This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /* |
||
3 | * @author Tom Klingenberg <https://github.com/ktomk> |
||
4 | * @license LGPL-3.0 <https://spdx.org/licenses/LGPL-3.0.html> |
||
5 | * |
||
6 | * This software consists of voluntary contributions made by many individuals |
||
7 | * and is licensed under the LGPL. For more information please see |
||
8 | * <http://phing.info>. |
||
9 | */ |
||
10 | |||
11 | /** |
||
12 | * Package task for {@link http://www.php.net/manual/en/book.phar.php Phar technology}. |
||
13 | * |
||
14 | * @package phing.tasks.ext |
||
15 | * @author Alexey Shockov <[email protected]> |
||
16 | * @since 2.4.0 |
||
17 | * @see PharPackageTask |
||
18 | */ |
||
19 | class PatchedPharPackageTask |
||
0 ignored issues
–
show
|
|||
20 | extends MatchingTask |
||
0 ignored issues
–
show
|
|||
21 | { |
||
22 | /** |
||
23 | * @var PhingFile |
||
24 | */ |
||
25 | private $destinationFile; |
||
26 | |||
27 | /** |
||
28 | * @var int |
||
29 | */ |
||
30 | private $compression = Phar::NONE; |
||
31 | |||
32 | /** |
||
33 | * Base directory, from where local package paths will be calculated. |
||
34 | * |
||
35 | * @var PhingFile |
||
36 | */ |
||
37 | private $baseDirectory; |
||
38 | |||
39 | /** |
||
40 | * @var PhingFile |
||
41 | */ |
||
42 | private $cliStubFile; |
||
43 | |||
44 | /** |
||
45 | * @var PhingFile |
||
46 | */ |
||
47 | private $webStubFile; |
||
48 | |||
49 | /** |
||
50 | * @var string |
||
51 | */ |
||
52 | private $stubPath; |
||
53 | |||
54 | /** |
||
55 | * Private key the Phar will be signed with. |
||
56 | * |
||
57 | * @var PhingFile |
||
58 | */ |
||
59 | private $key; |
||
60 | |||
61 | /** |
||
62 | * Password for the private key. |
||
63 | * |
||
64 | * @var string |
||
65 | */ |
||
66 | private $keyPassword = ''; |
||
67 | |||
68 | /** |
||
69 | * @var int |
||
70 | */ |
||
71 | private $signatureAlgorithm = Phar::SHA1; |
||
72 | |||
73 | /** |
||
74 | * @var array |
||
75 | */ |
||
76 | private $filesets = array(); |
||
77 | |||
78 | /** |
||
79 | * @var PharMetadata |
||
80 | */ |
||
81 | private $metadata = null; |
||
82 | |||
83 | /** |
||
84 | * @var string |
||
85 | */ |
||
86 | private $alias; |
||
87 | |||
88 | /** |
||
89 | * @return PharMetadata |
||
90 | */ |
||
91 | public function createMetadata() |
||
92 | { |
||
93 | return ($this->metadata = new PharMetadata()); |
||
94 | } |
||
95 | |||
96 | /** |
||
97 | * @return FileSet |
||
98 | */ |
||
99 | public function createFileSet() |
||
100 | { |
||
101 | $this->fileset = new IterableFileSet(); |
||
102 | $this->filesets[] = $this->fileset; |
||
103 | |||
104 | return $this->fileset; |
||
105 | } |
||
106 | |||
107 | /** |
||
108 | * Signature algorithm (md5, sha1, sha256, sha512, openssl), |
||
109 | * used for this package. |
||
110 | * |
||
111 | * @param string $algorithm |
||
112 | */ |
||
113 | public function setSignature($algorithm) |
||
114 | { |
||
115 | /* |
||
116 | * If we don't support passed algprithm, leave old one. |
||
117 | */ |
||
118 | switch ($algorithm) { |
||
119 | case 'md5': |
||
120 | $this->signatureAlgorithm = Phar::MD5; |
||
121 | break; |
||
122 | case 'sha1': |
||
123 | $this->signatureAlgorithm = Phar::SHA1; |
||
124 | break; |
||
125 | case 'sha256': |
||
126 | $this->signatureAlgorithm = Phar::SHA256; |
||
127 | break; |
||
128 | case 'sha512': |
||
129 | $this->signatureAlgorithm = Phar::SHA512; |
||
130 | break; |
||
131 | case 'openssl': |
||
132 | $this->signatureAlgorithm = Phar::OPENSSL; |
||
133 | break; |
||
134 | default: |
||
135 | break; |
||
136 | } |
||
137 | } |
||
138 | |||
139 | /** |
||
140 | * Compression type (gzip, bzip2, none) to apply to the packed files. |
||
141 | * |
||
142 | * @param string $compression |
||
143 | */ |
||
144 | public function setCompression($compression) |
||
145 | { |
||
146 | /** |
||
147 | * If we don't support passed compression, leave old one. |
||
148 | */ |
||
149 | switch ($compression) { |
||
150 | case 'gzip': |
||
151 | $this->compression = Phar::GZ; |
||
152 | break; |
||
153 | case 'bzip2': |
||
154 | $this->compression = Phar::BZ2; |
||
155 | break; |
||
156 | default: |
||
157 | break; |
||
158 | } |
||
159 | } |
||
160 | |||
161 | /** |
||
162 | * @return string |
||
163 | */ |
||
164 | private function getCompressionLabel() |
||
165 | { |
||
166 | $compression = $this->compression; |
||
167 | |||
168 | switch ($compression) { |
||
169 | case Phar::GZ: |
||
170 | return "gzip"; |
||
171 | |||
172 | case Phar::BZ2: |
||
173 | return "bzip2"; |
||
174 | |||
175 | default: |
||
176 | return sprintf("int(%d)", $compression); |
||
177 | } |
||
178 | } |
||
179 | |||
180 | /** |
||
181 | * Destination (output) file. |
||
182 | * |
||
183 | * @param PhingFile $destinationFile |
||
184 | */ |
||
185 | public function setDestFile(PhingFile $destinationFile) |
||
186 | { |
||
187 | $this->destinationFile = $destinationFile; |
||
188 | } |
||
189 | |||
190 | /** |
||
191 | * Base directory, which will be deleted from each included file (from path). |
||
192 | * Paths with deleted basedir part are local paths in package. |
||
193 | * |
||
194 | * @param PhingFile $baseDirectory |
||
195 | */ |
||
196 | public function setBaseDir(PhingFile $baseDirectory) |
||
197 | { |
||
198 | $this->baseDirectory = $baseDirectory; |
||
199 | } |
||
200 | |||
201 | /** |
||
202 | * Relative path within the phar package to run, |
||
203 | * if accessed on the command line. |
||
204 | * |
||
205 | * @param PhingFile $stubFile |
||
206 | */ |
||
207 | public function setCliStub(PhingFile $stubFile) |
||
208 | { |
||
209 | $this->cliStubFile = $stubFile; |
||
210 | } |
||
211 | |||
212 | /** |
||
213 | * Relative path within the phar package to run, |
||
214 | * if accessed through a web browser. |
||
215 | * |
||
216 | * @param PhingFile $stubFile |
||
217 | */ |
||
218 | public function setWebStub(PhingFile $stubFile) |
||
219 | { |
||
220 | $this->webStubFile = $stubFile; |
||
221 | } |
||
222 | |||
223 | /** |
||
224 | * A path to a php file that contains a custom stub. |
||
225 | * |
||
226 | * @param string $stubPath |
||
227 | */ |
||
228 | public function setStub($stubPath) |
||
229 | { |
||
230 | $this->stubPath = $stubPath; |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | * An alias to assign to the phar package. |
||
235 | * |
||
236 | * @param string $alias |
||
237 | */ |
||
238 | public function setAlias($alias) |
||
239 | { |
||
240 | $this->alias = $alias; |
||
241 | } |
||
242 | |||
243 | /** |
||
244 | * Sets the private key to use to sign the Phar with. |
||
245 | * |
||
246 | * @param PhingFile $key Private key to sign the Phar with. |
||
247 | */ |
||
248 | public function setKey(PhingFile $key) |
||
249 | { |
||
250 | $this->key = $key; |
||
251 | } |
||
252 | |||
253 | /** |
||
254 | * Password for the private key. |
||
255 | * |
||
256 | * @param string $keyPassword |
||
257 | */ |
||
258 | public function setKeyPassword($keyPassword) |
||
259 | { |
||
260 | $this->keyPassword = $keyPassword; |
||
261 | } |
||
262 | |||
263 | /** |
||
264 | * @throws BuildException |
||
265 | */ |
||
266 | public function main() |
||
267 | { |
||
268 | $this->checkPreconditions(); |
||
269 | |||
270 | try { |
||
271 | $this->log( |
||
272 | 'Building package: ' . $this->destinationFile->__toString(), |
||
273 | Project::MSG_INFO |
||
274 | ); |
||
275 | |||
276 | $baseDirectory = realpath($this->baseDirectory->getPath()); |
||
277 | |||
278 | try { |
||
279 | $this->compressAllFiles($this->initPhar(), $baseDirectory); |
||
280 | } catch (\RuntimeException $e) { |
||
281 | $this->log('Most likely compression failed (known bug): ' . $e->getMessage()); |
||
282 | $this->compressEachFile($this->initPhar(), $baseDirectory); |
||
283 | } |
||
284 | } catch (Exception $e) { |
||
285 | throw new BuildException( |
||
286 | 'Problem creating package: ' . $e->getMessage(), |
||
287 | $e, |
||
288 | $this->getLocation() |
||
289 | ); |
||
290 | } |
||
291 | } |
||
292 | |||
293 | /** |
||
294 | * @throws BuildException |
||
295 | */ |
||
296 | private function checkPreconditions() |
||
297 | { |
||
298 | if (!extension_loaded('phar')) { |
||
299 | throw new BuildException( |
||
300 | "PharPackageTask require either PHP 5.3 or better or the PECL's Phar extension" |
||
301 | ); |
||
302 | } |
||
303 | |||
304 | if (is_null($this->destinationFile)) { |
||
305 | throw new BuildException("destfile attribute must be set!", $this->getLocation()); |
||
306 | } |
||
307 | |||
308 | if ($this->destinationFile->exists() && $this->destinationFile->isDirectory()) { |
||
309 | throw new BuildException("destfile is a directory!", $this->getLocation()); |
||
310 | } |
||
311 | |||
312 | if (!$this->destinationFile->canWrite()) { |
||
313 | throw new BuildException("Can not write to the specified destfile!", $this->getLocation()); |
||
314 | } |
||
315 | View Code Duplication | if (!is_null($this->baseDirectory)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
316 | if (!$this->baseDirectory->exists()) { |
||
317 | throw new BuildException( |
||
318 | "basedir '" . (string) $this->baseDirectory . "' does not exist!", $this->getLocation() |
||
319 | ); |
||
320 | } |
||
321 | } |
||
322 | if ($this->signatureAlgorithm == Phar::OPENSSL) { |
||
323 | |||
324 | if (!extension_loaded('openssl')) { |
||
325 | throw new BuildException( |
||
326 | "PHP OpenSSL extension is required for OpenSSL signing of Phars!", $this->getLocation() |
||
327 | ); |
||
328 | } |
||
329 | |||
330 | if (is_null($this->key)) { |
||
331 | throw new BuildException("key attribute must be set for OpenSSL signing!", $this->getLocation()); |
||
332 | } |
||
333 | |||
334 | View Code Duplication | if (!$this->key->exists()) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
335 | throw new BuildException("key '" . (string) $this->key . "' does not exist!", $this->getLocation()); |
||
336 | } |
||
337 | |||
338 | if (!$this->key->canRead()) { |
||
339 | throw new BuildException("key '" . (string) $this->key . "' cannot be read!", $this->getLocation()); |
||
340 | } |
||
341 | } |
||
342 | } |
||
343 | |||
344 | /** |
||
345 | * Build and configure Phar object. |
||
346 | * |
||
347 | * @return Phar |
||
348 | */ |
||
349 | private function buildPhar() |
||
350 | { |
||
351 | $phar = new Phar($this->destinationFile); |
||
352 | |||
353 | if ($this->signatureAlgorithm == Phar::OPENSSL) { |
||
354 | |||
355 | // Load up the contents of the key |
||
356 | $keyContents = file_get_contents($this->key); |
||
357 | |||
358 | // Setup an OpenSSL resource using the private key and tell the Phar |
||
359 | // to sign it using that key. |
||
360 | $private = openssl_pkey_get_private($keyContents, $this->keyPassword); |
||
361 | $phar->setSignatureAlgorithm(Phar::OPENSSL, $private); |
||
362 | |||
363 | // Get the details so we can get the public key and write that out |
||
364 | // alongside the phar. |
||
365 | $details = openssl_pkey_get_details($private); |
||
366 | file_put_contents($this->destinationFile . '.pubkey', $details['key']); |
||
367 | |||
368 | } else { |
||
369 | $phar->setSignatureAlgorithm($this->signatureAlgorithm); |
||
370 | } |
||
371 | |||
372 | if (!empty($this->stubPath)) { |
||
373 | $phar->setStub(file_get_contents($this->stubPath)); |
||
374 | } else { |
||
375 | if (!empty($this->cliStubFile)) { |
||
376 | $cliStubFile = $this->cliStubFile->getPathWithoutBase($this->baseDirectory); |
||
377 | } else { |
||
378 | $cliStubFile = null; |
||
379 | } |
||
380 | |||
381 | if (!empty($this->webStubFile)) { |
||
382 | $webStubFile = $this->webStubFile->getPathWithoutBase($this->baseDirectory); |
||
383 | } else { |
||
384 | $webStubFile = null; |
||
385 | } |
||
386 | |||
387 | $phar->setDefaultStub($cliStubFile, $webStubFile); |
||
388 | } |
||
389 | |||
390 | if ($this->metadata === null) { |
||
391 | $this->createMetaData(); |
||
392 | } |
||
393 | |||
394 | if ($metadata = $this->metadata->toArray()) { |
||
395 | $phar->setMetadata($metadata); |
||
396 | } |
||
397 | |||
398 | if (!empty($this->alias)) { |
||
399 | $phar->setAlias($this->alias); |
||
400 | } |
||
401 | |||
402 | return $phar; |
||
403 | } |
||
404 | |||
405 | /** |
||
406 | * @return Phar |
||
407 | */ |
||
408 | private function initPhar() |
||
409 | { |
||
410 | /** |
||
411 | * Delete old package, if exists. |
||
412 | */ |
||
413 | if ($this->destinationFile->exists()) { |
||
414 | $this->destinationFile->delete(); |
||
415 | } |
||
416 | $phar = $this->buildPhar(); |
||
417 | |||
418 | return $phar; |
||
419 | } |
||
420 | |||
421 | /** |
||
422 | * @param Phar $phar |
||
423 | * @param string $baseDirectory |
||
424 | */ |
||
425 | private function compressEachFile(Phar $phar, $baseDirectory) |
||
426 | { |
||
427 | $phar->startBuffering(); |
||
428 | |||
429 | foreach ($this->filesets as $fileset) { |
||
430 | $this->log( |
||
431 | 'Adding specified files in ' . $fileset->getDir($this->project) . ' to package', |
||
432 | Project::MSG_VERBOSE |
||
433 | ); |
||
434 | |||
435 | $sortedFiles = $this->getSortedFilesFromFileSet($fileset); |
||
436 | if (Phar::NONE != $this->compression) { |
||
437 | foreach ($sortedFiles as $file) { |
||
438 | $localName = substr($file, strlen($baseDirectory) + 1); |
||
439 | $this->log($localName . "... ", Project::MSG_VERBOSE); |
||
440 | $phar->addFile($file, $localName); |
||
441 | $phar[$localName]->compress($this->compression); |
||
442 | } |
||
443 | } else { |
||
444 | $phar->buildFromIterator($sortedFiles, $baseDirectory); |
||
445 | } |
||
446 | } |
||
447 | |||
448 | $phar->stopBuffering(); |
||
449 | } |
||
450 | |||
451 | /** |
||
452 | * @param Phar $phar |
||
453 | * @param string $baseDirectory |
||
454 | */ |
||
455 | private function compressAllFiles(Phar $phar, $baseDirectory) |
||
456 | { |
||
457 | $total = 0; |
||
458 | |||
459 | $phar->startBuffering(); |
||
460 | |||
461 | foreach ($this->filesets as $fileset) { |
||
462 | /* @var $fileset IterableFileSet */ |
||
463 | $dir = $fileset->getDir($this->project); |
||
464 | $msg = sprintf("Fileset %s ...", $dir); |
||
465 | $this->log($msg, Project::MSG_VERBOSE); |
||
466 | $added = $phar->buildFromIterator($this->getSortedFilesFromFileSet($fileset), $baseDirectory); |
||
467 | $total += count($added); |
||
468 | } |
||
469 | |||
470 | $phar->stopBuffering(); |
||
471 | |||
472 | if (Phar::NONE === $this->compression) { |
||
473 | return; |
||
474 | } |
||
475 | |||
476 | $msg = sprintf("Compressing %d files (compression: %s) ... ", $total, $this->getCompressionLabel()); |
||
477 | $this->log($msg, Project::MSG_VERBOSE); |
||
478 | |||
479 | // safeguard open files soft limit |
||
480 | if (function_exists('posix_getrlimit')) { |
||
481 | $rlimit = posix_getrlimit(); |
||
482 | if ($rlimit['soft openfiles'] < ($total + 5)) { |
||
483 | $msg = sprintf("Limit of openfiles (%d) is too low.", $rlimit['soft openfiles']); |
||
484 | $this->log($msg, Project::MSG_VERBOSE); |
||
485 | } |
||
486 | } |
||
487 | |||
488 | // safeguard compression |
||
489 | try { |
||
490 | $phar->compressFiles($this->compression); |
||
491 | } catch (BadMethodCallException $e) { |
||
492 | if ($e->getMessage() === 'unable to create temporary file') { |
||
493 | $msg = sprintf("Info: Check openfiles limit it must be %d or higher", $total + 5); |
||
494 | throw new BadMethodCallException($msg, 0, $e); |
||
495 | } |
||
496 | throw $e; |
||
497 | } |
||
498 | } |
||
499 | |||
500 | /** |
||
501 | * Obtain ArrayIterator with keys preserved from IterableFileSet |
||
502 | * |
||
503 | * @param IterableFileSet $fileset |
||
504 | * @return ArrayIterator |
||
505 | */ |
||
506 | private function getSortedFilesFromFileSet(IterableFileSet $fileset) |
||
507 | { |
||
508 | $files = iterator_to_array($fileset, true); |
||
509 | $keys = array_keys($files); |
||
510 | usort($files, array($this, 'sortFilesCallback')); |
||
511 | $array = array_combine($keys, $files); |
||
512 | |||
513 | return new ArrayIterator($array); |
||
514 | } |
||
515 | |||
516 | /** |
||
517 | * @param string $a |
||
518 | * @param string $b |
||
519 | * @return int |
||
520 | * @see getSortedFilesFromFileSet |
||
521 | */ |
||
522 | private function sortFilesCallback($a, $b) |
||
523 | { |
||
524 | return strcmp(strtr($a, '\\', '/'), strtr($b, '\\', '/')); |
||
525 | } |
||
526 | } |
||
527 |
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.