Package railo.runtime.tag

Source Code of railo.runtime.tag.Http4

package railo.runtime.tag;

import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.zip.GZIPInputStream;

import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpOptions;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpTrace;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.FormBodyPart;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;

import railo.commons.io.CharsetUtil;
import railo.commons.io.IOUtil;
import railo.commons.io.SystemUtil;
import railo.commons.io.res.Resource;
import railo.commons.io.res.util.ResourceUtil;
import railo.commons.lang.StringUtil;
import railo.commons.lang.mimetype.ContentType;
import railo.commons.net.HTTPUtil;
import railo.commons.net.URLEncoder;
import railo.commons.net.http.HTTPEngine;
import railo.commons.net.http.Header;
import railo.commons.net.http.httpclient4.CachingGZIPInputStream;
import railo.commons.net.http.httpclient4.HTTPEngine4Impl;
import railo.commons.net.http.httpclient4.HTTPPatchFactory;
import railo.commons.net.http.httpclient4.HTTPResponse4Impl;
import railo.commons.net.http.httpclient4.ResourceBody;
import railo.runtime.config.Config;
import railo.runtime.config.ConfigWeb;
import railo.runtime.engine.ThreadLocalPageContext;
import railo.runtime.exp.ApplicationException;
import railo.runtime.exp.ExpressionException;
import railo.runtime.exp.HTTPException;
import railo.runtime.exp.NativeException;
import railo.runtime.exp.PageException;
import railo.runtime.ext.tag.BodyTagImpl;
import railo.runtime.net.http.MultiPartResponseUtils;
import railo.runtime.net.http.ReqRspUtil;
import railo.runtime.net.proxy.ProxyData;
import railo.runtime.net.proxy.ProxyDataImpl;
import railo.runtime.op.Caster;
import railo.runtime.text.csv.CSVParser;
import railo.runtime.type.Array;
import railo.runtime.type.ArrayImpl;
import railo.runtime.type.Collection.Key;
import railo.runtime.type.KeyImpl;
import railo.runtime.type.Query;
import railo.runtime.type.QueryImpl;
import railo.runtime.type.Struct;
import railo.runtime.type.StructImpl;
import railo.runtime.type.dt.DateTime;
import railo.runtime.type.util.KeyConstants;
import railo.runtime.type.util.ListUtil;
import railo.runtime.util.URLResolver;

// MUST change behavor of mltiple headers now is a array, it das so?

/**
* Lets you execute HTTP POST and GET operations on files. Using cfhttp, you can execute standard
*   GET operations and create a query object from a text file. POST operations lets you upload MIME file
*   types to a server, or post cookie, formfield, URL, file, or CGI variables directly to a specified server.
*
*
*
*
**/
public final class Http4 extends BodyTagImpl implements Http {

  public static final String MULTIPART_RELATED = "multipart/related";
  public static final String MULTIPART_FORM_DATA = "multipart/form-data";
 
 
 
    /**
     * Maximum redirect count (5)
     */
    public static final short MAX_REDIRECT=15;
   
    /**
     * Constant value for HTTP Status Code "moved Permanently 301"
     */
    public static final int STATUS_REDIRECT_MOVED_PERMANENTLY=301;
    /**
     * Constant value for HTTP Status Code "Found 302"
     */
    public static final int STATUS_REDIRECT_FOUND=302;
    /**
     * Constant value for HTTP Status Code "see other 303"
     */
    public static final int STATUS_REDIRECT_SEE_OTHER=303;
   

    public static final int STATUS_REDIRECT_TEMPORARY_REDIRECT = 307;


     
   
   

  private static final short METHOD_GET=0;
  private static final short METHOD_POST=1;
  private static final short METHOD_HEAD=2;
  private static final short METHOD_PUT=3;
  private static final short METHOD_DELETE=4;
  private static final short METHOD_OPTIONS=5;
  private static final short METHOD_TRACE=6;
  private static final short METHOD_PATCH=7;
 
  private static final String NO_MIMETYPE="Unable to determine MIME type of file.";
 
  private static final short GET_AS_BINARY_NO=0;
  private static final short GET_AS_BINARY_YES=1;
  private static final short GET_AS_BINARY_AUTO=2;

  private static final Key STATUSCODE = KeyConstants._statuscode;
  private static final Key CHARSET = KeyConstants._charset;
 
  private static final Key ERROR_DETAIL = KeyImpl.intern("errordetail");
  private static final Key STATUS_CODE = KeyImpl.intern("status_code");
  private static final Key STATUS_TEXT = KeyImpl.intern("status_text");
  private static final Key HTTP_VERSION = KeyImpl.intern("http_version");
 

  private static final Key FILE_CONTENT = KeyImpl.intern("filecontent");
  private static final Key EXPLANATION = KeyImpl.intern("explanation");
  private static final Key RESPONSEHEADER = KeyImpl.intern("responseheader");
  private static final Key SET_COOKIE = KeyImpl.intern("set-cookie");
 
  private static final short AUTH_TYPE_BASIC = 0;
  private static final short AUTH_TYPE_NTLM = 1;

 
 
 
  static {
      //Protocol myhttps = new Protocol("https", new EasySSLProtocolSocketFactory(), 443);
      //Protocol.registerProtocol("https", new Protocol("https", new EasySSLProtocolSocketFactory(), 443));
  }
 

    private ArrayList<HttpParamBean> params=new ArrayList<HttpParamBean>();
 
 
  /** When required by a server, a valid password. */
  private String password;

  /** Required for creating a query. Options are a tab or comma. Default is a comma. */
  private char delimiter=',';

  /** Yes or No. Default is No. For GET and POST operations, if Yes, page reference returned into the
  **   fileContent internal variable has its internal URLs fully resolved, including port number, so that
  **   links remain intact. */
  private boolean resolveurl;

  /** A value, in seconds. When a URL timeout is specified in the browser */
  private long timeout=-1;

  /** Host name or IP address of a proxy server. */
  private String proxyserver;

  /** The filename to be used for the file that is accessed. For GET operations, defaults to the name
  **   pecified in url. Enter path information in the path attribute. */
  private String strFile;

  /** The path to the directory in which a file is to be stored. If a path is not specified in a POST
  **   or GET operation, a variable is created (cfhttp.fileContent) that you can use to display the results
  **   of the POST operation in a cfoutput. */
  private String strPath;

  /** Boolean indicating whether to throw an exception that can be caught by using the cftry and
  **   cfcatch tags. The default is NO. */
  private boolean throwonerror;

  /** set the charset for the call. */
  private String charset=null;

  /** The port number on the proxy server from which the object is requested. Default is 80. When
  **   used with resolveURL, the URLs of retrieved documents that specify a port number are automatically
  **   resolved to preserve links in the retrieved document. */
  private int proxyport=80;

  /** Specifies the column names for a query when creating a query as a result of a cfhttp GET. */
  private String[] columns;

  /** The port number on the server from which the object is requested. Default is 80. When used with
  **   resolveURL, the URLs of retrieved documents that specify a port number are automatically resolved to
  **   preserve links in the retrieved document. If a port number is specified in the url attribute, the port
  **   value overrides the value of the port attribute. */
  private int port=-1;

  /** User agent request header. */
  private String useragent="Railo (CFML Engine)";

  /** Required for creating a query. Indicates the start and finish of a column. Should be
  **   appropriately escaped when embedded in a column. For example, if the qualifier is a double quotation
  **   mark, it should be escaped as """". If there is no text qualifier in the file, specify it as " ".
  **   Default is the double quotation mark ("). */
  private char textqualifier='"';

  /** When required by a server, a valid username. */
  private String username;

  /** Full URL of the host name or IP address of the server on which the file resides. The URL must be
  **   an absolute URL, including the protocol (http or https) and hostname. It may optionally contain a port
  **   number. Port numbers specified in the url attribute override the port attribute. */
  private String url;

  /** Boolean indicating whether to redirect execution or stop execution.*/
  private boolean redirect=true;


  /** The name to assign to a query if the a query is constructed from a file. */
  private String name;

  /** GET or POST. Use GET to download a text or binary file or to create a query from the contents
  **   of a text file. Use POST to send information to a server page or a CGI program for processing. POST
  **   requires the use of a cfhttpparam tag. */
  private short method=METHOD_GET;

  //private boolean hasBody=false;
 
  private boolean firstrowasheaders=true;

  private String proxyuser=null;
  private String proxypassword="";
  private boolean multiPart=false;
  private String multiPartType=MULTIPART_FORM_DATA;
 
  private short getAsBinary=GET_AS_BINARY_NO;
    private String result="cfhttp";
   
    private boolean addtoken=false;
   
    private short authType=AUTH_TYPE_BASIC;
    private String workStation=null;
    private String domain=null;
  private boolean preauth=true;
  private boolean encoded=true;
 
  private boolean compression=true;

 
  @Override
  public void release()  {
    super.release();
      params.clear();
    password=null;
    delimiter=',';
    resolveurl=false;
    timeout=-1L;
    proxyserver=null;
    proxyport=80;
    proxyuser=null;
    proxypassword="";
    strFile=null;
    throwonerror=false;
    charset=null;
    columns=null;
    port=-1;
    useragent="Railo (CFML Engine)";
    textqualifier='"';
    username=null;
    url=null;
    redirect=true;
    strPath=null;
    name=null;
    method=METHOD_GET;
    //hasBody=false;
    firstrowasheaders=true;
   
    getAsBinary=GET_AS_BINARY_NO;
    multiPart=false;
    multiPartType=MULTIPART_FORM_DATA;
        result="cfhttp";
        addtoken=false;
       
        authType=AUTH_TYPE_BASIC;
        workStation=null;
        domain=null;
        preauth=true;
        encoded=true;
        compression=true;
  }
 
  /**
   * @param firstrowasheaders
   */
  public void setFirstrowasheaders(boolean firstrowasheaders)  {
    this.firstrowasheaders=firstrowasheaders;
  }
 

  public void setEncoded(boolean encoded)  {
    this.encoded=encoded;
  }


  /** set the value password
  *  When required by a server, a valid password.
  * @param password value to set
  **/
  public void setPassword(String password)  {
    this.password=password;
  }
  /** set the value password
  *  When required by a proxy server, a valid password.
  * @param proxypassword value to set
  **/
  public void setProxypassword(String proxypassword)  {
    this.proxypassword=proxypassword;
  }

  /** set the value delimiter
  *  Required for creating a query. Options are a tab or comma. Default is a comma.
  * @param delimiter value to set
  **/
  public void setDelimiter(String delimiter)  {
    this.delimiter=delimiter.length()==0?',':delimiter.charAt(0);
  }

  /** set the value resolveurl
  *  Yes or No. Default is No. For GET and POST operations, if Yes, page reference returned into the
  *   fileContent internal variable has its internal URLs fully resolved, including port number, so that
  *   links remain intact.
  * @param resolveurl value to set
  **/
  public void setResolveurl(boolean resolveurl)  {
    this.resolveurl=resolveurl;
  }
 
  public void setPreauth(boolean preauth)  {
    this.preauth=preauth;
  }
 
 

  /** set the value timeout
  * @param timeout value to set
   * @throws ExpressionException
  **/
  public void setTimeout(double timeout) throws ExpressionException  {
    if(timeout<0)
      throw new ExpressionException("invalid value ["+Caster.toString(timeout)+"] for attribute timeout, value must be a positive integer greater or equal than 0");
   
      long requestTimeout = pageContext.getRequestTimeout();
      long _timeout=(long)(timeout*1000D);
      this.timeout=requestTimeout<_timeout?requestTimeout:_timeout;
    //print.out("this.timeout:"+this.timeout);
  }

  /** set the value proxyserver
  *  Host name or IP address of a proxy server.
  * @param proxyserver value to set
  **/
  public void setProxyserver(String proxyserver)  {
    this.proxyserver=proxyserver;
  }
 
  /** set the value proxyport
  *  The port number on the proxy server from which the object is requested. Default is 80. When
  *   used with resolveURL, the URLs of retrieved documents that specify a port number are automatically
  *   resolved to preserve links in the retrieved document.
  * @param proxyport value to set
  **/
  public void setProxyport(double proxyport)  {
    this.proxyport=(int)proxyport;
  }

  /** set the value file
  *  The filename to be used for the file that is accessed. For GET operations, defaults to the name
  *   pecified in url. Enter path information in the path attribute.
  * @param file value to set
  **/
  public void setFile(String file)  {
    this.strFile=file;
  }

  /** set the value throwonerror
  *  Boolean indicating whether to throw an exception that can be caught by using the cftry and
  *   cfcatch tags. The default is NO.
  * @param throwonerror value to set
  **/
  public void setThrowonerror(boolean throwonerror)  {
    this.throwonerror=throwonerror;
  }

  /** set the value charset
  *  set the charset for the call.
  * @param charset value to set
  **/
  public void setCharset(String charset)  {
    this.charset=charset;
  }

  /** set the value columns
  * @param columns value to set
   * @throws PageException
  **/
  public void setColumns(String columns) throws PageException  {
    this.columns=ListUtil.toStringArray(ListUtil.listToArrayRemoveEmpty(columns,","));
  }

  /** set the value port
  *  The port number on the server from which the object is requested. Default is 80. When used with
  *   resolveURL, the URLs of retrieved documents that specify a port number are automatically resolved to
  *   preserve links in the retrieved document. If a port number is specified in the url attribute, the port
  *   value overrides the value of the port attribute.
  * @param port value to set
  **/
  public void setPort(double port)  {
    this.port=(int) port;
  }

  /** set the value useragent
  *  User agent request header.
  * @param useragent value to set
  **/
  public void setUseragent(String useragent)  {
    this.useragent=useragent;
  }

  /** set the value textqualifier
  *  Required for creating a query. Indicates the start and finish of a column. Should be
  *   appropriately escaped when embedded in a column. For example, if the qualifier is a double quotation
  *   mark, it should be escaped as """". If there is no text qualifier in the file, specify it as " ".
  *   Default is the double quotation mark (").
  * @param textqualifier value to set
  **/
  public void setTextqualifier(String textqualifier)  {
    this.textqualifier=textqualifier.length()==0?'"':textqualifier.charAt(0);
  }

  /** set the value username
  *  When required by a proxy server, a valid username.
  * @param proxyuser value to set
  **/
  public void setProxyuser(String proxyuser)  {
    this.proxyuser=proxyuser;
  }

  /** set the value username
  *  When required by a server, a valid username.
  * @param username value to set
  **/
  public void setUsername(String username)  {
    this.username=username;
  }

  /** set the value url
  *  Full URL of the host name or IP address of the server on which the file resides. The URL must be
  *   an absolute URL, including the protocol (http or https) and hostname. It may optionally contain a port
  *   number. Port numbers specified in the url attribute override the port attribute.
  * @param url value to set
  **/
  public void setUrl(String url)  {
    this.url=url;
  }

  /** set the value redirect
  * @param redirect value to set
  **/
  public void setRedirect(boolean redirect)  {
    this.redirect=redirect;
  }

  /** set the value path
  *  The path to the directory in which a file is to be stored. If a path is not specified in a POST
  *   or GET operation, a variable is created (cfhttp.fileContent) that you can use to display the results
  *   of the POST operation in a cfoutput.
  * @param path value to set
  **/
  public void setPath(String path)  {
    this.strPath=path;
  }

  /** set the value name
  *  The name to assign to a query if the a query is constructed from a file.
  * @param name value to set
  **/
  public void setName(String name)  {
    this.name=name;
  }
 
  public void setAuthtype(String strAuthType) throws ExpressionException{
    if(StringUtil.isEmpty(strAuthType,true)) return;
    strAuthType=strAuthType.trim();
    if("basic".equalsIgnoreCase(strAuthType)) authType=AUTH_TYPE_BASIC;
    else if("ntlm".equalsIgnoreCase(strAuthType)) authType=AUTH_TYPE_NTLM;
    else
      throw new ExpressionException("invalid value ["+strAuthType+"] for attribute authType, value must be one of the following [basic,ntlm]");
  }

  public void setWorkstation(String workStation)  {
    this.workStation=workStation;
  }

  public void setDomain(String domain)  {
    this.domain=domain;
  }

  /** set the value method
  *  GET or POST. Use GET to download a text or binary file or to create a query from the contents
  *   of a text file. Use POST to send information to a server page or a CGI program for processing. POST
  *   requires the use of a cfhttpparam tag.
  * @param method value to set
   * @throws ApplicationException
  **/
  public void setMethod(String method) throws ApplicationException  {
      method=method.toLowerCase().trim();
      if(method.equals("post")) this.method=METHOD_POST;
      else if(method.equals("get")) this.method=METHOD_GET;
      else if(method.equals("head")) this.method=METHOD_HEAD;
      else if(method.equals("delete")) this.method=METHOD_DELETE;
      else if(method.equals("put")) this.method=METHOD_PUT;
      else if(method.equals("trace")) this.method=METHOD_TRACE;
      else if(method.equals("options")) this.method=METHOD_OPTIONS;
      else if(method.equals("patch")) this.method=METHOD_PATCH;
      else throw new ApplicationException("invalid method type ["+(method.toUpperCase())+"], valid types are POST,GET,HEAD,DELETE,PUT,TRACE,OPTIONS,PATCH");
  }
 
  public void setCompression(String strCompression) throws ApplicationException {
    if(StringUtil.isEmpty(strCompression,true)) return;
    Boolean b = Caster.toBoolean(strCompression,null);
   
    if(b!=null) compression=b.booleanValue();
    else if(strCompression.trim().equalsIgnoreCase("none")) compression=false;
      else throw new ApplicationException("invalid value for attribute compression ["+strCompression+"], valid values are: true,false or none");
   
  }


  @Override
  public int doStartTag()  {
    if(addtoken) {
      setParam("cookie","cfid",pageContext.getCFID());
      setParam("cookie","cftoken",pageContext.getCFToken());
      String jsessionid = pageContext.getJSessionId();
      if(jsessionid!=null)setParam("cookie","jsessionid",jsessionid);
    }
   
    return EVAL_BODY_INCLUDE;
  }

  private void setParam(String type, String name, String value) {
    HttpParamBean hpb = new HttpParamBean();
    hpb.setType(type);
    hpb.setName(name);
    hpb.setValue(value);
    setParam(hpb);
  }

  @Override
  public int doEndTag() throws PageException {
      Struct cfhttp=new StructImpl();
    cfhttp.setEL(ERROR_DETAIL,"");
    pageContext.setVariable(result,cfhttp);

    // because commons
    PrintStream out = System.out;
        try {
          //System.setOut(new PrintStream(DevNullOutputStream.DEV_NULL_OUTPUT_STREAM));
             _doEndTag(cfhttp);
             return EVAL_PAGE;
        }
        catch (IOException e) {
            throw Caster.toPageException(e);
        }
        finally {
          System.setOut(out);
        }

  }

 
 
  private void _doEndTag(Struct cfhttp) throws PageException, IOException  {
    BasicHttpParams params = new BasicHttpParams();
      DefaultHttpClient client = HTTPEngine4Impl.createClient(params,redirect?HTTPEngine.MAX_REDIRECT:0);
     
     
      ConfigWeb cw = pageContext.getConfig();
      HttpRequestBase req=null;
      HttpContext httpContext=null;
    //HttpRequestBase req = init(pageContext.getConfig(),this,client,params,url,port);
      {
        if(StringUtil.isEmpty(charset,true)) charset=cw.getWebCharset();
        else charset=charset.trim();
       
       
      // check if has fileUploads 
        boolean doUploadFile=false;
        for(int i=0;i<this.params.size();i++) {
          if((this.params.get(i)).getType().equalsIgnoreCase("file")) {
            doUploadFile=true;
            break;
          }
        } 
     
      // parse url (also query string)
        int len=this.params.size();
        StringBuilder sbQS=new StringBuilder();
        for(int i=0;i<len;i++) {
          HttpParamBean param=this.params.get(i);
          String type=param.getType();
        // URL
          if(type.equals("url")) {
            if(sbQS.length()>0)sbQS.append('&');
            sbQS.append(param.getEncoded()?urlenc(param.getName(),charset):param.getName());
            sbQS.append('=');
            sbQS.append(param.getEncoded()?urlenc(param.getValueAsString(), charset):param.getValueAsString());
          }
        }
        String host=null;
        HttpHost httpHost;
        try {
          URL _url = HTTPUtil.toURL(url,port,encoded);
          httpHost = new HttpHost(_url.getHost(),_url.getPort());
          host=_url.getHost();
          url=_url.toExternalForm();
          if(sbQS.length()>0){
            // no existing QS
            if(StringUtil.isEmpty(_url.getQuery())) {
              url+="?"+sbQS;
            }
            else {
              url+="&"+sbQS;
            }
          }
        }
        catch (MalformedURLException mue) {
          throw Caster.toPageException(mue);
        }
       
      // select best matching method (get,post, post multpart (file))

        boolean isBinary = false;
        boolean doMultiPart=doUploadFile || this.multiPart;
        HttpPost post=null;
        HttpEntityEnclosingRequest eem=null;
       
       
        if(this.method==METHOD_GET) {
          req=new HttpGet(url);
        }
        else if(this.method==METHOD_HEAD) {
            req=new HttpHead(url);
        }
        else if(this.method==METHOD_DELETE) {
          isBinary=true;
            req=new HttpDelete(url);
        }
        else if(this.method==METHOD_PUT) {
          isBinary=true;
          HttpPut put = new HttpPut(url);
            req=put;
            eem=put;
           
        }
        else if(this.method==METHOD_TRACE) {
          isBinary=true;
            req=new HttpTrace(url);
        }
        else if(this.method==METHOD_OPTIONS) {
          isBinary=true;
            req=new HttpOptions(url);
        }
        else if(this.method==METHOD_PATCH) {
          isBinary=true;
          eem = HTTPPatchFactory.getHTTPPatch(url);
            req=(HttpRequestBase) eem;
        }
        else {
          isBinary=true;
          post=new HttpPost(url);
          req=post;
          eem=post;
        }
       
        boolean hasForm=false;
        boolean hasBody=false;
        boolean hasContentType=false;
      // Set http params
        ArrayList<FormBodyPart> parts=new ArrayList<FormBodyPart>();
       
        StringBuilder acceptEncoding=new StringBuilder();
        java.util.List<NameValuePair> postParam = post!=null?new ArrayList <NameValuePair>():null;
           
        for(int i=0;i<len;i++) {
          HttpParamBean param=this.params.get(i);
          String type=param.getType();
         
        // URL
          if(type.equals("url")) {
            //listQS.add(new BasicNameValuePair(translateEncoding(param.getName(), http.charset),translateEncoding(param.getValueAsString(), http.charset)));
          }
        // Form
          else if(type.equals("formfield") || type.equals("form")) {
            hasForm=true;
            if(this.method==METHOD_GET) throw new ApplicationException("httpparam type formfield can't only be used, when method of the tag http equal post");
            if(post!=null){
              if(doMultiPart)  {
                parts.add(
                  new FormBodyPart(
                    param.getName(),
                    new StringBody(
                        param.getValueAsString(),
                        CharsetUtil.toCharset(charset)
                    )
                  )
                );
              }
              else {
                postParam.add(new BasicNameValuePair(param.getName(),param.getValueAsString()));
              }
            }
            //else if(multi!=null)multi.addParameter(param.getName(),param.getValueAsString());
          }
        // CGI
          else if(type.equals("cgi")) {
            if(param.getEncoded())
              req.addHeader(
                  urlenc(param.getName(),charset),
                  urlenc(param.getValueAsString(),charset));
                    else
                        req.addHeader(param.getName(),param.getValueAsString());
          }
            // Header
                else if(type.startsWith("head")) {
                  if(param.getName().equalsIgnoreCase("content-type")) hasContentType=true;
                 
                  if(param.getName().equalsIgnoreCase("Content-Length")) {}
                  else if(param.getName().equalsIgnoreCase("Accept-Encoding")) {
                    acceptEncoding.append(headerValue(param.getValueAsString()));
                    acceptEncoding.append(", ");
                  }
                  else req.addHeader(param.getName(),headerValue(param.getValueAsString()));
                }
        // Cookie
          else if(type.equals("cookie")) {
            HTTPEngine4Impl.addCookie(client,host,param.getName(),param.getValueAsString(),"/",charset);
          }
        // File
          else if(type.equals("file")) {
            hasForm=true;
            if(this.method==METHOD_GET) throw new ApplicationException("httpparam type file can't only be used, when method of the tag http equal post");
            String strCT = getContentType(param);
            ContentType ct = HTTPUtil.toContentType(strCT,null);
             
            String mt="text/xml";
            if(ct!=null && !StringUtil.isEmpty(ct.getMimeType(),true)) mt=ct.getMimeType();
           
            String cs=charset;
            if(ct!=null && !StringUtil.isEmpty(ct.getCharset(),true)) cs=ct.getCharset();
           
           
            if(doMultiPart) {
              try {
                Resource res = param.getFile();
                parts.add(new FormBodyPart(
                    param.getName(),
                    new ResourceBody(res, mt, res.getName(), cs)
                ));
                //parts.add(new ResourcePart(param.getName(),new ResourcePartSource(param.getFile()),getContentType(param),_charset));
              }
              catch (FileNotFoundException e) {
                throw new ApplicationException("can't upload file, path is invalid",e.getMessage());
              }
            }
          }
        // XML
          else if(type.equals("xml")) {
            ContentType ct = HTTPUtil.toContentType(param.getMimeType(),null);
             
            String mt="text/xml";
            if(ct!=null && !StringUtil.isEmpty(ct.getMimeType(),true)) mt=ct.getMimeType();
           
            String cs=charset;
            if(ct!=null && !StringUtil.isEmpty(ct.getCharset(),true)) cs=ct.getCharset();
           
            hasBody=true;
            hasContentType=true;
            req.addHeader("Content-type", mt+"; charset="+cs);
              if(eem==null)throw new ApplicationException("type xml is only supported for type post and put");
              HTTPEngine4Impl.setBody(eem, param.getValueAsString(),mt,cs);
          }
        // Body
          else if(type.equals("body")) {
            ContentType ct = HTTPUtil.toContentType(param.getMimeType(),null);
             
            String mt=null;
            if(ct!=null && !StringUtil.isEmpty(ct.getMimeType(),true)) mt=ct.getMimeType();
           
            String cs=charset;
            if(ct!=null && !StringUtil.isEmpty(ct.getCharset(),true)) cs=ct.getCharset();
           
           
            hasBody=true;
            if(eem==null)throw new ApplicationException("type body is only supported for type post and put");
            HTTPEngine4Impl.setBody(eem, param.getValue(),mt,cs);
           
          }
                else {
                    throw new ApplicationException("invalid type ["+type+"]");
                }
           
        }
       
        // post params
        if(postParam!=null && postParam.size()>0)
          post.setEntity(new org.apache.http.client.entity.UrlEncodedFormEntity(postParam,charset));
       
        if(compression){
          acceptEncoding.append("gzip");
        }
        else {
          acceptEncoding.append("deflate;q=0");
          req.setHeader("TE", "deflate;q=0");
        }
      req.setHeader("Accept-Encoding",acceptEncoding.toString());
       
       
       
        // multipart
        if(doMultiPart && eem!=null) {
          hasContentType=true;
          boolean doIt=true;
          if(!this.multiPart && parts.size()==1){
            ContentBody body = parts.get(0).getBody();
            if(body instanceof StringBody){
              StringBody sb=(StringBody)body;
              try {
                org.apache.http.entity.ContentType ct=org.apache.http.entity.ContentType.create(sb.getMimeType(),sb.getCharset());
                String str = IOUtil.toString(sb.getReader());
                StringEntity entity = new StringEntity(str,ct);
                eem.setEntity(entity);
               
              } catch (IOException e) {
                throw Caster.toPageException(e);
              }
              doIt=false;
            }
          }
          if(doIt) {
            MultipartEntity mpe = new MultipartEntity(HttpMultipartMode.STRICT);
            Iterator<FormBodyPart> it = parts.iterator();
            while(it.hasNext()) {
              FormBodyPart part = it.next();
              mpe.addPart(part.getName(),part.getBody());
            }
            eem.setEntity(mpe);
          }
            //eem.setRequestEntity(new MultipartRequestEntityFlex(parts.toArray(new Part[parts.size()]), eem.getParams(),http.multiPartType));
        }
       
       
       
        if(hasBody && hasForm)
          throw new ApplicationException("mixing httpparam  type file/formfield and body/XML is not allowed");
     
        if(!hasContentType) {
          if(isBinary) {
            if(hasBody) req.addHeader("Content-type", "application/octet-stream");
            else req.addHeader("Content-type", "application/x-www-form-urlencoded; charset="+charset);
          }
          else {
            if(hasBody)
              req.addHeader("Content-type", "text/html; charset="+charset );
          }
        }
       
       
        // set User Agent
          if(!hasHeaderIgnoreCase(req,"User-Agent"))
            req.setHeader("User-Agent",this.useragent);
       
      // set timeout
        if(this.timeout>0L)HTTPEngine4Impl.setTimeout(params, (int)this.timeout);
       
      // set Username and Password
        if(this.username!=null) {
          if(this.password==null)this.password="";
          if(AUTH_TYPE_NTLM==this.authType) {
            if(StringUtil.isEmpty(this.workStation,true))
                      throw new ApplicationException("attribute workstation is required when authentication type is [NTLM]");
            if(StringUtil.isEmpty(this.domain,true))
                      throw new ApplicationException("attribute domain is required when authentication type is [NTLM]");
             
            HTTPEngine4Impl.setNTCredentials(client, this.username, this.password, this.workStation,this.domain);
          }
          else httpContext=HTTPEngine4Impl.setCredentials(client, httpHost, this.username, this.password,preauth);
        }
     
      // set Proxy
        ProxyData proxy=null;
        if(!StringUtil.isEmpty(this.proxyserver)) {
          proxy=ProxyDataImpl.getInstance(this.proxyserver, this.proxyport, this.proxyuser, this.proxypassword) ;
        }
        if(pageContext.getConfig().isProxyEnableFor(host)) {
          proxy=pageContext.getConfig().getProxyData();
        }
        HTTPEngine4Impl.setProxy(client, req, proxy);
       
      }
     
     
     
     
     
      try {
      if(httpContext==null)httpContext = new BasicHttpContext();
       
/////////////////////////////////////////// EXECUTE /////////////////////////////////////////////////
    Executor4 e = new Executor4(this,client,httpContext,req,redirect);
    HTTPResponse4Impl rsp=null;
    if(timeout<0){
      try{
        rsp = e.execute(httpContext);
      }
     
      catch(Throwable t){
        if(!throwonerror){
          setUnknownHost(cfhttp, t);
          return;
        }
        throw toPageException(t);
       
      }
    }
    else {
      e.start();
      try {
        synchronized(this){//print.err(timeout);
          this.wait(timeout);
        }
      } catch (InterruptedException ie) {
        throw Caster.toPageException(ie);
      }
      if(e.t!=null){
        if(!throwonerror){
          setUnknownHost(cfhttp,e.t);
          return;
        }
        throw toPageException(e.t)
      }
     
      rsp=e.response;
     
     
      if(!e.done){
        req.abort();
        if(throwonerror)
          throw new HTTPException("408 Request Time-out","a timeout occurred in tag http",408,"Time-out",rsp.getURL());
        setRequestTimeout(cfhttp)
        return;
        //throw new ApplicationException("timeout"); 
      }
    }
   
/////////////////////////////////////////// EXECUTE /////////////////////////////////////////////////
    Charset responseCharset=CharsetUtil.toCharset(rsp.getCharset());
  // Write Response Scope
    //String rawHeader=httpMethod.getStatusLine().toString();
      String mimetype=null;
      String contentEncoding=null;
     
    // status code
      cfhttp.set(STATUSCODE,((rsp.getStatusCode()+" "+rsp.getStatusText()).trim()));
      cfhttp.set(STATUS_CODE,new Double(rsp.getStatusCode()));
      cfhttp.set(STATUS_TEXT,(rsp.getStatusText()));
      cfhttp.set(HTTP_VERSION,(rsp.getProtocolVersion()));
     
    //responseHeader
      railo.commons.net.http.Header[] headers = rsp.getAllHeaders();
      StringBuffer raw=new StringBuffer(rsp.getStatusLine()+" ");
      Struct responseHeader = new StructImpl();
      Struct cookie;
      Array setCookie = new ArrayImpl();
      Query cookies=new QueryImpl(new String[]{"name","value","path","domain","expires","secure","httpOnly"},0,"cookies");
     
          for(int i=0;i<headers.length;i++) {
            railo.commons.net.http.Header header=headers[i];
            //print.ln(header);
           
            raw.append(header.toString()+" ");
            if(header.getName().equalsIgnoreCase("Set-Cookie")) {
              setCookie.append(header.getValue());
              parseCookie(cookies,header.getValue());
            }
            else {
                //print.ln(header.getName()+"-"+header.getValue());
              Object value=responseHeader.get(KeyImpl.getInstance(header.getName()),null);
              if(value==null) responseHeader.set(KeyImpl.getInstance(header.getName()),header.getValue());
              else {
                  Array arr=null;
                  if(value instanceof Array) {
                      arr=(Array) value;
                  }
                  else {
                      arr=new ArrayImpl();
                      responseHeader.set(KeyImpl.getInstance(header.getName()),arr);
                      arr.appendEL(value);
                  }
                  arr.appendEL(header.getValue());
              }
            }
           
            // Content-Type
            if(header.getName().equalsIgnoreCase("Content-Type")) {
              mimetype=header.getValue();
              if(mimetype==null)mimetype=NO_MIMETYPE;
            }
           
            // Content-Encoding
            if(header.getName().equalsIgnoreCase("Content-Encoding")) {
              contentEncoding=header.getValue();
            }
           
          }
          cfhttp.set(RESPONSEHEADER,responseHeader);
          cfhttp.set(KeyConstants._cookies,cookies);
          responseHeader.set(STATUS_CODE,new Double(rsp.getStatusCode()));
          responseHeader.set(EXPLANATION,(rsp.getStatusText()));
          if(setCookie.size()>0)responseHeader.set(SET_COOKIE,setCookie);
         
      // is text
          boolean isText=
            mimetype == null || 
            mimetype == NO_MIMETYPE || HTTPUtil.isTextMimeType(mimetype);
           
        // is multipart
          boolean isMultipart= MultiPartResponseUtils.isMultipart(mimetype);       
        
          cfhttp.set(KeyConstants._text,Caster.toBoolean(isText));
         
      // mimetype charset
          //boolean responseProvideCharset=false;
          if(!StringUtil.isEmpty(mimetype,true)){
            if(isText) {
              String[] types=HTTPUtil.splitMimeTypeAndCharset(mimetype,null);
              if(types[0]!=null)cfhttp.set(KeyConstants._mimetype,types[0]);
              if(types[1]!=null)cfhttp.set(CHARSET,types[1]);
                 
            }
            else cfhttp.set(KeyConstants._mimetype,mimetype);
          }
          else cfhttp.set(KeyConstants._mimetype,NO_MIMETYPE);

      // File
          Resource file=null;
         
          if(strFile!=null && strPath!=null) {
              file=ResourceUtil.toResourceNotExisting(pageContext, strPath).getRealResource(strFile);
          }
          else if(strFile!=null) {
              file=ResourceUtil.toResourceNotExisting(pageContext, strFile);
          }
          else if(strPath!=null) {
              file=ResourceUtil.toResourceNotExisting(pageContext, strPath);
              //Resource dir = file.getParentResource();
              if(file.isDirectory()){
                file=file.getRealResource(req.getURI().getPath());// TODO was getName() ->http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/URI.html#getName()
              }
             
          }
          if(file!=null)pageContext.getConfig().getSecurityManager().checkFileLocation(file);
         
         
          // filecontent
          InputStream is=null;
        if(isText && getAsBinary!=GET_AS_BINARY_YES) {
          String str;
                try {
                 
                  // read content
                  if(method!=METHOD_HEAD) {
                    is = rsp.getContentAsStream();
                      if(is!=null &&isGzipEncoded(contentEncoding))
                        is = rsp.getStatusCode()!=200? new CachingGZIPInputStream(is):new GZIPInputStream(is);
                  }   
                    try {
                      try{
                      str = is==null?"":IOUtil.toString(is,responseCharset);
                      }
                      catch(EOFException eof){
                        if(is instanceof CachingGZIPInputStream) {
                          str = IOUtil.toString(is=((CachingGZIPInputStream)is).getRawData(),responseCharset);
                        }
                        else throw eof;
                      }
                    }
                    catch (UnsupportedEncodingException uee) {
                      str = IOUtil.toString(is,(Charset)null);
                    }
                }
                catch (IOException ioe) {
                  throw Caster.toPageException(ioe);
                }
                finally {
                  IOUtil.closeEL(is);
                }
                   
                if(str==null)str="";
            if(resolveurl){
              //if(e.redirectURL!=null)url=e.redirectURL.toExternalForm();
              str=new URLResolver().transform(str,e.response.getTargetURL(),false);
            }
            cfhttp.set(FILE_CONTENT,str);
            try {
              if(file!=null){
                IOUtil.write(file,str,pageContext.getConfig().getWebCharset(),false);
                    }
                }
            catch (IOException e1) {}

            if(name!=null) {
                    Query qry = CSVParser.toQuery( str, delimiter, textqualifier, columns, firstrowasheaders  );
                    pageContext.setVariable(name,qry);
            }
        }
        // Binary
        else {
          byte[] barr=null;
            if(isGzipEncoded(contentEncoding)){
              if(method!=METHOD_HEAD) {
                is=rsp.getContentAsStream();
                is = rsp.getStatusCode()!=200?new CachingGZIPInputStream(is) :new GZIPInputStream(is);
              }
             
              try {
                try{
                  barr = is==null?new byte[0]: IOUtil.toBytes(is);
                }
                catch(EOFException eof){
                  if(is instanceof CachingGZIPInputStream)
                    barr = IOUtil.toBytes(((CachingGZIPInputStream)is).getRawData());
                  else throw eof;
                }
          }
              catch (IOException t) {
                throw Caster.toPageException(t);
          }
          finally{
            IOUtil.closeEL(is);
          }
            }
            else {
              try {
                if(method!=METHOD_HEAD) barr = rsp.getContentAsByteArray();
                else barr=new byte[0];
          }
              catch (IOException t) {
                throw Caster.toPageException(t);
          }
            }
            //IF Multipart response get file content and parse parts
            if(barr!=null) {
            if(isMultipart) {
              cfhttp.set(FILE_CONTENT,MultiPartResponseUtils.getParts(barr,mimetype));
            } else {
              cfhttp.set(FILE_CONTENT,barr);
            }
            }
            else
            cfhttp.set(FILE_CONTENT,"");
           
           
            if(file!=null) {
              try {
                if(barr!=null)IOUtil.copy(new ByteArrayInputStream(barr),file,true);
              }
              catch (IOException ioe) {
                    throw Caster.toPageException(ioe);
              }
            }  
        }
         
      // header   
          cfhttp.set(KeyConstants._header,raw.toString());
          if(!isStatusOK(rsp.getStatusCode())){
            String msg=rsp.getStatusCode()+" "+rsp.getStatusText();
              cfhttp.setEL(ERROR_DETAIL,msg);
              if(throwonerror){
                throw new HTTPException(msg,null,rsp.getStatusCode(),rsp.getStatusText(),rsp.getURL());
              }
          }
    }
    finally {
      //rsp.release();
    }
     
  }

  private void parseCookie(Query cookies,String raw) {
    String[] arr =ListUtil.trimItems(ListUtil.trim(ListUtil.listToStringArray(raw, ';')));
    if(arr.length==0) return;
    int row = cookies.addRow();
    String item;
   
    int index;
    // name/value
    if(arr.length>0) {
      item=arr[0];
      index=item.indexOf('=');
      if(index==-1// only name
        cookies.setAtEL(KeyConstants._name,row, dec(item));
      else { // name and value
        cookies.setAtEL(KeyConstants._name,row, dec(item.substring(0,index)));
        cookies.setAtEL(KeyConstants._value,row, dec(item.substring(index+1)));
      }
     
    }
    String n,v;
    cookies.setAtEL("secure",row, Boolean.FALSE);
    cookies.setAtEL("httpOnly",row, Boolean.FALSE);
    for(int i=1;i<arr.length;i++){
      item=arr[i];
      index=item.indexOf('=');
      if(index==-1// only name
        cookies.setAtEL(dec(item),row, Boolean.TRUE);
      else { // name and value
        n=dec(item.substring(0,index));
        v=dec(item.substring(index+1));
        if(n.equalsIgnoreCase("expires")) {
          DateTime d = Caster.toDate(v, false, null,null);
         
          if(d!=null) {
            cookies.setAtEL(n,row, d);
            continue;
          }
        }
        cookies.setAtEL(n,row, v);
      }
     
    }
  }
 
  public String dec(String str) {
      return ReqRspUtil.decode(str, charset, false);
  }

  public static boolean isStatusOK(int statusCode) {
    return statusCode>=200 && statusCode<=299;
  }

  private PageException toPageException(Throwable t) {
    PageException pe = Caster.toPageException(t);
    if(pe instanceof NativeException) {
      ((NativeException) pe).setAdditional(KeyConstants._url, url);
    }
    return pe;
  }

  private void setUnknownHost(Struct cfhttp,Throwable t) {
    cfhttp.setEL(CHARSET,"");
    cfhttp.setEL(ERROR_DETAIL,"Unknown host: "+t.getMessage());
    cfhttp.setEL(FILE_CONTENT,"Connection Failure");
    cfhttp.setEL(KeyConstants._header,"");
    cfhttp.setEL(KeyConstants._mimetype,"Unable to determine MIME type of file.");
    cfhttp.setEL(RESPONSEHEADER,new StructImpl());
    cfhttp.setEL(STATUSCODE,"Connection Failure. Status code unavailable.");
    cfhttp.setEL(KeyConstants._text,Boolean.TRUE);
  }

  private void setRequestTimeout(Struct cfhttp) {
    cfhttp.setEL(CHARSET,"");
    cfhttp.setEL(ERROR_DETAIL,"");
    cfhttp.setEL(FILE_CONTENT,"Connection Timeout");
    cfhttp.setEL(KeyConstants._header,"");
    cfhttp.setEL(KeyConstants._mimetype,"Unable to determine MIME type of file.");
    cfhttp.setEL(RESPONSEHEADER,new StructImpl());
    cfhttp.setEL(STATUSCODE,"408 Request Time-out");
    cfhttp.setEL(STATUS_CODE,new Double(408));
    cfhttp.setEL(STATUS_TEXT,"Request Time-out");
    cfhttp.setEL(KeyConstants._text,Boolean.TRUE);
  }

  /*private static HttpMethod execute(Http http, HttpClient client, HttpMethod httpMethod, boolean redirect) throws PageException {
    try {
      // Execute Request
      short count=0;
          URL lu;
         
          while(isRedirect(client.executeMethod(httpMethod)) && redirect && count++ < MAX_REDIRECT) {
            lu=locationURL(httpMethod);
            httpMethod=createMethod(http,client,lu.toExternalForm(),-1);
          }
        }
    catch (IOException e) {
          PageException pe = Caster.toPageException(e);
      if(pe instanceof NativeException) {
        ((NativeException) pe).setAdditional("url", HTTPUtil.toURL(httpMethod));
      }
      throw pe;
        }
    return httpMethod;
  }*/


  /*static URL locationURL(HttpMethod method) throws MalformedURLException, ExpressionException {
        Header location = method.getResponseHeader("location");
       
        if(location==null) throw new ExpressionException("missing location header definition");
       
       
        HostConfiguration config = method.getHostConfiguration();
        URL url;
        try {
            url = new URL(location.getValue());
        }
        catch (MalformedURLException e) {
            url=new URL(config.getProtocol().getScheme(),
                    config.getHost(),
                    config.getPort(),
                    mergePath(method.getPath(),location.getValue()));
        }
           
        return url;
    }*/
 

  /*static HttpRequestBase init(Config cw,Http4 http, DefaultHttpClient client, HttpParams params, String url, int port) throws PageException, IOException {
    String charset=http.charset;
    if(StringUtil.isEmpty(charset,true)) charset=cw.getWebCharset();
    else charset=charset.trim();
   
    HttpRequestBase req;
   
  // check if has fileUploads 
    boolean doUploadFile=false;
    for(int i=0;i<http.params.size();i++) {
      if((http.params.get(i)).getType().equals("file")) {
        doUploadFile=true;
        break;
      }
    } 
 
  // parse url (also query string)
    int len=http.params.size();
    StringBuilder sbQS=new StringBuilder();
    for(int i=0;i<len;i++) {
      HttpParamBean param=http.params.get(i);
      String type=param.getType();
    // URL
      if(type.equals("url")) {
        if(sbQS.length()>0)sbQS.append('&');
        sbQS.append(translateEncoding(param.getName(), charset));
        sbQS.append('=');
        sbQS.append(translateEncoding(param.getValueAsString(), charset));
      }
    }
    String host=null;
    HttpHost httpHost;
    try {
      URL _url = HTTPUtil.toURL(url,port);
      httpHost = new HttpHost(_url.getHost(),_url.getPort());
      host=_url.getHost();
      url=_url.toExternalForm();
      if(sbQS.length()>0){
        // no existing QS
        if(StringUtil.isEmpty(_url.getQuery())) {
          url+="?"+sbQS;
        }
        else {
          url+="&"+sbQS;
        }
         
      }
     
     
    } catch (MalformedURLException mue) {
      throw Caster.toPageException(mue);
    }
   
  // select best matching method (get,post, post multpart (file))

    boolean isBinary = false;
    boolean doMultiPart=doUploadFile || http.multiPart;
    HttpPost post=null;
    HttpEntityEnclosingRequest eem=null;
   
   
    if(http.method==METHOD_GET) {
      req=new HttpGet(url);
    }
    else if(http.method==METHOD_HEAD) {
        req=new HttpHead(url);
    }
    else if(http.method==METHOD_DELETE) {
      isBinary=true;
        req=new HttpDelete(url);
    }
    else if(http.method==METHOD_PUT) {
      isBinary=true;
      HttpPut put = new HttpPut(url);
        req=put;
        eem=put;
       
    }
    else if(http.method==METHOD_TRACE) {
      isBinary=true;
        req=new HttpTrace(url);
    }
    else if(http.method==METHOD_OPTIONS) {
      isBinary=true;
        req=new HttpOptions(url);
    }
    else {
      isBinary=true;
      post=new HttpPost(url);
      req=post;
      eem=post;
    }
   
    boolean hasForm=false;
    boolean hasBody=false;
    boolean hasContentType=false;
  // Set http params
    ArrayList<FormBodyPart> parts=new ArrayList<FormBodyPart>();
   
    StringBuilder acceptEncoding=new StringBuilder();
    java.util.List<NameValuePair> postParam = post!=null?new ArrayList <NameValuePair>():null;
       
    for(int i=0;i<len;i++) {
      HttpParamBean param=http.params.get(i);
      String type=param.getType();
    // URL
      if(type.equals("url")) {
        //listQS.add(new BasicNameValuePair(translateEncoding(param.getName(), http.charset),translateEncoding(param.getValueAsString(), http.charset)));
      }
    // Form
      else if(type.equals("formfield") || type.equals("form")) {
        hasForm=true;
        if(http.method==METHOD_GET) throw new ApplicationException("httpparam type formfield can't only be used, when method of the tag http equal post");
        if(post!=null){
          if(doMultiPart){
            parts.add(
              new FormBodyPart(
                param.getName(),
                new StringBody(
                    param.getValueAsString(),
                    CharsetUtil.toCharset(charset)
                )
              )
            );
          }
          else {
            postParam.add(new BasicNameValuePair(param.getName(),param.getValueAsString()));
          }
        }
        //else if(multi!=null)multi.addParameter(param.getName(),param.getValueAsString());
      }
    // CGI
      else if(type.equals("cgi")) {
        if(param.isEncoded())
            req.addHeader(
                            translateEncoding(param.getName(),charset),
                            translateEncoding(param.getValueAsString(),charset));
                else
                    req.addHeader(param.getName(),param.getValueAsString());
      }
        // Header
            else if(type.startsWith("head")) {
              if(param.getName().equalsIgnoreCase("content-type")) hasContentType=true;
             
              if(param.getName().equalsIgnoreCase("Accept-Encoding")) {
                acceptEncoding.append(headerValue(param.getValueAsString()));
                acceptEncoding.append(", ");
              }
              else req.addHeader(param.getName(),headerValue(param.getValueAsString()));
            }
    // Cookie
      else if(type.equals("cookie")) {
        HTTPEngine4Impl.addCookie(client,host,param.getName(),param.getValueAsString(),"/",charset);
      }
    // File
      else if(type.equals("file")) {
        hasForm=true;
        if(http.method==METHOD_GET) throw new ApplicationException("httpparam type file can't only be used, when method of the tag http equal post");
        if(doMultiPart) {
          try {
            Resource res = param.getFile();
            parts.add(new FormBodyPart(
                param.getName(),
                new ResourceBody(res, getContentType(param), res.getName(), charset)
            ));
            //parts.add(new ResourcePart(param.getName(),new ResourcePartSource(param.getFile()),getContentType(param),_charset));
          }
          catch (FileNotFoundException e) {
            throw new ApplicationException("can't upload file, path is invalid",e.getMessage());
          }
        }
      }
    // XML
      else if(type.equals("xml")) {
        hasBody=true;
        hasContentType=true;
        req.addHeader("Content-type", "text/xml; charset="+charset);
          if(eem==null)throw new ApplicationException("type xml is only supported for type post and put");
          HTTPEngine4Impl.setBody(eem, param.getValueAsString());
      }
    // Body
      else if(type.equals("body")) {
        hasBody=true;
        if(eem==null)throw new ApplicationException("type body is only supported for type post and put");
        HTTPEngine4Impl.setBody(eem, param.getValue());
       
      }
            else {
                throw new ApplicationException("invalid type ["+type+"]");
            }
       
    }
   
    // post params
    if(postParam!=null && postParam.size()>0)
      post.setEntity(new org.apache.http.client.entity.UrlEncodedFormEntity(postParam,charset));
   
    req.setHeader("Accept-Encoding",acceptEncoding.append("gzip").toString());
   
    // multipart
    if(doMultiPart && eem!=null) {
      hasContentType=true;
      boolean doIt=true;
      if(!http.multiPart && parts.size()==1){
        ContentBody body = parts.get(0).getBody();
        if(body instanceof StringBody){
          StringBody sb=(StringBody)body;
          try {
            String str = IOUtil.toString(sb.getReader());
            StringEntity entity = new StringEntity(str,sb.getMimeType(),sb.getCharset());
            eem.setEntity(entity);
           
          } catch (IOException e) {
            throw Caster.toPageException(e);
          }
          doIt=false;
        }
      }
      if(doIt) {
        MultipartEntity mpe = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE,null,CharsetUtil.toCharset(charset));
        Iterator<FormBodyPart> it = parts.iterator();
        while(it.hasNext()) {
          mpe.addPart(it.next());
        }
        eem.setEntity(mpe);
      }
        //eem.setRequestEntity(new MultipartRequestEntityFlex(parts.toArray(new Part[parts.size()]), eem.getParams(),http.multiPartType));
    }
   
   
   
    if(hasBody && hasForm)
      throw new ApplicationException("mixing httpparam  type file/formfield and body/XML is not allowed");
 
    if(!hasContentType) {
      if(isBinary) {
        if(hasBody) req.addHeader("Content-type", "application/octet-stream");
        else req.addHeader("Content-type", "application/x-www-form-urlencoded; charset="+charset);
      }
      else {
        if(hasBody)
          req.addHeader("Content-type", "text/html; charset="+charset );
      }
    }
   
   
    // set User Agent
      if(!hasHeaderIgnoreCase(req,"User-Agent"))
        req.setHeader("User-Agent",http.useragent);
   
  // set timeout
    if(http.timeout>0L)HTTPEngine4Impl.setTimeout(params, (int)http.timeout);
   
  // set Username and Password
    BasicHttpContext httpContext=null;
    if(http.username!=null) {
      if(http.password==null)http.password="";
      if(AUTH_TYPE_NTLM==http.authType) {
        if(StringUtil.isEmpty(http.workStation,true))
                  throw new ApplicationException("attribute workstation is required when authentication type is [NTLM]");
        if(StringUtil.isEmpty(http.domain,true))
                  throw new ApplicationException("attribute domain is required when authentication type is [NTLM]");
         
        HTTPEngine4Impl.setNTCredentials(client, http.username, http.password, http.workStation,http.domain);
      }
      else httpContext=HTTPEngine4Impl.setCredentials(client, httpHost, http.username, http.password);
    }
 
  // set Proxy
    ProxyData proxy=null;
    if(!StringUtil.isEmpty(http.proxyserver)) {
      proxy=ProxyDataImpl.getInstance(http.proxyserver, http.proxyport, http.proxyuser, http.proxypassword) ;
    }
    if(http.pageContext.getConfig().isProxyEnableFor(host)) {
      proxy=http.pageContext.getConfig().getProxyData();
    }
    HTTPEngine4Impl.setProxy(client, req, proxy);
   
    return req;
  }*/

  private static boolean hasHeaderIgnoreCase(HttpRequestBase req,String name) {
    org.apache.http.Header[] headers = req.getAllHeaders();
    if(headers==null) return false;
    for(int i=0;i<headers.length;i++){
      if(name.equalsIgnoreCase(headers[i].getName())) return true;
    }
    return false;
  }

  private static String headerValue(String value) {
    if(value==null) return null;
    value=value.trim();
    value=value.replace('\n', ' ');
    value=value.replace('\r', ' ');
    /*int len=value.length();
    char c;
    for(int i=0;i<len;i++){
      c=value.charAt(i);
      if(c=='\n' || c=='\r') return value.substring(0,i);
    }*/
    return value;
  }

  private static String toQueryString(NameValuePair[] qsPairs) {
    StringBuffer sb=new StringBuffer();
        for(int i=0;i<qsPairs.length;i++) {
            if(sb.length()>0)sb.append('&');
            sb.append(qsPairs[i].getName());
            if(qsPairs[i].getValue()!=null){
              sb.append('=');
              sb.append(qsPairs[i].getValue());
            }
        }
        return sb.toString();
    }

    private static String urlenc(String str, String charset) throws UnsupportedEncodingException {
      if(!ReqRspUtil.needEncoding(str,false)) return str;
      return URLEncoder.encode(str,charset);
    }

    @Override
  public void doInitBody()  {
   
  }

  @Override
  public int doAfterBody()  {
    return SKIP_BODY;
  }

  /**
   * sets if has body or not
   * @param hasBody
   */
  public void hasBody(boolean hasBody) {
     
  }

  /**
   * @param param
   */
  public void setParam(HttpParamBean param) {
    params.add(param);
   
  }
 
 
    /**
     * @param getAsBinary The getasbinary to set.
     */
    public void setGetasbinary(String getAsBinary) {
      // TODO support never, wird das verwendet?
        getAsBinary=getAsBinary.toLowerCase().trim();
        if(getAsBinary.equals("yes") || getAsBinary.equals("true"))     this.getAsBinary=GET_AS_BINARY_YES;
        else if(getAsBinary.equals("no") || getAsBinary.equals("false"))   this.getAsBinary=GET_AS_BINARY_NO;
        else if(getAsBinary.equals("auto"))                 this.getAsBinary=GET_AS_BINARY_AUTO;
    }

    /**
     * @param multipart The multipart to set.
     */
    public void setMultipart(boolean multiPart) {
        this.multiPart = multiPart;
    }

    /**
     * @param multipart The multipart to set.
     * @throws ApplicationException
     */
    public void setMultiparttype(String multiPartType) throws ApplicationException {
      if(StringUtil.isEmpty(multiPartType))return;
      multiPartType=multiPartType.trim().toLowerCase();
     
      if("form-data".equals(multiPartType))   this.multiPartType=MULTIPART_FORM_DATA;
      //else if("related".equals(multiPartType))     this.multiPartType=MultipartRequestEntityFlex.MULTIPART_RELATED;
      else
      throw new ApplicationException("invalid value for attribute multiPartType ["+multiPartType+"]",
          "attribute must have one of the following values [form-data]");
     
    }

    /**
     * @param result The result to set.
     */
    public void setResult(String result) {
        this.result = result;
    }

  /**
   * @param addtoken the addtoken to set
   */
  public void setAddtoken(boolean addtoken) {
    this.addtoken = addtoken;
  }
 
  /**
     * checks if status code is a redirect
     * @param status
     * @return is redirect
     */
   
  static boolean isRedirect(int status) {
      return
          status==STATUS_REDIRECT_FOUND ||
          status==STATUS_REDIRECT_MOVED_PERMANENTLY ||
          status==STATUS_REDIRECT_SEE_OTHER ||
          status==STATUS_REDIRECT_TEMPORARY_REDIRECT;
     
     
    }
   
    /**
     * merge to pathes to one
     * @param current
     * @param realPath
     * @return
     * @throws MalformedURLException
     */
    public static String mergePath(String current, String realPath) throws MalformedURLException {
       
        // get current directory
        String currDir;
        if(current==null || current.indexOf('/')==-1)currDir="/";
        else if(current.endsWith("/"))currDir=current;
        else currDir=current.substring(0,current.lastIndexOf('/')+1);
       
        // merge together
        String path;
        if(realPath.startsWith("./"))path=currDir+realPath.substring(2);
        else if(realPath.startsWith("/"))path=realPath;
        else if(!realPath.startsWith("../"))path=currDir+realPath;
        else {
            while(realPath.startsWith("../") || currDir.length()==0) {
                realPath=realPath.substring(3);
                currDir=currDir.substring(0,currDir.length()-1);
                int index = currDir.lastIndexOf('/');
                if(index==-1)throw new MalformedURLException("invalid realpath definition for URL");
                currDir=currDir.substring(0,index+1);
            }
            path=currDir+realPath;
        }
       
        return path;
    }
   
  private static String getContentType(HttpParamBean param) {
    String mimeType=param.getMimeType();
    if(StringUtil.isEmpty(mimeType,true)) {
      mimeType=ResourceUtil.getMimeType(param.getFile(), ResourceUtil.MIMETYPE_CHECK_EXTENSION+ResourceUtil.MIMETYPE_CHECK_HEADER, null);
    }
    return mimeType;
  }

  public static boolean isGzipEncoded(String contentEncoding) {
    return !StringUtil.isEmpty(contentEncoding) && StringUtil.indexOfIgnoreCase(contentEncoding, "gzip")!=-1;
  }

  public static Object getOutput(InputStream is, String contentType, String contentEncoding, boolean closeIS) {
    if(StringUtil.isEmpty(contentType))contentType="text/html";
   
    // Gzip
    if(Http4.isGzipEncoded(contentEncoding)){
      try {
        is=new GZIPInputStream(is);
      }
      catch (IOException e) {}
    }
   
    try {
      // text
      if(HTTPUtil.isTextMimeType(contentType)) {
        String[] tmp = HTTPUtil.splitMimeTypeAndCharset(contentType,null);
        //String mimetype=tmp[0];
        String charset=tmp[1];
       
        if(StringUtil.isEmpty(charset,true)) {
          Config config = ThreadLocalPageContext.getConfig();
          if(config!=null)charset=config.getWebCharset();
        }
       
        try {
          return IOUtil.toString(is, charset);
        } catch (IOException e) {}
      }
      // Binary
      else {
        try {
          return IOUtil.toBytes(is);
        }
        catch (IOException e) {}
      }
    }
    finally{
      if(closeIS)IOUtil.closeEL(is);
    }

    return "";
  }
 
  public static URL locationURL(HttpUriRequest req, HttpResponse rsp) {
    URL url=null;
    try {
      url = req.getURI().toURL();
    } catch (MalformedURLException e1) {
      return null;
    }
   
    Header h = HTTPResponse4Impl.getLastHeaderIgnoreCase(rsp, "location");
    if(h!=null) {
      String str = h.getValue();
      try {
        return new URL(str);
      } catch (MalformedURLException e) {
        try {
          return new URL(url.getProtocol(), url.getHost(), url.getPort(), mergePath(url.getFile(), str));
         
        } catch (MalformedURLException e1) {
          return null;
        }
      }
    }
    return null;
  }
 
 
}

class Executor4 extends Thread {
 
   final Http4 http;
   private final DefaultHttpClient client;
   final boolean redirect;
   Throwable t;
   boolean done;
  //URL redirectURL;
  HTTPResponse4Impl response;
  private HttpRequestBase req;
  private HttpContext context;

  public Executor4(Http4 http,DefaultHttpClient client, HttpContext context, HttpRequestBase req, boolean redirect) {
    this.http=http;
    this.client=client;
    this.context=context;
    this.redirect=redirect;
    this.req=req;
  }
 
  @Override
  public void run(){
    try {
      response=execute(context);
      done=true;
    }
    catch (Throwable t) {
      this.t=t;
    }
    finally {
      SystemUtil.notify(http);
    }
  }
 
  public HTTPResponse4Impl execute(HttpContext context) throws IOException  {
    return response=new HTTPResponse4Impl(null,context,req,client.execute(req,context));
  }
}
TOP

Related Classes of railo.runtime.tag.Http4

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.