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 }