Differences From Artifact [c1fa8a1f8d]:
- File
src/OFZIPArchive.m
— part of check-in
[8ebf6ed443]
at
2017-08-13 22:34:33
on branch trunk
— OFZIPArchive(Entry): Remove ZIP64 from extra field
Treating the ZIP64 extra field as part of the entry itself makes things
a lot easier when (re)writing the central directory. (user: js, size: 21490) [annotate] [blame] [check-ins using]
To Artifact [db5f1942c0]:
- File src/OFZIPArchive.m — part of check-in [def4cbbba6] at 2017-08-14 00:31:05 on branch trunk — OFZIPArchive: Support for writing ZIP64 archives (user: js, size: 22371) [annotate] [blame] [check-ins using]
︙ | ︙ | |||
43 44 45 46 47 48 49 | #import "OFOutOfRangeException.h" #import "OFSeekFailedException.h" #import "OFUnsupportedVersionException.h" /* * FIXME: Current limitations: * - Split archives are not supported. | < < | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | #import "OFOutOfRangeException.h" #import "OFSeekFailedException.h" #import "OFUnsupportedVersionException.h" /* * FIXME: Current limitations: * - Split archives are not supported. * - Encrypted files cannot be read. */ @interface OFZIPArchive () - (void)of_readZIPInfo; - (void)of_readEntries; - (void)of_closeLastReturnedStream; - (void)of_writeCentralDirectory; |
︙ | ︙ | |||
471 472 473 474 475 476 477 478 479 480 481 482 | return [[_lastReturnedStream retain] autorelease]; } - (OFStream *)streamForWritingEntry: (OFZIPArchiveEntry *)entry_ { /* TODO: Avoid data descriptor when _stream is an OFSeekableStream */ void *pool; OFMutableZIPArchiveEntry *entry; OFString *fileName; OFData *extraField; uint16_t fileNameLength, extraFieldLength; | > < | 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 | return [[_lastReturnedStream retain] autorelease]; } - (OFStream *)streamForWritingEntry: (OFZIPArchiveEntry *)entry_ { /* TODO: Avoid data descriptor when _stream is an OFSeekableStream */ int64_t offsetAdd = 0; void *pool; OFMutableZIPArchiveEntry *entry; OFString *fileName; OFData *extraField; uint16_t fileNameLength, extraFieldLength; if (_mode != OF_ZIP_ARCHIVE_MODE_WRITE && _mode != OF_ZIP_ARCHIVE_MODE_APPEND) @throw [OFInvalidArgumentException exception]; pool = objc_autoreleasePoolPush(); entry = [[entry_ mutableCopy] autorelease]; |
︙ | ︙ | |||
498 499 500 501 502 503 504 | if ([entry compressionMethod] != OF_ZIP_ARCHIVE_ENTRY_COMPRESSION_METHOD_NONE) @throw [OFNotImplementedException exceptionWithSelector: _cmd object: self]; [self of_closeLastReturnedStream]; | > > > > | > | | | | > > | | | < < | > | > > > | < | < < < > > > > > > > > > | > | > > > > > > > | | | | | | | 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 | if ([entry compressionMethod] != OF_ZIP_ARCHIVE_ENTRY_COMPRESSION_METHOD_NONE) @throw [OFNotImplementedException exceptionWithSelector: _cmd object: self]; [self of_closeLastReturnedStream]; fileName = [entry fileName]; fileNameLength = [fileName UTF8StringLength]; extraField = [entry extraField]; extraFieldLength = [extraField count]; if (UINT16_MAX - extraFieldLength < 20) @throw [OFOutOfRangeException exception]; [entry setVersionMadeBy: ([entry versionMadeBy] & 0xFF00) | 45]; [entry setMinVersionNeeded: ([entry minVersionNeeded] & 0xFF00) | 45]; [entry setCompressedSize: 0]; [entry setUncompressedSize: 0]; [entry setCRC32: 0]; [entry setGeneralPurposeBitFlag: [entry generalPurposeBitFlag] | (1 << 3) | (1 << 11)]; [entry of_setLocalFileHeaderOffset: _offset]; [_stream writeLittleEndianInt32: 0x04034B50]; [_stream writeLittleEndianInt16: [entry minVersionNeeded]]; [_stream writeLittleEndianInt16: [entry generalPurposeBitFlag]]; [_stream writeLittleEndianInt16: [entry compressionMethod]]; [_stream writeLittleEndianInt16: [entry of_lastModifiedFileTime]]; [_stream writeLittleEndianInt16: [entry of_lastModifiedFileDate]]; /* We use ZIP64 */ [_stream writeLittleEndianInt32: 0xFFFFFFFF]; [_stream writeLittleEndianInt32: 0xFFFFFFFF]; [_stream writeLittleEndianInt32: 0xFFFFFFFF]; [_stream writeLittleEndianInt16: fileNameLength]; [_stream writeLittleEndianInt16: extraFieldLength + 20]; offsetAdd += 4 + (5 * 2) + (3 * 4) + (2 * 2); [_stream writeString: fileName]; offsetAdd += fileNameLength; [_stream writeLittleEndianInt16: OF_ZIP_ARCHIVE_ENTRY_EXTRA_FIELD_ZIP64]; [_stream writeLittleEndianInt16: 16]; /* We use the data descriptor */ [_stream writeLittleEndianInt64: 0]; [_stream writeLittleEndianInt64: 0]; offsetAdd += (2 * 2) + (2 * 8); if (extraField != nil) [_stream writeData: extraField]; offsetAdd += extraFieldLength; if (INT64_MAX - _offset < offsetAdd) @throw [OFOutOfRangeException exception]; _offset += offsetAdd; _lastReturnedStream = [[OFZIPArchive_FileWriteStream alloc] initWithStream: _stream entry: entry]; objc_autoreleasePoolPop(pool); return [[_lastReturnedStream retain] autorelease]; } - (void)of_writeCentralDirectory { void *pool = objc_autoreleasePoolPush(); _centralDirectoryEntries = 0; _centralDirectoryEntriesInDisk = 0; _centralDirectorySize = 0; _centralDirectoryOffset = _offset; for (OFZIPArchiveEntry *entry in _entries) { _centralDirectorySize += [entry of_writeToStream: _stream]; _centralDirectoryEntries++; _centralDirectoryEntriesInDisk++; } /* ZIP64 end of central directory */ [_stream writeLittleEndianInt32: 0x06064B50]; [_stream writeLittleEndianInt64: 44]; /* Remaining size */ [_stream writeLittleEndianInt16: 45]; /* Version made by */ [_stream writeLittleEndianInt16: 45]; /* Version required */ [_stream writeLittleEndianInt32: _diskNumber]; [_stream writeLittleEndianInt32: _centralDirectoryDisk]; [_stream writeLittleEndianInt64: _centralDirectoryEntriesInDisk]; [_stream writeLittleEndianInt64: _centralDirectoryEntries]; [_stream writeLittleEndianInt64: _centralDirectorySize]; [_stream writeLittleEndianInt64: _centralDirectoryOffset]; /* ZIP64 end of central directory locator */ [_stream writeLittleEndianInt32: 0x07064B50]; [_stream writeLittleEndianInt32: _diskNumber]; [_stream writeLittleEndianInt64: _centralDirectoryOffset + _centralDirectorySize]; [_stream writeLittleEndianInt32: 1]; /* Total number of disks */ /* End of central directory */ [_stream writeLittleEndianInt32: 0x06054B50]; [_stream writeLittleEndianInt16: 0xFFFF]; /* Disk number */ [_stream writeLittleEndianInt16: 0xFFFF]; /* CD disk */ [_stream writeLittleEndianInt16: 0xFFFF]; /* CD entries in disk */ [_stream writeLittleEndianInt16: 0xFFFF]; /* CD entries */ [_stream writeLittleEndianInt32: 0xFFFFFFFF]; /* CD size */ [_stream writeLittleEndianInt32: 0xFFFFFFFF]; /* CD offset */ [_stream writeLittleEndianInt16: [_archiveComment UTF8StringLength]]; if (_archiveComment != nil) [_stream writeString: _archiveComment]; objc_autoreleasePoolPop(pool); } |
︙ | ︙ | |||
833 834 835 836 837 838 839 | _bytesWritten += (int64_t)length; _CRC32 = of_crc32(_CRC32, buffer, length); } - (void)close { | < < < < < < < | | < | | | > > | 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 | _bytesWritten += (int64_t)length; _CRC32 = of_crc32(_CRC32, buffer, length); } - (void)close { if (_stream == nil) return; [_stream writeLittleEndianInt32: 0x08074B50]; [_stream writeLittleEndianInt32: _CRC32]; [_stream writeLittleEndianInt64: _bytesWritten]; [_stream writeLittleEndianInt64: _bytesWritten]; [_stream release]; _stream = nil; [_entry setCRC32: ~_CRC32]; [_entry setCompressedSize: _bytesWritten]; [_entry setUncompressedSize: _bytesWritten]; [_entry makeImmutable]; _bytesWritten += (2 * 4 + 2 * 8); } @end |