KTnef

lzfu.cpp
Go to the documentation of this file.
1/*
2 lzfu.cpp
3
4 SPDX-FileCopyrightText: 2003 Michael Goffioul <kdeprint@swing.be>
5
6 This file is part of KTNEF, the KDE TNEF support library/program.
7
8 SPDX-License-Identifier: LGPL-2.0-or-later
9 */
10/**
11 * @file
12 * This file is part of the API for handling TNEF data and
13 * provides the @acronym LZFU decompression functionality.
14 *
15 * @author Michael Goffioul
16 */
17
18#include "lzfu.h"
19
20#include <QIODevice>
21
22#include <cstdio>
23#include <cstring>
24#include <sys/types.h>
25
26//#define DO_DEBUG
27
28//@cond IGNORE
29#define LZFU_COMPRESSED 0x75465a4c
30#define LZFU_UNCOMPRESSED 0x414c454d
31
32#define LZFU_INITDICT \
33 "{\\rtf1\\ansi\\mac\\deff0\\deftab720{\\fonttbl;}" \
34 "{\\f0\\fnil \\froman \\fswiss \\fmodern \\fscrip" \
35 "t \\fdecor MS Sans SerifSymbolArialTimes Ne" \
36 "w RomanCourier{\\colortbl\\red0\\green0\\blue0" \
37 "\r\n\\par \\pard\\plain\\f0\\fs20\\b\\i\\u\\tab" \
38 "\\tx"
39#define LZFU_INITLENGTH 207
40//@endcond
41
42//@cond PRIVATE
43using lzfuheader = struct _lzfuheader {
44 quint32 cbSize;
45 quint32 cbRawSize;
46 quint32 dwMagic;
47 quint32 dwCRC;
48};
49//@endcond
50
51//@cond IGNORE
52#define FLAG(f, n) (f >> n) & 0x1
53
54/*typedef struct _blockheader {
55 unsigned int offset:12;
56 unsigned int length:4;
57 } blockheader;*/
58
59#define OFFSET(b) (b >> 4) & 0xFFF
60#define LENGTH(b) ((b & 0xF) + 2)
61//@endcond
62
64{
65 unsigned char window[4096];
66 unsigned int wlength = 0;
67 unsigned int cursor = 0;
68 unsigned int ocursor = 0;
69 lzfuheader lzfuhdr;
70 // blockheader blkhdr;
71 quint16 blkhdr;
72 char bFlags;
73 int nFlags;
74
75 memcpy(window, LZFU_INITDICT, LZFU_INITLENGTH);
76 wlength = LZFU_INITLENGTH;
77 if (input->read((char *)&lzfuhdr, sizeof(lzfuhdr)) != sizeof(lzfuhdr)) {
78 fprintf(stderr, "unexpected eof, cannot read LZFU header\n");
79 return -1;
80 }
81 cursor += sizeof(lzfuhdr);
82#ifdef DO_DEBUG
83 fprintf(stdout, "total size : %d\n", lzfuhdr.cbSize + 4);
84 fprintf(stdout, "raw size : %d\n", lzfuhdr.cbRawSize);
85 fprintf(stdout, "compressed : %s\n", (lzfuhdr.dwMagic == LZFU_COMPRESSED ? "yes" : "no"));
86 fprintf(stdout, "CRC : %x\n", lzfuhdr.dwCRC);
87 fprintf(stdout, "\n");
88#endif
89
90 while (cursor < lzfuhdr.cbSize + 4 && ocursor < lzfuhdr.cbRawSize && !input->atEnd()) {
91 if (input->read(&bFlags, 1) != 1) {
92 fprintf(stderr, "unexpected eof, cannot read chunk flag\n");
93 return -1;
94 }
95 nFlags = 8;
96 cursor++;
97#ifdef DO_DEBUG
98 fprintf(stdout, "Flags : ");
99 for (int i = nFlags - 1; i >= 0; i--) {
100 fprintf(stdout, "%d", FLAG(bFlags, i));
101 }
102 fprintf(stdout, "\n");
103#endif
104 for (int i = 0; i < nFlags && ocursor < lzfuhdr.cbRawSize && cursor < lzfuhdr.cbSize + 4; i++) {
105 if (FLAG(bFlags, i)) {
106 // compressed chunk
107 char c1;
108 char c2;
109 if (input->read(&c1, 1) != 1 || input->read(&c2, 1) != 1) {
110 fprintf(stderr, "unexpected eof, cannot read block header\n");
111 return -1;
112 }
113 blkhdr = c1;
114 blkhdr <<= 8;
115 blkhdr |= (0xFF & c2);
116 unsigned int offset = OFFSET(blkhdr);
117 unsigned int length = LENGTH(blkhdr);
118 cursor += 2;
119#ifdef DO_DEBUG
120 fprintf(stdout, "block : offset=%.4d [%d], length=%.2d (0x%04X)\n", OFFSET(blkhdr), wlength, LENGTH(blkhdr), blkhdr);
121#endif
122 // if ( offset >= wlength ) {
123 // break;
124 //}
125#ifdef DO_DEBUG
126 fprintf(stdout, "block : ");
127#endif
128 for (unsigned int i = 0; i < length; i++) {
129 c1 = window[(offset + i) % 4096];
130 // if ( wlength < 4096 ) {
131 window[wlength] = c1;
132 wlength = (wlength + 1) % 4096;
133 //}
134#ifdef DO_DEBUG
135 if (c1 == '\n') {
136 fprintf(stdout, "\nblock : ");
137 } else {
138 fprintf(stdout, "%c", c1);
139 }
140#endif
141 output->putChar(c1);
142 ocursor++;
143 }
144#ifdef DO_DEBUG
145 fprintf(stdout, "\n");
146#endif
147 } else {
148 // uncompressed chunk (char)
149 char c;
150 if (!input->getChar(&c)) {
151 if (!input->atEnd()) {
152 fprintf(stderr, "unexpected eof, cannot read character\n");
153 return -1;
154 }
155 break;
156 }
157#ifdef DO_DEBUG
158 fprintf(stdout, "char : %c\n", c);
159#endif
160 cursor++;
161 // if ( wlength < 4096 ) {
162 window[wlength] = c;
163 wlength = (wlength + 1) % 4096;
164 //}
165 output->putChar(c);
166 ocursor++;
167 }
168 }
169 }
170
171 return 0;
172}
This file is part of the API for handling TNEF data and provides the LZFU decompression functionality...
int lzfu_decompress(QIODevice *input, QIODevice *output)
LZFU decompress data in compressed Rich Text Format (RTF).
Definition lzfu.cpp:63
virtual bool atEnd() const const
bool getChar(char *c)
bool putChar(char c)
QByteArray read(qint64 maxSize)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:16:42 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.