xref: /inferno-os/appl/lib/ecmascript/uri.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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