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);
}
}
}
}