1 package com.quadcap.http.server22; 2 3 40 41 import java.util.Collections ; 42 import java.util.Comparator ; 43 import java.util.Date ; 44 import java.util.Enumeration ; 45 import java.util.Hashtable ; 46 import java.util.Locale ; 47 import java.util.Vector ; 48 49 import java.io.BufferedReader ; 50 import java.io.ByteArrayInputStream ; 51 import java.io.IOException ; 52 import java.io.InputStream ; 53 import java.io.InputStreamReader ; 54 import java.io.PushbackInputStream ; 55 56 import java.net.InetAddress ; 57 58 import java.text.DateFormat ; 59 60 import java.security.Principal ; 61 62 import javax.servlet.RequestDispatcher ; 63 import javax.servlet.ServletInputStream ; 64 import javax.servlet.http.Cookie ; 65 import javax.servlet.http.HttpServletRequest ; 66 import javax.servlet.http.HttpSession ; 67 68 import com.quadcap.http.util.HeaderParser; 69 70 import com.quadcap.util.Debug; 71 import com.quadcap.util.Util; 72 73 import com.quadcap.io.URLDecodeInputStream; 74 75 import com.quadcap.util.text.OctetMap; 76 import com.quadcap.util.text.Scanner; 77 78 79 85 public class HttpRequest implements HttpServletRequest { 86 WebWorker w; 87 HttpResponse res; 88 HttpInputStream his; 89 HttpDispatcher rd; 90 HSession session = null; 91 BufferedReader reader = null; 92 93 Scanner scanner; 94 static OctetMap mapM = new OctetMap('&'); 95 static { 96 mapM.include('\r'); 97 mapM.include('\n'); 98 } 99 static OctetMap mapE = new OctetMap('='); 100 static OctetMap mapQuote = new OctetMap('"'); 101 102 String method = null; 103 String uri = null; 104 String pathInfo = null; 105 String queryString = null; 106 int queryStringStart = 0; 107 int queryStringLen = 0; 108 String protocol = null; 109 byte[] headers = new byte[4096]; 110 int[] hOffsets = new int[32]; 111 Hashtable parameters = new Hashtable (); 112 Hashtable attributes = null; 113 boolean getInputStreamCalled = false; 114 boolean getReaderCalled = false; 115 116 static DateFormat dateFormat = DateFormat.getInstance(); 117 118 static final int CR = '\r'; 119 120 Cookie [] cookies = null; 121 boolean badRequest = false; 122 123 static final String methodGET = "GET"; 124 static final String methodHEAD = "HEAD"; 125 static final String methodPOST = "POST"; 126 127 static final String proto_09 = "HTTP/0.9"; 128 static final String proto_10 = "HTTP/1.0"; 129 static final String proto_11 = "HTTP/1.1"; 130 131 137 public HttpRequest(WebWorker w) { 138 this.w = w; 139 this.scanner = new Scanner(null); 140 } 141 142 145 public void reset(HttpInputStream is) throws IOException { 146 this.his = is; 149 parameters.clear(); 150 attributes = null; 151 method = null; 152 uri = null; 153 pathInfo = null; 154 queryString = null; 155 protocol = null; 156 reader = null; 157 session = null; 158 rd = null; 159 cookies = null; 160 queryStringStart = 0; 161 getInputStreamCalled = false; 162 getReaderCalled = false; 163 164 int hsize = is.getInputStream().readHeaders(headers, hOffsets); 166 int lim = hOffsets[1]; 169 int pos = 0; 170 while (headers[pos] == '\r' || headers[pos] == '\n') pos++; 171 int start = pos; 172 while (headers[pos] != ' ' && pos < lim) pos++; 173 174 final byte b1 = headers[start]; 175 if (b1 == 'G') { 176 if (headers[start+1] == 'E') { 177 if (headers[start+2] == 'T') { 178 method = methodGET; 179 } 180 } 181 } else if (b1 == 'P') { 182 if (headers[start+1] == 'O') { 183 if (headers[start+2] == 'S') { 184 if (headers[start+3] == 'T') { 185 method = methodPOST; 186 } 187 } 188 } 189 } else if (b1 == 'H') { 190 if (headers[start+1] == 'E') { 191 if (headers[start+2] == 'A') { 192 if (headers[start+3] == 'D') { 193 method = methodHEAD; 194 } 195 } 196 } 197 } 198 if (method == null) { 199 method = new String (headers, start, pos - start); 200 if (method.equalsIgnoreCase("get")) { 201 method = methodGET; 202 } else if (method.equalsIgnoreCase("post")) { 203 method = methodPOST; 204 } else if (method.equalsIgnoreCase("head")) { 205 method = methodHEAD; 206 } 207 } 208 209 while (headers[pos] == ' ' && pos < lim) pos++; 211 start = pos; 212 while (headers[pos] != ' ' && headers[pos] != '?' && pos < lim) pos++; 213 uri = new String (headers, start, pos - start); 214 if (headers[pos] == '?') { 216 start = ++pos; 217 while (headers[pos] != ' ' && headers[pos] != '\r'&& pos < lim) { 218 pos++; 219 } 220 queryStringStart = start; 221 queryStringLen = pos - start; 222 parseParameters(parameters, 223 new ByteArrayInputStream (headers, start, 224 pos-start)); 225 226 } 227 while (headers[pos] == ' ' && pos < lim) pos++; 228 start = pos; 229 if (pos < lim) { 230 for (byte c = headers[pos]; 231 c != '\r' && c != '\n' && c != ' '; 232 c = headers[pos]) { 233 if (++pos >= lim) break; 234 } 235 } 236 protocol = proto_10; 237 try { 238 if (headers[pos-1] == '0') { 239 protocol = proto_10; 240 } else if (headers[pos-1] == '1') { 241 protocol = proto_11; 242 } 243 if (protocol == null) { 244 protocol = new String (headers, start, pos - start); 245 } 246 } catch (Throwable t) {} 247 249 int cl = getContentLength(); 250 if (cl >= 0) { 251 is.setContentLength(cl); 252 } 253 } 254 255 final void maybeParsePostData() { 256 if (!getReaderCalled && !getInputStreamCalled && 257 method == methodPOST) { 258 String type = getContentType(); 259 if (type != null && 260 type.equals("application/x-www-form-urlencoded")) 261 { 262 scanner.reset(his); 263 parseParameters(parameters, scanner); 264 } 265 } 266 } 267 268 boolean badRequest() { return badRequest; } 269 270 public void setURI(String s) { 271 try { 272 Scanner scanner = 273 new Scanner(new ByteArrayInputStream (s.getBytes())); 274 this.uri = scanner.parseWhile(OctetMap.uriChars); 275 if (scanner.peek() == '?') { 276 scanner.matchChar('?'); 277 queryString = scanner.parseWhile(OctetMap.uriChars); 278 parseParameters(parameters, 279 new ByteArrayInputStream (queryString.getBytes())); 280 } else { 281 queryString = ""; 282 } 283 } catch (IOException e) {} 284 } 285 286 289 290 294 public int getContentLength() { 295 String s = getHeader("Content-Length"); 296 if (s == null) return -1; 297 try { 298 return Integer.parseInt(s); 299 } catch (Exception e) { 300 return -1; 301 } 302 } 303 304 308 public String getContentType() { 309 return getHeader("Content-Type"); 310 } 311 312 317 public String getProtocol() { 318 return protocol; 319 } 320 321 328 public String getScheme() { 329 return "HTTP"; 330 } 331 332 336 public String getServerName() { 337 return w.getHostName(); 338 } 339 340 344 public int getServerPort() { 345 return w.getPort(); 346 } 347 348 352 public String getRemoteAddr() { 353 return w.getRemoteAddr(); 354 } 355 356 360 public String getRemoteHost() { 361 return w.getRemoteHost(); 362 } 363 364 375 public String getRealPath(String path) { 376 WebApplication app = rd.getContext(); 377 return app.getRealPath(path); 378 } 379 380 387 public ServletInputStream getInputStream() throws IOException { 388 if (getReaderCalled) { 389 throw new IllegalStateException ("getReader() already called"); 390 } 391 getInputStreamCalled = true; 392 return w.getHttpInputStream(); 393 } 394 395 410 public String getParameter(String name) { 411 maybeParsePostData(); 412 String [] s = (String [])parameters.get(name); 413 if (s == null) return null; 414 return s[0]; 415 } 416 417 426 public String [] getParameterValues(String name) { 427 maybeParsePostData(); 428 String [] ret =(String [])parameters.get(name); 429 return ret; 430 } 431 432 439 public Enumeration getParameterNames() { 440 maybeParsePostData(); 441 return parameters.keys(); 442 } 443 444 450 public Object getAttribute(String name) { 451 Object obj = null; 452 if (attributes != null) obj = attributes.get(name); 453 return obj; 454 } 455 456 462 public void setAttribute(String name, Object obj) { 463 if (attributes == null) attributes = new Hashtable (); 464 attributes.put(name, obj); 465 } 466 467 470 public Enumeration getAttributeNames() { 471 if (attributes == null) return new Vector ().elements(); 472 return attributes.keys(); 473 } 474 475 478 public void removeAttribute(String name) { 479 attributes.remove(name); 480 } 481 482 493 public BufferedReader getReader() throws IOException { 494 if (getInputStreamCalled) { 495 throw new IllegalStateException ("getInputStream() already called"); 496 } 497 if (reader == null) { 498 reader = 499 new BufferedReader (new InputStreamReader (getInputStream())); 500 } 501 getReaderCalled = true; 502 return reader; 503 } 504 505 508 public String getCharacterEncoding () { 509 String s = getContentType(); 510 if (s == null) return null; 511 512 int idx = s.indexOf(';'); 513 while (idx > 0) { 514 s = s.substring(idx+1).trim(); 515 idx = s.indexOf(';'); 516 String c = s; 517 if (idx > 0) { 518 c = s.substring(0, idx).trim(); 519 } 520 if (c.startsWith("charset=")) { 521 return c.substring(8); 522 } 523 } 524 return null; 525 } 526 527 530 531 536 public Cookie [] getCookies() { 537 if (cookies == null) { 538 CookieParser cp = new CookieParser(getHeader("Cookie")); 539 try { 540 cookies = cp.parseCookies(); 541 } catch (IOException e) { 542 Debug.print(e); 543 cookies = new Cookie [0]; 544 } 545 } 546 return cookies; 547 } 548 549 555 public String getMethod() { 556 return method; 557 } 558 559 581 public String getRequestURI() { 582 return uri; 583 } 584 585 592 public String getServletPath() { 593 return rd.getServletPath(); 594 } 595 596 605 public String getPathInfo() { 606 return rd.getPathInfo(); 607 } 608 609 618 public String getPathTranslated() { 619 return null; 620 } 621 622 629 public String getQueryString() { 630 if (queryString == null) { 631 if (queryStringStart > 0) { 632 queryString = new String (headers, queryStringStart, 633 (queryStringLen)); 634 } 635 } 636 return queryString; 637 } 638 639 648 public String getRemoteUser() { 649 return null; 650 } 651 652 658 public String getAuthType() { 659 return null; 660 } 661 662 671 public String getHeader(String name) { 672 String ret = null; 673 int hcnt = hOffsets[0]; 674 for (int i = 1; i < hcnt; i++) { 675 int off = hOffsets[i]; 676 int lim = hOffsets[i+1]; 677 int pos = off; 678 while (headers[pos] != ':' && pos < lim) pos++; 679 String hdr = new String (headers, off, pos - off); 680 if (name.equalsIgnoreCase(hdr)) { 681 ret = new String (headers, pos+1, lim-pos-1).trim(); 682 break; 683 } 684 } 685 return ret; 686 } 687 688 689 700 public int getIntHeader(String name) { 701 int ret = -1; 702 String val = getHeader(name); 703 if (val != null) { 704 ret = Integer.parseInt(val); 705 } 706 return ret; 707 } 708 709 720 public long getDateHeader(String name) { 721 long ret = -1; 722 String val = getHeader(name); 723 if (val != null) { 724 try { 725 synchronized (dateFormat) { 726 Date d = dateFormat.parse(val); 727 ret = d.getTime(); 728 } 729 } catch (Exception e) { 730 } 731 } 732 return ret; 733 } 734 735 743 public Enumeration getHeaders() { 744 return getHeaderNames(); 745 } 746 747 public Enumeration getHeaders(String name) { 748 Vector v = new Vector (); 749 int hcnt = hOffsets[0]; 750 for (int i = 1; i < hcnt; i++) { 751 int off = hOffsets[i]; 752 int lim = hOffsets[i+1]; 753 int pos = off; 754 while (headers[pos] != ':' && pos < lim) pos++; 755 if (name.equalsIgnoreCase(new String (headers, off, pos-off))) { 756 pos++; 757 int len = lim - pos; 758 v.addElement(new String (headers, pos, len).trim()); 759 } 760 } 761 return v.elements(); 762 } 763 764 public Enumeration getHeaderNames() { 765 Vector v = new Vector (); 766 int hcnt = hOffsets[0]; 767 for (int i = 1; i < hcnt; i++) { 768 int off = hOffsets[i]; 769 int lim = hOffsets[i+1]; 770 int pos = off; 771 while (headers[pos] != ':' && pos < lim) pos++; 772 v.addElement(new String (headers, off, pos-off)); 773 } 774 return v.elements(); 775 } 776 777 795 public HttpSession getSession(boolean create) { 796 if (session == null) { 797 WebApplication app = rd.getContext(); 798 String sessionId = getRequestedSessionId(); 799 if (sessionId != null) { 800 session = app.getSession(sessionId); 801 } else if (create) { 802 session = app.createSession(); 803 sessionId = session.getId(); 804 } 805 if (sessionId != null) { 806 Cookie c = new Cookie ("sessionId", sessionId); 807 c.setPath(getContextPath()); 808 res.addCookie(c); 809 } 810 } 811 if (session != null) session.updateLastAccess(); 812 return session; 813 } 814 815 821 public HttpSession getSession() { 822 return getSession(true); 823 } 824 825 835 public String getRequestedSessionId() { 836 String sessionId = null; 837 getCookies(); 838 WebApplication app = rd.getContext(); 839 boolean foundSession = false; 840 for (int i = 0; i < cookies.length; i++) { 841 Cookie c = cookies[i]; 842 if (c.getName().equals("sessionId")) { 843 sessionId = c.getValue(); 844 if (app.getSession(sessionId) != null) { 845 foundSession = true; 846 break; 847 } 850 } 851 } 852 if (sessionId != null && !foundSession) { 853 sessionId = app.createSession().getId(); 854 } 855 return sessionId; 856 } 857 858 868 public boolean isRequestedSessionIdValid() { 869 HSession sess = null; 870 String sessionId = getRequestedSessionId(); 871 if (sessionId != null) { 872 sess = rd.getContext().getSession(sessionId); 873 } 874 return (sess != null && sess.isValid()); 875 } 876 877 886 public boolean isRequestedSessionIdFromCookie() { 887 return true; 888 } 889 890 899 public boolean isRequestedSessionIdFromURL() { 900 return false; 901 } 902 public boolean isRequestedSessionIdFromUrl() { 903 return false; 904 } 905 906 909 910 911 917 String getToken(OctetMap map) throws IOException { 918 scanner.skipWhile(OctetMap.wsChars); 919 return scanner.parseWhile(map); 920 } 921 922 static OctetMap versionMap = new OctetMap("HhTtPp/1.0"); 923 924 931 String parseHttpVersion() throws IOException { 932 scanner.skipWhile(OctetMap.wsChars); 933 return scanner.parseWhile(versionMap); 934 } 935 936 static final String urlDecode(String s) { 937 StringBuffer sb = null; 938 for (int i = 0; i < s.length(); i++) { 939 char c = s.charAt(i); 940 switch (c) { 941 case '+': 942 if (sb == null) sb = new StringBuffer (s.substring(0, i)); 943 sb.append(' '); 944 break; 945 case '%': 946 if (sb == null) sb = new StringBuffer (s.substring(0, i)); 947 try { 948 sb.append((char) Integer.parseInt(s.substring(i+1, i+3), 949 16)); 950 i += 2; 951 } catch (NumberFormatException e) { 952 throw new IllegalArgumentException (); 953 } catch (StringIndexOutOfBoundsException e) { 954 String rest = s.substring(i); 955 sb.append(rest); 956 if (rest.length()==2) i++; 957 } 958 break; 959 default: 960 if (sb != null) sb.append(c); 961 } 962 } 963 return sb == null ? s : sb.toString(); 964 } 965 966 973 public static void parseParameters(Hashtable params, InputStream is) { 974 parseParameters(params, new Scanner(is)); 975 } 976 977 public static void parseParameters(Hashtable params, Scanner s) { 978 try { 979 do { 980 String name = urlDecode(s.parseUntil(mapE)); 981 s.matchChar('='); 982 String val = urlDecode(s.parseUntil(mapM)); 983 String [] vals = (String [])params.get(name); 984 if (vals == null) { 985 vals = new String [1]; 986 } else { 987 String [] oldvals = vals; 988 vals = new String [vals.length+1]; 989 for (int i = 0; i < oldvals.length; i++) { 990 vals[i] = oldvals[i]; 991 } 992 } 993 vals[vals.length-1] = val; 994 params.put(name, vals); 995 s.matchChar('&'); 996 } while (s.peek() >= 0); 997 } catch (IOException e) { 998 } 999 } 1000 1001 1007 void setResponse(HttpResponse res) { this.res = res; } 1008 1009 1013 public String getContextPath() { 1014 return rd.getContextPath(); 1015 } 1016 1017 1021 public boolean isUserInRole(String role) { 1022 return false; } 1024 1025 1029 public Principal getUserPrincipal() { 1030 return null; } 1032 1033 1038 public Locale getLocale() { 1039 Locale locale = null; 1040 String accept = getHeader("Accept-Language"); 1041 if (accept != null) { 1042 int idx = accept.indexOf(','); 1043 if (idx > 0) { 1044 accept = accept.substring(0, idx).trim(); 1045 } 1046 locale = makeLocale(accept); 1047 } else { 1048 locale = Locale.getDefault(); 1049 } 1050 return locale; 1051 } 1052 1053 final Locale makeLocale(String s) { 1054 int idx = s.indexOf(';'); 1055 if (idx > 0) { 1056 s = s.substring(0, idx).trim(); 1057 } 1058 idx = s.indexOf('-'); 1059 String lang = null; 1060 String country = ""; 1061 if (idx > 0) { 1062 lang = s.substring(0, idx); 1063 country = s.substring(idx+1); 1064 } else { 1065 lang = s; 1066 } 1067 return new Locale (lang, country); 1068 } 1069 1070 final float getLangQual(String s) { 1071 float q = 1.0f; 1072 int idx = s.indexOf(';'); 1073 if (idx > 0) { 1074 s = s.substring(idx+1).trim(); 1075 idx = s.indexOf("q="); 1076 if (idx >= 0) { 1077 q =Float.parseFloat(s.substring(idx+2)); 1078 } 1079 } 1080 return q; 1081 } 1082 1083 final int compareAccept(String a, String b) { 1084 float aq = getLangQual(a); 1085 float bq = getLangQual(b); 1086 if (aq < bq) return -1; 1087 if (aq > bq) return 1; 1088 return 0; 1089 } 1090 1091 public Enumeration getLocales() { 1092 String accept = getHeader("Accept-Language"); 1093 if (accept == null) { 1094 Vector v = new Vector (); 1095 v.addElement(Locale.getDefault()); 1096 return v.elements(); 1097 } 1098 Vector v = Util.split(accept, ','); 1099 Comparator c = new Comparator () { 1100 public int compare(Object a, Object b) { 1101 return compareAccept(a.toString(), b.toString()); 1102 } 1103 }; 1104 Collections.sort(v, c); 1105 final Enumeration e = v.elements(); 1106 return new Enumeration () { 1107 public boolean hasMoreElements() { 1108 return e.hasMoreElements(); 1109 } 1110 public Object nextElement() { 1111 return makeLocale(e.nextElement().toString()); 1112 } 1113 }; 1114 } 1115 1116 public RequestDispatcher getRequestDispatcher(String path) { 1117 return rd.getContext().getRelativeRequestDispatcher(path, this); 1118 } 1119 1120 public boolean isSecure() { 1121 return false; 1122 } 1123 1124 final void setRequestDispatcher(HttpDispatcher rd) { 1125 this.rd = rd; 1126 } 1127 1128} 1129 | Popular Tags |