| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483 |
- //
- // ZipArchive.mm
- //
- //
- // Created by aish on 08-9-11.
- // acsolu@gmail.com
- // Copyright 2008 Inc. All rights reserved.
- //
- //消除三方库警告
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
- #pragma clang diagnostic ignored "-Wshorten-64-to-32"
- #pragma clang diagnostic ignored "-Wundeclared-selector"
- //#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- //#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- #import "ZipArchive.h"
- #import "zlib.h"
- #import "zconf.h"
- @interface ZipArchive (Private)
- -(void) OutputErrorMessage:(NSString*) msg;
- -(BOOL) OverWrite:(NSString*) file;
- -(NSDate*) Date1980;
- @end
- @implementation ZipArchive
- @synthesize delegate = _delegate;
- -(id) init
- {
- if( self=[super init] )
- {
- _zipFile = NULL ;
- }
- return self;
- }
- -(void) dealloc
- {
- [self CloseZipFile2];
- // [super dealloc];
- }
- -(BOOL) CreateZipFile2:(NSString*) zipFile
- {
- _zipFile = zipOpen( (const char*)[zipFile UTF8String], 0 );
- if( !_zipFile )
- return NO;
- return YES;
- }
- -(BOOL) CreateZipFile2:(NSString*) zipFile Password:(NSString*) password
- {
- _password = password;
- return [self CreateZipFile2:zipFile];
- }
- -(BOOL) addFileToZip:(NSString*) file newname:(NSString*) newname;
- {
- if( !_zipFile )
- return NO;
- // tm_zip filetime;
- time_t current;
- time( ¤t );
-
- zip_fileinfo zipInfo = {0};
- // zipInfo.dosDate = (unsigned long) current;
-
- NSDictionary* attr = [[NSFileManager defaultManager] fileAttributesAtPath:file traverseLink:YES];
- if( attr )
- {
- NSDate* fileDate = (NSDate*)[attr objectForKey:NSFileModificationDate];
- if( fileDate )
- {
- // some application does use dosDate, but tmz_date instead
- // zipInfo.dosDate = [fileDate timeIntervalSinceDate:[self Date1980] ];
- NSCalendar* currCalendar = [NSCalendar currentCalendar];
- uint flags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit |
- NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit ;
- NSDateComponents* dc = [currCalendar components:flags fromDate:fileDate];
- zipInfo.tmz_date.tm_sec = [dc second];
- zipInfo.tmz_date.tm_min = [dc minute];
- zipInfo.tmz_date.tm_hour = [dc hour];
- zipInfo.tmz_date.tm_mday = [dc day];
- zipInfo.tmz_date.tm_mon = [dc month] - 1;
- zipInfo.tmz_date.tm_year = [dc year];
- }
- }
-
- int ret ;
- NSData* data = nil;
- if( [_password length] == 0 )
- {
- ret = zipOpenNewFileInZip( _zipFile,
- (const char*) [newname UTF8String],
- &zipInfo,
- NULL,0,
- NULL,0,
- NULL,//comment
- Z_DEFLATED,
- Z_DEFAULT_COMPRESSION );
- }
- else
- {
- data = [ NSData dataWithContentsOfFile:file];
- uLong crcValue = crc32( 0L,NULL, 0L );
- crcValue = crc32( crcValue, (const Bytef*)[data bytes], [data length] );
- ret = zipOpenNewFileInZip3( _zipFile,
- (const char*) [newname UTF8String],
- &zipInfo,
- NULL,0,
- NULL,0,
- NULL,//comment
- Z_DEFLATED,
- Z_DEFAULT_COMPRESSION,
- 0,
- 15,
- 8,
- Z_DEFAULT_STRATEGY,
- [_password cStringUsingEncoding:NSASCIIStringEncoding],
- crcValue );
- }
- if( ret!=Z_OK )
- {
- return NO;
- }
- if( data==nil )
- {
- data = [ NSData dataWithContentsOfFile:file];
- }
- unsigned int dataLen = [data length];
- ret = zipWriteInFileInZip( _zipFile, (const void*)[data bytes], dataLen);
- if( ret!=Z_OK )
- {
- return NO;
- }
- ret = zipCloseFileInZip( _zipFile );
- if( ret!=Z_OK )
- return NO;
- return YES;
- }
- -(BOOL) CloseZipFile2
- {
- _password = nil;
- if( _zipFile==NULL )
- return NO;
- BOOL ret = zipClose( _zipFile,NULL )==Z_OK?YES:NO;
- _zipFile = NULL;
- return ret;
- }
- -(BOOL) UnzipOpenFile:(NSString*) zipFile
- {
- _unzFile = unzOpen( (const char*)[zipFile UTF8String] );
- if( _unzFile )
- {
- unz_global_info globalInfo = {0};
- if( unzGetGlobalInfo(_unzFile, &globalInfo )==UNZ_OK )
- {
- #ifdef DEBUG
- NSLog(@"%@", [NSString stringWithFormat:@"%lu entries in the zip file",globalInfo.number_entry] );
- #endif
- }
- }
- return _unzFile!=NULL;
- }
- -(BOOL) UnzipOpenFile:(NSString*) zipFile Password:(NSString*) password
- {
- _password = password;
- return [self UnzipOpenFile:zipFile];
- }
- -(BOOL) UnzipFileTo:(NSString*) path overWrite:(BOOL) overwrite
- {
- BOOL success = YES;
- int ret = unzGoToFirstFile( _unzFile );
- unsigned char buffer[4096] = {0};
- NSFileManager* fman = [NSFileManager defaultManager];
- if( ret!=UNZ_OK )
- {
- [self OutputErrorMessage:@"Failed"];
- }
-
- do{
- if( [_password length]==0 )
- ret = unzOpenCurrentFile( _unzFile );
- else
- ret = unzOpenCurrentFilePassword( _unzFile, [_password cStringUsingEncoding:NSASCIIStringEncoding] );
- if( ret!=UNZ_OK )
- {
- [self OutputErrorMessage:@"Error occurs"];
- success = NO;
- break;
- }
- // reading data and write to file
- int read ;
- unz_file_info fileInfo ={0};
- ret = unzGetCurrentFileInfo(_unzFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
- if( ret!=UNZ_OK )
- {
- [self OutputErrorMessage:@"Error occurs while getting file info"];
- success = NO;
- unzCloseCurrentFile( _unzFile );
- break;
- }
- char* filename = (char*) malloc( fileInfo.size_filename +1 );
- unzGetCurrentFileInfo(_unzFile, &fileInfo, filename, fileInfo.size_filename + 1, NULL, 0, NULL, 0);
- filename[fileInfo.size_filename] = '\0';
-
- // check if it contains directory
- NSString * strPath = [NSString stringWithCString:filename];
- BOOL isDirectory = NO;
- if( filename[fileInfo.size_filename-1]=='/' || filename[fileInfo.size_filename-1]=='\\')
- isDirectory = YES;
- free( filename );
- if( [strPath rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"/\\"]].location!=NSNotFound )
- {// contains a path
- strPath = [strPath stringByReplacingOccurrencesOfString:@"\\" withString:@"/"];
- }
- NSString* fullPath = [path stringByAppendingPathComponent:strPath];
-
- if( isDirectory )
- [fman createDirectoryAtPath:fullPath withIntermediateDirectories:YES attributes:nil error:nil];
- else
- [fman createDirectoryAtPath:[fullPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil];
- if( [fman fileExistsAtPath:fullPath] && !isDirectory && !overwrite )
- {
- if( ![self OverWrite:fullPath] )
- {
- unzCloseCurrentFile( _unzFile );
- ret = unzGoToNextFile( _unzFile );
- continue;
- }
- }
- FILE* fp = fopen( (const char*)[fullPath UTF8String], "wb");
- while( fp )
- {
- read=unzReadCurrentFile(_unzFile, buffer, 4096);
- if( read > 0 )
- {
- fwrite(buffer, read, 1, fp );
- }
- else if( read<0 )
- {
- [self OutputErrorMessage:@"Failed to reading zip file"];
- break;
- }
- else
- break;
- }
- if( fp )
- {
- fclose( fp );
- // set the orignal datetime property
- NSDate* orgDate = nil;
-
- //{{ thanks to brad.eaton for the solution
- NSDateComponents *dc = [[NSDateComponents alloc] init];
-
- dc.second = fileInfo.tmu_date.tm_sec;
- dc.minute = fileInfo.tmu_date.tm_min;
- dc.hour = fileInfo.tmu_date.tm_hour;
- dc.day = fileInfo.tmu_date.tm_mday;
- dc.month = fileInfo.tmu_date.tm_mon+1;
- dc.year = fileInfo.tmu_date.tm_year;
-
- NSCalendar *gregorian = [[NSCalendar alloc]
- initWithCalendarIdentifier:NSGregorianCalendar];
-
- orgDate = [gregorian dateFromComponents:dc] ;
- // [dc release];
- // [gregorian release];
- //}}
-
-
- NSDictionary* attr = [NSDictionary dictionaryWithObject:orgDate forKey:NSFileModificationDate]; //[[NSFileManager defaultManager] fileAttributesAtPath:fullPath traverseLink:YES];
- if( attr )
- {
- // [attr setValue:orgDate forKey:NSFileCreationDate];
- if( ![[NSFileManager defaultManager] setAttributes:attr ofItemAtPath:fullPath error:nil] )
- {
- // cann't set attributes
- #ifdef DEBUG
- NSLog(@"Failed to set attributes");
- #endif
- }
-
- }
-
-
-
- }
- unzCloseCurrentFile( _unzFile );
- ret = unzGoToNextFile( _unzFile );
- }while( ret==UNZ_OK && UNZ_OK!=UNZ_END_OF_LIST_OF_FILE );
- return success;
- }
- -(BOOL) UnzipAllFileToDir:(NSString*) path overWrite:(BOOL) overwrite
- {
- BOOL success = YES;
- int ret = unzGoToFirstFile( _unzFile );
- unsigned char buffer[4096] = {0};
- NSFileManager* fman = [NSFileManager defaultManager];
- if( ret!=UNZ_OK )
- {
- [self OutputErrorMessage:@"Failed"];
- }
-
- do{
- if( [_password length]==0 )
- ret = unzOpenCurrentFile( _unzFile );
- else
- ret = unzOpenCurrentFilePassword( _unzFile, [_password cStringUsingEncoding:NSASCIIStringEncoding] );
- if( ret!=UNZ_OK )
- {
- [self OutputErrorMessage:@"Error occurs"];
- success = NO;
- break;
- }
- // reading data and write to file
- int read ;
- unz_file_info fileInfo ={0};
- ret = unzGetCurrentFileInfo(_unzFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
- if( ret!=UNZ_OK )
- {
- [self OutputErrorMessage:@"Error occurs while getting file info"];
- success = NO;
- unzCloseCurrentFile( _unzFile );
- break;
- }
- char* filename = (char*) malloc( fileInfo.size_filename +1 );
- unzGetCurrentFileInfo(_unzFile, &fileInfo, filename, fileInfo.size_filename + 1, NULL, 0, NULL, 0);
- filename[fileInfo.size_filename] = '\0';
- NSString* fullPath=nil;
- // check if it contains directory
- // NSString * strPath = [NSString stringWithCString:filename];
- BOOL isDirectory = NO;
- if( filename[fileInfo.size_filename-1]=='/' || filename[fileInfo.size_filename-1]=='\\')
- {
- isDirectory = YES;
- fullPath= path;
- }
- else
- {
- NSString* fname = [fman displayNameAtPath:[NSString stringWithCString:filename]];
- fullPath= [path stringByAppendingPathComponent:fname];
- }
-
- free( filename );
-
-
- // if( [strPath rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"/\\"]].location!=NSNotFound )
- // {// contains a path
- // strPath = [strPath stringByReplacingOccurrencesOfString:@"\\" withString:@"/"];
- // }
-
-
- if( isDirectory )
- [fman createDirectoryAtPath:fullPath withIntermediateDirectories:YES attributes:nil error:nil];
- else
- [fman createDirectoryAtPath:[fullPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil];
- if( [fman fileExistsAtPath:fullPath] && !isDirectory && !overwrite )
- {
- if( ![self OverWrite:fullPath] )
- {
- unzCloseCurrentFile( _unzFile );
- ret = unzGoToNextFile( _unzFile );
- continue;
- }
- }
- FILE* fp = fopen( (const char*)[fullPath UTF8String], "wb");
- while( fp )
- {
- read=unzReadCurrentFile(_unzFile, buffer, 4096);
- if( read > 0 )
- {
- fwrite(buffer, read, 1, fp );
- }
- else if( read<0 )
- {
- [self OutputErrorMessage:@"Failed to reading zip file"];
- break;
- }
- else
- break;
- }
- if( fp )
- {
- fclose( fp );
- // set the orignal datetime property
- NSDate* orgDate = nil;
-
- //{{ thanks to brad.eaton for the solution
- NSDateComponents *dc = [[NSDateComponents alloc] init];
-
- dc.second = fileInfo.tmu_date.tm_sec;
- dc.minute = fileInfo.tmu_date.tm_min;
- dc.hour = fileInfo.tmu_date.tm_hour;
- dc.day = fileInfo.tmu_date.tm_mday;
- dc.month = fileInfo.tmu_date.tm_mon+1;
- dc.year = fileInfo.tmu_date.tm_year;
-
- NSCalendar *gregorian = [[NSCalendar alloc]
- initWithCalendarIdentifier:NSGregorianCalendar];
-
- orgDate = [gregorian dateFromComponents:dc] ;
- // [dc release];
- // [gregorian release];
- //}}
-
-
- NSDictionary* attr = [NSDictionary dictionaryWithObject:orgDate forKey:NSFileModificationDate]; //[[NSFileManager defaultManager] fileAttributesAtPath:fullPath traverseLink:YES];
- if( attr )
- {
- // [attr setValue:orgDate forKey:NSFileCreationDate];
- if( ![[NSFileManager defaultManager] setAttributes:attr ofItemAtPath:fullPath error:nil] )
- {
- // cann't set attributes
- #ifdef DEBUG
- NSLog(@"Failed to set attributes");
- #endif
- }
-
- }
-
-
-
- }
- unzCloseCurrentFile( _unzFile );
- ret = unzGoToNextFile( _unzFile );
- }while( ret==UNZ_OK && UNZ_OK!=UNZ_END_OF_LIST_OF_FILE );
- return success;
- }
- -(BOOL) UnzipCloseFile
- {
- _password = nil;
- if( _unzFile )
- return unzClose( _unzFile )==UNZ_OK;
- return YES;
- }
- #pragma mark wrapper for delegate
- -(void) OutputErrorMessage:(NSString*) msg
- {
- if( _delegate && [_delegate respondsToSelector:@selector(ErrorMessage)] )
- [_delegate ErrorMessage:msg];
- }
- -(BOOL) OverWrite:(NSString*) file
- {
- if( _delegate && [_delegate respondsToSelector:@selector(OverWriteOperation)] )
- return [_delegate OverWriteOperation:file];
- return YES;
- }
- #pragma mark get NSDate object for 1980-01-01
- -(NSDate*) Date1980
- {
- NSDateComponents *comps = [[NSDateComponents alloc] init];
- [comps setDay:1];
- [comps setMonth:1];
- [comps setYear:1980];
- NSCalendar *gregorian = [[NSCalendar alloc]
- initWithCalendarIdentifier:NSGregorianCalendar];
- NSDate *date = [gregorian dateFromComponents:comps];
-
- // [comps release];
- // [gregorian release];
- return date;
- }
- @end
|