// constructors

        internal FileWebResponse(FileWebRequest request, Uri uri, FileAccess access, bool asyncHint) {
            GlobalLog.Enter("FileWebResponse::FileWebResponse", "uri="+uri+", access="+access+", asyncHint="+asyncHint);
            try {
                m_fileAccess = access;
                if (access == FileAccess.Write) {
                    m_stream = Stream.Null;
                } else {

                    //
                    // apparently, specifying async when the stream will be read
                    // synchronously, or vice versa, can lead to a 10x perf hit.
                    // While we don't know how the app will read the stream, we
                    // use the hint from whether the app called BeginGetResponse
                    // or GetResponse to supply the async flag to the stream ctor
                    //

                    m_stream = new FileWebStream(request,
                                                 uri.LocalPath,
                                                 FileMode.Open,
                                                 FileAccess.Read,
                                                 FileShare.Read,
                                                 DefaultFileStreamBufferSize,
                                                 asyncHint
                                                 );
                    m_contentLength = m_stream.Length;
                }
                m_headers = new WebHeaderCollection(WebHeaderCollectionType.FileWebResponse);
                m_headers.AddInternal(HttpKnownHeaderNames.ContentLength, m_contentLength.ToString(NumberFormatInfo.InvariantInfo));
                m_headers.AddInternal(HttpKnownHeaderNames.ContentType, DefaultFileContentType);
                m_uri = uri;
            } catch (Exception e) {
                Exception ex = new WebException(e.Message, e, WebExceptionStatus.ConnectFailure, null);
                GlobalLog.LeaveException("FileWebResponse::FileWebResponse", ex);
                throw ex;
            }
            catch {
                Exception ex = new WebException(string.Empty, new Exception(SR.GetString(SR.net_nonClsCompliantException)), WebExceptionStatus.ConnectFailure, null);
                GlobalLog.LeaveException("FileWebResponse::FileWebResponse", ex);
                throw ex;
            }
            GlobalLog.Leave("FileWebResponse::FileWebResponse");
        }
            // Server API

            internal static WebHeaderCollection GetHeaders(byte[] memoryBlob, IntPtr originalAddress)
            {
                GlobalLog.Enter("HttpApi::GetHeaders()");

                // Return value.
                WebHeaderCollection headerCollection = new WebHeaderCollection(WebHeaderCollectionType.HttpListenerRequest);
                fixed (byte* pMemoryBlob = memoryBlob)
                {
                    HTTP_REQUEST* request = (HTTP_REQUEST*) pMemoryBlob;
                    long fixup = pMemoryBlob - (byte*) originalAddress;
                    int index;

                    // unknown headers
                    if (request->Headers.UnknownHeaderCount != 0)
                    {
                        HTTP_UNKNOWN_HEADER* pUnknownHeader = (HTTP_UNKNOWN_HEADER*) (fixup + (byte*) request->Headers.pUnknownHeaders);
                        for (index = 0; index < request->Headers.UnknownHeaderCount; index++)
                        {
                            // For unknown headers, when header value is empty, RawValueLength will be 0 and 
                            // pRawValue will be null.
                            if (pUnknownHeader->pName != null && pUnknownHeader->NameLength > 0)
                            {
                                string headerName = new string(pUnknownHeader->pName + fixup, 0, pUnknownHeader->NameLength);
                                string headerValue;
                                if (pUnknownHeader->pRawValue != null && pUnknownHeader->RawValueLength > 0) {
                                    headerValue = new string(pUnknownHeader->pRawValue + fixup, 0, pUnknownHeader->RawValueLength);
                                }
                                else {
                                    headerValue = string.Empty;
                                }
                                headerCollection.AddInternal(headerName, headerValue);
                            }
                            pUnknownHeader++;
                        }
                    }

                    // known headers
                    HTTP_KNOWN_HEADER* pKnownHeader = &request->Headers.KnownHeaders;
                    for (index = 0; index < HttpHeaderRequestMaximum; index++)
                    {
                        // For known headers, when header value is empty, RawValueLength will be 0 and 
                        // pRawValue will point to empty string ("\0")
                        if (pKnownHeader->pRawValue != null)
                        {
                            string headerValue = new string(pKnownHeader->pRawValue + fixup, 0, pKnownHeader->RawValueLength);
                            headerCollection.AddInternal(HTTP_REQUEST_HEADER_ID.ToString(index), headerValue);
                        }
                        pKnownHeader++;
                    }
                }

                GlobalLog.Leave("HttpApi::GetHeaders()");
                return headerCollection;
            }
예제 #3
0
        /// <summary>
        /// Parses request from client.
        /// Fills
        /// - HTTP Verb.
        /// - HTTP version.
        /// - Content Length.
        /// - Fills generic value name pair in WEB header collection.
        /// </summary>
        internal void ParseHTTPRequest()
        {
            // This is the request line.
            m_RequestString = m_clientStream.Read_HTTP_Line(HttpWebRequest.maxHTTPLineLength).Trim();

            // Split request line into 3 strings - VERB, URL and HTTP version.
            char[]   delimiter  = { ' ' };
            string[] requestStr = m_RequestString.Split(delimiter);
            // requestStr should consist of 3 parts.
            if (requestStr.Length < 3)
            {
                throw new ProtocolViolationException("Invalid HTTP request String: " + m_RequestString);
            }

            // We have at least 3 strings. Fills the proper fields
            m_requestVerb = requestStr[0];
            m_rawURL      = requestStr[1];

            // Process third string. It should be either http/1.1 or http/1.0
            string httpVerLowerCase = requestStr[2].ToLower();

            if (httpVerLowerCase.Equals("http/1.1"))
            {
                m_requestHttpVer = HttpVersion.Version11;
            }
            else if (httpVerLowerCase.Equals("http/1.0"))
            {
                m_requestHttpVer = HttpVersion.Version10;
            }
            else
            {
                throw new ProtocolViolationException("Unsupported HTTP version: " + requestStr[2]);
            }

            // Now it is list of HTTP headers:
            string line;
            int    headersLen = m_maxResponseHeadersLen;

            while ((line = m_clientStream.Read_HTTP_Header(HttpWebRequest.maxHTTPLineLength)).Length > 0)
            {
                // line.Length is used for the header. Substruct it.
                headersLen -= line.Length;
                // If total length used for header is exceeded, we break

                if (headersLen < 0)
                {
                    throw new ProtocolViolationException("Http Headers exceeding: " + m_maxResponseHeadersLen);
                }

                int sepIdx = line.IndexOf(':');
                if (sepIdx == -1)
                {
                    throw new ProtocolViolationException("Invalid HTTP Header: " + line);
                }

                string headerName          = line.Substring(0, sepIdx).Trim();
                string headerValue         = line.Substring(sepIdx + 1).Trim();
                string matchableHeaderName = headerName.ToLower();
                // Adds new header to collection.
                m_httpRequestHeaders.AddInternal(headerName, headerValue);

                // Now we check the value - name pair. For some of them we need to initilize member variables.
                headerName = headerName.ToLower();
                // If it is connection header
                if (headerName == "connection")
                {
                    // If value is "Keep-Alive" ( lower case now ), set m_KeepAlive to true;
                    headerValue = headerValue.ToLower();
                    m_KeepAlive = headerValue == "keep-alive";
                }

                // If user supplied user name and password - parse it and store in m_NetworkCredentials
                if (headerName == "authorization")
                {
                    int    sepSpace = headerValue.IndexOf(' ');
                    string authType = headerValue.Substring(0, sepSpace);
                    if (authType.ToLower() == "basic")
                    {
                        string authInfo = headerValue.Substring(sepSpace + 1);
                        // authInfo is base64 encoded username and password.
                        byte[] authInfoDecoded = Convert.FromBase64String(authInfo);
                        char[] authInfoDecChar = System.Text.Encoding.UTF8.GetChars(authInfoDecoded);
                        string strAuthInfo     = new string(authInfoDecChar);
                        // The strAuthInfo comes in format username:password. Parse it.
                        int sepColon = strAuthInfo.IndexOf(':');
                        if (sepColon != -1)
                        {
                            m_NetworkCredentials = new NetworkCredential(strAuthInfo.Substring(0, sepColon), strAuthInfo.Substring(sepColon + 1));
                        }
                    }
                }
            }

            // Http headers were processed. Now we search for content length.
            string strContentLen = m_httpRequestHeaders[HttpKnownHeaderNames.ContentLength];

            if (strContentLen != null)
            {
                try
                {
                    m_contentLength = Convert.ToInt32(strContentLen);
                }
                catch (Exception)
                {
                    throw new ProtocolViolationException("Invalid content length in request: " + strContentLen);
                }
            }
        }
예제 #4
0
        bool GetResponse(BufferOffsetSize buffer, ref int pos, ref ReadState state)
        {
            string line           = null;
            bool   lineok         = false;
            bool   isContinue     = false;
            bool   emptyFirstLine = false;

            do
            {
                if (state == ReadState.Aborted)
                {
                    throw GetReadException(WebExceptionStatus.RequestCanceled, null, "GetResponse");
                }

                if (state == ReadState.None)
                {
                    lineok = WebConnection.ReadLine(buffer.Buffer, ref pos, buffer.Offset, ref line);
                    if (!lineok)
                    {
                        return(false);
                    }

                    if (line == null)
                    {
                        emptyFirstLine = true;
                        continue;
                    }
                    emptyFirstLine = false;
                    state          = ReadState.Status;

                    string[] parts = line.Split(' ');
                    if (parts.Length < 2)
                    {
                        throw GetReadException(WebExceptionStatus.ServerProtocolViolation, null, "GetResponse");
                    }

                    if (String.Compare(parts[0], "HTTP/1.1", true) == 0)
                    {
                        Version = HttpVersion.Version11;
                        ServicePoint.SetVersion(HttpVersion.Version11);
                    }
                    else
                    {
                        Version = HttpVersion.Version10;
                        ServicePoint.SetVersion(HttpVersion.Version10);
                    }

                    StatusCode = (HttpStatusCode)UInt32.Parse(parts[1]);
                    if (parts.Length >= 3)
                    {
                        StatusDescription = String.Join(" ", parts, 2, parts.Length - 2);
                    }
                    else
                    {
                        StatusDescription = string.Empty;
                    }

                    if (pos >= buffer.Size)
                    {
                        return(true);
                    }
                }

                emptyFirstLine = false;
                if (state == ReadState.Status)
                {
                    state   = ReadState.Headers;
                    Headers = new WebHeaderCollection();
                    var  headerList = new List <string> ();
                    bool finished   = false;
                    while (!finished)
                    {
                        if (WebConnection.ReadLine(buffer.Buffer, ref pos, buffer.Offset, ref line) == false)
                        {
                            break;
                        }

                        if (line == null)
                        {
                            // Empty line: end of headers
                            finished = true;
                            continue;
                        }

                        if (line.Length > 0 && (line[0] == ' ' || line[0] == '\t'))
                        {
                            int count = headerList.Count - 1;
                            if (count < 0)
                            {
                                break;
                            }

                            string prev = headerList[count] + line;
                            headerList[count] = prev;
                        }
                        else
                        {
                            headerList.Add(line);
                        }
                    }

                    if (!finished)
                    {
                        return(false);
                    }

                    // .NET uses ParseHeaders or ParseHeadersStrict which is much better
                    foreach (string s in headerList)
                    {
                        int pos_s = s.IndexOf(':');
                        if (pos_s == -1)
                        {
                            throw new ArgumentException("no colon found", "header");
                        }

                        var header = s.Substring(0, pos_s);
                        var value  = s.Substring(pos_s + 1).Trim();

                        if (WebHeaderCollection.AllowMultiValues(header))
                        {
                            Headers.AddInternal(header, value);
                        }
                        else
                        {
                            Headers.SetInternal(header, value);
                        }
                    }

                    if (StatusCode == HttpStatusCode.Continue)
                    {
                        ServicePoint.SendContinue = true;
                        if (pos >= buffer.Offset)
                        {
                            return(true);
                        }

                        if (Request.ExpectContinue)
                        {
                            Request.DoContinueDelegate((int)StatusCode, Headers);
                            // Prevent double calls when getting the
                            // headers in several packets.
                            Request.ExpectContinue = false;
                        }

                        state      = ReadState.None;
                        isContinue = true;
                    }
                    else
                    {
                        state = ReadState.Content;
                        return(true);
                    }
                }
            } while (emptyFirstLine || isContinue);

            throw GetReadException(WebExceptionStatus.ServerProtocolViolation, null, "GetResponse");
        }
 internal static unsafe WebHeaderCollection GetHeaders(byte[] memoryBlob, IntPtr originalAddress)
 {
     WebHeaderCollection headers = new WebHeaderCollection(WebHeaderCollectionType.HttpListenerRequest);
     fixed (byte* numRef = memoryBlob)
     {
         int num2;
         HTTP_REQUEST* http_requestPtr = (HTTP_REQUEST*) numRef;
         long num = (long) ((numRef - ((void*) originalAddress)) / 1);
         if (http_requestPtr->Headers.UnknownHeaderCount != 0)
         {
             HTTP_UNKNOWN_HEADER* http_unknown_headerPtr = ((HTTP_UNKNOWN_HEADER*) num) + http_requestPtr->Headers.pUnknownHeaders;
             for (num2 = 0; num2 < http_requestPtr->Headers.UnknownHeaderCount; num2++)
             {
                 if ((http_unknown_headerPtr->pName != null) && (http_unknown_headerPtr->NameLength > 0))
                 {
                     string str2;
                     string name = new string(http_unknown_headerPtr->pName + ((sbyte*) num), 0, http_unknown_headerPtr->NameLength);
                     if ((http_unknown_headerPtr->pRawValue != null) && (http_unknown_headerPtr->RawValueLength > 0))
                     {
                         str2 = new string(http_unknown_headerPtr->pRawValue + ((sbyte*) num), 0, http_unknown_headerPtr->RawValueLength);
                     }
                     else
                     {
                         str2 = string.Empty;
                     }
                     headers.AddInternal(name, str2);
                 }
                 http_unknown_headerPtr++;
             }
         }
         HTTP_KNOWN_HEADER* http_known_headerPtr = &http_requestPtr->Headers.KnownHeaders;
         for (num2 = 0; num2 < 0x29; num2++)
         {
             if (http_known_headerPtr->pRawValue != null)
             {
                 string str3 = new string(http_known_headerPtr->pRawValue + ((sbyte*) num), 0, http_known_headerPtr->RawValueLength);
                 headers.AddInternal(HTTP_REQUEST_HEADER_ID.ToString(num2), str3);
             }
             http_known_headerPtr++;
         }
     }
     return headers;
 }