diff --git a/src/blackmisc/directoryutils.cpp b/src/blackmisc/directoryutils.cpp index 2db4443cd..bd1e25df9 100644 --- a/src/blackmisc/directoryutils.cpp +++ b/src/blackmisc/directoryutils.cpp @@ -525,6 +525,17 @@ namespace BlackMisc return d1.absolutePath() == d2.absolutePath(); } + bool CDirectoryUtils::isSubDirectoryOf(const QString &dir1, const QString &dir2) + { + QDir d1(dir1); + const QDir d2(dir2); + do + { + if (d1 == d2) { return true; } + } while (d1.cdUp()); + return false; + } + QSet CDirectoryUtils::fileNamesToQSet(const QFileInfoList &fileInfoList) { QSet sl; diff --git a/src/blackmisc/directoryutils.h b/src/blackmisc/directoryutils.h index dc9b864c8..3b43d930e 100644 --- a/src/blackmisc/directoryutils.h +++ b/src/blackmisc/directoryutils.h @@ -184,6 +184,9 @@ namespace BlackMisc //! Same existing directories static bool isSameExistingDirectory(const QString &dir1, const QString &dir2); + //! Is dir1 a subdirectory (possibly nested) of dir2 or the same directory + static bool isSubDirectoryOf(const QString &dir1, const QString &dir2); + //! Result of directory comparison struct DirComparison { diff --git a/src/blackmisc/simulation/settings/simulatorsettings.h b/src/blackmisc/simulation/settings/simulatorsettings.h index a9ec7cf17..5195fbd51 100644 --- a/src/blackmisc/simulation/settings/simulatorsettings.h +++ b/src/blackmisc/simulation/settings/simulatorsettings.h @@ -20,6 +20,7 @@ #include "blackmisc/statusmessage.h" #include "blackmisc/propertyindex.h" #include "blackmisc/blackmiscexport.h" +#include "blackmisc/directoryutils.h" #include #include @@ -386,6 +387,22 @@ namespace BlackMisc //! \copydoc BlackMisc::TSettingTrait::humanReadable static const QString &humanReadable() { static const QString name("XPlane settings"); return name; } + + //! \copydoc BlackMisc::TSettingTrait::isValid + static bool isValid(const CSimulatorSettings &value, QString &reason) + { + const QString simDir = value.hasSimulatorDirectory() ? value.getSimulatorDirectory() + : CSpecializedSimulatorSettings::defaultSimulatorDirectory(CSimulatorInfo::XPLANE); + for (const QString &modelDir : value.getModelDirectories()) + { + if (!CDirectoryUtils::isSubDirectoryOf(modelDir, simDir)) + { + reason = QStringLiteral("Model directory must be within the simulator directory structure"); + return false; + } + } + return true; + } }; //! Trait for simulator settings diff --git a/src/plugins/simulator/xplane/simulatorxplane.cpp b/src/plugins/simulator/xplane/simulatorxplane.cpp index adffcd59d..be1e18685 100644 --- a/src/plugins/simulator/xplane/simulatorxplane.cpp +++ b/src/plugins/simulator/xplane/simulatorxplane.cpp @@ -571,7 +571,14 @@ namespace BlackSimPlugin { Q_ASSERT(package.s.endsWith('/')); package.s.chop(1); - m_trafficProxy->loadPlanesPackage(package.s); + if (CDirectoryUtils::isSubDirectoryOf(package.s, getSimulatorSettings().getSimulatorDirectoryOrDefault())) + { + m_trafficProxy->loadPlanesPackage(package.s); + } + else + { + CLogMessage(this).validationError(u"CSL package '%1' can not be loaded as it is outside the X-Plane installation directory") << package.s; + } } }