/*
* ====================================================================
* Copyright (c) 2004-2008 TMate Software Ltd. All rights reserved.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://svnkit.com/license.html.
* If newer versions of this license are posted there, you may use a
* newer version instead, at your option.
* ====================================================================
*/
package org.tmatesoft.svn.core.internal.server.dav;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.logging.Level;
import javax.servlet.http.HttpServletResponse;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.internal.io.dav.DAVElement;
import org.tmatesoft.svn.core.internal.util.SVNEncodingUtil;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.util.SVNXMLUtil;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.util.SVNLogType;
/**
* @author TMate Software Ltd.
* @version 1.2.0
*/
public class DAVPathUtil {
private static final String SLASH = "/";
public static String dropLeadingSlash(String uri) {
if (uri == null) {
return "";
}
return uri.startsWith(SLASH) ? uri.substring(SLASH.length()) : uri;
}
public static String addLeadingSlash(String uri) {
if (uri == null) {
return SLASH;
}
return uri.startsWith(SLASH) ? uri : SLASH + uri;
}
public static String dropTraillingSlash(String uri) {
if (uri == null) {
return "";
}
return uri.endsWith(SLASH) ? uri.substring(0, uri.length() - SLASH.length()) : uri;
}
public static String addTrailingSlash(String uri) {
if (uri == null) {
return SLASH;
}
return uri.endsWith(SLASH) ? uri : uri + SLASH;
}
public static String head(String uri) {
uri = dropLeadingSlash(uri);
int slashIndex = uri.indexOf(SLASH);
if (slashIndex == -1) {
return uri;
}
return uri.substring(0, slashIndex);
}
public static String removeHead(String uri, boolean doStandardize) {
uri = dropLeadingSlash(uri);
int headLength = head(uri).length();
return doStandardize ? standardize(uri.substring(headLength)) : uri.substring(headLength);
}
public static String tail(String uri) {
uri = dropTraillingSlash(uri);
int lastSlashIndex = uri.lastIndexOf(SLASH);
if (lastSlashIndex == -1) {
return uri;
}
return uri.substring(lastSlashIndex);
}
public static String removeTail(String uri, boolean doStandardize) {
uri = dropTraillingSlash(uri);
int tailLength = tail(uri).length();
return doStandardize ? standardize(uri.substring(0, uri.length() - tailLength)) : uri.substring(0, uri.length() - tailLength);
}
public static String append(String parent, String child) {
StringBuffer uriBuffer = new StringBuffer();
uriBuffer.append(standardize(parent));
uriBuffer.append(standardize(child));
return uriBuffer.toString();
}
public static String standardize(String uri) {
if (uri == null) {
return SLASH;
}
return addLeadingSlash(dropTraillingSlash(uri));
}
public static String normalize(String uri) {
return "".equals(uri) ? SLASH : uri;
}
public static void testCanonical(String path) throws DAVException {
if (path != null && !path.equals(SVNPathUtil.canonicalizePath(path))) {
throw new DAVException("Path ''{0}'' is not canonicalized;\nthere is a problem with the client.", new Object[] { path },
HttpServletResponse.SC_BAD_REQUEST, null, SVNLogType.NETWORK, Level.FINE, null, DAVXMLUtil.SVN_DAV_ERROR_TAG,
DAVElement.SVN_DAV_ERROR_NAMESPACE, 0, null);
}
}
public static String buildURI(String context, DAVResourceKind davResourceKind, long revision, String path, boolean addHref) {
StringBuffer resultURI = new StringBuffer();
path = path == null ? "" : SVNEncodingUtil.uriEncode(path);
context = context == null ? "" : context;
if (addHref) {
SVNXMLUtil.openXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.HREF.getName(), SVNXMLUtil.XML_STYLE_PROTECT_CDATA,
null, resultURI);
}
resultURI.append(context);
resultURI.append(SLASH);
if (davResourceKind == DAVResourceKind.PUBLIC) {
resultURI.append(dropLeadingSlash(path));
} else {
resultURI.append(DAVResourceURI.SPECIAL_URI).append(SLASH);
if (davResourceKind == DAVResourceKind.ACT_COLLECTION) {
resultURI.append(davResourceKind.toString());
resultURI.append(SLASH);
} else if (davResourceKind == DAVResourceKind.BASELINE) {
resultURI.append(davResourceKind.toString());
resultURI.append(SLASH);
resultURI.append(String.valueOf(revision));
} else if (davResourceKind == DAVResourceKind.BASELINE_COLL) {
resultURI.append(davResourceKind.toString());
resultURI.append(SLASH);
resultURI.append(String.valueOf(revision));
resultURI.append(addLeadingSlash(path));
} else if (davResourceKind == DAVResourceKind.VERSION) {
resultURI.append(davResourceKind.toString());
resultURI.append(SLASH);
resultURI.append(String.valueOf(revision));
resultURI.append(addLeadingSlash(path));
} else if (davResourceKind == DAVResourceKind.VCC) {
resultURI.append(davResourceKind.toString());
resultURI.append(SLASH);
resultURI.append(DAVResourceURI.DEDAULT_VCC_NAME);
}
}
if (addHref) {
SVNXMLUtil.closeXMLTag(SVNXMLUtil.DAV_NAMESPACE_PREFIX, DAVElement.HREF.getName(), resultURI, false);
}
return resultURI.toString();
}
public static File getActivityPath(File activitiesDB, String activityID) {
String safeActivityID = SVNFileUtil.computeChecksum(activityID);
File finalActivityFile = new File(activitiesDB, safeActivityID);
return finalActivityFile;
}
public static DAVURIInfo simpleParseURI(String uri, DAVResource relative) throws SVNException {
URI parsedURI = null;
try {
parsedURI = new URI(uri);
} catch (URISyntaxException urise) {
throwMalformedURIErrorException();
}
String path = parsedURI.getPath();
if ("".equals(path)) {
path = "/";
}
String reposRoot = relative.getResourceURI().getContext();
if (!path.equals(reposRoot) && (!path.startsWith(reposRoot) || path.charAt(reposRoot.length()) != '/')) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.APMOD_MALFORMED_URI, "Unusable URI: it does not refer to this repository");
SVNErrorManager.error(err, SVNLogType.NETWORK);
}
long revision = SVNRepository.INVALID_REVISION;
path = path.substring(reposRoot.length());
if ("".equals(path) || "/".equals(path)) {
return new DAVURIInfo(null, "/", revision);
}
path = path.substring(1);
String specialURI = DAVResourceURI.SPECIAL_URI;
if (!path.equals(specialURI) && (!path.startsWith(specialURI) || path.charAt(specialURI.length()) != '/')) {
path = !path.startsWith("/") ? "/" + path : path;
return new DAVURIInfo(null, path, revision);
}
path = path.substring(specialURI.length());
if ("".equals(path) || "/".equals(path)) {
throwUnhandledFormException();
}
int slashInd = path.indexOf('/', 1);
if (slashInd == -1 || slashInd == path.length() -1) {
throwUnhandledFormException();
}
String segment = path.substring(0, slashInd + 1);
String activityID = null;
String reposPath = null;
if ("/act/".equals(segment)) {
activityID = path.substring(slashInd + 1);
} else if ("/ver/".equals(segment)) {
int nextSlashInd = path.indexOf('/', slashInd + 1);
if (nextSlashInd == -1) {
try {
revision = Long.parseLong(path.substring(slashInd + 1));
} catch (NumberFormatException nfe) {
throwMalformedURIErrorException();
}
reposPath = "/";
} else {
segment = path.substring(slashInd + 1, nextSlashInd);
try {
revision = Long.parseLong(segment);
} catch (NumberFormatException nfe) {
throwMalformedURIErrorException();
}
reposPath = SVNEncodingUtil.uriDecode(path.substring(nextSlashInd));
}
if (!SVNRevision.isValidRevisionNumber(revision)) {
throwMalformedURIErrorException();
}
} else {
throwUnhandledFormException();
}
return new DAVURIInfo(activityID, reposPath, revision);
}
private static void throwMalformedURIErrorException() throws SVNException {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.APMOD_MALFORMED_URI, "The specified URI could not be parsed");
SVNErrorManager.error(err, SVNLogType.NETWORK);
}
private static void throwUnhandledFormException() throws SVNException {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.UNSUPPORTED_FEATURE, "Unsupported URI form");
SVNErrorManager.error(err, SVNLogType.NETWORK);
}
}