using System; using System.IO; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Reflection; using System.Linq; using System.Text.RegularExpressions; namespace System.Net.ApiService { public class RequestHeader { public enum eMethod : byte { Get, Post, Delete, Put, Patch, Trace, Options, Connect } public enum eConnection : byte { Close, KeepAlive } public enum eEncoder : byte { none = 0, deflate = 1, gzip = 2, compress = 4, identity = 8, br = 16 } protected string _Path; protected NameValueCollection _Query; protected NameValueCollection _Post; protected HttpMethod _Method; protected string _UserAgent; protected int _UpgradeInsecureRequests; protected string _Pragma; protected string _Host; protected bool _DNT; protected eConnection _Connection; protected string _CacheControl; protected string _AcceptLanguage; protected eEncoder _AcceptEncoding; protected string _Accept; protected string _blankRequest; protected string _referer; protected int _contentLength = 0; protected string _contentType; protected string _boundary = ""; protected List Boundaries = new List(); public string Request(string variable) { if (this._Query.AllKeys.Contains(variable)) return this._Query[variable]; if (this._Post != null && this._Post.AllKeys.Contains(variable)) return this._Post[variable]; return ""; } public string Request(string variable, string defaultValue) { if (this._Query.AllKeys.Contains(variable)) return this._Query[variable]; if (this._Post !=null && this._Post.AllKeys.Contains(variable)) return this._Post[variable]; return default; } public string Path { get { return this._Path; } } public string Blank { get { return this._blankRequest; } } public NameValueCollection Query { get { return this._Query; } } public string QueryString { get { string s = ""; foreach (KeyValuePair k in this._Query) s += (s!=""?"&":"") + k.Key + "=" + k.Value; return s; } } public NameValueCollection Post { get { return this._Post; } } public int ContentLength { get => this._contentLength; } public string ContentType { get => this._contentType; } public string Boundary { get => this._boundary; } public string PostString { get { string s = ""; foreach (KeyValuePair k in this._Post) s += (s != "" ? "&" : "") + k.Key + "=" + k.Value; return s; } } public HttpMethod Method { get { return this._Method; } } public string UserAgent { get { return this._UserAgent; } } public int UpgradeInsecureRequests { get { return this._UpgradeInsecureRequests; } } public string Pragma { get { return this._Pragma; } } public string Host { get { return this._Host; } } public string CacheControl { get { return this._CacheControl; } } public string Referer { get { return this._referer; } } public bool DNT { get { return this._DNT; } } public eConnection Connection { get { return this._Connection; } } public string AcceptLanguage { get { return this._AcceptLanguage; } } public eEncoder AcceptEncoding { get { return this._AcceptEncoding; } } public string Accept { get { return this._Accept; } } public void SetPostData(string content) { string[] qis = content.Split('&'); foreach (string qi in qis) { if (qi.Contains("=")) { string variable = System.Web.HttpUtility.UrlDecode(qi.Substring(0, qi.IndexOf("="))); string value = System.Web.HttpUtility.UrlDecode(qi.Substring(qi.IndexOf("=") + 1)); if (variable != "") { this.Post.Add(variable, value); } } } } public void SetPostData(NameValueCollection content) { foreach (string qi in content.AllKeys) { this._Post[qi] = content[qi]; } } public RequestHeader() { } public override string ToString() { string res = ""; switch (this._Method) { case HttpMethod.GET: res = "GET " + this._Path + (this._Query.Count > 0 ? "?" + this.QueryString : "") + " HTTP/1.1\r\n"; break; case HttpMethod.POST: res = "POST " + this._Path + (this._Query.Count > 0 ? "?" + this.QueryString : "") + " HTTP/1.1\r\n"; break; case HttpMethod.PUT: res = "PUT " + this._Path + (this._Query.Count > 0 ? "?" + this.QueryString : "") + " HTTP/1.1\r\n"; break; case HttpMethod.DELETE: res = "GET " + this._Path + (this._Query.Count > 0 ? "?" + this.QueryString : "") + " HTTP/1.1\r\n"; break; } res += "Host: " + this._Host + "\r\n"; if(this._UserAgent.Length > 0) res += "UserAgent: " + this._UserAgent + "\r\n"; if (this._Pragma.Length > 0) res += "Pragma: " + this._Pragma + "\r\n"; if (this._DNT) res += "DNT: 1\r\n"; if (this._referer.Length>0) res += "Referer: "+this._referer+"\r\n"; if (this._Accept.Length > 0) res += "Accept: " + this._Accept + "\r\n"; if (this._AcceptEncoding != eEncoder.none) { string enc = ""; if ((this._AcceptEncoding | eEncoder.br) == this._AcceptEncoding) enc += (enc == "" ? "" : "; ") + "br"; res += "Accept: " + enc + "\r\n"; } return res; } public RequestHeader(string buffer) { //TODO: Request Header - requested path must cut down ../ at the beginning! System.Diagnostics.Debug.WriteLine("RequestHeader()"); this._blankRequest = buffer; string[] lines = buffer.Split('\n'); if (lines.Length > 1) { string[] firstLine = lines[0].Trim().Split(' '); if (firstLine.Length == 3) { switch (firstLine[0].ToLower()) { case "get": this._Method = HttpMethod.GET; break; case "post": this._Method = HttpMethod.POST; break; case "put": this._Method = HttpMethod.PUT; break; case "delete": this._Method = HttpMethod.DELETE; break; case "patch": this._Method = HttpMethod.PATCH; break; case "trace": this._Method = HttpMethod.TRACE; break; case "options": this._Method = HttpMethod.OPTIONS; break; case "connect": this._Method = HttpMethod.CONNECT; break; default: // invalid header System.Diagnostics.Debug.WriteLine("Invalid header - Method '" + firstLine[0] + "' not allowed"); break; } this._Path = firstLine[1].Split('?')[0]; this._Query = new NameValueCollection(); if (firstLine[1].Contains('?')) { string q = firstLine[1].Split('?')[1]; string[] qis = q.Split('&'); foreach (string qi in qis) { if (qi.Contains("=")) { string variable = System.Web.HttpUtility.UrlDecode(qi.Substring(0, qi.IndexOf("="))); string value = System.Web.HttpUtility.UrlDecode(qi.Substring(qi.IndexOf("=") + 1)); if (variable != "") { //System.Diagnostics.Debug.WriteLine("Query String: '" + variable + "' = '" + value + "'"); this.Query.Add(variable, value); } } } } for (int i = 1, c = lines.Length; i < c; i++) { if (lines[i].Trim() != "" && lines[i].Contains(":")) { string variable = lines[i].Substring(0, lines[i].IndexOf(":")).Trim().ToLower(); string value = lines[i].Substring(lines[i].IndexOf(":") + 1).Trim(); System.Diagnostics.Debug.WriteLine("- '" + variable + "': '" + value + "'"); if (variable != "") { switch (variable) { case "user-agent": this._UserAgent = value; break; case "upgrade-insecure-requests": int.TryParse(value, out this._UpgradeInsecureRequests); break; case "pragma": this._Pragma = value; break; case "host": this._Host = value; break; case "dnt": int xDoNotTrack = 0; int.TryParse(value, out xDoNotTrack); this._DNT = (xDoNotTrack == 1); break; case "connection": if (value.ToLower() == "keep-alive") { this._Connection = eConnection.KeepAlive; } else { this._Connection = eConnection.Close; } break; case "cache-control": this._CacheControl = value; break; case "accept-language": this._AcceptLanguage = value; break; case "content-length": int.TryParse(value, out this._contentLength); break; case "content-type": string[] ct = value.Split(';'); this._contentType = ct[0]; if(ct.Length>1) { ct[1] = ct[1].Trim(); if(ct[1].StartsWith("boundary=")) { string boundary = ct[1].Substring(9); if (boundary.StartsWith("\"") && boundary.EndsWith("\"")) boundary = boundary.Substring(1, boundary.Length - 2); this._boundary = boundary; } } break; case "accept-encoding": string[] encodings = value.Split(','); foreach (string enc in encodings) { if (enc.Trim() == "gzip") this._AcceptEncoding |= eEncoder.gzip; if (enc.Trim() == "deflate") this._AcceptEncoding |= eEncoder.deflate; if (enc.Trim() == "br") this._AcceptEncoding |= eEncoder.br; if (enc.Trim() == "compress") this._AcceptEncoding |= eEncoder.compress; if (enc.Trim() == "identity") this._AcceptEncoding |= eEncoder.identity; } break; case "accept": this._Accept = value; break; case "referer": this._referer = value; break; default: System.Diagnostics.Debug.WriteLine("Header field unknown: " + variable + ": " + value); break; } } } } } else { // Invalid header System.Diagnostics.Debug.WriteLine("Invalid header - First line has " + firstLine.Length + " parts"); } } else { // invalid header System.Diagnostics.Debug.WriteLine("Invalid header - There are only " + lines.Length + " lines"); } } } }