Bearsampp 2026.9.23
Loading...
Searching...
No Matches
Install.php
Go to the documentation of this file.
1<?php
16
20require_once 'PEAR/Command/Common.php';
21
37{
38 // {{{ properties
39
40 var $commands = array(
41 'install' => array(
42 'summary' => 'Install Package',
43 'function' => 'doInstall',
44 'shortcut' => 'i',
45 'options' => array(
46 'force' => array(
47 'shortopt' => 'f',
48 'doc' => 'will overwrite newer installed packages',
49 ),
50 'loose' => array(
51 'shortopt' => 'l',
52 'doc' => 'do not check for recommended dependency version',
53 ),
54 'nodeps' => array(
55 'shortopt' => 'n',
56 'doc' => 'ignore dependencies, install anyway',
57 ),
58 'register-only' => array(
59 'shortopt' => 'r',
60 'doc' => 'do not install files, only register the package as installed',
61 ),
62 'soft' => array(
63 'shortopt' => 's',
64 'doc' => 'soft install, fail silently, or upgrade if already installed',
65 ),
66 'nobuild' => array(
67 'shortopt' => 'B',
68 'doc' => 'don\'t build C extensions',
69 ),
70 'configureoptions' => array(
71 'shortopt' => 'D',
72 'arg' => 'OPTION1=VALUE[ OPTION2=VALUE]',
73 'doc' => 'space-delimited list of configure options',
74 ),
75 'nocompress' => array(
76 'shortopt' => 'Z',
77 'doc' => 'request uncompressed files when downloading',
78 ),
79 'installroot' => array(
80 'shortopt' => 'R',
81 'arg' => 'DIR',
82 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
83 ),
84 'packagingroot' => array(
85 'shortopt' => 'P',
86 'arg' => 'DIR',
87 'doc' => 'root directory used when packaging files, like RPM packaging',
88 ),
89 'ignore-errors' => array(
90 'doc' => 'force install even if there were errors',
91 ),
92 'alldeps' => array(
93 'shortopt' => 'a',
94 'doc' => 'install all required and optional dependencies',
95 ),
96 'onlyreqdeps' => array(
97 'shortopt' => 'o',
98 'doc' => 'install all required dependencies',
99 ),
100 'offline' => array(
101 'shortopt' => 'O',
102 'doc' => 'do not attempt to download any urls or contact channels',
103 ),
104 'pretend' => array(
105 'shortopt' => 'p',
106 'doc' => 'Only list the packages that would be downloaded',
107 ),
108 ),
109 'doc' => '[channel/]<package> ...
110Installs one or more PEAR packages. You can specify a package to
111install in four ways:
112
113"Package-1.0.tgz" : installs from a local file
114
115"http://example.com/Package-1.0.tgz" : installs from
116anywhere on the net.
117
118"package.xml" : installs the package described in
119package.xml. Useful for testing, or for wrapping a PEAR package in
120another package manager such as RPM.
121
122"Package[-version/state][.tar]" : queries your default channel\'s server
123({config master_server}) and downloads the newest package with
124the preferred quality/state ({config preferred_state}).
125
126To retrieve Package version 1.1, use "Package-1.1," to retrieve
127Package state beta, use "Package-beta." To retrieve an uncompressed
128file, append .tar (make sure there is no file by the same name first)
129
130To download a package from another channel, prefix with the channel name like
131"channel/Package"
132
133More than one package may be specified at once. It is ok to mix these
134four ways of specifying packages.
135'),
136 'upgrade' => array(
137 'summary' => 'Upgrade Package',
138 'function' => 'doInstall',
139 'shortcut' => 'up',
140 'options' => array(
141 'channel' => array(
142 'shortopt' => 'c',
143 'doc' => 'upgrade packages from a specific channel',
144 'arg' => 'CHAN',
145 ),
146 'force' => array(
147 'shortopt' => 'f',
148 'doc' => 'overwrite newer installed packages',
149 ),
150 'loose' => array(
151 'shortopt' => 'l',
152 'doc' => 'do not check for recommended dependency version',
153 ),
154 'nodeps' => array(
155 'shortopt' => 'n',
156 'doc' => 'ignore dependencies, upgrade anyway',
157 ),
158 'register-only' => array(
159 'shortopt' => 'r',
160 'doc' => 'do not install files, only register the package as upgraded',
161 ),
162 'nobuild' => array(
163 'shortopt' => 'B',
164 'doc' => 'don\'t build C extensions',
165 ),
166 'nocompress' => array(
167 'shortopt' => 'Z',
168 'doc' => 'request uncompressed files when downloading',
169 ),
170 'installroot' => array(
171 'shortopt' => 'R',
172 'arg' => 'DIR',
173 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
174 ),
175 'ignore-errors' => array(
176 'doc' => 'force install even if there were errors',
177 ),
178 'alldeps' => array(
179 'shortopt' => 'a',
180 'doc' => 'install all required and optional dependencies',
181 ),
182 'onlyreqdeps' => array(
183 'shortopt' => 'o',
184 'doc' => 'install all required dependencies',
185 ),
186 'offline' => array(
187 'shortopt' => 'O',
188 'doc' => 'do not attempt to download any urls or contact channels',
189 ),
190 'pretend' => array(
191 'shortopt' => 'p',
192 'doc' => 'Only list the packages that would be downloaded',
193 ),
194 ),
195 'doc' => '<package> ...
196Upgrades one or more PEAR packages. See documentation for the
197"install" command for ways to specify a package.
198
199When upgrading, your package will be updated if the provided new
200package has a higher version number (use the -f option if you need to
201upgrade anyway).
202
203More than one package may be specified at once.
204'),
205 'upgrade-all' => array(
206 'summary' => 'Upgrade All Packages [Deprecated in favor of calling upgrade with no parameters]',
207 'function' => 'doUpgradeAll',
208 'shortcut' => 'ua',
209 'options' => array(
210 'channel' => array(
211 'shortopt' => 'c',
212 'doc' => 'upgrade packages from a specific channel',
213 'arg' => 'CHAN',
214 ),
215 'nodeps' => array(
216 'shortopt' => 'n',
217 'doc' => 'ignore dependencies, upgrade anyway',
218 ),
219 'register-only' => array(
220 'shortopt' => 'r',
221 'doc' => 'do not install files, only register the package as upgraded',
222 ),
223 'nobuild' => array(
224 'shortopt' => 'B',
225 'doc' => 'don\'t build C extensions',
226 ),
227 'nocompress' => array(
228 'shortopt' => 'Z',
229 'doc' => 'request uncompressed files when downloading',
230 ),
231 'installroot' => array(
232 'shortopt' => 'R',
233 'arg' => 'DIR',
234 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
235 ),
236 'ignore-errors' => array(
237 'doc' => 'force install even if there were errors',
238 ),
239 'loose' => array(
240 'doc' => 'do not check for recommended dependency version',
241 ),
242 ),
243 'doc' => '
244WARNING: This function is deprecated in favor of using the upgrade command with no params
245
246Upgrades all packages that have a newer release available. Upgrades are
247done only if there is a release available of the state specified in
248"preferred_state" (currently {config preferred_state}), or a state considered
249more stable.
250'),
251 'uninstall' => array(
252 'summary' => 'Un-install Package',
253 'function' => 'doUninstall',
254 'shortcut' => 'un',
255 'options' => array(
256 'nodeps' => array(
257 'shortopt' => 'n',
258 'doc' => 'ignore dependencies, uninstall anyway',
259 ),
260 'register-only' => array(
261 'shortopt' => 'r',
262 'doc' => 'do not remove files, only register the packages as not installed',
263 ),
264 'installroot' => array(
265 'shortopt' => 'R',
266 'arg' => 'DIR',
267 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
268 ),
269 'ignore-errors' => array(
270 'doc' => 'force install even if there were errors',
271 ),
272 'offline' => array(
273 'shortopt' => 'O',
274 'doc' => 'do not attempt to uninstall remotely',
275 ),
276 ),
277 'doc' => '[channel/]<package> ...
278Uninstalls one or more PEAR packages. More than one package may be
279specified at once. Prefix with channel name to uninstall from a
280channel not in your default channel ({config default_channel})
281'),
282 'bundle' => array(
283 'summary' => 'Unpacks a Pecl Package',
284 'function' => 'doBundle',
285 'shortcut' => 'bun',
286 'options' => array(
287 'destination' => array(
288 'shortopt' => 'd',
289 'arg' => 'DIR',
290 'doc' => 'Optional destination directory for unpacking (defaults to current path or "ext" if exists)',
291 ),
292 'force' => array(
293 'shortopt' => 'f',
294 'doc' => 'Force the unpacking even if there were errors in the package',
295 ),
296 ),
297 'doc' => '<package>
298Unpacks a Pecl Package into the selected location. It will download the
299package if needed.
300'),
301 'run-scripts' => array(
302 'summary' => 'Run Post-Install Scripts bundled with a package',
303 'function' => 'doRunScripts',
304 'shortcut' => 'rs',
305 'options' => array(
306 ),
307 'doc' => '<package>
308Run post-installation scripts in package <package>, if any exist.
309'),
310 );
311
312 // }}}
313 // {{{ constructor
314
321 {
322 parent::__construct($ui, $config);
323 }
324
325 // }}}
326
331 {
332 if (!class_exists('PEAR_Downloader')) {
333 require_once 'PEAR/Downloader.php';
334 }
336 return $a;
337 }
338
342 function &getInstaller(&$ui)
343 {
344 if (!class_exists('PEAR_Installer')) {
345 require_once 'PEAR/Installer.php';
346 }
347 $a = new PEAR_Installer($ui);
348 return $a;
349 }
350
351 function enableExtension($binaries, $type)
352 {
353 if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
354 return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
355 }
356 $ini = $this->_parseIni($phpini);
357 if (PEAR::isError($ini)) {
358 return $ini;
359 }
360 $line = 0;
361 if ($type == 'extsrc' || $type == 'extbin') {
362 $search = 'extensions';
363 $enable = 'extension';
364 } else {
365 $search = 'zend_extensions';
366 ob_start();
367 phpinfo(INFO_GENERAL);
368 $info = ob_get_contents();
369 ob_end_clean();
370 $debug = function_exists('leak') ? '_debug' : '';
371 $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
372 $enable = 'zend_extension' . $debug . $ts;
373 }
374 foreach ($ini[$search] as $line => $extension) {
375 if (in_array($extension, $binaries, true) || in_array(
376 $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
377 // already enabled - assume if one is, all are
378 return true;
379 }
380 }
381 if ($line) {
382 $newini = array_slice($ini['all'], 0, $line);
383 } else {
384 $newini = array();
385 }
386 foreach ($binaries as $binary) {
387 if ($ini['extension_dir']) {
388 $binary = basename($binary);
389 }
390 $newini[] = $enable . '="' . $binary . '"' . (OS_UNIX ? "\n" : "\r\n");
391 }
392 $newini = array_merge($newini, array_slice($ini['all'], $line));
393 $fp = @fopen($phpini, 'wb');
394 if (!$fp) {
395 return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
396 }
397 foreach ($newini as $line) {
398 fwrite($fp, $line);
399 }
400 fclose($fp);
401 return true;
402 }
403
404 function disableExtension($binaries, $type)
405 {
406 if (!($phpini = $this->config->get('php_ini', null, 'pear.php.net'))) {
407 return PEAR::raiseError('configuration option "php_ini" is not set to php.ini location');
408 }
409 $ini = $this->_parseIni($phpini);
410 if (PEAR::isError($ini)) {
411 return $ini;
412 }
413 $line = 0;
414 if ($type == 'extsrc' || $type == 'extbin') {
415 $search = 'extensions';
416 $enable = 'extension';
417 } else {
418 $search = 'zend_extensions';
419 ob_start();
420 phpinfo(INFO_GENERAL);
421 $info = ob_get_contents();
422 ob_end_clean();
423 $debug = function_exists('leak') ? '_debug' : '';
424 $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
425 $enable = 'zend_extension' . $debug . $ts;
426 }
427 $found = false;
428 foreach ($ini[$search] as $line => $extension) {
429 if (in_array($extension, $binaries, true) || in_array(
430 $ini['extension_dir'] . DIRECTORY_SEPARATOR . $extension, $binaries, true)) {
431 $found = true;
432 break;
433 }
434 }
435 if (!$found) {
436 // not enabled
437 return true;
438 }
439 $fp = @fopen($phpini, 'wb');
440 if (!$fp) {
441 return PEAR::raiseError('cannot open php.ini "' . $phpini . '" for writing');
442 }
443 if ($line) {
444 $newini = array_slice($ini['all'], 0, $line);
445 // delete the enable line
446 $newini = array_merge($newini, array_slice($ini['all'], $line + 1));
447 } else {
448 $newini = array_slice($ini['all'], 1);
449 }
450 foreach ($newini as $line) {
451 fwrite($fp, $line);
452 }
453 fclose($fp);
454 return true;
455 }
456
457 function _parseIni($filename)
458 {
459 if (!file_exists($filename)) {
460 return PEAR::raiseError('php.ini "' . $filename . '" does not exist');
461 }
462
463 if (filesize($filename) > 300000) {
464 return PEAR::raiseError('php.ini "' . $filename . '" is too large, aborting');
465 }
466
467 ob_start();
468 phpinfo(INFO_GENERAL);
469 $info = ob_get_contents();
470 ob_end_clean();
471 $debug = function_exists('leak') ? '_debug' : '';
472 $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
473 $zend_extension_line = 'zend_extension' . $debug . $ts;
474 $all = @file($filename);
475 if ($all === false) {
476 return PEAR::raiseError('php.ini "' . $filename .'" could not be read');
477 }
478 $zend_extensions = $extensions = array();
479 // assume this is right, but pull from the php.ini if it is found
480 $extension_dir = ini_get('extension_dir');
481 foreach ($all as $linenum => $line) {
482 $line = trim($line);
483 if (!$line) {
484 continue;
485 }
486 if ($line[0] == ';') {
487 continue;
488 }
489 if (strtolower(substr($line, 0, 13)) == 'extension_dir') {
490 $line = trim(substr($line, 13));
491 if ($line[0] == '=') {
492 $x = trim(substr($line, 1));
493 $x = explode(';', $x);
494 $extension_dir = str_replace('"', '', array_shift($x));
495 continue;
496 }
497 }
498 if (strtolower(substr($line, 0, 9)) == 'extension') {
499 $line = trim(substr($line, 9));
500 if ($line[0] == '=') {
501 $x = trim(substr($line, 1));
502 $x = explode(';', $x);
503 $extensions[$linenum] = str_replace('"', '', array_shift($x));
504 continue;
505 }
506 }
507 if (strtolower(substr($line, 0, strlen($zend_extension_line))) ==
508 $zend_extension_line) {
509 $line = trim(substr($line, strlen($zend_extension_line)));
510 if ($line[0] == '=') {
511 $x = trim(substr($line, 1));
512 $x = explode(';', $x);
513 $zend_extensions[$linenum] = str_replace('"', '', array_shift($x));
514 continue;
515 }
516 }
517 }
518 return array(
519 'extensions' => $extensions,
520 'zend_extensions' => $zend_extensions,
521 'extension_dir' => $extension_dir,
522 'all' => $all,
523 );
524 }
525
526 // {{{ doInstall()
527
528 function doInstall($command, $options, $params)
529 {
530 if (!class_exists('PEAR_PackageFile')) {
531 require_once 'PEAR/PackageFile.php';
532 }
533
534 if (isset($options['installroot']) && isset($options['packagingroot'])) {
535 return $this->raiseError('ERROR: cannot use both --installroot and --packagingroot');
536 }
537
538 $reg = &$this->config->getRegistry();
539 $channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
540 if (!$reg->channelExists($channel)) {
541 return $this->raiseError('Channel "' . $channel . '" does not exist');
542 }
543
544 if (empty($this->installer)) {
545 $this->installer = &$this->getInstaller($this->ui);
546 }
547
548 if ($command == 'upgrade' || $command == 'upgrade-all') {
549 // If people run the upgrade command but pass nothing, emulate a upgrade-all
550 if ($command == 'upgrade' && empty($params)) {
551 return $this->doUpgradeAll($command, $options, $params);
552 }
553 $options['upgrade'] = true;
554 } else {
555 $packages = $params;
556 }
557
558 $instreg = &$reg; // instreg used to check if package is installed
559 if (isset($options['packagingroot']) && !isset($options['upgrade'])) {
560 $packrootphp_dir = $this->installer->_prependPath(
561 $this->config->get('php_dir', null, 'pear.php.net'),
562 $options['packagingroot']);
563 $metadata_dir = $this->config->get('metadata_dir', null, 'pear.php.net');
564 if ($metadata_dir) {
565 $metadata_dir = $this->installer->_prependPath(
566 $metadata_dir,
567 $options['packagingroot']);
568 }
569 $instreg = new PEAR_Registry($packrootphp_dir, false, false, $metadata_dir); // other instreg!
570
571 if ($this->config->get('verbose') > 2) {
572 $this->ui->outputData('using package root: ' . $options['packagingroot']);
573 }
574 }
575
576 $abstractpackages = $otherpackages = array();
577 // parse params
579
580 foreach ($params as $param) {
581 if (strpos($param, 'http://') === 0) {
582 $otherpackages[] = $param;
583 continue;
584 }
585
586 if (strpos($param, 'channel://') === false && @file_exists($param)) {
587 if (isset($options['force'])) {
588 $otherpackages[] = $param;
589 continue;
590 }
591
592 $pkg = new PEAR_PackageFile($this->config);
593 $pf = $pkg->fromAnyFile($param, PEAR_VALIDATE_DOWNLOADING);
594 if (PEAR::isError($pf)) {
595 $otherpackages[] = $param;
596 continue;
597 }
598
599 $exists = $reg->packageExists($pf->getPackage(), $pf->getChannel());
600 $pversion = $reg->packageInfo($pf->getPackage(), 'version', $pf->getChannel());
601 $version_compare = version_compare($pf->getVersion(), $pversion, '<=');
602 if ($exists && $version_compare) {
603 if ($this->config->get('verbose')) {
604 $this->ui->outputData('Ignoring installed package ' .
605 $reg->parsedPackageNameToString(
606 array('package' => $pf->getPackage(),
607 'channel' => $pf->getChannel()), true));
608 }
609 continue;
610 }
611 $otherpackages[] = $param;
612 continue;
613 }
614
615 $e = $reg->parsePackageName($param, $channel);
616 if (PEAR::isError($e)) {
617 $otherpackages[] = $param;
618 } else {
619 $abstractpackages[] = $e;
620 }
621 }
623
624 // if there are any local package .tgz or remote static url, we can't
625 // filter. The filter only works for abstract packages
626 if (count($abstractpackages) && !isset($options['force'])) {
627 // when not being forced, only do necessary upgrades/installs
628 if (isset($options['upgrade'])) {
629 $abstractpackages = $this->_filterUptodatePackages($abstractpackages, $command);
630 } else {
631 $count = count($abstractpackages);
632 foreach ($abstractpackages as $i => $package) {
633 if (isset($package['group'])) {
634 // do not filter out install groups
635 continue;
636 }
637
638 if ($instreg->packageExists($package['package'], $package['channel'])) {
639 if ($count > 1) {
640 if ($this->config->get('verbose')) {
641 $this->ui->outputData('Ignoring installed package ' .
642 $reg->parsedPackageNameToString($package, true));
643 }
644 unset($abstractpackages[$i]);
645 } elseif ($count === 1) {
646 // Lets try to upgrade it since it's already installed
647 $options['upgrade'] = true;
648 }
649 }
650 }
651 }
652 $abstractpackages =
653 array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
654 } elseif (count($abstractpackages)) {
655 $abstractpackages =
656 array_map(array($reg, 'parsedPackageNameToString'), $abstractpackages);
657 }
658
659 $packages = array_merge($abstractpackages, $otherpackages);
660 if (!count($packages)) {
661 $c = '';
662 if (isset($options['channel'])){
663 $c .= ' in channel "' . $options['channel'] . '"';
664 }
665 $this->ui->outputData('Nothing to ' . $command . $c);
666 return true;
667 }
668
669 $this->downloader = &$this->getDownloader($this->ui, $options, $this->config);
670 $errors = $downloaded = $binaries = array();
671 $downloaded = &$this->downloader->download($packages);
672 if (PEAR::isError($downloaded)) {
673 return $this->raiseError($downloaded);
674 }
675
676 $errors = $this->downloader->getErrorMsgs();
677 if (count($errors)) {
678 $err = array();
679 $err['data'] = array();
680 foreach ($errors as $error) {
681 if ($error !== null) {
682 $err['data'][] = array($error);
683 }
684 }
685
686 if (!empty($err['data'])) {
687 $err['headline'] = 'Install Errors';
688 $this->ui->outputData($err);
689 }
690
691 if (!count($downloaded)) {
692 return $this->raiseError("$command failed");
693 }
694 }
695
696 $data = array(
697 'headline' => 'Packages that would be Installed'
698 );
699
700 if (isset($options['pretend'])) {
701 foreach ($downloaded as $package) {
702 $data['data'][] = array($reg->parsedPackageNameToString($package->getParsedPackage()));
703 }
704 $this->ui->outputData($data, 'pretend');
705 return true;
706 }
707
708 $this->installer->setOptions($options);
709 $this->installer->sortPackagesForInstall($downloaded);
710 if (PEAR::isError($err = $this->installer->setDownloadedPackages($downloaded))) {
711 $this->raiseError($err->getMessage());
712 return true;
713 }
714
715 $binaries = $extrainfo = array();
716 foreach ($downloaded as $param) {
718 $info = $this->installer->install($param, $options);
720 if (PEAR::isError($info)) {
721 $oldinfo = $info;
722 $pkg = &$param->getPackageFile();
723 if ($info->getCode() != PEAR_INSTALLER_NOBINARY) {
724 if (!($info = $pkg->installBinary($this->installer))) {
725 return $this->raiseError('ERROR: ' .$oldinfo->getMessage());
726 }
727
728 // we just installed a different package than requested,
729 // let's change the param and info so that the rest of this works
730 $param = $info[0];
731 $info = $info[1];
732 }
733 }
734
735 if (!is_array($info)) {
736 return $this->raiseError("$command failed");
737 }
738
739 if ($param->getPackageType() == 'extsrc' ||
740 $param->getPackageType() == 'extbin' ||
741 $param->getPackageType() == 'zendextsrc' ||
742 $param->getPackageType() == 'zendextbin'
743 ) {
744 $pkg = &$param->getPackageFile();
745 if ($instbin = $pkg->getInstalledBinary()) {
746 $instpkg = &$instreg->getPackage($instbin, $pkg->getChannel());
747 } else {
748 $instpkg = &$instreg->getPackage($pkg->getPackage(), $pkg->getChannel());
749 }
750
751 foreach ($instpkg->getFilelist() as $name => $atts) {
752 $pinfo = pathinfo($atts['installed_as']);
753 if (!isset($pinfo['extension']) ||
754 in_array($pinfo['extension'], array('c', 'h'))
755 ) {
756 continue; // make sure we don't match php_blah.h
757 }
758
759 if ((strpos($pinfo['basename'], 'php_') === 0 &&
760 $pinfo['extension'] == 'dll') ||
761 // most unices
762 $pinfo['extension'] == 'so' ||
763 // hp-ux
764 $pinfo['extension'] == 'sl') {
765 $binaries[] = array($atts['installed_as'], $pinfo);
766 break;
767 }
768 }
769
770 if (count($binaries)) {
771 foreach ($binaries as $pinfo) {
773 $ret = $this->enableExtension(array($pinfo[0]), $param->getPackageType());
775 if (PEAR::isError($ret)) {
776 $extrainfo[] = $ret->getMessage();
777 if ($param->getPackageType() == 'extsrc' ||
778 $param->getPackageType() == 'extbin') {
779 $exttype = 'extension';
780 $extpath = $pinfo[1]['basename'];
781 } else {
782 $exttype = 'zend_extension';
783 $extpath = $atts['installed_as'];
784 }
785 $extrainfo[] = 'You should add "' . $exttype . '=' .
786 $extpath . '" to php.ini';
787 } else {
788 $extrainfo[] = 'Extension ' . $instpkg->getProvidesExtension() .
789 ' enabled in php.ini';
790 }
791 }
792 }
793 }
794
795 if ($this->config->get('verbose') > 0) {
796 $chan = $param->getChannel();
797 $label = $reg->parsedPackageNameToString(
798 array(
799 'channel' => $chan,
800 'package' => $param->getPackage(),
801 'version' => $param->getVersion(),
802 ));
803 $out = array('data' => "$command ok: $label");
804 if (isset($info['release_warnings'])) {
805 $out['release_warnings'] = $info['release_warnings'];
806 }
807 $this->ui->outputData($out, $command);
808
809 if (!isset($options['register-only']) && !isset($options['offline'])) {
810 if ($this->config->isDefinedLayer('ftp')) {
812 $info = $this->installer->ftpInstall($param);
814 if (PEAR::isError($info)) {
815 $this->ui->outputData($info->getMessage());
816 $this->ui->outputData("remote install failed: $label");
817 } else {
818 $this->ui->outputData("remote install ok: $label");
819 }
820 }
821 }
822 }
823
824 $deps = $param->getDeps();
825 if ($deps) {
826 if (isset($deps['group'])) {
827 $groups = $deps['group'];
828 if (!isset($groups[0])) {
829 $groups = array($groups);
830 }
831
832 foreach ($groups as $group) {
833 if ($group['attribs']['name'] == 'default') {
834 // default group is always installed, unless the user
835 // explicitly chooses to install another group
836 continue;
837 }
838 $extrainfo[] = $param->getPackage() . ': Optional feature ' .
839 $group['attribs']['name'] . ' available (' .
840 $group['attribs']['hint'] . ')';
841 }
842
843 $extrainfo[] = $param->getPackage() .
844 ': To install optional features use "pear install ' .
845 $reg->parsedPackageNameToString(
846 array('package' => $param->getPackage(),
847 'channel' => $param->getChannel()), true) .
848 '#featurename"';
849 }
850 }
851
852 $pkg = &$instreg->getPackage($param->getPackage(), $param->getChannel());
853 // $pkg may be NULL if install is a 'fake' install via --packagingroot
854 if (is_object($pkg)) {
855 $pkg->setConfig($this->config);
856 if ($list = $pkg->listPostinstallScripts()) {
857 $pn = $reg->parsedPackageNameToString(array('channel' =>
858 $param->getChannel(), 'package' => $param->getPackage()), true);
859 $extrainfo[] = $pn . ' has post-install scripts:';
860 foreach ($list as $file) {
861 $extrainfo[] = $file;
862 }
863 $extrainfo[] = $param->getPackage() .
864 ': Use "pear run-scripts ' . $pn . '" to finish setup.';
865 $extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES';
866 }
867 }
868 }
869
870 if (count($extrainfo)) {
871 foreach ($extrainfo as $info) {
872 $this->ui->outputData($info);
873 }
874 }
875
876 return true;
877 }
878
879 // }}}
880 // {{{ doUpgradeAll()
881
882 function doUpgradeAll($command, $options, $params)
883 {
884 $reg = &$this->config->getRegistry();
885 $upgrade = array();
886
887 if (isset($options['channel'])) {
888 $channels = array($options['channel']);
889 } else {
890 $channels = $reg->listChannels();
891 }
892
893 foreach ($channels as $channel) {
894 if ($channel == '__uri') {
895 continue;
896 }
897
898 // parse name with channel
899 foreach ($reg->listPackages($channel) as $name) {
900 $upgrade[] = $reg->parsedPackageNameToString(array(
901 'channel' => $channel,
902 'package' => $name
903 ));
904 }
905 }
906
907 $err = $this->doInstall($command, $options, $upgrade);
908 if (PEAR::isError($err)) {
909 $this->ui->outputData($err->getMessage(), $command);
910 }
911 }
912
913 // }}}
914 // {{{ doUninstall()
915
916 function doUninstall($command, $options, $params)
917 {
918 if (count($params) < 1) {
919 return $this->raiseError("Please supply the package(s) you want to uninstall");
920 }
921
922 if (empty($this->installer)) {
923 $this->installer = &$this->getInstaller($this->ui);
924 }
925
926 if (isset($options['remoteconfig'])) {
927 $e = $this->config->readFTPConfigFile($options['remoteconfig']);
928 if (!PEAR::isError($e)) {
929 $this->installer->setConfig($this->config);
930 }
931 }
932
933 $reg = &$this->config->getRegistry();
934 $newparams = array();
935 $binaries = array();
936 $badparams = array();
937 foreach ($params as $pkg) {
938 $channel = $this->config->get('default_channel');
940 $parsed = $reg->parsePackageName($pkg, $channel);
942 if (!$parsed || PEAR::isError($parsed)) {
943 $badparams[] = $pkg;
944 continue;
945 }
946 $package = $parsed['package'];
947 $channel = $parsed['channel'];
948 $info = &$reg->getPackage($package, $channel);
949 if ($info === null &&
950 ($channel == 'pear.php.net' || $channel == 'pecl.php.net')) {
951 // make sure this isn't a package that has flipped from pear to pecl but
952 // used a package.xml 1.0
953 $testc = ($channel == 'pear.php.net') ? 'pecl.php.net' : 'pear.php.net';
954 $info = &$reg->getPackage($package, $testc);
955 if ($info !== null) {
956 $channel = $testc;
957 }
958 }
959 if ($info === null) {
960 $badparams[] = $pkg;
961 } else {
962 $newparams[] = &$info;
963 // check for binary packages (this is an alias for those packages if so)
964 if ($installedbinary = $info->getInstalledBinary()) {
965 $this->ui->log('adding binary package ' .
966 $reg->parsedPackageNameToString(array('channel' => $channel,
967 'package' => $installedbinary), true));
968 $newparams[] = &$reg->getPackage($installedbinary, $channel);
969 }
970 // add the contents of a dependency group to the list of installed packages
971 if (isset($parsed['group'])) {
972 $group = $info->getDependencyGroup($parsed['group']);
973 if ($group) {
974 $installed = $reg->getInstalledGroup($group);
975 if ($installed) {
976 foreach ($installed as $i => $p) {
977 $newparams[] = &$installed[$i];
978 }
979 }
980 }
981 }
982 }
983 }
984 $err = $this->installer->sortPackagesForUninstall($newparams);
985 if (PEAR::isError($err)) {
986 $this->ui->outputData($err->getMessage(), $command);
987 return true;
988 }
989 $params = $newparams;
990 // twist this to use it to check on whether dependent packages are also being uninstalled
991 // for circular dependencies like subpackages
992 $this->installer->setUninstallPackages($newparams);
993 $params = array_merge($params, $badparams);
994 $binaries = array();
995 foreach ($params as $pkg) {
996 $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
997 if ($err = $this->installer->uninstall($pkg, $options)) {
998 $this->installer->popErrorHandling();
999 if (PEAR::isError($err)) {
1000 $this->ui->outputData($err->getMessage(), $command);
1001 continue;
1002 }
1003 if ($pkg->getPackageType() == 'extsrc' ||
1004 $pkg->getPackageType() == 'extbin' ||
1005 $pkg->getPackageType() == 'zendextsrc' ||
1006 $pkg->getPackageType() == 'zendextbin') {
1007 if ($instbin = $pkg->getInstalledBinary()) {
1008 continue; // this will be uninstalled later
1009 }
1010
1011 foreach ($pkg->getFilelist() as $name => $atts) {
1012 $pinfo = pathinfo($atts['installed_as']);
1013 if (!isset($pinfo['extension']) ||
1014 in_array($pinfo['extension'], array('c', 'h'))) {
1015 continue; // make sure we don't match php_blah.h
1016 }
1017 if ((strpos($pinfo['basename'], 'php_') === 0 &&
1018 $pinfo['extension'] == 'dll') ||
1019 // most unices
1020 $pinfo['extension'] == 'so' ||
1021 // hp-ux
1022 $pinfo['extension'] == 'sl') {
1023 $binaries[] = array($atts['installed_as'], $pinfo);
1024 break;
1025 }
1026 }
1027 if (count($binaries)) {
1028 foreach ($binaries as $pinfo) {
1030 $ret = $this->disableExtension(array($pinfo[0]), $pkg->getPackageType());
1032 if (PEAR::isError($ret)) {
1033 $extrainfo[] = $ret->getMessage();
1034 if ($pkg->getPackageType() == 'extsrc' ||
1035 $pkg->getPackageType() == 'extbin') {
1036 $exttype = 'extension';
1037 } else {
1038 ob_start();
1039 phpinfo(INFO_GENERAL);
1040 $info = ob_get_contents();
1041 ob_end_clean();
1042 $debug = function_exists('leak') ? '_debug' : '';
1043 $ts = preg_match('/Thread Safety.+enabled/', $info) ? '_ts' : '';
1044 $exttype = 'zend_extension' . $debug . $ts;
1045 }
1046 $this->ui->outputData('Unable to remove "' . $exttype . '=' .
1047 $pinfo[1]['basename'] . '" from php.ini', $command);
1048 } else {
1049 $this->ui->outputData('Extension ' . $pkg->getProvidesExtension() .
1050 ' disabled in php.ini', $command);
1051 }
1052 }
1053 }
1054 }
1055 $savepkg = $pkg;
1056 if ($this->config->get('verbose') > 0) {
1057 if (is_object($pkg)) {
1058 $pkg = $reg->parsedPackageNameToString($pkg);
1059 }
1060 $this->ui->outputData("uninstall ok: $pkg", $command);
1061 }
1062 if (!isset($options['offline']) && is_object($savepkg) &&
1063 defined('PEAR_REMOTEINSTALL_OK')) {
1064 if ($this->config->isDefinedLayer('ftp')) {
1065 $this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
1066 $info = $this->installer->ftpUninstall($savepkg);
1067 $this->installer->popErrorHandling();
1068 if (PEAR::isError($info)) {
1069 $this->ui->outputData($info->getMessage());
1070 $this->ui->outputData("remote uninstall failed: $pkg");
1071 } else {
1072 $this->ui->outputData("remote uninstall ok: $pkg");
1073 }
1074 }
1075 }
1076 } else {
1077 $this->installer->popErrorHandling();
1078 if (!is_object($pkg)) {
1079 return $this->raiseError("uninstall failed: $pkg");
1080 }
1081 $pkg = $reg->parsedPackageNameToString($pkg);
1082 }
1083 }
1084
1085 return true;
1086 }
1087
1088 // }}}
1089
1090
1091 // }}}
1092 // {{{ doBundle()
1093 /*
1094 (cox) It just downloads and untars the package, does not do
1095 any check that the PEAR_Installer::_installFile() does.
1096 */
1097
1098 function doBundle($command, $options, $params)
1099 {
1100 $opts = array(
1101 'force' => true,
1102 'nodeps' => true,
1103 'soft' => true,
1104 'downloadonly' => true
1105 );
1106 $downloader = &$this->getDownloader($this->ui, $opts, $this->config);
1107 $reg = &$this->config->getRegistry();
1108 if (count($params) < 1) {
1109 return $this->raiseError("Please supply the package you want to bundle");
1110 }
1111
1112 if (isset($options['destination'])) {
1113 if (!is_dir($options['destination'])) {
1114 System::mkdir('-p ' . $options['destination']);
1115 }
1116 $dest = realpath($options['destination']);
1117 } else {
1118 $pwd = getcwd();
1119 $dir = $pwd . DIRECTORY_SEPARATOR . 'ext';
1120 $dest = is_dir($dir) ? $dir : $pwd;
1121 }
1123 $err = $downloader->setDownloadDir($dest);
1125 if (PEAR::isError($err)) {
1126 return PEAR::raiseError('download directory "' . $dest .
1127 '" is not writeable.');
1128 }
1129 $result = &$downloader->download(array($params[0]));
1130 if (PEAR::isError($result)) {
1131 return $result;
1132 }
1133 if (!isset($result[0])) {
1134 return $this->raiseError('unable to unpack ' . $params[0]);
1135 }
1136 $pkgfile = &$result[0]->getPackageFile();
1137 $pkgname = $pkgfile->getName();
1138 $pkgversion = $pkgfile->getVersion();
1139
1140 // Unpacking -------------------------------------------------
1141 $dest .= DIRECTORY_SEPARATOR . $pkgname;
1142 $orig = $pkgname . '-' . $pkgversion;
1143
1144 $tar = new Archive_Tar($pkgfile->getArchiveFile());
1145 if (!$tar->extractModify($dest, $orig)) {
1146 return $this->raiseError('unable to unpack ' . $pkgfile->getArchiveFile());
1147 }
1148 $this->ui->outputData("Package ready at '$dest'");
1149 // }}}
1150 }
1151
1152 // }}}
1153
1154 function doRunScripts($command, $options, $params)
1155 {
1156 if (!isset($params[0])) {
1157 return $this->raiseError('run-scripts expects 1 parameter: a package name');
1158 }
1159
1160 $reg = &$this->config->getRegistry();
1162 $parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
1164 if (PEAR::isError($parsed)) {
1165 return $this->raiseError($parsed);
1166 }
1167
1168 $package = &$reg->getPackage($parsed['package'], $parsed['channel']);
1169 if (!is_object($package)) {
1170 return $this->raiseError('Could not retrieve package "' . $params[0] . '" from registry');
1171 }
1172
1173 $package->setConfig($this->config);
1174 $package->runPostinstallScripts();
1175 $this->ui->outputData('Install scripts complete', $command);
1176 return true;
1177 }
1178
1186 {
1187 $reg = &$this->config->getRegistry();
1188 $latestReleases = array();
1189
1190 $ret = array();
1191 foreach ($packages as $package) {
1192 if (isset($package['group'])) {
1193 $ret[] = $package;
1194 continue;
1195 }
1196
1197 $channel = $package['channel'];
1198 $name = $package['package'];
1199 if (!$reg->packageExists($name, $channel)) {
1200 $ret[] = $package;
1201 continue;
1202 }
1203
1204 if (!isset($latestReleases[$channel])) {
1205 // fill in cache for this channel
1206 $chan = $reg->getChannel($channel);
1207 if (PEAR::isError($chan)) {
1208 return $this->raiseError($chan);
1209 }
1210
1211 $base2 = false;
1212 $preferred_mirror = $this->config->get('preferred_mirror', null, $channel);
1213 if ($chan->supportsREST($preferred_mirror) &&
1214 (
1215 //($base2 = $chan->getBaseURL('REST1.4', $preferred_mirror)) ||
1216 ($base = $chan->getBaseURL('REST1.0', $preferred_mirror))
1217 )
1218 ) {
1219 $dorest = true;
1220 }
1221
1223 if (!isset($package['state'])) {
1224 $state = $this->config->get('preferred_state', null, $channel);
1225 } else {
1226 $state = $package['state'];
1227 }
1228
1229 if ($dorest) {
1230 if ($base2) {
1231 $rest = &$this->config->getREST('1.4', array());
1232 $base = $base2;
1233 } else {
1234 $rest = &$this->config->getREST('1.0', array());
1235 }
1236
1237 $installed = array_flip($reg->listPackages($channel));
1238 $latest = $rest->listLatestUpgrades($base, $state, $installed, $channel, $reg);
1239 }
1240
1242 if (PEAR::isError($latest)) {
1243 $this->ui->outputData('Error getting channel info from ' . $channel .
1244 ': ' . $latest->getMessage());
1245 continue;
1246 }
1247
1248 $latestReleases[$channel] = array_change_key_case($latest);
1249 }
1250
1251 // check package for latest release
1252 $name_lower = strtolower($name);
1253 if (isset($latestReleases[$channel][$name_lower])) {
1254 // if not set, up to date
1255 $inst_version = $reg->packageInfo($name, 'version', $channel);
1256 $channel_version = $latestReleases[$channel][$name_lower]['version'];
1257 if (version_compare($channel_version, $inst_version, 'le')) {
1258 // installed version is up-to-date
1259 continue;
1260 }
1261
1262 // maintain BC
1263 if ($command == 'upgrade-all') {
1264 $this->ui->outputData(array('data' => 'Will upgrade ' .
1265 $reg->parsedPackageNameToString($package)), $command);
1266 }
1267 $ret[] = $package;
1268 }
1269 }
1270
1271 return $ret;
1272 }
1273}
const PEAR_INSTALLER_NOBINARY
Definition Installer.php:25
const PEAR_ERROR_RETURN
Definition PEAR.php:24
const OS_UNIX
Definition PEAR.php:42
const PEAR_VALIDATE_DOWNLOADING
Definition Validate.php:21
$result
__construct(&$ui, &$config)
Definition Install.php:320
doInstall($command, $options, $params)
Definition Install.php:528
& getDownloader(&$ui, $options, &$config)
Definition Install.php:330
doUninstall($command, $options, $params)
Definition Install.php:916
enableExtension($binaries, $type)
Definition Install.php:351
_parseIni($filename)
Definition Install.php:457
_filterUptodatePackages($packages, $command)
Definition Install.php:1185
doUpgradeAll($command, $options, $params)
Definition Install.php:882
disableExtension($binaries, $type)
Definition Install.php:404
doRunScripts($command, $options, $params)
Definition Install.php:1154
doBundle($command, $options, $params)
Definition Install.php:1098
static staticPopErrorHandling()
Definition PEAR.php:654
static staticPushErrorHandling($mode, $options=null)
Definition PEAR.php:619
static isError($data, $code=null)
Definition PEAR.php:306
$options
Definition pearcmd.php:145
if( $raw) foreach($opts as $opt) if( $store_system_config) if($store_user_config) $command
Definition pearcmd.php:322
if(PEAR::isError($options)) $opts
Definition pearcmd.php:150