'LibPst'
lzfu.c
Go to the documentation of this file.
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 
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 }
uint32_t cbSize
Definition: lzfu.c:31
char * pst_lzfu_decompress(char *rtfcomp, uint32_t compsize, size_t *size)
decompress lz compressed rtf data.
Definition: lzfu.c:38
#define LE32_CPU(x)
Definition: define.h:198
uint32_t cbRawSize
Definition: lzfu.c:32
void * pst_malloc(size_t size)
Definition: debug.c:169
#define LE16_CPU(x)
Definition: define.h:203
uint32_t dwMagic
Definition: lzfu.c:33
struct _lzfuheader lzfuheader
#define LZFU_INITDICT
Definition: lzfu.c:20
#define LZFU_INITLENGTH
Definition: lzfu.c:27
uint32_t dwCRC
Definition: lzfu.c:34