00001 // $Id: zstream.cpp 1282 2006-06-09 09:46:49Z alex $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 // 00099 // A file which encapsulates the zipped file streaming routines and data. 00100 // Used to compress/uncompress the native files. 00101 00102 /* 00103 */ 00104 00105 #include "camtypes.h" 00106 //#include "fixmem.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00107 //#include "errors.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00108 00109 #include "zstream.h" 00110 #include "zdeflate.h" 00111 #include "zinflate.h" 00112 00113 // This is not compulsory, but you may as well put it in so that the correct version 00114 // of your file can be registered in the .exe 00115 DECLARE_SOURCE("$Revision: 1282 $"); 00116 00117 // An implement to match the Declare in the .h file. 00118 // If you have many classes, it is recommended to place them all together, here at the start of the file 00119 CC_IMPLEMENT_MEMDUMP(ZStream, CC_CLASS_MEMDUMP) 00120 CC_IMPLEMENT_MEMDUMP(GZipStream, CC_CLASS_MEMDUMP) 00121 CC_IMPLEMENT_MEMDUMP(GZipFile, CC_CLASS_MEMDUMP) 00122 00123 // This will get Camelot to display the filename and linenumber of any memory allocations 00124 // that are not released at program exit 00125 // Declare smart memory handling in Debug builds 00126 #define new CAM_DEBUG_NEW 00127 00128 // Some useful zip bits 00129 #if RALPH 00130 #define Z_BUFSIZE 32 // was 4096 00131 #else 00132 #define Z_BUFSIZE 32*1024 // was 4096 00133 #endif 00134 00135 //#define ALLOC(size) zcalloc((voidp)0, 1, size) 00136 //#define TRYFREE(p) {if (p) zcfree((voidp)0, p);} 00137 #define ALLOC(size) CCMalloc(size) 00138 #define TRYFREE(p) {if (p) { CCFree(p); p = NULL; } } 00139 00140 //#define GZ_MAGIC_1 0x1f 00141 //#define GZ_MAGIC_2 0x8b 00142 00143 //static INT32 gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ 00144 00145 /* gzip flag byte */ 00146 #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ 00147 #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ 00148 #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ 00149 #define ORIG_NAME 0x08 /* bit 3 set: original file name present */ 00150 #define COMMENT 0x10 /* bit 4 set: file comment present */ 00151 #define RESERVED 0xE0 /* bits 5..7: reserved */ 00152 00153 #ifndef SEEK_CUR 00154 # define SEEK_CUR 1 00155 #endif 00156 00157 /* ---------------------------------- ZStream class -------------------------------------- */ 00158 00159 /******************************************************************************************** 00160 00161 > ZStream::ZStream() 00162 00163 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00164 Created: 34/05/95 00165 Purpose: ZStream constructor. 00166 00167 ********************************************************************************************/ 00168 00169 ZStream::ZStream() 00170 { 00171 next_in = NULL; 00172 avail_in = 0; 00173 total_in = 0; 00174 00175 next_out = NULL; 00176 avail_out = 0; 00177 total_out = 0; 00178 00179 msg = NULL; 00180 00181 In_state = NULL; 00182 De_state = NULL; 00183 00184 zalloc = (alloc_func)0; 00185 zfree = (free_func)0; 00186 00187 data_type = Z_BINARY; 00188 adler = 0; 00189 reserved = 0; 00190 00191 zlib_version = ZLIB_VERSION; 00192 } 00193 00194 /******************************************************************************************** 00195 00196 > ZStream::ZStream() 00197 00198 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00199 Created: 34/05/95 00200 Purpose: ZStream destructor. 00201 00202 ********************************************************************************************/ 00203 00204 ZStream::~ZStream() 00205 { 00206 if (In_state) 00207 { 00208 delete In_state; 00209 In_state = NULL; 00210 } 00211 #ifdef DO_EXPORT 00212 if (De_state) 00213 { 00214 delete De_state; 00215 De_state = NULL; 00216 } 00217 #endif 00218 } 00219 00220 00221 /* ------------------------------- GZipStream class -------------------------------------- */ 00222 00223 /******************************************************************************************** 00224 00225 > GZipStream::GZipStream() 00226 00227 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00228 Created: 34/05/95 00229 Purpose: GZipStream constructor. 00230 00231 ********************************************************************************************/ 00232 00233 GZipStream::GZipStream() 00234 { 00235 z_err = Z_OK; 00236 z_eof = 0; 00237 00238 file = NULL; 00239 inbuf = NULL; 00240 outbuf = NULL; 00241 00242 crc = 0; 00243 crc = GZipFile::crc32(0L, NULL, 0); 00244 msg = NULL; 00245 path = NULL; 00246 transparent = 0; 00247 00248 Peek = FALSE; // no value peeked 00249 PeekedValue = '#'; // random value 00250 PeekStatus = Z_OK; // status ok 00251 00252 InitialPos = 0; 00253 00254 Inited = FALSE; 00255 } 00256 00257 /******************************************************************************************** 00258 00259 > GZipStream::~GZipStream() 00260 00261 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00262 Created: 34/05/95 00263 Purpose: GZipStream destructor. 00264 00265 ********************************************************************************************/ 00266 00267 GZipStream::~GZipStream() 00268 { 00269 // Try and free up the buffers that we have allocated 00270 TRYFREE(inbuf); 00271 TRYFREE(outbuf); 00272 TRYFREE(path); 00273 TRYFREE(msg); 00274 } 00275 00276 00277 /* --------------------------------- GZipFile class -------------------------------------- */ 00278 00279 /******************************************************************************************** 00280 00281 > GZipFile::GZipFile() 00282 00283 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00284 Created: 34/05/95 00285 Purpose: GZipFile constructor. 00286 00287 ********************************************************************************************/ 00288 00289 GZipFile::GZipFile() 00290 { 00291 deflate = NULL; 00292 inflate = NULL; 00293 } 00294 00295 /******************************************************************************************** 00296 00297 > GZipFile::~GZipFile() 00298 00299 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00300 Created: 34/05/95 00301 Purpose: GZipFile destructor. 00302 00303 ********************************************************************************************/ 00304 00305 GZipFile::~GZipFile() 00306 { 00307 #ifdef DO_EXPORT 00308 // Remove the deflate class, if present 00309 if (deflate != NULL) 00310 { 00311 delete deflate; 00312 deflate = NULL; 00313 } 00314 #endif 00315 00316 // Remove the inflate class, if present 00317 if (inflate != NULL) 00318 { 00319 delete inflate; 00320 inflate = NULL; 00321 } 00322 } 00323 00324 /******************************************************************************************** 00325 00326 > static double GZipFile::GetStreamVersionNo() 00327 00328 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00329 Created: 30/05/95 00330 Returns: the current version number of the stream in the form 0.92 00331 Purpose: To find out the current version number of the stream and hence files which 00332 it can recoknise. The verison is of the form 0.92. 00333 00334 ********************************************************************************************/ 00335 00336 double GZipFile::GetStreamVersionNo() 00337 { 00338 return ZLIB_VERSIONNO; 00339 } 00340 00341 /******************************************************************************************** 00342 00343 > INT32 GZipFile::destroy(GZipStream *s) 00344 00345 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00346 Created: 24/05/95 00347 Purpose: Cleanup then free the given GZipStream. Return a zlib error code. 00348 Assume caller will close the file. 00349 00350 ********************************************************************************************/ 00351 00352 INT32 GZipFile::destroy(GZipStream *s) 00353 { 00354 TRACEUSER( "Neville", _T("GZipFile::gzflush\n")); 00355 00356 // Check that a valid stream has been passed in 00357 if (!s) return Z_STREAM_ERROR; 00358 00359 INT32 err = Z_OK; 00360 00361 // Try and free up the buffers that we have allocated 00362 TRYFREE(s->inbuf); 00363 TRYFREE(s->outbuf); 00364 TRYFREE(s->path); 00365 TRYFREE(s->msg); 00366 00367 if (s->mode == 'w') 00368 { 00369 #ifdef DO_EXPORT 00370 if (s->stream.De_state != NULL && deflate != NULL) 00371 err = deflate->End(&(s->stream)); 00372 00373 // Now remove the deflate class, if present 00374 if (deflate != NULL) 00375 { 00376 delete deflate; 00377 deflate = NULL; 00378 } 00379 #endif 00380 } 00381 else if (s->mode == 'r') 00382 { 00383 if (s->stream.In_state != NULL && inflate != NULL) 00384 err = inflate->End(&(s->stream)); 00385 00386 // Now remove the inflate class, if present 00387 if (inflate != NULL) 00388 { 00389 delete inflate; 00390 inflate = NULL; 00391 } 00392 } 00393 00394 // If we had a file claimed then try and close it 00395 // Assume this is done by the caller as in the native file save we still have some 00396 // bits to write out to the file. 00397 // Assume pointer is of no use anymore so set to NULL. 00398 s->file = NULL; 00399 00400 if (s->z_err < 0) 00401 err = s->z_err; 00402 00403 // free up our ZipStream object 00404 delete s; 00405 s = NULL; 00406 00407 return err; 00408 } 00409 00410 //static const Bytef dictionary[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 00411 //static const uInt dictionary_size = 8; 00412 00413 /******************************************************************************************** 00414 00415 > GZipStream *GZipFile::gz_init(iostream *pFileStream, TCHAR *mode, BOOL Header = FALSE) 00416 00417 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00418 Created: 1/06/95 00419 Inputs: pFileStream the iostream class to use for reading/writing 00420 mode rw mode for this file 00421 00422 Purpose: Initialises the compression system and tries to grab the memory required. 00423 gz_init returns NULL if there was insufficient memory to allocate the 00424 (de)compression state; errno can be checked to distinguish the two cases 00425 (if errno is zero, the zlib error is Z_MEM_ERROR). 00426 Graeme ( 15/11/99) : Added the Header parameter to the parameter list. 00427 This enables the GZipStream to be initialised so that it writes the ZLib 00428 header, which was previously supressed. 00429 00430 ********************************************************************************************/ 00431 00432 GZipStream *GZipFile::gz_init(iostream *pFileStream, TCHAR *mode, BOOL Header) 00433 { 00434 TRACEUSER( "Neville", _T("GZipFile::gz_init\n")); 00435 00436 if (pFileStream == NULL) 00437 { 00438 ERROR3("GZipFile::gz_open Expects file class to be supplied and open as of yet!"); 00439 return NULL; 00440 } 00441 00442 GZipStream *s = new GZipStream; 00443 if (!s) return NULL; 00444 00445 s->stream.zalloc = (alloc_func)0; 00446 s->stream.zfree = (free_func)0; 00447 s->stream.next_in = NULL; 00448 s->inbuf = NULL; 00449 s->stream.next_out = NULL; 00450 s->outbuf = NULL; 00451 s->stream.avail_in = 0; 00452 s->stream.avail_out = 0; 00453 s->file = pFileStream; // will be NULL if wanting it to be opened 00454 s->z_err = Z_OK; 00455 s->z_eof = 0; 00456 s->crc = crc32(0L, NULL, 0); 00457 s->msg = NULL; 00458 s->transparent = 0; 00459 s->Peek = FALSE; // no value peeked 00460 s->PeekedValue = '#'; // random value 00461 s->PeekStatus = 0; // status 0 bytes present 00462 00463 // Work our whether we are reading or writing from the supplied mode 00464 TCHAR *p = mode; 00465 s->mode = '\0'; 00466 do 00467 { 00468 if( *p == _T('r') ) 00469 s->mode = _T('r'); 00470 if( *p == _T('w') ) 00471 s->mode = _T('w'); 00472 } while (*p++); 00473 00474 if( s->mode == _T('\0') ) 00475 { 00476 destroy(s); 00477 return NULL; 00478 } 00479 00480 INT32 err; 00481 if( s->mode == _T('w') ) 00482 { 00483 #ifdef DO_EXPORT 00484 // First, create the deflate class ready for use 00485 deflate = new ZipDeflate; 00486 if (deflate == NULL) 00487 { 00488 destroy(s); 00489 return NULL; 00490 } 00491 00492 // Now initialise it, ready for use. 00493 // Graeme ( 15/11/99 ) - Added the switch on Header to allow for the 00494 // zlib header. 00495 if ( Header ) 00496 { 00497 // Initialise using MAX_WBITS, so that the ZLib header is created. 00498 err = deflate->Init(&(s->stream), Z_DEFAULT_COMPRESSION, 00499 DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, 0); 00500 } 00501 else 00502 { 00503 // windowBits is passed < 0 to suppress zlib header. 00504 err = deflate->Init(&(s->stream), Z_DEFAULT_COMPRESSION, 00505 DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0); 00506 } 00507 00508 s->stream.next_out = (Byte*) ALLOC(Z_BUFSIZE); 00509 s->outbuf = s->stream.next_out; 00510 s->stream.avail_out = Z_BUFSIZE; 00511 00512 if (err != Z_OK || s->outbuf == NULL) 00513 { 00514 destroy(s); 00515 return NULL; 00516 } 00517 00518 /* err = deflate->SetDictionary(&(s->stream), dictionary, dictionary_size); 00519 if (err != Z_OK) 00520 { 00521 destroy(s); 00522 return NULL; 00523 } */ 00524 #else 00525 return NULL; 00526 #endif 00527 } 00528 else 00529 { 00530 // First, create the inflate class ready for use 00531 inflate = new ZipInflate; 00532 if (inflate == NULL) 00533 { 00534 destroy(s); 00535 return NULL; 00536 } 00537 00538 err = inflate->Init(&(s->stream), -MAX_WBITS); 00539 s->inbuf = (Byte*) ALLOC(Z_BUFSIZE); 00540 s->stream.next_in = s->inbuf; 00541 00542 if (err != Z_OK || s->inbuf == NULL) 00543 { 00544 destroy(s); 00545 return NULL; 00546 } 00547 00548 /* err = inflate->SetDictionary(&(s->stream), dictionary, dictionary_size); 00549 if (err != Z_OK) 00550 { 00551 destroy(s); 00552 return NULL; 00553 } */ 00554 } 00555 00556 s->Inited = TRUE; 00557 00558 return s; 00559 } 00560 00561 /******************************************************************************************** 00562 00563 > INT32 GZipFile::gz_open(GZipStream *s) 00564 00565 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00566 Created: 1/06/95 00567 Inputs: s the zip stream that we should be using 00568 00569 Purpose: The form of open if we have already called init. 00570 At present, this is fairly simple and just checks out a few things 00571 00572 ********************************************************************************************/ 00573 00574 INT32 GZipFile::gz_open(GZipStream *s) 00575 { 00576 TRACEUSER( "Neville", _T("GZipFile::gz_open init already called\n")); 00577 00578 // check that everyhting is valid before preceeding 00579 if (s == NULL) return Z_STREAM_ERROR; 00580 00581 // Check if init has been called 00582 if (!s->Inited) 00583 return Z_STREAM_ERROR; 00584 00585 // Note the current position in the file for later use 00586 s->InitialPos = s->file->tellg(); 00587 00588 // check if there is an actual file stream class attached 00589 if (s->file == NULL) 00590 { 00591 destroy(s); 00592 return 0; 00593 } 00594 00595 // Check if reading and already at end of file 00596 if (s->mode == 'r' && s->file->eof()) 00597 { 00598 s->z_err = Z_DATA_ERROR; 00599 return Z_DATA_ERROR; 00600 } 00601 00602 // Check if reading and the next bytes are not compressed 00603 if (s->mode == 'r') 00604 { 00605 s->stream.avail_in = 15; 00606 s->file->read( (char *)s->inbuf, s->stream.avail_in ); 00607 // Seek back to where we were before we started this test 00608 s->file->seekp(s->InitialPos); 00609 if (s->stream.avail_in == 15) 00610 { 00611 // If we find the following words then the data is not compressed 00612 // We must fail but cleanly as all we need to do is read it uncomrpessed 00613 if( strncmp( (PCSTR)s->inbuf, "%%AWColourTable", 15 ) == 0 ) 00614 { 00615 s->stream.avail_in = 0; 00616 s->z_err = Z_UNCOMPRESSED_ERROR; 00617 return Z_UNCOMPRESSED_ERROR; 00618 } 00619 s->stream.avail_in = 0; 00620 } 00621 else 00622 { 00623 s->z_err = Z_DATA_ERROR; 00624 return Z_DATA_ERROR; 00625 } 00626 } 00627 00628 // Everything went ok 00629 return Z_OK; 00630 } 00631 00632 /******************************************************************************************** 00633 00634 > GZipStream *GZipFile::gz_open(iostream* pFileStream, TCHAR *mode, TCHAR *path) 00635 00636 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00637 Created: 24/05/95 00638 Inputs: pFileStream the iostream class to use for reading/writing 00639 mode rw mode for this file 00640 path pathname for this file (optional) 00641 00642 Purpose: Opens a gzip file for reading or writing. The mode parameter is as in fopen 00643 ("rb" or "wb"). 00644 The stream is given at present by the iostream class, the patname is 00645 optional and is just used for debugging. 00646 00647 gz_open return NULL if the stream could not be opened or if there was 00648 insufficient memory to allocate the (de)compression state; errno 00649 can be checked to distinguish the two cases (if errno is zero, the 00650 zlib error is Z_MEM_ERROR). 00651 00652 ********************************************************************************************/ 00653 00654 GZipStream *GZipFile::gz_open(iostream* pFileStream, TCHAR *mode, TCHAR *path ) 00655 { 00656 TRACEUSER( "Neville", _T("GZipFile::gz_open\n")); 00657 00658 if (pFileStream == NULL) 00659 { 00660 ERROR3("GZipFile::gz_open Expects file class to be supplied and open as of yet!"); 00661 return NULL; 00662 } 00663 00664 INT32 err; 00665 TCHAR *p = mode; 00666 00667 GZipStream *s = new GZipStream; 00668 if (!s) return NULL; 00669 00670 s->stream.zalloc = (alloc_func) 0; 00671 s->stream.zfree = (free_func) 0; 00672 s->stream.next_in = NULL; 00673 s->inbuf = NULL; 00674 s->stream.next_out = NULL; 00675 s->outbuf = NULL; 00676 s->stream.avail_in = 0; 00677 s->stream.avail_out = 0; 00678 s->file = pFileStream; // will be NULL if wanting it to be opened 00679 s->z_err = Z_OK; 00680 s->z_eof = 0; 00681 s->crc = crc32(0L, NULL, 0); 00682 s->msg = NULL; 00683 s->transparent = 0; 00684 00685 // Our extra bits 00686 s->Peek = FALSE; // no value peeked 00687 s->PeekedValue = '#'; // random value 00688 s->PeekStatus = 0; // status 0 bytes present 00689 s->path = NULL; 00690 00691 if (path != NULL) 00692 { 00693 s->path = (TCHAR*) ALLOC((camStrlen(path) + 1) * sizeof(TCHAR)); 00694 if (s->path == NULL) 00695 { 00696 destroy(s); 00697 return NULL; 00698 } 00699 00700 camStrcpy(s->path, path); /* do this early for debugging */ 00701 } 00702 00703 // Note the current position in the file for later use 00704 s->InitialPos = s->file->tellg(); 00705 00706 // Work our whether we are reading or writing from the supplied mode 00707 s->mode = '\0'; 00708 do 00709 { 00710 if (*p == 'r') s->mode = 'r'; 00711 if (*p == 'w') s->mode = 'w'; 00712 } while (*p++); 00713 00714 if (s->mode == '\0') 00715 { 00716 destroy(s); 00717 return NULL; 00718 } 00719 00720 if (s->mode == 'w') 00721 { 00722 #ifdef DO_EXPORT 00723 // First, create the deflate class ready for use 00724 deflate = new ZipDeflate; 00725 if (deflate == NULL) 00726 { 00727 destroy(s); 00728 return NULL; 00729 } 00730 00731 // Now initialise it, ready for use 00732 err = deflate->Init(&(s->stream), Z_DEFAULT_COMPRESSION, 00733 DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0); 00734 /* windowBits is passed < 0 to suppress zlib header */ 00735 00736 s->stream.next_out = (Byte*) ALLOC(Z_BUFSIZE); 00737 s->outbuf = s->stream.next_out; 00738 00739 if (err != Z_OK || s->outbuf == NULL) 00740 { 00741 destroy(s); 00742 return NULL; 00743 } 00744 00745 s->stream.avail_out = Z_BUFSIZE; 00746 00747 /* err = deflate->SetDictionary(&(s->stream), dictionary, dictionary_size); 00748 if (err != Z_OK) 00749 { 00750 destroy(s); 00751 return NULL; 00752 } */ 00753 #else 00754 return NULL; 00755 #endif 00756 } 00757 else 00758 { 00759 // First, create the inflate class ready for use 00760 inflate = new ZipInflate; 00761 if (inflate == NULL) 00762 { 00763 destroy(s); 00764 return NULL; 00765 } 00766 00767 err = inflate->Init(&(s->stream), -MAX_WBITS); 00768 s->inbuf = (Byte*) ALLOC(Z_BUFSIZE); 00769 s->stream.next_in = s->inbuf; 00770 00771 if (err != Z_OK || s->inbuf == NULL) 00772 { 00773 destroy(s); 00774 return NULL; 00775 } 00776 00777 /*err = inflate->SetDictionary(&(s->stream), dictionary, dictionary_size); 00778 if (err != Z_OK) 00779 { 00780 destroy(s); 00781 return NULL; 00782 } */ 00783 } 00784 // Moved from inside write clause by 0.99 upgrade 00785 //s->stream.avail_out = Z_BUFSIZE; 00786 00787 if (s->file == NULL) 00788 { 00789 destroy(s); 00790 return NULL; 00791 } 00792 00793 // All simple header writing code is done by the native file class 00794 // All header/compression verison checking is done by the native file class 00795 if (s->mode == 'r') 00796 { 00797 // This is all done in the native file filter so need to do it here 00798 // reset buffer back to zero ready for the true data itself 00799 s->stream.avail_in = 0; 00800 00801 if (s->file->eof()) 00802 { 00803 s->z_err = Z_DATA_ERROR; 00804 } 00805 00806 // Check if reading and the next bytes are not compressed 00807 s->stream.avail_in = 15; 00808 s->file->read( (char *)s->inbuf, s->stream.avail_in ); 00809 // Seek back to where we were before we started this test 00810 s->file->seekg(s->InitialPos); 00811 if (s->stream.avail_in == 15) 00812 { 00813 // If we find the following words then the data is not compressed 00814 // We must fail but cleanly as all we need to do is read it uncomrpessed 00815 if( strncmp( (char *)s->inbuf, "%%AWColourTable", 15 ) == 0 ) 00816 { 00817 s->stream.avail_in = 0; 00818 s->z_err = Z_UNCOMPRESSED_ERROR; 00819 return s; 00820 } 00821 s->stream.avail_in = 0; 00822 } 00823 else 00824 { 00825 s->z_err = Z_DATA_ERROR; 00826 return s; 00827 } 00828 } 00829 00830 s->Inited = TRUE; 00831 00832 return s; 00833 } 00834 00835 /******************************************************************************************** 00836 00837 > INT32 GZipFile::gzpeek(GZipStream *file, TCHAR data) 00838 00839 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00840 Created: 24/05/95 00841 Inputs: s the zip stream that we should be using 00842 buf the character that we are to return 00843 Returns: number of uncompressed bytes actually read (0 for end of file, -1 for error) 00844 Purpose: Reads the next byte from the input stream and returns this to the caller. 00845 It then remembers this value for the next read. 00846 gzread returns the number of uncompressed bytes actually read (0 for 00847 end of file, -1 for error). 00848 00849 ********************************************************************************************/ 00850 00851 INT32 GZipFile::gzpeek( GZipStream *s, char *buf ) 00852 { 00853 // check that everyhting is valid before preceeding 00854 if (s == NULL || s->mode != 'r' || inflate == NULL || buf == NULL) return Z_STREAM_ERROR; 00855 00856 // First check for problem states from last reading/peeking 00857 if (s->z_err == Z_DATA_ERROR) return -1; /* bad .gz file */ 00858 if (s->z_err == Z_STREAM_END) return 0; /* don't read crc as data */ 00859 00860 // first check if we are in the peeked state already 00861 if (s->PeekStatus > 0) 00862 { 00863 // just return the peeked character 00864 // add in the values from the peeks 00865 ERROR3IF(s->PeekStatus > 1,"peek with status > 1"); 00866 buf[0] = s->PeekedValue; // set first byte to be the peeked value 00867 00868 // return amount read to caller 00869 return 1; 00870 } 00871 00872 Byte *b = (Byte*)buf; 00873 s->stream.next_out = b; 00874 00875 // remember the current uncompressed buffer size as this will give us where 00876 unsigned offset = s->stream.avail_out; 00877 if(offset !=0) 00878 ERROR3IF(offset != 0,"peek offset not zero"); 00879 s->stream.avail_out += 1; // we want 1 character 00880 00881 while (s->stream.avail_out != 0) 00882 { 00883 if (s->stream.avail_in == 0 && !s->z_eof) 00884 { 00885 s->stream.avail_in = Z_BUFSIZE; 00886 // Note the current file position 00887 FilePos Pos = s->file->tellg(); 00888 s->file->read((char *) s->inbuf, s->stream.avail_in ); 00889 FilePos PosAfter = s->file->tellg(); 00890 s->stream.avail_in = PosAfter- Pos; 00891 TRACEUSER( "Neville", _T("GZipFile::gz_peek filled buffer size %d\n"),s->stream.avail_in); 00892 if (s->stream.avail_in == 0) 00893 { 00894 s->z_eof = 1; 00895 // s->file->setf(s->file->eofbit); 00896 00897 } 00898 /* else if (s->stream.avail_in == (uInt)EOF) 00899 { 00900 // s->stream.avail_in = 0; 00901 s->z_eof = 1; 00902 // s->z_err = Z_ERRNO; 00903 // break; 00904 }*/ 00905 else if (s->stream.avail_in < Z_BUFSIZE || s->file->eof()) 00906 { 00907 // We are at the end of the file but have read some data in 00908 // We must set the goodbit to clear the eof and fail bits as otherwise 00909 // all the checks in the diskfile will then fail. 00910 s->z_eof = 1; 00911 s->file->clear(s->file->goodbit); 00912 } 00913 s->stream.next_in = s->inbuf; 00914 } 00915 s->z_err = inflate->inflate(&(s->stream), Z_NO_FLUSH); 00916 00917 if (s->z_err == Z_STREAM_END || 00918 s->z_err != Z_OK || s->z_eof) break; 00919 } 00920 00921 // Update len with the bytes left in the uncompressed stream, should be 0 if everything ok 00922 unsigned len = 1 - s->stream.avail_out; 00923 00924 s->PeekedValue = *buf; // remember the value that was read in 00925 s->PeekStatus += 1; // increment peek count 00926 s->stream.avail_out += 1; // say that we have peeked 1 character 00927 00928 // return the actual amount read in back to the caller 00929 return len; 00930 } 00931 00932 /******************************************************************************************** 00933 00934 > INT32 GZipFile::gzread(GZipStream *s, Byte *buf, unsigned len) 00935 00936 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 00937 Created: 24/05/95 00938 Inputs: s the zip stream that we should be using 00939 buf the buffer that needs the data reading into 00940 Returns: number of uncompressed bytes actually read (0 for end of file, -1 for error) 00941 Purpose: Reads the given number of uncompressed bytes from the compressed file. 00942 If the input file was not in gzip format, gzread copies the given number 00943 of bytes into the buffer. 00944 gzread returns the number of uncompressed bytes actually read (0 for 00945 end of file, -1 for error). 00946 00947 ********************************************************************************************/ 00948 00949 INT32 GZipFile::gzread( GZipStream *s, char *buf, unsigned len ) 00950 { 00951 //TRACEUSER( "Neville", _T("GZipFile::gz_read\n")); 00952 // check that everyhting is valid before preceeding 00953 if (s == NULL || s->mode != 'r' || inflate == NULL || buf == NULL) return Z_STREAM_ERROR; 00954 00955 Byte *b = (Byte*)buf; 00956 00957 // Section added by version 0.99 update 00958 if (s->transparent) 00959 { 00960 TRACEUSER( "Neville", _T("GZipFile::gz_read trying transparent!\n")); 00961 return 0; 00962 } 00963 00964 // First check for problem states from last reading/peeking 00965 if (s->z_err == Z_DATA_ERROR) return -1; /* bad .gz file */ 00966 if (s->z_err == Z_STREAM_END) return 0; /* don't read crc as data */ 00967 00968 // use the supplied buffer to read the characters into 00969 s->stream.next_out = b; 00970 00971 // if we have peeked then avail_out will be equal to the number of peeks made 00972 if (s->stream.avail_out > 0) 00973 { 00974 // add in the values from the peeks 00975 ERROR3IF(s->stream.avail_out > 1,"read with peek > 1"); 00976 buf[0] = s->PeekedValue; // set first byte to be the peeked value 00977 s->PeekStatus -= 1; // decrement peek count 00978 s->stream.avail_out -= 1; // need one less byte for input 00979 00980 if (len == 1) 00981 { 00982 // only 1 byte wanted and we have just supplied this 00983 // checksum the byte that we have just read in 00984 s->crc = crc32(s->crc, b, len); 00985 return len; 00986 } 00987 // otherwise we require some more input 00988 s->stream.avail_out = len - 1; // need one less byte for input 00989 s->stream.next_out = b + 1; // move buffer pointer on by one 00990 } 00991 else 00992 s->stream.avail_out = len; 00993 00994 while (s->stream.avail_out != 0) 00995 { 00996 if (s->stream.avail_in == 0 && !s->z_eof) 00997 { 00998 s->stream.avail_in = Z_BUFSIZE; 00999 // Note the current file position 01000 FilePos Pos = s->file->tellg(); 01001 s->file->read((char *) s->inbuf, s->stream.avail_in ); 01002 FilePos PosAfter = s->file->rdbuf()->pubseekoff( 0, iostream::cur, iostream::in ); 01003 s->stream.avail_in = PosAfter- Pos; 01004 TRACEUSER( "Neville", _T("GZipFile::gz_read filled buffer size %d\n"),s->stream.avail_in); 01005 if (s->stream.avail_in == 0) 01006 { 01007 //s->file->setf(s->file->eofbit); 01008 s->z_eof = 1; 01009 } 01010 /*else if (s->stream.avail_in == (uInt)EOF) 01011 { 01012 // s->stream.avail_in = 0; 01013 s->z_eof = 1; 01014 // s->z_err = Z_ERRNO; 01015 // break; 01016 } */ 01017 else if (s->stream.avail_in < Z_BUFSIZE || s->file->eof()) 01018 { 01019 // We are at the end of the file but have read some data in 01020 // We must set the goodbit to clear the eof and fail bits as otherwise 01021 // all the checks in the diskfile will then fail. 01022 s->z_eof = 1; 01023 s->file->clear(s->file->goodbit); 01024 } 01025 s->stream.next_in = s->inbuf; 01026 } 01027 s->z_err = inflate->inflate(&(s->stream), Z_NO_FLUSH); 01028 01029 if (s->z_err == Z_STREAM_END || 01030 s->z_err != Z_OK || s->z_eof) break; 01031 } 01032 01033 // Update len with the bytes left in the uncompressed stream, should be 0 if everything ok 01034 len -= s->stream.avail_out; 01035 01036 // checksum the data that we have just read in 01037 s->crc = crc32(s->crc, b, len); 01038 01039 // return the actual amount read in back to the caller 01040 return len; 01041 } 01042 01043 /******************************************************************************************** 01044 01045 > FilePos GZipFile::GetCurrentFilePos(GZipStream *s) 01046 01047 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01048 Created: 30/05/95 01049 Inputs: s the zip stream that we should be using 01050 Returns: the current file position 01051 Purpose: Allows the progress bar to be updated with the current position in 01052 the compressed file. 01053 01054 ********************************************************************************************/ 01055 01056 FilePos GZipFile::GetCurrentFilePos(GZipStream *s) 01057 { 01058 if (s == NULL || s->file == NULL) return 0; 01059 01060 // Get the current file position, this will be ready to read in the next chunk of data 01061 // into the input buffer. 01062 // Take off the position that we started at 01063 FilePos Pos = FilePos(s->file->tellg()) - s->InitialPos; 01064 01065 // Take off the current amount left in the input buffer. This is our current position. 01066 Pos -= (FilePos)s->stream.avail_in; 01067 01068 return Pos; 01069 } 01070 01071 01072 01073 /******************************************************************************************** 01074 01075 > INT32 GZipFile::gzwrite(GZipStream *s, const TCHAR *buf, unsigned len) 01076 01077 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01078 Created: 24/05/95 01079 Inputs: s the zip stream that we should be using 01080 buf the buffer that needs exporting 01081 len the length of the buffer 01082 Returns: the number of uncompressed bytes actually written (0 in case of error) 01083 Purpose: Writes the given number of uncompressed bytes into the compressed file. 01084 gzwrite returns the number of bytes actually written (0 in case of error). 01085 01086 ********************************************************************************************/ 01087 01088 INT32 GZipFile::gzwrite(GZipStream *s, const char *buf, unsigned len) 01089 { 01090 #ifdef DO_EXPORT 01091 //TRACEUSER( "Neville", _T("GZipFile::gz_write\n")); 01092 01093 if (s == NULL || s->mode != 'w' || deflate == NULL || buf == NULL) 01094 return Z_STREAM_ERROR; 01095 01096 Byte* b = (Byte*)buf; 01097 01098 s->stream.next_in = b; 01099 s->stream.avail_in = len; 01100 01101 while (s->stream.avail_in != 0) 01102 { 01103 if (s->stream.avail_out == 0) 01104 { 01105 s->stream.next_out = s->outbuf; 01106 INT32 len = Z_BUFSIZE; 01107 s->file->write((const char*)s->outbuf, len); 01108 if (len != Z_BUFSIZE) 01109 { 01110 s->z_err = Z_ERRNO; 01111 break; 01112 } 01113 s->stream.avail_out = Z_BUFSIZE; 01114 } 01115 s->z_err = deflate->deflate(&(s->stream), Z_NO_FLUSH); 01116 01117 // Check if we had a problem or not 01118 if (s->z_err != Z_OK) 01119 break; 01120 } 01121 01122 // Update our checksum of the data 01123 s->crc = crc32(s->crc, b, len); 01124 01125 // Return the number of bytes that we actually wrote 01126 return len - s->stream.avail_in; 01127 #else 01128 return Z_STREAM_ERROR; 01129 #endif 01130 } 01131 01132 /******************************************************************************************** 01133 01134 > INT32 GZipFile::gzflush(GZipStream *s, INT32 flush) 01135 01136 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01137 Created: 24/05/95 01138 Inputs: s the zip stream that is to be used 01139 flush 01140 Purpose: Flushes all pending output into the compressed file. The parameter 01141 flush is as in the deflate() function. The return value is the zlib 01142 error number (see function gzerror below). gzflush returns Z_OK if the 01143 flush parameter is Z_FINISH and all output could be flushed. 01144 gzflush should be called only when strictly necessary because it can 01145 degrade compression. 01146 01147 ********************************************************************************************/ 01148 01149 INT32 GZipFile::gzflush(GZipStream *s, INT32 flush) 01150 { 01151 #ifdef DO_EXPORT 01152 TRACEUSER( "Neville", _T("GZipFile::gzflush\n")); 01153 01154 uInt len; 01155 INT32 done = 0; 01156 01157 if (s == NULL || s->mode != 'w' || deflate == NULL) 01158 return Z_STREAM_ERROR; 01159 01160 s->stream.avail_in = 0; /* should be zero already anyway */ 01161 01162 for (;;) 01163 { 01164 len = Z_BUFSIZE - s->stream.avail_out; 01165 01166 if (len != 0) 01167 { 01168 // if (fwrite(s->outbuf, 1, len, s->file) != len) 01169 uInt len2 = len; 01170 s->file->write((const char*)s->outbuf, len2); 01171 if ( len2 != len) 01172 { 01173 s->z_err = Z_ERRNO; 01174 return Z_ERRNO; 01175 } 01176 s->stream.next_out = s->outbuf; 01177 s->stream.avail_out = Z_BUFSIZE; 01178 } 01179 if (done) break; 01180 s->z_err = deflate->deflate(&(s->stream), flush); 01181 01182 /* deflate has finished flushing only when it hasn't used up 01183 * all the available space in the output buffer: 01184 */ 01185 done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); 01186 01187 if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; 01188 } 01189 return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; 01190 #else 01191 return Z_STREAM_ERROR; 01192 #endif 01193 } 01194 01195 /******************************************************************************************** 01196 01197 > void GZipFile::putLong(iostream *file, uLong x) 01198 01199 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01200 Created: 24/05/95 01201 Purpose: Outputs an INT32 in LSB order to the given file 01202 01203 ********************************************************************************************/ 01204 01205 void GZipFile::putLong(iostream *file, uLong x) 01206 { 01207 #ifdef DO_EXPORT 01208 INT32 n; 01209 for (n = 0; n < 4; n++) 01210 { 01211 // _fputtc((INT32)(x & 0xff), file); 01212 file->put((TCHAR)(x & 0xff)); 01213 x >>= 8; 01214 } 01215 #endif 01216 } 01217 01218 /******************************************************************************************** 01219 01220 > uLong GZipFile::getLong (Byte *buf) 01221 01222 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01223 Created: 24/05/95 01224 Purpose: Reads an INT32 in LSB order from the given buffer 01225 01226 ********************************************************************************************/ 01227 01228 uLong GZipFile::getLong (Byte *buf) 01229 { 01230 uLong x = 0; 01231 Byte *p = buf+4; 01232 01233 do 01234 { 01235 x <<= 8; 01236 x |= *--p; 01237 } while (p != buf); 01238 01239 return x; 01240 } 01241 01242 /******************************************************************************************** 01243 01244 > INT32 GZipFile::gzclose(GZipStream *s) 01245 01246 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01247 Created: 24/05/95 01248 Inputs: s the z stream to be used 01249 Returns: Z_OK or an error number if there has been a problem 01250 Purpose: Flushes all pending output if necessary, closes the compressed file 01251 and deallocates all the (de)compression state. 01252 The return value is the zlib error number (see function gzerror below). 01253 01254 ********************************************************************************************/ 01255 01256 INT32 GZipFile::gzclose(GZipStream *s) 01257 { 01258 TRACEUSER( "Neville", _T("GZipFile::gzclose\n")); 01259 01260 uInt n; 01261 01262 if (s == NULL) return Z_STREAM_ERROR; 01263 01264 if (s->mode == 'w') 01265 { 01266 #ifdef DO_EXPORT 01267 INT32 err; 01268 err = gzflush(s, Z_FINISH); 01269 if (err != Z_OK) return destroy(s); 01270 01271 putLong (s->file, s->crc); 01272 putLong (s->file, s->stream.total_in); 01273 01274 TRACEUSER( "Neville", _T("gzclose calc'd crc = %d\n"),s->crc); 01275 TRACEUSER( "Neville", _T("gzclose bytes written = %d\n"),s->stream.total_out); 01276 #endif 01277 } 01278 else if (s->mode == 'r' && s->z_err == Z_STREAM_END) 01279 { 01280 01281 /* slide CRC and original size if they are at the end of inbuf */ 01282 if ((n = s->stream.avail_in) < 8 && !s->z_eof) 01283 { 01284 Byte *p = s->inbuf; 01285 Byte *q = s->stream.next_in; 01286 while (n--) 01287 { 01288 *p++ = *q++; 01289 }; 01290 01291 n = s->stream.avail_in; 01292 // n += fread(p, 1, 8, s->file); 01293 INT32 len = 8; 01294 s->file->read( (char *)p, len ); 01295 n += len; 01296 s->stream.next_in = s->inbuf; 01297 } 01298 01299 // check CRC and original size 01300 uLong FileCrc = getLong(s->stream.next_in); 01301 uLong FileSize = getLong(s->stream.next_in + 4); 01302 TRACEUSER( "Neville", _T("check stored crc %d, against calc'd crc = %d\n"), FileCrc, s->crc); 01303 TRACEUSER( "Neville", _T("check stored bytes written %d, against count = %d\n"), FileSize, s->stream.total_out); 01304 TRACEUSER( "Neville", _T("bytes left in buffer %d\n"), n); 01305 if (n < 8 || FileCrc != s->crc || FileSize != s->stream.total_out) 01306 { 01307 01308 s->z_err = Z_DATA_ERROR; 01309 } 01310 01311 // Quick bodge here. We now have n bytes left in the buffer, this will include 8 for the CRC etc. 01312 // If we close down compression then the file pointer will be sitting n - 8 bytes on from the 01313 // position where we actually want it. Therefore, we must skip back to the correct position. 01314 FilePos Pos = s->file->tellg(); 01315 Pos = Pos - (n - 8); 01316 s->file->seekg(Pos); 01317 } 01318 01319 return destroy(s); 01320 } 01321 01322 /******************************************************************************************** 01323 ********************************************************************************************/ 01324 //static char *z_errmsg[] = 01325 // { 01326 // "stream end", /* Z_STREAM_END 1 */ 01327 // "", /* Z_OK 0 */ 01328 // "file error", /* Z_ERRNO (-1) */ 01329 // "stream error", /* Z_STREAM_ERROR (-2) */ 01330 // "data error", /* Z_DATA_ERROR (-3) */ 01331 // "insufficient memory", /* Z_MEM_ERROR (-4) */ 01332 // "buffer error", /* Z_BUF_ERROR (-5) */ 01333 // "" 01334 // }; 01335 01336 /******************************************************************************************** 01337 01338 > char* GZipFile::gzerror(GZipStream *s, INT32 *errnum) 01339 01340 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01341 Created: 24/05/95 01342 Purpose: Returns the error message for the last error which occured on the 01343 given compressed file. errnum is set to zlib error number. If an 01344 error occured in the file system and not in the compression library, 01345 errnum is set to Z_ERRNO and the application may consult errno 01346 to get the exact error code. 01347 01348 ********************************************************************************************/ 01349 01350 //char* GZipFile::gzerror(GZipStream *s, INT32 *errnum) 01351 //{ 01352 // TRACEUSER( "Neville", _T("GZipFile::gzerror\n")); 01353 // 01354 // char *m; 01355 // 01356 // if (s == NULL) 01357 // { 01358 // *errnum = Z_STREAM_ERROR; 01359 // return z_errmsg[1-Z_STREAM_ERROR]; 01360 // } 01361 // 01362 // *errnum = s->z_err; 01363 // if (*errnum == Z_OK) return ""; 01364 // 01365 // if (*errnum == Z_ERRNO) 01366 // { 01367 // _stprintf(m, "Disc error number %d", errno); //zstrerror(errno); 01368 // } 01369 // else 01370 // { 01371 // m = s->stream.msg; 01372 // } 01373 // 01374 // if (m == NULL || *m == '\0') m = z_errmsg[1-s->z_err]; 01375 // 01376 // TRYFREE(s->msg); 01377 // s->msg = (char*)ALLOC(_tcsclen(s->path) + strlen(m) + 3); 01378 // if (s->msg) 01379 // { 01380 // camStrcpy(s->msg, s->path); 01381 // strcat(s->msg, ": "); 01382 // strcat(s->msg, m); 01383 // } 01384 // 01385 // return s->msg; 01386 //} 01387 01388 //------------------------------------------------------------------------------------------- 01389 // Contents of file CRC32.c 01390 //------------------------------------------------------------------------------------------- 01391 01392 /******************************************************************************************** 01393 01394 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01395 Created: 24/05/95 01396 Purpose: Table of CRC-32's of all single-byte values (made by make_crc_table) 01397 01398 ********************************************************************************************/ 01399 #if 0 //def DYNAMIC_CRC_TABLE 01400 01401 static INT32 crc_table_empty = 1; 01402 static uLongf crc_table[256]; 01403 static void make_crc_table OF((void)); 01404 01405 /* 01406 Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: 01407 x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. 01408 01409 Polynomials over GF(2) are represented in binary, one bit per coefficient, 01410 with the lowest powers in the most significant bit. Then adding polynomials 01411 is just exclusive-or, and multiplying a polynomial by x is a right shift by 01412 one. If we call the above polynomial p, and represent a byte as the 01413 polynomial q, also with the lowest power in the most significant bit (so the 01414 byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, 01415 where a mod b means the remainder after dividing a by b. 01416 01417 This calculation is done using the shift-register method of multiplying and 01418 taking the remainder. The register is initialized to zero, and for each 01419 incoming bit, x^32 is added mod p to the register if the bit is a one (where 01420 x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by 01421 x (which is shifting right by one and adding x^32 mod p if the bit shifted 01422 out is a one). We start with the highest power (least significant bit) of 01423 q and repeat for all eight bits of q. 01424 01425 The table is simply the CRC of all possible eight bit values. This is all 01426 the information needed to generate CRC's on data a byte at a time for all 01427 combinations of CRC register values and incoming bytes. 01428 */ 01429 01430 /* ========================================================================= 01431 * Make the crc table. This function is needed only if you want to compute 01432 * the table dynamically. 01433 */ 01434 01435 void make_crc_table() 01436 { 01437 uLong c; 01438 INT32 n, k; 01439 uLong poly; /* polynomial exclusive-or pattern */ 01440 /* terms of polynomial defining this crc (except x^32): */ 01441 static Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; 01442 01443 /* make exclusive-or pattern from polynomial (0xedb88320L) */ 01444 poly = 0L; 01445 for (n = 0; n < sizeof(p)/sizeof(Byte); n++) 01446 poly |= 1L << (31 - p[n]); 01447 01448 for (n = 0; n < 256; n++) 01449 { 01450 c = (uLong)n; 01451 for (k = 0; k < 8; k++) 01452 c = c & 1 ? poly ^ (c >> 1) : c >> 1; 01453 crc_table[n] = c; 01454 } 01455 crc_table_empty = 0; 01456 } 01457 #else 01458 /* ======================================================================== 01459 * Table of CRC-32's of all single-byte values (made by make_crc_table) 01460 */ 01461 static uLongf crc_table[256] = { 01462 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 01463 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 01464 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 01465 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 01466 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 01467 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 01468 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 01469 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 01470 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 01471 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 01472 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 01473 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 01474 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 01475 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 01476 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 01477 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 01478 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 01479 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 01480 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 01481 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 01482 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 01483 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 01484 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 01485 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 01486 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 01487 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 01488 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 01489 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 01490 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 01491 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 01492 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 01493 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 01494 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 01495 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 01496 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 01497 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 01498 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 01499 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 01500 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 01501 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 01502 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 01503 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 01504 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 01505 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 01506 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 01507 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 01508 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 01509 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 01510 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 01511 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 01512 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 01513 0x2d02ef8dL 01514 }; 01515 #endif 01516 01517 /* ========================================================================= */ 01518 #define DO1(buf) crc = crc_table[((INT32)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); 01519 #define DO2(buf) DO1(buf); DO1(buf); 01520 #define DO4(buf) DO2(buf); DO2(buf); 01521 #define DO8(buf) DO4(buf); DO4(buf); 01522 01523 /* ========================================================================= */ 01524 01525 /******************************************************************************************** 01526 01527 > uLong GZipFile::crc32(uLong crc, Bytef *buf, uInt len) 01528 01529 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01530 Created: 24/05/95 01531 Inputs: crc previous checksum value??? 01532 buf pointer to the buffer to check 01533 len length of the buffer 01534 Returns: the checksum value 01535 Purpose: Update a running crc with the bytes buf[0..len-1] and return the updated 01536 crc. If buf is NULL, this function returns the required initial value 01537 for the crc. Pre- and post-conditioning (one's complement) is performed 01538 within this function so it shouldn't be done by the application. 01539 Usage example: 01540 01541 uLong crc = crc32(0L, Z_NULL, 0); 01542 01543 while (read_buffer(buffer, length) != EOF) 01544 { 01545 crc = crc32(crc, buffer, length); 01546 } 01547 if (crc != original_crc) error(); 01548 01549 ********************************************************************************************/ 01550 uLong GZipFile::crc32(uLong crc, Bytef *buf, uInt len) 01551 { 01552 if (buf == Z_NULL) return 0L; 01553 #ifdef DYNAMIC_CRC_TABLE 01554 if (crc_table_empty) 01555 make_crc_table(); 01556 #endif 01557 crc = crc ^ 0xffffffffL; 01558 while (len >= 8) 01559 { 01560 DO8(buf); 01561 len -= 8; 01562 } 01563 if (len) do { 01564 DO1(buf); 01565 } while (--len); 01566 return crc ^ 0xffffffffL; 01567 } 01568 01569 /* ========================================================================= 01570 * This function can be used by asm versions of crc32() 01571 */ 01572 uLongf *GZipFile::get_crc_table() 01573 { 01574 #ifdef DYNAMIC_CRC_TABLE 01575 if (crc_table_empty) make_crc_table(); 01576 #endif 01577 return (uLongf *)crc_table; 01578 } 01579 01580 /******************************************************************************************** 01581 ********************************************************************************************/ 01582 01583 //------------------------------------------------------------------------------------------- 01584 // Contents of file CRC32.c 01585 //------------------------------------------------------------------------------------------- 01586 01587 #define BASE 65521L /* largest prime smaller than 65536 */ 01588 #define NMAX 5552 01589 /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ 01590 01591 #define A_DO1(buf,i) {s1 += buf[i]; s2 += s1;} 01592 #define A_DO2(buf,i) A_DO1(buf,i); A_DO1(buf,i+1); 01593 #define A_DO4(buf,i) A_DO2(buf,i); A_DO2(buf,i+2); 01594 #define A_DO8(buf,i) A_DO4(buf,i); A_DO4(buf,i+4); 01595 #define A_DO16(buf) A_DO8(buf,0); A_DO8(buf,8); 01596 01597 /******************************************************************************************** 01598 01599 > uLong GZipFile::adler32(uLong adler, const Bytef *buf, uInt len) 01600 01601 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01602 Created: 24/05/95 01603 Inputs: crc previous checksum value??? 01604 buf pointer to the buffer to check 01605 len length of the buffer 01606 Returns: the checksum value 01607 Purpose: Update a running Adler-32 checksum with the bytes buf[0..len-1] and 01608 return the updated checksum. If buf is NULL, this function returns 01609 the required initial value for the checksum. 01610 An Adler-32 checksum is almost as reliable as a CRC32 but can be computed 01611 much faster. Usage example: 01612 01613 uLong adler = adler32(0L, Z_NULL, 0); 01614 01615 while (read_buffer(buffer, length) != EOF) 01616 { 01617 adler = adler32(adler, buffer, length); 01618 } 01619 if (adler != original_adler) error(); 01620 01621 ********************************************************************************************/ 01622 01623 /* ========================================================================= */ 01624 uLong GZipFile::adler32(uLong adler, const Bytef *buf, uInt len) 01625 { 01626 UINT32 s1 = adler & 0xffff; 01627 UINT32 s2 = (adler >> 16) & 0xffff; 01628 INT32 k; 01629 01630 if (buf == Z_NULL) return 1L; 01631 01632 while (len > 0) { 01633 k = len < NMAX ? len : NMAX; 01634 len -= k; 01635 while (k >= 16) { 01636 A_DO16(buf); 01637 buf += 16; 01638 k -= 16; 01639 } 01640 if (k != 0) do { 01641 s1 += *buf++; 01642 s2 += s1; 01643 } while (--k); 01644 s1 %= BASE; 01645 s2 %= BASE; 01646 } 01647 return (s2 << 16) | s1;} 01648 01649 01650 /******************************************************************************************** 01651 01652 > void *GZipFile::zcalloc (opaque, items, size) 01653 01654 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01655 Created: 24/05/95 01656 Inputs: opaque random memory handle/checksum value, never used 01657 items number of items required 01658 size size of each buffer item 01659 Returns: the checksum value 01660 Purpose: Allocate memory of size items and with size bytes per item 01661 01662 ********************************************************************************************/ 01663 01664 void *GZipFile::zcalloc(void *opaque, unsigned items, unsigned size) 01665 { 01666 // allocate memory of size items and with size bytes per item 01667 //return calloc(items, size); 01668 return CCMalloc(items * size); 01669 } 01670 01671 /******************************************************************************************** 01672 01673 > void GZipFile::zcfree(opaque, ptr) 01674 01675 Author: Neville_Humphrys (Xara Group Ltd) <camelotdev@xara.com> 01676 Created: 24/05/95 01677 Inputs: opaque random memory handle/checksum value, never used 01678 ptr memory pointer to free, must have been allocated by zcalloc 01679 Purpose: A wrapper round the free function 01680 01681 ********************************************************************************************/ 01682 01683 void GZipFile::zcfree(void *opaque, void *ptr) 01684 { 01685 //free(ptr); 01686 if (ptr) 01687 CCFree(ptr); 01688 }