2007-02-16 Geoff Norton <gnorton@customerdna.com>
[mono.git] / mcs / class / System / System.Net / HttpWebResponse.jvm.cs
1 using System;\r
2 using System.Collections.Specialized;\r
3 using System.Globalization;\r
4 using System.IO;\r
5 using System.Runtime;\r
6 using System.Runtime.Serialization;\r
7 using System.Security.Cryptography.X509Certificates;\r
8 \r
9 namespace System.Net\r
10 {\r
11         [Serializable]\r
12         public class HttpWebResponse : WebResponse,  IDisposable\r
13         {\r
14                 #region Fields\r
15                 private mainsoft.apache.commons.httpclient.HttpMethod _httpMethod;\r
16                 private CookieCollection _cookies;\r
17                 private WebHeaderCollection _headers;\r
18                 private string _statusDescription;\r
19                 private Version _version = null;\r
20                 private Uri _uri;\r
21                 private string _method;\r
22                 private Stream _responseStream;\r
23                 private mainsoft.apache.commons.httpclient.HttpState _state;\r
24                 private HttpStateCache _stateCache;\r
25                 private HttpStatusCode _statusCode;\r
26                 private bool _isStatusCodeInitialized = false;\r
27 \r
28                 private Type _httpStatusCodeType = typeof(HttpStatusCode);\r
29 \r
30                 private sbyte [] _responseBody;\r
31                 private bool _isHttpMethodClosed = false;\r
32                 #endregion\r
33 \r
34                 #region Constructors\r
35 \r
36                 internal HttpWebResponse(mainsoft.apache.commons.httpclient.HttpMethod httpMethod,\r
37                         mainsoft.apache.commons.httpclient.HttpState state,\r
38                         HttpStateCache stateCache,\r
39                         Uri uri, string method)\r
40                 {\r
41                         _httpMethod = httpMethod;\r
42                         _uri = uri;\r
43                         _method = method;\r
44                         _state = state;\r
45                         _stateCache = stateCache;\r
46                 }\r
47 \r
48                 #endregion\r
49 \r
50                 #region Properties\r
51 \r
52                 public CookieCollection Cookies\r
53                 {\r
54                         get\r
55                         {\r
56                                 if(_cookies == null)\r
57                                 {\r
58                                         _cookies = new CookieCollection();\r
59                                         FillCookies();\r
60 \r
61                                 }\r
62                                 return _cookies;\r
63                         }\r
64 \r
65                         set\r
66                         {\r
67                                 _cookies = value;\r
68                         }\r
69                 }\r
70 \r
71                 public override WebHeaderCollection Headers\r
72                 {\r
73                         get\r
74                         {\r
75                                 if(_headers == null)\r
76                                 {\r
77                                         _headers = new WebHeaderCollection();\r
78                                         FillHeaders();\r
79                                 }\r
80                                 return _headers;\r
81                         }\r
82                 }\r
83                 public override long ContentLength\r
84                 {\r
85                         get\r
86                         {\r
87                                 string val = Headers["Content-Length"];\r
88                                 if(val == null || val.Trim().Equals(""))\r
89                                         return -1L;\r
90                                 try\r
91                                 {\r
92                                         return Int64.Parse(val);\r
93                                 }\r
94                                 catch\r
95                                 {\r
96                                         return -1L;\r
97                                 }\r
98                         }\r
99                 }\r
100 \r
101 \r
102                 public string ContentEncoding\r
103                 {\r
104                         get\r
105                         {\r
106                                 return Headers["Content-Encoding"];\r
107                         }\r
108                 }\r
109 \r
110                 public override string ContentType\r
111                 {\r
112                         get\r
113                         {\r
114                                 return  Headers["Content-Type"];\r
115                         }\r
116                 }\r
117 \r
118                 public string CharacterSet\r
119                 {\r
120                         get\r
121                         {\r
122                                 string contentType = ContentType;\r
123                                 if (contentType == null)\r
124                                         return "ISO-8859-1";\r
125                                 string val = contentType.ToLower ();                                    \r
126                                 int pos = val.IndexOf ("charset=");\r
127                                 if (pos == -1)\r
128                                         return "ISO-8859-1";\r
129                                 pos += 8;\r
130                                 int pos2 = val.IndexOf (';', pos);\r
131                                 return (pos2 == -1)\r
132                                         ? contentType.Substring (pos) \r
133                                         : contentType.Substring (pos, pos2 - pos);\r
134                         }\r
135                 }\r
136 \r
137                 public string Server\r
138                 {\r
139                         get\r
140                         {\r
141                                 return Headers ["Server"];\r
142                         }\r
143                 }\r
144 \r
145                 public DateTime LastModified\r
146                 {\r
147                         get\r
148                         {\r
149                                 try\r
150                                 {\r
151                                         string val =  Headers["Last-Modified"];\r
152                                         return MonoHttpDate.Parse(val);\r
153                                 }\r
154                                 catch\r
155                                 {\r
156                                         return DateTime.Now;\r
157                                 }\r
158                         }\r
159                 }\r
160 \r
161                 public HttpStatusCode StatusCode\r
162                 {\r
163                         get\r
164                         {\r
165                                 if(_isStatusCodeInitialized == false)\r
166                                 {\r
167                                         int status = _httpMethod.getStatusCode();\r
168                                         _statusCode = (HttpStatusCode)Enum.Parse(_httpStatusCodeType, \r
169                                                 Enum.GetName(_httpStatusCodeType, status));\r
170                                         _isStatusCodeInitialized = true;\r
171                                 }\r
172 \r
173                                 return _statusCode;\r
174                         }\r
175                 }\r
176 \r
177                 public string StatusDescription\r
178                 {\r
179                         get\r
180                         {\r
181                                 if(_statusDescription == null)\r
182                                         _statusDescription = _httpMethod.getStatusText();\r
183                                 return _statusDescription;\r
184                         }\r
185                 }\r
186 \r
187                 public Version ProtocolVersion\r
188                 {\r
189                         get\r
190                         {\r
191                                 if(_version == null)\r
192                                         ParseVersion();\r
193                                 return _version;\r
194                         }\r
195                 }\r
196 \r
197                 public override Uri ResponseUri\r
198                 {\r
199                         get\r
200                         {\r
201                                 return _uri;\r
202                         }\r
203                 }\r
204 \r
205                 public string Method\r
206                 {\r
207                         get\r
208                         {\r
209                                 return _method;\r
210                         }\r
211                 }\r
212                 #endregion\r
213 \r
214                 #region Methods\r
215 \r
216                 internal void ReadAllAndClose()\r
217                 {\r
218                         if (_responseBody != null)\r
219                                 return;\r
220 \r
221                         object temp = null;\r
222                         if(_cookies == null)\r
223                         {\r
224                 temp = this.Cookies;\r
225                         }\r
226                         if(_headers == null)\r
227                         {\r
228                                 temp = this.Headers;\r
229                         }\r
230                         if(_isStatusCodeInitialized == false)\r
231                         {\r
232                                 temp = this.StatusCode;\r
233                         }\r
234                         if(_statusDescription == null)\r
235                         {\r
236                                 temp = this.StatusDescription;\r
237                         }\r
238                         if(_version == null)\r
239                         {\r
240                                 temp = this.ProtocolVersion;\r
241                         }\r
242 \r
243                         _responseBody = _httpMethod.getResponseBody();\r
244 #if DEBUG\r
245                         Console.WriteLine("The response body as string == {0}", System.Text.Encoding.UTF8.GetString((byte[])vmw.common.TypeUtils.ToByteArray(_responseBody)));\r
246 #endif\r
247                         this.Close();\r
248                 }\r
249 \r
250                 public override Stream GetResponseStream()\r
251                 {\r
252                         try\r
253                         {\r
254                                 if(_responseStream == null)\r
255                                 {\r
256                                         Type t = Type.GetType("System.IO.ConsoleReadStream", true);\r
257                                         object [] param = null;\r
258                                         if (_responseBody == null)\r
259                                         {\r
260                                                 param = new object[]{_httpMethod.getResponseBodyAsStream()};\r
261                                         }\r
262                                         else\r
263                                         {\r
264                                                 param = new object[]{new java.io.ByteArrayInputStream(_responseBody)};\r
265                                         }\r
266                                         _responseStream = (Stream) Activator.CreateInstance(t, param);\r
267                                 }\r
268                                 return _responseStream;\r
269                         }\r
270                         catch(Exception e)\r
271                         {\r
272                                 Console.WriteLine("Exception caught!");\r
273                                 Console.WriteLine(e.GetType() + ":" + e.Message + "\n" + e.StackTrace);\r
274                                 throw e;\r
275                         }\r
276                 }\r
277 \r
278                 public override void Close()\r
279                 {\r
280                         try\r
281                         {\r
282                                 if(_responseStream != null)\r
283                                         _responseStream.Close();\r
284                         }\r
285                         finally\r
286                         {\r
287                                 _responseStream = null;\r
288 \r
289                                 if (!_isHttpMethodClosed)\r
290                                 {\r
291                                         _httpMethod.releaseConnection();\r
292                                         if(_stateCache != null && _state != null)\r
293                                         {\r
294                                                 _stateCache.ReleaseHttpState(_state);\r
295                                                 _state = null;\r
296                                                 _stateCache = null;\r
297                                         }\r
298                                         _isHttpMethodClosed = true;\r
299                                 }\r
300                         }\r
301                 }\r
302 \r
303                 public string GetResponseHeader(string headerName)\r
304                 {\r
305                         return Headers[headerName];\r
306                 }\r
307 \r
308                 public override int GetHashCode()\r
309                 {\r
310                         return base.GetHashCode();\r
311                 }\r
312 \r
313 \r
314                 protected virtual void Dispose(bool disposing)\r
315                 {\r
316                         try\r
317                         {\r
318                                 if(_responseStream != null)\r
319                                         _responseStream.Close();\r
320                         }\r
321                         finally\r
322                         {\r
323                                 _responseStream = null;\r
324 \r
325                                 if (!_isHttpMethodClosed)\r
326                                 {\r
327                                         _httpMethod.releaseConnection();\r
328                                         _isHttpMethodClosed = true;\r
329                                 }\r
330                         }\r
331                 }\r
332 \r
333                 private void FillHeaders()\r
334                 {\r
335                         mainsoft.apache.commons.httpclient.Header[] respHeaders =\r
336                                 _httpMethod.getResponseHeaders();\r
337                         if(respHeaders == null)\r
338                                 return;\r
339                         for(int i = 0; i < respHeaders.Length; i++)\r
340                         {\r
341                                 \r
342                                 mainsoft.apache.commons.httpclient.HeaderElement[] elements = respHeaders[i].getElements();     \r
343                                 for(int j = 0; j < elements.Length; j++)\r
344                                 {\r
345                                         string key = elements[j].getName();\r
346                                         string val = elements[j].getValue();\r
347                                         string pair = (key == null) ? ((val == null) ? "" : val) : ((val==null) ? key : key + "=" + val);\r
348                                         _headers.Add(respHeaders[i].getName(), pair);                                                   \r
349                                 }\r
350 \r
351                         }\r
352                         ParseVersion();\r
353                 }\r
354 \r
355                 private void ParseVersion()\r
356                 {\r
357                         mainsoft.apache.commons.httpclient.StatusLine statusLine =\r
358                                 _httpMethod.getStatusLine();\r
359                         string ver = statusLine.getHttpVersion().Trim().ToUpper();\r
360                         if(ver == "HTTP/1.1")\r
361                                _version = HttpVersion.Version11;\r
362                         else if(ver == "HTTP/1.0")\r
363                                 _version = HttpVersion.Version10;\r
364                         else\r
365                                 _version = null;\r
366                 }\r
367         \r
368                 private void FillCookies()\r
369                 {\r
370                         if(_state == null)\r
371                                 return;\r
372 \r
373                         mainsoft.apache.commons.httpclient.Cookie[] javaCookies =\r
374                                 _state.getCookies();\r
375 \r
376                         if(javaCookies == null)\r
377                                 return;\r
378 \r
379                         for(int i = 0; i < javaCookies.Length; i++)\r
380                         {\r
381                                 bool httpsProtocol = _httpMethod.getURI().ToString().StartsWith("https");\r
382                                 if(!httpsProtocol && javaCookies[i].getSecure())\r
383                                         continue;\r
384                                 Cookie c = new Cookie(javaCookies[i].getName(), \r
385                                         javaCookies[i].getValue(), \r
386                                         (javaCookies[i].getPath() == null) ? "" : javaCookies[i].getPath(),\r
387                                         (javaCookies[i].getDomain() == null) ? "" : javaCookies[i].getDomain());\r
388                                 java.util.Calendar jCalendar = java.util.Calendar.getInstance();\r
389                                 java.util.Date jDate = javaCookies[i].getExpiryDate();\r
390                                 if(jDate != null)\r
391                                 {\r
392                                         jCalendar.setTime(javaCookies[i].getExpiryDate());\r
393                                         c.Expires = (DateTime) vmw.common.DateTimeUtils.CalendarToDateTime(jCalendar);\r
394                                 }\r
395                                 \r
396                                 _cookies.Add(c);\r
397                         }\r
398 \r
399                 }\r
400 \r
401                 //todo remove unused methods\r
402                 private void FillCookies_old ()\r
403                 {\r
404                         \r
405                         string val = Headers["Set-Cookie"];\r
406                         if (val != null && val.Trim () != "")\r
407                                 SetCookie (val);\r
408 \r
409                         val = Headers["Set-Cookie2"];\r
410                         if (val != null && val.Trim () != "")\r
411                                 SetCookie2 (val);\r
412                 }\r
413 \r
414                 static string [] SplitValue (string input)\r
415                 {\r
416                         string [] result = new string [2];\r
417                         int eq = input.IndexOf ('=');\r
418                         if (eq == -1) \r
419                         {\r
420                                 result [0] = "invalid";\r
421                         } \r
422                         else \r
423                         {\r
424                                 result [0] = input.Substring (0, eq).Trim ().ToUpper ();\r
425                                 result [1] = input.Substring (eq + 1);\r
426                         }\r
427                         \r
428                         return result;\r
429                 }\r
430 \r
431                 private void SetCookie(string val)\r
432                 {\r
433 //                      Console.WriteLine("in set cookie 1 - got value : " + val);\r
434                         string[] parts = null;\r
435                         Collections.Queue options = null;\r
436                         Cookie cookie = null;\r
437 \r
438                         options = new Collections.Queue (val.Split (';'));\r
439                         parts = SplitValue ((string) options.Dequeue()); // NAME=VALUE must be first\r
440 \r
441                         cookie = new Cookie (parts[0], parts[1]);\r
442 \r
443                         while (options.Count > 0) \r
444                         {\r
445                                 parts = SplitValue ((string) options.Dequeue());\r
446                                 switch (parts [0]) \r
447                                 {\r
448                                         case "COMMENT":\r
449                                                 if (cookie.Comment == null)\r
450                                                         cookie.Comment = parts[1];\r
451                                                 break;\r
452                                         case "COMMENTURL":\r
453                                                 if (cookie.CommentUri == null)\r
454                                                         cookie.CommentUri = new Uri(parts[1]);\r
455                                                 break;\r
456                                         case "DISCARD":\r
457                                                 cookie.Discard = true;\r
458                                                 break;\r
459                                         case "DOMAIN":\r
460                                                 if (cookie.Domain == "")\r
461                                                         cookie.Domain = parts[1];\r
462                                                 break;\r
463                                         case "MAX-AGE": // RFC Style Set-Cookie2\r
464                                                 if (cookie.Expires == DateTime.MinValue)\r
465                                                         cookie.Expires = cookie.TimeStamp.AddSeconds (Int32.Parse (parts[1]));\r
466                                                 break;\r
467                                         case "EXPIRES": // Netscape Style Set-Cookie\r
468                                                 if (cookie.Expires == DateTime.MinValue) \r
469                                                 {\r
470                                                         //FIXME: Does DateTime parse something like: "Sun, 17-Jan-2038 19:14:07 GMT"?\r
471                                                         //cookie.Expires = DateTime.ParseExact (parts[1]);\r
472                                                         cookie.Expires = DateTime.Now.AddDays (1);\r
473                                                 }\r
474                                                 break;\r
475                                         case "PATH":\r
476                                                 cookie.Path = parts[1];\r
477                                                 break;\r
478                                         case "PORT":\r
479                                                 if (cookie.Port == null)\r
480                                                         cookie.Port = parts[1];\r
481                                                 break;\r
482                                         case "SECURE":\r
483                                                 cookie.Secure = true;\r
484                                                 break;\r
485                                         case "VERSION":\r
486                                                 cookie.Version = Int32.Parse (parts[1]);\r
487                                                 break;\r
488                                 } // switch\r
489                         } // while\r
490 \r
491                         if (_cookies == null)\r
492                                 _cookies = new CookieCollection();\r
493 \r
494                         if (cookie.Domain == "")\r
495                                 cookie.Domain = _uri.Host;\r
496 \r
497 //                      Console.WriteLine("adding cookie " + cookie + " to collection");\r
498                         _cookies.Add (cookie);\r
499 //                      Console.WriteLine("exit from method...");\r
500                 }               \r
501                 \r
502                 private void SetCookie2 (string cookies_str)\r
503                 {\r
504                         string [] cookies = cookies_str.Split (',');\r
505                         foreach (string cookie_str in cookies)\r
506                                 SetCookie (cookie_str);\r
507                 }\r
508                 #endregion\r
509         }\r
510 }\r