[ Index ] |
|
Code source de PHP PEAR 1.4.5 |
1 <?php 2 /** 3 * PEAR_Command_Remote (remote-info, list-upgrades, remote-list, search, list-all, download, 4 * clear-cache commands) 5 * 6 * PHP versions 4 and 5 7 * 8 * LICENSE: This source file is subject to version 3.0 of the PHP license 9 * that is available through the world-wide-web at the following URI: 10 * http://www.php.net/license/3_0.txt. If you did not receive a copy of 11 * the PHP License and are unable to obtain it through the web, please 12 * send a note to license@php.net so we can mail you a copy immediately. 13 * 14 * @category pear 15 * @package PEAR 16 * @author Stig Bakken <ssb@php.net> 17 * @author Greg Beaver <cellog@php.net> 18 * @copyright 1997-2006 The PHP Group 19 * @license http://www.php.net/license/3_0.txt PHP License 3.0 20 * @version CVS: $Id: Remote.php,v 1.96 2006/09/24 03:08:57 cellog Exp $ 21 * @link http://pear.php.net/package/PEAR 22 * @since File available since Release 0.1 23 */ 24 25 /** 26 * base class 27 */ 28 require_once 'PEAR/Command/Common.php'; 29 require_once 'PEAR/REST.php'; 30 31 /** 32 * PEAR commands for remote server querying 33 * 34 * @category pear 35 * @package PEAR 36 * @author Stig Bakken <ssb@php.net> 37 * @author Greg Beaver <cellog@php.net> 38 * @copyright 1997-2006 The PHP Group 39 * @license http://www.php.net/license/3_0.txt PHP License 3.0 40 * @version Release: 1.5.0 41 * @link http://pear.php.net/package/PEAR 42 * @since Class available since Release 0.1 43 */ 44 class PEAR_Command_Remote extends PEAR_Command_Common 45 { 46 // {{{ command definitions 47 48 var $commands = array( 49 'remote-info' => array( 50 'summary' => 'Information About Remote Packages', 51 'function' => 'doRemoteInfo', 52 'shortcut' => 'ri', 53 'options' => array(), 54 'doc' => '<package> 55 Get details on a package from the server.', 56 ), 57 'list-upgrades' => array( 58 'summary' => 'List Available Upgrades', 59 'function' => 'doListUpgrades', 60 'shortcut' => 'lu', 61 'options' => array(), 62 'doc' => '[preferred_state] 63 List releases on the server of packages you have installed where 64 a newer version is available with the same release state (stable etc.) 65 or the state passed as the second parameter.' 66 ), 67 'remote-list' => array( 68 'summary' => 'List Remote Packages', 69 'function' => 'doRemoteList', 70 'shortcut' => 'rl', 71 'options' => array( 72 'channel' => 73 array( 74 'shortopt' => 'c', 75 'doc' => 'specify a channel other than the default channel', 76 'arg' => 'CHAN', 77 ) 78 ), 79 'doc' => ' 80 Lists the packages available on the configured server along with the 81 latest stable release of each package.', 82 ), 83 'search' => array( 84 'summary' => 'Search remote package database', 85 'function' => 'doSearch', 86 'shortcut' => 'sp', 87 'options' => array( 88 'channel' => 89 array( 90 'shortopt' => 'c', 91 'doc' => 'specify a channel other than the default channel', 92 'arg' => 'CHAN', 93 ) 94 ), 95 'doc' => '[packagename] [packageinfo] 96 Lists all packages which match the search parameters. The first 97 parameter is a fragment of a packagename. The default channel 98 will be used unless explicitly overridden. The second parameter 99 will be used to match any portion of the summary/description', 100 ), 101 'list-all' => array( 102 'summary' => 'List All Packages', 103 'function' => 'doListAll', 104 'shortcut' => 'la', 105 'options' => array( 106 'channel' => 107 array( 108 'shortopt' => 'c', 109 'doc' => 'specify a channel other than the default channel', 110 'arg' => 'CHAN', 111 ) 112 ), 113 'doc' => ' 114 Lists the packages available on the configured server along with the 115 latest stable release of each package.', 116 ), 117 'download' => array( 118 'summary' => 'Download Package', 119 'function' => 'doDownload', 120 'shortcut' => 'd', 121 'options' => array( 122 'nocompress' => array( 123 'shortopt' => 'Z', 124 'doc' => 'download an uncompressed (.tar) file', 125 ), 126 ), 127 'doc' => '<package>... 128 Download package tarballs. The files will be named as suggested by the 129 server, for example if you download the DB package and the latest stable 130 version of DB is 1.6.5, the downloaded file will be DB-1.6.5.tgz.', 131 ), 132 'clear-cache' => array( 133 'summary' => 'Clear Web Services Cache', 134 'function' => 'doClearCache', 135 'shortcut' => 'cc', 136 'options' => array(), 137 'doc' => ' 138 Clear the XML-RPC/REST cache. See also the cache_ttl configuration 139 parameter. 140 ', 141 ), 142 ); 143 144 // }}} 145 // {{{ constructor 146 147 /** 148 * PEAR_Command_Remote constructor. 149 * 150 * @access public 151 */ 152 function PEAR_Command_Remote(&$ui, &$config) 153 { 154 parent::PEAR_Command_Common($ui, $config); 155 } 156 157 // }}} 158 159 function _checkChannelForStatus($channel, $chan) 160 { 161 if (PEAR::isError($chan)) { 162 $this->raiseError($chan); 163 } 164 if (!is_a($chan, 'PEAR_ChannelFile')) { 165 return $this->raiseError('Internal corruption error: invalid channel "' . 166 $channel . '"'); 167 } 168 $rest = new PEAR_REST($this->config); 169 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); 170 $a = $rest->downloadHttp('http://' . $channel . 171 '/channel.xml', $chan->lastModified()); 172 PEAR::staticPopErrorHandling(); 173 if (!PEAR::isError($a) && $a) { 174 $this->ui->outputData('WARNING: channel "' . $channel . '" has ' . 175 'updated its protocols, use "channel-update ' . $channel . 176 '" to update'); 177 } 178 } 179 180 // {{{ doRemoteInfo() 181 182 function doRemoteInfo($command, $options, $params) 183 { 184 if (sizeof($params) != 1) { 185 return $this->raiseError("$command expects one param: the remote package name"); 186 } 187 $savechannel = $channel = $this->config->get('default_channel'); 188 $reg = &$this->config->getRegistry(); 189 $package = $params[0]; 190 $parsed = $reg->parsePackageName($package, $channel); 191 if (PEAR::isError($parsed)) { 192 return $this->raiseError('Invalid package name "' . $package . '"'); 193 } 194 195 $channel = $parsed['channel']; 196 $this->config->set('default_channel', $channel); 197 $chan = $reg->getChannel($channel); 198 if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { 199 return $e; 200 } 201 if ($chan->supportsREST($this->config->get('preferred_mirror')) && 202 $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { 203 $rest = &$this->config->getREST('1.0', array()); 204 $info = $rest->packageInfo($base, $parsed['package']); 205 } else { 206 $r = &$this->config->getRemote(); 207 $info = $r->call('package.info', $parsed['package']); 208 } 209 if (PEAR::isError($info)) { 210 $this->config->set('default_channel', $savechannel); 211 return $this->raiseError($info); 212 } 213 if (!isset($info['name'])) { 214 return $this->raiseError('No remote package "' . $package . '" was found'); 215 } 216 217 $installed = $reg->packageInfo($info['name'], null, $channel); 218 $info['installed'] = $installed['version'] ? $installed['version'] : '- no -'; 219 if (is_array($info['installed'])) { 220 $info['installed'] = $info['installed']['release']; 221 } 222 223 $this->ui->outputData($info, $command); 224 $this->config->set('default_channel', $savechannel); 225 226 return true; 227 } 228 229 // }}} 230 // {{{ doRemoteList() 231 232 function doRemoteList($command, $options, $params) 233 { 234 $savechannel = $channel = $this->config->get('default_channel'); 235 $reg = &$this->config->getRegistry(); 236 if (isset($options['channel'])) { 237 $channel = $options['channel']; 238 if ($reg->channelExists($channel)) { 239 $this->config->set('default_channel', $channel); 240 } else { 241 return $this->raiseError('Channel "' . $channel . '" does not exist'); 242 } 243 } 244 $chan = $reg->getChannel($channel); 245 if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { 246 return $e; 247 } 248 $list_options = false; 249 if ($this->config->get('preferred_state') == 'stable') { 250 $list_options = true; 251 } 252 if ($chan->supportsREST($this->config->get('preferred_mirror')) && 253 $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) { 254 // use faster list-all if available 255 $rest = &$this->config->getREST('1.1', array()); 256 $available = $rest->listAll($base, $list_options); 257 } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) && 258 $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { 259 $rest = &$this->config->getREST('1.0', array()); 260 $available = $rest->listAll($base, $list_options); 261 } else { 262 $r = &$this->config->getRemote(); 263 if ($channel == 'pear.php.net') { 264 // hack because of poor pearweb design 265 $available = $r->call('package.listAll', true, $list_options, false); 266 } else { 267 $available = $r->call('package.listAll', true, $list_options); 268 } 269 } 270 if (PEAR::isError($available)) { 271 $this->config->set('default_channel', $savechannel); 272 return $this->raiseError($available); 273 } 274 $i = $j = 0; 275 $data = array( 276 'caption' => 'Channel ' . $channel . ' Available packages:', 277 'border' => true, 278 'headline' => array('Package', 'Version'), 279 ); 280 if (count($available)==0) { 281 $data = '(no packages available yet)'; 282 } else { 283 foreach ($available as $name => $info) { 284 $data['data'][] = array($name, (isset($info['stable']) && $info['stable']) 285 ? $info['stable'] : '-n/a-'); 286 } 287 } 288 $this->ui->outputData($data, $command); 289 $this->config->set('default_channel', $savechannel); 290 return true; 291 } 292 293 // }}} 294 // {{{ doListAll() 295 296 function doListAll($command, $options, $params) 297 { 298 $savechannel = $channel = $this->config->get('default_channel'); 299 $reg = &$this->config->getRegistry(); 300 if (isset($options['channel'])) { 301 $channel = $options['channel']; 302 if ($reg->channelExists($channel)) { 303 $this->config->set('default_channel', $channel); 304 } else { 305 return $this->raiseError("Channel \"$channel\" does not exist"); 306 } 307 } 308 $list_options = false; 309 if ($this->config->get('preferred_state') == 'stable') { 310 $list_options = true; 311 } 312 $chan = $reg->getChannel($channel); 313 if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { 314 return $e; 315 } 316 if ($chan->supportsREST($this->config->get('preferred_mirror')) && 317 $base = $chan->getBaseURL('REST1.1', $this->config->get('preferred_mirror'))) { 318 // use faster list-all if available 319 $rest = &$this->config->getREST('1.1', array()); 320 $available = $rest->listAll($base, $list_options, false); 321 } elseif ($chan->supportsREST($this->config->get('preferred_mirror')) && 322 $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { 323 $rest = &$this->config->getREST('1.0', array()); 324 $available = $rest->listAll($base, $list_options, false); 325 } else { 326 $r = &$this->config->getRemote(); 327 if ($channel == 'pear.php.net') { 328 // hack because of poor pearweb design 329 $available = $r->call('package.listAll', true, $list_options, false); 330 } else { 331 $available = $r->call('package.listAll', true, $list_options); 332 } 333 } 334 if (PEAR::isError($available)) { 335 $this->config->set('default_channel', $savechannel); 336 return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "' . $available->getMessage() . '")'); 337 } 338 $data = array( 339 'caption' => 'All packages:', 340 'border' => true, 341 'headline' => array('Package', 'Latest', 'Local'), 342 ); 343 $local_pkgs = $reg->listPackages($channel); 344 345 foreach ($available as $name => $info) { 346 $installed = $reg->packageInfo($name, null, $channel); 347 if (is_array($installed['version'])) { 348 $installed['version'] = $installed['version']['release']; 349 } 350 $desc = $info['summary']; 351 if (isset($params[$name])) { 352 $desc .= "\n\n".$info['description']; 353 } 354 if (isset($options['mode'])) 355 { 356 if ($options['mode'] == 'installed' && !isset($installed['version'])) { 357 continue; 358 } 359 if ($options['mode'] == 'notinstalled' && isset($installed['version'])) { 360 continue; 361 } 362 if ($options['mode'] == 'upgrades' 363 && (!isset($installed['version']) || version_compare($installed['version'], 364 $info['stable'], '>='))) { 365 continue; 366 } 367 } 368 $pos = array_search(strtolower($name), $local_pkgs); 369 if ($pos !== false) { 370 unset($local_pkgs[$pos]); 371 } 372 373 if (isset($info['stable']) && !$info['stable']) { 374 $info['stable'] = null; 375 } 376 $data['data'][$info['category']][] = array( 377 $reg->channelAlias($channel) . '/' . $name, 378 isset($info['stable']) ? $info['stable'] : null, 379 isset($installed['version']) ? $installed['version'] : null, 380 isset($desc) ? $desc : null, 381 isset($info['deps']) ? $info['deps'] : null, 382 ); 383 } 384 385 if (isset($options['mode']) && in_array($options['mode'], array('notinstalled', 'upgrades'))) { 386 $this->config->set('default_channel', $savechannel); 387 $this->ui->outputData($data, $command); 388 return true; 389 } 390 foreach ($local_pkgs as $name) { 391 $info = &$reg->getPackage($name, $channel); 392 $data['data']['Local'][] = array( 393 $reg->channelAlias($channel) . '/' . $info->getPackage(), 394 '', 395 $info->getVersion(), 396 $info->getSummary(), 397 $info->getDeps() 398 ); 399 } 400 401 $this->config->set('default_channel', $savechannel); 402 $this->ui->outputData($data, $command); 403 return true; 404 } 405 406 // }}} 407 // {{{ doSearch() 408 409 function doSearch($command, $options, $params) 410 { 411 if ((!isset($params[0]) || empty($params[0])) 412 && (!isset($params[1]) || empty($params[1]))) 413 { 414 return $this->raiseError('no valid search string supplied'); 415 }; 416 417 $savechannel = $channel = $this->config->get('default_channel'); 418 $reg = &$this->config->getRegistry(); 419 $package = $params[0]; 420 $summary = isset($params[1]) ? $params[1] : false; 421 if (isset($options['channel'])) { 422 $reg = &$this->config->getRegistry(); 423 $channel = $options['channel']; 424 if ($reg->channelExists($channel)) { 425 $this->config->set('default_channel', $channel); 426 } else { 427 return $this->raiseError('Channel "' . $channel . '" does not exist'); 428 } 429 } 430 $chan = $reg->getChannel($channel); 431 if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { 432 return $e; 433 } 434 if ($chan->supportsREST($this->config->get('preferred_mirror')) && 435 $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { 436 $rest = &$this->config->getREST('1.0', array()); 437 $available = $rest->listAll($base, false, false, $package, $summary); 438 } else { 439 $r = &$this->config->getRemote(); 440 $available = $r->call('package.search', $package, $summary, true, 441 $this->config->get('preferred_state') == 'stable', true); 442 } 443 if (PEAR::isError($available)) { 444 $this->config->set('default_channel', $savechannel); 445 return $this->raiseError($available); 446 } 447 if (!$available) { 448 return $this->raiseError('no packages found that match pattern "' . $package . '"'); 449 } 450 $data = array( 451 'caption' => 'Matched packages, channel ' . $channel . ':', 452 'border' => true, 453 'headline' => array('Package', 'Stable/(Latest)', 'Local'), 454 ); 455 456 foreach ($available as $name => $info) { 457 $installed = $reg->packageInfo($name, null, $channel); 458 $desc = $info['summary']; 459 if (isset($params[$name])) 460 $desc .= "\n\n".$info['description']; 461 462 $unstable = ''; 463 if ($info['unstable']) { 464 $unstable = '/(' . $info['unstable'] . ' ' . $info['state'] . ')'; 465 } 466 if (!isset($info['stable']) || !$info['stable']) { 467 $info['stable'] = 'none'; 468 } 469 $version = is_array($installed['version']) ? $installed['version']['release'] : 470 $installed['version']; 471 $data['data'][$info['category']][] = array( 472 $name, 473 $info['stable'] . $unstable, 474 $version, 475 $desc, 476 ); 477 } 478 $this->ui->outputData($data, $command); 479 $this->config->set('default_channel', $channel); 480 return true; 481 } 482 483 // }}} 484 function &getDownloader($options) 485 { 486 if (!class_exists('PEAR_Downloader')) { 487 require_once 'PEAR/Downloader.php'; 488 } 489 $a = &new PEAR_Downloader($this->ui, $options, $this->config); 490 return $a; 491 } 492 // {{{ doDownload() 493 494 function doDownload($command, $options, $params) 495 { 496 // make certain that dependencies are ignored 497 $options['downloadonly'] = 1; 498 499 // eliminate error messages for preferred_state-related errors 500 /* TODO: Should be an option, but until now download does respect 501 prefered state */ 502 /* $options['ignorepreferred_state'] = 1; */ 503 // eliminate error messages for preferred_state-related errors 504 505 $downloader = &$this->getDownloader($options); 506 $downloader->setDownloadDir(getcwd()); 507 $errors = array(); 508 $downloaded = array(); 509 $err = $downloader->download($params); 510 if (PEAR::isError($err)) { 511 return $err; 512 } 513 $errors = $downloader->getErrorMsgs(); 514 if (count($errors)) { 515 foreach ($errors as $error) { 516 $this->ui->outputData($error); 517 } 518 return $this->raiseError("$command failed"); 519 } 520 $downloaded = $downloader->getDownloadedPackages(); 521 foreach ($downloaded as $pkg) { 522 $this->ui->outputData("File $pkg[file] downloaded", $command); 523 } 524 return true; 525 } 526 527 function downloadCallback($msg, $params = null) 528 { 529 if ($msg == 'done') { 530 $this->bytes_downloaded = $params; 531 } 532 } 533 534 // }}} 535 // {{{ doListUpgrades() 536 537 function doListUpgrades($command, $options, $params) 538 { 539 require_once 'PEAR/Common.php'; 540 if (isset($params[0]) && !is_array(PEAR_Common::betterStates($params[0]))) { 541 return $this->raiseError($params[0] . ' is not a valid state (stable/beta/alpha/devel/etc.) try "pear help list-upgrades"'); 542 } 543 $savechannel = $channel = $this->config->get('default_channel'); 544 $reg = &$this->config->getRegistry(); 545 foreach ($reg->listChannels() as $channel) { 546 $inst = array_flip($reg->listPackages($channel)); 547 if (!count($inst)) { 548 continue; 549 } 550 if ($channel == '__uri') { 551 continue; 552 } 553 $this->config->set('default_channel', $channel); 554 if (empty($params[0])) { 555 $state = $this->config->get('preferred_state'); 556 } else { 557 $state = $params[0]; 558 } 559 $caption = $channel . ' Available Upgrades'; 560 $chan = $reg->getChannel($channel); 561 if (PEAR::isError($e = $this->_checkChannelForStatus($channel, $chan))) { 562 return $e; 563 } 564 if ($chan->supportsREST($this->config->get('preferred_mirror')) && 565 $base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) { 566 $rest = &$this->config->getREST('1.0', array()); 567 if (empty($state) || $state == 'any') { 568 $state = false; 569 } else { 570 $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')'; 571 } 572 PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); 573 $latest = $rest->listLatestUpgrades($base, $state, $inst, $channel, $reg); 574 PEAR::staticPopErrorHandling(); 575 } else { 576 $remote = &$this->config->getRemote(); 577 $remote->pushErrorHandling(PEAR_ERROR_RETURN); 578 if (empty($state) || $state == 'any') { 579 $latest = $remote->call("package.listLatestReleases"); 580 } else { 581 $latest = $remote->call("package.listLatestReleases", $state); 582 $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')'; 583 } 584 $remote->popErrorHandling(); 585 } 586 if (PEAR::isError($latest)) { 587 $this->ui->outputData($latest->getMessage()); 588 continue; 589 } 590 $caption .= ':'; 591 if (PEAR::isError($latest)) { 592 $this->config->set('default_channel', $savechannel); 593 return $latest; 594 } 595 $data = array( 596 'caption' => $caption, 597 'border' => 1, 598 'headline' => array('Channel', 'Package', 'Local', 'Remote', 'Size'), 599 ); 600 foreach ((array)$latest as $pkg => $info) { 601 $package = strtolower($pkg); 602 if (!isset($inst[$package])) { 603 // skip packages we don't have installed 604 continue; 605 } 606 extract($info); 607 $inst_version = $reg->packageInfo($package, 'version', $channel); 608 $inst_state = $reg->packageInfo($package, 'release_state', $channel); 609 if (version_compare("$version", "$inst_version", "le")) { 610 // installed version is up-to-date 611 continue; 612 } 613 if ($filesize >= 20480) { 614 $filesize += 1024 - ($filesize % 1024); 615 $fs = sprintf("%dkB", $filesize / 1024); 616 } elseif ($filesize > 0) { 617 $filesize += 103 - ($filesize % 103); 618 $fs = sprintf("%.1fkB", $filesize / 1024.0); 619 } else { 620 $fs = " -"; // XXX center instead 621 } 622 $data['data'][] = array($channel, $pkg, "$inst_version ($inst_state)", "$version ($state)", $fs); 623 } 624 if (empty($data['data'])) { 625 $this->ui->outputData('Channel ' . $channel . ': No upgrades available'); 626 } else { 627 $this->ui->outputData($data, $command); 628 } 629 } 630 $this->config->set('default_channel', $savechannel); 631 return true; 632 } 633 634 // }}} 635 // {{{ doClearCache() 636 637 function doClearCache($command, $options, $params) 638 { 639 $cache_dir = $this->config->get('cache_dir'); 640 $verbose = $this->config->get('verbose'); 641 $output = ''; 642 if (!file_exists($cache_dir) || !is_dir($cache_dir)) { 643 return $this->raiseError("$cache_dir does not exist or is not a directory"); 644 } 645 if (!($dp = @opendir($cache_dir))) { 646 return $this->raiseError("opendir($cache_dir) failed: $php_errormsg"); 647 } 648 if ($verbose >= 1) { 649 $output .= "reading directory $cache_dir\n"; 650 } 651 $num = 0; 652 while ($ent = readdir($dp)) { 653 if (preg_match('/^xmlrpc_cache_[a-z0-9]{32}$/', $ent) || 654 preg_match('/rest.cache(file|id)$/', $ent)) { 655 $path = $cache_dir . DIRECTORY_SEPARATOR . $ent; 656 if (file_exists($path)) { 657 $ok = @unlink($path); 658 } else { 659 $ok = false; 660 $php_errormsg = ''; 661 } 662 if ($ok) { 663 if ($verbose >= 2) { 664 $output .= "deleted $path\n"; 665 } 666 $num++; 667 } elseif ($verbose >= 1) { 668 $output .= "failed to delete $path $php_errormsg\n"; 669 } 670 } 671 } 672 closedir($dp); 673 if ($verbose >= 1) { 674 $output .= "$num cache entries cleared\n"; 675 } 676 $this->ui->outputData(rtrim($output), $command); 677 return $num; 678 } 679 680 // }}} 681 } 682 683 ?>
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 |