It is allowed to use ssziparchive library in the App Store? - ios

Due to cryptography export regulations, it is possible to use this library? or which one could I use to compress/decompress files?

I don't know if SSZipArchive is allowed to use in distributed apps, but the library I am using is Objective-Zip.
It can be easily integrated into any project.
Sample code for zipping:
// create a zip file for writing
ZipFile *zipFile= [[ZipFile alloc] initWithFileName:pathOfTheFileToBeZipped mode:ZipFileModeCreate];
// Add a file, write to its stream and close it
ZipWriteStream *stream1= [zipFile writeFileInZipWithName:#"abc.txt" fileDate:[NSDate dateWithTimeIntervalSinceNow:-86400.0] compressionLevel:ZipCompressionLevelBest];
NSString *text= #"abc";
[stream1 writeData:[text dataUsingEncoding:NSUTF8StringEncoding]];
[stream1 finishedWriting];
// Add another file, write to its stream and close it
ZipWriteStream *stream2= [zipFile writeFileInZipWithName:#"x/y/z/xyz.txt" compressionLevel:ZipCompressionLevelNone];
NSString *text2= #"XYZ";
[stream2 writeData:[text2 dataUsingEncoding:NSUTF8StringEncoding]];
[stream2 finishedWriting];
// Close the zip file
[zipFile close];
Sample code for unzipping:
// open the zip file for reading
ZipFile *unzipFile = [[ZipFile alloc] initWithFileName:pathOfTheFileToBeUnzipped mode:ZipFileModeUnzip];
// retrieve the info of the files inside
NSArray *infos= [unzipFile listFileInZipInfos];
// iterate over files
for (FileInZipInfo *info in infos) {
// locate the file in the zip
[unzipFile locateFileInZip:info.name];
// expand the file in memory
ZipReadStream *read= [unzipFile readCurrentFileInZip];
NSData *data = [read readDataOfLength:info.length];
[read finishedReading];
// construct the folder/file path structure
NSString *unzipPathFilename = [unzipPath stringByAppendingPathComponent:info.name];
NSString *unzipPathFoldername = [[unzipPathFilename stringByDeletingLastPathComponent] copy];
NSError *errorw;
// write the unzipped files, with some consistency checks
NSRange range = [unzipPathFoldername rangeOfString:#"__MACOSX"];
if (range.location == NSNotFound) {
if ([fileManager createDirectoryAtPath:unzipPathFoldername withIntermediateDirectories:YES attributes:nil error:&errorw]) {
if (![[unzipPathFilename pathExtension] isEqualToString:#""] && ![[[unzipPathFilename lastPathComponent] substringToIndex:1] isEqualToString:#"." ]) {
[data writeToFile:unzipPathFilename atomically:NO];
}
}
else {
NSLog(#"Directory Fail: %#", errorw);
}
}
}
// close the zip file
[unzipFile close];

Actually you are allowed to have encryption in iOS application.
You just have to submit application to NSA who you are and what kind of encryption do have in app.
Respond with your reg number usually comes in 30 minutes.
It is automatic or semi-automatic.
They just collect information about developers.
It is simpler then register as iOS developer.
My opinion:-
If you do not use encryption in ZIP library then you should submit any application.
Linker will remove that code after optimization.
That code is not used. But if you use encryption even that comes with iOS then you should apply.
e.g. UIWebView if it opens https:// URLs (e.g. Facebook) but if you use UIWebView to open non secure pages then you should not apply.

Related

"Open In" with dynamically generated file fails in iOS 8

I use this code to save some PDF data to a file, send it to another app using the "Open In" menu, then delete the file when that's done:
- (void)openIn:(NSData *)fileData {
// save the PDF data to a temporary file
NSString *fileName = [NSString stringWithFormat:#"%#.pdf", self.name];
NSString *filePath = [NSString stringWithFormat:#"%#/Documents/%#", NSHomeDirectory(), fileName];
BOOL result = [fileData writeToFile:filePath atomically:TRUE];
if (result) {
NSURL *URL = [NSURL fileURLWithPath:filePath];
UIDocumentInteractionController *controller = [[UIDocumentInteractionController interactionControllerWithURL:URL] retain];
controller.delegate = self;
[controller presentOpenInMenuFromBarButtonItem:self.openInButton animated:TRUE];
}
}
- (void)documentInteractionControllerDidDismissOpenInMenu:(UIDocumentInteractionController *)controller {
// when the document interaction controller finishes, delete the temporary file
NSString *fileName = [NSString stringWithFormat:#"%#.pdf", self.name];
NSString *filePath = [NSString stringWithFormat:#"%#/Documents/%#", NSHomeDirectory(), fileName];
[[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
}
This has worked fine until iOS 8. Now, the file is created and I can verify that it contains the correct content, the Open In menu appears, I can select an app, and the delegate method runs and cleans up the file. But instead of iOS switching to the selected app and copying the file into it as it did before, the Open In menu simply closes when I select an app, and the file is not copied.
This works if I give the UIDocumentInteractionController an existing file. It also works if I use the provided fileData but change the destination filename to the filename of an existing file. This suggests a permissions problem -- as if new files are created in iOS 8 with default permissions that UIDocumentInteractionController can't read.
Does anyone know what's happening and how I can work around it?
It looks like the order of operations has changed slightly in iOS 8. DidDismissOpenInMenu used to run after the file was finished sending, but now it runs after the file begins sending. This means my cleanup code was sometimes running before the file was finished sending, leaving no file to send. I figured this out after noticing that smaller files were being sent okay; apparently the processing for smaller files was finishing before my cleanup code got them, but the processing for larger files was not.
To ensure the correct timing, but also clean up files that are created when the user opens the DocumentInteractionController and then dismisses the controller without doing anything, I changed my methods like this:
- (void)openIn:(NSData *)fileData {
// save the PDF data to a temporary file
NSString *fileName = [NSString stringWithFormat:#"%#.pdf", self.name];
NSString *filePath = [NSString stringWithFormat:#"%#/Documents/%#", NSHomeDirectory(), fileName];
BOOL result = [fileData writeToFile:filePath atomically:TRUE];
if (result) {
self.sendingFile = FALSE;
NSURL *URL = [NSURL fileURLWithPath:filePath];
UIDocumentInteractionController *controller = [[UIDocumentInteractionController interactionControllerWithURL:URL] retain];
controller.delegate = self;
[controller presentOpenInMenuFromBarButtonItem:self.openInButton animated:TRUE];
}
}
- (void)documentInteractionController:(UIDocumentInteractionController *)controller willBeginSendingToApplication:(NSString *)application {
// the user chose to send the file, so we shouldn't clean it up until that's done
self.sendingFile = TRUE;
}
- (void)documentInteractionControllerDidDismissOpenInMenu:(UIDocumentInteractionController *)controller {
if (!self.sendingFile) {
// the user didn't choose to send the file, so we can clean it up now
[self openInCleanup];
}
}
- (void)documentInteractionController:(UIDocumentInteractionController *)controller didEndSendingToApplication:(NSString *)application {
// the user chose to send the file, and the sending is finished, so we can clean it up now
[self openInCleanup];
self.sendingFile = FALSE;
}
- (void)openInCleanup {
// delete the temporary file
NSString *fileName = [NSString stringWithFormat:#"%#.pdf", self.name];
NSString *filePath = [NSString stringWithFormat:#"%#/Documents/%#", NSHomeDirectory(), fileName];
[[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
}
Update for iOS 11
Before iOS 11, it seems that the operating system kept a copy of the file available until the receiving app was finished reading it, even though my cleanup function ran as soon as the file was sent out from my app. In iOS 11, this changed and the receiving app fails to read the file because my app deletes it before that's done. So now instead of saving the temporary file to Documents and using the openInCleanup method to delete it immediately, I'm saving the temporary file to tmp and emptying the tmp folder next time the app launches. This approach should also work with older iOS versions. Just remove openInCleanup, change Documents to tmp in the paths, and add this to applicationDidFinishLaunching:
// clear the tmp directory, which will contain any files saved for Open In
NSString *tmpDirectory = [NSString stringWithFormat:#"%#/tmp", NSHomeDirectory()];
NSArray *tmpFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:tmpDirectory error:NULL];
for (NSString *tmpFile in tmpFiles) {
[[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:#"%#/%#", tmpDirectory, tmpFile] error:NULL];
}
After reading this post, I already hoped to have found the solution to a similar problem:
For me, as of iOS 8, sharing was only working with Mail.app. It was failing for Dropbox, etc.
Turns out it was something else:
On my interactionController I was setting an annotation like this:
interactionController.annotation = #"Some text"
For unknown reasons, this prevented Dropbox to open at all. There were no error messages or anything. Removing this line solved the issue.

iOS app out of memory handling

In an iOS application, I'm generating a 'voice recorder' functionality for continuous capturing of speech.
I use the following code for writing the speech in to a file.
//output speech
NSString *filePath = [root stringByAppendingPathComponent:#"output_speech.raw"];
if(![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
[[NSData data] writeToFile:filePath atomically:YES];
}
NSData *myData = [NSData dataWithBytes:ptrOut length:DataByteSize];
NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:filePath];
[handle truncateFileAtOffset:[handle seekToEndOfFile]];
[handle writeData:myData];
[handle closeFile];
My question is, in case the iOS device is going out of memory, how to handle the file writing situation?
There is a very similar question here:
iPhone: available disk space
I would check for the available disk space and appropriately determine whether to cancel the write and alert the user, or to just silently fail.
#Infinity James, I obtained the free space using the method mentioned in following link. [link] (http://www.linkedin.com/groups/How-detect-total-available-free-72283.S.217861544)

Unable to copy sqlite file from app bundle to documents directory: getting (Cocoa error 260)

I am trying to copy my sqlite file from app bundle into documents directory using the code below
-(id)init {
self = [super init];
if (self) {
// 1. Create a handle to the database file for UIManagedDocument
NSURL *docURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
docURL = [docURL URLByAppendingPathComponent:#"DefaultDatabase"];
self.document = [[UIManagedDocument alloc] initWithFileURL:docURL]; // URL of the location of document i.e. /documents directory
NSLog(#" URL document");
//set our document up for automatic migrations
if (self.document) {
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES],
NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES],
NSInferMappingModelAutomaticallyOption, nil];
self.document.persistentStoreOptions = options;
// Register for Notifications
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(objectsDidChange:) name:NSManagedObjectContextObjectsDidChangeNotification object:self.document.managedObjectContext];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(contextDidSave:) name:NSManagedObjectContextDidSaveNotification object:self.document.managedObjectContext];
} else {
NSLog(#"The UIManaged Document could not be initialized");
}
// 2. Check if the persistent store file does not exists in case of first run
if (!([[NSFileManager defaultManager] fileExistsAtPath:[self.document.fileURL path]])) {
NSLog(#" persistent file not found trying to copy from app bbundle");
NSString *docFileName = [UIManagedDocument persistentStoreName];
NSString *docFilePath = [[NSBundle mainBundle] pathForResource:docFileName ofType:#"sqlite"];
**NSLog(#" doc file path = %#", docFilePath);**
if (docFilePath) { // found the database file in app bundle
NSLog(#" found file in bundle");
//Production: Copy from app bundle.
NSError *error = nil;
NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *copyToPath = [searchPaths lastObject];
if([[NSFileManager defaultManager] copyItemAtPath:docFilePath toPath:copyToPath error:&error]){
NSLog(#"File successfully copied");
} else { // if could not locate the file
[[[UIAlertView alloc]initWithTitle:NSLocalizedString(#"error", nil) message: NSLocalizedString(#"failedcopydb", nil) delegate:nil cancelButtonTitle:NSLocalizedString(#"ok", nil) otherButtonTitles:nil] show];
NSLog(#"Error description-%# \n", [error localizedDescription]);
NSLog(#"Error reason-%#", [error localizedFailureReason]);
}
}
}
}
return self;
}
a) I created the .sqlite file using data loader app which uses UIManagedDcoument to add data to Core Data. The .sqlite file gets generated in documents directory.
b) I add the *.sqlite file to resources folder and add it to bundle. If I check the app bundle using Terminal..I see 'persistent store' and <app name.momd> file under the bundle directory. There is no file with extension .sqlite
c)But in my code above when I check for whether files exists in app bundle using line of code, it is successful. So file exists in bundle
NSString *file = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:fileName];
d) But when try to copy, it fails and gives me (Cocca Error 206) meaning its unable to find the .sqlite file in the app bundle.
if([[NSFileManager defaultManager] copyItemAtPath:file toPath:copyToPath error:&error])
which is in line with the fact that I don't see .sqlite file under app bundle directory instead I see a persistent store and .momd files.
So where I am going wrong ?
EDIT
This is an explanation of how I am generating my mydata.sqlite file.
I am using Core Data and want to provide a pre-poulated database upon first launch of app to the user. So I used a data loader app to create .sqlite file for me. I am using UIManagedDocument for core data. After I run the app, I see a mydata.sqlite directory gets created under documents directory. The directory structure is as follows
/users//.../documents/mydata.sqlite/storeContent/persistenStore.
So basically instead of creating a file, it creates a directory with .sqlite extension and I see persistentStore file. So when I try to copy resources under app bundle in target under build phases..it adds the persistentStore and not .sqlite file.
My question whatever is described is correct and I am supposed to handle it differently in my code. If yes, what is that I am supposed to do to get handle on data store.
I thought .sqlite was a file and not a directory. Please guide
Thanks
This line does not actually check if the file exists:
NSString *file = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:fileName];
All that does is build the path in file. If you want to check whether it exists, you need to use [NSFileManager fileExistsAtPath:]. Or you could go back to using pathForResource:ofType:, which was apparently correct when it returned nil.
You don't seem to be copying the file into the bundle at all. This is a problem with your Xcode project configuration.
I read up apple documentation on UIManagedDocument and here are the key points that I was going wrong on
Was handling UIManagedDocument incorrectly. When you initialize a managed document, you specify the URL for the document location. and not the document itself. If you need to add
You can perform additional customization by creating a subclass of UIManagedDocument i.e.
Override persistentStoreName to customize the name of the persistent store file inside the document’s file package.
cutting and pasting the example code for the right way to handle the data file
You create a managed document object using initWithFileURL:; if you want, you can then configure the document before you use its managed object context. Typically you might set the persistent store options, as illustrated in this example:
NSURL *docURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"FirstDocument"];
doc = [[UIManagedDocument alloc] initWithFileURL:docURL];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
doc.persistentStoreOptions = options;
**if ([[NSFileManager defaultManager] fileExistsAtPath:[docURL path]]**) {
[doc openWithCompletionHandler:^(BOOL success){
if (!success) {
// Handle the error.
}
}];
}
else {
[self addInitialData];
[doc saveToURL:docURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success){
if (!success) {
// Handle the error.
}
}];
}

Can't write large file (> 200MB, 700MB in my case) in ios device?

I am having the problem of writing large file (>200 MB) in iOS device (iPad) but in the simulator it works perfect.
I am using NSFileManager to create file and NSFileData to write file.
I think there is no problem in my code as it runs fine in the simulator.
Does anyone having the same problem?
To elaborate my situation:
I am saving chunk of files (3MB each) in my device which works fine. That means for a 300 MB file I have 100 chunks. Now, from the 100 chunks I want to create the actual file. So I am using the NSFileManager to create file in first iteration and then using NSFileData to write the 3MB data at the end of the file. While running the program it crashes after 61 chunks. I am guessing there might have some memory related issues in the iPad.
I am saving the chunk of files in fileDir in the format data-0, data-1, data-2...
I am applying the decrypt operation on data but for simplicity I have removed that portion.
// List of chunk files
NSArray *filelist= [[NSFileManager defaultManager] contentsOfDirectoryAtPath:fileDir error:err];
for(int i = 0; i < [filelist count]; i++) {
// Read the chunk of file
fileName = [[NSString alloc] initWithFormat:#"data-%d", i];
filePath = [fileDir stringByAppendingPathComponent:fileName];
fileReadHandle = [NSFileHandle fileHandleForReadingAtPath:filePath];
// Write in tempFile
if(offset == 0){
if([[NSFileManager defaultManager] createFileAtPath:tempFile contents:data attributes:nil]){
fileWriteHandle = [NSFileHandle fileHandleForWritingAtPath:tempFile];
NSLog(#"File was created!");
} else {
NSLog(#"File was not created.");
}
} else {
[fileWriteHandle seekToEndOfFile]; // Tried with comment out this line but same problem
// Write the decrypted data from chunk
[fileWriteHandle writeData:[[fileReadHandle readDataToEndOfFile] decryptedAES256DataUsingKey:AESEncryptionKey error:err]];
}
}
Edit (11.02.2013)
I tried with my previous code where I omitted the data decryption part.
Interestingly, the problem was in the decryption part I guess cause without the decryption it works fine. I have added the decryption code. For decryption I am using NSData+CommonCrypto library (it's non ARC) but my project is in ARC.
It could be an operating system issue because the NSFileHandle is never being closed for each chunk. I would recommend closing it.
Also, it looks like you have your variables declared outside the scope of the for loop. Unless you need those variables outside the loop, it's generally good to keep the scope of your variables as small as possible, especially if you are using ARC and are trying to think about when memory will be released.
If you think that the NSFileHandle is holding onto data in memory, try to use the -synchronizeFile method after writing each chunk to make sure in memory changes are reflected to disk.
Also, I moved the creation of the file you are writing to outside the loop, because it's easier to follow for me.
Try this adjustment:
// List of chunk files
NSArray *filelist= [[NSFileManager defaultManager] contentsOfDirectoryAtPath:fileDir error:err];
if([[NSFileManager defaultManager] createFileAtPath:tempFile contents:[NSData data] attributes:nil]){
NSLog(#"File was created!");
} else {
NSLog(#"File was not created.");
}
NSFileHandle *fileWriteHandle = [NSFileHandle fileHandleForWritingAtPath:tempFile];
for(int i = 0; i < [filelist count]; i++) {
// Read the chunk of file
NSString *fileName = [NSString stringWithFormat:#"data-%d", i];
NSString *filePath = [fileDir stringByAppendingPathComponent:fileName];
NSFileHandle *fileReadHandle = [NSFileHandle fileHandleForReadingAtPath:filePath];
NSData *data = [fileReadHandle readDataToEndOfFile];
// No longer using the file
[fileReadHandle closeFile];
// Write in tempFile
[fileWriteHandle writeData:data];
[fileWriteHandle synchronizeFile];// Flush any data in memory to disk
}
[fileWriteHandle closeFile];
Modifying the following code worked like a magic,
#autoreleasepool {
[fileWriteHandle writeData:[[fileReadHandle readDataToEndOfFile] decryptedAES256DataUsingKey:AESEncryptionKey error:err]];
}

iPhone Unzip code

Really stuck on trying to write code to unzip a file or directory on the iPhone.
Below is some sample code that I'm using to try and unzip a simple text file.
It unzips the file but its corrupt.
(void)loadView {
NSString *DOCUMENTS_FOLDER = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
NSString *path = [DOCUMENTS_FOLDER stringByAppendingPathComponent:#"sample.zip"];
NSString *unzipeddest = [DOCUMENTS_FOLDER stringByAppendingPathComponent:#"test.txt"];
gzFile file = gzopen([path UTF8String], "rb");
FILE *dest = fopen([unzipeddest UTF8String], "w");
unsigned char buffer[CHUNK];
int uncompressedLength = gzread(file, buffer, CHUNK);
if(fwrite(buffer, 1, uncompressedLength, dest) != uncompressedLength || ferror(dest)) {
NSLog(#"error writing data");
}
else{
}
fclose(dest);
gzclose(file);
}
I wanted an easy solution and didn't find one I liked here, so I modified a library to do what I wanted. You may find SSZipArchive useful. (It can also create zip files by the way.)
Usage:
NSString *path = #"path_to_your_zip_file";
NSString *destination = #"path_to_the_folder_where_you_want_it_unzipped";
[SSZipArchive unzipFileAtPath:path toDestination:destination];
Has "sample.zip" really been created with gZip? The .zip extension usually is used for archives created by WinZip. Those can also be decompressed using zLib, but you'd have to parse the header and use other routines.
To check, have a look at the first two bytes of the file. If it is 'PK', it's WinZip, if it's 0x1F8B, it's gZip.
Because this is iPhone specific, have a look at this iPhone SDK forum discussion where miniZip is mentioned. It seems this can handle WinZip files.
But if it's really a WinZip file, you should have a look at the WinZip specification and try to parse the file yourself. It basically should be parsing some header values, seeking the compressed stream position and using zLib routines to decompress it.
This code worked well for me for gzip:
the database was prepared like this:
gzip foo.db
the key was looping over the gzread(). The example above only reads the first CHUNK bytes.
#import <zlib.h>
#define CHUNK 16384
NSLog(#"testing unzip of database");
start = [NSDate date];
NSString *zippedDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"foo.db.gz"];
NSString *unzippedDBPath = [documentsDirectory stringByAppendingPathComponent:#"foo2.db"];
gzFile file = gzopen([zippedDBPath UTF8String], "rb");
FILE *dest = fopen([unzippedDBPath UTF8String], "w");
unsigned char buffer[CHUNK];
int uncompressedLength;
while (uncompressedLength = gzread(file, buffer, CHUNK) ) {
// got data out of our file
if(fwrite(buffer, 1, uncompressedLength, dest) != uncompressedLength || ferror(dest)) {
NSLog(#"error writing data");
}
}
fclose(dest);
gzclose(file);
NSLog(#"Finished unzipping database");
Incidentally, I can unzip 33MB into 130MB in 77 seconds or about 1.7 MB uncompressed/second.
This code will unzip any .zip file into your app document directory and get file from app resources.
self.fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSLog(#"document directory path:%#",paths);
self.documentDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/abc", self.documentDirectory];
NSLog(#"file path is:%#",filePath);
NSString *fileContent = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"data.zip"];
NSData *unzipData = [NSData dataWithContentsOfFile:fileContent];
[self.fileManager createFileAtPath:filePath contents:unzipData attributes:nil];
// here we go, unzipping code
ZipArchive *zipArchive = [[ZipArchive alloc] init];
if ([zipArchive UnzipOpenFile:filePath])
{
if ([zipArchive UnzipFileTo:self.documentDirectory overWrite:NO])
{
NSLog(#"Archive unzip success");
[self.fileManager removeItemAtPath:filePath error:NULL];
}
else
{
NSLog(#"Failure to unzip archive");
}
}
else
{
NSLog(#"Failure to open archive");
}
[zipArchive release];
It's really hard to unzip any arbitrary zip file. It's a complex file format, and there are potentially many different compression routines that could have been used internally to the file. Info-ZIP has some freely licencable code to do it (http://www.info-zip.org/UnZip.html) that can be made to work on the iPhone with some hacking, but the API is frankly horrible - it involves passing command-line arguments to a fake 'main' that simulates the running of UnZIP (to be fair that's because their code was never designed to be used like this in the first place, the library functionality was bolted on afterwards).
If you have any control of where the files you're trying to unzip are coming from, I highly recommend using another compression system instead of ZIP. It's flexibility and ubiquity make it great for passing archives of files around in person-to-person, but it's very awkward to automate.
zlib isn't meant to open .zip files, but you are in luck: zlib's contrib directory includes minizip, which is able to use zlib to open .zip files.
It may not be bundled in the SDK, but you can probably use the bundled version of zlib use it. Grab a copy of the zlib source and look in contrib/minizip.
I haven't used the iPhone, but you may want to look at GZIP, which is a very portable open source zip library available for many platforms.
I had some luck testing this on the iPhone simulator:
NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *saveLocation =
[documentsDirectory stringByAppendingString:#"myfile.zip"];
NSFileManager* fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:saveLocation]) {
[fileManager removeItemAtPath:saveLocation error:nil];
}
NSURLRequest *theRequest =
[NSURLRequest requestWithURL:
[NSURL URLWithString:#"http://example.com/myfile.zip"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSData *received =
[NSURLConnection sendSynchronousRequest:theRequest
returningResponse:nil error:nil];
if ([received writeToFile:saveLocation atomically:TRUE]) {
NSString *cmd =
[NSString stringWithFormat:#"unzip \"%#\" -d\"%#\"",
saveLocation, documentsDirectory];
// Here comes the magic...
system([cmd UTF8String]);
}
It looks easier than fiddling about with zlib...

Resources