Bearsampp 2026.9.23
Loading...
Searching...
No Matches
PEAR_Installer Class Reference
Inheritance diagram for PEAR_Installer:
Collaboration diagram for PEAR_Installer:

Public Member Functions

 __construct (&$ui)
 _buildCallback ($what, $data)
 _compileSourceFiles ($savechannel, &$filelist, $configureoptions)
 _deletePackageFiles ($package, $channel=false, $backup=false)
 _installFile ($file, $atts, $tmp_path, $options)
 _installFile2 (&$pkg, $file, &$real_atts, $tmp_path, $options)
 _parsePackageXml (&$descfile)
 _removeBackups ($files)
 _sortDirs ($a, $b)
 _sortUninstall ($a, $b)
 addFileOperation ($type, $data)
 commitFileTransaction ()
 getInstallPackages ()
& getUninstallPackages ()
 install ($pkgfile, $options=array())
 mkDirHier ($dir)
 rollbackFileTransaction ()
 setConfig (&$config)
 setDownloadedPackages (&$pkgs)
 setOptions ($options)
 setUninstallPackages (&$pkgs)
 sortPackagesForUninstall (&$packages)
 startFileTransaction ($rollback_in_case=false)
 uninstall ($package, $options=array())
Public Member Functions inherited from PEAR_Downloader
 __construct ($ui=null, $options=array(), $config=null)
 _checkDepTree ($channel, $package, $b, $checked=array())
 _dependsOn ($a, $b)
 _detectDepCycle (&$deplinks)
 _downloadCallback ($msg, $params=null)
 _getDepPackageDownloadUrl ($dep, $parr)
 _getPackageDownloadUrl ($parr)
 _prependPath ($path, $prepend)
 _setupGraph ($t, $reg, &$deplinks, &$nodes, $package)
 _sortInstall ($a, $b)
 _testCycle ($test, $deplinks, $dep)
 analyzeDependencies (&$params, $force=false)
 configSet ($key, $value, $layer='user', $channel=false)
 discover ($channel)
& download ($params)
& getDependency2Object (&$c, $i, $p, $s)
 getDownloadDir ()
 getDownloadedPackages ()
 getErrorMsgs ()
 getOptions ()
 getPackageDownloadUrl ($package, $version=null, $channel=false)
 newDownloaderPackage (&$t)
 pushError ($errmsg, $code=-1)
 setDownloadDir ($dir)
 sortPackagesForInstall (&$packages)
 sortPkgDeps (&$packages, $uninstall=false)
Public Member Functions inherited from PEAR_Common
 __construct ()
 _PEAR_Common ()
 _postProcessChecks ($pf)
 _postProcessValidPackagexml (&$pf)
 buildProvidesArray ($srcinfo)
 detectDependencies ($any, $status_callback=null)
 downloadHttp ( $url, &$ui, $save_dir='.', $callback=null, $lastmodified=null, $accept=false, $channel=false)
 infoFromAny ($info)
 infoFromDescriptionFile ($descfile)
 infoFromString ($data)
 infoFromTgzFile ($file)
 log ($level, $msg, $append_crlf=true)
 mkTempDir ($tmpdir='')
 setFrontendObject (&$ui)
 validatePackageInfo ($info, &$errors, &$warnings, $dir_prefix='')
 validPackageName ($name)
 validPackageVersion ($ver)
 xmlFromInfo ($pkginfo)
Public Member Functions inherited from PEAR
 __call ($method, $arguments)
 __construct ($error_class=null)
 _checkDelExpect ($error_code)
 _PEAR ()
 delExpect ($error_code)
 expectError ($code=' *')
 PEAR ($error_class=null)
 popExpect ()

Data Fields

 $_downloadedPackages
 $debug = 1
 $docdir
 $extdir
 $file_operations = array()
 $installroot = ''
 $phpdir
 $pkgdir
 $registry
 $tmpdir
Data Fields inherited from PEAR_Downloader
 $_downloadDir
 $_downloadedPackages = array()
 $_errorStack = array()
 $_installed = array()
 $_internalDownload = false
 $_options
 $_packageSortTree
 $_preferredState
 $_registry
 $_toDownload = array()
Data Fields inherited from PEAR_Common
 $_validPackageFile
 $config = null
 $current_attributes = array()
 $current_element
 $current_path = null
 $element_stack = array()
 $pkginfo = array()
 $ui = null
Data Fields inherited from PEAR
 $_debug = false
 $_default_error_handler = ''
 $_default_error_mode = null
 $_default_error_options = null
 $_error_class = 'PEAR_Error'
 $_expected_errors = array()

Additional Inherited Members

Static Public Member Functions inherited from PEAR_Downloader
static _downloadHttp ( $object, $url, &$ui, $save_dir='.', $callback=null, $lastmodified=null, $accept=false, $channel=false)
Static Public Member Functions inherited from PEAR_Common
static addTempFile ($file)
static analyzeSourceCode ($file)
static betterStates ($state, $include=false)
static getDependencyRelations ()
static getDependencyTypes ()
static getFileRoles ()
static getProvideTypes ()
static getReleaseStates ()
static getReplacementTypes ()
static getScriptPhases ()
static getUserRoles ()
static isIncludeable ($path)
Static Public Member Functions inherited from PEAR
static __callStatic ($method, $arguments)
static getSourceDateEpoch ()
static & getStaticProperty ($class, $var)
static isError ($data, $code=null)
static loadExtension ($ext)
static registerShutdownFunc ($func, $args=array())
static staticPopErrorHandling ()
static staticPushErrorHandling ($mode, $options=null)
Static Protected Member Functions inherited from PEAR
static _popErrorHandling ($object)
static _pushErrorHandling ($object, $mode, $options=null)
static _raiseError ($object, $message=null, $code=null, $mode=null, $options=null, $userinfo=null, $error_class=null, $skipmsg=false)
static _setErrorHandling ( $object, $mode=null, $options=null)
static _throwError ($object, $message=null, $code=null, $userinfo=null)
Static Protected Attributes inherited from PEAR_Downloader
static $bivalentMethods
Static Protected Attributes inherited from PEAR
static $bivalentMethods

Detailed Description

Definition at line 42 of file Installer.php.

Constructor & Destructor Documentation

◆ __construct()

__construct ( & $ui)

PEAR_Installer constructor.

Parameters
object$uiuser interface object (instance of PEAR_Frontend_*)

@access public

Definition at line 118 of file Installer.php.

119 {
120 parent::__construct($ui, array(), null);
121 $this->setFrontendObject($ui);
122 $this->debug = $this->config->get('verbose');
123 }
setFrontendObject(&$ui)
Definition Common.php:294

References PEAR_Common\$ui, and PEAR_Common\setFrontendObject().

Here is the call graph for this function:

Member Function Documentation

◆ _buildCallback()

_buildCallback ( $what,
$data )

Definition at line 1798 of file Installer.php.

1799 {
1800 if (($what == 'cmdoutput' && $this->debug > 1) ||
1801 ($what == 'output' && $this->debug > 0)) {
1802 $this->ui->outputData(rtrim($data), 'build');
1803 }
1804 }

◆ _compileSourceFiles()

_compileSourceFiles ( $savechannel,
& $filelist,
$configureoptions )
Parameters
string
PEAR_PackageFile_v1|PEAR_PackageFile_v2
mixed[]$configureoptions

Definition at line 1515 of file Installer.php.

1516 {
1517 require_once 'PEAR/Builder.php';
1518 $this->log(1, "$this->source_files source files, building");
1519 $bob = new PEAR_Builder($configureoptions, $this->ui);
1520 $bob->debug = $this->debug;
1521 $built = $bob->build($filelist, array(&$this, '_buildCallback'));
1522 if (PEAR::isError($built)) {
1523 $this->rollbackFileTransaction();
1524 $this->configSet('default_channel', $savechannel);
1525 return $built;
1526 }
1527
1528 $this->log(1, "\nBuild process completed successfully");
1529 foreach ($built as $ext) {
1530 $bn = basename($ext['file']);
1531 list($_ext_name, $_ext_suff) = explode('.', $bn);
1532 if ($_ext_suff == 'so' || $_ext_suff == 'dll') {
1533 if (extension_loaded($_ext_name)) {
1534 return $this->raiseError("Extension '$_ext_name' already loaded. " .
1535 'Please unload it in your php.ini file ' .
1536 'prior to install or upgrade');
1537 }
1538 $role = 'ext';
1539 } else {
1540 $role = 'src';
1541 }
1542
1543 $dest = $ext['dest'];
1544 $packagingroot = '';
1545 if (isset($this->_options['packagingroot'])) {
1546 $packagingroot = $this->_options['packagingroot'];
1547 }
1548
1549 $copyto = $this->_prependPath($dest, $packagingroot);
1550 $extra = $copyto != $dest ? " as '$copyto'" : '';
1551 $this->log(1, "Installing '$dest'$extra");
1552
1553 $copydir = dirname($copyto);
1554 // pretty much nothing happens if we are only registering the install
1555 if (empty($this->_options['register-only'])) {
1556 if (!file_exists($copydir) || !is_dir($copydir)) {
1557 if (!$this->mkDirHier($copydir)) {
1558 return $this->raiseError("failed to mkdir $copydir",
1560 }
1561
1562 $this->log(3, "+ mkdir $copydir");
1563 }
1564
1565 if (!@copy($ext['file'], $copyto)) {
1566 return $this->raiseError(
1567 "failed to write $copyto (" . error_get_last()["message"] . ")",
1569 }
1570
1571 $this->log(3, "+ cp $ext[file] $copyto");
1572 $this->addFileOperation('rename', array($ext['file'], $copyto));
1573 if (!OS_WINDOWS) {
1574 $mode = 0666 & ~(int)octdec($this->config->get('umask'));
1575 $this->addFileOperation('chmod', array($mode, $copyto));
1576 if (!@chmod($copyto, $mode)) {
1577 $this->log(0, "failed to change mode of $copyto (" .
1578 error_get_last()["message"] . ")");
1579 }
1580 }
1581 }
1582
1583
1584 $data = array(
1585 'role' => $role,
1586 'name' => $bn,
1587 'installed_as' => $dest,
1588 'php_api' => $ext['php_api'],
1589 'zend_mod_api' => $ext['zend_mod_api'],
1590 'zend_ext_api' => $ext['zend_ext_api'],
1591 );
1592
1593 if ($filelist->getPackageXmlVersion() == '1.0') {
1594 $filelist->installedFile($bn, $data);
1595 } else {
1596 $filelist->installedFile($bn, array('attribs' => $data));
1597 }
1598 }
1599 }
const PEAR_INSTALLER_FAILED
log($level, $msg, $append_crlf=true)
Definition Common.php:244
configSet($key, $value, $layer='user', $channel=false)
_prependPath($path, $prepend)
addFileOperation($type, $data)

References $debug, PEAR_Downloader\_prependPath(), addFileOperation(), PEAR_Downloader\configSet(), PEAR\isError(), PEAR_Common\log(), mkDirHier(), PEAR_INSTALLER_FAILED, and rollbackFileTransaction().

Referenced by install().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _deletePackageFiles()

_deletePackageFiles ( $package,
$channel = false,
$backup = false )

Delete a package's installed files, does not remove empty directories.

Parameters
stringpackage name
stringchannel name
boolif true, then files are backed up first
Returns
bool TRUE on success, or a PEAR error on failure @access protected

Definition at line 156 of file Installer.php.

157 {
158 if (!$channel) {
159 $channel = 'pear.php.net';
160 }
161
162 if (!strlen($package)) {
163 return $this->raiseError("No package to uninstall given");
164 }
165
166 if (strtolower($package) == 'pear' && $channel == 'pear.php.net') {
167 // to avoid race conditions, include all possible needed files
168 require_once 'PEAR/Task/Common.php';
169 require_once 'PEAR/Task/Replace.php';
170 require_once 'PEAR/Task/Unixeol.php';
171 require_once 'PEAR/Task/Windowseol.php';
172 require_once 'PEAR/PackageFile/v1.php';
173 require_once 'PEAR/PackageFile/v2.php';
174 require_once 'PEAR/PackageFile/Generator/v1.php';
175 require_once 'PEAR/PackageFile/Generator/v2.php';
176 }
177
178 $filelist = $this->_registry->packageInfo($package, 'filelist', $channel);
179 if ($filelist == null) {
180 return $this->raiseError("$channel/$package not installed");
181 }
182
183 $ret = array();
184 foreach ($filelist as $file => $props) {
185 if (empty($props['installed_as'])) {
186 continue;
187 }
188
189 $path = $props['installed_as'];
190 if ($backup) {
191 $this->addFileOperation('backup', array($path));
192 $ret[] = $path;
193 }
194
195 $this->addFileOperation('delete', array($path));
196 }
197
198 if ($backup) {
199 return $ret;
200 }
201
202 return true;
203 }

References addFileOperation().

Referenced by install(), and uninstall().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _installFile()

_installFile ( $file,
$atts,
$tmp_path,
$options )
Parameters
stringfilename
arrayattributes from <file> tag in package.xml
stringpath to install the file in
arrayoptions from command-line @access private

Definition at line 215 of file Installer.php.

216 {
217 // {{{ return if this file is meant for another platform
218 static $os;
219 if (!isset($this->_registry)) {
220 $this->_registry = &$this->config->getRegistry();
221 }
222
223 if (isset($atts['platform'])) {
224 if (empty($os)) {
225 $os = new OS_Guess();
226 }
227
228 if (strlen($atts['platform']) && $atts['platform'][0] == '!') {
229 $negate = true;
230 $platform = substr($atts['platform'], 1);
231 } else {
232 $negate = false;
233 $platform = $atts['platform'];
234 }
235
236 if ((bool) $os->matchSignature($platform) === $negate) {
237 $this->log(3, "skipped $file (meant for $atts[platform], we are ".$os->getSignature().")");
239 }
240 }
241 // }}}
242
243 $channel = $this->pkginfo->getChannel();
244 // {{{ assemble the destination paths
245 switch ($atts['role']) {
246 case 'src':
247 case 'extsrc':
248 $this->source_files++;
249 return;
250 case 'doc':
251 case 'data':
252 case 'test':
253 $dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel) .
254 DIRECTORY_SEPARATOR . $this->pkginfo->getPackage();
255 unset($atts['baseinstalldir']);
256 break;
257 case 'ext':
258 case 'php':
259 $dest_dir = $this->config->get($atts['role'] . '_dir', null, $channel);
260 break;
261 case 'script':
262 $dest_dir = $this->config->get('bin_dir', null, $channel);
263 break;
264 default:
265 return $this->raiseError("Invalid role `$atts[role]' for file $file");
266 }
267
268 $save_destdir = $dest_dir;
269 if (!empty($atts['baseinstalldir'])) {
270 $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
271 }
272
273 if (dirname($file) != '.' && empty($atts['install-as'])) {
274 $dest_dir .= DIRECTORY_SEPARATOR . dirname($file);
275 }
276
277 if (empty($atts['install-as'])) {
278 $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file);
279 } else {
280 $dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as'];
281 }
282 $orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file;
283
284 // Clean up the DIRECTORY_SEPARATOR mess
285 $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
286 list($dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
287 array(DIRECTORY_SEPARATOR,
288 DIRECTORY_SEPARATOR,
289 DIRECTORY_SEPARATOR),
290 array($dest_file, $orig_file));
291 $final_dest_file = $installed_as = $dest_file;
292 if (isset($this->_options['packagingroot'])) {
293 $installedas_dest_dir = dirname($final_dest_file);
294 $installedas_dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
295 $final_dest_file = $this->_prependPath($final_dest_file, $this->_options['packagingroot']);
296 } else {
297 $installedas_dest_dir = dirname($final_dest_file);
298 $installedas_dest_file = $installedas_dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
299 }
300
301 $dest_dir = dirname($final_dest_file);
302 $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
303 if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) {
304 return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED);
305 }
306 // }}}
307
308 if (empty($this->_options['register-only']) &&
309 (!file_exists($dest_dir) || !is_dir($dest_dir))) {
310 if (!$this->mkDirHier($dest_dir)) {
311 return $this->raiseError("failed to mkdir $dest_dir",
313 }
314 $this->log(3, "+ mkdir $dest_dir");
315 }
316
317 // pretty much nothing happens if we are only registering the install
318 if (empty($this->_options['register-only'])) {
319 if (empty($atts['replacements'])) {
320 if (!file_exists($orig_file)) {
321 return $this->raiseError("file $orig_file does not exist",
323 }
324
325 if (!@copy($orig_file, $dest_file)) {
326 return $this->raiseError(
327 "failed to write $dest_file: " . error_get_last()["message"],
329 }
330
331 $this->log(3, "+ cp $orig_file $dest_file");
332 if (isset($atts['md5sum'])) {
333 $md5sum = md5_file($dest_file);
334 }
335 } else {
336 // {{{ file with replacements
337 if (!file_exists($orig_file)) {
338 return $this->raiseError("file does not exist",
340 }
341
342 $contents = file_get_contents($orig_file);
343 if ($contents === false) {
344 $contents = '';
345 }
346
347 if (isset($atts['md5sum'])) {
348 $md5sum = md5($contents);
349 }
350
351 $subst_from = $subst_to = array();
352 foreach ($atts['replacements'] as $a) {
353 $to = '';
354 if ($a['type'] == 'php-const') {
355 if (preg_match('/^[a-z0-9_]+\\z/i', $a['to'])) {
356 eval("\$to = $a[to];");
357 } else {
358 if (!isset($options['soft'])) {
359 $this->log(0, "invalid php-const replacement: $a[to]");
360 }
361 continue;
362 }
363 } elseif ($a['type'] == 'pear-config') {
364 if ($a['to'] == 'master_server') {
365 $chan = $this->_registry->getChannel($channel);
366 if (!PEAR::isError($chan)) {
367 $to = $chan->getServer();
368 } else {
369 $to = $this->config->get($a['to'], null, $channel);
370 }
371 } else {
372 $to = $this->config->get($a['to'], null, $channel);
373 }
374 if (is_null($to)) {
375 if (!isset($options['soft'])) {
376 $this->log(0, "invalid pear-config replacement: $a[to]");
377 }
378 continue;
379 }
380 } elseif ($a['type'] == 'package-info') {
381 if ($t = $this->pkginfo->packageInfo($a['to'])) {
382 $to = $t;
383 } else {
384 if (!isset($options['soft'])) {
385 $this->log(0, "invalid package-info replacement: $a[to]");
386 }
387 continue;
388 }
389 }
390 if (!is_null($to)) {
391 $subst_from[] = $a['from'];
392 $subst_to[] = $to;
393 }
394 }
395
396 $this->log(3, "doing ".sizeof($subst_from)." substitution(s) for $final_dest_file");
397 if (sizeof($subst_from)) {
398 $contents = str_replace($subst_from, $subst_to, $contents);
399 }
400
401 $wp = @fopen($dest_file, "wb");
402 if (!is_resource($wp)) {
403 return $this->raiseError(
404 "failed to create $dest_file: " . error_get_last()["message"],
406 }
407
408 if (@fwrite($wp, $contents) === false) {
409 return $this->raiseError(
410 "failed writing to $dest_file: " . error_get_last()["message"],
412 }
413
414 fclose($wp);
415 // }}}
416 }
417
418 // {{{ check the md5
419 if (isset($md5sum)) {
420 if (strtolower($md5sum) === strtolower($atts['md5sum'])) {
421 $this->log(2, "md5sum ok: $final_dest_file");
422 } else {
423 if (empty($options['force'])) {
424 // delete the file
425 if (file_exists($dest_file)) {
426 unlink($dest_file);
427 }
428
429 if (!isset($options['ignore-errors'])) {
430 return $this->raiseError("bad md5sum for file $final_dest_file",
432 }
433
434 if (!isset($options['soft'])) {
435 $this->log(0, "warning : bad md5sum for file $final_dest_file");
436 }
437 } else {
438 if (!isset($options['soft'])) {
439 $this->log(0, "warning : bad md5sum for file $final_dest_file");
440 }
441 }
442 }
443 }
444 // }}}
445 // {{{ set file permissions
446 if (!OS_WINDOWS) {
447 if ($atts['role'] == 'script') {
448 $mode = 0777 & ~(int)octdec($this->config->get('umask'));
449 $this->log(3, "+ chmod +x $dest_file");
450 } else {
451 $mode = 0666 & ~(int)octdec($this->config->get('umask'));
452 }
453
454 if ($atts['role'] != 'src') {
455 $this->addFileOperation("chmod", array($mode, $dest_file));
456 if (!@chmod($dest_file, $mode)) {
457 if (!isset($options['soft'])) {
458 $this->log(0, "failed to change mode of $dest_file: " .
459 error_get_last()["message"]);
460 }
461 }
462 }
463 }
464 // }}}
465
466 if ($atts['role'] == 'src') {
467 rename($dest_file, $final_dest_file);
468 $this->log(2, "renamed source file $dest_file to $final_dest_file");
469 } else {
470 $this->addFileOperation("rename", array($dest_file, $final_dest_file,
471 $atts['role'] == 'ext'));
472 }
473 }
474
475 // Store the full path where the file was installed for easy unistall
476 if ($atts['role'] != 'script') {
477 $loc = $this->config->get($atts['role'] . '_dir');
478 } else {
479 $loc = $this->config->get('bin_dir');
480 }
481
482 if ($atts['role'] != 'src') {
483 $this->addFileOperation("installed_as", array($file, $installed_as,
484 $loc,
485 dirname(substr($installedas_dest_file, strlen($loc)))));
486 }
487
488 //$this->log(2, "installed: $dest_file");
489 return PEAR_INSTALLER_OK;
490 }
const PEAR_INSTALLER_OK
const PEAR_INSTALLER_SKIPPED
$options
Definition pearcmd.php:145

References $options, PEAR_Downloader\_prependPath(), addFileOperation(), PEAR\isError(), PEAR_Common\log(), mkDirHier(), PEAR_INSTALLER_FAILED, PEAR_INSTALLER_OK, and PEAR_INSTALLER_SKIPPED.

Referenced by install().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _installFile2()

_installFile2 ( & $pkg,
$file,
& $real_atts,
$tmp_path,
$options )
Parameters
PEAR_PackageFile_v1|PEAR_PackageFile_v2
stringfilename
arrayattributes from <file> tag in package.xml
stringpath to install the file in
arrayoptions from command-line @access private

Definition at line 503 of file Installer.php.

504 {
505 $atts = $real_atts;
506 if (!isset($this->_registry)) {
507 $this->_registry = &$this->config->getRegistry();
508 }
509
510 $channel = $pkg->getChannel();
511 // {{{ assemble the destination paths
512 if (!in_array($atts['attribs']['role'],
513 PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) {
514 return $this->raiseError('Invalid role `' . $atts['attribs']['role'] .
515 "' for file $file");
516 }
517
518 $role = &PEAR_Installer_Role::factory($pkg, $atts['attribs']['role'], $this->config);
519 $err = $role->setup($this, $pkg, $atts['attribs'], $file);
520 if (PEAR::isError($err)) {
521 return $err;
522 }
523
524 if (!$role->isInstallable()) {
525 return;
526 }
527
528 $info = $role->processInstallation($pkg, $atts['attribs'], $file, $tmp_path);
529 if (PEAR::isError($info)) {
530 return $info;
531 }
532
533 list($save_destdir, $dest_dir, $dest_file, $orig_file) = $info;
534 if (preg_match('~/\.\.(/|\\z)|^\.\./~', str_replace('\\', '/', $dest_file))) {
535 return $this->raiseError("SECURITY ERROR: file $file (installed to $dest_file) contains parent directory reference ..", PEAR_INSTALLER_FAILED);
536 }
537
538 $final_dest_file = $installed_as = $dest_file;
539 if (isset($this->_options['packagingroot'])) {
540 $final_dest_file = $this->_prependPath($final_dest_file,
541 $this->_options['packagingroot']);
542 }
543
544 $dest_dir = dirname($final_dest_file);
545 $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file);
546 // }}}
547
548 if (empty($this->_options['register-only'])) {
549 if (!file_exists($dest_dir) || !is_dir($dest_dir)) {
550 if (!$this->mkDirHier($dest_dir)) {
551 return $this->raiseError("failed to mkdir $dest_dir",
553 }
554 $this->log(3, "+ mkdir $dest_dir");
555 }
556 }
557
558 $attribs = $atts['attribs'];
559 unset($atts['attribs']);
560 // pretty much nothing happens if we are only registering the install
561 if (empty($this->_options['register-only'])) {
562 if (!count($atts)) { // no tasks
563 if (!file_exists($orig_file)) {
564 return $this->raiseError("file $orig_file does not exist",
566 }
567
568 if (!@copy($orig_file, $dest_file)) {
569 return $this->raiseError(
570 "failed to write $dest_file: " . error_get_last()["message"],
572 }
573
574 $this->log(3, "+ cp $orig_file $dest_file");
575 if (isset($attribs['md5sum'])) {
576 $md5sum = md5_file($dest_file);
577 }
578 } else { // file with tasks
579 if (!file_exists($orig_file)) {
580 return $this->raiseError("file $orig_file does not exist",
582 }
583
584 $contents = file_get_contents($orig_file);
585 if ($contents === false) {
586 $contents = '';
587 }
588
589 if (isset($attribs['md5sum'])) {
590 $md5sum = md5($contents);
591 }
592
593 foreach ($atts as $tag => $raw) {
594 $tag = str_replace(array($pkg->getTasksNs() . ':', '-'), array('', '_'), $tag);
595 $task = "PEAR_Task_$tag";
596 $task = new $task($this->config, $this, PEAR_TASK_INSTALL);
597 if (!$task->isScript()) { // scripts are only handled after installation
598 $task->init($raw, $attribs, $pkg->getLastInstalledVersion());
599 $res = $task->startSession($pkg, $contents, $final_dest_file);
600 if ($res === false) {
601 continue; // skip this file
602 }
603
604 if (PEAR::isError($res)) {
605 return $res;
606 }
607
608 $contents = $res; // save changes
609 }
610
611 $wp = @fopen($dest_file, "wb");
612 if (!is_resource($wp)) {
613 return $this->raiseError(
614 "failed to create $dest_file: " . error_get_last()["message"],
616 }
617
618 if (fwrite($wp, $contents) === false) {
619 return $this->raiseError(
620 "failed writing to $dest_file: " . error_get_last()["message"],
622 }
623
624 fclose($wp);
625 }
626 }
627
628 // {{{ check the md5
629 if (isset($md5sum)) {
630 // Make sure the original md5 sum matches with expected
631 if (strtolower($md5sum) === strtolower($attribs['md5sum'])) {
632 $this->log(2, "md5sum ok: $final_dest_file");
633
634 if (isset($contents)) {
635 // set md5 sum based on $content in case any tasks were run.
636 $real_atts['attribs']['md5sum'] = md5($contents);
637 }
638 } else {
639 if (empty($options['force'])) {
640 // delete the file
641 if (file_exists($dest_file)) {
642 unlink($dest_file);
643 }
644
645 if (!isset($options['ignore-errors'])) {
646 return $this->raiseError("bad md5sum for file $final_dest_file",
648 }
649
650 if (!isset($options['soft'])) {
651 $this->log(0, "warning : bad md5sum for file $final_dest_file");
652 }
653 } else {
654 if (!isset($options['soft'])) {
655 $this->log(0, "warning : bad md5sum for file $final_dest_file");
656 }
657 }
658 }
659 } else {
660 $real_atts['attribs']['md5sum'] = md5_file($dest_file);
661 }
662
663 // }}}
664 // {{{ set file permissions
665 if (!OS_WINDOWS) {
666 if ($role->isExecutable()) {
667 $mode = 0777 & ~(int)octdec($this->config->get('umask'));
668 $this->log(3, "+ chmod +x $dest_file");
669 } else {
670 $mode = 0666 & ~(int)octdec($this->config->get('umask'));
671 }
672
673 if ($attribs['role'] != 'src') {
674 $this->addFileOperation("chmod", array($mode, $dest_file));
675 if (!@chmod($dest_file, $mode)) {
676 if (!isset($options['soft'])) {
677 $this->log(0, "failed to change mode of $dest_file: " .
678 error_get_last()["message"]);
679 }
680 }
681 }
682 }
683 // }}}
684
685 if ($attribs['role'] == 'src') {
686 rename($dest_file, $final_dest_file);
687 $this->log(2, "renamed source file $dest_file to $final_dest_file");
688 } else {
689 $this->addFileOperation("rename", array($dest_file, $final_dest_file, $role->isExtension()));
690 }
691 }
692
693 // Store the full path where the file was installed for easy uninstall
694 if ($attribs['role'] != 'src') {
695 $loc = $this->config->get($role->getLocationConfig(), null, $channel);
696 $this->addFileOperation('installed_as', array($file, $installed_as,
697 $loc,
698 dirname(substr($installed_as, strlen($loc)))));
699 }
700
701 //$this->log(2, "installed: $dest_file");
702 return PEAR_INSTALLER_OK;
703 }
const PEAR_TASK_INSTALL
Definition Common.php:24
static & factory($pkg, $role, &$config)
Definition Role.php:60
static getValidRoles($release, $clear=false)
Definition Role.php:88
$raw
Definition pearcmd.php:116

References $options, $raw, PEAR_Downloader\_prependPath(), addFileOperation(), PEAR_Installer_Role\factory(), PEAR_Installer_Role\getValidRoles(), PEAR\isError(), PEAR_Common\log(), mkDirHier(), PEAR_INSTALLER_FAILED, PEAR_INSTALLER_OK, and PEAR_TASK_INSTALL.

Referenced by install().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _parsePackageXml()

_parsePackageXml ( & $descfile)

Definition at line 1033 of file Installer.php.

1034 {
1035 // Parse xml file -----------------------------------------------
1036 $pkg = new PEAR_PackageFile($this->config, $this->debug);
1038 $p = &$pkg->fromAnyFile($descfile, PEAR_VALIDATE_INSTALLING);
1040 if (PEAR::isError($p)) {
1041 if (is_array($p->getUserInfo())) {
1042 foreach ($p->getUserInfo() as $err) {
1043 $loglevel = $err['level'] == 'error' ? 0 : 1;
1044 if (!isset($this->_options['soft'])) {
1045 $this->log($loglevel, ucfirst($err['level']) . ': ' . $err['message']);
1046 }
1047 }
1048 }
1049 return $this->raiseError('Installation failed: invalid package file');
1050 }
1051
1052 $descfile = $p->getPackageFile();
1053 return $p;
1054 }
const PEAR_ERROR_RETURN
Definition PEAR.php:24
const PEAR_VALIDATE_INSTALLING
Definition Validate.php:18
static staticPopErrorHandling()
Definition PEAR.php:654
static staticPushErrorHandling($mode, $options=null)
Definition PEAR.php:619

References PEAR\isError(), PEAR_Common\log(), PEAR_ERROR_RETURN, PEAR_VALIDATE_INSTALLING, PEAR\staticPopErrorHandling(), and PEAR\staticPushErrorHandling().

Referenced by install().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _removeBackups()

_removeBackups ( $files)

Definition at line 138 of file Installer.php.

139 {
140 foreach ($files as $path) {
141 $this->addFileOperation('removebackup', array($path));
142 }
143 }

References addFileOperation().

Referenced by install().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ _sortDirs()

_sortDirs ( $a,
$b )

Definition at line 1787 of file Installer.php.

1788 {
1789 if (strnatcmp($a, $b) == -1) return 1;
1790 if (strnatcmp($a, $b) == 1) return -1;
1791 return 0;
1792 }

◆ _sortUninstall()

_sortUninstall ( $a,
$b )

Definition at line 1764 of file Installer.php.

1765 {
1766 if (!$a->getDeps() && !$b->getDeps()) {
1767 return 0; // neither package has dependencies, order is insignificant
1768 }
1769 if ($a->getDeps() && !$b->getDeps()) {
1770 return -1; // $a must be installed after $b because $a has dependencies
1771 }
1772 if (!$a->getDeps() && $b->getDeps()) {
1773 return 1; // $b must be installed after $a because $b has dependencies
1774 }
1775 // both packages have dependencies
1776 if ($this->_dependencyDB->dependsOn($a, $b)) {
1777 return -1;
1778 }
1779 if ($this->_dependencyDB->dependsOn($b, $a)) {
1780 return 1;
1781 }
1782 return 0;
1783 }

◆ addFileOperation()

addFileOperation ( $type,
$data )

Add a file operation to the current file transaction.

See also
startFileTransaction()
Parameters
string$typeThis can be one of:
  • rename: rename a file ($data has 3 values)
  • backup: backup an existing file ($data has 1 value)
  • removebackup: clean up backups created during install ($data has 1 value)
  • chmod: change permissions on a file ($data has 2 values)
  • delete: delete a file ($data has 1 value)
  • rmdir: delete a directory if empty ($data has 1 value)
  • installed_as: mark a file as installed ($data has 4 values).
array$dataFor all file operations, this array must contain the full path to the file or directory that is being operated on. For the rename command, the first parameter must be the file to rename, the second its new name, the third whether this is a PHP extension.

The installed_as operation contains 4 elements in this order:

  1. Filename as listed in the filelist element from package.xml
  2. Full path to the installed file
  3. Full path from the php_dir configuration variable used in this installation
  4. Relative path from the php_dir that this file is installed in

Definition at line 732 of file Installer.php.

733 {
734 if (!is_array($data)) {
735 return $this->raiseError('Internal Error: $data in addFileOperation'
736 . ' must be an array, was ' . gettype($data));
737 }
738
739 if ($type == 'chmod') {
740 $octmode = decoct($data[0]);
741 $this->log(3, "adding to transaction: $type $octmode $data[1]");
742 } else {
743 $this->log(3, "adding to transaction: $type " . implode(" ", $data));
744 }
745 $this->file_operations[] = array($type, $data);
746 }

References PEAR_Common\log().

Referenced by _compileSourceFiles(), _deletePackageFiles(), _installFile(), _installFile2(), _removeBackups(), install(), mkDirHier(), and uninstall().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ commitFileTransaction()

commitFileTransaction ( )

Definition at line 762 of file Installer.php.

763 {
764 // {{{ first, check permissions and such manually
765 $errors = array();
766 foreach ($this->file_operations as $key => $tr) {
767 list($type, $data) = $tr;
768 switch ($type) {
769 case 'rename':
770 if (!file_exists($data[0])) {
771 $errors[] = "cannot rename file $data[0], doesn't exist";
772 }
773
774 // check that dest dir. is writable
775 if (!is_writable(dirname($data[1]))) {
776 $errors[] = "permission denied ($type): $data[1]";
777 }
778 break;
779 case 'chmod':
780 // check that file is writable
781 if (!is_writable($data[1])) {
782 $errors[] = "permission denied ($type): $data[1] " . decoct($data[0]);
783 }
784 break;
785 case 'delete':
786 if (!file_exists($data[0])) {
787 $this->log(2, "warning: file $data[0] doesn't exist, can't be deleted");
788 }
789 // check that directory is writable
790 if (file_exists($data[0])) {
791 if (!is_writable(dirname($data[0]))) {
792 $errors[] = "permission denied ($type): $data[0]";
793 } else {
794 // make sure the file to be deleted can be opened for writing
795 $fp = false;
796 if (!is_dir($data[0]) &&
797 (!is_writable($data[0]) || !($fp = @fopen($data[0], 'a')))) {
798 $errors[] = "permission denied ($type): $data[0]";
799 } elseif ($fp) {
800 fclose($fp);
801 }
802 }
803
804 /* Verify we are not deleting a file owned by another package
805 * This can happen when a file moves from package A to B in
806 * an upgrade ala http://pear.php.net/17986
807 */
808 $info = array(
809 'package' => strtolower($this->pkginfo->getName()),
810 'channel' => strtolower($this->pkginfo->getChannel()),
811 );
812 $result = $this->_registry->checkFileMap($data[0], $info, '1.1');
813 if (is_array($result)) {
814 $res = array_diff($result, $info);
815 if (!empty($res)) {
816 $new = $this->_registry->getPackage($result[1], $result[0]);
817 $this->file_operations[$key] = false;
818 $pkginfoName = $this->pkginfo->getName();
819 $newChannel = $new->getChannel();
820 $newPackage = $new->getName();
821 $this->log(3, "file $data[0] was scheduled for removal from $pkginfoName but is owned by $newChannel/$newPackage, removal has been cancelled.");
822 }
823 }
824 }
825 break;
826 }
827
828 }
829 // }}}
830
831 $n = count($this->file_operations);
832 $this->log(2, "about to commit $n file operations for " . $this->pkginfo->getName());
833
834 $m = count($errors);
835 if ($m > 0) {
836 foreach ($errors as $error) {
837 if (!isset($this->_options['soft'])) {
838 $this->log(1, $error);
839 }
840 }
841
842 if (!isset($this->_options['ignore-errors'])) {
843 return false;
844 }
845 }
846
847 $this->_dirtree = array();
848 // {{{ really commit the transaction
849 foreach ($this->file_operations as $i => $tr) {
850 if (!$tr) {
851 // support removal of non-existing backups
852 continue;
853 }
854
855 list($type, $data) = $tr;
856 switch ($type) {
857 case 'backup':
858 if (!file_exists($data[0])) {
859 $this->file_operations[$i] = false;
860 break;
861 }
862
863 if (!@copy($data[0], $data[0] . '.bak')) {
864 $this->log(1, 'Could not copy ' . $data[0] . ' to ' . $data[0] .
865 '.bak ' . error_get_last()["message"]);
866 return false;
867 }
868 $this->log(3, "+ backup $data[0] to $data[0].bak");
869 break;
870 case 'removebackup':
871 if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) {
872 unlink($data[0] . '.bak');
873 $this->log(3, "+ rm backup of $data[0] ($data[0].bak)");
874 }
875 break;
876 case 'rename':
877 $test = file_exists($data[1]) ? @unlink($data[1]) : null;
878 if (!$test && file_exists($data[1])) {
879 if ($data[2]) {
880 $extra = ', this extension must be installed manually. Rename to "' .
881 basename($data[1]) . '"';
882 } else {
883 $extra = '';
884 }
885
886 if (!isset($this->_options['soft'])) {
887 $this->log(1, 'Could not delete ' . $data[1] . ', cannot rename ' .
888 $data[0] . $extra);
889 }
890
891 if (!isset($this->_options['ignore-errors'])) {
892 return false;
893 }
894 }
895
896 // permissions issues with rename - copy() is far superior
897 $perms = @fileperms($data[0]);
898 if (!@copy($data[0], $data[1])) {
899 $this->log(1, 'Could not rename ' . $data[0] . ' to ' . $data[1] .
900 ' ' . error_get_last()["message"]);
901 return false;
902 }
903
904 // copy over permissions, otherwise they are lost
905 @chmod($data[1], $perms);
906 @unlink($data[0]);
907 $this->log(3, "+ mv $data[0] $data[1]");
908 break;
909 case 'chmod':
910 if (!@chmod($data[1], $data[0])) {
911 $this->log(1, 'Could not chmod ' . $data[1] . ' to ' .
912 decoct($data[0]) . ' ' . error_get_last()["message"]);
913 return false;
914 }
915
916 $octmode = decoct($data[0]);
917 $this->log(3, "+ chmod $octmode $data[1]");
918 break;
919 case 'delete':
920 if (file_exists($data[0])) {
921 if (!@unlink($data[0])) {
922 $this->log(1, 'Could not delete ' . $data[0] . ' ' .
923 error_get_last()["message"]);
924 return false;
925 }
926 $this->log(3, "+ rm $data[0]");
927 }
928 break;
929 case 'rmdir':
930 if (file_exists($data[0])) {
931 do {
932 $testme = opendir($data[0]);
933 while (false !== ($entry = readdir($testme))) {
934 if ($entry == '.' || $entry == '..') {
935 continue;
936 }
937 closedir($testme);
938 break 2; // this directory is not empty and can't be
939 // deleted
940 }
941
942 closedir($testme);
943 if (!@rmdir($data[0])) {
944 $this->log(1, 'Could not rmdir ' . $data[0] . ' ' .
945 error_get_last()["message"]);
946 return false;
947 }
948 $this->log(3, "+ rmdir $data[0]");
949 } while (false);
950 }
951 break;
952 case 'installed_as':
953 $this->pkginfo->setInstalledAs($data[0], $data[1]);
954 if (!isset($this->_dirtree[dirname($data[1])])) {
955 $this->_dirtree[dirname($data[1])] = true;
956 $this->pkginfo->setDirtree(dirname($data[1]));
957
958 while(!empty($data[3]) && dirname($data[3]) != $data[3] &&
959 $data[3] != '/' && $data[3] != '\\') {
960 $this->pkginfo->setDirtree($pp =
961 $this->_prependPath($data[3], $data[2]));
962 $this->_dirtree[$pp] = true;
963 $data[3] = dirname($data[3]);
964 }
965 }
966 break;
967 }
968 }
969 // }}}
970 $this->log(2, "successfully committed $n file operations");
971 $this->file_operations = array();
972 return true;
973 }
$result

References $result, PEAR_Downloader\_prependPath(), and PEAR_Common\log().

Referenced by install(), and uninstall().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getInstallPackages()

getInstallPackages ( )

Definition at line 1083 of file Installer.php.

1084 {
1086 }

References $_downloadedPackages.

Referenced by install().

Here is the caller graph for this function:

◆ getUninstallPackages()

& getUninstallPackages ( )

Definition at line 1602 of file Installer.php.

1603 {
1605 }

References $_downloadedPackages.

◆ install()

install ( $pkgfile,
$options = array() )

Installs the files within the package file specified.

Parameters
string | PEAR_Downloader_Package$pkgfilepath to the package file, or a pre-initialized packagefile object
array$optionsrecognized options:
  • installroot : optional prefix directory for installation
  • force : force installation
  • register-only : update registry but don't install files
  • upgrade : upgrade existing install
  • soft : fail silently
  • nodeps : ignore dependency conflicts/missing dependencies
  • alldeps : install all dependencies
  • onlyreqdeps : install only required dependencies
Returns
array|PEAR_Error package info if successful

Definition at line 1108 of file Installer.php.

1109 {
1110 $this->_options = $options;
1111 $this->_registry = &$this->config->getRegistry();
1112 if (is_object($pkgfile)) {
1113 $dlpkg = &$pkgfile;
1114 $pkg = $pkgfile->getPackageFile();
1115 $pkgfile = $pkg->getArchiveFile();
1116 $descfile = $pkg->getPackageFile();
1117 } else {
1118 $descfile = $pkgfile;
1119 $pkg = $this->_parsePackageXml($descfile);
1120 if (PEAR::isError($pkg)) {
1121 return $pkg;
1122 }
1123 }
1124
1125 $tmpdir = dirname($descfile);
1126 if (realpath($descfile) != realpath($pkgfile)) {
1127 // Use the temp_dir since $descfile can contain the download dir path
1128 $tmpdir = $this->config->get('temp_dir', null, 'pear.php.net');
1129 $tmpdir = System::mktemp('-d -t "' . $tmpdir . '"');
1130
1131 $tar = new Archive_Tar($pkgfile);
1132 if (!$tar->extract($tmpdir)) {
1133 return $this->raiseError("unable to unpack $pkgfile");
1134 }
1135 }
1136
1137 $pkgname = $pkg->getName();
1138 $channel = $pkg->getChannel();
1139
1140 if (isset($options['installroot'])) {
1141 $this->config->setInstallRoot($options['installroot']);
1142 $this->_registry = &$this->config->getRegistry();
1143 $installregistry = &$this->_registry;
1144 $this->installroot = ''; // all done automagically now
1145 $php_dir = $this->config->get('php_dir', null, $channel);
1146 } else {
1147 $this->config->setInstallRoot(false);
1148 $this->_registry = &$this->config->getRegistry();
1149 if (isset($this->_options['packagingroot'])) {
1150 $regdir = $this->_prependPath(
1151 $this->config->get('php_dir', null, 'pear.php.net'),
1152 $this->_options['packagingroot']);
1153
1154 $metadata_dir = $this->config->get('metadata_dir', null, 'pear.php.net');
1155 if ($metadata_dir) {
1156 $metadata_dir = $this->_prependPath(
1157 $metadata_dir,
1158 $this->_options['packagingroot']);
1159 }
1160 $packrootphp_dir = $this->_prependPath(
1161 $this->config->get('php_dir', null, $channel),
1162 $this->_options['packagingroot']);
1163
1164 $installregistry = new PEAR_Registry($regdir, false, false, $metadata_dir);
1165 if (!$installregistry->channelExists($channel, true)) {
1166 // we need to fake a channel-discover of this channel
1167 $chanobj = $this->_registry->getChannel($channel, true);
1168 $installregistry->addChannel($chanobj);
1169 }
1170 $php_dir = $packrootphp_dir;
1171 } else {
1172 $installregistry = &$this->_registry;
1173 $php_dir = $this->config->get('php_dir', null, $channel);
1174 }
1175 $this->installroot = '';
1176 }
1177
1178 // {{{ checks to do when not in "force" mode
1179 if (empty($options['force']) &&
1180 (file_exists($this->config->get('php_dir')) &&
1181 is_dir($this->config->get('php_dir')))) {
1182 $testp = $channel == 'pear.php.net' ? $pkgname : array($channel, $pkgname);
1183 $instfilelist = $pkg->getInstallationFileList(true);
1184 if (PEAR::isError($instfilelist)) {
1185 return $instfilelist;
1186 }
1187
1188 // ensure we have the most accurate registry
1189 $installregistry->flushFileMap();
1190 $test = $installregistry->checkFileMap($instfilelist, $testp, '1.1');
1191 if (PEAR::isError($test)) {
1192 return $test;
1193 }
1194
1195 if (sizeof($test)) {
1196 $pkgs = $this->getInstallPackages();
1197 $found = false;
1198 foreach ($pkgs as $param) {
1199 if ($pkg->isSubpackageOf($param)) {
1200 $found = true;
1201 break;
1202 }
1203 }
1204
1205 if ($found) {
1206 // subpackages can conflict with earlier versions of parent packages
1207 $parentreg = $installregistry->packageInfo($param->getPackage(), null, $param->getChannel());
1208 $tmp = $test;
1209 foreach ($tmp as $file => $info) {
1210 if (is_array($info)) {
1211 if (strtolower($info[1]) == strtolower($param->getPackage()) &&
1212 strtolower($info[0]) == strtolower($param->getChannel())
1213 ) {
1214 if (isset($parentreg['filelist'][$file])) {
1215 unset($parentreg['filelist'][$file]);
1216 } else{
1217 $pos = strpos($file, '/');
1218 $basedir = substr($file, 0, $pos);
1219 $file2 = substr($file, $pos + 1);
1220 if (isset($parentreg['filelist'][$file2]['baseinstalldir'])
1221 && $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir
1222 ) {
1223 unset($parentreg['filelist'][$file2]);
1224 }
1225 }
1226
1227 unset($test[$file]);
1228 }
1229 } else {
1230 if (strtolower($param->getChannel()) != 'pear.php.net') {
1231 continue;
1232 }
1233
1234 if (strtolower($info) == strtolower($param->getPackage())) {
1235 if (isset($parentreg['filelist'][$file])) {
1236 unset($parentreg['filelist'][$file]);
1237 } else{
1238 $pos = strpos($file, '/');
1239 $basedir = substr($file, 0, $pos);
1240 $file2 = substr($file, $pos + 1);
1241 if (isset($parentreg['filelist'][$file2]['baseinstalldir'])
1242 && $parentreg['filelist'][$file2]['baseinstalldir'] === $basedir
1243 ) {
1244 unset($parentreg['filelist'][$file2]);
1245 }
1246 }
1247
1248 unset($test[$file]);
1249 }
1250 }
1251 }
1252
1253 $pfk = new PEAR_PackageFile($this->config);
1254 $parentpkg = &$pfk->fromArray($parentreg);
1255 $installregistry->updatePackage2($parentpkg);
1256 }
1257
1258 if ($param->getChannel() == 'pecl.php.net' && isset($options['upgrade'])) {
1259 $tmp = $test;
1260 foreach ($tmp as $file => $info) {
1261 if (is_string($info)) {
1262 // pear.php.net packages are always stored as strings
1263 if (strtolower($info) == strtolower($param->getPackage())) {
1264 // upgrading existing package
1265 unset($test[$file]);
1266 }
1267 }
1268 }
1269 }
1270
1271 if (count($test)) {
1272 $msg = "$channel/$pkgname: conflicting files found:\n";
1273 $longest = max(array_map("strlen", array_keys($test)));
1274 $fmt = "%{$longest}s (%s)\n";
1275 foreach ($test as $file => $info) {
1276 if (!is_array($info)) {
1277 $info = array('pear.php.net', $info);
1278 }
1279 $info = $info[0] . '/' . $info[1];
1280 $msg .= sprintf($fmt, $file, $info);
1281 }
1282
1283 if (!isset($options['ignore-errors'])) {
1284 return $this->raiseError($msg);
1285 }
1286
1287 if (!isset($options['soft'])) {
1288 $this->log(0, "WARNING: $msg");
1289 }
1290 }
1291 }
1292 }
1293 // }}}
1294
1295 $this->startFileTransaction();
1296
1297 $usechannel = $channel;
1298 if ($channel == 'pecl.php.net') {
1299 $test = $installregistry->packageExists($pkgname, $channel);
1300 if (!$test) {
1301 $test = $installregistry->packageExists($pkgname, 'pear.php.net');
1302 $usechannel = 'pear.php.net';
1303 }
1304 } else {
1305 $test = $installregistry->packageExists($pkgname, $channel);
1306 }
1307
1308 if (empty($options['upgrade']) && empty($options['soft'])) {
1309 // checks to do only when installing new packages
1310 if (empty($options['force']) && $test) {
1311 return $this->raiseError("$channel/$pkgname is already installed");
1312 }
1313 } else {
1314 // Upgrade
1315 if ($test) {
1316 $v1 = $installregistry->packageInfo($pkgname, 'version', $usechannel);
1317 $v2 = $pkg->getVersion();
1318 $cmp = version_compare("$v1", "$v2", 'gt');
1319 if (empty($options['force']) && !version_compare("$v2", "$v1", 'gt')) {
1320 return $this->raiseError("upgrade to a newer version ($v2 is not newer than $v1)");
1321 }
1322 }
1323 }
1324
1325 // Do cleanups for upgrade and install, remove old release's files first
1326 if ($test && empty($options['register-only'])) {
1327 // when upgrading, remove old release's files first:
1328 if (PEAR::isError($err = $this->_deletePackageFiles($pkgname, $usechannel,
1329 true))) {
1330 if (!isset($options['ignore-errors'])) {
1331 return $this->raiseError($err);
1332 }
1333
1334 if (!isset($options['soft'])) {
1335 $this->log(0, 'WARNING: ' . $err->getMessage());
1336 }
1337 } else {
1338 $backedup = $err;
1339 }
1340 }
1341
1342 // {{{ Copy files to dest dir ---------------------------------------
1343
1344 // info from the package it self we want to access from _installFile
1345 $this->pkginfo = &$pkg;
1346 // used to determine whether we should build any C code
1347 $this->source_files = 0;
1348
1349 $savechannel = $this->config->get('default_channel');
1350 if (empty($options['register-only']) && !is_dir($php_dir)) {
1351 if (PEAR::isError(System::mkdir(array('-p'), $php_dir))) {
1352 return $this->raiseError("no installation destination directory '$php_dir'\n");
1353 }
1354 }
1355
1356 if (substr($pkgfile, -4) != '.xml') {
1357 $tmpdir .= DIRECTORY_SEPARATOR . $pkgname . '-' . $pkg->getVersion();
1358 }
1359
1360 $this->configSet('default_channel', $channel);
1361 // {{{ install files
1362
1363 $ver = $pkg->getPackagexmlVersion();
1364 if (version_compare($ver, '2.0', '>=')) {
1365 $filelist = $pkg->getInstallationFilelist();
1366 } else {
1367 $filelist = $pkg->getFileList();
1368 }
1369
1370 if (PEAR::isError($filelist)) {
1371 return $filelist;
1372 }
1373
1374 $p = &$installregistry->getPackage($pkgname, $channel);
1375 $dirtree = (empty($options['register-only']) && $p) ? $p->getDirTree() : false;
1376
1377 $pkg->resetFilelist();
1378 $pkg->setLastInstalledVersion($installregistry->packageInfo($pkg->getPackage(),
1379 'version', $pkg->getChannel()));
1380 foreach ($filelist as $file => $atts) {
1382 if ($pkg->getPackagexmlVersion() == '1.0') {
1383 $res = $this->_installFile($file, $atts, $tmpdir, $options);
1384 } else {
1385 $res = $this->_installFile2($pkg, $file, $atts, $tmpdir, $options);
1386 }
1387 $this->popExpect();
1388
1389 if (PEAR::isError($res)) {
1390 if (empty($options['ignore-errors'])) {
1391 $this->rollbackFileTransaction();
1392 if ($res->getMessage() == "file does not exist") {
1393 $this->raiseError("file $file in package.xml does not exist");
1394 }
1395
1396 return $this->raiseError($res);
1397 }
1398
1399 if (!isset($options['soft'])) {
1400 $this->log(0, "Warning: " . $res->getMessage());
1401 }
1402 }
1403
1404 $real = isset($atts['attribs']) ? $atts['attribs'] : $atts;
1405 if ($res == PEAR_INSTALLER_OK && $real['role'] != 'src') {
1406 // Register files that were installed
1407 $pkg->installedFile($file, $atts);
1408 }
1409 }
1410 // }}}
1411
1412 // {{{ compile and install source files
1413 if ($this->source_files > 0 && empty($options['nobuild'])) {
1414 $configureoptions = empty($options['configureoptions']) ? '' : $options['configureoptions'];
1415 if (PEAR::isError($err =
1416 $this->_compileSourceFiles($savechannel, $pkg, $configureoptions))) {
1417 return $err;
1418 }
1419 }
1420 // }}}
1421
1422 if (isset($backedup)) {
1423 $this->_removeBackups($backedup);
1424 }
1425
1426 if (!$this->commitFileTransaction()) {
1427 $this->rollbackFileTransaction();
1428 $this->configSet('default_channel', $savechannel);
1429 return $this->raiseError("commit failed", PEAR_INSTALLER_FAILED);
1430 }
1431 // }}}
1432
1433 $ret = false;
1434 $installphase = 'install';
1435 $oldversion = false;
1436 // {{{ Register that the package is installed -----------------------
1437 if (empty($options['upgrade'])) {
1438 // if 'force' is used, replace the info in registry
1439 $usechannel = $channel;
1440 if ($channel == 'pecl.php.net') {
1441 $test = $installregistry->packageExists($pkgname, $channel);
1442 if (!$test) {
1443 $test = $installregistry->packageExists($pkgname, 'pear.php.net');
1444 $usechannel = 'pear.php.net';
1445 }
1446 } else {
1447 $test = $installregistry->packageExists($pkgname, $channel);
1448 }
1449
1450 if (!empty($options['force']) && $test) {
1451 $oldversion = $installregistry->packageInfo($pkgname, 'version', $usechannel);
1452 $installregistry->deletePackage($pkgname, $usechannel);
1453 }
1454 $ret = $installregistry->addPackage2($pkg);
1455 } else {
1456 if ($dirtree) {
1457 $this->startFileTransaction();
1458 // attempt to delete empty directories
1459 uksort($dirtree, array($this, '_sortDirs'));
1460 foreach($dirtree as $dir => $notused) {
1461 $this->addFileOperation('rmdir', array($dir));
1462 }
1463 $this->commitFileTransaction();
1464 }
1465
1466 $usechannel = $channel;
1467 if ($channel == 'pecl.php.net') {
1468 $test = $installregistry->packageExists($pkgname, $channel);
1469 if (!$test) {
1470 $test = $installregistry->packageExists($pkgname, 'pear.php.net');
1471 $usechannel = 'pear.php.net';
1472 }
1473 } else {
1474 $test = $installregistry->packageExists($pkgname, $channel);
1475 }
1476
1477 // new: upgrade installs a package if it isn't installed
1478 if (!$test) {
1479 $ret = $installregistry->addPackage2($pkg);
1480 } else {
1481 if ($usechannel != $channel) {
1482 $installregistry->deletePackage($pkgname, $usechannel);
1483 $ret = $installregistry->addPackage2($pkg);
1484 } else {
1485 $ret = $installregistry->updatePackage2($pkg);
1486 }
1487 $installphase = 'upgrade';
1488 }
1489 }
1490
1491 if (!$ret) {
1492 $this->configSet('default_channel', $savechannel);
1493 return $this->raiseError("Adding package $channel/$pkgname to registry failed");
1494 }
1495 // }}}
1496
1497 $this->configSet('default_channel', $savechannel);
1498 if (class_exists('PEAR_Task_Common')) { // this is auto-included if any tasks exist
1501 }
1502 }
1503
1504 return $pkg->toArray(true);
1505 }
_parsePackageXml(&$descfile)
_installFile2(&$pkg, $file, &$real_atts, $tmp_path, $options)
startFileTransaction($rollback_in_case=false)
_compileSourceFiles($savechannel, &$filelist, $configureoptions)
_installFile($file, $atts, $tmp_path, $options)
_removeBackups($files)
_deletePackageFiles($package, $channel=false, $backup=false)
static hasPostinstallTasks()
Definition Common.php:170
static runPostinstallTasks()
Definition Common.php:178
expectError($code=' *')
Definition PEAR.php:415
popExpect()
Definition PEAR.php:431
static mktemp($args=null)
Definition System.php:395

References PEAR_Downloader\$_registry, $options, $tmpdir, _compileSourceFiles(), _deletePackageFiles(), _installFile(), _installFile2(), _parsePackageXml(), PEAR_Downloader\_prependPath(), _removeBackups(), addFileOperation(), commitFileTransaction(), PEAR_Downloader\configSet(), PEAR\expectError(), getInstallPackages(), PEAR_Task_Common\hasPostinstallTasks(), PEAR\isError(), PEAR_Common\log(), PEAR_INSTALLER_FAILED, PEAR_INSTALLER_OK, PEAR\popExpect(), rollbackFileTransaction(), PEAR_Task_Common\runPostinstallTasks(), and startFileTransaction().

Here is the call graph for this function:

◆ mkDirHier()

mkDirHier ( $dir)

Wrapper to System::mkDir(), creates a directory as well as any necessary parent directories.

Parameters
string$dirdirectory name
Returns
bool TRUE on success, or a PEAR error

@access public

Reimplemented from PEAR_Common.

Definition at line 1024 of file Installer.php.

1025 {
1026 $this->addFileOperation('mkdir', array($dir));
1027 return parent::mkDirHier($dir);
1028 }

References addFileOperation().

Referenced by _compileSourceFiles(), _installFile(), and _installFile2().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ rollbackFileTransaction()

rollbackFileTransaction ( )

Definition at line 978 of file Installer.php.

979 {
980 $n = count($this->file_operations);
981 $this->log(2, "rolling back $n file operations");
982 foreach ($this->file_operations as $tr) {
983 list($type, $data) = $tr;
984 switch ($type) {
985 case 'backup':
986 if (file_exists($data[0] . '.bak')) {
987 if (file_exists($data[0] && is_writable($data[0]))) {
988 unlink($data[0]);
989 }
990 @copy($data[0] . '.bak', $data[0]);
991 $this->log(3, "+ restore $data[0] from $data[0].bak");
992 }
993 break;
994 case 'removebackup':
995 if (file_exists($data[0] . '.bak') && is_writable($data[0] . '.bak')) {
996 unlink($data[0] . '.bak');
997 $this->log(3, "+ rm backup of $data[0] ($data[0].bak)");
998 }
999 break;
1000 case 'rename':
1001 @unlink($data[0]);
1002 $this->log(3, "+ rm $data[0]");
1003 break;
1004 case 'mkdir':
1005 @rmdir($data[0]);
1006 $this->log(3, "+ rmdir $data[0]");
1007 break;
1008 case 'chmod':
1009 break;
1010 case 'delete':
1011 break;
1012 case 'installed_as':
1013 $this->pkginfo->setInstalledAs($data[0], false);
1014 break;
1015 }
1016 }
1017 $this->pkginfo->resetDirtree();
1018 $this->file_operations = array();
1019 }

References PEAR_Common\log().

Referenced by _compileSourceFiles(), install(), startFileTransaction(), and uninstall().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setConfig()

setConfig ( & $config)

Definition at line 130 of file Installer.php.

131 {
132 $this->config = &$config;
133 $this->_registry = &$config->getRegistry();
134 }

References PEAR_Common\$config.

◆ setDownloadedPackages()

setDownloadedPackages ( & $pkgs)

Set the list of PEAR_Downloader_Package objects to allow more sane dependency validation

Parameters
array

Definition at line 1062 of file Installer.php.

1063 {
1064 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
1065 $err = $this->analyzeDependencies($pkgs);
1066 PEAR::popErrorHandling();
1067 if (PEAR::isError($err)) {
1068 return $err;
1069 }
1070 $this->_downloadedPackages = &$pkgs;
1071 }
analyzeDependencies(&$params, $force=false)

References PEAR_Downloader\analyzeDependencies(), PEAR\isError(), and PEAR_ERROR_RETURN.

Here is the call graph for this function:

◆ setOptions()

setOptions ( $options)

Reimplemented from PEAR_Downloader.

Definition at line 125 of file Installer.php.

126 {
127 $this->_options = $options;
128 }

References $options.

◆ setUninstallPackages()

setUninstallPackages ( & $pkgs)

Set the list of PEAR_Downloader_Package objects to allow more sane dependency validation

Parameters
array

Definition at line 1078 of file Installer.php.

1079 {
1080 $this->_downloadedPackages = &$pkgs;
1081 }

◆ sortPackagesForUninstall()

sortPackagesForUninstall ( & $packages)

Sort a list of arrays of array(downloaded packagefilename) by dependency.

It also removes duplicate dependencies

Parameters
arrayan array of PEAR_PackageFile_v[1/2] objects
Returns
array|PEAR_Error array of array(packagefilename, package.xml contents)

Definition at line 1755 of file Installer.php.

1756 {
1757 $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->config);
1758 if (PEAR::isError($this->_dependencyDB)) {
1759 return $this->_dependencyDB;
1760 }
1761 usort($packages, array(&$this, '_sortUninstall'));
1762 }
static & singleton(&$config, $depdb=false)

References PEAR\isError(), and PEAR_DependencyDB\singleton().

Here is the call graph for this function:

◆ startFileTransaction()

startFileTransaction ( $rollback_in_case = false)

Definition at line 751 of file Installer.php.

752 {
753 if (count($this->file_operations) && $rollback_in_case) {
755 }
756 $this->file_operations = array();
757 }

References rollbackFileTransaction().

Referenced by install(), and uninstall().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ uninstall()

uninstall ( $package,
$options = array() )

Uninstall a package

This method removes all files installed by the application, and then removes any empty directories.

Parameters
stringpackage name
arrayCommand-line options. Possibilities include:
         - installroot: base installation dir, if not the default
         - register-only : update registry but don't remove files
         - nodeps: do not process dependencies of other packages to ensure
                   uninstallation does not break things

Definition at line 1621 of file Installer.php.

1622 {
1623 $installRoot = isset($options['installroot']) ? $options['installroot'] : '';
1624 $this->config->setInstallRoot($installRoot);
1625
1626 $this->installroot = '';
1627 $this->_registry = &$this->config->getRegistry();
1628 if (is_object($package)) {
1629 $channel = $package->getChannel();
1630 $pkg = $package;
1631 $package = $pkg->getPackage();
1632 } else {
1633 $pkg = false;
1634 $info = $this->_registry->parsePackageName($package,
1635 $this->config->get('default_channel'));
1636 $channel = $info['channel'];
1637 $package = $info['package'];
1638 }
1639
1640 $savechannel = $this->config->get('default_channel');
1641 $this->configSet('default_channel', $channel);
1642 if (!is_object($pkg)) {
1643 $pkg = $this->_registry->getPackage($package, $channel);
1644 }
1645
1646 if (!$pkg) {
1647 $this->configSet('default_channel', $savechannel);
1648 return $this->raiseError($this->_registry->parsedPackageNameToString(
1649 array(
1650 'channel' => $channel,
1651 'package' => $package
1652 ), true) . ' not installed');
1653 }
1654
1655 if ($pkg->getInstalledBinary()) {
1656 // this is just an alias for a binary package
1657 return $this->_registry->deletePackage($package, $channel);
1658 }
1659
1660 $filelist = $pkg->getFilelist();
1662 if (!class_exists('PEAR_Dependency2')) {
1663 require_once 'PEAR/Dependency2.php';
1664 }
1665
1666 $depchecker = new PEAR_Dependency2($this->config, $options,
1667 array('channel' => $channel, 'package' => $package),
1669 $e = $depchecker->validatePackageUninstall($this);
1671 if (PEAR::isError($e)) {
1672 if (!isset($options['ignore-errors'])) {
1673 return $this->raiseError($e);
1674 }
1675
1676 if (!isset($options['soft'])) {
1677 $this->log(0, 'WARNING: ' . $e->getMessage());
1678 }
1679 } elseif (is_array($e)) {
1680 if (!isset($options['soft'])) {
1681 $this->log(0, $e[0]);
1682 }
1683 }
1684
1685 $this->pkginfo = &$pkg;
1686 // pretty much nothing happens if we are only registering the uninstall
1687 if (empty($options['register-only'])) {
1688 // {{{ Delete the files
1689 $this->startFileTransaction();
1690 PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
1691 if (PEAR::isError($err = $this->_deletePackageFiles($package, $channel))) {
1692 PEAR::popErrorHandling();
1693 $this->rollbackFileTransaction();
1694 $this->configSet('default_channel', $savechannel);
1695 if (!isset($options['ignore-errors'])) {
1696 return $this->raiseError($err);
1697 }
1698
1699 if (!isset($options['soft'])) {
1700 $this->log(0, 'WARNING: ' . $err->getMessage());
1701 }
1702 } else {
1703 PEAR::popErrorHandling();
1704 }
1705
1706 if (!$this->commitFileTransaction()) {
1707 $this->rollbackFileTransaction();
1708 if (!isset($options['ignore-errors'])) {
1709 return $this->raiseError("uninstall failed");
1710 }
1711
1712 if (!isset($options['soft'])) {
1713 $this->log(0, 'WARNING: uninstall failed');
1714 }
1715 } else {
1716 $this->startFileTransaction();
1717 $dirtree = $pkg->getDirTree();
1718 if ($dirtree === false) {
1719 $this->configSet('default_channel', $savechannel);
1720 return $this->_registry->deletePackage($package, $channel);
1721 }
1722
1723 // attempt to delete empty directories
1724 uksort($dirtree, array($this, '_sortDirs'));
1725 foreach($dirtree as $dir => $notused) {
1726 $this->addFileOperation('rmdir', array($dir));
1727 }
1728
1729 if (!$this->commitFileTransaction()) {
1730 $this->rollbackFileTransaction();
1731 if (!isset($options['ignore-errors'])) {
1732 return $this->raiseError("uninstall failed");
1733 }
1734
1735 if (!isset($options['soft'])) {
1736 $this->log(0, 'WARNING: uninstall failed');
1737 }
1738 }
1739 }
1740 // }}}
1741 }
1742
1743 $this->configSet('default_channel', $savechannel);
1744 // Register that the package is no longer installed
1745 return $this->_registry->deletePackage($package, $channel);
1746 }
const PEAR_VALIDATE_UNINSTALLING
Definition Validate.php:19

References $options, _deletePackageFiles(), addFileOperation(), commitFileTransaction(), PEAR_Downloader\configSet(), PEAR\isError(), PEAR_Common\log(), PEAR_ERROR_RETURN, PEAR_VALIDATE_UNINSTALLING, rollbackFileTransaction(), startFileTransaction(), PEAR\staticPopErrorHandling(), and PEAR\staticPushErrorHandling().

Here is the call graph for this function:

Field Documentation

◆ $_downloadedPackages

$_downloadedPackages

Definition at line 92 of file Installer.php.

Referenced by getInstallPackages(), and getUninstallPackages().

◆ $debug

$debug = 1

Definition at line 75 of file Installer.php.

Referenced by _compileSourceFiles().

◆ $docdir

$docdir

Definition at line 64 of file Installer.php.

◆ $extdir

$extdir

Definition at line 59 of file Installer.php.

◆ $file_operations

$file_operations = array()

Definition at line 105 of file Installer.php.

◆ $installroot

$installroot = ''

Definition at line 70 of file Installer.php.

◆ $phpdir

$phpdir

Definition at line 54 of file Installer.php.

◆ $pkgdir

$pkgdir

Definition at line 49 of file Installer.php.

◆ $registry

$registry

Definition at line 86 of file Installer.php.

◆ $tmpdir

$tmpdir

Definition at line 80 of file Installer.php.

Referenced by install().


The documentation for this class was generated from the following file:
  • E:/Bearsampp-development/sandbox/core/libs/php/pear/pear/PEAR/Installer.php