Cleaned up parameter decoding.
[jsvc.git] / src / dolda / jsvc / util / Params.java
CommitLineData
efa9722b
FT
1package dolda.jsvc.util;
2
3import dolda.jsvc.*;
4import java.util.*;
5import java.io.*;
6import java.net.*;
7import java.nio.charset.CharacterCodingException;
8
9public 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 }
efa9722b 132}