public static List < String > fixPath ( final String path ) throws ServletException { if ( path == null ) { return null ; } String decoded ; try { decoded = URLDecoder . decode ( path , "UTF8" ) ; } catch ( Throwable t ) { throw new ServletException ( "bad path: " + path ) ; } if ( decoded == null ) { return ( null ) ; } /** Make any backslashes into forward slashes. */ if ( decoded . indexOf ( ' ' ) >= 0 ) { decoded = decoded . replace ( ' ' , ' ' ) ; } /** Ensure a leading '/' */ if ( ! decoded . startsWith ( "/" ) ) { decoded = "/" + decoded ; } /** Remove all instances of '//'. */ while ( decoded . contains ( "//" ) ) { decoded = decoded . replaceAll ( "//" , "/" ) ; } /** Somewhere we may have /./ or /../ */ final StringTokenizer st = new StringTokenizer ( decoded , "/" ) ; ArrayList < String > al = new ArrayList < String > ( ) ; while ( st . hasMoreTokens ( ) ) { String s = st . nextToken ( ) ; if ( s . equals ( "." ) ) { // ignore } else if ( s . equals ( ".." ) ) { // Back up 1 if ( al . size ( ) == 0 ) { // back too far return null ; } al . remove ( al . size ( ) - 1 ) ; } else { al . add ( s ) ; } } return al ; }
Return a path broken into its elements after . and .. are removed . If the parameter path attempts to go above the root we return null .