pkzip.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #if !defined(INCLUDED_PKZIP_H)
00023 #define INCLUDED_PKZIP_H
00024
00025 #include "bytestreamutils.h"
00026 #include "idatastream.h"
00027 #include <algorithm>
00028
00029 class zip_magic
00030 {
00031 public:
00032 bool operator== (const zip_magic& other) const
00033 {
00034 return m_value[0] == other.m_value[0] && m_value[1] == other.m_value[1] && m_value[2] == other.m_value[2]
00035 && m_value[3] == other.m_value[3];
00036 }
00037 bool operator!= (const zip_magic& other) const
00038 {
00039 return !(*this == other);
00040 }
00041 char m_value[4];
00042 };
00043
00044 inline void istream_read_zip_magic (InputStream& istream, zip_magic& magic)
00045 {
00046 istream.read(reinterpret_cast<InputStream::byte_type*> (magic.m_value), 4);
00047 }
00048
00049 struct zip_version
00050 {
00051 char version;
00052 char ostype;
00053 };
00054
00055 inline void istream_read_zip_version (InputStream& istream, zip_version& version)
00056 {
00057 version.version = istream_read_byte(istream);
00058 version.ostype = istream_read_byte(istream);
00059 }
00060
00061 struct zip_dostime
00062 {
00063 unsigned short time;
00064 unsigned short date;
00065 };
00066
00067 inline void istream_read_zip_dostime (InputStream& istream, zip_dostime& dostime)
00068 {
00069 dostime.time = istream_read_int16_le(istream);
00070 dostime.date = istream_read_int16_le(istream);
00071 }
00072
00073 const zip_magic zip_file_header_magic = { { 'P', 'K', 0x03, 0x04 } };
00074
00075
00076 struct zip_file_header
00077 {
00078 zip_magic z_magic;
00079 zip_version z_extract;
00080 unsigned short z_flags;
00081 unsigned short z_compr;
00082 zip_dostime z_dostime;
00083 unsigned int z_crc32;
00084 unsigned int z_csize;
00085 unsigned int z_usize;
00086 unsigned short z_namlen;
00087 unsigned short z_extras;
00088
00089
00090 };
00091
00092 inline void istream_read_zip_file_header (SeekableInputStream& istream, zip_file_header& file_header)
00093 {
00094 istream_read_zip_magic(istream, file_header.z_magic);
00095 istream_read_zip_version(istream, file_header.z_extract);
00096 file_header.z_flags = istream_read_uint16_le(istream);
00097 file_header.z_compr = istream_read_uint16_le(istream);
00098 istream_read_zip_dostime(istream, file_header.z_dostime);
00099 file_header.z_crc32 = istream_read_uint32_le(istream);
00100 file_header.z_csize = istream_read_uint32_le(istream);
00101 file_header.z_usize = istream_read_uint32_le(istream);
00102 file_header.z_namlen = istream_read_uint16_le(istream);
00103 file_header.z_extras = istream_read_uint16_le(istream);
00104 istream.seek(file_header.z_namlen + file_header.z_extras, SeekableInputStream::cur);
00105 }
00106 ;
00107
00108
00109
00110
00111
00112
00113 const zip_magic zip_file_trailer_magic = { { 'P', 'K', 0x07, 0x08 } };
00114
00115 struct zip_file_trailer
00116 {
00117 zip_magic z_magic;
00118 unsigned int z_crc32;
00119 unsigned int z_csize;
00120 unsigned int z_usize;
00121 };
00122
00123 inline void istream_read_zip_file_trailer (InputStream& istream, zip_file_trailer& file_trailer)
00124 {
00125 istream_read_zip_magic(istream, file_trailer.z_magic);
00126 file_trailer.z_crc32 = istream_read_uint32_le(istream);
00127 file_trailer.z_csize = istream_read_uint32_le(istream);
00128 file_trailer.z_usize = istream_read_uint32_le(istream);
00129 }
00130 ;
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 const zip_magic zip_root_dirent_magic = { { 'P', 'K', 0x01, 0x02 } };
00141
00142 struct zip_root_dirent
00143 {
00144 zip_magic z_magic;
00145 zip_version z_encoder;
00146 zip_version z_extract;
00147 unsigned short z_flags;
00148 unsigned short z_compr;
00149 zip_dostime z_dostime;
00150 unsigned int z_crc32;
00151 unsigned int z_csize;
00152 unsigned int z_usize;
00153 unsigned short z_namlen;
00154 unsigned short z_extras;
00155 unsigned short z_comment;
00156 unsigned short z_diskstart;
00157 unsigned short z_filetype;
00158 unsigned int z_filemode;
00159 unsigned int z_off;
00160
00161
00162
00163 };
00164
00165 inline void istream_read_zip_root_dirent (SeekableInputStream& istream, zip_root_dirent& root_dirent)
00166 {
00167 istream_read_zip_magic(istream, root_dirent.z_magic);
00168 istream_read_zip_version(istream, root_dirent.z_encoder);
00169 istream_read_zip_version(istream, root_dirent.z_extract);
00170 root_dirent.z_flags = istream_read_uint16_le(istream);
00171 root_dirent.z_compr = istream_read_uint16_le(istream);
00172 istream_read_zip_dostime(istream, root_dirent.z_dostime);
00173 root_dirent.z_crc32 = istream_read_uint32_le(istream);
00174 root_dirent.z_csize = istream_read_uint32_le(istream);
00175 root_dirent.z_usize = istream_read_uint32_le(istream);
00176 root_dirent.z_namlen = istream_read_uint16_le(istream);
00177 root_dirent.z_extras = istream_read_uint16_le(istream);
00178 root_dirent.z_comment = istream_read_uint16_le(istream);
00179 root_dirent.z_diskstart = istream_read_uint16_le(istream);
00180 root_dirent.z_filetype = istream_read_uint16_le(istream);
00181 root_dirent.z_filemode = istream_read_uint32_le(istream);
00182 root_dirent.z_off = istream_read_uint32_le(istream);
00183 istream.seek(root_dirent.z_namlen + root_dirent.z_extras + root_dirent.z_comment, SeekableInputStream::cur);
00184 }
00185
00186
00187 const zip_magic zip_disk_trailer_magic = { { 'P', 'K', 0x05, 0x06 } };
00188 const unsigned int disk_trailer_length = 22;
00189 struct zip_disk_trailer
00190 {
00191 zip_magic z_magic;
00192 unsigned short z_disk;
00193 unsigned short z_finaldisk;
00194 unsigned short z_entries;
00195 unsigned short z_finalentries;
00196 unsigned int z_rootsize;
00197 unsigned int z_rootseek;
00198
00199 unsigned short z_comment;
00200
00201 };
00202
00203 inline void istream_read_zip_disk_trailer (SeekableInputStream& istream, zip_disk_trailer& disk_trailer)
00204 {
00205 istream_read_zip_magic(istream, disk_trailer.z_magic);
00206 disk_trailer.z_disk = istream_read_uint16_le(istream);
00207 disk_trailer.z_finaldisk = istream_read_uint16_le(istream);
00208 disk_trailer.z_entries = istream_read_uint16_le(istream);
00209 disk_trailer.z_finalentries = istream_read_uint16_le(istream);
00210 disk_trailer.z_rootsize = istream_read_uint32_le(istream);
00211 disk_trailer.z_rootseek = istream_read_uint32_le(istream);
00212 disk_trailer.z_comment = istream_read_uint16_le(istream);
00213 istream.seek(disk_trailer.z_comment, SeekableInputStream::cur);
00214 }
00215
00216 inline SeekableStream::position_type pkzip_find_disk_trailer (SeekableInputStream& istream)
00217 {
00218 istream.seek(0, SeekableInputStream::end);
00219 SeekableStream::position_type start_position = istream.tell();
00220 if (start_position < disk_trailer_length)
00221 return 0;
00222 start_position -= disk_trailer_length;
00223
00224 zip_magic magic;
00225 istream.seek(start_position);
00226 istream_read_zip_magic(istream, magic);
00227
00228 if (magic == zip_disk_trailer_magic)
00229 return start_position;
00230 else {
00231 const SeekableStream::position_type max_comment = 0x10000;
00232 const SeekableStream::position_type bufshift = 6;
00233 const SeekableStream::position_type bufsize = max_comment >> bufshift;
00234 unsigned char buffer[bufsize];
00235
00236 SeekableStream::position_type search_end = (max_comment < start_position) ? start_position - max_comment : 0;
00237 SeekableStream::position_type position = start_position;
00238 while (position != search_end) {
00239 StreamBase::size_type to_read = std::min(bufsize, position - search_end);
00240 position -= to_read;
00241
00242 istream.seek(position);
00243 StreamBase::size_type size = istream.read(buffer, to_read);
00244
00245 unsigned char* p = buffer + size;
00246 while (p != buffer) {
00247 --p;
00248 magic.m_value[3] = magic.m_value[2];
00249 magic.m_value[2] = magic.m_value[1];
00250 magic.m_value[1] = magic.m_value[0];
00251 magic.m_value[0] = *p;
00252 if (magic == zip_disk_trailer_magic) {
00253 return position + (p - buffer);
00254 }
00255 }
00256 }
00257 return 0;
00258 }
00259 }
00260
00261 #endif