mirror of https://github.com/kiwix/libkiwix.git
Merge pull request #1023 from kiwix/suggestions_with_control_characters
Control characters are escaped in suggestions JSON
This commit is contained in:
commit
24faf84163
|
@ -330,17 +330,19 @@ std::string kiwix::render_template(const std::string& template_str, kainjow::mus
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
std::string escapeBackslashes(const std::string& s)
|
std::string escapeForJSON(const std::string& s)
|
||||||
{
|
{
|
||||||
std::string es;
|
std::ostringstream oss;
|
||||||
es.reserve(s.size());
|
|
||||||
for (char c : s) {
|
for (char c : s) {
|
||||||
if ( c == '\\' ) {
|
if ( c == '\\' ) {
|
||||||
es.push_back('\\');
|
oss << "\\\\";
|
||||||
|
} else if ( unsigned(c) < 0x20U ) {
|
||||||
|
oss << "\\u" << std::setw(4) << std::setfill('0') << unsigned(c);
|
||||||
|
} else {
|
||||||
|
oss << c;
|
||||||
}
|
}
|
||||||
es.push_back(c);
|
|
||||||
}
|
}
|
||||||
return es;
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string makeFulltextSearchSuggestion(const std::string& lang,
|
std::string makeFulltextSearchSuggestion(const std::string& lang,
|
||||||
|
@ -368,10 +370,10 @@ void kiwix::Suggestions::add(const zim::SuggestionItem& suggestion)
|
||||||
? suggestion.getSnippet()
|
? suggestion.getSnippet()
|
||||||
: suggestion.getTitle();
|
: suggestion.getTitle();
|
||||||
|
|
||||||
result.set("label", escapeBackslashes(label));
|
result.set("label", escapeForJSON(label));
|
||||||
result.set("value", escapeBackslashes(suggestion.getTitle()));
|
result.set("value", escapeForJSON(suggestion.getTitle()));
|
||||||
result.set("kind", "path");
|
result.set("kind", "path");
|
||||||
result.set("path", escapeBackslashes(suggestion.getPath()));
|
result.set("path", escapeForJSON(suggestion.getPath()));
|
||||||
result.set("first", m_data.is_empty_list());
|
result.set("first", m_data.is_empty_list());
|
||||||
m_data.push_back(result);
|
m_data.push_back(result);
|
||||||
}
|
}
|
||||||
|
@ -381,8 +383,8 @@ void kiwix::Suggestions::addFTSearchSuggestion(const std::string& uiLang,
|
||||||
{
|
{
|
||||||
kainjow::mustache::data result;
|
kainjow::mustache::data result;
|
||||||
const std::string label = makeFulltextSearchSuggestion(uiLang, queryString);
|
const std::string label = makeFulltextSearchSuggestion(uiLang, queryString);
|
||||||
result.set("label", escapeBackslashes(label));
|
result.set("label", escapeForJSON(label));
|
||||||
result.set("value", escapeBackslashes(queryString + " "));
|
result.set("value", escapeForJSON(queryString + " "));
|
||||||
result.set("kind", "pattern");
|
result.set("kind", "pattern");
|
||||||
result.set("first", m_data.is_empty_list());
|
result.set("first", m_data.is_empty_list());
|
||||||
m_data.push_back(result);
|
m_data.push_back(result);
|
||||||
|
|
|
@ -100,7 +100,7 @@ TEST(Suggestions, specialCharHandling)
|
||||||
{
|
{
|
||||||
// HTML special symbols (<, >, &, ", and ') must be HTML-escaped
|
// HTML special symbols (<, >, &, ", and ') must be HTML-escaped
|
||||||
// Backslash symbols (\) must be duplicated.
|
// Backslash symbols (\) must be duplicated.
|
||||||
const std::string SYMBOLS(R"(\<>&'"~!@#$%^*()_+`-=[]{}|:;,.?)");
|
const std::string SYMBOLS("\t\n\r" R"(\<>&'"~!@#$%^*()_+`-=[]{}|:;,.?)");
|
||||||
{
|
{
|
||||||
kiwix::Suggestions s;
|
kiwix::Suggestions s;
|
||||||
s.add(zim::SuggestionItem("Title with " + SYMBOLS,
|
s.add(zim::SuggestionItem("Title with " + SYMBOLS,
|
||||||
|
@ -110,10 +110,10 @@ TEST(Suggestions, specialCharHandling)
|
||||||
CHECK_SUGGESTIONS(s.getJSON(),
|
CHECK_SUGGESTIONS(s.getJSON(),
|
||||||
R"EXPECTEDJSON([
|
R"EXPECTEDJSON([
|
||||||
{
|
{
|
||||||
"value" : "Title with \\<>&'"~!@#$%^*()_+`-=[]{}|:;,.?",
|
"value" : "Title with \u0009\u0010\u0013\\<>&'"~!@#$%^*()_+`-=[]{}|:;,.?",
|
||||||
"label" : "Snippet with \\<>&'"~!@#$%^*()_+`-=[]{}|:;,.?",
|
"label" : "Snippet with \u0009\u0010\u0013\\<>&'"~!@#$%^*()_+`-=[]{}|:;,.?",
|
||||||
"kind" : "path"
|
"kind" : "path"
|
||||||
, "path" : "Path with \\<>&'"~!@#$%^*()_+`-=[]{}|:;,.?"
|
, "path" : "Path with \u0009\u0010\u0013\\<>&'"~!@#$%^*()_+`-=[]{}|:;,.?"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
)EXPECTEDJSON"
|
)EXPECTEDJSON"
|
||||||
|
@ -128,10 +128,10 @@ R"EXPECTEDJSON([
|
||||||
CHECK_SUGGESTIONS(s.getJSON(),
|
CHECK_SUGGESTIONS(s.getJSON(),
|
||||||
R"EXPECTEDJSON([
|
R"EXPECTEDJSON([
|
||||||
{
|
{
|
||||||
"value" : "Snippetless title with \\<>&'"~!@#$%^*()_+`-=[]{}|:;,.?",
|
"value" : "Snippetless title with \u0009\u0010\u0013\\<>&'"~!@#$%^*()_+`-=[]{}|:;,.?",
|
||||||
"label" : "Snippetless title with \\<>&'"~!@#$%^*()_+`-=[]{}|:;,.?",
|
"label" : "Snippetless title with \u0009\u0010\u0013\\<>&'"~!@#$%^*()_+`-=[]{}|:;,.?",
|
||||||
"kind" : "path"
|
"kind" : "path"
|
||||||
, "path" : "Path with \\<>&'"~!@#$%^*()_+`-=[]{}|:;,.?"
|
, "path" : "Path with \u0009\u0010\u0013\\<>&'"~!@#$%^*()_+`-=[]{}|:;,.?"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
)EXPECTEDJSON"
|
)EXPECTEDJSON"
|
||||||
|
@ -145,8 +145,8 @@ R"EXPECTEDJSON([
|
||||||
CHECK_SUGGESTIONS(s.getJSON(),
|
CHECK_SUGGESTIONS(s.getJSON(),
|
||||||
R"EXPECTEDJSON([
|
R"EXPECTEDJSON([
|
||||||
{
|
{
|
||||||
"value" : "text with \\<>&'"~!@#$%^*()_+`-=[]{}|:;,.? ",
|
"value" : "text with \u0009\u0010\u0013\\<>&'"~!@#$%^*()_+`-=[]{}|:;,.? ",
|
||||||
"label" : "containing 'text with \\<>&'"~!@#$%^*()_+`-=[]{}|:;,.?'...",
|
"label" : "containing 'text with \u0009\u0010\u0013\\<>&'"~!@#$%^*()_+`-=[]{}|:;,.?'...",
|
||||||
"kind" : "pattern"
|
"kind" : "pattern"
|
||||||
//EOLWHITESPACEMARKER
|
//EOLWHITESPACEMARKER
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue