Index: include.postload.js |
=================================================================== |
--- a/include.postload.js |
+++ b/include.postload.js |
@@ -24,9 +24,28 @@ |
var clickHideFiltersDialog = null; |
var lastRightClickEvent = null; |
+function escapeChar(chr, pos, s) { |
+ var code = chr.charCodeAt(0); |
+ |
+ // non-ascii, needs no escaping |
+ if (code >= 128) |
Sebastian Noack
2014/11/05 18:09:04
I just realized that I can easily check in the reg
|
+ return chr; |
+ |
+ // control characters and numbers, must be escaped based on their code point |
+ if ((code >= 0 && code <= 31) || (code >= 48 && code <= 57) || code == 127) |
Wladimir Palant
2014/11/05 15:14:41
How about:
if (code <= 0x1F || /\d/.test(chr) |
Sebastian Noack
2014/11/05 18:09:04
I already considered using that regex to check for
|
+ return "\\" + code.toString(16) + (pos + 1 < s.length ? " " : ""); |
Wladimir Palant
2014/11/05 15:14:41
Why create a special case for end of string? That
Sebastian Noack
2014/11/05 18:09:04
I find the extra space in the end confusing. It ca
|
+ |
+ // others, can be escaped by prepending a backslash |
+ return "\\" + chr; |
+} |
+ |
function quote(value) |
{ |
- return '"' + value.replace(/(["\\])/g, "\\$1") + '"'; |
+ return '"' + value.replace(/["\\\r\n\f\0]/g, escapeChar) + '"'; |
Wladimir Palant
2014/11/05 15:14:41
How about generally escaping all non-printable cha
Sebastian Noack
2014/11/05 18:09:04
Yeah, un-escaped control characters make quoted st
|
+} |
+ |
+function escapeToken(s) { |
+ return s.replace(/^\d|^-(?![^\d-])|[^\w-]/g, escapeChar); |
Wladimir Palant
2014/11/05 15:14:41
How about always escaping leading dashes? These ar
Sebastian Noack
2014/11/05 18:09:04
I'd prefer to keep the logic for escaping dashes.
Wladimir Palant
2014/11/05 19:56:52
I'll leave the decision on whether that branch in
|
} |
function supportsShadowRoot(element) |
@@ -376,10 +395,6 @@ |
else if (elt.src) |
url = elt.src; |
- // Construct filters. The popup will retrieve these. |
- // Only one ID |
- var elementId = elt.id ? elt.id.split(' ').join('') : null; |
- |
clickHideFilters = new Array(); |
selectorList = new Array(); |
@@ -389,15 +404,15 @@ |
selectorList.push(selector); |
}; |
- if (elementId) |
- addSelector("#" + elementId); |
+ if (elt.id) |
+ addSelector("#" + escapeToken(elt.id)); |
if (elt.classList.length > 0) |
{ |
var selector = ""; |
for (var i = 0; i < elt.classList.length; i++) |
- selector += "." + elt.classList[i].replace(/([^\w-])/g, "\\$1"); |
+ selector += "." + escapeToken(elt.classList[i]); |
addSelector(selector); |
} |
@@ -405,7 +420,7 @@ |
if (url) |
{ |
var src = elt.getAttribute("src"); |
- var selector = src && elt.localName + '[src=' + quote(src) + ']'; |
+ var selector = src && escapeToken(elt.localName) + '[src=' + quote(src) + ']'; |
if (/^https?:/i.test(url)) |
{ |
@@ -427,7 +442,7 @@ |
{ |
var style = elt.getAttribute("style"); |
if (style) |
- addSelector(elt.localName + '[style=' + quote(style) + ']'); |
+ addSelector(escapeToken(elt.localName) + '[style=' + quote(style) + ']'); |
} |
// Show popup |