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.security;
020
021import java.util.Iterator;
022import java.util.Map.Entry;
023
024import lucee.runtime.type.Collection.Key;
025import lucee.runtime.type.Struct;
026
027/**
028 * Script-protect to remove cross-attacks from strings
029 */
030public final class ScriptProtect {
031        
032        public static final String[] invalids=new String[]{
033                "object", "embed", "script", "applet", "meta", "iframe"
034        };
035        
036        /**
037         * translate all strig values of the struct i script-protected form
038         * @param sct Struct to translate its values
039         */
040        public static void translate(Struct sct) {
041                Iterator<Entry<Key, Object>> it = sct.entryIterator();
042                Entry<Key, Object> e;
043                Object value;
044                while(it.hasNext()) {
045                        e = it.next();
046                        value=e.getValue(); 
047                        if(value instanceof String) {
048                                sct.setEL(e.getKey(),translate((String)value));
049                        }
050                }
051        }
052        
053        /**
054         * translate string to script-protected form
055         * @param str
056         * @return translated String
057         */
058        public static String translate(String str) {
059                // TODO do-while machen und StringBuffer 
060                int index,last=0,endIndex;
061                StringBuffer sb=null;
062                String tagName;
063                while((index=str.indexOf('<',last))!=-1) {
064                        // read tagname
065                        int len=str.length();
066                        char c;
067                        for(endIndex=index+1;endIndex<len;endIndex++) {
068                                c=str.charAt(endIndex);
069                                if((c<'a' || c>'z') && (c<'A' || c>'Z'))break;
070                        }
071                        tagName=str.substring(index+1,endIndex);
072
073                        if(compareTagName(tagName)) {
074                                if(sb==null) {
075                                        sb=new StringBuffer();
076                                        last=0;
077                                }
078                                sb.append(str.substring(last,index+1));
079                                sb.append("invalidTag");
080                                last=endIndex;
081                        }
082                        else if(sb!=null) {
083                                sb.append(str.substring(last,index+1));
084                                last=index+1;
085                        }
086                        else last=index+1;
087                        
088                }
089                if(sb!=null) {
090                        if(last!=str.length())sb.append(str.substring(last));
091                        return sb.toString(); 
092                }
093                return str;
094        }
095        
096        
097        private static boolean compareTagName(String tagName) {
098                for(int i=0;i<invalids.length;i++) {
099                        if(invalids[i].equalsIgnoreCase(tagName)) return true;
100                }
101                return false;
102        }
103
104        /**
105         * @param args
106         */
107        public static void main(String[] args) {
108                System.out.println(translate("<hell <script><script susi=1><scriptsrc><> how are you <br />object <object ddd"));
109
110        }
111}