diff --git a/gui/test/resultstree/testresultstree.cpp b/gui/test/resultstree/testresultstree.cpp index 31520f3e6d9..75eb3f362a5 100644 --- a/gui/test/resultstree/testresultstree.cpp +++ b/gui/test/resultstree/testresultstree.cpp @@ -106,9 +106,6 @@ Application& ApplicationList::getApplication(const int /*unused*/) { const Application& ApplicationList::getApplication(const int index) const { return mApplications.at(index); } -QString XmlReport::quoteMessage(const QString &message) { - return message; -} QString XmlReport::unquoteMessage(const QString &message) { return message; } diff --git a/gui/test/xmlreportv2/testxmlreportv2.cpp b/gui/test/xmlreportv2/testxmlreportv2.cpp index 2dc0927b870..c00877e0f35 100644 --- a/gui/test/xmlreportv2/testxmlreportv2.cpp +++ b/gui/test/xmlreportv2/testxmlreportv2.cpp @@ -21,7 +21,9 @@ #include "erroritem.h" #include "xmlreportv2.h" +#include #include +#include #include void TestXmlReportV2::readXml() const @@ -53,4 +55,52 @@ void TestXmlReportV2::readXml() const QCOMPARE(item2.message, QString("Mismatching allocation and deallocation: k")); } +void TestXmlReportV2::writeXmlEscaping() const +{ + QTemporaryDir tmpdir; + const QString path = tmpdir.path() + "/results.xml"; + + ErrorItem item; + item.errorId = "unusedVariable"; + item.severity = Severity::style; + item.summary = "Unused variable: \"x\" & "; + item.message = item.summary; + + QErrorPathItem loc; + loc.file = "test.cpp"; + loc.line = 1; + loc.column = 1; + loc.info = item.summary; + item.errorPath << loc; + loc.line = 2; + item.errorPath << loc; + + { + XmlReportV2 report(path, QString()); + QVERIFY(report.create()); + report.writeHeader(); + report.writeError(item); + report.writeFooter(); + } + + // Each special character must be escaped exactly once + QFile file(path); + QVERIFY(file.open(QIODevice::ReadOnly)); + + const QString xml = QString::fromUtf8(file.readAll()); + QVERIFY(xml.contains("msg=\"Unused variable: "x" & <y>\"")); + QVERIFY(xml.contains("info=\"Unused variable: "x" & <y>\"")); + QVERIFY(!xml.contains("&quot;")); + + XmlReportV2 report(path, QString()); + QVERIFY(report.open()); + + const QList errors = report.read(); + QCOMPARE(errors.size(), 1); + QCOMPARE(errors[0].summary, item.summary); + QCOMPARE(errors[0].message, item.message); + QCOMPARE(errors[0].errorPath.size(), 2); + QCOMPARE(errors[0].errorPath[0].info, item.summary); +} + QTEST_MAIN(TestXmlReportV2) diff --git a/gui/test/xmlreportv2/testxmlreportv2.h b/gui/test/xmlreportv2/testxmlreportv2.h index 9b864239414..9662bd00b27 100644 --- a/gui/test/xmlreportv2/testxmlreportv2.h +++ b/gui/test/xmlreportv2/testxmlreportv2.h @@ -23,4 +23,5 @@ class TestXmlReportV2 : public QObject { private slots: void readXml() const; + void writeXmlEscaping() const; }; diff --git a/gui/xmlreport.cpp b/gui/xmlreport.cpp index c5f00fc5bb7..37befc80235 100644 --- a/gui/xmlreport.cpp +++ b/gui/xmlreport.cpp @@ -32,17 +32,6 @@ XmlReport::XmlReport(const QString &filename) : Report(filename) {} -QString XmlReport::quoteMessage(const QString &message) -{ - QString quotedMessage(message); - quotedMessage.replace("&", "&"); - quotedMessage.replace("\"", """); - quotedMessage.replace("'", "'"); - quotedMessage.replace("<", "<"); - quotedMessage.replace(">", ">"); - return quotedMessage; -} - QString XmlReport::unquoteMessage(const QString &message) { QString quotedMessage(message); diff --git a/gui/xmlreport.h b/gui/xmlreport.h index 2483b1b7471..e4b1ff5103c 100644 --- a/gui/xmlreport.h +++ b/gui/xmlreport.h @@ -42,17 +42,11 @@ class XmlReport : public Report { */ virtual QList read() = 0; - /** - * @brief Quote the message. - * @param message Message to quote. - * @return quoted message. - */ - static QString quoteMessage(const QString &message); - /** * @brief Unquote the message. - * @param message Message to quote. - * @return quoted message. + * For older reports where special characters have been escaped twice (#15107). + * @param message Message to unquote. + * @return unquoted message. */ static QString unquoteMessage(const QString &message); diff --git a/gui/xmlreportv2.cpp b/gui/xmlreportv2.cpp index abf6aa361ba..aba9b0c480f 100644 --- a/gui/xmlreportv2.cpp +++ b/gui/xmlreportv2.cpp @@ -132,10 +132,8 @@ void XmlReportV2::writeError(const ErrorItem &error) // Don't localize severity so we can read these files mXmlWriter->writeAttribute(SeverityAttribute, GuiSeverity::toString(error.severity)); - const QString summary = XmlReport::quoteMessage(error.summary); - mXmlWriter->writeAttribute(MsgAttribute, summary); - const QString message = XmlReport::quoteMessage(error.message); - mXmlWriter->writeAttribute(VerboseAttribute, message); + mXmlWriter->writeAttribute(MsgAttribute, error.summary); + mXmlWriter->writeAttribute(VerboseAttribute, error.message); if (error.inconclusive) mXmlWriter->writeAttribute(InconclusiveAttribute, "true"); if (!error.remark.isEmpty()) @@ -145,7 +143,7 @@ void XmlReportV2::writeError(const ErrorItem &error) if (error.hash > 0) mXmlWriter->writeAttribute(HashAttribute, QString::number(error.hash)); if (!error.file0.isEmpty()) - mXmlWriter->writeAttribute(IncludedFromFilenameAttribute, quoteMessage(error.file0)); + mXmlWriter->writeAttribute(IncludedFromFilenameAttribute, error.file0); if (!error.sinceDate.isEmpty()) mXmlWriter->writeAttribute(SinceDateAttribute, error.sinceDate); if (!error.tags.isEmpty()) @@ -155,12 +153,12 @@ void XmlReportV2::writeError(const ErrorItem &error) mXmlWriter->writeStartElement(LocationElementName); QString file = QDir::toNativeSeparators(error.errorPath[i].file); - mXmlWriter->writeAttribute(FilenameAttribute, XmlReport::quoteMessage(file)); + mXmlWriter->writeAttribute(FilenameAttribute, file); mXmlWriter->writeAttribute(LineAttribute, QString::number(error.errorPath[i].line)); if (error.errorPath[i].column > 0) mXmlWriter->writeAttribute(ColumnAttribute, QString::number(error.errorPath[i].column)); if (error.errorPath.count() > 1) - mXmlWriter->writeAttribute(InfoAttribute, XmlReport::quoteMessage(error.errorPath[i].info)); + mXmlWriter->writeAttribute(InfoAttribute, error.errorPath[i].info); mXmlWriter->writeEndElement(); }