[ Index ] |
|
Code source de PHP PEAR 1.4.5 |
1 <?php 2 /** 3 * PEAR_ChannelFile, the channel handling class 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: ChannelFile.php,v 1.78 2006/10/31 02:54:40 cellog Exp $ 19 * @link http://pear.php.net/package/PEAR 20 * @since File available since Release 1.4.0a1 21 */ 22 23 /** 24 * Needed for error handling 25 */ 26 require_once 'PEAR/ErrorStack.php'; 27 require_once 'PEAR/XMLParser.php'; 28 require_once 'PEAR/Common.php'; 29 30 /** 31 * Error code if the channel.xml <channel> tag does not contain a valid version 32 */ 33 define('PEAR_CHANNELFILE_ERROR_NO_VERSION', 1); 34 /** 35 * Error code if the channel.xml <channel> tag version is not supported (version 1.0 is the only supported version, 36 * currently 37 */ 38 define('PEAR_CHANNELFILE_ERROR_INVALID_VERSION', 2); 39 40 /** 41 * Error code if parsing is attempted with no xml extension 42 */ 43 define('PEAR_CHANNELFILE_ERROR_NO_XML_EXT', 3); 44 45 /** 46 * Error code if creating the xml parser resource fails 47 */ 48 define('PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER', 4); 49 50 /** 51 * Error code used for all sax xml parsing errors 52 */ 53 define('PEAR_CHANNELFILE_ERROR_PARSER_ERROR', 5); 54 55 /**#@+ 56 * Validation errors 57 */ 58 /** 59 * Error code when channel name is missing 60 */ 61 define('PEAR_CHANNELFILE_ERROR_NO_NAME', 6); 62 /** 63 * Error code when channel name is invalid 64 */ 65 define('PEAR_CHANNELFILE_ERROR_INVALID_NAME', 7); 66 /** 67 * Error code when channel summary is missing 68 */ 69 define('PEAR_CHANNELFILE_ERROR_NO_SUMMARY', 8); 70 /** 71 * Error code when channel summary is multi-line 72 */ 73 define('PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY', 9); 74 /** 75 * Error code when channel server is missing for xmlrpc or soap protocol 76 */ 77 define('PEAR_CHANNELFILE_ERROR_NO_HOST', 10); 78 /** 79 * Error code when channel server is invalid for xmlrpc or soap protocol 80 */ 81 define('PEAR_CHANNELFILE_ERROR_INVALID_HOST', 11); 82 /** 83 * Error code when a mirror name is invalid 84 */ 85 define('PEAR_CHANNELFILE_ERROR_INVALID_MIRROR', 21); 86 /** 87 * Error code when a mirror type is invalid 88 */ 89 define('PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE', 22); 90 /** 91 * Error code when an attempt is made to generate xml, but the parsed content is invalid 92 */ 93 define('PEAR_CHANNELFILE_ERROR_INVALID', 23); 94 /** 95 * Error code when an empty package name validate regex is passed in 96 */ 97 define('PEAR_CHANNELFILE_ERROR_EMPTY_REGEX', 24); 98 /** 99 * Error code when a <function> tag has no version 100 */ 101 define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION', 25); 102 /** 103 * Error code when a <function> tag has no name 104 */ 105 define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME', 26); 106 /** 107 * Error code when a <validatepackage> tag has no name 108 */ 109 define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME', 27); 110 /** 111 * Error code when a <validatepackage> tag has no version attribute 112 */ 113 define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION', 28); 114 /** 115 * Error code when a mirror does not exist but is called for in one of the set* 116 * methods. 117 */ 118 define('PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND', 32); 119 /** 120 * Error code when a server port is not numeric 121 */ 122 define('PEAR_CHANNELFILE_ERROR_INVALID_PORT', 33); 123 /** 124 * Error code when <static> contains no version attribute 125 */ 126 define('PEAR_CHANNELFILE_ERROR_NO_STATICVERSION', 34); 127 /** 128 * Error code when <baseurl> contains no type attribute in a <rest> protocol definition 129 */ 130 define('PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE', 35); 131 /** 132 * Error code when a mirror is defined and the channel.xml represents the __uri pseudo-channel 133 */ 134 define('PEAR_CHANNELFILE_URI_CANT_MIRROR', 36); 135 /** 136 * Error code when ssl attribute is present and is not "yes" 137 */ 138 define('PEAR_CHANNELFILE_ERROR_INVALID_SSL', 37); 139 /**#@-*/ 140 141 /** 142 * Mirror types allowed. Currently only internet servers are recognized. 143 */ 144 $GLOBALS['_PEAR_CHANNELS_MIRROR_TYPES'] = array('server'); 145 146 147 /** 148 * The Channel handling class 149 * 150 * @category pear 151 * @package PEAR 152 * @author Greg Beaver <cellog@php.net> 153 * @copyright 1997-2006 The PHP Group 154 * @license http://www.php.net/license/3_0.txt PHP License 3.0 155 * @version Release: 1.5.0 156 * @link http://pear.php.net/package/PEAR 157 * @since Class available since Release 1.4.0a1 158 */ 159 class PEAR_ChannelFile { 160 /** 161 * @access private 162 * @var PEAR_ErrorStack 163 * @access private 164 */ 165 var $_stack; 166 167 /** 168 * Supported channel.xml versions, for parsing 169 * @var array 170 * @access private 171 */ 172 var $_supportedVersions = array('1.0'); 173 174 /** 175 * Parsed channel information 176 * @var array 177 * @access private 178 */ 179 var $_channelInfo; 180 181 /** 182 * index into the subchannels array, used for parsing xml 183 * @var int 184 * @access private 185 */ 186 var $_subchannelIndex; 187 188 /** 189 * index into the mirrors array, used for parsing xml 190 * @var int 191 * @access private 192 */ 193 var $_mirrorIndex; 194 195 /** 196 * Flag used to determine the validity of parsed content 197 * @var boolean 198 * @access private 199 */ 200 var $_isValid = false; 201 202 function PEAR_ChannelFile() 203 { 204 $this->_stack = &new PEAR_ErrorStack('PEAR_ChannelFile'); 205 $this->_stack->setErrorMessageTemplate($this->_getErrorMessage()); 206 $this->_isValid = false; 207 } 208 209 /** 210 * @return array 211 * @access protected 212 */ 213 function _getErrorMessage() 214 { 215 return 216 array( 217 PEAR_CHANNELFILE_ERROR_INVALID_VERSION => 218 'While parsing channel.xml, an invalid version number "%version% was passed in, expecting one of %versions%', 219 PEAR_CHANNELFILE_ERROR_NO_VERSION => 220 'No version number found in <channel> tag', 221 PEAR_CHANNELFILE_ERROR_NO_XML_EXT => 222 '%error%', 223 PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER => 224 'Unable to create XML parser', 225 PEAR_CHANNELFILE_ERROR_PARSER_ERROR => 226 '%error%', 227 PEAR_CHANNELFILE_ERROR_NO_NAME => 228 'Missing channel name', 229 PEAR_CHANNELFILE_ERROR_INVALID_NAME => 230 'Invalid channel %tag% "%name%"', 231 PEAR_CHANNELFILE_ERROR_NO_SUMMARY => 232 'Missing channel summary', 233 PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY => 234 'Channel summary should be on one line, but is multi-line', 235 PEAR_CHANNELFILE_ERROR_NO_HOST => 236 'Missing channel server for %type% server', 237 PEAR_CHANNELFILE_ERROR_INVALID_HOST => 238 'Server name "%server%" is invalid for %type% server', 239 PEAR_CHANNELFILE_ERROR_INVALID_MIRROR => 240 'Invalid mirror name "%name%", mirror type %type%', 241 PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE => 242 'Invalid mirror type "%type%"', 243 PEAR_CHANNELFILE_ERROR_INVALID => 244 'Cannot generate xml, contents are invalid', 245 PEAR_CHANNELFILE_ERROR_EMPTY_REGEX => 246 'packagenameregex cannot be empty', 247 PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION => 248 '%parent% %protocol% function has no version', 249 PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME => 250 '%parent% %protocol% function has no name', 251 PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE => 252 '%parent% rest baseurl has no type', 253 PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME => 254 'Validation package has no name in <validatepackage> tag', 255 PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION => 256 'Validation package "%package%" has no version', 257 PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND => 258 'Mirror "%mirror%" does not exist', 259 PEAR_CHANNELFILE_ERROR_INVALID_PORT => 260 'Port "%port%" must be numeric', 261 PEAR_CHANNELFILE_ERROR_NO_STATICVERSION => 262 '<static> tag must contain version attribute', 263 PEAR_CHANNELFILE_URI_CANT_MIRROR => 264 'The __uri pseudo-channel cannot have mirrors', 265 PEAR_CHANNELFILE_ERROR_INVALID_SSL => 266 '%server% has invalid ssl attribute "%ssl%" can only be yes or not present', 267 ); 268 } 269 270 /** 271 * @param string contents of package.xml file 272 * @return bool success of parsing 273 */ 274 function fromXmlString($data) 275 { 276 if (preg_match('/<channel\s+version="([0-9]+\.[0-9]+)"/', $data, $channelversion)) { 277 if (!in_array($channelversion[1], $this->_supportedVersions)) { 278 $this->_stack->push(PEAR_CHANNELFILE_ERROR_INVALID_VERSION, 'error', 279 array('version' => $channelversion[1])); 280 return false; 281 } 282 $parser = new PEAR_XMLParser; 283 $result = $parser->parse($data); 284 if ($result !== true) { 285 if ($result->getCode() == 1) { 286 $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_XML_EXT, 'error', 287 array('error' => $error)); 288 } else { 289 $this->_stack->push(PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER, 'error'); 290 } 291 return false; 292 } 293 $this->_channelInfo = $parser->getData(); 294 return true; 295 } else { 296 $this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_VERSION, 'error', array('xml' => $data)); 297 return false; 298 } 299 } 300 301 /** 302 * @return array 303 */ 304 function toArray() 305 { 306 if (!$this->_isValid && !$this->validate()) { 307 return false; 308 } 309 return $this->_channelInfo; 310 } 311 312 /** 313 * @param array 314 * @static 315 * @return PEAR_ChannelFile|false false if invalid 316 */ 317 function &fromArray($data, $compatibility = false, $stackClass = 'PEAR_ErrorStack') 318 { 319 $a = new PEAR_ChannelFile($compatibility, $stackClass); 320 $a->_fromArray($data); 321 if (!$a->validate()) { 322 $a = false; 323 return $a; 324 } 325 return $a; 326 } 327 328 /** 329 * Unlike {@link fromArray()} this does not do any validation 330 * @param array 331 * @static 332 * @return PEAR_ChannelFile 333 */ 334 function &fromArrayWithErrors($data, $compatibility = false, 335 $stackClass = 'PEAR_ErrorStack') 336 { 337 $a = new PEAR_ChannelFile($compatibility, $stackClass); 338 $a->_fromArray($data); 339 return $a; 340 } 341 342 /** 343 * @param array 344 * @access private 345 */ 346 function _fromArray($data) 347 { 348 $this->_channelInfo = $data; 349 } 350 351 /** 352 * Wrapper to {@link PEAR_ErrorStack::getErrors()} 353 * @param boolean determines whether to purge the error stack after retrieving 354 * @return array 355 */ 356 function getErrors($purge = false) 357 { 358 return $this->_stack->getErrors($purge); 359 } 360 361 /** 362 * Unindent given string (?) 363 * 364 * @param string $str The string that has to be unindented. 365 * @return string 366 * @access private 367 */ 368 function _unIndent($str) 369 { 370 // remove leading newlines 371 $str = preg_replace('/^[\r\n]+/', '', $str); 372 // find whitespace at the beginning of the first line 373 $indent_len = strspn($str, " \t"); 374 $indent = substr($str, 0, $indent_len); 375 $data = ''; 376 // remove the same amount of whitespace from following lines 377 foreach (explode("\n", $str) as $line) { 378 if (substr($line, 0, $indent_len) == $indent) { 379 $data .= substr($line, $indent_len) . "\n"; 380 } 381 } 382 return $data; 383 } 384 385 /** 386 * Parse a channel.xml file. Expects the name of 387 * a channel xml file as input. 388 * 389 * @param string $descfile name of channel xml file 390 * @return bool success of parsing 391 */ 392 function fromXmlFile($descfile) 393 { 394 if (!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) || 395 (!$fp = fopen($descfile, 'r'))) { 396 require_once 'PEAR.php'; 397 return PEAR::raiseError("Unable to open $descfile"); 398 } 399 400 // read the whole thing so we only get one cdata callback 401 // for each block of cdata 402 fclose($fp); 403 $data = file_get_contents($descfile); 404 return $this->fromXmlString($data); 405 } 406 407 /** 408 * Parse channel information from different sources 409 * 410 * This method is able to extract information about a channel 411 * from an .xml file or a string 412 * 413 * @access public 414 * @param string Filename of the source or the source itself 415 * @return bool 416 */ 417 function fromAny($info) 418 { 419 if (is_string($info) && file_exists($info) && strlen($info) < 255) { 420 $tmp = substr($info, -4); 421 if ($tmp == '.xml') { 422 $info = $this->fromXmlFile($info); 423 } else { 424 $fp = fopen($info, "r"); 425 $test = fread($fp, 5); 426 fclose($fp); 427 if ($test == "<?xml") { 428 $info = $this->fromXmlFile($info); 429 } 430 } 431 if (PEAR::isError($info)) { 432 require_once 'PEAR.php'; 433 return PEAR::raiseError($info); 434 } 435 } 436 if (is_string($info)) { 437 $info = $this->fromXmlString($info); 438 } 439 return $info; 440 } 441 442 /** 443 * Return an XML document based on previous parsing and modifications 444 * 445 * @return string XML data 446 * 447 * @access public 448 */ 449 function toXml() 450 { 451 if (!$this->_isValid && !$this->validate()) { 452 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID); 453 return false; 454 } 455 if (!isset($this->_channelInfo['attribs']['version'])) { 456 $this->_channelInfo['attribs']['version'] = '1.0'; 457 } 458 $channelInfo = $this->_channelInfo; 459 $ret = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"; 460 $ret .= "<channel version=\"" . 461 $channelInfo['attribs']['version'] . "\" xmlns=\"http://pear.php.net/channel-1.0\" 462 xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 463 xsi:schemaLocation=\"http://pear.php.net/dtd/channel-" 464 . $channelInfo['attribs']['version'] . " http://pear.php.net/dtd/channel-" . 465 $channelInfo['attribs']['version'] . ".xsd\"> 466 <name>$channelInfo[name]</name> 467 <summary>" . htmlspecialchars($channelInfo['summary'])."</summary> 468 "; 469 if (isset($channelInfo['suggestedalias'])) { 470 $ret .= ' <suggestedalias>' . $channelInfo['suggestedalias'] . "</suggestedalias>\n"; 471 } 472 if (isset($channelInfo['validatepackage'])) { 473 $ret .= ' <validatepackage version="' . 474 $channelInfo['validatepackage']['attribs']['version']. '">' . 475 htmlspecialchars($channelInfo['validatepackage']['_content']) . 476 "</validatepackage>\n"; 477 } 478 $ret .= " <servers>\n"; 479 $ret .= ' <primary'; 480 if (isset($channelInfo['servers']['primary']['attribs']['ssl'])) { 481 $ret .= ' ssl="' . $channelInfo['servers']['primary']['attribs']['ssl'] . '"'; 482 } 483 if (isset($channelInfo['servers']['primary']['attribs']['port'])) { 484 $ret .= ' port="' . $channelInfo['servers']['primary']['attribs']['port'] . '"'; 485 } 486 $ret .= ">\n"; 487 if (isset($channelInfo['servers']['primary']['xmlrpc'])) { 488 $ret .= $this->_makeXmlrpcXml($channelInfo['servers']['primary']['xmlrpc'], ' '); 489 } 490 if (isset($channelInfo['servers']['primary']['rest'])) { 491 $ret .= $this->_makeRestXml($channelInfo['servers']['primary']['rest'], ' '); 492 } 493 if (isset($channelInfo['servers']['primary']['soap'])) { 494 $ret .= $this->_makeSoapXml($channelInfo['servers']['primary']['soap'], ' '); 495 } 496 $ret .= " </primary>\n"; 497 if (isset($channelInfo['servers']['mirror'])) { 498 $ret .= $this->_makeMirrorsXml($channelInfo); 499 } 500 $ret .= " </servers>\n"; 501 $ret .= "</channel>"; 502 return str_replace("\r", "\n", str_replace("\r\n", "\n", $ret)); 503 } 504 505 /** 506 * Generate the <xmlrpc> tag 507 * @access private 508 */ 509 function _makeXmlrpcXml($info, $indent) 510 { 511 $ret = $indent . "<xmlrpc"; 512 if (isset($info['attribs']['path'])) { 513 $ret .= ' path="' . htmlspecialchars($info['attribs']['path']) . '"'; 514 } 515 $ret .= ">\n"; 516 $ret .= $this->_makeFunctionsXml($info['function'], "$indent "); 517 $ret .= $indent . "</xmlrpc>\n"; 518 return $ret; 519 } 520 521 /** 522 * Generate the <soap> tag 523 * @access private 524 */ 525 function _makeSoapXml($info, $indent) 526 { 527 $ret = $indent . "<soap"; 528 if (isset($info['attribs']['path'])) { 529 $ret .= ' path="' . htmlspecialchars($info['attribs']['path']) . '"'; 530 } 531 $ret .= ">\n"; 532 $ret .= $this->_makeFunctionsXml($info['function'], "$indent "); 533 $ret .= $indent . "</soap>\n"; 534 return $ret; 535 } 536 537 /** 538 * Generate the <rest> tag 539 * @access private 540 */ 541 function _makeRestXml($info, $indent) 542 { 543 $ret = $indent . "<rest>\n"; 544 if (!isset($info['baseurl'][0])) { 545 $info['baseurl'] = array($info['baseurl']); 546 } 547 foreach ($info['baseurl'] as $url) { 548 $ret .= "$indent <baseurl type=\"" . $url['attribs']['type'] . "\""; 549 $ret .= ">" . $url['_content'] . "</baseurl>\n"; 550 } 551 $ret .= $indent . "</rest>\n"; 552 return $ret; 553 } 554 555 /** 556 * Generate the <mirrors> tag 557 * @access private 558 */ 559 function _makeMirrorsXml($channelInfo) 560 { 561 $ret = ""; 562 if (!isset($channelInfo['servers']['mirror'][0])) { 563 $channelInfo['servers']['mirror'] = array($channelInfo['servers']['mirror']); 564 } 565 foreach ($channelInfo['servers']['mirror'] as $mirror) { 566 $ret .= ' <mirror host="' . $mirror['attribs']['host'] . '"'; 567 if (isset($mirror['attribs']['port'])) { 568 $ret .= ' port="' . $mirror['attribs']['port'] . '"'; 569 } 570 if (isset($mirror['attribs']['ssl'])) { 571 $ret .= ' ssl="' . $mirror['attribs']['ssl'] . '"'; 572 } 573 $ret .= ">\n"; 574 if (isset($mirror['xmlrpc']) || isset($mirror['soap'])) { 575 if (isset($mirror['xmlrpc'])) { 576 $ret .= $this->_makeXmlrpcXml($mirror['xmlrpc'], ' '); 577 } 578 if (isset($mirror['rest'])) { 579 $ret .= $this->_makeRestXml($mirror['rest'], ' '); 580 } 581 if (isset($mirror['soap'])) { 582 $ret .= $this->_makeSoapXml($mirror['soap'], ' '); 583 } 584 $ret .= " </mirror>\n"; 585 } else { 586 $ret .= "/>\n"; 587 } 588 } 589 return $ret; 590 } 591 592 /** 593 * Generate the <functions> tag 594 * @access private 595 */ 596 function _makeFunctionsXml($functions, $indent, $rest = false) 597 { 598 $ret = ''; 599 if (!isset($functions[0])) { 600 $functions = array($functions); 601 } 602 foreach ($functions as $function) { 603 $ret .= "$indent<function version=\"" . $function['attribs']['version'] . "\""; 604 if ($rest) { 605 $ret .= ' uri="' . $function['attribs']['uri'] . '"'; 606 } 607 $ret .= ">" . $function['_content'] . "</function>\n"; 608 } 609 return $ret; 610 } 611 612 /** 613 * Validation error. Also marks the object contents as invalid 614 * @param error code 615 * @param array error information 616 * @access private 617 */ 618 function _validateError($code, $params = array()) 619 { 620 $this->_stack->push($code, 'error', $params); 621 $this->_isValid = false; 622 } 623 624 /** 625 * Validation warning. Does not mark the object contents invalid. 626 * @param error code 627 * @param array error information 628 * @access private 629 */ 630 function _validateWarning($code, $params = array()) 631 { 632 $this->_stack->push($code, 'warning', $params); 633 } 634 635 /** 636 * Validate parsed file. 637 * 638 * @access public 639 * @return boolean 640 */ 641 function validate() 642 { 643 $this->_isValid = true; 644 $info = $this->_channelInfo; 645 if (empty($info['name'])) { 646 $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_NAME); 647 } elseif (!$this->validChannelServer($info['name'])) { 648 if ($info['name'] != '__uri') { 649 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, array('tag' => 'name', 650 'name' => $info['name'])); 651 } 652 } 653 if (empty($info['summary'])) { 654 $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY); 655 } elseif (strpos(trim($info['summary']), "\n") !== false) { 656 $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY, 657 array('summary' => $info['summary'])); 658 } 659 if (isset($info['suggestedalias'])) { 660 if (!$this->validChannelServer($info['suggestedalias'])) { 661 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, 662 array('tag' => 'suggestedalias', 'name' =>$info['suggestedalias'])); 663 } 664 } 665 if (isset($info['localalias'])) { 666 if (!$this->validChannelServer($info['localalias'])) { 667 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, 668 array('tag' => 'localalias', 'name' =>$info['localalias'])); 669 } 670 } 671 if (isset($info['validatepackage'])) { 672 if (!isset($info['validatepackage']['_content'])) { 673 $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME); 674 } 675 if (!isset($info['validatepackage']['attribs']['version'])) { 676 $content = isset($info['validatepackage']['_content']) ? 677 $info['validatepackage']['_content'] : 678 null; 679 $this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION, 680 array('package' => $content)); 681 } 682 } 683 if (isset($info['servers']['primary']['attribs']['port']) && 684 !is_numeric($info['servers']['primary']['attribs']['port'])) { 685 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_PORT, 686 array('port' => $info['servers']['primary']['attribs']['port'])); 687 } 688 if (isset($info['servers']['primary']['attribs']['ssl']) && 689 $info['servers']['primary']['attribs']['ssl'] != 'yes') { 690 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL, 691 array('ssl' => $info['servers']['primary']['attribs']['ssl'], 692 'server' => $info['name'])); 693 } 694 695 if (isset($info['servers']['primary']['xmlrpc']) && 696 isset($info['servers']['primary']['xmlrpc']['function'])) { 697 $this->_validateFunctions('xmlrpc', $info['servers']['primary']['xmlrpc']['function']); 698 } 699 if (isset($info['servers']['primary']['soap']) && 700 isset($info['servers']['primary']['soap']['function'])) { 701 $this->_validateFunctions('soap', $info['servers']['primary']['soap']['function']); 702 } 703 if (isset($info['servers']['primary']['rest']) && 704 isset($info['servers']['primary']['rest']['baseurl'])) { 705 $this->_validateFunctions('rest', $info['servers']['primary']['rest']['baseurl']); 706 } 707 if (isset($info['servers']['mirror'])) { 708 if ($this->_channelInfo['name'] == '__uri') { 709 $this->_validateError(PEAR_CHANNELFILE_URI_CANT_MIRROR); 710 } 711 if (!isset($info['servers']['mirror'][0])) { 712 $info['servers']['mirror'] = array($info['servers']['mirror']); 713 } 714 $i = 0; 715 foreach ($info['servers']['mirror'] as $mirror) { 716 if (!isset($mirror['attribs']['host'])) { 717 $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_HOST, 718 array('type' => 'mirror')); 719 } elseif (!$this->validChannelServer($mirror['attribs']['host'])) { 720 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_HOST, 721 array('server' => $mirror['attribs']['host'], 'type' => 'mirror')); 722 } 723 if (isset($mirror['attribs']['ssl']) && $mirror['attribs']['ssl'] != 'yes') { 724 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL, 725 array('ssl' => $info['ssl'], 'server' => $mirror['attribs']['host'])); 726 } 727 if (isset($mirror['xmlrpc'])) { 728 $this->_validateFunctions('xmlrpc', 729 $mirror['xmlrpc']['function'], $mirror['attribs']['host']); 730 } 731 if (isset($mirror['soap'])) { 732 $this->_validateFunctions('soap', $mirror['soap']['function'], 733 $mirror['attribs']['host']); 734 } 735 if (isset($mirror['rest'])) { 736 $this->_validateFunctions('rest', $mirror['rest']['baseurl'], 737 $mirror['attribs']['host']); 738 } 739 } 740 } 741 return $this->_isValid; 742 } 743 744 /** 745 * @param string xmlrpc or soap - protocol name this function applies to 746 * @param array the functions 747 * @param string the name of the parent element (mirror name, for instance) 748 */ 749 function _validateFunctions($protocol, $functions, $parent = '') 750 { 751 if (!isset($functions[0])) { 752 $functions = array($functions); 753 } 754 foreach ($functions as $function) { 755 if (!isset($function['_content']) || empty($function['_content'])) { 756 $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME, 757 array('parent' => $parent, 'protocol' => $protocol)); 758 } 759 if ($protocol == 'rest') { 760 if (!isset($function['attribs']['type']) || 761 empty($function['attribs']['type'])) { 762 $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_BASEURLTYPE, 763 array('parent' => $parent, 'protocol' => $protocol)); 764 } 765 } else { 766 if (!isset($function['attribs']['version']) || 767 empty($function['attribs']['version'])) { 768 $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION, 769 array('parent' => $parent, 'protocol' => $protocol)); 770 } 771 } 772 } 773 } 774 775 /** 776 * Test whether a string contains a valid channel server. 777 * @param string $ver the package version to test 778 * @return bool 779 */ 780 function validChannelServer($server) 781 { 782 if ($server == '__uri') { 783 return true; 784 } 785 return (bool) preg_match(PEAR_CHANNELS_SERVER_PREG, $server); 786 } 787 788 /** 789 * @return string|false 790 */ 791 function getName() 792 { 793 if (isset($this->_channelInfo['name'])) { 794 return $this->_channelInfo['name']; 795 } else { 796 return false; 797 } 798 } 799 800 /** 801 * @return string|false 802 */ 803 function getServer() 804 { 805 if (isset($this->_channelInfo['name'])) { 806 return $this->_channelInfo['name']; 807 } else { 808 return false; 809 } 810 } 811 812 /** 813 * @return int|80 port number to connect to 814 */ 815 function getPort($mirror = false) 816 { 817 if ($mirror) { 818 if ($mir = $this->getMirror($mirror)) { 819 if (isset($mir['attribs']['port'])) { 820 return $mir['attribs']['port']; 821 } else { 822 if ($this->getSSL($mirror)) { 823 return 443; 824 } 825 return 80; 826 } 827 } 828 return false; 829 } 830 if (isset($this->_channelInfo['servers']['primary']['attribs']['port'])) { 831 return $this->_channelInfo['servers']['primary']['attribs']['port']; 832 } 833 if ($this->getSSL()) { 834 return 443; 835 } 836 return 80; 837 } 838 839 /** 840 * @return bool Determines whether secure sockets layer (SSL) is used to connect to this channel 841 */ 842 function getSSL($mirror = false) 843 { 844 if ($mirror) { 845 if ($mir = $this->getMirror($mirror)) { 846 if (isset($mir['attribs']['ssl'])) { 847 return true; 848 } else { 849 return false; 850 } 851 } 852 return false; 853 } 854 if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) { 855 return true; 856 } 857 return false; 858 } 859 860 /** 861 * @return string|false 862 */ 863 function getSummary() 864 { 865 if (isset($this->_channelInfo['summary'])) { 866 return $this->_channelInfo['summary']; 867 } else { 868 return false; 869 } 870 } 871 872 /** 873 * @param string xmlrpc or soap 874 * @param string|false mirror name or false for primary server 875 */ 876 function getPath($protocol, $mirror = false) 877 { 878 if (!in_array($protocol, array('xmlrpc', 'soap'))) { 879 return false; 880 } 881 if ($mirror) { 882 if (!($mir = $this->getMirror($mirror))) { 883 return false; 884 } 885 if (isset($mir[$protocol]['attribs']['path'])) { 886 return $mir[$protocol]['attribs']['path']; 887 } else { 888 return $protocol . '.php'; 889 } 890 } elseif (isset($this->_channelInfo['servers']['primary'][$protocol]['attribs']['path'])) { 891 return $this->_channelInfo['servers']['primary'][$protocol]['attribs']['path']; 892 } 893 return $protocol . '.php'; 894 } 895 896 /** 897 * @param string protocol type (xmlrpc, soap) 898 * @param string Mirror name 899 * @return array|false 900 */ 901 function getFunctions($protocol, $mirror = false) 902 { 903 if ($this->getName() == '__uri') { 904 return false; 905 } 906 if ($protocol == 'rest') { 907 $function = 'baseurl'; 908 } else { 909 $function = 'function'; 910 } 911 if ($mirror) { 912 if ($mir = $this->getMirror($mirror)) { 913 if (isset($mir[$protocol][$function])) { 914 return $mir[$protocol][$function]; 915 } 916 } 917 return false; 918 } 919 if (isset($this->_channelInfo['servers']['primary'][$protocol][$function])) { 920 return $this->_channelInfo['servers']['primary'][$protocol][$function]; 921 } else { 922 return false; 923 } 924 } 925 926 /** 927 * @param string Protocol type 928 * @param string Function name (null to return the 929 * first protocol of the type requested) 930 * @param string Mirror name, if any 931 * @return array 932 */ 933 function getFunction($type, $name = null, $mirror = false) 934 { 935 $protocols = $this->getFunctions($type, $mirror); 936 if (!$protocols) { 937 return false; 938 } 939 foreach ($protocols as $protocol) { 940 if ($name === null) { 941 return $protocol; 942 } 943 if ($protocol['_content'] != $name) { 944 continue; 945 } 946 return $protocol; 947 } 948 return false; 949 } 950 951 /** 952 * @param string protocol type 953 * @param string protocol name 954 * @param string version 955 * @param string mirror name 956 * @return boolean 957 */ 958 function supports($type, $name = null, $mirror = false, $version = '1.0') 959 { 960 $protocols = $this->getFunctions($type, $mirror); 961 if (!$protocols) { 962 return false; 963 } 964 foreach ($protocols as $protocol) { 965 if ($protocol['attribs']['version'] != $version) { 966 continue; 967 } 968 if ($name === null) { 969 return true; 970 } 971 if ($protocol['_content'] != $name) { 972 continue; 973 } 974 return true; 975 } 976 return false; 977 } 978 979 /** 980 * Determines whether a channel supports Representational State Transfer (REST) protocols 981 * for retrieving channel information 982 * @param string 983 * @return bool 984 */ 985 function supportsREST($mirror = false) 986 { 987 if ($mirror == $this->_channelInfo['name']) { 988 $mirror = false; 989 } 990 if ($mirror) { 991 if ($mir = $this->getMirror($mirror)) { 992 return isset($mir['rest']); 993 } 994 return false; 995 } 996 return isset($this->_channelInfo['servers']['primary']['rest']); 997 } 998 999 /** 1000 * Get the URL to access a base resource. 1001 * 1002 * Hyperlinks in the returned xml will be used to retrieve the proper information 1003 * needed. This allows extreme extensibility and flexibility in implementation 1004 * @param string Resource Type to retrieve 1005 */ 1006 function getBaseURL($resourceType, $mirror = false) 1007 { 1008 if ($mirror == $this->_channelInfo['name']) { 1009 $mirror = false; 1010 } 1011 if ($mirror) { 1012 if ($mir = $this->getMirror($mirror)) { 1013 $rest = $mir['rest']; 1014 } else { 1015 return false; 1016 } 1017 $server = $mirror; 1018 } else { 1019 $rest = $this->_channelInfo['servers']['primary']['rest']; 1020 $server = $this->getServer(); 1021 } 1022 if (!isset($rest['baseurl'][0])) { 1023 $rest['baseurl'] = array($rest['baseurl']); 1024 } 1025 foreach ($rest['baseurl'] as $baseurl) { 1026 if (strtolower($baseurl['attribs']['type']) == strtolower($resourceType)) { 1027 return $baseurl['_content']; 1028 } 1029 } 1030 return false; 1031 } 1032 1033 /** 1034 * Since REST does not implement RPC, provide this as a logical wrapper around 1035 * resetFunctions for REST 1036 * @param string|false mirror name, if any 1037 */ 1038 function resetREST($mirror = false) 1039 { 1040 return $this->resetFunctions('rest', $mirror); 1041 } 1042 1043 /** 1044 * Empty all protocol definitions 1045 * @param string protocol type (xmlrpc, soap) 1046 * @param string|false mirror name, if any 1047 */ 1048 function resetFunctions($type, $mirror = false) 1049 { 1050 if ($mirror) { 1051 if (isset($this->_channelInfo['servers']['mirror'])) { 1052 $mirrors = $this->_channelInfo['servers']['mirror']; 1053 if (!isset($mirrors[0])) { 1054 $mirrors = array($mirrors); 1055 } 1056 foreach ($mirrors as $i => $mir) { 1057 if ($mir['attribs']['host'] == $mirror) { 1058 if (isset($this->_channelInfo['servers']['mirror'][$i][$type])) { 1059 unset($this->_channelInfo['servers']['mirror'][$i][$type]); 1060 } 1061 return true; 1062 } 1063 } 1064 return false; 1065 } else { 1066 return false; 1067 } 1068 } else { 1069 if (isset($this->_channelInfo['servers']['primary'][$type])) { 1070 unset($this->_channelInfo['servers']['primary'][$type]); 1071 } 1072 return true; 1073 } 1074 } 1075 1076 /** 1077 * Set a channel's protocols to the protocols supported by pearweb 1078 */ 1079 function setDefaultPEARProtocols($version = '1.0', $mirror = false) 1080 { 1081 switch ($version) { 1082 case '1.0' : 1083 $this->resetFunctions('xmlrpc', $mirror); 1084 $this->resetFunctions('soap', $mirror); 1085 $this->resetREST($mirror); 1086 $this->addFunction('xmlrpc', '1.0', 'logintest', $mirror); 1087 $this->addFunction('xmlrpc', '1.0', 'package.listLatestReleases', $mirror); 1088 $this->addFunction('xmlrpc', '1.0', 'package.listAll', $mirror); 1089 $this->addFunction('xmlrpc', '1.0', 'package.info', $mirror); 1090 $this->addFunction('xmlrpc', '1.0', 'package.getDownloadURL', $mirror); 1091 $this->addFunction('xmlrpc', '1.1', 'package.getDownloadURL', $mirror); 1092 $this->addFunction('xmlrpc', '1.0', 'package.getDepDownloadURL', $mirror); 1093 $this->addFunction('xmlrpc', '1.1', 'package.getDepDownloadURL', $mirror); 1094 $this->addFunction('xmlrpc', '1.0', 'package.search', $mirror); 1095 $this->addFunction('xmlrpc', '1.0', 'channel.listAll', $mirror); 1096 return true; 1097 break; 1098 default : 1099 return false; 1100 break; 1101 } 1102 } 1103 1104 /** 1105 * @return array 1106 */ 1107 function getMirrors() 1108 { 1109 if (isset($this->_channelInfo['servers']['mirror'])) { 1110 $mirrors = $this->_channelInfo['servers']['mirror']; 1111 if (!isset($mirrors[0])) { 1112 $mirrors = array($mirrors); 1113 } 1114 return $mirrors; 1115 } else { 1116 return array(); 1117 } 1118 } 1119 1120 /** 1121 * Get the unserialized XML representing a mirror 1122 * @return array|false 1123 */ 1124 function getMirror($server) 1125 { 1126 foreach ($this->getMirrors() as $mirror) { 1127 if ($mirror['attribs']['host'] == $server) { 1128 return $mirror; 1129 } 1130 } 1131 return false; 1132 } 1133 1134 /** 1135 * @param string 1136 * @return string|false 1137 * @error PEAR_CHANNELFILE_ERROR_NO_NAME 1138 * @error PEAR_CHANNELFILE_ERROR_INVALID_NAME 1139 */ 1140 function setName($name) 1141 { 1142 return $this->setServer($name); 1143 } 1144 1145 /** 1146 * Set the socket number (port) that is used to connect to this channel 1147 * @param integer 1148 * @param string|false name of the mirror server, or false for the primary 1149 */ 1150 function setPort($port, $mirror = false) 1151 { 1152 if ($mirror) { 1153 if (!isset($this->_channelInfo['servers']['mirror'])) { 1154 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, 1155 array('mirror' => $mirror)); 1156 return false; 1157 } 1158 $setmirror = false; 1159 if (isset($this->_channelInfo['servers']['mirror'][0])) { 1160 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { 1161 if ($mirror == $mir['attribs']['host']) { 1162 $this->_channelInfo['servers']['mirror'][$i]['attribs']['port'] = $port; 1163 return true; 1164 } 1165 } 1166 return false; 1167 } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { 1168 $this->_channelInfo['servers']['mirror']['attribs']['port'] = $port; 1169 $this->_isValid = false; 1170 return true; 1171 } 1172 } 1173 $this->_channelInfo['servers']['primary']['attribs']['port'] = $port; 1174 $this->_isValid = false; 1175 return true; 1176 } 1177 1178 /** 1179 * Set the socket number (port) that is used to connect to this channel 1180 * @param bool Determines whether to turn on SSL support or turn it off 1181 * @param string|false name of the mirror server, or false for the primary 1182 */ 1183 function setSSL($ssl = true, $mirror = false) 1184 { 1185 if ($mirror) { 1186 if (!isset($this->_channelInfo['servers']['mirror'])) { 1187 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, 1188 array('mirror' => $mirror)); 1189 return false; 1190 } 1191 $setmirror = false; 1192 if (isset($this->_channelInfo['servers']['mirror'][0])) { 1193 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { 1194 if ($mirror == $mir['attribs']['host']) { 1195 if (!$ssl) { 1196 if (isset($this->_channelInfo['servers']['mirror'][$i] 1197 ['attribs']['ssl'])) { 1198 unset($this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl']); 1199 } 1200 } else { 1201 $this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl'] = 'yes'; 1202 } 1203 return true; 1204 } 1205 } 1206 return false; 1207 } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { 1208 if (!$ssl) { 1209 if (isset($this->_channelInfo['servers']['mirror']['attribs']['ssl'])) { 1210 unset($this->_channelInfo['servers']['mirror']['attribs']['ssl']); 1211 } 1212 } else { 1213 $this->_channelInfo['servers']['mirror']['attribs']['ssl'] = 'yes'; 1214 } 1215 $this->_isValid = false; 1216 return true; 1217 } 1218 } 1219 if ($ssl) { 1220 $this->_channelInfo['servers']['primary']['attribs']['ssl'] = 'yes'; 1221 } else { 1222 if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) { 1223 unset($this->_channelInfo['servers']['primary']['attribs']['ssl']); 1224 } 1225 } 1226 $this->_isValid = false; 1227 return true; 1228 } 1229 1230 /** 1231 * Set the socket number (port) that is used to connect to this channel 1232 * @param integer 1233 * @param string|false name of the mirror server, or false for the primary 1234 */ 1235 function setPath($protocol, $path, $mirror = false) 1236 { 1237 if (!in_array($protocol, array('xmlrpc', 'soap'))) { 1238 return false; 1239 } 1240 if ($mirror) { 1241 if (!isset($this->_channelInfo['servers']['mirror'])) { 1242 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, 1243 array('mirror' => $mirror)); 1244 return false; 1245 } 1246 $setmirror = false; 1247 if (isset($this->_channelInfo['servers']['mirror'][0])) { 1248 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { 1249 if ($mirror == $mir['attribs']['host']) { 1250 $this->_channelInfo['servers']['mirror'][$i][$protocol]['attribs']['path'] = 1251 $path; 1252 return true; 1253 } 1254 } 1255 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, 1256 array('mirror' => $mirror)); 1257 return false; 1258 } elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { 1259 $this->_channelInfo['servers']['mirror'][$protocol]['attribs']['path'] = $path; 1260 $this->_isValid = false; 1261 return true; 1262 } 1263 } 1264 $this->_channelInfo['servers']['primary'][$protocol]['attribs']['path'] = $path; 1265 $this->_isValid = false; 1266 return true; 1267 } 1268 1269 /** 1270 * @param string 1271 * @return string|false 1272 * @error PEAR_CHANNELFILE_ERROR_NO_SERVER 1273 * @error PEAR_CHANNELFILE_ERROR_INVALID_SERVER 1274 */ 1275 function setServer($server, $mirror = false) 1276 { 1277 if (empty($server)) { 1278 $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SERVER); 1279 return false; 1280 } elseif (!$this->validChannelServer($server)) { 1281 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, 1282 array('tag' => 'name', 'name' => $server)); 1283 return false; 1284 } 1285 if ($mirror) { 1286 $found = false; 1287 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { 1288 if ($mirror == $mir['attribs']['host']) { 1289 $found = true; 1290 break; 1291 } 1292 } 1293 if (!$found) { 1294 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, 1295 array('mirror' => $mirror)); 1296 return false; 1297 } 1298 $this->_channelInfo['mirror'][$i]['attribs']['host'] = $server; 1299 return true; 1300 } 1301 $this->_channelInfo['name'] = $server; 1302 return true; 1303 } 1304 1305 /** 1306 * @param string 1307 * @return boolean success 1308 * @error PEAR_CHANNELFILE_ERROR_NO_SUMMARY 1309 * @warning PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY 1310 */ 1311 function setSummary($summary) 1312 { 1313 if (empty($summary)) { 1314 $this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY); 1315 return false; 1316 } elseif (strpos(trim($summary), "\n") !== false) { 1317 $this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY, 1318 array('summary' => $summary)); 1319 } 1320 $this->_channelInfo['summary'] = $summary; 1321 return true; 1322 } 1323 1324 /** 1325 * @param string 1326 * @param boolean determines whether the alias is in channel.xml or local 1327 * @return boolean success 1328 */ 1329 function setAlias($alias, $local = false) 1330 { 1331 if (!$this->validChannelServer($alias)) { 1332 $this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, 1333 array('tag' => 'suggestedalias', 'name' => $alias)); 1334 return false; 1335 } 1336 if ($local) { 1337 $this->_channelInfo['localalias'] = $alias; 1338 } else { 1339 $this->_channelInfo['suggestedalias'] = $alias; 1340 } 1341 return true; 1342 } 1343 1344 /** 1345 * @return string 1346 */ 1347 function getAlias() 1348 { 1349 if (isset($this->_channelInfo['localalias'])) { 1350 return $this->_channelInfo['localalias']; 1351 } 1352 if (isset($this->_channelInfo['suggestedalias'])) { 1353 return $this->_channelInfo['suggestedalias']; 1354 } 1355 if (isset($this->_channelInfo['name'])) { 1356 return $this->_channelInfo['name']; 1357 } 1358 } 1359 1360 /** 1361 * Set the package validation object if it differs from PEAR's default 1362 * The class must be includeable via changing _ in the classname to path separator, 1363 * but no checking of this is made. 1364 * @param string|false pass in false to reset to the default packagename regex 1365 * @return boolean success 1366 */ 1367 function setValidationPackage($validateclass, $version) 1368 { 1369 if (empty($validateclass)) { 1370 unset($this->_channelInfo['validatepackage']); 1371 } 1372 $this->_channelInfo['validatepackage'] = array('_content' => $validateclass); 1373 $this->_channelInfo['validatepackage']['attribs'] = array('version' => $version); 1374 } 1375 1376 /** 1377 * Add a protocol to the provides section 1378 * @param string protocol type 1379 * @param string protocol version 1380 * @param string protocol name, if any 1381 * @param string mirror name, if this is a mirror's protocol 1382 * @return bool 1383 */ 1384 function addFunction($type, $version, $name = '', $mirror = false) 1385 { 1386 if ($mirror) { 1387 return $this->addMirrorFunction($mirror, $type, $version, $name); 1388 } 1389 $set = array('attribs' => array('version' => $version), '_content' => $name); 1390 if (!isset($this->_channelInfo['servers']['primary'][$type]['function'])) { 1391 if (!isset($this->_channelInfo['servers'])) { 1392 $this->_channelInfo['servers'] = array('primary' => 1393 array($type => array())); 1394 } elseif (!isset($this->_channelInfo['servers']['primary'])) { 1395 $this->_channelInfo['servers']['primary'] = array($type => array()); 1396 } 1397 $this->_channelInfo['servers']['primary'][$type]['function'] = $set; 1398 $this->_isValid = false; 1399 return true; 1400 } elseif (!isset($this->_channelInfo['servers']['primary'][$type]['function'][0])) { 1401 $this->_channelInfo['servers']['primary'][$type]['function'] = array( 1402 $this->_channelInfo['servers']['primary'][$type]['function']); 1403 } 1404 $this->_channelInfo['servers']['primary'][$type]['function'][] = $set; 1405 return true; 1406 } 1407 /** 1408 * Add a protocol to a mirror's provides section 1409 * @param string mirror name (server) 1410 * @param string protocol type 1411 * @param string protocol version 1412 * @param string protocol name, if any 1413 */ 1414 function addMirrorFunction($mirror, $type, $version, $name = '') 1415 { 1416 $found = false; 1417 if (!isset($this->_channelInfo['servers']['mirror'])) { 1418 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, 1419 array('mirror' => $mirror)); 1420 return false; 1421 } 1422 $setmirror = false; 1423 if (isset($this->_channelInfo['servers']['mirror'][0])) { 1424 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { 1425 if ($mirror == $mir['attribs']['host']) { 1426 $setmirror = &$this->_channelInfo['servers']['mirror'][$i]; 1427 break; 1428 } 1429 } 1430 } else { 1431 if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { 1432 $setmirror = &$this->_channelInfo['servers']['mirror']; 1433 } 1434 } 1435 if (!$setmirror) { 1436 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, 1437 array('mirror' => $mirror)); 1438 return false; 1439 } 1440 $set = array('attribs' => array('version' => $version), '_content' => $name); 1441 if (!isset($setmirror[$type]['function'])) { 1442 $setmirror[$type]['function'] = $set; 1443 $this->_isValid = false; 1444 return true; 1445 } elseif (!isset($setmirror[$type]['function'][0])) { 1446 $setmirror[$type]['function'] = array($setmirror[$type]['function']); 1447 } 1448 $setmirror[$type]['function'][] = $set; 1449 $this->_isValid = false; 1450 return true; 1451 } 1452 1453 /** 1454 * @param string Resource Type this url links to 1455 * @param string URL 1456 * @param string|false mirror name, if this is not a primary server REST base URL 1457 */ 1458 function setBaseURL($resourceType, $url, $mirror = false) 1459 { 1460 if ($mirror) { 1461 $found = false; 1462 if (!isset($this->_channelInfo['servers']['mirror'])) { 1463 $this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND, 1464 array('mirror' => $mirror)); 1465 return false; 1466 } 1467 $setmirror = false; 1468 if (isset($this->_channelInfo['servers']['mirror'][0])) { 1469 foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) { 1470 if ($mirror == $mir['attribs']['host']) { 1471 $setmirror = &$this->_channelInfo['servers']['mirror'][$i]; 1472 break; 1473 } 1474 } 1475 } else { 1476 if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) { 1477 $setmirror = &$this->_channelInfo['servers']['mirror']; 1478 } 1479 } 1480 } else { 1481 $setmirror = &$this->_channelInfo['servers']['primary']; 1482 } 1483 $set = array('attribs' => array('type' => $resourceType), '_content' => $url); 1484 if (!isset($setmirror['rest'])) { 1485 $setmirror['rest'] = array(); 1486 } 1487 if (!isset($setmirror['rest']['baseurl'])) { 1488 $setmirror['rest']['baseurl'] = $set; 1489 $this->_isValid = false; 1490 return true; 1491 } elseif (!isset($setmirror['rest']['baseurl'][0])) { 1492 $setmirror['rest']['baseurl'] = array($setmirror['rest']['baseurl']); 1493 } 1494 foreach ($setmirror['rest']['baseurl'] as $i => $url) { 1495 if ($url['attribs']['type'] == $resourceType) { 1496 $this->_isValid = false; 1497 $setmirror['rest']['baseurl'][$i] = $set; 1498 return true; 1499 } 1500 } 1501 $setmirror['rest']['baseurl'][] = $set; 1502 $this->_isValid = false; 1503 return true; 1504 } 1505 1506 /** 1507 * @param string mirror server 1508 * @param int mirror http port 1509 * @return boolean 1510 */ 1511 function addMirror($server, $port = null) 1512 { 1513 if ($this->_channelInfo['name'] == '__uri') { 1514 return false; // the __uri channel cannot have mirrors by definition 1515 } 1516 $set = array('attribs' => array('host' => $server)); 1517 if (is_numeric($port)) { 1518 $set['attribs']['port'] = $port; 1519 } 1520 if (!isset($this->_channelInfo['servers']['mirror'])) { 1521 $this->_channelInfo['servers']['mirror'] = $set; 1522 return true; 1523 } else { 1524 if (!isset($this->_channelInfo['servers']['mirror'][0])) { 1525 $this->_channelInfo['servers']['mirror'] = 1526 array($this->_channelInfo['servers']['mirror']); 1527 } 1528 } 1529 $this->_channelInfo['servers']['mirror'][] = $set; 1530 return true; 1531 } 1532 1533 /** 1534 * Retrieve the name of the validation package for this channel 1535 * @return string|false 1536 */ 1537 function getValidationPackage() 1538 { 1539 if (!$this->_isValid && !$this->validate()) { 1540 return false; 1541 } 1542 if (!isset($this->_channelInfo['validatepackage'])) { 1543 return array('attribs' => array('version' => 'default'), 1544 '_content' => 'PEAR_Validate'); 1545 } 1546 return $this->_channelInfo['validatepackage']; 1547 } 1548 1549 /** 1550 * Retrieve the object that can be used for custom validation 1551 * @param string|false the name of the package to validate. If the package is 1552 * the channel validation package, PEAR_Validate is returned 1553 * @return PEAR_Validate|false false is returned if the validation package 1554 * cannot be located 1555 */ 1556 function &getValidationObject($package = false) 1557 { 1558 if (!class_exists('PEAR_Validate')) { 1559 require_once 'PEAR/Validate.php'; 1560 } 1561 if (!$this->_isValid) { 1562 if (!$this->validate()) { 1563 $a = false; 1564 return $a; 1565 } 1566 } 1567 if (isset($this->_channelInfo['validatepackage'])) { 1568 if ($package == $this->_channelInfo['validatepackage']) { 1569 // channel validation packages are always validated by PEAR_Validate 1570 $val = &new PEAR_Validate; 1571 return $val; 1572 } 1573 if (!class_exists(str_replace('.', '_', 1574 $this->_channelInfo['validatepackage']['_content']))) { 1575 if ($this->isIncludeable(str_replace('_', '/', 1576 $this->_channelInfo['validatepackage']['_content']) . '.php')) { 1577 include_once str_replace('_', '/', 1578 $this->_channelInfo['validatepackage']['_content']) . '.php'; 1579 $vclass = str_replace('.', '_', 1580 $this->_channelInfo['validatepackage']['_content']); 1581 $val = &new $vclass; 1582 } else { 1583 $a = false; 1584 return $a; 1585 } 1586 } else { 1587 $vclass = str_replace('.', '_', 1588 $this->_channelInfo['validatepackage']['_content']); 1589 $val = &new $vclass; 1590 } 1591 } else { 1592 $val = &new PEAR_Validate; 1593 } 1594 return $val; 1595 } 1596 1597 function isIncludeable($path) 1598 { 1599 $possibilities = explode(PATH_SEPARATOR, ini_get('include_path')); 1600 foreach ($possibilities as $dir) { 1601 if (file_exists($dir . DIRECTORY_SEPARATOR . $path) 1602 && is_readable($dir . DIRECTORY_SEPARATOR . $path)) { 1603 return true; 1604 } 1605 } 1606 return false; 1607 } 1608 1609 /** 1610 * This function is used by the channel updater and retrieves a value set by 1611 * the registry, or the current time if it has not been set 1612 * @return string 1613 */ 1614 function lastModified() 1615 { 1616 if (isset($this->_channelInfo['_lastmodified'])) { 1617 return $this->_channelInfo['_lastmodified']; 1618 } 1619 return time(); 1620 } 1621 } 1622 ?>
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 |