Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 61 additions & 59 deletions WebDAVClient/Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Net.Http.Headers;
using System.Net.Security;
using System.Text;
using System.Threading;
using System.Threading;
using System.Threading.Tasks;
using WebDAVClient.Helpers;
using WebDAVClient.HttpClient;
Expand Down Expand Up @@ -45,12 +45,12 @@ public class Client : IClient
"</propfind>";
private static readonly byte[] s_propFindRequestContentBytes = Encoding.UTF8.GetBytes(c_propFindRequestContent);

private IHttpClientWrapper m_httpClientWrapper;
private readonly bool m_shouldDispose;
private IHttpClientWrapper m_httpClientWrapper;
private readonly bool m_shouldDispose;
private string m_server;
private string m_basePath = "/";
private string m_encodedBasePath;
private bool m_disposedValue;
private bool m_disposedValue;

#region WebDAV connection parameters

Expand Down Expand Up @@ -107,13 +107,14 @@ public string BasePath
/// Specify the certificates validation logic
/// </summary>
public RemoteCertificateValidationCallback ServerCertificateValidationCallback { get; set; }

#endregion

public Client(NetworkCredential credential = null, TimeSpan? uploadTimeout = null, IWebProxy proxy = null)
{
var handler = new HttpClientHandler();
if (proxy != null && handler.SupportsProxy)
{
{
handler.Proxy = proxy;
}
if (handler.SupportsAutomaticDecompression)
Expand All @@ -129,6 +130,7 @@ public Client(NetworkCredential credential = null, TimeSpan? uploadTimeout = nul
{
handler.UseDefaultCredentials = true;
}
handler.ServerCertificateCustomValidationCallback = ServerCertificateValidation;

var client = new System.Net.Http.HttpClient(handler, disposeHandler: true);
client.DefaultRequestHeaders.ExpectContinue = false;
Expand Down Expand Up @@ -228,7 +230,7 @@ public async Task<IEnumerable<Item>> List(string path = "/", int? depth = 1, Can
}
finally
{
response?.Dispose();
response?.Dispose();
}
}

Expand Down Expand Up @@ -260,8 +262,8 @@ public async Task<Item> GetFile(string path = "/", CancellationToken cancellatio
public Task<Stream> Download(string remoteFilePath, CancellationToken cancellationToken = default)
{
var headers = new Dictionary<string, string>(1 + (CustomHeaders?.Count ?? 0))
{
{ "translate", "f" }
{
{ "translate", "f" }
};
if (CustomHeaders != null)
{
Expand Down Expand Up @@ -527,11 +529,11 @@ private async Task Delete(Uri listUri, CancellationToken cancellationToken = def
private async Task<Item> Get(Uri listUri, CancellationToken cancellationToken = default)
{
// Depth header: http://webdav.org/specs/rfc4918.html#rfc.section.9.1.4
IDictionary<string, string> headers = new Dictionary<string, string>(1 + (CustomHeaders?.Count ?? 0))
{
{ "Depth", "0" }
};
IDictionary<string, string> headers = new Dictionary<string, string>(1 + (CustomHeaders?.Count ?? 0))
{
{ "Depth", "0" }
};

if (CustomHeaders != null)
{
foreach (var keyValuePair in CustomHeaders)
Expand Down Expand Up @@ -566,19 +568,19 @@ private async Task<Item> Get(Uri listUri, CancellationToken cancellationToken =
}
finally
{
response?.Dispose();
response?.Dispose();
}
}

private async Task<bool> Move(Uri srcUri, Uri dstUri, CancellationToken cancellationToken = default)
{
const string requestContent = "MOVE";

IDictionary<string, string> headers = new Dictionary<string, string>(1 + (CustomHeaders?.Count ?? 0))
{
{ "Destination", dstUri.ToString() }
};
IDictionary<string, string> headers = new Dictionary<string, string>(1 + (CustomHeaders?.Count ?? 0))
{
{ "Destination", dstUri.ToString() }
};

if (CustomHeaders != null)
{
foreach (var keyValuePair in CustomHeaders)
Expand All @@ -602,9 +604,9 @@ private async Task<bool> Copy(Uri srcUri, Uri dstUri, CancellationToken cancella
{
const string requestContent = "COPY";

IDictionary<string, string> headers = new Dictionary<string, string>(1 + (CustomHeaders?.Count ?? 0))
{
{ "Destination", dstUri.ToString() }
IDictionary<string, string> headers = new Dictionary<string, string>(1 + (CustomHeaders?.Count ?? 0))
{
{ "Destination", dstUri.ToString() }
};

if (CustomHeaders != null)
Expand Down Expand Up @@ -741,9 +743,9 @@ private async Task<UriBuilder> GetServerUrl(string path, bool appendTrailingSlas
{
Path = m_basePath
};
if (Port != null)
if (Port != null)
{
baseUri.Port = (int)Port;
baseUri.Port = (int)Port;
}
var root = await Get(baseUri.Uri).ConfigureAwait(false);

Expand All @@ -762,11 +764,11 @@ private async Task<UriBuilder> GetServerUrl(string path, bool appendTrailingSlas
// Otherwise, use the resolved base path relatively to the server
var baseUri = new UriBuilder(m_server)
{
Path = m_encodedBasePath
Path = m_encodedBasePath
};
if (Port != null)
if (Port != null)
{
baseUri.Port = (int)Port;
baseUri.Port = (int)Port;
}
return baseUri;
}
Expand Down Expand Up @@ -794,7 +796,7 @@ private async Task<UriBuilder> GetServerUrl(string path, bool appendTrailingSlas
baseUri = new UriBuilder(m_server);
if (Port!= null)
{
baseUri.Port = (int)Port;
baseUri.Port = (int)Port;
}

// Ensure we don't add the base path twice
Expand All @@ -807,8 +809,8 @@ private async Task<UriBuilder> GetServerUrl(string path, bool appendTrailingSlas
finalPath = finalPath.TrimEnd('/') + "/";

baseUri.Path = finalPath;
}
}

return baseUri;
}
}
Expand All @@ -819,43 +821,43 @@ private async Task<UriBuilder> GetServerUrl(string path, bool appendTrailingSlas

#region WebDAV Connection Helpers

public bool ServerCertificateValidation(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certification, System.Security.Cryptography.X509Certificates.X509Chain chain, SslPolicyErrors sslPolicyErrors)
public bool ServerCertificateValidation(HttpRequestMessage requestMessage, System.Security.Cryptography.X509Certificates.X509Certificate certification, System.Security.Cryptography.X509Certificates.X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (ServerCertificateValidationCallback != null)
{
return ServerCertificateValidationCallback(sender, certification, chain, sslPolicyErrors);
return ServerCertificateValidationCallback(requestMessage, certification, chain, sslPolicyErrors);
}
return false;
return sslPolicyErrors == SslPolicyErrors.None;
}
#endregion

#region IDisposable methods
protected virtual void Dispose(bool disposing)
{
if (!m_disposedValue)
{
if (disposing)
{
if (m_shouldDispose)
{
if (m_httpClientWrapper is IDisposable httpClientWrapperDisposable)
{
httpClientWrapperDisposable.Dispose();
m_httpClientWrapper = null;
}
}
}
m_disposedValue = true;
}
}
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!m_disposedValue)
{
if (disposing)
{
if (m_shouldDispose)
{
if (m_httpClientWrapper is IDisposable httpClientWrapperDisposable)
{
httpClientWrapperDisposable.Dispose();
m_httpClientWrapper = null;
}
}
}

m_disposedValue = true;
}
}

public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
#endregion
}
}
6 changes: 6 additions & 0 deletions WebDAVClient/IClient.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Security;
using System.Threading;
using System.Threading.Tasks;
using WebDAVClient.Model;
Expand Down Expand Up @@ -39,6 +40,11 @@ public interface IClient : IDisposable
/// </summary>
ICollection<KeyValuePair<string, string>> CustomHeaders { get; set; }

/// <summary>
/// Specify the certificates validation logic
/// </summary>
RemoteCertificateValidationCallback ServerCertificateValidationCallback { get; set; }

/// <summary>
/// List all files present on the server.
/// </summary>
Expand Down