AbstractUnicodeExtraField.php 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4. * This file is part of the nelexa/zip package.
  5. * (c) Ne-Lexa <https://github.com/Ne-Lexa/php-zip>
  6. * For the full copyright and license information, please view the LICENSE
  7. * file that was distributed with this source code.
  8. */
  9. namespace PhpZip\Model\Extra\Fields;
  10. use PhpZip\Exception\ZipException;
  11. use PhpZip\Model\Extra\ZipExtraField;
  12. use PhpZip\Model\ZipEntry;
  13. /**
  14. * A common base class for Unicode extra information extra fields.
  15. */
  16. abstract class AbstractUnicodeExtraField implements ZipExtraField
  17. {
  18. public const DEFAULT_VERSION = 0x01;
  19. private int $crc32;
  20. private string $unicodeValue;
  21. public function __construct(int $crc32, string $unicodeValue)
  22. {
  23. $this->crc32 = $crc32;
  24. $this->unicodeValue = $unicodeValue;
  25. }
  26. /**
  27. * @return int the CRC32 checksum of the filename or comment as
  28. * encoded in the central directory of the zip file
  29. */
  30. public function getCrc32(): int
  31. {
  32. return $this->crc32;
  33. }
  34. public function setCrc32(int $crc32): void
  35. {
  36. $this->crc32 = $crc32;
  37. }
  38. public function getUnicodeValue(): string
  39. {
  40. return $this->unicodeValue;
  41. }
  42. /**
  43. * @param string $unicodeValue the UTF-8 encoded name to set
  44. */
  45. public function setUnicodeValue(string $unicodeValue): void
  46. {
  47. $this->unicodeValue = $unicodeValue;
  48. }
  49. /**
  50. * Populate data from this array as if it was in local file data.
  51. *
  52. * @param string $buffer the buffer to read data from
  53. * @param ZipEntry|null $entry optional zip entry
  54. *
  55. * @throws ZipException on error
  56. *
  57. * @return static
  58. */
  59. public static function unpackLocalFileData(string $buffer, ?ZipEntry $entry = null): self
  60. {
  61. if (\strlen($buffer) < 5) {
  62. throw new ZipException('Unicode path extra data must have at least 5 bytes.');
  63. }
  64. [
  65. 'version' => $version,
  66. 'crc32' => $crc32,
  67. ] = unpack('Cversion/Vcrc32', $buffer);
  68. if ($version !== self::DEFAULT_VERSION) {
  69. throw new ZipException(sprintf('Unsupported version [%d] for Unicode path extra data.', $version));
  70. }
  71. $unicodeValue = substr($buffer, 5);
  72. return new static($crc32, $unicodeValue);
  73. }
  74. /**
  75. * Populate data from this array as if it was in central directory data.
  76. *
  77. * @param string $buffer the buffer to read data from
  78. * @param ZipEntry|null $entry optional zip entry
  79. *
  80. * @throws ZipException on error
  81. *
  82. * @return static
  83. */
  84. public static function unpackCentralDirData(string $buffer, ?ZipEntry $entry = null): self
  85. {
  86. return self::unpackLocalFileData($buffer, $entry);
  87. }
  88. /**
  89. * The actual data to put into local file data - without Header-ID
  90. * or length specifier.
  91. *
  92. * @return string the data
  93. */
  94. public function packLocalFileData(): string
  95. {
  96. return pack(
  97. 'CV',
  98. self::DEFAULT_VERSION,
  99. $this->crc32
  100. )
  101. . $this->unicodeValue;
  102. }
  103. /**
  104. * The actual data to put into central directory - without Header-ID or
  105. * length specifier.
  106. *
  107. * @return string the data
  108. */
  109. public function packCentralDirData(): string
  110. {
  111. return $this->packLocalFileData();
  112. }
  113. }