Skip to content

Minor core refactor. Fix some tests. #61

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
ZipArchive/build
*.pbxuser
*.mode1v3
.*.swp

.DS_Store
xcuserdata/
Expand Down
19 changes: 19 additions & 0 deletions ZipArchive.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,25 @@ typedef void(^ZipArchiveProgressUpdateBlock)(int percentage, int filesProcessed,

@end

/**
@class
@brief An object that contains information about a file in a zip archive.

It also provides methods to expand an existing archive file (optionally with a password),
and extract the files.
*/

@interface ZipFileInfo : NSObject {
NSString* _strPath;
NSDate* _orgDate;
}

@property (nonatomic, copy) NSString *strPath;
@property (nonatomic, retain) NSDate* orgDate;

@end


/**
@class
@brief An object that can create zip files and expand existing ones.
Expand Down
173 changes: 92 additions & 81 deletions ZipArchive.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ @interface NSFileManager(ZipArchive)
- (NSDictionary *)_attributesOfItemAtPath:(NSString *)path followingSymLinks:(BOOL)followingSymLinks error:(NSError **)error;
@end



@interface ZipArchive ()

-(void) OutputErrorMessage:(NSString*) msg;
Expand Down Expand Up @@ -272,6 +274,64 @@ -(BOOL) UnzipOpenFile:(NSString*) zipFile Password:(NSString*) password
return [self UnzipOpenFile:zipFile];
}


// Helper function to replace all \ with /
-(NSString *)strPathWithCString:(char *)filename
{
NSString * strPath = [NSString stringWithCString:filename encoding:self.stringEncoding];

if( [strPath rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"/\\"]].location!=NSNotFound )
{
strPath = [strPath stringByReplacingOccurrencesOfString:@"\\" withString:@"/"];
}

return strPath;
}

-(ZipFileInfo *)currentFileInfo
{
// reading data and write to file
unz_file_info fileInfo ={0};
int ret = unzGetCurrentFileInfo(_unzFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
if( ret!=UNZ_OK )
{
return nil;
}
ZipFileInfo* zipFileInfo = [[[ZipFileInfo alloc] init] autorelease];

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';

zipFileInfo.strPath = [self strPathWithCString:filename];
free(filename);

// set the orignal datetime property
if( fileInfo.tmu_date.tm_year!=0 )
{
NSDateComponents* components = [[NSDateComponents alloc] init];
components.second = fileInfo.tmu_date.tm_sec;
components.minute = fileInfo.tmu_date.tm_min;
components.hour = fileInfo.tmu_date.tm_hour;
components.day = fileInfo.tmu_date.tm_mday;
components.month = fileInfo.tmu_date.tm_mon + 1;
components.year = fileInfo.tmu_date.tm_year;

NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];

zipFileInfo.orgDate = [gregorianCalendar dateFromComponents:components];

[components release];
[gregorianCalendar release];
}
else
{
zipFileInfo.orgDate = nil;
}

return zipFileInfo;
}

/**
* Expand all files in the zip archive into the specified directory.
*
Expand Down Expand Up @@ -313,37 +373,24 @@ -(BOOL) UnzipFileTo:(NSString*) path overWrite:(BOOL) overwrite
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 )
{

ZipFileInfo *fileInfo = [self currentFileInfo];
if (fileInfo == nil){
[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 encoding:self.stringEncoding];
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];
}

BOOL isDirectory = isDirectory = [fileInfo.strPath hasSuffix:@"/"];
NSString* fullPath = [path stringByAppendingPathComponent:fileInfo.strPath];

if( isDirectory )
[_fileManager createDirectoryAtPath:fullPath withIntermediateDirectories:YES attributes:nil error:nil];
else
[_fileManager createDirectoryAtPath:[fullPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil];

int read ;
FILE* fp = NULL;
do
{
Expand Down Expand Up @@ -384,23 +431,10 @@ -(BOOL) UnzipFileTo:(NSString*) path overWrite:(BOOL) overwrite
// add the full path of this file to the output array
[(NSMutableArray*)_unzippedFiles addObject:fullPath];

// set the orignal datetime property
if( fileInfo.tmu_date.tm_year!=0 )
// set the original datetime property
if( fileInfo.orgDate != nil)
{
NSDateComponents* components = [[NSDateComponents alloc] init];
components.second = fileInfo.tmu_date.tm_sec;
components.minute = fileInfo.tmu_date.tm_min;
components.hour = fileInfo.tmu_date.tm_hour;
components.day = fileInfo.tmu_date.tm_mday;
components.month = fileInfo.tmu_date.tm_mon + 1;
components.year = fileInfo.tmu_date.tm_year;

NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDate* orgDate = [[gregorianCalendar dateFromComponents:components] retain];
[components release];
[gregorianCalendar release];

NSDictionary* attr = [NSDictionary dictionaryWithObject:orgDate forKey:NSFileModificationDate]; //[_fileManager fileAttributesAtPath:fullPath traverseLink:YES];
NSDictionary* attr = [NSDictionary dictionaryWithObject:fileInfo.orgDate forKey:NSFileModificationDate]; //[_fileManager fileAttributesAtPath:fullPath traverseLink:YES];
if( attr )
{
// [attr setValue:orgDate forKey:NSFileCreationDate];
Expand All @@ -411,8 +445,6 @@ -(BOOL) UnzipFileTo:(NSString*) path overWrite:(BOOL) overwrite
}

}
[orgDate release];
orgDate = nil;
}

}
Expand All @@ -436,7 +468,7 @@ -(BOOL) UnzipFileTo:(NSString*) path overWrite:(BOOL) overwrite
_progressBlock(progress, index, _numFiles);
}
}
} while (ret==UNZ_OK && ret!=UNZ_END_OF_LIST_OF_FILE);
} while (ret==UNZ_OK);
return success;
}

Expand Down Expand Up @@ -468,29 +500,16 @@ -(NSDictionary *)UnzipFileToMemory
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 )
{
// reading data and copy to memory
ZipFileInfo *fileInfo = [self currentFileInfo];
if (fileInfo == nil){
[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 encoding:self.stringEncoding];
free( filename );
if( [strPath rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"/\\"]].location!=NSNotFound )
{// contains a path
strPath = [strPath stringByReplacingOccurrencesOfString:@"\\" withString:@"/"];
}

}

int read ;
NSMutableData *fileMutableData = [NSMutableData data];
do
{
Expand All @@ -514,7 +533,7 @@ -(NSDictionary *)UnzipFileToMemory
if (fileMutableData.length > 0)
{
NSData *fileData = [NSData dataWithData:fileMutableData];
[fileDictionary setObject:fileData forKey:strPath];
[fileDictionary setObject:fileData forKey:fileInfo.strPath];
}

if (ret == UNZ_OK) {
Expand All @@ -536,7 +555,7 @@ -(NSDictionary *)UnzipFileToMemory
_progressBlock(progress, index, _numFiles);
}
}
} while (ret==UNZ_OK && ret!=UNZ_END_OF_LIST_OF_FILE);
} while (ret==UNZ_OK);

NSDictionary *resultDictionary = [NSDictionary dictionaryWithDictionary:fileDictionary];
return resultDictionary;
Expand Down Expand Up @@ -590,33 +609,20 @@ -(NSArray*) getZipFileContents // list the contents of the zip archive. must
break;
}

// reading data and write to file
unz_file_info fileInfo ={0};
ret = unzGetCurrentFileInfo(_unzFile, &fileInfo, NULL, 0, NULL, 0, NULL, 0);
if( ret!=UNZ_OK )
{
// Just get the file info
ZipFileInfo *fileInfo = [self currentFileInfo];
if (fileInfo == nil){
[self OutputErrorMessage:@"Error occurs while getting file info"];
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 encoding:self.stringEncoding];
free( filename );
if( [strPath rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"/\\"]].location!=NSNotFound )
{// contains a path
strPath = [strPath stringByReplacingOccurrencesOfString:@"\\" withString:@"/"];
}

}

// Copy name to array
[allFilenames addObject:strPath];
[allFilenames addObject:fileInfo.strPath];

unzCloseCurrentFile( _unzFile );
ret = unzGoToNextFile( _unzFile );
} while( ret==UNZ_OK && UNZ_OK!=UNZ_END_OF_LIST_OF_FILE );
} while( ret==UNZ_OK);

// return an immutable array.
return [NSArray arrayWithArray:allFilenames];
Expand Down Expand Up @@ -689,3 +695,8 @@ - (NSDictionary *)_attributesOfItemAtPath:(NSString *)path followingSymLinks:(BO

@end


@implementation ZipFileInfo
@synthesize strPath = _strPath;
@synthesize orgDate = _orgDate;
@end
14 changes: 14 additions & 0 deletions ZipArchive/ZipArchive.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@
C9E8EBF6124F3D030047C862 /* zip.h in Headers */ = {isa = PBXBuildFile; fileRef = C9E8EBEC124F3D030047C862 /* zip.h */; };
C9E8EBF9124F3D170047C862 /* ZipArchive.h in Headers */ = {isa = PBXBuildFile; fileRef = C9E8EBF7124F3D170047C862 /* ZipArchive.h */; settings = {ATTRIBUTES = (); }; };
C9E8EBFA124F3D170047C862 /* ZipArchive.m in Sources */ = {isa = PBXBuildFile; fileRef = C9E8EBF8124F3D170047C862 /* ZipArchive.m */; };
E255FE4F1ACE49F9002D63F7 /* V3.xml in Resources */ = {isa = PBXBuildFile; fileRef = C95AB35117E1C14A00120861 /* V3.xml */; };
E255FE501ACE49FA002D63F7 /* V3.xml in Resources */ = {isa = PBXBuildFile; fileRef = C95AB35117E1C14A00120861 /* V3.xml */; };
E255FE511ACE4A02002D63F7 /* V3.png in Resources */ = {isa = PBXBuildFile; fileRef = C95AB35017E1C14A00120861 /* V3.png */; };
E255FE521ACE4A03002D63F7 /* V3.png in Resources */ = {isa = PBXBuildFile; fileRef = C95AB35017E1C14A00120861 /* V3.png */; };
E255FE531ACE4A06002D63F7 /* hier.zip in Resources */ = {isa = PBXBuildFile; fileRef = E255FE4D1ACE4811002D63F7 /* hier.zip */; };
E255FE541ACE4A07002D63F7 /* hier.zip in Resources */ = {isa = PBXBuildFile; fileRef = E255FE4D1ACE4811002D63F7 /* hier.zip */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -135,6 +141,7 @@
C9E8EBF7124F3D170047C862 /* ZipArchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZipArchive.h; path = ../ZipArchive.h; sourceTree = "<group>"; };
C9E8EBF8124F3D170047C862 /* ZipArchive.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ZipArchive.m; path = ../ZipArchive.m; sourceTree = "<group>"; };
D2AAC07E0554694100DB518D /* libZipArchive-ios.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libZipArchive-ios.a"; sourceTree = BUILT_PRODUCTS_DIR; };
E255FE4D1ACE4811002D63F7 /* hier.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = hier.zip; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -242,6 +249,7 @@
C95AB34F17E1C14A00120861 /* test-files */ = {
isa = PBXGroup;
children = (
E255FE4D1ACE4811002D63F7 /* hier.zip */,
C95AB35017E1C14A00120861 /* V3.png */,
C95AB35117E1C14A00120861 /* V3.xml */,
);
Expand Down Expand Up @@ -483,6 +491,9 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E255FE511ACE4A02002D63F7 /* V3.png in Resources */,
E255FE531ACE4A06002D63F7 /* hier.zip in Resources */,
E255FE4F1ACE49F9002D63F7 /* V3.xml in Resources */,
C95AB36317E1C37800120861 /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand All @@ -491,6 +502,9 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E255FE521ACE4A03002D63F7 /* V3.png in Resources */,
E255FE541ACE4A07002D63F7 /* hier.zip in Resources */,
E255FE501ACE49FA002D63F7 /* V3.xml in Resources */,
C95AB37B17E1C47D00120861 /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
Binary file added ZipArchive/tests/test-files/hier.zip
Binary file not shown.
Loading