/// <inheritdoc /> public Task <IWebDavResult> PropPatchAsync(string path, propertyupdate request, CancellationToken cancellationToken) { if (_propPatchHandler == null) { throw new NotSupportedException(); } return(_propPatchHandler.PropPatchAsync(path, request, cancellationToken)); }
internal Task <IActionResult> QuearyManualControllerCall(HttpContext context, string filePath, IServiceProvider serviceProvider, CancellationToken ct = default(CancellationToken)) { switch (context.Request.Method.ToUpperInvariant()) { case "OPTIONS": return(QueryOptionsAsync(filePath, ct)); case "MKCOL": return(MkColAsync(filePath, ct)); case "GET": return(GetAsync(filePath, ct)); case "PUT": return(PutAsync(filePath, ct)); case "DELETE": return(DeleteAsync(filePath, ct)); case "PROPFIND": propfind request = null; return(PropFindAsync(filePath, request, ct)); case "PROPPATCH": propertyupdate propUp = null; return(PropPatchAsync(filePath, propUp, ct)); case "HEAD": return(HeadAsync(filePath, ct)); case "COPY": string copyDestination = context.Request.Headers["Destination"]; return(CopyAsync(filePath, copyDestination, ct)); case "MOVE": string moveDestination = context.Request.Headers["Destination"]; return(MoveAsync(filePath, moveDestination, ct)); case "LOCK": Stream body = context.Request.Body; MemoryStream mem = new MemoryStream(); body.CopyTo(mem); body.Dispose(); byte[] raw = mem.ToArray(); string json = Encoding.UTF8.GetString(raw); //? return(LockAsync(filePath, null, ct)); case "UNLOCK": string lockToken = context.Request.Headers["Lock-Token"]; return(this.UnlockAsync(filePath, lockToken)); default: return(null); } }
/// <inheritdoc /> public async Task <IWebDavResult> PropPatchAsync( string path, propertyupdate request, CancellationToken cancellationToken) { var selectionResult = await _fileSystem.SelectAsync(path, cancellationToken).ConfigureAwait(false); if (selectionResult.IsMissing) { if (_context.RequestHeaders.IfNoneMatch != null) { throw new WebDavException(WebDavStatusCode.PreconditionFailed); } throw new WebDavException(WebDavStatusCode.NotFound); } var targetEntry = selectionResult.TargetEntry; Debug.Assert(targetEntry != null, "targetEntry != null"); await _context.RequestHeaders .ValidateAsync(selectionResult.TargetEntry, cancellationToken).ConfigureAwait(false); var lockRequirements = new Lock( new Uri(path, UriKind.Relative), _context.PublicRelativeRequestUrl, false, new XElement(WebDavXml.Dav + "owner", _context.User.Identity.Name), LockAccessType.Write, LockShareMode.Shared, TimeoutHeader.Infinite); var lockManager = _fileSystem.LockManager; var tempLock = lockManager == null ? new ImplicitLock(true) : await lockManager.LockImplicitAsync( _fileSystem, _context.RequestHeaders.If?.Lists, lockRequirements, cancellationToken) .ConfigureAwait(false); if (!tempLock.IsSuccessful) { return(tempLock.CreateErrorResponse()); } try { var propertiesList = new List <IUntypedReadableProperty>(); using (var propEnum = targetEntry.GetProperties(_context.Dispatcher, returnInvalidProperties: true).GetEnumerator()) { while (await propEnum.MoveNext(cancellationToken).ConfigureAwait(false)) { propertiesList.Add(propEnum.Current); } } var properties = propertiesList.ToDictionary(x => x.Name); var changes = await ApplyChangesAsync(targetEntry, properties, request, cancellationToken).ConfigureAwait(false); var hasError = changes.Any(x => !x.IsSuccess); if (hasError) { changes = await RevertChangesAsync( targetEntry, changes, properties, cancellationToken) .ConfigureAwait(false); } else { var targetPropStore = targetEntry.FileSystem.PropertyStore; if (targetPropStore != null) { await targetPropStore.UpdateETagAsync(targetEntry, cancellationToken).ConfigureAwait(false); } var parent = targetEntry.Parent; while (parent != null) { var parentPropStore = parent.FileSystem.PropertyStore; if (parentPropStore != null) { await parentPropStore.UpdateETagAsync(parent, cancellationToken) .ConfigureAwait(false); } parent = parent.Parent; } } var statusCode = hasError ? WebDavStatusCode.Forbidden : WebDavStatusCode.MultiStatus; var propStats = new List <propstat>(); var readOnlyProperties = changes.Where(x => x.Status == ChangeStatus.ReadOnlyProperty).ToList(); if (readOnlyProperties.Count != 0) { propStats.AddRange( CreatePropStats( readOnlyProperties, new error() { ItemsElementName = new[] { ItemsChoiceType.cannotmodifyprotectedproperty, }, Items = new[] { new object(), }, })); changes = changes.Except(readOnlyProperties).ToList(); } propStats.AddRange(CreatePropStats(changes, null)); var status = new multistatus() { response = new[] { new response() { href = _context.PublicControllerUrl.Append(path, true).OriginalString, ItemsElementName = propStats.Select(x => ItemsChoiceType2.propstat).ToArray(), Items = propStats.Cast <object>().ToArray(), }, }, }; return(new WebDavResult <multistatus>(statusCode, status)); } finally { await tempLock.DisposeAsync(cancellationToken).ConfigureAwait(false); } }
private async Task <IReadOnlyCollection <ChangeItem> > ApplyChangesAsync([NotNull] IEntry entry, [NotNull] Dictionary <XName, IUntypedReadableProperty> properties, [NotNull] propertyupdate request, CancellationToken cancellationToken) { var result = new List <ChangeItem>(); if (request.Items == null) { return(result); } var failed = false; foreach (var item in request.Items) { IReadOnlyCollection <ChangeItem> changeItems; var set = item as propset; if (set != null) { changeItems = await ApplySetAsync(entry, properties, set, failed, cancellationToken).ConfigureAwait(false); } else if (item is propremove remove) { changeItems = await ApplyRemoveAsync(entry, properties, remove, failed, cancellationToken).ConfigureAwait(false); } else { changeItems = new ChangeItem[0]; } result.AddRange(changeItems); failed = failed || changeItems.Any(x => !x.IsSuccess); } return(result); }
public async Task <IActionResult> PropPatchAsync(string path, [FromBody] propertyupdate request, CancellationToken cancellationToken) { var result = await _dispatcher.Class1.PropPatchAsync(path ?? string.Empty, request, cancellationToken).ConfigureAwait(false); return(new WebDavIndirectResult(_dispatcher, result, _responseLogger)); }
private async Task <IReadOnlyCollection <XName> > SetPropertiesAsync([NotNull] Uri targetUrl, [NotNull][ItemNotNull] IEnumerable <IUntypedWriteableProperty> properties, CancellationToken cancellationToken) { var elements = new List <XElement>(); foreach (var property in properties) { var element = await property.GetXmlValueAsync(cancellationToken).ConfigureAwait(false); var deadProp = property as IDeadProperty; if (deadProp == null || !deadProp.IsDefaultValue(element)) { elements.Add(element); } } var requestData = new propertyupdate() { Items = new object[] { new propset() { prop = new prop() { Any = elements.ToArray(), }, }, }, }; multistatus result; using (var httpRequest = new HttpRequestMessage(_propPatchHttpMethod, targetUrl) { Content = CreateContent(_propertyUpdateSerializer, requestData), }) { using (var httpResponse = await Client.SendAsync(httpRequest, cancellationToken).ConfigureAwait(false)) { if (httpResponse.IsSuccessStatusCode) { return(new XName[0]); } var resultDoc = await ReadResponseAsync(httpResponse).ConfigureAwait(false); if (resultDoc == null) { throw new RemoteTargetException("The destination server didn't return a response", targetUrl); } result = Parse(targetUrl, httpResponse, resultDoc); } } if (result.response == null || result.response.Length == 0) { throw new RemoteTargetException("The destination server didn't return a response", targetUrl); } if (result.response.Length != 1) { throw new RemoteTargetException("Received more than one multi-status response", targetUrl); } var response = result.response[0]; var hrefs = response.GetHrefs().Select(x => new Uri(x, UriKind.RelativeOrAbsolute)).ToList(); if (hrefs.Count == 0) { hrefs.Add(targetUrl); } var statusIndex = Array.IndexOf(response.ItemsElementName, ItemsChoiceType2.status); var isFailure = response.error != null; if (statusIndex != -1 && !isFailure) { var responseStatus = Status.Parse((string)response.Items[statusIndex]); isFailure = !responseStatus.IsSuccessStatusCode; } var hasFailedPropStats = false; var failedProperties = new List <XName>(); foreach (var propstat in response.Items.OfType <propstat>()) { var propStatIsFailure = isFailure || propstat.error != null || (!string.IsNullOrEmpty(propstat.status) && !Status.Parse(propstat.status).IsSuccessStatusCode); hasFailedPropStats |= propStatIsFailure; if (propStatIsFailure && propstat.prop?.Any != null) { foreach (var element in propstat.prop.Any) { failedProperties.Add(element.Name); } } } if (failedProperties.Count == 0 && (isFailure || hasFailedPropStats)) { throw new RemoteTargetException("Failed properties were not returned by the server."); } return(failedProperties); }