From 0d940df4e2f88ffc80d6f4179805b752fc54ed7a Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sat, 11 Apr 2020 15:18:49 +0100 Subject: [PATCH] http server: change uri query handling --- .../Servers/HttpServer/OSHttpRequest.cs | 54 ++++---- .../OSHttpServer/HttpClientContext.cs | 28 ++++- .../OSHttpServer/HttpContextFactory.cs | 1 - .../HttpServer/OSHttpServer/HttpHelper.cs | 118 ------------------ .../HttpServer/OSHttpServer/HttpRequest.cs | 84 +++++-------- .../OSHttpServer/HttpRequestParser.cs | 3 + .../HttpServer/OSHttpServer/IHttpRequest.cs | 22 +--- 7 files changed, 84 insertions(+), 226 deletions(-) delete mode 100644 OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpHelper.cs diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs index d172993a14..ee6191b4c2 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpRequest.cs @@ -120,15 +120,20 @@ namespace OpenSim.Framework.Servers.HttpServer public NameValueCollection QueryString { - get { return _queryString; } + get { return _request.QueryString;} } - private NameValueCollection _queryString; public Dictionary Query { - get { return _query; } + get + { + if (_queryKeyValues == null) + BuildQueryDictionary(); + return _queryKeyValues; + } } - private Dictionary _query; + + private Dictionary _queryKeyValues = null; /// /// POST request values, if applicable @@ -190,7 +195,7 @@ namespace OpenSim.Framework.Servers.HttpServer { _contentEncoding = Encoding.GetEncoding(_request.Headers["content-encoding"]); } - catch (Exception) + catch { // ignore } @@ -224,29 +229,6 @@ namespace OpenSim.Framework.Servers.HttpServer } } - _queryString = new NameValueCollection(); - _query = new Dictionary(); - try - { - foreach (HttpInputItem item in req.QueryString) - { - try - { - _queryString.Add(item.Name, item.Value); - _query[item.Name] = item.Value; - } - catch (InvalidCastException) - { - _log.DebugFormat("[OSHttpRequest]: error parsing {0} query item, skipping it", item.Name); - continue; - } - } - } - catch (Exception) - { - _log.ErrorFormat("[OSHttpRequest]: Error parsing querystring"); - } - // Form = new Hashtable(); // foreach (HttpInputItem item in req.Form) // { @@ -255,6 +237,22 @@ namespace OpenSim.Framework.Servers.HttpServer // } } + private void BuildQueryDictionary() + { + NameValueCollection q = _request.QueryString; + _queryKeyValues = new Dictionary(); // only key value pairs + for(int i = 0; i - /// Generic helper functions for HTTP - /// - public static class HttpHelper - { - /// - /// An empty URI - /// - public static readonly Uri EmptyUri = new Uri("http://localhost/"); - - /// - /// Parses a query string. - /// - /// Query string (URI encoded) - /// A object if successful; otherwise - /// queryString is null. - /// If string cannot be parsed. - public static HttpInput ParseQueryString(string queryString) - { - if (queryString == null) - throw new ArgumentNullException("queryString"); - if (queryString == string.Empty) - return HttpInput.Empty; - - HttpInput input = new HttpInput("QueryString"); - - queryString = queryString.TrimStart('?', '&'); - - // a simple value. - if (queryString.IndexOf("&") == -1 && !queryString.Contains("%3d") && !queryString.Contains("%3D") && !queryString.Contains("=")) - { - input.Add(string.Empty, queryString); - return input; - } - - int state = 0; - int startpos = 0; - string name = null; - for (int i = 0; i < queryString.Length; ++i) - { - int newIndexPos; - if (state == 0 && IsEqual(queryString, ref i, out newIndexPos)) - { - name = queryString.Substring(startpos, i - startpos); - i = newIndexPos; - startpos = i + 1; - ++state; - } - else if (state == 1 && IsAmp(queryString, ref i, out newIndexPos)) - { - Add(input, name, queryString.Substring(startpos, i - startpos)); - i = newIndexPos; - startpos = i + 1; - state = 0; - name = null; - } - } - - if (state == 0 && !input.GetEnumerator().MoveNext()) - throw new FormatException("Not a valid query string: " + queryString); - - if (startpos <= queryString.Length) - { - if (name != null) - Add(input, name, queryString.Substring(startpos, queryString.Length - startpos)); - else - Add(input, string.Empty, queryString.Substring(startpos, queryString.Length - startpos)); - } - - return input; - } - - private static bool IsEqual(string queryStr, ref int index, out int outIndex) - { - outIndex = index; - if (queryStr[index] == '=') - return true; - if (queryStr[index] == '%' && queryStr.Length > index + 2 && queryStr[index + 1] == '3' - && (queryStr[index + 2] == 'd' || queryStr[index + 2] == 'D')) - { - outIndex += 2; - return true; - } - return false; - } - - private static bool IsAmp(string queryStr, ref int index, out int outIndex) - { - outIndex = index; - if (queryStr[index] == '%' && queryStr.Length > index + 2 && queryStr[index + 1] == '2' && - queryStr[index + 2] == '6') - outIndex += 2; - else if (queryStr[index] == '&') - { - if (queryStr.Length > index + 4 - && (queryStr[index + 1] == 'a' || queryStr[index + 1] == 'A') - && (queryStr[index + 2] == 'm' || queryStr[index + 2] == 'M') - && (queryStr[index + 3] == 'p' || queryStr[index + 3] == 'P') - && queryStr[index + 4] == ';') - outIndex += 4; - } - else - return false; - - return true; - } - - private static void Add(IHttpInput input, string name, string value) - { - input.Add(HttpUtility.UrlDecode(name), HttpUtility.UrlDecode(value)); - } - } -} diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpRequest.cs index 10a3745eb0..96f55d2ca6 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpRequest.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpRequest.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Specialized; using System.IO; using System.Text; +using System.Web; using OSHttpServer.Exceptions; @@ -26,8 +27,8 @@ namespace OSHttpServer private int m_contentLength; private string m_httpVersion = string.Empty; private string m_method = string.Empty; - private HttpInput m_queryString = HttpInput.Empty; - private Uri m_uri = HttpHelper.EmptyUri; + private NameValueCollection m_queryString = null; + private Uri m_uri = null; private string m_uriPath; public readonly IHttpClientContext m_context; @@ -42,7 +43,7 @@ namespace OSHttpServer /// /// Gets or sets a value indicating whether this is secure. /// - public bool Secure { get; internal set; } + public bool Secure { get { return m_context.IsSecured; } } public IHttpClientContext Context { get { return m_context; } } /// @@ -52,24 +53,7 @@ namespace OSHttpServer public string UriPath { get { return m_uriPath; } - set - { - m_uriPath = value; - int pos = m_uriPath.IndexOf('?'); - if (pos != -1) - { - m_queryString = HttpHelper.ParseQueryString(m_uriPath.Substring(pos + 1)); - m_param.SetQueryString(m_queryString); - string path = m_uriPath.Substring(0, pos); - m_uriPath = System.Web.HttpUtility.UrlDecode(path) + "?" + m_uriPath.Substring(pos + 1); - UriParts = value.Substring(0, pos).Split(UriSplitters, StringSplitOptions.RemoveEmptyEntries); - } - else - { - m_uriPath = System.Web.HttpUtility.UrlDecode(m_uriPath); - UriParts = value.Split(UriSplitters, StringSplitOptions.RemoveEmptyEntries); - } - } + set { m_uriPath = value; } } /// @@ -85,14 +69,6 @@ namespace OSHttpServer #region IHttpRequest Members - /// - /// Gets whether the body is complete. - /// - public bool BodyIsComplete - { - get { return m_bodyBytesLeft == 0; } - } - /// /// Gets kind of types accepted by the client. /// @@ -167,40 +143,38 @@ namespace OSHttpServer /// /// Gets variables sent in the query string /// - public HttpInput QueryString + public NameValueCollection QueryString { - get { return m_queryString; } + get + { + if(m_queryString == null) + { + if(m_uri == null || m_uri.Query.Length == 0) + m_queryString = new NameValueCollection(); + else + { + try + { + m_queryString = HttpUtility.ParseQueryString(m_uri.Query); + } + catch { m_queryString = new NameValueCollection(); } + } + } + + return m_queryString; + } } - + public static readonly Uri EmptyUri = new Uri("http://localhost/"); /// /// Gets or sets requested URI. /// public Uri Uri { get { return m_uri; } - set - { - m_uri = value ?? HttpHelper.EmptyUri; - UriParts = m_uri.AbsolutePath.Split(UriSplitters, StringSplitOptions.RemoveEmptyEntries); - } + set { m_uri = value ?? EmptyUri; } // not safe } - /// - /// Uri absolute path splitted into parts. - /// - /// - /// // uri is: http://gauffin.com/code/tiny/ - /// Console.WriteLine(request.UriParts[0]); // result: code - /// Console.WriteLine(request.UriParts[1]); // result: tiny - /// - /// - /// If you're using controllers than the first part is controller name, - /// the second part is method name and the third part is Id property. - /// - /// - public string[] UriParts { get; private set; } - /// /// Gets parameter from or . /// @@ -341,7 +315,7 @@ namespace OSHttpServer try { m_uri = new Uri(Secure ? "https://" : "http://" + value + m_uriPath); - UriParts = m_uri.AbsolutePath.Split(UriSplitters, StringSplitOptions.RemoveEmptyEntries); + m_uriPath = m_uri.AbsolutePath; } catch (UriFormatException err) { @@ -421,8 +395,8 @@ namespace OSHttpServer m_body = null; m_contentLength = 0; m_method = string.Empty; - m_uri = HttpHelper.EmptyUri; - m_queryString = HttpInput.Empty; + m_uri = null; + m_queryString = null; m_bodyBytesLeft = 0; m_headers.Clear(); m_connection = ConnectionType.KeepAlive; diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpRequestParser.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpRequestParser.cs index 1ae5486441..5868187b2c 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpRequestParser.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/HttpRequestParser.cs @@ -123,12 +123,15 @@ namespace OSHttpServer.Parser string path = value.Substring(oldPos, pos - oldPos); if (path.Length > 4196) throw new BadRequestException("Too long URI."); + if (path == "*") + throw new BadRequestException("Not supported URI."); if (pos + 1 >= value.Length) { m_log.Write(this, LogPrio.Warning, "Invalid request line, missing HTTP-Version. Line: " + value); throw new BadRequestException("Invalid request line, missing HTTP-Version. Line: " + value); } + string version = value.Substring(pos + 1); if (version.Length < 4 || string.Compare(version.Substring(0, 4), "HTTP", true) != 0) { diff --git a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/IHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/IHttpRequest.cs index e65055a7d6..36525828c0 100644 --- a/OpenSim/Framework/Servers/HttpServer/OSHttpServer/IHttpRequest.cs +++ b/OpenSim/Framework/Servers/HttpServer/OSHttpServer/IHttpRequest.cs @@ -21,11 +21,6 @@ namespace OSHttpServer /// Stream Body { get; set; } - /// - /// Gets whether the body is complete. - /// - bool BodyIsComplete { get; } - /// /// Gets or sets kind of connection used for the session. /// @@ -84,28 +79,13 @@ namespace OSHttpServer /// /// Gets variables sent in the query string /// - HttpInput QueryString { get; } + NameValueCollection QueryString { get; } /// /// Gets or sets requested URI. /// Uri Uri { get; set; } - /// - /// Gets URI absolute path divided into parts. - /// - /// - /// // URI is: http://gauffin.com/code/tiny/ - /// Console.WriteLine(request.UriParts[0]); // result: code - /// Console.WriteLine(request.UriParts[1]); // result: tiny - /// - /// - /// If you're using controllers than the first part is controller name, - /// the second part is method name and the third part is Id property. - /// - /// - string[] UriParts { get; } - /// /// Gets or sets path and query. ///