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) ); }
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) ); }
/// <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())); }
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(); }
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); }
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; }
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; }
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; }
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); }
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; }
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; } }
/// <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)); }
/// <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); }
/// <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); }
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; }
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; }
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; }
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); } }
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); }
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 } }