home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / tmp / PEAR-1.7.1 / PEAR / PackageFile / v2.php < prev   
Encoding:
PHP Script  |  2008-02-15  |  68.1 KB  |  2,043 lines

  1. <?php
  2. /**
  3.  * PEAR_PackageFile_v2, package.xml version 2.0
  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-2008 The PHP Group
  17.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  18.  * @version    CVS: $Id: v2.php,v 1.141 2008/01/03 20:26:36 cellog Exp $
  19.  * @link       http://pear.php.net/package/PEAR
  20.  * @since      File available since Release 1.4.0a1
  21.  */
  22. /**
  23.  * For error handling
  24.  */
  25. require_once 'PEAR/ErrorStack.php';
  26. /**
  27.  * @category   pear
  28.  * @package    PEAR
  29.  * @author     Greg Beaver <cellog@php.net>
  30.  * @copyright  1997-2008 The PHP Group
  31.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  32.  * @version    Release: 1.7.1
  33.  * @link       http://pear.php.net/package/PEAR
  34.  * @since      Class available since Release 1.4.0a1
  35.  */
  36. class PEAR_PackageFile_v2
  37. {
  38.  
  39.     /**
  40.      * Parsed package information
  41.      * @var array
  42.      * @access private
  43.      */
  44.     var $_packageInfo = array();
  45.  
  46.     /**
  47.      * path to package .tgz or false if this is a local/extracted package.xml
  48.      * @var string|false
  49.      * @access private
  50.      */
  51.     var $_archiveFile;
  52.  
  53.     /**
  54.      * path to package .xml or false if this is an abstract parsed-from-string xml
  55.      * @var string|false
  56.      * @access private
  57.      */
  58.     var $_packageFile;
  59.  
  60.     /**
  61.      * This is used by file analysis routines to log progress information
  62.      * @var PEAR_Common
  63.      * @access protected
  64.      */
  65.     var $_logger;
  66.  
  67.     /**
  68.      * This is set to the highest validation level that has been validated
  69.      *
  70.      * If the package.xml is invalid or unknown, this is set to 0.  If
  71.      * normal validation has occurred, this is set to PEAR_VALIDATE_NORMAL.  If
  72.      * downloading/installation validation has occurred it is set to PEAR_VALIDATE_DOWNLOADING
  73.      * or INSTALLING, and so on up to PEAR_VALIDATE_PACKAGING.  This allows validation
  74.      * "caching" to occur, which is particularly important for package validation, so
  75.      * that PHP files are not validated twice
  76.      * @var int
  77.      * @access private
  78.      */
  79.     var $_isValid = 0;
  80.  
  81.     /**
  82.      * True if the filelist has been validated
  83.      * @param bool
  84.      */
  85.     var $_filesValid = false;
  86.  
  87.     /**
  88.      * @var PEAR_Registry
  89.      * @access protected
  90.      */
  91.     var $_registry;
  92.  
  93.     /**
  94.      * @var PEAR_Config
  95.      * @access protected
  96.      */
  97.     var $_config;
  98.  
  99.     /**
  100.      * Optional Dependency group requested for installation
  101.      * @var string
  102.      * @access private
  103.      */
  104.     var $_requestedGroup = false;
  105.  
  106.     /**
  107.      * @var PEAR_ErrorStack
  108.      * @access protected
  109.      */
  110.     var $_stack;
  111.  
  112.     /**
  113.      * Namespace prefix used for tasks in this package.xml - use tasks: whenever possible
  114.      */
  115.     var $_tasksNs;
  116.  
  117.     /**
  118.      * Determines whether this packagefile was initialized only with partial package info
  119.      *
  120.      * If this package file was constructed via parsing REST, it will only contain
  121.      *
  122.      * - package name
  123.      * - channel name
  124.      * - dependencies 
  125.      * @var boolean
  126.      * @access private
  127.      */
  128.     var $_incomplete = true;
  129.  
  130.     /**
  131.      * @var PEAR_PackageFile_v2_Validator
  132.      */
  133.     var $_v2Validator;
  134.  
  135.     /**
  136.      * The constructor merely sets up the private error stack
  137.      */
  138.     function PEAR_PackageFile_v2()
  139.     {
  140.         $this->_stack = new PEAR_ErrorStack('PEAR_PackageFile_v2', false, null);
  141.         $this->_isValid = false;
  142.     }
  143.  
  144.     /**
  145.      * To make unit-testing easier
  146.      * @param PEAR_Frontend_*
  147.      * @param array options
  148.      * @param PEAR_Config
  149.      * @return PEAR_Downloader
  150.      * @access protected
  151.      */
  152.     function &getPEARDownloader(&$i, $o, &$c)
  153.     {
  154.         $z = &new PEAR_Downloader($i, $o, $c);
  155.         return $z;
  156.     }
  157.  
  158.     /**
  159.      * To make unit-testing easier
  160.      * @param PEAR_Config
  161.      * @param array options
  162.      * @param array package name as returned from {@link PEAR_Registry::parsePackageName()}
  163.      * @param int PEAR_VALIDATE_* constant
  164.      * @return PEAR_Dependency2
  165.      * @access protected
  166.      */
  167.     function &getPEARDependency2(&$c, $o, $p, $s = PEAR_VALIDATE_INSTALLING)
  168.     {
  169.         if (!class_exists('PEAR_Dependency2')) {
  170.             require_once 'PEAR/Dependency2.php';
  171.         }
  172.         $z = &new PEAR_Dependency2($c, $o, $p, $s);
  173.         return $z;
  174.     }
  175.  
  176.     function getInstalledBinary()
  177.     {
  178.         return isset($this->_packageInfo['#binarypackage']) ? $this->_packageInfo['#binarypackage'] :
  179.             false;
  180.     }
  181.  
  182.     /**
  183.      * Installation of source package has failed, attempt to download and install the
  184.      * binary version of this package.
  185.      * @param PEAR_Installer
  186.      * @return array|false
  187.      */
  188.     function installBinary(&$installer)
  189.     {
  190.         if (!OS_WINDOWS) {
  191.             $a = false;
  192.             return $a;
  193.         }
  194.         if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
  195.             $releasetype = $this->getPackageType() . 'release';
  196.             if (!is_array($installer->getInstallPackages())) {
  197.                 $a = false;
  198.                 return $a;
  199.             }
  200.             foreach ($installer->getInstallPackages() as $p) {
  201.                 if ($p->isExtension($this->_packageInfo['providesextension'])) {
  202.                     if ($p->getPackageType() != 'extsrc' && $p->getPackageType() != 'zendextsrc') {
  203.                         $a = false;
  204.                         return $a; // the user probably downloaded it separately
  205.                     }
  206.                 }
  207.             }
  208.             if (isset($this->_packageInfo[$releasetype]['binarypackage'])) {
  209.                 $installer->log(0, 'Attempting to download binary version of extension "' .
  210.                     $this->_packageInfo['providesextension'] . '"');
  211.                 $params = $this->_packageInfo[$releasetype]['binarypackage'];
  212.                 if (!is_array($params) || !isset($params[0])) {
  213.                     $params = array($params);
  214.                 }
  215.                 if (isset($this->_packageInfo['channel'])) {
  216.                     foreach ($params as $i => $param) {
  217.                         $params[$i] = array('channel' => $this->_packageInfo['channel'],
  218.                             'package' => $param, 'version' => $this->getVersion());
  219.                     }
  220.                 }
  221.                 $dl = &$this->getPEARDownloader($installer->ui, $installer->getOptions(),
  222.                     $installer->config);
  223.                 $verbose = $dl->config->get('verbose');
  224.                 $dl->config->set('verbose', -1);
  225.                 foreach ($params as $param) {
  226.                     PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  227.                     $ret = $dl->download(array($param));
  228.                     PEAR::popErrorHandling();
  229.                     if (is_array($ret) && count($ret)) {
  230.                         break;
  231.                     }
  232.                 }
  233.                 $dl->config->set('verbose', $verbose);
  234.                 if (is_array($ret)) {
  235.                     if (count($ret) == 1) {
  236.                         $pf = $ret[0]->getPackageFile();
  237.                         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  238.                         $err = $installer->install($ret[0]);
  239.                         PEAR::popErrorHandling();
  240.                         if (is_array($err)) {
  241.                             $this->_packageInfo['#binarypackage'] = $ret[0]->getPackage();
  242.                             // "install" self, so all dependencies will work transparently
  243.                             $this->_registry->addPackage2($this);
  244.                             $installer->log(0, 'Download and install of binary extension "' .
  245.                                 $this->_registry->parsedPackageNameToString(
  246.                                     array('channel' => $pf->getChannel(),
  247.                                           'package' => $pf->getPackage()), true) . '" successful');
  248.                             $a = array($ret[0], $err);
  249.                             return $a;
  250.                         }
  251.                         $installer->log(0, 'Download and install of binary extension "' .
  252.                             $this->_registry->parsedPackageNameToString(
  253.                                     array('channel' => $pf->getChannel(),
  254.                                           'package' => $pf->getPackage()), true) . '" failed');
  255.                     }
  256.                 }
  257.             }
  258.         }
  259.         $a = false;
  260.         return $a;
  261.     }
  262.  
  263.     /**
  264.      * @return string|false Extension name
  265.      */
  266.     function getProvidesExtension()
  267.     {
  268.         if (in_array($this->getPackageType(),
  269.               array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
  270.             if (isset($this->_packageInfo['providesextension'])) {
  271.                 return $this->_packageInfo['providesextension'];
  272.             }
  273.         }
  274.         return false;
  275.     }
  276.  
  277.     /**
  278.      * @param string Extension name
  279.      * @return bool
  280.      */
  281.     function isExtension($extension)
  282.     {
  283.         if (in_array($this->getPackageType(),
  284.               array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
  285.             return $this->_packageInfo['providesextension'] == $extension;
  286.         }
  287.         return false;
  288.     }
  289.  
  290.     /**
  291.      * Tests whether every part of the package.xml 1.0 is represented in
  292.      * this package.xml 2.0
  293.      * @param PEAR_PackageFile_v1
  294.      * @return bool
  295.      */
  296.     function isEquivalent($pf1)
  297.     {
  298.         if (!$pf1) {
  299.             return true;
  300.         }
  301.         if ($this->getPackageType() == 'bundle') {
  302.             return false;
  303.         }
  304.         $this->_stack->getErrors(true);
  305.         if (!$pf1->validate(PEAR_VALIDATE_NORMAL)) {
  306.             return false;
  307.         }
  308.         $pass = true;
  309.         if ($pf1->getPackage() != $this->getPackage()) {
  310.             $this->_differentPackage($pf1->getPackage());
  311.             $pass = false;
  312.         }
  313.         if ($pf1->getVersion() != $this->getVersion()) {
  314.             $this->_differentVersion($pf1->getVersion());
  315.             $pass = false;
  316.         }
  317.         if (trim($pf1->getSummary()) != $this->getSummary()) {
  318.             $this->_differentSummary($pf1->getSummary());
  319.             $pass = false;
  320.         }
  321.         if (preg_replace('/\s+/', '', $pf1->getDescription()) !=
  322.               preg_replace('/\s+/', '', $this->getDescription())) {
  323.             $this->_differentDescription($pf1->getDescription());
  324.             $pass = false;
  325.         }
  326.         if ($pf1->getState() != $this->getState()) {
  327.             $this->_differentState($pf1->getState());
  328.             $pass = false;
  329.         }
  330.         if (!strstr(preg_replace('/\s+/', '', $this->getNotes()),
  331.               preg_replace('/\s+/', '', $pf1->getNotes()))) {
  332.             $this->_differentNotes($pf1->getNotes());
  333.             $pass = false;
  334.         }
  335.         $mymaintainers = $this->getMaintainers();
  336.         $yourmaintainers = $pf1->getMaintainers();
  337.         for ($i1 = 0; $i1 < count($yourmaintainers); $i1++) {
  338.             $reset = false;
  339.             for ($i2 = 0; $i2 < count($mymaintainers); $i2++) {
  340.                 if ($mymaintainers[$i2]['handle'] == $yourmaintainers[$i1]['handle']) {
  341.                     if ($mymaintainers[$i2]['role'] != $yourmaintainers[$i1]['role']) {
  342.                         $this->_differentRole($mymaintainers[$i2]['handle'],
  343.                             $yourmaintainers[$i1]['role'], $mymaintainers[$i2]['role']);
  344.                         $pass = false;
  345.                     }
  346.                     if ($mymaintainers[$i2]['email'] != $yourmaintainers[$i1]['email']) {
  347.                         $this->_differentEmail($mymaintainers[$i2]['handle'],
  348.                             $yourmaintainers[$i1]['email'], $mymaintainers[$i2]['email']);
  349.                         $pass = false;
  350.                     }
  351.                     if ($mymaintainers[$i2]['name'] != $yourmaintainers[$i1]['name']) {
  352.                         $this->_differentName($mymaintainers[$i2]['handle'],
  353.                             $yourmaintainers[$i1]['name'], $mymaintainers[$i2]['name']);
  354.                         $pass = false;
  355.                     }
  356.                     unset($mymaintainers[$i2]);
  357.                     $mymaintainers = array_values($mymaintainers);
  358.                     unset($yourmaintainers[$i1]);
  359.                     $yourmaintainers = array_values($yourmaintainers);
  360.                     $reset = true;
  361.                     break;
  362.                 }
  363.             }
  364.             if ($reset) {
  365.                 $i1 = -1;
  366.             }
  367.         }
  368.         $this->_unmatchedMaintainers($mymaintainers, $yourmaintainers);
  369.         $filelist = $this->getFilelist();
  370.         foreach ($pf1->getFilelist() as $file => $atts) {
  371.             if (!isset($filelist[$file])) {
  372.                 $this->_missingFile($file);
  373.                 $pass = false;
  374.             }
  375.         }
  376.         return $pass;
  377.     }
  378.  
  379.     function _differentPackage($package)
  380.     {
  381.         $this->_stack->push(__FUNCTION__, 'error', array('package' => $package,
  382.             'self' => $this->getPackage()),
  383.             'package.xml 1.0 package "%package%" does not match "%self%"');
  384.     }
  385.  
  386.     function _differentVersion($version)
  387.     {
  388.         $this->_stack->push(__FUNCTION__, 'error', array('version' => $version,
  389.             'self' => $this->getVersion()),
  390.             'package.xml 1.0 version "%version%" does not match "%self%"');
  391.     }
  392.  
  393.     function _differentState($state)
  394.     {
  395.         $this->_stack->push(__FUNCTION__, 'error', array('state' => $state,
  396.             'self' => $this->getState()),
  397.             'package.xml 1.0 state "%state%" does not match "%self%"');
  398.     }
  399.  
  400.     function _differentRole($handle, $role, $selfrole)
  401.     {
  402.         $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
  403.             'role' => $role, 'self' => $selfrole),
  404.             'package.xml 1.0 maintainer "%handle%" role "%role%" does not match "%self%"');
  405.     }
  406.  
  407.     function _differentEmail($handle, $email, $selfemail)
  408.     {
  409.         $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
  410.             'email' => $email, 'self' => $selfemail),
  411.             'package.xml 1.0 maintainer "%handle%" email "%email%" does not match "%self%"');
  412.     }
  413.  
  414.     function _differentName($handle, $name, $selfname)
  415.     {
  416.         $this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
  417.             'name' => $name, 'self' => $selfname),
  418.             'package.xml 1.0 maintainer "%handle%" name "%name%" does not match "%self%"');
  419.     }
  420.  
  421.     function _unmatchedMaintainers($my, $yours)
  422.     {
  423.         if ($my) {
  424.             array_walk($my, create_function('&$i, $k', '$i = $i["handle"];'));
  425.             $this->_stack->push(__FUNCTION__, 'error', array('handles' => $my),
  426.                 'package.xml 2.0 has unmatched extra maintainers "%handles%"');
  427.         }
  428.         if ($yours) {
  429.             array_walk($yours, create_function('&$i, $k', '$i = $i["handle"];'));
  430.             $this->_stack->push(__FUNCTION__, 'error', array('handles' => $yours),
  431.                 'package.xml 1.0 has unmatched extra maintainers "%handles%"');
  432.         }
  433.     }
  434.  
  435.     function _differentNotes($notes)
  436.     {
  437.         $truncnotes = strlen($notes) < 25 ? $notes : substr($notes, 0, 24) . '...';
  438.         $truncmynotes = strlen($this->getNotes()) < 25 ? $this->getNotes() :
  439.             substr($this->getNotes(), 0, 24) . '...';
  440.         $this->_stack->push(__FUNCTION__, 'error', array('notes' => $truncnotes,
  441.             'self' => $truncmynotes),
  442.             'package.xml 1.0 release notes "%notes%" do not match "%self%"');
  443.     }
  444.  
  445.     function _differentSummary($summary)
  446.     {
  447.         $truncsummary = strlen($summary) < 25 ? $summary : substr($summary, 0, 24) . '...';
  448.         $truncmysummary = strlen($this->getsummary()) < 25 ? $this->getSummary() :
  449.             substr($this->getsummary(), 0, 24) . '...';
  450.         $this->_stack->push(__FUNCTION__, 'error', array('summary' => $truncsummary,
  451.             'self' => $truncmysummary),
  452.             'package.xml 1.0 summary "%summary%" does not match "%self%"');
  453.     }
  454.  
  455.     function _differentDescription($description)
  456.     {
  457.         $truncdescription = trim(strlen($description) < 25 ? $description : substr($description, 0, 24) . '...');
  458.         $truncmydescription = trim(strlen($this->getDescription()) < 25 ? $this->getDescription() :
  459.             substr($this->getdescription(), 0, 24) . '...');
  460.         $this->_stack->push(__FUNCTION__, 'error', array('description' => $truncdescription,
  461.             'self' => $truncmydescription),
  462.             'package.xml 1.0 description "%description%" does not match "%self%"');
  463.     }
  464.  
  465.     function _missingFile($file)
  466.     {
  467.         $this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
  468.             'package.xml 1.0 file "%file%" is not present in <contents>');
  469.     }
  470.  
  471.     /**
  472.      * WARNING - do not use this function unless you know what you're doing
  473.      */
  474.     function setRawState($state)
  475.     {
  476.         if (!isset($this->_packageInfo['stability'])) {
  477.             $this->_packageInfo['stability'] = array();
  478.         }
  479.         $this->_packageInfo['stability']['release'] = $state;
  480.     }
  481.  
  482.     /**
  483.      * WARNING - do not use this function unless you know what you're doing
  484.      */
  485.     function setRawCompatible($compatible)
  486.     {
  487.         $this->_packageInfo['compatible'] = $compatible;
  488.     }
  489.  
  490.     /**
  491.      * WARNING - do not use this function unless you know what you're doing
  492.      */
  493.     function setRawPackage($package)
  494.     {
  495.         $this->_packageInfo['name'] = $package;
  496.     }
  497.  
  498.     /**
  499.      * WARNING - do not use this function unless you know what you're doing
  500.      */
  501.     function setRawChannel($channel)
  502.     {
  503.         $this->_packageInfo['channel'] = $channel;
  504.     }
  505.  
  506.     function setRequestedGroup($group)
  507.     {
  508.         $this->_requestedGroup = $group;
  509.     }
  510.  
  511.     function getRequestedGroup()
  512.     {
  513.         if (isset($this->_requestedGroup)) {
  514.             return $this->_requestedGroup;
  515.         }
  516.         return false;
  517.     }
  518.  
  519.     /**
  520.      * For saving in the registry.
  521.      *
  522.      * Set the last version that was installed
  523.      * @param string
  524.      */
  525.     function setLastInstalledVersion($version)
  526.     {
  527.         $this->_packageInfo['_lastversion'] = $version;
  528.     }
  529.  
  530.     /**
  531.      * @return string|false
  532.      */
  533.     function getLastInstalledVersion()
  534.     {
  535.         if (isset($this->_packageInfo['_lastversion'])) {
  536.             return $this->_packageInfo['_lastversion'];
  537.         }
  538.         return false;
  539.     }
  540.  
  541.     /**
  542.      * Determines whether this package.xml has post-install scripts or not
  543.      * @return array|false
  544.      */
  545.     function listPostinstallScripts()
  546.     {
  547.         $filelist = $this->getFilelist();
  548.         $contents = $this->getContents();
  549.         $contents = $contents['dir']['file'];
  550.         if (!is_array($contents) || !isset($contents[0])) {
  551.             $contents = array($contents);
  552.         }
  553.         $taskfiles = array();
  554.         foreach ($contents as $file) {
  555.             $atts = $file['attribs'];
  556.             unset($file['attribs']);
  557.             if (count($file)) {
  558.                 $taskfiles[$atts['name']] = $file;
  559.             }
  560.         }
  561.         $common = new PEAR_Common;
  562.         $common->debug = $this->_config->get('verbose');
  563.         $this->_scripts = array();
  564.         $ret = array();
  565.         foreach ($taskfiles as $name => $tasks) {
  566.             if (!isset($filelist[$name])) {
  567.                 // ignored files will not be in the filelist
  568.                 continue;
  569.             }
  570.             $atts = $filelist[$name];
  571.             foreach ($tasks as $tag => $raw) {
  572.                 $task = $this->getTask($tag);
  573.                 $task = &new $task($this->_config, $common, PEAR_TASK_INSTALL);
  574.                 if ($task->isScript()) {
  575.                     $ret[] = $filelist[$name]['installed_as'];
  576.                 }
  577.             }
  578.         }
  579.         if (count($ret)) {
  580.             return $ret;
  581.         }
  582.         return false;
  583.     }
  584.  
  585.     /**
  586.      * Initialize post-install scripts for running
  587.      *
  588.      * This method can be used to detect post-install scripts, as the return value
  589.      * indicates whether any exist
  590.      * @return bool
  591.      */
  592.     function initPostinstallScripts()
  593.     {
  594.         $filelist = $this->getFilelist();
  595.         $contents = $this->getContents();
  596.         $contents = $contents['dir']['file'];
  597.         if (!is_array($contents) || !isset($contents[0])) {
  598.             $contents = array($contents);
  599.         }
  600.         $taskfiles = array();
  601.         foreach ($contents as $file) {
  602.             $atts = $file['attribs'];
  603.             unset($file['attribs']);
  604.             if (count($file)) {
  605.                 $taskfiles[$atts['name']] = $file;
  606.             }
  607.         }
  608.         $common = new PEAR_Common;
  609.         $common->debug = $this->_config->get('verbose');
  610.         $this->_scripts = array();
  611.         foreach ($taskfiles as $name => $tasks) {
  612.             if (!isset($filelist[$name])) {
  613.                 // file was not installed due to installconditions
  614.                 continue;
  615.             }
  616.             $atts = $filelist[$name];
  617.             foreach ($tasks as $tag => $raw) {
  618.                 $taskname = $this->getTask($tag);
  619.                 $task = &new $taskname($this->_config, $common, PEAR_TASK_INSTALL);
  620.                 if (!$task->isScript()) {
  621.                     continue; // scripts are only handled after installation
  622.                 }
  623.                 $lastversion = isset($this->_packageInfo['_lastversion']) ?
  624.                     $this->_packageInfo['_lastversion'] : null;
  625.                 $task->init($raw, $atts, $lastversion);
  626.                 $res = $task->startSession($this, $atts['installed_as']);
  627.                 if (!$res) {
  628.                     continue; // skip this file
  629.                 }
  630.                 if (PEAR::isError($res)) {
  631.                     return $res;
  632.                 }
  633.                 $assign = &$task;
  634.                 $this->_scripts[] = &$assign;
  635.             }
  636.         }
  637.         if (count($this->_scripts)) {
  638.             return true;
  639.         }
  640.         return false;
  641.     }
  642.  
  643.     function runPostinstallScripts()
  644.     {
  645.         if ($this->initPostinstallScripts()) {
  646.             $ui = &PEAR_Frontend::singleton();
  647.             if ($ui) {
  648.                 $ui->runPostinstallScripts($this->_scripts, $this);
  649.             }
  650.         }
  651.     }
  652.  
  653.  
  654.     /**
  655.      * Convert a recursive set of <dir> and <file> tags into a single <dir> tag with
  656.      * <file> tags.
  657.      */
  658.     function flattenFilelist()
  659.     {
  660.         if (isset($this->_packageInfo['bundle'])) {
  661.             return;
  662.         }
  663.         $filelist = array();
  664.         if (isset($this->_packageInfo['contents']['dir']['dir'])) {
  665.             $this->_getFlattenedFilelist($filelist, $this->_packageInfo['contents']['dir']);
  666.             if (!isset($filelist[1])) {
  667.                 $filelist = $filelist[0];
  668.             }
  669.             $this->_packageInfo['contents']['dir']['file'] = $filelist;
  670.             unset($this->_packageInfo['contents']['dir']['dir']);
  671.         } else {
  672.             // else already flattened but check for baseinstalldir propagation
  673.             if (isset($this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'])) {
  674.                 if (isset($this->_packageInfo['contents']['dir']['file'][0])) {
  675.                     foreach ($this->_packageInfo['contents']['dir']['file'] as $i => $file) {
  676.                         if (isset($file['attribs']['baseinstalldir'])) {
  677.                             continue;
  678.                         }
  679.                         $this->_packageInfo['contents']['dir']['file'][$i]['attribs']['baseinstalldir']
  680.                             = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
  681.                     }
  682.                 } else {
  683.                     if (!isset($this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'])) {
  684.                        $this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir']
  685.                             = $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
  686.                     }
  687.                 }
  688.             }
  689.         }
  690.     }
  691.  
  692.     /**
  693.      * @param array the final flattened file list
  694.      * @param array the current directory being processed
  695.      * @param string|false any recursively inherited baeinstalldir attribute
  696.      * @param string private recursion variable
  697.      * @return array
  698.      * @access protected
  699.      */
  700.     function _getFlattenedFilelist(&$files, $dir, $baseinstall = false, $path = '')
  701.     {
  702.         if (isset($dir['attribs']) && isset($dir['attribs']['baseinstalldir'])) {
  703.             $baseinstall = $dir['attribs']['baseinstalldir'];
  704.         }
  705.         if (isset($dir['dir'])) {
  706.             if (!isset($dir['dir'][0])) {
  707.                 $dir['dir'] = array($dir['dir']);
  708.             }
  709.             foreach ($dir['dir'] as $subdir) {
  710.                 if (!isset($subdir['attribs']) || !isset($subdir['attribs']['name'])) {
  711.                     $name = '*unknown*';
  712.                 } else {
  713.                     $name = $subdir['attribs']['name'];
  714.                 }
  715.                 $newpath = empty($path) ? $name :
  716.                     $path . '/' . $name;
  717.                 $this->_getFlattenedFilelist($files, $subdir,
  718.                     $baseinstall, $newpath);
  719.             }
  720.         }
  721.         if (isset($dir['file'])) {
  722.             if (!isset($dir['file'][0])) {
  723.                 $dir['file'] = array($dir['file']);
  724.             }
  725.             foreach ($dir['file'] as $file) {
  726.                 $attrs = $file['attribs'];
  727.                 $name = $attrs['name'];
  728.                 if ($baseinstall && !isset($attrs['baseinstalldir'])) {
  729.                     $attrs['baseinstalldir'] = $baseinstall;
  730.                 }
  731.                 $attrs['name'] = empty($path) ? $name : $path . '/' . $name;
  732.                 $attrs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
  733.                     $attrs['name']);
  734.                 $file['attribs'] = $attrs;
  735.                 $files[] = $file;
  736.             }
  737.         }
  738.     }
  739.  
  740.     function setConfig(&$config)
  741.     {
  742.         $this->_config = &$config;
  743.         $this->_registry = &$config->getRegistry();
  744.     }
  745.  
  746.     function setLogger(&$logger)
  747.     {
  748.         if (!is_object($logger) || !method_exists($logger, 'log')) {
  749.             return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
  750.         }
  751.         $this->_logger = &$logger;
  752.     }
  753.  
  754.     /**
  755.      * WARNING - do not use this function directly unless you know what you're doing
  756.      */
  757.     function setDeps($deps)
  758.     {
  759.         $this->_packageInfo['dependencies'] = $deps;
  760.     }
  761.  
  762.     /**
  763.      * WARNING - do not use this function directly unless you know what you're doing
  764.      */
  765.     function setCompatible($compat)
  766.     {
  767.         $this->_packageInfo['compatible'] = $compat;
  768.     }
  769.  
  770.     function setPackagefile($file, $archive = false)
  771.     {
  772.         $this->_packageFile = $file;
  773.         $this->_archiveFile = $archive ? $archive : $file;
  774.     }
  775.  
  776.     /**
  777.      * Wrapper to {@link PEAR_ErrorStack::getErrors()}
  778.      * @param boolean determines whether to purge the error stack after retrieving
  779.      * @return array
  780.      */
  781.     function getValidationWarnings($purge = true)
  782.     {
  783.         return $this->_stack->getErrors($purge);
  784.     }
  785.  
  786.     function getPackageFile()
  787.     {
  788.         return $this->_packageFile;
  789.     }
  790.  
  791.     function getArchiveFile()
  792.     {
  793.         return $this->_archiveFile;
  794.     }
  795.  
  796.  
  797.     /**
  798.      * Directly set the array that defines this packagefile
  799.      *
  800.      * WARNING: no validation.  This should only be performed by internal methods
  801.      * inside PEAR or by inputting an array saved from an existing PEAR_PackageFile_v2
  802.      * @param array
  803.      */
  804.     function fromArray($pinfo)
  805.     {
  806.         unset($pinfo['old']);
  807.         unset($pinfo['xsdversion']);
  808.         $this->_incomplete = false;
  809.         $this->_packageInfo = $pinfo;
  810.     }
  811.  
  812.     function isIncomplete()
  813.     {
  814.         return $this->_incomplete;
  815.     }
  816.  
  817.     /**
  818.      * @return array
  819.      */
  820.     function toArray($forreg = false)
  821.     {
  822.         if (!$this->validate(PEAR_VALIDATE_NORMAL)) {
  823.             return false;
  824.         }
  825.         return $this->getArray($forreg);
  826.     }
  827.  
  828.     function getArray($forReg = false)
  829.     {
  830.         if ($forReg) {
  831.             $arr = $this->_packageInfo;
  832.             $arr['old'] = array();
  833.             $arr['old']['version'] = $this->getVersion();
  834.             $arr['old']['release_date'] = $this->getDate();
  835.             $arr['old']['release_state'] = $this->getState();
  836.             $arr['old']['release_license'] = $this->getLicense();
  837.             $arr['old']['release_notes'] = $this->getNotes();
  838.             $arr['old']['release_deps'] = $this->getDeps();
  839.             $arr['old']['maintainers'] = $this->getMaintainers();
  840.             $arr['xsdversion'] = '2.0';
  841.             return $arr;
  842.         } else {
  843.             $info = $this->_packageInfo;
  844.             unset($info['dirtree']);
  845.             if (isset($info['_lastversion'])) {
  846.                 unset($info['_lastversion']);
  847.             }
  848.             if (isset($info['#binarypackage'])) {
  849.                 unset($info['#binarypackage']);
  850.             }
  851.             return $info;
  852.         }
  853.     }
  854.  
  855.     function packageInfo($field)
  856.     {
  857.         $arr = $this->getArray(true);
  858.         if ($field == 'state') {
  859.             return $arr['stability']['release'];
  860.         }
  861.         if ($field == 'api-version') {
  862.             return $arr['version']['api'];
  863.         }
  864.         if ($field == 'api-state') {
  865.             return $arr['stability']['api'];
  866.         }
  867.         if (isset($arr['old'][$field])) {
  868.             if (!is_string($arr['old'][$field])) {
  869.                 return null;
  870.             }
  871.             return $arr['old'][$field];
  872.         }
  873.         if (isset($arr[$field])) {
  874.             if (!is_string($arr[$field])) {
  875.                 return null;
  876.             }
  877.             return $arr[$field];
  878.         }
  879.         return null;
  880.     }
  881.  
  882.     function getName()
  883.     {
  884.         return $this->getPackage();
  885.     }
  886.  
  887.     function getPackage()
  888.     {
  889.         if (isset($this->_packageInfo['name'])) {
  890.             return $this->_packageInfo['name'];
  891.         }
  892.         return false;
  893.     }
  894.  
  895.     function getChannel()
  896.     {
  897.         if (isset($this->_packageInfo['uri'])) {
  898.             return '__uri';
  899.         }
  900.         if (isset($this->_packageInfo['channel'])) {
  901.             return strtolower($this->_packageInfo['channel']);
  902.         }
  903.         return false;
  904.     }
  905.  
  906.     function getUri()
  907.     {
  908.         if (isset($this->_packageInfo['uri'])) {
  909.             return $this->_packageInfo['uri'];
  910.         }
  911.         return false;
  912.     }
  913.  
  914.     function getExtends()
  915.     {
  916.         if (isset($this->_packageInfo['extends'])) {
  917.             return $this->_packageInfo['extends'];
  918.         }
  919.         return false;
  920.     }
  921.  
  922.     function getSummary()
  923.     {
  924.         if (isset($this->_packageInfo['summary'])) {
  925.             return $this->_packageInfo['summary'];
  926.         }
  927.         return false;
  928.     }
  929.  
  930.     function getDescription()
  931.     {
  932.         if (isset($this->_packageInfo['description'])) {
  933.             return $this->_packageInfo['description'];
  934.         }
  935.         return false;
  936.     }
  937.  
  938.     function getMaintainers($raw = false)
  939.     {
  940.         if (!isset($this->_packageInfo['lead'])) {
  941.             return false;
  942.         }
  943.         if ($raw) {
  944.             $ret = array('lead' => $this->_packageInfo['lead']);
  945.             (isset($this->_packageInfo['developer'])) ?
  946.                 $ret['developer'] = $this->_packageInfo['developer'] :null;
  947.             (isset($this->_packageInfo['contributor'])) ?
  948.                 $ret['contributor'] = $this->_packageInfo['contributor'] :null;
  949.             (isset($this->_packageInfo['helper'])) ?
  950.                 $ret['helper'] = $this->_packageInfo['helper'] :null;
  951.             return $ret;
  952.         } else {
  953.             $ret = array();
  954.             $leads = isset($this->_packageInfo['lead'][0]) ? $this->_packageInfo['lead'] :
  955.                 array($this->_packageInfo['lead']);
  956.             foreach ($leads as $lead) {
  957.                 $s = $lead;
  958.                 $s['handle'] = $s['user'];
  959.                 unset($s['user']);
  960.                 $s['role'] = 'lead';
  961.                 $ret[] = $s;
  962.             }
  963.             if (isset($this->_packageInfo['developer'])) {
  964.                 $leads = isset($this->_packageInfo['developer'][0]) ?
  965.                     $this->_packageInfo['developer'] :
  966.                     array($this->_packageInfo['developer']);
  967.                 foreach ($leads as $maintainer) {
  968.                     $s = $maintainer;
  969.                     $s['handle'] = $s['user'];
  970.                     unset($s['user']);
  971.                     $s['role'] = 'developer';
  972.                     $ret[] = $s;
  973.                 }
  974.             }
  975.             if (isset($this->_packageInfo['contributor'])) {
  976.                 $leads = isset($this->_packageInfo['contributor'][0]) ?
  977.                     $this->_packageInfo['contributor'] :
  978.                     array($this->_packageInfo['contributor']);
  979.                 foreach ($leads as $maintainer) {
  980.                     $s = $maintainer;
  981.                     $s['handle'] = $s['user'];
  982.                     unset($s['user']);
  983.                     $s['role'] = 'contributor';
  984.                     $ret[] = $s;
  985.                 }
  986.             }
  987.             if (isset($this->_packageInfo['helper'])) {
  988.                 $leads = isset($this->_packageInfo['helper'][0]) ?
  989.                     $this->_packageInfo['helper'] :
  990.                     array($this->_packageInfo['helper']);
  991.                 foreach ($leads as $maintainer) {
  992.                     $s = $maintainer;
  993.                     $s['handle'] = $s['user'];
  994.                     unset($s['user']);
  995.                     $s['role'] = 'helper';
  996.                     $ret[] = $s;
  997.                 }
  998.             }
  999.             return $ret;
  1000.         }
  1001.         return false;
  1002.     }
  1003.  
  1004.     function getLeads()
  1005.     {
  1006.         if (isset($this->_packageInfo['lead'])) {
  1007.             return $this->_packageInfo['lead'];
  1008.         }
  1009.         return false;
  1010.     }
  1011.  
  1012.     function getDevelopers()
  1013.     {
  1014.         if (isset($this->_packageInfo['developer'])) {
  1015.             return $this->_packageInfo['developer'];
  1016.         }
  1017.         return false;
  1018.     }
  1019.  
  1020.     function getContributors()
  1021.     {
  1022.         if (isset($this->_packageInfo['contributor'])) {
  1023.             return $this->_packageInfo['contributor'];
  1024.         }
  1025.         return false;
  1026.     }
  1027.  
  1028.     function getHelpers()
  1029.     {
  1030.         if (isset($this->_packageInfo['helper'])) {
  1031.             return $this->_packageInfo['helper'];
  1032.         }
  1033.         return false;
  1034.     }
  1035.  
  1036.     function setDate($date)
  1037.     {
  1038.         if (!isset($this->_packageInfo['date'])) {
  1039.             // ensure that the extends tag is set up in the right location
  1040.             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
  1041.                 array('time', 'version',
  1042.                     'stability', 'license', 'notes', 'contents', 'compatible',
  1043.                     'dependencies', 'providesextension', 'srcpackage', 'srcuri',
  1044.                     'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
  1045.                     'zendextbinrelease', 'bundle', 'changelog'), array(), 'date');
  1046.         }
  1047.         $this->_packageInfo['date'] = $date;
  1048.         $this->_isValid = 0;
  1049.     }
  1050.  
  1051.     function setTime($time)
  1052.     {
  1053.         $this->_isValid = 0;
  1054.         if (!isset($this->_packageInfo['time'])) {
  1055.             // ensure that the time tag is set up in the right location
  1056.             $this->_packageInfo = $this->_insertBefore($this->_packageInfo,
  1057.                     array('version',
  1058.                     'stability', 'license', 'notes', 'contents', 'compatible',
  1059.                     'dependencies', 'providesextension', 'srcpackage', 'srcuri',
  1060.                     'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
  1061.                     'zendextbinrelease', 'bundle', 'changelog'), $time, 'time');
  1062.         }
  1063.         $this->_packageInfo['time'] = $time;
  1064.     }
  1065.  
  1066.     function getDate()
  1067.     {
  1068.         if (isset($this->_packageInfo['date'])) {
  1069.             return $this->_packageInfo['date'];
  1070.         }
  1071.         return false;
  1072.     }
  1073.  
  1074.     function getTime()
  1075.     {
  1076.         if (isset($this->_packageInfo['time'])) {
  1077.             return $this->_packageInfo['time'];
  1078.         }
  1079.         return false;
  1080.     }
  1081.  
  1082.     /**
  1083.      * @param package|api version category to return
  1084.      */
  1085.     function getVersion($key = 'release')
  1086.     {
  1087.         if (isset($this->_packageInfo['version'][$key])) {
  1088.             return $this->_packageInfo['version'][$key];
  1089.         }
  1090.         return false;
  1091.     }
  1092.  
  1093.     function getStability()
  1094.     {
  1095.         if (isset($this->_packageInfo['stability'])) {
  1096.             return $this->_packageInfo['stability'];
  1097.         }
  1098.         return false;
  1099.     }
  1100.  
  1101.     function getState($key = 'release')
  1102.     {
  1103.         if (isset($this->_packageInfo['stability'][$key])) {
  1104.             return $this->_packageInfo['stability'][$key];
  1105.         }
  1106.         return false;
  1107.     }
  1108.  
  1109.     function getLicense($raw = false)
  1110.     {
  1111.         if (isset($this->_packageInfo['license'])) {
  1112.             if ($raw) {
  1113.                 return $this->_packageInfo['license'];
  1114.             }
  1115.             if (is_array($this->_packageInfo['license'])) {
  1116.                 return $this->_packageInfo['license']['_content'];
  1117.             } else {
  1118.                 return $this->_packageInfo['license'];
  1119.             }
  1120.         }
  1121.         return false;
  1122.     }
  1123.  
  1124.     function getLicenseLocation()
  1125.     {
  1126.         if (!isset($this->_packageInfo['license']) || !is_array($this->_packageInfo['license'])) {
  1127.             return false;
  1128.         }
  1129.         return $this->_packageInfo['license']['attribs'];
  1130.     }
  1131.  
  1132.     function getNotes()
  1133.     {
  1134.         if (isset($this->_packageInfo['notes'])) {
  1135.             return $this->_packageInfo['notes'];
  1136.         }
  1137.         return false;
  1138.     }
  1139.  
  1140.     /**
  1141.      * Return the <usesrole> tag contents, if any
  1142.      * @return array|false
  1143.      */
  1144.     function getUsesrole()
  1145.     {
  1146.         if (isset($this->_packageInfo['usesrole'])) {
  1147.             return $this->_packageInfo['usesrole'];
  1148.         }
  1149.         return false;
  1150.     }
  1151.  
  1152.     /**
  1153.      * Return the <usestask> tag contents, if any
  1154.      * @return array|false
  1155.      */
  1156.     function getUsestask()
  1157.     {
  1158.         if (isset($this->_packageInfo['usestask'])) {
  1159.             return $this->_packageInfo['usestask'];
  1160.         }
  1161.         return false;
  1162.     }
  1163.  
  1164.     /**
  1165.      * This should only be used to retrieve filenames and install attributes
  1166.      */
  1167.     function getFilelist($preserve = false)
  1168.     {
  1169.         if (isset($this->_packageInfo['filelist']) && !$preserve) {
  1170.             return $this->_packageInfo['filelist'];
  1171.         }
  1172.         $this->flattenFilelist();
  1173.         if ($contents = $this->getContents()) {
  1174.             $ret = array();
  1175.             if (!isset($contents['dir']['file'][0])) {
  1176.                 $contents['dir']['file'] = array($contents['dir']['file']);
  1177.             }
  1178.             foreach ($contents['dir']['file'] as $file) {
  1179.                 $name = $file['attribs']['name'];
  1180.                 if (!$preserve) {
  1181.                     $file = $file['attribs'];
  1182.                 }
  1183.                 $ret[$name] = $file;
  1184.             }
  1185.             if (!$preserve) {
  1186.                 $this->_packageInfo['filelist'] = $ret;
  1187.             }
  1188.             return $ret;
  1189.         }
  1190.         return false;
  1191.     }
  1192.  
  1193.     /**
  1194.      * Return configure options array, if any
  1195.      *
  1196.      * @return array|false
  1197.      */
  1198.     function getConfigureOptions()
  1199.     {
  1200.         if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
  1201.             return false;
  1202.         }
  1203.         $releases = $this->getReleases();
  1204.         if (isset($releases[0])) {
  1205.             $releases = $releases[0];
  1206.         }
  1207.         if (isset($releases['configureoption'])) {
  1208.             if (!isset($releases['configureoption'][0])) {
  1209.                 $releases['configureoption'] = array($releases['configureoption']);
  1210.             }
  1211.             for ($i = 0; $i < count($releases['configureoption']); $i++) {
  1212.                 $releases['configureoption'][$i] = $releases['configureoption'][$i]['attribs'];
  1213.             }
  1214.             return $releases['configureoption'];
  1215.         }
  1216.         return false;
  1217.     }
  1218.  
  1219.     /**
  1220.      * This is only used at install-time, after all serialization
  1221.      * is over.
  1222.      */
  1223.     function resetFilelist()
  1224.     {
  1225.         $this->_packageInfo['filelist'] = array();
  1226.     }
  1227.  
  1228.     /**
  1229.      * Retrieve a list of files that should be installed on this computer
  1230.      * @return array
  1231.      */
  1232.     function getInstallationFilelist($forfilecheck = false)
  1233.     {
  1234.         $contents = $this->getFilelist(true);
  1235.         if (isset($contents['dir']['attribs']['baseinstalldir'])) {
  1236.             $base = $contents['dir']['attribs']['baseinstalldir'];
  1237.         }
  1238.         if (isset($this->_packageInfo['bundle'])) {
  1239.             return PEAR::raiseError(
  1240.                 'Exception: bundles should be handled in download code only');
  1241.         }
  1242.         $release = $this->getReleases();
  1243.         if ($release) {
  1244.             if (!isset($release[0])) {
  1245.                 if (!isset($release['installconditions']) && !isset($release['filelist'])) {
  1246.                     if ($forfilecheck) {
  1247.                         return $this->getFilelist();
  1248.                     }
  1249.                     return $contents;
  1250.                 }
  1251.                 $release = array($release);
  1252.             }
  1253.             $depchecker = &$this->getPEARDependency2($this->_config, array(),
  1254.                 array('channel' => $this->getChannel(), 'package' => $this->getPackage()),
  1255.                 PEAR_VALIDATE_INSTALLING);
  1256.             foreach ($release as $instance) {
  1257.                 if (isset($instance['installconditions'])) {
  1258.                     $installconditions = $instance['installconditions'];
  1259.                     if (is_array($installconditions)) {
  1260.                         PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  1261.                         foreach ($installconditions as $type => $conditions) {
  1262.                             if (!isset($conditions[0])) {
  1263.                                 $conditions = array($conditions);
  1264.                             }
  1265.                             foreach ($conditions as $condition) {
  1266.                                 $ret = $depchecker->{"validate{$type}Dependency"}($condition);
  1267.                                 if (PEAR::isError($ret)) {
  1268.                                     PEAR::popErrorHandling();
  1269.                                     continue 3; // skip this release
  1270.                                 }
  1271.                             }
  1272.                         }
  1273.                         PEAR::popErrorHandling();
  1274.                     }
  1275.                 }
  1276.                 // this is the release to use
  1277.                 if (isset($instance['filelist'])) {
  1278.                     // ignore files
  1279.                     if (isset($instance['filelist']['ignore'])) {
  1280.                         $ignore = isset($instance['filelist']['ignore'][0]) ?
  1281.                             $instance['filelist']['ignore'] :
  1282.                             array($instance['filelist']['ignore']);
  1283.                         foreach ($ignore as $ig) {
  1284.                             unset ($contents[$ig['attribs']['name']]);
  1285.                         }
  1286.                     }
  1287.                     // install files as this name
  1288.                     if (isset($instance['filelist']['install'])) {
  1289.                         $installas = isset($instance['filelist']['install'][0]) ?
  1290.                             $instance['filelist']['install'] :
  1291.                             array($instance['filelist']['install']);
  1292.                         foreach ($installas as $as) {
  1293.                             $contents[$as['attribs']['name']]['attribs']['install-as'] =
  1294.                                 $as['attribs']['as'];
  1295.                         }
  1296.                     }
  1297.                 }
  1298.                 if ($forfilecheck) {
  1299.                     foreach ($contents as $file => $attrs) {
  1300.                         $contents[$file] = $attrs['attribs'];
  1301.                     }
  1302.                 }
  1303.                 return $contents;
  1304.             }
  1305.         } else { // simple release - no installconditions or install-as
  1306.             if ($forfilecheck) {
  1307.                 return $this->getFilelist();
  1308.             }
  1309.             return $contents;
  1310.         }
  1311.         // no releases matched
  1312.         return PEAR::raiseError('No releases in package.xml matched the existing operating ' .
  1313.             'system, extensions installed, or architecture, cannot install');
  1314.     }
  1315.  
  1316.     /**
  1317.      * This is only used at install-time, after all serialization
  1318.      * is over.
  1319.      * @param string file name
  1320.      * @param string installed path
  1321.      */
  1322.     function setInstalledAs($file, $path)
  1323.     {
  1324.         if ($path) {
  1325.             return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
  1326.         }
  1327.         unset($this->_packageInfo['filelist'][$file]['installed_as']);
  1328.     }
  1329.  
  1330.     function getInstalledLocation($file)
  1331.     {
  1332.         if (isset($this->_packageInfo['filelist'][$file]['installed_as'])) {
  1333.             return $this->_packageInfo['filelist'][$file]['installed_as'];
  1334.         }
  1335.         return false;
  1336.     }
  1337.  
  1338.     /**
  1339.      * This is only used at install-time, after all serialization
  1340.      * is over.
  1341.      */
  1342.     function installedFile($file, $atts)
  1343.     {
  1344.         if (isset($this->_packageInfo['filelist'][$file])) {
  1345.             $this->_packageInfo['filelist'][$file] =
  1346.                 array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']);
  1347.         } else {
  1348.             $this->_packageInfo['filelist'][$file] = $atts['attribs'];
  1349.         }
  1350.     }
  1351.  
  1352.     /**
  1353.      * Retrieve the contents tag
  1354.      */
  1355.     function getContents()
  1356.     {
  1357.         if (isset($this->_packageInfo['contents'])) {
  1358.             return $this->_packageInfo['contents'];
  1359.         }
  1360.         return false;
  1361.     }
  1362.  
  1363.     /**
  1364.      * @param string full path to file
  1365.      * @param string attribute name
  1366.      * @param string attribute value
  1367.      * @param int risky but fast - use this to choose a file based on its position in the list
  1368.      *            of files.  Index is zero-based like PHP arrays.
  1369.      * @return bool success of operation
  1370.      */
  1371.     function setFileAttribute($filename, $attr, $value, $index = false)
  1372.     {
  1373.         $this->_isValid = 0;
  1374.         if (in_array($attr, array('role', 'name', 'baseinstalldir'))) {
  1375.             $this->_filesValid = false;
  1376.         }
  1377.         if ($index !== false &&
  1378.               isset($this->_packageInfo['contents']['dir']['file'][$index]['attribs'])) {
  1379.             $this->_packageInfo['contents']['dir']['file'][$index]['attribs'][$attr] = $value;
  1380.             return true;
  1381.         }
  1382.         if (!isset($this->_packageInfo['contents']['dir']['file'])) {
  1383.             return false;
  1384.         }
  1385.         $files = $this->_packageInfo['contents']['dir']['file'];
  1386.         if (!isset($files[0])) {
  1387.             $files = array($files);
  1388.             $ind = false;
  1389.         } else {
  1390.             $ind = true;
  1391.         }
  1392.         foreach ($files as $i => $file) {
  1393.             if (isset($file['attribs'])) {
  1394.                 if ($file['attribs']['name'] == $filename) {
  1395.                     if ($ind) {
  1396.                         $this->_packageInfo['contents']['dir']['file'][$i]['attribs'][$attr] = $value;
  1397.                     } else {
  1398.                         $this->_packageInfo['contents']['dir']['file']['attribs'][$attr] = $value;
  1399.                     }
  1400.                     return true;
  1401.                 }
  1402.             }
  1403.         }
  1404.         return false;
  1405.     }
  1406.  
  1407.     function setDirtree($path)
  1408.     {
  1409.         if (!isset($this->_packageInfo['dirtree'])) {
  1410.             $this->_packageInfo['dirtree'] = array();
  1411.         }
  1412.         $this->_packageInfo['dirtree'][$path] = true;
  1413.     }
  1414.  
  1415.     function getDirtree()
  1416.     {
  1417.         if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) {
  1418.             return $this->_packageInfo['dirtree'];
  1419.         }
  1420.         return false;
  1421.     }
  1422.  
  1423.     function resetDirtree()
  1424.     {
  1425.         unset($this->_packageInfo['dirtree']);
  1426.     }
  1427.  
  1428.     /**
  1429.      * Determines whether this package claims it is compatible with the version of
  1430.      * the package that has a recommended version dependency
  1431.      * @param PEAR_PackageFile_v2|PEAR_PackageFile_v1|PEAR_Downloader_Package
  1432.      * @return boolean
  1433.      */
  1434.     function isCompatible($pf)
  1435.     {
  1436.         if (!isset($this->_packageInfo['compatible'])) {
  1437.             return false;
  1438.         }
  1439.         if (!isset($this->_packageInfo['channel'])) {
  1440.             return false;
  1441.         }
  1442.         $me = $pf->getVersion();
  1443.         $compatible = $this->_packageInfo['compatible'];
  1444.         if (!isset($compatible[0])) {
  1445.             $compatible = array($compatible);
  1446.         }
  1447.         $found = false;
  1448.         foreach ($compatible as $info) {
  1449.             if (strtolower($info['name']) == strtolower($pf->getPackage())) {
  1450.                 if (strtolower($info['channel']) == strtolower($pf->getChannel())) {
  1451.                     $found = true;
  1452.                     break;
  1453.                 }
  1454.             }
  1455.         }
  1456.         if (!$found) {
  1457.             return false;
  1458.         }
  1459.         if (isset($info['exclude'])) {
  1460.             if (!isset($info['exclude'][0])) {
  1461.                 $info['exclude'] = array($info['exclude']);
  1462.             }
  1463.             foreach ($info['exclude'] as $exclude) {
  1464.                 if (version_compare($me, $exclude, '==')) {
  1465.                     return false;
  1466.                 }
  1467.             }
  1468.         }
  1469.         if (version_compare($me, $info['min'], '>=') && version_compare($me, $info['max'], '<=')) {
  1470.             return true;
  1471.         }
  1472.         return false;
  1473.     }
  1474.  
  1475.     /**
  1476.      * @return array|false
  1477.      */
  1478.     function getCompatible()
  1479.     {
  1480.         if (isset($this->_packageInfo['compatible'])) {
  1481.             return $this->_packageInfo['compatible'];
  1482.         }
  1483.         return false;
  1484.     }
  1485.  
  1486.     function getDependencies()
  1487.     {
  1488.         if (isset($this->_packageInfo['dependencies'])) {
  1489.             return $this->_packageInfo['dependencies'];
  1490.         }
  1491.         return false;
  1492.     }
  1493.  
  1494.     function isSubpackageOf($p)
  1495.     {
  1496.         return $p->isSubpackage($this);
  1497.     }
  1498.  
  1499.     /**
  1500.      * Determines whether the passed in package is a subpackage of this package.
  1501.      *
  1502.      * No version checking is done, only name verification.
  1503.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
  1504.      * @return bool
  1505.      */
  1506.     function isSubpackage($p)
  1507.     {
  1508.         $sub = array();
  1509.         if (isset($this->_packageInfo['dependencies']['required']['subpackage'])) {
  1510.             $sub = $this->_packageInfo['dependencies']['required']['subpackage'];
  1511.             if (!isset($sub[0])) {
  1512.                 $sub = array($sub);
  1513.             }
  1514.         }
  1515.         if (isset($this->_packageInfo['dependencies']['optional']['subpackage'])) {
  1516.             $sub1 = $this->_packageInfo['dependencies']['optional']['subpackage'];
  1517.             if (!isset($sub1[0])) {
  1518.                 $sub1 = array($sub1);
  1519.             }
  1520.             $sub = array_merge($sub, $sub1);
  1521.         }
  1522.         if (isset($this->_packageInfo['dependencies']['group'])) {
  1523.             $group = $this->_packageInfo['dependencies']['group'];
  1524.             if (!isset($group[0])) {
  1525.                 $group = array($group);
  1526.             }
  1527.             foreach ($group as $deps) {
  1528.                 if (isset($deps['subpackage'])) {
  1529.                     $sub2 = $deps['subpackage'];
  1530.                     if (!isset($sub2[0])) {
  1531.                         $sub2 = array($sub2);
  1532.                     }
  1533.                     $sub = array_merge($sub, $sub2);
  1534.                 }
  1535.             }
  1536.         }
  1537.         foreach ($sub as $dep) {
  1538.             if (strtolower($dep['name']) == strtolower($p->getPackage())) {
  1539.                 if (isset($dep['channel'])) {
  1540.                     if (strtolower($dep['channel']) == strtolower($p->getChannel())) {
  1541.                         return true;
  1542.                     }
  1543.                 } else {
  1544.                     if ($dep['uri'] == $p->getURI()) {
  1545.                         return true;
  1546.                     }
  1547.                 }
  1548.             }
  1549.         }
  1550.         return false;
  1551.     }
  1552.  
  1553.     function dependsOn($package, $channel)
  1554.     {
  1555.         if (!($deps = $this->getDependencies())) {
  1556.             return false;
  1557.         }
  1558.         foreach (array('package', 'subpackage') as $type) {
  1559.             foreach (array('required', 'optional') as $needed) {
  1560.                 if (isset($deps[$needed][$type])) {
  1561.                     if (!isset($deps[$needed][$type][0])) {
  1562.                         $deps[$needed][$type] = array($deps[$needed][$type]);
  1563.                     }
  1564.                     foreach ($deps[$needed][$type] as $dep) {
  1565.                         $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
  1566.                         if (strtolower($dep['name']) == strtolower($package) &&
  1567.                               $depchannel == $channel) {
  1568.                             return true;
  1569.                         }  
  1570.                     }
  1571.                 }
  1572.             }
  1573.             if (isset($deps['group'])) {
  1574.                 if (!isset($deps['group'][0])) {
  1575.                     $dep['group'] = array($deps['group']);
  1576.                 }
  1577.                 foreach ($deps['group'] as $group) {
  1578.                     if (isset($group[$type])) {
  1579.                         if (!is_array($group[$type])) {
  1580.                             $group[$type] = array($group[$type]);
  1581.                         }
  1582.                         foreach ($group[$type] as $dep) {
  1583.                             $depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
  1584.                             if (strtolower($dep['name']) == strtolower($package) &&
  1585.                                   $depchannel == $channel) {
  1586.                                 return true;
  1587.                             }  
  1588.                         }
  1589.                     }
  1590.                 }
  1591.             }
  1592.         }
  1593.         return false;
  1594.     }
  1595.  
  1596.     /**
  1597.      * Get the contents of a dependency group
  1598.      * @param string
  1599.      * @return array|false
  1600.      */
  1601.     function getDependencyGroup($name)
  1602.     {
  1603.         $name = strtolower($name);
  1604.         if (!isset($this->_packageInfo['dependencies']['group'])) {
  1605.             return false;
  1606.         }
  1607.         $groups = $this->_packageInfo['dependencies']['group'];
  1608.         if (!isset($groups[0])) {
  1609.             $groups = array($groups);
  1610.         }
  1611.         foreach ($groups as $group) {
  1612.             if (strtolower($group['attribs']['name']) == $name) {
  1613.                 return $group;
  1614.             }
  1615.         }
  1616.         return false;
  1617.     }
  1618.  
  1619.     /**
  1620.      * Retrieve a partial package.xml 1.0 representation of dependencies
  1621.      *
  1622.      * a very limited representation of dependencies is returned by this method.
  1623.      * The <exclude> tag for excluding certain versions of a dependency is
  1624.      * completely ignored.  In addition, dependency groups are ignored, with the
  1625.      * assumption that all dependencies in dependency groups are also listed in
  1626.      * the optional group that work with all dependency groups
  1627.      * @param boolean return package.xml 2.0 <dependencies> tag
  1628.      * @return array|false
  1629.      */
  1630.     function getDeps($raw = false, $nopearinstaller = false)
  1631.     {
  1632.         if (isset($this->_packageInfo['dependencies'])) {
  1633.             if ($raw) {
  1634.                 return $this->_packageInfo['dependencies'];
  1635.             }
  1636.             $ret = array();
  1637.             $map = array(
  1638.                 'php' => 'php',
  1639.                 'package' => 'pkg',
  1640.                 'subpackage' => 'pkg',
  1641.                 'extension' => 'ext',
  1642.                 'os' => 'os',
  1643.                 'pearinstaller' => 'pkg',
  1644.                 );
  1645.             foreach (array('required', 'optional') as $type) {
  1646.                 $optional = ($type == 'optional') ? 'yes' : 'no';
  1647.                 if (!isset($this->_packageInfo['dependencies'][$type])) {
  1648.                     continue;
  1649.                 }
  1650.                 foreach ($this->_packageInfo['dependencies'][$type] as $dtype => $deps) {
  1651.                     if ($dtype == 'pearinstaller' && $nopearinstaller) {
  1652.                         continue;
  1653.                     }
  1654.                     if (!isset($deps[0])) {
  1655.                         $deps = array($deps);
  1656.                     }
  1657.                     foreach ($deps as $dep) {
  1658.                         if (!isset($map[$dtype])) {
  1659.                             // no support for arch type
  1660.                             continue;
  1661.                         }
  1662.                         if ($dtype == 'pearinstaller') {
  1663.                             $dep['name'] = 'PEAR';
  1664.                             $dep['channel'] = 'pear.php.net';
  1665.                         }
  1666.                         $s = array('type' => $map[$dtype]);
  1667.                         if (isset($dep['channel'])) {
  1668.                             $s['channel'] = $dep['channel'];
  1669.                         }
  1670.                         if (isset($dep['uri'])) {
  1671.                             $s['uri'] = $dep['uri'];
  1672.                         }
  1673.                         if (isset($dep['name'])) {
  1674.                             $s['name'] = $dep['name'];
  1675.                         }
  1676.                         if (isset($dep['conflicts'])) {
  1677.                             $s['rel'] = 'not';
  1678.                         } else {
  1679.                             if (!isset($dep['min']) &&
  1680.                                   !isset($dep['max'])) {
  1681.                                 $s['rel'] = 'has';
  1682.                                 $s['optional'] = $optional;
  1683.                             } elseif (isset($dep['min']) &&
  1684.                                   isset($dep['max'])) {
  1685.                                 $s['rel'] = 'ge';
  1686.                                 $s1 = $s;
  1687.                                 $s1['rel'] = 'le';
  1688.                                 $s['version'] = $dep['min'];
  1689.                                 $s1['version'] = $dep['max'];
  1690.                                 if (isset($dep['channel'])) {
  1691.                                     $s1['channel'] = $dep['channel'];
  1692.                                 }
  1693.                                 if ($dtype != 'php') {
  1694.                                     $s['name'] = $dep['name'];
  1695.                                     $s1['name'] = $dep['name'];
  1696.                                 }
  1697.                                 $s['optional'] = $optional;
  1698.                                 $s1['optional'] = $optional;
  1699.                                 $ret[] = $s1;
  1700.                             } elseif (isset($dep['min'])) {
  1701.                                 if (isset($dep['exclude']) &&
  1702.                                       $dep['exclude'] == $dep['min']) {
  1703.                                     $s['rel'] = 'gt';
  1704.                                 } else {
  1705.                                     $s['rel'] = 'ge';
  1706.                                 }
  1707.                                 $s['version'] = $dep['min'];
  1708.                                 $s['optional'] = $optional;
  1709.                                 if ($dtype != 'php') {
  1710.                                     $s['name'] = $dep['name'];
  1711.                                 }
  1712.                             } elseif (isset($dep['max'])) {
  1713.                                 if (isset($dep['exclude']) &&
  1714.                                       $dep['exclude'] == $dep['max']) {
  1715.                                     $s['rel'] = 'lt';
  1716.                                 } else {
  1717.                                     $s['rel'] = 'le';
  1718.                                 }
  1719.                                 $s['version'] = $dep['max'];
  1720.                                 $s['optional'] = $optional;
  1721.                                 if ($dtype != 'php') {
  1722.                                     $s['name'] = $dep['name'];
  1723.                                 }
  1724.                             }
  1725.                         }
  1726.                         $ret[] = $s;
  1727.                     }
  1728.                 }
  1729.             }
  1730.             if (count($ret)) {
  1731.                 return $ret;
  1732.             }
  1733.         }
  1734.         return false;
  1735.     }
  1736.  
  1737.     /**
  1738.      * @return php|extsrc|extbin|zendextsrc|zendextbin|bundle|false
  1739.      */
  1740.     function getPackageType()
  1741.     {
  1742.         if (isset($this->_packageInfo['phprelease'])) {
  1743.             return 'php';
  1744.         }
  1745.         if (isset($this->_packageInfo['extsrcrelease'])) {
  1746.             return 'extsrc';
  1747.         }
  1748.         if (isset($this->_packageInfo['extbinrelease'])) {
  1749.             return 'extbin';
  1750.         }
  1751.         if (isset($this->_packageInfo['zendextsrcrelease'])) {
  1752.             return 'zendextsrc';
  1753.         }
  1754.         if (isset($this->_packageInfo['zendextbinrelease'])) {
  1755.             return 'zendextbin';
  1756.         }
  1757.         if (isset($this->_packageInfo['bundle'])) {
  1758.             return 'bundle';
  1759.         }
  1760.         return false;
  1761.     }
  1762.  
  1763.     /**
  1764.      * @return array|false
  1765.      */
  1766.     function getReleases()
  1767.     {
  1768.         $type = $this->getPackageType();
  1769.         if ($type != 'bundle') {
  1770.             $type .= 'release';
  1771.         }
  1772.         if ($this->getPackageType() && isset($this->_packageInfo[$type])) {
  1773.             return $this->_packageInfo[$type];
  1774.         }
  1775.         return false;
  1776.     }
  1777.  
  1778.     /**
  1779.      * @return array
  1780.      */
  1781.     function getChangelog()
  1782.     {
  1783.         if (isset($this->_packageInfo['changelog'])) {
  1784.             return $this->_packageInfo['changelog'];
  1785.         }
  1786.         return false;
  1787.     }
  1788.  
  1789.     function hasDeps()
  1790.     {
  1791.         return isset($this->_packageInfo['dependencies']);
  1792.     }
  1793.  
  1794.     function getPackagexmlVersion()
  1795.     {
  1796.         if (isset($this->_packageInfo['zendextsrcrelease'])) {
  1797.             return '2.1';
  1798.         }
  1799.         if (isset($this->_packageInfo['zendextbinrelease'])) {
  1800.             return '2.1';
  1801.         }
  1802.         return '2.0';
  1803.     }
  1804.  
  1805.     /**
  1806.      * @return array|false
  1807.      */
  1808.     function getSourcePackage()
  1809.     {
  1810.         if (isset($this->_packageInfo['extbinrelease']) ||
  1811.               isset($this->_packageInfo['zendextbinrelease'])) {
  1812.             return array('channel' => $this->_packageInfo['srcchannel'],
  1813.                          'package' => $this->_packageInfo['srcpackage']);
  1814.         }
  1815.         return false;
  1816.     }
  1817.  
  1818.     function getBundledPackages()
  1819.     {
  1820.         if (isset($this->_packageInfo['bundle'])) {
  1821.             return $this->_packageInfo['contents']['bundledpackage'];
  1822.         }
  1823.         return false;
  1824.     }
  1825.  
  1826.     function getLastModified()
  1827.     {
  1828.         if (isset($this->_packageInfo['_lastmodified'])) {
  1829.             return $this->_packageInfo['_lastmodified'];
  1830.         }
  1831.         return false;
  1832.     }
  1833.  
  1834.     /**
  1835.      * Get the contents of a file listed within the package.xml
  1836.      * @param string
  1837.      * @return string
  1838.      */
  1839.     function getFileContents($file)
  1840.     {
  1841.         if ($this->_archiveFile == $this->_packageFile) { // unpacked
  1842.             $dir = dirname($this->_packageFile);
  1843.             $file = $dir . DIRECTORY_SEPARATOR . $file;
  1844.             $file = str_replace(array('/', '\\'),
  1845.                 array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file);
  1846.             if (file_exists($file) && is_readable($file)) {
  1847.                 return implode('', file($file));
  1848.             }
  1849.         } else { // tgz
  1850.             $tar = &new Archive_Tar($this->_archiveFile);
  1851.             $tar->pushErrorHandling(PEAR_ERROR_RETURN);
  1852.             if ($file != 'package.xml' && $file != 'package2.xml') {
  1853.                 $file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file;
  1854.             }
  1855.             $file = $tar->extractInString($file);
  1856.             $tar->popErrorHandling();
  1857.             if (PEAR::isError($file)) {
  1858.                 return PEAR::raiseError("Cannot locate file '$file' in archive");
  1859.             }
  1860.             return $file;
  1861.         }
  1862.     }
  1863.  
  1864.     function &getRW()
  1865.     {
  1866.         if (!class_exists('PEAR_PackageFile_v2_rw')) {
  1867.             require_once 'PEAR/PackageFile/v2/rw.php';
  1868.         }
  1869.         $a = new PEAR_PackageFile_v2_rw;
  1870.         foreach (get_object_vars($this) as $name => $unused) {
  1871.             if (!isset($this->$name)) {
  1872.                 continue;
  1873.             }
  1874.             if ($name == '_config' || $name == '_logger'|| $name == '_registry' ||
  1875.                   $name == '_stack') {
  1876.                 $a->$name = &$this->$name;
  1877.             } else {
  1878.                 $a->$name = $this->$name;
  1879.             }
  1880.         }
  1881.         return $a;
  1882.     }
  1883.  
  1884.     function &getDefaultGenerator()
  1885.     {
  1886.         if (!class_exists('PEAR_PackageFile_Generator_v2')) {
  1887.             require_once 'PEAR/PackageFile/Generator/v2.php';
  1888.         }
  1889.         $a = &new PEAR_PackageFile_Generator_v2($this);
  1890.         return $a;
  1891.     }
  1892.  
  1893.     function analyzeSourceCode($file, $string = false)
  1894.     {
  1895.         if (!isset($this->_v2Validator) ||
  1896.               !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
  1897.             if (!class_exists('PEAR_PackageFile_v2_Validator')) {
  1898.                 require_once 'PEAR/PackageFile/v2/Validator.php';
  1899.             }
  1900.             $this->_v2Validator = new PEAR_PackageFile_v2_Validator;
  1901.         }
  1902.         return $this->_v2Validator->analyzeSourceCode($file, $string);
  1903.     }
  1904.  
  1905.     function validate($state = PEAR_VALIDATE_NORMAL)
  1906.     {
  1907.         if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
  1908.             return false;
  1909.         }
  1910.         if (!isset($this->_v2Validator) ||
  1911.               !is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
  1912.             if (!class_exists('PEAR_PackageFile_v2_Validator')) {
  1913.                 require_once 'PEAR/PackageFile/v2/Validator.php';
  1914.             }
  1915.             $this->_v2Validator = new PEAR_PackageFile_v2_Validator;
  1916.         }
  1917.         if (isset($this->_packageInfo['xsdversion'])) {
  1918.             unset($this->_packageInfo['xsdversion']);
  1919.         }
  1920.         return $this->_v2Validator->validate($this, $state);
  1921.     }
  1922.  
  1923.     function getTasksNs()
  1924.     {
  1925.         if (!isset($this->_tasksNs)) {
  1926.             if (isset($this->_packageInfo['attribs'])) {
  1927.                 foreach ($this->_packageInfo['attribs'] as $name => $value) {
  1928.                     if ($value == 'http://pear.php.net/dtd/tasks-1.0') {
  1929.                         $this->_tasksNs = str_replace('xmlns:', '', $name);
  1930.                         break;
  1931.                     }
  1932.                 }
  1933.             }
  1934.         }
  1935.         return $this->_tasksNs;
  1936.     }
  1937.  
  1938.     /**
  1939.      * Determine whether a task name is a valid task.  Custom tasks may be defined
  1940.      * using subdirectories by putting a "-" in the name, as in <tasks:mycustom-task>
  1941.      *
  1942.      * Note that this method will auto-load the task class file and test for the existence
  1943.      * of the name with "-" replaced by "_" as in PEAR/Task/mycustom/task.php makes class
  1944.      * PEAR_Task_mycustom_task
  1945.      * @param string
  1946.      * @return boolean
  1947.      */
  1948.     function getTask($task)
  1949.     {
  1950.         $this->getTasksNs();
  1951.         // transform all '-' to '/' and 'tasks:' to '' so tasks:replace becomes replace
  1952.         $task = str_replace(array($this->_tasksNs . ':', '-'), array('', ' '), $task);
  1953.         $taskfile = str_replace(' ', '/', ucwords($task));
  1954.         $task = str_replace(array(' ', '/'), '_', ucwords($task));
  1955.         if (class_exists("PEAR_Task_$task")) {
  1956.             return "PEAR_Task_$task";
  1957.         }
  1958.         $fp = @fopen("PEAR/Task/$taskfile.php", 'r', true);
  1959.         if ($fp) {
  1960.             fclose($fp);
  1961.             require_once "PEAR/Task/$taskfile.php";
  1962.             return "PEAR_Task_$task";
  1963.         }
  1964.         return false;
  1965.     }
  1966.  
  1967.     /**
  1968.      * Key-friendly array_splice
  1969.      * @param tagname to splice a value in before
  1970.      * @param mixed the value to splice in
  1971.      * @param string the new tag name
  1972.      */
  1973.     function _ksplice($array, $key, $value, $newkey)
  1974.     {
  1975.         $offset = array_search($key, array_keys($array));
  1976.         $after = array_slice($array, $offset);
  1977.         $before = array_slice($array, 0, $offset);
  1978.         $before[$newkey] = $value;
  1979.         return array_merge($before, $after);
  1980.     }
  1981.  
  1982.     /**
  1983.      * @param array a list of possible keys, in the order they may occur
  1984.      * @param mixed contents of the new package.xml tag
  1985.      * @param string tag name
  1986.      * @access private
  1987.      */
  1988.     function _insertBefore($array, $keys, $contents, $newkey)
  1989.     {
  1990.         foreach ($keys as $key) {
  1991.             if (isset($array[$key])) {
  1992.                 return $array = $this->_ksplice($array, $key, $contents, $newkey);
  1993.             }
  1994.         }
  1995.         $array[$newkey] = $contents;
  1996.         return $array;
  1997.     }
  1998.  
  1999.     /**
  2000.      * @param subsection of {@link $_packageInfo}
  2001.      * @param array|string tag contents
  2002.      * @param array format:
  2003.      * <pre>
  2004.      * array(
  2005.      *   tagname => array(list of tag names that follow this one),
  2006.      *   childtagname => array(list of child tag names that follow this one),
  2007.      * )
  2008.      * </pre>
  2009.      *
  2010.      * This allows construction of nested tags
  2011.      * @access private
  2012.      */
  2013.     function _mergeTag($manip, $contents, $order)
  2014.     {
  2015.         if (count($order)) {
  2016.             foreach ($order as $tag => $curorder) {
  2017.                 if (!isset($manip[$tag])) {
  2018.                     // ensure that the tag is set up
  2019.                     $manip = $this->_insertBefore($manip, $curorder, array(), $tag);
  2020.                 }
  2021.                 if (count($order) > 1) {
  2022.                     $manip[$tag] = $this->_mergeTag($manip[$tag], $contents, array_slice($order, 1));
  2023.                     return $manip;
  2024.                 }
  2025.             }
  2026.         } else {
  2027.             return $manip;
  2028.         }
  2029.         if (is_array($manip[$tag]) && !empty($manip[$tag]) && isset($manip[$tag][0])) {
  2030.             $manip[$tag][] = $contents;
  2031.         } else {
  2032.             if (!count($manip[$tag])) {
  2033.                 $manip[$tag] = $contents;
  2034.             } else {
  2035.                 $manip[$tag] = array($manip[$tag]);
  2036.                 $manip[$tag][] = $contents;
  2037.             }
  2038.         }
  2039.         return $manip;
  2040.     }
  2041. }
  2042. ?>
  2043.