Mercurial > libpst
view src/lzfu.c @ 118:0f1492b7fe8b
patch from Fridrich Strba for building on mingw and general cleanup of autoconf files
add processing for pst files of type 0x0f
start adding support for properly building and installing libpst.so and the header files required to use it.
remove version.h since the version number is now in config.h
more const correctness issues regarding getopt()
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Sat, 31 Jan 2009 12:12:36 -0800 |
parents | 582e927756d3 |
children | 6395ced2b8b2 |
line wrap: on
line source
/* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include "define.h" #include "libpst.h" #include <sys/types.h> #include <string.h> #include <stdio.h> #include "lzfu.h" #define LZFU_COMPRESSED 0x75465a4c #define LZFU_UNCOMPRESSED 0x414c454d // initital dictionary #define LZFU_INITDICT "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}" \ "{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscrip" \ "t \\fdecor MS Sans SerifSymbolArialTimes Ne" \ "w RomanCourier{\\colortbl\\red0\\green0\\blue0" \ "\r\n\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab" \ "\\tx" // initial length of dictionary #define LZFU_INITLENGTH 207 // header for compressed rtf typedef struct _lzfuheader { uint32_t cbSize; uint32_t cbRawSize; uint32_t dwMagic; uint32_t dwCRC; } lzfuheader; char* lzfu_decompress(char* rtfcomp, uint32_t compsize, size_t *size) { unsigned char dict[4096]; // the dictionary buffer unsigned int dict_length = 0; // the dictionary pointer lzfuheader lzfuhdr; // the header of the lzfu block unsigned char flags; // 8 bits of flags (1=2byte block pointer into the dict, 0=1 byte literal) unsigned char flag_mask; // look at one flag bit each time thru the loop uint32_t i; char *out_buf; uint32_t out_ptr = 0; uint32_t out_size; uint32_t in_ptr; uint32_t in_size; memcpy(dict, LZFU_INITDICT, LZFU_INITLENGTH); memset(dict + LZFU_INITLENGTH, 0, sizeof(dict) - LZFU_INITLENGTH); dict_length = LZFU_INITLENGTH; memcpy(&lzfuhdr, rtfcomp, sizeof(lzfuhdr)); LE32_CPU(lzfuhdr.cbSize); LE32_CPU(lzfuhdr.cbRawSize); LE32_CPU(lzfuhdr.dwMagic); LE32_CPU(lzfuhdr.dwCRC); //printf("total size: %d\n", lzfuhdr.cbSize+4); //printf("raw size : %d\n", lzfuhdr.cbRawSize); //printf("compressed: %s\n", (lzfuhdr.dwMagic == LZFU_COMPRESSED ? "yes" : "no")); //printf("CRC : %#x\n", lzfuhdr.dwCRC); //printf("\n"); out_size = lzfuhdr.cbRawSize; out_buf = (char*)xmalloc(out_size); in_ptr = sizeof(lzfuhdr); // Make sure to correct lzfuhdr.cbSize with 4 bytes before comparing // to compsize in_size = (lzfuhdr.cbSize + 4 < compsize) ? lzfuhdr.cbSize + 4 : compsize; while (in_ptr < in_size) { flags = (unsigned char)(rtfcomp[in_ptr++]); flag_mask = 1; while (flag_mask) { if (flag_mask & flags) { // two bytes available? if (in_ptr+1 < in_size) { // read 2 bytes from input unsigned short int blkhdr, offset, length; memcpy(&blkhdr, rtfcomp+in_ptr, 2); LE16_CPU(blkhdr); in_ptr += 2; /* swap the upper and lower bytes of blkhdr */ blkhdr = (((blkhdr&0xFF00)>>8)+ ((blkhdr&0x00FF)<<8)); /* the offset is the first 12 bits of the 16 bit value */ offset = (blkhdr&0xFFF0)>>4; /* the length of the dict entry are the last 4 bits */ length = (blkhdr&0x000F)+2; // add the value we are about to print to the dictionary for (i=0; i < length; i++) { unsigned char c1; c1 = dict[(offset+i)%4096]; dict[dict_length] = c1; dict_length = (dict_length+1) % 4096; if (out_ptr < out_size) out_buf[out_ptr++] = (char)c1; // required for dictionary wrap around // otherwise 0 byte values are referenced incorrectly dict[dict_length] = 0; } } } else { // one byte available? if (in_ptr < in_size) { // uncompressed chunk (single byte) char c1 = rtfcomp[in_ptr++]; dict[dict_length] = c1; dict_length = (dict_length+1)%4096; if (out_ptr < out_size) out_buf[out_ptr++] = (char)c1; // required for dictionary wrap around // otherwise 0 byte values are referenced incorrect dict[dict_length] = 0; } } flag_mask <<= 1; } } *size = out_ptr; return out_buf; }