Technical: QuickTime
Advanced Search
Apple Developer Connection
Member Login Log In | Not a Member? Contact ADC

Finding the file type and extension from the MIME type

Dispatch 5

The use of MIME types has been an increasingly common way to identify the type of a file. Developers using Movie Import and Graphics Import Component need to be able to identify an Import Component from a MIME type. Additionally, it is sometimes useful to be able to determine what MacOS file types or Windows file types correspond to a particular MIME type.

Solution

QuickTime movie import components can implement a component routine, MovieImportGetMIMETypeList, that returns a QTAtomContainer holding MIME-related information. Among the information returned is the MIME type (e.g., "image/gif"), standard file extensions ("gif"), and descriptions (e.g., "GIF Image"). Components that implement this routine set a component flag hasMovieImportMIMEList to indicate this.

The process of mapping from MIME type to import component involves iterating over the movie import components that implement the MovieImportGetMIMETypeList and searching for the particular MIME type in the atom container returned.

Movie import components are registered as associated with either a file's MacOS file type ('GIFf') or a file's extension (e.g., ".gif"). Those registered for file extensions set the movieImportSubTypeIsFileExtension flag in the componentFlags field and set the componentSubType field to the uppercased characters of the extension following the period. For extensions less than 4 characters, the OSType is padded with spaces to the right. So, ".gif" becomes 'GIF '. Movie import components registered for file types have the movieImportSubTypeIsFileExtension flag clear and set the componentSubType to the MacOS file type.

To find all movie import components that import from files, are registered for file types, and that have a MIME type list, the following code will work:

ComponentDescription looking;
Component c = 0;
   
looking.componentType = MovieImportType;
looking.componentSubType = 0; // Any subtype is OK
looking.componentManufacturer = 0; // Any manufacturer is OK
looking.componentFlags = canMovieImportFiles | hasMovieImportMIMEList;
looking.componentFlagsMask = canMovieImportFiles | movieImportSubTypeIsFileExtension | hasMovieImportMIMEList; while( c = FindNextComponent( c, &looking )) { // Check the MIME type list here }

Each iteration will find the next registered Component that meets the conditions.

As each component is found, an application can retrieve the MIME information QTAtomContainer and then search through it for the particular MIME type string. Once the atom container is retrieved, the application should look for all QTAtoms of type kMimeInfoMimeTypeTag and check the contents for the sought MIME type. Because there may be more than one atom of type kMimeInfoMimeTypeTag and there's no requirement that the IDs of these atoms be in a particular order, the code should iterate through each atom using QTFindChildByIndex.

The following code does the trick:

OSErr err = noErr;
QTAtomContainer mimeList = nil;
QTAtom mimeAtom;
short mimeTypeInfoIndex;
   
while( c = FindNextComponent( c, &looking) ) {
  err = MovieImportGetMIMETypeList((MovieImportComponent) c, &mimeList );
  if( err ) continue; // Well, just keep looking
   
  for (mimeTypeInfoIndex = 1;
      mimeTypeInfoIndex <= QTCountChildrenOfType( mimeList,
      kParentAtomIsContainer); mimeTypeInfoIndex++ )
  {
    mimeAtom = QTFindChildByIndex( mimeList, kParentAtomIsContainer,
            kMimeInfoMimeTypeTag, mimeTypeInfoIndex, nil );
   
    // Now, do check if the atom contains the MIME type we're
    // searching for.
  }
   
  QTDisposeAtomContainer( mimeList );
}

With the found atom, it's now possible to perform the comparison with the MIME type being sought. The data for the kMimeInfoMimeTypeTag atom is neither a Pascal nor a C string. The size of the atom is the size in bytes of the text string (or put another way, is the number of ASCII characters). The following code will copy the string into a Pascal string:

Str255 str;
long actualSize;
   
err = QTCopyAtomDataToPtr( mimeList, atom, true,
  sizeof(Str255)-1, &str[1], &actualSize );
if (err) goto bail;
str[0] = actualSize;

Code to convert the text to a C string is straightforward also.

char myCString[256]; // let's use 255 chars + terminator
long actualSize;
   
err = QTCopyAtomDataToPtr( mimeList, atom, true,
        sizeof(myCString)-1, myCString, &actualSize );
if (err) goto bail;
myCString[actualSize] = '\0';

Once the MIME type string is found, we know that the component we retrieved the atom container from is the component that imports the MIME type.

Finding the MacOS file type

The only issue left is determining the MacOS file type. To do this, we retrieve the componentSubType field from a ComponentDescription we fill in using GetComponentInfo on the component c we've already found.

ComponentDescription cd;
   
GetComponentInfo( c, &cd, nil, nil, nil );
fileType = cd.componentSubType;

If we were trying to map MIME types back to file extensions, then the only changes necessary are to set the movieImportSubTypeIsFileExtension component flag in the looking component description and interpret the componentSubType field in the previous code as the file extension.

NOTE: To denote file extensions, the OSType is composed of all the characters following the period, uppercased, and padded with spaces on the right if less than 4 characters. So, .gif maps to 'GIF ' and .jpg maps to 'JPG ' but .html would map to 'HTML'.

MIME types and Graphics Importer Components

Graphics Importer Components can implement a similar call, GraphicsImportGetMIMETypeList, that returns the same kind of atom container. Except for the type of component we search for and the call to MovieImportGetMIMETypeList, all other details - including component flags - are the same. Shown next is code to find Graphics Import Components that implement GraphicsImportGetMIMETypeList.Notice how the componentFlags and componentFlagsMask also use the hasMovieImportMIMEList value.

ComponentDescription looking;
Component c = 0;
   
looking.componentType = GraphicImporterComponentType;
looking.componentSubType = 0;      // Any subtype is OK
looking.componentManufacturer = 0; // Any manufacturer is OK
looking.componentFlags = hasMovieImportMIMEList;
looking.componentFlagsMask = hasMovieImportMIMEList;
   
while( c = FindNextComponent( c, &looking )) {
    // Check the MIME type list here
}

See Also

QuickTime 3 Reference

Inside Macintosh: More Macintosh Toolbox. Component Manager chapter.

Modification History

4/16/98 - clf - First published
Topics
Previous | Next