Code

New test files. I will rip this out later.
authorishmal <ishmal@users.sourceforge.net>
Mon, 10 Apr 2006 01:03:56 +0000 (01:03 +0000)
committerishmal <ishmal@users.sourceforge.net>
Mon, 10 Apr 2006 01:03:56 +0000 (01:03 +0000)
src/dom/ziptool.cpp [new file with mode: 0644]
src/dom/ziptool.h [new file with mode: 0644]

diff --git a/src/dom/ziptool.cpp b/src/dom/ziptool.cpp
new file mode 100644 (file)
index 0000000..657d267
--- /dev/null
@@ -0,0 +1,2913 @@
+/**\r
+ * This is intended to be a standalone, reduced capability\r
+ * implementation of Gzip and Zip functionality.  Its\r
+ * targeted use case is for archiving and retrieving single files\r
+ * which use these encoding types.  Being memory based and\r
+ * non-optimized, it is not useful in cases where very large\r
+ * archives are needed or where high performance is desired.\r
+ * However, it should hopefully work very well for smaller,\r
+ * one-at-a-time tasks.  What you get in return is the ability\r
+ * to drop these files into your project and remove the dependencies\r
+ * on ZLib and Info-Zip.  Enjoy.\r
+ *\r
+ * Authors:\r
+ *   Bob Jamison\r
+ *\r
+ * Copyright (C) 2006 Bob Jamison\r
+ *\r
+ *  This library is free software; you can redistribute it and/or\r
+ *  modify it under the terms of the GNU Lesser General Public\r
+ *  License as published by the Free Software Foundation; either\r
+ *  version 2.1 of the License, or (at your option) any later version.\r
+ *\r
+ *  This library is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+ *  Lesser General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; if not, write to the Free Software\r
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
+ */\r
+\r
+\r
+#include <stdio.h>\r
+#include <stdarg.h>\r
+#include <time.h>\r
+\r
+#include <string>\r
+\r
+#include "ziptool.h"\r
+\r
+\r
+\r
+\r
+\r
+\r
+//########################################################################\r
+//#  A D L E R  3 2\r
+//########################################################################\r
+\r
+/**\r
+ * Constructor\r
+ */\r
+Adler32::Adler32()\r
+{\r
+    reset();\r
+}\r
+\r
+/**\r
+ * Destructor\r
+ */\r
+Adler32::~Adler32()\r
+{\r
+}\r
+\r
+/**\r
+ * Reset Adler-32 checksum to initial value.\r
+ */\r
+void Adler32::reset()\r
+{\r
+    value = 1;\r
+}\r
+\r
+// ADLER32_BASE is the largest prime number smaller than 65536\r
+#define ADLER32_BASE 65521\r
+\r
+void Adler32::update(unsigned char b)\r
+{\r
+    unsigned long s1 = value & 0xffff;\r
+    unsigned long s2 = (value >> 16) & 0xffff;\r
+    s1 += b & 0xff;\r
+    s2 += s1;\r
+    value = ((s2 % ADLER32_BASE) << 16) | (s1 % ADLER32_BASE);\r
+}\r
+\r
+void Adler32::update(char *str)\r
+{\r
+    if (str)\r
+        while (*str)\r
+            update((unsigned char)*str++);\r
+}\r
+\r
+\r
+/**\r
+ * Returns current checksum value.\r
+ */\r
+unsigned long Adler32::getValue()\r
+{\r
+    return value & 0xffffffffL;\r
+}\r
+\r
+\r
+\r
+//########################################################################\r
+//#  C R C  3 2\r
+//########################################################################\r
+\r
+/**\r
+ * Constructor\r
+ */\r
+Crc32::Crc32()\r
+{\r
+    reset();\r
+}\r
+\r
+/**\r
+ * Destructor\r
+ */\r
+Crc32::~Crc32()\r
+{\r
+}\r
+\r
+static bool crc_table_ready = false;\r
+static unsigned long crc_table[256];\r
+\r
+/**\r
+ * make the table for a fast CRC.\r
+ */\r
+void makeCrcTable()\r
+{\r
+    if (crc_table_ready)\r
+        return;\r
+    for (int n = 0; n < 256; n++)\r
+        {\r
+        unsigned long c = n;\r
+        for (int k = 8;  --k >= 0; )\r
+            {\r
+            if ((c & 1) != 0)\r
+                c = 0xedb88320 ^ (c >> 1);\r
+            else\r
+                c >>= 1;\r
+            }\r
+        crc_table[n] = c;\r
+        }\r
+    crc_table_ready = true;\r
+}\r
+\r
+\r
+/**\r
+ * Reset CRC-32 checksum to initial value.\r
+ */\r
+void Crc32::reset()\r
+{\r
+    value = 0;\r
+    makeCrcTable();\r
+}\r
+\r
+void Crc32::update(unsigned char b)\r
+{\r
+    unsigned long c = ~value;\r
+    c = crc_table[(c ^ b) & 0xff] ^ (c >> 8);\r
+    value = ~c;\r
+}\r
+\r
+\r
+void Crc32::update(char *str)\r
+{\r
+    if (str)\r
+        while (*str)\r
+            update((unsigned char)*str++);\r
+}\r
+\r
+void Crc32::update(const std::vector<unsigned char> &buf)\r
+{\r
+    std::vector<unsigned char>::const_iterator iter;\r
+    for (iter=buf.begin() ; iter!=buf.end() ; iter++)\r
+        {\r
+        unsigned char ch = *iter;\r
+        update(ch);\r
+        }\r
+}\r
+\r
+\r
+/**\r
+ * Returns current checksum value.\r
+ */\r
+unsigned long Crc32::getValue()\r
+{\r
+    return value & 0xffffffffL;\r
+}\r
+\r
+//########################################################################\r
+//#  I N F L A T E R\r
+//########################################################################\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+typedef struct\r
+{\r
+    int *count;  // number of symbols of each length\r
+    int *symbol; // canonically ordered symbols\r
+} Huffman;\r
+\r
+/**\r
+ *\r
+ */\r
+class Inflater\r
+{\r
+public:\r
+\r
+    Inflater();\r
+\r
+    virtual ~Inflater();\r
+\r
+    static const int MAXBITS   =  15; // max bits in a code\r
+    static const int MAXLCODES = 286; // max number of literal/length codes\r
+    static const int MAXDCODES =  30; // max number of distance codes\r
+    static const int MAXCODES  = 316; // max codes lengths to read\r
+    static const int FIXLCODES = 288; // number of fixed literal/length codes\r
+\r
+    /**\r
+     *\r
+     */\r
+    bool inflate(std::vector<unsigned char> &destination,\r
+                 std::vector<unsigned char> &source);\r
+\r
+private:\r
+\r
+    /**\r
+     *\r
+     */\r
+    void error(char *fmt, ...);\r
+\r
+    /**\r
+     *\r
+     */\r
+    void trace(char *fmt, ...);\r
+\r
+    /**\r
+     *\r
+     */\r
+    void dump();\r
+\r
+    /**\r
+     *\r
+     */\r
+    int buildHuffman(Huffman *h, int *length, int n);\r
+\r
+    /**\r
+     *\r
+     */\r
+    bool getBits(int need, int *oval);\r
+\r
+    /**\r
+     *\r
+     */\r
+    int doDecode(Huffman *h);\r
+\r
+    /**\r
+     *\r
+     */\r
+    bool doCodes(Huffman *lencode, Huffman *distcode);\r
+\r
+    /**\r
+     *\r
+     */\r
+    bool doStored();\r
+\r
+    /**\r
+     *\r
+     */\r
+    bool doFixed();\r
+\r
+    /**\r
+     *\r
+     */\r
+    bool doDynamic();\r
+\r
+\r
+    std::vector<unsigned char>dest;\r
+\r
+    std::vector<unsigned char>src;\r
+    unsigned long srcPos;  //current read position\r
+    int bitBuf;\r
+    int bitCnt;\r
+\r
+};\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+Inflater::Inflater()\r
+{\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+Inflater::~Inflater()\r
+{\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void Inflater::error(char *fmt, ...)\r
+{\r
+    va_list args;\r
+    va_start(args, fmt);\r
+    fprintf(stdout, "Inflater error:");\r
+    vfprintf(stdout, fmt, args);\r
+    fprintf(stdout, "\n");\r
+    va_end(args);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void Inflater::trace(char *fmt, ...)\r
+{\r
+    va_list args;\r
+    va_start(args, fmt);\r
+    fprintf(stdout, "Inflater:");\r
+    vfprintf(stdout, fmt, args);\r
+    fprintf(stdout, "\n");\r
+    va_end(args);\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void Inflater::dump()\r
+{\r
+    for (unsigned int i=0 ; i<dest.size() ; i++)\r
+        {\r
+        fputc(dest[i], stdout);\r
+        }\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+int Inflater::buildHuffman(Huffman *h, int *length, int n)\r
+{\r
+    // count number of codes of each length\r
+    for (int len = 0; len <= MAXBITS; len++)\r
+        h->count[len] = 0;\r
+    for (int symbol = 0; symbol < n; symbol++)\r
+        (h->count[length[symbol]])++;   // assumes lengths are within bounds\r
+    if (h->count[0] == n)               // no codes!\r
+        {\r
+        error("huffman tree will result in failed decode");\r
+        return -1;\r
+        }\r
+\r
+    // check for an over-subscribed or incomplete set of lengths\r
+    int left = 1;                // number of possible codes left of current length\r
+    for (int len = 1; len <= MAXBITS; len++)\r
+        {\r
+        left <<= 1;                     // one more bit, double codes left\r
+        left -= h->count[len];          // deduct count from possible codes\r
+        if (left < 0)\r
+            {\r
+            error("huffman over subscribed");\r
+            return -1;\r
+            }\r
+        }\r
+\r
+    // generate offsets into symbol table for each length for sorting\r
+    int offs[MAXBITS+1]; //offsets in symbol table for each length\r
+    offs[1] = 0;\r
+    for (int len = 1; len < MAXBITS; len++)\r
+        offs[len + 1] = offs[len] + h->count[len];\r
+\r
+    /*\r
+     * put symbols in table sorted by length, by symbol order within each\r
+     * length\r
+     */\r
+    for (int symbol = 0; symbol < n; symbol++)\r
+        if (length[symbol] != 0)\r
+            h->symbol[offs[length[symbol]]++] = symbol;\r
+\r
+    // return zero for complete set, positive for incomplete set\r
+    return left;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool Inflater::getBits(int requiredBits, int *oval)\r
+{\r
+    long val = bitBuf;\r
+\r
+    //add more bytes if needed\r
+    while (bitCnt < requiredBits)\r
+        {\r
+        if (srcPos >= src.size())\r
+            {\r
+            error("premature end of input");\r
+            return false;\r
+            }\r
+        val |= ((long)(src[srcPos++])) << bitCnt;\r
+        bitCnt += 8;\r
+        }\r
+\r
+    //update the buffer and return the data\r
+    bitBuf =  (int)(val >> requiredBits);\r
+    bitCnt -= requiredBits;\r
+    *oval = (int)(val & ((1L << requiredBits) - 1));\r
+\r
+    return true;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+int Inflater::doDecode(Huffman *h)\r
+{\r
+    int bitTmp  = bitBuf;\r
+    int left    = bitCnt;\r
+    int code    = 0;\r
+    int first   = 0;\r
+    int index   = 0;\r
+    int len     = 1;\r
+    int *next = h->count + 1;\r
+    while (true)\r
+        {\r
+        while (left--)\r
+            {\r
+            code   |=  bitTmp & 1;\r
+            bitTmp >>= 1;\r
+            int count  =   *next++;\r
+            if (code < first + count)\r
+                { /* if length len, return symbol */\r
+                bitBuf = bitTmp;\r
+                bitCnt = (bitCnt - len) & 7;\r
+                return h->symbol[index + (code - first)];\r
+                }\r
+            index +=  count;\r
+            first +=  count;\r
+            first <<= 1;\r
+            code  <<= 1;\r
+            len++;\r
+            }\r
+        left = (MAXBITS+1) - len;\r
+        if (left == 0)\r
+            break;\r
+        if (srcPos >= src.size())\r
+            {\r
+            error("premature end of input");\r
+            dump();\r
+            return -1;\r
+            }\r
+        bitTmp = src[srcPos++];\r
+        if (left > 8)\r
+            left = 8;\r
+        }\r
+\r
+    error("no end of block found");\r
+    return -1;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+bool Inflater::doCodes(Huffman *lencode, Huffman *distcode)\r
+{\r
+    static const int lens[29] = { // Size base for length codes 257..285\r
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,\r
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};\r
+    static const int lext[29] = { // Extra bits for length codes 257..285\r
+        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,\r
+        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};\r
+    static const int dists[30] = { // Offset base for distance codes 0..29\r
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,\r
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,\r
+        8193, 12289, 16385, 24577};\r
+    static const int dext[30] = { // Extra bits for distance codes 0..29\r
+        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,\r
+        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,\r
+        12, 12, 13, 13};\r
+\r
+    //decode literals and length/distance pairs\r
+    while (true)\r
+        {\r
+        int symbol = doDecode(lencode);\r
+        if (symbol == 256)\r
+            break;\r
+        if (symbol < 0)\r
+            {\r
+            return false;\r
+            }\r
+        if (symbol < 256) //literal\r
+            {\r
+            dest.push_back(symbol);\r
+            }\r
+        else if (symbol > 256)//length\r
+            {\r
+            symbol -= 257;\r
+            if (symbol >= 29)\r
+                {\r
+                error("invalid fixed code");\r
+                return false;\r
+                }\r
+            int ret;\r
+            if (!getBits(lext[symbol], &ret))\r
+                return false;\r
+            int len = lens[symbol] + ret;\r
+\r
+            symbol = doDecode(distcode);//distance\r
+            if (symbol < 0)\r
+                {\r
+                return false;\r
+                }\r
+\r
+            if (!getBits(dext[symbol], &ret))\r
+                return false;\r
+            unsigned int dist = dists[symbol] + ret;\r
+            if (dist > dest.size())\r
+                {\r
+                error("distance too far back %d/%d", dist, dest.size());\r
+                dump();\r
+                //printf("pos:%d\n", srcPos);\r
+                return false;\r
+                }\r
+\r
+            // copy length bytes from distance bytes back\r
+            //dest.push_back('{');\r
+            while (len--)\r
+                {\r
+                dest.push_back(dest[dest.size() - dist]);\r
+                }\r
+            //dest.push_back('}');\r
+\r
+            }\r
+        }\r
+\r
+    return true;\r
+}\r
+\r
+/**\r
+ */\r
+bool Inflater::doStored()\r
+{\r
+    //trace("### stored ###");\r
+\r
+    // clear bits from current byte\r
+    bitBuf = 0;\r
+    bitCnt = 0;\r
+\r
+    // length\r
+    if (srcPos + 4 > src.size())\r
+        {\r
+        error("not enough input");\r
+        return false;\r
+        }\r
+\r
+    int len = src[srcPos++];\r
+    len |= src[srcPos++] << 8;\r
+    //trace("### len:%d", len);\r
+    // check complement\r
+    if (src[srcPos++] != (~len & 0xff) ||\r
+        src[srcPos++] != ((~len >> 8) & 0xff))\r
+        {\r
+        error("twos complement for storage size do not match");\r
+        return false;\r
+        }\r
+\r
+    // copy data\r
+    if (srcPos + len > src.size())\r
+        {\r
+        error("Not enough input for stored block");\r
+        return false;\r
+        }\r
+    while (len--)\r
+        dest.push_back(src[srcPos++]);\r
+\r
+    return true;\r
+}\r
+\r
+/**\r
+ */\r
+bool Inflater::doFixed()\r
+{\r
+    //trace("### fixed ###");\r
+\r
+    static bool firstTime = true;\r
+    static int lencnt[MAXBITS+1], lensym[FIXLCODES];\r
+    static int distcnt[MAXBITS+1], distsym[MAXDCODES];\r
+    static Huffman lencode = {lencnt, lensym};\r
+    static Huffman distcode = {distcnt, distsym};\r
+\r
+    if (firstTime)\r
+        {\r
+        firstTime = false;\r
+\r
+        int lengths[FIXLCODES];\r
+\r
+        // literal/length table\r
+        int symbol = 0;\r
+        for ( ; symbol < 144; symbol++)\r
+            lengths[symbol] = 8;\r
+        for ( ; symbol < 256; symbol++)\r
+            lengths[symbol] = 9;\r
+        for ( ; symbol < 280; symbol++)\r
+            lengths[symbol] = 7;\r
+        for ( ; symbol < FIXLCODES; symbol++)\r
+            lengths[symbol] = 8;\r
+        buildHuffman(&lencode, lengths, FIXLCODES);\r
+\r
+        // distance table\r
+        for (int symbol = 0; symbol < MAXDCODES; symbol++)\r
+            lengths[symbol] = 5;\r
+        buildHuffman(&distcode, lengths, MAXDCODES);\r
+        }\r
+\r
+    // decode data until end-of-block code\r
+    bool ret = doCodes(&lencode, &distcode);\r
+    return ret;\r
+}\r
+\r
+/**\r
+ */\r
+bool Inflater::doDynamic()\r
+{\r
+    //trace("### dynamic ###");\r
+    int lengths[MAXCODES];                      // descriptor code lengths\r
+    int lencnt[MAXBITS+1], lensym[MAXLCODES];   // lencode memory\r
+    int distcnt[MAXBITS+1], distsym[MAXDCODES]; // distcode memory\r
+    Huffman lencode  = {lencnt, lensym};          // length code\r
+    Huffman distcode = {distcnt, distsym};        // distance code\r
+    static const int order[19] =                // permutation of code length codes\r
+        {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};\r
+\r
+    // get number of lengths in each table, check lengths\r
+    int ret;\r
+    if (!getBits(5, &ret))\r
+        return false;\r
+    int nlen  = ret + 257;\r
+    if (!getBits(5, &ret))\r
+        return false;\r
+    int ndist = ret + 1;\r
+    if (!getBits(4, &ret))\r
+        return false;\r
+    int ncode = ret + 4;\r
+    if (nlen > MAXLCODES || ndist > MAXDCODES)\r
+        {\r
+        error("Bad codes");\r
+        return false;\r
+        }\r
+\r
+    // get code length code lengths\r
+    int index = 0;\r
+    for ( ; index < ncode; index++)\r
+        {\r
+        if (!getBits(3, &ret))\r
+            return false;\r
+        lengths[order[index]] = ret;\r
+        }\r
+    for ( ; index < 19; index++)\r
+        lengths[order[index]] = 0;\r
+\r
+    // build huffman table for code lengths codes\r
+    if (buildHuffman(&lencode, lengths, 19) != 0)\r
+        return false;\r
+\r
+    // read length/literal and distance code length tables\r
+    index = 0;\r
+    while (index < nlen + ndist)\r
+        {\r
+        int symbol = doDecode(&lencode);\r
+        if (symbol < 16)                // length in 0..15\r
+            lengths[index++] = symbol;\r
+        else\r
+            {                          // repeat instruction\r
+            int len = 0;               // assume repeating zeros\r
+            if (symbol == 16)\r
+                {         // repeat last length 3..6 times\r
+                if (index == 0)\r
+                    {\r
+                    error("no last length");\r
+                    return false;\r
+                    }\r
+                len = lengths[index - 1];// last length\r
+                if (!getBits(2, &ret))\r
+                    return false;\r
+                symbol = 3 + ret;\r
+                }\r
+            else if (symbol == 17)      // repeat zero 3..10 times\r
+                {\r
+                if (!getBits(3, &ret))\r
+                    return false;\r
+                symbol = 3 + ret;\r
+                }\r
+            else                        // == 18, repeat zero 11..138 times\r
+                {\r
+                if (!getBits(7, &ret))\r
+                    return false;\r
+                symbol = 11 + ret;\r
+                }\r
+            if (index + symbol > nlen + ndist)\r
+                {\r
+                error("too many lengths");\r
+                return false;\r
+                }\r
+            while (symbol--)            // repeat last or zero symbol times\r
+                lengths[index++] = len;\r
+            }\r
+        }\r
+\r
+    // build huffman table for literal/length codes\r
+    int err = buildHuffman(&lencode, lengths, nlen);\r
+    if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1))\r
+        {\r
+        error("incomplete length codes");\r
+        //return false;\r
+        }\r
+    // build huffman table for distance codes\r
+    err = buildHuffman(&distcode, lengths + nlen, ndist);\r
+    if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1))\r
+        {\r
+        error("incomplete dist codes");\r
+        return false;\r
+        }\r
+\r
+    // decode data until end-of-block code\r
+    bool retn = doCodes(&lencode, &distcode);\r
+    return retn;\r
+}\r
+\r
+/**\r
+ */\r
+bool Inflater::inflate(std::vector<unsigned char> &destination,\r
+                       std::vector<unsigned char> &source)\r
+{\r
+    dest.clear();\r
+    src = source;\r
+    srcPos = 0;\r
+    bitBuf = 0;\r
+    bitCnt = 0;\r
+\r
+    while (true)\r
+        {\r
+        int last; // one if last block\r
+        if (!getBits(1, &last))\r
+            return false;\r
+        int type; // block type 0..3\r
+        if (!getBits(2, &type))\r
+            return false;\r
+        switch (type)\r
+            {\r
+            case 0:\r
+                if (!doStored())\r
+                    return false;\r
+                break;\r
+            case 1:\r
+                if (!doFixed())\r
+                    return false;\r
+                break;\r
+            case 2:\r
+                if (!doDynamic())\r
+                    return false;\r
+                break;\r
+            default:\r
+                error("Unknown block type %d", type);\r
+                return false;\r
+            }\r
+        if (last)\r
+            break;\r
+        }\r
+\r
+    destination = dest;\r
+\r
+    return true;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+//########################################################################\r
+//#  D E F L A T E R\r
+//########################################################################\r
+\r
+\r
+\r
+class Deflater\r
+{\r
+public:\r
+\r
+    /**\r
+     *\r
+     */\r
+    Deflater();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual ~Deflater();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual void reset();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual bool update(int ch);\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual bool finish();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual std::vector<unsigned char> &getCompressed();\r
+\r
+    /**\r
+     *\r
+     */\r
+    bool deflate(std::vector<unsigned char> &dest,\r
+                 const std::vector<unsigned char> &src);\r
+\r
+    void encodeDistStatic(unsigned int len, unsigned int dist);\r
+\r
+private:\r
+\r
+    //debug messages\r
+    void error(char *fmt, ...);\r
+    void trace(char *fmt, ...);\r
+\r
+    bool compressWindow();\r
+\r
+    bool compress();\r
+\r
+    std::vector<unsigned char> uncompressed;\r
+\r
+    std::vector<unsigned char> window;\r
+\r
+    unsigned int windowPos;\r
+\r
+    std::vector<unsigned char> compressed;\r
+\r
+    //#### Output\r
+    unsigned int outputBitBuf;\r
+    unsigned int outputNrBits;\r
+\r
+    void put(int ch);\r
+\r
+    void putWord(int ch);\r
+\r
+    void putFlush();\r
+\r
+    void putBits(unsigned int ch, unsigned int bitsWanted);\r
+\r
+    void putBitsR(unsigned int ch, unsigned int bitsWanted);\r
+\r
+    //#### Huffman Encode\r
+    void encodeLiteralStatic(unsigned int ch);\r
+};\r
+\r
+\r
+//########################################################################\r
+//# A P I\r
+//########################################################################\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+Deflater::Deflater()\r
+{\r
+    reset();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+Deflater::~Deflater()\r
+{\r
+\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void Deflater::reset()\r
+{\r
+    outputBitBuf = 0;\r
+    outputNrBits = 0;\r
+    window.clear();\r
+    compressed.clear();\r
+    uncompressed.clear();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+bool Deflater::update(int ch)\r
+{\r
+    uncompressed.push_back((unsigned char)(ch & 0xff));\r
+    return true;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+bool Deflater::finish()\r
+{\r
+    return compress();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+std::vector<unsigned char> &Deflater::getCompressed()\r
+{\r
+    return compressed;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool Deflater::deflate(std::vector<unsigned char> &dest,\r
+                       const std::vector<unsigned char> &src)\r
+{\r
+    reset();\r
+    uncompressed = src;\r
+    if (!compress())\r
+        return false;\r
+    dest = compressed;\r
+    return true;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+//########################################################################\r
+//# W O R K I N G    C O D E\r
+//########################################################################\r
+\r
+\r
+//#############################\r
+//#  M E S S A G E S\r
+//#############################\r
+\r
+/**\r
+ *  Print error messages\r
+ */\r
+void Deflater::error(char *fmt, ...)\r
+{\r
+    va_list args;\r
+    va_start(args, fmt);\r
+    fprintf(stdout, "Deflater error:");\r
+    vfprintf(stdout, fmt, args);\r
+    fprintf(stdout, "\n");\r
+    va_end(args);\r
+}\r
+\r
+/**\r
+ *  Print trace messages\r
+ */\r
+void Deflater::trace(char *fmt, ...)\r
+{\r
+    va_list args;\r
+    va_start(args, fmt);\r
+    fprintf(stdout, "Deflater:");\r
+    vfprintf(stdout, fmt, args);\r
+    fprintf(stdout, "\n");\r
+    va_end(args);\r
+}\r
+\r
+\r
+\r
+\r
+//#############################\r
+//#  O U T P U T\r
+//#############################\r
+\r
+/**\r
+ *\r
+ */\r
+void Deflater::put(int ch)\r
+{\r
+    compressed.push_back(ch);\r
+    outputBitBuf = 0;\r
+    outputNrBits = 0;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void Deflater::putWord(int ch)\r
+{\r
+    int lo = (ch   ) & 0xff;\r
+    int hi = (ch>>8) & 0xff;\r
+    put(lo);\r
+    put(hi);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void Deflater::putFlush()\r
+{\r
+    if (outputNrBits > 0)\r
+        {\r
+        put(outputBitBuf & 0xff);\r
+        }\r
+    outputBitBuf = 0;\r
+    outputNrBits = 0;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void Deflater::putBits(unsigned int ch, unsigned int bitsWanted)\r
+{\r
+    //trace("n:%4u, %d\n", ch, bitsWanted);\r
+\r
+    while (bitsWanted--)\r
+        {\r
+        //add bits to position 7.  shift right\r
+        outputBitBuf = (outputBitBuf>>1) + (ch<<7 & 0x80);\r
+        ch >>= 1;\r
+        outputNrBits++;\r
+        if (outputNrBits >= 8)\r
+            {\r
+            unsigned char b = outputBitBuf & 0xff;\r
+            //printf("b:%02x\n", b);\r
+            put(b);\r
+            }\r
+        }\r
+}\r
+\r
+static unsigned int bitReverse(unsigned int code, unsigned int nrBits)\r
+{\r
+    unsigned int outb = 0;\r
+    while (nrBits--)\r
+        {\r
+        outb = (outb << 1) | (code & 0x01);\r
+        code >>= 1;\r
+        }\r
+    return outb;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void Deflater::putBitsR(unsigned int ch, unsigned int bitsWanted)\r
+{\r
+    //trace("r:%4u, %d", ch, bitsWanted);\r
+\r
+    unsigned int rcode = bitReverse(ch, bitsWanted);\r
+\r
+    putBits(rcode, bitsWanted);\r
+\r
+}\r
+\r
+\r
+//#############################\r
+//#  E N C O D E\r
+//#############################\r
+\r
+\r
+\r
+void Deflater::encodeLiteralStatic(unsigned int ch)\r
+{\r
+    //trace("c: %d", ch);\r
+\r
+    if (ch < 144)\r
+        {\r
+        putBitsR(ch + 0x0030 , 8); // 00110000\r
+        }\r
+    else if (ch < 256)\r
+        {\r
+        putBitsR(ch - 144 + 0x0190 , 9); // 110010000\r
+        }\r
+    else if (ch < 280)\r
+        {\r
+        putBitsR(ch - 256 + 0x0000 , 7); // 0000000\r
+        }\r
+    else if (ch < 288)\r
+        {\r
+        putBitsR(ch - 280 + 0x00c0 , 8); // 11000000\r
+        }\r
+    else //out of range\r
+        {\r
+        error("Literal out of range: %d", ch);\r
+        }\r
+\r
+}\r
+\r
+\r
+typedef struct\r
+{\r
+    unsigned int base;\r
+    unsigned int range;\r
+    unsigned int bits;\r
+} LenBase;\r
+\r
+LenBase lenBases[] =\r
+{\r
+    {   3,  1, 0 },\r
+    {   4,  1, 0 },\r
+    {   5,  1, 0 },\r
+    {   6,  1, 0 },\r
+    {   7,  1, 0 },\r
+    {   8,  1, 0 },\r
+    {   9,  1, 0 },\r
+    {  10,  1, 0 },\r
+    {  11,  2, 1 },\r
+    {  13,  2, 1 },\r
+    {  15,  2, 1 },\r
+    {  17,  2, 1 },\r
+    {  19,  4, 2 },\r
+    {  23,  4, 2 },\r
+    {  27,  4, 2 },\r
+    {  31,  4, 2 },\r
+    {  35,  8, 3 },\r
+    {  43,  8, 3 },\r
+    {  51,  8, 3 },\r
+    {  59,  8, 3 },\r
+    {  67, 16, 4 },\r
+    {  83, 16, 4 },\r
+    {  99, 16, 4 },\r
+    { 115, 16, 4 },\r
+    { 131, 32, 5 },\r
+    { 163, 32, 5 },\r
+    { 195, 32, 5 },\r
+    { 227, 32, 5 },\r
+    { 258,  1, 0 }\r
+};\r
+\r
+typedef struct\r
+{\r
+    unsigned int base;\r
+    unsigned int range;\r
+    unsigned int bits;\r
+} DistBase;\r
+\r
+DistBase distBases[] =\r
+{\r
+    {     1,    1,  0 },\r
+    {     2,    1,  0 },\r
+    {     3,    1,  0 },\r
+    {     4,    1,  0 },\r
+    {     5,    2,  1 },\r
+    {     7,    2,  1 },\r
+    {     9,    4,  2 },\r
+    {    13,    4,  2 },\r
+    {    17,    8,  3 },\r
+    {    25,    8,  3 },\r
+    {    33,   16,  4 },\r
+    {    49,   16,  4 },\r
+    {    65,   32,  5 },\r
+    {    97,   32,  5 },\r
+    {   129,   64,  6 },\r
+    {   193,   64,  6 },\r
+    {   257,  128,  7 },\r
+    {   385,  128,  7 },\r
+    {   513,  256,  8 },\r
+    {   769,  256,  8 },\r
+    {  1025,  512,  9 },\r
+    {  1537,  512,  9 },\r
+    {  2049, 1024, 10 },\r
+    {  3073, 1024, 10 },\r
+    {  4097, 2048, 11 },\r
+    {  6145, 2048, 11 },\r
+    {  8193, 4096, 12 },\r
+    { 12289, 4096, 12 },\r
+    { 16385, 8192, 13 },\r
+    { 24577, 8192, 13 }\r
+};\r
+\r
+void Deflater::encodeDistStatic(unsigned int len, unsigned int dist)\r
+{\r
+\r
+    //## Output length\r
+\r
+    if (len < 3 || len > 258)\r
+        {\r
+        error("Length out of range:%d", len);\r
+        return;\r
+        }\r
+\r
+    bool found = false;\r
+    for (int i=0 ; i<30 ; i++)\r
+        {\r
+        unsigned int base  = lenBases[i].base;\r
+        unsigned int range = lenBases[i].range;\r
+        if (base + range > len)\r
+            {\r
+            unsigned int lenCode = 257 + i;\r
+            unsigned int length  = len - base;\r
+            //trace("--- %d %d %d %d", len, base, range, length);\r
+            encodeLiteralStatic(lenCode);\r
+            putBits(length, lenBases[i].bits);\r
+            found = true;\r
+            break;\r
+            }\r
+        }\r
+    if (!found)\r
+        {\r
+        error("Length not found in table:%d", len);\r
+        return;\r
+        }\r
+\r
+    //## Output distance\r
+\r
+    if (dist < 4 || dist > 32768)\r
+        {\r
+        error("Distance out of range:%d", dist);\r
+        return;\r
+        }\r
+\r
+    found = false;\r
+    for (int i=0 ; i<30 ; i++)\r
+        {\r
+        unsigned int base  = distBases[i].base;\r
+        unsigned int range = distBases[i].range;\r
+        if (base + range > dist)\r
+            {\r
+            unsigned int distCode = i;\r
+            unsigned int distance = dist - base;\r
+            //error("--- %d %d %d %d", dist, base, range, distance);\r
+            putBitsR(distCode, 5);\r
+            putBits(distance, distBases[i].bits);\r
+            found = true;\r
+            break;\r
+            }\r
+        }\r
+    if (!found)\r
+        {\r
+        error("Distance not found in table:%d", dist);\r
+        return;\r
+        }\r
+}\r
+\r
+\r
+//#############################\r
+//#  C O M P R E S S\r
+//#############################\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool Deflater::compressWindow()\r
+{\r
+    //### Compress as much of the window as possible\r
+    while (windowPos < window.size())\r
+        {\r
+        //### Find best match, if any\r
+        unsigned int bestMatchLen  = 0;\r
+        unsigned int bestMatchDist = 0;\r
+        if (windowPos >= 4)\r
+            {\r
+            for (unsigned int lookBack=0 ; lookBack<windowPos-4 ; lookBack++)\r
+                {\r
+                unsigned int lookAhead;\r
+                unsigned int lookAheadMax = window.size() - windowPos;\r
+                if (lookBack + lookAheadMax >= windowPos)\r
+                    lookAheadMax = windowPos - lookBack;\r
+                if (lookAheadMax > 258)\r
+                    lookAheadMax = 258;\r
+                for (lookAhead = 0 ; lookAhead<lookAheadMax ; lookAhead++)\r
+                    {\r
+                    unsigned int pos1 = lookBack  + lookAhead;\r
+                    unsigned int pos2 = windowPos + lookAhead;\r
+                    if (window[pos1] != window[pos2])\r
+                        break;\r
+                    }\r
+                if (lookAhead > bestMatchLen)\r
+                    {\r
+                    bestMatchLen  = lookAhead;\r
+                    bestMatchDist = windowPos - lookBack;\r
+                    }\r
+                }\r
+            }\r
+        if (bestMatchLen > 3)\r
+            {\r
+            //Distance encode\r
+            //trace("### distance");\r
+            /*\r
+            printf("### 1 '");\r
+            for (int i=0 ; i < bestMatchLen ; i++)\r
+                fputc(window[windowPos+i], stdout);\r
+            printf("'\n### 2 '");\r
+            for (int i=0 ; i < bestMatchLen ; i++)\r
+                fputc(window[windowPos-bestMatchDist+i], stdout);\r
+            printf("'\n");\r
+            */\r
+            encodeDistStatic(bestMatchLen, bestMatchDist);\r
+            windowPos += bestMatchLen;\r
+            }\r
+        else\r
+            {\r
+            //Literal encode\r
+            //trace("### literal");\r
+            encodeLiteralStatic(window[windowPos]);\r
+            windowPos++;\r
+            }\r
+        }\r
+    encodeLiteralStatic(256);\r
+    return true;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool Deflater::compress()\r
+{\r
+    //trace("compress");\r
+    unsigned long total = 0L;\r
+    windowPos = 0;\r
+    std::vector<unsigned char>::iterator iter;\r
+    for (iter = uncompressed.begin(); iter != uncompressed.end() ; )\r
+        {\r
+        total += windowPos;\r
+        //trace("total:%ld", total);\r
+        window.erase(window.begin() , window.begin()+windowPos);\r
+        while (window.size() < 32768 && iter != uncompressed.end())\r
+            {\r
+            window.push_back(*iter);\r
+            iter++;\r
+            }\r
+        windowPos = 0;\r
+        putBits(0x01, 1); //1  -- last block\r
+        putBits(0x01, 2); //01 -- static trees\r
+        if (!compressWindow())\r
+            return false;\r
+        }\r
+    putFlush();\r
+    return true;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+//########################################################################\r
+//#  G Z I P    F I L E\r
+//########################################################################\r
+\r
+/**\r
+ * Constructor\r
+ */\r
+GzipFile::GzipFile()\r
+{\r
+}\r
+\r
+/**\r
+ * Destructor\r
+ */\r
+GzipFile::~GzipFile()\r
+{\r
+}\r
+\r
+/**\r
+ *  Print error messages\r
+ */\r
+void GzipFile::error(char *fmt, ...)\r
+{\r
+    va_list args;\r
+    va_start(args, fmt);\r
+    fprintf(stdout, "GzipFile error:");\r
+    vfprintf(stdout, fmt, args);\r
+    fprintf(stdout, "\n");\r
+    va_end(args);\r
+}\r
+\r
+/**\r
+ *  Print trace messages\r
+ */\r
+void GzipFile::trace(char *fmt, ...)\r
+{\r
+    va_list args;\r
+    va_start(args, fmt);\r
+    fprintf(stdout, "GzipFile:");\r
+    vfprintf(stdout, fmt, args);\r
+    fprintf(stdout, "\n");\r
+    va_end(args);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void GzipFile::put(unsigned char ch)\r
+{\r
+    data.push_back(ch);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void GzipFile::setData(const std::vector<unsigned char> &str)\r
+{\r
+    data = str;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void GzipFile::clearData()\r
+{\r
+    data.clear();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+std::vector<unsigned char> &GzipFile::getData()\r
+{\r
+    return data;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+std::string &GzipFile::getFileName()\r
+{\r
+    return fileName;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void GzipFile::setFileName(const std::string &val)\r
+{\r
+    fileName = val;\r
+}\r
+\r
+\r
+\r
+//#####################################\r
+//# U T I L I T Y\r
+//#####################################\r
+\r
+/**\r
+ *  Loads a new file into an existing GzipFile\r
+ */\r
+bool GzipFile::loadFile(const std::string &fName)\r
+{\r
+    FILE *f = fopen(fName.c_str() , "rb");\r
+    if (!f)\r
+        {\r
+        error("Cannot open file %s", fName.c_str());\r
+        return false;\r
+        }\r
+    while (true)\r
+        {\r
+        int ch = fgetc(f);\r
+        if (ch < 0)\r
+            break;\r
+        data.push_back(ch);\r
+        }\r
+    fclose(f);\r
+    setFileName(fName);\r
+    return true;\r
+}\r
+\r
+\r
+\r
+//#####################################\r
+//# W R I T E\r
+//#####################################\r
+\r
+/**\r
+ *\r
+ */\r
+bool GzipFile::putByte(unsigned char ch)\r
+{\r
+    fileBuf.push_back(ch);\r
+    return true;\r
+}\r
+\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool GzipFile::putLong(unsigned long val)\r
+{\r
+    fileBuf.push_back( (unsigned char)((val    ) & 0xff));\r
+    fileBuf.push_back( (unsigned char)((val>> 8) & 0xff));\r
+    fileBuf.push_back( (unsigned char)((val>>16) & 0xff));\r
+    fileBuf.push_back( (unsigned char)((val>>24) & 0xff));\r
+    return true;\r
+}\r
+\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool GzipFile::write()\r
+{\r
+    fileBuf.clear();\r
+\r
+    putByte(0x1f); //magic\r
+    putByte(0x8b); //magic\r
+    putByte(   8); //compression method\r
+    putByte(0x08); //flags.  say we have a crc and file name\r
+\r
+    unsigned long ltime = (unsigned long) time(NULL);\r
+    putLong(ltime);\r
+\r
+    //xfl\r
+    putByte(0);\r
+    //OS\r
+    putByte(0);\r
+\r
+    //file name\r
+    for (int i=0 ; i<fileName.size() ; i++)\r
+        putByte(fileName[i]);\r
+    putByte(0);\r
+\r
+\r
+    //compress\r
+    std::vector<unsigned char> compBuf;\r
+    Deflater deflater;\r
+    if (!deflater.deflate(compBuf, data))\r
+        {\r
+        return false;\r
+        }\r
+\r
+    std::vector<unsigned char>::iterator iter;\r
+    for (iter=compBuf.begin() ; iter!=compBuf.end() ; iter++)\r
+        {\r
+        unsigned char ch = *iter;\r
+        putByte(ch);\r
+        }\r
+\r
+    Crc32 crcEngine;\r
+    crcEngine.update(data);\r
+    unsigned long crc = crcEngine.getValue();\r
+    putLong(crc);\r
+\r
+    putLong(data.size());\r
+\r
+    return true;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool GzipFile::writeBuffer(std::vector<unsigned char> &outBuf)\r
+{\r
+    if (!write())\r
+        return false;\r
+    outBuf.clear();\r
+    outBuf = fileBuf;\r
+    return true;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool GzipFile::writeFile(const std::string &fileName)\r
+{\r
+    if (!write())\r
+        return false;\r
+    FILE *f = fopen(fileName.c_str(), "wb");\r
+    if (!f)\r
+        return false;\r
+    std::vector<unsigned char>::iterator iter;\r
+    for (iter=fileBuf.begin() ; iter!=fileBuf.end() ; iter++)\r
+        {\r
+        unsigned char ch = *iter;\r
+        fputc(ch, f);\r
+        }\r
+    fclose(f);\r
+    return true;\r
+}\r
+\r
+\r
+//#####################################\r
+//# R E A D\r
+//#####################################\r
+\r
+bool GzipFile::getByte(unsigned char *ch)\r
+{\r
+    if (fileBufPos >= fileBuf.size())\r
+        {\r
+        error("unexpected end of data");\r
+        return false;\r
+        }\r
+    *ch = fileBuf[fileBufPos++];\r
+    return true;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+bool GzipFile::getLong(unsigned long *val)\r
+{\r
+    if (fileBuf.size() - fileBufPos < 4)\r
+        return false;\r
+    int ch1 = fileBuf[fileBufPos++];\r
+    int ch2 = fileBuf[fileBufPos++];\r
+    int ch3 = fileBuf[fileBufPos++];\r
+    int ch4 = fileBuf[fileBufPos++];\r
+    *val = ((ch4<<24) & 0xff000000L) |\r
+           ((ch3<<16) & 0x00ff0000L) |\r
+           ((ch2<< 8) & 0x0000ff00L) |\r
+           ((ch1    ) & 0x000000ffL);\r
+    return true;\r
+}\r
+\r
+bool GzipFile::read()\r
+{\r
+    fileBufPos = 0;\r
+\r
+    unsigned char ch;\r
+\r
+    //magic cookie\r
+    if (!getByte(&ch))\r
+        return false;\r
+    if (ch != 0x1f)\r
+        {\r
+        error("bad gzip header");\r
+        return false;\r
+        }\r
+    if (!getByte(&ch))\r
+        return false;\r
+    if (ch != 0x8b)\r
+        {\r
+        error("bad gzip header");\r
+        return false;\r
+        }\r
+\r
+    //## compression method\r
+    if (!getByte(&ch))\r
+        return false;\r
+    int cm = ch & 0xff;\r
+\r
+    //## flags\r
+    if (!getByte(&ch))\r
+        return false;\r
+    bool ftext    = ch & 0x01;\r
+    bool fhcrc    = ch & 0x02;\r
+    bool fextra   = ch & 0x04;\r
+    bool fname    = ch & 0x08;\r
+    bool fcomment = ch & 0x10;\r
+\r
+    //trace("cm:%d ftext:%d fhcrc:%d fextra:%d fname:%d fcomment:%d",\r
+    //         cm, ftext, fhcrc, fextra, fname, fcomment);\r
+\r
+    //## file time\r
+    unsigned long ltime;\r
+    if (!getLong(&ltime))\r
+        return false;\r
+    time_t mtime = (time_t)ltime;\r
+\r
+    //## XFL\r
+    if (!getByte(&ch))\r
+        return false;\r
+    int xfl = ch;\r
+\r
+    //## OS\r
+    if (!getByte(&ch))\r
+        return false;\r
+    int os = ch;\r
+\r
+    //std::string timestr = ctime(&mtime);\r
+    //trace("xfl:%d os:%d mtime:%s", xfl, os, timestr.c_str());\r
+\r
+    if (fextra)\r
+        {\r
+        if (!getByte(&ch))\r
+            return false;\r
+        long xlen = ch;\r
+        if (!getByte(&ch))\r
+            return false;\r
+        xlen = (xlen << 8) + ch;\r
+        for (long l=0 ; l<xlen ; l++)\r
+            {\r
+            if (!getByte(&ch))\r
+                return false;\r
+            }\r
+        }\r
+\r
+    if (fname)\r
+        {\r
+        fileName = "";\r
+       while (true)\r
+           {\r
+            if (!getByte(&ch))\r
+                return false;\r
+            if (ch==0)\r
+                break;\r
+            fileName.push_back(ch);\r
+            }\r
+        }\r
+\r
+    if (fcomment)\r
+        {\r
+       while (true)\r
+           {\r
+            if (!getByte(&ch))\r
+                return false;\r
+            if (ch==0)\r
+                break;\r
+            }\r
+        }\r
+\r
+    if (fhcrc)\r
+        {\r
+        if (!getByte(&ch))\r
+            return false;\r
+        if (!getByte(&ch))\r
+            return false;\r
+        }\r
+\r
+    //read remainder of stream\r
+    //compressed data runs up until 8 bytes before end of buffer\r
+    std::vector<unsigned char> compBuf;\r
+    while (fileBufPos < fileBuf.size() - 8)\r
+        {\r
+        if (!getByte(&ch))\r
+            return false;\r
+        compBuf.push_back(ch);\r
+        }\r
+    //uncompress\r
+    data.clear();\r
+    Inflater inflater;\r
+    if (!inflater.inflate(data, compBuf))\r
+        {\r
+        return false;\r
+        }\r
+\r
+    //Get the CRC and compare\r
+    Crc32 crcEngine;\r
+    crcEngine.update(data);\r
+    unsigned long calcCrc = crcEngine.getValue();\r
+    unsigned long givenCrc;\r
+    if (!getLong(&givenCrc))\r
+        return false;\r
+    if (givenCrc != calcCrc)\r
+        {\r
+        error("Specified crc, %ud, not what received: %ud",\r
+                givenCrc, calcCrc);\r
+        return false;\r
+        }\r
+\r
+    //Get the file size and compare\r
+    unsigned long givenFileSize;\r
+    if (!getLong(&givenFileSize))\r
+        return false;\r
+    if (givenFileSize != data.size())\r
+        {\r
+        error("Specified data size, %ld, not what received: %ld",\r
+                givenFileSize, data.size());\r
+        return false;\r
+        }\r
+\r
+    return true;\r
+}\r
+\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool GzipFile::readBuffer(const std::vector<unsigned char> &inbuf)\r
+{\r
+    fileBuf = inbuf;\r
+    if (!read())\r
+        return false;\r
+    return true;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool GzipFile::readFile(const std::string &fileName)\r
+{\r
+    fileBuf.clear();\r
+    FILE *f = fopen(fileName.c_str(), "rb");\r
+    if (!f)\r
+        return false;\r
+    while (true)\r
+        {\r
+        int ch = fgetc(f);\r
+        if (ch < 0)\r
+            break;\r
+        fileBuf.push_back(ch);\r
+        }\r
+    fclose(f);\r
+    if (!read())\r
+        return false;\r
+    return true;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+//########################################################################\r
+//#  Z I P    F I L E\r
+//########################################################################\r
+\r
+/**\r
+ * Constructor\r
+ */\r
+ZipEntry::ZipEntry()\r
+{\r
+    crc               = 0L;\r
+    compressionMethod = 8;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+ZipEntry::ZipEntry(const std::string &fileNameArg,\r
+                   const std::string &commentArg)\r
+{\r
+    crc               = 0L;\r
+    compressionMethod = 8;\r
+    fileName          = fileNameArg;\r
+    comment           = commentArg;\r
+}\r
+\r
+/**\r
+ * Destructor\r
+ */\r
+ZipEntry::~ZipEntry()\r
+{\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+std::string ZipEntry::getFileName()\r
+{\r
+    return fileName;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void ZipEntry::setFileName(const std::string &val)\r
+{\r
+    fileName = val;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+std::string ZipEntry::getComment()\r
+{\r
+    return comment;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void ZipEntry::setComment(const std::string &val)\r
+{\r
+    comment = val;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned long ZipEntry::getCompressedSize()\r
+{\r
+    return (unsigned long)compressedData.size();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+int ZipEntry::getCompressionMethod()\r
+{\r
+    return compressionMethod;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void ZipEntry::setCompressionMethod(int val)\r
+{\r
+    compressionMethod = val;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+std::vector<unsigned char> &ZipEntry::getCompressedData()\r
+{\r
+    return compressedData;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void ZipEntry::setCompressedData(const std::vector<unsigned char> &val)\r
+{\r
+    compressedData = val;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned long ZipEntry::getUncompressedSize()\r
+{\r
+    return (unsigned long)uncompressedData.size();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+std::vector<unsigned char> &ZipEntry::getUncompressedData()\r
+{\r
+    return uncompressedData;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void ZipEntry::setUncompressedData(const std::vector<unsigned char> &val)\r
+{\r
+    uncompressedData = val;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void ZipEntry::write(unsigned char ch)\r
+{\r
+    uncompressedData.push_back(ch);\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void ZipEntry::finish()\r
+{\r
+    Crc32 c32;\r
+    std::vector<unsigned char>::iterator iter;\r
+    for (iter = uncompressedData.begin() ;\r
+           iter!= uncompressedData.end() ; iter++)\r
+        {\r
+        unsigned char ch = *iter;\r
+        c32.update(ch);\r
+        }\r
+    crc = c32.getValue();\r
+    switch (compressionMethod)\r
+        {\r
+        case 0: //none\r
+            {\r
+            for (iter = uncompressedData.begin() ;\r
+               iter!= uncompressedData.end() ; iter++)\r
+                {\r
+                unsigned char ch = *iter;\r
+                compressedData.push_back(ch);\r
+                }\r
+            break;\r
+            }\r
+        case 8: //deflate\r
+            {\r
+            Deflater deflater;\r
+            if (!deflater.deflate(compressedData, uncompressedData))\r
+                {\r
+                //some error\r
+                }\r
+            break;\r
+            }\r
+        default:\r
+            {\r
+            printf("error: unknown compression method %d\n",\r
+                    compressionMethod);\r
+            }\r
+        }\r
+    printf("### done\n");\r
+}\r
+\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned long ZipEntry::getCrc()\r
+{\r
+    return crc;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipEntry::readFile(const std::string &fileNameArg,\r
+                        const std::string &commentArg)\r
+{\r
+    crc = 0L;\r
+    uncompressedData.clear();\r
+    fileName = fileNameArg;\r
+    comment  = commentArg;\r
+    FILE *f = fopen(fileName.c_str(), "rb");\r
+    if (!f)\r
+        {\r
+        return false;\r
+        }\r
+    while (true)\r
+        {\r
+        int ch = fgetc(f);\r
+        if (ch < 0)\r
+            break;\r
+        uncompressedData.push_back((unsigned char)ch);\r
+        }\r
+    fclose(f);\r
+    finish();\r
+    return true;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+void ZipEntry::setPosition(unsigned long val)\r
+{\r
+    position = val;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+unsigned long ZipEntry::getPosition()\r
+{\r
+    return position;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+/**\r
+ * Constructor\r
+ */\r
+ZipFile::ZipFile()\r
+{\r
+\r
+}\r
+\r
+/**\r
+ * Destructor\r
+ */\r
+ZipFile::~ZipFile()\r
+{\r
+    std::vector<ZipEntry *>::iterator iter;\r
+    for (iter=entries.begin() ; iter!=entries.end() ; iter++)\r
+        {\r
+        ZipEntry *entry = *iter;\r
+        delete entry;\r
+        }\r
+    entries.clear();\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+void ZipFile::setComment(const std::string &val)\r
+{\r
+    comment = val;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+std::string ZipFile::getComment()\r
+{\r
+    return comment;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+std::vector<ZipEntry *> &ZipFile::getEntries()\r
+{\r
+    return entries;\r
+}\r
+\r
+\r
+\r
+//#####################################\r
+//# M E S S A G E S\r
+//#####################################\r
+\r
+void ZipFile::error(char *fmt, ...)\r
+{\r
+    va_list args;\r
+    va_start(args, fmt);\r
+    fprintf(stdout, "ZipFile error:");\r
+    vfprintf(stdout, fmt, args);\r
+    fprintf(stdout, "\n");\r
+    va_end(args);\r
+}\r
+\r
+void ZipFile::trace(char *fmt, ...)\r
+{\r
+    va_list args;\r
+    va_start(args, fmt);\r
+    fprintf(stdout, "ZipFile:");\r
+    vfprintf(stdout, fmt, args);\r
+    fprintf(stdout, "\n");\r
+    va_end(args);\r
+}\r
+\r
+//#####################################\r
+//# U T I L I T Y\r
+//#####################################\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipFile::addFile(const std::string &fileName,\r
+                      const std::string &comment)\r
+{\r
+    ZipEntry *ze = new ZipEntry();\r
+    if (!ze->readFile(fileName, comment))\r
+        {\r
+        return false;\r
+        }\r
+    entries.push_back(ze);\r
+    return true;\r
+}\r
+\r
+\r
+//#####################################\r
+//# W R I T E\r
+//#####################################\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipFile::putLong(unsigned long val)\r
+{\r
+    fileBuf.push_back( ((int)(val    )) & 0xff);\r
+    fileBuf.push_back( ((int)(val>> 8)) & 0xff);\r
+    fileBuf.push_back( ((int)(val>>16)) & 0xff);\r
+    fileBuf.push_back( ((int)(val>>24)) & 0xff);\r
+    return true;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipFile::putInt(unsigned int val)\r
+{\r
+    fileBuf.push_back( (val    ) & 0xff);\r
+    fileBuf.push_back( (val>> 8) & 0xff);\r
+    return true;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipFile::putByte(unsigned char val)\r
+{\r
+    fileBuf.push_back(val);\r
+    return true;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipFile::writeFileData()\r
+{\r
+    std::vector<ZipEntry *>::iterator iter;\r
+    for (iter = entries.begin() ; iter != entries.end() ; iter++)\r
+        {\r
+        ZipEntry *entry = *iter;\r
+        entry->setPosition(fileBuf.size());\r
+        //##### HEADER\r
+        std::string fname = entry->getFileName();\r
+        putLong(0x04034b50L);\r
+        putInt(20); //versionNeeded\r
+        putInt(0); //gpBitFlag\r
+        //putInt(0); //compression method\r
+        putInt(entry->getCompressionMethod()); //compression method\r
+        putInt(0); //mod time\r
+        putInt(0); //mod date\r
+        putLong(entry->getCrc()); //crc32\r
+        putLong(entry->getCompressedSize());\r
+        putLong(entry->getUncompressedSize());\r
+        putInt(fname.size());//fileName length\r
+        putInt(8);//extra field length\r
+        //file name\r
+        for (unsigned int i=0 ; i<fname.size() ; i++)\r
+            putByte((unsigned char)fname[i]);\r
+        //extra field\r
+        putInt(0x7855);\r
+        putInt(4);\r
+        putInt(100);\r
+        putInt(100);\r
+\r
+        //##### DATA\r
+        std::vector<unsigned char> &buf = entry->getCompressedData();\r
+        std::vector<unsigned char>::iterator iter;\r
+        for (iter = buf.begin() ; iter != buf.end() ; iter++)\r
+            {\r
+            unsigned char ch = (unsigned char) *iter;\r
+            putByte(ch);\r
+            }\r
+        }\r
+    return true;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipFile::writeCentralDirectory()\r
+{\r
+    unsigned long cdPosition = fileBuf.size();\r
+    std::vector<ZipEntry *>::iterator iter;\r
+    for (iter = entries.begin() ; iter != entries.end() ; iter++)\r
+        {\r
+        ZipEntry *entry = *iter;\r
+        std::string fname   = entry->getFileName();\r
+        std::string ecomment = entry->getComment();\r
+        putLong(0x02014b50L);  //magic cookie\r
+        putInt(2386); //versionMadeBy\r
+        putInt(20); //versionNeeded\r
+        putInt(0); //gpBitFlag\r
+        putInt(entry->getCompressionMethod()); //compression method\r
+        putInt(0); //mod time\r
+        putInt(0); //mod date\r
+        putLong(entry->getCrc()); //crc32\r
+        putLong(entry->getCompressedSize());\r
+        putLong(entry->getUncompressedSize());\r
+        putInt(fname.size());//fileName length\r
+        putInt(4);//extra field length\r
+        putInt(ecomment.size());//comment length\r
+        putInt(0); //disk number start\r
+        putInt(0); //internal attributes\r
+        putLong(0); //external attributes\r
+        putLong(entry->getPosition());\r
+\r
+        //file name\r
+        for (unsigned int i=0 ; i<fname.size() ; i++)\r
+            putByte((unsigned char)fname[i]);\r
+        //extra field\r
+        putInt(0x7855);\r
+        putInt(0);\r
+        //comment\r
+        for (unsigned int i=0 ; i<ecomment.size() ; i++)\r
+            putByte((unsigned char)ecomment[i]);\r
+        }\r
+    unsigned long cdSize = fileBuf.size() - cdPosition;\r
+\r
+    putLong(0x06054b50L);\r
+    putInt(0);//number of this disk\r
+    putInt(0);//nr of disk with central dir\r
+    putInt(entries.size()); //number of entries on this disk\r
+    putInt(entries.size()); //number of entries total\r
+    putLong(cdSize);  //size of central dir\r
+    putLong(cdPosition); //position of central dir\r
+    putInt(comment.size());//comment size\r
+    for (unsigned int i=0 ; i<comment.size() ; i++)\r
+        putByte(comment[i]);\r
+    return true;\r
+}\r
+\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipFile::write()\r
+{\r
+    fileBuf.clear();\r
+    if (!writeFileData())\r
+        return false;\r
+    if (!writeCentralDirectory())\r
+        return false;\r
+    return true;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipFile::writeBuffer(std::vector<unsigned char> &outBuf)\r
+{\r
+    if (!write())\r
+        return false;\r
+    outBuf.clear();\r
+    outBuf = fileBuf;\r
+    return true;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipFile::writeFile(const std::string &fileName)\r
+{\r
+    if (!write())\r
+        return false;\r
+    FILE *f = fopen(fileName.c_str(), "wb");\r
+    if (!f)\r
+        return false;\r
+    std::vector<unsigned char>::iterator iter;\r
+    for (iter=fileBuf.begin() ; iter!=fileBuf.end() ; iter++)\r
+        {\r
+        unsigned char ch = *iter;\r
+        fputc(ch, f);\r
+        }\r
+    fclose(f);\r
+    return true;\r
+}\r
+\r
+//#####################################\r
+//# R E A D\r
+//#####################################\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipFile::getLong(unsigned long *val)\r
+{\r
+    if (fileBuf.size() - fileBufPos < 4)\r
+        return false;\r
+    int ch1 = fileBuf[fileBufPos++];\r
+    int ch2 = fileBuf[fileBufPos++];\r
+    int ch3 = fileBuf[fileBufPos++];\r
+    int ch4 = fileBuf[fileBufPos++];\r
+    *val = ((ch4<<24) & 0xff000000L) |\r
+           ((ch3<<16) & 0x00ff0000L) |\r
+           ((ch2<< 8) & 0x0000ff00L) |\r
+           ((ch1    ) & 0x000000ffL);\r
+    return true;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipFile::getInt(unsigned int *val)\r
+{\r
+    if (fileBuf.size() - fileBufPos < 2)\r
+        return false;\r
+    int ch1 = fileBuf[fileBufPos++];\r
+    int ch2 = fileBuf[fileBufPos++];\r
+    *val = ((ch2<< 8) & 0xff00) |\r
+           ((ch1    ) & 0x00ff);\r
+    return true;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipFile::getByte(unsigned char *val)\r
+{\r
+    if (fileBuf.size() <= fileBufPos)\r
+        return false;\r
+    *val = fileBuf[fileBufPos++];\r
+    return true;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipFile::readFileData()\r
+{\r
+    //printf("#################################################\n");\r
+    //printf("###D A T A\n");\r
+    //printf("#################################################\n");\r
+    while (true)\r
+        {\r
+        unsigned long magicCookie;\r
+        if (!getLong(&magicCookie))\r
+            {\r
+            error("magic cookie not found");\r
+            break;\r
+            }\r
+        trace("###Cookie:%lx", magicCookie);\r
+        if (magicCookie == 0x02014b50L) //central directory\r
+            break;\r
+        if (magicCookie != 0x04034b50L)\r
+            {\r
+            error("file header not found");\r
+            return false;\r
+            }\r
+        unsigned int versionNeeded;\r
+        if (!getInt(&versionNeeded))\r
+            {\r
+            error("bad version needed found");\r
+            return false;\r
+            }\r
+        unsigned int gpBitFlag;\r
+        if (!getInt(&gpBitFlag))\r
+            {\r
+            error("bad bit flag found");\r
+            return false;\r
+            }\r
+        unsigned int compressionMethod;\r
+        if (!getInt(&compressionMethod))\r
+            {\r
+            error("bad compressionMethod found");\r
+            return false;\r
+            }\r
+        unsigned int modTime;\r
+        if (!getInt(&modTime))\r
+            {\r
+            error("bad modTime found");\r
+            return false;\r
+            }\r
+        unsigned int modDate;\r
+        if (!getInt(&modDate))\r
+            {\r
+            error("bad modDate found");\r
+            return false;\r
+            }\r
+        unsigned long crc32;\r
+        if (!getLong(&crc32))\r
+            {\r
+            error("bad crc32 found");\r
+            return false;\r
+            }\r
+        unsigned long compressedSize;\r
+        if (!getLong(&compressedSize))\r
+            {\r
+            error("bad compressedSize found");\r
+            return false;\r
+            }\r
+        unsigned long uncompressedSize;\r
+        if (!getLong(&uncompressedSize))\r
+            {\r
+            error("bad uncompressedSize found");\r
+            return false;\r
+            }\r
+        unsigned int fileNameLength;\r
+        if (!getInt(&fileNameLength))\r
+            {\r
+            error("bad fileNameLength found");\r
+            return false;\r
+            }\r
+        unsigned int extraFieldLength;\r
+        if (!getInt(&extraFieldLength))\r
+            {\r
+            error("bad extraFieldLength found");\r
+            return false;\r
+            }\r
+        std::string fileName;\r
+        for (unsigned int i=0 ; i<fileNameLength ; i++)\r
+            {\r
+            unsigned char ch;\r
+            if (!getByte(&ch))\r
+                break;\r
+            fileName.push_back(ch);\r
+            }\r
+        std::string extraField;\r
+        for (unsigned int i=0 ; i<extraFieldLength ; i++)\r
+            {\r
+            unsigned char ch;\r
+            if (!getByte(&ch))\r
+                break;\r
+            extraField.push_back(ch);\r
+            }\r
+        trace("#########################  DATA");\r
+        trace("FileName           :%d:%s" , fileName.size(), fileName.c_str());\r
+        trace("Extra field        :%d:%s" , extraField.size(), extraField.c_str());\r
+        trace("Version needed     :%d" , versionNeeded);\r
+        trace("Bitflag            :%d" , gpBitFlag);\r
+        trace("Compression Method :%d" , compressionMethod);\r
+        trace("Mod time           :%d" , modTime);\r
+        trace("Mod date           :%d" , modDate);\r
+        trace("CRC                :%lx", crc32);\r
+        trace("Compressed size    :%ld", compressedSize);\r
+        trace("Uncompressed size  :%ld", uncompressedSize);\r
+\r
+        //#### Uncompress the data\r
+        std::vector<unsigned char> compBuf;\r
+        if (gpBitFlag & 0x8)//bit 3 was set.  means we dont know compressed size\r
+            {\r
+            unsigned char c1, c2, c3, c4;\r
+            c1 = c2 = c3 = c4 = 0;\r
+            while (true)\r
+                {\r
+                unsigned char ch;\r
+                if (!getByte(&ch))\r
+                    {\r
+                    error("premature end of data");\r
+                    break;\r
+                    }\r
+                compBuf.push_back(ch);\r
+                c1 = c2; c2 = c3; c3 = c4; c4 = ch;\r
+                if (c1 == 0x50 && c2 == 0x4b && c3 == 0x07 && c4 == 0x08)\r
+                    {\r
+                    trace("found end of compressed data");\r
+                    //remove the cookie\r
+                    compBuf.erase(compBuf.end() -4, compBuf.end());\r
+                    break;\r
+                    }\r
+                }\r
+            }\r
+        else\r
+            {\r
+            for (unsigned long bnr = 0 ; bnr < compressedSize ; bnr++)\r
+                {\r
+                unsigned char ch;\r
+                if (!getByte(&ch))\r
+                    {\r
+                    error("premature end of data");\r
+                    break;\r
+                    }\r
+                compBuf.push_back(ch);\r
+                }\r
+            }\r
+\r
+        printf("### data: ");\r
+        for (int i=0 ; i<10 ; i++)\r
+            printf("%02x ", compBuf[i] & 0xff);\r
+        printf("\n");\r
+\r
+        if (gpBitFlag & 0x8)//only if bit 3 set\r
+            {\r
+            /* this cookie was read in the loop above\r
+            unsigned long dataDescriptorSignature ;\r
+            if (!getLong(&dataDescriptorSignature))\r
+                break;\r
+            if (dataDescriptorSignature != 0x08074b50L)\r
+                {\r
+                error("bad dataDescriptorSignature found");\r
+                return false;\r
+                }\r
+            */\r
+            unsigned long crc32;\r
+            if (!getLong(&crc32))\r
+                {\r
+                error("bad crc32 found");\r
+                return false;\r
+                }\r
+            unsigned long compressedSize;\r
+            if (!getLong(&compressedSize))\r
+                {\r
+                error("bad compressedSize found");\r
+                return false;\r
+                }\r
+            unsigned long uncompressedSize;\r
+            if (!getLong(&uncompressedSize))\r
+                {\r
+                error("bad uncompressedSize found");\r
+                return false;\r
+                }\r
+            }//bit 3 was set\r
+        //break;\r
+\r
+        std::vector<unsigned char> uncompBuf;\r
+        switch (compressionMethod)\r
+            {\r
+            case 8: //deflate\r
+                {\r
+                Inflater inflater;\r
+                if (!inflater.inflate(uncompBuf, compBuf))\r
+                    {\r
+                    return false;\r
+                    }\r
+                break;\r
+                }\r
+            default:\r
+                {\r
+                error("Unimplemented compression method %d", compressionMethod);\r
+                return false;\r
+                }\r
+            }\r
+\r
+        ZipEntry *ze = new ZipEntry(fileName, comment);\r
+        ze->setCompressionMethod(compressionMethod);\r
+        ze->setCompressedData(compBuf);\r
+        ze->setUncompressedData(uncompBuf);\r
+        entries.push_back(ze);\r
+\r
+\r
+        }\r
+    return true;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipFile::readCentralDirectory()\r
+{\r
+    //printf("#################################################\n");\r
+    //printf("###D I R E C T O R Y\n");\r
+    //printf("#################################################\n");\r
+    while (true)\r
+        {\r
+        //We start with a central directory cookie already\r
+        //Check at the bottom of the loop.\r
+        unsigned int version;\r
+        if (!getInt(&version))\r
+            {\r
+            error("bad version found");\r
+            return false;\r
+            }\r
+        unsigned int versionNeeded;\r
+        if (!getInt(&versionNeeded))\r
+            {\r
+            error("bad version found");\r
+            return false;\r
+            }\r
+        unsigned int gpBitFlag;\r
+        if (!getInt(&gpBitFlag))\r
+            {\r
+            error("bad bit flag found");\r
+            return false;\r
+            }\r
+        unsigned int compressionMethod;\r
+        if (!getInt(&compressionMethod))\r
+            {\r
+            error("bad compressionMethod found");\r
+            return false;\r
+            }\r
+        unsigned int modTime;\r
+        if (!getInt(&modTime))\r
+            {\r
+            error("bad modTime found");\r
+            return false;\r
+            }\r
+        unsigned int modDate;\r
+        if (!getInt(&modDate))\r
+            {\r
+            error("bad modDate found");\r
+            return false;\r
+            }\r
+        unsigned long crc32;\r
+        if (!getLong(&crc32))\r
+            {\r
+            error("bad crc32 found");\r
+            return false;\r
+            }\r
+        unsigned long compressedSize;\r
+        if (!getLong(&compressedSize))\r
+            {\r
+            error("bad compressedSize found");\r
+            return false;\r
+            }\r
+        unsigned long uncompressedSize;\r
+        if (!getLong(&uncompressedSize))\r
+            {\r
+            error("bad uncompressedSize found");\r
+            return false;\r
+            }\r
+        unsigned int fileNameLength;\r
+        if (!getInt(&fileNameLength))\r
+            {\r
+            error("bad fileNameLength found");\r
+            return false;\r
+            }\r
+        unsigned int extraFieldLength;\r
+        if (!getInt(&extraFieldLength))\r
+            {\r
+            error("bad extraFieldLength found");\r
+            return false;\r
+            }\r
+        unsigned int fileCommentLength;\r
+        if (!getInt(&fileCommentLength))\r
+            {\r
+            error("bad fileCommentLength found");\r
+            return false;\r
+            }\r
+        unsigned int diskNumberStart;\r
+        if (!getInt(&diskNumberStart))\r
+            {\r
+            error("bad diskNumberStart found");\r
+            return false;\r
+            }\r
+        unsigned int internalFileAttributes;\r
+        if (!getInt(&internalFileAttributes))\r
+            {\r
+            error("bad internalFileAttributes found");\r
+            return false;\r
+            }\r
+        unsigned long externalFileAttributes;\r
+        if (!getLong(&externalFileAttributes))\r
+            {\r
+            error("bad externalFileAttributes found");\r
+            return false;\r
+            }\r
+        unsigned long localHeaderOffset;\r
+        if (!getLong(&localHeaderOffset))\r
+            {\r
+            error("bad localHeaderOffset found");\r
+            return false;\r
+            }\r
+        std::string fileName;\r
+        for (unsigned int i=0 ; i<fileNameLength ; i++)\r
+            {\r
+            unsigned char ch;\r
+            if (!getByte(&ch))\r
+                break;\r
+            fileName.push_back(ch);\r
+            }\r
+        std::string extraField;\r
+        for (unsigned int i=0 ; i<extraFieldLength ; i++)\r
+            {\r
+            unsigned char ch;\r
+            if (!getByte(&ch))\r
+                break;\r
+            extraField.push_back(ch);\r
+            }\r
+        std::string fileComment;\r
+        for (unsigned int i=0 ; i<fileCommentLength ; i++)\r
+            {\r
+            unsigned char ch;\r
+            if (!getByte(&ch))\r
+                break;\r
+            fileComment.push_back(ch);\r
+            }\r
+        trace("######################### ENTRY");\r
+        trace("FileName           :%s" , fileName.c_str());\r
+        trace("Extra field        :%s" , extraField.c_str());\r
+        trace("File comment       :%s" , fileComment.c_str());\r
+        trace("Version            :%d" , version);\r
+        trace("Version needed     :%d" , versionNeeded);\r
+        trace("Bitflag            :%d" , gpBitFlag);\r
+        trace("Compression Method :%d" , compressionMethod);\r
+        trace("Mod time           :%d" , modTime);\r
+        trace("Mod date           :%d" , modDate);\r
+        trace("CRC                :%lx", crc32);\r
+        trace("Compressed size    :%ld", compressedSize);\r
+        trace("Uncompressed size  :%ld", uncompressedSize);\r
+        trace("Disk nr start      :%ld", diskNumberStart);\r
+        trace("Header offset      :%ld", localHeaderOffset);\r
+\r
+\r
+        unsigned long magicCookie;\r
+        if (!getLong(&magicCookie))\r
+            {\r
+            error("magic cookie not found");\r
+            return false;\r
+            }\r
+        trace("###Cookie:%lx", magicCookie);\r
+        if (magicCookie  == 0x06054b50L) //end of central directory\r
+            break;\r
+        else if (magicCookie == 0x05054b50L) //signature\r
+            {\r
+            //## Digital Signature\r
+            unsigned int signatureSize;\r
+            if (!getInt(&signatureSize))\r
+                {\r
+                error("bad signatureSize found");\r
+                return false;\r
+                }\r
+            std::string digitalSignature;\r
+            for (unsigned int i=0 ; i<signatureSize ; i++)\r
+                {\r
+                unsigned char ch;\r
+                if (!getByte(&ch))\r
+                    break;\r
+                digitalSignature.push_back(ch);\r
+                }\r
+            trace("######## SIGNATURE :'%s'" , digitalSignature.c_str());\r
+            }\r
+        else if (magicCookie != 0x02014b50L) //central directory\r
+            {\r
+            error("directory file header not found");\r
+            return false;\r
+            }\r
+        }\r
+\r
+    unsigned int diskNr;\r
+    if (!getInt(&diskNr))\r
+        {\r
+        error("bad diskNr found");\r
+        return false;\r
+        }\r
+    unsigned int diskWithCd;\r
+    if (!getInt(&diskWithCd))\r
+        {\r
+        error("bad diskWithCd found");\r
+        return false;\r
+        }\r
+    unsigned int nrEntriesDisk;\r
+    if (!getInt(&nrEntriesDisk))\r
+        {\r
+        error("bad nrEntriesDisk found");\r
+        return false;\r
+        }\r
+    unsigned int nrEntriesTotal;\r
+    if (!getInt(&nrEntriesTotal))\r
+        {\r
+        error("bad nrEntriesTotal found");\r
+        return false;\r
+        }\r
+    unsigned long cdSize;\r
+    if (!getLong(&cdSize))\r
+        {\r
+        error("bad cdSize found");\r
+        return false;\r
+        }\r
+    unsigned long cdPos;\r
+    if (!getLong(&cdPos))\r
+        {\r
+        error("bad cdPos found");\r
+        return false;\r
+        }\r
+    unsigned int commentSize;\r
+    if (!getInt(&commentSize))\r
+        {\r
+        error("bad commentSize found");\r
+        return false;\r
+        }\r
+    comment = "";\r
+    for (unsigned int i=0 ; i<commentSize ; i++)\r
+        {\r
+        unsigned char ch;\r
+        if (!getByte(&ch))\r
+            break;\r
+        comment.push_back(ch);\r
+        }\r
+    trace("######## Zip Comment :'%s'" , comment.c_str());\r
+\r
+    return true;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipFile::read()\r
+{\r
+    fileBufPos = 0;\r
+    if (!readFileData())\r
+        {\r
+        return false;\r
+        }\r
+    if (!readCentralDirectory())\r
+        {\r
+        return false;\r
+        }\r
+    return true;\r
+}\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipFile::readBuffer(const std::vector<unsigned char> &inbuf)\r
+{\r
+    fileBuf = inbuf;\r
+    if (!read())\r
+        return false;\r
+    return true;\r
+}\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+bool ZipFile::readFile(const std::string &fileName)\r
+{\r
+    fileBuf.clear();\r
+    FILE *f = fopen(fileName.c_str(), "rb");\r
+    if (!f)\r
+        return false;\r
+    while (true)\r
+        {\r
+        int ch = fgetc(f);\r
+        if (ch < 0)\r
+            break;\r
+        fileBuf.push_back(ch);\r
+        }\r
+    fclose(f);\r
+    if (!read())\r
+        return false;\r
+    return true;\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+//########################################################################\r
+//#  E N D    O F    F I L E\r
+//########################################################################\r
+\r
+\r
diff --git a/src/dom/ziptool.h b/src/dom/ziptool.h
new file mode 100644 (file)
index 0000000..ad2f1dc
--- /dev/null
@@ -0,0 +1,539 @@
+#ifndef __ZIPTOOL_H__\r
+#define __ZIPTOOL_H__\r
+/**\r
+ * This is intended to be a standalone, reduced capability\r
+ * implementation of Gzip and Zip functionality.  Its\r
+ * targeted use case is for archiving and retrieving single files\r
+ * which use these encoding types.  Being memory based and\r
+ * non-optimized, it is not useful in cases where very large\r
+ * archives are needed or where high performance is desired.\r
+ * However, it should hopefully work well for smaller,\r
+ * one-at-a-time tasks.  What you get in return is the ability\r
+ * to drop these files into your project and remove the dependencies\r
+ * on ZLib and Info-Zip.  Enjoy.\r
+ *\r
+ * Authors:\r
+ *   Bob Jamison\r
+ *\r
+ * Copyright (C) 2006 Bob Jamison\r
+ *\r
+ *  This library is free software; you can redistribute it and/or\r
+ *  modify it under the terms of the GNU Lesser General Public\r
+ *  License as published by the Free Software Foundation; either\r
+ *  version 2.1 of the License, or (at your option) any later version.\r
+ *\r
+ *  This library is distributed in the hope that it will be useful,\r
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+ *  Lesser General Public License for more details.\r
+ *\r
+ *  You should have received a copy of the GNU Lesser General Public\r
+ *  License along with this library; if not, write to the Free Software\r
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
+ */\r
+\r
+#define MAX_BITS 8\r
+\r
+#include <vector>\r
+#include <string>\r
+\r
+\r
+//########################################################################\r
+//#  A D L E R  3 2\r
+//########################################################################\r
+\r
+class Adler32\r
+{\r
+public:\r
+\r
+    Adler32();\r
+\r
+    virtual ~Adler32();\r
+\r
+    void reset();\r
+\r
+    void update(unsigned char b);\r
+\r
+    void update(char *str);\r
+\r
+    unsigned long getValue();\r
+\r
+private:\r
+\r
+    unsigned long value;\r
+\r
+};\r
+\r
+\r
+//########################################################################\r
+//#  C R C  3 2\r
+//########################################################################\r
+\r
+class Crc32\r
+{\r
+public:\r
+\r
+    Crc32();\r
+\r
+    virtual ~Crc32();\r
+\r
+    void reset();\r
+\r
+    void update(unsigned char b);\r
+\r
+    void update(char *str);\r
+\r
+    void update(const std::vector<unsigned char> &buf);\r
+\r
+    unsigned long getValue();\r
+\r
+private:\r
+\r
+    unsigned long value;\r
+\r
+};\r
+\r
+\r
+\r
+\r
+\r
+\r
+//########################################################################\r
+//#  G Z I P    S T R E A M S\r
+//########################################################################\r
+\r
+class GzipFile\r
+{\r
+public:\r
+\r
+    /**\r
+     *\r
+     */\r
+    GzipFile();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual ~GzipFile();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual void put(unsigned char ch);\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual void setData(const std::vector<unsigned char> &str);\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual void clearData();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual std::vector<unsigned char> &getData();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual std::string &getFileName();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual void setFileName(const std::string &val);\r
+\r
+\r
+    //######################\r
+    //# U T I L I T Y\r
+    //######################\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual bool readFile(const std::string &fName);\r
+\r
+    //######################\r
+    //# W R I T E\r
+    //######################\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual bool write();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual bool writeBuffer(std::vector<unsigned char> &outbuf);\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual bool writeFile(const std::string &fileName);\r
+\r
+\r
+    //######################\r
+    //# R E A D\r
+    //######################\r
+\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual bool read();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual bool readBuffer(const std::vector<unsigned char> &inbuf);\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual bool loadFile(const std::string &fileName);\r
+\r
+\r
+\r
+private:\r
+\r
+    std::vector<unsigned char> data;\r
+    std::string fileName;\r
+\r
+    //debug messages\r
+    void error(char *fmt, ...);\r
+    void trace(char *fmt, ...);\r
+\r
+    unsigned long crc;\r
+\r
+    std::vector<unsigned char> fileBuf;\r
+    unsigned long fileBufPos;\r
+\r
+    bool getByte(unsigned char *ch);\r
+    bool getLong(unsigned long *val);\r
+\r
+    bool putByte(unsigned char ch);\r
+    bool putLong(unsigned long val);\r
+};\r
+\r
+\r
+\r
+\r
+//########################################################################\r
+//#  Z I P    F I L E\r
+//########################################################################\r
+\r
+\r
+/**\r
+ *\r
+ */\r
+class ZipEntry\r
+{\r
+public:\r
+\r
+    /**\r
+     *\r
+     */\r
+    ZipEntry();\r
+\r
+    /**\r
+     *\r
+     */\r
+    ZipEntry(const std::string &fileName,\r
+             const std::string &comment);\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual ~ZipEntry();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual std::string getFileName();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual void setFileName(const std::string &val);\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual std::string getComment();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual void setComment(const std::string &val);\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual unsigned long getCompressedSize();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual int getCompressionMethod();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual void setCompressionMethod(int val);\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual std::vector<unsigned char> &getCompressedData();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual void setCompressedData(const std::vector<unsigned char> &val);\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual unsigned long getUncompressedSize();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual std::vector<unsigned char> &getUncompressedData();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual void setUncompressedData(const std::vector<unsigned char> &val);\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual void write(unsigned char ch);\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual void finish();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual unsigned long getCrc();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual bool readFile(const std::string &fileNameArg,\r
+                          const std::string &commentArg);\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual void setPosition(unsigned long val);\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual unsigned long getPosition();\r
+\r
+private:\r
+\r
+    unsigned long crc;\r
+\r
+    std::string fileName;\r
+    std::string comment;\r
+\r
+    int compressionMethod;\r
+\r
+    std::vector<unsigned char> compressedData;\r
+    std::vector<unsigned char> uncompressedData;\r
+\r
+    unsigned long position;\r
+};\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+/**\r
+ * This class sits over the zlib and gzip code to\r
+ * implement a PKWare or Info-Zip .zip file reader and\r
+ * writer\r
+ */\r
+class ZipFile\r
+{\r
+public:\r
+\r
+    /**\r
+     *\r
+     */\r
+    ZipFile();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual ~ZipFile();\r
+\r
+    //######################\r
+    //# V A R I A B L E S\r
+    //######################\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual void setComment(const std::string &val);\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual std::string getComment();\r
+\r
+    /**\r
+     * Return the list of entries currently in this file\r
+     */\r
+    std::vector<ZipEntry *> &getEntries();\r
+\r
+\r
+    //######################\r
+    //# U T I L I T Y\r
+    //######################\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual bool addFile(const std::string &fileNameArg,\r
+                         const std::string &commentArg);\r
+\r
+    //######################\r
+    //# W R I T E\r
+    //######################\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual bool write();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual bool writeBuffer(std::vector<unsigned char> &outbuf);\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual bool writeFile(const std::string &fileName);\r
+\r
+\r
+    //######################\r
+    //# R E A D\r
+    //######################\r
+\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual bool read();\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual bool readBuffer(const std::vector<unsigned char> &inbuf);\r
+\r
+    /**\r
+     *\r
+     */\r
+    virtual bool readFile(const std::string &fileName);\r
+\r
+\r
+private:\r
+\r
+    //debug messages\r
+    void error(char *fmt, ...);\r
+    void trace(char *fmt, ...);\r
+\r
+    //# Private writing methods\r
+\r
+    /**\r
+     *\r
+     */\r
+    bool putLong(unsigned long val);\r
+\r
+    /**\r
+     *\r
+     */\r
+    bool putInt(unsigned int val);\r
+\r
+\r
+    /**\r
+     *\r
+     */\r
+    bool putByte(unsigned char val);\r
+\r
+    /**\r
+     *\r
+     */\r
+    bool writeFileData();\r
+\r
+    /**\r
+     *\r
+     */\r
+    bool writeCentralDirectory();\r
+\r
+\r
+    //# Private reading methods\r
+\r
+    /**\r
+     *\r
+     */\r
+    bool getLong(unsigned long *val);\r
+\r
+    /**\r
+     *\r
+     */\r
+    bool getInt(unsigned int *val);\r
+\r
+    /**\r
+     *\r
+     */\r
+    bool getByte(unsigned char *val);\r
+\r
+    /**\r
+     *\r
+     */\r
+    bool readFileData();\r
+\r
+    /**\r
+     *\r
+     */\r
+    bool readCentralDirectory();\r
+\r
+\r
+    std::vector<ZipEntry *> entries;\r
+\r
+    std::vector<unsigned char> fileBuf;\r
+    unsigned long fileBufPos;\r
+\r
+    std::string comment;\r
+};\r
+\r
+\r
+\r
+\r
+\r
+\r
+#endif /* __ZIPTOOL_H__ */\r
+\r
+\r
+//########################################################################\r
+//#  E N D    O F    F I L E\r
+//########################################################################\r
+\r