Code

Connector tool: make connectors avoid the convex hull of shapes.
[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-2007 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;
162     c &= 0xffffffff;
163     c = crc_table[(c ^ b) & 0xff] ^ (c >> 8);
164     value = ~c;
168 void Crc32::update(char *str)
170     if (str)
171         while (*str)
172             update((unsigned char)*str++);
175 void Crc32::update(const std::vector<unsigned char> &buf)
177     std::vector<unsigned char>::const_iterator iter;
178     for (iter=buf.begin() ; iter!=buf.end() ; iter++)
179         {
180         unsigned char ch = *iter;
181         update(ch);
182         }
186 /**
187  * Returns current checksum value.
188  */
189 unsigned long Crc32::getValue()
191     return value & 0xffffffffL;
194 //########################################################################
195 //#  I N F L A T E R
196 //########################################################################
199 /**
200  *
201  */
202 typedef struct
204     int *count;  // number of symbols of each length
205     int *symbol; // canonically ordered symbols
206 } Huffman;
208 /**
209  *
210  */
211 class Inflater
213 public:
215     Inflater();
217     virtual ~Inflater();
219     static const int MAXBITS   =  15; // max bits in a code
220     static const int MAXLCODES = 286; // max number of literal/length codes
221     static const int MAXDCODES =  30; // max number of distance codes
222     static const int MAXCODES  = 316; // max codes lengths to read
223     static const int FIXLCODES = 288; // number of fixed literal/length codes
225     /**
226      *
227      */
228     bool inflate(std::vector<unsigned char> &destination,
229                  std::vector<unsigned char> &source);
231 private:
233     /**
234      *
235      */
236     void error(char const *fmt, ...)
237     #ifdef G_GNUC_PRINTF
238     G_GNUC_PRINTF(2, 3)
239     #endif
240     ;
242     /**
243      *
244      */
245     void trace(char const *fmt, ...)
246     #ifdef G_GNUC_PRINTF
247     G_GNUC_PRINTF(2, 3)
248     #endif
249     ;
251     /**
252      *
253      */
254     void dump();
256     /**
257      *
258      */
259     int buildHuffman(Huffman *h, int *length, int n);
261     /**
262      *
263      */
264     bool getBits(int need, int *oval);
266     /**
267      *
268      */
269     int doDecode(Huffman *h);
271     /**
272      *
273      */
274     bool doCodes(Huffman *lencode, Huffman *distcode);
276     /**
277      *
278      */
279     bool doStored();
281     /**
282      *
283      */
284     bool doFixed();
286     /**
287      *
288      */
289     bool doDynamic();
292     std::vector<unsigned char>dest;
294     std::vector<unsigned char>src;
295     unsigned long srcPos;  //current read position
296     int bitBuf;
297     int bitCnt;
299 };
302 /**
303  *
304  */
305 Inflater::Inflater()
309 /**
310  *
311  */
312 Inflater::~Inflater()
316 /**
317  *
318  */
319 void Inflater::error(char const *fmt, ...)
321     va_list args;
322     va_start(args, fmt);
323     fprintf(stdout, "Inflater error:");
324     vfprintf(stdout, fmt, args);
325     fprintf(stdout, "\n");
326     va_end(args);
329 /**
330  *
331  */
332 void Inflater::trace(char const *fmt, ...)
334     va_list args;
335     va_start(args, fmt);
336     fprintf(stdout, "Inflater:");
337     vfprintf(stdout, fmt, args);
338     fprintf(stdout, "\n");
339     va_end(args);
343 /**
344  *
345  */
346 void Inflater::dump()
348     for (unsigned int i=0 ; i<dest.size() ; i++)
349         {
350         fputc(dest[i], stdout);
351         }
354 /**
355  *
356  */
357 int Inflater::buildHuffman(Huffman *h, int *length, int n)
359     // count number of codes of each length
360     for (int len = 0; len <= MAXBITS; len++)
361         h->count[len] = 0;
362     for (int symbol = 0; symbol < n; symbol++)
363         (h->count[length[symbol]])++;   // assumes lengths are within bounds
364     if (h->count[0] == n)               // no codes!
365         {
366         error("huffman tree will result in failed decode");
367         return -1;
368         }
370     // check for an over-subscribed or incomplete set of lengths
371     int left = 1;                // number of possible codes left of current length
372     for (int len = 1; len <= MAXBITS; len++)
373         {
374         left <<= 1;                     // one more bit, double codes left
375         left -= h->count[len];          // deduct count from possible codes
376         if (left < 0)
377             {
378             error("huffman over subscribed");
379             return -1;
380             }
381         }
383     // generate offsets into symbol table for each length for sorting
384     int offs[MAXBITS+1]; //offsets in symbol table for each length
385     offs[1] = 0;
386     for (int len = 1; len < MAXBITS; len++)
387         offs[len + 1] = offs[len] + h->count[len];
389     /*
390      * put symbols in table sorted by length, by symbol order within each
391      * length
392      */
393     for (int symbol = 0; symbol < n; symbol++)
394         if (length[symbol] != 0)
395             h->symbol[offs[length[symbol]]++] = symbol;
397     // return zero for complete set, positive for incomplete set
398     return left;
402 /**
403  *
404  */
405 bool Inflater::getBits(int requiredBits, int *oval)
407     long val = bitBuf;
409     //add more bytes if needed
410     while (bitCnt < requiredBits)
411         {
412         if (srcPos >= src.size())
413             {
414             error("premature end of input");
415             return false;
416             }
417         val |= ((long)(src[srcPos++])) << bitCnt;
418         bitCnt += 8;
419         }
421     //update the buffer and return the data
422     bitBuf =  (int)(val >> requiredBits);
423     bitCnt -= requiredBits;
424     *oval = (int)(val & ((1L << requiredBits) - 1));
426     return true;
430 /**
431  *
432  */
433 int Inflater::doDecode(Huffman *h)
435     int bitTmp  = bitBuf;
436     int left    = bitCnt;
437     int code    = 0;
438     int first   = 0;
439     int index   = 0;
440     int len     = 1;
441     int *next = h->count + 1;
442     while (true)
443         {
444         while (left--)
445             {
446             code   |=  bitTmp & 1;
447             bitTmp >>= 1;
448             int count  =   *next++;
449             if (code < first + count)
450                 { /* if length len, return symbol */
451                 bitBuf = bitTmp;
452                 bitCnt = (bitCnt - len) & 7;
453                 return h->symbol[index + (code - first)];
454                 }
455             index +=  count;
456             first +=  count;
457             first <<= 1;
458             code  <<= 1;
459             len++;
460             }
461         left = (MAXBITS+1) - len;
462         if (left == 0)
463             break;
464         if (srcPos >= src.size())
465             {
466             error("premature end of input");
467             dump();
468             return -1;
469             }
470         bitTmp = src[srcPos++];
471         if (left > 8)
472             left = 8;
473         }
475     error("no end of block found");
476     return -1;
479 /**
480  *
481  */
482 bool Inflater::doCodes(Huffman *lencode, Huffman *distcode)
484     static const int lens[29] = { // Size base for length codes 257..285
485         3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
486         35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
487     static const int lext[29] = { // Extra bits for length codes 257..285
488         0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
489         3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
490     static const int dists[30] = { // Offset base for distance codes 0..29
491         1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
492         257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
493         8193, 12289, 16385, 24577};
494     static const int dext[30] = { // Extra bits for distance codes 0..29
495         0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
496         7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
497         12, 12, 13, 13};
499     //decode literals and length/distance pairs
500     while (true)
501         {
502         int symbol = doDecode(lencode);
503         if (symbol == 256)
504             break;
505         if (symbol < 0)
506             {
507             return false;
508             }
509         if (symbol < 256) //literal
510             {
511             dest.push_back(symbol);
512             }
513         else if (symbol > 256)//length
514             {
515             symbol -= 257;
516             if (symbol >= 29)
517                 {
518                 error("invalid fixed code");
519                 return false;
520                 }
521             int ret;
522             if (!getBits(lext[symbol], &ret))
523                 return false;
524             int len = lens[symbol] + ret;
526             symbol = doDecode(distcode);//distance
527             if (symbol < 0)
528                 {
529                 return false;
530                 }
532             if (!getBits(dext[symbol], &ret))
533                 return false;
534             unsigned int dist = dists[symbol] + ret;
535             if (dist > dest.size())
536                 {
537                 error("distance too far back %d/%d", dist, dest.size());
538                 dump();
539                 //printf("pos:%d\n", srcPos);
540                 return false;
541                 }
543             // copy length bytes from distance bytes back
544             //dest.push_back('{');
545             while (len--)
546                 {
547                 dest.push_back(dest[dest.size() - dist]);
548                 }
549             //dest.push_back('}');
551             }
552         }
554     return true;
557 /**
558  */
559 bool Inflater::doStored()
561     //trace("### stored ###");
563     // clear bits from current byte
564     bitBuf = 0;
565     bitCnt = 0;
567     // length
568     if (srcPos + 4 > src.size())
569         {
570         error("not enough input");
571         return false;
572         }
574     int len = src[srcPos++];
575     len |= src[srcPos++] << 8;
576     //trace("### len:%d", len);
577     // check complement
578     if (src[srcPos++] != (~len & 0xff) ||
579         src[srcPos++] != ((~len >> 8) & 0xff))
580         {
581         error("twos complement for storage size do not match");
582         return false;
583         }
585     // copy data
586     if (srcPos + len > src.size())
587         {
588         error("Not enough input for stored block");
589         return false;
590         }
591     while (len--)
592         dest.push_back(src[srcPos++]);
594     return true;
597 /**
598  */
599 bool Inflater::doFixed()
601     //trace("### fixed ###");
603     static bool firstTime = true;
604     static int lencnt[MAXBITS+1], lensym[FIXLCODES];
605     static int distcnt[MAXBITS+1], distsym[MAXDCODES];
606     static Huffman lencode = {lencnt, lensym};
607     static Huffman distcode = {distcnt, distsym};
609     if (firstTime)
610         {
611         firstTime = false;
613         int lengths[FIXLCODES];
615         // literal/length table
616         int symbol = 0;
617         for ( ; symbol < 144; symbol++)
618             lengths[symbol] = 8;
619         for ( ; symbol < 256; symbol++)
620             lengths[symbol] = 9;
621         for ( ; symbol < 280; symbol++)
622             lengths[symbol] = 7;
623         for ( ; symbol < FIXLCODES; symbol++)
624             lengths[symbol] = 8;
625         buildHuffman(&lencode, lengths, FIXLCODES);
627         // distance table
628         for (int symbol = 0; symbol < MAXDCODES; symbol++)
629             lengths[symbol] = 5;
630         buildHuffman(&distcode, lengths, MAXDCODES);
631         }
633     // decode data until end-of-block code
634     bool ret = doCodes(&lencode, &distcode);
635     return ret;
638 /**
639  */
640 bool Inflater::doDynamic()
642     //trace("### dynamic ###");
643     int lengths[MAXCODES];                      // descriptor code lengths
644     int lencnt[MAXBITS+1], lensym[MAXLCODES];   // lencode memory
645     int distcnt[MAXBITS+1], distsym[MAXDCODES]; // distcode memory
646     Huffman lencode  = {lencnt, lensym};          // length code
647     Huffman distcode = {distcnt, distsym};        // distance code
648     static const int order[19] =                // permutation of code length codes
649         {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
651     // get number of lengths in each table, check lengths
652     int ret;
653     if (!getBits(5, &ret))
654         return false;
655     int nlen  = ret + 257;
656     if (!getBits(5, &ret))
657         return false;
658     int ndist = ret + 1;
659     if (!getBits(4, &ret))
660         return false;
661     int ncode = ret + 4;
662     if (nlen > MAXLCODES || ndist > MAXDCODES)
663         {
664         error("Bad codes");
665         return false;
666         }
668     // get code length code lengths
669     int index = 0;
670     for ( ; index < ncode; index++)
671         {
672         if (!getBits(3, &ret))
673             return false;
674         lengths[order[index]] = ret;
675         }
676     for ( ; index < 19; index++)
677         lengths[order[index]] = 0;
679     // build huffman table for code lengths codes
680     if (buildHuffman(&lencode, lengths, 19) != 0)
681         return false;
683     // read length/literal and distance code length tables
684     index = 0;
685     while (index < nlen + ndist)
686         {
687         int symbol = doDecode(&lencode);
688         if (symbol < 16)                // length in 0..15
689             lengths[index++] = symbol;
690         else
691             {                          // repeat instruction
692             int len = 0;               // assume repeating zeros
693             if (symbol == 16)
694                 {         // repeat last length 3..6 times
695                 if (index == 0)
696                     {
697                     error("no last length");
698                     return false;
699                     }
700                 len = lengths[index - 1];// last length
701                 if (!getBits(2, &ret))
702                     return false;
703                 symbol = 3 + ret;
704                 }
705             else if (symbol == 17)      // repeat zero 3..10 times
706                 {
707                 if (!getBits(3, &ret))
708                     return false;
709                 symbol = 3 + ret;
710                 }
711             else                        // == 18, repeat zero 11..138 times
712                 {
713                 if (!getBits(7, &ret))
714                     return false;
715                 symbol = 11 + ret;
716                 }
717             if (index + symbol > nlen + ndist)
718                 {
719                 error("too many lengths");
720                 return false;
721                 }
722             while (symbol--)            // repeat last or zero symbol times
723                 lengths[index++] = len;
724             }
725         }
727     // build huffman table for literal/length codes
728     int err = buildHuffman(&lencode, lengths, nlen);
729     if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1))
730         {
731         error("incomplete length codes");
732         //return false;
733         }
734     // build huffman table for distance codes
735     err = buildHuffman(&distcode, lengths + nlen, ndist);
736     if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1))
737         {
738         error("incomplete dist codes");
739         return false;
740         }
742     // decode data until end-of-block code
743     bool retn = doCodes(&lencode, &distcode);
744     return retn;
747 /**
748  */
749 bool Inflater::inflate(std::vector<unsigned char> &destination,
750                        std::vector<unsigned char> &source)
752     dest.clear();
753     src = source;
754     srcPos = 0;
755     bitBuf = 0;
756     bitCnt = 0;
758     while (true)
759         {
760         int last; // one if last block
761         if (!getBits(1, &last))
762             return false;
763         int type; // block type 0..3
764         if (!getBits(2, &type))
765             return false;
766         switch (type)
767             {
768             case 0:
769                 if (!doStored())
770                     return false;
771                 break;
772             case 1:
773                 if (!doFixed())
774                     return false;
775                 break;
776             case 2:
777                 if (!doDynamic())
778                     return false;
779                 break;
780             default:
781                 error("Unknown block type %d", type);
782                 return false;
783             }
784         if (last)
785             break;
786         }
788     destination = dest;
790     return true;
798 //########################################################################
799 //#  D E F L A T E R
800 //########################################################################
804 class Deflater
806 public:
808     /**
809      *
810      */
811     Deflater();
813     /**
814      *
815      */
816     virtual ~Deflater();
818     /**
819      *
820      */
821     virtual void reset();
823     /**
824      *
825      */
826     virtual bool update(int ch);
828     /**
829      *
830      */
831     virtual bool finish();
833     /**
834      *
835      */
836     virtual std::vector<unsigned char> &getCompressed();
838     /**
839      *
840      */
841     bool deflate(std::vector<unsigned char> &dest,
842                  const std::vector<unsigned char> &src);
844     void encodeDistStatic(unsigned int len, unsigned int dist);
846 private:
848     //debug messages
849     void error(char const *fmt, ...)
850     #ifdef G_GNUC_PRINTF
851     G_GNUC_PRINTF(2, 3)
852     #endif
853     ;
855     void trace(char const *fmt, ...)
856     #ifdef G_GNUC_PRINTF
857     G_GNUC_PRINTF(2, 3)
858     #endif
859     ;
861     bool compressWindow();
863     bool compress();
865     std::vector<unsigned char> uncompressed;
867     std::vector<unsigned char> window;
869     unsigned int windowPos;
871     std::vector<unsigned char> compressed;
873     //#### Output
874     unsigned int outputBitBuf;
875     unsigned int outputNrBits;
877     void put(int ch);
879     void putWord(int ch);
881     void putFlush();
883     void putBits(unsigned int ch, unsigned int bitsWanted);
885     void putBitsR(unsigned int ch, unsigned int bitsWanted);
887     //#### Huffman Encode
888     void encodeLiteralStatic(unsigned int ch);
890     unsigned char windowBuf[32768];
891     //assume 32-bit ints
892     unsigned int windowHashBuf[32768];
893 };
896 //########################################################################
897 //# A P I
898 //########################################################################
901 /**
902  *
903  */
904 Deflater::Deflater()
906     reset();
909 /**
910  *
911  */
912 Deflater::~Deflater()
917 /**
918  *
919  */
920 void Deflater::reset()
922     outputBitBuf = 0;
923     outputNrBits = 0;
924     window.clear();
925     compressed.clear();
926     uncompressed.clear();
929 /**
930  *
931  */
932 bool Deflater::update(int ch)
934     uncompressed.push_back((unsigned char)(ch & 0xff));
935     return true;
938 /**
939  *
940  */
941 bool Deflater::finish()
943     return compress();
946 /**
947  *
948  */
949 std::vector<unsigned char> &Deflater::getCompressed()
951     return compressed;
955 /**
956  *
957  */
958 bool Deflater::deflate(std::vector<unsigned char> &dest,
959                        const std::vector<unsigned char> &src)
961     reset();
962     uncompressed = src;
963     if (!compress())
964         return false;
965     dest = compressed;
966     return true;
975 //########################################################################
976 //# W O R K I N G    C O D E
977 //########################################################################
980 //#############################
981 //#  M E S S A G E S
982 //#############################
984 /**
985  *  Print error messages
986  */
987 void Deflater::error(char const *fmt, ...)
989     va_list args;
990     va_start(args, fmt);
991     fprintf(stdout, "Deflater error:");
992     vfprintf(stdout, fmt, args);
993     fprintf(stdout, "\n");
994     va_end(args);
997 /**
998  *  Print trace messages
999  */
1000 void Deflater::trace(char const *fmt, ...)
1002     va_list args;
1003     va_start(args, fmt);
1004     fprintf(stdout, "Deflater:");
1005     vfprintf(stdout, fmt, args);
1006     fprintf(stdout, "\n");
1007     va_end(args);
1013 //#############################
1014 //#  O U T P U T
1015 //#############################
1017 /**
1018  *
1019  */
1020 void Deflater::put(int ch)
1022     compressed.push_back(ch);
1023     outputBitBuf = 0;
1024     outputNrBits = 0;
1027 /**
1028  *
1029  */
1030 void Deflater::putWord(int ch)
1032     int lo = (ch   ) & 0xff;
1033     int hi = (ch>>8) & 0xff;
1034     put(lo);
1035     put(hi);
1038 /**
1039  *
1040  */
1041 void Deflater::putFlush()
1043     if (outputNrBits > 0)
1044         {
1045         put(outputBitBuf & 0xff);
1046         }
1047     outputBitBuf = 0;
1048     outputNrBits = 0;
1051 /**
1052  *
1053  */
1054 void Deflater::putBits(unsigned int ch, unsigned int bitsWanted)
1056     //trace("n:%4u, %d\n", ch, bitsWanted);
1058     while (bitsWanted--)
1059         {
1060         //add bits to position 7.  shift right
1061         outputBitBuf = (outputBitBuf>>1) + (ch<<7 & 0x80);
1062         ch >>= 1;
1063         outputNrBits++;
1064         if (outputNrBits >= 8)
1065             {
1066             unsigned char b = outputBitBuf & 0xff;
1067             //printf("b:%02x\n", b);
1068             put(b);
1069             }
1070         }
1073 static unsigned int bitReverse(unsigned int code, unsigned int nrBits)
1075     unsigned int outb = 0;
1076     while (nrBits--)
1077         {
1078         outb = (outb << 1) | (code & 0x01);
1079         code >>= 1;
1080         }
1081     return outb;
1085 /**
1086  *
1087  */
1088 void Deflater::putBitsR(unsigned int ch, unsigned int bitsWanted)
1090     //trace("r:%4u, %d", ch, bitsWanted);
1092     unsigned int rcode = bitReverse(ch, bitsWanted);
1094     putBits(rcode, bitsWanted);
1099 //#############################
1100 //#  E N C O D E
1101 //#############################
1105 void Deflater::encodeLiteralStatic(unsigned int ch)
1107     //trace("c: %d", ch);
1109     if (ch < 144)
1110         {
1111         putBitsR(ch + 0x0030 , 8); // 00110000
1112         }
1113     else if (ch < 256)
1114         {
1115         putBitsR(ch - 144 + 0x0190 , 9); // 110010000
1116         }
1117     else if (ch < 280)
1118         {
1119         putBitsR(ch - 256 + 0x0000 , 7); // 0000000
1120         }
1121     else if (ch < 288)
1122         {
1123         putBitsR(ch - 280 + 0x00c0 , 8); // 11000000
1124         }
1125     else //out of range
1126         {
1127         error("Literal out of range: %d", ch);
1128         }
1133 typedef struct
1135     unsigned int base;
1136     unsigned int range;
1137     unsigned int bits;
1138 } LenBase;
1140 LenBase lenBases[] =
1142     {   3,  1, 0 },
1143     {   4,  1, 0 },
1144     {   5,  1, 0 },
1145     {   6,  1, 0 },
1146     {   7,  1, 0 },
1147     {   8,  1, 0 },
1148     {   9,  1, 0 },
1149     {  10,  1, 0 },
1150     {  11,  2, 1 },
1151     {  13,  2, 1 },
1152     {  15,  2, 1 },
1153     {  17,  2, 1 },
1154     {  19,  4, 2 },
1155     {  23,  4, 2 },
1156     {  27,  4, 2 },
1157     {  31,  4, 2 },
1158     {  35,  8, 3 },
1159     {  43,  8, 3 },
1160     {  51,  8, 3 },
1161     {  59,  8, 3 },
1162     {  67, 16, 4 },
1163     {  83, 16, 4 },
1164     {  99, 16, 4 },
1165     { 115, 16, 4 },
1166     { 131, 32, 5 },
1167     { 163, 32, 5 },
1168     { 195, 32, 5 },
1169     { 227, 32, 5 },
1170     { 258,  1, 0 }
1171 };
1173 typedef struct
1175     unsigned int base;
1176     unsigned int range;
1177     unsigned int bits;
1178 } DistBase;
1180 DistBase distBases[] =
1182     {     1,    1,  0 },
1183     {     2,    1,  0 },
1184     {     3,    1,  0 },
1185     {     4,    1,  0 },
1186     {     5,    2,  1 },
1187     {     7,    2,  1 },
1188     {     9,    4,  2 },
1189     {    13,    4,  2 },
1190     {    17,    8,  3 },
1191     {    25,    8,  3 },
1192     {    33,   16,  4 },
1193     {    49,   16,  4 },
1194     {    65,   32,  5 },
1195     {    97,   32,  5 },
1196     {   129,   64,  6 },
1197     {   193,   64,  6 },
1198     {   257,  128,  7 },
1199     {   385,  128,  7 },
1200     {   513,  256,  8 },
1201     {   769,  256,  8 },
1202     {  1025,  512,  9 },
1203     {  1537,  512,  9 },
1204     {  2049, 1024, 10 },
1205     {  3073, 1024, 10 },
1206     {  4097, 2048, 11 },
1207     {  6145, 2048, 11 },
1208     {  8193, 4096, 12 },
1209     { 12289, 4096, 12 },
1210     { 16385, 8192, 13 },
1211     { 24577, 8192, 13 }
1212 };
1214 void Deflater::encodeDistStatic(unsigned int len, unsigned int dist)
1217     //## Output length
1219     if (len < 3 || len > 258)
1220         {
1221         error("Length out of range:%d", len);
1222         return;
1223         }
1225     bool found = false;
1226     for (int i=0 ; i<30 ; i++)
1227         {
1228         unsigned int base  = lenBases[i].base;
1229         unsigned int range = lenBases[i].range;
1230         if (base + range > len)
1231             {
1232             unsigned int lenCode = 257 + i;
1233             unsigned int length  = len - base;
1234             //trace("--- %d %d %d %d", len, base, range, length);
1235             encodeLiteralStatic(lenCode);
1236             putBits(length, lenBases[i].bits);
1237             found = true;
1238             break;
1239             }
1240         }
1241     if (!found)
1242         {
1243         error("Length not found in table:%d", len);
1244         return;
1245         }
1247     //## Output distance
1249     if (dist < 4 || dist > 32768)
1250         {
1251         error("Distance out of range:%d", dist);
1252         return;
1253         }
1255     found = false;
1256     for (int i=0 ; i<30 ; i++)
1257         {
1258         unsigned int base  = distBases[i].base;
1259         unsigned int range = distBases[i].range;
1260         if (base + range > dist)
1261             {
1262             unsigned int distCode = i;
1263             unsigned int distance = dist - base;
1264             //error("--- %d %d %d %d", dist, base, range, distance);
1265             putBitsR(distCode, 5);
1266             putBits(distance, distBases[i].bits);
1267             found = true;
1268             break;
1269             }
1270         }
1271     if (!found)
1272         {
1273         error("Distance not found in table:%d", dist);
1274         return;
1275         }
1279 //#############################
1280 //#  C O M P R E S S
1281 //#############################
1284 /**
1285  * This method does the dirty work of dictionary
1286  * compression.  Basically it looks for redundant
1287  * strings and has the current duplicate refer back
1288  * to the previous one.
1289  */
1290 bool Deflater::compressWindow()
1292     windowPos = 0;
1293     unsigned int windowSize = window.size();
1294     //### Compress as much of the window as possible
1296     unsigned int hash = 0;
1297     //Have each value be a long with the byte at this position,
1298     //plus the 3 bytes after it in the window
1299     for (int i=windowSize-1 ; i>=0 ; i--)
1300         {
1301         unsigned char ch = window[i];
1302         windowBuf[i] = ch;
1303         hash = ((hash<<8) & 0xffffff00) | ch;
1304         windowHashBuf[i] = hash;
1305         }
1307     while (windowPos < windowSize - 3)
1308         {
1309         //### Find best match, if any
1310         unsigned int bestMatchLen  = 0;
1311         unsigned int bestMatchDist = 0;
1312         if (windowPos >= 4)
1313             {
1314             for (unsigned int lookBack=0 ; lookBack<windowPos-4 ; lookBack++)
1315                 {
1316                 //Check 4-char hashes first, before continuing with string
1317                 if (windowHashBuf[lookBack] == windowHashBuf[windowPos])
1318                     {
1319                     unsigned int lookAhead=4;
1320                     unsigned int lookAheadMax = windowSize - 4 - windowPos;
1321                     if (lookBack + lookAheadMax >= windowPos -4 )
1322                         lookAheadMax = windowPos - 4 - lookBack;
1323                     if (lookAheadMax > 258)
1324                         lookAheadMax = 258;
1325                     unsigned char *wp = &(windowBuf[windowPos+4]);
1326                     unsigned char *lb = &(windowBuf[lookBack+4]);
1327                     while (lookAhead<lookAheadMax)
1328                         {
1329                         if (*lb++ != *wp++)
1330                             break;
1331                         lookAhead++;
1332                         }
1333                     if (lookAhead > bestMatchLen)
1334                         {
1335                         bestMatchLen  = lookAhead;
1336                         bestMatchDist = windowPos - lookBack;
1337                         }
1338                     }
1339                 }
1340             }
1341         if (bestMatchLen > 3)
1342             {
1343             //Distance encode
1344             //trace("### distance");
1345             /*
1346             printf("### 1 '");
1347             for (int i=0 ; i < bestMatchLen ; i++)
1348                 fputc(window[windowPos+i], stdout);
1349             printf("'\n### 2 '");
1350             for (int i=0 ; i < bestMatchLen ; i++)
1351                 fputc(window[windowPos-bestMatchDist+i], stdout);
1352             printf("'\n");
1353             */
1354             encodeDistStatic(bestMatchLen, bestMatchDist);
1355             windowPos += bestMatchLen;
1356             }
1357         else
1358             {
1359             //Literal encode
1360             //trace("### literal");
1361             encodeLiteralStatic(windowBuf[windowPos]);
1362             windowPos++;
1363             }
1364         }
1366     while (windowPos < windowSize)
1367         encodeLiteralStatic(windowBuf[windowPos++]);
1369     encodeLiteralStatic(256);
1370     return true;
1374 /**
1375  *
1376  */
1377 bool Deflater::compress()
1379     //trace("compress");
1380     unsigned long total = 0L;
1381     windowPos = 0;
1382     std::vector<unsigned char>::iterator iter;
1383     for (iter = uncompressed.begin(); iter != uncompressed.end() ; )
1384         {
1385         total += windowPos;
1386         trace("total:%ld", total);
1387         if (windowPos > window.size())
1388             windowPos = window.size();
1389         window.erase(window.begin() , window.begin()+windowPos);
1390         while (window.size() < 32768 && iter != uncompressed.end())
1391             {
1392             window.push_back(*iter);
1393             iter++;
1394             }
1395         if (window.size() >= 32768)
1396             putBits(0x00, 1); //0  -- more blocks
1397         else
1398             putBits(0x01, 1); //1  -- last block
1399         putBits(0x01, 2); //01 -- static trees
1400         if (!compressWindow())
1401             return false;
1402         }
1403     putFlush();
1404     return true;
1411 //########################################################################
1412 //#  G Z I P    F I L E
1413 //########################################################################
1415 /**
1416  * Constructor
1417  */
1418 GzipFile::GzipFile()
1422 /**
1423  * Destructor
1424  */
1425 GzipFile::~GzipFile()
1429 /**
1430  *  Print error messages
1431  */
1432 void GzipFile::error(char const *fmt, ...)
1434     va_list args;
1435     va_start(args, fmt);
1436     fprintf(stdout, "GzipFile error:");
1437     vfprintf(stdout, fmt, args);
1438     fprintf(stdout, "\n");
1439     va_end(args);
1442 /**
1443  *  Print trace messages
1444  */
1445 void GzipFile::trace(char const *fmt, ...)
1447     va_list args;
1448     va_start(args, fmt);
1449     fprintf(stdout, "GzipFile:");
1450     vfprintf(stdout, fmt, args);
1451     fprintf(stdout, "\n");
1452     va_end(args);
1455 /**
1456  *
1457  */
1458 void GzipFile::put(unsigned char ch)
1460     data.push_back(ch);
1463 /**
1464  *
1465  */
1466 void GzipFile::setData(const std::vector<unsigned char> &str)
1468     data = str;
1471 /**
1472  *
1473  */
1474 void GzipFile::clearData()
1476     data.clear();
1479 /**
1480  *
1481  */
1482 std::vector<unsigned char> &GzipFile::getData()
1484     return data;
1487 /**
1488  *
1489  */
1490 std::string &GzipFile::getFileName()
1492     return fileName;
1495 /**
1496  *
1497  */
1498 void GzipFile::setFileName(const std::string &val)
1500     fileName = val;
1505 //#####################################
1506 //# U T I L I T Y
1507 //#####################################
1509 /**
1510  *  Loads a new file into an existing GzipFile
1511  */
1512 bool GzipFile::loadFile(const std::string &fName)
1514     FILE *f = fopen(fName.c_str() , "rb");
1515     if (!f)
1516         {
1517         error("Cannot open file %s", fName.c_str());
1518         return false;
1519         }
1520     while (true)
1521         {
1522         int ch = fgetc(f);
1523         if (ch < 0)
1524             break;
1525         data.push_back(ch);
1526         }
1527     fclose(f);
1528     setFileName(fName);
1529     return true;
1534 //#####################################
1535 //# W R I T E
1536 //#####################################
1538 /**
1539  *
1540  */
1541 bool GzipFile::putByte(unsigned char ch)
1543     fileBuf.push_back(ch);
1544     return true;
1549 /**
1550  *
1551  */
1552 bool GzipFile::putLong(unsigned long val)
1554     fileBuf.push_back( (unsigned char)((val    ) & 0xff));
1555     fileBuf.push_back( (unsigned char)((val>> 8) & 0xff));
1556     fileBuf.push_back( (unsigned char)((val>>16) & 0xff));
1557     fileBuf.push_back( (unsigned char)((val>>24) & 0xff));
1558     return true;
1563 /**
1564  *
1565  */
1566 bool GzipFile::write()
1568     fileBuf.clear();
1570     putByte(0x1f); //magic
1571     putByte(0x8b); //magic
1572     putByte(   8); //compression method
1573     putByte(0x08); //flags.  say we have a crc and file name
1575     unsigned long ltime = (unsigned long) time(NULL);
1576     putLong(ltime);
1578     //xfl
1579     putByte(0);
1580     //OS
1581     putByte(0);
1583     //file name
1584     for (unsigned int i=0 ; i<fileName.size() ; i++)
1585         putByte(fileName[i]);
1586     putByte(0);
1589     //compress
1590     std::vector<unsigned char> compBuf;
1591     Deflater deflater;
1592     if (!deflater.deflate(compBuf, data))
1593         {
1594         return false;
1595         }
1597     std::vector<unsigned char>::iterator iter;
1598     for (iter=compBuf.begin() ; iter!=compBuf.end() ; iter++)
1599         {
1600         unsigned char ch = *iter;
1601         putByte(ch);
1602         }
1604     Crc32 crcEngine;
1605     crcEngine.update(data);
1606     unsigned long crc = crcEngine.getValue();
1607     putLong(crc);
1609     putLong(data.size());
1611     return true;
1615 /**
1616  *
1617  */
1618 bool GzipFile::writeBuffer(std::vector<unsigned char> &outBuf)
1620     if (!write())
1621         return false;
1622     outBuf.clear();
1623     outBuf = fileBuf;
1624     return true;
1628 /**
1629  *
1630  */
1631 bool GzipFile::writeFile(const std::string &fileName)
1633     if (!write())
1634         return false;
1635     FILE *f = fopen(fileName.c_str(), "wb");
1636     if (!f)
1637         return false;
1638     std::vector<unsigned char>::iterator iter;
1639     for (iter=fileBuf.begin() ; iter!=fileBuf.end() ; iter++)
1640         {
1641         unsigned char ch = *iter;
1642         fputc(ch, f);
1643         }
1644     fclose(f);
1645     return true;
1649 //#####################################
1650 //# R E A D
1651 //#####################################
1653 bool GzipFile::getByte(unsigned char *ch)
1655     if (fileBufPos >= fileBuf.size())
1656         {
1657         error("unexpected end of data");
1658         return false;
1659         }
1660     *ch = fileBuf[fileBufPos++];
1661     return true;
1664 /**
1665  *
1666  */
1667 bool GzipFile::getLong(unsigned long *val)
1669     if (fileBuf.size() - fileBufPos < 4)
1670         return false;
1671     int ch1 = fileBuf[fileBufPos++];
1672     int ch2 = fileBuf[fileBufPos++];
1673     int ch3 = fileBuf[fileBufPos++];
1674     int ch4 = fileBuf[fileBufPos++];
1675     *val = ((ch4<<24) & 0xff000000L) |
1676            ((ch3<<16) & 0x00ff0000L) |
1677            ((ch2<< 8) & 0x0000ff00L) |
1678            ((ch1    ) & 0x000000ffL);
1679     return true;
1682 bool GzipFile::read()
1684     fileBufPos = 0;
1686     unsigned char ch;
1688     //magic cookie
1689     if (!getByte(&ch))
1690         return false;
1691     if (ch != 0x1f)
1692         {
1693         error("bad gzip header");
1694         return false;
1695         }
1696     if (!getByte(&ch))
1697         return false;
1698     if (ch != 0x8b)
1699         {
1700         error("bad gzip header");
1701         return false;
1702         }
1704     //## compression method
1705     if (!getByte(&ch))
1706         return false;
1707     compressionMethod = ch & 0xff;
1709     //## flags
1710     if (!getByte(&ch))
1711         return false;
1712     //bool ftext    = ch & 0x01;
1713     bool fhcrc    = ch & 0x02;
1714     bool fextra   = ch & 0x04;
1715     bool fname    = ch & 0x08;
1716     bool fcomment = ch & 0x10;
1718     //trace("cm:%d ftext:%d fhcrc:%d fextra:%d fname:%d fcomment:%d",
1719     //         cm, ftext, fhcrc, fextra, fname, fcomment);
1721     //## file time
1722     unsigned long ltime;
1723     if (!getLong(&ltime))
1724         return false;
1725     //time_t mtime = (time_t)ltime;
1727     //## XFL
1728     if (!getByte(&ch))
1729         return false;
1730     //int xfl = ch;
1732     //## OS
1733     if (!getByte(&ch))
1734         return false;
1735     //int os = ch;
1737     //std::string timestr = ctime(&mtime);
1738     //trace("xfl:%d os:%d mtime:%s", xfl, os, timestr.c_str());
1740     if (fextra)
1741         {
1742         if (!getByte(&ch))
1743             return false;
1744         long xlen = ch;
1745         if (!getByte(&ch))
1746             return false;
1747         xlen = (xlen << 8) + ch;
1748         for (long l=0 ; l<xlen ; l++)
1749             {
1750             if (!getByte(&ch))
1751                 return false;
1752             }
1753         }
1755     if (fname)
1756         {
1757         fileName = "";
1758         while (true)
1759             {
1760             if (!getByte(&ch))
1761                 return false;
1762             if (ch==0)
1763                 break;
1764             fileName.push_back(ch);
1765             }
1766         }
1768     if (fcomment)
1769         {
1770         while (true)
1771             {
1772             if (!getByte(&ch))
1773                 return false;
1774             if (ch==0)
1775                 break;
1776             }
1777         }
1779     if (fhcrc)
1780         {
1781         if (!getByte(&ch))
1782             return false;
1783         if (!getByte(&ch))
1784             return false;
1785         }
1787     //read remainder of stream
1788     //compressed data runs up until 8 bytes before end of buffer
1789     std::vector<unsigned char> compBuf;
1790     while (fileBufPos < fileBuf.size() - 8)
1791         {
1792         if (!getByte(&ch))
1793             return false;
1794         compBuf.push_back(ch);
1795         }
1796     //uncompress
1797     data.clear();
1798     Inflater inflater;
1799     if (!inflater.inflate(data, compBuf))
1800         {
1801         return false;
1802         }
1804     //Get the CRC and compare
1805     Crc32 crcEngine;
1806     crcEngine.update(data);
1807     unsigned long calcCrc = crcEngine.getValue();
1808     unsigned long givenCrc;
1809     if (!getLong(&givenCrc))
1810         return false;
1811     if (givenCrc != calcCrc)
1812         {
1813         error("Specified crc, %ud, not what received: %ud",
1814                 givenCrc, calcCrc);
1815         return false;
1816         }
1818     //Get the file size and compare
1819     unsigned long givenFileSize;
1820     if (!getLong(&givenFileSize))
1821         return false;
1822     if (givenFileSize != data.size())
1823         {
1824         error("Specified data size, %ld, not what received: %ld",
1825                 givenFileSize, data.size());
1826         return false;
1827         }
1829     return true;
1834 /**
1835  *
1836  */
1837 bool GzipFile::readBuffer(const std::vector<unsigned char> &inbuf)
1839     fileBuf = inbuf;
1840     if (!read())
1841         return false;
1842     return true;
1846 /**
1847  *
1848  */
1849 bool GzipFile::readFile(const std::string &fileName)
1851     fileBuf.clear();
1852     FILE *f = fopen(fileName.c_str(), "rb");
1853     if (!f)
1854         return false;
1855     while (true)
1856         {
1857         int ch = fgetc(f);
1858         if (ch < 0)
1859             break;
1860         fileBuf.push_back(ch);
1861         }
1862     fclose(f);
1863     if (!read())
1864         return false;
1865     return true;
1875 //########################################################################
1876 //#  Z I P    F I L E
1877 //########################################################################
1879 /**
1880  * Constructor
1881  */
1882 ZipEntry::ZipEntry()
1884     crc               = 0L;
1885     compressionMethod = 8;
1888 /**
1889  *
1890  */
1891 ZipEntry::ZipEntry(const std::string &fileNameArg,
1892                    const std::string &commentArg)
1894     crc               = 0L;
1895     compressionMethod = 8;
1896     fileName          = fileNameArg;
1897     comment           = commentArg;
1900 /**
1901  * Destructor
1902  */
1903 ZipEntry::~ZipEntry()
1908 /**
1909  *
1910  */
1911 std::string ZipEntry::getFileName()
1913     return fileName;
1916 /**
1917  *
1918  */
1919 void ZipEntry::setFileName(const std::string &val)
1921     fileName = val;
1924 /**
1925  *
1926  */
1927 std::string ZipEntry::getComment()
1929     return comment;
1932 /**
1933  *
1934  */
1935 void ZipEntry::setComment(const std::string &val)
1937     comment = val;
1940 /**
1941  *
1942  */
1943 unsigned long ZipEntry::getCompressedSize()
1945     return (unsigned long)compressedData.size();
1948 /**
1949  *
1950  */
1951 int ZipEntry::getCompressionMethod()
1953     return compressionMethod;
1956 /**
1957  *
1958  */
1959 void ZipEntry::setCompressionMethod(int val)
1961     compressionMethod = val;
1964 /**
1965  *
1966  */
1967 std::vector<unsigned char> &ZipEntry::getCompressedData()
1969     return compressedData;
1972 /**
1973  *
1974  */
1975 void ZipEntry::setCompressedData(const std::vector<unsigned char> &val)
1977     compressedData = val;
1980 /**
1981  *
1982  */
1983 unsigned long ZipEntry::getUncompressedSize()
1985     return (unsigned long)uncompressedData.size();
1988 /**
1989  *
1990  */
1991 std::vector<unsigned char> &ZipEntry::getUncompressedData()
1993     return uncompressedData;
1996 /**
1997  *
1998  */
1999 void ZipEntry::setUncompressedData(const std::vector<unsigned char> &val)
2001     uncompressedData = val;
2004 /**
2005  *
2006  */
2007 unsigned long ZipEntry::getCrc()
2009     return crc;
2012 /**
2013  *
2014  */
2015 void ZipEntry::setCrc(unsigned long val)
2017     crc = val;
2020 /**
2021  *
2022  */
2023 void ZipEntry::write(unsigned char ch)
2025     uncompressedData.push_back(ch);
2028 /**
2029  *
2030  */
2031 void ZipEntry::finish()
2033     Crc32 c32;
2034     std::vector<unsigned char>::iterator iter;
2035     for (iter = uncompressedData.begin() ;
2036            iter!= uncompressedData.end() ; iter++)
2037         {
2038         unsigned char ch = *iter;
2039         c32.update(ch);
2040         }
2041     crc = c32.getValue();
2042     switch (compressionMethod)
2043         {
2044         case 0: //none
2045             {
2046             for (iter = uncompressedData.begin() ;
2047                iter!= uncompressedData.end() ; iter++)
2048                 {
2049                 unsigned char ch = *iter;
2050                 compressedData.push_back(ch);
2051                 }
2052             break;
2053             }
2054         case 8: //deflate
2055             {
2056             Deflater deflater;
2057             if (!deflater.deflate(compressedData, uncompressedData))
2058                 {
2059                 //some error
2060                 }
2061             break;
2062             }
2063         default:
2064             {
2065             printf("error: unknown compression method %d\n",
2066                     compressionMethod);
2067             }
2068         }
2074 /**
2075  *
2076  */
2077 bool ZipEntry::readFile(const std::string &fileNameArg,
2078                         const std::string &commentArg)
2080     crc = 0L;
2081     uncompressedData.clear();
2082     fileName = fileNameArg;
2083     comment  = commentArg;
2084     FILE *f = fopen(fileName.c_str(), "rb");
2085     if (!f)
2086         {
2087         return false;
2088         }
2089     while (true)
2090         {
2091         int ch = fgetc(f);
2092         if (ch < 0)
2093             break;
2094         uncompressedData.push_back((unsigned char)ch);
2095         }
2096     fclose(f);
2097     finish();
2098     return true;
2102 /**
2103  *
2104  */
2105 void ZipEntry::setPosition(unsigned long val)
2107     position = val;
2110 /**
2111  *
2112  */
2113 unsigned long ZipEntry::getPosition()
2115     return position;
2124 /**
2125  * Constructor
2126  */
2127 ZipFile::ZipFile()
2132 /**
2133  * Destructor
2134  */
2135 ZipFile::~ZipFile()
2137     std::vector<ZipEntry *>::iterator iter;
2138     for (iter=entries.begin() ; iter!=entries.end() ; iter++)
2139         {
2140         ZipEntry *entry = *iter;
2141         delete entry;
2142         }
2143     entries.clear();
2146 /**
2147  *
2148  */
2149 void ZipFile::setComment(const std::string &val)
2151     comment = val;
2154 /**
2155  *
2156  */
2157 std::string ZipFile::getComment()
2159     return comment;
2163 /**
2164  *
2165  */
2166 std::vector<ZipEntry *> &ZipFile::getEntries()
2168     return entries;
2173 //#####################################
2174 //# M E S S A G E S
2175 //#####################################
2177 void ZipFile::error(char const *fmt, ...)
2179     va_list args;
2180     va_start(args, fmt);
2181     fprintf(stdout, "ZipFile error:");
2182     vfprintf(stdout, fmt, args);
2183     fprintf(stdout, "\n");
2184     va_end(args);
2187 void ZipFile::trace(char const *fmt, ...)
2189     va_list args;
2190     va_start(args, fmt);
2191     fprintf(stdout, "ZipFile:");
2192     vfprintf(stdout, fmt, args);
2193     fprintf(stdout, "\n");
2194     va_end(args);
2197 //#####################################
2198 //# U T I L I T Y
2199 //#####################################
2201 /**
2202  *
2203  */
2204 ZipEntry *ZipFile::addFile(const std::string &fileName,
2205                       const std::string &comment)
2207     ZipEntry *ze = new ZipEntry();
2208     if (!ze->readFile(fileName, comment))
2209         {
2210         delete ze;
2211         return NULL;
2212         }
2213     entries.push_back(ze);
2214     return ze;
2218 /**
2219  *
2220  */
2221 ZipEntry *ZipFile::newEntry(const std::string &fileName,
2222                             const std::string &comment)
2224     ZipEntry *ze = new ZipEntry(fileName, comment);
2225     entries.push_back(ze);
2226     return ze;
2230 //#####################################
2231 //# W R I T E
2232 //#####################################
2234 /**
2235  *
2236  */
2237 bool ZipFile::putLong(unsigned long val)
2239     fileBuf.push_back( ((int)(val    )) & 0xff);
2240     fileBuf.push_back( ((int)(val>> 8)) & 0xff);
2241     fileBuf.push_back( ((int)(val>>16)) & 0xff);
2242     fileBuf.push_back( ((int)(val>>24)) & 0xff);
2243     return true;
2247 /**
2248  *
2249  */
2250 bool ZipFile::putInt(unsigned int val)
2252     fileBuf.push_back( (val    ) & 0xff);
2253     fileBuf.push_back( (val>> 8) & 0xff);
2254     return true;
2257 /**
2258  *
2259  */
2260 bool ZipFile::putByte(unsigned char val)
2262     fileBuf.push_back(val);
2263     return true;
2266 /**
2267  *
2268  */
2269 bool ZipFile::writeFileData()
2271     std::vector<ZipEntry *>::iterator iter;
2272     for (iter = entries.begin() ; iter != entries.end() ; iter++)
2273         {
2274         ZipEntry *entry = *iter;
2275         entry->setPosition(fileBuf.size());
2276         //##### HEADER
2277         std::string fname = entry->getFileName();
2278         putLong(0x04034b50L);
2279         putInt(20); //versionNeeded
2280         putInt(0); //gpBitFlag
2281         //putInt(0); //compression method
2282         putInt(entry->getCompressionMethod()); //compression method
2283         putInt(0); //mod time
2284         putInt(0); //mod date
2285         putLong(entry->getCrc()); //crc32
2286         putLong(entry->getCompressedSize());
2287         putLong(entry->getUncompressedSize());
2288         putInt(fname.size());//fileName length
2289         putInt(8);//extra field length
2290         //file name
2291         for (unsigned int i=0 ; i<fname.size() ; i++)
2292             putByte((unsigned char)fname[i]);
2293         //extra field
2294         putInt(0x7855);
2295         putInt(4);
2296         putInt(100);
2297         putInt(100);
2299         //##### DATA
2300         std::vector<unsigned char> &buf = entry->getCompressedData();
2301         std::vector<unsigned char>::iterator iter;
2302         for (iter = buf.begin() ; iter != buf.end() ; iter++)
2303             {
2304             unsigned char ch = (unsigned char) *iter;
2305             putByte(ch);
2306             }
2307         }
2308     return true;
2311 /**
2312  *
2313  */
2314 bool ZipFile::writeCentralDirectory()
2316     unsigned long cdPosition = fileBuf.size();
2317     std::vector<ZipEntry *>::iterator iter;
2318     for (iter = entries.begin() ; iter != entries.end() ; iter++)
2319         {
2320         ZipEntry *entry = *iter;
2321         std::string fname   = entry->getFileName();
2322         std::string ecomment = entry->getComment();
2323         putLong(0x02014b50L);  //magic cookie
2324         putInt(2386); //versionMadeBy
2325         putInt(20); //versionNeeded
2326         putInt(0); //gpBitFlag
2327         putInt(entry->getCompressionMethod()); //compression method
2328         putInt(0); //mod time
2329         putInt(0); //mod date
2330         putLong(entry->getCrc()); //crc32
2331         putLong(entry->getCompressedSize());
2332         putLong(entry->getUncompressedSize());
2333         putInt(fname.size());//fileName length
2334         putInt(4);//extra field length
2335         putInt(ecomment.size());//comment length
2336         putInt(0); //disk number start
2337         putInt(0); //internal attributes
2338         putLong(0); //external attributes
2339         putLong(entry->getPosition());
2341         //file name
2342         for (unsigned int i=0 ; i<fname.size() ; i++)
2343             putByte((unsigned char)fname[i]);
2344         //extra field
2345         putInt(0x7855);
2346         putInt(0);
2347         //comment
2348         for (unsigned int i=0 ; i<ecomment.size() ; i++)
2349             putByte((unsigned char)ecomment[i]);
2350         }
2351     unsigned long cdSize = fileBuf.size() - cdPosition;
2353     putLong(0x06054b50L);
2354     putInt(0);//number of this disk
2355     putInt(0);//nr of disk with central dir
2356     putInt(entries.size()); //number of entries on this disk
2357     putInt(entries.size()); //number of entries total
2358     putLong(cdSize);  //size of central dir
2359     putLong(cdPosition); //position of central dir
2360     putInt(comment.size());//comment size
2361     for (unsigned int i=0 ; i<comment.size() ; i++)
2362         putByte(comment[i]);
2363     return true;
2368 /**
2369  *
2370  */
2371 bool ZipFile::write()
2373     fileBuf.clear();
2374     if (!writeFileData())
2375         return false;
2376     if (!writeCentralDirectory())
2377         return false;
2378     return true;
2382 /**
2383  *
2384  */
2385 bool ZipFile::writeBuffer(std::vector<unsigned char> &outBuf)
2387     if (!write())
2388         return false;
2389     outBuf.clear();
2390     outBuf = fileBuf;
2391     return true;
2395 /**
2396  *
2397  */
2398 bool ZipFile::writeFile(const std::string &fileName)
2400     if (!write())
2401         return false;
2402     FILE *f = fopen(fileName.c_str(), "wb");
2403     if (!f)
2404         return false;
2405     std::vector<unsigned char>::iterator iter;
2406     for (iter=fileBuf.begin() ; iter!=fileBuf.end() ; iter++)
2407         {
2408         unsigned char ch = *iter;
2409         fputc(ch, f);
2410         }
2411     fclose(f);
2412     return true;
2415 //#####################################
2416 //# R E A D
2417 //#####################################
2419 /**
2420  *
2421  */
2422 bool ZipFile::getLong(unsigned long *val)
2424     if (fileBuf.size() - fileBufPos < 4)
2425         return false;
2426     int ch1 = fileBuf[fileBufPos++];
2427     int ch2 = fileBuf[fileBufPos++];
2428     int ch3 = fileBuf[fileBufPos++];
2429     int ch4 = fileBuf[fileBufPos++];
2430     *val = ((ch4<<24) & 0xff000000L) |
2431            ((ch3<<16) & 0x00ff0000L) |
2432            ((ch2<< 8) & 0x0000ff00L) |
2433            ((ch1    ) & 0x000000ffL);
2434     return true;
2437 /**
2438  *
2439  */
2440 bool ZipFile::getInt(unsigned int *val)
2442     if (fileBuf.size() - fileBufPos < 2)
2443         return false;
2444     int ch1 = fileBuf[fileBufPos++];
2445     int ch2 = fileBuf[fileBufPos++];
2446     *val = ((ch2<< 8) & 0xff00) |
2447            ((ch1    ) & 0x00ff);
2448     return true;
2452 /**
2453  *
2454  */
2455 bool ZipFile::getByte(unsigned char *val)
2457     if (fileBuf.size() <= fileBufPos)
2458         return false;
2459     *val = fileBuf[fileBufPos++];
2460     return true;
2464 /**
2465  *
2466  */
2467 bool ZipFile::readFileData()
2469     //printf("#################################################\n");
2470     //printf("###D A T A\n");
2471     //printf("#################################################\n");
2472     while (true)
2473         {
2474         unsigned long magicCookie;
2475         if (!getLong(&magicCookie))
2476             {
2477             error("magic cookie not found");
2478             break;
2479             }
2480         trace("###Cookie:%lx", magicCookie);
2481         if (magicCookie == 0x02014b50L) //central directory
2482             break;
2483         if (magicCookie != 0x04034b50L)
2484             {
2485             error("file header not found");
2486             return false;
2487             }
2488         unsigned int versionNeeded;
2489         if (!getInt(&versionNeeded))
2490             {
2491             error("bad version needed found");
2492             return false;
2493             }
2494         unsigned int gpBitFlag;
2495         if (!getInt(&gpBitFlag))
2496             {
2497             error("bad bit flag found");
2498             return false;
2499             }
2500         unsigned int compressionMethod;
2501         if (!getInt(&compressionMethod))
2502             {
2503             error("bad compressionMethod found");
2504             return false;
2505             }
2506         unsigned int modTime;
2507         if (!getInt(&modTime))
2508             {
2509             error("bad modTime found");
2510             return false;
2511             }
2512         unsigned int modDate;
2513         if (!getInt(&modDate))
2514             {
2515             error("bad modDate found");
2516             return false;
2517             }
2518         unsigned long crc32;
2519         if (!getLong(&crc32))
2520             {
2521             error("bad crc32 found");
2522             return false;
2523             }
2524         unsigned long compressedSize;
2525         if (!getLong(&compressedSize))
2526             {
2527             error("bad compressedSize found");
2528             return false;
2529             }
2530         unsigned long uncompressedSize;
2531         if (!getLong(&uncompressedSize))
2532             {
2533             error("bad uncompressedSize found");
2534             return false;
2535             }
2536         unsigned int fileNameLength;
2537         if (!getInt(&fileNameLength))
2538             {
2539             error("bad fileNameLength found");
2540             return false;
2541             }
2542         unsigned int extraFieldLength;
2543         if (!getInt(&extraFieldLength))
2544             {
2545             error("bad extraFieldLength found");
2546             return false;
2547             }
2548         std::string fileName;
2549         for (unsigned int i=0 ; i<fileNameLength ; i++)
2550             {
2551             unsigned char ch;
2552             if (!getByte(&ch))
2553                 break;
2554             fileName.push_back(ch);
2555             }
2556         std::string extraField;
2557         for (unsigned int i=0 ; i<extraFieldLength ; i++)
2558             {
2559             unsigned char ch;
2560             if (!getByte(&ch))
2561                 break;
2562             extraField.push_back(ch);
2563             }
2564         trace("#########################  DATA");
2565         trace("FileName           :%d:%s" , fileName.size(), fileName.c_str());
2566         trace("Extra field        :%d:%s" , extraField.size(), extraField.c_str());
2567         trace("Version needed     :%d" , versionNeeded);
2568         trace("Bitflag            :%d" , gpBitFlag);
2569         trace("Compression Method :%d" , compressionMethod);
2570         trace("Mod time           :%d" , modTime);
2571         trace("Mod date           :%d" , modDate);
2572         trace("CRC                :%lx", crc32);
2573         trace("Compressed size    :%ld", compressedSize);
2574         trace("Uncompressed size  :%ld", uncompressedSize);
2576         //#### Uncompress the data
2577         std::vector<unsigned char> compBuf;
2578         if (gpBitFlag & 0x8)//bit 3 was set.  means we dont know compressed size
2579             {
2580             unsigned char c1, c2, c3, c4;
2581             c1 = c2 = c3 = c4 = 0;
2582             while (true)
2583                 {
2584                 unsigned char ch;
2585                 if (!getByte(&ch))
2586                     {
2587                     error("premature end of data");
2588                     break;
2589                     }
2590                 compBuf.push_back(ch);
2591                 c1 = c2; c2 = c3; c3 = c4; c4 = ch;
2592                 if (c1 == 0x50 && c2 == 0x4b && c3 == 0x07 && c4 == 0x08)
2593                     {
2594                     trace("found end of compressed data");
2595                     //remove the cookie
2596                     compBuf.erase(compBuf.end() -4, compBuf.end());
2597                     break;
2598                     }
2599                 }
2600             }
2601         else
2602             {
2603             for (unsigned long bnr = 0 ; bnr < compressedSize ; bnr++)
2604                 {
2605                 unsigned char ch;
2606                 if (!getByte(&ch))
2607                     {
2608                     error("premature end of data");
2609                     break;
2610                     }
2611                 compBuf.push_back(ch);
2612                 }
2613             }
2615         printf("### data: ");
2616         for (int i=0 ; i<10 ; i++)
2617             printf("%02x ", compBuf[i] & 0xff);
2618         printf("\n");
2620         if (gpBitFlag & 0x8)//only if bit 3 set
2621             {
2622             /* this cookie was read in the loop above
2623             unsigned long dataDescriptorSignature ;
2624             if (!getLong(&dataDescriptorSignature))
2625                 break;
2626             if (dataDescriptorSignature != 0x08074b50L)
2627                 {
2628                 error("bad dataDescriptorSignature found");
2629                 return false;
2630                 }
2631             */
2632             unsigned long crc32;
2633             if (!getLong(&crc32))
2634                 {
2635                 error("bad crc32 found");
2636                 return false;
2637                 }
2638             unsigned long compressedSize;
2639             if (!getLong(&compressedSize))
2640                 {
2641                 error("bad compressedSize found");
2642                 return false;
2643                 }
2644             unsigned long uncompressedSize;
2645             if (!getLong(&uncompressedSize))
2646                 {
2647                 error("bad uncompressedSize found");
2648                 return false;
2649                 }
2650             }//bit 3 was set
2651         //break;
2653         std::vector<unsigned char> uncompBuf;
2654         switch (compressionMethod)
2655             {
2656             case 8: //deflate
2657                 {
2658                 Inflater inflater;
2659                 if (!inflater.inflate(uncompBuf, compBuf))
2660                     {
2661                     return false;
2662                     }
2663                 break;
2664                 }
2665             default:
2666                 {
2667                 error("Unimplemented compression method %d", compressionMethod);
2668                 return false;
2669                 }
2670             }
2672         if (uncompressedSize != uncompBuf.size())
2673             {
2674             error("Size mismatch.  Expected %ld, received %ld",
2675                 uncompressedSize, uncompBuf.size());
2676             return false;
2677             }
2679         Crc32 crcEngine;
2680         crcEngine.update(uncompBuf);
2681         unsigned long crc = crcEngine.getValue();
2682         if (crc != crc32)
2683             {
2684             error("Crc mismatch.  Calculated %08ux, received %08ux", crc, crc32);
2685             return false;
2686             }
2688         ZipEntry *ze = new ZipEntry(fileName, comment);
2689         ze->setCompressionMethod(compressionMethod);
2690         ze->setCompressedData(compBuf);
2691         ze->setUncompressedData(uncompBuf);
2692         ze->setCrc(crc);
2693         entries.push_back(ze);
2696         }
2697     return true;
2701 /**
2702  *
2703  */
2704 bool ZipFile::readCentralDirectory()
2706     //printf("#################################################\n");
2707     //printf("###D I R E C T O R Y\n");
2708     //printf("#################################################\n");
2709     while (true)
2710         {
2711         //We start with a central directory cookie already
2712         //Check at the bottom of the loop.
2713         unsigned int version;
2714         if (!getInt(&version))
2715             {
2716             error("bad version found");
2717             return false;
2718             }
2719         unsigned int versionNeeded;
2720         if (!getInt(&versionNeeded))
2721             {
2722             error("bad version found");
2723             return false;
2724             }
2725         unsigned int gpBitFlag;
2726         if (!getInt(&gpBitFlag))
2727             {
2728             error("bad bit flag found");
2729             return false;
2730             }
2731         unsigned int compressionMethod;
2732         if (!getInt(&compressionMethod))
2733             {
2734             error("bad compressionMethod found");
2735             return false;
2736             }
2737         unsigned int modTime;
2738         if (!getInt(&modTime))
2739             {
2740             error("bad modTime found");
2741             return false;
2742             }
2743         unsigned int modDate;
2744         if (!getInt(&modDate))
2745             {
2746             error("bad modDate found");
2747             return false;
2748             }
2749         unsigned long crc32;
2750         if (!getLong(&crc32))
2751             {
2752             error("bad crc32 found");
2753             return false;
2754             }
2755         unsigned long compressedSize;
2756         if (!getLong(&compressedSize))
2757             {
2758             error("bad compressedSize found");
2759             return false;
2760             }
2761         unsigned long uncompressedSize;
2762         if (!getLong(&uncompressedSize))
2763             {
2764             error("bad uncompressedSize found");
2765             return false;
2766             }
2767         unsigned int fileNameLength;
2768         if (!getInt(&fileNameLength))
2769             {
2770             error("bad fileNameLength found");
2771             return false;
2772             }
2773         unsigned int extraFieldLength;
2774         if (!getInt(&extraFieldLength))
2775             {
2776             error("bad extraFieldLength found");
2777             return false;
2778             }
2779         unsigned int fileCommentLength;
2780         if (!getInt(&fileCommentLength))
2781             {
2782             error("bad fileCommentLength found");
2783             return false;
2784             }
2785         unsigned int diskNumberStart;
2786         if (!getInt(&diskNumberStart))
2787             {
2788             error("bad diskNumberStart found");
2789             return false;
2790             }
2791         unsigned int internalFileAttributes;
2792         if (!getInt(&internalFileAttributes))
2793             {
2794             error("bad internalFileAttributes found");
2795             return false;
2796             }
2797         unsigned long externalFileAttributes;
2798         if (!getLong(&externalFileAttributes))
2799             {
2800             error("bad externalFileAttributes found");
2801             return false;
2802             }
2803         unsigned long localHeaderOffset;
2804         if (!getLong(&localHeaderOffset))
2805             {
2806             error("bad localHeaderOffset found");
2807             return false;
2808             }
2809         std::string fileName;
2810         for (unsigned int i=0 ; i<fileNameLength ; i++)
2811             {
2812             unsigned char ch;
2813             if (!getByte(&ch))
2814                 break;
2815             fileName.push_back(ch);
2816             }
2817         std::string extraField;
2818         for (unsigned int i=0 ; i<extraFieldLength ; i++)
2819             {
2820             unsigned char ch;
2821             if (!getByte(&ch))
2822                 break;
2823             extraField.push_back(ch);
2824             }
2825         std::string fileComment;
2826         for (unsigned int i=0 ; i<fileCommentLength ; i++)
2827             {
2828             unsigned char ch;
2829             if (!getByte(&ch))
2830                 break;
2831             fileComment.push_back(ch);
2832             }
2833         trace("######################### ENTRY");
2834         trace("FileName           :%s" , fileName.c_str());
2835         trace("Extra field        :%s" , extraField.c_str());
2836         trace("File comment       :%s" , fileComment.c_str());
2837         trace("Version            :%d" , version);
2838         trace("Version needed     :%d" , versionNeeded);
2839         trace("Bitflag            :%d" , gpBitFlag);
2840         trace("Compression Method :%d" , compressionMethod);
2841         trace("Mod time           :%d" , modTime);
2842         trace("Mod date           :%d" , modDate);
2843         trace("CRC                :%lx", crc32);
2844         trace("Compressed size    :%ld", compressedSize);
2845         trace("Uncompressed size  :%ld", uncompressedSize);
2846         trace("Disk nr start      :%ld", diskNumberStart);
2847         trace("Header offset      :%ld", localHeaderOffset);
2850         unsigned long magicCookie;
2851         if (!getLong(&magicCookie))
2852             {
2853             error("magic cookie not found");
2854             return false;
2855             }
2856         trace("###Cookie:%lx", magicCookie);
2857         if (magicCookie  == 0x06054b50L) //end of central directory
2858             break;
2859         else if (magicCookie == 0x05054b50L) //signature
2860             {
2861             //## Digital Signature
2862             unsigned int signatureSize;
2863             if (!getInt(&signatureSize))
2864                 {
2865                 error("bad signatureSize found");
2866                 return false;
2867                 }
2868             std::string digitalSignature;
2869             for (unsigned int i=0 ; i<signatureSize ; i++)
2870                 {
2871                 unsigned char ch;
2872                 if (!getByte(&ch))
2873                     break;
2874                 digitalSignature.push_back(ch);
2875                 }
2876             trace("######## SIGNATURE :'%s'" , digitalSignature.c_str());
2877             }
2878         else if (magicCookie != 0x02014b50L) //central directory
2879             {
2880             error("directory file header not found");
2881             return false;
2882             }
2883         }
2885     unsigned int diskNr;
2886     if (!getInt(&diskNr))
2887         {
2888         error("bad diskNr found");
2889         return false;
2890         }
2891     unsigned int diskWithCd;
2892     if (!getInt(&diskWithCd))
2893         {
2894         error("bad diskWithCd found");
2895         return false;
2896         }
2897     unsigned int nrEntriesDisk;
2898     if (!getInt(&nrEntriesDisk))
2899         {
2900         error("bad nrEntriesDisk found");
2901         return false;
2902         }
2903     unsigned int nrEntriesTotal;
2904     if (!getInt(&nrEntriesTotal))
2905         {
2906         error("bad nrEntriesTotal found");
2907         return false;
2908         }
2909     unsigned long cdSize;
2910     if (!getLong(&cdSize))
2911         {
2912         error("bad cdSize found");
2913         return false;
2914         }
2915     unsigned long cdPos;
2916     if (!getLong(&cdPos))
2917         {
2918         error("bad cdPos found");
2919         return false;
2920         }
2921     unsigned int commentSize;
2922     if (!getInt(&commentSize))
2923         {
2924         error("bad commentSize found");
2925         return false;
2926         }
2927     comment = "";
2928     for (unsigned int i=0 ; i<commentSize ; i++)
2929         {
2930         unsigned char ch;
2931         if (!getByte(&ch))
2932             break;
2933         comment.push_back(ch);
2934         }
2935     trace("######## Zip Comment :'%s'" , comment.c_str());
2937     return true;
2941 /**
2942  *
2943  */
2944 bool ZipFile::read()
2946     fileBufPos = 0;
2947     if (!readFileData())
2948         {
2949         return false;
2950         }
2951     if (!readCentralDirectory())
2952         {
2953         return false;
2954         }
2955     return true;
2958 /**
2959  *
2960  */
2961 bool ZipFile::readBuffer(const std::vector<unsigned char> &inbuf)
2963     fileBuf = inbuf;
2964     if (!read())
2965         return false;
2966     return true;
2970 /**
2971  *
2972  */
2973 bool ZipFile::readFile(const std::string &fileName)
2975     fileBuf.clear();
2976     FILE *f = fopen(fileName.c_str(), "rb");
2977     if (!f)
2978         return false;
2979     while (true)
2980         {
2981         int ch = fgetc(f);
2982         if (ch < 0)
2983             break;
2984         fileBuf.push_back(ch);
2985         }
2986     fclose(f);
2987     if (!read())
2988         return false;
2989     return true;
3000 //########################################################################
3001 //#  E N D    O F    F I L E
3002 //########################################################################