OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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_paser.authentication_challenge; | 5 library http_paser.authentication_challenge; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 | 8 |
9 import 'package:string_scanner/string_scanner.dart'; | 9 import 'package:string_scanner/string_scanner.dart'; |
10 | 10 |
| 11 import 'case_insensitive_map.dart'; |
11 import 'scan.dart'; | 12 import 'scan.dart'; |
12 import 'utils.dart'; | 13 import 'utils.dart'; |
13 | 14 |
14 /// A single challenge in a WWW-Authenticate header, parsed as per [RFC 2617][]. | 15 /// A single challenge in a WWW-Authenticate header, parsed as per [RFC 2617][]. |
15 /// | 16 /// |
16 /// [RFC 2617]: http://tools.ietf.org/html/rfc2617 | 17 /// [RFC 2617]: http://tools.ietf.org/html/rfc2617 |
17 /// | 18 /// |
18 /// Each WWW-Authenticate header contains one or more challenges, representing | 19 /// Each WWW-Authenticate header contains one or more challenges, representing |
19 /// valid ways to authenticate with the server. | 20 /// valid ways to authenticate with the server. |
20 class AuthenticationChallenge { | 21 class AuthenticationChallenge { |
21 /// The scheme describing the type of authentication that's required, for | 22 /// The scheme describing the type of authentication that's required, for |
22 /// example "basic" or "digest". | 23 /// example "basic" or "digest". |
23 /// | 24 /// |
24 /// This is normalized to always be lower-case. | 25 /// This is normalized to always be lower-case. |
25 final String scheme; | 26 final String scheme; |
26 | 27 |
27 /// The parameters describing how to authenticate. | 28 /// The parameters describing how to authenticate. |
28 /// | 29 /// |
29 /// The semantics of these parameters are scheme-specific. | 30 /// The semantics of these parameters are scheme-specific. The keys of this |
| 31 /// map are case-insensitive. |
30 final Map<String, String> parameters; | 32 final Map<String, String> parameters; |
31 | 33 |
32 /// Parses a WWW-Authenticate header, which should contain one or more | 34 /// Parses a WWW-Authenticate header, which should contain one or more |
33 /// challenges. | 35 /// challenges. |
34 /// | 36 /// |
35 /// Throws a [FormatException] if the header is invalid. | 37 /// Throws a [FormatException] if the header is invalid. |
36 static List<AuthenticationChallenge> parseHeader(String header) { | 38 static List<AuthenticationChallenge> parseHeader(String header) { |
37 return wrapFormatException("authentication header", header, () { | 39 return wrapFormatException("authentication header", header, () { |
38 var scanner = new StringScanner(header); | 40 var scanner = new StringScanner(header); |
39 scanner.scan(whitespace); | 41 scanner.scan(whitespace); |
(...skipping 12 matching lines...) Expand all Loading... |
52 _scanAuthParam(scanner, params); | 54 _scanAuthParam(scanner, params); |
53 | 55 |
54 var beforeComma = scanner.position; | 56 var beforeComma = scanner.position; |
55 while (scanner.scan(",")) { | 57 while (scanner.scan(",")) { |
56 scanner.scan(whitespace); | 58 scanner.scan(whitespace); |
57 | 59 |
58 // Empty elements are allowed, but excluded from the results. | 60 // Empty elements are allowed, but excluded from the results. |
59 if (scanner.matches(",") || scanner.isDone) continue; | 61 if (scanner.matches(",") || scanner.isDone) continue; |
60 | 62 |
61 scanner.expect(token, name: "a token"); | 63 scanner.expect(token, name: "a token"); |
62 var name = scanner.lastMatch[0].toLowerCase(); | 64 var name = scanner.lastMatch[0]; |
63 scanner.scan(whitespace); | 65 scanner.scan(whitespace); |
64 | 66 |
65 // If there's no "=", then this is another challenge rather than a | 67 // If there's no "=", then this is another challenge rather than a |
66 // parameter for the current challenge. | 68 // parameter for the current challenge. |
67 if (!scanner.scan('=')) { | 69 if (!scanner.scan('=')) { |
68 scanner.position = beforeComma; | 70 scanner.position = beforeComma; |
69 break; | 71 break; |
70 } | 72 } |
71 | 73 |
72 scanner.scan(whitespace); | 74 scanner.scan(whitespace); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 if (scanner.lastMatch == null || !scanner.lastMatch[0].contains(" ")) { | 124 if (scanner.lastMatch == null || !scanner.lastMatch[0].contains(" ")) { |
123 scanner.expect(" ", name: whitespaceName); | 125 scanner.expect(" ", name: whitespaceName); |
124 } | 126 } |
125 | 127 |
126 return scheme; | 128 return scheme; |
127 } | 129 } |
128 | 130 |
129 /// Scans a single authentication parameter and stores its result in [params]. | 131 /// Scans a single authentication parameter and stores its result in [params]. |
130 static void _scanAuthParam(StringScanner scanner, Map params) { | 132 static void _scanAuthParam(StringScanner scanner, Map params) { |
131 scanner.expect(token, name: "a token"); | 133 scanner.expect(token, name: "a token"); |
132 var name = scanner.lastMatch[0].toLowerCase(); | 134 var name = scanner.lastMatch[0]; |
133 scanner.scan(whitespace); | 135 scanner.scan(whitespace); |
134 scanner.expect('='); | 136 scanner.expect('='); |
135 scanner.scan(whitespace); | 137 scanner.scan(whitespace); |
136 | 138 |
137 if (scanner.scan(token)) { | 139 if (scanner.scan(token)) { |
138 params[name] = scanner.lastMatch[0]; | 140 params[name] = scanner.lastMatch[0]; |
139 } else { | 141 } else { |
140 params[name] = expectQuotedString( | 142 params[name] = expectQuotedString( |
141 scanner, name: "a token or a quoted string"); | 143 scanner, name: "a token or a quoted string"); |
142 } | 144 } |
143 | 145 |
144 scanner.scan(whitespace); | 146 scanner.scan(whitespace); |
145 } | 147 } |
146 | 148 |
147 /// Creates a new challenge value with [scheme] and [parameters]. | 149 /// Creates a new challenge value with [scheme] and [parameters]. |
148 AuthenticationChallenge(this.scheme, Map<String, String> parameters) | 150 AuthenticationChallenge(this.scheme, Map<String, String> parameters) |
149 : parameters = new UnmodifiableMapView(parameters); | 151 : parameters = new UnmodifiableMapView( |
| 152 new CaseInsensitiveMap.from(parameters)); |
150 } | 153 } |
OLD | NEW |