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

Source for file PackageFile.php

Documentation is available at PackageFile.php

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

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