Code

Rearrange to enable code that does not directly rely on lcms.
[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;
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 const *fmt, ...)
235     #ifdef G_GNUC_PRINTF
236     G_GNUC_PRINTF(2, 3)
237     #endif
238     ;
240     /**
241      *
242      */
243     void trace(char const *fmt, ...)
244     #ifdef G_GNUC_PRINTF
245     G_GNUC_PRINTF(2, 3)
246     #endif
247     ;
249     /**
250      *
251      */
252     void dump();
254     /**
255      *
256      */
257     int buildHuffman(Huffman *h, int *length, int n);
259     /**
260      *
261      */
262     bool getBits(int need, int *oval);
264     /**
265      *
266      */
267     int doDecode(Huffman *h);
269     /**
270      *
271      */
272     bool doCodes(Huffman *lencode, Huffman *distcode);
274     /**
275      *
276      */
277     bool doStored();
279     /**
280      *
281      */
282     bool doFixed();
284     /**
285      *
286      */
287     bool doDynamic();
290     std::vector<unsigned char>dest;
292     std::vector<unsigned char>src;
293     unsigned long srcPos;  //current read position
294     int bitBuf;
295     int bitCnt;
297 };
300 /**
301  *
302  */
303 Inflater::Inflater()
307 /**
308  *
309  */
310 Inflater::~Inflater()
314 /**
315  *
316  */
317 void Inflater::error(char const *fmt, ...)
319     va_list args;
320     va_start(args, fmt);
321     fprintf(stdout, "Inflater error:");
322     vfprintf(stdout, fmt, args);
323     fprintf(stdout, "\n");
324     va_end(args);
327 /**
328  *
329  */
330 void Inflater::trace(char const *fmt, ...)
332     va_list args;
333     va_start(args, fmt);
334     fprintf(stdout, "Inflater:");
335     vfprintf(stdout, fmt, args);
336     fprintf(stdout, "\n");
337     va_end(args);
341 /**
342  *
343  */
344 void Inflater::dump()
346     for (unsigned int i=0 ; i<dest.size() ; i++)
347         {
348         fputc(dest[i], stdout);
349         }
352 /**
353  *
354  */
355 int Inflater::buildHuffman(Huffman *h, int *length, int n)
357     // count number of codes of each length
358     for (int len = 0; len <= MAXBITS; len++)
359         h->count[len] = 0;
360     for (int symbol = 0; symbol < n; symbol++)
361         (h->count[length[symbol]])++;   // assumes lengths are within bounds
362     if (h->count[0] == n)               // no codes!
363         {
364         error("huffman tree will result in failed decode");
365         return -1;
366         }
368     // check for an over-subscribed or incomplete set of lengths
369     int left = 1;                // number of possible codes left of current length
370     for (int len = 1; len <= MAXBITS; len++)
371         {
372         left <<= 1;                     // one more bit, double codes left
373         left -= h->count[len];          // deduct count from possible codes
374         if (left < 0)
375             {
376             error("huffman over subscribed");
377             return -1;
378             }
379         }
381     // generate offsets into symbol table for each length for sorting
382     int offs[MAXBITS+1]; //offsets in symbol table for each length
383     offs[1] = 0;
384     for (int len = 1; len < MAXBITS; len++)
385         offs[len + 1] = offs[len] + h->count[len];
387     /*
388      * put symbols in table sorted by length, by symbol order within each
389      * length
390      */
391     for (int symbol = 0; symbol < n; symbol++)
392         if (length[symbol] != 0)
393             h->symbol[offs[length[symbol]]++] = symbol;
395     // return zero for complete set, positive for incomplete set
396     return left;
400 /**
401  *
402  */
403 bool Inflater::getBits(int requiredBits, int *oval)
405     long val = bitBuf;
407     //add more bytes if needed
408     while (bitCnt < requiredBits)
409         {
410         if (srcPos >= src.size())
411             {
412             error("premature end of input");
413             return false;
414             }
415         val |= ((long)(src[srcPos++])) << bitCnt;
416         bitCnt += 8;
417         }
419     //update the buffer and return the data
420     bitBuf =  (int)(val >> requiredBits);
421     bitCnt -= requiredBits;
422     *oval = (int)(val & ((1L << requiredBits) - 1));
424     return true;
428 /**
429  *
430  */
431 int Inflater::doDecode(Huffman *h)
433     int bitTmp  = bitBuf;
434     int left    = bitCnt;
435     int code    = 0;
436     int first   = 0;
437     int index   = 0;
438     int len     = 1;
439     int *next = h->count + 1;
440     while (true)
441         {
442         while (left--)
443             {
444             code   |=  bitTmp & 1;
445             bitTmp >>= 1;
446             int count  =   *next++;
447             if (code < first + count)
448                 { /* if length len, return symbol */
449                 bitBuf = bitTmp;
450                 bitCnt = (bitCnt - len) & 7;
451                 return h->symbol[index + (code - first)];
452                 }
453             index +=  count;
454             first +=  count;
455             first <<= 1;
456             code  <<= 1;
457             len++;
458             }
459         left = (MAXBITS+1) - len;
460         if (left == 0)
461             break;
462         if (srcPos >= src.size())
463             {
464             error("premature end of input");
465             dump();
466             return -1;
467             }
468         bitTmp = src[srcPos++];
469         if (left > 8)
470             left = 8;
471         }
473     error("no end of block found");
474     return -1;
477 /**
478  *
479  */
480 bool Inflater::doCodes(Huffman *lencode, Huffman *distcode)
482     static const int lens[29] = { // Size base for length codes 257..285
483         3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
484         35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
485     static const int lext[29] = { // Extra bits for length codes 257..285
486         0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
487         3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
488     static const int dists[30] = { // Offset base for distance codes 0..29
489         1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
490         257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
491         8193, 12289, 16385, 24577};
492     static const int dext[30] = { // Extra bits for distance codes 0..29
493         0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
494         7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
495         12, 12, 13, 13};
497     //decode literals and length/distance pairs
498     while (true)
499         {
500         int symbol = doDecode(lencode);
501         if (symbol == 256)
502             break;
503         if (symbol < 0)
504             {
505             return false;
506             }
507         if (symbol < 256) //literal
508             {
509             dest.push_back(symbol);
510             }
511         else if (symbol > 256)//length
512             {
513             symbol -= 257;
514             if (symbol >= 29)
515                 {
516                 error("invalid fixed code");
517                 return false;
518                 }
519             int ret;
520             if (!getBits(lext[symbol], &ret))
521                 return false;
522             int len = lens[symbol] + ret;
524             symbol = doDecode(distcode);//distance
525             if (symbol < 0)
526                 {
527                 return false;
528                 }
530             if (!getBits(dext[symbol], &ret))
531                 return false;
532             unsigned int dist = dists[symbol] + ret;
533             if (dist > dest.size())
534                 {
535                 error("distance too far back %d/%d", dist, dest.size());
536                 dump();
537                 //printf("pos:%d\n", srcPos);
538                 return false;
539                 }
541             // copy length bytes from distance bytes back
542             //dest.push_back('{');
543             while (len--)
544                 {
545                 dest.push_back(dest[dest.size() - dist]);
546                 }
547             //dest.push_back('}');
549             }
550         }
552     return true;
555 /**
556  */
557 bool Inflater::doStored()
559     //trace("### stored ###");
561     // clear bits from current byte
562     bitBuf = 0;
563     bitCnt = 0;
565     // length
566     if (srcPos + 4 > src.size())
567         {
568         error("not enough input");
569         return false;
570         }
572     int len = src[srcPos++];
573     len |= src[srcPos++] << 8;
574     //trace("### len:%d", len);
575     // check complement
576     if (src[srcPos++] != (~len & 0xff) ||
577         src[srcPos++] != ((~len >> 8) & 0xff))
578         {
579         error("twos complement for storage size do not match");
580         return false;
581         }
583     // copy data
584     if (srcPos + len > src.size())
585         {
586         error("Not enough input for stored block");
587         return false;
588         }
589     while (len--)
590         dest.push_back(src[srcPos++]);
592     return true;
595 /**
596  */
597 bool Inflater::doFixed()
599     //trace("### fixed ###");
601     static bool firstTime = true;
602     static int lencnt[MAXBITS+1], lensym[FIXLCODES];
603     static int distcnt[MAXBITS+1], distsym[MAXDCODES];
604     static Huffman lencode = {lencnt, lensym};
605     static Huffman distcode = {distcnt, distsym};
607     if (firstTime)
608         {
609         firstTime = false;
611         int lengths[FIXLCODES];
613         // literal/length table
614         int symbol = 0;
615         for ( ; symbol < 144; symbol++)
616             lengths[symbol] = 8;
617         for ( ; symbol < 256; symbol++)
618             lengths[symbol] = 9;
619         for ( ; symbol < 280; symbol++)
620             lengths[symbol] = 7;
621         for ( ; symbol < FIXLCODES; symbol++)
622             lengths[symbol] = 8;
623         buildHuffman(&lencode, lengths, FIXLCODES);
625         // distance table
626         for (int symbol = 0; symbol < MAXDCODES; symbol++)
627             lengths[symbol] = 5;
628         buildHuffman(&distcode, lengths, MAXDCODES);
629         }
631     // decode data until end-of-block code
632     bool ret = doCodes(&lencode, &distcode);
633     return ret;
636 /**
637  */
638 bool Inflater::doDynamic()
640     //trace("### dynamic ###");
641     int lengths[MAXCODES];                      // descriptor code lengths
642     int lencnt[MAXBITS+1], lensym[MAXLCODES];   // lencode memory
643     int distcnt[MAXBITS+1], distsym[MAXDCODES]; // distcode memory
644     Huffman lencode  = {lencnt, lensym};          // length code
645     Huffman distcode = {distcnt, distsym};        // distance code
646     static const int order[19] =                // permutation of code length codes
647         {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
649     // get number of lengths in each table, check lengths
650     int ret;
651     if (!getBits(5, &ret))
652         return false;
653     int nlen  = ret + 257;
654     if (!getBits(5, &ret))
655         return false;
656     int ndist = ret + 1;
657     if (!getBits(4, &ret))
658         return false;
659     int ncode = ret + 4;
660     if (nlen > MAXLCODES || ndist > MAXDCODES)
661         {
662         error("Bad codes");
663         return false;
664         }
666     // get code length code lengths
667     int index = 0;
668     for ( ; index < ncode; index++)
669         {
670         if (!getBits(3, &ret))
671             return false;
672         lengths[order[index]] = ret;
673         }
674     for ( ; index < 19; index++)
675         lengths[order[index]] = 0;
677     // build huffman table for code lengths codes
678     if (buildHuffman(&lencode, lengths, 19) != 0)
679         return false;
681     // read length/literal and distance code length tables
682     index = 0;
683     while (index < nlen + ndist)
684         {
685         int symbol = doDecode(&lencode);
686         if (symbol < 16)                // length in 0..15
687             lengths[index++] = symbol;
688         else
689             {                          // repeat instruction
690             int len = 0;               // assume repeating zeros
691             if (symbol == 16)
692                 {         // repeat last length 3..6 times
693                 if (index == 0)
694                     {
695                     error("no last length");
696                     return false;
697                     }
698                 len = lengths[index - 1];// last length
699                 if (!getBits(2, &ret))
700                     return false;
701                 symbol = 3 + ret;
702                 }
703             else if (symbol == 17)      // repeat zero 3..10 times
704                 {
705                 if (!getBits(3, &ret))
706                     return false;
707                 symbol = 3 + ret;
708                 }
709             else                        // == 18, repeat zero 11..138 times
710                 {
711                 if (!getBits(7, &ret))
712                     return false;
713                 symbol = 11 + ret;
714                 }
715             if (index + symbol > nlen + ndist)
716                 {
717                 error("too many lengths");
718                 return false;
719                 }
720             while (symbol--)            // repeat last or zero symbol times
721                 lengths[index++] = len;
722             }
723         }
725     // build huffman table for literal/length codes
726     int err = buildHuffman(&lencode, lengths, nlen);
727     if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1))
728         {
729         error("incomplete length codes");
730         //return false;
731         }
732     // build huffman table for distance codes
733     err = buildHuffman(&distcode, lengths + nlen, ndist);
734     if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1))
735         {
736         error("incomplete dist codes");
737         return false;
738         }
740     // decode data until end-of-block code
741     bool retn = doCodes(&lencode, &distcode);
742     return retn;
745 /**
746  */
747 bool Inflater::inflate(std::vector<unsigned char> &destination,
748                        std::vector<unsigned char> &source)
750     dest.clear();
751     src = source;
752     srcPos = 0;
753     bitBuf = 0;
754     bitCnt = 0;
756     while (true)
757         {
758         int last; // one if last block
759         if (!getBits(1, &last))
760             return false;
761         int type; // block type 0..3
762         if (!getBits(2, &type))
763             return false;
764         switch (type)
765             {
766             case 0:
767                 if (!doStored())
768                     return false;
769                 break;
770             case 1:
771                 if (!doFixed())
772                     return false;
773                 break;
774             case 2:
775                 if (!doDynamic())
776                     return false;
777                 break;
778             default:
779                 error("Unknown block type %d", type);
780                 return false;
781             }
782         if (last)
783             break;
784         }
786     destination = dest;
788     return true;
796 //########################################################################
797 //#  D E F L A T E R
798 //########################################################################
802 class Deflater
804 public:
806     /**
807      *
808      */
809     Deflater();
811     /**
812      *
813      */
814     virtual ~Deflater();
816     /**
817      *
818      */
819     virtual void reset();
821     /**
822      *
823      */
824     virtual bool update(int ch);
826     /**
827      *
828      */
829     virtual bool finish();
831     /**
832      *
833      */
834     virtual std::vector<unsigned char> &getCompressed();
836     /**
837      *
838      */
839     bool deflate(std::vector<unsigned char> &dest,
840                  const std::vector<unsigned char> &src);
842     void encodeDistStatic(unsigned int len, unsigned int dist);
844 private:
846     //debug messages
847     void error(char const *fmt, ...)
848     #ifdef G_GNUC_PRINTF
849     G_GNUC_PRINTF(2, 3)
850     #endif
851     ;
853     void trace(char const *fmt, ...)
854     #ifdef G_GNUC_PRINTF
855     G_GNUC_PRINTF(2, 3)
856     #endif
857     ;
859     bool compressWindow();
861     bool compress();
863     std::vector<unsigned char> uncompressed;
865     std::vector<unsigned char> window;
867     unsigned int windowPos;
869     std::vector<unsigned char> compressed;
871     //#### Output
872     unsigned int outputBitBuf;
873     unsigned int outputNrBits;
875     void put(int ch);
877     void putWord(int ch);
879     void putFlush();
881     void putBits(unsigned int ch, unsigned int bitsWanted);
883     void putBitsR(unsigned int ch, unsigned int bitsWanted);
885     //#### Huffman Encode
886     void encodeLiteralStatic(unsigned int ch);
888     unsigned char windowBuf[32768];
889     //assume 32-bit ints
890     unsigned int windowHashBuf[32768];
891 };
894 //########################################################################
895 //# A P I
896 //########################################################################
899 /**
900  *
901  */
902 Deflater::Deflater()
904     reset();
907 /**
908  *
909  */
910 Deflater::~Deflater()
915 /**
916  *
917  */
918 void Deflater::reset()
920     outputBitBuf = 0;
921     outputNrBits = 0;
922     window.clear();
923     compressed.clear();
924     uncompressed.clear();
927 /**
928  *
929  */
930 bool Deflater::update(int ch)
932     uncompressed.push_back((unsigned char)(ch & 0xff));
933     return true;
936 /**
937  *
938  */
939 bool Deflater::finish()
941     return compress();
944 /**
945  *
946  */
947 std::vector<unsigned char> &Deflater::getCompressed()
949     return compressed;
953 /**
954  *
955  */
956 bool Deflater::deflate(std::vector<unsigned char> &dest,
957                        const std::vector<unsigned char> &src)
959     reset();
960     uncompressed = src;
961     if (!compress())
962         return false;
963     dest = compressed;
964     return true;
973 //########################################################################
974 //# W O R K I N G    C O D E
975 //########################################################################
978 //#############################
979 //#  M E S S A G E S
980 //#############################
982 /**
983  *  Print error messages
984  */
985 void Deflater::error(char const *fmt, ...)
987     va_list args;
988     va_start(args, fmt);
989     fprintf(stdout, "Deflater error:");
990     vfprintf(stdout, fmt, args);
991     fprintf(stdout, "\n");
992     va_end(args);
995 /**
996  *  Print trace messages
997  */
998 void Deflater::trace(char const *fmt, ...)
1000     va_list args;
1001     va_start(args, fmt);
1002     fprintf(stdout, "Deflater:");
1003     vfprintf(stdout, fmt, args);
1004     fprintf(stdout, "\n");
1005     va_end(args);
1011 //#############################
1012 //#  O U T P U T
1013 //#############################
1015 /**
1016  *
1017  */
1018 void Deflater::put(int ch)
1020     compressed.push_back(ch);
1021     outputBitBuf = 0;
1022     outputNrBits = 0;
1025 /**
1026  *
1027  */
1028 void Deflater::putWord(int ch)
1030     int lo = (ch   ) & 0xff;
1031     int hi = (ch>>8) & 0xff;
1032     put(lo);
1033     put(hi);
1036 /**
1037  *
1038  */
1039 void Deflater::putFlush()
1041     if (outputNrBits > 0)
1042         {
1043         put(outputBitBuf & 0xff);
1044         }
1045     outputBitBuf = 0;
1046     outputNrBits = 0;
1049 /**
1050  *
1051  */
1052 void Deflater::putBits(unsigned int ch, unsigned int bitsWanted)
1054     //trace("n:%4u, %d\n", ch, bitsWanted);
1056     while (bitsWanted--)
1057         {
1058         //add bits to position 7.  shift right
1059         outputBitBuf = (outputBitBuf>>1) + (ch<<7 & 0x80);
1060         ch >>= 1;
1061         outputNrBits++;
1062         if (outputNrBits >= 8)
1063             {
1064             unsigned char b = outputBitBuf & 0xff;
1065             //printf("b:%02x\n", b);
1066             put(b);
1067             }
1068         }
1071 static unsigned int bitReverse(unsigned int code, unsigned int nrBits)
1073     unsigned int outb = 0;
1074     while (nrBits--)
1075         {
1076         outb = (outb << 1) | (code & 0x01);
1077         code >>= 1;
1078         }
1079     return outb;
1083 /**
1084  *
1085  */
1086 void Deflater::putBitsR(unsigned int ch, unsigned int bitsWanted)
1088     //trace("r:%4u, %d", ch, bitsWanted);
1090     unsigned int rcode = bitReverse(ch, bitsWanted);
1092     putBits(rcode, bitsWanted);
1097 //#############################
1098 //#  E N C O D E
1099 //#############################
1103 void Deflater::encodeLiteralStatic(unsigned int ch)
1105     //trace("c: %d", ch);
1107     if (ch < 144)
1108         {
1109         putBitsR(ch + 0x0030 , 8); // 00110000
1110         }
1111     else if (ch < 256)
1112         {
1113         putBitsR(ch - 144 + 0x0190 , 9); // 110010000
1114         }
1115     else if (ch < 280)
1116         {
1117         putBitsR(ch - 256 + 0x0000 , 7); // 0000000
1118         }
1119     else if (ch < 288)
1120         {
1121         putBitsR(ch - 280 + 0x00c0 , 8); // 11000000
1122         }
1123     else //out of range
1124         {
1125         error("Literal out of range: %d", ch);
1126         }
1131 typedef struct
1133     unsigned int base;
1134     unsigned int range;
1135     unsigned int bits;
1136 } LenBase;
1138 LenBase lenBases[] =
1140     {   3,  1, 0 },
1141     {   4,  1, 0 },
1142     {   5,  1, 0 },
1143     {   6,  1, 0 },
1144     {   7,  1, 0 },
1145     {   8,  1, 0 },
1146     {   9,  1, 0 },
1147     {  10,  1, 0 },
1148     {  11,  2, 1 },
1149     {  13,  2, 1 },
1150     {  15,  2, 1 },
1151     {  17,  2, 1 },
1152     {  19,  4, 2 },
1153     {  23,  4, 2 },
1154     {  27,  4, 2 },
1155     {  31,  4, 2 },
1156     {  35,  8, 3 },
1157     {  43,  8, 3 },
1158     {  51,  8, 3 },
1159     {  59,  8, 3 },
1160     {  67, 16, 4 },
1161     {  83, 16, 4 },
1162     {  99, 16, 4 },
1163     { 115, 16, 4 },
1164     { 131, 32, 5 },
1165     { 163, 32, 5 },
1166     { 195, 32, 5 },
1167     { 227, 32, 5 },
1168     { 258,  1, 0 }
1169 };
1171 typedef struct
1173     unsigned int base;
1174     unsigned int range;
1175     unsigned int bits;
1176 } DistBase;
1178 DistBase distBases[] =
1180     {     1,    1,  0 },
1181     {     2,    1,  0 },
1182     {     3,    1,  0 },
1183     {     4,    1,  0 },
1184     {     5,    2,  1 },
1185     {     7,    2,  1 },
1186     {     9,    4,  2 },
1187     {    13,    4,  2 },
1188     {    17,    8,  3 },
1189     {    25,    8,  3 },
1190     {    33,   16,  4 },
1191     {    49,   16,  4 },
1192     {    65,   32,  5 },
1193     {    97,   32,  5 },
1194     {   129,   64,  6 },
1195     {   193,   64,  6 },
1196     {   257,  128,  7 },
1197     {   385,  128,  7 },
1198     {   513,  256,  8 },
1199     {   769,  256,  8 },
1200     {  1025,  512,  9 },
1201     {  1537,  512,  9 },
1202     {  2049, 1024, 10 },
1203     {  3073, 1024, 10 },
1204     {  4097, 2048, 11 },
1205     {  6145, 2048, 11 },
1206     {  8193, 4096, 12 },
1207     { 12289, 4096, 12 },
1208     { 16385, 8192, 13 },
1209     { 24577, 8192, 13 }
1210 };
1212 void Deflater::encodeDistStatic(unsigned int len, unsigned int dist)
1215     //## Output length
1217     if (len < 3 || len > 258)
1218         {
1219         error("Length out of range:%d", len);
1220         return;
1221         }
1223     bool found = false;
1224     for (int i=0 ; i<30 ; i++)
1225         {
1226         unsigned int base  = lenBases[i].base;
1227         unsigned int range = lenBases[i].range;
1228         if (base + range > len)
1229             {
1230             unsigned int lenCode = 257 + i;
1231             unsigned int length  = len - base;
1232             //trace("--- %d %d %d %d", len, base, range, length);
1233             encodeLiteralStatic(lenCode);
1234             putBits(length, lenBases[i].bits);
1235             found = true;
1236             break;
1237             }
1238         }
1239     if (!found)
1240         {
1241         error("Length not found in table:%d", len);
1242         return;
1243         }
1245     //## Output distance
1247     if (dist < 4 || dist > 32768)
1248         {
1249         error("Distance out of range:%d", dist);
1250         return;
1251         }
1253     found = false;
1254     for (int i=0 ; i<30 ; i++)
1255         {
1256         unsigned int base  = distBases[i].base;
1257         unsigned int range = distBases[i].range;
1258         if (base + range > dist)
1259             {
1260             unsigned int distCode = i;
1261             unsigned int distance = dist - base;
1262             //error("--- %d %d %d %d", dist, base, range, distance);
1263             putBitsR(distCode, 5);
1264             putBits(distance, distBases[i].bits);
1265             found = true;
1266             break;
1267             }
1268         }
1269     if (!found)
1270         {
1271         error("Distance not found in table:%d", dist);
1272         return;
1273         }
1277 //#############################
1278 //#  C O M P R E S S
1279 //#############################
1282 /**
1283  * This method does the dirty work of dictionary
1284  * compression.  Basically it looks for redundant
1285  * strings and has the current duplicate refer back
1286  * to the previous one.
1287  */
1288 bool Deflater::compressWindow()
1290     windowPos = 0;
1291     unsigned int windowSize = window.size();
1292     //### Compress as much of the window as possible
1294     unsigned int hash = 0;
1295     //Have each value be a long with the byte at this position,
1296     //plus the 3 bytes after it in the window
1297     for (int i=windowSize-1 ; i>=0 ; i--)
1298         {
1299         unsigned char ch = window[i];
1300         windowBuf[i] = ch;
1301         hash = ((hash<<8) & 0xffffff00) | ch;
1302         windowHashBuf[i] = hash;
1303         }
1305     while (windowPos < windowSize - 3)
1306         {
1307         //### Find best match, if any
1308         unsigned int bestMatchLen  = 0;
1309         unsigned int bestMatchDist = 0;
1310         if (windowPos >= 4)
1311             {
1312             for (unsigned int lookBack=0 ; lookBack<windowPos-4 ; lookBack++)
1313                 {
1314                 //Check 4-char hashes first, before continuing with string
1315                 if (windowHashBuf[lookBack] == windowHashBuf[windowPos])
1316                     {
1317                     unsigned int lookAhead=4;
1318                     unsigned int lookAheadMax = windowSize - 4 - windowPos;
1319                     if (lookBack + lookAheadMax >= windowPos -4 )
1320                         lookAheadMax = windowPos - 4 - lookBack;
1321                     if (lookAheadMax > 258)
1322                         lookAheadMax = 258;
1323                     unsigned char *wp = &(windowBuf[windowPos+4]);
1324                     unsigned char *lb = &(windowBuf[lookBack+4]);
1325                     while (lookAhead<lookAheadMax)
1326                         {
1327                         if (*lb++ != *wp++)
1328                             break;
1329                         lookAhead++;
1330                         }
1331                     if (lookAhead > bestMatchLen)
1332                         {
1333                         bestMatchLen  = lookAhead;
1334                         bestMatchDist = windowPos - lookBack;
1335                         }
1336                     }
1337                 }
1338             }
1339         if (bestMatchLen > 3)
1340             {
1341             //Distance encode
1342             //trace("### distance");
1343             /*
1344             printf("### 1 '");
1345             for (int i=0 ; i < bestMatchLen ; i++)
1346                 fputc(window[windowPos+i], stdout);
1347             printf("'\n### 2 '");
1348             for (int i=0 ; i < bestMatchLen ; i++)
1349                 fputc(window[windowPos-bestMatchDist+i], stdout);
1350             printf("'\n");
1351             */
1352             encodeDistStatic(bestMatchLen, bestMatchDist);
1353             windowPos += bestMatchLen;
1354             }
1355         else
1356             {
1357             //Literal encode
1358             //trace("### literal");
1359             encodeLiteralStatic(windowBuf[windowPos]);
1360             windowPos++;
1361             }
1362         }
1364     while (windowPos < windowSize)
1365         encodeLiteralStatic(windowBuf[windowPos++]);
1367     encodeLiteralStatic(256);
1368     return true;
1372 /**
1373  *
1374  */
1375 bool Deflater::compress()
1377     //trace("compress");
1378     unsigned long total = 0L;
1379     windowPos = 0;
1380     std::vector<unsigned char>::iterator iter;
1381     for (iter = uncompressed.begin(); iter != uncompressed.end() ; )
1382         {
1383         total += windowPos;
1384         trace("total:%ld", total);
1385         if (windowPos > window.size())
1386             windowPos = window.size();
1387         window.erase(window.begin() , window.begin()+windowPos);
1388         while (window.size() < 32768 && iter != uncompressed.end())
1389             {
1390             window.push_back(*iter);
1391             iter++;
1392             }
1393         if (window.size() >= 32768)
1394             putBits(0x00, 1); //0  -- more blocks
1395         else
1396             putBits(0x01, 1); //1  -- last block
1397         putBits(0x01, 2); //01 -- static trees
1398         if (!compressWindow())
1399             return false;
1400         }
1401     putFlush();
1402     return true;
1409 //########################################################################
1410 //#  G Z I P    F I L E
1411 //########################################################################
1413 /**
1414  * Constructor
1415  */
1416 GzipFile::GzipFile()
1420 /**
1421  * Destructor
1422  */
1423 GzipFile::~GzipFile()
1427 /**
1428  *  Print error messages
1429  */
1430 void GzipFile::error(char const *fmt, ...)
1432     va_list args;
1433     va_start(args, fmt);
1434     fprintf(stdout, "GzipFile error:");
1435     vfprintf(stdout, fmt, args);
1436     fprintf(stdout, "\n");
1437     va_end(args);
1440 /**
1441  *  Print trace messages
1442  */
1443 void GzipFile::trace(char const *fmt, ...)
1445     va_list args;
1446     va_start(args, fmt);
1447     fprintf(stdout, "GzipFile:");
1448     vfprintf(stdout, fmt, args);
1449     fprintf(stdout, "\n");
1450     va_end(args);
1453 /**
1454  *
1455  */
1456 void GzipFile::put(unsigned char ch)
1458     data.push_back(ch);
1461 /**
1462  *
1463  */
1464 void GzipFile::setData(const std::vector<unsigned char> &str)
1466     data = str;
1469 /**
1470  *
1471  */
1472 void GzipFile::clearData()
1474     data.clear();
1477 /**
1478  *
1479  */
1480 std::vector<unsigned char> &GzipFile::getData()
1482     return data;
1485 /**
1486  *
1487  */
1488 std::string &GzipFile::getFileName()
1490     return fileName;
1493 /**
1494  *
1495  */
1496 void GzipFile::setFileName(const std::string &val)
1498     fileName = val;
1503 //#####################################
1504 //# U T I L I T Y
1505 //#####################################
1507 /**
1508  *  Loads a new file into an existing GzipFile
1509  */
1510 bool GzipFile::loadFile(const std::string &fName)
1512     FILE *f = fopen(fName.c_str() , "rb");
1513     if (!f)
1514         {
1515         error("Cannot open file %s", fName.c_str());
1516         return false;
1517         }
1518     while (true)
1519         {
1520         int ch = fgetc(f);
1521         if (ch < 0)
1522             break;
1523         data.push_back(ch);
1524         }
1525     fclose(f);
1526     setFileName(fName);
1527     return true;
1532 //#####################################
1533 //# W R I T E
1534 //#####################################
1536 /**
1537  *
1538  */
1539 bool GzipFile::putByte(unsigned char ch)
1541     fileBuf.push_back(ch);
1542     return true;
1547 /**
1548  *
1549  */
1550 bool GzipFile::putLong(unsigned long val)
1552     fileBuf.push_back( (unsigned char)((val    ) & 0xff));
1553     fileBuf.push_back( (unsigned char)((val>> 8) & 0xff));
1554     fileBuf.push_back( (unsigned char)((val>>16) & 0xff));
1555     fileBuf.push_back( (unsigned char)((val>>24) & 0xff));
1556     return true;
1561 /**
1562  *
1563  */
1564 bool GzipFile::write()
1566     fileBuf.clear();
1568     putByte(0x1f); //magic
1569     putByte(0x8b); //magic
1570     putByte(   8); //compression method
1571     putByte(0x08); //flags.  say we have a crc and file name
1573     unsigned long ltime = (unsigned long) time(NULL);
1574     putLong(ltime);
1576     //xfl
1577     putByte(0);
1578     //OS
1579     putByte(0);
1581     //file name
1582     for (unsigned int i=0 ; i<fileName.size() ; i++)
1583         putByte(fileName[i]);
1584     putByte(0);
1587     //compress
1588     std::vector<unsigned char> compBuf;
1589     Deflater deflater;
1590     if (!deflater.deflate(compBuf, data))
1591         {
1592         return false;
1593         }
1595     std::vector<unsigned char>::iterator iter;
1596     for (iter=compBuf.begin() ; iter!=compBuf.end() ; iter++)
1597         {
1598         unsigned char ch = *iter;
1599         putByte(ch);
1600         }
1602     Crc32 crcEngine;
1603     crcEngine.update(data);
1604     unsigned long crc = crcEngine.getValue();
1605     putLong(crc);
1607     putLong(data.size());
1609     return true;
1613 /**
1614  *
1615  */
1616 bool GzipFile::writeBuffer(std::vector<unsigned char> &outBuf)
1618     if (!write())
1619         return false;
1620     outBuf.clear();
1621     outBuf = fileBuf;
1622     return true;
1626 /**
1627  *
1628  */
1629 bool GzipFile::writeFile(const std::string &fileName)
1631     if (!write())
1632         return false;
1633     FILE *f = fopen(fileName.c_str(), "wb");
1634     if (!f)
1635         return false;
1636     std::vector<unsigned char>::iterator iter;
1637     for (iter=fileBuf.begin() ; iter!=fileBuf.end() ; iter++)
1638         {
1639         unsigned char ch = *iter;
1640         fputc(ch, f);
1641         }
1642     fclose(f);
1643     return true;
1647 //#####################################
1648 //# R E A D
1649 //#####################################
1651 bool GzipFile::getByte(unsigned char *ch)
1653     if (fileBufPos >= fileBuf.size())
1654         {
1655         error("unexpected end of data");
1656         return false;
1657         }
1658     *ch = fileBuf[fileBufPos++];
1659     return true;
1662 /**
1663  *
1664  */
1665 bool GzipFile::getLong(unsigned long *val)
1667     if (fileBuf.size() - fileBufPos < 4)
1668         return false;
1669     int ch1 = fileBuf[fileBufPos++];
1670     int ch2 = fileBuf[fileBufPos++];
1671     int ch3 = fileBuf[fileBufPos++];
1672     int ch4 = fileBuf[fileBufPos++];
1673     *val = ((ch4<<24) & 0xff000000L) |
1674            ((ch3<<16) & 0x00ff0000L) |
1675            ((ch2<< 8) & 0x0000ff00L) |
1676            ((ch1    ) & 0x000000ffL);
1677     return true;
1680 bool GzipFile::read()
1682     fileBufPos = 0;
1684     unsigned char ch;
1686     //magic cookie
1687     if (!getByte(&ch))
1688         return false;
1689     if (ch != 0x1f)
1690         {
1691         error("bad gzip header");
1692         return false;
1693         }
1694     if (!getByte(&ch))
1695         return false;
1696     if (ch != 0x8b)
1697         {
1698         error("bad gzip header");
1699         return false;
1700         }
1702     //## compression method
1703     if (!getByte(&ch))
1704         return false;
1705     compressionMethod = ch & 0xff;
1707     //## flags
1708     if (!getByte(&ch))
1709         return false;
1710     //bool ftext    = ch & 0x01;
1711     bool fhcrc    = ch & 0x02;
1712     bool fextra   = ch & 0x04;
1713     bool fname    = ch & 0x08;
1714     bool fcomment = ch & 0x10;
1716     //trace("cm:%d ftext:%d fhcrc:%d fextra:%d fname:%d fcomment:%d",
1717     //         cm, ftext, fhcrc, fextra, fname, fcomment);
1719     //## file time
1720     unsigned long ltime;
1721     if (!getLong(&ltime))
1722         return false;
1723     //time_t mtime = (time_t)ltime;
1725     //## XFL
1726     if (!getByte(&ch))
1727         return false;
1728     //int xfl = ch;
1730     //## OS
1731     if (!getByte(&ch))
1732         return false;
1733     //int os = ch;
1735     //std::string timestr = ctime(&mtime);
1736     //trace("xfl:%d os:%d mtime:%s", xfl, os, timestr.c_str());
1738     if (fextra)
1739         {
1740         if (!getByte(&ch))
1741             return false;
1742         long xlen = ch;
1743         if (!getByte(&ch))
1744             return false;
1745         xlen = (xlen << 8) + ch;
1746         for (long l=0 ; l<xlen ; l++)
1747             {
1748             if (!getByte(&ch))
1749                 return false;
1750             }
1751         }
1753     if (fname)
1754         {
1755         fileName = "";
1756         while (true)
1757             {
1758             if (!getByte(&ch))
1759                 return false;
1760             if (ch==0)
1761                 break;
1762             fileName.push_back(ch);
1763             }
1764         }
1766     if (fcomment)
1767         {
1768         while (true)
1769             {
1770             if (!getByte(&ch))
1771                 return false;
1772             if (ch==0)
1773                 break;
1774             }
1775         }
1777     if (fhcrc)
1778         {
1779         if (!getByte(&ch))
1780             return false;
1781         if (!getByte(&ch))
1782             return false;
1783         }
1785     //read remainder of stream
1786     //compressed data runs up until 8 bytes before end of buffer
1787     std::vector<unsigned char> compBuf;
1788     while (fileBufPos < fileBuf.size() - 8)
1789         {
1790         if (!getByte(&ch))
1791             return false;
1792         compBuf.push_back(ch);
1793         }
1794     //uncompress
1795     data.clear();
1796     Inflater inflater;
1797     if (!inflater.inflate(data, compBuf))
1798         {
1799         return false;
1800         }
1802     //Get the CRC and compare
1803     Crc32 crcEngine;
1804     crcEngine.update(data);
1805     unsigned long calcCrc = crcEngine.getValue();
1806     unsigned long givenCrc;
1807     if (!getLong(&givenCrc))
1808         return false;
1809     if (givenCrc != calcCrc)
1810         {
1811         error("Specified crc, %ud, not what received: %ud",
1812                 givenCrc, calcCrc);
1813         return false;
1814         }
1816     //Get the file size and compare
1817     unsigned long givenFileSize;
1818     if (!getLong(&givenFileSize))
1819         return false;
1820     if (givenFileSize != data.size())
1821         {
1822         error("Specified data size, %ld, not what received: %ld",
1823                 givenFileSize, data.size());
1824         return false;
1825         }
1827     return true;
1832 /**
1833  *
1834  */
1835 bool GzipFile::readBuffer(const std::vector<unsigned char> &inbuf)
1837     fileBuf = inbuf;
1838     if (!read())
1839         return false;
1840     return true;
1844 /**
1845  *
1846  */
1847 bool GzipFile::readFile(const std::string &fileName)
1849     fileBuf.clear();
1850     FILE *f = fopen(fileName.c_str(), "rb");
1851     if (!f)
1852         return false;
1853     while (true)
1854         {
1855         int ch = fgetc(f);
1856         if (ch < 0)
1857             break;
1858         fileBuf.push_back(ch);
1859         }
1860     fclose(f);
1861     if (!read())
1862         return false;
1863     return true;
1873 //########################################################################
1874 //#  Z I P    F I L E
1875 //########################################################################
1877 /**
1878  * Constructor
1879  */
1880 ZipEntry::ZipEntry()
1882     crc               = 0L;
1883     compressionMethod = 8;
1886 /**
1887  *
1888  */
1889 ZipEntry::ZipEntry(const std::string &fileNameArg,
1890                    const std::string &commentArg)
1892     crc               = 0L;
1893     compressionMethod = 8;
1894     fileName          = fileNameArg;
1895     comment           = commentArg;
1898 /**
1899  * Destructor
1900  */
1901 ZipEntry::~ZipEntry()
1906 /**
1907  *
1908  */
1909 std::string ZipEntry::getFileName()
1911     return fileName;
1914 /**
1915  *
1916  */
1917 void ZipEntry::setFileName(const std::string &val)
1919     fileName = val;
1922 /**
1923  *
1924  */
1925 std::string ZipEntry::getComment()
1927     return comment;
1930 /**
1931  *
1932  */
1933 void ZipEntry::setComment(const std::string &val)
1935     comment = val;
1938 /**
1939  *
1940  */
1941 unsigned long ZipEntry::getCompressedSize()
1943     return (unsigned long)compressedData.size();
1946 /**
1947  *
1948  */
1949 int ZipEntry::getCompressionMethod()
1951     return compressionMethod;
1954 /**
1955  *
1956  */
1957 void ZipEntry::setCompressionMethod(int val)
1959     compressionMethod = val;
1962 /**
1963  *
1964  */
1965 std::vector<unsigned char> &ZipEntry::getCompressedData()
1967     return compressedData;
1970 /**
1971  *
1972  */
1973 void ZipEntry::setCompressedData(const std::vector<unsigned char> &val)
1975     compressedData = val;
1978 /**
1979  *
1980  */
1981 unsigned long ZipEntry::getUncompressedSize()
1983     return (unsigned long)uncompressedData.size();
1986 /**
1987  *
1988  */
1989 std::vector<unsigned char> &ZipEntry::getUncompressedData()
1991     return uncompressedData;
1994 /**
1995  *
1996  */
1997 void ZipEntry::setUncompressedData(const std::vector<unsigned char> &val)
1999     uncompressedData = val;
2002 /**
2003  *
2004  */
2005 unsigned long ZipEntry::getCrc()
2007     return crc;
2010 /**
2011  *
2012  */
2013 void ZipEntry::setCrc(unsigned long val)
2015     crc = val;
2018 /**
2019  *
2020  */
2021 void ZipEntry::write(unsigned char ch)
2023     uncompressedData.push_back(ch);
2026 /**
2027  *
2028  */
2029 void ZipEntry::finish()
2031     Crc32 c32;
2032     std::vector<unsigned char>::iterator iter;
2033     for (iter = uncompressedData.begin() ;
2034            iter!= uncompressedData.end() ; iter++)
2035         {
2036         unsigned char ch = *iter;
2037         c32.update(ch);
2038         }
2039     crc = c32.getValue();
2040     switch (compressionMethod)
2041         {
2042         case 0: //none
2043             {
2044             for (iter = uncompressedData.begin() ;
2045                iter!= uncompressedData.end() ; iter++)
2046                 {
2047                 unsigned char ch = *iter;
2048                 compressedData.push_back(ch);
2049                 }
2050             break;
2051             }
2052         case 8: //deflate
2053             {
2054             Deflater deflater;
2055             if (!deflater.deflate(compressedData, uncompressedData))
2056                 {
2057                 //some error
2058                 }
2059             break;
2060             }
2061         default:
2062             {
2063             printf("error: unknown compression method %d\n",
2064                     compressionMethod);
2065             }
2066         }
2072 /**
2073  *
2074  */
2075 bool ZipEntry::readFile(const std::string &fileNameArg,
2076                         const std::string &commentArg)
2078     crc = 0L;
2079     uncompressedData.clear();
2080     fileName = fileNameArg;
2081     comment  = commentArg;
2082     FILE *f = fopen(fileName.c_str(), "rb");
2083     if (!f)
2084         {
2085         return false;
2086         }
2087     while (true)
2088         {
2089         int ch = fgetc(f);
2090         if (ch < 0)
2091             break;
2092         uncompressedData.push_back((unsigned char)ch);
2093         }
2094     fclose(f);
2095     finish();
2096     return true;
2100 /**
2101  *
2102  */
2103 void ZipEntry::setPosition(unsigned long val)
2105     position = val;
2108 /**
2109  *
2110  */
2111 unsigned long ZipEntry::getPosition()
2113     return position;
2122 /**
2123  * Constructor
2124  */
2125 ZipFile::ZipFile()
2130 /**
2131  * Destructor
2132  */
2133 ZipFile::~ZipFile()
2135     std::vector<ZipEntry *>::iterator iter;
2136     for (iter=entries.begin() ; iter!=entries.end() ; iter++)
2137         {
2138         ZipEntry *entry = *iter;
2139         delete entry;
2140         }
2141     entries.clear();
2144 /**
2145  *
2146  */
2147 void ZipFile::setComment(const std::string &val)
2149     comment = val;
2152 /**
2153  *
2154  */
2155 std::string ZipFile::getComment()
2157     return comment;
2161 /**
2162  *
2163  */
2164 std::vector<ZipEntry *> &ZipFile::getEntries()
2166     return entries;
2171 //#####################################
2172 //# M E S S A G E S
2173 //#####################################
2175 void ZipFile::error(char const *fmt, ...)
2177     va_list args;
2178     va_start(args, fmt);
2179     fprintf(stdout, "ZipFile error:");
2180     vfprintf(stdout, fmt, args);
2181     fprintf(stdout, "\n");
2182     va_end(args);
2185 void ZipFile::trace(char const *fmt, ...)
2187     va_list args;
2188     va_start(args, fmt);
2189     fprintf(stdout, "ZipFile:");
2190     vfprintf(stdout, fmt, args);
2191     fprintf(stdout, "\n");
2192     va_end(args);
2195 //#####################################
2196 //# U T I L I T Y
2197 //#####################################
2199 /**
2200  *
2201  */
2202 ZipEntry *ZipFile::addFile(const std::string &fileName,
2203                       const std::string &comment)
2205     ZipEntry *ze = new ZipEntry();
2206     if (!ze->readFile(fileName, comment))
2207         {
2208         return NULL;
2209         }
2210     entries.push_back(ze);
2211     return ze;
2215 /**
2216  *
2217  */
2218 ZipEntry *ZipFile::newEntry(const std::string &fileName,
2219                             const std::string &comment)
2221     ZipEntry *ze = new ZipEntry(fileName, comment);
2222     entries.push_back(ze);
2223     return ze;
2227 //#####################################
2228 //# W R I T E
2229 //#####################################
2231 /**
2232  *
2233  */
2234 bool ZipFile::putLong(unsigned long val)
2236     fileBuf.push_back( ((int)(val    )) & 0xff);
2237     fileBuf.push_back( ((int)(val>> 8)) & 0xff);
2238     fileBuf.push_back( ((int)(val>>16)) & 0xff);
2239     fileBuf.push_back( ((int)(val>>24)) & 0xff);
2240     return true;
2244 /**
2245  *
2246  */
2247 bool ZipFile::putInt(unsigned int val)
2249     fileBuf.push_back( (val    ) & 0xff);
2250     fileBuf.push_back( (val>> 8) & 0xff);
2251     return true;
2254 /**
2255  *
2256  */
2257 bool ZipFile::putByte(unsigned char val)
2259     fileBuf.push_back(val);
2260     return true;
2263 /**
2264  *
2265  */
2266 bool ZipFile::writeFileData()
2268     std::vector<ZipEntry *>::iterator iter;
2269     for (iter = entries.begin() ; iter != entries.end() ; iter++)
2270         {
2271         ZipEntry *entry = *iter;
2272         entry->setPosition(fileBuf.size());
2273         //##### HEADER
2274         std::string fname = entry->getFileName();
2275         putLong(0x04034b50L);
2276         putInt(20); //versionNeeded
2277         putInt(0); //gpBitFlag
2278         //putInt(0); //compression method
2279         putInt(entry->getCompressionMethod()); //compression method
2280         putInt(0); //mod time
2281         putInt(0); //mod date
2282         putLong(entry->getCrc()); //crc32
2283         putLong(entry->getCompressedSize());
2284         putLong(entry->getUncompressedSize());
2285         putInt(fname.size());//fileName length
2286         putInt(8);//extra field length
2287         //file name
2288         for (unsigned int i=0 ; i<fname.size() ; i++)
2289             putByte((unsigned char)fname[i]);
2290         //extra field
2291         putInt(0x7855);
2292         putInt(4);
2293         putInt(100);
2294         putInt(100);
2296         //##### DATA
2297         std::vector<unsigned char> &buf = entry->getCompressedData();
2298         std::vector<unsigned char>::iterator iter;
2299         for (iter = buf.begin() ; iter != buf.end() ; iter++)
2300             {
2301             unsigned char ch = (unsigned char) *iter;
2302             putByte(ch);
2303             }
2304         }
2305     return true;
2308 /**
2309  *
2310  */
2311 bool ZipFile::writeCentralDirectory()
2313     unsigned long cdPosition = fileBuf.size();
2314     std::vector<ZipEntry *>::iterator iter;
2315     for (iter = entries.begin() ; iter != entries.end() ; iter++)
2316         {
2317         ZipEntry *entry = *iter;
2318         std::string fname   = entry->getFileName();
2319         std::string ecomment = entry->getComment();
2320         putLong(0x02014b50L);  //magic cookie
2321         putInt(2386); //versionMadeBy
2322         putInt(20); //versionNeeded
2323         putInt(0); //gpBitFlag
2324         putInt(entry->getCompressionMethod()); //compression method
2325         putInt(0); //mod time
2326         putInt(0); //mod date
2327         putLong(entry->getCrc()); //crc32
2328         putLong(entry->getCompressedSize());
2329         putLong(entry->getUncompressedSize());
2330         putInt(fname.size());//fileName length
2331         putInt(4);//extra field length
2332         putInt(ecomment.size());//comment length
2333         putInt(0); //disk number start
2334         putInt(0); //internal attributes
2335         putLong(0); //external attributes
2336         putLong(entry->getPosition());
2338         //file name
2339         for (unsigned int i=0 ; i<fname.size() ; i++)
2340             putByte((unsigned char)fname[i]);
2341         //extra field
2342         putInt(0x7855);
2343         putInt(0);
2344         //comment
2345         for (unsigned int i=0 ; i<ecomment.size() ; i++)
2346             putByte((unsigned char)ecomment[i]);
2347         }
2348     unsigned long cdSize = fileBuf.size() - cdPosition;
2350     putLong(0x06054b50L);
2351     putInt(0);//number of this disk
2352     putInt(0);//nr of disk with central dir
2353     putInt(entries.size()); //number of entries on this disk
2354     putInt(entries.size()); //number of entries total
2355     putLong(cdSize);  //size of central dir
2356     putLong(cdPosition); //position of central dir
2357     putInt(comment.size());//comment size
2358     for (unsigned int i=0 ; i<comment.size() ; i++)
2359         putByte(comment[i]);
2360     return true;
2365 /**
2366  *
2367  */
2368 bool ZipFile::write()
2370     fileBuf.clear();
2371     if (!writeFileData())
2372         return false;
2373     if (!writeCentralDirectory())
2374         return false;
2375     return true;
2379 /**
2380  *
2381  */
2382 bool ZipFile::writeBuffer(std::vector<unsigned char> &outBuf)
2384     if (!write())
2385         return false;
2386     outBuf.clear();
2387     outBuf = fileBuf;
2388     return true;
2392 /**
2393  *
2394  */
2395 bool ZipFile::writeFile(const std::string &fileName)
2397     if (!write())
2398         return false;
2399     FILE *f = fopen(fileName.c_str(), "wb");
2400     if (!f)
2401         return false;
2402     std::vector<unsigned char>::iterator iter;
2403     for (iter=fileBuf.begin() ; iter!=fileBuf.end() ; iter++)
2404         {
2405         unsigned char ch = *iter;
2406         fputc(ch, f);
2407         }
2408     fclose(f);
2409     return true;
2412 //#####################################
2413 //# R E A D
2414 //#####################################
2416 /**
2417  *
2418  */
2419 bool ZipFile::getLong(unsigned long *val)
2421     if (fileBuf.size() - fileBufPos < 4)
2422         return false;
2423     int ch1 = fileBuf[fileBufPos++];
2424     int ch2 = fileBuf[fileBufPos++];
2425     int ch3 = fileBuf[fileBufPos++];
2426     int ch4 = fileBuf[fileBufPos++];
2427     *val = ((ch4<<24) & 0xff000000L) |
2428            ((ch3<<16) & 0x00ff0000L) |
2429            ((ch2<< 8) & 0x0000ff00L) |
2430            ((ch1    ) & 0x000000ffL);
2431     return true;
2434 /**
2435  *
2436  */
2437 bool ZipFile::getInt(unsigned int *val)
2439     if (fileBuf.size() - fileBufPos < 2)
2440         return false;
2441     int ch1 = fileBuf[fileBufPos++];
2442     int ch2 = fileBuf[fileBufPos++];
2443     *val = ((ch2<< 8) & 0xff00) |
2444            ((ch1    ) & 0x00ff);
2445     return true;
2449 /**
2450  *
2451  */
2452 bool ZipFile::getByte(unsigned char *val)
2454     if (fileBuf.size() <= fileBufPos)
2455         return false;
2456     *val = fileBuf[fileBufPos++];
2457     return true;
2461 /**
2462  *
2463  */
2464 bool ZipFile::readFileData()
2466     //printf("#################################################\n");
2467     //printf("###D A T A\n");
2468     //printf("#################################################\n");
2469     while (true)
2470         {
2471         unsigned long magicCookie;
2472         if (!getLong(&magicCookie))
2473             {
2474             error("magic cookie not found");
2475             break;
2476             }
2477         trace("###Cookie:%lx", magicCookie);
2478         if (magicCookie == 0x02014b50L) //central directory
2479             break;
2480         if (magicCookie != 0x04034b50L)
2481             {
2482             error("file header not found");
2483             return false;
2484             }
2485         unsigned int versionNeeded;
2486         if (!getInt(&versionNeeded))
2487             {
2488             error("bad version needed found");
2489             return false;
2490             }
2491         unsigned int gpBitFlag;
2492         if (!getInt(&gpBitFlag))
2493             {
2494             error("bad bit flag found");
2495             return false;
2496             }
2497         unsigned int compressionMethod;
2498         if (!getInt(&compressionMethod))
2499             {
2500             error("bad compressionMethod found");
2501             return false;
2502             }
2503         unsigned int modTime;
2504         if (!getInt(&modTime))
2505             {
2506             error("bad modTime found");
2507             return false;
2508             }
2509         unsigned int modDate;
2510         if (!getInt(&modDate))
2511             {
2512             error("bad modDate found");
2513             return false;
2514             }
2515         unsigned long crc32;
2516         if (!getLong(&crc32))
2517             {
2518             error("bad crc32 found");
2519             return false;
2520             }
2521         unsigned long compressedSize;
2522         if (!getLong(&compressedSize))
2523             {
2524             error("bad compressedSize found");
2525             return false;
2526             }
2527         unsigned long uncompressedSize;
2528         if (!getLong(&uncompressedSize))
2529             {
2530             error("bad uncompressedSize found");
2531             return false;
2532             }
2533         unsigned int fileNameLength;
2534         if (!getInt(&fileNameLength))
2535             {
2536             error("bad fileNameLength found");
2537             return false;
2538             }
2539         unsigned int extraFieldLength;
2540         if (!getInt(&extraFieldLength))
2541             {
2542             error("bad extraFieldLength found");
2543             return false;
2544             }
2545         std::string fileName;
2546         for (unsigned int i=0 ; i<fileNameLength ; i++)
2547             {
2548             unsigned char ch;
2549             if (!getByte(&ch))
2550                 break;
2551             fileName.push_back(ch);
2552             }
2553         std::string extraField;
2554         for (unsigned int i=0 ; i<extraFieldLength ; i++)
2555             {
2556             unsigned char ch;
2557             if (!getByte(&ch))
2558                 break;
2559             extraField.push_back(ch);
2560             }
2561         trace("#########################  DATA");
2562         trace("FileName           :%d:%s" , fileName.size(), fileName.c_str());
2563         trace("Extra field        :%d:%s" , extraField.size(), extraField.c_str());
2564         trace("Version needed     :%d" , versionNeeded);
2565         trace("Bitflag            :%d" , gpBitFlag);
2566         trace("Compression Method :%d" , compressionMethod);
2567         trace("Mod time           :%d" , modTime);
2568         trace("Mod date           :%d" , modDate);
2569         trace("CRC                :%lx", crc32);
2570         trace("Compressed size    :%ld", compressedSize);
2571         trace("Uncompressed size  :%ld", uncompressedSize);
2573         //#### Uncompress the data
2574         std::vector<unsigned char> compBuf;
2575         if (gpBitFlag & 0x8)//bit 3 was set.  means we dont know compressed size
2576             {
2577             unsigned char c1, c2, c3, c4;
2578             c1 = c2 = c3 = c4 = 0;
2579             while (true)
2580                 {
2581                 unsigned char ch;
2582                 if (!getByte(&ch))
2583                     {
2584                     error("premature end of data");
2585                     break;
2586                     }
2587                 compBuf.push_back(ch);
2588                 c1 = c2; c2 = c3; c3 = c4; c4 = ch;
2589                 if (c1 == 0x50 && c2 == 0x4b && c3 == 0x07 && c4 == 0x08)
2590                     {
2591                     trace("found end of compressed data");
2592                     //remove the cookie
2593                     compBuf.erase(compBuf.end() -4, compBuf.end());
2594                     break;
2595                     }
2596                 }
2597             }
2598         else
2599             {
2600             for (unsigned long bnr = 0 ; bnr < compressedSize ; bnr++)
2601                 {
2602                 unsigned char ch;
2603                 if (!getByte(&ch))
2604                     {
2605                     error("premature end of data");
2606                     break;
2607                     }
2608                 compBuf.push_back(ch);
2609                 }
2610             }
2612         printf("### data: ");
2613         for (int i=0 ; i<10 ; i++)
2614             printf("%02x ", compBuf[i] & 0xff);
2615         printf("\n");
2617         if (gpBitFlag & 0x8)//only if bit 3 set
2618             {
2619             /* this cookie was read in the loop above
2620             unsigned long dataDescriptorSignature ;
2621             if (!getLong(&dataDescriptorSignature))
2622                 break;
2623             if (dataDescriptorSignature != 0x08074b50L)
2624                 {
2625                 error("bad dataDescriptorSignature found");
2626                 return false;
2627                 }
2628             */
2629             unsigned long crc32;
2630             if (!getLong(&crc32))
2631                 {
2632                 error("bad crc32 found");
2633                 return false;
2634                 }
2635             unsigned long compressedSize;
2636             if (!getLong(&compressedSize))
2637                 {
2638                 error("bad compressedSize found");
2639                 return false;
2640                 }
2641             unsigned long uncompressedSize;
2642             if (!getLong(&uncompressedSize))
2643                 {
2644                 error("bad uncompressedSize found");
2645                 return false;
2646                 }
2647             }//bit 3 was set
2648         //break;
2650         std::vector<unsigned char> uncompBuf;
2651         switch (compressionMethod)
2652             {
2653             case 8: //deflate
2654                 {
2655                 Inflater inflater;
2656                 if (!inflater.inflate(uncompBuf, compBuf))
2657                     {
2658                     return false;
2659                     }
2660                 break;
2661                 }
2662             default:
2663                 {
2664                 error("Unimplemented compression method %d", compressionMethod);
2665                 return false;
2666                 }
2667             }
2669         if (uncompressedSize != uncompBuf.size())
2670             {
2671             error("Size mismatch.  Expected %ld, received %ld",
2672                 uncompressedSize, uncompBuf.size());
2673             return false;
2674             }
2676         Crc32 crcEngine;
2677         crcEngine.update(uncompBuf);
2678         unsigned long crc = crcEngine.getValue();
2679         if (crc != crc32)
2680             {
2681             error("Crc mismatch.  Calculated %08ux, received %08ux", crc, crc32);
2682             return false;
2683             }
2685         ZipEntry *ze = new ZipEntry(fileName, comment);
2686         ze->setCompressionMethod(compressionMethod);
2687         ze->setCompressedData(compBuf);
2688         ze->setUncompressedData(uncompBuf);
2689         ze->setCrc(crc);
2690         entries.push_back(ze);
2693         }
2694     return true;
2698 /**
2699  *
2700  */
2701 bool ZipFile::readCentralDirectory()
2703     //printf("#################################################\n");
2704     //printf("###D I R E C T O R Y\n");
2705     //printf("#################################################\n");
2706     while (true)
2707         {
2708         //We start with a central directory cookie already
2709         //Check at the bottom of the loop.
2710         unsigned int version;
2711         if (!getInt(&version))
2712             {
2713             error("bad version found");
2714             return false;
2715             }
2716         unsigned int versionNeeded;
2717         if (!getInt(&versionNeeded))
2718             {
2719             error("bad version found");
2720             return false;
2721             }
2722         unsigned int gpBitFlag;
2723         if (!getInt(&gpBitFlag))
2724             {
2725             error("bad bit flag found");
2726             return false;
2727             }
2728         unsigned int compressionMethod;
2729         if (!getInt(&compressionMethod))
2730             {
2731             error("bad compressionMethod found");
2732             return false;
2733             }
2734         unsigned int modTime;
2735         if (!getInt(&modTime))
2736             {
2737             error("bad modTime found");
2738             return false;
2739             }
2740         unsigned int modDate;
2741         if (!getInt(&modDate))
2742             {
2743             error("bad modDate found");
2744             return false;
2745             }
2746         unsigned long crc32;
2747         if (!getLong(&crc32))
2748             {
2749             error("bad crc32 found");
2750             return false;
2751             }
2752         unsigned long compressedSize;
2753         if (!getLong(&compressedSize))
2754             {
2755             error("bad compressedSize found");
2756             return false;
2757             }
2758         unsigned long uncompressedSize;
2759         if (!getLong(&uncompressedSize))
2760             {
2761             error("bad uncompressedSize found");
2762             return false;
2763             }
2764         unsigned int fileNameLength;
2765         if (!getInt(&fileNameLength))
2766             {
2767             error("bad fileNameLength found");
2768             return false;
2769             }
2770         unsigned int extraFieldLength;
2771         if (!getInt(&extraFieldLength))
2772             {
2773             error("bad extraFieldLength found");
2774             return false;
2775             }
2776         unsigned int fileCommentLength;
2777         if (!getInt(&fileCommentLength))
2778             {
2779             error("bad fileCommentLength found");
2780             return false;
2781             }
2782         unsigned int diskNumberStart;
2783         if (!getInt(&diskNumberStart))
2784             {
2785             error("bad diskNumberStart found");
2786             return false;
2787             }
2788         unsigned int internalFileAttributes;
2789         if (!getInt(&internalFileAttributes))
2790             {
2791             error("bad internalFileAttributes found");
2792             return false;
2793             }
2794         unsigned long externalFileAttributes;
2795         if (!getLong(&externalFileAttributes))
2796             {
2797             error("bad externalFileAttributes found");
2798             return false;
2799             }
2800         unsigned long localHeaderOffset;
2801         if (!getLong(&localHeaderOffset))
2802             {
2803             error("bad localHeaderOffset found");
2804             return false;
2805             }
2806         std::string fileName;
2807         for (unsigned int i=0 ; i<fileNameLength ; i++)
2808             {
2809             unsigned char ch;
2810             if (!getByte(&ch))
2811                 break;
2812             fileName.push_back(ch);
2813             }
2814         std::string extraField;
2815         for (unsigned int i=0 ; i<extraFieldLength ; i++)
2816             {
2817             unsigned char ch;
2818             if (!getByte(&ch))
2819                 break;
2820             extraField.push_back(ch);
2821             }
2822         std::string fileComment;
2823         for (unsigned int i=0 ; i<fileCommentLength ; i++)
2824             {
2825             unsigned char ch;
2826             if (!getByte(&ch))
2827                 break;
2828             fileComment.push_back(ch);
2829             }
2830         trace("######################### ENTRY");
2831         trace("FileName           :%s" , fileName.c_str());
2832         trace("Extra field        :%s" , extraField.c_str());
2833         trace("File comment       :%s" , fileComment.c_str());
2834         trace("Version            :%d" , version);
2835         trace("Version needed     :%d" , versionNeeded);
2836         trace("Bitflag            :%d" , gpBitFlag);
2837         trace("Compression Method :%d" , compressionMethod);
2838         trace("Mod time           :%d" , modTime);
2839         trace("Mod date           :%d" , modDate);
2840         trace("CRC                :%lx", crc32);
2841         trace("Compressed size    :%ld", compressedSize);
2842         trace("Uncompressed size  :%ld", uncompressedSize);
2843         trace("Disk nr start      :%ld", diskNumberStart);
2844         trace("Header offset      :%ld", localHeaderOffset);
2847         unsigned long magicCookie;
2848         if (!getLong(&magicCookie))
2849             {
2850             error("magic cookie not found");
2851             return false;
2852             }
2853         trace("###Cookie:%lx", magicCookie);
2854         if (magicCookie  == 0x06054b50L) //end of central directory
2855             break;
2856         else if (magicCookie == 0x05054b50L) //signature
2857             {
2858             //## Digital Signature
2859             unsigned int signatureSize;
2860             if (!getInt(&signatureSize))
2861                 {
2862                 error("bad signatureSize found");
2863                 return false;
2864                 }
2865             std::string digitalSignature;
2866             for (unsigned int i=0 ; i<signatureSize ; i++)
2867                 {
2868                 unsigned char ch;
2869                 if (!getByte(&ch))
2870                     break;
2871                 digitalSignature.push_back(ch);
2872                 }
2873             trace("######## SIGNATURE :'%s'" , digitalSignature.c_str());
2874             }
2875         else if (magicCookie != 0x02014b50L) //central directory
2876             {
2877             error("directory file header not found");
2878             return false;
2879             }
2880         }
2882     unsigned int diskNr;
2883     if (!getInt(&diskNr))
2884         {
2885         error("bad diskNr found");
2886         return false;
2887         }
2888     unsigned int diskWithCd;
2889     if (!getInt(&diskWithCd))
2890         {
2891         error("bad diskWithCd found");
2892         return false;
2893         }
2894     unsigned int nrEntriesDisk;
2895     if (!getInt(&nrEntriesDisk))
2896         {
2897         error("bad nrEntriesDisk found");
2898         return false;
2899         }
2900     unsigned int nrEntriesTotal;
2901     if (!getInt(&nrEntriesTotal))
2902         {
2903         error("bad nrEntriesTotal found");
2904         return false;
2905         }
2906     unsigned long cdSize;
2907     if (!getLong(&cdSize))
2908         {
2909         error("bad cdSize found");
2910         return false;
2911         }
2912     unsigned long cdPos;
2913     if (!getLong(&cdPos))
2914         {
2915         error("bad cdPos found");
2916         return false;
2917         }
2918     unsigned int commentSize;
2919     if (!getInt(&commentSize))
2920         {
2921         error("bad commentSize found");
2922         return false;
2923         }
2924     comment = "";
2925     for (unsigned int i=0 ; i<commentSize ; i++)
2926         {
2927         unsigned char ch;
2928         if (!getByte(&ch))
2929             break;
2930         comment.push_back(ch);
2931         }
2932     trace("######## Zip Comment :'%s'" , comment.c_str());
2934     return true;
2938 /**
2939  *
2940  */
2941 bool ZipFile::read()
2943     fileBufPos = 0;
2944     if (!readFileData())
2945         {
2946         return false;
2947         }
2948     if (!readCentralDirectory())
2949         {
2950         return false;
2951         }
2952     return true;
2955 /**
2956  *
2957  */
2958 bool ZipFile::readBuffer(const std::vector<unsigned char> &inbuf)
2960     fileBuf = inbuf;
2961     if (!read())
2962         return false;
2963     return true;
2967 /**
2968  *
2969  */
2970 bool ZipFile::readFile(const std::string &fileName)
2972     fileBuf.clear();
2973     FILE *f = fopen(fileName.c_str(), "rb");
2974     if (!f)
2975         return false;
2976     while (true)
2977         {
2978         int ch = fgetc(f);
2979         if (ch < 0)
2980             break;
2981         fileBuf.push_back(ch);
2982         }
2983     fclose(f);
2984     if (!read())
2985         return false;
2986     return true;
2997 //########################################################################
2998 //#  E N D    O F    F I L E
2999 //########################################################################