private async Task <DavStatusCode> DeleteItemAsync(IStoreCollection collection, string name, IHttpContext httpContext, Uri baseUri, UriResultCollection errors) { // Obtain the actual item var deleteCollection = await collection.GetItemAsync(name, httpContext).ConfigureAwait(false) as IStoreCollection; if (deleteCollection != null) { // Determine the new base URI var subBaseUri = UriHelper.Combine(baseUri, name); // Delete all entries first foreach (var entry in await deleteCollection.GetItemsAsync(httpContext).ConfigureAwait(false)) { await DeleteItemAsync(deleteCollection, entry.Name, httpContext, subBaseUri, errors); } } // Attempt to delete the item return(await collection.DeleteItemAsync(name, httpContext).ConfigureAwait(false)); }
public async Task <bool> HandleRequestAsync(IHttpContext httpContext, IStore store) { // Obtain request and response var request = httpContext.Request; var response = httpContext.Response; // Keep track of all errors var errors = new UriResultCollection(); // We should always remove the item from a parent container var splitUri = RequestHelper.SplitUri(request.Url); // Obtain parent collection var parentCollection = await store.GetCollectionAsync(splitUri.CollectionUri, httpContext).ConfigureAwait(false); if (parentCollection == null) { // Source not found response.SendResponse(DavStatusCode.NotFound); return(true); } // Obtain the item that actually is deleted var deleteItem = await parentCollection.GetItemAsync(splitUri.Name, httpContext).ConfigureAwait(false); if (deleteItem == null) { // Source not found response.SendResponse(DavStatusCode.NotFound); return(true); } // Check if the item is locked if (deleteItem.LockingManager?.IsLocked(deleteItem) ?? false) { // Obtain the lock token var ifToken = request.GetIfLockToken(); if (!deleteItem.LockingManager.HasLock(deleteItem, ifToken)) { response.SendResponse(DavStatusCode.Locked); return(true); } // Remove the token deleteItem.LockingManager.Unlock(deleteItem, ifToken); } // Delete item var status = await DeleteItemAsync(parentCollection, splitUri.Name, httpContext, splitUri.CollectionUri, errors).ConfigureAwait(false); if (status == DavStatusCode.Ok && errors.HasItems) { // Obtain the status document var xDocument = new XDocument(errors.GetXmlMultiStatus()); // Stream the document await response.SendResponseAsync(DavStatusCode.MultiStatus, xDocument).ConfigureAwait(false); } else { // Return the proper status response.SendResponse(status); } return(true); }
private async Task MoveAsync(IStoreCollection sourceCollection, string sourceName, IStoreCollection destinationCollection, string destinationName, bool overwrite, IHttpContext httpContext, WebDavUri baseUri, UriResultCollection errors) { // Determine the new base URI var subBaseUri = UriHelper.Combine(baseUri, destinationName); // Obtain the actual item if (await sourceCollection.GetItemAsync(sourceName, httpContext).ConfigureAwait(false) is IStoreCollection moveCollection) { // Create a new collection var newCollectionResult = await destinationCollection.CreateCollectionAsync(destinationName, overwrite, httpContext); if (newCollectionResult.Result != DavStatusCode.Created && newCollectionResult.Result != DavStatusCode.NoContent) { errors.AddResult(subBaseUri, newCollectionResult.Result); return; } // Move all subitems foreach (var entry in await moveCollection.GetItemsAsync(httpContext).ConfigureAwait(false)) { await MoveAsync(moveCollection, entry.Name, newCollectionResult.Collection, entry.Name, overwrite, httpContext, subBaseUri, errors); } // Delete the source collection var deleteResult = await sourceCollection.DeleteItemAsync(sourceName, httpContext); if (deleteResult != DavStatusCode.Ok) { errors.AddResult(subBaseUri, newCollectionResult.Result); return; } } else { // Items should be moved directly var result = await sourceCollection.MoveItemAsync(sourceName, destinationCollection, destinationName, overwrite, httpContext); if (result.Result != DavStatusCode.Created && result.Result != DavStatusCode.NoContent) { errors.AddResult(subBaseUri, result.Result); return; } } }
/// <summary> /// Handle a MOVE request. /// </summary> /// <param name="httpContext"> /// The HTTP context of the request. /// </param> /// <param name="store"> /// Store that is used to access the collections and items. /// </param> /// <returns> /// A task that represents the asynchronous MOVE operation. The task /// will always return <see langword="true"/> upon completion. /// </returns> public async Task <bool> HandleRequestAsync(IHttpContext httpContext, IStore store) { // Obtain request and response var request = httpContext.Request; var response = httpContext.Response; // We should always move the item from a parent container var splitSourceUri = RequestHelper.SplitUri(request.Url); // Obtain source collection var sourceCollection = await store.GetCollectionAsync(splitSourceUri.CollectionUri, httpContext).ConfigureAwait(false); if (sourceCollection == null) { // Source not found response.SetStatus(DavStatusCode.NotFound); return(true); } // Obtain the destination var destinationUri = request.GetDestinationUri(); if (destinationUri == null) { // Bad request response.SetStatus(DavStatusCode.BadRequest, "Destination header is missing."); return(true); } // Make sure the source and destination are different if (request.Url.AbsoluteUri.Equals(destinationUri.AbsoluteUri, StringComparison.CurrentCultureIgnoreCase)) { // Forbidden response.SetStatus(DavStatusCode.Forbidden, "Source and destination cannot be the same."); return(true); } // We should always move the item to a parent var splitDestinationUri = RequestHelper.SplitUri(destinationUri); // Obtain destination collection var destinationCollection = await store.GetCollectionAsync(splitDestinationUri.CollectionUri, httpContext).ConfigureAwait(false); if (destinationCollection == null) { // Source not found response.SetStatus(DavStatusCode.NotFound); return(true); } // Check if the Overwrite header is set var overwrite = request.GetOverwrite(); // Keep track of all errors var errors = new UriResultCollection(); // Move collection await MoveAsync(sourceCollection, splitSourceUri.Name, destinationCollection, splitDestinationUri.Name, overwrite, httpContext, splitDestinationUri.CollectionUri, errors).ConfigureAwait(false); // Check if there are any errors if (errors.HasItems) { // Obtain the status document var xDocument = new XDocument(errors.GetXmlMultiStatus()); // Stream the document await response.SendResponseAsync(DavStatusCode.MultiStatus, xDocument).ConfigureAwait(false); } else { // Set the response response.SetStatus(DavStatusCode.Ok); } return(true); }
private async Task CopyAsync(IStoreItem source, IStoreCollection destinationCollection, string name, bool overwrite, int depth, IHttpContext httpContext, Uri baseUri, UriResultCollection errors) { // Determine the new base Uri var newBaseUri = UriHelper.Combine(baseUri, name); // Copy the item var copyResult = await source.CopyAsync(destinationCollection, name, overwrite, httpContext).ConfigureAwait(false); if (copyResult.Result != DavStatusCode.Created && copyResult.Result != DavStatusCode.NoContent) { errors.AddResult(newBaseUri, copyResult.Result); return; } // Check if the source is a collection and we are requested to copy recursively var sourceCollection = source as IStoreCollection; if (sourceCollection != null && depth > 0) { // The result should also contain a collection var newCollection = (IStoreCollection)copyResult.Item; // Copy all childs of the source collection foreach (var entry in await sourceCollection.GetItemsAsync(httpContext).ConfigureAwait(false)) { await CopyAsync(entry, newCollection, entry.Name, overwrite, depth - 1, httpContext, newBaseUri, errors).ConfigureAwait(false); } } }