* HttpWriter.cs: Use a constant for the buffer size so the cache
[mono.git] / mcs / class / System.Web / System.Web / HttpResponse.cs
1 // 
2 // System.Web.HttpResponse
3 //
4 // Authors:
5 //      Patrik Torstensson (Patrik.Torstensson@labs2.com)
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //
8 // (c) 2002 Ximian, Inc. (http://www.ximian.com)
9 //
10 using System;
11 using System.Collections;
12 using System.Globalization;
13 using System.IO;
14 using System.Text;
15 using System.Threading;
16 using System.Web.Util;
17 using System.Web.Caching;
18
19 namespace System.Web
20 {
21         public sealed class HttpResponse
22         {
23                 // Chunked encoding static helpers
24                 static byte [] s_arrChunkSuffix = { 10, 13 };
25                 static byte [] s_arrChunkEnd = { 10 , 13 };
26                 static string s_sChunkedPrefix = "\r\n";
27
28                 ArrayList _Headers;
29                         
30                 bool _bClientDisconnected;
31                 bool _bSuppressHeaders;
32                 bool _bSuppressContent;
33                 bool _bChunked;
34                 bool _bEnded;
35                 bool _bBuffering;
36                 bool _bHeadersSent;
37                 bool _bFlushing;
38                 bool filtered;
39                 long _lContentLength;
40                 int _iStatusCode;
41
42                 bool _ClientDisconnected;
43                 bool closed;
44
45                 string  _sContentType;
46                 string  _sCacheControl;
47                 string  _sTransferEncoding;
48                 string  _sCharset;
49                 string  _sStatusDescription;
50
51                 HttpCookieCollection _Cookies;
52                 HttpCachePolicy _CachePolicy;
53
54                 Encoding _ContentEncoding;
55                         
56                 HttpContext _Context;
57                 HttpWriter _Writer;
58                 TextWriter _TextWriter;
59
60                 HttpWorkerRequest _WorkerRequest;
61
62                 ArrayList fileDependencies;
63                 CachedRawResponse cached_response;
64                 ArrayList cached_headers;
65                 
66                 public HttpResponse (TextWriter output)
67                 {
68                          _bBuffering = true;
69                          _bFlushing = false;
70                          _bHeadersSent = false;
71
72                          _Headers = new ArrayList ();
73
74                          _sContentType = "text/html";
75
76                          _iStatusCode = 200;
77                          _sCharset = null;
78                          _sCacheControl = null;
79
80                          _lContentLength = 0;
81                          _bSuppressContent = false;
82                          _bSuppressHeaders = false;
83                          _bClientDisconnected = false;
84
85                          _bChunked = false;
86
87                          _TextWriter = output;
88                 }
89
90                 internal HttpResponse (HttpWorkerRequest WorkerRequest, HttpContext Context)
91                 {
92                          _Context = Context;
93                          _WorkerRequest = WorkerRequest;
94
95                          _bBuffering = true;
96                          _bFlushing = false;
97                          _bHeadersSent = false;
98
99                          _Headers = new ArrayList ();
100
101                          _sContentType = "text/html";
102
103                          _iStatusCode = 200;
104                          _sCharset = null;
105                          _sCacheControl = null;
106
107                          _lContentLength = 0;
108                          _bSuppressContent = false;
109                          _bSuppressHeaders = false;
110                          _bClientDisconnected = false;
111
112                          _bChunked = false;
113
114                          _Writer = new HttpWriter (this);
115                          _TextWriter = _Writer;
116                 }
117
118                 internal void FinalFlush ()
119                 {
120                         Flush (true);
121                 }
122
123                 internal void DoFilter (bool really)
124                 {
125                         if (really && null != _Writer) 
126                                 _Writer.FilterData (true);
127
128                         filtered = true;
129                 }
130
131                 internal bool IsCached {
132                         get { return cached_response != null; }
133                 }
134                 
135                 internal void CacheResponse (HttpRequest request) {
136                         cached_response = new CachedRawResponse (_CachePolicy, request);
137                 }
138
139                 internal CachedRawResponse GetCachedResponse () {
140                         cached_response.StatusCode = StatusCode;
141                         cached_response.StatusDescription = StatusDescription;
142                         return cached_response;
143                 }
144
145                 internal void SetCachedHeaders (ArrayList headers)
146                 {
147                         cached_headers = headers;
148                 }
149                 
150                 [MonoTODO("We need to add cache headers also")]
151                 private ArrayList GenerateHeaders ()
152                 {
153                         ArrayList oHeaders = new ArrayList (_Headers.ToArray ());
154
155                         oHeaders.Add (new HttpResponseHeader ("X-Powered-By", "Mono"));
156                         // save culture info, we need us info here
157                         CultureInfo oSavedInfo = Thread.CurrentThread.CurrentCulture;
158                         Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
159
160                         string date = DateTime.Now.ToUniversalTime ().ToString ("ddd, d MMM yyyy HH:mm:ss ");
161                         oHeaders.Add (new HttpResponseHeader ("Date", date + "GMT"));
162
163                         Thread.CurrentThread.CurrentCulture = oSavedInfo;
164
165                         if (_lContentLength > 0) {
166                                 oHeaders.Add (new HttpResponseHeader (HttpWorkerRequest.HeaderContentLength,
167                                                                       _lContentLength.ToString ()));
168                         }
169
170                         if (_sContentType != null) {
171                                 if (_sContentType.IndexOf ("charset=") == -1) {
172                                         if (Charset.Length == 0) {
173                                                 Charset = ContentEncoding.HeaderName;
174                                         }
175
176                                         // Time to build our string
177                                         if (Charset.Length > 0) {
178                                                 _sContentType += "; charset=" + Charset;
179                                         }
180                                 }
181
182                                 oHeaders.Add (new HttpResponseHeader (HttpWorkerRequest.HeaderContentType,
183                                                                       _sContentType));
184                         }
185
186                         if (_CachePolicy != null)
187                                 _CachePolicy.SetHeaders (this, oHeaders);
188                         
189                         if (_sCacheControl != null) {
190                                 oHeaders.Add (new HttpResponseHeader (HttpWorkerRequest.HeaderPragma,
191                                                                       _sCacheControl));
192                         }
193
194                         if (_sTransferEncoding != null) {
195                                 oHeaders.Add (new HttpResponseHeader (HttpWorkerRequest.HeaderTransferEncoding,
196                                                                       _sTransferEncoding));
197                         }
198
199                         if (_Cookies != null) {
200                                 int length = _Cookies.Count;
201                                 for (int i = 0; i < length; i++) {
202                                         oHeaders.Add (_Cookies.Get (i).GetCookieHeader ());
203                                 }
204                         }
205
206                         return oHeaders;
207                 }
208                 
209                 private void SendHeaders ()
210                 {
211                         _WorkerRequest.SendStatus (StatusCode, StatusDescription);
212                         
213                         ArrayList oHeaders;
214
215                         if (cached_headers != null)
216                                 oHeaders = cached_headers;
217                         else
218                                 oHeaders = GenerateHeaders ();
219
220                         if (cached_response != null)
221                                 cached_response.SetHeaders (oHeaders);
222                         
223                         foreach (HttpResponseHeader oHeader in oHeaders)
224                                 oHeader.SendContent (_WorkerRequest);
225                         
226                         _bHeadersSent = true;
227                 }
228
229                 public string Status
230                 {
231                         get {
232                                 return String.Format ("{0} {1}", StatusCode, StatusDescription);
233                         }
234
235                         set {
236                                 string sMsg = "OK";
237                                 int iCode = 200;
238
239                                 try {
240                                         iCode = Int32.Parse (value.Substring (0, value.IndexOf (' ')));
241                                         sMsg = value.Substring (value.IndexOf (' ') + 1);
242                                 } catch (Exception) {
243                                         throw new HttpException ("Invalid status string");
244                                 }
245
246                                 StatusCode = iCode;
247                                 StatusDescription = sMsg;
248                         }
249                 }
250
251                 [MonoTODO()]
252                 public void AddCacheItemDependencies (ArrayList cacheKeys)
253                 {
254                         throw new NotImplementedException ();
255                 }
256
257                 [MonoTODO()]
258                 public void AddCacheItemDependency(string cacheKey)
259                 {
260                         throw new NotImplementedException ();
261                 }
262
263                 public void AddFileDependencies (ArrayList filenames)
264                 {
265                         if (filenames == null || filenames.Count == 0)
266                                 return;
267                         
268                         if (fileDependencies == null) {
269                                 fileDependencies = (ArrayList) filenames.Clone ();
270                                 return;
271                         }
272
273                         foreach (string fn in filenames)
274                                 AddFileDependency (fn);
275                 }
276
277                 public void AddFileDependency (string filename)
278                 {
279                         if (fileDependencies == null)
280                                 fileDependencies = new ArrayList ();
281
282                         fileDependencies.Add (filename);
283                 }
284
285                 public void AddHeader (string name, string value)
286                 {
287                         AppendHeader(name, value);
288                 }
289
290                 public void AppendCookie (HttpCookie cookie)
291                 {
292                         if (_bHeadersSent)
293                                 throw new HttpException ("Cannot append cookies after HTTP headers have been sent");
294
295                         Cookies.Add (cookie);
296                 }
297
298                 [MonoTODO()]
299                 public void AppendToLog (string param)
300                 {
301                         throw new NotImplementedException ();
302                 }
303
304                 public string ApplyAppPathModifier (string virtualPath)
305                 {
306                         if (virtualPath == null)
307                                 return null;
308
309                         if (virtualPath == "")
310                                 return _Context.Request.RootVirtualDir;
311
312                         if (UrlUtils.IsRelativeUrl (virtualPath)) {
313                                 virtualPath = UrlUtils.Combine (_Context.Request.RootVirtualDir, virtualPath);
314                         } else if (UrlUtils.IsRooted (virtualPath)) {
315                                 virtualPath = UrlUtils.Reduce (virtualPath);
316                         }
317
318                         return virtualPath;
319                 }
320
321                 public bool Buffer
322                 {
323                         get {
324                                 return BufferOutput;
325                         }
326
327                         set {
328                                 BufferOutput = value;
329                         }
330                 }
331
332                 public bool BufferOutput
333                 {
334                         get {
335                                 return _bBuffering;
336                         }
337                         
338                         set {
339                                 if (_Writer != null)
340                                         _Writer.Update ();
341
342                                 _bBuffering = value;
343                         }
344                 }
345
346                 public HttpCachePolicy Cache
347                 {
348                         get {
349                                 if (null == _CachePolicy)
350                                         _CachePolicy = new HttpCachePolicy ();
351
352                                 return _CachePolicy;
353                         }
354                 }
355
356                 [MonoTODO("Set status in the cache policy")]
357                 public string CacheControl
358                 {
359                         get {
360                                 return _sCacheControl;
361                         }
362
363                         set {
364                                 if (_bHeadersSent)
365                                         throw new HttpException ("Headers has been sent to the client");
366
367                                 _sCacheControl = value;
368                         }
369                 }
370
371                 public string Charset
372                 {
373                         get {
374                                 if (null == _sCharset)
375                                         _sCharset = ContentEncoding.WebName;
376
377                                 return _sCharset;
378                         }
379
380                         set {
381                                 if (_bHeadersSent)
382                                         throw new HttpException ("Headers has been sent to the client");
383
384                                 _sCharset = value;
385                         }
386                 }
387
388                 public Encoding ContentEncoding
389                 {
390                         get {
391                                 if (_ContentEncoding == null)
392                                         _ContentEncoding = WebEncoding.ResponseEncoding;
393
394                                 return _ContentEncoding;
395                         }
396
397                         set {
398                                 if (value == null)
399                                         throw new ArgumentNullException ("Can't set a null as encoding");
400
401                                 _ContentEncoding = value;
402
403                                 if (_Writer != null)
404                                         _Writer.Update ();
405                         }
406                 }
407
408                 public string ContentType
409                 {
410                         get {
411                                 return _sContentType;
412                         }
413
414                         set {
415                                 if (_bHeadersSent)
416                                         throw new HttpException ("Headers has been sent to the client");
417
418                                 _sContentType = value;
419                         }
420                 }
421
422                 public HttpCookieCollection Cookies
423                 {
424                         get {
425                                 if (null == _Cookies)
426                                         _Cookies = new HttpCookieCollection (this, false);
427
428                                 return _Cookies;
429                         }
430                 }
431
432                 [MonoTODO("Set expires in the cache policy")]
433                 public int Expires
434                 {
435                         get {
436                                 throw new NotImplementedException ();
437                         }
438
439                         set {
440                                 throw new NotImplementedException ();
441                         }
442                 }
443
444                 [MonoTODO("Set expiresabsolute in the cache policy")]
445                 public DateTime ExpiresAbsolute
446                 {
447                         get {
448                                 throw new NotImplementedException ();
449                         }
450
451                         set {
452                                 throw new NotImplementedException ();
453                         }
454                 }
455
456                 public Stream Filter
457                 {
458                         get {
459                                 if (_Writer != null)
460                                         return _Writer.GetActiveFilter ();
461
462                                 return null;
463                         }
464
465                         set {
466                                 if (_Writer == null)
467                                         throw new HttpException ("Filtering is not allowed");
468
469                                 _Writer.ActivateFilter (value);
470                         }
471                 }
472
473                 public bool IsClientConnected
474                 {
475                         get {
476                                 if (_ClientDisconnected)
477                                         return false;
478
479                                 if (null != _WorkerRequest && (!_WorkerRequest.IsClientConnected ())) {
480                                         _ClientDisconnected = false;
481                                         return false;
482                                 }
483
484                                 return true;
485                         }
486                 }
487       
488                 public TextWriter Output
489                 {
490                         get {
491                                 return _TextWriter;
492                         }
493                 }
494
495                 public Stream OutputStream
496                 {
497                         get {
498                                 if (_Writer == null)
499                                         throw new HttpException ("an Output stream not available when " +
500                                                                  "running with custom text writer");
501
502                                 return _Writer.OutputStream;
503                         }
504                 }
505
506                 public string StatusDescription
507                 {
508                         get {
509                                 if (null == _sStatusDescription)
510                                         _sStatusDescription =
511                                                 HttpWorkerRequest.GetStatusDescription (_iStatusCode);
512
513                                 return _sStatusDescription;
514                         }
515
516                         set {
517                                 if (_bHeadersSent)
518                                         throw new HttpException ("Headers has been sent to the client");
519
520                                 _sStatusDescription = value;
521                         }
522                 }
523         
524                 public int StatusCode
525                 {
526                         get {
527                                 return _iStatusCode;
528                         }
529
530                         set {
531                                 if (_bHeadersSent)
532                                         throw new HttpException ("Headers has been sent to the client");
533
534                                 _sStatusDescription = null;
535                                 _iStatusCode = value;
536                         }
537                 }
538
539                 public bool SuppressContent
540                 {
541                         get {
542                                 return _bSuppressContent;
543                         }
544                         
545                         set {
546                                 if (_bHeadersSent)
547                                         throw new HttpException ("Headers has been sent to the client");
548
549                                 _bSuppressContent = true;
550                         }
551                 }
552
553                 HttpRequest Request
554                 {
555                         get {
556                                 if (_Context == null)
557                                         return null;
558
559                                 return _Context.Request;
560                         }
561                 }
562
563                 internal void AppendHeader (int iIndex, string value)
564                 {
565                         if (_bHeadersSent)
566                                 throw new HttpException ("Headers has been sent to the client");
567
568                         switch (iIndex) {
569                         case HttpWorkerRequest.HeaderContentLength:
570                                 _lContentLength = Int64.Parse (value);
571                                 break;
572                         case HttpWorkerRequest.HeaderContentEncoding:
573                                 _sContentType = value;
574                                 break;
575                         case HttpWorkerRequest.HeaderTransferEncoding:
576                                 _sTransferEncoding = value;
577                                 if (value.Equals ("chunked")) {
578                                         _bChunked = true;
579                                 } else {
580                                         _bChunked = false;
581                                 }
582                                 break;
583                         case HttpWorkerRequest.HeaderPragma:
584                                 _sCacheControl = value;
585                                 break;
586                         default:
587                                 _Headers.Add (new HttpResponseHeader (iIndex, value));
588                                 break;
589                         }
590                 }
591
592                 public void AppendHeader (string name, string value)
593                 {
594                         if (_bHeadersSent)
595                                 throw new HttpException ("Headers has been sent to the client");
596
597                         switch (name.ToLower ()) {
598                         case "content-length":
599                                 _lContentLength = Int64.Parse (value);
600                                 break;
601                         case "content-type":
602                                 _sContentType = value;
603                                 break;
604                         case "transfer-encoding":
605                                 _sTransferEncoding = value;
606                                 if (value.Equals ("chunked")) {
607                                         _bChunked = true;
608                                 } else {
609                                         _bChunked = false;
610                                 }
611                                 break;
612                         case "pragma":
613                                 _sCacheControl = value;
614                                 break;
615                         default:
616                                 _Headers.Add (new HttpResponseHeader (name, value));
617                                 break;
618                         }
619                 }
620         
621                 internal TextWriter SetTextWriter (TextWriter w)
622                 {
623                         TextWriter prev = _TextWriter;
624                         _TextWriter = w;
625                         return prev;
626                 }
627                 
628                 public void BinaryWrite (byte [] buffer)
629                 {
630                         OutputStream.Write (buffer, 0, buffer.Length);
631                 }
632
633                 public void Clear ()
634                 {
635                         if (_Writer != null)
636                                 _Writer.Clear ();
637                 }
638
639                 public void ClearContent ()
640                 {
641                         Clear();
642                 }
643
644                 public void ClearHeaders ()
645                 {
646                         if (_bHeadersSent)
647                                 throw new HttpException ("Headers has been sent to the client");
648
649                         _sContentType = "text/html";
650
651                         _iStatusCode = 200;
652                         _sCharset = null;
653                         _Headers = new ArrayList ();
654                         _sCacheControl = null;
655                         _sTransferEncoding = null;
656
657                         _lContentLength = 0;
658                         _bSuppressContent = false;
659                         _bSuppressHeaders = false;
660                         _bClientDisconnected = false;
661                 }
662
663                 public void Close ()
664                 {
665                         if (closed && !_bClientDisconnected) {
666                                 _bClientDisconnected = false;
667                                 _WorkerRequest.CloseConnection ();
668                                 _bClientDisconnected = true;
669                         }
670                 }
671
672                 internal void Dispose ()
673                 {
674                         if (_Writer != null) {
675                                 _Writer.Dispose ();
676                                 _Writer = null;
677                         }
678                 }
679
680                 [MonoTODO("Handle callbacks into before done with session, needs to have a non ended flush here")]
681                 internal void FlushAtEndOfRequest () 
682                 {
683                         Flush (true);
684                 }
685
686                 public void End ()
687                 {
688                         if (_bEnded)
689                                 return;
690
691                         Flush ();
692                         _bEnded = true;
693                         _Context.ApplicationInstance.CompleteRequest ();
694                 }
695
696                 public void Flush ()
697                 {
698                         if (closed)
699                                 throw new HttpException ("Response already finished.");
700
701                         Flush (false);
702                 }
703
704                 private void Flush (bool bFinish)
705                 {
706                         if (_bFlushing || closed)
707                                 return;
708
709                         _bFlushing = true;
710
711                         if (_Writer == null) {
712                                 _TextWriter.Flush ();
713                                 _bFlushing = false;
714                                 return;
715                         }
716
717                         try {
718                                 if (_bClientDisconnected)
719                                         return;
720
721                                 long length = _Writer.BufferSize;
722                                 if (!_bHeadersSent && !_bSuppressHeaders) {
723                                         if (bFinish) {
724                                                 if (length == 0 && _lContentLength == 0)
725                                                         _sContentType = null;
726
727                                                 SendHeaders ();
728                                                 length = _Writer.BufferSize;
729                                                 if (length != 0)
730                                                         _WorkerRequest.SendCalculatedContentLength ((int) length);
731                                         } else {
732                                                 if (_lContentLength == 0 && _iStatusCode == 200 &&
733                                                    _sTransferEncoding == null) {
734                                                         // Check we are going todo chunked encoding
735                                                         string sProto = Request.ServerVariables ["SERVER_PROTOCOL"];
736                                                         sProto = "HTTP/1.0"; // Remove this line when we support properly
737                                                                              // chunked content
738
739                                                         if (sProto != null && sProto == "HTTP/1.1") {
740                                                                 AppendHeader (
741                                                                         HttpWorkerRequest.HeaderTransferEncoding,
742                                                                         "chunked");
743                                                         }  else {
744                                                                 // Just in case, the old browsers send a HTTP/1.0
745                                                                 // request with Connection: Keep-Alive
746                                                                 AppendHeader (
747                                                                         HttpWorkerRequest.HeaderConnection,
748                                                                         "Close");
749                                                         }
750                                                 }
751
752                                                 length = _Writer.BufferSize;
753                                                 SendHeaders ();
754                                         }
755                                 }
756
757                                 if (!filtered) {
758                                         _Writer.FilterData (false);
759                                         length = _Writer.BufferSize;
760                                 }
761
762                                 if (length == 0) {
763                                         _WorkerRequest.FlushResponse (bFinish);
764                                         if (!bFinish)
765                                                 _Writer.Clear ();
766                                         return;
767                                 }
768
769                                 if (!_bSuppressContent && Request.HttpMethod == "HEAD")
770                                         _bSuppressContent = true;
771
772                                 if (!_bSuppressContent) {
773                                         _bClientDisconnected = false;
774                                         if (_bChunked) {
775                                                 Encoding oASCII = Encoding.ASCII;
776
777                                                 string chunk = Convert.ToString(_Writer.BufferSize, 16);
778                                                 byte [] arrPrefix = oASCII.GetBytes (chunk + s_sChunkedPrefix);
779
780                                                 _WorkerRequest.SendResponseFromMemory (arrPrefix,
781                                                                                        arrPrefix.Length);
782
783                                                 _Writer.SendContent (_WorkerRequest);
784
785                                                 _WorkerRequest.SendResponseFromMemory (s_arrChunkSuffix,
786                                                                                        s_arrChunkSuffix.Length);
787                                                 if (bFinish)
788                                                         _WorkerRequest.SendResponseFromMemory (
789                                                                         s_arrChunkEnd, s_arrChunkEnd.Length);
790                                         } else {
791                                                 _Writer.SendContent (_WorkerRequest);
792                                         }
793                                 }
794
795                                 _WorkerRequest.FlushResponse (bFinish);
796                                 if (IsCached)
797                                         cached_response.SetData (_Writer.GetBuffer ());
798                                 _Writer.Clear ();
799                         } finally {
800                                 if (bFinish)
801                                         closed = true;
802                                 _bFlushing = false;
803                         }
804                 }
805
806                 public void Pics (string value)
807                 {
808                         AppendHeader ("PICS-Label", value);
809                 }
810
811
812                 public void Redirect (string url)
813                 {
814                         Redirect (url, true);
815                 }
816
817                 public void Redirect (string url, bool endResponse)
818                 {
819                         if (_bHeadersSent)
820                                 throw new HttpException ("Headers has been sent to the client");
821
822                         Clear ();
823
824                         url = ApplyAppPathModifier (url);
825                         StatusCode = 302;
826                         AppendHeader (HttpWorkerRequest.HeaderLocation, url);
827
828                         // Text for browsers that can't handle location header
829                         Write ("<html><head><title>Object moved</title></head><body>\r\n");
830                         Write ("<h2>Object moved to <a href='" + url + "'>here</a></h2>\r\n");
831                         Write ("</body><html>\r\n");
832
833                         if (endResponse)
834                                 End ();
835                 }
836
837                 public void Write (char ch)
838                 {
839                         _TextWriter.Write(ch);
840                 }
841
842                 public void Write (object obj)
843                 {
844                         _TextWriter.Write(obj);
845                 }
846
847                 public void Write (string str)
848                 {
849                         _TextWriter.Write (str);
850                 }
851
852                 public void Write (char [] buffer, int index, int count)
853                 {
854                         _TextWriter.Write (buffer, index, count);
855                 }
856
857                 [MonoTODO()]
858                 public static void RemoveOutputCacheItem (string path)
859                 {
860                         throw new NotImplementedException ();
861                 }
862
863                 public void SetCookie (HttpCookie cookie)
864                 {
865                         if (_bHeadersSent)
866                                 throw new HttpException ("Cannot append cookies after HTTP headers have been sent");
867
868                         Cookies.Add (cookie);
869                 }
870
871                 private void WriteFromStream (Stream stream, long offset, long length, long bufsize)
872                 {
873                         if (offset < 0 || length <= 0)
874                                 return;
875                         
876                         long stLength = stream.Length;
877                         if (offset + length > stLength)
878                                 length = stLength - offset;
879
880                         if (offset > 0)
881                                 stream.Seek (offset, SeekOrigin.Begin);
882
883                         byte [] fileContent = new byte [bufsize];
884                         int count = (int) Math.Min (Int32.MaxValue, bufsize);
885                         while (length > 0 && (count = stream.Read (fileContent, 0, count)) != 0) {
886                                 _Writer.WriteBytes (fileContent, 0, count);
887                                 length -= count;
888                                 count = (int) Math.Min (length, fileContent.Length);
889                         }
890                 }
891
892                 public void WriteFile (string filename)
893                 {
894                         WriteFile (filename, false);
895                 }
896
897                 public void WriteFile (string filename, bool readIntoMemory)
898                 {
899                         FileStream fs = null;
900                         try {
901                                 fs = File.OpenRead (filename);
902                                 long size = fs.Length;
903                                 if (readIntoMemory) {
904                                         WriteFromStream (fs, 0, size, size);
905                                 } else {
906                                         WriteFromStream (fs, 0, size, 8192);
907                                 }
908                         } finally {
909                                 if (fs != null)
910                                         fs.Close ();
911                         }
912                 }
913
914                 public void WriteFile (string filename, long offset, long size)
915                 {
916                         FileStream fs = null;
917                         try {
918                                 fs = File.OpenRead (filename);
919                                 WriteFromStream (fs, offset, size, 8192);
920                         } finally {
921                                 if (fs != null)
922                                         fs.Close ();
923                         }
924                 }
925
926                 public void WriteFile (IntPtr fileHandle, long offset, long size)
927                 {
928                         FileStream fs = null;
929                         try {
930                                 fs = new FileStream (fileHandle, FileAccess.Read);
931                                 WriteFromStream (fs, offset, size, 8192);
932                         } finally {
933                                 if (fs != null)
934                                         fs.Close ();
935                         }
936                 }   
937
938                 [MonoTODO()]
939                 internal void OnCookieAdd (HttpCookie cookie)
940                 {
941                 }
942
943                 [MonoTODO("Do we need this?")]
944                 internal void OnCookieChange (HttpCookie cookie)
945                 {
946                 }
947
948                 [MonoTODO()]
949                 internal void GoingToChangeCookieColl ()
950                 {
951                 }
952
953                 [MonoTODO()]
954                 internal void ChangedCookieColl ()
955                 {
956                 }
957         }
958 }