--- /dev/null
+// HttpSetCookieList.java\r
+// $Id: HttpSetCookieList.java,v 1.1 2010/06/15 12:19:44 smhuang Exp $\r
+// (c) COPYRIGHT MIT and INRIA, 1996.\r
+// Please first read the full copyright statement in file COPYRIGHT.html\r
+\r
+package org.w3c.www.http;\r
+\r
+import java.util.Date;\r
+import java.util.Vector;\r
+\r
+import java.io.IOException;\r
+import java.io.OutputStream;\r
+\r
+public class HttpSetCookieList extends BasicValue {\r
+ Vector setcookies = null;\r
+ Vector raws = null;\r
+ Vector copycookies = null;\r
+ boolean original = true;\r
+\r
+ protected int length() {\r
+ if (setcookies == null)\r
+ return 0;\r
+ return setcookies.size();\r
+ }\r
+\r
+ protected int copyLength() {\r
+ if (copycookies == null)\r
+ return 0;\r
+ return copycookies.size();\r
+ }\r
+\r
+ // if the cookie is home made or copied from an upstream source\r
+ protected boolean isOriginal() {\r
+ return original;\r
+ }\r
+\r
+ protected void emitCookie(OutputStream out, int cookie) \r
+ throws IOException\r
+ {\r
+ checkByteValues();\r
+ out.write(((HttpBuffer)raws.elementAt(cookie)).getByteCopy());\r
+ }\r
+\r
+ protected void emitCopyCookie(OutputStream out, int cookie) \r
+ throws IOException\r
+ {\r
+ out.write(((HttpBuffer)copycookies.elementAt(cookie)).getByteCopy());\r
+ }\r
+\r
+ protected final void checkByteValues() {\r
+ if (raws == null) {\r
+ updateByteValue();\r
+ }\r
+ }\r
+\r
+ protected void updateByteValue() {\r
+ // Dump all cookies, one after the other:\r
+ int len = setcookies.size();\r
+ raws = new Vector(len);\r
+ for (int i = 0 ; i < len ; i++) {\r
+ HttpBuffer buf = new HttpBuffer();\r
+ HttpSetCookie sc = (HttpSetCookie) setcookies.elementAt(i);\r
+ buf.append(sc.getName(), (byte) '=', sc.getValue());\r
+ String s = sc.getComment();\r
+ if (s != null ) {\r
+ buf.append((byte) ';');\r
+ buf.append(" comment", (byte) '=', s);\r
+ }\r
+ if ((s = sc.getDomain()) != null ) {\r
+ buf.append((byte) ';');\r
+ buf.append(" domain", (byte) '=', s);\r
+ } \r
+ int ii = sc.getMaxAge();\r
+ if ( ii >= 0 ) {\r
+ // Append expires time:\r
+ float exp = (float)ii * (float)1000;\r
+ CookieDate expires = \r
+ new CookieDate(true,\r
+ (long)(System.currentTimeMillis()\r
+ + exp));\r
+ buf.append((byte) ';');\r
+ buf.append(" expires=");\r
+ expires.appendValue(buf);\r
+ }\r
+ if ((s = sc.getPath()) != null ) {\r
+ buf.append((byte) ';');\r
+ buf.append(" path", (byte) '=', s);\r
+ }\r
+ if ( sc.getSecurity() ) {\r
+ buf.append(';');\r
+ buf.append(" secure");\r
+ }\r
+ raws.addElement(buf);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * HeaderValue implementation - Add these bytes to the header raw value.\r
+ * @param buf The byte buffer containing some part of the header value.\r
+ * @param off The offset of the header value in above buffer.\r
+ * @param len The length of the header value in above buffer.\r
+ */\r
+\r
+ public void addBytes(byte buf[], int off, int len) {\r
+ original = false;\r
+ super.addBytes(buf, off, len);\r
+ HttpBuffer b = new HttpBuffer(len+1);\r
+ b.append(buf, off, len);\r
+ if (copycookies == null) {\r
+ copycookies = new Vector(2);\r
+ }\r
+ copycookies.addElement(b);\r
+ }\r
+\r
+ /**\r
+ * parse set cookie header according to the specification:\r
+ * http://www.netscape.com/newsref/std/cookie_spec.html\r
+ * @exception HttpParserException if parsing failed.\r
+ */\r
+ protected void parse()\r
+ throws HttpParserException\r
+ {\r
+ ParseState cl = new ParseState(roff, rlen);\r
+ ParseState av = new ParseState(0, 0);\r
+ ParseState it = new ParseState(0, 0);\r
+ ParseState val = new ParseState(0, 0);\r
+ // Prepare parser states:\r
+ // FIXME SPEC \r
+ cl.separator = (byte) ',';\r
+ cl.spaceIsSep = false;\r
+ av.separator = (byte) ';';\r
+ av.spaceIsSep = false;\r
+ it.separator = (byte) '=';\r
+ it.spaceIsSep = false;\r
+ val.separator = (byte) ';';\r
+ val.spaceIsSep = false;\r
+\r
+ // Parse the cookie list with cl\r
+ boolean inExpireItem = false;\r
+ String expiresDay = null;\r
+ HttpSetCookie sc = null;\r
+ while (HttpParser.nextItem(raw, cl) >= 0) {\r
+ // Each cookie is made of attr-value pairs:\r
+ av.ioff = cl.start;\r
+ av.bufend = cl.end;\r
+ if (!inExpireItem)\r
+ sc = new HttpSetCookie();\r
+ while ( HttpParser.nextItem(raw, av) >= 0 ) {\r
+ if (inExpireItem) {\r
+ //get the rest of the expire date\r
+ try {\r
+ String date = expiresDay+", "+av.toString(raw);\r
+ Date maxage = new Date(date);\r
+ sc.setMaxAge((int) (maxage.getTime()/1000));\r
+ } catch (Exception e) {}\r
+ inExpireItem = false;\r
+ } else {\r
+ // Each av is made of an attr '=' value:\r
+ it.ioff = av.start;\r
+ it.bufend = av.end;\r
+ if ( HttpParser.nextItem(raw, it) < 0 )\r
+ error("Invalid cookie item ["+av.toString(raw)+"]");\r
+ String itemNaturalCase = it.toString(raw);\r
+ String item = it.toString(raw, true);\r
+ it.prepare();\r
+ if ( HttpParser.nextItem(raw, it) < 0 ) {\r
+ // There's no value for the item. It's either an error,\r
+ // a cookie without value or the "secure" item.\r
+ if ( item.equals("secure") ) {\r
+ // Secure is the only item without value.\r
+ sc.setSecurity(true);\r
+ } else if ( item.equals("comment") || \r
+ item.equals("domain") ||\r
+ item.equals("expires") || \r
+ item.equals("max-age") ||\r
+ item.equals("path") ||\r
+ item.equals("version") ) {\r
+ // All these items *must* have a value if they \r
+ // are defined. So it's an error.\r
+ error("No value for attribute ["+item+"]");\r
+ } else {\r
+ // This is probably a cookie without value.\r
+ sc.setName(itemNaturalCase);\r
+ sc.setValue("");\r
+ }\r
+ } else {\r
+ if ( item.equals("comment") ) {\r
+ sc.setComment(it.toString(raw));\r
+ } else if ( item.equals("domain") ) {\r
+ sc.setDomain(it.toString(raw));\r
+ } else if ( item.equals("expires") ) {\r
+ //Ugly hack because there is a ',' in date\r
+ expiresDay = it.toString(raw);\r
+ inExpireItem = true;\r
+ } else if ( item.equals("max-age") ) {\r
+ sc.setMaxAge(Integer.parseInt(it.toString(raw)));\r
+ } else if ( item.equals("path") ) {\r
+ sc.setPath(it.toString(raw));\r
+ } else if ( item.equals("version") ) {\r
+ sc.setVersion(Integer.parseInt(it.toString(raw)));\r
+ } else {\r
+ // This is probably the name/value for the cookie:\r
+ if ( sc.getName() != null )\r
+ error("Invalid cookie item ["+item+"]");\r
+ sc.setName(itemNaturalCase);\r
+ val.ioff = it.start;\r
+ val.bufend = av.end;\r
+ HttpParser.nextItem(raw, val);\r
+ sc.setValue(val.toString(raw));\r
+ }\r
+ }\r
+ }\r
+ av.prepare();\r
+ }\r
+ if (!inExpireItem) // Add the newly created cookie:\r
+ setcookies.addElement(sc);\r
+ cl.prepare();\r
+ }\r
+ }\r
+\r
+ public Object getValue() {\r
+ return this;\r
+ }\r
+\r
+ /**\r
+ * Add a specific cookie to the SetCookie header value.\r
+ * This method creates a new, empty SetCookie holder, attaches it to the\r
+ * SetCookie header, and returns it.\r
+ * @param name The cookie's name.\r
+ * @param value The cookie's value.\r
+ */\r
+\r
+ public HttpSetCookie addSetCookie(String name, String value) {\r
+ validate();\r
+ HttpSetCookie setcookie = new HttpSetCookie(true, name, value);\r
+ setcookies.addElement(setcookie);\r
+ return setcookie;\r
+ }\r
+\r
+ public void addSetCookie(HttpSetCookie setCookie) {\r
+ validate();\r
+ setcookies.addElement(setCookie);\r
+ }\r
+\r
+ /**\r
+ * Remove a predefined cookie from this SetCookie header.\r
+ * @param name The name of the cookie to remove.\r
+ * @return A boolean <strong>true</strong> if removed, <strong>false\r
+ * </strong> otherwise.\r
+ */\r
+\r
+ public boolean removeSetCookie(String name) {\r
+ validate();\r
+ for (int i = 0 ; i < setcookies.size() ; i++) {\r
+ HttpSetCookie setcookie = (HttpSetCookie) setcookies.elementAt(i);\r
+ if ( setcookie.getName().equals(name) ) {\r
+ setcookies.removeElementAt(i);\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Get the cookie infos associated with the given cookie name, if any.\r
+ * @param name The cookie's name.\r
+ * @return A HttpSetCookie instance, if found, or <strong>null</strong> \r
+ * otherwise.\r
+ */\r
+\r
+ public HttpSetCookie getSetCookie(String name) {\r
+ validate();\r
+ for (int i = 0 ; i < setcookies.size() ; i++) {\r
+ HttpSetCookie setcookie = (HttpSetCookie) setcookies.elementAt(i);\r
+ if ( setcookie.getName().equals(name) )\r
+ return setcookie;\r
+ }\r
+ return null;\r
+ }\r
+\r
+ public HttpSetCookie[] getSetCookies() {\r
+ validate();\r
+ HttpSetCookie cooks [] = new HttpSetCookie[setcookies.size()];\r
+ setcookies.copyInto(cooks);\r
+ return cooks;\r
+ }\r
+\r
+ HttpSetCookieList() {\r
+ this.isValid = false;\r
+ this.setcookies = new Vector(2);\r
+ }\r
+\r
+ public HttpSetCookieList(HttpSetCookie sc[]) {\r
+ this.isValid = true;\r
+ this.setcookies = new Vector(2);\r
+ if ( sc != null ) {\r
+ // FIXME Eouf corse, it's broken\r
+ for (int i = 0 ; i < sc.length ; i++)\r
+ setcookies.addElement(sc[i]);\r
+ }\r
+ }\r
+\r
+}\r