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.registry;
020
021import java.io.IOException;
022import java.io.InputStream;
023import java.io.StringWriter;
024import java.util.ArrayList;
025
026import lucee.commons.cli.Command;
027import lucee.commons.lang.StringUtil;
028import lucee.runtime.functions.string.ParseNumber;
029import lucee.runtime.op.Caster;
030import lucee.runtime.type.util.ListUtil;
031
032
033/**
034 * 
035 */
036public final class RegistryQuery {
037
038  private static final char DQ='"'; 
039  private static final int lenDWORD=RegistryEntry.REGDWORD_TOKEN.length();
040  private static final int lenSTRING=RegistryEntry.REGSTR_TOKEN.length();
041  private static final String NO_NAME="<NO NAME>";
042  
043          /**
044           * execute a String query on command line
045         * @param query String to execute
046         * @return
047         * @throws IOException
048         * @throws InterruptedException
049         */
050        public static String executeQuery(String[] cmd) throws IOException, InterruptedException {
051                return Command.execute(cmd).getOutput();
052        }  
053  
054          /**
055           * gets a single value form the registry
056         * @param branch brach to get value from
057         * @param entry entry to get
058         * @param type type of the registry entry to get
059         * @return registry entry or null of not exist
060         * @throws RegistryException
061         * @throws IOException
062         * @throws InterruptedException
063         */
064        public static RegistryEntry getValue(String branch, String entry, short type) throws RegistryException, IOException, InterruptedException {
065            String[] cmd = new String[]{"reg","query",cleanBrunch(branch),"/v",entry};
066                RegistryEntry[] rst = filter(executeQuery(cmd),branch,type);
067            if(rst.length==1) {
068                return rst[0];
069                //if(type==RegistryEntry.TYPE_ANY || type==r.getType()) return r;
070            }
071            return null;
072        }
073
074        /**
075         * gets all entries of one branch
076         * @param branch
077         * @param type
078         * @return
079         * @throws RegistryException
080         * @throws IOException
081         * @throws InterruptedException
082         */
083        public static RegistryEntry[] getValues(String branch, short type) throws RegistryException, IOException, InterruptedException {
084                String[] cmd = new String[]{"reg","query",branch};
085                return filter(executeQuery(cmd),cleanBrunch(branch),type);
086        }
087
088        /**
089         * writes a value to registry
090         * @param branch
091         * @param entry
092         * @param type
093         * @param value
094         * @throws RegistryException
095         * @throws IOException
096         * @throws InterruptedException
097         */
098        public static void setValue(String branch, String entry, short type, String value) throws RegistryException, IOException, InterruptedException {
099            
100            if(type==RegistryEntry.TYPE_KEY) {
101                String fullKey=ListUtil.trim(branch,"\\")+"\\"+ListUtil.trim(entry,"\\");
102                //String[] cmd = new String[]{"reg","add",cleanBrunch(fullKey),"/ve","/f"};
103                String[] cmd = new String[]{"reg","add",cleanBrunch(fullKey),"/f"};
104                executeQuery(cmd);
105                }
106            else {
107                if(type==RegistryEntry.TYPE_DWORD)value=Caster.toString(Caster.toIntValue(value,0));
108                String[] cmd = new String[]{"reg","add",cleanBrunch(branch),"/v",entry,"/t",RegistryEntry.toStringType(type),"/d",value,"/f"};
109                executeQuery(cmd);
110            }
111        }
112        
113        /**
114         * deletes a value or a key
115         * @param branch
116         * @param entry
117         * @throws IOException
118         * @throws InterruptedException
119         */
120        public static void deleteValue(String branch, String entry) throws IOException, InterruptedException {
121            if(entry==null) {
122                String[] cmd = new String[]{"reg","delete",cleanBrunch(branch),"/f"};
123                executeQuery(cmd);
124                //executeQuery("reg delete \""+List.trim(branch,"\\")+"\"  /f");
125            }
126            else {
127                String[] cmd = new String[]{"reg","delete",cleanBrunch(branch),"/v",entry,"/f"};
128                executeQuery(cmd);
129                //executeQuery("reg delete \""+List.trim(branch,"\\")+"\" /v "+entry+" /f");
130            }
131        }
132        
133        private static String cleanBrunch(String branch) {
134                branch=branch.replace('/', '\\');
135                branch=ListUtil.trim(branch,"\\");
136                if(branch.length()==0) return "\\";
137                return branch;
138        }
139        
140
141        /**
142         * filter registry entries from the raw result
143         * @param string plain result to filter regisry entries
144         * @param branch
145         * @param type
146         * @return filtered entries
147         * @throws RegistryException
148         */
149        private static RegistryEntry[] filter(String string,String branch, short type) throws RegistryException {
150                branch=ListUtil.trim(branch,"\\");
151            StringBuffer result=new StringBuffer();
152                ArrayList array=new ArrayList();
153                String[] arr=string.split("\n");
154                
155                for(int i=0;i<arr.length;i++) {
156                        String line=arr[i].trim();
157                        int indexDWORD=line.indexOf(RegistryEntry.REGDWORD_TOKEN);
158                        int indexSTRING=line.indexOf(RegistryEntry.REGSTR_TOKEN);
159                        
160                        if((indexDWORD!=-1) || (indexSTRING!=-1) ) {
161                            int index=(indexDWORD==-1)?indexSTRING:indexDWORD;
162                            int len=(indexDWORD==-1)?lenSTRING:lenDWORD;
163                            short _type=(indexDWORD==-1)?RegistryEntry.TYPE_STRING:RegistryEntry.TYPE_DWORD;
164                            
165                                if(result.length()>0)result.append("\n");
166                                 
167                                String _key=line.substring(0,index).trim();
168                                String _value=StringUtil.substringEL(line,index+len+1,"").trim();
169                                
170                                if(_key.equals(NO_NAME)) _key="";
171                                    if(_type==RegistryEntry.TYPE_DWORD)_value=String.valueOf(ParseNumber.invoke(_value.substring(2),"hex",0));
172                                    RegistryEntry re = new RegistryEntry(_type,_key,_value);
173                                    if(type==RegistryEntry.TYPE_ANY || type==re.getType()) array.add(re);
174                                //}
175                        }
176                        else if(line.indexOf(branch)==0 && (type==RegistryEntry.TYPE_ANY || type==RegistryEntry.TYPE_KEY)) {
177                            line=ListUtil.trim(line,"\\");
178                            if(branch.length()<line.length()) {
179                                array.add(new RegistryEntry(RegistryEntry.TYPE_KEY,ListUtil.last(line,"\\",true),""));
180                            }
181                        }
182                }
183                return (RegistryEntry[])array.toArray(new RegistryEntry[array.size()]);
184        }
185
186
187
188
189
190
191
192
193
194
195
196static class StreamReader extends Thread {
197    private InputStream is;
198    private StringWriter sw;
199
200    StreamReader(InputStream is) {
201      this.is = is;
202      sw = new StringWriter();
203    }
204
205    @Override
206    public void run() {
207      try {
208        int c;
209        while ((c = is.read()) != -1)
210          sw.write(c);
211        }
212        catch (IOException e) {  }
213      }
214
215    String getResult() {
216      return sw.toString();
217    }
218  }  
219}
220
221
222