1tohex(c: int): int 2{ 3 if(c > 9) 4 return c-10+'A'; 5 return c+'0'; 6} 7 8fromhex(ex: ref Exec, c1: int, c2: int): int 9{ 10 c1 = hexdigit(c1); 11 c2 = hexdigit(c2); 12 if(c1 < 0 || c2 < 0) 13 runtime(ex, URIError, "bad hex digit"); 14 return 16*c1+c2; 15} 16 17isres(c: int): int 18{ 19 return c == ';' || c == '/' || c == '?' || c == ':' || c == '@' || c == '&' || c == '=' || c == '+' || c == '$' || c == ',' || c == '#'; # add '#' here for convenience 20} 21 22isunesc(c: int): int 23{ 24 return isalpha(c) || isdigit(c) || c == '-' || c == '_' || c == '.' || c == '!' || c == '~' || c == '*' || c == ''' || c == '(' || c == ')'; 25} 26 27encode(ex: ref Exec, s: string, flag: int): string 28{ 29 m := len s; 30 r := ""; 31 n := len r; 32 for(k := 0; k < m; k++){ 33 c := s[k]; 34 if(isunesc(c) || (flag && isres(c))) 35 r[n++] = c; 36 else{ 37 if(c >= 16rdc00 && c <= 16rdfff) 38 runtime(ex, URIError, "char out of range"); 39 if(c < 16rd800 || c > 16rdbff) 40 ; 41 else{ 42 if(++k == m) 43 runtime(ex, URIError, "char missing"); 44 if(s[k] < 16rdc00 || s[k] > 16rdfff) 45 runtime(ex, URIError, "char out of range"); 46 c = (c-16rd800)*16r400 + (s[k]-16rdc00) + 16r10000; 47 } 48 s1 := "Z"; 49 s1[0] = c; 50 o := array of byte s1; 51 for(j := 0; j < len o; j++){ 52 r += sys->sprint("%%%c%c", tohex(int o[j]/16), tohex(int o[j]%16)); 53 n += 3; 54 } 55 } 56 } 57 return r; 58} 59 60decode(ex: ref Exec, s: string, flag: int): string 61{ 62 m := len s; 63 r := ""; 64 n := len r; 65 for(k := 0; k < m; k++){ 66 c := s[k]; 67 if(c != '%') 68 r[n++] = c; 69 else{ 70 start := k; 71 if(k+2 >= m) 72 runtime(ex, URIError, "char missing"); 73 c = fromhex(ex, s[k+1], s[k+2]); 74 k += 2; 75 if((c&16r80 == 0)){ 76 if(flag && isres(c)){ 77 r += s[start: k+1]; 78 n += k+1-start; 79 } 80 else 81 r[n++] = c; 82 } 83 else{ 84 for(i := 1; ((c<<i)&16r80) == 0; i++) 85 ; 86 if(i == 1 || i > 4) 87 runtime(ex, URIError, "bad hex number"); 88 o := array[i] of byte; 89 o[0] = byte c; 90 if(k+3*(n-1) >= m) 91 runtime(ex, URIError, "char missing"); 92 for(j := 1; j < i; j++){ 93 if(s[++k] != '%') 94 runtime(ex, URIError, "% missing"); 95 c = fromhex(ex, s[k+1], s[k+2]); 96 k += 2; 97 if((c&16rc0) != 2) 98 runtime(ex, URIError, "bad hex number"); 99 o[j] = byte c; 100 } 101 (c, nil, nil) = sys->byte2char(o, 0); 102 if(c < 16r10000){ 103 if(flag && isres(c)){ 104 r += s[start: k+1]; 105 n += k+1-start; 106 } 107 else 108 r[n++] = c; 109 } 110 else if(c > 16r10ffff) 111 runtime(ex, URIError, "bad byte sequence"); 112 else{ 113 r[n++] = ((c-16r10000)&16r3ff)+16rdc00; 114 r[n++] = (((c-16r10000)>>10)&16r3ff)+16rd800; 115 } 116 } 117 } 118 } 119 return r; 120} 121 122cdecodeuri(ex: ref Exec, nil, nil: ref Ecmascript->Obj, args: array of ref Val): ref Val 123{ 124 return strval(decode(ex, toString(ex, biarg(args, 0)), 1)); 125} 126 127cdecodeuric(ex: ref Exec, nil, nil: ref Ecmascript->Obj, args: array of ref Val): ref Val 128{ 129 return strval(decode(ex, toString(ex, biarg(args, 0)), 0)); 130} 131 132cencodeuri(ex: ref Exec, nil, nil: ref Ecmascript->Obj, args: array of ref Val): ref Val 133{ 134 return strval(encode(ex, toString(ex, biarg(args, 0)), 1)); 135} 136 137cencodeuric(ex: ref Exec, nil, nil: ref Ecmascript->Obj, args: array of ref Val): ref Val 138{ 139 return strval(encode(ex, toString(ex, biarg(args, 0)), 0)); 140} 141