Skip to content

Commit

Permalink
Merge pull request #47 from yar229/develop
Browse files Browse the repository at this point in the history
fixed renaming folders with many inner items
  • Loading branch information
yar229 authored Jan 5, 2017
2 parents a4bbbc8 + bf11f54 commit a13367e
Show file tree
Hide file tree
Showing 13 changed files with 316 additions and 95 deletions.
3 changes: 1 addition & 2 deletions WDMRC.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using NWebDav.Server.Http;
using NWebDav.Server.HttpListener;
using NWebDav.Server.Logging;
using WebDavMailRuCloudStore;
using YaR.WebDavMailRu.CloudStore;
using YaR.WebDavMailRu.CloudStore.Mailru.StoreBase;

Expand Down Expand Up @@ -82,7 +81,7 @@ static void Main(string[] args)
private static async void DispatchHttpRequestsAsync(HttpListener httpListener, CancellationToken cancellationToken, int maxThreadCount = Int32.MaxValue)
{
// Create a request handler factory that uses basic authentication
var requestHandlerFactory = new RequestHandlerFactory();
var requestHandlerFactory = new CloudStore.Mailru.RequestHandlerFactory();

// Create WebDAV dispatcher
var homeFolder = new MailruStore();
Expand Down
63 changes: 63 additions & 0 deletions WebDAVMailRuCloud.sln
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,91 @@ EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|ARM = Release|ARM
Release|x64 = Release|x64
Release|x86 = Release|x86
ReleaseBinaries|Any CPU = ReleaseBinaries|Any CPU
ReleaseBinaries|ARM = ReleaseBinaries|ARM
ReleaseBinaries|x64 = ReleaseBinaries|x64
ReleaseBinaries|x86 = ReleaseBinaries|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.Debug|ARM.ActiveCfg = Debug|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.Debug|ARM.Build.0 = Debug|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.Debug|x64.ActiveCfg = Debug|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.Debug|x64.Build.0 = Debug|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.Debug|x86.ActiveCfg = Debug|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.Debug|x86.Build.0 = Debug|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.Release|Any CPU.Build.0 = Release|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.Release|ARM.ActiveCfg = Release|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.Release|ARM.Build.0 = Release|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.Release|x64.ActiveCfg = Release|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.Release|x64.Build.0 = Release|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.Release|x86.ActiveCfg = Release|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.Release|x86.Build.0 = Release|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.ReleaseBinaries|Any CPU.ActiveCfg = Release|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.ReleaseBinaries|Any CPU.Build.0 = Release|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.ReleaseBinaries|ARM.ActiveCfg = Release|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.ReleaseBinaries|ARM.Build.0 = Release|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.ReleaseBinaries|x64.ActiveCfg = Release|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.ReleaseBinaries|x64.Build.0 = Release|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.ReleaseBinaries|x86.ActiveCfg = Release|Any CPU
{9E1B53CF-F6CD-4861-A177-E06DBC95CD7D}.ReleaseBinaries|x86.Build.0 = Release|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.Debug|ARM.ActiveCfg = Debug|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.Debug|ARM.Build.0 = Debug|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.Debug|x64.ActiveCfg = Debug|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.Debug|x64.Build.0 = Debug|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.Debug|x86.ActiveCfg = Debug|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.Debug|x86.Build.0 = Debug|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.Release|Any CPU.Build.0 = Release|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.Release|ARM.ActiveCfg = Release|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.Release|ARM.Build.0 = Release|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.Release|x64.ActiveCfg = Release|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.Release|x64.Build.0 = Release|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.Release|x86.ActiveCfg = Release|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.Release|x86.Build.0 = Release|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.ReleaseBinaries|Any CPU.ActiveCfg = Release|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.ReleaseBinaries|Any CPU.Build.0 = Release|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.ReleaseBinaries|ARM.ActiveCfg = Release|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.ReleaseBinaries|ARM.Build.0 = Release|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.ReleaseBinaries|x64.ActiveCfg = Release|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.ReleaseBinaries|x64.Build.0 = Release|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.ReleaseBinaries|x86.ActiveCfg = Release|Any CPU
{75BF5EAC-81A8-4E00-A82E-0BCBD17AC50B}.ReleaseBinaries|x86.Build.0 = Release|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.Debug|ARM.ActiveCfg = Debug|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.Debug|ARM.Build.0 = Debug|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.Debug|x64.ActiveCfg = Debug|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.Debug|x64.Build.0 = Debug|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.Debug|x86.ActiveCfg = Debug|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.Debug|x86.Build.0 = Debug|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.Release|Any CPU.Build.0 = Release|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.Release|ARM.ActiveCfg = Release|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.Release|ARM.Build.0 = Release|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.Release|x64.ActiveCfg = Release|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.Release|x64.Build.0 = Release|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.Release|x86.ActiveCfg = Release|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.Release|x86.Build.0 = Release|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.ReleaseBinaries|Any CPU.ActiveCfg = Release|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.ReleaseBinaries|Any CPU.Build.0 = Release|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.ReleaseBinaries|ARM.ActiveCfg = Release|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.ReleaseBinaries|ARM.Build.0 = Release|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.ReleaseBinaries|x64.ActiveCfg = Release|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.ReleaseBinaries|x64.Build.0 = Release|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.ReleaseBinaries|x86.ActiveCfg = Release|Any CPU
{F8FA91A5-466D-4072-8D7B-7791831F520D}.ReleaseBinaries|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
7 changes: 1 addition & 6 deletions WebDavMailRuCloudStore/Cloud.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
using MailRuCloudApi;

namespace WebDavMailRuCloudStore
namespace YaR.WebDavMailRu.CloudStore
{
public static class Cloud
{
static Cloud()
{

}

public static void Init(string login, string password, string userAgent = "")
{
if (!string.IsNullOrEmpty(userAgent))
Expand Down
10 changes: 2 additions & 8 deletions WebDavMailRuCloudStore/DavCustomProperty/DavSharedLink.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,9 @@ namespace YaR.WebDavMailRu.CloudStore.DavCustomProperty
{
public class DavSharedLink<TEntry> : DavString<TEntry> where TEntry : IStoreItem
{
public static readonly XName PropertyName = WebDavNamespaces.DavNs + "SharedLink";
private static readonly XName PropertyName = WebDavNamespaces.DavNs + "SharedLink";

public override XName Name
{
get
{
return DavSharedLink<TEntry>.PropertyName;
}
}
public override XName Name => PropertyName;
}

}
17 changes: 14 additions & 3 deletions WebDavMailRuCloudStore/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MailRuCloudApi;
using NWebDav.Server.Http;
using NWebDav.Server.Stores;
using WebDavMailRuCloudStore;
using YaR.WebDavMailRu.CloudStore.Mailru.StoreBase;

namespace YaR.WebDavMailRu.CloudStore
Expand Down Expand Up @@ -41,6 +38,20 @@ public static Task<bool> Rename(this MailRuCloud cloud, IStoreItem item, string
throw new ArgumentException(string.Empty, nameof(item));
}

public static Task<bool> Move(this MailRuCloud cloud, IStoreItem item, string destinationName)
{
if (null == item) return Task.FromResult(false);

var storeItem = item as MailruStoreItem;
if (storeItem != null)
return cloud.Move(storeItem.FileInfo, destinationName);
var storeCollection = item as MailruStoreCollection;
if (storeCollection != null)
return cloud.Move(storeCollection.DirectoryInfo, destinationName);

throw new ArgumentException(string.Empty, nameof(item));
}


public static long ContentLength(this IHttpRequest request)
{
Expand Down
155 changes: 155 additions & 0 deletions WebDavMailRuCloudStore/Mailru/MoveHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
using NWebDav.Server;
using NWebDav.Server.Helpers;
using NWebDav.Server.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using NWebDav.Server.Stores;

namespace YaR.WebDavMailRu.CloudStore.Mailru
{
public class MoveHandler : IRequestHandler
{
/// <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 MoveAsync(IStoreCollection sourceCollection, string sourceName, IStoreCollection destinationCollection, string destinationName, bool overwrite, IHttpContext httpContext, Uri 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);
if (result.Result != DavStatusCode.Created && result.Result != DavStatusCode.NoContent)
errors.AddResult(subBaseUri, result.Result);
}
}

internal class UriResultCollection
{
private struct UriResult
{
private Uri Uri { get; }
private DavStatusCode Result { get; }

public UriResult(Uri uri, DavStatusCode result)
{
Uri = uri;
Result = result;
}

public XElement GetXmlResponse()
{
var href = Uri.AbsoluteUri;
var statusText = $"HTTP/1.1 {(int)Result} {Result.GetStatusDescription()}";
return new XElement(WebDavNamespaces.DavNs + "response",
new XElement(WebDavNamespaces.DavNs + "href", href),
new XElement(WebDavNamespaces.DavNs + "status", statusText));
}
}

private readonly IList<UriResult> _results = new List<UriResult>();

public bool HasItems => _results.Any();

public void AddResult(Uri uri, DavStatusCode result)
{
_results.Add(new UriResult(uri, result));
}

public XElement GetXmlMultiStatus()
{
var xMultiStatus = new XElement(WebDavNamespaces.DavNs + "multistatus");
foreach (var result in _results)
xMultiStatus.Add(result.GetXmlResponse());
return xMultiStatus;
}
}
}
40 changes: 40 additions & 0 deletions WebDavMailRuCloudStore/Mailru/RequestHandlerFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NWebDav.Server;
using NWebDav.Server.Http;

namespace YaR.WebDavMailRu.CloudStore.Mailru
{
public class RequestHandlerFactory : IRequestHandlerFactory
{
private static readonly IDictionary<string, IRequestHandler> RequestHandlers = new Dictionary<string, IRequestHandler>
{
{ "COPY", new NWebDav.Server.Handlers.CopyHandler() },
{ "DELETE", new NWebDav.Server.Handlers.DeleteHandler() },
{ "GET", new NWebDav.Server.Handlers.GetAndHeadHandler() },
{ "HEAD", new NWebDav.Server.Handlers.GetAndHeadHandler() },
{ "LOCK", new NWebDav.Server.Handlers.LockHandler() },
{ "MKCOL", new NWebDav.Server.Handlers.MkcolHandler() },
{ "MOVE", new MoveHandler() },
{ "OPTIONS", new NWebDav.Server.Handlers.OptionsHandler() },
{ "PROPFIND", new NWebDav.Server.Handlers.PropFindHandler() },
{ "PROPPATCH", new NWebDav.Server.Handlers.PropPatchHandler() },
{ "PUT", new NWebDav.Server.Handlers.PutHandler() },
{ "UNLOCK", new NWebDav.Server.Handlers.UnlockHandler() }
};

public IRequestHandler GetRequestHandler(IHttpContext httpContext)
{
IRequestHandler requestHandler;
if (!RequestHandlers.TryGetValue(httpContext.Request.HttpMethod, out requestHandler))
return null;

return requestHandler;
}

public static IEnumerable<string> AllowedMethods => RequestHandlers.Keys;
}
}
Loading

0 comments on commit a13367e

Please sign in to comment.