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

chore: protect get bytes method #10

Merged
merged 1 commit into from
Apr 19, 2023
Merged
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
72 changes: 46 additions & 26 deletions src/TusDotNetClient/TusClient.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TusDotNetClient
namespace TusDotNetClient
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

/// <summary>
/// Represents the different hashing algorithm implementations supported by <see cref="TusClient"/>
/// </summary>
Expand Down Expand Up @@ -91,23 +91,30 @@ public async Task<string> CreateAsync(string url, long uploadLength,
{
request.AddHeader(TusHeaderNames.UploadMetadata, string.Join(",", metadata
.Select(md =>
$"{md.key.Replace(" ", "").Replace(",", "")} {Convert.ToBase64String(Encoding.UTF8.GetBytes(md.value))}")));
$"{md.key.Replace(" ", "").Replace(",", "")} {Convert.ToBase64String(GetByteArray(md))}")));
}

var response = await client.PerformRequestAsync(request)
.ConfigureAwait(false);
var response = await client.PerformRequestAsync(request).ConfigureAwait(false);

if (response.StatusCode != HttpStatusCode.Created)
throw new Exception("CreateFileInServer failed. " + response.ResponseString);
{
throw new Exception("Failed to create the file in the server. " + response.ResponseString);
}

if (!response.Headers.ContainsKey("Location"))
throw new Exception("Location Header Missing");
{
throw new Exception("Location Header not found");
}

if (!Uri.TryCreate(response.Headers["Location"], UriKind.RelativeOrAbsolute, out var locationUri))
{
throw new Exception("Invalid Location Header");
}

if (!locationUri.IsAbsoluteUri)
{
locationUri = new Uri(requestUri, locationUri);
}

return locationUri.ToString();
}
Expand Down Expand Up @@ -149,8 +156,7 @@ public TusOperation<TusHttpResponse> DownloadAsync(string url, CancellationToken

request.DownloadProgressed += reportProgress;

var response = await client.PerformRequestAsync(request)
.ConfigureAwait(false);
var response = await client.PerformRequestAsync(request).ConfigureAwait(false);

request.DownloadProgressed -= reportProgress;

Expand All @@ -168,19 +174,21 @@ public async Task<TusServerInfo> GetServerInfo(string url)
var client = new TusHttpClient();
var request = new TusHttpRequest(url, RequestMethod.Options, AdditionalHeaders);

var response = await client.PerformRequestAsync(request)
.ConfigureAwait(false);
var response = await client.PerformRequestAsync(request).ConfigureAwait(false);

// Spec says NoContent but tusd gives OK because of browser bugs
if (response.StatusCode != HttpStatusCode.NoContent && response.StatusCode != HttpStatusCode.OK)
throw new Exception("getServerInfo failed. " + response.ResponseString);
{
throw new Exception("Failed to get the server info. " + response.ResponseString);
}

response.Headers.TryGetValue(TusHeaderNames.TusResumable, out var version);
response.Headers.TryGetValue(TusHeaderNames.TusVersion, out var supportedVersions);
response.Headers.TryGetValue(TusHeaderNames.TusExtension, out var extensions);
response.Headers.TryGetValue(TusHeaderNames.TusMaxSize, out var maxSizeString);
response.Headers.TryGetValue(TusHeaderNames.TusChecksumAlgorithm, out var checksumAlgorithms);
long.TryParse(maxSizeString, out var maxSize);

return new TusServerInfo(version, supportedVersions, extensions, maxSize, checksumAlgorithms);
}

Expand All @@ -196,8 +204,7 @@ public async Task<TusHttpResponse> HeadAsync(string url)

try
{
return await client.PerformRequestAsync(request)
.ConfigureAwait(false);
return await client.PerformRequestAsync(request).ConfigureAwait(false);
}
catch (TusException ex)
{
Expand Down Expand Up @@ -315,8 +322,7 @@ void OnProgress(long written, long total) =>
{
// retry by continuing the while loop but get new offset
// from server to prevent Conflict error
offset = await GetFileOffset(url)
.ConfigureAwait(false);
offset = await GetFileOffset(url).ConfigureAwait(false);
}
else
{
Expand Down Expand Up @@ -344,6 +350,16 @@ private static int ChunkSizeToMB(double chunkSize)
return (int)Math.Ceiling(chunkSize * 1024.0 * 1024.0);
}

private static byte[] GetByteArray((string key, string value) md)
{
if (md.value != null)
{
return Encoding.UTF8.GetBytes(md.value);
}

return Encoding.UTF8.GetBytes(string.Empty);
}

private async Task<long> GetFileOffset(string url)
{
var client = new TusHttpClient();
Expand All @@ -353,10 +369,14 @@ private async Task<long> GetFileOffset(string url)
.ConfigureAwait(false);

if (response.StatusCode != HttpStatusCode.NoContent && response.StatusCode != HttpStatusCode.OK)
{
throw new Exception("GetFileOffset failed. " + response.ResponseString);
}

if (!response.Headers.ContainsKey(TusHeaderNames.UploadOffset))
{
throw new Exception("Offset Header Missing");
}

return long.Parse(response.Headers[TusHeaderNames.UploadOffset]);
}
Expand Down
64 changes: 35 additions & 29 deletions src/TusDotNetClient/TusException.cs
Original file line number Diff line number Diff line change
@@ -1,39 +1,21 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;

namespace TusDotNetClient
namespace TusDotNetClient
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;

/// <summary>
/// Represents an exception that might occur when using <see cref="TusClient"/>.
/// </summary>
public class TusException : WebException
{
/// <summary>
/// Get the content, if any, of the failed operation.
/// </summary>
public string ResponseContent { get; }

/// <summary>
/// Get the HTTP status code, if any, of the failed operation.
/// </summary>
public HttpStatusCode StatusCode { get; }

/// <summary>
/// Get the description of the HTTP status code.
/// </summary>
public string StatusDescription { get; }

/// <summary>
/// Get the original <see cref="WebException"/> that occured.
/// </summary>
public WebException OriginalException { get; }

/// <summary>
/// Create a new instance of <see cref="TusException"/> based on an <see cref="OperationCanceledException"/>.
/// </summary>
/// <param name="ex">An <see cref="OperationCanceledException"/> to base the <see cref="TusException"/> on.</param>
/// <param name="ex">
/// An <see cref="OperationCanceledException"/> to base the <see cref="TusException"/> on.
/// </param>
public TusException(OperationCanceledException ex)
: base(ex.Message, ex, WebExceptionStatus.RequestCanceled, null)
{
Expand All @@ -43,7 +25,9 @@ public TusException(OperationCanceledException ex)
/// <summary>
/// Create a new instance of <see cref="TusException"/> based on another <see cref="TusException"/>.
/// </summary>
/// <param name="ex">The <see cref="TusException"/> to base the new <see cref="TusException"/> on.</param>
/// <param name="ex">
/// The <see cref="TusException"/> to base the new <see cref="TusException"/> on.
/// </param>
/// <param name="message">Text to prefix the <see cref="Exception.Message"/> with.</param>
public TusException(TusException ex, string message)
: base($"{message}{ex.Message}", ex, ex.Status, ex.Response)
Expand All @@ -58,7 +42,9 @@ public TusException(TusException ex, string message)
/// <summary>
/// Create a new instance of <see cref="TusException"/> based on a <see cref="WebException"/>.
/// </summary>
/// <param name="ex">The <see cref="WebException"/> to base the new <see cref="TusException"/> on.</param>
/// <param name="ex">
/// The <see cref="WebException"/> to base the new <see cref="TusException"/> on.
/// </param>
/// <param name="message">Text to prefix the <see cref="Exception.Message"/> with.</param>
public TusException(WebException ex, string message = "")
: base($"{message}{ex.Message}", ex, ex.Status, ex.Response)
Expand All @@ -77,6 +63,26 @@ public TusException(WebException ex, string message = "")
}
}

/// <summary>
/// Get the original <see cref="WebException"/> that occured.
/// </summary>
public WebException OriginalException { get; }

/// <summary>
/// Get the content, if any, of the failed operation.
/// </summary>
public string ResponseContent { get; }

/// <summary>
/// Get the HTTP status code, if any, of the failed operation.
/// </summary>
public HttpStatusCode StatusCode { get; }

/// <summary>
/// Get the description of the HTTP status code.
/// </summary>
public string StatusDescription { get; }

/// <summary>
/// Get a <see cref="string"/> containing all relevant information about the <see cref="TusException"/>.
/// </summary>
Expand Down
20 changes: 11 additions & 9 deletions src/TusDotNetClient/TusHTTPClient.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

namespace TusDotNetClient
namespace TusDotNetClient
{
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

/// <summary>
/// A class to execute requests against a Tus enabled server.
/// </summary>
Expand Down Expand Up @@ -64,9 +64,11 @@ public async Task<TusHttpResponse> PerformRequestAsync(TusHttpRequest request)
case TusHeaderNames.ContentLength:
webRequest.ContentLength = long.Parse(header.Value);
break;

case TusHeaderNames.ContentType:
webRequest.ContentType = header.Value;
break;

default:
webRequest.Headers.Add(header.Key, header.Value);
break;
Expand Down Expand Up @@ -101,7 +103,7 @@ await requestStream.WriteAsync(buffer, 0, bytesWritten, request.CancelToken)
}
}

var response = (HttpWebResponse) await webRequest.GetResponseAsync()
var response = (HttpWebResponse)await webRequest.GetResponseAsync()
.ConfigureAwait(false);

//contentLength=0 for gzipped responses due to .net bug
Expand Down
14 changes: 7 additions & 7 deletions src/TusDotNetClient/TusHeaderNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ namespace TusDotNetClient
/// </summary>
public static class TusHeaderNames
{
public const string TusResumable = "Tus-Resumable";
public const string TusVersion = "Tus-Version";
public const string ContentLength = "Content-Length";
public const string ContentType = "Content-Type";
public const string TusChecksumAlgorithm = "Tus-Checksum-Algorithm";
public const string TusExtension = "Tus-Extension";
public const string TusMaxSize = "Tus-Max-Size";
public const string TusChecksumAlgorithm = "Tus-Checksum-Algorithm";
public const string TusResumable = "Tus-Resumable";
public const string TusVersion = "Tus-Version";
public const string UploadChecksum = "Upload-Checksum";
public const string UploadLength = "Upload-Length";
public const string UploadOffset = "Upload-Offset";
public const string UploadMetadata = "Upload-Metadata";
public const string UploadChecksum = "Upload-Checksum";
public const string ContentLength = "Content-Length";
public const string ContentType = "Content-Type";
public const string UploadOffset = "Upload-Offset";
}
}
10 changes: 5 additions & 5 deletions src/TusDotNetClient/TusHttpRequest.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Threading;

namespace TusDotNetClient
namespace TusDotNetClient
{
using System;
using System.Collections.Generic;
using System.Threading;

/// <summary>
/// HTTP methods supported by <see cref="TusDotNetClient"/>
/// </summary>
Expand Down
12 changes: 6 additions & 6 deletions src/TusDotNetClient/TusHttpResponse.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;

namespace TusDotNetClient
namespace TusDotNetClient
{
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;

/// <summary>
/// Represents a response from a request made to a Tus enabled server.
/// </summary>
Expand Down
Loading