/* Open a Zip file. path contain the full pathname (by example, on a Windows NT computer "c:\\test\\zlib114.zip" or on a Unix computer "zlib/zlib114.zip". If the zipfile cannot be opened (file doesn't exist or in not valid), the return value is NULL. Else, the return value is an unzFile Handle, usable with other function of this unzip package. */ unzFile ZEXPORT unzOpen2 ( const char *path, zlib_filefunc_def* pzlib_filefunc_def) { unz_s us; unz_s *s; uLong central_pos,uL; uLong number_disk; /* number of the current dist, used for spaning ZIP, unsupported, always 0*/ uLong number_disk_with_CD; /* number the the disk with central dir, used for spaning ZIP, unsupported, always 0*/ uLong number_entry_CD; /* total number of entries in the central dir (same than number_entry on nospan) */ int err=UNZ_OK; if (unz_copyright[0]!=' ') return NULL; if (pzlib_filefunc_def==NULL) fill_fopen_filefunc(&us.z_filefunc); else us.z_filefunc = *pzlib_filefunc_def; us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque, path, ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_EXISTING); if (us.filestream==NULL) return NULL; central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream); if (central_pos==0) err=UNZ_ERRNO; if (ZSEEK(us.z_filefunc, us.filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) err=UNZ_ERRNO; /* the signature, already checked */ if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) err=UNZ_ERRNO; /* number of this disk */ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) err=UNZ_ERRNO; /* number of the disk with the start of the central directory */ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) err=UNZ_ERRNO; /* total number of entries in the central dir on this disk */ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) err=UNZ_ERRNO; /* total number of entries in the central dir */ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK) err=UNZ_ERRNO; if ((number_entry_CD!=us.gi.number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) err=UNZ_BADZIPFILE; /* size of the central directory */ if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK) err=UNZ_ERRNO; /* offset of start of central directory with respect to the starting disk number */ if (unzlocal_getLong(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) err=UNZ_ERRNO; /* zipfile comment length */ if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) err=UNZ_ERRNO; if ((central_pos<us.offset_central_dir+us.size_central_dir) && (err==UNZ_OK)) err=UNZ_BADZIPFILE; if (err!=UNZ_OK) { ZCLOSE(us.z_filefunc, us.filestream); return NULL; } us.byte_before_the_zipfile = central_pos - (us.offset_central_dir+us.size_central_dir); us.central_pos = central_pos; us.pfile_in_zip_read = NULL; us.encrypted = 0; s=(unz_s*)ALLOC(sizeof(unz_s)); *s=us; unzGoToFirstFile((unzFile)s); return (unzFile)s; }
extern zipFile ZEXPORT zipOpen2 ( const char *pathname, int append, zipcharpc* globalcomment, zlib_filefunc_def* pzlib_filefunc_def) { zip_internal ziinit; zip_internal* zi; int err=ZIP_OK; if (pzlib_filefunc_def==NULL) fill_fopen_filefunc(&ziinit.z_filefunc); else ziinit.z_filefunc = *pzlib_filefunc_def; ziinit.filestream = (*(ziinit.z_filefunc.zopen_file)) (ziinit.z_filefunc.opaque, pathname, (append == APPEND_STATUS_CREATE) ? (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_CREATE) : (ZLIB_FILEFUNC_MODE_READ | ZLIB_FILEFUNC_MODE_WRITE | ZLIB_FILEFUNC_MODE_EXISTING)); if (ziinit.filestream == NULL) return NULL; ziinit.begin_pos = ZTELL(ziinit.z_filefunc,ziinit.filestream); ziinit.in_opened_file_inzip = 0; ziinit.ci.stream_initialised = 0; ziinit.number_entry = 0; ziinit.add_position_when_writting_offset = 0; init_linkedlist(&(ziinit.central_dir)); zi = (zip_internal*)ALLOC(sizeof(zip_internal)); if (zi==NULL) { ZCLOSE(ziinit.z_filefunc,ziinit.filestream); return NULL; } /* now we add file in a zipfile */ # ifndef NO_ADDFILEINEXISTINGZIP if (append == APPEND_STATUS_ADDINZIP) { uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ uLong size_central_dir; /* size of the central directory */ uLong offset_central_dir; /* offset of start of central directory */ uLong central_pos,uL; uLong number_disk; /* number of the current dist, used for spaning ZIP, unsupported, always 0*/ uLong number_disk_with_CD; /* number the the disk with central dir, used for spaning ZIP, unsupported, always 0*/ uLong number_entry; uLong number_entry_CD; /* total number of entries in the central dir (same than number_entry on nospan) */ uLong size_comment; central_pos = ziplocal_SearchCentralDir(&ziinit.z_filefunc,ziinit.filestream); if (central_pos==0) err=ZIP_ERRNO; if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) err=ZIP_ERRNO; /* the signature, already checked */ if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&uL)!=ZIP_OK) err=ZIP_ERRNO; /* number of this disk */ if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk)!=ZIP_OK) err=ZIP_ERRNO; /* number of the disk with the start of the central directory */ if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_disk_with_CD)!=ZIP_OK) err=ZIP_ERRNO; /* total number of entries in the central dir on this disk */ if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry)!=ZIP_OK) err=ZIP_ERRNO; /* total number of entries in the central dir */ if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&number_entry_CD)!=ZIP_OK) err=ZIP_ERRNO; if ((number_entry_CD!=number_entry) || (number_disk_with_CD!=0) || (number_disk!=0)) err=ZIP_BADZIPFILE; /* size of the central directory */ if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&size_central_dir)!=ZIP_OK) err=ZIP_ERRNO; /* offset of start of central directory with respect to the starting disk number */ if (ziplocal_getLong(&ziinit.z_filefunc, ziinit.filestream,&offset_central_dir)!=ZIP_OK) err=ZIP_ERRNO; /* zipfile comment length */ if (ziplocal_getShort(&ziinit.z_filefunc, ziinit.filestream,&size_comment)!=ZIP_OK) err=ZIP_ERRNO; if ((central_pos<offset_central_dir+size_central_dir) && (err==ZIP_OK)) err=ZIP_BADZIPFILE; if (err!=ZIP_OK) { ZCLOSE(ziinit.z_filefunc, ziinit.filestream); return NULL; } byte_before_the_zipfile = central_pos - (offset_central_dir+size_central_dir); ziinit.add_position_when_writting_offset = byte_before_the_zipfile ; { uLong size_central_dir_to_read = size_central_dir; size_t buf_size = SIZEDATA_INDATABLOCK; void* buf_read = (void*)ALLOC(buf_size); if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, offset_central_dir + byte_before_the_zipfile, ZLIB_FILEFUNC_SEEK_SET) != 0) err=ZIP_ERRNO; while ((size_central_dir_to_read>0) && (err==ZIP_OK)) { uLong read_this = SIZEDATA_INDATABLOCK; if (read_this > size_central_dir_to_read) read_this = size_central_dir_to_read; if (ZREAD(ziinit.z_filefunc, ziinit.filestream,buf_read,read_this) != read_this) err=ZIP_ERRNO; if (err==ZIP_OK) err = add_data_in_datablock(&ziinit.central_dir,buf_read, (uLong)read_this); size_central_dir_to_read-=read_this; } TRYFREE(buf_read); } ziinit.begin_pos = byte_before_the_zipfile; ziinit.number_entry = number_entry_CD; if (ZSEEK(ziinit.z_filefunc, ziinit.filestream, offset_central_dir+byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) err=ZIP_ERRNO; } # endif /* !NO_ADDFILEINEXISTINGZIP*/ if (err != ZIP_OK) { TRYFREE(zi); return NULL; } else { *zi = ziinit; return (zipFile)zi; } }
/////////////////////////////////////////////////////////////// // // 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; }