341 * Writes local file (LOC) header for specified entry. |
342 * Writes local file (LOC) header for specified entry. |
342 */ |
343 */ |
343 private void writeLOC(XEntry xentry) throws IOException { |
344 private void writeLOC(XEntry xentry) throws IOException { |
344 ZipEntry e = xentry.entry; |
345 ZipEntry e = xentry.entry; |
345 int flag = xentry.flag; |
346 int flag = xentry.flag; |
|
347 int elen = (e.extra != null) ? e.extra.length : 0; |
|
348 boolean hasZip64 = false; |
|
349 |
346 writeInt(LOCSIG); // LOC header signature |
350 writeInt(LOCSIG); // LOC header signature |
347 writeShort(version(e)); // version needed to extract |
351 |
348 writeShort(flag); // general purpose bit flag |
|
349 writeShort(e.method); // compression method |
|
350 writeInt(e.time); // last modification time |
|
351 if ((flag & 8) == 8) { |
352 if ((flag & 8) == 8) { |
|
353 writeShort(version(e)); // version needed to extract |
|
354 writeShort(flag); // general purpose bit flag |
|
355 writeShort(e.method); // compression method |
|
356 writeInt(e.time); // last modification time |
|
357 |
352 // store size, uncompressed size, and crc-32 in data descriptor |
358 // store size, uncompressed size, and crc-32 in data descriptor |
353 // immediately following compressed entry data |
359 // immediately following compressed entry data |
354 writeInt(0); |
360 writeInt(0); |
355 writeInt(0); |
361 writeInt(0); |
356 writeInt(0); |
362 writeInt(0); |
357 } else { |
363 } else { |
358 writeInt(e.crc); // crc-32 |
364 if (e.csize >= ZIP64_MAGICVAL || e.size >= ZIP64_MAGICVAL) { |
359 writeInt(e.csize); // compressed size |
365 hasZip64 = true; |
360 writeInt(e.size); // uncompressed size |
366 writeShort(45); // ver 4.5 for zip64 |
|
367 } else { |
|
368 writeShort(version(e)); // version needed to extract |
|
369 } |
|
370 writeShort(flag); // general purpose bit flag |
|
371 writeShort(e.method); // compression method |
|
372 writeInt(e.time); // last modification time |
|
373 writeInt(e.crc); // crc-32 |
|
374 if (hasZip64) { |
|
375 writeInt(ZIP64_MAGICVAL); |
|
376 writeInt(ZIP64_MAGICVAL); |
|
377 elen += 20; //headid(2) + size(2) + size(8) + csize(8) |
|
378 } else { |
|
379 writeInt(e.csize); // compressed size |
|
380 writeInt(e.size); // uncompressed size |
|
381 } |
361 } |
382 } |
362 byte[] nameBytes = getUTF8Bytes(e.name); |
383 byte[] nameBytes = getUTF8Bytes(e.name); |
363 writeShort(nameBytes.length); |
384 writeShort(nameBytes.length); |
364 writeShort(e.extra != null ? e.extra.length : 0); |
385 writeShort(elen); |
365 writeBytes(nameBytes, 0, nameBytes.length); |
386 writeBytes(nameBytes, 0, nameBytes.length); |
|
387 if (hasZip64) { |
|
388 writeShort(ZIP64_EXTID); |
|
389 writeShort(16); |
|
390 writeLong(e.size); |
|
391 writeLong(e.csize); |
|
392 } |
366 if (e.extra != null) { |
393 if (e.extra != null) { |
367 writeBytes(e.extra, 0, e.extra.length); |
394 writeBytes(e.extra, 0, e.extra.length); |
368 } |
395 } |
369 locoff = written; |
396 locoff = written; |
370 } |
397 } |
373 * Writes extra data descriptor (EXT) for specified entry. |
400 * Writes extra data descriptor (EXT) for specified entry. |
374 */ |
401 */ |
375 private void writeEXT(ZipEntry e) throws IOException { |
402 private void writeEXT(ZipEntry e) throws IOException { |
376 writeInt(EXTSIG); // EXT header signature |
403 writeInt(EXTSIG); // EXT header signature |
377 writeInt(e.crc); // crc-32 |
404 writeInt(e.crc); // crc-32 |
378 writeInt(e.csize); // compressed size |
405 if (e.csize >= ZIP64_MAGICVAL || e.size >= ZIP64_MAGICVAL) { |
379 writeInt(e.size); // uncompressed size |
406 writeLong(e.csize); |
|
407 writeLong(e.size); |
|
408 } else { |
|
409 writeInt(e.csize); // compressed size |
|
410 writeInt(e.size); // uncompressed size |
|
411 } |
380 } |
412 } |
381 |
413 |
382 /* |
414 /* |
383 * Write central directory (CEN) header for specified entry. |
415 * Write central directory (CEN) header for specified entry. |
384 * REMIND: add support for file attributes |
416 * REMIND: add support for file attributes |
385 */ |
417 */ |
386 private void writeCEN(XEntry xentry) throws IOException { |
418 private void writeCEN(XEntry xentry) throws IOException { |
387 ZipEntry e = xentry.entry; |
419 ZipEntry e = xentry.entry; |
388 int flag = xentry.flag; |
420 int flag = xentry.flag; |
389 int version = version(e); |
421 int version = version(e); |
|
422 |
|
423 long csize = e.csize; |
|
424 long size = e.size; |
|
425 long offset = xentry.offset; |
|
426 int e64len = 0; |
|
427 boolean hasZip64 = false; |
|
428 if (e.csize >= ZIP64_MAGICVAL) { |
|
429 csize = ZIP64_MAGICVAL; |
|
430 e64len += 8; // csize(8) |
|
431 hasZip64 = true; |
|
432 } |
|
433 if (e.size >= ZIP64_MAGICVAL) { |
|
434 size = ZIP64_MAGICVAL; // size(8) |
|
435 e64len += 8; |
|
436 hasZip64 = true; |
|
437 } |
|
438 if (xentry.offset >= ZIP64_MAGICVAL) { |
|
439 offset = ZIP64_MAGICVAL; |
|
440 e64len += 8; // offset(8) |
|
441 hasZip64 = true; |
|
442 } |
390 writeInt(CENSIG); // CEN header signature |
443 writeInt(CENSIG); // CEN header signature |
391 writeShort(version); // version made by |
444 if (hasZip64) { |
392 writeShort(version); // version needed to extract |
445 writeShort(45); // ver 4.5 for zip64 |
|
446 writeShort(45); |
|
447 } else { |
|
448 writeShort(version); // version made by |
|
449 writeShort(version); // version needed to extract |
|
450 } |
393 writeShort(flag); // general purpose bit flag |
451 writeShort(flag); // general purpose bit flag |
394 writeShort(e.method); // compression method |
452 writeShort(e.method); // compression method |
395 writeInt(e.time); // last modification time |
453 writeInt(e.time); // last modification time |
396 writeInt(e.crc); // crc-32 |
454 writeInt(e.crc); // crc-32 |
397 writeInt(e.csize); // compressed size |
455 writeInt(csize); // compressed size |
398 writeInt(e.size); // uncompressed size |
456 writeInt(size); // uncompressed size |
399 byte[] nameBytes = getUTF8Bytes(e.name); |
457 byte[] nameBytes = getUTF8Bytes(e.name); |
400 writeShort(nameBytes.length); |
458 writeShort(nameBytes.length); |
401 writeShort(e.extra != null ? e.extra.length : 0); |
459 if (hasZip64) { |
|
460 // + headid(2) + datasize(2) |
|
461 writeShort(e64len + 4 + (e.extra != null ? e.extra.length : 0)); |
|
462 } else { |
|
463 writeShort(e.extra != null ? e.extra.length : 0); |
|
464 } |
402 byte[] commentBytes; |
465 byte[] commentBytes; |
403 if (e.comment != null) { |
466 if (e.comment != null) { |
404 commentBytes = getUTF8Bytes(e.comment); |
467 commentBytes = getUTF8Bytes(e.comment); |
405 writeShort(commentBytes.length); |
468 writeShort(commentBytes.length); |
406 } else { |
469 } else { |
408 writeShort(0); |
471 writeShort(0); |
409 } |
472 } |
410 writeShort(0); // starting disk number |
473 writeShort(0); // starting disk number |
411 writeShort(0); // internal file attributes (unused) |
474 writeShort(0); // internal file attributes (unused) |
412 writeInt(0); // external file attributes (unused) |
475 writeInt(0); // external file attributes (unused) |
413 writeInt(xentry.offset); // relative offset of local header |
476 writeInt(offset); // relative offset of local header |
414 writeBytes(nameBytes, 0, nameBytes.length); |
477 writeBytes(nameBytes, 0, nameBytes.length); |
|
478 if (hasZip64) { |
|
479 writeShort(ZIP64_EXTID);// Zip64 extra |
|
480 writeShort(e64len); |
|
481 if (size == ZIP64_MAGICVAL) |
|
482 writeLong(e.size); |
|
483 if (csize == ZIP64_MAGICVAL) |
|
484 writeLong(e.csize); |
|
485 if (offset == ZIP64_MAGICVAL) |
|
486 writeLong(xentry.offset); |
|
487 } |
415 if (e.extra != null) { |
488 if (e.extra != null) { |
416 writeBytes(e.extra, 0, e.extra.length); |
489 writeBytes(e.extra, 0, e.extra.length); |
417 } |
490 } |
418 if (commentBytes != null) { |
491 if (commentBytes != null) { |
419 writeBytes(commentBytes, 0, commentBytes.length); |
492 writeBytes(commentBytes, 0, commentBytes.length); |
422 |
495 |
423 /* |
496 /* |
424 * Writes end of central directory (END) header. |
497 * Writes end of central directory (END) header. |
425 */ |
498 */ |
426 private void writeEND(long off, long len) throws IOException { |
499 private void writeEND(long off, long len) throws IOException { |
|
500 boolean hasZip64 = false; |
|
501 long xlen = len; |
|
502 long xoff = off; |
|
503 if (xlen >= ZIP64_MAGICVAL) { |
|
504 xlen = ZIP64_MAGICVAL; |
|
505 hasZip64 = true; |
|
506 } |
|
507 if (xoff >= ZIP64_MAGICVAL) { |
|
508 xoff = ZIP64_MAGICVAL; |
|
509 hasZip64 = true; |
|
510 } |
427 int count = xentries.size(); |
511 int count = xentries.size(); |
428 writeInt(ENDSIG); // END record signature |
512 if (count >= ZIP64_MAGICCOUNT) { |
429 writeShort(0); // number of this disk |
513 count = ZIP64_MAGICCOUNT; |
430 writeShort(0); // central directory start disk |
514 hasZip64 = true; |
431 writeShort(count); // number of directory entries on disk |
515 } |
432 writeShort(count); // total number of directory entries |
516 if (hasZip64) { |
433 writeInt(len); // length of central directory |
517 long off64 = written; |
434 writeInt(off); // offset of central directory |
518 //zip64 end of central directory record |
435 if (comment != null) { // zip file comment |
519 writeInt(ZIP64_ENDSIG); // zip64 END record signature |
|
520 writeLong(ZIP64_ENDHDR - 12); // size of zip64 end |
|
521 writeShort(45); // version made by |
|
522 writeShort(45); // version needed to extract |
|
523 writeInt(0); // number of this disk |
|
524 writeInt(0); // central directory start disk |
|
525 writeLong(xentries.size()); // number of directory entires on disk |
|
526 writeLong(xentries.size()); // number of directory entires |
|
527 writeLong(len); // length of central directory |
|
528 writeLong(off); // offset of central directory |
|
529 |
|
530 //zip64 end of central directory locator |
|
531 writeInt(ZIP64_LOCSIG); // zip64 END locator signature |
|
532 writeInt(0); // zip64 END start disk |
|
533 writeLong(off64); // offset of zip64 END |
|
534 writeInt(1); // total number of disks (?) |
|
535 } |
|
536 writeInt(ENDSIG); // END record signature |
|
537 writeShort(0); // number of this disk |
|
538 writeShort(0); // central directory start disk |
|
539 writeShort(count); // number of directory entries on disk |
|
540 writeShort(count); // total number of directory entries |
|
541 writeInt(xlen); // length of central directory |
|
542 writeInt(xoff); // offset of central directory |
|
543 if (comment != null) { // zip file comment |
436 byte[] b = getUTF8Bytes(comment); |
544 byte[] b = getUTF8Bytes(comment); |
437 writeShort(b.length); |
545 writeShort(b.length); |
438 writeBytes(b, 0, b.length); |
546 writeBytes(b, 0, b.length); |
439 } else { |
547 } else { |
440 writeShort(0); |
548 writeShort(0); |
459 out.write((int)((v >>> 0) & 0xff)); |
567 out.write((int)((v >>> 0) & 0xff)); |
460 out.write((int)((v >>> 8) & 0xff)); |
568 out.write((int)((v >>> 8) & 0xff)); |
461 out.write((int)((v >>> 16) & 0xff)); |
569 out.write((int)((v >>> 16) & 0xff)); |
462 out.write((int)((v >>> 24) & 0xff)); |
570 out.write((int)((v >>> 24) & 0xff)); |
463 written += 4; |
571 written += 4; |
|
572 } |
|
573 |
|
574 /* |
|
575 * Writes a 64-bit int to the output stream in little-endian byte order. |
|
576 */ |
|
577 private void writeLong(long v) throws IOException { |
|
578 OutputStream out = this.out; |
|
579 out.write((int)((v >>> 0) & 0xff)); |
|
580 out.write((int)((v >>> 8) & 0xff)); |
|
581 out.write((int)((v >>> 16) & 0xff)); |
|
582 out.write((int)((v >>> 24) & 0xff)); |
|
583 out.write((int)((v >>> 32) & 0xff)); |
|
584 out.write((int)((v >>> 40) & 0xff)); |
|
585 out.write((int)((v >>> 48) & 0xff)); |
|
586 out.write((int)((v >>> 56) & 0xff)); |
|
587 written += 8; |
464 } |
588 } |
465 |
589 |
466 /* |
590 /* |
467 * Writes an array of bytes to the output stream. |
591 * Writes an array of bytes to the output stream. |
468 */ |
592 */ |