[ Index ] |
|
Code source de PHP PEAR 1.4.5 |
1 <?php 2 /** 3 * PEAR_Downloader_Package 4 * 5 * PHP versions 4 and 5 6 * 7 * LICENSE: This source file is subject to version 3.0 of the PHP license 8 * that is available through the world-wide-web at the following URI: 9 * http://www.php.net/license/3_0.txt. If you did not receive a copy of 10 * the PHP License and are unable to obtain it through the web, please 11 * send a note to license@php.net so we can mail you a copy immediately. 12 * 13 * @category pear 14 * @package PEAR 15 * @author Greg Beaver <cellog@php.net> 16 * @copyright 1997-2006 The PHP Group 17 * @license http://www.php.net/license/3_0.txt PHP License 3.0 18 * @version CVS: $Id: Package.php,v 1.104 2007/01/14 21:11:54 cellog Exp $ 19 * @link http://pear.php.net/package/PEAR 20 * @since File available since Release 1.4.0a1 21 */ 22 /** 23 * Error code when parameter initialization fails because no releases 24 * exist within preferred_state, but releases do exist 25 */ 26 define('PEAR_DOWNLOADER_PACKAGE_STATE', -1003); 27 /** 28 * Coordinates download parameters and manages their dependencies 29 * prior to downloading them. 30 * 31 * Input can come from three sources: 32 * 33 * - local files (archives or package.xml) 34 * - remote files (downloadable urls) 35 * - abstract package names 36 * 37 * The first two elements are handled cleanly by PEAR_PackageFile, but the third requires 38 * accessing pearweb's xml-rpc interface to determine necessary dependencies, and the 39 * format returned of dependencies is slightly different from that used in package.xml. 40 * 41 * This class hides the differences between these elements, and makes automatic 42 * dependency resolution a piece of cake. It also manages conflicts when 43 * two classes depend on incompatible dependencies, or differing versions of the same 44 * package dependency. In addition, download will not be attempted if the php version is 45 * not supported, PEAR installer version is not supported, or non-PECL extensions are not 46 * installed. 47 * @category pear 48 * @package PEAR 49 * @author Greg Beaver <cellog@php.net> 50 * @copyright 1997-2006 The PHP Group 51 * @license http://www.php.net/license/3_0.txt PHP License 3.0 52 * @version Release: 1.5.0 53 * @link http://pear.php.net/package/PEAR 54 * @since Class available since Release 1.4.0a1 55 */ 56 class PEAR_Downloader_Package 57 { 58 /** 59 * @var PEAR_Downloader 60 */ 61 var $_downloader; 62 /** 63 * @var PEAR_Config 64 */ 65 var $_config; 66 /** 67 * @var PEAR_Registry 68 */ 69 var $_registry; 70 /** 71 * Used to implement packagingroot properly 72 * @var PEAR_Registry 73 */ 74 var $_installRegistry; 75 /** 76 * @var PEAR_PackageFile_v1|PEAR_PackageFile|v2 77 */ 78 var $_packagefile; 79 /** 80 * @var array 81 */ 82 var $_parsedname; 83 /** 84 * @var array 85 */ 86 var $_downloadURL; 87 /** 88 * @var array 89 */ 90 var $_downloadDeps = array(); 91 /** 92 * @var boolean 93 */ 94 var $_valid = false; 95 /** 96 * @var boolean 97 */ 98 var $_analyzed = false; 99 /** 100 * if this or a parent package was invoked with Package-state, this is set to the 101 * state variable. 102 * 103 * This allows temporary reassignment of preferred_state for a parent package and all of 104 * its dependencies. 105 * @var string|false 106 */ 107 var $_explicitState = false; 108 /** 109 * If this package is invoked with Package#group, this variable will be true 110 */ 111 var $_explicitGroup = false; 112 /** 113 * Package type local|url|xmlrpc 114 * @var string 115 */ 116 var $_type; 117 /** 118 * Contents of package.xml, if downloaded from a remote channel 119 * @var string|false 120 * @access private 121 */ 122 var $_rawpackagefile; 123 /** 124 * @var boolean 125 * @access private 126 */ 127 var $_validated = false; 128 129 /** 130 * @param PEAR_Downloader 131 */ 132 function PEAR_Downloader_Package(&$downloader) 133 { 134 $this->_downloader = &$downloader; 135 $this->_config = &$this->_downloader->config; 136 $this->_registry = &$this->_config->getRegistry(); 137 $options = $downloader->getOptions(); 138 if (isset($options['packagingroot'])) { 139 $this->_config->setInstallRoot($options['packagingroot']); 140 $this->_installRegistry = &$this->_config->getRegistry(); 141 $this->_config->setInstallRoot(false); 142 } else { 143 $this->_installRegistry = &$this->_registry; 144 } 145 $this->_valid = $this->_analyzed = false; 146 } 147 148 /** 149 * Parse the input and determine whether this is a local file, a remote uri, or an 150 * abstract package name. 151 * 152 * This is the heart of the PEAR_Downloader_Package(), and is used in 153 * {@link PEAR_Downloader::download()} 154 * @param string 155 * @return bool|PEAR_Error 156 */ 157 function initialize($param) 158 { 159 $origErr = $this->_fromFile($param); 160 if (!$this->_valid) { 161 $options = $this->_downloader->getOptions(); 162 if (isset($options['offline'])) { 163 if (PEAR::isError($origErr)) { 164 if (!isset($options['soft'])) { 165 $this->_downloader->log(0, $origErr->getMessage()); 166 } 167 } 168 return PEAR::raiseError('Cannot download non-local package "' . $param . '"'); 169 } 170 $err = $this->_fromUrl($param); 171 if (PEAR::isError($err) || !$this->_valid) { 172 if ($this->_type == 'url') { 173 if (PEAR::isError($err)) { 174 if (!isset($options['soft'])) { 175 $this->_downloader->log(0, $err->getMessage()); 176 } 177 } 178 return PEAR::raiseError("Invalid or missing remote package file"); 179 } 180 $err = $this->_fromString($param); 181 if (PEAR::isError($err) || !$this->_valid) { 182 if (PEAR::isError($err) && 183 $err->getCode() == PEAR_DOWNLOADER_PACKAGE_STATE) { 184 return false; // instruct the downloader to silently skip 185 } 186 if (isset($this->_type) && $this->_type == 'local' && 187 PEAR::isError($origErr)) { 188 if (is_array($origErr->getUserInfo())) { 189 foreach ($origErr->getUserInfo() as $err) { 190 if (is_array($err)) { 191 $err = $err['message']; 192 } 193 if (!isset($options['soft'])) { 194 $this->_downloader->log(0, $err); 195 } 196 } 197 } 198 if (!isset($options['soft'])) { 199 $this->_downloader->log(0, $origErr->getMessage()); 200 } 201 if (is_array($param)) { 202 $param = $this->_registry->parsedPackageNameToString($param, 203 true); 204 } 205 return PEAR::raiseError( 206 "Cannot initialize '$param', invalid or missing package file"); 207 } 208 if (PEAR::isError($err)) { 209 if (!isset($options['soft'])) { 210 $this->_downloader->log(0, $err->getMessage()); 211 } 212 } 213 if (is_array($param)) { 214 $param = $this->_registry->parsedPackageNameToString($param, true); 215 } 216 return PEAR::raiseError( 217 "Cannot initialize '$param', invalid or missing package file"); 218 } 219 } 220 } 221 return true; 222 } 223 224 /** 225 * Retrieve any non-local packages 226 * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|PEAR_Error 227 */ 228 function &download() 229 { 230 if (isset($this->_packagefile)) { 231 return $this->_packagefile; 232 } 233 if (isset($this->_downloadURL['url'])) { 234 $this->_isvalid = false; 235 $info = $this->getParsedPackage(); 236 foreach ($info as $i => $p) { 237 $info[$i] = strtolower($p); 238 } 239 $err = $this->_fromUrl($this->_downloadURL['url'], 240 $this->_registry->parsedPackageNameToString($this->_parsedname, true)); 241 $newinfo = $this->getParsedPackage(); 242 foreach ($newinfo as $i => $p) { 243 $newinfo[$i] = strtolower($p); 244 } 245 if ($info != $newinfo) { 246 do { 247 if ($info['package'] == 'pecl.php.net' && $newinfo['package'] == 'pear.php.net') { 248 $info['package'] = 'pear.php.net'; 249 if ($info == $newinfo) { 250 // skip the channel check if a pecl package says it's a PEAR package 251 break; 252 } 253 } 254 return PEAR::raiseError('CRITICAL ERROR: We are ' . 255 $this->_registry->parsedPackageNameToString($info) . ', but the file ' . 256 'downloaded claims to be ' . 257 $this->_registry->parsedPackageNameToString($this->getParsedPackage())); 258 } while (false); 259 } 260 if (PEAR::isError($err) || !$this->_valid) { 261 return $err; 262 } 263 } 264 $this->_type = 'local'; 265 return $this->_packagefile; 266 } 267 268 function &getPackageFile() 269 { 270 return $this->_packagefile; 271 } 272 273 function &getDownloader() 274 { 275 return $this->_downloader; 276 } 277 278 function getType() 279 { 280 return $this->_type; 281 } 282 283 /** 284 * Like {@link initialize()}, but operates on a dependency 285 */ 286 function fromDepURL($dep) 287 { 288 $this->_downloadURL = $dep; 289 if (isset($dep['uri'])) { 290 $options = $this->_downloader->getOptions(); 291 if (!extension_loaded("zlib") || isset($options['nocompress'])) { 292 $ext = '.tar'; 293 } else { 294 $ext = '.tgz'; 295 } 296 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 297 $err = $this->_fromUrl($dep['uri'] . $ext); 298 PEAR::popErrorHandling(); 299 if (PEAR::isError($err)) { 300 if (!isset($options['soft'])) { 301 $this->_downloader->log(0, $err->getMessage()); 302 } 303 return PEAR::raiseError('Invalid uri dependency "' . $dep['uri'] . $ext . '", ' . 304 'cannot download'); 305 } 306 } else { 307 $this->_parsedname = 308 array( 309 'package' => $dep['info']->getPackage(), 310 'channel' => $dep['info']->getChannel(), 311 'version' => $dep['version'] 312 ); 313 if (!isset($dep['nodefault'])) { 314 $this->_parsedname['group'] = 'default'; // download the default dependency group 315 $this->_explicitGroup = false; 316 } 317 $this->_rawpackagefile = $dep['raw']; 318 } 319 } 320 321 function detectDependencies($params) 322 { 323 $options = $this->_downloader->getOptions(); 324 if (isset($options['downloadonly'])) { 325 return; 326 } 327 if (isset($options['offline'])) { 328 $this->_downloader->log(3, 'Skipping dependency download check, --offline specified'); 329 return; 330 } 331 $pname = $this->getParsedPackage(); 332 if (!$pname) { 333 return; 334 } 335 $deps = $this->getDeps(); 336 if (!$deps) { 337 return; 338 } 339 if (isset($deps['required'])) { // package.xml 2.0 340 return $this->_detect2($deps, $pname, $options, $params); 341 } else { 342 return $this->_detect1($deps, $pname, $options, $params); 343 } 344 } 345 346 function setValidated() 347 { 348 $this->_validated = true; 349 } 350 351 function alreadyValidated() 352 { 353 return $this->_validated; 354 } 355 356 /** 357 * Remove packages to be downloaded that are already installed 358 * @param array of PEAR_Downloader_Package objects 359 * @static 360 */ 361 function removeInstalled(&$params) 362 { 363 if (!isset($params[0])) { 364 return; 365 } 366 $options = $params[0]->_downloader->getOptions(); 367 if (!isset($options['downloadonly'])) { 368 foreach ($params as $i => $param) { 369 // remove self if already installed with this version 370 // this does not need any pecl magic - we only remove exact matches 371 if ($param->_installRegistry->packageExists($param->getPackage(), $param->getChannel())) { 372 if (version_compare($param->_installRegistry->packageInfo($param->getPackage(), 'version', 373 $param->getChannel()), $param->getVersion(), '==')) { 374 if (!isset($options['force'])) { 375 $info = $param->getParsedPackage(); 376 unset($info['version']); 377 unset($info['state']); 378 if (!isset($options['soft'])) { 379 $param->_downloader->log(1, 'Skipping package "' . 380 $param->getShortName() . 381 '", already installed as version ' . 382 $param->_installRegistry->packageInfo($param->getPackage(), 383 'version', $param->getChannel())); 384 } 385 $params[$i] = false; 386 } 387 } elseif (!isset($options['force']) && !isset($options['upgrade']) && 388 !isset($options['soft'])) { 389 $info = $param->getParsedPackage(); 390 $param->_downloader->log(1, 'Skipping package "' . 391 $param->getShortName() . 392 '", already installed as version ' . 393 $param->_installRegistry->packageInfo($param->getPackage(), 'version', 394 $param->getChannel())); 395 $params[$i] = false; 396 } 397 } 398 } 399 } 400 PEAR_Downloader_Package::removeDuplicates($params); 401 } 402 403 function _detect2($deps, $pname, $options, $params) 404 { 405 $this->_downloadDeps = array(); 406 $groupnotfound = false; 407 foreach (array('package', 'subpackage') as $packagetype) { 408 // get required dependency group 409 if (isset($deps['required'][$packagetype])) { 410 if (isset($deps['required'][$packagetype][0])) { 411 foreach ($deps['required'][$packagetype] as $dep) { 412 if (isset($dep['conflicts'])) { 413 // skip any package that this package conflicts with 414 continue; 415 } 416 $ret = $this->_detect2Dep($dep, $pname, 'required', $params); 417 if (is_array($ret)) { 418 $this->_downloadDeps[] = $ret; 419 } 420 } 421 } else { 422 $dep = $deps['required'][$packagetype]; 423 if (!isset($dep['conflicts'])) { 424 // skip any package that this package conflicts with 425 $ret = $this->_detect2Dep($dep, $pname, 'required', $params); 426 if (is_array($ret)) { 427 $this->_downloadDeps[] = $ret; 428 } 429 } 430 } 431 } 432 // get optional dependency group, if any 433 if (isset($deps['optional'][$packagetype])) { 434 $skipnames = array(); 435 if (!isset($deps['optional'][$packagetype][0])) { 436 $deps['optional'][$packagetype] = array($deps['optional'][$packagetype]); 437 } 438 foreach ($deps['optional'][$packagetype] as $dep) { 439 $skip = false; 440 if (!isset($options['alldeps'])) { 441 $dep['package'] = $dep['name']; 442 if (!isset($options['soft'])) { 443 $this->_downloader->log(3, 'Notice: package "' . 444 $this->_registry->parsedPackageNameToString($this->getParsedPackage(), 445 true) . '" optional dependency "' . 446 $this->_registry->parsedPackageNameToString(array('package' => 447 $dep['name'], 'channel' => 'pear.php.net'), true) . 448 '" will not be automatically downloaded'); 449 } 450 $skipnames[] = $this->_registry->parsedPackageNameToString($dep, true); 451 $skip = true; 452 unset($dep['package']); 453 } 454 if (!($ret = $this->_detect2Dep($dep, $pname, 'optional', $params))) { 455 $dep['package'] = $dep['name']; 456 $skip = count($skipnames) ? 457 $skipnames[count($skipnames) - 1] : ''; 458 if ($skip == 459 $this->_registry->parsedPackageNameToString($dep, true)) { 460 array_pop($skipnames); 461 } 462 } 463 if (!$skip && is_array($ret)) { 464 $this->_downloadDeps[] = $ret; 465 } 466 } 467 if (count($skipnames)) { 468 if (!isset($options['soft'])) { 469 $this->_downloader->log(1, 'Did not download optional dependencies: ' . 470 implode(', ', $skipnames) . 471 ', use --alldeps to download automatically'); 472 } 473 } 474 } 475 // get requested dependency group, if any 476 $groupname = $this->getGroup(); 477 $explicit = $this->_explicitGroup; 478 if (!$groupname) { 479 if ($this->canDefault()) { 480 $groupname = 'default'; // try the default dependency group 481 } else { 482 continue; 483 } 484 } 485 if ($groupnotfound) { 486 continue; 487 } 488 if (isset($deps['group'])) { 489 if (isset($deps['group']['attribs'])) { 490 if (strtolower($deps['group']['attribs']['name']) == strtolower($groupname)) { 491 $group = $deps['group']; 492 } elseif ($explicit) { 493 if (!isset($options['soft'])) { 494 $this->_downloader->log(0, 'Warning: package "' . 495 $this->_registry->parsedPackageNameToString($pname, true) . 496 '" has no dependency ' . 'group named "' . $groupname . '"'); 497 } 498 $groupnotfound = true; 499 continue; 500 } 501 } else { 502 $found = false; 503 foreach ($deps['group'] as $group) { 504 if (strtolower($group['attribs']['name']) == strtolower($groupname)) { 505 $found = true; 506 break; 507 } 508 } 509 if (!$found) { 510 if ($explicit) { 511 if (!isset($options['soft'])) { 512 $this->_downloader->log(0, 'Warning: package "' . 513 $this->_registry->parsedPackageNameToString($pname, true) . 514 '" has no dependency ' . 'group named "' . $groupname . '"'); 515 } 516 } 517 $groupnotfound = true; 518 continue; 519 } 520 } 521 } 522 if (isset($group)) { 523 if (isset($group[$packagetype])) { 524 if (isset($group[$packagetype][0])) { 525 foreach ($group[$packagetype] as $dep) { 526 $ret = $this->_detect2Dep($dep, $pname, 'dependency group "' . 527 $group['attribs']['name'] . '"', $params); 528 if (is_array($ret)) { 529 $this->_downloadDeps[] = $ret; 530 } 531 } 532 } else { 533 $ret = $this->_detect2Dep($group[$packagetype], $pname, 534 'dependency group "' . 535 $group['attribs']['name'] . '"', $params); 536 if (is_array($ret)) { 537 $this->_downloadDeps[] = $ret; 538 } 539 } 540 } 541 } 542 } 543 } 544 545 function _detect2Dep($dep, $pname, $group, $params) 546 { 547 if (isset($dep['conflicts'])) { 548 return true; 549 } 550 $options = $this->_downloader->getOptions(); 551 if (isset($dep['uri'])) { 552 return array('uri' => $dep['uri'], 'dep' => $dep);; 553 } 554 $testdep = $dep; 555 $testdep['package'] = $dep['name']; 556 if (PEAR_Downloader_Package::willDownload($testdep, $params)) { 557 $dep['package'] = $dep['name']; 558 if (!isset($options['soft'])) { 559 $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group . 560 ' dependency "' . 561 $this->_registry->parsedPackageNameToString($dep, true) . 562 '", will be installed'); 563 } 564 return false; 565 } 566 $options = $this->_downloader->getOptions(); 567 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 568 if ($this->_explicitState) { 569 $pname['state'] = $this->_explicitState; 570 } 571 $url = 572 $this->_downloader->_getDepPackageDownloadUrl($dep, $pname); 573 if (PEAR::isError($url)) { 574 PEAR::popErrorHandling(); 575 return $url; 576 } 577 $dep['package'] = $dep['name']; 578 $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, $group == 'optional' && 579 !isset($options['alldeps']), true); 580 PEAR::popErrorHandling(); 581 if (PEAR::isError($ret)) { 582 if (!isset($options['soft'])) { 583 $this->_downloader->log(0, $ret->getMessage()); 584 } 585 return false; 586 } else { 587 // check to see if a dep is already installed and is the same or newer 588 if (!isset($dep['min']) && !isset($dep['max']) && !isset($dep['recommended'])) { 589 $oper = 'has'; 590 } else { 591 $oper = 'gt'; 592 } 593 // do not try to move this before getDepPackageDownloadURL 594 // we can't determine whether upgrade is necessary until we know what 595 // version would be downloaded 596 if (!isset($options['force']) && $this->isInstalled($ret, $oper)) { 597 $version = $this->_installRegistry->packageInfo($dep['name'], 'version', 598 $dep['channel']); 599 $dep['package'] = $dep['name']; 600 if (!isset($options['soft'])) { 601 $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group . 602 ' dependency "' . 603 $this->_registry->parsedPackageNameToString($dep, true) . 604 '" version ' . $url['version'] . ', already installed as version ' . 605 $version); 606 } 607 return false; 608 } 609 } 610 if (isset($dep['nodefault'])) { 611 $ret['nodefault'] = true; 612 } 613 return $ret; 614 } 615 616 function _detect1($deps, $pname, $options, $params) 617 { 618 $this->_downloadDeps = array(); 619 $skipnames = array(); 620 foreach ($deps as $dep) { 621 $nodownload = false; 622 if ($dep['type'] == 'pkg') { 623 $dep['channel'] = 'pear.php.net'; 624 $dep['package'] = $dep['name']; 625 switch ($dep['rel']) { 626 case 'not' : 627 continue 2; 628 case 'ge' : 629 case 'eq' : 630 case 'gt' : 631 case 'has' : 632 $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ? 633 'required' : 634 'optional'; 635 if (PEAR_Downloader_Package::willDownload($dep, $params)) { 636 $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group 637 . ' dependency "' . 638 $this->_registry->parsedPackageNameToString($dep, true) . 639 '", will be installed'); 640 continue 2; 641 } 642 $fakedp = new PEAR_PackageFile_v1; 643 $fakedp->setPackage($dep['name']); 644 // skip internet check if we are not upgrading (bug #5810) 645 if (!isset($options['upgrade']) && $this->isInstalled( 646 $fakedp, $dep['rel'])) { 647 $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group 648 . ' dependency "' . 649 $this->_registry->parsedPackageNameToString($dep, true) . 650 '", is already installed'); 651 continue 2; 652 } 653 } 654 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 655 if ($this->_explicitState) { 656 $pname['state'] = $this->_explicitState; 657 } 658 $url = 659 $this->_downloader->_getDepPackageDownloadUrl($dep, $pname); 660 $chan = 'pear.php.net'; 661 if (PEAR::isError($url)) { 662 // check to see if this is a pecl package that has jumped 663 // from pear.php.net to pecl.php.net channel 664 if (!class_exists('PEAR_Dependency2')) { 665 require_once 'PEAR/Dependency2.php'; 666 } 667 $newdep = PEAR_Dependency2::normalizeDep($dep); 668 $newdep = $newdep[0]; 669 $newdep['channel'] = 'pecl.php.net'; 670 $chan = 'pecl.php.net'; 671 $url = 672 $this->_downloader->_getDepPackageDownloadUrl($newdep, $pname); 673 $obj = &$this->_installRegistry->getPackage($dep['name']); 674 if (PEAR::isError($url)) { 675 PEAR::popErrorHandling(); 676 if ($obj !== null && $this->isInstalled($obj, $dep['rel'])) { 677 $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ? 678 'required' : 679 'optional'; 680 $dep['package'] = $dep['name']; 681 if (!isset($options['soft'])) { 682 $this->_downloader->log(3, $this->getShortName() . 683 ': Skipping ' . $group . ' dependency "' . 684 $this->_registry->parsedPackageNameToString($dep, true) . 685 '", already installed as version ' . $obj->getVersion()); 686 } 687 $skip = count($skipnames) ? 688 $skipnames[count($skipnames) - 1] : ''; 689 if ($skip == 690 $this->_registry->parsedPackageNameToString($dep, true)) { 691 array_pop($skipnames); 692 } 693 continue; 694 } else { 695 if (isset($dep['optional']) && $dep['optional'] == 'yes') { 696 $this->_downloader->log(2, $this->getShortName() . 697 ': Skipping ' . $group 698 . ' dependency "' . 699 $this->_registry->parsedPackageNameToString($dep, true) . 700 '", no releases exist'); 701 continue; 702 } else { 703 return $url; 704 } 705 } 706 } 707 } 708 PEAR::popErrorHandling(); 709 if (!isset($options['alldeps'])) { 710 if (isset($dep['optional']) && $dep['optional'] == 'yes') { 711 if (!isset($options['soft'])) { 712 $this->_downloader->log(3, 'Notice: package "' . 713 $this->getShortName() . 714 '" optional dependency "' . 715 $this->_registry->parsedPackageNameToString( 716 array('channel' => $chan, 'package' => 717 $dep['name']), true) . 718 '" will not be automatically downloaded'); 719 } 720 $skipnames[] = $this->_registry->parsedPackageNameToString( 721 array('channel' => $chan, 'package' => 722 $dep['name']), true); 723 $nodownload = true; 724 } 725 } 726 if (!isset($options['alldeps']) && !isset($options['onlyreqdeps'])) { 727 if (!isset($dep['optional']) || $dep['optional'] == 'no') { 728 if (!isset($options['soft'])) { 729 $this->_downloader->log(3, 'Notice: package "' . 730 $this->getShortName() . 731 '" required dependency "' . 732 $this->_registry->parsedPackageNameToString( 733 array('channel' => $chan, 'package' => 734 $dep['name']), true) . 735 '" will not be automatically downloaded'); 736 } 737 $skipnames[] = $this->_registry->parsedPackageNameToString( 738 array('channel' => $chan, 'package' => 739 $dep['name']), true); 740 $nodownload = true; 741 } 742 } 743 // check to see if a dep is already installed 744 // do not try to move this before getDepPackageDownloadURL 745 // we can't determine whether upgrade is necessary until we know what 746 // version would be downloaded 747 if (!isset($options['force']) && $this->isInstalled( 748 $url, $dep['rel'])) { 749 $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ? 750 'required' : 751 'optional'; 752 $dep['package'] = $dep['name']; 753 if (isset($newdep)) { 754 $version = $this->_installRegistry->packageInfo($newdep['name'], 'version', 755 $newdep['channel']); 756 } else { 757 $version = $this->_installRegistry->packageInfo($dep['name'], 'version'); 758 } 759 $dep['version'] = $url['version']; 760 if (!isset($options['soft'])) { 761 $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group . 762 ' dependency "' . 763 $this->_registry->parsedPackageNameToString($dep, true) . 764 '", already installed as version ' . $version); 765 } 766 $skip = count($skipnames) ? 767 $skipnames[count($skipnames) - 1] : ''; 768 if ($skip == 769 $this->_registry->parsedPackageNameToString($dep, true)) { 770 array_pop($skipnames); 771 } 772 continue; 773 } 774 if ($nodownload) { 775 continue; 776 } 777 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 778 if (isset($newdep)) { 779 $dep = $newdep; 780 } 781 $dep['package'] = $dep['name']; 782 $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, 783 isset($dep['optional']) && $dep['optional'] == 'yes' && 784 !isset($options['alldeps']), true); 785 PEAR::popErrorHandling(); 786 if (PEAR::isError($ret)) { 787 if (!isset($options['soft'])) { 788 $this->_downloader->log(0, $ret->getMessage()); 789 } 790 continue; 791 } 792 $this->_downloadDeps[] = $ret; 793 } 794 } 795 if (count($skipnames)) { 796 if (!isset($options['soft'])) { 797 $this->_downloader->log(1, 'Did not download dependencies: ' . 798 implode(', ', $skipnames) . 799 ', use --alldeps or --onlyreqdeps to download automatically'); 800 } 801 } 802 } 803 804 function setDownloadURL($pkg) 805 { 806 $this->_downloadURL = $pkg; 807 } 808 809 /** 810 * Set the package.xml object for this downloaded package 811 * 812 * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 $pkg 813 */ 814 function setPackageFile(&$pkg) 815 { 816 $this->_packagefile = &$pkg; 817 } 818 819 function getShortName() 820 { 821 return $this->_registry->parsedPackageNameToString(array('channel' => $this->getChannel(), 822 'package' => $this->getPackage()), true); 823 } 824 825 function getParsedPackage() 826 { 827 if (isset($this->_packagefile) || isset($this->_parsedname)) { 828 return array('channel' => $this->getChannel(), 829 'package' => $this->getPackage(), 830 'version' => $this->getVersion()); 831 } 832 return false; 833 } 834 835 function getDownloadURL() 836 { 837 return $this->_downloadURL; 838 } 839 840 function canDefault() 841 { 842 if (isset($this->_downloadURL)) { 843 if (isset($this->_downloadURL['nodefault'])) { 844 return false; 845 } 846 } 847 return true; 848 } 849 850 function getPackage() 851 { 852 if (isset($this->_packagefile)) { 853 return $this->_packagefile->getPackage(); 854 } elseif (isset($this->_downloadURL['info'])) { 855 return $this->_downloadURL['info']->getPackage(); 856 } else { 857 return false; 858 } 859 } 860 861 /** 862 * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 863 */ 864 function isSubpackage(&$pf) 865 { 866 if (isset($this->_packagefile)) { 867 return $this->_packagefile->isSubpackage($pf); 868 } elseif (isset($this->_downloadURL['info'])) { 869 return $this->_downloadURL['info']->isSubpackage($pf); 870 } else { 871 return false; 872 } 873 } 874 875 function getPackageType() 876 { 877 if (isset($this->_packagefile)) { 878 return $this->_packagefile->getPackageType(); 879 } elseif (isset($this->_downloadURL['info'])) { 880 return $this->_downloadURL['info']->getPackageType(); 881 } else { 882 return false; 883 } 884 } 885 886 function isBundle() 887 { 888 if (isset($this->_packagefile)) { 889 return $this->_packagefile->getPackageType() == 'bundle'; 890 } else { 891 return false; 892 } 893 } 894 895 function getPackageXmlVersion() 896 { 897 if (isset($this->_packagefile)) { 898 return $this->_packagefile->getPackagexmlVersion(); 899 } elseif (isset($this->_downloadURL['info'])) { 900 return $this->_downloadURL['info']->getPackagexmlVersion(); 901 } else { 902 return '1.0'; 903 } 904 } 905 906 function getChannel() 907 { 908 if (isset($this->_packagefile)) { 909 return $this->_packagefile->getChannel(); 910 } elseif (isset($this->_downloadURL['info'])) { 911 return $this->_downloadURL['info']->getChannel(); 912 } else { 913 return false; 914 } 915 } 916 917 function getURI() 918 { 919 if (isset($this->_packagefile)) { 920 return $this->_packagefile->getURI(); 921 } elseif (isset($this->_downloadURL['info'])) { 922 return $this->_downloadURL['info']->getURI(); 923 } else { 924 return false; 925 } 926 } 927 928 function getVersion() 929 { 930 if (isset($this->_packagefile)) { 931 return $this->_packagefile->getVersion(); 932 } elseif (isset($this->_downloadURL['version'])) { 933 return $this->_downloadURL['version']; 934 } else { 935 return false; 936 } 937 } 938 939 function isCompatible($pf) 940 { 941 if (isset($this->_packagefile)) { 942 return $this->_packagefile->isCompatible($pf); 943 } elseif (isset($this->_downloadURL['info'])) { 944 return $this->_downloadURL['info']->isCompatible($pf); 945 } else { 946 return true; 947 } 948 } 949 950 function setGroup($group) 951 { 952 $this->_parsedname['group'] = $group; 953 } 954 955 function getGroup() 956 { 957 if (isset($this->_parsedname['group'])) { 958 return $this->_parsedname['group']; 959 } else { 960 return ''; 961 } 962 } 963 964 function isExtension($name) 965 { 966 if (isset($this->_packagefile)) { 967 return $this->_packagefile->isExtension($name); 968 } elseif (isset($this->_downloadURL['info'])) { 969 if ($this->_downloadURL['info']->getPackagexmlVersion() == '2.0') { 970 return $this->_downloadURL['info']->getProvidesExtension() == $name; 971 } else { 972 return false; 973 } 974 } else { 975 return false; 976 } 977 } 978 979 function getDeps() 980 { 981 if (isset($this->_packagefile)) { 982 $ver = $this->_packagefile->getPackagexmlVersion(); 983 if (version_compare($ver, '2.0', '>=')) { 984 return $this->_packagefile->getDeps(true); 985 } else { 986 return $this->_packagefile->getDeps(); 987 } 988 } elseif (isset($this->_downloadURL['info'])) { 989 $ver = $this->_downloadURL['info']->getPackagexmlVersion(); 990 if (version_compare($ver, '2.0', '>=')) { 991 return $this->_downloadURL['info']->getDeps(true); 992 } else { 993 return $this->_downloadURL['info']->getDeps(); 994 } 995 } else { 996 return array(); 997 } 998 } 999 1000 /** 1001 * @param array Parsed array from {@link PEAR_Registry::parsePackageName()} or a dependency 1002 * returned from getDepDownloadURL() 1003 */ 1004 function isEqual($param) 1005 { 1006 if (is_object($param)) { 1007 $channel = $param->getChannel(); 1008 $package = $param->getPackage(); 1009 if ($param->getURI()) { 1010 $param = array( 1011 'channel' => $param->getChannel(), 1012 'package' => $param->getPackage(), 1013 'version' => $param->getVersion(), 1014 'uri' => $param->getURI(), 1015 ); 1016 } else { 1017 $param = array( 1018 'channel' => $param->getChannel(), 1019 'package' => $param->getPackage(), 1020 'version' => $param->getVersion(), 1021 ); 1022 } 1023 } else { 1024 if (isset($param['uri'])) { 1025 if ($this->getChannel() != '__uri') { 1026 return false; 1027 } 1028 return $param['uri'] == $this->getURI(); 1029 } 1030 $package = isset($param['package']) ? $param['package'] : 1031 $param['info']->getPackage(); 1032 $channel = isset($param['channel']) ? $param['channel'] : 1033 $param['info']->getChannel(); 1034 if (isset($param['rel'])) { 1035 if (!class_exists('PEAR_Dependency2')) { 1036 require_once 'PEAR/Dependency2.php'; 1037 } 1038 $newdep = PEAR_Dependency2::normalizeDep($param); 1039 $newdep = $newdep[0]; 1040 } elseif (isset($param['min'])) { 1041 $newdep = $param; 1042 } 1043 } 1044 if (isset($newdep)) { 1045 if (!isset($newdep['min'])) { 1046 $newdep['min'] = '0'; 1047 } 1048 if (!isset($newdep['max'])) { 1049 $newdep['max'] = '100000000000000000000'; 1050 } 1051 // use magic to support pecl packages suddenly jumping to the pecl channel 1052 // we need to support both dependency possibilities 1053 if ($channel == 'pear.php.net' && $this->getChannel() == 'pecl.php.net') { 1054 if ($package == $this->getPackage()) { 1055 $channel = 'pecl.php.net'; 1056 } 1057 } 1058 if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') { 1059 if ($package == $this->getPackage()) { 1060 $channel = 'pear.php.net'; 1061 } 1062 } 1063 return (strtolower($package) == strtolower($this->getPackage()) && 1064 $channel == $this->getChannel() && 1065 version_compare($newdep['min'], $this->getVersion(), '<=') && 1066 version_compare($newdep['max'], $this->getVersion(), '>=')); 1067 } 1068 // use magic to support pecl packages suddenly jumping to the pecl channel 1069 if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') { 1070 if (strtolower($package) == strtolower($this->getPackage())) { 1071 $channel = 'pear.php.net'; 1072 } 1073 } 1074 if (isset($param['version'])) { 1075 return (strtolower($package) == strtolower($this->getPackage()) && 1076 $channel == $this->getChannel() && 1077 $param['version'] == $this->getVersion()); 1078 } else { 1079 return strtolower($package) == strtolower($this->getPackage()) && 1080 $channel == $this->getChannel(); 1081 } 1082 } 1083 1084 function isInstalled($dep, $oper = '==') 1085 { 1086 if (!$dep) { 1087 return false; 1088 } 1089 if ($oper != 'ge' && $oper != 'gt' && $oper != 'has' && $oper != '==') { 1090 return false; 1091 } 1092 if (is_object($dep)) { 1093 $package = $dep->getPackage(); 1094 $channel = $dep->getChannel(); 1095 if ($dep->getURI()) { 1096 $dep = array( 1097 'uri' => $dep->getURI(), 1098 'version' => $dep->getVersion(), 1099 ); 1100 } else { 1101 $dep = array( 1102 'version' => $dep->getVersion(), 1103 ); 1104 } 1105 } else { 1106 if (isset($dep['uri'])) { 1107 $channel = '__uri'; 1108 $package = $dep['dep']['name']; 1109 } else { 1110 $channel = $dep['info']->getChannel(); 1111 $package = $dep['info']->getPackage(); 1112 } 1113 } 1114 $options = $this->_downloader->getOptions(); 1115 $test = $this->_installRegistry->packageExists($package, $channel); 1116 if (!$test && $channel == 'pecl.php.net') { 1117 // do magic to allow upgrading from old pecl packages to new ones 1118 $test = $this->_installRegistry->packageExists($package, 'pear.php.net'); 1119 $channel = 'pear.php.net'; 1120 } 1121 if ($test) { 1122 if (isset($dep['uri'])) { 1123 if ($this->_installRegistry->packageInfo($package, 'uri', '__uri') == $dep['uri']) { 1124 return true; 1125 } 1126 } 1127 if (isset($options['upgrade'])) { 1128 if ($oper == 'has') { 1129 if (version_compare($this->_installRegistry->packageInfo( 1130 $package, 'version', $channel), 1131 $dep['version'], '>=')) { 1132 return true; 1133 } else { 1134 return false; 1135 } 1136 } else { 1137 if (version_compare($this->_installRegistry->packageInfo( 1138 $package, 'version', $channel), 1139 $dep['version'], '>=')) { 1140 return true; 1141 } 1142 return false; 1143 } 1144 } 1145 return true; 1146 } 1147 return false; 1148 } 1149 1150 /** 1151 * @param array 1152 * @param bool ignore install groups - for final removal of dupe packages 1153 * @static 1154 */ 1155 function removeDuplicates(&$params, $ignoreGroups = false) 1156 { 1157 $pnames = array(); 1158 foreach ($params as $i => $param) { 1159 if (!$param) { 1160 continue; 1161 } 1162 if ($param->getPackage()) { 1163 if ($ignoreGroups) { 1164 $group = ''; 1165 } else { 1166 $group = $param->getGroup(); 1167 } 1168 $pnames[$i] = $param->getChannel() . '/' . 1169 $param->getPackage() . '-' . $param->getVersion() . '#' . $group; 1170 } 1171 } 1172 $pnames = array_unique($pnames); 1173 $unset = array_diff(array_keys($params), array_keys($pnames)); 1174 $testp = array_flip($pnames); 1175 foreach ($params as $i => $param) { 1176 if (!$param) { 1177 $unset[] = $i; 1178 continue; 1179 } 1180 if (!is_a($param, 'PEAR_Downloader_Package')) { 1181 $unset[] = $i; 1182 continue; 1183 } 1184 if ($ignoreGroups) { 1185 $group = ''; 1186 } else { 1187 $group = $param->getGroup(); 1188 } 1189 if (!isset($testp[$param->getChannel() . '/' . $param->getPackage() . '-' . 1190 $param->getVersion() . '#' . $group])) { 1191 $unset[] = $i; 1192 } 1193 } 1194 foreach ($unset as $i) { 1195 unset($params[$i]); 1196 } 1197 $ret = array(); 1198 foreach ($params as $i => $param) { 1199 $ret[] = &$params[$i]; 1200 } 1201 $params = array(); 1202 foreach ($ret as $i => $param) { 1203 $params[] = &$ret[$i]; 1204 } 1205 } 1206 1207 function explicitState() 1208 { 1209 return $this->_explicitState; 1210 } 1211 1212 function setExplicitState($s) 1213 { 1214 $this->_explicitState = $s; 1215 } 1216 1217 /** 1218 * @static 1219 */ 1220 function mergeDependencies(&$params) 1221 { 1222 $newparams = array(); 1223 $bundles = array(); 1224 foreach ($params as $i => $param) { 1225 if (!$param->isBundle()) { 1226 continue; 1227 } 1228 $bundles[] = $i; 1229 $pf = &$param->getPackageFile(); 1230 $newdeps = array(); 1231 $contents = $pf->getBundledPackages(); 1232 if (!is_array($contents)) { 1233 $contents = array($contents); 1234 } 1235 foreach ($contents as $file) { 1236 $filecontents = $pf->getFileContents($file); 1237 $dl = &$param->getDownloader(); 1238 $options = $dl->getOptions(); 1239 if (PEAR::isError($dir = $dl->getDownloadDir())) { 1240 return $dir; 1241 } 1242 $fp = @fopen($dir . DIRECTORY_SEPARATOR . $file, 'wb'); 1243 if (!$fp) { 1244 continue; 1245 } 1246 fwrite($fp, $filecontents, strlen($filecontents)); 1247 fclose($fp); 1248 if ($s = $params[$i]->explicitState()) { 1249 $obj->setExplicitState($s); 1250 } 1251 $obj = &new PEAR_Downloader_Package($params[$i]->getDownloader()); 1252 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 1253 if (PEAR::isError($dir = $dl->getDownloadDir())) { 1254 PEAR::popErrorHandling(); 1255 return $dir; 1256 } 1257 $e = $obj->_fromFile($a = $dir . DIRECTORY_SEPARATOR . $file); 1258 PEAR::popErrorHandling(); 1259 if (PEAR::isError($e)) { 1260 if (!isset($options['soft'])) { 1261 $dl->log(0, $e->getMessage()); 1262 } 1263 continue; 1264 } 1265 $j = &$obj; 1266 if (!PEAR_Downloader_Package::willDownload($j, 1267 array_merge($params, $newparams)) && !$param->isInstalled($j)) { 1268 $newparams[] = &$j; 1269 } 1270 } 1271 } 1272 foreach ($bundles as $i) { 1273 unset($params[$i]); // remove bundles - only their contents matter for installation 1274 } 1275 PEAR_Downloader_Package::removeDuplicates($params); // strip any unset indices 1276 if (count($newparams)) { // add in bundled packages for install 1277 foreach ($newparams as $i => $unused) { 1278 $params[] = &$newparams[$i]; 1279 } 1280 $newparams = array(); 1281 } 1282 foreach ($params as $i => $param) { 1283 $newdeps = array(); 1284 foreach ($param->_downloadDeps as $dep) { 1285 if (!PEAR_Downloader_Package::willDownload($dep, 1286 array_merge($params, $newparams)) && !$param->isInstalled($dep)) { 1287 $newdeps[] = $dep; 1288 } else { 1289 // detect versioning conflicts here 1290 } 1291 } 1292 // convert the dependencies into PEAR_Downloader_Package objects for the next time 1293 // around 1294 $params[$i]->_downloadDeps = array(); 1295 foreach ($newdeps as $dep) { 1296 $obj = &new PEAR_Downloader_Package($params[$i]->getDownloader()); 1297 if ($s = $params[$i]->explicitState()) { 1298 $obj->setExplicitState($s); 1299 } 1300 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 1301 $e = $obj->fromDepURL($dep); 1302 PEAR::popErrorHandling(); 1303 if (PEAR::isError($e)) { 1304 if (!isset($options['soft'])) { 1305 $obj->_downloader->log(0, $e->getMessage()); 1306 } 1307 continue; 1308 } 1309 $e = $obj->detectDependencies($params); 1310 if (PEAR::isError($e)) { 1311 if (!isset($options['soft'])) { 1312 $obj->_downloader->log(0, $e->getMessage()); 1313 } 1314 } 1315 $j = &$obj; 1316 $newparams[] = &$j; 1317 } 1318 } 1319 if (count($newparams)) { 1320 foreach ($newparams as $i => $unused) { 1321 $params[] = &$newparams[$i]; 1322 } 1323 return true; 1324 } else { 1325 return false; 1326 } 1327 } 1328 1329 1330 /** 1331 * @static 1332 */ 1333 function willDownload($param, $params) 1334 { 1335 if (!is_array($params)) { 1336 return false; 1337 } 1338 foreach ($params as $obj) { 1339 if ($obj->isEqual($param)) { 1340 return true; 1341 } 1342 } 1343 return false; 1344 } 1345 1346 /** 1347 * For simpler unit-testing 1348 * @param PEAR_Config 1349 * @param int 1350 * @param string 1351 */ 1352 function &getPackagefileObject(&$c, $d, $t = false) 1353 { 1354 $a = &new PEAR_PackageFile($c, $d, $t); 1355 return $a; 1356 } 1357 1358 1359 /** 1360 * This will retrieve from a local file if possible, and parse out 1361 * a group name as well. The original parameter will be modified to reflect this. 1362 * @param string|array can be a parsed package name as well 1363 * @access private 1364 */ 1365 function _fromFile(&$param) 1366 { 1367 $saveparam = $param; 1368 if (is_string($param)) { 1369 if (!@file_exists($param)) { 1370 $test = explode('#', $param); 1371 $group = array_pop($test); 1372 if (file_exists(implode('#', $test))) { 1373 $this->setGroup($group); 1374 $param = implode('#', $test); 1375 $this->_explicitGroup = true; 1376 } 1377 } 1378 if (@is_file($param)) { 1379 $this->_type = 'local'; 1380 $options = $this->_downloader->getOptions(); 1381 if (isset($options['downloadonly'])) { 1382 $pkg = &$this->getPackagefileObject($this->_config, 1383 $this->_downloader->_debug); 1384 } else { 1385 if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) { 1386 return $dir; 1387 } 1388 $pkg = &$this->getPackagefileObject($this->_config, 1389 $this->_downloader->_debug, $dir); 1390 } 1391 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 1392 $pf = &$pkg->fromAnyFile($param, PEAR_VALIDATE_INSTALLING); 1393 PEAR::popErrorHandling(); 1394 if (PEAR::isError($pf)) { 1395 $this->_valid = false; 1396 $param = $saveparam; 1397 return $pf; 1398 } 1399 $this->_packagefile = &$pf; 1400 if (!$this->getGroup()) { 1401 $this->setGroup('default'); // install the default dependency group 1402 } 1403 return $this->_valid = true; 1404 } 1405 } 1406 $param = $saveparam; 1407 return $this->_valid = false; 1408 } 1409 1410 function _fromUrl($param, $saveparam = '') 1411 { 1412 if (!is_array($param) && 1413 (preg_match('#^(http|ftp)://#', $param))) { 1414 $options = $this->_downloader->getOptions(); 1415 $this->_type = 'url'; 1416 $callback = $this->_downloader->ui ? 1417 array(&$this->_downloader, '_downloadCallback') : null; 1418 $this->_downloader->pushErrorHandling(PEAR_ERROR_RETURN); 1419 if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) { 1420 $this->_downloader->popErrorHandling(); 1421 return $dir; 1422 } 1423 $file = $this->_downloader->downloadHttp($param, $this->_downloader->ui, 1424 $dir, $callback); 1425 $this->_downloader->popErrorHandling(); 1426 if (PEAR::isError($file)) { 1427 if (!empty($saveparam)) { 1428 $saveparam = ", cannot download \"$saveparam\""; 1429 } 1430 $err = PEAR::raiseError('Could not download from "' . $param . 1431 '"' . $saveparam . ' (' . $file->getMessage() . ')'); 1432 return $err; 1433 } 1434 if ($this->_rawpackagefile) { 1435 require_once 'Archive/Tar.php'; 1436 $tar = &new Archive_Tar($file); 1437 $packagexml = $tar->extractInString('package2.xml'); 1438 if (!$packagexml) { 1439 $packagexml = $tar->extractInString('package.xml'); 1440 } 1441 if (str_replace(array("\n", "\r"), array('',''), $packagexml) != 1442 str_replace(array("\n", "\r"), array('',''), $this->_rawpackagefile)) { 1443 if ($this->getChannel() == 'pear.php.net') { 1444 // be more lax for the existing PEAR packages that have not-ok 1445 // characters in their package.xml 1446 $this->_downloader->log(0, 'CRITICAL WARNING: The "' . 1447 $this->getPackage() . '" package has invalid characters in its ' . 1448 'package.xml. The next version of PEAR may not be able to install ' . 1449 'this package for security reasons. Please open a bug report at ' . 1450 'http://pear.php.net/package/' . $this->getPackage() . '/bugs'); 1451 } else { 1452 return PEAR::raiseError('CRITICAL ERROR: package.xml downloaded does ' . 1453 'not match value returned from xml-rpc'); 1454 } 1455 } 1456 } 1457 // whew, download worked! 1458 if (isset($options['downloadonly'])) { 1459 $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->debug); 1460 } else { 1461 if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) { 1462 return $dir; 1463 } 1464 $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->debug, 1465 $dir); 1466 } 1467 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 1468 $pf = &$pkg->fromAnyFile($file, PEAR_VALIDATE_INSTALLING); 1469 PEAR::popErrorHandling(); 1470 if (PEAR::isError($pf)) { 1471 if (is_array($pf->getUserInfo())) { 1472 foreach ($pf->getUserInfo() as $err) { 1473 if (is_array($err)) { 1474 $err = $err['message']; 1475 } 1476 if (!isset($options['soft'])) { 1477 $this->_downloader->log(0, "Validation Error: $err"); 1478 } 1479 } 1480 } 1481 if (!isset($options['soft'])) { 1482 $this->_downloader->log(0, $pf->getMessage()); 1483 } 1484 $err = PEAR::raiseError('Download of "' . ($saveparam ? $saveparam : 1485 $param) . '" succeeded, but it is not a valid package archive'); 1486 $this->_valid = false; 1487 return $err; 1488 } 1489 $this->_packagefile = &$pf; 1490 $this->setGroup('default'); // install the default dependency group 1491 return $this->_valid = true; 1492 } 1493 return $this->_valid = false; 1494 } 1495 1496 /** 1497 * 1498 * @param string|array pass in an array of format 1499 * array( 1500 * 'package' => 'pname', 1501 * ['channel' => 'channame',] 1502 * ['version' => 'version',] 1503 * ['state' => 'state',]) 1504 * or a string of format [channame/]pname[-version|-state] 1505 */ 1506 function _fromString($param) 1507 { 1508 $options = $this->_downloader->getOptions(); 1509 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 1510 $pname = $this->_registry->parsePackageName($param, 1511 $this->_config->get('default_channel')); 1512 PEAR::popErrorHandling(); 1513 if (PEAR::isError($pname)) { 1514 if ($pname->getCode() == 'invalid') { 1515 $this->_valid = false; 1516 return false; 1517 } 1518 if ($pname->getCode() == 'channel') { 1519 $parsed = $pname->getUserInfo(); 1520 if ($this->_downloader->discover($parsed['channel'])) { 1521 if ($this->_config->get('auto_discover')) { 1522 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 1523 $pname = $this->_registry->parsePackageName($param, 1524 $this->_config->get('default_channel')); 1525 PEAR::popErrorHandling(); 1526 } else { 1527 if (!isset($options['soft'])) { 1528 $this->_downloader->log(0, 'Channel "' . $parsed['channel'] . 1529 '" is not initialized, use ' . 1530 '"pear channel-discover ' . $parsed['channel'] . '" to initialize' . 1531 'or pear config-set auto_discover 1'); 1532 } 1533 } 1534 } 1535 if (PEAR::isError($pname)) { 1536 if (!isset($options['soft'])) { 1537 $this->_downloader->log(0, $pname->getMessage()); 1538 } 1539 if (is_array($param)) { 1540 $param = $this->_registry->parsedPackageNameToString($param); 1541 } 1542 $err = PEAR::raiseError('invalid package name/package file "' . 1543 $param . '"'); 1544 $this->_valid = false; 1545 return $err; 1546 } 1547 } else { 1548 if (!isset($options['soft'])) { 1549 $this->_downloader->log(0, $pname->getMessage()); 1550 } 1551 $err = PEAR::raiseError('invalid package name/package file "' . 1552 $param . '"'); 1553 $this->_valid = false; 1554 return $err; 1555 } 1556 } 1557 if (!isset($this->_type)) { 1558 $this->_type = 'xmlrpc'; 1559 } 1560 $this->_parsedname = $pname; 1561 if (isset($pname['state'])) { 1562 $this->_explicitState = $pname['state']; 1563 } else { 1564 $this->_explicitState = false; 1565 } 1566 if (isset($pname['group'])) { 1567 $this->_explicitGroup = true; 1568 } else { 1569 $this->_explicitGroup = false; 1570 } 1571 $info = $this->_downloader->_getPackageDownloadUrl($pname); 1572 if (PEAR::isError($info)) { 1573 if ($info->getCode() != -976 && $pname['channel'] == 'pear.php.net') { 1574 // try pecl 1575 $pname['channel'] = 'pecl.php.net'; 1576 if ($test = $this->_downloader->_getPackageDownloadUrl($pname)) { 1577 if (!PEAR::isError($test)) { 1578 $info = PEAR::raiseError($info->getMessage() . ' - package ' . 1579 $this->_registry->parsedPackageNameToString($pname, true) . 1580 ' can be installed with "pecl install ' . $pname['package'] . 1581 '"'); 1582 } else { 1583 $pname['channel'] = 'pear.php.net'; 1584 } 1585 } else { 1586 $pname['channel'] = 'pear.php.net'; 1587 } 1588 } 1589 return $info; 1590 } 1591 $this->_rawpackagefile = $info['raw']; 1592 $ret = $this->_analyzeDownloadURL($info, $param, $pname); 1593 if (PEAR::isError($ret)) { 1594 return $ret; 1595 } 1596 if ($ret) { 1597 $this->_downloadURL = $ret; 1598 return $this->_valid = (bool) $ret; 1599 } 1600 } 1601 1602 /** 1603 * @param array output of package.getDownloadURL 1604 * @param string|array|object information for detecting packages to be downloaded, and 1605 * for errors 1606 * @param array name information of the package 1607 * @param array|null packages to be downloaded 1608 * @param bool is this an optional dependency? 1609 * @param bool is this any kind of dependency? 1610 * @access private 1611 */ 1612 function _analyzeDownloadURL($info, $param, $pname, $params = null, $optional = false, 1613 $isdependency = false) 1614 { 1615 if (!is_string($param) && PEAR_Downloader_Package::willDownload($param, $params)) { 1616 return false; 1617 } 1618 if (!$info) { 1619 if (!is_string($param)) { 1620 $saveparam = ", cannot download \"$param\""; 1621 } else { 1622 $saveparam = ''; 1623 } 1624 // no releases exist 1625 return PEAR::raiseError('No releases for package "' . 1626 $this->_registry->parsedPackageNameToString($pname, true) . '" exist' . $saveparam); 1627 } 1628 if (strtolower($info['info']->getChannel()) != strtolower($pname['channel'])) { 1629 $err = false; 1630 if ($pname['channel'] == 'pecl.php.net') { 1631 if ($info['info']->getChannel() != 'pear.php.net') { 1632 $err = true; 1633 } 1634 } elseif ($info['info']->getChannel() == 'pecl.php.net') { 1635 if ($pname['channel'] != 'pear.php.net') { 1636 $err = true; 1637 } 1638 } else { 1639 $err = true; 1640 } 1641 if ($err) { 1642 return PEAR::raiseError('SECURITY ERROR: package in channel "' . $pname['channel'] . 1643 '" retrieved another channel\'s name for download! ("' . 1644 $info['info']->getChannel() . '")'); 1645 } 1646 } 1647 if (!isset($info['url'])) { 1648 if ($this->isInstalled($info)) { 1649 if ($isdependency && version_compare($info['version'], 1650 $this->_registry->packageInfo($info['info']->getPackage(), 1651 'version', $info['info']->getChannel()), '<=')) { 1652 // ignore bogus errors of "failed to download dependency" 1653 // if it is already installed and the one that would be 1654 // downloaded is older or the same version (Bug #7219) 1655 return false; 1656 } 1657 } 1658 $instead = ', will instead download version ' . $info['version'] . 1659 ', stability "' . $info['info']->getState() . '"'; 1660 // releases exist, but we failed to get any 1661 if (isset($this->_downloader->_options['force'])) { 1662 if (isset($pname['version'])) { 1663 $vs = ', version "' . $pname['version'] . '"'; 1664 } elseif (isset($pname['state'])) { 1665 $vs = ', stability "' . $pname['state'] . '"'; 1666 } elseif ($param == 'dependency') { 1667 if (!class_exists('PEAR_Common')) { 1668 require_once 'PEAR/Common.php'; 1669 } 1670 if (!in_array($info['info']->getState(), 1671 PEAR_Common::betterStates($this->_config->get('preferred_state'), true))) { 1672 if ($optional) { 1673 // don't spit out confusing error message 1674 return $this->_downloader->_getPackageDownloadUrl( 1675 array('package' => $pname['package'], 1676 'channel' => $pname['channel'], 1677 'version' => $info['version'])); 1678 } 1679 $vs = ' within preferred state "' . $this->_config->get('preferred_state') . 1680 '"'; 1681 } else { 1682 if (!class_exists('PEAR_Dependency2')) { 1683 require_once 'PEAR/Dependency2.php'; 1684 } 1685 if ($optional) { 1686 // don't spit out confusing error message 1687 return $this->_downloader->_getPackageDownloadUrl( 1688 array('package' => $pname['package'], 1689 'channel' => $pname['channel'], 1690 'version' => $info['version'])); 1691 } 1692 $vs = PEAR_Dependency2::_getExtraString($pname); 1693 $instead = ''; 1694 } 1695 } else { 1696 $vs = ' within preferred state "' . $this->_config->get( 1697 'preferred_state') . '"'; 1698 } 1699 if (!isset($options['soft'])) { 1700 $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] . 1701 '/' . $pname['package'] . $vs . $instead); 1702 } 1703 // download the latest release 1704 return $this->_downloader->_getPackageDownloadUrl( 1705 array('package' => $pname['package'], 1706 'channel' => $pname['channel'], 1707 'version' => $info['version'])); 1708 } else { 1709 // construct helpful error message 1710 if (isset($pname['version'])) { 1711 $vs = ', version "' . $pname['version'] . '"'; 1712 } elseif (isset($pname['state'])) { 1713 $vs = ', stability "' . $pname['state'] . '"'; 1714 } elseif ($param == 'dependency') { 1715 if (!class_exists('PEAR_Common')) { 1716 require_once 'PEAR/Common.php'; 1717 } 1718 if (!in_array($info['info']->getState(), 1719 PEAR_Common::betterStates($this->_config->get('preferred_state'), true))) { 1720 if ($optional) { 1721 // don't spit out confusing error message, and don't die on 1722 // optional dep failure! 1723 return $this->_downloader->_getPackageDownloadUrl( 1724 array('package' => $pname['package'], 1725 'channel' => $pname['channel'], 1726 'version' => $info['version'])); 1727 } 1728 $vs = ' within preferred state "' . $this->_config->get('preferred_state') . 1729 '"'; 1730 } else { 1731 if (!class_exists('PEAR_Dependency2')) { 1732 require_once 'PEAR/Dependency2.php'; 1733 } 1734 if ($optional) { 1735 // don't spit out confusing error message, and don't die on 1736 // optional dep failure! 1737 return $this->_downloader->_getPackageDownloadUrl( 1738 array('package' => $pname['package'], 1739 'channel' => $pname['channel'], 1740 'version' => $info['version'])); 1741 } 1742 $vs = PEAR_Dependency2::_getExtraString($pname); 1743 } 1744 } else { 1745 $vs = ' within preferred state "' . $this->_downloader->config->get( 1746 'preferred_state') . '"'; 1747 } 1748 $options = $this->_downloader->getOptions(); 1749 // this is only set by the "download-all" command 1750 if (isset($options['ignorepreferred_state'])) { 1751 $err = PEAR::raiseError( 1752 'Failed to download ' . $this->_registry->parsedPackageNameToString( 1753 array('channel' => $pname['channel'], 'package' => $pname['package']), 1754 true) 1755 . $vs . 1756 ', latest release is version ' . $info['version'] . 1757 ', stability "' . $info['info']->getState() . '", use "' . 1758 $this->_registry->parsedPackageNameToString( 1759 array('channel' => $pname['channel'], 'package' => $pname['package'], 1760 'version' => $info['version'])) . '" to install', 1761 PEAR_DOWNLOADER_PACKAGE_STATE); 1762 return $err; 1763 } 1764 $err = PEAR::raiseError( 1765 'Failed to download ' . $this->_registry->parsedPackageNameToString( 1766 array('channel' => $pname['channel'], 'package' => $pname['package']), 1767 true) 1768 . $vs . 1769 ', latest release is version ' . $info['version'] . 1770 ', stability "' . $info['info']->getState() . '", use "' . 1771 $this->_registry->parsedPackageNameToString( 1772 array('channel' => $pname['channel'], 'package' => $pname['package'], 1773 'version' => $info['version'])) . '" to install'); 1774 return $err; 1775 } 1776 } 1777 if (isset($info['deprecated']) && $info['deprecated']) { 1778 $this->_downloader->log(0, 1779 'WARNING: "' . 1780 $this->_registry->parsedPackageNameToString( 1781 array('channel' => $info['info']->getChannel(), 1782 'package' => $info['info']->getPackage()), true) . 1783 '" is deprecated in favor of "' . 1784 $this->_registry->parsedPackageNameToString($info['deprecated'], true) . 1785 '"'); 1786 } 1787 return $info; 1788 } 1789 } 1790 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 14:08:00 2007 | par Balluche grâce à PHPXref 0.7 |