| // | 
| // WebHeaderCollection.cs | 
| //    Copied from System.Net.WebHeaderCollection | 
| // | 
| // Authors: | 
| //    Lawrence Pit (loz@cable.a2000.nl) | 
| //    Gonzalo Paniagua Javier (gonzalo@ximian.com) | 
| //    Miguel de Icaza (miguel@novell.com) | 
| // | 
| // Copyright 2003 Ximian, Inc. (http://www.ximian.com) | 
| // Copyright 2007 Novell, Inc. (http://www.novell.com) | 
| // | 
| // Permission is hereby granted, free of charge, to any person obtaining | 
| // a copy of this software and associated documentation files (the | 
| // "Software"), to deal in the Software without restriction, including | 
| // without limitation the rights to use, copy, modify, merge, publish, | 
| // distribute, sublicense, and/or sell copies of the Software, and to | 
| // permit persons to whom the Software is furnished to do so, subject to | 
| // the following conditions: | 
| //  | 
| // The above copyright notice and this permission notice shall be | 
| // included in all copies or substantial portions of the Software. | 
| //  | 
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | 
| // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | 
| // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 
| // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | 
| // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | 
| // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | 
| // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 
| // | 
|   | 
| using System; | 
| using System.Collections; | 
| using System.Collections.Generic; | 
| using System.Collections.Specialized; | 
| using System.Net; | 
| using System.Runtime.InteropServices; | 
| using System.Runtime.Serialization; | 
| using System.Text; | 
|      | 
| // See RFC 2068 par 4.2 Message Headers | 
|      | 
| namespace WebSocketSharp.Net { | 
|   | 
|     [Serializable] | 
|     [ComVisible(true)] | 
|     public class WebHeaderCollection : NameValueCollection, ISerializable | 
|     { | 
|         private static readonly Dictionary<string, bool> multiValue; | 
|         private static readonly Dictionary<string, bool> restricted; | 
|         private static readonly Dictionary<string, bool> restricted_response; | 
|   | 
|         private bool internallyCreated = false; | 
|          | 
|         // Static Initializer | 
|          | 
|         static WebHeaderCollection ()  | 
|         { | 
|             // the list of restricted header names as defined  | 
|             // by the ms.net spec | 
|             restricted = new Dictionary<string, bool> (StringComparer.InvariantCultureIgnoreCase); | 
|             restricted.Add ("accept", true); | 
|             restricted.Add ("connection", true); | 
|             restricted.Add ("content-length", true); | 
|             restricted.Add ("content-type", true); | 
|             restricted.Add ("date", true); | 
|             restricted.Add ("expect", true); | 
|             restricted.Add ("host", true); | 
|             restricted.Add ("if-modified-since", true); | 
|             restricted.Add ("range", true); | 
|             restricted.Add ("referer", true); | 
|             restricted.Add ("transfer-encoding", true); | 
|             restricted.Add ("user-agent", true); | 
|             restricted.Add ("proxy-connection", true); | 
|   | 
|             // | 
|             restricted_response = new Dictionary<string, bool> (StringComparer.InvariantCultureIgnoreCase); | 
|             restricted_response.Add ("Content-Length", true); | 
|             restricted_response.Add ("Transfer-Encoding", true); | 
|             restricted_response.Add ("WWW-Authenticate", true); | 
|   | 
|             // see par 14 of RFC 2068 to see which header names | 
|             // accept multiple values each separated by a comma | 
|             multiValue = new Dictionary<string, bool> (StringComparer.InvariantCultureIgnoreCase); | 
|             multiValue.Add ("accept", true); | 
|             multiValue.Add ("accept-charset", true); | 
|             multiValue.Add ("accept-encoding", true); | 
|             multiValue.Add ("accept-language", true); | 
|             multiValue.Add ("accept-ranges", true); | 
|             multiValue.Add ("allow", true); | 
|             multiValue.Add ("authorization", true); | 
|             multiValue.Add ("cache-control", true); | 
|             multiValue.Add ("connection", true); | 
|             multiValue.Add ("content-encoding", true); | 
|             multiValue.Add ("content-language", true);             | 
|             multiValue.Add ("expect", true);         | 
|             multiValue.Add ("if-match", true); | 
|             multiValue.Add ("if-none-match", true); | 
|             multiValue.Add ("proxy-authenticate", true); | 
|             multiValue.Add ("public", true);             | 
|             multiValue.Add ("range", true); | 
|             multiValue.Add ("transfer-encoding", true); | 
|             multiValue.Add ("upgrade", true); | 
|             multiValue.Add ("vary", true); | 
|             multiValue.Add ("via", true); | 
|             multiValue.Add ("warning", true); | 
|             multiValue.Add ("www-authenticate", true); | 
|   | 
|             // Extra | 
|             multiValue.Add ("set-cookie", true); | 
|             multiValue.Add ("set-cookie2", true); | 
|         } | 
|          | 
|         // Constructors | 
|   | 
|         public WebHeaderCollection () { } | 
|   | 
|         protected WebHeaderCollection ( | 
|             SerializationInfo serializationInfo,  | 
|             StreamingContext streamingContext) | 
|         { | 
|             int count; | 
|   | 
|             try { | 
|                 count = serializationInfo.GetInt32("Count"); | 
|                 for (int i = 0; i < count; i++)  | 
|                     this.Add (serializationInfo.GetString (i.ToString ()), | 
|                           serializationInfo.GetString ((count + i).ToString ())); | 
|             } catch (SerializationException){ | 
|                 count = serializationInfo.GetInt32("count"); | 
|                 for (int i = 0; i < count; i++)  | 
|                     this.Add (serializationInfo.GetString ("k" + i), | 
|                           serializationInfo.GetString ("v" + i)); | 
|             } | 
|              | 
|         } | 
|          | 
|         internal WebHeaderCollection (bool internallyCreated) | 
|         { | 
|             this.internallyCreated = internallyCreated; | 
|         } | 
|   | 
|         // Methods | 
|          | 
|         public void Add (string header) | 
|         { | 
|             if (header == null) | 
|                 throw new ArgumentNullException ("header"); | 
|             int pos = header.IndexOf (':'); | 
|             if (pos == -1) | 
|                 throw new ArgumentException ("no colon found", "header"); | 
|             this.Add (header.Substring (0, pos),  | 
|                   header.Substring (pos + 1)); | 
|         } | 
|          | 
|         public override void Add (string name, string value) | 
|         { | 
|             if (name == null) | 
|                 throw new ArgumentNullException ("name"); | 
|             if (internallyCreated && IsRestricted (name)) | 
|                 throw new ArgumentException ("This header must be modified with the appropiate property."); | 
|             this.AddWithoutValidate (name, value); | 
|         } | 
|   | 
|         protected void AddWithoutValidate (string headerName, string headerValue) | 
|         { | 
|             if (!IsHeaderName (headerName)) | 
|                 throw new ArgumentException ("invalid header name: " + headerName, "headerName"); | 
|             if (headerValue == null) | 
|                 headerValue = String.Empty; | 
|             else | 
|                 headerValue = headerValue.Trim (); | 
|             if (!IsHeaderValue (headerValue)) | 
|                 throw new ArgumentException ("invalid header value: " + headerValue, "headerValue"); | 
|             base.Add (headerName, headerValue);             | 
|         } | 
|   | 
|         public override string [] GetValues (string header) | 
|         { | 
|             if (header == null) | 
|                 throw new ArgumentNullException ("header"); | 
|   | 
|             string [] values = base.GetValues (header); | 
|             if (values == null || values.Length == 0) | 
|                 return null; | 
|   | 
|             /* | 
|             if (IsMultiValue (header)) { | 
|                 values = GetMultipleValues (values); | 
|             } | 
|             */ | 
|   | 
|             return values; | 
|         } | 
|   | 
|         public override string[] GetValues (int index) | 
|         { | 
|             string[] values = base.GetValues (index); | 
|             if (values == null || values.Length == 0) { | 
|                 return(null); | 
|             } | 
|              | 
|             return(values); | 
|         } | 
|   | 
|         /* Now i wonder why this is here... | 
|         static string [] GetMultipleValues (string [] values) | 
|         { | 
|             ArrayList mvalues = new ArrayList (values.Length); | 
|             StringBuilder sb = null; | 
|             for (int i = 0; i < values.Length; ++i) { | 
|                 string val = values [i]; | 
|                 if (val.IndexOf (',') == -1) { | 
|                     mvalues.Add (val); | 
|                     continue; | 
|                 } | 
|   | 
|                 if (sb == null) | 
|                     sb = new StringBuilder (); | 
|   | 
|                 bool quote = false; | 
|                 for (int k = 0; k < val.Length; k++) { | 
|                     char c = val [k]; | 
|                     if (c == '"') { | 
|                         quote = !quote; | 
|                     } else if (!quote && c == ',') { | 
|                         mvalues.Add (sb.ToString ().Trim ()); | 
|                         sb.Length = 0; | 
|                         continue; | 
|                     } | 
|                     sb.Append (c); | 
|                 } | 
|   | 
|                 if (sb.Length > 0) { | 
|                     mvalues.Add (sb.ToString ().Trim ()); | 
|                     sb.Length = 0; | 
|                 } | 
|             } | 
|   | 
|             return (string []) mvalues.ToArray (typeof (string)); | 
|         } | 
|         */ | 
|   | 
|         public static bool IsRestricted (string headerName) | 
|         { | 
|             if (headerName == null) | 
|                 throw new ArgumentNullException ("headerName"); | 
|   | 
|             if (headerName == "") // MS throw nullexception here! | 
|                 throw new ArgumentException ("empty string", "headerName"); | 
|   | 
|             if (!IsHeaderName (headerName)) | 
|                 throw new ArgumentException ("Invalid character in header"); | 
|   | 
|             return restricted.ContainsKey (headerName); | 
|         } | 
|   | 
|         public static bool IsRestricted (string headerName, bool response) | 
|         { | 
|             if (String.IsNullOrEmpty (headerName)) | 
|                 throw new ArgumentNullException ("headerName"); | 
|   | 
|             if (!IsHeaderName (headerName)) | 
|                 throw new ArgumentException ("Invalid character in header"); | 
|   | 
|   | 
|             if (response) | 
|                 return restricted_response.ContainsKey (headerName); | 
|             return restricted.ContainsKey (headerName); | 
|         } | 
|   | 
|         public override void OnDeserialization (object sender) | 
|         { | 
|         } | 
|   | 
|         public override void Remove (string name) | 
|         { | 
|             if (name == null) | 
|                 throw new ArgumentNullException ("name"); | 
|             if (internallyCreated && IsRestricted (name)) | 
|                 throw new ArgumentException ("restricted header"); | 
|             base.Remove (name); | 
|         } | 
|   | 
|         public override void Set (string name, string value) | 
|         { | 
|             if (name == null) | 
|                 throw new ArgumentNullException ("name"); | 
|             if (internallyCreated && IsRestricted (name)) | 
|                 throw new ArgumentException ("restricted header"); | 
|             if (!IsHeaderName (name)) | 
|                 throw new ArgumentException ("invalid header name"); | 
|             if (value == null) | 
|                 value = String.Empty; | 
|             else | 
|                 value = value.Trim (); | 
|             if (!IsHeaderValue (value)) | 
|                 throw new ArgumentException ("invalid header value"); | 
|             base.Set (name, value);             | 
|         } | 
|   | 
|         public byte[] ToByteArray () | 
|         { | 
|             return Encoding.UTF8.GetBytes(ToString ()); | 
|         } | 
|   | 
|         internal string ToStringMultiValue () | 
|         { | 
|             StringBuilder sb = new StringBuilder(); | 
|   | 
|             int count = base.Count; | 
|             for (int i = 0; i < count ; i++) { | 
|                 string key = GetKey (i); | 
|                 if (IsMultiValue (key)) { | 
|                     foreach (string v in GetValues (i)) { | 
|                         sb.Append (key) | 
|                           .Append (": ") | 
|                           .Append (v) | 
|                           .Append ("\r\n"); | 
|                     } | 
|                 } else { | 
|                     sb.Append (key) | 
|                       .Append (": ") | 
|                       .Append (Get (i)) | 
|                       .Append ("\r\n"); | 
|                 } | 
|              } | 
|             return sb.Append("\r\n").ToString(); | 
|         } | 
|   | 
|         public override string ToString () | 
|         { | 
|             StringBuilder sb = new StringBuilder(); | 
|   | 
|             int count = base.Count; | 
|             for (int i = 0; i < count ; i++) | 
|                 sb.Append (GetKey (i)) | 
|                   .Append (": ") | 
|                   .Append (Get (i)) | 
|                   .Append ("\r\n"); | 
|   | 
|             return sb.Append("\r\n").ToString(); | 
|         } | 
|   | 
|         void ISerializable.GetObjectData ( | 
|             SerializationInfo serializationInfo, | 
|             StreamingContext streamingContext) | 
|         { | 
|             GetObjectData (serializationInfo, streamingContext); | 
|         } | 
|   | 
|         public override void GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext) | 
|         { | 
|             int count = base.Count; | 
|             serializationInfo.AddValue ("Count", count); | 
|             for (int i = 0; i < count; i++) { | 
|                 serializationInfo.AddValue (i.ToString (), GetKey (i)); | 
|                 serializationInfo.AddValue ((count + i).ToString (), Get (i)); | 
|             } | 
|         } | 
|   | 
|         public override string[] AllKeys | 
|         { | 
|             get { | 
|                 return(base.AllKeys); | 
|             } | 
|         } | 
|          | 
|         public override int Count  | 
|         { | 
|             get { | 
|                 return(base.Count); | 
|             } | 
|         } | 
|   | 
|         public override KeysCollection Keys | 
|         { | 
|             get { | 
|                 return(base.Keys); | 
|             } | 
|         } | 
|   | 
|         public override string Get (int index) | 
|         { | 
|             return(base.Get (index)); | 
|         } | 
|          | 
|         public override string Get (string name) | 
|         { | 
|             return(base.Get (name)); | 
|         } | 
|          | 
|         public override string GetKey (int index) | 
|         { | 
|             return(base.GetKey (index)); | 
|         } | 
|   | 
|         public void Add (HttpRequestHeader header, string value) | 
|         { | 
|             Add (RequestHeaderToString (header), value); | 
|         } | 
|   | 
|         public void Remove (HttpRequestHeader header) | 
|         { | 
|             Remove (RequestHeaderToString (header)); | 
|         } | 
|   | 
|         public void Set (HttpRequestHeader header, string value) | 
|         { | 
|             Set (RequestHeaderToString (header), value); | 
|         } | 
|   | 
|         public void Add (HttpResponseHeader header, string value) | 
|         { | 
|             Add (ResponseHeaderToString (header), value); | 
|         } | 
|   | 
|         public void Remove (HttpResponseHeader header) | 
|         { | 
|             Remove (ResponseHeaderToString (header)); | 
|         } | 
|   | 
|         public void Set (HttpResponseHeader header, string value) | 
|         { | 
|             Set (ResponseHeaderToString (header), value); | 
|         } | 
|   | 
|         string RequestHeaderToString (HttpRequestHeader value) | 
|         { | 
|             switch (value){ | 
|             case HttpRequestHeader.CacheControl: | 
|                 return "Cache-Control"; | 
|             case HttpRequestHeader.Connection: | 
|                 return "Connection"; | 
|             case HttpRequestHeader.Date: | 
|                 return "Date"; | 
|             case HttpRequestHeader.KeepAlive: | 
|                 return "Keep-Alive"; | 
|             case HttpRequestHeader.Pragma: | 
|                 return "Pragma"; | 
|             case HttpRequestHeader.Trailer: | 
|                 return "Trailer"; | 
|             case HttpRequestHeader.TransferEncoding: | 
|                 return "Transfer-Encoding"; | 
|             case HttpRequestHeader.Upgrade: | 
|                 return "Upgrade"; | 
|             case HttpRequestHeader.Via: | 
|                 return "Via"; | 
|             case HttpRequestHeader.Warning: | 
|                 return "Warning"; | 
|             case HttpRequestHeader.Allow: | 
|                 return "Allow"; | 
|             case HttpRequestHeader.ContentLength: | 
|                 return "Content-Length"; | 
|             case HttpRequestHeader.ContentType: | 
|                 return "Content-Type"; | 
|             case HttpRequestHeader.ContentEncoding: | 
|                 return "Content-Encoding"; | 
|             case HttpRequestHeader.ContentLanguage: | 
|                 return "Content-Language"; | 
|             case HttpRequestHeader.ContentLocation: | 
|                 return "Content-Location"; | 
|             case HttpRequestHeader.ContentMd5: | 
|                 return "Content-MD5"; | 
|             case HttpRequestHeader.ContentRange: | 
|                 return "Content-Range"; | 
|             case HttpRequestHeader.Expires: | 
|                 return "Expires"; | 
|             case HttpRequestHeader.LastModified: | 
|                 return "Last-Modified"; | 
|             case HttpRequestHeader.Accept: | 
|                 return "Accept"; | 
|             case HttpRequestHeader.AcceptCharset: | 
|                 return "Accept-Charset"; | 
|             case HttpRequestHeader.AcceptEncoding: | 
|                 return "Accept-Encoding"; | 
|             case HttpRequestHeader.AcceptLanguage: | 
|                 return "accept-language"; | 
|             case HttpRequestHeader.Authorization: | 
|                 return "Authorization"; | 
|             case HttpRequestHeader.Cookie: | 
|                 return "Cookie"; | 
|             case HttpRequestHeader.Expect: | 
|                 return "Expect"; | 
|             case HttpRequestHeader.From: | 
|                 return "From"; | 
|             case HttpRequestHeader.Host: | 
|                 return "Host"; | 
|             case HttpRequestHeader.IfMatch: | 
|                 return "If-Match"; | 
|             case HttpRequestHeader.IfModifiedSince: | 
|                 return "If-Modified-Since"; | 
|             case HttpRequestHeader.IfNoneMatch: | 
|                 return "If-None-Match"; | 
|             case HttpRequestHeader.IfRange: | 
|                 return "If-Range"; | 
|             case HttpRequestHeader.IfUnmodifiedSince: | 
|                 return "If-Unmodified-Since"; | 
|             case HttpRequestHeader.MaxForwards: | 
|                 return "Max-Forwards"; | 
|             case HttpRequestHeader.ProxyAuthorization: | 
|                 return "Proxy-Authorization"; | 
|             case HttpRequestHeader.Referer: | 
|                 return "Referer"; | 
|             case HttpRequestHeader.Range: | 
|                 return "Range"; | 
|             case HttpRequestHeader.Te: | 
|                 return "TE"; | 
|             case HttpRequestHeader.Translate: | 
|                 return "Translate"; | 
|             case HttpRequestHeader.UserAgent: | 
|                 return "User-Agent"; | 
|             default: | 
|                 throw new InvalidOperationException (); | 
|             } | 
|         } | 
|          | 
|          | 
|         public string this[HttpRequestHeader hrh] | 
|         { | 
|             get { | 
|                 return Get (RequestHeaderToString (hrh)); | 
|             } | 
|              | 
|             set { | 
|                 Add (RequestHeaderToString (hrh), value); | 
|             } | 
|         } | 
|   | 
|         string ResponseHeaderToString (HttpResponseHeader value) | 
|         { | 
|             switch (value){ | 
|             case HttpResponseHeader.CacheControl: | 
|                 return "Cache-Control"; | 
|             case HttpResponseHeader.Connection: | 
|                 return "Connection"; | 
|             case HttpResponseHeader.Date: | 
|                 return "Date"; | 
|             case HttpResponseHeader.KeepAlive: | 
|                 return "Keep-Alive"; | 
|             case HttpResponseHeader.Pragma: | 
|                 return "Pragma"; | 
|             case HttpResponseHeader.Trailer: | 
|                 return "Trailer"; | 
|             case HttpResponseHeader.TransferEncoding: | 
|                 return "Transfer-Encoding"; | 
|             case HttpResponseHeader.Upgrade: | 
|                 return "Upgrade"; | 
|             case HttpResponseHeader.Via: | 
|                 return "Via"; | 
|             case HttpResponseHeader.Warning: | 
|                 return "Warning"; | 
|             case HttpResponseHeader.Allow: | 
|                 return "Allow"; | 
|             case HttpResponseHeader.ContentLength: | 
|                 return "Content-Length"; | 
|             case HttpResponseHeader.ContentType: | 
|                 return "Content-Type"; | 
|             case HttpResponseHeader.ContentEncoding: | 
|                 return "Content-Encoding"; | 
|             case HttpResponseHeader.ContentLanguage: | 
|                 return "Content-Language"; | 
|             case HttpResponseHeader.ContentLocation: | 
|                 return "Content-Location"; | 
|             case HttpResponseHeader.ContentMd5: | 
|                 return "Content-MD5"; | 
|             case HttpResponseHeader.ContentRange: | 
|                 return "Content-Range"; | 
|             case HttpResponseHeader.Expires: | 
|                 return "Expires"; | 
|             case HttpResponseHeader.LastModified: | 
|                 return "Last-Modified"; | 
|             case HttpResponseHeader.AcceptRanges: | 
|                 return "Accept-Ranges"; | 
|             case HttpResponseHeader.Age: | 
|                 return "Age"; | 
|             case HttpResponseHeader.ETag: | 
|                 return "ETag"; | 
|             case HttpResponseHeader.Location: | 
|                 return "Location"; | 
|             case HttpResponseHeader.ProxyAuthenticate: | 
|                 return "Proxy-Authenticate"; | 
|             case HttpResponseHeader.RetryAfter: | 
|                 return "Retry-After"; | 
|             case HttpResponseHeader.Server: | 
|                 return "Server"; | 
|             case HttpResponseHeader.SetCookie: | 
|                 return "Set-Cookie"; | 
|             case HttpResponseHeader.Vary: | 
|                 return "Vary"; | 
|             case HttpResponseHeader.WwwAuthenticate: | 
|                 return "WWW-Authenticate"; | 
|             default: | 
|                 throw new InvalidOperationException (); | 
|             } | 
|         } | 
|   | 
|         public string this[HttpResponseHeader hrh] | 
|         { | 
|             get | 
|             { | 
|                 return Get (ResponseHeaderToString (hrh)); | 
|             } | 
|   | 
|             set | 
|             { | 
|                 Add (ResponseHeaderToString (hrh), value); | 
|             } | 
|         } | 
|   | 
|         public override void Clear () | 
|         { | 
|             base.Clear (); | 
|         } | 
|   | 
|         public override IEnumerator GetEnumerator () | 
|         { | 
|             return(base.GetEnumerator ()); | 
|         } | 
|   | 
|         // Internal Methods | 
|          | 
|         // With this we don't check for invalid characters in header. See bug #55994. | 
|         internal void SetInternal (string header) | 
|         { | 
|             int pos = header.IndexOf (':'); | 
|             if (pos == -1) | 
|                 throw new ArgumentException ("no colon found", "header");                 | 
|   | 
|             SetInternal (header.Substring (0, pos), header.Substring (pos + 1)); | 
|         } | 
|   | 
|         internal void SetInternal (string name, string value) | 
|         { | 
|             if (value == null) | 
|                 value = String.Empty; | 
|             else | 
|                 value = value.Trim (); | 
|             if (!IsHeaderValue (value)) | 
|                 throw new ArgumentException ("invalid header value"); | 
|   | 
|             if (IsMultiValue (name)) { | 
|                 base.Add (name, value); | 
|             } else { | 
|                 base.Remove (name); | 
|                 base.Set (name, value);     | 
|             } | 
|         } | 
|   | 
|         internal void RemoveAndAdd (string name, string value) | 
|         { | 
|             if (value == null) | 
|                 value = String.Empty; | 
|             else | 
|                 value = value.Trim (); | 
|   | 
|             base.Remove (name); | 
|             base.Set (name, value); | 
|         } | 
|   | 
|         internal void RemoveInternal (string name) | 
|         { | 
|             if (name == null) | 
|                 throw new ArgumentNullException ("name"); | 
|             base.Remove (name); | 
|         }         | 
|          | 
|         // Private Methods | 
|          | 
|         internal static bool IsMultiValue (string headerName) | 
|         { | 
|             if (headerName == null || headerName == "") | 
|                 return false; | 
|   | 
|             return multiValue.ContainsKey (headerName); | 
|         }         | 
|          | 
|         internal static bool IsHeaderValue (string value) | 
|         { | 
|             // TEXT any 8 bit value except CTL's (0-31 and 127) | 
|             //      but including \r\n space and \t | 
|             //      after a newline at least one space or \t must follow | 
|             //      certain header fields allow comments () | 
|                  | 
|             int len = value.Length; | 
|             for (int i = 0; i < len; i++) {             | 
|                 char c = value [i]; | 
|                 if (c == 127) | 
|                     return false; | 
|                 if (c < 0x20 && (c != '\r' && c != '\n' && c != '\t')) | 
|                     return false; | 
|                 if (c == '\n' && ++i < len) { | 
|                     c = value [i]; | 
|                     if (c != ' ' && c != '\t') | 
|                         return false; | 
|                 } | 
|             } | 
|              | 
|             return true; | 
|         } | 
|          | 
|         internal static bool IsHeaderName (string name) | 
|         { | 
|             if (name == null || name.Length == 0) | 
|                 return false; | 
|   | 
|             int len = name.Length; | 
|             for (int i = 0; i < len; i++) {             | 
|                 char c = name [i]; | 
|                 if (c > 126 || !allowed_chars [(int) c]) | 
|                     return false; | 
|             } | 
|              | 
|             return true; | 
|         } | 
|   | 
|         static bool [] allowed_chars = new bool [126] { | 
|             false, false, false, false, false, false, false, false, false, false, false, false, false, false, | 
|             false, false, false, false, false, false, false, false, false, false, false, false, false, false, | 
|             false, false, false, false, false, true, false, true, true, true, true, false, false, false, true, | 
|             true, false, true, true, false, true, true, true, true, true, true, true, true, true, true, false, | 
|             false, false, false, false, false, false, true, true, true, true, true, true, true, true, true, | 
|             true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, | 
|             false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, | 
|             true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, | 
|             false, true, false | 
|             }; | 
|     } | 
| } |