コード例 #1
0
        private async Task <Engines.CollectionActionResult> LocalExecuteAsync(
            ITargetActions <CollectionTarget, DocumentTarget, MissingTarget> handler,
            Uri sourceUrl,
            SelectionResult sourceSelectionResult,
            FileSystemTarget targetInfo,
            DepthHeader depth,
            bool overwrite,
            CancellationToken cancellationToken)
        {
            Debug.Assert(sourceSelectionResult.Collection != null, "sourceSelectionResult.Collection != null");

            var engine = new RecursiveExecutionEngine <CollectionTarget, DocumentTarget, MissingTarget>(
                handler,
                overwrite,
                Logger);

            CollectionTarget parentCollection;
            ITarget          targetItem;

            if (targetInfo.Collection != null)
            {
                var collTarget = targetInfo.NewCollectionTarget();
                parentCollection = collTarget.Parent;
                targetItem       = collTarget;
            }
            else if (targetInfo.Document != null)
            {
                var docTarget = targetInfo.NewDocumentTarget();
                parentCollection = docTarget.Parent;
                targetItem       = docTarget;
            }
            else
            {
                var missingTarget = targetInfo.NewMissingTarget();
                parentCollection = missingTarget.Parent;
                targetItem       = missingTarget;
            }

            Debug.Assert(parentCollection != null, "Cannt copy or move the root collection.");
            if (parentCollection == null)
            {
                throw new InvalidOperationException("Cannt copy or move the root collection.");
            }

            return(await ExecuteAsync(
                       engine,
                       sourceUrl,
                       sourceSelectionResult,
                       parentCollection,
                       targetItem,
                       depth,
                       cancellationToken)
                   );
        }
コード例 #2
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);
        }