diff --git a/KSUniformType.h b/KSUniformType.h new file mode 100644 index 0000000..745f730 --- /dev/null +++ b/KSUniformType.h @@ -0,0 +1,28 @@ +// +// KSUniformType.h +// Sandvox +// +// Created by Mike Abdullah on 01/04/2012. +// Copyright (c) 2012 Karelia Software. All rights reserved. +// + +#import + +@interface KSUniformType : NSObject + ++ (NSString *)MIMETypeForType:(NSString *)aUTI; ++ (NSString *)OSTypeStringForType:(NSString *)aUTI; ++ (OSType)OSTypeForType:(NSString *)aUTI; + +// Unlike -typeOfFile:error: this will fallback to guessing from the path extension ++ (NSString *)typeOfFileAtURL:(NSURL *)url; + ++ (NSString *)typeForFilenameExtension:(NSString *)anExtension; ++ (NSString *)typeForMIMEType:(NSString *)aMIMEType; ++ (NSString *)typeForOSTypeString:(NSString *)aFileType; ++ (NSString *)typeForOSType:(OSType)anOSType; + ++ (BOOL)type:(NSString *)type1 isEqualToType:(NSString *)anotherUTI; ++ (BOOL)type:(NSString *)type conformsToOneOfTypes:(NSArray *)types; + +@end diff --git a/KSUniformType.m b/KSUniformType.m new file mode 100644 index 0000000..df8eac3 --- /dev/null +++ b/KSUniformType.m @@ -0,0 +1,195 @@ +// +// KSUniformType.m +// Sandvox +// +// Created by Mike Abdullah on 01/04/2012. +// Copyright (c) 2012 Karelia Software. All rights reserved. +// + +#import "KSUniformType.h" + +@implementation KSUniformType + ++ (NSString *)MIMETypeForType:(NSString *)aUTI; +{ + NSString *result = NSMakeCollectable(UTTypeCopyPreferredTagWithClass((CFStringRef)aUTI, kUTTagClassMIMEType)); + [result autorelease]; + + // BUGSID:37340 OS X doesn't know the MIME type for .m4a files, so we're hardcoding it here. + if (!result) + { + if ([aUTI isEqualToString:(NSString *)kUTTypeMPEG4Audio]) + { + result = @"audio/x-m4a"; + } + else if ([aUTI isEqualToString:(NSString *)kUTTypeICO]) + { + result = @"image/vnd.microsoft.icon"; + } + // Apparently .m4v com.apple.protected-mpeg-4-video is also not known. + else if ([aUTI isEqualToString:@"com.apple.protected-mpeg-4-video"]) + { + result = @"video/x-m4v"; + } + else + { + result = @"application/octet-stream"; + } + } + + NSAssert(result, @"Should always fall back to raw data MIME type at the least"); + return result; +} + ++ (NSString *)OSTypeStringForType:(NSString *)aUTI +{ + NSString *result = NSMakeCollectable(UTTypeCopyPreferredTagWithClass( + (CFStringRef)aUTI, + kUTTagClassOSType + )); + return [result autorelease]; +} + ++ (OSType)OSTypeForType:(NSString *)aUTI +{ + return UTGetOSTypeFromString((CFStringRef)[self OSTypeStringForType:aUTI]); +} + ++ (NSString *)typeOfFileAtURL:(NSURL *)url; +{ + NSString *result = nil; + FSRef fileRef; + Boolean isDir; + + if (FSPathMakeRef((const UInt8 *)[[url path] fileSystemRepresentation], &fileRef, &isDir) == noErr) + { + // get the content type (UTI) of this file + CFStringRef uti; + if (LSCopyItemAttribute(&fileRef, kLSRolesViewer, kLSItemContentType, (CFTypeRef*)&uti)==noErr) + { + result = [NSMakeCollectable(uti) autorelease]; // I want an autoreleased copy of this. + } + } + + // check extension if we can't find the actual file + if (nil == result) + { + NSString *extension = [url pathExtension]; + if ( (nil != extension) && ![extension isEqualToString:@""] ) + { + result = [self typeForFilenameExtension:extension]; + } + } + + // if no extension or no result, check file type + if ( nil == result || [result isEqualToString:(NSString *)kUTTypeData]) + { + NSString *fileType = NSHFSTypeOfFile([url path]); + if (6 == [fileType length]) + { + fileType = [fileType substringWithRange:NSMakeRange(1,4)]; + } + result = [self typeForOSTypeString:fileType]; + if ([result hasPrefix:@"dyn."]) + { + result = nil; // reject a dynamic type if it tries that. + } + } + + if (nil == result) // not found, figure out if it's a directory or not + { + BOOL isDirectory; + if ( [[NSFileManager defaultManager] fileExistsAtPath:[url path] isDirectory:&isDirectory] ) + { + result = isDirectory ? (NSString *)kUTTypeDirectory : (NSString *)kUTTypeData; + } + } + + // Will return nil if file doesn't exist. + + return result; +} + ++ (NSString *)typeForFilenameExtension:(NSString *)anExtension; +{ + NSString *UTI = nil; + + if ([anExtension isEqualToString:@"m4v"]) + { + // Hack, since we already have this UTI defined in the system, I don't think I can add it to the plist. + UTI = (NSString *)kUTTypeMPEG4; + } + else + { + UTI = NSMakeCollectable(UTTypeCreatePreferredIdentifierForTag( + kUTTagClassFilenameExtension, + (CFStringRef)anExtension, + NULL + )); + [UTI autorelease]; + } + + // If we don't find it, add an entry to the info.plist of the APP, + // along the lines of what is documented here: + // http://developer.apple.com/documentation/Carbon/Conceptual/understanding_utis/understand_utis_conc/chapter_2_section_4.html + // A good starting point for informal ones is: + // http://www.huw.id.au/code/fileTypeIDs.html + + return UTI; +} + ++ (NSString *)typeForMIMEType:(NSString *)aMIMEType +{ + if ([aMIMEType isEqualToString:@"image/vnd.microsoft.icon"]) + { + return (NSString *)kUTTypeICO; + } + else + { + NSString *result = NSMakeCollectable(UTTypeCreatePreferredIdentifierForTag( + kUTTagClassMIMEType, + (CFStringRef)aMIMEType, + kUTTypeData + )); + return [result autorelease]; + } +} + ++ (NSString *)typeForOSTypeString:(NSString *)aFileType; +{ + NSString *result = NSMakeCollectable(UTTypeCreatePreferredIdentifierForTag( + kUTTagClassOSType, + (CFStringRef)aFileType, + NULL + )); + return [result autorelease]; +} + ++ (NSString *)typeForOSType:(OSType)anOSType; +{ + NSString *OSTypeAsString = NSMakeCollectable(UTCreateStringForOSType(anOSType)); + NSString *result = [self typeForOSTypeString:OSTypeAsString]; + [OSTypeAsString release]; + return result; +} + ++ (BOOL)type:(NSString *)type1 isEqualToType:(NSString *)anotherUTI; +{ + return UTTypeEqual ( + (CFStringRef)type1, + (CFStringRef)anotherUTI + ); +} + + ++ (BOOL)type:(NSString *)type conformsToOneOfTypes:(NSArray *)types; +{ + for (NSString *aType in types) + { + if ([[NSWorkspace sharedWorkspace] type:type conformsToType:aType]) return YES; + } + + return NO; +} + +@end diff --git a/KSWorkspaceUtilities.h b/KSWorkspaceUtilities.h index 4ac4c97..2183731 100644 --- a/KSWorkspaceUtilities.h +++ b/KSWorkspaceUtilities.h @@ -14,24 +14,6 @@ @interface NSWorkspace (KSWorkspaceUtilities) -#pragma mark Manipulating Uniform Type Identifier Information - -- (NSString *)ks_MIMETypeForType:(NSString *)aUTI; -- (NSString *)ks_OSTypeStringForType:(NSString *)aUTI; -- (OSType)ks_OSTypeForType:(NSString *)aUTI; - -// Unlike -typeOfFile:error: this will fallback to guessing from the path extension -- (NSString *)ks_typeOfFileAtURL:(NSURL *)url; - -- (NSString *)ks_typeForFilenameExtension:(NSString *)anExtension; -- (NSString *)ks_typeForMIMEType:(NSString *)aMIMEType; -- (NSString *)ks_typeForOSTypeString:(NSString *)aFileType; -- (NSString *)ks_typeForOSType:(OSType)anOSType; - -- (BOOL)ks_type:(NSString *)type1 isEqualToType:(NSString *)anotherUTI; -- (BOOL)ks_type:(NSString *)type conformsToOneOfTypes:(NSArray *)types; - - #pragma mark Requesting Information - (NSImage *)ks_iconForType:(NSString *)aUTI; diff --git a/KSWorkspaceUtilities.m b/KSWorkspaceUtilities.m index e501ec4..a77a852 100644 --- a/KSWorkspaceUtilities.m +++ b/KSWorkspaceUtilities.m @@ -13,190 +13,6 @@ @implementation NSWorkspace (KSWorkspaceUtilities) -#pragma mark Manipulating Uniform Type Identifier Information - -- (NSString *)ks_MIMETypeForType:(NSString *)aUTI; -{ - NSString *result = NSMakeCollectable(UTTypeCopyPreferredTagWithClass((CFStringRef)aUTI, kUTTagClassMIMEType)); - [result autorelease]; - - // BUGSID:37340 OS X doesn't know the MIME type for .m4a files, so we're hardcoding it here. - if (!result) - { - if ([aUTI isEqualToString:(NSString *)kUTTypeMPEG4Audio]) - { - result = @"audio/x-m4a"; - } - else if ([aUTI isEqualToString:(NSString *)kUTTypeICO]) - { - result = @"image/vnd.microsoft.icon"; - } - // Apparently .m4v com.apple.protected-mpeg-4-video is also not known. - else if ([aUTI isEqualToString:@"com.apple.protected-mpeg-4-video"]) - { - result = @"video/x-m4v"; - } - else - { - result = @"application/octet-stream"; - } - } - - NSAssert(result, @"Should always fall back to raw data MIME type at the least"); - return result; -} - -- (NSString *)ks_OSTypeStringForType:(NSString *)aUTI -{ - NSString *result = NSMakeCollectable(UTTypeCopyPreferredTagWithClass( - (CFStringRef)aUTI, - kUTTagClassOSType - )); - return [result autorelease]; -} - -- (OSType)ks_OSTypeForType:(NSString *)aUTI -{ - return UTGetOSTypeFromString((CFStringRef)[self ks_OSTypeStringForType:aUTI]); -} - -- (NSString *)ks_typeOfFileAtURL:(NSURL *)url; -{ - NSString *result = nil; - FSRef fileRef; - Boolean isDir; - - if (FSPathMakeRef((const UInt8 *)[[url path] fileSystemRepresentation], &fileRef, &isDir) == noErr) - { - // get the content type (UTI) of this file - CFStringRef uti; - if (LSCopyItemAttribute(&fileRef, kLSRolesViewer, kLSItemContentType, (CFTypeRef*)&uti)==noErr) - { - result = [NSMakeCollectable(uti) autorelease]; // I want an autoreleased copy of this. - } - } - - // check extension if we can't find the actual file - if (nil == result) - { - NSString *extension = [url ks_pathExtension]; - if ( (nil != extension) && ![extension isEqualToString:@""] ) - { - result = [self ks_typeForFilenameExtension:extension]; - } - } - - // if no extension or no result, check file type - if ( nil == result || [result isEqualToString:(NSString *)kUTTypeData]) - { - NSString *fileType = NSHFSTypeOfFile([url path]); - if (6 == [fileType length]) - { - fileType = [fileType substringWithRange:NSMakeRange(1,4)]; - } - result = [self ks_typeForOSTypeString:fileType]; - if ([result hasPrefix:@"dyn."]) - { - result = nil; // reject a dynamic type if it tries that. - } - } - - if (nil == result) // not found, figure out if it's a directory or not - { - BOOL isDirectory; - if ( [[NSFileManager defaultManager] fileExistsAtPath:[url path] isDirectory:&isDirectory] ) - { - result = isDirectory ? (NSString *)kUTTypeDirectory : (NSString *)kUTTypeData; - } - } - - // Will return nil if file doesn't exist. - - return result; -} - -- (NSString *)ks_typeForFilenameExtension:(NSString *)anExtension; -{ - NSString *UTI = nil; - - if ([anExtension isEqualToString:@"m4v"]) - { - // Hack, since we already have this UTI defined in the system, I don't think I can add it to the plist. - UTI = (NSString *)kUTTypeMPEG4; - } - else - { - UTI = NSMakeCollectable(UTTypeCreatePreferredIdentifierForTag( - kUTTagClassFilenameExtension, - (CFStringRef)anExtension, - NULL - )); - [UTI autorelease]; - } - - // If we don't find it, add an entry to the info.plist of the APP, - // along the lines of what is documented here: - // http://developer.apple.com/documentation/Carbon/Conceptual/understanding_utis/understand_utis_conc/chapter_2_section_4.html - // A good starting point for informal ones is: - // http://www.huw.id.au/code/fileTypeIDs.html - - return UTI; -} - -- (NSString *)ks_typeForMIMEType:(NSString *)aMIMEType -{ - if ([aMIMEType isEqualToString:@"image/vnd.microsoft.icon"]) - { - return (NSString *)kUTTypeICO; - } - else - { - NSString *result = NSMakeCollectable(UTTypeCreatePreferredIdentifierForTag( - kUTTagClassMIMEType, - (CFStringRef)aMIMEType, - kUTTypeData - )); - return [result autorelease]; - } -} - -- (NSString *)ks_typeForOSTypeString:(NSString *)aFileType; -{ - NSString *result = NSMakeCollectable(UTTypeCreatePreferredIdentifierForTag( - kUTTagClassOSType, - (CFStringRef)aFileType, - NULL - )); - return [result autorelease]; -} - -- (NSString *)ks_typeForOSType:(OSType)anOSType; -{ - NSString *OSTypeAsString = NSMakeCollectable(UTCreateStringForOSType(anOSType)); - NSString *result = [self ks_typeForOSTypeString:OSTypeAsString]; - [OSTypeAsString release]; - return result; -} - -- (BOOL)ks_type:(NSString *)type1 isEqualToType:(NSString *)anotherUTI; -{ - return UTTypeEqual ( - (CFStringRef)type1, - (CFStringRef)anotherUTI - ); -} - - -- (BOOL)ks_type:(NSString *)type conformsToOneOfTypes:(NSArray *)types; -{ - for (NSString *aType in types) - { - if ([self type:type conformsToType:aType]) return YES; - } - - return NO; -} - #pragma mark Requesting Information - (NSImage *)ks_iconForType:(NSString *)aUTI;