| 1 16 package org.mortbay.http; 17 18 import java.io.IOException ; 19 import java.io.InputStream ; 20 import java.io.Writer ; 21 import java.net.InetAddress ; 22 import java.security.Principal ; 23 import java.util.Collections ; 24 import java.util.Enumeration ; 25 import java.util.List ; 26 import java.util.ListIterator ; 27 import java.util.Map ; 28 import java.util.Set ; 29 30 import javax.print.URIException ; 31 import javax.servlet.http.Cookie ; 32 33 import org.apache.commons.logging.Log; 34 import org.mortbay.log.LogFactory; 35 import org.mortbay.util.ByteArrayOutputStream2; 36 import org.mortbay.util.IO; 37 import org.mortbay.util.InetAddrPort; 38 import org.mortbay.util.LazyList; 39 import org.mortbay.util.LineInput; 40 import org.mortbay.util.LogSupport; 41 import org.mortbay.util.MultiMap; 42 import org.mortbay.util.QuotedStringTokenizer; 43 import org.mortbay.util.StringMap; 44 import org.mortbay.util.StringUtil; 45 import org.mortbay.util.TypeUtil; 46 import org.mortbay.util.URI; 47 import org.mortbay.util.UrlEncoded; 48 49 50 61 public class HttpRequest extends HttpMessage 62 { 63 private static Log log = LogFactory.getLog(HttpRequest.class); 64 65 66 69 public static final String __GET = "GET", __POST = "POST", __HEAD = "HEAD", __PUT = "PUT", 70 __OPTIONS = "OPTIONS", __DELETE = "DELETE", __TRACE = "TRACE", __CONNECT = "CONNECT", 71 __MOVE = "MOVE"; 72 73 74 78 public static int __maxFormContentSize = Integer.getInteger( 79 "org.mortbay.http.HttpRequest.maxFormContentSize", 200000).intValue(); 80 81 82 85 public static int __maxLineLength = 4096; 86 87 public static final StringMap __methodCache = new StringMap(true); 88 public static final StringMap __versionCache = new StringMap(true); 89 static 90 { 91 __methodCache.put(__GET, null); 92 __methodCache.put(__POST, null); 93 __methodCache.put(__HEAD, null); 94 __methodCache.put(__PUT, null); 95 __methodCache.put(__OPTIONS, null); 96 __methodCache.put(__DELETE, null); 97 __methodCache.put(__TRACE, null); 98 __methodCache.put(__CONNECT, null); 99 __methodCache.put(__MOVE, null); 100 101 __versionCache.put(__HTTP_1_1, null); 102 __versionCache.put(__HTTP_1_0, null); 103 __versionCache.put(__HTTP_0_9, null); 104 } 105 106 private static Cookie [] __noCookies = new Cookie [0]; 107 108 109 private String _method = null; 110 private URI _uri = null; 111 private String _host; 112 private String _hostPort; 113 private int _port; 114 private List _te; 115 private MultiMap _parameters; 116 private boolean _paramsExtracted; 117 private boolean _handled; 118 private Cookie [] _cookies; 119 private String [] _lastCookies; 120 private boolean _cookiesExtracted; 121 private long _timeStamp; 122 private String _timeStampStr; 123 private Principal _userPrincipal; 124 private String _authUser; 125 private String _authType; 126 private char[] _uriExpanded; 127 128 129 132 public HttpRequest() 133 { 134 } 135 136 137 142 public HttpRequest(HttpConnection connection) 143 { 144 super(connection); 145 } 146 147 148 153 public String getTimeStampStr() 154 { 155 if (_timeStampStr == null && _timeStamp > 0) 156 _timeStampStr = HttpFields.__dateCache.format(_timeStamp); 157 return _timeStampStr; 158 } 159 160 161 166 public long getTimeStamp() 167 { 168 return _timeStamp; 169 } 170 171 172 public void setTimeStamp(long ts) 173 { 174 _timeStamp = ts; 175 } 176 177 178 181 public HttpResponse getResponse() 182 { 183 return getHttpResponse(); 184 } 185 186 187 192 public HttpResponse getHttpResponse() 193 { 194 if (_connection == null) return null; 195 return _connection.getResponse(); 196 } 197 198 199 205 public boolean isHandled() 206 { 207 if (_handled) return true; 208 209 HttpResponse response = getHttpResponse(); 210 return (response != null && response.getState() != HttpMessage.__MSG_EDITABLE); 211 } 212 213 214 219 public void setHandled(boolean handled) 220 { 221 _handled = handled; 222 } 223 224 225 231 public void readHeader(LineInput in) throws IOException  232 { 233 _state = __MSG_BAD; 234 235 org.mortbay.util.LineInput.LineBuffer line_buffer; 237 238 do 239 { 240 line_buffer = in.readLineBuffer(); 241 if (line_buffer == null) throw new EOFException(); 242 } 243 while (line_buffer.size == 0); 244 245 if (line_buffer.size >= __maxLineLength) 246 throw new HttpException(HttpResponse.__414_Request_URI_Too_Large); 247 decodeRequestLine(line_buffer.buffer, line_buffer.size); 248 _timeStamp = System.currentTimeMillis(); 249 250 if (__HTTP_1_1.equals(_version)) 252 { 253 _dotVersion = 1; 254 _version = __HTTP_1_1; 255 _header.read(in); 256 updateMimeType(); 257 } 258 else if (__HTTP_0_9.equals(_version)) 259 { 260 _dotVersion = -1; 261 _version = __HTTP_0_9; 262 } 263 else 264 { 265 _dotVersion = 0; 266 _version = __HTTP_1_0; 267 _header.read(in); 268 updateMimeType(); 269 } 270 271 _handled = false; 272 _state = __MSG_RECEIVED; 273 } 274 275 276 279 public void writeRequestLine(Writer writer) throws IOException  280 { 281 writer.write(_method); 282 writer.write(' '); 283 writer.write(_uri != null ? _uri.toString() : "null"); 284 writer.write(' '); 285 writer.write(_version); 286 } 287 288 289 295 public void writeHeader(Writer writer) throws IOException  296 { 297 if (_state != __MSG_EDITABLE) throw new IllegalStateException ("Not MSG_EDITABLE"); 298 299 _state = __MSG_BAD; 300 writeRequestLine(writer); 301 writer.write(HttpFields.__CRLF); 302 _header.write(writer); 303 _state = __MSG_SENDING; 304 } 305 306 307 310 public String getRequestLine() 311 { 312 return _method + " " + _uri + " " + _version; 313 } 314 315 316 323 public String getMethod() 324 { 325 return _method; 326 } 327 328 329 public void setMethod(String method) 330 { 331 if (getState() != __MSG_EDITABLE) throw new IllegalStateException ("Not EDITABLE"); 332 _method = method; 333 } 334 335 336 public String getVersion() 337 { 338 return _version; 339 } 340 341 342 353 public StringBuffer getRootURL() 354 { 355 StringBuffer url = new StringBuffer (48); 356 synchronized (url) 357 { 358 String scheme = getScheme(); 359 int port = getPort(); 360 361 url.append(scheme); 362 url.append("://"); 363 if (_hostPort != null) 364 url.append(_hostPort); 365 else 366 { 367 url.append(getHost()); 368 if (port > 0 369 && ((scheme.equalsIgnoreCase("http") && port != 80) || (scheme 370 .equalsIgnoreCase("https") && port != 443))) 371 { 372 url.append(':'); 373 url.append(port); 374 } 375 } 376 return url; 377 } 378 } 379 380 381 396 public StringBuffer getRequestURL() 397 { 398 StringBuffer buf = getRootURL(); 399 buf.append(getPath()); 400 return buf; 401 } 402 403 404 409 public URI getURI() 410 { 411 return _uri; 412 } 413 414 415 422 public String getScheme() 423 { 424 String scheme = _uri.getScheme(); 425 if (scheme == null && _connection != null) scheme = _connection.getDefaultScheme(); 426 return scheme == null ? "http" : scheme; 427 } 428 429 430 433 public boolean isIntegral() 434 { 435 return _connection.getListener().isIntegral(_connection); 436 } 437 438 439 442 public boolean isConfidential() 443 { 444 return _connection.getListener().isConfidential(_connection); 445 } 446 447 448 454 public String getHost() 455 { 456 if (_host != null) return _host; 458 459 _host = _uri.getHost(); 461 _port = _uri.getPort(); 462 if (_host != null) return _host; 463 464 _hostPort = _header.get(HttpFields.__Host); 466 _host = _hostPort; 467 _port = 0; 468 if (_host != null && _host.length() > 0) 469 { 470 int colon = _host.lastIndexOf(':'); 471 if (colon >= 0) 472 { 473 if (colon < _host.length()) 474 { 475 try 476 { 477 _port = TypeUtil.parseInt(_host, colon + 1, -1, 10); 478 } 479 catch (Exception e) 480 { 481 LogSupport.ignore(log, e); 482 } 483 } 484 _host = _host.substring(0, colon); 485 } 486 487 return _host; 488 } 489 490 if (_connection != null) 492 { 493 _host = _connection.getServerName(); 494 _port = _connection.getServerPort(); 495 if (_host != null && !InetAddrPort.__0_0_0_0.equals(_host)) return _host; 496 } 497 498 try 500 { 501 _host = InetAddress.getLocalHost().getHostAddress(); 502 } 503 catch (java.net.UnknownHostException e) 504 { 505 LogSupport.ignore(log, e); 506 } 507 return _host; 508 } 509 510 511 517 public int getPort() 518 { 519 if (_port > 0) return _port; 520 if (_host != null) return 0; 521 if (_uri.isAbsolute()) 522 _port = _uri.getPort(); 523 else if (_connection != null) _port = _connection.getServerPort(); 524 return _port; 525 } 526 527 528 533 public String getPath() 534 { 535 return _uri.getPath(); 536 } 537 538 539 public void setPath(String path) 540 { 541 if (getState() != __MSG_EDITABLE) throw new IllegalStateException ("Not EDITABLE"); 542 if (_uri == null) 543 _uri = new URI(path); 544 else 545 _uri.setURI(path); 546 } 547 548 549 554 public String getEncodedPath() 555 { 556 return _uri.getEncodedPath(); 557 } 558 559 560 565 public String getQuery() 566 { 567 return _uri.getQuery(); 568 } 569 570 571 public void setQuery(String q) 572 { 573 if (getState() != __MSG_EDITABLE) throw new IllegalStateException ("Not EDITABLE"); 574 _uri.setQuery(q); 575 } 576 577 578 public String getRemoteAddr() 579 { 580 String addr = "127.0.0.1"; 581 HttpConnection connection = getHttpConnection(); 582 if (connection != null) 583 { 584 addr = connection.getRemoteAddr(); 585 if (addr == null) addr = connection.getRemoteHost(); 586 } 587 return addr; 588 } 589 590 591 public String getRemoteHost() 592 { 593 String host = "127.0.0.1"; 594 HttpConnection connection = getHttpConnection(); 595 if (connection != null) 596 { 597 host = connection.getRemoteHost(); 598 if (host == null) host = connection.getRemoteAddr(); 599 } 600 return host; 601 } 602 603 604 611 void decodeRequestLine(char[] buf, int len) throws IOException  612 { 613 int s1 = -1, s2 = -1, s3 = -1; 615 int state = 0; 616 startloop: for (int i = 0; i < len; i++) 617 { 618 char c = buf[i]; 619 switch (state) 620 { 621 case 0: if (c == ' ') continue; 623 state = 1; 624 s1 = i; 625 626 case 1: if (c == ' ') 628 state = 2; 629 else 630 { 631 s2 = i; 632 if (c >= 'a' && c <= 'z') buf[i] = (char) (c - 'a' + 'A'); 633 } 634 continue; 635 636 case 2: s3 = i; 638 if (c != ' ') break startloop; 639 } 640 } 641 642 int e1 = -1, e2 = -1, e3 = -1; 644 state = 0; 645 endloop: for (int i = len; i-- > 0;) 646 { 647 char c = buf[i]; 648 switch (state) 649 { 650 case 0: if (c == ' ') continue; 652 state = 1; 653 e1 = i; 654 655 case 1: if (c == ' ') 657 state = 2; 658 else 659 e2 = i; 660 continue; 661 662 case 2: e3 = i; 664 if (c != ' ') break endloop; 665 } 666 } 667 668 if (s3 < 0 || e1 < 0 || e3 < s2) 670 throw new IOException ("Bad Request: " + new String (buf, 0, len)); 671 672 Map.Entry method = __methodCache.getEntry(buf, s1, s2 - s1 + 1); 674 if (method != null) 675 _method = (String ) method.getKey(); 676 else 677 _method = new String (buf, s1, s2 - s1 + 1).toUpperCase(); 678 679 if (s2 != e3 || s3 != e2) 681 { 682 Map.Entry version = __versionCache.getEntry(buf, e2, e1 - e2 + 1); 683 if (version != null) 684 _version = (String ) version.getKey(); 685 else 686 { 687 for (int i = e2; i <= e1; i++) 688 if (buf[i] >= 'a' && buf[i] <= 'z') buf[i] = (char) (buf[i] - 'a' + 'A'); 689 _version = new String (buf, e2, e1 - e2 + 1); 690 } 691 } 692 else 693 { 694 _version = __HTTP_0_9; 696 e3 = e1; 697 } 698 699 try 701 { 702 String raw_uri =null; 703 if (URI.__CHARSET_IS_DEFAULT) 704 raw_uri = new String (buf, s3, e3 - s3 + 1); 705 else 706 { 707 int l=e3-s3+1; 708 for (int i=0;i<l;i++) 709 { 710 char c=buf[s3+i]; 711 712 if (c>=0 && c<0x80) 713 continue; 714 715 if (_uriExpanded==null || _uriExpanded.length<3*l) 716 _uriExpanded=new char[3*l]; 717 718 if (i>0) 719 System.arraycopy(buf, s3, _uriExpanded, 0, i); 720 int j=i; 721 for (;i<l;i++) 722 { 723 c=buf[s3+i]; 724 if (c>=0 && c<0x80) 725 _uriExpanded[j++]=c; 726 else 727 { 728 _uriExpanded[j++]='%'; 729 _uriExpanded[j++]=TypeUtil.toHexChar(0xf&(c>>4)); 730 _uriExpanded[j++]=TypeUtil.toHexChar(0xf&c); 731 } 732 } 733 raw_uri=new String (_uriExpanded, 0, j); 734 } 735 736 if (raw_uri==null) 737 raw_uri = new String (buf, s3, e3 - s3 + 1); 738 } 739 740 if (_uri == null) 741 _uri = new URI(raw_uri); 742 else 743 _uri.setURI(raw_uri); 744 } 745 catch (IllegalArgumentException e) 746 { 747 LogSupport.ignore(log, e); 748 throw new HttpException(HttpResponse.__400_Bad_Request, 749 new String (buf, s3, e3 - s3 + 1)); 750 } 751 } 752 753 754 761 Object forceRemoveField(String name) 762 { 763 int saved_state = _state; 764 try 765 { 766 _state = __MSG_EDITABLE; 767 return removeField(name); 768 } 769 finally 770 { 771 _state = saved_state; 772 } 773 } 774 775 776 786 public List getAcceptableTransferCodings() 787 { 788 if (_dotVersion < 1) return null; 789 if (_te != null) return _te; 790 791 Enumeration tenum = getFieldValues(HttpFields.__TE, HttpFields.__separators); 793 794 if (tenum != null) 795 { 796 List te = HttpFields.qualityList(tenum); 798 int size = te.size(); 799 if (size > 0) 801 { 802 Object acceptable = null; 803 804 ListIterator iter = te.listIterator(); 806 while (iter.hasNext()) 807 { 808 String coding = StringUtil.asciiToLowerCase(HttpFields.valueParameters(iter 809 .next().toString(), null)); 810 811 if (!HttpFields.__Chunked.equalsIgnoreCase(coding)) 812 { 813 acceptable = LazyList.ensureSize(acceptable, size); 814 acceptable = LazyList.add(acceptable, coding); 815 } 816 } 817 _te = LazyList.getList(acceptable); 818 } 819 else 820 _te = Collections.EMPTY_LIST; 821 } 822 else 823 _te = Collections.EMPTY_LIST; 824 825 return _te; 826 } 827 828 829 832 private void extractParameters() 833 { 834 if (_paramsExtracted) return; 835 _paramsExtracted = true; 836 837 if (_parameters == null) _parameters = new MultiMap(16); 838 839 String encoding = getCharacterEncoding(); 841 if (encoding == null) 842 { 843 _uri.putParametersTo(_parameters); 844 } 845 else 846 { 847 String query = _uri.getQuery(); 849 if (query != null) UrlEncoded.decodeTo(query, _parameters, encoding); 850 } 851 852 if (_state == __MSG_RECEIVED) 854 { 855 String content_type = getField(HttpFields.__ContentType); 856 &n
|