mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-02-01 00:18:14 +01:00
Update custom metadata provider results to sanitize html descriptions #3880
This commit is contained in:
parent
e096da1b4d
commit
558173e086
@ -7,12 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const htmlparser = require('htmlparser2');
|
const htmlparser = require('htmlparser2');
|
||||||
// const escapeStringRegexp = require('escape-string-regexp');
|
|
||||||
// const { isPlainObject } = require('is-plain-object');
|
|
||||||
// const deepmerge = require('deepmerge');
|
|
||||||
// const parseSrcset = require('parse-srcset');
|
|
||||||
// const { parse: postcssParse } = require('postcss');
|
|
||||||
// Tags that can conceivably represent stand-alone media.
|
|
||||||
|
|
||||||
// ABS UPDATE: Packages not necessary
|
// ABS UPDATE: Packages not necessary
|
||||||
// SOURCE: https://github.com/sindresorhus/escape-string-regexp/blob/main/index.js
|
// SOURCE: https://github.com/sindresorhus/escape-string-regexp/blob/main/index.js
|
||||||
@ -76,17 +70,6 @@ function has(obj, key) {
|
|||||||
return ({}).hasOwnProperty.call(obj, key);
|
return ({}).hasOwnProperty.call(obj, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns those elements of `a` for which `cb(a)` returns truthy
|
|
||||||
function filter(a, cb) {
|
|
||||||
const n = [];
|
|
||||||
each(a, function (v) {
|
|
||||||
if (cb(v)) {
|
|
||||||
n.push(v);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isEmptyObject(obj) {
|
function isEmptyObject(obj) {
|
||||||
for (const key in obj) {
|
for (const key in obj) {
|
||||||
if (has(obj, key)) {
|
if (has(obj, key)) {
|
||||||
@ -96,21 +79,6 @@ function isEmptyObject(obj) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function stringifySrcset(parsedSrcset) {
|
|
||||||
return parsedSrcset.map(function (part) {
|
|
||||||
if (!part.url) {
|
|
||||||
throw new Error('URL missing');
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
part.url +
|
|
||||||
(part.w ? ` ${part.w}w` : '') +
|
|
||||||
(part.h ? ` ${part.h}h` : '') +
|
|
||||||
(part.d ? ` ${part.d}x` : '')
|
|
||||||
);
|
|
||||||
}).join(', ');
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = sanitizeHtml;
|
module.exports = sanitizeHtml;
|
||||||
|
|
||||||
// A valid attribute name.
|
// A valid attribute name.
|
||||||
@ -714,86 +682,6 @@ function sanitizeHtml(html, options, _recursing) {
|
|||||||
return !options.allowedSchemes || options.allowedSchemes.indexOf(scheme) === -1;
|
return !options.allowedSchemes || options.allowedSchemes.indexOf(scheme) === -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Filters user input css properties by allowlisted regex attributes.
|
|
||||||
* Modifies the abstractSyntaxTree object.
|
|
||||||
*
|
|
||||||
* @param {object} abstractSyntaxTree - Object representation of CSS attributes.
|
|
||||||
* @property {array[Declaration]} abstractSyntaxTree.nodes[0] - Each object cointains prop and value key, i.e { prop: 'color', value: 'red' }.
|
|
||||||
* @param {object} allowedStyles - Keys are properties (i.e color), value is list of permitted regex rules (i.e /green/i).
|
|
||||||
* @return {object} - The modified tree.
|
|
||||||
*/
|
|
||||||
// function filterCss(abstractSyntaxTree, allowedStyles) {
|
|
||||||
// if (!allowedStyles) {
|
|
||||||
// return abstractSyntaxTree;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const astRules = abstractSyntaxTree.nodes[0];
|
|
||||||
// let selectedRule;
|
|
||||||
|
|
||||||
// // Merge global and tag-specific styles into new AST.
|
|
||||||
// if (allowedStyles[astRules.selector] && allowedStyles['*']) {
|
|
||||||
// selectedRule = deepmerge(
|
|
||||||
// allowedStyles[astRules.selector],
|
|
||||||
// allowedStyles['*']
|
|
||||||
// );
|
|
||||||
// } else {
|
|
||||||
// selectedRule = allowedStyles[astRules.selector] || allowedStyles['*'];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (selectedRule) {
|
|
||||||
// abstractSyntaxTree.nodes[0].nodes = astRules.nodes.reduce(filterDeclarations(selectedRule), []);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return abstractSyntaxTree;
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts the style attributes from an AbstractSyntaxTree and formats those
|
|
||||||
* values in the inline style attribute format.
|
|
||||||
*
|
|
||||||
* @param {AbstractSyntaxTree} filteredAST
|
|
||||||
* @return {string} - Example: "color:yellow;text-align:center !important;font-family:helvetica;"
|
|
||||||
*/
|
|
||||||
function stringifyStyleAttributes(filteredAST) {
|
|
||||||
return filteredAST.nodes[0].nodes
|
|
||||||
.reduce(function (extractedAttributes, attrObject) {
|
|
||||||
extractedAttributes.push(
|
|
||||||
`${attrObject.prop}:${attrObject.value}${attrObject.important ? ' !important' : ''}`
|
|
||||||
);
|
|
||||||
return extractedAttributes;
|
|
||||||
}, [])
|
|
||||||
.join(';');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filters the existing attributes for the given property. Discards any attributes
|
|
||||||
* which don't match the allowlist.
|
|
||||||
*
|
|
||||||
* @param {object} selectedRule - Example: { color: red, font-family: helvetica }
|
|
||||||
* @param {array} allowedDeclarationsList - List of declarations which pass the allowlist.
|
|
||||||
* @param {object} attributeObject - Object representing the current css property.
|
|
||||||
* @property {string} attributeObject.type - Typically 'declaration'.
|
|
||||||
* @property {string} attributeObject.prop - The CSS property, i.e 'color'.
|
|
||||||
* @property {string} attributeObject.value - The corresponding value to the css property, i.e 'red'.
|
|
||||||
* @return {function} - When used in Array.reduce, will return an array of Declaration objects
|
|
||||||
*/
|
|
||||||
function filterDeclarations(selectedRule) {
|
|
||||||
return function (allowedDeclarationsList, attributeObject) {
|
|
||||||
// If this property is allowlisted...
|
|
||||||
if (has(selectedRule, attributeObject.prop)) {
|
|
||||||
const matchesRegex = selectedRule[attributeObject.prop].some(function (regularExpression) {
|
|
||||||
return regularExpression.test(attributeObject.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (matchesRegex) {
|
|
||||||
allowedDeclarationsList.push(attributeObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return allowedDeclarationsList;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function filterClasses(classes, allowed, allowedGlobs) {
|
function filterClasses(classes, allowed, allowedGlobs) {
|
||||||
if (!allowed) {
|
if (!allowed) {
|
||||||
// The class attribute is allowed without filtering on this tag
|
// The class attribute is allowed without filtering on this tag
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
const axios = require('axios').default
|
const axios = require('axios').default
|
||||||
const Database = require('../Database')
|
const Database = require('../Database')
|
||||||
const Logger = require('../Logger')
|
const Logger = require('../Logger')
|
||||||
|
const htmlSanitizer = require('../utils/htmlSanitizer')
|
||||||
|
|
||||||
class CustomProviderAdapter {
|
class CustomProviderAdapter {
|
||||||
#responseTimeout = 30000
|
#responseTimeout = 30000
|
||||||
@ -74,7 +75,7 @@ class CustomProviderAdapter {
|
|||||||
narrator,
|
narrator,
|
||||||
publisher,
|
publisher,
|
||||||
publishedYear,
|
publishedYear,
|
||||||
description,
|
description: htmlSanitizer.sanitize(description),
|
||||||
cover,
|
cover,
|
||||||
isbn,
|
isbn,
|
||||||
asin,
|
asin,
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
const sanitizeHtml = require('../libs/sanitizeHtml')
|
const sanitizeHtml = require('../libs/sanitizeHtml')
|
||||||
const { entities } = require('./htmlEntities')
|
const { entities } = require('./htmlEntities')
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} html
|
||||||
|
* @returns {string}
|
||||||
|
* @throws {Error} if input is not a string
|
||||||
|
*/
|
||||||
function sanitize(html) {
|
function sanitize(html) {
|
||||||
|
if (typeof html !== 'string') {
|
||||||
|
throw new Error('sanitizeHtml: input must be a string')
|
||||||
|
}
|
||||||
|
|
||||||
const sanitizerOptions = {
|
const sanitizerOptions = {
|
||||||
allowedTags: ['p', 'ol', 'ul', 'li', 'a', 'strong', 'em', 'del', 'br', 'b', 'i'],
|
allowedTags: ['p', 'ol', 'ul', 'li', 'a', 'strong', 'em', 'del', 'br', 'b', 'i'],
|
||||||
disallowedTagsMode: 'discard',
|
disallowedTagsMode: 'discard',
|
||||||
|
Loading…
Reference in New Issue
Block a user