diff --git a/Zip/Makefile b/Zip/Makefile new file mode 100644 index 000000000..15c306fcb --- /dev/null +++ b/Zip/Makefile @@ -0,0 +1,20 @@ +# +# Makefile +# +# $Id: //poco/1.3/Zip/Makefile#2 $ +# +# Makefile for Poco Zip +# + +include $(POCO_BASE)/build/rules/global + +objects = AutoDetectStream Compress Decompress ParseCallback PartialStream \ + SkipCallback ZipArchive ZipArchiveInfo ZipDataInfo \ + ZipFileInfo ZipLocalFileHeader ZipStream ZipUtil ZipCommon ZipException \ + Add Delete Keep Rename Replace ZipManipulator ZipOperation + +target = PocoZip +target_version = $(LIBVERSION) +target_libs = PocoFoundation + +include $(POCO_BASE)/build/rules/lib diff --git a/Zip/Zip.vmsbuild b/Zip/Zip.vmsbuild new file mode 100644 index 000000000..ea37adebb --- /dev/null +++ b/Zip/Zip.vmsbuild @@ -0,0 +1,16 @@ +# +# Zip.vmsbuild +# +# $Id: //poco/1.3/Zip/Zip.vmsbuild#1 $ +# +LIB=PocoZip +Decompress +ParseCallback +PartialStream +SkipCallback +ZipArchive +ZipArchiveInfo +ZipFileInfo +ZipLocalFileHeader +ZipStream +ZipUtil diff --git a/Zip/Zip_VS71.sln b/Zip/Zip_VS71.sln new file mode 100644 index 000000000..66ded41b4 --- /dev/null +++ b/Zip/Zip_VS71.sln @@ -0,0 +1,30 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Zip", "Zip_VS71.vcproj", "{4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSuite", "testsuite\TestSuite_VS71.vcproj", "{9665FC3C-DB71-4C6C-AAEE-AAFD73CB31E7}" + ProjectSection(ProjectDependencies) = postProject + {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61} = {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + debug_shared = debug_shared + release_shared = release_shared + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61}.debug_shared.ActiveCfg = debug_shared|Win32 + {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61}.debug_shared.Build.0 = debug_shared|Win32 + {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61}.release_shared.ActiveCfg = release_shared|Win32 + {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61}.release_shared.Build.0 = release_shared|Win32 + {9665FC3C-DB71-4C6C-AAEE-AAFD73CB31E7}.debug_shared.ActiveCfg = debug_shared|Win32 + {9665FC3C-DB71-4C6C-AAEE-AAFD73CB31E7}.debug_shared.Build.0 = debug_shared|Win32 + {9665FC3C-DB71-4C6C-AAEE-AAFD73CB31E7}.release_shared.ActiveCfg = release_shared|Win32 + {9665FC3C-DB71-4C6C-AAEE-AAFD73CB31E7}.release_shared.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/Zip/Zip_VS71.vcproj b/Zip/Zip_VS71.vcproj new file mode 100644 index 000000000..077ed6b97 --- /dev/null +++ b/Zip/Zip_VS71.vcproj @@ -0,0 +1,307 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Zip/Zip_VS80.sln b/Zip/Zip_VS80.sln new file mode 100644 index 000000000..26b7d8bcc --- /dev/null +++ b/Zip/Zip_VS80.sln @@ -0,0 +1,28 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Zip", "Zip_VS80.vcproj", "{4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSuite", "testsuite\TestSuite_VS80.vcproj", "{9665FC3C-DB71-4C6C-AAEE-AAFD73CB31E7}" + ProjectSection(ProjectDependencies) = postProject + {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61} = {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + debug_shared|Win32 = debug_shared|Win32 + release_shared|Win32 = release_shared|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61}.release_shared|Win32.Build.0 = release_shared|Win32 + {9665FC3C-DB71-4C6C-AAEE-AAFD73CB31E7}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {9665FC3C-DB71-4C6C-AAEE-AAFD73CB31E7}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {9665FC3C-DB71-4C6C-AAEE-AAFD73CB31E7}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {9665FC3C-DB71-4C6C-AAEE-AAFD73CB31E7}.release_shared|Win32.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Zip/Zip_VS80.vcproj b/Zip/Zip_VS80.vcproj new file mode 100644 index 000000000..c3afe3872 --- /dev/null +++ b/Zip/Zip_VS80.vcproj @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Zip/Zip_vs90.sln b/Zip/Zip_vs90.sln new file mode 100644 index 000000000..94fbc6121 --- /dev/null +++ b/Zip/Zip_vs90.sln @@ -0,0 +1,28 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Zip", "Zip_vs90.vcproj", "{4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSuite", "testsuite\TestSuite_vs90.vcproj", "{9665FC3C-DB71-4C6C-AAEE-AAFD73CB31E7}" + ProjectSection(ProjectDependencies) = postProject + {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61} = {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + debug_shared|Win32 = debug_shared|Win32 + release_shared|Win32 = release_shared|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {4AC75EAD-BFCF-41E6-AB1F-0DA203CC7C61}.release_shared|Win32.Build.0 = release_shared|Win32 + {9665FC3C-DB71-4C6C-AAEE-AAFD73CB31E7}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {9665FC3C-DB71-4C6C-AAEE-AAFD73CB31E7}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {9665FC3C-DB71-4C6C-AAEE-AAFD73CB31E7}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {9665FC3C-DB71-4C6C-AAEE-AAFD73CB31E7}.release_shared|Win32.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Zip/Zip_vs90.vcproj b/Zip/Zip_vs90.vcproj new file mode 100644 index 000000000..5089c0d59 --- /dev/null +++ b/Zip/Zip_vs90.vcproj @@ -0,0 +1,413 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Zip/dependencies b/Zip/dependencies new file mode 100644 index 000000000..5242bc4e0 --- /dev/null +++ b/Zip/dependencies @@ -0,0 +1,4 @@ +Foundation +Net +Util +XML diff --git a/Zip/doc/ZIP Spec.txt b/Zip/doc/ZIP Spec.txt new file mode 100644 index 000000000..4fe38584f --- /dev/null +++ b/Zip/doc/ZIP Spec.txt @@ -0,0 +1,1636 @@ +[Info-ZIP note, 970311: this file is based on PKWARE's appnote.txt of + 15 February 1996. It has been unofficially corrected and extended by + Info-ZIP without explicit permission by PKWARE. Although Info-ZIP + believes the information to be accurate and complete, it is provided + under a disclaimer similar to the PKWARE disclaimer below, differing + only in the substitution of "Info-ZIP" for "PKWARE". In other words, + use this information at your own risk, but we think it's correct. As + of PKZIPW 2.50, two new incompatibilities have been introduced by PKWARE; + they are noted below. Note that the NTFS "conflict" is currently not + real; PKZIPW 2.50 actually tags NTFS files as having come from a FAT + file system, too.] + + +Disclaimer +---------- + +Although PKWARE will attempt to supply current and accurate +information relating to its file formats, algorithms, and the +subject programs, the possibility of error can not be eliminated. +PKWARE therefore expressly disclaims any warranty that the +information contained in the associated materials relating to the +subject programs and/or the format of the files created or +accessed by the subject programs and/or the algorithms used by +the subject programs, or any other matter, is current, correct or +accurate as delivered. Any risk of damage due to any possible +inaccurate information is assumed by the user of the information. +Furthermore, the information relating to the subject programs +and/or the file formats created or accessed by the subject +programs and/or the algorithms used by the subject programs is +subject to change without notice. + + +General Format of a ZIP file +---------------------------- + + Files stored in arbitrary order. Large zipfiles can span multiple + diskette media. + + Overall zipfile format: + + [local file header + file data + data_descriptor] . . . + [central directory] end of central directory record + + + A. Local file header: + + local file header signature 4 bytes (0x04034b50) + version needed to extract 2 bytes + general purpose bit flag 2 bytes + compression method 2 bytes + last mod file time 2 bytes + last mod file date 2 bytes + crc-32 4 bytes + compressed size 4 bytes + uncompressed size 4 bytes + filename length 2 bytes + extra field length 2 bytes + + filename (variable size) + extra field (variable size) + + + B. Data descriptor: + + data descriptor signature 4 bytes (0x08074b50) + crc-32 4 bytes + compressed size 4 bytes + uncompressed size 4 bytes + + This descriptor exists only if bit 3 of the general + purpose bit flag is set (see below). It is byte aligned + and immediately follows the last byte of compressed data. + This descriptor is used only when it was not possible to + seek in the output zip file, e.g., when the output zip file + was standard output or a non seekable device. + + C. Central directory structure: + + [file header] . . . end of central dir record + + File header: + + central file header signature 4 bytes (0x02014b50) + version made by 2 bytes + version needed to extract 2 bytes + general purpose bit flag 2 bytes + compression method 2 bytes + last mod file time 2 bytes + last mod file date 2 bytes + crc-32 4 bytes + compressed size 4 bytes + uncompressed size 4 bytes + filename length 2 bytes + extra field length 2 bytes + file comment length 2 bytes + disk number start 2 bytes + internal file attributes 2 bytes + external file attributes 4 bytes + relative offset of local header 4 bytes + + filename (variable size) + extra field (variable size) + file comment (variable size) + + End of central dir record: + + end of central dir signature 4 bytes (0x06054b50) + number of this disk 2 bytes + number of the disk with the + start of the central directory 2 bytes + total number of entries in + the central dir on this disk 2 bytes + total number of entries in + the central dir 2 bytes + size of the central directory 4 bytes + offset of start of central + directory with respect to + the starting disk number 4 bytes + zipfile comment length 2 bytes + zipfile comment (variable size) + + + D. Explanation of fields: + + version made by (2 bytes) + + The upper byte indicates the host system (OS) for the + file. Software can use this information to determine + the line record format for text files etc. The current + mappings are: + + 0 - FAT file system (DOS, OS/2, NT) + PKZIPW 2.50 VFAT, NTFS + 1 - Amiga + 2 - VMS (VAX or Alpha AXP) + 3 - Unix + 4 - VM/CMS + 5 - Atari + 6 - HPFS file system (OS/2, NT 3.x) + 7 - Macintosh + 8 - Z-System + 9 - CP/M + 10 - TOPS-20 [supposedly PKZIPW 2.50 NTFS] + 11 - NTFS file system (NT) + 12 - SMS/QDOS + 13 - Acorn RISC OS + 14 - VFAT file system (Win95, NT) + 15 - MVS + 16 - BeOS (BeBox or PowerMac) + 17 - Tandem + 18 thru 255 - unused + + The lower byte indicates the version number of the + software used to encode the file. The value/10 + indicates the major version number, and the value + mod 10 is the minor version number. + + version needed to extract (2 bytes) + + The minimum software version needed to extract the + file, mapped as above. + + general purpose bit flag: (2 bytes) + + bit 0: If set, indicates that the file is encrypted. + + (For Method 6 - Imploding) + bit 1: If the compression method used was type 6, + Imploding, then this bit, if set, indicates + an 8K sliding dictionary was used. If clear, + then a 4K sliding dictionary was used. + bit 2: If the compression method used was type 6, + Imploding, then this bit, if set, indicates + an 3 Shannon-Fano trees were used to encode the + sliding dictionary output. If clear, then 2 + Shannon-Fano trees were used. + + (For Method 8 - Deflating) + bit 2 bit 1 + 0 0 Normal (-en) compression option was used. + 0 1 Maximum (-ex) compression option was used. + 1 0 Fast (-ef) compression option was used. + 1 1 Super Fast (-es) compression option was used. + + Note: Bits 1 and 2 are undefined if the compression + method is any other. + + (For method 8) + bit 3: If this bit is set, the fields crc-32, compressed size + and uncompressed size are set to zero in the local + header. The correct values are put in the data descriptor + immediately following the compressed data. + + The upper three bits are reserved and used internally + by the software when processing the zipfile. The + remaining bits are unused. + + compression method: (2 bytes) + + (see accompanying documentation for algorithm + descriptions) + + 0 - The file is stored (no compression) + 1 - The file is Shrunk + 2 - The file is Reduced with compression factor 1 + 3 - The file is Reduced with compression factor 2 + 4 - The file is Reduced with compression factor 3 + 5 - The file is Reduced with compression factor 4 + 6 - The file is Imploded + 7 - Reserved for Tokenizing compression algorithm + 8 - The file is Deflated + 9 - Reserved for enhanced Deflating + 10 - PKWARE Date Compression Library Imploding + + date and time fields: (2 bytes each) + + The date and time are encoded in standard MS-DOS format. + If input came from standard input, the date and time are + those at which compression was started for this data. + + CRC-32: (4 bytes) + + The CRC-32 algorithm was generously contributed by + David Schwaderer and can be found in his excellent + book "C Programmers Guide to NetBIOS" published by + Howard W. Sams & Co. Inc. The 'magic number' for + the CRC is 0xdebb20e3. The proper CRC pre and post + conditioning is used, meaning that the CRC register + is pre-conditioned with all ones (a starting value + of 0xffffffff) and the value is post-conditioned by + taking the one's complement of the CRC residual. + If bit 3 of the general purpose flag is set, this + field is set to zero in the local header and the correct + value is put in the data descriptor and in the central + directory. + + compressed size: (4 bytes) + uncompressed size: (4 bytes) + + The size of the file compressed and uncompressed, + respectively. If bit 3 of the general purpose bit flag + is set, these fields are set to zero in the local header + and the correct values are put in the data descriptor and + in the central directory. + + filename length: (2 bytes) + extra field length: (2 bytes) + file comment length: (2 bytes) + + The length of the filename, extra field, and comment + fields respectively. The combined length of any + directory record and these three fields should not + generally exceed 65,535 bytes. If input came from + standard input, the filename is set to "-" (length one). + + + disk number start: (2 bytes) + + The number of the disk on which this file begins. + + internal file attributes: (2 bytes) + + The lowest bit of this field indicates, if set, that + the file is apparently an ASCII or text file. If not + set, that the file apparently contains binary data. + The remaining bits are unused in version 1.0. + + external file attributes: (4 bytes) + + The mapping of the external attributes is + host-system dependent (see 'version made by'). For + MS-DOS, the low order byte is the MS-DOS directory + attribute byte. If input came from standard input, this + field is set to zero. + + relative offset of local header: (4 bytes) + + This is the offset from the start of the first disk on + which this file appears, to where the local header should + be found. + + filename: (Variable) + + The name of the file, with optional relative path. + The path stored should not contain a drive or + device letter, or a leading slash. All slashes + should be forward slashes '/' as opposed to + backwards slashes '\' for compatibility with Amiga + and Unix file systems etc. If input came from standard + input, the file name is set to "-" (without the quotes). + + extra field: (Variable) + + This is for future expansion. If additional information + needs to be stored in the future, it should be stored + here. Earlier versions of the software can then safely + skip this file, and find the next file or header. This + field will be 0 length in version 1.0. + + In order to allow different programs and different types + of information to be stored in the 'extra' field in .ZIP + files, the following structure should be used for all + programs storing data in this field: + + header1+data1 + header2+data2 . . . + + Each header should consist of: + + Header ID - 2 bytes + Data Size - 2 bytes + + Note: all fields stored in Intel low-byte/high-byte order. + + The Header ID field indicates the type of data that is in + the following data block. + + Header ID's of 0 thru 31 are reserved for use by PKWARE. + The remaining ID's can be used by third party vendors for + proprietary usage. + + The current Header ID mappings are: + + 0x0007 AV Info + 0x0009 OS/2 extended attributes + 0x000c PKWARE VAX/VMS + 0x000d reserved for Unix + 0x07c8 Info-ZIP Macintosh + 0x2605 ZipIt Macintosh + 0x4341 Acorn/SparkFS (David Pilling) + 0x4453 Windows NT security descriptor (binary ACL) + 0x4704 VM/CMS + 0x470f MVS + 0x4b46 FWKCS MD5 (third party, see below) + 0x4c41 OS/2 access control list (text ACL) + 0x4d49 Info-ZIP VMS (VAX or Alpha) + 0x5356 AOS/VS (binary ACL) + 0x5455 extended timestamp + 0x5855 Info-ZIP Unix (original; also OS/2, NT, etc.) + 0x6542 BeOS (BeBox, PowerMac, etc.) + 0x756e ASi Unix + 0x7855 Info-ZIP Unix (new) + 0xfb4a SMS/QDOS + + The Data Size field indicates the size of the following + data block. Programs can use this value to skip to the + next header block, passing over any data blocks that are + not of interest. + + Note: As stated above, the size of the entire .ZIP file + header, including the filename, comment, and extra + field should not exceed 64K in size. + + In case two different programs should appropriate the same + Header ID value, it is strongly recommended that each + program place a unique signature of at least two bytes in + size (and preferably 4 bytes or bigger) at the start of + each data area. Every program should verify that its + unique signature is present, in addition to the Header ID + value being correct, before assuming that it is a block of + known type. + + In the following descriptions, note that "Short" means two bytes + and "Long" means four bytes, regardless of their native sizes. + + + -OS/2 Extended Attributes Extra Field: + ==================================== + + The following is the layout of the OS/2 extended attributes "extra" + block. (Last Revision 960922) + + Note: all fields stored in Intel low-byte/high-byte order. + + Local-header version: + + Value Size Description + ----- ---- ----------- + (OS/2) 0x0009 Short tag for this extra block type + TSize Short total data size for this block + BSize Long uncompressed EA data size + CType Short compression type + EACRC Long CRC value for uncompressed EA data + (var.) variable compressed EA data + + Central-header version: + + Value Size Description + ----- ---- ----------- + (OS/2) 0x0009 Short tag for this extra block type + TSize Short total data size for this block + BSize Long size of uncompressed local EA data + + The value of CType is interpreted according to the "compression + method" section above; i.e., 0 for stored, 8 for deflated, etc. + + The OS/2 extended attribute structure (FEA2LIST) is compressed and + then stored in its entirety within this structure. There will only + ever be one block of data in the variable-length field. + + + -OS/2 Access Control List Extra Field: + ==================================== + + The following is the layout of the OS/2 ACL extra block. + (Last Revision 960922) + + Local-header version: + + Value Size Description + ----- ---- ----------- + (ACL) 0x4c41 Short tag for this extra block type + TSize Short total data size for this block + BSize Long uncompressed ACL data size + CType Short compression type + EACRC Long CRC value for uncompressed ACL data + (var.) variable compressed ACL data + + Central-header version: + + Value Size Description + ----- ---- ----------- + (ACL) 0x4c41 Short tag for this extra block type + TSize Short total data size for this block + BSize Long size of uncompressed local ACL data + + The value of CType is interpreted according to the "compression + method" section above; i.e., 0 for stored, 8 for deflated, etc. + + The uncompressed ACL data consist of a text header of the form + "ACL1:%hX,%hd\n", where the first field is the OS/2 ACCINFO acc_attr + member and the second is acc_count, followed by acc_count strings + of the form "%s,%hx\n", where the first field is acl_ugname (user + group name) and the second acl_access. This block type will be + extended for other operating systems as needed. + + + -Windows NT Security Descriptor Extra Field: + ========================================== + + The following is the layout of the NT Security Descriptor (another + type of ACL) extra block. (Last Revision 960922) + + Local-header version: + + Value Size Description + ----- ---- ----------- + (SD) 0x4453 Short tag for this extra block type + TSize Short total data size for this block + BSize Long uncompressed SD data size + Version Byte version of uncompressed SD data format + CType Short compression type + EACRC Long CRC value for uncompressed SD data + (var.) variable compressed SD data + + Central-header version: + + Value Size Description + ----- ---- ----------- + (SD) 0x4453 Short tag for this extra block type + TSize Short total data size for this block + BSize Long size of uncompressed local SD data + Version Byte version of uncompressed SD data format + + The value of CType is interpreted according to the "compression + method" section above; i.e., 0 for stored, 8 for deflated, etc. + Version specifies how the compressed data are to be interpreted + and allows for future expansion of this extra field type. Currently + only version 0 is defined. + + For version 0, the compressed data are to be interpreted as a single + valid Windows NT SECURITY_DESCRIPTOR data structure, in self-relative + format. + + + -PKWARE VAX/VMS Extra Field: + ========================== + + The following is the layout of PKWARE's VAX/VMS attributes "extra" + block. (Last Revision 12/17/91) + + Note: all fields stored in Intel low-byte/high-byte order. + + Value Size Description + ----- ---- ----------- + (VMS) 0x000c Short Tag for this "extra" block type + TSize Short Total Data Size for this block + CRC Long 32-bit CRC for remainder of the block + Tag1 Short VMS attribute tag value #1 + Size1 Short Size of attribute #1, in bytes + (var.) Size1 Attribute #1 data + . + . + . + TagN Short VMS attribute tage value #N + SizeN Short Size of attribute #N, in bytes + (var.) SizeN Attribute #N data + + Rules: + + 1. There will be one or more of attributes present, which will + each be preceded by the above TagX & SizeX values. These + values are identical to the ATR$C_XXXX and ATR$S_XXXX constants + which are defined in ATR.H under VMS C. Neither of these values + will ever be zero. + + 2. No word alignment or padding is performed. + + 3. A well-behaved PKZIP/VMS program should never produce more than + one sub-block with the same TagX value. Also, there will never + be more than one "extra" block of type 0x000c in a particular + directory record. + + + -Info-ZIP VMS Extra Field: + ======================== + + The following is the layout of Info-ZIP's VMS attributes extra + block for VAX or Alpha AXP. The local-header and central-header + versions are identical. (Last Revision 960922) + + Value Size Description + ----- ---- ----------- + (VMS2) 0x4d49 Short tag for this extra block type + TSize Short total data size for this block + ID Long block ID + Flags Short info bytes + BSize Short uncompressed block size + Reserved Long (reserved) + (var.) variable compressed VMS file-attributes block + + The block ID is one of the following unterminated strings: + + "VFAB" struct FAB + "VALL" struct XABALL + "VFHC" struct XABFHC + "VDAT" struct XABDAT + "VRDT" struct XABRDT + "VPRO" struct XABPRO + "VKEY" struct XABKEY + "VMSV" version (e.g., "V6.1"; truncated at hyphen) + "VNAM" reserved + + The lower three bits of Flags indicate the compression method. The + currently defined methods are: + + 0 stored (not compressed) + 1 simple "RLE" + 2 deflated + + The "RLE" method simply replaces zero-valued bytes with zero-valued + bits and non-zero-valued bytes with a "1" bit followed by the byte + value. + + The variable-length compressed data contains only the data corre- + sponding to the indicated structure or string. Typically multiple + VMS2 extra fields are present (each with a unique block type). + + + -Info-ZIP Macintosh Extra Field: + ============================== + + The following is the layout of the (old) Info-ZIP resource-fork extra + block for Macintosh. The local-header and central-header versions + are identical. (Last Revision 960922) + + Value Size Description + ----- ---- ----------- + (Mac) 0x07c8 Short tag for this extra block type + TSize Short total data size for this block + "JLEE" beLong extra-field signature + FInfo 16 bytes Macintosh FInfo structure + CrDat beLong HParamBlockRec fileParam.ioFlCrDat + MdDat beLong HParamBlockRec fileParam.ioFlMdDat + Flags beLong info bits + DirID beLong HParamBlockRec fileParam.ioDirID + VolName 28 bytes volume name (optional) + + All fields but the first two are in native Macintosh format + (big-endian Motorola order, not little-endian Intel). The least + significant bit of Flags is 1 if the file is a data fork, 0 other- + wise. In addition, if this extra field is present, the filename + has an extra 'd' or 'r' appended to indicate data fork or resource + fork. The 28-byte VolName field may be omitted. + + + -ZipIt Macintosh Extra Field: + =========================== + + The following is the layout of the ZipIt extra block for Macintosh. + The local-header and central-header versions are identical. + (Last Revision 970130) + + Value Size Description + ----- ---- ----------- + (Mac2) 0x2605 Short tag for this extra block type + TSize Short total data size for this block + "ZPIT" beLong extra-field signature + FnLen Byte length of FileName + FileName variable full Macintosh filename + FileType beLong four-byte Mac file type string + Creator beLong four-byte Mac creator string + + + -Acorn SparkFS Extra Field: + ========================= + + The following is the layout of David Pilling's SparkFS extra block + for Acorn RISC OS. The local-header and central-header versions are + identical. (Last Revision 960922) + + Value Size Description + ----- ---- ----------- + (Acorn) 0x4341 Short tag for this extra block type + TSize Short total data size for this block + "ARC0" Long extra-field signature + LoadAddr Long load address or file type + ExecAddr Long exec address + Attr Long file permissions + Zero Long reserved; always zero + + The following bits of Attr are associated with the given file + permissions: + + bit 0 user-writable ('W') + bit 1 user-readable ('R') + bit 2 reserved + bit 3 locked ('L') + bit 4 publicly writable ('w') + bit 5 publicly readable ('r') + bit 6 reserved + bit 7 reserved + + + -VM/CMS Extra Field: + ================== + + The following is the layout of the file-attributes extra block for + VM/CMS. The local-header and central-header versions are + identical. (Last Revision 960922) + + Value Size Description + ----- ---- ----------- + (VM/CMS) 0x4704 Short tag for this extra block type + TSize Short total data size for this block + flData variable file attributes data + + flData is an uncompressed fldata_t struct. + + + -MVS Extra Field: + =============== + + The following is the layout of the file-attributes extra block for + MVS. The local-header and central-header versions are identical. + (Last Revision 960922) + + Value Size Description + ----- ---- ----------- + (MVS) 0x470f Short tag for this extra block type + TSize Short total data size for this block + flData variable file attributes data + + flData is an uncompressed fldata_t struct. + + + -Extended Timestamp Extra Field: + ============================== + + The following is the layout of the extended-timestamp extra block. + (Last Revision 970118) + + Local-header version: + + Value Size Description + ----- ---- ----------- + (time) 0x5455 Short tag for this extra block type + TSize Short total data size for this block + Flags Byte info bits + (ModTime) Long time of last modification (UTC/GMT) + (AcTime) Long time of last access (UTC/GMT) + (CrTime) Long time of original creation (UTC/GMT) + + Central-header version: + + Value Size Description + ----- ---- ----------- + (time) 0x5455 Short tag for this extra block type + TSize Short total data size for this block + Flags Byte info bits (refers to local header!) + (ModTime) Long time of last modification (UTC/GMT) + + The central-header extra field contains the modification time only, + or no timestamp at all. TSize is used to flag its presence or + absence. But note: + + If "Flags" indicates that Modtime is present in the local header + field, it MUST be present in the central header field, too! + This correspondence is required because the modification time + value may be used to support trans-timezone freshening and + updating operations with zip archives. + + The time values are in standard Unix signed-long format, indicating + the number of seconds since 1 January 1970 00:00:00. The times + are relative to Coordinated Universal Time (UTC), also sometimes + referred to as Greenwich Mean Time (GMT). To convert to local time, + the software must know the local timezone offset from UTC/GMT. + + The lower three bits of Flags in both headers indicate which time- + stamps are present in the LOCAL extra field: + + bit 0 if set, modification time is present + bit 1 if set, access time is present + bit 2 if set, creation time is present + bits 3-7 reserved for additional timestamps; not set + + Those times that are present will appear in the order indicated, but + any combination of times may be omitted. (Creation time may be + present without access time, for example.) TSize should equal + (1 + 4*(number of set bits in Flags)), as the block is currently + defined. Other timestamps may be added in the future. + + + -Info-ZIP Unix Extra Field (type 1): + ================================== + + The following is the layout of the old Info-ZIP extra block for + Unix. It has been replaced by the extended-timestamp extra block + (0x5455) and the Unix type 2 extra block (0x7855). + (Last Revision 970118) + + Local-header version: + + Value Size Description + ----- ---- ----------- + (Unix1) 0x5855 Short tag for this extra block type + TSize Short total data size for this block + ModTime Long time of last modification (UTC/GMT) + AcTime Long time of last access (UTC/GMT) + UID Short Unix user ID + GID Short Unix group ID + + Central-header version: + + Value Size Description + ----- ---- ----------- + (Unix1) 0x5855 Short tag for this extra block type + TSize Short total data size for this block + ModTime Long time of last modification (GMT/UTC) + AcTime Long time of last access (GMT/UTC) + + The file modification and access times are in standard Unix signed- + long format, indicating the number of seconds since 1 January 1970 + 00:00:00. The times are relative to Coordinated Universal Time + (UTC), also sometimes referred to as Greenwich Mean Time (GMT). To + convert to local time, the software must know the local timezone + offset from UTC/GMT. The modification time may be used by non-Unix + systems to support inter-timezone freshening and updating of zip + archives. + + The local-header extra block may optionally contain UID and GID + info for the file. The local-header TSize value is the only + indication of this. Note that Unix UIDs and GIDs are usually + specific to a particular machine, and they generally require root + access to restore. + + This extra field type is obsolete, but it has been in use since + mid-1994. Therefore future archiving software should continue to + support it. Some guidelines: + + An archive member should either contain the old "Unix1" + extra field block or the new extra field types "time" and/or + "Unix2". + + If both the old "Unix1" block type and one or both of the new + block types "time" and "Unix2" are found, the "Unix1" block + should be considered invalid and ignored. + + Unarchiving software should recognize both old and new extra + field block types, but the info from new types overrides the + old "Unix1" field. + + Archiving software should recognize "Unix1" extra fields for + timestamp comparison but never create it for updated, freshened + or new archive members. When copying existing members to a new + archive, any "Unix1" extra field blocks should be converted to + the new "time" and/or "Unix2" types. + + + -Info-ZIP Unix Extra Field (type 2): + ================================== + + The following is the layout of the new Info-ZIP extra block for + Unix. (Last Revision 960922) + + Local-header version: + + Value Size Description + ----- ---- ----------- + (Unix2) 0x7855 Short tag for this extra block type + TSize Short total data size for this block + UID Short Unix user ID + GID Short Unix group ID + + Central-header version: + + Value Size Description + ----- ---- ----------- + (Unix2) 0x7855 Short tag for this extra block type + TSize Short total data size for this block + + The data size of the central-header version is zero; it is used + solely as a flag that UID/GID info is present in the local-header + extra field. If additional fields are ever added to the local + version, the central version may be extended to indicate this. + + Note that Unix UIDs and GIDs are usually specific to a particular + machine, and they generally require root access to restore. + + + -ASi Unix Extra Field: + ==================== + + The following is the layout of the ASi extra block for Unix. The + local-header and central-header versions are identical. + (Last Revision 960916) + + Value Size Description + ----- ---- ----------- + (Unix3) 0x756e Short tag for this extra block type + TSize Short total data size for this block + CRC Long CRC-32 of the remaining data + Mode Short file permissions + SizDev Long symlink'd size OR major/minor dev num + UID Short user ID + GID Short group ID + (var.) variable symbolic link filename + + Mode is the standard Unix st_mode field from struct stat, containing + user/group/other permissions, setuid/setgid and symlink info, etc. + + If Mode indicates that this file is a symbolic link, SizDev is the + size of the file to which the link points. Otherwise, if the file + is a device, SizDev contains the standard Unix st_rdev field from + struct stat (includes the major and minor numbers of the device). + SizDev is undefined in other cases. + + If Mode indicates that the file is a symbolic link, the final field + will be the name of the file to which the link points. The file- + name length can be inferred from TSize. + + [Note that TSize may incorrectly refer to the data size not counting + the CRC; i.e., it may be four bytes too small.] + + + -BeOS Extra Field: + ================ + + The following is the layout of the file-attributes extra block for + BeOS. (Last Revision 970311) + + Local-header version: + + Value Size Description + ----- ---- ----------- + (BeOS) 0x6542 Short tag for this extra block type + TSize Short total data size for this block + Type Long file type + Creator Long file creator + + Type and Creator are "longtext" in native BeOS code (that is, un- + signed longs that are typically readable as 4-byte text strings). + This will change during the filesystem rewrite for BeOS DR9 (expected + in spring 1997), probably as follows: + + Value Size Description + ----- ---- ----------- + (BeOS) 0x6542 Short tag for this extra block type + TSize Short total data size for this block + BSize Long uncompressed file attribute data size + CType Short compression type + CRC Long CRC value for uncompressed file attribs + Attribs variable compressed file attribute data + + The local extra block is similar to OS/2's since OS/2 EAs are similar + to the file attributes planned for BeOS 1.1DR9, but the implementation + will be different. + + Central-header version: + + Value Size Description + ----- ---- ----------- + (BeOS) 0x6542 Short tag for this extra block type + TSize Short total data size for this block + BSize Long size of local EF block data + + + -SMS/QDOS Extra Field: + ==================== + + The following is the layout of the file-attributes extra block for + SMS/QDOS. The local-header and central-header versions are identical. + (Last Revision 960929) + + Value Size Description + ----- ---- ----------- + (QDOS) 0xfb4a Short tag for this extra block type + TSize Short total data size for this block + LongID Long extra-field signature + (ExtraID) Long additional signature/flag bytes + QDirect 64 bytes qdirect structure + + LongID may be "QZHD" or "QDOS". In the latter case, ExtraID will + be present. Its first three bytes are "02\0"; the last byte is + currently undefined. + + QDirect contains the file's uncompressed directory info (qdirect + struct). Its elements are in native (big-endian) format: + + d_length beLong file length + d_access byte file access type + d_type byte file type + d_datalen beLong data length + d_reserved beLong unused + d_szname beShort size of filename + d_name 36 bytes filename + d_update beLong time of last update + d_refdate beLong file version number + d_backup beLong time of last backup (archive date) + + + -AOS/VS Extra Field: + ================== + + The following is the layout of the extra block for Data General + AOS/VS. The local-header and central-header versions are identical. + (Last Revision 961125) + + Value Size Description + ----- ---- ----------- + (AOSVS) 0x5356 Short tag for this extra block type + TSize Short total data size for this block + "FCI\0" Long extra-field signature + Version Byte version of AOS/VS extra block (10 = 1.0) + Fstat variable fstat packet + AclBuf variable raw ACL data ($MXACL bytes) + + Fstat contains the file's uncompressed fstat packet, which is one of + the following: + + normal fstat packet (P_FSTAT struct) + DIR/CPD fstat packet (P_FSTAT_DIR struct) + unit (device) fstat packet (P_FSTAT_UNIT struct) + IPC file fstat packet (P_FSTAT_IPC struct) + + AclBuf contains the raw ACL data; its length is $MXACL. + + + -FWKCS MD5 Extra Field: + ===================== + + The following is the layout of the optional extra block used by the + FWKCS utility. There is no local-header version; the following + applies only to the central header. (Last Revision 961207) + + Central-header version: + + Value Size Description + ----- ---- ----------- + (MD5) 0x4b46 Short tag for this extra block type + TSize Short total data size for this block (19) + "MD5" 3 bytes extra-field signature + MD5hash 16 bytes 128-bit MD5 hash of uncompressed data + + The MD5 hash in this extra block is used to automatically identify + files independent of their filenames; it is an an enhanced contents- + signature. Adding or removing this block should preserve the PKWARE + AV (Authenticity Verification) signature. + + ``The MD5 algorithm is being placed in the public domain for review + and possible adoption as a standard.'' (Ron Rivest, MIT Laboratory + for Computer Science and RSA Data Security, Inc., April 1992, RFC + 1321, 11.76-77). FWKCS is a trademark of Frederick W. Kantor. + + + + file comment: (Variable) + + The comment for this file. + + number of this disk: (2 bytes) + + The number of this disk, which contains central + directory end record. + + number of the disk with the start of the central directory: (2 bytes) + + The number of the disk on which the central + directory starts. + + total number of entries in the central dir on this disk: (2 bytes) + + The number of central directory entries on this disk. + + total number of entries in the central dir: (2 bytes) + + The total number of files in the zipfile. + + + size of the central directory: (4 bytes) + + The size (in bytes) of the entire central directory. + + offset of start of central directory with respect to + the starting disk number: (4 bytes) + + Offset of the start of the central direcory on the + disk on which the central directory starts. + + zipfile comment length: (2 bytes) + + The length of the comment for this zipfile. + + zipfile comment: (Variable) + + The comment for this zipfile. + + + D. General notes: + + 1) All fields unless otherwise noted are unsigned and stored + in Intel low-byte:high-byte, low-word:high-word order. + + 2) String fields are not null terminated, since the + length is given explicitly. + + 3) Local headers should not span disk boundries. Also, even + though the central directory can span disk boundries, no + single record in the central directory should be split + across disks. + + 4) The entries in the central directory may not necessarily + be in the same order that files appear in the zipfile. + +UnShrinking - Method 1 +---------------------- + +Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm +with partial clearing. The initial code size is 9 bits, and +the maximum code size is 13 bits. Shrinking differs from +conventional Dynamic Ziv-Lempel-Welch implementations in several +respects: + +1) The code size is controlled by the compressor, and is not + automatically increased when codes larger than the current + code size are created (but not necessarily used). When + the decompressor encounters the code sequence 256 + (decimal) followed by 1, it should increase the code size + read from the input stream to the next bit size. No + blocking of the codes is performed, so the next code at + the increased size should be read from the input stream + immediately after where the previous code at the smaller + bit size was read. Again, the decompressor should not + increase the code size used until the sequence 256,1 is + encountered. + +2) When the table becomes full, total clearing is not + performed. Rather, when the compresser emits the code + sequence 256,2 (decimal), the decompressor should clear + all leaf nodes from the Ziv-Lempel tree, and continue to + use the current code size. The nodes that are cleared + from the Ziv-Lempel tree are then re-used, with the lowest + code value re-used first, and the highest code value + re-used last. The compressor can emit the sequence 256,2 + at any time. + + + +Expanding - Methods 2-5 +----------------------- + +The Reducing algorithm is actually a combination of two +distinct algorithms. The first algorithm compresses repeated +byte sequences, and the second algorithm takes the compressed +stream from the first algorithm and applies a probabilistic +compression method. + +The probabilistic compression stores an array of 'follower +sets' S(j), for j=0 to 255, corresponding to each possible +ASCII character. Each set contains between 0 and 32 +characters, to be denoted as S(j)[0],...,S(j)[m], where m<32. +The sets are stored at the beginning of the data area for a +Reduced file, in reverse order, with S(255) first, and S(0) +last. + +The sets are encoded as { N(j), S(j)[0],...,S(j)[N(j)-1] }, +where N(j) is the size of set S(j). N(j) can be 0, in which +case the follower set for S(j) is empty. Each N(j) value is +encoded in 6 bits, followed by N(j) eight bit character values +corresponding to S(j)[0] to S(j)[N(j)-1] respectively. If +N(j) is 0, then no values for S(j) are stored, and the value +for N(j-1) immediately follows. + +Immediately after the follower sets, is the compressed data +stream. The compressed data stream can be interpreted for the +probabilistic decompression as follows: + + +let Last-Character <- 0. +loop until done + if the follower set S(Last-Character) is empty then + read 8 bits from the input stream, and copy this + value to the output stream. + otherwise if the follower set S(Last-Character) is non-empty then + read 1 bit from the input stream. + if this bit is not zero then + read 8 bits from the input stream, and copy this + value to the output stream. + otherwise if this bit is zero then + read B(N(Last-Character)) bits from the input + stream, and assign this value to I. + Copy the value of S(Last-Character)[I] to the + output stream. + + assign the last value placed on the output stream to + Last-Character. +end loop + + +B(N(j)) is defined as the minimal number of bits required to +encode the value N(j)-1. + + +The decompressed stream from above can then be expanded to +re-create the original file as follows: + + +let State <- 0. + +loop until done + read 8 bits from the input stream into C. + case State of + 0: if C is not equal to DLE (144 decimal) then + copy C to the output stream. + otherwise if C is equal to DLE then + let State <- 1. + + 1: if C is non-zero then + let V <- C. + let Len <- L(V) + let State <- F(Len). + otherwise if C is zero then + copy the value 144 (decimal) to the output stream. + let State <- 0 + + 2: let Len <- Len + C + let State <- 3. + + 3: move backwards D(V,C) bytes in the output stream + (if this position is before the start of the output + stream, then assume that all the data before the + start of the output stream is filled with zeros). + copy Len+3 bytes from this position to the output stream. + let State <- 0. + end case +end loop + + +The functions F,L, and D are dependent on the 'compression +factor', 1 through 4, and are defined as follows: + +For compression factor 1: + L(X) equals the lower 7 bits of X. + F(X) equals 2 if X equals 127 otherwise F(X) equals 3. + D(X,Y) equals the (upper 1 bit of X) * 256 + Y + 1. +For compression factor 2: + L(X) equals the lower 6 bits of X. + F(X) equals 2 if X equals 63 otherwise F(X) equals 3. + D(X,Y) equals the (upper 2 bits of X) * 256 + Y + 1. +For compression factor 3: + L(X) equals the lower 5 bits of X. + F(X) equals 2 if X equals 31 otherwise F(X) equals 3. + D(X,Y) equals the (upper 3 bits of X) * 256 + Y + 1. +For compression factor 4: + L(X) equals the lower 4 bits of X. + F(X) equals 2 if X equals 15 otherwise F(X) equals 3. + D(X,Y) equals the (upper 4 bits of X) * 256 + Y + 1. + + +Imploding - Method 6 +-------------------- + +The Imploding algorithm is actually a combination of two distinct +algorithms. The first algorithm compresses repeated byte +sequences using a sliding dictionary. The second algorithm is +used to compress the encoding of the sliding dictionary ouput, +using multiple Shannon-Fano trees. + +The Imploding algorithm can use a 4K or 8K sliding dictionary +size. The dictionary size used can be determined by bit 1 in the +general purpose flag word; a 0 bit indicates a 4K dictionary +while a 1 bit indicates an 8K dictionary. + +The Shannon-Fano trees are stored at the start of the compressed +file. The number of trees stored is defined by bit 2 in the +general purpose flag word; a 0 bit indicates two trees stored, a +1 bit indicates three trees are stored. If 3 trees are stored, +the first Shannon-Fano tree represents the encoding of the +Literal characters, the second tree represents the encoding of +the Length information, the third represents the encoding of the +Distance information. When 2 Shannon-Fano trees are stored, the +Length tree is stored first, followed by the Distance tree. + +The Literal Shannon-Fano tree, if present is used to represent +the entire ASCII character set, and contains 256 values. This +tree is used to compress any data not compressed by the sliding +dictionary algorithm. When this tree is present, the Minimum +Match Length for the sliding dictionary is 3. If this tree is +not present, the Minimum Match Length is 2. + +The Length Shannon-Fano tree is used to compress the Length part +of the (length,distance) pairs from the sliding dictionary +output. The Length tree contains 64 values, ranging from the +Minimum Match Length, to 63 plus the Minimum Match Length. + +The Distance Shannon-Fano tree is used to compress the Distance +part of the (length,distance) pairs from the sliding dictionary +output. The Distance tree contains 64 values, ranging from 0 to +63, representing the upper 6 bits of the distance value. The +distance values themselves will be between 0 and the sliding +dictionary size, either 4K or 8K. + +The Shannon-Fano trees themselves are stored in a compressed +format. The first byte of the tree data represents the number of +bytes of data representing the (compressed) Shannon-Fano tree +minus 1. The remaining bytes represent the Shannon-Fano tree +data encoded as: + + High 4 bits: Number of values at this bit length + 1. (1 - 16) + Low 4 bits: Bit Length needed to represent value + 1. (1 - 16) + +The Shannon-Fano codes can be constructed from the bit lengths +using the following algorithm: + +1) Sort the Bit Lengths in ascending order, while retaining the + order of the original lengths stored in the file. + +2) Generate the Shannon-Fano trees: + + Code <- 0 + CodeIncrement <- 0 + LastBitLength <- 0 + i <- number of Shannon-Fano codes - 1 (either 255 or 63) + + loop while i >= 0 + Code = Code + CodeIncrement + if BitLength(i) <> LastBitLength then + LastBitLength=BitLength(i) + CodeIncrement = 1 shifted left (16 - LastBitLength) + ShannonCode(i) = Code + i <- i - 1 + end loop + + +3) Reverse the order of all the bits in the above ShannonCode() + vector, so that the most significant bit becomes the least + significant bit. For example, the value 0x1234 (hex) would + become 0x2C48 (hex). + +4) Restore the order of Shannon-Fano codes as originally stored + within the file. + +Example: + + This example will show the encoding of a Shannon-Fano tree + of size 8. Notice that the actual Shannon-Fano trees used + for Imploding are either 64 or 256 entries in size. + +Example: 0x02, 0x42, 0x01, 0x13 + + The first byte indicates 3 values in this table. Decoding the + bytes: + 0x42 = 5 codes of 3 bits long + 0x01 = 1 code of 2 bits long + 0x13 = 2 codes of 4 bits long + + This would generate the original bit length array of: + (3, 3, 3, 3, 3, 2, 4, 4) + + There are 8 codes in this table for the values 0 thru 7. Using the + algorithm to obtain the Shannon-Fano codes produces: + + Reversed Order Original +Val Sorted Constructed Code Value Restored Length +--- ------ ----------------- -------- -------- ------ +0: 2 1100000000000000 11 101 3 +1: 3 1010000000000000 101 001 3 +2: 3 1000000000000000 001 110 3 +3: 3 0110000000000000 110 010 3 +4: 3 0100000000000000 010 100 3 +5: 3 0010000000000000 100 11 2 +6: 4 0001000000000000 1000 1000 4 +7: 4 0000000000000000 0000 0000 4 + + +The values in the Val, Order Restored and Original Length columns +now represent the Shannon-Fano encoding tree that can be used for +decoding the Shannon-Fano encoded data. How to parse the +variable length Shannon-Fano values from the data stream is beyond the +scope of this document. (See the references listed at the end of +this document for more information.) However, traditional decoding +schemes used for Huffman variable length decoding, such as the +Greenlaw algorithm, can be succesfully applied. + +The compressed data stream begins immediately after the +compressed Shannon-Fano data. The compressed data stream can be +interpreted as follows: + +loop until done + read 1 bit from input stream. + + if this bit is non-zero then (encoded data is literal data) + if Literal Shannon-Fano tree is present + read and decode character using Literal Shannon-Fano tree. + otherwise + read 8 bits from input stream. + copy character to the output stream. + otherwise (encoded data is sliding dictionary match) + if 8K dictionary size + read 7 bits for offset Distance (lower 7 bits of offset). + otherwise + read 6 bits for offset Distance (lower 6 bits of offset). + + using the Distance Shannon-Fano tree, read and decode the + upper 6 bits of the Distance value. + + using the Length Shannon-Fano tree, read and decode + the Length value. + + Length <- Length + Minimum Match Length + + if Length = 63 + Minimum Match Length + read 8 bits from the input stream, + add this value to Length. + + move backwards Distance+1 bytes in the output stream, and + copy Length characters from this position to the output + stream. (if this position is before the start of the output + stream, then assume that all the data before the start of + the output stream is filled with zeros). +end loop + +Tokenizing - Method 7 +-------------------- + +This method is not used by PKZIP. + +Deflating - Method 8 +----------------- + +The Deflate algorithm is similar to the Implode algorithm using +a sliding dictionary of up to 32K with secondary compression +from Huffman/Shannon-Fano codes. + +The compressed data is stored in blocks with a header describing +the block and the Huffman codes used in the data block. The header +format is as follows: + + Bit 0: Last Block bit This bit is set to 1 if this is the last + compressed block in the data. + Bits 1-2: Block type + 00 (0) - Block is stored - All stored data is byte aligned. + Skip bits until next byte, then next word = block length, + followed by the ones compliment of the block length word. + Remaining data in block is the stored data. + + 01 (1) - Use fixed Huffman codes for literal and distance codes. + Lit Code Bits Dist Code Bits + --------- ---- --------- ---- + 0 - 143 8 0 - 31 5 + 144 - 255 9 + 256 - 279 7 + 280 - 287 8 + + Literal codes 286-287 and distance codes 30-31 are never + used but participate in the huffman construction. + + 10 (2) - Dynamic Huffman codes. (See expanding Huffman codes) + + 11 (3) - Reserved - Flag a "Error in compressed data" if seen. + +Expanding Huffman Codes +----------------------- +If the data block is stored with dynamic Huffman codes, the Huffman +codes are sent in the following compressed format: + + 5 Bits: # of Literal codes sent - 257 (257 - 286) + All other codes are never sent. + 5 Bits: # of Dist codes - 1 (1 - 32) + 4 Bits: # of Bit Length codes - 4 (4 - 19) + +The Huffman codes are sent as bit lengths and the codes are built as +described in the implode algorithm. The bit lengths themselves are +compressed with Huffman codes. There are 19 bit length codes: + + 0 - 15: Represent bit lengths of 0 - 15 + 16: Copy the previous bit length 3 - 6 times. + The next 2 bits indicate repeat length (0 = 3, ... ,3 = 6) + Example: Codes 8, 16 (+2 bits 11), 16 (+2 bits 10) will + expand to 12 bit lengths of 8 (1 + 6 + 5) + 17: Repeat a bit length of 0 for 3 - 10 times. (3 bits of length) + 18: Repeat a bit length of 0 for 11 - 138 times (7 bits of length) + +The lengths of the bit length codes are sent packed 3 bits per value +(0 - 7) in the following order: + + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + +The Huffman codes should be built as described in the Implode algorithm +except codes are assigned starting at the shortest bit length, i.e. the +shortest code should be all 0's rather than all 1's. Also, codes with +a bit length of zero do not participate in the tree construction. The +codes are then used to decode the bit lengths for the literal and distance +tables. + +The bit lengths for the literal tables are sent first with the number +of entries sent described by the 5 bits sent earlier. There are up +to 286 literal characters; the first 256 represent the respective 8 +bit character, code 256 represents the End-Of-Block code, the remaining +29 codes represent copy lengths of 3 thru 258. There are up to 30 +distance codes representing distances from 1 thru 32k as described +below. + + Length Codes + ------------ + Extra Extra Extra Extra + Code Bits Length Code Bits Lengths Code Bits Lengths Code Bits Length(s) + ---- ---- ------ ---- ---- ------- ---- ---- ------- ---- ---- --------- + 257 0 3 265 1 11,12 273 3 35-42 281 5 131-162 + 258 0 4 266 1 13,14 274 3 43-50 282 5 163-194 + 259 0 5 267 1 15,16 275 3 51-58 283 5 195-226 + 260 0 6 268 1 17,18 276 3 59-66 284 5 227-257 + 261 0 7 269 2 19-22 277 4 67-82 285 0 258 + 262 0 8 270 2 23-26 278 4 83-98 + 263 0 9 271 2 27-30 279 4 99-114 + 264 0 10 272 2 31-34 280 4 115-130 + + Distance Codes + -------------- + Extra Extra Extra Extra + Code Bits Dist Code Bits Dist Code Bits Distance Code Bits Distance + ---- ---- ---- ---- ---- ------ ---- ---- -------- ---- ---- -------- + 0 0 1 8 3 17-24 16 7 257-384 24 11 4097-6144 + 1 0 2 9 3 25-32 17 7 385-512 25 11 6145-8192 + 2 0 3 10 4 33-48 18 8 513-768 26 12 8193-12288 + 3 0 4 11 4 49-64 19 8 769-1024 27 12 12289-16384 + 4 1 5,6 12 5 65-96 20 9 1025-1536 28 13 16385-24576 + 5 1 7,8 13 5 97-128 21 9 1537-2048 29 13 24577-32768 + 6 2 9-12 14 6 129-192 22 10 2049-3072 + 7 2 13-16 15 6 193-256 23 10 3073-4096 + +The compressed data stream begins immediately after the +compressed header data. The compressed data stream can be +interpreted as follows: + +do + read header from input stream. + + if stored block + skip bits until byte aligned + read count and 1's compliment of count + copy count bytes data block + otherwise + loop until end of block code sent + decode literal character from input stream + if literal < 256 + copy character to the output stream + otherwise + if literal = end of block + break from loop + otherwise + decode distance from input stream + + move backwards distance bytes in the output stream, and + copy length characters from this position to the output + stream. + end loop +while not last block + +if data descriptor exists + skip bits until byte aligned + read crc and sizes +endif + +Decryption +---------- + +The encryption used in PKZIP was generously supplied by Roger +Schlafly. PKWARE is grateful to Mr. Schlafly for his expert +help and advice in the field of data encryption. + +PKZIP encrypts the compressed data stream. Encrypted files must +be decrypted before they can be extracted. + +Each encrypted file has an extra 12 bytes stored at the start of +the data area defining the encryption header for that file. The +encryption header is originally set to random values, and then +itself encrypted, using three, 32-bit keys. The key values are +initialized using the supplied encryption password. After each byte +is encrypted, the keys are then updated using pseudo-random number +generation techniques in combination with the same CRC-32 algorithm +used in PKZIP and described elsewhere in this document. + +The following is the basic steps required to decrypt a file: + +1) Initialize the three 32-bit keys with the password. +2) Read and decrypt the 12-byte encryption header, further + initializing the encryption keys. +3) Read and decrypt the compressed data stream using the + encryption keys. + + +Step 1 - Initializing the encryption keys +----------------------------------------- + +Key(0) <- 305419896 +Key(1) <- 591751049 +Key(2) <- 878082192 + +loop for i <- 0 to length(password)-1 + update_keys(password(i)) +end loop + + +Where update_keys() is defined as: + + +update_keys(char): + Key(0) <- crc32(key(0),char) + Key(1) <- Key(1) + (Key(0) & 000000ffH) + Key(1) <- Key(1) * 134775813 + 1 + Key(2) <- crc32(key(2),key(1) >> 24) +end update_keys + + +Where crc32(old_crc,char) is a routine that given a CRC value and a +character, returns an updated CRC value after applying the CRC-32 +algorithm described elsewhere in this document. + + +Step 2 - Decrypting the encryption header +----------------------------------------- + +The purpose of this step is to further initialize the encryption +keys, based on random data, to render a plaintext attack on the +data ineffective. + + +Read the 12-byte encryption header into Buffer, in locations +Buffer(0) thru Buffer(11). + +loop for i <- 0 to 11 + C <- buffer(i) ^ decrypt_byte() + update_keys(C) + buffer(i) <- C +end loop + + +Where decrypt_byte() is defined as: + + +unsigned char decrypt_byte() + local unsigned short temp + temp <- Key(2) | 2 + decrypt_byte <- (temp * (temp ^ 1)) >> 8 +end decrypt_byte + + +After the header is decrypted, the last 1 or 2 bytes in Buffer +should be the high-order word/byte of the CRC for the file being +decrypted, stored in Intel low-byte/high-byte order, or the high-order +byte of the file time if bit 3 of the general purpose bit flag is set. +Versions of PKZIP prior to 2.0 used a 2 byte CRC check; a 1 byte CRC check is +used on versions after 2.0. This can be used to test if the password +supplied is correct or not. + + +Step 3 - Decrypting the compressed data stream +---------------------------------------------- + +The compressed data stream can be decrypted as follows: + + +loop until done + read a charcter into C + Temp <- C ^ decrypt_byte() + update_keys(temp) + output Temp +end loop + + +In addition to the above mentioned contributors to PKZIP and PKUNZIP, +I would like to extend special thanks to Robert Mahoney for suggesting +the extension .ZIP for this software. + + +References: + + Fiala, Edward R., and Greene, Daniel H., "Data compression with + finite windows", Communications of the ACM, Volume 32, Number 4, + April 1989, pages 490-505. + + Held, Gilbert, "Data Compression, Techniques and Applications, + Hardware and Software Considerations", + John Wiley & Sons, 1987. + + Huffman, D.A., "A method for the construction of minimum-redundancy + codes", Proceedings of the IRE, Volume 40, Number 9, September 1952, + pages 1098-1101. + + Nelson, Mark, "LZW Data Compression", Dr. Dobbs Journal, Volume 14, + Number 10, October 1989, pages 29-37. + + Nelson, Mark, "The Data Compression Book", M&T Books, 1991. + + Storer, James A., "Data Compression, Methods and Theory", + Computer Science Press, 1988 + + Welch, Terry, "A Technique for High-Performance Data Compression", + IEEE Computer, Volume 17, Number 6, June 1984, pages 8-19. + + Ziv, J. and Lempel, A., "A universal algorithm for sequential data + compression", Communications of the ACM, Volume 30, Number 6, + June 1987, pages 520-540. + + Ziv, J. and Lempel, A., "Compression of individual sequences via + variable-rate coding", IEEE Transactions on Information Theory, + Volume 24, Number 5, September 1978, pages 530-536. diff --git a/Zip/doc/ZipUserGuide.page b/Zip/doc/ZipUserGuide.page new file mode 100644 index 000000000..4b79dfa43 --- /dev/null +++ b/Zip/doc/ZipUserGuide.page @@ -0,0 +1,161 @@ +POCO Zip User Guide +Zip + +!!!Introduction +POCO Zip adds support for parsing and creating Zip files. It offers the following features: + * decompress from local files + * decompress from network files while they are downloaded + * compress to local files + * compress directly to a network destination + +!!Restrictions + * POCO Zip does not support the DEFLATE64 algorithm. + * encrypted files are not supported + +!!!Main Classes +Most users will work with two common classes: <*Compress*> and <*Decompress*> + +!!Compress +Compress is a helper class that simplifies creation of Zip files. +Creating a Zip file is a basically a three-step process: + * Create the Compress object: Specify the output stream and define if it is seekable (set to true for local files, to false for network files) + + Compress(std::ostream& out, bool seekableOut); +---- + * Add entries: either add single files or directory entries + + void addFile(std::istream& input, + const Poco::DateTime& lastModifiedAt, + const Poco::Path& fileName, + ZipCommon::CompressionMethod cm = ZipCommon::CM_DEFLATE, + ZipCommon::CompressionLevel cl = ZipCommon::CL_MAXIMUM); + /// Adds a single file to the Zip File. fileName must not be a directory name. + + void addFile(const Poco::Path& file, + const Poco::Path& fileName, + ZipCommon::CompressionMethod cm = ZipCommon::CM_DEFLATE, + ZipCommon::CompressionLevel cl = ZipCommon::CL_MAXIMUM); + /// Adds a single file to the Zip File. fileName must not be a directory name. The file must exist physically! + + void addDirectory(const Poco::Path& entryName, const Poco::DateTime& lastModifiedAt); + /// Adds a directory entry excluding all children to the Zip file, entryName must not be empty. + + void addRecursive(const Poco::Path& entry, + ZipCommon::CompressionLevel cl = ZipCommon::CL_MAXIMUM, + bool excludeRoot = true, + const Poco::Path& name = Poco::Path()); + /// Adds a directory entry recursively to the zip file, set excludeRoot to false to exclude the parent directory. + /// The name specifies under which path the entries are added in the Zip file. +---- +Note that one must always define a name when adding a file entry, otherwise the compresser can not decide if the file should be added with an absolute or a relative path. +Assume you are adding the file <*c:\\data\\hello.txt*> twice to a Zip: + + // MUST use binary! + std::ofstream out("test.zip", std::ios::binary); + Compress c(out, true); + Poco::Path aFile("c:\\data\\hello.txt"); + c.addFile(theFile, "hello.txt"); + c.addFile(theFile, theFile); + c.close(); // MUST be done to finalize the Zip file +---- +A Zip file stores entries internally in UNIX path style. The Zip file created above will contain the following entries: + + hello.txt + data/ + data/hello.txt +---- +The directory entry <*data/*> was automatically added. + +When adding directories recursively, the same principle applies. You specify the root directory that should be added and an optional path name where entries are added in the Zip file. +Assume you have the following directory structure: + + data/ + run1/ + result1.txt + run2/ + result2.txt +---- +The following call will add all subdirectories and all files of data to the Zip but not the root entry <*data*>: + + Poco::Path data("data"); + data.makeDirectory(); + c.addRecursive(data); +---- +Or if you want the files to be added under the directory name <*20070401*> (you basically <*rename*> data to 20070401): + + Poco::Path data("data"); + Poco::Path name("20070401); + data.makeDirectory(); + name.makeDirectory(); + c.addRecursive(data, ZipCommon::CL_NORMAL, false, name); +---- +Note that <*makeDirectory*> does not create a directory, it simply assures that the Path is treated as a directory not as a file. +Also using NORMAL compression instead of MAXIMUM (which is the default) has the benefit of improved performance. +To get notified about the entries that are added during <*addRecursive*> register to the event of the Compress object: + + Poco::FIFOEvent EDone; +---- + * Closing the Zip file: It is mandatory to manually close Compress objects. This guarantees that the Zip directory is written, thus creating a valid Zip file. It is safe to call <*close*> multiple times, only the first call takes effect. + + ZipArchive close(); +---- +<*close*> returns a ZipArchive which describes all entries inside a Zip file. + +!!Decompress +Decompress can be used to decompress all files from a Zip file or to decompress single files only. + +!Decompress All +The following sample code shows how all entries can be extracted from a Zip file: + + std::ifstream inp("test.zip", std::ios::binary); + poco_assert (inp); + // decompress to current working dir + Decompress dec(inp, Poco::Path()); + // if an error happens invoke the ZipTest::onDecompressError method + dec.EError += Poco::Delegate >(this, &ZipTest::onDecompressError); + dec.decompressAllFiles(); + dec.EError -= Poco::Delegate >(this, &ZipTest::onDecompressError); +---- +The onDecompressError method: + + void ZipTest::onDecompressError(const void* pSender, std::pair& info) + { + // inform user about error + [...] + } +---- +Decompressing directly from the net works similar: + + Poco::URI uri("http://www.appinf.com/test.zip"); + HTTPClientSession session(uri.getHost(), uri.getPort()); + HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1); + session.sendRequest(req); + HTTPResponse res; + std::istream& rs = session.receiveResponse(res); + Decompress dec(rs, Poco::Path()); + // if an error happens invoke the ZipTest::onDecompressError method + dec.EError += Poco::Delegate >(this, &ZipTest::onDecompressError); + dec.decompressAllFiles(); + dec.EError -= Poco::Delegate >(this, &ZipTest::onDecompressError); +---- +Furthermore, Decompress supports additional parameters: + + Decompress(std::istream& in, const Poco::Path& outputDir, bool flattenDirs = false, bool keepIncompleteFiles = false); +---- +If <*flattenDirs*> is set to true no subdirs are extracted, if <*keepIncompleteFiles*> is set to true, corrupt files (i.e. wrong CRC, wrong size on disk) will not be deleted. + +!Decompress Single Files +To decompress single files you must first parse a Zip file, and then decompress the file which happens transparently inside the <*ZipInputStream*>: + + std::ifstream inp("test.zip", std::ios::binary); + poco_assert (inp); + ZipArchive arch(inp); + ZipArchive::FileHeaders::const_iterator it = arch.findHeader("data/hello.txt"); + poco_assert (it != arch.headerEnd()); + ZipInputStream zipin (inp, it->second); + std::ostringstream out(std::ios::binary); + Poco::StreamCopier::copyStream(zipin, out); +---- +Note that this will only work with local files which allow us to seek inside the file. +Directly extracting single entries from a network file is currently not possible via the Decompress class. + diff --git a/Zip/include/Poco/Zip/Add.h b/Zip/include/Poco/Zip/Add.h new file mode 100644 index 000000000..42e984c5e --- /dev/null +++ b/Zip/include/Poco/Zip/Add.h @@ -0,0 +1,73 @@ +// +// Add.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/Add.h#1 $ +// +// Library: Zip +// Package: Manipulation +// Module: Add +// +// Definition of the Add class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_Add_INCLUDED +#define Zip_Add_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Zip/ZipOperation.h" +#include "Poco/Zip/ZipCommon.h" + + +namespace Poco { +namespace Zip { + + +class Zip_API Add: public ZipOperation + /// Operation Add adds a new file entry to an existing Zip File +{ +public: + Add(const std::string& zipPath, const std::string& localPath, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl); + /// Creates the Add. + + void execute(Compress& c, std::istream& input); + /// Performs the add operation + +private: + const std::string _zipPath; + const std::string _localPath; + const ZipCommon::CompressionMethod _cm; + const ZipCommon::CompressionLevel _cl; +}; + + +} } // namespace Poco::Zip + + +#endif // Zip_Add_INCLUDED diff --git a/Zip/include/Poco/Zip/AutoDetectStream.h b/Zip/include/Poco/Zip/AutoDetectStream.h new file mode 100644 index 000000000..2208ff1a1 --- /dev/null +++ b/Zip/include/Poco/Zip/AutoDetectStream.h @@ -0,0 +1,152 @@ +// +// AutoDetectStream.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/AutoDetectStream.h#4 $ +// +// Library: Zip +// Package: Zip +// Module: AutoDetectStream +// +// Definition of the AutoDetectStream class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_AutoDetectStream_INCLUDED +#define Zip_AutoDetectStream_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/BufferedStreamBuf.h" +#include +#include + + +namespace Poco { +namespace Zip { + + +class Zip_API AutoDetectStreamBuf: public Poco::BufferedStreamBuf + /// A AutoDetectStreamBuf is a class that limits one view on an inputstream to a selected view range +{ +public: + AutoDetectStreamBuf(std::istream& in, const std::string& prefix, const std::string& postfix, bool reposition, Poco::UInt32 start); + /// Creates the AutoDetectStream. + + + AutoDetectStreamBuf(std::ostream& out); + /// Creates the AutoDetectStream. + /// If initStream is true the status of the stream will be cleared on the first access, and the stream will be repositioned + /// to position start + + ~AutoDetectStreamBuf(); + /// Destroys the AutoDetectStream. + +protected: + int readFromDevice(char* buffer, std::streamsize length); + + int writeToDevice(const char* buffer, std::streamsize length); + +private: + enum + { + STREAM_BUFFER_SIZE = 1024 + }; + + std::istream* _pIstr; + std::ostream* _pOstr; + bool _eofDetected; + int _matchCnt; + std::string _prefix; + std::string _postfix; + bool _reposition; + Poco::UInt32 _start; +}; + + +class Zip_API AutoDetectIOS: public virtual std::ios + /// The base class for AutoDetectInputStream and AutoDetectOutputStream. + /// + /// This class is needed to ensure the correct initialization + /// order of the stream buffer and base classes. +{ +public: + AutoDetectIOS(std::istream& istr, const std::string& prefix, const std::string& postfix, bool reposition, Poco::UInt32 start); + /// Creates the basic stream and connects it + /// to the given input stream. + + AutoDetectIOS(std::ostream& ostr); + /// Creates the basic stream and connects it + /// to the given output stream. + + ~AutoDetectIOS(); + /// Destroys the stream. + + AutoDetectStreamBuf* rdbuf(); + /// Returns a pointer to the underlying streambuf. + +protected: + AutoDetectStreamBuf _buf; +}; + + +class Zip_API AutoDetectInputStream: public AutoDetectIOS, public std::istream + /// This stream copies all characters read through it + /// to one or multiple output streams. +{ +public: + AutoDetectInputStream(std::istream& istr, const std::string& prefix = std::string(), const std::string& postfix = std::string(), bool reposition = false, Poco::UInt32 start = 0); + /// Creates the AutoDetectInputStream and connects it + /// to the given input stream. Bytes read are guaranteed to be in the range [start, end-1] + /// If initStream is true the status of the stream will be cleared on the first access, and the stream will be repositioned + /// to position start + + ~AutoDetectInputStream(); + /// Destroys the AutoDetectInputStream. +}; + + +class Zip_API AutoDetectOutputStream: public AutoDetectIOS, public std::ostream + /// This stream copies all characters written to it + /// to one or multiple output streams. +{ +public: + AutoDetectOutputStream(std::ostream& ostr); + /// Creates the AutoDetectOutputStream and connects it + /// to the given input stream. Bytes written are guaranteed to be in the range [start, end-1] + /// If initStream is true the status of the stream will be cleared on the first access, and the stream will be repositioned + /// to position start + + ~AutoDetectOutputStream(); + /// Destroys the AutoDetectOutputStream. +}; + + +} } // namespace Poco::Zip + + +#endif // Zip_AutoDetectStream_INCLUDED diff --git a/Zip/include/Poco/Zip/Compress.h b/Zip/include/Poco/Zip/Compress.h new file mode 100644 index 000000000..4812686c9 --- /dev/null +++ b/Zip/include/Poco/Zip/Compress.h @@ -0,0 +1,112 @@ +// +// Compress.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/Compress.h#4 $ +// +// Library: Zip +// Package: Zip +// Module: Compress +// +// Definition of the Compress class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_Compress_INCLUDED +#define Zip_Compress_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Zip/ZipArchive.h" +#include "Poco/FIFOEvent.h" + + +namespace Poco { +namespace Zip { + + +class Zip_API Compress + /// Compresses a directory or files as zip. +{ +public: + Poco::FIFOEvent EDone; + + Compress(std::ostream& out, bool seekableOut); + /// seekableOut determines how we write the zip, setting it to true is recommended for local files (smaller zip file), + /// if you are compressing directly to a network, you MUST set it to false + + ~Compress(); + + void addFile(std::istream& input, const Poco::DateTime& lastModifiedAt, const Poco::Path& fileName, ZipCommon::CompressionMethod cm = ZipCommon::CM_DEFLATE, ZipCommon::CompressionLevel cl = ZipCommon::CL_MAXIMUM); + /// Adds a single file to the Zip File. fileName must not be a directory name. + + void addFile(const Poco::Path& file, const Poco::Path& fileName, ZipCommon::CompressionMethod cm = ZipCommon::CM_DEFLATE, ZipCommon::CompressionLevel cl = ZipCommon::CL_MAXIMUM); + /// Adds a single file to the Zip File. fileName must not be a directory name. The file must exist physically! + + void addDirectory(const Poco::Path& entryName, const Poco::DateTime& lastModifiedAt); + /// Adds a directory entry excluding all children to the Zip file, entryName must not be empty. + + void addRecursive(const Poco::Path& entry, ZipCommon::CompressionLevel cl = ZipCommon::CL_MAXIMUM, bool excludeRoot = true, const Poco::Path& name = Poco::Path()); + /// Adds a directory entry recursively to the zip file, set excludeRoot to false to exclude the parent directory. + /// If excludeRoot is true you can specify an empty name to add the files as relative files + + ZipArchive close(); + /// Finalizes the ZipArchive, closes it. + +private: + enum + { + COMPRESS_CHUNK_SIZE = 8192 + }; + + Compress(const Compress&); + Compress& operator=(const Compress&); + + void addEntry(std::istream& input, const Poco::DateTime& lastModifiedAt, const Poco::Path& fileName, ZipCommon::CompressionMethod cm = ZipCommon::CM_DEFLATE, ZipCommon::CompressionLevel cl = ZipCommon::CL_MAXIMUM); + /// Either adds a file or a single directory entry (excluding subchildren) to the Zip file. the compression level will be ignored + /// for directories. + + void addFileRaw(std::istream& in, const ZipLocalFileHeader& hdr, const Poco::Path& fileName); + /// copys an already compressed ZipEntry from in + +private: + std::ostream& _out; + bool _seekableOut; + ZipArchive::FileHeaders _files; + ZipArchive::FileInfos _infos; + ZipArchive::DirectoryInfos _dirs; + Poco::UInt32 _offset; + + friend class Keep; + friend class Rename; +}; + + +} } // namespace Poco::Zip + + +#endif // Zip_Compress_INCLUDED diff --git a/Zip/include/Poco/Zip/Decompress.h b/Zip/include/Poco/Zip/Decompress.h new file mode 100644 index 000000000..3b083fb15 --- /dev/null +++ b/Zip/include/Poco/Zip/Decompress.h @@ -0,0 +1,111 @@ +// +// Decompress.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/Decompress.h#3 $ +// +// Library: Zip +// Package: Zip +// Module: Decompress +// +// Definition of the Decompress class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_Decompress_INCLUDED +#define Zip_Decompress_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Zip/ParseCallback.h" +#include "Poco/Path.h" +#include "Poco/FIFOEvent.h" + + +namespace Poco { +namespace Zip { + + +class ZipArchive; + + +class Zip_API Decompress: public ParseCallback + /// Decompress extracts files from zip files, can be used to extract single files or all files +{ +public: + typedef std::map ZipMapping; + /// Maps key of FileInfo entries to their local decompressed representation + Poco::FIFOEvent > EError; + /// Thrown whenever an error is detected when handling a ZipLocalFileHeader entry. The string contains an error message + Poco::FIFOEvent > EOk; + /// Thrown whenever a file was successfully decompressed + + Decompress(std::istream& in, const Poco::Path& outputDir, bool flattenDirs = false, bool keepIncompleteFiles = false); + /// Creates the Decompress. Note that istream must be good and at the very beginning of the file! + /// Calling decompressAllFiles will cause the stream to be in state failed once the zip file is processed. + /// outputDir must be a directory. If it doesn't exist yet, it will be automatically created. + /// If flattenDirs is set to true, the directory structure of the zip file is not recreated. + /// Instead, all files are extracted into one single directory. + + ~Decompress(); + /// Destroys the Decompress. + + ZipArchive decompressAllFiles(); + /// Decompresses all files stored in the zip File. Can only be called once per Decompress object. + /// Use mapping to retrieve the location of the decompressed files + + bool handleZipEntry(std::istream& zipStream, const ZipLocalFileHeader& hdr); + + const ZipMapping& mapping() const; + /// A ZipMapping stores as key the full name of the ZipFileInfo/ZipLocalFileHeader and as value the decompressed file + /// If for a ZipFileInfo no mapping exists, there was an error during decompression and the entry is considered to be corrupt + +private: + Decompress(const Decompress&); + Decompress& operator=(const Decompress&); + + void onOk(const void*, std::pair& val); + +private: + std::istream& _in; + Poco::Path _outDir; + bool _flattenDirs; + bool _keepIncompleteFiles; + ZipMapping _mapping; +}; + + +inline const Decompress::ZipMapping& Decompress::mapping() const +{ + return _mapping; +} + + +} } // namespace Poco::Zip + + +#endif // Zip_Decompress_INCLUDED diff --git a/Zip/include/Poco/Zip/Delete.h b/Zip/include/Poco/Zip/Delete.h new file mode 100644 index 000000000..74af4ace8 --- /dev/null +++ b/Zip/include/Poco/Zip/Delete.h @@ -0,0 +1,70 @@ +// +// Delete.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/Delete.h#1 $ +// +// Library: Zip +// Package: Manipulation +// Module: Delete +// +// Definition of the Delete class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_Delete_INCLUDED +#define Zip_Delete_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Zip/ZipOperation.h" +#include "Poco/Zip/ZipLocalFileHeader.h" + + +namespace Poco { +namespace Zip { + + +class Zip_API Delete: public ZipOperation + /// Delete Operation removes an entry from a Zip +{ +public: + Delete(const ZipLocalFileHeader& hdr); + /// Creates the Delete. + + void execute(Compress& c, std::istream& input); + /// Throws away the ZipEntry + +private: + const ZipLocalFileHeader _hdr; +}; + + +} } // namespace Poco::Zip + + +#endif // Zip_Delete_INCLUDED diff --git a/Zip/include/Poco/Zip/Keep.h b/Zip/include/Poco/Zip/Keep.h new file mode 100644 index 000000000..7d91ede51 --- /dev/null +++ b/Zip/include/Poco/Zip/Keep.h @@ -0,0 +1,71 @@ +// +// Keep.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/Keep.h#1 $ +// +// Library: Zip +// Package: Manipulation +// Module: Keep +// +// Definition of the Keep class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_Keep_INCLUDED +#define Zip_Keep_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Zip/ZipOperation.h" +#include "Poco/Zip/ZipLocalFileHeader.h" + + +namespace Poco { +namespace Zip { + + +class Zip_API Keep: public ZipOperation + /// Keep simply forwards the compressed data stream from the input ZipArchive + /// to the output zip archive +{ +public: + Keep(const ZipLocalFileHeader& hdr); + /// Creates the Keep object. + + void execute(Compress& c, std::istream& input); + ///Adds a copy of the compressed input file to the ZipArchive + +private: + const ZipLocalFileHeader _hdr; +}; + + +} } // namespace Poco::Zip + + +#endif // Zip_Keep_INCLUDED diff --git a/Zip/include/Poco/Zip/ParseCallback.h b/Zip/include/Poco/Zip/ParseCallback.h new file mode 100644 index 000000000..fd166299f --- /dev/null +++ b/Zip/include/Poco/Zip/ParseCallback.h @@ -0,0 +1,76 @@ +// +// ParseCallback.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/ParseCallback.h#3 $ +// +// Library: Zip +// Package: Zip +// Module: ParseCallback +// +// Definition of the ParseCallback class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_ParseCallback_INCLUDED +#define Zip_ParseCallback_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include + + +namespace Poco { +namespace Zip { + + +class ZipLocalFileHeader; + + +class Zip_API ParseCallback + /// Interface for callbacks to handle ZipData +{ +public: + ParseCallback(); + /// Creates the ParseCallback. + + virtual ~ParseCallback(); + /// Destroys the ParseCallback. + + virtual bool handleZipEntry(std::istream& zipStream, const ZipLocalFileHeader& hdr) = 0; + /// Handles parsing of the data of a single Zip Entry. zipStream is guaranteed to be at the very first data byte. + /// Note that a callback class SHOULD consume all data inside a zip file, ie. after + /// processing the next 4 bytes point the next ZipLocalFileHeader or the ZipDirectory. + /// If it fails to do so, it must return false, otherwise true. + +}; + + +} } // namespace Poco::Zip + + +#endif // Zip_ParseCallback_INCLUDED diff --git a/Zip/include/Poco/Zip/PartialStream.h b/Zip/include/Poco/Zip/PartialStream.h new file mode 100644 index 000000000..78db319e6 --- /dev/null +++ b/Zip/include/Poco/Zip/PartialStream.h @@ -0,0 +1,209 @@ +// +// PartialStream.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/PartialStream.h#3 $ +// +// Library: Zip +// Package: Zip +// Module: PartialStream +// +// Definition of the PartialStream class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_PartialStream_INCLUDED +#define Zip_PartialStream_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/BufferedStreamBuf.h" +#include "Poco/Buffer.h" +#include +#include + + +namespace Poco { +namespace Zip { + + +class Zip_API PartialStreamBuf: public Poco::BufferedStreamBuf + /// A PartialStreamBuf is a class that limits one view on an inputstream to a selected view range +{ +public: + PartialStreamBuf(std::istream& in, std::ios::pos_type start, std::ios::pos_type end, const std::string& prefix, const std::string& postfix, bool initStream); + /// Creates the PartialStream. + /// If initStream is true the status of the stream will be cleared on the first access, and the stream will be repositioned + /// to position start + + PartialStreamBuf(std::ostream& out, std::size_t start, std::size_t end, bool initStream); + /// Creates the PartialStream. + /// If initStream is true the status of the stream will be cleared on the first access. + /// start and end acts as offset values for the written content. A start value greater than zero, + /// means that the first bytes are not written but discarded instead, + /// an end value not equal to zero means that the last end bytes are not written! + /// Examples: + /// start = 3; end = 1 + /// write("hello", 5) -> "l" + + ~PartialStreamBuf(); + /// Destroys the PartialStream. + + void close(); + /// Flushes a writing streambuf + + Poco::UInt64 bytesWritten() const; + +protected: + int readFromDevice(char* buffer, std::streamsize length); + + int writeToDevice(const char* buffer, std::streamsize length); + +private: + enum + { + STREAM_BUFFER_SIZE = 1024 + }; + + bool _initialized; + std::ios::pos_type _start; + Poco::UInt64 _numBytes; + Poco::UInt64 _bytesWritten; + std::istream* _pIstr; + std::ostream* _pOstr; + std::string _prefix; + std::string _postfix; + std::size_t _ignoreStart; + Poco::Buffer _buffer; + Poco::UInt32 _bufferOffset; +}; + + +inline Poco::UInt64 PartialStreamBuf::bytesWritten() const +{ + return _bytesWritten; +} + + +class Zip_API PartialIOS: public virtual std::ios + /// The base class for PartialInputStream and PartialOutputStream. + /// + /// This class is needed to ensure the correct initialization + /// order of the stream buffer and base classes. +{ +public: + PartialIOS(std::istream& istr, std::ios::pos_type start, std::ios::pos_type end, const std::string& prefix, const std::string& postfix, bool initStream); + /// Creates the basic stream and connects it + /// to the given input stream. + /// If initStream is true the status of the stream will be cleared on the first access, and the stream will be repositioned + /// to position start + + PartialIOS(std::ostream& ostr, std::size_t start, std::size_t end, bool initStream); + /// Creates the basic stream and connects it + /// to the given output stream. + /// If initStream is true the status of the stream will be cleared on the first access. + /// start and end acts as offset values for the written content. A start value greater than zero, + /// means that the first bytes are not written but discarded instead, + /// an end value not equal to zero means that the last end bytes are not written! + /// Examples: + /// start = 3; end = 1 + /// write("hello", 5) -> "l" + + ~PartialIOS(); + /// Destroys the stream. + + PartialStreamBuf* rdbuf(); + /// Returns a pointer to the underlying streambuf. + +protected: + PartialStreamBuf _buf; +}; + + +class Zip_API PartialInputStream: public PartialIOS, public std::istream + /// This stream copies all characters read through it + /// to one or multiple output streams. +{ +public: + PartialInputStream(std::istream& istr, std::ios::pos_type start, std::ios::pos_type end, bool initStream = true, const std::string& prefix = std::string(), const std::string& postfix = std::string()); + /// Creates the PartialInputStream and connects it + /// to the given input stream. Bytes read are guaranteed to be in the range [start, end-1] + /// If initStream is true the status of the stream will be cleared on the first access, and the stream will be repositioned + /// to position start + + ~PartialInputStream(); + /// Destroys the PartialInputStream. +}; + + +class Zip_API PartialOutputStream: public PartialIOS, public std::ostream + /// This stream copies all characters written to it + /// to one or multiple output streams. +{ +public: + PartialOutputStream(std::ostream& ostr, std::size_t start, std::size_t end, bool initStream = true); + /// Creates the PartialOutputStream and connects it + /// to the given output stream. Bytes written are guaranteed to be in the range [start, realEnd - end]. + /// If initStream is true the status of the stream will be cleared on the first access. + /// start and end acts as offset values for the written content. A start value greater than zero, + /// means that the first bytes are not written but discarded instead, + /// an end value not equal to zero means that the last end bytes are not written! + /// Examples: + /// start = 3; end = 1 + /// write("hello", 5) -> "l" + /// + /// start = 3; end = 0 + /// write("hello", 5) -> "lo" + + ~PartialOutputStream(); + /// Destroys the PartialOutputStream. + + void close(); + /// must be called for the stream to properly terminate it + + Poco::UInt64 bytesWritten() const; + /// Returns the number of bytes actually forwarded to the inner ostream +}; + + +inline void PartialOutputStream::close() +{ + flush(); + _buf.close(); +} + + +inline Poco::UInt64 PartialOutputStream::bytesWritten() const +{ + return _buf.bytesWritten(); +} + + +} } // namespace Poco::Zip + + +#endif // Zip_PartialStream_INCLUDED diff --git a/Zip/include/Poco/Zip/Rename.h b/Zip/include/Poco/Zip/Rename.h new file mode 100644 index 000000000..2cefb7d39 --- /dev/null +++ b/Zip/include/Poco/Zip/Rename.h @@ -0,0 +1,71 @@ +// +// Rename.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/Rename.h#1 $ +// +// Library: Zip +// Package: Manipulation +// Module: Rename +// +// Definition of the Rename class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_Rename_INCLUDED +#define Zip_Rename_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Zip/ZipOperation.h" +#include "Poco/Zip/ZipLocalFileHeader.h" + + +namespace Poco { +namespace Zip { + + +class Zip_API Rename: public ZipOperation + /// Renames an existing Zip Entry +{ +public: + Rename(const ZipLocalFileHeader& hdr, const std::string& newZipEntryName); + /// Creates the Rename. + + void execute(Compress& c, std::istream& input); + /// Performs the rename operation + +private: + const ZipLocalFileHeader _hdr; + const std::string _newZipEntryName; +}; + + +} } // namespace Poco::Zip + + +#endif // Zip_Rename_INCLUDED diff --git a/Zip/include/Poco/Zip/Replace.h b/Zip/include/Poco/Zip/Replace.h new file mode 100644 index 000000000..d92d9a39d --- /dev/null +++ b/Zip/include/Poco/Zip/Replace.h @@ -0,0 +1,72 @@ +// +// Replace.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/Replace.h#1 $ +// +// Library: Zip +// Package: Manipulation +// Module: Replace +// +// Definition of the Replace class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_Replace_INCLUDED +#define Zip_Replace_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Zip/Add.h" +#include "Poco/Zip/Delete.h" +#include "Poco/Zip/ZipOperation.h" + + +namespace Poco { +namespace Zip { + + +class Zip_API Replace: public ZipOperation + /// Operation Replace replaces the content of an existing entry with a new one +{ +public: + Replace(const ZipLocalFileHeader& hdr, const std::string& localPath); + /// Creates the Replace. + + void execute(Compress& c, std::istream& input); + /// Performs the replace operation + +private: + Delete _del; + Add _add; +}; + + +} } // namespace Poco::Zip + + +#endif // Zip_Replace_INCLUDED diff --git a/Zip/include/Poco/Zip/SkipCallback.h b/Zip/include/Poco/Zip/SkipCallback.h new file mode 100644 index 000000000..bee78664a --- /dev/null +++ b/Zip/include/Poco/Zip/SkipCallback.h @@ -0,0 +1,68 @@ +// +// SkipCallback.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/SkipCallback.h#3 $ +// +// Library: Zip +// Package: Zip +// Module: SkipCallback +// +// Definition of the SkipCallback class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_SkipCallback_INCLUDED +#define Zip_SkipCallback_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Zip/ParseCallback.h" + + +namespace Poco { +namespace Zip { + + +class Zip_API SkipCallback: public ParseCallback + /// A SkipCallback simply skips over the data +{ +public: + SkipCallback(); + /// Creates the SkipCallback. + + virtual ~SkipCallback(); + /// Destroys the SkipCallback. + + bool handleZipEntry(std::istream& zipStream, const ZipLocalFileHeader& hdr); +}; + + +} } // namespace Poco::Zip + + +#endif // Zip_SkipCallback_INCLUDED diff --git a/Zip/include/Poco/Zip/Zip.h b/Zip/include/Poco/Zip/Zip.h new file mode 100644 index 000000000..9d74f8e02 --- /dev/null +++ b/Zip/include/Poco/Zip/Zip.h @@ -0,0 +1,92 @@ +// +// Zip.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/Zip.h#4 $ +// +// Library: Zip +// Package: Zip +// Module: Zip +// +// Basic definitions for the Poco Zip library. +// This file must be the first file included by every other Zip +// header file. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_Zip_INCLUDED +#define Zip_Zip_INCLUDED + + +#include "Poco/Foundation.h" + + +// +// The following block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the Zip_EXPORTS +// symbol defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// Zip_API functions as being imported from a DLL, wheras this DLL sees symbols +// defined with this macro as being exported. +// +#if defined(_WIN32) && defined(POCO_DLL) + #if defined(Zip_EXPORTS) + #define Zip_API __declspec(dllexport) + #else + #define Zip_API __declspec(dllimport) + #endif +#endif + + +#if !defined(Zip_API) + #define Zip_API +#endif + + +// +// Automatically link Zip library. +// +#if defined(_MSC_VER) + #if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(Zip_EXPORTS) + #if defined(POCO_DLL) + #if defined(_DEBUG) + #pragma comment(lib, "PocoZipd.lib") + #else + #pragma comment(lib, "PocoZip.lib") + #endif + #else + #if defined(_DEBUG) + #pragma comment(lib, "PocoZipmtd.lib") + #else + #pragma comment(lib, "PocoZipmt.lib") + #endif + #endif + #endif +#endif + + +#endif // Zip_Zip_INCLUDED diff --git a/Zip/include/Poco/Zip/ZipArchive.h b/Zip/include/Poco/Zip/ZipArchive.h new file mode 100644 index 000000000..66dc22531 --- /dev/null +++ b/Zip/include/Poco/Zip/ZipArchive.h @@ -0,0 +1,136 @@ +// +// ZipArchive.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/ZipArchive.h#3 $ +// +// Library: Zip +// Package: Zip +// Module: ZipArchive +// +// Definition of the ZipArchive class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_ZipArchive_INCLUDED +#define Zip_ZipArchive_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Zip/ZipLocalFileHeader.h" +#include "Poco/Zip/ZipFileInfo.h" +#include "Poco/Zip/ZipArchiveInfo.h" +#include +#include + + +namespace Poco { +namespace Zip { + + +class ParseCallback; +class Compress; + + +class Zip_API ZipArchive + /// A ZipArchive contains information on the content of a zip file +{ +public: + typedef std::map FileHeaders; + typedef std::map FileInfos; + typedef std::map DirectoryInfos; + + ZipArchive(std::istream& in); + /// Creates the ZipArchive from a file. Note that the in stream will be in state failed after the constructor is finished + + ZipArchive(std::istream& in, ParseCallback& callback); + /// Creates the ZipArchive from a file or network stream. Note that the in stream will be in state failed after the constructor is finished + + ~ZipArchive(); + /// Destroys the ZipArchive. + + FileInfos::const_iterator fileInfoBegin() const; + + FileInfos::const_iterator fileInfoEnd() const; + + FileHeaders::const_iterator findHeader(const std::string& fileName) const; + + FileHeaders::const_iterator headerBegin() const; + + FileHeaders::const_iterator headerEnd() const; + +private: + void parse(std::istream& in, ParseCallback& pc); + + ZipArchive(const FileHeaders& entries, const FileInfos& infos, const DirectoryInfos& dirs ); + +private: + FileHeaders _entries; + /// Info generated by parsing the data block of the zip file + FileInfos _infos; + /// Info generated by parsing the directory block of the zip file + DirectoryInfos _disks; + /// Stores directory info for all found disks + + friend class Compress; +}; + + +inline ZipArchive::FileInfos::const_iterator ZipArchive::fileInfoBegin() const +{ + return _infos.begin(); +} + + +inline ZipArchive::FileInfos::const_iterator ZipArchive::fileInfoEnd() const +{ + return _infos.end(); +} + + +inline ZipArchive::FileHeaders::const_iterator ZipArchive::findHeader(const std::string& fileName) const +{ + return _entries.find(fileName); +} + + +inline ZipArchive::FileHeaders::const_iterator ZipArchive::headerBegin() const +{ + return _entries.begin(); +} + + +inline ZipArchive::FileHeaders::const_iterator ZipArchive::headerEnd() const +{ + return _entries.end(); +} + + +} } // namespace Poco::Zip + + +#endif // Zip_ZipArchive_INCLUDED diff --git a/Zip/include/Poco/Zip/ZipArchiveInfo.h b/Zip/include/Poco/Zip/ZipArchiveInfo.h new file mode 100644 index 000000000..3b4494de6 --- /dev/null +++ b/Zip/include/Poco/Zip/ZipArchiveInfo.h @@ -0,0 +1,210 @@ +// +// ZipArchiveInfo.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/ZipArchiveInfo.h#3 $ +// +// Library: Zip +// Package: Zip +// Module: ZipArchiveInfo +// +// Definition of the ZipArchiveInfo class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_ZipArchiveInfo_INCLUDED +#define Zip_ZipArchiveInfo_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Zip/ZipCommon.h" +#include "Poco/Zip/ZipUtil.h" + + +namespace Poco { +namespace Zip { + + +class Zip_API ZipArchiveInfo + /// A ZipArchiveInfo stores central directory info +{ +public: + static const char HEADER[ZipCommon::HEADER_SIZE]; + + ZipArchiveInfo(); + /// Default constructor, everything set to zero or empty + + ZipArchiveInfo(std::istream& in, bool assumeHeaderRead); + /// Creates the ZipArchiveInfo by parsing the input stream. + /// If assumeHeaderRead is true we assume that the first 4 bytes were already read outside. + + ~ZipArchiveInfo(); + /// Destroys the ZipArchiveInfo. + + Poco::UInt16 getDiskNumber() const; + /// Get the number of the disk where this header can be found + + Poco::UInt16 getFirstDiskForDirectoryHeader() const; + /// Returns the number of the disk that contains the start of the directory header + + Poco::UInt16 getNumberOfEntries() const; + /// Returns the number of entries on this disk + + Poco::UInt16 getTotalNumberOfEntries() const; + /// Returns the total number of entries on all disks + + Poco::UInt32 getCentralDirectorySize() const; + /// Returns the size of the central directory in bytes + + std::streamoff getHeaderOffset() const; + /// Returns the offset of the header in relation to the begin of this disk + + const std::string& getZipComment() const; + /// Returns the (optional) Zip Comment + + void setNumberOfEntries(Poco::UInt16 val); + /// Returns the number of entries on this disk + + void setTotalNumberOfEntries(Poco::UInt16 val); + /// Returns the total number of entries on all disks + + void setCentralDirectorySize(Poco::UInt32 val); + /// Returns the size of the central directory in bytes + + void setHeaderOffset(Poco::UInt32 val); + + std::string createHeader() const; + /// Creates a header + +private: + void parse(std::istream& inp, bool assumeHeaderRead); + + Poco::UInt16 getZipCommentSize() const; + +private: + enum + { + HEADER_POS = 0, + NUMBEROFTHISDISK_POS = HEADER_POS + ZipCommon::HEADER_SIZE, + NUMBEROFTHISDISK_SIZE = 2, + NUMBEROFCENTRALDIRDISK_POS = NUMBEROFTHISDISK_POS + NUMBEROFTHISDISK_SIZE, + NUMBEROFCENTRALDIRDISK_SIZE = 2, + NUMENTRIESTHISDISK_POS = NUMBEROFCENTRALDIRDISK_POS + NUMBEROFCENTRALDIRDISK_SIZE, + NUMENTRIESTHISDISK_SIZE = 2, + TOTALNUMENTRIES_POS = NUMENTRIESTHISDISK_POS + NUMENTRIESTHISDISK_SIZE, + TOTALNUMENTRIES_SIZE = 2, + CENTRALDIRSIZE_POS = TOTALNUMENTRIES_POS + TOTALNUMENTRIES_SIZE, + CENTRALDIRSIZE_SIZE = 4, + CENTRALDIRSTARTOFFSET_POS = CENTRALDIRSIZE_POS + CENTRALDIRSIZE_SIZE, + CENTRALDIRSTARTOFFSET_SIZE = 4, + ZIPCOMMENT_LENGTH_POS = CENTRALDIRSTARTOFFSET_POS + CENTRALDIRSTARTOFFSET_SIZE, + ZIPCOMMENT_LENGTH_SIZE = 2, + FULLHEADER_SIZE = 22 + }; + + char _rawInfo[FULLHEADER_SIZE]; + std::streamoff _startPos; + std::string _comment; +}; + + +inline Poco::UInt16 ZipArchiveInfo::getDiskNumber() const +{ + return ZipUtil::get16BitValue(_rawInfo, NUMBEROFTHISDISK_POS); +} + + +inline Poco::UInt16 ZipArchiveInfo::getFirstDiskForDirectoryHeader() const +{ + return ZipUtil::get16BitValue(_rawInfo, NUMBEROFCENTRALDIRDISK_POS); +} + + +inline Poco::UInt16 ZipArchiveInfo::getNumberOfEntries() const +{ + return ZipUtil::get16BitValue(_rawInfo, NUMENTRIESTHISDISK_POS); +} + + +inline Poco::UInt16 ZipArchiveInfo::getTotalNumberOfEntries() const +{ + return ZipUtil::get16BitValue(_rawInfo, TOTALNUMENTRIES_POS); +} + + +inline Poco::UInt32 ZipArchiveInfo::getCentralDirectorySize() const +{ + return ZipUtil::get32BitValue(_rawInfo, CENTRALDIRSIZE_POS); +} + + +inline std::streamoff ZipArchiveInfo::getHeaderOffset() const +{ + return _startPos; +} + + +inline Poco::UInt16 ZipArchiveInfo::getZipCommentSize() const +{ + return ZipUtil::get16BitValue(_rawInfo, ZIPCOMMENT_LENGTH_POS); +} + + +inline const std::string& ZipArchiveInfo::getZipComment() const +{ + return _comment; +} + + +inline void ZipArchiveInfo::setNumberOfEntries(Poco::UInt16 val) +{ + ZipUtil::set16BitValue(val, _rawInfo, NUMENTRIESTHISDISK_POS); +} + + +inline void ZipArchiveInfo::setTotalNumberOfEntries(Poco::UInt16 val) +{ + ZipUtil::set16BitValue(val, _rawInfo, TOTALNUMENTRIES_POS); +} + + +inline void ZipArchiveInfo::setCentralDirectorySize(Poco::UInt32 val) +{ + ZipUtil::set32BitValue(val, _rawInfo, CENTRALDIRSIZE_POS); +} + + +inline void ZipArchiveInfo::setHeaderOffset(Poco::UInt32 val) +{ + ZipUtil::set32BitValue(val, _rawInfo, CENTRALDIRSTARTOFFSET_POS); +} + + +} } // namespace Poco::Zip + + +#endif // Zip_ZipArchiveInfo_INCLUDED diff --git a/Zip/include/Poco/Zip/ZipCommon.h b/Zip/include/Poco/Zip/ZipCommon.h new file mode 100644 index 000000000..a8ec5f9d6 --- /dev/null +++ b/Zip/include/Poco/Zip/ZipCommon.h @@ -0,0 +1,119 @@ +// +// ZipCommon.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/ZipCommon.h#3 $ +// +// Library: Zip +// Package: Zip +// Module: ZipCommon +// +// Definition of the ZipCommon class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_ZipCommon_INCLUDED +#define Zip_ZipCommon_INCLUDED + + +#include "Poco/Zip/Zip.h" + + +namespace Poco { +namespace Zip { + + +class Zip_API ZipCommon + /// Common enums used in the Zip project +{ +public: + enum + { + HEADER_SIZE = 4 + }; + + enum CompressionMethod + { + CM_STORE = 0, + CM_SHRUNK = 1, + CM_FACTOR1 = 2, + CM_FACTOR2 = 3, + CM_FACTOR3 = 4, + CM_FACTOR4 = 5, + CM_IMPLODE = 6, + CM_TOKENIZE= 7, + CM_DEFLATE = 8, + CM_ENHANCEDDEFLATE = 9, + CM_DATECOMPRIMPLODING = 10, + CM_UNUSED = 11 + }; + + enum CompressionLevel + { + CL_NORMAL = 0, + CL_MAXIMUM = 1, + CL_FAST = 2, + CL_SUPERFAST = 3 + }; + + enum HostSystem + { + HS_FAT = 0, // + PKZIPW 2.50 VFAT, NTFS + HS_AMIGA = 1, + HS_VMS = 2, + HS_UNIX = 3, + HS_VM_CMS = 4, + HS_ATARI = 5, + HS_HPFS = 6, + HS_MACINTOSH = 7, + HS_ZSYSTEM = 8, + HS_CP_M = 9, + HS_TOPS20 = 10, // used by pkzip2.5 to indicate ntfs + HS_NTFS = 11, + HS_SMS_QDOS = 12, + HS_ACORN = 13, + HS_VFAT = 14, + HS_MVS = 15, + HS_BEOS = 16, + HS_TANDEM = 17, + HS_UNUSED = 18, + }; + + enum FileType + { + FT_BINARY= 0, + FT_ASCII = 1 + }; + + static const std::string ILLEGAL_PATH; +}; + + +} } // namespace Poco::Zip + + +#endif // Zip_ZipCommon_INCLUDED diff --git a/Zip/include/Poco/Zip/ZipDataInfo.h b/Zip/include/Poco/Zip/ZipDataInfo.h new file mode 100644 index 000000000..7823907cd --- /dev/null +++ b/Zip/include/Poco/Zip/ZipDataInfo.h @@ -0,0 +1,160 @@ +// +// ZipDataInfo.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/ZipDataInfo.h#3 $ +// +// Library: Zip +// Package: Zip +// Module: ZipDataInfo +// +// Definition of the ZipDataInfo class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_ZipDataInfo_INCLUDED +#define Zip_ZipDataInfo_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Zip/ZipCommon.h" +#include "Poco/Zip/ZipUtil.h" + + +namespace Poco { +namespace Zip { + + +class Zip_API ZipDataInfo + /// A ZipDataInfo stores a Zip data descriptor +{ +public: + static const char HEADER[ZipCommon::HEADER_SIZE]; + + ZipDataInfo(); + /// Creates a header with all fields (except the header field) set to 0 + + ZipDataInfo(std::istream& in, bool assumeHeaderRead); + /// Creates the ZipDataInfo. + + ~ZipDataInfo(); + /// Destroys the ZipDataInfo. + + bool isValid() const; + + Poco::UInt32 getCRC32() const; + + void setCRC32(Poco::UInt32 crc); + + Poco::UInt32 getCompressedSize() const; + + void setCompressedSize(Poco::UInt32 size); + + Poco::UInt32 getUncompressedSize() const; + + void setUncompressedSize(Poco::UInt32 size); + + static Poco::UInt32 getFullHeaderSize(); + + const char* getRawHeader() const; + +private: + enum + { + HEADER_POS = 0, + CRC32_POS = HEADER_POS + ZipCommon::HEADER_SIZE, + CRC32_SIZE = 4, + COMPRESSED_POS = CRC32_POS + CRC32_SIZE, + COMPRESSED_SIZE = 4, + UNCOMPRESSED_POS = COMPRESSED_POS + COMPRESSED_SIZE, + UNCOMPRESSED_SIZE = 4, + FULLHEADER_SIZE = UNCOMPRESSED_POS + UNCOMPRESSED_SIZE + }; + + char _rawInfo[FULLHEADER_SIZE]; + bool _valid; +}; + + +inline const char* ZipDataInfo::getRawHeader() const +{ + return _rawInfo; +} + + +inline bool ZipDataInfo::isValid() const +{ + return _valid; +} + + +inline Poco::UInt32 ZipDataInfo::getCRC32() const +{ + return ZipUtil::get32BitValue(_rawInfo, CRC32_POS); +} + + +inline void ZipDataInfo::setCRC32(Poco::UInt32 crc) +{ + return ZipUtil::set32BitValue(crc, _rawInfo, CRC32_POS); +} + + +inline Poco::UInt32 ZipDataInfo::getCompressedSize() const +{ + return ZipUtil::get32BitValue(_rawInfo, COMPRESSED_POS); +} + + +inline void ZipDataInfo::setCompressedSize(Poco::UInt32 size) +{ + return ZipUtil::set32BitValue(size, _rawInfo, COMPRESSED_POS); +} + + +inline Poco::UInt32 ZipDataInfo::getUncompressedSize() const +{ + return ZipUtil::get32BitValue(_rawInfo, UNCOMPRESSED_POS); +} + + +inline void ZipDataInfo::setUncompressedSize(Poco::UInt32 size) +{ + return ZipUtil::set32BitValue(size, _rawInfo, UNCOMPRESSED_POS); +} + + +inline Poco::UInt32 ZipDataInfo::getFullHeaderSize() +{ + return FULLHEADER_SIZE; +} + + +} } // namespace Poco::Zip + + +#endif // Zip_ZipDataInfo_INCLUDED diff --git a/Zip/include/Poco/Zip/ZipException.h b/Zip/include/Poco/Zip/ZipException.h new file mode 100644 index 000000000..b70209794 --- /dev/null +++ b/Zip/include/Poco/Zip/ZipException.h @@ -0,0 +1,58 @@ +// +// ZipException.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/ZipException.h#4 $ +// +// Library: Zip +// Package: Zip +// Module: ZipException +// +// Definition of the ZipException class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_ZipException_INCLUDED +#define Zip_ZipException_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Exception.h" + + +namespace Poco { +namespace Zip { + + +POCO_DECLARE_EXCEPTION(Zip_API, ZipException, Poco::RuntimeException) +POCO_DECLARE_EXCEPTION(Zip_API, ZipManipulationException, ZipException) + + +} } // namespace Poco::Zip + + +#endif // Zip_ZipException_INCLUDED diff --git a/Zip/include/Poco/Zip/ZipFileInfo.h b/Zip/include/Poco/Zip/ZipFileInfo.h new file mode 100644 index 000000000..b18c22b25 --- /dev/null +++ b/Zip/include/Poco/Zip/ZipFileInfo.h @@ -0,0 +1,468 @@ +// +// ZipFileInfo.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/ZipFileInfo.h#3 $ +// +// Library: Zip +// Package: Zip +// Module: ZipFileInfo +// +// Definition of the ZipFileInfo class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_ZipFileInfo_INCLUDED +#define Zip_ZipFileInfo_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Zip/ZipCommon.h" +#include "Poco/Zip/ZipUtil.h" + + +namespace Poco { +namespace Zip { + + +class ZipLocalFileHeader; + + +class Zip_API ZipFileInfo + /// Stores a Zip directory entry of a file +{ +public: + static const char HEADER[ZipCommon::HEADER_SIZE]; + + ZipFileInfo(const ZipLocalFileHeader& header); + /// Creates a ZipFileInfo from a ZipLocalFileHeader + + ZipFileInfo(std::istream& in, bool assumeHeaderRead); + /// Creates the ZipFileInfo by parsing the input stream. + /// If assumeHeaderRead is true we assume that the first 4 bytes were already read outside. + + ~ZipFileInfo(); + /// Destroys the ZipFileInfo. + + Poco::UInt32 getRelativeOffsetOfLocalHeader() const; + /// Where on the disk starts the localheader. Combined with the disk number gives the exact location of the header + + ZipCommon::CompressionMethod getCompressionMethod() const; + + bool isEncrypted() const; + + const Poco::DateTime& lastModifiedAt() const; + + Poco::UInt32 getCRC() const; + + Poco::UInt32 getHeaderSize() const; + /// Returns the total size of the header including filename + other additional fields + + Poco::UInt32 getCompressedSize() const; + + Poco::UInt32 getUncompressedSize() const; + + const std::string& getFileName() const; + + bool isFile() const; + + bool isDirectory() const; + + bool hasExtraField() const; + + const std::string& getExtraField() const; + + const std::string& getFileComment() const; + + void getVersionMadeBy(int& major, int& minor); + /// The ZIP version used to create the file + + void getRequiredVersion(int& major, int& minor); + /// The minimum version required to extract the data + + ZipCommon::HostSystem getHostSystem() const; + + Poco::UInt16 getDiskNumberStart() const; + /// The number of the disk on which this file begins (multidisk archives) + + ZipCommon::FileType getFileType() const; + /// Binary or ASCII file? + + std::string createHeader() const; + + void setOffset(Poco::UInt32 val); + +private: + void setCRC(Poco::UInt32 val); + + void setCompressedSize(Poco::UInt32 val); + + void setUncompressedSize(Poco::UInt32 val); + + void setCompressionMethod(ZipCommon::CompressionMethod cm); + + void setCompressionLevel(ZipCommon::CompressionLevel cl); + + void setRequiredVersion(int major, int minor); + + void setHostSystem(ZipCommon::HostSystem hs); + + void setLastModifiedAt(const Poco::DateTime& dt); + + void setEncryption(bool val); + + void setFileNameLength(Poco::UInt16 size); + + void setFileName(const std::string& str); + + void parse(std::istream& in, bool assumeHeaderRead); + + void parseDateTime(); + + Poco::UInt32 getCRCFromHeader() const; + + Poco::UInt32 getCompressedSizeFromHeader() const; + + Poco::UInt32 getUncompressedSizeFromHeader() const; + + Poco::UInt16 getFileNameLength() const; + + Poco::UInt16 getExtraFieldLength() const; + + Poco::UInt16 getFileCommentLength() const; + + Poco::UInt32 getExternalFileAttributes() const; + +private: + enum + { + HEADER_POS = 0, + VERSIONMADEBY_POS = HEADER_POS + ZipCommon::HEADER_SIZE, + VERSIONMADEBY_SIZE = 2, + VERSION_NEEDED_POS = VERSIONMADEBY_POS + VERSIONMADEBY_SIZE, + VERSION_NEEDED_SIZE = 2, + GENERAL_PURPOSE_POS = VERSION_NEEDED_POS + VERSION_NEEDED_SIZE, + GENERAL_PURPOSE_SIZE = 2, + COMPR_METHOD_POS = GENERAL_PURPOSE_POS + GENERAL_PURPOSE_SIZE, + COMPR_METHOD_SIZE = 2, + LASTMODFILETIME_POS = COMPR_METHOD_POS + COMPR_METHOD_SIZE, + LASTMODFILETIME_SIZE = 2, + LASTMODFILEDATE_POS = LASTMODFILETIME_POS + LASTMODFILETIME_SIZE, + LASTMODFILEDATE_SIZE = 2, + CRC32_POS = LASTMODFILEDATE_POS + LASTMODFILEDATE_SIZE, + CRC32_SIZE = 4, + COMPRESSED_SIZE_POS = CRC32_POS + CRC32_SIZE, + COMPRESSED_SIZE_SIZE = 4, + UNCOMPRESSED_SIZE_POS = COMPRESSED_SIZE_POS + COMPRESSED_SIZE_SIZE, + UNCOMPRESSED_SIZE_SIZE = 4, + FILENAME_LENGTH_POS = UNCOMPRESSED_SIZE_POS + UNCOMPRESSED_SIZE_SIZE, + FILENAME_LENGTH_SIZE = 2, + EXTRAFIELD_LENGTH_POS = FILENAME_LENGTH_POS + FILENAME_LENGTH_SIZE, + EXTRAFIELD_LENGTH_SIZE = 2, + FILECOMMENT_LENGTH_POS = EXTRAFIELD_LENGTH_POS + EXTRAFIELD_LENGTH_SIZE, + FILECOMMENT_LENGTH_SIZE = 2, + DISKNUMBERSTART_POS = FILECOMMENT_LENGTH_POS + FILECOMMENT_LENGTH_SIZE, + DISKNUMBERSTART_SIZE = 2, + INTERNALFILE_ATTR_POS = DISKNUMBERSTART_POS + DISKNUMBERSTART_SIZE, + INTERNALFILE_ATTR_SIZE = 2, + EXTERNALFILE_ATTR_POS = INTERNALFILE_ATTR_POS + INTERNALFILE_ATTR_SIZE, + EXTERNALFILE_ATTR_SIZE = 4, + RELATIVEOFFSETLOCALHEADER_POS = EXTERNALFILE_ATTR_POS + EXTERNALFILE_ATTR_SIZE, + RELATIVEOFFSETLOCALHEADER_SIZE = 4, + FULLHEADER_SIZE = 46 + }; + + char _rawInfo[FULLHEADER_SIZE]; + Poco::UInt32 _crc32; + Poco::UInt32 _compressedSize; + Poco::UInt32 _uncompressedSize; + std::string _fileName; + Poco::DateTime _lastModifiedAt; + std::string _extraField; + std::string _fileComment; +}; + + +inline Poco::UInt32 ZipFileInfo::getRelativeOffsetOfLocalHeader() const +{ + return ZipUtil::get32BitValue(_rawInfo, RELATIVEOFFSETLOCALHEADER_POS); +} + + +inline Poco::UInt32 ZipFileInfo::getCRCFromHeader() const +{ + return ZipUtil::get32BitValue(_rawInfo, CRC32_POS); +} + + +inline Poco::UInt32 ZipFileInfo::getCompressedSizeFromHeader() const +{ + return ZipUtil::get32BitValue(_rawInfo, COMPRESSED_SIZE_POS); +} + + +inline Poco::UInt32 ZipFileInfo::getUncompressedSizeFromHeader() const +{ + return ZipUtil::get32BitValue(_rawInfo, UNCOMPRESSED_SIZE_POS); +} + + +inline void ZipFileInfo::parseDateTime() +{ + _lastModifiedAt = ZipUtil::parseDateTime(_rawInfo, LASTMODFILETIME_POS, LASTMODFILEDATE_POS); +} + + +inline ZipCommon::CompressionMethod ZipFileInfo::getCompressionMethod() const +{ + return static_cast(ZipUtil::get16BitValue(_rawInfo, COMPR_METHOD_POS)); +} + + +inline bool ZipFileInfo::isEncrypted() const +{ + // bit 0 indicates encryption + return ((ZipUtil::get16BitValue(_rawInfo, GENERAL_PURPOSE_POS) & 0x0001) != 0); +} + + +inline const Poco::DateTime& ZipFileInfo::lastModifiedAt() const +{ + return _lastModifiedAt; +} + + +inline Poco::UInt32 ZipFileInfo::getCRC() const +{ + return _crc32; +} + + +inline Poco::UInt32 ZipFileInfo::getCompressedSize() const +{ + return _compressedSize; +} + + +inline Poco::UInt32 ZipFileInfo::getUncompressedSize() const +{ + return _uncompressedSize; +} + + +inline const std::string& ZipFileInfo::getFileName() const +{ + return _fileName; +} + + +inline bool ZipFileInfo::isFile() const +{ + return !isDirectory(); +} + + +inline bool ZipFileInfo::isDirectory() const +{ + poco_assert_dbg(!_fileName.empty()); + return getUncompressedSize() == 0 && getCompressionMethod() == ZipCommon::CM_STORE && _fileName[_fileName.length()-1] == '/'; +} + + +inline Poco::UInt16 ZipFileInfo::getFileNameLength() const +{ + return ZipUtil::get16BitValue(_rawInfo, FILENAME_LENGTH_POS); +} + + +inline Poco::UInt16 ZipFileInfo::getExtraFieldLength() const +{ + return ZipUtil::get16BitValue(_rawInfo, EXTRAFIELD_LENGTH_POS); +} + + +inline bool ZipFileInfo::hasExtraField() const +{ + return getExtraFieldLength() > 0; +} + + +inline const std::string& ZipFileInfo::getExtraField() const +{ + return _extraField; +} + + +inline const std::string& ZipFileInfo::getFileComment() const +{ + return _fileComment; +} + + +inline Poco::UInt16 ZipFileInfo::getFileCommentLength() const +{ + return ZipUtil::get16BitValue(_rawInfo, FILECOMMENT_LENGTH_POS); +} + + +inline void ZipFileInfo::getVersionMadeBy(int& major, int& minor) +{ + major = (_rawInfo[VERSIONMADEBY_POS]/10); + minor = (_rawInfo[VERSIONMADEBY_POS]%10); +} + + +inline void ZipFileInfo::getRequiredVersion(int& major, int& minor) +{ + major = (_rawInfo[VERSION_NEEDED_POS]/10); + minor = (_rawInfo[VERSION_NEEDED_POS]%10); +} + + +inline ZipCommon::HostSystem ZipFileInfo::getHostSystem() const +{ + return static_cast(_rawInfo[VERSION_NEEDED_POS + 1]); +} + + +inline Poco::UInt16 ZipFileInfo::getDiskNumberStart() const +{ + return ZipUtil::get16BitValue(_rawInfo, DISKNUMBERSTART_POS); +} + + +inline ZipCommon::FileType ZipFileInfo::getFileType() const +{ + return static_cast(_rawInfo[INTERNALFILE_ATTR_POS] & 0x01); +} + + +inline Poco::UInt32 ZipFileInfo::getExternalFileAttributes() const +{ + return ZipUtil::get32BitValue(_rawInfo, EXTERNALFILE_ATTR_POS); +} + + +inline Poco::UInt32 ZipFileInfo::getHeaderSize() const +{ + return FULLHEADER_SIZE + getFileNameLength() + getExtraFieldLength() + getFileCommentLength(); +} + + +inline void ZipFileInfo::setCRC(Poco::UInt32 val) +{ + _crc32 = val; + ZipUtil::set32BitValue(val, _rawInfo, CRC32_POS); +} + + +inline void ZipFileInfo::setOffset(Poco::UInt32 val) +{ + ZipUtil::set32BitValue(val, _rawInfo, RELATIVEOFFSETLOCALHEADER_POS); +} + + +inline void ZipFileInfo::setCompressedSize(Poco::UInt32 val) +{ + _compressedSize = val; + ZipUtil::set32BitValue(val, _rawInfo, COMPRESSED_SIZE_POS); +} + + +inline void ZipFileInfo::setUncompressedSize(Poco::UInt32 val) +{ + _uncompressedSize = val; + ZipUtil::set32BitValue(val, _rawInfo, UNCOMPRESSED_SIZE_POS); +} + + +inline void ZipFileInfo::setCompressionMethod(ZipCommon::CompressionMethod cm) +{ + ZipUtil::set16BitValue(static_cast(cm), _rawInfo, COMPR_METHOD_POS); +} + + +inline void ZipFileInfo::setCompressionLevel(ZipCommon::CompressionLevel cl) +{ + // bit 1 and 2 indicate the level + Poco::UInt16 val = static_cast(cl); + val <<= 1; + Poco::UInt16 mask = 0xfff9; + _rawInfo[GENERAL_PURPOSE_POS] = ((_rawInfo[GENERAL_PURPOSE_POS] & mask) | val); +} + + +inline void ZipFileInfo::setFileNameLength(Poco::UInt16 size) +{ + ZipUtil::set16BitValue(size, _rawInfo, FILENAME_LENGTH_POS); +} + + +inline void ZipFileInfo::setHostSystem(ZipCommon::HostSystem hs) +{ + _rawInfo[VERSIONMADEBY_POS + 1] = static_cast(hs); + _rawInfo[VERSION_NEEDED_POS + 1] = static_cast(hs); +} + + +inline void ZipFileInfo::setRequiredVersion(int major, int minor) +{ + poco_assert (minor < 10); + poco_assert (major < 24); + Poco::UInt8 val = static_cast(major)*10+static_cast(minor); + _rawInfo[VERSIONMADEBY_POS] = static_cast(val); + _rawInfo[VERSION_NEEDED_POS] = static_cast(val); +} + + +inline void ZipFileInfo::setLastModifiedAt(const Poco::DateTime& dt) +{ + _lastModifiedAt = dt; + ZipUtil::setDateTime(dt, _rawInfo, LASTMODFILETIME_POS, LASTMODFILEDATE_POS); +} + + +inline void ZipFileInfo::setEncryption(bool val) +{ + if (val) + _rawInfo[GENERAL_PURPOSE_POS] |= 0x01; + else + _rawInfo[GENERAL_PURPOSE_POS] &= 0xfe; +} + + +inline void ZipFileInfo::setFileName(const std::string& str) +{ + _fileName = str; + setFileNameLength(static_cast(str.size())); +} + + +} } // namespace Poco::Zip + + +#endif // Zip_ZipFileInfo_INCLUDED diff --git a/Zip/include/Poco/Zip/ZipLocalFileHeader.h b/Zip/include/Poco/Zip/ZipLocalFileHeader.h new file mode 100644 index 000000000..79fe1b9fc --- /dev/null +++ b/Zip/include/Poco/Zip/ZipLocalFileHeader.h @@ -0,0 +1,486 @@ +// +// ZipLocalFileHeader.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/ZipLocalFileHeader.h#4 $ +// +// Library: Zip +// Package: Zip +// Module: ZipLocalFileHeader +// +// Definition of the ZipLocalFileHeader class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_ZipLocalFileHeader_INCLUDED +#define Zip_ZipLocalFileHeader_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Zip/ZipUtil.h" +#include "Poco/Zip/ZipCommon.h" +#include "Poco/DateTime.h" +#include "Poco/Path.h" +#include + + +namespace Poco { +namespace Zip { + + +class ParseCallback; + + +class Zip_API ZipLocalFileHeader + /// Stores a Zip local file header +{ +public: + static const char HEADER[ZipCommon::HEADER_SIZE]; + + ZipLocalFileHeader(const Poco::Path& fileName, const Poco::DateTime& lastModifiedAt, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl); + /// Creates a zip file header from an absoluteFile. fileName is the name of the file in the zip, outputIsSeekable determines if we write + /// CRC and file sizes to the LocalFileHeader or after data compression into a ZipDataInfo + + ZipLocalFileHeader(std::istream& inp, bool assumeHeaderRead, ParseCallback& callback); + /// Creates the ZipLocalFileHeader by parsing the input stream. + /// If assumeHeaderRead is true we assume that the first 4 bytes were already read outside. + /// If skipOverDataBlock is true we position the stream after the data block (either at the next FileHeader or the Directory Entry) + + virtual ~ZipLocalFileHeader(); + /// Destroys the ZipLocalFileHeader. + + ZipCommon::HostSystem getHostSystem() const; + + int getMajorVersionNumber() const; + + int getMinorVersionNumber() const; + + void getRequiredVersion(int& major, int& minor); + /// The minimum version required to extract the data + + Poco::UInt32 getHeaderSize() const; + /// Returns the total size of the header including filename + extra field size + + void setStartPos(std::streamoff start); + /// Sets the start position to start and the end position to start+compressedSize + + std::streamoff getStartPos() const; + /// Returns the position of the first byte of the header in the file stream + + std::streamoff getEndPos() const; + /// Points past the last byte of the file entry (ie. either the first byte of the next header, or the directory) + + std::streamoff getDataStartPos() const; + /// Returns the streamoffset for the very first byte of data. Will be equal to DataEndPos if no data present + + std::streamoff getDataEndPos() const; + + ZipCommon::CompressionMethod getCompressionMethod() const; + + ZipCommon::CompressionLevel getCompressionLevel() const; + /// Returns the compression level used. Only valid when the compression method is CM_DEFLATE + + bool isEncrypted() const; + + const Poco::DateTime& lastModifiedAt() const; + + Poco::UInt32 getCRC() const; + + Poco::UInt32 getCompressedSize() const; + + Poco::UInt32 getUncompressedSize() const; + + void setCRC(Poco::UInt32 val); + + void setCompressedSize(Poco::UInt32 val); + + void setUncompressedSize(Poco::UInt32 val); + + const std::string& getFileName() const; + + bool isFile() const; + + bool isDirectory() const; + + bool hasExtraField() const; + + const std::string& getExtraField() const; + + bool hasData() const; + + bool searchCRCAndSizesAfterData() const; + + void setSearchCRCAndSizesAfterData(bool val); + + void setFileName(const std::string& fileName, bool isDirectory); + + std::string createHeader() const; + /// Creates a header + +private: + void parse(std::istream& inp, bool assumeHeaderRead); + + void parseDateTime(); + + void init(const Poco::Path& fileName, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl); + + Poco::UInt16 getFileNameLength() const; + + Poco::UInt16 getExtraFieldLength() const; + + Poco::UInt32 getCRCFromHeader() const; + + Poco::UInt32 getCompressedSizeFromHeader() const; + + Poco::UInt32 getUncompressedSizeFromHeader() const; + + void setRequiredVersion(int major, int minor); + + void setHostSystem(ZipCommon::HostSystem hs); + + void setLastModifiedAt(const Poco::DateTime& dt); + + void setEncryption(bool val); + + void setFileNameLength(Poco::UInt16 size); + + void setExtraFieldSize(Poco::UInt16 size); + + void setCompressionMethod(ZipCommon::CompressionMethod cm); + + void setCompressionLevel(ZipCommon::CompressionLevel cl); + +private: + enum + { + HEADER_POS = 0, + VERSION_SIZE = 2, + VERSION_POS = HEADER_POS+ZipCommon::HEADER_SIZE, + GENERAL_PURPOSE_SIZE = 2, + GENERAL_PURPOSE_POS = VERSION_POS + VERSION_SIZE, + COMPR_METHOD_SIZE = 2, + COMPR_METHOD_POS = GENERAL_PURPOSE_POS + GENERAL_PURPOSE_SIZE, + LASTMODEFILETIME_SIZE = 2, + LASTMODEFILETIME_POS = COMPR_METHOD_POS + COMPR_METHOD_SIZE, + LASTMODEFILEDATE_SIZE = 2, + LASTMODEFILEDATE_POS = LASTMODEFILETIME_POS + LASTMODEFILETIME_SIZE, + CRC32_SIZE = 4, + CRC32_POS = LASTMODEFILEDATE_POS + LASTMODEFILEDATE_SIZE, + COMPRESSEDSIZE_SIZE = 4, + COMPRESSEDSIZE_POS = CRC32_POS + CRC32_SIZE, + UNCOMPRESSEDSIZE_SIZE = 4, + UNCOMPRESSEDSIZE_POS = COMPRESSEDSIZE_POS + COMPRESSEDSIZE_SIZE, + FILELENGTH_SIZE = 2, + FILELENGTH_POS = UNCOMPRESSEDSIZE_POS + UNCOMPRESSEDSIZE_SIZE, + EXTRAFIELD_LENGTH = 2, + EXTRAFIELD_POS = FILELENGTH_POS + FILELENGTH_SIZE, + FULLHEADER_SIZE = 30 + }; + + char _rawHeader[FULLHEADER_SIZE]; + std::streamoff _startPos; + std::streamoff _endPos; + std::string _fileName; + Poco::DateTime _lastModifiedAt; + std::string _extraField; + Poco::UInt32 _crc32; + Poco::UInt32 _compressedSize; + Poco::UInt32 _uncompressedSize; +}; + + +inline void ZipLocalFileHeader::setFileNameLength(Poco::UInt16 size) +{ + ZipUtil::set16BitValue(size, _rawHeader, FILELENGTH_POS); +} + + +inline void ZipLocalFileHeader::setExtraFieldSize(Poco::UInt16 size) +{ + ZipUtil::set16BitValue(size, _rawHeader, EXTRAFIELD_POS); +} + + +inline ZipCommon::HostSystem ZipLocalFileHeader::getHostSystem() const +{ + return static_cast(_rawHeader[VERSION_POS + 1]); +} + + +inline void ZipLocalFileHeader::setHostSystem(ZipCommon::HostSystem hs) +{ + _rawHeader[VERSION_POS + 1] = static_cast(hs); +} + + +inline int ZipLocalFileHeader::getMajorVersionNumber() const +{ + return (_rawHeader[VERSION_POS]/10); +} + + +inline int ZipLocalFileHeader::getMinorVersionNumber() const +{ + return (_rawHeader[VERSION_POS]%10); +} + + +inline void ZipLocalFileHeader::getRequiredVersion(int& major, int& minor) +{ + major = getMajorVersionNumber(); + minor = getMinorVersionNumber(); +} + + +inline void ZipLocalFileHeader::setRequiredVersion(int major, int minor) +{ + poco_assert (minor < 10); + poco_assert (major < 24); + _rawHeader[VERSION_POS] = static_cast(static_cast(major)*10+static_cast(minor)); +} + +inline Poco::UInt16 ZipLocalFileHeader::getFileNameLength() const +{ + return ZipUtil::get16BitValue(_rawHeader, FILELENGTH_POS); +} + + +inline Poco::UInt16 ZipLocalFileHeader::getExtraFieldLength() const +{ + return ZipUtil::get16BitValue(_rawHeader, EXTRAFIELD_POS); +} + + +inline Poco::UInt32 ZipLocalFileHeader::getHeaderSize() const +{ + return FULLHEADER_SIZE+getExtraFieldLength()+getFileNameLength(); +} + + +inline std::streamoff ZipLocalFileHeader::getStartPos() const +{ + return _startPos; +} + + +inline void ZipLocalFileHeader::setStartPos(std::streamoff start) +{ + _startPos = start; + _endPos = start + getHeaderSize()+getCompressedSize(); +} + + +inline std::streamoff ZipLocalFileHeader::getEndPos() const +{ + return _endPos; +} + + +inline void ZipLocalFileHeader::parseDateTime() +{ + _lastModifiedAt = ZipUtil::parseDateTime(_rawHeader, LASTMODEFILETIME_POS, LASTMODEFILEDATE_POS); +} + + +inline void ZipLocalFileHeader::setLastModifiedAt(const Poco::DateTime& dt) +{ + _lastModifiedAt = dt; + ZipUtil::setDateTime(dt, _rawHeader, LASTMODEFILETIME_POS, LASTMODEFILEDATE_POS); +} + + +inline ZipCommon::CompressionMethod ZipLocalFileHeader::getCompressionMethod() const +{ + return static_cast(ZipUtil::get16BitValue(_rawHeader, COMPR_METHOD_POS)); +} + + +inline ZipCommon::CompressionLevel ZipLocalFileHeader::getCompressionLevel() const +{ + // bit 1 and 2 indicate the level + return static_cast((ZipUtil::get16BitValue(_rawHeader, GENERAL_PURPOSE_POS)>>1) & 0x0003); +} + + +inline void ZipLocalFileHeader::setCompressionMethod(ZipCommon::CompressionMethod cm) +{ + ZipUtil::set16BitValue(static_cast(cm), _rawHeader, COMPR_METHOD_POS); +} + + +inline void ZipLocalFileHeader::setCompressionLevel(ZipCommon::CompressionLevel cl) +{ + // bit 1 and 2 indicate the level + Poco::UInt16 val = static_cast(cl); + val <<= 1; + Poco::UInt16 mask = 0xfff9; + _rawHeader[GENERAL_PURPOSE_POS] = ((_rawHeader[GENERAL_PURPOSE_POS] & mask) | val); +} + + +inline bool ZipLocalFileHeader::isEncrypted() const +{ + // bit 0 indicates encryption + return ((ZipUtil::get16BitValue(_rawHeader, GENERAL_PURPOSE_POS) & 0x0001) != 0); +} + + +inline void ZipLocalFileHeader::setEncryption(bool val) +{ + if (val) + _rawHeader[GENERAL_PURPOSE_POS] |= 0x01; + else + _rawHeader[GENERAL_PURPOSE_POS] &= 0xfe; +} + + +inline void ZipLocalFileHeader::setSearchCRCAndSizesAfterData(bool val) +{ + //set bit 3 of general purpose reg + if (val) + _rawHeader[GENERAL_PURPOSE_POS] |= 0x08; + else + _rawHeader[GENERAL_PURPOSE_POS] &= 0xf7; +} + + +inline const Poco::DateTime& ZipLocalFileHeader::lastModifiedAt() const +{ + return _lastModifiedAt; +} + + +inline Poco::UInt32 ZipLocalFileHeader::getCRC() const +{ + return _crc32; +} + + +inline Poco::UInt32 ZipLocalFileHeader::getCompressedSize() const +{ + return _compressedSize; +} + + +inline Poco::UInt32 ZipLocalFileHeader::getUncompressedSize() const +{ + return _uncompressedSize; +} + + +inline void ZipLocalFileHeader::setCRC(Poco::UInt32 val) +{ + _crc32 = val; + ZipUtil::set32BitValue(val, _rawHeader, CRC32_POS); +} + + +inline void ZipLocalFileHeader::setCompressedSize(Poco::UInt32 val) +{ + _compressedSize = val; + ZipUtil::set32BitValue(val, _rawHeader, COMPRESSEDSIZE_POS); +} + + +inline void ZipLocalFileHeader::setUncompressedSize(Poco::UInt32 val) +{ + _uncompressedSize = val; + ZipUtil::set32BitValue(val, _rawHeader, UNCOMPRESSEDSIZE_POS); +} + + +inline Poco::UInt32 ZipLocalFileHeader::getCRCFromHeader() const +{ + return ZipUtil::get32BitValue(_rawHeader, CRC32_POS); +} + + +inline Poco::UInt32 ZipLocalFileHeader::getCompressedSizeFromHeader() const +{ + return ZipUtil::get32BitValue(_rawHeader, COMPRESSEDSIZE_POS); +} + + +inline Poco::UInt32 ZipLocalFileHeader::getUncompressedSizeFromHeader() const +{ + return ZipUtil::get32BitValue(_rawHeader, UNCOMPRESSEDSIZE_POS); +} + + +inline const std::string& ZipLocalFileHeader::getFileName() const +{ + return _fileName; +} + + +inline bool ZipLocalFileHeader::isFile() const +{ + return !isDirectory(); +} + + +inline bool ZipLocalFileHeader::isDirectory() const +{ + poco_assert_dbg(!_fileName.empty()); + return getUncompressedSize() == 0 && getCompressionMethod() == ZipCommon::CM_STORE && _fileName[_fileName.length()-1] == '/'; +} + + +inline bool ZipLocalFileHeader::hasExtraField() const +{ + return getExtraFieldLength() > 0; +} + + +inline const std::string& ZipLocalFileHeader::getExtraField() const +{ + return _extraField; +} + + +inline bool ZipLocalFileHeader::hasData() const +{ + return (getCompressedSize() > 0); +} + + +inline std::streamoff ZipLocalFileHeader::getDataStartPos() const +{ + return getStartPos() + getHeaderSize(); +} + + +inline std::streamoff ZipLocalFileHeader::getDataEndPos() const +{ + return getDataStartPos()+getCompressedSize(); +} + + +} } // namespace Poco::Zip + + +#endif // Zip_ZipLocalFileHeader_INCLUDED diff --git a/Zip/include/Poco/Zip/ZipManipulator.h b/Zip/include/Poco/Zip/ZipManipulator.h new file mode 100644 index 000000000..81db23cc9 --- /dev/null +++ b/Zip/include/Poco/Zip/ZipManipulator.h @@ -0,0 +1,131 @@ +// +// ZipManipulator.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/ZipManipulator.h#2 $ +// +// Library: Zip +// Package: Manipulation +// Module: ZipManipulator +// +// Definition of the ZipManipulator class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_ZipManipulator_INCLUDED +#define Zip_ZipManipulator_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Zip/ZipArchive.h" +#include "Poco/Zip/ZipCommon.h" +#include "Poco/Zip/ZipOperation.h" +#include "Poco/FIFOEvent.h" +#include "Poco/SharedPtr.h" +#include + + +namespace Poco { +namespace Zip { + + +class ZipArchive; + + +class Zip_API ZipManipulator + /// ZipManipulator allows to add/remove/update files inside zip files +{ +public: + Poco::FIFOEvent EDone; + // Fired for each entry once commit is invoked + + ZipManipulator(const std::string& zipFile, bool backupOriginalFile); + /// Creates the ZipManipulator. + + virtual ~ZipManipulator(); + /// Destroys the ZipManipulator. + + void deleteFile(const std::string& zipPath); + /// Removes the given file from the Zip archive. + + void replaceFile(const std::string& zipPath, const std::string& localPath); + /// Replaces the contents of the file in the archive with the contents + /// from the file given by localPath. + + void renameFile(const std::string& zipPath, const std::string& newZipPath); + /// Renames the file in the archive to newZipPath + + void addFile(const std::string& zipPath, const std::string& localPath, ZipCommon::CompressionMethod cm = ZipCommon::CM_DEFLATE, ZipCommon::CompressionLevel cl = ZipCommon::CL_MAXIMUM); + /// Adds a file to the zip file. + + ZipArchive commit(); + /// Commits all changes and re-creates the Zip File with the changes applied. + /// Returns the ZipArchive for the newly created archive + /// + /// Changes will be first written to a temporary file, + /// then the originalfile will be either deleted or renamed to .bak, + /// then, the temp file will be renamed to the original zip file name. + + const ZipArchive& originalArchive() const; + /// Returns the original archive information + +private: + const ZipLocalFileHeader& getForChange(const std::string& zipPath) const; + /// Searches for the entry given by the zipPath. + /// Throws an exception if the entry does not exist + /// or if an entry already exists in the Changeslist + + void addOperation(const std::string& zipPath, ZipOperation::Ptr ptrOp); + /// Adds the operation to the changes list. Throws an exception if an + /// entry for the zipPath already exists + + void onEDone(const void* pSender, const ZipLocalFileHeader& hdr); + /// Forwards the event to the EDone event + + ZipArchive compress(const std::string& outFile); + /// Compresses the new file to outFile + +private: + typedef std::map Changes; + + const std::string _zipFile; + bool _backupOriginalFile; + Changes _changes; + Poco::SharedPtr _in; +}; + + +inline const ZipArchive& ZipManipulator::originalArchive() const +{ + return *_in; +} + + +} } // namespace Poco::Zip + + +#endif // Zip_ZipManipulator_INCLUDED diff --git a/Zip/include/Poco/Zip/ZipOperation.h b/Zip/include/Poco/Zip/ZipOperation.h new file mode 100644 index 000000000..dd6e4a387 --- /dev/null +++ b/Zip/include/Poco/Zip/ZipOperation.h @@ -0,0 +1,78 @@ +// +// ZipOperation.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/ZipOperation.h#1 $ +// +// Library: Zip +// Package: Manipulation +// Module: ZipOperation +// +// Definition of the ZipOperation class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_ZipOperation_INCLUDED +#define Zip_ZipOperation_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/RefCountedObject.h" +#include "Poco/AutoPtr.h" +#include +#include + + +namespace Poco { +namespace Zip { + + +class Compress; + + +class Zip_API ZipOperation: public Poco::RefCountedObject + /// Abstract super class for operations on individual zip entries +{ +public: + typedef Poco::AutoPtr Ptr; + + ZipOperation(); + /// Creates the ZipOperation. + + virtual void execute(Compress& c, std::istream& input) = 0; + /// Executes the operation + +protected: + virtual ~ZipOperation(); + /// Destroys the ZipOperation. +}; + + +} } // namespace Poco::Zip + + +#endif // Zip_ZipOperation_INCLUDED diff --git a/Zip/include/Poco/Zip/ZipStream.h b/Zip/include/Poco/Zip/ZipStream.h new file mode 100644 index 000000000..45fd09d64 --- /dev/null +++ b/Zip/include/Poco/Zip/ZipStream.h @@ -0,0 +1,171 @@ +// +// ZipStream.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/ZipStream.h#3 $ +// +// Library: Zip +// Package: Zip +// Module: ZipStream +// +// Definition of the ZipStream class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_ZipStream_INCLUDED +#define Zip_ZipStream_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Zip/PartialStream.h" +#include "Poco/SharedPtr.h" +#include "Poco/BufferedStreamBuf.h" +#include "Poco/Checksum.h" +#include +#include + + +namespace Poco { +namespace Zip { + + +class ZipArchive; +class ZipLocalFileHeader; + + +class Zip_API ZipStreamBuf: public Poco::BufferedStreamBuf + /// ZipStreamBuf is used to decompress single files from a Zip file. +{ +public: + ZipStreamBuf(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition); + /// Creates the ZipStreamBuf. Set reposition to false, if you do on-the-fly decompression. + + ZipStreamBuf(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool reposition); + /// Creates the ZipStreamBuf. Set reposition to false, if you do on-the-fly compression. + + virtual ~ZipStreamBuf(); + /// Destroys the ZipStreamBuf. + + void close(); + /// Informs a writing outputstream that writing is done for this stream + + bool crcValid() const; + /// Call this method once all bytes were read from the input stream to determine if the CRC is valid + +protected: + int readFromDevice(char* buffer, std::streamsize length); + + int writeToDevice(const char* buffer, std::streamsize length); + +private: + enum + { + STREAM_BUFFER_SIZE = 1024 + }; + + typedef Poco::SharedPtr PtrIStream; + typedef Poco::SharedPtr PtrOStream; + std::istream* _pIstr; + std::ostream* _pOstr; + PtrIStream _ptrBuf; + PtrOStream _ptrOBuf; + PtrIStream _ptrHelper; + Poco::SharedPtr _ptrOHelper; + Poco::Checksum _crc32; + Poco::UInt32 _expectedCrc32; + bool _checkCRC; + /// Note: we do not check crc if we decompress a streaming zip file and the crc is stored in the directory header + Poco::UInt32 _bytesWritten; + ZipLocalFileHeader* _pHeader; +}; + + +class Zip_API ZipIOS: public virtual std::ios + /// The base class for ZipInputStream and ZipOutputStream. + /// + /// This class is needed to ensure the correct initialization + /// order of the stream buffer and base classes. +{ +public: + ZipIOS(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition); + /// Creates the basic stream and connects it + /// to the given input stream. + + ZipIOS(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool reposition); + /// Creates the basic stream and connects it + /// to the given output stream. + + ~ZipIOS(); + /// Destroys the stream. + + ZipStreamBuf* rdbuf(); + /// Returns a pointer to the underlying streambuf. + +protected: + ZipStreamBuf _buf; +}; + + +class Zip_API ZipInputStream: public ZipIOS, public std::istream + /// This stream copies all characters read through it + /// to one or multiple output streams. +{ +public: + ZipInputStream(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition = true); + /// Creates the ZipInputStream and connects it + /// to the given input stream. + + ~ZipInputStream(); + /// Destroys the ZipInputStream. + + bool crcValid() const; + /// Call this method once all bytes were read from the input stream to determine if the CRC is valid +}; + + + +class Zip_API ZipOutputStream: public ZipIOS, public std::ostream + /// This stream compresses all characters written through it + /// to one output stream. +{ +public: + ZipOutputStream(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool seekableOutput); + /// Creates the ZipOutputStream and connects it + /// to the given output stream. + + ~ZipOutputStream(); + /// Destroys the ZipOutputStream. + + void close(); + /// Must be called for ZipOutputStreams! +}; + + +} } // namespace Poco::Zip + + +#endif // Zip_ZipStream_INCLUDED diff --git a/Zip/include/Poco/Zip/ZipUtil.h b/Zip/include/Poco/Zip/ZipUtil.h new file mode 100644 index 000000000..3ea331ecf --- /dev/null +++ b/Zip/include/Poco/Zip/ZipUtil.h @@ -0,0 +1,119 @@ +// +// ZipUtil.h +// +// $Id: //poco/1.3/Zip/include/Poco/Zip/ZipUtil.h#4 $ +// +// Library: Zip +// Package: Zip +// Module: ZipUtil +// +// Definition of the ZipUtil class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef Zip_ZipUtil_INCLUDED +#define Zip_ZipUtil_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Zip/ZipCommon.h" +#include "Poco/DateTime.h" +#include "Poco/Path.h" + + +namespace Poco { +namespace Zip { + + +class ZipUtil + /// A utility class used for parsing header information inside of zip files +{ +public: + static Poco::UInt16 get16BitValue(const char* pVal, const Poco::UInt32 pos); + + static Poco::UInt32 get32BitValue(const char* pVal, const Poco::UInt32 pos); + + static void set16BitValue(const Poco::UInt16 val, char* pVal, const Poco::UInt32 pos); + + static void set32BitValue(const Poco::UInt32 val, char* pVal, const Poco::UInt32 pos); + + static Poco::DateTime parseDateTime(const char* pVal, const Poco::UInt32 timePos, const Poco::UInt32 datePos); + + static void setDateTime(const Poco::DateTime& dt, char* pVal, const Poco::UInt32 timePos, const Poco::UInt32 datePos); + + static std::string fakeZLibInitString(ZipCommon::CompressionLevel cl); + + static void sync(std::istream& in); + /// Searches the next valid header in the input stream, stops right before it + + static void verifyZipEntryFileName(const std::string& zipPath); + /// Verifies that the name of the ZipEntry is a valid path + + static std::string validZipEntryFileName(const Poco::Path& entry); + +private: + ZipUtil(); + ~ZipUtil(); + ZipUtil(const ZipUtil&); + ZipUtil& operator=(const ZipUtil&); +}; + + +inline Poco::UInt16 ZipUtil::get16BitValue(const char* pVal, const Poco::UInt32 pos) +{ + return static_cast((unsigned char)pVal[pos])+ (static_cast((unsigned char)pVal[pos+1]) << 8); +} + + +inline Poco::UInt32 ZipUtil::get32BitValue(const char* pVal, const Poco::UInt32 pos) +{ + return static_cast((unsigned char)pVal[pos])+ (static_cast((unsigned char)pVal[pos+1]) << 8)+ + (static_cast((unsigned char)pVal[pos+2]) << 16) + (static_cast((unsigned char)pVal[pos+3]) << 24); +} + + +inline void ZipUtil::set16BitValue(const Poco::UInt16 val, char* pVal, const Poco::UInt32 pos) +{ + pVal[pos] = static_cast(val); + pVal[pos+1] = static_cast(val>>8); +} + + +inline void ZipUtil::set32BitValue(const Poco::UInt32 val, char* pVal, const Poco::UInt32 pos) +{ + pVal[pos] = static_cast(val); + pVal[pos+1] = static_cast(val>>8); + pVal[pos+2] = static_cast(val>>16); + pVal[pos+3] = static_cast(val>>24); +} + + +} } // namespace Poco::Zip + + +#endif // Zip_ZipUtil_INCLUDED diff --git a/Zip/samples/Makefile b/Zip/samples/Makefile new file mode 100644 index 000000000..0439fdc4a --- /dev/null +++ b/Zip/samples/Makefile @@ -0,0 +1,13 @@ +# +# Makefile +# +# $Id: //poco/1.3/Zip/samples/Makefile#1 $ +# +# Makefile for Poco Util Samples +# + +.PHONY: projects +clean all: projects +projects: + $(MAKE) -C unzip $(MAKECMDGOALS) + $(MAKE) -C zip $(MAKECMDGOALS) diff --git a/Zip/samples/samples_vs71.sln b/Zip/samples/samples_vs71.sln new file mode 100644 index 000000000..fa384755e --- /dev/null +++ b/Zip/samples/samples_vs71.sln @@ -0,0 +1,39 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unzip", "unzip\unzip_vs71.vcproj", "{0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zip", "zip\zip_vs71.vcproj", "{73408DCF-2E65-47AF-BF38-7466DAB8D5CB}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + debug_shared = debug_shared + debug_static = debug_static + release_shared = release_shared + release_static = release_static + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}.debug_shared.ActiveCfg = debug_shared|Win32 + {0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}.debug_shared.Build.0 = debug_shared|Win32 + {0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}.debug_static.ActiveCfg = debug_shared|Win32 + {0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}.debug_static.Build.0 = debug_shared|Win32 + {0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}.release_shared.ActiveCfg = release_shared|Win32 + {0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}.release_shared.Build.0 = release_shared|Win32 + {0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}.release_static.ActiveCfg = release_shared|Win32 + {0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}.release_static.Build.0 = release_shared|Win32 + {73408DCF-2E65-47AF-BF38-7466DAB8D5CB}.debug_shared.ActiveCfg = debug_shared|Win32 + {73408DCF-2E65-47AF-BF38-7466DAB8D5CB}.debug_shared.Build.0 = debug_shared|Win32 + {73408DCF-2E65-47AF-BF38-7466DAB8D5CB}.debug_static.ActiveCfg = debug_shared|Win32 + {73408DCF-2E65-47AF-BF38-7466DAB8D5CB}.debug_static.Build.0 = debug_shared|Win32 + {73408DCF-2E65-47AF-BF38-7466DAB8D5CB}.release_shared.ActiveCfg = release_shared|Win32 + {73408DCF-2E65-47AF-BF38-7466DAB8D5CB}.release_shared.Build.0 = release_shared|Win32 + {73408DCF-2E65-47AF-BF38-7466DAB8D5CB}.release_static.ActiveCfg = release_shared|Win32 + {73408DCF-2E65-47AF-BF38-7466DAB8D5CB}.release_static.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/Zip/samples/samples_vs80.sln b/Zip/samples/samples_vs80.sln new file mode 100644 index 000000000..8c11b6867 --- /dev/null +++ b/Zip/samples/samples_vs80.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zip", "zip\zip_vs80.vcproj", "{73408DCF-2E65-47AF-BF38-7466DAB8D5CB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unzip", "unzip\unzip_vs80.vcproj", "{0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + debug_shared|Win32 = debug_shared|Win32 + release_shared|Win32 = release_shared|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {73408DCF-2E65-47AF-BF38-7466DAB8D5CB}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {73408DCF-2E65-47AF-BF38-7466DAB8D5CB}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {73408DCF-2E65-47AF-BF38-7466DAB8D5CB}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {73408DCF-2E65-47AF-BF38-7466DAB8D5CB}.release_shared|Win32.Build.0 = release_shared|Win32 + {0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}.release_shared|Win32.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Zip/samples/samples_vs90.sln b/Zip/samples/samples_vs90.sln new file mode 100644 index 000000000..a8e41f7ac --- /dev/null +++ b/Zip/samples/samples_vs90.sln @@ -0,0 +1,25 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zip", "zip\zip_vs90.vcproj", "{73408DCF-2E65-47AF-BF38-7466DAB8D5CB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unzip", "unzip\unzip_vs90.vcproj", "{0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + debug_shared|Win32 = debug_shared|Win32 + release_shared|Win32 = release_shared|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {73408DCF-2E65-47AF-BF38-7466DAB8D5CB}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {73408DCF-2E65-47AF-BF38-7466DAB8D5CB}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {73408DCF-2E65-47AF-BF38-7466DAB8D5CB}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {73408DCF-2E65-47AF-BF38-7466DAB8D5CB}.release_shared|Win32.Build.0 = release_shared|Win32 + {0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {0CFFC7B0-04F4-4A60-B6E4-84D78EDA2C73}.release_shared|Win32.Build.0 = release_shared|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Zip/samples/unzip/Makefile b/Zip/samples/unzip/Makefile new file mode 100644 index 000000000..ff9e9709b --- /dev/null +++ b/Zip/samples/unzip/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.3/Zip/samples/unzip/Makefile#1 $ +# +# Makefile for Poco SampleServer +# + +include $(POCO_BASE)/build/rules/global + +objects = unzip + +target = unzip +target_version = 1 +target_libs = PocoZip PocoUtil PocoXML PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Zip/samples/unzip/src/unzip.cpp b/Zip/samples/unzip/src/unzip.cpp new file mode 100644 index 000000000..fde9e33c1 --- /dev/null +++ b/Zip/samples/unzip/src/unzip.cpp @@ -0,0 +1,182 @@ +// +// unzip.cpp +// +// $Id: //poco/1.3/Zip/samples/unzip/src/unzip.cpp#3 $ +// +// This sample demonstrates the Decompress class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Util/Application.h" +#include "Poco/Util/Option.h" +#include "Poco/Util/OptionSet.h" +#include "Poco/Util/HelpFormatter.h" +#include "Poco/Util/AbstractConfiguration.h" +#include "Poco/AutoPtr.h" +#include "Poco/Zip/Decompress.h" +#include "Poco/Zip/ZipLocalFileHeader.h" +#include "Poco/Zip/ZipArchive.h" +#include "Poco/Path.h" +#include "Poco/File.h" +#include "Poco/Delegate.h" +#include +#include + + +using Poco::Util::Application; +using Poco::Util::Option; +using Poco::Util::OptionSet; +using Poco::Util::HelpFormatter; +using Poco::Util::AbstractConfiguration; +using Poco::Util::OptionCallback; +using Poco::Zip::ZipLocalFileHeader; +using Poco::AutoPtr; + + +class DecompressHandler +{ +public: + DecompressHandler() + { + } + + ~DecompressHandler() + { + } + + void onError(const void*, std::pair& info) + { + Poco::Util::Application::instance().logger().error("ERR: " + info.second); + } + + void onOk(const void*, std::pair& info) + { + Poco::Util::Application::instance().logger().information("OK: " + info.second.toString(Poco::Path::PATH_UNIX)); + } +}; + + +class UnzipApp: public Application + /// This sample demonstrates some of the features of the Util::Application class, + /// such as configuration file handling and command line arguments processing. + /// + /// Try zip --help (on Unix platforms) or zip /help (elsewhere) for + /// more information. +{ +public: + UnzipApp(): _helpRequested(false) + { + } + +protected: + void initialize(Application& self) + { + loadConfiguration(); // load default configuration files, if present + Application::initialize(self); + // add your own initialization code here + } + + void uninitialize() + { + // add your own uninitialization code here + Application::uninitialize(); + } + + void reinitialize(Application& self) + { + Application::reinitialize(self); + // add your own reinitialization code here + } + + void defineOptions(OptionSet& options) + { + Application::defineOptions(options); + + options.addOption( + Option("help", "h", "display help information on command line arguments") + .required(false) + .repeatable(false) + .callback(OptionCallback(this, &UnzipApp::handleHelp))); + + options.addOption( + Option("file", "f", "specifies the input zip file") + .required(true) + .repeatable(false) + .argument("filename") + .callback(OptionCallback(this, &UnzipApp::handleFile))); + } + + void handleHelp(const std::string& name, const std::string& value) + { + _helpRequested = true; + displayHelp(); + stopOptionsProcessing(); + } + + void handleFile(const std::string& name, const std::string& value) + { + _zipFile = value; + } + + void displayHelp() + { + HelpFormatter helpFormatter(options()); + helpFormatter.setCommand(commandName()); + helpFormatter.setUsage("OPTIONS outdir"); + helpFormatter.setHeader("A application that demonstrates usage of Poco::Zip::Decompress class."); + helpFormatter.format(std::cout); + } + + + int main(const std::vector& args) + { + if (!_helpRequested) + { + Poco::Path outputDir; + if (!args.empty()) + outputDir.parseDirectory(args[0]); + + std::ifstream in(_zipFile.c_str(), std::ios::binary); + Poco::Zip::Decompress c(in, outputDir); + DecompressHandler handler; + c.EError += Poco::Delegate >(&handler, &DecompressHandler::onError); + c.EOk +=Poco::Delegate >(&handler, &DecompressHandler::onOk); + c.decompressAllFiles(); + c.EError -= Poco::Delegate >(&handler, &DecompressHandler::onError); + c.EOk -=Poco::Delegate >(&handler, &DecompressHandler::onOk); + } + return Application::EXIT_OK; + } + +private: + bool _helpRequested; + std::string _zipFile; +}; + + +POCO_APP_MAIN(UnzipApp) diff --git a/Zip/samples/unzip/unzip_vs71.vcproj b/Zip/samples/unzip/unzip_vs71.vcproj new file mode 100644 index 000000000..bf73522d3 --- /dev/null +++ b/Zip/samples/unzip/unzip_vs71.vcproj @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Zip/samples/unzip/unzip_vs80.vcproj b/Zip/samples/unzip/unzip_vs80.vcproj new file mode 100644 index 000000000..6094b787d --- /dev/null +++ b/Zip/samples/unzip/unzip_vs80.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Zip/samples/unzip/unzip_vs90.vcproj b/Zip/samples/unzip/unzip_vs90.vcproj new file mode 100644 index 000000000..f3f99a8cf --- /dev/null +++ b/Zip/samples/unzip/unzip_vs90.vcproj @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Zip/samples/zip/Makefile b/Zip/samples/zip/Makefile new file mode 100644 index 000000000..cb8852f8d --- /dev/null +++ b/Zip/samples/zip/Makefile @@ -0,0 +1,17 @@ +# +# Makefile +# +# $Id: //poco/1.3/Zip/samples/zip/Makefile#1 $ +# +# Makefile for Poco SampleApp +# + +include $(POCO_BASE)/build/rules/global + +objects = zip + +target = zip +target_version = 1 +target_libs = PocoZip PocoUtil PocoXML PocoFoundation + +include $(POCO_BASE)/build/rules/exec diff --git a/Zip/samples/zip/src/zip.cpp b/Zip/samples/zip/src/zip.cpp new file mode 100644 index 000000000..acead7534 --- /dev/null +++ b/Zip/samples/zip/src/zip.cpp @@ -0,0 +1,183 @@ +// +// zip.cpp +// +// $Id: //poco/1.3/Zip/samples/zip/src/zip.cpp#3 $ +// +// This sample demonstrates the Compress class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Util/Application.h" +#include "Poco/Util/Option.h" +#include "Poco/Util/OptionSet.h" +#include "Poco/Util/HelpFormatter.h" +#include "Poco/Util/AbstractConfiguration.h" +#include "Poco/AutoPtr.h" +#include "Poco/Zip/Compress.h" +#include "Poco/Path.h" +#include "Poco/File.h" +#include "Poco/Delegate.h" +#include +#include + + +using Poco::Util::Application; +using Poco::Util::Option; +using Poco::Util::OptionSet; +using Poco::Util::HelpFormatter; +using Poco::Util::AbstractConfiguration; +using Poco::Util::OptionCallback; +using Poco::AutoPtr; + + +class ZipApp: public Application + /// This sample demonstrates some of the features of the Util::Application class, + /// such as configuration file handling and command line arguments processing. + /// + /// Try zip --help (on Unix platforms) or zip /help (elsewhere) for + /// more information. +{ +public: + ZipApp(): _helpRequested(false) + { + } + +protected: + void initialize(Application& self) + { + loadConfiguration(); // load default configuration files, if present + Application::initialize(self); + // add your own initialization code here + } + + void uninitialize() + { + // add your own uninitialization code here + Application::uninitialize(); + } + + void reinitialize(Application& self) + { + Application::reinitialize(self); + // add your own reinitialization code here + } + + void defineOptions(OptionSet& options) + { + Application::defineOptions(options); + + options.addOption( + Option("help", "h", "display help information on command line arguments") + .required(false) + .repeatable(false) + .callback(OptionCallback(this, &ZipApp::handleHelp))); + + options.addOption( + Option("file", "f", "specifies the output zip file") + .required(true) + .repeatable(false) + .argument("filename") + .callback(OptionCallback(this, &ZipApp::handleFile))); + } + + void handleHelp(const std::string& name, const std::string& value) + { + _helpRequested = true; + displayHelp(); + stopOptionsProcessing(); + } + + void handleFile(const std::string& name, const std::string& value) + { + _outFile = value; + } + + void displayHelp() + { + HelpFormatter helpFormatter(options()); + helpFormatter.setCommand(commandName()); + helpFormatter.setUsage("OPTIONS "); + helpFormatter.setHeader("A application that demonstrates usage of Poco::Zip::Compress class."); + helpFormatter.format(std::cout); + } + + void onDone(const void*, const Poco::Zip::ZipLocalFileHeader& hdr) + { + logger().information("DONE: " + hdr.getFileName()); + } + + int main(const std::vector& args) + { + if (!_helpRequested) + { + if (args.empty()) + { + logger().warning("No input files specified for compression"); + } + else + { + std::ofstream out(_outFile.c_str(), std::ios::binary); + Poco::Zip::Compress c(out, true); + c.EDone += Poco::Delegate(this, &ZipApp::onDone); + for (std::vector::const_iterator it = args.begin(); it != args.end(); ++it) + { + // no WILDCARD support! + Poco::File aFile(*it); + if (!aFile.exists()) + { + logger().error("File not found: " + *it); + } + else + { + Poco::Path anEntry(*it); + if (aFile.isDirectory()) + { + anEntry.makeDirectory(); + c.addRecursive(anEntry, Poco::Zip::ZipCommon::CL_MAXIMUM, (args.size() != 1)); // add root if we have more than one entry + } + else + { + anEntry.makeFile(); + c.addFile(anEntry, anEntry); + } + } + } + c.close(); + c.EDone -= Poco::Delegate(this, &ZipApp::onDone); + } + } + return Application::EXIT_OK; + } + +private: + bool _helpRequested; + std::string _outFile; +}; + + +POCO_APP_MAIN(ZipApp) diff --git a/Zip/samples/zip/zip_vs71.vcproj b/Zip/samples/zip/zip_vs71.vcproj new file mode 100644 index 000000000..557a0767d --- /dev/null +++ b/Zip/samples/zip/zip_vs71.vcproj @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Zip/samples/zip/zip_vs80.vcproj b/Zip/samples/zip/zip_vs80.vcproj new file mode 100644 index 000000000..9ebc99eac --- /dev/null +++ b/Zip/samples/zip/zip_vs80.vcproj @@ -0,0 +1,209 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Zip/samples/zip/zip_vs90.vcproj b/Zip/samples/zip/zip_vs90.vcproj new file mode 100644 index 000000000..a91ced5a3 --- /dev/null +++ b/Zip/samples/zip/zip_vs90.vcproj @@ -0,0 +1,209 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Zip/src/Add.cpp b/Zip/src/Add.cpp new file mode 100644 index 000000000..228fe1e52 --- /dev/null +++ b/Zip/src/Add.cpp @@ -0,0 +1,60 @@ +// +// Add.cpp +// +// $Id: //poco/1.3/Zip/src/Add.cpp#1 $ +// +// Library: Zip +// Package: Manipulation +// Module: Add +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/Add.h" +#include "Poco/Zip/Compress.h" + + +namespace Poco { +namespace Zip { + + +Add::Add(const std::string& zipPath, const std::string& localPath, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl): + _zipPath(zipPath), + _localPath(localPath), + _cm(cm), + _cl(cl) +{ +} + + +void Add::execute(Compress& c, std::istream& input) +{ + c.addFile(Poco::Path(_localPath), Poco::Path(_zipPath), _cm, _cl); +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/AutoDetectStream.cpp b/Zip/src/AutoDetectStream.cpp new file mode 100644 index 000000000..f4159fa8f --- /dev/null +++ b/Zip/src/AutoDetectStream.cpp @@ -0,0 +1,252 @@ +// +// AutoDetectStream.cpp +// +// $Id: //poco/1.3/Zip/src/AutoDetectStream.cpp#4 $ +// +// Library: Zip +// Package: Zip +// Module: AutoDetectStream +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/AutoDetectStream.h" +#include "Poco/Zip/ZipLocalFileHeader.h" +#include "Poco/Zip/ZipArchiveInfo.h" +#include "Poco/Zip/ZipDataInfo.h" +#include "Poco/Zip/ZipFileInfo.h" +#include "Poco/Exception.h" +#include + + +namespace Poco { +namespace Zip { + + +AutoDetectStreamBuf::AutoDetectStreamBuf(std::istream& in, const std::string& pre, const std::string& post, bool reposition, Poco::UInt32 start): + Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in), + _pIstr(&in), + _pOstr(0), + _eofDetected(false), + _matchCnt(0), + _prefix(pre), + _postfix(post), + _reposition(reposition), + _start(start) +{ +} + + +AutoDetectStreamBuf::AutoDetectStreamBuf(std::ostream& out): + Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::out), + _pIstr(0), + _pOstr(&out), + _eofDetected(false), + _matchCnt(0), + _prefix(), + _postfix(), + _reposition(false), + _start(0u) +{ +} + + +AutoDetectStreamBuf::~AutoDetectStreamBuf() +{ +} + + +int AutoDetectStreamBuf::readFromDevice(char* buffer, std::streamsize length) +{ + poco_assert_dbg(length >= 8); + if (_pIstr == 0 ||length == 0) return -1; + + if (_reposition) + { + _pIstr->seekg(_start, std::ios_base::beg); + _reposition = false; + } + + if (!_prefix.empty()) + { + std::streamsize tmp = (_prefix.size() > length)? length: static_cast(_prefix.size()); + std::memcpy(buffer, _prefix.c_str(), tmp); + _prefix = _prefix.substr(tmp); + return tmp; + } + + if (_eofDetected) + { + if (!_postfix.empty()) + { + std::streamsize tmp = (_postfix.size() > length)? length: static_cast(_postfix.size()); + std::memcpy(buffer, _postfix.c_str(), tmp); + _postfix = _postfix.substr(tmp); + return tmp; + } + else + return -1; + } + + if (!_pIstr->good()) + return -1; + + char byte3('\x00'); + std::streamsize tempPos = 0; + static std::istream::int_type eof = std::istream::traits_type::eof(); + while (_pIstr->good() && !_pIstr->eof() && (tempPos+4) < length) + { + std::istream::int_type c = _pIstr->get(); + if (c != eof) + { + // all zip headers start with the same 2byte prefix + if (_matchCnt<2) + { + if (c == ZipLocalFileHeader::HEADER[_matchCnt]) + ++_matchCnt; + else + { + // matchcnt was either 0 or 1 the headers have all unique chars -> safe to set to 0 + if (_matchCnt == 1) + { + buffer[tempPos++] = ZipLocalFileHeader::HEADER[0]; + } + _matchCnt = 0; + + buffer[tempPos++] = static_cast(c); + } + } + else + { + //the upper 2 bytes differ: the lower one must be in range 1,3,5,7, the upper must be one larger: 2,4,6,8 + if (_matchCnt == 2) + { + if (ZipLocalFileHeader::HEADER[2] == c || + ZipArchiveInfo::HEADER[2] == c || + ZipFileInfo::HEADER[2] == c || + ZipDataInfo::HEADER[2] == c) + { + byte3 = static_cast(c);; + _matchCnt++; + } + else + { + buffer[tempPos++] = ZipLocalFileHeader::HEADER[0]; + buffer[tempPos++] = ZipLocalFileHeader::HEADER[1]; + buffer[tempPos++] = static_cast(c); + _matchCnt = 0; + } + } + else if (_matchCnt == 3) + { + if (c-1 == byte3) + { + // a match, pushback + _pIstr->putback(c); + _pIstr->putback(byte3); + _pIstr->putback(ZipLocalFileHeader::HEADER[1]); + _pIstr->putback(ZipLocalFileHeader::HEADER[0]); + _eofDetected = true; + return tempPos; + } + else + { + buffer[tempPos++] = ZipLocalFileHeader::HEADER[0]; + buffer[tempPos++] = ZipLocalFileHeader::HEADER[1]; + buffer[tempPos++] = byte3; + buffer[tempPos++] = c; + _matchCnt = 0; //the headers have all unique chars -> safe to set to 0 + } + } + } + } + } + + return tempPos; + +} + + +int AutoDetectStreamBuf::writeToDevice(const char* buffer, std::streamsize length) +{ + if (_pOstr == 0 || length == 0) return -1; + _pOstr->write(buffer, length); + if (_pOstr->good()) + return length; + throw Poco::IOException("Failed to write to output stream"); +} + + +AutoDetectIOS::AutoDetectIOS(std::istream& istr, const std::string& pre, const std::string& post, bool reposition, Poco::UInt32 start): + _buf(istr, pre, post, reposition, start) +{ + poco_ios_init(&_buf); +} + + +AutoDetectIOS::AutoDetectIOS(std::ostream& ostr): _buf(ostr) +{ + poco_ios_init(&_buf); +} + + +AutoDetectIOS::~AutoDetectIOS() +{ +} + + +AutoDetectStreamBuf* AutoDetectIOS::rdbuf() +{ + return &_buf; +} + + +AutoDetectInputStream::AutoDetectInputStream(std::istream& istr, const std::string& pre, const std::string& post, bool reposition, Poco::UInt32 start): + AutoDetectIOS(istr, pre, post, reposition, start), + std::istream(&_buf) +{ +} + + +AutoDetectInputStream::~AutoDetectInputStream() +{ +} + + +AutoDetectOutputStream::AutoDetectOutputStream(std::ostream& ostr): + AutoDetectIOS(ostr), + std::ostream(&_buf) +{ +} + + +AutoDetectOutputStream::~AutoDetectOutputStream() +{ +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/Compress.cpp b/Zip/src/Compress.cpp new file mode 100644 index 000000000..aaddd8ff9 --- /dev/null +++ b/Zip/src/Compress.cpp @@ -0,0 +1,322 @@ +// +// Compress.cpp +// +// $Id: //poco/1.3/Zip/src/Compress.cpp#4 $ +// +// Library: Zip +// Package: Zip +// Module: Compress +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/Compress.h" +#include "Poco/Zip/ZipLocalFileHeader.h" +#include "Poco/Zip/ZipStream.h" +#include "Poco/Zip/ZipArchiveInfo.h" +#include "Poco/Zip/ZipDataInfo.h" +#include "Poco/Zip/ZipException.h" +#include "Poco/StreamCopier.h" +#include "Poco/File.h" +#include + + +namespace Poco { +namespace Zip { + + +Compress::Compress(std::ostream& out, bool seekableOut): + _out(out), + _seekableOut(seekableOut), + _files(), + _infos(), + _dirs(), + _offset(0) +{ +} + + +Compress::~Compress() +{ +} + + +void Compress::addEntry(std::istream& in, const Poco::DateTime& lastModifiedAt, const Poco::Path& fileName, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl) +{ + std::string fn = ZipUtil::validZipEntryFileName(fileName); + + if (_files.size() >= 65535) + throw ZipException("Maximum number of entries for a ZIP file reached: 65535"); + if (!in.good()) + throw ZipException("Invalid input stream"); + + std::streamoff localHeaderOffset = _offset; + ZipLocalFileHeader hdr(fileName, lastModifiedAt, cm, cl); + hdr.setStartPos(localHeaderOffset); + + ZipOutputStream zipOut(_out, hdr, _seekableOut); + Poco::StreamCopier::copyStream(in, zipOut); + zipOut.close(); + hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known + _offset = hdr.getEndPos(); + if (hdr.searchCRCAndSizesAfterData()) + _offset += ZipDataInfo::getFullHeaderSize(); + _files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr)); + poco_assert (_out); + ZipFileInfo nfo(hdr); + nfo.setOffset(localHeaderOffset); + _infos.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), nfo)); + EDone.notify(this, hdr); +} + + +void Compress::addFileRaw(std::istream& in, const ZipLocalFileHeader& h, const Poco::Path& fileName) +{ + std::string fn = ZipUtil::validZipEntryFileName(fileName); + //bypass the header of the input stream and point to the first byte of the data payload + in.seekg(h.getDataStartPos(), std::ios_base::beg); + + if (_files.size() >= 65535) + throw ZipException("Maximum number of entries for a ZIP file reached: 65535"); + if (!in.good()) + throw ZipException("Invalid input stream"); + + std::streamoff localHeaderOffset = _offset; + ZipLocalFileHeader hdr(h); + hdr.setFileName(fn, h.isDirectory()); + hdr.setStartPos(localHeaderOffset); + //bypass zipoutputstream + //write the header directly + std::string header = hdr.createHeader(); + _out.write(header.c_str(), static_cast(header.size())); + // now fwd the payload to _out in chunks of size CHUNKSIZE + Poco::UInt32 totalSize = hdr.getCompressedSize(); + if (totalSize > 0) + { + Poco::Buffer buffer(COMPRESS_CHUNK_SIZE); + Poco::UInt32 remaining = totalSize; + while(remaining > 0) + { + if (remaining > COMPRESS_CHUNK_SIZE) + { + in.read(buffer.begin(), COMPRESS_CHUNK_SIZE); + std::streamsize n = in.gcount(); + poco_assert_dbg (n == COMPRESS_CHUNK_SIZE); + _out.write(buffer.begin(), n); + remaining -= COMPRESS_CHUNK_SIZE; + } + else + { + in.read(buffer.begin(), remaining); + std::streamsize n = in.gcount(); + poco_assert_dbg (n == remaining); + _out.write(buffer.begin(), n); + remaining = 0; + } + } + } + //write optional block afterwards + if (hdr.searchCRCAndSizesAfterData()) + { + ZipDataInfo info(in, false); + _out.write(info.getRawHeader(), static_cast(info.getFullHeaderSize())); + } + hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known + _offset = hdr.getEndPos(); + if (hdr.searchCRCAndSizesAfterData()) + _offset += ZipDataInfo::getFullHeaderSize(); + _files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr)); + poco_assert (_out); + ZipFileInfo nfo(hdr); + nfo.setOffset(localHeaderOffset); + _infos.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), nfo)); + EDone.notify(this, hdr); +} + + +void Compress::addFile(std::istream& in, const Poco::DateTime& lastModifiedAt, const Poco::Path& fileName, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl) +{ + if (!fileName.isFile()) + throw ZipException("Not a file: "+ fileName.toString()); + + if (fileName.depth() > 1) + { + addDirectory(fileName.parent(), lastModifiedAt); + } + addEntry(in, lastModifiedAt, fileName, cm, cl); +} + + +void Compress::addFile(const Poco::Path& file, const Poco::Path& fileName, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl) +{ + Poco::File aFile(file); + Poco::File::FileSize size = aFile.getSize(); + if (size < 16) + { + cm = ZipCommon::CM_STORE; + cl = ZipCommon::CL_NORMAL; + } + + std::ifstream in(file.toString().c_str(), std::ios::binary); + if (!in.good()) + throw ZipException("Invalid input stream for " + aFile.path()); + if (fileName.depth() > 1) + { + Poco::File aParent(file.parent()); + addDirectory(fileName.parent(), aParent.getLastModified()); + } + addFile(in, aFile.getLastModified(), fileName, cm, cl); +} + + +void Compress::addDirectory(const Poco::Path& entryName, const Poco::DateTime& lastModifiedAt) +{ + if (!entryName.isDirectory()) + throw ZipException("Not a directory: "+ entryName.toString()); + + std::string fileStr = entryName.toString(Poco::Path::PATH_UNIX); + if (_files.find(fileStr) != _files.end()) + return; // ignore duplicate add + if (_files.size() >= 65535) + throw ZipException("Maximum number of entries for a ZIP file reached: 65535"); + if (fileStr == "/") + throw ZipException("Illegal entry name /"); + if (fileStr.empty()) + throw ZipException("Illegal empty entry name"); + if (fileStr.find(ZipCommon::ILLEGAL_PATH) != std::string::npos) + throw ZipException("Illegal entry name " + fileStr + " containing " + ZipCommon::ILLEGAL_PATH); + + if (entryName.depth() > 1) + { + addDirectory(entryName.parent(), lastModifiedAt); + } + + std::streamoff localHeaderOffset = _offset; + ZipCommon::CompressionMethod cm = ZipCommon::CM_STORE; + ZipCommon::CompressionLevel cl = ZipCommon::CL_NORMAL; + ZipLocalFileHeader hdr(entryName, lastModifiedAt, cm, cl); + hdr.setStartPos(localHeaderOffset); + ZipOutputStream zipOut(_out, hdr, _seekableOut); + zipOut.close(); + hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known + _offset = hdr.getEndPos(); + if (hdr.searchCRCAndSizesAfterData()) + _offset += ZipDataInfo::getFullHeaderSize(); + _files.insert(std::make_pair(entryName.toString(Poco::Path::PATH_UNIX), hdr)); + poco_assert (_out); + ZipFileInfo nfo(hdr); + nfo.setOffset(localHeaderOffset); + _infos.insert(std::make_pair(entryName.toString(Poco::Path::PATH_UNIX), nfo)); + EDone.notify(this, hdr); +} + + +void Compress::addRecursive(const Poco::Path& entry, ZipCommon::CompressionLevel cl, bool excludeRoot, const Poco::Path& name) +{ + Poco::File aFile(entry); + if (!aFile.isDirectory()) + throw ZipException("Not a directory: "+ entry.toString()); + Poco::Path aName(name); + aName.makeDirectory(); + if (!excludeRoot) + { + if (aName.depth() == 0) + { + Poco::Path tmp(entry); + tmp.makeAbsolute(); // eliminate ../ + aName = Poco::Path(tmp[tmp.depth()-1]); + aName.makeDirectory(); + } + + addDirectory(aName, aFile.getLastModified()); + } + + // iterate over children + std::vector children; + aFile.list(children); + std::vector::const_iterator it = children.begin(); + std::vector::const_iterator itEnd = children.end(); + for (; it != itEnd; ++it) + { + Poco::Path realFile(entry, *it); + Poco::Path renamedFile(aName, *it); + Poco::File aFile(realFile); + if (aFile.isDirectory()) + { + realFile.makeDirectory(); + renamedFile.makeDirectory(); + addRecursive(realFile, cl, false, renamedFile); + } + else + { + realFile.makeFile(); + renamedFile.makeFile(); + addFile(realFile, renamedFile, ZipCommon::CM_DEFLATE, cl); + } + } +} + + +ZipArchive Compress::close() +{ + if (!_dirs.empty()) + return ZipArchive(_files, _infos, _dirs); + + poco_assert (_infos.size() == _files.size()); + poco_assert (_files.size() < 65536); + Poco::UInt32 centralDirStart = _offset; + Poco::UInt32 centralDirSize = 0; + // write all infos + ZipArchive::FileInfos::const_iterator it = _infos.begin(); + ZipArchive::FileInfos::const_iterator itEnd = _infos.end(); + for (; it != itEnd; ++it) + { + const ZipFileInfo& nfo = it->second; + std::string info(nfo.createHeader()); + _out.write(info.c_str(), static_cast(info.size())); + Poco::UInt32 entrySize = static_cast(info.size()); + centralDirSize += entrySize; + _offset += entrySize; + } + poco_assert (_out); + + + Poco::UInt16 numEntries = static_cast(_infos.size()); + ZipArchiveInfo central; + central.setCentralDirectorySize(centralDirSize); + central.setNumberOfEntries(numEntries); + central.setTotalNumberOfEntries(numEntries); + central.setHeaderOffset(centralDirStart); + std::string centr(central.createHeader()); + _out.write(centr.c_str(), static_cast(centr.size())); + _out.flush(); + _dirs.insert(std::make_pair(0, central)); + return ZipArchive(_files, _infos, _dirs); +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/Decompress.cpp b/Zip/src/Decompress.cpp new file mode 100644 index 000000000..b46766483 --- /dev/null +++ b/Zip/src/Decompress.cpp @@ -0,0 +1,192 @@ +// +// Decompress.cpp +// +// $Id: //poco/1.3/Zip/src/Decompress.cpp#4 $ +// +// Library: Zip +// Package: Zip +// Module: Decompress +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/Decompress.h" +#include "Poco/Zip/ZipLocalFileHeader.h" +#include "Poco/Zip/ZipArchive.h" +#include "Poco/Zip/ZipStream.h" +#include "Poco/Zip/ZipException.h" +#include "Poco/File.h" +#include "Poco/Exception.h" +#include "Poco/StreamCopier.h" +#include "Poco/Delegate.h" +#include + + +namespace Poco { +namespace Zip { + + +Decompress::Decompress(std::istream& in, const Poco::Path& outputDir, bool flattenDirs, bool keepIncompleteFiles): + _in(in), + _outDir(outputDir), + _flattenDirs(flattenDirs), + _keepIncompleteFiles(keepIncompleteFiles), + _mapping() +{ + _outDir.makeAbsolute(); + poco_assert (_in.good()); + Poco::File tmp(_outDir); + if (!tmp.exists()) + { + tmp.createDirectories(); + } + if (!tmp.isDirectory()) + throw Poco::IOException("Failed to create/open directory: " + _outDir.toString()); + EOk += Poco::Delegate >(this, &Decompress::onOk); + +} + + +Decompress::~Decompress() +{ + EOk -= Poco::Delegate >(this, &Decompress::onOk); +} + + +ZipArchive Decompress::decompressAllFiles() +{ + poco_assert (_mapping.empty()); + ZipArchive arch(_in, *this); + return arch; +} + + +bool Decompress::handleZipEntry(std::istream& zipStream, const ZipLocalFileHeader& hdr) +{ + if (hdr.isDirectory()) + { + // directory have 0 size, nth to read + if (!_flattenDirs) + { + std::string dirName = hdr.getFileName(); + if (dirName.find(ZipCommon::ILLEGAL_PATH) != std::string::npos) + throw ZipException("Illegal entry name " + dirName + " containing " + ZipCommon::ILLEGAL_PATH); + Poco::Path dir(dirName); + dir.makeDirectory(); + Poco::File aFile(dir); + aFile.createDirectories(); + } + return true; + } + try + { + std::string fileName = hdr.getFileName(); + if (_flattenDirs) + { + // remove path info + Poco::Path p(fileName); + p.makeFile(); + fileName = p.getFileName(); + } + + if (fileName.find(ZipCommon::ILLEGAL_PATH) != std::string::npos) + throw ZipException("Illegal entry name " + fileName + " containing " + ZipCommon::ILLEGAL_PATH); + + Poco::Path file(fileName); + file.makeFile(); + Poco::Path dest(_outDir, file); + dest.makeFile(); + if (dest.depth() > 0) + { + Poco::File aFile(dest.parent()); + aFile.createDirectories(); + } + std::ofstream out(dest.toString().c_str(), std::ios::binary); + if (!out) + { + std::pair tmp = std::make_pair(hdr, "Failed to open output stream " + dest.toString()); + EError.notify(this, tmp); + return false; + } + ZipInputStream inp(zipStream, hdr, false); + Poco::StreamCopier::copyStream(inp, out); + out.close(); + Poco::File aFile(file); + if (!aFile.exists() || !aFile.isFile()) + { + std::pair tmp = std::make_pair(hdr, "Failed to create output stream " + dest.toString()); + EError.notify(this, tmp); + return false; + } + + if (!inp.crcValid()) + { + if (!_keepIncompleteFiles) + aFile.remove(); + std::pair tmp = std::make_pair(hdr, "CRC mismatch. Corrupt file: " + dest.toString()); + EError.notify(this, tmp); + return false; + } + + // cannot check against hdr.getUnCompressedSize if CRC and size are not set in hdr but in a ZipDataInfo + // crc is typically enough to detect errors + if (aFile.getSize() != hdr.getUncompressedSize() && !hdr.searchCRCAndSizesAfterData()) + { + if (!_keepIncompleteFiles) + aFile.remove(); + std::pair tmp = std::make_pair(hdr, "Filesizes do not match. Corrupt file: " + dest.toString()); + EError.notify(this, tmp); + return false; + } + + std::pair tmp = std::make_pair(hdr, file); + EOk.notify(this, tmp); + } + catch (Poco::Exception& e) + { + std::pair tmp = std::make_pair(hdr, "Exception: " + e.displayText()); + EError.notify(this, tmp); + return false; + } + catch (...) + { + std::pair tmp = std::make_pair(hdr, "Unknown Exception"); + EError.notify(this, tmp); + return false; + } + + return true; +} + + +void Decompress::onOk(const void*, std::pair& val) +{ + _mapping.insert(std::make_pair(val.first.getFileName(), val.second)); +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/Delete.cpp b/Zip/src/Delete.cpp new file mode 100644 index 000000000..9af00660c --- /dev/null +++ b/Zip/src/Delete.cpp @@ -0,0 +1,63 @@ +// +// Delete.cpp +// +// $Id: //poco/1.3/Zip/src/Delete.cpp#1 $ +// +// Library: Zip +// Package: Manipulation +// Module: Delete +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/Delete.h" + + +namespace Poco { +namespace Zip { + + +Delete::Delete(const ZipLocalFileHeader& hdr): + _hdr(hdr) +{ +} + + +void Delete::execute(Compress& c, std::istream& input) +{ + // due to absolute positioning in compress we don't need to do this + /* + input.seekg(_hdr.getEndPos(), std::ios_base::beg); + if (_hdr.searchCRCAndSizesAfterData()) + { + ZipDataInfo info(in, false); + } + */ +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/Keep.cpp b/Zip/src/Keep.cpp new file mode 100644 index 000000000..6ed697735 --- /dev/null +++ b/Zip/src/Keep.cpp @@ -0,0 +1,59 @@ +// +// Keep.cpp +// +// $Id: //poco/1.3/Zip/src/Keep.cpp#1 $ +// +// Library: Zip +// Package: Manipulation +// Module: Keep +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/Keep.h" +#include "Poco/Zip/Compress.h" +#include "Poco/Buffer.h" +#include "Poco/StreamCopier.h" + + +namespace Poco { +namespace Zip { + + +Keep::Keep(const ZipLocalFileHeader& hdr): + _hdr(hdr) +{ +} + + +void Keep::execute(Compress& c, std::istream& input) +{ + c.addFileRaw(input, _hdr, _hdr.getFileName()); +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/ParseCallback.cpp b/Zip/src/ParseCallback.cpp new file mode 100644 index 000000000..925f4d74e --- /dev/null +++ b/Zip/src/ParseCallback.cpp @@ -0,0 +1,54 @@ +// +// ParseCallback.cpp +// +// $Id: //poco/1.3/Zip/src/ParseCallback.cpp#3 $ +// +// Library: Zip +// Package: Zip +// Module: ParseCallback +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/ParseCallback.h" + + +namespace Poco { +namespace Zip { + + +ParseCallback::ParseCallback() +{ +} + + +ParseCallback::~ParseCallback() +{ +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/PartialStream.cpp b/Zip/src/PartialStream.cpp new file mode 100644 index 000000000..2c66750cb --- /dev/null +++ b/Zip/src/PartialStream.cpp @@ -0,0 +1,269 @@ +// +// PartialStream.cpp +// +// $Id: //poco/1.3/Zip/src/PartialStream.cpp#3 $ +// +// Library: Zip +// Package: Zip +// Module: PartialStream +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/PartialStream.h" +#include "Poco/Exception.h" +#include + + +namespace Poco { +namespace Zip { + + +PartialStreamBuf::PartialStreamBuf(std::istream& in, std::ios::pos_type start, std::ios::pos_type end, const std::string& pre, const std::string& post, bool initStream): + Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in), + _initialized(!initStream), + _start(start), + _numBytes(end-start), + _bytesWritten(0), + _pIstr(&in), + _pOstr(0), + _prefix(pre), + _postfix(post), + _ignoreStart(0), + _buffer(0), + _bufferOffset(0) +{ +} + + +PartialStreamBuf::PartialStreamBuf(std::ostream& out, std::size_t start, std::size_t end, bool initStream): + Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::out), + _initialized(!initStream), + _start(0), + _numBytes(0), + _bytesWritten(0), + _pIstr(0), + _pOstr(&out), + _ignoreStart(start), + _buffer(end), + _bufferOffset(0) +{ +} + + +PartialStreamBuf::~PartialStreamBuf() +{ +} + + +int PartialStreamBuf::readFromDevice(char* buffer, std::streamsize length) +{ + if (_pIstr == 0 ||length == 0) return -1; + if (!_initialized) + { + _initialized = true; + _pIstr->clear(); + _pIstr->seekg(_start, std::ios_base::beg); + if (_pIstr->fail()) + throw Poco::IOException("Failed to reposition in stream"); + } + if (!_prefix.empty()) + { + std::streamsize tmp = (_prefix.size() > length)? length: static_cast(_prefix.size()); + std::memcpy(buffer, _prefix.c_str(), tmp); + _prefix = _prefix.substr(tmp); + return tmp; + } + + if (_numBytes == 0) + { + if (!_postfix.empty()) + { + std::streamsize tmp = (_postfix.size() > length)? length: static_cast(_postfix.size()); + std::memcpy(buffer, _postfix.c_str(), tmp); + _postfix = _postfix.substr(tmp); + return tmp; + } + else + return -1; + } + + if (!_pIstr->good()) + return -1; + + if (_numBytes < length) + length = static_cast(_numBytes); + + _pIstr->read(buffer, length); + std::streamsize bytesRead = _pIstr->gcount(); + _numBytes -= bytesRead; + return bytesRead; + +} + + +int PartialStreamBuf::writeToDevice(const char* buffer, std::streamsize length) +{ + if (_pOstr == 0 || length == 0) return -1; + if (!_initialized) + { + _initialized = true; + _pOstr->clear(); + if (_pOstr->fail()) + throw Poco::IOException("Failed to clear stream status"); + } + + if (_ignoreStart > 0) + { + if (_ignoreStart > length) + { + _ignoreStart -= length; + // fake return values + return length; + } + else + { + std::streamsize cnt = static_cast(length - _ignoreStart - _buffer.size()); + if (cnt > 0) + { + _pOstr->write(buffer+_ignoreStart, cnt); + _bytesWritten += cnt; + } + + // copy the rest into buffer + cnt += static_cast(_ignoreStart); + _ignoreStart = 0; + poco_assert (cnt < length); + _bufferOffset = length - cnt; + std::memcpy(_buffer.begin(), buffer + cnt, _bufferOffset); + + return length; + } + } + if (_buffer.size() > 0) + { + // always treat each write as the potential last one + // thus first fill the buffer with the last n bytes of the msg + + // how much of the already cached data do we need to write? + Poco::Int32 cache = _bufferOffset + length - _buffer.size(); + if (cache > 0) + { + if (cache > _bufferOffset) + cache = _bufferOffset; + _pOstr->write(_buffer.begin(), cache); + _bytesWritten += cache; + _bufferOffset -= cache; + if (_bufferOffset > 0) + std::memmove(_buffer.begin(), _buffer.begin()+cache, _bufferOffset); + } + + // now fill up _buffer with the last bytes from buffer + Poco::Int32 pos = static_cast(length - static_cast(_buffer.size()) + _bufferOffset); + if (pos <= 0) + { + // all of the message goes to _buffer + std::memcpy(_buffer.begin() + _bufferOffset, buffer, length); + } + else + { + poco_assert (_bufferOffset == 0); + std::memcpy(_buffer.begin(), buffer+pos, _buffer.size()); + _bufferOffset = static_cast(_buffer.size()); + // the rest is written + _pOstr->write(buffer, static_cast(length - _buffer.size())); + _bytesWritten += (length - _buffer.size()); + } + } + else + { + _pOstr->write(buffer, length); + _bytesWritten += length; + } + + if (_pOstr->good()) + return length; + + throw Poco::IOException("Failed to write to output stream"); +} + + +void PartialStreamBuf::close() +{ + // DONT write data from _buffer! +} + + +PartialIOS::PartialIOS(std::istream& istr, std::ios::pos_type start, std::ios::pos_type end, const std::string& pre, const std::string& post, bool initStream): _buf(istr, start, end, pre, post, initStream) +{ + poco_ios_init(&_buf); +} + + +PartialIOS::PartialIOS(std::ostream& ostr, std::size_t start, std::size_t end, bool initStream): _buf(ostr, start, end, initStream) +{ + poco_ios_init(&_buf); +} + + +PartialIOS::~PartialIOS() +{ +} + + +PartialStreamBuf* PartialIOS::rdbuf() +{ + return &_buf; +} + + +PartialInputStream::PartialInputStream(std::istream& istr, std::ios::pos_type start, std::ios::pos_type end, bool initStream, const std::string& pre, const std::string& post): + PartialIOS(istr, start, end, pre, post, initStream), + std::istream(&_buf) +{ +} + + +PartialInputStream::~PartialInputStream() +{ +} + + +PartialOutputStream::PartialOutputStream(std::ostream& ostr, std::size_t start, std::size_t end, bool initStream): + PartialIOS(ostr, start, end, initStream), + std::ostream(&_buf) +{ +} + + +PartialOutputStream::~PartialOutputStream() +{ + close(); +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/Rename.cpp b/Zip/src/Rename.cpp new file mode 100644 index 000000000..a8d589739 --- /dev/null +++ b/Zip/src/Rename.cpp @@ -0,0 +1,58 @@ +// +// Rename.cpp +// +// $Id: //poco/1.3/Zip/src/Rename.cpp#1 $ +// +// Library: Zip +// Package: Manipulation +// Module: Rename +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/Rename.h" +#include "Poco/Zip/Compress.h" + + +namespace Poco { +namespace Zip { + + +Rename::Rename(const ZipLocalFileHeader& hdr, const std::string& newZipEntryName): + _hdr(hdr), + _newZipEntryName(newZipEntryName) +{ +} + + +void Rename::execute(Compress& c, std::istream& input) +{ + c.addFileRaw(input, _hdr, _newZipEntryName); +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/Replace.cpp b/Zip/src/Replace.cpp new file mode 100644 index 000000000..970f673e7 --- /dev/null +++ b/Zip/src/Replace.cpp @@ -0,0 +1,60 @@ +// +// Replace.cpp +// +// $Id: //poco/1.3/Zip/src/Replace.cpp#1 $ +// +// Library: Zip +// Package: Manipulation +// Module: Replace +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/Replace.h" +#include "Poco/Zip/Compress.h" + + +namespace Poco { +namespace Zip { + + +Replace::Replace(const ZipLocalFileHeader& hdr, const std::string& localPath): + _del(hdr), + _add(hdr.getFileName(), localPath, hdr.getCompressionMethod(), hdr.getCompressionLevel()) +{ +} + + + +void Replace::execute(Compress& c, std::istream& input) +{ + _del.execute(c, input); + _add.execute(c, input); +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/SkipCallback.cpp b/Zip/src/SkipCallback.cpp new file mode 100644 index 000000000..d4f6d36dc --- /dev/null +++ b/Zip/src/SkipCallback.cpp @@ -0,0 +1,66 @@ +// +// SkipCallback.cpp +// +// $Id: //poco/1.3/Zip/src/SkipCallback.cpp#4 $ +// +// Library: Zip +// Package: Zip +// Module: SkipCallback +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/SkipCallback.h" +#include "Poco/Zip/ZipLocalFileHeader.h" +#include "Poco/Zip/ZipUtil.h" + + +namespace Poco { +namespace Zip { + + +SkipCallback::SkipCallback() +{ +} + + +SkipCallback::~SkipCallback() +{ +} + + +bool SkipCallback::handleZipEntry(std::istream& zipStream, const ZipLocalFileHeader& hdr) +{ + if (!hdr.searchCRCAndSizesAfterData()) + zipStream.seekg(hdr.getCompressedSize(), std::ios_base::cur); + else + ZipUtil::sync(zipStream); + return true; +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/ZipArchive.cpp b/Zip/src/ZipArchive.cpp new file mode 100644 index 000000000..e76a368ef --- /dev/null +++ b/Zip/src/ZipArchive.cpp @@ -0,0 +1,122 @@ +// +// ZipArchive.cpp +// +// $Id: //poco/1.3/Zip/src/ZipArchive.cpp#3 $ +// +// Library: Zip +// Package: Zip +// Module: ZipArchive +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/ZipArchive.h" +#include "Poco/Zip/SkipCallback.h" +#include "Poco/Exception.h" +#include + + +namespace Poco { +namespace Zip { + + +ZipArchive::ZipArchive(std::istream& in): + _entries(), + _infos(), + _disks() +{ + poco_assert_dbg (in); + SkipCallback skip; + parse(in, skip); +} + + +ZipArchive::ZipArchive(const FileHeaders& entries, const FileInfos& infos, const DirectoryInfos& dirs): + _entries(entries), + _infos(infos), + _disks(dirs) +{ +} + + +ZipArchive::ZipArchive(std::istream& in, ParseCallback& pc): + _entries(), + _infos(), + _disks() +{ + poco_assert_dbg (in); + parse(in, pc); +} + + +ZipArchive::~ZipArchive() +{ +} + + +void ZipArchive::parse(std::istream& in, ParseCallback& pc) +{ + // read 4 bytes + while (in.good() && !in.eof()) + { + char header[ZipCommon::HEADER_SIZE]={'\x00', '\x00', '\x00', '\x00'}; + in.read(header, ZipCommon::HEADER_SIZE); + if (in.eof()) + return; + if (std::memcmp(header, ZipLocalFileHeader::HEADER, ZipCommon::HEADER_SIZE) == 0) + { + ZipLocalFileHeader entry(in, true, pc); + poco_assert (_entries.insert(std::make_pair(entry.getFileName(), entry)).second); + } + else if (std::memcmp(header, ZipFileInfo::HEADER, ZipCommon::HEADER_SIZE) == 0) + { + ZipFileInfo info(in, true); + FileHeaders::iterator it = _entries.find(info.getFileName()); + if (it != _entries.end()) + { + it->second.setStartPos(info.getRelativeOffsetOfLocalHeader()); + } + poco_assert (_infos.insert(std::make_pair(info.getFileName(), info)).second); + } + else if (std::memcmp(header, ZipArchiveInfo::HEADER, ZipCommon::HEADER_SIZE) == 0) + { + ZipArchiveInfo nfo(in, true); + poco_assert (_disks.insert(std::make_pair(nfo.getDiskNumber(), nfo)).second); + } + else + { + if (_disks.empty()) + throw Poco::IllegalStateException("Illegal header in zip file"); + else + throw Poco::IllegalStateException("Garbage after directory header"); + } + + } +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/ZipArchiveInfo.cpp b/Zip/src/ZipArchiveInfo.cpp new file mode 100644 index 000000000..4ea9dee9f --- /dev/null +++ b/Zip/src/ZipArchiveInfo.cpp @@ -0,0 +1,106 @@ +// +// ZipArchiveInfo.cpp +// +// $Id: //poco/1.3/Zip/src/ZipArchiveInfo.cpp#3 $ +// +// Library: Zip +// Package: Zip +// Module: ZipArchiveInfo +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/ZipArchiveInfo.h" +#include "Poco/Buffer.h" +#include +#include + + +namespace Poco { +namespace Zip { + + +const char ZipArchiveInfo::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x05', '\x06'}; + + +ZipArchiveInfo::ZipArchiveInfo(std::istream& in, bool assumeHeaderRead): + _rawInfo(), + _startPos(in.tellg()), + _comment() +{ + if (assumeHeaderRead) + _startPos -= ZipCommon::HEADER_SIZE; + parse(in, assumeHeaderRead); +} + +ZipArchiveInfo::ZipArchiveInfo(): + _rawInfo(), + _startPos(0), + _comment() +{ + std::memset(_rawInfo, 0, FULLHEADER_SIZE); + std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); +} + + +ZipArchiveInfo::~ZipArchiveInfo() +{ +} + + +void ZipArchiveInfo::parse(std::istream& inp, bool assumeHeaderRead) +{ + if (!assumeHeaderRead) + { + inp.read(_rawInfo, ZipCommon::HEADER_SIZE); + } + else + { + std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); + } + poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); + // read the rest of the header + inp.read(_rawInfo + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); + Poco::UInt16 len = getZipCommentSize(); + if (len > 0) + { + Poco::Buffer buf(len); + inp.read(buf.begin(), len); + _comment = std::string(buf.begin(), len); + } +} + + +std::string ZipArchiveInfo::createHeader() const +{ + std::string result(_rawInfo, FULLHEADER_SIZE); + result.append(_comment); + return result; +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/ZipCommon.cpp b/Zip/src/ZipCommon.cpp new file mode 100644 index 000000000..7771726d7 --- /dev/null +++ b/Zip/src/ZipCommon.cpp @@ -0,0 +1,47 @@ +// +// ZipCommon.cpp +// +// $Id: //poco/1.3/Zip/src/ZipCommon.cpp#3 $ +// +// Library: Zip +// Package: Zip +// Module: ZipCommon +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/ZipCommon.h" + + +namespace Poco { +namespace Zip { + + +const std::string ZipCommon::ILLEGAL_PATH(".."); + + +} } // namespace Poco::Zip diff --git a/Zip/src/ZipDataInfo.cpp b/Zip/src/ZipDataInfo.cpp new file mode 100644 index 000000000..fae972294 --- /dev/null +++ b/Zip/src/ZipDataInfo.cpp @@ -0,0 +1,79 @@ +// +// ZipDataInfo.cpp +// +// $Id: //poco/1.3/Zip/src/ZipDataInfo.cpp#3 $ +// +// Library: Zip +// Package: Zip +// Module: ZipDataInfo +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/ZipDataInfo.h" +#include +#include + + +namespace Poco { +namespace Zip { + + +const char ZipDataInfo::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x07', '\x08'}; + + +ZipDataInfo::ZipDataInfo(): + _rawInfo(), + _valid(true) +{ + std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); + std::memset(_rawInfo+ZipCommon::HEADER_SIZE, 0, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); + _valid = true; +} + + +ZipDataInfo::ZipDataInfo(std::istream& in, bool assumeHeaderRead): + _rawInfo(), + _valid(false) +{ + if (assumeHeaderRead) + std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); + else + in.read(_rawInfo, ZipCommon::HEADER_SIZE); + poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); + // now copy the rest of the header + in.read(_rawInfo+ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); + _valid = (!in.eof() && in.good()); +} + + +ZipDataInfo::~ZipDataInfo() +{ +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/ZipException.cpp b/Zip/src/ZipException.cpp new file mode 100644 index 000000000..0a6c2045c --- /dev/null +++ b/Zip/src/ZipException.cpp @@ -0,0 +1,49 @@ +// +// ZipException.cpp +// +// $Id: //poco/1.3/Zip/src/ZipException.cpp#4 $ +// +// Library: Zip +// Package: Zip +// Module: ZipException +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/ZipException.h" +#include + + +namespace Poco { +namespace Zip { + + +POCO_IMPLEMENT_EXCEPTION(ZipException, Poco::RuntimeException, "ZIP Exception") +POCO_IMPLEMENT_EXCEPTION(ZipManipulationException, ZipException, "ZIP Manipulation Exception") + + +} } // namespace Poco::Zip diff --git a/Zip/src/ZipFileInfo.cpp b/Zip/src/ZipFileInfo.cpp new file mode 100644 index 000000000..2cbc35061 --- /dev/null +++ b/Zip/src/ZipFileInfo.cpp @@ -0,0 +1,143 @@ +// +// ZipFileInfo.cpp +// +// $Id: //poco/1.3/Zip/src/ZipFileInfo.cpp#4 $ +// +// Library: Zip +// Package: Zip +// Module: ZipFileInfo +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/ZipFileInfo.h" +#include "Poco/Zip/ZipLocalFileHeader.h" +#include "Poco/Buffer.h" +#include +#include + + +namespace Poco { +namespace Zip { + + +const char ZipFileInfo::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x01', '\x02'}; + + +ZipFileInfo::ZipFileInfo(const ZipLocalFileHeader& header): + _rawInfo(), + _crc32(0), + _compressedSize(0), + _uncompressedSize(0), + _fileName(), + _lastModifiedAt(), + _extraField() +{ + std::memset(_rawInfo, 0, FULLHEADER_SIZE); + std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); + setCompressedSize(header.getCompressedSize()); + setUncompressedSize(header.getUncompressedSize()); + setCRC(header.getCRC()); + setCompressionMethod(header.getCompressionMethod()); + setCompressionLevel(header.getCompressionLevel()); + setRequiredVersion(header.getMajorVersionNumber(), header.getMinorVersionNumber()); + setHostSystem(header.getHostSystem()); + setLastModifiedAt(header.lastModifiedAt()); + setEncryption(false); + setFileName(header.getFileName()); +} + + +ZipFileInfo::ZipFileInfo(std::istream& in, bool assumeHeaderRead): + _rawInfo(), + _crc32(0), + _compressedSize(0), + _uncompressedSize(0), + _fileName(), + _lastModifiedAt(), + _extraField() +{ + // sanity check + poco_assert_dbg (RELATIVEOFFSETLOCALHEADER_POS + RELATIVEOFFSETLOCALHEADER_SIZE == FULLHEADER_SIZE); + parse(in, assumeHeaderRead); +} + + +ZipFileInfo::~ZipFileInfo() +{ +} + + +void ZipFileInfo::parse(std::istream& inp, bool assumeHeaderRead) +{ + if (!assumeHeaderRead) + { + inp.read(_rawInfo, ZipCommon::HEADER_SIZE); + } + else + { + std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); + } + poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); + // read the rest of the header + inp.read(_rawInfo + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); + _crc32 = getCRCFromHeader(); + _compressedSize = getCompressedSizeFromHeader(); + _uncompressedSize = getUncompressedSizeFromHeader(); + parseDateTime(); + Poco::UInt16 len = getFileNameLength(); + Poco::Buffer buf(len); + inp.read(buf.begin(), len); + _fileName = std::string(buf.begin(), len); + if (hasExtraField()) + { + len = getExtraFieldLength(); + Poco::Buffer xtra(len); + inp.read(xtra.begin(), len); + _extraField = std::string(xtra.begin(), len); + } + len = getFileCommentLength(); + if (len > 0) + { + Poco::Buffer buf2(len); + inp.read(buf2.begin(), len); + _fileComment = std::string(buf2.begin(), len); + } +} + + +std::string ZipFileInfo::createHeader() const +{ + std::string result(_rawInfo, FULLHEADER_SIZE); + result.append(_fileName); + result.append(_extraField); + result.append(_fileComment); + return result; +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/ZipLocalFileHeader.cpp b/Zip/src/ZipLocalFileHeader.cpp new file mode 100644 index 000000000..7886f59f1 --- /dev/null +++ b/Zip/src/ZipLocalFileHeader.cpp @@ -0,0 +1,238 @@ +// +// ZipLocalFileHeader.cpp +// +// $Id: //poco/1.3/Zip/src/ZipLocalFileHeader.cpp#4 $ +// +// Library: Zip +// Package: Zip +// Module: ZipLocalFileHeader +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/ZipLocalFileHeader.h" +#include "Poco/Zip/ZipDataInfo.h" +#include "Poco/Zip/ParseCallback.h" +#include "Poco/Buffer.h" +#include "Poco/Exception.h" +#include "Poco/File.h" +#include + + +namespace Poco { +namespace Zip { + + +const char ZipLocalFileHeader::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x03', '\x04'}; + + +ZipLocalFileHeader::ZipLocalFileHeader(const Poco::Path& fileName, + const Poco::DateTime& lastModifiedAt, + ZipCommon::CompressionMethod cm, + ZipCommon::CompressionLevel cl): + _rawHeader(), + _startPos(-1), + _endPos(-1), + _fileName(), + _lastModifiedAt(), + _extraField(), + _crc32(0), + _compressedSize(0), + _uncompressedSize(0) +{ + std::memcpy(_rawHeader, HEADER, ZipCommon::HEADER_SIZE); + std::memset(_rawHeader+ZipCommon::HEADER_SIZE, 0, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); + ZipCommon::HostSystem hs = ZipCommon::HS_FAT; + +#if (POCO_OS == POCO_OS_CYGWIN) + hs = ZipCommon::HS_UNIX; +#endif +#if (POCO_OS == POCO_OS_VMS) + hs = ZipCommon::HS_VMS; +#endif +#if defined(POCO_OS_FAMILY_UNIX) + hs = ZipCommon::HS_UNIX; +#endif + setHostSystem(hs); + setEncryption(false); + setExtraFieldSize(0); + setLastModifiedAt(lastModifiedAt); + init(fileName, cm, cl); +} + + +ZipLocalFileHeader::ZipLocalFileHeader(std::istream& inp, bool assumeHeaderRead, ParseCallback& callback): + _rawHeader(), + _startPos(inp.tellg()), + _endPos(-1), + _fileName(), + _lastModifiedAt(), + _extraField(), + _crc32(0), + _compressedSize(0), + _uncompressedSize(0) +{ + poco_assert_dbg( (EXTRAFIELD_POS+EXTRAFIELD_LENGTH) == FULLHEADER_SIZE); + + if (assumeHeaderRead) + _startPos -= ZipCommon::HEADER_SIZE; + + parse(inp, assumeHeaderRead); + + bool ok = callback.handleZipEntry(inp, *this); + + if (ok) + { + if (searchCRCAndSizesAfterData()) + { + ZipDataInfo nfo(inp, false); + setCRC(nfo.getCRC32()); + setCompressedSize(nfo.getCompressedSize()); + setUncompressedSize(nfo.getUncompressedSize()); + } + } + else + { + poco_assert_dbg(!searchCRCAndSizesAfterData()); + ZipUtil::sync(inp); + } + _endPos = _startPos + getHeaderSize() + _compressedSize; // exclude the data block! +} + + +ZipLocalFileHeader::~ZipLocalFileHeader() +{ +} + + +void ZipLocalFileHeader::parse(std::istream& inp, bool assumeHeaderRead) +{ + if (!assumeHeaderRead) + { + inp.read(_rawHeader, ZipCommon::HEADER_SIZE); + } + else + { + std::memcpy(_rawHeader, HEADER, ZipCommon::HEADER_SIZE); + } + poco_assert (std::memcmp(_rawHeader, HEADER, ZipCommon::HEADER_SIZE) == 0); + // read the rest of the header + inp.read(_rawHeader + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); + poco_assert (_rawHeader[VERSION_POS + 1]>= ZipCommon::HS_FAT && _rawHeader[VERSION_POS + 1] < ZipCommon::HS_UNUSED); + poco_assert (getMajorVersionNumber() <= 2); + poco_assert (ZipUtil::get16BitValue(_rawHeader, COMPR_METHOD_POS) < ZipCommon::CM_UNUSED); + parseDateTime(); + Poco::UInt16 len = getFileNameLength(); + Poco::Buffer buf(len); + inp.read(buf.begin(), len); + _fileName = std::string(buf.begin(), len); + if (hasExtraField()) + { + len = getExtraFieldLength(); + Poco::Buffer xtra(len); + inp.read(xtra.begin(), len); + _extraField = std::string(xtra.begin(), len); + } + if (!searchCRCAndSizesAfterData()) + { + _crc32 = getCRCFromHeader(); + _compressedSize = getCompressedSizeFromHeader(); + _uncompressedSize = getUncompressedSizeFromHeader(); + } +} + + +bool ZipLocalFileHeader::searchCRCAndSizesAfterData() const +{ + if (getCompressionMethod() == ZipCommon::CM_DEFLATE) + { + // check bit 3 + return ((ZipUtil::get16BitValue(_rawHeader, GENERAL_PURPOSE_POS) & 0x0008) != 0); + } + return false; +} + + +void ZipLocalFileHeader::setFileName(const std::string& fileName, bool isDirectory) +{ + poco_assert (!fileName.empty()); + Poco::Path aPath(fileName); + + if (isDirectory) + { + aPath.makeDirectory(); + setCRC(0); + setCompressedSize(0); + setUncompressedSize(0); + setCompressionMethod(ZipCommon::CM_STORE); + setCompressionLevel(ZipCommon::CL_NORMAL); + } + else + { + aPath.makeFile(); + } + _fileName = aPath.toString(Poco::Path::PATH_UNIX); + if (_fileName[0] == '/') + _fileName = _fileName.substr(1); + if (isDirectory) + { + poco_assert_dbg (_fileName[_fileName.size()-1] == '/'); + } + setFileNameLength(static_cast(_fileName.size())); +} + + +void ZipLocalFileHeader::init( const Poco::Path& fName, + ZipCommon::CompressionMethod cm, + ZipCommon::CompressionLevel cl) +{ + poco_assert (_fileName.empty()); + setSearchCRCAndSizesAfterData(false); + Poco::Path fileName(fName); + fileName.setDevice(""); // clear device! + setFileName(fileName.toString(Poco::Path::PATH_UNIX), fileName.isDirectory()); + setRequiredVersion(2, 0); + if (fileName.isFile()) + { + setCompressionMethod(cm); + setCompressionLevel(cl); + } + else + setCompressionMethod(ZipCommon::CM_STORE); +} + + +std::string ZipLocalFileHeader::createHeader() const +{ + std::string result(_rawHeader, FULLHEADER_SIZE); + result.append(_fileName); + result.append(_extraField); + return result; +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/ZipManipulator.cpp b/Zip/src/ZipManipulator.cpp new file mode 100644 index 000000000..adb4fff5d --- /dev/null +++ b/Zip/src/ZipManipulator.cpp @@ -0,0 +1,194 @@ +// +// ZipManipulator.cpp +// +// $Id: //poco/1.3/Zip/src/ZipManipulator.cpp#2 $ +// +// Library: Zip +// Package: Manipulation +// Module: ZipManipulator +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/ZipManipulator.h" +#include "Poco/Zip/ZipException.h" +#include "Poco/Zip/ZipUtil.h" +#include "Poco/Zip/Add.h" +#include "Poco/Zip/Delete.h" +#include "Poco/Zip/Keep.h" +#include "Poco/Zip/Rename.h" +#include "Poco/Zip/Replace.h" +#include "Poco/Zip/Compress.h" +#include "Poco/Delegate.h" +#include "Poco/File.h" +#include "Poco/FileStream.h" +#include + + +namespace Poco { +namespace Zip { + + +ZipManipulator::ZipManipulator(const std::string& zipFile, bool backupOriginalFile): + _zipFile(zipFile), + _backupOriginalFile(backupOriginalFile), + _changes(), + _in(0) +{ + std::ifstream in(zipFile.c_str()); + _in = new ZipArchive(in); +} + + +ZipManipulator::~ZipManipulator() +{ +} + + +void ZipManipulator::deleteFile(const std::string& zipPath) +{ + const ZipLocalFileHeader& entry = getForChange(zipPath); + addOperation(zipPath, new Delete(entry)); +} + + +void ZipManipulator::replaceFile(const std::string& zipPath, const std::string& localPath) +{ + const ZipLocalFileHeader& entry = getForChange(zipPath); + addOperation(zipPath, new Replace(entry, localPath)); +} + + +void ZipManipulator::renameFile(const std::string& zipPath, const std::string& newZipPath) +{ + const ZipLocalFileHeader& entry = getForChange(zipPath); + // checked later in Compress too but the earlier one gets the error the better + std::string fn = ZipUtil::validZipEntryFileName(newZipPath); + addOperation(zipPath, new Rename(entry, fn)); +} + + +void ZipManipulator::addFile(const std::string& zipPath, const std::string& localPath, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl) +{ + addOperation(zipPath, new Add(zipPath, localPath, cm, cl)); +} + + +ZipArchive ZipManipulator::commit() +{ + // write to a tmp file + std::string outFile(_zipFile + ".tmp"); + ZipArchive retVal(compress(outFile)); + //renaming + { + Poco::File aFile(_zipFile); + if (_backupOriginalFile) + { + Poco::File tmp(_zipFile+".bak"); + if (tmp.exists()) + tmp.remove(); + aFile.renameTo(_zipFile+".bak"); + } + else + aFile.remove(); + } + + { + Poco::File resFile(outFile); + Poco::File zipFile(_zipFile); + if (zipFile.exists()) + zipFile.remove(); + resFile.renameTo(_zipFile); + } + return retVal; +} + + +const ZipLocalFileHeader& ZipManipulator::getForChange(const std::string& zipPath) const +{ + ZipArchive::FileHeaders::const_iterator it = _in->findHeader(zipPath); + if (it == _in->headerEnd()) + throw ZipManipulationException("entry not found: " + zipPath); + + if (_changes.find(zipPath) != _changes.end()) + throw ZipManipulationException("A change request exists already for entry " + zipPath); + + return it->second; +} + + +void ZipManipulator::addOperation(const std::string& zipPath, ZipOperation::Ptr ptrOp) +{ + std::pair result = _changes.insert(std::make_pair(zipPath, ptrOp)); + if (!result.second) + throw ZipManipulationException("A change request exists already for entry " + zipPath); +} + + +void ZipManipulator::onEDone(const void*, const ZipLocalFileHeader& hdr) +{ + EDone(this, hdr); +} + + +ZipArchive ZipManipulator::compress(const std::string& outFile) +{ + // write to a tmp file + Poco::FileInputStream in(_zipFile); + Poco::FileOutputStream out(outFile); + Compress c(out, true); + c.EDone += Poco::Delegate(this, &ZipManipulator::onEDone); + + ZipArchive::FileHeaders::const_iterator it = _in->headerBegin(); + for (; it != _in->headerEnd(); ++it) + { + Changes::iterator itC = _changes.find(it->first); + if (itC != _changes.end()) + { + itC->second->execute(c, in); + _changes.erase(itC); + } + else + { + Keep k(it->second); + k.execute(c, in); + } + } + //Remaining files are add operations! + Changes::iterator itC = _changes.begin(); + for (; itC != _changes.end(); ++itC) + { + itC->second->execute(c, in); + } + _changes.clear(); + c.EDone -= Poco::Delegate(this, &ZipManipulator::onEDone); + in.close(); + return c.close(); +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/ZipOperation.cpp b/Zip/src/ZipOperation.cpp new file mode 100644 index 000000000..f1aed3d0e --- /dev/null +++ b/Zip/src/ZipOperation.cpp @@ -0,0 +1,54 @@ +// +// ZipOperation.cpp +// +// $Id: //poco/1.3/Zip/src/ZipOperation.cpp#1 $ +// +// Library: Zip +// Package: Manipulation +// Module: ZipOperation +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/ZipOperation.h" + + +namespace Poco { +namespace Zip { + + +ZipOperation::ZipOperation() +{ +} + + +ZipOperation::~ZipOperation() +{ +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/ZipStream.cpp b/Zip/src/ZipStream.cpp new file mode 100644 index 000000000..5b2ad8dd5 --- /dev/null +++ b/Zip/src/ZipStream.cpp @@ -0,0 +1,319 @@ +// +// ZipStream.cpp +// +// $Id: //poco/1.3/Zip/src/ZipStream.cpp#4 $ +// +// Library: Zip +// Package: Zip +// Module: ZipStream +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/ZipStream.h" +#include "Poco/zlib.h" +#include "Poco/Zip/ZipArchive.h" +#include "Poco/Zip/AutoDetectStream.h" +#include "Poco/Zip/PartialStream.h" +#include "Poco/Zip/ZipDataInfo.h" +#include "Poco/Zip/ZipException.h" +#include "Poco/Exception.h" +#include "Poco/InflatingStream.h" +#include "Poco/DeflatingStream.h" + + +namespace Poco { +namespace Zip { + + +ZipStreamBuf::ZipStreamBuf(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): + Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in), + _pIstr(&istr), + _pOstr(0), + _ptrBuf(), + _ptrOBuf(), + _ptrHelper(), + _ptrOHelper(), + _crc32(Poco::Checksum::TYPE_CRC32), + _expectedCrc32(0), + _checkCRC(true), + _bytesWritten(0), + _pHeader(0) +{ + if (fileEntry.isDirectory()) + return; + _expectedCrc32 = fileEntry.getCRC(); + std::streamoff start = fileEntry.getDataStartPos(); + std::streamoff end = fileEntry.getDataEndPos(); + _checkCRC = !fileEntry.searchCRCAndSizesAfterData(); + if (fileEntry.getCompressionMethod() == ZipCommon::CM_DEFLATE) + { + // Fake init bytes at beginning of stream + std::string init = ZipUtil::fakeZLibInitString(fileEntry.getCompressionLevel()); + + // Fake adler at end of stream: just some dummy value, not checked anway + std::string crc(4, ' '); + if (fileEntry.searchCRCAndSizesAfterData()) + { + _ptrHelper = new AutoDetectInputStream(istr, init, crc, reposition, start); + } + else + _ptrHelper = new PartialInputStream(istr, start, end, reposition, init, crc); + _ptrBuf = new Poco::InflatingInputStream(*_ptrHelper, Poco::InflatingStreamBuf::STREAM_ZIP); + } + else if (fileEntry.getCompressionMethod() == ZipCommon::CM_STORE) + { + if (fileEntry.searchCRCAndSizesAfterData()) + { + _ptrBuf = new AutoDetectInputStream(istr, "", "", reposition, start); + } + else + _ptrBuf = new PartialInputStream(istr, start, end, reposition); + } + else + { + throw Poco::NotImplementedException("Unsupported compression method"); + } +} + + +ZipStreamBuf::ZipStreamBuf(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool reposition): + Poco::BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::out), + _pIstr(0), + _pOstr(&ostr), + _ptrBuf(), + _ptrOBuf(), + _ptrHelper(), + _ptrOHelper(), + _crc32(Poco::Checksum::TYPE_CRC32), + _expectedCrc32(0), + _checkCRC(false), + _bytesWritten(0), + _pHeader(&fileEntry) +{ + if (fileEntry.isEncrypted()) + throw Poco::NotImplementedException("Encryption not supported"); + + if (fileEntry.isDirectory()) + { + // only header, no payload, zero crc + fileEntry.setSearchCRCAndSizesAfterData(false); + fileEntry.setCompressedSize(0); + fileEntry.setUncompressedSize(0); + fileEntry.setCRC(0); + std::string header = fileEntry.createHeader(); + ostr.write(header.c_str(), static_cast(header.size())); + } + else + { + fileEntry.setSearchCRCAndSizesAfterData(!reposition); + if (fileEntry.getCompressionMethod() == ZipCommon::CM_DEFLATE) + { + int level = Z_DEFAULT_COMPRESSION; + if (fileEntry.getCompressionLevel() == ZipCommon::CL_FAST || fileEntry.getCompressionLevel() == ZipCommon::CL_SUPERFAST) + level = Z_BEST_SPEED; + else if (fileEntry.getCompressionLevel() == ZipCommon::CL_MAXIMUM) + level = Z_BEST_COMPRESSION; + // ignore the zlib init string which is of size 2 and also ignore the 4 byte adler32 value at the end of the stream! + _ptrOHelper = new PartialOutputStream(*_pOstr, 2, 4, false); + _ptrOBuf = new Poco::DeflatingOutputStream(*_ptrOHelper, DeflatingStreamBuf::STREAM_ZLIB, level); + } + else if (fileEntry.getCompressionMethod() == ZipCommon::CM_STORE) + { + _ptrOHelper = new PartialOutputStream(*_pOstr, 0, 0, false); + _ptrOBuf = _ptrOHelper; + } + else + { + throw Poco::NotImplementedException("Unsupported compression method"); + } + // now write the header to the ostr! + std::string header = fileEntry.createHeader(); + ostr.write(header.c_str(), static_cast(header.size())); + } +} + + +ZipStreamBuf::~ZipStreamBuf() +{ +} + + +int ZipStreamBuf::readFromDevice(char* buffer, std::streamsize length) +{ + if (!_ptrBuf) return 0; // directory entry + _ptrBuf->read(buffer, length); + int cnt = _ptrBuf->gcount(); + if (cnt > 0) + { + _crc32.update(buffer, cnt); + } + else + { + if (_crc32.checksum() != _expectedCrc32) + { + if (_checkCRC) + throw ZipException("CRC failure"); + else + { + // the CRC value is written directly after the data block + // parse it directly from the input stream + ZipDataInfo nfo(*_pIstr, false); + // now push back the header to the stream, so that the ZipLocalFileHeader can read it + Poco::Int32 size = static_cast(nfo.getFullHeaderSize()); + _expectedCrc32 = nfo.getCRC32(); + const char* rawHeader = nfo.getRawHeader(); + for (Poco::Int32 i = size-1; i >= 0; --i) + _pIstr->putback(rawHeader[i]); + if (!crcValid()) + throw ZipException("CRC failure"); + } + } + } + return cnt; +} + + +int ZipStreamBuf::writeToDevice(const char* buffer, std::streamsize length) +{ + if (!_ptrOBuf) return 0; // directory entry + if (length == 0) + return 0; + _bytesWritten += length; + _ptrOBuf->write(buffer, length); + _crc32.update(buffer, length); + return length; +} + + +void ZipStreamBuf::close() +{ + if (_ptrOBuf && _pHeader) + { + _ptrOBuf->flush(); + DeflatingOutputStream* pDO = dynamic_cast(_ptrOBuf.get()); + if (pDO) + pDO->close(); + if (_ptrOHelper) + { + _ptrOHelper->flush(); + _ptrOHelper->close(); + } + _ptrOBuf = 0; + poco_assert (*_pOstr); + // write an extra datablock if required + // or fix the crc entries + if (_pHeader->searchCRCAndSizesAfterData()) + { + ZipDataInfo info; + info.setCRC32(_crc32.checksum()); + info.setUncompressedSize(_bytesWritten); + info.setCompressedSize(static_cast(_ptrOHelper->bytesWritten())); + _pOstr->write(info.getRawHeader(), static_cast(info.getFullHeaderSize())); + } + else + { + poco_check_ptr (_pHeader); + _pHeader->setCRC(_crc32.checksum()); + _pHeader->setUncompressedSize(_bytesWritten); + _pHeader->setCompressedSize(static_cast(_ptrOHelper->bytesWritten())); + _pOstr->seekp(_pHeader->getStartPos(), std::ios_base::beg); + poco_assert (*_pOstr); + std::string header = _pHeader->createHeader(); + _pOstr->write(header.c_str(), static_cast(header.size())); + _pOstr->seekp(0, std::ios_base::end); + poco_assert (*_pOstr); + } + _pHeader = 0; + } +} + + +bool ZipStreamBuf::crcValid() const +{ + if (!_ptrBuf) return true; // directory entry + return _crc32.checksum() == _expectedCrc32; +} + + +ZipIOS::ZipIOS(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): _buf(istr, fileEntry, reposition) +{ + poco_ios_init(&_buf); +} + + +ZipIOS::ZipIOS(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool reposition): _buf(ostr, fileEntry, reposition) +{ + poco_ios_init(&_buf); +} + + +ZipIOS::~ZipIOS() +{ +} + + +ZipStreamBuf* ZipIOS::rdbuf() +{ + return &_buf; +} + + +ZipInputStream::ZipInputStream(std::istream& istr, const ZipLocalFileHeader& fileEntry, bool reposition): ZipIOS(istr, fileEntry, reposition), std::istream(&_buf) +{ +} + + +ZipInputStream::~ZipInputStream() +{ +} + + +bool ZipInputStream::crcValid() const +{ + return _buf.crcValid(); +} + + +ZipOutputStream::ZipOutputStream(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bool seekableOutput): ZipIOS(ostr, fileEntry, seekableOutput), std::ostream(&_buf) +{ +} + + +ZipOutputStream::~ZipOutputStream() +{ +} + + +void ZipOutputStream::close() +{ + flush(); + _buf.close(); +} + + +} } // namespace Poco::Zip diff --git a/Zip/src/ZipUtil.cpp b/Zip/src/ZipUtil.cpp new file mode 100644 index 000000000..7199ebb17 --- /dev/null +++ b/Zip/src/ZipUtil.cpp @@ -0,0 +1,212 @@ +// +// ZipUtil.cpp +// +// $Id: //poco/1.3/Zip/src/ZipUtil.cpp#4 $ +// +// Library: Zip +// Package: Zip +// Module: ZipUtil +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "Poco/Zip/ZipUtil.h" +#include "Poco/Zip/ZipException.h" +#include "Poco/Zip/ZipLocalFileHeader.h" +#include "Poco/Zip/ZipFileInfo.h" +#include "Poco/Zip/ZipDataInfo.h" +#include "Poco/Zip/ZipArchiveInfo.h" +#include + + +namespace Poco { +namespace Zip { + + +Poco::DateTime ZipUtil::parseDateTime(const char* pVal, const Poco::UInt32 timePos, const Poco::UInt32 datePos) +{ + Poco::UInt16 time = ZipUtil::get16BitValue(pVal, timePos); + Poco::UInt16 date = ZipUtil::get16BitValue(pVal, datePos); + //TIME: second 0-4, minute 5-10, hour 11-15, second resolution is 2! + int sec = 2*(time & 0x001fu); // 0000 0000 0001 1111 + int min = ((time & 0x07e0u) >> 5); // 0000 0111 1110 0000 + int hour= ((time & 0xf800u) >> 11); // 1111 1000 0000 0000 + + //DATE: day 0-4, month 5-8, year (starting with 1980): 9-16 + int day = (date & 0x001fu); // 0000 0000 0001 1111 + int mon = ((date & 0x01e0u) >> 5); // 0000 0001 1110 0000 + int year= 1980+((date & 0xfe00u) >> 9); // 1111 1110 0000 0000 + return Poco::DateTime(year, mon, day, hour, min, sec); +} + + +void ZipUtil::setDateTime(const Poco::DateTime& dt, char* pVal, const Poco::UInt32 timePos, const Poco::UInt32 datePos) +{ + //TIME: second 0-4, minute 5-10, hour 11-15 + Poco::UInt16 time = static_cast((dt.second()/2) + (dt.minute()<<5) + (dt.hour()<<11)); + //DATE: day 0-4, month 5-8, year (starting with 1980): 9-16 + int year = dt.year() - 1980; + if (year<0) + year = 0; + Poco::UInt16 date = static_cast(dt.day() + (dt.month()<<5) + (year<<9)); + ZipUtil::set16BitValue(time, pVal, timePos); + ZipUtil::set16BitValue(date, pVal, datePos); + +} + + +std::string ZipUtil::fakeZLibInitString(ZipCommon::CompressionLevel cl) +{ + std::string init(2, ' '); + + // compression info: + // deflate is used, bit 0-3: 0x08 + // dictionary size is always 32k: calc ld2(32k)-8 = ld2(2^15) - 8 = 15 - 8 = 7 --> bit 4-7: 0x70 + init[0] = '\x78'; + + // now fake flags + // bits 0-4 check bits: set them so that init[0]*256+init[1] % 31 == 0 + // bit 5: preset dictionary? always no for us, set to 0 + // bits 6-7: compression level: 00 very fast, 01 fast, 10 normal, 11 best + if (cl == ZipCommon::CL_SUPERFAST) + init[1] = '\x00'; + else if (cl == ZipCommon::CL_FAST) + init[1] = '\x40'; + else if (cl == ZipCommon::CL_NORMAL) + init[1] = '\x80'; + else + init[1] = '\xc0'; + // now set the last 5 bits + Poco::UInt16 tmpVal = ((Poco::UInt16)init[0])*256+((unsigned char)init[1]); + char checkBits = (31 - (char)(tmpVal%31)); + init[1] |= checkBits; // set the lower 5 bits + tmpVal = ((Poco::UInt16)init[0])*256+((unsigned char)init[1]); + poco_assert_dbg ((tmpVal % 31) == 0); + return init; +} + + +void ZipUtil::sync(std::istream& in) +{ + enum + { + PREFIX = 2, + BUFFER_SIZE = 1024 + }; + char temp[BUFFER_SIZE]; + in.read(temp, PREFIX); + std::size_t tempPos = PREFIX; + + while (in.good() && !in.eof()) + { + // all zip headers start withe same 2byte prefix + if(std::memcmp(ZipLocalFileHeader::HEADER, &temp[tempPos - PREFIX], PREFIX) == 0) + { + // we have a possible header! + // read the next 2 bytes + in.read(temp+tempPos, PREFIX); + tempPos += PREFIX; + if (std::memcmp(ZipLocalFileHeader::HEADER+PREFIX, &temp[tempPos - PREFIX], PREFIX) == 0 || + std::memcmp(ZipArchiveInfo::HEADER+PREFIX, &temp[tempPos - PREFIX], PREFIX) == 0 || + std::memcmp(ZipFileInfo::HEADER+PREFIX, &temp[tempPos - PREFIX], PREFIX) == 0 || + std::memcmp(ZipDataInfo::HEADER+PREFIX, &temp[tempPos - PREFIX], PREFIX) == 0) + { + if (std::memcmp(ZipLocalFileHeader::HEADER+PREFIX, &temp[tempPos - PREFIX], PREFIX) == 0) + { + in.putback(ZipLocalFileHeader::HEADER[3]); + in.putback(ZipLocalFileHeader::HEADER[2]); + in.putback(ZipLocalFileHeader::HEADER[1]); + in.putback(ZipLocalFileHeader::HEADER[0]); + } + else if (std::memcmp(ZipArchiveInfo::HEADER+PREFIX, &temp[tempPos - PREFIX], PREFIX) == 0) + { + in.putback(ZipArchiveInfo::HEADER[3]); + in.putback(ZipArchiveInfo::HEADER[2]); + in.putback(ZipArchiveInfo::HEADER[1]); + in.putback(ZipArchiveInfo::HEADER[0]); + } + else if (std::memcmp(ZipFileInfo::HEADER+PREFIX, &temp[tempPos - PREFIX], PREFIX) == 0) + { + in.putback(ZipFileInfo::HEADER[3]); + in.putback(ZipFileInfo::HEADER[2]); + in.putback(ZipFileInfo::HEADER[1]); + in.putback(ZipFileInfo::HEADER[0]); + } + else + { + in.putback(ZipDataInfo::HEADER[3]); + in.putback(ZipDataInfo::HEADER[2]); + in.putback(ZipDataInfo::HEADER[1]); + in.putback(ZipDataInfo::HEADER[0]); + } + return; + } + else + { + // we have read 2 bytes, should only be one: putback the last char + in.putback(temp[tempPos - 1]); + --tempPos; + } + } + else + { + // read one byte + in.read(temp + tempPos, 1); + ++tempPos; + } + + if (tempPos > (BUFFER_SIZE - ZipCommon::HEADER_SIZE)) + { + std::memcpy(temp, &temp[tempPos - ZipCommon::HEADER_SIZE], ZipCommon::HEADER_SIZE); + tempPos = ZipCommon::HEADER_SIZE; + } + } +} + + +void ZipUtil::verifyZipEntryFileName(const std::string& fn) +{ + if (fn.find("\\") != std::string::npos) + throw ZipException("Illegal entry name " + fn + " containing \\"); + if (fn == "/") + throw ZipException("Illegal entry name /"); + if (fn.empty()) + throw ZipException("Illegal empty entry name"); + if (fn.find(ZipCommon::ILLEGAL_PATH) != std::string::npos) + throw ZipException("Illegal entry name " + fn + " containing " + ZipCommon::ILLEGAL_PATH); +} + + +std::string ZipUtil::validZipEntryFileName(const Poco::Path& entry) +{ + std::string fn = entry.toString(Poco::Path::PATH_UNIX); + verifyZipEntryFileName(fn); + return fn; +} + + +} } // namespace Poco::Zip diff --git a/Zip/testsuite/Makefile b/Zip/testsuite/Makefile new file mode 100644 index 000000000..adc669d1e --- /dev/null +++ b/Zip/testsuite/Makefile @@ -0,0 +1,18 @@ +# +# Makefile +# +# $Id: //poco/1.3/Zip/testsuite/Makefile#1 $ +# +# Makefile for Poco Zip testsuite +# + +include $(POCO_BASE)/build/rules/global + +objects = ZipTestSuite Driver \ + ZipTest CompressTest PartialStreamTest + +target = testrunner +target_version = 1 +target_libs = PocoZip PocoNet PocoFoundation CppUnit + +include $(POCO_BASE)/build/rules/exec diff --git a/Zip/testsuite/TestSuite.vmsbuild b/Zip/testsuite/TestSuite.vmsbuild new file mode 100644 index 000000000..14c917e5b --- /dev/null +++ b/Zip/testsuite/TestSuite.vmsbuild @@ -0,0 +1,9 @@ +# +# TestSuite.vmsbuild +# +# $Id: //poco/1.3/Zip/testsuite/TestSuite.vmsbuild#1 $ +# +EXE=TestRunner +ZipTestSuite +Driver + diff --git a/Zip/testsuite/TestSuite_VS71.vcproj b/Zip/testsuite/TestSuite_VS71.vcproj new file mode 100644 index 000000000..16a4324f3 --- /dev/null +++ b/Zip/testsuite/TestSuite_VS71.vcproj @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Zip/testsuite/TestSuite_VS80.vcproj b/Zip/testsuite/TestSuite_VS80.vcproj new file mode 100644 index 000000000..383564443 --- /dev/null +++ b/Zip/testsuite/TestSuite_VS80.vcproj @@ -0,0 +1,267 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Zip/testsuite/TestSuite_vs90.vcproj b/Zip/testsuite/TestSuite_vs90.vcproj new file mode 100644 index 000000000..1cddf3510 --- /dev/null +++ b/Zip/testsuite/TestSuite_vs90.vcproj @@ -0,0 +1,267 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Zip/testsuite/data/data.zip b/Zip/testsuite/data/data.zip new file mode 100644 index 000000000..cedf96dcb Binary files /dev/null and b/Zip/testsuite/data/data.zip differ diff --git a/Zip/testsuite/data/doc.zip b/Zip/testsuite/data/doc.zip new file mode 100644 index 000000000..4a853199a Binary files /dev/null and b/Zip/testsuite/data/doc.zip differ diff --git a/Zip/testsuite/data/java.zip b/Zip/testsuite/data/java.zip new file mode 100644 index 000000000..80ebc780d Binary files /dev/null and b/Zip/testsuite/data/java.zip differ diff --git a/Zip/testsuite/data/test.zip b/Zip/testsuite/data/test.zip new file mode 100644 index 000000000..cedf96dcb Binary files /dev/null and b/Zip/testsuite/data/test.zip differ diff --git a/Zip/testsuite/src/CompressTest.cpp b/Zip/testsuite/src/CompressTest.cpp new file mode 100644 index 000000000..9ce4162e7 --- /dev/null +++ b/Zip/testsuite/src/CompressTest.cpp @@ -0,0 +1,165 @@ +// +// CompressTest.cpp +// +// $Id: //poco/1.3/Zip/testsuite/src/CompressTest.cpp#5 $ +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "CompressTest.h" +#include "ZipTest.h" +#include "Poco/Zip/Compress.h" +#include "Poco/Zip/ZipManipulator.h" +#include "Poco/File.h" +#include "Poco/FileStream.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include + + +using namespace Poco::Zip; + + +CompressTest::CompressTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +CompressTest::~CompressTest() +{ +} + + +void CompressTest::testSingleFile() +{ + std::ofstream out("appinf.zip", std::ios::binary); + Poco::Path theFile(ZipTest::getTestFile("test.zip")); + Compress c(out, true); + c.addFile(theFile, theFile.getFileName()); + ZipArchive a(c.close()); +} + + +void CompressTest::testDirectory() +{ + std::ofstream out("pocobin.zip", std::ios::binary); + Poco::File aFile("some/"); + if (aFile.exists()) + aFile.remove(true); + Poco::File aDir("some/recursive/dir/"); + aDir.createDirectories(); + Poco::File aDir2("some/other/recursive/dir/"); + aDir2.createDirectories(); + Poco::File aF("some/recursive/dir/test.file"); + aF.createFile(); + Poco::FileOutputStream fos(aF.path()); + fos << "just some test data"; + fos.close(); + + Poco::Path theFile(aFile.path()); + theFile.makeDirectory(); + Compress c(out, true); + c.addRecursive(theFile, ZipCommon::CL_MAXIMUM, false, theFile); + ZipArchive a(c.close()); +} + + +void CompressTest::testManipulator() +{ + { + std::ofstream out("appinf.zip", std::ios::binary); + Poco::Path theFile(ZipTest::getTestFile("test.zip")); + Compress c(out, true); + c.addFile(theFile, theFile.getFileName()); + ZipArchive a(c.close()); + } + ZipManipulator zm("appinf.zip", true); + zm.renameFile("test.zip", "renamedtest.zip"); + zm.addFile("doc/othertest.zip", ZipTest::getTestFile("test.zip")); + ZipArchive archive=zm.commit(); + assert (archive.findHeader("doc/othertest.zip") != archive.headerEnd()); +} + + +void CompressTest::testManipulatorDel() +{ + { + std::ofstream out("appinf.zip", std::ios::binary); + Poco::Path theFile(ZipTest::getTestFile("test.zip")); + Compress c(out, true); + c.addFile(theFile, theFile.getFileName()); + ZipArchive a(c.close()); + } + ZipManipulator zm("appinf.zip", true); + zm.deleteFile("test.zip"); + zm.addFile("doc/data.zip", ZipTest::getTestFile("data.zip")); + ZipArchive archive=zm.commit(); + assert (archive.findHeader("test.zip") == archive.headerEnd()); + assert (archive.findHeader("doc/data.zip") != archive.headerEnd()); +} + + +void CompressTest::testManipulatorReplace() +{ + { + std::ofstream out("appinf.zip", std::ios::binary); + Poco::Path theFile(ZipTest::getTestFile("test.zip")); + Compress c(out, true); + c.addFile(theFile, theFile.getFileName()); + ZipArchive a(c.close()); + } + ZipManipulator zm("appinf.zip", true); + zm.replaceFile("test.zip", ZipTest::getTestFile("doc.zip")); + + ZipArchive archive=zm.commit(); + assert (archive.findHeader("test.zip") != archive.headerEnd()); + assert (archive.findHeader("doc.zip") == archive.headerEnd()); +} + + +void CompressTest::setUp() +{ +} + + +void CompressTest::tearDown() +{ +} + + +CppUnit::Test* CompressTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("CompressTest"); + + CppUnit_addTest(pSuite, CompressTest, testSingleFile); + CppUnit_addTest(pSuite, CompressTest, testDirectory); + CppUnit_addTest(pSuite, CompressTest, testManipulator); + CppUnit_addTest(pSuite, CompressTest, testManipulatorDel); + CppUnit_addTest(pSuite, CompressTest, testManipulatorReplace); + + return pSuite; +} diff --git a/Zip/testsuite/src/CompressTest.h b/Zip/testsuite/src/CompressTest.h new file mode 100644 index 000000000..a04afe67d --- /dev/null +++ b/Zip/testsuite/src/CompressTest.h @@ -0,0 +1,64 @@ +// +// CompressTest.h +// +// $Id: //poco/1.3/Zip/testsuite/src/CompressTest.h#4 $ +// +// Definition of the CompressTest class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef CompressTest_INCLUDED +#define CompressTest_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "CppUnit/TestCase.h" + + +class CompressTest: public CppUnit::TestCase +{ +public: + CompressTest(const std::string& name); + ~CompressTest(); + + void testSingleFile(); + void testDirectory(); + void testManipulator(); + void testManipulatorDel(); + void testManipulatorReplace(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // CompressTest_INCLUDED diff --git a/Zip/testsuite/src/Driver.cpp b/Zip/testsuite/src/Driver.cpp new file mode 100644 index 000000000..4db1715d7 --- /dev/null +++ b/Zip/testsuite/src/Driver.cpp @@ -0,0 +1,39 @@ +// +// Driver.cpp +// +// $Id: //poco/1.3/Zip/testsuite/src/Driver.cpp#2 $ +// +// Console-based test driver for Poco Zip. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "CppUnit/TestRunner.h" +#include "ZipTestSuite.h" + + +CppUnitMain(ZipTestSuite) diff --git a/Zip/testsuite/src/PartialStreamTest.cpp b/Zip/testsuite/src/PartialStreamTest.cpp new file mode 100644 index 000000000..b8ba66b3a --- /dev/null +++ b/Zip/testsuite/src/PartialStreamTest.cpp @@ -0,0 +1,139 @@ +// +// PartialStreamTest.cpp +// +// $Id: //poco/1.3/Zip/testsuite/src/PartialStreamTest.cpp#3 $ +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "PartialStreamTest.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include "Poco/Zip/PartialStream.h" +#include + + +using namespace Poco::Zip; + + +PartialStreamTest::PartialStreamTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +PartialStreamTest::~PartialStreamTest() +{ +} + + +void PartialStreamTest::testReading() +{ + std::string message("some dummy message !"); + std::string prefix("pre "); + std::string postfix(" post"); + std::string result(prefix+message+postfix); + std::istringstream istr(message); + PartialInputStream in(istr, 0, static_cast(message.length()), true, prefix, postfix); + char buf[124]; + in.read(buf, 124); + std::string res(buf, in.gcount()); + poco_assert (res == result); +} + + +void PartialStreamTest::testWriting() +{ + std::string prefix("X"); + std::string message("some test message"); + std::string postfix("YYY"); + std::string result(prefix+message+postfix); + std::ostringstream ostr; + PartialOutputStream out(ostr, prefix.size(), postfix.size()); + out.write(result.c_str(), static_cast(result.length())); + poco_assert (out.good()); + out.close(); + std::string res (ostr.str()); + poco_assert (out.bytesWritten() == message.size()); + poco_assert (message == res); +} + + +void PartialStreamTest::testWritingZero() +{ + std::string prefix("X"); + std::string message; + std::string postfix("YYY"); + std::string result(prefix+message+postfix); + std::ostringstream ostr; + PartialOutputStream out(ostr, prefix.size(), postfix.size()); + out.write(result.c_str(), static_cast(result.length())); + poco_assert (out.good()); + out.close(); + std::string res (ostr.str()); + poco_assert (out.bytesWritten() == message.size()); + poco_assert (message == res); +} + + +void PartialStreamTest::testWritingOne() +{ + std::string prefix("X"); + std::string message("a"); + std::string postfix("YYY"); + std::string result(prefix+message+postfix); + std::ostringstream ostr; + PartialOutputStream out(ostr, prefix.size(), postfix.size()); + out.write(result.c_str(), static_cast(result.length())); + poco_assert (out.good()); + out.close(); + std::string res (ostr.str()); + poco_assert (out.bytesWritten() == message.size()); + poco_assert (message == res); +} + + +void PartialStreamTest::setUp() +{ +} + + +void PartialStreamTest::tearDown() +{ +} + + +CppUnit::Test* PartialStreamTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("PartialStreamTest"); + + CppUnit_addTest(pSuite, PartialStreamTest, testReading); + CppUnit_addTest(pSuite, PartialStreamTest, testWriting); + CppUnit_addTest(pSuite, PartialStreamTest, testWritingZero); + CppUnit_addTest(pSuite, PartialStreamTest, testWritingOne); + + return pSuite; +} diff --git a/Zip/testsuite/src/PartialStreamTest.h b/Zip/testsuite/src/PartialStreamTest.h new file mode 100644 index 000000000..f33f9f2f9 --- /dev/null +++ b/Zip/testsuite/src/PartialStreamTest.h @@ -0,0 +1,63 @@ +// +// PartialStreamTest.h +// +// $Id: //poco/1.3/Zip/testsuite/src/PartialStreamTest.h#3 $ +// +// Definition of the PartialStreamTest class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef PartialStreamTest_INCLUDED +#define PartialStreamTest_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "CppUnit/TestCase.h" + + +class PartialStreamTest: public CppUnit::TestCase +{ +public: + PartialStreamTest(const std::string& name); + ~PartialStreamTest(); + + void testReading(); + void testWriting(); + void testWritingZero(); + void testWritingOne(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + +private: +}; + + +#endif // PartialStreamTest_INCLUDED diff --git a/Zip/testsuite/src/WinDriver.cpp b/Zip/testsuite/src/WinDriver.cpp new file mode 100644 index 000000000..918219edc --- /dev/null +++ b/Zip/testsuite/src/WinDriver.cpp @@ -0,0 +1,50 @@ +// +// WinDriver.cpp +// +// $Id: //poco/1.3/Zip/testsuite/src/WinDriver.cpp#2 $ +// +// Windows test driver for Poco Zip. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "WinTestRunner/WinTestRunner.h" +#include "ZipTestSuite.h" + + +class TestDriver: public CppUnit::WinTestRunnerApp +{ + void TestMain() + { + CppUnit::WinTestRunner runner; + runner.addTest(ZipTestSuite::suite()); + runner.run(); + } +}; + + +TestDriver theDriver; diff --git a/Zip/testsuite/src/ZipTest.cpp b/Zip/testsuite/src/ZipTest.cpp new file mode 100644 index 000000000..e5878ef98 --- /dev/null +++ b/Zip/testsuite/src/ZipTest.cpp @@ -0,0 +1,286 @@ +// +// ZipTest.cpp +// +// $Id: //poco/1.3/Zip/testsuite/src/ZipTest.cpp#6 $ +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ZipTest.h" +#include "Poco/Zip/SkipCallback.h" +#include "Poco/Zip/ZipLocalFileHeader.h" +#include "Poco/Zip/ZipArchive.h" +#include "Poco/Zip/ZipStream.h" +#include "Poco/Zip/Decompress.h" +#include "Poco/StreamCopier.h" +#include "Poco/File.h" +#include "Poco/URI.h" +#include "Poco/Path.h" +#include "Poco/Delegate.h" +#include "Poco/Net/HTTPClientSession.h" +#include "Poco/Net/HTTPRequest.h" +#include "Poco/Net/HTTPResponse.h" +#include "Poco/Net/HTTPServer.h" +#include "Poco/Net/HTTPServerParams.h" +#include "Poco/Net/AbstractHTTPRequestHandler.h" +#include "Poco/Net/HTTPRequestHandlerFactory.h" +#include "Poco/Net/HTTPServerRequest.h" +#include "Poco/Net/HTTPServerResponse.h" +#include "Poco/Net/ServerSocket.h" +#include "Poco/StreamCopier.h" +#include "CppUnit/TestCaller.h" +#include "CppUnit/TestSuite.h" +#include +#include + + +using namespace Poco::Zip; +using namespace Poco::Net; + + + +namespace +{ + class ZipFileRequestHandler: public HTTPRequestHandler + { + public: + ZipFileRequestHandler() + { + } + + void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) + { + response.setChunkedTransferEncoding(true); + std::string testFile = ZipTest::getTestFile("test.zip"); + std::ifstream inp(testFile.c_str(), std::ios::binary); + poco_assert (inp); + + response.setContentType("application/zip"); + + std::ostream& ostr = response.send(); + Poco::StreamCopier::copyStream(inp, ostr); + } + }; + + class RequestHandlerFactory: public HTTPRequestHandlerFactory + { + public: + HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request) + { + if (request.getURI() == "/test.zip") + return new ZipFileRequestHandler; + else + return 0; + } + }; +} + +ZipTest::ZipTest(const std::string& name): CppUnit::TestCase(name) +{ +} + + +ZipTest::~ZipTest() +{ +} + + +void ZipTest::testSkipSingleFile() +{ + std::string testFile = getTestFile("test.zip"); + std::ifstream inp(testFile.c_str(), std::ios::binary); + poco_assert (inp); + SkipCallback skip; + ZipLocalFileHeader hdr(inp, false, skip); + poco_assert (ZipCommon::HS_FAT == hdr.getHostSystem()); + int major = hdr.getMajorVersionNumber(); + int minor = hdr.getMinorVersionNumber(); + poco_assert (major <= 2); + std::size_t hdrSize = hdr.getHeaderSize(); + poco_assert (hdrSize > 30); + ZipCommon::CompressionMethod cm = hdr.getCompressionMethod(); + poco_assert (!hdr.isEncrypted()); + Poco::DateTime aDate = hdr.lastModifiedAt(); + Poco::UInt32 cS = hdr.getCompressedSize(); + Poco::UInt32 uS = hdr.getUncompressedSize(); + const std::string& fileName = hdr.getFileName(); +} + + +void ZipTest::testDecompressSingleFile() +{ + std::string testFile = getTestFile("test.zip"); + std::ifstream inp(testFile.c_str(), std::ios::binary); + poco_assert (inp); + ZipArchive arch(inp); + ZipArchive::FileHeaders::const_iterator it = arch.findHeader("Zip_VS71.vcproj"); + poco_assert (it != arch.headerEnd()); + ZipInputStream zipin (inp, it->second); + std::ostringstream out(std::ios::binary); + Poco::StreamCopier::copyStream(zipin, out); + poco_assert(!out.str().empty()); +} + + +void ZipTest::testCrcAndSizeAfterData() +{ + std::string testFile = getTestFile("java.zip"); + std::ifstream inp(testFile.c_str(), std::ios::binary); + poco_assert (inp); + Decompress dec(inp, Poco::Path()); + dec.EError += Poco::Delegate >(this, &ZipTest::onDecompressError); + dec.decompressAllFiles(); + dec.EError -= Poco::Delegate >(this, &ZipTest::onDecompressError); + poco_assert (_errCnt == 0); + poco_assert (!dec.mapping().empty()); +} + + +void ZipTest::testCrcAndSizeAfterDataWithArchive() +{ + std::string testFile = getTestFile("java.zip"); + std::ifstream inp(testFile.c_str(), std::ios::binary); + poco_assert (inp); + Poco::Zip::ZipArchive zip(inp); + inp.clear(); + inp.seekg(0); + Poco::Zip::ZipArchive::FileHeaders::const_iterator it = zip.headerBegin(); + for ( ; it!=zip.headerEnd(); ++it) + { + Poco::Zip::ZipInputStream zipis(inp,it->second); + Poco::Path path(it->second.getFileName()); + if (path.isFile()) + { + std::ofstream os("test.dat"); + Poco::StreamCopier::copyStream(zipis,os); + } + } +} + + +std::string ZipTest::getTestFile(const std::string& testFile) +{ + Poco::Path root; + root.makeAbsolute(); + Poco::Path result; + while (!Poco::Path::find(root.toString(), "data", result)) + { + root.makeParent(); + if (root.toString().empty() || root.toString() == "/") + throw Poco::FileNotFoundException("Didn't find data subdir"); + } + result.makeDirectory(); + result.setFileName(testFile); + Poco::File aFile(result.toString()); + if (!aFile.exists() || (aFile.exists() && !aFile.isFile())) + throw Poco::FileNotFoundException("Didn't find " + testFile); + + return result.toString(); +} + + +void ZipTest::testDecompress() +{ + std::string testFile = getTestFile("test.zip"); + std::ifstream inp(testFile.c_str(), std::ios::binary); + poco_assert (inp); + Decompress dec(inp, Poco::Path()); + dec.EError += Poco::Delegate >(this, &ZipTest::onDecompressError); + dec.decompressAllFiles(); + dec.EError -= Poco::Delegate >(this, &ZipTest::onDecompressError); + poco_assert (_errCnt == 0); + poco_assert (!dec.mapping().empty()); +} + + +void ZipTest::testDecompressFlat() +{ + std::string testFile = getTestFile("test.zip"); + std::ifstream inp(testFile.c_str(), std::ios::binary); + poco_assert (inp); + Decompress dec(inp, Poco::Path(), true); + dec.EError += Poco::Delegate >(this, &ZipTest::onDecompressError); + dec.decompressAllFiles(); + dec.EError -= Poco::Delegate >(this, &ZipTest::onDecompressError); + poco_assert (_errCnt == 0); + poco_assert (!dec.mapping().empty()); +} + + +void ZipTest::decompressDirectlyFromNet() +{ + ServerSocket svs(22222); + HTTPServerParams* pParams = new HTTPServerParams; + pParams->setKeepAlive(true); + HTTPServer srv(new RequestHandlerFactory, svs, pParams); + srv.start(); + Poco::URI uri("http://localhost:22222/test.zip"); + + HTTPClientSession session("localhost", 22222); + HTTPRequest req(HTTPRequest::HTTP_GET, "/test.zip", HTTPMessage::HTTP_1_1); + session.sendRequest(req); + HTTPResponse res; + std::istream& rs = session.receiveResponse(res); + Decompress dec(rs, Poco::Path()); + dec.EError += Poco::Delegate >(this, &ZipTest::onDecompressError); + dec.decompressAllFiles(); + dec.EError -= Poco::Delegate >(this, &ZipTest::onDecompressError); + poco_assert (_errCnt == 0); + poco_assert (!dec.mapping().empty()); +} + + +void ZipTest::onDecompressError(const void* pSender, std::pair& info) +{ + ++_errCnt; +} + + +void ZipTest::setUp() +{ + _errCnt = 0; +} + + +void ZipTest::tearDown() +{ +} + + +CppUnit::Test* ZipTest::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ZipTest"); + + CppUnit_addTest(pSuite, ZipTest, testSkipSingleFile); + CppUnit_addTest(pSuite, ZipTest, testDecompressSingleFile); + CppUnit_addTest(pSuite, ZipTest, testDecompress); + CppUnit_addTest(pSuite, ZipTest, testDecompressFlat); + CppUnit_addTest(pSuite, ZipTest, decompressDirectlyFromNet); + CppUnit_addTest(pSuite, ZipTest, testCrcAndSizeAfterData); + CppUnit_addTest(pSuite, ZipTest, testCrcAndSizeAfterDataWithArchive); + return pSuite; +} diff --git a/Zip/testsuite/src/ZipTest.h b/Zip/testsuite/src/ZipTest.h new file mode 100644 index 000000000..6e9e8347c --- /dev/null +++ b/Zip/testsuite/src/ZipTest.h @@ -0,0 +1,73 @@ +// +// ZipTest.h +// +// $Id: //poco/1.3/Zip/testsuite/src/ZipTest.h#5 $ +// +// Definition of the ZipTest class. +// +// Copyright (c) 2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ZipTest_INCLUDED +#define ZipTest_INCLUDED + + +#include "Poco/Zip/Zip.h" +#include "Poco/Zip/ZipLocalFileHeader.h" +#include "CppUnit/TestCase.h" + + +class ZipTest: public CppUnit::TestCase +{ +public: + ZipTest(const std::string& name); + ~ZipTest(); + + void testSkipSingleFile(); + void testDecompressSingleFile(); + void testDecompress(); + void decompressDirectlyFromNet(); + void testCrcAndSizeAfterData(); + void testCrcAndSizeAfterDataWithArchive(); + + void testDecompressFlat(); + + void setUp(); + void tearDown(); + + static CppUnit::Test* suite(); + + static std::string getTestFile(const std::string& testFile); + +private: + void onDecompressError(const void* pSender, std::pair& info); + + int _errCnt; +}; + + +#endif // ZipTest_INCLUDED diff --git a/Zip/testsuite/src/ZipTestSuite.cpp b/Zip/testsuite/src/ZipTestSuite.cpp new file mode 100644 index 000000000..d8027c1ac --- /dev/null +++ b/Zip/testsuite/src/ZipTestSuite.cpp @@ -0,0 +1,48 @@ +// +// ZipTestSuite.cpp +// +// $Id: //poco/1.3/Zip/testsuite/src/ZipTestSuite.cpp#1 $ +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#include "ZipTestSuite.h" +#include "ZipTest.h" +#include "PartialStreamTest.h" +#include "CompressTest.h" + + +CppUnit::Test* ZipTestSuite::suite() +{ + CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ZipTestSuite"); + + pSuite->addTest(ZipTest::suite()); + pSuite->addTest(PartialStreamTest::suite()); + pSuite->addTest(CompressTest::suite()); + + return pSuite; +} diff --git a/Zip/testsuite/src/ZipTestSuite.h b/Zip/testsuite/src/ZipTestSuite.h new file mode 100644 index 000000000..e9bfbfe47 --- /dev/null +++ b/Zip/testsuite/src/ZipTestSuite.h @@ -0,0 +1,49 @@ +// +// ZipTestSuite.h +// +// $Id: //poco/1.3/Zip/testsuite/src/ZipTestSuite.h#1 $ +// +// Definition of the ZipTestSuite class. +// +// Copyright (c) 2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + + +#ifndef ZipTestSuite_INCLUDED +#define ZipTestSuite_INCLUDED + + +#include "CppUnit/TestSuite.h" + + +class ZipTestSuite +{ +public: + static CppUnit::Test* suite(); +}; + + +#endif // ZipTestSuite_INCLUDED