Skip to content

Commit

Permalink
Fixed wrong URL encoding
Browse files Browse the repository at this point in the history
Implemented command String
  • Loading branch information
stevenengland committed Feb 18, 2017
1 parent c031413 commit d27dc2f
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 21 deletions.
10 changes: 7 additions & 3 deletions README.md
Expand Up @@ -13,17 +13,21 @@ X3270

X3270 is the namespace under which I want to release libraries that expose additional functionalities for the x3270 client by Paul Mattes.

See the [offcial X3270 wiki](https://github.com/stevenengland/X3270/wiki/X3270) for more information.

X3270.Rest
===

X3270.Rest is a wrapper for the standard x3270 HTTP REST interface. Remote controlling the x3270 client via HTTP is very advantageous because the HTTP protocol is very mature and as popular as never before. This imlies a broad support of any kind. In terms of .NET this means that one can easily build really asynchronous
calls from ones application to the x3270 terminal by using just a few native features for HTTP. This is why I built X3270.Rest that wrapps all the calls to x3270 for you in a straighforward manner.

More content coming soon...
To find out more have a look at
* the [X3270.Rest wiki pages](https://github.com/stevenengland/X3270/wiki/X3270-REST) or
* the [X3270.Rest test project](https://github.com/stevenengland/X3270/tree/master/src/StEn.X3270.Rest.Test)

Testing:
---
For testing purposes you need to set up a x3270 client and Sim390 emulator. These are not privided within this package.
For most of the testing actions you need to set up a x3270 client and Sim390 emulator. These are not privided within this package.
instead have a look at:

* Sim390 executable: http://www.canpub.com/teammpg/de/sim390/download.htm (Windows executable v1.7)
Expand Down Expand Up @@ -52,4 +56,4 @@ wc3270 -httpd 6001 +S "test.wc3270"
Credits
===

Thank you Paul Mattes for building x3270 where this repo is based on.
Thank you Paul Mattes for building x3270 on which this repo is based on.
43 changes: 33 additions & 10 deletions src/StEn.X3270.Rest.Test/RestClientTest.cs
Expand Up @@ -76,15 +76,15 @@ public async Task TearDownEach()
{
/* Determine if we are on the start screen */
var response = await this.apiClient.Ascii().ConfigureAwait(false);
if (response.PayLoad.To2DimensionalTerminalArray()[15][10] == "u") return;
if (response.PayLoad.ToAsciiMatrix()[15][10] == "u") return;

/* If not navigate to start screen */
await this.apiClient.Tab().ConfigureAwait(false); // If keys are locked
await this.apiClient.Pf(3).ConfigureAwait(false); // log off

/* Determine if we are on the start screen */
response = await this.apiClient.Ascii().ConfigureAwait(false);
Assert.That(response.PayLoad.To2DimensionalTerminalArray()[15][10] == "u");
Assert.That(response.PayLoad.ToAsciiMatrix()[15][10] == "u");
}

/// <summary>
Expand Down Expand Up @@ -171,7 +171,10 @@ public async Task TestConnectionCheck()
public async Task TestAscii()
{
var response = await this.apiClient.Ascii().ConfigureAwait(false);
Assert.That(response.PayLoad.To2DimensionalTerminalArray()[15][10] == "u");
Assert.That(response.PayLoad.ToAsciiMatrix()[15][10] == "u");
response = await this.apiClient.ReadBufferAsAscii().ConfigureAwait(false);
var byteArray = response.PayLoad.ToByteMatrix();
Assert.That(byteArray[15][10] == "75");
}

/// <summary>
Expand Down Expand Up @@ -231,10 +234,10 @@ public async Task TestEnter()
{
/* Determine if we are on the start screen */
var response = await this.apiClient.Ascii().ConfigureAwait(false);
Assert.That(response.PayLoad.To2DimensionalTerminalArray()[15][10] == "u");
Assert.That(response.PayLoad.ToAsciiMatrix()[15][10] == "u");
await this.apiClient.Enter().ConfigureAwait(false);
response = await this.apiClient.Ascii().ConfigureAwait(false);
Assert.That(response.PayLoad.To2DimensionalTerminalArray()[15][10] != "u");
Assert.That(response.PayLoad.ToAsciiMatrix()[15][10] != "u");
}

/// <summary>
Expand Down Expand Up @@ -275,6 +278,25 @@ public async Task TestDisconnect()
this.StartClient(this.pathToMock + "x3270\\wc3270.exe");
}

/// <summary>
/// Test the <c>String</c> command.
/// </summary>
/// <returns>
/// The <see cref="Task"/>.
/// </returns>
[Test, Category("Rest Actions")]
public async Task TestString()
{
await this.apiClient.Enter().ConfigureAwait(false);
await this.apiClient.String("\"insert this ()\"").ConfigureAwait(false);
var response = await this.apiClient.Ascii().ConfigureAwait(false);
Assert.That(response.PayLoad.ToAsciiMatrix()[2][17] == "i");
Assert.That(response.PayLoad.ToAsciiMatrix()[2][27] == "s");
Assert.That(response.PayLoad.ToAsciiMatrix()[2][29] == "(");
Assert.That(response.PayLoad.ToAsciiMatrix()[2][30] == ")");
Assert.That(response.PayLoad.ToAsciiMatrix()[2][23] == " ");
}

/// <summary>
/// Test the <c>Macro</c> command.
/// </summary>
Expand Down Expand Up @@ -424,9 +446,10 @@ public async Task CommandWithoutExpectedResult()
Assert.That(string.IsNullOrEmpty(response.PayLoad));
response = await this.apiClient.Key('C').ConfigureAwait(false);
Assert.That(string.IsNullOrEmpty(response.PayLoad));
//response = await this.apiClient.Key(',').ConfigureAwait(false);
//Assert.That(string.IsNullOrEmpty(response.PayLoad));
//response = await this.apiClient.Clear().ConfigureAwait(false);

// response = await this.apiClient.Key(',').ConfigureAwait(false);
// Assert.That(string.IsNullOrEmpty(response.PayLoad));
// response = await this.apiClient.Clear().ConfigureAwait(false);
response = await this.apiClient.Delete().ConfigureAwait(false);
Assert.That(string.IsNullOrEmpty(response.PayLoad));
response = await this.apiClient.DeleteField().ConfigureAwait(false);
Expand Down Expand Up @@ -487,14 +510,14 @@ public async Task CommandWithoutExpectedResult()
Assert.That(string.IsNullOrEmpty(response.PayLoad));
response = await this.apiClient.PreviousWord().ConfigureAwait(false);
Assert.That(string.IsNullOrEmpty(response.PayLoad));
response = await this.apiClient.Title("new title").ConfigureAwait(false);
response = await this.apiClient.Title("\"new title\"").ConfigureAwait(false);
Assert.That(string.IsNullOrEmpty(response.PayLoad));

response = await this.apiClient.Home().ConfigureAwait(false);
Assert.That(string.IsNullOrEmpty(response.PayLoad));
response = await this.apiClient.Clear().ConfigureAwait(false);
Assert.That(string.IsNullOrEmpty(response.PayLoad));
response = await this.apiClient.Execute("echo hallo").ConfigureAwait(false);
response = await this.apiClient.Execute("\"echo hallo\"").ConfigureAwait(false);
Assert.That(string.IsNullOrEmpty(response.PayLoad));
response = await this.apiClient.MonoCase().ConfigureAwait(false);
Assert.That(string.IsNullOrEmpty(response.PayLoad));
Expand Down
42 changes: 35 additions & 7 deletions src/StEn.X3270.Rest/Extensions/StringExtensions.cs
Expand Up @@ -8,18 +8,20 @@
public static class StringExtensions
{
/// <summary>
/// Converts a Newline separated string into a two dimensional array of strings.
/// Assumes that each line has the same count of characters as normal in terminals.
/// Takes a mask in ASCII representation (new line separated lines of ASCII symbols) and transforms it to a 2d array of ASCII symbols.
/// </summary>
/// <param name="input">
/// The input.
/// <param name="mask">
/// The mask.
/// </param>
/// <returns>
/// A 2 dimensional array of strings.
/// The <see>
/// <cref>string[][]</cref>
/// </see>
/// .
/// </returns>
public static string[][] To2DimensionalTerminalArray(this string input)
public static string[][] ToAsciiMatrix(this string mask)
{
var lines = input.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
var lines = mask.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
var returnStr = new string[lines.Length][];
for (var i = 0; i < lines.Length; i++)
{
Expand All @@ -32,5 +34,31 @@ public static string[][] To2DimensionalTerminalArray(this string input)

return returnStr;
}

/// <summary>
/// Takes a mask in byte representation (new line separated lines of bytes) to a 2d array of byte symbols.
/// </summary>
/// <param name="mask">
/// The mask.
/// </param>
/// <returns>
/// The <see>
/// <cref>string[][]</cref>
/// </see>
/// .
/// </returns>
public static string[][] ToByteMatrix(this string mask)
{
var lines = mask.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
var returnStr = new string[lines.Length][];
for (var i = 0; i < lines.Length; i++)
{
var line = lines[i].Split(' ');
returnStr[i] = line;
}

return returnStr;
}

}
}
14 changes: 14 additions & 0 deletions src/StEn.X3270.Rest/IActions.cs
Expand Up @@ -1108,6 +1108,20 @@ internal interface IActions
string file,
CancellationToken cancellationToken = default(CancellationToken));

/// <summary>
/// Insert a string.
/// </summary>
/// <param name="text">
/// The that shall be inserted.
/// </param>
/// <param name="cancellationToken">
/// The cancellation token.
/// </param>
/// <returns>
/// The <see cref="Task"/>.
/// </returns>
Task<StatusTextResponse<string>> String(string text, CancellationToken cancellationToken = default(CancellationToken));

/// <summary>
/// Changes the <c>wc3270</c> window title to text.
/// </summary>
Expand Down
5 changes: 5 additions & 0 deletions src/StEn.X3270.Rest/Json/JsonApiClient.cs
Expand Up @@ -445,6 +445,11 @@ public Task<StatusTextResponse<string>> SnapRows(CancellationToken cancellationT
throw new NotImplementedException();
}

public Task<StatusTextResponse<string>> String(string text, CancellationToken cancellationToken = new CancellationToken())
{
throw new NotImplementedException();
}

public Task<StatusTextResponse<string>> Title(
string text,
CancellationToken cancellationToken = new CancellationToken())
Expand Down
1 change: 1 addition & 0 deletions src/StEn.X3270.Rest/StEn.X3270.Rest.csproj
Expand Up @@ -30,6 +30,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\StEn.X3270.Rest.XML</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
Expand Down
45 changes: 44 additions & 1 deletion src/StEn.X3270.Rest/StatusText/StatusTextApiClient.cs
Expand Up @@ -5,6 +5,7 @@
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
Expand Down Expand Up @@ -1436,6 +1437,25 @@ public Task<StatusTextResponse<string>> Snap(CancellationToken cancellationToken
return this.Request<string>($"Source({file})", null, cancellationToken);
}

/// <summary>
/// Insert a string.
/// </summary>
/// <param name="text">
/// The that shall be inserted.
/// </param>
/// <param name="cancellationToken">
/// The cancellation token.
/// </param>
/// <returns>
/// The <see cref="Task"/>.
/// </returns>
public Task<StatusTextResponse<string>> String(
string text,
CancellationToken cancellationToken = default(CancellationToken))
{
return this.Request<string>($"String({text})", null, cancellationToken);
}

/// <summary>
/// Changes the <c>wc3270</c> window title to text.
/// </summary>
Expand Down Expand Up @@ -1578,7 +1598,11 @@ public Task<StatusTextResponse<string>> Up(CancellationToken cancellationToken =
CancellationToken cancellationToken = new CancellationToken())
{
cancellationToken.ThrowIfCancellationRequested();
var uri = new Uri(this.HostAddress + ":" + this.Port + RestRoot + HttpUtility.UrlEncode(resource));

// resource = HttpUtility.UrlEncode(resource); // Also encodes parameters within parenthesis.
resource = this.ReplaceCommandParenthesis(resource);

var uri = new Uri(this.HostAddress + ":" + this.Port + RestRoot + resource);

HttpResponseMessage response = new HttpResponseMessage();
var responseStr = string.Empty;
Expand Down Expand Up @@ -1688,6 +1712,25 @@ private StatusTextResponse<string> ConstructStatusTextResponse(string input)
return response;
}

/// <summary>
/// Replace leading and trailing parenthesis.
/// </summary>
/// <param name="input">
/// The input.
/// </param>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
private string ReplaceCommandParenthesis(string input)
{
var pos = input.IndexOf('(');
if (pos < 0)
{
return input;
}
return input.Substring(0, pos) + "%28" + input.Substring(pos + 1, input.Length - pos - 2) + "%29";
}

/// <summary>
/// Disposes this instance.
/// </summary>
Expand Down

0 comments on commit d27dc2f

Please sign in to comment.