1 #include "bzip2/bzlib.h"
2 #include "UnAlz.h"
3
4 #ifdef _WIN32
5 # include "zlib/zlib.h"
6 #else
7 # include <zlib.h>
8 #endif
9
10
11 #ifdef _WIN32
12 # pragma warning( disable : 4996 ) // crt secure warning
13 #endif
14
15 // utime
16 #if defined(_WIN32) || defined(__CYGWIN__)
17 # include <time.h>
18 # include <sys/utime.h>
19 #endif
20 #ifdef __GNUC__
21 # include <time.h>
22 # include <utime.h>
23 #endif
24
25 // mkdir
26 #ifdef _WIN32
27 # include <direct.h>
28 #else
29 # include <sys/stat.h>
30 #endif
31
32 #ifdef _UNALZ_ICONV // code page support
33 # include <iconv.h>
34 #endif
35
36 #if defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) || defined(__APPLE__)
37 # include <errno.h>
38 #endif
39
40 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
41 # include <sys/param.h> // __NetBSD_Version__
42 # include <errno.h> // iconv.h
43 #endif
44
45 #ifdef _WIN32 // safe string
46 # include <strsafe.h>
47 #endif
48
49
50 // ENDIAN
51 #ifdef _WIN32 // (L)
52 # define swapint64(a) (UINT64) ( (((a)&0x00000000000000FFL) << 56) | (((a)&0x000000000000FF00L) << 40) | (((a)&0x0000000000FF0000L) << 24) | (((a)&0x00000000FF000000L) << 8) | (((a)&0x000000FF00000000L) >> 8) | (((a)&0x0000FF0000000000L) >> 24) | (((a)&0x00FF000000000000L) >> 40) | (((a)&0xFF00000000000000L) >> 56) )
53 #else // (LL)
54 # define swapint64(a) (UINT64) ( (((a)&0x00000000000000FFLL) << 56) | (((a)&0x000000000000FF00LL) << 40) | (((a)&0x0000000000FF0000LL) << 24) | (((a)&0x00000000FF000000LL) << 8) | (((a)&0x000000FF00000000LL) >> 8) | (((a)&0x0000FF0000000000LL) >> 24) | (((a)&0x00FF000000000000LL) >> 40) | (((a)&0xFF00000000000000LL) >> 56) )
55 #endif
56 #define swapint32(a) ((((a)&0xff)<<24)+(((a>>8)&0xff)<<16)+(((a>>16)&0xff)<<8)+(((a>>24)&0xff)))
57 #define swapint16(a) (((a)&0xff)<<8)+(((a>>8)&0xff))
58
59 typedef UINT16 (*_unalz_le16toh)(UINT16 a);
60 typedef UINT32 (*_unalz_le32toh)(UINT32 a);
61 typedef UINT64 (*_unalz_le64toh)(UINT64 a);
62
63 static _unalz_le16toh unalz_le16toh=NULL;
64 static _unalz_le32toh unalz_le32toh=NULL;
65 static _unalz_le64toh unalz_le64toh=NULL;
66
le16tole(UINT16 a)67 static UINT16 le16tole(UINT16 a){return a;}
le32tole(UINT32 a)68 static UINT32 le32tole(UINT32 a){return a;}
le64tole(UINT64 a)69 static UINT64 le64tole(UINT64 a){return a;}
le16tobe(UINT16 a)70 static UINT16 le16tobe(UINT16 a){return swapint16(a);}
le32tobe(UINT32 a)71 static UINT32 le32tobe(UINT32 a){return swapint32(a);}
le64tobe(UINT64 a)72 static UINT64 le64tobe(UINT64 a){return swapint64(a);}
73
74
75 #ifndef MAX_PATH
76 # define MAX_PATH 260*6 //
77 #endif
78
79 #ifdef _WIN32
80 # define PATHSEP "\\"
81 # define PATHSEPC '\\'
82 #else
83 # define PATHSEP "/"
84 # define PATHSEPC '/'
85 #endif
86
dosTime2TimeT(UINT32 dostime)87 static time_t dosTime2TimeT(UINT32 dostime) // from INFO-ZIP src
88 {
89 struct tm t;
90 t.tm_isdst = -1;
91 t.tm_sec = (((int)dostime) << 1) & 0x3e;
92 t.tm_min = (((int)dostime) >> 5) & 0x3f;
93 t.tm_hour = (((int)dostime) >> 11) & 0x1f;
94 t.tm_mday = (int)(dostime >> 16) & 0x1f;
95 t.tm_mon = ((int)(dostime >> 21) & 0x0f) - 1;
96 t.tm_year = ((int)(dostime >> 25) & 0x7f) + 80;
97 return mktime(&t);
98 }
99
IsBigEndian(void)100 static BOOL IsBigEndian(void)
101 {
102 union {
103 short a;
104 char b[2];
105 } endian;
106
107 endian.a = 0x0102;
108 if(endian.b[0] == 0x02) return FALSE;
109 return TRUE;
110 }
111
112
113 #ifdef _WIN32
114 # define safe_sprintf StringCbPrintfA
115 #else
116 # define safe_sprintf snprintf
117 #endif
118
119
120 // 64bit file handling support
121 #if (_FILE_OFFSET_BITS==64)
122 # define unalz_fseek fseeko
123 # define unalz_ftell ftello
124 #else
125 # define unalz_fseek fseek
126 # define unalz_ftell ftell
127 #endif
128
129 // error string table <- CUnAlz::ERR
130 static const char* errorstrtable[]=
131 {
132 "no error", // ERR_NOERR
133 "general error", // ERR_GENERAL
134 "can't open archive file", // ERR_CANT_OPEN_FILE
135 "can't open dest file or path", // ERR_CANT_OPEN_DEST_FILE
136 // "can't create dest path", // ERR_CANT_CREATE_DEST_PATH
137 "corrupted file", // ERR_CORRUPTED_FILE
138 "not alz file", // ERR_NOT_ALZ_FILE
139 "can't read signature", // ERR_CANT_READ_SIG
140 "can't read file", // ERR_CANT_READ_FILE
141 "error at read header", // ERR_AT_READ_HEADER
142 "invalid filename length", // ERR_INVALID_FILENAME_LENGTH
143 "invalid extrafield length", // ERR_INVALID_EXTRAFIELD_LENGTH,
144 "can't read central directory structure head", // ERR_CANT_READ_CENTRAL_DIRECTORY_STRUCTURE_HEAD,
145 "invalid filename size", // ERR_INVALID_FILENAME_SIZE,
146 "invalid extrafield size", // ERR_INVALID_EXTRAFIELD_SIZE,
147 "invalid filecomment size", // ERR_INVALID_FILECOMMENT_SIZE,
148 "cant' read header", // ERR_CANT_READ_HEADER,
149 "memory allocation failed", // ERR_MEM_ALLOC_FAILED,
150 "file read error", // ERR_FILE_READ_ERROR,
151 "inflate failed", // ERR_INFLATE_FAILED,
152 "bzip2 decompress failed", // ERR_BZIP2_FAILED,
153 "invalid file CRC", // ERR_INVALID_FILE_CRC
154 "unknown compression method", // ERR_UNKNOWN_COMPRESSION_METHOD
155 "iconv-can't open iconv", // ERR_ICONV_CANT_OPEN,
156 "iconv-invalid multisequence of characters", // ERR_ICONV_INVALID_MULTISEQUENCE_OF_CHARACTERS,
157 "iconv-incomplete multibyte sequence", // ERR_ICONV_INCOMPLETE_MULTIBYTE_SEQUENCE,
158 "iconv-not enough space of buffer to convert", // ERR_ICONV_NOT_ENOUGH_SPACE_OF_BUFFER_TO_CONVERT,
159 "iconv-etc", // ERR_ICONV_ETC,
160 "password was not set", // ERR_PASSWD_NOT_SET,
161 "invalid password", // ERR_INVALID_PASSWD,
162 "user aborted",
163 };
164
165 ////////////////////////////////////////////////////////////////////////////////////////////////////
166 // ctor
167 // @date 2004-03-06 ¿ÀÈÄ 11:19:49
168 ////////////////////////////////////////////////////////////////////////////////////////////////////
CUnAlz()169 CUnAlz::CUnAlz()
170 {
171 memset(m_files, 0, sizeof(m_files));
172 m_nErr = ERR_NOERR;
173 m_posCur = m_fileList.end();//(FileList::iterator)NULL;
174 m_pFuncCallBack = NULL;
175 m_pCallbackParam = NULL;
176 m_bHalt = FALSE;
177 m_nFileCount = 0;
178 m_nCurFile = -1;
179 m_nVirtualFilePos = 0;
180 m_nCurFilePos = 0;
181 m_bIsEOF = FALSE;
182 m_bIsEncrypted = FALSE;
183 m_bIsDataDescr = FALSE;
184 m_bPipeMode = FALSE;
185
186 #ifdef _UNALZ_ICONV
187
188 #ifdef _UNALZ_UTF8
189 safe_strcpy(m_szToCodepage, "UTF-8",UNALZ_LEN_CODEPAGE) ; // utf-8
190 #else
191 safe_strcpy(m_szToCodepage, "CP949",UNALZ_LEN_CODEPAGE) ; // CP949
192 #endif // _UNALZ_UTF8
193
194 safe_strcpy(m_szFromCodepage, "CP949",UNALZ_LEN_CODEPAGE); // alz 949
195 #endif // _UNALZ_ICONV
196
197 // check endian
198 if(unalz_le16toh==NULL)
199 {
200 if(IsBigEndian())
201 {
202 unalz_le16toh = le16tobe;
203 unalz_le32toh = le32tobe;
204 unalz_le64toh = le64tobe;
205 }
206 else
207 {
208 unalz_le16toh = le16tole;
209 unalz_le32toh = le32tole;
210 unalz_le64toh = le64tole;
211 }
212 }
213 }
214
215 ////////////////////////////////////////////////////////////////////////////////////////////////////
216 // dtor
217 // @date 2004-03-06 11:19:52
218 ////////////////////////////////////////////////////////////////////////////////////////////////////
~CUnAlz()219 CUnAlz::~CUnAlz()
220 {
221 Close();
222 }
223
224 ////////////////////////////////////////////////////////////////////////////////////////////////////
225 // progress callback func setting
226 // @date 2004-03-01 6:02:05
227 ////////////////////////////////////////////////////////////////////////////////////////////////////
SetCallback(_UnAlzCallback * pFunc,void * param)228 void CUnAlz::SetCallback(_UnAlzCallback* pFunc, void* param)
229 {
230 m_pFuncCallBack = pFunc;
231 m_pCallbackParam = param;
232 }
233
234 #ifdef _WIN32
235 #if !defined(__GNUWIN32__) && !defined(__GNUC__)
236 ////////////////////////////////////////////////////////////////////////////////////////////////////
237 // @param szPathName
238 // @return
239 // @date 2004-03-06 11:03:59
240 ////////////////////////////////////////////////////////////////////////////////////////////////////
Open(LPCWSTR szPathName)241 BOOL CUnAlz::Open(LPCWSTR szPathName)
242 {
243 char szPathNameA[MAX_PATH];
244 ::WideCharToMultiByte(CP_ACP, 0, szPathName, -1, szPathNameA, MAX_PATH, NULL, NULL);
245 return Open(szPathNameA);
246 }
247 ////////////////////////////////////////////////////////////////////////////////////////////////////
248 // @param szFileName
249 // @return
250 // @date 2004-03-06 11:06:20
251 ////////////////////////////////////////////////////////////////////////////////////////////////////
SetCurrentFile(LPCWSTR szFileName)252 BOOL CUnAlz::SetCurrentFile(LPCWSTR szFileName)
253 {
254 char szFileNameA[MAX_PATH];
255 ::WideCharToMultiByte(CP_ACP, 0, szFileName, -1, szFileNameA, MAX_PATH, NULL, NULL);
256 return SetCurrentFile(szFileNameA);
257 }
IsFolder(LPCWSTR szPathName)258 BOOL CUnAlz::IsFolder(LPCWSTR szPathName)
259 {
260 UINT32 dwRet;
261 dwRet = GetFileAttributesW(szPathName);
262 if(dwRet==0xffffffff) return FALSE;
263 if(dwRet & FILE_ATTRIBUTE_DIRECTORY) return TRUE;
264 return FALSE;
265 }
266 #endif // __GNUWIN32__
267 #endif // _WIN32
268
Open(const char * szPathName)269 BOOL CUnAlz::Open(const char* szPathName)
270 {
271 if(FOpen(szPathName)==FALSE)
272 {
273 m_nErr = ERR_CANT_OPEN_FILE;
274 return FALSE;
275 }
276
277 BOOL bValidAlzHeader = FALSE;
278
279 // file
280 for(;;)
281 {
282 SIGNATURE sig;
283 BOOL ret;
284
285 if(FEof()) break;
286 //int pos = unalz_ftell(m_fp);
287 sig = ReadSignature();
288 if(sig==SIG_EOF)
289 {
290 break;
291 }
292 if(sig==SIG_ERROR)
293 {
294 if(bValidAlzHeader)
295 m_nErr = ERR_CORRUPTED_FILE; //
296 else
297 m_nErr = ERR_NOT_ALZ_FILE; // alz
298 return FALSE; //
299 }
300
301 if(sig==SIG_ALZ_FILE_HEADER)
302 {
303 ret = ReadAlzFileHeader();
304 bValidAlzHeader = TRUE; // alz
305 }
306 else if(sig==SIG_LOCAL_FILE_HEADER) ret = ReadLocalFileheader();
307 else if(sig==SIG_CENTRAL_DIRECTORY_STRUCTURE) ret = ReadCentralDirectoryStructure();
308 else if(sig==SIG_ENDOF_CENTRAL_DIRECTORY_RECORD) ret = ReadEndofCentralDirectoryRecord();
309 else
310 {
311 // signature
312 ASSERT(0);
313 m_nErr = ERR_CORRUPTED_FILE;
314 return FALSE;
315 }
316
317 if(ret==FALSE)
318 {
319 return FALSE;
320 }
321
322 if(FEof()) break;
323 }
324
325 return TRUE;
326 }
327
328 ////////////////////////////////////////////////////////////////////////////////////////////////////
329 // @return
330 // @date 2004-03-06 11:04:21
331 ////////////////////////////////////////////////////////////////////////////////////////////////////
Close()332 void CUnAlz::Close()
333 {
334 FClose();
335
336 //
337 FileList::iterator i;
338
339 for(i=m_fileList.begin(); i<m_fileList.end(); i++)
340 {
341 i->Clear();
342 }
343
344 m_posCur = m_fileList.end();//(FileList::iterator)NULL;
345 }
346
347 ////////////////////////////////////////////////////////////////////////////////////////////////////
348 // FILE SIGNATURE
349 // @return
350 // @date 2004-03-06 11:04:47
351 ////////////////////////////////////////////////////////////////////////////////////////////////////
ReadSignature()352 CUnAlz::SIGNATURE CUnAlz::ReadSignature()
353 {
354 UINT32 dwSig;
355 if(FRead(&dwSig, sizeof(dwSig))==FALSE)
356 {
357 if(FEof())
358 return SIG_EOF;
359 m_nErr = ERR_CANT_READ_SIG;
360 return SIG_ERROR;
361 }
362
363 return (SIGNATURE)unalz_le32toh(dwSig); // little to host;
364 }
365
366 ////////////////////////////////////////////////////////////////////////////////////////////////////
367 // ALZ HEADER SIGNATURE
368 // @return
369 // @date 2004-03-06 11:05:11
370 ////////////////////////////////////////////////////////////////////////////////////////////////////
ReadAlzFileHeader()371 BOOL CUnAlz::ReadAlzFileHeader()
372 {
373 SAlzHeader header;
374 if(FRead(&header, sizeof(header))==FALSE)
375 {
376 ASSERT(0);
377 m_nErr = ERR_CANT_READ_FILE;
378 return FALSE;
379 }
380 return TRUE;
381 }
382
383 ////////////////////////////////////////////////////////////////////////////////////////////////////
384 // @return
385 // @date 2004-03-06 11:05:18
386 ////////////////////////////////////////////////////////////////////////////////////////////////////
ReadLocalFileheader()387 BOOL CUnAlz::ReadLocalFileheader()
388 {
389 SAlzLocalFileHeader zipHeader;
390 int ret;
391
392 ret = FRead(&(zipHeader.head), sizeof(zipHeader.head));
393 if(ret==FALSE)
394 {
395 m_nErr = ERR_AT_READ_HEADER;
396 return FALSE;
397 }
398
399 // ALZ
400 if( (zipHeader.head.fileDescriptor & (SHORT)1) != 0){
401 m_bIsEncrypted = TRUE; //
402 }
403 if( (zipHeader.head.fileDescriptor & (SHORT)8) != 0){
404 m_bIsDataDescr = TRUE;
405 }
406
407 int byteLen = zipHeader.head.fileDescriptor/0x10;
408
409 if(byteLen)
410 {
411 FRead(&(zipHeader.compressionMethod), sizeof(zipHeader.compressionMethod));
412 FRead(&(zipHeader.unknown), sizeof(zipHeader.unknown));
413 FRead(&(zipHeader.fileCRC), sizeof(zipHeader.fileCRC));
414
415 FRead(&(zipHeader.compressedSize), byteLen);
416 FRead(&(zipHeader.uncompressedSize), byteLen); //
417 }
418
419 // little to system
420 zipHeader.fileCRC = unalz_le32toh(zipHeader.fileCRC);
421 zipHeader.head.fileNameLength = unalz_le16toh(zipHeader.head.fileNameLength);
422 zipHeader.compressedSize = unalz_le64toh(zipHeader.compressedSize);
423 zipHeader.uncompressedSize = unalz_le64toh(zipHeader.uncompressedSize);
424
425 // FILE NAME
426 zipHeader.fileName = (char*)malloc(zipHeader.head.fileNameLength+sizeof(char));
427 if(zipHeader.fileName==NULL)
428 {
429 m_nErr = ERR_INVALID_FILENAME_LENGTH;
430 return FALSE;
431 }
432 FRead(zipHeader.fileName, zipHeader.head.fileNameLength);
433 if(zipHeader.head.fileNameLength > MAX_PATH - 5)
434 zipHeader.head.fileNameLength = MAX_PATH - 5;
435 zipHeader.fileName[zipHeader.head.fileNameLength] = (CHAR)0;
436
437
438 #ifdef _UNALZ_ICONV // codepage convert
439
440 if(strlen(m_szToCodepage))
441 {
442
443 #define ICONV_BUF_SIZE (260*6) // utf8 6byte
444 size_t ileft, oleft;
445 iconv_t cd;
446 size_t iconv_result;
447 size_t size;
448 char inbuf[ICONV_BUF_SIZE];
449 char outbuf[ICONV_BUF_SIZE];
450 #if defined(__CYGWIN__) || defined(__NetBSD__)
451 const char *inptr = inbuf;
452 #else
453 char *inptr = inbuf;
454 #endif
455 char *outptr = outbuf;
456
457 size = strlen(zipHeader.fileName)+1;
458 strncpy(inbuf, zipHeader.fileName, size);
459 ileft = size;
460 oleft = sizeof(outbuf);
461
462 cd = iconv_open(m_szToCodepage, m_szFromCodepage); // "UTF-8"
463 iconv(cd, NULL, NULL, NULL, NULL);
464 if( cd == (iconv_t)(-1))
465 {
466 m_nErr = ERR_ICONV_CANT_OPEN; // printf("Converting Error : Cannot open iconv");
467 return FALSE;
468 }
469 else
470 {
471 iconv_result = iconv(cd, &inptr, &ileft, &outptr, &oleft);
472
473 if(iconv_result== (size_t)(-1)) // iconv
474 {
475 if (errno == EILSEQ)
476 m_nErr = ERR_ICONV_INVALID_MULTISEQUENCE_OF_CHARACTERS; // printf("Invalid Multibyte Sequence of Characters");
477 else if (errno == EINVAL)
478 m_nErr = ERR_ICONV_INCOMPLETE_MULTIBYTE_SEQUENCE; // printf("Incomplete multibyte sequence");
479 else if (errno != E2BIG)
480 m_nErr = ERR_ICONV_NOT_ENOUGH_SPACE_OF_BUFFER_TO_CONVERT; // printf("Not enough space of buffer to convert");
481 else
482 m_nErr = ERR_ICONV_ETC;
483 iconv_close(cd);
484 return FALSE;
485 }
486 else
487 {
488 outbuf[ICONV_BUF_SIZE-oleft] = 0;
489 if(zipHeader.fileName) free(zipHeader.fileName);
490 zipHeader.fileName = strdup(outbuf);
491 if (zipHeader.fileName == NULL)
492 {
493 m_nErr = ERR_ICONV_ETC;
494 iconv_close(cd);
495 return FALSE;
496 }
497 // printf("\n Converted File Name : %s", outbuf);
498 }
499
500 iconv_close(cd);
501 }
502
503 }
504 #endif
505
506 /*
507 // EXTRA FIELD LENGTH
508 if(zipHeader.head.extraFieldLength)
509 {
510 zipHeader.extraField = (BYTE*)malloc(zipHeader.head.extraFieldLength);
511 if(zipHeader.extraField==NULL)
512 {
513 m_nErr = ERR_INVALID_EXTRAFIELD_LENGTH;
514 return FALSE;
515 }
516 FRead(zipHeader.extraField, 1, zipHeader.head.extraFieldLength);
517 }
518 */
519
520 if(IsEncryptedFile(zipHeader.head.fileDescriptor))
521 FRead(zipHeader.encChk, ALZ_ENCR_HEADER_LEN); // xf86
522
523 // SKIP FILE DATA
524 zipHeader.dwFileDataPos = FTell(); // data
525 FSeek(FTell()+zipHeader.compressedSize);
526
527 // DATA DESCRIPTOR
528 /*
529 if(zipHeader.head.generalPurposeBitFlag.bit1)
530 {
531 FRead(zipHeader.extraField, 1, sizeof(zipHeader.extraField),);
532 }
533 */
534
535 /*
536 #ifdef _DEBUG
537 printf("NAME:%s COMPRESSED SIZE:%d UNCOMPRESSED SIZE:%d COMP METHOD:%d\n",
538 zipHeader.fileName,
539 zipHeader.compressedSize,
540 zipHeader.uncompressedSize,
541 zipHeader.compressionMethod
542 );
543 #endif
544 */
545
546 //
547 m_fileList.push_back(zipHeader);
548
549 return TRUE;
550 }
551
ReadCentralDirectoryStructure()552 BOOL CUnAlz::ReadCentralDirectoryStructure()
553 {
554 SCentralDirectoryStructure header;
555
556 if(FRead(&header, sizeof(header.head))==FALSE)
557 {
558 m_nErr = ERR_CANT_READ_CENTRAL_DIRECTORY_STRUCTURE_HEAD;
559 return FALSE;
560 }
561
562 /*
563 // read file name
564 if(header.head.fileNameLength)
565 {
566 header.fileName = (char*)malloc(header.head.fileNameLength+1);
567 if(header.fileName==NULL)
568 {
569 m_nErr = ERR_INVALID_FILENAME_SIZE;
570 return FALSE;
571 }
572 FRead(header.fileName, 1, header.head.fileNameLength, m_fp);
573 header.fileName[header.head.fileNameLength] = NULL;
574 }
575
576 // extra field;
577 if(header.head.extraFieldLength)
578 {
579 header.extraField = (BYTE*)malloc(header.head.extraFieldLength);
580 if(header.extraField==NULL)
581 {
582 m_nErr = ERR_INVALID_EXTRAFIELD_SIZE;
583 return FALSE;
584 }
585 FRead(header.extraField, 1, header.head.extraFieldLength, m_fp);
586 }
587
588 // file comment;
589 if(header.head.fileCommentLength)
590 {
591 header.fileComment = (char*)malloc(header.head.fileCommentLength+1);
592 if(header.fileComment==NULL)
593 {
594 m_nErr = ERR_INVALID_FILECOMMENT_SIZE;
595 return FALSE;
596 }
597 FRead(header.fileComment, 1, header.head.fileCommentLength, m_fp);
598 header.fileComment[header.head.fileCommentLength] = NULL;
599 }
600 */
601
602 return TRUE;
603 }
604
ReadEndofCentralDirectoryRecord()605 BOOL CUnAlz::ReadEndofCentralDirectoryRecord()
606 {
607 /*
608 SEndOfCentralDirectoryRecord header;
609
610 if(FRead(&header, sizeof(header.head), 1, m_fp)!=1)
611 {
612 m_nErr = ERR_CANT_READ_HEADER;
613 return FALSE;
614 }
615
616 if(header.head.zipFileCommentLength)
617 {
618 header.fileComment = (char*)malloc(header.head.zipFileCommentLength+1);
619 if(header.fileComment==NULL)
620 {
621 m_nErr = ERR_INVALID_FILECOMMENT_SIZE;
622 return FALSE;
623 }
624 FRead(header.fileComment, 1, header.head.zipFileCommentLength, m_fp);
625 header.fileComment[header.head.zipFileCommentLength] = NULL;
626 }
627 */
628
629 return TRUE;
630 }
631
SetCurrentFile(const char * szFileName)632 BOOL CUnAlz::SetCurrentFile(const char* szFileName)
633 {
634 FileList::iterator i;
635
636 //
637 for(i=m_fileList.begin(); i<m_fileList.end(); i++)
638 {
639 #ifdef _WIN32
640 if(stricmp(i->fileName, szFileName)==0)
641 #else
642 if(strcmp(i->fileName, szFileName)==0)
643 #endif
644 {
645 m_posCur = i;
646 return TRUE;
647 }
648 }
649
650 m_posCur = m_fileList.end();//(FileList::iterator)NULL;
651
652 return FALSE;
653 }
654
SetCurrentFile(FileList::iterator newPos)655 void CUnAlz::SetCurrentFile(FileList::iterator newPos)
656 {
657 m_posCur = newPos;
658 }
659
660 #ifndef MAX_WBITS
661 # define MAX_WBITS 15 /* 32K LZ77 window */
662 #endif
663
664 ////////////////////////////////////////////////////////////////////////////////////////////////////
665 // @param pDestBuf
666 // @return
667 // @date 2004-03-07 12:26:13
668 ////////////////////////////////////////////////////////////////////////////////////////////////////
ExtractCurrentFileToBuf(BYTE * pDestBuf,int nBufSize)669 BOOL CUnAlz::ExtractCurrentFileToBuf(BYTE* pDestBuf, int nBufSize)
670 {
671 SExtractDest dest;
672 dest.nType = ET_MEM;
673 dest.buf = pDestBuf;
674 dest.bufpos = 0;
675 dest.bufsize = nBufSize;
676 return ExtractTo(&dest);
677 }
678
679 ////////////////////////////////////////////////////////////////////////////////////////////////////
680 // (SetCurrentFile)
681 // @param szDestPathName -
682 // @param szDestFileName -
683 // @return
684 // @date 2004-03-06 11:06:59
685 ////////////////////////////////////////////////////////////////////////////////////////////////////
ExtractCurrentFile(const char * szDestPathName,const char * szDestFileName)686 BOOL CUnAlz::ExtractCurrentFile(const char* szDestPathName, const char* szDestFileName)
687 {
688 if(m_posCur==m_fileList.end()/*(FileList::iterator)NULL*/) {ASSERT(0); return FALSE;}
689 BOOL ret=FALSE;
690
691 SExtractDest dest;
692 char szDestPathFileName[MAX_PATH];
693
694 if(chkValidPassword() == FALSE)
695 {
696 return FALSE;
697 }
698
699 if( szDestPathName==NULL||
700 strlen(szDestPathName) + (szDestFileName?strlen(szDestFileName):strlen(m_posCur->fileName))+1 > MAX_PATH
701 ) // check buffer overflow
702 {
703 ASSERT(0);
704 m_nErr = ERR_GENERAL;
705 return FALSE;
706 }
707
708 //
709 safe_strcpy(szDestPathFileName, szDestPathName, MAX_PATH);
710 if(szDestPathFileName[strlen(szDestPathFileName)]!=PATHSEPC)
711 safe_strcat(szDestPathFileName, PATHSEP, MAX_PATH);
712
713 //
714 if(szDestFileName) safe_strcat(szDestPathFileName, szDestFileName, MAX_PATH);
715 else safe_strcat(szDestPathFileName, m_posCur->fileName, MAX_PATH);
716
717 // ../../
718 if( strstr(szDestPathFileName, "../")||
719 strstr(szDestPathFileName, "..\\"))
720 {
721 ASSERT(0);
722 m_nErr = ERR_GENERAL;
723 return FALSE;
724 }
725
726 #ifndef _WIN32
727 {
728 char* p = szDestPathFileName; // delimiter
729 while(*p)
730 {
731 if(*p=='\\') *p='/';
732 p++;
733 }
734 }
735 #endif
736
737 //
738 dest.nType = ET_FILE;
739
740 if(m_bPipeMode)
741 dest.fp = stdout; // pipe mode stdout
742 else
743 dest.fp = fopen(szDestPathFileName, "wb");
744
745 //
746 if(m_bPipeMode==FALSE && (m_posCur->head.fileAttribute) & ALZ_FILEATTR_DIRECTORY )
747 {
748 //printf("digpath:%s\n", szDestPathFileName);
749 //
750 DigPath(szDestPathFileName);
751 return TRUE;
752 // m_nErr = ERR_CANT_CREATE_DEST_PATH;
753 // return FALSE;
754 }
755
756 //
757 if(dest.fp==NULL)
758 {
759 DigPath(szDestPathFileName);
760 dest.fp = fopen(szDestPathFileName, "wb");
761 }
762
763 //
764 if(dest.fp==NULL)
765 {
766 //
767 m_nErr = ERR_CANT_OPEN_DEST_FILE;
768 //printf("dest pathfilename:%s\n",szDestPathFileName);
769 if(m_pFuncCallBack)
770 {
771 CHAR buf[1024];
772 // sprintf(buf, : %s", szDestPathFileName);
773 // m_pFuncCallBack(buf, 0,0,m_pCallbackParam, NULL);
774 }
775 return FALSE;
776 }
777 //#endif
778
779 // CALLBACK
780 if(m_pFuncCallBack) m_pFuncCallBack(m_posCur->fileName, 0,m_posCur->uncompressedSize,m_pCallbackParam, NULL);
781
782 ret = ExtractTo(&dest);
783 if(dest.fp!=NULL)
784 {
785 fclose(dest.fp);
786 // file time setting - from unalz_wcx_01i.zip
787 utimbuf tmp;
788 tmp.actime = 0; //
789 tmp.modtime = dosTime2TimeT(m_posCur->head.fileTimeDate); //
790 utime(m_posCur->fileName, &tmp);
791 }
792 return ret;
793 }
794
795 ////////////////////////////////////////////////////////////////////////////////////////////////////
796 // @param dest
797 // @return
798 // @date 2004-03-07 12:44:36
799 ////////////////////////////////////////////////////////////////////////////////////////////////////
ExtractTo(SExtractDest * dest)800 BOOL CUnAlz::ExtractTo(SExtractDest* dest)
801 {
802 BOOL ret = FALSE;
803 //
804 if(m_posCur->compressionMethod==COMP_NOCOMP)
805 {
806 ret = ExtractRawfile(dest, *m_posCur);
807 }
808 else if(m_posCur->compressionMethod==COMP_BZIP2)
809 {
810 ret = ExtractBzip2(dest, *m_posCur); // bzip2
811 }
812 else if(m_posCur->compressionMethod==COMP_DEFLATE)
813 {
814 ret = ExtractDeflate2(dest, *m_posCur); // deflate
815 }
816 else // COMP_UNKNOWN
817 {
818 // alzip 5.6 5.51
819 //
820 //
821 m_nErr = ERR_UNKNOWN_COMPRESSION_METHOD;
822 ASSERT(0);
823 ret = FALSE;
824 }
825 return ret;
826 }
827
828 ////////////////////////////////////////////////////////////////////////////////////////////////////
829 // DEFLATE
830 // @param fp -
831 // @param file -
832 // @return
833 // @date 2004-03-06 11:09:17
834 ////////////////////////////////////////////////////////////////////////////////////////////////////
835 /*
836 BOOL CUnAlz::ExtractDeflate(FILE* fp, SAlzLocalFileHeader& file)
837 {
838 z_stream stream;
839 BYTE* pInBuf=NULL;
840 BYTE* pOutBuf=NULL;
841 int nInBufSize = file.compressedSize;
842 int nOutBufSize = file.uncompressedSize;
843 int err;
844 int flush=Z_SYNC_FLUSH;
845 BOOL ret = FALSE;
846
847 memset(&stream, 0, sizeof(stream));
848
849 pInBuf = (BYTE*)malloc(nInBufSize);
850 if(pInBuf==NULL)
851 {
852 m_nErr = ERR_MEM_ALLOC_FAILED;
853 goto END;
854 }
855
856 pOutBuf = (BYTE*)malloc(nOutBufSize);
857 if(pOutBuf==NULL)
858 {
859 m_nErr = ERR_MEM_ALLOC_FAILED;
860 goto END;
861 }
862
863 //
864 fseek(m_fp, file.dwFileDataPos, SEEK_SET);
865 if(FRead(pInBuf, nInBufSize, 1, m_fp)!=1)
866 {
867 m_nErr = ERR_FILE_READ_ERROR;
868 goto END;
869 }
870
871 //
872 inflateInit2(&stream, -MAX_WBITS);
873
874 stream.next_out = pOutBuf;
875 stream.avail_out = nOutBufSize;
876 stream.next_in = pInBuf;
877 stream.avail_in = nInBufSize;
878
879 err = inflate(&stream, flush);
880
881 if(err!=Z_OK && err!=Z_STREAM_END )
882 {
883 m_nErr = ERR_INFLATE_FAILED;
884 goto END;
885 }
886
887 fwrite(pOutBuf, 1, nOutBufSize, fp);
888
889 ret = TRUE;
890
891 END :
892 inflateEnd(&stream);
893
894 if(pInBuf) free(pInBuf);
895 if(pOutBuf) free(pOutBuf);
896 return ret;
897 }
898 */
899
900 ////////////////////////////////////////////////////////////////////////////////////////////////////
901 // @param szDestPathName -
902 // @return
903 // @date 2004-03-06 11:09:49
904 ////////////////////////////////////////////////////////////////////////////////////////////////////
ExtractAll(const char * szDestPathName)905 BOOL CUnAlz::ExtractAll(const char* szDestPathName)
906 {
907 FileList::iterator i;
908
909 for(i=m_fileList.begin(); i<m_fileList.end(); i++)
910 {
911 m_posCur = i;
912 if(ExtractCurrentFile(szDestPathName)==FALSE) return FALSE;
913 if(m_bHalt)
914 break; //
915 }
916
917 return TRUE;
918 }
919
920 ////////////////////////////////////////////////////////////////////////////////////////////////////
921 // (dig)
922 // @param szPathName
923 // @return
924 // @date 2004-03-06 11:10:12
925 ////////////////////////////////////////////////////////////////////////////////////////////////////
DigPath(const char * szPathName)926 BOOL CUnAlz::DigPath(const char* szPathName)
927 {
928 char* dup = strdup(szPathName);
929 char seps[] = "/\\";
930 char* token;
931 char path[MAX_PATH] = {0};
932 char* last;
933
934 //
935 last = dup + strlen(dup);
936 while(last!=dup)
937 {
938 if(*last=='/' || *last=='\\')
939 {
940 *last = (char)0;
941 break;
942 }
943 last --;
944 }
945
946
947 token = strtok( dup, seps );
948 while( token != NULL )
949 {
950 if(strlen(path)==0)
951 {
952 if(szPathName[0]=='/') // is absolute path ?
953 safe_strcpy(path,"/", MAX_PATH);
954 else if(szPathName[0]=='\\' && szPathName[1]=='\\') // network drive ?
955 safe_strcpy(path,"\\\\", MAX_PATH);
956 safe_strcat(path, token, MAX_PATH);
957 }
958 else
959 {
960 safe_strcat(path, PATHSEP,MAX_PATH);
961 safe_strcat(path, token,MAX_PATH);
962 }
963
964 if(IsFolder(path)==FALSE)
965 #ifdef _WIN32
966 _mkdir(path);
967 #else
968 mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
969 #endif
970 //printf("path:%s\n", path);
971 token = strtok( NULL, seps );
972 }
973
974 free(dup);
975 if(IsFolder(szPathName)) return TRUE;
976 return FALSE;
977 }
978
979 ////////////////////////////////////////////////////////////////////////////////////////////////////
980 // @param szPathName
981 // @return
982 // @date 2004-03-06 11:03:26
983 ////////////////////////////////////////////////////////////////////////////////////////////////////
IsFolder(const CHAR * szPathName)984 BOOL CUnAlz::IsFolder(const CHAR* szPathName)
985 {
986 #ifdef _WIN32
987 UINT32 dwRet;
988 dwRet = GetFileAttributesA(szPathName);
989 if(dwRet==0xffffffff) return FALSE;
990 if(dwRet & FILE_ATTRIBUTE_DIRECTORY) return TRUE;
991 return FALSE;
992 #else
993
994 struct stat buf;
995 int result;
996
997 result = stat(szPathName, &buf);
998 if(result!=0) return FALSE;
999 //printf("isfolder:%s, %d,%d,%d\n", szPathName, buf.st_mode, S_IFDIR, buf.st_mode & S_IFDIR);
1000 if(buf.st_mode & S_IFDIR) return TRUE;
1001 return FALSE;
1002 #endif
1003 }
1004
1005 ////////////////////////////////////////////////////////////////////////////////////////////////////
1006 // @param dest - OBJECT
1007 // @param buf -
1008 // @param nSize -
1009 // @return
1010 // @date 2004-03-07 12:37:41
1011 ////////////////////////////////////////////////////////////////////////////////////////////////////
WriteToDest(SExtractDest * dest,BYTE * buf,int nSize)1012 int CUnAlz::WriteToDest(SExtractDest* dest, BYTE* buf, int nSize)
1013 {
1014 if(dest->nType==ET_FILE)
1015 {
1016 return fwrite(buf, 1, nSize, dest->fp);
1017 }
1018 else if(dest->nType==ET_MEM)
1019 {
1020 if(dest->buf==NULL) return nSize; // NULL
1021 if(dest->bufpos+nSize >dest->bufsize) //
1022 {
1023 ASSERT(0);
1024 return -1;
1025 }
1026 // memcpy
1027 memcpy(dest->buf + dest->bufpos, buf, nSize);
1028 dest->bufpos += nSize;
1029 return nSize;
1030 }
1031 else
1032 {
1033 ASSERT(0);
1034 }
1035 return -1;
1036 }
1037
1038 /*
1039 #define ALZDLZ_HEADER_SIZE 4 // alz bzip2
1040 #define BZIP2_HEADER_SIZE 10 // bzip
1041 #define BZIP2_CRC_SIZE 4 // bzip2 crc
1042 #define BZIP2_TAIL_SIZE 10 // 4+5
1043 BYTE bzip2Header[BZIP2_HEADER_SIZE] = {0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, 0x53, 0x59};
1044
1045 BOOL CUnAlz::ExtractBzip2_bak(FILE* fp, SAlzLocalFileHeader& file)
1046 {
1047 bz_stream stream;
1048 BYTE* pInBuf=NULL;
1049 BYTE* pOutBuf=NULL;
1050 int nInBufSize = file.compressedSize;
1051 int nOutBufSize = file.uncompressedSize;
1052 //int err;
1053 int flush=Z_SYNC_FLUSH;
1054 BOOL ret = FALSE;
1055 UINT32 crc = 0xffffffff;
1056
1057 //BYTE temp[100];
1058
1059 memset(&stream, 0, sizeof(stream));
1060
1061 pInBuf = (BYTE*)malloc(nInBufSize + BZIP2_HEADER_SIZE + BZIP2_CRC_SIZE - ALZDLZ_HEADER_SIZE + BZIP2_TAIL_SIZE);
1062 if(pInBuf==NULL)
1063 {
1064 m_nErr = ERR_MEM_ALLOC_FAILED;
1065 goto END;
1066 }
1067
1068 pOutBuf = (BYTE*)malloc(nOutBufSize);
1069 if(pOutBuf==NULL)
1070 {
1071 m_nErr = ERR_MEM_ALLOC_FAILED;
1072 goto END;
1073 }
1074
1075 // ALZ BZIP ("DLZ.").
1076 fseek(m_fp, ALZDLZ_HEADER_SIZE, SEEK_CUR);
1077 // BZIP2
1078 memcpy(pInBuf, bzip2Header, BZIP2_HEADER_SIZE);
1079 // BZIP2 CRC
1080 memcpy(pInBuf+BZIP2_HEADER_SIZE, &(crc), BZIP2_CRC_SIZE);
1081
1082 //
1083 fseek(m_fp, file.dwFileDataPos+ALZDLZ_HEADER_SIZE, SEEK_SET);
1084 if(FRead(pInBuf+BZIP2_HEADER_SIZE+BZIP2_CRC_SIZE, nInBufSize-ALZDLZ_HEADER_SIZE, 1, m_fp)!=1)
1085 {
1086 m_nErr = ERR_FILE_READ_ERROR;
1087 goto END;
1088 }
1089
1090 //
1091 stream.bzalloc = NULL;
1092 stream.bzfree = NULL;
1093 stream.opaque = NULL;
1094 ret = BZ2_bzDecompressInit ( &stream, 3,0 );
1095 if (ret != BZ_OK) goto END;
1096
1097 //memcpy(temp, pInBuf, 100);
1098
1099 stream.next_in = (char*)pInBuf;
1100 stream.next_out = (char*)pOutBuf;
1101 stream.avail_in = nInBufSize+BZIP2_HEADER_SIZE+BZIP2_CRC_SIZE+BZIP2_TAIL_SIZE;
1102 stream.avail_out = nOutBufSize;
1103
1104 ret = BZ2_bzDecompress ( &stream );
1105
1106 // BZ_DATA_ERROR
1107 //if (ret == BZ_OK) goto END;
1108 //if (ret != BZ_STREAM_END) goto END;
1109
1110 BZ2_bzDecompressEnd(&stream);
1111
1112 fwrite(pOutBuf, 1, nOutBufSize, fp);
1113
1114 ret = TRUE;
1115
1116 END :
1117
1118 if(pInBuf) free(pInBuf);
1119 if(pOutBuf) free(pOutBuf);
1120
1121 if(ret==FALSE) BZ2_bzDecompressEnd(&stream);
1122
1123 return ret;
1124 }
1125 */
1126
1127 ////////////////////////////////////////////////////////////////////////////////////////////////////
1128 // RAW
1129 // @param fp -
1130 // @param file -
1131 // @return
1132 // @date 2004-03-06 11:10:53
1133 ////////////////////////////////////////////////////////////////////////////////////////////////////
1134 #define BUF_LEN (4096*2)
ExtractRawfile(SExtractDest * dest,SAlzLocalFileHeader & file)1135 BOOL CUnAlz::ExtractRawfile(SExtractDest* dest, SAlzLocalFileHeader& file)
1136 {
1137 BOOL ret = FALSE;
1138 BYTE buf[BUF_LEN];
1139 INT64 read;
1140 INT64 sizeToRead;
1141 INT64 bufLen = BUF_LEN;
1142 INT64 nWritten = 0;
1143 BOOL bHalt = FALSE;
1144 BOOL bIsEncrypted = IsEncryptedFile(); //
1145 UINT32 dwCRC32= 0;
1146
1147 //
1148 FSeek(file.dwFileDataPos);
1149
1150 sizeToRead = file.compressedSize; //
1151
1152 m_nErr = ERR_NOERR;
1153 while(sizeToRead)
1154 {
1155 read = min(sizeToRead, bufLen);
1156 if(FRead(buf, (int)read)==FALSE)
1157 {
1158 break;
1159 }
1160
1161 if(bIsEncrypted)
1162 DecryptingData((int)read, buf); // xf86
1163
1164 dwCRC32 = crc32(dwCRC32, buf, (UINT)(read));
1165
1166 WriteToDest(dest, buf, (int)read);
1167 //fwrite(buf, read, 1, fp);
1168 sizeToRead -= read;
1169
1170 nWritten+=read;
1171
1172 // progress callback
1173 if(m_pFuncCallBack)
1174 {
1175 m_pFuncCallBack(NULL, nWritten, file.uncompressedSize, m_pCallbackParam, &bHalt);
1176 if(bHalt)
1177 {
1178 break;
1179 }
1180 }
1181 }
1182
1183 m_bHalt = bHalt;
1184
1185 if(m_nErr==ERR_NOERR) //
1186 {
1187 if(file.fileCRC==dwCRC32)
1188 {
1189 ret = TRUE;
1190 }
1191 else
1192 {
1193 m_nErr = ERR_INVALID_FILE_CRC;
1194 }
1195 }
1196
1197
1198 return ret;
1199 }
1200
1201 ////////////////////////////////////////////////////////////////////////////////////////////////////
1202 // BZIP2
1203 // @param fp_w -
1204 // @param file -
1205 // @return
1206 // @date 2004-03-01 5:47:36
1207 ////////////////////////////////////////////////////////////////////////////////////////////////////
1208 #define BZIP2_EXTRACT_BUF_SIZE 0x2000
ExtractBzip2(SExtractDest * dest,SAlzLocalFileHeader & file)1209 BOOL CUnAlz::ExtractBzip2(SExtractDest* dest, SAlzLocalFileHeader& file)
1210 {
1211 BZFILE *bzfp = NULL;
1212 int smallMode = 0;
1213 int verbosity = 1;
1214 int bzerr;
1215 INT64 len;
1216 BYTE buff[BZIP2_EXTRACT_BUF_SIZE];
1217 INT64 nWritten = 0;
1218 BOOL bHalt = FALSE;
1219 UINT32 dwCRC32= 0;
1220 BOOL ret = FALSE;
1221
1222 FSeek(file.dwFileDataPos);
1223
1224 bzfp = BZ2_bzReadOpen(&bzerr,this,verbosity,smallMode,0,0);
1225
1226 if(bzfp==NULL){ASSERT(0); return FALSE;}
1227
1228 m_nErr = ERR_NOERR;
1229 while((len=BZ2_bzread(bzfp,buff,BZIP2_EXTRACT_BUF_SIZE))>0)
1230 {
1231 WriteToDest(dest, (BYTE*)buff, (int)len);
1232 //fwrite(buff,1,len,fp_w);
1233
1234 dwCRC32 = crc32(dwCRC32,buff, (UINT)(len));
1235
1236
1237 nWritten+=len;
1238
1239 // progress callback
1240 if(m_pFuncCallBack)
1241 {
1242 m_pFuncCallBack(NULL, nWritten, file.uncompressedSize, m_pCallbackParam, &bHalt);
1243 if(bHalt)
1244 {
1245 break;
1246 }
1247 }
1248 }
1249
1250 if(len<0) //
1251 {
1252 m_nErr = ERR_INFLATE_FAILED;
1253 }
1254
1255 BZ2_bzReadClose( &bzerr, bzfp);
1256
1257 m_bHalt = bHalt;
1258
1259 if(m_nErr==ERR_NOERR) //
1260 {
1261 if(file.fileCRC==dwCRC32)
1262 {
1263 ret = TRUE;
1264 }
1265 else
1266 {
1267 m_nErr = ERR_INVALID_FILE_CRC;
1268 }
1269 }
1270
1271 /*
1272 // FILE*
1273 BZFILE *bzfp = NULL;
1274 int smallMode = 0;
1275 int verbosity = 1;
1276 int bzerr;
1277 int len;
1278 char buff[BZIP2_EXTRACT_BUF_SIZE];
1279 INT64 nWritten = 0;
1280 BOOL bHalt = FALSE;
1281
1282 FSeek(file.dwFileDataPos, SEEK_SET);
1283
1284 bzfp = BZ2_bzReadOpen(&bzerr,m_fp,verbosity,smallMode,0,0);
1285
1286 while((len=BZ2_bzread(bzfp,buff,BZIP2_EXTRACT_BUF_SIZE))>0)
1287 {
1288 WriteToDest(dest, (BYTE*)buff, len);
1289 //fwrite(buff,1,len,fp_w);
1290
1291 nWritten+=len;
1292
1293 // progress callback
1294 if(m_pFuncCallBack)
1295 {
1296 m_pFuncCallBack(NULL, nWritten, file.uncompressedSize, m_pCallbackParam, &bHalt);
1297 if(bHalt)
1298 {
1299 break;
1300 }
1301 }
1302 }
1303
1304 BZ2_bzReadClose( &bzerr, bzfp);
1305
1306 m_bHalt = bHalt;
1307 */
1308
1309 return ret;
1310 }
1311
1312
1313 #ifndef UNZ_BUFSIZE
1314 #define UNZ_BUFSIZE 0x1000 // (16384)
1315 #endif
1316
1317 #define IN_BUF_SIZE UNZ_BUFSIZE
1318 #define OUT_BUF_SIZE 0x1000 //IN_BUF_SIZE
1319
1320 ////////////////////////////////////////////////////////////////////////////////////////////////////
1321 // deflate ExtractDeflate()
1322 // @param fp
1323 // @param file
1324 // @return
1325 // @date 2004-03-06 11:11:36
1326 ////////////////////////////////////////////////////////////////////////////////////////////////////
ExtractDeflate2(SExtractDest * dest,SAlzLocalFileHeader & file)1327 BOOL CUnAlz::ExtractDeflate2(SExtractDest* dest, SAlzLocalFileHeader& file)
1328 {
1329 z_stream stream;
1330 BYTE pInBuf[IN_BUF_SIZE];
1331 BYTE pOutBuf[OUT_BUF_SIZE];
1332 int nInBufSize = IN_BUF_SIZE;
1333 int nOutBufSize = OUT_BUF_SIZE;
1334 int err;
1335 int flush=Z_SYNC_FLUSH;
1336 BOOL ret = FALSE;
1337 INT64 nRestReadCompressed;
1338 UINT32 dwCRC32= 0;
1339 INT64 rest_read_uncompressed;
1340 UINT iRead = 0;
1341 INT64 nWritten = 0;
1342 BOOL bHalt = FALSE;
1343 BOOL bIsEncrypted = IsEncryptedFile(); //
1344
1345 memset(&stream, 0, sizeof(stream));
1346
1347 FSeek(file.dwFileDataPos);
1348
1349 inflateInit2(&stream, -MAX_WBITS);
1350 nRestReadCompressed = file.compressedSize;
1351 rest_read_uncompressed = file.uncompressedSize;
1352
1353 //
1354 stream.next_out = pOutBuf;
1355 stream.avail_out = OUT_BUF_SIZE;
1356
1357 m_nErr = ERR_NOERR;
1358 while(stream.avail_out>0)
1359 {
1360 if(stream.avail_in==0 && nRestReadCompressed>0)
1361 {
1362 UINT uReadThis = UNZ_BUFSIZE;
1363 if (nRestReadCompressed<(int)uReadThis)
1364 uReadThis = (UINT)nRestReadCompressed; //
1365
1366 if (uReadThis == 0)
1367 break; //
1368
1369 if(FRead(pInBuf, uReadThis)==FALSE)
1370 {
1371 m_nErr = ERR_CANT_READ_FILE;
1372 goto END;
1373 }
1374
1375 if(bIsEncrypted)
1376 DecryptingData(uReadThis, pInBuf); // xf86
1377
1378 // dwCRC32 = crc32(dwCRC32,pInBuf, (UINT)(uReadThis));
1379
1380 nRestReadCompressed -= uReadThis;
1381 stream.next_in = pInBuf;
1382 stream.avail_in = uReadThis;
1383 }
1384
1385 UINT uTotalOutBefore,uTotalOutAfter;
1386 const BYTE *bufBefore;
1387 UINT uOutThis;
1388 int flush=Z_SYNC_FLUSH;
1389
1390 uTotalOutBefore = stream.total_out;
1391 bufBefore = stream.next_out;
1392
1393 err=inflate(&stream,flush);
1394
1395 uTotalOutAfter = stream.total_out;
1396 uOutThis = uTotalOutAfter-uTotalOutBefore;
1397
1398 dwCRC32 = crc32(dwCRC32,bufBefore, (UINT)(uOutThis));
1399
1400 rest_read_uncompressed -= uOutThis;
1401
1402 iRead += (UINT)(uTotalOutAfter - uTotalOutBefore);
1403
1404 WriteToDest(dest, pOutBuf, uOutThis);
1405 //fwrite(pOutBuf, uOutThis, 1, fp); // file
1406 stream.next_out = pOutBuf;
1407 stream.avail_out = OUT_BUF_SIZE;
1408
1409 nWritten+=uOutThis;
1410
1411 // progress callback
1412 if(m_pFuncCallBack)
1413 {
1414 m_pFuncCallBack(NULL, nWritten, file.uncompressedSize, m_pCallbackParam, &bHalt);
1415 if(bHalt)
1416 {
1417 m_nErr = ERR_USER_ABORTED;
1418 break;
1419 }
1420 }
1421
1422 if (err==Z_STREAM_END)
1423 break;
1424 //if(iRead==0) break; // UNZ_EOF;
1425 if (err!=Z_OK)
1426 {
1427 m_nErr = ERR_INFLATE_FAILED;
1428 goto END;
1429 }
1430 }
1431 m_bHalt = bHalt;
1432
1433
1434 if(m_nErr==ERR_NOERR) //
1435 {
1436 if(file.fileCRC==dwCRC32)
1437 {
1438 ret = TRUE;
1439 }
1440 else
1441 {
1442 m_nErr = ERR_INVALID_FILE_CRC;
1443 }
1444 }
1445
1446
1447 END :
1448 inflateEnd(&stream);
1449
1450 return ret;
1451 }
1452
1453 ////////////////////////////////////////////////////////////////////////////////////////////////////
1454 // @param szPathName
1455 // @return
1456 // @date 2004-10-02 11:47:14
1457 ////////////////////////////////////////////////////////////////////////////////////////////////////
FOpen(const char * szPathName)1458 BOOL CUnAlz::FOpen(const char* szPathName)
1459 {
1460 char* temp = strdup(szPathName); //
1461 int i;
1462 int nLen = strlen(szPathName);
1463 UINT64 nFileSizeLow;
1464 UINT32 dwFileSizeHigh;
1465 m_nFileCount = 0;
1466 m_nCurFile = 0;
1467 m_nVirtualFilePos = 0;
1468 m_nCurFilePos = 0;
1469 m_bIsEOF = FALSE;
1470 for(i=0;i<MAX_FILES;i++) //
1471 {
1472 if(i>0)
1473 safe_sprintf(temp+nLen-3, 4, "%c%02d", (i-1)/100+'a', (i-1)%100);
1474
1475 #ifdef _WIN32
1476 m_files[i].fp = CreateFileA(temp, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
1477 if(m_files[i].fp==INVALID_HANDLE_VALUE) break;
1478 nFileSizeLow = GetFileSize(m_files[i].fp, (DWORD*)&dwFileSizeHigh);
1479 #else
1480 m_files[i].fp = fopen(temp, "rb");
1481 if(m_files[i].fp==NULL) break;
1482 dwFileSizeHigh=0;
1483 unalz_fseek(m_files[i].fp,0,SEEK_END);
1484 nFileSizeLow=unalz_ftell(m_files[i].fp);
1485 unalz_fseek(m_files[i].fp,0,SEEK_SET);
1486 #endif
1487 m_nFileCount++;
1488 m_files[i].nFileSize = ((INT64)nFileSizeLow) + (((INT64)dwFileSizeHigh)<<32);
1489 if(i==0) m_files[i].nMultivolHeaderSize = 0;
1490 else m_files[i].nMultivolHeaderSize = MULTIVOL_HEAD_SIZE;
1491 m_files[i].nMultivolTailSize = MULTIVOL_TAIL_SIZE;
1492 }
1493 free(temp);
1494 if(m_nFileCount==0) return FALSE;
1495 m_files[m_nFileCount-1].nMultivolTailSize = 0; //
1496 return TRUE;
1497 }
1498
1499 ////////////////////////////////////////////////////////////////////////////////////////////////////
1500 // @return
1501 // @date 2004-10-02 11:48:53
1502 ////////////////////////////////////////////////////////////////////////////////////////////////////
FClose()1503 void CUnAlz::FClose()
1504 {
1505 int i;
1506 #ifdef _WIN32
1507 for(i=0;i<m_nFileCount;i++) CloseHandle(m_files[i].fp);
1508 #else
1509 for(i=0;i<m_nFileCount;i++) fclose(m_files[i].fp);
1510 #endif
1511 memset(m_files, 0, sizeof(m_files));
1512 m_nFileCount = 0;
1513 m_nCurFile = -1;
1514 m_nVirtualFilePos = 0;
1515 m_nCurFilePos = 0;
1516 m_bIsEOF = FALSE;
1517
1518 }
1519
1520 ////////////////////////////////////////////////////////////////////////////////////////////////////
1521 // @return
1522 // @date 2004-10-02 11:48:21
1523 ////////////////////////////////////////////////////////////////////////////////////////////////////
FEof()1524 BOOL CUnAlz::FEof()
1525 {
1526 return m_bIsEOF;
1527 /*
1528 if(m_fp==NULL){ASSERT(0); return TRUE;}
1529 if(feof(m_fp)) return TRUE;
1530 return FALSE;
1531 */
1532 }
1533
1534
1535 ////////////////////////////////////////////////////////////////////////////////////////////////////
1536 // @return
1537 // @date 2004-10-02 11:50:50
1538 ////////////////////////////////////////////////////////////////////////////////////////////////////
FTell()1539 INT64 CUnAlz::FTell()
1540 {
1541 return m_nVirtualFilePos; // return ftell(m_fp);
1542 }
1543
1544 ////////////////////////////////////////////////////////////////////////////////////////////////////
1545 // @param offset
1546 // @param origin
1547 // @return
1548 // @date 2004-10-02 11:51:53
1549 ////////////////////////////////////////////////////////////////////////////////////////////////////
FSeek(INT64 offset)1550 BOOL CUnAlz::FSeek(INT64 offset)
1551 {
1552 m_nVirtualFilePos = offset;
1553 int i;
1554 INT64 remain=offset;
1555 LONG remainHigh;
1556
1557 m_bIsEOF = FALSE;
1558
1559 for(i=0;i<m_nFileCount;i++) //
1560 {
1561 if(remain<=m_files[i].nFileSize-m_files[i].nMultivolHeaderSize-m_files[i].nMultivolTailSize)
1562 {
1563 m_nCurFile = i;
1564 m_nCurFilePos = remain+m_files[i].nMultivolHeaderSize; //
1565 remainHigh = (LONG)((m_nCurFilePos>>32)&0xffffffff);
1566 #ifdef _WIN32
1567 SetFilePointer(m_files[i].fp, LONG(m_nCurFilePos), &remainHigh, FILE_BEGIN);
1568 #else
1569 unalz_fseek(m_files[i].fp, m_nCurFilePos, SEEK_SET);
1570 #endif
1571 return TRUE;
1572 }
1573 remain -= (m_files[i].nFileSize-m_files[i].nMultivolHeaderSize-m_files[i].nMultivolTailSize);
1574 }
1575
1576 //
1577 ASSERT(0);
1578 return FALSE;
1579 }
1580
1581 ////////////////////////////////////////////////////////////////////////////////////////////////////
1582 // @param buffer
1583 // @param size
1584 // @param count
1585 // @return
1586 // @date 2004-10-02 11:44:05
1587 ////////////////////////////////////////////////////////////////////////////////////////////////////
FRead(void * buffer,UINT32 nBytesToRead,int * pTotRead)1588 BOOL CUnAlz::FRead(void* buffer, UINT32 nBytesToRead, int* pTotRead )
1589 {
1590 BOOL ret;
1591 UINT32 nNumOfBytesRead;
1592 INT64 dwRemain;
1593 UINT32 dwRead;
1594 UINT32 dwTotRead;
1595
1596 dwRemain = nBytesToRead;
1597 dwTotRead = 0;
1598 if(pTotRead) *pTotRead=0;
1599
1600 while(dwRemain)
1601 {
1602 dwRead = (UINT32)min(dwRemain, (m_files[m_nCurFile].nFileSize-m_nCurFilePos-m_files[m_nCurFile].nMultivolTailSize));
1603 if(dwRead==0) {
1604 m_bIsEOF = TRUE;return FALSE;
1605 }
1606 #ifdef _WIN32
1607 ret = ReadFile(m_files[m_nCurFile].fp, ((BYTE*)buffer)+dwTotRead, dwRead, (DWORD*)&nNumOfBytesRead, NULL);
1608 if(ret==FALSE && GetLastError()==ERROR_HANDLE_EOF)
1609 {
1610 m_bIsEOF = TRUE;return FALSE;
1611 }
1612
1613 #else
1614 nNumOfBytesRead = fread(((BYTE*)buffer)+dwTotRead, 1,dwRead ,m_files[m_nCurFile].fp);
1615 if(nNumOfBytesRead<=0)
1616 {
1617 m_bIsEOF = TRUE;return FALSE;
1618 }
1619 ret=TRUE;
1620 #endif
1621 if(dwRead!=nNumOfBytesRead) //
1622 {
1623 ASSERT(0); return FALSE;
1624 }
1625
1626 m_nVirtualFilePos += nNumOfBytesRead; // virtual
1627
1628 m_nCurFilePos+=nNumOfBytesRead; //
1629 dwRemain-=nNumOfBytesRead;
1630 dwTotRead+=nNumOfBytesRead;
1631 if(pTotRead) *pTotRead=dwTotRead;
1632
1633 if(m_nCurFilePos==m_files[m_nCurFile].nFileSize-m_files[m_nCurFile].nMultivolTailSize) // overflow
1634 {
1635 m_nCurFile++;
1636
1637 #ifdef _WIN32
1638 if(m_files[m_nCurFile].fp==INVALID_HANDLE_VALUE)
1639 #else
1640 if(m_files[m_nCurFile].fp==NULL)
1641 #endif
1642 {
1643 m_bIsEOF = TRUE;
1644 if(dwRemain==0) return TRUE; //
1645 return FALSE;
1646 }
1647
1648 m_nCurFilePos = m_files[m_nCurFile].nMultivolHeaderSize; // header skip
1649 #ifdef _WIN32
1650 SetFilePointer(m_files[m_nCurFile].fp, (int)m_nCurFilePos, NULL, FILE_BEGIN);
1651 #else
1652 unalz_fseek(m_files[m_nCurFile].fp, m_nCurFilePos, SEEK_SET);
1653 #endif
1654 }
1655 else
1656 if(m_nCurFilePos>m_files[m_nCurFile].nFileSize-m_files[m_nCurFile].nMultivolTailSize) ASSERT(0);
1657 }
1658
1659 return ret;
1660 }
1661
1662 ////////////////////////////////////////////////////////////////////////////////////////////////////
1663 // error code
1664 // @param nERR
1665 // @return
1666 // @date 2004-10-24 3:28:39
1667 ////////////////////////////////////////////////////////////////////////////////////////////////////
LastErrToStr(ERR nERR)1668 const char* CUnAlz::LastErrToStr(ERR nERR)
1669 {
1670 if(nERR>= sizeof(errorstrtable)/sizeof(errorstrtable[0])) {ASSERT(0); return NULL; }
1671 return errorstrtable[nERR];
1672 }
1673
1674
1675 // by xf86
chkValidPassword()1676 BOOL CUnAlz::chkValidPassword()
1677 {
1678 if(IsEncryptedFile()==FALSE) {return TRUE;}
1679
1680 if (getPasswordLen() == 0){
1681 m_nErr = ERR_PASSWD_NOT_SET;
1682 return FALSE;
1683 }
1684 InitCryptKeys(m_szPasswd);
1685 if(CryptCheck(m_posCur->encChk) == FALSE){
1686 m_nErr = ERR_INVALID_PASSWD;
1687 return FALSE;
1688 }
1689 return TRUE;
1690 }
1691
1692 /*
1693 ////////////////////////////////////////////////////////////////////////////////////////////////////
1694 // from CZipArchive
1695 // Copyright (C) 2000 - 2004 Tadeusz Dracz
1696 //
1697 // http://www.artpol-software.com
1698 //
1699 // it's under GPL.
1700 ////////////////////////////////////////////////////////////////////////////////////////////////////
1701 void CUnAlz::CryptDecodeBuffer(UINT32 uCount, CHAR *buf)
1702 {
1703 if (IsEncrypted())
1704 for (UINT32 i = 0; i < uCount; i++)
1705 CryptDecode(buf[i]);
1706 }
1707
1708 void CUnAlz::CryptInitKeys()
1709 {
1710 m_keys[0] = 305419896L;
1711 m_keys[1] = 591751049L;
1712 m_keys[2] = 878082192L;
1713 for (int i = 0; i < strlen(m_szPasswd); i++)
1714 CryptUpdateKeys(m_szPasswd[i]);
1715 }
1716
1717 void CUnAlz::CryptUpdateKeys(CHAR c)
1718 {
1719
1720 m_keys[0] = CryptCRC32(m_keys[0], c);
1721 m_keys[1] += m_keys[0] & 0xff;
1722 m_keys[1] = m_keys[1] * 134775813L + 1;
1723 c = CHAR(m_keys[1] >> 24);
1724 m_keys[2] = CryptCRC32(m_keys[2], c);
1725 }
1726
1727 BOOL CUnAlz::CryptCheck(CHAR *buf)
1728 {
1729 CHAR b = 0;
1730 for (int i = 0; i < ALZ_ENCR_HEADER_LEN; i++)
1731 {
1732 b = buf[i];
1733 CryptDecode((CHAR&)b);
1734 }
1735
1736 if (IsDataDescr()) // Data descriptor present
1737 return CHAR(m_posCur->head.fileTimeDate >> 8) == b;
1738 else
1739 return CHAR(m_posCur->maybeCRC >> 24) == b;
1740 }
1741
1742 CHAR CUnAlz::CryptDecryptCHAR()
1743 {
1744 int temp = (m_keys[2] & 0xffff) | 2;
1745 return (CHAR)(((temp * (temp ^ 1)) >> 8) & 0xff);
1746 }
1747
1748 void CUnAlz::CryptDecode(CHAR &c)
1749 {
1750 c ^= CryptDecryptCHAR();
1751 CryptUpdateKeys(c);
1752 }
1753
1754 UINT32 CUnAlz::CryptCRC32(UINT32 l, CHAR c)
1755 {
1756 const ULONG *CRC_TABLE = get_crc_table();
1757 return CRC_TABLE[(l ^ c) & 0xff] ^ (l >> 8);
1758 }
1759 */
1760
1761 ////////////////////////////////////////////////////////////////////////////////////////////////////
1762 // @param fileDescriptor
1763 // @return
1764 // @date 2004-11-27 11:25:32
1765 ////////////////////////////////////////////////////////////////////////////////////////////////////
IsEncryptedFile(BYTE fileDescriptor)1766 BOOL CUnAlz::IsEncryptedFile(BYTE fileDescriptor)
1767 {
1768 return fileDescriptor&0x01;
1769 }
IsEncryptedFile()1770 BOOL CUnAlz::IsEncryptedFile()
1771 {
1772 return m_posCur->head.fileDescriptor&0x01;
1773 }
1774
1775 ////////////////////////////////////////////////////////////////////////////////////////////////////
1776 // @param szPassword
1777 // @return
1778 // @date 2004-11-27 11:04:01
1779 ////////////////////////////////////////////////////////////////////////////////////////////////////
InitCryptKeys(const CHAR * szPassword)1780 void CUnAlz::InitCryptKeys(const CHAR* szPassword)
1781 {
1782 m_key[0] = 305419896;
1783 m_key[1] = 591751049;
1784 m_key[2] = 878082192;
1785
1786 int i;
1787 for(i=0;i<(int)strlen(szPassword);i++)
1788 {
1789 UpdateKeys(szPassword[i]);
1790 }
1791 }
1792
1793 ////////////////////////////////////////////////////////////////////////////////////////////////////
1794 // @param c
1795 // @return
1796 // @date 2004-11-27 11:04:09
1797 ////////////////////////////////////////////////////////////////////////////////////////////////////
UpdateKeys(BYTE c)1798 void CUnAlz::UpdateKeys(BYTE c)
1799 {
1800 m_key[0] = CRC32(m_key[0], c);
1801 m_key[1] = m_key[1]+(m_key[0]&0x000000ff);
1802 m_key[1] = m_key[1]*134775813+1;
1803 m_key[2] = CRC32(m_key[2],m_key[1]>>24);
1804 }
1805
1806 ////////////////////////////////////////////////////////////////////////////////////////////////////
1807 // @param buf
1808 // @return
1809 // @date 2004-11-27 11:04:24
1810 ////////////////////////////////////////////////////////////////////////////////////////////////////
CryptCheck(const BYTE * buf)1811 BOOL CUnAlz::CryptCheck(const BYTE* buf)
1812 {
1813 int i;
1814 BYTE c;
1815 BYTE temp[ALZ_ENCR_HEADER_LEN];
1816
1817 memcpy(temp, buf, ALZ_ENCR_HEADER_LEN); //
1818
1819 for(i=0;i<ALZ_ENCR_HEADER_LEN;i++)
1820 {
1821 c = temp[i] ^ DecryptByte();
1822 UpdateKeys(c);
1823 temp[i] = c;
1824 }
1825
1826 if (IsDataDescr()) // Data descriptor present
1827 return (m_posCur->head.fileTimeDate >> 8) == c;
1828 else
1829 return ( ((m_posCur->fileCRC)>>24) ) == c; // crc byte
1830 }
1831
1832 ////////////////////////////////////////////////////////////////////////////////////////////////////
1833 // @return
1834 // @date 2004-11-27 11:05:36
1835 ////////////////////////////////////////////////////////////////////////////////////////////////////
DecryptByte()1836 BYTE CUnAlz::DecryptByte()
1837 {
1838 UINT16 temp;
1839 temp = m_key[2] | 2;
1840 return (temp * (temp^1))>>8;
1841 }
1842
1843 ////////////////////////////////////////////////////////////////////////////////////////////////////
1844 // @param nSize
1845 // @param data
1846 // @return
1847 // @date 2004-11-27 11:03:30
1848 ////////////////////////////////////////////////////////////////////////////////////////////////////
DecryptingData(int nSize,BYTE * data)1849 void CUnAlz::DecryptingData(int nSize, BYTE* data)
1850 {
1851 BYTE* p = data;
1852 BYTE temp;
1853
1854 while(nSize)
1855 {
1856 temp = *p ^ DecryptByte();
1857 UpdateKeys(temp);
1858 *p = temp;
1859 nSize--;
1860 p++;
1861 }
1862 }
1863
1864 ////////////////////////////////////////////////////////////////////////////////////////////////////
1865 // CRC
1866 // @param l
1867 // @param c
1868 // @return
1869 // @date 2004-11-27 11:14:16
1870 ////////////////////////////////////////////////////////////////////////////////////////////////////
CRC32(UINT32 l,BYTE c)1871 UINT32 CUnAlz::CRC32(UINT32 l, BYTE c)
1872 {
1873 #ifndef Z_U4
1874 const unsigned long *CRC_TABLE = get_crc_table();
1875 #else
1876 const Z_U4 *CRC_TABLE = get_crc_table();
1877 #endif
1878 return CRC_TABLE[(l ^ c) & 0xff] ^ (l >> 8);
1879 }
1880
SetPassword(char * passwd)1881 void CUnAlz::SetPassword(char *passwd)
1882 {
1883 if(strlen(passwd) == 0) return;
1884 safe_strcpy(m_szPasswd, passwd, UNALZ_LEN_PASSWORD);
1885 }
1886
1887 #ifdef _UNALZ_ICONV
SetDestCodepage(const char * szToCodepage)1888 void CUnAlz::SetDestCodepage(const char* szToCodepage)
1889 {
1890 safe_strcpy(m_szToCodepage, szToCodepage, UNALZ_LEN_CODEPAGE);
1891 }
1892 #endif
1893
1894 ////////////////////////////////////////////////////////////////////////////////////////////////////
1895 // @param l
1896 // @param c
1897 // @return
1898 // @date 2007-02
1899 ////////////////////////////////////////////////////////////////////////////////////////////////////
_strlcpy(char * dest,const char * src,unsigned int size)1900 unsigned int CUnAlz::_strlcpy (char *dest, const char *src, unsigned int size)
1901 {
1902 register unsigned int i = 0;
1903 if (size > 0) {
1904 size--;
1905 for (i=0; size > 0 && src[i] != '\0'; ++i, size--)
1906 dest[i] = src[i];
1907 dest[i] = '\0';
1908 }
1909 while (src[i++]);
1910 return i;
1911 }
_strlcat(char * dest,const char * src,unsigned int size)1912 unsigned int CUnAlz::_strlcat (char *dest, const char *src, unsigned int size)
1913 {
1914 register char *d = dest;
1915 for (; size > 0 && *d != '\0'; size--, d++);
1916 return (d - dest) + _strlcpy(d, src, size);
1917 }
1918
1919 // strcpy
safe_strcpy(char * dst,const char * src,size_t dst_size)1920 void CUnAlz::safe_strcpy(char* dst, const char* src, size_t dst_size)
1921 {
1922 #ifdef _WIN32
1923 lstrcpynA(dst, src, dst_size);
1924 #else
1925 _strlcpy(dst, src, dst_size);
1926 #endif
1927 }
1928
safe_strcat(char * dst,const char * src,size_t dst_size)1929 void CUnAlz::safe_strcat(char* dst, const char* src, size_t dst_size)
1930 {
1931 #ifdef _WIN32
1932 StringCchCatExA(dst, dst_size, src, NULL, NULL, STRSAFE_FILL_BEHIND_NULL);
1933 //lstrcatA(dst, src); // not safe!!
1934 #else
1935 _strlcat(dst, src, dst_size);
1936 #endif
1937 }
1938