summaryrefslogtreecommitdiffstats
path: root/src/streams-gzip.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/streams-gzip.cpp')
-rw-r--r--src/streams-gzip.cpp149
1 files changed, 149 insertions, 0 deletions
diff --git a/src/streams-gzip.cpp b/src/streams-gzip.cpp
new file mode 100644
index 000000000..c2cda1c2b
--- /dev/null
+++ b/src/streams-gzip.cpp
@@ -0,0 +1,149 @@
+/*
+ * IO layer : gzip streambuf and streams
+ *
+ * Authors:
+ * Johan Ceuppens <jceuppen at easynet dot be>
+ *
+ * Copyright (C) 2004 Johan Ceuppens
+ *
+ * Released under GNU LGPL, read the file 'COPYING.LIB' for more information
+ */
+
+#include "streams-gzip.h"
+
+namespace Inkscape {
+
+//With some inpsiration and code from libgsf, fastjar, libpng and RFC 1952
+
+static int const GZIP_IS_ASCII = 0x01; //file contains text
+static int const GZIP_HEADER_CRC = 0x02; //there is a CRC in the header
+static int const GZIP_EXTRA_FIELD = 0x04; //there is an 'extra' field
+static int const GZIP_ORIGINAL_NAME = 0x08; //the original is stored
+static int const GZIP_HAS_COMMENT = 0x10; //There is a comment in the header
+static unsigned int const GZIP_HEADER_FLAGS = (GZIP_IS_ASCII
+ |GZIP_HEADER_CRC
+ |GZIP_EXTRA_FIELD
+ |GZIP_ORIGINAL_NAME
+ |GZIP_HAS_COMMENT);
+
+/**
+ * GZipBuffer
+ */
+
+void GZipBuffer::consume_header() throw(GZipHeaderException)
+{
+ unsigned int flags;
+ guint8 data[4];
+
+ try {
+ _urihandle->read(data, 4);
+ check_signature(data);
+ check_flags(data);
+ flags = data[3];
+ _urihandle->read(data, 4);
+ //get_modification_time()
+ _urihandle->read(data, 1);
+ //check_extra_flags();
+ _urihandle->read(data, 1);
+ //check_OS();
+
+ if (flags & GZIP_EXTRA_FIELD) {
+ get_extrafield();
+ }
+ if (flags & GZIP_ORIGINAL_NAME) {
+ get_filename();
+ }
+ if (flags & GZIP_HAS_COMMENT) {
+ get_comment();
+ }
+ if (flags & GZIP_HEADER_CRC) {
+ get_crc();
+ }
+ }
+ catch(std::exception& e) {
+ throw GZipHeaderException();
+ }
+}
+
+void GZipBuffer::check_signature(guint8 *data) throw(GZipHeaderException)
+{
+ guint8 const signature[2] = {0x1f, 0x8b};
+ if (memcmp(data, signature, sizeof(signature)) != 0)
+ throw GZipHeaderException();
+}
+
+void GZipBuffer::check_flags(guint8 *data) throw(GZipHeaderException)
+{
+ unsigned int flags = data[3];
+ if (data[2] != Z_DEFLATED || (flags & ~GZIP_HEADER_FLAGS) != 0)
+ throw GZipHeaderException();
+}
+
+gchar *GZipBuffer::get_filename()
+{
+#ifdef DEBUG_STREAMS
+ std::cout<<"Filename is ";
+#endif
+ return read_string();
+}
+
+gchar *GZipBuffer::get_comment()
+{
+#ifdef DEBUG_STREAMS
+ std::cout<<"Comment is "<<std::endl;
+#endif
+ return read_string();
+}
+
+guint16 GZipBuffer::get_crc()
+{
+ guint16 buf;
+ _urihandle->read(&buf, 2);
+ return buf;
+}
+
+void GZipBuffer::get_extrafield()
+{
+ guint8 length_data[2];
+ _urihandle->read(length_data, 2);
+ unsigned int const length = length_data[0] | (length_data[1] << 8);
+ guint8 *data = new guint8[length];
+ _urihandle->read(data, length);
+}
+
+gchar *GZipBuffer::read_string() throw(GZipHeaderException)
+{
+ GByteArray *gba = g_byte_array_new();
+ try {
+ guint8 byte[1];
+ do {
+ _urihandle->read(byte, 1);
+ g_byte_array_append(gba, byte, sizeof(byte));
+#ifdef DEBUG_STREAMS
+ std::cout <<(char)*byte;
+#endif
+ } while (*byte != 0);
+ } catch (std::exception& e) {
+ g_byte_array_free(gba, TRUE);
+ throw GZipHeaderException();
+ }
+#ifdef DEBUG_STREAMS
+ std::cout<<std::endl;
+#endif
+ gchar *ret = (gchar *)gba->data;
+ g_byte_array_free(gba, FALSE);
+ return ret;
+}
+
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :