40 if key in self: |
40 if key in self: |
41 raise DuplicateParamError(key) |
41 raise DuplicateParamError(key) |
42 super().__setitem__(key, value) |
42 super().__setitem__(key, value) |
43 |
43 |
44 # RFC 2616 |
44 # RFC 2616 |
45 separator_chars = "()<>@,;:\\\"/[]?={} \t" |
45 separator_chars = "()<>@,;:\\\"/[]?={} \t" # __IGNORE_WARNING__ |
46 ctl_chars = ''.join(chr(i) for i in range(32)) + chr(127) |
46 ctl_chars = ''.join(chr(i) for i in range(32)) + chr(127) |
47 nontoken_chars = separator_chars + ctl_chars |
47 nontoken_chars = separator_chars + ctl_chars |
48 |
48 |
49 # RFC 5987 |
49 # RFC 5987 |
50 attr_chars_nonalnum = '!#$&+-.^_`|~' |
50 attr_chars_nonalnum = '!#$&+-.^_`|~' |
51 attr_chars = string.ascii_letters + string.digits + attr_chars_nonalnum |
51 attr_chars = string.ascii_letters + string.digits + attr_chars_nonalnum |
52 |
52 |
53 # RFC 5987 gives this alternative construction of the token character class |
53 # RFC 5987 gives this alternative construction of the token character class |
54 token_chars = attr_chars + "*'%" |
54 token_chars = attr_chars + "*'%" # __IGNORE_WARNING__ |
55 |
55 |
56 # Definitions from https://tools.ietf.org/html/rfc2616#section-2.2 |
56 # Definitions from https://tools.ietf.org/html/rfc2616#section-2.2 |
57 # token was redefined from attr_chars to avoid using AnyBut, |
57 # token was redefined from attr_chars to avoid using AnyBut, |
58 # which might include non-ascii octets. |
58 # which might include non-ascii octets. |
59 token_re = '[{}]+'.format(re.escape(token_chars)) |
59 token_re = '[{0}]+'.format(re.escape(token_chars)) |
60 |
60 |
61 class Token(str): |
61 class Token(str): |
62 """ |
62 """ |
63 A token (RFC 2616, Section 2.2). |
63 A token (RFC 2616, Section 2.2). |
64 """ |
64 """ |
75 # because the spec only allows iso, and because encoding-sniffing |
75 # because the spec only allows iso, and because encoding-sniffing |
76 # can mangle valid values. |
76 # can mangle valid values. |
77 # Everything else in this grammar (including RFC 5987 ext values) |
77 # Everything else in this grammar (including RFC 5987 ext values) |
78 # is in an ascii-safe encoding. |
78 # is in an ascii-safe encoding. |
79 |
79 |
80 qdtext_re = r'[^"{}]'.format(re.escape(ctl_chars)) |
80 qdtext_re = r'[^"{0}]'.format(re.escape(ctl_chars)) |
81 quoted_pair_re = r'\\[{}]'.format(re.escape( |
81 quoted_pair_re = r'\\[{0}]'.format(re.escape( |
82 ''.join(chr(i) for i in range(128)))) |
82 ''.join(chr(i) for i in range(128)))) |
83 |
83 |
84 class QuotedString(str): |
84 class QuotedString(str): |
85 """ |
85 """ |
86 A quoted string (RFC 2616, Section 2.2). |
86 A quoted string (RFC 2616, Section 2.2). |
87 """ |
87 """ |
88 grammar = re.compile(r'"({}|{})+"'.format(quoted_pair_re, qdtext_re)) |
88 grammar = re.compile(r'"({0}|{1})+"'.format(quoted_pair_re, qdtext_re)) |
89 |
89 |
90 def __str__(self): |
90 def __str__(self): |
91 s = super().__str__() |
91 s = super().__str__() |
92 s = s[1:-1] # remove quotes |
92 s = s[1:-1] # remove quotes |
93 s = re.sub(r'\\(.)', r'\1', s) # drop backslashes |
93 s = re.sub(r'\\(.)', r'\1', s) # drop backslashes |
114 Fixme: This grammar is not 100% correct yet. |
114 Fixme: This grammar is not 100% correct yet. |
115 https://github.com/The-Compiler/qutebrowser/issues/105 |
115 https://github.com/The-Compiler/qutebrowser/issues/105 |
116 """ |
116 """ |
117 grammar = re.compile('[A-Za-z0-9-]+') |
117 grammar = re.compile('[A-Za-z0-9-]+') |
118 |
118 |
119 attr_char_re = '[{}]'.format(re.escape(attr_chars)) |
119 attr_char_re = '[{0}]'.format(re.escape(attr_chars)) |
120 hex_digit_re = '%[' + string.hexdigits + ']{2}' |
120 hex_digit_re = '%[' + string.hexdigits + ']{2}' |
121 |
121 |
122 class ValueChars(str): |
122 class ValueChars(str): |
123 """ |
123 """ |
124 A value of an attribute. |
124 A value of an attribute. |
125 |
125 |
126 Fixme: Can we merge this with Value? |
126 Fixme: Can we merge this with Value? |
127 https://github.com/The-Compiler/qutebrowser/issues/105 |
127 https://github.com/The-Compiler/qutebrowser/issues/105 |
128 """ |
128 """ |
129 grammar = re.compile('({}|{})*'.format(attr_char_re, hex_digit_re)) |
129 grammar = re.compile('({0}|{1})*'.format(attr_char_re, hex_digit_re)) |
130 |
130 |
131 class ExtValue(peg.List): |
131 class ExtValue(peg.List): |
132 """ |
132 """ |
133 An ext-value of an attribute (RFC 5987, Section 3.2). |
133 An ext-value of an attribute (RFC 5987, Section 3.2). |
134 """ |
134 """ |