bool UnzipBase::__extract(const mbs& filename,vector<char>& buffer,bool case_sens,bool raw,int& method,int& level) { if(!_handle) return false; if(!filename.length()) return false; __int64 index; if(case_sens) { hash_map<mbs,__int64>::iterator iter=_indices.find(filename); if(iter==_indices.end()) return false; index=iter->second; } else { mbs filename2=TOLOWER(filename); hash_map<mbs,__int64>::iterator iter=_indices_ci.find(filename2); if(iter==_indices_ci.end()) return false; index=iter->second; } unz_file_info file_info; if(unzGoToFilePos(_handle,(unz_file_pos*)&index)!=UNZ_OK) return false; if(unzGetCurrentFileInfo(_handle,&file_info,0,0,0,0,0,0)!=UNZ_OK) return false; if(unzOpenCurrentFile2(_handle,&method,&level,raw?1:0)!=UNZ_OK) return false; buffer.resize(file_info.uncompressed_size); int ret; int decomp = 0; if(buffer.size()) while(decomp != file_info.uncompressed_size) { ret = unzReadCurrentFile(_handle,&buffer[decomp], (unsigned int)buffer.size() - decomp); if(ret > 0) decomp += ret; else if(ret <= 0) break; } unzCloseCurrentFile(_handle); return (decomp==file_info.uncompressed_size); }
/////////////////////////////////////////////////////////////// // // CResourceChecker::ReplaceFilesInZIP // // Based on example at http://www.winimage.com/zLibDll/minizip.html // by Ivan A. Krestinin // /////////////////////////////////////////////////////////////// int CResourceChecker::ReplaceFilesInZIP( const string& strOrigZip, const string& strTempZip, const vector < string >& pathInArchiveList, const vector < string >& m_upgradedFullPathList ) { // open source and destination file zlib_filefunc_def ffunc; #ifdef WIN32 fill_win32_filefunc(&ffunc); #else fill_fopen_filefunc(&ffunc); #endif zipFile szip = unzOpen2(strOrigZip.c_str(), &ffunc); if (szip==NULL) { /*free(tmp_name);*/ return 0; } zipFile dzip = zipOpen2(strTempZip.c_str(), APPEND_STATUS_CREATE, NULL, &ffunc); if (dzip==NULL) { unzClose(szip); /*free(tmp_name);*/ return 0; } // get global commentary unz_global_info glob_info; if (unzGetGlobalInfo(szip, &glob_info) != UNZ_OK) { zipClose(dzip, NULL); unzClose(szip); /*free(tmp_name);*/ return 0; } char* glob_comment = NULL; if (glob_info.size_comment > 0) { glob_comment = (char*)malloc(glob_info.size_comment+1); if ((glob_comment==NULL)&&(glob_info.size_comment!=0)) { zipClose(dzip, NULL); unzClose(szip); /*free(tmp_name);*/ return 0; } if ((unsigned int)unzGetGlobalComment(szip, glob_comment, glob_info.size_comment+1) != glob_info.size_comment) { zipClose(dzip, NULL); unzClose(szip); free(glob_comment); /*free(tmp_name);*/ return 0; } } // copying files int n_files = 0; int rv = unzGoToFirstFile(szip); while (rv == UNZ_OK) { // get zipped file info unz_file_info unzfi; char dos_fn[MAX_PATH]; if (unzGetCurrentFileInfo(szip, &unzfi, dos_fn, MAX_PATH, NULL, 0, NULL, 0) != UNZ_OK) break; char fn[MAX_PATH]; #ifdef WIN32 OemToChar(dos_fn, fn); #endif // See if file should be replaced string fullPathReplacement; for ( unsigned long i = 0 ; i < pathInArchiveList.size () ; i++ ) if ( stricmp ( fn, pathInArchiveList[i].c_str () ) == 0 ) fullPathReplacement = m_upgradedFullPathList[i]; // Replace file in zip if ( fullPathReplacement.length () ) { void* buf = NULL; unsigned long ulLength = 0; // Get new file into a buffer if ( FILE* pFile = File::Fopen ( fullPathReplacement.c_str (), "rb" ) ) { // Get the file size, fseek( pFile, 0, SEEK_END ); ulLength = ftell( pFile ); fseek( pFile, 0, SEEK_SET ); // Load file into a buffer buf = malloc( ulLength ); if ( fread ( buf, 1, ulLength, pFile ) != ulLength ) { free( buf ); buf = NULL; } // Clean up fclose ( pFile ); } if( !buf ) break; // open destination file zip_fileinfo zfi; memcpy (&zfi.tmz_date, &unzfi.tmu_date, sizeof(tm_unz)); zfi.dosDate = unzfi.dosDate; zfi.internal_fa = unzfi.internal_fa; zfi.external_fa = unzfi.external_fa; char* extrafield = NULL; char* commentary = NULL; int size_local_extra = 0; void* local_extra = NULL; int unzfi_size_file_extra = 0; int method = Z_DEFLATED; int level = Z_DEFAULT_COMPRESSION; if (zipOpenNewFileInZip(dzip, dos_fn, &zfi, local_extra, size_local_extra, extrafield, unzfi_size_file_extra, commentary, method, level )!=UNZ_OK) {free(extrafield); free(commentary); free(local_extra); free(buf); break;} // write file if (zipWriteInFileInZip(dzip, buf, ulLength)!=UNZ_OK) {free(extrafield); free(commentary); free(local_extra); free(buf); break;} if (zipCloseFileInZip(dzip/*, unzfi.uncompressed_size, unzfi.crc*/)!=UNZ_OK) {free(extrafield); free(commentary); free(local_extra); free(buf); break;} free( buf ); } // Copy file in zip if ( !fullPathReplacement.length () ) { char* extrafield = (char*)malloc(unzfi.size_file_extra); if ((extrafield==NULL)&&(unzfi.size_file_extra!=0)) break; char* commentary = (char*)malloc(unzfi.size_file_comment); if ((commentary==NULL)&&(unzfi.size_file_comment!=0)) {free(extrafield); break;} if (unzGetCurrentFileInfo(szip, &unzfi, dos_fn, MAX_PATH, extrafield, unzfi.size_file_extra, commentary, unzfi.size_file_comment) != UNZ_OK) {free(extrafield); free(commentary); break;} // open file for RAW reading int method; int level; if (unzOpenCurrentFile2(szip, &method, &level, 1)!=UNZ_OK) {free(extrafield); free(commentary); break;} int size_local_extra = unzGetLocalExtrafield(szip, NULL, 0); if (size_local_extra<0) {free(extrafield); free(commentary); break;} void* local_extra = malloc(size_local_extra); if ((local_extra==NULL)&&(size_local_extra!=0)) {free(extrafield); free(commentary); break;} if (unzGetLocalExtrafield(szip, local_extra, size_local_extra)<0) {free(extrafield); free(commentary); free(local_extra); break;} // this malloc may fail if file very large void* buf = malloc(unzfi.compressed_size); if ((buf==NULL)&&(unzfi.compressed_size!=0)) {free(extrafield); free(commentary); free(local_extra); break;} // read file int sz = unzReadCurrentFile(szip, buf, unzfi.compressed_size); if ((unsigned int)sz != unzfi.compressed_size) {free(extrafield); free(commentary); free(local_extra); free(buf); break;} // open destination file zip_fileinfo zfi; memcpy (&zfi.tmz_date, &unzfi.tmu_date, sizeof(tm_unz)); zfi.dosDate = unzfi.dosDate; zfi.internal_fa = unzfi.internal_fa; zfi.external_fa = unzfi.external_fa; if (zipOpenNewFileInZip2(dzip, dos_fn, &zfi, local_extra, size_local_extra, extrafield, unzfi.size_file_extra, commentary, method, level, 1)!=UNZ_OK) {free(extrafield); free(commentary); free(local_extra); free(buf); break;} // write file if (zipWriteInFileInZip(dzip, buf, unzfi.compressed_size)!=UNZ_OK) {free(extrafield); free(commentary); free(local_extra); free(buf); break;} if (zipCloseFileInZipRaw(dzip, unzfi.uncompressed_size, unzfi.crc)!=UNZ_OK) {free(extrafield); free(commentary); free(local_extra); free(buf); break;} if (unzCloseCurrentFile(szip)==UNZ_CRCERROR) {free(extrafield); free(commentary); free(local_extra); free(buf); break;} free(commentary); free(buf); free(extrafield); free(local_extra); n_files ++; } rv = unzGoToNextFile(szip); } zipClose(dzip, glob_comment); unzClose(szip); free(glob_comment); return rv==UNZ_END_OF_LIST_OF_FILE; }
bool MinizipUtils::copy_file_raw(unzFile uf, zipFile zf, const std::string &name, void (*cb)(uint64_t bytes, void *), void *userData) { unz_file_info64 ufi; if (!get_info(uf, &ufi, nullptr)) { return false; } bool zip64 = ufi.uncompressed_size >= ((1ull << 32) - 1); zip_fileinfo zfi; memset(&zfi, 0, sizeof(zfi)); zfi.dos_date = ufi.dos_date; zfi.internal_fa = ufi.internal_fa; zfi.external_fa = ufi.external_fa; int method; int level; // Open raw file in input zip int ret = unzOpenCurrentFile2( uf, // file &method, // method &level, // level 1 // raw ); if (ret != UNZ_OK) { LOGE("miniunz: Failed to open inner file: %s", unz_error_string(ret).c_str()); return false; } // Open raw file in output zip ret = zipOpenNewFileInZip2_64( zf, // file name.c_str(), // filename &zfi, // zip_fileinfo nullptr, // extrafield_local 0, // size_extrafield_local nullptr, // extrafield_global 0, // size_extrafield_global nullptr, // comment static_cast<uint16_t>(method), // method level, // level 1, // raw zip64 // zip64 ); if (ret != ZIP_OK) { LOGE("minizip: Failed to open inner file: %s", zip_error_string(ret).c_str()); unzCloseCurrentFile(uf); return false; } uint64_t bytes = 0; // minizip no longer supports buffers larger than UINT16_MAX char buf[UINT16_MAX]; int bytes_read; double ratio; while ((bytes_read = unzReadCurrentFile(uf, buf, sizeof(buf))) > 0) { bytes += static_cast<uint64_t>(bytes_read); if (cb) { // Scale this to the uncompressed size for the purposes of a // progress bar ratio = static_cast<double>(bytes) / static_cast<double>(ufi.compressed_size); cb(static_cast<uint64_t>( ratio * static_cast<double>(ufi.uncompressed_size)), userData); } ret = zipWriteInFileInZip(zf, buf, static_cast<uint32_t>(bytes_read)); if (ret != ZIP_OK) { LOGE("minizip: Failed to write data to inner file: %s", zip_error_string(ret).c_str()); unzCloseCurrentFile(uf); zipCloseFileInZip(zf); return false; } } if (bytes_read != 0) { LOGE("miniunz: Finished before reaching inner file's EOF: %s", unz_error_string(bytes_read).c_str()); } bool close_success = true; ret = unzCloseCurrentFile(uf); if (ret != UNZ_OK) { LOGE("miniunz: Failed to close inner file: %s", unz_error_string(ret).c_str()); close_success = false; } ret = zipCloseFileInZipRaw64(zf, ufi.uncompressed_size, ufi.crc); if (ret != ZIP_OK) { LOGE("minizip: Failed to close inner file: %s", zip_error_string(ret).c_str()); close_success = false; } return bytes_read == 0 && close_success; }
bool FileUtils::mzCopyFileRaw(unzFile uf, zipFile zf, const std::string &name, void (*cb)(uint64_t bytes, void *), void *userData) { unz_file_info64 ufi; if (!mzGetInfo(uf, &ufi, nullptr)) { return false; } bool zip64 = ufi.uncompressed_size >= ((1ull << 32) - 1); zip_fileinfo zfi; memset(&zfi, 0, sizeof(zfi)); zfi.dosDate = ufi.dosDate; zfi.tmz_date.tm_sec = ufi.tmu_date.tm_sec; zfi.tmz_date.tm_min = ufi.tmu_date.tm_min; zfi.tmz_date.tm_hour = ufi.tmu_date.tm_hour; zfi.tmz_date.tm_mday = ufi.tmu_date.tm_mday; zfi.tmz_date.tm_mon = ufi.tmu_date.tm_mon; zfi.tmz_date.tm_year = ufi.tmu_date.tm_year; zfi.internal_fa = ufi.internal_fa; zfi.external_fa = ufi.external_fa; int method; int level; // Open raw file in input zip int ret = unzOpenCurrentFile2( uf, // file &method, // method &level, // level 1 // raw ); if (ret != UNZ_OK) { return false; } // Open raw file in output zip ret = zipOpenNewFileInZip2_64( zf, // file name.c_str(), // filename &zfi, // zip_fileinfo nullptr, // extrafield_local 0, // size_extrafield_local nullptr, // extrafield_global 0, // size_extrafield_global nullptr, // comment method, // method level, // level 1, // raw zip64 // zip64 ); if (ret != ZIP_OK) { unzCloseCurrentFile(uf); return false; } uint64_t bytes = 0; // Exceeds Android's default stack size, unfortunately, so allocate // on the heap std::vector<unsigned char> buf(1024 * 1024); // 1MiB int bytes_read; double ratio; while ((bytes_read = unzReadCurrentFile(uf, buf.data(), buf.size())) > 0) { bytes += bytes_read; if (cb) { // Scale this to the uncompressed size for the purposes of a // progress bar ratio = (double) bytes / ufi.compressed_size; cb(ratio * ufi.uncompressed_size, userData); } ret = zipWriteInFileInZip(zf, buf.data(), bytes_read); if (ret != ZIP_OK) { unzCloseCurrentFile(uf); zipCloseFileInZip(zf); return false; } } unzCloseCurrentFile(uf); zipCloseFileInZipRaw64(zf, ufi.uncompressed_size, ufi.crc); return bytes_read == 0; }
static int hb_zipDeleteFile( const char * szZipFile, const char * szFileMask ) { char szTempFile[ HB_PATH_MAX ]; char szCurrFile[ HB_PATH_MAX ]; PHB_FNAME pFileName; HB_FHANDLE hFile; unzFile hUnzip; zipFile hZip; unz_global_info ugi; unz_file_info ufi; zip_fileinfo zfi; char * pszGlobalComment = NULL; char * pszFileComment = NULL; void * pExtraField = NULL; void * pLocalExtraField = NULL; int iFilesLeft = 0; int iFilesDel = 0; int iExtraFieldLen; int method; int level; int iResult; char * pszFree; /* open source file */ hUnzip = unzOpen( hb_fsNameConv( szZipFile, &pszFree ) ); if( pszFree ) hb_xfree( pszFree ); if( hUnzip == NULL ) return UNZ_ERRNO; pFileName = hb_fsFNameSplit( szZipFile ); hFile = hb_fsCreateTemp( pFileName->szPath, NULL, FC_NORMAL, szTempFile ); hZip = NULL; if( hFile != FS_ERROR ) { hb_fsClose( hFile ); hZip = zipOpen( szTempFile, APPEND_STATUS_CREATE ); } hb_xfree( pFileName ); if( hZip == NULL ) { unzClose( hUnzip ); return UNZ_ERRNO; } iResult = unzGetGlobalInfo( hUnzip, &ugi ); if( iResult == UNZ_OK ) { if( ugi.size_comment > 0 ) { pszGlobalComment = ( char * ) hb_xgrab( ugi.size_comment + 1 ); if( ( uLong ) unzGetGlobalComment( hUnzip, pszGlobalComment, ugi.size_comment ) != ugi.size_comment ) iResult = UNZ_ERRNO; pszGlobalComment[ ugi.size_comment ] = '\0'; } if( iResult == UNZ_OK ) iResult = unzGoToFirstFile( hUnzip ); } while( iResult == UNZ_OK ) { iResult = unzGetCurrentFileInfo( hUnzip, &ufi, szCurrFile, HB_PATH_MAX - 1, NULL, 0, NULL, 0 ); if( iResult != UNZ_OK ) break; if( hb_strMatchFile( szCurrFile, szFileMask ) ) iFilesDel++; else { if( ufi.size_file_extra ) pExtraField = ( char * ) hb_xgrab( ufi.size_file_extra ); if( ufi.size_file_comment ) pszFileComment = ( char * ) hb_xgrab( ufi.size_file_comment + 1 ); iResult = unzGetCurrentFileInfo( hUnzip, &ufi, NULL, 0, pExtraField, ufi.size_file_extra, pszFileComment, ufi.size_file_comment ); if( pszFileComment ) pszFileComment[ ufi.size_file_comment ] = '\0'; if( iResult != UNZ_OK ) break; iResult = unzOpenCurrentFile2( hUnzip, &method, &level, 1 ); if( iResult != UNZ_OK ) break; iExtraFieldLen = unzGetLocalExtrafield( hUnzip, NULL, 0 ); if( iExtraFieldLen < 0 ) { iResult = UNZ_ERRNO; break; } else if( iExtraFieldLen > 0 ) { pLocalExtraField = hb_xgrab( iExtraFieldLen ); if( unzGetLocalExtrafield( hUnzip, pLocalExtraField, iExtraFieldLen ) != iExtraFieldLen ) { iResult = UNZ_ERRNO; break; } } memset( &zfi, 0, sizeof( zfi ) ); memcpy( &zfi.tmz_date, &ufi.tmu_date, sizeof( tm_unz ) ); zfi.dosDate = ufi.dosDate; zfi.internal_fa = ufi.internal_fa; zfi.external_fa = ufi.external_fa; iResult = zipOpenNewFileInZip2( hZip, szCurrFile, &zfi, pLocalExtraField, iExtraFieldLen, pExtraField, ufi.size_file_extra, pszFileComment, method, level, 1 ); if( iResult != UNZ_OK ) break; if( ufi.compressed_size ) { void * buffer = hb_xgrab( HB_Z_IOBUF_SIZE ); uLong ulLeft = ufi.compressed_size; while( ulLeft > 0 ) { int iRead = HB_MIN( ulLeft, HB_Z_IOBUF_SIZE ); iResult = unzReadCurrentFile( hUnzip, ( voidp ) buffer, iRead ); if( iResult < 0 ) break; if( iResult != iRead ) { iResult = UNZ_ERRNO; break; } iResult = zipWriteInFileInZip( hZip, ( voidp ) buffer, iRead ); if( iResult != UNZ_OK ) break; ulLeft -= iRead; } hb_xfree( buffer ); if( iResult != UNZ_OK ) break; } iResult = zipCloseFileInZipRaw( hZip, ufi.uncompressed_size, ufi.crc ); if( iResult != UNZ_OK ) break; iResult = unzCloseCurrentFile( hUnzip ); if( iResult != UNZ_OK ) break; if( pExtraField ) { hb_xfree( pExtraField ); pExtraField = NULL; } if( pszFileComment ) { hb_xfree( pszFileComment ); pszFileComment = NULL; } if( pLocalExtraField ) { hb_xfree( pLocalExtraField ); pLocalExtraField = NULL; } iFilesLeft++; } iResult = unzGoToNextFile( hUnzip ); } if( pExtraField ) hb_xfree( pExtraField ); if( pszFileComment ) hb_xfree( pszFileComment ); if( pLocalExtraField ) hb_xfree( pLocalExtraField ); if( iFilesDel == 0 ) iResult = UNZ_ERRNO; else if( iResult == UNZ_END_OF_LIST_OF_FILE ) iResult = UNZ_OK; if( iResult != UNZ_OK ) zipClose( hZip, NULL ); else iResult = zipClose( hZip, pszGlobalComment ); unzClose( hUnzip ); if( pszGlobalComment ) hb_xfree( pszGlobalComment ); if( iResult != UNZ_OK ) hb_fsDelete( szTempFile ); else { hb_fsDelete( szZipFile ); if( iFilesLeft == 0 ) hb_fsDelete( szTempFile ); else if( ! hb_fsRename( szTempFile, szZipFile ) ) iResult = UNZ_ERRNO; } return iResult; }