[evolution-ews] Read the extra_length bits which is added in lzxd version. Update the position slots. Set the window



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]