//
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;
internal HttpCacheability Cacheability;
string etag;
bool etag_from_file_dependencies;
+ bool last_modified_from_file_dependencies;
//
// Used externally
internal DateTime expire_date;
internal bool have_last_modified;
internal DateTime last_modified;
-
+
//bool LastModifiedFromFileDependencies;
HttpCacheRevalidation revalidation;
string vary_by_custom;
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; }
}
get { return vary_by_params; }
}
+ internal bool AllowServerCaching {
+ get { return allow_server_caching; }
+ }
+
internal int Duration {
get { return duration; }
set { duration = value; }
internal bool Sliding {
get { return sliding_expiration; }
}
-
- internal DateTime Expires {
- get { return expire_date; }
- }
+
+ internal DateTime Expires {
+ get { return expire_date; }
+ }
internal ArrayList ValidationCallbacks {
get { return validation_callbacks; }
}
-#endregion // Properties
+ 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)
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)
last_modified = date;
}
- [MonoTODO ("Not implemented")]
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;
HaveMaxAge = true;
}
- [MonoTODO ("Not implemented")]
public void SetNoServerCaching ()
{
- throw new NotImplementedException ();
+ allow_server_caching = false;
}
- [MonoTODO ("Not implemented")]
public void SetNoStore ()
{
- throw new NotImplementedException ();
+ set_no_store = true;
}
- [MonoTODO ("Not implemented")]
public void SetNoTransforms ()
{
- throw new NotImplementedException ();
+ set_no_transform = true;
}
public void SetProxyMaxAge (TimeSpan delta)
return;
ProxyMaxAge = delta;
+ HaveProxyMaxAge = true;
}
public void SetRevalidation (HttpCacheRevalidation revalidation)
sliding_expiration = slide;
}
- [MonoTODO ("Not implemented")]
public void SetValidUntilExpires (bool validUntilExpires)
{
- throw new NotImplementedException ();
+ valid_until_expires = validUntilExpires;
}
public void SetVaryByCustom (string custom)
allow_response_in_browser_history = allow;
}
- internal void SetHeaders (HttpResponse response, ArrayList headers)
+ internal void SetHeaders (HttpResponse response, NameValueCollection headers)
{
bool noCache = false;
string cc = null;
cc = "public";
break;
- case HttpCacheability.Private:
- case HttpCacheability.ServerAndPrivate:
- cc = "private";
- break;
-
case HttpCacheability.NoCache:
case HttpCacheability.ServerAndNoCache:
- default:
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) {
- headers.Add (new UnknownResponseHeader ("Expires", "-1"));
- headers.Add (new UnknownResponseHeader ("Pragma", "no-cache"));
+ headers.Add ("Expires", "-1");
+ headers.Add ("Pragma", "no-cache");
}
} else {
- if (MaxAge.TotalSeconds != 0)
- cc = String.Format ("{0}, max-age={1}", cc, (long) MaxAge.TotalSeconds);
+ 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);
+ }
+ }
- string expires = TimeUtil.ToUtcTimeString (expire_date);
- headers.Add (new UnknownResponseHeader ("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 ("Cache-Control", cc);
+
+ if (last_modified_from_file_dependencies || etag_from_file_dependencies)
+ HeadersFromFileDependencies (response);
- headers.Add (new UnknownResponseHeader ("Cache-Control", cc));
-
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);
}
+ }
+ void HeadersFromFileDependencies (HttpResponse response)
+ {
+ 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 ();
}
-#if NET_2_0
- [MonoTODO ("Not implemented")]
+
public void SetOmitVaryStar (bool omit)
{
- throw new NotImplementedException ();
+ omit_vary_star = omit;
}
-#endif
-
-#endregion // Methods
}
}
-