using System; using System.Collections; using System.Collections.Generic; namespace OSHttpServer { /// /// This class is created as a wrapper, since there are two different cookie types in .Net (Cookie and HttpCookie). /// The framework might switch class in the future and we dont want to have to replace all instances /// public sealed class RequestCookies : IEnumerable { private readonly IDictionary _items = new Dictionary(); /// /// Let's copy all the cookies. /// /// value from cookie header. public RequestCookies(string cookies) { if (string.IsNullOrEmpty(cookies)) return; string name = string.Empty; int state = 0; int start = -1; for (int i = 0; i < cookies.Length; ++i) { char ch = cookies[i]; // searching for start of cookie name switch (state) { case 0: if (char.IsWhiteSpace(ch)) continue; start = i; ++state; break; case 1: if (char.IsWhiteSpace(ch) || ch == '=') { if (start == -1) return; // todo: decide if an exception should be thrown. name = cookies.Substring(start, i - start); start = -1; ++state; } break; case 2: if (!char.IsWhiteSpace(ch) && ch != '=') { start = i; ++state; } break; case 3: if (ch == ';') { if (start >= -1) Add(new RequestCookie(name, cookies.Substring(start, i - start))); start = -1; state = 0; name = string.Empty; } break; } } // last cookie if (name != string.Empty) Add(new RequestCookie(name, cookies.Substring(start, cookies.Length - start))); } /// /// Adds a cookie in the collection. /// /// cookie to add /// cookie is null internal void Add(RequestCookie cookie) { // Verifies the parameter if (cookie == null) throw new ArgumentNullException("cookie"); if (cookie.Name == null || cookie.Name.Trim().Length == 0) throw new ArgumentException("Name must be specified."); if (cookie.Value == null || cookie.Value.Trim().Length == 0) throw new ArgumentException("Content must be specified."); if (_items.ContainsKey(cookie.Name)) _items[cookie.Name] = cookie; else _items.Add(cookie.Name, cookie); } /// /// Gets the count of cookies in the collection. /// public int Count { get { return _items.Count; } } /// /// Gets the cookie of a given identifier (null if not existing). /// public RequestCookie this[string id] { get { return _items.ContainsKey(id) ? _items[id] : null; } } /// /// Gets a collection enumerator on the cookie list. /// /// collection enumerator public IEnumerator GetEnumerator() { return _items.Values.GetEnumerator(); } /// /// Remove all cookies. /// public void Clear() { _items.Clear(); } #region IEnumerable Members /// ///Returns an enumerator that iterates through the collection. /// /// /// ///A that can be used to iterate through the collection. /// ///1 IEnumerator IEnumerable.GetEnumerator() { return _items.Values.GetEnumerator(); } #endregion /// /// Remove a cookie from the collection. /// /// Name of cookie. public void Remove(string cookieName) { lock (_items) { if (!_items.ContainsKey(cookieName)) return; _items.Remove(cookieName); } } } }