Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2014 Attila Szegedi, Daniel Dekany, Jonathan Revusky
   * 
   * Licensed 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.core;
 
 import java.util.List;
 import java.util.Set;
 
A TemplateClassResolver that resolves only the classes whose name was specified in the constructor.
 
 public class OptInTemplateClassResolver implements TemplateClassResolver {
     
     private final Set/*<String>*/ allowedClasses;
     private final List/*<String>*/ trustedTemplatePrefixes;
     private final Set/*<String>*/ trustedTemplateNames;
    
    
Creates a new instance.

Parameters:
allowedClasses the java.util.Set of java.lang.String-s that contains the full-qualified names of the allowed classes. Can be null (means not class is allowed).
trustedTemplates the java.util.List of java.lang.String-s that contains template names (i.e., template root directory relative paths) and prefix patterns (like "include/*") of templates for which TemplateClassResolver.SAFER_RESOLVER will be used (which is not as safe as OptInTemplateClassResolver). The list items need not start with "/" (if they are, it will be removed). List items ending with "*" are treated as prefixes (i.e. "foo*" matches "foobar", "foo/bar/baaz", "foowhatever/bar/baaz", etc.). The "*" has no special meaning anywhere else. The matched template name is the name (template root directory relative path) of the template that directly (lexically) contains the operation (like ?new) that wants to get the class. Thus, if a trusted template includes a non-trusted template, the allowedClasses restriction will apply in the included template. This parameter can be null (means no trusted templates).
 
     public OptInTemplateClassResolver(
             Set allowedClassesList trustedTemplates) {
         this. = allowedClasses != null ? allowedClasses : .;
         if (trustedTemplates != null) {
              = new HashSet();
              = new ArrayList();
             
             Iterator it = trustedTemplates.iterator();
             while (it.hasNext()) {
                 String li = (Stringit.next();
                 if (li.startsWith("/")) li = li.substring(1);
                 if (li.endsWith("*")) {
                     .add(li.substring(0, li.length() - 1));
                 } else {
                     .add(li);
                 }
             }
         } else {
              = .;
              = .;
         }
     }
 
     public Class resolve(String classNameEnvironment envTemplate template)
     throws TemplateException {
         String templateName = safeGetTemplateName(template);
         
         if (templateName != null
                 && (.contains(templateName)
                         || hasMatchingPrefix(templateName))) {
             return ..resolve(classNameenvtemplate);
         } else {
             if (!.contains(className)) {
                 throw new _MiscTemplateException(envnew Object[] {
                         "Instantiating "className" is not allowed in the template for security reasons. (If you "
                        + "run into this problem when using ?new in a template, you may want to check the \"",
                        .,
                        "\" setting in the FreeMarker configuration.)" });
            } else {
                try {
                    return ClassUtil.forName(className);
                } catch (ClassNotFoundException e) {
                    throw new _MiscTemplateException(eenv);
                }
            }
        }
    }

    
Extract the template name from the template object which will be matched against the trusted template names and pattern.
    protected String safeGetTemplateName(Template template) {
        if (template == nullreturn null;
        
        String name = template.getName();
        if (name == nullreturn null;
        // Detect exploits, return null if one is suspected:
        String decodedName = name;
        if (decodedName.indexOf('%') != -1) {
            decodedName = StringUtil.replace(decodedName"%2e""."falsefalse);
            decodedName = StringUtil.replace(decodedName"%2E""."falsefalse);
            decodedName = StringUtil.replace(decodedName"%2f""/"falsefalse);
            decodedName = StringUtil.replace(decodedName"%2F""/"falsefalse);
            decodedName = StringUtil.replace(decodedName"%5c""\\"falsefalse);
            decodedName = StringUtil.replace(decodedName"%5C""\\"falsefalse);
        }
        int dotDotIdx = decodedName.indexOf("..");
        if (dotDotIdx != -1) {
            int before = dotDotIdx - 1 >= 0 ? decodedName.charAt(dotDotIdx - 1) : -1;
            int after = dotDotIdx + 2 < decodedName.length() ? decodedName.charAt(dotDotIdx + 2) : -1;
            if ((before == -1 || before == '/' || before == '\\')
                    && (after == -1 || after == '/' || after == '\\')) {
                return null;
            }
        }
        
        return name.startsWith("/") ? name.substring(1) : name;
    }
    private boolean hasMatchingPrefix(String name) {
        for (int i = 0; i < .size(); i++) {
            String prefix = (String.get(i);
            if (name.startsWith(prefix)) return true;
        }
        return false;
    }
New to GrepCode? Check out our FAQ X