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 #endregion // Properties
120 internal int ExpireMinutes ()
122 if (!have_expire_date)
125 return (expire_date - DateTime.Now).Minutes;
128 public void AddValidationCallback (HttpCacheValidateHandler handler, object data)
131 throw new ArgumentNullException ("handler");
133 if (validation_callbacks == null)
134 validation_callbacks = new ArrayList ();
136 validation_callbacks.Add (new Pair (handler, data));
139 public void AppendCacheExtension (string extension)
141 if (extension == null)
142 throw new ArgumentNullException ("extension");
144 if (cache_extension == null)
145 cache_extension = new StringBuilder (extension);
147 cache_extension.Append (", " + extension);
151 // This one now allows the full range of Cacheabilities.
153 public void SetCacheability (HttpCacheability cacheability)
155 if (cacheability < HttpCacheability.NoCache || cacheability > HttpCacheability.ServerAndPrivate)
156 throw new ArgumentOutOfRangeException ("cacheability");
158 if (Cacheability > 0 && cacheability > Cacheability)
161 Cacheability = cacheability;
163 if (CacheabilityUpdated != null)
164 CacheabilityUpdated (this, new CacheabilityUpdatedEventArgs (cacheability));
167 public void SetCacheability (HttpCacheability cacheability, string field)
170 throw new ArgumentNullException ("field");
172 if (cacheability != HttpCacheability.NoCache && cacheability != HttpCacheability.Private)
173 throw new ArgumentException ("Must be NoCache or Private", "cacheability");
176 fields = new ArrayList ();
178 fields.Add (new Pair (cacheability, field));
181 public void SetETag (string etag)
184 throw new ArgumentNullException ("etag");
186 if (this.etag != null)
187 throw new InvalidOperationException ("The ETag header has already been set");
189 if (etag_from_file_dependencies)
190 throw new InvalidOperationException ("SetEtagFromFileDependencies has already been called");
195 public void SetETagFromFileDependencies ()
197 if (this.etag != null)
198 throw new InvalidOperationException ("The ETag header has already been set");
200 etag_from_file_dependencies = true;
203 public void SetExpires (DateTime date)
205 if (have_expire_date && date > expire_date)
208 have_expire_date = true;
212 public void SetLastModified (DateTime date)
214 if (date > DateTime.Now)
215 throw new ArgumentOutOfRangeException ("date");
217 if (have_last_modified && date < last_modified)
220 have_last_modified = true;
221 last_modified = date;
225 public void SetLastModifiedFromFileDependencies ()
227 throw new NotImplementedException ();
230 public void SetMaxAge (TimeSpan date)
232 if (date < TimeSpan.Zero)
233 throw new ArgumentOutOfRangeException ("date");
235 if (HaveMaxAge && MaxAge < date)
243 public void SetNoServerCaching ()
245 throw new NotImplementedException ();
249 public void SetNoStore ()
251 throw new NotImplementedException ();
255 public void SetNoTransforms ()
257 throw new NotImplementedException ();
260 public void SetProxyMaxAge (TimeSpan delta)
262 if (delta < TimeSpan.Zero)
263 throw new ArgumentOutOfRangeException ("delta");
265 if (HaveProxyMaxAge && ProxyMaxAge < delta)
271 public void SetRevalidation (HttpCacheRevalidation revalidation)
273 if (revalidation < HttpCacheRevalidation.AllCaches ||
274 revalidation > HttpCacheRevalidation.None)
275 throw new ArgumentOutOfRangeException ("revalidation");
277 if (this.revalidation > revalidation)
278 this.revalidation = revalidation;
281 public void SetSlidingExpiration (bool slide)
283 sliding_expiration = slide;
287 public void SetValidUntilExpires (bool validUntilExpires)
289 throw new NotImplementedException ();
292 public void SetVaryByCustom (string custom)
295 throw new ArgumentNullException ("custom");
297 if (vary_by_custom != null)
298 throw new InvalidOperationException ("VaryByCustom has already been set.");
300 vary_by_custom = custom;
303 internal string GetVaryByCustom ()
305 return vary_by_custom;
308 public void SetAllowResponseInBrowserHistory (bool allow)
310 if (Cacheability == HttpCacheability.NoCache || Cacheability == HttpCacheability.ServerAndNoCache)
311 allow_response_in_browser_history = allow;
314 internal void SetHeaders (HttpResponse response, ArrayList headers)
317 if (Cacheability > HttpCacheability.NoCache) {
318 string c = Cacheability.ToString ().ToLower (CultureInfo.InvariantCulture);
320 if (MaxAge.TotalSeconds != 0)
321 cc = String.Format ("{0}, max-age={1}", c, (long) MaxAge.TotalSeconds);
325 expires = TimeUtil.ToUtcTimeString (expire_date);
326 headers.Add (new UnknownResponseHeader ("Expires", expires));
329 response.CacheControl = cc;
330 if (!allow_response_in_browser_history) {
332 headers.Add (new UnknownResponseHeader ("Expires", expires));
336 headers.Add (new UnknownResponseHeader ("Cache-Control", cc));
339 headers.Add (new UnknownResponseHeader ("ETag", etag));
341 if (have_last_modified)
342 headers.Add (new UnknownResponseHeader ("Last-Modified",
343 TimeUtil.ToUtcTimeString (last_modified)));
345 if (!vary_by_params.IgnoreParams) {
346 BaseResponseHeader vb = vary_by_params.GetResponseHeader ();
354 public void SetOmitVaryStar (bool omit)
356 throw new NotImplementedException ();
360 #endregion // Methods