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 | ||
d7bc1a7a | 20 | public static MultiMap<String, String> urlparams(Reader in) throws IOException { |
efa9722b FT |
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(); | |
efa9722b | 26 | while(true) { |
d7bc1a7a | 27 | int c = in.read(); |
efa9722b FT |
28 | if(st == "key") { |
29 | if(c == '%') { | |
efa9722b | 30 | try { |
d7bc1a7a FT |
31 | int d1 = in.read(); |
32 | int d2 = in.read(); | |
33 | buf.append((byte)((Misc.hex2int((char)d1) << 4) | Misc.hex2int((char)d2))); | |
efa9722b FT |
34 | } catch(NumberFormatException e) { |
35 | throw(new EncodingException("Invalid character escape")); | |
36 | } | |
efa9722b FT |
37 | } else if(c == '=') { |
38 | key = buf.convert(); | |
39 | buf = new MixedBuffer(); | |
40 | st = "val"; | |
41 | } else if(c == '&') { | |
42 | ret.add(buf.convert(), ""); | |
43 | buf = new MixedBuffer(); | |
44 | } else if(c == -1) { | |
45 | if(buf.size() == 0) { | |
46 | break; | |
47 | } else { | |
48 | ret.add(buf.convert(), ""); | |
49 | buf = new MixedBuffer(); | |
50 | } | |
51 | } else { | |
52 | buf.append((char)c); | |
53 | } | |
54 | } else if(st == "val") { | |
55 | if(c == '%') { | |
efa9722b | 56 | try { |
d7bc1a7a FT |
57 | int d1 = in.read(); |
58 | int d2 = in.read(); | |
59 | buf.append((byte)((Misc.hex2int((char)d1) << 4) | Misc.hex2int((char)d2))); | |
efa9722b FT |
60 | } catch(NumberFormatException e) { |
61 | throw(new EncodingException("Invalid character escape")); | |
62 | } | |
efa9722b FT |
63 | } else if((c == '&') || (c == -1)) { |
64 | ret.add(key, buf.convert()); | |
65 | buf = new MixedBuffer(); | |
66 | st = "key"; | |
67 | } else if(c == '+') { | |
68 | buf.append(' '); | |
69 | } else { | |
70 | buf.append((char)c); | |
71 | } | |
72 | } | |
73 | } | |
74 | return(ret); | |
75 | } catch(CharacterCodingException e) { | |
76 | throw(new EncodingException("Escaped parameter text is not proper UTF-8")); | |
77 | } | |
78 | } | |
79 | ||
d7bc1a7a FT |
80 | public static MultiMap<String, String> urlparams(String q) { |
81 | try { | |
82 | return(urlparams(new StringReader(q))); | |
83 | } catch(IOException e) { | |
84 | /* This will, of course, never ever once happen, but do | |
85 | * you think Javac cares? */ | |
86 | throw(new Error(e)); | |
87 | } | |
88 | } | |
89 | ||
efa9722b | 90 | public static MultiMap<String, String> urlparams(URL url) { |
ca045757 FT |
91 | String q = url.getQuery(); |
92 | if(q == null) | |
93 | q = ""; | |
94 | return(urlparams(q)); | |
efa9722b FT |
95 | } |
96 | ||
97 | public static MultiMap<String, String> urlparams(Request req) { | |
98 | return(urlparams(req.url())); | |
99 | } | |
100 | ||
101 | public static String encquery(Map<String, String> pars) { | |
102 | StringBuilder buf = new StringBuilder(); | |
103 | boolean f = true; | |
104 | for(Map.Entry<String, String> par : pars.entrySet()) { | |
105 | if(!f) | |
106 | buf.append('&'); | |
107 | buf.append(Misc.urlq(par.getKey())); | |
108 | buf.append('='); | |
109 | buf.append(Misc.urlq(par.getValue())); | |
110 | f = false; | |
111 | } | |
112 | return(buf.toString()); | |
113 | } | |
ca045757 FT |
114 | |
115 | public static MultiMap<String, String> postparams(Request req) { | |
116 | if(req.method() != "POST") | |
117 | return(null); | |
ca045757 FT |
118 | String ctype = req.inheaders().get("Content-Type"); |
119 | if(ctype == null) | |
120 | return(null); | |
121 | ctype = ctype.toLowerCase(); | |
122 | if(ctype.equals("application/x-www-form-urlencoded")) { | |
ca045757 FT |
123 | byte[] data; |
124 | try { | |
d7bc1a7a | 125 | return(urlparams(new InputStreamReader(req.input(), "UTF-8"))); |
ca045757 FT |
126 | } catch(IOException e) { |
127 | return(null); | |
128 | } | |
ca045757 FT |
129 | } |
130 | return(null); | |
131 | } | |
80e2f848 FT |
132 | |
133 | public static MultiMap<String, String> stdparams(Request req) { | |
134 | MultiMap<String, String> params = Params.urlparams(req); | |
135 | if(req.method() == "POST") { | |
136 | MultiMap<String, String> pp = Params.postparams(req); | |
137 | if(pp != null) | |
138 | params.putAll(pp); | |
139 | } | |
140 | return(params); | |
141 | } | |
efa9722b | 142 | } |