PEAR
[ class tree: PEAR ] [ index: PEAR ] [ all elements ]

Source for file ChannelFile.php

Documentation is available at ChannelFile.php

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

Documentation generated on Wed, 06 Jul 2011 23:30:29 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.