Modified Cookie.cs, CookieCollection.cs

This commit is contained in:
sta
2013-04-10 15:31:15 +09:00
parent 9bf4adfbab
commit 48dbb4a811
30 changed files with 204 additions and 91 deletions

View File

@@ -40,18 +40,21 @@ using System.Collections;
namespace WebSocketSharp.Net {
/// <summary>
/// Provides a set of properties and methods to use to manage the HTTP Cookie.
/// Provides a set of properties and methods used to manage an HTTP Cookie.
/// </summary>
/// <remarks>
/// The Cookie class cannot be inherited.
/// <para>
/// The Cookie class supports the following cookie formats:
/// <see href="http://web.archive.org/web/20020803110822/http://wp.netscape.com/newsref/std/cookie_spec.html">Netscape specification</see>,
/// <see href="http://www.ietf.org/rfc/rfc2109.txt">RFC 2109</see> and
/// <see href="http://www.ietf.org/rfc/rfc2965.txt">RFC 2965</see>.
/// </para>
/// <para>
/// The Cookie class cannot be inherited.
/// </para>
/// </remarks>
[Serializable]
public sealed class Cookie
{
// Supported cookie formats are:
// Netscape: http://home.netscape.com/newsref/std/cookie_spec.html
// RFC 2109: http://www.ietf.org/rfc/rfc2109.txt
// RFC 2965: http://www.ietf.org/rfc/rfc2965.txt
public sealed class Cookie {
#region Static Private Fields
@@ -79,7 +82,7 @@ namespace WebSocketSharp.Net {
#endregion
#region Constructors
#region Public Constructors
/// <summary>
/// Initializes a new instance of the <see cref="Cookie"/> class.
@@ -135,15 +138,8 @@ namespace WebSocketSharp.Net {
public Cookie (string name, string value)
: this ()
{
string msg;
if (!CanSetName (name, out msg))
throw new CookieException (msg);
if (!CanSetValue (value, out msg))
throw new CookieException (msg);
this.name = name;
this.val = value;
Name = name;
Value = value;
}
/// <summary>
@@ -465,23 +461,28 @@ namespace WebSocketSharp.Net {
/// <value>
/// A <see cref="string"/> that contains the Value of the cookie.
/// </value>
/// <exception cref="CookieException">
/// <para>
/// The value specified for a set operation is <see langword="null"/>.
/// </para>
/// <para>
/// - or -
/// </para>
/// <para>
/// The value specified for a set operation contains a string not enclosed in double quotes
/// that contains an invalid character.
/// </para>
/// </exception>
public string Value {
get { return val; }
set {
if (value == null) {
val = String.Empty;
return;
}
set {
string msg;
if (!CanSetValue (value, out msg))
throw new CookieException (msg);
// LAMESPEC: According to .Net specs the Value property should not accept
// the semicolon and comma characters, yet it does. For now we'll follow
// the behaviour of MS.Net instead of the specs.
/*
if (value.IndexOfAny(reservedCharsForValue) != -1)
throw new CookieException("Invalid value. Value cannot contain semicolon or comma characters.");
*/
val = value;
val = value.IsEmpty ()
? "\"\""
: value;
}
}
@@ -512,7 +513,7 @@ namespace WebSocketSharp.Net {
static bool CanSetName (string name, out string message)
{
if (name.IsNullOrEmpty ()) {
message = "Name can not be null or empty.";
message = "Name must not be null or empty.";
return false;
}
@@ -528,7 +529,7 @@ namespace WebSocketSharp.Net {
static bool CanSetValue (string value, out string message)
{
if (value.IsNull ()) {
message = "Value can not be null.";
message = "Value must not be null.";
return false;
}
@@ -548,7 +549,7 @@ namespace WebSocketSharp.Net {
return i ^ (j << 13 | j >> 19) ^ (k << 26 | k >> 6) ^ (l << 7 | l >> 25) ^ (m << 20 | m >> 12);
}
// See par 3.6 of RFC 2616
// See para 3.6 of RFC 2616
string Quote (string value)
{
if (version == 0 || value.IsToken ())
@@ -559,7 +560,7 @@ namespace WebSocketSharp.Net {
string ToResponseStringVersion0 ()
{
var result = new StringBuilder ();
var result = new StringBuilder (64);
result.AppendFormat ("{0}={1}", name, val);
if (expires != DateTime.MinValue)
result.AppendFormat ("; Expires={0}",
@@ -583,7 +584,7 @@ namespace WebSocketSharp.Net {
string ToResponseStringVersion1 ()
{
var result = new StringBuilder ();
var result = new StringBuilder (64);
result.AppendFormat ("{0}={1}; Version={2}", name, val, version);
if (expires != DateTime.MinValue)
result.AppendFormat ("; Max-Age={0}", MaxAge);
@@ -595,7 +596,10 @@ namespace WebSocketSharp.Net {
result.AppendFormat ("; Domain={0}", domain);
if (!port.IsNullOrEmpty ())
result.AppendFormat ("; Port={0}", port);
if (port == "\"\"")
result.Append ("; Port");
else
result.AppendFormat ("; Port={0}", port);
if (!comment.IsNullOrEmpty ())
result.AppendFormat ("; Comment={0}", comment.UrlEncode ());
@@ -647,7 +651,7 @@ namespace WebSocketSharp.Net {
if (version == 0)
return String.Format ("{0}={1}", name, val);
var result = new StringBuilder ();
var result = new StringBuilder (64);
result.AppendFormat ("$Version={0}; {1}={2}", version, name, val);
if (!path.IsNullOrEmpty ())
result.AppendFormat ("; $Path={0}", path);
@@ -661,7 +665,10 @@ namespace WebSocketSharp.Net {
result.AppendFormat ("; $Domain={0}", domain);
if (!port.IsNullOrEmpty ())
result.AppendFormat ("; $Port={0}", port);
if (port == "\"\"")
result.Append ("; $Port");
else
result.AppendFormat ("; $Port={0}", port);
return result.ToString ();
}

View File

@@ -62,20 +62,20 @@ namespace WebSocketSharp.Net {
}
}
#region Static Field
#region Private Static Fields
static CookieCollectionComparer Comparer = new CookieCollectionComparer ();
#endregion
#region Field
#region Private Fields
List<Cookie> list;
object sync;
#endregion
#region Constructor
#region Public Constructors
/// <summary>
/// Initializes a new instance of the <see cref="CookieCollection"/> class.
@@ -87,7 +87,7 @@ namespace WebSocketSharp.Net {
#endregion
#region Internal Property
#region Internal Properties
internal IList<Cookie> List {
get { return list; }
@@ -182,7 +182,7 @@ namespace WebSocketSharp.Net {
if (name.IsNull ())
throw new ArgumentNullException ("name");
foreach (var cookie in list) {
foreach (var cookie in Sorted) {
if (cookie.Name.Equals (name, StringComparison.InvariantCultureIgnoreCase))
return cookie;
}
@@ -208,7 +208,7 @@ namespace WebSocketSharp.Net {
#endregion
#region Private Method
#region Private Methods
static CookieCollection ParseRequest (string value)
{
@@ -216,9 +216,8 @@ namespace WebSocketSharp.Net {
Cookie cookie = null;
int version = 0;
string [] pairs = value.Split (',', ';');
for (int i = 0; i < pairs.Length; i++)
{
string [] pairs = Split(value).ToArray();
for (int i = 0; i < pairs.Length; i++) {
string pair = pairs [i].Trim ();
if (pair.IsEmpty ())
continue;
@@ -235,27 +234,32 @@ namespace WebSocketSharp.Net {
cookie.Domain = pair.GetValueInternal ("=");
}
else if (pair.StartsWith ("$port", StringComparison.InvariantCultureIgnoreCase)) {
if (!pair.Equals ("$port", StringComparison.InvariantCultureIgnoreCase) && !pair.EndsWith ("\"")) {
var buffer = new StringBuilder (pair);
string port;
while (i < pairs.Length - 1) {
port = pairs [++i].Trim ();
buffer.AppendFormat (", {0}", port);
if (port.EndsWith ("\""))
break;
}
pair = buffer.ToString ();
}
var port = pair.Equals ("$port", StringComparison.InvariantCultureIgnoreCase)
? "\"\""
: pair.GetValueInternal ("=");
if (!cookie.IsNull ())
cookie.Port = pair.GetValueInternal ("=");
cookie.Port = port;
}
else {
if (!cookie.IsNull ())
cookies.Add (cookie);
cookie = new Cookie (pair.GetNameInternal ("="), pair.GetValueInternal ("="));
string name;
string val = String.Empty;
int pos = pair.IndexOf ('=');
if (pos == -1) {
name = pair;
}
else if (pos == pair.Length - 1) {
name = pair.Substring (0, pos).TrimEnd (' ');
}
else {
name = pair.Substring (0, pos).TrimEnd (' ');
val = pair.Substring (pos + 1).TrimStart (' ');
}
cookie = new Cookie (name, val);
if (version != 0)
cookie.Version = version;
}
@@ -272,9 +276,8 @@ namespace WebSocketSharp.Net {
var cookies = new CookieCollection ();
Cookie cookie = null;
string [] pairs = value.Split (',', ';');
for (int i = 0; i < pairs.Length; i++)
{
string [] pairs = Split(value).ToArray();
for (int i = 0; i < pairs.Length; i++) {
string pair = pairs [i].Trim ();
if (pair.IsEmpty ())
continue;
@@ -284,7 +287,7 @@ namespace WebSocketSharp.Net {
cookie.Version = Int32.Parse (pair.GetValueInternal ("=").Trim ('"'));
}
else if (pair.StartsWith ("expires", StringComparison.InvariantCultureIgnoreCase)) {
var buffer = new StringBuilder (pair.GetValueInternal ("="));
var buffer = new StringBuilder (pair.GetValueInternal ("="), 32);
if (i < pairs.Length - 1)
buffer.AppendFormat (", {0}", pairs [++i].Trim ());
@@ -314,21 +317,12 @@ namespace WebSocketSharp.Net {
cookie.Domain = pair.GetValueInternal ("=");
}
else if (pair.StartsWith ("port", StringComparison.InvariantCultureIgnoreCase)) {
if (!pair.Equals ("port", StringComparison.InvariantCultureIgnoreCase) && !pair.EndsWith ("\"")) {
var buffer = new StringBuilder (pair);
string port;
while (i < pairs.Length - 1) {
port = pairs [++i].Trim ();
buffer.AppendFormat (", {0}", port);
if (port.EndsWith ("\""))
break;
}
pair = buffer.ToString ();
}
var port = pair.Equals ("port", StringComparison.InvariantCultureIgnoreCase)
? "\"\""
: pair.GetValueInternal ("=");
if (!cookie.IsNull ())
cookie.Port = pair.GetValueInternal ("=");
cookie.Port = port;
}
else if (pair.StartsWith ("comment", StringComparison.InvariantCultureIgnoreCase)) {
if (!cookie.IsNull ())
@@ -354,7 +348,21 @@ namespace WebSocketSharp.Net {
if (!cookie.IsNull ())
cookies.Add (cookie);
cookie = new Cookie (pair.GetNameInternal ("="), pair.GetValueInternal ("="));
string name;
string val = String.Empty;
int pos = pair.IndexOf ('=');
if (pos == -1) {
name = pair;
}
else if (pos == pair.Length - 1) {
name = pair.Substring (0, pos).TrimEnd (' ');
}
else {
name = pair.Substring (0, pos).TrimEnd (' ');
val = pair.Substring (pos + 1).TrimStart (' ');
}
cookie = new Cookie (name, val);
}
}
@@ -391,9 +399,33 @@ namespace WebSocketSharp.Net {
return -1;
}
static IEnumerable<string> Split (string value)
{
var buffer = new StringBuilder (64);
bool quoted = false;
foreach (char c in value) {
if (c == '"') {
quoted = !quoted;
}
else if (c == ',' || c == ';') {
if (!quoted) {
yield return buffer.ToString ();
buffer.Length = 0;
continue;
}
}
else {
}
buffer.Append (c);
}
yield return buffer.ToString ();
}
#endregion
#region Internal Method
#region Internal Methods
internal static CookieCollection Parse (string value, bool response)
{