diff options
Diffstat (limited to 'src/corelib/io/qstandardpaths_unix.cpp')
-rw-r--r-- | src/corelib/io/qstandardpaths_unix.cpp | 99 |
1 files changed, 62 insertions, 37 deletions
diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp index e5122ff3b6..55150f9e93 100644 --- a/src/corelib/io/qstandardpaths_unix.cpp +++ b/src/corelib/io/qstandardpaths_unix.cpp @@ -180,10 +180,14 @@ QString QStandardPaths::writableLocation(StandardLocation type) case CacheLocation: case GenericCacheLocation: { + if (isTestModeEnabled()) + return QDir::homePath() + "/.qttest/cache"_L1; + // http://standards.freedesktop.org/basedir-spec/basedir-spec-0.6.html QString xdgCacheHome = QFile::decodeName(qgetenv("XDG_CACHE_HOME")); - if (isTestModeEnabled()) - xdgCacheHome = QDir::homePath() + "/.qttest/cache"_L1; + if (!xdgCacheHome.startsWith(u'/')) + xdgCacheHome.clear(); // spec says relative paths should be ignored + if (xdgCacheHome.isEmpty()) xdgCacheHome = QDir::homePath() + "/.cache"_L1; if (type == QStandardPaths::CacheLocation) @@ -194,9 +198,13 @@ QString QStandardPaths::writableLocation(StandardLocation type) case AppLocalDataLocation: case GenericDataLocation: { - QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME")); if (isTestModeEnabled()) - xdgDataHome = QDir::homePath() + "/.qttest/share"_L1; + return QDir::homePath() + "/.qttest/share"_L1; + + QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME")); + if (!xdgDataHome.startsWith(u'/')) + xdgDataHome.clear(); // spec says relative paths should be ignored + if (xdgDataHome.isEmpty()) xdgDataHome = QDir::homePath() + "/.local/share"_L1; if (type == AppDataLocation || type == AppLocalDataLocation) @@ -207,10 +215,14 @@ QString QStandardPaths::writableLocation(StandardLocation type) case GenericConfigLocation: case AppConfigLocation: { + if (isTestModeEnabled()) + return QDir::homePath() + "/.qttest/config"_L1; + // http://standards.freedesktop.org/basedir-spec/latest/ QString xdgConfigHome = QFile::decodeName(qgetenv("XDG_CONFIG_HOME")); - if (isTestModeEnabled()) - xdgConfigHome = QDir::homePath() + "/.qttest/config"_L1; + if (!xdgConfigHome.startsWith(u'/')) + xdgConfigHome.clear(); // spec says relative paths should be ignored + if (xdgConfigHome.isEmpty()) xdgConfigHome = QDir::homePath() + "/.config"_L1; if (type == AppConfigLocation) @@ -220,6 +232,9 @@ QString QStandardPaths::writableLocation(StandardLocation type) case RuntimeLocation: { QString xdgRuntimeDir = QFile::decodeName(qgetenv("XDG_RUNTIME_DIR")); + if (!xdgRuntimeDir.startsWith(u'/')) + xdgRuntimeDir.clear(); // spec says relative paths should be ignored + bool fromEnv = !xdgRuntimeDir.isEmpty(); if (xdgRuntimeDir.isEmpty() || !checkXdgRuntimeDir(xdgRuntimeDir)) { // environment variable not set or is set to something unsuitable @@ -246,6 +261,9 @@ QString QStandardPaths::writableLocation(StandardLocation type) #if QT_CONFIG(regularexpression) // http://www.freedesktop.org/wiki/Software/xdg-user-dirs QString xdgConfigHome = QFile::decodeName(qgetenv("XDG_CONFIG_HOME")); + if (!xdgConfigHome.startsWith(u'/')) + xdgConfigHome.clear(); // spec says relative paths should be ignored + if (xdgConfigHome.isEmpty()) xdgConfigHome = QDir::homePath() + "/.config"_L1; QFile file(xdgConfigHome + "/user-dirs.dirs"_L1); @@ -253,23 +271,23 @@ QString QStandardPaths::writableLocation(StandardLocation type) if (!key.isEmpty() && !isTestModeEnabled() && file.open(QIODevice::ReadOnly)) { QTextStream stream(&file); // Only look for lines like: XDG_DESKTOP_DIR="$HOME/Desktop" - QRegularExpression exp("^XDG_(.*)_DIR=(.*)$"_L1); + static const QRegularExpression exp(u"^XDG_(.*)_DIR=(.*)$"_s); QString result; while (!stream.atEnd()) { const QString &line = stream.readLine(); QRegularExpressionMatch match = exp.match(line); if (match.hasMatch() && match.capturedView(1) == key) { QStringView value = match.capturedView(2); - if (value.length() > 2 + if (value.size() > 2 && value.startsWith(u'\"') && value.endsWith(u'\"')) - value = value.mid(1, value.length() - 2); + value = value.mid(1, value.size() - 2); // value can start with $HOME if (value.startsWith("$HOME"_L1)) result = QDir::homePath() + value.mid(5); else result = value.toString(); - if (result.length() > 1 && result.endsWith(u'/')) + if (result.size() > 1 && result.endsWith(u'/')) result.chop(1); } } @@ -323,41 +341,48 @@ QString QStandardPaths::writableLocation(StandardLocation type) return path; } -static QStringList xdgDataDirs() +static QStringList dirsList(const QString &xdgEnvVar) { QStringList dirs; // http://standards.freedesktop.org/basedir-spec/latest/ + // Normalize paths, skip relative paths (the spec says relative paths + // should be ignored) + for (const auto dir : qTokenize(xdgEnvVar, u':')) + if (dir.startsWith(u'/')) + dirs.push_back(QDir::cleanPath(dir.toString())); + + // Remove duplicates from the list, there's no use for duplicated + // paths in XDG_DATA_DIRS - if it's not found in the given + // directory the first time, it won't be there the second time. + // Plus duplicate paths causes problems for example for mimetypes, + // where duplicate paths here lead to duplicated mime types returned + // for a file, eg "text/plain,text/plain" instead of "text/plain" + dirs.removeDuplicates(); + + return dirs; +} + +static QStringList xdgDataDirs() +{ + // http://standards.freedesktop.org/basedir-spec/latest/ QString xdgDataDirsEnv = QFile::decodeName(qgetenv("XDG_DATA_DIRS")); - if (xdgDataDirsEnv.isEmpty()) { - dirs.append(QString::fromLatin1("/usr/local/share")); - dirs.append(QString::fromLatin1("/usr/share")); - } else { - // Normalize paths, skip relative paths - for (const auto dir : qTokenize(xdgDataDirsEnv, u':')) { - if (dir.startsWith(u'/')) - dirs.push_back(QDir::cleanPath(dir.toString())); - } - // Remove duplicates from the list, there's no use for duplicated - // paths in XDG_DATA_DIRS - if it's not found in the given - // directory the first time, it won't be there the second time. - // Plus duplicate paths causes problems for example for mimetypes, - // where duplicate paths here lead to duplicated mime types returned - // for a file, eg "text/plain,text/plain" instead of "text/plain" - dirs.removeDuplicates(); - } + QStringList dirs = dirsList(xdgDataDirsEnv); + if (dirs.isEmpty()) + dirs = QStringList{u"/usr/local/share"_s, u"/usr/share"_s}; + return dirs; } static QStringList xdgConfigDirs() { - QStringList dirs; // http://standards.freedesktop.org/basedir-spec/latest/ const QString xdgConfigDirs = QFile::decodeName(qgetenv("XDG_CONFIG_DIRS")); - if (xdgConfigDirs.isEmpty()) - dirs.append(QString::fromLatin1("/etc/xdg")); - else - dirs = xdgConfigDirs.split(u':'); + + QStringList dirs = dirsList(xdgConfigDirs); + if (dirs.isEmpty()) + dirs.push_back(u"/etc/xdg"_s); + return dirs; } @@ -371,7 +396,7 @@ QStringList QStandardPaths::standardLocations(StandardLocation type) break; case AppConfigLocation: dirs = xdgConfigDirs(); - for (int i = 0; i < dirs.count(); ++i) + for (int i = 0; i < dirs.size(); ++i) appendOrganizationAndApp(dirs[i]); break; case GenericDataLocation: @@ -379,19 +404,19 @@ QStringList QStandardPaths::standardLocations(StandardLocation type) break; case ApplicationsLocation: dirs = xdgDataDirs(); - for (int i = 0; i < dirs.count(); ++i) + for (int i = 0; i < dirs.size(); ++i) dirs[i].append("/applications"_L1); break; case AppDataLocation: case AppLocalDataLocation: dirs = xdgDataDirs(); - for (int i = 0; i < dirs.count(); ++i) + for (int i = 0; i < dirs.size(); ++i) appendOrganizationAndApp(dirs[i]); break; case FontsLocation: dirs += QDir::homePath() + "/.fonts"_L1; dirs += xdgDataDirs(); - for (int i = 1; i < dirs.count(); ++i) + for (int i = 1; i < dirs.size(); ++i) dirs[i].append("/fonts"_L1); break; default: |