Merge pull request #2530 from lambdageek/monoerror-mono_string_new
[mono.git] / mcs / class / System.Web / System.Web / HttpCachePolicy.cs
index a77113dca9ef7e465acbe0b1ecf5141cb18a6725..4f9ddcda64181589b222cc9bad99f45628431763 100644 (file)
 //
 
 using System.Collections;
+using System.Collections.Specialized;
+using System.ComponentModel;
 using System.Globalization;
+using System.IO;
 using System.Security.Permissions;
 using System.Text;
 using System.Web.UI;
 using System.Web.Util;
 
-namespace System.Web {
-
-       class CacheabilityUpdatedEventArgs : EventArgs {
-
-               public readonly HttpCacheability Cacheability;
-
-               public CacheabilityUpdatedEventArgs (HttpCacheability cacheability)
-               {
-                       Cacheability = cacheability;
-               }
-       }
-       
-       internal delegate void CacheabilityUpdatedCallback (object sender, CacheabilityUpdatedEventArgs args);
-       
+namespace System.Web
+{
        // CAS - no InheritanceDemand here as the class is sealed
        [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
-       public sealed class HttpCachePolicy {
-
+       public sealed class HttpCachePolicy
+       {
                internal HttpCachePolicy ()
                {
                }
 
-#region Fields
-
+               HttpCacheVaryByContentEncodings vary_by_content_encodings = new HttpCacheVaryByContentEncodings ();
                HttpCacheVaryByHeaders vary_by_headers = new HttpCacheVaryByHeaders ();
                HttpCacheVaryByParams vary_by_params = new HttpCacheVaryByParams ();
                ArrayList validation_callbacks;
@@ -65,6 +55,7 @@ namespace System.Web {
                internal HttpCacheability Cacheability;
                string etag;
                bool etag_from_file_dependencies;
+               bool last_modified_from_file_dependencies;
 
                //
                // Used externally
@@ -73,7 +64,7 @@ namespace System.Web {
                internal DateTime expire_date;
                internal bool have_last_modified;
                internal DateTime last_modified;
-               
+
                //bool LastModifiedFromFileDependencies;
                HttpCacheRevalidation revalidation;
                string vary_by_custom;
@@ -85,13 +76,16 @@ namespace System.Web {
                bool sliding_expiration;
                int duration;
                bool allow_response_in_browser_history;
-                
-#endregion
+               bool allow_server_caching = true;
+               bool set_no_store;
+               bool set_no_transform;
+               bool valid_until_expires;
+               bool omit_vary_star;
+               
+               public HttpCacheVaryByContentEncodings VaryByContentEncodings {
+                       get { return vary_by_content_encodings; }
+               }
 
-                internal event CacheabilityUpdatedCallback CacheabilityUpdated;
-                
-#region Properties
-                
                public HttpCacheVaryByHeaders VaryByHeaders {
                        get { return vary_by_headers; }
                }
@@ -100,6 +94,10 @@ namespace System.Web {
                        get { return vary_by_params; }
                }
 
+               internal bool AllowServerCaching {
+                       get { return allow_server_caching; }
+               }
+
                internal int Duration {
                        get { return duration; }
                        set { duration = value; }
@@ -108,23 +106,31 @@ namespace System.Web {
                internal bool Sliding {
                        get { return sliding_expiration; }
                }
-               
-                internal DateTime Expires {
-                        get { return expire_date; }
-                }
 
-#endregion // Properties
+               internal DateTime Expires {
+                       get { return expire_date; }
+               }
+
+               internal ArrayList ValidationCallbacks {
+                       get { return validation_callbacks; }
+               }
+
+               internal bool OmitVaryStar {
+                       get { return omit_vary_star; }
+               }
 
-#region Methods
+               internal bool ValidUntilExpires {
+                       get { return valid_until_expires; }
+               }
 
                internal int ExpireMinutes ()
                {
                        if (!have_expire_date)
                                return 0;
-                       
+
                        return (expire_date - DateTime.Now).Minutes;
                }
-               
+
                public void AddValidationCallback (HttpCacheValidateHandler handler, object data)
                {
                        if (handler == null)
@@ -157,11 +163,8 @@ namespace System.Web {
 
                        if (Cacheability > 0 && cacheability > Cacheability)
                                return;
-                       
-                       Cacheability = cacheability;
 
-                       if (CacheabilityUpdated != null)
-                               CacheabilityUpdated (this, new CacheabilityUpdatedEventArgs (cacheability));
+                       Cacheability = cacheability;
                }
 
                public void SetCacheability (HttpCacheability cacheability, string field)
@@ -221,17 +224,16 @@ namespace System.Web {
                        last_modified = date;
                }
 
-               [MonoTODO]
                public void SetLastModifiedFromFileDependencies ()
                {
-                       throw new NotImplementedException (); 
+                       last_modified_from_file_dependencies = true;
                }
 
                public void SetMaxAge (TimeSpan date)
                {
                        if (date < TimeSpan.Zero)
                                throw new ArgumentOutOfRangeException ("date");
-                       
+
                        if (HaveMaxAge && MaxAge < date)
                                return;
 
@@ -239,22 +241,19 @@ namespace System.Web {
                        HaveMaxAge = true;
                }
 
-               [MonoTODO]
                public void SetNoServerCaching ()
                {
-                       throw new NotImplementedException (); 
+                       allow_server_caching = false;
                }
 
-               [MonoTODO]
                public void SetNoStore ()
                {
-                       throw new NotImplementedException (); 
+                       set_no_store = true;
                }
 
-               [MonoTODO]
                public void SetNoTransforms ()
                {
-                       throw new NotImplementedException (); 
+                       set_no_transform = true;
                }
 
                public void SetProxyMaxAge (TimeSpan delta)
@@ -266,6 +265,7 @@ namespace System.Web {
                                return;
 
                        ProxyMaxAge = delta;
+                       HaveProxyMaxAge = true;
                }
 
                public void SetRevalidation (HttpCacheRevalidation revalidation)
@@ -283,10 +283,9 @@ namespace System.Web {
                        sliding_expiration = slide;
                }
 
-               [MonoTODO]
                public void SetValidUntilExpires (bool validUntilExpires)
                {
-                       throw new NotImplementedException (); 
+                       valid_until_expires = validUntilExpires;
                }
 
                public void SetVaryByCustom (string custom)
@@ -311,59 +310,115 @@ namespace System.Web {
                                allow_response_in_browser_history = allow;
                }
 
-               internal void SetHeaders (HttpResponse response, ArrayList headers)
+               internal void SetHeaders (HttpResponse response, NameValueCollection headers)
                {
-                       string cc, expires;
-                       if (Cacheability > HttpCacheability.NoCache) {
-                               string c = Cacheability.ToString ().ToLower (CultureInfo.InvariantCulture);
-                               
-                               if (MaxAge.TotalSeconds != 0)
-                                       cc = String.Format ("{0}, max-age={1}", c, (long) MaxAge.TotalSeconds);
-                               else
-                                       cc = c;
-                               
-                               expires = TimeUtil.ToUtcTimeString (expire_date);
-                               headers.Add (new UnknownResponseHeader ("Expires", expires));
-                       } else {
+                       bool noCache = false;
+                       string cc = null;
+
+                       switch (Cacheability) {
+                       case HttpCacheability.Public:
+                               cc = "public";
+                               break;
+
+                       case HttpCacheability.NoCache:
+                       case HttpCacheability.ServerAndNoCache:
+                               noCache = true;
                                cc = "no-cache";
+                               break;
+
+                       case HttpCacheability.Private:
+                       case HttpCacheability.ServerAndPrivate:
+                       default:
+                               cc = "private";
+                               break;
+                       }
+
+                       if (noCache) {
                                response.CacheControl = cc;
                                if (!allow_response_in_browser_history) {
-                                       expires = "-1";
-                                       headers.Add (new UnknownResponseHeader ("Expires", expires));
+                                       headers.Add ("Expires", "-1");
+                                       headers.Add ("Pragma", "no-cache");
                                }
+                       } else {
+                               if (HaveMaxAge)
+                                       cc = String.Concat (cc, ", max-age=", ((long) MaxAge.TotalSeconds).ToString ());
+
+                               if (have_expire_date) {
+                                       string expires = TimeUtil.ToUtcTimeString (expire_date);
+                                       headers.Add ("Expires", expires);
+                               }
+                       }
+
+                       if (set_no_store)
+                               cc = String.Concat (cc, ", no-store");
+                       if (set_no_transform)
+                               cc = String.Concat (cc, ", no-transform");
+                       if (cache_extension != null && cache_extension.Length > 0) {
+                               if (!String.IsNullOrEmpty (cc))
+                                       cc = String.Concat (cc, ", ");
+                               cc = String.Concat (cc, cache_extension.ToString ());
                        }
                        
-                       headers.Add (new UnknownResponseHeader ("Cache-Control", cc));
-                                               
+                       headers.Add ("Cache-Control", cc);
+
+                       if (last_modified_from_file_dependencies || etag_from_file_dependencies)
+                               HeadersFromFileDependencies (response);
+
                        if (etag != null)
-                               headers.Add (new UnknownResponseHeader ("ETag", etag));
+                               headers.Add ("ETag", etag);
 
                        if (have_last_modified)
-                               headers.Add (new UnknownResponseHeader ("Last-Modified",
-                                                            TimeUtil.ToUtcTimeString (last_modified)));
+                               headers.Add ("Last-Modified", TimeUtil.ToUtcTimeString (last_modified));
 
                        if (!vary_by_params.IgnoreParams) {
-                               BaseResponseHeader vb = vary_by_params.GetResponseHeader ();
+                               string vb = vary_by_params.GetResponseHeaderValue ();
                                if (vb != null)
-                                       headers.Add (vb);
+                                       headers.Add ("Vary", vb);
                        }
-
                }
-#if NET_2_0
-               [MonoTODO]
-               public void SetDiskCacheable (bool diskCacheable)
+
+               void HeadersFromFileDependencies (HttpResponse response)
                {
-                       throw new NotImplementedException (); 
+                       string [] fileDeps = response.FileDependencies;
+
+                       if (fileDeps == null || fileDeps.Length == 0)
+                               return;
+
+                       bool doEtag = etag != null && etag_from_file_dependencies;
+                       if (!doEtag && !last_modified_from_file_dependencies)
+                               return;
+
+                       DateTime latest_mod = DateTime.MinValue, mod;
+                       StringBuilder etagsb = new StringBuilder ();
+                       
+                       foreach (string f in fileDeps) {
+                               if (!File.Exists (f))
+                                       continue;
+                               try {
+                                       mod = File.GetLastWriteTime (f);
+                               } catch {
+                                       // ignore
+                                       continue;
+                               }
+
+                               if (last_modified_from_file_dependencies && mod > latest_mod)
+                                       latest_mod = mod;
+                               if (doEtag)
+                                       etagsb.AppendFormat ("{0}", mod.Ticks.ToString ("x"));
+                       }
+
+                       if (last_modified_from_file_dependencies && latest_mod > DateTime.MinValue) {
+                               last_modified = latest_mod;
+                               have_last_modified = true;
+                       }
+
+                       if (doEtag && etagsb.Length > 0)
+                               etag = etagsb.ToString ();
                }
 
-               [MonoTODO]
                public void SetOmitVaryStar (bool omit)
                {
-                       throw new NotImplementedException (); 
+                       omit_vary_star = omit;
                }
-#endif
-               
-#endregion // Methods
        }
 }
-