From 7693079b8cf3ba8f66ee3449c0611ff751ce41eb Mon Sep 17 00:00:00 2001 From: rlx <0x0073@0x2620.org> Date: Mon, 26 Aug 2013 23:18:05 +0000 Subject: [PATCH] Ox.decodeURI/Ox.decodeURIComponent: replace all '%' with '%25' that are not part of valid UTF8 sequence (fixes #1841) --- source/Ox/js/String.js | 55 ++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/source/Ox/js/String.js b/source/Ox/js/String.js index ca062373..cdb9c92e 100644 --- a/source/Ox/js/String.js +++ b/source/Ox/js/String.js @@ -24,23 +24,46 @@ Ox.clean = function(string) { })).join('\n'); }; -/*@ -Ox.decodeURIComponent Decodes URI - Unlike window.decodeURI, this doesn't throw on trailing '%'. - (string) -> Decoded string -@*/ -Ox.decodeURI = function(string) { - return decodeURIComponent(string.replace(/%(?![0-9A-F]{2})/g, '%25')); -}; +(function() { -/*@ -Ox.decodeURIComponent Decodes URI component - Unlike window.decodeURIComponent, this doesn't throw on trailing '%'. - (string) -> Decoded string -@*/ -Ox.decodeURIComponent = function(string) { - return decodeURIComponent(string.replace(/%(?![0-9A-F]{2})/g, '%25')); -}; + function replace(string) { + return string.replace(/%(?![0-9A-Fa-f]{2})/g, '%25') + .replace(/(%[0-9A-Fa-f]{2})+/g, function(match) { + var hex = match.split('%').slice(1), ret; + Ox.forEach(Ox.range(1, hex.length + 1), function(length) { + var string = Ox.range(length).map(function(i) { + return Ox.char(parseInt(hex[i], 16)); + }).join(''); + try { + Ox.decodeUTF8(string); + ret = match.slice(0, length * 3) + + match.slice(length * 3).replace(/%/g, '%25'); + return false; + } catch(e) {} + }); + return ret || '%25' + hex[0] + replace(match.slice(3)); + }); + } + + /*@ + Ox.decodeURI Decodes URI + Unlike window.decodeURI, this doesn't throw on trailing '%'. + (string) -> Decoded string + @*/ + Ox.decodeURI = function(string) { + return decodeURI(replace(string)); + }; + + /*@ + Ox.decodeURIComponent Decodes URI component + Unlike window.decodeURIComponent, this doesn't throw on trailing '%'. + (string) -> Decoded string + @*/ + Ox.decodeURIComponent = function(string) { + return decodeURIComponent(replace(string)); + }; + +}()); /*@ Ox.endsWith Tests if a string ends with a given substring