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, '"')