Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "signtool.h"
6 #include "zip.h"
7 #include "zlib.h"
8 #include "prmem.h"
10 static void inttox (int in, char *out);
11 static void longtox (long in, char *out);
13 /****************************************************************
14 *
15 * J z i p O p e n
16 *
17 * Opens a new ZIP file and creates a new ZIPfile structure to
18 * control the process of installing files into a zip.
19 */
20 ZIPfile*
21 JzipOpen(char *filename, char *comment)
22 {
23 ZIPfile * zipfile;
24 PRExplodedTime prtime;
26 zipfile = PORT_ZAlloc(sizeof(ZIPfile));
27 if (!zipfile)
28 out_of_memory();
30 /* Construct time and date */
31 PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &prtime);
32 zipfile->date = ((prtime.tm_year - 1980) << 9) |
33 ((prtime.tm_month + 1) << 5) |
34 prtime.tm_mday;
35 zipfile->time = (prtime.tm_hour << 11) |
36 (prtime.tm_min << 5) |
37 (prtime.tm_sec & 0x3f);
39 zipfile->fp = NULL;
40 if (filename &&
41 (zipfile->fp = PR_Open(filename,
42 PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0777)) == NULL) {
43 char *nsprErr;
44 if (PR_GetErrorTextLength()) {
45 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
46 PR_GetErrorText(nsprErr);
47 } else {
48 nsprErr = NULL;
49 }
50 PR_fprintf(errorFD, "%s: can't open output jar, %s.%s\n",
51 PROGRAM_NAME,
52 filename, nsprErr ? nsprErr : "");
53 if (nsprErr)
54 PR_Free(nsprErr);
55 errorCount++;
56 exit (ERRX);
57 }
59 zipfile->list = NULL;
60 if (filename) {
61 zipfile->filename = PORT_ZAlloc(strlen(filename) + 1);
62 if (!zipfile->filename)
63 out_of_memory();
64 PORT_Strcpy(zipfile->filename, filename);
65 }
66 if (comment) {
67 zipfile->comment = PORT_ZAlloc(strlen(comment) + 1);
68 if (!zipfile->comment)
69 out_of_memory();
70 PORT_Strcpy(zipfile->comment, comment);
71 }
73 return zipfile;
74 }
77 static
78 void*
79 my_alloc_func(void*opaque, uInt items, uInt size)
80 {
81 return PORT_Alloc(items * size);
82 }
85 static
86 void
87 my_free_func(void*opaque, void*address)
88 {
89 PORT_Free(address);
90 }
93 static
94 void
95 handle_zerror(int err, char *msg)
96 {
97 if (!msg) {
98 msg = "";
99 }
101 errorCount++; /* unless Z_OK...see below */
103 switch (err) {
104 case Z_OK:
105 PR_fprintf(errorFD, "No error: %s\n", msg);
106 errorCount--; /* this was incremented above */
107 break;
108 case Z_MEM_ERROR:
109 PR_fprintf(errorFD, "Deflation ran out of memory: %s\n", msg);
110 break;
111 case Z_STREAM_ERROR:
112 PR_fprintf(errorFD, "Invalid compression level: %s\n", msg);
113 break;
114 case Z_VERSION_ERROR:
115 PR_fprintf(errorFD, "Incompatible compression library version: %s\n",
116 msg);
117 break;
118 case Z_DATA_ERROR:
119 PR_fprintf(errorFD, "Compression data error: %s\n", msg);
120 break;
121 default:
122 PR_fprintf(errorFD, "Unknown error in compression library: %s\n", msg);
123 break;
124 }
125 }
130 /****************************************************************
131 *
132 * J z i p A d d
133 *
134 * Adds a new file into a ZIP file. The ZIP file must have already
135 * been opened with JzipOpen.
136 */
137 int
138 JzipAdd(char *fullname, char *filename, ZIPfile *zipfile, int compression_level)
139 {
140 ZIPentry * entry;
141 PRFileDesc * readfp;
142 PRFileDesc * zipfp;
143 unsigned long crc;
144 unsigned long local_size_pos;
145 int num;
146 int err;
147 int deflate_percent;
148 z_stream zstream;
149 Bytef inbuf[BUFSIZ];
150 Bytef outbuf[BUFSIZ];
153 if ( !fullname || !filename || !zipfile) {
154 return - 1;
155 }
157 zipfp = zipfile->fp;
158 if (!zipfp)
159 return - 1;
162 if ( (readfp = PR_Open(fullname, PR_RDONLY, 0777)) == NULL) {
163 char *nsprErr;
164 if (PR_GetErrorTextLength()) {
165 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
166 PR_GetErrorText(nsprErr);
167 } else {
168 nsprErr = NULL;
169 }
170 PR_fprintf(errorFD, "%s: %s\n", fullname, nsprErr ? nsprErr :
171 "");
172 errorCount++;
173 if (nsprErr)
174 PR_Free(nsprErr);
175 exit(ERRX);
176 }
178 /*
179 * Make sure the input file is not the output file.
180 * Add a few bytes to the end of the JAR file and see if the input file
181 * twitches
182 */
183 {
184 PRInt32 endOfJar;
185 PRInt32 inputSize;
186 PRBool isSame;
188 inputSize = PR_Available(readfp);
190 endOfJar = PR_Seek(zipfp, 0L, PR_SEEK_CUR);
192 if (PR_Write(zipfp, "abcde", 5) < 5) {
193 char *nsprErr;
195 if (PR_GetErrorTextLength()) {
196 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
197 PR_GetErrorText(nsprErr);
198 } else {
199 nsprErr = NULL;
200 }
201 PR_fprintf(errorFD, "Writing to zip file: %s\n",
202 nsprErr ? nsprErr : "");
203 if (nsprErr)
204 PR_Free(nsprErr);
205 errorCount++;
206 exit(ERRX);
207 }
209 isSame = (PR_Available(readfp) != inputSize);
211 PR_Seek(zipfp, endOfJar, PR_SEEK_SET);
213 if (isSame) {
214 /* It's the same file! Forget it! */
215 PR_Close(readfp);
216 return 0;
217 }
218 }
220 if (verbosity >= 0) {
221 PR_fprintf(outputFD, "adding %s to %s...", fullname, zipfile->filename);
222 }
224 entry = PORT_ZAlloc(sizeof(ZIPentry));
225 if (!entry)
226 out_of_memory();
228 entry->filename = PORT_Strdup(filename);
229 entry->comment = NULL;
231 /* Set up local file header */
232 longtox(LSIG, entry->local.signature);
233 inttox(strlen(filename), entry->local.filename_len);
234 inttox(zipfile->time, entry->local.time);
235 inttox(zipfile->date, entry->local.date);
236 inttox(Z_DEFLATED, entry->local.method);
238 /* Set up central directory entry */
239 longtox(CSIG, entry->central.signature);
240 inttox(strlen(filename), entry->central.filename_len);
241 if (entry->comment) {
242 inttox(strlen(entry->comment), entry->central.commentfield_len);
243 }
244 longtox(PR_Seek(zipfile->fp, 0, PR_SEEK_CUR),
245 entry->central.localhdr_offset);
246 inttox(zipfile->time, entry->central.time);
247 inttox(zipfile->date, entry->central.date);
248 inttox(Z_DEFLATED, entry->central.method);
250 /* Compute crc. Too bad we have to process the whole file to do this*/
251 crc = crc32(0L, NULL, 0);
252 while ( (num = PR_Read(readfp, inbuf, BUFSIZ)) > 0) {
253 crc = crc32(crc, inbuf, num);
254 }
255 PR_Seek(readfp, 0L, PR_SEEK_SET);
257 /* Store CRC */
258 longtox(crc, entry->local.crc32);
259 longtox(crc, entry->central.crc32);
261 /* Stick this entry onto the end of the list */
262 entry->next = NULL;
263 if ( zipfile->list == NULL ) {
264 /* First entry */
265 zipfile->list = entry;
266 } else {
267 ZIPentry * pe;
269 pe = zipfile->list;
270 while (pe->next != NULL) {
271 pe = pe->next;
272 }
273 pe->next = entry;
274 }
276 /*
277 * Start writing stuff out
278 */
280 local_size_pos = PR_Seek(zipfp, 0, PR_SEEK_CUR) + 18;
281 /* File header */
282 if (PR_Write(zipfp, &entry->local, sizeof(struct ZipLocal ))
283 < sizeof(struct ZipLocal )) {
284 char *nsprErr;
285 if (PR_GetErrorTextLength()) {
286 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
287 PR_GetErrorText(nsprErr);
288 } else {
289 nsprErr = NULL;
290 }
291 PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr :
292 "");
293 if (nsprErr)
294 PR_Free(nsprErr);
295 errorCount++;
296 exit(ERRX);
297 }
299 /* File Name */
300 if ( PR_Write(zipfp, filename, strlen(filename)) < strlen(filename)) {
301 char *nsprErr;
302 if (PR_GetErrorTextLength()) {
303 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
304 PR_GetErrorText(nsprErr);
305 } else {
306 nsprErr = NULL;
307 }
308 PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr :
309 "");
310 if (nsprErr)
311 PR_Free(nsprErr);
312 errorCount++;
313 exit(ERRX);
314 }
316 /*
317 * File data
318 */
319 /* Initialize zstream */
320 zstream.zalloc = my_alloc_func;
321 zstream.zfree = my_free_func;
322 zstream.opaque = NULL;
323 zstream.next_in = inbuf;
324 zstream.avail_in = BUFSIZ;
325 zstream.next_out = outbuf;
326 zstream.avail_out = BUFSIZ;
327 /* Setting the windowBits to -MAX_WBITS is an undocumented feature of
328 * zlib (see deflate.c in zlib). It is the same thing that Java does
329 * when you specify the nowrap option for deflation in java.util.zip.
330 * It causes zlib to leave out its headers and footers, which don't
331 * work in PKZIP files.
332 */
333 err = deflateInit2(&zstream, compression_level, Z_DEFLATED,
334 -MAX_WBITS, 8 /*default*/, Z_DEFAULT_STRATEGY);
335 if (err != Z_OK) {
336 handle_zerror(err, zstream.msg);
337 exit(ERRX);
338 }
340 while ( (zstream.avail_in = PR_Read(readfp, inbuf, BUFSIZ)) > 0) {
341 zstream.next_in = inbuf;
342 /* Process this chunk of data */
343 while (zstream.avail_in > 0) {
344 err = deflate(&zstream, Z_NO_FLUSH);
345 if (err != Z_OK) {
346 handle_zerror(err, zstream.msg);
347 exit(ERRX);
348 }
349 if (zstream.avail_out <= 0) {
350 if ( PR_Write(zipfp, outbuf, BUFSIZ) < BUFSIZ) {
351 char *nsprErr;
352 if (PR_GetErrorTextLength()) {
353 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
354 PR_GetErrorText(nsprErr);
355 } else {
356 nsprErr = NULL;
357 }
358 PR_fprintf(errorFD, "Writing zip data: %s\n",
359 nsprErr ? nsprErr : "");
360 if (nsprErr)
361 PR_Free(nsprErr);
362 errorCount++;
363 exit(ERRX);
364 }
365 zstream.next_out = outbuf;
366 zstream.avail_out = BUFSIZ;
367 }
368 }
369 }
371 /* Now flush everything */
372 while (1) {
373 err = deflate(&zstream, Z_FINISH);
374 if (err == Z_STREAM_END) {
375 break;
376 } else if (err == Z_OK) {
377 /* output buffer full, repeat */
378 } else {
379 handle_zerror(err, zstream.msg);
380 exit(ERRX);
381 }
382 if ( PR_Write(zipfp, outbuf, BUFSIZ) < BUFSIZ) {
383 char *nsprErr;
384 if (PR_GetErrorTextLength()) {
385 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
386 PR_GetErrorText(nsprErr);
387 } else {
388 nsprErr = NULL;
389 }
390 PR_fprintf(errorFD, "Writing zip data: %s\n",
391 nsprErr ? nsprErr : "");
392 if (nsprErr)
393 PR_Free(nsprErr);
394 errorCount++;
395 exit(ERRX);
396 }
397 zstream.avail_out = BUFSIZ;
398 zstream.next_out = outbuf;
399 }
401 /* If there's any output left, write it out. */
402 if (zstream.next_out != outbuf) {
403 if ( PR_Write(zipfp, outbuf, zstream.next_out - outbuf) <
404 zstream.next_out - outbuf) {
405 char *nsprErr;
406 if (PR_GetErrorTextLength()) {
407 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
408 PR_GetErrorText(nsprErr);
409 } else {
410 nsprErr = NULL;
411 }
412 PR_fprintf(errorFD, "Writing zip data: %s\n",
413 nsprErr ? nsprErr : "");
414 if (nsprErr)
415 PR_Free(nsprErr);
416 errorCount++;
417 exit(ERRX);
418 }
419 zstream.avail_out = BUFSIZ;
420 zstream.next_out = outbuf;
421 }
423 /* Now that we know the compressed size, write this to the headers */
424 longtox(zstream.total_in, entry->local.orglen);
425 longtox(zstream.total_out, entry->local.size);
426 if (PR_Seek(zipfp, local_size_pos, PR_SEEK_SET) == -1) {
427 char *nsprErr;
428 if (PR_GetErrorTextLength()) {
429 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
430 PR_GetErrorText(nsprErr);
431 } else {
432 nsprErr = NULL;
433 }
434 PR_fprintf(errorFD, "Accessing zip file: %s\n", nsprErr ? nsprErr : "");
435 if (nsprErr)
436 PR_Free(nsprErr);
437 errorCount++;
438 exit(ERRX);
439 }
440 if ( PR_Write(zipfp, entry->local.size, 8) != 8) {
441 char *nsprErr;
442 if (PR_GetErrorTextLength()) {
443 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
444 PR_GetErrorText(nsprErr);
445 } else {
446 nsprErr = NULL;
447 }
448 PR_fprintf(errorFD, "Writing zip data: %s\n", nsprErr ? nsprErr : "");
449 if (nsprErr)
450 PR_Free(nsprErr);
451 errorCount++;
452 exit(ERRX);
453 }
454 if (PR_Seek(zipfp, 0L, PR_SEEK_END) == -1) {
455 char *nsprErr;
456 if (PR_GetErrorTextLength()) {
457 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
458 PR_GetErrorText(nsprErr);
459 } else {
460 nsprErr = NULL;
461 }
462 PR_fprintf(errorFD, "Accessing zip file: %s\n",
463 nsprErr ? nsprErr : "");
464 if (nsprErr)
465 PR_Free(nsprErr);
466 errorCount++;
467 exit(ERRX);
468 }
469 longtox(zstream.total_in, entry->central.orglen);
470 longtox(zstream.total_out, entry->central.size);
472 /* Close out the deflation operation */
473 err = deflateEnd(&zstream);
474 if (err != Z_OK) {
475 handle_zerror(err, zstream.msg);
476 exit(ERRX);
477 }
479 PR_Close(readfp);
481 if ((zstream.total_in > zstream.total_out) && (zstream.total_in > 0)) {
482 deflate_percent = (int)
483 ((zstream.total_in - zstream.total_out) *100 / zstream.total_in);
484 } else {
485 deflate_percent = 0;
486 }
487 if (verbosity >= 0) {
488 PR_fprintf(outputFD, "(deflated %d%%)\n", deflate_percent);
489 }
491 return 0;
492 }
495 /********************************************************************
496 * J z i p C l o s e
497 *
498 * Finishes the ZipFile. ALSO DELETES THE ZIPFILE STRUCTURE PASSED IN!!
499 */
500 int
501 JzipClose(ZIPfile *zipfile)
502 {
503 ZIPentry * pe, *dead;
504 PRFileDesc * zipfp;
505 struct ZipEnd zipend;
506 unsigned int entrycount = 0;
508 if (!zipfile) {
509 return - 1;
510 }
512 if (!zipfile->filename) {
513 /* bogus */
514 return 0;
515 }
517 zipfp = zipfile->fp;
518 zipfile->central_start = PR_Seek(zipfp, 0L, PR_SEEK_CUR);
520 /* Write out all the central directories */
521 pe = zipfile->list;
522 while (pe) {
523 entrycount++;
525 /* Write central directory info */
526 if ( PR_Write(zipfp, &pe->central, sizeof(struct ZipCentral ))
527 < sizeof(struct ZipCentral )) {
528 char *nsprErr;
529 if (PR_GetErrorTextLength()) {
530 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
531 PR_GetErrorText(nsprErr);
532 } else {
533 nsprErr = NULL;
534 }
535 PR_fprintf(errorFD, "Writing zip data: %s\n",
536 nsprErr ? nsprErr : "");
537 if (nsprErr)
538 PR_Free(nsprErr);
539 errorCount++;
540 exit(ERRX);
541 }
543 /* Write filename */
544 if ( PR_Write(zipfp, pe->filename, strlen(pe->filename))
545 < strlen(pe->filename)) {
546 char *nsprErr;
547 if (PR_GetErrorTextLength()) {
548 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
549 PR_GetErrorText(nsprErr);
550 } else {
551 nsprErr = NULL;
552 }
553 PR_fprintf(errorFD, "Writing zip data: %s\n",
554 nsprErr ? nsprErr : "");
555 if (nsprErr)
556 PR_Free(nsprErr);
557 errorCount++;
558 exit(ERRX);
559 }
561 /* Write file comment */
562 if (pe->comment) {
563 if ( PR_Write(zipfp, pe->comment, strlen(pe->comment))
564 < strlen(pe->comment)) {
565 char *nsprErr;
566 if (PR_GetErrorTextLength()) {
567 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
568 PR_GetErrorText(nsprErr);
569 } else {
570 nsprErr = NULL;
571 }
572 PR_fprintf(errorFD, "Writing zip data: %s\n",
573 nsprErr ? nsprErr : "");
574 if (nsprErr)
575 PR_Free(nsprErr);
576 errorCount++;
577 exit(ERRX);
578 }
579 }
581 /* Delete the structure */
582 dead = pe;
583 pe = pe->next;
584 if (dead->filename) {
585 PORT_Free(dead->filename);
586 }
587 if (dead->comment) {
588 PORT_Free(dead->comment);
589 }
590 PORT_Free(dead);
591 }
592 zipfile->central_end = PR_Seek(zipfile->fp, 0L, PR_SEEK_CUR);
594 /* Create the ZipEnd structure */
595 PORT_Memset(&zipend, 0, sizeof(zipend));
596 longtox(ESIG, zipend.signature);
597 inttox(entrycount, zipend.total_entries_disk);
598 inttox(entrycount, zipend.total_entries_archive);
599 longtox(zipfile->central_end - zipfile->central_start,
600 zipend.central_dir_size);
601 longtox(zipfile->central_start, zipend.offset_central_dir);
602 if (zipfile->comment) {
603 inttox(strlen(zipfile->comment), zipend.commentfield_len);
604 }
606 /* Write out ZipEnd xtructure */
607 if ( PR_Write(zipfp, &zipend, sizeof(zipend)) < sizeof(zipend)) {
608 char *nsprErr;
609 if (PR_GetErrorTextLength()) {
610 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
611 PR_GetErrorText(nsprErr);
612 } else {
613 nsprErr = NULL;
614 }
615 PR_fprintf(errorFD, "Writing zip data: %s\n",
616 nsprErr ? nsprErr : "");
617 if (nsprErr)
618 PR_Free(nsprErr);
619 errorCount++;
620 exit(ERRX);
621 }
623 /* Write out Zipfile comment */
624 if (zipfile->comment) {
625 if ( PR_Write(zipfp, zipfile->comment, strlen(zipfile->comment))
626 < strlen(zipfile->comment)) {
627 char *nsprErr;
628 if (PR_GetErrorTextLength()) {
629 nsprErr = PR_Malloc(PR_GetErrorTextLength() + 1);
630 PR_GetErrorText(nsprErr);
631 } else {
632 nsprErr = NULL;
633 }
634 PR_fprintf(errorFD, "Writing zip data: %s\n",
635 nsprErr ? nsprErr : "");
636 if (nsprErr)
637 PR_Free(nsprErr);
638 errorCount++;
639 exit(ERRX);
640 }
641 }
643 PR_Close(zipfp);
645 /* Free the memory of the zipfile structure */
646 if (zipfile->filename) {
647 PORT_Free(zipfile->filename);
648 }
649 if (zipfile->comment) {
650 PORT_Free(zipfile->comment);
651 }
652 PORT_Free(zipfile);
654 return 0;
655 }
658 /**********************************************
659 * i n t t o x
660 *
661 * Converts a two byte ugly endianed integer
662 * to our platform's integer.
663 *
664 */
666 static void inttox (int in, char *out)
667 {
668 out [0] = (in & 0xFF);
669 out [1] = (in & 0xFF00) >> 8;
670 }
673 /*********************************************
674 * l o n g t o x
675 *
676 * Converts a four byte ugly endianed integer
677 * to our platform's integer.
678 *
679 */
681 static void longtox (long in, char *out)
682 {
683 out [0] = (in & 0xFF);
684 out [1] = (in & 0xFF00) >> 8;
685 out [2] = (in & 0xFF0000) >> 16;
686 out [3] = (in & 0xFF000000) >> 24;
687 }