2003-10-06 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System.Web / System.Web / HttpResponse.cs
index 9b34316badd9303b262e6829a662ff2a3aa692d9..dcce865f49b14ff75f2dfdccc00f7615e356ac9f 100644 (file)
@@ -13,6 +13,7 @@ using System.Globalization;
 using System.IO;
 using System.Text;
 using System.Threading;
+using System.Web.Util;
 
 namespace System.Web
 {
@@ -33,6 +34,7 @@ namespace System.Web
                bool _bBuffering;
                bool _bHeadersSent;
                bool _bFlushing;
+               bool filtered;
                long _lContentLength;
                int _iStatusCode;
 
@@ -55,6 +57,8 @@ namespace System.Web
 
                HttpWorkerRequest _WorkerRequest;
 
+               ArrayList fileDependencies;
+
                public HttpResponse (TextWriter output)
                {
                         _bBuffering = true;
@@ -119,10 +123,12 @@ namespace System.Web
                        Flush (true);
                }
 
-               internal void DoFilter ()
+               internal void DoFilter (bool really)
                {
-                       if (null != _Writer) 
+                       if (really && null != _Writer) 
                                _Writer.FilterData (true);
+
+                       filtered = true;
                }
 
                [MonoTODO("We need to add cache headers also")]
@@ -130,11 +136,12 @@ namespace System.Web
                {
                        ArrayList oHeaders = new ArrayList (_Headers.ToArray ());
 
+                       oHeaders.Add (new HttpResponseHeader ("X-Powered-By", "Mono"));
                        // save culture info, we need us info here
                        CultureInfo oSavedInfo = Thread.CurrentThread.CurrentCulture;
                        Thread.CurrentThread.CurrentCulture = new CultureInfo (0x0409);
 
-                       string date = DateTime.Now.ToUniversalTime ().ToString ("ddd, d MMM yyyy HH:mm:ss");
+                       string date = DateTime.Now.ToUniversalTime ().ToString ("ddd, d MMM yyyy HH:mm:ss ");
                        oHeaders.Add (new HttpResponseHeader ("Date", date + "GMT"));
 
                        Thread.CurrentThread.CurrentCulture = oSavedInfo;
@@ -170,7 +177,12 @@ namespace System.Web
                                                                      _sTransferEncoding));
                        }
 
-                       // TODO: Add Cookie headers..
+                       if (_Cookies != null) {
+                               int length = _Cookies.Count;
+                               for (int i = 0; i < length; i++) {
+                                       oHeaders.Add (_Cookies.Get (i).GetCookieHeader ());
+                               }
+                       }
 
                        return oHeaders;
                }
@@ -220,16 +232,26 @@ namespace System.Web
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO()]
                public void AddFileDependencies (ArrayList filenames)
                {
-                       //throw new NotImplementedException();
+                       if (filenames == null || filenames.Count == 0)
+                               return;
+                       
+                       if (fileDependencies == null) {
+                               fileDependencies = (ArrayList) filenames.Clone ();
+                               return;
+                       }
+
+                       foreach (string fn in filenames)
+                               AddFileDependency (fn);
                }
 
-               [MonoTODO()]
                public void AddFileDependency (string filename)
                {
-                       //throw new NotImplementedException();
+                       if (fileDependencies == null)
+                               fileDependencies = new ArrayList ();
+
+                       fileDependencies.Add (filename);
                }
 
                public void AddHeader (string name, string value)
@@ -237,10 +259,12 @@ namespace System.Web
                        AppendHeader(name, value);
                }
 
-               [MonoTODO()]
                public void AppendCookie (HttpCookie cookie)
                {
-                       throw new NotImplementedException ();
+                       if (_bHeadersSent)
+                               throw new HttpException ("Cannot append cookies after HTTP headers have been sent");
+
+                       Cookies.Add (cookie);
                }
 
                [MonoTODO()]
@@ -249,10 +273,21 @@ namespace System.Web
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO()]
                public string ApplyAppPathModifier (string virtualPath)
                {
-                       throw new NotImplementedException ();
+                       if (virtualPath == null)
+                               return null;
+
+                       if (virtualPath == "")
+                               return _Context.Request.RootVirtualDir;
+
+                       if (UrlUtils.IsRelativeUrl (virtualPath)) {
+                               virtualPath = UrlUtils.Combine (_Context.Request.RootVirtualDir, virtualPath);
+                       } else if (UrlUtils.IsRooted (virtualPath)) {
+                               virtualPath = UrlUtils.Reduce (virtualPath);
+                       }
+
+                       return virtualPath;
                }
 
                public bool Buffer
@@ -326,7 +361,7 @@ namespace System.Web
                {
                        get {
                                if (_ContentEncoding == null)
-                                       _ContentEncoding = Encoding.UTF8;
+                                       _ContentEncoding = WebEncoding.Encoding;
 
                                return _ContentEncoding;
                        }
@@ -487,9 +522,12 @@ namespace System.Web
                        }
                }
 
-               public HttpRequest Request
+               HttpRequest Request
                {
                        get {
+                               if (_Context == null)
+                                       return null;
+
                                return _Context.Request;
                        }
                }
@@ -608,14 +646,14 @@ namespace System.Web
                        Flush (true);
                }
 
-               [MonoTODO("Check timeout and if we can cancel the thread...")]
                public void End ()
                {
-                       if (!_bEnded) {
-                               Flush ();
-                               _WorkerRequest.CloseConnection ();
-                               _bEnded = true;
-                       }
+                       if (_bEnded)
+                               return;
+
+                       Flush ();
+                       _bEnded = true;
+                       _Context.ApplicationInstance.CompleteRequest ();
                }
 
                public void Flush ()
@@ -630,44 +668,67 @@ namespace System.Web
 
                        _bFlushing = true;
 
-                       if (_Writer != null) {
-                               _Writer.FlushBuffers ();
-                       } else {
+                       if (_Writer == null) {
                                _TextWriter.Flush ();
+                               _bFlushing = false;
+                               return;
                        }
 
                        try {
-                               if (!_bHeadersSent && !_bSuppressHeaders && !_bClientDisconnected) {
-                                       if (_Writer != null && BufferOutput) {
-                                               _lContentLength = _Writer.BufferSize;
-                                       } else {
-                                               _lContentLength = 0;
-                                       }
+                               if (_bClientDisconnected)
+                                       return;
 
-                                       if (_lContentLength == 0 && _iStatusCode == 200 &&
-                                               _sTransferEncoding == null) {
-                                               // Check we are going todo chunked encoding
-                                               string sProto = Request.ServerVariables ["SERVER_PROTOCOL"];
-
-                                               if (sProto != null && sProto == "HTTP/1.1") {
-                                                       AppendHeader (
-                                                               HttpWorkerRequest.HeaderTransferEncoding,
-                                                               "chunked");
-                                               }  else {
-                                                       // Just in case, the old browsers sends a HTTP/1.0
-                                                       // request with Connection: Keep-Alive
-                                                       AppendHeader (
-                                                               HttpWorkerRequest.HeaderConnection,
-                                                               "Close");
+                               long length = _Writer.BufferSize;
+                               if (!_bHeadersSent && !_bSuppressHeaders) {
+                                       if (bFinish) {
+                                               if (length == 0 && _lContentLength == 0)
+                                                       _sContentType = null;
+
+                                               SendHeaders ();
+                                               length = _Writer.BufferSize;
+                                               if (length != 0)
+                                                       _WorkerRequest.SendCalculatedContentLength ((int) length);
+                                       } else {
+                                               if (_lContentLength == 0 && _iStatusCode == 200 &&
+                                                  _sTransferEncoding == null) {
+                                                       // Check we are going todo chunked encoding
+                                                       string sProto = Request.ServerVariables ["SERVER_PROTOCOL"];
+                                                       sProto = "HTTP/1.0"; // Remove this line when we support properly
+                                                                            // chunked content
+
+                                                       if (sProto != null && sProto == "HTTP/1.1") {
+                                                               AppendHeader (
+                                                                       HttpWorkerRequest.HeaderTransferEncoding,
+                                                                       "chunked");
+                                                       }  else {
+                                                               // Just in case, the old browsers send a HTTP/1.0
+                                                               // request with Connection: Keep-Alive
+                                                               AppendHeader (
+                                                                       HttpWorkerRequest.HeaderConnection,
+                                                                       "Close");
+                                                       }
                                                }
 
+                                               length = _Writer.BufferSize;
                                                SendHeaders ();
-                                       }                                       
+                                       }
                                }
-                               if ((!_bSuppressContent && Request.HttpMethod == "HEAD") || _Writer == null) {
-                                       _bSuppressContent = true;
+
+                               if (!filtered) {
+                                       _Writer.FilterData (false);
+                                       length = _Writer.BufferSize;
                                }
 
+                               if (length == 0) {
+                                       _WorkerRequest.FlushResponse (bFinish);
+                                       if (!bFinish)
+                                               _Writer.Clear ();
+                                       return;
+                               }
+
+                               if (!_bSuppressContent && Request.HttpMethod == "HEAD")
+                                       _bSuppressContent = true;
+
                                if (!_bSuppressContent) {
                                        _bClientDisconnected = false;
                                        if (_bChunked) {
@@ -689,12 +750,14 @@ namespace System.Web
                                        } else {
                                                _Writer.SendContent (_WorkerRequest);
                                        }
+                               } else {
+                                       _Writer.Clear ();
+                               }
 
-                                       _WorkerRequest.FlushResponse (bFinish);
+                               _WorkerRequest.FlushResponse (bFinish);
 
-                                       if (!bFinish)
-                                               _Writer.Clear ();
-                               }
+                               if (!bFinish)
+                                       _Writer.Clear ();
                        } finally {
                                _bFlushing = false;
                        }
@@ -711,15 +774,6 @@ namespace System.Web
                        Redirect (url, true);
                }
 
-               //FIXME: [1] this is an ugly hack to make it work until we have SimpleWorkerRequest!
-               private string redirectLocation;
-               public string RedirectLocation
-               {
-                     get {
-                             return redirectLocation;
-                     }
-               }
-
                public void Redirect (string url, bool endResponse)
                {
                        if (_bHeadersSent)
@@ -727,20 +781,17 @@ namespace System.Web
 
                        Clear ();
 
+                       url = ApplyAppPathModifier (url);
                        StatusCode = 302;
-                       redirectLocation = url;
-                       //[1]AppendHeader(HttpWorkerRequest.HeaderLocation, url);
+                       AppendHeader (HttpWorkerRequest.HeaderLocation, url);
 
                        // Text for browsers that can't handle location header
                        Write ("<html><head><title>Object moved</title></head><body>\r\n");
                        Write ("<h2>Object moved to <a href='" + url + "'>here</a></h2>\r\n");
                        Write ("</body><html>\r\n");
 
-                       /* [1]
-                       if (endResponse) {
-                       End();
-                       }
-                       */
+                       if (endResponse)
+                               End ();
                }
 
                public void Write (char ch)
@@ -769,10 +820,12 @@ namespace System.Web
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO()]
                public void SetCookie (HttpCookie cookie)
                {
-                       throw new NotImplementedException ();
+                       if (_bHeadersSent)
+                               throw new HttpException ("Cannot append cookies after HTTP headers have been sent");
+
+                       Cookies.Add (cookie);
                }
 
                private void WriteFromStream (Stream stream, long offset, long length, long bufsize)