1 /*
2 * IO layer : gzip streambuf and streams
3 *
4 * Authors:
5 * Johan Ceuppens <jceuppen at easynet dot be>
6 *
7 * Copyright (C) 2004 Johan Ceuppens
8 *
9 * Released under GNU LGPL, read the file 'COPYING.LIB' for more information
10 */
12 #include "streams-gzip.h"
14 namespace Inkscape {
16 //With some inpsiration and code from libgsf, fastjar, libpng and RFC 1952
18 static int const GZIP_IS_ASCII = 0x01; //file contains text
19 static int const GZIP_HEADER_CRC = 0x02; //there is a CRC in the header
20 static int const GZIP_EXTRA_FIELD = 0x04; //there is an 'extra' field
21 static int const GZIP_ORIGINAL_NAME = 0x08; //the original is stored
22 static int const GZIP_HAS_COMMENT = 0x10; //There is a comment in the header
23 static unsigned int const GZIP_HEADER_FLAGS = (GZIP_IS_ASCII
24 |GZIP_HEADER_CRC
25 |GZIP_EXTRA_FIELD
26 |GZIP_ORIGINAL_NAME
27 |GZIP_HAS_COMMENT);
29 /**
30 * GZipBuffer
31 */
33 void GZipBuffer::consume_header() throw(GZipHeaderException)
34 {
35 unsigned int flags;
36 guint8 data[4];
38 try {
39 _urihandle->read(data, 4);
40 check_signature(data);
41 check_flags(data);
42 flags = data[3];
43 _urihandle->read(data, 4);
44 //get_modification_time()
45 _urihandle->read(data, 1);
46 //check_extra_flags();
47 _urihandle->read(data, 1);
48 //check_OS();
50 if (flags & GZIP_EXTRA_FIELD) {
51 get_extrafield();
52 }
53 if (flags & GZIP_ORIGINAL_NAME) {
54 get_filename();
55 }
56 if (flags & GZIP_HAS_COMMENT) {
57 get_comment();
58 }
59 if (flags & GZIP_HEADER_CRC) {
60 get_crc();
61 }
62 }
63 catch(std::exception& e) {
64 throw GZipHeaderException();
65 }
66 }
68 void GZipBuffer::check_signature(guint8 *data) throw(GZipHeaderException)
69 {
70 guint8 const signature[2] = {0x1f, 0x8b};
71 if (memcmp(data, signature, sizeof(signature)) != 0)
72 throw GZipHeaderException();
73 }
75 void GZipBuffer::check_flags(guint8 *data) throw(GZipHeaderException)
76 {
77 unsigned int flags = data[3];
78 if (data[2] != Z_DEFLATED || (flags & ~GZIP_HEADER_FLAGS) != 0)
79 throw GZipHeaderException();
80 }
82 gchar *GZipBuffer::get_filename()
83 {
84 #ifdef DEBUG_STREAMS
85 std::cout<<"Filename is ";
86 #endif
87 return read_string();
88 }
90 gchar *GZipBuffer::get_comment()
91 {
92 #ifdef DEBUG_STREAMS
93 std::cout<<"Comment is "<<std::endl;
94 #endif
95 return read_string();
96 }
98 guint16 GZipBuffer::get_crc()
99 {
100 guint16 buf;
101 _urihandle->read(&buf, 2);
102 return buf;
103 }
105 void GZipBuffer::get_extrafield()
106 {
107 guint8 length_data[2];
108 _urihandle->read(length_data, 2);
109 unsigned int const length = length_data[0] | (length_data[1] << 8);
110 guint8 *data = new guint8[length];
111 _urihandle->read(data, length);
112 }
114 gchar *GZipBuffer::read_string() throw(GZipHeaderException)
115 {
116 GByteArray *gba = g_byte_array_new();
117 try {
118 guint8 byte[1];
119 do {
120 _urihandle->read(byte, 1);
121 g_byte_array_append(gba, byte, sizeof(byte));
122 #ifdef DEBUG_STREAMS
123 std::cout <<(char)*byte;
124 #endif
125 } while (*byte != 0);
126 } catch (std::exception& e) {
127 g_byte_array_free(gba, TRUE);
128 throw GZipHeaderException();
129 }
130 #ifdef DEBUG_STREAMS
131 std::cout<<std::endl;
132 #endif
133 gchar *ret = (gchar *)gba->data;
134 g_byte_array_free(gba, FALSE);
135 return ret;
136 }
138 } // namespace Inkscape
140 /*
141 Local Variables:
142 mode:c++
143 c-file-style:"stroustrup"
144 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
145 indent-tabs-mode:nil
146 fill-column:99
147 End:
148 */
149 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :