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;


/**
*
* To change the template for this generated type comment go to
* Window - Preferences - Java - Code Generation - Code and Comments
*/
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);  
    }
   
    private 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;
        hostName = method.getURI().getHost();
        method.setDoAuthentication(true);

//        if (client.getState() != null) {
//            Cookie[] cookie = client.getState().getCookies();
//            for (int i=0; i<cookie.length;i++) {
//                System.out.println(cookie[i].getName() + ":" + cookie[i].getValue());
//            }
//        }
//
//        if (clientViaProxy.getState() != null) {
//            Cookie[] cookie = clientViaProxy.getState().getCookies();
//            for (int i=0; i<cookie.length;i++) {
//                System.out.println(cookie[i].getName() + ":" + cookie[i].getValue());
//            }
//        }
       
        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 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();
            }
            //client.getState().setCredentials(
            //        new HttpAuthRealm(auth.getHostName(), auth.getPort(), (auth.getRealm().equals("") ? null : auth.getRealm())),
            //        new UsernamePasswordCredentials(auth.getUserName(), auth.getPassword())
            //        );
        }
       
        /*List authPrefs = new Vector(3);
        authPrefs.add(AuthPolicy.NTLM);
        authPrefs.add(AuthPolicy.BASIC);
        authPrefs.add(AuthPolicy.DIGEST);
        client.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
        */
    }

    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)//  replaceAll("Transfer-Encoding: chunked\r\n", "");
          msg.setResponseHeader(resHeader);
          msg.getResponseBody().setCharset(resHeader.getCharset());
          // process response for each listner
          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 {
      int status = -1;
    HttpMethod method = null;
    // no more retry
    modifyUserAgent(msg);
        method = helper.createRequestMethod(msg.getRequestHeader(), msg.getRequestBody());
        method.setFollowRedirects(isFollowRedirect);
        status = 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 {
          // no modification to user agent if empty
          if (userAgent.equals("") || msg.getRequestHeader().isEmpty()) {
              return;
          }
         
          // append new user agent to existing user agent
          String currentUserAgent = msg.getRequestHeader().getHeader(HttpHeader.USER_AGENT);
          if (currentUserAgent == null) {
              currentUserAgent = "";
          }

          if (currentUserAgent.indexOf(userAgent) >= 0) {
              // user agent already in place, exit
              return;
          }

          String delimiter = "";
          if (!currentUserAgent.equals("") && !currentUserAgent.endsWith(" ")) {
              delimiter = " ";
          }
         
          currentUserAgent = currentUserAgent + delimiter + userAgent;
          msg.getRequestHeader().setHeader(HttpHeader.USER_AGENT, currentUserAgent);
      } 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);

        // to use for HttpClient 3.0.1
        //mgr.getParams().setDefaultMaxConnectionsPerHost((Constant.MAX_HOST_CONNECTION > 5) ? 15 : 3*Constant.MAX_HOST_CONNECTION);

        //mgr.getParams().setMaxTotalConnections(mgr.getParams().getDefaultMaxConnectionsPerHost()*10);
       
        //mgr.getParams().setConnectionTimeout(60000);  // use default

    }
   
    /**
     * 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)//  replaceAll("Transfer-Encoding: chunked\r\n", "");
          msg.setResponseHeader(resHeader);
          msg.getResponseBody().setCharset(resHeader.getCharset());
            msg.getResponseBody().setLength(0);

          // process response for each listner
         
            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 {
              //byte[] buf = new byte[4096];
              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.