Display encrypted file using QuickLook framework or UiDocumentInteractionController

I have a file with the encrypted word / excel / pdf, which I must preview in my iPad application. I understand that you can use QLPreviewController or UiDocumentInteractionController to view these files. I use it very well

- (id <QLPreviewItem>) previewController: (QLPreviewController *) controller previewItemAtIndex: (NSInteger) index { return [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[documents objectAtIndex:index] ofType:nil]]; } 

But the file is encrypted, and when I decrypt it, I get an NSData object. How can I load NSData in any of them.

I also understand that I can very well store NSData as a local file and load it into Preview. But there is a restriction not to store an unencrypted file locally.

If someone has already achieved this and can help me here, we will be very grateful.

Thanks AJ

+6
source share
4 answers

Since you use Quick Look , your options are limited. You must specify Quick Look a NSURL , which means that it must reside on the file system (or the Internet). Fortunately, this should not be a big problem. IOS devices use hardware encryption. When your file is encrypted, only your application has a key to decrypt it. Thus, your file will still be encrypted, but it will also be readable by your application and only by your application.

Here is what you do:

  • Decrypt your file into an NSData object that you already made.

  • Write the file to a folder that will not be downloaded to iCloud or not supported by iTunes. The tmp is probably the best choice. The code looks something like this:

     NSData * data = // Your decrypted file data. NSString * fileName = // Whatever you want to name your file. NSString * path = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName]; NSURL * url = [NSURL URLWithString:path]; NSError * error = nil; BOOL success = [data writeToURL:url options:NSDataWritingFileProtectionComplete error:&error]; if (success) { // Give the URL to Quick Look. } else { // An error happened. See the 'error' object for the details. } 

    At this point, you have an NSURL that you can use with Quick Look . Remember to delete the decrypted file when you are done with it.

There are several things to consider when encrypting to disk:

  • It is only supported on iOS 4.0+.

  • It may not work on "old" devices.

  • The user must have an active access code.

  • If you are using NSDataWritingFileProtectionComplete , the file is not available when the device is locked. If you need to access the file when the application is locked, you should use NSDataWritingFileProtectionCompleteUnlessOpen or NSFileProtectionCompleteUntilFirstUserAuthentication . This will still give you more protection, even if the device is stolen and cracked. However, keep in mind that these encryption options are only available on iOS 5.0+

For more information on disk encryption, see iOS Application Programming Guide

+11
source

After some digging, I found that the QLPreviewController uses the UIWebView under it and calls loadRequest: to load the requested file.

Another way to accomplish what you want is to make a private category on the UIWebView , and use the swizzling method to override the loadRequest: method and instead call the loadData:MIMEType:textEncodingName:baseURL: method.

Beware :

1) In scenarios with low memory (that is, large files), a black screen appears with a โ€œError loading documentโ€ message if this bothers you. (The unhacked QLPreviewController knows how to handle these scripts very well and present a document.)

2) I'm not sure that Apple is going to approve this type of hack, although private APIs are not used here.

the code:

 @implementation UIWebView (QLHack) - (void)MyloadRequest:(NSURLRequest *)request { // Check somehow that it the call of your QLPreviewController // If not, just call the original method. if (!insideQLPreviewController) { // Call original implementation [self MyloadRequest:request]; } else { // Load the real data you want [self loadData:data MIMEType:mimeType textEncodingName:nil baseURL:someURL]; } } + (void)load { method_exchangeImplementations(class_getInstanceMethod(self, @selector(loadRequest:)), class_getInstanceMethod(self, @selector(MyloadRequest:))); } @end 
+1
source

Actually, writing a file to the tmp directory is still unsafe. Another alternative is to use UIWebView with NSURLProtocol and enable decryption of this data on the fly.

+1
source

One way could be.

use Temp Dir, save the file in Temp, make NSURL from this file and Temp display, and then delete this Temp Dir after that.

Thanks.

0
source

Source: https://habr.com/ru/post/906342/


All Articles