1 #include "streams-jar.h"
3 namespace Inkscape {
5 const int LOC_EXTRA = 6; // extra bytes
6 const int LOC_COMP = 8; // compression method
7 const int LOC_CSIZE = 18; // compressed size
8 const int LOC_FNLEN = 26; // filename length
9 const int LOC_EFLEN = 28; // extra-field length
11 void JarBuffer::consume_header() throw(JarHeaderException)
12 {
13 try {
14 guint8 data[30];
15 _urihandle->read(data, 4);
16 check_signature(data);
17 _urihandle->read(data+4, 26);
18 compressed_size = compressed_left = unpack_4bytes(data, LOC_CSIZE);
19 guint16 filename_length = unpack_2bytes(data, LOC_FNLEN);
20 eflen = unpack_2bytes(data, LOC_EFLEN);
21 flags = unpack_2bytes(data, LOC_EXTRA);
22 method = unpack_2bytes(data, LOC_COMP);
24 #ifdef DEBUG_STREAMS
25 std::printf("Compressed size is %u\n", compressed_size);
26 std::printf("Filename length is %hu\n", filename_length);
27 std::printf("Extra field length is %hu\n", eflen);
28 std::printf("Flags are %#hx\n", flags);
29 std::printf("Compression method is %#hx\n", method);
30 #endif
32 //guint32 crc = check_crc(data, flags);
33 gchar filename[filename_length+1];
34 _urihandle->read(filename, filename_length);
35 filename[filename_length] = '\0';
37 #ifdef DEBUG_STREAMS
38 std::printf("Filename is %s\n", filename);
39 #endif
40 }
41 catch (std::exception& e) {
42 throw JarHeaderException();
43 }
44 }
46 void JarBuffer::check_signature(guint8 *data) throw(JarHeaderException)
47 {
48 guint32 signature = unpack_4bytes(data, 0);
50 #ifdef DEBUG_STREAMS
51 std::printf("signature is %x\n", signature);
52 #endif
54 if (signature == 0x08074b50) {
55 _urihandle->read(data, 12);
56 } else if (signature != 0x02014b50 && signature != 0x04034b50) {
57 throw JarHeaderException();
58 }
59 }
61 void JarBuffer::reset()//resets zlib and buffer (also skips archived directories)
62 {
63 bool do_reset = false;
64 while (compressed_left == 0) {
65 consume_header();
66 do_reset = true;
67 }
69 if (do_reset) {
70 reset_inflation();
71 setg(eback(), eback(), eback());
72 }
73 }
75 int JarBuffer::consume_and_inflate()
76 {
77 int nbytes;
79 reset();
81 nbytes = compressed_left > BUFSIZE_STREAM ? BUFSIZE_STREAM
82 : compressed_left;
84 if (is_compressed())
85 return consume_compressed(nbytes);
86 else
87 return consume_uncompressed(nbytes);
88 }
90 int JarBuffer::consume_compressed(int nbytes)
91 {
92 int ret;
94 if ((ret = do_consume_and_inflate(nbytes)) == EOF && eflen > 0) {
95 guint8 efbuf[eflen];
96 _urihandle->read(efbuf, eflen);
97 return 1;
98 }
100 return ret;
101 }
103 int JarBuffer::consume_uncompressed(int nbytes)
104 {
105 guint8 data[nbytes];
106 if (consume(data, nbytes) == EOF)
107 return EOF;
109 copy_to_get(data, nbytes);
110 compressed_left -= nbytes;
112 return nbytes;
113 }
115 GByteArray *JarBuffer::inflate(guint8 *data, const int nbytes)
116 {
117 GByteArray *gba = do_inflate(data, nbytes);
118 compressed_left -= nbytes;
119 return gba;
120 }
122 guint32 JarBuffer::unpack_4bytes(guint8 *data, const int offset)
123 {
124 return ((guint32)data[offset]
125 + (((guint32)data[offset + 1]) << 8)
126 + (((guint32)data[offset + 2]) << 16)
127 + (((guint32)data[offset + 3]) << 24));
128 }
130 guint16 JarBuffer::unpack_2bytes(guint8 *data, int offset)
131 {
132 return ((guint16)data[offset] + (((guint16)data[offset + 1]) << 8));
133 }
135 } // namespace Inkscape
137 /*
138 Local Variables:
139 mode:c++
140 c-file-style:"stroustrup"
141 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
142 indent-tabs-mode:nil
143 fill-column:99
144 End:
145 */
146 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :