Do not use Qt streams with legacy encodings in the Wizard code

7220-lua-add-a-general-purpose-lexical-parser
Andrei Kortunov 2 years ago
parent e575c25278
commit 9a7c57874d

@ -5,7 +5,10 @@
#include <QRegularExpression>
#include <QString>
#include <QStringList>
#include <QTextStream>
#include <fstream>
#include <components/files/qtconversion.hpp>
Wizard::IniSettings::IniSettings() {}
@ -25,7 +28,7 @@ QStringList Wizard::IniSettings::findKeys(const QString& text)
return result;
}
bool Wizard::IniSettings::readFile(QTextStream& stream)
bool Wizard::IniSettings::readFile(std::ifstream& stream, ToUTF8::FromType encoding)
{
// Look for a square bracket, "'\\["
// that has one or more "not nothing" in it, "([^]]+)"
@ -39,10 +42,20 @@ bool Wizard::IniSettings::readFile(QTextStream& stream)
QString currentSection;
while (!stream.atEnd())
ToUTF8::Utf8Encoder encoder(encoding);
std::string legacyEncLine;
while (std::getline(stream, legacyEncLine))
{
const QString line(stream.readLine());
std::string_view lineBuffer = encoder.getUtf8(legacyEncLine);
// unify Unix-style and Windows file ending
if (!(lineBuffer.empty()) && (lineBuffer[lineBuffer.length() - 1]) == '\r')
{
lineBuffer = lineBuffer.substr(0, lineBuffer.length() - 1);
}
const QString line = QString::fromStdString(std::string(lineBuffer));
if (line.isEmpty() || line.startsWith(QLatin1Char(';')))
continue;
@ -70,7 +83,7 @@ bool Wizard::IniSettings::readFile(QTextStream& stream)
return true;
}
bool Wizard::IniSettings::writeFile(const QString& path, QTextStream& stream)
bool Wizard::IniSettings::writeFile(const QString& path, std::ifstream& stream, ToUTF8::FromType encoding)
{
// Look for a square bracket, "'\\["
// that has one or more "not nothing" in it, "([^]]+)"
@ -87,10 +100,19 @@ bool Wizard::IniSettings::writeFile(const QString& path, QTextStream& stream)
QString currentSection;
QString buffer;
while (!stream.atEnd())
ToUTF8::Utf8Encoder encoder(encoding);
std::string legacyEncLine;
while (std::getline(stream, legacyEncLine))
{
const QString line(stream.readLine());
std::string_view lineBuffer = encoder.getUtf8(legacyEncLine);
// unify Unix-style and Windows file ending
if (!(lineBuffer.empty()) && (lineBuffer[lineBuffer.length() - 1]) == '\r')
{
lineBuffer = lineBuffer.substr(0, lineBuffer.length() - 1);
}
const QString line = QString::fromStdString(std::string(lineBuffer));
if (line.isEmpty() || line.startsWith(QLatin1Char(';')))
{
buffer.append(line + QLatin1String("\n"));
@ -158,27 +180,13 @@ bool Wizard::IniSettings::writeFile(const QString& path, QTextStream& stream)
}
}
// Now we reopen the file, this time we write
QFile file(path);
if (file.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text))
{
QTextStream in(&file);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
in.setCodec(stream.codec());
#else
in.setEncoding(stream.encoding());
#endif
// Write the updated buffer to an empty file
in << buffer;
file.flush();
file.close();
}
else
{
const auto iniPath = Files::pathFromQString(path);
std::ofstream file(iniPath, std::ios::out);
if (file.fail())
return false;
}
file << encoder.getLegacyEnc(buffer.toStdString());
file.close();
return true;
}

@ -4,7 +4,7 @@
#include <QHash>
#include <QVariant>
class QTextStream;
#include <components/to_utf8/to_utf8.hpp>
namespace Wizard
{
@ -30,8 +30,8 @@ namespace Wizard
QStringList findKeys(const QString& text);
bool readFile(QTextStream& stream);
bool writeFile(const QString& path, QTextStream& stream);
bool readFile(std::ifstream& stream, ToUTF8::FromType encoding);
bool writeFile(const QString& path, std::ifstream& stream, ToUTF8::FromType encoding);
bool parseInx(const QString& path);

@ -128,15 +128,15 @@ void Wizard::InstallationPage::startInstallation()
if (language == QLatin1String("Polish"))
{
mUnshield->setIniCodec(QTextCodec::codecForName("windows-1250"));
mUnshield->setIniEncoding(ToUTF8::FromType::WINDOWS_1250);
}
else if (language == QLatin1String("Russian"))
{
mUnshield->setIniCodec(QTextCodec::codecForName("windows-1251"));
mUnshield->setIniEncoding(ToUTF8::FromType::WINDOWS_1251);
}
else
{
mUnshield->setIniCodec(QTextCodec::codecForName("windows-1252"));
mUnshield->setIniEncoding(ToUTF8::FromType::WINDOWS_1252);
}
mThread->start();

@ -6,8 +6,10 @@
#include <QFileInfo>
#include <QReadLocker>
#include <QStringList>
#include <QTextCodec>
#include <QTextStream>
#include <fstream>
#include <components/files/qtconversion.hpp>
#include <apps/wizard/inisettings.hpp>
@ -23,7 +25,7 @@ Wizard::UnshieldWorker::UnshieldWorker(qint64 expectedMorrowindBsaSize, QObject*
mDiskPath = QString();
// Default to Latin encoding
mIniCodec = QTextCodec::codecForName("windows-1252");
mIniEncoding = ToUTF8::FromType::WINDOWS_1252;
mInstallMorrowind = false;
mInstallTribunal = false;
@ -153,10 +155,10 @@ QString Wizard::UnshieldWorker::getDiskPath()
return mDiskPath;
}
void Wizard::UnshieldWorker::setIniCodec(QTextCodec* codec)
void Wizard::UnshieldWorker::setIniEncoding(ToUTF8::FromType encoding)
{
QWriteLocker writeLock(&mLock);
mIniCodec = codec;
mIniEncoding = encoding;
}
void Wizard::UnshieldWorker::wakeAll()
@ -170,19 +172,16 @@ bool Wizard::UnshieldWorker::setupSettings()
if (getIniPath().isEmpty())
return false;
QFile file(getIniPath());
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
const auto iniPath = Files::pathFromQString(getIniPath());
std::ifstream file(iniPath);
if (file.fail())
{
emit error(tr("Failed to open Morrowind configuration file!"),
tr("Opening %1 failed: %2.").arg(getIniPath(), file.errorString()));
tr("Opening %1 failed: %2.").arg(getIniPath(), strerror(errno)));
return false;
}
QTextStream stream(&file);
stream.setCodec(mIniCodec);
mIniSettings.readFile(stream);
mIniSettings.readFile(file, mIniEncoding);
return true;
}
@ -192,22 +191,19 @@ bool Wizard::UnshieldWorker::writeSettings()
if (getIniPath().isEmpty())
return false;
QFile file(getIniPath());
if (!file.open(QIODevice::ReadWrite | QIODevice::Text))
const auto iniPath = Files::pathFromQString(getIniPath());
std::ifstream file(iniPath);
if (file.fail())
{
emit error(tr("Failed to open Morrowind configuration file!"),
tr("Opening %1 failed: %2.").arg(getIniPath(), file.errorString()));
tr("Opening %1 failed: %2.").arg(getIniPath(), strerror(errno)));
return false;
}
QTextStream stream(&file);
stream.setCodec(mIniCodec);
if (!mIniSettings.writeFile(getIniPath(), stream))
if (!mIniSettings.writeFile(getIniPath(), file, mIniEncoding))
{
emit error(tr("Failed to write Morrowind configuration file!"),
tr("Writing to %1 failed: %2.").arg(getIniPath(), file.errorString()));
tr("Writing to %1 failed: %2.").arg(getIniPath(), strerror(errno)));
return false;
}

@ -41,7 +41,7 @@ namespace Wizard
QString getPath();
QString getIniPath();
void setIniCodec(QTextCodec* codec);
void setIniEncoding(ToUTF8::FromType encoding);
bool setupSettings();
@ -104,7 +104,7 @@ namespace Wizard
IniSettings mIniSettings;
QTextCodec* mIniCodec;
ToUTF8::FromType mIniEncoding;
QWaitCondition mWait;

Loading…
Cancel
Save