diff --git a/.gitignore b/.gitignore index d35929a..c499f18 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ config.status configure version.c *.o +duti diff --git a/duti.c b/duti.c index 464d327..e23a418 100644 --- a/duti.c +++ b/duti.c @@ -28,7 +28,7 @@ struct roles rtm[] = { main( int ac, char *av[] ) { struct stat st; - int c, err = 0; + int c, rc, err = 0; int set = 0; int ( *handler_f )( char * ); char *path = NULL; @@ -37,13 +37,28 @@ main( int ac, char *av[] ) extern int optind; extern char *optarg; - while (( c = getopt( ac, av, "d:e:l:hsu:Vvx:" )) != -1 ) { + while (( c = getopt( ac, av, "b:d:e:hl:o:st:u:Vvx:" )) != -1 ) { switch ( c ) { + case 'b': /* show bundle URLs for identifier */ + rc = duti_urls_for_bundle( optarg ); + if ( rc ) { + exit( 0 ); + } + break; + case 'd': /* show default handler for UTI */ - return( uti_handler_show( optarg, 0 )); + rc = uti_handler_show( optarg, 0 ); + if ( rc ) { + exit( 0 ); + } + break; case 'e': /* UTI declarations for extension */ - return( duti_utis_for_extension( optarg )); + rc = duti_utis_for_extension( optarg ); + if ( rc ) { + exit( 0 ); + } + break; case 'h': /* help */ default: @@ -51,28 +66,57 @@ main( int ac, char *av[] ) break; case 'l': /* list all handlers for UTI */ - return( uti_handler_show( optarg, 1 )); + rc = uti_handler_show( optarg, 1 ); + if ( rc ) { + exit( 0 ); + } + break; + + case 'o': /* show all bundles able to open path */ + rc = duti_urls_for_url( optarg ); + if ( rc ) { + exit( 0 ); + } + break; case 's': /* set handler */ set = 1; break; + case 't': /* info for type */ + rc = duti_default_app_for_type( optarg ); + if ( rc ) { + exit( 0 ); + } + break; + case 'u': /* UTI declarations */ - return( duti_utis( optarg )); + rc = duti_utis( optarg ); + if ( rc ) { + exit( 0 ); + } + break; case 'V': /* version */ printf( "%s\n", duti_version ); - exit( 0 ); + break; case 'v': /* verbose */ verbose = 1; break; case 'x': /* info for extension */ - return( duti_default_app_for_extension( optarg )); + rc = duti_default_app_for_extension( optarg ); + if ( rc ) { + exit( 0 ); + } } } + if ( !set && !err) { + exit( 0 ); + } + nroles = sizeof( rtm ) / sizeof( rtm[ 0 ] ); switch (( ac - optind )) { @@ -109,11 +153,18 @@ main( int ac, char *av[] ) } if ( err ) { - fprintf( stderr, "usage: %s [ -hvV ] [ -d uti ] [ -l uti ] " - "[ settings_path ]\n", av[ 0 ] ); - fprintf( stderr, "usage: %s -s bundle_id { uti | url_scheme } " - "[ role ]\n", av[ 0 ] ); - fprintf( stderr, "usage: %s -x extension\n", av[ 0 ] ); + fprintf( stderr, "usage: %s [ -hvV ] [ -b bundle_id ] [ -d uti ] [ -e ext ] [ -l uti ] [ -o path ] [ -t type ] [ -u uti ] [ -x ext ]" + "[ settings_path ]\n", av[ 0 ] ); + fprintf( stderr, " -b print the URLs to all bundles with the identifier\n" ); + fprintf( stderr, " -d print the default handler for the UTI\n" ); + fprintf( stderr, " -e print the UTI declaration for the file extension\n" ); + fprintf( stderr, " -l print the handlers for the UTI\n" ); + fprintf( stderr, " -o print the URLs for all bundles able to open path\n" ); + fprintf( stderr, " -t print the UTI declaration for the file type\n" ); + fprintf( stderr, " -u print the UTI declaration for the UTI\n" ); + fprintf( stderr, " -x print bundle claiming the file extension\n" ); + fprintf( stderr, "usage: %s -s bundle_id url_scheme\n", av[ 0 ] ); + fprintf( stderr, "usage: %s -s bundle_id uti role\n", av[ 0 ] ); exit( 1 ); } diff --git a/handler.c b/handler.c index 23c6a3a..d80a067 100644 --- a/handler.c +++ b/handler.c @@ -34,10 +34,10 @@ duti_is_conformant_uti( CFStringRef uti ) */ if ( UTTypeConformsTo( uti, kUTTypeItem ) || - UTTypeConformsTo( uti, kUTTypeContent ) || - UTTypeConformsTo( uti, kUTTypeMessage ) || - UTTypeConformsTo( uti, kUTTypeContact ) || - UTTypeConformsTo( uti, kUTTypeArchive )) { + UTTypeConformsTo( uti, kUTTypeContent ) || + UTTypeConformsTo( uti, kUTTypeMessage ) || + UTTypeConformsTo( uti, kUTTypeContact ) || + UTTypeConformsTo( uti, kUTTypeArchive )) { return( 1 ); } @@ -65,6 +65,16 @@ set_uti_handler( CFStringRef bid, CFStringRef type, LSRolesMask mask ) fprintf( stderr, "%s does not conform to any UTI hierarchy\n", ct ); return( 1 ); } + + /* don't set handler if it's already set */ + CFStringRef cur_bid = LSCopyDefaultRoleHandlerForContentType(type, mask); + if (cur_bid) { + if (CFStringCompare(bid, cur_bid, kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + CFRelease(cur_bid); + return noErr; + } + CFRelease(cur_bid); + } if ( verbose ) { printf( "setting %s as handler for %s\n", cb, ct ); @@ -92,6 +102,16 @@ set_url_handler( CFStringRef bid, CFStringRef url_scheme ) if ( cf2c( url_scheme, cu, sizeof( cu )) != 0 ) { strlcpy( cu, "url_scheme", sizeof( cu )); } + + /* don't set handler if it's already set */ + CFStringRef cur_bid = LSCopyDefaultHandlerForURLScheme(url_scheme); + if (cur_bid) { + if (CFStringCompare(bid, cur_bid, kCFCompareCaseInsensitive) == kCFCompareEqualTo) { + CFRelease(cur_bid); + return noErr; + } + CFRelease(cur_bid); + } if ( verbose ) { printf( "setting %s as handler for %s:// URLs\n", cb, cu ); @@ -360,8 +380,10 @@ dirsethandler( char *dirpath ) uti_handler_show( char *uti, int showall ) { CFArrayRef cfhandlers = NULL; + CFArrayRef cfschemes = NULL; CFStringRef cfuti = NULL; CFStringRef cfhandler = NULL; + CFStringRef cfscheme = NULL; char dh[ MAXPATHLEN ]; int rc = 0; int count, i; @@ -376,64 +398,101 @@ uti_handler_show( char *uti, int showall ) } if ( showall ) { - if (( cfhandlers = LSCopyAllRoleHandlersForContentType( - cfuti, kLSRolesAll )) == NULL ) { - if (( cfhandlers = LSCopyAllHandlersForURLScheme( - cfuti )) == NULL ) { - fprintf( stderr, "%s: no handlers\n", uti ); - rc = 1; - goto uti_show_done; - } + cfhandlers = LSCopyAllRoleHandlersForContentType( cfuti, kLSRolesAll ); + cfschemes = LSCopyAllHandlersForURLScheme( cfuti ); + if (( cfhandlers == NULL ) && ( cfschemes == NULL )) { + fprintf( stderr, "%s: no handlers\n", uti ); + rc = 1; + goto uti_show_done; } - if ( verbose ) { - printf( "All handlers for %s:\n", uti ); - } + if ( cfhandlers ) { + if ( verbose ) { + printf( "All handlers for %s:\n", uti ); + } - count = CFArrayGetCount( cfhandlers ); - for ( i = 0; i < count; i++ ) { - cfhandler = CFArrayGetValueAtIndex( cfhandlers, i ); - if ( cf2c( cfhandler, dh, sizeof( dh )) != 0 ) { - rc = 2; - continue; + count = CFArrayGetCount( cfhandlers ); + for ( i = 0; i < count; i++ ) { + cfhandler = CFArrayGetValueAtIndex( cfhandlers, i ); + if ( cf2c( cfhandler, dh, sizeof( dh )) != 0 ) { + rc = 2; + continue; + } + printf( "%s\n", dh ); + memset( dh, 0, sizeof( dh )); } - printf( "%s\n", dh ); - memset( dh, 0, sizeof( dh )); + + cfhandler = NULL; } + + if ( cfschemes ) { + if ( verbose ) { + printf( "All handlers for scheme %s:\n", uti ); + } + + count = CFArrayGetCount( cfschemes ); + for ( i = 0; i < count; i++ ) { + cfscheme = CFArrayGetValueAtIndex( cfschemes, i ); + if ( cf2c( cfscheme, dh, sizeof( dh )) != 0 ) { + rc = 2; + continue; + } + printf( "%s\n", dh ); + memset( dh, 0, sizeof( dh )); + } - cfhandler = NULL; + cfscheme = NULL; + } } else { - if (( cfhandler = LSCopyDefaultRoleHandlerForContentType( - cfuti, kLSRolesAll )) == NULL ) { - if (( cfhandler = LSCopyDefaultHandlerForURLScheme( - cfuti )) == NULL ) { - fprintf( stderr, "%s: no default handler\n", uti ); - rc = 1; + cfhandler = LSCopyDefaultRoleHandlerForContentType( cfuti, kLSRolesAll ); + cfscheme = LSCopyDefaultHandlerForURLScheme( cfuti ); + if (( cfhandler == NULL ) && ( cfscheme == NULL )) { + fprintf( stderr, "%s: no default handler\n", uti ); + rc = 1; + goto uti_show_done; + } + + if ( cfhandler ) { + if ( cf2c( cfhandler, dh, MAXPATHLEN ) != 0 ) { + rc = 2; goto uti_show_done; } - } - if ( cf2c( cfhandler, dh, MAXPATHLEN ) != 0 ) { - rc = 2; - goto uti_show_done; + if ( verbose ) { + printf( "Default handler for UTI %s: ", uti ); + } + printf( "%s\n", dh ); } - if ( verbose ) { - printf( "Default handler for %s: ", uti ); + if ( cfscheme ) { + if ( cf2c( cfscheme, dh, MAXPATHLEN ) != 0 ) { + rc = 2; + goto uti_show_done; + } + + if ( verbose ) { + printf( "Default handler for scheme %s: ", uti ); + } + printf( "%s\n", dh ); } - printf( "%s\n", dh ); } uti_show_done: if ( cfhandlers ) { CFRelease( cfhandlers ); } + if ( cfschemes ) { + CFRelease( cfschemes ); + } if ( cfuti ) { CFRelease( cfuti ); } if ( cfhandler ) { CFRelease( cfhandler ); } + if ( cfscheme ) { + CFRelease( cfscheme ); + } return( rc ); } @@ -555,10 +614,12 @@ duti_default_app_for_extension( char *ext ) { CFDictionaryRef cf_info_dict = NULL; CFStringRef cf_ext = NULL; + CFStringRef cf_uti = NULL; CFStringRef cf_app_bundle_id = NULL; CFStringRef cf_app_name = NULL; + CFStringRef cf_error_description = NULL; CFURLRef cf_app_url = NULL; - OSStatus err; + CFErrorRef cf_error = NULL; char *rext; char tmp[ MAXPATHLEN ]; int rc = 2; @@ -576,27 +637,44 @@ duti_default_app_for_extension( char *ext ) return( rc ); } - err = LSGetApplicationForInfo( kLSUnknownType, kLSUnknownCreator, cf_ext, - kLSRolesAll, NULL, &cf_app_url ); - if ( err != noErr ) { - fprintf( stderr, "Failed to get default application for " - "extension \'%s\'\n", rext ); + cf_uti = UTTypeCreatePreferredIdentifierForTag( kUTTagClassFilenameExtension, cf_ext, NULL ); + if ( cf_uti == NULL ) { + fprintf( stderr, "Failed to get default application for extension \'%s\'\n", rext ); + goto duti_extension_cleanup; + } + cf_app_url = UTTypeCopyDeclaringBundleURL( cf_uti ); + if ( cf_app_url == NULL ) { + fprintf( stderr, "Failed to find bundle for extension \'%s\'\n", rext ); goto duti_extension_cleanup; } - err = LSCopyDisplayNameForURL( cf_app_url, &cf_app_name ); - if ( err != noErr ) { - fprintf( stderr, "Failed to get display name\n" ); + if ( !CFURLCopyResourcePropertyForKey( cf_app_url, kCFURLLocalizedNameKey, &cf_app_name, &cf_error )) { + cf_error_description = CFErrorCopyDescription( cf_error ); + if ( cf_error_description != NULL ) { + if ( cf2c( cf_error_description, tmp, sizeof( tmp )) != 0 ) { + goto duti_extension_cleanup; + } + fprintf( stderr, "Failed to get display name: %s\n", tmp ); + } goto duti_extension_cleanup; } + if ( verbose ) { + printf( "bundle claiming the file extension %s\n", ext ); + } if ( cf2c( cf_app_name, tmp, sizeof( tmp )) != 0 ) { goto duti_extension_cleanup; } + if ( verbose ) { + printf( "Name: " ); + } printf( "%s\n", tmp ); if ( cfurl2path( cf_app_url, tmp, sizeof( tmp )) != 0 ) { goto duti_extension_cleanup; } + if ( verbose ) { + printf( "Path: " ); + } printf( "%s\n", tmp ); cf_info_dict = CFBundleCopyInfoDictionaryInDirectory( cf_app_url ); @@ -615,6 +693,9 @@ duti_default_app_for_extension( char *ext ) if ( cf2c( cf_app_bundle_id, tmp, sizeof( tmp )) != 0 ) { goto duti_extension_cleanup; } + if ( verbose ) { + printf( " ID: " ); + } printf( "%s\n", tmp ); /* success */ @@ -624,50 +705,249 @@ duti_default_app_for_extension( char *ext ) if ( cf_ext != NULL ) { CFRelease( cf_ext ); } + if ( cf_uti != NULL ) { + CFRelease( cf_uti ); + } if ( cf_app_url != NULL ) { CFRelease( cf_app_url ); } if ( cf_info_dict != NULL ) { CFRelease( cf_info_dict ); } + if ( cf_error_description != NULL ) { + CFRelease( cf_error_description ); + } if ( cf_app_name != NULL ) { CFRelease( cf_app_name ); } + if ( cf_error != NULL ) { + CFRelease( cf_error ); + } return( rc ); } -int -duti_utis( char * uti ) { - CFStringRef cf_uti_identifier = NULL; - CFStringRef cf_uti_description = NULL; - CFDictionaryRef cf_uti_declaration = NULL; + int +duti_default_app_for_type( char *osType ) { + union { + OSType typeAsOSType; + char typeAsString[4]; + } u; + CFStringRef cf_type = NULL; + CFArrayRef cf_array = NULL; + CFStringRef cf_uti_description = NULL; + CFDictionaryRef cf_uti_declaration = NULL; + CFIndex index; + CFIndex count; char tmp[ MAXPATHLEN ]; int rc = 2; - if ( uti == NULL ) { - fprintf( stderr, "Invalid UTI.\n" ); - return( rc ); - } + u.typeAsOSType = 0; + strncpy( u.typeAsString, osType, sizeof( u.typeAsOSType )); + cf_type = UTCreateStringForOSType( htonl( u.typeAsOSType )); - if ( c2cf( uti, &cf_uti_identifier ) != 0 ) { - return( rc ); - } + cf_array = UTTypeCreateAllIdentifiersForTag(kUTTagClassOSType, cf_type, nil); + for (index = 0, count = CFArrayGetCount(cf_array); index < count; index++) { + CFStringRef cf_uti_identifier = CFArrayGetValueAtIndex(cf_array, index); + if ( cf2c( cf_uti_identifier, tmp, sizeof( tmp )) != 0 ) { + goto duti_default_app_for_type_cleanup; + } + printf( "identifier: %s\n", tmp ); cf_uti_description = UTTypeCopyDescription(cf_uti_identifier); if ( cf2c( cf_uti_description, tmp, sizeof( tmp )) != 0 ) { - goto duti_utis_cleanup; + goto duti_default_app_for_type_cleanup; } CFRelease(cf_uti_description); cf_uti_description = NULL; printf( "description: %s\n", tmp ); - + cf_uti_declaration = UTTypeCopyDeclaration(cf_uti_identifier); printf( "declaration: {\n" ); CFDictionaryApplyFunction(cf_uti_declaration, dump_cf_dictionary, "\t"); CFRelease(cf_uti_declaration); cf_uti_declaration = NULL; printf( "}\n" ); + } - /* success */ + /* success */ + rc = 0; + +duti_default_app_for_type_cleanup: + if ( cf_type != NULL ) { + CFRelease( cf_type ); + } + return( rc ); +} + + int +duti_urls_for_url( char *pathOrURL ) { + char *url; + CFURLRef cf_url = NULL; + CFURLRef cf_url_default = NULL; + CFURLRef cf_other_url = NULL; + CFArrayRef cf_urls = NULL; + CFStringRef cf_url_path = NULL; + CFStringRef cf_error_description = NULL; + CFErrorRef cf_error = NULL; + CFIndex count; + CFIndex index; + char tmp[ MAXPATHLEN ]; + int rc = 2; + + url = pathOrURL; + if ( strncmp( pathOrURL, "file://", 7 ) != 0 ) { + url = tmp; + strncpy( url, "file://", MAXPATHLEN ); + if ( strncmp( pathOrURL, "/", 1 ) != 0 ) { + getcwd( url + 7, MAXPATHLEN - 7 ); + url[MAXPATHLEN - 1] = '\0'; + } + count = strlen( url ); + strncat( url, "/", MAXPATHLEN - count ); + if ( count < MAXPATHLEN ) { + count++; + } + strncpy( url + count, pathOrURL, MAXPATHLEN - count ); + url[MAXPATHLEN - 1] = '\0'; + } + + cf_url = CFURLCreateAbsoluteURLWithBytes(kCFAllocatorDefault, (UInt8*) url, strlen(url), kCFStringEncodingUTF8, NULL, TRUE ); + if ( cf_url == NULL ) { + goto duti_urls_for_url_cleanup; + } + + cf_url_default = LSCopyDefaultApplicationURLForURL(cf_url, kLSRolesAll, &cf_error); + if ( cf_url_default == NULL ) { + cf_error_description = CFErrorCopyDescription( cf_error ); + if ( cf_error_description != NULL ) { + if ( cf2c( cf_error_description, tmp, sizeof( tmp )) != 0 ) { + goto duti_urls_for_url_cleanup; + } + fprintf( stderr, "%s\n", tmp ); + } + goto duti_urls_for_url_cleanup; + } + + cf_url_path = CFURLGetString( cf_url_default ); + if ( cf2c( cf_url_path, tmp, sizeof( tmp )) != 0 ) { + goto duti_urls_for_url_cleanup; + } + printf( "default:\n" ); + printf( "%s\n", tmp ); + + cf_urls = LSCopyApplicationURLsForURL(cf_url, kLSRolesEditor); + if ( cf_urls != NULL ) { + printf( "\neditor:\n" ); + count = CFArrayGetCount( cf_urls ); + for ( index = 0; index < count; index++ ) { + cf_other_url = CFArrayGetValueAtIndex( cf_urls, index ); + cf_url_path = CFURLGetString( cf_other_url ); + if ( cf2c( cf_url_path, tmp, sizeof( tmp )) != 0 ) { + goto duti_urls_for_url_cleanup; + } + printf( "%s\n", tmp ); + } + CFRelease( cf_urls ); cf_urls = NULL; + } + + cf_urls = LSCopyApplicationURLsForURL(cf_url, kLSRolesViewer); + if ( cf_urls != NULL ) { + printf( "\nviewer:\n" ); + count = CFArrayGetCount( cf_urls ); + for ( index = 0; index < count; index++ ) { + cf_other_url = CFArrayGetValueAtIndex( cf_urls, index ); + cf_url_path = CFURLGetString( cf_other_url ); + if ( cf2c( cf_url_path, tmp, sizeof( tmp )) != 0 ) { + goto duti_urls_for_url_cleanup; + } + printf( "%s\n", tmp ); + } + CFRelease( cf_urls ); cf_urls = NULL; + } + + cf_urls = LSCopyApplicationURLsForURL(cf_url, kLSRolesShell); + if ( cf_urls != NULL ) { + printf( "\nshell:\n" ); + count = CFArrayGetCount( cf_urls ); + for ( index = 0; index < count; index++ ) { + cf_other_url = CFArrayGetValueAtIndex( cf_urls, index ); + cf_url_path = CFURLGetString( cf_other_url ); + if ( cf2c( cf_url_path, tmp, sizeof( tmp )) != 0 ) { + goto duti_urls_for_url_cleanup; + } + printf( "%s\n", tmp ); + } + CFRelease( cf_urls ); cf_urls = NULL; + } + + cf_urls = LSCopyApplicationURLsForURL(cf_url, kLSRolesNone); + if ( cf_urls != NULL ) { + printf( "\nnone:\n" ); + count = CFArrayGetCount( cf_urls ); + for ( index = 0; index < count; index++ ) { + cf_other_url = CFArrayGetValueAtIndex( cf_urls, index ); + cf_url_path = CFURLGetString( cf_other_url ); + if ( cf2c( cf_url_path, tmp, sizeof( tmp )) != 0 ) { + goto duti_urls_for_url_cleanup; + } + printf( "%s\n", tmp ); + } + CFRelease( cf_urls ); cf_urls = NULL; + } + + /* success */ + rc = 0; + +duti_urls_for_url_cleanup: + if ( cf_url != NULL ) { + CFRelease( cf_url ); + } + if ( cf_url_default != NULL ) { + CFRelease( cf_url_default ); + } + if ( cf_urls != NULL ) { + CFRelease( cf_urls ); + } + if ( cf_error_description != NULL ) { + CFRelease( cf_error_description ); + } + if ( cf_error != NULL ) { + CFRelease( cf_error ); + } + + return rc; +} + + int +duti_utis( char *uti ) { + CFStringRef cf_uti_identifier = NULL; + CFStringRef cf_uti_description = NULL; + CFDictionaryRef cf_uti_declaration = NULL; + char tmp[ MAXPATHLEN ]; + int rc = 2; + + if ( uti == NULL ) { + fprintf( stderr, "Invalid UTI.\n" ); + return( rc ); + } + + if ( c2cf( uti, &cf_uti_identifier ) != 0 ) { + return( rc ); + } + + cf_uti_description = UTTypeCopyDescription(cf_uti_identifier); + if ( cf2c( cf_uti_description, tmp, sizeof( tmp )) != 0 ) { + goto duti_utis_cleanup; + } + CFRelease(cf_uti_description); cf_uti_description = NULL; + printf( "description: %s\n", tmp ); + + cf_uti_declaration = UTTypeCopyDeclaration(cf_uti_identifier); + printf( "declaration: {\n" ); + CFDictionaryApplyFunction(cf_uti_declaration, dump_cf_dictionary, "\t"); + CFRelease(cf_uti_declaration); cf_uti_declaration = NULL; + printf( "}\n" ); + + /* success */ rc = 0; duti_utis_cleanup: @@ -681,21 +961,58 @@ duti_utis( char * uti ) { CFRelease( cf_uti_declaration ); } - return rc; + return rc; } -int -duti_utis_for_extension(char* ext) { - CFStringRef cf_ext = NULL; - CFArrayRef cf_array = NULL; - CFStringRef cf_uti_description = NULL; - CFDictionaryRef cf_uti_declaration = NULL; - CFIndex index; - CFIndex count; - char *rext; - char tmp[ MAXPATHLEN ]; + int +duti_urls_for_bundle(char *bundle_id) { + CFStringRef cf_bundle_id = NULL; + CFArrayRef cf_array = NULL; + CFErrorRef cf_error = NULL; int rc = 2; + if ( bundle_id == NULL ) { + fprintf( stderr, "Invalid bundle identifier.\n" ); + return( rc ); + } + + if ( c2cf( bundle_id, &cf_bundle_id ) != 0 ) { + return( rc ); + } + + cf_array = LSCopyApplicationURLsForBundleIdentifier(cf_bundle_id, &cf_error); + if (cf_array) { + CFArrayApplyFunction(cf_array, CFRangeMake( 0, CFArrayGetCount( cf_array )), dump_cf_array, "url: "); + } + + /* success */ + rc = 0; + + if ( cf_bundle_id ) { + CFRelease( cf_bundle_id ); + } + if ( cf_array != NULL ) { + CFRelease( cf_array ); + } + if ( cf_error != NULL ) { + CFRelease( cf_error ); + } + + return rc; +} + + int +duti_utis_for_extension(char *ext) { + CFStringRef cf_ext = NULL; + CFArrayRef cf_array = NULL; + CFStringRef cf_uti_description = NULL; + CFDictionaryRef cf_uti_declaration = NULL; + CFIndex index; + CFIndex count; + char *rext; + char tmp[ MAXPATHLEN ]; + int rc = 2; + if (( rext = strrchr( ext, '.' )) == NULL ) { rext = ext; } else { @@ -709,27 +1026,27 @@ duti_utis_for_extension(char* ext) { return( rc ); } - cf_array = UTTypeCreateAllIdentifiersForTag(kUTTagClassFilenameExtension, cf_ext, nil); - for (index = 0, count = CFArrayGetCount(cf_array); index < count; index++) { - CFStringRef cf_uti_identifier = CFArrayGetValueAtIndex(cf_array, index); - if ( cf2c( cf_uti_identifier, tmp, sizeof( tmp )) != 0 ) { - goto duti_utis_cleanup; - } - printf( "identifier: %s\n", tmp ); - - cf_uti_description = UTTypeCopyDescription(cf_uti_identifier); - if ( cf2c( cf_uti_description, tmp, sizeof( tmp )) != 0 ) { - goto duti_utis_cleanup; - } - CFRelease(cf_uti_description); cf_uti_description = NULL; - printf( "description: %s\n", tmp ); + cf_array = UTTypeCreateAllIdentifiersForTag(kUTTagClassFilenameExtension, cf_ext, nil); + for (index = 0, count = CFArrayGetCount(cf_array); index < count; index++) { + CFStringRef cf_uti_identifier = CFArrayGetValueAtIndex(cf_array, index); + if ( cf2c( cf_uti_identifier, tmp, sizeof( tmp )) != 0 ) { + goto duti_utis_cleanup; + } + printf( "identifier: %s\n", tmp ); - cf_uti_declaration = UTTypeCopyDeclaration(cf_uti_identifier); - printf( "declaration: {\n" ); - CFDictionaryApplyFunction(cf_uti_declaration, dump_cf_dictionary, "\t"); - CFRelease(cf_uti_declaration); cf_uti_declaration = NULL; - printf( "}\n" ); + cf_uti_description = UTTypeCopyDescription(cf_uti_identifier); + if ( cf2c( cf_uti_description, tmp, sizeof( tmp )) != 0 ) { + goto duti_utis_cleanup; } + CFRelease(cf_uti_description); cf_uti_description = NULL; + printf( "description: %s\n", tmp ); + + cf_uti_declaration = UTTypeCopyDeclaration(cf_uti_identifier); + printf( "declaration: {\n" ); + CFDictionaryApplyFunction(cf_uti_declaration, dump_cf_dictionary, "\t"); + CFRelease(cf_uti_declaration); cf_uti_declaration = NULL; + printf( "}\n" ); + } /* success */ rc = 0; @@ -753,47 +1070,54 @@ duti_utis_for_extension(char* ext) { static void dump_cf_array( const void *value, void *context ) { - CFTypeID typeID; - char tmp[ MAXPATHLEN ]; + CFTypeID typeID; + char tmp[ MAXPATHLEN ]; - typeID = CFGetTypeID( value ); - if (typeID == CFStringGetTypeID()) { - if ( cf2c( value, tmp, sizeof( tmp )) != 0 ) { - return; - } - printf( "%s%s\n", (char *) context, tmp ); - } else { - printf( "%sunhandled value\n", (char *) context ); + typeID = CFGetTypeID( value ); + if (typeID == CFStringGetTypeID()) { + if ( cf2c( value, tmp, sizeof( tmp )) != 0 ) { + return; + } + printf( "%s%s\n", (char *) context, tmp ); + } else if (typeID == CFURLGetTypeID()) { + CFURLRef cf_url = (CFURLRef) value; + CFStringRef cf_url_path = CFURLGetString( cf_url ); + if ( cf2c( cf_url_path, tmp, sizeof( tmp )) != 0 ) { + return; } + printf( "%s%s\n", (char *) context, tmp ); + } else { + printf( "%sunhandled value\n", (char *) context ); + } } static void dump_cf_dictionary( const void *key, const void *value, void *context ) { - CFTypeID typeID; - char tmp[ MAXPATHLEN ]; + CFTypeID typeID; + char tmp[ MAXPATHLEN ]; - if ( cf2c( key, tmp, sizeof( tmp )) != 0 ) { + if ( cf2c( key, tmp, sizeof( tmp )) != 0 ) { return; - } - printf( "%s%s = ", (char *) context, tmp ); + } + printf( "%s%s = ", (char *) context, tmp ); - typeID = CFGetTypeID( value ); - if (typeID == CFStringGetTypeID()) { - if ( cf2c( value, tmp, sizeof( tmp )) != 0 ) { - return; - } - printf( "%s\n", tmp ); - } else if (typeID == CFArrayGetTypeID()) { - printf( "[\n" ); - sprintf(tmp, "%s\t", (char *) context ); - CFArrayApplyFunction(value, CFRangeMake( 0, CFArrayGetCount( value )), dump_cf_array, tmp); - printf( "%s]\n", (char *) context ); - } else if (typeID == CFDictionaryGetTypeID()) { - printf( "{\n" ); - sprintf(tmp, "%s\t", (char *) context ); - CFDictionaryApplyFunction(value, dump_cf_dictionary, tmp); - printf( "%s}\n", (char *) context ); - } else { - printf( "unhandled key\n"); + typeID = CFGetTypeID( value ); + if (typeID == CFStringGetTypeID()) { + if ( cf2c( value, tmp, sizeof( tmp )) != 0 ) { + return; } + printf( "%s\n", tmp ); + } else if (typeID == CFArrayGetTypeID()) { + printf( "[\n" ); + sprintf(tmp, "%s\t", (char *) context ); + CFArrayApplyFunction(value, CFRangeMake( 0, CFArrayGetCount( value )), dump_cf_array, tmp); + printf( "%s]\n", (char *) context ); + } else if (typeID == CFDictionaryGetTypeID()) { + printf( "{\n" ); + sprintf(tmp, "%s\t", (char *) context ); + CFDictionaryApplyFunction(value, dump_cf_dictionary, tmp); + printf( "%s}\n", (char *) context ); + } else { + printf( "unhandled key\n"); + } } diff --git a/handler.h b/handler.h index dc4b5e7..5bf9996 100644 --- a/handler.h +++ b/handler.h @@ -18,6 +18,9 @@ int uti_handler_show( char *uti, int showall ); int url_handler_show( char *url_scheme ); int duti_handler_set( char *, char *, char * ); int duti_default_app_for_extension( char * ); +int duti_default_app_for_type( char * ); int duti_is_conformant_uti( CFStringRef ); +int duti_urls_for_url( char * ); int duti_utis( char * ); +int duti_urls_for_bundle( char * ); int duti_utis_for_extension( char * ); diff --git a/plist.c b/plist.c index 11dfb2a..ad983e1 100644 --- a/plist.c +++ b/plist.c @@ -62,7 +62,7 @@ read_plist( char *plpath, CFDictionaryRef *dr ) goto cleanup; } - if (( cfdict = CFPropertyListCreateFromStream( kCFAllocatorDefault, cfrs, + if (( cfdict = CFPropertyListCreateWithStream( kCFAllocatorDefault, cfrs, 0, kCFPropertyListImmutable, &fmt, NULL )) == NULL ) { fprintf( stderr, "%s: failed to read plist\n", __FUNCTION__ ); rc = -1;