Skip to content
This repository was archived by the owner on Jul 9, 2023. It is now read-only.
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
5 changes: 5 additions & 0 deletions Titanium.Web.Proxy.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=dda2ffa1_002D435c_002D4111_002D88eb_002D1a7c93c382f0/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="Property (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="PROPERTY" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String></wpf:ResourceDictionary>
5 changes: 3 additions & 2 deletions Titanium.Web.Proxy/Extensions/HttpWebRequestExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text;
using System;
using System.Text;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Shared;

Expand Down Expand Up @@ -29,7 +30,7 @@ internal static Encoding GetEncoding(this Request request)
foreach (var contentType in contentTypes)
{
var encodingSplit = contentType.Split('=');
if (encodingSplit.Length == 2 && encodingSplit[0].ToLower().Trim() == "charset")
if (encodingSplit.Length == 2 && encodingSplit[0].Trim().Equals("charset", StringComparison.CurrentCultureIgnoreCase))
{
return Encoding.GetEncoding(encodingSplit[1]);
}
Expand Down
5 changes: 3 additions & 2 deletions Titanium.Web.Proxy/Extensions/HttpWebResponseExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text;
using System;
using System.Text;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Shared;

Expand Down Expand Up @@ -26,7 +27,7 @@ internal static Encoding GetResponseCharacterEncoding(this Response response)
foreach (var contentType in contentTypes)
{
var encodingSplit = contentType.Split('=');
if (encodingSplit.Length == 2 && encodingSplit[0].ToLower().Trim() == "charset")
if (encodingSplit.Length == 2 && encodingSplit[0].Trim().Equals("charset", StringComparison.CurrentCultureIgnoreCase))
{
return Encoding.GetEncoding(encodingSplit[1]);
}
Expand Down
17 changes: 17 additions & 0 deletions Titanium.Web.Proxy/Extensions/StringExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Titanium.Web.Proxy.Extensions
{
internal static class StringExtensions
{
internal static bool ContainsIgnoreCase(this string str, string value)
{
return CultureInfo.CurrentCulture.CompareInfo.IndexOf(str, value, CompareOptions.IgnoreCase) >= 0;
}
}
}
135 changes: 94 additions & 41 deletions Titanium.Web.Proxy/Helpers/CustomBinaryReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Extensions;

namespace Titanium.Web.Proxy.Helpers
{
Expand All @@ -15,12 +14,30 @@ namespace Titanium.Web.Proxy.Helpers
/// </summary>
internal class CustomBinaryReader : IDisposable
{
private readonly Stream stream;
private readonly CustomBufferedStream stream;
private readonly int bufferSize;
private readonly Encoding encoding;

internal CustomBinaryReader(Stream stream)
[ThreadStatic]
private static byte[] staticBuffer;

private byte[] buffer
{
get
{
if (staticBuffer == null || staticBuffer.Length != bufferSize)
{
staticBuffer = new byte[bufferSize];
}

return staticBuffer;
}
}

internal CustomBinaryReader(CustomBufferedStream stream, int bufferSize)
{
this.stream = stream;
this.bufferSize = bufferSize;

//default to UTF-8
encoding = Encoding.UTF8;
Expand All @@ -34,33 +51,41 @@ internal CustomBinaryReader(Stream stream)
/// <returns></returns>
internal async Task<string> ReadLineAsync()
{
using (var readBuffer = new MemoryStream())
var lastChar = default(byte);

int bufferDataLength = 0;

// try to use the thread static buffer, usually it is enough
var buffer = this.buffer;

while (stream.DataAvailable || await stream.FillBufferAsync())
{
var lastChar = default(char);
var buffer = new byte[1];

while ((await stream.ReadAsync(buffer, 0, 1)) > 0)
{
//if new line
if (lastChar == '\r' && buffer[0] == '\n')
{
var result = readBuffer.ToArray();
return encoding.GetString(result.SubArray(0, result.Length - 1));
}
//end of stream
if (buffer[0] == '\0')
{
return encoding.GetString(readBuffer.ToArray());
}

await readBuffer.WriteAsync(buffer,0,1);

//store last char for new line comparison
lastChar = (char)buffer[0];
}

return encoding.GetString(readBuffer.ToArray());
var newChar = stream.ReadByteFromBuffer();
buffer[bufferDataLength] = newChar;

//if new line
if (lastChar == '\r' && newChar == '\n')
{
return encoding.GetString(buffer, 0, bufferDataLength - 1);
}
//end of stream
if (newChar == '\0')
{
return encoding.GetString(buffer, 0, bufferDataLength);
}

bufferDataLength++;

//store last char for new line comparison
lastChar = newChar;

if (bufferDataLength == buffer.Length)
{
ResizeBuffer(ref buffer, bufferDataLength * 2);
}
}

return encoding.GetString(buffer, 0, bufferDataLength);
}

/// <summary>
Expand All @@ -78,6 +103,17 @@ internal async Task<List<string>> ReadAllLinesAsync()
return requestLines;
}

/// <summary>
/// Read until the last new line, ignores the result
/// </summary>
/// <returns></returns>
internal async Task ReadAndIgnoreAllLinesAsync()
{
while (!string.IsNullOrEmpty(await ReadLineAsync()))
{
}
}

/// <summary>
/// Read the specified number of raw bytes from the base stream
/// </summary>
Expand All @@ -91,34 +127,51 @@ internal async Task<byte[]> ReadBytesAsync(int bufferSize, long totalBytesToRead
if (totalBytesToRead < bufferSize)
bytesToRead = (int)totalBytesToRead;

var buffer = new byte[bufferSize];
var buffer = this.buffer;
if (bytesToRead > buffer.Length)
{
buffer = new byte[bytesToRead];
}

var bytesRead = 0;
int bytesRead;
var totalBytesRead = 0;

using (var outStream = new MemoryStream())
while ((bytesRead = await stream.ReadAsync(buffer, totalBytesRead, bytesToRead)) > 0)
{
while ((bytesRead += await stream.ReadAsync(buffer, 0, bytesToRead)) > 0)
{
await outStream.WriteAsync(buffer, 0, bytesRead);
totalBytesRead += bytesRead;
totalBytesRead += bytesRead;

if (totalBytesRead == totalBytesToRead)
break;

if (totalBytesRead == totalBytesToRead)
break;
var remainingBytes = totalBytesToRead - totalBytesRead;
bytesToRead = Math.Min(bufferSize, (int)remainingBytes);

bytesRead = 0;
var remainingBytes = (totalBytesToRead - totalBytesRead);
bytesToRead = remainingBytes > (long)bufferSize ? bufferSize : (int)remainingBytes;
if (totalBytesRead + bytesToRead > buffer.Length)
{
ResizeBuffer(ref buffer, Math.Min(totalBytesToRead, buffer.Length * 2));
}
}

return outStream.ToArray();
if (totalBytesRead != buffer.Length)
{
//Normally this should not happen. Resize the buffer anyway
var newBuffer = new byte[totalBytesRead];
Buffer.BlockCopy(buffer, 0, newBuffer, 0, totalBytesRead);
buffer = newBuffer;
}

return buffer;
}

public void Dispose()
{
}

private void ResizeBuffer(ref byte[] buffer, long size)
{
var newBuffer = new byte[size];
Buffer.BlockCopy(buffer, 0, newBuffer, 0, buffer.Length);
buffer = newBuffer;
}
}
}
Loading