57
55
#include "sechash.h" /* for HASH_GetHashObject() */
57
PR_STATIC_ASSERT(46 == sizeof(struct ZipCentral));
58
PR_STATIC_ASSERT(30 == sizeof(struct ZipLocal));
59
PR_STATIC_ASSERT(22 == sizeof(struct ZipEnd));
60
PR_STATIC_ASSERT(512 == sizeof(union TarEntry));
61
static int jar_guess_jar (char *filename, JAR_FILE fp);
63
static int jar_inflate_memory
64
(unsigned int method, long *length, long expected_out_len, char ZHUGEP **data);
66
static int jar_physical_extraction
67
(JAR_FILE fp, char *outpath, long offset, long length);
69
static int jar_physical_inflate
70
(JAR_FILE fp, char *outpath, long offset,
71
long length, unsigned int method);
73
static int jar_verify_extract
74
(JAR *jar, char *path, char *physical_path);
76
static JAR_Physical *jar_get_physical (JAR *jar, char *pathname);
78
static int jar_extract_manifests (JAR *jar, jarArch format, JAR_FILE fp);
80
static int jar_extract_mf (JAR *jar, jarArch format, JAR_FILE fp, char *ext);
64
jar_guess_jar(const char *filename, JAR_FILE fp);
67
jar_inflate_memory(unsigned int method, long *length, long expected_out_len,
71
jar_physical_extraction(JAR_FILE fp, char *outpath, long offset, long length);
74
jar_physical_inflate(JAR_FILE fp, char *outpath, long offset, long length,
78
jar_verify_extract(JAR *jar, char *path, char *physical_path);
81
jar_get_physical(JAR *jar, char *pathname);
84
jar_extract_manifests(JAR *jar, jarArch format, JAR_FILE fp);
87
jar_extract_mf(JAR *jar, jarArch format, JAR_FILE fp, char *ext);
85
static int jar_gen_index (JAR *jar, jarArch format, JAR_FILE fp);
87
static int jar_listtar (JAR *jar, JAR_FILE fp);
89
static int jar_listzip (JAR *jar, JAR_FILE fp);
92
jar_gen_index(JAR *jar, jarArch format, JAR_FILE fp);
95
jar_listtar(JAR *jar, JAR_FILE fp);
98
jar_listzip(JAR *jar, JAR_FILE fp);
94
static int dosdate (char *date, char *s);
96
static int dostime (char *time, char *s);
98
static unsigned int xtoint (unsigned char *ii);
100
static unsigned long xtolong (unsigned char *ll);
102
static long atoo (char *s);
103
dosdate(char *date, const char *s);
106
dostime(char *time, const char *s);
108
#ifdef NSS_X86_OR_X64
109
#define x86ShortToUint32(ii) ((const PRUint32)*((const PRUint16 *)(ii)))
110
#define x86LongToUint32(ii) (*(const PRUint32 *)(ii))
113
x86ShortToUint32(const void *ii);
116
x86LongToUint32(const void *ll);
120
octalToLong(const char *s);
105
123
* J A R _ p a s s _ a r c h i v e
199
208
* Optimization: keep a file descriptor open
200
209
* inside the JAR structure, so we don't have to
201
* open the file 25 times to run java.
210
* open the file 25 times to run java.
205
int JAR_verified_extract
206
(JAR *jar, char *path, char *outpath)
210
status = JAR_extract (jar, path, outpath);
213
return jar_verify_extract (jar, path, outpath);
215
JAR_verified_extract(JAR *jar, char *path, char *outpath)
217
int status = JAR_extract (jar, path, outpath);
220
return jar_verify_extract(jar, path, outpath);
219
(JAR *jar, char *path, char *outpath)
225
if (jar->fp == NULL && jar->filename)
227
jar->fp = (FILE*)JAR_FOPEN (jar->filename, "rb");
236
phy = jar_get_physical (jar, path);
240
if (phy->compression != 0 && phy->compression != 8)
242
/* unsupported compression method */
243
result = JAR_ERR_CORRUPT;
246
if (phy->compression == 0)
248
result = jar_physical_extraction
249
((PRFileDesc*)jar->fp, outpath, phy->offset, phy->length);
253
result = jar_physical_inflate
254
((PRFileDesc*)jar->fp, outpath, phy->offset, phy->length,
255
(unsigned int) phy->compression);
225
JAR_extract(JAR *jar, char *path, char *outpath)
230
if (jar->fp == NULL && jar->filename) {
231
jar->fp = (FILE*)JAR_FOPEN (jar->filename, "rb");
233
if (jar->fp == NULL) {
238
phy = jar_get_physical (jar, path);
240
if (phy->compression != 0 && phy->compression != 8) {
241
/* unsupported compression method */
242
result = JAR_ERR_CORRUPT;
244
if (phy->compression == 0) {
245
result = jar_physical_extraction
246
((PRFileDesc*)jar->fp, outpath, phy->offset, phy->length);
248
result = jar_physical_inflate((PRFileDesc*)jar->fp, outpath,
249
phy->offset, phy->length,
250
(unsigned int) phy->compression);
258
253
#if defined(XP_UNIX) || defined(XP_BEOS)
260
chmod (outpath, 0400 | (mode_t) phy->mode);
255
chmod (outpath, 0400 | (mode_t) phy->mode);
265
/* pathname not found in archive */
266
result = JAR_ERR_PNF;
258
/* pathname not found in archive */
259
result = JAR_ERR_PNF;
273
265
* p h y s i c a l _ e x t r a c t i o n
275
267
* This needs to be done in chunks of say 32k, instead of
339
315
* result to "outpath". Chunk based.
343
318
/* input and output chunks differ, assume 4x compression */
345
320
#define ICHUNK 8192
346
321
#define OCHUNK 32768
348
static int jar_physical_inflate
349
(JAR_FILE fp, char *outpath, long offset,
350
long length, unsigned int method)
357
char *inbuf, *outbuf;
361
unsigned long prev_total, ochunk, tin;
363
/* Raw inflate in zlib 1.1.4 needs an extra dummy byte at the end */
364
if ((inbuf = (char *) PORT_ZAlloc (ICHUNK + 1)) == NULL)
365
return JAR_ERR_MEMORY;
367
if ((outbuf = (char *) PORT_ZAlloc (OCHUNK)) == NULL)
370
return JAR_ERR_MEMORY;
373
PORT_Memset (&zs, 0, sizeof (zs));
374
status = inflateInit2 (&zs, -MAX_WBITS);
324
jar_physical_inflate(JAR_FILE fp, char *outpath, long offset, long length,
327
char *inbuf, *outbuf;
332
/* Raw inflate in zlib 1.1.4 needs an extra dummy byte at the end */
333
if ((inbuf = (char *)PORT_ZAlloc(ICHUNK + 1)) == NULL)
334
return JAR_ERR_MEMORY;
336
if ((outbuf = (char *)PORT_ZAlloc(OCHUNK)) == NULL) {
338
return JAR_ERR_MEMORY;
341
PORT_Memset (&zs, 0, sizeof (zs));
342
status = inflateInit2 (&zs, -MAX_WBITS);
343
if (status != Z_OK) {
346
return JAR_ERR_GENERAL;
349
if ((out = JAR_FOPEN (outpath, "wb")) != NULL) {
352
JAR_FSEEK (fp, offset, (PRSeekWhence)0);
353
while (at < length) {
354
long chunk = (at + ICHUNK <= length) ? ICHUNK : length - at;
357
if (JAR_FREAD (fp, inbuf, chunk) != chunk) {
358
/* incomplete read */
362
return JAR_ERR_CORRUPT;
366
/* add an extra dummy byte at the end */
367
inbuf[chunk++] = 0xDD;
369
zs.next_in = (Bytef *) inbuf;
371
zs.avail_out = OCHUNK;
373
while ((zs.total_in - tin < chunk) || (zs.avail_out == 0)) {
374
unsigned long prev_total = zs.total_out;
375
unsigned long ochunk;
377
zs.next_out = (Bytef *) outbuf;
378
zs.avail_out = OCHUNK;
379
status = inflate (&zs, Z_NO_FLUSH);
380
if (status != Z_OK && status != Z_STREAM_END) {
381
/* error during decompression */
385
return JAR_ERR_CORRUPT;
387
ochunk = zs.total_out - prev_total;
388
if (JAR_FWRITE (out, outbuf, ochunk) < ochunk) {
389
/* most likely a disk full error */
390
status = JAR_ERR_DISK;
393
if (status == Z_STREAM_END)
398
status = inflateEnd (&zs);
400
/* error opening output file */
401
status = JAR_ERR_DISK;
378
403
PORT_Free (inbuf);
379
404
PORT_Free (outbuf);
380
return JAR_ERR_GENERAL;
383
if ((out = JAR_FOPEN (outpath, "wb")) != NULL)
387
JAR_FSEEK (fp, offset, (PRSeekWhence)0);
391
chunk = (at + ICHUNK <= length) ? ICHUNK : length - at;
393
if (JAR_FREAD (fp, inbuf, chunk) != chunk)
395
/* incomplete read */
399
return JAR_ERR_CORRUPT;
406
/* add an extra dummy byte at the end */
407
inbuf[chunk++] = 0xDD;
410
zs.next_in = (Bytef *) inbuf;
412
zs.avail_out = OCHUNK;
416
while ((zs.total_in - tin < chunk) || (zs.avail_out == 0))
418
prev_total = zs.total_out;
420
zs.next_out = (Bytef *) outbuf;
421
zs.avail_out = OCHUNK;
423
status = inflate (&zs, Z_NO_FLUSH);
425
if (status != Z_OK && status != Z_STREAM_END)
427
/* error during decompression */
431
return JAR_ERR_CORRUPT;
434
ochunk = zs.total_out - prev_total;
436
if (JAR_FWRITE (out, outbuf, ochunk) < ochunk)
438
/* most likely a disk full error */
439
status = JAR_ERR_DISK;
443
if (status == Z_STREAM_END)
449
status = inflateEnd (&zs);
453
/* error opening output file */
454
status = JAR_ERR_DISK;
464
409
* j a r _ i n f l a t e _ m e m o r y
466
* Call zlib to inflate the given memory chunk. It is re-XP_ALLOC'd,
411
* Call zlib to inflate the given memory chunk. It is re-XP_ALLOC'd,
467
412
* and thus appears to operate inplace to the caller.
471
static int jar_inflate_memory
472
(unsigned int method, long *length, long expected_out_len, char ZHUGEP **data)
479
char *inbuf, *outbuf;
484
outsz = expected_out_len;
485
outbuf = (char*)PORT_ZAlloc (outsz);
488
return JAR_ERR_MEMORY;
490
PORT_Memset (&zs, 0, sizeof (zs));
492
status = inflateInit2 (&zs, -MAX_WBITS);
496
/* error initializing zlib stream */
498
return JAR_ERR_GENERAL;
501
zs.next_in = (Bytef *) inbuf;
502
zs.next_out = (Bytef *) outbuf;
505
zs.avail_out = outsz;
507
status = inflate (&zs, Z_FINISH);
509
if (status != Z_OK && status != Z_STREAM_END)
511
/* error during deflation */
513
return JAR_ERR_GENERAL;
516
status = inflateEnd (&zs);
520
/* error during deflation */
522
return JAR_ERR_GENERAL;
528
*length = zs.total_out;
416
jar_inflate_memory(unsigned int method, long *length, long expected_out_len,
420
char *outbuf = (char*)PORT_ZAlloc(expected_out_len);
426
return JAR_ERR_MEMORY;
428
PORT_Memset(&zs, 0, sizeof zs);
429
status = inflateInit2 (&zs, -MAX_WBITS);
431
/* error initializing zlib stream */
433
return JAR_ERR_GENERAL;
436
zs.next_in = (Bytef *) inbuf;
437
zs.next_out = (Bytef *) outbuf;
439
zs.avail_out = expected_out_len;
441
status = inflate (&zs, Z_FINISH);
442
if (status != Z_OK && status != Z_STREAM_END) {
443
/* error during deflation */
445
return JAR_ERR_GENERAL;
448
status = inflateEnd (&zs);
449
if (status != Z_OK) {
450
/* error during deflation */
452
return JAR_ERR_GENERAL;
456
*length = zs.total_out;
534
461
* v e r i f y _ e x t r a c t
596
513
* from an open archive file whose contents are known.
600
static int jar_extract_manifests (JAR *jar, jarArch format, JAR_FILE fp)
602
int status, signatures;
604
if (format != jarArchZip && format != jarArchTar)
605
return JAR_ERR_CORRUPT;
607
if ((status = jar_extract_mf (jar, format, fp, "mf")) < 0)
610
return JAR_ERR_ORDER;
611
if ((status = jar_extract_mf (jar, format, fp, "sf")) < 0)
614
return JAR_ERR_ORDER;
615
if ((status = jar_extract_mf (jar, format, fp, "rsa")) < 0)
618
if ((status = jar_extract_mf (jar, format, fp, "dsa")) < 0)
620
if (!(signatures += status))
517
jar_extract_manifests(JAR *jar, jarArch format, JAR_FILE fp)
519
int status, signatures;
521
if (format != jarArchZip && format != jarArchTar)
522
return JAR_ERR_CORRUPT;
524
if ((status = jar_extract_mf (jar, format, fp, "mf")) < 0)
527
return JAR_ERR_ORDER;
528
if ((status = jar_extract_mf (jar, format, fp, "sf")) < 0)
531
return JAR_ERR_ORDER;
532
if ((status = jar_extract_mf (jar, format, fp, "rsa")) < 0)
535
if ((status = jar_extract_mf (jar, format, fp, "dsa")) < 0)
537
if (!(signatures += status))
626
543
* j a r _ e x t r a c t _ m f
628
* Extracts manifest files based on an extension, which
629
* should be .MF, .SF, .RSA, etc. Order of the files is now no
545
* Extracts manifest files based on an extension, which
546
* should be .MF, .SF, .RSA, etc. Order of the files is now no
630
547
* longer important when zipping jar files.
634
static int jar_extract_mf (JAR *jar, jarArch format, JAR_FILE fp, char *ext)
644
char ZHUGEP *manifest;
647
int status, ret = 0, num;
651
if (ZZ_ListEmpty (list))
654
for (link = ZZ_ListHead (list);
655
ret >= 0 && !ZZ_ListIterDone (list, link);
659
if (it->type == jarTypePhy
660
&& !PORT_Strncmp (it->pathname, "META-INF", 8))
662
phy = (JAR_Physical *) it->data;
664
if (PORT_Strlen (it->pathname) < 8)
667
fn = it->pathname + 8;
668
if (*fn == '/' || *fn == '\\') fn++;
672
/* just a directory entry */
676
/* skip to extension */
677
for (e = fn; *e && *e != '.'; e++)
683
if (PORT_Strcasecmp (ext, e))
685
/* not the right extension */
689
if (phy->length == 0 || phy->length > 0xFFFF)
691
/* manifest files cannot be zero length or too big! */
692
/* the 0xFFFF limit is per J2SE SDK */
693
return JAR_ERR_CORRUPT;
696
/* Read in the manifest and parse it */
697
/* Raw inflate in zlib 1.1.4 needs an extra dummy byte at the end */
698
manifest = (char ZHUGEP *) PORT_ZAlloc (phy->length + 1);
701
JAR_FSEEK (fp, phy->offset, (PRSeekWhence)0);
702
num = JAR_FREAD (fp, manifest, phy->length);
704
if (num != phy->length)
706
/* corrupt archive file */
707
PORT_Free (manifest);
708
return JAR_ERR_CORRUPT;
711
if (phy->compression == 8)
713
length = phy->length;
714
/* add an extra dummy byte at the end */
715
manifest[length++] = 0xDD;
717
status = jar_inflate_memory ((unsigned int) phy->compression, &length, phy->uncompressed_length, &manifest);
721
PORT_Free (manifest);
725
else if (phy->compression)
727
/* unsupported compression method */
728
PORT_Free (manifest);
729
return JAR_ERR_CORRUPT;
732
length = phy->length;
734
status = JAR_parse_manifest
735
(jar, manifest, length, it->pathname, "url");
737
PORT_Free (manifest);
745
return JAR_ERR_MEMORY;
747
else if (it->type == jarTypePhy)
551
jar_extract_mf(JAR *jar, jarArch format, JAR_FILE fp, char *ext)
554
ZZList *list = jar->phy;
557
if (ZZ_ListEmpty (list))
560
for (link = ZZ_ListHead (list);
561
ret >= 0 && !ZZ_ListIterDone (list, link);
563
JAR_Item *it = link->thing;
565
if (it->type == jarTypePhy &&
566
!PORT_Strncmp (it->pathname, "META-INF", 8))
568
JAR_Physical *phy = (JAR_Physical *) it->data;
569
char *fn = it->pathname + 8;
575
if (PORT_Strlen (it->pathname) < 8)
578
if (*fn == '/' || *fn == '\\')
581
/* just a directory entry */
585
/* skip to extension */
586
for (e = fn; *e && *e != '.'; e++)
592
if (PORT_Strcasecmp (ext, e)) {
593
/* not the right extension */
596
if (phy->length == 0 || phy->length > 0xFFFF) {
597
/* manifest files cannot be zero length or too big! */
598
/* the 0xFFFF limit is per J2SE SDK */
599
return JAR_ERR_CORRUPT;
602
/* Read in the manifest and parse it */
603
/* Raw inflate in zlib 1.1.4 needs an extra dummy byte at the end */
604
manifest = (char *)PORT_ZAlloc(phy->length + 1);
606
return JAR_ERR_MEMORY;
608
JAR_FSEEK (fp, phy->offset, (PRSeekWhence)0);
609
num = JAR_FREAD (fp, manifest, phy->length);
610
if (num != phy->length) {
611
/* corrupt archive file */
612
PORT_Free (manifest);
613
return JAR_ERR_CORRUPT;
616
if (phy->compression == 8) {
617
length = phy->length;
618
/* add an extra dummy byte at the end */
619
manifest[length++] = 0xDD;
620
status = jar_inflate_memory((unsigned int)phy->compression,
622
phy->uncompressed_length,
625
PORT_Free (manifest);
628
} else if (phy->compression) {
629
/* unsupported compression method */
630
PORT_Free (manifest);
631
return JAR_ERR_CORRUPT;
633
length = phy->length;
635
status = JAR_parse_manifest(jar, manifest, length,
636
it->pathname, "url");
637
PORT_Free (manifest);
642
} else if (it->type == jarTypePhy) {
757
650
* j a r _ g e n _ i n d e x
760
653
* known archive files. Right now .ZIP and .TAR
764
static int jar_gen_index (JAR *jar, jarArch format, JAR_FILE fp)
766
int result = JAR_ERR_CORRUPT;
767
JAR_FSEEK (fp, 0, (PRSeekWhence)0);
657
jar_gen_index(JAR *jar, jarArch format, JAR_FILE fp)
659
int result = JAR_ERR_CORRUPT;
661
JAR_FSEEK (fp, 0, (PRSeekWhence)0);
772
result = jar_listzip (jar, fp);
664
result = jar_listzip (jar, fp);
776
result = jar_listtar (jar, fp);
668
result = jar_listtar (jar, fp);
779
671
case jarArchGuess:
780
672
case jarArchNone:
781
return JAR_ERR_GENERAL;
673
return JAR_ERR_GENERAL;
784
JAR_FSEEK (fp, 0, (PRSeekWhence)0);
675
JAR_FSEEK (fp, 0, (PRSeekWhence)0);
790
680
* j a r _ l i s t z i p
792
* List the physical contents of a Phil Katz
682
* List the physical contents of a Phil Katz
793
683
* style .ZIP file into the JAR linked list.
797
static int jar_listzip (JAR *jar, JAR_FILE fp)
802
char filename [JAR_SIZE];
804
char date [9], time [9];
807
unsigned int compression;
808
unsigned int filename_len, extra_len;
810
struct ZipLocal *Local;
811
struct ZipCentral *Central;
820
Local = (struct ZipLocal *) PORT_ZAlloc (30);
821
Central = (struct ZipCentral *) PORT_ZAlloc (46);
822
End = (struct ZipEnd *) PORT_ZAlloc (22);
824
if (!Local || !Central || !End)
827
err = JAR_ERR_MEMORY;
687
jar_listzip(JAR *jar, JAR_FILE fp)
692
struct ZipLocal *Local = PORT_ZNew(struct ZipLocal);
693
struct ZipCentral *Central = PORT_ZNew(struct ZipCentral);
694
struct ZipEnd *End = PORT_ZNew(struct ZipEnd);
698
unsigned int compression;
699
unsigned int filename_len, extra_len;
701
char filename[JAR_SIZE];
702
char date[9], time[9];
705
if (!Local || !Central || !End) {
707
err = JAR_ERR_MEMORY;
833
JAR_FSEEK (fp, pos, (PRSeekWhence)0);
835
if (JAR_FREAD (fp, (char *) sig, 4) != 4)
837
/* zip file ends prematurely */
838
err = JAR_ERR_CORRUPT;
842
JAR_FSEEK (fp, pos, (PRSeekWhence)0);
844
if (xtolong ((unsigned char *)sig) == LSIG)
846
JAR_FREAD (fp, (char *) Local, 30);
848
filename_len = xtoint ((unsigned char *) Local->filename_len);
849
extra_len = xtoint ((unsigned char *) Local->extrafield_len);
851
if (filename_len >= JAR_SIZE)
853
/* corrupt zip file */
854
err = JAR_ERR_CORRUPT;
858
if (JAR_FREAD (fp, filename, filename_len) != filename_len)
860
/* truncated archive file */
861
err = JAR_ERR_CORRUPT;
865
filename [filename_len] = 0;
867
/* Add this to our jar chain */
869
phy = (JAR_Physical *) PORT_ZAlloc (sizeof (JAR_Physical));
873
err = JAR_ERR_MEMORY;
877
/* We will index any file that comes our way, but when it comes
878
to actually extraction, compression must be 0 or 8 */
880
compression = xtoint ((unsigned char *) Local->method);
881
phy->compression = compression >= 0 &&
882
compression <= 255 ? compression : 222;
884
phy->offset = pos + 30 + filename_len + extra_len;
885
phy->length = xtolong ((unsigned char *) Local->size);
886
phy->uncompressed_length = xtolong((unsigned char *) Local->orglen);
888
dosdate (date, Local->date);
889
dostime (time, Local->time);
891
it = (JAR_Item*)PORT_ZAlloc (sizeof (JAR_Item));
894
err = JAR_ERR_MEMORY;
898
it->pathname = PORT_Strdup (filename);
900
it->type = jarTypePhy;
902
it->data = (unsigned char *) phy;
903
it->size = sizeof (JAR_Physical);
905
ent = ZZ_NewLink (it);
909
err = JAR_ERR_MEMORY;
913
ZZ_AppendLink (jar->phy, ent);
915
pos = phy->offset + phy->length;
917
else if (xtolong ( (unsigned char *)sig) == CSIG)
919
if (JAR_FREAD (fp, (char *) Central, 46) != 46)
921
/* apparently truncated archive */
922
err = JAR_ERR_CORRUPT;
713
JAR_FSEEK (fp, pos, (PRSeekWhence)0);
715
if (JAR_FREAD(fp, sig, sizeof sig) != sizeof sig) {
716
/* zip file ends prematurely */
717
err = JAR_ERR_CORRUPT;
721
JAR_FSEEK (fp, pos, (PRSeekWhence)0);
722
sigVal = x86LongToUint32(sig);
723
if (sigVal == LSIG) {
724
JAR_FREAD (fp, Local, sizeof *Local);
726
filename_len = x86ShortToUint32(Local->filename_len);
727
extra_len = x86ShortToUint32(Local->extrafield_len);
728
if (filename_len >= JAR_SIZE) {
729
/* corrupt zip file */
730
err = JAR_ERR_CORRUPT;
734
if (JAR_FREAD (fp, filename, filename_len) != filename_len) {
735
/* truncated archive file */
736
err = JAR_ERR_CORRUPT;
739
filename [filename_len] = 0;
740
/* Add this to our jar chain */
741
phy = PORT_ZNew(JAR_Physical);
743
err = JAR_ERR_MEMORY;
747
/* We will index any file that comes our way, but when it comes
748
to actually extraction, compression must be 0 or 8 */
749
compression = x86ShortToUint32(Local->method);
751
(compression >= 0 && compression <= 255) ? compression : 222;
752
/* XXX 222 is bad magic. */
754
phy->offset = pos + (sizeof *Local) + filename_len + extra_len;
755
phy->length = x86LongToUint32(Local->size);
756
phy->uncompressed_length = x86LongToUint32(Local->orglen);
758
dosdate (date, Local->date);
759
dostime (time, Local->time);
761
it = PORT_ZNew(JAR_Item);
763
err = JAR_ERR_MEMORY;
767
it->pathname = PORT_Strdup(filename);
768
it->type = jarTypePhy;
769
it->data = (unsigned char *) phy;
770
it->size = sizeof (JAR_Physical);
772
ent = ZZ_NewLink (it);
774
err = JAR_ERR_MEMORY;
778
ZZ_AppendLink (jar->phy, ent);
779
pos = phy->offset + phy->length;
780
} else if (sigVal == CSIG) {
781
unsigned int attr = 0;
782
if (JAR_FREAD(fp, Central, sizeof *Central) != sizeof *Central) {
783
/* apparently truncated archive */
784
err = JAR_ERR_CORRUPT;
926
788
#if defined(XP_UNIX) || defined(XP_BEOS)
927
/* with unix we need to locate any bits from
928
the protection mask in the external attributes. */
932
/* determined empirically */
933
attr = Central->external_attributes [2];
937
/* we have to read the filename, again */
939
filename_len = xtoint ((unsigned char *) Central->filename_len);
941
if (filename_len >= JAR_SIZE)
943
/* corrupt in central directory */
944
err = JAR_ERR_CORRUPT;
948
if (JAR_FREAD (fp, filename, filename_len) != filename_len)
950
/* truncated in central directory */
951
err = JAR_ERR_CORRUPT;
955
filename [filename_len] = 0;
957
/* look up this name again */
958
phy = jar_get_physical (jar, filename);
962
/* always allow access by self */
963
phy->mode = 0400 | attr;
789
/* with unix we need to locate any bits from
790
the protection mask in the external attributes. */
791
attr = Central->external_attributes [2]; /* magic */
793
/* we have to read the filename, again */
794
filename_len = x86ShortToUint32(Central->filename_len);
795
if (filename_len >= JAR_SIZE) {
796
/* corrupt in central directory */
797
err = JAR_ERR_CORRUPT;
801
if (JAR_FREAD(fp, filename, filename_len) != filename_len) {
802
/* truncated in central directory */
803
err = JAR_ERR_CORRUPT;
806
filename [filename_len] = 0;
808
/* look up this name again */
809
phy = jar_get_physical (jar, filename);
811
/* always allow access by self */
812
phy->mode = 0400 | attr;
969
pos += 46 + xtoint ( (unsigned char *)Central->filename_len)
970
+ xtoint ( (unsigned char *)Central->commentfield_len)
971
+ xtoint ( (unsigned char *)Central->extrafield_len);
973
else if (xtolong ( (unsigned char *)sig) == ESIG)
975
if (JAR_FREAD (fp, (char *) End, 22) != 22)
977
err = JAR_ERR_CORRUPT;
985
/* garbage in archive */
986
err = JAR_ERR_CORRUPT;
816
pos += sizeof(struct ZipCentral)
817
+ x86ShortToUint32(Central->filename_len)
818
+ x86ShortToUint32(Central->commentfield_len)
819
+ x86ShortToUint32(Central->extrafield_len);
820
} else if (sigVal == ESIG) {
821
if (JAR_FREAD(fp, End, sizeof *End) != sizeof *End) {
822
err = JAR_ERR_CORRUPT;
827
/* garbage in archive */
828
err = JAR_ERR_CORRUPT;
993
if (Local) PORT_Free (Local);
994
if (Central) PORT_Free (Central);
995
if (End) PORT_Free (End);
1001
844
* j a r _ l i s t t a r
1003
* List the physical contents of a Unix
846
* List the physical contents of a Unix
1004
847
* .tar file into the JAR linked list.
1008
static int jar_listtar (JAR *jar, JAR_FILE fp)
1014
union TarEntry tarball;
1024
JAR_FSEEK (fp, pos, (PRSeekWhence)0);
1026
if (JAR_FREAD (fp, (char *) &tarball, 512) < 512)
1029
if (!*tarball.val.filename)
1032
when = atoo (tarball.val.time);
1033
sz = atoo (tarball.val.size);
1034
mode = atoo (tarball.val.mode);
1037
/* Tag the end of filename */
1039
s = tarball.val.filename;
1040
while (*s && *s != ' ') s++;
1044
/* Add to our linked list */
1046
phy = (JAR_Physical *) PORT_ZAlloc (sizeof (JAR_Physical));
1049
return JAR_ERR_MEMORY;
1051
phy->compression = 0;
1052
phy->offset = pos + 512;
1055
ADDITEM (jar->phy, jarTypePhy,
1056
tarball.val.filename, phy, sizeof (JAR_Physical));
1059
/* Advance to next file entry */
1062
sz = (sz / 512) * 512;
851
jar_listtar(JAR *jar, JAR_FILE fp)
858
union TarEntry tarball;
861
JAR_FSEEK (fp, pos, (PRSeekWhence)0);
863
if (JAR_FREAD (fp, &tarball, sizeof tarball) < sizeof tarball)
866
if (!*tarball.val.filename)
869
when = octalToLong (tarball.val.time);
870
sz = octalToLong (tarball.val.size);
871
mode = octalToLong (tarball.val.mode);
873
/* Tag the end of filename */
874
s = tarball.val.filename;
875
while (*s && *s != ' ')
879
/* Add to our linked list */
880
phy = PORT_ZNew(JAR_Physical);
882
return JAR_ERR_MEMORY;
884
phy->compression = 0;
885
phy->offset = pos + sizeof tarball;
888
ADDITEM(jar->phy, jarTypePhy, tarball.val.filename, phy,
891
/* Advance to next file entry */
892
sz = PR_ROUNDUP(sz,sizeof tarball);
893
pos += sz + sizeof tarball;
1073
902
* Not used right now, but keep it in here because
1074
* it will be needed.
1078
static int dosdate (char *date, char *s)
1080
int num = xtoint ( (unsigned char *)s);
1082
PR_snprintf (date, 9, "%02d-%02d-%02d",
1083
((num >> 5) & 0x0F), (num & 0x1F), ((num >> 9) + 80));
907
dosdate(char *date, const char *s)
909
PRUint32 num = x86ShortToUint32(s);
911
PR_snprintf(date, 9, "%02d-%02d-%02d", ((num >> 5) & 0x0F), (num & 0x1F),
1091
919
* Not used right now, but keep it in here because
1092
* it will be needed.
1096
static int dostime (char *time, char *s)
1098
int num = xtoint ( (unsigned char *)s);
1100
PR_snprintf (time, 6, "%02d:%02d",
1101
((num >> 11) & 0x1F), ((num >> 5) & 0x3F));
1109
* Converts a two byte ugly endianed integer
1110
* to our platform's integer.
1114
static unsigned int xtoint (unsigned char *ii)
1116
return (int) (ii [0]) | ((int) ii [1] << 8);
1122
* Converts a four byte ugly endianed integer
1123
* to our platform's integer.
1127
static unsigned long xtolong (unsigned char *ll)
1132
(((unsigned long) ll [0]) << 0) |
1133
(((unsigned long) ll [1]) << 8) |
1134
(((unsigned long) ll [2]) << 16) |
1135
(((unsigned long) ll [3]) << 24)
1144
* Ascii octal to decimal.
924
dostime (char *time, const char *s)
926
PRUint32 num = x86ShortToUint32(s);
928
PR_snprintf (time, 6, "%02d:%02d", ((num >> 11) & 0x1F),
929
((num >> 5) & 0x3F));
933
#ifndef NSS_X86_OR_X64
935
* Simulates an x86 (little endian, unaligned) ushort fetch from any address.
938
x86ShortToUint32(const void * v)
940
const unsigned char *ii = (const unsigned char *)v;
941
PRUint32 ret = (PRUint32)(ii[0]) | ((PRUint32)(ii[1]) << 8);
946
* Simulates an x86 (little endian, unaligned) uint fetch from any address.
949
x86LongToUint32(const void *v)
951
const unsigned char *ll = (const unsigned char *)v;
954
ret = ((((PRUint32)(ll[0])) << 0) |
955
(((PRUint32)(ll[1])) << 8) |
956
(((PRUint32)(ll[2])) << 16) |
957
(((PRUint32)(ll[3])) << 24));
963
* ASCII octal to binary long.
1145
964
* Used for integer encoding inside tar files.
1149
static long atoo (char *s)
1153
while (*s == ' ') s++;
1155
while (*s >= '0' && *s <= '7')
968
octalToLong(const char *s)
974
while (*s >= '0' && *s <= '7') {
1165
982
* g u e s s _ j a r