Oolite 1.91.0.7644-241112-7f5034b
Loading...
Searching...
No Matches
ResourceManager Class Reference

#include <ResourceManager.h>

+ Inheritance diagram for ResourceManager:
+ Collaboration diagram for ResourceManager:

Class Methods

(void) + reset
 
(void) + resetManifestKnowledgeForOXZManager
 
(NSArray *) + rootPaths
 
(NSArray *) + userRootPaths
 
(NSString *) + builtInPath
 
(NSArray *) + pathsWithAddOns
 
(NSArray *) + paths
 
(NSString *) + useAddOns
 
(NSArray *) + OXPsWithMessagesFound
 
(void) + setUseAddOns:
 
(void) + addExternalPath:
 
(NSEnumerator *) + pathEnumerator
 
(NSEnumerator *) + reversePathEnumerator
 
(NSDictionary *) + manifestForIdentifier:
 
(BOOL) + checkVersionCompatibility:forOXP:
 
(BOOL) + manifestHasConflicts:logErrors:
 
(BOOL) + manifestHasMissingDependencies:logErrors:
 
(BOOL) + manifest:HasUnmetDependency:logErrors:
 
(BOOL) + matchVersions:withVersion:
 
(void) + handleEquipmentListMerging:forLookupIndex:
 
(void) + handleEquipmentOverrides:
 
(void) + handleStarNebulaListMerging:
 
(NSString *) + errors
 
(NSString *) + pathForFileNamed:inFolder:
 
(NSString *) + pathForFileNamed:inFolder:cache:
 
(BOOL) + corePlist:excludedAt:
 
(NSDictionary *) + dictionaryFromFilesNamed:inFolder:andMerge:
 
(NSDictionary *) + dictionaryFromFilesNamed:inFolder:mergeMode:cache:
 
(NSArray *) + arrayFromFilesNamed:inFolder:andMerge:
 
(NSArray *) + arrayFromFilesNamed:inFolder:andMerge:cache:
 
(NSDictionary *) + whitelistDictionary
 
(NSDictionary *) + shaderBindingTypesDictionary
 
(NSDictionary *) + logControlDictionary
 
(NSDictionary *) + roleCategoriesDictionary
 
(OOSystemDescriptionManager *) + systemDescriptionManager
 
(OOSound *) + ooSoundNamed:inFolder:
 
(OOMusic *) + ooMusicNamed:inFolder:
 
(NSString *) + stringFromFilesNamed:inFolder:
 
(NSString *) + stringFromFilesNamed:inFolder:cache:
 
(NSDictionary *) + loadScripts
 
(BOOL) + writeDiagnosticData:toFileNamed:
 
(BOOL) + writeDiagnosticString:toFileNamed:
 
(BOOL) + writeDiagnosticPList:toFileNamed:
 
(NSString *) + diagnosticFileLocation
 
(NSDictionary *) + materialDefaults
 
(void) + clearCaches
 
(void) + preloadFileLists [implementation]
 
(void) + preloadFileListFromOXZ:forFolders: [implementation]
 
(void) + preloadFileListFromFolder:forFolders: [implementation]
 
(void) + preloadFilePathFor:inFolder:atPath: [implementation]
 
(void) + checkOXPMessagesInPath: [implementation]
 
(void) + checkPotentialPath:path: [implementation]
 
(BOOL) + validateManifest:forOXP: [implementation]
 
(BOOL) + areRequirementsFulfilled:forOXP:andFile: [implementation]
 
(void) + filterSearchPathsForConflicts: [implementation]
 
(BOOL) + filterSearchPathsForRequirements: [implementation]
 
(void) + filterSearchPathsToExcludeScenarioOnlyPaths: [implementation]
 
(void) + filterSearchPathsByScenario: [implementation]
 
(BOOL) + manifestAllowedByScenario: [implementation]
 
(BOOL) + manifestAllowedByScenario:withIdentifier: [implementation]
 
(BOOL) + manifestAllowedByScenario:withTag: [implementation]
 
(void) + addErrorWithKey:param1:param2: [implementation]
 
(BOOL) + checkCacheUpToDateForPaths: [implementation]
 
(static NSString *) + LogClassKeyRoot [implementation]
 
(void) + mergeRoleCategories:intoDictionary: [implementation]
 
(id) + retrieveFileNamed:inFolder:cache:key:class:usePathCache: [implementation]
 
(BOOL) + directoryExists:create: [implementation]
 
(void) + logPaths [implementation]
 

Detailed Description

Definition at line 55 of file ResourceManager.h.

Method Documentation

◆ addErrorWithKey:param1:param2:

+ (void) addErrorWithKey: (NSString *) descriptionKey
param1: (id) param1
param2: (id) param2 
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 104 of file ResourceManager.m.

1114 :(NSString *)descriptionKey param1:(id)param1 param2:(id)param2
1115{
1116 if (descriptionKey != nil)
1117 {
1118 if (sErrors == nil) sErrors = [[NSMutableArray alloc] init];
1119 [sErrors addObject:[NSArray arrayWithObjects:descriptionKey, param1 ?: (id)@"", param2 ?: (id)@"", nil]];
1120 }
1121}
return nil
static NSMutableArray * sErrors

◆ addExternalPath:

+ (void) addExternalPath: (NSString *) fileName

Definition at line 104 of file ResourceManager.m.

527 :(NSString *)path
528{
529 if (sSearchPaths == nil) sSearchPaths = [[NSMutableArray alloc] init];
530 if (![sSearchPaths containsObject:path])
531 {
532 [sSearchPaths addObject:path];
533
534 if (sExternalPaths == nil) sExternalPaths = [[NSMutableArray alloc] init];
535 [sExternalPaths addObject:path];
536 }
537}
static NSMutableArray * sSearchPaths
static NSMutableArray * sExternalPaths

◆ areRequirementsFulfilled:forOXP:andFile:

+ (BOOL) areRequirementsFulfilled: (NSDictionary*) requirements
forOXP: (NSString *) path
andFile: (NSString *) file 
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 104 of file ResourceManager.m.

723 :(NSDictionary*)requirements forOXP:(NSString *)path andFile:(NSString *)file
724{
725 BOOL OK = YES;
726 NSString *requiredVersion = nil;
727 NSString *maxVersion = nil;
728 unsigned conditionsHandled = 0;
729 static NSArray *ooVersionComponents = nil;
730 NSArray *oxpVersionComponents = nil;
731
732 if (requirements == nil) return YES;
733
734 if (ooVersionComponents == nil)
735 {
736 ooVersionComponents = ComponentsFromVersionString([[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]);
737 [ooVersionComponents retain];
738 }
739
740 // Check "version" (minimum version)
741 if (OK)
742 {
743 // Not oo_stringForKey:, because we need to be able to complain about non-strings.
744 requiredVersion = [requirements objectForKey:@"version"];
745 if (requiredVersion != nil)
746 {
747 ++conditionsHandled;
748 if ([requiredVersion isKindOfClass:[NSString class]])
749 {
750 oxpVersionComponents = ComponentsFromVersionString(requiredVersion);
751 if (NSOrderedAscending == CompareVersions(ooVersionComponents, oxpVersionComponents)) OK = NO;
752 }
753 else
754 {
755 OOLog(@"requirements.wrongType", @"Expected %@ entry \"%@\" to be string, but got %@ in OXP %@.", file, @"version", [requirements class], [path lastPathComponent]);
756 OK = NO;
757 }
758 }
759 }
760
761 // Check "max_version" (minimum max_version)
762 if (OK)
763 {
764 // Not oo_stringForKey:, because we need to be able to complain about non-strings.
765 maxVersion = [requirements objectForKey:@"max_version"];
766 if (maxVersion != nil)
767 {
768 ++conditionsHandled;
769 if ([maxVersion isKindOfClass:[NSString class]])
770 {
771 oxpVersionComponents = ComponentsFromVersionString(maxVersion);
772 if (NSOrderedDescending == CompareVersions(ooVersionComponents, oxpVersionComponents)) OK = NO;
773 }
774 else
775 {
776 OOLog(@"requirements.wrongType", @"Expected %@ entry \"%@\" to be string, but got %@ in OXP %@.", file, @"max_version", [requirements class], [path lastPathComponent]);
777 OK = NO;
778 }
779 }
780 }
781
782 if (OK && conditionsHandled < [requirements count])
783 {
784 // There are unknown requirement keys - don't support. NOTE: this check was not made pre 1.69!
785 OOLog(@"requirements.unknown", @"requires.plist for OXP %@ contains unknown keys, rejecting.", [path lastPathComponent]);
786 OK = NO;
787 }
788
789 return OK;
790}
#define OOLog(class, format,...)
Definition OOLogging.h:88
unsigned count
NSArray * ComponentsFromVersionString(NSString *string)
NSComparisonResult CompareVersions(NSArray *version1, NSArray *version2)

◆ arrayFromFilesNamed:inFolder:andMerge:

+ (NSArray *) arrayFromFilesNamed: (NSString *) fileName
inFolder: (NSString *) folderName
andMerge: (BOOL) mergeFiles 

Definition at line 104 of file ResourceManager.m.

1342 :(NSString *)fileName inFolder:(NSString *)folderName andMerge:(BOOL) mergeFiles
1343{
1344 return [self arrayFromFilesNamed:fileName inFolder:folderName andMerge:mergeFiles cache:YES];
1345}

◆ arrayFromFilesNamed:inFolder:andMerge:cache:

+ (NSArray *) arrayFromFilesNamed: (NSString *) fileName
inFolder: (NSString *) folderName
andMerge: (BOOL) mergeFiles
cache: (BOOL) useCache 

Definition at line 104 of file ResourceManager.m.

1348 :(NSString *)fileName inFolder:(NSString *)folderName andMerge:(BOOL) mergeFiles cache:(BOOL)useCache
1349{
1350 id result = nil;
1351 NSMutableArray *results = nil;
1352 NSString *cacheKey = nil;
1354 NSEnumerator *enumerator = nil;
1355 NSString *path = nil;
1356 NSString *arrayPath = nil;
1357 NSMutableArray *array = nil;
1358 NSArray *arrayNonEditable = nil;
1359
1360 if (fileName == nil) return nil;
1361
1362 if (useCache)
1363 {
1364 cacheKey = [NSString stringWithFormat:@"%@%@ merge:%@", (folderName != nil) ? [folderName stringByAppendingString:@"/"] : (NSString *)@"", fileName, mergeFiles ? @"yes" : @"no"];
1365 result = [cache objectForKey:cacheKey inCache:@"arrays"];
1366 if (result != nil) return result;
1367 }
1368
1369 if (!mergeFiles)
1370 {
1371 // Find "last" matching array
1372 for (enumerator = [ResourceManager reversePathEnumerator]; (path = [enumerator nextObject]); )
1373 {
1374 if (folderName != nil)
1375 {
1376 arrayPath = [[path stringByAppendingPathComponent:folderName] stringByAppendingPathComponent:fileName];
1377 arrayNonEditable = OOArrayFromFile(arrayPath);
1378 if (arrayNonEditable != nil) break;
1379 }
1380 arrayPath = [path stringByAppendingPathComponent:fileName];
1381 arrayNonEditable = OOArrayFromFile(arrayPath);
1382 if (arrayNonEditable != nil) break;
1383 }
1384 result = arrayNonEditable;
1385 }
1386 else
1387 {
1388 // Find all matching arrays
1389 results = [NSMutableArray array];
1390 for (enumerator = [ResourceManager pathEnumerator]; (path = [enumerator nextObject]); )
1391 {
1392 if ([ResourceManager corePlist:fileName excludedAt:path])
1393 {
1394 continue;
1395 }
1396
1397 arrayPath = [path stringByAppendingPathComponent:fileName];
1398 array = [[OOArrayFromFile(arrayPath) mutableCopy] autorelease];
1399 if (array != nil) [results addObject:array];
1400
1401 // Special handling for arrays merging. Currently, only equipment.plist, nebulatextures.plist and
1402 // startextures.plist gets their objects merged.
1403 // A lookup index is required. For the equipment.plist items, this is the index corresponding to the
1404 // EQ_* string, which describes the role of an equipment item and is unique.
1405 // For nebula and star textures, this is the texture filename, although it can be overridden with a
1406 // "key" property
1407 if ([array count] != 0 && ([[fileName lowercaseString] isEqualToString:@"nebulatextures.plist"] ||
1408 [[fileName lowercaseString] isEqualToString:@"startextures.plist"]))
1409 [self handleStarNebulaListMerging:results];
1410
1411 if ([array count] != 0 && [[array objectAtIndex:0] isKindOfClass:[NSArray class]])
1412 {
1413 if ([[fileName lowercaseString] isEqualToString:@"equipment.plist"])
1414 [self handleEquipmentListMerging:results forLookupIndex:3]; // Index 3 is the role string (EQ_*).
1415 }
1416 if (folderName != nil)
1417 {
1418 arrayPath = [[path stringByAppendingPathComponent:folderName] stringByAppendingPathComponent:fileName];
1419 array = [[OOArrayFromFile(arrayPath) mutableCopy] autorelease];
1420 if (array != nil) [results addObject:array];
1421
1422 if ([array count] != 0 && ([[fileName lowercaseString] isEqualToString:@"nebulatextures.plist"] ||
1423 [[fileName lowercaseString] isEqualToString:@"startextures.plist"]))
1424 [self handleStarNebulaListMerging:results];
1425
1426 if ([array count] != 0 && [[array objectAtIndex:0] isKindOfClass:[NSArray class]])
1427 {
1428 if ([[fileName lowercaseString] isEqualToString:@"equipment.plist"])
1429 [self handleEquipmentListMerging:results forLookupIndex:3]; // Index 3 is the role string (EQ_*).
1430 }
1431 }
1432 }
1433
1434 if ([results count] == 0) return nil;
1435
1436 // Merge result
1437 result = [NSMutableArray array];
1438
1439 for (enumerator = [results objectEnumerator]; (array = [enumerator nextObject]); )
1440 {
1441 [result addObjectsFromArray:array];
1442 }
1443 // if we're doing equipment.plist, do equipment overrides now, while the array is still mutable
1444 if ([[fileName lowercaseString] isEqualToString:@"equipment.plist"])
1445 {
1446 [self handleEquipmentOverrides:result];
1447 }
1448 result = [[result copy] autorelease]; // Make immutable
1449 }
1450
1451 if (useCache && result != nil) [cache setObject:result forKey:cacheKey inCache:@"arrays"];
1452
1453 return [NSArray arrayWithArray:result];
1454}
NSArray * OOArrayFromFile(NSString *path)
id objectForKey:inCache:(NSString *inKey,[inCache] NSString *inCacheKey)
OOCacheManager * sharedCache()
NSEnumerator * reversePathEnumerator()
NSEnumerator * pathEnumerator()

◆ builtInPath

+ (NSString *) builtInPath

Definition at line 104 of file ResourceManager.m.

215{
216#if OOLITE_WINDOWS
217 /* [[NSBundle mainBundle] resourcePath] causes complaints under Windows,
218 because we don't have a properly-built bundle.
219 */
220 return @"Resources";
221#else
222 return [[NSBundle mainBundle] resourcePath];
223#endif
224}

Referenced by LoadExplicitSettings().

+ Here is the caller graph for this function:

◆ checkCacheUpToDateForPaths:

+ (BOOL) checkCacheUpToDateForPaths: (NSArray *) searchPaths
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 104 of file ResourceManager.m.

1124 :(NSArray *)searchPaths
1125{
1126 /* Check if caches are up to date.
1127 The strategy is to use a two-entry cache. One entry is an array
1128 containing the search paths, the other an array of modification dates
1129 (in the same order). If either fails to match the correct settings,
1130 we delete both.
1131 */
1133 NSFileManager *fmgr = [NSFileManager defaultManager];
1134 BOOL upToDate = YES;
1135 id oldPaths = nil;
1136 NSMutableArray *modDates = nil;
1137 NSEnumerator *pathEnum = nil;
1138 NSString *path = nil;
1139 id modDate = nil;
1140
1141 if (EXPECT_NOT([[NSUserDefaults standardUserDefaults] boolForKey:@"always-flush-cache"]))
1142 {
1143 OOLog(kOOLogCacheExplicitFlush, @"%@", @"Cache explicitly flushed with always-flush-cache preference. Rebuilding from scratch.");
1144 upToDate = NO;
1145 }
1146 else if ([MyOpenGLView pollShiftKey])
1147 {
1148 OOLog(kOOLogCacheExplicitFlush, @"%@", @"Cache explicitly flushed with shift key. Rebuilding from scratch.");
1149 upToDate = NO;
1150 }
1151
1152 oldPaths = [cacheMgr objectForKey:kOOCacheKeySearchPaths inCache:kOOCacheSearchPathModDates];
1153 if (upToDate && ![oldPaths isEqual:searchPaths])
1154 {
1155 // OXPs added/removed
1156 if (oldPaths != nil) OOLog(kOOLogCacheStalePaths, @"%@", @"Cache is stale (search paths have changed). Rebuilding from scratch.");
1157 upToDate = NO;
1158 }
1159
1160 // Build modification date list. (We need this regardless of whether the search paths matched.)
1161
1162 modDates = [NSMutableArray arrayWithCapacity:[searchPaths count]];
1163 for (pathEnum = [searchPaths objectEnumerator]; (path = [pathEnum nextObject]); )
1164 {
1165 modDate = [[fmgr oo_fileAttributesAtPath:path traverseLink:YES] objectForKey:NSFileModificationDate];
1166 if (modDate != nil)
1167 {
1168 // Converts to double because I'm not sure the cache can deal with dates under GNUstep.
1169 modDate = [NSNumber numberWithDouble:[modDate timeIntervalSince1970]];
1170 [modDates addObject:modDate];
1171 }
1172 }
1173
1174 if (upToDate && ![[cacheMgr objectForKey:kOOCacheKeyModificationDates inCache:kOOCacheSearchPathModDates] isEqual:modDates])
1175 {
1176 OOLog(kOOLogCacheStaleDates, @"%@", @"Cache is stale (modification dates have changed). Rebuilding from scratch.");
1177 upToDate = NO;
1178 }
1179
1180 if (!upToDate)
1181 {
1182 [cacheMgr clearAllCaches];
1183 [cacheMgr setObject:searchPaths forKey:kOOCacheKeySearchPaths inCache:kOOCacheSearchPathModDates];
1184 [cacheMgr setObject:modDates forKey:kOOCacheKeyModificationDates inCache:kOOCacheSearchPathModDates];
1185 }
1186 else OOLog(kOOLogCacheUpToDate, @"%@", @"Data cache is up to date.");
1187
1188 return upToDate;
1189}
#define EXPECT_NOT(x)
static NSString *const kOOLogCacheUpToDate
static NSString *const kOOLogCacheStalePaths
static NSString *const kOOCacheSearchPathModDates
static NSString *const kOOLogCacheStaleDates
static NSString *const kOOLogCacheExplicitFlush
static NSString *const kOOCacheKeyModificationDates
void setObject:forKey:inCache:(id inElement,[forKey] NSString *inKey,[inCache] NSString *inCacheKey)

◆ checkOXPMessagesInPath:

+ (void) checkOXPMessagesInPath: (NSString *) path
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 104 of file ResourceManager.m.

564 :(NSString *)path
565{
566 NSArray *OXPMessageArray = OOArrayFromFile([path stringByAppendingPathComponent:@"OXPMessages.plist"]);
567
568 if ([OXPMessageArray count] > 0)
569 {
570 unsigned i;
571 for (i = 0; i < [OXPMessageArray count]; i++)
572 {
573 NSString *oxpMessage = [OXPMessageArray oo_stringAtIndex:i];
574 if (oxpMessage)
575 {
576 OOLog(@"oxp.message", @"%@: %@", path, oxpMessage);
577 }
578 }
579 if (sOXPsWithMessagesFound == nil) sOXPsWithMessagesFound = [[NSMutableArray alloc] init];
580 [sOXPsWithMessagesFound addObject:[path lastPathComponent]];
581 }
582}
static NSMutableArray * sOXPsWithMessagesFound

◆ checkPotentialPath:path:

+ (void) checkPotentialPath: (NSString *)
path: (NSMutableArray *) searchPaths 
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 104 of file ResourceManager.m.

586 :(NSString *)path :(NSMutableArray *)searchPaths
587{
588 NSDictionary *requirements = nil;
589 NSDictionary *manifest = nil;
590 BOOL requirementsMet = YES;
591
592 if (![[[path pathExtension] lowercaseString] isEqualToString:@"oxz"])
593 {
594 // OXZ format ignores requires.plist
595 requirements = OODictionaryFromFile([path stringByAppendingPathComponent:@"requires.plist"]);
596 requirementsMet = [self areRequirementsFulfilled:requirements forOXP:path andFile:@"requires.plist"];
597 }
598 if (!requirementsMet)
599 {
600 NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
601 OOLog(@"oxp.versionMismatch", @"OXP %@ is incompatible with version %@ of Oolite.", path, version);
602 [self addErrorWithKey:@"oxp-is-incompatible" param1:[path lastPathComponent] param2:version];
603 return;
604 }
605
606 manifest = OODictionaryFromFile([path stringByAppendingPathComponent:@"manifest.plist"]);
607 if (manifest == nil)
608 {
609 if ([[[path pathExtension] lowercaseString] isEqualToString:@"oxz"])
610 {
611 OOLog(@"oxp.noManifest", @"OXZ %@ has no manifest.plist", path);
612 [self addErrorWithKey:@"oxz-lacks-manifest" param1:[path lastPathComponent] param2:nil];
613 return;
614 }
615 else
616 {
617 if ([[[path pathExtension] lowercaseString] isEqualToString:@"oxp"])
618 {
619 OOStandardsError([NSString stringWithFormat:@"OXP %@ has no manifest.plist", path]);
620 if (OOEnforceStandards())
621 {
622 [self addErrorWithKey:@"oxp-lacks-manifest" param1:[path lastPathComponent] param2:nil];
623 return;
624 }
625 }
626 // make up a basic manifest in relaxed mode or for base folders
627 manifest = [NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"__oolite.tmp.%@",path],kOOManifestIdentifier,@"1",kOOManifestVersion,@"OXP without manifest",kOOManifestTitle,@"1",kOOManifestRequiredOoliteVersion,nil];
628 }
629 }
630
631 requirementsMet = [self validateManifest:manifest forOXP:path];
632
633
634 if (requirementsMet)
635 {
636 [searchPaths addObject:path];
637 }
638}
BOOL OOEnforceStandards(void)
void OOStandardsError(NSString *message)
NSDictionary * OODictionaryFromFile(NSString *path)

◆ checkVersionCompatibility:forOXP:

+ (BOOL) checkVersionCompatibility: (NSDictionary *) manifest
forOXP: (NSString *) title 

Definition at line 104 of file ResourceManager.m.

707 :(NSDictionary *)manifest forOXP:(NSString *)title
708{
709 NSString *required = [manifest oo_stringForKey:kOOManifestRequiredOoliteVersion defaultValue:nil];
710 NSString *maxRequired = [manifest oo_stringForKey:kOOManifestMaximumOoliteVersion defaultValue:nil];
711 // ignore empty max version string rather than treating as "version 0"
712 if (maxRequired == nil || [maxRequired length] == 0)
713 {
714 return [self areRequirementsFulfilled:[NSDictionary dictionaryWithObjectsAndKeys:required, @"version", nil] forOXP:title andFile:@"manifest.plist"];
715 }
716 else
717 {
718 return [self areRequirementsFulfilled:[NSDictionary dictionaryWithObjectsAndKeys:required, @"version", maxRequired, @"max_version", nil] forOXP:title andFile:@"manifest.plist"];
719 }
720}

◆ clearCaches

+ (void) clearCaches

Definition at line 1679 of file ResourceManager.m.

2250{
2251 [sSoundCache release];
2252 sSoundCache = nil;
2253 [sStringCache release];
2254 sStringCache = nil;
2255}
static NSMutableDictionary * sSoundCache
static NSMutableDictionary * sStringCache

◆ corePlist:excludedAt:

+ (BOOL) corePlist: (NSString *) fileName
excludedAt: (NSString *) path 

Definition at line 104 of file ResourceManager.m.

1200 :(NSString *)fileName excludedAt:(NSString *)path
1201{
1202 if (![path isEqualToString:[self builtInPath]])
1203 {
1204 // non-core paths always okay
1205 return NO;
1206 }
1207 NSString *uaoBit = nil;
1208 foreach (uaoBit, sUseAddOnsParts)
1209 {
1210 if ([uaoBit hasPrefix:SCENARIO_OXP_DEFINITION_NOPLIST])
1211 {
1212 NSString *plist = [uaoBit substringFromIndex:[SCENARIO_OXP_DEFINITION_NOPLIST length]];
1213 if ([plist isEqualToString:fileName])
1214 {
1215 // this core plist file should not be loaded at all
1216 return YES;
1217 }
1218 }
1219 }
1220 // then not excluded
1221 return NO;
1222}
#define SCENARIO_OXP_DEFINITION_NOPLIST
static NSArray * sUseAddOnsParts
NSString * builtInPath()

◆ diagnosticFileLocation

+ (NSString *) diagnosticFileLocation

Definition at line 1679 of file ResourceManager.m.

2226{
2228}
NSString * OOLogHandlerGetLogBasePath(void)

◆ dictionaryFromFilesNamed:inFolder:andMerge:

+ (NSDictionary *) dictionaryFromFilesNamed: (NSString *) fileName
inFolder: (NSString *) folderName
andMerge: (BOOL) mergeFiles 

Definition at line 104 of file ResourceManager.m.

1225 :(NSString *)fileName
1226 inFolder:(NSString *)folderName
1227 andMerge:(BOOL) mergeFiles
1228{
1229 return [ResourceManager dictionaryFromFilesNamed:fileName inFolder:folderName mergeMode:mergeFiles ? MERGE_BASIC : MERGE_NONE cache:YES];
1230}

Referenced by GuiDisplayGen::addLongText:startingAtRow:align:, CompileSystemDescriptions(), ExportSystemDescriptions(), GlobalAutoAIForRole(), HeadUpDisplay::InitTextEngine(void), and ReportJSError().

+ Here is the caller graph for this function:

◆ dictionaryFromFilesNamed:inFolder:mergeMode:cache:

+ (NSDictionary *) dictionaryFromFilesNamed: (NSString *) fileName
inFolder: (NSString *) folderName
mergeMode: (OOResourceMergeMode) mergeMode
cache: (BOOL) useCache 

Definition at line 104 of file ResourceManager.m.

1233 :(NSString *)fileName
1234 inFolder:(NSString *)folderName
1235 mergeMode:(OOResourceMergeMode)mergeMode
1236 cache:(BOOL)cache
1237{
1238 id result = nil;
1239 NSMutableArray *results = nil;
1240 NSString *cacheKey = nil;
1241 NSString *mergeType = nil;
1243 NSEnumerator *enumerator = nil;
1244 NSString *path = nil;
1245 NSString *dictPath = nil;
1246 NSDictionary *dict = nil;
1247
1248 if (fileName == nil) return nil;
1249
1250 switch (mergeMode)
1251 {
1252 case MERGE_NONE:
1253 mergeType = @"none";
1254 break;
1255
1256 case MERGE_BASIC:
1257 mergeType = @"basic";
1258 break;
1259
1260 case MERGE_SMART:
1261 mergeType = @"smart";
1262 break;
1263 }
1264 if (mergeType == nil)
1265 {
1266 OOLog(kOOLogParameterError, @"Unknown dictionary merge mode %u for %@. (This is an internal programming error, please report it.)", mergeMode, fileName);
1267 return nil;
1268 }
1269
1270 if (cache)
1271 {
1272
1273 if (folderName != nil)
1274 {
1275 cacheKey = [NSString stringWithFormat:@"%@/%@ merge:%@", folderName, fileName, mergeType];
1276 }
1277 else
1278 {
1279 cacheKey = [NSString stringWithFormat:@"%@ merge:%@", fileName, mergeType];
1280 }
1281 result = [cacheMgr objectForKey:cacheKey inCache:@"dictionaries"];
1282 if (result != nil) return result;
1283 }
1284
1285 if (mergeMode == MERGE_NONE)
1286 {
1287 // Find "last" matching dictionary
1288 for (enumerator = [ResourceManager reversePathEnumerator]; (path = [enumerator nextObject]); )
1289 {
1290 if (folderName != nil)
1291 {
1292 dictPath = [[path stringByAppendingPathComponent:folderName] stringByAppendingPathComponent:fileName];
1293 dict = OODictionaryFromFile(dictPath);
1294 if (dict != nil) break;
1295 }
1296 dictPath = [path stringByAppendingPathComponent:fileName];
1297 dict = OODictionaryFromFile(dictPath);
1298 if (dict != nil) break;
1299 }
1300 result = dict;
1301 }
1302 else
1303 {
1304 // Find all matching dictionaries
1305 results = [NSMutableArray array];
1306 for (enumerator = [ResourceManager pathEnumerator]; (path = [enumerator nextObject]); )
1307 {
1308 if ([ResourceManager corePlist:fileName excludedAt:path])
1309 {
1310 continue;
1311 }
1312 dictPath = [path stringByAppendingPathComponent:fileName];
1313 dict = OODictionaryFromFile(dictPath);
1314 if (dict != nil) [results addObject:dict];
1315 if (folderName != nil)
1316 {
1317 dictPath = [[path stringByAppendingPathComponent:folderName] stringByAppendingPathComponent:fileName];
1318 dict = OODictionaryFromFile(dictPath);
1319 if (dict != nil) [results addObject:dict];
1320 }
1321 }
1322
1323 if ([results count] == 0) return nil;
1324
1325 // Merge result
1326 result = [NSMutableDictionary dictionary];
1327
1328 for (enumerator = [results objectEnumerator]; (dict = [enumerator nextObject]); )
1329 {
1330 if (mergeMode == MERGE_SMART) [result mergeEntriesFromDictionary:dict];
1331 else [result addEntriesFromDictionary:dict];
1332 }
1333 result = [[result copy] autorelease]; // Make immutable
1334 }
1335
1336 if (cache && result != nil) [cacheMgr setObject:result forKey:cacheKey inCache:@"dictionaries"];
1337
1338 return result;
1339}
NSString *const kOOLogParameterError
Definition OOLogging.m:647
OOResourceMergeMode
@ MERGE_SMART
@ MERGE_NONE
@ MERGE_BASIC

Referenced by NSObject(OODebugPlugInController)::setUpDebugger.

+ Here is the caller graph for this function:

◆ directoryExists:create:

+ (BOOL) directoryExists: (NSString *) inPath
create: (BOOL) inCreate 
implementation

Definition at line 1679 of file ResourceManager.m.

2199 :(NSString *)inPath create:(BOOL)inCreate
2200{
2201 BOOL exists, directory;
2202 NSFileManager *fmgr = [NSFileManager defaultManager];
2203
2204 exists = [fmgr fileExistsAtPath:inPath isDirectory:&directory];
2205
2206 if (exists && !directory)
2207 {
2208 OOLog(@"resourceManager.write.buildPath.failed", @"Expected %@ to be a folder, but it is a file.", inPath);
2209 return NO;
2210 }
2211 if (!exists)
2212 {
2213 if (!inCreate) return NO;
2214 if (![fmgr oo_createDirectoryAtPath:inPath attributes:nil])
2215 {
2216 OOLog(@"resourceManager.write.buildPath.failed", @"Could not create folder %@.", inPath);
2217 return NO;
2218 }
2219 }
2220
2221 return YES;
2222}

◆ errors

+ (NSString *) errors

Definition at line 104 of file ResourceManager.m.

134{
135 NSArray *error = nil;
136 NSUInteger i, count;
137 NSMutableArray *result = nil;
138 NSString *errStr = nil;
139
140 count = [sErrors count];
141 if (count == 0) return nil;
142
143 // Expand error messages. This is deferred for localizability.
144 result = [NSMutableArray arrayWithCapacity:count];
145 for (i = 0; i != count; ++i)
146 {
147 error = [sErrors objectAtIndex:i];
148 errStr = [UNIVERSE descriptionForKey:[error oo_stringAtIndex:0]];
149 if (errStr != nil)
150 {
151 errStr = [NSString stringWithFormat:errStr, [error objectAtIndex:1], [error objectAtIndex:2]];
152 [result addObject:errStr];
153 }
154 }
155
156 [sErrors release];
157 sErrors = nil;
158
159 return [result componentsJoinedByString:@"\n"];
160}

◆ filterSearchPathsByScenario:

+ (void) filterSearchPathsByScenario: (NSMutableArray *) searchPaths
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 104 of file ResourceManager.m.

1004 :(NSMutableArray *)searchPaths
1005{
1006 NSDictionary *manifest = nil;
1007 NSString *identifier = nil;
1008 NSArray *identifiers = [sOXPManifests allKeys];
1009
1010 // take a copy because we'll mutate the original
1011 // foreach identified add-on
1012 foreach (identifier, identifiers)
1013 {
1014 manifest = [sOXPManifests objectForKey:identifier];
1015 if (manifest != nil)
1016 {
1017 if (![ResourceManager manifestAllowedByScenario:manifest])
1018 {
1019 // then we don't need this one
1020 [searchPaths removeObject:[manifest oo_stringForKey:kOOManifestFilePath]];
1021 [sOXPManifests removeObjectForKey:identifier];
1022 }
1023 }
1024 }
1025}

◆ filterSearchPathsForConflicts:

+ (void) filterSearchPathsForConflicts: (NSMutableArray *) searchPaths
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 104 of file ResourceManager.m.

829 :(NSMutableArray *)searchPaths
830{
831 NSDictionary *manifest = nil;
832 NSString *identifier = nil;
833 NSArray *identifiers = [sOXPManifests allKeys];
834
835 // take a copy because we'll mutate the original
836 // foreach identified add-on
837 foreach (identifier, identifiers)
838 {
839 manifest = [sOXPManifests objectForKey:identifier];
840 if (manifest != nil)
841 {
842 if ([self manifestHasConflicts:manifest logErrors:YES])
843 {
844 // then we have a conflict, so remove this path
845 [searchPaths removeObject:[manifest oo_stringForKey:kOOManifestFilePath]];
846 [sOXPManifests removeObjectForKey:identifier];
847 }
848 }
849 }
850}

◆ filterSearchPathsForRequirements:

+ (BOOL) filterSearchPathsForRequirements: (NSMutableArray *) searchPaths
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 104 of file ResourceManager.m.

922 :(NSMutableArray *)searchPaths
923{
924 NSDictionary *manifest = nil;
925 NSString *identifier = nil;
926 NSArray *identifiers = [sOXPManifests allKeys];
927
928 sAllMet = YES;
929
930 // take a copy because we'll mutate the original
931 // foreach identified add-on
932 foreach (identifier, identifiers)
933 {
934 manifest = [sOXPManifests objectForKey:identifier];
935 if (manifest != nil)
936 {
937 if ([self manifestHasMissingDependencies:manifest logErrors:YES])
938 {
939 // then we have a missing requirement, so remove this path
940 [searchPaths removeObject:[manifest oo_stringForKey:kOOManifestFilePath]];
941 [sOXPManifests removeObjectForKey:identifier];
942 sAllMet = NO;
943 }
944 }
945 }
946
947 return sAllMet;
948}
static BOOL sAllMet

◆ filterSearchPathsToExcludeScenarioOnlyPaths:

+ (void) filterSearchPathsToExcludeScenarioOnlyPaths: (NSMutableArray *) searchPaths
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 104 of file ResourceManager.m.

980 :(NSMutableArray *)searchPaths
981{
982 NSDictionary *manifest = nil;
983 NSString *identifier = nil;
984 NSArray *identifiers = [sOXPManifests allKeys];
985
986 // take a copy because we'll mutate the original
987 // foreach identified add-on
988 foreach (identifier, identifiers)
989 {
990 manifest = [sOXPManifests objectForKey:identifier];
991 if (manifest != nil)
992 {
993 if ([[manifest oo_arrayForKey:kOOManifestTags] containsObject:kOOManifestTagScenarioOnly])
994 {
995 [searchPaths removeObject:[manifest oo_stringForKey:kOOManifestFilePath]];
996 [sOXPManifests removeObjectForKey:identifier];
997 }
998 }
999 }
1000}
static NSString *const kOOManifestTags
static NSString *const kOOManifestTagScenarioOnly

◆ handleEquipmentListMerging:forLookupIndex:

+ (void) handleEquipmentListMerging: (NSMutableArray *) arrayToProcess
forLookupIndex: (unsigned) lookupIndex 

Definition at line 104 of file ResourceManager.m.

1460 : (NSMutableArray *)arrayToProcess forLookupIndex:(unsigned)lookupIndex
1461{
1462 NSUInteger i,j,k;
1463 NSMutableArray *refArray = [arrayToProcess objectAtIndex:[arrayToProcess count] - 1];
1464
1465 // Any change to refArray will directly modify arrayToProcess.
1466
1467 for (i = 0; i < [refArray count]; i++)
1468 {
1469 for (j = 0; j < [arrayToProcess count] - 1; j++)
1470 {
1471 NSUInteger count = [[arrayToProcess oo_arrayAtIndex:j] count];
1472 if (count == 0) continue;
1473
1474 for (k=0; k < count; k++)
1475 {
1476 id processValue = [[[arrayToProcess oo_arrayAtIndex:j] oo_arrayAtIndex:k] oo_objectAtIndex:lookupIndex defaultValue:nil];
1477 id refValue = [[refArray oo_arrayAtIndex:i] oo_objectAtIndex:lookupIndex defaultValue:nil];
1478
1479 if ([processValue isEqual:refValue])
1480 {
1481 [[arrayToProcess objectAtIndex:j] replaceObjectAtIndex:k withObject:[refArray objectAtIndex:i]];
1482 [refArray removeObjectAtIndex:i];
1483 }
1484 }
1485 }
1486 }
1487 // arrayToProcess has been processed at this point. Any necessary merging has been done.
1488}

◆ handleEquipmentOverrides:

+ (void) handleEquipmentOverrides: (NSMutableArray *) arrayToProcess

Definition at line 104 of file ResourceManager.m.

1495 : (NSMutableArray *)arrayToProcess
1496{
1497 NSEnumerator *equipKeyEnum = nil;
1498 NSString *equipKey = nil;
1499 NSDictionary *overrides = nil;
1500 NSDictionary *overridesEntry = nil;
1501 int i;
1502
1503 overrides = [ResourceManager dictionaryFromFilesNamed:@"equipment-overrides.plist"
1504 inFolder:@"Config"
1505 mergeMode:MERGE_SMART
1506 cache:NO];
1507
1508 // cycle through all the equipment keys found in override files
1509 for (equipKeyEnum = [overrides keyEnumerator]; (equipKey = [equipKeyEnum nextObject]); )
1510 {
1511 overridesEntry = [overrides objectForKey:equipKey];
1512 // loop through our data array to find a match
1513 for (i = 0; i < [arrayToProcess count]; i++)
1514 {
1515 NSMutableArray *equipArray = [[[arrayToProcess objectAtIndex:i] mutableCopy] autorelease];
1516 id refValue = [equipArray oo_objectAtIndex:EQUIPMENT_KEY_INDEX defaultValue:nil];
1517 // does the overridden equipment item exist in the equipment array? if so, get working
1518 if ([equipKey isEqual:refValue])
1519 {
1520 NSEnumerator *infoKeyEnum = nil;
1521 NSString *infoKey;
1522 // cycle through all the properties found for this equipment key in the overrides file
1523 for (infoKeyEnum = [overridesEntry keyEnumerator]; (infoKey = [infoKeyEnum nextObject]); )
1524 {
1525 // special cases for the array items that don't have a direct keyname
1526 if ([infoKey isEqualToString:@"techlevel"])
1527 [equipArray replaceObjectAtIndex:EQUIPMENT_TECH_LEVEL_INDEX withObject:[overridesEntry objectForKey:infoKey]];
1528 else if ([infoKey isEqualToString:@"price"])
1529 [equipArray replaceObjectAtIndex:EQUIPMENT_PRICE_INDEX withObject:[overridesEntry objectForKey:infoKey]];
1530 else if ([infoKey isEqualToString:@"short_description"])
1531 [equipArray replaceObjectAtIndex:EQUIPMENT_SHORT_DESC_INDEX withObject:[overridesEntry objectForKey:infoKey]];
1532 else if ([infoKey isEqualToString:@"name"])
1533 [equipArray replaceObjectAtIndex:EQUIPMENT_SHORT_DESC_INDEX withObject:[overridesEntry objectForKey:infoKey]];
1534 else if ([infoKey isEqualToString:@"long_description"])
1535 [equipArray replaceObjectAtIndex:EQUIPMENT_LONG_DESC_INDEX withObject:[overridesEntry objectForKey:infoKey]];
1536 else if ([infoKey isEqualToString:@"description"])
1537 [equipArray replaceObjectAtIndex:EQUIPMENT_LONG_DESC_INDEX withObject:[overridesEntry objectForKey:infoKey]];
1538 else
1539 {
1540 NSMutableDictionary *extra = nil;
1541 // for everything else
1542 // do we actually have an extras dictionary?
1543 if (![equipArray oo_dictionaryAtIndex:EQUIPMENT_EXTRA_INFO_INDEX])
1544 {
1545 // if not, create a blank one we can add to
1546 extra = [NSMutableDictionary dictionary];
1547 }
1548 else
1549 {
1550 extra = [[equipArray oo_dictionaryAtIndex:EQUIPMENT_EXTRA_INFO_INDEX] mutableCopy];
1551 }
1552 // special case for weapon_info && script_info, which are child dictionaries
1553 if ([infoKey isEqualToString:@"weapon_info"] || [infoKey isEqualToString:@"script_info"])
1554 {
1555 NSEnumerator *subEnum = nil;
1556 NSString *subKey;
1557 NSMutableDictionary *subInfo = nil;
1558 NSDictionary *subOverrides = nil;
1559 // do we actually have a weapon_info/script_info dictionary?
1560 if (![extra oo_dictionaryForKey:infoKey])
1561 {
1562 // if not, create a blank dictionary we can add to
1563 subInfo = [NSMutableDictionary dictionary];
1564 }
1565 else
1566 {
1567 subInfo = [[extra oo_dictionaryForKey:infoKey] mutableCopy];
1568 }
1569 subOverrides = [overridesEntry oo_dictionaryForKey:infoKey];
1570 // cycle through all the sub keys found in the overrides file for this equipment key item
1571 for (subEnum = [subOverrides keyEnumerator]; (subKey = [subEnum nextObject]); )
1572 {
1573 [subInfo setObject:[subOverrides objectForKey:subKey] forKey:subKey];
1574 }
1575 [extra setObject:[[subInfo copy] autorelease] forKey:infoKey];
1576 }
1577 else
1578 {
1579 // for all other keys in the extras dictionary
1580 [extra setObject:[overridesEntry objectForKey:infoKey] forKey:infoKey];
1581 }
1582 [equipArray replaceObjectAtIndex:EQUIPMENT_EXTRA_INFO_INDEX withObject:[[extra copy] autorelease]];
1583 }
1584 }
1585 [arrayToProcess replaceObjectAtIndex:i withObject:equipArray];
1586 }
1587 }
1588 }
1589}
@ EQUIPMENT_EXTRA_INFO_INDEX
Definition Universe.h:84
NSDictionary * dictionaryFromFilesNamed:inFolder:mergeMode:cache:(NSString *fileName,[inFolder] NSString *folderName,[mergeMode] OOResourceMergeMode mergeMode,[cache] BOOL useCache)

◆ handleStarNebulaListMerging:

+ (void) handleStarNebulaListMerging: (NSMutableArray *) arrayToProcess

Definition at line 104 of file ResourceManager.m.

1594 : (NSMutableArray *)arrayToProcess
1595{
1596 NSUInteger i,j,k;
1597 NSMutableArray *refArray = [arrayToProcess objectAtIndex:[arrayToProcess count] - 1];
1598
1599 // Any change to refArray will directly modify arrayToProcess.
1600 for (i = 0; i < [refArray count]; i++)
1601 {
1602 for (j = 0; j < [arrayToProcess count] - 1; j++)
1603 {
1604 NSUInteger count = [[arrayToProcess oo_arrayAtIndex:j] count];
1605 if (count == 0) continue;
1606
1607 for (k = 0; k < count; k++)
1608 {
1609 id processValue = [[arrayToProcess oo_arrayAtIndex:j] oo_objectAtIndex:k defaultValue:nil];
1610 id refValue = [refArray oo_objectAtIndex:i defaultValue:nil];
1611 NSString *key1 = nil;
1612 NSString *key2 = nil;
1613
1614 if ([processValue isKindOfClass:[NSString class]])
1615 {
1616 key1 = processValue;
1617 }
1618 else if ([processValue isKindOfClass:[NSDictionary class]])
1619 {
1620 if (![processValue objectForKey:@"key"])
1621 {
1622 key1 = [processValue objectForKey:@"texture"];
1623 }
1624 else
1625 {
1626 key1 = [processValue objectForKey:@"key"];
1627 }
1628 }
1629 if (!key1) continue;
1630
1631 if ([refValue isKindOfClass:[NSString class]])
1632 {
1633 key2 = refValue;
1634 }
1635 else if ([refValue isKindOfClass:[NSDictionary class]])
1636 {
1637 if (![refValue objectForKey:@"key"])
1638 {
1639 key2 = [refValue objectForKey:@"texture"];
1640 }
1641 else
1642 {
1643 key2 = [refValue objectForKey:@"key"];
1644 }
1645 }
1646 if (!key2) continue;
1647
1648 if ([key1 isEqual:key2])
1649 {
1650 [[arrayToProcess objectAtIndex:j] replaceObjectAtIndex:k withObject:[refArray objectAtIndex:i]];
1651 [refArray removeObjectAtIndex:i];
1652 }
1653
1654 }
1655 }
1656 }
1657 // arrayToProcess has been processed at this point. Any necessary merging has been done.
1658}

◆ loadScripts

+ (NSDictionary *) loadScripts

Definition at line 1679 of file ResourceManager.m.

2070{
2071 NSMutableDictionary *loadedScripts = nil;
2072 NSArray *results = nil;
2073 NSArray *paths = nil;
2074 NSEnumerator *pathEnum = nil;
2075 NSString *path = nil;
2076 NSEnumerator *scriptEnum = nil;
2077 OOScript *script = nil;
2078 NSString *name = nil;
2079 NSAutoreleasePool *pool = nil;
2080
2081 OOLog(@"script.load.world.begin", @"%@", @"Loading world scripts...");
2082
2083 loadedScripts = [NSMutableDictionary dictionary];
2085 for (pathEnum = [paths objectEnumerator]; (path = [pathEnum nextObject]); )
2086 {
2087 // excluding world-scripts.plist also excludes script.js / script.plist
2088 // though as those core files don't and won't exist this is not
2089 // a problem.
2090 if (![ResourceManager corePlist:@"world-scripts.plist" excludedAt:path])
2091 {
2092 pool = [[NSAutoreleasePool alloc] init];
2093
2094 @try
2095 {
2096 results = [OOScript worldScriptsAtPath:[path stringByAppendingPathComponent:@"Config"]];
2097 if (results == nil) results = [OOScript worldScriptsAtPath:path];
2098 if (results != nil)
2099 {
2100 for (scriptEnum = [results objectEnumerator]; (script = [scriptEnum nextObject]); )
2101 {
2102 name = [script name];
2103 if (name != nil) [loadedScripts setObject:script forKey:name];
2104 else OOLog(@"script.load.unnamed", @"Discarding anonymous script %@", script);
2105 }
2106 }
2107 }
2108 @catch (NSException *exception)
2109 {
2110 OOLog(@"script.load.exception", @"***** %s encountered exception %@ (%@) while trying to load script from %@ -- ignoring this location.", __PRETTY_FUNCTION__, [exception name], [exception reason], path);
2111 // Ignore exception and keep loading other scripts.
2112 }
2113
2114 [pool release];
2115 }
2116 }
2117
2118 if (OOLogWillDisplayMessagesInClass(@"script.load.world.listAll"))
2119 {
2120 NSUInteger count = [loadedScripts count];
2121 if (count != 0)
2122 {
2123 NSMutableArray *displayNames = nil;
2124 NSEnumerator *scriptEnum = nil;
2125 OOScript *script = nil;
2126 NSString *displayString = nil;
2127
2128 displayNames = [NSMutableArray arrayWithCapacity:count];
2129
2130 for (scriptEnum = [loadedScripts objectEnumerator]; (script = [scriptEnum nextObject]); )
2131 {
2132 [displayNames addObject:[script displayName]];
2133 }
2134
2135 displayString = [[displayNames sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)] componentsJoinedByString:@"\n "];
2136 OOLog(@"script.load.world.listAll", @"Loaded %lu world scripts:\n %@", count, displayString);
2137 }
2138 else
2139 {
2140 OOLog(@"script.load.world.listAll", @"%@", @"*** No world scripts loaded.");
2141 }
2142 }
2143
2144 return loadedScripts;
2145}
BOOL OOLogWillDisplayMessagesInClass(NSString *inMessageClass)
Definition OOLogging.m:144
NSString * name()
Definition OOScript.m:256
NSArray * worldScriptsAtPath:(NSString *path)
Definition OOScript.m:45
NSString * displayName()
Definition OOScript.m:277

◆ LogClassKeyRoot

+ (static NSString *) LogClassKeyRoot (NSString *) key
implementation

Definition at line 1679 of file ResourceManager.m.

1680{
1681 NSRange dot = [key rangeOfString:@"."];
1682 if (dot.location != NSNotFound)
1683 {
1684 return [key substringToIndex:dot.location];
1685 }
1686 else
1687 {
1688 return key;
1689 }
1690}

◆ logControlDictionary

+ (NSDictionary *) logControlDictionary

Definition at line 1679 of file ResourceManager.m.

1694{
1695 // Load built-in copy of logcontrol.plist.
1696 NSString *path = [[[ResourceManager builtInPath] stringByAppendingPathComponent:@"Config"]
1697 stringByAppendingPathComponent:@"logcontrol.plist"];
1698 NSMutableDictionary *logControl = [NSMutableDictionary dictionaryWithDictionary:OODictionaryFromFile(path)];
1699 if (logControl == nil) logControl = [NSMutableDictionary dictionary];
1700
1701 // Build list of root log message classes that appear in the built-in list.
1702 NSMutableSet *coreRoots = [NSMutableSet set];
1703 NSString *key = nil;
1704 foreachkey(key, logControl)
1705 {
1706 [coreRoots addObject:LogClassKeyRoot(key)];
1707 }
1708
1709 NSArray *rootPaths = [self rootPaths];
1710 NSString *configPath = nil;
1711 NSDictionary *dict = nil;
1712
1713 // Look for logcontrol.plists inside OXPs (but not in root paths). These are not allowed to define keys in hierarchies used by the build-in one.
1714 NSEnumerator *pathEnum = [self pathEnumerator];
1715 while ((path = [pathEnum nextObject]))
1716 {
1717 if ([rootPaths containsObject:path]) continue;
1718
1719 configPath = [[path stringByAppendingPathComponent:@"Config"]
1720 stringByAppendingPathComponent:@"logcontrol.plist"];
1721 dict = OODictionaryFromFile(configPath);
1722 if (dict == nil)
1723 {
1724 configPath = [path stringByAppendingPathComponent:@"logcontrol.plist"];
1725 dict = OODictionaryFromFile(configPath);
1726 }
1727 foreachkey (key, dict)
1728 {
1729 if (![coreRoots containsObject:LogClassKeyRoot(key)])
1730 {
1731 [logControl setObject:[dict objectForKey:key] forKey:key];
1732 }
1733 }
1734 }
1735
1736 // Now, look for logcontrol.plists in root paths, i.e. not within OXPs. These are allowed to override the built-in copy.
1737 pathEnum = [rootPaths objectEnumerator];
1738 while ((path = [pathEnum nextObject]))
1739 {
1740 configPath = [[path stringByAppendingPathComponent:@"Config"]
1741 stringByAppendingPathComponent:@"logcontrol.plist"];
1742 dict = OODictionaryFromFile(configPath);
1743 if (dict == nil)
1744 {
1745 configPath = [path stringByAppendingPathComponent:@"logcontrol.plist"];
1746 dict = OODictionaryFromFile(configPath);
1747 }
1748 foreachkey (key, dict)
1749 {
1750 [logControl setObject:[dict objectForKey:key] forKey:key];
1751 }
1752 }
1753
1754 // Finally, look in preferences, which can override all of the above.
1755 dict = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"logging-enable"];
1756 if (dict != nil) [logControl addEntriesFromDictionary:dict];
1757
1758 return logControl;
1759}
#define foreachkey(VAR, DICT)
Definition OOCocoa.h:366
static NSString * LogClassKeyRoot(NSString *key)

Referenced by LoadExplicitSettings().

+ Here is the caller graph for this function:

◆ logPaths

+ (void) logPaths
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 1679 of file ResourceManager.m.

2232{
2233 NSMutableArray *displayPaths = nil;
2234 NSEnumerator *pathEnum = nil;
2235 NSString *path = nil;
2236
2237 // Prettify paths for logging.
2238 displayPaths = [NSMutableArray arrayWithCapacity:[sSearchPaths count]];
2239 for (pathEnum = [sSearchPaths objectEnumerator]; (path = [pathEnum nextObject]); )
2240 {
2241 [displayPaths addObject:[[path stringByStandardizingPath] stringByAbbreviatingWithTildeInPath]];
2242 }
2243
2244 OOLog(@"searchPaths.dumpAll", @"Resource paths: %@\n %@", sUseAddOns, [displayPaths componentsJoinedByString:@"\n "]);
2245
2246}
static NSString * sUseAddOns

◆ manifest:HasUnmetDependency:logErrors:

+ (BOOL) manifest: (NSDictionary *) manifest
HasUnmetDependency: (NSDictionary *) required
logErrors: (BOOL) logErrors 

Definition at line 104 of file ResourceManager.m.

875 :(NSDictionary *)manifest HasUnmetDependency:(NSDictionary *)required logErrors:(BOOL)logErrors
876{
877 NSString *requiredID = [required oo_stringForKey:kOOManifestRelationIdentifier];
878 NSMutableDictionary *requiredManifest = [sOXPManifests objectForKey:requiredID];
879 // if the other OXP is in the list
880 BOOL requirementsMet = NO;
881 if (requiredManifest != nil)
882 {
883 // then check versions
884 if ([self matchVersions:required withVersion:[requiredManifest oo_stringForKey:kOOManifestVersion]])
885 {
886 requirementsMet = YES;
887 /* Mark the requiredManifest as a dependency of the
888 * requiring manifest */
889 NSSet *reqby = [requiredManifest oo_setForKey:kOOManifestRequiredBy defaultValue:[NSSet set]];
890 NSUInteger reqbycount = [reqby count];
891 /* then add this manifest to its required set. This is
892 * done without checking if it's already there, because
893 * the list of nested requirements may have changed. */
894 reqby = [reqby setByAddingObject:[manifest oo_stringForKey:kOOManifestIdentifier]];
895 // *and* anything that requires this OXP to be installed
896 reqby = [reqby setByAddingObjectsFromSet:[manifest oo_setForKey:kOOManifestRequiredBy]];
897 if (reqbycount < [reqby count])
898 {
899 /* Then the set has increased in size. To handle
900 * potential cases with nested dependencies, need to
901 * re-run the requirement filter until all the sets
902 * stabilise. */
903 sAllMet = NO;
904 }
905 // and push back into the requiring manifest
906 [requiredManifest setObject:reqby forKey:kOOManifestRequiredBy];
907 }
908 }
909 if (!requirementsMet)
910 {
911 if (logErrors)
912 {
913 [self addErrorWithKey:@"oxp-required" param1:[manifest oo_stringForKey:kOOManifestTitle] param2:[required oo_stringForKey:kOOManifestRelationDescription defaultValue:[required oo_stringForKey:kOOManifestRelationIdentifier]]];
914 OOLog(@"oxp.requirementMissing",@"OXP %@ had unmet requirements and was removed from the loading list",[[manifest oo_stringForKey:kOOManifestFilePath] lastPathComponent]);
915 }
916 return YES;
917 }
918 return NO;
919}
static NSString *const kOOManifestVersion
static NSString *const kOOManifestFilePath

◆ manifestAllowedByScenario:

+ (BOOL) manifestAllowedByScenario: (NSDictionary *) manifest
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 104 of file ResourceManager.m.

1028 :(NSDictionary *)manifest
1029{
1030 /* Checks for a couple of "never happens" cases */
1031#ifndef NDEBUG
1032 // test string
1033 if ([sUseAddOns isEqualToString:SCENARIO_OXP_DEFINITION_ALL])
1034 {
1035 OOLog(@"scenario.check", @"%@", @"Checked scenario allowances in all state - this is an internal error; please report this");
1036 return YES;
1037 }
1038 if ([sUseAddOns isEqualToString:SCENARIO_OXP_DEFINITION_NONE])
1039 {
1040 OOLog(@"scenario.check", @"%@", @"Checked scenario allowances in none state - this is an internal error; please report this");
1041 return NO;
1042 }
1043#endif
1044 if ([[manifest oo_stringForKey:kOOManifestIdentifier] isEqualToString:@"org.oolite.oolite"])
1045 {
1046 // the core data is always allowed!
1047 return YES;
1048 }
1049
1050 NSString *uaoBit = nil;
1051 BOOL result = NO;
1052 foreach (uaoBit, sUseAddOnsParts)
1053 {
1054 if ([uaoBit hasPrefix:SCENARIO_OXP_DEFINITION_BYID])
1055 {
1056 result |= [ResourceManager manifestAllowedByScenario:manifest withIdentifier:[uaoBit substringFromIndex:[SCENARIO_OXP_DEFINITION_BYID length]]];
1057 }
1058 else if ([uaoBit hasPrefix:SCENARIO_OXP_DEFINITION_BYTAG])
1059 {
1060 result |= [ResourceManager manifestAllowedByScenario:manifest withTag:[uaoBit substringFromIndex:[SCENARIO_OXP_DEFINITION_BYTAG length]]];
1061 }
1062 }
1063 return result;
1064}
static NSString *const kOOManifestIdentifier
#define SCENARIO_OXP_DEFINITION_BYID
#define SCENARIO_OXP_DEFINITION_NONE
#define SCENARIO_OXP_DEFINITION_ALL
#define SCENARIO_OXP_DEFINITION_BYTAG
BOOL manifestAllowedByScenario:withTag:(NSDictionary *manifest, [withTag] NSString *tag)
BOOL manifestAllowedByScenario:withIdentifier:(NSDictionary *manifest, [withIdentifier] NSString *identifier)

◆ manifestAllowedByScenario:withIdentifier:

+ (BOOL) manifestAllowedByScenario: (NSDictionary *) manifest
withIdentifier: (NSString *) identifier 
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 104 of file ResourceManager.m.

1067 :(NSDictionary *)manifest withIdentifier:(NSString *)identifier
1068{
1069 if ([[manifest oo_stringForKey:kOOManifestIdentifier] isEqualToString:identifier])
1070 {
1071 // manifest has the identifier - easy
1072 return YES;
1073 }
1074 // manifest is also allowed if a manifest with that identifier
1075 // requires it to be installed
1076 if ([[manifest oo_setForKey:kOOManifestRequiredBy] containsObject:identifier])
1077 {
1078 return YES;
1079 }
1080 // otherwise, no
1081 return NO;
1082}
static NSString *const kOOManifestRequiredBy

◆ manifestAllowedByScenario:withTag:

+ (BOOL) manifestAllowedByScenario: (NSDictionary *) manifest
withTag: (NSString *) tag 
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 104 of file ResourceManager.m.

1085 :(NSDictionary *)manifest withTag:(NSString *)tag
1086{
1087 if ([[manifest oo_arrayForKey:kOOManifestTags] containsObject:tag])
1088 {
1089 // manifest has the tag - easy
1090 return YES;
1091 }
1092 // manifest is also allowed if a manifest with that tag
1093 // requires it to be installed
1094 NSSet *reqby = [manifest oo_setForKey:kOOManifestRequiredBy];
1095 if (reqby != nil)
1096 {
1097 NSString *identifier = nil;
1098 foreach (identifier, reqby)
1099 {
1100 NSDictionary *reqManifest = [sOXPManifests oo_dictionaryForKey:identifier defaultValue:nil];
1101 // need to check for nil as this one may already have been ruled out
1102 if (reqManifest != nil && [[reqManifest oo_arrayForKey:kOOManifestTags] containsObject:tag])
1103 {
1104 return YES;
1105 }
1106 }
1107 }
1108 // otherwise, no
1109 return NO;
1110}

◆ manifestForIdentifier:

+ (NSDictionary *) manifestForIdentifier: (NSString *) identifier

Definition at line 104 of file ResourceManager.m.

558 :(NSString *)identifier
559{
560 return [sOXPManifests objectForKey:identifier];
561}

◆ manifestHasConflicts:logErrors:

+ (BOOL) manifestHasConflicts: (NSDictionary *) manifest
logErrors: (BOOL) logErrors 

Definition at line 104 of file ResourceManager.m.

793 :(NSDictionary *)manifest logErrors:(BOOL)logErrors
794{
795 NSDictionary *conflicting = nil;
796 NSDictionary *conflictManifest = nil;
797 NSString *conflictID = nil;
798 NSArray *conflicts = nil;
799
800 conflicts = [manifest oo_arrayForKey:kOOManifestConflictOXPs defaultValue:nil];
801 // if it has a non-empty conflict_oxps list
802 if (conflicts != nil && [conflicts count] > 0)
803 {
804 // iterate over that list
805 foreach (conflicting, conflicts)
806 {
807 conflictID = [conflicting oo_stringForKey:kOOManifestRelationIdentifier];
808 conflictManifest = [sOXPManifests objectForKey:conflictID];
809 // if the other OXP is in the list
810 if (conflictManifest != nil)
811 {
812 // then check versions
813 if ([self matchVersions:conflicting withVersion:[conflictManifest oo_stringForKey:kOOManifestVersion]])
814 {
815 if (logErrors)
816 {
817 [self addErrorWithKey:@"oxp-conflict" param1:[manifest oo_stringForKey:kOOManifestTitle] param2:[conflictManifest oo_stringForKey:kOOManifestTitle]];
818 OOLog(@"oxp.conflict",@"OXP %@ conflicts with %@ and was removed from the loading list",[[manifest oo_stringForKey:kOOManifestFilePath] lastPathComponent],[[conflictManifest oo_stringForKey:kOOManifestFilePath] lastPathComponent]);
819 }
820 return YES;
821 }
822 }
823 }
824 }
825 return NO;
826}

◆ manifestHasMissingDependencies:logErrors:

+ (BOOL) manifestHasMissingDependencies: (NSDictionary *) manifest
logErrors: (BOOL) logErrors 

Definition at line 104 of file ResourceManager.m.

853 :(NSDictionary *)manifest logErrors:(BOOL)logErrors
854{
855 NSDictionary *required = nil;
856 NSArray *requireds = nil;
857
858 requireds = [manifest oo_arrayForKey:kOOManifestRequiresOXPs defaultValue:nil];
859 // if it has a non-empty required_oxps list
860 if (requireds != nil && [requireds count] > 0)
861 {
862 // iterate over that list
863 foreach (required, requireds)
864 {
865 if ([ResourceManager manifest:manifest HasUnmetDependency:required logErrors:logErrors])
866 {
867 return YES;
868 }
869 }
870 }
871 return NO;
872}

◆ matchVersions:withVersion:

+ (BOOL) matchVersions: (NSDictionary *) rangeDict
withVersion: (NSString *) version 

Definition at line 104 of file ResourceManager.m.

951 :(NSDictionary *)rangeDict withVersion:(NSString *)version
952{
953 NSString *minimum = [rangeDict oo_stringForKey:kOOManifestRelationVersion defaultValue:nil];
954 NSString *maximum = [rangeDict oo_stringForKey:kOOManifestRelationMaxVersion defaultValue:nil];
955 NSArray *isVersionComponents = ComponentsFromVersionString(version);
956 NSArray *reqVersionComponents = nil;
957 if (minimum != nil)
958 {
959 reqVersionComponents = ComponentsFromVersionString(minimum);
960 if (NSOrderedAscending == CompareVersions(isVersionComponents, reqVersionComponents))
961 {
962 // earlier than minimum version
963 return NO;
964 }
965 }
966 if (maximum != nil)
967 {
968 reqVersionComponents = ComponentsFromVersionString(maximum);
969 if (NSOrderedDescending == CompareVersions(isVersionComponents, reqVersionComponents))
970 {
971 // later than maximum version
972 return NO;
973 }
974 }
975 // either version was okay, or no version info so an unconditional match
976 return YES;
977}

◆ materialDefaults

+ (NSDictionary *) materialDefaults

Definition at line 1679 of file ResourceManager.m.

2194{
2195 return [self dictionaryFromFilesNamed:@"material-defaults.plist" inFolder:@"Config" andMerge:YES];
2196}

Referenced by OODefaultShipShaderMacros(), ShipSetMaterialsInternal(), and VisualEffectSetMaterialsInternal().

+ Here is the caller graph for this function:

◆ mergeRoleCategories:intoDictionary:

+ (void) mergeRoleCategories: (NSDictionary *) catData
intoDictionary: (NSMutableDictionary *) categories 
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 1679 of file ResourceManager.m.

1799 :(NSDictionary *)catData intoDictionary:(NSMutableDictionary *)categories
1800{
1801 NSMutableSet *contents = nil;
1802 NSArray *catDataEntry = nil;
1803 NSString *key;
1804 foreachkey(key, catData)
1805 {
1806 contents = [categories objectForKey:key];
1807 if (contents == nil)
1808 {
1809 contents = [NSMutableSet setWithCapacity:16];
1810 [categories setObject:contents forKey:key];
1811 }
1812 catDataEntry = [catData oo_arrayForKey:key];
1813 OOLog(@"shipData.load.roleCategories", @"Adding %ld entries for category %@", (unsigned long)[catDataEntry count], key);
1814 [contents addObjectsFromArray:catDataEntry];
1815 }
1816}

◆ ooMusicNamed:inFolder:

+ (OOMusic *) ooMusicNamed: (NSString *) fileName
inFolder: (NSString *) folderName 

Definition at line 1679 of file ResourceManager.m.

2011 :(NSString *)fileName inFolder:(NSString *)folderName
2012{
2013 return [self retrieveFileNamed:fileName
2014 inFolder:folderName
2015 cache:NULL // Don't cache music objects; minimizing latency isn't really important.
2016 key:[NSString stringWithFormat:@"OOMusic:%@:%@", folderName, fileName]
2017 class:[OOMusic class]
2018 usePathCache:YES];
2019}

◆ ooSoundNamed:inFolder:

+ (OOSound *) ooSoundNamed: (NSString *) fileName
inFolder: (NSString *) folderName 

Definition at line 1679 of file ResourceManager.m.

2022 :(NSString *)fileName inFolder:(NSString *)folderName
2023{
2024 return [self retrieveFileNamed:fileName
2025 inFolder:folderName
2026 cache:&sSoundCache
2027 key:[NSString stringWithFormat:@"OOSound:%@:%@", folderName, fileName]
2028 class:[OOSound class]
2029 usePathCache:YES];
2030}

Referenced by Universe::addConditionScripts:, and GetNamedSound().

+ Here is the caller graph for this function:

◆ OXPsWithMessagesFound

+ (NSArray *) OXPsWithMessagesFound

Definition at line 104 of file ResourceManager.m.

553{
554 return [[sOXPsWithMessagesFound copy] autorelease];
555}

◆ pathEnumerator

+ (NSEnumerator *) pathEnumerator

Definition at line 104 of file ResourceManager.m.

541{
542 return [[self paths] objectEnumerator];
543}

◆ pathForFileNamed:inFolder:

+ (NSString *) pathForFileNamed: (NSString *) fileName
inFolder: (NSString *) folderName 

Definition at line 1679 of file ResourceManager.m.

1916 :(NSString *)fileName inFolder:(NSString *)folderName
1917{
1918 return [self pathForFileNamed:fileName inFolder:folderName cache:YES];
1919}

Referenced by NSObject(OODebugPlugInController)::setUpDebugger.

+ Here is the caller graph for this function:

◆ pathForFileNamed:inFolder:cache:

+ (NSString *) pathForFileNamed: (NSString *) fileName
inFolder: (NSString *) folderName
cache: (BOOL) useCache 

Definition at line 1679 of file ResourceManager.m.

1923 :(NSString *)fileName inFolder:(NSString *)folderName cache:(BOOL)useCache
1924{
1925 NSString *result = nil;
1926 NSString *cacheKey = nil;
1928 NSEnumerator *pathEnum = nil;
1929 NSString *path = nil;
1930 NSString *filePath = nil;
1931 NSFileManager *fmgr = nil;
1932
1933 if (fileName == nil) return nil;
1934
1935 if (cache)
1936 {
1937 if (folderName != nil) cacheKey = [NSString stringWithFormat:@"%@/%@", folderName, fileName];
1938 else cacheKey = fileName;
1939 result = [cache objectForKey:cacheKey inCache:@"resolved paths"];
1940 if (result != nil) return result;
1941 }
1942
1943 // Search for file
1944 fmgr = [NSFileManager defaultManager];
1945 // reverse object enumerator allows OXPs to override core
1946 for (pathEnum = [[ResourceManager paths] reverseObjectEnumerator]; (path = [pathEnum nextObject]); )
1947 {
1948 filePath = [[path stringByAppendingPathComponent:folderName] stringByAppendingPathComponent:fileName];
1949 if ([fmgr oo_oxzFileExistsAtPath:filePath])
1950 {
1951 result = filePath;
1952 break;
1953 }
1954
1955 filePath = [path stringByAppendingPathComponent:fileName];
1956 if ([fmgr oo_oxzFileExistsAtPath:filePath])
1957 {
1958 result = filePath;
1959 break;
1960 }
1961 }
1962
1963 if (result != nil)
1964 {
1965 OOLog(@"resourceManager.foundFile", @"Found %@/%@ at %@", folderName, fileName, filePath);
1966 if (useCache)
1967 {
1968 [cache setObject:result forKey:cacheKey inCache:@"resolved paths"];
1969 }
1970 }
1971 return result;
1972}

◆ paths

+ (NSArray *) paths

Definition at line 104 of file ResourceManager.m.

472{
474 {
475 sSearchPaths = [[NSMutableArray alloc] init];
476 }
477 return [self pathsWithAddOns];
478}

Referenced by OoliteGetProperty().

+ Here is the caller graph for this function:

◆ pathsWithAddOns

+ (NSArray *) pathsWithAddOns

Definition at line 104 of file ResourceManager.m.

228{
229 if ([sSearchPaths count] > 0) return sSearchPaths;
230
231 if (sUseAddOns == nil)
232 {
233 sUseAddOns = [[NSString alloc] initWithString:SCENARIO_OXP_DEFINITION_ALL];
234 sUseAddOnsParts = [[sUseAddOns componentsSeparatedByString:@";"] retain];
235 }
236
237 /* Handle special case of 'strict mode' efficiently */
238 // testing actual string
239 if ([sUseAddOns isEqualToString:SCENARIO_OXP_DEFINITION_NONE])
240 {
241 return (NSArray *)[NSArray arrayWithObject:[self builtInPath]];
242 }
243
244 [sErrors release];
245 sErrors = nil;
246
247 NSFileManager *fmgr = [NSFileManager defaultManager];
248 NSArray *rootPaths = nil;
249 NSMutableArray *existingRootPaths = nil;
250 NSEnumerator *pathEnum = nil;
251 NSString *root = nil;
252 NSDirectoryEnumerator *dirEnum = nil;
253 NSString *subPath = nil;
254 NSString *path = nil;
255 BOOL isDirectory;
256
257 // Copy those root paths that actually exist to search paths.
258 rootPaths = [self rootPaths];
259 existingRootPaths = [NSMutableArray arrayWithCapacity:[rootPaths count]];
260 for (pathEnum = [rootPaths objectEnumerator]; (root = [pathEnum nextObject]); )
261 {
262 if ([fmgr fileExistsAtPath:root isDirectory:&isDirectory] && isDirectory)
263 {
264 [existingRootPaths addObject:root];
265 }
266 }
267
268 // validate default search paths
270 sSearchPaths = [NSMutableArray new];
271 foreach(path, existingRootPaths)
272 {
273 [self checkPotentialPath:path :sSearchPaths];
274 }
275
276 // Iterate over root paths.
277 for (pathEnum = [existingRootPaths objectEnumerator]; (root = [pathEnum nextObject]); )
278 {
279 // Iterate over each root path's contents.
280 if ([fmgr fileExistsAtPath:root isDirectory:&isDirectory] && isDirectory)
281 {
282 for (dirEnum = [fmgr enumeratorAtPath:root]; (subPath = [dirEnum nextObject]); )
283 {
284 // Check if it's a directory.
285 path = [root stringByAppendingPathComponent:subPath];
286 if ([fmgr fileExistsAtPath:path isDirectory:&isDirectory])
287 {
288 if (isDirectory)
289 {
290 // If it is, is it an OXP?.
291 if ([[[path pathExtension] lowercaseString] isEqualToString:@"oxp"])
292 {
293 [self checkPotentialPath:path :sSearchPaths];
294 if ([sSearchPaths containsObject:path]) [self checkOXPMessagesInPath:path];
295 }
296 else
297 {
298 // If not, don't search subdirectories.
299 [dirEnum skipDescendents];
300 }
301 }
302 else
303 {
304 // If not a directory, is it an OXZ?
305 if ([[[path pathExtension] lowercaseString] isEqualToString:@"oxz"])
306 {
307 [self checkPotentialPath:path :sSearchPaths];
308 if ([sSearchPaths containsObject:path]) [self checkOXPMessagesInPath:path];
309 }
310 }
311 }
312 }
313 }
314 }
315
316 for (pathEnum = [sExternalPaths objectEnumerator]; (path = [pathEnum nextObject]); )
317 {
318 [self checkPotentialPath:path :sSearchPaths];
319 if ([sSearchPaths containsObject:path]) [self checkOXPMessagesInPath:path];
320 }
321
322 /* If a scenario restriction is *not* in place, remove
323 * scenario-only OXPs. */
324 // test string
325 if ([sUseAddOns isEqualToString:SCENARIO_OXP_DEFINITION_ALL])
326 {
327 [self filterSearchPathsToExcludeScenarioOnlyPaths:sSearchPaths];
328 }
329
330 /* This is a conservative filter. It probably gets rid of more
331 * OXPs than it technically needs to in certain situations with
332 * dependency chains, but really any conflict here needs to be
333 * resolved by the user rather than Oolite. The point is to avoid
334 * loading OXPs which we shouldn't; if doing so takes out other
335 * OXPs which would have been safe, that's not important. */
336 [self filterSearchPathsForConflicts:sSearchPaths];
337
338 /* This one needs to be run repeatedly to be sure. Take the chain
339 * A depends on B depends on C. A and B are installed. A is
340 * checked first, and depends on B, which is thought to be
341 * okay. So A is kept. Then B is checked and removed. A must then
342 * be rechecked. This function therefore is run repeatedly until a
343 * run of it removes no further items.
344 *
345 * There may well be more elegant and efficient ways to do this
346 * but this is already fast enough for most purposes.
347 */
348 while (![self filterSearchPathsForRequirements:sSearchPaths]) {}
349
350 /* If a scenario restriction is in place, restrict OXPs to the
351 * ones valid for the scenario only. */
352 // test string
353 if (![sUseAddOns isEqualToString:SCENARIO_OXP_DEFINITION_ALL])
354 {
355 [self filterSearchPathsByScenario:sSearchPaths];
356 }
357
358 [self checkCacheUpToDateForPaths:sSearchPaths];
359
360 return sSearchPaths;
361}
#define DESTROY(x)
Definition OOCocoa.h:77

◆ preloadFileListFromFolder:forFolders:

+ (void) preloadFileListFromFolder: (NSString *) path
forFolders: (NSArray *) folders 
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 104 of file ResourceManager.m.

434 :(NSString *)path forFolders:(NSArray *)folders
435{
436 NSFileManager *fmgr = [NSFileManager defaultManager];
437 NSString *subFolder = nil;
438 NSString *subFolderPath = nil;
439 NSArray *fileList = nil;
440 NSString *fileName = nil;
441
442 // search each subfolder for files
443 foreach (subFolder, folders)
444 {
445 subFolderPath = [path stringByAppendingPathComponent:subFolder];
446 fileList = [fmgr oo_directoryContentsAtPath:subFolderPath];
447 foreach (fileName, fileList)
448 {
449 [self preloadFilePathFor:fileName inFolder:subFolder atPath:[subFolderPath stringByAppendingPathComponent:fileName]];
450 }
451 }
452
453}

◆ preloadFileListFromOXZ:forFolders:

+ (void) preloadFileListFromOXZ: (NSString *) path
forFolders: (NSArray *) folders 
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 104 of file ResourceManager.m.

386 :(NSString *)path forFolders:(NSArray *)folders
387{
388 unzFile uf = NULL;
389 const char* zipname = [path UTF8String];
390 char componentName[512];
391
392 if (zipname != NULL)
393 {
394 uf = unzOpen64(zipname);
395 }
396 if (uf == NULL)
397 {
398 OOLog(@"resourceManager.error",@"Could not open .oxz at %@ as zip file",path);
399 return;
400 }
401 if (unzGoToFirstFile(uf) == UNZ_OK)
402 {
403 do
404 {
406 componentName, 512,
407 NULL, 0,
408 NULL, 0);
409 NSString *zipEntry = [NSString stringWithUTF8String:componentName];
410 NSArray *pathBits = [zipEntry pathComponents];
411 if ([pathBits count] >= 2)
412 {
413 NSString *folder = [pathBits oo_stringAtIndex:0];
414 if ([folders containsObject:folder])
415 {
416 NSRange bitRange;
417 bitRange.location = 1;
418 bitRange.length = [pathBits count]-1;
419 NSString *file = [NSString pathWithComponents:[pathBits subarrayWithRange:bitRange]];
420 NSString *fullPath = [[path stringByAppendingPathComponent:folder] stringByAppendingPathComponent:file];
421
422 [self preloadFilePathFor:file inFolder:folder atPath:fullPath];
423 }
424 }
425
426 }
427 while (unzGoToNextFile(uf) == UNZ_OK);
428 }
429 unzClose(uf);
430
431}
int ZEXPORT unzGetCurrentFileInfo64(unzFile file, unz_file_info64 *pfile_info, char *szFileName, uLong fileNameBufferSize, void *extraField, uLong extraFieldBufferSize, char *szComment, uLong commentBufferSize)
Definition unzip.c:1130
int ZEXPORT unzGoToFirstFile(unzFile file)
Definition unzip.c:1184
unzFile ZEXPORT unzOpen64(const void *path)
Definition unzip.c:801
int ZEXPORT unzGoToNextFile(unzFile file)
Definition unzip.c:1205
int ZEXPORT unzClose(unzFile file)
Definition unzip.c:811
voidp unzFile
Definition unzip.h:70
#define UNZ_OK
Definition unzip.h:74

◆ preloadFileLists

+ (void) preloadFileLists
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 104 of file ResourceManager.m.

365{
366 NSString *path = nil;
367 NSEnumerator *pathEnum = nil;
368
369 // folders which may contain files to be cached
370 NSArray *folders = [NSArray arrayWithObjects:@"AIs",@"Images",@"Models",@"Music",@"Scenarios",@"Scripts",@"Shaders",@"Sounds",@"Textures",nil];
371
372 for (pathEnum = [[ResourceManager paths] reverseObjectEnumerator]; (path = [pathEnum nextObject]); )
373 {
374 if ([path hasSuffix:@".oxz"])
375 {
376 [self preloadFileListFromOXZ:path forFolders:folders];
377 }
378 else
379 {
380 [self preloadFileListFromFolder:path forFolders:folders];
381 }
382 }
383}

◆ preloadFilePathFor:inFolder:atPath:

+ (void) preloadFilePathFor: (NSString *) fileName
inFolder: (NSString *) subFolder
atPath: (NSString *) path 
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 104 of file ResourceManager.m.

456 :(NSString *)fileName inFolder:(NSString *)subFolder atPath:(NSString *)path
457{
459 NSString *cacheKey = [NSString stringWithFormat:@"%@/%@", subFolder, fileName];
460 NSString *result = [cache objectForKey:cacheKey inCache:@"resolved paths"];
461 // if nil, not found in another OXP already
462 if (result == nil)
463 {
464 OOLog(@"resourceManager.foundFile.preLoad", @"Found %@/%@ at %@", subFolder, fileName, path);
465 [cache setObject:path forKey:cacheKey inCache:@"resolved paths"];
466 }
467}

◆ reset

+ (void) reset

Definition at line 104 of file ResourceManager.m.

111{
112 sFirstRun = YES;
120}
static NSMutableDictionary * sOXPManifests
static BOOL sFirstRun

◆ resetManifestKnowledgeForOXZManager

+ (void) resetManifestKnowledgeForOXZManager

◆ retrieveFileNamed:inFolder:cache:key:class:usePathCache:

+ (id) retrieveFileNamed: (NSString *) fileName
inFolder: (NSString *) folderName
cache: (NSMutableDictionary **) ioCache
key: (NSString *) key
class: (Class) class
usePathCache: (BOOL) useCache 
implementation

Definition at line 1679 of file ResourceManager.m.

1977 :(NSString *)fileName
1978 inFolder:(NSString *)folderName
1979 cache:(NSMutableDictionary **)ioCache
1980 key:(NSString *)key
1981 class:(Class)class
1982 usePathCache:(BOOL)useCache
1983{
1984 id result = nil;
1985 NSString *path = nil;
1986
1987 if (ioCache)
1988 {
1989 if (key == nil) key = [NSString stringWithFormat:@"%@:%@", folderName, fileName];
1990 if (*ioCache != nil)
1991 {
1992 // return the cached object, if any
1993 result = [*ioCache objectForKey:key];
1994 if (result) return result;
1995 }
1996 }
1997
1998 path = [self pathForFileNamed:fileName inFolder:folderName cache:useCache];
1999 if (path != nil) result = [[[class alloc] initWithContentsOfFile:path] autorelease];
2000
2001 if (result != nil && ioCache != NULL)
2002 {
2003 if (*ioCache == nil) *ioCache = [[NSMutableDictionary alloc] init];
2004 [*ioCache setObject:result forKey:key];
2005 }
2006
2007 return result;
2008}

◆ reversePathEnumerator

+ (NSEnumerator *) reversePathEnumerator

Definition at line 104 of file ResourceManager.m.

547{
548 return [[self paths] reverseObjectEnumerator];
549}

◆ roleCategoriesDictionary

+ (NSDictionary *) roleCategoriesDictionary

Definition at line 1679 of file ResourceManager.m.

1763{
1764 NSMutableDictionary *roleCategories = [NSMutableDictionary dictionaryWithCapacity:16];
1765
1766 NSString *path = nil;
1767 NSString *configPath = nil;
1768 NSDictionary *categories = nil;
1769
1770 NSEnumerator *pathEnum = [self pathEnumerator];
1771 while ((path = [pathEnum nextObject]))
1772 {
1773 if ([ResourceManager corePlist:@"role-categories.plist" excludedAt:path])
1774 {
1775 continue;
1776 }
1777
1778 configPath = [[path stringByAppendingPathComponent:@"Config"]
1779 stringByAppendingPathComponent:@"role-categories.plist"];
1780 categories = OODictionaryFromFile(configPath);
1781 if (categories != nil)
1782 {
1783 [ResourceManager mergeRoleCategories:categories intoDictionary:roleCategories];
1784 }
1785 }
1786
1787 /* If the old pirate-victim-roles files exist, merge them in */
1788 NSArray *pirateVictims = [ResourceManager arrayFromFilesNamed:@"pirate-victim-roles.plist" inFolder:@"Config" andMerge:YES];
1789 if (OOEnforceStandards() && [pirateVictims count] > 0)
1790 {
1791 OOStandardsDeprecated(@"pirate-victim-roles.plist is still being used.");
1792 }
1793 [ResourceManager mergeRoleCategories:[NSDictionary dictionaryWithObject:pirateVictims forKey:@"oolite-pirate-victim"] intoDictionary:roleCategories];
1794
1795 return [[roleCategories copy] autorelease];
1796}
void OOStandardsDeprecated(NSString *message)
NSArray * arrayFromFilesNamed:inFolder:andMerge:(NSString *fileName,[inFolder] NSString *folderName,[andMerge] BOOL mergeFiles)
void mergeRoleCategories:intoDictionary:(NSDictionary *catData, [intoDictionary] NSMutableDictionary *categories)

◆ rootPaths

+ (NSArray *) rootPaths

Definition at line 104 of file ResourceManager.m.

164{
165 static NSArray *sRootPaths = nil;
166 if (sRootPaths == nil) {
167 /* Built-in data, then managed OXZs, then manually installed ones,
168 * which may be useful for debugging/testing purposes. */
169 sRootPaths = [NSArray arrayWithObjects:[self builtInPath], [[OOOXZManager sharedManager] installPath], nil];
170 sRootPaths = [[sRootPaths arrayByAddingObjectsFromArray:[self userRootPaths]] retain];
171 }
172 return sRootPaths;
173}
NSString * installPath()
OOOXZManager * sharedManager()

◆ setUseAddOns:

+ (void) setUseAddOns: (NSString *) useAddOns

Definition at line 104 of file ResourceManager.m.

487 :(NSString *)useAddOns
488{
489 if (sFirstRun || ![useAddOns isEqualToString:sUseAddOns])
490 {
491 [self reset];
492 sFirstRun = NO;
495 sUseAddOns = [useAddOns retain];
496 sUseAddOnsParts = [[sUseAddOns componentsSeparatedByString:@";"] retain];
497
500
502 /* only allow cache writes for the "all OXPs" default
503 *
504 * cache should be less necessary for restricted sets anyway */
505 // testing the actual string here
506 if ([sUseAddOns isEqualToString:SCENARIO_OXP_DEFINITION_ALL])
507 {
508 [cmgr reloadAllCaches];
509 [cmgr setAllowCacheWrites:YES];
510 }
511 else
512 {
513 [cmgr clearAllCaches];
514 [cmgr setAllowCacheWrites:NO];
515 }
516
517 [self checkCacheUpToDateForPaths:[self paths]];
518 [self logPaths];
519 /* preloading the file lists at this stage helps efficiency a
520 * lot when many OXZs are installed */
521 [self preloadFileLists];
522
523 }
524}
void OOHUDResetTextEngine(void)
void setAllowCacheWrites:(BOOL flag)
NSString * useAddOns()

◆ shaderBindingTypesDictionary

+ (NSDictionary *) shaderBindingTypesDictionary

Definition at line 1679 of file ResourceManager.m.

1871{
1873
1875 {
1876 NSAutoreleasePool *pool = [NSAutoreleasePool new];
1877
1878 NSString *path = [[[ResourceManager builtInPath] stringByAppendingPathComponent:@"Config"] stringByAppendingPathComponent:@"shader-uniform-bindings.plist"];
1879 NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfFile:path];
1880 NSArray *keys = [dict allKeys];
1881
1882 // Resolve all $inherit keys.
1883 unsigned changeCount = 0;
1884 do {
1885 changeCount = 0;
1886 NSString *key = nil;
1887 foreach (key, keys)
1888 {
1889 NSDictionary *value = [dict oo_dictionaryForKey:key];
1890 NSString *inheritKey = [value oo_stringForKey:@"$w2"];
1891 if (inheritKey != nil)
1892 {
1893 changeCount++;
1894 NSMutableDictionary *mutableValue = [[value mutableCopy] autorelease];
1895 [mutableValue removeObjectForKey:@"$w3"];
1896 NSDictionary *inherited = [dict oo_dictionaryForKey:inheritKey];
1897 if (inherited != nil)
1898 {
1899 [mutableValue addEntriesFromDictionary:inherited];
1900 }
1901
1902 [dict setObject:[[mutableValue copy] autorelease] forKey:key];
1903 }
1904 }
1905 } while (changeCount != 0);
1906
1907 shaderBindingTypesDictionary = [dict copy];
1908
1909 [pool release];
1910 }
1911
1913}
NSDictionary * shaderBindingTypesDictionary()

◆ stringFromFilesNamed:inFolder:

+ (NSString *) stringFromFilesNamed: (NSString *) fileName
inFolder: (NSString *) folderName 

Definition at line 1679 of file ResourceManager.m.

2033 :(NSString *)fileName inFolder:(NSString *)folderName
2034{
2035 return [self stringFromFilesNamed:fileName inFolder:folderName cache:YES];
2036}

Referenced by GetShaderSource().

+ Here is the caller graph for this function:

◆ stringFromFilesNamed:inFolder:cache:

+ (NSString *) stringFromFilesNamed: (NSString *) fileName
inFolder: (NSString *) folderName
cache: (BOOL) useCache 

Definition at line 1679 of file ResourceManager.m.

2039 :(NSString *)fileName inFolder:(NSString *)folderName cache:(BOOL)useCache
2040{
2041 id result = nil;
2042 NSString *path = nil;
2043 NSString *key = nil;
2044
2045 if (useCache)
2046 {
2047 key = [NSString stringWithFormat:@"%@:%@", folderName, fileName];
2048 if (sStringCache != nil)
2049 {
2050 // return the cached object, if any
2051 result = [sStringCache objectForKey:key];
2052 if (result) return result;
2053 }
2054 }
2055
2056 path = [self pathForFileNamed:fileName inFolder:folderName cache:YES];
2057 if (path != nil) result = [NSString stringWithContentsOfUnicodeFile:path];
2058
2059 if (result != nil && useCache)
2060 {
2061 if (sStringCache == nil) sStringCache = [[NSMutableDictionary alloc] init];
2062 [sStringCache setObject:result forKey:key];
2063 }
2064
2065 return result;
2066}

◆ systemDescriptionManager

+ (OOSystemDescriptionManager *) systemDescriptionManager

Definition at line 1679 of file ResourceManager.m.

1820{
1821 OOLog(@"resourceManager.planetinfo.load", @"%@", @"Initialising manager");
1823
1824 NSString *path = nil;
1825 NSString *configPath = nil;
1826 NSDictionary *categories = nil;
1827 NSString *systemKey = nil;
1828
1829 NSEnumerator *pathEnum = [self pathEnumerator];
1830 while ((path = [pathEnum nextObject]))
1831 {
1832 if ([ResourceManager corePlist:@"planetinfo.plist" excludedAt:path])
1833 {
1834 continue;
1835 }
1836 configPath = [[path stringByAppendingPathComponent:@"Config"]
1837 stringByAppendingPathComponent:@"planetinfo.plist"];
1838 categories = OODictionaryFromFile(configPath);
1839 if (categories != nil)
1840 {
1841 foreachkey(systemKey,categories)
1842 {
1843 NSDictionary *values = [categories oo_dictionaryForKey:systemKey defaultValue:nil];
1844 if (values != nil)
1845 {
1846 if ([systemKey isEqualToString:PLANETINFO_UNIVERSAL_KEY])
1847 {
1848 [manager setUniversalProperties:values];
1849 }
1850 else if ([systemKey isEqualToString:PLANETINFO_INTERSTELLAR_KEY])
1851 {
1852 [manager setInterstellarProperties:values];
1853 }
1854 else
1855 {
1856 [manager setProperties:values forSystemKey:systemKey];
1857 }
1858 }
1859 }
1860 }
1861 }
1862 OOLog(@"resourceManager.planetinfo.load", @"%@", @"Caching routes");
1863 [manager buildRouteCache];
1864 OOLog(@"resourceManager.planetinfo.load", @"%@", @"Initialised manager");
1865 return [manager autorelease];
1866}
#define PLANETINFO_UNIVERSAL_KEY
Definition Universe.h:153
#define PLANETINFO_INTERSTELLAR_KEY
Definition Universe.h:154
void setUniversalProperties:(NSDictionary *properties)
void setProperties:forSystemKey:(NSDictionary *properties,[forSystemKey] NSString *key)
void setInterstellarProperties:(NSDictionary *properties)

◆ useAddOns

+ (NSString *) useAddOns

Definition at line 104 of file ResourceManager.m.

482{
483 return sUseAddOns;
484}

◆ userRootPaths

+ (NSArray *) userRootPaths

Definition at line 104 of file ResourceManager.m.

177{
178 static NSArray *sUserRootPaths = nil;
179
180 if (sUserRootPaths == nil)
181 {
182 // the paths are now in order of preference as per yesterday's talk. -- Kaks 2010-05-05
183
184 sUserRootPaths = [[NSArray alloc] initWithObjects:
185
186#if OOLITE_MAC_OS_X
187 [[[[NSHomeDirectory() stringByAppendingPathComponent:@"Library"]
188 stringByAppendingPathComponent:@"Application Support"]
189 stringByAppendingPathComponent:@"Oolite"]
190 stringByAppendingPathComponent:@"AddOns"],
191 [[[[NSBundle mainBundle] bundlePath]
192 stringByDeletingLastPathComponent]
193 stringByAppendingPathComponent:@"AddOns"],
194
195#elif OOLITE_WINDOWS
196 @"../AddOns",
197#else
198 @"AddOns",
199#endif
200
201#if !OOLITE_WINDOWS
202 [[NSHomeDirectory()
203 stringByAppendingPathComponent:@".Oolite"]
204 stringByAppendingPathComponent:@"AddOns"],
205#endif
206
207 nil];
208 }
209 OOLog(@"searchPaths.debug",@"%@",sUserRootPaths);
210 return sUserRootPaths;
211}

◆ validateManifest:forOXP:

+ (BOOL) validateManifest: (NSDictionary*) manifest
forOXP: (NSString *) path 
implementation

Provided by category ResourceManager(OOPrivate).

Definition at line 104 of file ResourceManager.m.

641 :(NSDictionary*)manifest forOXP:(NSString *)path
642{
644 {
645 sOXPManifests = [[NSMutableDictionary alloc] initWithCapacity:32];
646 }
647
648 BOOL OK = YES;
649 NSString *identifier = [manifest oo_stringForKey:kOOManifestIdentifier defaultValue:nil];
650 NSString *version = [manifest oo_stringForKey:kOOManifestVersion defaultValue:nil];
651 NSString *required = [manifest oo_stringForKey:kOOManifestRequiredOoliteVersion defaultValue:nil];
652 NSString *title = [manifest oo_stringForKey:kOOManifestTitle defaultValue:nil];
653
654 if (identifier == nil)
655 {
656 OOLog(@"oxp.noManifest", @"OXZ %@ manifest.plist has no '%@' field.", path, kOOManifestIdentifier);
657 [self addErrorWithKey:@"oxp-manifest-incomplete" param1:title param2:kOOManifestIdentifier];
658 OK = NO;
659 }
660 if (version == nil)
661 {
662 OOLog(@"oxp.noManifest", @"OXZ %@ manifest.plist has no '%@' field.", path, kOOManifestVersion);
663 [self addErrorWithKey:@"oxp-manifest-incomplete" param1:title param2:kOOManifestVersion];
664 OK = NO;
665 }
666 if (required == nil)
667 {
668 OOLog(@"oxp.noManifest", @"OXZ %@ manifest.plist has no '%@' field.", path, kOOManifestRequiredOoliteVersion);
669 [self addErrorWithKey:@"oxp-manifest-incomplete" param1:title param2:kOOManifestRequiredOoliteVersion];
670 OK = NO;
671 }
672 if (title == nil)
673 {
674 OOLog(@"oxp.noManifest", @"OXZ %@ manifest.plist has no '%@' field.", path, kOOManifestTitle);
675 [self addErrorWithKey:@"oxp-manifest-incomplete" param1:title param2:kOOManifestTitle];
676 OK = NO;
677 }
678 if (!OK)
679 {
680 return NO;
681 }
682 OK = [self checkVersionCompatibility:manifest forOXP:title];
683
684 if (!OK)
685 {
686 NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
687 OOLog(@"oxp.versionMismatch", @"OXP %@ is incompatible with version %@ of Oolite.", path, version);
688 [self addErrorWithKey:@"oxp-is-incompatible" param1:[path lastPathComponent] param2:version];
689 return NO;
690 }
691
692 NSDictionary *duplicate = [sOXPManifests objectForKey:identifier];
693 if (duplicate != nil)
694 {
695 OOLog(@"oxp.duplicate", @"OXP %@ has the same identifier (%@) as %@ which has already been loaded.",path,identifier,[duplicate oo_stringForKey:kOOManifestFilePath]);
696 [self addErrorWithKey:@"oxp-manifest-duplicate" param1:path param2:[duplicate oo_stringForKey:kOOManifestFilePath]];
697 return NO;
698 }
699 NSMutableDictionary *mData = [NSMutableDictionary dictionaryWithDictionary:manifest];
700 [mData setObject:path forKey:kOOManifestFilePath];
701 // add an extra key
702 [sOXPManifests setObject:mData forKey:identifier];
703 return YES;
704}
static NSString *const kOOManifestRequiredOoliteVersion
static NSString *const kOOManifestTitle

◆ whitelistDictionary

+ (NSDictionary *) whitelistDictionary

Definition at line 104 of file ResourceManager.m.

1662{
1663 static id whitelistDictionary = nil;
1664
1665 if (whitelistDictionary == nil)
1666 {
1667 NSString *path = [[[ResourceManager builtInPath] stringByAppendingPathComponent:@"Config"] stringByAppendingPathComponent:@"whitelist.plist"];
1668 whitelistDictionary = [NSDictionary dictionaryWithContentsOfFile:path];
1669 if (whitelistDictionary == nil) whitelistDictionary = [NSNull null];
1670
1671 [whitelistDictionary retain];
1672 }
1673
1674 if (whitelistDictionary == [NSNull null]) return nil;
1675 return whitelistDictionary;
1676}
NSDictionary * whitelistDictionary()

Referenced by LookUpLegacySelector(), OOUniformBindingPermitted(), SanitizeActionMethod(), and SanitizeQueryMethod().

+ Here is the caller graph for this function:

◆ writeDiagnosticData:toFileNamed:

+ (BOOL) writeDiagnosticData: (NSData *) data
toFileNamed: (NSString *) name 

Definition at line 1679 of file ResourceManager.m.

2148 :(NSData *)data toFileNamed:(NSString *)name
2149{
2150 if (data == nil || name == nil) return NO;
2151
2152 NSString *directory = [self diagnosticFileLocation];
2153 if (directory == nil) return NO;
2154
2155 NSArray *nameComponents = [name componentsSeparatedByString:@"/"];
2156 NSUInteger count = [nameComponents count];
2157 if (count > 1)
2158 {
2159 name = [nameComponents lastObject];
2160
2161 for (NSUInteger i = 0; i < count - 1; i++)
2162 {
2163 NSString *component = [nameComponents objectAtIndex:i];
2164 if ([component hasPrefix:@"."])
2165 {
2166 component = [@"!" stringByAppendingString:[component substringFromIndex:1]];
2167 }
2168 directory = [directory stringByAppendingPathComponent:component];
2169 [[NSFileManager defaultManager] oo_createDirectoryAtPath:directory attributes:nil];
2170 }
2171 }
2172
2173 return [data writeToFile:[directory stringByAppendingPathComponent:name] atomically:YES];
2174}

◆ writeDiagnosticPList:toFileNamed:

+ (BOOL) writeDiagnosticPList: (id) plist
toFileNamed: (NSString *) name 

Definition at line 1679 of file ResourceManager.m.

2183 :(id)plist toFileNamed:(NSString *)name
2184{
2185 NSData *data = [plist oldSchoolPListFormatWithErrorDescription:NULL];
2186 if (data == nil) [NSPropertyListSerialization dataFromPropertyList:plist format:NSPropertyListXMLFormat_v1_0 errorDescription:NULL];
2187 if (data == nil) return NO;
2188
2189 return [self writeDiagnosticData:data toFileNamed:name];
2190}

◆ writeDiagnosticString:toFileNamed:

+ (BOOL) writeDiagnosticString: (NSString *) string
toFileNamed: (NSString *) name 

Definition at line 1679 of file ResourceManager.m.

2177 :(NSString *)string toFileNamed:(NSString *)name
2178{
2179 return [self writeDiagnosticData:[string dataUsingEncoding:NSUTF8StringEncoding] toFileNamed:name];
2180}

Referenced by SVGDumpEnd().

+ Here is the caller graph for this function:

The documentation for this class was generated from the following files: