Commit 3f66d38c authored by Honfika's avatar Honfika

PROPFIND method is not supported (#367)

parent 788deefa
using System.Globalization;
using System;
using System.Globalization;
namespace Titanium.Web.Proxy.Extensions
{
internal static class StringExtensions
{
internal static bool EqualsIgnoreCase(this string str, string value)
{
return str.Equals(value, StringComparison.CurrentCultureIgnoreCase);
}
internal static bool ContainsIgnoreCase(this string str, string value)
{
return CultureInfo.CurrentCulture.CompareInfo.IndexOf(str, value, CompareOptions.IgnoreCase) >= 0;
......
using System;
using System.Text;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Shared;
......@@ -29,7 +30,7 @@ namespace Titanium.Web.Proxy.Helpers
foreach (string parameter in parameters)
{
var split = parameter.Split(ProxyConstants.EqualSplit, 2);
if (split.Length == 2 && split[0].Trim().Equals(KnownHeaders.ContentTypeCharset, StringComparison.CurrentCultureIgnoreCase))
if (split.Length == 2 && split[0].Trim().EqualsIgnoreCase(KnownHeaders.ContentTypeCharset))
{
string value = split[1];
if (value.Equals("x-user-defined", StringComparison.OrdinalIgnoreCase))
......@@ -66,7 +67,7 @@ namespace Titanium.Web.Proxy.Helpers
foreach (string parameter in parameters)
{
var split = parameter.Split(ProxyConstants.EqualSplit, 2);
if (split.Length == 2 && split[0].Trim().Equals(KnownHeaders.ContentTypeBoundary, StringComparison.CurrentCultureIgnoreCase))
if (split.Length == 2 && split[0].Trim().EqualsIgnoreCase(KnownHeaders.ContentTypeBoundary))
{
string value = split[1];
if (value.Length > 2 && value[0] == '"' && value[value.Length - 1] == '"')
......
......@@ -36,7 +36,8 @@ namespace Titanium.Web.Proxy.Helpers
try
{
tcpTable = Marshal.AllocHGlobal(tcpTableLength);
if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, ipVersionValue, (int)NativeMethods.TcpTableType.OwnerPidAll, 0) == 0)
if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, ipVersionValue, (int)NativeMethods.TcpTableType.OwnerPidAll, 0) ==
0)
{
var table = (NativeMethods.TcpTable)Marshal.PtrToStructure(tcpTable, typeof(NativeMethods.TcpTable));
......@@ -77,7 +78,8 @@ namespace Titanium.Web.Proxy.Helpers
try
{
tcpTable = Marshal.AllocHGlobal(tcpTableLength);
if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, ipVersionValue, (int)NativeMethods.TcpTableType.OwnerPidAll, 0) == 0)
if (NativeMethods.GetExtendedTcpTable(tcpTable, ref tcpTableLength, true, ipVersionValue, (int)NativeMethods.TcpTableType.OwnerPidAll, 0) ==
0)
{
var table = (NativeMethods.TcpTable)Marshal.PtrToStructure(tcpTable, typeof(NativeMethods.TcpTable));
......@@ -142,7 +144,8 @@ namespace Titanium.Web.Proxy.Helpers
}
}
private static void BeginRead(Stream inputStream, Stream outputStream, byte[] buffer, CancellationTokenSource cts, Action<byte[], int, int> onCopy, Action<Exception> exceptionFunc)
private static void BeginRead(Stream inputStream, Stream outputStream, byte[] buffer, CancellationTokenSource cts, Action<byte[], int, int> onCopy,
Action<Exception> exceptionFunc)
{
if (cts.IsCancellationRequested)
{
......@@ -231,5 +234,27 @@ namespace Titanium.Web.Proxy.Helpers
await Task.WhenAll(sendRelay, receiveRelay);
}
/// <summary>
/// relays the input clientStream to the server at the specified host name and port with the given httpCmd and headers as prefix
/// Usefull for websocket requests
/// </summary>
/// <param name="clientStream"></param>
/// <param name="serverStream"></param>
/// <param name="bufferSize"></param>
/// <param name="onDataSend"></param>
/// <param name="onDataReceive"></param>
/// <param name="exceptionFunc"></param>
/// <returns></returns>
internal static Task SendRaw(Stream clientStream, Stream serverStream, int bufferSize,
Action<byte[], int, int> onDataSend, Action<byte[], int, int> onDataReceive, Action<Exception> exceptionFunc)
{
#if NET45
return SendRawApm(clientStream, serverStream, bufferSize, onDataSend, onDataReceive, exceptionFunc);
#else
// todo: Apm hangs in dotnet core
return SendRawTap(clientStream, serverStream, bufferSize, onDataSend, onDataReceive, exceptionFunc);
#endif
}
}
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Models;
using Titanium.Web.Proxy.Network.Tcp;
......@@ -123,13 +124,13 @@ namespace Titanium.Web.Proxy.Http
//find if server is willing for expect continue
if (responseStatusCode == (int)HttpStatusCode.Continue
&& responseStatusDescription.Equals("continue", StringComparison.CurrentCultureIgnoreCase))
&& responseStatusDescription.EqualsIgnoreCase("continue"))
{
Request.Is100Continue = true;
await ServerConnection.StreamReader.ReadLineAsync();
}
else if (responseStatusCode == (int)HttpStatusCode.ExpectationFailed
&& responseStatusDescription.Equals("expectation failed", StringComparison.CurrentCultureIgnoreCase))
&& responseStatusDescription.EqualsIgnoreCase("expectation failed"))
{
Request.ExpectationFailed = true;
await ServerConnection.StreamReader.ReadLineAsync();
......@@ -168,7 +169,7 @@ namespace Titanium.Web.Proxy.Http
//For HTTP 1.1 comptibility server may send expect-continue even if not asked for it in request
if (Response.StatusCode == (int)HttpStatusCode.Continue
&& Response.StatusDescription.Equals("continue", StringComparison.CurrentCultureIgnoreCase))
&& Response.StatusDescription.EqualsIgnoreCase("continue"))
{
//Read the next line after 100-continue
Response.Is100Continue = true;
......@@ -181,7 +182,7 @@ namespace Titanium.Web.Proxy.Http
}
if (Response.StatusCode == (int)HttpStatusCode.ExpectationFailed
&& Response.StatusDescription.Equals("expectation failed", StringComparison.CurrentCultureIgnoreCase))
&& Response.StatusDescription.EqualsIgnoreCase("expectation failed"))
{
//read next line after expectation failed response
Response.ExpectationFailed = true;
......
......@@ -33,6 +33,7 @@ namespace Titanium.Web.Proxy.Http
public const string Host = "host";
public const string ProxyAuthorization = "Proxy-Authorization";
public const string ProxyAuthorizationBasic = "basic";
public const string ProxyConnection = "Proxy-Connection";
public const string ProxyConnectionClose = "close";
......
......@@ -58,7 +58,33 @@ namespace Titanium.Web.Proxy.Http
/// <summary>
/// Has request body?
/// </summary>
public bool HasBody => Method == "POST" || Method == "PUT" || Method == "PATCH";
public bool HasBody
{
get
{
long contentLength = ContentLength;
//If content length is set to 0 the request has no body
if (contentLength == 0)
{
return false;
}
//Has body only if request is chunked or content length >0
if (IsChunked || contentLength > 0)
{
return true;
}
//has body if POST and when version is http/1.0
if (Method == "POST" && HttpVersion == HttpHeader.Version10)
{
return true;
}
return false;
}
}
/// <summary>
/// Http hostname header value if exists
......@@ -248,7 +274,7 @@ namespace Titanium.Web.Proxy.Http
return false;
}
return headerValue.Equals(KnownHeaders.UpgradeWebsocket, StringComparison.CurrentCultureIgnoreCase);
return headerValue.EqualsIgnoreCase(KnownHeaders.UpgradeWebsocket);
}
}
......
......@@ -98,7 +98,7 @@ namespace Titanium.Web.Proxy.Http
if (headerValue != null)
{
if (headerValue.ContainsIgnoreCase(KnownHeaders.ConnectionClose))
if (headerValue.EqualsIgnoreCase(KnownHeaders.ConnectionClose))
{
return false;
}
......
......@@ -86,9 +86,12 @@ namespace Titanium.Web.Proxy.Network.Tcp
using (var reader = new CustomBinaryReader(stream, server.BufferSize))
{
string result = await reader.ReadLineAsync();
string httpStatus = await reader.ReadLineAsync();
if (!new[] { "200 OK", "connection established" }.Any(s => result.ContainsIgnoreCase(s)))
Response.ParseResponseLine(httpStatus, out var version, out int statusCode, out string statusDescription);
if (!statusDescription.EqualsIgnoreCase("200 OK")
&& !statusDescription.EqualsIgnoreCase("connection established"))
{
throw new Exception("Upstream proxy failed to create a secure tunnel");
}
......@@ -99,7 +102,6 @@ namespace Titanium.Web.Proxy.Network.Tcp
if (isHttps)
{
var sslStream = new SslStream(stream, false, server.ValidateServerCertificate, server.SelectClientCertificate);
stream = new CustomBufferedStream(sslStream, server.BufferSize);
......
......@@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Exceptions;
using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models;
......@@ -33,7 +34,7 @@ namespace Titanium.Web.Proxy
}
var headerValueParts = header.Value.Split(ProxyConstants.SpaceSplit);
if (headerValueParts.Length != 2 || !headerValueParts[0].Equals("basic", StringComparison.CurrentCultureIgnoreCase))
if (headerValueParts.Length != 2 || !headerValueParts[0].EqualsIgnoreCase(KnownHeaders.ProxyAuthorizationBasic))
{
//Return not authorized
session.WebSession.Response = await SendAuthentication407Response(clientStreamWriter, "Proxy Authentication Invalid");
......
......@@ -196,7 +196,7 @@ namespace Titanium.Web.Proxy
((ConnectResponse)connectArgs.WebSession.Response).ServerHelloInfo = serverHelloInfo;
}
await TcpHelper.SendRawApm(clientStream, connection.Stream, BufferSize,
await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize,
(buffer, offset, count) => { connectArgs.OnDataSent(buffer, offset, count); },
(buffer, offset, count) => { connectArgs.OnDataReceived(buffer, offset, count); },
ExceptionFunc);
......@@ -475,7 +475,7 @@ namespace Titanium.Web.Proxy
await BeforeResponse.InvokeAsync(this, args, ExceptionFunc);
}
await TcpHelper.SendRawApm(clientStream, connection.Stream, BufferSize,
await TcpHelper.SendRaw(clientStream, connection.Stream, BufferSize,
(buffer, offset, count) => { args.OnDataSent(buffer, offset, count); },
(buffer, offset, count) => { args.OnDataReceived(buffer, offset, count); },
ExceptionFunc);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment