-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathwww_authenticate.py
More file actions
85 lines (73 loc) · 2.54 KB
/
Copy pathwww_authenticate.py
File metadata and controls
85 lines (73 loc) · 2.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
from collections import OrderedDict
import re
_tokens = (
('token', re.compile(r'''^([!#$%&'*+\-.^_`|~\w/]+(?:={1,2}$)?)''')),
('token', re.compile(r'''^"((?:[^"\\]|\\\\|\\")+)"''')),
(None, re.compile(r'^\s+')),
('equals', re.compile(r'^(=)')),
('comma', re.compile(r'^(,)')),
)
def _casefold(value):
try:
return value.casefold()
except AttributeError:
return value.lower()
class CaseFoldedOrderedDict(OrderedDict):
def __getitem__(self, key):
return super(CaseFoldedOrderedDict, self).__getitem__(_casefold(key))
def __setitem__(self, key, value):
super(CaseFoldedOrderedDict, self).__setitem__(_casefold(key), value)
def __contains__(self, key):
return super(CaseFoldedOrderedDict, self).__contains__(_casefold(key))
def get(self, key, default=None):
return super(CaseFoldedOrderedDict, self).get(_casefold(key), default)
def pop(self, key, default=None):
return super(CaseFoldedOrderedDict, self).pop(_casefold(key), default)
def _group_pairs(tokens):
i = 0
while i < len(tokens) - 2:
if tokens[i][0] == 'token' and \
tokens[i+1][0] == 'equals' and \
tokens[i+2][0] == 'token':
tokens[i:i+3] = [('pair', (tokens[i][1], tokens[i+2][1]))]
i += 1
def _group_challenges(tokens):
challenges = []
while tokens:
j = 1
if len(tokens) == 1:
pass
elif tokens[1][0] == 'comma':
pass
elif tokens[1][0] == 'token':
j = 2
else:
while j < len(tokens) and tokens[j][0] == 'pair':
j += 2
j -= 1
challenges.append((tokens[0][1], tokens[1:j]))
tokens[:j+1] = []
return challenges
def parse(value):
tokens = []
while value:
for token_name, pattern in _tokens:
match = pattern.match(value)
if match:
value = value[match.end():]
if token_name:
tokens.append((token_name, match.group(1)))
break
else:
raise ValueError("Failed to parse value")
_group_pairs(tokens)
challenges = CaseFoldedOrderedDict()
for name, tokens in _group_challenges(tokens):
args, kwargs = [], {}
for token_name, value in tokens:
if token_name == 'token':
args.append(value)
elif token_name == 'pair':
kwargs[value[0]] = value[1]
challenges[name] = (args and args[0]) or kwargs or None
return challenges