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