1 /*****************************************************************************/
2 /* Software Testing Automation Framework (STAF) */
3 /* (C) Copyright IBM Corp. 2004 */
4 /* */
5 /* This software is licensed under the Eclipse Public License (EPL) V1.0. */
6 /*****************************************************************************/
7 #include "STAF.h"
8 #include "STAFString.h"
9 #include "STAFTrace.h"
10
11 #include <vector>
12 #include <map>
13
14 #include "zlib.h"
15
16 #include "STAFZip.h"
17 #include "STAFZipUtil.h"
18 #include "STAFZipFileAttribute.h"
19 #include "STAFZipCentralDirExtension.h"
20 #include "STAFZipLocalFileHeader.h"
21 #include "STAFZipFileHeader.h"
22
23
24 // constructor
STAFZipLocalFileHeader()25 STAFZipLocalFileHeader::STAFZipLocalFileHeader()
26 {
27 signature = 0x04034b50;
28
29 // 2 bytes, zip 2.0
30 versionNeededToExtract = 20;
31
32 // 2 bytes, general purpose bit flag bit 2, 1 set to be 1 0 for
33 // maximum compression
34 generalPurposeBitFlag = 2;
35
36 // 2 bytes, method 8 - deflating
37 compressionMethod = Z_DEFLATED;
38
39 // 2 bytes time, 2 bytes date
40 lastModifiedTimeDate = 0;
41
42 // 4 bytes
43 crc = 0;
44
45 // 4 bytes, not initialized yet
46 compressedSize = 0;
47
48 // 4 bytes, not initialized yet
49 uncompressedSize = 0;
50
51 // 2 bytes
52 fileNameLength = 0;
53
54 // 2 bytes
55 extraFieldLength = 0;
56
57 fileName = NULL;
58
59 extraField = NULL;
60
61 fullFileName = NULL;
62
63 size = 30;
64
65 offset = 0;
66
67 }
68
69
70 // constructor based on pathname and prefix length
STAFZipLocalFileHeader(const char * pathname,int prefixlen)71 STAFZipLocalFileHeader::STAFZipLocalFileHeader(const char *pathname,
72 int prefixlen)
73 {
74 STAFZipUtil util = STAFZipUtil();
75
76 signature = 0x04034b50;
77
78
79 fileName = NULL;
80
81 fullFileName = NULL;
82
83 // 2 bytes
84 fileNameLength = 0;
85
86 // 2 bytes time, 2 bytes date
87 lastModifiedTimeDate = 0;
88
89
90 fullFileName = (char*)calloc(strlen(pathname) + 1, 1);
91
92 if (fullFileName != NULL)
93 {
94 strcpy(fullFileName, pathname);
95
96 fileName = util.calculateFileNameInZip(fullFileName, prefixlen);
97
98 fileNameLength = strlen(fileName);
99
100 lastModifiedTimeDate = util.fileTime(fullFileName);
101 }
102 else
103 {
104 STAFTrace::trace(kSTAFTraceServiceResult,
105 STAFString("STAFZipLocalFileHeader::STAFZipLocalFileHeader1_CP1")
106 + "Error allocating memory for full file name.\n");
107 }
108
109 // 2 bytes, zip 2.0
110 versionNeededToExtract = 20;
111
112 // 2 bytes, general purpose bit flag bit 2, 1 set to be 1 0 for
113 // maximum compression
114 generalPurposeBitFlag = 2;
115
116 // 2 bytes, method 8 - deflating
117 compressionMethod = Z_DEFLATED;
118
119 // 4 bytes
120 crc = 0;
121
122 // 4 bytes, not initialized yet
123 compressedSize = 0;
124
125 // 4 bytes, not initialized yet
126 uncompressedSize = 0;
127
128 // 2 bytes
129 extraFieldLength = 0;
130
131 extraField = NULL;
132
133
134 size = 30 + fileNameLength;
135
136 offset = 0;
137
138 }
139
140
141 // flush local file header to zip archive and deflating data by
142 // using of zlib utility
flush(FILE * zf,STAFString * result)143 STAFRC_t STAFZipLocalFileHeader::flush(FILE *zf, STAFString *result)
144 {
145 STAFZipUtil util = STAFZipUtil();
146
147 STAFRC_t rc;
148 int err;
149
150 // save the current file offset
151 offset = util.tell(zf);
152
153 // write the local header
154
155 STAFTrace::trace(kSTAFTraceServiceResult,
156 STAFString("STAFZipLocalFileHeader::flush_CP1")
157 + " offset ["
158 + offset
159 + "] signature ["
160 + signature
161 + "]");
162
163 // local header magic
164 rc = util.putValue(zf, (uLong)signature, 4);
165
166 // version needed to extract
167 if (rc == kSTAFOk)
168 {
169 STAFTrace::trace(kSTAFTraceServiceResult,
170 STAFString("STAFZipLocalFileHeader::flush_CP2")
171 + " versionNeededToExtract ["
172 + versionNeededToExtract
173 + "]");
174
175 rc = util.putValue(zf, (uLong)versionNeededToExtract, 2);
176 }
177
178 // general purpose bit flag, 2 for Maximum (-exx/-ex) compression option was
179 // used for method 8 and 9 - deflating
180 if (rc == kSTAFOk)
181 {
182 STAFTrace::trace(kSTAFTraceServiceResult,
183 STAFString("STAFZipLocalFileHeader::flush_CP3")
184 + " generalPurposeBitFlag ["
185 + generalPurposeBitFlag
186 + "]");
187
188 rc = util.putValue(zf, (uLong)generalPurposeBitFlag, 2);
189 }
190
191 // compression method
192 if (rc == kSTAFOk)
193 {
194 STAFTrace::trace(kSTAFTraceServiceResult,
195 STAFString("STAFZipLocalFileHeader::flush_CP4")
196 + " compressionMethod ["
197 + compressionMethod
198 + "]");
199
200 rc = util.putValue(zf, (uLong)compressionMethod, 2);
201 }
202
203 // file time in DOS format
204 if (rc == kSTAFOk)
205 {
206 STAFTrace::trace(kSTAFTraceServiceResult,
207 STAFString("STAFZipLocalFileHeader::flush_CP5")
208 + " lastModifiedTimeDate ["
209 + lastModifiedTimeDate
210 + "]");
211
212 rc = util.putValue(zf, (uLong)lastModifiedTimeDate, 4);
213 }
214
215 // CRC 32, unknown
216 if (rc == kSTAFOk)
217 {
218 STAFTrace::trace(kSTAFTraceServiceResult,
219 STAFString("STAFZipLocalFileHeader::flush_CP6")
220 + " crc ["
221 + crc
222 + "]");
223
224 rc = util.putValue(zf, (uLong)crc, 4);
225 }
226
227 // compressed size, unknown
228 if (rc == kSTAFOk)
229 {
230 STAFTrace::trace(kSTAFTraceServiceResult,
231 STAFString("STAFZipLocalFileHeader::flush_CP7")
232 + " compressedSize ["
233 + compressedSize
234 + "]");
235
236 rc = util.putValue(zf, (uLong)compressedSize, 4);
237 }
238
239 // uncompressed size, unknown
240 if (rc == kSTAFOk)
241 {
242 STAFTrace::trace(kSTAFTraceServiceResult,
243 STAFString("STAFZipLocalFileHeader::flush_CP7")
244 + " uncompressedSize ["
245 + uncompressedSize
246 + "]");
247
248 rc = util.putValue(zf, (uLong)uncompressedSize, 4);
249 }
250
251 // file name size
252 if (rc == kSTAFOk)
253 {
254 STAFTrace::trace(kSTAFTraceServiceResult,
255 STAFString("STAFZipLocalFileHeader::flush_CP8")
256 + " fileNameLength ["
257 + fileNameLength
258 + "]");
259
260 rc = util.putValue(zf, (uLong)fileNameLength, 2);
261 }
262
263 // extra field size
264 if (rc == kSTAFOk)
265 {
266 STAFTrace::trace(kSTAFTraceServiceResult,
267 STAFString("STAFZipLocalFileHeader::flush_CP9")
268 + " extraFieldLength ["
269 + extraFieldLength
270 + "]");
271
272 rc = util.putValue(zf, (uLong)extraFieldLength, 2);
273 }
274
275 // file name
276 if (rc == kSTAFOk && fileNameLength > 0)
277 {
278 STAFTrace::trace(kSTAFTraceServiceResult,
279 STAFString("STAFZipLocalFileHeader::flush_CP10")
280 + " fileName ["
281 + fileName
282 + "]");
283
284 if (fwrite(fileName, (uInt)fileNameLength, 1, zf)!=1)
285 {
286 *result = STAFString("STAFZipLocalFileHeader::flush: ")
287 + "Error writting file name ["
288 + fileName
289 + "].\n";
290
291 rc = kZIPGeneralZipError;
292 }
293 }
294
295 // extra field
296 if (rc == kSTAFOk && extraFieldLength > 0)
297 {
298 STAFTrace::trace(kSTAFTraceServiceResult,
299 STAFString("STAFZipLocalFileHeader::flush_CP12")
300 + " extraField offset ["
301 + util.tell(zf)
302 + "]");
303
304 if (fwrite(extraField, (uInt)extraFieldLength, 1, zf)!=1)
305 {
306 *result = STAFString("STAFZipLocalFileHeader::flush: ")
307 + "Error writting extra field ["
308 + fileName
309 + "].\n";
310
311 rc = kZIPGeneralZipError;
312 }
313 }
314
315
316 if (rc != kSTAFOk)
317 {
318
319 if ((*result).length() == 0)
320 {
321 *result = STAFString("STAFZipLocalFileHeader::flush: ")
322 + "Error writing data.\n";
323 }
324
325 return rc;
326 }
327
328
329 // start deflating the file
330 if (*(fileName + fileNameLength - 1) != '/'
331 && *(fileName + fileNameLength - 1) != '\\')
332 {
333
334 void *outbuf = NULL;
335 void *inbuf = NULL;
336
337
338 // allocate output buffer
339 outbuf = (void*)malloc(Z_BUFSIZE);
340 if(outbuf == NULL)
341 {
342 *result = STAFString("STAFZipLocalFileHeader::flush: ")
343 + "Error allocating memory for zip output buffer ["
344 + Z_BUFSIZE
345 + "].\n";
346
347 return kZIPNotEnoughMemory;
348 }
349
350
351 // initialize zLib stream structure for deflate
352 z_stream stream;
353
354
355 stream.total_in = 0;
356
357 stream.total_out = 0;
358
359 stream.zalloc = (alloc_func)0;
360
361 stream.zfree = (free_func)0;
362
363 stream.opaque = (voidpf)0;
364
365 uInt level = 9;
366
367 err = deflateInit2(&stream, level,
368 Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
369
370
371 if (err != Z_OK)
372 {
373 free(outbuf);
374
375 *result = STAFString("STAFZipLocalFileHeader::flush: ")
376 + "Error in zlib deflate init ["
377 + err
378 + "].\n";
379
380 return kZIPGeneralZipError;
381 }
382
383
384 // allocate input buffer
385 inbuf = (void*)malloc(Z_BUFSIZE);
386 if(inbuf == NULL)
387 {
388 *result = STAFString("STAFZipLocalFileHeader::flush: ")
389 + "Error allocating memory for zip input buffer ["
390 + Z_BUFSIZE
391 + "].\n";
392
393 return kZIPNotEnoughMemory;
394 }
395
396
397
398 FILE *fin;
399
400 // open the to be zipped file
401 fin = fopen(fullFileName, "rb");
402 if (fin == NULL)
403 {
404 *result = STAFString("STAFZipLocalFileHeader::flush: ")
405 + "Error in open file ["
406 + fullFileName
407 + "].\n";
408
409 free(inbuf);
410 free(outbuf);
411
412 return kSTAFFileOpenError;
413 }
414
415
416 uInt compressed_bytes;
417
418 stream.avail_in = (uInt)0;
419
420
421 // loop to read data from original file
422 while (err == Z_OK)
423 {
424
425 // prepare zip buffer
426
427 stream.next_out = (Bytef*)outbuf;
428
429 stream.avail_out = (uInt)Z_BUFSIZE;
430
431
432 // set compressed bytes to 0
433 compressed_bytes = 0;
434
435
436 STAFTrace::trace(kSTAFTraceServiceResult,
437 STAFString("STAFZipLocalFileHeader::flush_CP19")
438 + " stream.avail_out ["
439 + stream.avail_out
440 + "] stream.avail_in ["
441 + stream.avail_in
442 + "]");
443
444 // loop to zip data
445 while (stream.avail_out > 0 && err == Z_OK)
446 {
447
448 if (stream.avail_in == 0)
449 {
450
451 // read Z_BUFSIZE of bytes from file
452 stream.avail_in = fread(inbuf, 1, Z_BUFSIZE, fin);
453
454 STAFTrace::trace(kSTAFTraceServiceResult,
455 STAFString("STAFZipLocalFileHeader::flush_CP20")
456 + " stream.avail_in ["
457 + stream.avail_in
458 + "]");
459
460 // if size read < Z_BUFSIZE and not end of file, return err
461 if (stream.avail_in < Z_BUFSIZE)
462 {
463 if (feof(fin) == 0)
464 {
465 *result =
466 STAFString("STAFZipLocalFileHeader::flush: ")
467 + "Error in reading file ["
468 + fullFileName
469 + "].\n";
470
471 rc = kSTAFFileReadError;
472
473 break;
474 }
475 }
476
477
478 // if size read > 0
479 if (stream.avail_in > 0)
480 {
481 // set next in
482 stream.next_in = (Bytef*)inbuf;
483
484 // calculate crc
485 crc = crc32(crc, stream.next_in, stream.avail_in);
486 }
487
488 } // read in raw data from file
489
490
491 // save the total out before delfating
492 uLong uTotalOutBefore = stream.total_out;
493
494 STAFTrace::trace(kSTAFTraceServiceResult,
495 STAFString("STAFZipLocalFileHeader::flush_CP22")
496 + " stream.total_out ["
497 + stream.total_out
498 + "] stream.avail_in ["
499 + stream.avail_in
500 + "]");
501
502
503 if (stream.avail_in == 0)
504 {
505 // do delate with Z_FINISH
506 err = deflate(&stream, Z_FINISH);
507 }
508 else
509 {
510 // do delate with Z_NO_FLUSH
511 err = deflate(&stream, Z_NO_FLUSH);
512 }
513
514
515 // calculate compressed size
516 compressed_bytes += (uInt)(stream.total_out - uTotalOutBefore);
517
518 STAFTrace::trace(kSTAFTraceServiceResult,
519 STAFString("STAFZipLocalFileHeader::flush_CP23")
520 + " stream.total_out ["
521 + stream.total_out
522 + "] uTotalOutBefore ["
523 + uTotalOutBefore
524 + "] compressed_bytes ["
525 + compressed_bytes
526 + "]");
527
528 } // loop to zip data
529
530
531 // if error, break
532 if (rc != kSTAFOk || (err != Z_STREAM_END && err != Z_OK))
533 {
534 if ((*result).length() == 0)
535 {
536 *result = STAFString("STAFZipLocalFileHeader::flush: ")
537 + "Error in deflating ["
538 + err
539 + "].\n";
540 }
541
542 rc = kZIPGeneralZipError;
543
544 break;
545 }
546
547
548 // write the unzipped buffer to file
549
550 STAFTrace::trace(kSTAFTraceServiceResult,
551 STAFString("STAFZipLocalFileHeader::flush_CP25")
552 + " compressed_bytes ["
553 + compressed_bytes
554 + "]");
555
556 if (compressed_bytes > 0)
557 {
558 if (fwrite(outbuf, compressed_bytes, 1, zf)!=1)
559 {
560 *result = STAFString("STAFZipLocalFileHeader::flush: ")
561 + "Error writting compressed bytes ["
562 + compressed_bytes
563 + "].\n";
564
565 rc = kSTAFFileWriteError;
566
567 break;
568 }
569
570 }
571
572
573 } // loop to read data from original file
574
575
576 fclose(fin);
577
578 STAFTrace::trace(kSTAFTraceServiceResult,
579 STAFString("STAFZipLocalFileHeader::flush_CP27")
580 + " err ["
581 + err
582 + "] rc ["
583 + rc
584 + "]");
585
586 // end the deflate
587 if (err == Z_STREAM_END && rc == kSTAFOk)
588 {
589 err = deflateEnd(&stream);
590 }
591
592
593 free(inbuf);
594
595 free(outbuf);
596
597
598 if (err != Z_OK)
599 {
600 if ((*result).length() == 0)
601 {
602 *result = STAFString("STAFZipLocalFileHeader::flush: ")
603 + "Error finishing deflating ["
604 + err
605 + "].\n";
606 }
607
608 rc = kZIPGeneralZipError;
609 }
610
611
612 if (rc != kSTAFOk)
613 {
614 return rc;
615 }
616
617
618 compressedSize = stream.total_out;
619
620 uncompressedSize = stream.total_in;
621
622
623
624 // save current end of local file header position
625 STAFInt64_t curpos = util.tell(zf);
626
627 STAFTrace::trace(kSTAFTraceServiceResult,
628 STAFString("STAFZipLocalFileHeader::flush_CP30")
629 + " curpos ["
630 + curpos
631 + "]");
632
633 // update crc, compressed size, uncompressed size
634 if (util.seek(zf, offset + 14, SEEK_SET) != 0)
635 {
636 *result = STAFString("STAFZipLocalFileHeader::flush: ")
637 + "Error seek crc, compressed uncompressed size ["
638 + (offset + 14)
639 + "].\n";
640
641 rc = kZIPGeneralZipError;
642 }
643
644
645 // save crc32
646 if (rc == kSTAFOk)
647 {
648 STAFTrace::trace(kSTAFTraceServiceResult,
649 STAFString("STAFZipLocalFileHeader::flush_CP32")
650 + " crc ["
651 + crc
652 + "]");
653
654 rc = util.putValue(zf, (uLong)crc, 4);
655 }
656
657 // save compressed size
658 if (rc == kSTAFOk)
659 {
660 STAFTrace::trace(kSTAFTraceServiceResult,
661 STAFString("STAFZipLocalFileHeader::flush_CP33")
662 + " compressedSize ["
663 + compressedSize
664 + "]");
665
666 rc = util.putValue(zf, (uLong)compressedSize, 4);
667 }
668
669
670 // save uncompressed size
671 if (rc == kSTAFOk)
672 {
673 STAFTrace::trace(kSTAFTraceServiceResult,
674 STAFString("STAFZipLocalFileHeader::flush_CP34")
675 + " uncompressedSize ["
676 + uncompressedSize
677 + "]");
678
679 rc = util.putValue(zf, (uLong)uncompressedSize, 4);
680 }
681
682
683 // restore the previous end of local file header position
684 if (util.seek(zf, curpos, SEEK_SET) != 0 && rc == kSTAFOk)
685 {
686 *result = STAFString("STAFZipLocalFileHeader::flush: ")
687 + "Error restore end of local header pos ["
688 + curpos
689 + "].\n";
690
691 rc = kZIPGeneralZipError;
692 }
693
694
695 } // zip the file
696
697 size = util.tell(zf) - offset;
698
699 STAFTrace::trace(kSTAFTraceServiceResult,
700 STAFString("STAFZipLocalFileHeader::flush_CP36")
701 + " size ["
702 + size
703 + "]");
704
705 return rc;
706 }
707
708
709 // extract one file from zip archive by using zlib utility
doExtract(FILE * zf,uLong startPos,FILE * outfile,STAFString * result)710 STAFRC_t STAFZipLocalFileHeader::doExtract(FILE *zf, uLong startPos,
711 FILE *outfile,
712 STAFString *result)
713 {
714 STAFZipUtil util = STAFZipUtil();
715 z_stream stream;
716 stream.total_out = 0;
717
718 int err = Z_OK;
719 STAFRC_t rc = kSTAFOk;
720
721 STAFTrace::trace(kSTAFTraceServiceResult,
722 STAFString("STAFZipLocalFileHeader::doExtract_CP1")
723 + " rc ["
724 + rc
725 + "]");
726
727 if (compressionMethod != 0)
728 {
729 stream.zalloc = (alloc_func)0;
730 stream.zfree = (free_func)0;
731 stream.opaque = (voidpf)0;
732
733 err = inflateInit2(&stream, -MAX_WBITS);
734 /* windowBits is passed < 0 to tell that there is no zlib header.
735 * Note that in this case inflate *requires* an extra "dummy" byte
736 * after the compressed stream in order to complete decompression and
737 * return Z_STREAM_END.
738 * In unzip, i don't wait absolutely Z_STREAM_END because I known the
739 * size of both compressed and uncompressed data
740 */
741
742 if (err != Z_OK)
743 {
744 *result = STAFString("STAFZipLocalFileHeader::doExtract: ")
745 + "Error init zlib inflate ["
746 + err
747 + "].\n";
748
749 return kZIPGeneralZipError;
750 }
751 }
752
753 // allocate input buffer
754
755 void *inbuf = (void*)malloc(Z_BUFSIZE);
756
757 if(inbuf == NULL)
758 {
759 *result = STAFString("STAFZipLocalFileHeader::doExtract: ")
760 + "Error allocating memory for input buffer ["
761 + Z_BUFSIZE
762 + "].\n";
763 return kZIPNotEnoughMemory;
764 }
765
766 // allocate output buffer
767
768 void *outbuf = (void*)malloc(Z_BUFSIZE);
769
770 if(outbuf == NULL)
771 {
772 *result = STAFString("STAFZipLocalFileHeader::doExtract: ")
773 + "Error allocating memory for output buffer ["
774 + Z_BUFSIZE
775 + "].\n";
776 return kZIPNotEnoughMemory;
777 }
778
779 uLong pos = offset + size - compressedSize;
780 uLong rest_uncompressed, rest_compressed;
781
782 rest_uncompressed = uncompressedSize;
783 rest_compressed = compressedSize;
784
785 uInt uncompressed_bytes;
786 uLong newcrc32 = 0;
787
788 stream.avail_in = (uInt)0;
789
790 STAFTrace::trace(kSTAFTraceServiceResult,
791 STAFString("STAFZipLocalFileHeader::doExtract_CP4.5")
792 + " pos ["
793 + pos
794 + "] stream.avail_in ["
795 + stream.avail_in
796 + "] rest_uncompressed ["
797 + rest_uncompressed
798 + "] rest_compressed ["
799 + rest_compressed
800 + "]");
801
802 // loop to read compressed data from zip file
803
804 while (rest_uncompressed > 0)
805 {
806 // unzip buffer
807
808 stream.next_out = (Bytef*)outbuf;
809 stream.avail_out = (uInt)Z_BUFSIZE;
810
811 STAFTrace::trace(kSTAFTraceServiceResult,
812 STAFString("STAFZipLocalFileHeader::doExtract_CP5")
813 + " stream.avail_out ["
814 + stream.avail_out
815 + "] rest_uncompressed ["
816 + rest_uncompressed
817 + "]");
818
819 if (stream.avail_out > rest_uncompressed)
820 {
821 stream.avail_out = (uInt)rest_uncompressed;
822 }
823
824 uncompressed_bytes = 0;
825
826 STAFTrace::trace(kSTAFTraceServiceResult,
827 STAFString("STAFZipLocalFileHeader::doExtract_CP6")
828 + " stream.avail_out ["
829 + stream.avail_out
830 + "]");
831
832 // loop to unzip compressed data
833
834 while (stream.avail_out > 0)
835 {
836 STAFTrace::trace(kSTAFTraceServiceResult,
837 STAFString("STAFZipLocalFileHeader::doExtract_CP7")
838 + " stream.avail_in ["
839 + stream.avail_in
840 + "] rest_compressed ["
841 + rest_compressed
842 + "]");
843
844 if (stream.avail_in == 0 && rest_compressed != 0)
845 {
846 // set available in
847
848 stream.avail_in = Z_BUFSIZE;
849
850 STAFTrace::trace(kSTAFTraceServiceResult,
851 STAFString("STAFZipLocalFileHeader::doExtract_CP8")
852 + " stream.avail_in ["
853 + stream.avail_in
854 + "] rest_compressed ["
855 + rest_compressed
856 + "]");
857
858 if (stream.avail_in > rest_compressed)
859 {
860 stream.avail_in = (uInt)rest_compressed;
861 }
862
863 // set file position to the next compressed data
864
865 if (util.seek(zf, pos + startPos, SEEK_SET) != 0)
866 {
867 *result = STAFString("STAFZipLocalFileHeader::doExtract: ")
868 + "Error set pos to next compressed data ["
869 + pos + " + " + startPos + "].\n";
870 rc = kZIPGeneralZipError;
871
872 break;
873 }
874
875 // read stream.avail_in bytes of data from file to inbuf
876
877 if (fread(inbuf, stream.avail_in, 1, zf) != 1)
878 {
879 *result = STAFString("STAFZipLocalFileHeader::doExtract: ")
880 + "Error reading file bytes ["
881 + stream.avail_in
882 + "].\n";
883 rc = kSTAFFileReadError;
884
885 break;
886 }
887
888 // prepare file position to next compressed data
889
890 pos += stream.avail_in;
891
892 // reduce rest_compressed data size
893
894 rest_compressed -= stream.avail_in;
895
896 STAFTrace::trace(kSTAFTraceServiceResult,
897 STAFString("STAFZipLocalFileHeader::doExtract_CP11")
898 + " stream.avail_in ["
899 + stream.avail_in
900 + "] rest_compressed ["
901 + rest_compressed
902 + "] pos ["
903 + pos
904 + "]");
905
906 // set zip stream to point to inbuf
907
908 stream.next_in = (Bytef*)inbuf;
909 }
910
911 STAFTrace::trace(kSTAFTraceServiceResult,
912 STAFString("STAFZipLocalFileHeader::doExtract_CP12")
913 + " compressionMethod ["
914 + compressionMethod
915 + "]");
916
917 // if no compression
918 if (compressionMethod == 0)
919 {
920 uLong processed_bytes;
921
922 STAFTrace::trace(kSTAFTraceServiceResult,
923 STAFString("STAFZipLocalFileHeader::doExtract_CP13")
924 + " stream.avail_in ["
925 + stream.avail_in
926 + "] stream.avail_out ["
927 + stream.avail_out
928 + "]");
929
930 if (stream.avail_out < stream.avail_in)
931 {
932 processed_bytes = stream.avail_out;
933 }
934 else
935 {
936 processed_bytes = stream.avail_in;
937 }
938
939 STAFTrace::trace(kSTAFTraceServiceResult,
940 STAFString("STAFZipLocalFileHeader::doExtract_CP14")
941 + " processed_bytes ["
942 + processed_bytes
943 + "]");
944
945 for (int i = 0; i < processed_bytes; i++)
946 {
947 *(stream.next_out + i) = *(stream.next_in + i);
948 }
949
950 newcrc32 = crc32(newcrc32, stream.next_out, processed_bytes);
951
952 stream.avail_in -= processed_bytes;
953 stream.avail_out -= processed_bytes;
954
955 stream.next_out += processed_bytes;
956 stream.next_in += processed_bytes;
957
958 stream.total_out += processed_bytes;
959
960 uncompressed_bytes += processed_bytes;
961
962 STAFTrace::trace(kSTAFTraceServiceResult,
963 STAFString("STAFZipLocalFileHeader::doExtract_CP15")
964 + " stream.avail_in ["
965 + stream.avail_in
966 + " stream.avail_out ["
967 + stream.avail_out
968 + " stream.total_out ["
969 + stream.total_out
970 + " uncompressed_bytes ["
971 + uncompressed_bytes
972 + " newcrc32 ["
973 + newcrc32
974 + "]");
975 }
976 else
977 {
978 // start deflating the file
979
980 uLong total_out_before, processed_bytes;
981 total_out_before = stream.total_out;
982
983 const Bytef *bufBefore;
984 bufBefore = stream.next_out;
985
986 STAFTrace::trace(kSTAFTraceServiceResult,
987 STAFString("STAFZipLocalFileHeader::doExtract_CP16")
988 + " total_out_before ["
989 + total_out_before
990 + "]");
991
992 // unzip
993
994 err = inflate(&stream, Z_SYNC_FLUSH);
995
996 processed_bytes = stream.total_out - total_out_before;
997
998 // calculate crc
999
1000 newcrc32 = crc32(newcrc32, bufBefore, (uInt)(processed_bytes));
1001
1002 // calculate uncompressed bytes
1003
1004 uncompressed_bytes += (uInt)processed_bytes;
1005
1006 STAFTrace::trace(kSTAFTraceServiceResult,
1007 STAFString("STAFZipLocalFileHeader::doExtract_CP17")
1008 + " err ["
1009 + err
1010 + "] stream.total_out ["
1011 + stream.total_out
1012 + "] processed_bytes ["
1013 + processed_bytes
1014 + "] newcrc32 ["
1015 + newcrc32
1016 + "] uncompressed_bytes ["
1017 + uncompressed_bytes
1018 + "]");
1019
1020 if (err != Z_OK)
1021 {
1022 *result = STAFString("STAFZipLocalFileHeader::doExtract: ")
1023 + "Error inflate file, err ["
1024 + err
1025 + "].\n";
1026
1027 break;
1028 }
1029 } // compressionMethod == 0?
1030 } // while stream.avail_out > 0
1031
1032 if (rc != kSTAFOk || (err != Z_OK && err != Z_STREAM_END))
1033 {
1034 if ((*result).length() == 0)
1035 {
1036 *result = STAFString("STAFZipLocalFileHeader::doExtract: ")
1037 + "Error deflating file, err ["
1038 + err
1039 + "].\n";
1040 }
1041
1042 rc = kZIPGeneralZipError;
1043
1044 break;
1045 }
1046
1047 STAFTrace::trace(kSTAFTraceServiceResult,
1048 STAFString("STAFZipLocalFileHeader::doExtract_CP20")
1049 + " uncompressed_bytes ["
1050 + uncompressed_bytes
1051 + "]");
1052
1053 // write the unzipped buffer to file
1054
1055 if (uncompressed_bytes > 0)
1056 {
1057 if (fwrite(outbuf, uncompressed_bytes, 1, outfile) != 1)
1058 {
1059 *result = STAFString("STAFZipLocalFileHeader::doExtract: ")
1060 + "Error writing file bytes ["
1061 + uncompressed_bytes
1062 + "].\n";
1063
1064 rc = kSTAFFileWriteError;
1065
1066 break;
1067 }
1068
1069 rest_uncompressed -= uncompressed_bytes;
1070
1071 STAFTrace::trace(kSTAFTraceServiceResult,
1072 STAFString("STAFZipLocalFileHeader::doExtract_CP22")
1073 + " rest_uncompressed ["
1074 + rest_uncompressed
1075 + "]");
1076 }
1077 } // loop to read compressed data from zip file
1078
1079 if (compressionMethod != 0)
1080 {
1081 STAFTrace::trace(kSTAFTraceServiceResult,
1082 STAFString("STAFZipLocalFileHeader::doExtract_CP23")
1083 + " compressionMethod ["
1084 + compressionMethod
1085 + "]");
1086
1087 // inflate end
1088
1089 inflateEnd(&stream);
1090 }
1091
1092 // compare crc
1093
1094 if (rc == kSTAFOk)
1095 {
1096 if (newcrc32 != crc)
1097 {
1098 *result = STAFString("STAFZipLocalFileHeader::doExtract: ")
1099 + "Bad CRC new crc ["
1100 + newcrc32
1101 + "] old crc ["
1102 + crc
1103 + "].\n";
1104 rc = kZIPBadCRC;
1105 }
1106 }
1107
1108 free(inbuf);
1109 free(outbuf);
1110
1111 return rc;
1112 }
1113
1114
1115 // destructor
1116
~STAFZipLocalFileHeader()1117 STAFZipLocalFileHeader::~STAFZipLocalFileHeader()
1118 {
1119 if (fullFileName != NULL)
1120 {
1121 free(fullFileName);
1122 }
1123
1124 if (extraField != NULL)
1125 {
1126 free(extraField);
1127 }
1128 }
1129
1130
1131 // extract zip archive to output dir
1132
extract(FILE * zf,uLong startPos,const char * outputdir,STAFString * result)1133 STAFRC_t STAFZipLocalFileHeader::extract(FILE *zf, uLong startPos,
1134 const char *outputdir,
1135 STAFString *result)
1136 {
1137 STAFRC_t rc;
1138 STAFZipUtil util = STAFZipUtil();
1139
1140 STAFTrace::trace(kSTAFTraceServiceResult,
1141 STAFString("STAFZipLocalFileHeader::extract_CP1")
1142 + " outputdir ["
1143 + outputdir
1144 + "]");
1145
1146 fullFileName = (char*)calloc(strlen(outputdir) + fileNameLength + 1, 1);
1147
1148 if (fullFileName == NULL)
1149 {
1150 *result = STAFString("STAFZipLocalFileHeader::extract: ")
1151 + "Error allocating memory for fullFileName ["
1152 + (strlen(outputdir) + fileNameLength + 1)
1153 + "].\n";
1154 return kZIPNotEnoughMemory;
1155 }
1156
1157 strcpy(fullFileName, outputdir);
1158 strcat(fullFileName, fileName);
1159
1160 fileName = fullFileName + strlen(outputdir);
1161
1162 STAFTrace::trace(kSTAFTraceServiceResult,
1163 STAFString("STAFZipLocalFileHeader::extract_CP3")
1164 + " fileName ["
1165 + fileName
1166 + "] fullFileName ["
1167 + fullFileName
1168 + "]");
1169
1170 if (*(fileName + strlen(fileName) - 1) == '\\'
1171 || *(fileName + strlen(fileName) - 1) == '/')
1172 {
1173 STAFTrace::trace(kSTAFTraceServiceResult,
1174 STAFString("STAFZipLocalFileHeader::extract_CP4"));
1175
1176 // create dir
1177
1178 if ((rc = util.makeDir(fullFileName)) != kSTAFOk)
1179 {
1180 *result = STAFString("STAFZipLocalFileHeader::extract: ")
1181 + "Error making dir ["
1182 + fullFileName
1183 + "].\n";
1184 }
1185
1186 return rc;
1187 }
1188
1189 FILE *outfile;
1190
1191 // make sure the target directories exist before extracting files
1192
1193 if ((outfile = fopen(fullFileName, "wb")) == NULL)
1194 {
1195 // finding fileName without path
1196
1197 char *p, *filename_withoutpath;
1198 p = filename_withoutpath = fullFileName;
1199
1200 while ((*p) != '\0')
1201 {
1202 if (((*p) == '/') || ((*p) == '\\'))
1203 {
1204 filename_withoutpath = p + 1;
1205 }
1206
1207 p++;
1208 }
1209
1210 STAFTrace::trace(kSTAFTraceServiceResult,
1211 STAFString("STAFZipLocalFileHeader::extract_CP5")
1212 + " filename_withoutpath ["
1213 + filename_withoutpath
1214 + "]");
1215
1216 // store the char before the file name without path
1217
1218 char c = *(filename_withoutpath - 1);
1219
1220 // to form a string which contains only the directory
1221
1222 *(filename_withoutpath - 1) = '\0';
1223
1224 STAFTrace::trace(kSTAFTraceServiceResult,
1225 STAFString("STAFZipLocalFileHeader::extract_CP6")
1226 + " fullFileName ["
1227 + fullFileName
1228 + "]");
1229
1230 // make the directory
1231
1232 if ((rc = util.makeDir(fullFileName)) != kSTAFOk)
1233 {
1234 *result = STAFString("STAFZipLocalFileHeader::extract: ")
1235 + "Error making directory: ["
1236 + fullFileName
1237 + "].\n";
1238 return rc;
1239 }
1240
1241 *(filename_withoutpath - 1) = c;
1242
1243 if ((outfile = fopen(fullFileName, "wb")) == NULL)
1244 {
1245 *result = STAFString("STAFZipLocalFileHeader::extract: ")
1246 + "Error creating file ["
1247 + fullFileName
1248 + "].\n";
1249
1250 return kZIPGeneralZipError;
1251 }
1252 }
1253
1254 rc = doExtract(zf, startPos, outfile, result);
1255
1256 STAFTrace::trace(kSTAFTraceServiceResult,
1257 STAFString("STAFZipLocalFileHeader::extract_CP8")
1258 + " rc ["
1259 + rc
1260 + "]");
1261
1262 fclose(outfile);
1263
1264 if (rc == kSTAFOk)
1265 {
1266 tm filedate;
1267
1268 util.fileTime(lastModifiedTimeDate, &filedate);
1269 util.changeFileDate(fullFileName, lastModifiedTimeDate, filedate);
1270 }
1271
1272 return rc;
1273 }
1274
1275
1276
1277
1278
1279