Logo Search packages:      
Sourcecode: paros version File versions  Download package

HttpSender.java

/*
 *
 * 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
 */
00047 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
     */
00219     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
     */
00231     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.
     */
00346     public static String getUserAgent() {
        return userAgent;
    }
    
    /**
     * @param userAgent The userAgent to set.
     */
00353     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
     */
00379     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
     */
00430     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();
              }
        }

        
    }   
    
}

Generated by  Doxygen 1.6.0   Back to index