![JAR search and dependency download from the Maven repository](/logo.png)
org.parosproxy.paros.network.HttpInputStream Maven / Gradle / Ivy
/*
* Created on May 29, 2004
*
* Paros and its related class files.
*
* Paros is an HTTP/HTTPS proxy for assessing web application security.
* Copyright (C) 2003-2004 Chinotec Technologies Company
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the Clarified Artistic License
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Clarified Artistic License for more details.
*
* You should have received a copy of the Clarified Artistic License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// ZAP: 2012/03/15 Changed to use the classes HttpRequestBody and HttpResponseBody
// Added @Override annotation where appropriate.
// ZAP: 2013/03/03 Issue 546: Remove all template Javadoc comments
// ZAP: 2019/06/01 Normalise line endings.
// ZAP: 2019/06/05 Normalise format/style.
// ZAP: 2020/08/25 Correctly read chunks of the body.
// ZAP: 2020/11/26 Use Log4j 2 classes for logging.
// ZAP: 2020/12/09 Set content encoding to the request body.
package org.parosproxy.paros.network;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketTimeoutException;
import javax.net.ssl.SSLSocket;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.zaproxy.zap.network.HttpRequestBody;
import org.zaproxy.zap.network.HttpResponseBody;
public class HttpInputStream extends BufferedInputStream {
private static final Logger LOGGER = LogManager.getLogger(HttpInputStream.class);
static final int BUFFER_SIZE = 4096;
private static final String CRLF = "\r\n";
private static final String CRLF2 = CRLF + CRLF;
private static final String LF = "\n";
private static final String LF2 = LF + LF;
// private BufferedInputStream in = null;
private byte[] mBuffer = new byte[BUFFER_SIZE];
private Socket mSocket = null;
public HttpInputStream(Socket socket) throws IOException {
super(socket.getInputStream(), BUFFER_SIZE);
setSocket(socket);
// this.in = new BufferedInputStream(mSocket.getInputStream());
}
public HttpRequestHeader readRequestHeader(boolean isSecure)
throws HttpMalformedHeaderException, IOException {
String msg = "";
HttpRequestHeader httpRequestHeader = null;
msg = readHeader();
if (msg.length() == 0) {
LOGGER.debug("Read 0 bytes from upstream. Could not read header!");
throw new IOException();
}
httpRequestHeader = new HttpRequestHeader(msg, isSecure);
return httpRequestHeader;
}
public synchronized String readHeader() throws IOException {
String msg = "";
int oneByte = -1;
boolean eoh = false;
StringBuilder sb = new StringBuilder(200);
do {
oneByte = super.read();
if (oneByte == -1) {
eoh = true;
break;
}
sb.append((char) oneByte);
if (((char) oneByte) == '\n' && isHeaderEnd(sb)) {
eoh = true;
msg = sb.toString();
}
} while (!eoh);
return msg;
}
/**
* Check if the current StringBuilder trailing characters is an HTTP header end (empty CRLF).
*
* @param sb
* @return true - if end of HTTP header.
*/
private static final boolean isHeaderEnd(StringBuilder sb) {
int len = sb.length();
if (len > 2) {
if (LF2.equals(sb.substring(len - 2))) {
return true;
}
}
if (len > 4) {
if (CRLF2.equals(sb.substring(len - 4))) {
return true;
}
}
return false;
}
/**
* Read Http body from input stream as a string basing on the content length on the method.
*
* @param httpHeader
* @return Http body
*/
public synchronized HttpRequestBody readRequestBody(HttpHeader httpHeader) {
int contentLength =
httpHeader.getContentLength(); // -1 = default to unlimited length until connection
// close
HttpRequestBody body =
(contentLength > 0) ? new HttpRequestBody(contentLength) : new HttpRequestBody();
readBody(contentLength, body);
HttpMessage.setContentEncodings(httpHeader, body);
return body;
}
/**
* Read Http body from input stream as a string basing on the content length on the method.
*
* @param httpHeader
* @return Http body
*/
public synchronized HttpResponseBody readResponseBody(HttpHeader httpHeader) {
int contentLength =
httpHeader.getContentLength(); // -1 = default to unlimited length until connection
// close
HttpResponseBody body =
(contentLength > 0) ? new HttpResponseBody(contentLength) : new HttpResponseBody();
readBody(contentLength, body);
return body;
}
private void readBody(int contentLength, HttpBody body) {
int readBodyLength = 0;
int len = 0;
try {
while (contentLength == -1 || readBodyLength < contentLength) {
len =
readBody(
contentLength,
readBodyLength,
mBuffer); // use mBuffer to avoid locally create too many data
// buffer
if (len > 0) {
readBodyLength += len;
} else if (len < 0) {
// ZAP: FindBugs fix
break;
}
body.append(mBuffer, len);
}
} catch (IOException e) {
// read until IO error occur - e.g. connection close
}
}
/**
* @param contentLength Content length read to be read. -1 = unlimited until connection close.
* @param readBodyLength Body length read so far
* @param buffer Buffer storing the read bytes.
* @return Number of bytes read in buffer
* @throws IOException
*/
private int readBody(int contentLength, int readBodyLength, byte[] buffer) throws IOException {
int len = 0;
int remainingLen = 0;
if (contentLength == -1) {
// len = in.read(buffer);
len = super.read(buffer);
} else {
remainingLen = contentLength - readBodyLength;
if (remainingLen <= buffer.length && remainingLen > 0) {
// len = in.read(buffer,0,remainingLen);
len = super.read(buffer, 0, remainingLen);
} else if (remainingLen > buffer.length) {
// len = in.read(buffer);
len = super.read(buffer);
}
}
return len;
}
public void setSocket(Socket socket) {
mSocket = socket;
}
@Override
public synchronized int available() throws IOException {
int avail = 0;
// int oneByte = -1;
int timeout = 0;
avail = super.available();
if (avail == 0 && mSocket != null && mSocket instanceof SSLSocket) {
try {
timeout = mSocket.getSoTimeout();
mSocket.setSoTimeout(1);
super.mark(256);
super.read();
super.reset();
avail = super.available();
} catch (SocketTimeoutException e) {
avail = 0;
} finally {
mSocket.setSoTimeout(timeout);
}
}
return avail;
}
@Override
public int read() throws IOException {
// return in.read();
return super.read();
}
@Override
public int read(byte[] b) throws IOException {
return super.read(b);
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
return super.read(b, off, len);
}
@Override
public void close() {
try {
super.close();
} catch (Exception e) {
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy