RequestCookies.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. namespace OSHttpServer
  5. {
  6. /// <summary>
  7. /// This class is created as a wrapper, since there are two different cookie types in .Net (Cookie and HttpCookie).
  8. /// The framework might switch class in the future and we dont want to have to replace all instances
  9. /// </summary>
  10. public sealed class RequestCookies : IEnumerable<RequestCookie>
  11. {
  12. private readonly IDictionary<string, RequestCookie> _items = new Dictionary<string, RequestCookie>();
  13. /// <summary>
  14. /// Let's copy all the cookies.
  15. /// </summary>
  16. /// <param name="cookies">value from cookie header.</param>
  17. public RequestCookies(string cookies)
  18. {
  19. if (string.IsNullOrEmpty(cookies))
  20. return;
  21. string name = string.Empty;
  22. int state = 0;
  23. int start = -1;
  24. for (int i = 0; i < cookies.Length; ++i)
  25. {
  26. char ch = cookies[i];
  27. // searching for start of cookie name
  28. switch (state)
  29. {
  30. case 0:
  31. if (char.IsWhiteSpace(ch))
  32. continue;
  33. start = i;
  34. ++state;
  35. break;
  36. case 1:
  37. if (char.IsWhiteSpace(ch) || ch == '=')
  38. {
  39. if (start == -1)
  40. return; // todo: decide if an exception should be thrown.
  41. name = cookies.Substring(start, i - start);
  42. start = -1;
  43. ++state;
  44. }
  45. break;
  46. case 2:
  47. if (!char.IsWhiteSpace(ch) && ch != '=')
  48. {
  49. start = i;
  50. ++state;
  51. }
  52. break;
  53. case 3:
  54. if (ch == ';')
  55. {
  56. if (start >= -1)
  57. Add(new RequestCookie(name, cookies.Substring(start, i - start)));
  58. start = -1;
  59. state = 0;
  60. name = string.Empty;
  61. }
  62. break;
  63. }
  64. }
  65. // last cookie
  66. if (name != string.Empty)
  67. Add(new RequestCookie(name, cookies.Substring(start, cookies.Length - start)));
  68. }
  69. /// <summary>
  70. /// Adds a cookie in the collection.
  71. /// </summary>
  72. /// <param name="cookie">cookie to add</param>
  73. /// <exception cref="ArgumentNullException">cookie is null</exception>
  74. internal void Add(RequestCookie cookie)
  75. {
  76. // Verifies the parameter
  77. if (cookie == null)
  78. throw new ArgumentNullException("cookie");
  79. if (cookie.Name == null || cookie.Name.Trim().Length == 0)
  80. throw new ArgumentException("Name must be specified.");
  81. if (cookie.Value == null || cookie.Value.Trim().Length == 0)
  82. throw new ArgumentException("Content must be specified.");
  83. if (_items.ContainsKey(cookie.Name))
  84. _items[cookie.Name] = cookie;
  85. else _items.Add(cookie.Name, cookie);
  86. }
  87. /// <summary>
  88. /// Gets the count of cookies in the collection.
  89. /// </summary>
  90. public int Count
  91. {
  92. get { return _items.Count; }
  93. }
  94. /// <summary>
  95. /// Gets the cookie of a given identifier (null if not existing).
  96. /// </summary>
  97. public RequestCookie this[string id]
  98. {
  99. get
  100. {
  101. return _items.ContainsKey(id) ? _items[id] : null;
  102. }
  103. }
  104. /// <summary>
  105. /// Gets a collection enumerator on the cookie list.
  106. /// </summary>
  107. /// <returns>collection enumerator</returns>
  108. public IEnumerator GetEnumerator()
  109. {
  110. return _items.Values.GetEnumerator();
  111. }
  112. /// <summary>
  113. /// Remove all cookies.
  114. /// </summary>
  115. public void Clear()
  116. {
  117. _items.Clear();
  118. }
  119. #region IEnumerable<RequestCookie> Members
  120. ///<summary>
  121. ///Returns an enumerator that iterates through the collection.
  122. ///</summary>
  123. ///
  124. ///<returns>
  125. ///A <see cref="T:System.Collections.Generic.IEnumerator`1"></see> that can be used to iterate through the collection.
  126. ///</returns>
  127. ///<filterpriority>1</filterpriority>
  128. IEnumerator<RequestCookie> IEnumerable<RequestCookie>.GetEnumerator()
  129. {
  130. return _items.Values.GetEnumerator();
  131. }
  132. #endregion
  133. /// <summary>
  134. /// Remove a cookie from the collection.
  135. /// </summary>
  136. /// <param name="cookieName">Name of cookie.</param>
  137. public void Remove(string cookieName)
  138. {
  139. lock (_items)
  140. {
  141. if (!_items.ContainsKey(cookieName))
  142. return;
  143. _items.Remove(cookieName);
  144. }
  145. }
  146. }
  147. }