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.php < prev    next >
Encoding:
PHP Script  |  2008-02-15  |  16.2 KB  |  475 lines

  1. <?php
  2. /**
  3.  * PEAR_PackageFile, package.xml parsing utility class
  4.  *
  5.  * PHP versions 4 and 5
  6.  *
  7.  * LICENSE: This source file is subject to version 3.0 of the PHP license
  8.  * that is available through the world-wide-web at the following URI:
  9.  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  10.  * the PHP License and are unable to obtain it through the web, please
  11.  * send a note to license@php.net so we can mail you a copy immediately.
  12.  *
  13.  * @category   pear
  14.  * @package    PEAR
  15.  * @author     Greg Beaver <cellog@php.net>
  16.  * @copyright  1997-2008 The PHP Group
  17.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  18.  * @version    CVS: $Id: PackageFile.php,v 1.41 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. /**
  24.  * needed for PEAR_VALIDATE_* constants
  25.  */
  26. require_once 'PEAR/Validate.php';
  27. /**
  28.  * Error code if the package.xml <package> tag does not contain a valid version
  29.  */
  30. define('PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION', 1);
  31. /**
  32.  * Error code if the package.xml <package> tag version is not supported (version 1.0 and 1.1 are the only supported versions,
  33.  * currently
  34.  */
  35. define('PEAR_PACKAGEFILE_ERROR_INVALID_PACKAGEVERSION', 2);
  36. /**
  37.  * Abstraction for the package.xml package description file
  38.  *
  39.  * @category   pear
  40.  * @package    PEAR
  41.  * @author     Greg Beaver <cellog@php.net>
  42.  * @copyright  1997-2008 The PHP Group
  43.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  44.  * @version    Release: 1.7.1
  45.  * @link       http://pear.php.net/package/PEAR
  46.  * @since      Class available since Release 1.4.0a1
  47.  */
  48. class PEAR_PackageFile
  49. {
  50.     /**
  51.      * @var PEAR_Config
  52.      */
  53.     var $_config;
  54.     var $_debug;
  55.     /**
  56.      * Temp directory for uncompressing tgz files.
  57.      * @var string|false
  58.      */
  59.     var $_tmpdir;
  60.     var $_logger = false;
  61.     /**
  62.      * @var boolean
  63.      */
  64.     var $_rawReturn = false;
  65.  
  66.     /**
  67.      *
  68.      * @param   PEAR_Config $config
  69.      * @param   ?   $debug
  70.      * @param   string @tmpdir Optional temporary directory for uncompressing
  71.      *          files
  72.      */
  73.     function PEAR_PackageFile(&$config, $debug = false, $tmpdir = false)
  74.     {
  75.         $this->_config = $config;
  76.         $this->_debug = $debug;
  77.         $this->_tmpdir = $tmpdir;
  78.     }
  79.  
  80.     /**
  81.      * Turn off validation - return a parsed package.xml without checking it
  82.      *
  83.      * This is used by the package-validate command
  84.      */
  85.     function rawReturn()
  86.     {
  87.         $this->_rawReturn = true;
  88.     }
  89.  
  90.     function setLogger(&$l)
  91.     {
  92.         $this->_logger = &$l;
  93.     }
  94.  
  95.     /**
  96.      * Create a PEAR_PackageFile_Parser_v* of a given version.
  97.      * @param   int $version
  98.      * @return  PEAR_PackageFile_Parser_v1|PEAR_PackageFile_Parser_v1
  99.      */
  100.     function &parserFactory($version)
  101.     {
  102.         if (!in_array($version{0}, array('1', '2'))) {
  103.             $a = false;
  104.             return $a;
  105.         }
  106.         include_once 'PEAR/PackageFile/Parser/v' . $version{0} . '.php';
  107.         $version = $version{0};
  108.         $class = "PEAR_PackageFile_Parser_v$version";
  109.         $a = new $class;
  110.         return $a;
  111.     }
  112.  
  113.     /**
  114.      * For simpler unit-testing
  115.      * @return string
  116.      */
  117.     function getClassPrefix()
  118.     {
  119.         return 'PEAR_PackageFile_v';
  120.     }
  121.  
  122.     /**
  123.      * Create a PEAR_PackageFile_v* of a given version.
  124.      * @param   int $version
  125.      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v1
  126.      */
  127.     function &factory($version)
  128.     {
  129.         if (!in_array($version{0}, array('1', '2'))) {
  130.             $a = false;
  131.             return $a;
  132.         }
  133.         include_once 'PEAR/PackageFile/v' . $version{0} . '.php';
  134.         $version = $version{0};
  135.         $class = $this->getClassPrefix() . $version;
  136.         $a = new $class;
  137.         return $a;
  138.     }
  139.  
  140.     /**
  141.      * Create a PEAR_PackageFile_v* from its toArray() method
  142.      *
  143.      * WARNING: no validation is performed, the array is assumed to be valid,
  144.      * always parse from xml if you want validation.
  145.      * @param   array $arr
  146.      * @return PEAR_PackageFileManager_v1|PEAR_PackageFileManager_v2
  147.      * @uses    factory() to construct the returned object.
  148.      */
  149.     function &fromArray($arr)
  150.     {
  151.         if (isset($arr['xsdversion'])) {
  152.             $obj = &$this->factory($arr['xsdversion']);
  153.             if ($this->_logger) {
  154.                 $obj->setLogger($this->_logger);
  155.             }
  156.             $obj->setConfig($this->_config);
  157.             $obj->fromArray($arr);
  158.             return $obj;
  159.         } else {
  160.             if (isset($arr['package']['attribs']['version'])) {
  161.                 $obj = &$this->factory($arr['package']['attribs']['version']);
  162.             } else {
  163.                 $obj = &$this->factory('1.0');
  164.             }
  165.             if ($this->_logger) {
  166.                 $obj->setLogger($this->_logger);
  167.             }
  168.             $obj->setConfig($this->_config);
  169.             $obj->fromArray($arr);
  170.             return $obj;
  171.         }
  172.     }
  173.  
  174.     /**
  175.      * Create a PEAR_PackageFile_v* from an XML string.
  176.      * @access  public
  177.      * @param   string $data contents of package.xml file
  178.      * @param   int $state package state (one of PEAR_VALIDATE_* constants)
  179.      * @param   string $file full path to the package.xml file (and the files
  180.      *          it references)
  181.      * @param   string $archive optional name of the archive that the XML was
  182.      *          extracted from, if any
  183.      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
  184.      * @uses    parserFactory() to construct a parser to load the package.
  185.      */
  186.     function &fromXmlString($data, $state, $file, $archive = false)
  187.     {
  188.         if (preg_match('/<package[^>]+version="([0-9]+\.[0-9]+)"/', $data, $packageversion)) {
  189.             if (!in_array($packageversion[1], array('1.0', '2.0', '2.1'))) {
  190.                 return PEAR::raiseError('package.xml version "' . $packageversion[1] .
  191.                     '" is not supported, only 1.0, 2.0, and 2.1 are supported.');
  192.             }
  193.             $object = &$this->parserFactory($packageversion[1]);
  194.             if ($this->_logger) {
  195.                 $object->setLogger($this->_logger);
  196.             }
  197.             $object->setConfig($this->_config);
  198.             $pf = $object->parse($data, $file, $archive);
  199.             if (PEAR::isError($pf)) {
  200.                 return $pf;
  201.             }
  202.             if ($this->_rawReturn) {
  203.                 return $pf;
  204.             }
  205.             if ($pf->validate($state)) {
  206.                 if ($this->_logger) {
  207.                     if ($pf->getValidationWarnings(false)) {
  208.                         foreach ($pf->getValidationWarnings() as $warning) {
  209.                             $this->_logger->log(0, 'WARNING: ' . $warning['message']);
  210.                         }
  211.                     }
  212.                 }
  213.                 if (method_exists($pf, 'flattenFilelist')) {
  214.                     $pf->flattenFilelist(); // for v2
  215.                 }
  216.                 return $pf;
  217.             } else {
  218.                 if ($this->_config->get('verbose') > 0) {
  219.                     if ($this->_logger) {
  220.                         if ($pf->getValidationWarnings(false)) {
  221.                             foreach ($pf->getValidationWarnings(false) as $warning) {
  222.                                 $this->_logger->log(0, 'ERROR: ' . $warning['message']);
  223.                             }
  224.                         }
  225.                     }
  226.                 }
  227.                 $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed',
  228.                     2, null, null, $pf->getValidationWarnings());
  229.                 return $a;
  230.             }
  231.         } elseif (preg_match('/<package[^>]+version="([^"]+)"/', $data, $packageversion)) {
  232.             $a = PEAR::raiseError('package.xml file "' . $file .
  233.                 '" has unsupported package.xml <package> version "' . $packageversion[1] . '"');
  234.             return $a;
  235.         } else {
  236.             if (!class_exists('PEAR_ErrorStack')) {
  237.                 require_once 'PEAR/ErrorStack.php';
  238.             }
  239.             PEAR_ErrorStack::staticPush('PEAR_PackageFile',
  240.                 PEAR_PACKAGEFILE_ERROR_NO_PACKAGEVERSION,
  241.                 'warning', array('xml' => $data), 'package.xml "' . $file .
  242.                     '" has no package.xml <package> version');
  243.             $object = &$this->parserFactory('1.0');
  244.             $object->setConfig($this->_config);
  245.             $pf = $object->parse($data, $file, $archive);
  246.             if (PEAR::isError($pf)) {
  247.                 return $pf;
  248.             }
  249.             if ($this->_rawReturn) {
  250.                 return $pf;
  251.             }
  252.             if ($pf->validate($state)) {
  253.                 if ($this->_logger) {
  254.                     if ($pf->getValidationWarnings(false)) {
  255.                         foreach ($pf->getValidationWarnings() as $warning) {
  256.                             $this->_logger->log(0, 'WARNING: ' . $warning['message']);
  257.                         }
  258.                     }
  259.                 }
  260.                 if (method_exists($pf, 'flattenFilelist')) {
  261.                     $pf->flattenFilelist(); // for v2
  262.                 }
  263.                 return $pf;
  264.             } else {
  265.                 $a = PEAR::raiseError('Parsing of package.xml from file "' . $file . '" failed',
  266.                     2, null, null, $pf->getValidationWarnings());
  267.                 return $a;
  268.             }
  269.         }
  270.     }
  271.  
  272.     /**
  273.      * Register a temporary file or directory.  When the destructor is
  274.      * executed, all registered temporary files and directories are
  275.      * removed.
  276.      *
  277.      * @param string  $file  name of file or directory
  278.      * @return  void
  279.      */
  280.     function addTempFile($file)
  281.     {
  282.         $GLOBALS['_PEAR_Common_tempfiles'][] = $file;
  283.     }
  284.  
  285.     /**
  286.      * Create a PEAR_PackageFile_v* from a compresed Tar or Tgz file.
  287.      * @access  public
  288.      * @param string contents of package.xml file
  289.      * @param int package state (one of PEAR_VALIDATE_* constants)
  290.      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
  291.      * @using   Archive_Tar to extract the files
  292.      * @using   fromPackageFile() to load the package after the package.xml
  293.      *          file is extracted.
  294.      */
  295.     function &fromTgzFile($file, $state)
  296.     {
  297.         if (!class_exists('Archive_Tar')) {
  298.             require_once 'Archive/Tar.php';
  299.         }
  300.         $tar = new Archive_Tar($file);
  301.         if ($this->_debug <= 1) {
  302.             $tar->pushErrorHandling(PEAR_ERROR_RETURN);
  303.         }
  304.         $content = $tar->listContent();
  305.         if ($this->_debug <= 1) {
  306.             $tar->popErrorHandling();
  307.         }
  308.         if (!is_array($content)) {
  309.             if (is_string($file) && strlen($file < 255) &&
  310.                   (!file_exists($file) || !@is_file($file))) {
  311.                 $ret = PEAR::raiseError("could not open file \"$file\"");
  312.                 return $ret;
  313.             }
  314.             $file = realpath($file);
  315.             $ret = PEAR::raiseError("Could not get contents of package \"$file\"".
  316.                                      '. Invalid tgz file.');
  317.             return $ret;
  318.         } else {
  319.             if (!count($content) && !@is_file($file)) {
  320.                 $ret = PEAR::raiseError("could not open file \"$file\"");
  321.                 return $ret;
  322.             }
  323.         }
  324.         $xml = null;
  325.         $origfile = $file;
  326.         foreach ($content as $file) {
  327.             $name = $file['filename'];
  328.             if ($name == 'package2.xml') { // allow a .tgz to distribute both versions
  329.                 $xml = $name;
  330.                 break;
  331.             }
  332.             if ($name == 'package.xml') {
  333.                 $xml = $name;
  334.                 break;
  335.             } elseif (ereg('package.xml$', $name, $match)) {
  336.                 $xml = $name;
  337.                 break;
  338.             }
  339.         }
  340.         if ($this->_tmpdir) {
  341.             $tmpdir = $this->_tmpdir;
  342.         } else {
  343.             $tmpdir = System::mkTemp(array('-d', 'pear'));
  344.             PEAR_PackageFile::addTempFile($tmpdir);
  345.         }
  346.         $this->_extractErrors();
  347.         PEAR::staticPushErrorHandling(PEAR_ERROR_CALLBACK, array($this, '_extractErrors'));
  348.         if (!$xml || !$tar->extractList(array($xml), $tmpdir)) {
  349.             $extra = implode("\n", $this->_extractErrors());
  350.             if ($extra) {
  351.                 $extra = ' ' . $extra;
  352.             }
  353.             PEAR::staticPopErrorHandling();
  354.             $ret = PEAR::raiseError('could not extract the package.xml file from "' .
  355.                 $origfile . '"' . $extra);
  356.             return $ret;
  357.         }
  358.         PEAR::staticPopErrorHandling();
  359.         $ret = &PEAR_PackageFile::fromPackageFile("$tmpdir/$xml", $state, $origfile);
  360.         return $ret;
  361.     }
  362.  
  363.     /**
  364.      * helper for extracting Archive_Tar errors
  365.      * @var array
  366.      * @access private
  367.      */
  368.     var $_extractErrors = array();
  369.  
  370.     /**
  371.      * helper callback for extracting Archive_Tar errors
  372.      *
  373.      * @param PEAR_Error|null $err
  374.      * @return array
  375.      * @access private
  376.      */
  377.     function _extractErrors($err = null)
  378.     {
  379.         static $errors = array();
  380.         if ($err === null) {
  381.             $e = $errors;
  382.             $errors = array();
  383.             return $e;
  384.         }
  385.         $errors[] = $err->getMessage();
  386.     }
  387.  
  388.     /**
  389.      * Create a PEAR_PackageFile_v* from a package.xml file.
  390.      *
  391.      * @access public
  392.      * @param   string  $descfile  name of package xml file
  393.      * @param   int     $state package state (one of PEAR_VALIDATE_* constants)
  394.      * @param   string|false $archive name of the archive this package.xml came
  395.      *          from, if any
  396.      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
  397.      * @uses    PEAR_PackageFile::fromXmlString to create the oject after the
  398.      *          XML is loaded from the package.xml file.
  399.      */
  400.     function &fromPackageFile($descfile, $state, $archive = false)
  401.     {
  402.         if (is_string($descfile) && strlen($descfile) < 255 &&
  403.              (!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) ||
  404.              (!$fp = @fopen($descfile, 'r')))) {
  405.             $a = PEAR::raiseError("Unable to open $descfile");
  406.             return $a;
  407.         }
  408.  
  409.         // read the whole thing so we only get one cdata callback
  410.         // for each block of cdata
  411.         fclose($fp);
  412.         $data = file_get_contents($descfile);
  413.         $ret = &PEAR_PackageFile::fromXmlString($data, $state, $descfile, $archive);
  414.         return $ret;
  415.     }
  416.  
  417.  
  418.     /**
  419.      * Create a PEAR_PackageFile_v* from a .tgz archive or package.xml file.
  420.      *
  421.      * This method is able to extract information about a package from a .tgz
  422.      * archive or from a XML package definition file.
  423.      *
  424.      * @access public
  425.      * @param   string  $info file name
  426.      * @param   int     $state package state (one of PEAR_VALIDATE_* constants)
  427.      * @return  PEAR_PackageFile_v1|PEAR_PackageFile_v2
  428.      * @uses    fromPackageFile() if the file appears to be XML
  429.      * @uses    fromTgzFile() to load all non-XML files
  430.      */
  431.     function &fromAnyFile($info, $state)
  432.     {
  433.         if (is_dir($info)) {
  434.             $dir_name = realpath($info);
  435.             if (file_exists($dir_name . '/package.xml')) {
  436.                 $info = PEAR_PackageFile::fromPackageFile($dir_name .  '/package.xml', $state);
  437.             } elseif (file_exists($dir_name .  '/package2.xml')) {
  438.                 $info = PEAR_PackageFile::fromPackageFile($dir_name .  '/package2.xml', $state);
  439.             } else {
  440.                 $info = PEAR::raiseError("No package definition found in '$info' directory");
  441.             }
  442.             return $info;
  443.         }
  444.  
  445.         $fp = false;
  446.         if (is_string($info) && strlen($info) < 255 &&
  447.              (file_exists($info) || ($fp = @fopen($info, 'r')))) {
  448.             if ($fp) {
  449.                 fclose($fp);
  450.             }
  451.             $tmp = substr($info, -4);
  452.             if ($tmp == '.xml') {
  453.                 $info = &PEAR_PackageFile::fromPackageFile($info, $state);
  454.             } elseif ($tmp == '.tar' || $tmp == '.tgz') {
  455.                 $info = &PEAR_PackageFile::fromTgzFile($info, $state);
  456.             } else {
  457.                 $fp = fopen($info, "r");
  458.                 $test = fread($fp, 5);
  459.                 fclose($fp);
  460.                 if ($test == "<?xml") {
  461.                     $info = &PEAR_PackageFile::fromPackageFile($info, $state);
  462.                 } else {
  463.                     $info = &PEAR_PackageFile::fromTgzFile($info, $state);
  464.                 }
  465.             }
  466.         } else {
  467.             $info = PEAR::raiseError("Cannot open '$info' for parsing");
  468.             return $info;
  469.         }
  470.         return $info;
  471.     }
  472. }
  473.  
  474. ?>
  475.