From 83d4565b227508e25bd1e93d2155d167be51dc74 Mon Sep 17 00:00:00 2001 From: Robert Krimen Date: Thu, 2 May 2013 20:23:06 +0200 Subject: [PATCH] Make decodeURI correspond to the 15.1.3.1 algorithm and decodeURIComponent ito 15.1.3.2 --- builtin.go | 31 +++++++++++++++++++++++++++---- global.go | 4 ++-- global_test.go | 12 ++++++++++++ 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/builtin.go b/builtin.go index 775ad52..999d122 100644 --- a/builtin.go +++ b/builtin.go @@ -177,12 +177,35 @@ func builtinGlobal_encodeURIComponent(call FunctionCall) Value { return _builtinGlobal_encodeURI(call, encodeURIComponent_Regexp) } -func builtinGlobal_decodeURI_decodeURIComponent(call FunctionCall) Value { - value, err := url.QueryUnescape(toString(call.Argument(0))) - if err != nil { +// 3B/2F/3F/3A/40/26/3D/2B/24/2C/23 +var decodeURI_guard = regexp.MustCompile(`(?i)(?:%)(3B|2F|3F|3A|40|26|3D|2B|24|2C|23)`) + +func _decodeURI(input string, reserve bool) (string, bool) { + if reserve { + input = decodeURI_guard.ReplaceAllString(input, "%25$1") + } + input = strings.Replace(input, "+", "%2B", -1) // Ugly hack to make QueryUnescape work with our use case + output, err := url.QueryUnescape(input) + if err != nil || !utf8.ValidString(output) { + return "", true + } + return output, false +} + +func builtinGlobal_decodeURI(call FunctionCall) Value { + output, err := _decodeURI(toString(call.Argument(0)), true) + if err { panic(newURIError("URI malformed")) } - return toValue(value) + return toValue(output) +} + +func builtinGlobal_decodeURIComponent(call FunctionCall) Value { + output, err := _decodeURI(toString(call.Argument(0)), false) + if err { + panic(newURIError("URI malformed")) + } + return toValue(output) } // escape/unescape diff --git a/global.go b/global.go index 8d6b0b8..dac5275 100644 --- a/global.go +++ b/global.go @@ -706,8 +706,8 @@ func newContext() *_runtime { "parseFloat", -1, builtinGlobal_parseFloat, "isNaN", -1, builtinGlobal_isNaN, "isFinite", -1, builtinGlobal_isFinite, - "decodeURI", builtinGlobal_decodeURI_decodeURIComponent, - "decodeURIComponent", builtinGlobal_decodeURI_decodeURIComponent, + "decodeURI", -1, builtinGlobal_decodeURI, + "decodeURIComponent", -1, builtinGlobal_decodeURIComponent, "encodeURI", builtinGlobal_encodeURI, "encodeURIComponent", builtinGlobal_encodeURIComponent, "escape", builtinGlobal_escape, diff --git a/global_test.go b/global_test.go index a97c8eb..4eb66ad 100644 --- a/global_test.go +++ b/global_test.go @@ -2,6 +2,8 @@ package otto import ( . "./terst" + "fmt" + "strings" "testing" ) @@ -190,6 +192,13 @@ func Test_decodeURI(t *testing.T) { test(`decodeURI(encodeURI("http://example.com/ Nothing happens."))`, "http://example.com/ Nothing happens.") test(`decodeURI(encodeURI("http://example.com/ _^#"))`, "http://example.com/ _^#") test(`raise: decodeURI("http://example.com/ _^#%")`, "URIError: URI malformed") + test(`raise: decodeURI("%DF%7F")`, "URIError: URI malformed") + for _, check := range strings.Fields("+ %3B %2F %3F %3A %40 %26 %3D %2B %24 %2C %23") { + test(fmt.Sprintf(`decodeURI("%s")`, check), check) + } + + test(`decodeURI.length === 1`, "true") + test(`decodeURI.prototype === undefined`, "true") } func Test_decodeURIComponent(t *testing.T) { @@ -198,6 +207,9 @@ func Test_decodeURIComponent(t *testing.T) { test := runTest() test(`decodeURIComponent(encodeURI("http://example.com/ Nothing happens."))`, "http://example.com/ Nothing happens.") test(`decodeURIComponent(encodeURI("http://example.com/ _^#"))`, "http://example.com/ _^#") + + test(`decodeURIComponent.length === 1`, "true") + test(`decodeURIComponent.prototype === undefined`, "true") } func TestGlobal_skipEnumeration(t *testing.T) {