// Written in the D programming language. /**Read and write data in the$(LINK2 https://en.wikipedia.org/wiki/Zip_%28file_format%29, zip archive)format. Standards: The current implementation mostly conforms to$(LINK2 https://www.iso.org/standard/60101.html, ISO/IEC 21320-1:2015),which means,$(UL$(LI that files can only be stored uncompressed or using the deflate mechanism,)$(LI that encryption features are not used,)$(LI that digital signature features are not used,)$(LI that patched data features are not used, and)$(LI that archives may not span multiple volumes.)) Additionally, archives are checked for malware attacks and rejected if detected.This includes$(UL$(LI $(LINK2 https://news.ycombinator.com/item?id=20352439, zip bombs) which generate gigantic amounts of unpacked data)$(LI zip archives that contain overlapping records)$(LI chameleon zip archives which generate different unpacked data, depending on the implementation of the unpack algorithm)) The current implementation makes use of the zlib compression library. Usage: There are two main ways of usage: Extracting files from a zip archiveand storing files into a zip archive. These can be mixed though (e.g.read an archive, remove some files, add others and write the newarchive). Examples: Example for reading an existing zip archive:---import std.stdio : writeln, writefln;import std.file : read;import std.zip; void main(string[] args){ // read a zip file into memory auto zip = new ZipArchive(read(args[1])); // iterate over all zip members writefln("%-10s %-8s Name", "Length", "CRC-32"); foreach (name, am; zip.directory) { // print some data about each member writefln("%10s %08x %s", am.expandedSize, am.crc32, name); assert(am.expandedData.length == 0); // decompress the archive member zip.expand(am); assert(am.expandedData.length == am.expandedSize); }}--- Example for writing files into a zip archive:---import std.file : write;import std.string : representation;import std.zip; void main(){ // Create an ArchiveMembers for each file. ArchiveMember file1 = new ArchiveMember(); file1.name = "test1.txt"; file1.expandedData("Test data.\n".dup.representation); file1.compressionMethod = CompressionMethod.none; // don't compress ArchiveMember file2 = new ArchiveMember(); file2.name = "test2.txt"; file2.expandedData("More test data.\n".dup.representation); file2.compressionMethod = CompressionMethod.deflate; // compress // Create an archive and add the member. ZipArchive zip = new ZipArchive(); // add ArchiveMembers zip.addMember(file1); zip.addMember(file2); // Build the archive void[] compressed_data = zip.build(); // Write to a file write("test.zip", compressed_data);}--- * Copyright: Copyright The D Language Foundation 2000 - 2009. * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). * Authors: $(HTTP digitalmars.com, Walter Bright) * Source: $(PHOBOSSRC std/zip.d) */ /* Copyright The D Language Foundation 2000 - 2009. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) */module std.zip; import std.exception : enforce; // Non-Android/Apple ARM POSIX-only, because we can't rely on the unzip// command being available on Android, Apple ARM or Windowsversion (Android) {}else version (iOS) {}else version (TVOS) {}else version (WatchOS) {}else version (Posix) version = HasUnzip; //debug=print; /// Thrown on error.class ZipException : Exception{ import std.exception : basicExceptionCtors; /// mixin basicExceptionCtors;} /// Compression method used by `ArchiveMember`.enum CompressionMethod : ushort{ none = 0, /// No compression, just archiving. deflate = 8 /// Deflate algorithm. Use zlib library to compress.} /// A single file or directory inside the archive.final class ArchiveMember{ import std.conv : to, octal; import std.datetime.systime : DosFileTime, SysTime, SysTimeToDosFileTime; /** * The name of the archive member; it is used to index the * archive directory for the member. Each member must have a * unique name. Do not change without removing member from the * directory first. */ string name; /** * The content of the extra data field for this member. See * $(LINK2 https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT, * original documentation) * for a description of the general format of this data. May contain * undocumented 3rd-party data. */ ubyte[] extra; string comment; /// Comment associated with this member. private ubyte[] _compressedData; private ubyte[] _expandedData; private uint offset; private uint _crc32; private uint _compressedSize; private uint _expandedSize; private CompressionMethod _compressionMethod; private ushort _madeVersion = 20; private ushort _extractVersion = 20; private uint _externalAttributes; private DosFileTime _time; // by default, no explicit order goes after explicit order private uint _index = uint.max; /** * Contains some information on how to extract this archive. See * $(LINK2 https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT, * original documentation) * for details. */ ushort flags; /** * Internal attributes. Bit 1 is set, if the member is apparently in binary format * and bit 2 is set, if each record is preceded by the length of the record. */ ushort internalAttributes; /** * The zip file format version needed to extract this member. * * Returns: Format version needed to extract this member. */ @property @safe pure nothrow @nogc ushort extractVersion() const { return _extractVersion; } /** * Cyclic redundancy check (CRC) value. * * Returns: CRC32 value. */ @property @safe pure nothrow @nogc uint crc32() const { return _crc32; } /** * Size of data of member in compressed form. * * Returns: Size of the compressed archive. */ @property @safe pure nothrow @nogc uint compressedSize() const { return _compressedSize; } /** * Size of data of member in uncompressed form. * * Returns: Size of uncompressed archive. */ @property @safe pure nothrow @nogc uint expandedSize() const { return _expandedSize; } /** * Data of member in compressed form. * * Returns: The file data in compressed form. */ @property @safe pure nothrow @nogc ubyte[] compressedData() { return _compressedData; } /** * Get or set data of member in uncompressed form. When an existing archive is * read `ZipArchive.expand` needs to be called before this can be accessed. * * Params: * ed = Expanded Data. * * Returns: The file data. */ @property @safe pure nothrow @nogc ubyte[] expandedData() { return _expandedData; } /// ditto @property @safe void expandedData(ubyte[] ed) { _expandedData = ed; _expandedSize = to!uint(_expandedData.length); // Clean old compressed data, if any _compressedData.length = 0; _compressedSize = 0; } /** * Get or set the OS specific file attributes for this archive member. * * Params: * attr = Attributes as obtained by $(REF getAttributes, std,file) or * $(REF DirEntry.attributes, std,file). * * Returns: The file attributes or 0 if the file attributes were * encoded for an incompatible OS (Windows vs. POSIX). */ @property @safe void fileAttributes(uint attr) { version (Posix) { _externalAttributes = (attr & 0xFFFF) << 16; _madeVersion &= 0x00FF; _madeVersion |= 0x0300; // attributes are in UNIX format } else version (Windows) { _externalAttributes = attr; _madeVersion &= 0x00FF; // attributes are in MS-DOS and OS/2 format } else { static assert(0, "Unimplemented platform"); } } version (Posix) @safe unittest { auto am = new ArchiveMember(); am.fileAttributes = octal!100644; assert(am._externalAttributes == octal!100644 << 16); assert((am._madeVersion & 0xFF00) == 0x0300); } /// ditto @property @nogc nothrow uint fileAttributes() const { version (Posix) { if ((_madeVersion & 0xFF00) == 0x0300) return _externalAttributes >> 16; return 0; } else version (Windows) { if ((_madeVersion & 0xFF00) == 0x0000) return _externalAttributes; return 0; } else { static assert(0, "Unimplemented platform"); } } /** * Get or set the last modification time for this member. * * Params: * time = Time to set (will be saved as DosFileTime, which is less accurate). * * Returns: * The last modification time in DosFileFormat. */ @property DosFileTime time() const @safe pure nothrow @nogc { return _time; } /// ditto @property void time(SysTime time) { _time = SysTimeToDosFileTime(time); } /// ditto @property void time(DosFileTime time) @safe pure nothrow @nogc { _time = time; } /** * Get or set compression method used for this member. * * Params: * cm = Compression method. * * Returns: Compression method. * * See_Also: * $(LREF CompressionMethod) **/ @property @safe @nogc pure nothrow CompressionMethod compressionMethod() const { return _compressionMethod; } /// ditto @property @safe pure void compressionMethod(CompressionMethod cm) { if (cm == _compressionMethod) return; enforce!ZipException(_compressedSize == 0, "Can't change compression method for a compressed element"); _compressionMethod = cm; } /** * The index of this archive member within the archive. Set this to a * different value for reordering the members of an archive. * * Params: * value = Index value to set. * * Returns: The index. */ @property uint index(uint value) @safe pure nothrow @nogc { return _index = value; } @property uint index() const @safe pure nothrow @nogc { return _index; } /// ditto debug(print) { void print() { printf("name = '%.*s'\n", cast(int) name.length, name.ptr); printf("\tcomment = '%.*s'\n", cast(int) comment.length, comment.ptr); printf("\tmadeVersion = x%04x\n", _madeVersion); printf("\textractVersion = x%04x\n", extractVersion); printf("\tflags = x%04x\n", flags); printf("\tcompressionMethod = %d\n", compressionMethod); printf("\ttime = %d\n", time); printf("\tcrc32 = x%08x\n", crc32); printf("\texpandedSize = %d\n", expandedSize); printf("\tcompressedSize = %d\n", compressedSize); printf("\tinternalAttributes = x%04x\n", internalAttributes); printf("\texternalAttributes = x%08x\n", externalAttributes); printf("\tindex = x%08x\n", index); } }} @safe pure unittest{ import std.exception : assertThrown, assertNotThrown; auto am = new ArchiveMember(); assertNotThrown(am.compressionMethod(CompressionMethod.deflate)); assertNotThrown(am.compressionMethod(CompressionMethod.none)); am._compressedData = [0x65]; // not strictly necessary, but for consistency am._compressedSize = 1; assertThrown!ZipException(am.compressionMethod(CompressionMethod.deflate));} /** * Object representing the entire archive. * ZipArchives are collections of ArchiveMembers. */final class ZipArchive{ import std.algorithm.comparison : max; import std.bitmanip : littleEndianToNative, nativeToLittleEndian; import std.conv : to; import std.datetime.systime : DosFileTime; private: // names are taken directly from the specification // https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT static immutable ubyte[] centralFileHeaderSignature = [ 0x50, 0x4b, 0x01, 0x02 ]; static immutable ubyte[] localFileHeaderSignature = [ 0x50, 0x4b, 0x03, 0x04 ]; static immutable ubyte[] endOfCentralDirSignature = [ 0x50, 0x4b, 0x05, 0x06 ]; static immutable ubyte[] archiveExtraDataSignature = [ 0x50, 0x4b, 0x06, 0x08 ]; static immutable ubyte[] digitalSignatureSignature = [ 0x50, 0x4b, 0x05, 0x05 ]; static immutable ubyte[] zip64EndOfCentralDirSignature = [ 0x50, 0x4b, 0x06, 0x06 ]; static immutable ubyte[] zip64EndOfCentralDirLocatorSignature = [ 0x50, 0x4b, 0x06, 0x07 ]; enum centralFileHeaderLength = 46; enum localFileHeaderLength = 30; enum endOfCentralDirLength = 22; enum archiveExtraDataLength = 8; enum digitalSignatureLength = 6; enum zip64EndOfCentralDirLength = 56; enum zip64EndOfCentralDirLocatorLength = 20; enum dataDescriptorLength = 12; public: string comment; /// The archive comment. Must be less than 65536 bytes in length. private ubyte[] _data; private bool _isZip64; static const ushort zip64ExtractVersion = 45; private Segment[] _segs; /** * Array representing the entire contents of the archive. * * Returns: Data of the entire contents of the archive. */ @property @safe @nogc pure nothrow ubyte[] data() { return _data; } /** * Number of ArchiveMembers in the directory. * * Returns: The number of files in this archive. */ @property @safe @nogc pure nothrow uint totalEntries() const { return cast(uint) _directory.length; } /** * True when the archive is in Zip64 format. Set this to true to force building a Zip64 archive. * * Params: * value = True, when the archive is forced to be build in Zip64 format. * * Returns: True, when the archive is in Zip64 format. */ @property @safe @nogc pure nothrow bool isZip64() const { return _isZip64; } /// ditto @property @safe @nogc pure nothrow void isZip64(bool value) { _isZip64 = value; } /** * Associative array indexed by the name of each member of the archive. * * All the members of the archive can be accessed with a foreach loop: * * Example: * -------------------- * ZipArchive archive = new ZipArchive(data); * foreach (ArchiveMember am; archive.directory) * { * writefln("member name is '%s'", am.name); * } * -------------------- * * Returns: Associative array with all archive members. */ @property @safe @nogc pure nothrow ArchiveMember[string] directory() { return _directory; } private ArchiveMember[string] _directory; debug (print) { @safe void print() { printf("\tdiskNumber = %u\n", diskNumber);Lines 1–500 of 1710. Load more
// Written in the D programming language. /** Read and write data in the $(LINK2 https://en.wikipedia.org/wiki/Zip_%28file_format%29, zip archive) format. Standards: The current implementation mostly conforms to $(LINK2 https://www.iso.org/standard/60101.html, ISO/IEC 21320-1:2015), which means, $(UL $(LI that files can only be stored uncompressed or using the deflate mechanism,) $(LI that encryption features are not used,) $(LI that digital signature features are not used,) $(LI that patched data features are not used, and) $(LI that archives may not span multiple volumes.) ) Additionally, archives are checked for malware attacks and rejected if detected. This includes $(UL $(LI $(LINK2 https://news.ycombinator.com/item?id=20352439, zip bombs) which generate gigantic amounts of unpacked data) $(LI zip archives that contain overlapping records) $(LI chameleon zip archives which generate different unpacked data, depending on the implementation of the unpack algorithm) ) The current implementation makes use of the zlib compression library. Usage: There are two main ways of usage: Extracting files from a zip archive and storing files into a zip archive. These can be mixed though (e.g. read an archive, remove some files, add others and write the new archive). Examples: Example for reading an existing zip archive: --- import std.stdio : writeln, writefln; import std.file : read; import std.zip; void main(string[] args) { // read a zip file into memory auto zip = new ZipArchive(read(args[1])); // iterate over all zip members writefln("%-10s %-8s Name", "Length", "CRC-32"); foreach (name, am; zip.directory) { // print some data about each member writefln("%10s %08x %s", am.expandedSize, am.crc32, name); assert(am.expandedData.length == 0); // decompress the archive member zip.expand(am); assert(am.expandedData.length == am.expandedSize); } } --- Example for writing files into a zip archive: --- import std.file : write; import std.string : representation; import std.zip; void main() { // Create an ArchiveMembers for each file. ArchiveMember file1 = new ArchiveMember(); file1.name = "test1.txt"; file1.expandedData("Test data.\n".dup.representation); file1.compressionMethod = CompressionMethod.none; // don't compress ArchiveMember file2 = new ArchiveMember(); file2.name = "test2.txt"; file2.expandedData("More test data.\n".dup.representation); file2.compressionMethod = CompressionMethod.deflate; // compress // Create an archive and add the member. ZipArchive zip = new ZipArchive(); // add ArchiveMembers zip.addMember(file1); zip.addMember(file2); // Build the archive void[] compressed_data = zip.build(); // Write to a file write("test.zip", compressed_data); } --- * Copyright: Copyright The D Language Foundation 2000 - 2009. * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). * Authors: $(HTTP digitalmars.com, Walter Bright) * Source: $(PHOBOSSRC std/zip.d) */ /* Copyright The D Language Foundation 2000 - 2009. * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) */ module std.zip; import std.exception : enforce; // Non-Android/Apple ARM POSIX-only, because we can't rely on the unzip // command being available on Android, Apple ARM or Windows version (Android) {} else version (iOS) {} else version (TVOS) {} else version (WatchOS) {} else version (Posix) version = HasUnzip; //debug=print; /// Thrown on error. class ZipException : Exception { import std.exception : basicExceptionCtors; /// mixin basicExceptionCtors; } /// Compression method used by `ArchiveMember`. enum CompressionMethod : ushort { none = 0, /// No compression, just archiving. deflate = 8 /// Deflate algorithm. Use zlib library to compress. } /// A single file or directory inside the archive. final class ArchiveMember { import std.conv : to, octal; import std.datetime.systime : DosFileTime, SysTime, SysTimeToDosFileTime; /** * The name of the archive member; it is used to index the * archive directory for the member. Each member must have a * unique name. Do not change without removing member from the * directory first. */ string name; /** * The content of the extra data field for this member. See * $(LINK2 https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT, * original documentation) * for a description of the general format of this data. May contain * undocumented 3rd-party data. */ ubyte[] extra; string comment; /// Comment associated with this member. private ubyte[] _compressedData; private ubyte[] _expandedData; private uint offset; private uint _crc32; private uint _compressedSize; private uint _expandedSize; private CompressionMethod _compressionMethod; private ushort _madeVersion = 20; private ushort _extractVersion = 20; private uint _externalAttributes; private DosFileTime _time; // by default, no explicit order goes after explicit order private uint _index = uint.max; /** * Contains some information on how to extract this archive. See * $(LINK2 https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT, * original documentation) * for details. */ ushort flags; /** * Internal attributes. Bit 1 is set, if the member is apparently in binary format * and bit 2 is set, if each record is preceded by the length of the record. */ ushort internalAttributes; /** * The zip file format version needed to extract this member. * * Returns: Format version needed to extract this member. */ @property @safe pure nothrow @nogc ushort extractVersion() const { return _extractVersion; } /** * Cyclic redundancy check (CRC) value. * * Returns: CRC32 value. */ @property @safe pure nothrow @nogc uint crc32() const { return _crc32; } /** * Size of data of member in compressed form. * * Returns: Size of the compressed archive. */ @property @safe pure nothrow @nogc uint compressedSize() const { return _compressedSize; } /** * Size of data of member in uncompressed form. * * Returns: Size of uncompressed archive. */ @property @safe pure nothrow @nogc uint expandedSize() const { return _expandedSize; } /** * Data of member in compressed form. * * Returns: The file data in compressed form. */ @property @safe pure nothrow @nogc ubyte[] compressedData() { return _compressedData; } /** * Get or set data of member in uncompressed form. When an existing archive is * read `ZipArchive.expand` needs to be called before this can be accessed. * * Params: * ed = Expanded Data. * * Returns: The file data. */ @property @safe pure nothrow @nogc ubyte[] expandedData() { return _expandedData; } /// ditto @property @safe void expandedData(ubyte[] ed) { _expandedData = ed; _expandedSize = to!uint(_expandedData.length); // Clean old compressed data, if any _compressedData.length = 0; _compressedSize = 0; } /** * Get or set the OS specific file attributes for this archive member. * * Params: * attr = Attributes as obtained by $(REF getAttributes, std,file) or * $(REF DirEntry.attributes, std,file). * * Returns: The file attributes or 0 if the file attributes were * encoded for an incompatible OS (Windows vs. POSIX). */ @property @safe void fileAttributes(uint attr) { version (Posix) { _externalAttributes = (attr & 0xFFFF) << 16; _madeVersion &= 0x00FF; _madeVersion |= 0x0300; // attributes are in UNIX format } else version (Windows) { _externalAttributes = attr; _madeVersion &= 0x00FF; // attributes are in MS-DOS and OS/2 format } else { static assert(0, "Unimplemented platform"); } } version (Posix) @safe unittest { auto am = new ArchiveMember(); am.fileAttributes = octal!100644; assert(am._externalAttributes == octal!100644 << 16); assert((am._madeVersion & 0xFF00) == 0x0300); } /// ditto @property @nogc nothrow uint fileAttributes() const { version (Posix) { if ((_madeVersion & 0xFF00) == 0x0300) return _externalAttributes >> 16; return 0; } else version (Windows) { if ((_madeVersion & 0xFF00) == 0x0000) return _externalAttributes; return 0; } else { static assert(0, "Unimplemented platform"); } } /** * Get or set the last modification time for this member. * * Params: * time = Time to set (will be saved as DosFileTime, which is less accurate). * * Returns: * The last modification time in DosFileFormat. */ @property DosFileTime time() const @safe pure nothrow @nogc { return _time; } /// ditto @property void time(SysTime time) { _time = SysTimeToDosFileTime(time); } /// ditto @property void time(DosFileTime time) @safe pure nothrow @nogc { _time = time; } /** * Get or set compression method used for this member. * * Params: * cm = Compression method. * * Returns: Compression method. * * See_Also: * $(LREF CompressionMethod) **/ @property @safe @nogc pure nothrow CompressionMethod compressionMethod() const { return _compressionMethod; } /// ditto @property @safe pure void compressionMethod(CompressionMethod cm) { if (cm == _compressionMethod) return; enforce!ZipException(_compressedSize == 0, "Can't change compression method for a compressed element"); _compressionMethod = cm; } /** * The index of this archive member within the archive. Set this to a * different value for reordering the members of an archive. * * Params: * value = Index value to set. * * Returns: The index. */ @property uint index(uint value) @safe pure nothrow @nogc { return _index = value; } @property uint index() const @safe pure nothrow @nogc { return _index; } /// ditto debug(print) { void print() { printf("name = '%.*s'\n", cast(int) name.length, name.ptr); printf("\tcomment = '%.*s'\n", cast(int) comment.length, comment.ptr); printf("\tmadeVersion = x%04x\n", _madeVersion); printf("\textractVersion = x%04x\n", extractVersion); printf("\tflags = x%04x\n", flags); printf("\tcompressionMethod = %d\n", compressionMethod); printf("\ttime = %d\n", time); printf("\tcrc32 = x%08x\n", crc32); printf("\texpandedSize = %d\n", expandedSize); printf("\tcompressedSize = %d\n", compressedSize); printf("\tinternalAttributes = x%04x\n", internalAttributes); printf("\texternalAttributes = x%08x\n", externalAttributes); printf("\tindex = x%08x\n", index); } } } @safe pure unittest { import std.exception : assertThrown, assertNotThrown; auto am = new ArchiveMember(); assertNotThrown(am.compressionMethod(CompressionMethod.deflate)); assertNotThrown(am.compressionMethod(CompressionMethod.none)); am._compressedData = [0x65]; // not strictly necessary, but for consistency am._compressedSize = 1; assertThrown!ZipException(am.compressionMethod(CompressionMethod.deflate)); } /** * Object representing the entire archive. * ZipArchives are collections of ArchiveMembers. */ final class ZipArchive { import std.algorithm.comparison : max; import std.bitmanip : littleEndianToNative, nativeToLittleEndian; import std.conv : to; import std.datetime.systime : DosFileTime; private: // names are taken directly from the specification // https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT static immutable ubyte[] centralFileHeaderSignature = [ 0x50, 0x4b, 0x01, 0x02 ]; static immutable ubyte[] localFileHeaderSignature = [ 0x50, 0x4b, 0x03, 0x04 ]; static immutable ubyte[] endOfCentralDirSignature = [ 0x50, 0x4b, 0x05, 0x06 ]; static immutable ubyte[] archiveExtraDataSignature = [ 0x50, 0x4b, 0x06, 0x08 ]; static immutable ubyte[] digitalSignatureSignature = [ 0x50, 0x4b, 0x05, 0x05 ]; static immutable ubyte[] zip64EndOfCentralDirSignature = [ 0x50, 0x4b, 0x06, 0x06 ]; static immutable ubyte[] zip64EndOfCentralDirLocatorSignature = [ 0x50, 0x4b, 0x06, 0x07 ]; enum centralFileHeaderLength = 46; enum localFileHeaderLength = 30; enum endOfCentralDirLength = 22; enum archiveExtraDataLength = 8; enum digitalSignatureLength = 6; enum zip64EndOfCentralDirLength = 56; enum zip64EndOfCentralDirLocatorLength = 20; enum dataDescriptorLength = 12; public: string comment; /// The archive comment. Must be less than 65536 bytes in length. private ubyte[] _data; private bool _isZip64; static const ushort zip64ExtractVersion = 45; private Segment[] _segs; /** * Array representing the entire contents of the archive. * * Returns: Data of the entire contents of the archive. */ @property @safe @nogc pure nothrow ubyte[] data() { return _data; } /** * Number of ArchiveMembers in the directory. * * Returns: The number of files in this archive. */ @property @safe @nogc pure nothrow uint totalEntries() const { return cast(uint) _directory.length; } /** * True when the archive is in Zip64 format. Set this to true to force building a Zip64 archive. * * Params: * value = True, when the archive is forced to be build in Zip64 format. * * Returns: True, when the archive is in Zip64 format. */ @property @safe @nogc pure nothrow bool isZip64() const { return _isZip64; } /// ditto @property @safe @nogc pure nothrow void isZip64(bool value) { _isZip64 = value; } /** * Associative array indexed by the name of each member of the archive. * * All the members of the archive can be accessed with a foreach loop: * * Example: * -------------------- * ZipArchive archive = new ZipArchive(data); * foreach (ArchiveMember am; archive.directory) * { * writefln("member name is '%s'", am.name); * } * -------------------- * * Returns: Associative array with all archive members. */ @property @safe @nogc pure nothrow ArchiveMember[string] directory() { return _directory; } private ArchiveMember[string] _directory; debug (print) { @safe void print() { printf("\tdiskNumber = %u\n", diskNumber);