/// <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);
        }
Beispiel #2
0
        /// <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(' ', '?');
        }