Process an extended or global header as described in POSIX.1-2008.
(self, tarfile)
| 1397 | return self |
| 1398 | |
| 1399 | def _proc_pax(self, tarfile): |
| 1400 | """Process an extended or global header as described in |
| 1401 | POSIX.1-2008. |
| 1402 | """ |
| 1403 | # Read the header information. |
| 1404 | buf = tarfile.fileobj.read(self._block(self.size)) |
| 1405 | |
| 1406 | # A pax header stores supplemental information for either |
| 1407 | # the following file (extended) or all following files |
| 1408 | # (global). |
| 1409 | if self.type == XGLTYPE: |
| 1410 | pax_headers = tarfile.pax_headers |
| 1411 | else: |
| 1412 | pax_headers = tarfile.pax_headers.copy() |
| 1413 | |
| 1414 | # Check if the pax header contains a hdrcharset field. This tells us |
| 1415 | # the encoding of the path, linkpath, uname and gname fields. Normally, |
| 1416 | # these fields are UTF-8 encoded but since POSIX.1-2008 tar |
| 1417 | # implementations are allowed to store them as raw binary strings if |
| 1418 | # the translation to UTF-8 fails. |
| 1419 | match = re.search(br"\d+ hdrcharset=([^\n]+)\n", buf) |
| 1420 | if match is not None: |
| 1421 | pax_headers["hdrcharset"] = match.group(1).decode("utf-8") |
| 1422 | |
| 1423 | # For the time being, we don't care about anything other than "BINARY". |
| 1424 | # The only other value that is currently allowed by the standard is |
| 1425 | # "ISO-IR 10646 2000 UTF-8" in other words UTF-8. |
| 1426 | hdrcharset = pax_headers.get("hdrcharset") |
| 1427 | if hdrcharset == "BINARY": |
| 1428 | encoding = tarfile.encoding |
| 1429 | else: |
| 1430 | encoding = "utf-8" |
| 1431 | |
| 1432 | # Parse pax header information. A record looks like that: |
| 1433 | # "%d %s=%s\n" % (length, keyword, value). length is the size |
| 1434 | # of the complete record including the length field itself and |
| 1435 | # the newline. keyword and value are both UTF-8 encoded strings. |
| 1436 | regex = re.compile(br"(\d+) ([^=]+)=") |
| 1437 | pos = 0 |
| 1438 | while True: |
| 1439 | match = regex.match(buf, pos) |
| 1440 | if not match: |
| 1441 | break |
| 1442 | |
| 1443 | length, keyword = match.groups() |
| 1444 | length = int(length) |
| 1445 | if length == 0: |
| 1446 | raise InvalidHeaderError("invalid header") |
| 1447 | value = buf[match.end(2) + 1:match.start(1) + length - 1] |
| 1448 | |
| 1449 | # Normally, we could just use "utf-8" as the encoding and "strict" |
| 1450 | # as the error handler, but we better not take the risk. For |
| 1451 | # example, GNU tar <= 1.23 is known to store filenames it cannot |
| 1452 | # translate to UTF-8 as raw strings (unfortunately without a |
| 1453 | # hdrcharset=BINARY header). |
| 1454 | # We first try the strict standard encoding, and if that fails we |
| 1455 | # fall back on the user's encoding and error handler. |
| 1456 | keyword = self._decode_pax_field(keyword, "utf-8", "utf-8", |
no test coverage detected