2 // System.Web.HttpCachePolicy
5 // Tim Coleman (tim@timcoleman.com)
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Collections;
31 using System.Globalization;
32 using System.Security.Permissions;
35 using System.Web.Util;
37 namespace System.Web {
39 class CacheabilityUpdatedEventArgs : EventArgs {
41 public readonly HttpCacheability Cacheability;
43 public CacheabilityUpdatedEventArgs (HttpCacheability cacheability)
45 Cacheability = cacheability;
49 internal delegate void CacheabilityUpdatedCallback (object sender, CacheabilityUpdatedEventArgs args);
51 // CAS - no InheritanceDemand here as the class is sealed
52 [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
53 public sealed class HttpCachePolicy {
55 internal HttpCachePolicy ()
61 HttpCacheVaryByHeaders vary_by_headers = new HttpCacheVaryByHeaders ();
62 HttpCacheVaryByParams vary_by_params = new HttpCacheVaryByParams ();
63 ArrayList validation_callbacks;
64 StringBuilder cache_extension;
65 internal HttpCacheability Cacheability;
67 bool etag_from_file_dependencies;
72 internal bool have_expire_date;
73 internal DateTime expire_date;
74 internal bool have_last_modified;
75 internal DateTime last_modified;
77 //bool LastModifiedFromFileDependencies;
78 HttpCacheRevalidation revalidation;
79 string vary_by_custom;
85 bool sliding_expiration;
87 bool allow_response_in_browser_history;
91 internal event CacheabilityUpdatedCallback CacheabilityUpdated;
95 public HttpCacheVaryByHeaders VaryByHeaders {
96 get { return vary_by_headers; }
99 public HttpCacheVaryByParams VaryByParams {
100 get { return vary_by_params; }
103 internal int Duration {
104 get { return duration; }
105 set { duration = value; }
108 internal bool Sliding {
109 get { return sliding_expiration; }
112 internal DateTime Expires {
113 get { return expire_date; }
116 internal ArrayList ValidationCallbacks {
117 get { return validation_callbacks; }
120 #endregion // Properties
124 internal int ExpireMinutes ()
126 if (!have_expire_date)
129 return (expire_date - DateTime.Now).Minutes;
132 public void AddValidationCallback (HttpCacheValidateHandler handler, object data)
135 throw new ArgumentNullException ("handler");
137 if (validation_callbacks == null)
138 validation_callbacks = new ArrayList ();
140 validation_callbacks.Add (new Pair (handler, data));
143 public void AppendCacheExtension (string extension)
145 if (extension == null)
146 throw new ArgumentNullException ("extension");
148 if (cache_extension == null)
149 cache_extension = new StringBuilder (extension);
151 cache_extension.Append (", " + extension);
155 // This one now allows the full range of Cacheabilities.
157 public void SetCacheability (HttpCacheability cacheability)
159 if (cacheability < HttpCacheability.NoCache || cacheability > HttpCacheability.ServerAndPrivate)
160 throw new ArgumentOutOfRangeException ("cacheability");
162 if (Cacheability > 0 && cacheability > Cacheability)
165 Cacheability = cacheability;
167 if (CacheabilityUpdated != null)
168 CacheabilityUpdated (this, new CacheabilityUpdatedEventArgs (cacheability));
171 public void SetCacheability (HttpCacheability cacheability, string field)
174 throw new ArgumentNullException ("field");
176 if (cacheability != HttpCacheability.NoCache && cacheability != HttpCacheability.Private)
177 throw new ArgumentException ("Must be NoCache or Private", "cacheability");
180 fields = new ArrayList ();
182 fields.Add (new Pair (cacheability, field));
185 public void SetETag (string etag)
188 throw new ArgumentNullException ("etag");
190 if (this.etag != null)
191 throw new InvalidOperationException ("The ETag header has already been set");
193 if (etag_from_file_dependencies)
194 throw new InvalidOperationException ("SetEtagFromFileDependencies has already been called");
199 public void SetETagFromFileDependencies ()
201 if (this.etag != null)
202 throw new InvalidOperationException ("The ETag header has already been set");
204 etag_from_file_dependencies = true;
207 public void SetExpires (DateTime date)
209 if (have_expire_date && date > expire_date)
212 have_expire_date = true;
216 public void SetLastModified (DateTime date)
218 if (date > DateTime.Now)
219 throw new ArgumentOutOfRangeException ("date");
221 if (have_last_modified && date < last_modified)
224 have_last_modified = true;
225 last_modified = date;
229 public void SetLastModifiedFromFileDependencies ()
231 throw new NotImplementedException ();
234 public void SetMaxAge (TimeSpan date)
236 if (date < TimeSpan.Zero)
237 throw new ArgumentOutOfRangeException ("date");
239 if (HaveMaxAge && MaxAge < date)
247 public void SetNoServerCaching ()
249 throw new NotImplementedException ();
253 public void SetNoStore ()
255 throw new NotImplementedException ();
259 public void SetNoTransforms ()
261 throw new NotImplementedException ();
264 public void SetProxyMaxAge (TimeSpan delta)
266 if (delta < TimeSpan.Zero)
267 throw new ArgumentOutOfRangeException ("delta");
269 if (HaveProxyMaxAge && ProxyMaxAge < delta)
275 public void SetRevalidation (HttpCacheRevalidation revalidation)
277 if (revalidation < HttpCacheRevalidation.AllCaches ||
278 revalidation > HttpCacheRevalidation.None)
279 throw new ArgumentOutOfRangeException ("revalidation");
281 if (this.revalidation > revalidation)
282 this.revalidation = revalidation;
285 public void SetSlidingExpiration (bool slide)
287 sliding_expiration = slide;
291 public void SetValidUntilExpires (bool validUntilExpires)
293 throw new NotImplementedException ();
296 public void SetVaryByCustom (string custom)
299 throw new ArgumentNullException ("custom");
301 if (vary_by_custom != null)
302 throw new InvalidOperationException ("VaryByCustom has already been set.");
304 vary_by_custom = custom;
307 internal string GetVaryByCustom ()
309 return vary_by_custom;
312 public void SetAllowResponseInBrowserHistory (bool allow)
314 if (Cacheability == HttpCacheability.NoCache || Cacheability == HttpCacheability.ServerAndNoCache)
315 allow_response_in_browser_history = allow;
318 internal void SetHeaders (HttpResponse response, ArrayList headers)
320 bool noCache = false;
323 switch (Cacheability) {
324 case HttpCacheability.Public:
328 case HttpCacheability.Private:
329 case HttpCacheability.ServerAndPrivate:
333 case HttpCacheability.NoCache:
334 case HttpCacheability.ServerAndNoCache:
342 response.CacheControl = cc;
343 if (!allow_response_in_browser_history) {
344 headers.Add (new UnknownResponseHeader ("Expires", "-1"));
345 headers.Add (new UnknownResponseHeader ("Pragma", "no-cache"));
348 if (MaxAge.TotalSeconds != 0)
349 cc = String.Format ("{0}, max-age={1}", cc, (long) MaxAge.TotalSeconds);
351 string expires = TimeUtil.ToUtcTimeString (expire_date);
352 headers.Add (new UnknownResponseHeader ("Expires", expires));
355 headers.Add (new UnknownResponseHeader ("Cache-Control", cc));
358 headers.Add (new UnknownResponseHeader ("ETag", etag));
360 if (have_last_modified)
361 headers.Add (new UnknownResponseHeader ("Last-Modified",
362 TimeUtil.ToUtcTimeString (last_modified)));
364 if (!vary_by_params.IgnoreParams) {
365 BaseResponseHeader vb = vary_by_params.GetResponseHeader ();
373 public void SetOmitVaryStar (bool omit)
375 throw new NotImplementedException ();
379 #endregion // Methods