/// <summary> /// Handle a COPY 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 COPY 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; // 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); } // Check if the Overwrite header is set var overwrite = request.GetOverwrite(); // Split the destination Uri var destination = RequestHelper.SplitUri(destinationUri); // Obtain the destination collection var destinationCollection = await store.GetCollectionAsync(destination.CollectionUri, httpContext).ConfigureAwait(false); if (destinationCollection == null) { // Source not found response.SetStatus(DavStatusCode.Conflict, "Destination cannot be found or is not a collection."); return(true); } // Obtain the source item var sourceItem = await store.GetItemAsync(request.Url, httpContext).ConfigureAwait(false); if (sourceItem == null) { // Source not found response.SetStatus(DavStatusCode.NotFound, "Source cannot be found."); return(true); } // Determine depth var depth = request.GetDepth(); // Keep track of all errors var errors = new UriResultCollection(); // Copy collection await CopyAsync(sourceItem, destinationCollection, destination.Name, overwrite, depth, httpContext, destination.CollectionUri, errors).ConfigureAwait(false); // Check if there are any errors if (errors.HasItems) { var xDocument = new XDocument(errors.GetXmlMultiStatus()); await response.SendResponseAsync(DavStatusCode.MultiStatus, xDocument).ConfigureAwait(false); } else { // Set the response response.SetStatus(DavStatusCode.Ok); } return(true); }
//TODO: something wrong with unused depth? private async Task CopyAsync(IStoreItem source, IStoreCollection destinationCollection, string name, bool overwrite, int depth, IHttpContext httpContext, WebDavUri 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); } //do not copy recursively }
/// <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(); var destinationUri = GetDestinationUri(request); 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); }
/// <summary> /// Handle a DELETE 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 DELETE 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; // 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.SetStatus(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.SetStatus(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.SetStatus(DavStatusCode.Locked); return(true); } // Remove the token deleteItem.LockingManager.Unlock(deleteItem, ifToken); } // Delete item var status = await DeleteItemAsync(parentCollection, splitUri.Name, httpContext).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.SetStatus(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); // Items should be moved directly var result = await sourceCollection.MoveItemAsync(sourceName, destinationCollection, destinationName, overwrite, httpContext).ConfigureAwait(false); if (result.Result != DavStatusCode.Created && result.Result != DavStatusCode.NoContent) { errors.AddResult(subBaseUri, result.Result); } }