diff options
author | David Walter Seikel | 2013-01-13 18:54:10 +1000 |
---|---|---|
committer | David Walter Seikel | 2013-01-13 18:54:10 +1000 |
commit | 959831f4ef5a3e797f576c3de08cd65032c997ad (patch) | |
tree | e7351908be5995f0b325b2ebeaa02d5a34b82583 /libraries/irrlicht-1.8/source/Irrlicht/CZipReader.cpp | |
parent | Add info about changes to Irrlicht. (diff) | |
download | SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.zip SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.gz SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.bz2 SledjHamr-959831f4ef5a3e797f576c3de08cd65032c997ad.tar.xz |
Remove damned ancient DOS line endings from Irrlicht. Hopefully I did not go overboard.
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CZipReader.cpp | 1678 |
1 files changed, 839 insertions, 839 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CZipReader.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CZipReader.cpp index be29f98..d080943 100644 --- a/libraries/irrlicht-1.8/source/Irrlicht/CZipReader.cpp +++ b/libraries/irrlicht-1.8/source/Irrlicht/CZipReader.cpp | |||
@@ -1,839 +1,839 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | 1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt |
2 | // This file is part of the "Irrlicht Engine". | 2 | // This file is part of the "Irrlicht Engine". |
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | 3 | // For conditions of distribution and use, see copyright notice in irrlicht.h |
4 | 4 | ||
5 | #include "CZipReader.h" | 5 | #include "CZipReader.h" |
6 | 6 | ||
7 | #include "os.h" | 7 | #include "os.h" |
8 | 8 | ||
9 | // This method is used for error output from bzip2. | 9 | // This method is used for error output from bzip2. |
10 | extern "C" void bz_internal_error(int errorCode) | 10 | extern "C" void bz_internal_error(int errorCode) |
11 | { | 11 | { |
12 | irr::os::Printer::log("Error in bzip2 handling", irr::core::stringc(errorCode), irr::ELL_ERROR); | 12 | irr::os::Printer::log("Error in bzip2 handling", irr::core::stringc(errorCode), irr::ELL_ERROR); |
13 | } | 13 | } |
14 | 14 | ||
15 | #ifdef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ | 15 | #ifdef __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ |
16 | 16 | ||
17 | #include "CFileList.h" | 17 | #include "CFileList.h" |
18 | #include "CReadFile.h" | 18 | #include "CReadFile.h" |
19 | #include "coreutil.h" | 19 | #include "coreutil.h" |
20 | 20 | ||
21 | #include "IrrCompileConfig.h" | 21 | #include "IrrCompileConfig.h" |
22 | #ifdef _IRR_COMPILE_WITH_ZLIB_ | 22 | #ifdef _IRR_COMPILE_WITH_ZLIB_ |
23 | #ifndef _IRR_USE_NON_SYSTEM_ZLIB_ | 23 | #ifndef _IRR_USE_NON_SYSTEM_ZLIB_ |
24 | #include <zlib.h> // use system lib | 24 | #include <zlib.h> // use system lib |
25 | #else | 25 | #else |
26 | #include "zlib/zlib.h" | 26 | #include "zlib/zlib.h" |
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | #ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ | 29 | #ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ |
30 | #include "aesGladman/fileenc.h" | 30 | #include "aesGladman/fileenc.h" |
31 | #endif | 31 | #endif |
32 | #ifdef _IRR_COMPILE_WITH_BZIP2_ | 32 | #ifdef _IRR_COMPILE_WITH_BZIP2_ |
33 | #ifndef _IRR_USE_NON_SYSTEM_BZLIB_ | 33 | #ifndef _IRR_USE_NON_SYSTEM_BZLIB_ |
34 | #include <bzlib.h> | 34 | #include <bzlib.h> |
35 | #else | 35 | #else |
36 | #include "bzip2/bzlib.h" | 36 | #include "bzip2/bzlib.h" |
37 | #endif | 37 | #endif |
38 | #endif | 38 | #endif |
39 | #ifdef _IRR_COMPILE_WITH_LZMA_ | 39 | #ifdef _IRR_COMPILE_WITH_LZMA_ |
40 | #include "lzma/LzmaDec.h" | 40 | #include "lzma/LzmaDec.h" |
41 | #endif | 41 | #endif |
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | namespace irr | 44 | namespace irr |
45 | { | 45 | { |
46 | namespace io | 46 | namespace io |
47 | { | 47 | { |
48 | 48 | ||
49 | 49 | ||
50 | // ----------------------------------------------------------------------------- | 50 | // ----------------------------------------------------------------------------- |
51 | // zip loader | 51 | // zip loader |
52 | // ----------------------------------------------------------------------------- | 52 | // ----------------------------------------------------------------------------- |
53 | 53 | ||
54 | //! Constructor | 54 | //! Constructor |
55 | CArchiveLoaderZIP::CArchiveLoaderZIP(io::IFileSystem* fs) | 55 | CArchiveLoaderZIP::CArchiveLoaderZIP(io::IFileSystem* fs) |
56 | : FileSystem(fs) | 56 | : FileSystem(fs) |
57 | { | 57 | { |
58 | #ifdef _DEBUG | 58 | #ifdef _DEBUG |
59 | setDebugName("CArchiveLoaderZIP"); | 59 | setDebugName("CArchiveLoaderZIP"); |
60 | #endif | 60 | #endif |
61 | } | 61 | } |
62 | 62 | ||
63 | //! returns true if the file maybe is able to be loaded by this class | 63 | //! returns true if the file maybe is able to be loaded by this class |
64 | bool CArchiveLoaderZIP::isALoadableFileFormat(const io::path& filename) const | 64 | bool CArchiveLoaderZIP::isALoadableFileFormat(const io::path& filename) const |
65 | { | 65 | { |
66 | return core::hasFileExtension(filename, "zip", "pk3") || | 66 | return core::hasFileExtension(filename, "zip", "pk3") || |
67 | core::hasFileExtension(filename, "gz", "tgz"); | 67 | core::hasFileExtension(filename, "gz", "tgz"); |
68 | } | 68 | } |
69 | 69 | ||
70 | //! Check to see if the loader can create archives of this type. | 70 | //! Check to see if the loader can create archives of this type. |
71 | bool CArchiveLoaderZIP::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const | 71 | bool CArchiveLoaderZIP::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const |
72 | { | 72 | { |
73 | return (fileType == EFAT_ZIP || fileType == EFAT_GZIP); | 73 | return (fileType == EFAT_ZIP || fileType == EFAT_GZIP); |
74 | } | 74 | } |
75 | 75 | ||
76 | 76 | ||
77 | //! Creates an archive from the filename | 77 | //! Creates an archive from the filename |
78 | /** \param file File handle to check. | 78 | /** \param file File handle to check. |
79 | \return Pointer to newly created archive, or 0 upon error. */ | 79 | \return Pointer to newly created archive, or 0 upon error. */ |
80 | IFileArchive* CArchiveLoaderZIP::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const | 80 | IFileArchive* CArchiveLoaderZIP::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const |
81 | { | 81 | { |
82 | IFileArchive *archive = 0; | 82 | IFileArchive *archive = 0; |
83 | io::IReadFile* file = FileSystem->createAndOpenFile(filename); | 83 | io::IReadFile* file = FileSystem->createAndOpenFile(filename); |
84 | 84 | ||
85 | if (file) | 85 | if (file) |
86 | { | 86 | { |
87 | archive = createArchive(file, ignoreCase, ignorePaths); | 87 | archive = createArchive(file, ignoreCase, ignorePaths); |
88 | file->drop(); | 88 | file->drop(); |
89 | } | 89 | } |
90 | 90 | ||
91 | return archive; | 91 | return archive; |
92 | } | 92 | } |
93 | 93 | ||
94 | //! creates/loads an archive from the file. | 94 | //! creates/loads an archive from the file. |
95 | //! \return Pointer to the created archive. Returns 0 if loading failed. | 95 | //! \return Pointer to the created archive. Returns 0 if loading failed. |
96 | IFileArchive* CArchiveLoaderZIP::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const | 96 | IFileArchive* CArchiveLoaderZIP::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const |
97 | { | 97 | { |
98 | IFileArchive *archive = 0; | 98 | IFileArchive *archive = 0; |
99 | if (file) | 99 | if (file) |
100 | { | 100 | { |
101 | file->seek(0); | 101 | file->seek(0); |
102 | 102 | ||
103 | u16 sig; | 103 | u16 sig; |
104 | file->read(&sig, 2); | 104 | file->read(&sig, 2); |
105 | 105 | ||
106 | #ifdef __BIG_ENDIAN__ | 106 | #ifdef __BIG_ENDIAN__ |
107 | sig = os::Byteswap::byteswap(sig); | 107 | sig = os::Byteswap::byteswap(sig); |
108 | #endif | 108 | #endif |
109 | 109 | ||
110 | file->seek(0); | 110 | file->seek(0); |
111 | 111 | ||
112 | bool isGZip = (sig == 0x8b1f); | 112 | bool isGZip = (sig == 0x8b1f); |
113 | 113 | ||
114 | archive = new CZipReader(file, ignoreCase, ignorePaths, isGZip); | 114 | archive = new CZipReader(file, ignoreCase, ignorePaths, isGZip); |
115 | } | 115 | } |
116 | return archive; | 116 | return archive; |
117 | } | 117 | } |
118 | 118 | ||
119 | //! Check if the file might be loaded by this class | 119 | //! Check if the file might be loaded by this class |
120 | /** Check might look into the file. | 120 | /** Check might look into the file. |
121 | \param file File handle to check. | 121 | \param file File handle to check. |
122 | \return True if file seems to be loadable. */ | 122 | \return True if file seems to be loadable. */ |
123 | bool CArchiveLoaderZIP::isALoadableFileFormat(io::IReadFile* file) const | 123 | bool CArchiveLoaderZIP::isALoadableFileFormat(io::IReadFile* file) const |
124 | { | 124 | { |
125 | SZIPFileHeader header; | 125 | SZIPFileHeader header; |
126 | 126 | ||
127 | file->read( &header.Sig, 4 ); | 127 | file->read( &header.Sig, 4 ); |
128 | #ifdef __BIG_ENDIAN__ | 128 | #ifdef __BIG_ENDIAN__ |
129 | header.Sig = os::Byteswap::byteswap(header.Sig); | 129 | header.Sig = os::Byteswap::byteswap(header.Sig); |
130 | #endif | 130 | #endif |
131 | 131 | ||
132 | return header.Sig == 0x04034b50 || // ZIP | 132 | return header.Sig == 0x04034b50 || // ZIP |
133 | (header.Sig&0xffff) == 0x8b1f; // gzip | 133 | (header.Sig&0xffff) == 0x8b1f; // gzip |
134 | } | 134 | } |
135 | 135 | ||
136 | // ----------------------------------------------------------------------------- | 136 | // ----------------------------------------------------------------------------- |
137 | // zip archive | 137 | // zip archive |
138 | // ----------------------------------------------------------------------------- | 138 | // ----------------------------------------------------------------------------- |
139 | 139 | ||
140 | CZipReader::CZipReader(IReadFile* file, bool ignoreCase, bool ignorePaths, bool isGZip) | 140 | CZipReader::CZipReader(IReadFile* file, bool ignoreCase, bool ignorePaths, bool isGZip) |
141 | : CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), File(file), IsGZip(isGZip) | 141 | : CFileList((file ? file->getFileName() : io::path("")), ignoreCase, ignorePaths), File(file), IsGZip(isGZip) |
142 | { | 142 | { |
143 | #ifdef _DEBUG | 143 | #ifdef _DEBUG |
144 | setDebugName("CZipReader"); | 144 | setDebugName("CZipReader"); |
145 | #endif | 145 | #endif |
146 | 146 | ||
147 | if (File) | 147 | if (File) |
148 | { | 148 | { |
149 | File->grab(); | 149 | File->grab(); |
150 | 150 | ||
151 | // load file entries | 151 | // load file entries |
152 | if (IsGZip) | 152 | if (IsGZip) |
153 | while (scanGZipHeader()) { } | 153 | while (scanGZipHeader()) { } |
154 | else | 154 | else |
155 | while (scanZipHeader()) { } | 155 | while (scanZipHeader()) { } |
156 | 156 | ||
157 | sort(); | 157 | sort(); |
158 | } | 158 | } |
159 | } | 159 | } |
160 | 160 | ||
161 | CZipReader::~CZipReader() | 161 | CZipReader::~CZipReader() |
162 | { | 162 | { |
163 | if (File) | 163 | if (File) |
164 | File->drop(); | 164 | File->drop(); |
165 | } | 165 | } |
166 | 166 | ||
167 | 167 | ||
168 | //! get the archive type | 168 | //! get the archive type |
169 | E_FILE_ARCHIVE_TYPE CZipReader::getType() const | 169 | E_FILE_ARCHIVE_TYPE CZipReader::getType() const |
170 | { | 170 | { |
171 | return IsGZip ? EFAT_GZIP : EFAT_ZIP; | 171 | return IsGZip ? EFAT_GZIP : EFAT_ZIP; |
172 | } | 172 | } |
173 | 173 | ||
174 | const IFileList* CZipReader::getFileList() const | 174 | const IFileList* CZipReader::getFileList() const |
175 | { | 175 | { |
176 | return this; | 176 | return this; |
177 | } | 177 | } |
178 | 178 | ||
179 | 179 | ||
180 | //! scans for a local header, returns false if there is no more local file header. | 180 | //! scans for a local header, returns false if there is no more local file header. |
181 | //! The gzip file format seems to think that there can be multiple files in a gzip file | 181 | //! The gzip file format seems to think that there can be multiple files in a gzip file |
182 | //! but none | 182 | //! but none |
183 | bool CZipReader::scanGZipHeader() | 183 | bool CZipReader::scanGZipHeader() |
184 | { | 184 | { |
185 | SZipFileEntry entry; | 185 | SZipFileEntry entry; |
186 | entry.Offset = 0; | 186 | entry.Offset = 0; |
187 | memset(&entry.header, 0, sizeof(SZIPFileHeader)); | 187 | memset(&entry.header, 0, sizeof(SZIPFileHeader)); |
188 | 188 | ||
189 | // read header | 189 | // read header |
190 | SGZIPMemberHeader header; | 190 | SGZIPMemberHeader header; |
191 | if (File->read(&header, sizeof(SGZIPMemberHeader)) == sizeof(SGZIPMemberHeader)) | 191 | if (File->read(&header, sizeof(SGZIPMemberHeader)) == sizeof(SGZIPMemberHeader)) |
192 | { | 192 | { |
193 | 193 | ||
194 | #ifdef __BIG_ENDIAN__ | 194 | #ifdef __BIG_ENDIAN__ |
195 | header.sig = os::Byteswap::byteswap(header.sig); | 195 | header.sig = os::Byteswap::byteswap(header.sig); |
196 | header.time = os::Byteswap::byteswap(header.time); | 196 | header.time = os::Byteswap::byteswap(header.time); |
197 | #endif | 197 | #endif |
198 | 198 | ||
199 | // check header value | 199 | // check header value |
200 | if (header.sig != 0x8b1f) | 200 | if (header.sig != 0x8b1f) |
201 | return false; | 201 | return false; |
202 | 202 | ||
203 | // now get the file info | 203 | // now get the file info |
204 | if (header.flags & EGZF_EXTRA_FIELDS) | 204 | if (header.flags & EGZF_EXTRA_FIELDS) |
205 | { | 205 | { |
206 | // read lenth of extra data | 206 | // read lenth of extra data |
207 | u16 dataLen; | 207 | u16 dataLen; |
208 | 208 | ||
209 | File->read(&dataLen, 2); | 209 | File->read(&dataLen, 2); |
210 | 210 | ||
211 | #ifdef __BIG_ENDIAN__ | 211 | #ifdef __BIG_ENDIAN__ |
212 | dataLen = os::Byteswap::byteswap(dataLen); | 212 | dataLen = os::Byteswap::byteswap(dataLen); |
213 | #endif | 213 | #endif |
214 | 214 | ||
215 | // skip it | 215 | // skip it |
216 | File->seek(dataLen, true); | 216 | File->seek(dataLen, true); |
217 | } | 217 | } |
218 | 218 | ||
219 | io::path ZipFileName = ""; | 219 | io::path ZipFileName = ""; |
220 | 220 | ||
221 | if (header.flags & EGZF_FILE_NAME) | 221 | if (header.flags & EGZF_FILE_NAME) |
222 | { | 222 | { |
223 | c8 c; | 223 | c8 c; |
224 | File->read(&c, 1); | 224 | File->read(&c, 1); |
225 | while (c) | 225 | while (c) |
226 | { | 226 | { |
227 | ZipFileName.append(c); | 227 | ZipFileName.append(c); |
228 | File->read(&c, 1); | 228 | File->read(&c, 1); |
229 | } | 229 | } |
230 | } | 230 | } |
231 | else | 231 | else |
232 | { | 232 | { |
233 | // no file name? | 233 | // no file name? |
234 | ZipFileName = Path; | 234 | ZipFileName = Path; |
235 | core::deletePathFromFilename(ZipFileName); | 235 | core::deletePathFromFilename(ZipFileName); |
236 | 236 | ||
237 | // rename tgz to tar or remove gz extension | 237 | // rename tgz to tar or remove gz extension |
238 | if (core::hasFileExtension(ZipFileName, "tgz")) | 238 | if (core::hasFileExtension(ZipFileName, "tgz")) |
239 | { | 239 | { |
240 | ZipFileName[ ZipFileName.size() - 2] = 'a'; | 240 | ZipFileName[ ZipFileName.size() - 2] = 'a'; |
241 | ZipFileName[ ZipFileName.size() - 1] = 'r'; | 241 | ZipFileName[ ZipFileName.size() - 1] = 'r'; |
242 | } | 242 | } |
243 | else if (core::hasFileExtension(ZipFileName, "gz")) | 243 | else if (core::hasFileExtension(ZipFileName, "gz")) |
244 | { | 244 | { |
245 | ZipFileName[ ZipFileName.size() - 3] = 0; | 245 | ZipFileName[ ZipFileName.size() - 3] = 0; |
246 | ZipFileName.validate(); | 246 | ZipFileName.validate(); |
247 | } | 247 | } |
248 | } | 248 | } |
249 | 249 | ||
250 | if (header.flags & EGZF_COMMENT) | 250 | if (header.flags & EGZF_COMMENT) |
251 | { | 251 | { |
252 | c8 c='a'; | 252 | c8 c='a'; |
253 | while (c) | 253 | while (c) |
254 | File->read(&c, 1); | 254 | File->read(&c, 1); |
255 | } | 255 | } |
256 | 256 | ||
257 | if (header.flags & EGZF_CRC16) | 257 | if (header.flags & EGZF_CRC16) |
258 | File->seek(2, true); | 258 | File->seek(2, true); |
259 | 259 | ||
260 | // we are now at the start of the data blocks | 260 | // we are now at the start of the data blocks |
261 | entry.Offset = File->getPos(); | 261 | entry.Offset = File->getPos(); |
262 | 262 | ||
263 | entry.header.FilenameLength = ZipFileName.size(); | 263 | entry.header.FilenameLength = ZipFileName.size(); |
264 | 264 | ||
265 | entry.header.CompressionMethod = header.compressionMethod; | 265 | entry.header.CompressionMethod = header.compressionMethod; |
266 | entry.header.DataDescriptor.CompressedSize = (File->getSize() - 8) - File->getPos(); | 266 | entry.header.DataDescriptor.CompressedSize = (File->getSize() - 8) - File->getPos(); |
267 | 267 | ||
268 | // seek to file end | 268 | // seek to file end |
269 | File->seek(entry.header.DataDescriptor.CompressedSize, true); | 269 | File->seek(entry.header.DataDescriptor.CompressedSize, true); |
270 | 270 | ||
271 | // read CRC | 271 | // read CRC |
272 | File->read(&entry.header.DataDescriptor.CRC32, 4); | 272 | File->read(&entry.header.DataDescriptor.CRC32, 4); |
273 | // read uncompressed size | 273 | // read uncompressed size |
274 | File->read(&entry.header.DataDescriptor.UncompressedSize, 4); | 274 | File->read(&entry.header.DataDescriptor.UncompressedSize, 4); |
275 | 275 | ||
276 | #ifdef __BIG_ENDIAN__ | 276 | #ifdef __BIG_ENDIAN__ |
277 | entry.header.DataDescriptor.CRC32 = os::Byteswap::byteswap(entry.header.DataDescriptor.CRC32); | 277 | entry.header.DataDescriptor.CRC32 = os::Byteswap::byteswap(entry.header.DataDescriptor.CRC32); |
278 | entry.header.DataDescriptor.UncompressedSize = os::Byteswap::byteswap(entry.header.DataDescriptor.UncompressedSize); | 278 | entry.header.DataDescriptor.UncompressedSize = os::Byteswap::byteswap(entry.header.DataDescriptor.UncompressedSize); |
279 | #endif | 279 | #endif |
280 | 280 | ||
281 | // now we've filled all the fields, this is just a standard deflate block | 281 | // now we've filled all the fields, this is just a standard deflate block |
282 | addItem(ZipFileName, entry.Offset, entry.header.DataDescriptor.UncompressedSize, false, 0); | 282 | addItem(ZipFileName, entry.Offset, entry.header.DataDescriptor.UncompressedSize, false, 0); |
283 | FileInfo.push_back(entry); | 283 | FileInfo.push_back(entry); |
284 | } | 284 | } |
285 | 285 | ||
286 | // there's only one block of data in a gzip file | 286 | // there's only one block of data in a gzip file |
287 | return false; | 287 | return false; |
288 | } | 288 | } |
289 | 289 | ||
290 | //! scans for a local header, returns false if there is no more local file header. | 290 | //! scans for a local header, returns false if there is no more local file header. |
291 | bool CZipReader::scanZipHeader(bool ignoreGPBits) | 291 | bool CZipReader::scanZipHeader(bool ignoreGPBits) |
292 | { | 292 | { |
293 | io::path ZipFileName = ""; | 293 | io::path ZipFileName = ""; |
294 | SZipFileEntry entry; | 294 | SZipFileEntry entry; |
295 | entry.Offset = 0; | 295 | entry.Offset = 0; |
296 | memset(&entry.header, 0, sizeof(SZIPFileHeader)); | 296 | memset(&entry.header, 0, sizeof(SZIPFileHeader)); |
297 | 297 | ||
298 | File->read(&entry.header, sizeof(SZIPFileHeader)); | 298 | File->read(&entry.header, sizeof(SZIPFileHeader)); |
299 | 299 | ||
300 | #ifdef __BIG_ENDIAN__ | 300 | #ifdef __BIG_ENDIAN__ |
301 | entry.header.Sig = os::Byteswap::byteswap(entry.header.Sig); | 301 | entry.header.Sig = os::Byteswap::byteswap(entry.header.Sig); |
302 | entry.header.VersionToExtract = os::Byteswap::byteswap(entry.header.VersionToExtract); | 302 | entry.header.VersionToExtract = os::Byteswap::byteswap(entry.header.VersionToExtract); |
303 | entry.header.GeneralBitFlag = os::Byteswap::byteswap(entry.header.GeneralBitFlag); | 303 | entry.header.GeneralBitFlag = os::Byteswap::byteswap(entry.header.GeneralBitFlag); |
304 | entry.header.CompressionMethod = os::Byteswap::byteswap(entry.header.CompressionMethod); | 304 | entry.header.CompressionMethod = os::Byteswap::byteswap(entry.header.CompressionMethod); |
305 | entry.header.LastModFileTime = os::Byteswap::byteswap(entry.header.LastModFileTime); | 305 | entry.header.LastModFileTime = os::Byteswap::byteswap(entry.header.LastModFileTime); |
306 | entry.header.LastModFileDate = os::Byteswap::byteswap(entry.header.LastModFileDate); | 306 | entry.header.LastModFileDate = os::Byteswap::byteswap(entry.header.LastModFileDate); |
307 | entry.header.DataDescriptor.CRC32 = os::Byteswap::byteswap(entry.header.DataDescriptor.CRC32); | 307 | entry.header.DataDescriptor.CRC32 = os::Byteswap::byteswap(entry.header.DataDescriptor.CRC32); |
308 | entry.header.DataDescriptor.CompressedSize = os::Byteswap::byteswap(entry.header.DataDescriptor.CompressedSize); | 308 | entry.header.DataDescriptor.CompressedSize = os::Byteswap::byteswap(entry.header.DataDescriptor.CompressedSize); |
309 | entry.header.DataDescriptor.UncompressedSize = os::Byteswap::byteswap(entry.header.DataDescriptor.UncompressedSize); | 309 | entry.header.DataDescriptor.UncompressedSize = os::Byteswap::byteswap(entry.header.DataDescriptor.UncompressedSize); |
310 | entry.header.FilenameLength = os::Byteswap::byteswap(entry.header.FilenameLength); | 310 | entry.header.FilenameLength = os::Byteswap::byteswap(entry.header.FilenameLength); |
311 | entry.header.ExtraFieldLength = os::Byteswap::byteswap(entry.header.ExtraFieldLength); | 311 | entry.header.ExtraFieldLength = os::Byteswap::byteswap(entry.header.ExtraFieldLength); |
312 | #endif | 312 | #endif |
313 | 313 | ||
314 | if (entry.header.Sig != 0x04034b50) | 314 | if (entry.header.Sig != 0x04034b50) |
315 | return false; // local file headers end here. | 315 | return false; // local file headers end here. |
316 | 316 | ||
317 | // read filename | 317 | // read filename |
318 | { | 318 | { |
319 | c8 *tmp = new c8 [ entry.header.FilenameLength + 2 ]; | 319 | c8 *tmp = new c8 [ entry.header.FilenameLength + 2 ]; |
320 | File->read(tmp, entry.header.FilenameLength); | 320 | File->read(tmp, entry.header.FilenameLength); |
321 | tmp[entry.header.FilenameLength] = 0; | 321 | tmp[entry.header.FilenameLength] = 0; |
322 | ZipFileName = tmp; | 322 | ZipFileName = tmp; |
323 | delete [] tmp; | 323 | delete [] tmp; |
324 | } | 324 | } |
325 | 325 | ||
326 | #ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ | 326 | #ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ |
327 | // AES encryption | 327 | // AES encryption |
328 | if ((entry.header.GeneralBitFlag & ZIP_FILE_ENCRYPTED) && (entry.header.CompressionMethod == 99)) | 328 | if ((entry.header.GeneralBitFlag & ZIP_FILE_ENCRYPTED) && (entry.header.CompressionMethod == 99)) |
329 | { | 329 | { |
330 | s16 restSize = entry.header.ExtraFieldLength; | 330 | s16 restSize = entry.header.ExtraFieldLength; |
331 | SZipFileExtraHeader extraHeader; | 331 | SZipFileExtraHeader extraHeader; |
332 | while (restSize) | 332 | while (restSize) |
333 | { | 333 | { |
334 | File->read(&extraHeader, sizeof(extraHeader)); | 334 | File->read(&extraHeader, sizeof(extraHeader)); |
335 | #ifdef __BIG_ENDIAN__ | 335 | #ifdef __BIG_ENDIAN__ |
336 | extraHeader.ID = os::Byteswap::byteswap(extraHeader.ID); | 336 | extraHeader.ID = os::Byteswap::byteswap(extraHeader.ID); |
337 | extraHeader.Size = os::Byteswap::byteswap(extraHeader.Size); | 337 | extraHeader.Size = os::Byteswap::byteswap(extraHeader.Size); |
338 | #endif | 338 | #endif |
339 | restSize -= sizeof(extraHeader); | 339 | restSize -= sizeof(extraHeader); |
340 | if (extraHeader.ID==(s16)0x9901) | 340 | if (extraHeader.ID==(s16)0x9901) |
341 | { | 341 | { |
342 | SZipFileAESExtraData data; | 342 | SZipFileAESExtraData data; |
343 | File->read(&data, sizeof(data)); | 343 | File->read(&data, sizeof(data)); |
344 | #ifdef __BIG_ENDIAN__ | 344 | #ifdef __BIG_ENDIAN__ |
345 | data.Version = os::Byteswap::byteswap(data.Version); | 345 | data.Version = os::Byteswap::byteswap(data.Version); |
346 | data.CompressionMode = os::Byteswap::byteswap(data.CompressionMode); | 346 | data.CompressionMode = os::Byteswap::byteswap(data.CompressionMode); |
347 | #endif | 347 | #endif |
348 | restSize -= sizeof(data); | 348 | restSize -= sizeof(data); |
349 | if (data.Vendor[0]=='A' && data.Vendor[1]=='E') | 349 | if (data.Vendor[0]=='A' && data.Vendor[1]=='E') |
350 | { | 350 | { |
351 | // encode values into Sig | 351 | // encode values into Sig |
352 | // AE-Version | Strength | ActualMode | 352 | // AE-Version | Strength | ActualMode |
353 | entry.header.Sig = | 353 | entry.header.Sig = |
354 | ((data.Version & 0xff) << 24) | | 354 | ((data.Version & 0xff) << 24) | |
355 | (data.EncryptionStrength << 16) | | 355 | (data.EncryptionStrength << 16) | |
356 | (data.CompressionMode); | 356 | (data.CompressionMode); |
357 | File->seek(restSize, true); | 357 | File->seek(restSize, true); |
358 | break; | 358 | break; |
359 | } | 359 | } |
360 | } | 360 | } |
361 | } | 361 | } |
362 | } | 362 | } |
363 | // move forward length of extra field. | 363 | // move forward length of extra field. |
364 | else | 364 | else |
365 | #endif | 365 | #endif |
366 | if (entry.header.ExtraFieldLength) | 366 | if (entry.header.ExtraFieldLength) |
367 | File->seek(entry.header.ExtraFieldLength, true); | 367 | File->seek(entry.header.ExtraFieldLength, true); |
368 | 368 | ||
369 | // if bit 3 was set, use CentralDirectory for setup | 369 | // if bit 3 was set, use CentralDirectory for setup |
370 | if (!ignoreGPBits && entry.header.GeneralBitFlag & ZIP_INFO_IN_DATA_DESCRIPTOR) | 370 | if (!ignoreGPBits && entry.header.GeneralBitFlag & ZIP_INFO_IN_DATA_DESCRIPTOR) |
371 | { | 371 | { |
372 | SZIPFileCentralDirEnd dirEnd; | 372 | SZIPFileCentralDirEnd dirEnd; |
373 | FileInfo.clear(); | 373 | FileInfo.clear(); |
374 | Files.clear(); | 374 | Files.clear(); |
375 | // First place where the end record could be stored | 375 | // First place where the end record could be stored |
376 | File->seek(File->getSize()-22); | 376 | File->seek(File->getSize()-22); |
377 | const char endID[] = {0x50, 0x4b, 0x05, 0x06, 0x0}; | 377 | const char endID[] = {0x50, 0x4b, 0x05, 0x06, 0x0}; |
378 | char tmp[5]={'\0'}; | 378 | char tmp[5]={'\0'}; |
379 | bool found=false; | 379 | bool found=false; |
380 | // search for the end record ID | 380 | // search for the end record ID |
381 | while (!found && File->getPos()>0) | 381 | while (!found && File->getPos()>0) |
382 | { | 382 | { |
383 | int seek=8; | 383 | int seek=8; |
384 | File->read(tmp, 4); | 384 | File->read(tmp, 4); |
385 | switch (tmp[0]) | 385 | switch (tmp[0]) |
386 | { | 386 | { |
387 | case 0x50: | 387 | case 0x50: |
388 | if (!strcmp(endID, tmp)) | 388 | if (!strcmp(endID, tmp)) |
389 | { | 389 | { |
390 | seek=4; | 390 | seek=4; |
391 | found=true; | 391 | found=true; |
392 | } | 392 | } |
393 | break; | 393 | break; |
394 | case 0x4b: | 394 | case 0x4b: |
395 | seek=5; | 395 | seek=5; |
396 | break; | 396 | break; |
397 | case 0x05: | 397 | case 0x05: |
398 | seek=6; | 398 | seek=6; |
399 | break; | 399 | break; |
400 | case 0x06: | 400 | case 0x06: |
401 | seek=7; | 401 | seek=7; |
402 | break; | 402 | break; |
403 | } | 403 | } |
404 | File->seek(-seek, true); | 404 | File->seek(-seek, true); |
405 | } | 405 | } |
406 | File->read(&dirEnd, sizeof(dirEnd)); | 406 | File->read(&dirEnd, sizeof(dirEnd)); |
407 | #ifdef __BIG_ENDIAN__ | 407 | #ifdef __BIG_ENDIAN__ |
408 | dirEnd.NumberDisk = os::Byteswap::byteswap(dirEnd.NumberDisk); | 408 | dirEnd.NumberDisk = os::Byteswap::byteswap(dirEnd.NumberDisk); |
409 | dirEnd.NumberStart = os::Byteswap::byteswap(dirEnd.NumberStart); | 409 | dirEnd.NumberStart = os::Byteswap::byteswap(dirEnd.NumberStart); |
410 | dirEnd.TotalDisk = os::Byteswap::byteswap(dirEnd.TotalDisk); | 410 | dirEnd.TotalDisk = os::Byteswap::byteswap(dirEnd.TotalDisk); |
411 | dirEnd.TotalEntries = os::Byteswap::byteswap(dirEnd.TotalEntries); | 411 | dirEnd.TotalEntries = os::Byteswap::byteswap(dirEnd.TotalEntries); |
412 | dirEnd.Size = os::Byteswap::byteswap(dirEnd.Size); | 412 | dirEnd.Size = os::Byteswap::byteswap(dirEnd.Size); |
413 | dirEnd.Offset = os::Byteswap::byteswap(dirEnd.Offset); | 413 | dirEnd.Offset = os::Byteswap::byteswap(dirEnd.Offset); |
414 | dirEnd.CommentLength = os::Byteswap::byteswap(dirEnd.CommentLength); | 414 | dirEnd.CommentLength = os::Byteswap::byteswap(dirEnd.CommentLength); |
415 | #endif | 415 | #endif |
416 | FileInfo.reallocate(dirEnd.TotalEntries); | 416 | FileInfo.reallocate(dirEnd.TotalEntries); |
417 | File->seek(dirEnd.Offset); | 417 | File->seek(dirEnd.Offset); |
418 | while (scanCentralDirectoryHeader()) { } | 418 | while (scanCentralDirectoryHeader()) { } |
419 | return false; | 419 | return false; |
420 | } | 420 | } |
421 | 421 | ||
422 | // store position in file | 422 | // store position in file |
423 | entry.Offset = File->getPos(); | 423 | entry.Offset = File->getPos(); |
424 | // move forward length of data | 424 | // move forward length of data |
425 | File->seek(entry.header.DataDescriptor.CompressedSize, true); | 425 | File->seek(entry.header.DataDescriptor.CompressedSize, true); |
426 | 426 | ||
427 | #ifdef _DEBUG | 427 | #ifdef _DEBUG |
428 | //os::Debuginfo::print("added file from archive", ZipFileName.c_str()); | 428 | //os::Debuginfo::print("added file from archive", ZipFileName.c_str()); |
429 | #endif | 429 | #endif |
430 | 430 | ||
431 | addItem(ZipFileName, entry.Offset, entry.header.DataDescriptor.UncompressedSize, ZipFileName.lastChar()=='/', FileInfo.size()); | 431 | addItem(ZipFileName, entry.Offset, entry.header.DataDescriptor.UncompressedSize, ZipFileName.lastChar()=='/', FileInfo.size()); |
432 | FileInfo.push_back(entry); | 432 | FileInfo.push_back(entry); |
433 | 433 | ||
434 | return true; | 434 | return true; |
435 | } | 435 | } |
436 | 436 | ||
437 | 437 | ||
438 | //! scans for a local header, returns false if there is no more local file header. | 438 | //! scans for a local header, returns false if there is no more local file header. |
439 | bool CZipReader::scanCentralDirectoryHeader() | 439 | bool CZipReader::scanCentralDirectoryHeader() |
440 | { | 440 | { |
441 | io::path ZipFileName = ""; | 441 | io::path ZipFileName = ""; |
442 | SZIPFileCentralDirFileHeader entry; | 442 | SZIPFileCentralDirFileHeader entry; |
443 | File->read(&entry, sizeof(SZIPFileCentralDirFileHeader)); | 443 | File->read(&entry, sizeof(SZIPFileCentralDirFileHeader)); |
444 | 444 | ||
445 | #ifdef __BIG_ENDIAN__ | 445 | #ifdef __BIG_ENDIAN__ |
446 | entry.Sig = os::Byteswap::byteswap(entry.Sig); | 446 | entry.Sig = os::Byteswap::byteswap(entry.Sig); |
447 | entry.VersionMadeBy = os::Byteswap::byteswap(entry.VersionMadeBy); | 447 | entry.VersionMadeBy = os::Byteswap::byteswap(entry.VersionMadeBy); |
448 | entry.VersionToExtract = os::Byteswap::byteswap(entry.VersionToExtract); | 448 | entry.VersionToExtract = os::Byteswap::byteswap(entry.VersionToExtract); |
449 | entry.GeneralBitFlag = os::Byteswap::byteswap(entry.GeneralBitFlag); | 449 | entry.GeneralBitFlag = os::Byteswap::byteswap(entry.GeneralBitFlag); |
450 | entry.CompressionMethod = os::Byteswap::byteswap(entry.CompressionMethod); | 450 | entry.CompressionMethod = os::Byteswap::byteswap(entry.CompressionMethod); |
451 | entry.LastModFileTime = os::Byteswap::byteswap(entry.LastModFileTime); | 451 | entry.LastModFileTime = os::Byteswap::byteswap(entry.LastModFileTime); |
452 | entry.LastModFileDate = os::Byteswap::byteswap(entry.LastModFileDate); | 452 | entry.LastModFileDate = os::Byteswap::byteswap(entry.LastModFileDate); |
453 | entry.CRC32 = os::Byteswap::byteswap(entry.CRC32); | 453 | entry.CRC32 = os::Byteswap::byteswap(entry.CRC32); |
454 | entry.CompressedSize = os::Byteswap::byteswap(entry.CompressedSize); | 454 | entry.CompressedSize = os::Byteswap::byteswap(entry.CompressedSize); |
455 | entry.UncompressedSize = os::Byteswap::byteswap(entry.UncompressedSize); | 455 | entry.UncompressedSize = os::Byteswap::byteswap(entry.UncompressedSize); |
456 | entry.FilenameLength = os::Byteswap::byteswap(entry.FilenameLength); | 456 | entry.FilenameLength = os::Byteswap::byteswap(entry.FilenameLength); |
457 | entry.ExtraFieldLength = os::Byteswap::byteswap(entry.ExtraFieldLength); | 457 | entry.ExtraFieldLength = os::Byteswap::byteswap(entry.ExtraFieldLength); |
458 | entry.FileCommentLength = os::Byteswap::byteswap(entry.FileCommentLength); | 458 | entry.FileCommentLength = os::Byteswap::byteswap(entry.FileCommentLength); |
459 | entry.DiskNumberStart = os::Byteswap::byteswap(entry.DiskNumberStart); | 459 | entry.DiskNumberStart = os::Byteswap::byteswap(entry.DiskNumberStart); |
460 | entry.InternalFileAttributes = os::Byteswap::byteswap(entry.InternalFileAttributes); | 460 | entry.InternalFileAttributes = os::Byteswap::byteswap(entry.InternalFileAttributes); |
461 | entry.ExternalFileAttributes = os::Byteswap::byteswap(entry.ExternalFileAttributes); | 461 | entry.ExternalFileAttributes = os::Byteswap::byteswap(entry.ExternalFileAttributes); |
462 | entry.RelativeOffsetOfLocalHeader = os::Byteswap::byteswap(entry.RelativeOffsetOfLocalHeader); | 462 | entry.RelativeOffsetOfLocalHeader = os::Byteswap::byteswap(entry.RelativeOffsetOfLocalHeader); |
463 | #endif | 463 | #endif |
464 | 464 | ||
465 | if (entry.Sig != 0x02014b50) | 465 | if (entry.Sig != 0x02014b50) |
466 | return false; // central dir headers end here. | 466 | return false; // central dir headers end here. |
467 | 467 | ||
468 | const long pos = File->getPos(); | 468 | const long pos = File->getPos(); |
469 | File->seek(entry.RelativeOffsetOfLocalHeader); | 469 | File->seek(entry.RelativeOffsetOfLocalHeader); |
470 | scanZipHeader(true); | 470 | scanZipHeader(true); |
471 | File->seek(pos+entry.FilenameLength+entry.ExtraFieldLength+entry.FileCommentLength); | 471 | File->seek(pos+entry.FilenameLength+entry.ExtraFieldLength+entry.FileCommentLength); |
472 | FileInfo.getLast().header.DataDescriptor.CompressedSize=entry.CompressedSize; | 472 | FileInfo.getLast().header.DataDescriptor.CompressedSize=entry.CompressedSize; |
473 | FileInfo.getLast().header.DataDescriptor.UncompressedSize=entry.UncompressedSize; | 473 | FileInfo.getLast().header.DataDescriptor.UncompressedSize=entry.UncompressedSize; |
474 | FileInfo.getLast().header.DataDescriptor.CRC32=entry.CRC32; | 474 | FileInfo.getLast().header.DataDescriptor.CRC32=entry.CRC32; |
475 | Files.getLast().Size=entry.UncompressedSize; | 475 | Files.getLast().Size=entry.UncompressedSize; |
476 | return true; | 476 | return true; |
477 | } | 477 | } |
478 | 478 | ||
479 | 479 | ||
480 | //! opens a file by file name | 480 | //! opens a file by file name |
481 | IReadFile* CZipReader::createAndOpenFile(const io::path& filename) | 481 | IReadFile* CZipReader::createAndOpenFile(const io::path& filename) |
482 | { | 482 | { |
483 | s32 index = findFile(filename, false); | 483 | s32 index = findFile(filename, false); |
484 | 484 | ||
485 | if (index != -1) | 485 | if (index != -1) |
486 | return createAndOpenFile(index); | 486 | return createAndOpenFile(index); |
487 | 487 | ||
488 | return 0; | 488 | return 0; |
489 | } | 489 | } |
490 | 490 | ||
491 | #ifdef _IRR_COMPILE_WITH_LZMA_ | 491 | #ifdef _IRR_COMPILE_WITH_LZMA_ |
492 | //! Used for LZMA decompression. The lib has no default memory management | 492 | //! Used for LZMA decompression. The lib has no default memory management |
493 | namespace | 493 | namespace |
494 | { | 494 | { |
495 | void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } | 495 | void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } |
496 | void SzFree(void *p, void *address) { p = p; free(address); } | 496 | void SzFree(void *p, void *address) { p = p; free(address); } |
497 | ISzAlloc lzmaAlloc = { SzAlloc, SzFree }; | 497 | ISzAlloc lzmaAlloc = { SzAlloc, SzFree }; |
498 | } | 498 | } |
499 | #endif | 499 | #endif |
500 | 500 | ||
501 | //! opens a file by index | 501 | //! opens a file by index |
502 | IReadFile* CZipReader::createAndOpenFile(u32 index) | 502 | IReadFile* CZipReader::createAndOpenFile(u32 index) |
503 | { | 503 | { |
504 | // Irrlicht supports 0, 8, 12, 14, 99 | 504 | // Irrlicht supports 0, 8, 12, 14, 99 |
505 | //0 - The file is stored (no compression) | 505 | //0 - The file is stored (no compression) |
506 | //1 - The file is Shrunk | 506 | //1 - The file is Shrunk |
507 | //2 - The file is Reduced with compression factor 1 | 507 | //2 - The file is Reduced with compression factor 1 |
508 | //3 - The file is Reduced with compression factor 2 | 508 | //3 - The file is Reduced with compression factor 2 |
509 | //4 - The file is Reduced with compression factor 3 | 509 | //4 - The file is Reduced with compression factor 3 |
510 | //5 - The file is Reduced with compression factor 4 | 510 | //5 - The file is Reduced with compression factor 4 |
511 | //6 - The file is Imploded | 511 | //6 - The file is Imploded |
512 | //7 - Reserved for Tokenizing compression algorithm | 512 | //7 - Reserved for Tokenizing compression algorithm |
513 | //8 - The file is Deflated | 513 | //8 - The file is Deflated |
514 | //9 - Reserved for enhanced Deflating | 514 | //9 - Reserved for enhanced Deflating |
515 | //10 - PKWARE Date Compression Library Imploding | 515 | //10 - PKWARE Date Compression Library Imploding |
516 | //12 - bzip2 - Compression Method from libbz2, WinZip 10 | 516 | //12 - bzip2 - Compression Method from libbz2, WinZip 10 |
517 | //14 - LZMA - Compression Method, WinZip 12 | 517 | //14 - LZMA - Compression Method, WinZip 12 |
518 | //96 - Jpeg compression - Compression Method, WinZip 12 | 518 | //96 - Jpeg compression - Compression Method, WinZip 12 |
519 | //97 - WavPack - Compression Method, WinZip 11 | 519 | //97 - WavPack - Compression Method, WinZip 11 |
520 | //98 - PPMd - Compression Method, WinZip 10 | 520 | //98 - PPMd - Compression Method, WinZip 10 |
521 | //99 - AES encryption, WinZip 9 | 521 | //99 - AES encryption, WinZip 9 |
522 | 522 | ||
523 | const SZipFileEntry &e = FileInfo[Files[index].ID]; | 523 | const SZipFileEntry &e = FileInfo[Files[index].ID]; |
524 | wchar_t buf[64]; | 524 | wchar_t buf[64]; |
525 | s16 actualCompressionMethod=e.header.CompressionMethod; | 525 | s16 actualCompressionMethod=e.header.CompressionMethod; |
526 | IReadFile* decrypted=0; | 526 | IReadFile* decrypted=0; |
527 | u8* decryptedBuf=0; | 527 | u8* decryptedBuf=0; |
528 | u32 decryptedSize=e.header.DataDescriptor.CompressedSize; | 528 | u32 decryptedSize=e.header.DataDescriptor.CompressedSize; |
529 | #ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ | 529 | #ifdef _IRR_COMPILE_WITH_ZIP_ENCRYPTION_ |
530 | if ((e.header.GeneralBitFlag & ZIP_FILE_ENCRYPTED) && (e.header.CompressionMethod == 99)) | 530 | if ((e.header.GeneralBitFlag & ZIP_FILE_ENCRYPTED) && (e.header.CompressionMethod == 99)) |
531 | { | 531 | { |
532 | os::Printer::log("Reading encrypted file."); | 532 | os::Printer::log("Reading encrypted file."); |
533 | u8 salt[16]={0}; | 533 | u8 salt[16]={0}; |
534 | const u16 saltSize = (((e.header.Sig & 0x00ff0000) >>16)+1)*4; | 534 | const u16 saltSize = (((e.header.Sig & 0x00ff0000) >>16)+1)*4; |
535 | File->seek(e.Offset); | 535 | File->seek(e.Offset); |
536 | File->read(salt, saltSize); | 536 | File->read(salt, saltSize); |
537 | char pwVerification[2]; | 537 | char pwVerification[2]; |
538 | char pwVerificationFile[2]; | 538 | char pwVerificationFile[2]; |
539 | File->read(pwVerification, 2); | 539 | File->read(pwVerification, 2); |
540 | fcrypt_ctx zctx; // the encryption context | 540 | fcrypt_ctx zctx; // the encryption context |
541 | int rc = fcrypt_init( | 541 | int rc = fcrypt_init( |
542 | (e.header.Sig & 0x00ff0000) >>16, | 542 | (e.header.Sig & 0x00ff0000) >>16, |
543 | (const unsigned char*)Password.c_str(), // the password | 543 | (const unsigned char*)Password.c_str(), // the password |
544 | Password.size(), // number of bytes in password | 544 | Password.size(), // number of bytes in password |
545 | salt, // the salt | 545 | salt, // the salt |
546 | (unsigned char*)pwVerificationFile, // on return contains password verifier | 546 | (unsigned char*)pwVerificationFile, // on return contains password verifier |
547 | &zctx); // encryption context | 547 | &zctx); // encryption context |
548 | if (strncmp(pwVerificationFile, pwVerification, 2)) | 548 | if (strncmp(pwVerificationFile, pwVerification, 2)) |
549 | { | 549 | { |
550 | os::Printer::log("Wrong password"); | 550 | os::Printer::log("Wrong password"); |
551 | return 0; | 551 | return 0; |
552 | } | 552 | } |
553 | decryptedSize= e.header.DataDescriptor.CompressedSize-saltSize-12; | 553 | decryptedSize= e.header.DataDescriptor.CompressedSize-saltSize-12; |
554 | decryptedBuf= new u8[decryptedSize]; | 554 | decryptedBuf= new u8[decryptedSize]; |
555 | u32 c = 0; | 555 | u32 c = 0; |
556 | while ((c+32768)<=decryptedSize) | 556 | while ((c+32768)<=decryptedSize) |
557 | { | 557 | { |
558 | File->read(decryptedBuf+c, 32768); | 558 | File->read(decryptedBuf+c, 32768); |
559 | fcrypt_decrypt( | 559 | fcrypt_decrypt( |
560 | decryptedBuf+c, // pointer to the data to decrypt | 560 | decryptedBuf+c, // pointer to the data to decrypt |
561 | 32768, // how many bytes to decrypt | 561 | 32768, // how many bytes to decrypt |
562 | &zctx); // decryption context | 562 | &zctx); // decryption context |
563 | c+=32768; | 563 | c+=32768; |
564 | } | 564 | } |
565 | File->read(decryptedBuf+c, decryptedSize-c); | 565 | File->read(decryptedBuf+c, decryptedSize-c); |
566 | fcrypt_decrypt( | 566 | fcrypt_decrypt( |
567 | decryptedBuf+c, // pointer to the data to decrypt | 567 | decryptedBuf+c, // pointer to the data to decrypt |
568 | decryptedSize-c, // how many bytes to decrypt | 568 | decryptedSize-c, // how many bytes to decrypt |
569 | &zctx); // decryption context | 569 | &zctx); // decryption context |
570 | 570 | ||
571 | char fileMAC[10]; | 571 | char fileMAC[10]; |
572 | char resMAC[10]; | 572 | char resMAC[10]; |
573 | rc = fcrypt_end( | 573 | rc = fcrypt_end( |
574 | (unsigned char*)resMAC, // on return contains the authentication code | 574 | (unsigned char*)resMAC, // on return contains the authentication code |
575 | &zctx); // encryption context | 575 | &zctx); // encryption context |
576 | if (rc != 10) | 576 | if (rc != 10) |
577 | { | 577 | { |
578 | os::Printer::log("Error on encryption closing"); | 578 | os::Printer::log("Error on encryption closing"); |
579 | delete [] decryptedBuf; | 579 | delete [] decryptedBuf; |
580 | return 0; | 580 | return 0; |
581 | } | 581 | } |
582 | File->read(fileMAC, 10); | 582 | File->read(fileMAC, 10); |
583 | if (strncmp(fileMAC, resMAC, 10)) | 583 | if (strncmp(fileMAC, resMAC, 10)) |
584 | { | 584 | { |
585 | os::Printer::log("Error on encryption check"); | 585 | os::Printer::log("Error on encryption check"); |
586 | delete [] decryptedBuf; | 586 | delete [] decryptedBuf; |
587 | return 0; | 587 | return 0; |
588 | } | 588 | } |
589 | decrypted = io::createMemoryReadFile(decryptedBuf, decryptedSize, Files[index].FullName, true); | 589 | decrypted = io::createMemoryReadFile(decryptedBuf, decryptedSize, Files[index].FullName, true); |
590 | actualCompressionMethod = (e.header.Sig & 0xffff); | 590 | actualCompressionMethod = (e.header.Sig & 0xffff); |
591 | #if 0 | 591 | #if 0 |
592 | if ((e.header.Sig & 0xff000000)==0x01000000) | 592 | if ((e.header.Sig & 0xff000000)==0x01000000) |
593 | { | 593 | { |
594 | } | 594 | } |
595 | else if ((e.header.Sig & 0xff000000)==0x02000000) | 595 | else if ((e.header.Sig & 0xff000000)==0x02000000) |
596 | { | 596 | { |
597 | } | 597 | } |
598 | else | 598 | else |
599 | { | 599 | { |
600 | os::Printer::log("Unknown encryption method"); | 600 | os::Printer::log("Unknown encryption method"); |
601 | return 0; | 601 | return 0; |
602 | } | 602 | } |
603 | #endif | 603 | #endif |
604 | } | 604 | } |
605 | #endif | 605 | #endif |
606 | switch(actualCompressionMethod) | 606 | switch(actualCompressionMethod) |
607 | { | 607 | { |
608 | case 0: // no compression | 608 | case 0: // no compression |
609 | { | 609 | { |
610 | if (decrypted) | 610 | if (decrypted) |
611 | return decrypted; | 611 | return decrypted; |
612 | else | 612 | else |
613 | return createLimitReadFile(Files[index].FullName, File, e.Offset, decryptedSize); | 613 | return createLimitReadFile(Files[index].FullName, File, e.Offset, decryptedSize); |
614 | } | 614 | } |
615 | case 8: | 615 | case 8: |
616 | { | 616 | { |
617 | #ifdef _IRR_COMPILE_WITH_ZLIB_ | 617 | #ifdef _IRR_COMPILE_WITH_ZLIB_ |
618 | 618 | ||
619 | const u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize; | 619 | const u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize; |
620 | c8* pBuf = new c8[ uncompressedSize ]; | 620 | c8* pBuf = new c8[ uncompressedSize ]; |
621 | if (!pBuf) | 621 | if (!pBuf) |
622 | { | 622 | { |
623 | swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); | 623 | swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); |
624 | os::Printer::log( buf, ELL_ERROR); | 624 | os::Printer::log( buf, ELL_ERROR); |
625 | if (decrypted) | 625 | if (decrypted) |
626 | decrypted->drop(); | 626 | decrypted->drop(); |
627 | return 0; | 627 | return 0; |
628 | } | 628 | } |
629 | 629 | ||
630 | u8 *pcData = decryptedBuf; | 630 | u8 *pcData = decryptedBuf; |
631 | if (!pcData) | 631 | if (!pcData) |
632 | { | 632 | { |
633 | pcData = new u8[decryptedSize]; | 633 | pcData = new u8[decryptedSize]; |
634 | if (!pcData) | 634 | if (!pcData) |
635 | { | 635 | { |
636 | swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); | 636 | swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); |
637 | os::Printer::log( buf, ELL_ERROR); | 637 | os::Printer::log( buf, ELL_ERROR); |
638 | delete [] pBuf; | 638 | delete [] pBuf; |
639 | return 0; | 639 | return 0; |
640 | } | 640 | } |
641 | 641 | ||
642 | //memset(pcData, 0, decryptedSize); | 642 | //memset(pcData, 0, decryptedSize); |
643 | File->seek(e.Offset); | 643 | File->seek(e.Offset); |
644 | File->read(pcData, decryptedSize); | 644 | File->read(pcData, decryptedSize); |
645 | } | 645 | } |
646 | 646 | ||
647 | // Setup the inflate stream. | 647 | // Setup the inflate stream. |
648 | z_stream stream; | 648 | z_stream stream; |
649 | s32 err; | 649 | s32 err; |
650 | 650 | ||
651 | stream.next_in = (Bytef*)pcData; | 651 | stream.next_in = (Bytef*)pcData; |
652 | stream.avail_in = (uInt)decryptedSize; | 652 | stream.avail_in = (uInt)decryptedSize; |
653 | stream.next_out = (Bytef*)pBuf; | 653 | stream.next_out = (Bytef*)pBuf; |
654 | stream.avail_out = uncompressedSize; | 654 | stream.avail_out = uncompressedSize; |
655 | stream.zalloc = (alloc_func)0; | 655 | stream.zalloc = (alloc_func)0; |
656 | stream.zfree = (free_func)0; | 656 | stream.zfree = (free_func)0; |
657 | 657 | ||
658 | // Perform inflation. wbits < 0 indicates no zlib header inside the data. | 658 | // Perform inflation. wbits < 0 indicates no zlib header inside the data. |
659 | err = inflateInit2(&stream, -MAX_WBITS); | 659 | err = inflateInit2(&stream, -MAX_WBITS); |
660 | if (err == Z_OK) | 660 | if (err == Z_OK) |
661 | { | 661 | { |
662 | err = inflate(&stream, Z_FINISH); | 662 | err = inflate(&stream, Z_FINISH); |
663 | inflateEnd(&stream); | 663 | inflateEnd(&stream); |
664 | if (err == Z_STREAM_END) | 664 | if (err == Z_STREAM_END) |
665 | err = Z_OK; | 665 | err = Z_OK; |
666 | err = Z_OK; | 666 | err = Z_OK; |
667 | inflateEnd(&stream); | 667 | inflateEnd(&stream); |
668 | } | 668 | } |
669 | 669 | ||
670 | if (decrypted) | 670 | if (decrypted) |
671 | decrypted->drop(); | 671 | decrypted->drop(); |
672 | else | 672 | else |
673 | delete[] pcData; | 673 | delete[] pcData; |
674 | 674 | ||
675 | if (err != Z_OK) | 675 | if (err != Z_OK) |
676 | { | 676 | { |
677 | swprintf ( buf, 64, L"Error decompressing %s", Files[index].FullName.c_str() ); | 677 | swprintf ( buf, 64, L"Error decompressing %s", Files[index].FullName.c_str() ); |
678 | os::Printer::log( buf, ELL_ERROR); | 678 | os::Printer::log( buf, ELL_ERROR); |
679 | delete [] pBuf; | 679 | delete [] pBuf; |
680 | return 0; | 680 | return 0; |
681 | } | 681 | } |
682 | else | 682 | else |
683 | return io::createMemoryReadFile(pBuf, uncompressedSize, Files[index].FullName, true); | 683 | return io::createMemoryReadFile(pBuf, uncompressedSize, Files[index].FullName, true); |
684 | 684 | ||
685 | #else | 685 | #else |
686 | return 0; // zlib not compiled, we cannot decompress the data. | 686 | return 0; // zlib not compiled, we cannot decompress the data. |
687 | #endif | 687 | #endif |
688 | } | 688 | } |
689 | case 12: | 689 | case 12: |
690 | { | 690 | { |
691 | #ifdef _IRR_COMPILE_WITH_BZIP2_ | 691 | #ifdef _IRR_COMPILE_WITH_BZIP2_ |
692 | 692 | ||
693 | const u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize; | 693 | const u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize; |
694 | c8* pBuf = new c8[ uncompressedSize ]; | 694 | c8* pBuf = new c8[ uncompressedSize ]; |
695 | if (!pBuf) | 695 | if (!pBuf) |
696 | { | 696 | { |
697 | swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); | 697 | swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); |
698 | os::Printer::log( buf, ELL_ERROR); | 698 | os::Printer::log( buf, ELL_ERROR); |
699 | if (decrypted) | 699 | if (decrypted) |
700 | decrypted->drop(); | 700 | decrypted->drop(); |
701 | return 0; | 701 | return 0; |
702 | } | 702 | } |
703 | 703 | ||
704 | u8 *pcData = decryptedBuf; | 704 | u8 *pcData = decryptedBuf; |
705 | if (!pcData) | 705 | if (!pcData) |
706 | { | 706 | { |
707 | pcData = new u8[decryptedSize]; | 707 | pcData = new u8[decryptedSize]; |
708 | if (!pcData) | 708 | if (!pcData) |
709 | { | 709 | { |
710 | swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); | 710 | swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); |
711 | os::Printer::log( buf, ELL_ERROR); | 711 | os::Printer::log( buf, ELL_ERROR); |
712 | delete [] pBuf; | 712 | delete [] pBuf; |
713 | return 0; | 713 | return 0; |
714 | } | 714 | } |
715 | 715 | ||
716 | //memset(pcData, 0, decryptedSize); | 716 | //memset(pcData, 0, decryptedSize); |
717 | File->seek(e.Offset); | 717 | File->seek(e.Offset); |
718 | File->read(pcData, decryptedSize); | 718 | File->read(pcData, decryptedSize); |
719 | } | 719 | } |
720 | 720 | ||
721 | bz_stream bz_ctx={0}; | 721 | bz_stream bz_ctx={0}; |
722 | /* use BZIP2's default memory allocation | 722 | /* use BZIP2's default memory allocation |
723 | bz_ctx->bzalloc = NULL; | 723 | bz_ctx->bzalloc = NULL; |
724 | bz_ctx->bzfree = NULL; | 724 | bz_ctx->bzfree = NULL; |
725 | bz_ctx->opaque = NULL; | 725 | bz_ctx->opaque = NULL; |
726 | */ | 726 | */ |
727 | int err = BZ2_bzDecompressInit(&bz_ctx, 0, 0); /* decompression */ | 727 | int err = BZ2_bzDecompressInit(&bz_ctx, 0, 0); /* decompression */ |
728 | if(err != BZ_OK) | 728 | if(err != BZ_OK) |
729 | { | 729 | { |
730 | os::Printer::log("bzip2 decompression failed. File cannot be read.", ELL_ERROR); | 730 | os::Printer::log("bzip2 decompression failed. File cannot be read.", ELL_ERROR); |
731 | return 0; | 731 | return 0; |
732 | } | 732 | } |
733 | bz_ctx.next_in = (char*)pcData; | 733 | bz_ctx.next_in = (char*)pcData; |
734 | bz_ctx.avail_in = decryptedSize; | 734 | bz_ctx.avail_in = decryptedSize; |
735 | /* pass all input to decompressor */ | 735 | /* pass all input to decompressor */ |
736 | bz_ctx.next_out = pBuf; | 736 | bz_ctx.next_out = pBuf; |
737 | bz_ctx.avail_out = uncompressedSize; | 737 | bz_ctx.avail_out = uncompressedSize; |
738 | err = BZ2_bzDecompress(&bz_ctx); | 738 | err = BZ2_bzDecompress(&bz_ctx); |
739 | err = BZ2_bzDecompressEnd(&bz_ctx); | 739 | err = BZ2_bzDecompressEnd(&bz_ctx); |
740 | 740 | ||
741 | if (decrypted) | 741 | if (decrypted) |
742 | decrypted->drop(); | 742 | decrypted->drop(); |
743 | else | 743 | else |
744 | delete[] pcData; | 744 | delete[] pcData; |
745 | 745 | ||
746 | if (err != BZ_OK) | 746 | if (err != BZ_OK) |
747 | { | 747 | { |
748 | swprintf ( buf, 64, L"Error decompressing %s", Files[index].FullName.c_str() ); | 748 | swprintf ( buf, 64, L"Error decompressing %s", Files[index].FullName.c_str() ); |
749 | os::Printer::log( buf, ELL_ERROR); | 749 | os::Printer::log( buf, ELL_ERROR); |
750 | delete [] pBuf; | 750 | delete [] pBuf; |
751 | return 0; | 751 | return 0; |
752 | } | 752 | } |
753 | else | 753 | else |
754 | return io::createMemoryReadFile(pBuf, uncompressedSize, Files[index].FullName, true); | 754 | return io::createMemoryReadFile(pBuf, uncompressedSize, Files[index].FullName, true); |
755 | 755 | ||
756 | #else | 756 | #else |
757 | os::Printer::log("bzip2 decompression not supported. File cannot be read.", ELL_ERROR); | 757 | os::Printer::log("bzip2 decompression not supported. File cannot be read.", ELL_ERROR); |
758 | return 0; | 758 | return 0; |
759 | #endif | 759 | #endif |
760 | } | 760 | } |
761 | case 14: | 761 | case 14: |
762 | { | 762 | { |
763 | #ifdef _IRR_COMPILE_WITH_LZMA_ | 763 | #ifdef _IRR_COMPILE_WITH_LZMA_ |
764 | 764 | ||
765 | u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize; | 765 | u32 uncompressedSize = e.header.DataDescriptor.UncompressedSize; |
766 | c8* pBuf = new c8[ uncompressedSize ]; | 766 | c8* pBuf = new c8[ uncompressedSize ]; |
767 | if (!pBuf) | 767 | if (!pBuf) |
768 | { | 768 | { |
769 | swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); | 769 | swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); |
770 | os::Printer::log( buf, ELL_ERROR); | 770 | os::Printer::log( buf, ELL_ERROR); |
771 | if (decrypted) | 771 | if (decrypted) |
772 | decrypted->drop(); | 772 | decrypted->drop(); |
773 | return 0; | 773 | return 0; |
774 | } | 774 | } |
775 | 775 | ||
776 | u8 *pcData = decryptedBuf; | 776 | u8 *pcData = decryptedBuf; |
777 | if (!pcData) | 777 | if (!pcData) |
778 | { | 778 | { |
779 | pcData = new u8[decryptedSize]; | 779 | pcData = new u8[decryptedSize]; |
780 | if (!pcData) | 780 | if (!pcData) |
781 | { | 781 | { |
782 | swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); | 782 | swprintf ( buf, 64, L"Not enough memory for decompressing %s", Files[index].FullName.c_str() ); |
783 | os::Printer::log( buf, ELL_ERROR); | 783 | os::Printer::log( buf, ELL_ERROR); |
784 | delete [] pBuf; | 784 | delete [] pBuf; |
785 | return 0; | 785 | return 0; |
786 | } | 786 | } |
787 | 787 | ||
788 | //memset(pcData, 0, decryptedSize); | 788 | //memset(pcData, 0, decryptedSize); |
789 | File->seek(e.Offset); | 789 | File->seek(e.Offset); |
790 | File->read(pcData, decryptedSize); | 790 | File->read(pcData, decryptedSize); |
791 | } | 791 | } |
792 | 792 | ||
793 | ELzmaStatus status; | 793 | ELzmaStatus status; |
794 | SizeT tmpDstSize = uncompressedSize; | 794 | SizeT tmpDstSize = uncompressedSize; |
795 | SizeT tmpSrcSize = decryptedSize; | 795 | SizeT tmpSrcSize = decryptedSize; |
796 | 796 | ||
797 | unsigned int propSize = (pcData[3]<<8)+pcData[2]; | 797 | unsigned int propSize = (pcData[3]<<8)+pcData[2]; |
798 | int err = LzmaDecode((Byte*)pBuf, &tmpDstSize, | 798 | int err = LzmaDecode((Byte*)pBuf, &tmpDstSize, |
799 | pcData+4+propSize, &tmpSrcSize, | 799 | pcData+4+propSize, &tmpSrcSize, |
800 | pcData+4, propSize, | 800 | pcData+4, propSize, |
801 | e.header.GeneralBitFlag&0x1?LZMA_FINISH_END:LZMA_FINISH_ANY, &status, | 801 | e.header.GeneralBitFlag&0x1?LZMA_FINISH_END:LZMA_FINISH_ANY, &status, |
802 | &lzmaAlloc); | 802 | &lzmaAlloc); |
803 | uncompressedSize = tmpDstSize; // may be different to expected value | 803 | uncompressedSize = tmpDstSize; // may be different to expected value |
804 | 804 | ||
805 | if (decrypted) | 805 | if (decrypted) |
806 | decrypted->drop(); | 806 | decrypted->drop(); |
807 | else | 807 | else |
808 | delete[] pcData; | 808 | delete[] pcData; |
809 | 809 | ||
810 | if (err != SZ_OK) | 810 | if (err != SZ_OK) |
811 | { | 811 | { |
812 | os::Printer::log( "Error decompressing", Files[index].FullName, ELL_ERROR); | 812 | os::Printer::log( "Error decompressing", Files[index].FullName, ELL_ERROR); |
813 | delete [] pBuf; | 813 | delete [] pBuf; |
814 | return 0; | 814 | return 0; |
815 | } | 815 | } |
816 | else | 816 | else |
817 | return io::createMemoryReadFile(pBuf, uncompressedSize, Files[index].FullName, true); | 817 | return io::createMemoryReadFile(pBuf, uncompressedSize, Files[index].FullName, true); |
818 | 818 | ||
819 | #else | 819 | #else |
820 | os::Printer::log("lzma decompression not supported. File cannot be read.", ELL_ERROR); | 820 | os::Printer::log("lzma decompression not supported. File cannot be read.", ELL_ERROR); |
821 | return 0; | 821 | return 0; |
822 | #endif | 822 | #endif |
823 | } | 823 | } |
824 | case 99: | 824 | case 99: |
825 | // If we come here with an encrypted file, decryption support is missing | 825 | // If we come here with an encrypted file, decryption support is missing |
826 | os::Printer::log("Decryption support not enabled. File cannot be read.", ELL_ERROR); | 826 | os::Printer::log("Decryption support not enabled. File cannot be read.", ELL_ERROR); |
827 | return 0; | 827 | return 0; |
828 | default: | 828 | default: |
829 | swprintf ( buf, 64, L"file has unsupported compression method. %s", Files[index].FullName.c_str() ); | 829 | swprintf ( buf, 64, L"file has unsupported compression method. %s", Files[index].FullName.c_str() ); |
830 | os::Printer::log( buf, ELL_ERROR); | 830 | os::Printer::log( buf, ELL_ERROR); |
831 | return 0; | 831 | return 0; |
832 | }; | 832 | }; |
833 | 833 | ||
834 | } | 834 | } |
835 | 835 | ||
836 | } // end namespace io | 836 | } // end namespace io |
837 | } // end namespace irr | 837 | } // end namespace irr |
838 | 838 | ||
839 | #endif // __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ | 839 | #endif // __IRR_COMPILE_WITH_ZIP_ARCHIVE_LOADER_ |