velocity-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jonathan Revusky <jrevu...@terra.es>
Subject Re: template encodings
Date Tue, 17 Jul 2001 00:27:07 GMT
"Geir Magnusson Jr." wrote:
> 
> Why didn't you use the ClasspathResourceLoader or the jar resource
> loader?

Well, I wanted to have my own code with absolute control. I've received
a couple of messages saying how easy it was. So I thought you were
encouraging me to do it.

I already knew that it was easy! I wrote this code a few days ago.

Jonathan

> 
> geir
> 
> Jonathan Revusky wrote:
> >
> > Jon Stevens wrote:
> > >
> > > on 7/15/01 5:09 PM, "Jonathan Revusky" <jrevusky@terra.es> wrote:
> > >
> > > > Somebody else pointed out that if you
> > > > specifically give an absolute location for the template file, it doesn't
> > > > work, i.e. some naive user who tries:
> > > > getTemplate("C:\\mytemplates\\mytemplate.html"). Well, that's basically
> > > > a bug. The default code should have the smarts that if you give it an
> > > > absolute path AND the file is there and readable, it should use it. To
> > > > have any other behavior is to willfully waste people's time.
> > >
> > > No, it is a security hole.
> > >
> > > You don't want some random user to be able to access something like
> > > /etc/passwd or /etc/shadow.
> >
> > Could you explain the mechanism by which a random user would access
> > /etc/passwd because I load a template file from an absolute path?
> >
> > >
> > > Setting a base template path is necessary. Then everything to access the
> > > file is relative to that path and you don't have to worry about people
> > > randomly reading files from that path.
> > >
> > > Go read the bugtraq archives. You will see literally hundreds of security
> > > holes as a result of what you describe.
> > >
> > > This is a very common mistake by newbie software engineers.
> > >
> > > Lastly, it is entirely possible within Velocity for you to come up with your
> > > own ResourceLoader. So, if you don't like the one that comes with Velocity,
> > > then make your own!
> >
> > I already did. Though I am advocating the position of a newbie user, *I*
> > am not at all helpless in this regard. The code below is in the version
> > of Niggle I put up today. It seems fairly reasonable to me. Note that a
> > template is only loaded from an absolute location if the application
> > programmer specifies an absolute location. I encourage people to locate
> > their templates relative to the servlet context classpath.
> >
> > /*
> > Bridge Code to use Velocity template engine with Niggle
> > Copyright (c) 2001, Jonathan Revusky
> > All rights reserved.
> >
> > Redistribution and use in source and binary forms, with or without
> > modification, are permitted provided that the following conditions
> > are met:
> >
> > Redistributions of source code must retain the above copyright notice,
> > this list of conditions and the following disclaimer.
> >
> > Redistributions in binary form must reproduce the above copyright
> > notice,
> > this list of conditions and the following disclaimer in the
> > documentation
> > and/or other materials provided with the distribution.
> >
> > The name of Jonathan Revusky may not be used to endorse or promote
> > products derived from this software without specific prior written
> > permission.
> >
> > THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> > ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> > LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
> > FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> > COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
> > INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> > (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
> > SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> > HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
> > STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
> > IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> > POSSIBILITY OF SUCH DAMAGE.
> > */
> >
> > package com.revusky.niggle.templates.velocityimpl;
> >
> > import org.apache.velocity.exception.ResourceNotFoundException;
> > import org.apache.velocity.runtime.resource.loader.ResourceLoader;
> > import org.apache.velocity.runtime.resource.Resource;
> > import org.apache.commons.collections.ExtendedProperties;
> > import com.revusky.oreo.util.*;
> > import java.io.*;
> > import java.util.*;
> > import java.net.URL;
> >
> > public class CustomResourceLoader extends ResourceLoader {
> >
> >     static private ClassLoader classLoader;
> >     static private String searchPath;
> >
> >     static public void setClassLoader(ClassLoader classLoader) {
> >         CustomResourceLoader.classLoader = classLoader;
> >     }
> >
> >     static public void setSearchPath(String searchPath) {
> >         CustomResourceLoader.searchPath = searchPath;
> >     }
> >
> >     public void init(ExtendedProperties props) {
> >         Logger.log("Niggle custom resource loader for Velocity :
> > initialized.", Logger.LOG_INFO);
> >     }
> >
> >     public InputStream getResourceStream(String name)
> >     throws ResourceNotFoundException {
> >         try {
> >             return findResource(name);
> >         } catch (IOException ioe) {
> >         }
> >         throw new ResourceNotFoundException("Template " + name + " not
> > found");
> >     }
> >
> >     private InputStream findResource(String name) throws IOException {
> >         InputStream is = findAbsolute(name);
> >         if (is == null) {
> >             is = findOnSearchPath(name);
> >         }
> >         if (is == null) {
> >             is = findOnClassPath(name);
> >         }
> >         return is;
> >     }
> >
> >     private InputStream findAbsolute(String name) throws IOException {
> >         File f = new File(name);
> >         if (f.isAbsolute() && f.canRead()) {
> >             fileCache.put(name, f);
> >             lastModifiedCache.put(name, new Long(f.lastModified()));
> >             return new FileInputStream(f);
> >         }
> >         else
> >             return null;
> >     }
> >
> >     private InputStream findOnSearchPath(String name) throws IOException
> > {
> >         if (searchPath != null) {
> >             StringTokenizer st = new StringTokenizer(searchPath,
> > File.pathSeparator);
> >             while (st.hasMoreTokens()) {
> >                 String path = st.nextToken();
> >                 if (path.endsWith("/") || path.endsWith("\\")) {
> >                     path = path.substring(0, path.length() -1);
> >                 }
> >                 String filename = path + "/" + name;
> >                 InputStream is = findAbsolute(filename);
> >                 if (is == null) {
> >                     is = findOnClassPath(filename);
> >                 }
> >                 if (is != null) {
> >                     return is;
> >                 }
> >             }
> >         }
> >         return null;
> >     }
> >
> >     private InputStream findOnClassPath(String name) throws IOException
> > {
> >         URL url = classLoader.getResource(name);
> >         if (url == null) {
> >             url = ClassLoader.getSystemResource(name);
> >         }
> >         if (url == null) {
> >             return null;
> >         }
> >         String filename = url.getFile();
> >         if (filename.startsWith("file:")) {
> >             filename = filename.substring(5);
> >         }
> >         File f = new File(filename);
> >         if (f.exists()) {
> >             fileCache.put(name, f);
> >             lastModifiedCache.put(name, new Long(f.lastModified()));
> >         }
> >         else
> >             fileCache.put(name, null);
> >         return url.openStream();
> >     }
> >
> >     public boolean isSourceModified(Resource res) {
> >         String name = res.getName();
> >         if (fileCache.containsKey(name)) {
> >             File f = (File) fileCache.get(name);
> >             if (f == null) {
> >                 return false;
> >             }
> >             else {
> >                 long l = f.lastModified();
> >                 Long L = (Long) lastModifiedCache.get(name);
> >                 return (L!=null) && (L.longValue() < l);
> >             }
> >         }
> >         return false;
> >     }
> >
> >     public long getLastModified(Resource res) {
> >         String name = res.getName();
> >         Long L = (Long) lastModifiedCache.get(name);
> >         if (L!= null) {
> >             return L.longValue();
> >         }
> >         return 0L;
> >     }
> >
> >     private Map fileCache = Collections.synchronizedMap(new HashMap());
> >     private Map lastModifiedCache = Collections.synchronizedMap(new
> > HashMap());
> > }
>

Mime
View raw message