File: HttpCacheVary.cs
Project: ndp\fx\src\xsp\system\Web\System.Web.csproj (System.Web)
//------------------------------------------------------------------------------
// <copyright file="HttpCacheVary.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>                                                                
//------------------------------------------------------------------------------
 
/*
 * Cache Vary class.  Wraps Vary header
 * 
 * Copyright (c) 1998 Microsoft Corporation
 */
 
namespace System.Web {
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Web.Util;
    using System.Security.Permissions;
 
 
    /// <devdoc>
    ///    <para>Indicates that a cache should contain multiple 
    ///       representations for a particular Uri. This class is an encapsulation that
    ///       provides a rich, type-safe way to set the Vary header.</para>
    /// </devdoc>
    public sealed class HttpCacheVaryByHeaders {
        bool            _isModified;
        bool            _varyStar;
        HttpDictionary  _headers;
 
        public HttpCacheVaryByHeaders() {
            Reset();
        }
 
        internal void Reset() {
            _isModified = false;
            _varyStar = false;
            _headers = null;
        }
 
        /// <summary>
        /// Set the Headers in Cache Vary
        /// </summary>
        /// <param name="headers"></param>
        public void SetHeaders(string[] headers) {
 
            int i, n;
 
            if (headers == null) {
                _isModified = false;
                _varyStar = false;
                _headers = null;
            }
            else {           
                _isModified = true;
                if (headers[0].Equals("*")) {
                    Debug.Assert(headers.Length == 1, "headers.Length == 1");
 
                    _varyStar = true;
                    _headers = null;
                }
                else {
                    _varyStar = false;
                    _headers = new HttpDictionary();
                    for (i = 0, n = headers.Length; i < n; i++) {
                        _headers.SetValue(headers[i], headers[i]);
                    }
                }
            }
        }
 
        internal bool IsModified() {
            return _isModified;
        }
 
        /*
         * Construct header value string
         */
        internal String ToHeaderString() {
            StringBuilder   s;
            Object          item;
            int             i, n;
 
            if (_varyStar) {
                return "*";
            }
            else if (_headers != null) {
                s = new StringBuilder();
 
                for (i = 0, n = _headers.Size; i < n; i++) {
                    item = _headers.GetValue(i);
                    if (item != null) {
                        HttpCachePolicy.AppendValueToHeader(s, (String)item);
                    }
                }
 
                if (s.Length > 0)
                    return s.ToString();
            }
 
            return null;
        }
 
        /// <summary>
        /// Get the Headers in Cache Vary
        /// </summary>
        /// <returns></returns>
        public string[] GetHeaders() {
            string[]    s = null;
 
            Object      item;
            int         i, j, c, n;
 
            if (_varyStar) {
                return new string[1] {"*"};
            }
            else if (_headers != null) {
                n = _headers.Size;
                c = 0;
                for (i = 0; i < n; i++) {
                    item = _headers.GetValue(i);
                    if (item != null) {
                        c++;
                    }
                }
 
                if (c > 0) {
                    s = new string[c];
                    j = 0;
                    for (i = 0; i < n; i++) {
                        item = _headers.GetValue(i);
                        if (item != null) {
                            s[j] = (string) item;
                            j++;
                        }
                    }
 
                    Debug.Assert(j == c, "j == c");
                }
            }
 
            return s;
        }
  
        //
        // Public methods and properties
        //
 
 
        /// <devdoc>
        ///    <para>Sets the "Vary: *" header and causes all other Vary:
        ///       header information to be dropped.</para>
        /// </devdoc>
        public void VaryByUnspecifiedParameters() {
            _isModified = true;
            _varyStar = true;
            _headers = null;
        }
 
        internal bool GetVaryByUnspecifiedParameters() {
            return _varyStar;
        }
 
        /*
         * Vary by accept types
         */
 
        /// <devdoc>
        ///    <para>Retrieves or assigns a value indicating whether the cache should vary by Accept types. This causes the
        ///       Vary: header to include an Accept field.</para>
        /// </devdoc>
        public bool AcceptTypes {
            get { 
                return this["Accept"]; 
            }
 
            set {         
                _isModified = true;
                this["Accept"] = value; 
            }
        }
 
        /*
         * Vary by accept language
         */
 
        /// <devdoc>
        ///    <para> Retrieves or assigns a Boolean value indicating whether
        ///       the cache should vary by user language.</para>
        /// </devdoc>
        public bool UserLanguage {
            get { 
                return this["Accept-Language"]; 
            }
 
            set { 
                _isModified = true;
                this["Accept-Language"] = value; 
            }
        }
 
        /*
         * Vary by user agent
         */
 
        /// <devdoc>
        ///    <para> Retrieves or assigns a Boolean value indicating whether
        ///       the cache should vary by user agent.</para>
        /// </devdoc>
        public bool UserAgent {
            get {   
                return this["User-Agent"]; 
            }
 
            set { 
                _isModified = true;
                this["User-Agent"] = value; 
            }
        }
 
        /*
         * Vary by charset
         */
 
        /// <devdoc>
        ///    <para> Retrieves or assigns a value indicating whether the
        ///       cache should vary by browser character set.</para>
        /// </devdoc>
        public bool UserCharSet {
            get { 
                return this["Accept-Charset"]; 
            }
 
            set { 
                _isModified = true;
                this["Accept-Charset"] = value; 
            }
        }
 
        /*
         * Vary by a given header
         */
 
        /// <devdoc>
        ///    <para> Default property.
        ///       Indexed property indicating that a cache should (or should not) vary according
        ///       to a custom header.</para>
        /// </devdoc>
        public bool this[String header]
        {
            get {
                if (header == null) {
                    throw new ArgumentNullException("header");
                }
 
                if (header.Equals("*")) {
                    return _varyStar;
                }
                else {
                    return (_headers != null && _headers.GetValue(header) != null);
                }
            }
 
            set {
                if (header == null) {
                    throw new ArgumentNullException("header");
                }
 
                /*
                 * Since adding a Vary header is more restrictive, we don't
                 * want components to be able to set a Vary header to false
                 * if another component has set it to true.
                 */
                if (value == false) {
                    return;
                }
 
                _isModified = true;
 
                if (header.Equals("*")) {
                    VaryByUnspecifiedParameters();
                }
                else {
                    // set value to header if true or null if false
                    if (!_varyStar) {
                        if (_headers == null) {
                            _headers = new HttpDictionary();
                        }
 
                        _headers.SetValue(header, header);
                    }
                }
            }
        }
    }
}