AbstractUnicodeExtraField.php 3.3 KB

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