NtfsExtraField.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <?php
  2. namespace PhpZip\Extra;
  3. use PhpZip\Exception\ZipException;
  4. use PhpZip\Util\PackUtil;
  5. /**
  6. * NTFS Extra Field
  7. *
  8. * @see https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT .ZIP File Format Specification
  9. * @author Ne-Lexa alexey@nelexa.ru
  10. * @license MIT
  11. */
  12. class NtfsExtraField extends ExtraField
  13. {
  14. /**
  15. * Modify time
  16. *
  17. * @var int Unix Timestamp
  18. */
  19. private $mtime;
  20. /**
  21. * Access Time
  22. *
  23. * @var int Unix Timestamp
  24. */
  25. private $atime;
  26. /**
  27. * Create Time
  28. *
  29. * @var int Unix Time
  30. */
  31. private $ctime;
  32. /**
  33. * @var string
  34. */
  35. private $rawData = "";
  36. /**
  37. * Returns the Header ID (type) of this Extra Field.
  38. * The Header ID is an unsigned short integer (two bytes)
  39. * which must be constant during the life cycle of this object.
  40. *
  41. * @return int
  42. */
  43. public static function getHeaderId()
  44. {
  45. return 0x000a;
  46. }
  47. /**
  48. * Returns the Data Size of this Extra Field.
  49. * The Data Size is an unsigned short integer (two bytes)
  50. * which indicates the length of the Data Block in bytes and does not
  51. * include its own size in this Extra Field.
  52. * This property may be initialized by calling ExtraField::readFrom.
  53. *
  54. * @return int The size of the Data Block in bytes
  55. * or 0 if unknown.
  56. */
  57. public function getDataSize()
  58. {
  59. return 8 * 4 + strlen($this->rawData);
  60. }
  61. /**
  62. * Initializes this Extra Field by deserializing a Data Block of
  63. * size bytes $size from the resource $handle at the zero based offset $off.
  64. *
  65. * @param resource $handle
  66. * @param int $off Offset bytes
  67. * @param int $size Size
  68. * @throws ZipException If size out of range
  69. */
  70. public function readFrom($handle, $off, $size)
  71. {
  72. if (0x0000 > $size || $size > 0xffff) {
  73. throw new ZipException('size out of range');
  74. }
  75. if ($size > 0) {
  76. $off += 4;
  77. fseek($handle, $off, SEEK_SET);
  78. $unpack = unpack('vtag/vsizeAttr', fread($handle, 4));
  79. if (24 === $unpack['sizeAttr']) {
  80. $tagData = fread($handle, $unpack['sizeAttr']);
  81. $this->mtime = PackUtil::unpackLongLE(substr($tagData, 0, 8)) / 10000000 - 11644473600;
  82. $this->atime = PackUtil::unpackLongLE(substr($tagData, 8, 8)) / 10000000 - 11644473600;
  83. $this->ctime = PackUtil::unpackLongLE(substr($tagData, 16, 8)) / 10000000 - 11644473600;
  84. }
  85. $off += $unpack['sizeAttr'];
  86. if ($size > $off) {
  87. $this->rawData .= fread($handle, $size - $off);
  88. }
  89. }
  90. }
  91. /**
  92. * Serializes a Data Block of ExtraField::getDataSize bytes to the
  93. * resource $handle at the zero based offset $off.
  94. *
  95. * @param resource $handle
  96. * @param int $off Offset bytes
  97. */
  98. public function writeTo($handle, $off)
  99. {
  100. if (null !== $this->mtime && null !== $this->atime && null !== $this->ctime) {
  101. fseek($handle, $off, SEEK_SET);
  102. fwrite($handle, pack('Vvv', 0, 1, 8 * 3 + strlen($this->rawData)));
  103. $mtimeLong = ($this->mtime + 11644473600) * 10000000;
  104. fwrite($handle, PackUtil::packLongLE($mtimeLong));
  105. $atimeLong = ($this->atime + 11644473600) * 10000000;
  106. fwrite($handle, PackUtil::packLongLE($atimeLong));
  107. $ctimeLong = ($this->ctime + 11644473600) * 10000000;
  108. fwrite($handle, PackUtil::packLongLE($ctimeLong));
  109. if (!empty($this->rawData)) {
  110. fwrite($handle, $this->rawData);
  111. }
  112. }
  113. }
  114. /**
  115. * @return int
  116. */
  117. public function getMtime()
  118. {
  119. return $this->mtime;
  120. }
  121. /**
  122. * @param int $mtime
  123. */
  124. public function setMtime($mtime)
  125. {
  126. $this->mtime = (int)$mtime;
  127. }
  128. /**
  129. * @return int
  130. */
  131. public function getAtime()
  132. {
  133. return $this->atime;
  134. }
  135. /**
  136. * @param int $atime
  137. */
  138. public function setAtime($atime)
  139. {
  140. $this->atime = (int)$atime;
  141. }
  142. /**
  143. * @return int
  144. */
  145. public function getCtime()
  146. {
  147. return $this->ctime;
  148. }
  149. /**
  150. * @param int $ctime
  151. */
  152. public function setCtime($ctime)
  153. {
  154. $this->ctime = (int)$ctime;
  155. }
  156. }