PixelLightAPI
.
|
00001 /*********************************************************\ 00002 * File: ZipHandle.h * 00003 * 00004 * Copyright (C) 2002-2012 The PixelLight Team (http://www.pixellight.org/) 00005 * 00006 * This file is part of PixelLight. 00007 * 00008 * PixelLight is free software: you can redistribute it and/or modify 00009 * it under the terms of the GNU Lesser General Public License as published by 00010 * the Free Software Foundation, either version 3 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * PixelLight is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public License 00019 * along with PixelLight. If not, see <http://www.gnu.org/licenses/>. 00020 \*********************************************************/ 00021 00022 00023 #ifndef __PLCORE_ZIPHANDLE_H__ 00024 #define __PLCORE_ZIPHANDLE_H__ 00025 #pragma once 00026 00027 00028 //[-------------------------------------------------------] 00029 //[ Includes ] 00030 //[-------------------------------------------------------] 00031 #include "PLCore/File/File.h" 00032 #include "PLCore/Tools/Time.h" 00033 00034 00035 //[-------------------------------------------------------] 00036 //[ Forward declarations ] 00037 //[-------------------------------------------------------] 00038 struct z_stream_s; 00039 typedef z_stream_s z_stream; 00040 00041 00042 //[-------------------------------------------------------] 00043 //[ Namespace ] 00044 //[-------------------------------------------------------] 00045 namespace PLCore { 00046 00047 00048 //[-------------------------------------------------------] 00049 //[ Classes ] 00050 //[-------------------------------------------------------] 00051 /** 00052 * @brief 00053 * This class represents a handle for working on a ZIP-file 00054 * 00055 * @remarks 00056 * It can be used to navigate inside the ZIP-file and read data from it, but you don't need 00057 * to use it directly, as ZIP-files can be directly accessed through the File/Directory classes 00058 * (e.g.: File("C:\\test.zip\\readme.txt") to extract a file from a ZIP-file) 00059 */ 00060 class ZipHandle { 00061 00062 00063 //[-------------------------------------------------------] 00064 //[ ZIP file entry ] 00065 //[-------------------------------------------------------] 00066 public: 00067 /** 00068 * @brief 00069 * Represents an entry (file or directory) in a ZIP-file 00070 */ 00071 class ZipEntry { 00072 00073 00074 //[-------------------------------------------------------] 00075 //[ Public functions ] 00076 //[-------------------------------------------------------] 00077 public: 00078 /** 00079 * @brief 00080 * Constructor 00081 */ 00082 PLCORE_API ZipEntry(); 00083 00084 /** 00085 * @brief 00086 * Copy constructor 00087 * 00088 * @param[in] cZipEntry 00089 * ZipEntry to copy 00090 */ 00091 PLCORE_API ZipEntry(const ZipEntry &cZipEntry); 00092 00093 /** 00094 * @brief 00095 * Destructor 00096 */ 00097 PLCORE_API ~ZipEntry(); 00098 00099 /** 00100 * @brief 00101 * Assignment operator 00102 * 00103 * @param[in] cZipEntry 00104 * ZipEntry to copy 00105 * 00106 * @return 00107 * Reference to this instance 00108 */ 00109 PLCORE_API ZipEntry &operator =(const ZipEntry &cZipEntry); 00110 00111 /** 00112 * @brief 00113 * Clear entry 00114 */ 00115 PLCORE_API void Clear(); 00116 00117 /** 00118 * @brief 00119 * Allocate memory for extra-field 00120 * 00121 * @param[in] nSize 00122 * Size of extra-field 00123 */ 00124 PLCORE_API void AllocateExtraField(uint16 nSize); 00125 00126 00127 //[-------------------------------------------------------] 00128 //[ Public fields ] 00129 //[-------------------------------------------------------] 00130 public: 00131 bool m_bValid; /**< Is the current entry valid? */ 00132 String m_sFilename; /**< Filename */ 00133 String m_sComment; /**< File comment */ 00134 uint16 m_nVersion; /**< Version made by 2 bytes */ 00135 uint16 m_nVersionNeeded; /**< Version needed to extract 2 bytes */ 00136 uint16 m_nFlags; /**< General purpose bit flag 2 bytes */ 00137 uint16 m_nCompressionMethod; /**< Compression method 2 bytes */ 00138 uint32 m_nDOSDate; /**< Last mod file date in DOS fmt 4 bytes */ 00139 uint32 m_nCRC; /**< Crc-32 4 bytes */ 00140 uint32 m_nCompressedSize; /**< Compressed size 4 bytes */ 00141 uint32 m_nUncompressedSize; /**< Uncompressed size 4 bytes */ 00142 uint16 m_nSizeFilename; /**< Filename length 2 bytes */ 00143 uint16 m_nSizeFileExtra; /**< Extra field length 2 bytes */ 00144 uint16 m_nSizeFileComment; /**< File comment length 2 bytes */ 00145 uint16 m_nDiskNumStart; /**< Disk number start 2 bytes */ 00146 uint16 m_nInternalAttr; /**< Internal file attributes 2 bytes */ 00147 uint32 m_nExternalAttr; /**< External file attributes 4 bytes */ 00148 uint32 m_nOffsetCurFile; /**< Relative offset of local header 4 bytes */ 00149 Time m_cTime; /**< Time of the current file */ 00150 uint8 *m_pExtraField; /**< Extra data, can be a null pointer */ 00151 00152 00153 }; 00154 00155 00156 //[-------------------------------------------------------] 00157 //[ Public functions ] 00158 //[-------------------------------------------------------] 00159 public: 00160 //[-------------------------------------------------------] 00161 //[ General ] 00162 //[-------------------------------------------------------] 00163 /** 00164 * @brief 00165 * Constructor 00166 */ 00167 PLCORE_API ZipHandle(); 00168 00169 /** 00170 * @brief 00171 * Destructor 00172 */ 00173 PLCORE_API ~ZipHandle(); 00174 00175 /** 00176 * @brief 00177 * Check if the ZIP-file is open 00178 * 00179 * @return 00180 * 'true', if the file is valid, 'false' on error 00181 */ 00182 PLCORE_API bool IsOpen() const; 00183 00184 /** 00185 * @brief 00186 * Open the ZIP-file 00187 * 00188 * @param[in] sFilename 00189 * Filename of the ZIP-file 00190 * @param[in] sPassword 00191 * Password if the file is encrypted, else empty string 00192 * @param[in] bCaseSensitive 00193 * Shall the filenames be treated case sensitive? 00194 * @param[in] bMemBuf 00195 * Shall the ZIP-file be read into a memory-buffer? 00196 * @param[in] pAccess 00197 * Access information to pass through (can be a null pointer) 00198 * 00199 * @return 00200 * 'true', if the file could be opened, 'false' on error 00201 */ 00202 PLCORE_API bool Open(const String &sFilename, const String &sPassword, bool bCaseSensitive = true, bool bMemBuf = true, const FileAccess *pAccess = nullptr); 00203 00204 /** 00205 * @brief 00206 * Close the ZIP file 00207 * 00208 * @return 00209 * 'true', if the file could be closed, 'false' on error 00210 */ 00211 PLCORE_API bool Close(); 00212 00213 /** 00214 * @brief 00215 * Returns whether names treated case sensitive 00216 * 00217 * @return 00218 * 'true' if names treated case sensitive, else 'false' 00219 */ 00220 PLCORE_API bool IsCaseSensitive() const; 00221 00222 //[-------------------------------------------------------] 00223 //[ Enumerate entries in the ZIP-file ] 00224 //[-------------------------------------------------------] 00225 /** 00226 * @brief 00227 * Sets the pointer to the first entry in the ZIP-file 00228 * 00229 * @return 00230 * 'true', if the file is valid, 'false' on error 00231 */ 00232 PLCORE_API bool LocateFirstFile(); 00233 00234 /** 00235 * @brief 00236 * Sets the pointer to the next entry in the ZIP-file 00237 * 00238 * @return 00239 * 'true', if the file is valid, 'false' on error 00240 */ 00241 PLCORE_API bool LocateNextFile(); 00242 00243 /** 00244 * @brief 00245 * Sets the pointer to a specific entry in the ZIP-file 00246 * 00247 * @param[in] sFilename 00248 * Name of the file 00249 * 00250 * @return 00251 * 'true', if the file is valid, 'false' on error 00252 */ 00253 PLCORE_API bool LocateFile(const String &sFilename); 00254 00255 /** 00256 * @brief 00257 * Get information about the current entry in the ZIP-file 00258 * 00259 * @return 00260 * Current ZipEntry, could be invalid (see ZipEntry::IsValid) 00261 */ 00262 PLCORE_API const ZipEntry &GetCurrentFile() const; 00263 00264 //[-------------------------------------------------------] 00265 //[ Read file from ZIP-file ] 00266 //[-------------------------------------------------------] 00267 /** 00268 * @brief 00269 * Check if a file is currently open 00270 * 00271 * @return 00272 * 'true' if a file is currently open, else 'false' 00273 */ 00274 PLCORE_API bool IsFileOpen() const; 00275 00276 /** 00277 * @brief 00278 * Open the currently selected file 00279 * 00280 * @return 00281 * 'true' if all went fine, else 'false' 00282 */ 00283 PLCORE_API bool OpenFile(); 00284 00285 /** 00286 * @brief 00287 * Close file 00288 * 00289 * @return 00290 * 'true' if all went fine, else 'false' 00291 */ 00292 PLCORE_API bool CloseFile(); 00293 00294 /** 00295 * @brief 00296 * Reads data from the file 00297 * 00298 * @param[out] pBuffer 00299 * Buffer to store the data (MUST be valid and large enough!) 00300 * @param[in] nSize 00301 * Item size in bytes 00302 * @param[in] nCount 00303 * Number of items to read 00304 * 00305 * @return 00306 * Number of full read items, if != 'nCount' an error occurred 00307 */ 00308 PLCORE_API uint32 Read(void *pBuffer, uint32 nSize, uint32 nCount); 00309 00310 /** 00311 * @brief 00312 * Sets the starting position 00313 * 00314 * @param[in] nOffset 00315 * File offset in bytes relative to the given location 00316 * @param[in] nLocation 00317 * Location 00318 * 00319 * @return 00320 * 'true' if all went fine, else 'false' 00321 */ 00322 PLCORE_API bool Seek(int32 nOffset, File::ESeek nLocation); 00323 00324 /** 00325 * @brief 00326 * Returns the file position 00327 * 00328 * @return 00329 * Current position within the file, or < 0 on error 00330 */ 00331 PLCORE_API int32 Tell() const; 00332 00333 /** 00334 * @brief 00335 * Returns whether end of file has been reached 00336 * 00337 * @return 00338 * 'true', if the end of the file has been reached, else 'false' 00339 */ 00340 PLCORE_API bool IsEof() const; 00341 00342 /** 00343 * @brief 00344 * Gets the size of the current file's extra data field 00345 * 00346 * @return 00347 * Size of the local data field 00348 */ 00349 PLCORE_API uint32 GetLocalExtrafieldSize() const; 00350 00351 /** 00352 * @brief 00353 * Reads the extra data of the current file 00354 * 00355 * @param[out] pBuffer 00356 * Buffer to store the data (MUST valid and large enough!) 00357 * @param[in] nSize 00358 * Size of the buffer (MUST be valid!) 00359 * 00360 * @return 00361 * 'true', if all went fine, else 'false' 00362 */ 00363 PLCORE_API bool GetLocalExtrafield(void *pBuffer, uint32 nSize); 00364 00365 00366 //[-------------------------------------------------------] 00367 //[ Private functions ] 00368 //[-------------------------------------------------------] 00369 private: 00370 /** 00371 * @brief 00372 * Copy constructor 00373 * 00374 * @param[in] cSource 00375 * Source to copy from 00376 */ 00377 ZipHandle(const ZipHandle &cSource); 00378 00379 /** 00380 * @brief 00381 * Copy operator 00382 * 00383 * @param[in] cSource 00384 * Source to copy from 00385 * 00386 * @return 00387 * Reference to this instance 00388 */ 00389 ZipHandle &operator =(const ZipHandle &cSource); 00390 00391 /** 00392 * @brief 00393 * Opens the ZIP-file 00394 * 00395 * @return 00396 * 'true', if all went fine, else 'false' 00397 */ 00398 bool OpenZipFile(); 00399 00400 /** 00401 * @brief 00402 * Search for the central directory entry within the ZIP-file 00403 * 00404 * @return 00405 * Position of the central directory, 0 on error 00406 */ 00407 uint32 SearchCentralDir(); 00408 00409 /** 00410 * @brief 00411 * Reads the information about the current file 00412 * 00413 * @return 00414 * 'true', if the file is valid, 'false' on error 00415 */ 00416 bool ReadCurrentFileInfo(); 00417 00418 /** 00419 * @brief 00420 * Checks the local header of the selected file 00421 * 00422 * @param[out] nSizeVar 00423 * Will receive the total local header size 00424 * @param[out] nPosLocalExtra 00425 * Will receive the position of the local extra 00426 * @param[out] nSizeLocalExtra 00427 * Will receive the size of the local extra 00428 * @param[out] nFlags 00429 * Will receive the flags 00430 * 00431 * @return 00432 * 'true' if all went fine, else 'false' 00433 */ 00434 bool CheckFileHeader(uint32 &nSizeVar, uint32 &nPosLocalExtra, uint32 &nSizeLocalExtra, uint16 &nFlags); 00435 00436 /** 00437 * @brief 00438 * Reads a byte from the ZIP-file 00439 * 00440 * @param[out] nByte 00441 * Will receive the read byte value 00442 * 00443 * @return 00444 * 'true' if everything went fine, else 'false' ('nByte' is set to 0) 00445 */ 00446 bool ReadByte(uint8 &nByte); 00447 00448 /** 00449 * @brief 00450 * Reads a unsigned short from the ZIP-file 00451 * 00452 * @param[out] nShort 00453 * Will receive the read unsigned short value 00454 * 00455 * @return 00456 * 'true' if everything went fine, else 'false' ('nShort' is set to 0) 00457 */ 00458 bool ReadShort(uint16 &nShort); 00459 00460 /** 00461 * @brief 00462 * Reads a unsigned long from the ZIP-file 00463 * 00464 * @param[out] nLong 00465 * Will receive the read unsigned long value 00466 * 00467 * @return 00468 * 'true' if everything went fine, else 'false' ('nLong' is set to 0) 00469 */ 00470 bool ReadLong(uint32 &nLong); 00471 00472 00473 //[-------------------------------------------------------] 00474 //[ Private data ] 00475 //[-------------------------------------------------------] 00476 private: 00477 // General 00478 File m_cZipFile; /**< ZIP-file to work on */ 00479 bool m_bCaseSensitive; /**< Are names treated case sensitive? */ 00480 bool m_bMemBuf; /**< Read ZIP-file memory-buffered? */ 00481 00482 // Information about the ZIP-file 00483 bool m_bZipFileValid; /**< Error flag */ 00484 uint16 m_nNumEntries; /**< Number of directory entries in the ZIP-file */ 00485 uint16 m_nCommentSize; /**< Size of the ZIP-file comment */ 00486 uint32 m_nBytesBeforeZip; /**< Byte before the ZIP-file, (> 0 for sfx) */ 00487 uint32 m_nCentralDirPos; /**< Position of the beginning of the central directory */ 00488 uint32 m_nCentralDirSize; /**< Size of the central directory */ 00489 uint32 m_nCentralDirOffset; /**< Offset of start of central directory with respect to the starting disk number */ 00490 uint16 m_nDiskNum; /**< Disk number (for splitted ZIP-files) */ 00491 uint16 m_nMainDisk; /**< Disk number that contains the central directory */ 00492 uint16 m_nMainEntries; /**< Number of entries in the central directory on this disk */ 00493 00494 // Currently selected file 00495 ZipEntry m_cCurFile; /**< Current file entry */ 00496 uint32 m_nCurFile; /**< Number of the current file in the ZIP-file */ 00497 uint32 m_nCurCentralDirPos; /**< Position of the current file in the central directory */ 00498 00499 // Stream data 00500 uint8 *m_pReadBuffer; /**< Internal buffer for compressed data (always valid!) */ 00501 z_stream *m_pStream; /**< ZLib stream structure for inflate, can be a null pointer */ 00502 uint32 m_nPosInZip; /**< Position in byte on the ZIP-file, for fseek */ 00503 uint32 m_nPosLocalExtra; /**< Offset of the local extra field */ 00504 uint32 m_nSizeLocalExtra; /**< Size of the local extra field */ 00505 uint32 m_nPosInLocalExtra; /**< Position in the local extra field in read */ 00506 uint32 m_nCRC32; /**< CRC32 of all data uncompressed */ 00507 uint32 m_nCRC32Wait; /**< CRC32 we must obtain after decompress all */ 00508 uint32 m_nReadCompressed; /**< Number of byte to be decompressed */ 00509 uint32 m_nReadUncompressed; /**< Number of byte to be obtained after decompression */ 00510 uint16 m_nCompressionMethod; /**< Currently used compression method (copied from cCurrentFile) */ 00511 00512 // Encryption data 00513 bool m_bEncrypted; /**< Is the file encrypted? */ 00514 uint32 m_nKeys[3]; /**< Decryption keys, initialized by constructor */ 00515 int m_nEncheadLeft; /**< The first call(s) to Read() will read this many encryption-header bytes first */ 00516 char m_nCRCEncTest; /**< If encrypted, we'll check the encryption buffer against this */ 00517 00518 00519 }; 00520 00521 00522 //[-------------------------------------------------------] 00523 //[ Namespace ] 00524 //[-------------------------------------------------------] 00525 } // PLCore 00526 00527 00528 #endif // __PLCORE_ZIPHANDLE_H__
|