Skip to content

Commit

Permalink
Fixing the exception for #867
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeyzimarev committed May 11, 2020
1 parent 370659d commit ee97e33
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@

namespace RestSharp.Authenticators.OAuth.Extensions
{
internal static class StringExtensions
static class StringExtensions
{
public static bool IsNullOrBlank(this string value) => string.IsNullOrWhiteSpace(value);

public static bool EqualsIgnoreCase(this string left, string right) => string.Equals(left, right, StringComparison.InvariantCultureIgnoreCase);

public static string Then(this string input, string value) => string.Concat(input, value);
Expand Down
7 changes: 4 additions & 3 deletions src/RestSharp/Authenticators/OAuth/OAuth1Authenticator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using System.Web;
using RestSharp.Authenticators.OAuth;
using RestSharp.Authenticators.OAuth.Extensions;
using RestSharp.Extensions;

// ReSharper disable CheckNamespace

Expand Down Expand Up @@ -314,7 +315,7 @@ IEnumerable<Parameter> CreateHeaderParameters()
=> new[] {new Parameter("Authorization", GetAuthorizationHeader(), ParameterType.HttpHeader)};

IEnumerable<Parameter> CreateUrlParameters()
=> parameters.Where(p => !p.Name.IsNullOrBlank() && (p.Name.StartsWith("oauth_") || p.Name.StartsWith("x_auth_")))
=> parameters.Where(p => !p.Name.IsEmpty() && (p.Name.StartsWith("oauth_") || p.Name.StartsWith("x_auth_")))
.Select(p => new Parameter(p.Name, HttpUtility.UrlDecode(p.Value), ParameterType.GetOrPost));

string GetAuthorizationHeader()
Expand All @@ -324,13 +325,13 @@ string GetAuthorizationHeader()
.OrderBy(x => x, WebPair.Comparer)
.Where(
p =>
!p.Name.IsNullOrBlank() && !p.Value.IsNullOrBlank() &&
!p.Name.IsEmpty() && !p.Value.IsEmpty() &&
(p.Name.StartsWith("oauth_") || p.Name.StartsWith("x_auth_"))
)
.Select(x => $"{x.Name}=\"{x.Value}\"")
.ToList();

if (!Realm.IsNullOrBlank())
if (!Realm.IsEmpty())
oathParameters.Insert(0, $"realm=\"{OAuthTools.UrlEncodeRelaxed(Realm)}\"");

return "OAuth " + string.Join(",", oathParameters);
Expand Down
2 changes: 1 addition & 1 deletion src/RestSharp/Authenticators/OAuth/OAuthTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ public static string GetSignature(
string tokenSecret
)
{
if (tokenSecret.IsNullOrBlank())
if (tokenSecret.IsEmpty())
tokenSecret = string.Empty;

var unencodedConsumerSecret = consumerSecret;
Expand Down
69 changes: 23 additions & 46 deletions src/RestSharp/Authenticators/OAuth/OAuthWorkflow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@
using System.Collections.Generic;
using System.Web;
using RestSharp.Authenticators.OAuth.Extensions;
using RestSharp.Extensions;
using RestSharp.Validation;

namespace RestSharp.Authenticators.OAuth
{
/// <summary>
/// A class to encapsulate OAuth authentication flow.
/// </summary>
internal sealed class OAuthWorkflow
sealed class OAuthWorkflow
{
public string Version { get; set; }

Expand Down Expand Up @@ -66,8 +68,7 @@ public string BuildRequestTokenInfo(string method, WebPairCollection parameters)
{
ValidateTokenRequestState();

if (parameters == null)
parameters = new WebPairCollection();
parameters ??= new WebPairCollection();

var timestamp = OAuthTools.GetTimestamp();
var nonce = OAuthTools.GetNonce();
Expand All @@ -89,8 +90,7 @@ public string BuildAccessTokenSignature(string method, WebPairCollection paramet
{
ValidateAccessRequestState();

if (parameters == null)
parameters = new WebPairCollection();
parameters ??= new WebPairCollection();

var uri = new Uri(AccessTokenUrl);
var timestamp = OAuthTools.GetTimestamp();
Expand Down Expand Up @@ -138,8 +138,7 @@ public string BuildProtectedResourceSignature(string method, WebPairCollection p
{
ValidateProtectedResourceState();

if (parameters == null)
parameters = new WebPairCollection();
parameters ??= new WebPairCollection();

// Include url parameters in query pool
var uri = new Uri(url);
Expand All @@ -163,53 +162,31 @@ public string BuildProtectedResourceSignature(string method, WebPairCollection p

void ValidateTokenRequestState()
{
if (RequestTokenUrl.IsNullOrBlank())
throw new ArgumentException("You must specify a request token URL");

if (ConsumerKey.IsNullOrBlank())
throw new ArgumentException("You must specify a consumer key");

if (ConsumerSecret.IsNullOrBlank())
throw new ArgumentException("You must specify a consumer secret");
Ensure.NotEmpty(RequestTokenUrl, nameof(RequestTokenUrl));
Ensure.NotEmpty(ConsumerKey, nameof(ConsumerKey));
Ensure.NotEmpty(ConsumerSecret, nameof(ConsumerSecret));
}

void ValidateAccessRequestState()
{
if (AccessTokenUrl.IsNullOrBlank())
throw new ArgumentException("You must specify an access token URL");

if (ConsumerKey.IsNullOrBlank())
throw new ArgumentException("You must specify a consumer key");

if (ConsumerSecret.IsNullOrBlank())
throw new ArgumentException("You must specify a consumer secret");

if (Token.IsNullOrBlank())
throw new ArgumentException("You must specify a token");
Ensure.NotEmpty(AccessTokenUrl, nameof(AccessTokenUrl));
Ensure.NotEmpty(ConsumerKey, nameof(ConsumerKey));
Ensure.NotEmpty(ConsumerSecret, nameof(ConsumerSecret));
Ensure.NotEmpty(Token, nameof(Token));
}

void ValidateClientAuthAccessRequestState()
{
if (AccessTokenUrl.IsNullOrBlank())
throw new ArgumentException("You must specify an access token URL");

if (ConsumerKey.IsNullOrBlank())
throw new ArgumentException("You must specify a consumer key");

if (ConsumerSecret.IsNullOrBlank())
throw new ArgumentException("You must specify a consumer secret");

if (ClientUsername.IsNullOrBlank() || ClientPassword.IsNullOrBlank())
throw new ArgumentException("You must specify user credentials");
Ensure.NotEmpty(AccessTokenUrl, nameof(AccessTokenUrl));
Ensure.NotEmpty(ConsumerKey, nameof(ConsumerKey));
Ensure.NotEmpty(ConsumerSecret, nameof(ConsumerSecret));
Ensure.NotEmpty(ClientUsername, nameof(ClientUsername));
}

void ValidateProtectedResourceState()
{
if (ConsumerKey.IsNullOrBlank())
throw new ArgumentException("You must specify a consumer key");

if (ConsumerSecret.IsNullOrBlank())
throw new ArgumentException("You must specify a consumer secret");
Ensure.NotEmpty(ConsumerKey, nameof(ConsumerKey));
Ensure.NotEmpty(ConsumerSecret, nameof(ConsumerSecret));
}

void AddAuthParameters(ICollection<WebPair> parameters, string timestamp, string nonce)
Expand All @@ -223,16 +200,16 @@ void AddAuthParameters(ICollection<WebPair> parameters, string timestamp, string
new WebPair("oauth_version", Version ?? "1.0")
};

if (!Token.IsNullOrBlank())
if (!Token.IsEmpty())
authParameters.Add(new WebPair("oauth_token", Token));

if (!CallbackUrl.IsNullOrBlank())
if (!CallbackUrl.IsEmpty())
authParameters.Add(new WebPair("oauth_callback", CallbackUrl));

if (!Verifier.IsNullOrBlank())
if (!Verifier.IsEmpty())
authParameters.Add(new WebPair("oauth_verifier", Verifier));

if (!SessionHandle.IsNullOrBlank())
if (!SessionHandle.IsEmpty())
authParameters.Add(new WebPair("oauth_session_handle", SessionHandle));

foreach (var authParameter in authParameters)
Expand Down
37 changes: 2 additions & 35 deletions src/RestSharp/Extensions/MiscExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

using System;
using System.IO;
using System.Linq;
using System.Text;
using RestSharp.Authenticators.OAuth.Extensions;

namespace RestSharp.Extensions
{
Expand Down Expand Up @@ -72,40 +74,5 @@ public static void CopyTo(this Stream input, Stream output)
}
}

/// <summary>
/// Converts a byte array to a string, using its byte order mark to convert it to the right encoding.
/// http://www.shrinkrays.net/code-snippets/csharp/an-extension-method-for-converting-a-byte-array-to-a-string.aspx
/// </summary>
/// <param name="buffer">An array of bytes to convert</param>
/// <param name="encoding">Content encoding. Will fallback to UTF8 if not a valid encoding.</param>
/// <returns>The byte as a string.</returns>
[Obsolete("This method will be removed soon. If you use it, please copy the code to your project.")]
public static string AsString(this byte[] buffer, string encoding)
{
var enc = Encoding.UTF8;

try
{
if (!string.IsNullOrEmpty(encoding))
enc = Encoding.GetEncoding(encoding);
}
catch (Exception)
{
// Use UTF8 as the default
}

return AsString(buffer, enc);
}

/// <summary>
/// Converts a byte array to a string, using its byte order mark to convert it to the right encoding.
/// http://www.shrinkrays.net/code-snippets/csharp/an-extension-method-for-converting-a-byte-array-to-a-string.aspx
/// </summary>
/// <param name="buffer">An array of bytes to convert</param>
/// <returns>The byte as a string using UTF8.</returns>
[Obsolete("This method will be removed soon. If you use it, please copy the code to your project.")]
public static string AsString(this byte[] buffer) => AsString(buffer, Encoding.UTF8);

static string AsString(byte[] buffer, Encoding encoding) => buffer == null ? "" : encoding.GetString(buffer, 0, buffer.Length);
}
}
62 changes: 62 additions & 0 deletions src/RestSharp/Extensions/StringEncodingExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright © 2009-2020 John Sheehan, Andrew Young, Alexey Zimarev and RestSharp community
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

using System;
using System.Collections.Generic;
using System.Text;

namespace RestSharp.Extensions
{
public static class StringEncodingExtensions
{
static readonly Dictionary<string, Encoding> Encodings = new Dictionary<string, Encoding>();

static StringEncodingExtensions()
{
var encodings = Encoding.GetEncodings();

foreach (var encoding in encodings)
{
Encodings[encoding.Name] = encoding.GetEncoding();
}
}

/// <summary>
/// Converts a byte array to a string, using its byte order mark to convert it to the right encoding.
/// http://www.shrinkrays.net/code-snippets/csharp/an-extension-method-for-converting-a-byte-array-to-a-string.aspx
/// </summary>
/// <param name="buffer">An array of bytes to convert</param>
/// <param name="encoding">Content encoding. Will fallback to UTF8 if not a valid encoding.</param>
/// <returns>The byte as a string.</returns>
[Obsolete("This method will be removed soon. If you use it, please copy the code to your project.")]
public static string AsString(this byte[] buffer, string? encoding)
{
var enc = encoding.IsEmpty() ? Encoding.UTF8 : Encodings.TryGetValue(encoding!, out var e) ? e : Encoding.UTF8;

return AsString(buffer, enc);
}

/// <summary>
/// Converts a byte array to a string, using its byte order mark to convert it to the right encoding.
/// http://www.shrinkrays.net/code-snippets/csharp/an-extension-method-for-converting-a-byte-array-to-a-string.aspx
/// </summary>
/// <param name="buffer">An array of bytes to convert</param>
/// <returns>The byte as a string using UTF8.</returns>
[Obsolete("This method will be removed soon. If you use it, please copy the code to your project.")]
public static string AsString(this byte[] buffer) => AsString(buffer, Encoding.UTF8);

static string AsString(byte[] buffer, Encoding encoding) => buffer == null ? "" : encoding.GetString(buffer, 0, buffer.Length);
}
}
2 changes: 1 addition & 1 deletion src/RestSharp/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ public static string AddSpaces(this string pascalCasedWord)
" "
);

internal static bool IsEmpty(this string value) => string.IsNullOrWhiteSpace(value);
internal static bool IsEmpty(this string? value) => string.IsNullOrWhiteSpace(value);

internal static bool IsNotEmpty(this string value) => !string.IsNullOrWhiteSpace(value);

Expand Down
3 changes: 3 additions & 0 deletions src/RestSharp/RestSharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
<ItemGroup>
<Reference Include="System.Web" Condition="'$(TargetFramework)' == 'net452'" />
</ItemGroup>
<ItemGroup>
<None Remove="RestSharp.csproj.DotSettings" />
</ItemGroup>

<Target DependsOnTargets="ResolveReferences" Name="CopyProjectReferencesToPackage">
<ItemGroup>
Expand Down
25 changes: 22 additions & 3 deletions test/RestSharp.Tests/StringExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Globalization;
using System.Text;
using FluentAssertions;
using NUnit.Framework;
using RestSharp.Extensions;

Expand All @@ -13,9 +14,7 @@ public void UrlEncode_Throws_ArgumentNullException_For_Null_Input()
{
const string nullString = null;

Assert.Throws<ArgumentNullException>(
delegate { nullString.UrlEncode(); }
);
Assert.Throws<ArgumentNullException>(() => nullString.UrlEncode());
}

[Test]
Expand Down Expand Up @@ -66,5 +65,25 @@ public void ToPascalCase(string start, bool removeUnderscores, string finish)

Assert.AreEqual(finish, result);
}

[Test]
public void Does_not_throw_on_invalid_encoding()
{
const string value = "SomeValue";
var bytes = Encoding.UTF8.GetBytes(value);

var decoded = bytes.AsString("blah");
decoded.Should().Be(value);
}

[Test]
public void Does_not_throw_on_missing_encoding()
{
const string value = "SomeValue";
var bytes = Encoding.UTF8.GetBytes(value);

var decoded = bytes.AsString(null);
decoded.Should().Be(value);
}
}
}

0 comments on commit ee97e33

Please sign in to comment.