OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library http_parser.http_date; | 5 library http_parser.http_date; |
6 | 6 |
7 import 'package:string_scanner/string_scanner.dart'; | 7 import 'package:string_scanner/string_scanner.dart'; |
8 | 8 |
| 9 import 'utils.dart'; |
| 10 |
9 const _WEEKDAYS = const ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; | 11 const _WEEKDAYS = const ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; |
10 const _MONTHS = const ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", | 12 const _MONTHS = const ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", |
11 "Sep", "Oct", "Nov", "Dec"]; | 13 "Sep", "Oct", "Nov", "Dec"]; |
12 | 14 |
13 final _shortWeekdayRegExp = new RegExp(r"Mon|Tue|Wed|Thu|Fri|Sat|Sun"); | 15 final _shortWeekdayRegExp = new RegExp(r"Mon|Tue|Wed|Thu|Fri|Sat|Sun"); |
14 final _longWeekdayRegExp = | 16 final _longWeekdayRegExp = |
15 new RegExp(r"Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday"); | 17 new RegExp(r"Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday"); |
16 final _monthRegExp = | 18 final _monthRegExp = |
17 new RegExp(r"Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec"); | 19 new RegExp(r"Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec"); |
18 final _digitRegExp = new RegExp(r"\d+"); | 20 final _digitRegExp = new RegExp(r"\d+"); |
(...skipping 22 matching lines...) Expand all Loading... |
41 ..write(" GMT"); | 43 ..write(" GMT"); |
42 return buffer.toString(); | 44 return buffer.toString(); |
43 } | 45 } |
44 | 46 |
45 /// Parses an HTTP-formatted date into a UTC [DateTime]. | 47 /// Parses an HTTP-formatted date into a UTC [DateTime]. |
46 /// | 48 /// |
47 /// This follows [RFC | 49 /// This follows [RFC |
48 /// 2616](http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3). It will | 50 /// 2616](http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3). It will |
49 /// throw a [FormatException] if [date] is invalid. | 51 /// throw a [FormatException] if [date] is invalid. |
50 DateTime parseHttpDate(String date) { | 52 DateTime parseHttpDate(String date) { |
51 try { | 53 return wrapFormatException("HTTP date", date, () { |
52 var scanner = new StringScanner(date); | 54 var scanner = new StringScanner(date); |
53 | 55 |
54 if (scanner.scan(_longWeekdayRegExp)) { | 56 if (scanner.scan(_longWeekdayRegExp)) { |
55 // RFC 850 starts with a long weekday. | 57 // RFC 850 starts with a long weekday. |
56 scanner.expect(", "); | 58 scanner.expect(", "); |
57 var day = _parseInt(scanner, 2); | 59 var day = _parseInt(scanner, 2); |
58 scanner.expect("-"); | 60 scanner.expect("-"); |
59 var month = _parseMonth(scanner); | 61 var month = _parseMonth(scanner); |
60 scanner.expect("-"); | 62 scanner.expect("-"); |
61 var year = 1900 + _parseInt(scanner, 2); | 63 var year = 1900 + _parseInt(scanner, 2); |
(...skipping 27 matching lines...) Expand all Loading... |
89 var month = _parseMonth(scanner); | 91 var month = _parseMonth(scanner); |
90 scanner.expect(" "); | 92 scanner.expect(" "); |
91 var day = scanner.scan(" ") ? _parseInt(scanner, 1) : _parseInt(scanner, 2); | 93 var day = scanner.scan(" ") ? _parseInt(scanner, 1) : _parseInt(scanner, 2); |
92 scanner.expect(" "); | 94 scanner.expect(" "); |
93 var time = _parseTime(scanner); | 95 var time = _parseTime(scanner); |
94 scanner.expect(" "); | 96 scanner.expect(" "); |
95 var year = _parseInt(scanner, 4); | 97 var year = _parseInt(scanner, 4); |
96 scanner.expectDone(); | 98 scanner.expectDone(); |
97 | 99 |
98 return _makeDateTime(year, month, day, time); | 100 return _makeDateTime(year, month, day, time); |
99 } on FormatException catch (error) { | 101 }); |
100 throw new FormatException('Invalid HTTP date "$date": ${error.message}'); | |
101 } | |
102 } | 102 } |
103 | 103 |
104 /// Parses a short-form month name to a form accepted by [DateTime]. | 104 /// Parses a short-form month name to a form accepted by [DateTime]. |
105 int _parseMonth(StringScanner scanner) { | 105 int _parseMonth(StringScanner scanner) { |
106 scanner.expect(_monthRegExp); | 106 scanner.expect(_monthRegExp); |
107 // DateTime uses 1-indexed months. | 107 // DateTime uses 1-indexed months. |
108 return _MONTHS.indexOf(scanner.lastMatch[0]) + 1; | 108 return _MONTHS.indexOf(scanner.lastMatch[0]) + 1; |
109 } | 109 } |
110 | 110 |
111 /// Parses an int an enforces that it has exactly [digits] digits. | 111 /// Parses an int an enforces that it has exactly [digits] digits. |
(...skipping 29 matching lines...) Expand all Loading... |
141 DateTime _makeDateTime(int year, int month, int day, DateTime time) { | 141 DateTime _makeDateTime(int year, int month, int day, DateTime time) { |
142 var dateTime = | 142 var dateTime = |
143 new DateTime.utc(year, month, day, time.hour, time.minute, time.second); | 143 new DateTime.utc(year, month, day, time.hour, time.minute, time.second); |
144 | 144 |
145 // If [day] was too large, it will cause [month] to overflow. | 145 // If [day] was too large, it will cause [month] to overflow. |
146 if (dateTime.month != month) { | 146 if (dateTime.month != month) { |
147 throw new FormatException("invalid day '$day' for month '$month'."); | 147 throw new FormatException("invalid day '$day' for month '$month'."); |
148 } | 148 } |
149 return dateTime; | 149 return dateTime; |
150 } | 150 } |
OLD | NEW |