diff --git a/source/java/org/alfresco/repo/webdav/GetMethod.java b/source/java/org/alfresco/repo/webdav/GetMethod.java index 0a76debfd4..4467149f7a 100644 --- a/source/java/org/alfresco/repo/webdav/GetMethod.java +++ b/source/java/org/alfresco/repo/webdav/GetMethod.java @@ -318,7 +318,7 @@ public class GetMethod extends WebDAVMethod writer.write("\n"); writer.write("\n"); writer.write("\n"); writer.write("
Directory listing for "); - writer.write(getPath()); + writer.write(WebDAVHelper.encodeHTML(getPath())); writer.write("
"); @@ -331,7 +331,9 @@ public class GetMethod extends WebDAVMethod // Get the URL for the root path String rootURL = WebDAV.getURLForPath(m_request, getPath(), true); if (rootURL.endsWith(WebDAVHelper.PathSeperator) == false) + { rootURL = rootURL + WebDAVHelper.PathSeperator; + } // Start with a link to the parent folder so we can navigate back up, unless we are at the root level if (fileInfo.getNodeRef().equals(getRootNodeRef()) == false) @@ -370,9 +372,9 @@ public class GetMethod extends WebDAVMethod String fname = childNodeInfo.getName(); - writer.write(fname); + writer.write(WebDAVHelper.encodeURL(fname)); writer.write("\">"); - writer.write(fname); + writer.write(WebDAVHelper.encodeHTML(fname)); writer.write(""); writer.write(""); diff --git a/source/java/org/alfresco/repo/webdav/WebDAV.java b/source/java/org/alfresco/repo/webdav/WebDAV.java index d3b19976de..8324f21071 100644 --- a/source/java/org/alfresco/repo/webdav/WebDAV.java +++ b/source/java/org/alfresco/repo/webdav/WebDAV.java @@ -25,6 +25,7 @@ import java.util.Date; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; +import java.util.StringTokenizer; import javax.servlet.http.HttpServletRequest; @@ -405,28 +406,37 @@ public class WebDAV String servletPath = request.getServletPath(); int rootPos = urlStr.indexOf(servletPath); - if ( rootPos != -1) - urlStr.setLength(rootPos + servletPath.length()); - - if ( urlStr.charAt(urlStr.length() - 1) != PathSeperatorChar) - urlStr.append(PathSeperator); - - if ( path.equals(RootPath) == false) + if (rootPos != -1) { - if ( path.startsWith(PathSeperator)) - urlStr.append(path.substring(1)); - else - urlStr.append(path); + urlStr.setLength(rootPos + servletPath.length()); + } + + if (urlStr.charAt(urlStr.length() - 1) != PathSeperatorChar) + { + urlStr.append(PathSeperator); + } + + if (path.equals(RootPath) == false) + { + // split the path and URL encode each path element + for (StringTokenizer t = new StringTokenizer(path, PathSeperator); t.hasMoreTokens(); /**/) + { + urlStr.append( WebDAVHelper.encodeURL(t.nextToken()) ); + if (t.hasMoreTokens()) + { + urlStr.append(PathSeperator); + } + } } // If the URL is to a collection add a trailing slash - - if ( isCollection && urlStr.charAt( urlStr.length() - 1) != PathSeperatorChar) + if (isCollection && urlStr.charAt( urlStr.length() - 1) != PathSeperatorChar) + { urlStr.append( PathSeperator); - - // Return the encoded URL string - - return encodeURL( urlStr.toString()); + } + + // Return the URL string + return urlStr.toString(); } /** @@ -507,86 +517,6 @@ public class WebDAV return strNormalized; } - /** - * Encodes the given URL string - * - * @param string the String to convert - */ - public static String encodeURL(String string) - { - if (string == null) - { - return ""; - } - - StringBuilder sb = null; //create on demand - String enc; - char c; - for (int i = 0; i < string.length(); i++) - { - enc = null; - c = string.charAt(i); - switch (c) - { - case '"': enc = """; break; //" - case '&': enc = "&"; break; //& - case '<': enc = "<"; break; //< - case '>': enc = ">"; break; //> - - //german umlauts - case '\u00E4' : enc = "ä"; break; - case '\u00C4' : enc = "Ä"; break; - case '\u00F6' : enc = "ö"; break; - case '\u00D6' : enc = "Ö"; break; - case '\u00FC' : enc = "ü"; break; - case '\u00DC' : enc = "Ü"; break; - case '\u00DF' : enc = "ß"; break; - - //misc - //case 0x80: enc = "€"; break; sometimes euro symbol is ascii 128, should we suport it? - case '\u20AC': enc = "€"; break; - case '\u00AB': enc = "«"; break; - case '\u00BB': enc = "»"; break; - case '\u00A0': enc = " "; break; - - default: - if (((int)c) >= 0x80) - { - //encode all non basic latin characters - enc = "&#" + ((int)c) + ";"; - } - break; - } - - if (enc != null) - { - if (sb == null) - { - String soFar = string.substring(0, i); - sb = new StringBuilder(i + 8); - sb.append(soFar); - } - sb.append(enc); - } - else - { - if (sb != null) - { - sb.append(c); - } - } - } - - if (sb == null) - { - return string; - } - else - { - return sb.toString(); - } - } - /** * Make a unique lock token * diff --git a/source/java/org/alfresco/repo/webdav/WebDAVHelper.java b/source/java/org/alfresco/repo/webdav/WebDAVHelper.java index 4d69018675..6bd6bac7cd 100644 --- a/source/java/org/alfresco/repo/webdav/WebDAVHelper.java +++ b/source/java/org/alfresco/repo/webdav/WebDAVHelper.java @@ -16,6 +16,8 @@ */ package org.alfresco.repo.webdav; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -415,4 +417,133 @@ public class WebDAVHelper { return m_nullAttribs; } + + /** + * Encodes the given string to valid URL format + * + * @param s the String to convert + */ + public final static String encodeURL(String s) + { + try + { + return replace(URLEncoder.encode(s, "UTF-8"), "+", "%20"); + } + catch (UnsupportedEncodingException err) + { + throw new RuntimeException(err); + } + } + + /** + * Replace one string instance with another within the specified string + * + * @param str + * @param repl + * @param with + * + * @return replaced string + */ + public static String replace(String str, String repl, String with) + { + int lastindex = 0; + int pos = str.indexOf(repl); + + // If no replacement needed, return the original string + // and save StringBuffer allocation/char copying + if (pos < 0) + { + return str; + } + + int len = repl.length(); + int lendiff = with.length() - repl.length(); + StringBuilder out = new StringBuilder((lendiff <= 0) ? str.length() : (str.length() + (lendiff << 3))); + for (; pos >= 0; pos = str.indexOf(repl, lastindex = pos + len)) + { + out.append(str.substring(lastindex, pos)).append(with); + } + + return out.append(str.substring(lastindex, str.length())).toString(); + } + + /** + * Encodes the given string to valid HTML format + * + * @param string the String to convert + */ + public final static String encodeHTML(String string) + { + if (string == null) + { + return ""; + } + + StringBuilder sb = null; //create on demand + String enc; + char c; + for (int i = 0; i < string.length(); i++) + { + enc = null; + c = string.charAt(i); + switch (c) + { + case '"': enc = """; break; //" + case '&': enc = "&"; break; //& + case '<': enc = "<"; break; //< + case '>': enc = ">"; break; //> + + //german umlauts + case '\u00E4' : enc = "ä"; break; + case '\u00C4' : enc = "Ä"; break; + case '\u00F6' : enc = "ö"; break; + case '\u00D6' : enc = "Ö"; break; + case '\u00FC' : enc = "ü"; break; + case '\u00DC' : enc = "Ü"; break; + case '\u00DF' : enc = "ß"; break; + + //misc + //case 0x80: enc = "€"; break; sometimes euro symbol is ascii 128, should we suport it? + case '\u20AC': enc = "€"; break; + case '\u00AB': enc = "«"; break; + case '\u00BB': enc = "»"; break; + case '\u00A0': enc = " "; break; + + default: + if (((int)c) >= 0x80) + { + //encode all non basic latin characters + enc = "&#" + ((int)c) + ";"; + } + break; + } + + if (enc != null) + { + if (sb == null) + { + String soFar = string.substring(0, i); + sb = new StringBuilder(i + 8); + sb.append(soFar); + } + sb.append(enc); + } + else + { + if (sb != null) + { + sb.append(c); + } + } + } + + if (sb == null) + { + return string; + } + else + { + return sb.toString(); + } + } }