Code

plumb XML::Documents in everywhere
[inkscape.git] / src / streams-gzip.cpp
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 <cstring>
13 #include <string>
14 #include <string.h>
16 #include "streams-gzip.h"
18 namespace Inkscape {
20 //With some inpsiration and code from libgsf, fastjar, libpng and RFC 1952
22 static int const GZIP_IS_ASCII       = 0x01; //file contains text
23 static int const GZIP_HEADER_CRC     = 0x02; //there is a CRC in the header
24 static int const GZIP_EXTRA_FIELD    = 0x04; //there is an 'extra' field
25 static int const GZIP_ORIGINAL_NAME  = 0x08; //the original is stored
26 static int const GZIP_HAS_COMMENT    = 0x10; //There is a comment in the header
27 static unsigned int const GZIP_HEADER_FLAGS = (GZIP_IS_ASCII
28                                                |GZIP_HEADER_CRC
29                                                |GZIP_EXTRA_FIELD
30                                                |GZIP_ORIGINAL_NAME
31                                                |GZIP_HAS_COMMENT);
33 /**
34  * GZipBuffer
35  */
37 void GZipBuffer::consume_header() throw(GZipHeaderException)
38 {
39     unsigned int flags;
40     guint8 data[4];
42     try {
43         _urihandle->read(data, 4);
44         check_signature(data);
45         check_flags(data);
46         flags = data[3];
47         _urihandle->read(data, 4);
48         //get_modification_time()
49         _urihandle->read(data, 1);
50         //check_extra_flags();
51         _urihandle->read(data, 1);
52         //check_OS();
53         
54         if (flags & GZIP_EXTRA_FIELD) {
55             get_extrafield();
56         }
57         if (flags & GZIP_ORIGINAL_NAME) {
58             get_filename();
59         }
60         if (flags & GZIP_HAS_COMMENT) {
61             get_comment();
62         }
63         if (flags & GZIP_HEADER_CRC) {
64             get_crc();
65         }
66     }
67     catch(std::exception& e) {
68         throw GZipHeaderException();
69     }
70 }
72 void GZipBuffer::check_signature(guint8 *data) throw(GZipHeaderException)
73 {
74     guint8 const signature[2] = {0x1f, 0x8b};
75     if (memcmp(data, signature, sizeof(signature)) != 0)
76         throw GZipHeaderException();
77 }
79 void GZipBuffer::check_flags(guint8 *data) throw(GZipHeaderException)
80 {
81     unsigned int flags = data[3];
82     if (data[2] != Z_DEFLATED || (flags & ~GZIP_HEADER_FLAGS) != 0)
83         throw GZipHeaderException();
84 }
86 gchar *GZipBuffer::get_filename()
87 {
88 #ifdef DEBUG_STREAMS
89     std::cout<<"Filename is ";
90 #endif
91     return read_string();
92 }
94 gchar *GZipBuffer::get_comment()
95 {
96 #ifdef DEBUG_STREAMS
97     std::cout<<"Comment is "<<std::endl;
98 #endif
99     return read_string();
102 guint16 GZipBuffer::get_crc()
104     guint16 buf;
105     _urihandle->read(&buf, 2);
106     return buf;
109 void GZipBuffer::get_extrafield()
111     guint8 length_data[2];
112     _urihandle->read(length_data, 2);
113     unsigned int const length = length_data[0] | (length_data[1] << 8);
114     guint8 *data = new guint8[length];
115     _urihandle->read(data, length);
118 gchar *GZipBuffer::read_string() throw(GZipHeaderException)
120     GByteArray *gba = g_byte_array_new();
121     try {
122         guint8 byte[1];
123         do {
124             _urihandle->read(byte, 1);
125             g_byte_array_append(gba, byte, sizeof(byte));
126 #ifdef DEBUG_STREAMS
127             std::cout <<(char)*byte;
128 #endif
129         } while (*byte != 0);
130     } catch (std::exception& e) {
131         g_byte_array_free(gba, TRUE);
132         throw GZipHeaderException();
133     }
134 #ifdef DEBUG_STREAMS
135     std::cout<<std::endl;
136 #endif
137     gchar *ret = (gchar *)gba->data;
138     g_byte_array_free(gba, FALSE);
139     return ret;
142 } // namespace Inkscape
144 /*
145   Local Variables:
146   mode:c++
147   c-file-style:"stroustrup"
148   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
149   indent-tabs-mode:nil
150   fill-column:99
151   End:
152 */
153 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :