jicarilla-sandbox/platform/components/http/impl/src/java/org/jicarilla/io FilesystemImpl.java,1.5,1.6

Leo Simons <[email protected]>
Newsgroups gmane.comp.java.jicarilla.cvs
Message-ID <[email protected]>
Update of /cvsroot/jicarilla/jicarilla-sandbox/platform/components/http/impl/src/java/org/jicarilla/io
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20979/platform/components/http/impl/src/java/org/jicarilla/io

Modified Files:
	FilesystemImpl.java 
Log Message:
seperate plumbing material from the basic HTTP logic, and work on solidifying the I/O code.

Index: FilesystemImpl.java
===================================================================
RCS file: /cvsroot/jicarilla/jicarilla-sandbox/platform/components/http/impl/src/java/org/jicarilla/io/FilesystemImpl.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- FilesystemImpl.java	23 Mar 2004 13:37:50 -0000	1.5
+++ FilesystemImpl.java	31 Mar 2004 12:10:59 -0000	1.6
@@ -59,7 +59,7 @@
         final File root = new File( rootDirectory );
         setRootDirectory( root );
 
-        m_openFiles = new WeakHashMap();
+        setOpenFiles( new WeakHashMap() );
     }
 
     // ----------------------------------------------------------------------
@@ -72,10 +72,10 @@
 
     protected synchronized void setRootDirectory( final File root )
     {
-        Assert.assertNotNull( root );
-        Assert.assertTrue( root.exists() );
-        Assert.assertTrue( root.canRead() );
-        Assert.assertTrue( root.isDirectory() );
+        Assert.assertNotNull( "root argument may not be null", root );
+        Assert.assertTrue( "root must exist", root.exists() );
+        Assert.assertTrue( "root must be readable", root.canRead() );
+        Assert.assertTrue( "root must be a directory", root.isDirectory() );
 
         m_rootDirectory = root;
     }
@@ -87,42 +87,155 @@
 
     protected synchronized void setOpenFiles( final Map openFiles )
     {
+        Assert.assertNotNull( "openFiles argument may not be null",
+                openFiles );
         m_openFiles = openFiles;
     }
 
     // ----------------------------------------------------------------------
     //  Interface: Filesystem
     // ----------------------------------------------------------------------
-    public synchronized ReadableByteChannel getFile( final String relativePath )
+    public synchronized ReadableByteChannel getFile(
+            final String relativePath )
             throws FileNotFoundException
     {
-        final String path;
-        if( relativePath.charAt(0) != File.separatorChar )
-            path = m_rootDirectory.getAbsolutePath() + File.separator + relativePath;
+        final File file = getFileFromRelativePath( relativePath );
+        final FileChannel fileChannel = getFileChannel( file );
+        return fileChannel;
+    }
+
+    public synchronized void returnFile( final ReadableByteChannel channel )
+    {
+        if(! (channel instanceof FileChannel) )
+            return;
+
+        final FileChannel fileChannel = (FileChannel)channel;
+        returnChannel( fileChannel );
+    }
+
+    // ----------------------------------------------------------------------
+    //  Helper Methods
+    // ----------------------------------------------------------------------
+    /**
+     * Tries to make sure that the provided path lives somewhere inside 
+     * @link m_rootDirectory}.
+     * 
+     * @param absolutePath the path to check for location validity.
+     * @throws SecurityException if the file does not live inside
+     *     the root directory.
+     */ 
+    protected void checkPathIsAllowed( String absolutePath )
+    {
+        final String rootPath = getRootDirectory().getAbsolutePath();
+        final boolean startsWithRootPath = rootPath.equals(
+                absolutePath.substring(
+                        0, rootPath.length()
+                )
+        );
+        if( !startsWithRootPath )
+            throw new SecurityException(
+                    "Access denied to: " + absolutePath );
+    }
+
+    /**
+     * Transform a path relative to the root directory to an absolute path. 
+     * 
+     * @param relativePath the path to transform.
+     * @return an absolute path to the same location.
+     * @throws SecurityException if access to the file is denied.
+     */ 
+    protected String getFullPath( final String relativePath )
+    {
+        // handle optional '/' and '\'
+        String path;
+        if(     relativePath.charAt(0) != File.separatorChar &&
+                relativePath.charAt(0) != '/' &&
+                relativePath.charAt(0) != '\\' )
+            path = getRootDirectory().getAbsolutePath() + File.separator +
+                    relativePath;
         else
-            path = m_rootDirectory.getAbsolutePath() + relativePath;
+            path = getRootDirectory().getAbsolutePath() + relativePath;
+        
+        // convert '/' and '\'
+        path.replaceAll( "/", File.separator );
+        path.replaceAll( "\\\\", File.separator );
+        
+        // check against stuff like '../../../..'
+        checkPathIsAllowed( path );
+        
+        return path;
+    }
 
+    /**
+     * Transform a path relative to the root directory to a {@link File}. 
+     * 
+     * @param relativePath the path to transform.
+     * @return a <code>File</code> instance pointing to the specified path.
+     * @throws FileNotFoundException if the specified file cannot be found,
+     *    the provided path points to a directory or to a file from which
+     *    cannot be read.
+     * @throws SecurityException if access to the file is denied.
+     */ 
+    protected File getFileFromRelativePath( final String relativePath )
+            throws FileNotFoundException
+    {
+        final String path = getFullPath( relativePath );
         final File file = new File( path );
-        if( !file.exists() )
-            throw new FileNotFoundException(path);
-        Assert.assertTrue( file.canRead() );
-        Assert.assertFalse( file.isDirectory() );
 
+        if( !file.exists() || !file.canRead() || !file.isDirectory() )
+            throw new FileNotFoundException( path );
+
+        return file;
+    }
+    
+    /**
+     * Retrieve a {@link FileChannel} pointing to the provided file.
+     * 
+     * @param file the file to retrieve the associated <code>FileChannel</code>
+     *     for.
+     * @return the {@link FileChannel} pointing to the provided file.
+     * @throws FileNotFoundException if the specified file cannot be found,
+     *    the provided path points to a directory or to a file from which
+     *    cannot be read.
+     * @throws SecurityException if access to the file is denied.
+     */ 
+    protected FileChannel getFileChannel( final File file )
+            throws FileNotFoundException
+    {
         final FileInputStream fis = new FileInputStream( file );
-        final FileChannel fc = fis.getChannel();
-        getOpenFiles().put( fc, fis );
-        return fc;
+        final FileChannel fileChannel = fis.getChannel();
+        addOpenFile( fileChannel, fis );
+        return fileChannel;
     }
 
-    public synchronized void returnFile( final ReadableByteChannel channel )
+    /**
+     * Keep a reference to the provided {@link FileInputStream} around in order
+     * to be able to close it when it is fed to
+     * {@link #returnFile(ReadableByteChannel)}.
+     * 
+     * @param fc the channel associated with the stream.
+     * @param fis the stream to keep around.
+     */ 
+    protected void addOpenFile( final FileChannel fc,
+            final FileInputStream fis )
     {
-        if(! (channel instanceof FileChannel) )
-            return;
+        final FileChannelWrapper key = new FileChannelWrapper(fc);
+        getOpenFiles().put( key, fis );
+    }
 
-        final FileChannel fc = (FileChannel)channel;
-        if( getOpenFiles().containsKey( fc ) )
+    /**
+     * Remove the reference to the provided {@link FileInputStream} and close
+     * it if it existed before.
+     * 
+     * @param fc the channel associated with the stream.
+     */ 
+    protected void returnChannel( final FileChannel fc )
+    {
+        final FileChannelWrapper key = new FileChannelWrapper(fc);
+        if( getOpenFiles().containsKey( key ) )
         {
-            final FileInputStream fs = (FileInputStream)getOpenFiles().remove( fc );
+            final FileInputStream fs =
+                    (FileInputStream)getOpenFiles().remove( fc );
             try
             {
                 fs.close();
@@ -130,4 +243,18 @@
             catch( IOException e ) {}
         }
     }
+    
+    /**
+     * Helper class to make sure a channel is put into the cache every time
+     * one is requested, and no entries are overridden.
+     */ 
+    protected static class FileChannelWrapper
+    {
+        public FileChannel channel;
+
+        public FileChannelWrapper( FileChannel channel )
+        {
+            this.channel = channel;
+        }
+    }
 }



-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.