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.storage; 020 021import java.util.Date; 022 023import lucee.commons.io.log.Log; 024import lucee.commons.lang.ExceptionUtil; 025import lucee.commons.lang.StringUtil; 026import lucee.runtime.PageContext; 027import lucee.runtime.converter.ScriptConverter; 028import lucee.runtime.interpreter.CFMLExpressionInterpreter; 029import lucee.runtime.listener.ApplicationContext; 030import lucee.runtime.op.Caster; 031import lucee.runtime.type.KeyImpl; 032import lucee.runtime.type.Struct; 033import lucee.runtime.type.StructImpl; 034import lucee.runtime.type.dt.DateTime; 035import lucee.runtime.type.dt.DateTimeImpl; 036import lucee.runtime.type.dt.TimeSpan; 037import lucee.runtime.type.scope.Cookie; 038import lucee.runtime.type.scope.ScopeContext; 039import lucee.runtime.type.util.KeyConstants; 040 041/** 042 * client scope that store it's data in the cookie of the client 043 */ 044public abstract class StorageScopeCookie extends StorageScopeImpl { 045 046 private static final long serialVersionUID = -3509170569488448183L; 047 048 private static ScriptConverter serializer=new ScriptConverter(); 049 protected static CFMLExpressionInterpreter evaluator=new CFMLExpressionInterpreter(false); 050 //private Cookie cookie; 051 private String cookieName; 052 053 //private TimeSpan timeout; 054 055 056 static { 057 ignoreSet.add(KeyConstants._cfid); 058 ignoreSet.add(KeyConstants._cftoken); 059 ignoreSet.add(KeyConstants._urltoken); 060 ignoreSet.add(KeyConstants._lastvisit); 061 ignoreSet.add(KeyConstants._hitcount); 062 ignoreSet.add(KeyConstants._timecreated); 063 } 064 065 066 067 /** 068 * Constructor of the class 069 * @param pc 070 * @param name 071 * @param sct 072 */ 073 protected StorageScopeCookie(PageContext pc,String cookieName,String strType,int type,Struct sct) { 074 super( 075 sct, 076 doNowIfNull(pc,Caster.toDate(sct.get(TIMECREATED,null),false,pc.getTimeZone(),null)), 077 doNowIfNull(pc,Caster.toDate(sct.get(LASTVISIT,null),false,pc.getTimeZone(),null)), 078 -1, 079 type==SCOPE_CLIENT?Caster.toIntValue(sct.get(HITCOUNT,"1"),1):0, 080 strType,type); 081 this.cookieName=cookieName; 082 } 083 084 /** 085 * Constructor of the class, clone existing 086 * @param other 087 */ 088 protected StorageScopeCookie(StorageScopeCookie other,boolean deepCopy) { 089 super(other,deepCopy); 090 cookieName=other.cookieName; 091 } 092 093 private static DateTime doNowIfNull(PageContext pc,DateTime dt) { 094 if(dt==null)return new DateTimeImpl(pc.getConfig()); 095 return dt; 096 } 097 098 public void touchAfterRequest(PageContext pc) { 099 boolean _isInit=isinit; 100 super.touchAfterRequest(pc); 101 if(!_isInit) return; 102 103 ApplicationContext ac=pc.getApplicationContext(); 104 TimeSpan timespan=(getType()==SCOPE_CLIENT)?ac.getClientTimeout():ac.getSessionTimeout(); 105 Cookie cookie = pc.cookieScope(); 106 107 108 Date exp = new DateTimeImpl(pc,System.currentTimeMillis()+timespan.getMillis(),true); 109 try { 110 String ser=serializer.serializeStruct(sct, ignoreSet); 111 if(hasChanges()){ 112 cookie.setCookie(KeyImpl.init(cookieName), ser,exp, false, "/", null); 113 } 114 cookie.setCookie(KeyImpl.init(cookieName+"_LV"), Caster.toString(_lastvisit.getTime()), exp, false, "/", null); 115 116 if(getType()==SCOPE_CLIENT){ 117 cookie.setCookie(KeyImpl.init(cookieName+"_TC"), Caster.toString(timecreated.getTime()),exp, false, "/", null); 118 cookie.setCookie(KeyImpl.init(cookieName+"_HC"), Caster.toString(sct.get(HITCOUNT,"")), exp, false, "/", null); 119 } 120 121 } 122 catch (Throwable t) { 123 ExceptionUtil.rethrowIfNecessary(t); 124 } 125 } 126 127 @Override 128 public String getStorageType() { 129 return "Cookie"; 130 } 131 132 133 protected static Struct _loadData(PageContext pc, String cookieName, int type,String strType, Log log) { 134 String data = (String)pc.cookieScope().get(cookieName,null); 135 if(data!=null) { 136 try { 137 Struct sct = (Struct) evaluator.interpret(pc,data); 138 long l; 139 String str; 140 141 // last visit 142 str = (String)pc.cookieScope().get(cookieName+"_LV",null); 143 if(!StringUtil.isEmpty(str)) { 144 l=Caster.toLongValue(str,0); 145 if(l>0)sct.setEL(LASTVISIT, new DateTimeImpl(pc,l,true)); 146 } 147 148 149 if(type==SCOPE_CLIENT){ 150 // hit count 151 str= (String)pc.cookieScope().get(cookieName+"_HC",null); 152 if(!StringUtil.isEmpty(str)) sct.setEL(HITCOUNT, Caster.toDouble(str,null)); 153 154 // time created 155 str = (String)pc.cookieScope().get(cookieName+"_TC",null); 156 if(!StringUtil.isEmpty(str)) { 157 l=Caster.toLongValue(str,0); 158 if(l>0)sct.setEL(TIMECREATED, new DateTimeImpl(pc,l,true)); 159 } 160 } 161 162 ScopeContext.info(log,"load data from cookie for "+strType+" scope for "+pc.getApplicationContext().getName()+"/"+pc.getCFID()); 163 return sct; 164 } 165 catch (Exception e) { 166 167 } 168 } 169 ScopeContext.info(log,"create new "+strType+" scope for "+pc.getApplicationContext().getName()+"/"+pc.getCFID()); 170 171 return new StructImpl(); 172 } 173 174 protected static boolean has(PageContext pc, String cookieName, int type,String strType) { 175 // TODO better impl 176 String data = (String)pc.cookieScope().get(cookieName,null); 177 return data!=null; 178 179 } 180}