* MonoHttpDate.cs: added
[mono.git] / mcs / class / System / System.Net / HttpWebResponse.cs
1 //\r
2 // System.Net.HttpWebResponse\r
3 //\r
4 // Author:\r
5 //   Lawrence Pit (loz@cable.a2000.nl)\r
6 //\r
7 \r
8 using System;\r
9 using System.IO;\r
10 using System.Runtime.Serialization;\r
11 \r
12 namespace System.Net \r
13 {\r
14         [Serializable]\r
15         public class HttpWebResponse : WebResponse, ISerializable, IDisposable\r
16         {\r
17                 private Uri uri;\r
18                 private WebHeaderCollection webHeaders;\r
19                 private CookieCollection cookieCollection = null;\r
20                 private string method = null;\r
21                 private Version version = null;\r
22                 private HttpStatusCode statusCode;\r
23                 private string statusDescription = null;\r
24 \r
25                 private Stream responseStream;          \r
26                 private bool disposed = false;\r
27                 \r
28                 // Constructors\r
29                 \r
30                 internal HttpWebResponse (Uri uri, string method, Stream responseStream) \r
31                 { \r
32                         this.uri = uri;\r
33                         this.method = method;\r
34                         this.responseStream = responseStream;\r
35                         \r
36                         // TODO: parse headers from responseStream\r
37                         \r
38                         this.statusCode = HttpStatusCode.OK;\r
39                 }\r
40                 \r
41                 protected HttpWebResponse (SerializationInfo serializationInfo, StreamingContext streamingContext)\r
42                 {\r
43                         throw new NotSupportedException ();\r
44                 }\r
45                 \r
46                 // Properties\r
47                 \r
48                 public string CharacterSet {\r
49                         // Content-Type   = "Content-Type" ":" media-type\r
50                         // media-type     = type "/" subtype *( ";" parameter )\r
51                         // parameter      = attribute "=" value\r
52                         // 3.7.1. default is ISO-8859-1\r
53                         get { \r
54                                 try {\r
55                                         string contentType = ContentType;\r
56                                         if (contentType == null)\r
57                                                 return "ISO-8859-1";\r
58                                         string val = contentType.ToLower ();                                    \r
59                                         int pos = val.IndexOf ("charset=");\r
60                                         if (pos == -1)\r
61                                                 return "ISO-8859-1";\r
62                                         pos += 8;\r
63                                         int pos2 = val.IndexOf (';', pos);\r
64                                         return (pos2 == -1)\r
65                                              ? contentType.Substring (pos) \r
66                                              : contentType.Substring (pos, pos2 - pos);\r
67                                 } finally {\r
68                                         CheckDisposed ();\r
69                                 }\r
70                         }\r
71                 }\r
72                 \r
73                 public string ContentEncoding {\r
74                         get { \r
75                                 try { return webHeaders ["Content-Encoding"]; }\r
76                                 finally { CheckDisposed (); }\r
77                         }\r
78                 }\r
79                 \r
80                 public override long ContentLength {            \r
81                         get { \r
82                                 try {\r
83                                         return Int64.Parse (webHeaders ["Content-Length"]); \r
84                                 } catch (Exception) {\r
85                                         return -1;\r
86                                 } finally {\r
87                                         CheckDisposed ();\r
88                                 }\r
89                         }\r
90                 }\r
91                 \r
92                 public override string ContentType {            \r
93                         get { \r
94                                 try { return webHeaders ["Content-Type"]; }\r
95                                 finally { CheckDisposed (); }\r
96                         }\r
97                 }\r
98                 \r
99                 public CookieCollection Cookies {\r
100                         get { \r
101                                 CheckDisposed ();\r
102                                 \r
103                                 // LAMESPEC: a simple test reveal this always \r
104                                 // returns an empty collection. It is not filled \r
105                                 // with the values from the Set-Cookie or \r
106                                 // Set-Cookie2 response headers, which is a bit\r
107                                 // of a shame..\r
108                                 if (cookieCollection == null)\r
109                                         cookieCollection = new CookieCollection ();\r
110                                 return cookieCollection;\r
111                         }\r
112                         set {\r
113                                 CheckDisposed ();\r
114                                 // ?? don't understand how you can set cookies on a response.\r
115                                 throw new NotSupportedException ();\r
116                         }\r
117                 }\r
118                 \r
119                 public override WebHeaderCollection Headers {           \r
120                         get { \r
121                                 CheckDisposed ();\r
122                                 return webHeaders; \r
123                         }\r
124                 }\r
125                 \r
126                 public DateTime LastModified {\r
127                         get {\r
128                                 CheckDisposed ();\r
129                                 try {\r
130                                         string dtStr = webHeaders ["Last-Modified"];\r
131                                         return MonoHttpDate.Parse (dtStr);\r
132                                 } catch (Exception) {\r
133                                         return DateTime.Now;    \r
134                                 }\r
135                         }\r
136                 }\r
137                 \r
138                 public string Method {\r
139                         get { \r
140                                 CheckDisposed ();\r
141                                 return method; \r
142                         }\r
143                 }\r
144                 \r
145                 public Version ProtocolVersion {\r
146                         get { \r
147                                 CheckDisposed ();\r
148                                 return version; \r
149                         }\r
150                 }\r
151                 \r
152                 public override Uri ResponseUri {               \r
153                         get { \r
154                                 CheckDisposed ();\r
155                                 return uri; \r
156                         }\r
157                 }               \r
158                 \r
159                 public string Server {\r
160                         get { \r
161                                 try {\r
162                                         return webHeaders ["Server"]; \r
163                                 } finally {\r
164                                         CheckDisposed ();\r
165                                 }\r
166                         }\r
167                 }\r
168                 \r
169                 public HttpStatusCode StatusCode {\r
170                         get { \r
171                                 CheckDisposed ();\r
172                                 return statusCode; \r
173                         }\r
174                 }\r
175                 \r
176                 public string StatusDescription {\r
177                         get { \r
178                                 CheckDisposed ();\r
179                                 return statusDescription; \r
180                         }\r
181                 }\r
182 \r
183                 // Methods\r
184                 \r
185                 public override int GetHashCode ()\r
186                 {\r
187                         try {\r
188                                 return base.GetHashCode ();\r
189                         } finally {\r
190                                 CheckDisposed ();\r
191                         }\r
192                 }\r
193                 \r
194                 public string GetResponseHeader (string headerName)\r
195                 {\r
196                         try {\r
197                                 return webHeaders [headerName];\r
198                         } finally {\r
199                                 CheckDisposed ();\r
200                         }\r
201                 }\r
202                 \r
203                 public override Stream GetResponseStream ()\r
204                 {\r
205                         try {\r
206                                 if (method.Equals ("HEAD")) // see par 4.3 & 9.4\r
207                                         return Stream.Null;  \r
208                                 return responseStream;\r
209                         } finally {\r
210                                 CheckDisposed ();\r
211                         }\r
212                 }\r
213                 \r
214                 [MonoTODO]\r
215                 void ISerializable.GetObjectData (SerializationInfo serializationInfo,\r
216                                                   StreamingContext streamingContext)\r
217                 {\r
218                         CheckDisposed ();\r
219                         throw new NotImplementedException ();\r
220                 }               \r
221 \r
222 \r
223                 // Cleaning up stuff\r
224 \r
225                 ~HttpWebResponse ()\r
226                 {\r
227                         Dispose (false);\r
228                 }               \r
229                 \r
230                 public override void Close ()\r
231                 {\r
232                         ((IDisposable) this).Dispose ();\r
233                 }\r
234                 \r
235                 void IDisposable.Dispose ()\r
236                 {\r
237                         Dispose (true);\r
238                         GC.SuppressFinalize (this);  \r
239                 }\r
240                 \r
241                 protected virtual void Dispose (bool disposing) \r
242                 {\r
243                         if (this.disposed)\r
244                                 return;\r
245                         this.disposed = true;\r
246                         \r
247                         if (disposing) {\r
248                                 // release managed resources\r
249                                 uri = null;\r
250                                 webHeaders = null;\r
251                                 cookieCollection = null;\r
252                                 method = null;\r
253                                 version = null;\r
254                                 // statusCode = null;\r
255                                 statusDescription = null;\r
256                         }\r
257                         \r
258                         // release unmanaged resources\r
259                         Stream stream = responseStream;\r
260                         responseStream = null;\r
261                         if (stream != null)\r
262                                 stream.Close ();  // also closes webRequest                     \r
263                 }\r
264                 \r
265                 private void CheckDisposed () \r
266                 {\r
267                         if (disposed)\r
268                                 throw new ObjectDisposedException (GetType ().FullName);\r
269                 }\r
270         }       \r
271 }