WebDavSharp/WebDavSharp_MVC/WebDAVSharp.Server/MethodHandlers/WebDavMethodHandlerBase.cs

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();
}
}
}