001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.freemarker;
016    
017    import com.liferay.portal.kernel.util.GetterUtil;
018    import com.liferay.portal.kernel.util.StringPool;
019    import com.liferay.portal.util.ClassLoaderUtil;
020    import com.liferay.portal.util.PropsValues;
021    
022    import freemarker.core.Environment;
023    import freemarker.core.TemplateClassResolver;
024    
025    import freemarker.template.Template;
026    import freemarker.template.TemplateException;
027    import freemarker.template.utility.Execute;
028    import freemarker.template.utility.ObjectConstructor;
029    
030    /**
031     * @author Raymond Aug??
032     */
033    public class LiferayTemplateClassResolver implements TemplateClassResolver {
034    
035            @Override
036            public Class<?> resolve(
037                            String className, Environment environment, Template template)
038                    throws TemplateException {
039    
040                    if (className.equals(Execute.class.getName()) ||
041                            className.equals(ObjectConstructor.class.getName())) {
042    
043                            throw new TemplateException(
044                                    "Instantiating " + className + " is not allowed in the " +
045                                            "template for security reasons",
046                                    environment);
047                    }
048    
049                    String[] restrictedClassNames = GetterUtil.getStringValues(
050                            PropsValues.FREEMARKER_ENGINE_RESTRICTED_CLASSES);
051    
052                    for (String restrictedClassName : restrictedClassNames) {
053                            if (restrictedClassName.equals(StringPool.STAR)) {
054                                    throw new TemplateException(
055                                            "Instantiating " + className + " is not allowed in the " +
056                                                    "template for security reasons",
057                                            environment);
058                            }
059                            else if (restrictedClassName.endsWith(StringPool.STAR)) {
060                                    restrictedClassName = restrictedClassName.substring(
061                                            0, restrictedClassName.length() -1);
062    
063                                    if (className.startsWith(restrictedClassName)) {
064                                            throw new TemplateException(
065                                                    "Instantiating " + className + " is not allowed in " +
066                                                            "the template for security reasons",
067                                                    environment);
068                                    }
069                            }
070                            else if (className.equals(restrictedClassName)) {
071                                    throw new TemplateException(
072                                            "Instantiating " + className + " is not allowed in the " +
073                                                    "template for security reasons",
074                                            environment);
075                            }
076                    }
077    
078                    for (String restrictedPackageName :
079                                    PropsValues.FREEMARKER_ENGINE_RESTRICTED_PACKAGES) {
080    
081                            if (className.startsWith(restrictedPackageName)) {
082                                    throw new TemplateException(
083                                            "Instantiating " + className + " is not allowed in the " +
084                                                    "template for security reasons",
085                                            environment);
086                            }
087                    }
088    
089                    boolean allowed = false;
090    
091                    String[] allowedClassNames = GetterUtil.getStringValues(
092                            PropsValues.FREEMARKER_ENGINE_ALLOWED_CLASSES);
093    
094                    for (String allowedClassName : allowedClassNames) {
095                            if (allowedClassName.equals(StringPool.STAR)) {
096                                    allowed = true;
097                                    break;
098                            }
099                            else if (allowedClassName.endsWith(StringPool.STAR)) {
100                                    allowedClassName = allowedClassName.substring(
101                                                    0, allowedClassName.length() - 1);
102    
103                                    if (className.startsWith(allowedClassName)) {
104                                            allowed = true;
105                                            break;
106                                    }
107                            }
108                            else if (allowedClassName.equals(className)) {
109                                    allowed = true;
110                                    break;
111                            }
112                    }
113    
114                    if (allowed) {
115                            try {
116                                    return Class.forName(
117                                            className, true, ClassLoaderUtil.getContextClassLoader());
118                            }
119                            catch (Exception e) {
120                                    throw new TemplateException(e, environment);
121                            }
122                    }
123    
124                    throw new TemplateException(
125                            "Instantiating " + className + " is not allowed in the template " +
126                                    "for security reasons",
127                            environment);
128            }
129    
130    }