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