1
  
2
  
3
  
4
  
5
  
6
  
7
  
8
  
9
  
10
  
11
  
12
  
13
  
14
  
15
  
16
  
17
  
18
  
19
  
20
  
21
  
22
  
23
  
24
  
25
  
26
  
27
  
28
  
29
  
30
  
31
  
32
  
33
  
34
  
35
  
36
  
37
  
38
  
39
  
40
  
41
  
42
  
43
  
44
  
45
  
46
  
47
  
48
  
49
  
50
  
51
  
52
  
53
  
54
  
55
  
56
  
57
  
58
  
59
  
60
  
61
  
62
  
63
  
64
  
65
  
66
  
67
  
68
  
69
  
70
  
71
  
72
  
73
  
74
  
75
  
76
  
77
  
78
  
79
  
START_MARKER 
 
test_eq(_Roxen.html_encode_string (0), "0") 
test_eq(_Roxen.html_encode_string (""), "") 
test_eq(_Roxen.html_encode_string (10), "10") 
test_eq(_Roxen.html_encode_string("a&b<c>d"), "a&amp;b&lt;c&gt;d") 
 
test_eq(_Roxen.http_decode_string(""), "") 
test_eq(_Roxen.http_decode_string("abc+d%20e%41"), "abc+d eA") 
test_eq(_Roxen.http_decode_string(""), "") 
test_eq(_Roxen.http_decode_string("+"), "+") 
 
test_eq(_Roxen.http_decode_string("%uD83D%uDE02"), "\U0001f602") 
 
// The following inputs are all illegal, but are allowed 
// for compat reasons. 
test_eq(_Roxen.http_decode_string("%"), "\0") 
test_eq(_Roxen.http_decode_string("%0"), "\0") 
test_eq(_Roxen.http_decode_string("%%"), "\0") 
test_eq(_Roxen.http_decode_string("%%%"), "U") 
test_eq(_Roxen.http_decode_string("%41%"), "A\0") 
test_eq(_Roxen.http_decode_string("%41%0"), "A\0") 
test_eq(_Roxen.http_decode_string("%41%%"), "A\0") 
test_eq(_Roxen.http_decode_string("%41%%%"), "AU") 
test_eq(_Roxen.http_decode_string("%u"), "\0") 
test_eq(_Roxen.http_decode_string("%u0"), "\0") 
test_eq(_Roxen.http_decode_string("%u00"), "\0") 
test_eq(_Roxen.http_decode_string("%u000"), "\0") 
test_eq(_Roxen.http_decode_string("%u000_"), "\b") 
test_eq(_Roxen.http_decode_string("%41%u"), "A\0") 
test_eq(_Roxen.http_decode_string("%41%u0"), "A\0") 
test_eq(_Roxen.http_decode_string("%41%u00"), "A\0") 
test_eq(_Roxen.http_decode_string("%41%u000"), "A\0") 
test_eq(_Roxen.http_decode_string("%41%u000_"), "A\b") 
 
test_eq(_Roxen.http_decode_string("%u12345"), "\x1234""5") 
test_eq(_Roxen.http_decode_string("%U12345"), "\x1234""5") 
 
define(test_mkhttp,[[ 
  test_any_equal([[ 
    string x=_Roxen.make_http_headers($1); 
    if(!has_suffix(x, "\r\n")) return -1; 
    return sort(x/"\r\n"-({""})); 
  ]],$2) 
]]) 
 
test_eval_error(_Roxen.make_http_headers(0)) 
 
test_mkhttp( ([]), ({}) ) 
test_mkhttp( (["":""]), ({": "}) ) 
test_mkhttp( (["a":"1","b":"2"]), ({"a: 1","b: 2"}) ) 
test_mkhttp( (["a":"1","b":({"2","3"})]), ({"a: 1","b: 2","b: 3"}) ) 
test_mkhttp( (["a":"1","b":({"2","2"})]), ({"a: 1","b: 2","b: 2"}) ) 
 
test_eval_error(_Roxen.make_http_headers((["a:1": "1"]))) 
test_eval_error(_Roxen.make_http_headers((["a\rb": "1"]))) 
test_eval_error(_Roxen.make_http_headers((["a\nb": "1"]))) 
test_eval_error(_Roxen.make_http_headers(([" a:1": "1"]))) 
test_eval_error(_Roxen.make_http_headers((["a": "1\r"]))) 
test_eval_error(_Roxen.make_http_headers((["a": "1\n"]))) 
test_eval_error(_Roxen.make_http_headers((["a": ({ "1\r\nb:2", "2\r\nc:2" }))))) 
 
define(test_hp,[[ 
  test_do( add_constant("hp", _Roxen.HeaderParser()) ) 
  test_equal( hp->feed( $1 ), $2) 
  test_do( add_constant("hp") ) 
]]) 
 
test_hp( "GET / HTTP/1.0\r\nblaha: foo\nbar\r\nzonk: 1\r\n\r\n", 
({ "", "GET / HTTP/1.0", ([ "blaha":"foo", "zonk":"1" ]) }) ) 
 
test_hp( "GET / HTTP/1.0\r\nblaha: foo\r\nzonk: 1\r\n\r\n", 
({ "", "GET / HTTP/1.0", ([ "blaha":"foo", "zonk":"1" ]) }) ) 
 
test_hp( "GET / HTTP/1.0\r\nblaha: foo\n\rblaha: bar\r\n\r\n", 
({ "", "GET / HTTP/1.0", ([ "blaha":({ "foo", "bar" }) ]) }) ) 
 
END_MARKER