summaryrefslogtreecommitdiffstats
path: root/ktnef/lib/lzfu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ktnef/lib/lzfu.cpp')
-rw-r--r--ktnef/lib/lzfu.cpp178
1 files changed, 178 insertions, 0 deletions
diff --git a/ktnef/lib/lzfu.cpp b/ktnef/lib/lzfu.cpp
new file mode 100644
index 00000000..ab4fa36a
--- /dev/null
+++ b/ktnef/lib/lzfu.cpp
@@ -0,0 +1,178 @@
+/*
+ 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;
+}