~valavanisalex/ubuntu/precise/inkscape/fix-943984

« back to all changes in this revision

Viewing changes to inkscape-0.47pre1/src/io/gzipstream.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2009-07-02 17:09:45 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702170945-nn6d6zswovbwju1t
Tags: 0.47~pre1-0ubuntu1
* New upstream release.
  - Don't constrain maximization on small resolution devices (pre0)
    (LP: #348842)
  - Fixes segfault on startup (pre0)
    (LP: #391149)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * Zlib-enabled input and output streams
 
3
 *
 
4
 * This is a thin wrapper of libz calls, in order
 
5
 * to provide a simple interface to our developers
 
6
 * for gzip input and output.
 
7
 *
 
8
 * Authors:
 
9
 *   Bob Jamison <rjamison@titan.com>
 
10
 *
 
11
 * Copyright (C) 2004 Inkscape.org
 
12
 *
 
13
 * Released under GNU GPL, read the file 'COPYING' for more information
 
14
 */
 
15
 
 
16
#include "gzipstream.h"
 
17
#include <cstdio>
 
18
#include <cstring>
 
19
#include <string>
 
20
 
 
21
namespace Inkscape
 
22
{
 
23
namespace IO
 
24
{
 
25
 
 
26
//#########################################################################
 
27
//# G Z I P    I N P U T    S T R E A M
 
28
//#########################################################################
 
29
 
 
30
#define OUT_SIZE 4000
 
31
 
 
32
/**
 
33
 *
 
34
 */ 
 
35
GzipInputStream::GzipInputStream(InputStream &sourceStream)
 
36
                    : BasicInputStream(sourceStream),
 
37
                      loaded(false),
 
38
                      totalIn(0),
 
39
                      totalOut(0),
 
40
                      outputBuf(NULL),
 
41
                      crc(0),
 
42
                      srcCrc(0),
 
43
                      srcSiz(0),
 
44
                      srcConsumed(0),
 
45
                      srcLen(0),
 
46
                      outputBufPos(0),
 
47
                      outputBufLen(0)
 
48
{
 
49
    memset( &d_stream, 0, sizeof(d_stream) );
 
50
}
 
51
 
 
52
/**
 
53
 *
 
54
 */ 
 
55
GzipInputStream::~GzipInputStream()
 
56
{
 
57
    close();
 
58
    if ( srcBuf ) {
 
59
      free(srcBuf);
 
60
      srcBuf = 0;
 
61
    }
 
62
    if ( outputBuf ) {
 
63
        free(outputBuf);
 
64
        outputBuf = 0;
 
65
    }
 
66
}
 
67
 
 
68
/**
 
69
 * Returns the number of bytes that can be read (or skipped over) from
 
70
 * this input stream without blocking by the next caller of a method for
 
71
 * this input stream.
 
72
 */ 
 
73
int GzipInputStream::available()
 
74
{
 
75
    if (closed || !outputBuf)
 
76
        return 0;
 
77
    return outputBufLen - outputBufPos;
 
78
}
 
79
 
 
80
    
 
81
/**
 
82
 *  Closes this input stream and releases any system resources
 
83
 *  associated with the stream.
 
84
 */ 
 
85
void GzipInputStream::close()
 
86
{
 
87
    if (closed)
 
88
        return;
 
89
 
 
90
    int zerr = inflateEnd(&d_stream);
 
91
    if (zerr != Z_OK) {
 
92
        printf("inflateEnd: Some kind of problem: %d\n", zerr);
 
93
    }
 
94
 
 
95
    if ( srcBuf ) {
 
96
      free(srcBuf);
 
97
      srcBuf = 0;
 
98
    }
 
99
    if ( outputBuf ) {
 
100
        free(outputBuf);
 
101
        outputBuf = 0;
 
102
    }
 
103
    closed = true;
 
104
}
 
105
    
 
106
/**
 
107
 * Reads the next byte of data from the input stream.  -1 if EOF
 
108
 */ 
 
109
int GzipInputStream::get()
 
110
{
 
111
    int ch = -1;
 
112
    if (closed) {
 
113
        // leave return value -1
 
114
    }
 
115
    else if (!loaded && !load()) {
 
116
        closed=true;
 
117
    } else {
 
118
        loaded = true;
 
119
 
 
120
        int zerr = Z_OK;
 
121
        if ( outputBufPos >= outputBufLen ) {
 
122
            // time to read more, if we can
 
123
            zerr = fetchMore();
 
124
        }
 
125
 
 
126
        if ( outputBufPos < outputBufLen ) {
 
127
            ch = (int)outputBuf[outputBufPos++];
 
128
        }
 
129
    }
 
130
 
 
131
    return ch;
 
132
}
 
133
 
 
134
#define FTEXT 0x01
 
135
#define FHCRC 0x02
 
136
#define FEXTRA 0x04
 
137
#define FNAME 0x08
 
138
#define FCOMMENT 0x10
 
139
 
 
140
bool GzipInputStream::load()
 
141
{
 
142
    crc = crc32(0L, Z_NULL, 0);
 
143
    
 
144
    std::vector<Byte> inputBuf;
 
145
    while (true)
 
146
        {
 
147
        int ch = source.get();
 
148
        if (ch<0)
 
149
            break;
 
150
        inputBuf.push_back((Byte)(ch & 0xff));
 
151
        }
 
152
    long inputBufLen = inputBuf.size();
 
153
    
 
154
    if (inputBufLen < 19) //header + tail + 1
 
155
        {
 
156
        return false;
 
157
        }
 
158
 
 
159
    srcLen = inputBuf.size();
 
160
    srcBuf = (Bytef *)malloc(srcLen * sizeof(Byte));
 
161
    if (!srcBuf) {
 
162
        return false;
 
163
    }
 
164
 
 
165
    outputBuf = (unsigned char *)malloc(OUT_SIZE);
 
166
    if ( !outputBuf ) {
 
167
        free(srcBuf);
 
168
        srcBuf = 0;
 
169
        return false;
 
170
    }
 
171
    outputBufLen = 0; // Not filled in yet
 
172
 
 
173
    std::vector<unsigned char>::iterator iter;
 
174
    Bytef *p = srcBuf;
 
175
    for (iter=inputBuf.begin() ; iter != inputBuf.end() ; iter++)
 
176
        *p++ = *iter;
 
177
 
 
178
    int headerLen = 10;
 
179
 
 
180
    //Magic
 
181
    int val = (int)srcBuf[0];
 
182
    //printf("val:%x\n", val);
 
183
    val = (int)srcBuf[1];
 
184
    //printf("val:%x\n", val);
 
185
 
 
186
    //Method
 
187
    val = (int)srcBuf[2];
 
188
    //printf("val:%x\n", val);
 
189
 
 
190
    //flags
 
191
    int flags = (int)srcBuf[3];
 
192
 
 
193
    //time
 
194
    val = (int)srcBuf[4];
 
195
    val = (int)srcBuf[5];
 
196
    val = (int)srcBuf[6];
 
197
    val = (int)srcBuf[7];
 
198
 
 
199
    //xflags
 
200
    val = (int)srcBuf[8];
 
201
    //OS
 
202
    val = (int)srcBuf[9];
 
203
 
 
204
    int cur = 10;
 
205
//     if ( flags & FEXTRA ) {
 
206
//         headerLen += 2;
 
207
//         int xlen = 
 
208
//         TODO deal with optional header parts
 
209
//     }
 
210
    if ( flags & FNAME ) {
 
211
        while ( srcBuf[cur] )
 
212
        {
 
213
            cur++;
 
214
            headerLen++;
 
215
        }
 
216
        headerLen++;
 
217
    }
 
218
 
 
219
 
 
220
    srcCrc = ((0x0ff & srcBuf[srcLen - 5]) << 24)
 
221
           | ((0x0ff & srcBuf[srcLen - 6]) << 16)
 
222
           | ((0x0ff & srcBuf[srcLen - 7]) <<  8)
 
223
           | ((0x0ff & srcBuf[srcLen - 8]) <<  0);
 
224
    //printf("srcCrc:%lx\n", srcCrc);
 
225
    
 
226
    srcSiz = ((0x0ff & srcBuf[srcLen - 1]) << 24)
 
227
           | ((0x0ff & srcBuf[srcLen - 2]) << 16)
 
228
           | ((0x0ff & srcBuf[srcLen - 3]) <<  8)
 
229
           | ((0x0ff & srcBuf[srcLen - 4]) <<  0);
 
230
    //printf("srcSiz:%lx/%ld\n", srcSiz, srcSiz);
 
231
    
 
232
    if ( srcSiz <= 0 ) {
 
233
        return false;
 
234
    }
 
235
 
 
236
    //outputBufLen = srcSiz + srcSiz/100 + 14;
 
237
    
 
238
    unsigned char *data = srcBuf + headerLen;
 
239
    unsigned long dataLen = srcLen - (headerLen + 8);
 
240
    //printf("%x %x\n", data[0], data[dataLen-1]);
 
241
    
 
242
    d_stream.zalloc    = (alloc_func)0;
 
243
    d_stream.zfree     = (free_func)0;
 
244
    d_stream.opaque    = (voidpf)0;
 
245
    d_stream.next_in   = data;
 
246
    d_stream.avail_in  = dataLen;
 
247
    d_stream.next_out  = outputBuf;
 
248
    d_stream.avail_out = OUT_SIZE;
 
249
    
 
250
    int zerr = inflateInit2(&d_stream, -MAX_WBITS);
 
251
    if ( zerr == Z_OK )
 
252
    {
 
253
        zerr = fetchMore();
 
254
    } else {
 
255
        printf("inflateInit2: Some kind of problem: %d\n", zerr);
 
256
    }
 
257
 
 
258
        
 
259
    return (zerr == Z_OK) || (zerr == Z_STREAM_END);
 
260
}
 
261
 
 
262
 
 
263
int GzipInputStream::fetchMore()
 
264
{
 
265
    int zerr = Z_OK;
 
266
 
 
267
    // TODO assumes we aren't called till the buffer is empty
 
268
    d_stream.next_out  = outputBuf;
 
269
    d_stream.avail_out = OUT_SIZE;
 
270
    outputBufLen = 0;
 
271
    outputBufPos = 0;
 
272
 
 
273
    zerr = inflate( &d_stream, Z_SYNC_FLUSH );
 
274
    if ( zerr == Z_OK || zerr == Z_STREAM_END ) {
 
275
        outputBufLen = OUT_SIZE - d_stream.avail_out;
 
276
        if ( outputBufLen ) {
 
277
            crc = crc32(crc, (const Bytef *)outputBuf, outputBufLen);
 
278
        }
 
279
        //printf("crc:%lx\n", crc);
 
280
//     } else if ( zerr != Z_STREAM_END ) {
 
281
//         // TODO check to be sure this won't happen for partial end reads
 
282
//         printf("inflate: Some kind of problem: %d\n", zerr);
 
283
    }
 
284
 
 
285
    return zerr;
 
286
}
 
287
 
 
288
//#########################################################################
 
289
//# G Z I P   O U T P U T    S T R E A M
 
290
//#########################################################################
 
291
 
 
292
/**
 
293
 *
 
294
 */ 
 
295
GzipOutputStream::GzipOutputStream(OutputStream &destinationStream)
 
296
                     : BasicOutputStream(destinationStream)
 
297
{
 
298
 
 
299
    totalIn         = 0;
 
300
    totalOut        = 0;
 
301
    crc             = crc32(0L, Z_NULL, 0);
 
302
 
 
303
    //Gzip header
 
304
    destination.put(0x1f);
 
305
    destination.put(0x8b);
 
306
 
 
307
    //Say it is compressed
 
308
    destination.put(Z_DEFLATED);
 
309
 
 
310
    //flags
 
311
    destination.put(0);
 
312
 
 
313
    //time
 
314
    destination.put(0);
 
315
    destination.put(0);
 
316
    destination.put(0);
 
317
    destination.put(0);
 
318
 
 
319
    //xflags
 
320
    destination.put(0);
 
321
 
 
322
    //OS code - from zutil.h
 
323
    //destination.put(OS_CODE);
 
324
    //apparently, we should not explicitly include zutil.h
 
325
    destination.put(0);
 
326
 
 
327
}
 
328
 
 
329
/**
 
330
 *
 
331
 */ 
 
332
GzipOutputStream::~GzipOutputStream()
 
333
{
 
334
    close();
 
335
}
 
336
 
 
337
/**
 
338
 * Closes this output stream and releases any system resources
 
339
 * associated with this stream.
 
340
 */ 
 
341
void GzipOutputStream::close()
 
342
{
 
343
    if (closed)
 
344
        return;
 
345
 
 
346
    flush();
 
347
 
 
348
    //# Send the CRC
 
349
    uLong outlong = crc;
 
350
    for (int n = 0; n < 4; n++)
 
351
        {
 
352
        destination.put((int)(outlong & 0xff));
 
353
        outlong >>= 8;
 
354
        }
 
355
    //# send the file length
 
356
    outlong = totalIn & 0xffffffffL;
 
357
    for (int n = 0; n < 4; n++)
 
358
        {
 
359
        destination.put((int)(outlong & 0xff));
 
360
        outlong >>= 8;
 
361
        }
 
362
 
 
363
    destination.close();
 
364
    closed = true;
 
365
}
 
366
    
 
367
/**
 
368
 *  Flushes this output stream and forces any buffered output
 
369
 *  bytes to be written out.
 
370
 */ 
 
371
void GzipOutputStream::flush()
 
372
{
 
373
    if (closed || inputBuf.size()<1)
 
374
        return;
 
375
    
 
376
    uLong srclen = inputBuf.size();
 
377
    Bytef *srcbuf = (Bytef *)malloc(srclen * sizeof(Byte));
 
378
    if (!srcbuf)
 
379
        {
 
380
        return;
 
381
        }
 
382
        
 
383
    uLong destlen = srclen;
 
384
    Bytef *destbuf = (Bytef *)malloc((destlen + (srclen/100) + 13) * sizeof(Byte));
 
385
    if (!destbuf)
 
386
        {
 
387
        free(srcbuf);
 
388
        return;
 
389
        }
 
390
        
 
391
    std::vector<unsigned char>::iterator iter;
 
392
    Bytef *p = srcbuf;
 
393
    for (iter=inputBuf.begin() ; iter != inputBuf.end() ; iter++)
 
394
        *p++ = *iter;
 
395
        
 
396
    crc = crc32(crc, (const Bytef *)srcbuf, srclen);
 
397
    
 
398
    int zerr = compress(destbuf, (uLongf *)&destlen, srcbuf, srclen);
 
399
    if (zerr != Z_OK)
 
400
        {
 
401
        printf("Some kind of problem\n");
 
402
        }
 
403
 
 
404
    totalOut += destlen;
 
405
    //skip the redundant zlib header and checksum
 
406
    for (uLong i=2; i<destlen-4 ; i++)
 
407
        {
 
408
        destination.put((int)destbuf[i]);
 
409
        }
 
410
        
 
411
    destination.flush();
 
412
 
 
413
    inputBuf.clear();
 
414
    free(srcbuf);
 
415
    free(destbuf);
 
416
    
 
417
    //printf("done\n");
 
418
    
 
419
}
 
420
 
 
421
 
 
422
 
 
423
/**
 
424
 * Writes the specified byte to this output stream.
 
425
 */ 
 
426
void GzipOutputStream::put(int ch)
 
427
{
 
428
    if (closed)
 
429
        {
 
430
        //probably throw an exception here
 
431
        return;
 
432
        }
 
433
 
 
434
 
 
435
    //Add char to buffer
 
436
    inputBuf.push_back(ch);
 
437
    totalIn++;
 
438
 
 
439
}
 
440
 
 
441
 
 
442
 
 
443
} // namespace IO
 
444
} // namespace Inkscape
 
445
 
 
446
 
 
447
//#########################################################################
 
448
//# E N D    O F    F I L E
 
449
//#########################################################################
 
450
 
 
451
/*
 
452
  Local Variables:
 
453
  mode:c++
 
454
  c-file-style:"stroustrup"
 
455
  c-file-offsets:((innamespace . 0)(inline-open . 0))
 
456
  indent-tabs-mode:nil
 
457
  fill-column:99
 
458
  End:
 
459
*/
 
460
// vim: expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :