001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.net.http; 020 021import java.io.BufferedReader; 022import java.io.IOException; 023import java.io.Serializable; 024import java.io.UnsupportedEncodingException; 025import java.net.InetAddress; 026import java.net.UnknownHostException; 027import java.security.Principal; 028import java.util.ArrayList; 029import java.util.Date; 030import java.util.Enumeration; 031import java.util.HashSet; 032import java.util.Locale; 033import java.util.Map; 034 035import javax.servlet.RequestDispatcher; 036import javax.servlet.ServletInputStream; 037import javax.servlet.http.Cookie; 038import javax.servlet.http.HttpServletRequest; 039import javax.servlet.http.HttpSession; 040 041import lucee.commons.collection.MapFactory; 042import lucee.commons.io.IOUtil; 043import lucee.commons.io.res.Resource; 044import lucee.commons.lang.ExceptionUtil; 045import lucee.commons.lang.Pair; 046import lucee.runtime.config.Config; 047import lucee.runtime.exp.PageException; 048import lucee.runtime.op.Caster; 049import lucee.runtime.op.date.DateCaster; 050import lucee.runtime.type.Array; 051import lucee.runtime.type.KeyImpl; 052import lucee.runtime.type.Struct; 053import lucee.runtime.type.StructImpl; 054import lucee.runtime.type.dt.DateTimeImpl; 055import lucee.runtime.type.it.ItAsEnum; 056import lucee.runtime.util.EnumerationWrapper; 057 058public final class HttpServletRequestDummy implements HttpServletRequest,Serializable { 059 060 061 private Cookie[] cookies; 062 063 private String authType; 064 private Pair<String,Object>[] headers=new Pair[0]; 065 private Pair<String,Object>[] parameters=new Pair[0]; 066 private Struct attributes=new StructImpl(); 067 private String method="GET"; 068 private String pathInfo; 069 private String pathTranslated; 070 private String contextPath=""; 071 private String queryString; 072 private String remoteUser; 073 private String requestedSessionId; 074 private String requestURI; 075 076 private String protocol="HTTP/1.1"; 077 private String serverName="localhost"; 078 private int port=80; 079 080 private String characterEncoding="ISO-8859-1"; 081 082 private String contentType; 083 private byte[] inputData=new byte[0]; 084 085 086 private static InetAddress DEFAULT_REMOTE; 087 private static String DEFAULT_REMOTE_ADDR; 088 private static String DEFAULT_REMOTE_HOST; 089 static { 090 try { 091 DEFAULT_REMOTE=InetAddress.getLocalHost(); 092 DEFAULT_REMOTE_ADDR=DEFAULT_REMOTE.getHostAddress(); 093 DEFAULT_REMOTE_HOST=DEFAULT_REMOTE.getHostName(); 094 } 095 catch (UnknownHostException e) {} 096 } 097 //private InetAddress remoteq=DEFAULT_REMOTE; 098 private String remoteAddr=DEFAULT_REMOTE_ADDR; 099 private String remoteHost=DEFAULT_REMOTE_HOST; 100 101 private Locale locale=Locale.getDefault(); 102 103 private boolean secure; 104 105 private Resource contextRoot; 106 107 private String scheme="http"; 108 109 private HttpSession session; 110 111 112 113 /** 114 * constructor of the class 115 * @param headers 116 * @param parameters 117 * @param httpSession 118 * @param pairs 119 * @param cookiess 120 */ 121 public HttpServletRequestDummy(Resource contextRoot,String serverName, String scriptName,String queryString, 122 Cookie[] cookies, Pair[] headers, Pair[] parameters, Struct attributes, HttpSession session) { 123 this.serverName=serverName; 124 requestURI=scriptName; 125 this.queryString=queryString; 126 this.parameters=translateQS(queryString); 127 this.contextRoot=contextRoot; 128 if(cookies!=null)setCookies(cookies); 129 if(headers!=null)this.headers=headers; 130 if(parameters!=null)this.parameters=parameters; 131 if(attributes!=null)this.attributes=attributes; 132 this.session=session; 133 } 134 /** 135 * constructor of the class 136 * @throws PageException 137 * / 138 public HttpServletRequestDummy(String serverName, String scriptName,Struct queryString) throws PageException { 139 this.serverName=serverName; 140 requestURI=scriptName; 141 142 StringBuffer qs=new StringBuffer(); 143 String[] keys=queryString.keys(); 144 parameters=new Item[keys.length]; 145 String key; 146 Object value; 147 for(int i=0;i<keys.length;i++) { 148 if(i>0) qs.append('&'); 149 key=keys[i]; 150 value=queryString.get(key); 151 parameters[i]=new Item(key,value); 152 153 qs.append(key); 154 qs.append('='); 155 qs.append(Caster.toString(value)); 156 } 157 158 this.queryString=qs.toString(); 159 }*/ 160 161 private Pair[] translateQS(String qs) { 162 if(qs==null) return new Pair[0]; 163 Array arr=lucee.runtime.type.util.ListUtil.listToArrayRemoveEmpty(qs,"&"); 164 Pair[] parameters=new Pair[arr.size()]; 165 //Array item; 166 int index; 167 String name; 168 169 for(int i=1;i<=parameters.length;i++) { 170 name=Caster.toString(arr.get(i,""),""); 171 index=name.indexOf('='); 172 if(index!=-1) parameters[i-1]=new Pair(name.substring(0,index),name.substring(index+1)); 173 else parameters[i-1]=new Pair(name,""); 174 175 } 176 return parameters; 177 } 178 179 180 181 @Override 182 public String getAuthType() { 183 return authType; 184 } 185 186 /** 187 * sets the name of the authentication scheme used to protect the servlet. 188 * All servlet containers support basic, 189 * form and client certificate authentication, 190 * and may additionally support digest authentication. 191 * @param authType authentication type 192 */ 193 public void setAuthType(String authType) { 194 this.authType=authType; 195 } 196 197 @Override 198 public Cookie[] getCookies() { 199 return cookies; 200 } 201 202 /** 203 * sets an array containing all of the Cookie objects 204 * the client sent with this request. 205 * This method returns null if no cookies were sent. 206 * @param cookies 207 */ 208 public void setCookies(Cookie[] cookies) { 209 this.cookies=cookies; 210 } 211 212 @Override 213 public long getDateHeader(String name) { 214 Object value=getHeader(name); 215 if(value!=null) { 216 Date date=DateCaster.toDateAdvanced(value,null,null); 217 if(date!=null)return date.getTime(); 218 throw new IllegalArgumentException("can't convert value "+value+" to a Date"); 219 } 220 return -1; 221 } 222 223 public void setDateHeader(String name, long value) { 224 // TODO wrong format 225 setHeader(name,new DateTimeImpl(value,false).castToString()); 226 } 227 228 @Override 229 public String getHeader(String name) { 230 return ReqRspUtil.get(headers,name); 231 } 232 233 /** 234 * sets a new header value 235 * @param name name of the new value 236 * @param value header value 237 */ 238 public void setHeader(String name, String value) { 239 headers=ReqRspUtil.set(headers,name,value); 240 } 241 242 /** 243 * add a new header value 244 * @param name name of the new value 245 * @param value header value 246 */ 247 public void addHeader(String name, String value) { 248 headers=ReqRspUtil.add(headers,name,value); 249 } 250 251 252 @Override 253 public Enumeration getHeaders(String name) { 254 HashSet set=new HashSet(); 255 for(int i=0;i<headers.length;i++) { 256 if(headers[i].getName().equalsIgnoreCase(name)) 257 set.add(Caster.toString(headers[i].getValue(),null)); 258 } 259 return new EnumerationWrapper(set); 260 } 261 262 @Override 263 public Enumeration getHeaderNames() { 264 HashSet set=new HashSet(); 265 for(int i=0;i<headers.length;i++) { 266 set.add(headers[i].getName()); 267 } 268 return new EnumerationWrapper(set); 269 } 270 271 @Override 272 public int getIntHeader(String name) { 273 Object value=getHeader(name); 274 if(value!=null) { 275 try { 276 return Caster.toIntValue(value); 277 } catch (PageException e) { 278 throw new NumberFormatException(e.getMessage()); 279 } 280 } 281 return -1; 282 } 283 284 @Override 285 public String getMethod() { 286 return method; 287 } 288 289 /** 290 * sets the request method 291 * @param method 292 */ 293 public void setMethod(String method) { 294 this.method = method; 295 } 296 297 @Override 298 public String getPathInfo() { 299 return pathInfo; 300 } 301 302 303 /** 304 * Sets any extra path information associated with the URL the client sent 305 * when it made this request. 306 * The extra path information follows the servlet path but precedes 307 * the query string. 308 * @param pathInfo 309 */ 310 public void setPathInfo(String pathInfo) { 311 this.pathInfo = pathInfo; 312 } 313 314 315 @Override 316 public String getPathTranslated() { 317 return pathTranslated; 318 } 319 320 /** 321 * sets any extra path information after the servlet name 322 * but before the query string, translates to a real path. 323 * Same as the value of the CGI variable PATH_TRANSLATED. 324 * @param pathTranslated 325 */ 326 public void setPathTranslated(String pathTranslated) { 327 // TODO muss auf pathinfo basieren 328 this.pathTranslated = pathTranslated; 329 } 330 331 @Override 332 public String getContextPath() { 333 return contextPath; 334 } 335 336 /** 337 * sets the portion of the request URI that indicates the context of the request. 338 * The context path always comes first in a request URI. 339 * The path starts with a "/" character but does not end with a "/" character. 340 * @param contextPath 341 */ 342 public void setContextPath(String contextPath) { 343 this.contextPath = contextPath; 344 } 345 346 @Override 347 public String getQueryString() { 348 return queryString; 349 } 350 351 /** 352 * sets the query string that is contained in the request URL after the path. 353 * Same as the value of the CGI variable QUERY_STRING. 354 355 * @param queryString 356 */ 357 public void setQueryString(String queryString) { 358 this.queryString = queryString; 359 parameters=translateQS(queryString); 360 } 361 362 @Override 363 public String getRemoteUser() { 364 return remoteUser; 365 } 366 367 /** 368 * sets the login of the user making this request, 369 * if the user has been authenticated, 370 * or null if the user has not been authenticated. 371 * Whether the user name is sent with each subsequent request depends 372 * on the browser and type of authentication. 373 * Same as the value of the CGI variable REMOTE_USER. 374 * @param remoteUser 375 */ 376 public void setRemoteUser(String remoteUser) { 377 this.remoteUser = remoteUser; 378 } 379 380 @Override 381 public boolean isUserInRole(String role) { 382 // TODO impl 383 return false; 384 } 385 386 @Override 387 public Principal getUserPrincipal() { 388 //TODO impl 389 return null; 390 } 391 392 @Override 393 public String getRequestedSessionId() { 394 return requestedSessionId; 395 } 396 397 /** 398 * sets the session ID specified by the client. 399 * This may not be the same as the ID of the actual session in use. 400 * For example, if the request specified an old (expired) session ID 401 * and the server has started a new session, 402 * this method gets a new session with a new ID. 403 * @param requestedSessionId 404 */ 405 public void setRequestedSessionId(String requestedSessionId) { 406 this.requestedSessionId = requestedSessionId; 407 } 408 409 @Override 410 public String getRequestURI() { 411 return requestURI; 412 } 413 414 /** 415 * sets the part of this request's URL from the protocol name 416 * up to the query string in the first line of the HTTP request. 417 * The web container does not decode this String. 418 * @param requestURI 419 */ 420 public void setRequestURI(String requestURI) { 421 this.requestURI = requestURI; 422 } 423 424 @Override 425 public StringBuffer getRequestURL() { 426 return new StringBuffer(isSecure()?"https":"http"). 427 append("://"). 428 append(serverName). 429 append(':'). 430 append(port). 431 append('/'). 432 append(requestURI); 433 } 434 435 @Override 436 public String getServletPath() { 437 // TODO when different ? 438 return requestURI; 439 } 440 @Override 441 public HttpSession getSession(boolean arg0) { 442 return session; 443 } 444 @Override 445 public HttpSession getSession() { 446 return getSession(true); 447 } 448 @Override 449 public boolean isRequestedSessionIdValid() { 450// not supported 451 return false; 452 } 453 @Override 454 public boolean isRequestedSessionIdFromCookie() { 455// not supported 456 return false; 457 } 458 @Override 459 public boolean isRequestedSessionIdFromURL() { 460// not supported 461 return false; 462 } 463 @Override 464 public boolean isRequestedSessionIdFromUrl() { 465 return isRequestedSessionIdFromURL(); 466 } 467 @Override 468 public Object getAttribute(String key) { 469 return attributes.get(key,null); 470 } 471 472 @Override 473 public void setAttribute(String key, Object value) { 474 attributes.setEL(key,value); 475 } 476 477 @Override 478 public void removeAttribute(String key) { 479 attributes.removeEL(KeyImpl.init(key)); 480 } 481 482 @Override 483 public Enumeration getAttributeNames() { 484 return ItAsEnum.toStringEnumeration(attributes.keyIterator()); 485 } 486 @Override 487 public String getCharacterEncoding() { 488 return characterEncoding; 489 } 490 @Override 491 public void setCharacterEncoding(String characterEncoding) 492 throws UnsupportedEncodingException { 493 this.characterEncoding=characterEncoding; 494 } 495 @Override 496 public int getContentLength() { 497 return -1; 498 } 499 @Override 500 public String getContentType() { 501 return contentType; 502 } 503 504 /** 505 * sets the content Type of the Request 506 * @param contentType 507 */ 508 public void setContentType(String contentType) { 509 this.contentType=contentType; 510 } 511 512 @Override 513 public ServletInputStream getInputStream() throws IOException { 514 return new ServletInputStreamDummy(inputData); 515 } 516 517 public void setParameter(String key,String value) { 518 parameters=ReqRspUtil.set(parameters,key,value); 519 rewriteQS(); 520 } 521 522 public void addParameter(String key,String value) { 523 parameters=ReqRspUtil.add(parameters,key,value); 524 rewriteQS(); 525 } 526 527 @Override 528 public String getParameter(String key) { 529 return ReqRspUtil.get(parameters,key); 530 } 531 532 @Override 533 public String[] getParameterValues(String key) { 534 ArrayList list=new ArrayList(); 535 for(int i=0;i<parameters.length;i++) { 536 if(parameters[i].getName().equalsIgnoreCase(key)) 537 list.add(Caster.toString(parameters[i].getValue(),null)); 538 } 539 return (String[]) list.toArray(new String[list.size()]); 540 } 541 542 @Override 543 public Enumeration getParameterNames() { 544 HashSet set=new HashSet(); 545 for(int i=0;i<parameters.length;i++) { 546 set.add(parameters[i].getName()); 547 } 548 return new EnumerationWrapper(set); 549 } 550 551 @Override 552 public Map getParameterMap() { 553 Map<String,Object> p=MapFactory.<String,Object>getConcurrentMap(); 554 for(int i=0;i<parameters.length;i++) { 555 p.put(parameters[i].getName(), parameters[i].getValue()); 556 } 557 return p; 558 } 559 560 /** 561 * set the Protocol (Default "http") 562 * @param protocol 563 */ 564 public void setProtocol(String protocol) { 565 this.protocol=protocol; 566 } 567 568 @Override 569 public String getProtocol() { 570 return protocol; 571 } 572 573 @Override 574 public String getScheme() { 575 return scheme; 576 } 577 578 public void setScheme(String scheme) { 579 this.scheme=scheme; 580 } 581 582 @Override 583 public String getServerName() { 584 return serverName; 585 } 586 587 @Override 588 public int getServerPort() { 589 return port; 590 } 591 592 /** 593 * @param port The port to set. 594 */ 595 public void setServerPort(int port) { 596 this.port = port; 597 } 598 599 @Override 600 public BufferedReader getReader() throws IOException { 601 return IOUtil.toBufferedReader(IOUtil.getReader(getInputStream(),"ISO-8859-1")); 602 } 603 604 @Override 605 public String getRemoteAddr() { 606 return remoteAddr; 607 } 608 609 public void setRemoteAddr(String remoteAddr) { 610 this.remoteAddr=remoteAddr; 611 } 612 public void setRemoteHost(String remoteHost) { 613 this.remoteHost=remoteHost; 614 } 615 616 @Override 617 public String getRemoteHost() { 618 return remoteHost; 619 } 620 621 public void setRemoteInetAddress(InetAddress ia) { 622 setRemoteAddr(ia.getHostAddress()); 623 setRemoteHost(ia.getHostName()); 624 } 625 626 @Override 627 public Locale getLocale() { 628 return locale; 629 } 630 631 public void setLocale(Locale locale) { 632 this.locale=locale; 633 } 634 635 @Override 636 public Enumeration getLocales() { 637 return new EnumerationWrapper(Locale.getAvailableLocales()); 638 } 639 640 @Override 641 public boolean isSecure() { 642 return secure; 643 } 644 645 public void setSecure(boolean secure) { 646 this.secure=secure; 647 } 648 649 @Override 650 public RequestDispatcher getRequestDispatcher(String arg0) { 651 return new RequestDispatcherDummy(this); 652 } 653 654 @Override 655 public String getRealPath(String path) { 656 return contextRoot.getReal(path); 657 } 658 659 /** 660 * @return the inputData 661 */ 662 public byte[] getInputData() { 663 return inputData; 664 } 665 /** 666 * @param inputData the inputData to set 667 */ 668 public void setInputData(byte[] inputData) { 669 this.inputData = inputData; 670 } 671 672 private void rewriteQS() { 673 StringBuffer qs=new StringBuffer(); 674 Pair p; 675 for(int i=0;i<parameters.length;i++) { 676 if(i>0) qs.append('&'); 677 p=parameters[i]; 678 qs.append(p.getName()); 679 qs.append('='); 680 qs.append(Caster.toString(p.getValue(),"")); 681 } 682 queryString=qs.toString(); 683 } 684 public void setSession(HttpSession session) { 685 this.session=session; 686 } 687 public static HttpServletRequestDummy clone(Config config,Resource rootDirectory,HttpServletRequest req) { 688 689 HttpServletRequestDummy dest = new HttpServletRequestDummy( 690 rootDirectory, 691 req.getServerName(), 692 req.getRequestURI(), 693 req.getQueryString(), 694 HttpUtil.cloneCookies(config,req), 695 HttpUtil.cloneHeaders(req), 696 HttpUtil.cloneParameters(req), 697 HttpUtil.getAttributesAsStruct(req), 698 getSessionEL(req) 699 ); 700 701 702 try { 703 dest.setCharacterEncoding(req.getCharacterEncoding()); 704 } catch (Exception e) { 705 706 } 707 708 dest.setRemoteAddr(req.getRemoteAddr()); 709 dest.setRemoteHost(req.getRemoteHost()); 710 dest.setAuthType(req.getAuthType()); 711 dest.setContentType(req.getContentType()); 712 dest.setContextPath(req.getContextPath()); 713 dest.setLocale(req.getLocale()); 714 dest.setMethod(req.getMethod()); 715 dest.setPathInfo(req.getPathInfo()); 716 dest.setProtocol(req.getProtocol()); 717 dest.setRequestedSessionId(req.getRequestedSessionId()); 718 dest.setScheme(req.getScheme()); 719 dest.setServerPort(req.getServerPort()); 720 dest.setSession(getSessionEL(req)); 721 return dest; 722 } 723 private static HttpSession getSessionEL(HttpServletRequest req) { 724 try{ 725 return req.getSession(); 726 } 727 catch(Throwable t){ 728 ExceptionUtil.rethrowIfNecessary(t); 729 } 730 return null; 731 } 732 public void setAttributes(Struct attributes) { 733 this.attributes=attributes; 734 } 735 736}