diff options
author | Lucie Gerard <lucie.gerard@qt.io> | 2019-04-03 09:02:35 +0200 |
---|---|---|
committer | Lucie Gerard <lucie.gerard@qt.io> | 2019-04-03 07:09:38 +0000 |
commit | 3d095069cf2e2e349489bcf5faf92145320471fb (patch) | |
tree | 9e09badc10713851f568a9a6cf163da03f57b615 | |
parent | b8a6084861456f5448c0fd0c22e0192e83ffb5f0 (diff) |
lupdate: Escape special characters when processing QML
The transcode function is now in a parser tool class.
It is used by the cpp and qml parser.
Fixes: QTBUG-40639
Change-Id: I3c9c9d137669900642a077cf81a739bfc31be800
Reviewed-by: Kai Koehne <kai.koehne@qt.io>
-rw-r--r-- | src/linguist/lupdate/cpp.cpp | 66 | ||||
-rw-r--r-- | src/linguist/lupdate/lupdate.h | 5 | ||||
-rw-r--r-- | src/linguist/lupdate/main.cpp | 51 | ||||
-rw-r--r-- | src/linguist/lupdate/qdeclarative.cpp | 12 |
4 files changed, 69 insertions, 65 deletions
diff --git a/src/linguist/lupdate/cpp.cpp b/src/linguist/lupdate/cpp.cpp index d8a4f9a37..e96e102af 100644 --- a/src/linguist/lupdate/cpp.cpp +++ b/src/linguist/lupdate/cpp.cpp @@ -250,7 +250,6 @@ private: bool matchStringOrNull(QString *s); bool matchExpression(); - QString transcode(const QString &str); void recordMessage( int line, const QString &context, const QString &text, const QString &comment, const QString &extracomment, const QString &msgid, const TranslatorMessage::ExtraData &extra, @@ -1469,7 +1468,7 @@ bool CppParser::matchString(QString *s) return matches; matches = true; if (yyTok == Tok_String) - *s += transcode(yyWord); + *s += ParserTool::transcode(yyWord); else *s += yyWord; s->detach(); @@ -1550,65 +1549,14 @@ bool CppParser::matchExpression() return true; } -QString CppParser::transcode(const QString &str) -{ - static const char tab[] = "abfnrtv"; - static const char backTab[] = "\a\b\f\n\r\t\v"; - // This function has to convert back to bytes, as C's \0* sequences work at that level. - const QByteArray in = str.toUtf8(); - QByteArray out; - - out.reserve(in.length()); - for (int i = 0; i < in.length();) { - uchar c = in[i++]; - if (c == '\\') { - if (i >= in.length()) - break; - c = in[i++]; - - if (c == '\n') - continue; - - if (c == 'x' || c == 'u' || c == 'U') { - const bool unicode = (c != 'x'); - QByteArray hex; - while (i < in.length() && isxdigit((c = in[i]))) { - hex += c; - i++; - } - if (unicode) - out += QString(QChar(hex.toUInt(nullptr, 16))).toUtf8(); - else - out += hex.toUInt(nullptr, 16); - } else if (c >= '0' && c < '8') { - QByteArray oct; - int n = 0; - oct += c; - while (n < 2 && i < in.length() && (c = in[i]) >= '0' && c < '8') { - i++; - n++; - oct += c; - } - out += oct.toUInt(0, 8); - } else { - const char *p = strchr(tab, c); - out += !p ? c : backTab[p - tab]; - } - } else { - out += c; - } - } - return QString::fromUtf8(out.constData(), out.length()); -} - void CppParser::recordMessage(int line, const QString &context, const QString &text, const QString &comment, const QString &extracomment, const QString &msgid, const TranslatorMessage::ExtraData &extra, bool plural) { TranslatorMessage msg( - transcode(context), text, transcode(comment), QString(), + ParserTool::transcode(context), text, ParserTool::transcode(comment), QString(), yyFileName, line, QStringList(), TranslatorMessage::Unfinished, plural); - msg.setExtraComment(transcode(extracomment.simplified())); + msg.setExtraComment(ParserTool::transcode(extracomment.simplified())); msg.setId(msgid); msg.setExtras(extra); tor->append(msg); @@ -1778,7 +1726,7 @@ void CppParser::handleTrId(bool plural) yyTok = getToken(); if (matchString(&msgid) && !msgid.isEmpty()) { plural |= match(Tok_Comma); - recordMessage(line, QString(), transcode(sourcetext), QString(), extracomment, + recordMessage(line, QString(), ParserTool::transcode(sourcetext), QString(), extracomment, msgid, extra, plural); } sourcetext.clear(); @@ -2335,11 +2283,11 @@ void CppParser::processComment() context = comment.left(k); comment.remove(0, k + 1); TranslatorMessage msg( - transcode(context), QString(), - transcode(comment), QString(), + ParserTool::transcode(context), QString(), + ParserTool::transcode(comment), QString(), yyFileName, yyLineNo, QStringList(), TranslatorMessage::Finished, false); - msg.setExtraComment(transcode(extracomment.simplified())); + msg.setExtraComment(ParserTool::transcode(extracomment.simplified())); extracomment.clear(); tor->append(msg); tor->setExtras(extra); diff --git a/src/linguist/lupdate/lupdate.h b/src/linguist/lupdate/lupdate.h index 0d98379d0..bb58cbd1e 100644 --- a/src/linguist/lupdate/lupdate.h +++ b/src/linguist/lupdate/lupdate.h @@ -99,6 +99,11 @@ bool loadQml(Translator &translator, const QString &filename, ConversionData &cd UNARY_MACRO(qsTranslate) \ /*end*/ +class ParserTool +{ +public: + static QString transcode(const QString &str); +}; class TrFunctionAliasManager { public: diff --git a/src/linguist/lupdate/main.cpp b/src/linguist/lupdate/main.cpp index ba1126aa7..c6b026dc7 100644 --- a/src/linguist/lupdate/main.cpp +++ b/src/linguist/lupdate/main.cpp @@ -136,6 +136,57 @@ QStringList TrFunctionAliasManager::availableFunctionsWithAliases() const TrFunctionAliasManager trFunctionAliasManager; +QString ParserTool::transcode(const QString &str) +{ + static const char tab[] = "abfnrtv"; + static const char backTab[] = "\a\b\f\n\r\t\v"; + // This function has to convert back to bytes, as C's \0* sequences work at that level. + const QByteArray in = str.toUtf8(); + QByteArray out; + + out.reserve(in.length()); + for (int i = 0; i < in.length();) { + uchar c = in[i++]; + if (c == '\\') { + if (i >= in.length()) + break; + c = in[i++]; + + if (c == '\n') + continue; + + if (c == 'x' || c == 'u' || c == 'U') { + const bool unicode = (c != 'x'); + QByteArray hex; + while (i < in.length() && isxdigit((c = in[i]))) { + hex += c; + i++; + } + if (unicode) + out += QString(QChar(hex.toUInt(nullptr, 16))).toUtf8(); + else + out += hex.toUInt(nullptr, 16); + } else if (c >= '0' && c < '8') { + QByteArray oct; + int n = 0; + oct += c; + while (n < 2 && i < in.length() && (c = in[i]) >= '0' && c < '8') { + i++; + n++; + oct += c; + } + out += oct.toUInt(0, 8); + } else { + const char *p = strchr(tab, c); + out += !p ? c : backTab[p - tab]; + } + } else { + out += c; + } + } + return QString::fromUtf8(out.constData(), out.length()); +} + static QString m_defaultExtensions; static void printOut(const QString & out) diff --git a/src/linguist/lupdate/qdeclarative.cpp b/src/linguist/lupdate/qdeclarative.cpp index 69164add2..fa8ad260e 100644 --- a/src/linguist/lupdate/qdeclarative.cpp +++ b/src/linguist/lupdate/qdeclarative.cpp @@ -130,11 +130,11 @@ protected: if (!sourcetext.isEmpty()) yyMsg(identLineNo) << qPrintable(LU::tr("//% cannot be used with %1(). Ignoring\n").arg(name)); - TranslatorMessage msg(m_component, source, + TranslatorMessage msg(m_component, ParserTool::transcode(source), comment, QString(), m_fileName, node->firstSourceLocation().startLine, QStringList(), TranslatorMessage::Unfinished, plural); - msg.setExtraComment(extracomment.simplified()); + msg.setExtraComment(ParserTool::transcode(extracomment.simplified())); msg.setId(msgid); msg.setExtras(extra); m_translator->extend(msg, m_cd); @@ -171,11 +171,11 @@ protected: plural = true; } - TranslatorMessage msg(context, source, + TranslatorMessage msg(context, ParserTool::transcode(source), comment, QString(), m_fileName, node->firstSourceLocation().startLine, QStringList(), TranslatorMessage::Unfinished, plural); - msg.setExtraComment(extracomment.simplified()); + msg.setExtraComment(ParserTool::transcode(extracomment.simplified())); msg.setId(msgid); msg.setExtras(extra); m_translator->extend(msg, m_cd); @@ -199,11 +199,11 @@ protected: bool plural = node->arguments->next; - TranslatorMessage msg(QString(), sourcetext, + TranslatorMessage msg(QString(), ParserTool::transcode(sourcetext), QString(), QString(), m_fileName, node->firstSourceLocation().startLine, QStringList(), TranslatorMessage::Unfinished, plural); - msg.setExtraComment(extracomment.simplified()); + msg.setExtraComment(ParserTool::transcode(extracomment.simplified())); msg.setId(id); msg.setExtras(extra); m_translator->extend(msg, m_cd); |