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