Author: costin Date: Sun Nov 20 10:19:56 2005 New Revision: 345767 URL: http://svn.apache.org/viewcvs?rev=345767&view=rev Log: Remove even more dups. It seems the apr and non-apr were not actually in sync, there are at least 2 places where extra SecurityManager magic was used in non-apr.
Modified: tomcat/sandbox/java/org/apache/coyote/http11/Http11AprProcessor.java tomcat/sandbox/java/org/apache/coyote/http11/Http11Processor.java tomcat/sandbox/java/org/apache/coyote/http11/InternalAprInputBuffer.java tomcat/sandbox/java/org/apache/coyote/http11/InternalInputBuffer.java Modified: tomcat/sandbox/java/org/apache/coyote/http11/Http11AprProcessor.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/coyote/http11/Http11AprProcessor.java?rev=345767&r1=345766&r2=345767&view=diff ============================================================================== --- tomcat/sandbox/java/org/apache/coyote/http11/Http11AprProcessor.java (original) +++ tomcat/sandbox/java/org/apache/coyote/http11/Http11AprProcessor.java Sun Nov 20 10:19:56 2005 @@ -19,12 +19,11 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InterruptedIOException; -import java.net.InetAddress; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; import java.util.StringTokenizer; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; import org.apache.coyote.ActionCode; import org.apache.coyote.ActionHook; @@ -32,6 +31,7 @@ import org.apache.coyote.Request; import org.apache.coyote.RequestInfo; import org.apache.coyote.Response; +import org.apache.coyote.http11.filters.BufferedInputFilter; import org.apache.coyote.http11.filters.ChunkedInputFilter; import org.apache.coyote.http11.filters.ChunkedOutputFilter; import org.apache.coyote.http11.filters.GzipOutputFilter; @@ -40,7 +40,6 @@ import org.apache.coyote.http11.filters.SavedRequestInputFilter; import org.apache.coyote.http11.filters.VoidInputFilter; import org.apache.coyote.http11.filters.VoidOutputFilter; -import org.apache.coyote.http11.filters.BufferedInputFilter; import org.apache.tomcat.jni.Address; import org.apache.tomcat.jni.SSL; import org.apache.tomcat.jni.SSLSocket; @@ -64,20 +63,7 @@ */ public class Http11AprProcessor extends Http11Processor implements ActionHook { - - /** - * Logger. - */ - protected static org.apache.commons.logging.Log log - = org.apache.commons.logging.LogFactory.getLog(Http11AprProcessor.class); - - /** - * The string manager for this package. - */ - protected static StringManager sm = - StringManager.getManager(Constants.Package); - - + // ----------------------------------------------------------- Constructors @@ -92,643 +78,52 @@ } inputBuffer = new InternalAprInputBuffer(request, headerBufferSize, readTimeout); - request.setInputBuffer(inputBuffer); - - response = new Response(); - response.setHook(this); - outputBuffer = new InternalAprOutputBuffer(response, headerBufferSize); - response.setOutputBuffer(outputBuffer); - request.setResponse(response); - - ssl = !"off".equalsIgnoreCase(endpoint.getSSLEngine()); - - initializeFilters(); - - // Cause loading of HexUtils - int foo = HexUtils.DEC[0]; - - // Cause loading of FastHttpDateFormat - FastHttpDateFormat.getCurrentDate(); - - } - - - // ----------------------------------------------------- Instance Variables - - - /** - * Associated adapter. - */ - protected Adapter adapter = null; - - - /** - * Request object. - */ - protected Request request = null; - - - /** - * Response object. - */ - protected Response response = null; - - - /** - * Input. - */ - protected InternalAprInputBuffer inputBuffer = null; - - - /** - * Output. - */ - protected InternalAprOutputBuffer outputBuffer = null; - - - /** - * State flag. - */ - protected boolean started = false; - - - /** - * Error flag. - */ - protected boolean error = false; - - - /** - * Keep-alive. - */ - protected boolean keepAlive = true; - - - /** - * HTTP/1.1 flag. - */ - protected boolean http11 = true; - - - /** - * HTTP/0.9 flag. - */ - protected boolean http09 = false; - - - /** - * Sendfile data. - */ - protected AprEndpoint.SendfileData sendfileData = null; - - - /** - * Content delimitator for the request (if false, the connection will - * be closed at the end of the request). - */ - protected boolean contentDelimitation = true; - - - /** - * Is there an expectation ? - */ - protected boolean expectation = false; - - - /** - * List of restricted user agents. - */ - protected Pattern[] restrictedUserAgents = null; - - - /** - * Maximum number of Keep-Alive requests to honor. - */ - protected int maxKeepAliveRequests = -1; - - - /** - * SSL enabled ? - */ - protected boolean ssl = false; - - - /** - * Socket associated with the current connection. - */ - protected long socket; - - - /** - * Remote Address associated with the current connection. - */ - protected String remoteAddr = null; - - - /** - * Remote Host associated with the current connection. - */ - protected String remoteHost = null; - - - /** - * Local Host associated with the current connection. - */ - protected String localName = null; - - - - /** - * Local port to which the socket is connected - */ - protected int localPort = -1; - - - /** - * Remote port to which the socket is connected - */ - protected int remotePort = -1; - - - /** - * The local Host address. - */ - protected String localAddr = null; - - - /** - * Maximum timeout on uploads. 5 minutes as in Apache HTTPD server. - */ - protected int timeout = 300000; - - - /** - * Flag to disable setting a different time-out on uploads. - */ - protected boolean disableUploadTimeout = false; - - - /** - * Allowed compression level. - */ - protected int compressionLevel = 0; - - - /** - * Minimum contentsize to make compression. - */ - protected int compressionMinSize = 2048; - - - /** - * Socket buffering. - */ - protected int socketBuffer = -1; - - - /** - * Max save post size. - */ - protected int maxSavePostSize = 4 * 1024; - - - /** - * List of user agents to not use gzip with - */ - protected Pattern noCompressionUserAgents[] = null; - - /** - * List of MIMES which could be gzipped - */ - protected String[] compressableMimeTypes = - { "text/html", "text/xml", "text/plain" }; - - - /** - * Host name (used to avoid useless B2C conversion on the host name). - */ - protected char[] hostNameC = new char[0]; - - - /** - * Associated endpoint. - */ - protected AprEndpoint endpoint; - - - /** - * Allow a customized the server header for the tin-foil hat folks. - */ - protected String server = null; - - - // ------------------------------------------------------------- Properties - - - /** - * Return compression level. - */ - public String getCompression() { - switch (compressionLevel) { - case 0: - return "off"; - case 1: - return "on"; - case 2: - return "force"; - } - return "off"; - } - - - /** - * Set compression level. - */ - public void setCompression(String compression) { - if (compression.equals("on")) { - this.compressionLevel = 1; - } else if (compression.equals("force")) { - this.compressionLevel = 2; - } else if (compression.equals("off")) { - this.compressionLevel = 0; - } else { - try { - // Try to parse compression as an int, which would give the - // minimum compression size - compressionMinSize = Integer.parseInt(compression); - this.compressionLevel = 1; - } catch (Exception e) { - this.compressionLevel = 0; - } - } - } - - /** - * Set Minimum size to trigger compression. - */ - public void setCompressionMinSize(int compressionMinSize) { - this.compressionMinSize = compressionMinSize; - } - - - /** - * Add user-agent for which gzip compression didn't works - * The user agent String given will be exactly matched - * to the user-agent header submitted by the client. - * - * @param userAgent user-agent string - */ - public void addNoCompressionUserAgent(String userAgent) { - try { - Pattern nRule = Pattern.compile(userAgent); - noCompressionUserAgents = - addREArray(noCompressionUserAgents, nRule); - } catch (PatternSyntaxException pse) { - log.error(sm.getString("http11processor.regexp.error", userAgent), pse); - } - } - - - /** - * Set no compression user agent list (this method is best when used with - * a large number of connectors, where it would be better to have all of - * them referenced a single array). - */ - public void setNoCompressionUserAgents(Pattern[] noCompressionUserAgents) { - this.noCompressionUserAgents = noCompressionUserAgents; - } - - - /** - * Set no compression user agent list. - * List contains users agents separated by ',' : - * - * ie: "gorilla,desesplorer,tigrus" - */ - public void setNoCompressionUserAgents(String noCompressionUserAgents) { - if (noCompressionUserAgents != null) { - StringTokenizer st = new StringTokenizer(noCompressionUserAgents, ","); - - while (st.hasMoreTokens()) { - addNoCompressionUserAgent(st.nextToken().trim()); - } - } - } - - /** - * Add a mime-type which will be compressable - * The mime-type String will be exactly matched - * in the response mime-type header . - * - * @param mimeType mime-type string - */ - public void addCompressableMimeType(String mimeType) { - compressableMimeTypes = - addStringArray(compressableMimeTypes, mimeType); - } - - - /** - * Set compressable mime-type list (this method is best when used with - * a large number of connectors, where it would be better to have all of - * them referenced a single array). - */ - public void setCompressableMimeTypes(String[] compressableMimeTypes) { - this.compressableMimeTypes = compressableMimeTypes; - } - - - /** - * Set compressable mime-type list - * List contains users agents separated by ',' : - * - * ie: "text/html,text/xml,text/plain" - */ - public void setCompressableMimeTypes(String compressableMimeTypes) { - if (compressableMimeTypes != null) { - StringTokenizer st = new StringTokenizer(compressableMimeTypes, ","); - - while (st.hasMoreTokens()) { - addCompressableMimeType(st.nextToken().trim()); - } - } - } - - - /** - * Return the list of restricted user agents. - */ - public String[] findCompressableMimeTypes() { - return (compressableMimeTypes); - } - - - - // --------------------------------------------------------- Public Methods - - - /** - * Add input or output filter. - * - * @param className class name of the filter - */ - protected void addFilter(String className) { - try { - Class clazz = Class.forName(className); - Object obj = clazz.newInstance(); - if (obj instanceof InputFilter) { - inputBuffer.addFilter((InputFilter) obj); - } else if (obj instanceof OutputFilter) { - outputBuffer.addFilter((OutputFilter) obj); - } else { - log.warn(sm.getString("http11processor.filter.unknown", className)); - } - } catch (Exception e) { - log.error(sm.getString("http11processor.filter.error", className), e); - } - } - - - /** - * General use method - * - * @param sArray the StringArray - * @param value string - */ - private String[] addStringArray(String sArray[], String value) { - String[] result = null; - if (sArray == null) { - result = new String[1]; - result[0] = value; - } - else { - result = new String[sArray.length + 1]; - for (int i = 0; i < sArray.length; i++) - result[i] = sArray[i]; - result[sArray.length] = value; - } - return result; - } - - - /** - * General use method - * - * @param rArray the REArray - * @param value Obj - */ - private Pattern[] addREArray(Pattern rArray[], Pattern value) { - Pattern[] result = null; - if (rArray == null) { - result = new Pattern[1]; - result[0] = value; - } - else { - result = new Pattern[rArray.length + 1]; - for (int i = 0; i < rArray.length; i++) - result[i] = rArray[i]; - result[rArray.length] = value; - } - return result; - } - - - /** - * General use method - * - * @param sArray the StringArray - * @param value string - */ - private boolean inStringArray(String sArray[], String value) { - for (int i = 0; i < sArray.length; i++) { - if (sArray[i].equals(value)) { - return true; - } - } - return false; - } - - - /** - * Checks if any entry in the string array starts with the specified value - * - * @param sArray the StringArray - * @param value string - */ - private boolean startsWithStringArray(String sArray[], String value) { - if (value == null) - return false; - for (int i = 0; i < sArray.length; i++) { - if (value.startsWith(sArray[i])) { - return true; - } - } - return false; - } - - - /** - * Add restricted user-agent (which will downgrade the connector - * to HTTP/1.0 mode). The user agent String given will be matched - * via regexp to the user-agent header submitted by the client. - * - * @param userAgent user-agent string - */ - public void addRestrictedUserAgent(String userAgent) { - try { - Pattern nRule = Pattern.compile(userAgent); - restrictedUserAgents = addREArray(restrictedUserAgents, nRule); - } catch (PatternSyntaxException pse) { - log.error(sm.getString("http11processor.regexp.error", userAgent), pse); - } - } - - - /** - * Set restricted user agent list (this method is best when used with - * a large number of connectors, where it would be better to have all of - * them referenced a single array). - */ - public void setRestrictedUserAgents(Pattern[] restrictedUserAgents) { - this.restrictedUserAgents = restrictedUserAgents; - } - - - /** - * Set restricted user agent list (which will downgrade the connector - * to HTTP/1.0 mode). List contains users agents separated by ',' : - * - * ie: "gorilla,desesplorer,tigrus" - */ - public void setRestrictedUserAgents(String restrictedUserAgents) { - if (restrictedUserAgents != null) { - StringTokenizer st = - new StringTokenizer(restrictedUserAgents, ","); - while (st.hasMoreTokens()) { - addRestrictedUserAgent(st.nextToken().trim()); - } - } - } - - - /** - * Return the list of restricted user agents. - */ - public String[] findRestrictedUserAgents() { - String[] sarr = new String [restrictedUserAgents.length]; - - for (int i = 0; i < restrictedUserAgents.length; i++) - sarr[i] = restrictedUserAgents[i].toString(); - - return (sarr); - } - - - /** - * Set the maximum number of Keep-Alive requests to honor. - * This is to safeguard from DoS attacks. Setting to a negative - * value disables the check. - */ - public void setMaxKeepAliveRequests(int mkar) { - maxKeepAliveRequests = mkar; - } - - - /** - * Return the number of Keep-Alive requests that we will honor. - */ - public int getMaxKeepAliveRequests() { - return maxKeepAliveRequests; - } - - - /** - * Set the maximum size of a POST which will be buffered in SSL mode. - */ - public void setMaxSavePostSize(int msps) { - maxSavePostSize = msps; - } - - - /** - * Return the maximum size of a POST which will be buffered in SSL mode. - */ - public int getMaxSavePostSize() { - return maxSavePostSize; - } + request.setInputBuffer(inputBuffer); + response = new Response(); + response.setHook(this); + outputBuffer = new InternalAprOutputBuffer(response, headerBufferSize); + response.setOutputBuffer(outputBuffer); + request.setResponse(response); + + ssl = !"off".equalsIgnoreCase(endpoint.getSSLEngine()); - /** - * Set the flag to control upload time-outs. - */ - public void setDisableUploadTimeout(boolean isDisabled) { - disableUploadTimeout = isDisabled; - } + initializeFilters(); - /** - * Get the flag that controls upload time-outs. - */ - public boolean getDisableUploadTimeout() { - return disableUploadTimeout; - } + // Cause loading of HexUtils + int foo = HexUtils.DEC[0]; - /** - * Set the socket buffer flag. - */ - public void setSocketBuffer(int socketBuffer) { - this.socketBuffer = socketBuffer; - outputBuffer.setSocketBuffer(socketBuffer); - } + // Cause loading of FastHttpDateFormat + FastHttpDateFormat.getCurrentDate(); - /** - * Get the socket buffer flag. - */ - public int getSocketBuffer() { - return socketBuffer; } - /** - * Set the upload timeout. - */ - public void setTimeout( int timeouts ) { - timeout = timeouts ; - } + // ----------------------------------------------------- Instance Variables /** - * Get the upload timeout. + * Sendfile data. */ - public int getTimeout() { - return timeout; - } + protected AprEndpoint.SendfileData sendfileData = null; /** - * Set the server header name. + * SSL enabled ? */ - public void setServer( String server ) { - if (server==null || server.equals("")) { - this.server = null; - } else { - this.server = server; - } - } + protected boolean ssl = false; + /** - * Get the server header name. + * Socket associated with the current connection. */ - public String getServer() { - return server; - } + protected long socket; - /** Get the request associated with this processor. - * - * @return The request + /** + * Associated endpoint. */ - public Request getRequest() { - return request; - } + //protected AprEndpoint endpoint; + // ------------------------------------------------------------- Properties /** * Process pipelined HTTP requests using the specified input and output * streams. @@ -752,8 +147,8 @@ // Setting up the socket this.socket = socket; - inputBuffer.setSocket(socket); - outputBuffer.setSocket(socket); + ((InternalAprInputBuffer)inputBuffer).setSocket(socket); + ((InternalAprOutputBuffer)outputBuffer).setSocket(socket); // Error flag error = false; @@ -763,7 +158,7 @@ long soTimeout = endpoint.getSoTimeout(); int limit = 0; - if (endpoint.getFirstReadTimeout() > 0) { + if (((AprEndpoint)endpoint).getFirstReadTimeout() > 0) { limit = endpoint.getMaxThreads() / 2; } @@ -784,7 +179,7 @@ // and the method should return true openSocket = true; // Add the socket to the poller - endpoint.getPoller().add(socket); + ((AprEndpoint)endpoint).getPoller().add(socket); break; } request.setStartTime(System.currentTimeMillis()); @@ -894,7 +289,7 @@ if (sendfileData != null) { sendfileData.socket = socket; sendfileData.keepAlive = keepAlive; - if (!endpoint.getSendfile().add(sendfileData)) { + if (!((AprEndpoint)endpoint).getSendfile().add(sendfileData)) { openSocket = true; break; } @@ -915,92 +310,10 @@ // ----------------------------------------------------- ActionHook Methods - - /** - * Send an action to the connector. - * - * @param actionCode Type of the action - * @param param Action parameter - */ - public void action(ActionCode actionCode, Object param) { - - if (actionCode == ActionCode.ACTION_COMMIT) { - // Commit current response - - if (response.isCommitted()) - return; - - // Validate and write response headers - prepareResponse(); - try { - outputBuffer.commit(); - } catch (IOException e) { - // Set error flag - error = true; - } - - } else if (actionCode == ActionCode.ACTION_ACK) { - - // Acknowlege request - - // Send a 100 status back if it makes sense (response not committed - // yet, and client specified an expectation for 100-continue) - - if ((response.isCommitted()) || !expectation) - return; - - inputBuffer.setSwallowInput(true); - try { - outputBuffer.sendAck(); - } catch (IOException e) { - // Set error flag - error = true; - } - - } else if (actionCode == ActionCode.ACTION_CLIENT_FLUSH) { - - try { - outputBuffer.flush(); - } catch (IOException e) { - // Set error flag - error = true; - response.setErrorException(e); - } - - } else if (actionCode == ActionCode.ACTION_CLOSE) { - // Close - - // End the processing of the current request, and stop any further - // transactions with the client - - try { - outputBuffer.endRequest(); - } catch (IOException e) { - // Set error flag - error = true; - } - - } else if (actionCode == ActionCode.ACTION_RESET) { - - // Reset response - - // Note: This must be called before the response is committed - - outputBuffer.reset(); - - } else if (actionCode == ActionCode.ACTION_CUSTOM) { - - // Do nothing - - } else if (actionCode == ActionCode.ACTION_START) { - - started = true; - - } else if (actionCode == ActionCode.ACTION_STOP) { - - started = false; - - } else if (actionCode == ActionCode.ACTION_REQ_HOST_ADDR_ATTRIBUTE) { + + protected void endpointAction(ActionCode actionCode, Object param) { + if (actionCode == ActionCode.ACTION_REQ_HOST_ADDR_ATTRIBUTE) { + // Get remote host address if (remoteAddr == null) { @@ -1167,43 +480,10 @@ } } - } else if (actionCode == ActionCode.ACTION_REQ_SET_BODY_REPLAY) { - ByteChunk body = (ByteChunk) param; - - InputFilter savedBody = new SavedRequestInputFilter(body); - savedBody.setRequest(request); - - InternalInputBuffer internalBuffer = (InternalInputBuffer) - request.getInputBuffer(); - internalBuffer.addActiveFilter(savedBody); } } - - // ------------------------------------------------------ Connector Methods - - - /** - * Set the associated adapter. - * - * @param adapter the new adapter - */ - public void setAdapter(Adapter adapter) { - this.adapter = adapter; - } - - - /** - * Get the associated adapter. - * - * @return the associated adapter - */ - public Adapter getAdapter() { - return adapter; - } - - // ------------------------------------------------------ Protected Methods @@ -1211,356 +491,28 @@ * After reading the request headers, we have to setup the request filters. */ protected void prepareRequest() { - - http11 = true; - http09 = false; - contentDelimitation = false; - expectation = false; + super.prepareRequest(); + sendfileData = null; - if (ssl) { - request.scheme().setString("https"); - } - MessageBytes protocolMB = request.protocol(); - if (protocolMB.equals(Constants.HTTP_11)) { - http11 = true; - protocolMB.setString(Constants.HTTP_11); - } else if (protocolMB.equals(Constants.HTTP_10)) { - http11 = false; - keepAlive = false; - protocolMB.setString(Constants.HTTP_10); - } else if (protocolMB.equals("")) { - // HTTP/0.9 - http09 = true; - http11 = false; - keepAlive = false; - } else { - // Unsupported protocol - http11 = false; - error = true; - // Send 505; Unsupported HTTP version - response.setStatus(505); - } - - MessageBytes methodMB = request.method(); - if (methodMB.equals(Constants.GET)) { - methodMB.setString(Constants.GET); - } else if (methodMB.equals(Constants.POST)) { - methodMB.setString(Constants.POST); - } - - MimeHeaders headers = request.getMimeHeaders(); - - // Check connection header - MessageBytes connectionValueMB = headers.getValue("connection"); - if (connectionValueMB != null) { - ByteChunk connectionValueBC = connectionValueMB.getByteChunk(); - if (findBytes(connectionValueBC, Constants.CLOSE_BYTES) != -1) { - keepAlive = false; - } else if (findBytes(connectionValueBC, - Constants.KEEPALIVE_BYTES) != -1) { - keepAlive = true; - } - } - - MessageBytes expectMB = null; - if (http11) - expectMB = headers.getValue("expect"); - if ((expectMB != null) - && (expectMB.indexOfIgnoreCase("100-continue", 0) != -1)) { - inputBuffer.setSwallowInput(false); - expectation = true; - } - - // Check user-agent header - if ((restrictedUserAgents != null) && ((http11) || (keepAlive))) { - MessageBytes userAgentValueMB = headers.getValue("user-agent"); - // Check in the restricted list, and adjust the http11 - // and keepAlive flags accordingly - if(userAgentValueMB != null) { - String userAgentValue = userAgentValueMB.toString(); - for (int i = 0; i < restrictedUserAgents.length; i++) { - if (restrictedUserAgents[i].matcher(userAgentValue).matches()) { - http11 = false; - keepAlive = false; - break; - } - } - } - } - - // Check for a full URI (including protocol://host:port/) - ByteChunk uriBC = request.requestURI().getByteChunk(); - if (uriBC.startsWithIgnoreCase("http", 0)) { - - int pos = uriBC.indexOf("://", 0, 3, 4); - int uriBCStart = uriBC.getStart(); - int slashPos = -1; - if (pos != -1) { - byte[] uriB = uriBC.getBytes(); - slashPos = uriBC.indexOf('/', pos + 3); - if (slashPos == -1) { - slashPos = uriBC.getLength(); - // Set URI as "/" - request.requestURI().setBytes - (uriB, uriBCStart + pos + 1, 1); - } else { - request.requestURI().setBytes - (uriB, uriBCStart + slashPos, - uriBC.getLength() - slashPos); - } - MessageBytes hostMB = headers.setValue("host"); - hostMB.setBytes(uriB, uriBCStart + pos + 3, - slashPos - pos - 3); - } - - } - - // Input filter setup - InputFilter[] inputFilters = inputBuffer.getFilters(); - - // Parse transfer-encoding header - MessageBytes transferEncodingValueMB = null; - if (http11) - transferEncodingValueMB = headers.getValue("transfer-encoding"); - if (transferEncodingValueMB != null) { - String transferEncodingValue = transferEncodingValueMB.toString(); - // Parse the comma separated list. "identity" codings are ignored - int startPos = 0; - int commaPos = transferEncodingValue.indexOf(','); - String encodingName = null; - while (commaPos != -1) { - encodingName = transferEncodingValue.substring - (startPos, commaPos).toLowerCase().trim(); - if (!addInputFilter(inputFilters, encodingName)) { - // Unsupported transfer encoding - error = true; - // 501 - Unimplemented - response.setStatus(501); - } - startPos = commaPos + 1; - commaPos = transferEncodingValue.indexOf(',', startPos); - } - encodingName = transferEncodingValue.substring(startPos) - .toLowerCase().trim(); - if (!addInputFilter(inputFilters, encodingName)) { - // Unsupported transfer encoding - error = true; - // 501 - Unimplemented - response.setStatus(501); - } - } - - // Parse content-length header - long contentLength = request.getContentLengthLong(); - if (contentLength >= 0 && !contentDelimitation) { - inputBuffer.addActiveFilter - (inputFilters[Constants.IDENTITY_FILTER]); - contentDelimitation = true; - } - - MessageBytes valueMB = headers.getValue("host"); - - // Check host header - if (http11 && (valueMB == null)) { - error = true; - // 400 - Bad request - response.setStatus(400); - } - - parseHost(valueMB); - - if (!contentDelimitation) { - // If there's no content length and we're using keep-alive - // (HTTP/1.0 with keep-alive or HTTP/1.1), assume - // the client is not broken and didn't send a body - if (keepAlive) { - inputBuffer.addActiveFilter - (inputFilters[Constants.VOID_FILTER]); - contentDelimitation = true; - } - } - - if (!contentDelimitation) - keepAlive = false; - // Advertise sendfile support through a request attribute - if (endpoint.getUseSendfile()) { + if (((AprEndpoint)endpoint).getUseSendfile()) { request.setAttribute("org.apache.tomcat.sendfile.support", Boolean.TRUE); } } - /** - * Parse host. - */ - public void parseHost(MessageBytes valueMB) { - - if (valueMB == null || valueMB.isNull()) { - // HTTP/1.0 - // Default is what the socket tells us. Overriden if a host is - // found/parsed - request.setServerPort(endpoint.getPort()); - return; - } - - ByteChunk valueBC = valueMB.getByteChunk(); - byte[] valueB = valueBC.getBytes(); - int valueL = valueBC.getLength(); - int valueS = valueBC.getStart(); - int colonPos = -1; - if (hostNameC.length < valueL) { - hostNameC = new char[valueL]; - } - - boolean ipv6 = (valueB[valueS] == '['); - boolean bracketClosed = false; - for (int i = 0; i < valueL; i++) { - char b = (char) valueB[i + valueS]; - hostNameC[i] = b; - if (b == ']') { - bracketClosed = true; - } else if (b == ':') { - if (!ipv6 || bracketClosed) { - colonPos = i; - break; - } - } - } - - if (colonPos < 0) { - if (!ssl) { - // 80 - Default HTTP port - request.setServerPort(80); - } else { - // 443 - Default HTTPS port - request.setServerPort(443); - } - request.serverName().setChars(hostNameC, 0, valueL); - } else { - - request.serverName().setChars(hostNameC, 0, colonPos); - - int port = 0; - int mult = 1; - for (int i = valueL - 1; i > colonPos; i--) { - int charValue = HexUtils.DEC[(int) valueB[i + valueS]]; - if (charValue == -1) { - // Invalid character - error = true; - // 400 - Bad request - response.setStatus(400); - break; - } - port = port + (charValue * mult); - mult = 10 * mult; - } - request.setServerPort(port); - - } - - } - - - /** - * Check for compression - */ - private boolean isCompressable() { - - // Nope Compression could works in HTTP 1.0 also - // cf: mod_deflate - - // Compression only since HTTP 1.1 - // if (! http11) - // return false; - - // Check if browser support gzip encoding - MessageBytes acceptEncodingMB = - request.getMimeHeaders().getValue("accept-encoding"); - - if ((acceptEncodingMB == null) - || (acceptEncodingMB.indexOf("gzip") == -1)) - return false; - - // Check if content is not allready gzipped - MessageBytes contentEncodingMB = - response.getMimeHeaders().getValue("Content-Encoding"); - - if ((contentEncodingMB != null) - && (contentEncodingMB.indexOf("gzip") != -1)) - return false; - - // If force mode, allways compress (test purposes only) - if (compressionLevel == 2) - return true; - - // Check for incompatible Browser - if (noCompressionUserAgents != null) { - MessageBytes userAgentValueMB = - request.getMimeHeaders().getValue("user-agent"); - if(userAgentValueMB != null) { - String userAgentValue = userAgentValueMB.toString(); - - // If one Regexp rule match, disable compression - for (int i = 0; i < noCompressionUserAgents.length; i++) - if (noCompressionUserAgents[i].matcher(userAgentValue).matches()) - return false; - } - } - - // Check if suffisant len to trig the compression - long contentLength = response.getContentLengthLong(); - if ((contentLength == -1) - || (contentLength > compressionMinSize)) { - // Check for compatible MIME-TYPE - if (compressableMimeTypes != null) { - return (startsWithStringArray(compressableMimeTypes, - response.getContentType())); - } - } - - return false; + protected void setDefaultHost() { + // HTTP/1.0 + // Default is what the socket tells us. Overriden if a host is + // found/parsed + request.setServerPort(endpoint.getPort()); } + - - /** - * When committing the response, we have to validate the set of headers, as - * well as setup the response filters. - */ - protected void prepareResponse() { - - boolean entityBody = true; - contentDelimitation = false; - - OutputFilter[] outputFilters = outputBuffer.getFilters(); - - if (http09 == true) { - // HTTP/0.9 - outputBuffer.addActiveFilter - (outputFilters[Constants.IDENTITY_FILTER]); - return; - } - - int statusCode = response.getStatus(); - if ((statusCode == 204) || (statusCode == 205) - || (statusCode == 304)) { - // No entity body - outputBuffer.addActiveFilter - (outputFilters[Constants.VOID_FILTER]); - entityBody = false; - contentDelimitation = true; - } - - MessageBytes methodMB = request.method(); - if (methodMB.equals("HEAD")) { - // No entity body - outputBuffer.addActiveFilter - (outputFilters[Constants.VOID_FILTER]); - contentDelimitation = true; - } - + protected void sendfileSupport(OutputFilter[] outputFilters) { // Sendfile support - if (endpoint.getUseSendfile()) { + if (((AprEndpoint)endpoint).getUseSendfile()) { String fileName = (String) request.getAttribute("org.apache.tomcat.sendfile.filename"); if (fileName != null) { // No entity body sent here @@ -1575,192 +527,6 @@ ((Long) request.getAttribute("org.apache.tomcat.sendfile.end")).longValue(); } } - - // Check for compression - boolean useCompression = false; - if (entityBody && (compressionLevel > 0) && (sendfileData == null)) { - useCompression = isCompressable(); - // Change content-length to -1 to force chunking - if (useCompression) { - response.setContentLength(-1); - } - } - - MimeHeaders headers = response.getMimeHeaders(); - if (!entityBody) { - response.setContentLength(-1); - } else { - String contentType = response.getContentType(); - if (contentType != null) { - headers.setValue("Content-Type").setString(contentType); - } - String contentLanguage = response.getContentLanguage(); - if (contentLanguage != null) { - headers.setValue("Content-Language") - .setString(contentLanguage); - } - } - - long contentLength = response.getContentLengthLong(); - if (contentLength != -1) { - headers.setValue("Content-Length").setLong(contentLength); - outputBuffer.addActiveFilter - (outputFilters[Constants.IDENTITY_FILTER]); - contentDelimitation = true; - } else { - if (entityBody && http11 && keepAlive) { - outputBuffer.addActiveFilter - (outputFilters[Constants.CHUNKED_FILTER]); - contentDelimitation = true; - headers.addValue(Constants.TRANSFERENCODING).setString(Constants.CHUNKED); - } else { - outputBuffer.addActiveFilter - (outputFilters[Constants.IDENTITY_FILTER]); - } - } - - if (useCompression) { - outputBuffer.addActiveFilter(outputFilters[Constants.GZIP_FILTER]); - headers.setValue("Content-Encoding").setString("gzip"); - // Make Proxies happy via Vary (from mod_deflate) - headers.setValue("Vary").setString("Accept-Encoding"); - } - - // Add date header - headers.setValue("Date").setString(FastHttpDateFormat.getCurrentDate()); - - // FIXME: Add transfer encoding header - - if ((entityBody) && (!contentDelimitation)) { - // Mark as close the connection after the request, and add the - // connection: close header - keepAlive = false; - } - - // If we know that the request is bad this early, add the - // Connection: close header. - keepAlive = keepAlive && !statusDropsConnection(statusCode); - if (!keepAlive) { - headers.addValue(Constants.CONNECTION).setString(Constants.CLOSE); - } else if (!http11 && !error) { - headers.addValue(Constants.CONNECTION).setString(Constants.KEEPALIVE); - } - - // Build the response header - outputBuffer.sendStatus(); - - // Add server header - if (server != null) { - headers.setValue("Server").setString(server); - } else { - outputBuffer.write(Constants.SERVER_BYTES); - } - - int size = headers.size(); - for (int i = 0; i < size; i++) { - outputBuffer.sendHeader(headers.getName(i), headers.getValue(i)); - } - outputBuffer.endHeaders(); - - } - - - /** - * Initialize standard input and output filters. - */ - protected void initializeFilters() { - - // Create and add the identity filters. - inputBuffer.addFilter(new IdentityInputFilter()); - outputBuffer.addFilter(new IdentityOutputFilter()); - - // Create and add the chunked filters. - inputBuffer.addFilter(new ChunkedInputFilter()); - outputBuffer.addFilter(new ChunkedOutputFilter()); - - // Create and add the void filters. - inputBuffer.addFilter(new VoidInputFilter()); - outputBuffer.addFilter(new VoidOutputFilter()); - - // Create and add buffered input filter - inputBuffer.addFilter(new BufferedInputFilter()); - - // Create and add the chunked filters. - //inputBuffer.addFilter(new GzipInputFilter()); - outputBuffer.addFilter(new GzipOutputFilter()); - - } - - - /** - * Add an input filter to the current request. - * - * @return false if the encoding was not found (which would mean it is - * unsupported) - */ - protected boolean addInputFilter(InputFilter[] inputFilters, - String encodingName) { - if (encodingName.equals("identity")) { - // Skip - } else if (encodingName.equals("chunked")) { - inputBuffer.addActiveFilter - (inputFilters[Constants.CHUNKED_FILTER]); - contentDelimitation = true; - } else { - for (int i = 2; i < inputFilters.length; i++) { - if (inputFilters[i].getEncodingName() - .toString().equals(encodingName)) { - inputBuffer.addActiveFilter(inputFilters[i]); - return true; - } - } - return false; - } - return true; - } - - - /** - * Specialized utility method: find a sequence of lower case bytes inside - * a ByteChunk. - */ - protected int findBytes(ByteChunk bc, byte[] b) { - - byte first = b[0]; - byte[] buff = bc.getBuffer(); - int start = bc.getStart(); - int end = bc.getEnd(); - - // Look for first char - int srcEnd = b.length; - - for (int i = start; i <= (end - srcEnd); i++) { - if (Ascii.toLower(buff[i]) != first) continue; - // found first char, now look for a match - int myPos = i+1; - for (int srcPos = 1; srcPos < srcEnd; ) { - if (Ascii.toLower(buff[myPos++]) != b[srcPos++]) - break; - if (srcPos == srcEnd) return i - start; // found it - } - } - return -1; - - } - - /** - * Determine if we must drop the connection because of the HTTP status - * code. Use the same list of codes as Apache/httpd. - */ - protected boolean statusDropsConnection(int status) { - return status == 400 /* SC_BAD_REQUEST */ || - status == 408 /* SC_REQUEST_TIMEOUT */ || - status == 411 /* SC_LENGTH_REQUIRED */ || - status == 413 /* SC_REQUEST_ENTITY_TOO_LARGE */ || - status == 414 /* SC_REQUEST_URI_TOO_LARGE */ || - status == 500 /* SC_INTERNAL_SERVER_ERROR */ || - status == 503 /* SC_SERVICE_UNAVAILABLE */ || - status == 501 /* SC_NOT_IMPLEMENTED */; } } Modified: tomcat/sandbox/java/org/apache/coyote/http11/Http11Processor.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/coyote/http11/Http11Processor.java?rev=345767&r1=345766&r2=345767&view=diff ============================================================================== --- tomcat/sandbox/java/org/apache/coyote/http11/Http11Processor.java (original) +++ tomcat/sandbox/java/org/apache/coyote/http11/Http11Processor.java Sun Nov 20 10:19:56 2005 @@ -561,7 +561,7 @@ * @param sArray the StringArray * @param value string */ - private boolean startsWithStringArray(String sArray[], String value) { + protected boolean startsWithStringArray(String sArray[], String value) { if (value == null) return false; for (int i = 0; i < sArray.length; i++) { @@ -1026,8 +1026,26 @@ } else if (actionCode == ActionCode.ACTION_STOP) { started = false; + + // ------------------------------------ + } else if (actionCode == ActionCode.ACTION_REQ_SET_BODY_REPLAY) { + ByteChunk body = (ByteChunk) param; + + InputFilter savedBody = new SavedRequestInputFilter(body); + savedBody.setRequest(request); + + InternalInputBuffer internalBuffer = (InternalInputBuffer) + request.getInputBuffer(); + internalBuffer.addActiveFilter(savedBody); + } else { + endpointAction(actionCode, param); + } + } - } else if (actionCode == ActionCode.ACTION_REQ_SSL_ATTRIBUTE ) { + protected void endpointAction(ActionCode actionCode, + Object param) { + + if (actionCode == ActionCode.ACTION_REQ_SSL_ATTRIBUTE ) { try { if (sslSupport != null) { @@ -1124,15 +1142,6 @@ log.warn(sm.getString("http11processor.socket.ssl"), e); } } - } else if (actionCode == ActionCode.ACTION_REQ_SET_BODY_REPLAY) { - ByteChunk body = (ByteChunk) param; - - InputFilter savedBody = new SavedRequestInputFilter(body); - savedBody.setRequest(request); - - InternalInputBuffer internalBuffer = (InternalInputBuffer) - request.getInputBuffer(); - internalBuffer.addActiveFilter(savedBody); } } @@ -1341,6 +1350,18 @@ } + protected void setDefaultHost() { + // HTTP/1.0 + // Default is what the socket tells us. Overriden if a host is + // found/parsed + // APR: endpoint.getPort(), no serverName. + request.setServerPort(socket.getLocalPort()); + + InetAddress localAddress = socket.getLocalAddress(); + // Setting the socket-related fields. The adapter doesn't know + // about socket. + request.serverName().setString(localAddress.getHostName()); + } /** * Parse host. @@ -1348,14 +1369,7 @@ public void parseHost(MessageBytes valueMB) { if (valueMB == null || valueMB.isNull()) { - // HTTP/1.0 - // Default is what the socket tells us. Overriden if a host is - // found/parsed - request.setServerPort(socket.getLocalPort()); - InetAddress localAddress = socket.getLocalAddress(); - // Setting the socket-related fields. The adapter doesn't know - // about socket. - request.serverName().setString(localAddress.getHostName()); + setDefaultHost(); return; } @@ -1420,7 +1434,7 @@ /** * Check for compression */ - private boolean isCompressable() { + protected boolean isCompressable() { // Nope Compression could works in HTTP 1.0 also // cf: mod_deflate @@ -1514,6 +1528,9 @@ contentDelimitation = true; } + // APR: sendfile + sendfileSupport(outputFilters); + // Check for compression boolean useCompression = false; if (entityBody && (compressionLevel > 0)) { @@ -1565,7 +1582,7 @@ headers.setValue("Vary").setString("Accept-Encoding"); } - // Add date header + // Add date header. APR didn't have SecurityManager wrapper String date = null; if (System.getSecurityManager() != null){ date = (String)AccessController.doPrivileged( @@ -1615,6 +1632,9 @@ } + // Hook for sendfile + protected void sendfileSupport(OutputFilter[] outputFilters) { + } /** * Initialize standard input and output filters. Modified: tomcat/sandbox/java/org/apache/coyote/http11/InternalAprInputBuffer.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/coyote/http11/InternalAprInputBuffer.java?rev=345767&r1=345766&r2=345767&view=diff ============================================================================== --- tomcat/sandbox/java/org/apache/coyote/http11/InternalAprInputBuffer.java (original) +++ tomcat/sandbox/java/org/apache/coyote/http11/InternalAprInputBuffer.java Sun Nov 20 10:19:56 2005 @@ -21,11 +21,9 @@ import java.io.IOException; import java.nio.ByteBuffer; -import org.apache.coyote.InputBuffer; import org.apache.coyote.Request; import org.apache.tomcat.jni.Socket; import org.apache.tomcat.jni.Status; -import org.apache.tomcat.util.buf.ByteChunk; /** * Implementation of InputBuffer which provides HTTP request header parsing as @@ -51,8 +49,6 @@ bbuf = ByteBuffer.allocateDirect(headerBufferSize); - inputStreamInputBuffer = new SocketInputBuffer(); - this.readTimeout = readTimeout * 1000; } @@ -110,9 +106,6 @@ public void recycle() { super.recycle(); - // Recycle Request object - request.recycle(); - socket = 0; } @@ -364,40 +357,4 @@ return (nRead > 0); } - - - // ------------------------------------- InputStreamInputBuffer Inner Class - - - /** - * This class is an input buffer which will read its data from an input - * stream. - */ - protected class SocketInputBuffer - implements InputBuffer { - - - /** - * Read bytes into the specified chunk. - */ - public int doRead(ByteChunk chunk, Request req ) - throws IOException { - - if (pos >= lastValid) { - if (!fill()) - return -1; - } - - int length = lastValid - pos; - chunk.setBytes(buf, pos, length); - pos = lastValid; - - return (length); - - } - - - } - - } Modified: tomcat/sandbox/java/org/apache/coyote/http11/InternalInputBuffer.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/coyote/http11/InternalInputBuffer.java?rev=345767&r1=345766&r2=345767&view=diff ============================================================================== --- tomcat/sandbox/java/org/apache/coyote/http11/InternalInputBuffer.java (original) +++ tomcat/sandbox/java/org/apache/coyote/http11/InternalInputBuffer.java Sun Nov 20 10:19:56 2005 @@ -21,6 +21,8 @@ import java.io.InputStream; import java.io.EOFException; +import org.apache.tomcat.jni.Socket; +import org.apache.tomcat.jni.Status; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.buf.MessageBytes; import org.apache.tomcat.util.http.MimeHeaders; @@ -385,7 +387,7 @@ * read operations, or if the given buffer is not big enough to accomodate * the whole line. */ - public boolean parseRequestLine(boolean dummy) + public boolean parseRequestLine(boolean useAvailableData) throws IOException { int start = 0; @@ -399,6 +401,27 @@ // Read new bytes if needed if (pos >= lastValid) { + /* APR version: + if (useAvailableData) { + return false; + } + // Do a simple read with a short timeout + bbuf.clear(); + int nRead = Socket.recvbbt + (socket, 0, buf.length - lastValid, readTimeout); + if (nRead > 0) { + bbuf.limit(nRead); + bbuf.get(buf, pos, nRead); + lastValid = pos + nRead; + } else { + if ((-nRead) == Status.ETIMEDOUT || (-nRead) == Status.TIMEUP) { + return false; + } else { + throw new IOException(sm.getString("iib.failedread")); + } + } + + */ if (!fill()) throw new EOFException(sm.getString("iib.eof.error")); } @@ -417,6 +440,29 @@ // Method name is always US-ASCII // + /* APR: extra code: + if (pos >= lastValid) { + if (useAvailableData) { + return false; + } + // Do a simple read with a short timeout + bbuf.clear(); + int nRead = Socket.recvbbt + (socket, 0, buf.length - lastValid, readTimeout); + if (nRead > 0) { + bbuf.limit(nRead); + bbuf.get(buf, pos, nRead); + lastValid = pos + nRead; + } else { + if ((-nRead) == Status.ETIMEDOUT || (-nRead) == Status.TIMEUP) { + return false; + } else { + throw new IOException(sm.getString("iib.failedread")); + } + } + } + */ + boolean space = false; while (!space) { @@ -740,16 +786,44 @@ (sm.getString("iib.requestheadertoolarge.error")); } + // In APR: + /* + bbuf.clear(); + nRead = Socket.recvbb + (socket, 0, buf.length - lastValid); + if (nRead > 0) { + bbuf.limit(nRead); + bbuf.get(buf, pos, nRead); + lastValid = pos + nRead; + } else { + if ((-nRead) == Status.EAGAIN) { + return false; + } else { + throw new IOException(sm.getString("iib.failedread")); + } + } + */ nRead = inputStream.read(buf, pos, buf.length - lastValid); if (nRead > 0) { lastValid = pos + nRead; } } else { - buf = bodyBuffer; pos = 0; lastValid = 0; + /*APR: + bbuf.clear(); + nRead = Socket.recvbb + (socket, 0, buf.length); + if (nRead > 0) { + bbuf.limit(nRead); + bbuf.get(buf, 0, nRead); + lastValid = nRead; + } else { + throw new IOException(sm.getString("iib.failedread")); + } + */ nRead = inputStream.read(buf, 0, buf.length); if (nRead > 0) { lastValid = nRead; @@ -768,6 +842,8 @@ /** * This class is an input buffer which will read its data from an input * stream. + * + * Used as an adapter for the ByteChunk. */ protected class InputStreamInputBuffer implements InputBuffer { --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]