00001 #ifndef __ZIP_ABSTRACTION_CPP__
00002 #define __ZIP_ABSTRACTION_CPP__
00003
00004 #define ZLIB_WINAPI
00005
00006 #include <system/zip_abstraction.h>
00007 #include <system/zlib/zip.h>
00008 #include <system/zlib/zlib.h>
00009 #include <system/zlib/unzip.h>
00010 #include <system/zlib/iowin32.h>
00011 #include <utilities/directory_utilities.h>
00012 #include <utilities/file_utilities.h>
00013 #include <utilities/string_utilities.h>
00014
00015 #if defined( WIN32_PLATFORM )
00016 #pragma comment( lib , "zlibstat.lib" )
00017 #endif
00018
00019 #if defined( WIN32_PLATFORM ) || defined( MINGW_PLATFORM )
00020 #undef max
00021 #endif
00022
00023 #include <limits>
00024
00025 namespace nitro
00026 {
00027 ZIPAbstraction::ZIPAbstraction( void ) : File( 0 )
00028 {
00029 try
00030 {
00031 }
00032 catch( nitro::exception e )
00033 {
00034 throw( nitro::exception( std::string( "ZIPAbstraction::CloseZIP( void )::" ) + e.what() , e.code() ) );
00035 }
00036 catch( ... )
00037 {
00038 throw( nitro::exception( std::string( "ZIPAbstraction::CloseZIP( void )::An error occured while unzipping file" ) , 1 ) );
00039 }
00040 }
00041
00042
00043 ZIPAbstraction::ZIPAbstraction( const std::string & FilePath ) : File( 0 )
00044 {
00045 try
00046 {
00047 Close();
00048
00049 Open( FilePath );
00050 }
00051 catch( nitro::exception e )
00052 {
00053 throw( nitro::exception( std::string( "ZIPAbstraction::ZIPAbstraction( const std::string & FilePath /* = NULL */ )::" ) + e.what() , e.code() ) );
00054 }
00055 catch( ... )
00056 {
00057 throw( nitro::exception( std::string( "ZIPAbstraction::ZIPAbstraction( const std::string & FilePath /* = NULL */ )::An error occured while unzipping file" ) , 1 ) );
00058 }
00059 }
00060
00061 void ZIPAbstraction::Open( const std::string & FilePath )
00062 {
00063 try
00064 {
00065 Close();
00066
00067 if( FilePath == "" || FilePath.size() == 0 )
00068 {
00069 throw( nitro::exception( std::string( "Invalid file path" ) , 1 ) );
00070 }
00071
00072 if( nitro::File::FileExists( FilePath ) == false )
00073 {
00074 if( ( File = zipOpen( FilePath.c_str() , 0 ) ) == NULL )
00075 {
00076 throw( nitro::exception( std::string( "File " ) + FilePath + " was not opened" , 1 ) );
00077 }
00078 }
00079 else
00080 {
00081 if( ( File = zipOpen( FilePath.c_str() , 1 ) ) == NULL )
00082 {
00083 throw( nitro::exception( std::string( "File " ) + FilePath + " was not opened" , 1 ) );
00084 }
00085 }
00086 }
00087 catch( nitro::exception e )
00088 {
00089 throw( nitro::exception( std::string( "ZIPAbstraction::Open( const std::string & FilePath )::" ) + e.what() , e.code() ) );
00090 }
00091 catch( ... )
00092 {
00093 throw( nitro::exception( std::string( "ZIPAbstraction::Open( const std::string & FilePath )::An error occured while unzipping file" ) , 1 ) );
00094 }
00095 }
00096
00097 void ZIPAbstraction::AddFile( const std::string & FilePath , const nitro::BinaryData & LoadedFile , const std::string & RelFolderPath )
00098 {
00099 try
00100 {
00101
00102 zip_fileinfo zfi;
00103
00104 zfi.internal_fa = 0;
00105 zfi.external_fa = 0;
00106
00107 tm LastModifiedDate = nitro::File::GetLastModified( FilePath );
00108
00109 zfi.dosDate = 0;
00110 zfi.tmz_date.tm_year = LastModifiedDate.tm_year + 1900;
00111 zfi.tmz_date.tm_mon = LastModifiedDate.tm_mon;
00112 zfi.tmz_date.tm_mday = LastModifiedDate.tm_mday;
00113 zfi.tmz_date.tm_hour = LastModifiedDate.tm_hour;
00114 zfi.tmz_date.tm_min = LastModifiedDate.tm_min;
00115 zfi.tmz_date.tm_sec = LastModifiedDate.tm_sec;
00116
00117
00118 std::string FileName;
00119 if( RelFolderPath == "" )
00120 {
00121 FileName = nitro::FSPath::ExtractFileName( std::string( FilePath ) );
00122 }
00123 else
00124 {
00125 FileName = nitro::FSPath::AddEndSlash( std::string( RelFolderPath ) ) + nitro::FSPath::ExtractFileName( std::string( FilePath ) );
00126 }
00127
00128
00129 if( zipOpenNewFileInZip( File , FileName.c_str() , & zfi ,
00130 NULL , 0 , NULL , 0 ,
00131 NULL , Z_DEFLATED , Z_DEFAULT_COMPRESSION ) != ZIP_OK )
00132 {
00133 throw( nitro::exception( std::string( "An error occured while opening zip file " ) + FileName , 1 ) );
00134 }
00135
00136 if( zipWriteInFileInZip( File , LoadedFile.GetBuffer() , ( unsigned int )LoadedFile.GetBufferLength() ) != ZIP_OK )
00137 {
00138 throw( nitro::exception( std::string( "An error occured while saving data " ) + FilePath + " to zip file" , 1 ) );
00139 }
00140
00141 zipCloseFileInZip( File );
00142 }
00143 catch( nitro::exception e )
00144 {
00145 throw( nitro::exception( std::string( "ZIPAbstraction::AddFile( const std::string & FilePath , const nitro::BinaryData & LoadedFile , const std::string & RelFolderPath /* = "" */ )::" ) + e.what() , e.code() ) );
00146 }
00147 catch( ... )
00148 {
00149 throw( nitro::exception( std::string( "ZIPAbstraction::AddFile( const std::string & FilePath , const nitro::BinaryData & LoadedFile , const std::string & RelFolderPath /* = "" */ )::An error occured while unzipping file" ) , 1 ) );
00150 }
00151 }
00152
00153 void ZIPAbstraction::AddFile( const std::string & FilePath , const std::string & RelFolderPath )
00154 {
00155 try
00156 {
00157 nitro::BinaryData LoadedFile;
00158
00159 nitro::File::LoadBinDataFromFile( LoadedFile , FilePath );
00160
00161 AddFile( FilePath , LoadedFile , RelFolderPath );
00162 }
00163 catch( nitro::exception e )
00164 {
00165 throw( nitro::exception( std::string( "ZIPAbstraction::AddFile( const std::string & FilePath , const std::string & RelFolderPath /* = NULL */ )::" ) + e.what() , e.code() ) );
00166 }
00167 catch( ... )
00168 {
00169 throw( nitro::exception( std::string( "ZIPAbstraction::AddFile( const std::string & FilePath , const std::string & RelFolderPath /* = NULL */ )::An error occured while unzipping file" ) , 1 ) );
00170 }
00171 }
00172
00173 void ZIPAbstraction::Close( void )
00174 {
00175 try
00176 {
00177 if( File ? zipClose( File , NULL ) : ZIP_OK != ZIP_OK )
00178 {
00179 throw( nitro::exception( std::string( "An error occured while closing zip file" ) , 1 ) );
00180 }
00181
00182 File = NULL;
00183 }
00184 catch( nitro::exception e )
00185 {
00186 throw( nitro::exception( std::string( "ZIPAbstraction::Close( void )::" ) + e.what() , e.code() ) );
00187 }
00188 catch( ... )
00189 {
00190 throw( nitro::exception( std::string( "ZIPAbstraction::Close( void )::An error occured while unzipping file" ) , 1 ) );
00191 }
00192 }
00193
00194 ZIPAbstraction::~ZIPAbstraction()
00195 {
00196 try
00197 {
00198 Close();
00199 }
00200 catch( nitro::exception e )
00201 {
00202 }
00203 catch( ... )
00204 {
00205 }
00206 }
00207
00208 UnZIPAbstraction::UnZIPAbstraction( void ) : File( 0 )
00209 {
00210 try
00211 {
00212 CurrentCursorPosition = std::numeric_limits< std::size_t >::max();
00213 }
00214 catch( nitro::exception e )
00215 {
00216 throw( nitro::exception( std::string( "UnZIPAbstraction::CloseZIP( void )::" ) + e.what() , e.code() ) );
00217 }
00218 catch( ... )
00219 {
00220 throw( nitro::exception( std::string( "UnZIPAbstraction::CloseZIP( void )::An error occured while unzipping file" ) , 1 ) );
00221 }
00222 }
00223
00224
00225 UnZIPAbstraction::UnZIPAbstraction( const std::string & FilePath ) : File( 0 )
00226 {
00227 try
00228 {
00229 Close();
00230
00231 Open( FilePath );
00232 }
00233 catch( nitro::exception e )
00234 {
00235 throw( nitro::exception( std::string( "UnZIPAbstraction::UnZIPAbstraction( const std::string & FilePath )::" ) + e.what() , e.code() ) );
00236 }
00237 catch( ... )
00238 {
00239 throw( nitro::exception( std::string( "UnZIPAbstraction::UnZIPAbstraction( const std::string & FilePath )::An error occured while unzipping file" ) , 1 ) );
00240 }
00241 }
00242
00243 void UnZIPAbstraction::Open( const std::string & FilePath )
00244 {
00245 try
00246 {
00247 Close();
00248
00249 if( FilePath == "" || FilePath.size() == 0 )
00250 {
00251 throw( nitro::exception( std::string( "Invalid file path" ) , 1 ) );
00252 }
00253
00254 if( nitro::File::FileExists( FilePath ) != false )
00255 {
00256 if( ( File = unzOpen( FilePath.c_str() ) ) == NULL )
00257 {
00258 throw( nitro::exception( std::string( "File " ) + FilePath + " was not opened" , 1 ) );
00259 }
00260 }
00261 else
00262 {
00263 throw( nitro::exception( std::string( "File " ) + FilePath + " was not found" , 1 ) );
00264 }
00265
00266 CurrentCursorPosition = std::numeric_limits< std::size_t >::max();
00267 }
00268 catch( nitro::exception e )
00269 {
00270 throw( nitro::exception( std::string( "UnZIPAbstraction::Open( const std::string & FilePath )::" ) + e.what() , e.code() ) );
00271 }
00272 catch( ... )
00273 {
00274 throw( nitro::exception( std::string( "UnZIPAbstraction::Open( const std::string & FilePath )::An error occured while unzipping file" ) , 1 ) );
00275 }
00276 }
00277
00278 void UnZIPAbstraction::GotoFile( const std::size_t FileCursor )
00279 {
00280 try
00281 {
00282 if( !File )
00283 {
00284 throw( nitro::exception( std::string( "Archive was not opened" ) , 1 ) );
00285 }
00286
00287 if( FileCursor >= GetCountOfFiles() )
00288 {
00289 throw( nitro::exception( std::string( "Illegal file cursor" ) , 1 ) );
00290 }
00291
00292 if( FileCursor < CurrentCursorPosition )
00293 {
00294 GotoFirstFile();
00295
00296 std::size_t TmpFileCursor( FileCursor );
00297
00298 while( TmpFileCursor-- )
00299 {
00300 GotoNextFile();
00301 }
00302 }
00303 else
00304 {
00305 for( ; FileCursor - CurrentCursorPosition ; )
00306 {
00307 GotoNextFile();
00308 }
00309 }
00310
00311 CurrentCursorPosition = FileCursor;
00312 }
00313 catch( nitro::exception e )
00314 {
00315 throw( nitro::exception( std::string( "UnZIPAbstraction::GotoFile( const std::size_t FileCursor )::" ) + e.what() , e.code() ) );
00316 }
00317 catch( ... )
00318 {
00319 throw( nitro::exception( std::string( "UnZIPAbstraction::GotoFile( const std::size_t FileCursor )::An error occured while unzipping file" ) , 1 ) );
00320 }
00321 }
00322
00323 void UnZIPAbstraction::GotoFirstFile( void )
00324 {
00325 try
00326 {
00327 if( !File )
00328 {
00329 throw( nitro::exception( std::string ( "Archive was not opened" ) , 1 ) );
00330 }
00331
00332 if( unzGoToFirstFile( File ) != UNZ_OK )
00333 {
00334 throw( nitro::exception( std::string( "An error occured while moving cursor to the first file" ) , 1 ) );
00335 }
00336
00337 CurrentCursorPosition = std::numeric_limits< std::size_t >::max();
00338 }
00339 catch( nitro::exception e )
00340 {
00341 throw( nitro::exception( std::string( "UnZIPAbstraction::GotoFirstFile( void )::" ) + e.what() , e.code() ) );
00342 }
00343 catch( ... )
00344 {
00345 throw( nitro::exception( std::string( "UnZIPAbstraction::GotoFirstFile( void )::An error occured while unzipping file" ) , 1 ) );
00346 }
00347 }
00348
00349 void UnZIPAbstraction::GotoNextFile( void )
00350 {
00351 try
00352 {
00353 if( !File )
00354 {
00355 throw( nitro::exception( std::string( "Archive was not opened" ) , 1 ) );
00356 }
00357
00358 if( unzGoToNextFile( File ) != UNZ_OK )
00359 {
00360 throw( nitro::exception( std::string( "An error occured while moving cursor to the first file" ) , 1 ) );
00361 }
00362
00363 CurrentCursorPosition++;
00364 }
00365 catch( nitro::exception e )
00366 {
00367 throw( nitro::exception( std::string( "UnZIPAbstraction::GotoNextFile( void )::" ) + e.what() , e.code() ) );
00368 }
00369 catch( ... )
00370 {
00371 throw( nitro::exception( std::string( "UnZIPAbstraction::GotoNextFile( void )::An error occured while unzipping file" ) , 1 ) );
00372 }
00373 }
00374
00375 std::size_t UnZIPAbstraction::GetCountOfFiles( void ) const
00376 {
00377 try
00378 {
00379 if( !File )
00380 {
00381 throw( nitro::exception( std::string( "Archive was not opened" ) , 1 ) );
00382 }
00383
00384 unz_global_info info;
00385
00386 if( unzGetGlobalInfo( File , & info ) != UNZ_OK )
00387 {
00388 throw( nitro::exception( std::string( "An error occured while getting global info" ) , 1 ) );
00389 }
00390
00391 return( ( int )info.number_entry );
00392 }
00393 catch( nitro::exception e )
00394 {
00395 throw( nitro::exception( std::string( "UnZIPAbstraction::GetCountOfFiles( void )::" ) + e.what() , e.code() ) );
00396 }
00397 catch( ... )
00398 {
00399 throw( nitro::exception( std::string( "UnZIPAbstraction::GetCountOfFiles( void )::An error occured while unzipping file" ) , 1 ) );
00400 }
00401 }
00402
00403 void UnZIPAbstraction::UnZIPFile( const std::size_t FileCursor , const std::string & Folder, bool IgnoreFilePath )
00404 {
00405 try
00406 {
00407 if( !File )
00408 {
00409 throw( nitro::exception( std::string( "Archive was not opened" ) , 1 ) );
00410 }
00411
00412 GotoFile( FileCursor );
00413
00414 UnZIPFile( Folder , IgnoreFilePath );
00415 }
00416 catch( nitro::exception e )
00417 {
00418 throw( nitro::exception( std::string( "UnZIPAbstraction::UnZIPFile( const std::size_t FileCursor , const std::string & Folder, bool IgnoreFilePath )::" ) + e.what() , e.code() ) );
00419 }
00420 catch( ... )
00421 {
00422 throw( nitro::exception( std::string( "UnZIPAbstraction::UnZIPFile( const std::size_t FileCursor , const std::string & Folder, bool IgnoreFilePath )::An error occured while unzipping file" ) , 1 ) );
00423 }
00424 }
00425
00426 void UnZIPAbstraction::UnZIPFile( const std::string & Folder , bool IgnoreFilePath )
00427 {
00428 try
00429 {
00430 if( !File )
00431 {
00432 throw( nitro::exception( std::string( "Archive was not opened" ) , 1 ) );
00433 }
00434
00435 nitro::Directory::ForceCreateDirectory( Folder );
00436
00437 int Ret = UNZ_OK;
00438 char Buffer[ 1024 ];
00439 char FileName[ 1024 ];
00440 nitro::File UncomressedFile;
00441
00442 if( unzGetCurrentFileInfo( File , NULL , FileName , 1024 , NULL , 0 , NULL , 0 ) != UNZ_OK )
00443 {
00444 throw( nitro::exception( std::string( "An error occured while reading info about the extracting file" ) , 1 ) );
00445 }
00446
00447 std::string FilePath( "" );
00448 if( IgnoreFilePath )
00449 {
00450 FilePath = nitro::FSPath::AddEndSlash( std::string( Folder ) ) + nitro::FSPath::ExtractFileName( std::string( FileName ) );
00451 }
00452 else
00453 {
00454 FilePath = nitro::FSPath::AddEndSlash( std::string( Folder ) ) + std::string( FileName );
00455 }
00456
00457 File::ForceCreateFile( FilePath );
00458 UncomressedFile.Open( FilePath , nitro::FA_FILE_BINARY | nitro::FA_FILE_WRITE | nitro::FA_FILE_TRUNCATE );
00459
00460 if( unzOpenCurrentFile( File ) != UNZ_OK )
00461 {
00462 throw( nitro::exception( std::string( "An error occured while opening zip file handle" ) , 1 ) );
00463 }
00464
00465 do
00466 {
00467 Ret = unzReadCurrentFile( File , Buffer , 1024 );
00468
00469 if( Ret > 0 )
00470 {
00471 UncomressedFile.Write( Buffer , 1024 );
00472 }
00473 }
00474 while( Ret > 0 );
00475
00476 if( unzCloseCurrentFile( File ) != UNZ_OK )
00477 {
00478 throw( nitro::exception( std::string( "An error occured while closing zip file handle" ) , 1 ) );
00479 }
00480 }
00481 catch( nitro::exception e )
00482 {
00483 throw( nitro::exception( std::string( "UnZIPAbstraction::UnZIPFile( const std::string & Folder , bool IgnoreFilePath )::" ) + e.what() , e.code() ) );
00484 }
00485 catch( ... )
00486 {
00487 throw( nitro::exception( std::string( "UnZIPAbstraction::UnZIPFile( const std::string & Folder , bool IgnoreFilePath )::An error occured while unzipping file" ) , 1 ) );
00488 }
00489 }
00490
00491 void UnZIPAbstraction::Close( void )
00492 {
00493 try
00494 {
00495 if( File ? unzClose( File ) : ZIP_OK != ZIP_OK )
00496 {
00497 throw( nitro::exception( std::string( "An error occured while closing zip file" ) , 1 ) );
00498 }
00499
00500 File = NULL;
00501 }
00502 catch( nitro::exception e )
00503 {
00504 throw( nitro::exception( std::string( "UnZIPAbstraction::Close( void )::" ) + e.what() , e.code() ) );
00505 }
00506 catch( ... )
00507 {
00508 throw( nitro::exception( std::string( "UnZIPAbstraction::Close( void )::An error occured while unzipping file" ) , 1 ) );
00509 }
00510 }
00511
00512 UnZIPAbstraction::~UnZIPAbstraction()
00513 {
00514 try
00515 {
00516 Close();
00517 }
00518 catch( nitro::exception e )
00519 {
00520 }
00521 catch( ... )
00522 {
00523 }
00524 }
00525
00526
00527
00528
00529 BEGIN_TESTING_SECTION()
00530
00531 ENABLE_CLASS_TESTING( ZIPAbstraction )
00532 ENABLE_CLASS_TESTING( UnZIPAbstraction )
00533
00534 #ifdef ENABLE_AUTOTESTING
00535 NITRO_EXPORTING void tstOpenOpen( const char * ObjectName , const char * FilePath )
00536 {
00537 ZIPAbstractionGetter( ObjectName ).Open( FilePath );
00538 }
00539 NITRO_EXPORTING void tstCloseFile( const char * ObjectName , const char * FilePath )
00540 {
00541 ZIPAbstractionGetter( ObjectName ).Close();
00542 }
00543 NITRO_EXPORTING void tstuOpenFile( const char * ObjectName , const char * FilePath )
00544 {
00545 UnZIPAbstractionGetter( ObjectName ).Open( FilePath );
00546 }
00547 NITRO_EXPORTING void tstuCloseFile( const char * ObjectName , const char * FilePath )
00548 {
00549 UnZIPAbstractionGetter( ObjectName ).Close();
00550 }
00551 #endif
00552 END_TESTING_SECTION()
00553 }
00554
00555 #endif