Parse a Content-type like header. Return the main content-type and a dictionary of options. If `line` is longer than `max_length`, `ValueError` is raised.
(line, max_length=MAX_HEADER_LENGTH)
| 330 | |
| 331 | |
| 332 | def parse_header_parameters(line, max_length=MAX_HEADER_LENGTH): |
| 333 | """ |
| 334 | Parse a Content-type like header. |
| 335 | Return the main content-type and a dictionary of options. |
| 336 | |
| 337 | If `line` is longer than `max_length`, `ValueError` is raised. |
| 338 | """ |
| 339 | if not line: |
| 340 | return "", {} |
| 341 | |
| 342 | if max_length is not None and len(line) > max_length: |
| 343 | raise ValueError("Unable to parse header parameters (value too long).") |
| 344 | |
| 345 | # Fast path for no params. |
| 346 | if ";" not in line: |
| 347 | return line.strip().lower(), {} |
| 348 | |
| 349 | parts = _parseparam(";" + line) |
| 350 | key = parts.__next__().lower() |
| 351 | pdict = {} |
| 352 | for p in parts: |
| 353 | i = p.find("=") |
| 354 | if i >= 0: |
| 355 | has_encoding = False |
| 356 | name = p[:i].strip().lower() |
| 357 | if name.endswith("*"): |
| 358 | # Embedded lang/encoding, like "filename*=UTF-8''file.ext". |
| 359 | # https://tools.ietf.org/html/rfc2231#section-4 |
| 360 | name = name[:-1] |
| 361 | if p.count("'") == 2: |
| 362 | has_encoding = True |
| 363 | value = p[i + 1 :].strip() |
| 364 | if len(value) >= 2 and value[0] == value[-1] == '"': |
| 365 | value = value[1:-1] |
| 366 | value = value.replace("\\\\", "\\").replace('\\"', '"') |
| 367 | if has_encoding: |
| 368 | encoding, lang, value = value.split("'") |
| 369 | try: |
| 370 | value = unquote(value, encoding=encoding) |
| 371 | except (LookupError, UnicodeDecodeError): |
| 372 | msg = f"Invalid encoding {encoding!r} for RFC 2231 param." |
| 373 | raise ValueError(msg) |
| 374 | pdict[name] = value |
| 375 | return key, pdict |
| 376 | |
| 377 | |
| 378 | def content_disposition_header(as_attachment, filename): |