diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index a897806c2..0ea28dceb 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -55,7 +55,6 @@ void Config::GameSettings::validatePaths() for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) { QString path = QString::fromUtf8(it->string().c_str()); - path.remove(QChar('\"')); QDir dir(path); if (dir.exists()) @@ -64,6 +63,11 @@ void Config::GameSettings::validatePaths() // Do the same for data-local QString local = mSettings.value(QString("data-local")); + if (local.at(0) == QChar('\"')) + { + local.remove(0, 1); + local.chop(1); + } if (local.isEmpty()) return; @@ -76,7 +80,6 @@ void Config::GameSettings::validatePaths() if (!dataDirs.empty()) { QString path = QString::fromUtf8(dataDirs.front().string().c_str()); - path.remove(QChar('\"')); QDir dir(path); if (dir.exists()) @@ -120,6 +123,28 @@ bool Config::GameSettings::readFile(QTextStream &stream, QMap // Don't remove existing data entries if (key != QLatin1String("data")) settings.remove(key); + else + { + // 'data=...' line, so needs processing to deal with ampersands and quotes + // The following is based on boost::io::detail::quoted_manip.hpp, but calling those functions did not work as there are too may QStrings involved + QChar delim = '\"'; + QChar escape = '&'; + + if (value.at(0) == delim) + { + QString valueOriginal = value; + value = ""; + + for (QString::const_iterator it = valueOriginal.begin() + 1; it != valueOriginal.end(); ++it) + { + if (*it == escape) + ++it; + else if (*it == delim) + break; + value += *it; + } + } + } QStringList values = cache.values(key); values.append(settings.values(key)); @@ -152,9 +177,31 @@ bool Config::GameSettings::writeFile(QTextStream &stream) while (i.hasPrevious()) { i.previous(); + // 'data=...' lines need quotes and ampersands escaping to match how boost::filesystem::path uses boost::io::quoted + if (i.key() == QLatin1String("data")) + { + stream << i.key() << "="; + + // The following is based on boost::io::detail::quoted_manip.hpp, but calling those functions did not work as there are too may QStrings involved + QChar delim = '\"'; + QChar escape = '&'; + QString string = i.value(); + + stream << delim; + for (QString::const_iterator it = string.begin(); it != string.end(); ++it) + { + if (*it == delim || *it == escape) + stream << escape; + stream << *it; + } + stream << delim; + + stream << '\n'; + continue; + } + // Quote paths with spaces - if (i.key() == QLatin1String("data") - || i.key() == QLatin1String("data-local") + if (i.key() == QLatin1String("data-local") || i.key() == QLatin1String("resources")) { if (i.value().contains(QChar(' '))) @@ -358,9 +405,26 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) { it.previous(); + if (it.key() == QLatin1String("data")) + { + settingLine = it.key() + "="; + + // The following is based on boost::io::detail::quoted_manip.hpp, but calling those functions did not work as there are too may QStrings involved + QChar delim = '\"'; + QChar escape = '&'; + QString string = it.value(); + + settingLine += delim; + for (QString::const_iterator iter = string.begin(); iter != string.end(); ++iter) + { + if (*iter == delim || *iter == escape) + settingLine += escape; + settingLine += *iter; + } + settingLine += delim; + } // Quote paths with spaces - if ((it.key() == QLatin1String("data") - || it.key() == QLatin1String("data-local") + else if ((it.key() == QLatin1String("data-local") || it.key() == QLatin1String("resources")) && it.value().contains(QChar(' '))) { QString stripped = it.value(); diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index 5316255ad..7c3956a29 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -75,8 +75,6 @@ void ConfigurationManager::processPaths(Files::PathContainer& dataDirs, bool cre for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) { path = it->string(); - boost::erase_all(path, "\""); - *it = boost::filesystem::path(path); // Check if path contains a token if (!path.empty() && *path.begin() == '?')