001 package railo.runtime.type.scope; 002 003 import java.io.UnsupportedEncodingException; 004 005 import railo.commons.lang.StringList; 006 import railo.commons.lang.StringUtil; 007 import railo.commons.net.URLDecoder; 008 import railo.commons.net.URLItem; 009 import railo.runtime.PageContext; 010 import railo.runtime.dump.DumpData; 011 import railo.runtime.dump.DumpProperties; 012 import railo.runtime.exp.ExpressionException; 013 import railo.runtime.op.Caster; 014 import railo.runtime.security.ScriptProtect; 015 import railo.runtime.type.Array; 016 import railo.runtime.type.ArrayImpl; 017 import railo.runtime.type.CastableStruct; 018 import railo.runtime.type.Collection; 019 import railo.runtime.type.KeyImpl; 020 import railo.runtime.type.List; 021 import railo.runtime.type.Scope; 022 import railo.runtime.type.Sizeable; 023 import railo.runtime.type.Struct; 024 import railo.runtime.type.StructImpl; 025 import railo.runtime.type.util.StructUtil; 026 027 028 029 /** 030 * Simple standart implementation of a Scope, for standart use. 031 */ 032 public abstract class ScopeSupport extends StructImpl implements Scope,Sizeable { 033 034 035 public static final Key APPLICATION = KeyImpl.intern("application"); 036 public static final Key CGI = KeyImpl.intern("cgi"); 037 public static final Key COOKIE = KeyImpl.intern("cookie"); 038 public static final Key CLIENT = KeyImpl.intern("client"); 039 public static final Key CLUSTER = KeyImpl.intern("cluster"); 040 public static final Key FORM = KeyImpl.intern("form"); 041 public static final Key REQUEST = KeyImpl.intern("request"); 042 public static final Key SESSION = KeyImpl.intern("session"); 043 public static final Key URL = KeyImpl.intern("url"); 044 045 private String name; 046 private String dspName; 047 private static int _id=0; 048 private int id=0; 049 private static final byte[] EMPTY="".getBytes(); 050 051 public static final int SCOPE_VAR=15; // FUTURE add to interface Scope 052 public static final int SCOPE_COUNT=16; 053 054 /** 055 * Field <code>isInit</code> 056 */ 057 protected boolean isInit; 058 private int type; 059 060 /** 061 * constructor for the Simple class 062 * @param name name of the scope 063 * @param type scope type (SCOPE_APPLICATION,SCOPE_COOKIE use) 064 */ 065 public ScopeSupport(boolean sync,String name, int type) { 066 super(sync?StructImpl.TYPE_SYNC:StructImpl.TYPE_REGULAR); 067 this.name=name; 068 this.type=type; 069 070 id=++_id; 071 } 072 /** 073 * constructor for ScopeSupport 074 * @param name name of the scope 075 * @param type scope type (SCOPE_APPLICATION,SCOPE_COOKIE use) 076 * @param doubleLinked mean that the struct has predictable iteration order this make the input order fix 077 */ 078 public ScopeSupport(String name, int type, int mapType) { 079 super(mapType); 080 this.name=name; 081 this.type=type; 082 083 id=++_id; 084 } 085 086 /** 087 * @see railo.runtime.dump.Dumpable#toDumpData(railo.runtime.PageContext, int) 088 */ 089 090 public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) { 091 return toDumpData(pageContext, maxlevel, dp, this, dspName); 092 } 093 094 public static DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp, Struct sct,String dspName) { 095 if(StringUtil.isEmpty(dspName))dspName="Scope"; 096 097 return StructUtil.toDumpTable(sct, dspName, pageContext, maxlevel, dp); 098 099 } 100 101 /** 102 * @see railo.runtime.type.StructImpl#invalidKey(java.lang.String) 103 */ 104 protected ExpressionException invalidKey(String key) { 105 return new ExpressionException("variable ["+key+"] doesn't exist in "+StringUtil.ucFirst(name)+" Scope (keys:"+List.arrayToList(keysAsString(), ",")+")"); 106 } 107 108 /** 109 * write parameter defined in a query string (name1=value1&name2=value2) to the scope 110 * @param qs Query String 111 * @return parsed name value pair 112 */ 113 protected static URLItem[] setFromQueryString(String str) { 114 return setFrom___(str, '&'); 115 } 116 117 protected static URLItem[] setFromTextPlain(String str) { 118 return setFrom___(str, '\n'); 119 } 120 protected static URLItem[] setFrom___(String tp,char delimeter) { 121 if(tp==null) return new URLItem[0]; 122 Array arr=List.listToArrayRemoveEmpty(tp,delimeter); 123 URLItem[] pairs=new URLItem[arr.size()]; 124 125 //Array item; 126 int index; 127 String name; 128 129 for(int i=1;i<=pairs.length;i++) { 130 name=Caster.toString(arr.get(i,""),""); 131 //if(name.length()==0) continue; 132 133 index=name.indexOf('='); 134 if(index!=-1) pairs[i-1]=new URLItem(name.substring(0,index),name.substring(index+1),true); 135 else pairs[i-1]=new URLItem(name,"",true); 136 137 } 138 return pairs; 139 } 140 141 protected static byte[] getBytes(String str) { 142 return str.getBytes(); 143 } 144 protected static byte[] getBytes(String str,String encoding) { 145 try { 146 return str.getBytes(encoding); 147 } catch (UnsupportedEncodingException e) { 148 return EMPTY; 149 } 150 } 151 152 protected void fillDecodedEL(URLItem[] raw, String encoding, boolean scriptProteced) { 153 try { 154 fillDecoded(raw, encoding,scriptProteced); 155 } catch (UnsupportedEncodingException e) { 156 try { 157 fillDecoded(raw, "iso-8859-1",scriptProteced); 158 } catch (UnsupportedEncodingException e1) {} 159 } 160 } 161 162 163 /** 164 * fill th data from given strut and decode it 165 * @param raw 166 * @param encoding 167 * @throws UnsupportedEncodingException 168 */ 169 protected void fillDecoded(URLItem[] raw, String encoding, boolean scriptProteced) throws UnsupportedEncodingException { 170 clear(); 171 String name,value; 172 //Object curr; 173 for(int i=0;i<raw.length;i++) { 174 name=raw[i].getName(); 175 value=raw[i].getValue(); 176 if(raw[i].isUrlEncoded()) { 177 name=URLDecoder.decode(name,encoding,true); 178 value=URLDecoder.decode(value,encoding,true); 179 } 180 // MUST valueStruct 181 if(name.indexOf('.')!=-1) { 182 StringList list=List.listToStringListRemoveEmpty(name,'.'); 183 Struct parent=this; 184 while(list.hasNextNext()) { 185 parent=_fill(parent,list.next(),new CastableStruct(),false,scriptProteced); 186 } 187 _fill(parent,list.next(),value,true,scriptProteced); 188 } 189 //else 190 _fill(this,name,value,true,scriptProteced); 191 } 192 } 193 194 private Struct _fill(Struct parent, String name, Object value, boolean isLast, boolean scriptProteced) { 195 Object curr; 196 boolean isArrayDef=false; 197 Collection.Key key=KeyImpl.getInstance(name); 198 199 // script protect 200 if(scriptProteced && value instanceof String) { 201 value=ScriptProtect.translate((String)value); 202 } 203 204 if(name.length() >2 && name.endsWith("[]")) { 205 isArrayDef=true; 206 name=name.substring(0,name.length()-2); 207 key=KeyImpl.getInstance(name); 208 curr=parent.get(key,null); 209 } 210 else { 211 curr=parent.get(key,null); 212 } 213 214 if(curr==null) { 215 if(isArrayDef) { 216 Array arr = new ArrayImpl(); 217 arr.appendEL(value); 218 parent.setEL(key,arr); 219 } 220 else parent.setEL(key,value); 221 } 222 else if(curr instanceof Array){ 223 ((Array) curr).appendEL(value); 224 } 225 else if(curr instanceof CastableStruct){ 226 if(isLast) ((CastableStruct)curr).setValue(value); 227 else return (Struct) curr; 228 229 } 230 else if(curr instanceof Struct){ 231 if(isLast) parent.setEL(key,value); 232 else return (Struct) curr; 233 } 234 else if(curr instanceof String){ 235 if(isArrayDef) { 236 Array arr = new ArrayImpl(); 237 arr.appendEL(curr); 238 arr.appendEL(value); 239 parent.setEL(key,arr); 240 } 241 else if(value instanceof Struct) { 242 parent.setEL(key,value); 243 } 244 else { 245 if(!StringUtil.isEmpty(value)) { 246 String existing=Caster.toString(curr,""); 247 if(StringUtil.isEmpty(existing)) 248 parent.setEL(key,value); 249 else 250 parent.setEL(key,Caster.toString(curr,"")+','+value); 251 } 252 } 253 } 254 if(!isLast) { 255 return (Struct)value; 256 } 257 return null; 258 } 259 260 /* 261 private String decode(Object value,String encoding) throws UnsupportedEncodingException { 262 return URLDecoder.decode(new String(Caster.toString(value,"").getBytes("ISO-8859-1"),encoding),encoding); 263 }*/ 264 265 /** 266 * @see railo.runtime.type.Scope#isInitalized() 267 */ 268 public boolean isInitalized() { 269 return isInit; 270 } 271 272 /** 273 * @see railo.runtime.type.Scope#initialize(railo.runtime.PageContext) 274 */ 275 public void initialize(PageContext pc) { 276 isInit=true; 277 } 278 279 /** 280 * @see railo.runtime.type.Scope#release() 281 */ 282 public void release() { 283 clear(); 284 isInit=false; 285 } 286 287 288 /** 289 * @return Returns the id. 290 */ 291 public int _getId() { 292 return id; 293 } 294 295 /** 296 * display name for dump 297 * @param dspName 298 */ 299 protected void setDisplayName(String dspName) { 300 this.dspName=dspName; 301 } 302 303 /** 304 * @see railo.runtime.type.Scope#getType() 305 */ 306 public int getType() { 307 return type; 308 } 309 310 /** 311 * @see railo.runtime.type.Scope#getTypeAsString() 312 */ 313 public String getTypeAsString() { 314 return name; 315 } 316 public long sizeOf() { 317 return StructUtil.sizeOf(this); 318 } 319 320 }