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 }