diff options
Diffstat (limited to 'appl/lib/ecmascript/uri.b')
| -rw-r--r-- | appl/lib/ecmascript/uri.b | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/appl/lib/ecmascript/uri.b b/appl/lib/ecmascript/uri.b new file mode 100644 index 00000000..b571f286 --- /dev/null +++ b/appl/lib/ecmascript/uri.b @@ -0,0 +1,140 @@ +tohex(c: int): int +{ + if(c > 9) + return c-10+'A'; + return c+'0'; +} + +fromhex(ex: ref Exec, c1: int, c2: int): int +{ + c1 = hexdigit(c1); + c2 = hexdigit(c2); + if(c1 < 0 || c2 < 0) + runtime(ex, URIError, "bad hex digit"); + return 16*c1+c2; +} + +isres(c: int): int +{ + return c == ';' || c == '/' || c == '?' || c == ':' || c == '@' || c == '&' || c == '=' || c == '+' || c == '$' || c == ',' || c == '#'; # add '#' here for convenience +} + +isunesc(c: int): int +{ + return isalpha(c) || isdigit(c) || c == '-' || c == '_' || c == '.' || c == '!' || c == '~' || c == '*' || c == ''' || c == '(' || c == ')'; +} + +encode(ex: ref Exec, s: string, flag: int): string +{ + m := len s; + r := ""; + n := len r; + for(k := 0; k < m; k++){ + c := s[k]; + if(isunesc(c) || (flag && isres(c))) + r[n++] = c; + else{ + if(c >= 16rdc00 && c <= 16rdfff) + runtime(ex, URIError, "char out of range"); + if(c < 16rd800 || c > 16rdbff) + ; + else{ + if(++k == m) + runtime(ex, URIError, "char missing"); + if(s[k] < 16rdc00 || s[k] > 16rdfff) + runtime(ex, URIError, "char out of range"); + c = (c-16rd800)*16r400 + (s[k]-16rdc00) + 16r10000; + } + s1 := "Z"; + s1[0] = c; + o := array of byte s1; + for(j := 0; j < len o; j++){ + r += sys->sprint("%%%c%c", tohex(int o[j]/16), tohex(int o[j]%16)); + n += 3; + } + } + } + return r; +} + +decode(ex: ref Exec, s: string, flag: int): string +{ + m := len s; + r := ""; + n := len r; + for(k := 0; k < m; k++){ + c := s[k]; + if(c != '%') + r[n++] = c; + else{ + start := k; + if(k+2 >= m) + runtime(ex, URIError, "char missing"); + c = fromhex(ex, s[k+1], s[k+2]); + k += 2; + if((c&16r80 == 0)){ + if(flag && isres(c)){ + r += s[start: k+1]; + n += k+1-start; + } + else + r[n++] = c; + } + else{ + for(i := 1; ((c<<i)&16r80) == 0; i++) + ; + if(i == 1 || i > 4) + runtime(ex, URIError, "bad hex number"); + o := array[i] of byte; + o[0] = byte c; + if(k+3*(n-1) >= m) + runtime(ex, URIError, "char missing"); + for(j := 1; j < i; j++){ + if(s[++k] != '%') + runtime(ex, URIError, "% missing"); + c = fromhex(ex, s[k+1], s[k+2]); + k += 2; + if((c&16rc0) != 2) + runtime(ex, URIError, "bad hex number"); + o[j] = byte c; + } + (c, nil, nil) = sys->byte2char(o, 0); + if(c < 16r10000){ + if(flag && isres(c)){ + r += s[start: k+1]; + n += k+1-start; + } + else + r[n++] = c; + } + else if(c > 16r10ffff) + runtime(ex, URIError, "bad byte sequence"); + else{ + r[n++] = ((c-16r10000)&16r3ff)+16rdc00; + r[n++] = (((c-16r10000)>>10)&16r3ff)+16rd800; + } + } + } + } + return r; +} + +cdecodeuri(ex: ref Exec, nil, nil: ref Ecmascript->Obj, args: array of ref Val): ref Val +{ + return strval(decode(ex, toString(ex, biarg(args, 0)), 1)); +} + +cdecodeuric(ex: ref Exec, nil, nil: ref Ecmascript->Obj, args: array of ref Val): ref Val +{ + return strval(decode(ex, toString(ex, biarg(args, 0)), 0)); +} + +cencodeuri(ex: ref Exec, nil, nil: ref Ecmascript->Obj, args: array of ref Val): ref Val +{ + return strval(encode(ex, toString(ex, biarg(args, 0)), 1)); +} + +cencodeuric(ex: ref Exec, nil, nil: ref Ecmascript->Obj, args: array of ref Val): ref Val +{ + return strval(encode(ex, toString(ex, biarg(args, 0)), 0)); +} |
