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.type.scope; 020 021import java.net.InetAddress; 022import java.net.UnknownHostException; 023import java.util.Enumeration; 024import java.util.HashMap; 025import java.util.HashSet; 026import java.util.Iterator; 027import java.util.Map; 028import java.util.Set; 029 030import javax.servlet.http.HttpServletRequest; 031 032import lucee.commons.lang.ExceptionUtil; 033import lucee.commons.lang.StringUtil; 034import lucee.runtime.PageContext; 035import lucee.runtime.config.NullSupportHelper; 036import lucee.runtime.dump.DumpData; 037import lucee.runtime.dump.DumpProperties; 038import lucee.runtime.engine.ThreadLocalPageContext; 039import lucee.runtime.exp.PageException; 040import lucee.runtime.listener.ApplicationContext; 041import lucee.runtime.net.http.ReqRspUtil; 042import lucee.runtime.op.Caster; 043import lucee.runtime.security.ScriptProtect; 044import lucee.runtime.type.Collection; 045import lucee.runtime.type.KeyImpl; 046import lucee.runtime.type.Struct; 047import lucee.runtime.type.StructImpl; 048import lucee.runtime.type.it.EntryIterator; 049import lucee.runtime.type.it.KeyIterator; 050import lucee.runtime.type.util.KeyConstants; 051import lucee.runtime.type.util.StructSupport; 052import lucee.runtime.type.util.StructUtil; 053 054/** 055 * 056 * 057 * To change the template for this generated type comment go to 058 * Window - Preferences - Java - Code Generation - Code and Comments 059 */ 060public final class CGIImpl extends StructSupport implements CGI,ScriptProtected { 061 062 private static final long serialVersionUID = 5219795840777155232L; 063 064 private static final Collection.Key[] STATIC_KEYS={ 065 KeyConstants._auth_password, KeyConstants._auth_type, KeyConstants._auth_user, KeyConstants._cert_cookie, KeyConstants._cert_flags, 066 KeyConstants._cert_issuer, KeyConstants._cert_keysize, KeyConstants._cert_secretkeysize, KeyConstants._cert_serialnumber, 067 KeyConstants._cert_server_issuer, KeyConstants._cert_server_subject, KeyConstants._cert_subject,KeyConstants._cf_template_path, 068 KeyConstants._content_length, KeyConstants._content_type, KeyConstants._gateway_interface, KeyConstants._http_accept, 069 KeyConstants._http_accept_encoding, KeyConstants._http_accept_language, KeyConstants._http_connection, KeyConstants._http_cookie, 070 KeyConstants._http_host, KeyConstants._http_user_agent, KeyConstants._http_referer, KeyConstants._https, KeyConstants._https_keysize, 071 KeyConstants._https_secretkeysize, KeyConstants._https_server_issuer, KeyConstants._https_server_subject, KeyConstants._path_info, 072 KeyConstants._path_translated, KeyConstants._query_string, KeyConstants._remote_addr, KeyConstants._remote_host, KeyConstants._remote_user, 073 KeyConstants._request_method, KeyConstants._request_url, KeyConstants._script_name, KeyConstants._server_name, KeyConstants._server_port, KeyConstants._server_port_secure, 074 KeyConstants._server_protocol, KeyConstants._server_software, KeyConstants._web_server_api, KeyConstants._context_path, KeyConstants._local_addr, 075 KeyConstants._local_host 076 }; 077 private static Struct staticKeys=new StructImpl(); 078 static{ 079 for(int i=0;i<STATIC_KEYS.length;i++){ 080 staticKeys.setEL(STATIC_KEYS[i],""); 081 } 082 } 083 084 private static String localAddress=""; 085 private static String localHost=""; 086 087 static { 088 try { 089 InetAddress addr = InetAddress.getLocalHost(); 090 localAddress=addr.getHostAddress(); 091 localHost=addr.getHostName(); 092 } 093 catch(UnknownHostException uhe) {} 094 } 095 096 private HttpServletRequest req; 097 private boolean isInit; 098 private Struct internal; 099 private Map<Collection.Key,Collection.Key> aliases; 100 private int scriptProtected; 101 102 103 public CGIImpl(){ 104 //this.setReadOnly(true); 105 } 106 107 @Override 108 public boolean isInitalized() { 109 return isInit; 110 } 111 112 @Override 113 public void initialize(PageContext pc) { 114 isInit=true; 115 req=pc.getHttpServletRequest(); 116 117 118 if(scriptProtected==ScriptProtected.UNDEFINED) { 119 scriptProtected=((pc.getApplicationContext().getScriptProtect()&ApplicationContext.SCRIPT_PROTECT_CGI)>0)? 120 ScriptProtected.YES:ScriptProtected.NO; 121 } 122 123 //if(internal==null) { 124 internal=new StructImpl(); 125 aliases=new HashMap<Collection.Key,Collection.Key>(); 126 String k,v; 127 Collection.Key key,alias,httpKey; 128 try { 129 Enumeration e = req.getHeaderNames(); 130 while(e.hasMoreElements()) { 131 132 // keys 133 k = (String)e.nextElement(); 134 key=KeyImpl.init(k); 135 if(k.contains("-")) alias=KeyImpl.init(k.replace('-','_')); 136 else alias=null; 137 httpKey=KeyImpl.init("http_"+(alias==null?key:alias).getString()); 138 139 // value 140 v = doScriptProtect(req.getHeader(k)); 141 142 // set value 143 internal.setEL(httpKey,v); 144 145 // set alias keys 146 aliases.put(key, httpKey); 147 if(alias!=null)aliases.put(alias, httpKey); 148 } 149 } 150 catch(Throwable t){ 151 ExceptionUtil.rethrowIfNecessary(t); 152 t.printStackTrace(); 153 } 154 //} 155 } 156 157 @Override 158 public void release() { 159 isInit=false; 160 scriptProtected=ScriptProtected.UNDEFINED; 161 req=null; 162 internal=null; 163 aliases=null; 164 } 165 166 @Override 167 public void release(PageContext pc) { 168 release(); 169 } 170 171 @Override 172 public boolean containsKey(Key key) { 173 return internal.containsKey(key) || staticKeys.containsKey(key) || aliases.containsKey(key); 174 } 175 176 @Override 177 public boolean containsValue(Object value) { 178 Iterator<Object> it = internal.valueIterator(); 179 while(it.hasNext()){ 180 if(it.next().equals(value)) return true; 181 } 182 return false; 183 } 184 185 @Override 186 public Collection duplicate(boolean deepCopy) { 187 Struct sct=new StructImpl(); 188 StructImpl.copy(this,sct,deepCopy); 189 return sct; 190 } 191 192 193 @Override 194 public int size() { 195 return keys().length; 196 } 197 198 @Override 199 public Collection.Key[] keys() { 200 Set<Collection.Key> set=new HashSet<Collection.Key>(); 201 Iterator<Key> it = internal.keyIterator(); 202 while(it.hasNext())set.add(it.next()); 203 it = staticKeys.keyIterator(); 204 while(it.hasNext())set.add(it.next()); 205 return set.toArray(new Collection.Key[set.size()]); 206 } 207 208 @Override 209 public Object get(Collection.Key key, Object defaultValue) { 210 211 // do we have internal? 212 Object res = internal.get(key, NullSupportHelper.NULL()); 213 if(res!=NullSupportHelper.NULL()) return res; 214 215 // do we have an alias 216 { 217 Key k = aliases.get(key); 218 if(k!=null) { 219 res = internal.get(k, NullSupportHelper.NULL()); 220 if(res!=NullSupportHelper.NULL()) return res; 221 } 222 } 223 224 225 if(key.length()>7) { 226 char first=key.lowerCharAt(0); 227 try{ 228 if(first=='a') { 229 if(key.equals(KeyConstants._auth_type)) 230 return store(key,toString(req.getAuthType())); 231 } 232 else if(first=='c') { 233 if(key.equals(KeyConstants._context_path)) 234 return store(key,toString(req.getContextPath())); 235 if(key.equals(KeyConstants._cf_template_path)) 236 return store(key,getPathTranslated()); 237 } 238 else if(first=='h') { 239 if(StringUtil.startsWithIgnoreCase(key.getString(), "http_")) { 240 // _http_if_modified_since 241 if(key.equals(KeyConstants._http_if_modified_since)) { 242 Object o = internal.get(KeyConstants._last_modified,NullSupportHelper.NULL()); 243 if(o!=NullSupportHelper.NULL()) return store(key,(String)o); 244 } 245 } 246 } 247 else if(first=='r') { 248 if(key.equals(KeyConstants._remote_user)) 249 return store(key,toString(req.getRemoteUser())); 250 if(key.equals(KeyConstants._remote_addr)) 251 return store(key,toString(req.getRemoteAddr())); 252 if(key.equals(KeyConstants._remote_host)) 253 return store(key,toString(req.getRemoteHost())); 254 if(key.equals(KeyConstants._request_method)) 255 return store(key,req.getMethod()); 256 if(key.equals(KeyConstants._request_url)) 257 return store(key,ReqRspUtil.getRequestURL( req, true )); 258 if(key.equals(KeyConstants._request_uri)) 259 return store(key,toString(req.getAttribute("javax.servlet.include.request_uri"))); 260 // we do not store this, to be as backward compatible as possible. 261 if(key.getUpperString().startsWith("REDIRECT_")){ 262 // from attributes (key sensitive) 263 Object value = req.getAttribute(key.getString()); 264 if(!StringUtil.isEmpty(value)) return toString(value); 265 266 // from attributes (key insensitive) 267 Enumeration<String> names = req.getAttributeNames(); 268 String k; 269 while(names.hasMoreElements()){ 270 k=names.nextElement(); 271 if(k.equalsIgnoreCase(key.getString())) { 272 return toString(req.getAttribute(k)); 273 } 274 } 275 } 276 } 277 else if(first=='l') { 278 if(key.equals(KeyConstants._local_addr)) 279 return store(key,toString(localAddress)); 280 if(key.equals(KeyConstants._local_host)) 281 return store(key,toString(localHost)); 282 } 283 else if(first=='s') { 284 if(key.equals(KeyConstants._script_name)) 285 return store(key,ReqRspUtil.getScriptName(null,req)); 286 if(key.equals(KeyConstants._server_name)) 287 return store(key,toString(req.getServerName())); 288 if(key.equals(KeyConstants._server_protocol)) 289 return store(key,toString(req.getProtocol())); 290 if(key.equals(KeyConstants._server_port)) 291 return store(key,Caster.toString(req.getServerPort())); 292 if(key.equals(KeyConstants._server_port_secure)) 293 return store(key,req.isSecure()?"1":"0"); 294 } 295 else if(first=='p') { 296 if(key.equals(KeyConstants._path_info)) { 297 String pathInfo = Caster.toString(req.getAttribute("javax.servlet.include.path_info"),null); 298 if(StringUtil.isEmpty(pathInfo)) pathInfo = Caster.toString(req.getHeader("xajp-path-info"),null); 299 if(StringUtil.isEmpty(pathInfo)) pathInfo = req.getPathInfo(); 300 if(StringUtil.isEmpty(pathInfo)) { 301 pathInfo = Caster.toString(req.getAttribute("requestedPath"),null); 302 if(!StringUtil.isEmpty(pathInfo,true)) { 303 String scriptName = ReqRspUtil.getScriptName(null,req); 304 if ( pathInfo.startsWith(scriptName) ) 305 pathInfo = pathInfo.substring(scriptName.length()); 306 } 307 } 308 309 if(!StringUtil.isEmpty(pathInfo,true)) 310 return store(key,pathInfo); 311 return ""; 312 } 313 if(key.equals(KeyConstants._path_translated)) 314 return store(key,getPathTranslated()); 315 } 316 else if(first=='q') { 317 if(key.equals(KeyConstants._query_string)) 318 return store(key,doScriptProtect(toString(ReqRspUtil.getQueryString(req)))); 319 } 320 } 321 catch(Throwable t){ 322 ExceptionUtil.rethrowIfNecessary(t); 323 } 324 } 325 return other(key,defaultValue); 326 } 327 private Object store(Key key, String value) { 328 internal.setEL(key, value); 329 return value; 330 } 331 332 private Object other(Collection.Key key, Object defaultValue) { 333 if(staticKeys.containsKey(key)) return ""; 334 return defaultValue; 335 } 336 337 private String getPathTranslated() { 338 try{ 339 PageContext pc = ThreadLocalPageContext.get(); 340 return pc.getBasePageSource().getResourceTranslated(pc).toString(); 341 } 342 catch(Throwable t){ 343 ExceptionUtil.rethrowIfNecessary(t); 344 } 345 return ""; 346 } 347 348 private String doScriptProtect(String value) { 349 if(isScriptProtected()) return ScriptProtect.translate(value); 350 return value; 351 } 352 353 private String toString(Object str) { 354 return StringUtil.toStringEmptyIfNull(str); 355 } 356 357 @Override 358 public Object get(Collection.Key key) { 359 Object value=get(key,""); 360 if(value==null)value= ""; 361 return value; 362 } 363 364 @Override 365 public Iterator<Collection.Key> keyIterator() { 366 return new KeyIterator(keys()); 367 } 368 369 @Override 370 public Iterator<Entry<Key, Object>> entryIterator() { 371 return new EntryIterator(this, keys()); 372 } 373 374 375 @Override 376 public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) { 377 return StructUtil.toDumpTable(this, "CGI Scope (writable)", pageContext, maxlevel, dp); 378 } 379 380 @Override 381 public int getType() { 382 return SCOPE_CGI; 383 } 384 385 @Override 386 public String getTypeAsString() { 387 return "cgi"; 388 } 389 390 @Override 391 public boolean isScriptProtected() { 392 return scriptProtected==ScriptProtected.YES; 393 } 394 395 @Override 396 public void setScriptProtecting(ApplicationContext ac,boolean scriptProtecting) { 397 scriptProtected=scriptProtecting?ScriptProtected.YES:ScriptProtected.NO; 398 } 399 400 @Override 401 public Object remove(Key key) throws PageException { 402 Key k = aliases.remove(key); 403 if(k!=null) key=k; 404 405 Object rtn=internal.remove(key); 406 if(staticKeys.containsKey(key))internal.set(key, ""); // we do this to avoid to this get reinit again 407 return rtn; 408 } 409 410 411 @Override 412 public Object removeEL(Key key) { 413 Key k = aliases.remove(key); 414 if(k!=null) key=k; 415 416 Object rtn=internal.removeEL(key); 417 if(staticKeys.containsKey(key))internal.setEL(key, ""); // we do this to avoid to this get reinit again 418 return rtn; 419 } 420 421 422 @Override 423 public void clear() { 424 Key[] keys = keys(); 425 for(int i=0;i<keys.length;i++){ 426 removeEL(keys[i]); 427 } 428 } 429 430 431 @Override 432 public Object set(Key key, Object value) throws PageException { 433 Key k = aliases.get(key); 434 if(k!=null) key=k; 435 return internal.set(key, value); 436 } 437 438 439 @Override 440 public Object setEL(Key key, Object value) { 441 Key k = aliases.get(key); 442 if(k!=null) key=k; 443 return internal.setEL(key, value); 444 } 445 446 447 @Override 448 public Iterator<Object> valueIterator() { 449 return internal.valueIterator(); 450 } 451 452}