Mercurial > libpst
comparison src/lzfu.c @ 16:c508ee15dfca
switch to automake/autoconf
author | carl |
---|---|
date | Sun, 19 Feb 2006 18:47:46 -0800 |
parents | |
children | 6fe121a971c9 |
comparison
equal
deleted
inserted
replaced
15:ac98f448b6ab | 16:c508ee15dfca |
---|---|
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 #include "lzfu.h" | |
27 | |
28 #define LZFU_COMPRESSED 0x75465a4c | |
29 #define LZFU_UNCOMPRESSED 0x414c454d | |
30 | |
31 // initital dictionary | |
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" | |
38 // initial length of dictionary | |
39 #define LZFU_INITLENGTH 207 | |
40 | |
41 // header for compressed rtf | |
42 typedef struct _lzfuheader { | |
43 uint32_t cbSize; | |
44 uint32_t cbRawSize; | |
45 uint32_t dwMagic; | |
46 uint32_t dwCRC; | |
47 } lzfuheader; | |
48 | |
49 | |
50 /** | |
51 We always need to add 0x10 to the buffer offset because we need to skip past the header info | |
52 */ | |
53 | |
54 unsigned char* lzfu_decompress (unsigned char* rtfcomp) { | |
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; | |
68 | |
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; | |
86 | |
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 } | |
120 } | |
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 return out_buf; | |
127 } |