| 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 |