001package lucee.runtime.tag;
002
003import java.io.IOException;
004import java.io.InputStream;
005import java.io.UnsupportedEncodingException;
006import java.net.MalformedURLException;
007import java.net.URL;
008import java.nio.charset.Charset;
009import java.util.zip.GZIPInputStream;
010
011import javax.servlet.jsp.JspException;
012import javax.servlet.jsp.PageContext;
013import javax.servlet.jsp.tagext.BodyContent;
014import javax.servlet.jsp.tagext.BodyTag;
015import javax.servlet.jsp.tagext.Tag;
016
017import lucee.commons.io.CharsetUtil;
018import lucee.commons.io.IOUtil;
019import lucee.commons.io.res.util.ResourceUtil;
020import lucee.commons.lang.ExceptionUtil;
021import lucee.commons.lang.StringUtil;
022import lucee.commons.net.HTTPUtil;
023import lucee.commons.net.URLEncoder;
024import lucee.commons.net.http.Header;
025import lucee.commons.net.http.httpclient4.HTTPResponse4Impl;
026import lucee.runtime.exp.PageException;
027import lucee.runtime.net.http.ReqRspUtil;
028
029import org.apache.http.HttpResponse;
030import org.apache.http.client.methods.HttpRequestBase;
031import org.apache.http.client.methods.HttpUriRequest;
032
033public class HttpImpl implements Http,BodyTag {
034        
035        private Http instance;
036
037        public HttpImpl(){
038                try{
039                        instance = new Http41(); // try to use the implemenation based on the newer apache library
040                }
041                catch(Throwable t){
042                        ExceptionUtil.rethrowIfNecessary(t);
043                        instance = new Http4(); // if it fails we have a fallback to the old implementation
044                }
045        }
046
047        @Override
048        public void setParam(HttpParamBean param) {
049                instance.setParam(param);
050        }
051
052        @Override
053        public void setFirstrowasheaders(boolean firstrowasheaders) {
054                instance.setFirstrowasheaders(firstrowasheaders);
055        }
056
057        @Override
058        public void setEncodeurl(boolean encoded) {
059                instance.setEncodeurl(encoded);
060        }
061
062        @Override
063        public void setPassword(String password) {
064                instance.setPassword(password);
065        }
066
067        @Override
068        public void setProxypassword(String proxypassword) {
069                instance.setProxypassword(proxypassword);
070        }
071
072        @Override
073        public void setDelimiter(String delimiter) {
074                instance.setDelimiter(delimiter);
075        }
076
077        @Override
078        public void setResolveurl(boolean resolveurl) {
079                instance.setResolveurl(resolveurl);
080        }
081
082        @Override
083        public void setPreauth(boolean preauth) {
084                instance.setPreauth(preauth);
085        }
086
087        @Override
088        public void setTimeout(Object timeout) throws PageException {
089                instance.setTimeout(timeout);
090        }
091
092        @Override
093        public void setProxyserver(String proxyserver) {
094                instance.setProxyserver(proxyserver);
095        }
096
097        @Override
098        public void setProxyport(double proxyport) {
099                instance.setProxyport(proxyport);
100        }
101
102        @Override
103        public void setFile(String file) {
104                instance.setFile(file);
105        }
106
107        @Override
108        public void setThrowonerror(boolean throwonerror) {
109                instance.setThrowonerror(throwonerror);
110        }
111
112        @Override
113        public void setCharset(String charset) {
114                instance.setCharset(charset);
115        }
116
117        @Override
118        public void setColumns(String columns) throws PageException {
119                instance.setColumns(columns);
120        }
121
122        @Override
123        public void setPort(double port) {
124                instance.setPort(port);
125        }
126
127        @Override
128        public void setUseragent(String useragent) {
129                instance.setUseragent(useragent);
130        }
131
132        @Override
133        public void setTextqualifier(String textqualifier) {
134                instance.setTextqualifier(textqualifier);
135        }
136
137        @Override
138        public void setProxyuser(String proxyuser) {
139                instance.setProxyuser(proxyuser);
140        }
141
142        @Override
143        public void setUsername(String username) {
144                instance.setUsername(username);
145        }
146
147        @Override
148        public void setUrl(String url) {
149                instance.setUrl(url);
150        }
151
152        @Override
153        public void setRedirect(boolean redirect) {
154                instance.setRedirect(redirect);
155        }
156
157        @Override
158        public void setPath(String path) {
159                instance.setPath(path);
160        }
161
162        @Override
163        public void setName(String name) {
164                instance.setName(name);
165        }
166
167        @Override
168        public void setAuthtype(String strAuthType) throws PageException {
169                instance.setAuthtype(strAuthType);
170        }
171
172        @Override
173        public void setWorkstation(String workStation) {
174                instance.setWorkstation(workStation);
175        }
176
177        @Override
178        public void setDomain(String domain) {
179                instance.setDomain(domain);
180        }
181
182        @Override
183        public void setMethod(String method) throws PageException {
184                instance.setMethod(method);
185        }
186
187        @Override
188        public void setCompression(String strCompression) throws PageException {
189                instance.setCompression(strCompression);
190        }
191
192        @Override
193        public void setGetasbinary(String getAsBinary) {
194                instance.setGetasbinary(getAsBinary);
195        }
196
197        @Override
198        public void setMultipart(boolean multiPart) {
199                instance.setMultipart(multiPart);
200        }
201
202        @Override
203        public void setMultiparttype(String multiPartType) throws PageException {
204                instance.setMultiparttype(multiPartType);
205        }
206
207        @Override
208        public void setResult(String result) {
209                instance.setResult(result);
210        }
211
212        @Override
213        public void setAddtoken(boolean addtoken) {
214                instance.setAddtoken(addtoken);
215        }
216
217
218        @Override
219        public int doAfterBody() throws JspException {
220                return instance.doAfterBody();
221        }
222
223        @Override
224        public int doEndTag() throws JspException {
225                return instance.doEndTag();
226        }
227
228        @Override
229        public int doStartTag() throws JspException {
230                return instance.doStartTag();
231        }
232
233        @Override
234        public Tag getParent() {
235                return instance.getParent();
236        }
237
238        @Override
239        public void release() {
240                instance.release();
241        }
242
243        @Override
244        public void setPageContext(PageContext pc) {
245                instance.setPageContext(pc);
246        }
247
248        @Override
249        public void setParent(Tag arg0) {
250                instance.setParent(arg0);
251        }
252
253        @Override
254        public void doInitBody() throws JspException {
255                instance.doInitBody();
256        }
257
258        @Override
259        public void setBodyContent(BodyContent arg0) {
260                instance.setBodyContent(arg0);
261        }
262
263        static String headerValue(String value) {
264                if(value==null) return null;
265                value=value.trim();
266                value=value.replace('\n', ' ');
267                value=value.replace('\r', ' ');
268                return value;
269        }
270        
271        static boolean hasHeaderIgnoreCase(HttpRequestBase req,String name) {
272                org.apache.http.Header[] headers = req.getAllHeaders();
273                if(headers==null) return false;
274                for(int i=0;i<headers.length;i++){
275                        if(name.equalsIgnoreCase(headers[i].getName())) return true;
276                }
277                return false;
278        }
279
280    static String urlenc(String str, String charset) throws UnsupportedEncodingException {
281        if(!ReqRspUtil.needEncoding(str,false)) return str;
282        return URLEncoder.encode(str,charset);
283    }
284        
285        static Charset getCharset(String strCharset) {
286                if(!StringUtil.isEmpty(strCharset,true)) 
287                        return CharsetUtil.toCharset(strCharset);
288                return CharsetUtil.getWebCharset();
289        }
290        
291        static String getContentType(HttpParamBean param) {
292                String mimeType=param.getMimeType();
293                if(StringUtil.isEmpty(mimeType,true)) {
294                        mimeType=ResourceUtil.getMimeType(param.getFile(), ResourceUtil.MIMETYPE_CHECK_EXTENSION+ResourceUtil.MIMETYPE_CHECK_HEADER, null);
295                }
296                return mimeType;
297        }
298    
299        static boolean isGzipEncoded(String contentEncoding) {
300                return !StringUtil.isEmpty(contentEncoding) && StringUtil.indexOfIgnoreCase(contentEncoding, "gzip")!=-1;
301        }
302
303        static boolean isStatusOK(int statusCode) {
304                return statusCode>=200 && statusCode<=299;
305        }
306
307        public static Object getOutput(InputStream is, String contentType, String contentEncoding, boolean closeIS) {
308                if(StringUtil.isEmpty(contentType))contentType="text/html";
309                
310                // Gzip
311                if(HttpImpl.isGzipEncoded(contentEncoding)){
312                        try {
313                                is=new GZIPInputStream(is);
314                        } 
315                        catch (IOException e) {}
316                }
317                
318                try {
319                        // text
320                        if(HTTPUtil.isTextMimeType(contentType)) {
321                                String[] tmp = HTTPUtil.splitMimeTypeAndCharset(contentType,null);
322                                Charset cs=HttpImpl.getCharset(tmp[1]);
323                                
324                                try {
325                                        return IOUtil.toString(is, cs);
326                                } catch (IOException e) {}
327                        }
328                        // Binary
329                        else {
330                                try {
331                                        return IOUtil.toBytes(is);
332                                } 
333                                catch (IOException e) {}
334                        }
335                }
336                finally{
337                        if(closeIS)IOUtil.closeEL(is);
338                }
339
340                return "";
341        }
342        
343        static URL locationURL(HttpUriRequest req, HttpResponse rsp) {
344                URL url=null;
345                try {
346                        url = req.getURI().toURL();
347                } catch (MalformedURLException e1) {
348                        return null;
349                }
350                
351                Header h = HTTPResponse4Impl.getLastHeaderIgnoreCase(rsp, "location");
352                if(h!=null) {
353                        String str = h.getValue();
354                        try {
355                                return new URL(str);
356                        } catch (MalformedURLException e) {
357                                try {
358                                        return new URL(url.getProtocol(), url.getHost(), url.getPort(), mergePath(url.getFile(), str));
359                                        
360                                } catch (MalformedURLException e1) {
361                                        return null;
362                                }
363                        }
364                }
365                return null;
366        }
367
368    /**
369     * merge to pathes to one
370     * @param current
371     * @param relPath
372     * @return
373     * @throws MalformedURLException
374     */
375    static String mergePath(String current, String relPath) throws MalformedURLException {
376        
377        // get current directory
378        String currDir;
379        if(current==null || current.indexOf('/')==-1)currDir="/";
380        else if(current.endsWith("/"))currDir=current;
381        else currDir=current.substring(0,current.lastIndexOf('/')+1);
382        
383        // merge together
384        String path;
385        if(relPath.startsWith("./"))path=currDir+relPath.substring(2);
386        else if(relPath.startsWith("/"))path=relPath;
387        else if(!relPath.startsWith("../"))path=currDir+relPath;
388        else {
389            while(relPath.startsWith("../") || currDir.length()==0) {
390                relPath=relPath.substring(3);
391                currDir=currDir.substring(0,currDir.length()-1);
392                int index = currDir.lastIndexOf('/');
393                if(index==-1)throw new MalformedURLException("invalid relpath definition for URL");
394                currDir=currDir.substring(0,index+1);
395            }
396            path=currDir+relPath;
397        }
398        
399        return path;
400    }
401        
402        /**
403     * checks if status code is a redirect
404     * @param status
405     * @return is redirect
406     */
407    
408        static boolean isRedirect(int status) {
409        return 
410                status==STATUS_REDIRECT_FOUND || 
411                status==STATUS_REDIRECT_MOVED_PERMANENTLY ||
412                status==STATUS_REDIRECT_SEE_OTHER ||
413                status==STATUS_REDIRECT_TEMPORARY_REDIRECT;
414    }
415}