[evolution-ews] Read the extra_length bits which is added in lzxd version. Update the position slots. Set the window
- From: Chenthill Palanisamy <pchen src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-ews] Read the extra_length bits which is added in lzxd version. Update the position slots. Set the window
- Date: Sun, 10 Jul 2011 14:27:23 +0000 (UTC)
commit 4a6a1e4c5551c0221f1eaa2d336901baedcdff9f
Author: Chenthill Palanisamy <pchenthill novell com>
Date: Sun Jul 10 16:37:58 2011 +0530
Read the extra_length bits which is added in lzxd version.
Update the position slots.
Set the window bits in lzxd_init properly.
Read the crc element from the lzx block header.
These fix the decoding of bigger oab files with multiple blocks and chunks.
src/addressbook/lzx/ews-oal-decompress.c | 56 ++++++++++++++++--
src/addressbook/lzx/lzxd.c | 91 +++++++++++++++++++++++++----
2 files changed, 127 insertions(+), 20 deletions(-)
---
diff --git a/src/addressbook/lzx/ews-oal-decompress.c b/src/addressbook/lzx/ews-oal-decompress.c
index 3cd0f66..60f13d5 100644
--- a/src/addressbook/lzx/ews-oal-decompress.c
+++ b/src/addressbook/lzx/ews-oal-decompress.c
@@ -25,6 +25,7 @@
#include <stdio.h>
#include <unistd.h>
#include <glib.h>
+#include <glib/gstdio.h>
#include "lzx.h"
#include "ews-oal-decompress.h"
@@ -49,6 +50,7 @@ typedef struct {
guint32 flags;
guint32 comp_size;
guint32 ucomp_size;
+ guint32 crc;
} LzxBlockHeader;
static gboolean
@@ -123,6 +125,8 @@ read_block_header (FILE *input, GError **error)
success = read_uint32 (input, &lzx_b->ucomp_size);
if (!success)
goto exit;
+
+ success = read_uint32 (input, &lzx_b->crc);
exit:
if (!success) {
@@ -148,27 +152,37 @@ oal_decompress_v4_full_detail_file (const gchar *filename, const gchar *output_f
input = fopen (filename, "rb");
if (!input) {
g_set_error_literal (&err, g_quark_from_string ("lzx"), 1, "unable to open the input file");
+ ret = FALSE;
goto exit;
}
output = fopen (output_filename, "wb");
if (!input) {
g_set_error_literal (&err, g_quark_from_string ("lzx"), 1, "unable to open the output file");
+ ret = FALSE;
goto exit;
}
lzx_h = read_headers (input, &err);
- if (!lzx_h)
+ if (!lzx_h) {
+ ret = FALSE;
goto exit;
+ }
/* TODO decompressing multiple lzx_blocks has not been tested yet. Will need to get a setup and test it. */
do {
LzxBlockHeader *lzx_b;
struct lzxd_stream *lzs;
+ goffset offset;
lzx_b = read_block_header (input, &err);
- if (err)
+ if (err) {
+ ret = FALSE;
goto exit;
+ }
+
+ /* note the file offset */
+ offset = ftell (input);
/* lzx_b points to 1, write it directly to file */
if (lzx_b->flags == 0) {
@@ -178,31 +192,58 @@ oal_decompress_v4_full_detail_file (const gchar *filename, const gchar *output_f
fwrite (buffer, 1, lzx_b->ucomp_size, output) == lzx_b->ucomp_size)) {
g_set_error_literal (&err, g_quark_from_string ("lzx"), 1, "failed to write data in output file");
g_free (buffer);
+ ret = FALSE;
goto exit;
}
g_free (buffer);
} else {
+ /* round to multiples of 32768 */
+ guint round = (lzx_b->ucomp_size % 32768) + lzx_b->ucomp_size;
+ gint set = g_bit_nth_lsf ((round >> 17), -1);
+ guint window_bits = set + 17;
+
+ if (set > 8)
+ window_bits = 25;
+ else if (set == -1)
+ window_bits = 17;
+ else
+ window_bits = set + 17;
+
+ if (window_bits > 25)
+ window_bits = 25;
+
+ lzs = lzxd_init (input, output, window_bits, 0, 16, lzx_b->ucomp_size);
- lzs = lzxd_init (input, output, 17, 0, 16, lzx_b->ucomp_size);
if (lzxd_decompress (lzs, lzs->length) != LZX_ERR_OK) {
g_set_error_literal (&err, g_quark_from_string ("lzx"), 1, "decompression failed");
- /* set err */
+ ret = FALSE;
goto exit;
}
}
+
+ /* Set the fp to beggining of next block. This is a HACK, looks like decompress reads beyond the block.
+ Since we can identify the next block start from block header, we just reset the offset */
+ offset += lzx_b->comp_size;
+ fseek (input, offset, SEEK_SET);
+
total_decomp_size += lzx_b->ucomp_size;
g_free (lzx_b);
} while (total_decomp_size < lzx_h->target_size);
exit:
+ if (input)
+ fclose (input);
+
+ if (output)
+ fclose (output);
+
if (err) {
ret = FALSE;
g_propagate_error (error, err);
+ g_unlink (output_filename);
}
- fclose (input);
- fclose (output);
g_free (lzx_h);
return ret;
@@ -216,6 +257,7 @@ main (int argc, char *argv [])
g_print ("Pass an lzx file and an output filename as argument \n");
return;
}
+
g_type_init ();
g_thread_init (NULL);
@@ -225,4 +267,4 @@ main (int argc, char *argv [])
g_print ("decompression failed \n");
return 0;
-} */
+} */
diff --git a/src/addressbook/lzx/lzxd.c b/src/addressbook/lzx/lzxd.c
index 9bf2db7..e32ba31 100644
--- a/src/addressbook/lzx/lzxd.c
+++ b/src/addressbook/lzx/lzxd.c
@@ -211,6 +211,7 @@ static void lzxd_reset_state(struct lzxd_stream *lzx) {
}
/*-------- main LZX code --------*/
+static int pos_slots[9] = {34, 36, 38, 42, 50, 66, 98, 162, 290};
struct lzxd_stream *lzxd_init(FILE *input,
FILE *output,
@@ -222,8 +223,8 @@ struct lzxd_stream *lzxd_init(FILE *input,
unsigned int window_size = 1 << window_bits;
struct lzxd_stream *lzx;
- /* LZX supports window sizes of 2^15 (32Kb) through 2^21 (2Mb) */
- if (window_bits < 15 || window_bits > 21) return NULL;
+ /* LZX supports window sizes of 2^17 (128Kb) through 2^25 (32Mb) */
+ if (window_bits < 17 || window_bits > 26) return NULL;
input_buffer_size = (input_buffer_size + 1) & -2;
if (!input_buffer_size) return NULL;
@@ -260,10 +261,9 @@ struct lzxd_stream *lzxd_init(FILE *input,
lzx->intel_started = 0;
lzx->error = LZX_ERR_OK;
- /* window bits: 15 16 17 18 19 20 21
- * position slots: 30 32 34 36 38 42 50 */
- lzx->posn_slots = ((window_bits == 21) ? 50 :
- ((window_bits == 20) ? 42 : (window_bits << 1)));
+ /* window bits: 17 18 19 20 21 22 23 24 25
+ * position slots: 34 36 38 42 50 66 98 162 290 */
+ lzx->posn_slots = pos_slots[window_bits-17];
lzx->o_ptr = lzx->o_end = &lzx->e8_buf[0];
lzxd_reset_state(lzx);
@@ -316,6 +316,8 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
end_frame = (unsigned int)((lzx->offset + out_bytes) / LZX_FRAME_SIZE) + 1;
while (lzx->frame < end_frame) {
+ int chunk_size;
+
/* have we reached the reset interval? (if there is one?) */
if (lzx->reset_interval && ((lzx->frame % lzx->reset_interval) == 0)) {
if (lzx->block_remaining) {
@@ -331,8 +333,8 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
}
/* LZXD format has the chunk_size. not present in lzx format */
- READ_BITS (i, 16);
- D(("chunk size is %d \n", i))
+ READ_BITS (chunk_size, 16);
+ D(("chunk size is %d \n", chunk_size))
/* read header if necessary */
if (!lzx->header_read) {
@@ -368,7 +370,7 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
READ_BITS(lzx->block_type, 3);
READ_BITS(i, 16); READ_BITS(j, 8);
lzx->block_remaining = lzx->block_length = (i << 8) | j;
- /*D(("new block t%d len %u", lzx->block_type, lzx->block_length))*/
+ D(("new block type %d len %u", lzx->block_type, lzx->block_length))
/* read individual block headers */
switch (lzx->block_type) {
@@ -434,6 +436,8 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
this_run--;
}
else {
+ int bit = 0, extra_len = 0;
+
/* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
main_element -= LZX_NUM_CHARS;
@@ -459,10 +463,41 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
}
if ((window_posn + match_length) > lzx->window_size) {
- D(("match ran over window wrap"))
+ D(("match ran over window wrap %lu %d ", ftell (lzx->input), match_length))
+ lzx->o_ptr = &lzx->window[lzx->frame_posn];
return lzx->error = LZX_ERR_DECRUNCH;
}
-
+
+ /* check for extra len */
+ if (match_length == 257) {
+ READ_BITS (bit, 1);
+ if (bit) {
+ bit = 0;
+ READ_BITS (bit, 1);
+ if (bit) {
+ bit = 0;
+ READ_BITS (bit, 1);
+ if (bit) {
+ /* 111 */
+ READ_BITS (extra_len, 15);
+ } else {
+ /* 110 */
+ READ_BITS (extra_len, 12);
+ extra_len += 256 + 1024;
+ }
+ } else {
+ /* 10 */
+ READ_BITS (extra_len, 10);
+ extra_len += 256;
+ }
+ } else {
+ /* 0 */
+ READ_BITS (extra_len, 8);
+ }
+ }
+
+ match_length += extra_len;
+
/* copy match */
rundest = &window[window_posn];
i = match_length;
@@ -486,10 +521,10 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
runsrc = rundest - match_offset;
while (i-- > 0) *rundest++ = *runsrc++;
}
-
this_run -= match_length;
window_posn += match_length;
}
+
} /* while (this_run > 0) */
break;
@@ -502,6 +537,8 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
this_run--;
}
else {
+ int bit = 0, extra_len = 0;
+
/* match: LZX_NUM_CHARS + ((slot<<3) | length_header (3 bits)) */
main_element -= LZX_NUM_CHARS;
@@ -551,6 +588,34 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
D(("match ran over window wrap"))
return lzx->error = LZX_ERR_DECRUNCH;
}
+
+ /* check for extra len */
+ if (match_length == 257) {
+ READ_BITS (bit, 1);
+ if (bit) {
+ bit = 0;
+ READ_BITS (bit, 1);
+ if (bit) {
+ bit = 0;
+ READ_BITS (bit, 1);
+ if (bit) {
+ /* 111 */
+ READ_BITS (extra_len, 15);
+ } else {
+ /* 110 */
+ READ_BITS (extra_len, 12);
+ extra_len += 256 + 1024;
+ }
+ } else {
+ /* 10 */
+ READ_BITS (extra_len, 10);
+ extra_len += 256;
+ }
+ } else {
+ /* 0 */
+ READ_BITS (extra_len, 8);
+ }
+ }
/* copy match */
rundest = &window[window_posn];
@@ -629,7 +694,7 @@ int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
/* check that we've used all of the previous frame first */
if (lzx->o_ptr != lzx->o_end) {
- D(("%ld avail bytes, new %d frame", (long int)(lzx->o_end-lzx->o_ptr), frame_size))
+ D(("%d avail bytes, new %d frame", lzx->o_end-lzx->o_ptr, frame_size))
return lzx->error = LZX_ERR_DECRUNCH;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]