1 17 18 package org.apache.coyote.http11; 19 20 import java.io.ByteArrayInputStream ; 21 import java.io.IOException ; 22 import java.io.InterruptedIOException ; 23 import java.util.StringTokenizer ; 24 import java.util.regex.Pattern ; 25 import java.util.regex.PatternSyntaxException ; 26 import java.security.cert.CertificateFactory ; 27 import java.security.cert.X509Certificate ; 28 29 import org.apache.coyote.ActionCode; 30 import org.apache.coyote.ActionHook; 31 import org.apache.coyote.Adapter; 32 import org.apache.coyote.Request; 33 import org.apache.coyote.RequestInfo; 34 import org.apache.coyote.Response; 35 import org.apache.coyote.http11.filters.ChunkedInputFilter; 36 import org.apache.coyote.http11.filters.ChunkedOutputFilter; 37 import org.apache.coyote.http11.filters.GzipOutputFilter; 38 import org.apache.coyote.http11.filters.IdentityInputFilter; 39 import org.apache.coyote.http11.filters.IdentityOutputFilter; 40 import org.apache.coyote.http11.filters.SavedRequestInputFilter; 41 import org.apache.coyote.http11.filters.VoidInputFilter; 42 import org.apache.coyote.http11.filters.VoidOutputFilter; 43 import org.apache.coyote.http11.filters.BufferedInputFilter; 44 import org.apache.tomcat.jni.Address; 45 import org.apache.tomcat.jni.SSL; 46 import org.apache.tomcat.jni.SSLSocket; 47 import org.apache.tomcat.jni.Sockaddr; 48 import org.apache.tomcat.jni.Socket; 49 import org.apache.tomcat.util.buf.Ascii; 50 import org.apache.tomcat.util.buf.ByteChunk; 51 import org.apache.tomcat.util.buf.HexUtils; 52 import org.apache.tomcat.util.buf.MessageBytes; 53 import org.apache.tomcat.util.http.FastHttpDateFormat; 54 import org.apache.tomcat.util.http.MimeHeaders; 55 import org.apache.tomcat.util.net.AprEndpoint; 56 import org.apache.tomcat.util.net.SocketStatus; 57 import org.apache.tomcat.util.net.AprEndpoint.Handler.SocketState; 58 import org.apache.tomcat.util.res.StringManager; 59 60 61 66 public class Http11AprProcessor implements ActionHook { 67 68 69 72 protected static org.apache.commons.logging.Log log 73 = org.apache.commons.logging.LogFactory.getLog(Http11AprProcessor.class); 74 75 78 protected static StringManager sm = 79 StringManager.getManager(Constants.Package); 80 81 82 84 85 public Http11AprProcessor(int headerBufferSize, AprEndpoint endpoint) { 86 87 this.endpoint = endpoint; 88 89 request = new Request(); 90 int readTimeout = endpoint.getFirstReadTimeout(); 91 if (readTimeout == 0) { 92 readTimeout = 100; 93 } else if (readTimeout < 0) { 94 readTimeout = -1; 95 } 96 inputBuffer = new InternalAprInputBuffer(request, headerBufferSize, 97 readTimeout); 98 request.setInputBuffer(inputBuffer); 99 100 response = new Response(); 101 response.setHook(this); 102 outputBuffer = new InternalAprOutputBuffer(response, headerBufferSize); 103 response.setOutputBuffer(outputBuffer); 104 request.setResponse(response); 105 106 ssl = endpoint.isSSLEnabled(); 107 108 initializeFilters(); 109 110 int foo = HexUtils.DEC[0]; 112 113 FastHttpDateFormat.getCurrentDate(); 115 116 } 117 118 119 121 122 125 protected Adapter adapter = null; 126 127 128 131 protected Request request = null; 132 133 134 137 protected Response response = null; 138 139 140 143 protected InternalAprInputBuffer inputBuffer = null; 144 145 146 149 protected InternalAprOutputBuffer outputBuffer = null; 150 151 152 155 protected boolean error = false; 156 157 158 161 protected boolean keepAlive = true; 162 163 164 167 protected boolean http11 = true; 168 169 170 173 protected boolean http09 = false; 174 175 176 179 protected AprEndpoint.SendfileData sendfileData = null; 180 181 182 185 protected boolean comet = false; 186 187 188 192 protected boolean contentDelimitation = true; 193 194 195 198 protected boolean expectation = false; 199 200 201 204 protected Pattern [] restrictedUserAgents = null; 205 206 207 210 protected int maxKeepAliveRequests = -1; 211 212 213 216 protected boolean ssl = false; 217 218 219 222 protected long socket = 0; 223 224 225 228 protected String remoteAddr = null; 229 230 231 234 protected String remoteHost = null; 235 236 237 240 protected String localName = null; 241 242 243 244 247 protected int localPort = -1; 248 249 250 253 protected int remotePort = -1; 254 255 256 259 protected String localAddr = null; 260 261 262 265 protected int timeout = 300000; 266 267 268 271 protected boolean disableUploadTimeout = false; 272 273 274 277 protected int compressionLevel = 0; 278 279 280 283 protected int compressionMinSize = 2048; 284 285 286 289 protected int socketBuffer = -1; 290 291 292 295 protected int maxSavePostSize = 4 * 1024; 296 297 298 301 protected Pattern noCompressionUserAgents[] = null; 302 303 306 protected String [] compressableMimeTypes = 307 { "text/html", "text/xml", "text/plain" }; 308 309 310 313 protected char[] hostNameC = new char[0]; 314 315 316 319 protected AprEndpoint endpoint; 320 321 322 325 protected String server = null; 326 327 328 330 331 334 public String getCompression() { 335 switch (compressionLevel) { 336 case 0: 337 return "off"; 338 case 1: 339 return "on"; 340 case 2: 341 return "force"; 342 } 343 return "off"; 344 } 345 346 347 350 public void setCompression(String compression) { 351 if (compression.equals("on")) { 352 this.compressionLevel = 1; 353 } else if (compression.equals("force")) { 354 this.compressionLevel = 2; 355 } else if (compression.equals("off")) { 356 this.compressionLevel = 0; 357 } else { 358 try { 359 compressionMinSize = Integer.parseInt(compression); 362 this.compressionLevel = 1; 363 } catch (Exception e) { 364 this.compressionLevel = 0; 365 } 366 } 367 } 368 369 372 public void setCompressionMinSize(int compressionMinSize) { 373 this.compressionMinSize = compressionMinSize; 374 } 375 376 377 384 public void addNoCompressionUserAgent(String userAgent) { 385 try { 386 Pattern nRule = Pattern.compile(userAgent); 387 noCompressionUserAgents = 388 addREArray(noCompressionUserAgents, nRule); 389 } catch (PatternSyntaxException pse) { 390 log.error(sm.getString("http11processor.regexp.error", userAgent), pse); 391 } 392 } 393 394 395 400 public void setNoCompressionUserAgents(Pattern [] noCompressionUserAgents) { 401 this.noCompressionUserAgents = noCompressionUserAgents; 402 } 403 404 405 411 public void setNoCompressionUserAgents(String noCompressionUserAgents) { 412 if (noCompressionUserAgents != null) { 413 StringTokenizer st = new StringTokenizer (noCompressionUserAgents, ","); 414 415 while (st.hasMoreTokens()) { 416 addNoCompressionUserAgent(st.nextToken().trim()); 417 } 418 } 419 } 420 421 428 public void addCompressableMimeType(String mimeType) { 429 compressableMimeTypes = 430 addStringArray(compressableMimeTypes, mimeType); 431 } 432 433 434 439 public void setCompressableMimeTypes(String [] compressableMimeTypes) { 440 this.compressableMimeTypes = compressableMimeTypes; 441 } 442 443 444 450 public void setCompressableMimeTypes(String compressableMimeTypes) { 451 if (compressableMimeTypes != null) { 452 StringTokenizer st = new StringTokenizer (compressableMimeTypes, ","); 453 454 while (st.hasMoreTokens()) { 455 addCompressableMimeType(st.nextToken().trim()); 456 } 457 } 458 } 459 460 461 464 public String [] findCompressableMimeTypes() { 465 return (compressableMimeTypes); 466 } 467 468 469 470 472 473 478 protected void addFilter(String className) { 479 try { 480 Class clazz = Class.forName(className); 481 Object obj = clazz.newInstance(); 482 if (obj instanceof InputFilter) { 483 inputBuffer.addFilter((InputFilter) obj); 484 } else if (obj instanceof OutputFilter) { 485 outputBuffer.addFilter((OutputFilter) obj); 486 } else { 487 log.warn(sm.getString("http11processor.filter.unknown", className)); 488 } 489 } catch (Exception e) { 490 log.error(sm.getString("http11processor.filter.error", className), e); 491 } 492 } 493 494 495 501 private String [] addStringArray(String sArray[], String value) { 502 String [] result = null; 503 if (sArray == null) { 504 result = new String [1]; 505 result[0] = value; 506 } 507 else { 508 result = new String [sArray.length + 1]; 509 for (int i = 0; i < sArray.length; i++) 510 result[i] = sArray[i]; 511 result[sArray.length] = value; 512 } 513 return result; 514 } 515 516 517 523 private Pattern [] addREArray(Pattern rArray[], Pattern value) { 524 Pattern [] result = null; 525 if (rArray == null) { 526 result = new Pattern [1]; 527 result[0] = value; 528 } 529 else { 530 result = new Pattern [rArray.length + 1]; 531 for (int i = 0; i < rArray.length; i++) 532 result[i] = rArray[i]; 533 result[rArray.length] = value; 534 } 535 return result; 536 } 537 538 539 545 private boolean inStringArray(String sArray[], String value) { 546 for (int i = 0; i < sArray.length; i++) { 547 if (sArray[i].equals(value)) { 548 return true; 549 } 550 } 551 return false; 552 } 553 554 555 561 private boolean startsWithStringArray(String sArray[], String value) { 562 if (value == null) 563 return false; 564 for (int i = 0; i < sArray.length; i++) { 565 if (value.startsWith(sArray[i])) { 566 return true; 567 } 568 } 569 return false; 570 } 571 572 573 580 public void addRestrictedUserAgent(String userAgent) { 581 try { 582 Pattern nRule = Pattern.compile(userAgent); 583 restrictedUserAgents = addREArray(restrictedUserAgents, nRule); 584 } catch (PatternSyntaxException pse) { 585 log.error(sm.getString("http11processor.regexp.error", userAgent), pse); 586 } 587 } 588 589 590 595 public void setRestrictedUserAgents(Pattern [] restrictedUserAgents) { 596 this.restrictedUserAgents = restrictedUserAgents; 597 } 598 599 600 606 public void setRestrictedUserAgents(String restrictedUserAgents) { 607 if (restrictedUserAgents != null) { 608 StringTokenizer st = 609 new StringTokenizer (restrictedUserAgents, ","); 610 while (st.hasMoreTokens()) { 611 addRestrictedUserAgent(st.nextToken().trim()); 612 } 613 } 614 } 615 616 617 620 public String [] findRestrictedUserAgents() { 621 String [] sarr = new String [restrictedUserAgents.length]; 622 623 for (int i = 0; i < restrictedUserAgents.length; i++) 624 sarr[i] = restrictedUserAgents[i].toString(); 625 626 return (sarr); 627 } 628 629 630 635 public void setMaxKeepAliveRequests(int mkar) { 636 maxKeepAliveRequests = mkar; 637 } 638 639 640 643 public int getMaxKeepAliveRequests() { 644 return maxKeepAliveRequests; 645 } 646 647 648 651 public void setMaxSavePostSize(int msps) { 652 maxSavePostSize = msps; 653 } 654 655 656 659 public int getMaxSavePostSize() { 660 return maxSavePostSize; 661 } 662 663 664 667 public void setDisableUploadTimeout(boolean isDisabled) { 668 disableUploadTimeout = isDisabled; 669 } 670 671 674 public boolean getDisableUploadTimeout() { 675 return disableUploadTimeout; 676 } 677 678 681 public void setSocketBuffer(int socketBuffer) { 682 this.socketBuffer = socketBuffer; 683 outputBuffer.setSocketBuffer(socketBuffer); 684 } 685 686 689 public int getSocketBuffer() { 690 return socketBuffer; 691 } 692 693 696 public void setTimeout( int timeouts ) { 697 timeout = timeouts ; 698 } 699 700 703 public int getTimeout() { 704 return timeout; 705 } 706 707 708 711 public void setServer( String server ) { 712 if (server==null || server.equals("")) { 713 this.server = null; 714 } else { 715 this.server = server; 716 } 717 } 718 719 722 public String getServer() { 723 return server; 724 } 725 726 727 731 public Request getRequest() { 732 return request; 733 } 734 735 741 public SocketState event(SocketStatus status) 742 throws IOException { 743 744 RequestInfo rp = request.getRequestProcessor(); 745 746 try { 747 rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE); 748 error = !adapter.event(request, response, status); 749 } catch (InterruptedIOException e) { 750 error = true; 751 } catch (Throwable t) { 752 log.error(sm.getString("http11processor.request.process"), t); 753 response.setStatus(500); 755 error = true; 756 } 757 758 rp.setStage(org.apache.coyote.Constants.STAGE_ENDED); 759 760 if (error) { 761 recycle(); 762 return SocketState.CLOSED; 763 } else if (!comet) { 764 endpoint.getPoller().add(socket); 765 recycle(); 766 return SocketState.OPEN; 767 } else { 768 endpoint.getCometPoller().add(socket); 769 return SocketState.LONG; 770 } 771 } 772 773 779 public SocketState process(long socket) 780 throws IOException { 781 RequestInfo rp = request.getRequestProcessor(); 782 rp.setStage(org.apache.coyote.Constants.STAGE_PARSE); 783 784 remoteAddr = null; 786 remoteHost = null; 787 localAddr = null; 788 localName = null; 789 remotePort = -1; 790 localPort = -1; 791 792 this.socket = socket; 794 inputBuffer.setSocket(socket); 795 outputBuffer.setSocket(socket); 796 797 error = false; 799 keepAlive = true; 800 801 int keepAliveLeft = maxKeepAliveRequests; 802 long soTimeout = endpoint.getSoTimeout(); 803 804 int limit = 0; 805 if (endpoint.getFirstReadTimeout() > 0 || endpoint.getFirstReadTimeout() < -1) { 806 limit = endpoint.getMaxThreads() / 2; 807 } 808 809 boolean keptAlive = false; 810 boolean openSocket = false; 811 812 while (!error && keepAlive && !comet) { 813 814 try { 816 if( !disableUploadTimeout && keptAlive && soTimeout > 0 ) { 817 Socket.timeoutSet(socket, soTimeout * 1000); 818 } 819 if (!inputBuffer.parseRequestLine 820 (keptAlive && (endpoint.getCurrentThreadsBusy() > limit))) { 821 openSocket = true; 825 endpoint.getPoller().add(socket); 827 break; 828 } 829 request.setStartTime(System.currentTimeMillis()); 830 keptAlive = true; 831 if (!disableUploadTimeout) { 832 Socket.timeoutSet(socket, timeout * 1000); 833 } 834 inputBuffer.parseHeaders(); 835 } catch (IOException e) { 836 error = true; 837 break; 838 } catch (Throwable t) { 839 if (log.isDebugEnabled()) { 840 log.debug(sm.getString("http11processor.header.parse"), t); 841 } 842 response.setStatus(400); 844 error = true; 845 } 846 847 rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE); 849 try { 850 prepareRequest(); 851 } catch (Throwable t) { 852 if (log.isDebugEnabled()) { 853 log.debug(sm.getString("http11processor.request.prepare"), t); 854 } 855 response.setStatus(400); 857 error = true; 858 } 859 860 if (maxKeepAliveRequests > 0 && --keepAliveLeft == 0) 861 keepAlive = false; 862 863 if (!error) { 865 try { 866 rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE); 867 adapter.service(request, response); 868 if(keepAlive && !error) { error = response.getErrorException() != null || 875 statusDropsConnection(response.getStatus()); 876 } 877 } catch (InterruptedIOException e) { 878 error = true; 879 } catch (Throwable t) { 880 log.error(sm.getString("http11processor.request.process"), t); 881 response.setStatus(500); 883 error = true; 884 } 885 } 886 887 if (!comet) { 889 endRequest(); 890 } 891 892 if (error) { 895 response.setStatus(500); 896 } 897 request.updateCounters(); 898 899 if (sendfileData != null && !error) { 901 sendfileData.socket = socket; 902 sendfileData.keepAlive = keepAlive; 903 if (!endpoint.getSendfile().add(sendfileData)) { 904 openSocket = true; 905 break; 906 } 907 } 908 909 rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE); 910 911 } 912 913 rp.setStage(org.apache.coyote.Constants.STAGE_ENDED); 914 915 if (comet) { 916 if (error) { 917 recycle(); 918 return SocketState.CLOSED; 919 } else { 920 return SocketState.LONG; 921 } 922 } else { 923 recycle(); 924 return (openSocket) ? SocketState.OPEN : SocketState.CLOSED; 925 } 926 927 } 928 929 930 public void endRequest() { 931 932 try { 934 inputBuffer.endRequest(); 935 } catch (IOException e) { 936 error = true; 937 } catch (Throwable t) { 938 log.error(sm.getString("http11processor.request.finish"), t); 939 response.setStatus(500); 941 error = true; 942 } 943 try { 944 outputBuffer.endRequest(); 945 } catch (IOException e) { 946 error = true; 947 } catch (Throwable t) { 948 log.error(sm.getString("http11processor.response.finish"), t); 949 error = true; 950 } 951 952 inputBuffer.nextRequest(); 954 outputBuffer.nextRequest(); 955 956 } 957 958 959 public void recycle() { 960 inputBuffer.recycle(); 961 outputBuffer.recycle(); 962 this.socket = 0; 963 } 964 965 966 968 969 975 public void action(ActionCode actionCode, Object param) { 976 977 if (actionCode == ActionCode.ACTION_COMMIT) { 978 980 if (response.isCommitted()) 981 return; 982 983 prepareResponse(); 985 try { 986 outputBuffer.commit(); 987 } catch (IOException e) { 988 error = true; 990 } 991 992 } else if (actionCode == ActionCode.ACTION_ACK) { 993 994 996 999 if ((response.isCommitted()) || !expectation) 1000 return; 1001 1002 inputBuffer.setSwallowInput(true); 1003 try { 1004 outputBuffer.sendAck(); 1005 } catch (IOException e) { 1006 error = true; 1008 } 1009 1010 } else if (actionCode == ActionCode.ACTION_CLIENT_FLUSH) { 1011 1012 try { 1013 outputBuffer.flush(); 1014 } catch (IOException e) { 1015 error = true; 1017 response.setErrorException(e); 1018 } 1019 1020 } else if (actionCode == ActionCode.ACTION_CLOSE) { 1021 1023 1026 comet = false; 1027 try { 1028 outputBuffer.endRequest(); 1029 } catch (IOException e) { 1030 error = true; 1032 } 1033 1034 } else if (actionCode == ActionCode.ACTION_RESET) { 1035 1036 1038 1040 outputBuffer.reset(); 1041 1042 } else if (actionCode == ActionCode.ACTION_CUSTOM) { 1043 1044 1046 } else if (actionCode == ActionCode.ACTION_REQ_HOST_ADDR_ATTRIBUTE) { 1047 1048 if (remoteAddr == null && (socket != 0)) { 1050 try { 1051 long sa = Address.get(Socket.APR_REMOTE, socket); 1052 remoteAddr = Address.getip(sa); 1053 } catch (Exception e) { 1054 log.warn(sm.getString("http11processor.socket.info"), e); 1055 } 1056 } 1057 request.remoteAddr().setString(remoteAddr); 1058 1059 } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_NAME_ATTRIBUTE) { 1060 1061 if (localName == null && (socket != 0)) { 1063 try { 1064 long sa = Address.get(Socket.APR_LOCAL, socket); 1065 localName = Address.getnameinfo(sa, 0); 1066 } catch (Exception e) { 1067 log.warn(sm.getString("http11processor.socket.info"), e); 1068 } 1069 } 1070 request.localName().setString(localName); 1071 1072 } else if (actionCode == ActionCode.ACTION_REQ_HOST_ATTRIBUTE) { 1073 1074 if (remoteHost == null && (socket != 0)) { 1076 try { 1077 long sa = Address.get(Socket.APR_REMOTE, socket); 1078 remoteHost = Address.getnameinfo(sa, 0); 1079 } catch (Exception e) { 1080 log.warn(sm.getString("http11processor.socket.info"), e); 1081 } 1082 } 1083 request.remoteHost().setString(remoteHost); 1084 1085 } else if (actionCode == ActionCode.ACTION_REQ_LOCAL_ADDR_ATTRIBUTE) { 1086 1087 if (localAddr == null && (socket != 0)) { 1089 try { 1090 long sa = Address.get(Socket.APR_LOCAL, socket); 1091 localAddr = Address.getip(sa); 1092 } catch (Exception e) { 1093 log.warn(sm.getString("http11processor.socket.info"), e); 1094 } 1095 } 1096 1097 request.localAddr().setString(localAddr); 1098 1099 } else if (actionCode == ActionCode.ACTION_REQ_REMOTEPORT_ATTRIBUTE) { 1100 1101 if (remotePort == -1 && (socket != 0)) { 1103 try { 1104 long sa = Address.get(Socket.APR_REMOTE, socket); 1105 Sockaddr addr = Address.getInfo(sa); 1106 remotePort = addr.port; 1107 } catch (Exception e) { 1108 log.warn(sm.getString("http11processor.socket.info"), e); 1109 } 1110 } 1111 request.setRemotePort(remotePort); 1112 1113 } else if (actionCode == ActionCode.ACTION_REQ_LOCALPORT_ATTRIBUTE) { 1114 1115 if (localPort == -1 && (socket != 0)) { 1117 try { 1118 long sa = Address.get(Socket.APR_LOCAL, socket); 1119 Sockaddr addr = Address.getInfo(sa); 1120 localPort = addr.port; 1121 } catch (Exception e) { 1122 log.warn(sm.getString("http11processor.socket.info"), e); 1123 } 1124 } 1125 request.setLocalPort(localPort); 1126 1127 } else if (actionCode == ActionCode.ACTION_REQ_SSL_ATTRIBUTE ) { 1128 1129 if (ssl && (socket != 0)) { 1130 try { 1131 Object sslO = SSLSocket.getInfoS(socket, SSL.SSL_INFO_CIPHER); 1133 if (sslO != null) { 1134 request.setAttribute 1135 (AprEndpoint.CIPHER_SUITE_KEY, sslO); 1136 } 1137 int certLength = SSLSocket.getInfoI(socket, SSL.SSL_INFO_CLIENT_CERT_CHAIN); 1139 X509Certificate [] certs = null; 1140 if (certLength > 0) { 1141 certs = new X509Certificate [certLength]; 1142 for (int i = 0; i < certLength; i++) { 1143 byte[] data = SSLSocket.getInfoB(socket, SSL.SSL_INFO_CLIENT_CERT_CHAIN + i); 1144 CertificateFactory cf = 1145 CertificateFactory.getInstance("X.509"); 1146 ByteArrayInputStream stream = new ByteArrayInputStream (data); 1147 certs[i] = (X509Certificate ) cf.generateCertificate(stream); 1148 } 1149 } 1150 if (certs != null) { 1151 request.setAttribute 1152 (AprEndpoint.CERTIFICATE_KEY, certs); 1153 } 1154 sslO = new Integer (SSLSocket.getInfoI(socket, SSL.SSL_INFO_CIPHER_USEKEYSIZE)); 1156 if (sslO != null) { 1157 request.setAttribute 1158 (AprEndpoint.KEY_SIZE_KEY, sslO); 1159 } 1160 sslO = SSLSocket.getInfoS(socket, SSL.SSL_INFO_SESSION_ID); 1162 if (sslO != null) { 1163 request.setAttribute 1164 (AprEndpoint.SESSION_ID_KEY, sslO); 1165 } 1166 } catch (Exception e) { 1167 log.warn(sm.getString("http11processor.socket.ssl"), e); 1168 } 1169 } 1170 1171 } else if (actionCode == ActionCode.ACTION_REQ_SSL_CERTIFICATE) { 1172 1173 if (ssl && (socket != 0)) { 1174 InputFilter[] inputFilters = inputBuffer.getFilters(); 1177 ((BufferedInputFilter) inputFilters[Constants.BUFFERED_FILTER]) 1178 .setLimit(maxSavePostSize); 1179 inputBuffer.addActiveFilter 1180 (inputFilters[Constants.BUFFERED_FILTER]); 1181 try { 1182 SSLSocket.renegotiate(socket); 1184 int certLength = SSLSocket.getInfoI(socket, SSL.SSL_INFO_CLIENT_CERT_CHAIN); 1186 X509Certificate [] certs = null; 1187 if (certLength > 0) { 1188 certs = new X509Certificate [certLength]; 1189 for (int i = 0; i < certLength; i++) { 1190 byte[] data = SSLSocket.getInfoB(socket, SSL.SSL_INFO_CLIENT_CERT_CHAIN + i); 1191 CertificateFactory cf = 1192 CertificateFactory.getInstance("X.509"); 1193 ByteArrayInputStream stream = new ByteArrayInputStream (data); 1194 certs[i] = (X509Certificate ) cf.generateCertificate(stream); 1195 } 1196 } 1197 if (certs != null) { 1198 request.setAttribute 1199 (AprEndpoint.CERTIFICATE_KEY, certs); 1200 } 1201 } catch (Exception e) { 1202 log.warn(sm.getString("http11processor.socket.ssl"), e); 1203 } 1204 } 1205 1206 } else if (actionCode == ActionCode.ACTION_REQ_SET_BODY_REPLAY) { 1207 ByteChunk body = (ByteChunk) param; 1208 1209 InputFilter savedBody = new SavedRequestInputFilter(body); 1210 savedBody.setRequest(request); 1211 1212 InternalAprInputBuffer internalBuffer = (InternalAprInputBuffer) 1213 request.getInputBuffer(); 1214 internalBuffer.addActiveFilter(savedBody); 1215 1216 } else if (actionCode == ActionCode.ACTION_COMET_BEGIN) { 1217 comet = true; 1218 } else if (actionCode == ActionCode.ACTION_COMET_END) { 1219 comet = false; 1220 } 1221 1222 } 1223 1224 1225 1227 1228 1233 public void setAdapter(Adapter adapter) { 1234 this.adapter = adapter; 1235 } 1236 1237 1238 1243 public Adapter getAdapter() { 1244 return adapter; 1245 } 1246 1247 1248 1250 1251 1254 protected void prepareRequest() { 1255 1256 http11 = true; 1257 http09 = false; 1258 contentDelimitation = false; 1259 expectation = false; 1260 sendfileData = null; 1261 if (ssl) { 1262 request.scheme().setString("https"); 1263 } 1264 MessageBytes protocolMB = request.protocol(); 1265 if (protocolMB.equals(Constants.HTTP_11)) { 1266 http11 = true; 1267 protocolMB.setString(Constants.HTTP_11); 1268 } else if (protocolMB.equals(Constants.HTTP_10)) { 1269 http11 = false; 1270 keepAlive = false; 1271 protocolMB.setString(Constants.HTTP_10); 1272 } else if (protocolMB.equals("")) { 1273 http09 = true; 1275 http11 = false; 1276 keepAlive = false; 1277 } else { 1278 http11 = false; 1280 error = true; 1281 response.setStatus(505); 1283 } 1284 1285 MessageBytes methodMB = request.method(); 1286 if (methodMB.equals(Constants.GET)) { 1287 methodMB.setString(Constants.GET); 1288 } else if (methodMB.equals(Constants.POST)) { 1289 methodMB.setString(Constants.POST); 1290 } 1291 1292 MimeHeaders headers = request.getMimeHeaders(); 1293 1294 MessageBytes connectionValueMB = headers.getValue("connection"); 1296 if (connectionValueMB != null) { 1297 ByteChunk connectionValueBC = connectionValueMB.getByteChunk(); 1298 if (findBytes(connectionValueBC, Constants.CLOSE_BYTES) != -1) { 1299 keepAlive = false; 1300 } else if (findBytes(connectionValueBC, 1301 Constants.KEEPALIVE_BYTES) != -1) { 1302 keepAlive = true; 1303 } 1304 } 1305 1306 MessageBytes expectMB = null; 1307 if (http11) 1308 expectMB = headers.getValue("expect"); 1309 if ((expectMB != null) 1310 && (expectMB.indexOfIgnoreCase("100-continue", 0) != -1)) { 1311 inputBuffer.setSwallowInput(false); 1312 expectation = true; 1313 } 1314 1315 if ((restrictedUserAgents != null) && ((http11) || (keepAlive))) { 1317 MessageBytes userAgentValueMB = headers.getValue("user-agent"); 1318 if(userAgentValueMB != null) { 1321 String userAgentValue = userAgentValueMB.toString(); 1322 for (int i = 0; i < restrictedUserAgents.length; i++) { 1323 if (restrictedUserAgents[i].matcher(userAgentValue).matches()) { 1324 http11 = false; 1325 keepAlive = false; 1326 break; 1327 } 1328 } 1329 } 1330 } 1331 1332 ByteChunk uriBC = request.requestURI().getByteChunk(); 1334 if (uriBC.startsWithIgnoreCase("http", 0)) { 1335 1336 int pos = uriBC.indexOf("://", 0, 3, 4); 1337 int uriBCStart = uriBC.getStart(); 1338 int slashPos = -1; 1339 if (pos != -1) { 1340 byte[] uriB = uriBC.getBytes(); 1341 slashPos = uriBC.indexOf('/', pos + 3); 1342 if (slashPos == -1) { 1343 slashPos = uriBC.getLength(); 1344 request.requestURI().setBytes 1346 (uriB, uriBCStart + pos + 1, 1); 1347 } else { 1348 request.requestURI().setBytes 1349 (uriB, uriBCStart + slashPos, 1350 uriBC.getLength() - slashPos); 1351 } 1352 MessageBytes hostMB = headers.setValue("host"); 1353 hostMB.setBytes(uriB, uriBCStart + pos + 3, 1354 slashPos - pos - 3); 1355 } 1356 1357 } 1358 1359 InputFilter[] inputFilters = inputBuffer.getFilters(); 1361 1362 MessageBytes transferEncodingValueMB = null; 1364 if (http11) 1365 transferEncodingValueMB = headers.getValue("transfer-encoding"); 1366 if (transferEncodingValueMB != null) { 1367 String transferEncodingValue = transferEncodingValueMB.toString(); 1368 int startPos = 0; 1370 int commaPos = transferEncodingValue.indexOf(','); 1371 String encodingName = null; 1372 while (commaPos != -1) { 1373 encodingName = transferEncodingValue.substring 1374 (startPos, commaPos).toLowerCase().trim(); 1375 if (!addInputFilter(inputFilters, encodingName)) { 1376 error = true; 1378 response.setStatus(501); 1380 } 1381 startPos = commaPos + 1; 1382 commaPos = transferEncodingValue.indexOf(',', startPos); 1383 } 1384 encodingName = transferEncodingValue.substring(startPos) 1385 .toLowerCase().trim(); 1386 if (!addInputFilter(inputFilters, encodingName)) { 1387 error = true; 1389 response.setStatus(501); 1391 } 1392 } 1393 1394 long contentLength = request.getContentLengthLong(); 1396 if (contentLength >= 0 && !contentDelimitation) { 1397 inputBuffer.addActiveFilter 1398 (inputFilters[Constants.IDENTITY_FILTER]); 1399 contentDelimitation = true; 1400 } 1401 1402 MessageBytes valueMB = headers.getValue("host"); 1403 1404 if (http11 && (valueMB == null)) { 1406 error = true; 1407 response.setStatus(400); 1409 } 1410 1411 parseHost(valueMB); 1412 1413 if (!contentDelimitation) { 1414 inputBuffer.addActiveFilter 1418 (inputFilters[Constants.VOID_FILTER]); 1419 contentDelimitation = true; 1420 } 1421 1422 if (endpoint.getUseSendfile()) { 1424 request.setAttribute("org.apache.tomcat.sendfile.support", Boolean.TRUE); 1425 } 1426 request.setAttribute("org.apache.tomcat.comet.support", Boolean.TRUE); 1428 1429 } 1430 1431 1432 1435 public void parseHost(MessageBytes valueMB) { 1436 1437 if (valueMB == null || valueMB.isNull()) { 1438 request.setServerPort(endpoint.getPort()); 1442 return; 1443 } 1444 1445 ByteChunk valueBC = valueMB.getByteChunk(); 1446 byte[] valueB = valueBC.getBytes(); 1447 int valueL = valueBC.getLength(); 1448 int valueS = valueBC.getStart(); 1449 int colonPos = -1; 1450 if (hostNameC.length < valueL) { 1451 hostNameC = new char[valueL]; 1452 } 1453 1454 boolean ipv6 = (valueB[valueS] == '['); 1455 boolean bracketClosed = false; 1456 for (int i = 0; i < valueL; i++) { 1457 char b = (char) valueB[i + valueS]; 1458 hostNameC[i] = b; 1459 if (b == ']') { 1460 bracketClosed = true; 1461 } else if (b == ':') { 1462 if (!ipv6 || bracketClosed) { 1463 colonPos = i; 1464 break; 1465 } 1466 } 1467 } 1468 1469 if (colonPos < 0) { 1470 if (!ssl) { 1471 request.setServerPort(80); 1473 } else { 1474 request.setServerPort(443); 1476 } 1477 request.serverName().setChars(hostNameC, 0, valueL); 1478 } else { 1479 1480 request.serverName().setChars(hostNameC, 0, colonPos); 1481 1482 int port = 0; 1483 int mult = 1; 1484 for (int i = valueL - 1; i > colonPos; i--) { 1485 int charValue = HexUtils.DEC[(int) valueB[i + valueS]]; 1486 if (charValue == -1) { 1487 error = true; 1489 response.setStatus(400); 1491 break; 1492 } 1493 port = port + (charValue * mult); 1494 mult = 10 * mult; 1495 } 1496 request.setServerPort(port); 1497 1498 } 1499 1500 } 1501 1502 1503 1506 private boolean isCompressable() { 1507 1508 1511 1515 MessageBytes acceptEncodingMB = 1517 request.getMimeHeaders().getValue("accept-encoding"); 1518 1519 if ((acceptEncodingMB == null) 1520 || (acceptEncodingMB.indexOf("gzip") == -1)) 1521 return false; 1522 1523 MessageBytes contentEncodingMB = 1525 response.getMimeHeaders().getValue("Content-Encoding"); 1526 1527 if ((contentEncodingMB != null) 1528 && (contentEncodingMB.indexOf("gzip") != -1)) 1529 return false; 1530 1531 if (compressionLevel == 2) 1533 return true; 1534 1535 if (noCompressionUserAgents != null) { 1537 MessageBytes userAgentValueMB = 1538 request.getMimeHeaders().getValue("user-agent"); 1539 if(userAgentValueMB != null) { 1540 String userAgentValue = userAgentValueMB.toString(); 1541 1542 for (int i = 0; i < noCompressionUserAgents.length; i++) 1544 if (noCompressionUserAgents[i].matcher(userAgentValue).matches()) 1545 return false; 1546 } 1547 } 1548 1549 long contentLength = response.getContentLengthLong(); 1551 if ((contentLength == -1) 1552 || (contentLength > compressionMinSize)) { 1553 if (compressableMimeTypes != null) { 1555 return (startsWithStringArray(compressableMimeTypes, 1556 response.getContentType())); 1557 } 1558 } 1559 1560 return false; 1561 } 1562 1563 1564 1568 protected void prepareResponse() { 1569 1570 boolean entityBody = true; 1571 contentDelimitation = false; 1572 1573 OutputFilter[] outputFilters = outputBuffer.getFilters(); 1574 1575 if (http09 == true) { 1576 outputBuffer.addActiveFilter 1578 (outputFilters[Constants.IDENTITY_FILTER]); 1579 return; 1580 } 1581 1582 int statusCode = response.getStatus(); 1583 if ((statusCode == 204) || (statusCode == 205) 1584 || (statusCode == 304)) { 1585 outputBuffer.addActiveFilter 1587 (outputFilters[Constants.VOID_FILTER]); 1588 entityBody = false; 1589 contentDelimitation = true; 1590 } 1591 1592 MessageBytes methodMB = request.method(); 1593 if (methodMB.equals("HEAD")) { 1594 outputBuffer.addActiveFilter 1596 (outputFilters[Constants.VOID_FILTER]); 1597 contentDelimitation = true; 1598 } 1599 1600 if (endpoint.getUseSendfile()) { 1602 String fileName = (String ) request.getAttribute("org.apache.tomcat.sendfile.filename"); 1603 if (fileName != null) { 1604 outputBuffer.addActiveFilter 1606 (outputFilters[Constants.VOID_FILTER]); 1607 contentDelimitation = true; 1608 sendfileData = new AprEndpoint.SendfileData(); 1609 sendfileData.fileName = fileName; 1610 sendfileData.start = 1611 ((Long ) request.getAttribute("org.apache.tomcat.sendfile.start")).longValue(); 1612 sendfileData.end = 1613 ((Long ) request.getAttribute("org.apache.tomcat.sendfile.end")).longValue(); 1614 } 1615 } 1616 1617 boolean useCompression = false; 1619 if (entityBody && (compressionLevel > 0) && (sendfileData == null)) { 1620 useCompression = isCompressable(); 1621 if (useCompression) { 1623 response.setContentLength(-1); 1624 } 1625 } 1626 1627 MimeHeaders headers = response.getMimeHeaders(); 1628 if (!entityBody) { 1629 response.setContentLength(-1); 1630 } else { 1631 String contentType = response.getContentType(); 1632 if (contentType != null) { 1633 headers.setValue("Content-Type").setString(contentType); 1634 } 1635 String contentLanguage = response.getContentLanguage(); 1636 if (contentLanguage != null) { 1637 headers.setValue("Content-Language") 1638 .setString(contentLanguage); 1639 } 1640 } 1641 1642 long contentLength = response.getContentLengthLong(); 1643 if (contentLength != -1) { 1644 headers.setValue("Content-Length").setLong(contentLength); 1645 outputBuffer.addActiveFilter 1646 (outputFilters[Constants.IDENTITY_FILTER]); 1647 contentDelimitation = true; 1648 } else { 1649 if (entityBody && http11 && keepAlive) { 1650 outputBuffer.addActiveFilter 1651 (outputFilters[Constants.CHUNKED_FILTER]); 1652 contentDelimitation = true; 1653 headers.addValue(Constants.TRANSFERENCODING).setString(Constants.CHUNKED); 1654 } else { 1655 outputBuffer.addActiveFilter 1656 (outputFilters[Constants.IDENTITY_FILTER]); 1657 } 1658 } 1659 1660 if (useCompression) { 1661 outputBuffer.addActiveFilter(outputFilters[Constants.GZIP_FILTER]); 1662 headers.setValue("Content-Encoding").setString("gzip"); 1663 headers.setValue("Vary").setString("Accept-Encoding"); 1665 } 1666 1667 headers.setValue("Date").setString(FastHttpDateFormat.getCurrentDate()); 1669 1670 1672 if ((entityBody) && (!contentDelimitation)) { 1673 keepAlive = false; 1676 } 1677 1678 keepAlive = keepAlive && !statusDropsConnection(statusCode); 1681 if (!keepAlive) { 1682 headers.addValue(Constants.CONNECTION).setString(Constants.CLOSE); 1683 } else if (!http11 && !error) { 1684 headers.addValue(Constants.CONNECTION).setString(Constants.KEEPALIVE); 1685 } 1686 1687 outputBuffer.sendStatus(); 1689 1690 if (server != null) { 1692 headers.setValue("Server").setString(server); 1693 } else { 1694 outputBuffer.write(Constants.SERVER_BYTES); 1695 } 1696 1697 int size = headers.size(); 1698 for (int i = 0; i < size; i++) { 1699 outputBuffer.sendHeader(headers.getName(i), headers.getValue(i)); 1700 } 1701 outputBuffer.endHeaders(); 1702 1703 } 1704 1705 1706 1709 protected void initializeFilters() { 1710 1711 inputBuffer.addFilter(new IdentityInputFilter()); 1713 outputBuffer.addFilter(new IdentityOutputFilter()); 1714 1715 inputBuffer.addFilter(new ChunkedInputFilter()); 1717 outputBuffer.addFilter(new ChunkedOutputFilter()); 1718 1719 inputBuffer.addFilter(new VoidInputFilter()); 1721 outputBuffer.addFilter(new VoidOutputFilter()); 1722 1723 inputBuffer.addFilter(new BufferedInputFilter()); 1725 1726 outputBuffer.addFilter(new GzipOutputFilter()); 1729 1730 } 1731 1732 1733 1739 protected boolean addInputFilter(InputFilter[] inputFilters, 1740 String encodingName) { 1741 if (encodingName.equals("identity")) { 1742 } else if (encodingName.equals("chunked")) { 1744 inputBuffer.addActiveFilter 1745 (inputFilters[Constants.CHUNKED_FILTER]); 1746 contentDelimitation = true; 1747 } else { 1748 for (int i = 2; i < inputFilters.length; i++) { 1749 if (inputFilters[i].getEncodingName() 1750 .toString().equals(encodingName)) { 1751 inputBuffer.addActiveFilter(inputFilters[i]); 1752 return true; 1753 } 1754 } 1755 return false; 1756 } 1757 return true; 1758 } 1759 1760 1761 1765 protected int findBytes(ByteChunk bc, byte[] b) { 1766 1767 byte first = b[0]; 1768 byte[] buff = bc.getBuffer(); 1769 int start = bc.getStart(); 1770 int end = bc.getEnd(); 1771 1772 int srcEnd = b.length; 1774 1775 for (int i = start; i <= (end - srcEnd); i++) { 1776 if (Ascii.toLower(buff[i]) != first) continue; 1777 int myPos = i+1; 1779 for (int srcPos = 1; srcPos < srcEnd; ) { 1780 if (Ascii.toLower(buff[myPos++]) != b[srcPos++]) 1781 break; 1782 if (srcPos == srcEnd) return i - start; } 1784 } 1785 return -1; 1786 1787 } 1788 1789 1793 protected boolean statusDropsConnection(int status) { 1794 return status == 400 || 1795 status == 408 || 1796 status == 411 || 1797 status == 413 || 1798 status == 414 || 1799 status == 500 || 1800 status == 503 || 1801 status == 501 ; 1802 } 1803 1804} 1805 | Popular Tags |