File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 1+ package proto
2+
3+ func fromhex (ch byte ) int8 {
4+ if ch >= '0' && ch <= '9' {
5+ return int8 (ch - '0' )
6+ }
7+ if ch >= 'a' && ch <= 'f' {
8+ return int8 (ch - 'a' + 10 )
9+ }
10+ if ch >= 'A' && ch <= 'F' {
11+ return int8 (ch - 'A' + 10 )
12+ }
13+ return - 1
14+ }
15+
16+ // RFC1738Unescape is a port of Squid rfc1738_unescape function.
17+ // It does unescaping in-place and returns slice pointing to boundaries of
18+ // unescaped bytes.
19+ func RFC1738Unescape (s []byte ) []byte {
20+ var i , j int /* i is write, j is read */
21+ for ; j < len (s ); i , j = i + 1 , j + 1 {
22+ s [i ] = s [j ]
23+ if s [j ] != '%' {
24+ /* normal case, nothing more to do */
25+ } else if j + 1 < len (s ) && s [j + 1 ] == '%' { /* %% case */
26+ j ++ /* Skip % */
27+ } else {
28+ if j + 2 >= len (s ) {
29+ continue
30+ }
31+ /* decode */
32+ var v1 , v2 int8
33+ var x byte
34+ v1 = fromhex (s [j + 1 ])
35+ if v1 < 0 {
36+ continue /* non-hex */
37+ }
38+ v2 = fromhex (s [j + 2 ])
39+ if v2 < 0 {
40+ continue /* non-hex */
41+ }
42+ x = byte (v1 )<< 4 | byte (v2 )
43+ if x > 0 && x <= 255 {
44+ s [i ] = x
45+ j += 2
46+ }
47+ }
48+ }
49+ return s [:i ]
50+ }
Original file line number Diff line number Diff line change 1+ package proto
2+
3+ import (
4+ "bytes"
5+ "fmt"
6+ "testing"
7+ )
8+
9+ func TestRFC1738Unescape (t * testing.T ) {
10+ testcases := []struct {
11+ input string
12+ output string
13+ }{
14+ {
15+ "%2Fdata%2Fsource%2Fpath" ,
16+ "/data/source/path" ,
17+ },
18+ {
19+ "http://foo.invalid%2Fdata%2Fsource%2Fpath" ,
20+ "http://foo.invalid/data/source/path" ,
21+ },
22+ {
23+ "w%0Ard" ,
24+ "w\n rd" ,
25+ },
26+ {
27+ "w%rd" ,
28+ "w%rd" ,
29+ },
30+ {
31+ "w%%rd" ,
32+ "w%rd" ,
33+ },
34+ {
35+ "w%%%rd" ,
36+ "w%%rd" ,
37+ },
38+ {
39+ "Bad String %1" ,
40+ "Bad String %1" ,
41+ },
42+ {
43+ "Bad String %1A%3" ,
44+ "Bad String \032 %3" ,
45+ },
46+ {
47+ "Good String %1A" ,
48+ "Good String \032 " ,
49+ },
50+ {
51+ "w%00rd" ,
52+ "w%00rd" ,
53+ },
54+ {
55+ "w%0rd" ,
56+ "w%0rd" ,
57+ },
58+ {
59+ "w%%00%rd" ,
60+ "w%00%rd" ,
61+ },
62+ {
63+ "w%%%00%rd" ,
64+ "w%%00%rd" ,
65+ },
66+ }
67+ for i , tc := range testcases {
68+ t .Run (fmt .Sprintf ("Testcase#%d" , i + 1 ), func (t * testing.T ) {
69+ output := RFC1738Unescape ([]byte (tc .input ))
70+ if bytes .Compare (output , []byte (tc .output )) != 0 {
71+ t .Errorf ("got: %x, want: %x" , output , []byte (tc .output ))
72+ }
73+ })
74+ }
75+ }
You can’t perform that action at this time.
0 commit comments