mirror of https://github.com/kiwix/libkiwix.git
Proper HTML encoding/decoding of tags in the frontend
- Tags in the OPDS feed are HTML encoded and must be decoded. - Tag values must be HTML encoded when injected into the DOM: * When the injection is done by setting the innerHTML attribute of a DOM element, HTML encoding must be done explicitly (since that text is going to be parsed as HTML). * When the tag value is expanded into a string that is then set as an attribute of a DOM element via the setAttribute() method, no HTML encoding must be done (since Element.setAttribute() directly sets that value and no HTML decoding is involved in that operation).
This commit is contained in:
parent
fbcd160efd
commit
846404e959
|
@ -51,8 +51,8 @@
|
||||||
, "torrent-download-link-text": "BitTorrent"
|
, "torrent-download-link-text": "BitTorrent"
|
||||||
, "torrent-download-alt-text": "Download via BitTorrent"
|
, "torrent-download-alt-text": "Download via BitTorrent"
|
||||||
, "library-opds-feed-all-entries": "Library OPDS Feed - All entries"
|
, "library-opds-feed-all-entries": "Library OPDS Feed - All entries"
|
||||||
, "filter-by-tag": "Filter by tag \"{{TAG}}\""
|
, "filter-by-tag": "Filter by tag \"{{{TAG}}}\""
|
||||||
, "stop-filtering-by-tag": "Stop filtering by tag \"{{TAG}}\""
|
, "stop-filtering-by-tag": "Stop filtering by tag \"{{{TAG}}}\""
|
||||||
, "library-opds-feed-parameterised": "Library OPDS Feed - entries matching {{#LANG}}\nLanguage: {{LANG}} {{/LANG}}{{#CATEGORY}}\nCategory: {{CATEGORY}} {{/CATEGORY}}{{#TAG}}\nTag: {{TAG}} {{/TAG}}{{#Q}}\nQuery: {{Q}} {{/Q}}"
|
, "library-opds-feed-parameterised": "Library OPDS Feed - entries matching {{#LANG}}\nLanguage: {{LANG}} {{/LANG}}{{#CATEGORY}}\nCategory: {{CATEGORY}} {{/CATEGORY}}{{#TAG}}\nTag: {{TAG}} {{/TAG}}{{#Q}}\nQuery: {{Q}} {{/Q}}"
|
||||||
, "welcome-to-kiwix-server": "Welcome to Kiwix Server"
|
, "welcome-to-kiwix-server": "Welcome to Kiwix Server"
|
||||||
, "download-links-heading": "Download links for <b><i>{{BOOK_TITLE}}</i></b>"
|
, "download-links-heading": "Download links for <b><i>{{BOOK_TITLE}}</i></b>"
|
||||||
|
|
|
@ -105,6 +105,14 @@
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Borrowed from https://stackoverflow.com/a/1912522
|
||||||
|
function htmlDecode(input){
|
||||||
|
var e = document.createElement('textarea');
|
||||||
|
e.innerHTML = input;
|
||||||
|
// handle case of empty input
|
||||||
|
return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
|
||||||
|
}
|
||||||
|
|
||||||
function htmlEncode(str) {
|
function htmlEncode(str) {
|
||||||
return str.replace(/[\u00A0-\u9999<>\&]/gim, (i) => `&#${i.charCodeAt(0)};`);
|
return str.replace(/[\u00A0-\u9999<>\&]/gim, (i) => `&#${i.charCodeAt(0)};`);
|
||||||
}
|
}
|
||||||
|
@ -121,9 +129,14 @@
|
||||||
|
|
||||||
function generateTagLink(tagValue) {
|
function generateTagLink(tagValue) {
|
||||||
tagValue = tagValue.toLowerCase();
|
tagValue = tagValue.toLowerCase();
|
||||||
const htmlEncodedTagValue = htmlEncode(tagValue);
|
|
||||||
const tagMessage = $t("filter-by-tag", {TAG: tagValue});
|
const tagMessage = $t("filter-by-tag", {TAG: tagValue});
|
||||||
return `<span class='tag__link' aria-label='${tagMessage}' title='${tagMessage}' data-tag=${htmlEncodedTagValue}>${htmlEncodedTagValue}</span>`
|
const spanElement = document.createElement("span");
|
||||||
|
spanElement.className = 'tag__link';
|
||||||
|
spanElement.setAttribute('aria-label', tagMessage);
|
||||||
|
spanElement.setAttribute('title', tagMessage);
|
||||||
|
spanElement.setAttribute('data-tag', tagValue);
|
||||||
|
spanElement.innerHTML = htmlEncode(tagValue);
|
||||||
|
return spanElement.outerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateBookHtml(book, sort = false) {
|
function generateBookHtml(book, sort = false) {
|
||||||
|
@ -144,7 +157,7 @@
|
||||||
const mulLangList = langCodesList.filter(x => languages.hasOwnProperty(x)).map(x => languages[x]);
|
const mulLangList = langCodesList.filter(x => languages.hasOwnProperty(x)).map(x => languages[x]);
|
||||||
language = mulLangList.join(', ');
|
language = mulLangList.join(', ');
|
||||||
}
|
}
|
||||||
const tags = getInnerHtml(book, 'tags');
|
const tags = htmlDecode(getInnerHtml(book, 'tags'));
|
||||||
const tagList = tags.split(';').filter(tag => {return !(tag.startsWith('_'))});
|
const tagList = tags.split(';').filter(tag => {return !(tag.startsWith('_'))});
|
||||||
const tagFilterLinks = tagList.map((tagValue) => generateTagLink(tagValue));
|
const tagFilterLinks = tagList.map((tagValue) => generateTagLink(tagValue));
|
||||||
const tagHtml = tagFilterLinks.join(' | ');
|
const tagHtml = tagFilterLinks.join(' | ');
|
||||||
|
@ -492,7 +505,7 @@
|
||||||
function addTagElement(tagValue, resetFilter) {
|
function addTagElement(tagValue, resetFilter) {
|
||||||
const tagElement = document.getElementsByClassName('tagFilterLabel')[0];
|
const tagElement = document.getElementsByClassName('tagFilterLabel')[0];
|
||||||
tagElement.style.display = 'inline-block';
|
tagElement.style.display = 'inline-block';
|
||||||
tagElement.innerHTML = `${tagValue}`;
|
tagElement.innerHTML = htmlEncode(tagValue);
|
||||||
const tagMessage = $t("stop-filtering-by-tag", {TAG: tagValue});
|
const tagMessage = $t("stop-filtering-by-tag", {TAG: tagValue});
|
||||||
tagElement.setAttribute('aria-label', tagMessage);
|
tagElement.setAttribute('aria-label', tagMessage);
|
||||||
tagElement.setAttribute('title', tagMessage);
|
tagElement.setAttribute('title', tagMessage);
|
||||||
|
|
Loading…
Reference in New Issue