freemarker.cache.FileTemplateLoader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.apache.servicemix.bundles.freemarker
Show all versions of org.apache.servicemix.bundles.freemarker
This OSGi bundle wraps ${pkgArtifactId} ${pkgVersion} jar file.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package freemarker.cache;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import freemarker.log.Logger;
import freemarker.template.Configuration;
import freemarker.template.utility.SecurityUtilities;
import freemarker.template.utility.StringUtil;
/**
* A {@link TemplateLoader} that uses files inside a specified directory as the source of templates. By default it does
* security checks on the canonical path that will prevent it serving templates outside that specified
* directory. If you want symbolic links that point outside the template directory to work, you need to disable this
* feature by using {@link #FileTemplateLoader(File, boolean)} with {@code true} second argument, but before that, check
* the security implications there!
*/
public class FileTemplateLoader implements TemplateLoader {
/**
* By setting this Java system property to {@code true}, you can change the default of
* {@code #getEmulateCaseSensitiveFileSystem()}.
*/
public static String SYSTEM_PROPERTY_NAME_EMULATE_CASE_SENSITIVE_FILE_SYSTEM
= "org.freemarker.emulateCaseSensitiveFileSystem";
private static final boolean EMULATE_CASE_SENSITIVE_FILE_SYSTEM_DEFAULT;
static {
final String s = SecurityUtilities.getSystemProperty(SYSTEM_PROPERTY_NAME_EMULATE_CASE_SENSITIVE_FILE_SYSTEM,
"false");
boolean emuCaseSensFS;
try {
emuCaseSensFS = StringUtil.getYesNo(s);
} catch (Exception e) {
emuCaseSensFS = false;
}
EMULATE_CASE_SENSITIVE_FILE_SYSTEM_DEFAULT = emuCaseSensFS;
}
private static final int CASE_CHECH_CACHE_HARD_SIZE = 50;
private static final int CASE_CHECK_CACHE__SOFT_SIZE = 1000;
private static final boolean SEP_IS_SLASH = File.separatorChar == '/';
private static final Logger LOG = Logger.getLogger("freemarker.cache");
public final File baseDir;
private final String canonicalBasePath;
private boolean emulateCaseSensitiveFileSystem;
private MruCacheStorage correctCasePaths;
/**
* Creates a new file template cache that will use the current directory (the value of the system property
* user.dir
as the base directory for loading templates. It will not allow access to template files
* that are accessible through symlinks that point outside the base directory.
*
* @deprecated Relying on what the current directory is is a bad practice; use
* {@link FileTemplateLoader#FileTemplateLoader(File)} instead.
*/
@Deprecated
public FileTemplateLoader() throws IOException {
this(new File(SecurityUtilities.getSystemProperty("user.dir")));
}
/**
* Creates a new file template loader that will use the specified directory
* as the base directory for loading templates. It will not allow access to
* template files that are accessible through symlinks that point outside
* the base directory.
* @param baseDir the base directory for loading templates
*/
public FileTemplateLoader(final File baseDir) throws IOException {
this(baseDir, false);
}
/**
* Creates a new file template loader that will use the specified directory as the base directory for loading
* templates. See the parameters for allowing symlinks that point outside the base directory.
*
* @param baseDir
* the base directory for loading templates
*
* @param disableCanonicalPathCheck
* If {@code true}, it will not check if the file to be loaded is inside the {@code baseDir} or not,
* according the canonical paths of the {@code baseDir} and the file to load. Note that
* {@link Configuration#getTemplate(String)} and (its overloads) already prevents backing out from the
* template directory with paths like {@code /../../../etc/password}, however, that can be circumvented
* with symbolic links or other file system features. If you really want to use symbolic links that point
* outside the {@code baseDir}, set this parameter to {@code true}, but then be very careful with
* template paths that are supplied by the visitor or an external system.
*/
public FileTemplateLoader(final File baseDir, final boolean disableCanonicalPathCheck) throws IOException {
try {
Object[] retval = AccessController.doPrivileged(new PrivilegedExceptionAction