Mercurial > libpst
comparison lzfu.c @ 0:6b1b602514db libpst_0_5
Initial revision
author | carl |
---|---|
date | Fri, 09 Jul 2004 07:26:16 -0700 |
parents | |
children | 43e8802f08c5 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:6b1b602514db |
---|---|
1 /* | |
2 This program is free software; you can redistribute it and/or modify | |
3 it under the terms of the GNU General Public License as published by | |
4 the Free Software Foundation; either version 2 of the License, or | |
5 (at your option) any later version. | |
6 | |
7 You should have received a copy of the GNU General Public License | |
8 along with this program; if not, write to the Free Software Foundation, | |
9 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | |
10 */ | |
11 | |
12 #include "define.h" | |
13 #include "libpst.h" | |
14 #include <sys/types.h> | |
15 #include <string.h> | |
16 #include <stdio.h> | |
17 | |
18 #ifndef _MSC_VER | |
19 #include <stdint.h> | |
20 #endif | |
21 | |
22 #ifdef _MSC_VER | |
23 #define uint32_t unsigned int | |
24 #endif | |
25 | |
26 #define LZFU_COMPRESSED 0x75465a4c | |
27 #define LZFU_UNCOMPRESSED 0x414c454d | |
28 | |
29 // initital dictionary | |
30 #define LZFU_INITDICT "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}" \ | |
31 "{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscrip" \ | |
32 "t \\fdecor MS Sans SerifSymbolArialTimes Ne" \ | |
33 "w RomanCourier{\\colortbl\\red0\\green0\\blue0" \ | |
34 "\r\n\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab" \ | |
35 "\\tx" | |
36 // initial length of dictionary | |
37 #define LZFU_INITLENGTH 207 | |
38 | |
39 // header for compressed rtf | |
40 typedef struct _lzfuheader { | |
41 uint32_t cbSize; | |
42 uint32_t cbRawSize; | |
43 uint32_t dwMagic; | |
44 uint32_t dwCRC; | |
45 } lzfuheader; | |
46 | |
47 | |
48 /** | |
49 We always need to add 0x10 to the buffer offset because we need to skip past the header info | |
50 */ | |
51 | |
52 unsigned char* lzfu_decompress (unsigned char* rtfcomp) { | |
53 // the dictionary buffer | |
54 unsigned char dict[4096]; | |
55 // the dictionary pointer | |
56 unsigned int dict_length=0; | |
57 // the header of the lzfu block | |
58 lzfuheader lzfuhdr; | |
59 // container for the data blocks | |
60 unsigned char flags; | |
61 // temp value for determining the bits in the flag | |
62 unsigned char flag_mask; | |
63 unsigned int i, in_size; | |
64 unsigned char *out_buf; | |
65 unsigned int out_ptr = 0; | |
66 | |
67 memcpy(dict, LZFU_INITDICT, LZFU_INITLENGTH); | |
68 dict_length = LZFU_INITLENGTH; | |
69 memcpy(&lzfuhdr, rtfcomp, sizeof(lzfuhdr)); | |
70 LE32_CPU(lzfuhdr.cbSize); LE32_CPU(lzfuhdr.cbRawSize); | |
71 LE32_CPU(lzfuhdr.dwMagic); LE32_CPU(lzfuhdr.dwCRC); | |
72 /* printf("total size: %d\n", lzfuhdr.cbSize+4); | |
73 printf("raw size : %d\n", lzfuhdr.cbRawSize); | |
74 printf("compressed: %s\n", (lzfuhdr.dwMagic == LZFU_COMPRESSED ? "yes" : "no")); | |
75 printf("CRC : %#x\n", lzfuhdr.dwCRC); | |
76 printf("\n");*/ | |
77 out_buf = (unsigned char*)xmalloc(lzfuhdr.cbRawSize+20); //plus 4 cause we have 2x'}' and a \0 | |
78 in_size = 0; | |
79 // we add plus one here cause when referencing an array, the index is always one less | |
80 // (ie, when accessing 2 element array, highest index is [1]) | |
81 while (in_size+0x11 < lzfuhdr.cbSize) { | |
82 memcpy(&flags, &(rtfcomp[in_size+0x10]), 1); | |
83 in_size += 1; | |
84 | |
85 flag_mask = 1; | |
86 while (flag_mask != 0 && in_size+0x11 < lzfuhdr.cbSize) { | |
87 if (flag_mask & flags) { | |
88 // read 2 bytes from input | |
89 unsigned short int blkhdr, offset, length; | |
90 memcpy(&blkhdr, &(rtfcomp[in_size+0x10]), 2); | |
91 LE16_CPU(blkhdr); | |
92 in_size += 2; | |
93 /* swap the upper and lower bytes of blkhdr */ | |
94 blkhdr = (((blkhdr&0xFF00)>>8)+ | |
95 ((blkhdr&0x00FF)<<8)); | |
96 /* the offset is the first 24 bits of the 32 bit value */ | |
97 offset = (blkhdr&0xFFF0)>>4; | |
98 /* the length of the dict entry are the last 8 bits */ | |
99 length = (blkhdr&0x000F)+2; | |
100 // add the value we are about to print to the dictionary | |
101 for (i=0; i < length; i++) { | |
102 unsigned char c1; | |
103 c1 = dict[(offset+i)%4096]; | |
104 dict[dict_length]=c1; | |
105 dict_length = (dict_length+1) % 4096; | |
106 out_buf[out_ptr++] = c1; | |
107 } | |
108 } else { | |
109 // uncompressed chunk (single byte) | |
110 char c1 = rtfcomp[in_size+0x10]; | |
111 in_size ++; | |
112 dict[dict_length] = c1; | |
113 dict_length = (dict_length+1)%4096; | |
114 out_buf[out_ptr++] = c1; | |
115 } | |
116 flag_mask <<= 1; | |
117 } | |
118 } | |
119 // the compressed version doesn't appear to drop the closing braces onto the doc. | |
120 // we should do that | |
121 out_buf[out_ptr++] = '}'; | |
122 out_buf[out_ptr++] = '}'; | |
123 out_buf[out_ptr++] = '\0'; | |
124 return out_buf; | |
125 } |