this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

LaunchServices: Implement LSFindApplicationForInfo, LSCopyApplicationURLsForBundleIdentifier, LSGetApplicationForInfo and LSCopyDefaultApplicationURLForContentType

+263 -13
+5 -1
src/frameworks/CoreServices/src/CarbonCore/ComponentManager.cpp
··· 82 82 CFRelease(urlDir); 83 83 84 84 for (CFIndex i = 0; i < CFArrayGetCount(componentBundles); i++) 85 - analyzeComponent((CFBundleRef) CFArrayGetValueAtIndex(componentBundles, i)); 85 + { 86 + CFBundleRef bundle = (CFBundleRef) CFArrayGetValueAtIndex(componentBundles, i); 87 + analyzeComponent(bundle); 88 + CFRelease(bundle); 89 + } 86 90 87 91 CFRelease(componentBundles); 88 92 }
+5
src/frameworks/CoreServices/src/LaunchServices/CMakeLists.txt
··· 1 + 2 + include_directories( 3 + ${CMAKE_SOURCE_DIR}/src/external/fmdb/src 4 + ) 1 5 2 6 add_framework(LaunchServices 3 7 FAT ··· 20 24 icucore 21 25 system 22 26 CarbonCore 27 + FMDB 23 28 ) 24 29 25 30 add_subdirectory(launchservicesd)
+214 -4
src/frameworks/CoreServices/src/LaunchServices/LSInfo.m
··· 21 21 #include <LaunchServices/LaunchServices.h> 22 22 #include <CoreServices/MacErrors.h> 23 23 #include <stdio.h> 24 + #include <sqlite3.h> 25 + #import <Foundation/NSString.h> 26 + #import <fmdb/FMDatabaseQueue.h> 27 + 28 + __attribute__((visibility("hidden"))) 29 + FMDatabaseQueue* getDatabaseQueue(void) 30 + { 31 + static FMDatabaseQueue* db = nil; 32 + if (!db) 33 + { 34 + db = [[FMDatabaseQueue databaseQueueWithPath: @"/private/var/db/launchservices.db" flags:SQLITE_OPEN_READONLY] retain]; 35 + } 36 + return db; 37 + } 38 + 39 + // An SQL-safe fourcc string 40 + static NSString* fourcc(UInt32 code) 41 + { 42 + char buf[9]; 43 + int pos = 0; 44 + int shift = 24; 45 + 46 + do 47 + { 48 + buf[pos] = (code >> shift) & 0xff; 49 + 50 + // Escape ' by doubling it 51 + if (buf[pos++] == '\'') 52 + buf[pos++] = '\''; 53 + 54 + shift -= 8; 55 + } 56 + while (shift != 0); 57 + buf[pos] = '\0'; 58 + 59 + return [NSString stringWithCString:buf encoding:NSASCIIStringEncoding]; 60 + } 61 + 62 + static NSString* escape(NSString* str) 63 + { 64 + return [str stringByReplacingOccurrencesOfString:@"'" 65 + withString:@"''"]; 66 + } 24 67 25 68 OSStatus 26 69 LSFindApplicationForInfo( ··· 30 73 FSRef * outAppRef, 31 74 CFURLRef * outAppURL) 32 75 { 33 - puts("LSFindApplicationForInfo STUB"); 34 - return unimpErr; 76 + if (outAppURL) 77 + *outAppURL = NULL; 78 + 79 + if (inCreator == kLSUnknownCreator && !inBundleID && !inName) 80 + return paramErr; 81 + 82 + __block OSStatus retval; 83 + [getDatabaseQueue() inDatabase:^(FMDatabase* db) { 84 + NSString* query = @"select path from bundle where package_type='APPL'"; 85 + 86 + if (inCreator != kLSUnknownCreator) 87 + query = [query stringByAppendingFormat:@" and creator = '%@'", fourcc(inCreator)]; 88 + if (inBundleID != NULL) 89 + query = [query stringByAppendingFormat:@" and bundle_id = '%@'", escape((NSString*) inBundleID)]; 90 + if (inName != NULL) 91 + query = [query stringByAppendingFormat:@" and path like '%%%@'", escape((NSString*) inName)]; 92 + 93 + FMResultSet* rs = [db executeQuery:query]; 94 + if ([rs next]) 95 + { 96 + NSString* path = [rs stringForColumn:@"path"]; 97 + if (outAppURL) 98 + *outAppURL = (CFURLRef) [[NSURL alloc] initFileURLWithPath:path isDirectory:YES]; 99 + if (outAppRef) 100 + FSPathMakeRef((const UInt8*) [path fileSystemRepresentation], outAppRef, NULL); 101 + 102 + retval = noErr; 103 + } 104 + else 105 + retval = kLSApplicationNotFoundErr; 106 + [rs close]; 107 + }]; 108 + 109 + return retval; 110 + } 111 + 112 + CFArrayRef LSCopyApplicationURLsForBundleIdentifier(CFStringRef inBundleIdentifier, CFErrorRef _Nullable *outError) 113 + { 114 + if (!inBundleIdentifier) 115 + { 116 + if (*outError) 117 + *outError = CFErrorCreate(NULL, kCFErrorDomainOSStatus, paramErr, NULL); 118 + return NULL; 119 + } 120 + 121 + __block CFArrayRef retval; 122 + 123 + [getDatabaseQueue() inDatabase:^(FMDatabase* db) { 124 + FMResultSet* rs = [db executeQuery:@"select path from bundle where package_type='APPL' and bundle_id = ?", inBundleIdentifier]; 125 + 126 + if ([rs next]) 127 + { 128 + NSMutableArray* mut = [[NSMutableArray alloc] init]; 129 + do 130 + { 131 + [mut addObject: [NSURL fileURLWithPath: [rs stringForColumn:@"path"] isDirectory: YES]]; 132 + } 133 + while ([rs next]); 134 + 135 + retval = (CFArrayRef) [[NSArray alloc] initWithArray: mut]; 136 + [mut release]; 137 + } 138 + else 139 + { 140 + if (*outError) 141 + *outError = CFErrorCreate(NULL, kCFErrorDomainOSStatus, kLSApplicationNotFoundErr, NULL); 142 + retval = NULL; 143 + } 144 + [rs close]; 145 + }]; 146 + 147 + return retval; 148 + } 149 + 150 + static NSString* appendRole(NSString* str, NSString* role) 151 + { 152 + if (str == nil) 153 + return [NSString stringWithFormat:@"'%@'", role]; 154 + else 155 + return [str stringByAppendingFormat:@",'%@'", role]; 156 + } 157 + 158 + static NSString* roleSQLArray(LSRolesMask inRoleMask) 159 + { 160 + NSString* str = nil; 161 + if (inRoleMask & kLSRolesNone) 162 + str = appendRole(str, @"None"); 163 + if (inRoleMask & kLSRolesViewer) 164 + str = appendRole(str, @"Viewer"); 165 + if (inRoleMask & kLSRolesEditor) 166 + str = appendRole(str, @"Editor"); 167 + if (inRoleMask & kLSRolesShell) 168 + str = appendRole(str, @"Shell"); 169 + return str; 35 170 } 36 171 37 172 OSStatus ··· 43 178 FSRef * outAppRef, 44 179 CFURLRef * outAppURL) 45 180 { 46 - puts("LSGetApplicationForInfo STUB"); 47 - return unimpErr; 181 + __block OSStatus retval; 182 + 183 + if (outAppURL) 184 + *outAppURL = NULL; 185 + 186 + if (inType == kLSUnknownType && inCreator == kLSUnknownCreator && inExtension == NULL) 187 + { 188 + return paramErr; 189 + } 190 + 191 + [getDatabaseQueue() inDatabase:^(FMDatabase* db) { 192 + NSString* query = @"select path from bundle where package_type='APPL'"; 193 + 194 + if (inType != kLSUnknownType) 195 + query = [query stringByAppendingFormat:@" and signature='%@'", fourcc(inType)]; 196 + if (inCreator != kLSUnknownCreator) 197 + query = [query stringByAppendingFormat:@" and creator='%@'", fourcc(inCreator)]; 198 + if (inExtension != NULL) 199 + { 200 + NSString* escaped = escape((NSString*) inExtension); 201 + query = [query stringByAppendingFormat:@" and (id IN (SELECT A.bundle FROM app_doc A LEFT JOIN app_doc_extension AE ON AE.doc=A.id WHERE AE.extension = '%@')" 202 + @" OR " 203 + @"id IN (SELECT A.bundle FROM app_doc A LEFT JOIN app_doc_uti AU ON AU.doc=A.id LEFT JOIN uti ON uti.type_identifier = AU.uti LEFT JOIN uti_tag UT ON UT.uti=uti.id WHERE UT.tag = 'public.filename-extension' AND UT.value='%@'))", 204 + escaped, escaped]; 205 + } 206 + if (inRoleMask != kLSRolesAll) 207 + { 208 + query = [query stringByAppendingFormat:@" and id IN (SELECT A.bundle FROM app_doc WHERE role IN (%@))", roleSQLArray(inRoleMask)]; 209 + } 210 + 211 + FMResultSet* rs = [db executeQuery:query]; 212 + if ([rs next]) 213 + { 214 + NSString* path = [rs stringForColumn:@"path"]; 215 + if (outAppURL) 216 + *outAppURL = (CFURLRef) [[NSURL alloc] initFileURLWithPath:path isDirectory:YES]; 217 + if (outAppRef) 218 + FSPathMakeRef((const UInt8*) [path fileSystemRepresentation], outAppRef, NULL); 219 + 220 + retval = noErr; 221 + } 222 + else 223 + retval = kLSApplicationNotFoundErr; 224 + [rs close]; 225 + }]; 226 + 227 + return retval; 228 + } 229 + 230 + CFURLRef LSCopyDefaultApplicationURLForContentType(CFStringRef inContentType, LSRolesMask inRoleMask, CFErrorRef _Nullable *outError) 231 + { 232 + __block CFURLRef retval; 233 + 234 + [getDatabaseQueue() inDatabase:^(FMDatabase* db) { 235 + NSString* query = @"select path from bundle LEFT JOIN app_doc AD on AD.bundle=bundle.id LEFT JOIN app_doc_uti AU on AU.doc=AD.id WHERE uti=?"; 236 + 237 + if (inRoleMask != kLSRolesAll) 238 + { 239 + query = [query stringByAppendingFormat:@" and AD.role in (%@)", roleSQLArray(inRoleMask)]; 240 + } 241 + 242 + FMResultSet* rs = [db executeQuery:query, inContentType]; 243 + 244 + if ([rs next]) 245 + { 246 + retval = (CFURLRef) [[NSURL alloc] initFileURLWithPath: [rs stringForColumn:@"path"] isDirectory: YES]; 247 + } 248 + else 249 + { 250 + if (*outError) 251 + *outError = CFErrorCreate(NULL, kCFErrorDomainOSStatus, kLSApplicationNotFoundErr, NULL); 252 + retval = NULL; 253 + } 254 + [rs close]; 255 + }]; 256 + 257 + return retval; 48 258 }
+32 -7
src/frameworks/CoreServices/src/LaunchServices/launchservicesd/LSBundle.m
··· 260 260 NSArray<NSDictionary*>* types = (NSArray*) infoDict[@"CFBundleDocumentTypes"]; 261 261 if (types) 262 262 { 263 - NSLog(@"Found type array\n"); 264 263 for (NSDictionary* type in types) 265 264 [self processFileAssociation: type]; 266 265 } 267 266 if (infoDict[@"CFBundleTypeRole"] != nil) 268 267 { 269 - NSLog(@"Found a single type\n"); 270 268 [self processFileAssociation: infoDict]; 271 269 } 272 270 } ··· 275 273 { 276 274 NSURL* url = (NSURL*) CFBundleCopyBundleURL(_bundle); 277 275 NSString* path = [url path]; 278 - const uint32_t newChecksum = [[(NSDictionary*) CFBundleGetInfoDictionary(_bundle) description] crc32]; 276 + NSDictionary* infoDict = (NSDictionary*) CFBundleGetInfoDictionary(_bundle); 277 + const uint32_t newChecksum = [[infoDict description] crc32]; 279 278 280 279 [url release]; 281 280 FMResultSet* rs = [g_database executeQuery:@"select id, checksum from bundle where path = ?", path]; ··· 296 295 297 296 [rs close]; 298 297 298 + UInt32 packageType = 0, packageCreator = 0; 299 + CFBundleGetPackageInfo(_bundle, &packageType, &packageCreator); 300 + 301 + NSString* packageTypeStr = nil; 302 + NSString* packageCreatorStr = nil; 303 + NSString* bundleSignature = infoDict[@"CFBundleSignature"]; 304 + 305 + if (packageType != 0) 306 + packageTypeStr = [LSBundle fourcc:packageType]; 307 + if (packageCreator != 0) 308 + packageCreatorStr = [LSBundle fourcc:packageCreator]; 309 + 299 310 if (!_bundleId) 300 311 { 301 312 CFStringRef identifier = CFBundleGetIdentifier(_bundle); 302 313 303 314 NSLog(@"Registering new bundle at '%@', identifier '%@'\n", path, identifier); 304 315 305 - [g_database executeUpdate:@"insert into bundle (path, bundle_id, checksum) values (?,?,?)", 306 - path, identifier, [NSNumber numberWithInt:newChecksum]]; 316 + [g_database executeUpdate:@"insert into bundle (path, bundle_id, checksum, package_type, creator, signature) values (?,?,?,?,?,?)", 317 + path, identifier, [NSNumber numberWithInt:newChecksum], packageTypeStr, packageCreatorStr, bundleSignature]; 307 318 308 319 _bundleId = [g_database lastInsertRowId]; 309 320 } ··· 312 323 NSLog(@"Updating bundle at '%@'\n", path); 313 324 314 325 // We're in a transaction, so it's OK to set the new checksum now 315 - [g_database executeUpdate:@"update bundle set checksum = ? where id = ?", 316 - [NSNumber numberWithInt:newChecksum], [NSNumber numberWithInt: _bundleId]]; 326 + [g_database executeUpdate:@"update bundle set checksum = ?, package_type = ?, creator = ?, signature = ? where id = ?", 327 + [NSNumber numberWithInt:newChecksum], packageTypeStr, packageCreatorStr, 328 + bundleSignature, [NSNumber numberWithInt: _bundleId]]; 317 329 } 318 330 319 331 return TRUE; ··· 368 380 } 369 381 } 370 382 383 + +(NSString*)fourcc:(UInt32)code 384 + { 385 + char str[5]; 386 + str[0] = (code >> 24) & 0xff; 387 + str[1] = (code >> 16) & 0xff; 388 + str[2] = (code >> 8) & 0xff; 389 + str[3] = code & 0xff; 390 + str[4] = '\0'; 391 + return [NSString stringWithCString:str encoding:NSASCIIStringEncoding]; 392 + } 393 + 371 394 +(void)scanForBundles:(NSString*)dir 372 395 { 373 396 @autoreleasepool ··· 386 409 LSBundle* b = [[[LSBundle alloc] initWithBundle: (CFBundleRef) bundle] autorelease]; 387 410 [b process]; 388 411 } 412 + 413 + CFRelease((CFBundleRef) bundle); 389 414 } 390 415 391 416 [bundles release];
+7 -1
src/frameworks/CoreServices/src/LaunchServices/launchservicesd/schema.sql
··· 5 5 `id` INTEGER PRIMARY KEY AUTOINCREMENT, 6 6 `path` TEXT NOT NULL, 7 7 `bundle_id` TEXT NOT NULL, 8 - `checksum` INTEGER NOT NULL 8 + `checksum` INTEGER NOT NULL, 9 + 'package_type' TEXT, 10 + 'creator' TEXT, 11 + 'signature' TEXT 9 12 ); 10 13 CREATE INDEX `bundle_id_index` ON `bundle`(`bundle_id`); 11 14 CREATE INDEX `bundle_path_index` ON `bundle`(`path`); 15 + CREATE INDEX `bundle_type` ON `bundle`(`package_type`); 16 + CREATE INDEX `bundle_creator` ON `bundle`(`creator`); 17 + CREATE INDEX `bundle_signature` ON `bundle`(`signature`); 12 18 13 19 CREATE TABLE `uti` ( 14 20 `id` INTEGER PRIMARY KEY AUTOINCREMENT,