Bugfixed cookie parsing.
[jsvc.git] / src / dolda / jsvc / util / Http.java
1 package dolda.jsvc.util;
2
3 import java.util.*;
4 import java.text.*;
5 import java.io.*;
6
7 public class Http {
8     public final static DateFormat datefmt;
9     public final static String tspecials = "()<>@,;:\\\"/[]?={} ";
10     static {
11         datefmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
12         datefmt.setCalendar(Calendar.getInstance(TimeZone.getTimeZone("UTC")));
13     }
14     
15     public static class EncodingException extends ClientError {
16         public EncodingException(String msg) {
17             super("Invalid header encoding", msg);
18         }
19     }
20     
21     public static String fmtdate(Date d) {
22         return(datefmt.format(d));
23     }
24     
25     public static Date parsedate(String str) throws ParseException {
26         return(datefmt.parse(str));
27     }
28     
29     public static boolean istoken(String str) {
30         for(int i = 0; i < str.length(); i++) {
31             char c = str.charAt(i);
32             if(c < 32)
33                 return(false);
34             if(c >= 127)
35                 return(false);
36             if(tspecials.indexOf(c) >= 0)
37                 return(false);
38         }
39         return(true);
40     }
41     
42     public static String tokenquote(String str) {
43         if(istoken(str))
44             return(str);
45         StringBuilder buf = new StringBuilder();
46         buf.append("\"");
47         for(int i = 0; i < str.length(); i++) {
48             char c = str.charAt(i);
49             if(((c < 32) && (c != 9)) || (c >= 127))
50                 throw(new RuntimeException("Invalid character in HTTP quoted-string: `" + c + "'"));
51             if((c == '"') || (c == '\\')) {
52                 buf.append('\\');
53                 buf.append(c);
54             } else {
55                 buf.append(c);
56             }
57         }
58         buf.append("\"");
59         return(buf.toString());
60     }
61     
62     public static String tokenunquote(PushbackReader in) throws IOException {
63         StringBuilder buf = new StringBuilder();
64         String st = "eatws";
65         int c = in.read();
66         while(true) {
67             if(st == "eatws") {
68                 if(Character.isWhitespace((char)c))
69                     c = in.read();
70                 else
71                     st = "token";
72             } else if(st == "token") {
73                 if(c == '"') {
74                     st = "quoted";
75                     c = in.read();
76                 } else if((c < 0) || Character.isWhitespace((char)c) || (tspecials.indexOf((char)c) >= 0)) {
77                     if(c >= 0)
78                         in.unread(c);
79                     if(buf.length() == 0)
80                         return(null);
81                     return(buf.toString());
82                 } else if((c < 32) || (c >= 127)) {
83                     throw(new EncodingException("Invalid characters in header"));
84                 } else {
85                     buf.append((char)c);
86                     c = in.read();
87                 }
88             } else if(st == "quoted") {
89                 if(c < 0) {
90                     throw(new EncodingException("Unterminated quoted-string"));
91                 } else if((c < 32) && !Character.isWhitespace((char)c)) {
92                     throw(new EncodingException("Invalid characters in header"));
93                 } else if(c == '"') {
94                     return(buf.toString());
95                 } else if(c == '\\') {
96                     st = "q1";
97                     c = in.read();
98                 } else {
99                     buf.append((char)c);
100                     c = in.read();
101                 }
102             } else if(st == "q1") {
103                 if(c < 0) {
104                     throw(new EncodingException("Unterminated quoted-string"));
105                 } else if(c > 127) {
106                     throw(new EncodingException("Invalid characters in header"));
107                 } else {
108                     buf.append((char)c);
109                     c = in.read();
110                     st = "quoted";
111                 }
112             }
113         }
114     }
115 }