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    }