You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by do...@apache.org on 2002/08/31 05:54:10 UTC
cvs commit: jakarta-avalon-excalibur/io/src/java/org/apache/avalon/excalibur/io FileUtil.java
donaldp 2002/08/30 20:54:10
Modified: io/src/java/org/apache/avalon/excalibur/io FileUtil.java
Log:
Fixed up the normalize method so that it actually works in more circumstances.
Submitted By: "Nicolas Leclerc" <nl...@novadeck.com>
Revision Changes Path
1.31 +122 -38 jakarta-avalon-excalibur/io/src/java/org/apache/avalon/excalibur/io/FileUtil.java
Index: FileUtil.java
===================================================================
RCS file: /home/cvs/jakarta-avalon-excalibur/io/src/java/org/apache/avalon/excalibur/io/FileUtil.java,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -r1.30 -r1.31
--- FileUtil.java 7 Aug 2002 05:44:02 -0000 1.30
+++ FileUtil.java 31 Aug 2002 03:54:10 -0000 1.31
@@ -433,10 +433,21 @@
}
/**
- * Normalize a path.
- * Eliminates "/../" and "/./" in a string. Returns <code>null</code> if the ..'s went past the
- * root.
- * Eg:
+ * Normalize a path. That means:
+ * <ul>
+ * <li>changes to unix style if under windows</li>
+ * <li>eliminates "/../" and "/./"</li>
+ * <li>if path is absolute (starts with '/') and there are
+ * too many occurences of "../" (would then have some kind
+ * of 'negative' path) returns null.</li>
+ * <li>If path is relative, the exceeding ../ are kept at
+ * the begining of the path.</li>
+ * </ul>
+ * <br><br>
+ *
+ * <b>Note:</b> note that this method has been tested with unix and windows only.
+ *
+ * <p>Eg:</p>
* <pre>
* /foo// --> /foo/
* /foo/./ --> /foo/
@@ -447,47 +458,122 @@
* /../ --> null
* </pre>
*
- * @param path the path to normalize
- * @return the normalized String, or <code>null</code> if too many ..'s.
+ * @param path the path to be normalized.
+ * @return the normalized path or null.
+ * @throws NullPointerException if path is null.
*/
- public static String normalize( final String path )
+ public static final String normalize( String path )
{
- String normalized = path;
- // Resolve occurrences of "//" in the normalized path
- while( true )
+ if( path.length() < 2 )
+ return path;
+
+ StringBuffer buff = new StringBuffer( path );
+
+ int length = path.length();
+
+ // this whole prefix thing is for windows compatibility only.
+ String prefix = null;
+
+ if( length > 2 && buff.charAt( 1 ) == ':' )
{
- int index = normalized.indexOf( "//" );
- if( index < 0 )
- break;
- normalized = normalized.substring( 0, index ) +
- normalized.substring( index + 1 );
+ prefix = path.substring( 0, 2 );
+ buff.delete( 0, 2 );
+ path = path.substring( 2 );
+ length -= 2;
}
- // Resolve occurrences of "/./" in the normalized path
- while( true )
+ boolean startsWithSlash = length > 0 && (buff.charAt( 0 ) == '/' || buff.charAt( 0 ) == '\\');
+
+ boolean expStart = true;
+ int ptCount = 0;
+ int lastSlash = length + 1;
+ int upLevel = 0;
+
+ for( int i = length - 1; i >= 0; i-- )
+ switch( path.charAt( i ) )
+ {
+ case '\\':
+ buff.setCharAt( i, '/' );
+ case '/':
+ if( lastSlash == i + 1 )
+ buff.deleteCharAt( i );
+
+ switch( ptCount )
+ {
+ case 1:
+ buff.delete( i, lastSlash );
+ break;
+
+ case 2:
+ upLevel++;
+ break;
+
+ default:
+ if( upLevel > 0 && lastSlash != i + 1 )
+ {
+ buff.delete( i, lastSlash + 3 );
+ upLevel--;
+ }
+ break;
+ }
+
+ ptCount = 0;
+ expStart = true;
+ lastSlash = i;
+ break;
+
+ case '.':
+ if( expStart )
+ {
+ ptCount++;
+ }
+ break;
+
+ default:
+ ptCount = 0;
+ expStart = false;
+ break;
+ }
+
+ switch( ptCount )
{
- int index = normalized.indexOf( "/./" );
- if( index < 0 )
+ case 1:
+ buff.delete( 0, lastSlash );
break;
- normalized = normalized.substring( 0, index ) +
- normalized.substring( index + 2 );
- }
- // Resolve occurrences of "/../" in the normalized path
- while( true )
- {
- int index = normalized.indexOf( "/../" );
- if( index < 0 )
+ case 2:
+ break;
+
+ default:
+ if( upLevel > 0 )
+ {
+ if( startsWithSlash )
+ return null;
+ else
+ upLevel = 1;
+ }
+
+ while( upLevel > 0 )
+ {
+ buff.delete( 0, lastSlash + 3 );
+ upLevel--;
+ }
break;
- if( index == 0 )
- return null; // Trying to go outside our context
- int index2 = normalized.lastIndexOf( '/', index - 1 );
- normalized = normalized.substring( 0, index2 ) +
- normalized.substring( index + 3 );
}
- // Return the normalized path that we have completed
- return normalized;
+ length = buff.length();
+ boolean isLengthNull = length == 0;
+ char firstChar = isLengthNull?(char)0:buff.charAt( 0 );
+
+ if( !startsWithSlash && !isLengthNull && firstChar == '/' )
+ buff.deleteCharAt( 0 );
+ else if( startsWithSlash && (isLengthNull || (!isLengthNull && firstChar != '/')) )
+ buff.insert( 0, '/' );
+
+ if( prefix != null )
+ buff.insert( 0, prefix );
+
+ return buff.toString();
}
/**
@@ -597,7 +683,7 @@
filenm = sb.toString();
//must be relative
- File file = ( new File( baseFile, filenm ) ).getAbsoluteFile();
+ File file = (new File( baseFile, filenm )).getAbsoluteFile();
try
{
@@ -712,7 +798,6 @@
}
}
-
/**
* Make a directory. If there already exists a file with specified name or
* the directory is unable to be created then an exception is thrown.
@@ -865,5 +950,4 @@
return size;
}
-
}
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>