| Index: mojo/public/dart/third_party/http_parser/lib/src/authentication_challenge.dart
|
| diff --git a/mojo/public/dart/third_party/http_parser/lib/src/authentication_challenge.dart b/mojo/public/dart/third_party/http_parser/lib/src/authentication_challenge.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..773ee3b81b6c8d45849a234f7de5f19c1f11b8bc
|
| --- /dev/null
|
| +++ b/mojo/public/dart/third_party/http_parser/lib/src/authentication_challenge.dart
|
| @@ -0,0 +1,153 @@
|
| +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +library http_paser.authentication_challenge;
|
| +
|
| +import 'dart:collection';
|
| +
|
| +import 'package:string_scanner/string_scanner.dart';
|
| +
|
| +import 'case_insensitive_map.dart';
|
| +import 'scan.dart';
|
| +import 'utils.dart';
|
| +
|
| +/// A single challenge in a WWW-Authenticate header, parsed as per [RFC 2617][].
|
| +///
|
| +/// [RFC 2617]: http://tools.ietf.org/html/rfc2617
|
| +///
|
| +/// Each WWW-Authenticate header contains one or more challenges, representing
|
| +/// valid ways to authenticate with the server.
|
| +class AuthenticationChallenge {
|
| + /// The scheme describing the type of authentication that's required, for
|
| + /// example "basic" or "digest".
|
| + ///
|
| + /// This is normalized to always be lower-case.
|
| + final String scheme;
|
| +
|
| + /// The parameters describing how to authenticate.
|
| + ///
|
| + /// The semantics of these parameters are scheme-specific. The keys of this
|
| + /// map are case-insensitive.
|
| + final Map<String, String> parameters;
|
| +
|
| + /// Parses a WWW-Authenticate header, which should contain one or more
|
| + /// challenges.
|
| + ///
|
| + /// Throws a [FormatException] if the header is invalid.
|
| + static List<AuthenticationChallenge> parseHeader(String header) {
|
| + return wrapFormatException("authentication header", header, () {
|
| + var scanner = new StringScanner(header);
|
| + scanner.scan(whitespace);
|
| + var challenges = parseList(scanner, () {
|
| + var scheme = _scanScheme(scanner, whitespaceName: '" " or "="');
|
| +
|
| + // Manually parse the inner list. We need to do some lookahead to
|
| + // disambiguate between an auth param and another challenge.
|
| + var params = {};
|
| +
|
| + // Consume initial empty values.
|
| + while (scanner.scan(",")) {
|
| + scanner.scan(whitespace);
|
| + }
|
| +
|
| + _scanAuthParam(scanner, params);
|
| +
|
| + var beforeComma = scanner.position;
|
| + while (scanner.scan(",")) {
|
| + scanner.scan(whitespace);
|
| +
|
| + // Empty elements are allowed, but excluded from the results.
|
| + if (scanner.matches(",") || scanner.isDone) continue;
|
| +
|
| + scanner.expect(token, name: "a token");
|
| + var name = scanner.lastMatch[0];
|
| + scanner.scan(whitespace);
|
| +
|
| + // If there's no "=", then this is another challenge rather than a
|
| + // parameter for the current challenge.
|
| + if (!scanner.scan('=')) {
|
| + scanner.position = beforeComma;
|
| + break;
|
| + }
|
| +
|
| + scanner.scan(whitespace);
|
| +
|
| + if (scanner.scan(token)) {
|
| + params[name] = scanner.lastMatch[0];
|
| + } else {
|
| + params[name] = expectQuotedString(
|
| + scanner, name: "a token or a quoted string");
|
| + }
|
| +
|
| + scanner.scan(whitespace);
|
| + beforeComma = scanner.position;
|
| + }
|
| +
|
| + return new AuthenticationChallenge(scheme, params);
|
| + });
|
| +
|
| + scanner.expectDone();
|
| + return challenges;
|
| + });
|
| + }
|
| +
|
| + /// Parses a single WWW-Authenticate challenge value.
|
| + ///
|
| + /// Throws a [FormatException] if the challenge is invalid.
|
| + factory AuthenticationChallenge.parse(String challenge) {
|
| + return wrapFormatException("authentication challenge", challenge, () {
|
| + var scanner = new StringScanner(challenge);
|
| + scanner.scan(whitespace);
|
| + var scheme = _scanScheme(scanner);
|
| +
|
| + var params = {};
|
| + parseList(scanner, () => _scanAuthParam(scanner, params));
|
| +
|
| + scanner.expectDone();
|
| + return new AuthenticationChallenge(scheme, params);
|
| + });
|
| + }
|
| +
|
| + /// Scans a single scheme name and asserts that it's followed by a space.
|
| + ///
|
| + /// If [whitespaceName] is passed, it's used as the name for exceptions thrown
|
| + /// due to invalid trailing whitespace.
|
| + static String _scanScheme(StringScanner scanner, {String whitespaceName}) {
|
| + scanner.expect(token, name: "a token");
|
| + var scheme = scanner.lastMatch[0].toLowerCase();
|
| +
|
| + scanner.scan(whitespace);
|
| +
|
| + // The spec specifically requires a space between the scheme and its
|
| + // params.
|
| + if (scanner.lastMatch == null || !scanner.lastMatch[0].contains(" ")) {
|
| + scanner.expect(" ", name: whitespaceName);
|
| + }
|
| +
|
| + return scheme;
|
| + }
|
| +
|
| + /// Scans a single authentication parameter and stores its result in [params].
|
| + static void _scanAuthParam(StringScanner scanner, Map params) {
|
| + scanner.expect(token, name: "a token");
|
| + var name = scanner.lastMatch[0];
|
| + scanner.scan(whitespace);
|
| + scanner.expect('=');
|
| + scanner.scan(whitespace);
|
| +
|
| + if (scanner.scan(token)) {
|
| + params[name] = scanner.lastMatch[0];
|
| + } else {
|
| + params[name] = expectQuotedString(
|
| + scanner, name: "a token or a quoted string");
|
| + }
|
| +
|
| + scanner.scan(whitespace);
|
| + }
|
| +
|
| + /// Creates a new challenge value with [scheme] and [parameters].
|
| + AuthenticationChallenge(this.scheme, Map<String, String> parameters)
|
| + : parameters = new UnmodifiableMapView(
|
| + new CaseInsensitiveMap.from(parameters));
|
| +}
|
|
|