16
|
1 /*
|
36
|
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.
|
16
|
6
|
36
|
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
|
16
|
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 #include "lzfu.h"
|
|
27
|
36
|
28 #define LZFU_COMPRESSED 0x75465a4c
|
|
29 #define LZFU_UNCOMPRESSED 0x414c454d
|
16
|
30
|
|
31 // initital dictionary
|
36
|
32 #define LZFU_INITDICT "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}" \
|
|
33 "{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscrip" \
|
|
34 "t \\fdecor MS Sans SerifSymbolArialTimes Ne" \
|
|
35 "w RomanCourier{\\colortbl\\red0\\green0\\blue0" \
|
|
36 "\r\n\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab" \
|
|
37 "\\tx"
|
16
|
38 // initial length of dictionary
|
|
39 #define LZFU_INITLENGTH 207
|
|
40
|
|
41 // header for compressed rtf
|
|
42 typedef struct _lzfuheader {
|
36
|
43 uint32_t cbSize;
|
|
44 uint32_t cbRawSize;
|
|
45 uint32_t dwMagic;
|
|
46 uint32_t dwCRC;
|
16
|
47 } lzfuheader;
|
|
48
|
|
49
|
36
|
50 /**
|
|
51 We always need to add 0x10 to the buffer offset because we need to skip past the header info
|
16
|
52 */
|
|
53
|
36
|
54 unsigned char* lzfu_decompress (unsigned char* rtfcomp, size_t *size) {
|
|
55 // the dictionary buffer
|
|
56 unsigned char dict[4096];
|
|
57 // the dictionary pointer
|
|
58 unsigned int dict_length=0;
|
|
59 // the header of the lzfu block
|
|
60 lzfuheader lzfuhdr;
|
|
61 // container for the data blocks
|
|
62 unsigned char flags;
|
|
63 // temp value for determining the bits in the flag
|
|
64 unsigned char flag_mask;
|
|
65 unsigned int i, in_size;
|
|
66 unsigned char *out_buf;
|
|
67 unsigned int out_ptr = 0;
|
16
|
68
|
36
|
69 memcpy(dict, LZFU_INITDICT, LZFU_INITLENGTH);
|
|
70 dict_length = LZFU_INITLENGTH;
|
|
71 memcpy(&lzfuhdr, rtfcomp, sizeof(lzfuhdr));
|
|
72 LE32_CPU(lzfuhdr.cbSize); LE32_CPU(lzfuhdr.cbRawSize);
|
|
73 LE32_CPU(lzfuhdr.dwMagic); LE32_CPU(lzfuhdr.dwCRC);
|
|
74 /* printf("total size: %d\n", lzfuhdr.cbSize+4);
|
|
75 printf("raw size : %d\n", lzfuhdr.cbRawSize);
|
|
76 printf("compressed: %s\n", (lzfuhdr.dwMagic == LZFU_COMPRESSED ? "yes" : "no"));
|
|
77 printf("CRC : %#x\n", lzfuhdr.dwCRC);
|
|
78 printf("\n");*/
|
|
79 out_buf = (unsigned char*)xmalloc(lzfuhdr.cbRawSize+20); //plus 4 cause we have 2x'}' and a \0
|
|
80 in_size = 0;
|
|
81 // we add plus one here cause when referencing an array, the index is always one less
|
|
82 // (ie, when accessing 2 element array, highest index is [1])
|
|
83 while (in_size+0x11 < lzfuhdr.cbSize) {
|
|
84 memcpy(&flags, &(rtfcomp[in_size+0x10]), 1);
|
|
85 in_size += 1;
|
16
|
86
|
36
|
87 flag_mask = 1;
|
|
88 while (flag_mask != 0 && in_size+0x11 < lzfuhdr.cbSize) {
|
|
89 if (flag_mask & flags) {
|
|
90 // read 2 bytes from input
|
|
91 unsigned short int blkhdr, offset, length;
|
|
92 memcpy(&blkhdr, &(rtfcomp[in_size+0x10]), 2);
|
|
93 LE16_CPU(blkhdr);
|
|
94 in_size += 2;
|
|
95 /* swap the upper and lower bytes of blkhdr */
|
|
96 blkhdr = (((blkhdr&0xFF00)>>8)+
|
|
97 ((blkhdr&0x00FF)<<8));
|
|
98 /* the offset is the first 24 bits of the 32 bit value */
|
|
99 offset = (blkhdr&0xFFF0)>>4;
|
|
100 /* the length of the dict entry are the last 8 bits */
|
|
101 length = (blkhdr&0x000F)+2;
|
|
102 // add the value we are about to print to the dictionary
|
|
103 for (i=0; i < length; i++) {
|
|
104 unsigned char c1;
|
|
105 c1 = dict[(offset+i)%4096];
|
|
106 dict[dict_length]=c1;
|
|
107 dict_length = (dict_length+1) % 4096;
|
|
108 out_buf[out_ptr++] = c1;
|
|
109 }
|
|
110 } else {
|
|
111 // uncompressed chunk (single byte)
|
|
112 char c1 = rtfcomp[in_size+0x10];
|
|
113 in_size ++;
|
|
114 dict[dict_length] = c1;
|
|
115 dict_length = (dict_length+1)%4096;
|
|
116 out_buf[out_ptr++] = c1;
|
|
117 }
|
|
118 flag_mask <<= 1;
|
|
119 }
|
16
|
120 }
|
36
|
121 // the compressed version doesn't appear to drop the closing braces onto the doc.
|
|
122 // we should do that
|
|
123 out_buf[out_ptr++] = '}';
|
|
124 out_buf[out_ptr++] = '}';
|
|
125 out_buf[out_ptr++] = '\0';
|
|
126 *size = out_ptr;
|
|
127 return out_buf;
|
16
|
128 }
|