View file vendor/nelexa/zip/src/Model/Extra/Fields/ApkAlignmentExtraField.php

File size: 4.25Kb
  1. <?php
  2.  
  3. namespace PhpZip\Model\Extra\Fields;
  4.  
  5. use PhpZip\Exception\ZipException;
  6. use PhpZip\Model\Extra\ZipExtraField;
  7. use PhpZip\Model\ZipEntry;
  8.  
  9. /**
  10. * Apk Alignment Extra Field.
  11. *
  12. * @see https://android.googlesource.com/platform/tools/apksig/+/master/src/main/java/com/android/apksig/ApkSigner.java
  13. * @see https://developer.android.com/studio/command-line/zipalign
  14. */
  15. class ApkAlignmentExtraField implements ZipExtraField
  16. {
  17. /**
  18. * @var int Extensible data block/field header ID used for storing
  19. * information about alignment of uncompressed entries as
  20. * well as for aligning the entries's data. See ZIP
  21. * appnote.txt section 4.5 Extensible data fields.
  22. */
  23. const HEADER_ID = 0xd935;
  24.  
  25. /**
  26. * @var int minimum size (in bytes) of the extensible data block/field used
  27. * for alignment of uncompressed entries
  28. */
  29. const MIN_SIZE = 6;
  30.  
  31. /** @var int */
  32. const ALIGNMENT_BYTES = 4;
  33.  
  34. /** @var int */
  35. const COMMON_PAGE_ALIGNMENT_BYTES = 4096;
  36.  
  37. /** @var int */
  38. private $multiple;
  39.  
  40. /** @var int */
  41. private $padding;
  42.  
  43. /**
  44. * @param int $multiple
  45. * @param int $padding
  46. */
  47. public function __construct($multiple, $padding)
  48. {
  49. $this->multiple = $multiple;
  50. $this->padding = $padding;
  51. }
  52.  
  53. /**
  54. * Returns the Header ID (type) of this Extra Field.
  55. * The Header ID is an unsigned short integer (two bytes)
  56. * which must be constant during the life cycle of this object.
  57. *
  58. * @return int
  59. */
  60. public function getHeaderId()
  61. {
  62. return self::HEADER_ID;
  63. }
  64.  
  65. /**
  66. * @return int
  67. */
  68. public function getMultiple()
  69. {
  70. return $this->multiple;
  71. }
  72.  
  73. /**
  74. * @return int
  75. */
  76. public function getPadding()
  77. {
  78. return $this->padding;
  79. }
  80.  
  81. /**
  82. * @param int $multiple
  83. */
  84. public function setMultiple($multiple)
  85. {
  86. $this->multiple = (int) $multiple;
  87. }
  88.  
  89. /**
  90. * @param int $padding
  91. */
  92. public function setPadding($padding)
  93. {
  94. $this->padding = (int) $padding;
  95. }
  96.  
  97. /**
  98. * Populate data from this array as if it was in local file data.
  99. *
  100. * @param string $buffer the buffer to read data from
  101. * @param ZipEntry|null $entry
  102. *
  103. * @throws ZipException
  104. *
  105. * @return ApkAlignmentExtraField
  106. */
  107. public static function unpackLocalFileData($buffer, ZipEntry $entry = null)
  108. {
  109. $length = \strlen($buffer);
  110.  
  111. if ($length < 2) {
  112. // This is APK alignment field.
  113. // FORMAT:
  114. // * uint16 alignment multiple (in bytes)
  115. // * remaining bytes -- padding to achieve alignment of data which starts after
  116. // the extra field
  117. throw new ZipException(
  118. 'Minimum 6 bytes of the extensible data block/field used for alignment of uncompressed entries.'
  119. );
  120. }
  121. $multiple = unpack('v', $buffer)[1];
  122. $padding = $length - 2;
  123.  
  124. return new self($multiple, $padding);
  125. }
  126.  
  127. /**
  128. * Populate data from this array as if it was in central directory data.
  129. *
  130. * @param string $buffer the buffer to read data from
  131. * @param ZipEntry|null $entry
  132. *
  133. * @throws ZipException on error
  134. *
  135. * @return ApkAlignmentExtraField
  136. */
  137. public static function unpackCentralDirData($buffer, ZipEntry $entry = null)
  138. {
  139. return self::unpackLocalFileData($buffer, $entry);
  140. }
  141.  
  142. /**
  143. * The actual data to put into local file data - without Header-ID
  144. * or length specifier.
  145. *
  146. * @return string the data
  147. */
  148. public function packLocalFileData()
  149. {
  150. return pack('vx' . $this->padding, $this->multiple);
  151. }
  152.  
  153. /**
  154. * The actual data to put into central directory - without Header-ID or
  155. * length specifier.
  156. *
  157. * @return string the data
  158. */
  159. public function packCentralDirData()
  160. {
  161. return $this->packLocalFileData();
  162. }
  163.  
  164. /**
  165. * @return string
  166. */
  167. public function __toString()
  168. {
  169. return sprintf(
  170. '0x%04x APK Alignment: Multiple=%d Padding=%d',
  171. self::HEADER_ID,
  172. $this->multiple,
  173. $this->padding
  174. );
  175. }
  176. }