mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-10-01 01:26:01 -04:00
Strip invalid XML chars when writing databases.
These characters are unprintable or just plain invalid. QXmlStreamReader throws and error when reading XML documents with such chars. Closes #392
This commit is contained in:
parent
5e6b17aba4
commit
2d741afe3e
@ -374,7 +374,7 @@ void KeePass2XmlWriter::writeEntry(const Entry* entry)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!value.isEmpty()) {
|
if (!value.isEmpty()) {
|
||||||
m_xml.writeCharacters(value);
|
m_xml.writeCharacters(stripInvalidXml10Chars(value));
|
||||||
}
|
}
|
||||||
m_xml.writeEndElement();
|
m_xml.writeEndElement();
|
||||||
|
|
||||||
@ -445,7 +445,7 @@ void KeePass2XmlWriter::writeString(const QString& qualifiedName, const QString&
|
|||||||
m_xml.writeEmptyElement(qualifiedName);
|
m_xml.writeEmptyElement(qualifiedName);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_xml.writeTextElement(qualifiedName, string);
|
m_xml.writeTextElement(qualifiedName, stripInvalidXml10Chars(string));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,6 +549,23 @@ QString KeePass2XmlWriter::colorPartToString(int value)
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString KeePass2XmlWriter::stripInvalidXml10Chars(QString str)
|
||||||
|
{
|
||||||
|
for (int i = str.size() - 1; i >= 0; i--) {
|
||||||
|
const ushort uc = str.at(i).unicode();
|
||||||
|
|
||||||
|
if ((uc < 0x20 && uc != 0x09 && uc != 0x0A && uc != 0x0D)
|
||||||
|
|| (uc > 0xD7FF && uc < 0xE000)
|
||||||
|
|| (uc > 0xFFFD))
|
||||||
|
{
|
||||||
|
qWarning("Stripping invalid XML 1.0 codepoint %x", uc);
|
||||||
|
str.remove(i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
void KeePass2XmlWriter::raiseError(const QString& errorMessage)
|
void KeePass2XmlWriter::raiseError(const QString& errorMessage)
|
||||||
{
|
{
|
||||||
m_error = true;
|
m_error = true;
|
||||||
|
@ -73,6 +73,7 @@ private:
|
|||||||
void writeColor(const QString& qualifiedName, const QColor& color);
|
void writeColor(const QString& qualifiedName, const QColor& color);
|
||||||
void writeTriState(const QString& qualifiedName, Group::TriState triState);
|
void writeTriState(const QString& qualifiedName, Group::TriState triState);
|
||||||
QString colorPartToString(int value);
|
QString colorPartToString(int value);
|
||||||
|
QString stripInvalidXml10Chars(QString str);
|
||||||
|
|
||||||
void raiseError(const QString& errorMessage);
|
void raiseError(const QString& errorMessage);
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include "TestKeePass2XmlReader.h"
|
#include "TestKeePass2XmlReader.h"
|
||||||
|
|
||||||
|
#include <QBuffer>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QTest>
|
#include <QTest>
|
||||||
|
|
||||||
@ -26,6 +27,7 @@
|
|||||||
#include "core/Metadata.h"
|
#include "core/Metadata.h"
|
||||||
#include "crypto/Crypto.h"
|
#include "crypto/Crypto.h"
|
||||||
#include "format/KeePass2XmlReader.h"
|
#include "format/KeePass2XmlReader.h"
|
||||||
|
#include "format/KeePass2XmlWriter.h"
|
||||||
#include "config-keepassx-tests.h"
|
#include "config-keepassx-tests.h"
|
||||||
|
|
||||||
QTEST_GUILESS_MAIN(TestKeePass2XmlReader)
|
QTEST_GUILESS_MAIN(TestKeePass2XmlReader)
|
||||||
@ -408,6 +410,35 @@ void TestKeePass2XmlReader::testEmptyUuids()
|
|||||||
QVERIFY(!reader.hasError());
|
QVERIFY(!reader.hasError());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestKeePass2XmlReader::testInvalidXmlChars()
|
||||||
|
{
|
||||||
|
QScopedPointer<Database> dbWrite(new Database());
|
||||||
|
|
||||||
|
Entry* entry = new Entry();
|
||||||
|
entry->setUuid(Uuid::random());
|
||||||
|
entry->setNotes(QString("a %1 b %2 c %3").arg(QChar(0x02)).arg(QChar(0xD800)).arg(QChar(0xFFFE)));
|
||||||
|
entry->setGroup(dbWrite->rootGroup());
|
||||||
|
|
||||||
|
QBuffer buffer;
|
||||||
|
buffer.open(QIODevice::ReadWrite);
|
||||||
|
KeePass2XmlWriter writer;
|
||||||
|
writer.writeDatabase(&buffer, dbWrite.data());
|
||||||
|
QVERIFY(!writer.hasError());
|
||||||
|
buffer.seek(0);
|
||||||
|
|
||||||
|
KeePass2XmlReader reader;
|
||||||
|
reader.setStrictMode(true);
|
||||||
|
QScopedPointer<Database> dbRead(reader.readDatabase(&buffer));
|
||||||
|
if (reader.hasError()) {
|
||||||
|
qWarning("Database read error: %s", qPrintable(reader.errorString()));
|
||||||
|
}
|
||||||
|
QVERIFY(!reader.hasError());
|
||||||
|
QVERIFY(!dbRead.isNull());
|
||||||
|
QCOMPARE(dbRead->rootGroup()->entries().size(), 1);
|
||||||
|
// check that the invalid codepoints have been stripped
|
||||||
|
QCOMPARE(dbRead->rootGroup()->entries().first()->notes(), QString("a b c "));
|
||||||
|
}
|
||||||
|
|
||||||
void TestKeePass2XmlReader::cleanupTestCase()
|
void TestKeePass2XmlReader::cleanupTestCase()
|
||||||
{
|
{
|
||||||
delete m_db;
|
delete m_db;
|
||||||
|
@ -42,6 +42,7 @@ private Q_SLOTS:
|
|||||||
void testBroken();
|
void testBroken();
|
||||||
void testBroken_data();
|
void testBroken_data();
|
||||||
void testEmptyUuids();
|
void testEmptyUuids();
|
||||||
|
void testInvalidXmlChars();
|
||||||
void cleanupTestCase();
|
void cleanupTestCase();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user