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    }