All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.parosproxy.paros.network.HttpInputStream Maven / Gradle / Ivy

Go to download

The Zed Attack Proxy (ZAP) is an easy to use integrated penetration testing tool for finding vulnerabilities in web applications. It is designed to be used by people with a wide range of security experience and as such is ideal for developers and functional testers who are new to penetration testing. ZAP provides automated scanners as well as a set of tools that allow you to find security vulnerabilities manually.

There is a newer version: 2.15.0
Show newest version
/*
 * 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 Logger log = 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) {
            log.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 - 2024 Weber Informatics LLC | Privacy Policy