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;
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, ...)
235 #ifdef G_GNUC_PRINTF
236 G_GNUC_PRINTF(2, 3)
237 #endif
238 ;
240 /**
241 *
242 */
243 void trace(char *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()
304 {
305 }
307 /**
308 *
309 */
310 Inflater::~Inflater()
311 {
312 }
314 /**
315 *
316 */
317 void Inflater::error(char *fmt, ...)
318 {
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);
325 }
327 /**
328 *
329 */
330 void Inflater::trace(char *fmt, ...)
331 {
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);
338 }
341 /**
342 *
343 */
344 void Inflater::dump()
345 {
346 for (unsigned int i=0 ; i<dest.size() ; i++)
347 {
348 fputc(dest[i], stdout);
349 }
350 }
352 /**
353 *
354 */
355 int Inflater::buildHuffman(Huffman *h, int *length, int n)
356 {
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;
397 }
400 /**
401 *
402 */
403 bool Inflater::getBits(int requiredBits, int *oval)
404 {
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;
425 }
428 /**
429 *
430 */
431 int Inflater::doDecode(Huffman *h)
432 {
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;
475 }
477 /**
478 *
479 */
480 bool Inflater::doCodes(Huffman *lencode, Huffman *distcode)
481 {
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;
553 }
555 /**
556 */
557 bool Inflater::doStored()
558 {
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;
593 }
595 /**
596 */
597 bool Inflater::doFixed()
598 {
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;
634 }
636 /**
637 */
638 bool Inflater::doDynamic()
639 {
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;
743 }
745 /**
746 */
747 bool Inflater::inflate(std::vector<unsigned char> &destination,
748 std::vector<unsigned char> &source)
749 {
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;
789 }
796 //########################################################################
797 //# D E F L A T E R
798 //########################################################################
802 class Deflater
803 {
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 *fmt, ...)
848 #ifdef G_GNUC_PRINTF
849 G_GNUC_PRINTF(2, 3)
850 #endif
851 ;
853 void trace(char *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()
903 {
904 reset();
905 }
907 /**
908 *
909 */
910 Deflater::~Deflater()
911 {
913 }
915 /**
916 *
917 */
918 void Deflater::reset()
919 {
920 outputBitBuf = 0;
921 outputNrBits = 0;
922 window.clear();
923 compressed.clear();
924 uncompressed.clear();
925 }
927 /**
928 *
929 */
930 bool Deflater::update(int ch)
931 {
932 uncompressed.push_back((unsigned char)(ch & 0xff));
933 return true;
934 }
936 /**
937 *
938 */
939 bool Deflater::finish()
940 {
941 return compress();
942 }
944 /**
945 *
946 */
947 std::vector<unsigned char> &Deflater::getCompressed()
948 {
949 return compressed;
950 }
953 /**
954 *
955 */
956 bool Deflater::deflate(std::vector<unsigned char> &dest,
957 const std::vector<unsigned char> &src)
958 {
959 reset();
960 uncompressed = src;
961 if (!compress())
962 return false;
963 dest = compressed;
964 return true;
965 }
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 *fmt, ...)
986 {
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);
993 }
995 /**
996 * Print trace messages
997 */
998 void Deflater::trace(char *fmt, ...)
999 {
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);
1006 }
1011 //#############################
1012 //# O U T P U T
1013 //#############################
1015 /**
1016 *
1017 */
1018 void Deflater::put(int ch)
1019 {
1020 compressed.push_back(ch);
1021 outputBitBuf = 0;
1022 outputNrBits = 0;
1023 }
1025 /**
1026 *
1027 */
1028 void Deflater::putWord(int ch)
1029 {
1030 int lo = (ch ) & 0xff;
1031 int hi = (ch>>8) & 0xff;
1032 put(lo);
1033 put(hi);
1034 }
1036 /**
1037 *
1038 */
1039 void Deflater::putFlush()
1040 {
1041 if (outputNrBits > 0)
1042 {
1043 put(outputBitBuf & 0xff);
1044 }
1045 outputBitBuf = 0;
1046 outputNrBits = 0;
1047 }
1049 /**
1050 *
1051 */
1052 void Deflater::putBits(unsigned int ch, unsigned int bitsWanted)
1053 {
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 }
1069 }
1071 static unsigned int bitReverse(unsigned int code, unsigned int nrBits)
1072 {
1073 unsigned int outb = 0;
1074 while (nrBits--)
1075 {
1076 outb = (outb << 1) | (code & 0x01);
1077 code >>= 1;
1078 }
1079 return outb;
1080 }
1083 /**
1084 *
1085 */
1086 void Deflater::putBitsR(unsigned int ch, unsigned int bitsWanted)
1087 {
1088 //trace("r:%4u, %d", ch, bitsWanted);
1090 unsigned int rcode = bitReverse(ch, bitsWanted);
1092 putBits(rcode, bitsWanted);
1094 }
1097 //#############################
1098 //# E N C O D E
1099 //#############################
1103 void Deflater::encodeLiteralStatic(unsigned int ch)
1104 {
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 }
1128 }
1131 typedef struct
1132 {
1133 unsigned int base;
1134 unsigned int range;
1135 unsigned int bits;
1136 } LenBase;
1138 LenBase lenBases[] =
1139 {
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
1172 {
1173 unsigned int base;
1174 unsigned int range;
1175 unsigned int bits;
1176 } DistBase;
1178 DistBase distBases[] =
1179 {
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)
1213 {
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 }
1274 }
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()
1289 {
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;
1369 }
1372 /**
1373 *
1374 */
1375 bool Deflater::compress()
1376 {
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;
1403 }
1409 //########################################################################
1410 //# G Z I P F I L E
1411 //########################################################################
1413 /**
1414 * Constructor
1415 */
1416 GzipFile::GzipFile()
1417 {
1418 }
1420 /**
1421 * Destructor
1422 */
1423 GzipFile::~GzipFile()
1424 {
1425 }
1427 /**
1428 * Print error messages
1429 */
1430 void GzipFile::error(char *fmt, ...)
1431 {
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);
1438 }
1440 /**
1441 * Print trace messages
1442 */
1443 void GzipFile::trace(char *fmt, ...)
1444 {
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);
1451 }
1453 /**
1454 *
1455 */
1456 void GzipFile::put(unsigned char ch)
1457 {
1458 data.push_back(ch);
1459 }
1461 /**
1462 *
1463 */
1464 void GzipFile::setData(const std::vector<unsigned char> &str)
1465 {
1466 data = str;
1467 }
1469 /**
1470 *
1471 */
1472 void GzipFile::clearData()
1473 {
1474 data.clear();
1475 }
1477 /**
1478 *
1479 */
1480 std::vector<unsigned char> &GzipFile::getData()
1481 {
1482 return data;
1483 }
1485 /**
1486 *
1487 */
1488 std::string &GzipFile::getFileName()
1489 {
1490 return fileName;
1491 }
1493 /**
1494 *
1495 */
1496 void GzipFile::setFileName(const std::string &val)
1497 {
1498 fileName = val;
1499 }
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)
1511 {
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;
1528 }
1532 //#####################################
1533 //# W R I T E
1534 //#####################################
1536 /**
1537 *
1538 */
1539 bool GzipFile::putByte(unsigned char ch)
1540 {
1541 fileBuf.push_back(ch);
1542 return true;
1543 }
1547 /**
1548 *
1549 */
1550 bool GzipFile::putLong(unsigned long val)
1551 {
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;
1557 }
1561 /**
1562 *
1563 */
1564 bool GzipFile::write()
1565 {
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;
1610 }
1613 /**
1614 *
1615 */
1616 bool GzipFile::writeBuffer(std::vector<unsigned char> &outBuf)
1617 {
1618 if (!write())
1619 return false;
1620 outBuf.clear();
1621 outBuf = fileBuf;
1622 return true;
1623 }
1626 /**
1627 *
1628 */
1629 bool GzipFile::writeFile(const std::string &fileName)
1630 {
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;
1644 }
1647 //#####################################
1648 //# R E A D
1649 //#####################################
1651 bool GzipFile::getByte(unsigned char *ch)
1652 {
1653 if (fileBufPos >= fileBuf.size())
1654 {
1655 error("unexpected end of data");
1656 return false;
1657 }
1658 *ch = fileBuf[fileBufPos++];
1659 return true;
1660 }
1662 /**
1663 *
1664 */
1665 bool GzipFile::getLong(unsigned long *val)
1666 {
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;
1678 }
1680 bool GzipFile::read()
1681 {
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(<ime))
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;
1828 }
1832 /**
1833 *
1834 */
1835 bool GzipFile::readBuffer(const std::vector<unsigned char> &inbuf)
1836 {
1837 fileBuf = inbuf;
1838 if (!read())
1839 return false;
1840 return true;
1841 }
1844 /**
1845 *
1846 */
1847 bool GzipFile::readFile(const std::string &fileName)
1848 {
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;
1864 }
1873 //########################################################################
1874 //# Z I P F I L E
1875 //########################################################################
1877 /**
1878 * Constructor
1879 */
1880 ZipEntry::ZipEntry()
1881 {
1882 crc = 0L;
1883 compressionMethod = 8;
1884 }
1886 /**
1887 *
1888 */
1889 ZipEntry::ZipEntry(const std::string &fileNameArg,
1890 const std::string &commentArg)
1891 {
1892 crc = 0L;
1893 compressionMethod = 8;
1894 fileName = fileNameArg;
1895 comment = commentArg;
1896 }
1898 /**
1899 * Destructor
1900 */
1901 ZipEntry::~ZipEntry()
1902 {
1903 }
1906 /**
1907 *
1908 */
1909 std::string ZipEntry::getFileName()
1910 {
1911 return fileName;
1912 }
1914 /**
1915 *
1916 */
1917 void ZipEntry::setFileName(const std::string &val)
1918 {
1919 fileName = val;
1920 }
1922 /**
1923 *
1924 */
1925 std::string ZipEntry::getComment()
1926 {
1927 return comment;
1928 }
1930 /**
1931 *
1932 */
1933 void ZipEntry::setComment(const std::string &val)
1934 {
1935 comment = val;
1936 }
1938 /**
1939 *
1940 */
1941 unsigned long ZipEntry::getCompressedSize()
1942 {
1943 return (unsigned long)compressedData.size();
1944 }
1946 /**
1947 *
1948 */
1949 int ZipEntry::getCompressionMethod()
1950 {
1951 return compressionMethod;
1952 }
1954 /**
1955 *
1956 */
1957 void ZipEntry::setCompressionMethod(int val)
1958 {
1959 compressionMethod = val;
1960 }
1962 /**
1963 *
1964 */
1965 std::vector<unsigned char> &ZipEntry::getCompressedData()
1966 {
1967 return compressedData;
1968 }
1970 /**
1971 *
1972 */
1973 void ZipEntry::setCompressedData(const std::vector<unsigned char> &val)
1974 {
1975 compressedData = val;
1976 }
1978 /**
1979 *
1980 */
1981 unsigned long ZipEntry::getUncompressedSize()
1982 {
1983 return (unsigned long)uncompressedData.size();
1984 }
1986 /**
1987 *
1988 */
1989 std::vector<unsigned char> &ZipEntry::getUncompressedData()
1990 {
1991 return uncompressedData;
1992 }
1994 /**
1995 *
1996 */
1997 void ZipEntry::setUncompressedData(const std::vector<unsigned char> &val)
1998 {
1999 uncompressedData = val;
2000 }
2002 /**
2003 *
2004 */
2005 unsigned long ZipEntry::getCrc()
2006 {
2007 return crc;
2008 }
2010 /**
2011 *
2012 */
2013 void ZipEntry::setCrc(unsigned long val)
2014 {
2015 crc = val;
2016 }
2018 /**
2019 *
2020 */
2021 void ZipEntry::write(unsigned char ch)
2022 {
2023 uncompressedData.push_back(ch);
2024 }
2026 /**
2027 *
2028 */
2029 void ZipEntry::finish()
2030 {
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 }
2067 }
2072 /**
2073 *
2074 */
2075 bool ZipEntry::readFile(const std::string &fileNameArg,
2076 const std::string &commentArg)
2077 {
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;
2097 }
2100 /**
2101 *
2102 */
2103 void ZipEntry::setPosition(unsigned long val)
2104 {
2105 position = val;
2106 }
2108 /**
2109 *
2110 */
2111 unsigned long ZipEntry::getPosition()
2112 {
2113 return position;
2114 }
2122 /**
2123 * Constructor
2124 */
2125 ZipFile::ZipFile()
2126 {
2128 }
2130 /**
2131 * Destructor
2132 */
2133 ZipFile::~ZipFile()
2134 {
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();
2142 }
2144 /**
2145 *
2146 */
2147 void ZipFile::setComment(const std::string &val)
2148 {
2149 comment = val;
2150 }
2152 /**
2153 *
2154 */
2155 std::string ZipFile::getComment()
2156 {
2157 return comment;
2158 }
2161 /**
2162 *
2163 */
2164 std::vector<ZipEntry *> &ZipFile::getEntries()
2165 {
2166 return entries;
2167 }
2171 //#####################################
2172 //# M E S S A G E S
2173 //#####################################
2175 void ZipFile::error(char *fmt, ...)
2176 {
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);
2183 }
2185 void ZipFile::trace(char *fmt, ...)
2186 {
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);
2193 }
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)
2204 {
2205 ZipEntry *ze = new ZipEntry();
2206 if (!ze->readFile(fileName, comment))
2207 {
2208 return NULL;
2209 }
2210 entries.push_back(ze);
2211 return ze;
2212 }
2215 /**
2216 *
2217 */
2218 ZipEntry *ZipFile::newEntry(const std::string &fileName,
2219 const std::string &comment)
2220 {
2221 ZipEntry *ze = new ZipEntry(fileName, comment);
2222 entries.push_back(ze);
2223 return ze;
2224 }
2227 //#####################################
2228 //# W R I T E
2229 //#####################################
2231 /**
2232 *
2233 */
2234 bool ZipFile::putLong(unsigned long val)
2235 {
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;
2241 }
2244 /**
2245 *
2246 */
2247 bool ZipFile::putInt(unsigned int val)
2248 {
2249 fileBuf.push_back( (val ) & 0xff);
2250 fileBuf.push_back( (val>> 8) & 0xff);
2251 return true;
2252 }
2254 /**
2255 *
2256 */
2257 bool ZipFile::putByte(unsigned char val)
2258 {
2259 fileBuf.push_back(val);
2260 return true;
2261 }
2263 /**
2264 *
2265 */
2266 bool ZipFile::writeFileData()
2267 {
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;
2306 }
2308 /**
2309 *
2310 */
2311 bool ZipFile::writeCentralDirectory()
2312 {
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;
2361 }
2365 /**
2366 *
2367 */
2368 bool ZipFile::write()
2369 {
2370 fileBuf.clear();
2371 if (!writeFileData())
2372 return false;
2373 if (!writeCentralDirectory())
2374 return false;
2375 return true;
2376 }
2379 /**
2380 *
2381 */
2382 bool ZipFile::writeBuffer(std::vector<unsigned char> &outBuf)
2383 {
2384 if (!write())
2385 return false;
2386 outBuf.clear();
2387 outBuf = fileBuf;
2388 return true;
2389 }
2392 /**
2393 *
2394 */
2395 bool ZipFile::writeFile(const std::string &fileName)
2396 {
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;
2410 }
2412 //#####################################
2413 //# R E A D
2414 //#####################################
2416 /**
2417 *
2418 */
2419 bool ZipFile::getLong(unsigned long *val)
2420 {
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;
2432 }
2434 /**
2435 *
2436 */
2437 bool ZipFile::getInt(unsigned int *val)
2438 {
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;
2446 }
2449 /**
2450 *
2451 */
2452 bool ZipFile::getByte(unsigned char *val)
2453 {
2454 if (fileBuf.size() <= fileBufPos)
2455 return false;
2456 *val = fileBuf[fileBufPos++];
2457 return true;
2458 }
2461 /**
2462 *
2463 */
2464 bool ZipFile::readFileData()
2465 {
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;
2695 }
2698 /**
2699 *
2700 */
2701 bool ZipFile::readCentralDirectory()
2702 {
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;
2935 }
2938 /**
2939 *
2940 */
2941 bool ZipFile::read()
2942 {
2943 fileBufPos = 0;
2944 if (!readFileData())
2945 {
2946 return false;
2947 }
2948 if (!readCentralDirectory())
2949 {
2950 return false;
2951 }
2952 return true;
2953 }
2955 /**
2956 *
2957 */
2958 bool ZipFile::readBuffer(const std::vector<unsigned char> &inbuf)
2959 {
2960 fileBuf = inbuf;
2961 if (!read())
2962 return false;
2963 return true;
2964 }
2967 /**
2968 *
2969 */
2970 bool ZipFile::readFile(const std::string &fileName)
2971 {
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;
2987 }
2997 //########################################################################
2998 //# E N D O F F I L E
2999 //########################################################################