/// <summary> /// Locks a file or directory at the URL specified. /// </summary> /// <param name="uri">The URI of the file or directory to lock.</param> /// <returns>The <see cref="Task"/> representing the asynchronous operation.</returns> public async Task <bool> LockAsync(Uri uri) { uri = UriHelper.GetCombinedUriWithTrailingSlash(this.BaseUri, uri, true, false); if (this.permanentLocks.ContainsKey(uri)) { return(true); // Lock already set. } var lockInfo = new LockInfo(); lockInfo.LockScope = LockScope.CreateExclusiveLockScope(); lockInfo.LockType = LockType.CreateWriteLockType(); var response = await this.webDavClient.LockAsync(uri, WebDavTimeoutHeaderValue.CreateInfiniteWebDavTimeout(), WebDavDepthHeaderValue.Infinity, lockInfo); if (!response.IsSuccessStatusCode) { return(false); // Lock already exists. } var lockToken = WebDavHelper.GetLockTokenFromWebDavResponseMessage(response); var prop = await WebDavResponseContentParser.ParsePropResponseContentAsync(response.Content); var lockDiscovery = prop.LockDiscovery; if (lockDiscovery == null) { return(false); } var url = uri.ToString(); var lockGranted = lockDiscovery.ActiveLock.FirstOrDefault(x => url.EndsWith(UriHelper.AddTrailingSlash(x.LockRoot.Href, false), StringComparison.OrdinalIgnoreCase)); if (lockGranted == null) { // Try with file expected. lockGranted = lockDiscovery.ActiveLock.FirstOrDefault(x => url.EndsWith(UriHelper.AddTrailingSlash(x.LockRoot.Href, true), StringComparison.OrdinalIgnoreCase)); } if (lockGranted == null) { return(false); } var permanentLock = new PermanentLock(this.webDavClient, lockToken, uri, lockGranted.Timeout); if (!this.permanentLocks.TryAdd(uri, permanentLock)) { throw new WebDavException("Lock with lock root " + uri.ToString() + " already exists."); } return(response.IsSuccessStatusCode); }
/// <summary> /// Gets a <see cref="LockToken"/> from a <see cref="WebDavResponseMessage"/>. /// </summary> /// <param name="responseMessage">The <see cref="WebDavResponseMessage"/> whose <see cref="LockToken"/> should be retrieved.</param> /// <returns>The <see cref="LockToken"/> of the <see cref="WebDavResponseMessage"/> or null if the WebDavResponseMessage does not contain a lock token.</returns> public static LockToken GetLockTokenFromWebDavResponseMessage(WebDavResponseMessage responseMessage) { // Try to get lock token from response header. if (responseMessage.Headers.TryGetValues(WebDavRequestHeader.LockTocken, out IEnumerable <string> lockTokenHeaderValues)) { var lockTokenHeaderValue = lockTokenHeaderValues.FirstOrDefault(); if (lockTokenHeaderValue != null) { return(new LockToken(lockTokenHeaderValue)); } } // If lock token was not submitted by response header, it should be found in the response content. try { var prop = WebDavResponseContentParser.ParsePropResponseContentAsync(responseMessage.Content).Result; return(new LockToken(prop.LockDiscovery.ActiveLock[0].LockToken.Href)); } catch (Exception) { return(null); } }
/// <summary> /// Retrieves a list of files and directories of the directory at the <see cref="Uri"/> specified using the <see cref="PropFind"/> specified. /// </summary> /// <param name="uri">The <see cref="Uri"/> of the directory which content should be listed. Has to be an absolute URI (including the base URI) or a relative URI (relative to base URI).</param> /// <param name="propFind">The <see cref="PropFind"/> to use. Different PropFind types can be created using the static methods of the class <see cref="PropFind"/>.</param> /// <returns>The <see cref="Task"/> representing the asynchronous operation.</returns> public async Task <IList <WebDavSessionListItem> > ListAsync(Uri uri, PropFind propFind) { if (propFind == null) { throw new ArgumentException("Argument propFind must not be null."); } uri = UriHelper.GetCombinedUriWithTrailingSlash(this.BaseUri, uri, true, false); var response = await this.webDavClient.PropFindAsync(uri, WebDavDepthHeaderValue.One, propFind); // Remember the original port to include it in the hrefs later. var port = UriHelper.GetPort(uri); if (response.StatusCode != WebDavStatusCode.MultiStatus) { throw new WebDavException(string.Format("Error while executing ListAsync (wrong response status code). Expected status code: 207 (MultiStatus); actual status code: {0} ({1})", (int)response.StatusCode, response.StatusCode)); } var multistatus = await WebDavResponseContentParser.ParseMultistatusResponseContentAsync(response.Content); var itemList = new List <WebDavSessionListItem>(); foreach (var responseItem in multistatus.Response) { var webDavSessionItem = new WebDavSessionListItem(); Uri href = null; if (!string.IsNullOrEmpty(responseItem.Href)) { if (Uri.TryCreate(responseItem.Href, UriKind.RelativeOrAbsolute, out href)) { var fullQualifiedUri = UriHelper.CombineUri(uri, href, true); fullQualifiedUri = UriHelper.SetPort(fullQualifiedUri, port); webDavSessionItem.Uri = fullQualifiedUri; } } // Skip the folder which contents were requested, only add children. if (href != null && WebUtility.UrlDecode(UriHelper.RemovePort(uri).ToString().Trim('/')).EndsWith(WebUtility.UrlDecode(UriHelper.RemovePort(href).ToString().Trim('/')), StringComparison.OrdinalIgnoreCase)) { continue; } foreach (var item in responseItem.Items) { var propStat = item as Propstat; // Do not items where no properties could be found. if (propStat == null || propStat.Status.ToLower().Contains("404 not found")) { continue; } // Do not add hidden items. if (!string.IsNullOrEmpty(propStat.Prop.IsHidden) && propStat.Prop.IsHidden.Equals("1")) { continue; } webDavSessionItem.ContentClass = propStat.Prop.ContentClass; webDavSessionItem.ContentLanguage = propStat.Prop.GetContentLanguage; if (!string.IsNullOrEmpty(propStat.Prop.GetContentLength)) { webDavSessionItem.ContentLength = long.Parse(propStat.Prop.GetContentLength, CultureInfo.InvariantCulture); } webDavSessionItem.ContentType = propStat.Prop.GetContentType; if (propStat.Prop.CreationDateSpecified && !string.IsNullOrEmpty(propStat.Prop.CreationDate)) { webDavSessionItem.CreationDate = DateTime.Parse(propStat.Prop.CreationDate, CultureInfo.InvariantCulture); } webDavSessionItem.DefaultDocument = propStat.Prop.DefaultDocument; webDavSessionItem.DisplayName = propStat.Prop.DisplayName; webDavSessionItem.ETag = propStat.Prop.GetEtag; if (!string.IsNullOrEmpty(propStat.Prop.GetLastModified)) { webDavSessionItem.LastModified = DateTime.Parse(propStat.Prop.GetLastModified, CultureInfo.InvariantCulture); } if (!string.IsNullOrEmpty(propStat.Prop.IsReadonly)) { webDavSessionItem.IsReadonly = propStat.Prop.IsReadonly.Equals("1"); } if (!string.IsNullOrEmpty(propStat.Prop.IsRoot)) { webDavSessionItem.IsRoot = propStat.Prop.IsRoot.Equals("1"); } if (!string.IsNullOrEmpty(propStat.Prop.IsStructuredDocument)) { webDavSessionItem.IsStructuredDocument = propStat.Prop.IsStructuredDocument.Equals("1"); } if (!string.IsNullOrEmpty(propStat.Prop.LastAccessed)) { webDavSessionItem.LastAccessed = DateTime.Parse(propStat.Prop.LastAccessed, CultureInfo.InvariantCulture); } webDavSessionItem.Name = propStat.Prop.Name; webDavSessionItem.ParentName = propStat.Prop.ParentName; if (!string.IsNullOrEmpty(propStat.Prop.QuotaAvailableBytes)) { webDavSessionItem.QuotaAvailableBytes = long.Parse(propStat.Prop.QuotaAvailableBytes, CultureInfo.InvariantCulture); } if (!string.IsNullOrEmpty(propStat.Prop.QuotaUsedBytes)) { webDavSessionItem.QuotaUsedBytes = long.Parse(propStat.Prop.QuotaUsedBytes, CultureInfo.InvariantCulture); } // Make sure that the IsDirectory property is set if it's a directory. if (!string.IsNullOrEmpty(propStat.Prop.IsCollection)) { webDavSessionItem.IsCollection = propStat.Prop.IsCollection.Equals("1"); } else if (propStat.Prop.ResourceType != null && propStat.Prop.ResourceType.Collection != null) { webDavSessionItem.IsCollection = true; } // Make sure that the name property is set. // Naming priority: // 1. displayname (only if it doesn't contain raw unicode, otherwise there are problems with non western characters) // 2. name // 3. (part of) URI. if (!TextHelper.StringContainsRawUnicode(propStat.Prop.DisplayName)) { webDavSessionItem.Name = propStat.Prop.DisplayName; } if (string.IsNullOrEmpty(webDavSessionItem.Name)) { webDavSessionItem.Name = propStat.Prop.Name; } if (string.IsNullOrEmpty(webDavSessionItem.Name) && href != null) { webDavSessionItem.Name = WebUtility.UrlDecode(href.ToString().Split('/').Last(x => !string.IsNullOrEmpty(x))); } } itemList.Add(webDavSessionItem); } return(itemList); }