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 **/ 019/** 020 * Implements the CFML Function expandpath 021 */ 022package lucee.runtime.functions.system; 023 024import java.io.IOException; 025 026import lucee.commons.io.SystemUtil; 027import lucee.commons.io.res.Resource; 028import lucee.commons.io.res.ResourceProvider; 029import lucee.commons.io.res.util.ResourceUtil; 030import lucee.commons.lang.StringUtil; 031import lucee.runtime.PageContext; 032import lucee.runtime.PageContextImpl; 033import lucee.runtime.PageSource; 034import lucee.runtime.config.ConfigWeb; 035import lucee.runtime.config.ConfigWebImpl; 036import lucee.runtime.config.ConfigWebUtil; 037import lucee.runtime.exp.PageException; 038import lucee.runtime.ext.function.Function; 039import lucee.runtime.type.util.ArrayUtil; 040 041public final class ExpandPath implements Function { 042 043 private static final long serialVersionUID = 6192659914120397912L; 044 045 public static String call(PageContext pc , String relPath) throws PageException { 046 ConfigWeb config=pc.getConfig(); 047 relPath=prettifyPath(pc,relPath); 048 049 String contextPath = pc.getHttpServletRequest().getContextPath(); 050 if ( !StringUtil.isEmpty( contextPath ) && relPath.startsWith( contextPath ) ) { 051 boolean sws=StringUtil.startsWith(relPath, '/'); 052 relPath = relPath.substring( contextPath.length() ); 053 if(sws && !StringUtil.startsWith(relPath, '/')) 054 relPath="/"+relPath; 055 } 056 057 Resource res; 058 059 if(StringUtil.startsWith(relPath,'/')) { 060 061 062 PageContextImpl pci=(PageContextImpl) pc; 063 ConfigWebImpl cwi=(ConfigWebImpl) config; 064 PageSource[] sources = cwi.getPageSources(pci, pc.getApplicationContext().getMappings(), relPath, 065 false, pci.useSpecialMappings(), true); 066 067 if(!ArrayUtil.isEmpty(sources)) { 068 // first check for existing 069 for(int i=0;i<sources.length;i++){ 070 if(sources[i].exists()) { 071 return toReturnValue(relPath,sources[i].getResource()); 072 } 073 } 074 075 // no expand needed 076 if(!SystemUtil.isWindows() && !sources[0].exists()) { 077 res=pc.getConfig().getResource(relPath); 078 if(res.exists()) { 079 return toReturnValue(relPath,res); 080 } 081 } 082 for(int i=0;i<sources.length;i++){ 083 res=sources[i].getResource(); 084 if(res!=null) { 085 return toReturnValue(relPath,res); 086 } 087 } 088 } 089 090 // no expand needed 091 else if(!SystemUtil.isWindows()) { 092 res=pc.getConfig().getResource(relPath); 093 if(res.exists()) { 094 return toReturnValue(relPath,res); 095 } 096 } 097 098 099 //Resource[] reses = cwi.getPhysicalResources(pc,pc.getApplicationContext().getMappings(),relPath,false,pci.useSpecialMappings(),true); 100 101 } 102 relPath=ConfigWebUtil.replacePlaceholder(relPath, config); 103 res=pc.getConfig().getResource(relPath); 104 if(res.isAbsolute()) return toReturnValue(relPath,res); 105 106 res=ResourceUtil.getResource(pc,pc.getBasePageSource()); 107 if(!res.isDirectory())res=res.getParentResource(); 108 res = res.getRealResource(relPath); 109 return toReturnValue(relPath,res); 110 111 } 112 113 private static String toReturnValue(String relPath,Resource res) { 114 String path; 115 char pathChar='/'; 116 try { 117 path=res.getCanonicalPath(); 118 pathChar=ResourceUtil.FILE_SEPERATOR; 119 } catch (IOException e) { 120 path= res.getAbsolutePath(); 121 } 122 boolean pathEndsWithSep=StringUtil.endsWith(path,pathChar); 123 boolean realEndsWithSep=StringUtil.endsWith(relPath,'/'); 124 125 if(realEndsWithSep) { 126 if(!pathEndsWithSep)path=path+pathChar; 127 } 128 else if(pathEndsWithSep) { 129 path=path.substring(0,path.length()-1); 130 } 131 132 return path; 133 } 134 135 private static String prettifyPath(PageContext pc, String path) { 136 if(path==null) return null; 137 138 // UNC Path 139 if(path.startsWith("\\\\") && SystemUtil.isWindows()) { 140 path=path.substring(2); 141 path=path.replace('\\','/'); 142 return "//"+StringUtil.replace(path, "//", "/", false); 143 } 144 145 path=path.replace('\\','/'); 146 147 // virtual file system path 148 int index=path.indexOf("://"); 149 if(index!=-1) { 150 ResourceProvider[] providers = pc.getConfig().getResourceProviders(); 151 String scheme=path.substring(0,index).toLowerCase().trim(); 152 for(int i=0;i<providers.length;i++) { 153 if(scheme.equalsIgnoreCase(providers[i].getScheme())) 154 return scheme+"://"+StringUtil.replace(path.substring(index+3), "//", "/", false); 155 } 156 } 157 158 return StringUtil.replace(path, "//", "/", false); 159 // TODO /aaa/../bbb/ 160 } 161}