|
23 | 23 | # Visit https://github.com/package-url/packageurl-python for support and
|
24 | 24 | # download.
|
25 | 25 |
|
| 26 | + |
26 | 27 | from __future__ import absolute_import
|
27 | 28 | from __future__ import print_function
|
28 | 29 | from __future__ import unicode_literals
|
29 | 30 |
|
30 | 31 | from collections import namedtuple
|
31 | 32 | from collections import OrderedDict
|
| 33 | +import string |
32 | 34 |
|
33 | 35 | # Python 2 and 3 support
|
34 | 36 | try:
|
@@ -172,9 +174,31 @@ def normalize_qualifiers(qualifiers, encode=True): # NOQA
|
172 | 174 | 'Must be a string or dict:{}'.format(repr(qualifiers)))
|
173 | 175 |
|
174 | 176 | quoter = get_quoter(encode)
|
175 |
| - qualifiers = {quoter(k.strip().lower()): quoter(v) |
| 177 | + qualifiers = {k.strip().lower(): quoter(v) |
176 | 178 | for k, v in qualifiers if k and k.strip() and v and v.strip()}
|
177 | 179 |
|
| 180 | + valid_chars = string.ascii_letters + string.digits + '.-_' |
| 181 | + for key in qualifiers: |
| 182 | + if not key: |
| 183 | + raise ValueError('A qualifier key cannot be empty') |
| 184 | + |
| 185 | + if '%' in key: |
| 186 | + raise ValueError( |
| 187 | + "A qualifier key cannot be percent encoded: {}".format(repr(key))) |
| 188 | + |
| 189 | + if ' ' in key: |
| 190 | + raise ValueError( |
| 191 | + "A qualifier key cannot contain spaces: {}".format(repr(key))) |
| 192 | + |
| 193 | + if not all(c in valid_chars for c in key): |
| 194 | + raise ValueError( |
| 195 | + "A qualifier key must be composed only of ASCII letters and numbers" |
| 196 | + "period, dash and underscore: {}".format(repr(key))) |
| 197 | + |
| 198 | + if key[0] in string.digits: |
| 199 | + raise ValueError( |
| 200 | + "A qualifier key cannot start with a number: {}".format(repr(key))) |
| 201 | + |
178 | 202 | if encode:
|
179 | 203 | qualifiers = sorted(qualifiers.items())
|
180 | 204 | qualifiers = ['{}={}'.format(k, v) for k, v in qualifiers]
|
|
0 commit comments