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 "lzfu.h"
14 
15 
16 #define LZFU_COMPRESSED 		0x75465a4c
17 #define LZFU_UNCOMPRESSED		0x414c454d
18 
19 // initital dictionary
20 #define LZFU_INITDICT	"{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}" \
21 						"{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscrip" \
22 						"t \\fdecor MS Sans SerifSymbolArialTimes Ne" \
23 						"w RomanCourier{\\colortbl\\red0\\green0\\blue0" \
24 						"\r\n\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab" \
25 						"\\tx"
26 // initial length of dictionary
27 #define LZFU_INITLENGTH 207
28 
29 // header for compressed rtf
30 typedef struct _lzfuheader {
31 	uint32_t cbSize;
32 	uint32_t cbRawSize;
33 	uint32_t dwMagic;
34 	uint32_t dwCRC;
35 } lzfuheader;
36 
37 
pst_lzfu_decompress(char * rtfcomp,uint32_t compsize,size_t * size)38 char* pst_lzfu_decompress(char* rtfcomp, uint32_t compsize, size_t *size) {
39 	unsigned char dict[4096];       // the dictionary buffer
40 	unsigned int dict_length = 0;   // the dictionary pointer
41 	lzfuheader lzfuhdr;             // the header of the lzfu block
42 	unsigned char flags;            // 8 bits of flags (1=2byte block pointer into the dict, 0=1 byte literal)
43 	unsigned char flag_mask;        // look at one flag bit each time through the loop
44 	uint32_t i;
45 	char    *out_buf;
46 	uint32_t out_ptr = 0;
47 	uint32_t out_size;
48 	uint32_t in_ptr;
49 	uint32_t in_size;
50 
51 	memcpy(dict, LZFU_INITDICT, LZFU_INITLENGTH);
52     memset(dict + LZFU_INITLENGTH, 0, sizeof(dict) - LZFU_INITLENGTH);
53 	dict_length = LZFU_INITLENGTH;
54 
55 	memcpy(&lzfuhdr, rtfcomp, sizeof(lzfuhdr));
56 	LE32_CPU(lzfuhdr.cbSize);
57 	LE32_CPU(lzfuhdr.cbRawSize);
58 	LE32_CPU(lzfuhdr.dwMagic);
59 	LE32_CPU(lzfuhdr.dwCRC);
60 	//printf("total size: %d\n", lzfuhdr.cbSize+4);
61 	//printf("raw size  : %d\n", lzfuhdr.cbRawSize);
62 	//printf("compressed: %s\n", (lzfuhdr.dwMagic == LZFU_COMPRESSED ? "yes" : "no"));
63 	//printf("CRC       : %#x\n", lzfuhdr.dwCRC);
64 	//printf("\n");
65 	out_size = lzfuhdr.cbRawSize;
66 	out_buf  = (char*)pst_malloc(out_size);
67 	in_ptr	 = sizeof(lzfuhdr);
68 	// Make sure to correct lzfuhdr.cbSize with 4 bytes before comparing
69 	// to compsize
70 	in_size  = (lzfuhdr.cbSize + 4 < compsize) ? lzfuhdr.cbSize + 4 : compsize;
71 	while (in_ptr < in_size) {
72 		flags = (unsigned char)(rtfcomp[in_ptr++]);
73 		flag_mask = 1;
74 		while (flag_mask) {
75 			if (flag_mask & flags) {
76 				// two bytes available?
77 				if (in_ptr+1 < in_size) {
78 					// read 2 bytes from input
79 					uint16_t blkhdr, offset, length;
80 					memcpy(&blkhdr, rtfcomp+in_ptr, 2);
81 					LE16_CPU(blkhdr);
82 					in_ptr += 2;
83 					/* swap the upper and lower bytes of blkhdr */
84 					blkhdr = (((blkhdr&0xFF00)>>8)+
85 							  ((blkhdr&0x00FF)<<8));
86 					/* the offset is the first 12 bits of the 16 bit value */
87 					offset = (blkhdr&0xFFF0)>>4;
88 					/* the length of the dict entry are the last 4 bits */
89 					length = (blkhdr&0x000F)+2;
90 					// add the value we are about to print to the dictionary
91 					for (i=0; i < length; i++) {
92 						unsigned char c1;
93 						c1 = dict[(offset+i)%4096];
94 						dict[dict_length] = c1;
95 						dict_length = (dict_length+1) % 4096;
96 						if (out_ptr < out_size) out_buf[out_ptr++] = (char)c1;
97 						// required for dictionary wrap around
98 						// otherwise 0 byte values are referenced incorrectly
99 						dict[dict_length] = 0;
100 					}
101 				}
102 			} else {
103 				// one byte available?
104 				if (in_ptr < in_size) {
105 					// uncompressed chunk (single byte)
106 					char c1 = rtfcomp[in_ptr++];
107 					dict[dict_length] = c1;
108 					dict_length = (dict_length+1)%4096;
109 					if (out_ptr < out_size) out_buf[out_ptr++] = (char)c1;
110 					// required for dictionary wrap around
111 					// otherwise 0 byte values are referenced incorrect
112 					dict[dict_length] = 0;
113 				}
114 			}
115 			flag_mask <<= 1;
116 		}
117 	}
118     *size = out_ptr;
119 	return out_buf;
120 }
121