コード例 #1
0
        private async Task <Engines.CollectionActionResult> RemoteExecuteAsync(
            IRemoteTargetActions handler,
            Uri sourceUrl,
            SelectionResult sourceSelectionResult,
            Uri targetUrl,
            DepthHeader depth,
            bool overwrite,
            CancellationToken cancellationToken)
        {
            Debug.Assert(sourceSelectionResult.Collection != null, "sourceSelectionResult.Collection != null");

            var parentCollectionUrl = targetUrl.GetParent();

            var engine = new RecursiveExecutionEngine <RemoteCollectionTarget, RemoteDocumentTarget, RemoteMissingTarget>(
                handler,
                overwrite,
                Logger);

            var targetName       = targetUrl.GetName();
            var parentName       = parentCollectionUrl.GetName();
            var parentCollection = new RemoteCollectionTarget(null, parentName, parentCollectionUrl, false, handler);
            var targetItem       = await handler.GetAsync(parentCollection, targetName, cancellationToken);

            return(await ExecuteAsync(
                       engine,
                       sourceUrl,
                       sourceSelectionResult,
                       parentCollection,
                       targetItem,
                       depth,
                       cancellationToken)
                   );
        }
コード例 #2
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)
                   );
        }
コード例 #3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="WebDavRequestHeaders"/> class.
 /// </summary>
 /// <param name="headers">The headers to parse</param>
 /// <param name="context">The WebDAV request context</param>
 public WebDavRequestHeaders([NotNull] IEnumerable <KeyValuePair <string, IEnumerable <string> > > headers, [NotNull] IWebDavContext context)
 {
     Headers           = headers.ToDictionary(x => x.Key, x => (IReadOnlyCollection <string>)x.Value.ToList(), StringComparer.OrdinalIgnoreCase);
     Depth             = ParseHeader("Depth", args => DepthHeader.Parse(args.Single()));
     Overwrite         = ParseHeader("Overwrite", args => OverwriteHeader.Parse(args.Single()));
     Range             = ParseHeader("Range", RangeHeader.Parse);
     If                = ParseHeader("If", args => IfHeader.Parse(args.Single(), EntityTagComparer.Strong, context));
     IfMatch           = ParseHeader("If-Match", IfMatchHeader.Parse);
     IfNoneMatch       = ParseHeader("If-None-Match", IfNoneMatchHeader.Parse);
     IfModifiedSince   = ParseHeader("If-Modified-Since", args => IfModifiedSinceHeader.Parse(args.Single()));
     IfUnmodifiedSince = ParseHeader("If-Unmodified-Since", args => IfUnmodifiedSinceHeader.Parse(args.Single()));
     Timeout           = ParseHeader("Timeout", TimeoutHeader.Parse);
     ContentLength     = ParseHeader("Content-Length", args => (long?)XmlConvert.ToInt64(args.Single()));
 }
コード例 #4
0
        public IList<IWebDAVResource> PropFindHandler(string username, string path, DepthHeader depth)
        {
            string[] parts = path.Split('/');
            //if (parts.Length >= 3 && parts[1] == "inventory")
            if (parts.Length >= 3 && parts[1] == m_SubDomain)
            {
                string localPath = "";
                UUID agentID = WebDAVServerConnector.AgentIDFromRequestPath(m_SubDomain, m_InitialLocalPath, path, ref localPath);
                if (agentID != UUID.Zero)
                {
                    List<IWebDAVResource> davEntries = new List<IWebDAVResource>();
                    InventoryNodeBase invObject = m_WebDAVServerConnector.PathToInventory(agentID, localPath);
                    if (invObject == null)
                        return davEntries;
                    path = HttpUtility.UrlPathEncode(path);

                    IWebDAVResource resource = null;
                    resource = m_PropertyProvider.Load(path);
                    if (resource == null)
                    {
                        resource = WebDAVServerConnector.InventoryToDAV(path, invObject);
                        m_PropertyProvider.Save(resource);
                    }

                    // Only add the root to response if the client wants it
                    if (depth != DepthHeader.InfinityNoRoot && depth != DepthHeader.OneNoRoot)
                        davEntries.Add(resource);
                    if (invObject is InventoryFolderBase && (depth == DepthHeader.One || depth == DepthHeader.Infinity))
                    {
                        InventoryFolderBase folder = (InventoryFolderBase)invObject;

                        RecursiveGetProperties(agentID, path, folder, ref davEntries, depth);
                    }
                    return davEntries;
                }
            }

            if (parts.Length == 2 || (parts.Length == 3 && parts[2] == String.Empty))
            {
                // Client requested PROPFIND for inventory/ or something alike
                // we probably will not send other users inventory listings because they're private

                List<IWebDAVResource> davEntries = new List<IWebDAVResource>();
                //TODO: Change the DateTimes to something meaningful
                davEntries.Add(new WebDAVFolder(path, DateTime.UtcNow, DateTime.UtcNow, DateTime.UtcNow, false));
                return davEntries;
            }
            throw new NotImplementedException();
        }
コード例 #5
0
 HttpStatusCode InventoryCopyHandler(string username, Uri uri, string destination, DepthHeader depth, bool overwrite, string[] ifHeaders, out Dictionary<string, HttpStatusCode> multiStatusValues)
 {
     return MoveAndCopyWorker(username, uri, destination, depth, overwrite, ifHeaders, out multiStatusValues, true);
 }
コード例 #6
0
        private HttpStatusCode MoveAndCopyWorker(string username, Uri uri, string destination, DepthHeader depth, bool overwrite, string[] ifHeaders, out Dictionary<string, HttpStatusCode> multiStatusValues, bool copy)
        {
            CopyMoveItemHandler copyMoveItemHandler = null;
            CopyMoveFolderHandler copyMoveFolderHandler = null;
            if (copy)
            {
                copyMoveItemHandler = new CopyMoveItemHandler(CopyItemToNonExistentDestination);
                copyMoveFolderHandler = new CopyMoveFolderHandler(CopyFolderToNonExistentDestination);
            }
            else 
            {
                copyMoveItemHandler = new CopyMoveItemHandler(MoveItemToNonExistentDestination);
                copyMoveFolderHandler = new CopyMoveFolderHandler(MoveFolderToNonExistentDestination);            
            }

            multiStatusValues = null;
            string source = uri.AbsoluteUri;
            string[] srcParts = source.ToString().Split('/');
            string[] dstParts = destination.Split('/');
            for (int i = 0; i < 3; i++)
            {
                if (srcParts[i] != dstParts[i])
                {
                    //error, some of the following has happened
                    //a) source or destination did not contain the whole absolute uri
                    //b) source and destination use different protocol http vs. https
                    //c) source and destination are in different domain
                    return HttpStatusCode.BadGateway;
                }
            }

            string localPath = "";
            string path = uri.LocalPath;
            UUID agentID = AgentIDFromRequestPath("inventory", "/", path, ref localPath);
            string localDestionation = destination;
            // get local destination cut out the http://127.0.0.1:8003/inventory/00000000-0000-0000-0000-000000000000/ part
            string[] parts = localDestionation.Split(new char[] { '/' }, 6);
            localDestionation = parts[5];

            if (destination.EndsWith("/"))
                destination = destination.Substring(0, destination.Length - 1);

            string destinationName = destination.Substring(destination.LastIndexOf('/') + 1); // destination object or collection name

            // Check if source & destination paths exist
            // check if we moving an item or collection
            // get source and change parentID

            // Check if source & destination paths exist
            bool destinationNodeExists = true;
            // get source node
            InventoryNodeBase sourceNode = PathToInventory(agentID, localPath);
            if (sourceNode == null)
                return HttpStatusCode.NotFound;
            // destination node
            InventoryNodeBase destinationNode = PathToInventory(agentID, localDestionation);
            if (destinationNode == null) { destinationNodeExists = false; }

            // Check if source is folder or item
            bool sourceIsItem = false;
            InventoryFolderBase fetchFolder = new InventoryFolderBase(sourceNode.ID, agentID);
            InventoryFolderBase sourceFolderBase = m_InventoryService.GetFolder(fetchFolder);
            if (sourceFolderBase == null) { sourceIsItem = true; }

            // if destination exists check if its an item
            bool destinationIsItem = false;
            InventoryFolderBase DestinationFolder = null;
            if (destinationNodeExists)
            {
                InventoryFolderBase fetchDestinationFolder = new InventoryFolderBase(destinationNode.ID, agentID);
                DestinationFolder = m_InventoryService.GetFolder(fetchDestinationFolder);
                if (DestinationFolder == null) { destinationIsItem = true; }
            }

            // Check if destination node does not exist check if its parent exists
            bool destinationParentExists = false;
            bool destinationParentIsFolder = false;
            InventoryNodeBase destinationParentNode = null;
            if (!destinationNodeExists)
            {
                if (localDestionation.EndsWith("/")) localDestionation = localDestionation.Substring(0, localDestionation.Length - 1);
                string destinationParentPath = localDestionation.Substring(0, localDestionation.LastIndexOf('/'));
                destinationParentNode = PathToInventory(agentID, destinationParentPath);
                if (destinationParentNode != null) 
                {
                    destinationParentExists = true;
                    // if parent exists make sure its actually a folder
                    if (destinationParentNode is InventoryFolderBase) {
                        destinationParentIsFolder = true;
                    }
                }
            }

            multiStatusValues = new Dictionary<string, HttpStatusCode>();

            // Go thru these scenarios
            // 1. source is an item and destination does not exist
            //      1.1. destination parent folder exists
            //      1.2. destination parent exist but is an item
            //      1.3. destination parent folder does not exist
            // 2. source is folder and destination does not exist
            //      2.1. destination parent folder exists
            //      2.2. destination parent exist but is an item
            //      2.3. destination parent folder does not exist
            // 3. source and destination are both items
            // 4. source and destination are both folders
            // 5. source is item and destination is folder
            // 6. source is folder and destination is item

            // 1. :
            if (sourceIsItem && !destinationNodeExists)
            {
                // 1.1.
                if (destinationParentExists && destinationParentIsFolder)
                {
                    HttpStatusCode result = copyMoveItemHandler(agentID, localDestionation, sourceNode, multiStatusValues, destinationName);
                    //m_InventoryPropertyHandler.CopyProperties(path, "/inventory/" + agentID.ToString() + "/" + localDestionation);
                    return (HttpStatusCode) 207;
                }
                // 1.2.
                if (destinationParentExists && !destinationParentIsFolder) 
                {
                    if (!overwrite)
                    { 
                        return SetErrorsAndReturnMultiStatus(agentID, sourceNode, ref multiStatusValues, 
                            new HttpStatusCode[] {HttpStatusCode.NotAcceptable}); 
                    }
                    // TODO: figure out right politics here
                    // could delete the item and write folder in its place like this:
                    //List<UUID> uuids = new List<UUID>();
                    //uuids.Add(destinationParentNode.ID);
                    //if (m_InventoryService.DeleteItems(agentID, uuids)) {
                    //    return copyMoveItemHandler(agentID, localDestionation, sourceNode, multiStatusValues, destinationName);
                    //}
                    // easy way out
                    return SetErrorsAndReturnMultiStatus(agentID, sourceNode, ref multiStatusValues,
                        new HttpStatusCode[] { HttpStatusCode.Conflict });
                }
                // 1.3.
                if (!destinationParentExists && !destinationParentIsFolder) 
                {
                    if (!overwrite)
                    {
                        return SetErrorsAndReturnMultiStatus(agentID, sourceNode, ref multiStatusValues,
                            new HttpStatusCode[] { HttpStatusCode.NotAcceptable });
                    }
                    // we could do path creation if overwrite is true, we need to overwrite if there's item in the path that has same
                    // name as folder in the path
                    // taking easy way out return conflict:
                    return SetErrorsAndReturnMultiStatus(agentID, sourceNode, ref multiStatusValues,
                        new HttpStatusCode[] { HttpStatusCode.Conflict });
                }                
            }

            // 2. :
            if (!sourceIsItem && !destinationNodeExists)
            {
                // 1.1.
                if (destinationParentExists && destinationParentIsFolder)
                    return copyMoveFolderHandler(agentID, localDestionation, sourceNode, depth, multiStatusValues, destinationName);
                // 1.2.
                if (destinationParentExists && !destinationParentIsFolder)
                {
                    if (!overwrite)
                    {
                        return SetErrorsAndReturnMultiStatus(agentID, sourceNode, ref multiStatusValues,
                            new HttpStatusCode[] { HttpStatusCode.NotAcceptable });
                    }
                    // TODO: figure out right politics here
                    // could delete the item and write folder in its place like this:
                    //List<UUID> uuids = new List<UUID>();
                    //uuids.Add(destinationParentNode.ID);
                    //if (m_InventoryService.DeleteItems(agentID, uuids))
                    //{
                    //    return copyMoveItemHandler(agentID, localDestionation, sourceNode, multiStatusValues, destinationName);
                    //}
                    // easy way out
                    return SetErrorsAndReturnMultiStatus(agentID, sourceNode, ref multiStatusValues,
                        new HttpStatusCode[] { HttpStatusCode.Conflict });
                }
                // 1.3.
                if (!destinationParentExists && !destinationParentIsFolder) // we could do path creation if overwrite is true
                {
                    if (!overwrite)
                    {
                        return SetErrorsAndReturnMultiStatus(agentID, sourceNode, ref multiStatusValues,
                            new HttpStatusCode[] { HttpStatusCode.NotAcceptable });
                    }
                    // we could do path creation if overwrite is true, we need to overwrite if there's item in the path that has same
                    // name as folder in the path
                    // taking easy way out return conflict:
                    // easy way out
                    return SetErrorsAndReturnMultiStatus(agentID, sourceNode, ref multiStatusValues,
                        new HttpStatusCode[] { HttpStatusCode.Conflict });
                }                
            }

            // 3. :
            if (sourceIsItem && destinationIsItem)
            {
                if (!overwrite)
                {
                    multiStatusValues.Add(NodeToPath(agentID, sourceNode), HttpStatusCode.Conflict);
                    return (HttpStatusCode)207; ;
                }
                // delete destination item
                List<UUID> items = new List<UUID>(); items.Add(destinationNode.ID);
                if (!m_InventoryService.DeleteItems(agentID, items))
                {
                    return HttpStatusCode.InternalServerError;
                }
                // reduces to 1:
                return copyMoveItemHandler(agentID, localDestionation, sourceNode, multiStatusValues, destinationName);
            }

            // 4. :
            if (!sourceIsItem && !destinationIsItem)
            {
                if (!overwrite)
                {
                    multiStatusValues.Add(NodeToPath(agentID, sourceNode), HttpStatusCode.Conflict);
                    return (HttpStatusCode)207; ;
                }
                // delete destination folder
                RecursiveDelete(DestinationFolder, NodeToPath(agentID, destinationNode), multiStatusValues, agentID);
                // reduces to 2:
                return copyMoveFolderHandler(agentID, localDestionation, sourceNode, depth, multiStatusValues, destinationName);
            }

            // 5. :
            if (sourceIsItem && !destinationIsItem)
            {
                if (!overwrite)
                {
                    multiStatusValues.Add(NodeToPath(agentID, sourceNode), HttpStatusCode.Conflict);
                    return (HttpStatusCode)207; ;
                }
                // delete destination folder
                RecursiveDelete(DestinationFolder, NodeToPath(agentID, destinationNode), multiStatusValues, agentID);
                // reduces to 1:
                return copyMoveItemHandler(agentID, localDestionation, sourceNode, multiStatusValues, destinationName);
            }

            // 6. :
            if (!sourceIsItem && destinationIsItem)
            {
                if (!overwrite)
                {
                    multiStatusValues.Add(NodeToPath(agentID, sourceNode), HttpStatusCode.Conflict);
                    return (HttpStatusCode)207; ;
                }
                // delete destination item
                List<UUID> items = new List<UUID>(); items.Add(destinationNode.ID);
                if (!m_InventoryService.DeleteItems(agentID, items))
                {
                    return HttpStatusCode.InternalServerError;
                }
                // reduces to 2:
                return copyMoveFolderHandler(agentID, localDestionation, sourceNode, depth, multiStatusValues, destinationName);
            }

            return HttpStatusCode.InternalServerError;
        }
コード例 #7
0
 private HttpStatusCode MoveFolderToNonExistentDestination(UUID agent_id,
                                               string local_destination,
                                               InventoryNodeBase source_node,
                                               DepthHeader depth, 
                                               Dictionary<string, HttpStatusCode> status_values,
                                               string destName)
 {
     InventoryFolderBase destinationParentFolder = CreateFolderPath(agent_id, local_destination, true);
     InventoryFolderBase sourceFolderBase = m_InventoryService.GetFolder(new InventoryFolderBase(source_node.ID, agent_id));
     List<string> customProperties = m_InventoryPropertyHandler.PreparePropertiesMove(agent_id, source_node);
     sourceFolderBase.ParentID = destinationParentFolder.ID;
     sourceFolderBase.Name = destName;
     if (m_InventoryService.UpdateFolder(sourceFolderBase))
     {
         m_InventoryPropertyHandler.MoveProperties(agent_id, sourceFolderBase, customProperties);
         status_values.Add(NodeToPath(agent_id, source_node), HttpStatusCode.OK);
     }
     else
     {
         status_values.Add(NodeToPath(agent_id, source_node), HttpStatusCode.InternalServerError);
     }
     return HttpStatusCode.OK;
 }
コード例 #8
0
 private HttpStatusCode CopyFolderToNonExistentDestination(UUID agent_id,
                                               string local_destionation,
                                               InventoryNodeBase source_node,
                                               DepthHeader depth, 
                                               Dictionary<string, HttpStatusCode> status_values,
                                               string destName)
 {
     InventoryFolderBase destinationParentFolder = CreateFolderPath(agent_id, local_destionation, true);
     //fetch folder and copy it
     InventoryFolderBase sourceFolderToCopy = m_InventoryService.GetFolder(new InventoryFolderBase(source_node.ID, agent_id));
     sourceFolderToCopy.Name = destName;
     HttpStatusCode ret = RecursiveCopyFolder(agent_id, sourceFolderToCopy, destinationParentFolder,
                                              depth, status_values);
     status_values.Add(NodeToPath(agent_id, source_node), ret);
     return (HttpStatusCode)207;
 }
コード例 #9
0
 public System.Net.HttpStatusCode MoveCallback(string username, System.Uri uri, string destination, DepthHeader depth, bool overwrite, string[] ifHeaders, out System.Collections.Generic.Dictionary<string, System.Net.HttpStatusCode> multiStatusValues)
 {
     CheckExpiringTimeOutLocks();
     return m_LockHandler.MoveCallback(username, uri, destination, depth, overwrite, ifHeaders, out multiStatusValues);
 }
コード例 #10
0
ファイル: WebDAVListener.cs プロジェクト: jonnenauha/ModreX
 internal HttpStatusCode OnMoveConnector(string username, Uri uri, string destination, DepthHeader depth, bool overwrite, string[] ifHeaders, out Dictionary<String, HttpStatusCode> multiStatusValues)
 {
     if (OnMove != null)
     {
         return OnMove(username, uri, destination, depth, overwrite, ifHeaders, out multiStatusValues);
     }
     multiStatusValues = null;
     return HttpStatusCode.MethodNotAllowed;
 }
コード例 #11
0
        HttpStatusCode MoveHandler(string username, Uri source, string destination, DepthHeader depth, bool overwrite,
            string[] ifHeaders, out Dictionary<string, HttpStatusCode> multiStatusValues)
        {
            multiStatusValues = null;
            try
            {
                string[] srcParts = source.ToString().Split('/');
                string[] dstParts = destination.Split('/');

                //check the source
                string srcParent = "/";
                string[] srcFolders = new string[srcParts.Length - 4];
                Array.Copy(srcParts, 3, srcFolders, 0, srcFolders.Length);
                for (int i = 0; i < srcFolders.Length; i++)
                {
                    srcParent += srcFolders[i];
                    srcParent += "/";
                }

                string srcResourceName = (source.ToString().EndsWith("/")) ? srcParts[srcParts.Length - 2] : srcParts[srcParts.Length - 1];
                AssetFolder sourceResource = m_assetFolderStrg.GetItem(srcParent, srcResourceName);

                if (sourceResource == null)
                    return HttpStatusCode.NotFound; //source resource not found

                //then check destination
                string dstParent = "/";
                string[] dstFolders = new string[dstParts.Length - 4];
                Array.Copy(dstParts, 3, dstFolders, 0, dstFolders.Length);
                for (int i = 0; i < dstFolders.Length; i++)
                {
                    dstParent += dstFolders[i];
                    dstParent += "/";
                }

                //check if destination parent exists
                AssetFolder destinationParent = GetAssetFolder(dstParent);
                if (destinationParent == null)
                    return HttpStatusCode.Conflict; //it didn't, conflict

                //if no problems, move
                string dstResourceName = (source.ToString().EndsWith("/")) ? dstParts[dstParts.Length - 2] : dstParts[dstParts.Length - 1];
                AssetFolder destinationResource = m_assetFolderStrg.GetItem(dstParent, dstResourceName);
                if (destinationResource == null)
                {
                    //no destination. simplest case.
                    //just move existing resource to here
                    MoveFolderAndAllSubFolders(sourceResource, destinationResource, dstParent, dstResourceName, ref multiStatusValues);

                    if (multiStatusValues != null)
                        return (HttpStatusCode)207;
                    else
                        return HttpStatusCode.Created;
                }
                else
                {
                    if (overwrite)
                    {
                        //check if source and destination are both folder so we move only the content
                        //and remove the old folder
                        bool sourceIsFolder = !(sourceResource is AssetFolderItem);
                        bool destinationIsFolder = !(destinationResource is AssetFolderItem);
                        if (sourceIsFolder && destinationIsFolder)
                        {
                            //remove, add etc.
                            MoveFolderAndAllSubFolders(sourceResource, destinationResource, dstParent, dstResourceName, ref multiStatusValues);

                            if (multiStatusValues != null)
                                return (HttpStatusCode)207;
                            else
                                return HttpStatusCode.NoContent; //all ok
                        }
                        else
                        {
                            MoveFolderAndAllSubFolders(sourceResource, destinationResource, dstParent, dstResourceName, ref multiStatusValues);

                            if (multiStatusValues != null)
                                return (HttpStatusCode)207;
                            else
                                return HttpStatusCode.Created;
                        }
                    }
                    else
                    {
                        return HttpStatusCode.PreconditionFailed;
                    }
                }
            }
            catch (Exception e)
            {
                m_log.ErrorFormat("[WORLDINVENTORY]: Could not move {0} to {1}, because exception {2} was thrown.", source.ToString(), destination, e.ToString());
                return HttpStatusCode.InternalServerError;
            }
        }
コード例 #12
0
        /// <summary>
        /// Operates on a collection and the given target collection
        /// </summary>
        /// <param name="sourceUrl">The root-relative source URL</param>
        /// <param name="source">The source collection</param>
        /// <param name="depth">The recursion depth</param>
        /// <param name="target">The target collection</param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns>The result information of the current operation</returns>
        public async Task <CollectionActionResult> ExecuteAsync(Uri sourceUrl, ICollection source, DepthHeader depth, TCollection target, CancellationToken cancellationToken)
        {
            if (_logger.IsEnabled(LogLevel.Trace))
            {
                _logger.LogTrace($"Collecting nodes for operation on collection {sourceUrl} with existing target {target.DestinationUrl}.");
            }
            var nodes = await source.GetNodeAsync(depth.OrderValue, cancellationToken).ConfigureAwait(false);

            return(await ExecuteAsync(sourceUrl, nodes, target, cancellationToken).ConfigureAwait(false));
        }
コード例 #13
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);
        }
コード例 #14
0
        /// <summary>
        /// Executes the COPY or MOVE recursively
        /// </summary>
        /// <typeparam name="TCollection">The collection type</typeparam>
        /// <typeparam name="TDocument">The document type</typeparam>
        /// <typeparam name="TMissing">The type for a missing entry</typeparam>
        /// <param name="engine">The engine to use to perform the operation</param>
        /// <param name="sourceUrl">The source URL</param>
        /// <param name="sourceSelectionResult">The source element</param>
        /// <param name="parentCollection">The parent collection of the source element</param>
        /// <param name="targetItem">The target of the operation</param>
        /// <param name="depth">The depth</param>
        /// <param name="cancellationToken">The cancellcation token</param>
        /// <returns>The result of the operation</returns>
        private async Task <Engines.CollectionActionResult> ExecuteAsync <TCollection, TDocument, TMissing>(
            RecursiveExecutionEngine <TCollection, TDocument, TMissing> engine,
            Uri sourceUrl,
            SelectionResult sourceSelectionResult,
            TCollection parentCollection,
            ITarget targetItem,
            DepthHeader depth,
            CancellationToken cancellationToken)
            where TCollection : class, ICollectionTarget <TCollection, TDocument, TMissing>
            where TDocument : class, IDocumentTarget <TCollection, TDocument, TMissing>
            where TMissing : class, IMissingTarget <TCollection, TDocument, TMissing>
        {
            Debug.Assert(sourceSelectionResult.Collection != null, "sourceSelectionResult.Collection != null");

            if (Logger.IsEnabled(LogLevel.Trace))
            {
                Logger.LogTrace($"Copy or move from {sourceUrl} to {targetItem.DestinationUrl}");
            }

            if (sourceSelectionResult.ResultType == SelectionResultType.FoundDocument)
            {
                ActionResult docResult;
                if (targetItem is TCollection)
                {
                    // Cannot overwrite collection with document
                    docResult = new ActionResult(ActionStatus.OverwriteFailed, targetItem);
                }
                else if (targetItem is TMissing)
                {
                    var target = (TMissing)targetItem;
                    docResult = await engine.ExecuteAsync(
                        sourceUrl,
                        sourceSelectionResult.Document,
                        target,
                        cancellationToken);
                }
                else
                {
                    var target = (TDocument)targetItem;
                    docResult = await engine.ExecuteAsync(
                        sourceUrl,
                        sourceSelectionResult.Document,
                        target,
                        cancellationToken);
                }

                var engineResult = new Engines.CollectionActionResult(ActionStatus.Ignored, parentCollection)
                {
                    DocumentActionResults = new[] { docResult },
                };

                return(engineResult);
            }

            Engines.CollectionActionResult collResult;
            if (targetItem is TDocument)
            {
                // Cannot overwrite document with collection
                collResult = new Engines.CollectionActionResult(ActionStatus.OverwriteFailed, targetItem);
            }
            else if (targetItem is TMissing)
            {
                var target = (TMissing)targetItem;
                collResult = await engine.ExecuteAsync(
                    sourceUrl,
                    sourceSelectionResult.Collection,
                    depth,
                    target,
                    cancellationToken);
            }
            else
            {
                var target = (TCollection)targetItem;
                collResult = await engine.ExecuteAsync(
                    sourceUrl,
                    sourceSelectionResult.Collection,
                    depth,
                    target,
                    cancellationToken);
            }

            return(collResult);
        }
コード例 #15
0
        private HttpStatusCode RecursiveCopyFolder(UUID agent_id, 
                                                   InventoryFolderBase source, 
                                                   InventoryFolderBase destinationParent, 
                                                   DepthHeader depth,
                                                   Dictionary<string, HttpStatusCode> status_values) 
        {
            InventoryFolderBase copyFolderBase = new InventoryFolderBase(UUID.Random(), source.Name,
                                                                         agent_id, 
                                                                         destinationParent.ID);

            if (m_InventoryService.AddFolder(copyFolderBase)) 
            {
                m_InventoryPropertyHandler.CopyProperties(agent_id, source,
                    "/inventory/" + agent_id.ToString() + "/" + NodeToPath(agent_id, copyFolderBase));

                InventoryCollection ic = m_InventoryService.GetFolderContent(agent_id, source.ID);
                if (depth == DepthHeader.Infinity) // copy folders
                {
                    foreach (InventoryFolderBase ifb in ic.Folders) { 
                        // create destination folder
                        HttpStatusCode status = RecursiveCopyFolder(agent_id, ifb, copyFolderBase, depth, status_values);
                        if (status == HttpStatusCode.OK) 
                        {
                            m_InventoryPropertyHandler.CopyProperties(agent_id, ifb,
                                "/inventory/" + agent_id.ToString() + "/" + NodeToPath(agent_id, copyFolderBase) + ifb.Name + "/");
                        }
                        status_values.Add(NodeToPath(agent_id, ifb), status);
                    }
                }
                // copy items
                foreach (InventoryItemBase iib in ic.Items) 
                {
                    HttpStatusCode status = CopyItem(agent_id, iib, copyFolderBase, iib.Name);
                    if (status == HttpStatusCode.Created) 
                    {
                        m_InventoryPropertyHandler.CopyProperties(agent_id, iib,
                            "/inventory/" + agent_id.ToString() + "/" + NodeToPath(agent_id, copyFolderBase) + iib.Name);
                    }
                    status_values.Add(NodeToPath(agent_id, iib), status);
                }
            }
            else 
            {   // Failed folder creation, so wont create subfolders or items for the folder either
                status_values.Add(NodeToPath(agent_id, copyFolderBase), HttpStatusCode.InternalServerError);
            }

            return HttpStatusCode.OK;
        }
コード例 #16
0
        IList<IWebDAVResource> PropFindHandler(string username, string path, DepthHeader depth)
        {
            string[] pathParts = path.Split('/');
            if (pathParts.Length >= 2 && pathParts[1] == "inventory")
            {
                List<IWebDAVResource> resources = new List<IWebDAVResource>();
                if (depth == DepthHeader.Zero)
                {
                    IWebDAVResource res = m_propertyMngr.GetResource(path);
                    resources.Add(res);
                    return resources;
                }
                else if (depth == DepthHeader.One)
                {
                    IWebDAVResource res = m_propertyMngr.GetResource(path);
                    resources.Add(res);
                    IList<AssetFolder> folders = m_assetFolderStrg.GetSubItems(path);
                    foreach (AssetFolder folder in folders)
                    {
                        if (!folder.ParentPath.EndsWith("/")) folder.ParentPath += "/";
                        string resourcePath = folder.ParentPath + folder.Name;
                        if (!(folder is AssetFolderItem))
                            resourcePath += "/";
                        IWebDAVResource folderProps = m_propertyMngr.GetResource(resourcePath);
                        if (folderProps != null)
                        {
                            resources.Add(folderProps);
                        }
                        else
                        {
                            //create new props, save them and add them to response
                            if (folder is AssetFolderItem)
                            {
                                AssetFolderItem item = (AssetFolderItem)folder;
                                AssetBase asset = m_scenes[0].AssetService.Get(item.AssetID.ToString());
                                string contentType = MimeTypeConverter.GetContentType((int)asset.Type);
                                WebDAVFile file = new WebDAVFile(resourcePath, contentType, asset.Data.Length,
                                    asset.Metadata.CreationDate, DateTime.Now, DateTime.Now, false, false);

                                //add asset id to custom properties
                                file.AddProperty(new WebDAVProperty("AssetID", "http://www.realxtend.org/", item.AssetID.ToString()));
                                m_propertyMngr.SaveResource(file);
                                resources.Add(file);
                            }
                            else
                            {
                                WebDAVFolder resource = new WebDAVFolder(resourcePath, DateTime.Now, DateTime.Now, DateTime.Now, false);
                                m_propertyMngr.SaveResource(resource);
                                resources.Add(resource);
                            }
                        }
                    }
                    return resources;
                }
                else if (depth == DepthHeader.Infinity)
                {
                    IWebDAVResource res = m_propertyMngr.GetResource(path);
                    resources.Add(res);
                    IList<AssetFolder> folders = m_assetFolderStrg.GetSubItems(path);
                    //get subitems until found all
                    foreach (AssetFolder folder in folders)
                    {
                        if (!folder.ParentPath.EndsWith("/")) folder.ParentPath += "/";
                        string resourcePath = folder.ParentPath + folder.Name;
                        if (!(folder is AssetFolderItem))
                            resourcePath += "/";
                        IWebDAVResource folderProps = m_propertyMngr.GetResource(resourcePath);
                        if (folderProps != null)
                        {
                            resources.Add(folderProps);
                        }
                        else
                        {
                            //create new props, save them and add them to response
                            if (folder is AssetFolderItem)
                            {
                                AssetFolderItem item = (AssetFolderItem)folder;
                                AssetBase asset = m_scenes[0].AssetService.Get(item.AssetID.ToString());
                                string contentType = MimeTypeConverter.GetContentType((int)asset.Type);
                                WebDAVFile file = new WebDAVFile(resourcePath, contentType, asset.Data.Length,
                                    asset.Metadata.CreationDate, DateTime.Now, DateTime.Now, false, false);

                                //add asset id to custom properties
                                file.AddProperty(new WebDAVProperty("AssetID", "http://www.realxtend.org/", item.AssetID.ToString()));
                                m_propertyMngr.SaveResource(file);
                                resources.Add(file);
                            }
                            else
                            {
                                WebDAVFolder resource = new WebDAVFolder(resourcePath, DateTime.Now, DateTime.Now, DateTime.Now, false);
                                m_propertyMngr.SaveResource(resource);
                                resources.Add(resource);
                            }
                        }
                    }
                    return resources;
                }
            }

            return null;
        }
コード例 #17
0
ファイル: WebDAVListener.cs プロジェクト: jonnenauha/ModreX
 internal HttpStatusCode OnCopyConnector(string username, Uri uri, string destination, DepthHeader depth, bool overwrite, string[] ifHeaders, out Dictionary<string, HttpStatusCode> multiStatusValues)
 {
     if (OnCopy != null)
     {
         return OnCopy(username, uri, destination, depth, overwrite, ifHeaders, out multiStatusValues);
     }
     multiStatusValues = null;
     return HttpStatusCode.Forbidden;
 }
コード例 #18
0
        private void RecursiveGetProperties(UUID agent_id, string path, InventoryFolderBase folder, ref List<IWebDAVResource> dav_entries, DepthHeader depth)
        {
            InventoryCollection ic = m_InventoryService.GetFolderContent(agent_id, folder.ID);

            foreach (InventoryFolderBase ifb in ic.Folders)
            {
                string resourcePath = CollectObjectProperties((InventoryNodeBase)ifb, ref dav_entries, path);
                if (depth == DepthHeader.Infinity)
                    RecursiveGetProperties(agent_id, resourcePath, (InventoryFolderBase)ifb, ref dav_entries, depth);
            }
            foreach (InventoryNodeBase iib in ic.Items)
            {
                //string itemPath;
                //if(path.EndsWith("/")){ itemPath = path.Substring(0, path.Length -1);} else { itemPath = path;}
                string resourcePath = CollectObjectProperties((InventoryNodeBase)iib, ref dav_entries, path);
            }
        }
コード例 #19
0
ファイル: WebDAVListener.cs プロジェクト: jonnenauha/ModreX
        internal IList<IWebDAVResource> OnPropFindConnector(string username, string path, DepthHeader depth)
        {
            if (OnPropFind != null)
            {
                try { return OnPropFind(username, path, depth); }
                catch (Exception ex)
                {
                    Console.WriteLine("Caught exception in OnPropFind callback: " + ex);
                }
            }

            return new List<IWebDAVResource>(0);
        }
コード例 #20
0
        public HttpStatusCode MoveCallback(string username, Uri uri, string destination, DepthHeader depth, bool overwrite, string[] ifHeaders, out Dictionary<string, HttpStatusCode> multiStatusValues)
        {
            string path = uri.LocalPath;
            Dictionary<string, WebDAVLockResponse> allLockedNodes;
            Dictionary<string, WebDAVLockResponse> lockedNodes = CheckAllLockedChildren(ifHeaders, path, out allLockedNodes);
            if (lockedNodes.Count != 0) 
            {
                multiStatusValues = new Dictionary<string, HttpStatusCode>();
                this.FailingDepsToMultiStatus(lockedNodes, ref multiStatusValues);
                return (HttpStatusCode)424; // failed dependency                
            }

            multiStatusValues = new Dictionary<string, HttpStatusCode>(); // empty status vals
            string parentPath = CheckParentPath(path);
            if (parentPath != null)
            {
                if (!CheckIfHeaders(ifHeaders, parentPath))
                {
                    multiStatusValues.Add(parentPath, (HttpStatusCode)423);
                    return (HttpStatusCode)424; //locked                    
                }
            }

            if (!lockedResources.ContainsKey(path) || !lockedResources.ContainsKey(path + "/"))
            {
                // update path to new value
                //WebDAVLockResponse resp = lockedResources[path];
                //lockedResources.Remove(path);
                string newPath = destination.Substring(destination.IndexOf("/" + m_SubDomain + "/"));
                //lockedResources.Add(newPath, resp);
                if(allLockedNodes.Count>0)
                {
                    //string newPath = destination.Substring(destination.IndexOf("/" + m_SubDomain + "/"));
                    this.SendAllChildrenNodeLocksToNewDestionation(allLockedNodes, path, newPath);
                }
                return m_WebDAVServerConnector.InventoryMoveHandler(username, uri, destination, depth, overwrite, 
                                                                            ifHeaders, out  multiStatusValues);

            }
            else
            {
                if (!CheckIfHeaders(ifHeaders, path))
                {
                    // update path to new value
                    WebDAVLockResponse resp = lockedResources[path];
                    lockedResources.Remove(path);
                    string newPath = destination.Substring(destination.IndexOf("/" + m_SubDomain + "/"));
                    lockedResources.Add(newPath, resp);
                    if (allLockedNodes.Count > 0)
                    {
                        this.SendAllChildrenNodeLocksToNewDestionation(allLockedNodes, path, newPath);
                    }
                    return m_WebDAVServerConnector.InventoryMoveHandler(username, uri, destination, depth, overwrite, ifHeaders, out  multiStatusValues);
                }
                multiStatusValues = new Dictionary<string, HttpStatusCode>(); // empty status vals
                return (HttpStatusCode)423; //locked
            }
        }