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(); |