|
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: