Merge pull request #3144 from Unity-Technologies/fix-recursive-property-call
[mono.git] / mcs / class / referencesource / System.Web / Util / ParseHttpDate.cs
1 using System;
2 using System.Globalization;
3
4
5 namespace System.Web.Util
6 {
7     internal static class HttpDate
8     {
9         static readonly int[] s_tensDigit = new int[10] { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 };
10         
11         /*++
12         
13             Converts a 2 character string to integer
14         
15             Arguments:
16                 s   String to convert
17         
18             Returns:
19                 numeric equivalent, 0 on failure.
20         --*/
21         static int atoi2(string s, int startIndex)
22         {
23             try {
24                 int tens = s[0 + startIndex] - '0';
25                 int ones = s[1 + startIndex] - '0';
26             
27                 return s_tensDigit[tens] + ones;
28             } 
29             catch {
30                 throw new FormatException(SR.GetString(SR.Atio2BadString, s, startIndex));
31             }
32         }
33         
34         static readonly string[] s_days = new string [7] {
35             "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
36         };
37         
38         static readonly string[] s_months = new string[12] {
39             "Jan", "Feb", "Mar", "Apr",
40             "May", "Jun", "Jul", "Aug",
41             "Sep", "Oct", "Nov", "Dec"
42         };
43         
44         // Custom table for make_month() for mapping "Apr" to 4
45         static readonly sbyte[] s_monthIndexTable = new sbyte[64] {
46            -1, (sbyte)'A',          2, 12, -1, -1,         -1,  8, // A to G
47            -1,         -1,         -1, -1,  7, -1, (sbyte)'N', -1, // H to O
48             9,         -1, (sbyte)'R', -1, 10, -1,         11, -1, // P to W
49            -1,          5,         -1, -1, -1, -1,         -1, -1, // X to Z
50            -1, (sbyte)'A',          2, 12, -1, -1,         -1,  8, // a to g
51            -1,         -1,         -1, -1,  7, -1, (sbyte)'N', -1, // h to o
52             9,         -1, (sbyte)'R', -1, 10, -1,         11, -1, // p to w
53            -1,          5,         -1, -1, -1, -1,         -1, -1  // x to z
54         };
55         
56         static int make_month(string s, int startIndex)
57         {
58             int i;
59             sbyte monthIndex;
60             string monthString;
61         
62             //
63             // use the third character as the index
64             //
65         
66             i = ((int) s[2 + startIndex] - 0x40) & 0x3F;
67             monthIndex = s_monthIndexTable[i];
68         
69             if ( monthIndex >= 13 ) {
70             
71                 //
72                 // ok, we need to look at the second character
73                 //
74             
75                 if ( monthIndex == (sbyte) 'N' ) {
76             
77                     //
78                     // we got an N which we need to resolve further
79                     //
80             
81                     //
82                     // if s[1] is 'u' then Jun, if 'a' then Jan
83                     //
84
85
86                     if ( s_monthIndexTable[(s[1 + startIndex]-0x40) & 0x3f] == (sbyte) 'A' ) {
87                         monthIndex = 1;
88                     } else {
89                         monthIndex = 6;
90                     }
91             
92                 } else if ( monthIndex == (sbyte) 'R' ) {
93             
94                     //
95                     // if s[1] is 'a' then [....], if 'p' then April
96                     //
97             
98                     if ( s_monthIndexTable[(s[1 + startIndex]-0x40) & 0x3f] == (sbyte) 'A' ) {
99                         monthIndex = 3;
100                     } else {
101                         monthIndex = 4;
102                     }
103                 } else {
104                     throw new FormatException(SR.GetString(SR.MakeMonthBadString, s, startIndex));
105                 }
106             }
107
108         
109             monthString = s_months[monthIndex-1];
110         
111             if ( (s[0 + startIndex] == monthString[0]) &&
112                  (s[1 + startIndex] == monthString[1]) &&
113                  (s[2 + startIndex] == monthString[2]) ) {
114         
115                 return(monthIndex);
116         
117             } else if ( ((Char.ToUpper(s[0 + startIndex], CultureInfo.InvariantCulture)) == monthString[0]) &&
118                         ((Char.ToLower(s[1 + startIndex], CultureInfo.InvariantCulture)) == monthString[1]) &&
119                         ((Char.ToLower(s[2 + startIndex], CultureInfo.InvariantCulture)) == monthString[2]) ) {
120         
121                 return monthIndex;
122             }
123
124             throw new FormatException(SR.GetString(SR.MakeMonthBadString, s, startIndex));
125
126         } // make_month
127         
128         /*++
129         
130           Converts a string representation of a GMT time (three different
131           varieties) to an NT representation of a file time.
132         
133           We handle the following variations:
134         
135             Sun, 06 Nov 1994 08:49:37 GMT   (RFC 822 updated by RFC 1123)
136             Sunday, 06-Nov-94 08:49:37 GMT  (RFC 850)
137             Sun Nov 06 08:49:37 1994        (ANSI C's asctime() format
138         
139           Arguments:
140             time                String representation of time field
141         
142           Returns:
143             TRUE on success and FALSE on failure.
144         
145           History:
146         
147             Johnl       24-Jan-1995     Modified from WWW library
148         
149         --*/
150         static internal DateTime UtcParse(string time)
151         {
152             int         i;
153             int         year, month, day, hour, minute, second;
154         
155             if (time == null) {
156                 throw new ArgumentNullException("time");
157             }
158         
159             if ((i = time.IndexOf(',')) != -1) {
160         
161                 //
162                 // Thursday, 10-Jun-93 01:29:59 GMT
163                 // or: Thu, 10 Jan 1993 01:29:59 GMT */
164                 //
165         
166                 int length = time.Length - i;
167                 while (--length > 0 && time[++i] == ' ') ;
168
169                 if (time[i+2] == '-' ) {      /* First format */
170         
171                     if (length < 18) {
172                         throw new FormatException(SR.GetString(SR.UtilParseDateTimeBad, time));
173                     }
174         
175                     day = atoi2(time, i);
176                     month = make_month(time, i + 3);
177                     year = atoi2(time, i + 7);
178                     if ( year < 50 ) {
179                         year += 2000;
180                     } else {
181                         year += 1900;
182                     }
183
184                     hour = atoi2(time, i + 10);
185                     minute = atoi2(time, i + 13);
186                     second = atoi2(time, i +16);
187         
188                 } else {                         /* Second format */
189         
190                     if (length < 20) {
191                         throw new FormatException(SR.GetString(SR.UtilParseDateTimeBad, time));
192                     }
193         
194                     day = atoi2(time, i);
195                     month = make_month(time, i + 3);
196                     year = atoi2(time, i + 7) * 100 + atoi2(time, i + 9);
197                     hour = atoi2(time, i + 12);
198                     minute = atoi2(time, i + 15);
199                     second = atoi2(time, i + 18);
200                 }
201             } else {    /* Try the other format:  Wed Jun 09 01:29:59 1993 GMT */
202         
203                 i = -1;
204                 int length = time.Length + 1;
205                 while (--length > 0 && time[++i] == ' ');
206         
207                 if (length < 24) {
208                     throw new FormatException(SR.GetString(SR.UtilParseDateTimeBad, time));
209                 }
210
211                 day = atoi2(time, i + 8);
212                 month = make_month(time, i + 4);
213                 year = atoi2(time, i + 20) * 100 + atoi2(time, i + 22);
214                 hour = atoi2(time, i + 11);
215                 minute = atoi2(time, i + 14);
216                 second = atoi2(time, i + 17);
217             }
218         
219             return new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc);
220         }
221     }
222 }
223
224