예제 #1
0
    public static HandshakeResponse Parse (string [] response)
    {
      var statusLine = response [0].Split (' ');
      if (statusLine.Length < 3)
        throw new ArgumentException ("Invalid status line.");

      var reason = new StringBuilder (statusLine [2], 64);
      for (int i = 3; i < statusLine.Length; i++)
        reason.AppendFormat (" {0}", statusLine [i]);

      var headers = new WebHeaderCollection ();
      for (int i = 1; i < response.Length; i++)
        headers.SetInternal (response [i], true);

      return new HandshakeResponse {
        Headers = headers,
        Reason = reason.ToString (),
        StatusCode = statusLine [1],
        ProtocolVersion = new Version (statusLine [0].Substring (5))
      };
    }
예제 #2
0
        internal void SendHeaders(bool closing, MemoryStream ms)
        {
            Encoding encoding = content_encoding;

            if (encoding == null)
            {
                encoding = Encoding.Default;
            }

            if (content_type != null)
            {
                if (content_encoding != null && content_type.IndexOf("charset=", StringComparison.Ordinal) == -1)
                {
                    string enc_name = content_encoding.WebName;
                    headers.SetInternal("Content-Type", content_type + "; charset=" + enc_name);
                }
                else
                {
                    headers.SetInternal("Content-Type", content_type);
                }
            }

            if (headers ["Server"] == null)
            {
                headers.SetInternal("Server", "Mono-HTTPAPI/1.0");
            }

            CultureInfo inv = CultureInfo.InvariantCulture;

            if (headers ["Date"] == null)
            {
                headers.SetInternal("Date", DateTime.UtcNow.ToString("r", inv));
            }

            if (!chunked)
            {
                if (!cl_set && closing)
                {
                    cl_set         = true;
                    content_length = 0;
                }

                if (cl_set)
                {
                    headers.SetInternal("Content-Length", content_length.ToString(inv));
                }
            }

            Version v = context.Request.ProtocolVersion;

            if (!cl_set && !chunked && v >= HttpVersion.Version11)
            {
                chunked = true;
            }

            /* Apache forces closing the connection for these status codes:
             *	HttpStatusCode.BadRequest               400
             *	HttpStatusCode.RequestTimeout           408
             *	HttpStatusCode.LengthRequired           411
             *	HttpStatusCode.RequestEntityTooLarge    413
             *	HttpStatusCode.RequestUriTooLong        414
             *	HttpStatusCode.InternalServerError      500
             *	HttpStatusCode.ServiceUnavailable       503
             */
            bool conn_close = (status_code == 400 || status_code == 408 || status_code == 411 ||
                               status_code == 413 || status_code == 414 || status_code == 500 ||
                               status_code == 503);

            if (conn_close == false)
            {
                conn_close = !context.Request.KeepAlive;
            }

            // They sent both KeepAlive: true and Connection: close!?
            if (!keep_alive || conn_close)
            {
                headers.SetInternal("Connection", "close");
                conn_close = true;
            }

            if (chunked)
            {
                headers.SetInternal("Transfer-Encoding", "chunked");
            }

            int reuses = context.Connection.Reuses;

            if (reuses >= 100)
            {
                force_close_chunked = true;
                if (!conn_close)
                {
                    headers.SetInternal("Connection", "close");
                    conn_close = true;
                }
            }

            if (!conn_close)
            {
                headers.SetInternal("Keep-Alive", String.Format("timeout=15,max={0}", 100 - reuses));
                if (context.Request.ProtocolVersion <= HttpVersion.Version10)
                {
                    headers.SetInternal("Connection", "keep-alive");
                }
            }

            if (location != null)
            {
                headers.SetInternal("Location", location);
            }

            if (cookies != null)
            {
                foreach (Cookie cookie in cookies)
                {
                    headers.SetInternal("Set-Cookie", cookie.ToClientString());
                }
            }

            StreamWriter writer = new StreamWriter(ms, encoding, 256);

            writer.Write("HTTP/{0} {1} {2}\r\n", version, status_code, status_description);
            string headers_str = headers.ToStringMultiValue();

            writer.Write(headers_str);
            writer.Flush();
            int preamble = (encoding.CodePage == 65001) ? 3 : encoding.GetPreamble().Length;

            if (output_stream == null)
            {
                output_stream = context.Connection.GetResponseStream();
            }

            /* Assumes that the ms was at position 0 */
            ms.Position = preamble;
            HeadersSent = true;
        }
예제 #3
0
        public static HandshakeResponse Parse(string [] headerParts)
        {
            var statusLine = headerParts [0].Split (new char [] { ' ' }, 3);
              if (statusLine.Length != 3)
            throw new ArgumentException ("Invalid status line: " + headerParts [0]);

              var headers = new WebHeaderCollection ();
              for (int i = 1; i < headerParts.Length; i++)
            headers.SetInternal (headerParts [i], true);

              return new HandshakeResponse {
            Headers = headers,
            ProtocolVersion = new Version (statusLine [0].Substring (5)),
            Reason = statusLine [2],
            StatusCode = statusLine [1]
              };
        }
        internal void AddHeader(string header)
        {
            var colon = header.IndexOf(':');

            if (colon <= 0)
            {
                _context.ErrorMessage = "Invalid header";
                return;
            }

            var name  = header.Substring(0, colon).Trim();
            var val   = header.Substring(colon + 1).Trim();
            var lower = name.ToLower(CultureInfo.InvariantCulture);

            _headers.SetInternal(name, val, false);

            if (lower == "accept")
            {
                _acceptTypes = val.SplitHeaderValue(',').ToArray();
                return;
            }

            if (lower == "accept-language")
            {
                _userLanguages = val.Split(',');
                return;
            }

            if (lower == "content-length")
            {
                long length;
                if (Int64.TryParse(val, out length) && length >= 0)
                {
                    _contentLength       = length;
                    _contentLengthWasSet = true;
                }
                else
                {
                    _context.ErrorMessage = "Invalid Content-Length header";
                }

                return;
            }

            if (lower == "content-type")
            {
                var contents = val.Split(';');
                foreach (var content in contents)
                {
                    var tmp = content.Trim();
                    if (tmp.StartsWith("charset"))
                    {
                        var charset = tmp.GetValue("=");
                        if (!charset.IsNullOrEmpty())
                        {
                            try {
                                _contentEncoding = Encoding.GetEncoding(charset);
                            } catch {
                                _context.ErrorMessage = "Invalid Content-Type header";
                            }
                        }

                        break;
                    }
                }

                return;
            }

            if (lower == "referer")
            {
                _referer = val.ToUri();
            }
        }
예제 #5
0
        internal void AddHeader(string header)
        {
            int colon = header.IndexOf(':');

            if (colon == -1 || colon == 0)
            {
                context.ErrorMessage = "Bad Request";
                context.ErrorStatus  = 400;
                return;
            }

            string name  = header.Substring(0, colon).Trim();
            string val   = header.Substring(colon + 1).Trim();
            string lower = name.ToLower(CultureInfo.InvariantCulture);

            headers.SetInternal(name, val);
            switch (lower)
            {
            case "accept-language":
                user_languages = val.Split(',');                          // yes, only split with a ','
                break;

            case "accept":
                accept_types = val.Split(',');                          // yes, only split with a ','
                break;

            case "content-length":
                try {
                    //TODO: max. content_length?
                    content_length = Int64.Parse(val.Trim());
                    if (content_length < 0)
                    {
                        context.ErrorMessage = "Invalid Content-Length.";
                    }
                    cl_set = true;
                } catch {
                    context.ErrorMessage = "Invalid Content-Length.";
                }

                break;

            case "referer":
                try {
                    referrer = new Uri(val);
                } catch {
                    referrer = new Uri("http://someone.is.screwing.with.the.headers.com/");
                }
                break;

            case "cookie":
                if (cookies == null)
                {
                    cookies = new CookieCollection();
                }

                string[] cookieStrings = val.Split(new char[] { ',', ';' });
                Cookie   current       = null;
                int      version       = 0;
                foreach (string cookieString in cookieStrings)
                {
                    string str = cookieString.Trim();
                    if (str.Length == 0)
                    {
                        continue;
                    }
                    if (str.StartsWith("$Version"))
                    {
                        version = Int32.Parse(Unquote(str.Substring(str.IndexOf('=') + 1)));
                    }
                    else if (str.StartsWith("$Path"))
                    {
                        if (current != null)
                        {
                            current.Path = str.Substring(str.IndexOf('=') + 1).Trim();
                        }
                    }
                    else if (str.StartsWith("$Domain"))
                    {
                        if (current != null)
                        {
                            current.Domain = str.Substring(str.IndexOf('=') + 1).Trim();
                        }
                    }
                    else if (str.StartsWith("$Port"))
                    {
                        if (current != null)
                        {
                            current.Port = str.Substring(str.IndexOf('=') + 1).Trim();
                        }
                    }
                    else
                    {
                        if (current != null)
                        {
                            cookies.Add(current);
                        }
                        current = new Cookie();
                        int idx = str.IndexOf('=');
                        if (idx > 0)
                        {
                            current.Name  = str.Substring(0, idx).Trim();
                            current.Value = str.Substring(idx + 1).Trim();
                        }
                        else
                        {
                            current.Name  = str.Trim();
                            current.Value = String.Empty;
                        }
                        current.Version = version;
                    }
                }
                if (current != null)
                {
                    cookies.Add(current);
                }
                break;
            }
        }
        public static RequestHandshake Parse(string[] request)
        {
            var requestLine = request[0].Split(' ');
              if (requestLine.Length != 3)
              {
            var msg = "Invalid HTTP Request-Line: " + request[0];
            throw new ArgumentException(msg, "request");
              }

              var headers = new WebHeaderCollection();
              for (int i = 1; i < request.Length; i++)
            headers.SetInternal(request[i], false);

              return new RequestHandshake {
            Headers         = headers,
            HttpMethod      = requestLine[0],
            RequestUri      = requestLine[1].ToUri(),
            ProtocolVersion = new Version(requestLine[2].Substring(5))
              };
        }
예제 #7
0
        public static HandshakeRequest Parse(string [] headerParts)
        {
            var requestLine = headerParts [0].Split (new char [] { ' ' }, 3);
              if (requestLine.Length != 3)
            throw new ArgumentException ("Invalid request line: " + headerParts [0]);

              var headers = new WebHeaderCollection ();
              for (int i = 1; i < headerParts.Length; i++)
            headers.SetInternal (headerParts [i], false);

              return new HandshakeRequest {
            Headers = headers,
            HttpMethod = requestLine [0],
            ProtocolVersion = new Version (requestLine [2].Substring (5)),
            RawUrl = requestLine [1],
            RequestUri = requestLine [1].ToUri ()
              };
        }
예제 #8
0
        internal void SendHeaders(bool closing, MemoryStream stream)
        {
            if (_contentType != null)
            {
                if (_contentEncoding != null &&
                    _contentType.IndexOf("charset=", StringComparison.Ordinal) == -1)
                {
                    var charset = _contentEncoding.WebName;
                    _headers.SetInternal(
                        "Content-Type", _contentType + "; charset=" + charset, true);
                }
                else
                {
                    _headers.SetInternal("Content-Type", _contentType, true);
                }
            }

            if (_headers ["Server"] == null)
            {
                _headers.SetInternal("Server", "websocket-sharp/1.0", true);
            }

            var provider = CultureInfo.InvariantCulture;

            if (_headers ["Date"] == null)
            {
                _headers.SetInternal(
                    "Date", DateTime.UtcNow.ToString("r", provider), true);
            }

            if (!_chunked)
            {
                if (!_contentLengthSet && closing)
                {
                    _contentLengthSet = true;
                    _contentLength    = 0;
                }

                if (_contentLengthSet)
                {
                    _headers.SetInternal(
                        "Content-Length", _contentLength.ToString(provider), true);
                }
            }

            var version = _context.Request.ProtocolVersion;

            if (!_contentLengthSet && !_chunked && version >= HttpVersion.Version11)
            {
                _chunked = true;
            }

            /* Apache forces closing the connection for these status codes:
             *   HttpStatusCode.BadRequest            400
             *   HttpStatusCode.RequestTimeout        408
             *   HttpStatusCode.LengthRequired        411
             *   HttpStatusCode.RequestEntityTooLarge 413
             *   HttpStatusCode.RequestUriTooLong     414
             *   HttpStatusCode.InternalServerError   500
             *   HttpStatusCode.ServiceUnavailable    503
             */
            var connClose = _statusCode == 400 ||
                            _statusCode == 408 ||
                            _statusCode == 411 ||
                            _statusCode == 413 ||
                            _statusCode == 414 ||
                            _statusCode == 500 ||
                            _statusCode == 503;

            if (!connClose)
            {
                connClose = !_context.Request.KeepAlive;
            }

            // They sent both KeepAlive: true and Connection: close!?
            if (!_keepAlive || connClose)
            {
                _headers.SetInternal("Connection", "close", true);
                connClose = true;
            }

            if (_chunked)
            {
                _headers.SetInternal("Transfer-Encoding", "chunked", true);
            }

            int reuses = _context.Connection.Reuses;

            if (reuses >= 100)
            {
                _forceCloseChunked = true;
                if (!connClose)
                {
                    _headers.SetInternal("Connection", "close", true);
                    connClose = true;
                }
            }

            if (!connClose)
            {
                _headers.SetInternal(
                    "Keep-Alive",
                    String.Format("timeout=15,max={0}", 100 - reuses), true);
                if (_context.Request.ProtocolVersion <= HttpVersion.Version10)
                {
                    _headers.SetInternal("Connection", "keep-alive", true);
                }
            }

            if (_location != null)
            {
                _headers.SetInternal("Location", _location, true);
            }

            if (_cookies != null)
            {
                foreach (Cookie cookie in _cookies)
                {
                    _headers.SetInternal("Set-Cookie", cookie.ToResponseString(), true);
                }
            }

            var encoding = _contentEncoding ?? Encoding.Default;
            var writer   = new StreamWriter(stream, encoding, 256);

            writer.Write(
                "HTTP/{0} {1} {2}\r\n", _version, _statusCode, _statusDescription);
            var headers = _headers.ToStringMultiValue(true);

            writer.Write(headers);
            writer.Flush();
            var preamble = encoding.CodePage == 65001 ? 3 : encoding.GetPreamble().Length;

            if (_outputStream == null)
            {
                _outputStream = _context.Connection.GetResponseStream();
            }

            // Assumes that the stream was at position 0.
            stream.Position = preamble;
            HeadersSent     = true;
        }