aboutsummaryrefslogtreecommitdiff
path: root/src/path_functions.cpp
diff options
context:
space:
mode:
authoroldmud0 <oldmud0@users.noreply.github.com>2021-12-18 22:34:04 -0600
committeroldmud0 <oldmud0@users.noreply.github.com>2021-12-18 22:34:04 -0600
commitb0e9f8dbe57df5e688d9583987d7e378eebd72b4 (patch)
tree18824b6a05fddfa71e4c1240023fc916d8ef4790 /src/path_functions.cpp
parentcf12168ebd426d7658d7f7021c47be519caa215a (diff)
parent641cca65044e41e49e5a871f0d60138b61c1bab3 (diff)
Merge branch 'master' into feature/http-ms
Diffstat (limited to 'src/path_functions.cpp')
-rw-r--r--src/path_functions.cpp220
1 files changed, 142 insertions, 78 deletions
diff --git a/src/path_functions.cpp b/src/path_functions.cpp
index dbf1cc4..6fd06e7 100644
--- a/src/path_functions.cpp
+++ b/src/path_functions.cpp
@@ -5,6 +5,7 @@
#include <QDir>
#include <QRegExp>
#include <QStandardPaths>
+#include <QStringBuilder>
#ifdef BASE_OVERRIDE
#include "base_override.h"
@@ -39,72 +40,57 @@ QString AOApplication::get_base_path()
return base_path;
}
-QString AOApplication::get_data_path() { return get_base_path() + "data/"; }
-
-QString AOApplication::get_theme_path(QString p_file, QString p_theme)
+VPath AOApplication::get_theme_path(QString p_file, QString p_theme)
{
if (p_theme == "")
p_theme = current_theme;
- QString path = get_base_path() + "themes/" + p_theme + "/" + p_file;
- return get_case_sensitive_path(path);
+ return VPath("themes/" + p_theme + "/" + p_file);
}
-QString AOApplication::get_character_path(QString p_char, QString p_file)
+VPath AOApplication::get_character_path(QString p_char, QString p_file)
{
- QString path = get_base_path() + "characters/" + p_char + "/" + p_file;
- return get_case_sensitive_path(path);
+ return VPath("characters/" + p_char + "/" + p_file);
}
-QString AOApplication::get_misc_path(QString p_misc, QString p_file)
+VPath AOApplication::get_misc_path(QString p_misc, QString p_file)
{
- QString path = get_base_path() + "misc/" + p_misc + "/" + p_file;
-#ifndef CASE_SENSITIVE_FILESYSTEM
- return path;
-#else
- return get_case_sensitive_path(path);
-#endif
+ return VPath("misc/" + p_misc + "/" + p_file);
}
-QString AOApplication::get_sounds_path(QString p_file)
+VPath AOApplication::get_sounds_path(QString p_file)
{
- QString path = get_base_path() + "sounds/general/" + p_file;
- return get_case_sensitive_path(path);
+ return VPath("sounds/general/" + p_file);
}
-QString AOApplication::get_music_path(QString p_song)
+VPath AOApplication::get_music_path(QString p_song)
{
if (p_song.startsWith("http")) {
- return p_song; // url
+ return VPath(p_song); // url
}
- QString path = get_base_path() + "sounds/music/" + p_song;
- return get_case_sensitive_path(path);
+ return VPath("sounds/music/" + p_song);
}
-QString AOApplication::get_background_path(QString p_file)
+VPath AOApplication::get_background_path(QString p_file)
{
- QString path = get_base_path() + "background/" +
- w_courtroom->get_current_background() + "/" + p_file;
if (courtroom_constructed) {
- return get_case_sensitive_path(path);
+ return VPath("background/" + w_courtroom->get_current_background() + "/" + p_file);
}
return get_default_background_path(p_file);
}
-QString AOApplication::get_default_background_path(QString p_file)
+VPath AOApplication::get_default_background_path(QString p_file)
{
- QString path = get_base_path() + "background/default/" + p_file;
- return get_case_sensitive_path(path);
+ return VPath("background/default/" + p_file);
}
-QString AOApplication::get_evidence_path(QString p_file)
+VPath AOApplication::get_evidence_path(QString p_file)
{
- QString path = get_base_path() + "evidence/" + p_file;
- return get_case_sensitive_path(path);
+ return VPath("evidence/" + p_file);
}
-QStringList AOApplication::get_asset_paths(QString p_element, QString p_theme, QString p_subtheme, QString p_default_theme, QString p_misc, QString p_character, QString p_placeholder)
+QVector<VPath> AOApplication::get_asset_paths(QString p_element, QString p_theme, QString p_subtheme, QString p_default_theme, QString p_misc, QString p_character, QString p_placeholder)
{
- QStringList pathlist;
+ QVector<VPath> pathlist;
if (p_character != "")
pathlist += get_character_path(p_character, p_element); // Character folder
if (p_misc != "" && p_theme != "" && p_subtheme != "")
@@ -119,7 +105,7 @@ QStringList AOApplication::get_asset_paths(QString p_element, QString p_theme, Q
pathlist += get_theme_path(p_element, p_theme); // Theme path
if (p_default_theme != "")
pathlist += get_theme_path(p_element, p_default_theme); // Default theme path
- pathlist += p_element; // The path by itself
+ pathlist += VPath(p_element); // The path by itself
if (p_placeholder != "" && p_theme != "")
pathlist += get_theme_path(p_placeholder, p_theme); // Placeholder path
if (p_placeholder != "" && p_default_theme != "")
@@ -127,52 +113,48 @@ QStringList AOApplication::get_asset_paths(QString p_element, QString p_theme, Q
return pathlist;
}
-QString AOApplication::get_asset_path(QStringList pathlist)
+QString AOApplication::get_asset_path(QVector<VPath> pathlist)
{
- QString path;
- for (QString p : pathlist) {
- p = get_case_sensitive_path(p);
- if (file_exists(p)) {
- path = p;
- break;
+ for (const VPath &p : pathlist) {
+ QString path = get_real_path(p);
+ if (!path.isEmpty()) {
+ return path;
}
}
- return path;
+ return QString();
}
-QString AOApplication::get_image_path(QStringList pathlist, bool static_image)
+QString AOApplication::get_image_path(QVector<VPath> pathlist, bool static_image)
{
- QString path;
- for (QString p : pathlist) {
- p = get_case_sensitive_path(get_image_suffix(p, static_image));
- if (file_exists(p)) {
- path = p;
- break;
- }
+ for (const VPath &p : pathlist) {
+ QString path = get_image_suffix(p, static_image);
+ if (!path.isEmpty()) {
+ return path;
+ }
}
- return path;
+ return QString();
}
-QString AOApplication::get_sfx_path(QStringList pathlist)
+QString AOApplication::get_sfx_path(QVector<VPath> pathlist)
{
- QString path;
- for (QString p : pathlist) {
- p = get_case_sensitive_path(get_sfx_suffix(p));
- if (file_exists(p)) {
- path = p;
- break;
+ for (const VPath &p : pathlist) {
+ QString path = get_sfx_suffix(p);
+ if (!path.isEmpty()) {
+ return path;
}
}
- return path;
+ return QString();
}
+
QString AOApplication::get_config_value(QString p_identifier, QString p_config, QString p_theme, QString p_subtheme, QString p_default_theme, QString p_misc)
{
QString path;
// qDebug() << "got request for" << p_identifier << "in" << p_config;
- for (QString p : get_asset_paths(p_config, p_theme, p_subtheme, p_default_theme, p_misc)) {
- p = get_case_sensitive_path(p);
- if (file_exists(p)) {
- QSettings settings(p, QSettings::IniFormat);
+ const auto paths = get_asset_paths(p_config, p_theme, p_subtheme, p_default_theme, p_misc);
+ for (const VPath &p : paths) {
+ path = get_real_path(p);
+ if (!path.isEmpty()) {
+ QSettings settings(path, QSettings::IniFormat);
settings.setIniCodec("UTF-8");
QVariant value = settings.value(p_identifier);
if (value.type() == QVariant::StringList) {
@@ -193,25 +175,22 @@ QString AOApplication::get_asset(QString p_element, QString p_theme, QString p_s
return get_asset_path(get_asset_paths(p_element, p_theme, p_subtheme, p_default_theme, p_misc, p_character, p_placeholder));
}
-QString AOApplication::get_image(QString p_element, QString p_theme, QString p_subtheme, QString p_default_theme, QString p_misc, QString p_character, QString p_placeholder)
+QString AOApplication::get_image(QString p_element, QString p_theme, QString p_subtheme, QString p_default_theme, QString p_misc, QString p_character, QString p_placeholder,
+ bool static_image)
{
- return get_image_path(get_asset_paths(p_element, p_theme, p_subtheme, p_default_theme, p_misc, p_character, p_placeholder));
+ return get_image_path(get_asset_paths(p_element, p_theme, p_subtheme, p_default_theme, p_misc, p_character, p_placeholder), static_image);
}
QString AOApplication::get_sfx(QString p_sfx, QString p_misc, QString p_character)
{
- QStringList pathlist = get_asset_paths(p_sfx, current_theme, get_subtheme(), default_theme, p_misc, p_character);
+ QVector<VPath> pathlist = get_asset_paths(p_sfx, current_theme, get_subtheme(), default_theme, p_misc, p_character);
pathlist += get_sounds_path(p_sfx); // Sounds folder path
return get_sfx_path(pathlist);
}
QString AOApplication::get_case_sensitive_path(QString p_file)
{
- // no path traversal above base folder
- if (!(p_file.startsWith(get_base_path())))
- return get_base_path() + p_file;
-
- #ifdef CASE_SENSITIVE_FILESYSTEM
+#ifdef CASE_SENSITIVE_FILESYSTEM
// first, check to see if it's actually there (also serves as base case for
// recursion)
QFileInfo file(p_file);
@@ -219,6 +198,7 @@ QString AOApplication::get_case_sensitive_path(QString p_file)
if (exists(p_file))
return p_file;
+
QString file_parent_dir = get_case_sensitive_path(file.absolutePath());
// second, does it exist in the new parent dir?
@@ -226,14 +206,20 @@ QString AOApplication::get_case_sensitive_path(QString p_file)
return file_parent_dir + "/" + file_basename;
// last resort, dirlist parent dir and find case insensitive match
- QRegExp file_rx =
- QRegExp(file_basename, Qt::CaseInsensitive, QRegExp::FixedString);
- QStringList files = QDir(file_parent_dir).entryList();
- int result = files.indexOf(file_rx);
+ if (!dir_listing_exist_cache.contains(qHash(file_parent_dir))) {
+ QStringList files = QDir(file_parent_dir).entryList();
+ for (const QString &file : files) {
+ dir_listing_cache.insert(qHash(file_parent_dir % QChar('/') % file.toLower()), file);
+ }
+ dir_listing_exist_cache.insert(qHash(file_parent_dir));
+ }
+ QString found_file = dir_listing_cache.value(
+ qHash(file_parent_dir % QChar('/') % file_basename.toLower()));
- if (result != -1)
- return file_parent_dir + "/" + files.at(result);
+ if (!found_file.isEmpty()) {
+ return file_parent_dir + "/" + found_file;
+ }
// if nothing is found, let the caller handle the missing file
return file_parent_dir + "/" + file_basename;
@@ -241,3 +227,81 @@ QString AOApplication::get_case_sensitive_path(QString p_file)
return p_file;
#endif
}
+
+QString AOApplication::get_real_path(const VPath &vpath) {
+ // Try cache first
+ QString phys_path = asset_lookup_cache.value(qHash(vpath));
+ if (!phys_path.isEmpty() && exists(phys_path)) {
+ return phys_path;
+ }
+
+ // Cache miss; try all known mount paths
+ QStringList bases = get_mount_paths();
+ bases.push_front(get_base_path());
+
+ for (const QString &base : bases) {
+ QDir baseDir(base);
+ QString path = baseDir.absoluteFilePath(vpath.toQString());
+ if (!path.startsWith(baseDir.absolutePath())) {
+ qWarning() << "invalid path" << path << "(path is outside vfs)";
+ break;
+ }
+ path = get_case_sensitive_path(path);
+ if (exists(path)) {
+ asset_lookup_cache.insert(qHash(vpath), path);
+ return path;
+ }
+ }
+
+ // Not found in mount paths; check if the file is remote
+ QString remotePath = vpath.toQString();
+ if (remotePath.startsWith("http:") || remotePath.startsWith("https:")) {
+ return remotePath;
+ }
+
+ // File or directory not found
+ return QString();
+}
+
+// Special case of get_real_path where multiple suffixes need to be tried
+// on each mount path.
+QString AOApplication::get_real_suffixed_path(const VPath &vpath,
+ const QStringList &suffixes) {
+ // Try cache first
+ QString phys_path = asset_lookup_cache.value(qHash(vpath));
+ if (!phys_path.isEmpty() && exists(phys_path)) {
+ for (const QString &suffix : suffixes) { // make sure cached asset is the right type
+ if (phys_path.endsWith(suffix, Qt::CaseInsensitive))
+ return phys_path;
+ }
+ }
+
+ // Cache miss; try each suffix on all known mount paths
+ QStringList bases = get_mount_paths();
+ bases.push_front(get_base_path());
+
+ for (const QString &base : bases) {
+ for (const QString &suffix : suffixes) {
+ QDir baseDir(base);
+ QString path = baseDir.absoluteFilePath(vpath.toQString() + suffix);
+ if (!path.startsWith(baseDir.absolutePath())) {
+ qWarning() << "invalid path" << path << "(path is outside vfs)";
+ break;
+ }
+ path = get_case_sensitive_path(path);
+ if (exists(path)) {
+ asset_lookup_cache.insert(qHash(vpath), path);
+ return path;
+ }
+ }
+ }
+
+ // File or directory not found
+ return QString();
+}
+
+void AOApplication::invalidate_lookup_cache() {
+ asset_lookup_cache.clear();
+ dir_listing_cache.clear();
+ dir_listing_exist_cache.clear();
+}