| [ Index ] |
|
Code source de GeekLog 1.4.1 |
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.91.2.1 2006/05/25 22:00:05 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.4.11 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 if (@$skipnames[count($skipnames) - 1] == 457 $this->_registry->parsedPackageNameToString($dep, true)) { 458 array_pop($skipnames); 459 } 460 } 461 if (!$skip && is_array($ret)) { 462 $this->_downloadDeps[] = $ret; 463 } 464 } 465 if (count($skipnames)) { 466 if (!isset($options['soft'])) { 467 $this->_downloader->log(1, 'Did not download optional dependencies: ' . 468 implode(', ', $skipnames) . 469 ', use --alldeps to download automatically'); 470 } 471 } 472 } 473 // get requested dependency group, if any 474 $groupname = $this->getGroup(); 475 $explicit = $this->_explicitGroup; 476 if (!$groupname) { 477 if ($this->canDefault()) { 478 $groupname = 'default'; // try the default dependency group 479 } else { 480 continue; 481 } 482 } 483 if ($groupnotfound) { 484 continue; 485 } 486 if (isset($deps['group'])) { 487 if (isset($deps['group']['attribs'])) { 488 if (strtolower($deps['group']['attribs']['name']) == strtolower($groupname)) { 489 $group = $deps['group']; 490 } elseif ($explicit) { 491 if (!isset($options['soft'])) { 492 $this->_downloader->log(0, 'Warning: package "' . 493 $this->_registry->parsedPackageNameToString($pname, true) . 494 '" has no dependency ' . 'group named "' . $groupname . '"'); 495 } 496 $groupnotfound = true; 497 continue; 498 } 499 } else { 500 $found = false; 501 foreach ($deps['group'] as $group) { 502 if (strtolower($group['attribs']['name']) == strtolower($groupname)) { 503 $found = true; 504 break; 505 } 506 } 507 if (!$found) { 508 if ($explicit) { 509 if (!isset($options['soft'])) { 510 $this->_downloader->log(0, 'Warning: package "' . 511 $this->_registry->parsedPackageNameToString($pname, true) . 512 '" has no dependency ' . 'group named "' . $groupname . '"'); 513 } 514 } 515 $groupnotfound = true; 516 continue; 517 } 518 } 519 } 520 if (isset($group)) { 521 if (isset($group[$packagetype])) { 522 if (isset($group[$packagetype][0])) { 523 foreach ($group[$packagetype] as $dep) { 524 $ret = $this->_detect2Dep($dep, $pname, 'dependency group "' . 525 $group['attribs']['name'] . '"', $params); 526 if (is_array($ret)) { 527 $this->_downloadDeps[] = $ret; 528 } 529 } 530 } else { 531 $ret = $this->_detect2Dep($group[$packagetype], $pname, 532 'dependency group "' . 533 $group['attribs']['name'] . '"', $params); 534 if (is_array($ret)) { 535 $this->_downloadDeps[] = $ret; 536 } 537 } 538 } 539 } 540 } 541 } 542 543 function _detect2Dep($dep, $pname, $group, $params) 544 { 545 if (isset($dep['conflicts'])) { 546 return true; 547 } 548 $options = $this->_downloader->getOptions(); 549 if (isset($dep['uri'])) { 550 return array('uri' => $dep['uri'], 'dep' => $dep);; 551 } 552 $testdep = $dep; 553 $testdep['package'] = $dep['name']; 554 if (PEAR_Downloader_Package::willDownload($testdep, $params)) { 555 $dep['package'] = $dep['name']; 556 if (!isset($options['soft'])) { 557 $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group . 558 ' dependency "' . 559 $this->_registry->parsedPackageNameToString($dep, true) . 560 '", will be installed'); 561 } 562 return false; 563 } 564 $options = $this->_downloader->getOptions(); 565 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 566 if ($this->_explicitState) { 567 $pname['state'] = $this->_explicitState; 568 } 569 $url = 570 $this->_downloader->_getDepPackageDownloadUrl($dep, $pname); 571 if (PEAR::isError($url)) { 572 PEAR::popErrorHandling(); 573 return $url; 574 } 575 $dep['package'] = $dep['name']; 576 $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, $group == 'optional' && 577 !isset($options['alldeps'])); 578 PEAR::popErrorHandling(); 579 if (PEAR::isError($ret)) { 580 if (!isset($options['soft'])) { 581 $this->_downloader->log(0, $ret->getMessage()); 582 } 583 return false; 584 } else { 585 // check to see if a dep is already installed and is the same or newer 586 if (!isset($dep['min']) && !isset($dep['max']) && !isset($dep['recommended'])) { 587 $oper = 'has'; 588 } else { 589 $oper = 'gt'; 590 } 591 // do not try to move this before getDepPackageDownloadURL 592 // we can't determine whether upgrade is necessary until we know what 593 // version would be downloaded 594 if (!isset($options['force']) && $this->isInstalled($ret, $oper)) { 595 $version = $this->_installRegistry->packageInfo($dep['name'], 'version', 596 $dep['channel']); 597 $dep['package'] = $dep['name']; 598 if (!isset($options['soft'])) { 599 $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group . 600 ' dependency "' . 601 $this->_registry->parsedPackageNameToString($dep, true) . 602 '" version ' . $url['version'] . ', already installed as version ' . 603 $version); 604 } 605 return false; 606 } 607 } 608 if (isset($dep['nodefault'])) { 609 $ret['nodefault'] = true; 610 } 611 return $ret; 612 } 613 614 function _detect1($deps, $pname, $options, $params) 615 { 616 $this->_downloadDeps = array(); 617 $skipnames = array(); 618 foreach ($deps as $dep) { 619 $nodownload = false; 620 if ($dep['type'] == 'pkg') { 621 $dep['channel'] = 'pear.php.net'; 622 $dep['package'] = $dep['name']; 623 switch ($dep['rel']) { 624 case 'not' : 625 continue 2; 626 case 'ge' : 627 case 'eq' : 628 case 'gt' : 629 case 'has' : 630 $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ? 631 'required' : 632 'optional'; 633 if (PEAR_Downloader_Package::willDownload($dep, $params)) { 634 $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group 635 . ' dependency "' . 636 $this->_registry->parsedPackageNameToString($dep, true) . 637 '", will be installed'); 638 continue 2; 639 } 640 $fakedp = new PEAR_PackageFile_v1; 641 $fakedp->setPackage($dep['name']); 642 // skip internet check if we are not upgrading (bug #5810) 643 if (!isset($options['upgrade']) && $this->isInstalled( 644 $fakedp, $dep['rel'])) { 645 $this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group 646 . ' dependency "' . 647 $this->_registry->parsedPackageNameToString($dep, true) . 648 '", is already installed'); 649 continue 2; 650 } 651 } 652 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 653 if ($this->_explicitState) { 654 $pname['state'] = $this->_explicitState; 655 } 656 $url = 657 $this->_downloader->_getDepPackageDownloadUrl($dep, $pname); 658 $chan = 'pear.php.net'; 659 if (PEAR::isError($url)) { 660 // check to see if this is a pecl package that has jumped 661 // from pear.php.net to pecl.php.net channel 662 if (!class_exists('PEAR_Dependency2')) { 663 require_once 'PEAR/Dependency2.php'; 664 } 665 $newdep = PEAR_Dependency2::normalizeDep($dep); 666 $newdep = $newdep[0]; 667 $newdep['channel'] = 'pecl.php.net'; 668 $chan = 'pecl.php.net'; 669 $url = 670 $this->_downloader->_getDepPackageDownloadUrl($newdep, $pname); 671 $obj = &$this->_installRegistry->getPackage($dep['name']); 672 if (PEAR::isError($url)) { 673 PEAR::popErrorHandling(); 674 if ($obj !== null && $this->isInstalled($obj, $dep['rel'])) { 675 $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ? 676 'required' : 677 'optional'; 678 $dep['package'] = $dep['name']; 679 if (!isset($options['soft'])) { 680 $this->_downloader->log(3, $this->getShortName() . 681 ': Skipping ' . $group . ' dependency "' . 682 $this->_registry->parsedPackageNameToString($dep, true) . 683 '", already installed as version ' . $obj->getVersion()); 684 } 685 if (@$skipnames[count($skipnames) - 1] == 686 $this->_registry->parsedPackageNameToString($dep, true)) { 687 array_pop($skipnames); 688 } 689 continue; 690 } else { 691 if (isset($dep['optional']) && $dep['optional'] == 'yes') { 692 $this->_downloader->log(2, $this->getShortName() . 693 ': Skipping ' . $group 694 . ' dependency "' . 695 $this->_registry->parsedPackageNameToString($dep, true) . 696 '", no releases exist'); 697 continue; 698 } else { 699 return $url; 700 } 701 } 702 } 703 } 704 PEAR::popErrorHandling(); 705 if (!isset($options['alldeps'])) { 706 if (isset($dep['optional']) && $dep['optional'] == 'yes') { 707 if (!isset($options['soft'])) { 708 $this->_downloader->log(3, 'Notice: package "' . 709 $this->getShortName() . 710 '" optional dependency "' . 711 $this->_registry->parsedPackageNameToString( 712 array('channel' => $chan, 'package' => 713 $dep['name']), true) . 714 '" will not be automatically downloaded'); 715 } 716 $skipnames[] = $this->_registry->parsedPackageNameToString( 717 array('channel' => $chan, 'package' => 718 $dep['name']), true); 719 $nodownload = true; 720 } 721 } 722 if (!isset($options['alldeps']) && !isset($options['onlyreqdeps'])) { 723 if (!isset($dep['optional']) || $dep['optional'] == 'no') { 724 if (!isset($options['soft'])) { 725 $this->_downloader->log(3, 'Notice: package "' . 726 $this->getShortName() . 727 '" required dependency "' . 728 $this->_registry->parsedPackageNameToString( 729 array('channel' => $chan, 'package' => 730 $dep['name']), true) . 731 '" will not be automatically downloaded'); 732 } 733 $skipnames[] = $this->_registry->parsedPackageNameToString( 734 array('channel' => $chan, 'package' => 735 $dep['name']), true); 736 $nodownload = true; 737 } 738 } 739 // check to see if a dep is already installed 740 // do not try to move this before getDepPackageDownloadURL 741 // we can't determine whether upgrade is necessary until we know what 742 // version would be downloaded 743 if (!isset($options['force']) && $this->isInstalled( 744 $url, $dep['rel'])) { 745 $group = (!isset($dep['optional']) || $dep['optional'] == 'no') ? 746 'required' : 747 'optional'; 748 $dep['package'] = $dep['name']; 749 if (isset($newdep)) { 750 $version = $this->_installRegistry->packageInfo($newdep['name'], 'version', 751 $newdep['channel']); 752 } else { 753 $version = $this->_installRegistry->packageInfo($dep['name'], 'version'); 754 } 755 $dep['version'] = $url['version']; 756 if (!isset($options['soft'])) { 757 $this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group . 758 ' dependency "' . 759 $this->_registry->parsedPackageNameToString($dep, true) . 760 '", already installed as version ' . $version); 761 } 762 if (@$skipnames[count($skipnames) - 1] == 763 $this->_registry->parsedPackageNameToString($dep, true)) { 764 array_pop($skipnames); 765 } 766 continue; 767 } 768 if ($nodownload) { 769 continue; 770 } 771 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 772 if (isset($newdep)) { 773 $dep = $newdep; 774 } 775 $dep['package'] = $dep['name']; 776 $ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, 777 isset($dep['optional']) && $dep['optional'] == 'yes' && 778 !isset($options['alldeps'])); 779 PEAR::popErrorHandling(); 780 if (PEAR::isError($ret)) { 781 if (!isset($options['soft'])) { 782 $this->_downloader->log(0, $ret->getMessage()); 783 } 784 continue; 785 } 786 $this->_downloadDeps[] = $ret; 787 } 788 } 789 if (count($skipnames)) { 790 if (!isset($options['soft'])) { 791 $this->_downloader->log(1, 'Did not download dependencies: ' . 792 implode(', ', $skipnames) . 793 ', use --alldeps or --onlyreqdeps to download automatically'); 794 } 795 } 796 } 797 798 function setDownloadURL($pkg) 799 { 800 $this->_downloadURL = $pkg; 801 } 802 803 /** 804 * Set the package.xml object for this downloaded package 805 * 806 * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 $pkg 807 */ 808 function setPackageFile(&$pkg) 809 { 810 $this->_packagefile = &$pkg; 811 } 812 813 function getShortName() 814 { 815 return $this->_registry->parsedPackageNameToString(array('channel' => $this->getChannel(), 816 'package' => $this->getPackage()), true); 817 } 818 819 function getParsedPackage() 820 { 821 if (isset($this->_packagefile) || isset($this->_parsedname)) { 822 return array('channel' => $this->getChannel(), 823 'package' => $this->getPackage(), 824 'version' => $this->getVersion()); 825 } 826 return false; 827 } 828 829 function getDownloadURL() 830 { 831 return $this->_downloadURL; 832 } 833 834 function canDefault() 835 { 836 if (isset($this->_downloadURL)) { 837 if (isset($this->_downloadURL['nodefault'])) { 838 return false; 839 } 840 } 841 return true; 842 } 843 844 function getPackage() 845 { 846 if (isset($this->_packagefile)) { 847 return $this->_packagefile->getPackage(); 848 } elseif (isset($this->_downloadURL['info'])) { 849 return $this->_downloadURL['info']->getPackage(); 850 } else { 851 return false; 852 } 853 } 854 855 /** 856 * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 857 */ 858 function isSubpackage(&$pf) 859 { 860 if (isset($this->_packagefile)) { 861 return $this->_packagefile->isSubpackage($pf); 862 } elseif (isset($this->_downloadURL['info'])) { 863 return $this->_downloadURL['info']->isSubpackage($pf); 864 } else { 865 return false; 866 } 867 } 868 869 function getPackageType() 870 { 871 if (isset($this->_packagefile)) { 872 return $this->_packagefile->getPackageType(); 873 } elseif (isset($this->_downloadURL['info'])) { 874 return $this->_downloadURL['info']->getPackageType(); 875 } else { 876 return false; 877 } 878 } 879 880 function isBundle() 881 { 882 if (isset($this->_packagefile)) { 883 return $this->_packagefile->getPackageType() == 'bundle'; 884 } else { 885 return false; 886 } 887 } 888 889 function getPackageXmlVersion() 890 { 891 if (isset($this->_packagefile)) { 892 return $this->_packagefile->getPackagexmlVersion(); 893 } elseif (isset($this->_downloadURL['info'])) { 894 return $this->_downloadURL['info']->getPackagexmlVersion(); 895 } else { 896 return '1.0'; 897 } 898 } 899 900 function getChannel() 901 { 902 if (isset($this->_packagefile)) { 903 return $this->_packagefile->getChannel(); 904 } elseif (isset($this->_downloadURL['info'])) { 905 return $this->_downloadURL['info']->getChannel(); 906 } else { 907 return false; 908 } 909 } 910 911 function getURI() 912 { 913 if (isset($this->_packagefile)) { 914 return $this->_packagefile->getURI(); 915 } elseif (isset($this->_downloadURL['info'])) { 916 return $this->_downloadURL['info']->getURI(); 917 } else { 918 return false; 919 } 920 } 921 922 function getVersion() 923 { 924 if (isset($this->_packagefile)) { 925 return $this->_packagefile->getVersion(); 926 } elseif (isset($this->_downloadURL['version'])) { 927 return $this->_downloadURL['version']; 928 } else { 929 return false; 930 } 931 } 932 933 function isCompatible($pf) 934 { 935 if (isset($this->_packagefile)) { 936 return $this->_packagefile->isCompatible($pf); 937 } elseif (isset($this->_downloadURL['info'])) { 938 return $this->_downloadURL['info']->isCompatible($pf); 939 } else { 940 return true; 941 } 942 } 943 944 function setGroup($group) 945 { 946 $this->_parsedname['group'] = $group; 947 } 948 949 function getGroup() 950 { 951 if (isset($this->_parsedname['group'])) { 952 return $this->_parsedname['group']; 953 } else { 954 return ''; 955 } 956 } 957 958 function isExtension($name) 959 { 960 if (isset($this->_packagefile)) { 961 return $this->_packagefile->isExtension($name); 962 } elseif (isset($this->_downloadURL['info'])) { 963 return $this->_downloadURL['info']->getProvidesExtension() == $name; 964 } else { 965 return false; 966 } 967 } 968 969 function getDeps() 970 { 971 if (isset($this->_packagefile)) { 972 if ($this->_packagefile->getPackagexmlVersion() == '2.0') { 973 return $this->_packagefile->getDeps(true); 974 } else { 975 return $this->_packagefile->getDeps(); 976 } 977 } elseif (isset($this->_downloadURL['info'])) { 978 if ($this->_downloadURL['info']->getPackagexmlVersion() == '2.0') { 979 return $this->_downloadURL['info']->getDeps(true); 980 } else { 981 return $this->_downloadURL['info']->getDeps(); 982 } 983 } else { 984 return array(); 985 } 986 } 987 988 /** 989 * @param array Parsed array from {@link PEAR_Registry::parsePackageName()} or a dependency 990 * returned from getDepDownloadURL() 991 */ 992 function isEqual($param) 993 { 994 if (is_object($param)) { 995 $channel = $param->getChannel(); 996 $package = $param->getPackage(); 997 if ($param->getURI()) { 998 $param = array( 999 'channel' => $param->getChannel(), 1000 'package' => $param->getPackage(), 1001 'version' => $param->getVersion(), 1002 'uri' => $param->getURI(), 1003 ); 1004 } else { 1005 $param = array( 1006 'channel' => $param->getChannel(), 1007 'package' => $param->getPackage(), 1008 'version' => $param->getVersion(), 1009 ); 1010 } 1011 } else { 1012 if (isset($param['uri'])) { 1013 if ($this->getChannel() != '__uri') { 1014 return false; 1015 } 1016 return $param['uri'] == $this->getURI(); 1017 } 1018 $package = isset($param['package']) ? $param['package'] : 1019 $param['info']->getPackage(); 1020 $channel = isset($param['channel']) ? $param['channel'] : 1021 $param['info']->getChannel(); 1022 if (isset($param['rel'])) { 1023 if (!class_exists('PEAR_Dependency2')) { 1024 require_once 'PEAR/Dependency2.php'; 1025 } 1026 $newdep = PEAR_Dependency2::normalizeDep($param); 1027 $newdep = $newdep[0]; 1028 } elseif (isset($param['min'])) { 1029 $newdep = $param; 1030 } 1031 } 1032 if (isset($newdep)) { 1033 if (!isset($newdep['min'])) { 1034 $newdep['min'] = '0'; 1035 } 1036 if (!isset($newdep['max'])) { 1037 $newdep['max'] = '100000000000000000000'; 1038 } 1039 // use magic to support pecl packages suddenly jumping to the pecl channel 1040 // we need to support both dependency possibilities 1041 if ($channel == 'pear.php.net' && $this->getChannel() == 'pecl.php.net') { 1042 if ($package == $this->getPackage()) { 1043 $channel = 'pecl.php.net'; 1044 } 1045 } 1046 if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') { 1047 if ($package == $this->getPackage()) { 1048 $channel = 'pear.php.net'; 1049 } 1050 } 1051 return (strtolower($package) == strtolower($this->getPackage()) && 1052 $channel == $this->getChannel() && 1053 version_compare($newdep['min'], $this->getVersion(), '<=') && 1054 version_compare($newdep['max'], $this->getVersion(), '>=')); 1055 } 1056 // use magic to support pecl packages suddenly jumping to the pecl channel 1057 if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') { 1058 if (strtolower($package) == strtolower($this->getPackage())) { 1059 $channel = 'pear.php.net'; 1060 } 1061 } 1062 if (isset($param['version'])) { 1063 return (strtolower($package) == strtolower($this->getPackage()) && 1064 $channel == $this->getChannel() && 1065 $param['version'] == $this->getVersion()); 1066 } else { 1067 return strtolower($package) == strtolower($this->getPackage()) && 1068 $channel == $this->getChannel(); 1069 } 1070 } 1071 1072 function isInstalled($dep, $oper = '==') 1073 { 1074 if (!$dep) { 1075 return false; 1076 } 1077 if ($oper != 'ge' && $oper != 'gt' && $oper != 'has' && $oper != '==') { 1078 return false; 1079 } 1080 if (is_object($dep)) { 1081 $package = $dep->getPackage(); 1082 $channel = $dep->getChannel(); 1083 if ($dep->getURI()) { 1084 $dep = array( 1085 'uri' => $dep->getURI(), 1086 'version' => $dep->getVersion(), 1087 ); 1088 } else { 1089 $dep = array( 1090 'version' => $dep->getVersion(), 1091 ); 1092 } 1093 } else { 1094 if (isset($dep['uri'])) { 1095 $channel = '__uri'; 1096 $package = $dep['dep']['name']; 1097 } else { 1098 $channel = $dep['info']->getChannel(); 1099 $package = $dep['info']->getPackage(); 1100 } 1101 } 1102 $options = $this->_downloader->getOptions(); 1103 $test = $this->_installRegistry->packageExists($package, $channel); 1104 if (!$test && $channel == 'pecl.php.net') { 1105 // do magic to allow upgrading from old pecl packages to new ones 1106 $test = $this->_installRegistry->packageExists($package, 'pear.php.net'); 1107 $channel = 'pear.php.net'; 1108 } 1109 if ($test) { 1110 if (isset($dep['uri'])) { 1111 if ($this->_installRegistry->packageInfo($package, 'uri', '__uri') == $dep['uri']) { 1112 return true; 1113 } 1114 } 1115 if (isset($options['upgrade'])) { 1116 if ($oper == 'has') { 1117 if (version_compare($this->_installRegistry->packageInfo( 1118 $package, 'version', $channel), 1119 $dep['version'], '>=')) { 1120 return true; 1121 } else { 1122 return false; 1123 } 1124 } else { 1125 if (version_compare($this->_installRegistry->packageInfo( 1126 $package, 'version', $channel), 1127 $dep['version'], '>=')) { 1128 return true; 1129 } 1130 return false; 1131 } 1132 } 1133 return true; 1134 } 1135 return false; 1136 } 1137 1138 /** 1139 * @param array 1140 * @static 1141 */ 1142 function removeDuplicates(&$params) 1143 { 1144 $pnames = array(); 1145 foreach ($params as $i => $param) { 1146 if (!$param) { 1147 continue; 1148 } 1149 if ($param->getPackage()) { 1150 $pnames[$i] = $param->getChannel() . '/' . 1151 $param->getPackage() . '-' . $param->getVersion() . '#' . $param->getGroup(); 1152 } 1153 } 1154 $pnames = array_unique($pnames); 1155 $unset = array_diff(array_keys($params), array_keys($pnames)); 1156 $testp = array_flip($pnames); 1157 foreach ($params as $i => $param) { 1158 if (!$param) { 1159 $unset[] = $i; 1160 continue; 1161 } 1162 if (!is_a($param, 'PEAR_Downloader_Package')) { 1163 $unset[] = $i; 1164 continue; 1165 } 1166 if (!isset($testp[$param->getChannel() . '/' . $param->getPackage() . '-' . 1167 $param->getVersion() . '#' . $param->getGroup()])) { 1168 $unset[] = $i; 1169 } 1170 } 1171 foreach ($unset as $i) { 1172 unset($params[$i]); 1173 } 1174 $ret = array(); 1175 foreach ($params as $i => $param) { 1176 $ret[] = &$params[$i]; 1177 } 1178 $params = array(); 1179 foreach ($ret as $i => $param) { 1180 $params[] = &$ret[$i]; 1181 } 1182 } 1183 1184 function explicitState() 1185 { 1186 return $this->_explicitState; 1187 } 1188 1189 function setExplicitState($s) 1190 { 1191 $this->_explicitState = $s; 1192 } 1193 1194 /** 1195 * @static 1196 */ 1197 function mergeDependencies(&$params) 1198 { 1199 $newparams = array(); 1200 $bundles = array(); 1201 foreach ($params as $i => $param) { 1202 if (!$param->isBundle()) { 1203 continue; 1204 } 1205 $bundles[] = $i; 1206 $pf = &$param->getPackageFile(); 1207 $newdeps = array(); 1208 $contents = $pf->getBundledPackages(); 1209 if (!is_array($contents)) { 1210 $contents = array($contents); 1211 } 1212 foreach ($contents as $file) { 1213 $filecontents = $pf->getFileContents($file); 1214 $dl = &$param->getDownloader(); 1215 $options = $dl->getOptions(); 1216 $fp = @fopen($dl->getDownloadDir() . DIRECTORY_SEPARATOR . $file, 'wb'); 1217 if (!$fp) { 1218 continue; 1219 } 1220 fwrite($fp, $filecontents, strlen($filecontents)); 1221 fclose($fp); 1222 if ($s = $params[$i]->explicitState()) { 1223 $obj->setExplicitState($s); 1224 } 1225 $obj = &new PEAR_Downloader_Package($params[$i]->getDownloader()); 1226 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 1227 $e = $obj->_fromFile($a = $dl->getDownloadDir() . DIRECTORY_SEPARATOR . $file); 1228 PEAR::popErrorHandling(); 1229 if (PEAR::isError($e)) { 1230 if (!isset($options['soft'])) { 1231 $dl->log(0, $e->getMessage()); 1232 } 1233 continue; 1234 } 1235 $j = &$obj; 1236 if (!PEAR_Downloader_Package::willDownload($j, 1237 array_merge($params, $newparams)) && !$param->isInstalled($j)) { 1238 $newparams[] = &$j; 1239 } 1240 } 1241 } 1242 foreach ($bundles as $i) { 1243 unset($params[$i]); // remove bundles - only their contents matter for installation 1244 } 1245 PEAR_Downloader_Package::removeDuplicates($params); // strip any unset indices 1246 if (count($newparams)) { // add in bundled packages for install 1247 foreach ($newparams as $i => $unused) { 1248 $params[] = &$newparams[$i]; 1249 } 1250 $newparams = array(); 1251 } 1252 foreach ($params as $i => $param) { 1253 $newdeps = array(); 1254 foreach ($param->_downloadDeps as $dep) { 1255 if (!PEAR_Downloader_Package::willDownload($dep, 1256 array_merge($params, $newparams)) && !$param->isInstalled($dep)) { 1257 $newdeps[] = $dep; 1258 } else { 1259 // detect versioning conflicts here 1260 } 1261 } 1262 // convert the dependencies into PEAR_Downloader_Package objects for the next time 1263 // around 1264 $params[$i]->_downloadDeps = array(); 1265 foreach ($newdeps as $dep) { 1266 $obj = &new PEAR_Downloader_Package($params[$i]->getDownloader()); 1267 if ($s = $params[$i]->explicitState()) { 1268 $obj->setExplicitState($s); 1269 } 1270 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 1271 $e = $obj->fromDepURL($dep); 1272 PEAR::popErrorHandling(); 1273 if (PEAR::isError($e)) { 1274 if (!isset($options['soft'])) { 1275 $obj->_downloader->log(0, $e->getMessage()); 1276 } 1277 continue; 1278 } 1279 $e = $obj->detectDependencies($params); 1280 if (PEAR::isError($e)) { 1281 if (!isset($options['soft'])) { 1282 $obj->_downloader->log(0, $e->getMessage()); 1283 } 1284 } 1285 $j = &$obj; 1286 $newparams[] = &$j; 1287 } 1288 } 1289 if (count($newparams)) { 1290 foreach ($newparams as $i => $unused) { 1291 $params[] = &$newparams[$i]; 1292 } 1293 return true; 1294 } else { 1295 return false; 1296 } 1297 } 1298 1299 1300 /** 1301 * @static 1302 */ 1303 function willDownload($param, $params) 1304 { 1305 if (!is_array($params)) { 1306 return false; 1307 } 1308 foreach ($params as $obj) { 1309 if ($obj->isEqual($param)) { 1310 return true; 1311 } 1312 } 1313 return false; 1314 } 1315 1316 /** 1317 * For simpler unit-testing 1318 * @param PEAR_Config 1319 * @param int 1320 * @param string 1321 */ 1322 function &getPackagefileObject(&$c, $d, $t = false) 1323 { 1324 $a = &new PEAR_PackageFile($c, $d, $t); 1325 return $a; 1326 } 1327 1328 1329 /** 1330 * This will retrieve from a local file if possible, and parse out 1331 * a group name as well. The original parameter will be modified to reflect this. 1332 * @param string|array can be a parsed package name as well 1333 * @access private 1334 */ 1335 function _fromFile(&$param) 1336 { 1337 if (is_string($param) && !@is_file($param)) { 1338 $test = explode('#', $param); 1339 $group = array_pop($test); 1340 if (@is_file(implode('#', $test))) { 1341 $this->setGroup($group); 1342 $param = implode('#', $test); 1343 $this->_explicitGroup = true; 1344 } 1345 } 1346 if (@is_file($param)) { 1347 $this->_type = 'local'; 1348 $options = $this->_downloader->getOptions(); 1349 if (isset($options['downloadonly'])) { 1350 $pkg = &$this->getPackagefileObject($this->_config, 1351 $this->_downloader->_debug); 1352 } else { 1353 $pkg = &$this->getPackagefileObject($this->_config, 1354 $this->_downloader->_debug, $this->_downloader->getDownloadDir()); 1355 } 1356 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 1357 $pf = &$pkg->fromAnyFile($param, PEAR_VALIDATE_INSTALLING); 1358 PEAR::popErrorHandling(); 1359 if (PEAR::isError($pf)) { 1360 $this->_valid = false; 1361 return $pf; 1362 } 1363 $this->_packagefile = &$pf; 1364 if (!$this->getGroup()) { 1365 $this->setGroup('default'); // install the default dependency group 1366 } 1367 return $this->_valid = true; 1368 } 1369 return $this->_valid = false; 1370 } 1371 1372 function _fromUrl($param, $saveparam = '') 1373 { 1374 if (!is_array($param) && 1375 (preg_match('#^(http|ftp)://#', $param))) { 1376 $options = $this->_downloader->getOptions(); 1377 $this->_type = 'url'; 1378 $callback = $this->_downloader->ui ? 1379 array(&$this->_downloader, '_downloadCallback') : null; 1380 $this->_downloader->pushErrorHandling(PEAR_ERROR_RETURN); 1381 $file = $this->_downloader->downloadHttp($param, $this->_downloader->ui, 1382 $this->_downloader->getDownloadDir(), $callback); 1383 $this->_downloader->popErrorHandling(); 1384 if (PEAR::isError($file)) { 1385 if (!empty($saveparam)) { 1386 $saveparam = ", cannot download \"$saveparam\""; 1387 } 1388 $err = PEAR::raiseError('Could not download from "' . $param . 1389 '"' . $saveparam); 1390 return $err; 1391 } 1392 if ($this->_rawpackagefile) { 1393 require_once 'Archive/Tar.php'; 1394 $tar = &new Archive_Tar($file); 1395 $packagexml = $tar->extractInString('package2.xml'); 1396 if (!$packagexml) { 1397 $packagexml = $tar->extractInString('package.xml'); 1398 } 1399 if (str_replace(array("\n", "\r"), array('',''), $packagexml) != 1400 str_replace(array("\n", "\r"), array('',''), $this->_rawpackagefile)) { 1401 if ($this->getChannel() == 'pear.php.net') { 1402 // be more lax for the existing PEAR packages that have not-ok 1403 // characters in their package.xml 1404 $this->_downloader->log(0, 'CRITICAL WARNING: The "' . 1405 $this->getPackage() . '" package has invalid characters in its ' . 1406 'package.xml. The next version of PEAR may not be able to install ' . 1407 'this package for security reasons. Please open a bug report at ' . 1408 'http://pear.php.net/package/' . $this->getPackage() . '/bugs'); 1409 } else { 1410 return PEAR::raiseError('CRITICAL ERROR: package.xml downloaded does ' . 1411 'not match value returned from xml-rpc'); 1412 } 1413 } 1414 } 1415 // whew, download worked! 1416 if (isset($options['downloadonly'])) { 1417 $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->debug); 1418 } else { 1419 $pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->debug, 1420 $this->_downloader->getDownloadDir()); 1421 } 1422 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 1423 $pf = &$pkg->fromAnyFile($file, PEAR_VALIDATE_INSTALLING); 1424 PEAR::popErrorHandling(); 1425 if (PEAR::isError($pf)) { 1426 if (is_array($pf->getUserInfo())) { 1427 foreach ($pf->getUserInfo() as $err) { 1428 if (is_array($err)) { 1429 $err = $err['message']; 1430 } 1431 if (!isset($options['soft'])) { 1432 $this->_downloader->log(0, "Validation Error: $err"); 1433 } 1434 } 1435 } 1436 if (!isset($options['soft'])) { 1437 $this->_downloader->log(0, $pf->getMessage()); 1438 } 1439 $err = PEAR::raiseError('Download of "' . ($saveparam ? $saveparam : 1440 $param) . '" succeeded, but it is not a valid package archive'); 1441 $this->_valid = false; 1442 return $err; 1443 } 1444 $this->_packagefile = &$pf; 1445 $this->setGroup('default'); // install the default dependency group 1446 return $this->_valid = true; 1447 } 1448 return $this->_valid = false; 1449 } 1450 1451 /** 1452 * 1453 * @param string|array pass in an array of format 1454 * array( 1455 * 'package' => 'pname', 1456 * ['channel' => 'channame',] 1457 * ['version' => 'version',] 1458 * ['state' => 'state',]) 1459 * or a string of format [channame/]pname[-version|-state] 1460 */ 1461 function _fromString($param) 1462 { 1463 $options = $this->_downloader->getOptions(); 1464 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 1465 $pname = $this->_registry->parsePackageName($param, 1466 $this->_config->get('default_channel')); 1467 PEAR::popErrorHandling(); 1468 if (PEAR::isError($pname)) { 1469 if ($pname->getCode() == 'invalid') { 1470 $this->_valid = false; 1471 return false; 1472 } 1473 if ($pname->getCode() == 'channel') { 1474 $parsed = $pname->getUserInfo(); 1475 if ($this->_downloader->discover($parsed['channel'])) { 1476 if ($this->_config->get('auto_discover')) { 1477 PEAR::pushErrorHandling(PEAR_ERROR_RETURN); 1478 $pname = $this->_registry->parsePackageName($param, 1479 $this->_config->get('default_channel')); 1480 PEAR::popErrorHandling(); 1481 } else { 1482 if (!isset($options['soft'])) { 1483 $this->_downloader->log(0, 'Channel "' . $parsed['channel'] . 1484 '" is not initialized, use ' . 1485 '"pear channel-discover ' . $parsed['channel'] . '" to initialize' . 1486 'or pear config-set auto_discover 1'); 1487 } 1488 } 1489 } 1490 if (PEAR::isError($pname)) { 1491 if (!isset($options['soft'])) { 1492 $this->_downloader->log(0, $pname->getMessage()); 1493 } 1494 if (is_array($param)) { 1495 $param = $this->_registry->parsedPackageNameToString($param); 1496 } 1497 $err = PEAR::raiseError('invalid package name/package file "' . 1498 $param . '"'); 1499 $this->_valid = false; 1500 return $err; 1501 } 1502 } else { 1503 if (!isset($options['soft'])) { 1504 $this->_downloader->log(0, $pname->getMessage()); 1505 } 1506 $err = PEAR::raiseError('invalid package name/package file "' . 1507 $param . '"'); 1508 $this->_valid = false; 1509 return $err; 1510 } 1511 } 1512 if (!isset($this->_type)) { 1513 $this->_type = 'xmlrpc'; 1514 } 1515 $this->_parsedname = $pname; 1516 if (isset($pname['state'])) { 1517 $this->_explicitState = $pname['state']; 1518 } else { 1519 $this->_explicitState = false; 1520 } 1521 if (isset($pname['group'])) { 1522 $this->_explicitGroup = true; 1523 } else { 1524 $this->_explicitGroup = false; 1525 } 1526 $info = $this->_downloader->_getPackageDownloadUrl($pname); 1527 if (PEAR::isError($info)) { 1528 if ($pname['channel'] == 'pear.php.net') { 1529 // try pecl 1530 $pname['channel'] = 'pecl.php.net'; 1531 if ($test = $this->_downloader->_getPackageDownloadUrl($pname)) { 1532 if (!PEAR::isError($test)) { 1533 $info = PEAR::raiseError($info->getMessage() . ' - package ' . 1534 $this->_registry->parsedPackageNameToString($pname, true) . 1535 ' can be installed with "pecl install ' . $pname['package'] . 1536 '"'); 1537 } else { 1538 $pname['channel'] = 'pear.php.net'; 1539 } 1540 } else { 1541 $pname['channel'] = 'pear.php.net'; 1542 } 1543 } 1544 return $info; 1545 } 1546 $this->_rawpackagefile = $info['raw']; 1547 $ret = $this->_analyzeDownloadURL($info, $param, $pname); 1548 if (PEAR::isError($ret)) { 1549 return $ret; 1550 } 1551 if ($ret) { 1552 $this->_downloadURL = $ret; 1553 return $this->_valid = (bool) $ret; 1554 } 1555 } 1556 1557 /** 1558 * @param array output of package.getDownloadURL 1559 * @param string|array|object information for detecting packages to be downloaded, and 1560 * for errors 1561 * @param array name information of the package 1562 * @param array|null packages to be downloaded 1563 * @param bool is this an optional dependency? 1564 * @access private 1565 */ 1566 function _analyzeDownloadURL($info, $param, $pname, $params = null, $optional = false) 1567 { 1568 if (!is_string($param) && PEAR_Downloader_Package::willDownload($param, $params)) { 1569 return false; 1570 } 1571 if (!$info) { 1572 if (!is_string($param)) { 1573 $saveparam = ", cannot download \"$param\""; 1574 } else { 1575 $saveparam = ''; 1576 } 1577 // no releases exist 1578 return PEAR::raiseError('No releases for package "' . 1579 $this->_registry->parsedPackageNameToString($pname, true) . '" exist' . $saveparam); 1580 } 1581 if (strtolower($info['info']->getChannel()) != strtolower($pname['channel'])) { 1582 $err = false; 1583 if ($pname['channel'] == 'pecl.php.net') { 1584 if ($info['info']->getChannel() != 'pear.php.net') { 1585 $err = true; 1586 } 1587 } elseif ($info['info']->getChannel() == 'pecl.php.net') { 1588 if ($pname['channel'] != 'pear.php.net') { 1589 $err = true; 1590 } 1591 } else { 1592 $err = true; 1593 } 1594 if ($err) { 1595 return PEAR::raiseError('SECURITY ERROR: package in channel "' . $pname['channel'] . 1596 '" retrieved another channel\'s name for download! ("' . 1597 $info['info']->getChannel() . '")'); 1598 } 1599 } 1600 if (!isset($info['url'])) { 1601 $instead = ', will instead download version ' . $info['version'] . 1602 ', stability "' . $info['info']->getState() . '"'; 1603 // releases exist, but we failed to get any 1604 if (isset($this->_downloader->_options['force'])) { 1605 if (isset($pname['version'])) { 1606 $vs = ', version "' . $pname['version'] . '"'; 1607 } elseif (isset($pname['state'])) { 1608 $vs = ', stability "' . $pname['state'] . '"'; 1609 } elseif ($param == 'dependency') { 1610 if (!class_exists('PEAR_Common')) { 1611 require_once 'PEAR/Common.php'; 1612 } 1613 if (!in_array($info['info']->getState(), 1614 PEAR_Common::betterStates($this->_config->get('preferred_state'), true))) { 1615 if ($optional) { 1616 // don't spit out confusing error message 1617 return $this->_downloader->_getPackageDownloadUrl( 1618 array('package' => $pname['package'], 1619 'channel' => $pname['channel'], 1620 'version' => $info['version'])); 1621 } 1622 $vs = ' within preferred state "' . $this->_config->get('preferred_state') . 1623 '"'; 1624 } else { 1625 if (!class_exists('PEAR_Dependency2')) { 1626 require_once 'PEAR/Dependency2.php'; 1627 } 1628 if ($optional) { 1629 // don't spit out confusing error message 1630 return $this->_downloader->_getPackageDownloadUrl( 1631 array('package' => $pname['package'], 1632 'channel' => $pname['channel'], 1633 'version' => $info['version'])); 1634 } 1635 $vs = PEAR_Dependency2::_getExtraString($pname); 1636 $instead = ''; 1637 } 1638 } else { 1639 $vs = ' within preferred state "' . $this->_config->get( 1640 'preferred_state') . '"'; 1641 } 1642 if (!isset($options['soft'])) { 1643 $this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] . 1644 '/' . $pname['package'] . $vs . $instead); 1645 } 1646 // download the latest release 1647 return $this->_downloader->_getPackageDownloadUrl( 1648 array('package' => $pname['package'], 1649 'channel' => $pname['channel'], 1650 'version' => $info['version'])); 1651 } else { 1652 // construct helpful error message 1653 if (isset($pname['version'])) { 1654 $vs = ', version "' . $pname['version'] . '"'; 1655 } elseif (isset($pname['state'])) { 1656 $vs = ', stability "' . $pname['state'] . '"'; 1657 } elseif ($param == 'dependency') { 1658 if (!class_exists('PEAR_Common')) { 1659 require_once 'PEAR/Common.php'; 1660 } 1661 if (!in_array($info['info']->getState(), 1662 PEAR_Common::betterStates($this->_config->get('preferred_state'), true))) { 1663 if ($optional) { 1664 // don't spit out confusing error message, and don't die on 1665 // optional dep failure! 1666 return $this->_downloader->_getPackageDownloadUrl( 1667 array('package' => $pname['package'], 1668 'channel' => $pname['channel'], 1669 'version' => $info['version'])); 1670 } 1671 $vs = ' within preferred state "' . $this->_config->get('preferred_state') . 1672 '"'; 1673 } else { 1674 if (!class_exists('PEAR_Dependency2')) { 1675 require_once 'PEAR/Dependency2.php'; 1676 } 1677 if ($optional) { 1678 // don't spit out confusing error message, and don't die on 1679 // optional dep failure! 1680 return $this->_downloader->_getPackageDownloadUrl( 1681 array('package' => $pname['package'], 1682 'channel' => $pname['channel'], 1683 'version' => $info['version'])); 1684 } 1685 $vs = PEAR_Dependency2::_getExtraString($pname); 1686 } 1687 } else { 1688 $vs = ' within preferred state "' . $this->_downloader->config->get( 1689 'preferred_state') . '"'; 1690 } 1691 $options = $this->_downloader->getOptions(); 1692 // this is only set by the "download-all" command 1693 if (isset($options['ignorepreferred_state'])) { 1694 $err = PEAR::raiseError( 1695 'Failed to download ' . $this->_registry->parsedPackageNameToString( 1696 array('channel' => $pname['channel'], 'package' => $pname['package']), 1697 true) 1698 . $vs . 1699 ', latest release is version ' . $info['version'] . 1700 ', stability "' . $info['info']->getState() . '", use "' . 1701 $this->_registry->parsedPackageNameToString( 1702 array('channel' => $pname['channel'], 'package' => $pname['package'], 1703 'version' => $info['version'])) . '" to install', 1704 PEAR_DOWNLOADER_PACKAGE_STATE); 1705 return $err; 1706 } 1707 $err = PEAR::raiseError( 1708 'Failed to download ' . $this->_registry->parsedPackageNameToString( 1709 array('channel' => $pname['channel'], 'package' => $pname['package']), 1710 true) 1711 . $vs . 1712 ', latest release is version ' . $info['version'] . 1713 ', stability "' . $info['info']->getState() . '", use "' . 1714 $this->_registry->parsedPackageNameToString( 1715 array('channel' => $pname['channel'], 'package' => $pname['package'], 1716 'version' => $info['version'])) . '" to install'); 1717 return $err; 1718 } 1719 } 1720 return $info; 1721 } 1722 } 1723 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Wed Nov 21 12:27:40 2007 | par Balluche grâce à PHPXref 0.7 |
|