From 38c2e3d1049f494529cb9876bcd564ec20ba512c Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 1 Sep 2014 14:26:51 +0200 Subject: [PATCH] Properly detect UTF-8 BOM markers in ini files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we detect a utf8 BOM mark at the beginning of the .ini file, skip the marker and set the iniCodec to utf8. Task-number: QTBUG-23381 Change-Id: I1b37fc4f1638a48e4f3ee71ab165e2989bc592f1 Reviewed-by: Jędrzej Nowacki --- src/corelib/io/qsettings.cpp | 9 +++++++++ src/corelib/io/qsettings_p.h | 2 +- tests/auto/corelib/io/qsettings/bom.ini | 4 ++++ tests/auto/corelib/io/qsettings/qsettings.qrc | 17 +++++++++-------- .../auto/corelib/io/qsettings/tst_qsettings.cpp | 10 ++++++++++ 5 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 tests/auto/corelib/io/qsettings/bom.ini diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index d896da176a..ebca7d57ff 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -1637,6 +1637,15 @@ bool QConfFileSettingsPrivate::readIniFile(const QByteArray &data, int sectionPosition = 0; bool ok = true; +#ifndef QT_NO_TEXTCODEC + // detect utf8 BOM + const uchar *dd = (const uchar *)data.constData(); + if (data.size() >= 3 && dd[0] == 0xef && dd[1] == 0xbb && dd[2] == 0xbf) { + iniCodec = QTextCodec::codecForName("UTF-8"); + dataPos = 3; + } +#endif + while (readIniLine(data, dataPos, lineStart, lineLen, equalsPos)) { char ch = data.at(lineStart); if (ch == '[') { diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h index cb29b4c83a..715f13530a 100644 --- a/src/corelib/io/qsettings_p.h +++ b/src/corelib/io/qsettings_p.h @@ -282,7 +282,7 @@ public: bool isWritable() const; QString fileName() const; - static bool readIniFile(const QByteArray &data, UnparsedSettingsMap *unparsedIniSections); + bool readIniFile(const QByteArray &data, UnparsedSettingsMap *unparsedIniSections); static bool readIniSection(const QSettingsKey §ion, const QByteArray &data, ParsedSettingsMap *settingsMap, QTextCodec *codec); static bool readIniLine(const QByteArray &data, int &dataPos, int &lineStart, int &lineLen, diff --git a/tests/auto/corelib/io/qsettings/bom.ini b/tests/auto/corelib/io/qsettings/bom.ini new file mode 100644 index 0000000000..8d46ee8d91 --- /dev/null +++ b/tests/auto/corelib/io/qsettings/bom.ini @@ -0,0 +1,4 @@ +[section1] +foo1=bar1 +[section2] +foo2=bar2 diff --git a/tests/auto/corelib/io/qsettings/qsettings.qrc b/tests/auto/corelib/io/qsettings/qsettings.qrc index 587c22ebe3..c0be7e013f 100644 --- a/tests/auto/corelib/io/qsettings/qsettings.qrc +++ b/tests/auto/corelib/io/qsettings/qsettings.qrc @@ -1,9 +1,10 @@ - - - resourcefile.ini - resourcefile2.ini - resourcefile3.ini - resourcefile4.ini - resourcefile5.ini - + + + resourcefile.ini + resourcefile2.ini + resourcefile3.ini + resourcefile4.ini + resourcefile5.ini + bom.ini + diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp index 3e68e4859f..c89923f159 100644 --- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp +++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp @@ -161,6 +161,7 @@ private slots: void testByteArray_data(); void testByteArray(); void iniCodec(); + void bom(); private: const bool m_canWriteNativeSystemSettings; @@ -730,6 +731,15 @@ void tst_QSettings::iniCodec() } +void tst_QSettings::bom() +{ + QSettings s(":/bom.ini", QSettings::IniFormat); + QStringList allkeys = s.allKeys(); + QCOMPARE(allkeys.size(), 2); + QVERIFY(allkeys.contains("section1/foo1")); + QVERIFY(allkeys.contains("section2/foo2")); +} + void tst_QSettings::testErrorHandling_data() { QTest::addColumn("filePerms"); // -1 means file should not exist