Recognize my mime type without file extensions on iOS - iphone

I am writing an application that needs to recognize my custom mime type so that when such file is downloaded from a server my application will be launched. I read the great article of Brad on how to write a mime type recognizer under iOS at How do I associate file types with an iPhone application? and it works well if and only if the extensions of the file is also specified in the UTExportedTypeDeclarations / UTTypeTagSpecification section of my plist and the server serves the files with the same extension. If the server serves the file with a different extension or if no extensions are specified in the plist but the mime-type is matching, the following happens:
The browser (or the application that received the file) shows the correct icon of my file type with the correct [Open in myApplication] button but clicking on the button does nothing, my application is not launched and if it is running, no application:openURL:sourceApplication:annotation: message is sent.
Is there any way to write a file type recognizer based only on the mime-type, without a specific file extension?

this has been answered, you'd want to use NSURLRequest, this will allow you to get to the mimeType which you can use to determine the file extension as needed. the full code and additional hints and tips are available at this post:
https://stackoverflow.com/a/1401918/728261

Related

Correctly write my files so they can open as text when my app is not installed

My application writes files known as ".nec", which are simply text files. I'd like them to open in my app if it's on the machine, or open in the default text editor if it's not.
There are surprisingly few examples of how to set these things in Apple's documentation. Do I simply set the MIME type to text/plain, or are there other things I should do as well?
Most computers / mobile devices will use the file extension to determine the file type rather than read the file headers so if you are using a custom file extension then the device won't know which application handles that file.
If you want your applications documents to opened by something outside of your application you will need to use a standard format for your file type.
For textual documents the most common are likely to be .txt, .rtf and .doc
If your documents are just plain text without any formatting (like a log file) then you would be best using .txt, you shouldn't need to change much (if anything) to write in this format.
After a quick google of the file extension .nec I found this:
NEC files are Uncommon Files primarily associated with Unknown Apple II File (found on Golden Orchard Apple II CD Rom).
NEC files are also associated with NEC JIS Encoded File, PIMS Notes for Windows CE Audio Record File (Nacetech Co. Ltd.) and FileViewPro.
If one of your files were to be (for example) emailed to a windows user, Windows would not know that this is a simple text file and would likely prompt the user to search online for a program that handles this file extension.
Not an answer as such, but as to date you don't have one here are some things to explore in the hope it is useful.
The old style type and creator of Mac OS have just about gone, first to replaced by just file extensions, and now there are UTIs.
If you read Apple's Uniform Type Identifier Concepts you will see your app can declare a UTI, say com.markowitz.nectext, which conforms to the standard UTI public.text. Now a UTI helps the Finder (Launch Services) locate the app to open a file, you could explore what happens if there is no such app available but the UTI declares it conforms to public.text.
[Just seen your comment on another answer re: right-clicking. At a guess this would be the UTI above.]
Another avenue to explore, getting into the undocumented side of OS X, is how the Finder's "Get Info" handles setting the "Open With" preference on a file. Try setting a plain text file to open in your app, then use the xattr -l <file> in the Terminal to see what was done. You should see an extended attribute com.apple.LaunchServices.OpenWith whose value looks like some form of plist.
Just remember this is undocumented, the API used by the Finder is private, but then its just an extended attribute...
Have fun.

Reading/writing data to encrypted custom file type

I'd like to create a custom file type, say, .cstm, and be able to create .cstm files on the mac, and read them on the iPhone.
I want the .cstm file to contain XML data. Currently I've got the mac app to successfully make .xml files and the iPhone app to successfully read .xml files, but I'd like to create a proprietary custom file type.
How would I go about doing this? I know how to allow the iPhone app to open a custom file type, but that's as far as I know.
Thanks!
You don't need anything special per se. You can just save and load to the URL with the ctsm extension. To support your app automatically launching as an editor of that extension in OSX, you will want to add an entry to your Info.plist file CFBundleDocumentTypes array entry declaring your app as an editor of that extension
https://developer.apple.com/library/mac/#documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-101685-TPXREF107

Parsing an XML from an e-mail attachment

Is there a way to parse an XML which is attached to an e-mail directly from my app? I have implemented a parser which is reading it from the documents path, but would like to allow the user to be able to directly get it from an e-mail attachment too.
Assuming that you don't want to restrict it to jailbroken files, the easiest way is to register a filetype (Apple docs) with the extension of your data format, so XML if it is a generic XML or some other type if you want to make it specific to your application (and remember if you register XML you will get all XMLs, not just yours), then the user can click on the extension and get the 'Open in....' menu with your application shown in the list.
You need to impliment application:didFinishLaunchingWithOptions:, but it is all in the docs.
A better option would be to give it a filetype that is not commonly used by anything else, so that yours is the only one in the list. I get 4 apps on my iPad for opening XML
There is no way to automatically do it.

(Iphone) associate an App to some file extension to open email attachments in Mail app

I found that some application, like "GoodReader" or "Docs to Go", once installed can be activated using the "Open in" function when opening an email attachment in the Mail App. How to add this function to have my App to be associated to some kind of documents (like pdf) ?
The idea is to have an easy way to get mail attachments to be used directly inside an app.
Edit: I found this document and think it fits my question:
Document Support
An application can now register the file types it supports with the system and receive notifications when a file of the given type needs to be opened. It does this by including the CFBundleDocumentTypes key in its Info.plist file. An application that registers one or more file types may also be expected to open files of those types at some point later. It does this by implementing the
application:didFinishLaunchingWithOptions:method in its application delegate and look for a file
in the UIApplicationLaunchOptionsURLKey key of the provided dictionary.
Complementing the ability to open files of known types is the addition of the
UIDocumentInteractionControllerclass in the UIKit framework. This class provides a user-based
interaction model for managing files that your application does not know how to open. The document
interaction controller provides options for previewing the contents of a file in place or opening it in another
application. Document interaction controllers are particularly useful for email applications or applications
that may download files from the network.
take a look at Custom URL Schemes and UIDocumentInteractionController. If you are looking to add the "open in" menu, the second link is what you need. If you are looking to register as a "PDF reader" this link (scroll to section about registering your app for certain types) should work iPad Programming Guide

How is mime type of an uploaded file determined by browser?

I have a web app where the user needs to upload a .zip file. On the server-side, I am checking the mime type of the uploaded file, to make sure it is application/x-zip-compressed or application/zip.
This worked fine for me on Firefox and IE. However, when a coworker tested it, it failed for him on Firefox (sent mime type was something like "application/octet-stream") but worked on Internet Explorer. Our setups seem to be identical: IE8, FF 3.5.1 with all add-ons disabled, Windows XP SP3, WinRAR installed as native .zip file handler (not sure if that's relevant).
So my question is: How does the browser determine what mime type to send?
Please note: I know that the mime type is sent by the browser and, therefore, unreliable. I am just checking it as a convenience--mainly to give a more friendly error message than the ones you get by trying to open a non-zip file as a zip file, and to avoid loading the (presumably heavy) zip file libraries.
Chrome
Chrome (version 38 as of writing) has 3 ways to determine the MIME type and does so in a certain order. The snippet below is from file src/net/base/mime_util.cc, method MimeUtil::GetMimeTypeFromExtensionHelper.
// We implement the same algorithm as Mozilla for mapping a file extension to
// a mime type. That is, we first check a hard-coded list (that cannot be
// overridden), and then if not found there, we defer to the system registry.
// Finally, we scan a secondary hard-coded list to catch types that we can
// deduce but that we also want to allow the OS to override.
The hard-coded lists come a bit earlier in the file: https://cs.chromium.org/chromium/src/net/base/mime_util.cc?l=170 (kPrimaryMappings and kSecondaryMappings).
An example: when uploading a CSV file from a Windows system with Microsoft Excel installed, Chrome will report this as application/vnd.ms-excel. This is because .csv is not specified in the first hard-coded list, so the browser falls back to the system registry. HKEY_CLASSES_ROOT\.csv has a value named Content Type that is set to application/vnd.ms-excel.
Internet Explorer
Again using the same example, the browser will report application/vnd.ms-excel. I think it's reasonable to assume Internet Explorer (version 11 as of writing) uses the registry. Possibly it also makes use of a hard-coded list like Chrome and Firefox, but its closed source nature makes it hard to verify.
Firefox
As indicated in the Chrome code, Firefox (version 32 as of writing) works in a similar way. Snippet from file uriloader\exthandler\nsExternalHelperAppService.cpp, method nsExternalHelperAppService::GetTypeFromExtension
// OK. We want to try the following sources of mimetype information, in this order:
// 1. defaultMimeEntries array
// 2. User-set preferences (managed by the handler service)
// 3. OS-provided information
// 4. our "extras" array
// 5. Information from plugins
// 6. The "ext-to-type-mapping" category
The hard-coded lists come earlier in the file, somewhere near line 441. You're looking for defaultMimeEntries and extraMimeEntries.
With my current profile, the browser will report text/csv because there's an entry for it in mimeTypes.rdf (item 2 in the list above). With a fresh profile, which does not have this entry, the browser will report application/vnd.ms-excel (item 3 in the list).
Summary
The hard-coded lists in the browsers are pretty limited. Often, the MIME type sent by the browser will be the one reported by the OS. And this is exactly why, as stated in the question, the MIME type reported by the browser is unreliable.
Kip, I spent some time reading RFCs, MSDN and MDN. Here is what I could understand. When a browser encounters a file for upload, it looks at the first buffer of data it receives and then runs a test on it. These tests try to determine if the file is a known mime type or not, and if known mime type it will simply further test it for which known mime type and take action accordingly. I think IE tries to do this first rather than just determining the file type from extension. This page explains this for IE http://msdn.microsoft.com/en-us/library/ms775147%28v=vs.85%29.aspx. For firefox, what I could understand was that it tries to read file info from filesystem or directory entry and then determines the file type. Here is a link for FF https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIFile. I would still like to have more authoritative info on this.
This is probably OS and possibly browser dependent, but on Windows, the MIME type for a given file extension can be found by looking in the registry under HKCR:
For example:
HKEY_CLASSES_ROOT.zip
- ContentType
To go from MIME to file extension, you can look at the keys under
HKEY_CLASSES_ROOT\Mime\Database\Content Type
To get the default extension for a particular MIME type.
While this is not an answer to your question, it does solve the problem you are trying to solve. YMMV.
As you wrote, mime type is not reliable as each browser has its way of determining it. However, browsers send the original name (including extension) of the file. So the best way to deal with the problem is to inspect extension of the file instead of the MIME type.
If you still need the mime type, you can use your own apache's mime.types to determine it server-side.
I agree with johndodo, there are so many variables that make mime types that are sent from browsers unreliable. I would exclude the subtypes that are received and just focus on the type like 'application'. if your app is php based, you can easily do this by using the function explode().
in addition, just check the file extension to make sure it is .zip or any other compression you are looking for!
According to rfc1867 - Form-based file upload in HTML:
Each part should be labelled with an appropriate content-type if the
media type is known (e.g., inferred from the file extension or
operating system typing information) or as application/octet-stream.
So my understanding is, application/octet-stream is kind of like a blanket catch-all identifier if the type cannot be inferred.