[5146] | 1 | <?php |
---|
| 2 | /** |
---|
| 3 | * PEAR_Common, the base class for the PEAR Installer |
---|
| 4 | * |
---|
| 5 | * PHP versions 4 and 5 |
---|
| 6 | * |
---|
| 7 | * @category pear |
---|
| 8 | * @package PEAR |
---|
| 9 | * @author Stig Bakken <ssb@php.net> |
---|
| 10 | * @author Tomas V. V. Cox <cox@idecnet.com> |
---|
| 11 | * @author Greg Beaver <cellog@php.net> |
---|
| 12 | * @copyright 1997-2009 The Authors |
---|
| 13 | * @license http://opensource.org/licenses/bsd-license.php New BSD License |
---|
| 14 | * @version CVS: $Id: Common.php 313023 2011-07-06 19:17:11Z dufuz $ |
---|
| 15 | * @link http://pear.php.net/package/PEAR |
---|
| 16 | * @since File available since Release 0.1.0 |
---|
| 17 | * @deprecated File deprecated since Release 1.4.0a1 |
---|
| 18 | */ |
---|
| 19 | |
---|
| 20 | /** |
---|
| 21 | * Include error handling |
---|
| 22 | */ |
---|
| 23 | require_once 'PEAR.php'; |
---|
| 24 | |
---|
| 25 | /** |
---|
| 26 | * PEAR_Common error when an invalid PHP file is passed to PEAR_Common::analyzeSourceCode() |
---|
| 27 | */ |
---|
| 28 | define('PEAR_COMMON_ERROR_INVALIDPHP', 1); |
---|
| 29 | define('_PEAR_COMMON_PACKAGE_NAME_PREG', '[A-Za-z][a-zA-Z0-9_]+'); |
---|
| 30 | define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/'); |
---|
| 31 | |
---|
| 32 | // this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1 |
---|
| 33 | define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?'); |
---|
| 34 | define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '\\z/i'); |
---|
| 35 | |
---|
| 36 | // XXX far from perfect :-) |
---|
| 37 | define('_PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '(' . _PEAR_COMMON_PACKAGE_NAME_PREG . |
---|
| 38 | ')(-([.0-9a-zA-Z]+))?'); |
---|
| 39 | define('PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_PACKAGE_DOWNLOAD_PREG . |
---|
| 40 | '\\z/'); |
---|
| 41 | |
---|
| 42 | define('_PEAR_CHANNELS_NAME_PREG', '[A-Za-z][a-zA-Z0-9\.]+'); |
---|
| 43 | define('PEAR_CHANNELS_NAME_PREG', '/^' . _PEAR_CHANNELS_NAME_PREG . '\\z/'); |
---|
| 44 | |
---|
| 45 | // this should allow any dns or IP address, plus a path - NO UNDERSCORES ALLOWED |
---|
| 46 | define('_PEAR_CHANNELS_SERVER_PREG', '[a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*(\/[a-zA-Z0-9\-]+)*'); |
---|
| 47 | define('PEAR_CHANNELS_SERVER_PREG', '/^' . _PEAR_CHANNELS_SERVER_PREG . '\\z/i'); |
---|
| 48 | |
---|
| 49 | define('_PEAR_CHANNELS_PACKAGE_PREG', '(' ._PEAR_CHANNELS_SERVER_PREG . ')\/(' |
---|
| 50 | . _PEAR_COMMON_PACKAGE_NAME_PREG . ')'); |
---|
| 51 | define('PEAR_CHANNELS_PACKAGE_PREG', '/^' . _PEAR_CHANNELS_PACKAGE_PREG . '\\z/i'); |
---|
| 52 | |
---|
| 53 | define('_PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '(' . _PEAR_CHANNELS_NAME_PREG . ')::(' |
---|
| 54 | . _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?'); |
---|
| 55 | define('PEAR_COMMON_CHANNEL_DOWNLOAD_PREG', '/^' . _PEAR_COMMON_CHANNEL_DOWNLOAD_PREG . '\\z/'); |
---|
| 56 | |
---|
| 57 | /** |
---|
| 58 | * List of temporary files and directories registered by |
---|
| 59 | * PEAR_Common::addTempFile(). |
---|
| 60 | * @var array |
---|
| 61 | */ |
---|
| 62 | $GLOBALS['_PEAR_Common_tempfiles'] = array(); |
---|
| 63 | |
---|
| 64 | /** |
---|
| 65 | * Valid maintainer roles |
---|
| 66 | * @var array |
---|
| 67 | */ |
---|
| 68 | $GLOBALS['_PEAR_Common_maintainer_roles'] = array('lead','developer','contributor','helper'); |
---|
| 69 | |
---|
| 70 | /** |
---|
| 71 | * Valid release states |
---|
| 72 | * @var array |
---|
| 73 | */ |
---|
| 74 | $GLOBALS['_PEAR_Common_release_states'] = array('alpha','beta','stable','snapshot','devel'); |
---|
| 75 | |
---|
| 76 | /** |
---|
| 77 | * Valid dependency types |
---|
| 78 | * @var array |
---|
| 79 | */ |
---|
| 80 | $GLOBALS['_PEAR_Common_dependency_types'] = array('pkg','ext','php','prog','ldlib','rtlib','os','websrv','sapi'); |
---|
| 81 | |
---|
| 82 | /** |
---|
| 83 | * Valid dependency relations |
---|
| 84 | * @var array |
---|
| 85 | */ |
---|
| 86 | $GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not', 'ne'); |
---|
| 87 | |
---|
| 88 | /** |
---|
| 89 | * Valid file roles |
---|
| 90 | * @var array |
---|
| 91 | */ |
---|
| 92 | $GLOBALS['_PEAR_Common_file_roles'] = array('php','ext','test','doc','data','src','script'); |
---|
| 93 | |
---|
| 94 | /** |
---|
| 95 | * Valid replacement types |
---|
| 96 | * @var array |
---|
| 97 | */ |
---|
| 98 | $GLOBALS['_PEAR_Common_replacement_types'] = array('php-const', 'pear-config', 'package-info'); |
---|
| 99 | |
---|
| 100 | /** |
---|
| 101 | * Valid "provide" types |
---|
| 102 | * @var array |
---|
| 103 | */ |
---|
| 104 | $GLOBALS['_PEAR_Common_provide_types'] = array('ext', 'prog', 'class', 'function', 'feature', 'api'); |
---|
| 105 | |
---|
| 106 | /** |
---|
| 107 | * Valid "provide" types |
---|
| 108 | * @var array |
---|
| 109 | */ |
---|
| 110 | $GLOBALS['_PEAR_Common_script_phases'] = array('pre-install', 'post-install', 'pre-uninstall', 'post-uninstall', 'pre-build', 'post-build', 'pre-configure', 'post-configure', 'pre-setup', 'post-setup'); |
---|
| 111 | |
---|
| 112 | /** |
---|
| 113 | * Class providing common functionality for PEAR administration classes. |
---|
| 114 | * @category pear |
---|
| 115 | * @package PEAR |
---|
| 116 | * @author Stig Bakken <ssb@php.net> |
---|
| 117 | * @author Tomas V. V. Cox <cox@idecnet.com> |
---|
| 118 | * @author Greg Beaver <cellog@php.net> |
---|
| 119 | * @copyright 1997-2009 The Authors |
---|
| 120 | * @license http://opensource.org/licenses/bsd-license.php New BSD License |
---|
| 121 | * @version Release: 1.9.4 |
---|
| 122 | * @link http://pear.php.net/package/PEAR |
---|
| 123 | * @since Class available since Release 1.4.0a1 |
---|
| 124 | * @deprecated This class will disappear, and its components will be spread |
---|
| 125 | * into smaller classes, like the AT&T breakup, as of Release 1.4.0a1 |
---|
| 126 | */ |
---|
| 127 | class PEAR_Common extends PEAR |
---|
| 128 | { |
---|
| 129 | /** |
---|
| 130 | * User Interface object (PEAR_Frontend_* class). If null, |
---|
| 131 | * the log() method uses print. |
---|
| 132 | * @var object |
---|
| 133 | */ |
---|
| 134 | var $ui = null; |
---|
| 135 | |
---|
| 136 | /** |
---|
| 137 | * Configuration object (PEAR_Config). |
---|
| 138 | * @var PEAR_Config |
---|
| 139 | */ |
---|
| 140 | var $config = null; |
---|
| 141 | |
---|
| 142 | /** stack of elements, gives some sort of XML context */ |
---|
| 143 | var $element_stack = array(); |
---|
| 144 | |
---|
| 145 | /** name of currently parsed XML element */ |
---|
| 146 | var $current_element; |
---|
| 147 | |
---|
| 148 | /** array of attributes of the currently parsed XML element */ |
---|
| 149 | var $current_attributes = array(); |
---|
| 150 | |
---|
| 151 | /** assoc with information about a package */ |
---|
| 152 | var $pkginfo = array(); |
---|
| 153 | |
---|
| 154 | var $current_path = null; |
---|
| 155 | |
---|
| 156 | /** |
---|
| 157 | * Flag variable used to mark a valid package file |
---|
| 158 | * @var boolean |
---|
| 159 | * @access private |
---|
| 160 | */ |
---|
| 161 | var $_validPackageFile; |
---|
| 162 | |
---|
| 163 | /** |
---|
| 164 | * PEAR_Common constructor |
---|
| 165 | * |
---|
| 166 | * @access public |
---|
| 167 | */ |
---|
| 168 | function PEAR_Common() |
---|
| 169 | { |
---|
| 170 | parent::PEAR(); |
---|
| 171 | $this->config = &PEAR_Config::singleton(); |
---|
| 172 | $this->debug = $this->config->get('verbose'); |
---|
| 173 | } |
---|
| 174 | |
---|
| 175 | /** |
---|
| 176 | * PEAR_Common destructor |
---|
| 177 | * |
---|
| 178 | * @access private |
---|
| 179 | */ |
---|
| 180 | function _PEAR_Common() |
---|
| 181 | { |
---|
| 182 | // doesn't work due to bug #14744 |
---|
| 183 | //$tempfiles = $this->_tempfiles; |
---|
| 184 | $tempfiles =& $GLOBALS['_PEAR_Common_tempfiles']; |
---|
| 185 | while ($file = array_shift($tempfiles)) { |
---|
| 186 | if (@is_dir($file)) { |
---|
| 187 | if (!class_exists('System')) { |
---|
| 188 | require_once 'System.php'; |
---|
| 189 | } |
---|
| 190 | |
---|
| 191 | System::rm(array('-rf', $file)); |
---|
| 192 | } elseif (file_exists($file)) { |
---|
| 193 | unlink($file); |
---|
| 194 | } |
---|
| 195 | } |
---|
| 196 | } |
---|
| 197 | |
---|
| 198 | /** |
---|
| 199 | * Register a temporary file or directory. When the destructor is |
---|
| 200 | * executed, all registered temporary files and directories are |
---|
| 201 | * removed. |
---|
| 202 | * |
---|
| 203 | * @param string $file name of file or directory |
---|
| 204 | * |
---|
| 205 | * @return void |
---|
| 206 | * |
---|
| 207 | * @access public |
---|
| 208 | */ |
---|
| 209 | function addTempFile($file) |
---|
| 210 | { |
---|
| 211 | if (!class_exists('PEAR_Frontend')) { |
---|
| 212 | require_once 'PEAR/Frontend.php'; |
---|
| 213 | } |
---|
| 214 | PEAR_Frontend::addTempFile($file); |
---|
| 215 | } |
---|
| 216 | |
---|
| 217 | /** |
---|
| 218 | * Wrapper to System::mkDir(), creates a directory as well as |
---|
| 219 | * any necessary parent directories. |
---|
| 220 | * |
---|
| 221 | * @param string $dir directory name |
---|
| 222 | * |
---|
| 223 | * @return bool TRUE on success, or a PEAR error |
---|
| 224 | * |
---|
| 225 | * @access public |
---|
| 226 | */ |
---|
| 227 | function mkDirHier($dir) |
---|
| 228 | { |
---|
| 229 | // Only used in Installer - move it there ? |
---|
| 230 | $this->log(2, "+ create dir $dir"); |
---|
| 231 | if (!class_exists('System')) { |
---|
| 232 | require_once 'System.php'; |
---|
| 233 | } |
---|
| 234 | return System::mkDir(array('-p', $dir)); |
---|
| 235 | } |
---|
| 236 | |
---|
| 237 | /** |
---|
| 238 | * Logging method. |
---|
| 239 | * |
---|
| 240 | * @param int $level log level (0 is quiet, higher is noisier) |
---|
| 241 | * @param string $msg message to write to the log |
---|
| 242 | * |
---|
| 243 | * @return void |
---|
| 244 | * |
---|
| 245 | * @access public |
---|
| 246 | * @static |
---|
| 247 | */ |
---|
| 248 | function log($level, $msg, $append_crlf = true) |
---|
| 249 | { |
---|
| 250 | if ($this->debug >= $level) { |
---|
| 251 | if (!class_exists('PEAR_Frontend')) { |
---|
| 252 | require_once 'PEAR/Frontend.php'; |
---|
| 253 | } |
---|
| 254 | |
---|
| 255 | $ui = &PEAR_Frontend::singleton(); |
---|
| 256 | if (is_a($ui, 'PEAR_Frontend')) { |
---|
| 257 | $ui->log($msg, $append_crlf); |
---|
| 258 | } else { |
---|
| 259 | print "$msg\n"; |
---|
| 260 | } |
---|
| 261 | } |
---|
| 262 | } |
---|
| 263 | |
---|
| 264 | /** |
---|
| 265 | * Create and register a temporary directory. |
---|
| 266 | * |
---|
| 267 | * @param string $tmpdir (optional) Directory to use as tmpdir. |
---|
| 268 | * Will use system defaults (for example |
---|
| 269 | * /tmp or c:\windows\temp) if not specified |
---|
| 270 | * |
---|
| 271 | * @return string name of created directory |
---|
| 272 | * |
---|
| 273 | * @access public |
---|
| 274 | */ |
---|
| 275 | function mkTempDir($tmpdir = '') |
---|
| 276 | { |
---|
| 277 | $topt = $tmpdir ? array('-t', $tmpdir) : array(); |
---|
| 278 | $topt = array_merge($topt, array('-d', 'pear')); |
---|
| 279 | if (!class_exists('System')) { |
---|
| 280 | require_once 'System.php'; |
---|
| 281 | } |
---|
| 282 | |
---|
| 283 | if (!$tmpdir = System::mktemp($topt)) { |
---|
| 284 | return false; |
---|
| 285 | } |
---|
| 286 | |
---|
| 287 | $this->addTempFile($tmpdir); |
---|
| 288 | return $tmpdir; |
---|
| 289 | } |
---|
| 290 | |
---|
| 291 | /** |
---|
| 292 | * Set object that represents the frontend to be used. |
---|
| 293 | * |
---|
| 294 | * @param object Reference of the frontend object |
---|
| 295 | * @return void |
---|
| 296 | * @access public |
---|
| 297 | */ |
---|
| 298 | function setFrontendObject(&$ui) |
---|
| 299 | { |
---|
| 300 | $this->ui = &$ui; |
---|
| 301 | } |
---|
| 302 | |
---|
| 303 | /** |
---|
| 304 | * Return an array containing all of the states that are more stable than |
---|
| 305 | * or equal to the passed in state |
---|
| 306 | * |
---|
| 307 | * @param string Release state |
---|
| 308 | * @param boolean Determines whether to include $state in the list |
---|
| 309 | * @return false|array False if $state is not a valid release state |
---|
| 310 | */ |
---|
| 311 | function betterStates($state, $include = false) |
---|
| 312 | { |
---|
| 313 | static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable'); |
---|
| 314 | $i = array_search($state, $states); |
---|
| 315 | if ($i === false) { |
---|
| 316 | return false; |
---|
| 317 | } |
---|
| 318 | if ($include) { |
---|
| 319 | $i--; |
---|
| 320 | } |
---|
| 321 | return array_slice($states, $i + 1); |
---|
| 322 | } |
---|
| 323 | |
---|
| 324 | /** |
---|
| 325 | * Get the valid roles for a PEAR package maintainer |
---|
| 326 | * |
---|
| 327 | * @return array |
---|
| 328 | * @static |
---|
| 329 | */ |
---|
| 330 | function getUserRoles() |
---|
| 331 | { |
---|
| 332 | return $GLOBALS['_PEAR_Common_maintainer_roles']; |
---|
| 333 | } |
---|
| 334 | |
---|
| 335 | /** |
---|
| 336 | * Get the valid package release states of packages |
---|
| 337 | * |
---|
| 338 | * @return array |
---|
| 339 | * @static |
---|
| 340 | */ |
---|
| 341 | function getReleaseStates() |
---|
| 342 | { |
---|
| 343 | return $GLOBALS['_PEAR_Common_release_states']; |
---|
| 344 | } |
---|
| 345 | |
---|
| 346 | /** |
---|
| 347 | * Get the implemented dependency types (php, ext, pkg etc.) |
---|
| 348 | * |
---|
| 349 | * @return array |
---|
| 350 | * @static |
---|
| 351 | */ |
---|
| 352 | function getDependencyTypes() |
---|
| 353 | { |
---|
| 354 | return $GLOBALS['_PEAR_Common_dependency_types']; |
---|
| 355 | } |
---|
| 356 | |
---|
| 357 | /** |
---|
| 358 | * Get the implemented dependency relations (has, lt, ge etc.) |
---|
| 359 | * |
---|
| 360 | * @return array |
---|
| 361 | * @static |
---|
| 362 | */ |
---|
| 363 | function getDependencyRelations() |
---|
| 364 | { |
---|
| 365 | return $GLOBALS['_PEAR_Common_dependency_relations']; |
---|
| 366 | } |
---|
| 367 | |
---|
| 368 | /** |
---|
| 369 | * Get the implemented file roles |
---|
| 370 | * |
---|
| 371 | * @return array |
---|
| 372 | * @static |
---|
| 373 | */ |
---|
| 374 | function getFileRoles() |
---|
| 375 | { |
---|
| 376 | return $GLOBALS['_PEAR_Common_file_roles']; |
---|
| 377 | } |
---|
| 378 | |
---|
| 379 | /** |
---|
| 380 | * Get the implemented file replacement types in |
---|
| 381 | * |
---|
| 382 | * @return array |
---|
| 383 | * @static |
---|
| 384 | */ |
---|
| 385 | function getReplacementTypes() |
---|
| 386 | { |
---|
| 387 | return $GLOBALS['_PEAR_Common_replacement_types']; |
---|
| 388 | } |
---|
| 389 | |
---|
| 390 | /** |
---|
| 391 | * Get the implemented file replacement types in |
---|
| 392 | * |
---|
| 393 | * @return array |
---|
| 394 | * @static |
---|
| 395 | */ |
---|
| 396 | function getProvideTypes() |
---|
| 397 | { |
---|
| 398 | return $GLOBALS['_PEAR_Common_provide_types']; |
---|
| 399 | } |
---|
| 400 | |
---|
| 401 | /** |
---|
| 402 | * Get the implemented file replacement types in |
---|
| 403 | * |
---|
| 404 | * @return array |
---|
| 405 | * @static |
---|
| 406 | */ |
---|
| 407 | function getScriptPhases() |
---|
| 408 | { |
---|
| 409 | return $GLOBALS['_PEAR_Common_script_phases']; |
---|
| 410 | } |
---|
| 411 | |
---|
| 412 | /** |
---|
| 413 | * Test whether a string contains a valid package name. |
---|
| 414 | * |
---|
| 415 | * @param string $name the package name to test |
---|
| 416 | * |
---|
| 417 | * @return bool |
---|
| 418 | * |
---|
| 419 | * @access public |
---|
| 420 | */ |
---|
| 421 | function validPackageName($name) |
---|
| 422 | { |
---|
| 423 | return (bool)preg_match(PEAR_COMMON_PACKAGE_NAME_PREG, $name); |
---|
| 424 | } |
---|
| 425 | |
---|
| 426 | /** |
---|
| 427 | * Test whether a string contains a valid package version. |
---|
| 428 | * |
---|
| 429 | * @param string $ver the package version to test |
---|
| 430 | * |
---|
| 431 | * @return bool |
---|
| 432 | * |
---|
| 433 | * @access public |
---|
| 434 | */ |
---|
| 435 | function validPackageVersion($ver) |
---|
| 436 | { |
---|
| 437 | return (bool)preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver); |
---|
| 438 | } |
---|
| 439 | |
---|
| 440 | /** |
---|
| 441 | * @param string $path relative or absolute include path |
---|
| 442 | * @return boolean |
---|
| 443 | * @static |
---|
| 444 | */ |
---|
| 445 | function isIncludeable($path) |
---|
| 446 | { |
---|
| 447 | if (file_exists($path) && is_readable($path)) { |
---|
| 448 | return true; |
---|
| 449 | } |
---|
| 450 | |
---|
| 451 | $ipath = explode(PATH_SEPARATOR, ini_get('include_path')); |
---|
| 452 | foreach ($ipath as $include) { |
---|
| 453 | $test = realpath($include . DIRECTORY_SEPARATOR . $path); |
---|
| 454 | if (file_exists($test) && is_readable($test)) { |
---|
| 455 | return true; |
---|
| 456 | } |
---|
| 457 | } |
---|
| 458 | |
---|
| 459 | return false; |
---|
| 460 | } |
---|
| 461 | |
---|
| 462 | function _postProcessChecks($pf) |
---|
| 463 | { |
---|
| 464 | if (!PEAR::isError($pf)) { |
---|
| 465 | return $this->_postProcessValidPackagexml($pf); |
---|
| 466 | } |
---|
| 467 | |
---|
| 468 | $errs = $pf->getUserinfo(); |
---|
| 469 | if (is_array($errs)) { |
---|
| 470 | foreach ($errs as $error) { |
---|
| 471 | $e = $this->raiseError($error['message'], $error['code'], null, null, $error); |
---|
| 472 | } |
---|
| 473 | } |
---|
| 474 | |
---|
| 475 | return $pf; |
---|
| 476 | } |
---|
| 477 | |
---|
| 478 | /** |
---|
| 479 | * Returns information about a package file. Expects the name of |
---|
| 480 | * a gzipped tar file as input. |
---|
| 481 | * |
---|
| 482 | * @param string $file name of .tgz file |
---|
| 483 | * |
---|
| 484 | * @return array array with package information |
---|
| 485 | * |
---|
| 486 | * @access public |
---|
| 487 | * @deprecated use PEAR_PackageFile->fromTgzFile() instead |
---|
| 488 | * |
---|
| 489 | */ |
---|
| 490 | function infoFromTgzFile($file) |
---|
| 491 | { |
---|
| 492 | $packagefile = &new PEAR_PackageFile($this->config); |
---|
| 493 | $pf = &$packagefile->fromTgzFile($file, PEAR_VALIDATE_NORMAL); |
---|
| 494 | return $this->_postProcessChecks($pf); |
---|
| 495 | } |
---|
| 496 | |
---|
| 497 | /** |
---|
| 498 | * Returns information about a package file. Expects the name of |
---|
| 499 | * a package xml file as input. |
---|
| 500 | * |
---|
| 501 | * @param string $descfile name of package xml file |
---|
| 502 | * |
---|
| 503 | * @return array array with package information |
---|
| 504 | * |
---|
| 505 | * @access public |
---|
| 506 | * @deprecated use PEAR_PackageFile->fromPackageFile() instead |
---|
| 507 | * |
---|
| 508 | */ |
---|
| 509 | function infoFromDescriptionFile($descfile) |
---|
| 510 | { |
---|
| 511 | $packagefile = &new PEAR_PackageFile($this->config); |
---|
| 512 | $pf = &$packagefile->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL); |
---|
| 513 | return $this->_postProcessChecks($pf); |
---|
| 514 | } |
---|
| 515 | |
---|
| 516 | /** |
---|
| 517 | * Returns information about a package file. Expects the contents |
---|
| 518 | * of a package xml file as input. |
---|
| 519 | * |
---|
| 520 | * @param string $data contents of package.xml file |
---|
| 521 | * |
---|
| 522 | * @return array array with package information |
---|
| 523 | * |
---|
| 524 | * @access public |
---|
| 525 | * @deprecated use PEAR_PackageFile->fromXmlstring() instead |
---|
| 526 | * |
---|
| 527 | */ |
---|
| 528 | function infoFromString($data) |
---|
| 529 | { |
---|
| 530 | $packagefile = &new PEAR_PackageFile($this->config); |
---|
| 531 | $pf = &$packagefile->fromXmlString($data, PEAR_VALIDATE_NORMAL, false); |
---|
| 532 | return $this->_postProcessChecks($pf); |
---|
| 533 | } |
---|
| 534 | |
---|
| 535 | /** |
---|
| 536 | * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 |
---|
| 537 | * @return array |
---|
| 538 | */ |
---|
| 539 | function _postProcessValidPackagexml(&$pf) |
---|
| 540 | { |
---|
| 541 | if (!is_a($pf, 'PEAR_PackageFile_v2')) { |
---|
| 542 | $this->pkginfo = $pf->toArray(); |
---|
| 543 | return $this->pkginfo; |
---|
| 544 | } |
---|
| 545 | |
---|
| 546 | // sort of make this into a package.xml 1.0-style array |
---|
| 547 | // changelog is not converted to old format. |
---|
| 548 | $arr = $pf->toArray(true); |
---|
| 549 | $arr = array_merge($arr, $arr['old']); |
---|
| 550 | unset($arr['old'], $arr['xsdversion'], $arr['contents'], $arr['compatible'], |
---|
| 551 | $arr['channel'], $arr['uri'], $arr['dependencies'], $arr['phprelease'], |
---|
| 552 | $arr['extsrcrelease'], $arr['zendextsrcrelease'], $arr['extbinrelease'], |
---|
| 553 | $arr['zendextbinrelease'], $arr['bundle'], $arr['lead'], $arr['developer'], |
---|
| 554 | $arr['helper'], $arr['contributor']); |
---|
| 555 | $arr['filelist'] = $pf->getFilelist(); |
---|
| 556 | $this->pkginfo = $arr; |
---|
| 557 | return $arr; |
---|
| 558 | } |
---|
| 559 | |
---|
| 560 | /** |
---|
| 561 | * Returns package information from different sources |
---|
| 562 | * |
---|
| 563 | * This method is able to extract information about a package |
---|
| 564 | * from a .tgz archive or from a XML package definition file. |
---|
| 565 | * |
---|
| 566 | * @access public |
---|
| 567 | * @param string Filename of the source ('package.xml', '<package>.tgz') |
---|
| 568 | * @return string |
---|
| 569 | * @deprecated use PEAR_PackageFile->fromAnyFile() instead |
---|
| 570 | */ |
---|
| 571 | function infoFromAny($info) |
---|
| 572 | { |
---|
| 573 | if (is_string($info) && file_exists($info)) { |
---|
| 574 | $packagefile = &new PEAR_PackageFile($this->config); |
---|
| 575 | $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL); |
---|
| 576 | if (PEAR::isError($pf)) { |
---|
| 577 | $errs = $pf->getUserinfo(); |
---|
| 578 | if (is_array($errs)) { |
---|
| 579 | foreach ($errs as $error) { |
---|
| 580 | $e = $this->raiseError($error['message'], $error['code'], null, null, $error); |
---|
| 581 | } |
---|
| 582 | } |
---|
| 583 | |
---|
| 584 | return $pf; |
---|
| 585 | } |
---|
| 586 | |
---|
| 587 | return $this->_postProcessValidPackagexml($pf); |
---|
| 588 | } |
---|
| 589 | |
---|
| 590 | return $info; |
---|
| 591 | } |
---|
| 592 | |
---|
| 593 | /** |
---|
| 594 | * Return an XML document based on the package info (as returned |
---|
| 595 | * by the PEAR_Common::infoFrom* methods). |
---|
| 596 | * |
---|
| 597 | * @param array $pkginfo package info |
---|
| 598 | * |
---|
| 599 | * @return string XML data |
---|
| 600 | * |
---|
| 601 | * @access public |
---|
| 602 | * @deprecated use a PEAR_PackageFile_v* object's generator instead |
---|
| 603 | */ |
---|
| 604 | function xmlFromInfo($pkginfo) |
---|
| 605 | { |
---|
| 606 | $config = &PEAR_Config::singleton(); |
---|
| 607 | $packagefile = &new PEAR_PackageFile($config); |
---|
| 608 | $pf = &$packagefile->fromArray($pkginfo); |
---|
| 609 | $gen = &$pf->getDefaultGenerator(); |
---|
| 610 | return $gen->toXml(PEAR_VALIDATE_PACKAGING); |
---|
| 611 | } |
---|
| 612 | |
---|
| 613 | /** |
---|
| 614 | * Validate XML package definition file. |
---|
| 615 | * |
---|
| 616 | * @param string $info Filename of the package archive or of the |
---|
| 617 | * package definition file |
---|
| 618 | * @param array $errors Array that will contain the errors |
---|
| 619 | * @param array $warnings Array that will contain the warnings |
---|
| 620 | * @param string $dir_prefix (optional) directory where source files |
---|
| 621 | * may be found, or empty if they are not available |
---|
| 622 | * @access public |
---|
| 623 | * @return boolean |
---|
| 624 | * @deprecated use the validation of PEAR_PackageFile objects |
---|
| 625 | */ |
---|
| 626 | function validatePackageInfo($info, &$errors, &$warnings, $dir_prefix = '') |
---|
| 627 | { |
---|
| 628 | $config = &PEAR_Config::singleton(); |
---|
| 629 | $packagefile = &new PEAR_PackageFile($config); |
---|
| 630 | PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); |
---|
| 631 | if (strpos($info, '<?xml') !== false) { |
---|
| 632 | $pf = &$packagefile->fromXmlString($info, PEAR_VALIDATE_NORMAL, ''); |
---|
| 633 | } else { |
---|
| 634 | $pf = &$packagefile->fromAnyFile($info, PEAR_VALIDATE_NORMAL); |
---|
| 635 | } |
---|
| 636 | |
---|
| 637 | PEAR::staticPopErrorHandling(); |
---|
| 638 | if (PEAR::isError($pf)) { |
---|
| 639 | $errs = $pf->getUserinfo(); |
---|
| 640 | if (is_array($errs)) { |
---|
| 641 | foreach ($errs as $error) { |
---|
| 642 | if ($error['level'] == 'error') { |
---|
| 643 | $errors[] = $error['message']; |
---|
| 644 | } else { |
---|
| 645 | $warnings[] = $error['message']; |
---|
| 646 | } |
---|
| 647 | } |
---|
| 648 | } |
---|
| 649 | |
---|
| 650 | return false; |
---|
| 651 | } |
---|
| 652 | |
---|
| 653 | return true; |
---|
| 654 | } |
---|
| 655 | |
---|
| 656 | /** |
---|
| 657 | * Build a "provides" array from data returned by |
---|
| 658 | * analyzeSourceCode(). The format of the built array is like |
---|
| 659 | * this: |
---|
| 660 | * |
---|
| 661 | * array( |
---|
| 662 | * 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'), |
---|
| 663 | * ... |
---|
| 664 | * ) |
---|
| 665 | * |
---|
| 666 | * |
---|
| 667 | * @param array $srcinfo array with information about a source file |
---|
| 668 | * as returned by the analyzeSourceCode() method. |
---|
| 669 | * |
---|
| 670 | * @return void |
---|
| 671 | * |
---|
| 672 | * @access public |
---|
| 673 | * |
---|
| 674 | */ |
---|
| 675 | function buildProvidesArray($srcinfo) |
---|
| 676 | { |
---|
| 677 | $file = basename($srcinfo['source_file']); |
---|
| 678 | $pn = ''; |
---|
| 679 | if (isset($this->_packageName)) { |
---|
| 680 | $pn = $this->_packageName; |
---|
| 681 | } |
---|
| 682 | |
---|
| 683 | $pnl = strlen($pn); |
---|
| 684 | foreach ($srcinfo['declared_classes'] as $class) { |
---|
| 685 | $key = "class;$class"; |
---|
| 686 | if (isset($this->pkginfo['provides'][$key])) { |
---|
| 687 | continue; |
---|
| 688 | } |
---|
| 689 | |
---|
| 690 | $this->pkginfo['provides'][$key] = |
---|
| 691 | array('file'=> $file, 'type' => 'class', 'name' => $class); |
---|
| 692 | if (isset($srcinfo['inheritance'][$class])) { |
---|
| 693 | $this->pkginfo['provides'][$key]['extends'] = |
---|
| 694 | $srcinfo['inheritance'][$class]; |
---|
| 695 | } |
---|
| 696 | } |
---|
| 697 | |
---|
| 698 | foreach ($srcinfo['declared_methods'] as $class => $methods) { |
---|
| 699 | foreach ($methods as $method) { |
---|
| 700 | $function = "$class::$method"; |
---|
| 701 | $key = "function;$function"; |
---|
| 702 | if ($method{0} == '_' || !strcasecmp($method, $class) || |
---|
| 703 | isset($this->pkginfo['provides'][$key])) { |
---|
| 704 | continue; |
---|
| 705 | } |
---|
| 706 | |
---|
| 707 | $this->pkginfo['provides'][$key] = |
---|
| 708 | array('file'=> $file, 'type' => 'function', 'name' => $function); |
---|
| 709 | } |
---|
| 710 | } |
---|
| 711 | |
---|
| 712 | foreach ($srcinfo['declared_functions'] as $function) { |
---|
| 713 | $key = "function;$function"; |
---|
| 714 | if ($function{0} == '_' || isset($this->pkginfo['provides'][$key])) { |
---|
| 715 | continue; |
---|
| 716 | } |
---|
| 717 | |
---|
| 718 | if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) { |
---|
| 719 | $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\""; |
---|
| 720 | } |
---|
| 721 | |
---|
| 722 | $this->pkginfo['provides'][$key] = |
---|
| 723 | array('file'=> $file, 'type' => 'function', 'name' => $function); |
---|
| 724 | } |
---|
| 725 | } |
---|
| 726 | |
---|
| 727 | /** |
---|
| 728 | * Analyze the source code of the given PHP file |
---|
| 729 | * |
---|
| 730 | * @param string Filename of the PHP file |
---|
| 731 | * @return mixed |
---|
| 732 | * @access public |
---|
| 733 | */ |
---|
| 734 | function analyzeSourceCode($file) |
---|
| 735 | { |
---|
| 736 | if (!class_exists('PEAR_PackageFile_v2_Validator')) { |
---|
| 737 | require_once 'PEAR/PackageFile/v2/Validator.php'; |
---|
| 738 | } |
---|
| 739 | |
---|
| 740 | $a = new PEAR_PackageFile_v2_Validator; |
---|
| 741 | return $a->analyzeSourceCode($file); |
---|
| 742 | } |
---|
| 743 | |
---|
| 744 | function detectDependencies($any, $status_callback = null) |
---|
| 745 | { |
---|
| 746 | if (!function_exists("token_get_all")) { |
---|
| 747 | return false; |
---|
| 748 | } |
---|
| 749 | |
---|
| 750 | if (PEAR::isError($info = $this->infoFromAny($any))) { |
---|
| 751 | return $this->raiseError($info); |
---|
| 752 | } |
---|
| 753 | |
---|
| 754 | if (!is_array($info)) { |
---|
| 755 | return false; |
---|
| 756 | } |
---|
| 757 | |
---|
| 758 | $deps = array(); |
---|
| 759 | $used_c = $decl_c = $decl_f = $decl_m = array(); |
---|
| 760 | foreach ($info['filelist'] as $file => $fa) { |
---|
| 761 | $tmp = $this->analyzeSourceCode($file); |
---|
| 762 | $used_c = @array_merge($used_c, $tmp['used_classes']); |
---|
| 763 | $decl_c = @array_merge($decl_c, $tmp['declared_classes']); |
---|
| 764 | $decl_f = @array_merge($decl_f, $tmp['declared_functions']); |
---|
| 765 | $decl_m = @array_merge($decl_m, $tmp['declared_methods']); |
---|
| 766 | $inheri = @array_merge($inheri, $tmp['inheritance']); |
---|
| 767 | } |
---|
| 768 | |
---|
| 769 | $used_c = array_unique($used_c); |
---|
| 770 | $decl_c = array_unique($decl_c); |
---|
| 771 | $undecl_c = array_diff($used_c, $decl_c); |
---|
| 772 | |
---|
| 773 | return array('used_classes' => $used_c, |
---|
| 774 | 'declared_classes' => $decl_c, |
---|
| 775 | 'declared_methods' => $decl_m, |
---|
| 776 | 'declared_functions' => $decl_f, |
---|
| 777 | 'undeclared_classes' => $undecl_c, |
---|
| 778 | 'inheritance' => $inheri, |
---|
| 779 | ); |
---|
| 780 | } |
---|
| 781 | |
---|
| 782 | /** |
---|
| 783 | * Download a file through HTTP. Considers suggested file name in |
---|
| 784 | * Content-disposition: header and can run a callback function for |
---|
| 785 | * different events. The callback will be called with two |
---|
| 786 | * parameters: the callback type, and parameters. The implemented |
---|
| 787 | * callback types are: |
---|
| 788 | * |
---|
| 789 | * 'setup' called at the very beginning, parameter is a UI object |
---|
| 790 | * that should be used for all output |
---|
| 791 | * 'message' the parameter is a string with an informational message |
---|
| 792 | * 'saveas' may be used to save with a different file name, the |
---|
| 793 | * parameter is the filename that is about to be used. |
---|
| 794 | * If a 'saveas' callback returns a non-empty string, |
---|
| 795 | * that file name will be used as the filename instead. |
---|
| 796 | * Note that $save_dir will not be affected by this, only |
---|
| 797 | * the basename of the file. |
---|
| 798 | * 'start' download is starting, parameter is number of bytes |
---|
| 799 | * that are expected, or -1 if unknown |
---|
| 800 | * 'bytesread' parameter is the number of bytes read so far |
---|
| 801 | * 'done' download is complete, parameter is the total number |
---|
| 802 | * of bytes read |
---|
| 803 | * 'connfailed' if the TCP connection fails, this callback is called |
---|
| 804 | * with array(host,port,errno,errmsg) |
---|
| 805 | * 'writefailed' if writing to disk fails, this callback is called |
---|
| 806 | * with array(destfile,errmsg) |
---|
| 807 | * |
---|
| 808 | * If an HTTP proxy has been configured (http_proxy PEAR_Config |
---|
| 809 | * setting), the proxy will be used. |
---|
| 810 | * |
---|
| 811 | * @param string $url the URL to download |
---|
| 812 | * @param object $ui PEAR_Frontend_* instance |
---|
| 813 | * @param object $config PEAR_Config instance |
---|
| 814 | * @param string $save_dir (optional) directory to save file in |
---|
| 815 | * @param mixed $callback (optional) function/method to call for status |
---|
| 816 | * updates |
---|
| 817 | * |
---|
| 818 | * @return string Returns the full path of the downloaded file or a PEAR |
---|
| 819 | * error on failure. If the error is caused by |
---|
| 820 | * socket-related errors, the error object will |
---|
| 821 | * have the fsockopen error code available through |
---|
| 822 | * getCode(). |
---|
| 823 | * |
---|
| 824 | * @access public |
---|
| 825 | * @deprecated in favor of PEAR_Downloader::downloadHttp() |
---|
| 826 | */ |
---|
| 827 | function downloadHttp($url, &$ui, $save_dir = '.', $callback = null) |
---|
| 828 | { |
---|
| 829 | if (!class_exists('PEAR_Downloader')) { |
---|
| 830 | require_once 'PEAR/Downloader.php'; |
---|
| 831 | } |
---|
| 832 | return PEAR_Downloader::downloadHttp($url, $ui, $save_dir, $callback); |
---|
| 833 | } |
---|
| 834 | } |
---|
| 835 | |
---|
| 836 | require_once 'PEAR/Config.php'; |
---|
| 837 | require_once 'PEAR/PackageFile.php'; |
---|