aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/CZipReader.cpp
diff options
context:
space:
mode:
authorDavid Walter Seikel2013-01-13 18:54:10 +1000
committerDavid Walter Seikel2013-01-13 18:54:10 +1000
commit959831f4ef5a3e797f576c3de08cd65032c997ad (patch)
treee7351908be5995f0b325b2ebeaa02d5a34b82583 /libraries/irrlicht-1.8/source/Irrlicht/CZipReader.cpp
parentAdd info about changes to Irrlicht. (diff)
downloadSledjHamr-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 'libraries/irrlicht-1.8/source/Irrlicht/CZipReader.cpp')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/CZipReader.cpp1678
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.
10extern "C" void bz_internal_error(int errorCode) 10extern "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
44namespace irr 44namespace irr
45{ 45{
46namespace io 46namespace io
47{ 47{
48 48
49 49
50// ----------------------------------------------------------------------------- 50// -----------------------------------------------------------------------------
51// zip loader 51// zip loader
52// ----------------------------------------------------------------------------- 52// -----------------------------------------------------------------------------
53 53
54//! Constructor 54//! Constructor
55CArchiveLoaderZIP::CArchiveLoaderZIP(io::IFileSystem* fs) 55CArchiveLoaderZIP::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
64bool CArchiveLoaderZIP::isALoadableFileFormat(const io::path& filename) const 64bool 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.
71bool CArchiveLoaderZIP::isALoadableFileFormat(E_FILE_ARCHIVE_TYPE fileType) const 71bool 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. */
80IFileArchive* CArchiveLoaderZIP::createArchive(const io::path& filename, bool ignoreCase, bool ignorePaths) const 80IFileArchive* 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.
96IFileArchive* CArchiveLoaderZIP::createArchive(io::IReadFile* file, bool ignoreCase, bool ignorePaths) const 96IFileArchive* 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. */
123bool CArchiveLoaderZIP::isALoadableFileFormat(io::IReadFile* file) const 123bool 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
140CZipReader::CZipReader(IReadFile* file, bool ignoreCase, bool ignorePaths, bool isGZip) 140CZipReader::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
161CZipReader::~CZipReader() 161CZipReader::~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
169E_FILE_ARCHIVE_TYPE CZipReader::getType() const 169E_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
174const IFileList* CZipReader::getFileList() const 174const 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
183bool CZipReader::scanGZipHeader() 183bool 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.
291bool CZipReader::scanZipHeader(bool ignoreGPBits) 291bool 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.
439bool CZipReader::scanCentralDirectoryHeader() 439bool 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
481IReadFile* CZipReader::createAndOpenFile(const io::path& filename) 481IReadFile* 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
493namespace 493namespace
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
502IReadFile* CZipReader::createAndOpenFile(u32 index) 502IReadFile* 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_