The Labs \ Source Viewer \ SSCLI \ System.Net \ HttpWebResponse

  1. //------------------------------------------------------------------------------
  2. // <copyright file="HttpWebResponse.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Net
  16. {
  17.     using System.IO;
  18.     using System.IO.Compression;
  19.     using System.Runtime.Serialization;
  20.     using System.Globalization;
  21.     using System.Security.Cryptography.X509Certificates;
  22.     using System.Security.Permissions;
  23.    
  24.     //
  25.     // HttpWebResponse - Handles retrival of HTTP Response headers, und Data reads.
  26.     //
  27.    
  28.     /// <devdoc>
  29.     /// <para>
  30.     /// An HTTP-specific implementation of the
  31.     /// <see cref='System.Net.WebResponse'/> class.
  32.     /// </para>
  33.     /// </devdoc>
  34.     [Serializable()]
  35.     public class HttpWebResponse : WebResponse, ISerializable
  36.     {
  37.         // response Uri generated by the request.
  38.         private Uri m_Uri;
  39.         // response Verb gernated by the request
  40.         private KnownHttpVerb m_Verb;
  41.         // response values
  42.         private HttpStatusCode m_StatusCode;
  43.         private string m_StatusDescription;
  44.         // ConnectStream - for reading actual data
  45.         private Stream m_ConnectStream;
  46.        
  47.         private WebHeaderCollection m_HttpResponseHeaders;
  48.        
  49.         // Content Length needed for symantics, -1 if chunked
  50.         private long m_ContentLength;
  51.        
  52.         // for which response ContentType we will look for and parse the CharacterSet
  53.         private string m_MediaType;
  54.         private string m_CharacterSet = null;
  55.        
  56.         private bool m_IsVersionHttp11;
  57.        
  58.        
  59.         private CookieCollection m_cookies;
  60.         private bool m_disposed;
  61.         // = false;
  62.         private bool m_propertiesDisposed;
  63.         private bool m_UsesProxySemantics;
  64.         private bool m_IsMutuallyAuthenticated;
  65.        
  66.         //
  67.         // Internal Access to the Response Stream,
  68.         // public method is GetResponseStream
  69.         //
  70.         internal Stream ResponseStream {
  71.             get { return m_ConnectStream; }
  72.             set { m_ConnectStream = value; }
  73.         }
  74.         //
  75.         public override bool IsMutuallyAuthenticated {
  76.             get { return m_IsMutuallyAuthenticated; }
  77.         }
  78.         internal bool InternalSetIsMutuallyAuthenticated {
  79.             set { m_IsMutuallyAuthenticated = value; }
  80.         }
  81.        
  82.         /// <devdoc>
  83.         /// <para>[To be supplied.]</para>
  84.         /// </devdoc>
  85.         public CookieCollection Cookies {
  86.             get {
  87.                 CheckDisposed();
  88.                 if (m_cookies == null) {
  89.                     m_cookies = new CookieCollection();
  90.                 }
  91.                 return m_cookies;
  92.             }
  93.             set {
  94.                 CheckDisposed();
  95.                 m_cookies = value;
  96.             }
  97.         }
  98.        
  99.         // retreives response header object
  100.         /// <devdoc>
  101.         /// <para>
  102.         /// Gets
  103.         /// the headers associated with this response from the server.
  104.         /// </para>
  105.         /// </devdoc>
  106.         public override WebHeaderCollection Headers {
  107.             get { return m_HttpResponseHeaders; }
  108.         }
  109.        
  110.         // ContentLength, -1 indicates unknown value
  111.         /// <devdoc>
  112.         /// <para>
  113.         /// Gets the lenght of the content returned by the request.
  114.         /// </para>
  115.         /// </devdoc>
  116.         public override long ContentLength {
  117.             get { return m_ContentLength; }
  118.         }
  119.        
  120.         /// <devdoc>
  121.         /// <para>
  122.         /// Gets the
  123.         /// method used to encode the body of the response.
  124.         /// </para>
  125.         /// </devdoc>
  126.         public string ContentEncoding {
  127.             get {
  128.                 CheckDisposed();
  129.                 string contentEncoding = m_HttpResponseHeaders[HttpKnownHeaderNames.ContentEncoding];
  130.                 return contentEncoding == null ? string.Empty : contentEncoding;
  131.             }
  132.         }
  133.        
  134.         // Returns the Content-Type of the response.
  135.        
  136.         /// <devdoc>
  137.         /// <para>
  138.         /// Gets the content type of the
  139.         /// response.
  140.         /// </para>
  141.         /// </devdoc>
  142.         public override string ContentType {
  143.             get {
  144.                 CheckDisposed();
  145.                 string contentType = m_HttpResponseHeaders.ContentType;
  146.                 return contentType == null ? string.Empty : contentType;
  147.             }
  148.         }
  149.        
  150.        
  151.         /// <devdoc>
  152.         /// <para>[To be supplied.]</para>
  153.         /// </devdoc>
  154.         public string CharacterSet {
  155.             get {
  156.                 CheckDisposed();
  157.                 string contentType = m_HttpResponseHeaders.ContentType;
  158.                
  159.                 if (m_CharacterSet == null && !ValidationHelper.IsBlankString(contentType)) {
  160.                    
  161.                     //sets characterset so the branch is never executed again.
  162.                     m_CharacterSet = String.Empty;
  163.                    
  164.                     //first string is the media type
  165.                     string srchString = contentType.ToLower(CultureInfo.InvariantCulture);
  166.                    
  167.                     //media subtypes of text type has a default as specified by rfc 2616
  168.                     if (srchString.Trim().StartsWith("text/")) {
  169.                         m_CharacterSet = "ISO-8859-1";
  170.                     }
  171.                    
  172.                     //one of the parameters may be the character set
  173.                     //there must be at least a mediatype for this to be valid
  174.                     int i = srchString.IndexOf(";");
  175.                     if (i > 0) {
  176.                        
  177.                         //search the parameters
  178.                         while ((i = srchString.IndexOf("charset", i)) >= 0) {
  179.                            
  180.                             i += 7;
  181.                            
  182.                             //make sure the word starts with charset
  183.                             if (srchString[i - 8] == ';' || srchString[i - 8] == ' ') {
  184.                                
  185.                                 //skip whitespace
  186.                                 while (i < srchString.Length && srchString[i] == ' ')
  187.                                     i++;
  188.                                
  189.                                 //only process if next character is '='
  190.                                 //and there is a character after that
  191.                                 if (i < srchString.Length - 1 && srchString[i] == '=') {
  192.                                     i++;
  193.                                    
  194.                                     //get and trim character set substring
  195.                                     int j = srchString.IndexOf(';', i);
  196.                                     if (j > i)
  197.                                         m_CharacterSet = contentType.Substring(i, j).Trim();
  198.                                     else
  199.                                         m_CharacterSet = contentType.Substring(i).Trim();
  200.                                    
  201.                                     //done
  202.                                     break;
  203.                                 }
  204.                             }
  205.                         }
  206.                     }
  207.                 }
  208.                 return m_CharacterSet;
  209.             }
  210.         }
  211.        
  212.         /// <devdoc>
  213.         /// <para>
  214.         /// Gets the name of the server that sent the response.
  215.         /// </para>
  216.         /// </devdoc>
  217.         public string Server {
  218.             get {
  219.                 CheckDisposed();
  220.                 string server = m_HttpResponseHeaders.Server;
  221.                 return server == null ? string.Empty : server;
  222.             }
  223.         }
  224.        
  225.         /// <devdoc>
  226.         /// <para>
  227.         /// Gets the last
  228.         /// date and time that the content of the response was modified.
  229.         /// </para>
  230.         /// </devdoc>
  231.         public DateTime LastModified {
  232.             get {
  233.                 CheckDisposed();
  234.                
  235.                 string lastmodHeaderValue = m_HttpResponseHeaders.LastModified;
  236.                
  237.                 if (lastmodHeaderValue == null) {
  238.                     return DateTime.Now;
  239.                 }
  240.                 return HttpProtocolUtils.string2date(lastmodHeaderValue);
  241.             }
  242.         }
  243.        
  244.         // returns StatusCode
  245.         /// <devdoc>
  246.         /// <para>
  247.         /// Gets
  248.         /// a number indicating the status of the response.
  249.         /// </para>
  250.         /// </devdoc>
  251.         public HttpStatusCode StatusCode {
  252.             get { return m_StatusCode; }
  253.         }
  254.        
  255.         // returns StatusDescription
  256.         /// <devdoc>
  257.         /// <para>
  258.         /// Gets the status description returned with the response.
  259.         /// </para>
  260.         /// </devdoc>
  261.         public string StatusDescription {
  262.             get {
  263.                 CheckDisposed();
  264.                 return m_StatusDescription;
  265.             }
  266.         }
  267.        
  268.         // HTTP Version
  269.         /// <devdoc>
  270.         /// <para>
  271.         /// Gets
  272.         /// the version of the HTTP protocol used in the response.
  273.         /// </para>
  274.         /// </devdoc>
  275.         public Version ProtocolVersion {
  276.             get {
  277.                 CheckDisposed();
  278.                 return m_IsVersionHttp11 ? HttpVersion.Version11 : HttpVersion.Version10;
  279.             }
  280.         }
  281.        
  282.        
  283.         internal bool KeepAlive {
  284.             get {
  285.                 if (ProtocolVersion == HttpVersion.Version10) {
  286.                     string keepAliveHeader = Headers[HttpKnownHeaderNames.KeepAlive];
  287.                     return keepAliveHeader != null;
  288.                 }
  289.                 if (ProtocolVersion >= HttpVersion.Version11) {
  290.                     string connectionHeader;
  291.                     if (m_UsesProxySemantics) {
  292.                         connectionHeader = Headers[HttpKnownHeaderNames.ProxyConnection];
  293.                         if (connectionHeader != null) {
  294.                             return connectionHeader.ToLower(CultureInfo.InvariantCulture).IndexOf("close") < 0 || connectionHeader.ToLower(CultureInfo.InvariantCulture).IndexOf("keep-alive") >= 0;
  295.                         }
  296.                     }
  297.                     connectionHeader = Headers[HttpKnownHeaderNames.Connection];
  298.                     return connectionHeader == null || connectionHeader.ToLower(CultureInfo.InvariantCulture).IndexOf("close") < 0 || connectionHeader.ToLower(CultureInfo.InvariantCulture).IndexOf("keep-alive") >= 0;
  299.                 }
  300.                 return false;
  301.             }
  302.         }
  303.        
  304.        
  305. /*++
  306.             ResponseStream - Return the response stream.
  307.             This property returns the response stream for this response. The
  308.             response stream will do de-chunking, etc. as needed.
  309.             Input: Nothing. Property is readonly.
  310.             Returns: Response stream for response.
  311.         --*/       
  312.        
  313.        
  314.         /// <devdoc>
  315.         /// <para>Gets the stream used for reading the body of the response from the
  316.         /// server.</para>
  317.         /// </devdoc>
  318.         public override Stream GetResponseStream()
  319.         {
  320.             if (Logging.On)
  321.                 Logging.Enter(Logging.Web, this, "GetResponseStream", "");
  322.             CheckDisposed();
  323.            
  324.             if (!CanGetResponseStream()) {
  325.                 // give a blank stream in the HEAD case, which = 0 bytes of data
  326.                 if (Logging.On)
  327.                     Logging.Exit(Logging.Web, this, "GetResponseStream", Stream.Null);
  328.                 return Stream.Null;
  329.             }
  330.             if (Logging.On)
  331.                 Logging.PrintInfo(Logging.Web, "ContentLength=" + m_ContentLength);
  332.             if (Logging.On)
  333.                 Logging.Exit(Logging.Web, this, "GetResponseStream", m_ConnectStream);
  334.             return m_ConnectStream;
  335.         }
  336.        
  337. /*++
  338.             Close - Closes the Response after the use.
  339.             This causes the read stream to be closed.
  340.         --*/       
  341.        
  342.         public override void Close()
  343.         {
  344.             if (Logging.On)
  345.                 Logging.Enter(Logging.Web, this, "Close", "");
  346.             if (!m_disposed) {
  347.                 m_disposed = true;
  348.                 Stream stream = m_ConnectStream;
  349.                 ICloseEx icloseEx = stream as ICloseEx;
  350.                 if (icloseEx != null) {
  351.                         /* | CloseExState.Silent */                    icloseEx.CloseEx(CloseExState.Normal);
  352.                 }
  353.                 else if (stream != null) {
  354.                     stream.Close();
  355.                 }
  356.             }
  357.             if (Logging.On)
  358.                 Logging.Exit(Logging.Web, this, "Close", "");
  359.         }
  360.        
  361.         internal void Abort()
  362.         {
  363.             Stream stream = m_ConnectStream;
  364.             ICloseEx icloseEx = stream as ICloseEx;
  365.             try {
  366.                 if (icloseEx != null) {
  367.                     icloseEx.CloseEx(CloseExState.Abort);
  368.                 }
  369.                 else if (stream != null) {
  370.                     stream.Close();
  371.                 }
  372.             }
  373.             catch {
  374.             }
  375.         }
  376.        
  377.         // for backward compat
  378.         internal override void OnDispose()
  379.         {
  380.             m_propertiesDisposed = true;
  381.         }
  382.        
  383.         // true if we success a call to get ResponseStream, note this code
  384.         // is duplicated and should use code out of the HttpWebRequest
  385.         internal bool CanGetResponseStream()
  386.         {
  387.             return !m_Verb.ExpectNoContentResponse;
  388.            
  389.         }
  390.        
  391.        
  392.         internal HttpWebResponse(Uri responseUri, KnownHttpVerb verb, CoreResponseData coreData, string mediaType, bool usesProxySemantics, DecompressionMethods decompressionMethod)
  393.         {
  394.             m_Uri = responseUri;
  395.             m_Verb = verb;
  396.             m_MediaType = mediaType;
  397.             m_UsesProxySemantics = usesProxySemantics;
  398.            
  399.             m_ConnectStream = coreData.m_ConnectStream;
  400.             m_HttpResponseHeaders = coreData.m_ResponseHeaders;
  401.             m_ContentLength = coreData.m_ContentLength;
  402.             m_StatusCode = coreData.m_StatusCode;
  403.             m_StatusDescription = coreData.m_StatusDescription;
  404.             m_IsVersionHttp11 = coreData.m_IsVersionHttp11;
  405.            
  406.            
  407.             //if the returned contentlength is zero, preemptively invoke calldone on the stream.
  408.             //this will wake up any pending reads.
  409.             if (m_ContentLength == 0 && m_ConnectStream is ConnectStream) {
  410.                 ((ConnectStream)m_ConnectStream).CallDone();
  411.             }
  412.            
  413.             // handle Content-Location header, by combining it with the orginal request.
  414.             string contentLocation = m_HttpResponseHeaders[HttpKnownHeaderNames.ContentLocation];
  415.            
  416.             if (contentLocation != null) {
  417.                 try {
  418.                     m_Uri = new Uri(m_Uri, contentLocation);
  419.                 }
  420.                 catch (UriFormatException e) {
  421.                     GlobalLog.Assert("Exception on response Uri parsing.", e.ToString());
  422.                 }
  423.             }
  424.             // decompress responses by hooking up a final response Stream - only if user required it
  425.             if (decompressionMethod != DecompressionMethods.None) {
  426.                 string contentEncoding = m_HttpResponseHeaders[HttpKnownHeaderNames.ContentEncoding];
  427.                 if (contentEncoding != null) {
  428.                     if (((decompressionMethod & DecompressionMethods.GZip) != 0) && contentEncoding.IndexOf(HttpWebRequest.GZipHeader) != -1) {
  429.                         m_ConnectStream = new GZipWrapperStream(m_ConnectStream, CompressionMode.Decompress);
  430.                         m_ContentLength = -1;
  431.                         // unknown on compressed streams
  432.                         // Setting a response header after parsing will ruin the Common Header optimization.
  433.                         // This seems like a corner case. ContentEncoding could be added as a common header, with a special
  434.                         // property allowing it to be nulled.
  435.                         m_HttpResponseHeaders[HttpKnownHeaderNames.ContentEncoding] = null;
  436.                     }
  437.                     else if (((decompressionMethod & DecompressionMethods.Deflate) != 0) && contentEncoding.IndexOf(HttpWebRequest.DeflateHeader) != -1) {
  438.                         m_ConnectStream = new DeflateWrapperStream(m_ConnectStream, CompressionMode.Decompress);
  439.                         m_ContentLength = -1;
  440.                         // unknown on compressed streams
  441.                         // Setting a response header after parsing will ruin the Common Header optimization.
  442.                         // This seems like a corner case. ContentEncoding could be added as a common header, with a special
  443.                         // property allowing it to be nulled.
  444.                         m_HttpResponseHeaders[HttpKnownHeaderNames.ContentEncoding] = null;
  445.                     }
  446.                 }
  447.             }
  448.         }
  449.        
  450.         //
  451.         // ISerializable constructor
  452.         //
  453.         /// <devdoc>
  454.         /// <para>[To be supplied.]</para>
  455.         /// </devdoc>
  456.        
  457.         [Obsolete("Serialization is obsoleted for this type. http://go.microsoft.com/fwlink/?linkid=14202")]
  458.         protected HttpWebResponse(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext)
  459.         {
  460.             m_HttpResponseHeaders = (WebHeaderCollection)serializationInfo.GetValue("m_HttpResponseHeaders", typeof(WebHeaderCollection));
  461.             m_Uri = (Uri)serializationInfo.GetValue("m_Uri", typeof(Uri));
  462.             Version version = (Version)serializationInfo.GetValue("m_Version", typeof(Version));
  463.             m_IsVersionHttp11 = version.Equals(HttpVersion.Version11);
  464.             m_StatusCode = (HttpStatusCode)serializationInfo.GetInt32("m_StatusCode");
  465.             m_ContentLength = serializationInfo.GetInt64("m_ContentLength");
  466.             m_Verb = KnownHttpVerb.Parse(serializationInfo.GetString("m_Verb"));
  467.             m_StatusDescription = serializationInfo.GetString("m_StatusDescription");
  468.             m_MediaType = serializationInfo.GetString("m_MediaType");
  469.         }
  470.        
  471.         //
  472.         // ISerializable method
  473.         //
  474.         /// <internalonly/>
  475.         [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter, SerializationFormatter = true)]
  476.         void ISerializable.GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
  477.         {
  478.             GetObjectData(serializationInfo, streamingContext);
  479.         }
  480.        
  481.         //
  482.         // FxCop: provide a way for derived classes to access this method even if they reimplement ISerializable.
  483.         //
  484.        
  485.         [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
  486.         protected override void GetObjectData(SerializationInfo serializationInfo, StreamingContext streamingContext)
  487.         {
  488.             //
  489.             // for now disregard streamingContext.
  490.             // just Add all the members we need to deserialize to construct
  491.             // the object at deserialization time
  492.             //
  493.             // the following runtime types already support serialization:
  494.             // Boolean, Char, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, DateTime
  495.             // for the others we need to provide our own serialization
  496.             //
  497.             serializationInfo.AddValue("m_HttpResponseHeaders", m_HttpResponseHeaders, typeof(WebHeaderCollection));
  498.             serializationInfo.AddValue("m_Uri", m_Uri, typeof(Uri));
  499.             serializationInfo.AddValue("m_Version", ProtocolVersion, typeof(Version));
  500.             serializationInfo.AddValue("m_StatusCode", m_StatusCode);
  501.             serializationInfo.AddValue("m_ContentLength", m_ContentLength);
  502.             serializationInfo.AddValue("m_Verb", m_Verb.Name);
  503.             serializationInfo.AddValue("m_StatusDescription", m_StatusDescription);
  504.             serializationInfo.AddValue("m_MediaType", m_MediaType);
  505.             base.GetObjectData(serializationInfo, streamingContext);
  506.         }
  507.        
  508. /*++
  509.         Routine Description:
  510.             Gets response headers from parsed server response
  511.         Arguments:
  512.             headerName - HTTP header to search for matching header on.
  513.         Return Value:
  514.             string - contains the matched entry, if found
  515.         --*/       
  516.         /// <devdoc>
  517.         /// <para>
  518.         /// Gets a specified header value returned with the response.
  519.         /// </para>
  520.         /// </devdoc>
  521.         public string GetResponseHeader(string headerName)
  522.         {
  523.             CheckDisposed();
  524.            
  525.             string headerValue = m_HttpResponseHeaders[headerName];
  526.            
  527.             return ((headerValue == null) ? String.Empty : headerValue);
  528.         }
  529.        
  530.        
  531. /*++
  532.             ResponseUri  - Gets the final Response Uri, that includes any
  533.             changes that may have transpired from the orginal Request
  534.             This property returns Uri for this WebResponse.
  535.             Input: Nothing.
  536.             Returns: Response Uri for response.
  537.                     read-only
  538.         --*/       
  539.        
  540.         /// <devdoc>
  541.         /// <para>
  542.         /// Gets the Uniform Resource Indentifier (Uri) of the resource that returned the
  543.         /// response.
  544.         /// </para>
  545.         /// </devdoc>
  546.         public override Uri ResponseUri {
  547.             // read-only
  548.             get {
  549.                 CheckDisposed();
  550.                 return m_Uri;
  551.             }
  552.         }
  553.        
  554. /*
  555.             Accessor:  Method
  556.             Gets/Sets the http method of this request.
  557.             This method represents the Verb,
  558.             after any redirects
  559.             Returns: Method currently being used.
  560.         */       
  561.         /// <devdoc>
  562.         /// <para>
  563.         /// Gets the value of the method used to return the response.
  564.         /// </para>
  565.         /// </devdoc>
  566.         public string Method {
  567.             get {
  568.                 CheckDisposed();
  569.                 return m_Verb.Name;
  570.             }
  571.         }
  572.        
  573.         private void CheckDisposed()
  574.         {
  575.             if (m_propertiesDisposed) {
  576.                 throw new ObjectDisposedException(this.GetType().FullName);
  577.             }
  578.         }
  579.        
  580.     }
  581.     // class HttpWebResponse
  582.     // transfer ICloseEx behavior to nested compound stream.
  583.     internal class GZipWrapperStream : GZipStream, ICloseEx
  584.     {
  585.        
  586.         public GZipWrapperStream(Stream stream, CompressionMode mode) : base(stream, mode, false)
  587.         {
  588.         }
  589.        
  590.         void ICloseEx.CloseEx(CloseExState closeState)
  591.         {
  592.             ICloseEx icloseEx = BaseStream as ICloseEx;
  593.             if (icloseEx != null) {
  594.                 // since the internal Close() of GZipStream just does Close on our base stream
  595.                 // we don't have to call it anymore at this point
  596.                 icloseEx.CloseEx(closeState);
  597.             }
  598.             else {
  599.                 Close();
  600.             }
  601.         }
  602.        
  603.        
  604.        
  605.         public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
  606.         {
  607.            
  608.             if (buffer == null) {
  609.                 throw new ArgumentNullException("buffer");
  610.             }
  611.             if (offset < 0 || offset > buffer.Length) {
  612.                 throw new ArgumentOutOfRangeException("offset");
  613.             }
  614.             if (size < 0 || size > buffer.Length - offset) {
  615.                 throw new ArgumentOutOfRangeException("size");
  616.             }
  617.            
  618.             try {
  619.                 return base.BeginRead(buffer, offset, size, callback, state);
  620.             }
  621.             catch (Exception e) {
  622.                 try {
  623.                     if (NclUtilities.IsFatal(e))
  624.                         throw;
  625.                     if (e is System.IO.InvalidDataException || e is InvalidOperationException || e is IndexOutOfRangeException) {
  626.                         Close();
  627.                     }
  628.                 }
  629.                 catch {
  630.                 }
  631.                 throw e;
  632.             }
  633.         }
  634.        
  635.         public override int EndRead(IAsyncResult asyncResult)
  636.         {
  637.            
  638.             if (asyncResult == null) {
  639.                 throw new ArgumentNullException("asyncResult");
  640.             }
  641.            
  642.             try {
  643.                 return base.EndRead(asyncResult);
  644.             }
  645.             catch (Exception e) {
  646.                 try {
  647.                     if (NclUtilities.IsFatal(e))
  648.                         throw;
  649.                     if (e is System.IO.InvalidDataException || e is InvalidOperationException || e is IndexOutOfRangeException) {
  650.                         Close();
  651.                     }
  652.                 }
  653.                 catch {
  654.                 }
  655.                 throw e;
  656.             }
  657.         }
  658.        
  659.         public override int Read(byte[] buffer, int offset, int size)
  660.         {
  661.            
  662.             if (buffer == null) {
  663.                 throw new ArgumentNullException("buffer");
  664.             }
  665.             if (offset < 0 || offset > buffer.Length) {
  666.                 throw new ArgumentOutOfRangeException("offset");
  667.             }
  668.             if (size < 0 || size > buffer.Length - offset) {
  669.                 throw new ArgumentOutOfRangeException("size");
  670.             }
  671.            
  672.             try {
  673.                 return base.Read(buffer, offset, size);
  674.             }
  675.             catch (Exception e) {
  676.                 try {
  677.                     if (NclUtilities.IsFatal(e))
  678.                         throw;
  679.                    
  680.                     if (e is System.IO.InvalidDataException || e is InvalidOperationException || e is IndexOutOfRangeException) {
  681.                         Close();
  682.                     }
  683.                 }
  684.                 catch {
  685.                 }
  686.                 throw e;
  687.             }
  688.         }
  689.     }
  690.    
  691.    
  692.     internal class DeflateWrapperStream : DeflateStream, ICloseEx
  693.     {
  694.        
  695.         public DeflateWrapperStream(Stream stream, CompressionMode mode) : base(stream, mode, false)
  696.         {
  697.         }
  698.        
  699.         void ICloseEx.CloseEx(CloseExState closeState)
  700.         {
  701.             ICloseEx icloseEx = BaseStream as ICloseEx;
  702.             if (icloseEx != null) {
  703.                 // since the internal Close() of GZipStream just does Close on our base stream
  704.                 // we don't have to call it anymore at this point
  705.                 icloseEx.CloseEx(closeState);
  706.             }
  707.             else {
  708.                 Close();
  709.             }
  710.         }
  711.        
  712.        
  713.         public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
  714.         {
  715.            
  716.             if (buffer == null) {
  717.                 throw new ArgumentNullException("buffer");
  718.             }
  719.             if (offset < 0 || offset > buffer.Length) {
  720.                 throw new ArgumentOutOfRangeException("offset");
  721.             }
  722.             if (size < 0 || size > buffer.Length - offset) {
  723.                 throw new ArgumentOutOfRangeException("size");
  724.             }
  725.            
  726.             try {
  727.                 return base.BeginRead(buffer, offset, size, callback, state);
  728.             }
  729.             catch (Exception e) {
  730.                 try {
  731.                     if (NclUtilities.IsFatal(e))
  732.                         throw;
  733.                     if (e is System.IO.InvalidDataException || e is InvalidOperationException || e is IndexOutOfRangeException) {
  734.                         Close();
  735.                     }
  736.                 }
  737.                 catch {
  738.                 }
  739.                 throw e;
  740.             }
  741.         }
  742.        
  743.         public override int EndRead(IAsyncResult asyncResult)
  744.         {
  745.            
  746.             if (asyncResult == null) {
  747.                 throw new ArgumentNullException("asyncResult");
  748.             }
  749.            
  750.             try {
  751.                 return base.EndRead(asyncResult);
  752.             }
  753.             catch (Exception e) {
  754.                 try {
  755.                     if (NclUtilities.IsFatal(e))
  756.                         throw;
  757.                     if (e is System.IO.InvalidDataException || e is InvalidOperationException || e is IndexOutOfRangeException) {
  758.                         Close();
  759.                     }
  760.                 }
  761.                 catch {
  762.                 }
  763.                 throw e;
  764.             }
  765.         }
  766.        
  767.         public override int Read(byte[] buffer, int offset, int size)
  768.         {
  769.            
  770.             if (buffer == null) {
  771.                 throw new ArgumentNullException("buffer");
  772.             }
  773.             if (offset < 0 || offset > buffer.Length) {
  774.                 throw new ArgumentOutOfRangeException("offset");
  775.             }
  776.             if (size < 0 || size > buffer.Length - offset) {
  777.                 throw new ArgumentOutOfRangeException("size");
  778.             }
  779.            
  780.             try {
  781.                 return base.Read(buffer, offset, size);
  782.             }
  783.             catch (Exception e) {
  784.                 try {
  785.                     if (NclUtilities.IsFatal(e))
  786.                         throw;
  787.                     if (e is System.IO.InvalidDataException || e is InvalidOperationException || e is IndexOutOfRangeException) {
  788.                         Close();
  789.                     }
  790.                 }
  791.                 catch {
  792.                 }
  793.                 throw e;
  794.             }
  795.         }
  796.     }
  797.    
  798.    
  799.    
  800. }
  801. // namespace System.Net

Developer Fusion