Decode parameters list according to RFC 2231. params is a sequence of 2-tuples containing (param name, string value).
(params)
| 393 | re.ASCII) |
| 394 | |
| 395 | def decode_params(params): |
| 396 | """Decode parameters list according to RFC 2231. |
| 397 | |
| 398 | params is a sequence of 2-tuples containing (param name, string value). |
| 399 | """ |
| 400 | new_params = [params[0]] |
| 401 | # Map parameter's name to a list of continuations. The values are a |
| 402 | # 3-tuple of the continuation number, the string value, and a flag |
| 403 | # specifying whether a particular segment is %-encoded. |
| 404 | rfc2231_params = {} |
| 405 | for name, value in params[1:]: |
| 406 | encoded = name.endswith('*') |
| 407 | value = unquote(value) |
| 408 | mo = rfc2231_continuation.match(name) |
| 409 | if mo: |
| 410 | name, num = mo.group('name', 'num') |
| 411 | if num is not None: |
| 412 | num = int(num) |
| 413 | rfc2231_params.setdefault(name, []).append((num, value, encoded)) |
| 414 | else: |
| 415 | new_params.append((name, '"%s"' % quote(value))) |
| 416 | if rfc2231_params: |
| 417 | for name, continuations in rfc2231_params.items(): |
| 418 | value = [] |
| 419 | extended = False |
| 420 | # Sort by number, treating None as 0 if there is no 0, |
| 421 | # and ignore it if there is already a 0. |
| 422 | has_zero = any(x[0] == 0 for x in continuations) |
| 423 | if has_zero: |
| 424 | continuations = [x for x in continuations if x[0] is not None] |
| 425 | else: |
| 426 | continuations = [(x[0] or 0, x[1], x[2]) for x in continuations] |
| 427 | continuations.sort(key=lambda x: x[0]) |
| 428 | # And now append all values in numerical order, converting |
| 429 | # %-encodings for the encoded segments. If any of the |
| 430 | # continuation names ends in a *, then the entire string, after |
| 431 | # decoding segments and concatenating, must have the charset and |
| 432 | # language specifiers at the beginning of the string. |
| 433 | for num, s, encoded in continuations: |
| 434 | if encoded: |
| 435 | # Decode as "latin-1", so the characters in s directly |
| 436 | # represent the percent-encoded octet values. |
| 437 | # collapse_rfc2231_value treats this as an octet sequence. |
| 438 | s = urllib.parse.unquote(s, encoding="latin-1") |
| 439 | extended = True |
| 440 | value.append(s) |
| 441 | value = quote(EMPTYSTRING.join(value)) |
| 442 | if extended: |
| 443 | charset, language, value = decode_rfc2231(value) |
| 444 | new_params.append((name, (charset, language, '"%s"' % value))) |
| 445 | else: |
| 446 | new_params.append((name, '"%s"' % value)) |
| 447 | return new_params |
| 448 | |
| 449 | def collapse_rfc2231_value(value, errors='replace', |
| 450 | fallback_charset='us-ascii'): |
nothing calls this directly
no test coverage detected
searching dependent graphs…