1 2 3 /* 4 * The contents of this file are subject to the terms 5 * of the Common Development and Distribution License 6 * (the "License"). You may not use this file except 7 * in compliance with the License. 8 * 9 * You can obtain a copy of the license at 10 * glassfish/bootstrap/legal/CDDLv1.0.txt or 11 * https://glassfish.dev.java.net/public/CDDLv1.0.html. 12 * See the License for the specific language governing 13 * permissions and limitations under the License. 14 * 15 * When distributing Covered Code, include this CDDL 16 * HEADER in each file and include the License file at 17 * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable, 18 * add the following below this CDDL HEADER, with the 19 * fields enclosed by brackets "[]" replaced with your 20 * own identifying information: Portions Copyright [yyyy] 21 * [name of copyright owner] 22 * 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * 25 * Portions Copyright Apache Software Foundation. 26 */ 27 28 package javax.servlet.http; 29 30 import java.text.MessageFormat; 31 import java.util.ResourceBundle; 32 33 /** 34 * 35 * Creates a cookie, a small amount of information sent by a servlet to 36 * a Web browser, saved by the browser, and later sent back to the server. 37 * A cookie's value can uniquely 38 * identify a client, so cookies are commonly used for session management. 39 * 40 * <p>A cookie has a name, a single value, and optional attributes 41 * such as a comment, path and domain qualifiers, a maximum age, and a 42 * version number. Some Web browsers have bugs in how they handle the 43 * optional attributes, so use them sparingly to improve the interoperability 44 * of your servlets. 45 * 46 * <p>The servlet sends cookies to the browser by using the 47 * {@link HttpServletResponse#addCookie} method, which adds 48 * fields to HTTP response headers to send cookies to the 49 * browser, one at a time. The browser is expected to 50 * support 20 cookies for each Web server, 300 cookies total, and 51 * may limit cookie size to 4 KB each. 52 * 53 * <p>The browser returns cookies to the servlet by adding 54 * fields to HTTP request headers. Cookies can be retrieved 55 * from a request by using the {@link HttpServletRequest#getCookies} method. 56 * Several cookies might have the same name but different path attributes. 57 * 58 * <p>Cookies affect the caching of the Web pages that use them. 59 * HTTP 1.0 does not cache pages that use cookies created with 60 * this class. This class does not support the cache control 61 * defined with HTTP 1.1. 62 * 63 * <p>This class supports both the Version 0 (by Netscape) and Version 1 64 * (by RFC 2109) cookie specifications. By default, cookies are 65 * created using Version 0 to ensure the best interoperability. 66 * 67 * 68 * @author Various 69 */ 70 71 // XXX would implement java.io.Serializable too, but can't do that 72 // so long as sun.servlet.* must run on older JDK 1.02 JVMs which 73 // don't include that support. 74 75 public class Cookie implements Cloneable { 76 77 private static final String LSTRING_FILE = 78 "javax.servlet.http.LocalStrings"; 79 private static ResourceBundle lStrings = 80 ResourceBundle.getBundle(LSTRING_FILE); 81 82 // 83 // The value of the cookie itself. 84 // 85 86 private String name; // NAME= ... "$Name" style is reserved 87 private String value; // value of NAME 88 89 // 90 // Attributes encoded in the header's cookie fields. 91 // 92 93 private String comment; // ;Comment=VALUE ... describes cookie's use 94 // ;Discard ... implied by maxAge < 0 95 private String domain; // ;Domain=VALUE ... domain that sees cookie 96 private int maxAge = -1; // ;Max-Age=VALUE ... cookies auto-expire 97 private String path; // ;Path=VALUE ... URLs that see the cookie 98 private boolean secure; // ;Secure ... e.g. use SSL 99 private int version = 0; // ;Version=1 ... means RFC 2109++ style 100 101 102 103 /** 104 * Constructs a cookie with a specified name and value. 105 * 106 * <p>The name must conform to RFC 2109. That means it can contain 107 * only ASCII alphanumeric characters and cannot contain commas, 108 * semicolons, or white space or begin with a $ character. The cookie's 109 * name cannot be changed after creation. 110 * 111 * <p>The value can be anything the server chooses to send. Its 112 * value is probably of interest only to the server. The cookie's 113 * value can be changed after creation with the 114 * <code>setValue</code> method. 115 * 116 * <p>By default, cookies are created according to the Netscape 117 * cookie specification. The version can be changed with the 118 * <code>setVersion</code> method. 119 * 120 * 121 * @param name a <code>String</code> specifying the name of the cookie 122 * 123 * @param value a <code>String</code> specifying the value of the cookie 124 * 125 * @throws IllegalArgumentException if the cookie name contains illegal characters 126 * (for example, a comma, space, or semicolon) 127 * or it is one of the tokens reserved for use 128 * by the cookie protocol 129 * @see #setValue 130 * @see #setVersion 131 * 132 */ 133 134 public Cookie(String name, String value) { 135 if (!isToken(name) 136 || name.equalsIgnoreCase("Comment") // rfc2019 137 || name.equalsIgnoreCase("Discard") // 2019++ 138 || name.equalsIgnoreCase("Domain") 139 || name.equalsIgnoreCase("Expires") // (old cookies) 140 || name.equalsIgnoreCase("Max-Age") // rfc2019 141 || name.equalsIgnoreCase("Path") 142 || name.equalsIgnoreCase("Secure") 143 || name.equalsIgnoreCase("Version") 144 || name.startsWith("$") 145 ) { 146 String errMsg = lStrings.getString("err.cookie_name_is_token"); 147 Object[] errArgs = new Object[1]; 148 errArgs[0] = name; 149 errMsg = MessageFormat.format(errMsg, errArgs); 150 throw new IllegalArgumentException(errMsg); 151 } 152 153 this.name = name; 154 this.value = value; 155 } 156 157 158 159 160 161 /** 162 * 163 * Specifies a comment that describes a cookie's purpose. 164 * The comment is useful if the browser presents the cookie 165 * to the user. Comments 166 * are not supported by Netscape Version 0 cookies. 167 * 168 * @param purpose a <code>String</code> specifying the comment 169 * to display to the user 170 * 171 * @see #getComment 172 * 173 */ 174 175 public void setComment(String purpose) { 176 comment = purpose; 177 } 178 179 180 181 182 /** 183 * Returns the comment describing the purpose of this cookie, or 184 * <code>null</code> if the cookie has no comment. 185 * 186 * @return a <code>String</code> containing the comment, 187 * or <code>null</code> if none 188 * 189 * @see #setComment 190 * 191 */ 192 193 public String getComment() { 194 return comment; 195 } 196 197 198 199 200 201 /** 202 * 203 * Specifies the domain within which this cookie should be presented. 204 * 205 * <p>The form of the domain name is specified by RFC 2109. A domain 206 * name begins with a dot (<code>.foo.com</code>) and means that 207 * the cookie is visible to servers in a specified Domain Name System 208 * (DNS) zone (for example, <code>www.foo.com</code>, but not 209 * <code>a.b.foo.com</code>). By default, cookies are only returned 210 * to the server that sent them. 211 * 212 * 213 * @param pattern a <code>String</code> containing the domain name 214 * within which this cookie is visible; 215 * form is according to RFC 2109 216 * 217 * @see #getDomain 218 * 219 */ 220 221 public void setDomain(String pattern) { 222 domain = pattern.toLowerCase(); // IE allegedly needs this 223 } 224 225 226 227 228 229 /** 230 * Returns the domain name set for this cookie. The form of 231 * the domain name is set by RFC 2109. 232 * 233 * @return a <code>String</code> containing the domain name 234 * 235 * @see #setDomain 236 * 237 */ 238 239 public String getDomain() { 240 return domain; 241 } 242 243 244 245 246 /** 247 * Sets the maximum age of the cookie in seconds. 248 * 249 * <p>A positive value indicates that the cookie will expire 250 * after that many seconds have passed. Note that the value is 251 * the <i>maximum</i> age when the cookie will expire, not the cookie's 252 * current age. 253 * 254 * <p>A negative value means 255 * that the cookie is not stored persistently and will be deleted 256 * when the Web browser exits. A zero value causes the cookie 257 * to be deleted. 258 * 259 * @param expiry an integer specifying the maximum age of the 260 * cookie in seconds; if negative, means 261 * the cookie is not stored; if zero, deletes 262 * the cookie 263 * 264 * 265 * @see #getMaxAge 266 * 267 */ 268 269 public void setMaxAge(int expiry) { 270 maxAge = expiry; 271 } 272 273 274 275 276 /** 277 * Returns the maximum age of the cookie, specified in seconds, 278 * By default, <code>-1</code> indicating the cookie will persist 279 * until browser shutdown. 280 * 281 * 282 * @return an integer specifying the maximum age of the 283 * cookie in seconds; if negative, means 284 * the cookie persists until browser shutdown 285 * 286 * 287 * @see #setMaxAge 288 * 289 */ 290 291 public int getMaxAge() { 292 return maxAge; 293 } 294 295 296 297 298 /** 299 * Specifies a path for the cookie 300 * to which the client should return the cookie. 301 * 302 * <p>The cookie is visible to all the pages in the directory 303 * you specify, and all the pages in that directory's subdirectories. 304 * A cookie's path must include the servlet that set the cookie, 305 * for example, <i>/catalog</i>, which makes the cookie 306 * visible to all directories on the server under <i>/catalog</i>. 307 * 308 * <p>Consult RFC 2109 (available on the Internet) for more 309 * information on setting path names for cookies. 310 * 311 * 312 * @param uri a <code>String</code> specifying a path 313 * 314 * 315 * @see #getPath 316 * 317 */ 318 319 public void setPath(String uri) { 320 path = uri; 321 } 322 323 324 325 326 /** 327 * Returns the path on the server 328 * to which the browser returns this cookie. The 329 * cookie is visible to all subpaths on the server. 330 * 331 * 332 * @return a <code>String</code> specifying a path that contains 333 * a servlet name, for example, <i>/catalog</i> 334 * 335 * @see #setPath 336 * 337 */ 338 339 public String getPath() { 340 return path; 341 } 342 343 344 345 346 347 /** 348 * Indicates to the browser whether the cookie should only be sent 349 * using a secure protocol, such as HTTPS or SSL. 350 * 351 * <p>The default value is <code>false</code>. 352 * 353 * @param flag if <code>true</code>, sends the cookie from the browser 354 * to the server only when using a secure protocol; 355 * if <code>false</code>, sent on any protocol 356 * 357 * @see #getSecure 358 * 359 */ 360 361 public void setSecure(boolean flag) { 362 secure = flag; 363 } 364 365 366 367 368 /** 369 * Returns <code>true</code> if the browser is sending cookies 370 * only over a secure protocol, or <code>false</code> if the 371 * browser can send cookies using any protocol. 372 * 373 * @return <code>true</code> if the browser uses a secure protocol; 374 * otherwise, <code>true</code> 375 * 376 * @see #setSecure 377 * 378 */ 379 380 public boolean getSecure() { 381 return secure; 382 } 383 384 385 386 387 388 /** 389 * Returns the name of the cookie. The name cannot be changed after 390 * creation. 391 * 392 * @return a <code>String</code> specifying the cookie's name 393 * 394 */ 395 396 public String getName() { 397 return name; 398 } 399 400 401 402 403 404 /** 405 * 406 * Assigns a new value to a cookie after the cookie is created. 407 * If you use a binary value, you may want to use BASE64 encoding. 408 * 409 * <p>With Version 0 cookies, values should not contain white 410 * space, brackets, parentheses, equals signs, commas, 411 * double quotes, slashes, question marks, at signs, colons, 412 * and semicolons. Empty values may not behave the same way 413 * on all browsers. 414 * 415 * @param newValue a <code>String</code> specifying the new value 416 * 417 * 418 * @see #getValue 419 * @see Cookie 420 * 421 */ 422 423 public void setValue(String newValue) { 424 value = newValue; 425 } 426 427 428 429 430 /** 431 * Returns the value of the cookie. 432 * 433 * @return a <code>String</code> containing the cookie's 434 * present value 435 * 436 * @see #setValue 437 * @see Cookie 438 * 439 */ 440 441 public String getValue() { 442 return value; 443 } 444 445 446 447 448 /** 449 * Returns the version of the protocol this cookie complies 450 * with. Version 1 complies with RFC 2109, 451 * and version 0 complies with the original 452 * cookie specification drafted by Netscape. Cookies provided 453 * by a browser use and identify the browser's cookie version. 454 * 455 * 456 * @return 0 if the cookie complies with the 457 * original Netscape specification; 1 458 * if the cookie complies with RFC 2109 459 * 460 * @see #setVersion 461 * 462 */ 463 464 public int getVersion() { 465 return version; 466 } 467 468 469 470 471 /** 472 * Sets the version of the cookie protocol this cookie complies 473 * with. Version 0 complies with the original Netscape cookie 474 * specification. Version 1 complies with RFC 2109. 475 * 476 * <p>Since RFC 2109 is still somewhat new, consider 477 * version 1 as experimental; do not use it yet on production sites. 478 * 479 * 480 * @param v 0 if the cookie should comply with 481 * the original Netscape specification; 482 * 1 if the cookie should comply with RFC 2109 483 * 484 * @see #getVersion 485 * 486 */ 487 488 public void setVersion(int v) { 489 version = v; 490 } 491 492 // Note -- disabled for now to allow full Netscape compatibility 493 // from RFC 2068, token special case characters 494 // 495 // private static final String tspecials = "()<>@,;:\\\"/[]?={} \t"; 496 497 private static final String tspecials = ",; "; 498 499 500 501 502 /* 503 * Tests a string and returns true if the string counts as a 504 * reserved token in the Java language. 505 * 506 * @param value the <code>String</code> to be tested 507 * 508 * @return <code>true</code> if the <code>String</code> is 509 * a reserved token; <code>false</code> 510 * if it is not 511 */ 512 513 private boolean isToken(String value) { 514 int len = value.length(); 515 516 for (int i = 0; i < len; i++) { 517 char c = value.charAt(i); 518 519 if (c < 0x20 || c >= 0x7f || tspecials.indexOf(c) != -1) 520 return false; 521 } 522 return true; 523 } 524 525 526 527 528 529 530 /** 531 * 532 * Overrides the standard <code>java.lang.Object.clone</code> 533 * method to return a copy of this cookie. 534 * 535 * 536 */ 537 538 public Object clone() { 539 try { 540 return super.clone(); 541 } catch (CloneNotSupportedException e) { 542 throw new RuntimeException(e.getMessage()); 543 } 544 } 545 } 546