WebHeaderCollection.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. //
  2. // System.Net.WebHeaderCollection
  3. //
  4. // Authors:
  5. // Lawrence Pit ([email protected])
  6. // Gonzalo Paniagua Javier ([email protected])
  7. // Miguel de Icaza ([email protected])
  8. // Marek Safar ([email protected])
  9. //
  10. // Copyright 2003 Ximian, Inc. (http://www.ximian.com)
  11. // Copyright 2007 Novell, Inc. (http://www.novell.com)
  12. // Copyright (C) 2011 Xamarin Inc (http://www.xamarin.com)
  13. //
  14. //
  15. // Permission is hereby granted, free of charge, to any person obtaining
  16. // a copy of this software and associated documentation files (the
  17. // "Software"), to deal in the Software without restriction, including
  18. // without limitation the rights to use, copy, modify, merge, publish,
  19. // distribute, sublicense, and/or sell copies of the Software, and to
  20. // permit persons to whom the Software is furnished to do so, subject to
  21. // the following conditions:
  22. //
  23. // The above copyright notice and this permission notice shall be
  24. // included in all copies or substantial portions of the Software.
  25. //
  26. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  27. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  28. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  29. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  30. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  31. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  32. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  33. //
  34. using System;
  35. using System.Collections;
  36. using System.Collections.Generic;
  37. using System.Collections.Specialized;
  38. using System.Runtime.InteropServices;
  39. using System.Runtime.Serialization;
  40. using System.Text;
  41. // See RFC 2068 par 4.2 Message Headers
  42. namespace System.Net
  43. {
  44. #if MOONLIGHT
  45. internal class WebHeaderCollection : NameValueCollection, ISerializable {
  46. #else
  47. [Serializable]
  48. [ComVisible(true)]
  49. public class WebHeaderCollection : NameValueCollection, ISerializable {
  50. #endif
  51. [Flags]
  52. internal enum HeaderInfo
  53. {
  54. Request = 1,
  55. Response = 1 << 1,
  56. MultiValue = 1 << 10
  57. }
  58. static readonly bool[] allowed_chars = {
  59. false, false, false, false, false, false, false, false, false, false, false, false, false, false,
  60. false, false, false, false, false, false, false, false, false, false, false, false, false, false,
  61. false, false, false, false, false, true, false, true, true, true, true, false, false, false, true,
  62. true, false, true, true, false, true, true, true, true, true, true, true, true, true, true, false,
  63. false, false, false, false, false, false, true, true, true, true, true, true, true, true, true,
  64. true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
  65. false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true,
  66. true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
  67. false, true, false
  68. };
  69. static readonly Dictionary<string, HeaderInfo> headers;
  70. HeaderInfo? headerRestriction;
  71. HeaderInfo? headerConsistency;
  72. static WebHeaderCollection ()
  73. {
  74. headers = new Dictionary<string, HeaderInfo> (StringComparer.OrdinalIgnoreCase) {
  75. { "Allow", HeaderInfo.MultiValue },
  76. { "Accept", HeaderInfo.Request | HeaderInfo.MultiValue },
  77. { "Accept-Charset", HeaderInfo.MultiValue },
  78. { "Accept-Encoding", HeaderInfo.MultiValue },
  79. { "Accept-Language", HeaderInfo.MultiValue },
  80. { "Accept-Ranges", HeaderInfo.MultiValue },
  81. { "Authorization", HeaderInfo.MultiValue },
  82. { "Cache-Control", HeaderInfo.MultiValue },
  83. { "Cookie", HeaderInfo.MultiValue },
  84. { "Connection", HeaderInfo.Request | HeaderInfo.MultiValue },
  85. { "Content-Encoding", HeaderInfo.MultiValue },
  86. { "Content-Length", HeaderInfo.Request | HeaderInfo.Response },
  87. { "Content-Type", HeaderInfo.Request },
  88. { "Content-Language", HeaderInfo.MultiValue },
  89. { "Date", HeaderInfo.Request },
  90. { "Expect", HeaderInfo.Request | HeaderInfo.MultiValue},
  91. { "Host", HeaderInfo.Request },
  92. { "If-Match", HeaderInfo.MultiValue },
  93. { "If-Modified-Since", HeaderInfo.Request },
  94. { "If-None-Match", HeaderInfo.MultiValue },
  95. { "Keep-Alive", HeaderInfo.Response },
  96. { "Pragma", HeaderInfo.MultiValue },
  97. { "Proxy-Authenticate", HeaderInfo.MultiValue },
  98. { "Proxy-Authorization", HeaderInfo.MultiValue },
  99. { "Proxy-Connection", HeaderInfo.Request | HeaderInfo.MultiValue },
  100. { "Range", HeaderInfo.Request | HeaderInfo.MultiValue },
  101. { "Referer", HeaderInfo.Request },
  102. { "Set-Cookie", HeaderInfo.MultiValue },
  103. { "Set-Cookie2", HeaderInfo.MultiValue },
  104. { "TE", HeaderInfo.MultiValue },
  105. { "Trailer", HeaderInfo.MultiValue },
  106. { "Transfer-Encoding", HeaderInfo.Request | HeaderInfo.Response | HeaderInfo.MultiValue },
  107. { "Upgrade", HeaderInfo.MultiValue },
  108. { "User-Agent", HeaderInfo.Request },
  109. { "Vary", HeaderInfo.MultiValue },
  110. { "Via", HeaderInfo.MultiValue },
  111. { "Warning", HeaderInfo.MultiValue },
  112. { "WWW-Authenticate", HeaderInfo.Response | HeaderInfo. MultiValue }
  113. };
  114. }
  115. // Constructors
  116. public WebHeaderCollection ()
  117. {
  118. }
  119. protected WebHeaderCollection (SerializationInfo serializationInfo,
  120. StreamingContext streamingContext)
  121. {
  122. int count;
  123. try {
  124. count = serializationInfo.GetInt32("Count");
  125. for (int i = 0; i < count; i++)
  126. this.Add (serializationInfo.GetString (i.ToString ()),
  127. serializationInfo.GetString ((count + i).ToString ()));
  128. } catch (SerializationException){
  129. count = serializationInfo.GetInt32("count");
  130. for (int i = 0; i < count; i++)
  131. this.Add (serializationInfo.GetString ("k" + i),
  132. serializationInfo.GetString ("v" + i));
  133. }
  134. }
  135. internal WebHeaderCollection (HeaderInfo headerRestriction)
  136. {
  137. this.headerRestriction = headerRestriction;
  138. }
  139. // Methods
  140. public void Add (string header)
  141. {
  142. if (header == null)
  143. throw new ArgumentNullException ("header");
  144. int pos = header.IndexOf (':');
  145. if (pos == -1)
  146. throw new ArgumentException ("no colon found", "header");
  147. this.Add (header.Substring (0, pos), header.Substring (pos + 1));
  148. }
  149. public override void Add (string name, string value)
  150. {
  151. if (name == null)
  152. throw new ArgumentNullException ("name");
  153. CheckRestrictedHeader (name);
  154. this.AddWithoutValidate (name, value);
  155. }
  156. protected void AddWithoutValidate (string headerName, string headerValue)
  157. {
  158. if (!IsHeaderName (headerName))
  159. throw new ArgumentException ("invalid header name: " + headerName, "headerName");
  160. if (headerValue == null)
  161. headerValue = String.Empty;
  162. else
  163. headerValue = headerValue.Trim ();
  164. if (!IsHeaderValue (headerValue))
  165. throw new ArgumentException ("invalid header value: " + headerValue, "headerValue");
  166. base.Add (headerName, headerValue);
  167. }
  168. public override string [] GetValues (string header)
  169. {
  170. if (header == null)
  171. throw new ArgumentNullException ("header");
  172. string [] values = base.GetValues (header);
  173. if (values == null || values.Length == 0)
  174. return null;
  175. if (IsMultiValue (header)) {
  176. List<string> separated = null;
  177. foreach (var value in values) {
  178. if (value.IndexOf (',') < 0)
  179. continue;
  180. if (separated == null) {
  181. separated = new List<string> (values.Length + 1);
  182. foreach (var v in values) {
  183. if (v == value)
  184. break;
  185. separated.Add (v);
  186. }
  187. }
  188. var slices = value.Split (',');
  189. var slices_length = slices.Length;
  190. if (value[value.Length - 1] == ',')
  191. --slices_length;
  192. for (int i = 0; i < slices_length; ++i ) {
  193. separated.Add (slices[i].Trim ());
  194. }
  195. }
  196. if (separated != null)
  197. return separated.ToArray ();
  198. }
  199. return values;
  200. }
  201. public override string[] GetValues (int index)
  202. {
  203. string[] values = base.GetValues (index);
  204. if (values == null || values.Length == 0) {
  205. return null;
  206. }
  207. return values;
  208. }
  209. public static bool IsRestricted (string headerName)
  210. {
  211. return IsRestricted (headerName, false);
  212. }
  213. public static bool IsRestricted (string headerName, bool response)
  214. {
  215. if (headerName == null)
  216. throw new ArgumentNullException ("headerName");
  217. if (headerName.Length == 0)
  218. throw new ArgumentException ("empty string", "headerName");
  219. if (!IsHeaderName (headerName))
  220. throw new ArgumentException ("Invalid character in header");
  221. HeaderInfo info;
  222. if (!headers.TryGetValue (headerName, out info))
  223. return false;
  224. var flag = response ? HeaderInfo.Response : HeaderInfo.Request;
  225. return (info & flag) != 0;
  226. }
  227. public override void OnDeserialization (object sender)
  228. {
  229. }
  230. public override void Remove (string name)
  231. {
  232. if (name == null)
  233. throw new ArgumentNullException ("name");
  234. CheckRestrictedHeader (name);
  235. base.Remove (name);
  236. }
  237. public override void Set (string name, string value)
  238. {
  239. if (name == null)
  240. throw new ArgumentNullException ("name");
  241. if (!IsHeaderName (name))
  242. throw new ArgumentException ("invalid header name");
  243. if (value == null)
  244. value = String.Empty;
  245. else
  246. value = value.Trim ();
  247. if (!IsHeaderValue (value))
  248. throw new ArgumentException ("invalid header value");
  249. CheckRestrictedHeader (name);
  250. base.Set (name, value);
  251. }
  252. public byte[] ToByteArray ()
  253. {
  254. return Encoding.UTF8.GetBytes(ToString ());
  255. }
  256. internal string ToStringMultiValue ()
  257. {
  258. StringBuilder sb = new StringBuilder();
  259. int count = base.Count;
  260. for (int i = 0; i < count ; i++) {
  261. string key = GetKey (i);
  262. if (IsMultiValue (key)) {
  263. foreach (string v in GetValues (i)) {
  264. sb.Append (key)
  265. .Append (": ")
  266. .Append (v)
  267. .Append ("\r\n");
  268. }
  269. } else {
  270. sb.Append (key)
  271. .Append (": ")
  272. .Append (Get (i))
  273. .Append ("\r\n");
  274. }
  275. }
  276. return sb.Append("\r\n").ToString();
  277. }
  278. public override string ToString ()
  279. {
  280. StringBuilder sb = new StringBuilder();
  281. int count = base.Count;
  282. for (int i = 0; i < count ; i++)
  283. sb.Append (GetKey (i))
  284. .Append (": ")
  285. .Append (Get (i))
  286. .Append ("\r\n");
  287. return sb.Append("\r\n").ToString();
  288. }
  289. #if !TARGET_JVM
  290. void ISerializable.GetObjectData (SerializationInfo serializationInfo,
  291. StreamingContext streamingContext)
  292. {
  293. GetObjectData (serializationInfo, streamingContext);
  294. }
  295. #endif
  296. public override void GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)
  297. {
  298. int count = base.Count;
  299. serializationInfo.AddValue ("Count", count);
  300. for (int i = 0; i < count; i++) {
  301. serializationInfo.AddValue (i.ToString (), GetKey (i));
  302. serializationInfo.AddValue ((count + i).ToString (), Get (i));
  303. }
  304. }
  305. public override string[] AllKeys {
  306. get {
  307. return base.AllKeys;
  308. }
  309. }
  310. public override int Count {
  311. get {
  312. return base.Count;
  313. }
  314. }
  315. public override KeysCollection Keys {
  316. get {
  317. return base.Keys;
  318. }
  319. }
  320. public override string Get (int index)
  321. {
  322. return base.Get (index);
  323. }
  324. public override string Get (string name)
  325. {
  326. return base.Get (name);
  327. }
  328. public override string GetKey (int index)
  329. {
  330. return base.GetKey (index);
  331. }
  332. public void Add (HttpRequestHeader header, string value)
  333. {
  334. Add (RequestHeaderToString (header), value);
  335. }
  336. public void Remove (HttpRequestHeader header)
  337. {
  338. Remove (RequestHeaderToString (header));
  339. }
  340. public void Set (HttpRequestHeader header, string value)
  341. {
  342. Set (RequestHeaderToString (header), value);
  343. }
  344. public void Add (HttpResponseHeader header, string value)
  345. {
  346. Add (ResponseHeaderToString (header), value);
  347. }
  348. public void Remove (HttpResponseHeader header)
  349. {
  350. Remove (ResponseHeaderToString (header));
  351. }
  352. public void Set (HttpResponseHeader header, string value)
  353. {
  354. Set (ResponseHeaderToString (header), value);
  355. }
  356. public string this [HttpRequestHeader header] {
  357. get {
  358. return Get (RequestHeaderToString (header));
  359. }
  360. set {
  361. Set (header, value);
  362. }
  363. }
  364. public string this [HttpResponseHeader header] {
  365. get {
  366. return Get (ResponseHeaderToString (header));
  367. }
  368. set {
  369. Set (header, value);
  370. }
  371. }
  372. public override void Clear ()
  373. {
  374. base.Clear ();
  375. }
  376. public override IEnumerator GetEnumerator ()
  377. {
  378. return base.GetEnumerator ();
  379. }
  380. // Internal Methods
  381. // With this we don't check for invalid characters in header. See bug #55994.
  382. internal void SetInternal (string header)
  383. {
  384. int pos = header.IndexOf (':');
  385. if (pos == -1)
  386. throw new ArgumentException ("no colon found", "header");
  387. SetInternal (header.Substring (0, pos), header.Substring (pos + 1));
  388. }
  389. internal void SetInternal (string name, string value)
  390. {
  391. if (value == null)
  392. value = String.Empty;
  393. else
  394. value = value.Trim ();
  395. if (!IsHeaderValue (value))
  396. throw new ArgumentException ("invalid header value");
  397. if (IsMultiValue (name)) {
  398. base.Add (name, value);
  399. } else {
  400. base.Remove (name);
  401. base.Set (name, value);
  402. }
  403. }
  404. internal void RemoveAndAdd (string name, string value)
  405. {
  406. if (value == null)
  407. value = String.Empty;
  408. else
  409. value = value.Trim ();
  410. base.Remove (name);
  411. base.Set (name, value);
  412. }
  413. internal void RemoveInternal (string name)
  414. {
  415. if (name == null)
  416. throw new ArgumentNullException ("name");
  417. base.Remove (name);
  418. }
  419. // Private Methods
  420. string RequestHeaderToString (HttpRequestHeader value)
  421. {
  422. CheckHeaderConsistency (HeaderInfo.Request);
  423. switch (value) {
  424. case HttpRequestHeader.CacheControl:
  425. return "Cache-Control";
  426. case HttpRequestHeader.Connection:
  427. return "Connection";
  428. case HttpRequestHeader.Date:
  429. return "Date";
  430. case HttpRequestHeader.KeepAlive:
  431. return "Keep-Alive";
  432. case HttpRequestHeader.Pragma:
  433. return "Pragma";
  434. case HttpRequestHeader.Trailer:
  435. return "Trailer";
  436. case HttpRequestHeader.TransferEncoding:
  437. return "Transfer-Encoding";
  438. case HttpRequestHeader.Upgrade:
  439. return "Upgrade";
  440. case HttpRequestHeader.Via:
  441. return "Via";
  442. case HttpRequestHeader.Warning:
  443. return "Warning";
  444. case HttpRequestHeader.Allow:
  445. return "Allow";
  446. case HttpRequestHeader.ContentLength:
  447. return "Content-Length";
  448. case HttpRequestHeader.ContentType:
  449. return "Content-Type";
  450. case HttpRequestHeader.ContentEncoding:
  451. return "Content-Encoding";
  452. case HttpRequestHeader.ContentLanguage:
  453. return "Content-Language";
  454. case HttpRequestHeader.ContentLocation:
  455. return "Content-Location";
  456. case HttpRequestHeader.ContentMd5:
  457. return "Content-MD5";
  458. case HttpRequestHeader.ContentRange:
  459. return "Content-Range";
  460. case HttpRequestHeader.Expires:
  461. return "Expires";
  462. case HttpRequestHeader.LastModified:
  463. return "Last-Modified";
  464. case HttpRequestHeader.Accept:
  465. return "Accept";
  466. case HttpRequestHeader.AcceptCharset:
  467. return "Accept-Charset";
  468. case HttpRequestHeader.AcceptEncoding:
  469. return "Accept-Encoding";
  470. case HttpRequestHeader.AcceptLanguage:
  471. return "accept-language";
  472. case HttpRequestHeader.Authorization:
  473. return "Authorization";
  474. case HttpRequestHeader.Cookie:
  475. return "Cookie";
  476. case HttpRequestHeader.Expect:
  477. return "Expect";
  478. case HttpRequestHeader.From:
  479. return "From";
  480. case HttpRequestHeader.Host:
  481. return "Host";
  482. case HttpRequestHeader.IfMatch:
  483. return "If-Match";
  484. case HttpRequestHeader.IfModifiedSince:
  485. return "If-Modified-Since";
  486. case HttpRequestHeader.IfNoneMatch:
  487. return "If-None-Match";
  488. case HttpRequestHeader.IfRange:
  489. return "If-Range";
  490. case HttpRequestHeader.IfUnmodifiedSince:
  491. return "If-Unmodified-Since";
  492. case HttpRequestHeader.MaxForwards:
  493. return "Max-Forwards";
  494. case HttpRequestHeader.ProxyAuthorization:
  495. return "Proxy-Authorization";
  496. case HttpRequestHeader.Referer:
  497. return "Referer";
  498. case HttpRequestHeader.Range:
  499. return "Range";
  500. case HttpRequestHeader.Te:
  501. return "TE";
  502. case HttpRequestHeader.Translate:
  503. return "Translate";
  504. case HttpRequestHeader.UserAgent:
  505. return "User-Agent";
  506. default:
  507. throw new InvalidOperationException ();
  508. }
  509. }
  510. string ResponseHeaderToString (HttpResponseHeader value)
  511. {
  512. CheckHeaderConsistency (HeaderInfo.Response);
  513. switch (value) {
  514. case HttpResponseHeader.CacheControl:
  515. return "Cache-Control";
  516. case HttpResponseHeader.Connection:
  517. return "Connection";
  518. case HttpResponseHeader.Date:
  519. return "Date";
  520. case HttpResponseHeader.KeepAlive:
  521. return "Keep-Alive";
  522. case HttpResponseHeader.Pragma:
  523. return "Pragma";
  524. case HttpResponseHeader.Trailer:
  525. return "Trailer";
  526. case HttpResponseHeader.TransferEncoding:
  527. return "Transfer-Encoding";
  528. case HttpResponseHeader.Upgrade:
  529. return "Upgrade";
  530. case HttpResponseHeader.Via:
  531. return "Via";
  532. case HttpResponseHeader.Warning:
  533. return "Warning";
  534. case HttpResponseHeader.Allow:
  535. return "Allow";
  536. case HttpResponseHeader.ContentLength:
  537. return "Content-Length";
  538. case HttpResponseHeader.ContentType:
  539. return "Content-Type";
  540. case HttpResponseHeader.ContentEncoding:
  541. return "Content-Encoding";
  542. case HttpResponseHeader.ContentLanguage:
  543. return "Content-Language";
  544. case HttpResponseHeader.ContentLocation:
  545. return "Content-Location";
  546. case HttpResponseHeader.ContentMd5:
  547. return "Content-MD5";
  548. case HttpResponseHeader.ContentRange:
  549. return "Content-Range";
  550. case HttpResponseHeader.Expires:
  551. return "Expires";
  552. case HttpResponseHeader.LastModified:
  553. return "Last-Modified";
  554. case HttpResponseHeader.AcceptRanges:
  555. return "Accept-Ranges";
  556. case HttpResponseHeader.Age:
  557. return "Age";
  558. case HttpResponseHeader.ETag:
  559. return "ETag";
  560. case HttpResponseHeader.Location:
  561. return "Location";
  562. case HttpResponseHeader.ProxyAuthenticate:
  563. return "Proxy-Authenticate";
  564. case HttpResponseHeader.RetryAfter:
  565. return "Retry-After";
  566. case HttpResponseHeader.Server:
  567. return "Server";
  568. case HttpResponseHeader.SetCookie:
  569. return "Set-Cookie";
  570. case HttpResponseHeader.Vary:
  571. return "Vary";
  572. case HttpResponseHeader.WwwAuthenticate:
  573. return "WWW-Authenticate";
  574. default:
  575. throw new InvalidOperationException ();
  576. }
  577. }
  578. void CheckRestrictedHeader (string headerName)
  579. {
  580. if (!headerRestriction.HasValue)
  581. return;
  582. HeaderInfo info;
  583. if (!headers.TryGetValue (headerName, out info))
  584. return;
  585. if ((info & headerRestriction.Value) != 0)
  586. throw new ArgumentException ("This header must be modified with the appropiate property.");
  587. }
  588. void CheckHeaderConsistency (HeaderInfo value)
  589. {
  590. if (!headerConsistency.HasValue) {
  591. headerConsistency = value;
  592. return;
  593. }
  594. if ((headerConsistency & value) == 0)
  595. throw new InvalidOperationException ();
  596. }
  597. internal static bool IsMultiValue (string headerName)
  598. {
  599. if (headerName == null)
  600. return false;
  601. HeaderInfo info;
  602. return headers.TryGetValue (headerName, out info) && (info & HeaderInfo.MultiValue) != 0;
  603. }
  604. internal static bool IsHeaderValue (string value)
  605. {
  606. // TEXT any 8 bit value except CTL's (0-31 and 127)
  607. // but including \r\n space and \t
  608. // after a newline at least one space or \t must follow
  609. // certain header fields allow comments ()
  610. int len = value.Length;
  611. for (int i = 0; i < len; i++) {
  612. char c = value [i];
  613. if (c == 127)
  614. return false;
  615. if (c < 0x20 && (c != '\r' && c != '\n' && c != '\t'))
  616. return false;
  617. if (c == '\n' && ++i < len) {
  618. c = value [i];
  619. if (c != ' ' && c != '\t')
  620. return false;
  621. }
  622. }
  623. return true;
  624. }
  625. internal static bool IsHeaderName (string name)
  626. {
  627. if (name == null || name.Length == 0)
  628. return false;
  629. int len = name.Length;
  630. for (int i = 0; i < len; i++) {
  631. char c = name [i];
  632. if (c > 126 || !allowed_chars [c])
  633. return false;
  634. }
  635. return true;
  636. }
  637. }
  638. }