diff --git a/simgear/embedded_resources/embedded_resources_test.cxx b/simgear/embedded_resources/embedded_resources_test.cxx index 5e9bf600..c15a6d65 100644 --- a/simgear/embedded_resources/embedded_resources_test.cxx +++ b/simgear/embedded_resources/embedded_resources_test.cxx @@ -314,7 +314,7 @@ void test_addAlreadyExistingResource() "add an already existing resource" << endl; const auto& resMgr = EmbeddedResourceManager::instance(); - for (const string& locale: {"", "fr", "fr_FR"}) { + for (const string locale: {"", "fr", "fr_FR"}) { // For these tests, we don't care about the resource contents -> no need // to substract 1 from the result of sizeof() as we did above. unique_ptr someRes( @@ -390,7 +390,7 @@ void test_getLocaleAndSelectLocale() "EmbeddedResourceManager" << endl; const auto& resMgr = EmbeddedResourceManager::instance(); - for (const string& locale: {"", "fr", "fr_FR", "de_DE"}) { + for (const string locale: {"", "fr", "fr_FR", "de_DE"}) { // The important effects of setLocale() are tested in // test_localeDependencyOfResourceFetching() resMgr->selectLocale(locale); diff --git a/simgear/misc/ResourceManager.cxx b/simgear/misc/ResourceManager.cxx index ec538f1b..9c3b6f2e 100644 --- a/simgear/misc/ResourceManager.cxx +++ b/simgear/misc/ResourceManager.cxx @@ -127,20 +127,32 @@ void ResourceManager::removeProvider(ResourceProvider* aProvider) SGPath ResourceManager::findPath(const std::string& aResource, SGPath aContext) { - if (!aContext.isNull()) { - SGPath r(aContext, aResource); - if (r.exists()) { - return r; + const SGPath completePath(aContext, aResource); + + if (!aContext.isNull() && completePath.exists()) { + return completePath; + } + + // Absolute, existing path and SGPath::validate() grants read access -> OK + if (completePath.isAbsolute()) { + const auto authorizedPath = completePath.validate(false); + if (!authorizedPath.isNull() && authorizedPath.exists()) { + return authorizedPath; } } - - for (auto provider : _providers) { - SGPath path = provider->resolve(aResource, aContext); - if (!path.isNull()) { - return path; - } + + // Loop over the resource providers even if 'completePath' is absolute. + // For instance, when readProperties() processes 'include' attributes, it + // is expected that 'aResource' be interpreted relatively to 'aContext' + // or, if this doesn't lead to an existing file, a data path like + // $FG_ROOT. In the latter case, BasePathProvider will do the job. + for (const auto& provider : _providers) { + const SGPath path = provider->resolve(aResource, aContext); + if (!path.isNull()) { + return path; + } } - + return SGPath(); }