rewrite a bunch of path/url mangling code

This commit is contained in:
Seth Alves 2016-03-30 13:33:49 -07:00
parent bd5757d586
commit 26e01bbacd
6 changed files with 104 additions and 79 deletions

View file

@ -234,7 +234,7 @@ void ScriptEngine::loadURL(const QUrl& scriptURL, bool reload) {
void ScriptEngine::scriptContentsAvailable(const QUrl& url, const QString& scriptContents) { void ScriptEngine::scriptContentsAvailable(const QUrl& url, const QString& scriptContents) {
_scriptContents = scriptContents; _scriptContents = scriptContents;
if (_wantSignals) { if (_wantSignals) {
emit scriptLoaded(_fileNameString); emit scriptLoaded(url.toString());
} }
} }

View file

@ -42,52 +42,49 @@ ScriptEngines::ScriptEngines()
_scriptsModelFilter.setDynamicSortFilter(true); _scriptsModelFilter.setDynamicSortFilter(true);
} }
QString normalizeScriptUrl(const QString& rawScriptUrl) { QUrl normalizeScriptURL(const QUrl& rawScriptURL) {
if (!rawScriptUrl.startsWith("http:") && !rawScriptUrl.startsWith("https:") && !rawScriptUrl.startsWith("atp:")) { if (rawScriptURL.scheme() == "file") {
QUrl fullNormal = rawScriptURL;
QUrl defaultScriptLoc = defaultScriptsLocation();
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
if (rawScriptUrl.startsWith("file:")) {
return rawScriptUrl;
}
return QUrl::fromLocalFile(rawScriptUrl).toString();
#else #else
QString fullNormal;
if (rawScriptUrl.startsWith("file:")) {
fullNormal = rawScriptUrl.toLower();
} else {
// Force lowercase on file scripts because of drive letter weirdness. // Force lowercase on file scripts because of drive letter weirdness.
fullNormal = QUrl::fromLocalFile(rawScriptUrl).toString().toLower(); if (rawScriptURL.isLocalFile()) {
fullNormal.setPath(fullNormal.path.toLower());
} }
QString defaultScriptLoc = defaultScriptsLocation(); #endif
if (fullNormal.startsWith(defaultScriptLoc)) { // if this url is something "beneath" the default script url, replace the local path with ~
return "~" + fullNormal.mid(defaultScriptLoc.size()); if (fullNormal.scheme() == defaultScriptLoc.scheme() &&
fullNormal.host() == defaultScriptLoc.host() &&
fullNormal.path().startsWith(defaultScriptLoc.path())) {
fullNormal.setPath("/~/" + fullNormal.path().mid(defaultScriptLoc.path().size()));
} }
return fullNormal; return fullNormal;
#endif } else if (rawScriptURL.scheme() == "http" || rawScriptURL.scheme() == "https" || rawScriptURL.scheme() == "atp") {
return rawScriptURL;
}
return QUrl(rawScriptUrl).toString();
}
QString expandScriptUrl(const QString& normalizedScriptURL) {
if (normalizedScriptURL.startsWith("http:") ||
normalizedScriptURL.startsWith("https:") ||
normalizedScriptURL.startsWith("atp:")) {
return QUrl(normalizedScriptURL).toString();
}
QUrl url;
if (normalizedScriptURL.startsWith("file:")) {
url = QUrl(normalizedScriptURL);
} else { } else {
url = QUrl::fromLocalFile(normalizedScriptURL); // don't accidently support gopher
return QUrl("");
}
} }
QString path = url.path(); QUrl expandScriptUrl(const QUrl& normalizedScriptURL) {
QStringList splitPath = path.split("/"); if (normalizedScriptURL.scheme() == "http" ||
if (splitPath.size() > 0 && splitPath[0] == "~") { normalizedScriptURL.scheme() == "https" ||
QString defaultScriptLoc = defaultScriptsLocation(); normalizedScriptURL.scheme() == "atp") {
url.setPath(defaultScriptLoc + splitPath.mid(1).join("/")); return normalizedScriptURL;
return url.toString(); } else if (normalizedScriptURL.scheme() == "file") {
if (normalizedScriptURL.path().startsWith("/~/")) {
QUrl url = normalizedScriptURL;
QStringList splitPath = url.path().split("/");
QUrl defaultScriptsLoc = defaultScriptsLocation();
url.setPath(defaultScriptsLoc.path() + "/" + splitPath.mid(2).join("/")); // 2 to skip the slashes in /~/
return url;
}
return normalizedScriptURL;
} else {
return QUrl("");
} }
} }
@ -229,14 +226,21 @@ QVariantList ScriptEngines::getRunning() {
auto runningScripts = getRunningScripts(); auto runningScripts = getRunningScripts();
foreach(const QString& runningScript, runningScripts) { foreach(const QString& runningScript, runningScripts) {
QUrl runningScriptURL = QUrl(runningScript); QUrl runningScriptURL = QUrl(runningScript);
if (runningScriptURL.scheme().size() <= WINDOWS_DRIVE_LETTER_SIZE) { if (!runningScriptURL.isValid()) {
runningScriptURL = QUrl::fromLocalFile(runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded))); runningScriptURL = QUrl::fromLocalFile(runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded)));
} }
QVariantMap resultNode; QVariantMap resultNode;
resultNode.insert("name", runningScriptURL.fileName()); resultNode.insert("name", runningScriptURL.fileName());
resultNode.insert("url", runningScriptURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded))); QUrl displayURL = expandScriptUrl(QUrl(runningScriptURL));
QString displayURLString;
if (displayURL.isLocalFile()) {
displayURLString = displayURL.toLocalFile();
} else {
displayURLString = displayURL.toDisplayString(QUrl::FormattingOptions(QUrl::FullyEncoded));
}
resultNode.insert("url", displayURLString);
// The path contains the exact path/URL of the script, which also is used in the stopScript function. // The path contains the exact path/URL of the script, which also is used in the stopScript function.
resultNode.insert("path", runningScript); resultNode.insert("path", normalizeScriptURL(runningScript).toString());
resultNode.insert("local", runningScriptURL.isLocalFile()); resultNode.insert("local", runningScriptURL.isLocalFile());
result.append(resultNode); result.append(resultNode);
} }
@ -247,7 +251,9 @@ QVariantList ScriptEngines::getRunning() {
static const QString SETTINGS_KEY = "Settings"; static const QString SETTINGS_KEY = "Settings";
void ScriptEngines::loadDefaultScripts() { void ScriptEngines::loadDefaultScripts() {
loadScript(defaultScriptsLocation() + "/scripts/defaultScripts.js"); QUrl defaultScriptsLoc = defaultScriptsLocation();
defaultScriptsLoc.setPath(defaultScriptsLoc.path() + "/scripts/defaultScripts.js");
loadScript(defaultScriptsLoc.toString());
} }
void ScriptEngines::loadOneScript(const QString& scriptFilename) { void ScriptEngines::loadOneScript(const QString& scriptFilename) {
@ -296,7 +302,7 @@ void ScriptEngines::saveScripts() {
for (auto it = runningScripts.begin(); it != runningScripts.end(); ++it) { for (auto it = runningScripts.begin(); it != runningScripts.end(); ++it) {
if (getScriptEngine(*it)->isUserLoaded()) { if (getScriptEngine(*it)->isUserLoaded()) {
settings.setArrayIndex(i); settings.setArrayIndex(i);
settings.setValue("script", *it); settings.setValue("script", normalizeScriptURL(*it).toString());
++i; ++i;
} }
} }
@ -338,11 +344,16 @@ void ScriptEngines::stopAllScripts(bool restart) {
} }
} }
bool ScriptEngines::stopScript(const QString& rawScriptUrl, bool restart) { bool ScriptEngines::stopScript(const QString& rawScriptURL, bool restart) {
bool stoppedScript = false; bool stoppedScript = false;
{ {
QUrl scriptURL = normalizeScriptURL(QUrl(rawScriptURL));
if (!scriptURL.isValid()) {
scriptURL = normalizeScriptURL(QUrl::fromLocalFile(rawScriptURL));
}
const QString scriptURLString = scriptURL.toString();
QReadLocker lock(&_scriptEnginesHashLock); QReadLocker lock(&_scriptEnginesHashLock);
const QString scriptURLString = normalizeScriptUrl(rawScriptUrl);
if (_scriptEnginesHash.contains(scriptURLString)) { if (_scriptEnginesHash.contains(scriptURLString)) {
ScriptEngine* scriptEngine = _scriptEnginesHash[scriptURLString]; ScriptEngine* scriptEngine = _scriptEnginesHash[scriptURLString];
if (restart) { if (restart) {
@ -375,18 +386,19 @@ void ScriptEngines::reloadAllScripts() {
stopAllScripts(true); stopAllScripts(true);
} }
ScriptEngine* ScriptEngines::loadScript(const QString& scriptFilename, bool isUserLoaded, bool loadScriptFromEditor, bool activateMainWindow, bool reload) { ScriptEngine* ScriptEngines::loadScript(const QUrl& scriptFilename, bool isUserLoaded, bool loadScriptFromEditor,
bool activateMainWindow, bool reload) {
if (thread() != QThread::currentThread()) { if (thread() != QThread::currentThread()) {
ScriptEngine* result { nullptr }; ScriptEngine* result { nullptr };
QMetaObject::invokeMethod(this, "loadScript", Qt::BlockingQueuedConnection, Q_RETURN_ARG(ScriptEngine*, result), QMetaObject::invokeMethod(this, "loadScript", Qt::BlockingQueuedConnection, Q_RETURN_ARG(ScriptEngine*, result),
Q_ARG(QString, scriptFilename), Q_ARG(QUrl, scriptFilename),
Q_ARG(bool, isUserLoaded), Q_ARG(bool, isUserLoaded),
Q_ARG(bool, loadScriptFromEditor), Q_ARG(bool, loadScriptFromEditor),
Q_ARG(bool, activateMainWindow), Q_ARG(bool, activateMainWindow),
Q_ARG(bool, reload)); Q_ARG(bool, reload));
return result; return result;
} }
QUrl scriptUrl(scriptFilename); QUrl scriptUrl = normalizeScriptURL(scriptFilename);
auto scriptEngine = getScriptEngine(scriptUrl.toString()); auto scriptEngine = getScriptEngine(scriptUrl.toString());
if (scriptEngine) { if (scriptEngine) {
return scriptEngine; return scriptEngine;
@ -399,7 +411,7 @@ ScriptEngine* ScriptEngines::loadScript(const QString& scriptFilename, bool isUs
}, Qt::QueuedConnection); }, Qt::QueuedConnection);
if (scriptFilename.isNull()) { if (scriptFilename.isEmpty()) {
launchScriptEngine(scriptEngine); launchScriptEngine(scriptEngine);
} else { } else {
// connect to the appropriate signals of this script engine // connect to the appropriate signals of this script engine
@ -407,17 +419,17 @@ ScriptEngine* ScriptEngines::loadScript(const QString& scriptFilename, bool isUs
connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &ScriptEngines::onScriptEngineError); connect(scriptEngine, &ScriptEngine::errorLoadingScript, this, &ScriptEngines::onScriptEngineError);
// get the script engine object to load the script at the designated script URL // get the script engine object to load the script at the designated script URL
scriptEngine->loadURL(scriptUrl, reload); scriptEngine->loadURL(QUrl(expandScriptUrl(scriptUrl.toString())), reload);
} }
return scriptEngine; return scriptEngine;
} }
ScriptEngine* ScriptEngines::getScriptEngine(const QString& rawScriptUrl) { ScriptEngine* ScriptEngines::getScriptEngine(const QString& rawScriptURL) {
ScriptEngine* result = nullptr; ScriptEngine* result = nullptr;
{ {
QReadLocker lock(&_scriptEnginesHashLock); QReadLocker lock(&_scriptEnginesHashLock);
const QString scriptURLString = normalizeScriptUrl(rawScriptUrl); const QString scriptURLString = normalizeScriptURL(QUrl(rawScriptURL)).toString();
auto it = _scriptEnginesHash.find(scriptURLString); auto it = _scriptEnginesHash.find(scriptURLString);
if (it != _scriptEnginesHash.end()) { if (it != _scriptEnginesHash.end()) {
result = it.value(); result = it.value();
@ -427,15 +439,17 @@ ScriptEngine* ScriptEngines::getScriptEngine(const QString& rawScriptUrl) {
} }
// FIXME - change to new version of ScriptCache loading notification // FIXME - change to new version of ScriptCache loading notification
void ScriptEngines::onScriptEngineLoaded(const QString& rawScriptUrl) { void ScriptEngines::onScriptEngineLoaded(const QString& rawScriptURL) {
UserActivityLogger::getInstance().loadedScript(rawScriptUrl); UserActivityLogger::getInstance().loadedScript(rawScriptURL);
ScriptEngine* scriptEngine = qobject_cast<ScriptEngine*>(sender()); ScriptEngine* scriptEngine = qobject_cast<ScriptEngine*>(sender());
launchScriptEngine(scriptEngine); launchScriptEngine(scriptEngine);
{ {
QWriteLocker lock(&_scriptEnginesHashLock); QWriteLocker lock(&_scriptEnginesHashLock);
const QString scriptURLString = normalizeScriptUrl(rawScriptUrl); QUrl url = QUrl(rawScriptURL);
QUrl normalized = normalizeScriptURL(url);
const QString scriptURLString = normalized.toString();
_scriptEnginesHash.insertMulti(scriptURLString, scriptEngine); _scriptEnginesHash.insertMulti(scriptURLString, scriptEngine);
} }
emit scriptCountChanged(); emit scriptCountChanged();
@ -458,11 +472,11 @@ void ScriptEngines::launchScriptEngine(ScriptEngine* scriptEngine) {
} }
void ScriptEngines::onScriptFinished(const QString& rawScriptUrl, ScriptEngine* engine) { void ScriptEngines::onScriptFinished(const QString& rawScriptURL, ScriptEngine* engine) {
bool removed = false; bool removed = false;
{ {
QWriteLocker lock(&_scriptEnginesHashLock); QWriteLocker lock(&_scriptEnginesHashLock);
const QString scriptURLString = normalizeScriptUrl(rawScriptUrl); const QString scriptURLString = normalizeScriptURL(QUrl(rawScriptURL)).toString();
for (auto it = _scriptEnginesHash.find(scriptURLString); it != _scriptEnginesHash.end(); ++it) { for (auto it = _scriptEnginesHash.find(scriptURLString); it != _scriptEnginesHash.end(); ++it) {
if (it.value() == engine) { if (it.value() == engine) {
_scriptEnginesHash.erase(it); _scriptEnginesHash.erase(it);

View file

@ -51,7 +51,7 @@ public:
ScriptsModelFilter* scriptsModelFilter() { return &_scriptsModelFilter; }; ScriptsModelFilter* scriptsModelFilter() { return &_scriptsModelFilter; };
Q_INVOKABLE void loadOneScript(const QString& scriptFilename); Q_INVOKABLE void loadOneScript(const QString& scriptFilename);
Q_INVOKABLE ScriptEngine* loadScript(const QString& scriptFilename = QString(), Q_INVOKABLE ScriptEngine* loadScript(const QUrl& scriptFilename = QString(),
bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false); bool isUserLoaded = true, bool loadScriptFromEditor = false, bool activateMainWindow = false, bool reload = false);
Q_INVOKABLE bool stopScript(const QString& scriptHash, bool restart = false); Q_INVOKABLE bool stopScript(const QString& scriptHash, bool restart = false);
@ -96,7 +96,7 @@ protected:
ScriptsModelFilter _scriptsModelFilter; ScriptsModelFilter _scriptsModelFilter;
}; };
QString normalizeScriptUrl(const QString& rawScriptUrl); QUrl normalizeScriptURL(const QUrl& rawScriptURL);
QString expandScriptUrl(const QString& normalizedScriptURL); QUrl expandScriptUrl(const QUrl& normalizedScriptURL);
#endif // hifi_ScriptEngine_h #endif // hifi_ScriptEngine_h

View file

@ -158,14 +158,21 @@ void ScriptsModel::requestDefaultFiles(QString marker) {
QUrl url(defaultScriptsLocation()); QUrl url(defaultScriptsLocation());
if (url.isLocalFile()) { if (url.isLocalFile()) {
QString localDir = url.toLocalFile() + "/scripts"; // if the url indicates a local directory, use QDirIterator
// QString localDir = url.toLocalFile() + "/scripts";
QString localDir = expandScriptUrl(url).toLocalFile() + "/scripts";
int localDirPartCount = localDir.split("/").size();
QDirIterator it(localDir, QStringList() << "*.js", QDir::Files, QDirIterator::Subdirectories); QDirIterator it(localDir, QStringList() << "*.js", QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext()) { while (it.hasNext()) {
QString jsFullPath = normalizeScriptUrl(it.next()); QUrl jsFullPath = QUrl::fromLocalFile(it.next());
QString jsPartialPath = normalizeScriptUrl(jsFullPath.mid(localDir.length() + 1)); // + 1 to skip a separator // QString jsPartialPath = jsFullPath.path().mid(localDir.length() + 1); // + 1 to skip a separator
_treeNodes.append(new TreeNodeScript(jsPartialPath, jsFullPath, SCRIPT_ORIGIN_DEFAULT)); QString jsPartialPath = jsFullPath.path().split("/").mid(localDirPartCount).join("/");
jsFullPath = normalizeScriptURL(jsFullPath);
_treeNodes.append(new TreeNodeScript(jsPartialPath, jsFullPath.toString(), SCRIPT_ORIGIN_DEFAULT));
} }
_loadingScripts = false;
} else { } else {
// the url indicates http(s), use QNetworkRequest
QUrlQuery query; QUrlQuery query;
query.addQueryItem(PREFIX_PARAMETER_NAME, MODELS_LOCATION); query.addQueryItem(PREFIX_PARAMETER_NAME, MODELS_LOCATION);
if (!marker.isEmpty()) { if (!marker.isEmpty()) {
@ -227,11 +234,13 @@ bool ScriptsModel::parseXML(QByteArray xmlFile) {
while (!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() == CONTAINER_NAME)) { while (!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() == CONTAINER_NAME)) {
if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == KEY_NAME) { if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == KEY_NAME) {
xml.readNext(); xml.readNext();
lastKey = normalizeScriptUrl(xml.text().toString()); lastKey = xml.text().toString();
if (jsRegex.exactMatch(xml.text().toString())) { if (jsRegex.exactMatch(xml.text().toString())) {
_treeNodes.append(new TreeNodeScript(lastKey.mid(MODELS_LOCATION.length()), QString localPath = lastKey.split("/").mid(1).join("/");
defaultScriptsLocation() + "/" + lastKey, QUrl fullPath = defaultScriptsLocation();
SCRIPT_ORIGIN_DEFAULT)); fullPath.setPath(fullPath.path() + "/" + lastKey);
const QString fullPathStr = normalizeScriptURL(fullPath).toString();
_treeNodes.append(new TreeNodeScript(localPath, fullPathStr, SCRIPT_ORIGIN_DEFAULT));
} }
} }
xml.readNext(); xml.readNext();
@ -274,9 +283,9 @@ void ScriptsModel::reloadLocalFiles() {
const QFileInfoList localFiles = _localDirectory.entryInfoList(); const QFileInfoList localFiles = _localDirectory.entryInfoList();
for (int i = 0; i < localFiles.size(); i++) { for (int i = 0; i < localFiles.size(); i++) {
QFileInfo file = localFiles[i]; QFileInfo file = localFiles[i];
QString fileName = normalizeScriptUrl(file.fileName()); QString fileName = file.fileName();
QString absPath = normalizeScriptUrl(file.absoluteFilePath()); QUrl absPath = normalizeScriptURL(QUrl::fromLocalFile(file.absoluteFilePath()));
_treeNodes.append(new TreeNodeScript(fileName, absPath, SCRIPT_ORIGIN_LOCAL)); _treeNodes.append(new TreeNodeScript(fileName, absPath.toString(), SCRIPT_ORIGIN_LOCAL));
} }
rebuildTree(); rebuildTree();
endResetModel(); endResetModel();
@ -302,7 +311,7 @@ void ScriptsModel::rebuildTree() {
for (pathIterator = pathList.constBegin(); pathIterator != pathList.constEnd(); ++pathIterator) { for (pathIterator = pathList.constBegin(); pathIterator != pathList.constEnd(); ++pathIterator) {
hash.append(*pathIterator + "/"); hash.append(*pathIterator + "/");
if (!folders.contains(hash)) { if (!folders.contains(hash)) {
folders[hash] = new TreeNodeFolder(normalizeScriptUrl(*pathIterator), parent); folders[hash] = new TreeNodeFolder(*pathIterator, parent);
} }
parent = folders[hash]; parent = folders[hash];
} }

View file

@ -15,6 +15,7 @@
#include <QDateTime> #include <QDateTime>
#include <QFileInfo> #include <QFileInfo>
#include <QDir> #include <QDir>
#include <QUrl>
#include "PathUtils.h" #include "PathUtils.h"
@ -54,12 +55,13 @@ QString findMostRecentFileExtension(const QString& originalFileName, QVector<QSt
return newestFileName; return newestFileName;
} }
QString defaultScriptsLocation() { QUrl defaultScriptsLocation() {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
return QString("file:///" + QCoreApplication::applicationDirPath()).toLower(); return QUrl(("file://" + QCoreApplication::applicationDirPath()).toLower());
#elif defined(Q_OS_OSX) #elif defined(Q_OS_OSX)
return QString("file:///" + QCoreApplication::applicationDirPath() + "/../..").toLower(); return QUrl(("file://" + QCoreApplication::applicationDirPath() + "/../..").toLower());
#else #else
return "http://s3.amazonaws.com/hifi-public"; // return "http://s3.amazonaws.com/hifi-public";
return QUrl("file://" + QCoreApplication::applicationDirPath());
#endif #endif
} }

View file

@ -27,6 +27,6 @@ public:
QString fileNameWithoutExtension(const QString& fileName, const QVector<QString> possibleExtensions); QString fileNameWithoutExtension(const QString& fileName, const QVector<QString> possibleExtensions);
QString findMostRecentFileExtension(const QString& originalFileName, QVector<QString> possibleExtensions); QString findMostRecentFileExtension(const QString& originalFileName, QVector<QString> possibleExtensions);
QString defaultScriptsLocation(); QUrl defaultScriptsLocation();
#endif // hifi_PathUtils_h #endif // hifi_PathUtils_h