Skip to content
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

Can't read file using NSData(contentsOfURL: options:) #293

Open
ravikiran-Conferra opened this issue Oct 20, 2016 · 7 comments
Open

Can't read file using NSData(contentsOfURL: options:) #293

ravikiran-Conferra opened this issue Oct 20, 2016 · 7 comments

Comments

@ravikiran-Conferra
Copy link

ravikiran-Conferra commented Oct 20, 2016

I'm using SSZipArchive to unzip the file from the server. Problem is after unzipping i am not able to read the file i am getting the following error The file “UnZippedFile” couldn’t be opened because you don’t have permission to view it(UnZippedFile is the file name given by me).

Here is my code

func saveFetchedDataAtTempDirectory( dataToSave: NSData)
    {
        let zipFilePath = NSTemporaryDirectory().stringByAppendingString("ZipFile")
        let filePath = NSTemporaryDirectory().stringByAppendingString("UnZippedFile")
        do
        {
            try dataToSave.writeToFile(zipFilePath, options: NSDataWritingOptions.DataWritingFileProtectionMask)
            SSZipArchive.unzipFileAtPath(zipFilePath, toDestination: filePath, overwrite: true, password: nil, progressHandler: { (fileName, fileInfo, num1, num2) in
                print("fileName: \(fileName)\n")
                print("info: \(fileInfo)\n")

                }, completionHandler: { (zippedFilePath, done, error) in
                    if done{
                        print("zippedFilePath: \(zippedFilePath)\n")
                        self.fetchJsonFromPath(filePath)
                    }
                    else
                    {
                        print("Error \(error.localizedDescription)")
                    }
            })

        }
        catch let error as NSError
        {
            print("Writing file failed with error\(error.localizedDescription)")
        }
    }

    func fetchJsonFromPath(path: String)
    {
        do
        { // failing here, the error is coming here
            let data = try NSData(contentsOfURL: NSURL(fileURLWithPath: path), options: NSDataReadingOptions.DataReadingMappedAlways)

            do
            {
                let json = try NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves)

                if let jsonDict : NSDictionary = json as? NSDictionary
                {
                    print("Json Dict \(jsonDict)")
                }

            } catch
            {
                print("Invalid JSON data received")
            }


        } catch let error as NSError {

            print("Fetching file data failed with error : \(error.localizedDescription)")
        }

    }
@zxl777
Copy link

zxl777 commented Jan 25, 2017

I also encountered this problem, please test.

TEST.ZIP

@jhudsonWA
Copy link
Member

Still having an issue? If you are having issues on the NSData() part I'm wondering if you checked to make sure file was at the path. Reopen if still having an issue.

@Coeur
Copy link
Member

Coeur commented Jul 12, 2017

@jhudsonWA I tested the file from @zxl777 and I reproduced the issue:

Error Domain=NSCocoaErrorDomain Code=257 "The file “017573.log” couldn’t be opened because you don’t have permission to view it." UserInfo={NSFilePath=/Users/coeur/Library/Developer/CoreSimulator/Devices/AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA/data/Containers/Data/Application/AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA/Library/Caches/AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA/017573.log, NSUnderlyingError=0x61800005eba0 {Error Domain=NSPOSIXErrorDomain Code=13 "Permission denied"}}

My code was:

        guard let unzipPath = tempUnzipPath() else {
            return
        }
        _ = SSZipArchive.unzipFile(atPath: zipPath, toDestination: unzipPath)
        let items = try! FileManager.default.contentsOfDirectory(atPath: unzipPath)
        do {
            let data = try Data(contentsOf: URL(fileURLWithPath: unzipPath + "/" + items[0]), options: .alwaysMapped)
            print("success: \(data.count)")
        } catch {
            print(error)
        }

@Coeur Coeur reopened this Jul 12, 2017
@Coeur
Copy link
Member

Coeur commented Jul 12, 2017

OK, apparently @zxl777 files inside the archive have no read permission, and our unzipFileAtPath:toDestination: is respecting those permissions. If I use a different tool to uncompress it, like Finder, then permissions are set to read+write.

We respect the original permissions because of SSZipArchive.m line 418:

                            // Set the original permissions on the file
                            uLong permissions = fileInfo.external_fa >> 16;
                            if (permissions != 0) {
                                // Store it into a NSNumber
                                NSNumber *permissionsValue = @(permissions);

                                // Retrieve any existing attributes
                                NSMutableDictionary *attrs = [[NSMutableDictionary alloc] initWithDictionary:[fileManager attributesOfItemAtPath:fullPath error:nil]];

                                // Set the value in the attributes dict
                                attrs[NSFilePosixPermissions] = permissionsValue;

                                // Update attributes
                                if ([fileManager setAttributes:attrs ofItemAtPath:fullPath error:nil] == NO) {
                                    // Unable to set the permissions attribute
                                    NSLog(@"[SSZipArchive] Failed to set attributes - whilst setting permissions");
                                }

#if !__has_feature(objc_arc)
                                [attrs release];
#endif
                            }

@Coeur
Copy link
Member

Coeur commented Jul 12, 2017

@jhudsonWA maybe we could provide an option that will set all uncompressed files to read+write, like Archive Utility is doing? See #348

@Coeur
Copy link
Member

Coeur commented Jul 12, 2017

@ravikiran-Conferra @zxl777 I successfully workaround the permissions with:

        do {
            // Retrieve any existing attributes
            var attrs = try FileManager.default.attributesOfItem(atPath: fullPath)
            let existing = (attrs as NSDictionary).filePosixPermissions()
            // Set the read+write value in the attributes dict
            attrs[.posixPermissions] = existing | 0b110000000
            // Update attributes
            try FileManager.default.setAttributes(attrs, ofItemAtPath: fullPath)
            
            let data = try Data(contentsOf: URL(fileURLWithPath: fullPath, isDirectory: false), options: .alwaysMapped)
            print("success: \(data.count)")
        } catch {
            print(error)
        }

I've also post it as a StackOverflow answer on https://stackoverflow.com/a/45048822/1033581

@jhudsonWA
Copy link
Member

@Coeur I like the idea of providing an option/override with the default add read+write, lets add it for 2.0

@jhudsonWA jhudsonWA added this to the 2.0 milestone Jul 12, 2017
@jhudsonWA jhudsonWA removed this from the 2.1 milestone Sep 29, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants