Пример #1
0
 protected MoveTestsBase(RecursiveProcessingMode processingMode, params XName[] propertiesToIgnore)
     : base(processingMode)
 {
     _propsToIgnoreDocument   = propertiesToIgnore.Union(new[] { LockDiscoveryProperty.PropertyName, DisplayNameProperty.PropertyName }).ToArray();
     _propsToIgnoreCollection = propertiesToIgnore.Union(new[] { LockDiscoveryProperty.PropertyName, DisplayNameProperty.PropertyName, GetETagProperty.PropertyName }).ToArray();
     Dispatcher = ServiceProvider.GetRequiredService <IWebDavDispatcher>();
 }
Пример #2
0
        private void ConfigureServices(ServerTestsBase container, RecursiveProcessingMode processingMode, IServiceCollection services)
        {
            IFileSystemFactory    fileSystemFactory    = null;
            IPropertyStoreFactory propertyStoreFactory = null;

            services
            .AddOptions()
            .AddLogging()
            .Configure <CopyHandlerOptions>(
                opt =>
            {
                opt.Mode = processingMode;
            })
            .Configure <MoveHandlerOptions>(
                opt =>
            {
                opt.Mode = processingMode;
            })
            .AddScoped <IWebDavContext>(sp => new TestHost(sp, container.Server.BaseAddress, sp.GetRequiredService <IHttpContextAccessor>()))
            .AddScoped <IHttpMessageHandlerFactory>(sp => new TestHttpMessageHandlerFactory(container.Server))
            .AddScoped(sp => fileSystemFactory ?? (fileSystemFactory = ActivatorUtilities.CreateInstance <InMemoryFileSystemFactory>(sp)))
            .AddScoped(sp => propertyStoreFactory ?? (propertyStoreFactory = ActivatorUtilities.CreateInstance <InMemoryPropertyStoreFactory>(sp)))
            .AddSingleton <ILockManager, InMemoryLockManager>()
            .AddMvcCore()
            .AddApplicationPart(typeof(TestWebDavController).GetTypeInfo().Assembly)
            .AddWebDav();
        }
Пример #3
0
        protected ServerTestsBase(RecursiveProcessingMode processingMode)
        {
            var builder = new WebHostBuilder()
                          .ConfigureServices(sc => ConfigureServices(this, processingMode, sc))
                          .UseStartup <TestStartup>();

            Server     = new TestServer(builder);
            FileSystem = Server.Host.Services.GetRequiredService <IFileSystem>();
            Client     = new WebDavClient(Server.CreateHandler())
            {
                BaseAddress = Server.BaseAddress,
            };
        }
Пример #4
0
 /// <inheritdoc />
 protected override ITargetActions <CollectionTarget, DocumentTarget, MissingTarget> CreateLocalTargetActions(RecursiveProcessingMode mode)
 {
     if (mode == RecursiveProcessingMode.PreferFastest)
     {
         return(new MoveInFileSystemTargetAction(WebDavContext.Dispatcher, Logger));
     }
     return(new MoveBetweenFileSystemsTargetAction(WebDavContext.Dispatcher));
 }
Пример #5
0
        /// <summary>
        /// Executes the COPY or MOVE recursively
        /// </summary>
        /// <param name="sourcePath">The source path</param>
        /// <param name="destination">The destination URI</param>
        /// <param name="depth">The depth</param>
        /// <param name="overwrite">Can the destination be overwritten?</param>
        /// <param name="mode">The COPY mode to use</param>
        /// <param name="isMove">Is this a move operation?</param>
        /// <param name="cancellationToken">The cancellcation token</param>
        /// <returns>The result of the operation</returns>
        protected async Task <IWebDavResult> ExecuteAsync(
            string sourcePath,
            Uri destination,
            DepthHeader depth,
            bool overwrite,
            RecursiveProcessingMode mode,
            bool isMove,
            CancellationToken cancellationToken)
        {
            var sourceSelectionResult = await _rootFileSystem.SelectAsync(sourcePath, cancellationToken);

            if (sourceSelectionResult.IsMissing)
            {
                if (WebDavContext.RequestHeaders.IfNoneMatch != null)
                {
                    throw new WebDavException(WebDavStatusCode.PreconditionFailed);
                }

                throw new WebDavException(WebDavStatusCode.NotFound);
            }

            await WebDavContext.RequestHeaders
            .ValidateAsync(sourceSelectionResult.TargetEntry, cancellationToken);

            IWebDavResult result;
            IImplicitLock sourceTempLock;
            var           lockManager = _rootFileSystem.LockManager;

            if (isMove)
            {
                var sourceLockRequirements = new Lock(
                    sourceSelectionResult.TargetEntry.Path,
                    WebDavContext.PublicRelativeRequestUrl,
                    depth != DepthHeader.Zero,
                    new XElement(WebDavXml.Dav + "owner", WebDavContext.User.Identity.Name),
                    LockAccessType.Write,
                    LockShareMode.Shared,
                    TimeoutHeader.Infinite);
                sourceTempLock = lockManager == null
                    ? new ImplicitLock(true)
                    : await lockManager.LockImplicitAsync(
                    _rootFileSystem,
                    WebDavContext.RequestHeaders.If?.Lists,
                    sourceLockRequirements,
                    cancellationToken)
                ;

                if (!sourceTempLock.IsSuccessful)
                {
                    return(sourceTempLock.CreateErrorResponse());
                }
            }
            else
            {
                sourceTempLock = new ImplicitLock(true);
            }

            try
            {
                var sourceUrl      = WebDavContext.PublicAbsoluteRequestUrl;
                var destinationUrl = new Uri(sourceUrl, destination);

                // Ignore different schemes
                if (!WebDavContext.PublicControllerUrl.IsBaseOf(destinationUrl) || mode == RecursiveProcessingMode.PreferCrossServer)
                {
                    if (Logger.IsEnabled(LogLevel.Trace))
                    {
                        Logger.LogTrace("Using cross-server mode");
                    }

                    if (Logger.IsEnabled(LogLevel.Debug))
                    {
                        Logger.LogDebug($"{WebDavContext.PublicControllerUrl} is not a base of {destinationUrl}");
                    }

                    using (var remoteHandler = await CreateRemoteTargetActionsAsync(
                               destinationUrl,
                               cancellationToken)
                           )
                    {
                        if (remoteHandler == null)
                        {
                            throw new WebDavException(
                                      WebDavStatusCode.BadGateway,
                                      "No remote handler for given client");
                        }

                        // For error reporting
                        sourceUrl = WebDavContext.PublicRootUrl.MakeRelativeUri(sourceUrl);

                        var remoteTargetResult = await RemoteExecuteAsync(
                            remoteHandler,
                            sourceUrl,
                            sourceSelectionResult,
                            destinationUrl,
                            depth,
                            overwrite,
                            cancellationToken);

                        result = remoteTargetResult.Evaluate(WebDavContext);
                    }
                }
                else
                {
                    // Copy or move from one known file system to another
                    var destinationPath = WebDavContext.PublicControllerUrl.MakeRelativeUri(destinationUrl).ToString();

                    // For error reporting
                    sourceUrl      = WebDavContext.PublicRootUrl.MakeRelativeUri(sourceUrl);
                    destinationUrl = WebDavContext.PublicRootUrl.MakeRelativeUri(destinationUrl);

                    var destinationSelectionResult =
                        await _rootFileSystem.SelectAsync(destinationPath, cancellationToken);

                    if (destinationSelectionResult.IsMissing && destinationSelectionResult.MissingNames.Count != 1)
                    {
                        Logger.LogDebug(
                            $"{destinationUrl}: The target is missing with the following path parts: {string.Join(", ", destinationSelectionResult.MissingNames)}");
                        throw new WebDavException(WebDavStatusCode.Conflict);
                    }

                    var destLockRequirements = new Lock(
                        new Uri(destinationPath, UriKind.Relative),
                        destinationUrl,
                        isMove || depth != DepthHeader.Zero,
                        new XElement(WebDavXml.Dav + "owner", WebDavContext.User.Identity.Name),
                        LockAccessType.Write,
                        LockShareMode.Shared,
                        TimeoutHeader.Infinite);
                    var destTempLock = lockManager == null
                        ? new ImplicitLock(true)
                        : await lockManager.LockImplicitAsync(
                        _rootFileSystem,
                        WebDavContext.RequestHeaders.If?.Lists,
                        destLockRequirements,
                        cancellationToken)
                    ;

                    if (!destTempLock.IsSuccessful)
                    {
                        return(destTempLock.CreateErrorResponse());
                    }

                    try
                    {
                        var isSameFileSystem = ReferenceEquals(
                            sourceSelectionResult.TargetFileSystem,
                            destinationSelectionResult.TargetFileSystem);
                        var localMode = isSameFileSystem && mode == RecursiveProcessingMode.PreferFastest
                            ? RecursiveProcessingMode.PreferFastest
                            : RecursiveProcessingMode.PreferCrossFileSystem;
                        var handler = CreateLocalTargetActions(localMode);

                        var targetInfo = FileSystemTarget.FromSelectionResult(
                            destinationSelectionResult,
                            destinationUrl,
                            handler);
                        var targetResult = await LocalExecuteAsync(
                            handler,
                            sourceUrl,
                            sourceSelectionResult,
                            targetInfo,
                            depth,
                            overwrite,
                            cancellationToken);

                        result = targetResult.Evaluate(WebDavContext);
                    }
                    finally
                    {
                        await destTempLock.DisposeAsync(cancellationToken);
                    }
                }
            }
            finally
            {
                await sourceTempLock.DisposeAsync(cancellationToken);
            }

            if (isMove && lockManager != null)
            {
                var locksToRemove = await lockManager
                                    .GetAffectedLocksAsync(sourcePath, true, false, cancellationToken)
                ;

                foreach (var activeLock in locksToRemove)
                {
                    await lockManager.ReleaseAsync(
                        activeLock.Path,
                        new Uri(activeLock.StateToken),
                        cancellationToken)
                    ;
                }
            }

            return(result);
        }
Пример #6
0
 /// <summary>
 /// Create the target action implementation for local COPY or MOVE
 /// </summary>
 /// <param name="mode">The requested processing mode (in-filesystem or cross-filesystem)</param>
 /// <returns>The implementation for local actions</returns>
 protected abstract ITargetActions <CollectionTarget, DocumentTarget, MissingTarget> CreateLocalTargetActions(RecursiveProcessingMode mode);