001: // HttpSetCookieList.java
002: // $Id: HttpSetCookieList.java,v 1.19 2003/01/31 13:53:28 ylafon Exp $
003: // (c) COPYRIGHT MIT and INRIA, 1996.
004: // Please first read the full copyright statement in file COPYRIGHT.html
005:
006: package org.w3c.www.http;
007:
008: import java.util.Date;
009: import java.util.Vector;
010:
011: import java.io.IOException;
012: import java.io.OutputStream;
013:
014: public class HttpSetCookieList extends BasicValue {
015: Vector setcookies = null;
016: Vector raws = null;
017: Vector copycookies = null;
018: boolean original = true;
019:
020: protected int length() {
021: if (setcookies == null)
022: return 0;
023: return setcookies.size();
024: }
025:
026: protected int copyLength() {
027: if (copycookies == null)
028: return 0;
029: return copycookies.size();
030: }
031:
032: // if the cookie is home made or copied from an upstream source
033: protected boolean isOriginal() {
034: return original;
035: }
036:
037: protected void emitCookie(OutputStream out, int cookie)
038: throws IOException {
039: checkByteValues();
040: out.write(((HttpBuffer) raws.elementAt(cookie)).getByteCopy());
041: }
042:
043: protected void emitCopyCookie(OutputStream out, int cookie)
044: throws IOException {
045: out.write(((HttpBuffer) copycookies.elementAt(cookie))
046: .getByteCopy());
047: }
048:
049: protected final void checkByteValues() {
050: if (raws == null) {
051: updateByteValue();
052: }
053: }
054:
055: protected void updateByteValue() {
056: // Dump all cookies, one after the other:
057: int len = setcookies.size();
058: raws = new Vector(len);
059: for (int i = 0; i < len; i++) {
060: HttpBuffer buf = new HttpBuffer();
061: HttpSetCookie sc = (HttpSetCookie) setcookies.elementAt(i);
062: buf.append(sc.getName(), (byte) '=', sc.getValue());
063: String s = sc.getComment();
064: if (s != null) {
065: buf.append((byte) ';');
066: buf.append(" comment", (byte) '=', s);
067: }
068: if ((s = sc.getDomain()) != null) {
069: buf.append((byte) ';');
070: buf.append(" domain", (byte) '=', s);
071: }
072: int ii = sc.getMaxAge();
073: if (ii >= 0) {
074: // Append expires time:
075: float exp = (float) ii * (float) 1000;
076: CookieDate expires = new CookieDate(true,
077: (long) (System.currentTimeMillis() + exp));
078: buf.append((byte) ';');
079: buf.append(" expires=");
080: expires.appendValue(buf);
081: }
082: if ((s = sc.getPath()) != null) {
083: buf.append((byte) ';');
084: buf.append(" path", (byte) '=', s);
085: }
086: if (sc.getSecurity()) {
087: buf.append(';');
088: buf.append(" secure");
089: }
090: raws.addElement(buf);
091: }
092: }
093:
094: /**
095: * HeaderValue implementation - Add these bytes to the header raw value.
096: * @param buf The byte buffer containing some part of the header value.
097: * @param off The offset of the header value in above buffer.
098: * @param len The length of the header value in above buffer.
099: */
100:
101: public void addBytes(byte buf[], int off, int len) {
102: original = false;
103: super .addBytes(buf, off, len);
104: HttpBuffer b = new HttpBuffer(len + 1);
105: b.append(buf, off, len);
106: if (copycookies == null) {
107: copycookies = new Vector(2);
108: }
109: copycookies.addElement(b);
110: }
111:
112: /**
113: * parse set cookie header according to the specification:
114: * http://www.netscape.com/newsref/std/cookie_spec.html
115: * @exception HttpParserException if parsing failed.
116: */
117: protected void parse() throws HttpParserException {
118: ParseState cl = new ParseState(roff, rlen);
119: ParseState av = new ParseState(0, 0);
120: ParseState it = new ParseState(0, 0);
121: ParseState val = new ParseState(0, 0);
122: // Prepare parser states:
123: // FIXME SPEC
124: cl.separator = (byte) ',';
125: cl.spaceIsSep = false;
126: av.separator = (byte) ';';
127: av.spaceIsSep = false;
128: it.separator = (byte) '=';
129: it.spaceIsSep = false;
130: val.separator = (byte) ';';
131: val.spaceIsSep = false;
132:
133: // Parse the cookie list with cl
134: boolean inExpireItem = false;
135: String expiresDay = null;
136: HttpSetCookie sc = null;
137: while (HttpParser.nextItem(raw, cl) >= 0) {
138: // Each cookie is made of attr-value pairs:
139: av.ioff = cl.start;
140: av.bufend = cl.end;
141: if (!inExpireItem)
142: sc = new HttpSetCookie();
143: while (HttpParser.nextItem(raw, av) >= 0) {
144: if (inExpireItem) {
145: //get the rest of the expire date
146: try {
147: String date = expiresDay + ", "
148: + av.toString(raw);
149: Date maxage = new Date(date);
150: sc.setMaxAge((int) (maxage.getTime() / 1000));
151: } catch (Exception e) {
152: }
153: inExpireItem = false;
154: } else {
155: // Each av is made of an attr '=' value:
156: it.ioff = av.start;
157: it.bufend = av.end;
158: if (HttpParser.nextItem(raw, it) < 0)
159: error("Invalid cookie item ["
160: + av.toString(raw) + "]");
161: String itemNaturalCase = it.toString(raw);
162: String item = it.toString(raw, true);
163: it.prepare();
164: if (HttpParser.nextItem(raw, it) < 0) {
165: // There's no value for the item. It's either an error,
166: // a cookie without value or the "secure" item.
167: if (item.equals("secure")) {
168: // Secure is the only item without value.
169: sc.setSecurity(true);
170: } else if (item.equals("comment")
171: || item.equals("domain")
172: || item.equals("expires")
173: || item.equals("max-age")
174: || item.equals("path")
175: || item.equals("version")) {
176: // All these items *must* have a value if they
177: // are defined. So it's an error.
178: error("No value for attribute [" + item
179: + "]");
180: } else {
181: // This is probably a cookie without value.
182: sc.setName(itemNaturalCase);
183: sc.setValue("");
184: }
185: } else {
186: if (item.equals("comment")) {
187: sc.setComment(it.toString(raw));
188: } else if (item.equals("domain")) {
189: sc.setDomain(it.toString(raw));
190: } else if (item.equals("expires")) {
191: //Ugly hack because there is a ',' in date
192: expiresDay = it.toString(raw);
193: inExpireItem = true;
194: } else if (item.equals("max-age")) {
195: sc.setMaxAge(Integer.parseInt(it
196: .toString(raw)));
197: } else if (item.equals("path")) {
198: sc.setPath(it.toString(raw));
199: } else if (item.equals("version")) {
200: sc.setVersion(Integer.parseInt(it
201: .toString(raw)));
202: } else {
203: // This is probably the name/value for the cookie:
204: if (sc.getName() != null)
205: error("Invalid cookie item [" + item
206: + "]");
207: sc.setName(itemNaturalCase);
208: val.ioff = it.start;
209: val.bufend = av.end;
210: HttpParser.nextItem(raw, val);
211: sc.setValue(val.toString(raw));
212: }
213: }
214: }
215: av.prepare();
216: }
217: if (!inExpireItem) // Add the newly created cookie:
218: setcookies.addElement(sc);
219: cl.prepare();
220: }
221: }
222:
223: public Object getValue() {
224: return this ;
225: }
226:
227: /**
228: * Add a specific cookie to the SetCookie header value.
229: * This method creates a new, empty SetCookie holder, attaches it to the
230: * SetCookie header, and returns it.
231: * @param name The cookie's name.
232: * @param value The cookie's value.
233: */
234:
235: public HttpSetCookie addSetCookie(String name, String value) {
236: validate();
237: HttpSetCookie setcookie = new HttpSetCookie(true, name, value);
238: setcookies.addElement(setcookie);
239: return setcookie;
240: }
241:
242: public void addSetCookie(HttpSetCookie setCookie) {
243: validate();
244: setcookies.addElement(setCookie);
245: }
246:
247: /**
248: * Remove a predefined cookie from this SetCookie header.
249: * @param name The name of the cookie to remove.
250: * @return A boolean <strong>true</strong> if removed, <strong>false
251: * </strong> otherwise.
252: */
253:
254: public boolean removeSetCookie(String name) {
255: validate();
256: for (int i = 0; i < setcookies.size(); i++) {
257: HttpSetCookie setcookie = (HttpSetCookie) setcookies
258: .elementAt(i);
259: if (setcookie.getName().equals(name)) {
260: setcookies.removeElementAt(i);
261: return true;
262: }
263: }
264: return false;
265: }
266:
267: /**
268: * Get the cookie infos associated with the given cookie name, if any.
269: * @param name The cookie's name.
270: * @return A HttpSetCookie instance, if found, or <strong>null</strong>
271: * otherwise.
272: */
273:
274: public HttpSetCookie getSetCookie(String name) {
275: validate();
276: for (int i = 0; i < setcookies.size(); i++) {
277: HttpSetCookie setcookie = (HttpSetCookie) setcookies
278: .elementAt(i);
279: if (setcookie.getName().equals(name))
280: return setcookie;
281: }
282: return null;
283: }
284:
285: public HttpSetCookie[] getSetCookies() {
286: validate();
287: HttpSetCookie cooks[] = new HttpSetCookie[setcookies.size()];
288: setcookies.copyInto(cooks);
289: return cooks;
290: }
291:
292: HttpSetCookieList() {
293: this .isValid = false;
294: this .setcookies = new Vector(2);
295: }
296:
297: public HttpSetCookieList(HttpSetCookie sc[]) {
298: this .isValid = true;
299: this .setcookies = new Vector(2);
300: if (sc != null) {
301: // FIXME Eouf corse, it's broken
302: for (int i = 0; i < sc.length; i++)
303: setcookies.addElement(sc[i]);
304: }
305: }
306:
307: }
|