home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 April / PCWorld_2005-04_cd.bin / akce / web / phptriad / phptriad2-2-1.exe / php / pear / PEAR / Common.php next >
PHP Script  |  2001-11-13  |  14KB  |  414 lines

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4.0                                                      |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2001 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 of the PHP license,      |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Stig Bakken <ssb@fast.no>                                   |
  17. // |          Tomas V.V.Cox <cox@idecnet.com>                             |
  18. // |                                                                      |
  19. // +----------------------------------------------------------------------+
  20. //
  21. // $Id: Common.php,v 1.8.2.3 2001/11/13 01:26:48 ssb Exp $
  22.  
  23. require_once 'PEAR.php';
  24. require_once 'Archive/Tar.php';
  25. require_once 'System.php';
  26.  
  27. /**
  28.  * TODO:
  29.  *   - check in inforFromDescFile that the minimal data needed is present
  30.  *     (pack name, version, files, others?)
  31.  *   - perhaps use parser folding to be less restrictive with the format
  32.  *     of the package.xml file
  33.  */
  34. class PEAR_Common extends PEAR
  35. {
  36.     // {{{ properties
  37.  
  38.     /** stack of elements, gives some sort of XML context */
  39.     var $element_stack = array();
  40.  
  41.     /** name of currently parsed XML element */
  42.     var $current_element;
  43.  
  44.     /** array of attributes of the currently parsed XML element */
  45.     var $current_attributes = array();
  46.  
  47.     /** list of temporary files created by this object */
  48.     var $_tempfiles = array();
  49.  
  50.     /** assoc with information about a package */
  51.     var $pkginfo = array();
  52.  
  53.     /**
  54.      * Permitted maintainer roles
  55.      * @var array
  56.      */
  57.     var $maintainer_roles = array('lead','developer','contributor','helper');
  58.  
  59.     /**
  60.      * Permitted release states
  61.      * @var array
  62.      */
  63.     var $releases_states  = array('alpha','beta','stable','snapshot');
  64.  
  65.     // }}}
  66.  
  67.     // {{{ constructor
  68.  
  69.     function PEAR_Common()
  70.     {
  71.         $this->PEAR();
  72.     }
  73.  
  74.     // }}}
  75.     // {{{ destructor
  76.  
  77.     function _PEAR_Common()
  78.     {
  79.         while (is_array($this->_tempfiles) &&
  80.                $file = array_shift($this->_tempfiles))
  81.         {
  82.             if (@is_dir($file)) {
  83.                 System::rm("-rf $file");
  84.             } elseif (file_exists($file)) {
  85.                 unlink($file);
  86.             }
  87.         }
  88.     }
  89.  
  90.     // }}}
  91.     // {{{ addTempFile()
  92.  
  93.     function addTempFile($file)
  94.     {
  95.         $this->_tempfiles[] = $file;
  96.     }
  97.  
  98.     // }}}
  99.     // {{{ mkDirHier()
  100.  
  101.     function mkDirHier($dir)
  102.     {
  103.         $dirstack = array();
  104.         while (!@is_dir($dir) && $dir != DIRECTORY_SEPARATOR) {
  105.             array_unshift($dirstack, $dir);
  106.             $dir = dirname($dir);
  107.         }
  108.         while ($newdir = array_shift($dirstack)) {
  109.             if (mkdir($newdir, 0755)) {
  110.                 $this->log(2, "+ created dir $newdir");
  111.             } else {
  112.                 return false;
  113.             }
  114.         }
  115.         return true;
  116.     }
  117.  
  118.     // }}}
  119.     // {{{ log()
  120.  
  121.     function log($level, $msg)
  122.     {
  123.         if ($this->debug >= $level) {
  124.             print "$msg\n";
  125.         }
  126.     }
  127.  
  128.     // }}}
  129.     // {{{ mkTempDir()
  130.  
  131.     function mkTempDir()
  132.     {
  133.         $dir = (OS_WINDOWS) ? 'c:\\windows\\temp' : '/tmp';
  134.         $tmpdir = tempnam($dir, 'pear');
  135.         unlink($tmpdir);
  136.         if (!mkdir($tmpdir, 0700)) {
  137.             return $this->raiseError("Unable to create temporary directory $tmpdir");
  138.         }
  139.         $this->addTempFile($tmpdir);
  140.         return $tmpdir;
  141.     }
  142.  
  143.     // }}}
  144.     // {{{ _element_start()
  145.  
  146.     function _element_start($xp, $name, $attribs)
  147.     {
  148.         array_push($this->element_stack, $name);
  149.         $this->current_element = $name;
  150.         $spos = sizeof($this->element_stack) - 2;
  151.         $this->prev_element = ($spos >= 0) ? $this->element_stack[$spos] : '';
  152.         $this->current_attributes = $attribs;
  153.         switch ($name) {
  154.             case 'dir':
  155.                 if (isset($this->dir_names)) {
  156.                     $this->dir_names[] = $attribs['name'];
  157.                 } else {
  158.                     // Don't add the root dir
  159.                     $this->dir_names = array();
  160.                 }
  161.                 if (isset($attribs['baseinstalldir'])) {
  162.                     $this->dir_install = $attribs['baseinstalldir'];
  163.                 }
  164.                 if (isset($attribs['role'])) {
  165.                     $this->dir_role = $attribs['role'];
  166.                 }
  167.                 break;
  168.             case 'libfile':
  169.                 $this->lib_atts = $attribs;
  170.                 $this->lib_atts['role'] = 'extension';
  171.                 break;
  172.             case 'maintainers':
  173.                 $this->pkginfo['maintainers'] = array();
  174.                 $this->m_i = 0; // maintainers array index
  175.                 break;
  176.             case 'maintainer':
  177.                 // compatibility check
  178.                 if (!isset($this->pkginfo['maintainers'])) {
  179.                     $this->pkginfo['maintainers'] = array();
  180.                     $this->m_i = 0;
  181.                 }
  182.                 $this->pkginfo['maintainers'][$this->m_i] = array();
  183.                 $this->current_maintainer =& $this->pkginfo['maintainers'][$this->m_i];
  184.                 break;
  185.             case 'changelog':
  186.                 $this->pkginfo['changelog'] = array();
  187.                 $this->c_i = 0; // changelog array index
  188.                 $this->in_changelog = true;
  189.                 break;
  190.             case 'release':
  191.                 if ($this->in_changelog) {
  192.                     $this->pkginfo['changelog'][$this->c_i] = array();
  193.                     $this->current_release =& $this->pkginfo['changelog'][$this->c_i];
  194.                 }
  195.                 break;
  196.         }
  197.     }
  198.  
  199.     // }}}
  200.     // {{{ _element_end()
  201.  
  202.     function _element_end($xp, $name)
  203.     {
  204.         switch ($name) {
  205.             case 'dir':
  206.                 array_pop($this->dir_names);
  207.                 break;
  208.             case 'file':
  209.                 $path = '';
  210.                 foreach ($this->dir_names as $dir) {
  211.                     $path .= $dir . DIRECTORY_SEPARATOR;
  212.                 }
  213.                 $path .= $this->current_file;
  214.                 $this->filelist[$path] = $this->current_attributes;
  215.                 // Set the baseinstalldir only if the file don't have this attrib
  216.                 if (!isset($this->filelist[$path]['baseinstalldir']) &&
  217.                     isset($this->dir_install))
  218.                 {
  219.                     $this->filelist[$path]['baseinstalldir'] = $this->dir_install;
  220.                 }
  221.                 // Set the Role
  222.                 if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
  223.                     $this->filelist[$path]['role'] = $this->dir_role;
  224.                 }
  225.                 break;
  226.             case 'libfile':
  227.                 $path = '';
  228.                 foreach ($this->dir_names as $dir) {
  229.                     $path .= $dir . DIRECTORY_SEPARATOR;
  230.                 }
  231.                 $path .= $this->lib_name;
  232.                 $this->filelist[$path] = $this->lib_atts;
  233.                 // Set the baseinstalldir only if the file don't have this attrib
  234.                 if (!isset($this->filelist[$path]['baseinstalldir']) &&
  235.                     isset($this->dir_install))
  236.                 {
  237.                     $this->filelist[$path]['baseinstalldir'] = $this->dir_install;
  238.                 }
  239.                 if (isset($this->lib_sources)) {
  240.                     $this->filelist[$path]['sources'] = $this->lib_sources;
  241.                 }
  242.                 unset($this->lib_atts);
  243.                 unset($this->lib_sources);
  244.                 break;
  245.             case 'maintainer':
  246.                 $this->m_i++;
  247.                 break;
  248.             case 'release':
  249.                 if ($this->in_changelog) {
  250.                     $this->c_i++;
  251.                 }
  252.                 break;
  253.             case 'changelog':
  254.                 $this->in_changelog = false;
  255.         }
  256.         array_pop($this->element_stack);
  257.         $spos = sizeof($this->element_stack) - 1;
  258.         $this->current_element = ($spos > 0) ? $this->element_stack[$spos] : '';
  259.     }
  260.  
  261.     // }}}
  262.     // {{{ _pkginfo_cdata()
  263.  
  264.     function _pkginfo_cdata($xp, $data)
  265.     {
  266.         switch ($this->current_element) {
  267.             case 'name':
  268.                 switch ($this->prev_element) {
  269.                     case 'package':
  270.                         $this->pkginfo['package'] = $data;
  271.                         break;
  272.                     case 'maintainer':
  273.                         $this->current_maintainer['name'] = $data;
  274.                         break;
  275.                 }
  276.                 break;
  277.             case 'summary':
  278.                 $this->pkginfo['summary'] = $data;
  279.                 break;
  280.             case 'user':
  281.                 $this->current_maintainer['handle'] = $data;
  282.                 break;
  283.             case 'email':
  284.                 $this->current_maintainer['email'] = $data;
  285.                 break;
  286.             case 'role':
  287.                 if (!in_array($data, $this->maintainer_roles)) {
  288.                     trigger_error("The maintainer role: '$data' is not valid", E_USER_WARNING);
  289.                 } else {
  290.                     $this->current_maintainer['role'] = $data;
  291.                 }
  292.                 break;
  293.             case 'version':
  294.                 if ($this->in_changelog) {
  295.                     $this->current_release['version'] = $data;
  296.                 } else {
  297.                     $this->pkginfo['version'] = $data;
  298.                 }
  299.                 break;
  300.             case 'date':
  301.                 if ($this->in_changelog) {
  302.                     $this->current_release['release_date'] = $data;
  303.                 } else {
  304.                     $this->pkginfo['release_date'] = $data;
  305.                 }
  306.                 break;
  307.             case 'notes':
  308.                 if ($this->in_changelog) {
  309.                     $this->current_release['release_notes'] = $data;
  310.                 } else {
  311.                     $this->pkginfo['release_notes'] = $data;
  312.                 }
  313.                 break;
  314.             case 'state':
  315.                 if (!in_array($data, $this->releases_states)) {
  316.                     trigger_error("The release state: '$data' is not valid", E_USER_WARNING);
  317.                 } elseif ($this->in_changelog) {
  318.                     $this->current_release['release_state'] = $data;
  319.                 } else {
  320.                     $this->pkginfo['release_state'] = $data;
  321.                 }
  322.                 break;
  323.             case 'dir':
  324.                 break;
  325.             case 'file':
  326.                 $this->current_file = trim($data);
  327.                 break;
  328.             case 'libname':
  329.                 $this->lib_name = trim($data);
  330.                 break;
  331.             case 'sources':
  332.                 $this->lib_sources[] = trim($data);
  333.                 break;
  334.         }
  335.     }
  336.  
  337.     // }}}
  338.     // {{{ infoFromDescriptionFile()
  339.  
  340.     function infoFromDescriptionFile($descfile)
  341.     {
  342.         if (!@is_file($descfile) || !is_readable($descfile) ||
  343.              (!$fp = @fopen($descfile, 'r'))) {
  344.             return $this->raiseError("Unable to open $descfile");
  345.         }
  346.         $xp = @xml_parser_create();
  347.         if (!$xp) {
  348.             return $this->raiseError('Unable to create XML parser');
  349.         }
  350.         xml_set_object($xp, $this);
  351.         xml_set_element_handler($xp, '_element_start', '_element_end');
  352.         xml_set_character_data_handler($xp, '_pkginfo_cdata');
  353.         xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false);
  354.  
  355.         $this->element_stack = array();
  356.         $this->pkginfo = array();
  357.         $this->current_element = false;
  358.         $this->destdir = '';
  359.         $this->pkginfo['filelist'] = array();
  360.         $this->filelist =& $this->pkginfo['filelist'];
  361.         $this->in_changelog = false;
  362.  
  363.         // read the whole thing so we only get one cdata callback
  364.         // for each block of cdata
  365.         $data = fread($fp, filesize($descfile));
  366.         if (!xml_parse($xp, $data, 1)) {
  367.             $msg = sprintf("XML error: %s at line %d",
  368.                            xml_error_string(xml_get_error_code($xp)),
  369.                            xml_get_current_line_number($xp));
  370.             xml_parser_free($xp);
  371.             return $this->raiseError($msg);
  372.         }
  373.  
  374.         xml_parser_free($xp);
  375.  
  376.         foreach ($this->pkginfo as $k => $v) {
  377.             if (!is_array($v)) {
  378.                 $this->pkginfo[$k] = trim($v);
  379.             }
  380.         }
  381.         return $this->pkginfo;
  382.     }
  383.     // }}}
  384.     // {{{ infoFromTgzFile()
  385.  
  386.     /**
  387.     * Returns info from a tgz pear package
  388.     * (experimental)
  389.     */
  390.     function infoFromTgzFile($file)
  391.     {
  392.         $file = basename($file); // XXX Fixme: Only allows file in the current dir
  393.         if (!@is_file($file)) {
  394.             return $this->raiseError('no tar file supplied');
  395.         }
  396.         // Assume the decompressed dir name
  397.         if (($pos = strrpos($file, '.')) === false) {
  398.             return $this->raiseError('file doesn\'t follow the package name convention');
  399.         }
  400.         $pkgdir = substr($file, 0, $pos);
  401.         $xml = $pkgdir . DIRECTORY_SEPARATOR . 'package.xml';
  402.  
  403.         $tar = new Archive_Tar($file, true);
  404.         if (!$tar->extractList($xml)) {
  405.             return $this->raiseError('could not extract the package.xml file');
  406.         }
  407.         $info = $this->infoFromDescriptionFile($xml);
  408.         unlink($xml);
  409.         return $info;
  410.     }
  411.  
  412.     // }}}
  413. }
  414. ?>