/// <summary> /// Convets to string using the encoding specified in the content type header /// </summary> /// <param name="contentTypeHeader"></param> /// <param name="encoding">Outputs the encoding for further use</param> /// <returns></returns> public string ToString(string contentTypeHeader, out Encoding encoding) { string html = String.Empty; encoding = HttpUtil.GetEncoding(contentTypeHeader); Decoder decoder = encoding.GetDecoder(); if (_chunks.Count > 0) { LinkedListNode <byte[]> currChunk = _chunks.First; int charSize = 0; do { //get the number of unicode chars in the current secquence charSize += decoder.GetCharCount(currChunk.Value, 0, currChunk.Value.Length, true); currChunk = currChunk.Next; }while (currChunk != null); currChunk = _chunks.First; char[] chars = new char[charSize]; int totalLen = 0; do { //get the number of unicode chars in the current secquence int count = decoder.GetChars(currChunk.Value, 0, currChunk.Value.Length, chars, totalLen); totalLen += count; //add the current char size to the total length currChunk = currChunk.Next; }while (currChunk != null); //if the totalLen is smaller after the transformation shrink the chars html = new String(chars, 0, totalLen); } return(html); }
/// <summary> /// Parses the request /// </summary> /// <param name="requestBytes"></param> /// <param name="parseVariables">Whether to parse parameters for the request</param> private void ParseRequest(byte [] requestBytes, bool parseVariables) { MemoryStream ms = new MemoryStream(requestBytes); byte [] lineBytes = Utils.ReadLine(ms, ESTIMATED_LINE_SIZE, LineEnding.Any); string requestLine = Constants.DefaultEncoding.GetString(lineBytes); if (!InitMethod(requestLine)) { //the request line is not long enough to read the method return; } //extract version int lastSpace = requestLine.LastIndexOf(' '); if (lastSpace > -1) { _httpVersion = requestLine.Substring(lastSpace + 1); } //extract query string int firstQuestionMark = requestLine.LastIndexOf('?'); if (firstQuestionMark > -1) { _queryString = requestLine.Substring(firstQuestionMark + 1); int endOfQuery = _queryString.LastIndexOf(' '); if (endOfQuery > -1) { _queryString = _queryString.Substring(0, endOfQuery); } } //iterate through the lines as long as there is no empty line which would separate post data string line; do { lineBytes = Utils.ReadLine(ms, ESTIMATED_LINE_SIZE, LineEnding.Any); if (lineBytes != null && lineBytes.Length > 0) { line = Constants.DefaultEncoding.GetString(lineBytes); string [] nameAndValue = line.Split(new char[] { ':' }, 3); if (nameAndValue.Length == 2) { _headers.Add(nameAndValue[0], nameAndValue[1].Trim()); } else if (nameAndValue.Length == 3) { if (String.IsNullOrWhiteSpace(nameAndValue[0])) { _headers.Add(String.Join(":", nameAndValue[0], nameAndValue[1]), nameAndValue[2].Trim()); } else { _headers.Add(nameAndValue[0], String.Join(":", nameAndValue[1], nameAndValue[2]).Trim()); } } } }while (lineBytes != null && lineBytes.Length > 0); //initialize encoding string contentTypeValue = _headers["Content-Type"]; if (contentTypeValue != null) { _contentEncoding = HttpUtil.GetEncoding(contentTypeValue); } if (lineBytes != null) //we read an empty line signaling that the headers are over { _isFullRequest = true; string contentLenHeaderString = _headers["Content-Length"]; if (contentLenHeaderString != null || IsPost || IsPut) { int contentLenHeaderVal = 0; int.TryParse(contentLenHeaderString, out contentLenHeaderVal); long pos = ms.Position; int contentLength = (int)(ms.Length - pos); if (contentLenHeaderVal > contentLength) { _isFullRequest = false; } _contentData = new byte[contentLength]; ms.Read(_contentData, 0, contentLength); } } else { _isFullRequest = false; //we didn't finish reading the headers } if (_headers["Host"] != null) { PopulateHostAndPort(_headers["Host"]); } else if (_headers[":authority"] != null) { PopulateHostAndPort(_headers[":authority"]); } int indexOfPath = _method.Length + 1; string temp = requestLine.Substring(indexOfPath); //remove the query and the http version if (_httpVersion != String.Empty) { temp = temp.Replace(_httpVersion, String.Empty); } if (_queryString != String.Empty) { temp = temp.Replace(String.Format("?{0} ", _queryString), String.Empty); } string protocol = String.Empty; //remove the protocol://host if (temp.IndexOf("https://", StringComparison.OrdinalIgnoreCase) == 0) { _isSecure = true; protocol = "https://"; } else if (temp.IndexOf("http://", StringComparison.OrdinalIgnoreCase) == 0) { _isProxyHttp = true; _isSecure = false; protocol = "http://"; } if (protocol != String.Empty) //this is a proxy request { // skip the protocol string and process whatever comes after that (hostAndPort, and then Path) // we already checked that temp starts with protocol and protocol is not empty temp = temp.Substring(protocol.Length); //next extract host and port //find the first fw slash int indexOfFws = temp.IndexOf('/'); string hostAndPort = temp.Substring(0, indexOfFws); PopulateHostAndPort(hostAndPort); temp = temp.Substring(indexOfFws); } _path = temp.TrimEnd(' '); //construct a search regex string _regexPath = Regex.Escape(_path); if (parseVariables) { ParseVariables(); } //in the case of custom parameters in the path make sure to remove from the regex if (_pathVariables.Count > 0) { _regexPath = NormalizePath(_regexPath, ".+"); } _searchRegex = String.Format("{0} ({1}[^/]+)?{2}[\\s|\\?]", _method, _isSecure ? "https://" : "http://", _regexPath); //replace any dynamic elements _searchRegex = _searchRegex.Replace(Constants.DYNAMIC_ELEM_STRING, ".+"); _path = _path.TrimEnd(' ', '?'); }