diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 20a2bbe2dd..6d4747df2d 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -982,7 +982,18 @@ void ScriptEngine::include(const QStringList& includeFiles, QScriptValue callbac // Do NOT use PreferLocalFile as its behavior is unpredictable (e.g., on defaultScriptsLocation()) const auto strippingFlags = QUrl::RemoveFilename | QUrl::RemoveQuery | QUrl::RemoveFragment; for (QString file : includeFiles) { - QUrl thisURL { resolvePath(file) }; + QUrl thisURL; + if (file.startsWith("/~/")) { + thisURL = expandScriptUrl(QUrl::fromLocalFile(expandScriptPath(file))); + QUrl defaultScriptsLoc = defaultScriptsLocation(); + if (!defaultScriptsLoc.isParentOf(thisURL)) { + qDebug() << "ScriptEngine::include -- skipping" << file << "-- outside of standard libraries"; + continue; + } + } else { + thisURL = resolvePath(file); + } + if (!_includedURLs.contains(thisURL)) { if (!currentSandboxURL.isEmpty() && (thisURL.scheme() == "file") && ( diff --git a/libraries/script-engine/src/ScriptEngines.cpp b/libraries/script-engine/src/ScriptEngines.cpp index 8fea7e4653..c6070e0598 100644 --- a/libraries/script-engine/src/ScriptEngines.cpp +++ b/libraries/script-engine/src/ScriptEngines.cpp @@ -70,6 +70,12 @@ QUrl normalizeScriptURL(const QUrl& rawScriptURL) { } } +QString expandScriptPath(const QString& rawPath) { + QStringList splitPath = rawPath.split("/"); + QUrl defaultScriptsLoc = defaultScriptsLocation(); + return defaultScriptsLoc.path() + "/" + splitPath.mid(2).join("/"); // 2 to skip the slashes in /~/ +} + QUrl expandScriptUrl(const QUrl& rawScriptURL) { QUrl normalizedScriptURL = normalizeScriptURL(rawScriptURL); if (normalizedScriptURL.scheme() == "http" || @@ -79,9 +85,23 @@ QUrl expandScriptUrl(const QUrl& rawScriptURL) { } else if (normalizedScriptURL.scheme() == "file") { if (normalizedScriptURL.path().startsWith("/~/")) { QUrl url = normalizedScriptURL; - QStringList splitPath = url.path().split("/"); + url.setPath(expandScriptPath(url.path())); + + // stop something like Script.include(["/~/../Desktop/naughty.js"]); from working + QFileInfo fileInfo(url.toLocalFile()); + url = QUrl::fromLocalFile(fileInfo.canonicalFilePath()); + QUrl defaultScriptsLoc = defaultScriptsLocation(); - url.setPath(defaultScriptsLoc.path() + "/" + splitPath.mid(2).join("/")); // 2 to skip the slashes in /~/ + if (!defaultScriptsLoc.isParentOf(url)) { + qCWarning(scriptengine) << "Script.include() ignoring file path" << rawScriptURL + << "-- outside of standard libraries: " + << url.path() + << defaultScriptsLoc.path(); + return rawScriptURL; + } + if (rawScriptURL.path().endsWith("/") && !url.path().endsWith("/")) { + url.setPath(url.path() + "/"); + } return url; } return normalizedScriptURL; diff --git a/libraries/script-engine/src/ScriptEngines.h b/libraries/script-engine/src/ScriptEngines.h index 5de71663e9..0963b21600 100644 --- a/libraries/script-engine/src/ScriptEngines.h +++ b/libraries/script-engine/src/ScriptEngines.h @@ -101,6 +101,7 @@ protected: }; QUrl normalizeScriptURL(const QUrl& rawScriptURL); +QString expandScriptPath(const QString& rawPath); QUrl expandScriptUrl(const QUrl& rawScriptURL); #endif // hifi_ScriptEngine_h diff --git a/libraries/shared/src/PathUtils.cpp b/libraries/shared/src/PathUtils.cpp index 025768908c..954ed2d75a 100644 --- a/libraries/shared/src/PathUtils.cpp +++ b/libraries/shared/src/PathUtils.cpp @@ -56,12 +56,15 @@ QString findMostRecentFileExtension(const QString& originalFileName, QVector