001 package railo.runtime.type.scope; 002 003 import java.util.Date; 004 import java.util.HashMap; 005 import java.util.Iterator; 006 import java.util.Map; 007 008 import javax.servlet.http.HttpServletRequest; 009 import javax.servlet.http.HttpServletResponse; 010 011 import railo.commons.lang.StringUtil; 012 import railo.runtime.PageContext; 013 import railo.runtime.config.Config; 014 import railo.runtime.engine.ThreadLocalPageContext; 015 import railo.runtime.exp.ExpressionException; 016 import railo.runtime.exp.PageException; 017 import railo.runtime.net.http.ReqRspUtil; 018 import railo.runtime.op.Caster; 019 import railo.runtime.op.date.DateCaster; 020 import railo.runtime.security.ScriptProtect; 021 import railo.runtime.type.Collection; 022 import railo.runtime.type.KeyImpl; 023 import railo.runtime.type.dt.DateTime; 024 import railo.runtime.type.dt.TimeSpan; 025 import railo.runtime.util.ApplicationContext; 026 027 /** 028 * Implementation of the Cookie scope 029 */ 030 public final class CookieImpl extends ScopeSupport implements Cookie,ScriptProtected { 031 032 private static final long serialVersionUID = -2341079090783313736L; 033 034 public static final int NEVER = 946626690; 035 036 private HttpServletResponse rsp; 037 private int scriptProtected=ScriptProtected.UNDEFINED; 038 private Map<String,String> raw=new HashMap<String,String>(); 039 private String charset; 040 041 /** 042 * constructor for the Cookie Scope 043 */ 044 public CookieImpl() { 045 super(false,"cookie",SCOPE_COOKIE); 046 } 047 048 049 /** 050 * @see railo.runtime.type.StructImpl#setEL(railo.runtime.type.Collection.Key, java.lang.Object) 051 */ 052 public Object setEL(Collection.Key key, Object value) { 053 try { 054 return set(key,value); 055 } catch (PageException e) { 056 return null; 057 } 058 } 059 060 public Object set(Collection.Key key, Object value) throws PageException { 061 raw.remove(key.getLowerString()); 062 setCookie(key,value,-1,false,"/",null); 063 return value; 064 } 065 066 private void set(Config config,javax.servlet.http.Cookie cookie) throws PageException { 067 068 String name=StringUtil.toLowerCase(ReqRspUtil.decode(cookie.getName(),charset,false)); 069 raw.put(name,cookie.getValue()); 070 if(isScriptProtected()) super.set (KeyImpl.init(name),ScriptProtect.translate(dec(cookie.getValue()))); 071 else super.set (KeyImpl.init(name),dec(cookie.getValue())); 072 } 073 074 /** 075 * @see railo.runtime.type.Collection#clear() 076 */ 077 public void clear() { 078 raw.clear(); 079 Collection.Key[] keys = keys(); 080 for(int i=0;i<keys.length;i++) { 081 removeEL(keys[i],false); 082 } 083 } 084 085 /** 086 * @see railo.runtime.type.Collection#remove(java.lang.String) 087 */ 088 public Object remove(String key) throws PageException { 089 return remove(KeyImpl.init(key), true); 090 } 091 092 public Object remove(Collection.Key key) throws PageException { 093 raw.remove(key.getLowerString()); 094 return remove(key, true); 095 } 096 097 public Object remove(Collection.Key key, boolean alsoInResponse) throws PageException { 098 raw.remove(key.getLowerString()); 099 Object obj=super.remove (key); 100 if(alsoInResponse)removeCookie(key); 101 return obj; 102 } 103 104 public Object removeEL(Collection.Key key) { 105 return removeEL(key, true); 106 } 107 108 private Object removeEL(Collection.Key key, boolean alsoInResponse) { 109 raw.remove(key.getLowerString()); 110 Object obj=super.removeEL (key); 111 if(obj!=null && alsoInResponse) removeCookie(key); 112 return obj; 113 } 114 115 private void removeCookie(Collection.Key key) { 116 javax.servlet.http.Cookie cookie=new javax.servlet.http.Cookie(key.getUpperString(),""); 117 cookie.setMaxAge(0); 118 cookie.setSecure(false); 119 cookie.setPath("/"); 120 rsp.addCookie(cookie); 121 } 122 123 /** 124 * @see railo.runtime.type.scope.Cookie#setCookie(java.lang.String, java.lang.Object, java.lang.Object, boolean, java.lang.String, java.lang.String) 125 */ 126 public void setCookie(String name, Object value, Object expires, boolean secure, String path, String domain) throws PageException { 127 setCookie(KeyImpl.init(name), value, expires, secure, path, domain); 128 } 129 public void setCookie(Collection.Key key, Object value, Object expires, boolean secure, String path, String domain) throws PageException { 130 int exp=-1; 131 132 // expires 133 if(expires instanceof Date) { 134 exp=toExpires((Date)expires); 135 } 136 else if(expires instanceof TimeSpan) { 137 exp=toExpires((TimeSpan)expires); 138 } 139 else if(expires instanceof Number) { 140 exp=toExpires((Number)expires); 141 } 142 else if(expires instanceof String) { 143 exp=toExpires((String)expires); 144 145 } 146 else { 147 throw new ExpressionException("invalid type ["+Caster.toClassName(expires)+"] for expires"); 148 } 149 150 setCookie(key, value, exp, secure, path, domain); 151 } 152 153 private int toExpires(String expires) throws ExpressionException { 154 String str=StringUtil.toLowerCase(expires.toString()); 155 if(str.equals("now"))return 0; 156 else if(str.equals("never"))return NEVER; 157 else { 158 DateTime dt = DateCaster.toDateAdvanced(expires,false,null,null); 159 if(dt!=null) { 160 return toExpires(dt); 161 } 162 return toExpires(Caster.toIntValue(expires)); 163 } 164 } 165 166 167 private int toExpires(Number expires) { 168 return toExpires(expires.intValue()); 169 } 170 private int toExpires(int expires) { 171 return expires*24*60*60; 172 } 173 174 175 private int toExpires(Date expires) { 176 double diff = expires.getTime()-System.currentTimeMillis(); 177 return (int)Math.round(diff/1000D); 178 } 179 private int toExpires(TimeSpan span) { 180 return (int)span.getSeconds(); 181 } 182 183 184 /** 185 * @see railo.runtime.type.scope.Cookie#setCookie(java.lang.String, java.lang.Object, int, boolean, java.lang.String, java.lang.String) 186 */ 187 public void setCookie(String name, Object value, int expires, boolean secure, String path, String domain) throws PageException { 188 setCookie(KeyImpl.init(name), value, expires, secure, path, domain); 189 } 190 191 /** 192 * @see railo.runtime.type.scope.Cookie#setCookie(railo.runtime.type.Collection.Key, java.lang.Object, int, boolean, java.lang.String, java.lang.String) 193 */ 194 public void setCookie(Collection.Key key, Object value, int expires, boolean secure, String path, String domain) 195 throws PageException { 196 197 javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie(enc(key.getUpperString()),enc(Caster.toString(value))); 198 cookie.setMaxAge(expires); 199 cookie.setSecure(secure); 200 cookie.setPath(path); 201 if(domain!=null && domain.trim().length()>0)cookie.setDomain(domain); 202 203 rsp.addCookie(cookie); 204 super.set (key, value); 205 } 206 207 208 209 /** 210 * @see railo.runtime.type.scope.Cookie#setCookieEL(java.lang.String, java.lang.Object, int, boolean, java.lang.String, java.lang.String) 211 */ 212 public void setCookieEL(String name, Object value, int expires, boolean secure, String path, String domain) { 213 setCookieEL(KeyImpl.init(name), value, expires, secure, path, domain); 214 } 215 216 public void setCookieEL(Collection.Key key, Object value, int expires, boolean secure, String path, String domain) { 217 javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie(enc(key.getUpperString()),enc(Caster.toString(value,"")));// encoding removed 218 219 cookie.setMaxAge( expires); 220 cookie.setSecure(secure); 221 cookie.setPath(path); 222 if(domain!=null && domain.trim().length()>0)cookie.setDomain(domain); 223 rsp.addCookie(cookie); 224 super.setEL (key, value); 225 } 226 227 228 229 /** 230 * @see railo.runtime.type.Scope#initialize(railo.runtime.PageContext) 231 */ 232 public void initialize(PageContext pc) { 233 Config config = ThreadLocalPageContext.getConfig(pc); 234 charset = pc.getConfig().getWebCharset(); 235 if(scriptProtected==ScriptProtected.UNDEFINED) { 236 scriptProtected=((pc.getApplicationContext().getScriptProtect()&ApplicationContext.SCRIPT_PROTECT_COOKIE)>0)? 237 ScriptProtected.YES:ScriptProtected.NO; 238 } 239 super.initialize(pc); 240 241 HttpServletRequest req = pc. getHttpServletRequest(); 242 this.rsp=pc. getHttpServletResponse(); 243 javax.servlet.http.Cookie[] cookies=ReqRspUtil.getCookies(config,req); 244 try { 245 for(int i=0;i<cookies.length;i++) { 246 set(config,cookies[i]); 247 } 248 } 249 catch (Exception e) {} 250 } 251 252 /** 253 * 254 * @see railo.runtime.type.scope.ScopeSupport#release() 255 */ 256 public void release() { 257 raw.clear(); 258 scriptProtected=ScriptProtected.UNDEFINED; 259 super.release(); 260 } 261 262 /** 263 * 264 * @see railo.runtime.type.scope.ScriptProtected#isScriptProtected() 265 */ 266 public boolean isScriptProtected() { 267 return scriptProtected==ScriptProtected.YES; 268 } 269 270 271 /** 272 * 273 * @see railo.runtime.type.scope.ScriptProtected#setScriptProtecting(boolean) 274 */ 275 public void setScriptProtecting(boolean scriptProtected) { 276 int _scriptProtected = scriptProtected?ScriptProtected.YES:ScriptProtected.NO; 277 if(isInitalized() && _scriptProtected!=this.scriptProtected) { 278 Iterator<Entry<String, String>> it = raw.entrySet().iterator(); 279 Entry<String, String> entry; 280 String key,value; 281 282 while(it.hasNext()){ 283 entry = it.next(); 284 key=entry.getKey().toString(); 285 value=dec(entry.getValue().toString()); 286 super.setEL(KeyImpl.init(key), scriptProtected?ScriptProtect.translate(value):value); 287 } 288 } 289 this.scriptProtected=_scriptProtected; 290 } 291 292 293 public String dec(String str) { 294 return ReqRspUtil.decode(str,charset,false); 295 } 296 public String enc(String str) { 297 return ReqRspUtil.encode(str,charset); 298 } 299 }