You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdepim/ktnef/lib/lzfu.cpp

179 lines
4.3 KiB

/*
lzfu.cpp
Copyright (C) 2003 Michael Goffioul <kdeprint@swing.be>
This file is part of KTNEF, the KDE TNEF support library/program.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include "lzfu.h"
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <sys/types.h>
#include <string.h>
#include <qiodevice.h>
#include <stdio.h>
//#define DO_DEBUG
#define LZFU_COMPRESSED 0x75465a4c
#define LZFU_UNCOMPRESSED 0x414c454d
#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"
#define LZFU_INITLENGTH 207
typedef struct _lzfuheader {
uint32_t cbSize;
uint32_t cbRawSize;
uint32_t dwMagic;
uint32_t dwCRC;
} lzfuheader;
#define FLAG(f,n) (f>>n)&0x1
/*typedef struct _blockheader {
unsigned int offset:12;
unsigned int length:4;
} blockheader;*/
#define OFFSET(b) (b>>4)&0xFFF
#define LENGTH(b) ((b&0xF)+2)
int lzfu_decompress(QIODevice *input, QIODevice *output)
{
unsigned char window[4096];
unsigned int wlength = 0, cursor = 0, ocursor = 0;
lzfuheader lzfuhdr;
//blockheader blkhdr;
uint16_t blkhdr;
char bFlags;
int nFlags;
memcpy(window, LZFU_INITDICT, LZFU_INITLENGTH);
wlength = LZFU_INITLENGTH;
if (input->readBlock((char*)&lzfuhdr, sizeof(lzfuhdr)) != sizeof(lzfuhdr))
{
fprintf(stderr, "unexpected eof, cannot read LZFU header\n");
return -1;
}
cursor += sizeof( lzfuhdr );
#ifdef DO_DEBUG
fprintf(stdout, "total size : %d\n", lzfuhdr.cbSize+4);
fprintf(stdout, "raw size : %d\n", lzfuhdr.cbRawSize);
fprintf(stdout, "compressed : %s\n", (lzfuhdr.dwMagic == LZFU_COMPRESSED ? "yes" : "no"));
fprintf(stdout, "CRC : %x\n", lzfuhdr.dwCRC);
fprintf(stdout, "\n");
#endif
while (cursor < lzfuhdr.cbSize+4 && ocursor < lzfuhdr.cbRawSize && !input->atEnd())
{
if (input->readBlock(&bFlags, 1) != 1)
{
fprintf(stderr, "unexpected eof, cannot read chunk flag\n");
return -1;
}
nFlags = 8;
cursor++;
#ifdef DO_DEBUG
fprintf(stdout, "Flags : ");
for (int i=nFlags-1; i>=0; i--)
fprintf(stdout, "%d", FLAG(bFlags, i));
fprintf(stdout, "\n");
#endif
for (int i=0; i<nFlags && ocursor<lzfuhdr.cbRawSize && cursor<lzfuhdr.cbSize+4; i++)
{
if (FLAG(bFlags, i))
{
// compressed chunck
char c1, c2;
if (input->readBlock(&c1, 1) != 1 || input->readBlock(&c2, 1) != 1)
{
fprintf(stderr, "unexpected eof, cannot read block header\n");
return -1;
}
blkhdr = c1;
blkhdr <<= 8;
blkhdr |= (0xFF&c2);
unsigned int offset = OFFSET(blkhdr), length = LENGTH(blkhdr);
cursor += 2;
#ifdef DO_DEBUG
fprintf( stdout, "block : offset=%.4d [%d], length=%.2d (0x%04X)\n", OFFSET( blkhdr ), wlength, LENGTH( blkhdr ), blkhdr );
#endif
//if (offset >= wlength)
//{
// break;
//}
#ifdef DO_DEBUG
fprintf( stdout, "block : " );
#endif
for (unsigned int i=0; i<length; i++)
{
c1 = window[( offset+i ) % 4096];
//if (wlength < 4096)
//{
window[wlength] = c1;
wlength = ( wlength+1 ) % 4096;
//}
#ifdef DO_DEBUG
if ( c1 == '\n' )
fprintf( stdout, "\nblock : " );
else
fprintf( stdout, "%c", c1 );
#endif
output->putch(c1);
ocursor++;
}
#ifdef DO_DEBUG
fprintf( stdout, "\n" );
#endif
}
else
{
// uncompressed chunk (char)
signed char c = (char)input->getch();
if (c == -1)
{
if (!input->atEnd())
{
fprintf(stderr, "unexpected eof, cannot read character\n");
return -1;
}
break;
}
#ifdef DO_DEBUG
fprintf( stdout, "char : %c\n", c );
#endif
cursor++;
//if (wlength < 4096)
//{
window[wlength] = c;
wlength = ( wlength+1 ) % 4096;
//}
output->putch(c);
ocursor++;
}
}
}
return 0;
}