diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index ec064e2dd..93dcadfc1 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -1914,6 +1914,7 @@ "core.openmodinbrowser": "Open {{$a}} in browser", "core.othergroups": "Other groups", "core.pagea": "Page {{$a}}", + "core.parentlanguage": "", "core.paymentinstant": "Use the button below to pay and be enrolled within minutes!", "core.percentagenumber": "{{$a}}%", "core.phone": "Phone", diff --git a/src/core/h5p/classes/content-validator.ts b/src/core/h5p/classes/content-validator.ts index e00f53dc4..d265cfaa8 100644 --- a/src/core/h5p/classes/content-validator.ts +++ b/src/core/h5p/classes/content-validator.ts @@ -162,7 +162,7 @@ export class CoreH5PContentValidator { text = this.filterXss(text, tags, stylePatterns); } else { // Filter text to plain text. - text = CoreTextUtils.instance.escapeHTML(text); + text = CoreTextUtils.instance.escapeHTML(text, false); } // Check if string is within allowed length. @@ -267,7 +267,7 @@ export class CoreH5PContentValidator { if (strict && !optional && !options[value]) { delete select[key]; } else { - select[key] = CoreTextUtils.instance.escapeHTML(value); + select[key] = CoreTextUtils.instance.escapeHTML(value, false); } } } else { @@ -279,7 +279,7 @@ export class CoreH5PContentValidator { if (strict && !optional && !options[select]) { select = semantics.options[0].value; } - select = CoreTextUtils.instance.escapeHTML(select); + select = CoreTextUtils.instance.escapeHTML(select, false); } return select; @@ -353,9 +353,9 @@ export class CoreH5PContentValidator { } // Make sure path and mime does not have any special chars - file.path = CoreTextUtils.instance.escapeHTML(file.path); + file.path = CoreTextUtils.instance.escapeHTML(file.path, false); if (file.mime) { - file.mime = CoreTextUtils.instance.escapeHTML(file.mime); + file.mime = CoreTextUtils.instance.escapeHTML(file.mime, false); } // Remove attributes that should not exist, they may contain JSON escape code. @@ -376,7 +376,7 @@ export class CoreH5PContentValidator { } if (file.codecs) { - file.codecs = CoreTextUtils.instance.escapeHTML(file.codecs); + file.codecs = CoreTextUtils.instance.escapeHTML(file.codecs, false); } if (typeof file.bitrate != 'undefined') { @@ -389,7 +389,7 @@ export class CoreH5PContentValidator { } else { this.filterParams(file.quality, ['level', 'label']); file.quality.level = parseInt(file.quality.level); - file.quality.label = CoreTextUtils.instance.escapeHTML(file.quality.label); + file.quality.label = CoreTextUtils.instance.escapeHTML(file.quality.label, false); } } @@ -840,7 +840,7 @@ export class CoreH5PContentValidator { str = CoreTextUtils.instance.decodeHTMLEntities(str); } - return CoreTextUtils.instance.escapeHTML(this.stripDangerousProtocols(str)); + return CoreTextUtils.instance.escapeHTML(this.stripDangerousProtocols(str), false); } /** diff --git a/src/directives/format-text.ts b/src/directives/format-text.ts index 996fab7bf..c4fb3b74b 100644 --- a/src/directives/format-text.ts +++ b/src/directives/format-text.ts @@ -213,7 +213,7 @@ export class CoreFormatTextDirective implements OnChanges { } const imgSrc = this.textUtils.escapeHTML(img.getAttribute('data-original-src') || img.getAttribute('src')), - label = this.textUtils.escapeHTML(this.translate.instant('core.openfullimage')), + label = this.translate.instant('core.openfullimage'), anchor = document.createElement('a'); anchor.classList.add('core-image-viewer-icon'); diff --git a/src/providers/utils/dom.ts b/src/providers/utils/dom.ts index b88c0aec9..cdc652f3e 100644 --- a/src/providers/utils/dom.ts +++ b/src/providers/utils/dom.ts @@ -658,10 +658,11 @@ export class CoreDomUtilsProvider { if (this.debugDisplay) { // Get the debug info. Escape the HTML so it is displayed as it is in the view. if (error.debuginfo) { - extraInfo = '

' + this.textUtils.escapeHTML(error.debuginfo); + extraInfo = '

' + this.textUtils.escapeHTML(error.debuginfo, false); } if (error.backtrace) { - extraInfo += '

' + this.textUtils.replaceNewLines(this.textUtils.escapeHTML(error.backtrace), '
'); + extraInfo += '

' + this.textUtils.replaceNewLines( + this.textUtils.escapeHTML(error.backtrace, false), '
'); } // tslint:disable-next-line diff --git a/src/providers/utils/text.ts b/src/providers/utils/text.ts index 9cb111747..9d005530f 100644 --- a/src/providers/utils/text.ts +++ b/src/providers/utils/text.ts @@ -413,17 +413,23 @@ export class CoreTextUtilsProvider { * Escape an HTML text. This implementation is based on PHP's htmlspecialchars. * * @param text Text to escape. + * @param doubleEncode If false, it will not convert existing html entities. Defaults to true. * @return Escaped text. */ - escapeHTML(text: string | number): string { + escapeHTML(text: string | number, doubleEncode: boolean = true): string { if (typeof text == 'undefined' || text === null || (typeof text == 'number' && isNaN(text))) { return ''; } else if (typeof text != 'string') { return '' + text; } + if (doubleEncode) { + text = text.replace(/&/g, '&'); + } else { + text = text.replace(/&(?!amp;)(?!lt;)(?!gt;)(?!quot;)(?!#039;)/g, '&'); + } + return text - .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"')