1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the puli/installer package. |
5
|
|
|
* |
6
|
|
|
* (c) Bernhard Schussek <[email protected]> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Puli\Installer; |
13
|
|
|
|
14
|
|
|
use Exception; |
15
|
|
|
use Humbug\SelfUpdate\VersionParser; |
16
|
|
|
use Phar; |
17
|
|
|
use PharException; |
18
|
|
|
use RuntimeException; |
19
|
|
|
use UnexpectedValueException; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Installs the puli.phar on the local system. |
23
|
|
|
* |
24
|
|
|
* Use it like this: |
25
|
|
|
* |
26
|
|
|
* ``` |
27
|
|
|
* $ curl -sS https://puli.io/installer | php |
28
|
|
|
* ``` |
29
|
|
|
* |
30
|
|
|
* This file was adapted from the installer file bundled with Composer. For the |
31
|
|
|
* original file, authors and copyright information see |
32
|
|
|
* |
33
|
|
|
* https://github.com/composer/getcomposer.org/blob/master/web/installer |
34
|
|
|
* |
35
|
|
|
* @author Nils Adermann <[email protected]> |
36
|
|
|
* @author Jordi Boggiano <[email protected]> |
37
|
|
|
* @author Thomas Rudolph <[email protected]> |
38
|
|
|
* @author Bernhard Schussek <[email protected]> |
39
|
|
|
*/ |
40
|
|
|
class Installer |
41
|
|
|
{ |
42
|
|
|
/** |
43
|
|
|
* The help text of the installer. |
44
|
|
|
*/ |
45
|
|
|
const HELP_TEXT = <<<HELP |
46
|
|
|
Puli Installer |
47
|
|
|
-------------- |
48
|
|
|
Options |
49
|
|
|
--help this help |
50
|
|
|
--check for checking environment only |
51
|
|
|
--force forces the installation even if the system requirements are not satisfied |
52
|
|
|
--ansi force ANSI color output |
53
|
|
|
--no-ansi disable ANSI color output |
54
|
|
|
--quiet do not output unimportant messages |
55
|
|
|
--install-dir="..." set the target installation directory |
56
|
|
|
--version="..." install a specific version |
57
|
|
|
--filename="..." set the target filename (default: puli.phar) |
58
|
|
|
--disable-tls disable SSL/TLS security for file downloads |
59
|
|
|
|
60
|
|
|
HELP; |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* The api url to determine the available versions of puli. |
64
|
|
|
*/ |
65
|
|
|
const VERSION_API_URL = '%s://puli.io/download/versions.json'; |
66
|
|
|
|
67
|
|
|
/** |
68
|
|
|
* The phar download url. |
69
|
|
|
*/ |
70
|
|
|
const PHAR_DOWNLOAD_URL = '%s://puli.io/download/%s/puli.phar'; |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* @var string |
74
|
|
|
*/ |
75
|
|
|
private $stability; |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* @var bool |
79
|
|
|
*/ |
80
|
|
|
private $check; |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* @var bool |
84
|
|
|
*/ |
85
|
|
|
private $help; |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* @var bool |
89
|
|
|
*/ |
90
|
|
|
private $force; |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* @var bool |
94
|
|
|
*/ |
95
|
|
|
private $quiet; |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* @var bool |
99
|
|
|
*/ |
100
|
|
|
private $disableTls; |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* @var string |
104
|
|
|
*/ |
105
|
|
|
private $installDir; |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @var string |
109
|
|
|
*/ |
110
|
|
|
private $version; |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* @var string |
114
|
|
|
*/ |
115
|
|
|
private $filename; |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* Runs the installer. |
119
|
|
|
* |
120
|
|
|
* @param array $argv The console arguments. |
121
|
|
|
* |
122
|
|
|
* @return int The return status. |
123
|
|
|
*/ |
124
|
5 |
|
public function run(array $argv) |
125
|
|
|
{ |
126
|
5 |
|
$this->parseOptions($argv); |
127
|
|
|
|
128
|
5 |
|
if ($this->help) { |
129
|
|
|
echo self::HELP_TEXT; |
130
|
|
|
|
131
|
|
|
return 0; |
132
|
|
|
} |
133
|
|
|
|
134
|
5 |
|
$ok = $this->validateSystem() && $this->validateOptions(); |
135
|
|
|
|
136
|
5 |
|
if ($this->disableTls) { |
137
|
|
|
$this->info( |
138
|
|
|
'You have instructed the Installer not to enforce SSL/TLS '. |
139
|
|
|
'security on remote HTTPS requests.'.PHP_EOL. |
140
|
|
|
'This will leave all downloads during installation vulnerable '. |
141
|
|
|
'to Man-In-The-Middle (MITM) attacks.' |
142
|
|
|
); |
143
|
|
|
} |
144
|
|
|
|
145
|
5 |
|
if ($this->check) { |
146
|
|
|
return $ok ? 0 : 1; |
147
|
|
|
} |
148
|
|
|
|
149
|
5 |
|
if ($ok || $this->force) { |
150
|
5 |
|
return $this->installPuli(); |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
return 1; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* Installs puli to the current working directory. |
158
|
|
|
* |
159
|
|
|
* @return int The return status. |
160
|
|
|
* |
161
|
|
|
* @throws Exception |
162
|
|
|
*/ |
163
|
5 |
|
private function installPuli() |
164
|
|
|
{ |
165
|
5 |
|
$workingDir = str_replace('\\', '/', getcwd()); |
166
|
5 |
|
$installDir = is_dir($this->installDir) ? realpath($this->installDir) : $workingDir; |
167
|
5 |
|
$installPath = str_replace('\\', '/', $installDir).'/'.$this->filename; |
168
|
5 |
|
$shortInstallPath = $installPath; |
169
|
|
|
|
170
|
|
|
// Strip the current working directory if possible |
171
|
5 |
|
if (0 === strpos($shortInstallPath, $workingDir.'/')) { |
172
|
3 |
|
$shortInstallPath = substr($shortInstallPath, strlen($workingDir.'/')); |
173
|
3 |
|
} |
174
|
|
|
|
175
|
5 |
|
if (is_readable($installPath)) { |
176
|
|
|
@unlink($installPath); |
|
|
|
|
177
|
|
|
} |
178
|
|
|
|
179
|
5 |
|
$httpClient = new HttpClient($this->disableTls); |
180
|
|
|
|
181
|
5 |
|
$versionUrl = sprintf( |
182
|
5 |
|
static::VERSION_API_URL, |
183
|
5 |
|
$this->disableTls ? 'http' : 'https' |
184
|
5 |
|
); |
185
|
|
|
|
186
|
5 |
|
$versions = array(); |
187
|
5 |
|
for ($retries = 3; $retries > 0; --$retries) { |
188
|
5 |
|
if (!$this->quiet) { |
189
|
5 |
|
$this->info('Downloading available versions...'); |
190
|
5 |
|
} |
191
|
|
|
|
192
|
|
|
try { |
193
|
5 |
|
$versions = $this->downloadVersions($httpClient, $versionUrl); |
194
|
5 |
|
break; |
195
|
|
|
} catch (RuntimeException $e) { |
196
|
|
|
$this->error($e->getMessage()); |
197
|
|
|
} |
198
|
|
|
} |
199
|
|
|
|
200
|
5 |
|
if (0 === $retries || empty($versions)) { |
201
|
|
|
$this->error('fatal: The download failed repeatedly, aborting.'); |
202
|
|
|
|
203
|
|
|
return 1; |
204
|
|
|
} |
205
|
|
|
|
206
|
5 |
|
$versionParser = new VersionParser($versions); |
207
|
5 |
|
if (!empty($this->version)) { |
208
|
1 |
|
if (!in_array($this->version, $versions, true)) { |
209
|
|
|
$this->error(sprintf( |
210
|
|
|
'fatal: Could not find version: %s.', |
211
|
|
|
$this->version |
212
|
|
|
)); |
213
|
|
|
|
214
|
|
|
return 1; |
215
|
|
|
} |
216
|
5 |
|
} elseif ('stable' === $this->stability) { |
217
|
1 |
|
$this->version = $versionParser->getMostRecentStable(); |
218
|
1 |
|
if (false === $this->version) { |
219
|
1 |
|
$this->error('fatal: Could not find a stable version.'); |
220
|
|
|
|
221
|
1 |
|
return 1; |
222
|
|
|
} |
223
|
|
|
} else { |
224
|
3 |
|
$this->version = $versionParser->getMostRecentAll(); |
225
|
|
|
} |
226
|
|
|
|
227
|
4 |
|
$url = sprintf( |
228
|
4 |
|
static::PHAR_DOWNLOAD_URL, |
229
|
4 |
|
$this->disableTls ? 'http' : 'https', |
230
|
4 |
|
$this->version |
231
|
4 |
|
); |
232
|
|
|
|
233
|
4 |
|
for ($retries = 3; $retries > 0; --$retries) { |
234
|
4 |
|
if (!$this->quiet) { |
235
|
4 |
|
$this->info(sprintf( |
236
|
4 |
|
'Downloading puli.phar at version %s...', |
237
|
4 |
|
$this->version) |
238
|
4 |
|
); |
239
|
4 |
|
} |
240
|
|
|
|
241
|
4 |
|
if (!$this->downloadFile($httpClient, $url, $installPath)) { |
242
|
|
|
continue; |
243
|
|
|
} |
244
|
|
|
|
245
|
|
|
try { |
246
|
4 |
|
$this->validatePhar($installPath); |
247
|
4 |
|
} catch (Exception $e) { |
248
|
|
|
unlink($installPath); |
249
|
|
|
|
250
|
|
|
if (!$e instanceof UnexpectedValueException && !$e instanceof PharException) { |
251
|
|
|
throw $e; |
252
|
|
|
} |
253
|
|
|
|
254
|
|
|
if ($retries > 0) { |
255
|
|
|
if (!$this->quiet) { |
256
|
|
|
$this->error('The download is corrupt, retrying...'); |
257
|
|
|
} |
258
|
|
|
} else { |
259
|
|
|
$this->error(sprintf( |
260
|
|
|
'fatal: The download is corrupt (%s), aborting.', |
261
|
|
|
$e->getMessage() |
262
|
|
|
)); |
263
|
|
|
|
264
|
|
|
return 1; |
265
|
|
|
} |
266
|
|
|
} |
267
|
|
|
|
268
|
4 |
|
break; |
269
|
|
|
} |
270
|
|
|
|
271
|
4 |
|
if (0 === $retries) { |
272
|
|
|
$this->error('fatal: The download failed repeatedly, aborting.'); |
273
|
|
|
|
274
|
|
|
return 1; |
275
|
|
|
} |
276
|
|
|
|
277
|
4 |
|
chmod($installPath, 0755); |
278
|
|
|
|
279
|
4 |
|
if (!$this->quiet) { |
280
|
4 |
|
$this->success(PHP_EOL.'Puli successfully installed to: '.$installPath); |
281
|
4 |
|
$this->info('Use it: php '.$shortInstallPath); |
282
|
4 |
|
} |
283
|
|
|
|
284
|
4 |
|
return 0; |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
/** |
288
|
|
|
* Downloads a URL to a path. |
289
|
|
|
* |
290
|
|
|
* @param HttpClient $httpClient The client to use. |
291
|
|
|
* @param string $url The URL to download. |
292
|
|
|
* @param string $targetPath The path to download the URL to. |
293
|
|
|
* |
294
|
|
|
* @return bool Whether the download completed successfully. |
295
|
|
|
*/ |
296
|
4 |
|
private function downloadFile(HttpClient $httpClient, $url, $targetPath) |
297
|
|
|
{ |
298
|
4 |
|
ErrorHandler::register(); |
299
|
|
|
|
300
|
4 |
|
$fh = fopen($targetPath, 'w'); |
301
|
|
|
|
302
|
4 |
|
if (!$fh) { |
303
|
|
|
$this->error(sprintf( |
304
|
|
|
'Could not create file %s: %s', |
305
|
|
|
$targetPath, |
306
|
|
|
implode(PHP_EOL, ErrorHandler::getErrors()) |
307
|
|
|
)); |
308
|
|
|
} |
309
|
|
|
|
310
|
4 |
|
if (!fwrite($fh, $httpClient->download($url))) { |
311
|
|
|
$this->error(sprintf( |
312
|
|
|
'Download failed: %s', |
313
|
|
|
implode(PHP_EOL, ErrorHandler::getErrors()) |
314
|
|
|
)); |
315
|
|
|
} |
316
|
|
|
|
317
|
4 |
|
fclose($fh); |
318
|
|
|
|
319
|
4 |
|
ErrorHandler::unregister(); |
320
|
|
|
|
321
|
4 |
|
return !ErrorHandler::hasErrors(); |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
/** |
325
|
|
|
* Downloads the available puli versions. |
326
|
|
|
* |
327
|
|
|
* @param HttpClient $httpClient The client to use. |
328
|
|
|
* @param string $url The URL to download. |
329
|
|
|
* |
330
|
|
|
* @return array The available versions, null if the download failed. |
331
|
|
|
* |
332
|
|
|
* @throws RuntimeException If an error occurs. |
333
|
|
|
*/ |
334
|
5 |
|
public function downloadVersions(HttpClient $httpClient, $url) |
335
|
|
|
{ |
336
|
5 |
|
ErrorHandler::register(); |
337
|
5 |
|
$versions = $httpClient->download($url); |
338
|
5 |
|
ErrorHandler::unregister(); |
339
|
|
|
|
340
|
5 |
|
if (ErrorHandler::hasErrors()) { |
341
|
|
|
throw new RuntimeException(sprintf( |
342
|
|
|
'Could not download %s:'.PHP_EOL.'%s', |
343
|
|
|
$url, |
344
|
|
|
implode(PHP_EOL, ErrorHandler::getErrors()) |
345
|
|
|
)); |
346
|
|
|
} |
347
|
|
|
|
348
|
5 |
|
$versions = json_decode($versions); |
349
|
5 |
|
if (json_last_error() !== JSON_ERROR_NONE || !is_array($versions)) { |
350
|
|
|
throw new RuntimeException(sprintf( |
351
|
|
|
'Could not download %s:'.PHP_EOL.'Malformed JSON returned.', |
352
|
|
|
$url |
353
|
|
|
)); |
354
|
|
|
} |
355
|
|
|
|
356
|
5 |
|
usort($versions, 'version_compare'); |
357
|
|
|
|
358
|
5 |
|
return $versions; |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
/** |
362
|
|
|
* Validates that the given path is a valid PHAR file. |
363
|
|
|
* |
364
|
|
|
* @param string $path A path to a PHAR file. |
365
|
|
|
* |
366
|
|
|
* @throws Exception If an error occurs. |
367
|
|
|
*/ |
368
|
4 |
|
private function validatePhar($path) |
369
|
|
|
{ |
370
|
4 |
|
$tmpFile = $path; |
371
|
|
|
|
372
|
|
|
try { |
373
|
|
|
// create a temp file ending in .phar since the Phar class only accepts that |
374
|
4 |
|
if ('.phar' !== substr($path, -5)) { |
375
|
|
|
copy($path, $path.'.tmp.phar'); |
376
|
|
|
$tmpFile = $path.'.tmp.phar'; |
377
|
|
|
} |
378
|
|
|
|
379
|
4 |
|
if (!ini_get('phar.readonly')) { |
380
|
|
|
// test the phar validity |
381
|
4 |
|
$phar = new Phar($tmpFile); |
382
|
|
|
|
383
|
|
|
// free the variable to unlock the file |
384
|
4 |
|
unset($phar); |
385
|
4 |
|
} |
386
|
4 |
|
} catch (Exception $e) { |
387
|
|
|
// clean up temp file if needed |
388
|
|
|
if ($path !== $tmpFile) { |
389
|
|
|
unlink($tmpFile); |
390
|
|
|
} |
391
|
|
|
|
392
|
|
|
throw $e; |
393
|
|
|
} |
394
|
|
|
|
395
|
|
|
// clean up temp file if needed |
396
|
4 |
|
if ($path !== $tmpFile) { |
397
|
|
|
unlink($tmpFile); |
398
|
|
|
} |
399
|
4 |
|
} |
400
|
|
|
|
401
|
|
|
/** |
402
|
|
|
* Check the platform for possible issues on running Puli. |
403
|
|
|
* |
404
|
|
|
* @return bool Whether the platform requirements are satisfied. |
405
|
|
|
*/ |
406
|
5 |
|
private function validateSystem() |
407
|
|
|
{ |
408
|
5 |
|
$errors = array(); |
409
|
5 |
|
$warnings = array(); |
410
|
|
|
|
411
|
5 |
|
$iniPath = php_ini_loaded_file(); |
412
|
5 |
|
$displayIniMessage = false; |
413
|
|
|
|
414
|
5 |
|
if ($iniPath) { |
415
|
5 |
|
$iniMessage = PHP_EOL.PHP_EOL.'The php.ini used by your command-line PHP is: '.$iniPath; |
416
|
5 |
|
} else { |
417
|
|
|
$iniMessage = PHP_EOL.PHP_EOL.'A php.ini file does not exist. You will have to create one.'; |
418
|
|
|
} |
419
|
|
|
|
420
|
5 |
|
$iniMessage .= PHP_EOL.'If you can not modify the ini file, you can also run `php -d option=value` to modify ini values on the fly. You can use -d multiple times.'; |
421
|
|
|
|
422
|
5 |
|
if (ini_get('detect_unicode')) { |
423
|
|
|
$errors['unicode'] = 'On'; |
424
|
|
|
} |
425
|
|
|
|
426
|
5 |
|
if (extension_loaded('suhosin')) { |
427
|
|
|
$suhosin = ini_get('suhosin.executor.include.whitelist'); |
428
|
|
|
$suhosinBlacklist = ini_get('suhosin.executor.include.blacklist'); |
429
|
|
|
if (false === stripos($suhosin, |
430
|
|
|
'phar') && (!$suhosinBlacklist || false !== stripos($suhosinBlacklist, |
431
|
|
|
'phar')) |
432
|
|
|
) { |
433
|
|
|
$errors['suhosin'] = $suhosin; |
434
|
|
|
} |
435
|
|
|
} |
436
|
|
|
|
437
|
5 |
|
if (!function_exists('json_decode')) { |
438
|
|
|
$errors['json'] = true; |
439
|
|
|
} |
440
|
|
|
|
441
|
5 |
|
if (!extension_loaded('Phar')) { |
442
|
|
|
$errors['phar'] = true; |
443
|
|
|
} |
444
|
|
|
|
445
|
5 |
|
if (!ini_get('allow_url_fopen')) { |
446
|
|
|
$errors['allow_url_fopen'] = true; |
447
|
|
|
} |
448
|
|
|
|
449
|
5 |
|
if (extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) { |
450
|
|
|
$errors['ioncube'] = ioncube_loader_version(); |
451
|
|
|
} |
452
|
|
|
|
453
|
5 |
|
if (version_compare(PHP_VERSION, '5.3.9', '<')) { |
454
|
|
|
$errors['php'] = PHP_VERSION; |
455
|
|
|
} |
456
|
|
|
|
457
|
5 |
|
if (!extension_loaded('openssl') && $this->disableTls) { |
458
|
|
|
$warnings['openssl'] = true; |
459
|
5 |
|
} elseif (!extension_loaded('openssl')) { |
460
|
|
|
$errors['openssl'] = true; |
461
|
|
|
} |
462
|
|
|
|
463
|
5 |
|
if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && ini_get('apc.enable_cli')) { |
464
|
|
|
$warnings['apc_cli'] = true; |
465
|
|
|
} |
466
|
|
|
|
467
|
5 |
|
ob_start(); |
468
|
5 |
|
phpinfo(INFO_GENERAL); |
469
|
5 |
|
$phpinfo = ob_get_clean(); |
470
|
5 |
|
if (preg_match('{Configure Command(?: *</td><td class="v">| *=> *)(.*?)(?:</td>|$)}m', |
471
|
5 |
|
$phpinfo, $match)) { |
472
|
5 |
|
$configure = $match[1]; |
473
|
|
|
|
474
|
5 |
|
if (false !== strpos($configure, '--enable-sigchild')) { |
475
|
|
|
$warnings['sigchild'] = true; |
476
|
|
|
} |
477
|
|
|
|
478
|
5 |
|
if (false !== strpos($configure, '--with-curlwrappers')) { |
479
|
|
|
$warnings['curlwrappers'] = true; |
480
|
|
|
} |
481
|
5 |
|
} |
482
|
|
|
|
483
|
5 |
|
if (!empty($errors)) { |
484
|
|
|
$this->error('Some settings on your machine make Puli unable to work properly.'); |
485
|
|
|
$this->error('Make sure that you fix the issues listed below and run this script again:'); |
486
|
|
|
|
487
|
|
|
foreach ($errors as $error => $current) { |
488
|
|
|
$text = ''; |
489
|
|
|
switch ($error) { |
490
|
|
|
case 'json': |
491
|
|
|
$text = PHP_EOL.'The json extension is missing.'.PHP_EOL; |
492
|
|
|
$text .= 'Install it or recompile php without --disable-json'; |
493
|
|
|
break; |
494
|
|
|
|
495
|
|
|
case 'phar': |
496
|
|
|
$text = PHP_EOL.'The phar extension is missing.'.PHP_EOL; |
497
|
|
|
$text .= 'Install it or recompile php without --disable-phar'; |
498
|
|
|
break; |
499
|
|
|
|
500
|
|
View Code Duplication |
case 'unicode': |
|
|
|
|
501
|
|
|
$text = PHP_EOL.'The detect_unicode setting must be disabled.'.PHP_EOL; |
502
|
|
|
$text .= 'Add the following to the end of your `php.ini`:'.PHP_EOL; |
503
|
|
|
$text .= ' detect_unicode = Off'; |
504
|
|
|
$displayIniMessage = true; |
505
|
|
|
break; |
506
|
|
|
|
507
|
|
View Code Duplication |
case 'suhosin': |
|
|
|
|
508
|
|
|
$text = PHP_EOL.'The suhosin.executor.include.whitelist setting is incorrect.'.PHP_EOL; |
509
|
|
|
$text .= 'Add the following to the end of your `php.ini` or suhosin.ini (Example path [for Debian]: /etc/php5/cli/conf.d/suhosin.ini):'.PHP_EOL; |
510
|
|
|
$text .= ' suhosin.executor.include.whitelist = phar '.$current; |
511
|
|
|
$displayIniMessage = true; |
512
|
|
|
break; |
513
|
|
|
|
514
|
|
|
case 'php': |
515
|
|
|
$text = PHP_EOL."Your PHP ({$current}) is too old, you must upgrade to PHP 5.3.9 or higher."; |
|
|
|
|
516
|
|
|
break; |
517
|
|
|
|
518
|
|
View Code Duplication |
case 'allow_url_fopen': |
|
|
|
|
519
|
|
|
$text = PHP_EOL.'The allow_url_fopen setting is incorrect.'.PHP_EOL; |
520
|
|
|
$text .= 'Add the following to the end of your `php.ini`:'.PHP_EOL; |
521
|
|
|
$text .= ' allow_url_fopen = On'; |
522
|
|
|
$displayIniMessage = true; |
523
|
|
|
break; |
524
|
|
|
|
525
|
|
View Code Duplication |
case 'ioncube': |
|
|
|
|
526
|
|
|
$text = PHP_EOL."Your ionCube Loader extension ($current) is incompatible with Phar files.".PHP_EOL; |
|
|
|
|
527
|
|
|
$text .= 'Upgrade to ionCube 4.0.9 or higher or remove this line (path may be different) from your `php.ini` to disable it:'.PHP_EOL; |
528
|
|
|
$text .= ' zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so'; |
529
|
|
|
$displayIniMessage = true; |
530
|
|
|
break; |
531
|
|
|
|
532
|
|
|
case 'openssl': |
533
|
|
|
$text = PHP_EOL.'The openssl extension is missing, which means that secure HTTPS transfers are impossible.'.PHP_EOL; |
534
|
|
|
$text .= 'If possible you should enable it or recompile php with --with-openssl'; |
535
|
|
|
break; |
536
|
|
|
} |
537
|
|
|
|
538
|
|
|
if ($displayIniMessage) { |
539
|
|
|
$text .= $iniMessage; |
540
|
|
|
} |
541
|
|
|
|
542
|
|
|
$this->info($text); |
543
|
|
|
} |
544
|
|
|
|
545
|
|
|
echo PHP_EOL; |
546
|
|
|
|
547
|
|
|
return false; |
548
|
|
|
} |
549
|
|
|
|
550
|
5 |
|
if (!empty($warnings)) { |
551
|
|
|
$this->error('Some settings on your machine may cause stability issues with Puli.'); |
552
|
|
|
$this->error('If you encounter issues, try to change the following:'); |
553
|
|
|
|
554
|
|
|
foreach ($warnings as $warning => $current) { |
555
|
|
|
$text = ''; |
556
|
|
|
switch ($warning) { |
557
|
|
View Code Duplication |
case 'apc_cli': |
|
|
|
|
558
|
|
|
$text = PHP_EOL.'The apc.enable_cli setting is incorrect.'.PHP_EOL; |
559
|
|
|
$text .= 'Add the following to the end of your `php.ini`:'.PHP_EOL; |
560
|
|
|
$text .= ' apc.enable_cli = Off'; |
561
|
|
|
$displayIniMessage = true; |
562
|
|
|
break; |
563
|
|
|
|
564
|
|
|
case 'sigchild': |
565
|
|
|
$text = PHP_EOL.'PHP was compiled with --enable-sigchild which can cause issues on some platforms.'.PHP_EOL; |
566
|
|
|
$text .= 'Recompile it without this flag if possible, see also:'.PHP_EOL; |
567
|
|
|
$text .= ' https://bugs.php.net/bug.php?id=22999'; |
568
|
|
|
break; |
569
|
|
|
|
570
|
|
|
case 'curlwrappers': |
571
|
|
|
$text = PHP_EOL.'PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub.'.PHP_EOL; |
572
|
|
|
$text .= 'Recompile it without this flag if possible'; |
573
|
|
|
break; |
574
|
|
|
|
575
|
|
|
case 'openssl': |
576
|
|
|
$text = PHP_EOL.'The openssl extension is missing, which means that secure HTTPS transfers are impossible.'.PHP_EOL; |
577
|
|
|
$text .= 'If possible you should enable it or recompile php with --with-openssl'; |
578
|
|
|
break; |
579
|
|
|
} |
580
|
|
|
if ($displayIniMessage) { |
581
|
|
|
$text .= $iniMessage; |
582
|
|
|
} |
583
|
|
|
$this->info($text); |
584
|
|
|
} |
585
|
|
|
|
586
|
|
|
echo PHP_EOL; |
587
|
|
|
|
588
|
|
|
return true; |
589
|
|
|
} |
590
|
|
|
|
591
|
5 |
|
if (!$this->quiet) { |
592
|
5 |
|
$this->success('All settings correct for using Puli'); |
593
|
5 |
|
} |
594
|
|
|
|
595
|
5 |
|
return true; |
596
|
|
|
} |
597
|
|
|
|
598
|
|
|
/** |
599
|
|
|
* Validate whether the passed command line options are correct. |
600
|
|
|
* |
601
|
|
|
* @return bool Returns `true` if the options are valid and `false` otherwise. |
602
|
|
|
*/ |
603
|
5 |
|
private function validateOptions() |
604
|
|
|
{ |
605
|
5 |
|
$ok = true; |
606
|
|
|
|
607
|
5 |
|
if (false !== $this->installDir && !is_dir($this->installDir)) { |
608
|
|
|
$this->info(sprintf( |
609
|
|
|
'The defined install dir (%s) does not exist.', |
610
|
|
|
$this->installDir |
611
|
|
|
)); |
612
|
|
|
$ok = false; |
613
|
|
|
} |
614
|
|
|
|
615
|
5 |
|
if (false !== $this->version && 1 !== preg_match('/^\d+\.\d+\.\d+(\-(alpha|beta)\d+)*$/', $this->version)) { |
616
|
|
|
$this->info(sprintf( |
617
|
|
|
'The defined install version (%s) does not match release pattern.', |
618
|
|
|
$this->version |
619
|
|
|
)); |
620
|
|
|
$ok = false; |
621
|
|
|
} |
622
|
|
|
|
623
|
5 |
|
return $ok; |
624
|
|
|
} |
625
|
|
|
|
626
|
|
|
/** |
627
|
|
|
* Parses the command line options. |
628
|
|
|
* |
629
|
|
|
* @param string[] $argv The command line options. |
630
|
|
|
*/ |
631
|
5 |
|
private function parseOptions(array $argv) |
632
|
|
|
{ |
633
|
5 |
|
$this->check = in_array('--check', $argv); |
634
|
5 |
|
$this->help = in_array('--help', $argv); |
635
|
5 |
|
$this->force = in_array('--force', $argv); |
636
|
5 |
|
$this->quiet = in_array('--quiet', $argv); |
637
|
5 |
|
$this->disableTls = in_array('--disable-tls', $argv); |
638
|
5 |
|
$this->installDir = false; |
|
|
|
|
639
|
5 |
|
$this->version = false; |
|
|
|
|
640
|
5 |
|
$this->filename = 'puli.phar'; |
641
|
5 |
|
$this->stability = 'unstable'; |
642
|
5 |
|
if (in_array('--stable', $argv)) { |
643
|
1 |
|
$this->stability = 'stable'; |
644
|
1 |
|
} |
645
|
|
|
|
646
|
|
|
// --no-ansi wins over --ansi |
647
|
5 |
|
if (in_array('--no-ansi', $argv)) { |
648
|
4 |
|
define('USE_ANSI', false); |
649
|
5 |
|
} elseif (in_array('--ansi', $argv)) { |
650
|
|
|
define('USE_ANSI', true); |
651
|
|
|
} else { |
652
|
|
|
// On Windows, default to no ANSI, except in ANSICON and ConEmu. |
653
|
|
|
// Everywhere else, default to ANSI if stdout is a terminal. |
654
|
1 |
|
define('USE_ANSI', ('\\' === DIRECTORY_SEPARATOR) |
655
|
1 |
|
? (false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI')) |
656
|
1 |
|
: (function_exists('posix_isatty') && posix_isatty(1))); |
657
|
|
|
} |
658
|
|
|
|
659
|
5 |
|
foreach ($argv as $key => $val) { |
660
|
5 |
View Code Duplication |
if (0 === strpos($val, '--install-dir')) { |
|
|
|
|
661
|
2 |
|
if (13 === strlen($val) && isset($argv[$key + 1])) { |
662
|
2 |
|
$this->installDir = trim($argv[$key + 1]); |
663
|
2 |
|
} else { |
664
|
|
|
$this->installDir = trim(substr($val, 14)); |
665
|
|
|
} |
666
|
2 |
|
} |
667
|
|
|
|
668
|
5 |
View Code Duplication |
if (0 === strpos($val, '--version')) { |
|
|
|
|
669
|
1 |
|
if (9 === strlen($val) && isset($argv[$key + 1])) { |
670
|
1 |
|
$this->version = trim($argv[$key + 1]); |
671
|
1 |
|
} else { |
672
|
|
|
$this->version = trim(substr($val, 10)); |
673
|
|
|
} |
674
|
1 |
|
} |
675
|
|
|
|
676
|
5 |
View Code Duplication |
if (0 === strpos($val, '--filename')) { |
|
|
|
|
677
|
|
|
if (10 === strlen($val) && isset($argv[$key + 1])) { |
678
|
|
|
$this->filename = trim($argv[$key + 1]); |
679
|
|
|
} else { |
680
|
|
|
$this->filename = trim(substr($val, 11)); |
681
|
|
|
} |
682
|
|
|
} |
683
|
5 |
|
} |
684
|
5 |
|
} |
685
|
|
|
|
686
|
|
|
/** |
687
|
|
|
* Prints output indicating a success. |
688
|
|
|
* |
689
|
|
|
* @param string $text The text to print. |
690
|
|
|
*/ |
691
|
5 |
|
private function success($text) |
692
|
|
|
{ |
693
|
5 |
|
printf(USE_ANSI ? "\033[0;32m%s\033[0m" : '%s', $text.PHP_EOL); |
694
|
5 |
|
} |
695
|
|
|
|
696
|
|
|
/** |
697
|
|
|
* Prints output indicating an error. |
698
|
|
|
* |
699
|
|
|
* @param string $text The text to print. |
700
|
|
|
*/ |
701
|
1 |
|
private function error($text) |
702
|
|
|
{ |
703
|
1 |
|
printf(USE_ANSI ? "\033[31;31m%s\033[0m" : '%s', $text.PHP_EOL); |
704
|
1 |
|
} |
705
|
|
|
|
706
|
|
|
/** |
707
|
|
|
* Prints output indicating some information. |
708
|
|
|
* |
709
|
|
|
* @param string $text The text to print. |
710
|
|
|
*/ |
711
|
5 |
|
private function info($text) |
712
|
|
|
{ |
713
|
5 |
|
printf(USE_ANSI ? "\033[33;33m%s\033[0m" : '%s', $text.PHP_EOL); |
714
|
5 |
|
} |
715
|
|
|
} |
716
|
|
|
|
If you suppress an error, we recommend checking for the error condition explicitly: