mscorlib(4.0.0.0) API with additions
Cookie.cs
1 using System.Collections;
5 
6 namespace System.Net
7 {
10  [global::__DynamicallyInvokable]
11  public sealed class Cookie
12  {
13  internal const int MaxSupportedVersion = 1;
14 
15  internal const string CommentAttributeName = "Comment";
16 
17  internal const string CommentUrlAttributeName = "CommentURL";
18 
19  internal const string DiscardAttributeName = "Discard";
20 
21  internal const string DomainAttributeName = "Domain";
22 
23  internal const string ExpiresAttributeName = "Expires";
24 
25  internal const string MaxAgeAttributeName = "Max-Age";
26 
27  internal const string PathAttributeName = "Path";
28 
29  internal const string PortAttributeName = "Port";
30 
31  internal const string SecureAttributeName = "Secure";
32 
33  internal const string VersionAttributeName = "Version";
34 
35  internal const string HttpOnlyAttributeName = "HttpOnly";
36 
37  internal const string SeparatorLiteral = "; ";
38 
39  internal const string EqualsLiteral = "=";
40 
41  internal const string QuotesLiteral = "\"";
42 
43  internal const string SpecialAttributeLiteral = "$";
44 
45  internal static readonly char[] PortSplitDelimiters = new char[3]
46  {
47  ' ',
48  ',',
49  '"'
50  };
51 
52  internal static readonly char[] Reserved2Name = new char[7]
53  {
54  ' ',
55  '\t',
56  '\r',
57  '\n',
58  '=',
59  ';',
60  ','
61  };
62 
63  internal static readonly char[] Reserved2Value = new char[2]
64  {
65  ';',
66  ','
67  };
68 
69  private static Comparer staticComparer = new Comparer();
70 
71  private string m_comment = string.Empty;
72 
73  private Uri m_commentUri;
74 
75  private CookieVariant m_cookieVariant = CookieVariant.Plain;
76 
77  private bool m_discard;
78 
79  private string m_domain = string.Empty;
80 
81  private bool m_domain_implicit = true;
82 
83  private DateTime m_expires = DateTime.MinValue;
84 
85  private string m_name = string.Empty;
86 
87  private string m_path = string.Empty;
88 
89  private bool m_path_implicit = true;
90 
91  private string m_port = string.Empty;
92 
93  private bool m_port_implicit = true;
94 
95  private int[] m_port_list;
96 
97  private bool m_secure;
98 
99  [OptionalField]
100  private bool m_httpOnly;
101 
102  private DateTime m_timeStamp = DateTime.Now;
103 
104  private string m_value = string.Empty;
105 
106  private int m_version;
107 
108  private string m_domainKey = string.Empty;
109 
110  internal bool IsQuotedVersion;
111 
112  internal bool IsQuotedDomain;
113 
116  [global::__DynamicallyInvokable]
117  public string Comment
118  {
119  [global::__DynamicallyInvokable]
120  get
121  {
122  return m_comment;
123  }
124  [global::__DynamicallyInvokable]
125  set
126  {
127  if (value == null)
128  {
129  value = string.Empty;
130  }
131  m_comment = value;
132  }
133  }
134 
137  [global::__DynamicallyInvokable]
138  public Uri CommentUri
139  {
140  [global::__DynamicallyInvokable]
141  get
142  {
143  return m_commentUri;
144  }
145  [global::__DynamicallyInvokable]
146  set
147  {
148  m_commentUri = value;
149  }
150  }
151 
154  [global::__DynamicallyInvokable]
155  public bool HttpOnly
156  {
157  [global::__DynamicallyInvokable]
158  get
159  {
160  return m_httpOnly;
161  }
162  [global::__DynamicallyInvokable]
163  set
164  {
165  m_httpOnly = value;
166  }
167  }
168 
172  [global::__DynamicallyInvokable]
173  public bool Discard
174  {
175  [global::__DynamicallyInvokable]
176  get
177  {
178  return m_discard;
179  }
180  [global::__DynamicallyInvokable]
181  set
182  {
183  m_discard = value;
184  }
185  }
186 
189  [global::__DynamicallyInvokable]
190  public string Domain
191  {
192  [global::__DynamicallyInvokable]
193  get
194  {
195  return m_domain;
196  }
197  [global::__DynamicallyInvokable]
198  set
199  {
200  m_domain = ((value == null) ? string.Empty : value);
201  m_domain_implicit = false;
202  m_domainKey = string.Empty;
203  }
204  }
205 
206  private string _Domain
207  {
208  get
209  {
210  if (!Plain && !m_domain_implicit && m_domain.Length != 0)
211  {
212  return "$Domain=" + (IsQuotedDomain ? "\"" : string.Empty) + m_domain + (IsQuotedDomain ? "\"" : string.Empty);
213  }
214  return string.Empty;
215  }
216  }
217 
218  internal bool DomainImplicit
219  {
220  get
221  {
222  return m_domain_implicit;
223  }
224  set
225  {
226  m_domain_implicit = value;
227  }
228  }
229 
233  [global::__DynamicallyInvokable]
234  public bool Expired
235  {
236  [global::__DynamicallyInvokable]
237  get
238  {
239  if (m_expires != DateTime.MinValue)
240  {
241  return m_expires.ToLocalTime() <= DateTime.Now;
242  }
243  return false;
244  }
245  [global::__DynamicallyInvokable]
246  set
247  {
248  if (value)
249  {
250  m_expires = DateTime.Now;
251  }
252  }
253  }
254 
257  [global::__DynamicallyInvokable]
258  public DateTime Expires
259  {
260  [global::__DynamicallyInvokable]
261  get
262  {
263  return m_expires;
264  }
265  [global::__DynamicallyInvokable]
266  set
267  {
268  m_expires = value;
269  }
270  }
271 
275  [global::__DynamicallyInvokable]
276  public string Name
277  {
278  [global::__DynamicallyInvokable]
279  get
280  {
281  return m_name;
282  }
283  [global::__DynamicallyInvokable]
284  set
285  {
286  if (ValidationHelper.IsBlankString(value) || !InternalSetName(value))
287  {
288  throw new CookieException(SR.GetString("net_cookie_attribute", "Name", (value == null) ? "<null>" : value));
289  }
290  }
291  }
292 
295  [global::__DynamicallyInvokable]
296  public string Path
297  {
298  [global::__DynamicallyInvokable]
299  get
300  {
301  return m_path;
302  }
303  [global::__DynamicallyInvokable]
304  set
305  {
306  m_path = ((value == null) ? string.Empty : value);
307  m_path_implicit = false;
308  }
309  }
310 
311  private string _Path
312  {
313  get
314  {
315  if (!Plain && !m_path_implicit && m_path.Length != 0)
316  {
317  return "$Path=" + m_path;
318  }
319  return string.Empty;
320  }
321  }
322 
323  internal bool Plain => Variant == CookieVariant.Plain;
324 
328  [global::__DynamicallyInvokable]
329  public string Port
330  {
331  [global::__DynamicallyInvokable]
332  get
333  {
334  return m_port;
335  }
336  [global::__DynamicallyInvokable]
337  set
338  {
339  m_port_implicit = false;
340  if (value == null || value.Length == 0)
341  {
342  m_port = string.Empty;
343  return;
344  }
345  if (value[0] != '"' || value[value.Length - 1] != '"')
346  {
347  throw new CookieException(SR.GetString("net_cookie_attribute", "Port", value));
348  }
349  string[] array = value.Split(PortSplitDelimiters);
350  List<int> list = new List<int>();
351  for (int i = 0; i < array.Length; i++)
352  {
353  if (array[i] != string.Empty)
354  {
355  if (!int.TryParse(array[i], out int result))
356  {
357  throw new CookieException(SR.GetString("net_cookie_attribute", "Port", value));
358  }
359  if (result < 0 || result > 65535)
360  {
361  throw new CookieException(SR.GetString("net_cookie_attribute", "Port", value));
362  }
363  list.Add(result);
364  }
365  }
366  m_port_list = list.ToArray();
367  m_port = value;
368  m_version = 1;
369  m_cookieVariant = CookieVariant.Rfc2965;
370  }
371  }
372 
373  internal int[] PortList => m_port_list;
374 
375  private string _Port
376  {
377  get
378  {
379  if (!m_port_implicit)
380  {
381  return "$Port" + ((m_port.Length == 0) ? string.Empty : ("=" + m_port));
382  }
383  return string.Empty;
384  }
385  }
386 
390  [global::__DynamicallyInvokable]
391  public bool Secure
392  {
393  [global::__DynamicallyInvokable]
394  get
395  {
396  return m_secure;
397  }
398  [global::__DynamicallyInvokable]
399  set
400  {
401  m_secure = value;
402  }
403  }
404 
407  [global::__DynamicallyInvokable]
408  public DateTime TimeStamp
409  {
410  [global::__DynamicallyInvokable]
411  get
412  {
413  return m_timeStamp;
414  }
415  }
416 
419  [global::__DynamicallyInvokable]
420  public string Value
421  {
422  [global::__DynamicallyInvokable]
423  get
424  {
425  return m_value;
426  }
427  [global::__DynamicallyInvokable]
428  set
429  {
430  m_value = ((value == null) ? string.Empty : value);
431  }
432  }
433 
434  internal CookieVariant Variant
435  {
436  get
437  {
438  return m_cookieVariant;
439  }
440  set
441  {
442  m_cookieVariant = value;
443  }
444  }
445 
446  internal string DomainKey
447  {
448  get
449  {
450  if (!m_domain_implicit)
451  {
452  return m_domainKey;
453  }
454  return Domain;
455  }
456  }
457 
461  [global::__DynamicallyInvokable]
462  public int Version
463  {
464  [global::__DynamicallyInvokable]
465  get
466  {
467  return m_version;
468  }
469  [global::__DynamicallyInvokable]
470  set
471  {
472  if (value < 0)
473  {
474  throw new ArgumentOutOfRangeException("value");
475  }
476  m_version = value;
477  if (value > 0 && m_cookieVariant < CookieVariant.Rfc2109)
478  {
479  m_cookieVariant = CookieVariant.Rfc2109;
480  }
481  }
482  }
483 
484  private string _Version
485  {
486  get
487  {
488  if (Version != 0)
489  {
490  return "$Version=" + (IsQuotedVersion ? "\"" : string.Empty) + m_version.ToString(NumberFormatInfo.InvariantInfo) + (IsQuotedVersion ? "\"" : string.Empty);
491  }
492  return string.Empty;
493  }
494  }
495 
497  [global::__DynamicallyInvokable]
498  public Cookie()
499  {
500  }
501 
506  [global::__DynamicallyInvokable]
507  public Cookie(string name, string value)
508  {
509  Name = name;
510  m_value = value;
511  }
512 
518  [global::__DynamicallyInvokable]
519  public Cookie(string name, string value, string path)
520  : this(name, value)
521  {
522  Path = path;
523  }
524 
531  [global::__DynamicallyInvokable]
532  public Cookie(string name, string value, string path, string domain)
533  : this(name, value, path)
534  {
535  Domain = domain;
536  }
537 
538  internal bool InternalSetName(string value)
539  {
540  if (ValidationHelper.IsBlankString(value) || value[0] == '$' || value.IndexOfAny(Reserved2Name) != -1)
541  {
542  m_name = string.Empty;
543  return false;
544  }
545  m_name = value;
546  return true;
547  }
548 
549  internal Cookie Clone()
550  {
551  Cookie cookie = new Cookie(m_name, m_value);
552  if (!m_port_implicit)
553  {
554  cookie.Port = m_port;
555  }
556  if (!m_path_implicit)
557  {
558  cookie.Path = m_path;
559  }
560  cookie.Domain = m_domain;
561  cookie.DomainImplicit = m_domain_implicit;
562  cookie.m_timeStamp = m_timeStamp;
563  cookie.Comment = m_comment;
564  cookie.CommentUri = m_commentUri;
565  cookie.HttpOnly = m_httpOnly;
566  cookie.Discard = m_discard;
567  cookie.Expires = m_expires;
568  cookie.Version = m_version;
569  cookie.Secure = m_secure;
570  cookie.m_cookieVariant = m_cookieVariant;
571  return cookie;
572  }
573 
574  private static bool IsDomainEqualToHost(string domain, string host)
575  {
576  if (host.Length + 1 == domain.Length && string.Compare(host, 0, domain, 1, host.Length, StringComparison.OrdinalIgnoreCase) == 0)
577  {
578  return true;
579  }
580  return false;
581  }
582 
583  internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDomain, string localDomain, bool set_default, bool isThrow)
584  {
585  string host = uri.Host;
586  int port = uri.Port;
587  string absolutePath = uri.AbsolutePath;
588  bool flag = true;
589  if (set_default)
590  {
591  if (Version == 0)
592  {
593  variant = CookieVariant.Plain;
594  }
595  else if (Version == 1 && variant == CookieVariant.Unknown)
596  {
597  variant = CookieVariant.Rfc2109;
598  }
599  m_cookieVariant = variant;
600  }
601  if (m_name == null || m_name.Length == 0 || m_name[0] == '$' || m_name.IndexOfAny(Reserved2Name) != -1)
602  {
603  if (isThrow)
604  {
605  throw new CookieException(SR.GetString("net_cookie_attribute", "Name", (m_name == null) ? "<null>" : m_name));
606  }
607  return false;
608  }
609  if (m_value == null || ((m_value.Length <= 2 || m_value[0] != '"' || m_value[m_value.Length - 1] != '"') && m_value.IndexOfAny(Reserved2Value) != -1))
610  {
611  if (isThrow)
612  {
613  throw new CookieException(SR.GetString("net_cookie_attribute", "Value", (m_value == null) ? "<null>" : m_value));
614  }
615  return false;
616  }
617  if (Comment != null && (Comment.Length <= 2 || Comment[0] != '"' || Comment[Comment.Length - 1] != '"') && Comment.IndexOfAny(Reserved2Value) != -1)
618  {
619  if (isThrow)
620  {
621  throw new CookieException(SR.GetString("net_cookie_attribute", "Comment", Comment));
622  }
623  return false;
624  }
625  if (Path != null && (Path.Length <= 2 || Path[0] != '"' || Path[Path.Length - 1] != '"') && Path.IndexOfAny(Reserved2Value) != -1)
626  {
627  if (isThrow)
628  {
629  throw new CookieException(SR.GetString("net_cookie_attribute", "Path", Path));
630  }
631  return false;
632  }
633  if (set_default && m_domain_implicit)
634  {
635  m_domain = host;
636  }
637  else
638  {
639  if (!m_domain_implicit)
640  {
641  string text = m_domain;
642  if (!DomainCharsTest(text))
643  {
644  if (isThrow)
645  {
646  throw new CookieException(SR.GetString("net_cookie_attribute", "Domain", (text == null) ? "<null>" : text));
647  }
648  return false;
649  }
650  if (text[0] != '.')
651  {
652  if (variant != CookieVariant.Rfc2965 && variant != CookieVariant.Plain)
653  {
654  if (isThrow)
655  {
656  throw new CookieException(SR.GetString("net_cookie_attribute", "Domain", m_domain));
657  }
658  return false;
659  }
660  text = "." + text;
661  }
662  int num = host.IndexOf('.');
663  if (isLocalDomain && string.Compare(localDomain, text, StringComparison.OrdinalIgnoreCase) == 0)
664  {
665  flag = true;
666  }
667  else if (text.IndexOf('.', 1, text.Length - 2) == -1)
668  {
669  if (!IsDomainEqualToHost(text, host))
670  {
671  flag = false;
672  }
673  }
674  else if (variant == CookieVariant.Plain)
675  {
676  if (!IsDomainEqualToHost(text, host) && (host.Length <= text.Length || string.Compare(host, host.Length - text.Length, text, 0, text.Length, StringComparison.OrdinalIgnoreCase) != 0))
677  {
678  flag = false;
679  }
680  }
681  else if ((num == -1 || text.Length != host.Length - num || string.Compare(host, num, text, 0, text.Length, StringComparison.OrdinalIgnoreCase) != 0) && !IsDomainEqualToHost(text, host))
682  {
683  flag = false;
684  }
685  if (flag)
686  {
687  m_domainKey = text.ToLower(CultureInfo.InvariantCulture);
688  }
689  }
690  else if (string.Compare(host, m_domain, StringComparison.OrdinalIgnoreCase) != 0)
691  {
692  flag = false;
693  }
694  if (!flag)
695  {
696  if (isThrow)
697  {
698  throw new CookieException(SR.GetString("net_cookie_attribute", "Domain", m_domain));
699  }
700  return false;
701  }
702  }
703  if (set_default && m_path_implicit)
704  {
705  switch (m_cookieVariant)
706  {
707  case CookieVariant.Plain:
708  m_path = absolutePath;
709  break;
710  case CookieVariant.Rfc2109:
711  m_path = absolutePath.Substring(0, absolutePath.LastIndexOf('/'));
712  break;
713  default:
714  m_path = absolutePath.Substring(0, absolutePath.LastIndexOf('/') + 1);
715  break;
716  }
717  }
718  else if (!absolutePath.StartsWith(CookieParser.CheckQuoted(m_path)))
719  {
720  if (isThrow)
721  {
722  throw new CookieException(SR.GetString("net_cookie_attribute", "Path", m_path));
723  }
724  return false;
725  }
726  if (set_default && !m_port_implicit && m_port.Length == 0)
727  {
728  m_port_list = new int[1]
729  {
730  port
731  };
732  }
733  if (!m_port_implicit)
734  {
735  flag = false;
736  int[] port_list = m_port_list;
737  foreach (int num2 in port_list)
738  {
739  if (num2 == port)
740  {
741  flag = true;
742  break;
743  }
744  }
745  if (!flag)
746  {
747  if (isThrow)
748  {
749  throw new CookieException(SR.GetString("net_cookie_attribute", "Port", m_port));
750  }
751  return false;
752  }
753  }
754  return true;
755  }
756 
757  private static bool DomainCharsTest(string name)
758  {
759  if (name == null || name.Length == 0)
760  {
761  return false;
762  }
763  foreach (char c in name)
764  {
765  if (c >= '0' && c <= '9')
766  {
767  continue;
768  }
769  switch (c)
770  {
771  case '-':
772  case '.':
773  case 'a':
774  case 'b':
775  case 'c':
776  case 'd':
777  case 'e':
778  case 'f':
779  case 'g':
780  case 'h':
781  case 'i':
782  case 'j':
783  case 'k':
784  case 'l':
785  case 'm':
786  case 'n':
787  case 'o':
788  case 'p':
789  case 'q':
790  case 'r':
791  case 's':
792  case 't':
793  case 'u':
794  case 'v':
795  case 'w':
796  case 'x':
797  case 'y':
798  case 'z':
799  continue;
800  }
801  if ((c < 'A' || c > 'Z') && c != '_')
802  {
803  return false;
804  }
805  }
806  return true;
807  }
808 
809  internal static IComparer GetComparer()
810  {
811  return staticComparer;
812  }
813 
817  [global::__DynamicallyInvokable]
818  public override bool Equals(object comparand)
819  {
820  if (!(comparand is Cookie))
821  {
822  return false;
823  }
824  Cookie cookie = (Cookie)comparand;
825  if (string.Compare(Name, cookie.Name, StringComparison.OrdinalIgnoreCase) == 0 && string.Compare(Value, cookie.Value, StringComparison.Ordinal) == 0 && string.Compare(Path, cookie.Path, StringComparison.Ordinal) == 0 && string.Compare(Domain, cookie.Domain, StringComparison.OrdinalIgnoreCase) == 0)
826  {
827  return Version == cookie.Version;
828  }
829  return false;
830  }
831 
834  [global::__DynamicallyInvokable]
835  public override int GetHashCode()
836  {
837  return (Name + "=" + Value + ";" + Path + "; " + Domain + "; " + Version).GetHashCode();
838  }
839 
842  [global::__DynamicallyInvokable]
843  public override string ToString()
844  {
845  string domain = _Domain;
846  string path = _Path;
847  string port = _Port;
848  string version = _Version;
849  string text = ((version.Length == 0) ? string.Empty : (version + "; ")) + Name + "=" + Value + ((path.Length == 0) ? string.Empty : ("; " + path)) + ((domain.Length == 0) ? string.Empty : ("; " + domain)) + ((port.Length == 0) ? string.Empty : ("; " + port));
850  if (text == "=")
851  {
852  return string.Empty;
853  }
854  return text;
855  }
856 
857  internal string ToServerString()
858  {
859  string text = Name + "=" + Value;
860  if (m_comment != null && m_comment.Length > 0)
861  {
862  text = text + "; Comment=" + m_comment;
863  }
864  if (m_commentUri != null)
865  {
866  text = text + "; CommentURL=\"" + m_commentUri.ToString() + "\"";
867  }
868  if (m_discard)
869  {
870  text += "; Discard";
871  }
872  if (!m_domain_implicit && m_domain != null && m_domain.Length > 0)
873  {
874  text = text + "; Domain=" + m_domain;
875  }
876  if (Expires != DateTime.MinValue)
877  {
878  int num = (int)(Expires.ToLocalTime() - DateTime.Now).TotalSeconds;
879  if (num < 0)
880  {
881  num = 0;
882  }
883  text = text + "; Max-Age=" + num.ToString(NumberFormatInfo.InvariantInfo);
884  }
885  if (!m_path_implicit && m_path != null && m_path.Length > 0)
886  {
887  text = text + "; Path=" + m_path;
888  }
889  if (!Plain && !m_port_implicit && m_port != null && m_port.Length > 0)
890  {
891  text = text + "; Port=" + m_port;
892  }
893  if (m_version > 0)
894  {
895  text = text + "; Version=" + m_version.ToString(NumberFormatInfo.InvariantInfo);
896  }
897  if (!(text == "="))
898  {
899  return text;
900  }
901  return null;
902  }
903  }
904 }
static CultureInfo InvariantCulture
Gets the T:System.Globalization.CultureInfo object that is culture-independent (invariant).
Definition: CultureInfo.cs:263
StringComparison
Specifies the culture, case, and sort rules to be used by certain overloads of the M:System....
static readonly DateTime MinValue
Represents the smallest possible value of T:System.DateTime. This field is read-only.
Definition: DateTime.cs:109
Definition: __Canon.cs:3
The exception that is thrown when the value of an argument is outside the allowable range of values a...
Represents an instant in time, typically expressed as a date and time of day. To browse the ....
Definition: DateTime.cs:13
A type representing a date and time value.
DateTime ToLocalTime()
Converts the value of the current T:System.DateTime object to local time.
Definition: DateTime.cs:1460
Exposes a method that compares two objects.
Definition: IComparer.cs:8
Represents the version number of an assembly, operating system, or the common language runtime....
Definition: Version.cs:11
Specifies that the class can be serialized.
static DateTime Now
Gets a T:System.DateTime object that is set to the current date and time on this computer,...
Definition: DateTime.cs:264
Provides information about a specific culture (called a locale for unmanaged code development)....
Definition: CultureInfo.cs:16
Provides an object representation of a uniform resource identifier (URI) and easy access to the parts...
Definition: Uri.cs:19
override string ToString()
Gets a canonical string representation for the specified T:System.Uri instance.
Definition: Uri.cs:1663
static NumberFormatInfo InvariantInfo
Gets a read-only T:System.Globalization.NumberFormatInfo object that is culture-independent (invarian...
Provides culture-specific information for formatting and parsing numeric values.