Commit | Line | Data |
---|---|---|
efa9722b FT |
1 | package dolda.jsvc.util; |
2 | ||
3 | import dolda.jsvc.*; | |
4 | import java.util.*; | |
5 | import java.io.*; | |
6 | import java.net.*; | |
7 | import java.nio.charset.CharacterCodingException; | |
8 | ||
9 | public class Params { | |
10 | public static class EncodingException extends RequestRestart { | |
11 | public EncodingException(String msg) { | |
12 | super(msg); | |
13 | } | |
14 | ||
15 | public void respond(Request req) { | |
16 | throw(Restarts.stdresponse(400, "Invalid parameter encoding", getMessage())); | |
17 | } | |
18 | } | |
19 | ||
20 | public static MultiMap<String, String> urlparams(String q) { | |
21 | try { | |
22 | MultiMap<String, String> ret = new WrappedMultiMap<String, String>(new TreeMap<String, Collection<String>>()); | |
23 | String st = "key"; | |
24 | String key = null; /* Java is stupid. */ | |
25 | MixedBuffer buf = new MixedBuffer(); | |
26 | int i = 0; | |
27 | while(true) { | |
28 | int c = (i >= q.length())?-1:(q.charAt(i++)); | |
29 | if(st == "key") { | |
30 | if(c == '%') { | |
31 | if(q.length() - i < 2) | |
32 | throw(new EncodingException("Invalid character escape")); | |
33 | try { | |
34 | buf.append((byte)((Misc.hex2int(q.charAt(i)) << 4) | Misc.hex2int(q.charAt(i + 1)))); | |
35 | } catch(NumberFormatException e) { | |
36 | throw(new EncodingException("Invalid character escape")); | |
37 | } | |
38 | i += 2; | |
39 | } else if(c == '=') { | |
40 | key = buf.convert(); | |
41 | buf = new MixedBuffer(); | |
42 | st = "val"; | |
43 | } else if(c == '&') { | |
44 | ret.add(buf.convert(), ""); | |
45 | buf = new MixedBuffer(); | |
46 | } else if(c == -1) { | |
47 | if(buf.size() == 0) { | |
48 | break; | |
49 | } else { | |
50 | ret.add(buf.convert(), ""); | |
51 | buf = new MixedBuffer(); | |
52 | } | |
53 | } else { | |
54 | buf.append((char)c); | |
55 | } | |
56 | } else if(st == "val") { | |
57 | if(c == '%') { | |
58 | if(q.length() - i < 2) | |
59 | throw(new EncodingException("Invalid character escape")); | |
60 | try { | |
61 | buf.append((byte)((Misc.hex2int(q.charAt(i)) << 4) | Misc.hex2int(q.charAt(i + 1)))); | |
62 | } catch(NumberFormatException e) { | |
63 | throw(new EncodingException("Invalid character escape")); | |
64 | } | |
65 | i += 2; | |
66 | } else if((c == '&') || (c == -1)) { | |
67 | ret.add(key, buf.convert()); | |
68 | buf = new MixedBuffer(); | |
69 | st = "key"; | |
70 | } else if(c == '+') { | |
71 | buf.append(' '); | |
72 | } else { | |
73 | buf.append((char)c); | |
74 | } | |
75 | } | |
76 | } | |
77 | return(ret); | |
78 | } catch(CharacterCodingException e) { | |
79 | throw(new EncodingException("Escaped parameter text is not proper UTF-8")); | |
80 | } | |
81 | } | |
82 | ||
83 | public static MultiMap<String, String> urlparams(URL url) { | |
ca045757 FT |
84 | String q = url.getQuery(); |
85 | if(q == null) | |
86 | q = ""; | |
87 | return(urlparams(q)); | |
efa9722b FT |
88 | } |
89 | ||
90 | public static MultiMap<String, String> urlparams(Request req) { | |
91 | return(urlparams(req.url())); | |
92 | } | |
93 | ||
94 | public static String encquery(Map<String, String> pars) { | |
95 | StringBuilder buf = new StringBuilder(); | |
96 | boolean f = true; | |
97 | for(Map.Entry<String, String> par : pars.entrySet()) { | |
98 | if(!f) | |
99 | buf.append('&'); | |
100 | buf.append(Misc.urlq(par.getKey())); | |
101 | buf.append('='); | |
102 | buf.append(Misc.urlq(par.getValue())); | |
103 | f = false; | |
104 | } | |
105 | return(buf.toString()); | |
106 | } | |
ca045757 FT |
107 | |
108 | public static MultiMap<String, String> postparams(Request req) { | |
109 | if(req.method() != "POST") | |
110 | return(null); | |
111 | String clens = req.inheaders().get("Content-Length"); | |
112 | if(clens == null) | |
113 | return(null); | |
114 | int clen; | |
115 | try { | |
116 | clen = Integer.parseInt(clens); | |
117 | } catch(NumberFormatException e) { | |
118 | return(null); | |
119 | } | |
120 | String ctype = req.inheaders().get("Content-Type"); | |
121 | if(ctype == null) | |
122 | return(null); | |
123 | ctype = ctype.toLowerCase(); | |
124 | if(ctype.equals("application/x-www-form-urlencoded")) { | |
125 | if(clen > (1 << 20)) /* Just to be safe */ | |
126 | return(null); | |
127 | byte[] data; | |
128 | try { | |
129 | data = Misc.readall(req.input()); | |
130 | } catch(IOException e) { | |
131 | return(null); | |
132 | } | |
133 | String dec = new String(data, Misc.utf8); | |
134 | return(urlparams(dec)); | |
135 | } | |
136 | return(null); | |
137 | } | |
efa9722b | 138 | } |