Chromium Code Reviews| Index: pkg/oauth2/lib/src/utils.dart |
| diff --git a/pkg/oauth2/lib/src/utils.dart b/pkg/oauth2/lib/src/utils.dart |
| index 583a5bc4438ecea546e41cb8b833b235448676de..122e74f3fcfdcd0886bb71007876d950c35ed16d 100644 |
| --- a/pkg/oauth2/lib/src/utils.dart |
| +++ b/pkg/oauth2/lib/src/utils.dart |
| @@ -65,6 +65,62 @@ List<String> split1(String toSplit, String pattern) { |
| toSplit.substring(index + pattern.length)]; |
| } |
| +/** A pair of values. */ |
|
Bob Nystrom
2012/12/04 01:41:48
If you're creating this type anyway, how about jus
nweiz
2012/12/04 01:51:35
Why would I create a specific type when I could ma
Bob Nystrom
2012/12/04 01:59:42
Why make types at all: They help clarify intent an
nweiz
2012/12/04 21:39:26
Done. I'm still not convinced this is better, but
|
| +class Pair<E, F> { |
| + E first; |
| + F last; |
| + |
| + Pair(this.first, this.last); |
| + |
| + String toString() => '($first, $last)'; |
| + |
| + bool operator==(other) { |
| + if (other is! Pair) return false; |
| + return other.first == first && other.last == last; |
| + } |
| +} |
| + |
| +/// Parses a WWW-Authenticate header value, as per [RFC 2617][]. This returns a |
| +/// pair where the first value is the authentication scheme, and the second is a |
| +/// map of parameters. |
| +/// |
| +/// Throws a [FormatException] if the header has invalid formatting. |
| +/// |
| +/// [RFC 2617]: http://tools.ietf.org/html/rfc2617 |
| +Pair<String, Map<String, String>> parseAuthenticateHeader(String header) { |
| + var split = split1(header, ' '); |
| + if (split.length == 0) { |
| + throw new FormatException('Invalid WWW-Authenticate header: "$header"'); |
| + } else if (split.length == 1 || split[1].trim().isEmpty) { |
| + return new Pair(split[0].toLowerCase(), {}); |
| + } |
| + var scheme = split[0].toLowerCase(); |
| + var paramString = split[1]; |
| + |
| + // From http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html. |
| + var tokenChar = r'[^\0-\x1F()<>@,;:\\"/\[\]?={} \t\x7F]'; |
| + var quotedStringChar = r'(?:[^\0-\x1F\x7F"]|\\.)'; |
| + var regexp = new RegExp('^ *($tokenChar+)="($quotedStringChar*)" *(, *)?'); |
| + |
| + var params = {}; |
| + var match; |
| + do { |
| + match = regexp.firstMatch(paramString); |
|
Bob Nystrom
2012/12/04 01:41:48
Can you use allMatches() here?
nweiz
2012/12/04 01:51:35
No. I need to enforce that each match follows dire
Bob Nystrom
2012/12/04 01:59:42
OK, that's what I figured. Just checking.
|
| + if (match == null) { |
| + throw new FormatException('Invalid WWW-Authenticate header: "$header"'); |
| + } |
| + |
| + paramString = paramString.substring(match.end); |
| + params[match.group(1).toLowerCase()] = match.group(2); |
| + } while (match.group(3) != null); |
| + |
| + if (!paramString.trim().isEmpty) { |
| + throw new FormatException('Invalid WWW-Authenticate header: "$header"'); |
| + } |
| + |
| + return new Pair<String, Map<String, String>>(scheme, params); |
| +} |
| + |
| /// Returns a [Future] that asynchronously completes to `null`. |
| Future get async { |
| var completer = new Completer(); |