Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various improvements, mostly having to do with large files. #22

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
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
675 changes: 675 additions & 0 deletions LICENSE.md

Large diffs are not rendered by default.

Binary file modified Reference/winfsp-msil.dll
Binary file not shown.
10 changes: 10 additions & 0 deletions Reference/winfsp-msil.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

318 changes: 271 additions & 47 deletions WebDAVClient/Client.cs

Large diffs are not rendered by default.

5 changes: 0 additions & 5 deletions WebDAVClient/Helpers/ResponseParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,6 @@ public static IEnumerable<Item> ParseItems(Stream stream)
case "version-controlled-configuration":
reader.Skip();
break;
default:
{
//int a = 0;
break;
}
}
}
else if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName.ToLower() == "response")
Expand Down
27 changes: 27 additions & 0 deletions WebDAVClient/HttpClient/HttpClientWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Net.Http;
using System.Threading.Tasks;

namespace WebDAVClient.HttpClient
{
public class HttpClientWrapper : IHttpClientWrapper
{
private readonly System.Net.Http.HttpClient _httpClient;
private readonly System.Net.Http.HttpClient _uploadHttpClient;

public HttpClientWrapper(System.Net.Http.HttpClient httpClient, System.Net.Http.HttpClient uploadHttpClient)
{
_httpClient = httpClient;
_uploadHttpClient = uploadHttpClient;
}

public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption responseHeadersRead)
{
return _httpClient.SendAsync(request, responseHeadersRead);
}

public Task<HttpResponseMessage> SendUploadAsync(HttpRequestMessage request)
{
return _uploadHttpClient.SendAsync(request);
}
}
}
11 changes: 11 additions & 0 deletions WebDAVClient/HttpClient/IHttpClientWrapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Net.Http;
using System.Threading.Tasks;

namespace WebDAVClient.HttpClient
{
public interface IHttpClientWrapper
{
Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption responseHeadersRead);
Task<HttpResponseMessage> SendUploadAsync(HttpRequestMessage request);
}
}
40 changes: 38 additions & 2 deletions WebDAVClient/IClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ public interface IClient
/// </summary>
string UserAgentVersion { get; set; }

/// <summary>
/// Specify additional headers to be sent with every request
/// </summary>
ICollection<KeyValuePair<string, string>> CustomHeaders { get; set; }

/// <summary>
/// List all files present on the server.
Expand All @@ -56,16 +60,34 @@ public interface IClient
/// Download a file from the server
/// </summary>
/// <param name="remoteFilePath">Source path and filename of the file on the server</param>
Task<byte[]> Download(string remoteFilePath);
Task<Stream> Download(string remoteFilePath);

/// <summary>
/// Download a file from the server
/// Download a part of file from the server
/// </summary>
/// <param name="remoteFilePath">Source path and filename of the file on the server</param>
/// <param name="startBytes">Start bytes of content</param>
/// <param name="endBytes">End bytes of content</param>
Task<Stream> DownloadPartial(string remoteFilePath, long startBytes, long endBytes);

/// <summary>
/// Upload a file to the server
/// </summary>
/// <param name="remoteFilePath">Source path and filename of the file on the server</param>
/// <param name="content"></param>
/// <param name="name"></param>
Task<bool> Upload(string remoteFilePath, Stream content, string name);

/// <summary>
/// Upload a part of a file to the server.
/// </summary>
/// <param name="remoteFilePath">Target path excluding the servername and base path</param>
/// <param name="content">The content to upload. Must match the length of <paramref name="endBytes"/> minus <paramref name="startBytes"/></param>
/// <param name="name">The target filename. The file must exist on the server</param>
/// <param name="startBytes">StartByte on the target file</param>
/// <param name="endBytes">EndByte on the target file</param>
Task<bool> UploadPartial(string remoteFilePath, Stream content, string name, long startBytes, long? endBytes);

/// <summary>
/// Create a directory on the server
/// </summary>
Expand Down Expand Up @@ -98,5 +120,19 @@ public interface IClient
/// <param name="srcFilePath">Source path and filename of the file on the server</param>
/// <param name="dstFilePath">Destination path and filename of the file on the server</param>
Task<bool> MoveFile(string srcFilePath, string dstFilePath);

/// <summary>
/// Copies a file on the server
/// </summary>
/// <param name="srcFilePath">Source path and filename of the file on the server</param>
/// <param name="dstFilePath">Destination path and filename of the file on the server</param>
Task<bool> CopyFile(string srcFilePath, string dstFilePath);

/// <summary>
/// Copies a folder on the server
/// </summary>
/// <param name="srcFolderPath">Source path of the folder on the server</param>
/// <param name="dstFolderPath">Destination path of the folder on the server</param>
Task<bool> CopyFolder(string srcFolderPath, string dstFolderPath);
}
}
4 changes: 2 additions & 2 deletions WebDAVClient/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.1.2.0")]
[assembly: AssemblyFileVersion("1.1.2.0")]
[assembly: AssemblyVersion("1.1.4.0")]
[assembly: AssemblyFileVersion("1.1.4.0")]
2 changes: 2 additions & 0 deletions WebDAVClient/WebDAVClient.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@
<ItemGroup>
<Compile Include="Helpers\ResponseParser.cs" />
<Compile Include="Helpers\WebDAVConflictException.cs" />
<Compile Include="HttpClient\HttpClientWrapper.cs" />
<Compile Include="IClient.cs" />
<Compile Include="HttpClient\IHttpClientWrapper.cs" />
<Compile Include="Model\Item.cs" />
<Compile Include="Client.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand Down
2 changes: 1 addition & 1 deletion src/About/About.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<List MarkerStyle="Box" >
<ListItem>
<Paragraph TextAlignment="Left" FontSize="14">
<Hyperlink NavigateUri="https://github.com/billziss-gh/winfsp/releases" RequestNavigate="Hyperlink_RequestNavigate">Install the 2018.2 B2 release of WinFSP or superior</Hyperlink>
<Hyperlink NavigateUri="https://github.com/billziss-gh/winfsp/releases" RequestNavigate="Hyperlink_RequestNavigate">Install the 2019.3 B1 release of WinFSP or superior</Hyperlink>
</Paragraph>

</ListItem>
Expand Down
79 changes: 77 additions & 2 deletions src/FS/FileNode.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
using Fsp.Interop;
using Newtonsoft.Json;
using System;
using System.IO.Pipes;
using System.Security.AccessControl;
using System.Threading;
using System.Threading.Tasks;
using System.Web;

namespace KS2Drive.FS
Expand Down Expand Up @@ -37,6 +40,10 @@ public class FileNode
private static String _DocumentLibraryPath;
private static WebDAVMode _WebDAVMode;

private AnonymousPipeServerStream UploadStream = null;
private UInt64 UploadOffset;
private Task<bool> UploadTask = null;

private static bool _IsInited = false;

public static void Init(String DocumentLibraryPath, WebDAVMode webDavMode)
Expand Down Expand Up @@ -66,6 +73,7 @@ public FileNode(WebDAVClient.Model.Item WebDavObject)
{
this.RepositoryPath = WebDavObject.Href;
}
this.RepositoryPath = this.RepositoryPath.Replace("//", "/");

this.LocalPath = HttpUtility.UrlDecode(ConvertRepositoryPathToLocalPath(this.RepositoryPath));

Expand Down Expand Up @@ -105,11 +113,78 @@ public FileNode(WebDAVClient.Model.Item WebDavObject)
this.FileSecurity = GetDefaultSecurity();
}

public FileNode(String Path)
{
if (!FileNode._IsInited) throw new InvalidOperationException("Please Call Init First");

lock (_handlelock)
{
this.ObjectId = (++ObjetIdSequence).ToString();
}

this.LastRefresh = DateTime.Now;

this.LocalPath = Path;
this.RepositoryPath = ConvertLocalPathToRepositoryPath(Path);
this.Name = GetRepositoryDocumentName(this.RepositoryPath);

this.FileInfo.FileAttributes = (UInt32)System.IO.FileAttributes.Normal;

this.FileSecurity = GetDefaultSecurity();
}

public bool PendingUpload(UInt64 Offset)
{
return (UploadStream != null && UploadOffset < Offset);
}

public bool FlushUpload()
{
if (UploadStream != null)
{
UploadStream.Close();
bool result = UploadTask.GetAwaiter().GetResult();
UploadStream = null;
UploadTask = null;
return result;
}
return false;
}

public void Upload(byte[] Data, UInt64 Offset, UInt32 Length)
{
if (UploadStream != null && UploadOffset != Offset)
{
FlushUpload();
}
if (UploadStream == null)
{
UploadStream = new AnonymousPipeServerStream();
UploadOffset = Offset;
var Proxy = new WebDavClient2(Timeout.InfiniteTimeSpan);
var PipeStream = new AnonymousPipeClientStream(PipeDirection.In, UploadStream.ClientSafePipeHandle);
if (UploadOffset == 0)
{
UploadTask = Proxy.Upload(GetRepositoryParentPath(RepositoryPath), PipeStream, Name);
}
else
{
UploadTask = Proxy.UploadPartial(GetRepositoryParentPath(RepositoryPath), PipeStream, Name, (long)UploadOffset);
}
}
if (Data != null)
{
UploadStream.Write(Data, 0, (int)Length);
UploadOffset += Length;
}
}

public static String ConvertRepositoryPathToLocalPath(String CMISPath)
{
if (CMISPath.EndsWith("/")) CMISPath = CMISPath.Substring(0, CMISPath.Length - 1);

String ReworkdPath = CMISPath.Replace(_DocumentLibraryPath, "").Replace('/', System.IO.Path.DirectorySeparatorChar);
if (!_DocumentLibraryPath.Equals("")) CMISPath = CMISPath.Replace(_DocumentLibraryPath, "");
String ReworkdPath = CMISPath.Replace('/', System.IO.Path.DirectorySeparatorChar);
if (!ReworkdPath.StartsWith(System.IO.Path.DirectorySeparatorChar.ToString())) ReworkdPath = System.IO.Path.DirectorySeparatorChar + ReworkdPath;
return ReworkdPath;
}
Expand Down Expand Up @@ -183,7 +258,7 @@ internal static String GetRepositoryParentPath(String DocumentPath)
{
if (DocumentPath.EndsWith("/")) DocumentPath = DocumentPath.Substring(0, DocumentPath.Length - 1);

if (DocumentPath.Equals(_DocumentLibraryPath)) return null;
if (DocumentPath.Equals(_DocumentLibraryPath)) return "";
if (DocumentPath.Length < _DocumentLibraryPath.Length) return null;
return DocumentPath.Substring(0, DocumentPath.LastIndexOf('/'));
}
Expand Down
26 changes: 24 additions & 2 deletions src/FS/WebDavClient2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,26 @@ private String ParameterConvert(String input)
return base.DeleteFolder(remotePath);
}

public new Task<Byte[]> Download(string remotePath)
public new async Task<byte[]> Download(string remotePath)
{
remotePath = ParameterConvert(remotePath);
return base.Download(remotePath);
Stream s = await base.Download(remotePath);
using (MemoryStream MS = new MemoryStream())
{
await s.CopyToAsync(MS);
return MS.ToArray();
}
}

public new async Task<byte[]> DownloadPartial(string remotePath, long startBytes, long endBytes)
{
remotePath = ParameterConvert(remotePath);
Stream s = await base.DownloadPartial(remotePath, startBytes, endBytes);
using (MemoryStream MS = new MemoryStream())
{
await s.CopyToAsync(MS);
return MS.ToArray();
}
}

public new Task<WebDAVClient.Model.Item> GetFile(string remotePath = "/")
Expand Down Expand Up @@ -105,6 +121,12 @@ private String ParameterConvert(String input)
return base.Upload(remoteFilePath, content, name);
}

public new Task<bool> UploadPartial(string remoteFilePath, Stream content, string name, long startBytes, long? endBytes = null)
{
remoteFilePath = ParameterConvert(remoteFilePath);
return base.UploadPartial(remoteFilePath, content, name, startBytes, endBytes);
}

/// <summary>
/// Retrieve a file or folder from the remote repository
/// Return either a RepositoryElement or a FileSystem Error Message
Expand Down
Loading