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