Package org.parosproxy.paros.network

Source Code of org.parosproxy.paros.network.HttpSender

/*
*
* 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.
*/
package org.parosproxy.paros.network;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.NTCredentials;
import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.parosproxy.paros.Constant;

public class HttpSender {

  private static ProtocolSocketFactory sslFactory = null;
  private static Protocol protocol = null;

  static {

    try {
      protocol = Protocol.getProtocol("https");
      sslFactory = protocol.getSocketFactory();
    } catch (Exception e) {
    }
   
    // avoid init again if already initialized
    if (sslFactory == null || !(sslFactory instanceof SSLConnector)) {
      Protocol.registerProtocol("https", new Protocol("https",
          (ProtocolSocketFactory) new SSLConnector(), 443));
    }
  }

  private static HttpMethodHelper helper = new HttpMethodHelper();
 
  private static String userAgent = "";
 
  private HttpClient client = null;
  private HttpClient clientViaProxy = null;
  private ConnectionParam param = null;
  private MultiThreadedHttpConnectionManager httpConnManager = null;
  private MultiThreadedHttpConnectionManager httpConnManagerProxy = null;
  private boolean followRedirect = false;
  private boolean allowState = false;

  public HttpSender(ConnectionParam connectionParam, boolean allowState) {
    this.param = connectionParam;
    this.allowState = allowState;

    client = createHttpClient();
    clientViaProxy = createHttpClientViaProxy();

    if (this.allowState) {
      checkState();
    }
    addAuth(client);
    addAuth(clientViaProxy);
  }

  public static SSLConnector getSSLConnector() {
    return (SSLConnector) protocol.getSocketFactory();
  }

  private void checkState() {
    if (param.isHttpStateEnabled()) {
      client.setState(param.getHttpState());
      clientViaProxy.setState(param.getHttpState());
      client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
      clientViaProxy.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
    } else {
      client.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
      clientViaProxy.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
    }
  }

  private HttpClient createHttpClient() {

    httpConnManager = new MultiThreadedHttpConnectionManager();
    setCommonManagerParams(httpConnManager);
    return new HttpClient(httpConnManager);
  }

  public HttpClient createHttpClientViaProxy() {

    if (param.getProxyChainName().equals("")) {
      return createHttpClient();
    }

    httpConnManagerProxy = new MultiThreadedHttpConnectionManager();
    setCommonManagerParams(httpConnManagerProxy);
    HttpClient clientProxy = new HttpClient(httpConnManagerProxy);
    clientProxy.getHostConfiguration().setProxy(param.getProxyChainName(), param.getProxyChainPort());

    if (!param.getProxyChainUserName().equals("")) {

      // NTCredentials credentials = new NTCredentials(
      // param.getProxyChainUserName(), param.getProxyChainPassword(),
      // param.getProxyChainName(), param.getProxyChainName());
      NTCredentials credentials = new NTCredentials(
          param.getProxyChainUserName(),
          param.getProxyChainPassword(), "",
          param.getProxyChainRealm().equals("")
            ? "" : param.getProxyChainRealm());

      // Below is the original code, but user reported that above code
      // works.
      // UsernamePasswordCredentials credentials = new
      // UsernamePasswordCredentials(
      // param.getProxyChainUserName(), param.getProxyChainPassword());
      AuthScope authScope = new AuthScope(param.getProxyChainName(),
          param.getProxyChainPort(),
          param.getProxyChainRealm().equals("")
            ? AuthScope.ANY_REALM : param.getProxyChainRealm());

      clientProxy.getState().setProxyCredentials(authScope, credentials);
    }

    return clientProxy;
  }

  public int executeMethod(HttpMethod method)
  throws HttpException, IOException
  {
    String hostName = method.getURI().getHost();
    method.setDoAuthentication(true);

    if (param.isUseProxy(hostName)) {
      return clientViaProxy.executeMethod(method);
    } else {
      return client.executeMethod(method);
    }
  }

  public void shutdown() {
    if (httpConnManager != null) {
      httpConnManager.shutdown();
    }
    if (httpConnManagerProxy != null) {
      httpConnManagerProxy.shutdown();
    }
  }

  private void addAuth(HttpClient client) {
    List<HostAuthentication> list = param.getListAuth();
    for (int i = 0; i < list.size(); i++) {
      HostAuthentication auth = (HostAuthentication) list.get(i);
      AuthScope authScope = null;
      NTCredentials credentials = null;
      try {
        authScope = new AuthScope(auth.getHostName(), auth.getPort(),
          (auth.getRealm() == null || auth.getRealm().equals("")) ? AuthScope.ANY_REALM : auth.getRealm());
        credentials = new NTCredentials(auth.getUserName(), auth.getPassword(),
          InetAddress.getLocalHost().getCanonicalHostName(), auth.getHostName());
        client.getState().setCredentials(authScope, credentials);
      } catch (UnknownHostException e1) {
        e1.printStackTrace();
      }
    }
  }

  public void sendAndReceive(HttpMessage msg)
  throws HttpException, IOException {
    sendAndReceive(msg, followRedirect);
  }

  /**
   * Do not use this unless sure what is doing. This method works but proxy
   * may skip the pipe without properly handle the filter.
   *
   * @param msg
   * @param pipe
   * @param buf
   * @throws HttpException
   * @throws IOException
   */
  public void sendAndReceive(HttpMessage msg, HttpOutputStream pipe, byte[] buf)
  throws HttpException, IOException
  {
    sendAndReceive(msg, followRedirect, pipe, buf);
  }

  /**
   * Send and receive a HttpMessage.
   *
   * @param msg
   * @param isFollowRedirect
   * @throws HttpException
   * @throws IOException
   */
  public void sendAndReceive(HttpMessage msg, boolean isFollowRedirect)
  throws HttpException, IOException {

    msg.setTimeSentMillis(System.currentTimeMillis());

    try {
      if (!isFollowRedirect
        || !(msg.getRequestHeader().getMethod().equalsIgnoreCase(HttpRequestHeader.POST)
        || msg.getRequestHeader().getMethod().equalsIgnoreCase(HttpRequestHeader.PUT))) {
       
        send(msg, isFollowRedirect);
        return;
      } else {
        send(msg, false);
      }

      HttpMessage temp = msg.cloneAll();
      // POST/PUT method cannot be redirected by library. Need to follow
      // by code

      // loop 1 time only because httpclient can handle redirect itself
      // after first GET.
      for (int i = 0; i < 1 && (HttpStatusCode.isRedirection(temp.getResponseHeader().getStatusCode())
        && temp.getResponseHeader().getStatusCode() != HttpStatusCode.NOT_MODIFIED); i++) {

        String location = temp.getResponseHeader().getHeader(HttpHeader.LOCATION);
        URI baseUri = temp.getRequestHeader().getURI();
        URI newLocation = new URI(baseUri, location, false);
        temp.getRequestHeader().setURI(newLocation);
        temp.getRequestHeader().setMethod(HttpRequestHeader.GET);
        temp.getRequestHeader().setContentLength(0);
        send(temp, true);
      }

      msg.setResponseHeader(temp.getResponseHeader());
      msg.setResponseBody(temp.getResponseBody());

    } finally {
      msg.setTimeElapsedMillis((int) (System.currentTimeMillis() - msg.getTimeSentMillis()));
    }
  }

  private void send(HttpMessage msg, boolean isFollowRedirect)
  throws HttpException, IOException {
    HttpMethod method = null;
    HttpResponseHeader resHeader = null;

    try {
      method = runMethod(msg, isFollowRedirect);
      // successfully executed;
      resHeader = HttpMethodHelper.getHttpResponseHeader(method);
      resHeader.setHeader(HttpHeader.TRANSFER_ENCODING, null);
      msg.setResponseHeader(resHeader);
      msg.getResponseBody().setCharset(resHeader.getCharset());
      // process response for each listener
      msg.getResponseBody().setLength(0);
      msg.getResponseBody().append(method.getResponseBody());
    } finally {
      if (method != null) {
        method.releaseConnection();
      }
    }

  }

  private HttpMethod runMethod(HttpMessage msg, boolean isFollowRedirect)
  throws HttpException, IOException {
    HttpMethod method = null;
    // no more retry
    modifyUserAgent(msg);
    method = helper.createRequestMethod(msg.getRequestHeader(), msg.getRequestBody());
    method.setFollowRedirects(isFollowRedirect);
    this.executeMethod(method);
    if (allowState) {
      if (param.isHttpStateEnabled()) {
        HttpMethodHelper.updateHttpRequestHeaderSent(msg.getRequestHeader(), method);
      }
    }
    return method;
  }

  public void setFollowRedirect(boolean followRedirect) {
    this.followRedirect = followRedirect;
  }

  private void modifyUserAgent(HttpMessage msg) {
   
    try {
      userAgent = getUserAgent();
     
      // no modification to user agent if empty
      if (userAgent.equals("") || msg.getRequestHeader().isEmpty()) {
        return;
      }
     
      String currentUserAgent = msg.getRequestHeader().getHeader(HttpHeader.USER_AGENT);
      if (currentUserAgent == null) currentUserAgent = "";
     
      if (currentUserAgent.indexOf(userAgent) >= 0) {
        // user agent already in place, exit
        return;
      }

      msg.getRequestHeader().setHeader(HttpHeader.USER_AGENT, userAgent);

    } catch (Exception e) {
    }
  }

  /**
   * @return Returns the userAgent.
   */
  public static String getUserAgent() {
    return userAgent;
  }

  /**
   * @param userAgent
   *            The userAgent to set.
   */
  public static void setUserAgent(String userAgent) {;
    HttpSender.userAgent = userAgent;
  }

  private void setCommonManagerParams(MultiThreadedHttpConnectionManager mgr) {
    mgr.getParams().setSoTimeout(40000);
    mgr.getParams().setStaleCheckingEnabled(true);
    mgr.getParams().setDefaultMaxConnectionsPerHost(
        (Constant.MAX_HOST_CONNECTION > 5) ? 10 : 5 * Constant.MAX_HOST_CONNECTION);
  }

  /**
   * Send and receive a HttpMessage.
   *
   * @param msg
   * @param isFollowRedirect
   * @throws HttpException
   * @throws IOException
   */
  public void sendAndReceive(HttpMessage msg, boolean isFollowRedirect, HttpOutputStream pipe, byte[] buf)
  throws HttpException, IOException
  {

    msg.setTimeSentMillis(System.currentTimeMillis());

    try {
      if (!isFollowRedirect
          || !(msg.getRequestHeader().getMethod().equalsIgnoreCase(HttpRequestHeader.POST)
          || msg.getRequestHeader().getMethod().equalsIgnoreCase(HttpRequestHeader.PUT))) {
        send(msg, isFollowRedirect, pipe, buf);
        return;
      } else {
        send(msg, false, pipe, buf);
      }

      HttpMessage temp = msg.cloneAll();
      // POST/PUT method cannot be redirected by library. Need to follow
      // by code

      // loop 1 time only because httpclient can handle redirect itself
      // after first GET.
      for (int i = 0; i < 1
        && (HttpStatusCode.isRedirection(temp.getResponseHeader().getStatusCode())
        && temp.getResponseHeader().getStatusCode() != HttpStatusCode.NOT_MODIFIED); i++) {

        String location = temp.getResponseHeader().getHeader(HttpHeader.LOCATION);
        URI baseUri = temp.getRequestHeader().getURI();
        URI newLocation = new URI(baseUri, location, false);
        temp.getRequestHeader().setURI(newLocation);
        temp.getRequestHeader().setMethod(HttpRequestHeader.GET);
        temp.getRequestHeader().setContentLength(0);
        send(temp, true, pipe, buf);
      }

      msg.setResponseHeader(temp.getResponseHeader());
      msg.setResponseBody(temp.getResponseBody());

    } finally {
      msg.setTimeElapsedMillis((int) (System.currentTimeMillis() - msg.getTimeSentMillis()));
    }
  }

  /**
   * Do not use this unless sure what is doing. This method works but proxy
   * may skip the pipe without properly handle the filter.
   *
   * @param msg
   * @param isFollowRedirect
   * @param pipe
   * @param buf
   * @throws HttpException
   * @throws IOException
   */
  private void send(HttpMessage msg, boolean isFollowRedirect, HttpOutputStream pipe, byte[] buf)
  throws HttpException, IOException {
   
    HttpMethod method = null;
    HttpResponseHeader resHeader = null;

    try {
      method = runMethod(msg, isFollowRedirect);
      // successfully executed;
      resHeader = HttpMethodHelper.getHttpResponseHeader(method);
      resHeader.setHeader(HttpHeader.TRANSFER_ENCODING, null);
      msg.setResponseHeader(resHeader);
      msg.getResponseBody().setCharset(resHeader.getCharset());
      msg.getResponseBody().setLength(0);
      // process response for each listener
      pipe.write(msg.getResponseHeader());
      pipe.flush();

      if (msg.getResponseHeader().getContentLength() >= 0
        && msg.getResponseHeader().getContentLength() < 20480) {
       
        // save time expanding buffer in HttpBody
        if (msg.getResponseHeader().getContentLength() > 0) {
          msg.getResponseBody().setBody(method.getResponseBody());
          pipe.write(msg.getResponseBody());
          pipe.flush();
        }
      } else {
        InputStream in = method.getResponseBodyAsStream();

        int len = 0;
        while (in != null && (len = in.read(buf)) > 0) {
          pipe.write(buf, 0, len);
          pipe.flush();

          msg.getResponseBody().append(buf, len);
        }
      }
    } finally {
      if (method != null) {
        method.releaseConnection();
      }
    }
  }
}
TOP

Related Classes of org.parosproxy.paros.network.HttpSender

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.