Zip.cpp 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. /*
  23. ================================================================================================
  24. Contains external code for building ZipFiles.
  25. ================================================================================================
  26. */
  27. #include "Zip.h"
  28. #include "Unzip.h"
  29. #undef STDC
  30. #include "zlib/zutil.h"
  31. /* zip.c -- IO on .zip files using zlib
  32. Version 1.01e, February 12th, 2005
  33. 27 Dec 2004 Rolf Kalbermatter
  34. Modification to zipOpen2 to support globalComment retrieval.
  35. Copyright (C) 1998-2005 Gilles Vollant
  36. This unzip package allow creates .ZIP file, compatible with PKZip 2.04g
  37. WinZip, InfoZip tools and compatible.
  38. Multi volume ZipFile (span) are not supported.
  39. Encryption compatible with pkzip 2.04g only supported
  40. Old compressions used by old PKZip 1.x are not supported
  41. For uncompress .zip file, look at unzip.h
  42. I WAIT FEEDBACK at mail info@winimage.com
  43. Visit also http://www.winimage.com/zLibDll/unzip.html for evolution
  44. Condition of use and distribution are the same than zlib :
  45. This software is provided 'as-is', without any express or implied
  46. warranty. In no event will the authors be held liable for any damages
  47. arising from the use of this software.
  48. Permission is granted to anyone to use this software for any purpose,
  49. including commercial applications, and to alter it and redistribute it
  50. freely, subject to the following restrictions:
  51. 1. The origin of this software must not be misrepresented; you must not
  52. claim that you wrote the original software. If you use this software
  53. in a product, an acknowledgment in the product documentation would be
  54. appreciated but is not required.
  55. 2. Altered source versions must be plainly marked as such, and must not be
  56. misrepresented as being the original software.
  57. 3. This notice may not be removed or altered from any source distribution.
  58. For more info about .ZIP format, see
  59. http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
  60. http://www.info-zip.org/pub/infozip/doc/
  61. PkWare has also a specification at :
  62. ftp://ftp.pkware.com/probdesc.zip
  63. */
  64. #ifndef Z_MAXFILENAMEINZIP
  65. #define Z_MAXFILENAMEINZIP (256)
  66. #endif
  67. #ifndef ALLOC
  68. #define ALLOC( size ) ( Mem_Alloc( size, TAG_ZIP ) )
  69. #endif
  70. #ifndef TRYFREE
  71. #define TRYFREE( p ) { if (p) { Mem_Free(p); } }
  72. #endif
  73. /*
  74. #define SIZECENTRALDIRITEM (0x2e)
  75. #define SIZEZIPLOCALHEADER (0x1e)
  76. */
  77. const char zip_copyright[] =
  78. " zip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
  79. #define LOCALHEADERMAGIC (0x04034b50)
  80. #define CENTRALHEADERMAGIC (0x02014b50)
  81. #define ENDHEADERMAGIC (0x06054b50)
  82. #define FLAG_LOCALHEADER_OFFSET (0x06)
  83. #define CRC_LOCALHEADER_OFFSET (0x0e)
  84. #define SIZECENTRALHEADER (0x2e) /* 46 */
  85. #define DEFAULT_COMPRESSION_LEVEL (5) /* 1 == Compress faster, 9 == Compress better */
  86. #define DEFAULT_WRITEBUFFERSIZE (16384)
  87. #ifndef NOCRYPT
  88. #define INCLUDECRYPTINGCODE_IFCRYPTALLOWED
  89. #include "crypt.h"
  90. #endif
  91. idCVar zip_verbosity( "zip_verbosity", "0", CVAR_BOOL, "1 = verbose logging when building zip files" );
  92. /*
  93. ========================
  94. allocate_new_datablock
  95. ========================
  96. */
  97. linkedlist_datablock_internal* allocate_new_datablock() {
  98. linkedlist_datablock_internal* ldi = NULL;
  99. ldi = (linkedlist_datablock_internal*) ALLOC( sizeof( linkedlist_datablock_internal ) );
  100. if ( ldi != NULL ) {
  101. ldi->next_datablock = NULL;
  102. ldi->filled_in_this_block = 0;
  103. ldi->avail_in_this_block = SIZEDATA_INDATABLOCK;
  104. }
  105. return ldi;
  106. }
  107. /*
  108. ========================
  109. free_datablock
  110. ========================
  111. */
  112. void free_datablock( linkedlist_datablock_internal* ldi ) {
  113. while ( ldi != NULL ) {
  114. linkedlist_datablock_internal* ldinext = ldi->next_datablock;
  115. TRYFREE( ldi );
  116. ldi = ldinext;
  117. }
  118. }
  119. /*
  120. ========================
  121. init_linkedlist
  122. ========================
  123. */
  124. void init_linkedlist( linkedlist_data* ll ) {
  125. ll->first_block = ll->last_block = NULL;
  126. }
  127. /*
  128. ========================
  129. free_linkedlist
  130. ========================
  131. */
  132. void free_linkedlist( linkedlist_data* ll ) {
  133. free_datablock( ll->first_block );
  134. ll->first_block = ll->last_block = NULL;
  135. }
  136. /*
  137. ========================
  138. add_data_in_datablock
  139. ========================
  140. */
  141. int add_data_in_datablock( linkedlist_data* ll, const void* buf, unsigned long len ) {
  142. linkedlist_datablock_internal* ldi;
  143. const unsigned char* from_copy;
  144. if ( ll == NULL ) {
  145. return ZIP_INTERNALERROR;
  146. }
  147. if ( ll->last_block == NULL ) {
  148. ll->first_block = ll->last_block = allocate_new_datablock();
  149. if ( ll->first_block == NULL ) {
  150. return ZIP_INTERNALERROR;
  151. }
  152. }
  153. ldi = ll->last_block;
  154. from_copy = (unsigned char*)buf;
  155. while ( len > 0 ) {
  156. unsigned int copy_this;
  157. unsigned char* to_copy;
  158. if ( ldi->avail_in_this_block == 0 ) {
  159. ldi->next_datablock = allocate_new_datablock();
  160. if ( ldi->next_datablock == NULL ) {
  161. return ZIP_INTERNALERROR;
  162. }
  163. ldi = ldi->next_datablock;
  164. ll->last_block = ldi;
  165. }
  166. if ( ldi->avail_in_this_block < len ) {
  167. copy_this = (unsigned int)ldi->avail_in_this_block;
  168. } else {
  169. copy_this = (unsigned int)len;
  170. }
  171. to_copy = &( ldi->data[ ldi->filled_in_this_block ] );
  172. for ( unsigned int i = 0; i < copy_this; i++ ) {
  173. *( to_copy + i ) =* ( from_copy + i );
  174. }
  175. ldi->filled_in_this_block += copy_this;
  176. ldi->avail_in_this_block -= copy_this;
  177. from_copy += copy_this;
  178. len -= copy_this;
  179. }
  180. return ZIP_OK;
  181. }
  182. #ifndef NO_ADDFILEINEXISTINGZIP
  183. /*
  184. ========================
  185. ziplocal_putValue
  186. Inputs a long in LSB order to the given file
  187. nbByte == 1, 2 or 4 (byte, short or long)
  188. ========================
  189. */
  190. int ziplocal_putValue( idFile* filestream, unsigned long x, int nbByte ) {
  191. unsigned char buf[4];
  192. for ( int n = 0; n < nbByte; n++ ) {
  193. buf[n] = (unsigned char)( x & 0xff );
  194. x >>= 8;
  195. }
  196. if ( x != 0 ) {
  197. /* data overflow - hack for ZIP64 (X Roche) */
  198. for ( int n = 0; n < nbByte; n++ ) {
  199. buf[n] = 0xff;
  200. }
  201. }
  202. if ( filestream->Write( buf, nbByte ) != nbByte ) {
  203. return ZIP_ERRNO;
  204. } else {
  205. return ZIP_OK;
  206. }
  207. }
  208. /*
  209. ========================
  210. ziplocal_putValue_inmemory
  211. ========================
  212. */
  213. void ziplocal_putValue_inmemory( void* dest, unsigned long x, int nbByte ){
  214. unsigned char* buf = (unsigned char*)dest;
  215. for ( int n = 0; n < nbByte; n++ ) {
  216. buf[n] = (unsigned char)( x & 0xff );
  217. x >>= 8;
  218. }
  219. if ( x != 0 ) {
  220. /* data overflow - hack for ZIP64 */
  221. for ( int n = 0; n < nbByte; n++ ) {
  222. buf[n] = 0xff;
  223. }
  224. }
  225. }
  226. /*
  227. ========================
  228. ziplocal_TmzDateToDosDate
  229. ========================
  230. */
  231. unsigned long ziplocal_TmzDateToDosDate( const tm_zip* ptm, unsigned long dosDate ) {
  232. unsigned long year = (unsigned long)ptm->tm_year;
  233. if ( year > 1980 ) {
  234. year-=1980;
  235. } else if ( year > 80 ) {
  236. year -= 80;
  237. }
  238. return (unsigned long)( ( ( ptm->tm_mday ) + ( 32 * ( ptm->tm_mon + 1 ) ) + ( 512 * year ) ) << 16 ) |
  239. ( ( ptm->tm_sec / 2 ) + ( 32 * ptm->tm_min ) + ( 2048 * (unsigned long)ptm->tm_hour ) );
  240. }
  241. /*
  242. ========================
  243. ziplocal_getByte
  244. ========================
  245. */
  246. int ziplocal_getByte( idFile* filestream, int *pi ) {
  247. unsigned char c;
  248. int err = (int)filestream->Read( &c, 1 );
  249. if ( err == 1 ) {
  250. *pi = (int)c;
  251. return ZIP_OK;
  252. } else {
  253. return ZIP_ERRNO;
  254. }
  255. /*
  256. unsigned char c;
  257. int err = (int)ZREAD( filestream, &c, 1 );
  258. if ( err == 1 ) {
  259. *pi = (int)c;
  260. return ZIP_OK;
  261. } else {
  262. if ( ZERROR( filestream ) ) {
  263. return ZIP_ERRNO;
  264. } else {
  265. return ZIP_EOF;
  266. }
  267. }
  268. */
  269. }
  270. /*
  271. ========================
  272. ziplocal_getShort
  273. Reads a long in LSB order from the given gz_stream. Sets
  274. ========================
  275. */
  276. int ziplocal_getShort( idFile* filestream, unsigned long *pX ) {
  277. short v;
  278. if ( filestream->Read( &v, sizeof( v ) ) == sizeof( v ) ) {
  279. idSwap::Little( v );
  280. *pX = v;
  281. return ZIP_OK;
  282. } else {
  283. return ZIP_ERRNO;
  284. }
  285. /*
  286. unsigned long x ;
  287. int i;
  288. int err;
  289. err = ziplocal_getByte( filestream, &i );
  290. x = (unsigned long)i;
  291. if ( err == ZIP_OK ) {
  292. err = ziplocal_getByte( filestream, &i );
  293. }
  294. x += ( (unsigned long)i ) << 8;
  295. if ( err == ZIP_OK ) {
  296. *pX = x;
  297. } else {
  298. *pX = 0;
  299. }
  300. return err;
  301. */
  302. }
  303. /*
  304. ========================
  305. ziplocal_getLong
  306. ========================
  307. */
  308. int ziplocal_getLong( idFile* filestream, unsigned long *pX ) {
  309. int v;
  310. if ( filestream->Read( &v, sizeof( v ) ) == sizeof( v ) ) {
  311. idSwap::Little( v );
  312. *pX = v;
  313. return ZIP_OK;
  314. } else {
  315. return ZIP_ERRNO;
  316. }
  317. /*
  318. unsigned long x ;
  319. int i;
  320. int err;
  321. err = ziplocal_getByte( filestream, &i );
  322. x = (unsigned long)i;
  323. if ( err == ZIP_OK ) {
  324. err = ziplocal_getByte( filestream, &i );
  325. }
  326. x += ( (unsigned long)i ) << 8;
  327. if ( err == ZIP_OK ) {
  328. err = ziplocal_getByte( filestream, &i );
  329. }
  330. x += ( (unsigned long)i) << 16;
  331. if ( err == ZIP_OK ) {
  332. err = ziplocal_getByte( filestream, &i );
  333. }
  334. x += ( (unsigned long)i ) << 24;
  335. if ( err == ZIP_OK ) {
  336. *pX = x;
  337. } else {
  338. *pX = 0;
  339. }
  340. return err;
  341. */
  342. }
  343. #ifndef BUFREADCOMMENT
  344. #define BUFREADCOMMENT (0x400)
  345. #endif
  346. /*
  347. ========================
  348. ziplocal_SearchCentralDir
  349. Locate the Central directory of a zipfile (at the end, just before
  350. the global comment)
  351. ========================
  352. */
  353. unsigned long ziplocal_SearchCentralDir( idFile* filestream ) {
  354. unsigned char* buf;
  355. unsigned long uSizeFile;
  356. unsigned long uBackRead;
  357. unsigned long uMaxBack = 0xffff; /* maximum size of global comment */
  358. unsigned long uPosFound = 0;
  359. if ( filestream->Seek( 0, FS_SEEK_END ) != 0 ) {
  360. return 0;
  361. }
  362. uSizeFile = (unsigned long)filestream->Tell();
  363. if ( uMaxBack > uSizeFile ) {
  364. uMaxBack = uSizeFile;
  365. }
  366. buf = (unsigned char*)ALLOC( BUFREADCOMMENT + 4 );
  367. if ( buf == NULL ) {
  368. return 0;
  369. }
  370. uBackRead = 4;
  371. while ( uBackRead < uMaxBack ) {
  372. unsigned long uReadSize,uReadPos;
  373. if ( uBackRead + BUFREADCOMMENT > uMaxBack ) {
  374. uBackRead = uMaxBack;
  375. } else {
  376. uBackRead += BUFREADCOMMENT;
  377. }
  378. uReadPos = uSizeFile - uBackRead ;
  379. uReadSize = ( ( BUFREADCOMMENT + 4 ) < ( uSizeFile - uReadPos ) ) ? ( BUFREADCOMMENT + 4 ) : ( uSizeFile - uReadPos );
  380. if ( filestream->Seek( uReadPos, FS_SEEK_SET ) != 0 ) {
  381. break;
  382. }
  383. if ( filestream->Read( buf, uReadSize ) != ( int )uReadSize ) {
  384. break;
  385. }
  386. for ( int i = (int)uReadSize - 3; ( i -- ) > 0; ) {
  387. if ( ( ( *( buf + i ) ) == 0x50 ) && ( ( *( buf + i + 1 ) ) == 0x4b ) && ( ( *( buf + i + 2 ) ) == 0x05 ) && ( ( *( buf + i + 3 ) ) == 0x06 ) ) {
  388. uPosFound = uReadPos + i;
  389. break;
  390. }
  391. }
  392. if ( uPosFound != 0 ) {
  393. break;
  394. }
  395. }
  396. TRYFREE( buf );
  397. return uPosFound;
  398. }
  399. #endif /* !NO_ADDFILEINEXISTINGZIP*/
  400. /*
  401. ========================
  402. zipOpen2
  403. ========================
  404. */
  405. zipFile zipOpen2( const char *pathname, int append, char* globalcomment ) {
  406. zip_internal ziinit;
  407. zip_internal* zi;
  408. int err = ZIP_OK;
  409. ziinit.filestream = fileSystem->OpenExplicitFileWrite( pathname );
  410. /*
  411. ziinit.filestream = ZOPEN( pathname, ( append == APPEND_STATUS_CREATE ) ?
  412. ( ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE ) :
  413. ( ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING ) );
  414. */
  415. if ( ziinit.filestream == NULL ) {
  416. return NULL;
  417. }
  418. ziinit.begin_pos = (unsigned long)ziinit.filestream->Tell();
  419. ziinit.in_opened_file_inzip = 0;
  420. ziinit.ci.stream_initialised = 0;
  421. ziinit.number_entry = 0;
  422. ziinit.add_position_when_writting_offset = 0;
  423. init_linkedlist( &(ziinit.central_dir) );
  424. zi = (zip_internal*)ALLOC( sizeof( zip_internal ) );
  425. if ( zi == NULL ) {
  426. delete ziinit.filestream;
  427. ziinit.filestream = NULL;
  428. return NULL;
  429. }
  430. /* now we add file in a zipfile */
  431. #ifndef NO_ADDFILEINEXISTINGZIP
  432. ziinit.globalcomment = NULL;
  433. if ( append == APPEND_STATUS_ADDINZIP ) {
  434. unsigned long byte_before_the_zipfile; // byte before the zipfile, ( > 0 for sfx )
  435. unsigned long size_central_dir; // size of the central directory
  436. unsigned long offset_central_dir; // offset of start of central directory
  437. unsigned long central_pos,uL;
  438. unsigned long number_disk; // number of the current dist, used for spaning ZIP, unsupported, always 0
  439. unsigned long number_disk_with_CD; // number the the disk with central dir, used for spaning ZIP, unsupported, always 0
  440. unsigned long number_entry;
  441. unsigned long number_entry_CD; // total number of entries in the central dir ( same than number_entry on nospan )
  442. unsigned long size_comment;
  443. central_pos = ziplocal_SearchCentralDir( ziinit.filestream );
  444. if ( central_pos == 0 ) {
  445. err = ZIP_ERRNO;
  446. }
  447. if ( ziinit.filestream->Seek( central_pos, FS_SEEK_SET ) != 0 ) {
  448. err = ZIP_ERRNO;
  449. }
  450. /* the signature, already checked */
  451. if ( ziplocal_getLong( ziinit.filestream, &uL ) != ZIP_OK ) {
  452. err = ZIP_ERRNO;
  453. }
  454. /* number of this disk */
  455. if ( ziplocal_getShort( ziinit.filestream, &number_disk ) != ZIP_OK ) {
  456. err = ZIP_ERRNO;
  457. }
  458. /* number of the disk with the start of the central directory */
  459. if ( ziplocal_getShort( ziinit.filestream, &number_disk_with_CD ) != ZIP_OK ) {
  460. err = ZIP_ERRNO;
  461. }
  462. /* total number of entries in the central dir on this disk */
  463. if ( ziplocal_getShort( ziinit.filestream, &number_entry ) != ZIP_OK ) {
  464. err = ZIP_ERRNO;
  465. }
  466. /* total number of entries in the central dir */
  467. if ( ziplocal_getShort( ziinit.filestream, &number_entry_CD ) != ZIP_OK ) {
  468. err = ZIP_ERRNO;
  469. }
  470. if ( ( number_entry_CD != number_entry ) || ( number_disk_with_CD != 0 ) || ( number_disk != 0 ) ) {
  471. err = ZIP_BADZIPFILE;
  472. }
  473. /* size of the central directory */
  474. if ( ziplocal_getLong( ziinit.filestream, &size_central_dir ) != ZIP_OK ) {
  475. err = ZIP_ERRNO;
  476. }
  477. /* offset of start of central directory with respect to the starting disk number */
  478. if ( ziplocal_getLong( ziinit.filestream, &offset_central_dir ) != ZIP_OK ) {
  479. err = ZIP_ERRNO;
  480. }
  481. /* zipfile global comment length */
  482. if ( ziplocal_getShort( ziinit.filestream, &size_comment ) != ZIP_OK ) {
  483. err = ZIP_ERRNO;
  484. }
  485. if ( ( central_pos < ( offset_central_dir + size_central_dir ) ) && ( err == ZIP_OK ) ) {
  486. err = ZIP_BADZIPFILE;
  487. }
  488. if ( err != ZIP_OK ) {
  489. delete ziinit.filestream;
  490. ziinit.filestream = NULL;
  491. return NULL;
  492. }
  493. if ( size_comment > 0 ) {
  494. ziinit.globalcomment = (char*)ALLOC( size_comment + 1 );
  495. if ( ziinit.globalcomment ) {
  496. size_comment = (unsigned long)ziinit.filestream->Read( ziinit.globalcomment, size_comment );
  497. ziinit.globalcomment[size_comment] = 0;
  498. }
  499. }
  500. byte_before_the_zipfile = central_pos - ( offset_central_dir + size_central_dir );
  501. ziinit.add_position_when_writting_offset = byte_before_the_zipfile;
  502. {
  503. unsigned long size_central_dir_to_read = size_central_dir;
  504. size_t buf_size = SIZEDATA_INDATABLOCK;
  505. void* buf_read = (void*)ALLOC( buf_size );
  506. if ( ziinit.filestream->Seek( offset_central_dir + byte_before_the_zipfile, FS_SEEK_SET ) != 0 ) {
  507. err = ZIP_ERRNO;
  508. }
  509. while ( ( size_central_dir_to_read > 0 ) && ( err == ZIP_OK ) ) {
  510. unsigned long read_this = SIZEDATA_INDATABLOCK;
  511. if ( read_this > size_central_dir_to_read ) {
  512. read_this = size_central_dir_to_read;
  513. }
  514. if ( ziinit.filestream->Read( buf_read, read_this ) != ( int )read_this ) {
  515. err = ZIP_ERRNO;
  516. }
  517. if ( err == ZIP_OK ) {
  518. err = add_data_in_datablock( &ziinit.central_dir, buf_read, (unsigned long)read_this );
  519. }
  520. size_central_dir_to_read -= read_this;
  521. }
  522. TRYFREE( buf_read );
  523. }
  524. ziinit.begin_pos = byte_before_the_zipfile;
  525. ziinit.number_entry = number_entry_CD;
  526. if ( ziinit.filestream->Seek( offset_central_dir + byte_before_the_zipfile, FS_SEEK_SET ) != 0 ) {
  527. err = ZIP_ERRNO;
  528. }
  529. }
  530. if ( globalcomment ) {
  531. /// ??
  532. globalcomment = ziinit.globalcomment;
  533. }
  534. #endif /* !NO_ADDFILEINEXISTINGZIP*/
  535. if ( err != ZIP_OK ) {
  536. #ifndef NO_ADDFILEINEXISTINGZIP
  537. TRYFREE( ziinit.globalcomment );
  538. #endif /* !NO_ADDFILEINEXISTINGZIP*/
  539. TRYFREE( zi );
  540. return NULL;
  541. } else {
  542. *zi = ziinit;
  543. return (zipFile)zi;
  544. }
  545. }
  546. /*
  547. ========================
  548. zipOpen
  549. ========================
  550. */
  551. zipFile zipOpen( const char *pathname, int append ) {
  552. return zipOpen2( pathname, append, NULL );
  553. }
  554. /*
  555. ========================
  556. zipOpenNewFileInZip3
  557. ========================
  558. */
  559. int zipOpenNewFileInZip3( zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, unsigned int size_extrafield_local, const void* extrafield_global,
  560. unsigned int size_extrafield_global, const char* comment, int method, int level, int raw, int windowBits, int memLevel, int strategy, const char* password, unsigned long crcForCrypting ) {
  561. unsigned int size_filename;
  562. unsigned int size_comment;
  563. int err = ZIP_OK;
  564. #ifdef NOCRYPT
  565. if ( password != NULL ) {
  566. return ZIP_PARAMERROR;
  567. }
  568. #endif
  569. if ( file == NULL ) {
  570. return ZIP_PARAMERROR;
  571. }
  572. if ( ( method != 0 ) && ( method != Z_DEFLATED ) ) {
  573. return ZIP_PARAMERROR;
  574. }
  575. zip_internal* zi = (zip_internal*)file;
  576. if ( zi->in_opened_file_inzip == 1 ) {
  577. err = zipCloseFileInZip( file );
  578. if ( err != ZIP_OK ) {
  579. return err;
  580. }
  581. }
  582. if ( filename == NULL ) {
  583. filename = "-";
  584. }
  585. if ( comment == NULL ) {
  586. size_comment = 0;
  587. } else {
  588. size_comment = (unsigned int)idStr::Length( comment );
  589. }
  590. size_filename = (unsigned int)idStr::Length( filename );
  591. if ( zipfi == NULL ) {
  592. zi->ci.dosDate = 0;
  593. } else {
  594. if ( zipfi->dosDate != 0 ) {
  595. zi->ci.dosDate = zipfi->dosDate;
  596. } else {
  597. zi->ci.dosDate = ziplocal_TmzDateToDosDate( &zipfi->tmz_date, zipfi->dosDate );
  598. }
  599. }
  600. zi->ci.flag = 0;
  601. if ( ( level == 8 ) || ( level == 9 ) ) {
  602. zi->ci.flag |= 2;
  603. }
  604. if ( ( level == 2 ) ) {
  605. zi->ci.flag |= 4;
  606. }
  607. if ( ( level == 1 ) ) {
  608. zi->ci.flag |= 6;
  609. }
  610. if ( password != NULL ) {
  611. zi->ci.flag |= 1;
  612. }
  613. zi->ci.crc32 = 0;
  614. zi->ci.method = method;
  615. zi->ci.encrypt = 0;
  616. zi->ci.stream_initialised = 0;
  617. zi->ci.pos_in_buffered_data = 0;
  618. zi->ci.raw = raw;
  619. zi->ci.pos_local_header = (unsigned long)zi->filestream->Tell();
  620. zi->ci.size_centralheader = SIZECENTRALHEADER + size_filename + size_extrafield_global + size_comment;
  621. zi->ci.central_header = (char*)ALLOC( (unsigned int)zi->ci.size_centralheader );
  622. ziplocal_putValue_inmemory( zi->ci.central_header, (unsigned long)CENTRALHEADERMAGIC, 4 );
  623. /* version info */
  624. ziplocal_putValue_inmemory( zi->ci.central_header + 4, (unsigned long)0, 2 );
  625. ziplocal_putValue_inmemory( zi->ci.central_header + 6, (unsigned long)20, 2 );
  626. ziplocal_putValue_inmemory( zi->ci.central_header + 8, (unsigned long)zi->ci.flag, 2 );
  627. ziplocal_putValue_inmemory( zi->ci.central_header + 10, (unsigned long)zi->ci.method, 2 );
  628. ziplocal_putValue_inmemory( zi->ci.central_header + 12, (unsigned long)zi->ci.dosDate, 4 );
  629. ziplocal_putValue_inmemory( zi->ci.central_header + 16, (unsigned long)0, 4 ); /*crc*/
  630. ziplocal_putValue_inmemory( zi->ci.central_header + 20, (unsigned long)0, 4 ); /*compr size*/
  631. ziplocal_putValue_inmemory( zi->ci.central_header + 24, (unsigned long)0, 4 ); /*uncompr size*/
  632. ziplocal_putValue_inmemory( zi->ci.central_header + 28, (unsigned long)size_filename, 2 );
  633. ziplocal_putValue_inmemory( zi->ci.central_header + 30, (unsigned long)size_extrafield_global, 2 );
  634. ziplocal_putValue_inmemory( zi->ci.central_header + 32, (unsigned long)size_comment, 2 );
  635. ziplocal_putValue_inmemory( zi->ci.central_header + 34, (unsigned long)0, 2 ); /*disk nm start*/
  636. if ( zipfi == NULL ) {
  637. ziplocal_putValue_inmemory( zi->ci.central_header + 36, (unsigned long)0, 2 );
  638. } else {
  639. ziplocal_putValue_inmemory( zi->ci.central_header + 36, (unsigned long)zipfi->internal_fa, 2 );
  640. }
  641. if ( zipfi == NULL ) {
  642. ziplocal_putValue_inmemory( zi->ci.central_header + 38,(unsigned long)0, 4);
  643. } else {
  644. ziplocal_putValue_inmemory( zi->ci.central_header + 38,(unsigned long)zipfi->external_fa, 4);
  645. }
  646. ziplocal_putValue_inmemory( zi->ci.central_header + 42, (unsigned long)zi->ci.pos_local_header - zi->add_position_when_writting_offset, 4 );
  647. for ( unsigned int i = 0; i < size_filename; i++ ) {
  648. *( zi->ci.central_header + SIZECENTRALHEADER + i ) = *( filename + i );
  649. }
  650. for ( unsigned int i = 0; i < size_extrafield_global; i++ ) {
  651. *( zi->ci.central_header + SIZECENTRALHEADER + size_filename + i ) = *( ( ( const char* )extrafield_global ) + i );
  652. }
  653. for ( unsigned int i = 0; i < size_comment; i++ ) {
  654. *( zi->ci.central_header + SIZECENTRALHEADER + size_filename + size_extrafield_global + i ) = *( comment + i );
  655. }
  656. if ( zi->ci.central_header == NULL ) {
  657. return ZIP_INTERNALERROR;
  658. }
  659. /* write the local header */
  660. err = ziplocal_putValue( zi->filestream, (unsigned long)LOCALHEADERMAGIC, 4 );
  661. if ( err == ZIP_OK ) {
  662. err = ziplocal_putValue( zi->filestream, (unsigned long)20, 2 ); /* version needed to extract */
  663. }
  664. if ( err == ZIP_OK ) {
  665. err = ziplocal_putValue( zi->filestream, (unsigned long)zi->ci.flag, 2 );
  666. }
  667. if ( err == ZIP_OK ) {
  668. err = ziplocal_putValue( zi->filestream, (unsigned long)zi->ci.method, 2 );
  669. }
  670. if ( err == ZIP_OK ) {
  671. err = ziplocal_putValue( zi->filestream, (unsigned long)zi->ci.dosDate, 4 );
  672. }
  673. if ( err == ZIP_OK ) {
  674. err = ziplocal_putValue( zi->filestream, (unsigned long)0, 4 ); /* crc 32, unknown */
  675. }
  676. if ( err == ZIP_OK ) {
  677. err = ziplocal_putValue( zi->filestream, (unsigned long)0, 4 ); /* compressed size, unknown */
  678. }
  679. if ( err == ZIP_OK ) {
  680. err = ziplocal_putValue( zi->filestream, (unsigned long)0, 4 ); /* uncompressed size, unknown */
  681. }
  682. if ( err == ZIP_OK ) {
  683. err = ziplocal_putValue( zi->filestream, (unsigned long)size_filename, 2 );
  684. }
  685. if ( err == ZIP_OK ) {
  686. err = ziplocal_putValue( zi->filestream, (unsigned long)size_extrafield_local, 2 );
  687. }
  688. if ( ( err == ZIP_OK ) && ( size_filename > 0 ) ) {
  689. if ( zi->filestream->Write( filename, size_filename ) != ( int )size_filename ) {
  690. err = ZIP_ERRNO;
  691. }
  692. }
  693. if ( ( err == ZIP_OK ) && ( size_extrafield_local > 0 ) ) {
  694. if ( zi->filestream->Write( extrafield_local, size_extrafield_local ) != ( int )size_extrafield_local ) {
  695. err = ZIP_ERRNO;
  696. }
  697. }
  698. zi->ci.stream.avail_in = (unsigned int)0;
  699. zi->ci.stream.avail_out = (unsigned int)Z_BUFSIZE;
  700. zi->ci.stream.next_out = zi->ci.buffered_data;
  701. zi->ci.stream.total_in = 0;
  702. zi->ci.stream.total_out = 0;
  703. if ( ( err == ZIP_OK ) && ( zi->ci.method == Z_DEFLATED ) && ( !zi->ci.raw ) ) {
  704. zi->ci.stream.zalloc = (alloc_func)0;
  705. zi->ci.stream.zfree = (free_func)0;
  706. zi->ci.stream.opaque = (voidpf)0;
  707. if ( windowBits > 0 ) {
  708. windowBits = -windowBits;
  709. }
  710. err = deflateInit2( &zi->ci.stream, level, Z_DEFLATED, windowBits, memLevel, strategy );
  711. if ( err == Z_OK ) {
  712. zi->ci.stream_initialised = 1;
  713. }
  714. }
  715. #ifndef NOCRYPT
  716. zi->ci.crypt_header_size = 0;
  717. if ( ( err == Z_OK ) && ( password != NULL ) ) {
  718. unsigned char bufHead[RAND_HEAD_LEN];
  719. unsigned int sizeHead;
  720. zi->ci.encrypt = 1;
  721. zi->ci.pcrc_32_tab = get_crc_table();
  722. /*init_keys( password, zi->ci.keys, zi->ci.pcrc_32_tab );*/
  723. sizeHead=crypthead( password, bufHead, RAND_HEAD_LEN, zi->ci.keys, zi->ci.pcrc_32_tab, crcForCrypting );
  724. zi->ci.crypt_header_size = sizeHead;
  725. if ( ZWRITE( zi->z_filefunc, zi->filestream, bufHead, sizeHead ) != sizeHead ) {
  726. err = ZIP_ERRNO;
  727. }
  728. }
  729. #endif
  730. if ( err == Z_OK ) {
  731. zi->in_opened_file_inzip = 1;
  732. }
  733. return err;
  734. }
  735. /*
  736. ========================
  737. zipOpenNewFileInZip2
  738. ========================
  739. */
  740. int zipOpenNewFileInZip2( zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, unsigned int size_extrafield_local,
  741. const void* extrafield_global, unsigned int size_extrafield_global, const char* comment, int method, int level, int raw ) {
  742. return zipOpenNewFileInZip3( file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global,
  743. comment, method, level, raw, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, NULL, 0 );
  744. }
  745. /*
  746. ========================
  747. zipOpenNewFileInZip
  748. ========================
  749. */
  750. int zipOpenNewFileInZip( zipFile file, const char* filename, const zip_fileinfo* zipfi, const void* extrafield_local, unsigned int size_extrafield_local, const void* extrafield_global,
  751. unsigned int size_extrafield_global, const char* comment, int method, int level ) {
  752. return zipOpenNewFileInZip2( file, filename, zipfi, extrafield_local, size_extrafield_local, extrafield_global, size_extrafield_global, comment, method, level, 0 );
  753. }
  754. /*
  755. ========================
  756. zipFlushWriteBuffer
  757. ========================
  758. */
  759. int zipFlushWriteBuffer( zip_internal* zi ) {
  760. int err = ZIP_OK;
  761. if ( zi->ci.encrypt != 0 ) {
  762. #ifndef NOCRYPT
  763. int t;
  764. for ( int i = 0; i < zi->ci.pos_in_buffered_data; i++ ) {
  765. zi->ci.buffered_data[i] = zencode( zi->ci.keys, zi->ci.pcrc_32_tab, zi->ci.buffered_data[i], t );
  766. }
  767. #endif
  768. }
  769. if ( zi->filestream->Write( zi->ci.buffered_data, zi->ci.pos_in_buffered_data ) != (int)zi->ci.pos_in_buffered_data ) {
  770. err = ZIP_ERRNO;
  771. }
  772. zi->ci.pos_in_buffered_data = 0;
  773. return err;
  774. }
  775. /*
  776. ========================
  777. zipWriteInFileInZip
  778. ========================
  779. */
  780. int zipWriteInFileInZip( zipFile file, const void* buf, unsigned int len ) {
  781. zip_internal* zi;
  782. int err = ZIP_OK;
  783. if ( file == NULL ) {
  784. return ZIP_PARAMERROR;
  785. }
  786. zi = (zip_internal*)file;
  787. if ( zi->in_opened_file_inzip == 0 ) {
  788. return ZIP_PARAMERROR;
  789. }
  790. zi->ci.stream.next_in = (Bytef*)buf;
  791. zi->ci.stream.avail_in = len;
  792. zi->ci.crc32 = crc32( zi->ci.crc32, (byte*)buf, len );
  793. while ( ( err == ZIP_OK ) && ( zi->ci.stream.avail_in > 0 ) ) {
  794. if ( zi->ci.stream.avail_out == 0 ) {
  795. if ( zipFlushWriteBuffer( zi ) == ZIP_ERRNO ) {
  796. err = ZIP_ERRNO;
  797. }
  798. zi->ci.stream.avail_out = (unsigned int)Z_BUFSIZE;
  799. zi->ci.stream.next_out = zi->ci.buffered_data;
  800. }
  801. if ( err != ZIP_OK ) {
  802. break;
  803. }
  804. if ( ( zi->ci.method == Z_DEFLATED ) && ( !zi->ci.raw ) ) {
  805. unsigned long uTotalOutBefore = zi->ci.stream.total_out;
  806. err = deflate( &zi->ci.stream, Z_NO_FLUSH );
  807. zi->ci.pos_in_buffered_data += (unsigned int)( zi->ci.stream.total_out - uTotalOutBefore );
  808. } else {
  809. unsigned int copy_this;
  810. if ( zi->ci.stream.avail_in < zi->ci.stream.avail_out ) {
  811. copy_this = zi->ci.stream.avail_in;
  812. } else {
  813. copy_this = zi->ci.stream.avail_out;
  814. }
  815. for ( unsigned int i = 0; i < copy_this; i++ ) {
  816. *( ( (char*)zi->ci.stream.next_out ) + i ) = *( ( (const char*)zi->ci.stream.next_in ) + i );
  817. }
  818. zi->ci.stream.avail_in -= copy_this;
  819. zi->ci.stream.avail_out-= copy_this;
  820. zi->ci.stream.next_in+= copy_this;
  821. zi->ci.stream.next_out+= copy_this;
  822. zi->ci.stream.total_in+= copy_this;
  823. zi->ci.stream.total_out+= copy_this;
  824. zi->ci.pos_in_buffered_data += copy_this;
  825. }
  826. }
  827. return err;
  828. }
  829. /*
  830. ========================
  831. zipCloseFileInZipRaw
  832. ========================
  833. */
  834. int zipCloseFileInZipRaw( zipFile file, unsigned long uncompressed_size, unsigned long crc32 ) {
  835. zip_internal* zi;
  836. unsigned long compressed_size;
  837. int err = ZIP_OK;
  838. if ( file == NULL ) {
  839. return ZIP_PARAMERROR;
  840. }
  841. zi = (zip_internal*)file;
  842. if ( zi->in_opened_file_inzip == 0 ) {
  843. return ZIP_PARAMERROR;
  844. }
  845. zi->ci.stream.avail_in = 0;
  846. if ( ( zi->ci.method == Z_DEFLATED ) && !zi->ci.raw ) {
  847. while ( err == ZIP_OK ) {
  848. unsigned long uTotalOutBefore;
  849. if ( zi->ci.stream.avail_out == 0 ) {
  850. if ( zipFlushWriteBuffer( zi ) == ZIP_ERRNO ) {
  851. err = ZIP_ERRNO;
  852. }
  853. zi->ci.stream.avail_out = (unsigned int)Z_BUFSIZE;
  854. zi->ci.stream.next_out = zi->ci.buffered_data;
  855. }
  856. uTotalOutBefore = zi->ci.stream.total_out;
  857. err = deflate( &zi->ci.stream, Z_FINISH );
  858. zi->ci.pos_in_buffered_data += (unsigned int)( zi->ci.stream.total_out - uTotalOutBefore );
  859. }
  860. }
  861. if ( err == Z_STREAM_END ) {
  862. err = ZIP_OK; /* this is normal */
  863. }
  864. if ( ( zi->ci.pos_in_buffered_data > 0 ) && ( err == ZIP_OK ) ) {
  865. if ( zipFlushWriteBuffer( zi ) == ZIP_ERRNO ) {
  866. err = ZIP_ERRNO;
  867. }
  868. }
  869. if ( ( zi->ci.method == Z_DEFLATED ) && !zi->ci.raw ) {
  870. err = deflateEnd( &zi->ci.stream );
  871. zi->ci.stream_initialised = 0;
  872. }
  873. if ( !zi->ci.raw ) {
  874. crc32 = (unsigned long)zi->ci.crc32;
  875. uncompressed_size = (unsigned long)zi->ci.stream.total_in;
  876. }
  877. compressed_size = (unsigned long)zi->ci.stream.total_out;
  878. #ifndef NOCRYPT
  879. compressed_size += zi->ci.crypt_header_size;
  880. #endif
  881. ziplocal_putValue_inmemory( zi->ci.central_header + 16, crc32, 4); /*crc*/
  882. ziplocal_putValue_inmemory( zi->ci.central_header + 20, compressed_size, 4 ); /*compr size*/
  883. if ( zi->ci.stream.data_type == Z_ASCII ) {
  884. ziplocal_putValue_inmemory( zi->ci.central_header + 36, (unsigned long)Z_ASCII, 2 );
  885. }
  886. ziplocal_putValue_inmemory( zi->ci.central_header + 24, uncompressed_size, 4 ); /*uncompr size*/
  887. if ( err == ZIP_OK ) {
  888. err = add_data_in_datablock( &zi->central_dir, zi->ci.central_header, (unsigned long)zi->ci.size_centralheader );
  889. }
  890. TRYFREE( zi->ci.central_header );
  891. if ( err == ZIP_OK ) {
  892. long cur_pos_inzip = (long)zi->filestream->Tell();
  893. if ( zi->filestream->Seek( zi->ci.pos_local_header + 14, FS_SEEK_SET ) != 0 ) {
  894. err = ZIP_ERRNO;
  895. }
  896. if ( err == ZIP_OK ) {
  897. err = ziplocal_putValue( zi->filestream, crc32, 4 ); /* crc 32, unknown */
  898. }
  899. if ( err == ZIP_OK ) { /* compressed size, unknown */
  900. err = ziplocal_putValue( zi->filestream, compressed_size, 4 );
  901. }
  902. if ( err == ZIP_OK ) { /* uncompressed size, unknown */
  903. err = ziplocal_putValue( zi->filestream, uncompressed_size, 4 );
  904. }
  905. if ( zi->filestream->Seek( cur_pos_inzip, FS_SEEK_SET ) != 0 ) {
  906. err = ZIP_ERRNO;
  907. }
  908. }
  909. zi->number_entry++;
  910. zi->in_opened_file_inzip = 0;
  911. return err;
  912. }
  913. /*
  914. ========================
  915. zipCloseFileInZip
  916. ========================
  917. */
  918. int zipCloseFileInZip( zipFile file ) {
  919. return zipCloseFileInZipRaw( file, 0, 0 );
  920. }
  921. /*
  922. ========================
  923. zipClose
  924. ========================
  925. */
  926. int zipClose( zipFile file, const char* global_comment ) {
  927. zip_internal* zi;
  928. int err = 0;
  929. unsigned long size_centraldir = 0;
  930. unsigned long centraldir_pos_inzip;
  931. unsigned int size_global_comment;
  932. if ( file == NULL ) {
  933. return ZIP_PARAMERROR;
  934. }
  935. zi = (zip_internal*)file;
  936. if ( zi->in_opened_file_inzip == 1 ) {
  937. err = zipCloseFileInZip( file );
  938. }
  939. #ifndef NO_ADDFILEINEXISTINGZIP
  940. if ( global_comment == NULL ) {
  941. global_comment = zi->globalcomment;
  942. }
  943. #endif
  944. if ( global_comment == NULL ) {
  945. size_global_comment = 0;
  946. } else {
  947. size_global_comment = (unsigned int)idStr::Length( global_comment );
  948. }
  949. centraldir_pos_inzip = (unsigned long)zi->filestream->Tell();
  950. if ( err == ZIP_OK ) {
  951. linkedlist_datablock_internal* ldi = zi->central_dir.first_block;
  952. while ( ldi != NULL ) {
  953. if ( ( err == ZIP_OK ) && ( ldi->filled_in_this_block > 0 ) ) {
  954. if ( zi->filestream->Write( ldi->data, ldi->filled_in_this_block ) != (int)ldi->filled_in_this_block ) {
  955. err = ZIP_ERRNO;
  956. }
  957. }
  958. size_centraldir += ldi->filled_in_this_block;
  959. ldi = ldi->next_datablock;
  960. }
  961. }
  962. free_datablock( zi->central_dir.first_block );
  963. if ( err == ZIP_OK ) { /* Magic End */
  964. err = ziplocal_putValue( zi->filestream, (unsigned long)ENDHEADERMAGIC, 4 );
  965. }
  966. if ( err == ZIP_OK ) { /* number of this disk */
  967. err = ziplocal_putValue( zi->filestream, (unsigned long)0, 2 );
  968. }
  969. if ( err == ZIP_OK ) { /* number of the disk with the start of the central directory */
  970. err = ziplocal_putValue( zi->filestream, (unsigned long)0, 2 );
  971. }
  972. if ( err == ZIP_OK ) { /* total number of entries in the central dir on this disk */
  973. err = ziplocal_putValue( zi->filestream, (unsigned long)zi->number_entry, 2 );
  974. }
  975. if ( err == ZIP_OK ) { /* total number of entries in the central dir */
  976. err = ziplocal_putValue( zi->filestream, (unsigned long)zi->number_entry, 2 );
  977. }
  978. if ( err == ZIP_OK ) { /* size of the central directory */
  979. err = ziplocal_putValue( zi->filestream, (unsigned long)size_centraldir, 4 );
  980. }
  981. if ( err == ZIP_OK ) { /* offset of start of central directory with respect to the starting disk number */
  982. err = ziplocal_putValue( zi->filestream, (unsigned long)( centraldir_pos_inzip - zi->add_position_when_writting_offset ), 4 );
  983. }
  984. if ( err == ZIP_OK ) { /* zipfile comment length */
  985. err = ziplocal_putValue( zi->filestream, (unsigned long)size_global_comment, 2 );
  986. }
  987. if ( ( err == ZIP_OK ) && ( size_global_comment > 0 ) ) {
  988. if ( zi->filestream->Write( global_comment, size_global_comment ) != (int)size_global_comment ) {
  989. err = ZIP_ERRNO;
  990. }
  991. }
  992. delete zi->filestream;
  993. zi->filestream = NULL;
  994. #ifndef NO_ADDFILEINEXISTINGZIP
  995. TRYFREE( zi->globalcomment );
  996. #endif
  997. TRYFREE( zi );
  998. return err;
  999. }
  1000. /*
  1001. ========================
  1002. idZipBuilder::AddFileFilters
  1003. ========================
  1004. */
  1005. void idZipBuilder::AddFileFilters( const char *filters ) {
  1006. #if 0
  1007. idStrList exts;
  1008. idStrListBreakupString( exts, filters, "|" );
  1009. if ( ( exts.Num() > 0 ) && ( exts[ exts.Num() - 1 ] == "" ) ) {
  1010. exts.RemoveIndex( exts.Num() - 1 );
  1011. }
  1012. filterExts.Append( exts );
  1013. #endif
  1014. }
  1015. /*
  1016. ========================
  1017. idZipBuilder::AddUncompressedFileFilters
  1018. ========================
  1019. */
  1020. void idZipBuilder::AddUncompressedFileFilters( const char *filters ) {
  1021. #if 0
  1022. idStrList exts;
  1023. idStrListBreakupString( exts, filters, "|" );
  1024. if ( ( exts.Num() > 0 ) && ( exts[ exts.Num() - 1 ] == "" ) ) {
  1025. exts.RemoveIndex( exts.Num() - 1 );
  1026. }
  1027. uncompressedFilterExts.Append( exts );
  1028. #endif
  1029. }
  1030. /*
  1031. ========================
  1032. idZipBuilder::Build
  1033. builds a zip file of all the files in the specified folder, overwriting if necessary
  1034. ========================
  1035. */
  1036. bool idZipBuilder::Build( const char* zipPath, const char *folder, bool cleanFolder ) {
  1037. zipFileName = zipPath;
  1038. sourceFolderName = folder;
  1039. if ( !CreateZipFile( false ) ) {
  1040. // don't clean the folder if the zip fails
  1041. return false;
  1042. }
  1043. if ( cleanFolder ) {
  1044. CleanSourceFolder();
  1045. }
  1046. return true;
  1047. }
  1048. /*
  1049. ========================
  1050. idZipBuilder::Update
  1051. updates a zip file with the files in the specified folder
  1052. ========================
  1053. */
  1054. bool idZipBuilder::Update( const char* zipPath, const char *folder, bool cleanFolder ) {
  1055. // if this file doesn't exist, just build it
  1056. if ( fileSystem->GetTimestamp( zipPath ) == FILE_NOT_FOUND_TIMESTAMP ) {
  1057. return Build( zipPath, folder, cleanFolder );
  1058. }
  1059. zipFileName = zipPath;
  1060. sourceFolderName = folder;
  1061. if ( !CreateZipFile( true ) ) {
  1062. // don't clean the folder if the zip fails
  1063. return false;
  1064. }
  1065. if ( cleanFolder ) {
  1066. CleanSourceFolder();
  1067. }
  1068. return true;
  1069. }
  1070. /*
  1071. ========================
  1072. idZipBuilder::GetFileTime
  1073. ========================
  1074. */
  1075. bool idZipBuilder::GetFileTime( const idStr &filename, unsigned long *dostime ) const {
  1076. {
  1077. FILETIME filetime;
  1078. WIN32_FIND_DATA fileData;
  1079. HANDLE findHandle = FindFirstFile( filename.c_str(), &fileData );
  1080. if ( findHandle != INVALID_HANDLE_VALUE ) {
  1081. FileTimeToLocalFileTime( &(fileData.ftLastWriteTime), &filetime );
  1082. FileTimeToDosDateTime( &filetime, ((LPWORD)dostime) + 1, ((LPWORD)dostime) + 0 );
  1083. FindClose( findHandle );
  1084. return true;
  1085. }
  1086. FindClose( findHandle );
  1087. }
  1088. return false;
  1089. }
  1090. /*
  1091. ========================
  1092. idZipBuilder::IsFiltered
  1093. ========================
  1094. */
  1095. bool idZipBuilder::IsFiltered( const idStr &filename ) const {
  1096. if ( filterExts.Num() == 0 && uncompressedFilterExts.Num() == 0 ) {
  1097. return false;
  1098. }
  1099. for ( int j = 0; j < filterExts.Num(); j++ ) {
  1100. idStr fileExt = idStr( "." + filterExts[j] );
  1101. if ( filename.Right( fileExt.Length() ).Icmp( fileExt ) == 0 ) {
  1102. return false;
  1103. }
  1104. }
  1105. for ( int j = 0; j < uncompressedFilterExts.Num(); j++ ) {
  1106. idStr fileExt = idStr( "." + uncompressedFilterExts[j] );
  1107. if ( filename.Right( fileExt.Length() ).Icmp( fileExt ) == 0 ) {
  1108. return false;
  1109. }
  1110. }
  1111. return true;
  1112. }
  1113. /*
  1114. ========================
  1115. idZipBuilder::IsUncompressed
  1116. ========================
  1117. */
  1118. bool idZipBuilder::IsUncompressed( const idStr &filename ) const {
  1119. if ( uncompressedFilterExts.Num() == 0 ) {
  1120. return false;
  1121. }
  1122. for ( int j = 0; j < uncompressedFilterExts.Num(); j++ ) {
  1123. idStr fileExt = idStr( "." + uncompressedFilterExts[j] );
  1124. if ( filename.Right( fileExt.Length() ).Icmp( fileExt ) == 0 ) {
  1125. return true;
  1126. }
  1127. }
  1128. return false;
  1129. }
  1130. /*
  1131. ========================
  1132. idZipBuilder::CreateZipFile
  1133. ========================
  1134. */
  1135. bool idZipBuilder::CreateZipFile( bool appendFiles ) {
  1136. #if 0
  1137. //#ifdef ID_PC
  1138. if ( zipFileName.IsEmpty() || sourceFolderName.IsEmpty() ) {
  1139. idLib::Warning( "[%s] - invalid parameters!", __FUNCTION__ );
  1140. return false;
  1141. }
  1142. // need to clear the filesystem's zip cache before we can open and write
  1143. //fileSystem->ClearZipCache();
  1144. idLib::Printf( "Building zip file: '%s'\n", zipFileName.c_str() );
  1145. sourceFolderName.StripTrailing( "\\" );
  1146. sourceFolderName.StripTrailing( "/" );
  1147. #if 0
  1148. // attempt to check the file out
  1149. if ( !Sys_IsFileWritable( zipFileName ) ) {
  1150. if ( ( idLib::sourceControl == NULL ) || !idLib::sourceControl->CheckOut( zipFileName ) ) {
  1151. idLib::Warning( "READONLY zip file couldn't be checked out: %s", zipFileName.c_str() );
  1152. } else {
  1153. idLib::Printf( "Checked out: %s\n", zipFileName.c_str() );
  1154. }
  1155. }
  1156. #endif
  1157. // if not appending, set the file size to zero to "create it from scratch"
  1158. if ( !appendFiles ) {
  1159. idLib::PrintfIf( zip_verbosity.GetBool(), "Overwriting zip file: '%s'\n", zipFileName.c_str() );
  1160. idFile *zipFile = fileSystem->OpenExplicitFileWrite( zipFileName );
  1161. if ( zipFile != NULL ) {
  1162. delete zipFile;
  1163. zipFile = NULL;
  1164. }
  1165. } else {
  1166. idLib::PrintfIf( zip_verbosity.GetBool(), "Appending to zip file: '%s'\n", zipFileName.c_str() );
  1167. }
  1168. // enumerate the files to zip up in the source folder
  1169. idStrStatic< MAX_OSPATH > relPath;
  1170. relPath =
  1171. fileSystem->OSPathToRelativePath( sourceFolderName );
  1172. idFileList *files = fileSystem->ListFilesTree( relPath, "*.*" );
  1173. // check to make sure that at least one file will be added to the package
  1174. int atLeastOneFilteredFile = false;
  1175. for ( int i = 0; i < files->GetNumFiles(); i++ ) {
  1176. idStr filename = files->GetFile( i );
  1177. if ( !IsFiltered( filename ) ) {
  1178. atLeastOneFilteredFile = true;
  1179. break;
  1180. }
  1181. }
  1182. if ( !atLeastOneFilteredFile ) {
  1183. // although we didn't actually update/create a zip file, it's because no files would be added anyway, which would result in a corrupted zip
  1184. idLib::Printf( "Skipping zip creation/modification, no additional changes need to be made...\n" );
  1185. return true;
  1186. }
  1187. // open the zip file
  1188. zipFile zf = zipOpen( zipFileName, appendFiles ? APPEND_STATUS_ADDINZIP : 0 );
  1189. if ( zf == NULL ) {
  1190. idLib::Warning( "[%s] - error opening file '%s'!", __FUNCTION__, zipFileName.c_str() );
  1191. return false;
  1192. }
  1193. // add the files to the zip file
  1194. for ( int i = 0; i < files->GetNumFiles(); i++ ) {
  1195. // add each file to the zip file
  1196. zip_fileinfo zi;
  1197. memset( &zi, 0, sizeof( zip_fileinfo ) );
  1198. idStr filename = files->GetFile( i );
  1199. if ( IsFiltered( filename ) ) {
  1200. idLib::PrintfIf( zip_verbosity.GetBool(), "...Skipping: '%s'\n", filename.c_str() );
  1201. continue;
  1202. }
  1203. idStr filenameInZip = filename;
  1204. filenameInZip.Strip( relPath );
  1205. filenameInZip.StripLeading( "/" );
  1206. idStrStatic< MAX_OSPATH > ospath;
  1207. ospath = fileSystem->RelativePathToOSPath( filename );
  1208. GetFileTime( ospath, &zi.dosDate );
  1209. idLib::PrintfIf( zip_verbosity.GetBool(), "...Adding: '%s' ", filenameInZip.c_str() );
  1210. int compressionMethod = Z_DEFLATED;
  1211. if ( IsUncompressed( filenameInZip ) ) {
  1212. compressionMethod = 0;
  1213. }
  1214. int errcode = zipOpenNewFileInZip3( zf, filenameInZip, &zi, NULL, 0, NULL, 0, NULL /* comment*/,
  1215. compressionMethod, DEFAULT_COMPRESSION_LEVEL, 0, -MAX_WBITS, DEF_MEM_LEVEL,
  1216. Z_DEFAULT_STRATEGY, NULL /*password*/, 0 /*fileCRC*/ );
  1217. if ( errcode != ZIP_OK ) {
  1218. idLib::Warning( "Error opening file in zipfile!" );
  1219. continue;
  1220. } else {
  1221. // open the source file
  1222. idFile_Permanent src( filename, ospath, FS_READ );
  1223. if ( !src.IsOpen() ) {
  1224. idLib::Warning( "Error opening source file!" );
  1225. continue;
  1226. }
  1227. // copy the file data into the zip file
  1228. idTempArray<byte> buffer( DEFAULT_WRITEBUFFERSIZE );
  1229. size_t total = 0;
  1230. while ( size_t bytesRead = src.Read( buffer.Ptr(), buffer.Size() ) ) {
  1231. if ( bytesRead > 0 ) {
  1232. errcode = zipWriteInFileInZip( zf, buffer.Ptr(), (unsigned int)bytesRead );
  1233. if ( errcode != ZIP_OK ) {
  1234. idLib::Warning( "Error writing to zipfile (%i bytes)!", bytesRead );
  1235. continue;
  1236. }
  1237. }
  1238. total += bytesRead;
  1239. }
  1240. assert( total == (size_t)src.Length() );
  1241. }
  1242. errcode = zipCloseFileInZip( zf );
  1243. if ( errcode != ZIP_OK ) {
  1244. idLib::Warning( "Error zipping source file!" );
  1245. continue;
  1246. }
  1247. idLib::PrintfIf( zip_verbosity.GetBool(), "\n" );
  1248. }
  1249. // free the file list
  1250. if ( files != NULL ) {
  1251. fileSystem->FreeFileList( files );
  1252. }
  1253. // close the zip file
  1254. int closeError = zipClose( zf, NULL );
  1255. if ( closeError != ZIP_OK ) {
  1256. idLib::Warning( "[%s] - error closing file '%s'!", __FUNCTION__, zipFileName.c_str() );
  1257. return false;
  1258. }
  1259. idLib::Printf( "Done.\n" );
  1260. return true;
  1261. #else
  1262. return false;
  1263. #endif
  1264. }
  1265. /*
  1266. ========================
  1267. idZipBuilder::CreateZipFileFromFileList
  1268. ========================
  1269. */
  1270. bool idZipBuilder::CreateZipFileFromFileList( const char *name, const idList< idFile_Memory * > & srcFiles ) {
  1271. zipFileName = name;
  1272. return CreateZipFileFromFiles( srcFiles );
  1273. }
  1274. /*
  1275. ========================
  1276. idZipBuilder::CreateZipFileFromFiles
  1277. ========================
  1278. */
  1279. bool idZipBuilder::CreateZipFileFromFiles( const idList< idFile_Memory * > & srcFiles ) {
  1280. if ( zipFileName.IsEmpty() ) {
  1281. idLib::Warning( "[%s] - invalid parameters!", __FUNCTION__ );
  1282. return false;
  1283. }
  1284. // need to clear the filesystem's zip cache before we can open and write
  1285. //fileSystem->ClearZipCache();
  1286. idLib::Printf( "Building zip file: '%s'\n", zipFileName.c_str() );
  1287. // do not allow overwrite as this should be a tempfile attempt to check the file out
  1288. if ( !Sys_IsFileWritable( zipFileName ) ) {
  1289. idLib::PrintfIf( zip_verbosity.GetBool(), "File %s not writeable, cannot proceed.\n", zipFileName.c_str() );
  1290. return false;
  1291. }
  1292. // open the zip file
  1293. zipFile zf = zipOpen( zipFileName, 0 );
  1294. if ( zf == NULL ) {
  1295. idLib::Warning( "[%s] - error opening file '%s'!", __FUNCTION__, zipFileName.c_str() );
  1296. return false;
  1297. }
  1298. // add the files to the zip file
  1299. for ( int i = 0; i < srcFiles.Num(); i++ ) {
  1300. // add each file to the zip file
  1301. zip_fileinfo zi;
  1302. memset( &zi, 0, sizeof( zip_fileinfo ) );
  1303. idFile_Memory * src = srcFiles[i];
  1304. src->MakeReadOnly();
  1305. idLib::PrintfIf( zip_verbosity.GetBool(), "...Adding: '%s' ", src->GetName() );
  1306. int compressionMethod = Z_DEFLATED;
  1307. if ( IsUncompressed( src->GetName() ) ) {
  1308. compressionMethod = 0;
  1309. }
  1310. int errcode = zipOpenNewFileInZip3( zf, src->GetName(), &zi, NULL, 0, NULL, 0, NULL /* comment*/,
  1311. compressionMethod, DEFAULT_COMPRESSION_LEVEL, 0, -MAX_WBITS, DEF_MEM_LEVEL,
  1312. Z_DEFAULT_STRATEGY, NULL /*password*/, 0 /*fileCRC*/ );
  1313. if ( errcode != ZIP_OK ) {
  1314. idLib::Warning( "Error opening file in zipfile!" );
  1315. continue;
  1316. } else {
  1317. // copy the file data into the zip file
  1318. idTempArray<byte> buffer( DEFAULT_WRITEBUFFERSIZE );
  1319. size_t total = 0;
  1320. while ( size_t bytesRead = src->Read( buffer.Ptr(), buffer.Size() ) ) {
  1321. if ( bytesRead > 0 ) {
  1322. errcode = zipWriteInFileInZip( zf, buffer.Ptr(), (unsigned int)bytesRead );
  1323. if ( errcode != ZIP_OK ) {
  1324. idLib::Warning( "Error writing to zipfile (%i bytes)!", bytesRead );
  1325. continue;
  1326. }
  1327. }
  1328. total += bytesRead;
  1329. }
  1330. assert( total == (size_t)src->Length() );
  1331. }
  1332. errcode = zipCloseFileInZip( zf );
  1333. if ( errcode != ZIP_OK ) {
  1334. idLib::Warning( "Error zipping source file!" );
  1335. continue;
  1336. }
  1337. idLib::PrintfIf( zip_verbosity.GetBool(), "\n" );
  1338. }
  1339. // close the zip file
  1340. int closeError = zipClose( zf, zipFileName );
  1341. if ( closeError != ZIP_OK ) {
  1342. idLib::Warning( "[%s] - error closing file '%s'!", __FUNCTION__, zipFileName.c_str() );
  1343. return false;
  1344. }
  1345. idLib::PrintfIf( zip_verbosity.GetBool(), "Done.\n" );
  1346. return true;
  1347. }
  1348. /*
  1349. ========================
  1350. idZipBuilder::CleanSourceFolder
  1351. this folder is assumed to be a path under FSPATH_BASE
  1352. ========================
  1353. */
  1354. zipFile idZipBuilder::CreateZipFile( const char *name ) {
  1355. idLib::Printf( "Creating zip file: '%s'\n", name );
  1356. // do not allow overwrite as this should be a tempfile attempt to check the file out
  1357. if ( !Sys_IsFileWritable( name ) ) {
  1358. idLib::PrintfIf( zip_verbosity.GetBool(), "File %s not writeable, cannot proceed.\n", name );
  1359. return NULL;
  1360. }
  1361. // open the zip file
  1362. zipFile zf = zipOpen( name, 0 );
  1363. if ( zf == NULL ) {
  1364. idLib::Warning( "[%s] - error opening file '%s'!", __FUNCTION__, name );
  1365. }
  1366. return zf;
  1367. }
  1368. /*
  1369. ========================
  1370. idZipBuilder::CleanSourceFolder
  1371. this folder is assumed to be a path under FSPATH_BASE
  1372. ========================
  1373. */
  1374. bool idZipBuilder::AddFile( zipFile zf, idFile_Memory *src, bool deleteFile ) {
  1375. // add each file to the zip file
  1376. zip_fileinfo zi;
  1377. memset( &zi, 0, sizeof( zip_fileinfo ) );
  1378. src->MakeReadOnly();
  1379. idLib::PrintfIf( zip_verbosity.GetBool(), "...Adding: '%s' ", src->GetName() );
  1380. int compressionMethod = Z_DEFLATED;
  1381. if ( IsUncompressed( src->GetName() ) ) {
  1382. compressionMethod = Z_NO_COMPRESSION;
  1383. }
  1384. int errcode = zipOpenNewFileInZip3( zf, src->GetName(), &zi, NULL, 0, NULL, 0, NULL /* comment*/,
  1385. compressionMethod, DEFAULT_COMPRESSION_LEVEL, 0, -MAX_WBITS, DEF_MEM_LEVEL,
  1386. Z_DEFAULT_STRATEGY, NULL /*password*/, 0 /*fileCRC*/ );
  1387. if ( errcode != ZIP_OK ) {
  1388. idLib::Warning( "Error opening file in zipfile!" );
  1389. if ( deleteFile ) {
  1390. src->Clear( true );
  1391. delete src;
  1392. }
  1393. return false;
  1394. } else {
  1395. // copy the file data into the zip file
  1396. idTempArray<byte> buffer( DEFAULT_WRITEBUFFERSIZE );
  1397. size_t total = 0;
  1398. while ( size_t bytesRead = src->Read( buffer.Ptr(), buffer.Size() ) ) {
  1399. if ( bytesRead > 0 ) {
  1400. errcode = zipWriteInFileInZip( zf, buffer.Ptr(), (unsigned int)bytesRead );
  1401. if ( errcode != ZIP_OK ) {
  1402. idLib::Warning( "Error writing to zipfile (%i bytes)!", bytesRead );
  1403. continue;
  1404. }
  1405. }
  1406. total += bytesRead;
  1407. }
  1408. assert( total == (size_t)src->Length() );
  1409. }
  1410. errcode = zipCloseFileInZip( zf );
  1411. if ( errcode != ZIP_OK ) {
  1412. idLib::Warning( "Error zipping source file!" );
  1413. if ( deleteFile ) {
  1414. src->Clear( true );
  1415. delete src;
  1416. }
  1417. return false;
  1418. }
  1419. idLib::PrintfIf( zip_verbosity.GetBool(), "\n" );
  1420. if ( deleteFile ) {
  1421. src->Clear( true );
  1422. delete src;
  1423. }
  1424. return true;
  1425. }
  1426. /*
  1427. ========================
  1428. idZipBuilder::CleanSourceFolder
  1429. this folder is assumed to be a path under FSPATH_BASE
  1430. ========================
  1431. */
  1432. void idZipBuilder::CloseZipFile( zipFile zf ) {
  1433. // close the zip file
  1434. int closeError = zipClose( zf, zipFileName );
  1435. if ( closeError != ZIP_OK ) {
  1436. idLib::Warning( "[%s] - error closing file '%s'!", __FUNCTION__, zipFileName.c_str() );
  1437. }
  1438. idLib::PrintfIf( zip_verbosity.GetBool(), "Done.\n" );
  1439. }
  1440. /*
  1441. ========================
  1442. idZipBuilder::CleanSourceFolder
  1443. this folder is assumed to be a path under FSPATH_BASE
  1444. ========================
  1445. */
  1446. void idZipBuilder::CleanSourceFolder() {
  1447. #if 0
  1448. //#ifdef ID_PC_WIN
  1449. idStrList deletedFiles;
  1450. // make sure this is a valid path, we don't want to go nuking
  1451. // some user path or something else unintentionally
  1452. idStr ospath = sourceFolderName;
  1453. ospath.SlashesToBackSlashes();
  1454. ospath.ToLower();
  1455. char relPath[MAX_OSPATH];
  1456. fileSystem->OSPathToRelativePath( ospath, relPath, MAX_OSPATH );
  1457. // get the game's base path
  1458. idStr basePath = fileSystem->GetBasePathStr( FSPATH_BASE );
  1459. basePath.AppendPath( BASE_GAMEDIR );
  1460. basePath.AppendPath( "maps" );
  1461. basePath.SlashesToBackSlashes();
  1462. basePath.ToLower();
  1463. // path must be off of our base path, ospath can't have .map on the end, and
  1464. // do some additional sanity checks
  1465. if ( ( ospath.Find( basePath ) == 0 ) && ( ospath.Right( 4 ) != ".map" ) &&
  1466. ( ospath != "c:\\" ) && ( ospath.Length() > basePath.Length() ) ) {
  1467. // get the files in the current directory
  1468. idFileList *files = fileSystem->ListFilesTree( relPath, "*.*" );
  1469. if ( files->GetNumFiles() && zip_verbosity.GetBool() ) {
  1470. idLib::Printf( "Deleting files in '%s'...\n", relPath );
  1471. }
  1472. for ( int i = 0; i < files->GetNumFiles(); i++ ) {
  1473. if ( IsFiltered( files->GetFile( i ) ) ) {
  1474. continue;
  1475. }
  1476. // nuke 'em
  1477. if ( zip_verbosity.GetBool() ) {
  1478. idLib::Printf( "\t...%s\n", files->GetFile( i ) );
  1479. }
  1480. fileSystem->RemoveFile( files->GetFile( i ) );
  1481. char ospath2[MAX_OSPATH];
  1482. fileSystem->RelativePathToOSPath( files->GetFile( i ), ospath2, MAX_OSPATH );
  1483. deletedFiles.Append( ospath2 );
  1484. }
  1485. fileSystem->FreeFileList( files );
  1486. fileSystem->RemoveDir( relPath );
  1487. } else {
  1488. idLib::Printf( "Warning: idZipBuilder::CleanSourceFolder - Non-standard path: '%s'!\n", ospath.c_str() );
  1489. return;
  1490. }
  1491. // figure out which deleted files need to be removed from source control, and then remove those files
  1492. idStrList filesToRemoveFromSourceControl;
  1493. for ( int i = 0; i < deletedFiles.Num(); i++ ) {
  1494. scFileStatus_t fileStatus = idLib::sourceControl->GetFileStatus( deletedFiles[ i ] );
  1495. if ( SCF_IS_IN_SOURCE_CONTROL( fileStatus ) ) {
  1496. filesToRemoveFromSourceControl.Append( deletedFiles[ i ] );
  1497. }
  1498. }
  1499. if ( filesToRemoveFromSourceControl.Num() > 0 ) {
  1500. idLib::sourceControl->Delete( filesToRemoveFromSourceControl );
  1501. }
  1502. #endif
  1503. }
  1504. /*
  1505. ========================
  1506. idZipBuilder::BuildMapFolderZip
  1507. ========================
  1508. */
  1509. const char *ZIP_FILE_EXTENSION = "pk4";
  1510. bool idZipBuilder::BuildMapFolderZip( const char *mapFileName ) {
  1511. idStr zipFileName = mapFileName;
  1512. zipFileName.SetFileExtension( ZIP_FILE_EXTENSION );
  1513. idStr pathToZip = mapFileName;
  1514. pathToZip.StripFileExtension();
  1515. idZipBuilder zip;
  1516. zip.AddFileFilters( "bcm|bmodel|proc|" );
  1517. zip.AddUncompressedFileFilters( "genmodel|sbcm|tbcm|" );
  1518. bool success = zip.Build( zipFileName, pathToZip, true );
  1519. // even if the zip build failed we want to clear the source folder so no contributing files are left around
  1520. if ( !success ) {
  1521. zip.CleanSourceFolder();
  1522. }
  1523. return success;
  1524. }
  1525. /*
  1526. ========================
  1527. idZipBuilder::UpdateMapFolderZip
  1528. ========================
  1529. */
  1530. bool idZipBuilder::UpdateMapFolderZip( const char *mapFileName ) {
  1531. idStr zipFileName = mapFileName;
  1532. zipFileName.SetFileExtension( ZIP_FILE_EXTENSION );
  1533. idStr pathToZip = mapFileName;
  1534. pathToZip.StripFileExtension();
  1535. idZipBuilder zip;
  1536. zip.AddFileFilters( "bcm|bmodel|proc|" );
  1537. zip.AddUncompressedFileFilters( "genmodel|sbcm|tbcm|" );
  1538. bool success = zip.Update( zipFileName, pathToZip, true );
  1539. // even if the zip build failed we want to clear the source folder so no contributing files are left around
  1540. if ( !success ) {
  1541. zip.CleanSourceFolder();
  1542. }
  1543. return success;
  1544. }
  1545. /*
  1546. ========================
  1547. idZipBuilder::CombineFiles
  1548. ========================
  1549. */
  1550. idFile_Memory * idZipBuilder::CombineFiles( const idList< idFile_Memory * > & srcFiles ) {
  1551. idFile_Memory * destFile = NULL;
  1552. #if 0
  1553. //#ifdef ID_PC
  1554. // create a new temp file so we can zip into it without refactoring the zip routines
  1555. char ospath[MAX_OSPATH];
  1556. const char * tempName = "temp.tmp";
  1557. fileSystem->RelativePathToOSPath( tempName, ospath, MAX_OSPATH, FSPATH_SAVE );
  1558. fileSystem->RemoveFile( ospath );
  1559. // combine src files into dest filename just specified
  1560. idZipBuilder zip;
  1561. zip.zipFileName = ospath;
  1562. bool ret = zip.CreateZipFileFromFiles( srcFiles );
  1563. // read the temp file created into a memory file to return
  1564. if ( ret ) {
  1565. destFile = new idFile_Memory();
  1566. if ( !destFile->Load( tempName, ospath ) ) {
  1567. assert( false && "couldn't read the combined file" );
  1568. delete destFile;
  1569. destFile = NULL;
  1570. }
  1571. // delete the temp file
  1572. fileSystem->RemoveFile( ospath );
  1573. // make the new file readable
  1574. destFile->MakeReadOnly();
  1575. }
  1576. #endif
  1577. return destFile;
  1578. }
  1579. CONSOLE_COMMAND( testZipBuilderCombineFiles, "test routine for memory zip file building", 0 ) {
  1580. #if 0
  1581. idList< idFile_Memory * > list;
  1582. const char * testString = "test";
  1583. int numFiles = 2;
  1584. if ( args.Argc() > 2 ) {
  1585. idLib::Printf( "usage: testZipBuilderExtractFiles [numFiles]\n" );
  1586. return;
  1587. }
  1588. for ( int arg = 1; arg < args.Argc(); arg++ ) {
  1589. numFiles = atoi( args.Argv( arg ) );
  1590. }
  1591. // allocate all the test files
  1592. for ( int i = 0; i < numFiles; i++ ) {
  1593. idFile_Memory * file = new idFile_Memory( va( "%s%d.txt", testString, i + 1 ) );
  1594. file->MakeWritable();
  1595. idStr str = va( "%s%d", testString, i + 1 );
  1596. file->WriteString( str );
  1597. list.Append( file );
  1598. }
  1599. // combine the files into a single memory file
  1600. idZipBuilder zip;
  1601. idFile_Memory * file = zip.CombineFiles( list );
  1602. if ( file != NULL ) {
  1603. file->MakeReadOnly();
  1604. char ospath[MAX_OSPATH];
  1605. const char * tempName = "temp.zip";
  1606. fileSystem->RelativePathToOSPath( tempName, ospath, MAX_OSPATH, FSPATH_SAVE );
  1607. // remove previous file if it exists
  1608. fileSystem->RemoveFile( ospath );
  1609. if ( file->Save( tempName, ospath ) ) {
  1610. idLib::PrintfIf( zip_verbosity.GetBool(), va( "File written: %s.\n", ospath ) );
  1611. } else {
  1612. idLib::Error( "Could not save the file." );
  1613. }
  1614. delete file;
  1615. }
  1616. list.DeleteContents();
  1617. #endif
  1618. // Now look at the temp.zip, unzip it to see if it works
  1619. }
  1620. /*
  1621. ========================
  1622. idZipBuilder::ExtractFiles
  1623. ========================
  1624. */
  1625. bool idZipBuilder::ExtractFiles( idFile_Memory * & srcFile, idList< idFile_Memory * > & destFiles ) {
  1626. bool ret = false;
  1627. #if 0
  1628. //#ifdef ID_PC
  1629. destFiles.Clear();
  1630. // write the memory file to temp storage so we can unzip it without refactoring the unzip routines
  1631. char ospath[MAX_OSPATH];
  1632. const char * tempName = "temp.tmp";
  1633. fileSystem->RelativePathToOSPath( tempName, ospath, MAX_OSPATH, FSPATH_SAVE );
  1634. ret = srcFile->Save( tempName, ospath );
  1635. assert( ret && "couldn't create temp file" );
  1636. if ( ret ) {
  1637. idLib::PrintfIf( zip_verbosity.GetBool(), "Opening archive %s:\n", ospath );
  1638. unzFile zip = unzOpen( ospath );
  1639. int numFiles = 0;
  1640. int result = unzGoToFirstFile( zip );
  1641. while( result == UNZ_OK ) {
  1642. numFiles++;
  1643. unz_file_info curFileInfo;
  1644. char fileName[MAX_OSPATH];
  1645. unzGetCurrentFileInfo( zip, &curFileInfo, fileName, MAX_OSPATH, NULL, 0, NULL, 0 );
  1646. idLib::PrintfIf( zip_verbosity.GetBool(), "%d: %s, size: %d \\ %d\n", numFiles, fileName, curFileInfo.compressed_size, curFileInfo.uncompressed_size );
  1647. // create a buffer big enough to hold the entire uncompressed file
  1648. void * buff = Mem_Alloc( curFileInfo.uncompressed_size, TAG_TEMP );
  1649. result = unzOpenCurrentFile( zip );
  1650. if ( result == UNZ_OK ) {
  1651. result = unzReadCurrentFile( zip, buff, curFileInfo.uncompressed_size );
  1652. unzCloseCurrentFile( zip );
  1653. }
  1654. // create the new memory file
  1655. idFile_Memory * outFile = new idFile_Memory( fileName );
  1656. outFile->SetReadOnlyData( (const char *)buff, curFileInfo.uncompressed_size );
  1657. destFiles.Append( outFile );
  1658. result = unzGoToNextFile( zip );
  1659. }
  1660. // close it so we can delete the zip file and create a new one
  1661. unzClose( zip );
  1662. // delete the temp zipfile
  1663. fileSystem->RemoveFile( ospath );
  1664. }
  1665. #endif
  1666. return ret;
  1667. }
  1668. CONSOLE_COMMAND( testZipBuilderExtractFiles, "test routine for memory zip file extraction", 0 ) {
  1669. #if 0
  1670. idList< idFile_Memory * > list;
  1671. idFile_Memory * zipfile;
  1672. const char * testString = "test";
  1673. int numFiles = 2;
  1674. bool overallSuccess = true;
  1675. bool success = true;
  1676. if ( args.Argc() > 2 ) {
  1677. idLib::Printf( "usage: testZipBuilderExtractFiles [numFiles]\n" );
  1678. return;
  1679. }
  1680. for ( int arg = 1; arg < args.Argc(); arg++ ) {
  1681. numFiles = atoi( args.Argv( arg ) );
  1682. }
  1683. // create a temp.zip file with string files
  1684. {
  1685. // allocate all the test files
  1686. for ( int i = 0; i < numFiles; i++ ) {
  1687. idFile_Memory * file = new idFile_Memory( va( "%s%d.txt", testString, i + 1 ) );
  1688. file->MakeWritable();
  1689. idStr str = va( "%s%d", testString, i + 1 );
  1690. file->WriteString( str );
  1691. list.Append( file );
  1692. }
  1693. // combine the files into a single memory file
  1694. idZipBuilder zip;
  1695. zipfile = zip.CombineFiles( list );
  1696. success = ( zipfile != NULL );
  1697. overallSuccess &= success;
  1698. idLib::Printf( "Zip file created: %s\n", success ? "^2PASS" : "^1FAIL" );
  1699. // destroy all the test files
  1700. list.DeleteContents();
  1701. }
  1702. // unzip the file into separate memory files
  1703. if ( overallSuccess ) {
  1704. // extract all the test files using the single zip file from above
  1705. idZipBuilder zip;
  1706. if ( !zip.ExtractFiles( zipfile, list ) ) {
  1707. idLib::Error( "Could not extract files." );
  1708. }
  1709. success = ( list.Num() == numFiles );
  1710. overallSuccess &= success;
  1711. idLib::Printf( "Number of files: %s\n", success ? "^2PASS" : "^1FAIL" );
  1712. for ( int i = 0; i < list.Num(); i++ ) {
  1713. idStr str;
  1714. idFile_Memory * file = list[i];
  1715. file->MakeReadOnly();
  1716. file->ReadString( str );
  1717. idStr filename = va( "%s%d.txt", testString, i + 1 );
  1718. idStr contents = va( "%s%d", testString, i + 1 );
  1719. // test the filename
  1720. bool nameSuccess = ( file->GetName() == filename );
  1721. overallSuccess &= nameSuccess;
  1722. // test the string
  1723. bool contentSuccess = ( str == contents );
  1724. overallSuccess &= contentSuccess;
  1725. idLib::Printf( "Extraction of file, %s: %s^0, contents check: %s\n", filename.c_str(), nameSuccess ? "^2PASS" : "^1FAIL", contentSuccess ? "^2PASS" : "^1FAIL" );
  1726. }
  1727. list.DeleteContents();
  1728. }
  1729. if ( zipfile != NULL ) {
  1730. delete zipfile;
  1731. }
  1732. idLib::Printf( "[%s] overall tests: %s\n", __FUNCTION__, overallSuccess ? "^2PASS" : "^1FAIL" );
  1733. #endif
  1734. }