001    package railo.runtime.config;
002    
003    import java.io.IOException;
004    import java.io.InputStream;
005    
006    import javax.servlet.ServletConfig;
007    import javax.servlet.ServletContext;
008    
009    import railo.commons.digest.MD5;
010    import railo.commons.io.IOUtil;
011    import railo.commons.io.SystemUtil;
012    import railo.commons.io.log.Log;
013    import railo.commons.io.log.LogAndSource;
014    import railo.commons.io.log.LogAndSourceImpl;
015    import railo.commons.io.log.LogConsole;
016    import railo.commons.io.log.LogResource;
017    import railo.commons.io.res.Resource;
018    import railo.commons.io.res.util.ResourceUtil;
019    import railo.commons.lang.StringUtil;
020    import railo.commons.lang.SystemOut;
021    import railo.runtime.Mapping;
022    import railo.runtime.exp.SecurityException;
023    import railo.runtime.security.SecurityManager;
024    import railo.runtime.type.Struct;
025    
026    
027    /**
028     * 
029     */
030    public final class ConfigWebUtil {
031        
032        /**
033         * touch a file object by the string definition
034         * @param config 
035         * @param directory
036         * @param path
037         * @param type
038         * @return matching file
039         */
040        public static Resource getFile(Config config, Resource directory,String path, short type) {
041            path=replacePlaceholder(path,config);
042            if(!StringUtil.isEmpty(path,true)) {
043                Resource file=getFile(directory.getRealResource(path),type);
044                if(file!=null) return file;
045    
046                file=getFile(config.getResource(path),type);
047                
048                if(file!=null) return file;
049            }
050            return null;
051        }
052        
053        /**
054             * generate a file object by the string definition
055         * @param rootDir 
056         * @param strDir 
057         * @param defaultDir 
058         * @param configDir 
059         * @param type 
060         * @param config 
061         * @return file
062             */
063        static Resource getFile(Resource rootDir,String strDir, String defaultDir,Resource configDir, short type, ConfigImpl config)  {
064            strDir=replacePlaceholder(strDir,config);
065            if(!StringUtil.isEmpty(strDir,true)) {
066                    Resource res;
067                    if(strDir.indexOf("://")!=-1){ // TODO better impl.
068                            res=getFile(config.getResource(strDir),type);
069                            if(res!=null) return res;
070                    }
071                    res=getFile(rootDir.getRealResource(strDir),type);
072                if(res!=null) return res;
073    
074                res=getFile(config.getResource(strDir),type);
075                if(res!=null) return res;
076            }
077            if(defaultDir==null) return null;
078            Resource file=getFile(configDir.getRealResource(defaultDir),type);
079            return file;
080        }
081    
082        
083        /*public static String replacePlaceholder(String str, Config config) {
084            if(StringUtil.isEmpty(str)) return str;
085            if(str.indexOf("railo-pcw-web")!=-1){
086                    print.out(str);
087                    str=_replacePlaceholder(str, config);
088                    print.out(str);
089                    return str;
090            }
091            return _replacePlaceholder(str, config);
092        }*/
093        public static String replacePlaceholder(String str, Config config) {
094            if(StringUtil.isEmpty(str)) return str;
095            
096            if(StringUtil.startsWith(str,'{')){
097                ConfigServer cs;
098                
099                
100                // Config Server
101                if(str.startsWith("{railo-config")) {    
102                    if(str.startsWith("}",13)) str=config.getConfigDir().getReal(str.substring(14));
103                    else if(str.startsWith("-dir}",13)) str=config.getConfigDir().getReal(str.substring(18));
104                    else if(str.startsWith("-directory}",13)) str=config.getConfigDir().getReal(str.substring(24));
105                }
106                
107                
108                else if(str.startsWith("{railo-server")) {
109                    cs=((ConfigImpl)config).getConfigServerImpl();
110                    //if(config instanceof ConfigServer && cs==null) cs=(ConfigServer) cw;
111                    if(cs!=null) {
112                        if(str.startsWith("}",13)) str=cs.getConfigDir().getReal(str.substring(14));
113                        else if(str.startsWith("-dir}",13)) str=cs.getConfigDir().getReal(str.substring(18));
114                        else if(str.startsWith("-directory}",13)) str=cs.getConfigDir().getReal(str.substring(24));
115                    }
116                }
117                // Config Web
118                else if(str.startsWith("{railo-web")) {
119                    //if(cw instanceof ConfigServer) cw=null;
120                    //if(config instanceof ConfigWeb) {
121                        if(str.startsWith("}",10)) str=config.getConfigDir().getReal(str.substring(11));
122                        else if(str.startsWith("-dir}",10)) str=config.getConfigDir().getReal(str.substring(15));
123                        else if(str.startsWith("-directory}",10)) str=config.getConfigDir().getReal(str.substring(21));
124                    //}
125                }
126                // Web Root
127                else if(str.startsWith("{web-root")) {
128                    //if(cw instanceof ConfigServer) cw=null;
129                    if(config instanceof ConfigWeb) {
130                        if(str.startsWith("}",9)) str=config.getRootDirectory().getReal(str.substring(10));
131                        else if(str.startsWith("-dir}",9)) str=config.getRootDirectory().getReal(str.substring(14));
132                        else if(str.startsWith("-directory}",9)) str=config.getRootDirectory().getReal(str.substring(20));
133                    }
134                }
135                // Temp
136                else if(str.startsWith("{temp")) {
137                    if(str.startsWith("}",5)) str=config.getTempDirectory().getRealResource(str.substring(6)).toString();
138                    else if(str.startsWith("-dir}",5)) str=config.getTempDirectory().getRealResource(str.substring(10)).toString();
139                    else if(str.startsWith("-directory}",5)) str=config.getTempDirectory().getRealResource(str.substring(16)).toString();
140                }
141                else if(config instanceof ServletConfig)str=SystemUtil.parsePlaceHolder(str,((ServletConfig)config).getServletContext(),((ConfigImpl)config).getConfigServerImpl().getLabels());
142                else str=SystemUtil.parsePlaceHolder(str);
143                
144                if(StringUtil.startsWith(str,'{')){
145                    Struct constants = ((ConfigImpl)config).getConstants();
146                    String[] arr = constants.keysAsString();
147                    for(int i=0;i<arr.length;i++) {
148                            if(StringUtil.startsWithIgnoreCase(str,"{"+arr[i]+"}")) {
149                                    String value=(String) constants.get(arr[i],null);
150                                    str=config.getResource( value)
151                                            .getReal(str.substring(arr[i].length()+2));
152                            break;
153                                    
154                            }
155                    }
156                }
157            }
158            return str;
159        }
160        
161        
162        /**
163         * get only a existing file, dont create it
164         * @param sc
165         * @param strDir
166         * @param defaultDir
167         * @param configDir
168         * @param type
169         * @param config 
170         * @return existing file
171         */
172        public static Resource getExistingResource(ServletContext sc,String strDir, String defaultDir,Resource configDir, short type, ConfigImpl config) {
173            //ARP
174            
175            strDir=replacePlaceholder(strDir,config);
176            if(strDir!=null && strDir.trim().length()>0) {
177                    Resource res=_getExistingFile(config.getResource(ResourceUtil.merge(sc.getRealPath("/"),strDir)),type);
178                if(res!=null) return res;
179                
180                res=_getExistingFile(config.getResource(strDir),type);
181                if(res!=null) return res;
182            }
183            if(defaultDir==null) return null;
184            return _getExistingFile(configDir.getRealResource(defaultDir),type);
185            
186        }
187    
188        private static Resource _getExistingFile(Resource file, short type) {
189            
190            boolean asDir=type==ResourceUtil.TYPE_DIR;
191            // File
192            if(file.exists() && ((file.isDirectory() && asDir)||(file.isFile() && !asDir))) {
193                return ResourceUtil.getCanonicalResourceEL(file);
194            }
195            return null;
196        }
197    
198        /**
199         * 
200         * @param file
201         * @param type (FileUtil.TYPE_X)
202         * @return created file
203         */
204        public static Resource getFile(Resource file, short type) {
205            return ResourceUtil.createResource(file,ResourceUtil.LEVEL_GRAND_PARENT_FILE,type);
206        }
207        /*public static File getFile(File file, int level, short type) {
208                    
209            boolean asDir=type==TYPE_DIR;
210            // File
211                    if(level>=LEVEL_FILE && file.exists() && ((file.isDirectory() && asDir)||(file.isFile() && !asDir))) {
212                        return FileUtil.getCanonicalFileEL(file);
213                    }
214                    
215                    // Parent
216                    File parent=file.getParentFile();
217                    if(level>=LEVEL_PARENT && parent!=null && parent.exists() && FileUtil.canRW(parent)) {
218                if(asDir) {
219                            if(file.mkdirs()) return FileUtil.getCanonicalFileEL(file);
220                        }
221                        else {
222                            if(FileUtil.createNewFileEL(file))return FileUtil.getCanonicalFileEL(file);
223                        }
224                            return FileUtil.getCanonicalFileEL(file);
225                    }    
226                    
227                    // Grand Parent
228                    if(level>=LEVEL_GRAND_PARENT && parent!=null) {
229                            File gparent=parent.getParentFile();
230                            if(gparent!=null && gparent.exists() && FileUtil.canRW(gparent)) {
231                                if(asDir) {
232                                    if(file.mkdirs())return FileUtil.getCanonicalFileEL(file);
233                                }
234                                else {
235                                    if(parent.mkdirs() && FileUtil.createNewFileEL(file))
236                                        return FileUtil.getCanonicalFileEL(file);
237                                }
238                            }        
239                    }
240                    return null;
241        }*/
242        
243        /**
244         * checks if file is a directory or not, if directory dosent exists, it will be created
245         * @param directory
246         * @return is directory or not
247         */
248            public static boolean isDirectory(Resource directory) {
249            if(directory.exists()) return directory.isDirectory();
250            return directory.mkdirs();
251        }
252        
253        /**
254         * checks if file is a file or not, if file dosent exists, it will be created
255         * @param file
256         * @return is file or not
257         */
258        public static boolean isFile(Resource file) {
259            if(file.exists()) return file.isFile();
260            Resource parent=file.getParentResource();
261            //try {
262                return parent.mkdirs() && file.createNewFile();
263            /*} catch (IOException e) {
264                return false;
265            }*/  
266        }
267        
268        /**
269         * has access checks if config object has access to given type
270         * @param config
271         * @param type
272         * @return has access
273         */
274        public static boolean hasAccess(Config config, int type) {
275            
276            boolean has=true;
277            if(config instanceof ConfigWeb) {
278                has=((ConfigWeb)config).getSecurityManager().getAccess(type)!=SecurityManager.VALUE_NO;
279            }
280            return has;
281        }
282    
283        /**
284         * loads log
285         * @param configServer 
286         * @param config 
287         * @param strLogger
288         * @param hasAccess 
289         * @param logLevel 
290         * @return log
291         * @throws IOException
292        */
293        public static LogAndSource getLogAndSource( ConfigServer configServer, Config config, String strLogger, boolean hasAccess, int logLevel) throws IOException {
294            if(logLevel==-1)logLevel=Log.LEVEL_ERROR;
295            boolean isCS=config instanceof ConfigServer;
296            if(!StringUtil.isEmpty(strLogger) && hasAccess && !"console".equalsIgnoreCase(strLogger)) {
297                    return ConfigWebUtil.getLogAndSource(config,strLogger,logLevel);
298            }
299            return new LogAndSourceImpl(LogConsole.getInstance(config,logLevel),strLogger);
300        }
301        private static LogAndSource getLogAndSource(Config config, String strLogger, int logLevel)  {
302            if(strLogger==null) return new LogAndSourceImpl(LogConsole.getInstance(config,logLevel),"");
303            
304            // File
305            strLogger=translateOldPath(strLogger);
306            Resource file=ConfigWebUtil.getFile(config, config.getConfigDir(),strLogger, ResourceUtil.TYPE_FILE);
307            if(file!=null && ResourceUtil.canRW(file)) {
308                try {
309                                    return new LogAndSourceImpl(new LogResource(file,logLevel,config.getResourceCharset()),strLogger);
310                            } catch (IOException e) {
311                                    SystemOut.printDate(config.getErrWriter(),e.getMessage());
312                            }
313            }
314            
315            if(file==null)SystemOut.printDate(config.getErrWriter(),"can't create logger from file ["+strLogger+"], invalid path");
316            else SystemOut.printDate(config.getErrWriter(),"can't create logger from file ["+strLogger+"], no write access");
317        
318            return new LogAndSourceImpl(LogConsole.getInstance(config,logLevel),strLogger);
319        
320        }
321    
322        public static String translateOldPath(String path) {
323            if(path==null) return path;
324            if(path.startsWith("/WEB-INF/railo/")) {
325                path="{web-root}"+path;
326            }
327            //print.ln(path);
328            return path;
329        }
330    
331            public static Object getIdMapping(Mapping m) {
332                    StringBuffer id=new StringBuffer(m.getVirtualLowerCase());
333            if(m.hasPhysical())id.append(m.getStrPhysical());
334            if(m.hasArchive())id.append(m.getStrPhysical());
335            return m.toString().toLowerCase();
336            }
337            public static void checkGeneralReadAccess(ConfigImpl config, String password) throws SecurityException {
338                    SecurityManager sm = config.getSecurityManager();
339            short access = sm.getAccess(SecurityManager.TYPE_ACCESS_READ);
340            if(config instanceof ConfigServer)access=SecurityManager.ACCESS_PROTECTED;
341            if(access==SecurityManager.ACCESS_PROTECTED) {
342                    checkPassword(config,"read",password);
343            }
344            else if(access==SecurityManager.ACCESS_CLOSE) {
345                    throw new SecurityException("can't access, read access is disabled");
346            }
347            }
348            
349            public static void checkGeneralWriteAccess(ConfigImpl config, String password) throws SecurityException {
350            SecurityManager sm = config.getSecurityManager();
351            short access = sm.getAccess(SecurityManager.TYPE_ACCESS_WRITE);
352            
353            if(config instanceof ConfigServer)access=SecurityManager.ACCESS_PROTECTED;
354            if(access==SecurityManager.ACCESS_PROTECTED) {
355                    checkPassword(config,"write",password);
356            }
357            else if(access==SecurityManager.ACCESS_CLOSE) {
358                    throw new SecurityException("can't access, write access is disabled");
359            }
360            }
361    
362        public static void checkPassword(ConfigImpl config, String type,String password) throws SecurityException {
363            if(!config.hasPassword())
364                throw new SecurityException("can't access, no password is defined");
365            //print.ln(config.getPassword()+".equalsIgnoreCase("+password+")");
366            if(!config.getPassword().equalsIgnoreCase(password)){
367                    if(StringUtil.isEmpty(password)){
368                            if(type==null)
369                                    throw new SecurityException("Access is protected",
370                                    "to access the configuration without a password, you need to change the access to [open] in the Server Administrator");
371                            throw new SecurityException(type +" access is protected",
372                                    "to access the configuration without a password, you need to change the "+type+" access to [open] in the Server Administrator");
373                    }
374                throw new SecurityException("No access, password is invalid");
375            }
376        }
377        
378        public static String createMD5FromResource(Resource resource) throws IOException {
379            InputStream is=null;
380            try{
381                    is=resource.getInputStream();   
382                    byte[] barr = IOUtil.toBytes(is);
383                    return MD5.getDigestAsString(barr);
384            }
385            finally{
386                    IOUtil.closeEL(is);
387            }
388        }
389        
390        
391    }