Exemple #1
0
        internal bool Read(Stream stream, IPEndPoint endPoint)
        {
            byte[] buffer = new byte[1024];
            RequestParserState state = RequestParserState.ReadMethod;
            string key = "";
            string value = "";
            MemoryStream ms = null;

            DateTime begin = DateTime.Now;
            DateTime lastByteReceived = begin;

            if (endPoint != null)
                UserHostAddress = endPoint.Address.ToString();

            while (true)
            {
                if (state == RequestParserState.ReadDone)
                    return true;

                int bytesRead = 0;
                int idx = 0;

#if(MF)
                // set all bytes to null byte (strings are ending with null byte in MF)
                Array.Clear(buffer, 0, buffer.Length);
#endif

                try
                {
                    bytesRead = stream.Read(buffer, 0, buffer.Length);

                    if (bytesRead > 0)
                        lastByteReceived = DateTime.Now;
                }
                catch (IOException)
                {
                    break;
                }
                catch (Exception)
                {
                    DateTime nd = DateTime.Now;
#if(MF)
                    if((nd.Ticks - lastByteReceived.Ticks) / TimeSpan.TicksPerMillisecond > MAX_REQUEST_SLIDING_TIMEOUT)
                        break;
#else
                    if ((nd - lastByteReceived).TotalMilliseconds > MAX_REQUEST_SLIDING_TIMEOUT)
                        break;
#endif

                    if (HttpMethod == "POST" && (_body == null || _body.Length < ContentLength))
                        continue;

#if(MF)
                    if((nd.Ticks - begin.Ticks) / TimeSpan.TicksPerMillisecond < MAX_REQUEST_TIMEOUT)
                        continue;
#else
                    if ((nd - begin).TotalMilliseconds < MAX_REQUEST_TIMEOUT)
                        continue;
#endif

                    break;
                }

                if (bytesRead == 0)     // should never happen
                    break;

                totalBytes += bytesRead;

#if(FILELOG && !MF && !WindowsCE)
                File.AppendAllText("loghttp-" + socket.RemoteEndPoint.ToString().Replace(":", "-") + ".txt", Encoding.UTF8.GetString(buffer, 0, bytesRead) + "\r\n");
#endif

                if (totalBytes <= idx)
                    continue;

                do
                {
                    switch (state)
                    {
                        case RequestParserState.ReadMethod:
                            if (buffer[idx] != ' ')
                                HttpMethod += (char)buffer[idx++];
                            else
                            {
                                // TODO: add a allowed methods list

                                //if (HttpMethod != "POST" && HttpMethod != "GET" && HttpMethod != "OPTIONS")
                                //    throw new HttpException(HttpStatusCode.MethodNotAllowed);

                                idx++;
                                state = RequestParserState.ReadUrl;
                            }
                            break;

                        case RequestParserState.ReadUrl:
                            if (buffer[idx] == '?')
                            {
                                idx++;
                                key = "";
                                _params = new NameValueCollection();
                                state = RequestParserState.ReadParamKey;
                            }
                            else if (buffer[idx] != ' ')
                            {
                                RawUrl += (char)buffer[idx++];
                            }
                            else
                            {
                                idx++;
                                RawUrl = HttpServerUtility.UrlDecode(RawUrl);
                                state = RequestParserState.ReadVersion;
                            }
                            break;

                        case RequestParserState.ReadParamKey:
                            if (buffer[idx] == '=')
                            {
                                idx++;
                                value = "";
                                state = RequestParserState.ReadParamValue;
                            }
                            else if (buffer[idx] == ' ')
                            {
                                idx++;
                                RawUrl = HttpServerUtility.UrlDecode(RawUrl);
                                state = RequestParserState.ReadVersion;
                            }
                            else
                            {
                                key += (char)buffer[idx++];
                            }
                            break;

                        case RequestParserState.ReadParamValue:
                            if (buffer[idx] == '&')
                            {
                                idx++;
                                key = HttpServerUtility.UrlDecode(key);
                                value = HttpServerUtility.UrlDecode(value);

                                Params[key] = (Params[key] != null ? Params[key] + ", " + value : value);

                                key = "";
                                value = "";

                                state = RequestParserState.ReadParamKey;
                            }
                            else if (buffer[idx] == ' ')
                            {
                                idx++;
                                key = HttpServerUtility.UrlDecode(key);
                                value = HttpServerUtility.UrlDecode(value);

                                Params[key] = (Params[key] != null ? Params[key] + ", " + value : value);

                                RawUrl = HttpServerUtility.UrlDecode(RawUrl);

                                state = RequestParserState.ReadVersion;
                            }
                            else
                            {
                                value += (char)buffer[idx++];
                            }
                            break;

                        case RequestParserState.ReadVersion:
                            if (buffer[idx] == '\r')
                                idx++;
                            else if (buffer[idx] != '\n')
                                HttpVersion += (char)buffer[idx++];
                            else
                            {
                                if (HttpVersion != "HTTP/1.1" && HttpVersion != "HTTP/1.0")
                                    throw new HttpException(HttpStatusCode.HttpVersionNotSupported);

                                idx++;
                                key = "";
                                Headers = new NameValueCollection();
                                state = RequestParserState.ReadHeaderKey;
                            }
                            break;

                        case RequestParserState.ReadHeaderKey:
                            if (buffer[idx] == '\r')
                                idx++;
                            else if (buffer[idx] == '\n')
                            {
                                idx++;
                                if (HttpMethod == "POST")
                                    state = RequestParserState.ReadBody;
                                else
                                {
                                    state = RequestParserState.ReadDone;    // well, we don't really need this
                                    return true;
                                }
                            }
                            else if (buffer[idx] == ':')
                                idx++;
                            else if (buffer[idx] != ' ')
                                key += (char)buffer[idx++];
                            else
                            {
                                idx++;
                                value = "";
                                state = RequestParserState.ReadHeaderValue;
                            }
                            break;

                        case RequestParserState.ReadHeaderValue:
                            if (buffer[idx] == '\r')
                                idx++;
                            else if (buffer[idx] != '\n')
                                value += (char)buffer[idx++];
                            else
                            {
                                idx++;
                                Headers.Add(key, value);
                                key = "";
                                state = RequestParserState.ReadHeaderKey;
                            }
                            break;

                        case RequestParserState.ReadBody:

                            if (ContentLength > MAX_CONTENT_LENGTH)
                            {
                                // TODO: how can I stop the client to cancel http request
                                //throw new HttpException(HttpStatusCode.RequestEntitiyTooLarge);
                            }

                            if (ms == null)
                                ms = new MemoryStream();

                            ms.Write(buffer, idx, bytesRead - idx);
                            idx = bytesRead;
                            
                            if (ms.Length >= ContentLength)
                            {
                                _body = ms.ToArray();

                                // if using a <form/> tag with POST check if it is urlencoded or multipart boundary

                                if (ContentType.IndexOf("application/x-www-form-urlencoded") != -1)
                                {
                                    _form = new NameValueCollection();
                                    key = "";
                                    value = null;

                                    for (int i = 0; i < _body.Length; i++)
                                    {
                                        if (_body[i] == '=')
                                            value = "";
                                        else if (_body[i] == '&')
                                        {
                                            _form.Add(key, value != null ? HttpServerUtility.UrlDecode(value) : "");
                                            key = "";
                                            value = null;
                                        }
                                        else if (value == null)
                                            key += (char)_body[i];
                                        else if (value != null)
                                            value += (char)_body[i];
                                    }

                                    if (key != null && key.Length > 0)
                                    {
                                        _form.Add(key, value != null ? HttpServerUtility.UrlDecode(value) : "");
                                    }
                                }
                                else if (ContentType != null && ContentType.Length > "multipart/form-data; boundary=".Length && ContentType.Substring(0, "multipart/form-data; boundary=".Length) == "multipart/form-data; boundary=")
                                {
                                    string boundary = ContentType.Substring("multipart/form-data; boundary=".Length);

                                    _mime = new MimeContentCollection();

                                    MimeParser mp = new MimeParser(_body, boundary);

                                    MimeContent mime = mp.GetNextContent();
                                    while (mime != null)
                                    {
                                        _mime.Add(mime.Name, mime);

                                        if (mime.Headers["Content-Disposition"] != null && mime.Headers["Content-Disposition"].IndexOf("form-data") >= 0)
                                        {
                                            if (_form == null)
                                                _form = new NameValueCollection();

                                            _form.Add(mime.Name, (mime.Content != null && mime.Content.Length > 0 ? new string(Encoding.UTF8.GetChars(mime.Content)) : ""));
                                        }

                                        mime = mp.GetNextContent();
                                    }
                                }
                                state = RequestParserState.ReadDone;        // well, we don't really need this
                                return true;
                            }
                            break;

                        case RequestParserState.ReadDone:                   // well, we don't really need this
                            return true;

                        default:
                            //idx++;
                            break;

                    }
                }
                while (idx < bytesRead);
            }

            return false;
        }
 public MimeContentEnumerator(MimeContentCollection collection)
 {
     _collection = collection;
 }
        internal bool Read(Stream stream, IPEndPoint endPoint)
        {
            byte[] buffer = new byte[1024];
            RequestParserState state = RequestParserState.ReadMethod;
            string key = "";
            string value = "";
            MemoryStream ms = null;

            DateTime begin = DateTime.Now;
            DateTime lastByteReceived = begin;

            if (endPoint != null)
                UserHostAddress = endPoint.Address.ToString();

            while (true)
            {
                if (state == RequestParserState.ReadDone)
                    return true;

                int bytesRead = 0;
                int idx = 0;

#if(MF)
                // set all bytes to null byte (strings are ending with null byte in MF)
                Array.Clear(buffer, 0, buffer.Length);
#endif

                try
                {
                    bytesRead = stream.Read(buffer, 0, buffer.Length);

                    if (bytesRead > 0)
                        lastByteReceived = DateTime.Now;
                }
                catch (IOException)
                {
                    break;
                }
                catch (Exception)
                {
                    DateTime nd = DateTime.Now;
#if(MF)
                    if((nd.Ticks - lastByteReceived.Ticks) / TimeSpan.TicksPerMillisecond > MAX_REQUEST_SLIDING_TIMEOUT)
                        break;
#else
                 //   if ((nd - lastByteReceived).TotalMilliseconds > MAX_REQUEST_SLIDING_TIMEOUT)
                 //       break;
#endif

                    if (HttpMethod == "POST" && (_body == null || _body.Length < ContentLength))
                        continue;

#if(MF)
                    if((nd.Ticks - begin.Ticks) / TimeSpan.TicksPerMillisecond < MAX_REQUEST_TIMEOUT)
                        continue;
#else
                   // if ((nd - begin).TotalMilliseconds < MAX_REQUEST_TIMEOUT)
                   //     continue;
#endif

                    break;
                }

                if (bytesRead == 0)     // should never happen
                    break;

                totalBytes += bytesRead;

#if(FILELOG && !MF && !WindowsCE)
                File.AppendAllText("loghttp-" + socket.RemoteEndPoint.ToString().Replace(":", "-") + ".txt", Encoding.UTF8.GetString(buffer, 0, bytesRead) + "\r\n");
#endif

                if (totalBytes <= idx)
                    continue;

                do
                {
                    switch (state)
                    {
                        case RequestParserState.ReadMethod:
                            if (buffer[idx] != ' ')
                                HttpMethod += (char)buffer[idx++];
                            else
                            {
                                // TODO: add a allowed methods list

                                //if (HttpMethod != "POST" && HttpMethod != "GET" && HttpMethod != "OPTIONS")
                                //    throw new HttpException(HttpStatusCode.MethodNotAllowed);

                                idx++;
                                state = RequestParserState.ReadUrl;
                            }
                            break;

                        case RequestParserState.ReadUrl:
                            if (buffer[idx] == '?')
                            {
                                idx++;
                                key = "";
                                _params = new MFToolkit.Collection.Spezialized.NameValueCollection();
                                state = RequestParserState.ReadParamKey;
                            }
                            else if (buffer[idx] != ' ')
                            {
                                RawUrl += (char)buffer[idx++];
                            }
                            else
                            {
                                idx++;
                                RawUrl = HttpServerUtility.UrlDecode(RawUrl);
                                state = RequestParserState.ReadVersion;
                            }
                            break;

                        case RequestParserState.ReadParamKey:
                            if (buffer[idx] == '=')
                            {
                                idx++;
                                value = "";
                                state = RequestParserState.ReadParamValue;
                            }
                            else if (buffer[idx] == ' ')
                            {
                                idx++;
                                RawUrl = HttpServerUtility.UrlDecode(RawUrl);
                                state = RequestParserState.ReadVersion;
                            }
                            else
                            {
                                key += (char)buffer[idx++];
                            }
                            break;

                        case RequestParserState.ReadParamValue:
                            if (buffer[idx] == '&')
                            {
                                idx++;
                                key = HttpServerUtility.UrlDecode(key);
                                value = HttpServerUtility.UrlDecode(value);

                                Params[key] = (Params[key] != null ? Params[key] + ", " + value : value);

                                key = "";
                                value = "";

                                state = RequestParserState.ReadParamKey;
                            }
                            else if (buffer[idx] == ' ')
                            {
                                idx++;
                                key = HttpServerUtility.UrlDecode(key);
                                value = HttpServerUtility.UrlDecode(value);

                                Params[key] = (Params[key] != null ? Params[key] + ", " + value : value);

                                RawUrl = HttpServerUtility.UrlDecode(RawUrl);

                                state = RequestParserState.ReadVersion;
                            }
                            else
                            {
                                value += (char)buffer[idx++];
                            }
                            break;

                        case RequestParserState.ReadVersion:
                            if (buffer[idx] == '\r')
                                idx++;
                            else if (buffer[idx] != '\n')
                                HttpVersion += (char)buffer[idx++];
                            else
                            {
                                if (HttpVersion != "HTTP/1.1" && HttpVersion != "HTTP/1.0")
                                    throw new HttpException(HttpStatusCode.HttpVersionNotSupported);

                                idx++;
                                key = "";
                                Headers = new MFToolkit.Collection.Spezialized.NameValueCollection();
                                state = RequestParserState.ReadHeaderKey;
                            }
                            break;

                        case RequestParserState.ReadHeaderKey:
                            if (buffer[idx] == '\r')
                                idx++;
                            else if (buffer[idx] == '\n')
                            {
                                idx++;
                                if (HttpMethod == "POST")
                                    state = RequestParserState.ReadBody;
                                else
                                {
                                    state = RequestParserState.ReadDone;    // well, we don't really need this
                                    return true;
                                }
                            }
                            else if (buffer[idx] == ':')
                                idx++;
                            else if (buffer[idx] != ' ')
                                key += (char)buffer[idx++];
                            else
                            {
                                idx++;
                                value = "";
                                state = RequestParserState.ReadHeaderValue;
                            }
                            break;

                        case RequestParserState.ReadHeaderValue:
                            if (buffer[idx] == '\r')
                                idx++;
                            else if (buffer[idx] != '\n')
                                value += (char)buffer[idx++];
                            else
                            {
                                idx++;
                                Headers.Add(key, value);
                                key = "";
                                state = RequestParserState.ReadHeaderKey;
                            }
                            break;

                        case RequestParserState.ReadBody:

                            if (ContentLength > MAX_CONTENT_LENGTH)
                            {
                                // TODO: how can I stop the client to cancel http request
                                //throw new HttpException(HttpStatusCode.RequestEntitiyTooLarge);
                            }

                            if (ms == null)
                                ms = new MemoryStream();

                            ms.Write(buffer, idx, bytesRead - idx);
                            idx = bytesRead;
                            
                            if (ms.Length >= ContentLength)
                            {
                                _body = ms.ToArray();

                                // if using a <form/> tag with POST check if it is urlencoded or multipart boundary

                                if (ContentType.IndexOf("application/x-www-form-urlencoded") != -1)
                                {
                                    _form = new MFToolkit.Collection.Spezialized.NameValueCollection();
                                    key = "";
                                    value = null;

                                    for (int i = 0; i < _body.Length; i++)
                                    {
                                        if (_body[i] == '=')
                                            value = "";
                                        else if (_body[i] == '&')
                                        {
                                            _form.Add(key, value != null ? HttpServerUtility.UrlDecode(value) : "");
                                            key = "";
                                            value = null;
                                        }
                                        else if (value == null)
                                            key += (char)_body[i];
                                        else if (value != null)
                                            value += (char)_body[i];
                                    }

                                    if (key != null && key.Length > 0)
                                    {
                                        _form.Add(key, value != null ? HttpServerUtility.UrlDecode(value) : "");
                                    }
                                }
                                else if (ContentType != null && ContentType.Length > "multipart/form-data; boundary=".Length && ContentType.Substring(0, "multipart/form-data; boundary=".Length) == "multipart/form-data; boundary=")
                                {
                                    string boundary = ContentType.Substring("multipart/form-data; boundary=".Length);

                                    _mime = new MimeContentCollection();

                                    MimeParser mp = new MimeParser(_body, boundary);

                                    MimeContent mime = mp.GetNextContent();
                                    while (mime != null)
                                    {
                                        _mime.Add(mime.Name, mime);

                                        if (mime.Headers["Content-Disposition"] != null && mime.Headers["Content-Disposition"].IndexOf("form-data") >= 0)
                                        {
                                            if (_form == null)
                                                _form = new MFToolkit.Collection.Spezialized.NameValueCollection();

                                            _form.Add(mime.Name, (mime.Content != null && mime.Content.Length > 0 ? new string(Encoding.UTF8.GetChars(mime.Content)) : ""));
                                        }

                                        mime = mp.GetNextContent();
                                    }
                                }
                                state = RequestParserState.ReadDone;        // well, we don't really need this
                                return true;
                            }
                            break;

                        case RequestParserState.ReadDone:                   // well, we don't really need this
                            return true;

                        default:
                            //idx++;
                            break;

                    }
                }
                while (idx < bytesRead);
            }

            return false;
        }
 public MimeContentEnumerator(MimeContentCollection collection)
 {
     _collection = collection;
 }