Code

change API: separate functions creating a blur filter, one for a given item, another...
[inkscape.git] / src / dom / util / ziptool.cpp
1 /**
2  * This is intended to be a standalone, reduced capability
3  * implementation of Gzip and Zip functionality.  Its
4  * targeted use case is for archiving and retrieving single files
5  * which use these encoding types.  Being memory based and
6  * non-optimized, it is not useful in cases where very large
7  * archives are needed or where high performance is desired.
8  * However, it should hopefully work very well for smaller,
9  * one-at-a-time tasks.  What you get in return is the ability
10  * to drop these files into your project and remove the dependencies
11  * on ZLib and Info-Zip.  Enjoy.
12  *
13  * Authors:
14  *   Bob Jamison
15  *
16  * Copyright (C) 2006 Bob Jamison
17  *
18  *  This library is free software; you can redistribute it and/or
19  *  modify it under the terms of the GNU Lesser General Public
20  *  License as published by the Free Software Foundation; either
21  *  version 2.1 of the License, or (at your option) any later version.
22  *
23  *  This library is distributed in the hope that it will be useful,
24  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
25  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26  *  Lesser General Public License for more details.
27  *
28  *  You should have received a copy of the GNU Lesser General Public
29  *  License along with this library; if not, write to the Free Software
30  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
31  */
34 #include <stdio.h>
35 #include <stdarg.h>
36 #include <time.h>
38 #include <string>
40 #include "ziptool.h"
47 //########################################################################
48 //#  A D L E R  3 2
49 //########################################################################
51 /**
52  * Constructor
53  */
54 Adler32::Adler32()
55 {
56     reset();
57 }
59 /**
60  * Destructor
61  */
62 Adler32::~Adler32()
63 {
64 }
66 /**
67  * Reset Adler-32 checksum to initial value.
68  */
69 void Adler32::reset()
70 {
71     value = 1;
72 }
74 // ADLER32_BASE is the largest prime number smaller than 65536
75 #define ADLER32_BASE 65521
77 void Adler32::update(unsigned char b)
78 {
79     unsigned long s1 = value & 0xffff;
80     unsigned long s2 = (value >> 16) & 0xffff;
81     s1 += b & 0xff;
82     s2 += s1;
83     value = ((s2 % ADLER32_BASE) << 16) | (s1 % ADLER32_BASE);
84 }
86 void Adler32::update(char *str)
87 {
88     if (str)
89         while (*str)
90             update((unsigned char)*str++);
91 }
94 /**
95  * Returns current checksum value.
96  */
97 unsigned long Adler32::getValue()
98 {
99     return value & 0xffffffffL;
104 //########################################################################
105 //#  C R C  3 2
106 //########################################################################
108 /**
109  * Constructor
110  */
111 Crc32::Crc32()
113     reset();
116 /**
117  * Destructor
118  */
119 Crc32::~Crc32()
123 static bool crc_table_ready = false;
124 static unsigned long crc_table[256];
126 /**
127  * make the table for a fast CRC.
128  */
129 void makeCrcTable()
131     if (crc_table_ready)
132         return;
133     for (int n = 0; n < 256; n++)
134         {
135         unsigned long c = n;
136         for (int k = 8;  --k >= 0; )
137             {
138             if ((c & 1) != 0)
139                 c = 0xedb88320 ^ (c >> 1);
140             else
141                 c >>= 1;
142             }
143         crc_table[n] = c;
144         }
145     crc_table_ready = true;
149 /**
150  * Reset CRC-32 checksum to initial value.
151  */
152 void Crc32::reset()
154     value = 0;
155     makeCrcTable();
158 void Crc32::update(unsigned char b)
160     unsigned long c = ~value;
161     c = crc_table[(c ^ b) & 0xff] ^ (c >> 8);
162     value = ~c;
166 void Crc32::update(char *str)
168     if (str)
169         while (*str)
170             update((unsigned char)*str++);
173 void Crc32::update(const std::vector<unsigned char> &buf)
175     std::vector<unsigned char>::const_iterator iter;
176     for (iter=buf.begin() ; iter!=buf.end() ; iter++)
177         {
178         unsigned char ch = *iter;
179         update(ch);
180         }
184 /**
185  * Returns current checksum value.
186  */
187 unsigned long Crc32::getValue()
189     return value & 0xffffffffL;
192 //########################################################################
193 //#  I N F L A T E R
194 //########################################################################
197 /**
198  *
199  */
200 typedef struct
202     int *count;  // number of symbols of each length
203     int *symbol; // canonically ordered symbols
204 } Huffman;
206 /**
207  *
208  */
209 class Inflater
211 public:
213     Inflater();
215     virtual ~Inflater();
217     static const int MAXBITS   =  15; // max bits in a code
218     static const int MAXLCODES = 286; // max number of literal/length codes
219     static const int MAXDCODES =  30; // max number of distance codes
220     static const int MAXCODES  = 316; // max codes lengths to read
221     static const int FIXLCODES = 288; // number of fixed literal/length codes
223     /**
224      *
225      */
226     bool inflate(std::vector<unsigned char> &destination,
227                  std::vector<unsigned char> &source);
229 private:
231     /**
232      *
233      */
234     void error(char *fmt, ...);
236     /**
237      *
238      */
239     void trace(char *fmt, ...);
241     /**
242      *
243      */
244     void dump();
246     /**
247      *
248      */
249     int buildHuffman(Huffman *h, int *length, int n);
251     /**
252      *
253      */
254     bool getBits(int need, int *oval);
256     /**
257      *
258      */
259     int doDecode(Huffman *h);
261     /**
262      *
263      */
264     bool doCodes(Huffman *lencode, Huffman *distcode);
266     /**
267      *
268      */
269     bool doStored();
271     /**
272      *
273      */
274     bool doFixed();
276     /**
277      *
278      */
279     bool doDynamic();
282     std::vector<unsigned char>dest;
284     std::vector<unsigned char>src;
285     unsigned long srcPos;  //current read position
286     int bitBuf;
287     int bitCnt;
289 };
292 /**
293  *
294  */
295 Inflater::Inflater()
299 /**
300  *
301  */
302 Inflater::~Inflater()
306 /**
307  *
308  */
309 void Inflater::error(char *fmt, ...)
311     va_list args;
312     va_start(args, fmt);
313     fprintf(stdout, "Inflater error:");
314     vfprintf(stdout, fmt, args);
315     fprintf(stdout, "\n");
316     va_end(args);
319 /**
320  *
321  */
322 void Inflater::trace(char *fmt, ...)
324     va_list args;
325     va_start(args, fmt);
326     fprintf(stdout, "Inflater:");
327     vfprintf(stdout, fmt, args);
328     fprintf(stdout, "\n");
329     va_end(args);
333 /**
334  *
335  */
336 void Inflater::dump()
338     for (unsigned int i=0 ; i<dest.size() ; i++)
339         {
340         fputc(dest[i], stdout);
341         }
344 /**
345  *
346  */
347 int Inflater::buildHuffman(Huffman *h, int *length, int n)
349     // count number of codes of each length
350     for (int len = 0; len <= MAXBITS; len++)
351         h->count[len] = 0;
352     for (int symbol = 0; symbol < n; symbol++)
353         (h->count[length[symbol]])++;   // assumes lengths are within bounds
354     if (h->count[0] == n)               // no codes!
355         {
356         error("huffman tree will result in failed decode");
357         return -1;
358         }
360     // check for an over-subscribed or incomplete set of lengths
361     int left = 1;                // number of possible codes left of current length
362     for (int len = 1; len <= MAXBITS; len++)
363         {
364         left <<= 1;                     // one more bit, double codes left
365         left -= h->count[len];          // deduct count from possible codes
366         if (left < 0)
367             {
368             error("huffman over subscribed");
369             return -1;
370             }
371         }
373     // generate offsets into symbol table for each length for sorting
374     int offs[MAXBITS+1]; //offsets in symbol table for each length
375     offs[1] = 0;
376     for (int len = 1; len < MAXBITS; len++)
377         offs[len + 1] = offs[len] + h->count[len];
379     /*
380      * put symbols in table sorted by length, by symbol order within each
381      * length
382      */
383     for (int symbol = 0; symbol < n; symbol++)
384         if (length[symbol] != 0)
385             h->symbol[offs[length[symbol]]++] = symbol;
387     // return zero for complete set, positive for incomplete set
388     return left;
392 /**
393  *
394  */
395 bool Inflater::getBits(int requiredBits, int *oval)
397     long val = bitBuf;
399     //add more bytes if needed
400     while (bitCnt < requiredBits)
401         {
402         if (srcPos >= src.size())
403             {
404             error("premature end of input");
405             return false;
406             }
407         val |= ((long)(src[srcPos++])) << bitCnt;
408         bitCnt += 8;
409         }
411     //update the buffer and return the data
412     bitBuf =  (int)(val >> requiredBits);
413     bitCnt -= requiredBits;
414     *oval = (int)(val & ((1L << requiredBits) - 1));
416     return true;
420 /**
421  *
422  */
423 int Inflater::doDecode(Huffman *h)
425     int bitTmp  = bitBuf;
426     int left    = bitCnt;
427     int code    = 0;
428     int first   = 0;
429     int index   = 0;
430     int len     = 1;
431     int *next = h->count + 1;
432     while (true)
433         {
434         while (left--)
435             {
436             code   |=  bitTmp & 1;
437             bitTmp >>= 1;
438             int count  =   *next++;
439             if (code < first + count)
440                 { /* if length len, return symbol */
441                 bitBuf = bitTmp;
442                 bitCnt = (bitCnt - len) & 7;
443                 return h->symbol[index + (code - first)];
444                 }
445             index +=  count;
446             first +=  count;
447             first <<= 1;
448             code  <<= 1;
449             len++;
450             }
451         left = (MAXBITS+1) - len;
452         if (left == 0)
453             break;
454         if (srcPos >= src.size())
455             {
456             error("premature end of input");
457             dump();
458             return -1;
459             }
460         bitTmp = src[srcPos++];
461         if (left > 8)
462             left = 8;
463         }
465     error("no end of block found");
466     return -1;
469 /**
470  *
471  */
472 bool Inflater::doCodes(Huffman *lencode, Huffman *distcode)
474     static const int lens[29] = { // Size base for length codes 257..285
475         3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
476         35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
477     static const int lext[29] = { // Extra bits for length codes 257..285
478         0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
479         3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
480     static const int dists[30] = { // Offset base for distance codes 0..29
481         1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
482         257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
483         8193, 12289, 16385, 24577};
484     static const int dext[30] = { // Extra bits for distance codes 0..29
485         0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
486         7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
487         12, 12, 13, 13};
489     //decode literals and length/distance pairs
490     while (true)
491         {
492         int symbol = doDecode(lencode);
493         if (symbol == 256)
494             break;
495         if (symbol < 0)
496             {
497             return false;
498             }
499         if (symbol < 256) //literal
500             {
501             dest.push_back(symbol);
502             }
503         else if (symbol > 256)//length
504             {
505             symbol -= 257;
506             if (symbol >= 29)
507                 {
508                 error("invalid fixed code");
509                 return false;
510                 }
511             int ret;
512             if (!getBits(lext[symbol], &ret))
513                 return false;
514             int len = lens[symbol] + ret;
516             symbol = doDecode(distcode);//distance
517             if (symbol < 0)
518                 {
519                 return false;
520                 }
522             if (!getBits(dext[symbol], &ret))
523                 return false;
524             unsigned int dist = dists[symbol] + ret;
525             if (dist > dest.size())
526                 {
527                 error("distance too far back %d/%d", dist, dest.size());
528                 dump();
529                 //printf("pos:%d\n", srcPos);
530                 return false;
531                 }
533             // copy length bytes from distance bytes back
534             //dest.push_back('{');
535             while (len--)
536                 {
537                 dest.push_back(dest[dest.size() - dist]);
538                 }
539             //dest.push_back('}');
541             }
542         }
544     return true;
547 /**
548  */
549 bool Inflater::doStored()
551     //trace("### stored ###");
553     // clear bits from current byte
554     bitBuf = 0;
555     bitCnt = 0;
557     // length
558     if (srcPos + 4 > src.size())
559         {
560         error("not enough input");
561         return false;
562         }
564     int len = src[srcPos++];
565     len |= src[srcPos++] << 8;
566     //trace("### len:%d", len);
567     // check complement
568     if (src[srcPos++] != (~len & 0xff) ||
569         src[srcPos++] != ((~len >> 8) & 0xff))
570         {
571         error("twos complement for storage size do not match");
572         return false;
573         }
575     // copy data
576     if (srcPos + len > src.size())
577         {
578         error("Not enough input for stored block");
579         return false;
580         }
581     while (len--)
582         dest.push_back(src[srcPos++]);
584     return true;
587 /**
588  */
589 bool Inflater::doFixed()
591     //trace("### fixed ###");
593     static bool firstTime = true;
594     static int lencnt[MAXBITS+1], lensym[FIXLCODES];
595     static int distcnt[MAXBITS+1], distsym[MAXDCODES];
596     static Huffman lencode = {lencnt, lensym};
597     static Huffman distcode = {distcnt, distsym};
599     if (firstTime)
600         {
601         firstTime = false;
603         int lengths[FIXLCODES];
605         // literal/length table
606         int symbol = 0;
607         for ( ; symbol < 144; symbol++)
608             lengths[symbol] = 8;
609         for ( ; symbol < 256; symbol++)
610             lengths[symbol] = 9;
611         for ( ; symbol < 280; symbol++)
612             lengths[symbol] = 7;
613         for ( ; symbol < FIXLCODES; symbol++)
614             lengths[symbol] = 8;
615         buildHuffman(&lencode, lengths, FIXLCODES);
617         // distance table
618         for (int symbol = 0; symbol < MAXDCODES; symbol++)
619             lengths[symbol] = 5;
620         buildHuffman(&distcode, lengths, MAXDCODES);
621         }
623     // decode data until end-of-block code
624     bool ret = doCodes(&lencode, &distcode);
625     return ret;
628 /**
629  */
630 bool Inflater::doDynamic()
632     //trace("### dynamic ###");
633     int lengths[MAXCODES];                      // descriptor code lengths
634     int lencnt[MAXBITS+1], lensym[MAXLCODES];   // lencode memory
635     int distcnt[MAXBITS+1], distsym[MAXDCODES]; // distcode memory
636     Huffman lencode  = {lencnt, lensym};          // length code
637     Huffman distcode = {distcnt, distsym};        // distance code
638     static const int order[19] =                // permutation of code length codes
639         {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
641     // get number of lengths in each table, check lengths
642     int ret;
643     if (!getBits(5, &ret))
644         return false;
645     int nlen  = ret + 257;
646     if (!getBits(5, &ret))
647         return false;
648     int ndist = ret + 1;
649     if (!getBits(4, &ret))
650         return false;
651     int ncode = ret + 4;
652     if (nlen > MAXLCODES || ndist > MAXDCODES)
653         {
654         error("Bad codes");
655         return false;
656         }
658     // get code length code lengths
659     int index = 0;
660     for ( ; index < ncode; index++)
661         {
662         if (!getBits(3, &ret))
663             return false;
664         lengths[order[index]] = ret;
665         }
666     for ( ; index < 19; index++)
667         lengths[order[index]] = 0;
669     // build huffman table for code lengths codes
670     if (buildHuffman(&lencode, lengths, 19) != 0)
671         return false;
673     // read length/literal and distance code length tables
674     index = 0;
675     while (index < nlen + ndist)
676         {
677         int symbol = doDecode(&lencode);
678         if (symbol < 16)                // length in 0..15
679             lengths[index++] = symbol;
680         else
681             {                          // repeat instruction
682             int len = 0;               // assume repeating zeros
683             if (symbol == 16)
684                 {         // repeat last length 3..6 times
685                 if (index == 0)
686                     {
687                     error("no last length");
688                     return false;
689                     }
690                 len = lengths[index - 1];// last length
691                 if (!getBits(2, &ret))
692                     return false;
693                 symbol = 3 + ret;
694                 }
695             else if (symbol == 17)      // repeat zero 3..10 times
696                 {
697                 if (!getBits(3, &ret))
698                     return false;
699                 symbol = 3 + ret;
700                 }
701             else                        // == 18, repeat zero 11..138 times
702                 {
703                 if (!getBits(7, &ret))
704                     return false;
705                 symbol = 11 + ret;
706                 }
707             if (index + symbol > nlen + ndist)
708                 {
709                 error("too many lengths");
710                 return false;
711                 }
712             while (symbol--)            // repeat last or zero symbol times
713                 lengths[index++] = len;
714             }
715         }
717     // build huffman table for literal/length codes
718     int err = buildHuffman(&lencode, lengths, nlen);
719     if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1))
720         {
721         error("incomplete length codes");
722         //return false;
723         }
724     // build huffman table for distance codes
725     err = buildHuffman(&distcode, lengths + nlen, ndist);
726     if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1))
727         {
728         error("incomplete dist codes");
729         return false;
730         }
732     // decode data until end-of-block code
733     bool retn = doCodes(&lencode, &distcode);
734     return retn;
737 /**
738  */
739 bool Inflater::inflate(std::vector<unsigned char> &destination,
740                        std::vector<unsigned char> &source)
742     dest.clear();
743     src = source;
744     srcPos = 0;
745     bitBuf = 0;
746     bitCnt = 0;
748     while (true)
749         {
750         int last; // one if last block
751         if (!getBits(1, &last))
752             return false;
753         int type; // block type 0..3
754         if (!getBits(2, &type))
755             return false;
756         switch (type)
757             {
758             case 0:
759                 if (!doStored())
760                     return false;
761                 break;
762             case 1:
763                 if (!doFixed())
764                     return false;
765                 break;
766             case 2:
767                 if (!doDynamic())
768                     return false;
769                 break;
770             default:
771                 error("Unknown block type %d", type);
772                 return false;
773             }
774         if (last)
775             break;
776         }
778     destination = dest;
780     return true;
788 //########################################################################
789 //#  D E F L A T E R
790 //########################################################################
794 class Deflater
796 public:
798     /**
799      *
800      */
801     Deflater();
803     /**
804      *
805      */
806     virtual ~Deflater();
808     /**
809      *
810      */
811     virtual void reset();
813     /**
814      *
815      */
816     virtual bool update(int ch);
818     /**
819      *
820      */
821     virtual bool finish();
823     /**
824      *
825      */
826     virtual std::vector<unsigned char> &getCompressed();
828     /**
829      *
830      */
831     bool deflate(std::vector<unsigned char> &dest,
832                  const std::vector<unsigned char> &src);
834     void encodeDistStatic(unsigned int len, unsigned int dist);
836 private:
838     //debug messages
839     void error(char *fmt, ...);
840     void trace(char *fmt, ...);
842     bool compressWindow();
844     bool compress();
846     std::vector<unsigned char> uncompressed;
848     std::vector<unsigned char> window;
850     unsigned int windowPos;
852     std::vector<unsigned char> compressed;
854     //#### Output
855     unsigned int outputBitBuf;
856     unsigned int outputNrBits;
858     void put(int ch);
860     void putWord(int ch);
862     void putFlush();
864     void putBits(unsigned int ch, unsigned int bitsWanted);
866     void putBitsR(unsigned int ch, unsigned int bitsWanted);
868     //#### Huffman Encode
869     void encodeLiteralStatic(unsigned int ch);
871     unsigned char windowBuf[32768];
872     //assume 32-bit ints
873     unsigned int windowHashBuf[32768];
874 };
877 //########################################################################
878 //# A P I
879 //########################################################################
882 /**
883  *
884  */
885 Deflater::Deflater()
887     reset();
890 /**
891  *
892  */
893 Deflater::~Deflater()
898 /**
899  *
900  */
901 void Deflater::reset()
903     outputBitBuf = 0;
904     outputNrBits = 0;
905     window.clear();
906     compressed.clear();
907     uncompressed.clear();
910 /**
911  *
912  */
913 bool Deflater::update(int ch)
915     uncompressed.push_back((unsigned char)(ch & 0xff));
916     return true;
919 /**
920  *
921  */
922 bool Deflater::finish()
924     return compress();
927 /**
928  *
929  */
930 std::vector<unsigned char> &Deflater::getCompressed()
932     return compressed;
936 /**
937  *
938  */
939 bool Deflater::deflate(std::vector<unsigned char> &dest,
940                        const std::vector<unsigned char> &src)
942     reset();
943     uncompressed = src;
944     if (!compress())
945         return false;
946     dest = compressed;
947     return true;
956 //########################################################################
957 //# W O R K I N G    C O D E
958 //########################################################################
961 //#############################
962 //#  M E S S A G E S
963 //#############################
965 /**
966  *  Print error messages
967  */
968 void Deflater::error(char *fmt, ...)
970     va_list args;
971     va_start(args, fmt);
972     fprintf(stdout, "Deflater error:");
973     vfprintf(stdout, fmt, args);
974     fprintf(stdout, "\n");
975     va_end(args);
978 /**
979  *  Print trace messages
980  */
981 void Deflater::trace(char *fmt, ...)
983     va_list args;
984     va_start(args, fmt);
985     fprintf(stdout, "Deflater:");
986     vfprintf(stdout, fmt, args);
987     fprintf(stdout, "\n");
988     va_end(args);
994 //#############################
995 //#  O U T P U T
996 //#############################
998 /**
999  *
1000  */
1001 void Deflater::put(int ch)
1003     compressed.push_back(ch);
1004     outputBitBuf = 0;
1005     outputNrBits = 0;
1008 /**
1009  *
1010  */
1011 void Deflater::putWord(int ch)
1013     int lo = (ch   ) & 0xff;
1014     int hi = (ch>>8) & 0xff;
1015     put(lo);
1016     put(hi);
1019 /**
1020  *
1021  */
1022 void Deflater::putFlush()
1024     if (outputNrBits > 0)
1025         {
1026         put(outputBitBuf & 0xff);
1027         }
1028     outputBitBuf = 0;
1029     outputNrBits = 0;
1032 /**
1033  *
1034  */
1035 void Deflater::putBits(unsigned int ch, unsigned int bitsWanted)
1037     //trace("n:%4u, %d\n", ch, bitsWanted);
1039     while (bitsWanted--)
1040         {
1041         //add bits to position 7.  shift right
1042         outputBitBuf = (outputBitBuf>>1) + (ch<<7 & 0x80);
1043         ch >>= 1;
1044         outputNrBits++;
1045         if (outputNrBits >= 8)
1046             {
1047             unsigned char b = outputBitBuf & 0xff;
1048             //printf("b:%02x\n", b);
1049             put(b);
1050             }
1051         }
1054 static unsigned int bitReverse(unsigned int code, unsigned int nrBits)
1056     unsigned int outb = 0;
1057     while (nrBits--)
1058         {
1059         outb = (outb << 1) | (code & 0x01);
1060         code >>= 1;
1061         }
1062     return outb;
1066 /**
1067  *
1068  */
1069 void Deflater::putBitsR(unsigned int ch, unsigned int bitsWanted)
1071     //trace("r:%4u, %d", ch, bitsWanted);
1073     unsigned int rcode = bitReverse(ch, bitsWanted);
1075     putBits(rcode, bitsWanted);
1080 //#############################
1081 //#  E N C O D E
1082 //#############################
1086 void Deflater::encodeLiteralStatic(unsigned int ch)
1088     //trace("c: %d", ch);
1090     if (ch < 144)
1091         {
1092         putBitsR(ch + 0x0030 , 8); // 00110000
1093         }
1094     else if (ch < 256)
1095         {
1096         putBitsR(ch - 144 + 0x0190 , 9); // 110010000
1097         }
1098     else if (ch < 280)
1099         {
1100         putBitsR(ch - 256 + 0x0000 , 7); // 0000000
1101         }
1102     else if (ch < 288)
1103         {
1104         putBitsR(ch - 280 + 0x00c0 , 8); // 11000000
1105         }
1106     else //out of range
1107         {
1108         error("Literal out of range: %d", ch);
1109         }
1114 typedef struct
1116     unsigned int base;
1117     unsigned int range;
1118     unsigned int bits;
1119 } LenBase;
1121 LenBase lenBases[] =
1123     {   3,  1, 0 },
1124     {   4,  1, 0 },
1125     {   5,  1, 0 },
1126     {   6,  1, 0 },
1127     {   7,  1, 0 },
1128     {   8,  1, 0 },
1129     {   9,  1, 0 },
1130     {  10,  1, 0 },
1131     {  11,  2, 1 },
1132     {  13,  2, 1 },
1133     {  15,  2, 1 },
1134     {  17,  2, 1 },
1135     {  19,  4, 2 },
1136     {  23,  4, 2 },
1137     {  27,  4, 2 },
1138     {  31,  4, 2 },
1139     {  35,  8, 3 },
1140     {  43,  8, 3 },
1141     {  51,  8, 3 },
1142     {  59,  8, 3 },
1143     {  67, 16, 4 },
1144     {  83, 16, 4 },
1145     {  99, 16, 4 },
1146     { 115, 16, 4 },
1147     { 131, 32, 5 },
1148     { 163, 32, 5 },
1149     { 195, 32, 5 },
1150     { 227, 32, 5 },
1151     { 258,  1, 0 }
1152 };
1154 typedef struct
1156     unsigned int base;
1157     unsigned int range;
1158     unsigned int bits;
1159 } DistBase;
1161 DistBase distBases[] =
1163     {     1,    1,  0 },
1164     {     2,    1,  0 },
1165     {     3,    1,  0 },
1166     {     4,    1,  0 },
1167     {     5,    2,  1 },
1168     {     7,    2,  1 },
1169     {     9,    4,  2 },
1170     {    13,    4,  2 },
1171     {    17,    8,  3 },
1172     {    25,    8,  3 },
1173     {    33,   16,  4 },
1174     {    49,   16,  4 },
1175     {    65,   32,  5 },
1176     {    97,   32,  5 },
1177     {   129,   64,  6 },
1178     {   193,   64,  6 },
1179     {   257,  128,  7 },
1180     {   385,  128,  7 },
1181     {   513,  256,  8 },
1182     {   769,  256,  8 },
1183     {  1025,  512,  9 },
1184     {  1537,  512,  9 },
1185     {  2049, 1024, 10 },
1186     {  3073, 1024, 10 },
1187     {  4097, 2048, 11 },
1188     {  6145, 2048, 11 },
1189     {  8193, 4096, 12 },
1190     { 12289, 4096, 12 },
1191     { 16385, 8192, 13 },
1192     { 24577, 8192, 13 }
1193 };
1195 void Deflater::encodeDistStatic(unsigned int len, unsigned int dist)
1198     //## Output length
1200     if (len < 3 || len > 258)
1201         {
1202         error("Length out of range:%d", len);
1203         return;
1204         }
1206     bool found = false;
1207     for (int i=0 ; i<30 ; i++)
1208         {
1209         unsigned int base  = lenBases[i].base;
1210         unsigned int range = lenBases[i].range;
1211         if (base + range > len)
1212             {
1213             unsigned int lenCode = 257 + i;
1214             unsigned int length  = len - base;
1215             //trace("--- %d %d %d %d", len, base, range, length);
1216             encodeLiteralStatic(lenCode);
1217             putBits(length, lenBases[i].bits);
1218             found = true;
1219             break;
1220             }
1221         }
1222     if (!found)
1223         {
1224         error("Length not found in table:%d", len);
1225         return;
1226         }
1228     //## Output distance
1230     if (dist < 4 || dist > 32768)
1231         {
1232         error("Distance out of range:%d", dist);
1233         return;
1234         }
1236     found = false;
1237     for (int i=0 ; i<30 ; i++)
1238         {
1239         unsigned int base  = distBases[i].base;
1240         unsigned int range = distBases[i].range;
1241         if (base + range > dist)
1242             {
1243             unsigned int distCode = i;
1244             unsigned int distance = dist - base;
1245             //error("--- %d %d %d %d", dist, base, range, distance);
1246             putBitsR(distCode, 5);
1247             putBits(distance, distBases[i].bits);
1248             found = true;
1249             break;
1250             }
1251         }
1252     if (!found)
1253         {
1254         error("Distance not found in table:%d", dist);
1255         return;
1256         }
1260 //#############################
1261 //#  C O M P R E S S
1262 //#############################
1265 /**
1266  * This method does the dirty work of dictionary
1267  * compression.  Basically it looks for redundant
1268  * strings and has the current duplicate refer back
1269  * to the previous one.
1270  */
1271 bool Deflater::compressWindow()
1273     windowPos = 0;
1274     unsigned int windowSize = window.size();
1275     //### Compress as much of the window as possible
1277     unsigned int hash = 0;
1278     //Have each value be a long with the byte at this position,
1279     //plus the 3 bytes after it in the window
1280     for (int i=windowSize-1 ; i>=0 ; i--)
1281         {
1282         unsigned char ch = window[i];
1283         windowBuf[i] = ch;
1284         hash = ((hash<<8) & 0xffffff00) | ch;
1285         windowHashBuf[i] = hash;
1286         }
1288     while (windowPos < windowSize - 3)
1289         {
1290         //### Find best match, if any
1291         unsigned int bestMatchLen  = 0;
1292         unsigned int bestMatchDist = 0;
1293         if (windowPos >= 4)
1294             {
1295             for (unsigned int lookBack=0 ; lookBack<windowPos-4 ; lookBack++)
1296                 {
1297                 //Check 4-char hashes first, before continuing with string
1298                 if (windowHashBuf[lookBack] == windowHashBuf[windowPos])
1299                     {
1300                     unsigned int lookAhead=4;
1301                     unsigned int lookAheadMax = windowSize - 4 - windowPos;
1302                     if (lookBack + lookAheadMax >= windowPos -4 )
1303                         lookAheadMax = windowPos - 4 - lookBack;
1304                     if (lookAheadMax > 258)
1305                         lookAheadMax = 258;
1306                     unsigned char *wp = &(windowBuf[windowPos+4]);
1307                     unsigned char *lb = &(windowBuf[lookBack+4]);
1308                     while (lookAhead<lookAheadMax)
1309                         {
1310                         if (*lb++ != *wp++)
1311                             break;
1312                         lookAhead++;
1313                         }
1314                     if (lookAhead > bestMatchLen)
1315                         {
1316                         bestMatchLen  = lookAhead;
1317                         bestMatchDist = windowPos - lookBack;
1318                         }
1319                     }
1320                 }
1321             }
1322         if (bestMatchLen > 3)
1323             {
1324             //Distance encode
1325             //trace("### distance");
1326             /*
1327             printf("### 1 '");
1328             for (int i=0 ; i < bestMatchLen ; i++)
1329                 fputc(window[windowPos+i], stdout);
1330             printf("'\n### 2 '");
1331             for (int i=0 ; i < bestMatchLen ; i++)
1332                 fputc(window[windowPos-bestMatchDist+i], stdout);
1333             printf("'\n");
1334             */
1335             encodeDistStatic(bestMatchLen, bestMatchDist);
1336             windowPos += bestMatchLen;
1337             }
1338         else
1339             {
1340             //Literal encode
1341             //trace("### literal");
1342             encodeLiteralStatic(windowBuf[windowPos]);
1343             windowPos++;
1344             }
1345         }
1347     while (windowPos < windowSize)
1348         encodeLiteralStatic(windowBuf[windowPos++]);
1350     encodeLiteralStatic(256);
1351     return true;
1355 /**
1356  *
1357  */
1358 bool Deflater::compress()
1360     //trace("compress");
1361     unsigned long total = 0L;
1362     windowPos = 0;
1363     std::vector<unsigned char>::iterator iter;
1364     for (iter = uncompressed.begin(); iter != uncompressed.end() ; )
1365         {
1366         total += windowPos;
1367         trace("total:%ld", total);
1368         if (windowPos > window.size())
1369             windowPos = window.size();
1370         window.erase(window.begin() , window.begin()+windowPos);
1371         while (window.size() < 32768 && iter != uncompressed.end())
1372             {
1373             window.push_back(*iter);
1374             iter++;
1375             }
1376         if (window.size() >= 32768)
1377             putBits(0x00, 1); //0  -- more blocks
1378         else
1379             putBits(0x01, 1); //1  -- last block
1380         putBits(0x01, 2); //01 -- static trees
1381         if (!compressWindow())
1382             return false;
1383         }
1384     putFlush();
1385     return true;
1392 //########################################################################
1393 //#  G Z I P    F I L E
1394 //########################################################################
1396 /**
1397  * Constructor
1398  */
1399 GzipFile::GzipFile()
1403 /**
1404  * Destructor
1405  */
1406 GzipFile::~GzipFile()
1410 /**
1411  *  Print error messages
1412  */
1413 void GzipFile::error(char *fmt, ...)
1415     va_list args;
1416     va_start(args, fmt);
1417     fprintf(stdout, "GzipFile error:");
1418     vfprintf(stdout, fmt, args);
1419     fprintf(stdout, "\n");
1420     va_end(args);
1423 /**
1424  *  Print trace messages
1425  */
1426 void GzipFile::trace(char *fmt, ...)
1428     va_list args;
1429     va_start(args, fmt);
1430     fprintf(stdout, "GzipFile:");
1431     vfprintf(stdout, fmt, args);
1432     fprintf(stdout, "\n");
1433     va_end(args);
1436 /**
1437  *
1438  */
1439 void GzipFile::put(unsigned char ch)
1441     data.push_back(ch);
1444 /**
1445  *
1446  */
1447 void GzipFile::setData(const std::vector<unsigned char> &str)
1449     data = str;
1452 /**
1453  *
1454  */
1455 void GzipFile::clearData()
1457     data.clear();
1460 /**
1461  *
1462  */
1463 std::vector<unsigned char> &GzipFile::getData()
1465     return data;
1468 /**
1469  *
1470  */
1471 std::string &GzipFile::getFileName()
1473     return fileName;
1476 /**
1477  *
1478  */
1479 void GzipFile::setFileName(const std::string &val)
1481     fileName = val;
1486 //#####################################
1487 //# U T I L I T Y
1488 //#####################################
1490 /**
1491  *  Loads a new file into an existing GzipFile
1492  */
1493 bool GzipFile::loadFile(const std::string &fName)
1495     FILE *f = fopen(fName.c_str() , "rb");
1496     if (!f)
1497         {
1498         error("Cannot open file %s", fName.c_str());
1499         return false;
1500         }
1501     while (true)
1502         {
1503         int ch = fgetc(f);
1504         if (ch < 0)
1505             break;
1506         data.push_back(ch);
1507         }
1508     fclose(f);
1509     setFileName(fName);
1510     return true;
1515 //#####################################
1516 //# W R I T E
1517 //#####################################
1519 /**
1520  *
1521  */
1522 bool GzipFile::putByte(unsigned char ch)
1524     fileBuf.push_back(ch);
1525     return true;
1530 /**
1531  *
1532  */
1533 bool GzipFile::putLong(unsigned long val)
1535     fileBuf.push_back( (unsigned char)((val    ) & 0xff));
1536     fileBuf.push_back( (unsigned char)((val>> 8) & 0xff));
1537     fileBuf.push_back( (unsigned char)((val>>16) & 0xff));
1538     fileBuf.push_back( (unsigned char)((val>>24) & 0xff));
1539     return true;
1544 /**
1545  *
1546  */
1547 bool GzipFile::write()
1549     fileBuf.clear();
1551     putByte(0x1f); //magic
1552     putByte(0x8b); //magic
1553     putByte(   8); //compression method
1554     putByte(0x08); //flags.  say we have a crc and file name
1556     unsigned long ltime = (unsigned long) time(NULL);
1557     putLong(ltime);
1559     //xfl
1560     putByte(0);
1561     //OS
1562     putByte(0);
1564     //file name
1565     for (unsigned int i=0 ; i<fileName.size() ; i++)
1566         putByte(fileName[i]);
1567     putByte(0);
1570     //compress
1571     std::vector<unsigned char> compBuf;
1572     Deflater deflater;
1573     if (!deflater.deflate(compBuf, data))
1574         {
1575         return false;
1576         }
1578     std::vector<unsigned char>::iterator iter;
1579     for (iter=compBuf.begin() ; iter!=compBuf.end() ; iter++)
1580         {
1581         unsigned char ch = *iter;
1582         putByte(ch);
1583         }
1585     Crc32 crcEngine;
1586     crcEngine.update(data);
1587     unsigned long crc = crcEngine.getValue();
1588     putLong(crc);
1590     putLong(data.size());
1592     return true;
1596 /**
1597  *
1598  */
1599 bool GzipFile::writeBuffer(std::vector<unsigned char> &outBuf)
1601     if (!write())
1602         return false;
1603     outBuf.clear();
1604     outBuf = fileBuf;
1605     return true;
1609 /**
1610  *
1611  */
1612 bool GzipFile::writeFile(const std::string &fileName)
1614     if (!write())
1615         return false;
1616     FILE *f = fopen(fileName.c_str(), "wb");
1617     if (!f)
1618         return false;
1619     std::vector<unsigned char>::iterator iter;
1620     for (iter=fileBuf.begin() ; iter!=fileBuf.end() ; iter++)
1621         {
1622         unsigned char ch = *iter;
1623         fputc(ch, f);
1624         }
1625     fclose(f);
1626     return true;
1630 //#####################################
1631 //# R E A D
1632 //#####################################
1634 bool GzipFile::getByte(unsigned char *ch)
1636     if (fileBufPos >= fileBuf.size())
1637         {
1638         error("unexpected end of data");
1639         return false;
1640         }
1641     *ch = fileBuf[fileBufPos++];
1642     return true;
1645 /**
1646  *
1647  */
1648 bool GzipFile::getLong(unsigned long *val)
1650     if (fileBuf.size() - fileBufPos < 4)
1651         return false;
1652     int ch1 = fileBuf[fileBufPos++];
1653     int ch2 = fileBuf[fileBufPos++];
1654     int ch3 = fileBuf[fileBufPos++];
1655     int ch4 = fileBuf[fileBufPos++];
1656     *val = ((ch4<<24) & 0xff000000L) |
1657            ((ch3<<16) & 0x00ff0000L) |
1658            ((ch2<< 8) & 0x0000ff00L) |
1659            ((ch1    ) & 0x000000ffL);
1660     return true;
1663 bool GzipFile::read()
1665     fileBufPos = 0;
1667     unsigned char ch;
1669     //magic cookie
1670     if (!getByte(&ch))
1671         return false;
1672     if (ch != 0x1f)
1673         {
1674         error("bad gzip header");
1675         return false;
1676         }
1677     if (!getByte(&ch))
1678         return false;
1679     if (ch != 0x8b)
1680         {
1681         error("bad gzip header");
1682         return false;
1683         }
1685     //## compression method
1686     if (!getByte(&ch))
1687         return false;
1688     compressionMethod = ch & 0xff;
1690     //## flags
1691     if (!getByte(&ch))
1692         return false;
1693     //bool ftext    = ch & 0x01;
1694     bool fhcrc    = ch & 0x02;
1695     bool fextra   = ch & 0x04;
1696     bool fname    = ch & 0x08;
1697     bool fcomment = ch & 0x10;
1699     //trace("cm:%d ftext:%d fhcrc:%d fextra:%d fname:%d fcomment:%d",
1700     //         cm, ftext, fhcrc, fextra, fname, fcomment);
1702     //## file time
1703     unsigned long ltime;
1704     if (!getLong(&ltime))
1705         return false;
1706     //time_t mtime = (time_t)ltime;
1708     //## XFL
1709     if (!getByte(&ch))
1710         return false;
1711     //int xfl = ch;
1713     //## OS
1714     if (!getByte(&ch))
1715         return false;
1716     //int os = ch;
1718     //std::string timestr = ctime(&mtime);
1719     //trace("xfl:%d os:%d mtime:%s", xfl, os, timestr.c_str());
1721     if (fextra)
1722         {
1723         if (!getByte(&ch))
1724             return false;
1725         long xlen = ch;
1726         if (!getByte(&ch))
1727             return false;
1728         xlen = (xlen << 8) + ch;
1729         for (long l=0 ; l<xlen ; l++)
1730             {
1731             if (!getByte(&ch))
1732                 return false;
1733             }
1734         }
1736     if (fname)
1737         {
1738         fileName = "";
1739         while (true)
1740             {
1741             if (!getByte(&ch))
1742                 return false;
1743             if (ch==0)
1744                 break;
1745             fileName.push_back(ch);
1746             }
1747         }
1749     if (fcomment)
1750         {
1751         while (true)
1752             {
1753             if (!getByte(&ch))
1754                 return false;
1755             if (ch==0)
1756                 break;
1757             }
1758         }
1760     if (fhcrc)
1761         {
1762         if (!getByte(&ch))
1763             return false;
1764         if (!getByte(&ch))
1765             return false;
1766         }
1768     //read remainder of stream
1769     //compressed data runs up until 8 bytes before end of buffer
1770     std::vector<unsigned char> compBuf;
1771     while (fileBufPos < fileBuf.size() - 8)
1772         {
1773         if (!getByte(&ch))
1774             return false;
1775         compBuf.push_back(ch);
1776         }
1777     //uncompress
1778     data.clear();
1779     Inflater inflater;
1780     if (!inflater.inflate(data, compBuf))
1781         {
1782         return false;
1783         }
1785     //Get the CRC and compare
1786     Crc32 crcEngine;
1787     crcEngine.update(data);
1788     unsigned long calcCrc = crcEngine.getValue();
1789     unsigned long givenCrc;
1790     if (!getLong(&givenCrc))
1791         return false;
1792     if (givenCrc != calcCrc)
1793         {
1794         error("Specified crc, %ud, not what received: %ud",
1795                 givenCrc, calcCrc);
1796         return false;
1797         }
1799     //Get the file size and compare
1800     unsigned long givenFileSize;
1801     if (!getLong(&givenFileSize))
1802         return false;
1803     if (givenFileSize != data.size())
1804         {
1805         error("Specified data size, %ld, not what received: %ld",
1806                 givenFileSize, data.size());
1807         return false;
1808         }
1810     return true;
1815 /**
1816  *
1817  */
1818 bool GzipFile::readBuffer(const std::vector<unsigned char> &inbuf)
1820     fileBuf = inbuf;
1821     if (!read())
1822         return false;
1823     return true;
1827 /**
1828  *
1829  */
1830 bool GzipFile::readFile(const std::string &fileName)
1832     fileBuf.clear();
1833     FILE *f = fopen(fileName.c_str(), "rb");
1834     if (!f)
1835         return false;
1836     while (true)
1837         {
1838         int ch = fgetc(f);
1839         if (ch < 0)
1840             break;
1841         fileBuf.push_back(ch);
1842         }
1843     fclose(f);
1844     if (!read())
1845         return false;
1846     return true;
1856 //########################################################################
1857 //#  Z I P    F I L E
1858 //########################################################################
1860 /**
1861  * Constructor
1862  */
1863 ZipEntry::ZipEntry()
1865     crc               = 0L;
1866     compressionMethod = 8;
1869 /**
1870  *
1871  */
1872 ZipEntry::ZipEntry(const std::string &fileNameArg,
1873                    const std::string &commentArg)
1875     crc               = 0L;
1876     compressionMethod = 8;
1877     fileName          = fileNameArg;
1878     comment           = commentArg;
1881 /**
1882  * Destructor
1883  */
1884 ZipEntry::~ZipEntry()
1889 /**
1890  *
1891  */
1892 std::string ZipEntry::getFileName()
1894     return fileName;
1897 /**
1898  *
1899  */
1900 void ZipEntry::setFileName(const std::string &val)
1902     fileName = val;
1905 /**
1906  *
1907  */
1908 std::string ZipEntry::getComment()
1910     return comment;
1913 /**
1914  *
1915  */
1916 void ZipEntry::setComment(const std::string &val)
1918     comment = val;
1921 /**
1922  *
1923  */
1924 unsigned long ZipEntry::getCompressedSize()
1926     return (unsigned long)compressedData.size();
1929 /**
1930  *
1931  */
1932 int ZipEntry::getCompressionMethod()
1934     return compressionMethod;
1937 /**
1938  *
1939  */
1940 void ZipEntry::setCompressionMethod(int val)
1942     compressionMethod = val;
1945 /**
1946  *
1947  */
1948 std::vector<unsigned char> &ZipEntry::getCompressedData()
1950     return compressedData;
1953 /**
1954  *
1955  */
1956 void ZipEntry::setCompressedData(const std::vector<unsigned char> &val)
1958     compressedData = val;
1961 /**
1962  *
1963  */
1964 unsigned long ZipEntry::getUncompressedSize()
1966     return (unsigned long)uncompressedData.size();
1969 /**
1970  *
1971  */
1972 std::vector<unsigned char> &ZipEntry::getUncompressedData()
1974     return uncompressedData;
1977 /**
1978  *
1979  */
1980 void ZipEntry::setUncompressedData(const std::vector<unsigned char> &val)
1982     uncompressedData = val;
1985 /**
1986  *
1987  */
1988 unsigned long ZipEntry::getCrc()
1990     return crc;
1993 /**
1994  *
1995  */
1996 void ZipEntry::setCrc(unsigned long val)
1998     crc = val;
2001 /**
2002  *
2003  */
2004 void ZipEntry::write(unsigned char ch)
2006     uncompressedData.push_back(ch);
2009 /**
2010  *
2011  */
2012 void ZipEntry::finish()
2014     Crc32 c32;
2015     std::vector<unsigned char>::iterator iter;
2016     for (iter = uncompressedData.begin() ;
2017            iter!= uncompressedData.end() ; iter++)
2018         {
2019         unsigned char ch = *iter;
2020         c32.update(ch);
2021         }
2022     crc = c32.getValue();
2023     switch (compressionMethod)
2024         {
2025         case 0: //none
2026             {
2027             for (iter = uncompressedData.begin() ;
2028                iter!= uncompressedData.end() ; iter++)
2029                 {
2030                 unsigned char ch = *iter;
2031                 compressedData.push_back(ch);
2032                 }
2033             break;
2034             }
2035         case 8: //deflate
2036             {
2037             Deflater deflater;
2038             if (!deflater.deflate(compressedData, uncompressedData))
2039                 {
2040                 //some error
2041                 }
2042             break;
2043             }
2044         default:
2045             {
2046             printf("error: unknown compression method %d\n",
2047                     compressionMethod);
2048             }
2049         }
2055 /**
2056  *
2057  */
2058 bool ZipEntry::readFile(const std::string &fileNameArg,
2059                         const std::string &commentArg)
2061     crc = 0L;
2062     uncompressedData.clear();
2063     fileName = fileNameArg;
2064     comment  = commentArg;
2065     FILE *f = fopen(fileName.c_str(), "rb");
2066     if (!f)
2067         {
2068         return false;
2069         }
2070     while (true)
2071         {
2072         int ch = fgetc(f);
2073         if (ch < 0)
2074             break;
2075         uncompressedData.push_back((unsigned char)ch);
2076         }
2077     fclose(f);
2078     finish();
2079     return true;
2083 /**
2084  *
2085  */
2086 void ZipEntry::setPosition(unsigned long val)
2088     position = val;
2091 /**
2092  *
2093  */
2094 unsigned long ZipEntry::getPosition()
2096     return position;
2105 /**
2106  * Constructor
2107  */
2108 ZipFile::ZipFile()
2113 /**
2114  * Destructor
2115  */
2116 ZipFile::~ZipFile()
2118     std::vector<ZipEntry *>::iterator iter;
2119     for (iter=entries.begin() ; iter!=entries.end() ; iter++)
2120         {
2121         ZipEntry *entry = *iter;
2122         delete entry;
2123         }
2124     entries.clear();
2127 /**
2128  *
2129  */
2130 void ZipFile::setComment(const std::string &val)
2132     comment = val;
2135 /**
2136  *
2137  */
2138 std::string ZipFile::getComment()
2140     return comment;
2144 /**
2145  *
2146  */
2147 std::vector<ZipEntry *> &ZipFile::getEntries()
2149     return entries;
2154 //#####################################
2155 //# M E S S A G E S
2156 //#####################################
2158 void ZipFile::error(char *fmt, ...)
2160     va_list args;
2161     va_start(args, fmt);
2162     fprintf(stdout, "ZipFile error:");
2163     vfprintf(stdout, fmt, args);
2164     fprintf(stdout, "\n");
2165     va_end(args);
2168 void ZipFile::trace(char *fmt, ...)
2170     va_list args;
2171     va_start(args, fmt);
2172     fprintf(stdout, "ZipFile:");
2173     vfprintf(stdout, fmt, args);
2174     fprintf(stdout, "\n");
2175     va_end(args);
2178 //#####################################
2179 //# U T I L I T Y
2180 //#####################################
2182 /**
2183  *
2184  */
2185 ZipEntry *ZipFile::addFile(const std::string &fileName,
2186                       const std::string &comment)
2188     ZipEntry *ze = new ZipEntry();
2189     if (!ze->readFile(fileName, comment))
2190         {
2191         return NULL;
2192         }
2193     entries.push_back(ze);
2194     return ze;
2198 /**
2199  *
2200  */
2201 ZipEntry *ZipFile::newEntry(const std::string &fileName,
2202                             const std::string &comment)
2204     ZipEntry *ze = new ZipEntry(fileName, comment);
2205     entries.push_back(ze);
2206     return ze;
2210 //#####################################
2211 //# W R I T E
2212 //#####################################
2214 /**
2215  *
2216  */
2217 bool ZipFile::putLong(unsigned long val)
2219     fileBuf.push_back( ((int)(val    )) & 0xff);
2220     fileBuf.push_back( ((int)(val>> 8)) & 0xff);
2221     fileBuf.push_back( ((int)(val>>16)) & 0xff);
2222     fileBuf.push_back( ((int)(val>>24)) & 0xff);
2223     return true;
2227 /**
2228  *
2229  */
2230 bool ZipFile::putInt(unsigned int val)
2232     fileBuf.push_back( (val    ) & 0xff);
2233     fileBuf.push_back( (val>> 8) & 0xff);
2234     return true;
2237 /**
2238  *
2239  */
2240 bool ZipFile::putByte(unsigned char val)
2242     fileBuf.push_back(val);
2243     return true;
2246 /**
2247  *
2248  */
2249 bool ZipFile::writeFileData()
2251     std::vector<ZipEntry *>::iterator iter;
2252     for (iter = entries.begin() ; iter != entries.end() ; iter++)
2253         {
2254         ZipEntry *entry = *iter;
2255         entry->setPosition(fileBuf.size());
2256         //##### HEADER
2257         std::string fname = entry->getFileName();
2258         putLong(0x04034b50L);
2259         putInt(20); //versionNeeded
2260         putInt(0); //gpBitFlag
2261         //putInt(0); //compression method
2262         putInt(entry->getCompressionMethod()); //compression method
2263         putInt(0); //mod time
2264         putInt(0); //mod date
2265         putLong(entry->getCrc()); //crc32
2266         putLong(entry->getCompressedSize());
2267         putLong(entry->getUncompressedSize());
2268         putInt(fname.size());//fileName length
2269         putInt(8);//extra field length
2270         //file name
2271         for (unsigned int i=0 ; i<fname.size() ; i++)
2272             putByte((unsigned char)fname[i]);
2273         //extra field
2274         putInt(0x7855);
2275         putInt(4);
2276         putInt(100);
2277         putInt(100);
2279         //##### DATA
2280         std::vector<unsigned char> &buf = entry->getCompressedData();
2281         std::vector<unsigned char>::iterator iter;
2282         for (iter = buf.begin() ; iter != buf.end() ; iter++)
2283             {
2284             unsigned char ch = (unsigned char) *iter;
2285             putByte(ch);
2286             }
2287         }
2288     return true;
2291 /**
2292  *
2293  */
2294 bool ZipFile::writeCentralDirectory()
2296     unsigned long cdPosition = fileBuf.size();
2297     std::vector<ZipEntry *>::iterator iter;
2298     for (iter = entries.begin() ; iter != entries.end() ; iter++)
2299         {
2300         ZipEntry *entry = *iter;
2301         std::string fname   = entry->getFileName();
2302         std::string ecomment = entry->getComment();
2303         putLong(0x02014b50L);  //magic cookie
2304         putInt(2386); //versionMadeBy
2305         putInt(20); //versionNeeded
2306         putInt(0); //gpBitFlag
2307         putInt(entry->getCompressionMethod()); //compression method
2308         putInt(0); //mod time
2309         putInt(0); //mod date
2310         putLong(entry->getCrc()); //crc32
2311         putLong(entry->getCompressedSize());
2312         putLong(entry->getUncompressedSize());
2313         putInt(fname.size());//fileName length
2314         putInt(4);//extra field length
2315         putInt(ecomment.size());//comment length
2316         putInt(0); //disk number start
2317         putInt(0); //internal attributes
2318         putLong(0); //external attributes
2319         putLong(entry->getPosition());
2321         //file name
2322         for (unsigned int i=0 ; i<fname.size() ; i++)
2323             putByte((unsigned char)fname[i]);
2324         //extra field
2325         putInt(0x7855);
2326         putInt(0);
2327         //comment
2328         for (unsigned int i=0 ; i<ecomment.size() ; i++)
2329             putByte((unsigned char)ecomment[i]);
2330         }
2331     unsigned long cdSize = fileBuf.size() - cdPosition;
2333     putLong(0x06054b50L);
2334     putInt(0);//number of this disk
2335     putInt(0);//nr of disk with central dir
2336     putInt(entries.size()); //number of entries on this disk
2337     putInt(entries.size()); //number of entries total
2338     putLong(cdSize);  //size of central dir
2339     putLong(cdPosition); //position of central dir
2340     putInt(comment.size());//comment size
2341     for (unsigned int i=0 ; i<comment.size() ; i++)
2342         putByte(comment[i]);
2343     return true;
2348 /**
2349  *
2350  */
2351 bool ZipFile::write()
2353     fileBuf.clear();
2354     if (!writeFileData())
2355         return false;
2356     if (!writeCentralDirectory())
2357         return false;
2358     return true;
2362 /**
2363  *
2364  */
2365 bool ZipFile::writeBuffer(std::vector<unsigned char> &outBuf)
2367     if (!write())
2368         return false;
2369     outBuf.clear();
2370     outBuf = fileBuf;
2371     return true;
2375 /**
2376  *
2377  */
2378 bool ZipFile::writeFile(const std::string &fileName)
2380     if (!write())
2381         return false;
2382     FILE *f = fopen(fileName.c_str(), "wb");
2383     if (!f)
2384         return false;
2385     std::vector<unsigned char>::iterator iter;
2386     for (iter=fileBuf.begin() ; iter!=fileBuf.end() ; iter++)
2387         {
2388         unsigned char ch = *iter;
2389         fputc(ch, f);
2390         }
2391     fclose(f);
2392     return true;
2395 //#####################################
2396 //# R E A D
2397 //#####################################
2399 /**
2400  *
2401  */
2402 bool ZipFile::getLong(unsigned long *val)
2404     if (fileBuf.size() - fileBufPos < 4)
2405         return false;
2406     int ch1 = fileBuf[fileBufPos++];
2407     int ch2 = fileBuf[fileBufPos++];
2408     int ch3 = fileBuf[fileBufPos++];
2409     int ch4 = fileBuf[fileBufPos++];
2410     *val = ((ch4<<24) & 0xff000000L) |
2411            ((ch3<<16) & 0x00ff0000L) |
2412            ((ch2<< 8) & 0x0000ff00L) |
2413            ((ch1    ) & 0x000000ffL);
2414     return true;
2417 /**
2418  *
2419  */
2420 bool ZipFile::getInt(unsigned int *val)
2422     if (fileBuf.size() - fileBufPos < 2)
2423         return false;
2424     int ch1 = fileBuf[fileBufPos++];
2425     int ch2 = fileBuf[fileBufPos++];
2426     *val = ((ch2<< 8) & 0xff00) |
2427            ((ch1    ) & 0x00ff);
2428     return true;
2432 /**
2433  *
2434  */
2435 bool ZipFile::getByte(unsigned char *val)
2437     if (fileBuf.size() <= fileBufPos)
2438         return false;
2439     *val = fileBuf[fileBufPos++];
2440     return true;
2444 /**
2445  *
2446  */
2447 bool ZipFile::readFileData()
2449     //printf("#################################################\n");
2450     //printf("###D A T A\n");
2451     //printf("#################################################\n");
2452     while (true)
2453         {
2454         unsigned long magicCookie;
2455         if (!getLong(&magicCookie))
2456             {
2457             error("magic cookie not found");
2458             break;
2459             }
2460         trace("###Cookie:%lx", magicCookie);
2461         if (magicCookie == 0x02014b50L) //central directory
2462             break;
2463         if (magicCookie != 0x04034b50L)
2464             {
2465             error("file header not found");
2466             return false;
2467             }
2468         unsigned int versionNeeded;
2469         if (!getInt(&versionNeeded))
2470             {
2471             error("bad version needed found");
2472             return false;
2473             }
2474         unsigned int gpBitFlag;
2475         if (!getInt(&gpBitFlag))
2476             {
2477             error("bad bit flag found");
2478             return false;
2479             }
2480         unsigned int compressionMethod;
2481         if (!getInt(&compressionMethod))
2482             {
2483             error("bad compressionMethod found");
2484             return false;
2485             }
2486         unsigned int modTime;
2487         if (!getInt(&modTime))
2488             {
2489             error("bad modTime found");
2490             return false;
2491             }
2492         unsigned int modDate;
2493         if (!getInt(&modDate))
2494             {
2495             error("bad modDate found");
2496             return false;
2497             }
2498         unsigned long crc32;
2499         if (!getLong(&crc32))
2500             {
2501             error("bad crc32 found");
2502             return false;
2503             }
2504         unsigned long compressedSize;
2505         if (!getLong(&compressedSize))
2506             {
2507             error("bad compressedSize found");
2508             return false;
2509             }
2510         unsigned long uncompressedSize;
2511         if (!getLong(&uncompressedSize))
2512             {
2513             error("bad uncompressedSize found");
2514             return false;
2515             }
2516         unsigned int fileNameLength;
2517         if (!getInt(&fileNameLength))
2518             {
2519             error("bad fileNameLength found");
2520             return false;
2521             }
2522         unsigned int extraFieldLength;
2523         if (!getInt(&extraFieldLength))
2524             {
2525             error("bad extraFieldLength found");
2526             return false;
2527             }
2528         std::string fileName;
2529         for (unsigned int i=0 ; i<fileNameLength ; i++)
2530             {
2531             unsigned char ch;
2532             if (!getByte(&ch))
2533                 break;
2534             fileName.push_back(ch);
2535             }
2536         std::string extraField;
2537         for (unsigned int i=0 ; i<extraFieldLength ; i++)
2538             {
2539             unsigned char ch;
2540             if (!getByte(&ch))
2541                 break;
2542             extraField.push_back(ch);
2543             }
2544         trace("#########################  DATA");
2545         trace("FileName           :%d:%s" , fileName.size(), fileName.c_str());
2546         trace("Extra field        :%d:%s" , extraField.size(), extraField.c_str());
2547         trace("Version needed     :%d" , versionNeeded);
2548         trace("Bitflag            :%d" , gpBitFlag);
2549         trace("Compression Method :%d" , compressionMethod);
2550         trace("Mod time           :%d" , modTime);
2551         trace("Mod date           :%d" , modDate);
2552         trace("CRC                :%lx", crc32);
2553         trace("Compressed size    :%ld", compressedSize);
2554         trace("Uncompressed size  :%ld", uncompressedSize);
2556         //#### Uncompress the data
2557         std::vector<unsigned char> compBuf;
2558         if (gpBitFlag & 0x8)//bit 3 was set.  means we dont know compressed size
2559             {
2560             unsigned char c1, c2, c3, c4;
2561             c1 = c2 = c3 = c4 = 0;
2562             while (true)
2563                 {
2564                 unsigned char ch;
2565                 if (!getByte(&ch))
2566                     {
2567                     error("premature end of data");
2568                     break;
2569                     }
2570                 compBuf.push_back(ch);
2571                 c1 = c2; c2 = c3; c3 = c4; c4 = ch;
2572                 if (c1 == 0x50 && c2 == 0x4b && c3 == 0x07 && c4 == 0x08)
2573                     {
2574                     trace("found end of compressed data");
2575                     //remove the cookie
2576                     compBuf.erase(compBuf.end() -4, compBuf.end());
2577                     break;
2578                     }
2579                 }
2580             }
2581         else
2582             {
2583             for (unsigned long bnr = 0 ; bnr < compressedSize ; bnr++)
2584                 {
2585                 unsigned char ch;
2586                 if (!getByte(&ch))
2587                     {
2588                     error("premature end of data");
2589                     break;
2590                     }
2591                 compBuf.push_back(ch);
2592                 }
2593             }
2595         printf("### data: ");
2596         for (int i=0 ; i<10 ; i++)
2597             printf("%02x ", compBuf[i] & 0xff);
2598         printf("\n");
2600         if (gpBitFlag & 0x8)//only if bit 3 set
2601             {
2602             /* this cookie was read in the loop above
2603             unsigned long dataDescriptorSignature ;
2604             if (!getLong(&dataDescriptorSignature))
2605                 break;
2606             if (dataDescriptorSignature != 0x08074b50L)
2607                 {
2608                 error("bad dataDescriptorSignature found");
2609                 return false;
2610                 }
2611             */
2612             unsigned long crc32;
2613             if (!getLong(&crc32))
2614                 {
2615                 error("bad crc32 found");
2616                 return false;
2617                 }
2618             unsigned long compressedSize;
2619             if (!getLong(&compressedSize))
2620                 {
2621                 error("bad compressedSize found");
2622                 return false;
2623                 }
2624             unsigned long uncompressedSize;
2625             if (!getLong(&uncompressedSize))
2626                 {
2627                 error("bad uncompressedSize found");
2628                 return false;
2629                 }
2630             }//bit 3 was set
2631         //break;
2633         std::vector<unsigned char> uncompBuf;
2634         switch (compressionMethod)
2635             {
2636             case 8: //deflate
2637                 {
2638                 Inflater inflater;
2639                 if (!inflater.inflate(uncompBuf, compBuf))
2640                     {
2641                     return false;
2642                     }
2643                 break;
2644                 }
2645             default:
2646                 {
2647                 error("Unimplemented compression method %d", compressionMethod);
2648                 return false;
2649                 }
2650             }
2652         if (uncompressedSize != uncompBuf.size())
2653             {
2654             error("Size mismatch.  Expected %ld, received %ld",
2655                 uncompressedSize, uncompBuf.size());
2656             return false;
2657             }
2659         Crc32 crcEngine;
2660         crcEngine.update(uncompBuf);
2661         unsigned long crc = crcEngine.getValue();
2662         if (crc != crc32)
2663             {
2664             error("Crc mismatch.  Calculated %08ux, received %08ux", crc, crc32);
2665             return false;
2666             }
2668         ZipEntry *ze = new ZipEntry(fileName, comment);
2669         ze->setCompressionMethod(compressionMethod);
2670         ze->setCompressedData(compBuf);
2671         ze->setUncompressedData(uncompBuf);
2672         ze->setCrc(crc);
2673         entries.push_back(ze);
2676         }
2677     return true;
2681 /**
2682  *
2683  */
2684 bool ZipFile::readCentralDirectory()
2686     //printf("#################################################\n");
2687     //printf("###D I R E C T O R Y\n");
2688     //printf("#################################################\n");
2689     while (true)
2690         {
2691         //We start with a central directory cookie already
2692         //Check at the bottom of the loop.
2693         unsigned int version;
2694         if (!getInt(&version))
2695             {
2696             error("bad version found");
2697             return false;
2698             }
2699         unsigned int versionNeeded;
2700         if (!getInt(&versionNeeded))
2701             {
2702             error("bad version found");
2703             return false;
2704             }
2705         unsigned int gpBitFlag;
2706         if (!getInt(&gpBitFlag))
2707             {
2708             error("bad bit flag found");
2709             return false;
2710             }
2711         unsigned int compressionMethod;
2712         if (!getInt(&compressionMethod))
2713             {
2714             error("bad compressionMethod found");
2715             return false;
2716             }
2717         unsigned int modTime;
2718         if (!getInt(&modTime))
2719             {
2720             error("bad modTime found");
2721             return false;
2722             }
2723         unsigned int modDate;
2724         if (!getInt(&modDate))
2725             {
2726             error("bad modDate found");
2727             return false;
2728             }
2729         unsigned long crc32;
2730         if (!getLong(&crc32))
2731             {
2732             error("bad crc32 found");
2733             return false;
2734             }
2735         unsigned long compressedSize;
2736         if (!getLong(&compressedSize))
2737             {
2738             error("bad compressedSize found");
2739             return false;
2740             }
2741         unsigned long uncompressedSize;
2742         if (!getLong(&uncompressedSize))
2743             {
2744             error("bad uncompressedSize found");
2745             return false;
2746             }
2747         unsigned int fileNameLength;
2748         if (!getInt(&fileNameLength))
2749             {
2750             error("bad fileNameLength found");
2751             return false;
2752             }
2753         unsigned int extraFieldLength;
2754         if (!getInt(&extraFieldLength))
2755             {
2756             error("bad extraFieldLength found");
2757             return false;
2758             }
2759         unsigned int fileCommentLength;
2760         if (!getInt(&fileCommentLength))
2761             {
2762             error("bad fileCommentLength found");
2763             return false;
2764             }
2765         unsigned int diskNumberStart;
2766         if (!getInt(&diskNumberStart))
2767             {
2768             error("bad diskNumberStart found");
2769             return false;
2770             }
2771         unsigned int internalFileAttributes;
2772         if (!getInt(&internalFileAttributes))
2773             {
2774             error("bad internalFileAttributes found");
2775             return false;
2776             }
2777         unsigned long externalFileAttributes;
2778         if (!getLong(&externalFileAttributes))
2779             {
2780             error("bad externalFileAttributes found");
2781             return false;
2782             }
2783         unsigned long localHeaderOffset;
2784         if (!getLong(&localHeaderOffset))
2785             {
2786             error("bad localHeaderOffset found");
2787             return false;
2788             }
2789         std::string fileName;
2790         for (unsigned int i=0 ; i<fileNameLength ; i++)
2791             {
2792             unsigned char ch;
2793             if (!getByte(&ch))
2794                 break;
2795             fileName.push_back(ch);
2796             }
2797         std::string extraField;
2798         for (unsigned int i=0 ; i<extraFieldLength ; i++)
2799             {
2800             unsigned char ch;
2801             if (!getByte(&ch))
2802                 break;
2803             extraField.push_back(ch);
2804             }
2805         std::string fileComment;
2806         for (unsigned int i=0 ; i<fileCommentLength ; i++)
2807             {
2808             unsigned char ch;
2809             if (!getByte(&ch))
2810                 break;
2811             fileComment.push_back(ch);
2812             }
2813         trace("######################### ENTRY");
2814         trace("FileName           :%s" , fileName.c_str());
2815         trace("Extra field        :%s" , extraField.c_str());
2816         trace("File comment       :%s" , fileComment.c_str());
2817         trace("Version            :%d" , version);
2818         trace("Version needed     :%d" , versionNeeded);
2819         trace("Bitflag            :%d" , gpBitFlag);
2820         trace("Compression Method :%d" , compressionMethod);
2821         trace("Mod time           :%d" , modTime);
2822         trace("Mod date           :%d" , modDate);
2823         trace("CRC                :%lx", crc32);
2824         trace("Compressed size    :%ld", compressedSize);
2825         trace("Uncompressed size  :%ld", uncompressedSize);
2826         trace("Disk nr start      :%ld", diskNumberStart);
2827         trace("Header offset      :%ld", localHeaderOffset);
2830         unsigned long magicCookie;
2831         if (!getLong(&magicCookie))
2832             {
2833             error("magic cookie not found");
2834             return false;
2835             }
2836         trace("###Cookie:%lx", magicCookie);
2837         if (magicCookie  == 0x06054b50L) //end of central directory
2838             break;
2839         else if (magicCookie == 0x05054b50L) //signature
2840             {
2841             //## Digital Signature
2842             unsigned int signatureSize;
2843             if (!getInt(&signatureSize))
2844                 {
2845                 error("bad signatureSize found");
2846                 return false;
2847                 }
2848             std::string digitalSignature;
2849             for (unsigned int i=0 ; i<signatureSize ; i++)
2850                 {
2851                 unsigned char ch;
2852                 if (!getByte(&ch))
2853                     break;
2854                 digitalSignature.push_back(ch);
2855                 }
2856             trace("######## SIGNATURE :'%s'" , digitalSignature.c_str());
2857             }
2858         else if (magicCookie != 0x02014b50L) //central directory
2859             {
2860             error("directory file header not found");
2861             return false;
2862             }
2863         }
2865     unsigned int diskNr;
2866     if (!getInt(&diskNr))
2867         {
2868         error("bad diskNr found");
2869         return false;
2870         }
2871     unsigned int diskWithCd;
2872     if (!getInt(&diskWithCd))
2873         {
2874         error("bad diskWithCd found");
2875         return false;
2876         }
2877     unsigned int nrEntriesDisk;
2878     if (!getInt(&nrEntriesDisk))
2879         {
2880         error("bad nrEntriesDisk found");
2881         return false;
2882         }
2883     unsigned int nrEntriesTotal;
2884     if (!getInt(&nrEntriesTotal))
2885         {
2886         error("bad nrEntriesTotal found");
2887         return false;
2888         }
2889     unsigned long cdSize;
2890     if (!getLong(&cdSize))
2891         {
2892         error("bad cdSize found");
2893         return false;
2894         }
2895     unsigned long cdPos;
2896     if (!getLong(&cdPos))
2897         {
2898         error("bad cdPos found");
2899         return false;
2900         }
2901     unsigned int commentSize;
2902     if (!getInt(&commentSize))
2903         {
2904         error("bad commentSize found");
2905         return false;
2906         }
2907     comment = "";
2908     for (unsigned int i=0 ; i<commentSize ; i++)
2909         {
2910         unsigned char ch;
2911         if (!getByte(&ch))
2912             break;
2913         comment.push_back(ch);
2914         }
2915     trace("######## Zip Comment :'%s'" , comment.c_str());
2917     return true;
2921 /**
2922  *
2923  */
2924 bool ZipFile::read()
2926     fileBufPos = 0;
2927     if (!readFileData())
2928         {
2929         return false;
2930         }
2931     if (!readCentralDirectory())
2932         {
2933         return false;
2934         }
2935     return true;
2938 /**
2939  *
2940  */
2941 bool ZipFile::readBuffer(const std::vector<unsigned char> &inbuf)
2943     fileBuf = inbuf;
2944     if (!read())
2945         return false;
2946     return true;
2950 /**
2951  *
2952  */
2953 bool ZipFile::readFile(const std::string &fileName)
2955     fileBuf.clear();
2956     FILE *f = fopen(fileName.c_str(), "rb");
2957     if (!f)
2958         return false;
2959     while (true)
2960         {
2961         int ch = fgetc(f);
2962         if (ch < 0)
2963             break;
2964         fileBuf.push_back(ch);
2965         }
2966     fclose(f);
2967     if (!read())
2968         return false;
2969     return true;
2980 //########################################################################
2981 //#  E N D    O F    F I L E
2982 //########################################################################