Source code: com/prolifics/servlet/HttpOutputStream.java
1 /*************************************************/
2 /* Copyright (c) 2000 */
3 /* by */
4 /* JYACC, Inc., New York NY USA */
5 /* and contributors. */
6 /* Use of this program is governed by the */
7 /* JYACC Public License Version 1.0, a copy of */
8 /* which can be obtained at */
9 /* http://www.possl.org/jyacc-license.html */
10 /*************************************************/
11
12 /* @(#)HttpOutputStream.java 77.2 00/05/10 13:27:56 */
13
14 package com.prolifics.servlet;
15 import java.io.*;
16 import java.util.*;
17
18 import javax.servlet.*;
19 import javax.servlet.http.*;
20
21 /**
22 * @version @(#)HttpOutputStream.java 77.2 00/05/10 13:27:56
23 * @author Prolifics
24 */
25 class HttpOutputStream extends FilterOutputStream
26 {
27 private static String sccsid = "@(#)HttpOutputStream.java 77.2 00/05/10 13:27:56";
28 private HttpServletResponse res;
29 private int state = start;
30 private int nmlen = 0;
31 private byte name[] = new byte[33];
32 private int vallen = 0;
33 private byte val[] = new byte[257];
34 private boolean hdrdone = false;
35 private boolean alldone = false;
36 private static final byte nul = 0;
37
38 private static final int start = 0;
39 private static final int hdrnm = 1;
40 private static final int aehdr = 2;
41 private static final int ehdr = 3;
42 private static final int aend = 4;
43 private static final int end = 5;
44 private static final int hdrsp = 6;
45 private static final int hdrval = 7;
46 private static final int ehdrnm = 8;
47 private static final int err = 9;
48 private static final String statenm[] =
49 {
50 "start",
51 "hdrnm",
52 "aehdr",
53 "ehdr",
54 "aend",
55 "end",
56 "hdrsp",
57 "hdrval",
58 "ehdrnm",
59 "err",
60 };
61
62 private static final int statetable[][] =
63 {
64 /* default '\r' '\n' ':' ' ' */
65 /* start */ { hdrnm, aend, end, err, err, },
66 /* hdrnm */ { hdrnm, err, err, ehdrnm, err, },
67 /* aehdr */ { err, err, ehdr, err, err, },
68 /* ehdr */ { err, err, err, err, err, },
69 /* aend */ { err, err, end, err, err, },
70 /* end */ { err, err, err, err, err, },
71 /* hdrsp */ { hdrval, err, err, hdrval, hdrsp, },
72 /* hdrval */ { hdrval, aehdr, ehdr, hdrval, hdrval, },
73 /* ehdrnm */ { hdrval, err, err, err, hdrsp, },
74 /* err */ { err, err, err, err, err, },
75 };
76
77 private static int
78 getclss(int chr)
79 {
80 switch (chr)
81 {
82 case '\r':
83 return 1;
84 case '\n':
85 return 2;
86 case ':':
87 return 3;
88 case ' ':
89 return 4;
90 default:
91 return 0;
92 }
93 }
94
95 private static int
96 newstate(int state, int clss)
97 {
98 return statetable[state][clss];
99 }
100
101 private void
102 addCookie(HttpServletResponse res, String cookieStr)
103 {
104 StringTokenizer st1 = new StringTokenizer(cookieStr, "; ");
105 String name = null;
106 String value = null;
107 String piece = null;
108 Cookie cookie = null;
109
110 while (st1.hasMoreTokens())
111 {
112 try
113 {
114 piece = st1.nextToken();
115 }
116 catch (NoSuchElementException excp)
117 {
118 break;
119 }
120
121 StringTokenizer st2 =
122 new StringTokenizer(piece, "= ");
123 try
124 {
125 name = st2.nextToken();
126 }
127 catch (NoSuchElementException excp)
128 {
129 name = null;
130 }
131
132 try
133 {
134 value = st2.nextToken();
135 }
136 catch (NoSuchElementException excp)
137 {
138 value = null;
139 }
140
141 if (cookie == null)
142 {
143 cookie = new Cookie(name, value);
144 }
145 else if (name.equalsIgnoreCase("Comment"))
146 {
147 cookie.setComment(value);
148 }
149 else if (name.equalsIgnoreCase("Discard"))
150 {
151 cookie.setMaxAge(-1);
152 }
153 else if (name.equalsIgnoreCase("Domain"))
154 {
155 cookie.setDomain(value);
156 }
157 else if (name.equalsIgnoreCase("Expires"))
158 {
159 }
160 else if (name.equalsIgnoreCase("Max-Age"))
161 {
162 cookie.setMaxAge(Integer.parseInt(value));
163 }
164 else if (name.equalsIgnoreCase("Path"))
165 {
166 cookie.setPath(value);
167 }
168 else if (name.equalsIgnoreCase("Secure"))
169 {
170 cookie.setSecure(true);
171 }
172 else if (name.equalsIgnoreCase("Version"))
173 {
174 cookie.setVersion(Integer.parseInt(value));
175 }
176 }
177 res.addCookie(cookie);
178 }
179
180 public HttpOutputStream(HttpServletResponse res,
181 ServletOutputStream out)
182 {
183 super(out);
184 this.res = res;
185 }
186
187 private static String bytesToString(byte src[], int offset, int len)
188 {
189 return new String(src, offset, len /* , encoding */);
190 }
191
192 public void write(byte buf[], int offset, int len)
193 throws IOException
194 {
195 int count = 0;
196
197 if (! hdrdone)
198 {
199 count = process(buf, offset, len);
200 }
201 offset += count;
202 len -= count;
203 if (len > 0 && ! alldone)
204 {
205 super.write(buf, offset, len);
206 }
207 }
208
209 public void write(byte buf[]) throws IOException
210 {
211 write(buf, 0, buf.length);
212 }
213
214 public void write(int b) throws IOException
215 {
216 byte buf[] = new byte[1];
217
218 write(buf, 0, 1);
219 }
220
221 private void
222 processhdr(HttpServletResponse res, String name, String value)
223 throws IOException
224 {
225 if (alldone)
226 {
227 return;
228 }
229
230 if (name.equals("Content-length"))
231 {
232 res.setContentLength(Integer.parseInt(value));
233 }
234 else if (name.equals("Content-type"))
235 {
236 res.setContentType(value);
237 }
238 else if (name.equals("Status"))
239 {
240 int offset = value.indexOf(' ');
241 int sc;
242 String scstr;
243 String sm;
244 if (offset < 0)
245 {
246 scstr = value;
247 sc = Integer.parseInt(scstr);
248 res.setStatus(sc);
249 }
250 else
251 {
252 scstr = value.substring(0, offset);
253 sm = value.substring(offset+1);
254 sc = Integer.parseInt(scstr);
255 res.setStatus(sc, sm);
256 }
257 }
258 else if (name.equals("Set-cookie"))
259 {
260 addCookie(res, value);
261 }
262 else if (name.equals("Location"))
263 {
264 res.sendRedirect(value);
265 alldone = true;
266 }
267 else
268 {
269 res.setHeader(name, value);
270 }
271 }
272
273 private int
274 process(byte buf[], int offset, int len)
275 throws IOException
276 {
277 int index;
278 int chr;
279
280 if (hdrdone)
281 {
282 return 0;
283 }
284
285 for (index = 0; index < len && state != end; index++)
286 {
287 chr = buf[index + offset];
288
289 state = newstate(state, getclss(chr));
290
291 switch (state)
292 {
293 case start:
294 nmlen = 0;
295 vallen = 0;
296 break;
297 case hdrnm:
298 if (nmlen >= name.length - 1)
299 {
300 throw new IOException();
301 }
302 name[nmlen] = (byte) chr;
303 nmlen++;
304 name[nmlen] = nul;
305 break;
306 case aehdr:
307 break;
308 case ehdr:
309 val[vallen] = nul;
310 processhdr(res,
311 bytesToString(name, 0, nmlen),
312 bytesToString(val, 0, vallen));
313 nmlen = 0;
314 vallen = 0;
315 state = start;
316 break;
317 case aend:
318 break;
319 case end:
320 hdrdone = true;
321 break;
322 case hdrsp:
323 break;
324 case hdrval:
325 if (vallen >= val.length - 1)
326 {
327 throw new IOException();
328 }
329 val[vallen] = (byte) chr;
330 vallen++;
331 val[vallen] = nul;
332 break;
333 case ehdrnm:
334 name[nmlen] = nul;
335 break;
336 case err:
337 throw new IOException();
338 default:
339 throw new IOException();
340 }
341 }
342
343 return index;
344 }
345 }