245 lines
9.5 KiB
C#
245 lines
9.5 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Web;
|
|
using WebDAVSharp.Server.Adapters;
|
|
using WebDAVSharp.Server.Exceptions;
|
|
using WebDAVSharp.Server.Stores;
|
|
|
|
namespace WebDAVSharp.Server.MethodHandlers {
|
|
/// <summary>
|
|
/// This is the base class for <see cref="IWebDavMethodHandler" /> implementations.
|
|
/// </summary>
|
|
public abstract class WebDavMethodHandlerBase {
|
|
private const int DepthInfinity = -1;
|
|
|
|
/// <summary>
|
|
/// Retrieves a store item through the specified
|
|
/// <see cref="Uri" /> from the
|
|
/// specified
|
|
/// <see cref="WebDavServer" /> and
|
|
/// <see cref="IWebDavStore" />.
|
|
/// </summary>
|
|
/// <param name="server">The <see cref="WebDavServer" /> that hosts the <paramref name="store" />.</param>
|
|
/// <param name="store">The <see cref="IWebDavStore" /> from which to retrieve the store item.</param>
|
|
/// <param name="fileName">The store-relative path to the store item.</param>
|
|
/// <returns>
|
|
/// The retrieved store item.
|
|
/// </returns>
|
|
/// <exception cref="System.ArgumentNullException"><para>
|
|
/// <paramref name="fileName" /> is <c>null</c>.</para>
|
|
/// <para>
|
|
/// <paramref name="server" /> is <c>null</c>.</para>
|
|
/// <para>
|
|
/// <paramref name="store" /> is <c>null</c>.</para></exception>
|
|
/// <exception cref="WebDAVSharp.Server.Exceptions.WebDavNotFoundException">If the item was not found.</exception>
|
|
/// <exception cref="WebDavConflictException"><paramref name="fileName" /> refers to a document in a collection, where the collection does not exist.</exception>
|
|
/// <exception cref="WebDavNotFoundException"><paramref name="fileName" /> refers to a document that does not exist.</exception>
|
|
public static IWebDavStoreItem GetItem(WebDavServer server, IWebDavStore store, String fileName) {
|
|
if (server == null)
|
|
throw new ArgumentNullException("server");
|
|
if (store == null)
|
|
throw new ArgumentNullException("store");
|
|
if (fileName == null)
|
|
throw new ArgumentNullException("fileName");
|
|
|
|
//Uri prefixUri = uri.GetPrefixUri(server);
|
|
//String prefixUri = server.ServiceUrl;
|
|
IWebDavStoreCollection collection = store.Root;
|
|
|
|
IWebDavStoreItem item = null;
|
|
//if (prefixUri.Segments.Length == uri.Segments.Length)
|
|
if (fileName == "/")
|
|
return collection;
|
|
var dirNames = fileName.Split(new char[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
//for (int index = prefixUri.Segments.Length; index < uri.Segments.Length; index++) {
|
|
for (int index = 0; index < dirNames.Length; index++) {
|
|
var dirName = dirNames[index];
|
|
//string segmentName = Uri.UnescapeDataString(uri.Segments[index]);
|
|
//IWebDavStoreItem nextItem = collection.GetItemByName(segmentName.TrimEnd('/', '\\'));
|
|
IWebDavStoreItem nextItem = collection.GetItemByName(dirName);
|
|
if (nextItem == null)
|
|
throw new WebDavNotFoundException(); //throw new WebDavConflictException();
|
|
|
|
if (index == dirNames.Length - 1)
|
|
item = nextItem;
|
|
else {
|
|
collection = nextItem as IWebDavStoreCollection;
|
|
if (collection == null)
|
|
throw new WebDavNotFoundException();
|
|
}
|
|
}
|
|
|
|
if (item == null)
|
|
throw new WebDavNotFoundException();
|
|
|
|
return item;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the parent collection from the requested
|
|
/// <see cref="Uri" />.
|
|
/// <see cref="WebDavException" /> 409 Conflict possible.
|
|
/// </summary>
|
|
/// <param name="server">The <see cref="WebDavServer" /> through which the request came in from the client.</param>
|
|
/// <param name="store">The <see cref="IWebDavStore" /> that the <see cref="WebDavServer" /> is hosting.</param>
|
|
/// <returns>
|
|
/// The parrent collection as an <see cref="IWebDavStoreCollection" />
|
|
/// </returns>
|
|
/// <exception cref="WebDAVSharp.Server.Exceptions.WebDavUnauthorizedException"></exception>
|
|
/// <exception cref="WebDAVSharp.Server.Exceptions.WebDavConflictException">
|
|
/// </exception>
|
|
/// <exception cref="WebDavUnauthorizedException">When the user is unauthorized and doesn't have access</exception>
|
|
/// <exception cref="WebDavConflictException">When the parent collection doesn't exist</exception>
|
|
public static IWebDavStoreCollection GetParentCollection(WebDavServer server, IWebDavStore store, String fileName) {
|
|
String parentDirName = ExtractParentName(fileName);
|
|
//Uri parentCollectionUri = childUri.GetParentUri();
|
|
IWebDavStoreCollection collection;
|
|
try {
|
|
collection = GetItem(server, store, parentDirName) as IWebDavStoreCollection;
|
|
}
|
|
catch (UnauthorizedAccessException) {
|
|
throw new WebDavUnauthorizedException();
|
|
}
|
|
catch (WebDavNotFoundException) {
|
|
throw new WebDavConflictException();
|
|
}
|
|
if (collection == null)
|
|
throw new WebDavConflictException();
|
|
|
|
return collection;
|
|
}
|
|
|
|
public static string ExtractParentName(string fileName) {
|
|
if (fileName == null)
|
|
throw new ArgumentNullException("fileName");
|
|
if (fileName == "/") {
|
|
//TODO: better throw error?
|
|
//throw new InvalidOperationException("Cannot get parent of root");
|
|
return fileName;
|
|
}
|
|
|
|
//get path without the last part "dir1/dir2/<remove>/"
|
|
return Path.GetDirectoryName(fileName.Trim('/', '\\')).Replace('\\', '/');
|
|
}
|
|
|
|
public string ExtractLocalPath(WebDavServer server, string absoluteUri) {
|
|
var serviceLocalPath = new Uri(server.ServiceUrl).LocalPath.Trim('/');
|
|
var startPos = absoluteUri.IndexOf(serviceLocalPath);
|
|
absoluteUri = Uri.UnescapeDataString(absoluteUri);
|
|
if (startPos > -1) {
|
|
return '/' + absoluteUri.Substring(startPos + serviceLocalPath.Length).Trim('/', '\\');
|
|
}else {
|
|
return '/' + absoluteUri.Trim('/', '\\');
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the item in the collection from the requested
|
|
/// <see cref="Uri" />.
|
|
/// <see cref="WebDavException" /> 409 Conflict possible.
|
|
/// </summary>
|
|
/// <param name="collection">The parent collection as a <see cref="IWebDavStoreCollection" /></param>
|
|
/// <param name="childUri">The <see cref="Uri" /> object containing the specific location of the child</param>
|
|
/// <returns>
|
|
/// The <see cref="IWebDavStoreItem" /> from the <see cref="IWebDavStoreCollection" />
|
|
/// </returns>
|
|
/// <exception cref="WebDAVSharp.Server.Exceptions.WebDavUnauthorizedException">If user is not authorized to get access to the item</exception>
|
|
/// <exception cref="WebDAVSharp.Server.Exceptions.WebDavNotFoundException">If item not found.</exception>
|
|
public static IWebDavStoreItem GetItemFromCollection(IWebDavStoreCollection collection, String fileName) {
|
|
IWebDavStoreItem item;
|
|
try {
|
|
item = collection.GetItemByName(ExtractFileName(fileName));
|
|
}
|
|
catch (UnauthorizedAccessException) {
|
|
throw new WebDavUnauthorizedException();
|
|
}
|
|
catch (WebDavNotFoundException) {
|
|
throw new WebDavNotFoundException();
|
|
}
|
|
if (item == null)
|
|
throw new WebDavNotFoundException();
|
|
|
|
return item;
|
|
}
|
|
|
|
public static string ExtractFileName(string fileName) {
|
|
//Uri.UnescapeDataString(childUri.Segments.Last().TrimEnd('/', '\\')));
|
|
return Path.GetFileName(fileName.Trim('/', '\\'));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the Depth header : 0, 1 or infinity
|
|
/// </summary>
|
|
/// <param name="request">The <see cref="IHttpListenerContext" /> with the response included</param>
|
|
/// <returns>
|
|
/// The values 0, 1 or -1 (for infinity)
|
|
/// </returns>
|
|
public static int GetDepthHeader(HttpRequest request) {
|
|
// get the value of the depth header as a string
|
|
string depth = request.Headers["Depth"];
|
|
|
|
// check if the string is valid or not infinity
|
|
// if so, try to parse it to an int
|
|
if (String.IsNullOrEmpty(depth) || depth.Equals("infinity"))
|
|
return DepthInfinity;
|
|
int value;
|
|
if (!int.TryParse(depth, out value))
|
|
return DepthInfinity;
|
|
if (value == 0 || value == 1)
|
|
return value;
|
|
// else, return the infinity value
|
|
return DepthInfinity;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the Overwrite header : T or F
|
|
/// </summary>
|
|
/// <param name="request">The <see cref="IHttpListenerRequest"/> has the header included</param>
|
|
/// <returns>The <see cref="bool"/> true if overwrite, false if no overwrite</returns>
|
|
public static bool GetOverwriteHeader(HttpRequest request) {
|
|
// get the value of the Overwrite header as a string
|
|
string overwrite = request.Headers["Overwrite"];
|
|
|
|
// check if the string is valid and if it equals T
|
|
return overwrite != null && overwrite.Equals("T");
|
|
// else, return false
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the Timeout header : Second-number
|
|
/// </summary>
|
|
/// <param name="request">The request with the request included</param>
|
|
/// <returns>The value of the Timeout header as a string</returns>
|
|
public static string GetTimeoutHeader(HttpRequest request) {
|
|
// get the value of the timeout header as a string
|
|
string timeout = request.Headers["Timeout"];
|
|
|
|
// check if the string is valid or not infinity
|
|
// if so, try to parse it to an int
|
|
if (!String.IsNullOrEmpty(timeout) && !timeout.Equals("infinity") &&
|
|
!timeout.Equals("Infinite, Second-4100000000"))
|
|
return timeout;
|
|
// else, return the timeout value as if it was requested to be 4 days
|
|
return "Second-345600";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the Destination header as an URI
|
|
/// </summary>
|
|
/// <param name="request">The <see cref="IHttpListenerRequest"/> has the header included</param>
|
|
/// <returns>The <see cref="Uri"/> containing the destination</returns>
|
|
public static Uri GetDestinationHeader(HttpRequest request) {
|
|
// get the value of the Destination header as a string
|
|
string destinationUri = request.Headers["Destination"];
|
|
|
|
// check if the string is valid
|
|
if (!String.IsNullOrEmpty(destinationUri))
|
|
return new Uri(destinationUri);
|
|
// else, throw exception
|
|
throw new WebDavConflictException();
|
|
}
|
|
}
|
|
}
|