From 67af45be7dec29fec89b959f39aba3108637f851 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Tue, 7 Oct 2008 12:02:39 -0500 Subject: [PATCH] jscript: Added encodeURI implementation. --- dlls/jscript/global.c | 107 +++++++++++++++++++++++++++++++++++++- dlls/jscript/tests/api.js | 21 ++++++++ 2 files changed, 127 insertions(+), 1 deletion(-) diff --git a/dlls/jscript/global.c b/dlls/jscript/global.c index 01d92dde71b..432bf00436f 100644 --- a/dlls/jscript/global.c +++ b/dlls/jscript/global.c @@ -53,6 +53,40 @@ static const WCHAR ScriptEngineBuildVersionW[] = {'S','c','r','i','p','t','E','n','g','i','n','e','B','u','i','l','d','V','e','r','s','i','o','n',0}; static const WCHAR CollectGarbageW[] = {'C','o','l','l','e','c','t','G','a','r','b','a','g','e',0}; static const WCHAR MathW[] = {'M','a','t','h',0}; +static const WCHAR encodeURIW[] = {'e','n','c','o','d','e','U','R','I',0}; + +static const WCHAR undefinedW[] = {'u','n','d','e','f','i','n','e','d',0}; + +static int uri_char_table[] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 00-0f */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 10-1f */ + 0,2,0,0,1,0,1,2,2,2,2,1,1,2,2,1, /* 20-2f */ + 2,2,2,2,2,2,2,2,2,2,1,1,0,1,0,1, /* 30-3f */ + 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 40-4f */ + 2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2, /* 50-5f */ + 0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 60-6f */ + 2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,0, /* 70-7f */ +}; + +/* 1 - reserved */ +/* 2 - unescaped */ + +static inline BOOL is_uri_reserved(WCHAR c) +{ + return c < 128 && uri_char_table[c] == 1; +} + +static inline BOOL is_uri_unescaped(WCHAR c) +{ + return c < 128 && uri_char_table[c] == 2; +} + +static WCHAR int_to_char(int i) +{ + if(i < 10) + return '0'+i; + return 'A'+i-10; +} static HRESULT constructor_call(DispatchEx *constr, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) @@ -205,7 +239,7 @@ static HRESULT JSGlobal_eval(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARA TRACE("parsing %s\n", debugstr_w(V_BSTR(arg))); hres = script_parse(dispex->ctx, V_BSTR(arg), &parser_ctx); if(FAILED(hres)) { - FIXME("parse failed: %08x\n", hres); + WARN("parse (%s) failed: %08x\n", debugstr_w(V_BSTR(arg)), hres); return hres; } @@ -364,6 +398,76 @@ static HRESULT JSGlobal_CollectGarbage(DispatchEx *dispex, LCID lcid, WORD flags return E_NOTIMPL; } +static HRESULT JSGlobal_encodeURI(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, + VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) +{ + const WCHAR *ptr; + DWORD len = 0, i; + char buf[4]; + BSTR str, ret; + WCHAR *rptr; + HRESULT hres; + + TRACE("\n"); + + if(!arg_cnt(dp)) { + if(retv) { + ret = SysAllocString(undefinedW); + if(!ret) + return E_OUTOFMEMORY; + + V_VT(retv) = VT_BSTR; + V_BSTR(retv) = ret; + } + + return S_OK; + } + + hres = to_string(dispex->ctx, get_arg(dp,0), ei, &str); + if(FAILED(hres)) + return hres; + + for(ptr = str; *ptr; ptr++) { + if(is_uri_unescaped(*ptr) || is_uri_reserved(*ptr) || *ptr == '#') { + len++; + }else { + i = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, NULL, 0, NULL, NULL)*3; + if(!i) { + FIXME("throw URIError\n"); + return E_FAIL; + } + + len += i; + } + } + + rptr = ret = SysAllocStringLen(NULL, len); + if(!ret) + return E_OUTOFMEMORY; + + for(ptr = str; *ptr; ptr++) { + if(is_uri_unescaped(*ptr) || is_uri_reserved(*ptr) || *ptr == '#') { + *rptr++ = *ptr; + }else { + len = WideCharToMultiByte(CP_UTF8, 0, ptr, 1, buf, sizeof(buf), NULL, NULL); + for(i=0; i> 4); + *rptr++ = int_to_char(buf[i] & 0x0f); + } + } + } + + TRACE("%s -> %s\n", debugstr_w(str), debugstr_w(ret)); + if(retv) { + V_VT(retv) = VT_BSTR; + V_BSTR(retv) = ret; + }else { + SysFreeString(ret); + } + return S_OK; +} + static const builtin_prop_t JSGlobal_props[] = { {ActiveXObjectW, JSGlobal_ActiveXObject, PROPF_METHOD}, {ArrayW, JSGlobal_Array, PROPF_CONSTR}, @@ -385,6 +489,7 @@ static const builtin_prop_t JSGlobal_props[] = { {ScriptEngineMinorVersionW, JSGlobal_ScriptEngineMinorVersion, PROPF_METHOD}, {StringW, JSGlobal_String, PROPF_CONSTR}, {VBArrayW, JSGlobal_VBArray, PROPF_METHOD}, + {encodeURIW, JSGlobal_encodeURI, PROPF_METHOD}, {escapeW, JSGlobal_escape, PROPF_METHOD}, {evalW, JSGlobal_eval, PROPF_METHOD|1}, {isFiniteW, JSGlobal_isFinite, PROPF_METHOD}, diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js index b421ceba264..35433576cd6 100644 --- a/dlls/jscript/tests/api.js +++ b/dlls/jscript/tests/api.js @@ -37,6 +37,27 @@ ok(i === 123, "parseInt('123', 10, 'test') = " + i); i = parseInt("11", "8"); ok(i === 9, "parseInt('11', '8') = " + i); +tmp = encodeURI("abc"); +ok(tmp === "abc", "encodeURI('abc') = " + tmp); +tmp = encodeURI("{abc}"); +ok(tmp === "%7Babc%7D", "encodeURI('{abc}') = " + tmp); +tmp = encodeURI(""); +ok(tmp === "", "encodeURI('') = " + tmp); +tmp = encodeURI("\01\02\03\04"); +ok(tmp === "%01%02%03%04", "encodeURI('\\01\\02\\03\\04') = " + tmp); +tmp = encodeURI("{#@}"); +ok(tmp === "%7B#@%7D", "encodeURI('{#@}') = " + tmp); +tmp = encodeURI("\xa1 "); +ok(tmp === "%C2%A1%20", "encodeURI(\\xa1 ) = " + tmp); +tmp = encodeURI("\xffff"); +ok(tmp.length === 8, "encodeURI('\\xffff').length = " + tmp.length); +tmp = encodeURI("abcABC123;/?:@&=+$,-_.!~*'()"); +ok(tmp === "abcABC123;/?:@&=+$,-_.!~*'()", "encodeURI('abcABC123;/?:@&=+$,-_.!~*'()') = " + tmp); +tmp = encodeURI(); +ok(tmp === "undefined", "encodeURI() = " + tmp); +tmp = encodeURI("abc", "test"); +ok(tmp === "abc", "encodeURI('abc') = " + tmp); + tmp = "" + new Object(); ok(tmp === "[object Object]", "'' + new Object() = " + tmp);