summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 7dd4081)
raw | patch | inline | side by side (parent: 7dd4081)
author | ishmal <ishmal@users.sourceforge.net> | |
Mon, 10 Apr 2006 01:03:56 +0000 (01:03 +0000) | ||
committer | ishmal <ishmal@users.sourceforge.net> | |
Mon, 10 Apr 2006 01:03:56 +0000 (01:03 +0000) |
src/dom/ziptool.cpp | [new file with mode: 0644] | patch | blob |
src/dom/ziptool.h | [new file with mode: 0644] | patch | blob |
diff --git a/src/dom/ziptool.cpp b/src/dom/ziptool.cpp
--- /dev/null
+++ b/src/dom/ziptool.cpp
@@ -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(<ime))\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
--- /dev/null
+++ b/src/dom/ziptool.h
@@ -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