Skip to content

Commit 8d33a71

Browse files
committed
Bugzilla #27612
Fix for catPath not handling Windows-style path separators. Submitted by: Maarten Coene <Maarten.Coene.at.qmedit.com> git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/io/trunk@140541 13f79535-47bb-0310-9956-ffa450edef68
1 parent b13ad1c commit 8d33a71

2 files changed

Lines changed: 44 additions & 13 deletions

File tree

src/java/org/apache/commons/io/FilenameUtils.java

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
* @author <a href="mailto:jefft@apache.org">Jeff Turner</a>
3939
* @author Matthew Hawthorne
4040
* @author <a href="mailto:jeremias@apache.org">Jeremias Maerki</a>
41-
* @version $Id: FilenameUtils.java,v 1.7 2004/02/23 04:35:59 bayard Exp $
41+
* @version $Id: FilenameUtils.java,v 1.8 2004/03/12 21:58:59 jeremias Exp $
4242
*/
4343
public class FilenameUtils {
4444

@@ -263,38 +263,61 @@ public static String normalize( String path) {
263263
}
264264

265265
/**
266-
* Will concatenate 2 paths. Paths with <code>..</code> will be
267-
* properly handled.
268-
* <p>Eg.,<br />
266+
* Will concatenate 2 paths. Paths with <code>..</code> will be
267+
* properly handled. The path separator between the 2 paths is the
268+
* system default path separator.
269+
*
270+
* <p>Eg. on UNIX,<br />
269271
* <code>/a/b/c</code> + <code>d</code> = <code>/a/b/d</code><br />
270272
* <code>/a/b/c</code> + <code>../d</code> = <code>/a/d</code><br />
271273
* </p>
272274
*
275+
* <p>Eg. on Microsoft Windows,<br />
276+
* <code>C:\a\b\c</code> + <code>d</code> = <code>C:\a\b\d</code><br />
277+
* <code>C:\a\b\c</code> + <code>..\d</code> = <code>C:\a\d</code><br />
278+
* <code>/a/b/c</code> + <code>d</code> = <code>/a/b\d</code><br />
279+
* </p>
280+
*
273281
* Thieved from Tomcat sources...
274282
*
283+
* @param lookupPath the base path to attach to
284+
* @param path path the second path to attach to the first
275285
* @return The concatenated paths, or null if error occurs
276286
*/
277287
public static String catPath( String lookupPath, String path) {
278288
// Cut off the last slash and everything beyond
279-
int index = lookupPath.lastIndexOf("/");
289+
int index = indexOfLastPathSeparator(lookupPath);
280290
String lookup = lookupPath.substring(0, index);
281291
String pth = path;
282292

283293
// Deal with .. by chopping dirs off the lookup path
284-
while (pth.startsWith("../")) {
294+
while (pth.startsWith("../") || pth.startsWith("..\\")) {
285295
if (lookup.length() > 0) {
286-
index = lookup.lastIndexOf("/");
296+
index = indexOfLastPathSeparator(lookup);
287297
lookup = lookup.substring(0, index);
288298
} else {
289299
// More ..'s than dirs, return null
290300
return null;
291301
}
292302

293-
index = pth.indexOf("../") + 3;
294-
pth = pth.substring(index);
303+
pth = pth.substring(3);
295304
}
296305

297-
return new StringBuffer(lookup).append("/").append(pth).toString();
306+
return new StringBuffer(lookup).append(File.separator).append(pth).toString();
307+
}
308+
309+
/**
310+
* Return the index of the last 'path separator' character. The 'path separator'
311+
* character is '/' for UNIX systems and '\' for Microsoft Windows systems.
312+
*
313+
* @param path The path to find the last path separator in
314+
* @return The index of the last 'path separator' character, or -1 if there
315+
* is no such character.
316+
*/
317+
public static int indexOfLastPathSeparator(String path) {
318+
int lastUnixPos = path.lastIndexOf('/');
319+
int lastWindowsPos = path.lastIndexOf('\\');
320+
return Math.max(lastUnixPos, lastWindowsPos);
298321
}
299322

300323
/**

src/test/org/apache/commons/io/FilenameUtilsTestCase.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
*
3030
* @author Peter Donald
3131
* @author Matthew Hawthorne
32-
* @version $Id: FilenameUtilsTestCase.java,v 1.6 2004/03/12 21:44:47 jeremias Exp $
32+
* @version $Id: FilenameUtilsTestCase.java,v 1.7 2004/03/12 21:59:19 jeremias Exp $
3333
* @see FilenameUtils
3434
*/
3535
public class FilenameUtilsTestCase extends FileBasedTestCase {
@@ -107,8 +107,16 @@ public void testCatPath() {
107107
// Is this acceptable?
108108
//assertEquals("", FilenameUtils.catPath("a", "b"));
109109

110-
assertEquals("/a/c", FilenameUtils.catPath("/a/b", "c"));
111-
assertEquals("/a/d", FilenameUtils.catPath("/a/b/c", "../d"));
110+
assertEquals("/a" + File.separator + "c", FilenameUtils.catPath("/a/b", "c"));
111+
assertEquals("/a" + File.separator + "d", FilenameUtils.catPath("/a/b/c", "../d"));
112+
assertEquals("C:\\a" + File.separator + "c", FilenameUtils.catPath("C:\\a\\b", "c"));
113+
assertEquals("C:\\a" + File.separator + "d", FilenameUtils.catPath("C:\\a\\b\\c", "../d"));
114+
}
115+
116+
public void testIndexOfLastPathSeparator() {
117+
assertEquals(-1, FilenameUtils.indexOfLastPathSeparator("noseperator.inthispath"));
118+
assertEquals(3, FilenameUtils.indexOfLastPathSeparator("a/b/c"));
119+
assertEquals(3, FilenameUtils.indexOfLastPathSeparator("a\\b\\c"));
112120
}
113121

114122
// resolveFile

0 commit comments

Comments
 (0)