Escape blacklisted html tags
This commit is contained in:
parent
62f17dffbd
commit
3f02b0bf56
@ -314,37 +314,67 @@ utils::linkifyMessage(const QString &body)
|
|||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray
|
QString
|
||||||
escapeRawHtml(const QByteArray &data)
|
utils::escapeBlacklistedHtml(const QString &rawStr)
|
||||||
{
|
{
|
||||||
|
static const std::vector<std::string_view> allowedTags = {
|
||||||
|
"font", "/font", "del", "/del", "h1", "/h1", "h2", "/h2",
|
||||||
|
"h3", "/h3", "h4", "/h4", "h5", "/h5", "h6", "/h6",
|
||||||
|
"blockquote", "/blockquote", "p", "/p", "a", "/a", "ul", "/ul",
|
||||||
|
"ol", "/ol", "sup", "/sup", "sub", "/sub", "li", "/li",
|
||||||
|
"b", "/b", "i", "/i", "u", "/u", "strong", "/strong",
|
||||||
|
"em", "/em", "strike", "/strike", "code", "/code", "hr", "/hr",
|
||||||
|
"br", "br/", "div", "/div", "table", "/table", "thead", "/thead",
|
||||||
|
"tbody", "/tbody", "tr", "/tr", "th", "/th", "td", "/td",
|
||||||
|
"caption", "/caption", "pre", "/pre", "span", "/span", "img", "/img"};
|
||||||
|
QByteArray data = rawStr.toUtf8();
|
||||||
QByteArray buffer;
|
QByteArray buffer;
|
||||||
const size_t length = data.size();
|
const size_t length = data.size();
|
||||||
buffer.reserve(length);
|
buffer.reserve(length);
|
||||||
|
bool escapingTag = false;
|
||||||
for (size_t pos = 0; pos != length; ++pos) {
|
for (size_t pos = 0; pos != length; ++pos) {
|
||||||
switch (data.at(pos)) {
|
switch (data.at(pos)) {
|
||||||
case '&':
|
case '<': {
|
||||||
buffer.append("&");
|
bool oneTagMatched = false;
|
||||||
break;
|
size_t endPos = std::min(static_cast<size_t>(data.indexOf('>', pos)),
|
||||||
case '<':
|
static_cast<size_t>(data.indexOf(' ', pos)));
|
||||||
buffer.append("<");
|
|
||||||
|
auto mid = data.mid(pos + 1, endPos - pos - 1);
|
||||||
|
for (const auto &tag : allowedTags) {
|
||||||
|
// TODO: Check src and href attribute
|
||||||
|
if (mid.compare(tag.data(), Qt::CaseInsensitive) == 0) {
|
||||||
|
oneTagMatched = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (oneTagMatched)
|
||||||
|
buffer.append('<');
|
||||||
|
else {
|
||||||
|
escapingTag = true;
|
||||||
|
buffer.append("<");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case '>':
|
case '>':
|
||||||
buffer.append(">");
|
if (escapingTag)
|
||||||
|
buffer.append(">");
|
||||||
|
else {
|
||||||
|
escapingTag = false;
|
||||||
|
buffer.append('>');
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
buffer.append(data.at(pos));
|
buffer.append(data.at(pos));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return buffer;
|
return QString::fromUtf8(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString
|
QString
|
||||||
utils::markdownToHtml(const QString &text)
|
utils::markdownToHtml(const QString &text)
|
||||||
{
|
{
|
||||||
const auto str = escapeRawHtml(text.toUtf8());
|
const auto str = text.toUtf8();
|
||||||
const char *tmp_buf =
|
const char *tmp_buf = cmark_markdown_to_html(str.constData(), str.size(), CMARK_OPT_UNSAFE);
|
||||||
cmark_markdown_to_html(str.constData(), str.size(), CMARK_OPT_DEFAULT);
|
|
||||||
|
|
||||||
// Copy the null terminated output buffer.
|
// Copy the null terminated output buffer.
|
||||||
std::string html(tmp_buf);
|
std::string html(tmp_buf);
|
||||||
@ -352,7 +382,7 @@ utils::markdownToHtml(const QString &text)
|
|||||||
// The buffer is no longer needed.
|
// The buffer is no longer needed.
|
||||||
free((char *)tmp_buf);
|
free((char *)tmp_buf);
|
||||||
|
|
||||||
auto result = QString::fromStdString(html).trimmed();
|
auto result = escapeBlacklistedHtml(QString::fromStdString(html)).trimmed();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -286,6 +286,10 @@ linkifyMessage(const QString &body);
|
|||||||
QString
|
QString
|
||||||
markdownToHtml(const QString &text);
|
markdownToHtml(const QString &text);
|
||||||
|
|
||||||
|
//! Escape every html tag, that was not whitelisted
|
||||||
|
QString
|
||||||
|
escapeBlacklistedHtml(const QString &data);
|
||||||
|
|
||||||
//! Generate a Rich Reply quote message
|
//! Generate a Rich Reply quote message
|
||||||
QString
|
QString
|
||||||
getFormattedQuoteBody(const RelatedInfo &related, const QString &html);
|
getFormattedQuoteBody(const RelatedInfo &related, const QString &html);
|
||||||
|
@ -260,8 +260,8 @@ TimelineModel::data(const QString &id, int role) const
|
|||||||
const static QRegularExpression replyFallback(
|
const static QRegularExpression replyFallback(
|
||||||
"<mx-reply>.*</mx-reply>", QRegularExpression::DotMatchesEverythingOption);
|
"<mx-reply>.*</mx-reply>", QRegularExpression::DotMatchesEverythingOption);
|
||||||
return QVariant(
|
return QVariant(
|
||||||
utils::replaceEmoji(utils::linkifyMessage(formattedBodyWithFallback(event)))
|
utils::replaceEmoji(utils::linkifyMessage(utils::escapeBlacklistedHtml(
|
||||||
.remove(replyFallback));
|
formattedBodyWithFallback(event).remove(replyFallback)))));
|
||||||
}
|
}
|
||||||
case Url:
|
case Url:
|
||||||
return QVariant(QString::fromStdString(url(event)));
|
return QVariant(QString::fromStdString(url(event)));
|
||||||
|
Loading…
Reference in New Issue
Block a user