Main Page | Namespace List | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

lzfu.c

Go to the documentation of this file.
00001  /*
00002      This program is free software; you can redistribute it and/or modify
00003      it under the terms of the GNU General Public License as published by
00004      the Free Software Foundation; either version 2 of the License, or
00005      (at your option) any later version.
00006 
00007      You should have received a copy of the GNU General Public License
00008      along with this program; if not, write to the Free Software Foundation,
00009      Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
00010   */
00011 
00012 #include "define.h"
00013 #include "libpst.h"
00014 
00015 #include <sys/types.h>
00016 #include <string.h>
00017 #include <stdio.h>
00018 
00019 #include "lzfu.h"
00020 
00021 #define LZFU_COMPRESSED         0x75465a4c
00022 #define LZFU_UNCOMPRESSED       0x414c454d
00023 
00024 // initital dictionary
00025 #define LZFU_INITDICT   "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}" \
00026                         "{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscrip" \
00027                         "t \\fdecor MS Sans SerifSymbolArialTimes Ne" \
00028                         "w RomanCourier{\\colortbl\\red0\\green0\\blue0" \
00029                         "\r\n\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab" \
00030                         "\\tx"
00031 // initial length of dictionary
00032 #define LZFU_INITLENGTH 207
00033 
00034 // header for compressed rtf
00035 typedef struct _lzfuheader {
00036     uint32_t cbSize;
00037     uint32_t cbRawSize;
00038     uint32_t dwMagic;
00039     uint32_t dwCRC;
00040 } lzfuheader;
00041 
00042 
00043 char* lzfu_decompress(char* rtfcomp, uint32_t compsize, size_t *size) {
00044     unsigned char dict[4096];       // the dictionary buffer
00045     unsigned int dict_length = 0;   // the dictionary pointer
00046     lzfuheader lzfuhdr;             // the header of the lzfu block
00047     unsigned char flags;            // 8 bits of flags (1=2byte block pointer into the dict, 0=1 byte literal)
00048     unsigned char flag_mask;        // look at one flag bit each time thru the loop
00049     uint32_t i;
00050     char    *out_buf;
00051     uint32_t out_ptr  = 0;
00052     uint32_t out_size;
00053     uint32_t in_ptr;
00054     uint32_t in_size;
00055 
00056     memcpy(dict, LZFU_INITDICT, LZFU_INITLENGTH);
00057     memset(dict + LZFU_INITLENGTH, 0, sizeof(dict) - LZFU_INITLENGTH);
00058     dict_length = LZFU_INITLENGTH;
00059 
00060     memcpy(&lzfuhdr, rtfcomp, sizeof(lzfuhdr));
00061     LE32_CPU(lzfuhdr.cbSize);
00062     LE32_CPU(lzfuhdr.cbRawSize);
00063     LE32_CPU(lzfuhdr.dwMagic);
00064     LE32_CPU(lzfuhdr.dwCRC);
00065     //printf("total size: %d\n", lzfuhdr.cbSize+4);
00066     //printf("raw size  : %d\n", lzfuhdr.cbRawSize);
00067     //printf("compressed: %s\n", (lzfuhdr.dwMagic == LZFU_COMPRESSED ? "yes" : "no"));
00068     //printf("CRC       : %#x\n", lzfuhdr.dwCRC);
00069     //printf("\n");
00070     out_size = lzfuhdr.cbRawSize;
00071     out_buf  = (char*)xmalloc(out_size);
00072     in_ptr   = sizeof(lzfuhdr);
00073     // Make sure to correct lzfuhdr.cbSize with 4 bytes before comparing
00074     // to compsize
00075     in_size  = (lzfuhdr.cbSize + 4 < compsize) ? lzfuhdr.cbSize + 4 : compsize;
00076     while (in_ptr < in_size) {
00077         flags = (unsigned char)(rtfcomp[in_ptr++]);
00078         flag_mask = 1;
00079         while (flag_mask) {
00080             if (flag_mask & flags) {
00081                 // two bytes available?
00082                 if (in_ptr+1 < in_size) {
00083                     // read 2 bytes from input
00084                     unsigned short int blkhdr, offset, length;
00085                     memcpy(&blkhdr, rtfcomp+in_ptr, 2);
00086                     LE16_CPU(blkhdr);
00087                     in_ptr += 2;
00088                     /* swap the upper and lower bytes of blkhdr */
00089                     blkhdr = (((blkhdr&0xFF00)>>8)+
00090                               ((blkhdr&0x00FF)<<8));
00091                     /* the offset is the first 12 bits of the 16 bit value */
00092                     offset = (blkhdr&0xFFF0)>>4;
00093                     /* the length of the dict entry are the last 4 bits */
00094                     length = (blkhdr&0x000F)+2;
00095                     // add the value we are about to print to the dictionary
00096                     for (i=0; i < length; i++) {
00097                         unsigned char c1;
00098                         c1 = dict[(offset+i)%4096];
00099                         dict[dict_length] = c1;
00100                         dict_length = (dict_length+1) % 4096;
00101                         if (out_ptr < out_size) out_buf[out_ptr++] = (char)c1;
00102                         // required for dictionary wrap around
00103                         // otherwise 0 byte values are referenced incorrectly
00104                         dict[dict_length] = 0;
00105                     }
00106                 }
00107             } else {
00108                 // one byte available?
00109                 if (in_ptr < in_size) {
00110                     // uncompressed chunk (single byte)
00111                     char c1 = rtfcomp[in_ptr++];
00112                     dict[dict_length] = c1;
00113                     dict_length = (dict_length+1)%4096;
00114                     if (out_ptr < out_size) out_buf[out_ptr++] = (char)c1;
00115                     // required for dictionary wrap around
00116                     // otherwise 0 byte values are referenced incorrect
00117                     dict[dict_length] = 0;
00118                 }
00119             }
00120             flag_mask <<= 1;
00121         }
00122     }
00123     *size = out_ptr;
00124     return out_buf;
00125 }

Generated on Tue Aug 5 12:06:14 2008 for 'LibPst' by  doxygen 1.3.9.1