lzfu.c
Go to the documentation of this file.00001  
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 #include "define.h"
00013 #include "lzfu.h"
00014 
00015 
00016 #define LZFU_COMPRESSED         0x75465a4c
00017 #define LZFU_UNCOMPRESSED       0x414c454d
00018 
00019 
00020 #define LZFU_INITDICT   "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}" \
00021                         "{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscrip" \
00022                         "t \\fdecor MS Sans SerifSymbolArialTimes Ne" \
00023                         "w RomanCourier{\\colortbl\\red0\\green0\\blue0" \
00024                         "\r\n\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab" \
00025                         "\\tx"
00026 
00027 #define LZFU_INITLENGTH 207
00028 
00029 
00030 typedef struct _lzfuheader {
00031     uint32_t cbSize;
00032     uint32_t cbRawSize;
00033     uint32_t dwMagic;
00034     uint32_t dwCRC;
00035 } lzfuheader;
00036 
00037 
00038 char* pst_lzfu_decompress(char* rtfcomp, uint32_t compsize, size_t *size) {
00039     unsigned char dict[4096];       
00040     unsigned int dict_length = 0;   
00041     lzfuheader lzfuhdr;             
00042     unsigned char flags;            
00043     unsigned char flag_mask;        
00044     uint32_t i;
00045     char    *out_buf;
00046     uint32_t out_ptr = 0;
00047     uint32_t out_size;
00048     uint32_t in_ptr;
00049     uint32_t in_size;
00050 
00051     memcpy(dict, LZFU_INITDICT, LZFU_INITLENGTH);
00052     memset(dict + LZFU_INITLENGTH, 0, sizeof(dict) - LZFU_INITLENGTH);
00053     dict_length = LZFU_INITLENGTH;
00054 
00055     memcpy(&lzfuhdr, rtfcomp, sizeof(lzfuhdr));
00056     LE32_CPU(lzfuhdr.cbSize);
00057     LE32_CPU(lzfuhdr.cbRawSize);
00058     LE32_CPU(lzfuhdr.dwMagic);
00059     LE32_CPU(lzfuhdr.dwCRC);
00060     
00061     
00062     
00063     
00064     
00065     out_size = lzfuhdr.cbRawSize;
00066     out_buf  = (char*)pst_malloc(out_size);
00067     in_ptr   = sizeof(lzfuhdr);
00068     
00069     
00070     in_size  = (lzfuhdr.cbSize + 4 < compsize) ? lzfuhdr.cbSize + 4 : compsize;
00071     while (in_ptr < in_size) {
00072         flags = (unsigned char)(rtfcomp[in_ptr++]);
00073         flag_mask = 1;
00074         while (flag_mask) {
00075             if (flag_mask & flags) {
00076                 
00077                 if (in_ptr+1 < in_size) {
00078                     
00079                     uint16_t blkhdr, offset, length;
00080                     memcpy(&blkhdr, rtfcomp+in_ptr, 2);
00081                     LE16_CPU(blkhdr);
00082                     in_ptr += 2;
00083                     
00084                     blkhdr = (((blkhdr&0xFF00)>>8)+
00085                               ((blkhdr&0x00FF)<<8));
00086                     
00087                     offset = (blkhdr&0xFFF0)>>4;
00088                     
00089                     length = (blkhdr&0x000F)+2;
00090                     
00091                     for (i=0; i < length; i++) {
00092                         unsigned char c1;
00093                         c1 = dict[(offset+i)%4096];
00094                         dict[dict_length] = c1;
00095                         dict_length = (dict_length+1) % 4096;
00096                         if (out_ptr < out_size) out_buf[out_ptr++] = (char)c1;
00097                         
00098                         
00099                         dict[dict_length] = 0;
00100                     }
00101                 }
00102             } else {
00103                 
00104                 if (in_ptr < in_size) {
00105                     
00106                     char c1 = rtfcomp[in_ptr++];
00107                     dict[dict_length] = c1;
00108                     dict_length = (dict_length+1)%4096;
00109                     if (out_ptr < out_size) out_buf[out_ptr++] = (char)c1;
00110                     
00111                     
00112                     dict[dict_length] = 0;
00113                 }
00114             }
00115             flag_mask <<= 1;
00116         }
00117     }
00118     *size = out_ptr;
00119     return out_buf;
00120 }