/**
*
* Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
**/
/**
* Implements the CFML Function expandpath
*/
package lucee.runtime.functions.system;
import java.io.IOException;
import lucee.commons.io.SystemUtil;
import lucee.commons.io.res.Resource;
import lucee.commons.io.res.ResourceProvider;
import lucee.commons.io.res.util.ResourceUtil;
import lucee.commons.lang.StringUtil;
import lucee.runtime.PageContext;
import lucee.runtime.PageContextImpl;
import lucee.runtime.PageSource;
import lucee.runtime.config.ConfigWeb;
import lucee.runtime.config.ConfigWebImpl;
import lucee.runtime.config.ConfigWebUtil;
import lucee.runtime.exp.PageException;
import lucee.runtime.ext.function.Function;
import lucee.runtime.net.http.ReqRspUtil;
import lucee.runtime.type.util.ArrayUtil;
public final class ExpandPath implements Function {
private static final long serialVersionUID = 6192659914120397912L;
public static String call(PageContext pc , String relPath) throws PageException {
ConfigWeb config=pc.getConfig();
relPath=prettifyPath(pc,relPath);
String contextPath = pc.getHttpServletRequest().getContextPath();
if ( !StringUtil.isEmpty( contextPath ) && relPath.startsWith( contextPath ) ) {
boolean sws=StringUtil.startsWith(relPath, '/');
relPath = relPath.substring( contextPath.length() );
if(sws && !StringUtil.startsWith(relPath, '/'))
relPath="/"+relPath;
}
Resource res;
if(StringUtil.startsWith(relPath,'/')) {
PageContextImpl pci=(PageContextImpl) pc;
ConfigWebImpl cwi=(ConfigWebImpl) config;
PageSource[] sources = cwi.getPageSources(pci, pc.getApplicationContext().getMappings(), relPath,
false, pci.useSpecialMappings(), true);
if(!ArrayUtil.isEmpty(sources)) {
// first check for existing
for(int i=0;i<sources.length;i++){
if(sources[i].exists()) {
return toReturnValue(relPath,sources[i].getResource());
}
}
// no expand needed
if(!SystemUtil.isWindows() && !sources[0].exists()) {
res=pc.getConfig().getResource(relPath);
if(res.exists()) {
return toReturnValue(relPath,res);
}
}
for(int i=0;i<sources.length;i++){
res=sources[i].getResource();
if(res!=null) {
return toReturnValue(relPath,res);
}
}
}
// no expand needed
else if(!SystemUtil.isWindows()) {
res=pc.getConfig().getResource(relPath);
if(res.exists()) {
return toReturnValue(relPath,res);
}
}
//Resource[] reses = cwi.getPhysicalResources(pc,pc.getApplicationContext().getMappings(),realPath,false,pci.useSpecialMappings(),true);
}
relPath=ConfigWebUtil.replacePlaceholder(relPath, config);
res=pc.getConfig().getResource(relPath);
if(res.isAbsolute()) return toReturnValue(relPath,res);
PageSource ps = pc.getBasePageSource();
res=ps==null?
ResourceUtil.getCanonicalResourceEL(ResourceUtil.toResourceExisting(pc.getConfig(), ReqRspUtil.getRootPath(pc.getServletContext()))):
ResourceUtil.getResource(pc,ps);
if(!res.isDirectory())res=res.getParentResource();
res = res.getRealResource(relPath);
return toReturnValue(relPath,res);
}
private static String toReturnValue(String realPath,Resource res) {
String path;
char pathChar='/';
try {
path=res.getCanonicalPath();
pathChar=ResourceUtil.FILE_SEPERATOR;
} catch (IOException e) {
path= res.getAbsolutePath();
}
boolean pathEndsWithSep=StringUtil.endsWith(path,pathChar);
boolean realEndsWithSep=StringUtil.endsWith(realPath,'/');
if(realEndsWithSep) {
if(!pathEndsWithSep)path=path+pathChar;
}
else if(pathEndsWithSep) {
path=path.substring(0,path.length()-1);
}
return path;
}
private static String prettifyPath(PageContext pc, String path) {
if(path==null) return null;
// UNC Path
if(path.startsWith("\\\\") && SystemUtil.isWindows()) {
path=path.substring(2);
path=path.replace('\\','/');
return "//"+StringUtil.replace(path, "//", "/", false);
}
path=path.replace('\\','/');
// virtual file system path
int index=path.indexOf("://");
if(index!=-1) {
ResourceProvider[] providers = pc.getConfig().getResourceProviders();
String scheme=path.substring(0,index).toLowerCase().trim();
for(int i=0;i<providers.length;i++) {
if(scheme.equalsIgnoreCase(providers[i].getScheme()))
return scheme+"://"+StringUtil.replace(path.substring(index+3), "//", "/", false);
}
}
return StringUtil.replace(path, "//", "/", false);
// TODO /aaa/../bbb/
}
}