PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/php/PEAR2/Pyrus/Developer/Creator/Phar.php

https://github.com/boekkooi/PEAR2_Pyrus
PHP | 218 lines | 181 code | 6 blank | 31 comment | 17 complexity | 1021abe411836d9bea3ab1243f84e713 MD5 | raw file
  1. <?php
  2. namespace PEAR2\Pyrus\Developer\Creator;
  3. class Phar implements \PEAR2\Pyrus\Package\CreatorInterface
  4. {
  5. /**
  6. * @var Phar
  7. */
  8. protected $phar;
  9. protected $others;
  10. protected $path;
  11. protected $stub;
  12. protected $format;
  13. protected $compression;
  14. protected $pkcs12;
  15. protected $passphrase;
  16. protected $x509cert;
  17. protected $publickey;
  18. private $_classname = 'Phar';
  19. private $_started = false;
  20. /**
  21. * Archive creator for phar, tar, tgz and zip archives.
  22. *
  23. * @param string path to primary archive
  24. * @param string|false stub or false to use default stub of phar archives
  25. * @param int one of Phar::TAR, Phar::PHAR, or Phar::ZIP
  26. * @param int if the archive can be compressed (phar and tar), one of Phar::GZ, Phar::BZ2 or Phar::NONE
  27. * for no compression
  28. * @param array an array of arrays containing information on additional archives to create. The indices are:
  29. *
  30. * 0. extension (tar/tgz/zip)
  31. * 1. format (Phar::TAR, Phar::ZIP, Phar::PHAR)
  32. * 2. compression (Phar::GZ, Phar::BZ2, Phar::NONE)
  33. * @param string PKCS12 certificate to be used to sign the archive. This must be a certificate issued
  34. * by a certificate authority, self-signed certs will not be accepted by Pyrus
  35. * @param string passphrase, if any, for the PKCS12 certificate.
  36. */
  37. function __construct($path, $stub = false, $fileformat = \Phar::TAR, $compression = \Phar::GZ, array $others = null,
  38. $releaser = null, \PEAR2\Pyrus\Package $new = null, $pkcs12 = null, $passphrase = '')
  39. {
  40. if (!class_exists('Phar')) {
  41. throw new \PEAR2\Pyrus\Developer\Creator\Exception(
  42. 'Phar extension is not available');
  43. }
  44. if (!\Phar::canWrite() || !\Phar::isValidPharFilename($path, true)) {
  45. $this->_classname = 'PharData';
  46. }
  47. $this->path = $path;
  48. $this->compression = $compression;
  49. $this->format = $fileformat;
  50. $this->others = $others;
  51. $this->stub = $stub;
  52. if ($pkcs12 && !extension_loaded('openssl')) {
  53. throw new \PEAR2\Pyrus\Developer\Creator\Exception('Unable to use ' .
  54. 'OpenSSL signing of phars, enable the openssl PHP extension');
  55. }
  56. $this->pkcs12 = $pkcs12;
  57. $this->passphrase = $passphrase;
  58. if (null !== $this->pkcs12) {
  59. $cert = array();
  60. $pkcs = openssl_pkcs12_read(file_get_contents($this->pkcs12), $cert, $this->passphrase);
  61. if (!$pkcs) {
  62. throw new \PEAR2\Pyrus\Developer\Creator\Exception('Unable to process openssl key');
  63. }
  64. $private = openssl_pkey_get_private($cert['pkey']);
  65. if (!$private) {
  66. throw new \PEAR2\Pyrus\Developer\Creator\Exception('Unable to extract private openssl key');
  67. }
  68. $pub = openssl_pkey_get_public($cert['cert']);
  69. $info = openssl_x509_parse($cert['cert']);
  70. $details = openssl_pkey_get_details($pub);
  71. if (true !== openssl_x509_checkpurpose($cert['cert'], X509_PURPOSE_SSL_SERVER,
  72. \PEAR2\Pyrus\Channel\RemotePackage::authorities())) {
  73. throw new \PEAR2\Pyrus\Developer\Creator\Exception(
  74. 'releasing maintainer\'s certificate is invalid');
  75. }
  76. // now verify that this cert is in fact the releasing maintainer's certificate
  77. // by verifying that alternate name is the releaser's email address
  78. if (!isset($info['subject']) || !isset($info['subject']['emailAddress'])) {
  79. throw new \PEAR2\Pyrus\Developer\Creator\Exception(
  80. 'releasing maintainer\'s certificate does not contain' .
  81. ' an alternate name corresponding to the releaser\'s email address');
  82. }
  83. if ($info['subject']['emailAddress'] != $new->maintainer[$releaser]->email) {
  84. throw new \PEAR2\Pyrus\Developer\Creator\Exception(
  85. 'releasing maintainer\'s certificate ' .
  86. 'alternate name does not match the releaser\'s email address ' .
  87. $new->maintainer[$releaser]->email);
  88. }
  89. $pkey = '';
  90. openssl_pkey_export($private, $pkey);
  91. $this->x509cert = $cert['cert'];
  92. $this->publickey = $details['key'];
  93. $this->privatekey = $pkey;
  94. }
  95. }
  96. /**
  97. * save a file inside this package
  98. * @param string relative path within the package
  99. * @param string|resource file contents or open file handle
  100. */
  101. function addFile($path, $fileOrStream)
  102. {
  103. if (!$this->_started) {
  104. // save package.xml name
  105. $this->phar->setMetadata($path);
  106. $this->_started = true;
  107. }
  108. $this->phar[$path] = $fileOrStream;
  109. }
  110. function addDir($path)
  111. {
  112. $this->phar->buildFromDirectory($path);
  113. }
  114. /**
  115. * Initialize the package creator
  116. */
  117. function init()
  118. {
  119. try {
  120. if (file_exists($this->path)) {
  121. @unlink($this->path);
  122. }
  123. $ext = strstr(strrchr($this->path, '-'), '.');
  124. if (!$ext) {
  125. $ext = strstr(strrchr($this->path, '/'), '.');
  126. if (!$ext) {
  127. $ext = strstr(strrchr($this->path, '\\'), '.');
  128. }
  129. }
  130. if (!$ext) {
  131. $ext = strstr($this->path, '.');
  132. }
  133. $a = $this->_classname;
  134. $this->phar = new $a($this->path);
  135. if ($this->phar instanceof \Phar) {
  136. $this->phar = $this->phar->convertToExecutable($this->format,
  137. $this->compression, $ext);
  138. } else {
  139. $this->phar = $this->phar->convertToData($this->format,
  140. $this->compression, $ext);
  141. }
  142. $this->phar->startBuffering();
  143. if ($this->phar instanceof \Phar && $this->stub) {
  144. $this->phar->setStub($this->stub);
  145. }
  146. } catch (Exception $e) {
  147. throw new \PEAR2\Pyrus\Developer\Creator\Exception(
  148. 'Cannot open Phar archive ' . $this->path, $e
  149. );
  150. }
  151. $this->_started = false;
  152. }
  153. /**
  154. * Create an internal directory, creating parent directories as needed
  155. *
  156. * @param string $dir
  157. */
  158. function mkdir($dir)
  159. {
  160. $this->phar->addEmptyDir($dir);
  161. }
  162. /**
  163. * Finish saving the package
  164. */
  165. function close()
  166. {
  167. if ($this->phar->isFileFormat(\Phar::ZIP) && $this->compression !== \Phar::NONE) {
  168. $this->phar->compressFiles($this->compression);
  169. }
  170. if (null !== $this->pkcs12) {
  171. $certpath = str_replace(array('.tar', '.zip', '.tgz', '.phar'), array('', '', '', ''), $this->path);
  172. $this->phar->setSignatureAlgorithm(\Phar::OPENSSL, $this->privatekey);
  173. file_put_contents($certpath . '.pem', $this->x509cert);
  174. file_put_contents($this->path . '.pubkey', $this->publickey);
  175. } elseif (!$this->phar->isFileFormat(\Phar::ZIP)) {
  176. $this->phar->setSignatureAlgorithm(\Phar::SHA1);
  177. }
  178. $this->phar->stopBuffering();
  179. $ext = str_replace(array('.tar', '.zip', '.tgz', '.phar'), array('', '', '', ''),
  180. basename($this->path)) . '.';
  181. $ext = substr($ext, strpos($ext, '.'));
  182. $newphar = $this->phar;
  183. if (count($this->others)) {
  184. foreach ($this->others as $pathinfo) {
  185. // remove the old file
  186. $pubkeypath = $newpath = str_replace(array('.tar', '.zip', '.tgz', '.phar'), array('', '', '', ''), $this->path);
  187. $newpath .= '.' .$pathinfo[0];
  188. if (file_exists($newpath)) {
  189. unlink($newpath);
  190. }
  191. $extension = $ext . $pathinfo[0];
  192. $fileformat = $pathinfo[1];
  193. $compression = $pathinfo[2];
  194. if ($fileformat != \Phar::PHAR) {
  195. $newphar = $newphar->convertToData($fileformat, $compression, $extension);
  196. } else {
  197. $newphar = $newphar->convertToExecutable($fileformat, $compression, $extension);
  198. }
  199. if (isset($pkey)) {
  200. $newphar->setSignatureAlgorithm(\Phar::OPENSSL, $this->privatekey);
  201. file_put_contents($pubkeypath . '.' . $pathinfo[0] . '.pubkey', $this->publickey);
  202. } else {
  203. $newphar->setSignatureAlgorithm(\Phar::SHA1);
  204. }
  205. }
  206. }
  207. }
  208. }