Subversion Repositories Applications.gtt

Compare Revisions

Ignore whitespace Rev 93 → Rev 94

/trunk/bibliotheque/pear/PEAR/PackageFile/Generator/v1.php
New file
0,0 → 1,1272
<?php
/**
* package.xml generation class, package.xml version 1.0
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: v1.php,v 1.72 2006/05/10 02:56:19 cellog Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* needed for PEAR_VALIDATE_* constants
*/
require_once 'PEAR/Validate.php';
require_once 'System.php';
require_once 'PEAR/PackageFile/v2.php';
/**
* This class converts a PEAR_PackageFile_v1 object into any output format.
*
* Supported output formats include array, XML string, and a PEAR_PackageFile_v2
* object, for converting package.xml 1.0 into package.xml 2.0 with no sweat.
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.5.1
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_PackageFile_Generator_v1
{
/**
* @var PEAR_PackageFile_v1
*/
var $_packagefile;
function PEAR_PackageFile_Generator_v1(&$packagefile)
{
$this->_packagefile = &$packagefile;
}
 
function getPackagerVersion()
{
return '1.5.1';
}
 
/**
* @param PEAR_Packager
* @param bool if true, a .tgz is written, otherwise a .tar is written
* @param string|null directory in which to save the .tgz
* @return string|PEAR_Error location of package or error object
*/
function toTgz(&$packager, $compress = true, $where = null)
{
require_once 'Archive/Tar.php';
if ($where === null) {
if (!($where = System::mktemp(array('-d')))) {
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: mktemp failed');
}
} elseif (!@System::mkDir(array('-p', $where))) {
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: "' . $where . '" could' .
' not be created');
}
if (file_exists($where . DIRECTORY_SEPARATOR . 'package.xml') &&
!is_file($where . DIRECTORY_SEPARATOR . 'package.xml')) {
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: unable to save package.xml as' .
' "' . $where . DIRECTORY_SEPARATOR . 'package.xml"');
}
if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) {
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: invalid package file');
}
$pkginfo = $this->_packagefile->getArray();
$ext = $compress ? '.tgz' : '.tar';
$pkgver = $pkginfo['package'] . '-' . $pkginfo['version'];
$dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext;
if (file_exists(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext) &&
!is_file(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext)) {
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: cannot create tgz file "' .
getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext . '"');
}
if ($pkgfile = $this->_packagefile->getPackageFile()) {
$pkgdir = dirname(realpath($pkgfile));
$pkgfile = basename($pkgfile);
} else {
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: package file object must ' .
'be created from a real file');
}
// {{{ Create the package file list
$filelist = array();
$i = 0;
 
foreach ($this->_packagefile->getFilelist() as $fname => $atts) {
$file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
if (!file_exists($file)) {
return PEAR::raiseError("File does not exist: $fname");
} else {
$filelist[$i++] = $file;
if (!isset($atts['md5sum'])) {
$this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($file));
}
$packager->log(2, "Adding file $fname");
}
}
// }}}
$packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true);
if ($packagexml) {
$tar =& new Archive_Tar($dest_package, $compress);
$tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors
// ----- Creates with the package.xml file
$ok = $tar->createModify(array($packagexml), '', $where);
if (PEAR::isError($ok)) {
return $ok;
} elseif (!$ok) {
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed');
}
// ----- Add the content of the package
if (!$tar->addModify($filelist, $pkgver, $pkgdir)) {
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed');
}
return $dest_package;
}
}
 
/**
* @param string|null directory to place the package.xml in, or null for a temporary dir
* @param int one of the PEAR_VALIDATE_* constants
* @param string name of the generated file
* @param bool if true, then no analysis will be performed on role="php" files
* @return string|PEAR_Error path to the created file on success
*/
function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml',
$nofilechecking = false)
{
if (!$this->_packagefile->validate($state, $nofilechecking)) {
return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: invalid package.xml',
null, null, null, $this->_packagefile->getValidationWarnings());
}
if ($where === null) {
if (!($where = System::mktemp(array('-d')))) {
return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: mktemp failed');
}
} elseif (!@System::mkDir(array('-p', $where))) {
return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: "' . $where . '" could' .
' not be created');
}
$newpkgfile = $where . DIRECTORY_SEPARATOR . $name;
$np = @fopen($newpkgfile, 'wb');
if (!$np) {
return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: unable to save ' .
"$name as $newpkgfile");
}
fwrite($np, $this->toXml($state, true));
fclose($np);
return $newpkgfile;
}
 
/**
* fix both XML encoding to be UTF8, and replace standard XML entities < > " & '
*
* @param string $string
* @return string
* @access private
*/
function _fixXmlEncoding($string)
{
if (version_compare(phpversion(), '5.0.0', 'lt')) {
$string = utf8_encode($string);
}
return strtr($string, array(
'&' => '&amp;',
'>' => '&gt;',
'<' => '&lt;',
'"' => '&quot;',
'\'' => '&apos;' ));
}
 
/**
* Return an XML document based on the package info (as returned
* by the PEAR_Common::infoFrom* methods).
*
* @return string XML data
*/
function toXml($state = PEAR_VALIDATE_NORMAL, $nofilevalidation = false)
{
$this->_packagefile->setDate(date('Y-m-d'));
if (!$this->_packagefile->validate($state, $nofilevalidation)) {
return false;
}
$pkginfo = $this->_packagefile->getArray();
static $maint_map = array(
"handle" => "user",
"name" => "name",
"email" => "email",
"role" => "role",
);
$ret = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
$ret .= "<!DOCTYPE package SYSTEM \"http://pear.php.net/dtd/package-1.0\">\n";
$ret .= "<package version=\"1.0\" packagerversion=\"1.5.1\">\n" .
" <name>$pkginfo[package]</name>";
if (isset($pkginfo['extends'])) {
$ret .= "\n<extends>$pkginfo[extends]</extends>";
}
$ret .=
"\n <summary>".$this->_fixXmlEncoding($pkginfo['summary'])."</summary>\n" .
" <description>".trim($this->_fixXmlEncoding($pkginfo['description']))."\n </description>\n" .
" <maintainers>\n";
foreach ($pkginfo['maintainers'] as $maint) {
$ret .= " <maintainer>\n";
foreach ($maint_map as $idx => $elm) {
$ret .= " <$elm>";
$ret .= $this->_fixXmlEncoding($maint[$idx]);
$ret .= "</$elm>\n";
}
$ret .= " </maintainer>\n";
}
$ret .= " </maintainers>\n";
$ret .= $this->_makeReleaseXml($pkginfo, false, $state);
if (isset($pkginfo['changelog']) && count($pkginfo['changelog']) > 0) {
$ret .= " <changelog>\n";
foreach ($pkginfo['changelog'] as $oldrelease) {
$ret .= $this->_makeReleaseXml($oldrelease, true);
}
$ret .= " </changelog>\n";
}
$ret .= "</package>\n";
return $ret;
}
 
// }}}
// {{{ _makeReleaseXml()
 
/**
* Generate part of an XML description with release information.
*
* @param array $pkginfo array with release information
* @param bool $changelog whether the result will be in a changelog element
*
* @return string XML data
*
* @access private
*/
function _makeReleaseXml($pkginfo, $changelog = false, $state = PEAR_VALIDATE_NORMAL)
{
// XXX QUOTE ENTITIES IN PCDATA, OR EMBED IN CDATA BLOCKS!!
$indent = $changelog ? " " : "";
$ret = "$indent <release>\n";
if (!empty($pkginfo['version'])) {
$ret .= "$indent <version>$pkginfo[version]</version>\n";
}
if (!empty($pkginfo['release_date'])) {
$ret .= "$indent <date>$pkginfo[release_date]</date>\n";
}
if (!empty($pkginfo['release_license'])) {
$ret .= "$indent <license>$pkginfo[release_license]</license>\n";
}
if (!empty($pkginfo['release_state'])) {
$ret .= "$indent <state>$pkginfo[release_state]</state>\n";
}
if (!empty($pkginfo['release_notes'])) {
$ret .= "$indent <notes>".trim($this->_fixXmlEncoding($pkginfo['release_notes']))
."\n$indent </notes>\n";
}
if (!empty($pkginfo['release_warnings'])) {
$ret .= "$indent <warnings>".$this->_fixXmlEncoding($pkginfo['release_warnings'])."</warnings>\n";
}
if (isset($pkginfo['release_deps']) && sizeof($pkginfo['release_deps']) > 0) {
$ret .= "$indent <deps>\n";
foreach ($pkginfo['release_deps'] as $dep) {
$ret .= "$indent <dep type=\"$dep[type]\" rel=\"$dep[rel]\"";
if (isset($dep['version'])) {
$ret .= " version=\"$dep[version]\"";
}
if (isset($dep['optional'])) {
$ret .= " optional=\"$dep[optional]\"";
}
if (isset($dep['name'])) {
$ret .= ">$dep[name]</dep>\n";
} else {
$ret .= "/>\n";
}
}
$ret .= "$indent </deps>\n";
}
if (isset($pkginfo['configure_options'])) {
$ret .= "$indent <configureoptions>\n";
foreach ($pkginfo['configure_options'] as $c) {
$ret .= "$indent <configureoption name=\"".
$this->_fixXmlEncoding($c['name']) . "\"";
if (isset($c['default'])) {
$ret .= " default=\"" . $this->_fixXmlEncoding($c['default']) . "\"";
}
$ret .= " prompt=\"" . $this->_fixXmlEncoding($c['prompt']) . "\"";
$ret .= "/>\n";
}
$ret .= "$indent </configureoptions>\n";
}
if (isset($pkginfo['provides'])) {
foreach ($pkginfo['provides'] as $key => $what) {
$ret .= "$indent <provides type=\"$what[type]\" ";
$ret .= "name=\"$what[name]\" ";
if (isset($what['extends'])) {
$ret .= "extends=\"$what[extends]\" ";
}
$ret .= "/>\n";
}
}
if (isset($pkginfo['filelist'])) {
$ret .= "$indent <filelist>\n";
if ($state ^ PEAR_VALIDATE_PACKAGING) {
$ret .= $this->recursiveXmlFilelist($pkginfo['filelist']);
} else {
foreach ($pkginfo['filelist'] as $file => $fa) {
if (!isset($fa['role'])) {
$fa['role'] = '';
}
$ret .= "$indent <file role=\"$fa[role]\"";
if (isset($fa['baseinstalldir'])) {
$ret .= ' baseinstalldir="' .
$this->_fixXmlEncoding($fa['baseinstalldir']) . '"';
}
if (isset($fa['md5sum'])) {
$ret .= " md5sum=\"$fa[md5sum]\"";
}
if (isset($fa['platform'])) {
$ret .= " platform=\"$fa[platform]\"";
}
if (!empty($fa['install-as'])) {
$ret .= ' install-as="' .
$this->_fixXmlEncoding($fa['install-as']) . '"';
}
$ret .= ' name="' . $this->_fixXmlEncoding($file) . '"';
if (empty($fa['replacements'])) {
$ret .= "/>\n";
} else {
$ret .= ">\n";
foreach ($fa['replacements'] as $r) {
$ret .= "$indent <replace";
foreach ($r as $k => $v) {
$ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"';
}
$ret .= "/>\n";
}
$ret .= "$indent </file>\n";
}
}
}
$ret .= "$indent </filelist>\n";
}
$ret .= "$indent </release>\n";
return $ret;
}
 
/**
* @param array
* @access protected
*/
function recursiveXmlFilelist($list)
{
$this->_dirs = array();
foreach ($list as $file => $attributes) {
$this->_addDir($this->_dirs, explode('/', dirname($file)), $file, $attributes);
}
return $this->_formatDir($this->_dirs);
}
 
/**
* @param array
* @param array
* @param string|null
* @param array|null
* @access private
*/
function _addDir(&$dirs, $dir, $file = null, $attributes = null)
{
if ($dir == array() || $dir == array('.')) {
$dirs['files'][basename($file)] = $attributes;
return;
}
$curdir = array_shift($dir);
if (!isset($dirs['dirs'][$curdir])) {
$dirs['dirs'][$curdir] = array();
}
$this->_addDir($dirs['dirs'][$curdir], $dir, $file, $attributes);
}
 
/**
* @param array
* @param string
* @param string
* @access private
*/
function _formatDir($dirs, $indent = '', $curdir = '')
{
$ret = '';
if (!count($dirs)) {
return '';
}
if (isset($dirs['dirs'])) {
uksort($dirs['dirs'], 'strnatcasecmp');
foreach ($dirs['dirs'] as $dir => $contents) {
$usedir = "$curdir/$dir";
$ret .= "$indent <dir name=\"$dir\">\n";
$ret .= $this->_formatDir($contents, "$indent ", $usedir);
$ret .= "$indent </dir> <!-- $usedir -->\n";
}
}
if (isset($dirs['files'])) {
uksort($dirs['files'], 'strnatcasecmp');
foreach ($dirs['files'] as $file => $attribs) {
$ret .= $this->_formatFile($file, $attribs, $indent);
}
}
return $ret;
}
 
/**
* @param string
* @param array
* @param string
* @access private
*/
function _formatFile($file, $attributes, $indent)
{
$ret = "$indent <file role=\"$attributes[role]\"";
if (isset($attributes['baseinstalldir'])) {
$ret .= ' baseinstalldir="' .
$this->_fixXmlEncoding($attributes['baseinstalldir']) . '"';
}
if (isset($attributes['md5sum'])) {
$ret .= " md5sum=\"$attributes[md5sum]\"";
}
if (isset($attributes['platform'])) {
$ret .= " platform=\"$attributes[platform]\"";
}
if (!empty($attributes['install-as'])) {
$ret .= ' install-as="' .
$this->_fixXmlEncoding($attributes['install-as']) . '"';
}
$ret .= ' name="' . $this->_fixXmlEncoding($file) . '"';
if (empty($attributes['replacements'])) {
$ret .= "/>\n";
} else {
$ret .= ">\n";
foreach ($attributes['replacements'] as $r) {
$ret .= "$indent <replace";
foreach ($r as $k => $v) {
$ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"';
}
$ret .= "/>\n";
}
$ret .= "$indent </file>\n";
}
return $ret;
}
 
// {{{ _unIndent()
 
/**
* Unindent given string (?)
*
* @param string $str The string that has to be unindented.
* @return string
* @access private
*/
function _unIndent($str)
{
// remove leading newlines
$str = preg_replace('/^[\r\n]+/', '', $str);
// find whitespace at the beginning of the first line
$indent_len = strspn($str, " \t");
$indent = substr($str, 0, $indent_len);
$data = '';
// remove the same amount of whitespace from following lines
foreach (explode("\n", $str) as $line) {
if (substr($line, 0, $indent_len) == $indent) {
$data .= substr($line, $indent_len) . "\n";
}
}
return $data;
}
 
/**
* @return array
*/
function dependenciesToV2()
{
$arr = array();
$this->_convertDependencies2_0($arr);
return $arr['dependencies'];
}
 
/**
* Convert a package.xml version 1.0 into version 2.0
*
* Note that this does a basic conversion, to allow more advanced
* features like bundles and multiple releases
* @param string the classname to instantiate and return. This must be
* PEAR_PackageFile_v2 or a descendant
* @param boolean if true, only valid, deterministic package.xml 1.0 as defined by the
* strictest parameters will be converted
* @return PEAR_PackageFile_v2|PEAR_Error
*/
function &toV2($class = 'PEAR_PackageFile_v2', $strict = false)
{
if ($strict) {
if (!$this->_packagefile->validate()) {
$a = PEAR::raiseError('invalid package.xml version 1.0 cannot be converted' .
' to version 2.0', null, null, null,
$this->_packagefile->getValidationWarnings(true));
return $a;
}
}
$arr = array(
'attribs' => array(
'version' => '2.0',
'xmlns' => 'http://pear.php.net/dtd/package-2.0',
'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation' => "http://pear.php.net/dtd/tasks-1.0\n" .
"http://pear.php.net/dtd/tasks-1.0.xsd\n" .
"http://pear.php.net/dtd/package-2.0\n" .
'http://pear.php.net/dtd/package-2.0.xsd',
),
'name' => $this->_packagefile->getPackage(),
'channel' => 'pear.php.net',
);
$arr['summary'] = $this->_packagefile->getSummary();
$arr['description'] = $this->_packagefile->getDescription();
$maintainers = $this->_packagefile->getMaintainers();
foreach ($maintainers as $maintainer) {
if ($maintainer['role'] != 'lead') {
continue;
}
$new = array(
'name' => $maintainer['name'],
'user' => $maintainer['handle'],
'email' => $maintainer['email'],
'active' => 'yes',
);
$arr['lead'][] = $new;
}
if (!isset($arr['lead'])) { // some people... you know?
$arr['lead'] = array(
'name' => 'unknown',
'user' => 'unknown',
'email' => 'noleadmaintainer@example.com',
'active' => 'no',
);
}
if (count($arr['lead']) == 1) {
$arr['lead'] = $arr['lead'][0];
}
foreach ($maintainers as $maintainer) {
if ($maintainer['role'] == 'lead') {
continue;
}
$new = array(
'name' => $maintainer['name'],
'user' => $maintainer['handle'],
'email' => $maintainer['email'],
'active' => 'yes',
);
$arr[$maintainer['role']][] = $new;
}
if (isset($arr['developer']) && count($arr['developer']) == 1) {
$arr['developer'] = $arr['developer'][0];
}
if (isset($arr['contributor']) && count($arr['contributor']) == 1) {
$arr['contributor'] = $arr['contributor'][0];
}
if (isset($arr['helper']) && count($arr['helper']) == 1) {
$arr['helper'] = $arr['helper'][0];
}
$arr['date'] = $this->_packagefile->getDate();
$arr['version'] =
array(
'release' => $this->_packagefile->getVersion(),
'api' => $this->_packagefile->getVersion(),
);
$arr['stability'] =
array(
'release' => $this->_packagefile->getState(),
'api' => $this->_packagefile->getState(),
);
$licensemap =
array(
'php' => 'http://www.php.net/license',
'php license' => 'http://www.php.net/license',
'lgpl' => 'http://www.gnu.org/copyleft/lesser.html',
'bsd' => 'http://www.opensource.org/licenses/bsd-license.php',
'bsd style' => 'http://www.opensource.org/licenses/bsd-license.php',
'bsd-style' => 'http://www.opensource.org/licenses/bsd-license.php',
'mit' => 'http://www.opensource.org/licenses/mit-license.php',
'gpl' => 'http://www.gnu.org/copyleft/gpl.html',
'apache' => 'http://www.opensource.org/licenses/apache2.0.php'
);
if (isset($licensemap[strtolower($this->_packagefile->getLicense())])) {
$arr['license'] = array(
'attribs' => array('uri' =>
$licensemap[strtolower($this->_packagefile->getLicense())]),
'_content' => $this->_packagefile->getLicense()
);
} else {
// don't use bogus uri
$arr['license'] = $this->_packagefile->getLicense();
}
$arr['notes'] = $this->_packagefile->getNotes();
$temp = array();
$arr['contents'] = $this->_convertFilelist2_0($temp);
$this->_convertDependencies2_0($arr);
$release = ($this->_packagefile->getConfigureOptions() || $this->_isExtension) ?
'extsrcrelease' : 'phprelease';
if ($release == 'extsrcrelease') {
$arr['channel'] = 'pecl.php.net';
$arr['providesextension'] = $arr['name']; // assumption
}
$arr[$release] = array();
if ($this->_packagefile->getConfigureOptions()) {
$arr[$release]['configureoption'] = $this->_packagefile->getConfigureOptions();
foreach ($arr[$release]['configureoption'] as $i => $opt) {
$arr[$release]['configureoption'][$i] = array('attribs' => $opt);
}
if (count($arr[$release]['configureoption']) == 1) {
$arr[$release]['configureoption'] = $arr[$release]['configureoption'][0];
}
}
$this->_convertRelease2_0($arr[$release], $temp);
if ($release == 'extsrcrelease' && count($arr[$release]) > 1) {
// multiple extsrcrelease tags added in PEAR 1.4.1
$arr['dependencies']['required']['pearinstaller']['min'] = '1.4.1';
}
if ($cl = $this->_packagefile->getChangelog()) {
foreach ($cl as $release) {
$rel = array();
$rel['version'] =
array(
'release' => $release['version'],
'api' => $release['version'],
);
if (!isset($release['release_state'])) {
$release['release_state'] = 'stable';
}
$rel['stability'] =
array(
'release' => $release['release_state'],
'api' => $release['release_state'],
);
if (isset($release['release_date'])) {
$rel['date'] = $release['release_date'];
} else {
$rel['date'] = date('Y-m-d');
}
if (isset($release['release_license'])) {
if (isset($licensemap[strtolower($release['release_license'])])) {
$uri = $licensemap[strtolower($release['release_license'])];
} else {
$uri = 'http://www.example.com';
}
$rel['license'] = array(
'attribs' => array('uri' => $uri),
'_content' => $release['release_license']
);
} else {
$rel['license'] = $arr['license'];
}
if (!isset($release['release_notes'])) {
$release['release_notes'] = 'no release notes';
}
$rel['notes'] = $release['release_notes'];
$arr['changelog']['release'][] = $rel;
}
}
$ret = new $class;
$ret->setConfig($this->_packagefile->_config);
if (isset($this->_packagefile->_logger) && is_object($this->_packagefile->_logger)) {
$ret->setLogger($this->_packagefile->_logger);
}
$ret->fromArray($arr);
return $ret;
}
 
/**
* @param array
* @param bool
* @access private
*/
function _convertDependencies2_0(&$release, $internal = false)
{
$peardep = array('pearinstaller' =>
array('min' => '1.4.0b1')); // this is a lot safer
$required = $optional = array();
$release['dependencies'] = array();
if ($this->_packagefile->hasDeps()) {
foreach ($this->_packagefile->getDeps() as $dep) {
if (!isset($dep['optional']) || $dep['optional'] == 'no') {
$required[] = $dep;
} else {
$optional[] = $dep;
}
}
foreach (array('required', 'optional') as $arr) {
$deps = array();
foreach ($$arr as $dep) {
// organize deps by dependency type and name
if (!isset($deps[$dep['type']])) {
$deps[$dep['type']] = array();
}
if (isset($dep['name'])) {
$deps[$dep['type']][$dep['name']][] = $dep;
} else {
$deps[$dep['type']][] = $dep;
}
}
do {
if (isset($deps['php'])) {
$php = array();
if (count($deps['php']) > 1) {
$php = $this->_processPhpDeps($deps['php']);
} else {
if (!isset($deps['php'][0])) {
list($key, $blah) = each ($deps['php']); // stupid buggy versions
$deps['php'] = array($blah[0]);
}
$php = $this->_processDep($deps['php'][0]);
if (!$php) {
break; // poor mans throw
}
}
$release['dependencies'][$arr]['php'] = $php;
}
} while (false);
do {
if (isset($deps['pkg'])) {
$pkg = array();
$pkg = $this->_processMultipleDepsName($deps['pkg']);
if (!$pkg) {
break; // poor mans throw
}
$release['dependencies'][$arr]['package'] = $pkg;
}
} while (false);
do {
if (isset($deps['ext'])) {
$pkg = array();
$pkg = $this->_processMultipleDepsName($deps['ext']);
$release['dependencies'][$arr]['extension'] = $pkg;
}
} while (false);
// skip sapi - it's not supported so nobody will have used it
// skip os - it's not supported in 1.0
}
}
if (isset($release['dependencies']['required'])) {
$release['dependencies']['required'] =
array_merge($peardep, $release['dependencies']['required']);
} else {
$release['dependencies']['required'] = $peardep;
}
if (!isset($release['dependencies']['required']['php'])) {
$release['dependencies']['required']['php'] =
array('min' => '4.0.0');
}
$order = array();
$bewm = $release['dependencies']['required'];
$order['php'] = $bewm['php'];
$order['pearinstaller'] = $bewm['pearinstaller'];
isset($bewm['package']) ? $order['package'] = $bewm['package'] :0;
isset($bewm['extension']) ? $order['extension'] = $bewm['extension'] :0;
$release['dependencies']['required'] = $order;
}
 
/**
* @param array
* @access private
*/
function _convertFilelist2_0(&$package)
{
$ret = array('dir' =>
array(
'attribs' => array('name' => '/'),
'file' => array()
)
);
$package['platform'] =
$package['install-as'] = array();
$this->_isExtension = false;
foreach ($this->_packagefile->getFilelist() as $name => $file) {
$file['name'] = $name;
if (isset($file['role']) && $file['role'] == 'src') {
$this->_isExtension = true;
}
if (isset($file['replacements'])) {
$repl = $file['replacements'];
unset($file['replacements']);
} else {
unset($repl);
}
if (isset($file['install-as'])) {
$package['install-as'][$name] = $file['install-as'];
unset($file['install-as']);
}
if (isset($file['platform'])) {
$package['platform'][$name] = $file['platform'];
unset($file['platform']);
}
$file = array('attribs' => $file);
if (isset($repl)) {
foreach ($repl as $replace ) {
$file['tasks:replace'][] = array('attribs' => $replace);
}
if (count($repl) == 1) {
$file['tasks:replace'] = $file['tasks:replace'][0];
}
}
$ret['dir']['file'][] = $file;
}
return $ret;
}
 
/**
* Post-process special files with install-as/platform attributes and
* make the release tag.
*
* This complex method follows this work-flow to create the release tags:
*
* <pre>
* - if any install-as/platform exist, create a generic release and fill it with
* o <install as=..> tags for <file name=... install-as=...>
* o <install as=..> tags for <file name=... platform=!... install-as=..>
* o <ignore> tags for <file name=... platform=...>
* o <ignore> tags for <file name=... platform=... install-as=..>
* - create a release for each platform encountered and fill with
* o <install as..> tags for <file name=... install-as=...>
* o <install as..> tags for <file name=... platform=this platform install-as=..>
* o <install as..> tags for <file name=... platform=!other platform install-as=..>
* o <ignore> tags for <file name=... platform=!this platform>
* o <ignore> tags for <file name=... platform=other platform>
* o <ignore> tags for <file name=... platform=other platform install-as=..>
* o <ignore> tags for <file name=... platform=!this platform install-as=..>
* </pre>
*
* It does this by accessing the $package parameter, which contains an array with
* indices:
*
* - platform: mapping of file => OS the file should be installed on
* - install-as: mapping of file => installed name
* - osmap: mapping of OS => list of files that should be installed
* on that OS
* - notosmap: mapping of OS => list of files that should not be
* installed on that OS
*
* @param array
* @param array
* @access private
*/
function _convertRelease2_0(&$release, $package)
{
//- if any install-as/platform exist, create a generic release and fill it with
if (count($package['platform']) || count($package['install-as'])) {
$generic = array();
$genericIgnore = array();
foreach ($package['install-as'] as $file => $as) {
//o <install as=..> tags for <file name=... install-as=...>
if (!isset($package['platform'][$file])) {
$generic[] = $file;
continue;
}
//o <install as=..> tags for <file name=... platform=!... install-as=..>
if (isset($package['platform'][$file]) &&
$package['platform'][$file]{0} == '!') {
$generic[] = $file;
continue;
}
//o <ignore> tags for <file name=... platform=... install-as=..>
if (isset($package['platform'][$file]) &&
$package['platform'][$file]{0} != '!') {
$genericIgnore[] = $file;
continue;
}
}
foreach ($package['platform'] as $file => $platform) {
if (isset($package['install-as'][$file])) {
continue;
}
if ($platform{0} != '!') {
//o <ignore> tags for <file name=... platform=...>
$genericIgnore[] = $file;
}
}
if (count($package['platform'])) {
$oses = $notplatform = $platform = array();
foreach ($package['platform'] as $file => $os) {
// get a list of oses
if ($os{0} == '!') {
if (isset($oses[substr($os, 1)])) {
continue;
}
$oses[substr($os, 1)] = count($oses);
} else {
if (isset($oses[$os])) {
continue;
}
$oses[$os] = count($oses);
}
}
//- create a release for each platform encountered and fill with
foreach ($oses as $os => $releaseNum) {
$release[$releaseNum]['installconditions']['os']['name'] = $os;
$release[$releaseNum]['filelist'] = array('install' => array(),
'ignore' => array());
foreach ($package['install-as'] as $file => $as) {
//o <install as=..> tags for <file name=... install-as=...>
if (!isset($package['platform'][$file])) {
$release[$releaseNum]['filelist']['install'][] =
array(
'attribs' => array(
'name' => $file,
'as' => $as,
),
);
continue;
}
//o <install as..> tags for
// <file name=... platform=this platform install-as=..>
if (isset($package['platform'][$file]) &&
$package['platform'][$file] == $os) {
$release[$releaseNum]['filelist']['install'][] =
array(
'attribs' => array(
'name' => $file,
'as' => $as,
),
);
continue;
}
//o <install as..> tags for
// <file name=... platform=!other platform install-as=..>
if (isset($package['platform'][$file]) &&
$package['platform'][$file] != "!$os" &&
$package['platform'][$file]{0} == '!') {
$release[$releaseNum]['filelist']['install'][] =
array(
'attribs' => array(
'name' => $file,
'as' => $as,
),
);
continue;
}
//o <ignore> tags for
// <file name=... platform=!this platform install-as=..>
if (isset($package['platform'][$file]) &&
$package['platform'][$file] == "!$os") {
$release[$releaseNum]['filelist']['ignore'][] =
array(
'attribs' => array(
'name' => $file,
),
);
continue;
}
//o <ignore> tags for
// <file name=... platform=other platform install-as=..>
if (isset($package['platform'][$file]) &&
$package['platform'][$file]{0} != '!' &&
$package['platform'][$file] != $os) {
$release[$releaseNum]['filelist']['ignore'][] =
array(
'attribs' => array(
'name' => $file,
),
);
continue;
}
}
foreach ($package['platform'] as $file => $platform) {
if (isset($package['install-as'][$file])) {
continue;
}
//o <ignore> tags for <file name=... platform=!this platform>
if ($platform == "!$os") {
$release[$releaseNum]['filelist']['ignore'][] =
array(
'attribs' => array(
'name' => $file,
),
);
continue;
}
//o <ignore> tags for <file name=... platform=other platform>
if ($platform{0} != '!' && $platform != $os) {
$release[$releaseNum]['filelist']['ignore'][] =
array(
'attribs' => array(
'name' => $file,
),
);
}
}
if (!count($release[$releaseNum]['filelist']['install'])) {
unset($release[$releaseNum]['filelist']['install']);
}
if (!count($release[$releaseNum]['filelist']['ignore'])) {
unset($release[$releaseNum]['filelist']['ignore']);
}
}
if (count($generic) || count($genericIgnore)) {
$release[count($oses)] = array();
if (count($generic)) {
foreach ($generic as $file) {
if (isset($package['install-as'][$file])) {
$installas = $package['install-as'][$file];
} else {
$installas = $file;
}
$release[count($oses)]['filelist']['install'][] =
array(
'attribs' => array(
'name' => $file,
'as' => $installas,
)
);
}
}
if (count($genericIgnore)) {
foreach ($genericIgnore as $file) {
$release[count($oses)]['filelist']['ignore'][] =
array(
'attribs' => array(
'name' => $file,
)
);
}
}
}
// cleanup
foreach ($release as $i => $rel) {
if (isset($rel['filelist']['install']) &&
count($rel['filelist']['install']) == 1) {
$release[$i]['filelist']['install'] =
$release[$i]['filelist']['install'][0];
}
if (isset($rel['filelist']['ignore']) &&
count($rel['filelist']['ignore']) == 1) {
$release[$i]['filelist']['ignore'] =
$release[$i]['filelist']['ignore'][0];
}
}
if (count($release) == 1) {
$release = $release[0];
}
} else {
// no platform atts, but some install-as atts
foreach ($package['install-as'] as $file => $value) {
$release['filelist']['install'][] =
array(
'attribs' => array(
'name' => $file,
'as' => $value
)
);
}
if (count($release['filelist']['install']) == 1) {
$release['filelist']['install'] = $release['filelist']['install'][0];
}
}
}
}
 
/**
* @param array
* @return array
* @access private
*/
function _processDep($dep)
{
if ($dep['type'] == 'php') {
if ($dep['rel'] == 'has') {
// come on - everyone has php!
return false;
}
}
$php = array();
if ($dep['type'] != 'php') {
$php['name'] = $dep['name'];
if ($dep['type'] == 'pkg') {
$php['channel'] = 'pear.php.net';
}
}
switch ($dep['rel']) {
case 'gt' :
$php['min'] = $dep['version'];
$php['exclude'] = $dep['version'];
break;
case 'ge' :
if (!isset($dep['version'])) {
if ($dep['type'] == 'php') {
if (isset($dep['name'])) {
$dep['version'] = $dep['name'];
}
}
}
$php['min'] = $dep['version'];
break;
case 'lt' :
$php['max'] = $dep['version'];
$php['exclude'] = $dep['version'];
break;
case 'le' :
$php['max'] = $dep['version'];
break;
case 'eq' :
$php['min'] = $dep['version'];
$php['max'] = $dep['version'];
break;
case 'ne' :
$php['exclude'] = $dep['version'];
break;
case 'not' :
$php['conflicts'] = 'yes';
break;
}
return $php;
}
 
/**
* @param array
* @return array
*/
function _processPhpDeps($deps)
{
$test = array();
foreach ($deps as $dep) {
$test[] = $this->_processDep($dep);
}
$min = array();
$max = array();
foreach ($test as $dep) {
if (!$dep) {
continue;
}
if (isset($dep['min'])) {
$min[$dep['min']] = count($min);
}
if (isset($dep['max'])) {
$max[$dep['max']] = count($max);
}
}
if (count($min) > 0) {
uksort($min, 'version_compare');
}
if (count($max) > 0) {
uksort($max, 'version_compare');
}
if (count($min)) {
// get the highest minimum
$min = array_pop($a = array_flip($min));
} else {
$min = false;
}
if (count($max)) {
// get the lowest maximum
$max = array_shift($a = array_flip($max));
} else {
$max = false;
}
if ($min) {
$php['min'] = $min;
}
if ($max) {
$php['max'] = $max;
}
$exclude = array();
foreach ($test as $dep) {
if (!isset($dep['exclude'])) {
continue;
}
$exclude[] = $dep['exclude'];
}
if (count($exclude)) {
$php['exclude'] = $exclude;
}
return $php;
}
 
/**
* process multiple dependencies that have a name, like package deps
* @param array
* @return array
* @access private
*/
function _processMultipleDepsName($deps)
{
$tests = array();
foreach ($deps as $name => $dep) {
foreach ($dep as $d) {
$tests[$name][] = $this->_processDep($d);
}
}
foreach ($tests as $name => $test) {
$php = array();
$min = array();
$max = array();
$php['name'] = $name;
foreach ($test as $dep) {
if (!$dep) {
continue;
}
if (isset($dep['channel'])) {
$php['channel'] = 'pear.php.net';
}
if (isset($dep['conflicts']) && $dep['conflicts'] == 'yes') {
$php['conflicts'] = 'yes';
}
if (isset($dep['min'])) {
$min[$dep['min']] = count($min);
}
if (isset($dep['max'])) {
$max[$dep['max']] = count($max);
}
}
if (count($min) > 0) {
uksort($min, 'version_compare');
}
if (count($max) > 0) {
uksort($max, 'version_compare');
}
if (count($min)) {
// get the highest minimum
$min = array_pop($a = array_flip($min));
} else {
$min = false;
}
if (count($max)) {
// get the lowest maximum
$max = array_shift($a = array_flip($max));
} else {
$max = false;
}
if ($min) {
$php['min'] = $min;
}
if ($max) {
$php['max'] = $max;
}
$exclude = array();
foreach ($test as $dep) {
if (!isset($dep['exclude'])) {
continue;
}
$exclude[] = $dep['exclude'];
}
if (count($exclude)) {
$php['exclude'] = $exclude;
}
$ret[] = $php;
}
return $ret;
}
}
?>
/trunk/bibliotheque/pear/PEAR/PackageFile/Generator/v2.php
New file
0,0 → 1,1527
<?php
/**
* package.xml generation class, package.xml version 2.0
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @author Stephan Schmidt (original XML_Serializer code)
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: v2.php,v 1.35 2006/03/25 21:09:08 cellog Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* file/dir manipulation routines
*/
require_once 'System.php';
/**
* This class converts a PEAR_PackageFile_v2 object into any output format.
*
* Supported output formats include array, XML string (using S. Schmidt's
* XML_Serializer, slightly customized)
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @author Stephan Schmidt (original XML_Serializer code)
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.5.1
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_PackageFile_Generator_v2
{
/**
* default options for the serialization
* @access private
* @var array $_defaultOptions
*/
var $_defaultOptions = array(
'indent' => ' ', // string used for indentation
'linebreak' => "\n", // string used for newlines
'typeHints' => false, // automatically add type hin attributes
'addDecl' => true, // add an XML declaration
'defaultTagName' => 'XML_Serializer_Tag', // tag used for indexed arrays or invalid names
'classAsTagName' => false, // use classname for objects in indexed arrays
'keyAttribute' => '_originalKey', // attribute where original key is stored
'typeAttribute' => '_type', // attribute for type (only if typeHints => true)
'classAttribute' => '_class', // attribute for class of objects (only if typeHints => true)
'scalarAsAttributes' => false, // scalar values (strings, ints,..) will be serialized as attribute
'prependAttributes' => '', // prepend string for attributes
'indentAttributes' => false, // indent the attributes, if set to '_auto', it will indent attributes so they all start at the same column
'mode' => 'simplexml', // use 'simplexml' to use parent name as tagname if transforming an indexed array
'addDoctype' => false, // add a doctype declaration
'doctype' => null, // supply a string or an array with id and uri ({@see PEAR_PackageFile_Generator_v2_PEAR_PackageFile_Generator_v2_XML_Util::getDoctypeDeclaration()}
'rootName' => 'package', // name of the root tag
'rootAttributes' => array(
'version' => '2.0',
'xmlns' => 'http://pear.php.net/dtd/package-2.0',
'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
http://pear.php.net/dtd/tasks-1.0.xsd
http://pear.php.net/dtd/package-2.0
http://pear.php.net/dtd/package-2.0.xsd',
), // attributes of the root tag
'attributesArray' => 'attribs', // all values in this key will be treated as attributes
'contentName' => '_content', // this value will be used directly as content, instead of creating a new tag, may only be used in conjuction with attributesArray
'beautifyFilelist' => false,
'encoding' => 'UTF-8',
);
 
/**
* options for the serialization
* @access private
* @var array $options
*/
var $options = array();
 
/**
* current tag depth
* @var integer $_tagDepth
*/
var $_tagDepth = 0;
 
/**
* serilialized representation of the data
* @var string $_serializedData
*/
var $_serializedData = null;
/**
* @var PEAR_PackageFile_v2
*/
var $_packagefile;
/**
* @param PEAR_PackageFile_v2
*/
function PEAR_PackageFile_Generator_v2(&$packagefile)
{
$this->_packagefile = &$packagefile;
}
 
/**
* @return string
*/
function getPackagerVersion()
{
return '1.5.1';
}
 
/**
* @param PEAR_Packager
* @param bool generate a .tgz or a .tar
* @param string|null temporary directory to package in
*/
function toTgz(&$packager, $compress = true, $where = null)
{
$a = null;
return $this->toTgz2($packager, $a, $compress, $where);
}
 
/**
* Package up both a package.xml and package2.xml for the same release
* @param PEAR_Packager
* @param PEAR_PackageFile_v1
* @param bool generate a .tgz or a .tar
* @param string|null temporary directory to package in
*/
function toTgz2(&$packager, &$pf1, $compress = true, $where = null)
{
require_once 'Archive/Tar.php';
if (!$this->_packagefile->isEquivalent($pf1)) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' .
basename($pf1->getPackageFile()) .
'" is not equivalent to "' . basename($this->_packagefile->getPackageFile())
. '"');
}
if ($where === null) {
if (!($where = System::mktemp(array('-d')))) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: mktemp failed');
}
} elseif (!@System::mkDir(array('-p', $where))) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' . $where . '" could' .
' not be created');
}
if (file_exists($where . DIRECTORY_SEPARATOR . 'package.xml') &&
!is_file($where . DIRECTORY_SEPARATOR . 'package.xml')) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: unable to save package.xml as' .
' "' . $where . DIRECTORY_SEPARATOR . 'package.xml"');
}
if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: invalid package.xml');
}
$ext = $compress ? '.tgz' : '.tar';
$pkgver = $this->_packagefile->getPackage() . '-' . $this->_packagefile->getVersion();
$dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext;
if (file_exists(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext) &&
!is_file(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext)) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: cannot create tgz file "' .
getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext . '"');
}
if ($pkgfile = $this->_packagefile->getPackageFile()) {
$pkgdir = dirname(realpath($pkgfile));
$pkgfile = basename($pkgfile);
} else {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: package file object must ' .
'be created from a real file');
}
// {{{ Create the package file list
$filelist = array();
$i = 0;
$this->_packagefile->flattenFilelist();
$contents = $this->_packagefile->getContents();
if (isset($contents['bundledpackage'])) { // bundles of packages
$contents = $contents['bundledpackage'];
if (!isset($contents[0])) {
$contents = array($contents);
}
$packageDir = $where;
foreach ($contents as $i => $package) {
$fname = $package;
$file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
if (!file_exists($file)) {
return $packager->raiseError("File does not exist: $fname");
}
$tfile = $packageDir . DIRECTORY_SEPARATOR . $fname;
System::mkdir(array('-p', dirname($tfile)));
copy($file, $tfile);
$filelist[$i++] = $tfile;
$packager->log(2, "Adding package $fname");
}
} else { // normal packages
$contents = $contents['dir']['file'];
if (!isset($contents[0])) {
$contents = array($contents);
}
$packageDir = $where;
foreach ($contents as $i => $file) {
$fname = $file['attribs']['name'];
$atts = $file['attribs'];
$orig = $file;
$file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
if (!file_exists($file)) {
return $packager->raiseError("File does not exist: $fname");
} else {
$tfile = $packageDir . DIRECTORY_SEPARATOR . $fname;
unset($orig['attribs']);
if (count($orig)) { // file with tasks
// run any package-time tasks
$contents = file_get_contents($file);
foreach ($orig as $tag => $raw) {
$tag = str_replace($this->_packagefile->getTasksNs() . ':', '', $tag);
$task = "PEAR_Task_$tag";
$task = &new $task($this->_packagefile->_config,
$this->_packagefile->_logger,
PEAR_TASK_PACKAGE);
$task->init($raw, $atts, null);
$res = $task->startSession($this->_packagefile, $contents, $tfile);
if (!$res) {
continue; // skip this task
}
if (PEAR::isError($res)) {
return $res;
}
$contents = $res; // save changes
System::mkdir(array('-p', dirname($tfile)));
$wp = fopen($tfile, "wb");
fwrite($wp, $contents);
fclose($wp);
}
}
if (!file_exists($tfile)) {
System::mkdir(array('-p', dirname($tfile)));
copy($file, $tfile);
}
$filelist[$i++] = $tfile;
$this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($tfile), $i - 1);
$packager->log(2, "Adding file $fname");
}
}
}
// }}}
if ($pf1 !== null) {
$name = 'package2.xml';
} else {
$name = 'package.xml';
}
$packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, $name);
if ($packagexml) {
$tar =& new Archive_Tar($dest_package, $compress);
$tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors
// ----- Creates with the package.xml file
$ok = $tar->createModify(array($packagexml), '', $where);
if (PEAR::isError($ok)) {
return $packager->raiseError($ok);
} elseif (!$ok) {
return $packager->raiseError('PEAR_Packagefile_v2::toTgz(): adding ' . $name .
' failed');
}
// ----- Add the content of the package
if (!$tar->addModify($filelist, $pkgver, $where)) {
return $packager->raiseError(
'PEAR_Packagefile_v2::toTgz(): tarball creation failed');
}
// add the package.xml version 1.0
if ($pf1 !== null) {
$pfgen = &$pf1->getDefaultGenerator();
$packagexml1 = $pfgen->toPackageFile($where, PEAR_VALIDATE_PACKAGING,
'package.xml', true);
if (!$tar->addModify(array($packagexml1), '', $where)) {
return $packager->raiseError(
'PEAR_Packagefile_v2::toTgz(): adding package.xml failed');
}
}
return $dest_package;
}
}
 
function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml')
{
if (!$this->_packagefile->validate($state)) {
return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: invalid package.xml',
null, null, null, $this->_packagefile->getValidationWarnings());
}
if ($where === null) {
if (!($where = System::mktemp(array('-d')))) {
return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: mktemp failed');
}
} elseif (!@System::mkDir(array('-p', $where))) {
return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: "' . $where . '" could' .
' not be created');
}
$newpkgfile = $where . DIRECTORY_SEPARATOR . $name;
$np = @fopen($newpkgfile, 'wb');
if (!$np) {
return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: unable to save ' .
"$name as $newpkgfile");
}
fwrite($np, $this->toXml($state));
fclose($np);
return $newpkgfile;
}
 
function &toV2()
{
return $this->_packagefile;
}
 
/**
* Return an XML document based on the package info (as returned
* by the PEAR_Common::infoFrom* methods).
*
* @return string XML data
*/
function toXml($state = PEAR_VALIDATE_NORMAL, $options = array())
{
$this->_packagefile->setDate(date('Y-m-d'));
$this->_packagefile->setTime(date('H:i:s'));
if (!$this->_packagefile->validate($state)) {
return false;
}
if (is_array($options)) {
$this->options = array_merge($this->_defaultOptions, $options);
} else {
$this->options = $this->_defaultOptions;
}
$arr = $this->_packagefile->getArray();
if (isset($arr['filelist'])) {
unset($arr['filelist']);
}
if (isset($arr['_lastversion'])) {
unset($arr['_lastversion']);
}
if ($state ^ PEAR_VALIDATE_PACKAGING && !isset($arr['bundle'])) {
$use = $this->_recursiveXmlFilelist($arr['contents']['dir']['file']);
unset($arr['contents']['dir']['file']);
if (isset($use['dir'])) {
$arr['contents']['dir']['dir'] = $use['dir'];
}
if (isset($use['file'])) {
$arr['contents']['dir']['file'] = $use['file'];
}
$this->options['beautifyFilelist'] = true;
}
$arr['attribs']['packagerversion'] = '1.5.1';
if ($this->serialize($arr, $options)) {
return $this->_serializedData . "\n";
}
return false;
}
 
 
function _recursiveXmlFilelist($list)
{
$dirs = array();
if (isset($list['attribs'])) {
$file = $list['attribs']['name'];
unset($list['attribs']['name']);
$attributes = $list['attribs'];
$this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes);
} else {
foreach ($list as $a) {
$file = $a['attribs']['name'];
$attributes = $a['attribs'];
unset($a['attribs']);
$this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes, $a);
}
}
$this->_formatDir($dirs);
$this->_deFormat($dirs);
return $dirs;
}
 
function _addDir(&$dirs, $dir, $file = null, $attributes = null, $tasks = null)
{
if (!$tasks) {
$tasks = array();
}
if ($dir == array() || $dir == array('.')) {
$dirs['file'][basename($file)] = $tasks;
$attributes['name'] = basename($file);
$dirs['file'][basename($file)]['attribs'] = $attributes;
return;
}
$curdir = array_shift($dir);
if (!isset($dirs['dir'][$curdir])) {
$dirs['dir'][$curdir] = array();
}
$this->_addDir($dirs['dir'][$curdir], $dir, $file, $attributes, $tasks);
}
 
function _formatDir(&$dirs)
{
if (!count($dirs)) {
return array();
}
$newdirs = array();
if (isset($dirs['dir'])) {
$newdirs['dir'] = $dirs['dir'];
}
if (isset($dirs['file'])) {
$newdirs['file'] = $dirs['file'];
}
$dirs = $newdirs;
if (isset($dirs['dir'])) {
uksort($dirs['dir'], 'strnatcasecmp');
foreach ($dirs['dir'] as $dir => $contents) {
$this->_formatDir($dirs['dir'][$dir]);
}
}
if (isset($dirs['file'])) {
uksort($dirs['file'], 'strnatcasecmp');
};
}
 
function _deFormat(&$dirs)
{
if (!count($dirs)) {
return array();
}
$newdirs = array();
if (isset($dirs['dir'])) {
foreach ($dirs['dir'] as $dir => $contents) {
$newdir = array();
$newdir['attribs']['name'] = $dir;
$this->_deFormat($contents);
foreach ($contents as $tag => $val) {
$newdir[$tag] = $val;
}
$newdirs['dir'][] = $newdir;
}
if (count($newdirs['dir']) == 1) {
$newdirs['dir'] = $newdirs['dir'][0];
}
}
if (isset($dirs['file'])) {
foreach ($dirs['file'] as $name => $file) {
$newdirs['file'][] = $file;
}
if (count($newdirs['file']) == 1) {
$newdirs['file'] = $newdirs['file'][0];
}
}
$dirs = $newdirs;
}
 
/**
* reset all options to default options
*
* @access public
* @see setOption(), XML_Unserializer()
*/
function resetOptions()
{
$this->options = $this->_defaultOptions;
}
 
/**
* set an option
*
* You can use this method if you do not want to set all options in the constructor
*
* @access public
* @see resetOption(), XML_Serializer()
*/
function setOption($name, $value)
{
$this->options[$name] = $value;
}
/**
* sets several options at once
*
* You can use this method if you do not want to set all options in the constructor
*
* @access public
* @see resetOption(), XML_Unserializer(), setOption()
*/
function setOptions($options)
{
$this->options = array_merge($this->options, $options);
}
 
/**
* serialize data
*
* @access public
* @param mixed $data data to serialize
* @return boolean true on success, pear error on failure
*/
function serialize($data, $options = null)
{
// if options have been specified, use them instead
// of the previously defined ones
if (is_array($options)) {
$optionsBak = $this->options;
if (isset($options['overrideOptions']) && $options['overrideOptions'] == true) {
$this->options = array_merge($this->_defaultOptions, $options);
} else {
$this->options = array_merge($this->options, $options);
}
}
else {
$optionsBak = null;
}
// start depth is zero
$this->_tagDepth = 0;
 
$this->_serializedData = '';
// serialize an array
if (is_array($data)) {
if (isset($this->options['rootName'])) {
$tagName = $this->options['rootName'];
} else {
$tagName = 'array';
}
 
$this->_serializedData .= $this->_serializeArray($data, $tagName, $this->options['rootAttributes']);
}
// add doctype declaration
if ($this->options['addDoctype'] === true) {
$this->_serializedData = PEAR_PackageFile_Generator_v2_XML_Util::getDoctypeDeclaration($tagName, $this->options['doctype'])
. $this->options['linebreak']
. $this->_serializedData;
}
 
// build xml declaration
if ($this->options['addDecl']) {
$atts = array();
if (isset($this->options['encoding']) ) {
$encoding = $this->options['encoding'];
} else {
$encoding = null;
}
$this->_serializedData = PEAR_PackageFile_Generator_v2_XML_Util::getXMLDeclaration('1.0', $encoding)
. $this->options['linebreak']
. $this->_serializedData;
}
if ($optionsBak !== null) {
$this->options = $optionsBak;
}
return true;
}
 
/**
* get the result of the serialization
*
* @access public
* @return string serialized XML
*/
function getSerializedData()
{
if ($this->_serializedData == null ) {
return $this->raiseError('No serialized data available. Use XML_Serializer::serialize() first.', XML_SERIALIZER_ERROR_NO_SERIALIZATION);
}
return $this->_serializedData;
}
/**
* serialize any value
*
* This method checks for the type of the value and calls the appropriate method
*
* @access private
* @param mixed $value
* @param string $tagName
* @param array $attributes
* @return string
*/
function _serializeValue($value, $tagName = null, $attributes = array())
{
if (is_array($value)) {
$xml = $this->_serializeArray($value, $tagName, $attributes);
} elseif (is_object($value)) {
$xml = $this->_serializeObject($value, $tagName);
} else {
$tag = array(
'qname' => $tagName,
'attributes' => $attributes,
'content' => $value
);
$xml = $this->_createXMLTag($tag);
}
return $xml;
}
/**
* serialize an array
*
* @access private
* @param array $array array to serialize
* @param string $tagName name of the root tag
* @param array $attributes attributes for the root tag
* @return string $string serialized data
* @uses PEAR_PackageFile_Generator_v2_XML_Util::isValidName() to check, whether key has to be substituted
*/
function _serializeArray(&$array, $tagName = null, $attributes = array())
{
$_content = null;
/**
* check for special attributes
*/
if ($this->options['attributesArray'] !== null) {
if (isset($array[$this->options['attributesArray']])) {
$attributes = $array[$this->options['attributesArray']];
unset($array[$this->options['attributesArray']]);
}
/**
* check for special content
*/
if ($this->options['contentName'] !== null) {
if (isset($array[$this->options['contentName']])) {
$_content = $array[$this->options['contentName']];
unset($array[$this->options['contentName']]);
}
}
}
 
/*
* if mode is set to simpleXML, check whether
* the array is associative or indexed
*/
if (is_array($array) && $this->options['mode'] == 'simplexml') {
$indexed = true;
if (!count($array)) {
$indexed = false;
}
foreach ($array as $key => $val) {
if (!is_int($key)) {
$indexed = false;
break;
}
}
 
if ($indexed && $this->options['mode'] == 'simplexml') {
$string = '';
foreach ($array as $key => $val) {
if ($this->options['beautifyFilelist'] && $tagName == 'dir') {
if (!isset($this->_curdir)) {
$this->_curdir = '';
}
$savedir = $this->_curdir;
if (isset($val['attribs'])) {
if ($val['attribs']['name'] == '/') {
$this->_curdir = '/';
} else {
if ($this->_curdir == '/') {
$this->_curdir = '';
}
$this->_curdir .= '/' . $val['attribs']['name'];
}
}
}
$string .= $this->_serializeValue( $val, $tagName, $attributes);
if ($this->options['beautifyFilelist'] && $tagName == 'dir') {
$string .= ' <!-- ' . $this->_curdir . ' -->';
if (empty($savedir)) {
unset($this->_curdir);
} else {
$this->_curdir = $savedir;
}
}
$string .= $this->options['linebreak'];
// do indentation
if ($this->options['indent']!==null && $this->_tagDepth>0) {
$string .= str_repeat($this->options['indent'], $this->_tagDepth);
}
}
return rtrim($string);
}
}
if ($this->options['scalarAsAttributes'] === true) {
foreach ($array as $key => $value) {
if (is_scalar($value) && (PEAR_PackageFile_Generator_v2_XML_Util::isValidName($key) === true)) {
unset($array[$key]);
$attributes[$this->options['prependAttributes'].$key] = $value;
}
}
}
 
// check for empty array => create empty tag
if (empty($array)) {
$tag = array(
'qname' => $tagName,
'content' => $_content,
'attributes' => $attributes
);
 
} else {
$this->_tagDepth++;
$tmp = $this->options['linebreak'];
foreach ($array as $key => $value) {
// do indentation
if ($this->options['indent']!==null && $this->_tagDepth>0) {
$tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
}
// copy key
$origKey = $key;
// key cannot be used as tagname => use default tag
$valid = PEAR_PackageFile_Generator_v2_XML_Util::isValidName($key);
if (PEAR::isError($valid)) {
if ($this->options['classAsTagName'] && is_object($value)) {
$key = get_class($value);
} else {
$key = $this->options['defaultTagName'];
}
}
$atts = array();
if ($this->options['typeHints'] === true) {
$atts[$this->options['typeAttribute']] = gettype($value);
if ($key !== $origKey) {
$atts[$this->options['keyAttribute']] = (string)$origKey;
}
}
if ($this->options['beautifyFilelist'] && $key == 'dir') {
if (!isset($this->_curdir)) {
$this->_curdir = '';
}
$savedir = $this->_curdir;
if (isset($value['attribs'])) {
if ($value['attribs']['name'] == '/') {
$this->_curdir = '/';
} else {
$this->_curdir .= '/' . $value['attribs']['name'];
}
}
}
 
if (is_string($value) && $value && ($value{strlen($value) - 1} == "\n")) {
$value .= str_repeat($this->options['indent'], $this->_tagDepth);
}
$tmp .= $this->_createXMLTag(array(
'qname' => $key,
'attributes' => $atts,
'content' => $value )
);
if ($this->options['beautifyFilelist'] && $key == 'dir') {
if (isset($value['attribs'])) {
$tmp .= ' <!-- ' . $this->_curdir . ' -->';
if (empty($savedir)) {
unset($this->_curdir);
} else {
$this->_curdir = $savedir;
}
}
}
$tmp .= $this->options['linebreak'];
}
$this->_tagDepth--;
if ($this->options['indent']!==null && $this->_tagDepth>0) {
$tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
}
if (trim($tmp) === '') {
$tmp = null;
}
$tag = array(
'qname' => $tagName,
'content' => $tmp,
'attributes' => $attributes
);
}
if ($this->options['typeHints'] === true) {
if (!isset($tag['attributes'][$this->options['typeAttribute']])) {
$tag['attributes'][$this->options['typeAttribute']] = 'array';
}
}
 
$string = $this->_createXMLTag($tag, false);
return $string;
}
/**
* create a tag from an array
* this method awaits an array in the following format
* array(
* 'qname' => $tagName,
* 'attributes' => array(),
* 'content' => $content, // optional
* 'namespace' => $namespace // optional
* 'namespaceUri' => $namespaceUri // optional
* )
*
* @access private
* @param array $tag tag definition
* @param boolean $replaceEntities whether to replace XML entities in content or not
* @return string $string XML tag
*/
function _createXMLTag( $tag, $replaceEntities = true )
{
if ($this->options['indentAttributes'] !== false) {
$multiline = true;
$indent = str_repeat($this->options['indent'], $this->_tagDepth);
 
if ($this->options['indentAttributes'] == '_auto') {
$indent .= str_repeat(' ', (strlen($tag['qname'])+2));
 
} else {
$indent .= $this->options['indentAttributes'];
}
} else {
$multiline = false;
$indent = false;
}
if (is_array($tag['content'])) {
if (empty($tag['content'])) {
$tag['content'] = '';
}
} elseif(is_scalar($tag['content']) && (string)$tag['content'] == '') {
$tag['content'] = '';
}
if (is_scalar($tag['content']) || is_null($tag['content'])) {
if ($this->options['encoding'] == 'UTF-8' &&
version_compare(phpversion(), '5.0.0', 'lt')) {
$encoding = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_UTF8_XML;
} else {
$encoding = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML;
}
$tag = PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $this->options['linebreak'], $encoding);
} elseif (is_array($tag['content'])) {
$tag = $this->_serializeArray($tag['content'], $tag['qname'], $tag['attributes']);
} elseif (is_object($tag['content'])) {
$tag = $this->_serializeObject($tag['content'], $tag['qname'], $tag['attributes']);
} elseif (is_resource($tag['content'])) {
settype($tag['content'], 'string');
$tag = PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray($tag, $replaceEntities);
}
return $tag;
}
}
 
// well, it's one way to do things without extra deps ...
/* vim: set expandtab tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Stephan Schmidt <schst@php-tools.net> |
// +----------------------------------------------------------------------+
//
// $Id: v2.php,v 1.35 2006/03/25 21:09:08 cellog Exp $
 
/**
* error code for invalid chars in XML name
*/
define("PEAR_PackageFile_Generator_v2_XML_Util_ERROR_INVALID_CHARS", 51);
 
/**
* error code for invalid chars in XML name
*/
define("PEAR_PackageFile_Generator_v2_XML_Util_ERROR_INVALID_START", 52);
 
/**
* error code for non-scalar tag content
*/
define("PEAR_PackageFile_Generator_v2_XML_Util_ERROR_NON_SCALAR_CONTENT", 60);
/**
* error code for missing tag name
*/
define("PEAR_PackageFile_Generator_v2_XML_Util_ERROR_NO_TAG_NAME", 61);
/**
* replace XML entities
*/
define("PEAR_PackageFile_Generator_v2_XML_Util_REPLACE_ENTITIES", 1);
 
/**
* embedd content in a CData Section
*/
define("PEAR_PackageFile_Generator_v2_XML_Util_CDATA_SECTION", 2);
 
/**
* do not replace entitites
*/
define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_NONE", 0);
 
/**
* replace all XML entitites
* This setting will replace <, >, ", ' and &
*/
define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML", 1);
 
/**
* replace only required XML entitites
* This setting will replace <, " and &
*/
define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML_REQUIRED", 2);
 
/**
* replace HTML entitites
* @link http://www.php.net/htmlentities
*/
define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_HTML", 3);
 
/**
* replace all XML entitites, and encode from ISO-8859-1 to UTF-8
* This setting will replace <, >, ", ' and &
*/
define("PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_UTF8_XML", 4);
 
/**
* utility class for working with XML documents
*
* customized version of XML_Util 0.6.0
*
* @category XML
* @package PEAR
* @version 0.6.0
* @author Stephan Schmidt <schst@php.net>
* @author Gregory Beaver <cellog@php.net>
*/
class PEAR_PackageFile_Generator_v2_XML_Util {
 
/**
* return API version
*
* @access public
* @static
* @return string $version API version
*/
function apiVersion()
{
return "0.6";
}
 
/**
* replace XML entities
*
* With the optional second parameter, you may select, which
* entities should be replaced.
*
* <code>
* require_once 'XML/Util.php';
*
* // replace XML entites:
* $string = PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities("This string contains < & >.");
* </code>
*
* @access public
* @static
* @param string string where XML special chars should be replaced
* @param integer setting for entities in attribute values (one of PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML_REQUIRED, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_HTML)
* @return string string with replaced chars
*/
function replaceEntities($string, $replaceEntities = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML)
{
switch ($replaceEntities) {
case PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_UTF8_XML:
return strtr(utf8_encode($string),array(
'&' => '&amp;',
'>' => '&gt;',
'<' => '&lt;',
'"' => '&quot;',
'\'' => '&apos;' ));
break;
case PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML:
return strtr($string,array(
'&' => '&amp;',
'>' => '&gt;',
'<' => '&lt;',
'"' => '&quot;',
'\'' => '&apos;' ));
break;
case PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML_REQUIRED:
return strtr($string,array(
'&' => '&amp;',
'<' => '&lt;',
'"' => '&quot;' ));
break;
case PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_HTML:
return htmlspecialchars($string);
break;
}
return $string;
}
 
/**
* build an xml declaration
*
* <code>
* require_once 'XML/Util.php';
*
* // get an XML declaration:
* $xmlDecl = PEAR_PackageFile_Generator_v2_XML_Util::getXMLDeclaration("1.0", "UTF-8", true);
* </code>
*
* @access public
* @static
* @param string $version xml version
* @param string $encoding character encoding
* @param boolean $standAlone document is standalone (or not)
* @return string $decl xml declaration
* @uses PEAR_PackageFile_Generator_v2_XML_Util::attributesToString() to serialize the attributes of the XML declaration
*/
function getXMLDeclaration($version = "1.0", $encoding = null, $standalone = null)
{
$attributes = array(
"version" => $version,
);
// add encoding
if ($encoding !== null) {
$attributes["encoding"] = $encoding;
}
// add standalone, if specified
if ($standalone !== null) {
$attributes["standalone"] = $standalone ? "yes" : "no";
}
return sprintf("<?xml%s?>", PEAR_PackageFile_Generator_v2_XML_Util::attributesToString($attributes, false));
}
 
/**
* build a document type declaration
*
* <code>
* require_once 'XML/Util.php';
*
* // get a doctype declaration:
* $xmlDecl = PEAR_PackageFile_Generator_v2_XML_Util::getDocTypeDeclaration("rootTag","myDocType.dtd");
* </code>
*
* @access public
* @static
* @param string $root name of the root tag
* @param string $uri uri of the doctype definition (or array with uri and public id)
* @param string $internalDtd internal dtd entries
* @return string $decl doctype declaration
* @since 0.2
*/
function getDocTypeDeclaration($root, $uri = null, $internalDtd = null)
{
if (is_array($uri)) {
$ref = sprintf( ' PUBLIC "%s" "%s"', $uri["id"], $uri["uri"] );
} elseif (!empty($uri)) {
$ref = sprintf( ' SYSTEM "%s"', $uri );
} else {
$ref = "";
}
 
if (empty($internalDtd)) {
return sprintf("<!DOCTYPE %s%s>", $root, $ref);
} else {
return sprintf("<!DOCTYPE %s%s [\n%s\n]>", $root, $ref, $internalDtd);
}
}
 
/**
* create string representation of an attribute list
*
* <code>
* require_once 'XML/Util.php';
*
* // build an attribute string
* $att = array(
* "foo" => "bar",
* "argh" => "tomato"
* );
*
* $attList = PEAR_PackageFile_Generator_v2_XML_Util::attributesToString($att);
* </code>
*
* @access public
* @static
* @param array $attributes attribute array
* @param boolean|array $sort sort attribute list alphabetically, may also be an assoc array containing the keys 'sort', 'multiline', 'indent', 'linebreak' and 'entities'
* @param boolean $multiline use linebreaks, if more than one attribute is given
* @param string $indent string used for indentation of multiline attributes
* @param string $linebreak string used for linebreaks of multiline attributes
* @param integer $entities setting for entities in attribute values (one of PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_NONE, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML_REQUIRED, PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_HTML)
* @return string string representation of the attributes
* @uses PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities() to replace XML entities in attribute values
* @todo allow sort also to be an options array
*/
function attributesToString($attributes, $sort = true, $multiline = false, $indent = ' ', $linebreak = "\n", $entities = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML)
{
/**
* second parameter may be an array
*/
if (is_array($sort)) {
if (isset($sort['multiline'])) {
$multiline = $sort['multiline'];
}
if (isset($sort['indent'])) {
$indent = $sort['indent'];
}
if (isset($sort['linebreak'])) {
$multiline = $sort['linebreak'];
}
if (isset($sort['entities'])) {
$entities = $sort['entities'];
}
if (isset($sort['sort'])) {
$sort = $sort['sort'];
} else {
$sort = true;
}
}
$string = '';
if (is_array($attributes) && !empty($attributes)) {
if ($sort) {
ksort($attributes);
}
if( !$multiline || count($attributes) == 1) {
foreach ($attributes as $key => $value) {
if ($entities != PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_NONE) {
$value = PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities($value, $entities);
}
$string .= ' '.$key.'="'.$value.'"';
}
} else {
$first = true;
foreach ($attributes as $key => $value) {
if ($entities != PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_NONE) {
$value = PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities($value, $entities);
}
if ($first) {
$string .= " ".$key.'="'.$value.'"';
$first = false;
} else {
$string .= $linebreak.$indent.$key.'="'.$value.'"';
}
}
}
}
return $string;
}
 
/**
* create a tag
*
* This method will call PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray(), which
* is more flexible.
*
* <code>
* require_once 'XML/Util.php';
*
* // create an XML tag:
* $tag = PEAR_PackageFile_Generator_v2_XML_Util::createTag("myNs:myTag", array("foo" => "bar"), "This is inside the tag", "http://www.w3c.org/myNs#");
* </code>
*
* @access public
* @static
* @param string $qname qualified tagname (including namespace)
* @param array $attributes array containg attributes
* @param mixed $content
* @param string $namespaceUri URI of the namespace
* @param integer $replaceEntities whether to replace XML special chars in content, embedd it in a CData section or none of both
* @param boolean $multiline whether to create a multiline tag where each attribute gets written to a single line
* @param string $indent string used to indent attributes (_auto indents attributes so they start at the same column)
* @param string $linebreak string used for linebreaks
* @param string $encoding encoding that should be used to translate content
* @return string $string XML tag
* @see PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray()
* @uses PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray() to create the tag
*/
function createTag($qname, $attributes = array(), $content = null, $namespaceUri = null, $replaceEntities = PEAR_PackageFile_Generator_v2_XML_Util_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n", $encoding = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML)
{
$tag = array(
"qname" => $qname,
"attributes" => $attributes
);
 
// add tag content
if ($content !== null) {
$tag["content"] = $content;
}
// add namespace Uri
if ($namespaceUri !== null) {
$tag["namespaceUri"] = $namespaceUri;
}
 
return PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $linebreak, $encoding);
}
 
/**
* create a tag from an array
* this method awaits an array in the following format
* <pre>
* array(
* "qname" => $qname // qualified name of the tag
* "namespace" => $namespace // namespace prefix (optional, if qname is specified or no namespace)
* "localpart" => $localpart, // local part of the tagname (optional, if qname is specified)
* "attributes" => array(), // array containing all attributes (optional)
* "content" => $content, // tag content (optional)
* "namespaceUri" => $namespaceUri // namespaceUri for the given namespace (optional)
* )
* </pre>
*
* <code>
* require_once 'XML/Util.php';
*
* $tag = array(
* "qname" => "foo:bar",
* "namespaceUri" => "http://foo.com",
* "attributes" => array( "key" => "value", "argh" => "fruit&vegetable" ),
* "content" => "I'm inside the tag",
* );
* // creating a tag with qualified name and namespaceUri
* $string = PEAR_PackageFile_Generator_v2_XML_Util::createTagFromArray($tag);
* </code>
*
* @access public
* @static
* @param array $tag tag definition
* @param integer $replaceEntities whether to replace XML special chars in content, embedd it in a CData section or none of both
* @param boolean $multiline whether to create a multiline tag where each attribute gets written to a single line
* @param string $indent string used to indent attributes (_auto indents attributes so they start at the same column)
* @param string $linebreak string used for linebreaks
* @return string $string XML tag
* @see PEAR_PackageFile_Generator_v2_XML_Util::createTag()
* @uses PEAR_PackageFile_Generator_v2_XML_Util::attributesToString() to serialize the attributes of the tag
* @uses PEAR_PackageFile_Generator_v2_XML_Util::splitQualifiedName() to get local part and namespace of a qualified name
*/
function createTagFromArray($tag, $replaceEntities = PEAR_PackageFile_Generator_v2_XML_Util_REPLACE_ENTITIES, $multiline = false, $indent = "_auto", $linebreak = "\n", $encoding = PEAR_PackageFile_Generator_v2_XML_Util_ENTITIES_XML)
{
if (isset($tag["content"]) && !is_scalar($tag["content"])) {
return PEAR_PackageFile_Generator_v2_XML_Util::raiseError( "Supplied non-scalar value as tag content", PEAR_PackageFile_Generator_v2_XML_Util_ERROR_NON_SCALAR_CONTENT );
}
 
if (!isset($tag['qname']) && !isset($tag['localPart'])) {
return PEAR_PackageFile_Generator_v2_XML_Util::raiseError( 'You must either supply a qualified name (qname) or local tag name (localPart).', PEAR_PackageFile_Generator_v2_XML_Util_ERROR_NO_TAG_NAME );
}
 
// if no attributes hav been set, use empty attributes
if (!isset($tag["attributes"]) || !is_array($tag["attributes"])) {
$tag["attributes"] = array();
}
// qualified name is not given
if (!isset($tag["qname"])) {
// check for namespace
if (isset($tag["namespace"]) && !empty($tag["namespace"])) {
$tag["qname"] = $tag["namespace"].":".$tag["localPart"];
} else {
$tag["qname"] = $tag["localPart"];
}
// namespace URI is set, but no namespace
} elseif (isset($tag["namespaceUri"]) && !isset($tag["namespace"])) {
$parts = PEAR_PackageFile_Generator_v2_XML_Util::splitQualifiedName($tag["qname"]);
$tag["localPart"] = $parts["localPart"];
if (isset($parts["namespace"])) {
$tag["namespace"] = $parts["namespace"];
}
}
 
if (isset($tag["namespaceUri"]) && !empty($tag["namespaceUri"])) {
// is a namespace given
if (isset($tag["namespace"]) && !empty($tag["namespace"])) {
$tag["attributes"]["xmlns:".$tag["namespace"]] = $tag["namespaceUri"];
} else {
// define this Uri as the default namespace
$tag["attributes"]["xmlns"] = $tag["namespaceUri"];
}
}
 
// check for multiline attributes
if ($multiline === true) {
if ($indent === "_auto") {
$indent = str_repeat(" ", (strlen($tag["qname"])+2));
}
}
// create attribute list
$attList = PEAR_PackageFile_Generator_v2_XML_Util::attributesToString($tag["attributes"], true, $multiline, $indent, $linebreak );
if (!isset($tag["content"]) || (string)$tag["content"] == '') {
$tag = sprintf("<%s%s />", $tag["qname"], $attList);
} else {
if ($replaceEntities == PEAR_PackageFile_Generator_v2_XML_Util_REPLACE_ENTITIES) {
$tag["content"] = PEAR_PackageFile_Generator_v2_XML_Util::replaceEntities($tag["content"], $encoding);
} elseif ($replaceEntities == PEAR_PackageFile_Generator_v2_XML_Util_CDATA_SECTION) {
$tag["content"] = PEAR_PackageFile_Generator_v2_XML_Util::createCDataSection($tag["content"]);
}
$tag = sprintf("<%s%s>%s</%s>", $tag["qname"], $attList, $tag["content"], $tag["qname"] );
}
return $tag;
}
 
/**
* create a start element
*
* <code>
* require_once 'XML/Util.php';
*
* // create an XML start element:
* $tag = PEAR_PackageFile_Generator_v2_XML_Util::createStartElement("myNs:myTag", array("foo" => "bar") ,"http://www.w3c.org/myNs#");
* </code>
*
* @access public
* @static
* @param string $qname qualified tagname (including namespace)
* @param array $attributes array containg attributes
* @param string $namespaceUri URI of the namespace
* @param boolean $multiline whether to create a multiline tag where each attribute gets written to a single line
* @param string $indent string used to indent attributes (_auto indents attributes so they start at the same column)
* @param string $linebreak string used for linebreaks
* @return string $string XML start element
* @see PEAR_PackageFile_Generator_v2_XML_Util::createEndElement(), PEAR_PackageFile_Generator_v2_XML_Util::createTag()
*/
function createStartElement($qname, $attributes = array(), $namespaceUri = null, $multiline = false, $indent = '_auto', $linebreak = "\n")
{
// if no attributes hav been set, use empty attributes
if (!isset($attributes) || !is_array($attributes)) {
$attributes = array();
}
if ($namespaceUri != null) {
$parts = PEAR_PackageFile_Generator_v2_XML_Util::splitQualifiedName($qname);
}
 
// check for multiline attributes
if ($multiline === true) {
if ($indent === "_auto") {
$indent = str_repeat(" ", (strlen($qname)+2));
}
}
 
if ($namespaceUri != null) {
// is a namespace given
if (isset($parts["namespace"]) && !empty($parts["namespace"])) {
$attributes["xmlns:".$parts["namespace"]] = $namespaceUri;
} else {
// define this Uri as the default namespace
$attributes["xmlns"] = $namespaceUri;
}
}
 
// create attribute list
$attList = PEAR_PackageFile_Generator_v2_XML_Util::attributesToString($attributes, true, $multiline, $indent, $linebreak);
$element = sprintf("<%s%s>", $qname, $attList);
return $element;
}
 
/**
* create an end element
*
* <code>
* require_once 'XML/Util.php';
*
* // create an XML start element:
* $tag = PEAR_PackageFile_Generator_v2_XML_Util::createEndElement("myNs:myTag");
* </code>
*
* @access public
* @static
* @param string $qname qualified tagname (including namespace)
* @return string $string XML end element
* @see PEAR_PackageFile_Generator_v2_XML_Util::createStartElement(), PEAR_PackageFile_Generator_v2_XML_Util::createTag()
*/
function createEndElement($qname)
{
$element = sprintf("</%s>", $qname);
return $element;
}
/**
* create an XML comment
*
* <code>
* require_once 'XML/Util.php';
*
* // create an XML start element:
* $tag = PEAR_PackageFile_Generator_v2_XML_Util::createComment("I am a comment");
* </code>
*
* @access public
* @static
* @param string $content content of the comment
* @return string $comment XML comment
*/
function createComment($content)
{
$comment = sprintf("<!-- %s -->", $content);
return $comment;
}
/**
* create a CData section
*
* <code>
* require_once 'XML/Util.php';
*
* // create a CData section
* $tag = PEAR_PackageFile_Generator_v2_XML_Util::createCDataSection("I am content.");
* </code>
*
* @access public
* @static
* @param string $data data of the CData section
* @return string $string CData section with content
*/
function createCDataSection($data)
{
return sprintf("<![CDATA[%s]]>", $data);
}
 
/**
* split qualified name and return namespace and local part
*
* <code>
* require_once 'XML/Util.php';
*
* // split qualified tag
* $parts = PEAR_PackageFile_Generator_v2_XML_Util::splitQualifiedName("xslt:stylesheet");
* </code>
* the returned array will contain two elements:
* <pre>
* array(
* "namespace" => "xslt",
* "localPart" => "stylesheet"
* );
* </pre>
*
* @access public
* @static
* @param string $qname qualified tag name
* @param string $defaultNs default namespace (optional)
* @return array $parts array containing namespace and local part
*/
function splitQualifiedName($qname, $defaultNs = null)
{
if (strstr($qname, ':')) {
$tmp = explode(":", $qname);
return array(
"namespace" => $tmp[0],
"localPart" => $tmp[1]
);
}
return array(
"namespace" => $defaultNs,
"localPart" => $qname
);
}
 
/**
* check, whether string is valid XML name
*
* <p>XML names are used for tagname, attribute names and various
* other, lesser known entities.</p>
* <p>An XML name may only consist of alphanumeric characters,
* dashes, undescores and periods, and has to start with a letter
* or an underscore.
* </p>
*
* <code>
* require_once 'XML/Util.php';
*
* // verify tag name
* $result = PEAR_PackageFile_Generator_v2_XML_Util::isValidName("invalidTag?");
* if (PEAR_PackageFile_Generator_v2_XML_Util::isError($result)) {
* print "Invalid XML name: " . $result->getMessage();
* }
* </code>
*
* @access public
* @static
* @param string $string string that should be checked
* @return mixed $valid true, if string is a valid XML name, PEAR error otherwise
* @todo support for other charsets
*/
function isValidName($string)
{
// check for invalid chars
if (!preg_match("/^[[:alnum:]_\-.]$/", $string{0})) {
return PEAR_PackageFile_Generator_v2_XML_Util::raiseError( "XML names may only start with letter or underscore", PEAR_PackageFile_Generator_v2_XML_Util_ERROR_INVALID_START );
}
// check for invalid chars
if (!preg_match("/^([a-zA-Z_]([a-zA-Z0-9_\-\.]*)?:)?[a-zA-Z_]([a-zA-Z0-9_\-\.]+)?$/", $string)) {
return PEAR_PackageFile_Generator_v2_XML_Util::raiseError( "XML names may only contain alphanumeric chars, period, hyphen, colon and underscores", PEAR_PackageFile_Generator_v2_XML_Util_ERROR_INVALID_CHARS );
}
// XML name is valid
return true;
}
 
/**
* replacement for PEAR_PackageFile_Generator_v2_XML_Util::raiseError
*
* Avoids the necessity to always require
* PEAR.php
*
* @access public
* @param string error message
* @param integer error code
* @return object PEAR_Error
*/
function raiseError($msg, $code)
{
require_once 'PEAR.php';
return PEAR::raiseError($msg, $code);
}
}
?>
/trunk/bibliotheque/pear/PEAR/PackageFile/v2/Validator.php
New file
0,0 → 1,2058
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 5 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available through the world-wide-web at the following url: |
// | http://www.php.net/license/3_0.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Author: Greg Beaver <cellog@php.net> |
// | |
// +----------------------------------------------------------------------+
//
// $Id: Validator.php,v 1.97 2007/02/10 05:56:18 cellog Exp $
/**
* Private validation class used by PEAR_PackageFile_v2 - do not use directly, its
* sole purpose is to split up the PEAR/PackageFile/v2.php file to make it smaller
* @author Greg Beaver <cellog@php.net>
* @access private
*/
class PEAR_PackageFile_v2_Validator
{
/**
* @var array
*/
var $_packageInfo;
/**
* @var PEAR_PackageFile_v2
*/
var $_pf;
/**
* @var PEAR_ErrorStack
*/
var $_stack;
/**
* @var int
*/
var $_isValid = 0;
/**
* @var int
*/
var $_filesValid = 0;
/**
* @var int
*/
var $_curState = 0;
/**
* @param PEAR_PackageFile_v2
* @param int
*/
function validate(&$pf, $state = PEAR_VALIDATE_NORMAL)
{
$this->_pf = &$pf;
$this->_curState = $state;
$this->_packageInfo = $this->_pf->getArray();
$this->_isValid = $this->_pf->_isValid;
$this->_filesValid = $this->_pf->_filesValid;
$this->_stack = &$pf->_stack;
$this->_stack->getErrors(true);
if (($this->_isValid & $state) == $state) {
return true;
}
if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
return false;
}
if (!isset($this->_packageInfo['attribs']['version']) ||
($this->_packageInfo['attribs']['version'] != '2.0' &&
$this->_packageInfo['attribs']['version'] != '2.1')) {
$this->_noPackageVersion();
}
$structure =
array(
'name',
'channel|uri',
'*extends', // can't be multiple, but this works fine
'summary',
'description',
'+lead', // these all need content checks
'*developer',
'*contributor',
'*helper',
'date',
'*time',
'version',
'stability',
'license->?uri->?filesource',
'notes',
'contents', //special validation needed
'*compatible',
'dependencies', //special validation needed
'*usesrole',
'*usestask', // reserve these for 1.4.0a1 to implement
// this will allow a package.xml to gracefully say it
// needs a certain package installed in order to implement a role or task
'*providesextension',
'*srcpackage|*srcuri',
'+phprelease|+extsrcrelease|+extbinrelease|' .
'+zendextsrcrelease|+zendextbinrelease|bundle', //special validation needed
'*changelog',
);
$test = $this->_packageInfo;
if (isset($test['dependencies']) &&
isset($test['dependencies']['required']) &&
isset($test['dependencies']['required']['pearinstaller']) &&
isset($test['dependencies']['required']['pearinstaller']['min']) &&
version_compare('1.5.1',
$test['dependencies']['required']['pearinstaller']['min'], '<')) {
$this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']);
return false;
}
// ignore post-installation array fields
if (array_key_exists('filelist', $test)) {
unset($test['filelist']);
}
if (array_key_exists('_lastmodified', $test)) {
unset($test['_lastmodified']);
}
if (array_key_exists('#binarypackage', $test)) {
unset($test['#binarypackage']);
}
if (array_key_exists('old', $test)) {
unset($test['old']);
}
if (array_key_exists('_lastversion', $test)) {
unset($test['_lastversion']);
}
if (!$this->_stupidSchemaValidate($structure,
$test, '<package>')) {
return false;
}
if (empty($this->_packageInfo['name'])) {
$this->_tagCannotBeEmpty('name');
}
if (isset($this->_packageInfo['uri'])) {
$test = 'uri';
} else {
$test = 'channel';
}
if (empty($this->_packageInfo[$test])) {
$this->_tagCannotBeEmpty($test);
}
if (is_array($this->_packageInfo['license']) &&
(!isset($this->_packageInfo['license']['_content']) ||
empty($this->_packageInfo['license']['_content']))) {
$this->_tagCannotBeEmpty('license');
} elseif (empty($this->_packageInfo['license'])) {
$this->_tagCannotBeEmpty('license');
}
if (empty($this->_packageInfo['summary'])) {
$this->_tagCannotBeEmpty('summary');
}
if (empty($this->_packageInfo['description'])) {
$this->_tagCannotBeEmpty('description');
}
if (empty($this->_packageInfo['date'])) {
$this->_tagCannotBeEmpty('date');
}
if (empty($this->_packageInfo['notes'])) {
$this->_tagCannotBeEmpty('notes');
}
if (isset($this->_packageInfo['time']) && empty($this->_packageInfo['time'])) {
$this->_tagCannotBeEmpty('time');
}
if (isset($this->_packageInfo['dependencies'])) {
$this->_validateDependencies();
}
if (isset($this->_packageInfo['compatible'])) {
$this->_validateCompatible();
}
if (!isset($this->_packageInfo['bundle'])) {
if (empty($this->_packageInfo['contents'])) {
$this->_tagCannotBeEmpty('contents');
}
if (!isset($this->_packageInfo['contents']['dir'])) {
$this->_filelistMustContainDir('contents');
return false;
}
if (isset($this->_packageInfo['contents']['file'])) {
$this->_filelistCannotContainFile('contents');
return false;
}
}
$this->_validateMaintainers();
$this->_validateStabilityVersion();
$fail = false;
if (array_key_exists('usesrole', $this->_packageInfo)) {
$roles = $this->_packageInfo['usesrole'];
if (!is_array($roles) || !isset($roles[0])) {
$roles = array($roles);
}
foreach ($roles as $role) {
if (!isset($role['role'])) {
$this->_usesroletaskMustHaveRoleTask('usesrole', 'role');
$fail = true;
} else {
if (!isset($role['channel'])) {
if (!isset($role['uri'])) {
$this->_usesroletaskMustHaveChannelOrUri($role['role'], 'usesrole');
$fail = true;
}
} elseif (!isset($role['package'])) {
$this->_usesroletaskMustHavePackage($role['role'], 'usesrole');
$fail = true;
}
}
}
}
if (array_key_exists('usestask', $this->_packageInfo)) {
$roles = $this->_packageInfo['usestask'];
if (!is_array($roles) || !isset($roles[0])) {
$roles = array($roles);
}
foreach ($roles as $role) {
if (!isset($role['task'])) {
$this->_usesroletaskMustHaveRoleTask('usestask', 'task');
$fail = true;
} else {
if (!isset($role['channel'])) {
if (!isset($role['uri'])) {
$this->_usesroletaskMustHaveChannelOrUri($role['task'], 'usestask');
$fail = true;
}
} elseif (!isset($role['package'])) {
$this->_usesroletaskMustHavePackage($role['task'], 'usestask');
$fail = true;
}
}
}
}
if ($fail) {
return false;
}
$list = $this->_packageInfo['contents'];
if (isset($list['dir']) && is_array($list['dir']) && isset($list['dir'][0])) {
$this->_multipleToplevelDirNotAllowed();
return $this->_isValid = 0;
}
$this->_validateFilelist();
$this->_validateRelease();
if (!$this->_stack->hasErrors()) {
$chan = $this->_pf->_registry->getChannel($this->_pf->getChannel(), true);
if (PEAR::isError($chan)) {
$this->_unknownChannel($this->_pf->getChannel());
} else {
$valpack = $chan->getValidationPackage();
// for channel validator packages, always use the default PEAR validator.
// otherwise, they can't be installed or packaged
$validator = $chan->getValidationObject($this->_pf->getPackage());
if (!$validator) {
$this->_stack->push(__FUNCTION__, 'error',
array_merge(
array('channel' => $chan->getName(),
'package' => $this->_pf->getPackage()),
$valpack
),
'package "%channel%/%package%" cannot be properly validated without ' .
'validation package "%channel%/%name%-%version%"');
return $this->_isValid = 0;
}
$validator->setPackageFile($this->_pf);
$validator->validate($state);
$failures = $validator->getFailures();
foreach ($failures['errors'] as $error) {
$this->_stack->push(__FUNCTION__, 'error', $error,
'Channel validator error: field "%field%" - %reason%');
}
foreach ($failures['warnings'] as $warning) {
$this->_stack->push(__FUNCTION__, 'warning', $warning,
'Channel validator warning: field "%field%" - %reason%');
}
}
}
$this->_pf->_isValid = $this->_isValid = !$this->_stack->hasErrors('error');
if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$this->_filesValid) {
if ($this->_pf->getPackageType() == 'bundle') {
if ($this->_analyzeBundledPackages()) {
$this->_filesValid = $this->_pf->_filesValid = true;
} else {
$this->_pf->_isValid = $this->_isValid = 0;
}
} else {
if (!$this->_analyzePhpFiles()) {
$this->_pf->_isValid = $this->_isValid = 0;
} else {
$this->_filesValid = $this->_pf->_filesValid = true;
}
}
}
if ($this->_isValid) {
return $this->_pf->_isValid = $this->_isValid = $state;
}
return $this->_pf->_isValid = $this->_isValid = 0;
}
 
function _stupidSchemaValidate($structure, $xml, $root)
{
if (!is_array($xml)) {
$xml = array();
}
$keys = array_keys($xml);
reset($keys);
$key = current($keys);
while ($key == 'attribs' || $key == '_contents') {
$key = next($keys);
}
$unfoundtags = $optionaltags = array();
$ret = true;
$mismatch = false;
foreach ($structure as $struc) {
if ($key) {
$tag = $xml[$key];
}
$test = $this->_processStructure($struc);
if (isset($test['choices'])) {
$loose = true;
foreach ($test['choices'] as $choice) {
if ($key == $choice['tag']) {
$key = next($keys);
while ($key == 'attribs' || $key == '_contents') {
$key = next($keys);
}
$unfoundtags = $optionaltags = array();
$mismatch = false;
if ($key && $key != $choice['tag'] && isset($choice['multiple'])) {
$unfoundtags[] = $choice['tag'];
$optionaltags[] = $choice['tag'];
if ($key) {
$mismatch = true;
}
}
$ret &= $this->_processAttribs($choice, $tag, $root);
continue 2;
} else {
$unfoundtags[] = $choice['tag'];
$mismatch = true;
}
if (!isset($choice['multiple']) || $choice['multiple'] != '*') {
$loose = false;
} else {
$optionaltags[] = $choice['tag'];
}
}
if (!$loose) {
$this->_invalidTagOrder($unfoundtags, $key, $root);
return false;
}
} else {
if ($key != $test['tag']) {
if (isset($test['multiple']) && $test['multiple'] != '*') {
$unfoundtags[] = $test['tag'];
$this->_invalidTagOrder($unfoundtags, $key, $root);
return false;
} else {
if ($key) {
$mismatch = true;
}
$unfoundtags[] = $test['tag'];
$optionaltags[] = $test['tag'];
}
if (!isset($test['multiple'])) {
$this->_invalidTagOrder($unfoundtags, $key, $root);
return false;
}
continue;
} else {
$unfoundtags = $optionaltags = array();
$mismatch = false;
}
$key = next($keys);
while ($key == 'attribs' || $key == '_contents') {
$key = next($keys);
}
if ($key && $key != $test['tag'] && isset($test['multiple'])) {
$unfoundtags[] = $test['tag'];
$optionaltags[] = $test['tag'];
$mismatch = true;
}
$ret &= $this->_processAttribs($test, $tag, $root);
continue;
}
}
if (!$mismatch && count($optionaltags)) {
// don't error out on any optional tags
$unfoundtags = array_diff($unfoundtags, $optionaltags);
}
if (count($unfoundtags)) {
$this->_invalidTagOrder($unfoundtags, $key, $root);
} elseif ($key) {
// unknown tags
$this->_invalidTagOrder('*no tags allowed here*', $key, $root);
while ($key = next($keys)) {
$this->_invalidTagOrder('*no tags allowed here*', $key, $root);
}
}
return $ret;
}
 
function _processAttribs($choice, $tag, $context)
{
if (isset($choice['attribs'])) {
if (!is_array($tag)) {
$tag = array($tag);
}
$tags = $tag;
if (!isset($tags[0])) {
$tags = array($tags);
}
$ret = true;
foreach ($tags as $i => $tag) {
if (!is_array($tag) || !isset($tag['attribs'])) {
foreach ($choice['attribs'] as $attrib) {
if ($attrib{0} != '?') {
$ret &= $this->_tagHasNoAttribs($choice['tag'],
$context);
continue 2;
}
}
}
foreach ($choice['attribs'] as $attrib) {
if ($attrib{0} != '?') {
if (!isset($tag['attribs'][$attrib])) {
$ret &= $this->_tagMissingAttribute($choice['tag'],
$attrib, $context);
}
}
}
}
return $ret;
}
return true;
}
 
function _processStructure($key)
{
$ret = array();
if (count($pieces = explode('|', $key)) > 1) {
$ret['choices'] = array();
foreach ($pieces as $piece) {
$ret['choices'][] = $this->_processStructure($piece);
}
return $ret;
}
$multi = $key{0};
if ($multi == '+' || $multi == '*') {
$ret['multiple'] = $key{0};
$key = substr($key, 1);
}
if (count($attrs = explode('->', $key)) > 1) {
$ret['tag'] = array_shift($attrs);
$ret['attribs'] = $attrs;
} else {
$ret['tag'] = $key;
}
return $ret;
}
 
function _validateStabilityVersion()
{
$structure = array('release', 'api');
$a = $this->_stupidSchemaValidate($structure, $this->_packageInfo['version'], '<version>');
$a &= $this->_stupidSchemaValidate($structure, $this->_packageInfo['stability'], '<stability>');
if ($a) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
$this->_packageInfo['version']['release'])) {
$this->_invalidVersion('release', $this->_packageInfo['version']['release']);
}
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
$this->_packageInfo['version']['api'])) {
$this->_invalidVersion('api', $this->_packageInfo['version']['api']);
}
if (!in_array($this->_packageInfo['stability']['release'],
array('snapshot', 'devel', 'alpha', 'beta', 'stable'))) {
$this->_invalidState('release', $this->_packageinfo['stability']['release']);
}
if (!in_array($this->_packageInfo['stability']['api'],
array('devel', 'alpha', 'beta', 'stable'))) {
$this->_invalidState('api', $this->_packageinfo['stability']['api']);
}
}
}
 
function _validateMaintainers()
{
$structure =
array(
'name',
'user',
'email',
'active',
);
foreach (array('lead', 'developer', 'contributor', 'helper') as $type) {
if (!isset($this->_packageInfo[$type])) {
continue;
}
if (isset($this->_packageInfo[$type][0])) {
foreach ($this->_packageInfo[$type] as $lead) {
$this->_stupidSchemaValidate($structure, $lead, '<' . $type . '>');
}
} else {
$this->_stupidSchemaValidate($structure, $this->_packageInfo[$type],
'<' . $type . '>');
}
}
}
 
function _validatePhpDep($dep, $installcondition = false)
{
$structure = array(
'min',
'*max',
'*exclude',
);
$type = $installcondition ? '<installcondition><php>' : '<dependencies><required><php>';
$this->_stupidSchemaValidate($structure, $dep, $type);
if (isset($dep['min'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?$/',
$dep['min'])) {
$this->_invalidVersion($type . '<min>', $dep['min']);
}
}
if (isset($dep['max'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?$/',
$dep['max'])) {
$this->_invalidVersion($type . '<max>', $dep['max']);
}
}
if (isset($dep['exclude'])) {
if (!is_array($dep['exclude'])) {
$dep['exclude'] = array($dep['exclude']);
}
foreach ($dep['exclude'] as $exclude) {
if (!preg_match(
'/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?$/',
$exclude)) {
$this->_invalidVersion($type . '<exclude>', $exclude);
}
}
}
}
 
function _validatePearinstallerDep($dep)
{
$structure = array(
'min',
'*max',
'*recommended',
'*exclude',
);
$this->_stupidSchemaValidate($structure, $dep, '<dependencies><required><pearinstaller>');
if (isset($dep['min'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
$dep['min'])) {
$this->_invalidVersion('<dependencies><required><pearinstaller><min>',
$dep['min']);
}
}
if (isset($dep['max'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
$dep['max'])) {
$this->_invalidVersion('<dependencies><required><pearinstaller><max>',
$dep['max']);
}
}
if (isset($dep['recommended'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
$dep['recommended'])) {
$this->_invalidVersion('<dependencies><required><pearinstaller><recommended>',
$dep['recommended']);
}
}
if (isset($dep['exclude'])) {
if (!is_array($dep['exclude'])) {
$dep['exclude'] = array($dep['exclude']);
}
foreach ($dep['exclude'] as $exclude) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
$exclude)) {
$this->_invalidVersion('<dependencies><required><pearinstaller><exclude>',
$exclude);
}
}
}
}
 
function _validatePackageDep($dep, $group, $type = '<package>')
{
if (isset($dep['uri'])) {
if (isset($dep['conflicts'])) {
$structure = array(
'name',
'uri',
'conflicts',
'*providesextension',
);
} else {
$structure = array(
'name',
'uri',
'*providesextension',
);
}
} else {
if (isset($dep['conflicts'])) {
$structure = array(
'name',
'channel',
'*min',
'*max',
'*exclude',
'conflicts',
'*providesextension',
);
} else {
$structure = array(
'name',
'channel',
'*min',
'*max',
'*recommended',
'*exclude',
'*nodefault',
'*providesextension',
);
}
}
if (isset($dep['name'])) {
$type .= '<name>' . $dep['name'] . '</name>';
}
$this->_stupidSchemaValidate($structure, $dep, '<dependencies>' . $group . $type);
if (isset($dep['uri']) && (isset($dep['min']) || isset($dep['max']) ||
isset($dep['recommended']) || isset($dep['exclude']))) {
$this->_uriDepsCannotHaveVersioning('<dependencies>' . $group . $type);
}
if (isset($dep['channel']) && strtolower($dep['channel']) == '__uri') {
$this->_DepchannelCannotBeUri('<dependencies>' . $group . $type);
}
if (isset($dep['min'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
$dep['min'])) {
$this->_invalidVersion('<dependencies>' . $group . $type . '<min>', $dep['min']);
}
}
if (isset($dep['max'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
$dep['max'])) {
$this->_invalidVersion('<dependencies>' . $group . $type . '<max>', $dep['max']);
}
}
if (isset($dep['recommended'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
$dep['recommended'])) {
$this->_invalidVersion('<dependencies>' . $group . $type . '<recommended>',
$dep['recommended']);
}
}
if (isset($dep['exclude'])) {
if (!is_array($dep['exclude'])) {
$dep['exclude'] = array($dep['exclude']);
}
foreach ($dep['exclude'] as $exclude) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
$exclude)) {
$this->_invalidVersion('<dependencies>' . $group . $type . '<exclude>',
$exclude);
}
}
}
}
 
function _validateSubpackageDep($dep, $group)
{
$this->_validatePackageDep($dep, $group, '<subpackage>');
if (isset($dep['providesextension'])) {
$this->_subpackageCannotProvideExtension(isset($dep['name']) ? $dep['name'] : '');
}
if (isset($dep['conflicts'])) {
$this->_subpackagesCannotConflict(isset($dep['name']) ? $dep['name'] : '');
}
}
 
function _validateExtensionDep($dep, $group = false, $installcondition = false)
{
if (isset($dep['conflicts'])) {
$structure = array(
'name',
'*min',
'*max',
'*exclude',
'conflicts',
);
} else {
$structure = array(
'name',
'*min',
'*max',
'*recommended',
'*exclude',
);
}
if ($installcondition) {
$type = '<installcondition><extension>';
} else {
$type = '<dependencies>' . $group . '<extension>';
}
if (isset($dep['name'])) {
$type .= '<name>' . $dep['name'] . '</name>';
}
$this->_stupidSchemaValidate($structure, $dep, $type);
if (isset($dep['min'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
$dep['min'])) {
$this->_invalidVersion(substr($type, 1) . '<min', $dep['min']);
}
}
if (isset($dep['max'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
$dep['max'])) {
$this->_invalidVersion(substr($type, 1) . '<max', $dep['max']);
}
}
if (isset($dep['recommended'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
$dep['recommended'])) {
$this->_invalidVersion(substr($type, 1) . '<recommended', $dep['recommended']);
}
}
if (isset($dep['exclude'])) {
if (!is_array($dep['exclude'])) {
$dep['exclude'] = array($dep['exclude']);
}
foreach ($dep['exclude'] as $exclude) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
$exclude)) {
$this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
}
}
}
}
 
function _validateOsDep($dep, $installcondition = false)
{
$structure = array(
'name',
'*conflicts',
);
$type = $installcondition ? '<installcondition><os>' : '<dependencies><required><os>';
if ($this->_stupidSchemaValidate($structure, $dep, $type)) {
if ($dep['name'] == '*') {
if (array_key_exists('conflicts', $dep)) {
$this->_cannotConflictWithAllOs($type);
}
}
}
}
 
function _validateArchDep($dep, $installcondition = false)
{
$structure = array(
'pattern',
'*conflicts',
);
$type = $installcondition ? '<installcondition><arch>' : '<dependencies><required><arch>';
$this->_stupidSchemaValidate($structure, $dep, $type);
}
 
function _validateInstallConditions($cond, $release)
{
$structure = array(
'*php',
'*extension',
'*os',
'*arch',
);
if (!$this->_stupidSchemaValidate($structure,
$cond, $release)) {
return false;
}
foreach (array('php', 'extension', 'os', 'arch') as $type) {
if (isset($cond[$type])) {
$iter = $cond[$type];
if (!is_array($iter) || !isset($iter[0])) {
$iter = array($iter);
}
foreach ($iter as $package) {
if ($type == 'extension') {
$this->{"_validate{$type}Dep"}($package, false, true);
} else {
$this->{"_validate{$type}Dep"}($package, true);
}
}
}
}
}
 
function _validateDependencies()
{
$structure = array(
'required',
'*optional',
'*group->name->hint'
);
if (!$this->_stupidSchemaValidate($structure,
$this->_packageInfo['dependencies'], '<dependencies>')) {
return false;
}
foreach (array('required', 'optional') as $simpledep) {
if (isset($this->_packageInfo['dependencies'][$simpledep])) {
if ($simpledep == 'optional') {
$structure = array(
'*package',
'*subpackage',
'*extension',
);
} else {
$structure = array(
'php',
'pearinstaller',
'*package',
'*subpackage',
'*extension',
'*os',
'*arch',
);
}
if ($this->_stupidSchemaValidate($structure,
$this->_packageInfo['dependencies'][$simpledep],
"<dependencies><$simpledep>")) {
foreach (array('package', 'subpackage', 'extension') as $type) {
if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
$iter = $this->_packageInfo['dependencies'][$simpledep][$type];
if (!isset($iter[0])) {
$iter = array($iter);
}
foreach ($iter as $package) {
if ($type != 'extension') {
if (isset($package['uri'])) {
if (isset($package['channel'])) {
$this->_UrlOrChannel($type,
$package['name']);
}
} else {
if (!isset($package['channel'])) {
$this->_NoChannel($type, $package['name']);
}
}
}
$this->{"_validate{$type}Dep"}($package, "<$simpledep>");
}
}
}
if ($simpledep == 'optional') {
continue;
}
foreach (array('php', 'pearinstaller', 'os', 'arch') as $type) {
if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
$iter = $this->_packageInfo['dependencies'][$simpledep][$type];
if (!isset($iter[0])) {
$iter = array($iter);
}
foreach ($iter as $package) {
$this->{"_validate{$type}Dep"}($package);
}
}
}
}
}
}
if (isset($this->_packageInfo['dependencies']['group'])) {
$groups = $this->_packageInfo['dependencies']['group'];
if (!isset($groups[0])) {
$groups = array($groups);
}
$structure = array(
'*package',
'*subpackage',
'*extension',
);
foreach ($groups as $group) {
if ($this->_stupidSchemaValidate($structure, $group, '<group>')) {
if (!PEAR_Validate::validGroupName($group['attribs']['name'])) {
$this->_invalidDepGroupName($group['attribs']['name']);
}
foreach (array('package', 'subpackage', 'extension') as $type) {
if (isset($group[$type])) {
$iter = $group[$type];
if (!isset($iter[0])) {
$iter = array($iter);
}
foreach ($iter as $package) {
if ($type != 'extension') {
if (isset($package['uri'])) {
if (isset($package['channel'])) {
$this->_UrlOrChannelGroup($type,
$package['name'],
$group['name']);
}
} else {
if (!isset($package['channel'])) {
$this->_NoChannelGroup($type,
$package['name'],
$group['name']);
}
}
}
$this->{"_validate{$type}Dep"}($package, '<group name="' .
$group['attribs']['name'] . '">');
}
}
}
}
}
}
}
 
function _validateCompatible()
{
$compat = $this->_packageInfo['compatible'];
if (!isset($compat[0])) {
$compat = array($compat);
}
$required = array('name', 'channel', 'min', 'max', '*exclude');
foreach ($compat as $package) {
$type = '<compatible>';
if (is_array($package) && array_key_exists('name', $package)) {
$type .= '<name>' . $package['name'] . '</name>';
}
$this->_stupidSchemaValidate($required, $package, $type);
if (is_array($package) && array_key_exists('min', $package)) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
$package['min'])) {
$this->_invalidVersion(substr($type, 1) . '<min', $package['min']);
}
}
if (is_array($package) && array_key_exists('max', $package)) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
$package['max'])) {
$this->_invalidVersion(substr($type, 1) . '<max', $package['max']);
}
}
if (is_array($package) && array_key_exists('exclude', $package)) {
if (!is_array($package['exclude'])) {
$package['exclude'] = array($package['exclude']);
}
foreach ($package['exclude'] as $exclude) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?$/',
$exclude)) {
$this->_invalidVersion(substr($type, 1) . '<exclude', $exclude);
}
}
}
}
}
 
function _validateBundle($list)
{
if (!is_array($list) || !isset($list['bundledpackage'])) {
return $this->_NoBundledPackages();
}
if (!is_array($list['bundledpackage']) || !isset($list['bundledpackage'][0])) {
return $this->_AtLeast2BundledPackages();
}
foreach ($list['bundledpackage'] as $package) {
if (!is_string($package)) {
$this->_bundledPackagesMustBeFilename();
}
}
}
 
function _validateFilelist($list = false, $allowignore = false, $dirs = '')
{
$iscontents = false;
if (!$list) {
$iscontents = true;
$list = $this->_packageInfo['contents'];
if (isset($this->_packageInfo['bundle'])) {
return $this->_validateBundle($list);
}
}
if ($allowignore) {
$struc = array(
'*install->name->as',
'*ignore->name'
);
} else {
$struc = array(
'*dir->name->?baseinstalldir',
'*file->name->role->?baseinstalldir->?md5sum'
);
if (isset($list['dir']) && isset($list['file'])) {
// stave off validation errors without requiring a set order.
$_old = $list;
if (isset($list['attribs'])) {
$list = array('attribs' => $_old['attribs']);
}
$list['dir'] = $_old['dir'];
$list['file'] = $_old['file'];
}
}
if (!isset($list['attribs']) || !isset($list['attribs']['name'])) {
$unknown = $allowignore ? '<filelist>' : '<dir name="*unknown*">';
$dirname = $iscontents ? '<contents>' : $unknown;
} else {
$dirname = '<dir name="' . $list['attribs']['name'] . '">';
}
$res = $this->_stupidSchemaValidate($struc, $list, $dirname);
if ($allowignore && $res) {
$ignored_or_installed = array();
$this->_pf->getFilelist();
$fcontents = $this->_pf->getContents();
$filelist = array();
if (!isset($fcontents['dir']['file'][0])) {
$fcontents['dir']['file'] = array($fcontents['dir']['file']);
}
foreach ($fcontents['dir']['file'] as $file) {
$filelist[$file['attribs']['name']] = true;
}
if (isset($list['install'])) {
if (!isset($list['install'][0])) {
$list['install'] = array($list['install']);
}
foreach ($list['install'] as $file) {
if (!isset($filelist[$file['attribs']['name']])) {
$this->_notInContents($file['attribs']['name'], 'install');
continue;
}
if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
$this->_multipleInstallAs($file['attribs']['name']);
}
if (!isset($ignored_or_installed[$file['attribs']['name']])) {
$ignored_or_installed[$file['attribs']['name']] = array();
}
$ignored_or_installed[$file['attribs']['name']][] = 1;
}
}
if (isset($list['ignore'])) {
if (!isset($list['ignore'][0])) {
$list['ignore'] = array($list['ignore']);
}
foreach ($list['ignore'] as $file) {
if (!isset($filelist[$file['attribs']['name']])) {
$this->_notInContents($file['attribs']['name'], 'ignore');
continue;
}
if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
$this->_ignoreAndInstallAs($file['attribs']['name']);
}
}
}
}
if (!$allowignore && isset($list['file'])) {
if (!isset($list['file'][0])) {
// single file
$list['file'] = array($list['file']);
}
foreach ($list['file'] as $i => $file)
{
if (isset($file['attribs']) && isset($file['attribs']['name']) &&
$file['attribs']['name']{0} == '.' &&
$file['attribs']['name']{1} == '/') {
// name is something like "./doc/whatever.txt"
$this->_invalidFileName($file['attribs']['name']);
}
if (isset($file['attribs']) && isset($file['attribs']['role'])) {
if (!$this->_validateRole($file['attribs']['role'])) {
if (isset($this->_packageInfo['usesrole'])) {
$roles = $this->_packageInfo['usesrole'];
if (!isset($roles[0])) {
$roles = array($roles);
}
foreach ($roles as $role) {
if ($role['role'] = $file['attribs']['role']) {
$msg = 'This package contains role "%role%" and requires ' .
'package "%package%" to be used';
if (isset($role['uri'])) {
$params = array('role' => $role['role'],
'package' => $role['uri']);
} else {
$params = array('role' => $role['role'],
'package' => $this->_pf->_registry->
parsedPackageNameToString(array('package' =>
$role['package'], 'channel' => $role['channel']),
true));
}
$this->_stack->push('_mustInstallRole', 'error', $params, $msg);
}
}
}
$this->_invalidFileRole($file['attribs']['name'],
$dirname, $file['attribs']['role']);
}
}
if (!isset($file['attribs'])) {
continue;
}
$save = $file['attribs'];
if ($dirs) {
$save['name'] = $dirs . '/' . $save['name'];
}
unset($file['attribs']);
if (count($file) && $this->_curState != PEAR_VALIDATE_DOWNLOADING) { // has tasks
foreach ($file as $task => $value) {
if ($tagClass = $this->_pf->getTask($task)) {
if (!is_array($value) || !isset($value[0])) {
$value = array($value);
}
foreach ($value as $v) {
$ret = call_user_func(array($tagClass, 'validateXml'),
$this->_pf, $v, $this->_pf->_config, $save);
if (is_array($ret)) {
$this->_invalidTask($task, $ret, isset($save['name']) ?
$save['name'] : '');
}
}
} else {
if (isset($this->_packageInfo['usestask'])) {
$roles = $this->_packageInfo['usestask'];
if (!isset($roles[0])) {
$roles = array($roles);
}
foreach ($roles as $role) {
if ($role['task'] = $task) {
$msg = 'This package contains task "%task%" and requires ' .
'package "%package%" to be used';
if (isset($role['uri'])) {
$params = array('task' => $role['task'],
'package' => $role['uri']);
} else {
$params = array('task' => $role['task'],
'package' => $this->_pf->_registry->
parsedPackageNameToString(array('package' =>
$role['package'], 'channel' => $role['channel']),
true));
}
$this->_stack->push('_mustInstallTask', 'error',
$params, $msg);
}
}
}
$this->_unknownTask($task, $save['name']);
}
}
}
}
}
if (isset($list['ignore'])) {
if (!$allowignore) {
$this->_ignoreNotAllowed('ignore');
}
}
if (isset($list['install'])) {
if (!$allowignore) {
$this->_ignoreNotAllowed('install');
}
}
if (isset($list['file'])) {
if ($allowignore) {
$this->_fileNotAllowed('file');
}
}
if (isset($list['dir'])) {
if ($allowignore) {
$this->_fileNotAllowed('dir');
} else {
if (!isset($list['dir'][0])) {
$list['dir'] = array($list['dir']);
}
foreach ($list['dir'] as $dir) {
if (isset($dir['attribs']) && isset($dir['attribs']['name'])) {
if ($dir['attribs']['name'] == '/' ||
!isset($this->_packageInfo['contents']['dir']['dir'])) {
// always use nothing if the filelist has already been flattened
$newdirs = '';
} elseif ($dirs == '') {
$newdirs = $dir['attribs']['name'];
} else {
$newdirs = $dirs . '/' . $dir['attribs']['name'];
}
} else {
$newdirs = $dirs;
}
$this->_validateFilelist($dir, $allowignore, $newdirs);
}
}
}
}
 
function _validateRelease()
{
if (isset($this->_packageInfo['phprelease'])) {
$release = 'phprelease';
if (isset($this->_packageInfo['providesextension'])) {
$this->_cannotProvideExtension($release);
}
if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
$this->_cannotHaveSrcpackage($release);
}
$releases = $this->_packageInfo['phprelease'];
if (!is_array($releases)) {
return true;
}
if (!isset($releases[0])) {
$releases = array($releases);
}
foreach ($releases as $rel) {
$this->_stupidSchemaValidate(array(
'*installconditions',
'*filelist',
), $rel, '<phprelease>');
}
}
foreach (array('', 'zend') as $prefix) {
$releasetype = $prefix . 'extsrcrelease';
if (isset($this->_packageInfo[$releasetype])) {
$release = $releasetype;
if (!isset($this->_packageInfo['providesextension'])) {
$this->_mustProvideExtension($release);
}
if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
$this->_cannotHaveSrcpackage($release);
}
$releases = $this->_packageInfo[$releasetype];
if (!is_array($releases)) {
return true;
}
if (!isset($releases[0])) {
$releases = array($releases);
}
foreach ($releases as $rel) {
$this->_stupidSchemaValidate(array(
'*installconditions',
'*configureoption->name->prompt->?default',
'*binarypackage',
'*filelist',
), $rel, '<' . $releasetype . '>');
if (isset($rel['binarypackage'])) {
if (!is_array($rel['binarypackage']) || !isset($rel['binarypackage'][0])) {
$rel['binarypackage'] = array($rel['binarypackage']);
}
foreach ($rel['binarypackage'] as $bin) {
if (!is_string($bin)) {
$this->_binaryPackageMustBePackagename();
}
}
}
}
}
$releasetype = 'extbinrelease';
if (isset($this->_packageInfo[$releasetype])) {
$release = $releasetype;
if (!isset($this->_packageInfo['providesextension'])) {
$this->_mustProvideExtension($release);
}
if (isset($this->_packageInfo['channel']) &&
!isset($this->_packageInfo['srcpackage'])) {
$this->_mustSrcPackage($release);
}
if (isset($this->_packageInfo['uri']) && !isset($this->_packageInfo['srcuri'])) {
$this->_mustSrcuri($release);
}
$releases = $this->_packageInfo[$releasetype];
if (!is_array($releases)) {
return true;
}
if (!isset($releases[0])) {
$releases = array($releases);
}
foreach ($releases as $rel) {
$this->_stupidSchemaValidate(array(
'*installconditions',
'*filelist',
), $rel, '<' . $releasetype . '>');
}
}
}
if (isset($this->_packageInfo['bundle'])) {
$release = 'bundle';
if (isset($this->_packageInfo['providesextension'])) {
$this->_cannotProvideExtension($release);
}
if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
$this->_cannotHaveSrcpackage($release);
}
$releases = $this->_packageInfo['bundle'];
if (!is_array($releases) || !isset($releases[0])) {
$releases = array($releases);
}
foreach ($releases as $rel) {
$this->_stupidSchemaValidate(array(
'*installconditions',
'*filelist',
), $rel, '<bundle>');
}
}
foreach ($releases as $rel) {
if (is_array($rel) && array_key_exists('installconditions', $rel)) {
$this->_validateInstallConditions($rel['installconditions'],
"<$release><installconditions>");
}
if (is_array($rel) && array_key_exists('filelist', $rel)) {
if ($rel['filelist']) {
$this->_validateFilelist($rel['filelist'], true);
}
}
}
}
 
/**
* This is here to allow role extension through plugins
* @param string
*/
function _validateRole($role)
{
return in_array($role, PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType()));
}
 
function _pearVersionTooLow($version)
{
$this->_stack->push(__FUNCTION__, 'error',
array('version' => $version),
'This package.xml requires PEAR version %version% to parse properly, we are ' .
'version 1.5.1');
}
 
function _invalidTagOrder($oktags, $actual, $root)
{
$this->_stack->push(__FUNCTION__, 'error',
array('oktags' => $oktags, 'actual' => $actual, 'root' => $root),
'Invalid tag order in %root%, found <%actual%> expected one of "%oktags%"');
}
 
function _ignoreNotAllowed($type)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
'<%type%> is not allowed inside global <contents>, only inside ' .
'<phprelease>/<extbinrelease>/<zendextbinrelease>, use <dir> and <file> only');
}
 
function _fileNotAllowed($type)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
'<%type%> is not allowed inside release <filelist>, only inside ' .
'<contents>, use <ignore> and <install> only');
}
 
function _tagMissingAttribute($tag, $attr, $context)
{
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
'attribute' => $attr, 'context' => $context),
'tag <%tag%> in context "%context%" has no attribute "%attribute%"');
}
 
function _tagHasNoAttribs($tag, $context)
{
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
'context' => $context),
'tag <%tag%> has no attributes in context "%context%"');
}
 
function _invalidInternalStructure()
{
$this->_stack->push(__FUNCTION__, 'exception', array(),
'internal array was not generated by compatible parser, or extreme parser error, cannot continue');
}
 
function _invalidFileRole($file, $dir, $role)
{
$this->_stack->push(__FUNCTION__, 'error', array(
'file' => $file, 'dir' => $dir, 'role' => $role,
'roles' => PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())),
'File "%file%" in directory "%dir%" has invalid role "%role%", should be one of %roles%');
}
 
function _invalidFileName($file, $dir)
{
$this->_stack->push(__FUNCTION__, 'error', array(
'file' => $file),
'File "%file%" cannot begin with "."');
}
 
function _filelistCannotContainFile($filelist)
{
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
'<%tag%> can only contain <dir>, contains <file>. Use ' .
'<dir name="/"> as the first dir element');
}
 
function _filelistMustContainDir($filelist)
{
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
'<%tag%> must contain <dir>. Use <dir name="/"> as the ' .
'first dir element');
}
 
function _tagCannotBeEmpty($tag)
{
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
'<%tag%> cannot be empty (<%tag%/>)');
}
 
function _UrlOrChannel($type, $name)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
'name' => $name),
'Required dependency <%type%> "%name%" can have either url OR ' .
'channel attributes, and not both');
}
 
function _NoChannel($type, $name)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
'name' => $name),
'Required dependency <%type%> "%name%" must have either url OR ' .
'channel attributes');
}
 
function _UrlOrChannelGroup($type, $name, $group)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
'name' => $name, 'group' => $group),
'Group "%group%" dependency <%type%> "%name%" can have either url OR ' .
'channel attributes, and not both');
}
 
function _NoChannelGroup($type, $name, $group)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
'name' => $name, 'group' => $group),
'Group "%group%" dependency <%type%> "%name%" must have either url OR ' .
'channel attributes');
}
 
function _unknownChannel($channel)
{
$this->_stack->push(__FUNCTION__, 'error', array('channel' => $channel),
'Unknown channel "%channel%"');
}
 
function _noPackageVersion()
{
$this->_stack->push(__FUNCTION__, 'error', array(),
'package.xml <package> tag has no version attribute, or version is not 2.0');
}
 
function _NoBundledPackages()
{
$this->_stack->push(__FUNCTION__, 'error', array(),
'No <bundledpackage> tag was found in <contents>, required for bundle packages');
}
 
function _AtLeast2BundledPackages()
{
$this->_stack->push(__FUNCTION__, 'error', array(),
'At least 2 packages must be bundled in a bundle package');
}
 
function _ChannelOrUri($name)
{
$this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
'Bundled package "%name%" can have either a uri or a channel, not both');
}
 
function _noChildTag($child, $tag)
{
$this->_stack->push(__FUNCTION__, 'error', array('child' => $child, 'tag' => $tag),
'Tag <%tag%> is missing child tag <%child%>');
}
 
function _invalidVersion($type, $value)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value),
'Version type <%type%> is not a valid version (%value%)');
}
 
function _invalidState($type, $value)
{
$states = array('stable', 'beta', 'alpha', 'devel');
if ($type != 'api') {
$states[] = 'snapshot';
}
if (strtolower($value) == 'rc') {
$this->_stack->push(__FUNCTION__, 'error',
array('version' => $this->_packageInfo['version']['release']),
'RC is not a state, it is a version postfix, try %version%RC1, stability beta');
}
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value,
'types' => $states),
'Stability type <%type%> is not a valid stability (%value%), must be one of ' .
'%types%');
}
 
function _invalidTask($task, $ret, $file)
{
switch ($ret[0]) {
case PEAR_TASK_ERROR_MISSING_ATTRIB :
$info = array('attrib' => $ret[1], 'task' => $task, 'file' => $file);
$msg = 'task <%task%> is missing attribute "%attrib%" in file %file%';
break;
case PEAR_TASK_ERROR_NOATTRIBS :
$info = array('task' => $task, 'file' => $file);
$msg = 'task <%task%> has no attributes in file %file%';
break;
case PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE :
$info = array('attrib' => $ret[1], 'values' => $ret[3],
'was' => $ret[2], 'task' => $task, 'file' => $file);
$msg = 'task <%task%> attribute "%attrib%" has the wrong value "%was%" '.
'in file %file%, expecting one of "%values%"';
break;
case PEAR_TASK_ERROR_INVALID :
$info = array('reason' => $ret[1], 'task' => $task, 'file' => $file);
$msg = 'task <%task%> in file %file% is invalid because of "%reason%"';
break;
}
$this->_stack->push(__FUNCTION__, 'error', $info, $msg);
}
 
function _unknownTask($task, $file)
{
$this->_stack->push(__FUNCTION__, 'error', array('task' => $task, 'file' => $file),
'Unknown task "%task%" passed in file <file name="%file%">');
}
 
function _subpackageCannotProvideExtension($name)
{
$this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
'Subpackage dependency "%name%" cannot use <providesextension>, ' .
'only package dependencies can use this tag');
}
 
function _subpackagesCannotConflict($name)
{
$this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
'Subpackage dependency "%name%" cannot use <conflicts/>, ' .
'only package dependencies can use this tag');
}
 
function _cannotProvideExtension($release)
{
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
'<%release%> packages cannot use <providesextension>, only extbinrelease, extsrcrelease, zendextsrcrelease, and zendextbinrelease can provide a PHP extension');
}
 
function _mustProvideExtension($release)
{
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
'<%release%> packages must use <providesextension> to indicate which PHP extension is provided');
}
 
function _cannotHaveSrcpackage($release)
{
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
'<%release%> packages cannot specify a source code package, only extension binaries may use the <srcpackage> tag');
}
 
function _mustSrcPackage($release)
{
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
'<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcpackage>');
}
 
function _mustSrcuri($release)
{
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
'<extbinrelease>/<zendextbinrelease> packages must specify a source code package with <srcuri>');
}
 
function _uriDepsCannotHaveVersioning($type)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
'%type%: dependencies with a <uri> tag cannot have any versioning information');
}
 
function _conflictingDepsCannotHaveVersioning($type)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
'%type%: conflicting dependencies cannot have versioning info, use <exclude> to ' .
'exclude specific versions of a dependency');
}
 
function _DepchannelCannotBeUri($type)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
'%type%: channel cannot be __uri, this is a pseudo-channel reserved for uri ' .
'dependencies only');
}
 
function _bundledPackagesMustBeFilename()
{
$this->_stack->push(__FUNCTION__, 'error', array(),
'<bundledpackage> tags must contain only the filename of a package release ' .
'in the bundle');
}
 
function _binaryPackageMustBePackagename()
{
$this->_stack->push(__FUNCTION__, 'error', array(),
'<binarypackage> tags must contain the name of a package that is ' .
'a compiled version of this extsrc/zendextsrc package');
}
 
function _fileNotFound($file)
{
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
'File "%file%" in package.xml does not exist');
}
 
function _notInContents($file, $tag)
{
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file, 'tag' => $tag),
'<%tag% name="%file%"> is invalid, file is not in <contents>');
}
 
function _cannotValidateNoPathSet()
{
$this->_stack->push(__FUNCTION__, 'error', array(),
'Cannot validate files, no path to package file is set (use setPackageFile())');
}
 
function _usesroletaskMustHaveChannelOrUri($role, $tag)
{
$this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
'<%tag%> must contain either <uri>, or <channel> and <package>');
}
 
function _usesroletaskMustHavePackage($role, $tag)
{
$this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
'<%tag%> must contain <package>');
}
 
function _usesroletaskMustHaveRoleTask($tag, $type)
{
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'type' => $type),
'<%tag%> must contain <%type%> defining the %type% to be used');
}
 
function _cannotConflictWithAllOs($type)
{
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
'%tag% cannot conflict with all OSes');
}
 
function _invalidDepGroupName($name)
{
$this->_stack->push(__FUNCTION__, 'error', array('group' => $name),
'Invalid dependency group name "%name%"');
}
 
function _multipleToplevelDirNotAllowed()
{
$this->_stack->push(__FUNCTION__, 'error', array(),
'Multiple top-level <dir> tags are not allowed. Enclose them ' .
'in a <dir name="/">');
}
 
function _multipleInstallAs($file)
{
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
'Only one <install> tag is allowed for file "%file%"');
}
 
function _ignoreAndInstallAs($file)
{
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
'Cannot have both <ignore> and <install> tags for file "%file%"');
}
 
function _analyzeBundledPackages()
{
if (!$this->_isValid) {
return false;
}
if (!$this->_pf->getPackageType() == 'bundle') {
return false;
}
if (!isset($this->_pf->_packageFile)) {
return false;
}
$dir_prefix = dirname($this->_pf->_packageFile);
$log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
array('PEAR_Common', 'log');
$info = $this->_pf->getContents();
$info = $info['bundledpackage'];
if (!is_array($info)) {
$info = array($info);
}
$pkg = &new PEAR_PackageFile($this->_pf->_config);
foreach ($info as $package) {
if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $package)) {
$this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $package);
$this->_isValid = 0;
continue;
}
call_user_func_array($log, array(1, "Analyzing bundled package $package"));
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$ret = $pkg->fromAnyFile($dir_prefix . DIRECTORY_SEPARATOR . $package,
PEAR_VALIDATE_NORMAL);
PEAR::popErrorHandling();
if (PEAR::isError($ret)) {
call_user_func_array($log, array(0, "ERROR: package $package is not a valid " .
'package'));
$inf = $ret->getUserInfo();
if (is_array($inf)) {
foreach ($inf as $err) {
call_user_func_array($log, array(1, $err['message']));
}
}
return false;
}
}
return true;
}
 
function _analyzePhpFiles()
{
if (!$this->_isValid) {
return false;
}
if (!isset($this->_pf->_packageFile)) {
$this->_cannotValidateNoPathSet();
return false;
}
$dir_prefix = dirname($this->_pf->_packageFile);
$common = new PEAR_Common;
$log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
array(&$common, 'log');
$info = $this->_pf->getContents();
if (!$info || !isset($info['dir']['file'])) {
$this->_tagCannotBeEmpty('contents><dir');
return false;
}
$info = $info['dir']['file'];
if (isset($info['attribs'])) {
$info = array($info);
}
$provides = array();
foreach ($info as $fa) {
$fa = $fa['attribs'];
$file = $fa['name'];
if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) {
$this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $file);
$this->_isValid = 0;
continue;
}
if (in_array($fa['role'], PEAR_Installer_Role::getPhpRoles()) && $dir_prefix) {
call_user_func_array($log, array(1, "Analyzing $file"));
$srcinfo = $this->analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
if ($srcinfo) {
$provides = array_merge($provides, $this->_buildProvidesArray($srcinfo));
}
}
}
$this->_packageName = $pn = $this->_pf->getPackage();
$pnl = strlen($pn);
foreach ($provides as $key => $what) {
if (isset($what['explicit']) || !$what) {
// skip conformance checks if the provides entry is
// specified in the package.xml file
continue;
}
extract($what);
if ($type == 'class') {
if (!strncasecmp($name, $pn, $pnl)) {
continue;
}
$this->_stack->push(__FUNCTION__, 'warning',
array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
'in %file%: %type% "%name%" not prefixed with package name "%package%"');
} elseif ($type == 'function') {
if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
continue;
}
$this->_stack->push(__FUNCTION__, 'warning',
array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
'in %file%: %type% "%name%" not prefixed with package name "%package%"');
}
}
return $this->_isValid;
}
 
/**
* Analyze the source code of the given PHP file
*
* @param string Filename of the PHP file
* @param boolean whether to analyze $file as the file contents
* @return mixed
*/
function analyzeSourceCode($file, $string = false)
{
if (!function_exists("token_get_all")) {
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
'Parser error: token_get_all() function must exist to analyze source code, PHP may have been compiled with --disable-tokenizer');
return false;
}
if (!defined('T_DOC_COMMENT')) {
define('T_DOC_COMMENT', T_COMMENT);
}
if (!defined('T_INTERFACE')) {
define('T_INTERFACE', -1);
}
if (!defined('T_IMPLEMENTS')) {
define('T_IMPLEMENTS', -1);
}
if ($string) {
$contents = $file;
} else {
if (!$fp = @fopen($file, "r")) {
return false;
}
fclose($fp);
$contents = file_get_contents($file);
}
$tokens = token_get_all($contents);
/*
for ($i = 0; $i < sizeof($tokens); $i++) {
@list($token, $data) = $tokens[$i];
if (is_string($token)) {
var_dump($token);
} else {
print token_name($token) . ' ';
var_dump(rtrim($data));
}
}
*/
$look_for = 0;
$paren_level = 0;
$bracket_level = 0;
$brace_level = 0;
$lastphpdoc = '';
$current_class = '';
$current_interface = '';
$current_class_level = -1;
$current_function = '';
$current_function_level = -1;
$declared_classes = array();
$declared_interfaces = array();
$declared_functions = array();
$declared_methods = array();
$used_classes = array();
$used_functions = array();
$extends = array();
$implements = array();
$nodeps = array();
$inquote = false;
$interface = false;
for ($i = 0; $i < sizeof($tokens); $i++) {
if (is_array($tokens[$i])) {
list($token, $data) = $tokens[$i];
} else {
$token = $tokens[$i];
$data = '';
}
if ($inquote) {
if ($token != '"' && $token != T_END_HEREDOC) {
continue;
} else {
$inquote = false;
continue;
}
}
switch ($token) {
case T_WHITESPACE :
continue;
case ';':
if ($interface) {
$current_function = '';
$current_function_level = -1;
}
break;
case '"':
case T_START_HEREDOC:
$inquote = true;
break;
case T_CURLY_OPEN:
case T_DOLLAR_OPEN_CURLY_BRACES:
case '{': $brace_level++; continue 2;
case '}':
$brace_level--;
if ($current_class_level == $brace_level) {
$current_class = '';
$current_class_level = -1;
}
if ($current_function_level == $brace_level) {
$current_function = '';
$current_function_level = -1;
}
continue 2;
case '[': $bracket_level++; continue 2;
case ']': $bracket_level--; continue 2;
case '(': $paren_level++; continue 2;
case ')': $paren_level--; continue 2;
case T_INTERFACE:
$interface = true;
case T_CLASS:
if (($current_class_level != -1) || ($current_function_level != -1)) {
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
'Parser error: invalid PHP found in file "%file%"');
return false;
}
case T_FUNCTION:
case T_NEW:
case T_EXTENDS:
case T_IMPLEMENTS:
$look_for = $token;
continue 2;
case T_STRING:
if (version_compare(zend_version(), '2.0', '<')) {
if (in_array(strtolower($data),
array('public', 'private', 'protected', 'abstract',
'interface', 'implements', 'throw')
)) {
$this->_stack->push(__FUNCTION__, 'warning', array(
'file' => $file),
'Error, PHP5 token encountered in %file%,' .
' analysis should be in PHP5');
}
}
if ($look_for == T_CLASS) {
$current_class = $data;
$current_class_level = $brace_level;
$declared_classes[] = $current_class;
} elseif ($look_for == T_INTERFACE) {
$current_interface = $data;
$current_class_level = $brace_level;
$declared_interfaces[] = $current_interface;
} elseif ($look_for == T_IMPLEMENTS) {
$implements[$current_class] = $data;
} elseif ($look_for == T_EXTENDS) {
$extends[$current_class] = $data;
} elseif ($look_for == T_FUNCTION) {
if ($current_class) {
$current_function = "$current_class::$data";
$declared_methods[$current_class][] = $data;
} elseif ($current_interface) {
$current_function = "$current_interface::$data";
$declared_methods[$current_interface][] = $data;
} else {
$current_function = $data;
$declared_functions[] = $current_function;
}
$current_function_level = $brace_level;
$m = array();
} elseif ($look_for == T_NEW) {
$used_classes[$data] = true;
}
$look_for = 0;
continue 2;
case T_VARIABLE:
$look_for = 0;
continue 2;
case T_DOC_COMMENT:
case T_COMMENT:
if (preg_match('!^/\*\*\s!', $data)) {
$lastphpdoc = $data;
if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
$nodeps = array_merge($nodeps, $m[1]);
}
}
continue 2;
case T_DOUBLE_COLON:
if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) {
$this->_stack->push(__FUNCTION__, 'warning', array('file' => $file),
'Parser error: invalid PHP found in file "%file%"');
return false;
}
$class = $tokens[$i - 1][1];
if (strtolower($class) != 'parent') {
$used_classes[$class] = true;
}
continue 2;
}
}
return array(
"source_file" => $file,
"declared_classes" => $declared_classes,
"declared_interfaces" => $declared_interfaces,
"declared_methods" => $declared_methods,
"declared_functions" => $declared_functions,
"used_classes" => array_diff(array_keys($used_classes), $nodeps),
"inheritance" => $extends,
"implements" => $implements,
);
}
 
/**
* Build a "provides" array from data returned by
* analyzeSourceCode(). The format of the built array is like
* this:
*
* array(
* 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
* ...
* )
*
*
* @param array $srcinfo array with information about a source file
* as returned by the analyzeSourceCode() method.
*
* @return void
*
* @access private
*
*/
function _buildProvidesArray($srcinfo)
{
if (!$this->_isValid) {
return array();
}
$providesret = array();
$file = basename($srcinfo['source_file']);
$pn = $this->_pf->getPackage();
$pnl = strlen($pn);
foreach ($srcinfo['declared_classes'] as $class) {
$key = "class;$class";
if (isset($providesret[$key])) {
continue;
}
$providesret[$key] =
array('file'=> $file, 'type' => 'class', 'name' => $class);
if (isset($srcinfo['inheritance'][$class])) {
$providesret[$key]['extends'] =
$srcinfo['inheritance'][$class];
}
}
foreach ($srcinfo['declared_methods'] as $class => $methods) {
foreach ($methods as $method) {
$function = "$class::$method";
$key = "function;$function";
if ($method{0} == '_' || !strcasecmp($method, $class) ||
isset($providesret[$key])) {
continue;
}
$providesret[$key] =
array('file'=> $file, 'type' => 'function', 'name' => $function);
}
}
 
foreach ($srcinfo['declared_functions'] as $function) {
$key = "function;$function";
if ($function{0} == '_' || isset($providesret[$key])) {
continue;
}
if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
$warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
}
$providesret[$key] =
array('file'=> $file, 'type' => 'function', 'name' => $function);
}
return $providesret;
}
}
?>
/trunk/bibliotheque/pear/PEAR/PackageFile/v2/rw.php
New file
0,0 → 1,1601
<?php
/**
* PEAR_PackageFile_v2, package.xml version 2.0, read/write version
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: rw.php,v 1.19 2006/10/30 04:12:02 cellog Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a8
*/
/**
* For base class
*/
require_once 'PEAR/PackageFile/v2.php';
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.5.1
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a8
*/
class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
{
/**
* @param string Extension name
* @return bool success of operation
*/
function setProvidesExtension($extension)
{
if (in_array($this->getPackageType(),
array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
if (!isset($this->_packageInfo['providesextension'])) {
// ensure that the channel tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
'bundle', 'changelog'),
$extension, 'providesextension');
}
$this->_packageInfo['providesextension'] = $extension;
return true;
}
return false;
}
 
function setPackage($package)
{
$this->_isValid = 0;
if (!isset($this->_packageInfo['attribs'])) {
$this->_packageInfo = array_merge(array('attribs' => array(
'version' => '2.0',
'xmlns' => 'http://pear.php.net/dtd/package-2.0',
'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
http://pear.php.net/dtd/tasks-1.0.xsd
http://pear.php.net/dtd/package-2.0
http://pear.php.net/dtd/package-2.0.xsd',
)), $this->_packageInfo);
}
if (!isset($this->_packageInfo['name'])) {
return $this->_packageInfo = array_merge(array('name' => $package),
$this->_packageInfo);
}
$this->_packageInfo['name'] = $package;
}
 
/**
* set this as a package.xml version 2.1
* @access private
*/
function _setPackageVersion2_1()
{
$info = array(
'version' => '2.1',
'xmlns' => 'http://pear.php.net/dtd/package-2.1',
'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
http://pear.php.net/dtd/tasks-1.0.xsd
http://pear.php.net/dtd/package-2.1
http://pear.php.net/dtd/package-2.1.xsd',
);
if (!isset($this->_packageInfo['attribs'])) {
$this->_packageInfo = array_merge(array('attribs' => $info), $this->_packageInfo);
} else {
$this->_packageInfo['attribs'] = $info;
}
}
 
function setUri($uri)
{
unset($this->_packageInfo['channel']);
$this->_isValid = 0;
if (!isset($this->_packageInfo['uri'])) {
// ensure that the uri tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('extends', 'summary', 'description', 'lead',
'developer', 'contributor', 'helper', 'date', 'time', 'version',
'stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'), $uri, 'uri');
}
$this->_packageInfo['uri'] = $uri;
}
 
function setChannel($channel)
{
unset($this->_packageInfo['uri']);
$this->_isValid = 0;
if (!isset($this->_packageInfo['channel'])) {
// ensure that the channel tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('extends', 'summary', 'description', 'lead',
'developer', 'contributor', 'helper', 'date', 'time', 'version',
'stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'), $channel, 'channel');
}
$this->_packageInfo['channel'] = $channel;
}
 
function setExtends($extends)
{
$this->_isValid = 0;
if (!isset($this->_packageInfo['extends'])) {
// ensure that the extends tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('summary', 'description', 'lead',
'developer', 'contributor', 'helper', 'date', 'time', 'version',
'stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'), $extends, 'extends');
}
$this->_packageInfo['extends'] = $extends;
}
 
function setSummary($summary)
{
$this->_isValid = 0;
if (!isset($this->_packageInfo['summary'])) {
// ensure that the summary tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('description', 'lead',
'developer', 'contributor', 'helper', 'date', 'time', 'version',
'stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'), $summary, 'summary');
}
$this->_packageInfo['summary'] = $summary;
}
 
function setDescription($desc)
{
$this->_isValid = 0;
if (!isset($this->_packageInfo['description'])) {
// ensure that the description tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('lead',
'developer', 'contributor', 'helper', 'date', 'time', 'version',
'stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'), $desc, 'description');
}
$this->_packageInfo['description'] = $desc;
}
 
/**
* Adds a new maintainer - no checking of duplicates is performed, use
* updatemaintainer for that purpose.
*/
function addMaintainer($role, $handle, $name, $email, $active = 'yes')
{
if (!in_array($role, array('lead', 'developer', 'contributor', 'helper'))) {
return false;
}
if (isset($this->_packageInfo[$role])) {
if (!isset($this->_packageInfo[$role][0])) {
$this->_packageInfo[$role] = array($this->_packageInfo[$role]);
}
$this->_packageInfo[$role][] =
array(
'name' => $name,
'user' => $handle,
'email' => $email,
'active' => $active,
);
} else {
$testarr = array('lead',
'developer', 'contributor', 'helper', 'date', 'time', 'version',
'stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog');
foreach (array('lead', 'developer', 'contributor', 'helper') as $testrole) {
array_shift($testarr);
if ($role == $testrole) {
break;
}
}
if (!isset($this->_packageInfo[$role])) {
// ensure that the extends tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, $testarr,
array(), $role);
}
$this->_packageInfo[$role] =
array(
'name' => $name,
'user' => $handle,
'email' => $email,
'active' => $active,
);
}
$this->_isValid = 0;
}
 
function updateMaintainer($newrole, $handle, $name, $email, $active = 'yes')
{
$found = false;
foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
if (!isset($this->_packageInfo[$role])) {
continue;
}
$info = $this->_packageInfo[$role];
if (!isset($info[0])) {
if ($info['user'] == $handle) {
$found = true;
break;
}
}
foreach ($info as $i => $maintainer) {
if ($maintainer['user'] == $handle) {
$found = $i;
break 2;
}
}
}
if ($found === false) {
return $this->addMaintainer($newrole, $handle, $name, $email, $active);
}
if ($found !== false) {
if ($found === true) {
unset($this->_packageInfo[$role]);
} else {
unset($this->_packageInfo[$role][$found]);
$this->_packageInfo[$role] = array_values($this->_packageInfo[$role]);
}
}
$this->addMaintainer($newrole, $handle, $name, $email, $active);
$this->_isValid = 0;
}
 
function deleteMaintainer($handle)
{
$found = false;
foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
if (!isset($this->_packageInfo[$role])) {
continue;
}
if (!isset($this->_packageInfo[$role][0])) {
$this->_packageInfo[$role] = array($this->_packageInfo[$role]);
}
foreach ($this->_packageInfo[$role] as $i => $maintainer) {
if ($maintainer['user'] == $handle) {
$found = $i;
break;
}
}
if ($found !== false) {
unset($this->_packageInfo[$role][$found]);
if (!count($this->_packageInfo[$role]) && $role == 'lead') {
$this->_isValid = 0;
}
if (!count($this->_packageInfo[$role])) {
unset($this->_packageInfo[$role]);
return true;
}
$this->_packageInfo[$role] =
array_values($this->_packageInfo[$role]);
if (count($this->_packageInfo[$role]) == 1) {
$this->_packageInfo[$role] = $this->_packageInfo[$role][0];
}
return true;
}
if (count($this->_packageInfo[$role]) == 1) {
$this->_packageInfo[$role] = $this->_packageInfo[$role][0];
}
}
return false;
}
 
function setReleaseVersion($version)
{
if (isset($this->_packageInfo['version']) &&
isset($this->_packageInfo['version']['release'])) {
unset($this->_packageInfo['version']['release']);
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'),
'release' => array('api')));
$this->_isValid = 0;
}
 
function setAPIVersion($version)
{
if (isset($this->_packageInfo['version']) &&
isset($this->_packageInfo['version']['api'])) {
unset($this->_packageInfo['version']['api']);
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'),
'api' => array()));
$this->_isValid = 0;
}
 
/**
* snapshot|devel|alpha|beta|stable
*/
function setReleaseStability($state)
{
if (isset($this->_packageInfo['stability']) &&
isset($this->_packageInfo['stability']['release'])) {
unset($this->_packageInfo['stability']['release']);
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
'stability' => array('license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'),
'release' => array('api')));
$this->_isValid = 0;
}
 
/**
* @param devel|alpha|beta|stable
*/
function setAPIStability($state)
{
if (isset($this->_packageInfo['stability']) &&
isset($this->_packageInfo['stability']['api'])) {
unset($this->_packageInfo['stability']['api']);
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
'stability' => array('license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'),
'api' => array()));
$this->_isValid = 0;
}
 
function setLicense($license, $uri = false, $filesource = false)
{
if (!isset($this->_packageInfo['license'])) {
// ensure that the license tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'), 0, 'license');
}
if ($uri || $filesource) {
$attribs = array();
if ($uri) {
$attribs['uri'] = $uri;
}
$uri = true; // for test below
if ($filesource) {
$attribs['filesource'] = $filesource;
}
}
$license = $uri ? array('attribs' => $attribs, '_content' => $license) : $license;
$this->_packageInfo['license'] = $license;
$this->_isValid = 0;
}
 
function setNotes($notes)
{
$this->_isValid = 0;
if (!isset($this->_packageInfo['notes'])) {
// ensure that the notes tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'), $notes, 'notes');
}
$this->_packageInfo['notes'] = $notes;
}
 
/**
* This is only used at install-time, after all serialization
* is over.
* @param string file name
* @param string installed path
*/
function setInstalledAs($file, $path)
{
if ($path) {
return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
}
unset($this->_packageInfo['filelist'][$file]['installed_as']);
}
 
/**
* This is only used at install-time, after all serialization
* is over.
*/
function installedFile($file, $atts)
{
if (isset($this->_packageInfo['filelist'][$file])) {
$this->_packageInfo['filelist'][$file] =
array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']);
} else {
$this->_packageInfo['filelist'][$file] = $atts['attribs'];
}
}
 
/**
* Reset the listing of package contents
* @param string base installation dir for the whole package, if any
*/
function clearContents($baseinstall = false)
{
$this->_filesValid = false;
$this->_isValid = 0;
if (!isset($this->_packageInfo['contents'])) {
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
'bundle', 'changelog'), array(), 'contents');
}
if ($this->getPackageType() != 'bundle') {
$this->_packageInfo['contents'] =
array('dir' => array('attribs' => array('name' => '/')));
if ($baseinstall) {
$this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'] = $baseinstall;
}
}
}
 
/**
* @param string relative path of the bundled package.
*/
function addBundledPackage($path)
{
if ($this->getPackageType() != 'bundle') {
return false;
}
$this->_filesValid = false;
$this->_isValid = 0;
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $path, array(
'contents' => array('compatible', 'dependencies', 'providesextension',
'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
'bundle', 'changelog'),
'bundledpackage' => array()));
}
 
/**
* @param string file name
* @param PEAR_Task_Common a read/write task
*/
function addTaskToFile($filename, $task)
{
if (!method_exists($task, 'getXml')) {
return false;
}
if (!method_exists($task, 'getName')) {
return false;
}
if (!method_exists($task, 'validate')) {
return false;
}
if (!$task->validate()) {
return false;
}
if (!isset($this->_packageInfo['contents']['dir']['file'])) {
return false;
}
$this->getTasksNs(); // discover the tasks namespace if not done already
$files = $this->_packageInfo['contents']['dir']['file'];
if (!isset($files[0])) {
$files = array($files);
$ind = false;
} else {
$ind = true;
}
foreach ($files as $i => $file) {
if (isset($file['attribs'])) {
if ($file['attribs']['name'] == $filename) {
if ($ind) {
$t = isset($this->_packageInfo['contents']['dir']['file'][$i]
['attribs'][$this->_tasksNs .
':' . $task->getName()]) ?
$this->_packageInfo['contents']['dir']['file'][$i]
['attribs'][$this->_tasksNs .
':' . $task->getName()] : false;
if ($t && !isset($t[0])) {
$this->_packageInfo['contents']['dir']['file'][$i]
[$this->_tasksNs . ':' . $task->getName()] = array($t);
}
$this->_packageInfo['contents']['dir']['file'][$i][$this->_tasksNs .
':' . $task->getName()][] = $task->getXml();
} else {
$t = isset($this->_packageInfo['contents']['dir']['file']
['attribs'][$this->_tasksNs .
':' . $task->getName()]) ? $this->_packageInfo['contents']['dir']['file']
['attribs'][$this->_tasksNs .
':' . $task->getName()] : false;
if ($t && !isset($t[0])) {
$this->_packageInfo['contents']['dir']['file']
[$this->_tasksNs . ':' . $task->getName()] = array($t);
}
$this->_packageInfo['contents']['dir']['file'][$this->_tasksNs .
':' . $task->getName()][] = $task->getXml();
}
return true;
}
}
}
return false;
}
 
/**
* @param string path to the file
* @param string filename
* @param array extra attributes
*/
function addFile($dir, $file, $attrs)
{
if ($this->getPackageType() == 'bundle') {
return false;
}
$this->_filesValid = false;
$this->_isValid = 0;
$dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir);
if ($dir == '/' || $dir == '') {
$dir = '';
} else {
$dir .= '/';
}
$attrs['name'] = $dir . $file;
if (!isset($this->_packageInfo['contents'])) {
// ensure that the contents tag is set up
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
'bundle', 'changelog'), array(), 'contents');
}
if (isset($this->_packageInfo['contents']['dir']['file'])) {
if (!isset($this->_packageInfo['contents']['dir']['file'][0])) {
$this->_packageInfo['contents']['dir']['file'] =
array($this->_packageInfo['contents']['dir']['file']);
}
$this->_packageInfo['contents']['dir']['file'][]['attribs'] = $attrs;
} else {
$this->_packageInfo['contents']['dir']['file']['attribs'] = $attrs;
}
}
 
/**
* @param string Dependent package name
* @param string Dependent package's channel name
* @param string minimum version of specified package that this release is guaranteed to be
* compatible with
* @param string maximum version of specified package that this release is guaranteed to be
* compatible with
* @param string versions of specified package that this release is not compatible with
*/
function addCompatiblePackage($name, $channel, $min, $max, $exclude = false)
{
$this->_isValid = 0;
$set = array(
'name' => $name,
'channel' => $channel,
'min' => $min,
'max' => $max,
);
if ($exclude) {
$set['exclude'] = $exclude;
}
$this->_isValid = 0;
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
'compatible' => array('dependencies', 'providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
));
}
 
/**
* Removes the <usesrole> tag entirely
*/
function resetUsesrole()
{
if (isset($this->_packageInfo['usesrole'])) {
unset($this->_packageInfo['usesrole']);
}
}
 
/**
* @param string
* @param string package name or uri
* @param string channel name if non-uri
*/
function addUsesrole($role, $packageOrUri, $channel = false) {
$set = array('role' => $role);
if ($channel) {
$set['package'] = $packageOrUri;
$set['channel'] = $channel;
} else {
$set['uri'] = $packageOrUri;
}
$this->_isValid = 0;
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
'usesrole' => array('usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
));
}
 
/**
* Removes the <usestask> tag entirely
*/
function resetUsestask()
{
if (isset($this->_packageInfo['usestask'])) {
unset($this->_packageInfo['usestask']);
}
}
 
 
/**
* @param string
* @param string package name or uri
* @param string channel name if non-uri
*/
function addUsestask($task, $packageOrUri, $channel = false) {
$set = array('task' => $task);
if ($channel) {
$set['package'] = $packageOrUri;
$set['channel'] = $channel;
} else {
$set['uri'] = $packageOrUri;
}
$this->_isValid = 0;
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
'usestask' => array('srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
));
}
 
/**
* Remove all compatible tags
*/
function clearCompatible()
{
unset($this->_packageInfo['compatible']);
}
 
/**
* Reset dependencies prior to adding new ones
*/
function clearDeps()
{
if (!isset($this->_packageInfo['dependencies'])) {
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(),
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')));
}
$this->_packageInfo['dependencies'] = array();
}
 
/**
* @param string minimum PHP version allowed
* @param string maximum PHP version allowed
* @param array $exclude incompatible PHP versions
*/
function setPhpDep($min, $max = false, $exclude = false)
{
$this->_isValid = 0;
$dep =
array(
'min' => $min,
);
if ($max) {
$dep['max'] = $max;
}
if ($exclude) {
if (count($exclude) == 1) {
$exclude = $exclude[0];
}
$dep['exclude'] = $exclude;
}
if (isset($this->_packageInfo['dependencies']['required']['php'])) {
$this->_stack->push(__FUNCTION__, 'warning', array('dep' =>
$this->_packageInfo['dependencies']['required']['php']),
'warning: PHP dependency already exists, overwriting');
unset($this->_packageInfo['dependencies']['required']['php']);
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
'required' => array('optional', 'group'),
'php' => array('pearinstaller', 'package', 'subpackage', 'extension', 'os', 'arch')
));
return true;
}
 
/**
* @param string minimum allowed PEAR installer version
* @param string maximum allowed PEAR installer version
* @param string recommended PEAR installer version
* @param array incompatible version of the PEAR installer
*/
function setPearinstallerDep($min, $max = false, $recommended = false, $exclude = false)
{
$this->_isValid = 0;
$dep =
array(
'min' => $min,
);
if ($max) {
$dep['max'] = $max;
}
if ($recommended) {
$dep['recommended'] = $recommended;
}
if ($exclude) {
if (count($exclude) == 1) {
$exclude = $exclude[0];
}
$dep['exclude'] = $exclude;
}
if (isset($this->_packageInfo['dependencies']['required']['pearinstaller'])) {
$this->_stack->push(__FUNCTION__, 'warning', array('dep' =>
$this->_packageInfo['dependencies']['required']['pearinstaller']),
'warning: PEAR Installer dependency already exists, overwriting');
unset($this->_packageInfo['dependencies']['required']['pearinstaller']);
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
'required' => array('optional', 'group'),
'pearinstaller' => array('package', 'subpackage', 'extension', 'os', 'arch')
));
}
 
/**
* Mark a package as conflicting with this package
* @param string package name
* @param string package channel
* @param string extension this package provides, if any
* @param string|false minimum version required
* @param string|false maximum version allowed
* @param array|false versions to exclude from installation
*/
function addConflictingPackageDepWithChannel($name, $channel,
$providesextension = false, $min = false, $max = false, $exclude = false)
{
$this->_isValid = 0;
$dep = $this->_constructDep($name, $channel, false, $min, $max, false,
$exclude, $providesextension, false, true);
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
'required' => array('optional', 'group'),
'package' => array('subpackage', 'extension', 'os', 'arch')
));
}
 
/**
* Mark a package as conflicting with this package
* @param string package name
* @param string package channel
* @param string extension this package provides, if any
*/
function addConflictingPackageDepWithUri($name, $uri, $providesextension = false)
{
$this->_isValid = 0;
$dep =
array(
'name' => $name,
'uri' => $uri,
'conflicts' => '',
);
if ($providesextension) {
$dep['providesextension'] = $providesextension;
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
'required' => array('optional', 'group'),
'package' => array('subpackage', 'extension', 'os', 'arch')
));
}
 
function addDependencyGroup($name, $hint)
{
$this->_isValid = 0;
$this->_packageInfo = $this->_mergeTag($this->_packageInfo,
array('attribs' => array('name' => $name, 'hint' => $hint)),
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
'group' => array(),
));
}
 
/**
* @param string package name
* @param string|false channel name, false if this is a uri
* @param string|false uri name, false if this is a channel
* @param string|false minimum version required
* @param string|false maximum version allowed
* @param string|false recommended installation version
* @param array|false versions to exclude from installation
* @param string extension this package provides, if any
* @param bool if true, tells the installer to ignore the default optional dependency group
* when installing this package
* @param bool if true, tells the installer to negate this dependency (conflicts)
* @return array
* @access private
*/
function _constructDep($name, $channel, $uri, $min, $max, $recommended, $exclude,
$providesextension = false, $nodefault = false,
$conflicts = false)
{
$dep =
array(
'name' => $name,
);
if ($channel) {
$dep['channel'] = $channel;
} elseif ($uri) {
$dep['uri'] = $uri;
}
if ($min) {
$dep['min'] = $min;
}
if ($max) {
$dep['max'] = $max;
}
if ($recommended) {
$dep['recommended'] = $recommended;
}
if ($exclude) {
if (is_array($exclude) && count($exclude) == 1) {
$exclude = $exclude[0];
}
$dep['exclude'] = $exclude;
}
if ($conflicts) {
$dep['conflicts'] = '';
}
if ($nodefault) {
$dep['nodefault'] = '';
}
if ($providesextension) {
$dep['providesextension'] = $providesextension;
}
return $dep;
}
 
/**
* @param package|subpackage
* @param string group name
* @param string package name
* @param string package channel
* @param string minimum version
* @param string maximum version
* @param string recommended version
* @param array|false optional excluded versions
* @param string extension this package provides, if any
* @param bool if true, tells the installer to ignore the default optional dependency group
* when installing this package
* @return bool false if the dependency group has not been initialized with
* {@link addDependencyGroup()}, or a subpackage is added with
* a providesextension
*/
function addGroupPackageDepWithChannel($type, $groupname, $name, $channel, $min = false,
$max = false, $recommended = false, $exclude = false,
$providesextension = false, $nodefault = false)
{
if ($type == 'subpackage' && $providesextension) {
return false; // subpackages must be php packages
}
$dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
$providesextension, $nodefault);
return $this->_addGroupDependency($type, $dep, $groupname);
}
 
/**
* @param package|subpackage
* @param string group name
* @param string package name
* @param string package uri
* @param string extension this package provides, if any
* @param bool if true, tells the installer to ignore the default optional dependency group
* when installing this package
* @return bool false if the dependency group has not been initialized with
* {@link addDependencyGroup()}
*/
function addGroupPackageDepWithURI($type, $groupname, $name, $uri, $providesextension = false,
$nodefault = false)
{
if ($type == 'subpackage' && $providesextension) {
return false; // subpackages must be php packages
}
$dep = $this->_constructDep($name, false, $uri, false, false, false, false,
$providesextension, $nodefault);
return $this->_addGroupDependency($type, $dep, $groupname);
}
 
/**
* @param string group name (must be pre-existing)
* @param string extension name
* @param string minimum version allowed
* @param string maximum version allowed
* @param string recommended version
* @param array incompatible versions
*/
function addGroupExtensionDep($groupname, $name, $min = false, $max = false,
$recommended = false, $exclude = false)
{
$this->_isValid = 0;
$dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
return $this->_addGroupDependency('extension', $dep, $groupname);
}
 
/**
* @param package|subpackage|extension
* @param array dependency contents
* @param string name of the dependency group to add this to
* @return boolean
* @access private
*/
function _addGroupDependency($type, $dep, $groupname)
{
$arr = array('subpackage', 'extension');
if ($type != 'package') {
array_shift($arr);
}
if ($type == 'extension') {
array_shift($arr);
}
if (!isset($this->_packageInfo['dependencies']['group'])) {
return false;
} else {
if (!isset($this->_packageInfo['dependencies']['group'][0])) {
if ($this->_packageInfo['dependencies']['group']['attribs']['name'] == $groupname) {
$this->_packageInfo['dependencies']['group'] = $this->_mergeTag(
$this->_packageInfo['dependencies']['group'], $dep,
array(
$type => $arr
));
$this->_isValid = 0;
return true;
} else {
return false;
}
} else {
foreach ($this->_packageInfo['dependencies']['group'] as $i => $group) {
if ($group['attribs']['name'] == $groupname) {
$this->_packageInfo['dependencies']['group'][$i] = $this->_mergeTag(
$this->_packageInfo['dependencies']['group'][$i], $dep,
array(
$type => $arr
));
$this->_isValid = 0;
return true;
}
}
return false;
}
}
}
 
/**
* @param optional|required
* @param string package name
* @param string package channel
* @param string minimum version
* @param string maximum version
* @param string recommended version
* @param string extension this package provides, if any
* @param bool if true, tells the installer to ignore the default optional dependency group
* when installing this package
* @param array|false optional excluded versions
*/
function addPackageDepWithChannel($type, $name, $channel, $min = false, $max = false,
$recommended = false, $exclude = false,
$providesextension = false, $nodefault = false)
{
if (!in_array($type, array('optional', 'required'), true)) {
$type = 'required';
}
$this->_isValid = 0;
$arr = array('optional', 'group');
if ($type != 'required') {
array_shift($arr);
}
$dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
$providesextension, $nodefault);
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
$type => $arr,
'package' => array('subpackage', 'extension', 'os', 'arch')
));
}
 
/**
* @param optional|required
* @param string name of the package
* @param string uri of the package
* @param string extension this package provides, if any
* @param bool if true, tells the installer to ignore the default optional dependency group
* when installing this package
*/
function addPackageDepWithUri($type, $name, $uri, $providesextension = false,
$nodefault = false)
{
$this->_isValid = 0;
$arr = array('optional', 'group');
if ($type != 'required') {
array_shift($arr);
}
$dep = $this->_constructDep($name, false, $uri, false, false, false, false,
$providesextension, $nodefault);
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
$type => $arr,
'package' => array('subpackage', 'extension', 'os', 'arch')
));
}
 
/**
* @param optional|required optional, required
* @param string package name
* @param string package channel
* @param string minimum version
* @param string maximum version
* @param string recommended version
* @param array incompatible versions
* @param bool if true, tells the installer to ignore the default optional dependency group
* when installing this package
*/
function addSubpackageDepWithChannel($type, $name, $channel, $min = false, $max = false,
$recommended = false, $exclude = false,
$nodefault = false)
{
$this->_isValid = 0;
$arr = array('optional', 'group');
if ($type != 'required') {
array_shift($arr);
}
$dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
$nodefault);
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
$type => $arr,
'subpackage' => array('extension', 'os', 'arch')
));
}
 
/**
* @param optional|required optional, required
* @param string package name
* @param string package uri for download
* @param bool if true, tells the installer to ignore the default optional dependency group
* when installing this package
*/
function addSubpackageDepWithUri($type, $name, $uri, $nodefault = false)
{
$this->_isValid = 0;
$arr = array('optional', 'group');
if ($type != 'required') {
array_shift($arr);
}
$dep = $this->_constructDep($name, false, $uri, false, false, false, false, $nodefault);
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
$type => $arr,
'subpackage' => array('extension', 'os', 'arch')
));
}
 
/**
* @param optional|required optional, required
* @param string extension name
* @param string minimum version
* @param string maximum version
* @param string recommended version
* @param array incompatible versions
*/
function addExtensionDep($type, $name, $min = false, $max = false, $recommended = false,
$exclude = false)
{
$this->_isValid = 0;
$arr = array('optional', 'group');
if ($type != 'required') {
array_shift($arr);
}
$dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
$type => $arr,
'extension' => array('os', 'arch')
));
}
 
/**
* @param string Operating system name
* @param boolean true if this package cannot be installed on this OS
*/
function addOsDep($name, $conflicts = false)
{
$this->_isValid = 0;
$dep = array('name' => $name);
if ($conflicts) {
$dep['conflicts'] = '';
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
'required' => array('optional', 'group'),
'os' => array('arch')
));
}
 
/**
* @param string Architecture matching pattern
* @param boolean true if this package cannot be installed on this architecture
*/
function addArchDep($pattern, $conflicts = false)
{
$this->_isValid = 0;
$dep = array('pattern' => $pattern);
if ($conflicts) {
$dep['conflicts'] = '';
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
'required' => array('optional', 'group'),
'arch' => array()
));
}
 
/**
* Set the kind of package, and erase all release tags
*
* - a php package is a PEAR-style package
* - an extbin package is a PECL-style extension binary
* - an extsrc package is a PECL-style source for a binary
* - an zendextbin package is a PECL-style zend extension binary
* - an zendextsrc package is a PECL-style source for a zend extension binary
* - a bundle package is a collection of other pre-packaged packages
* @param php|extbin|extsrc|zendextsrc|zendextbin|bundle
* @return bool success
*/
function setPackageType($type)
{
$this->_isValid = 0;
if (!in_array($type, array('php', 'extbin', 'extsrc', 'zendextsrc',
'zendextbin', 'bundle'))) {
return false;
}
if (in_array($type, array('zendextsrc', 'zendextbin'))) {
$this->_setPackageVersion2_1();
}
if ($type != 'bundle') {
$type .= 'release';
}
foreach (array('phprelease', 'extbinrelease', 'extsrcrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle') as $test) {
unset($this->_packageInfo[$test]);
}
if (!isset($this->_packageInfo[$type])) {
// ensure that the release tag is set up
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('changelog'),
array(), $type);
}
$this->_packageInfo[$type] = array();
return true;
}
 
/**
* @return bool true if package type is set up
*/
function addRelease()
{
if ($type = $this->getPackageType()) {
if ($type != 'bundle') {
$type .= 'release';
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(),
array($type => array('changelog')));
return true;
}
return false;
}
 
/**
* Get the current release tag in order to add to it
* @param bool returns only releases that have installcondition if true
* @return array|null
*/
function &_getCurrentRelease($strict = true)
{
if ($p = $this->getPackageType()) {
if ($strict) {
if ($p == 'extsrc' || $p == 'zendextsrc') {
$a = null;
return $a;
}
}
if ($p != 'bundle') {
$p .= 'release';
}
if (isset($this->_packageInfo[$p][0])) {
return $this->_packageInfo[$p][count($this->_packageInfo[$p]) - 1];
} else {
return $this->_packageInfo[$p];
}
} else {
$a = null;
return $a;
}
}
 
/**
* Add a file to the current release that should be installed under a different name
* @param string <contents> path to file
* @param string name the file should be installed as
*/
function addInstallAs($path, $as)
{
$r = &$this->_getCurrentRelease();
if ($r === null) {
return false;
}
$this->_isValid = 0;
$r = $this->_mergeTag($r, array('attribs' => array('name' => $path, 'as' => $as)),
array(
'filelist' => array(),
'install' => array('ignore')
));
}
 
/**
* Add a file to the current release that should be ignored
* @param string <contents> path to file
* @return bool success of operation
*/
function addIgnore($path)
{
$r = &$this->_getCurrentRelease();
if ($r === null) {
return false;
}
$this->_isValid = 0;
$r = $this->_mergeTag($r, array('attribs' => array('name' => $path)),
array(
'filelist' => array(),
'ignore' => array()
));
}
 
/**
* Add an extension binary package for this extension source code release
*
* Note that the package must be from the same channel as the extension source package
* @param string
*/
function addBinarypackage($package)
{
if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
return false;
}
$r = &$this->_getCurrentRelease(false);
if ($r === null) {
return false;
}
$this->_isValid = 0;
$r = $this->_mergeTag($r, $package,
array(
'binarypackage' => array('filelist'),
));
}
 
/**
* Add a configureoption to an extension source package
* @param string
* @param string
* @param string
*/
function addConfigureOption($name, $prompt, $default = null)
{
if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
return false;
}
$r = &$this->_getCurrentRelease(false);
if ($r === null) {
return false;
}
$opt = array('attribs' => array('name' => $name, 'prompt' => $prompt));
if ($default !== null) {
$opt['default'] = $default;
}
$this->_isValid = 0;
$r = $this->_mergeTag($r, $opt,
array(
'configureoption' => array('binarypackage', 'filelist'),
));
}
 
/**
* Set an installation condition based on php version for the current release set
* @param string minimum version
* @param string maximum version
* @param false|array incompatible versions of PHP
*/
function setPhpInstallCondition($min, $max, $exclude = false)
{
$r = &$this->_getCurrentRelease();
if ($r === null) {
return false;
}
$this->_isValid = 0;
if (isset($r['installconditions']['php'])) {
unset($r['installconditions']['php']);
}
$dep = array('min' => $min, 'max' => $max);
if ($exclude) {
if (is_array($exclude) && count($exclude) == 1) {
$exclude = $exclude[0];
}
$dep['exclude'] = $exclude;
}
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
$r = $this->_mergeTag($r, $dep,
array(
'installconditions' => array('configureoption', 'binarypackage',
'filelist'),
'php' => array('extension', 'os', 'arch')
));
} else {
$r = $this->_mergeTag($r, $dep,
array(
'installconditions' => array('filelist'),
'php' => array('extension', 'os', 'arch')
));
}
}
 
/**
* @param optional|required optional, required
* @param string extension name
* @param string minimum version
* @param string maximum version
* @param string recommended version
* @param array incompatible versions
*/
function addExtensionInstallCondition($name, $min = false, $max = false, $recommended = false,
$exclude = false)
{
$r = &$this->_getCurrentRelease();
if ($r === null) {
return false;
}
$this->_isValid = 0;
$dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
$r = $this->_mergeTag($r, $dep,
array(
'installconditions' => array('configureoption', 'binarypackage',
'filelist'),
'extension' => array('os', 'arch')
));
} else {
$r = $this->_mergeTag($r, $dep,
array(
'installconditions' => array('filelist'),
'extension' => array('os', 'arch')
));
}
}
 
/**
* Set an installation condition based on operating system for the current release set
* @param string OS name
* @param bool whether this OS is incompatible with the current release
*/
function setOsInstallCondition($name, $conflicts = false)
{
$r = &$this->_getCurrentRelease();
if ($r === null) {
return false;
}
$this->_isValid = 0;
if (isset($r['installconditions']['os'])) {
unset($r['installconditions']['os']);
}
$dep = array('name' => $name);
if ($conflicts) {
$dep['conflicts'] = '';
}
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
$r = $this->_mergeTag($r, $dep,
array(
'installconditions' => array('configureoption', 'binarypackage',
'filelist'),
'os' => array('arch')
));
} else {
$r = $this->_mergeTag($r, $dep,
array(
'installconditions' => array('filelist'),
'os' => array('arch')
));
}
}
 
/**
* Set an installation condition based on architecture for the current release set
* @param string architecture pattern
* @param bool whether this arch is incompatible with the current release
*/
function setArchInstallCondition($pattern, $conflicts = false)
{
$r = &$this->_getCurrentRelease();
if ($r === null) {
return false;
}
$this->_isValid = 0;
if (isset($r['installconditions']['arch'])) {
unset($r['installconditions']['arch']);
}
$dep = array('pattern' => $pattern);
if ($conflicts) {
$dep['conflicts'] = '';
}
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
$r = $this->_mergeTag($r, $dep,
array(
'installconditions' => array('configureoption', 'binarypackage',
'filelist'),
'arch' => array()
));
} else {
$r = $this->_mergeTag($r, $dep,
array(
'installconditions' => array('filelist'),
'arch' => array()
));
}
}
 
/**
* For extension binary releases, this is used to specify either the
* static URI to a source package, or the package name and channel of the extsrc/zendextsrc
* package it is based on.
* @param string Package name, or full URI to source package (extsrc/zendextsrc type)
*/
function setSourcePackage($packageOrUri)
{
$this->_isValid = 0;
if (isset($this->_packageInfo['channel'])) {
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
'bundle', 'changelog'),
$packageOrUri, 'srcpackage');
} else {
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
'bundle', 'changelog'), $packageOrUri, 'srcuri');
}
}
 
/**
* Generate a valid change log entry from the current package.xml
* @param string|false
*/
function generateChangeLogEntry($notes = false)
{
return array(
'version' =>
array(
'release' => $this->getVersion('release'),
'api' => $this->getVersion('api'),
),
'stability' =>
$this->getStability(),
'date' => $this->getDate(),
'license' => $this->getLicense(true),
'notes' => $notes ? $notes : $this->getNotes()
);
}
 
/**
* @param string release version to set change log notes for
* @param array output of {@link generateChangeLogEntry()}
*/
function setChangelogEntry($releaseversion, $contents)
{
if (!isset($this->_packageInfo['changelog'])) {
$this->_packageInfo['changelog']['release'] = $contents;
return;
}
if (!isset($this->_packageInfo['changelog']['release'][0])) {
if ($this->_packageInfo['changelog']['release']['version']['release'] == $releaseversion) {
$this->_packageInfo['changelog']['release'] = array(
$this->_packageInfo['changelog']['release']);
} else {
$this->_packageInfo['changelog']['release'] = array(
$this->_packageInfo['changelog']['release']);
return $this->_packageInfo['changelog']['release'][] = $contents;
}
}
foreach($this->_packageInfo['changelog']['release'] as $index => $changelog) {
if (isset($changelog['version']) &&
strnatcasecmp($changelog['version']['release'], $releaseversion) == 0) {
$curlog = $index;
}
}
if (isset($curlog)) {
$this->_packageInfo['changelog']['release'][$curlog] = $contents;
} else {
$this->_packageInfo['changelog']['release'][] = $contents;
}
}
 
/**
* Remove the changelog entirely
*/
function clearChangeLog()
{
unset($this->_packageInfo['changelog']);
}
}
?>
/trunk/bibliotheque/pear/PEAR/PackageFile/Parser/v1.php
New file
0,0 → 1,461
<?php
/**
* package.xml parsing class, package.xml version 1.0
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: v1.php,v 1.22 2006/03/27 05:25:48 cellog Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* package.xml abstraction class
*/
require_once 'PEAR/PackageFile/v1.php';
/**
* Parser for package.xml version 1.0
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: @PEAR-VER@
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_PackageFile_Parser_v1
{
var $_registry;
var $_config;
var $_logger;
/**
* BC hack to allow PEAR_Common::infoFromString() to sort of
* work with the version 2.0 format - there's no filelist though
* @param PEAR_PackageFile_v2
*/
function fromV2($packagefile)
{
$info = $packagefile->getArray(true);
$ret = new PEAR_PackageFile_v1;
$ret->fromArray($info['old']);
}
 
function setConfig(&$c)
{
$this->_config = &$c;
$this->_registry = &$c->getRegistry();
}
 
function setLogger(&$l)
{
$this->_logger = &$l;
}
 
/**
* @param string contents of package.xml file, version 1.0
* @return bool success of parsing
*/
function parse($data, $file, $archive = false)
{
if (!extension_loaded('xml')) {
return PEAR::raiseError('Cannot create xml parser for parsing package.xml, no xml extension');
}
$xp = xml_parser_create();
if (!$xp) {
return PEAR::raiseError('Cannot create xml parser for parsing package.xml');
}
xml_set_object($xp, $this);
xml_set_element_handler($xp, '_element_start_1_0', '_element_end_1_0');
xml_set_character_data_handler($xp, '_pkginfo_cdata_1_0');
xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false);
 
$this->element_stack = array();
$this->_packageInfo = array('provides' => array());
$this->current_element = false;
unset($this->dir_install);
$this->_packageInfo['filelist'] = array();
$this->filelist =& $this->_packageInfo['filelist'];
$this->dir_names = array();
$this->in_changelog = false;
$this->d_i = 0;
$this->cdata = '';
$this->_isValid = true;
 
if (!xml_parse($xp, $data, 1)) {
$code = xml_get_error_code($xp);
$line = xml_get_current_line_number($xp);
xml_parser_free($xp);
return PEAR::raiseError(sprintf("XML error: %s at line %d",
$str = xml_error_string($code), $line), 2);
}
 
xml_parser_free($xp);
 
$pf = new PEAR_PackageFile_v1;
$pf->setConfig($this->_config);
if (isset($this->_logger)) {
$pf->setLogger($this->_logger);
}
$pf->setPackagefile($file, $archive);
$pf->fromArray($this->_packageInfo);
return $pf;
}
// {{{ _unIndent()
 
/**
* Unindent given string
*
* @param string $str The string that has to be unindented.
* @return string
* @access private
*/
function _unIndent($str)
{
// remove leading newlines
$str = preg_replace('/^[\r\n]+/', '', $str);
// find whitespace at the beginning of the first line
$indent_len = strspn($str, " \t");
$indent = substr($str, 0, $indent_len);
$data = '';
// remove the same amount of whitespace from following lines
foreach (explode("\n", $str) as $line) {
if (substr($line, 0, $indent_len) == $indent) {
$data .= substr($line, $indent_len) . "\n";
}
}
return $data;
}
 
// Support for package DTD v1.0:
// {{{ _element_start_1_0()
 
/**
* XML parser callback for ending elements. Used for version 1.0
* packages.
*
* @param resource $xp XML parser resource
* @param string $name name of ending element
*
* @return void
*
* @access private
*/
function _element_start_1_0($xp, $name, $attribs)
{
array_push($this->element_stack, $name);
$this->current_element = $name;
$spos = sizeof($this->element_stack) - 2;
$this->prev_element = ($spos >= 0) ? $this->element_stack[$spos] : '';
$this->current_attributes = $attribs;
$this->cdata = '';
switch ($name) {
case 'dir':
if ($this->in_changelog) {
break;
}
if (array_key_exists('name', $attribs) && $attribs['name'] != '/') {
$attribs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
$attribs['name']);
if (strrpos($attribs['name'], '/') == strlen($attribs['name']) - 1) {
$attribs['name'] = substr($attribs['name'], 0,
strlen($attribs['name']) - 1);
}
if (strpos($attribs['name'], '/') === 0) {
$attribs['name'] = substr($attribs['name'], 1);
}
$this->dir_names[] = $attribs['name'];
}
if (isset($attribs['baseinstalldir'])) {
$this->dir_install = $attribs['baseinstalldir'];
}
if (isset($attribs['role'])) {
$this->dir_role = $attribs['role'];
}
break;
case 'file':
if ($this->in_changelog) {
break;
}
if (isset($attribs['name'])) {
$path = '';
if (count($this->dir_names)) {
foreach ($this->dir_names as $dir) {
$path .= $dir . '/';
}
}
$path .= preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
$attribs['name']);
unset($attribs['name']);
$this->current_path = $path;
$this->filelist[$path] = $attribs;
// Set the baseinstalldir only if the file don't have this attrib
if (!isset($this->filelist[$path]['baseinstalldir']) &&
isset($this->dir_install))
{
$this->filelist[$path]['baseinstalldir'] = $this->dir_install;
}
// Set the Role
if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
$this->filelist[$path]['role'] = $this->dir_role;
}
}
break;
case 'replace':
if (!$this->in_changelog) {
$this->filelist[$this->current_path]['replacements'][] = $attribs;
}
break;
case 'maintainers':
$this->_packageInfo['maintainers'] = array();
$this->m_i = 0; // maintainers array index
break;
case 'maintainer':
// compatibility check
if (!isset($this->_packageInfo['maintainers'])) {
$this->_packageInfo['maintainers'] = array();
$this->m_i = 0;
}
$this->_packageInfo['maintainers'][$this->m_i] = array();
$this->current_maintainer =& $this->_packageInfo['maintainers'][$this->m_i];
break;
case 'changelog':
$this->_packageInfo['changelog'] = array();
$this->c_i = 0; // changelog array index
$this->in_changelog = true;
break;
case 'release':
if ($this->in_changelog) {
$this->_packageInfo['changelog'][$this->c_i] = array();
$this->current_release = &$this->_packageInfo['changelog'][$this->c_i];
} else {
$this->current_release = &$this->_packageInfo;
}
break;
case 'deps':
if (!$this->in_changelog) {
$this->_packageInfo['release_deps'] = array();
}
break;
case 'dep':
// dependencies array index
if (!$this->in_changelog) {
$this->d_i++;
isset($attribs['type']) ? ($attribs['type'] = strtolower($attribs['type'])) : false;
$this->_packageInfo['release_deps'][$this->d_i] = $attribs;
}
break;
case 'configureoptions':
if (!$this->in_changelog) {
$this->_packageInfo['configure_options'] = array();
}
break;
case 'configureoption':
if (!$this->in_changelog) {
$this->_packageInfo['configure_options'][] = $attribs;
}
break;
case 'provides':
if (empty($attribs['type']) || empty($attribs['name'])) {
break;
}
$attribs['explicit'] = true;
$this->_packageInfo['provides']["$attribs[type];$attribs[name]"] = $attribs;
break;
case 'package' :
if (isset($attribs['version'])) {
$this->_packageInfo['xsdversion'] = trim($attribs['version']);
} else {
$this->_packageInfo['xsdversion'] = '1.0';
}
if (isset($attribs['packagerversion'])) {
$this->_packageInfo['packagerversion'] = $attribs['packagerversion'];
}
break;
}
}
 
// }}}
// {{{ _element_end_1_0()
 
/**
* XML parser callback for ending elements. Used for version 1.0
* packages.
*
* @param resource $xp XML parser resource
* @param string $name name of ending element
*
* @return void
*
* @access private
*/
function _element_end_1_0($xp, $name)
{
$data = trim($this->cdata);
switch ($name) {
case 'name':
switch ($this->prev_element) {
case 'package':
$this->_packageInfo['package'] = $data;
break;
case 'maintainer':
$this->current_maintainer['name'] = $data;
break;
}
break;
case 'extends' :
$this->_packageInfo['extends'] = $data;
break;
case 'summary':
$this->_packageInfo['summary'] = $data;
break;
case 'description':
$data = $this->_unIndent($this->cdata);
$this->_packageInfo['description'] = $data;
break;
case 'user':
$this->current_maintainer['handle'] = $data;
break;
case 'email':
$this->current_maintainer['email'] = $data;
break;
case 'role':
$this->current_maintainer['role'] = $data;
break;
case 'version':
//$data = ereg_replace ('[^a-zA-Z0-9._\-]', '_', $data);
if ($this->in_changelog) {
$this->current_release['version'] = $data;
} else {
$this->_packageInfo['version'] = $data;
}
break;
case 'date':
if ($this->in_changelog) {
$this->current_release['release_date'] = $data;
} else {
$this->_packageInfo['release_date'] = $data;
}
break;
case 'notes':
// try to "de-indent" release notes in case someone
// has been over-indenting their xml ;-)
$data = $this->_unIndent($this->cdata);
if ($this->in_changelog) {
$this->current_release['release_notes'] = $data;
} else {
$this->_packageInfo['release_notes'] = $data;
}
break;
case 'warnings':
if ($this->in_changelog) {
$this->current_release['release_warnings'] = $data;
} else {
$this->_packageInfo['release_warnings'] = $data;
}
break;
case 'state':
if ($this->in_changelog) {
$this->current_release['release_state'] = $data;
} else {
$this->_packageInfo['release_state'] = $data;
}
break;
case 'license':
if ($this->in_changelog) {
$this->current_release['release_license'] = $data;
} else {
$this->_packageInfo['release_license'] = $data;
}
break;
case 'dep':
if ($data && !$this->in_changelog) {
$this->_packageInfo['release_deps'][$this->d_i]['name'] = $data;
}
break;
case 'dir':
if ($this->in_changelog) {
break;
}
array_pop($this->dir_names);
break;
case 'file':
if ($this->in_changelog) {
break;
}
if ($data) {
$path = '';
if (count($this->dir_names)) {
foreach ($this->dir_names as $dir) {
$path .= $dir . '/';
}
}
$path .= $data;
$this->filelist[$path] = $this->current_attributes;
// Set the baseinstalldir only if the file don't have this attrib
if (!isset($this->filelist[$path]['baseinstalldir']) &&
isset($this->dir_install))
{
$this->filelist[$path]['baseinstalldir'] = $this->dir_install;
}
// Set the Role
if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
$this->filelist[$path]['role'] = $this->dir_role;
}
}
break;
case 'maintainer':
if (empty($this->_packageInfo['maintainers'][$this->m_i]['role'])) {
$this->_packageInfo['maintainers'][$this->m_i]['role'] = 'lead';
}
$this->m_i++;
break;
case 'release':
if ($this->in_changelog) {
$this->c_i++;
}
break;
case 'changelog':
$this->in_changelog = false;
break;
}
array_pop($this->element_stack);
$spos = sizeof($this->element_stack) - 1;
$this->current_element = ($spos > 0) ? $this->element_stack[$spos] : '';
$this->cdata = '';
}
 
// }}}
// {{{ _pkginfo_cdata_1_0()
 
/**
* XML parser callback for character data. Used for version 1.0
* packages.
*
* @param resource $xp XML parser resource
* @param string $name character data
*
* @return void
*
* @access private
*/
function _pkginfo_cdata_1_0($xp, $data)
{
if (isset($this->cdata)) {
$this->cdata .= $data;
}
}
 
// }}}
}
?>
/trunk/bibliotheque/pear/PEAR/PackageFile/Parser/v2.php
New file
0,0 → 1,115
<?php
/**
* package.xml parsing class, package.xml version 2.0
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: v2.php,v 1.19 2006/01/23 17:39:52 cellog Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* base xml parser class
*/
require_once 'PEAR/XMLParser.php';
require_once 'PEAR/PackageFile/v2.php';
/**
* Parser for package.xml version 2.0
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: @PEAR-VER@
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_PackageFile_Parser_v2 extends PEAR_XMLParser
{
var $_config;
var $_logger;
var $_registry;
 
function setConfig(&$c)
{
$this->_config = &$c;
$this->_registry = &$c->getRegistry();
}
 
function setLogger(&$l)
{
$this->_logger = &$l;
}
/**
* Unindent given string
*
* @param string $str The string that has to be unindented.
* @return string
* @access private
*/
function _unIndent($str)
{
// remove leading newlines
$str = preg_replace('/^[\r\n]+/', '', $str);
// find whitespace at the beginning of the first line
$indent_len = strspn($str, " \t");
$indent = substr($str, 0, $indent_len);
$data = '';
// remove the same amount of whitespace from following lines
foreach (explode("\n", $str) as $line) {
if (substr($line, 0, $indent_len) == $indent) {
$data .= substr($line, $indent_len) . "\n";
}
}
return $data;
}
 
/**
* post-process data
*
* @param string $data
* @param string $element element name
*/
function postProcess($data, $element)
{
if ($element == 'notes') {
return trim($this->_unIndent($data));
}
return trim($data);
}
 
/**
* @param string
* @param string file name of the package.xml
* @param string|false name of the archive this package.xml came from, if any
* @param string class name to instantiate and return. This must be PEAR_PackageFile_v2 or
* a subclass
* @return PEAR_PackageFile_v2
*/
function &parse($data, $file, $archive = false, $class = 'PEAR_PackageFile_v2')
{
if (PEAR::isError($err = parent::parse($data, $file))) {
return $err;
}
$ret = new $class;
$ret->setConfig($this->_config);
if (isset($this->_logger)) {
$ret->setLogger($this->_logger);
}
$ret->fromArray($this->_unserializedData);
$ret->setPackagefile($file, $archive);
return $ret;
}
}
?>
/trunk/bibliotheque/pear/PEAR/PackageFile/v1.php
New file
0,0 → 1,1603
<?php
/**
* PEAR_PackageFile_v1, package.xml version 1.0
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: v1.php,v 1.72 2006/10/31 02:54:41 cellog Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* For error handling
*/
require_once 'PEAR/ErrorStack.php';
 
/**
* Error code if parsing is attempted with no xml extension
*/
define('PEAR_PACKAGEFILE_ERROR_NO_XML_EXT', 3);
 
/**
* Error code if creating the xml parser resource fails
*/
define('PEAR_PACKAGEFILE_ERROR_CANT_MAKE_PARSER', 4);
 
/**
* Error code used for all sax xml parsing errors
*/
define('PEAR_PACKAGEFILE_ERROR_PARSER_ERROR', 5);
 
/**
* Error code used when there is no name
*/
define('PEAR_PACKAGEFILE_ERROR_NO_NAME', 6);
 
/**
* Error code when a package name is not valid
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_NAME', 7);
 
/**
* Error code used when no summary is parsed
*/
define('PEAR_PACKAGEFILE_ERROR_NO_SUMMARY', 8);
 
/**
* Error code for summaries that are more than 1 line
*/
define('PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY', 9);
 
/**
* Error code used when no description is present
*/
define('PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION', 10);
 
/**
* Error code used when no license is present
*/
define('PEAR_PACKAGEFILE_ERROR_NO_LICENSE', 11);
 
/**
* Error code used when a <version> version number is not present
*/
define('PEAR_PACKAGEFILE_ERROR_NO_VERSION', 12);
 
/**
* Error code used when a <version> version number is invalid
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_VERSION', 13);
 
/**
* Error code when release state is missing
*/
define('PEAR_PACKAGEFILE_ERROR_NO_STATE', 14);
 
/**
* Error code when release state is invalid
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_STATE', 15);
 
/**
* Error code when release state is missing
*/
define('PEAR_PACKAGEFILE_ERROR_NO_DATE', 16);
 
/**
* Error code when release state is invalid
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_DATE', 17);
 
/**
* Error code when no release notes are found
*/
define('PEAR_PACKAGEFILE_ERROR_NO_NOTES', 18);
 
/**
* Error code when no maintainers are found
*/
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS', 19);
 
/**
* Error code when a maintainer has no handle
*/
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE', 20);
 
/**
* Error code when a maintainer has no handle
*/
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE', 21);
 
/**
* Error code when a maintainer has no name
*/
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME', 22);
 
/**
* Error code when a maintainer has no email
*/
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL', 23);
 
/**
* Error code when a maintainer has no handle
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_MAINTROLE', 24);
 
/**
* Error code when a dependency is not a PHP dependency, but has no name
*/
define('PEAR_PACKAGEFILE_ERROR_NO_DEPNAME', 25);
 
/**
* Error code when a dependency has no type (pkg, php, etc.)
*/
define('PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE', 26);
 
/**
* Error code when a dependency has no relation (lt, ge, has, etc.)
*/
define('PEAR_PACKAGEFILE_ERROR_NO_DEPREL', 27);
 
/**
* Error code when a dependency is not a 'has' relation, but has no version
*/
define('PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION', 28);
 
/**
* Error code when a dependency has an invalid relation
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPREL', 29);
 
/**
* Error code when a dependency has an invalid type
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPTYPE', 30);
 
/**
* Error code when a dependency has an invalid optional option
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL', 31);
 
/**
* Error code when a dependency is a pkg dependency, and has an invalid package name
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPNAME', 32);
 
/**
* Error code when a dependency has a channel="foo" attribute, and foo is not a registered channel
*/
define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_DEPCHANNEL', 33);
 
/**
* Error code when rel="has" and version attribute is present.
*/
define('PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED', 34);
 
/**
* Error code when type="php" and dependency name is present
*/
define('PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED', 35);
 
/**
* Error code when a configure option has no name
*/
define('PEAR_PACKAGEFILE_ERROR_NO_CONFNAME', 36);
 
/**
* Error code when a configure option has no name
*/
define('PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT', 37);
 
/**
* Error code when a file in the filelist has an invalid role
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE', 38);
 
/**
* Error code when a file in the filelist has no role
*/
define('PEAR_PACKAGEFILE_ERROR_NO_FILEROLE', 39);
 
/**
* Error code when analyzing a php source file that has parse errors
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE', 40);
 
/**
* Error code when analyzing a php source file reveals a source element
* without a package name prefix
*/
define('PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX', 41);
 
/**
* Error code when an unknown channel is specified
*/
define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_CHANNEL', 42);
 
/**
* Error code when no files are found in the filelist
*/
define('PEAR_PACKAGEFILE_ERROR_NO_FILES', 43);
 
/**
* Error code when a file is not valid php according to _analyzeSourceCode()
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_FILE', 44);
 
/**
* Error code when the channel validator returns an error or warning
*/
define('PEAR_PACKAGEFILE_ERROR_CHANNELVAL', 45);
 
/**
* Error code when a php5 package is packaged in php4 (analysis doesn't work)
*/
define('PEAR_PACKAGEFILE_ERROR_PHP5', 46);
 
/**
* Error code when a file is listed in package.xml but does not exist
*/
define('PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND', 47);
 
/**
* Error code when a <dep type="php" rel="not"... is encountered (use rel="ne")
*/
define('PEAR_PACKAGEFILE_PHP_NO_NOT', 48);
 
/**
* Error code when a package.xml contains non-ISO-8859-1 characters
*/
define('PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS', 49);
 
/**
* Error code when a dependency is not a 'has' relation, but has no version
*/
define('PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION', 50);
 
/**
* Error code when a package has no lead developer
*/
define('PEAR_PACKAGEFILE_ERROR_NO_LEAD', 51);
 
/**
* Error code when a filename begins with "."
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME', 52);
/**
* package.xml encapsulator
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.5.1
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_PackageFile_v1
{
/**
* @access private
* @var PEAR_ErrorStack
* @access private
*/
var $_stack;
 
/**
* A registry object, used to access the package name validation regex for non-standard channels
* @var PEAR_Registry
* @access private
*/
var $_registry;
 
/**
* An object that contains a log method that matches PEAR_Common::log's signature
* @var object
* @access private
*/
var $_logger;
 
/**
* Parsed package information
* @var array
* @access private
*/
var $_packageInfo;
 
/**
* path to package.xml
* @var string
* @access private
*/
var $_packageFile;
 
/**
* path to package .tgz or false if this is a local/extracted package.xml
* @var string
* @access private
*/
var $_archiveFile;
 
/**
* @var int
* @access private
*/
var $_isValid = 0;
 
/**
* Determines whether this packagefile was initialized only with partial package info
*
* If this package file was constructed via parsing REST, it will only contain
*
* - package name
* - channel name
* - dependencies
* @var boolean
* @access private
*/
var $_incomplete = true;
 
/**
* @param bool determines whether to return a PEAR_Error object, or use the PEAR_ErrorStack
* @param string Name of Error Stack class to use.
*/
function PEAR_PackageFile_v1()
{
$this->_stack = &new PEAR_ErrorStack('PEAR_PackageFile_v1');
$this->_stack->setErrorMessageTemplate($this->_getErrorMessage());
$this->_isValid = 0;
}
 
function installBinary($installer)
{
return false;
}
 
function isExtension($name)
{
return false;
}
 
function setConfig(&$config)
{
$this->_config = &$config;
$this->_registry = &$config->getRegistry();
}
 
function setRequestedGroup()
{
// placeholder
}
 
/**
* For saving in the registry.
*
* Set the last version that was installed
* @param string
*/
function setLastInstalledVersion($version)
{
$this->_packageInfo['_lastversion'] = $version;
}
 
/**
* @return string|false
*/
function getLastInstalledVersion()
{
if (isset($this->_packageInfo['_lastversion'])) {
return $this->_packageInfo['_lastversion'];
}
return false;
}
 
function getInstalledBinary()
{
return false;
}
 
function listPostinstallScripts()
{
return false;
}
 
function initPostinstallScripts()
{
return false;
}
 
function setLogger(&$logger)
{
if ($logger && (!is_object($logger) || !method_exists($logger, 'log'))) {
return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
}
$this->_logger = &$logger;
}
 
function setPackagefile($file, $archive = false)
{
$this->_packageFile = $file;
$this->_archiveFile = $archive ? $archive : $file;
}
 
function getPackageFile()
{
return isset($this->_packageFile) ? $this->_packageFile : false;
}
 
function getPackageType()
{
return 'php';
}
 
function getArchiveFile()
{
return $this->_archiveFile;
}
 
function packageInfo($field)
{
if (!is_string($field) || empty($field) ||
!isset($this->_packageInfo[$field])) {
return false;
}
return $this->_packageInfo[$field];
}
 
function setDirtree($path)
{
if (!isset($this->_packageInfo['dirtree'])) {
$this->_packageInfo['dirtree'] = array();
}
$this->_packageInfo['dirtree'][$path] = true;
}
 
function getDirtree()
{
if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) {
return $this->_packageInfo['dirtree'];
}
return false;
}
 
function resetDirtree()
{
unset($this->_packageInfo['dirtree']);
}
 
function fromArray($pinfo)
{
$this->_incomplete = false;
$this->_packageInfo = $pinfo;
}
 
function isIncomplete()
{
return $this->_incomplete;
}
 
function getChannel()
{
return 'pear.php.net';
}
 
function getUri()
{
return false;
}
 
function getTime()
{
return false;
}
 
function getExtends()
{
if (isset($this->_packageInfo['extends'])) {
return $this->_packageInfo['extends'];
}
return false;
}
 
/**
* @return array
*/
function toArray()
{
if (!$this->validate(PEAR_VALIDATE_NORMAL)) {
return false;
}
return $this->getArray();
}
 
function getArray()
{
return $this->_packageInfo;
}
 
function getName()
{
return $this->getPackage();
}
 
function getPackage()
{
if (isset($this->_packageInfo['package'])) {
return $this->_packageInfo['package'];
}
return false;
}
 
/**
* WARNING - don't use this unless you know what you are doing
*/
function setRawPackage($package)
{
$this->_packageInfo['package'] = $package;
}
 
function setPackage($package)
{
$this->_packageInfo['package'] = $package;
$this->_isValid = false;
}
 
function getVersion()
{
if (isset($this->_packageInfo['version'])) {
return $this->_packageInfo['version'];
}
return false;
}
 
function setVersion($version)
{
$this->_packageInfo['version'] = $version;
$this->_isValid = false;
}
 
function clearMaintainers()
{
unset($this->_packageInfo['maintainers']);
}
 
function getMaintainers()
{
if (isset($this->_packageInfo['maintainers'])) {
return $this->_packageInfo['maintainers'];
}
return false;
}
 
/**
* Adds a new maintainer - no checking of duplicates is performed, use
* updatemaintainer for that purpose.
*/
function addMaintainer($role, $handle, $name, $email)
{
$this->_packageInfo['maintainers'][] =
array('handle' => $handle, 'role' => $role, 'email' => $email, 'name' => $name);
$this->_isValid = false;
}
 
function updateMaintainer($role, $handle, $name, $email)
{
$found = false;
if (!isset($this->_packageInfo['maintainers']) ||
!is_array($this->_packageInfo['maintainers'])) {
return $this->addMaintainer($role, $handle, $name, $email);
}
foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) {
if ($maintainer['handle'] == $handle) {
$found = $i;
break;
}
}
if ($found !== false) {
unset($this->_packageInfo['maintainers'][$found]);
$this->_packageInfo['maintainers'] =
array_values($this->_packageInfo['maintainers']);
}
$this->addMaintainer($role, $handle, $name, $email);
}
 
function deleteMaintainer($handle)
{
$found = false;
foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) {
if ($maintainer['handle'] == $handle) {
$found = $i;
break;
}
}
if ($found !== false) {
unset($this->_packageInfo['maintainers'][$found]);
$this->_packageInfo['maintainers'] =
array_values($this->_packageInfo['maintainers']);
return true;
}
return false;
}
 
function getState()
{
if (isset($this->_packageInfo['release_state'])) {
return $this->_packageInfo['release_state'];
}
return false;
}
 
function setRawState($state)
{
$this->_packageInfo['release_state'] = $state;
}
 
function setState($state)
{
$this->_packageInfo['release_state'] = $state;
$this->_isValid = false;
}
 
function getDate()
{
if (isset($this->_packageInfo['release_date'])) {
return $this->_packageInfo['release_date'];
}
return false;
}
 
function setDate($date)
{
$this->_packageInfo['release_date'] = $date;
$this->_isValid = false;
}
 
function getLicense()
{
if (isset($this->_packageInfo['release_license'])) {
return $this->_packageInfo['release_license'];
}
return false;
}
 
function setLicense($date)
{
$this->_packageInfo['release_license'] = $date;
$this->_isValid = false;
}
 
function getSummary()
{
if (isset($this->_packageInfo['summary'])) {
return $this->_packageInfo['summary'];
}
return false;
}
 
function setSummary($summary)
{
$this->_packageInfo['summary'] = $summary;
$this->_isValid = false;
}
 
function getDescription()
{
if (isset($this->_packageInfo['description'])) {
return $this->_packageInfo['description'];
}
return false;
}
 
function setDescription($desc)
{
$this->_packageInfo['description'] = $desc;
$this->_isValid = false;
}
 
function getNotes()
{
if (isset($this->_packageInfo['release_notes'])) {
return $this->_packageInfo['release_notes'];
}
return false;
}
 
function setNotes($notes)
{
$this->_packageInfo['release_notes'] = $notes;
$this->_isValid = false;
}
 
function getDeps()
{
if (isset($this->_packageInfo['release_deps'])) {
return $this->_packageInfo['release_deps'];
}
return false;
}
 
/**
* Reset dependencies prior to adding new ones
*/
function clearDeps()
{
unset($this->_packageInfo['release_deps']);
}
 
function addPhpDep($version, $rel)
{
$this->_isValid = false;
$this->_packageInfo['release_deps'][] =
array('type' => 'php',
'rel' => $rel,
'version' => $version);
}
 
function addPackageDep($name, $version, $rel, $optional = 'no')
{
$this->_isValid = false;
$dep =
array('type' => 'pkg',
'name' => $name,
'rel' => $rel,
'optional' => $optional);
if ($rel != 'has' && $rel != 'not') {
$dep['version'] = $version;
}
$this->_packageInfo['release_deps'][] = $dep;
}
 
function addExtensionDep($name, $version, $rel, $optional = 'no')
{
$this->_isValid = false;
$this->_packageInfo['release_deps'][] =
array('type' => 'ext',
'name' => $name,
'rel' => $rel,
'version' => $version,
'optional' => $optional);
}
 
/**
* WARNING - do not use this function directly unless you know what you're doing
*/
function setDeps($deps)
{
$this->_packageInfo['release_deps'] = $deps;
}
 
function hasDeps()
{
return isset($this->_packageInfo['release_deps']) &&
count($this->_packageInfo['release_deps']);
}
 
function getDependencyGroup($group)
{
return false;
}
 
function isCompatible($pf)
{
return false;
}
 
function isSubpackageOf($p)
{
return $p->isSubpackage($this);
}
 
function isSubpackage($p)
{
return false;
}
 
function dependsOn($package, $channel)
{
if (strtolower($channel) != 'pear.php.net') {
return false;
}
if (!($deps = $this->getDeps())) {
return false;
}
foreach ($deps as $dep) {
if ($dep['type'] != 'pkg') {
continue;
}
if (strtolower($dep['name']) == strtolower($package)) {
return true;
}
}
return false;
}
 
function getConfigureOptions()
{
if (isset($this->_packageInfo['configure_options'])) {
return $this->_packageInfo['configure_options'];
}
return false;
}
 
function hasConfigureOptions()
{
return isset($this->_packageInfo['configure_options']) &&
count($this->_packageInfo['configure_options']);
}
 
function addConfigureOption($name, $prompt, $default = false)
{
$o = array('name' => $name, 'prompt' => $prompt);
if ($default !== false) {
$o['default'] = $default;
}
if (!isset($this->_packageInfo['configure_options'])) {
$this->_packageInfo['configure_options'] = array();
}
$this->_packageInfo['configure_options'][] = $o;
}
 
function clearConfigureOptions()
{
unset($this->_packageInfo['configure_options']);
}
 
function getProvides()
{
if (isset($this->_packageInfo['provides'])) {
return $this->_packageInfo['provides'];
}
return false;
}
 
function getProvidesExtension()
{
return false;
}
 
function addFile($dir, $file, $attrs)
{
$dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir);
if ($dir == '/' || $dir == '') {
$dir = '';
} else {
$dir .= '/';
}
$file = $dir . $file;
$file = preg_replace('![\\/]+!', '/', $file);
$this->_packageInfo['filelist'][$file] = $attrs;
}
 
function getInstallationFilelist()
{
return $this->getFilelist();
}
 
function getFilelist()
{
if (isset($this->_packageInfo['filelist'])) {
return $this->_packageInfo['filelist'];
}
return false;
}
 
function setFileAttribute($file, $attr, $value)
{
$this->_packageInfo['filelist'][$file][$attr] = $value;
}
 
function resetFilelist()
{
$this->_packageInfo['filelist'] = array();
}
 
function setInstalledAs($file, $path)
{
if ($path) {
return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
}
unset($this->_packageInfo['filelist'][$file]['installed_as']);
}
 
function installedFile($file, $atts)
{
if (isset($this->_packageInfo['filelist'][$file])) {
$this->_packageInfo['filelist'][$file] =
array_merge($this->_packageInfo['filelist'][$file], $atts);
} else {
$this->_packageInfo['filelist'][$file] = $atts;
}
}
 
function getChangelog()
{
if (isset($this->_packageInfo['changelog'])) {
return $this->_packageInfo['changelog'];
}
return false;
}
 
function getPackagexmlVersion()
{
return '1.0';
}
 
/**
* Wrapper to {@link PEAR_ErrorStack::getErrors()}
* @param boolean determines whether to purge the error stack after retrieving
* @return array
*/
function getValidationWarnings($purge = true)
{
return $this->_stack->getErrors($purge);
}
 
// }}}
/**
* Validation error. Also marks the object contents as invalid
* @param error code
* @param array error information
* @access private
*/
function _validateError($code, $params = array())
{
$this->_stack->push($code, 'error', $params, false, false, debug_backtrace());
$this->_isValid = false;
}
 
/**
* Validation warning. Does not mark the object contents invalid.
* @param error code
* @param array error information
* @access private
*/
function _validateWarning($code, $params = array())
{
$this->_stack->push($code, 'warning', $params, false, false, debug_backtrace());
}
 
/**
* @param integer error code
* @access protected
*/
function _getErrorMessage()
{
return array(
PEAR_PACKAGEFILE_ERROR_NO_NAME =>
'Missing Package Name',
PEAR_PACKAGEFILE_ERROR_NO_SUMMARY =>
'No summary found',
PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY =>
'Summary should be on one line',
PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION =>
'Missing description',
PEAR_PACKAGEFILE_ERROR_NO_LICENSE =>
'Missing license',
PEAR_PACKAGEFILE_ERROR_NO_VERSION =>
'No release version found',
PEAR_PACKAGEFILE_ERROR_NO_STATE =>
'No release state found',
PEAR_PACKAGEFILE_ERROR_NO_DATE =>
'No release date found',
PEAR_PACKAGEFILE_ERROR_NO_NOTES =>
'No release notes found',
PEAR_PACKAGEFILE_ERROR_NO_LEAD =>
'Package must have at least one lead maintainer',
PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS =>
'No maintainers found, at least one must be defined',
PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE =>
'Maintainer %index% has no handle (user ID at channel server)',
PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE =>
'Maintainer %index% has no role',
PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME =>
'Maintainer %index% has no name',
PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL =>
'Maintainer %index% has no email',
PEAR_PACKAGEFILE_ERROR_NO_DEPNAME =>
'Dependency %index% is not a php dependency, and has no name',
PEAR_PACKAGEFILE_ERROR_NO_DEPREL =>
'Dependency %index% has no relation (rel)',
PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE =>
'Dependency %index% has no type',
PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED =>
'PHP Dependency %index% has a name attribute of "%name%" which will be' .
' ignored!',
PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION =>
'Dependency %index% is not a rel="has" or rel="not" dependency, ' .
'and has no version',
PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION =>
'Dependency %index% is a type="php" dependency, ' .
'and has no version',
PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED =>
'Dependency %index% is a rel="%rel%" dependency, versioning is ignored',
PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL =>
'Dependency %index% has invalid optional value "%opt%", should be yes or no',
PEAR_PACKAGEFILE_PHP_NO_NOT =>
'Dependency %index%: php dependencies cannot use "not" rel, use "ne"' .
' to exclude specific versions',
PEAR_PACKAGEFILE_ERROR_NO_CONFNAME =>
'Configure Option %index% has no name',
PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT =>
'Configure Option %index% has no prompt',
PEAR_PACKAGEFILE_ERROR_NO_FILES =>
'No files in <filelist> section of package.xml',
PEAR_PACKAGEFILE_ERROR_NO_FILEROLE =>
'File "%file%" has no role, expecting one of "%roles%"',
PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE =>
'File "%file%" has invalid role "%role%", expecting one of "%roles%"',
PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME =>
'File "%file%" cannot start with ".", cannot package or install',
PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE =>
'Parser error: invalid PHP found in file "%file%"',
PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX =>
'in %file%: %type% "%name%" not prefixed with package name "%package%"',
PEAR_PACKAGEFILE_ERROR_INVALID_FILE =>
'Parser error: invalid PHP file "%file%"',
PEAR_PACKAGEFILE_ERROR_CHANNELVAL =>
'Channel validator error: field "%field%" - %reason%',
PEAR_PACKAGEFILE_ERROR_PHP5 =>
'Error, PHP5 token encountered in %file%, analysis should be in PHP5',
PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND =>
'File "%file%" in package.xml does not exist',
PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS =>
'Package.xml contains non-ISO-8859-1 characters, and may not validate',
);
}
 
/**
* Validate XML package definition file.
*
* @access public
* @return boolean
*/
function validate($state = PEAR_VALIDATE_NORMAL, $nofilechecking = false)
{
if (($this->_isValid & $state) == $state) {
return true;
}
$this->_isValid = true;
$info = $this->_packageInfo;
if (empty($info['package'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NAME);
$this->_packageName = $pn = 'unknown';
} else {
$this->_packageName = $pn = $info['package'];
}
 
if (empty($info['summary'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_SUMMARY);
} elseif (strpos(trim($info['summary']), "\n") !== false) {
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY,
array('summary' => $info['summary']));
}
if (empty($info['description'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION);
}
if (empty($info['release_license'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LICENSE);
}
if (empty($info['version'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_VERSION);
}
if (empty($info['release_state'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_STATE);
}
if (empty($info['release_date'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DATE);
}
if (empty($info['release_notes'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NOTES);
}
if (empty($info['maintainers'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS);
} else {
$haslead = false;
$i = 1;
foreach ($info['maintainers'] as $m) {
if (empty($m['handle'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE,
array('index' => $i));
}
if (empty($m['role'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE,
array('index' => $i, 'roles' => PEAR_Common::getUserRoles()));
} elseif ($m['role'] == 'lead') {
$haslead = true;
}
if (empty($m['name'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME,
array('index' => $i));
}
if (empty($m['email'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL,
array('index' => $i));
}
$i++;
}
if (!$haslead) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LEAD);
}
}
if (!empty($info['release_deps'])) {
$i = 1;
foreach ($info['release_deps'] as $d) {
if (!isset($d['type']) || empty($d['type'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE,
array('index' => $i, 'types' => PEAR_Common::getDependencyTypes()));
continue;
}
if (!isset($d['rel']) || empty($d['rel'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPREL,
array('index' => $i, 'rels' => PEAR_Common::getDependencyRelations()));
continue;
}
if (!empty($d['optional'])) {
if (!in_array($d['optional'], array('yes', 'no'))) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL,
array('index' => $i, 'opt' => $d['optional']));
}
}
if ($d['rel'] != 'has' && $d['rel'] != 'not' && empty($d['version'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION,
array('index' => $i));
} elseif (($d['rel'] == 'has' || $d['rel'] == 'not') && !empty($d['version'])) {
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED,
array('index' => $i, 'rel' => $d['rel']));
}
if ($d['type'] == 'php' && !empty($d['name'])) {
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED,
array('index' => $i, 'name' => $d['name']));
} elseif ($d['type'] != 'php' && empty($d['name'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPNAME,
array('index' => $i));
}
if ($d['type'] == 'php' && empty($d['version'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION,
array('index' => $i));
}
if (($d['rel'] == 'not') && ($d['type'] == 'php')) {
$this->_validateError(PEAR_PACKAGEFILE_PHP_NO_NOT,
array('index' => $i));
}
$i++;
}
}
if (!empty($info['configure_options'])) {
$i = 1;
foreach ($info['configure_options'] as $c) {
if (empty($c['name'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFNAME,
array('index' => $i));
}
if (empty($c['prompt'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT,
array('index' => $i));
}
$i++;
}
}
if (empty($info['filelist'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILES);
$errors[] = 'no files';
} else {
foreach ($info['filelist'] as $file => $fa) {
if (empty($fa['role'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILEROLE,
array('file' => $file, 'roles' => PEAR_Common::getFileRoles()));
continue;
} elseif (!in_array($fa['role'], PEAR_Common::getFileRoles())) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE,
array('file' => $file, 'role' => $fa['role'], 'roles' => PEAR_Common::getFileRoles()));
}
if ($file{0} == '.' && $file{1} == '/') {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
array('file' => $file));
}
}
}
if (isset($this->_registry) && $this->_isValid) {
$chan = $this->_registry->getChannel('pear.php.net');
if (PEAR::isError($chan)) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $chan->getMessage());
return $this->_isValid = 0;
}
$validator = $chan->getValidationObject();
$validator->setPackageFile($this);
$validator->validate($state);
$failures = $validator->getFailures();
foreach ($failures['errors'] as $error) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $error);
}
foreach ($failures['warnings'] as $warning) {
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $warning);
}
}
if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$nofilechecking) {
if ($this->_analyzePhpFiles()) {
$this->_isValid = true;
}
}
if ($this->_isValid) {
return $this->_isValid = $state;
}
return $this->_isValid = 0;
}
 
function _analyzePhpFiles()
{
if (!$this->_isValid) {
return false;
}
if (!isset($this->_packageFile)) {
return false;
}
$dir_prefix = dirname($this->_packageFile);
$common = new PEAR_Common;
$log = isset($this->_logger) ? array(&$this->_logger, 'log') :
array($common, 'log');
$info = $this->getFilelist();
foreach ($info as $file => $fa) {
if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND,
array('file' => realpath($dir_prefix) . DIRECTORY_SEPARATOR . $file));
continue;
}
if ($fa['role'] == 'php' && $dir_prefix) {
call_user_func_array($log, array(1, "Analyzing $file"));
$srcinfo = $this->_analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
if ($srcinfo) {
$this->_buildProvidesArray($srcinfo);
}
}
}
$this->_packageName = $pn = $this->getPackage();
$pnl = strlen($pn);
if (isset($this->_packageInfo['provides'])) {
foreach ((array) $this->_packageInfo['provides'] as $key => $what) {
if (isset($what['explicit'])) {
// skip conformance checks if the provides entry is
// specified in the package.xml file
continue;
}
extract($what);
if ($type == 'class') {
if (!strncasecmp($name, $pn, $pnl)) {
continue;
}
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX,
array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn));
} elseif ($type == 'function') {
if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
continue;
}
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX,
array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn));
}
}
}
return $this->_isValid;
}
 
/**
* Get the default xml generator object
*
* @return PEAR_PackageFile_Generator_v1
*/
function &getDefaultGenerator()
{
if (!class_exists('PEAR_PackageFile_Generator_v1')) {
require_once 'PEAR/PackageFile/Generator/v1.php';
}
$a = &new PEAR_PackageFile_Generator_v1($this);
return $a;
}
 
/**
* Get the contents of a file listed within the package.xml
* @param string
* @return string
*/
function getFileContents($file)
{
if ($this->_archiveFile == $this->_packageFile) { // unpacked
$dir = dirname($this->_packageFile);
$file = $dir . DIRECTORY_SEPARATOR . $file;
$file = str_replace(array('/', '\\'),
array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file);
if (file_exists($file) && is_readable($file)) {
return implode('', file($file));
}
} else { // tgz
if (!class_exists('Archive_Tar')) {
require_once 'Archive/Tar.php';
}
$tar = &new Archive_Tar($this->_archiveFile);
$tar->pushErrorHandling(PEAR_ERROR_RETURN);
if ($file != 'package.xml' && $file != 'package2.xml') {
$file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file;
}
$file = $tar->extractInString($file);
$tar->popErrorHandling();
if (PEAR::isError($file)) {
return PEAR::raiseError("Cannot locate file '$file' in archive");
}
return $file;
}
}
 
// {{{ analyzeSourceCode()
/**
* Analyze the source code of the given PHP file
*
* @param string Filename of the PHP file
* @return mixed
* @access private
*/
function _analyzeSourceCode($file)
{
if (!function_exists("token_get_all")) {
return false;
}
if (!defined('T_DOC_COMMENT')) {
define('T_DOC_COMMENT', T_COMMENT);
}
if (!defined('T_INTERFACE')) {
define('T_INTERFACE', -1);
}
if (!defined('T_IMPLEMENTS')) {
define('T_IMPLEMENTS', -1);
}
if (!$fp = @fopen($file, "r")) {
return false;
}
fclose($fp);
$contents = file_get_contents($file);
$tokens = token_get_all($contents);
/*
for ($i = 0; $i < sizeof($tokens); $i++) {
@list($token, $data) = $tokens[$i];
if (is_string($token)) {
var_dump($token);
} else {
print token_name($token) . ' ';
var_dump(rtrim($data));
}
}
*/
$look_for = 0;
$paren_level = 0;
$bracket_level = 0;
$brace_level = 0;
$lastphpdoc = '';
$current_class = '';
$current_interface = '';
$current_class_level = -1;
$current_function = '';
$current_function_level = -1;
$declared_classes = array();
$declared_interfaces = array();
$declared_functions = array();
$declared_methods = array();
$used_classes = array();
$used_functions = array();
$extends = array();
$implements = array();
$nodeps = array();
$inquote = false;
$interface = false;
for ($i = 0; $i < sizeof($tokens); $i++) {
if (is_array($tokens[$i])) {
list($token, $data) = $tokens[$i];
} else {
$token = $tokens[$i];
$data = '';
}
if ($inquote) {
if ($token != '"' && $token != T_END_HEREDOC) {
continue;
} else {
$inquote = false;
continue;
}
}
switch ($token) {
case T_WHITESPACE :
continue;
case ';':
if ($interface) {
$current_function = '';
$current_function_level = -1;
}
break;
case '"':
case T_START_HEREDOC:
$inquote = true;
break;
case T_CURLY_OPEN:
case T_DOLLAR_OPEN_CURLY_BRACES:
case '{': $brace_level++; continue 2;
case '}':
$brace_level--;
if ($current_class_level == $brace_level) {
$current_class = '';
$current_class_level = -1;
}
if ($current_function_level == $brace_level) {
$current_function = '';
$current_function_level = -1;
}
continue 2;
case '[': $bracket_level++; continue 2;
case ']': $bracket_level--; continue 2;
case '(': $paren_level++; continue 2;
case ')': $paren_level--; continue 2;
case T_INTERFACE:
$interface = true;
case T_CLASS:
if (($current_class_level != -1) || ($current_function_level != -1)) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE,
array('file' => $file));
return false;
}
case T_FUNCTION:
case T_NEW:
case T_EXTENDS:
case T_IMPLEMENTS:
$look_for = $token;
continue 2;
case T_STRING:
if (version_compare(zend_version(), '2.0', '<')) {
if (in_array(strtolower($data),
array('public', 'private', 'protected', 'abstract',
'interface', 'implements', 'throw')
)) {
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_PHP5,
array($file));
}
}
if ($look_for == T_CLASS) {
$current_class = $data;
$current_class_level = $brace_level;
$declared_classes[] = $current_class;
} elseif ($look_for == T_INTERFACE) {
$current_interface = $data;
$current_class_level = $brace_level;
$declared_interfaces[] = $current_interface;
} elseif ($look_for == T_IMPLEMENTS) {
$implements[$current_class] = $data;
} elseif ($look_for == T_EXTENDS) {
$extends[$current_class] = $data;
} elseif ($look_for == T_FUNCTION) {
if ($current_class) {
$current_function = "$current_class::$data";
$declared_methods[$current_class][] = $data;
} elseif ($current_interface) {
$current_function = "$current_interface::$data";
$declared_methods[$current_interface][] = $data;
} else {
$current_function = $data;
$declared_functions[] = $current_function;
}
$current_function_level = $brace_level;
$m = array();
} elseif ($look_for == T_NEW) {
$used_classes[$data] = true;
}
$look_for = 0;
continue 2;
case T_VARIABLE:
$look_for = 0;
continue 2;
case T_DOC_COMMENT:
case T_COMMENT:
if (preg_match('!^/\*\*\s!', $data)) {
$lastphpdoc = $data;
if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
$nodeps = array_merge($nodeps, $m[1]);
}
}
continue 2;
case T_DOUBLE_COLON:
if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE,
array('file' => $file));
return false;
}
$class = $tokens[$i - 1][1];
if (strtolower($class) != 'parent') {
$used_classes[$class] = true;
}
continue 2;
}
}
return array(
"source_file" => $file,
"declared_classes" => $declared_classes,
"declared_interfaces" => $declared_interfaces,
"declared_methods" => $declared_methods,
"declared_functions" => $declared_functions,
"used_classes" => array_diff(array_keys($used_classes), $nodeps),
"inheritance" => $extends,
"implements" => $implements,
);
}
 
/**
* Build a "provides" array from data returned by
* analyzeSourceCode(). The format of the built array is like
* this:
*
* array(
* 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
* ...
* )
*
*
* @param array $srcinfo array with information about a source file
* as returned by the analyzeSourceCode() method.
*
* @return void
*
* @access private
*
*/
function _buildProvidesArray($srcinfo)
{
if (!$this->_isValid) {
return false;
}
$file = basename($srcinfo['source_file']);
$pn = $this->getPackage();
$pnl = strlen($pn);
foreach ($srcinfo['declared_classes'] as $class) {
$key = "class;$class";
if (isset($this->_packageInfo['provides'][$key])) {
continue;
}
$this->_packageInfo['provides'][$key] =
array('file'=> $file, 'type' => 'class', 'name' => $class);
if (isset($srcinfo['inheritance'][$class])) {
$this->_packageInfo['provides'][$key]['extends'] =
$srcinfo['inheritance'][$class];
}
}
foreach ($srcinfo['declared_methods'] as $class => $methods) {
foreach ($methods as $method) {
$function = "$class::$method";
$key = "function;$function";
if ($method{0} == '_' || !strcasecmp($method, $class) ||
isset($this->_packageInfo['provides'][$key])) {
continue;
}
$this->_packageInfo['provides'][$key] =
array('file'=> $file, 'type' => 'function', 'name' => $function);
}
}
 
foreach ($srcinfo['declared_functions'] as $function) {
$key = "function;$function";
if ($function{0} == '_' || isset($this->_packageInfo['provides'][$key])) {
continue;
}
if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
$warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
}
$this->_packageInfo['provides'][$key] =
array('file'=> $file, 'type' => 'function', 'name' => $function);
}
}
 
// }}}
}
?>
/trunk/bibliotheque/pear/PEAR/PackageFile/v2.php
New file
0,0 → 1,2039
<?php
/**
* PEAR_PackageFile_v2, package.xml version 2.0
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: v2.php,v 1.136 2007/02/20 00:16:12 cellog Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* For error handling
*/
require_once 'PEAR/ErrorStack.php';
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.5.1
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_PackageFile_v2
{
 
/**
* Parsed package information
* @var array
* @access private
*/
var $_packageInfo = array();
 
/**
* path to package .tgz or false if this is a local/extracted package.xml
* @var string|false
* @access private
*/
var $_archiveFile;
 
/**
* path to package .xml or false if this is an abstract parsed-from-string xml
* @var string|false
* @access private
*/
var $_packageFile;
 
/**
* This is used by file analysis routines to log progress information
* @var PEAR_Common
* @access protected
*/
var $_logger;
 
/**
* This is set to the highest validation level that has been validated
*
* If the package.xml is invalid or unknown, this is set to 0. If
* normal validation has occurred, this is set to PEAR_VALIDATE_NORMAL. If
* downloading/installation validation has occurred it is set to PEAR_VALIDATE_DOWNLOADING
* or INSTALLING, and so on up to PEAR_VALIDATE_PACKAGING. This allows validation
* "caching" to occur, which is particularly important for package validation, so
* that PHP files are not validated twice
* @var int
* @access private
*/
var $_isValid = 0;
 
/**
* True if the filelist has been validated
* @param bool
*/
var $_filesValid = false;
 
/**
* @var PEAR_Registry
* @access protected
*/
var $_registry;
 
/**
* @var PEAR_Config
* @access protected
*/
var $_config;
 
/**
* Optional Dependency group requested for installation
* @var string
* @access private
*/
var $_requestedGroup = false;
 
/**
* @var PEAR_ErrorStack
* @access protected
*/
var $_stack;
 
/**
* Namespace prefix used for tasks in this package.xml - use tasks: whenever possible
*/
var $_tasksNs;
 
/**
* Determines whether this packagefile was initialized only with partial package info
*
* If this package file was constructed via parsing REST, it will only contain
*
* - package name
* - channel name
* - dependencies
* @var boolean
* @access private
*/
var $_incomplete = true;
 
/**
* @var PEAR_PackageFile_v2_Validator
*/
var $_v2Validator;
 
/**
* The constructor merely sets up the private error stack
*/
function PEAR_PackageFile_v2()
{
$this->_stack = new PEAR_ErrorStack('PEAR_PackageFile_v2', false, null);
$this->_isValid = false;
}
 
/**
* To make unit-testing easier
* @param PEAR_Frontend_*
* @param array options
* @param PEAR_Config
* @return PEAR_Downloader
* @access protected
*/
function &getPEARDownloader(&$i, $o, &$c)
{
$z = &new PEAR_Downloader($i, $o, $c);
return $z;
}
 
/**
* To make unit-testing easier
* @param PEAR_Config
* @param array options
* @param array package name as returned from {@link PEAR_Registry::parsePackageName()}
* @param int PEAR_VALIDATE_* constant
* @return PEAR_Dependency2
* @access protected
*/
function &getPEARDependency2(&$c, $o, $p, $s = PEAR_VALIDATE_INSTALLING)
{
if (!class_exists('PEAR_Dependency2')) {
require_once 'PEAR/Dependency2.php';
}
$z = &new PEAR_Dependency2($c, $o, $p, $s);
return $z;
}
 
function getInstalledBinary()
{
return isset($this->_packageInfo['#binarypackage']) ? $this->_packageInfo['#binarypackage'] :
false;
}
 
/**
* Installation of source package has failed, attempt to download and install the
* binary version of this package.
* @param PEAR_Installer
* @return array|false
*/
function installBinary(&$installer)
{
if (!OS_WINDOWS) {
$a = false;
return $a;
}
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
$releasetype = $this->getPackageType() . 'release';
if (!is_array($installer->getInstallPackages())) {
$a = false;
return $a;
}
foreach ($installer->getInstallPackages() as $p) {
if ($p->isExtension($this->_packageInfo['providesextension'])) {
if ($p->getPackageType() != 'extsrc' && $p->getPackageType() != 'zendextsrc') {
$a = false;
return $a; // the user probably downloaded it separately
}
}
}
if (isset($this->_packageInfo[$releasetype]['binarypackage'])) {
$installer->log(0, 'Attempting to download binary version of extension "' .
$this->_packageInfo['providesextension'] . '"');
$params = $this->_packageInfo[$releasetype]['binarypackage'];
if (!is_array($params) || !isset($params[0])) {
$params = array($params);
}
if (isset($this->_packageInfo['channel'])) {
foreach ($params as $i => $param) {
$params[$i] = array('channel' => $this->_packageInfo['channel'],
'package' => $param, 'version' => $this->getVersion());
}
}
$dl = &$this->getPEARDownloader($installer->ui, $installer->getOptions(),
$installer->config);
$verbose = $dl->config->get('verbose');
$dl->config->set('verbose', -1);
foreach ($params as $param) {
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$ret = $dl->download(array($param));
PEAR::popErrorHandling();
if (is_array($ret) && count($ret)) {
break;
}
}
$dl->config->set('verbose', $verbose);
if (is_array($ret)) {
if (count($ret) == 1) {
$pf = $ret[0]->getPackageFile();
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$err = $installer->install($ret[0]);
PEAR::popErrorHandling();
if (is_array($err)) {
$this->_packageInfo['#binarypackage'] = $ret[0]->getPackage();
// "install" self, so all dependencies will work transparently
$this->_registry->addPackage2($this);
$installer->log(0, 'Download and install of binary extension "' .
$this->_registry->parsedPackageNameToString(
array('channel' => $pf->getChannel(),
'package' => $pf->getPackage()), true) . '" successful');
$a = array($ret[0], $err);
return $a;
}
$installer->log(0, 'Download and install of binary extension "' .
$this->_registry->parsedPackageNameToString(
array('channel' => $pf->getChannel(),
'package' => $pf->getPackage()), true) . '" failed');
}
}
}
}
$a = false;
return $a;
}
 
/**
* @return string|false Extension name
*/
function getProvidesExtension()
{
if (in_array($this->getPackageType(),
array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
if (isset($this->_packageInfo['providesextension'])) {
return $this->_packageInfo['providesextension'];
}
}
return false;
}
 
/**
* @param string Extension name
* @return bool
*/
function isExtension($extension)
{
if (in_array($this->getPackageType(),
array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
return $this->_packageInfo['providesextension'] == $extension;
}
return false;
}
 
/**
* Tests whether every part of the package.xml 1.0 is represented in
* this package.xml 2.0
* @param PEAR_PackageFile_v1
* @return bool
*/
function isEquivalent($pf1)
{
if (!$pf1) {
return true;
}
if ($this->getPackageType() == 'bundle') {
return false;
}
$this->_stack->getErrors(true);
if (!$pf1->validate(PEAR_VALIDATE_NORMAL)) {
return false;
}
$pass = true;
if ($pf1->getPackage() != $this->getPackage()) {
$this->_differentPackage($pf1->getPackage());
$pass = false;
}
if ($pf1->getVersion() != $this->getVersion()) {
$this->_differentVersion($pf1->getVersion());
$pass = false;
}
if (trim($pf1->getSummary()) != $this->getSummary()) {
$this->_differentSummary($pf1->getSummary());
$pass = false;
}
if (preg_replace('/\s+/', '', $pf1->getDescription()) !=
preg_replace('/\s+/', '', $this->getDescription())) {
$this->_differentDescription($pf1->getDescription());
$pass = false;
}
if ($pf1->getState() != $this->getState()) {
$this->_differentState($pf1->getState());
$pass = false;
}
if (!strstr(preg_replace('/\s+/', '', $this->getNotes()),
preg_replace('/\s+/', '', $pf1->getNotes()))) {
$this->_differentNotes($pf1->getNotes());
$pass = false;
}
$mymaintainers = $this->getMaintainers();
$yourmaintainers = $pf1->getMaintainers();
for ($i1 = 0; $i1 < count($yourmaintainers); $i1++) {
$reset = false;
for ($i2 = 0; $i2 < count($mymaintainers); $i2++) {
if ($mymaintainers[$i2]['handle'] == $yourmaintainers[$i1]['handle']) {
if ($mymaintainers[$i2]['role'] != $yourmaintainers[$i1]['role']) {
$this->_differentRole($mymaintainers[$i2]['handle'],
$yourmaintainers[$i1]['role'], $mymaintainers[$i2]['role']);
$pass = false;
}
if ($mymaintainers[$i2]['email'] != $yourmaintainers[$i1]['email']) {
$this->_differentEmail($mymaintainers[$i2]['handle'],
$yourmaintainers[$i1]['email'], $mymaintainers[$i2]['email']);
$pass = false;
}
if ($mymaintainers[$i2]['name'] != $yourmaintainers[$i1]['name']) {
$this->_differentName($mymaintainers[$i2]['handle'],
$yourmaintainers[$i1]['name'], $mymaintainers[$i2]['name']);
$pass = false;
}
unset($mymaintainers[$i2]);
$mymaintainers = array_values($mymaintainers);
unset($yourmaintainers[$i1]);
$yourmaintainers = array_values($yourmaintainers);
$reset = true;
break;
}
}
if ($reset) {
$i1 = -1;
}
}
$this->_unmatchedMaintainers($mymaintainers, $yourmaintainers);
$filelist = $this->getFilelist();
foreach ($pf1->getFilelist() as $file => $atts) {
if (!isset($filelist[$file])) {
$this->_missingFile($file);
$pass = false;
}
}
return $pass;
}
 
function _differentPackage($package)
{
$this->_stack->push(__FUNCTION__, 'error', array('package' => $package,
'self' => $this->getPackage()),
'package.xml 1.0 package "%package%" does not match "%self%"');
}
 
function _differentVersion($version)
{
$this->_stack->push(__FUNCTION__, 'error', array('version' => $version,
'self' => $this->getVersion()),
'package.xml 1.0 version "%version%" does not match "%self%"');
}
 
function _differentState($state)
{
$this->_stack->push(__FUNCTION__, 'error', array('state' => $state,
'self' => $this->getState()),
'package.xml 1.0 state "%state%" does not match "%self%"');
}
 
function _differentRole($handle, $role, $selfrole)
{
$this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
'role' => $role, 'self' => $selfrole),
'package.xml 1.0 maintainer "%handle%" role "%role%" does not match "%self%"');
}
 
function _differentEmail($handle, $email, $selfemail)
{
$this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
'email' => $email, 'self' => $selfemail),
'package.xml 1.0 maintainer "%handle%" email "%email%" does not match "%self%"');
}
 
function _differentName($handle, $name, $selfname)
{
$this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
'name' => $name, 'self' => $selfname),
'package.xml 1.0 maintainer "%handle%" name "%name%" does not match "%self%"');
}
 
function _unmatchedMaintainers($my, $yours)
{
if ($my) {
array_walk($my, create_function('&$i, $k', '$i = $i["handle"];'));
$this->_stack->push(__FUNCTION__, 'error', array('handles' => $my),
'package.xml 2.0 has unmatched extra maintainers "%handles%"');
}
if ($yours) {
array_walk($yours, create_function('&$i, $k', '$i = $i["handle"];'));
$this->_stack->push(__FUNCTION__, 'error', array('handles' => $yours),
'package.xml 1.0 has unmatched extra maintainers "%handles%"');
}
}
 
function _differentNotes($notes)
{
$truncnotes = strlen($notes) < 25 ? $notes : substr($notes, 0, 24) . '...';
$truncmynotes = strlen($this->getNotes()) < 25 ? $this->getNotes() :
substr($this->getNotes(), 0, 24) . '...';
$this->_stack->push(__FUNCTION__, 'error', array('notes' => $truncnotes,
'self' => $truncmynotes),
'package.xml 1.0 release notes "%notes%" do not match "%self%"');
}
 
function _differentSummary($summary)
{
$truncsummary = strlen($summary) < 25 ? $summary : substr($summary, 0, 24) . '...';
$truncmysummary = strlen($this->getsummary()) < 25 ? $this->getSummary() :
substr($this->getsummary(), 0, 24) . '...';
$this->_stack->push(__FUNCTION__, 'error', array('summary' => $truncsummary,
'self' => $truncmysummary),
'package.xml 1.0 summary "%summary%" does not match "%self%"');
}
 
function _differentDescription($description)
{
$truncdescription = trim(strlen($description) < 25 ? $description : substr($description, 0, 24) . '...');
$truncmydescription = trim(strlen($this->getDescription()) < 25 ? $this->getDescription() :
substr($this->getdescription(), 0, 24) . '...');
$this->_stack->push(__FUNCTION__, 'error', array('description' => $truncdescription,
'self' => $truncmydescription),
'package.xml 1.0 description "%description%" does not match "%self%"');
}
 
function _missingFile($file)
{
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
'package.xml 1.0 file "%file%" is not present in <contents>');
}
 
/**
* WARNING - do not use this function unless you know what you're doing
*/
function setRawState($state)
{
$this->_packageInfo['stability']['release'] = $state;
}
 
/**
* WARNING - do not use this function unless you know what you're doing
*/
function setRawCompatible($compatible)
{
$this->_packageInfo['compatible'] = $compatible;
}
 
/**
* WARNING - do not use this function unless you know what you're doing
*/
function setRawPackage($package)
{
$this->_packageInfo['name'] = $package;
}
 
/**
* WARNING - do not use this function unless you know what you're doing
*/
function setRawChannel($channel)
{
$this->_packageInfo['channel'] = $channel;
}
 
function setRequestedGroup($group)
{
$this->_requestedGroup = $group;
}
 
function getRequestedGroup()
{
if (isset($this->_requestedGroup)) {
return $this->_requestedGroup;
}
return false;
}
 
/**
* For saving in the registry.
*
* Set the last version that was installed
* @param string
*/
function setLastInstalledVersion($version)
{
$this->_packageInfo['_lastversion'] = $version;
}
 
/**
* @return string|false
*/
function getLastInstalledVersion()
{
if (isset($this->_packageInfo['_lastversion'])) {
return $this->_packageInfo['_lastversion'];
}
return false;
}
 
/**
* Determines whether this package.xml has post-install scripts or not
* @return array|false
*/
function listPostinstallScripts()
{
$filelist = $this->getFilelist();
$contents = $this->getContents();
$contents = $contents['dir']['file'];
if (!is_array($contents) || !isset($contents[0])) {
$contents = array($contents);
}
$taskfiles = array();
foreach ($contents as $file) {
$atts = $file['attribs'];
unset($file['attribs']);
if (count($file)) {
$taskfiles[$atts['name']] = $file;
}
}
$common = new PEAR_Common;
$common->debug = $this->_config->get('verbose');
$this->_scripts = array();
$ret = array();
foreach ($taskfiles as $name => $tasks) {
if (!isset($filelist[$name])) {
// ignored files will not be in the filelist
continue;
}
$atts = $filelist[$name];
foreach ($tasks as $tag => $raw) {
$task = $this->getTask($tag);
$task = &new $task($this->_config, $common, PEAR_TASK_INSTALL);
if ($task->isScript()) {
$ret[] = $filelist[$name]['installed_as'];
}
}
}
if (count($ret)) {
return $ret;
}
return false;
}
 
/**
* Initialize post-install scripts for running
*
* This method can be used to detect post-install scripts, as the return value
* indicates whether any exist
* @return bool
*/
function initPostinstallScripts()
{
$filelist = $this->getFilelist();
$contents = $this->getContents();
$contents = $contents['dir']['file'];
if (!is_array($contents) || !isset($contents[0])) {
$contents = array($contents);
}
$taskfiles = array();
foreach ($contents as $file) {
$atts = $file['attribs'];
unset($file['attribs']);
if (count($file)) {
$taskfiles[$atts['name']] = $file;
}
}
$common = new PEAR_Common;
$common->debug = $this->_config->get('verbose');
$this->_scripts = array();
foreach ($taskfiles as $name => $tasks) {
if (!isset($filelist[$name])) {
// file was not installed due to installconditions
continue;
}
$atts = $filelist[$name];
foreach ($tasks as $tag => $raw) {
$taskname = $this->getTask($tag);
$task = &new $taskname($this->_config, $common, PEAR_TASK_INSTALL);
if (!$task->isScript()) {
continue; // scripts are only handled after installation
}
$lastversion = isset($this->_packageInfo['_lastversion']) ?
$this->_packageInfo['_lastversion'] : null;
$task->init($raw, $atts, $lastversion);
$res = $task->startSession($this, $atts['installed_as']);
if (!$res) {
continue; // skip this file
}
if (PEAR::isError($res)) {
return $res;
}
$assign = &$task;
$this->_scripts[] = &$assign;
}
}
if (count($this->_scripts)) {
return true;
}
return false;
}
 
function runPostinstallScripts()
{
if ($this->initPostinstallScripts()) {
$ui = &PEAR_Frontend::singleton();
if ($ui) {
$ui->runPostinstallScripts($this->_scripts, $this);
}
}
}
 
 
/**
* Convert a recursive set of <dir> and <file> tags into a single <dir> tag with
* <file> tags.
*/
function flattenFilelist()
{
if (isset($this->_packageInfo['bundle'])) {
return;
}
$filelist = array();
if (isset($this->_packageInfo['contents']['dir']['dir'])) {
$this->_getFlattenedFilelist($filelist, $this->_packageInfo['contents']['dir']);
if (!isset($filelist[1])) {
$filelist = $filelist[0];
}
$this->_packageInfo['contents']['dir']['file'] = $filelist;
unset($this->_packageInfo['contents']['dir']['dir']);
} else {
// else already flattened but check for baseinstalldir propagation
if (isset($this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'])) {
if (isset($this->_packageInfo['contents']['dir']['file'][0])) {
foreach ($this->_packageInfo['contents']['dir']['file'] as $i => $file) {
if (isset($file['attribs']['baseinstalldir'])) {
continue;
}
$this->_packageInfo['contents']['dir']['file'][$i]['attribs']['baseinstalldir']
= $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
}
} else {
if (!isset($this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'])) {
$this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir']
= $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
}
}
}
}
}
 
/**
* @param array the final flattened file list
* @param array the current directory being processed
* @param string|false any recursively inherited baeinstalldir attribute
* @param string private recursion variable
* @return array
* @access protected
*/
function _getFlattenedFilelist(&$files, $dir, $baseinstall = false, $path = '')
{
if (isset($dir['attribs']) && isset($dir['attribs']['baseinstalldir'])) {
$baseinstall = $dir['attribs']['baseinstalldir'];
}
if (isset($dir['dir'])) {
if (!isset($dir['dir'][0])) {
$dir['dir'] = array($dir['dir']);
}
foreach ($dir['dir'] as $subdir) {
if (!isset($subdir['attribs']) || !isset($subdir['attribs']['name'])) {
$name = '*unknown*';
} else {
$name = $subdir['attribs']['name'];
}
$newpath = empty($path) ? $name :
$path . '/' . $name;
$this->_getFlattenedFilelist($files, $subdir,
$baseinstall, $newpath);
}
}
if (isset($dir['file'])) {
if (!isset($dir['file'][0])) {
$dir['file'] = array($dir['file']);
}
foreach ($dir['file'] as $file) {
$attrs = $file['attribs'];
$name = $attrs['name'];
if ($baseinstall && !isset($attrs['baseinstalldir'])) {
$attrs['baseinstalldir'] = $baseinstall;
}
$attrs['name'] = empty($path) ? $name : $path . '/' . $name;
$attrs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
$attrs['name']);
$file['attribs'] = $attrs;
$files[] = $file;
}
}
}
 
function setConfig(&$config)
{
$this->_config = &$config;
$this->_registry = &$config->getRegistry();
}
 
function setLogger(&$logger)
{
if (!is_object($logger) || !method_exists($logger, 'log')) {
return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
}
$this->_logger = &$logger;
}
 
/**
* WARNING - do not use this function directly unless you know what you're doing
*/
function setDeps($deps)
{
$this->_packageInfo['dependencies'] = $deps;
}
 
/**
* WARNING - do not use this function directly unless you know what you're doing
*/
function setCompatible($compat)
{
$this->_packageInfo['compatible'] = $compat;
}
 
function setPackagefile($file, $archive = false)
{
$this->_packageFile = $file;
$this->_archiveFile = $archive ? $archive : $file;
}
 
/**
* Wrapper to {@link PEAR_ErrorStack::getErrors()}
* @param boolean determines whether to purge the error stack after retrieving
* @return array
*/
function getValidationWarnings($purge = true)
{
return $this->_stack->getErrors($purge);
}
 
function getPackageFile()
{
return $this->_packageFile;
}
 
function getArchiveFile()
{
return $this->_archiveFile;
}
 
 
/**
* Directly set the array that defines this packagefile
*
* WARNING: no validation. This should only be performed by internal methods
* inside PEAR or by inputting an array saved from an existing PEAR_PackageFile_v2
* @param array
*/
function fromArray($pinfo)
{
unset($pinfo['old']);
unset($pinfo['xsdversion']);
$this->_incomplete = false;
$this->_packageInfo = $pinfo;
}
 
function isIncomplete()
{
return $this->_incomplete;
}
 
/**
* @return array
*/
function toArray($forreg = false)
{
if (!$this->validate(PEAR_VALIDATE_NORMAL)) {
return false;
}
return $this->getArray($forreg);
}
 
function getArray($forReg = false)
{
if ($forReg) {
$arr = $this->_packageInfo;
$arr['old'] = array();
$arr['old']['version'] = $this->getVersion();
$arr['old']['release_date'] = $this->getDate();
$arr['old']['release_state'] = $this->getState();
$arr['old']['release_license'] = $this->getLicense();
$arr['old']['release_notes'] = $this->getNotes();
$arr['old']['release_deps'] = $this->getDeps();
$arr['old']['maintainers'] = $this->getMaintainers();
$arr['xsdversion'] = '2.0';
return $arr;
} else {
$info = $this->_packageInfo;
unset($info['dirtree']);
if (isset($info['_lastversion'])) {
unset($info['_lastversion']);
}
if (isset($info['#binarypackage'])) {
unset($info['#binarypackage']);
}
return $info;
}
}
 
function packageInfo($field)
{
$arr = $this->getArray(true);
if ($field == 'state') {
return $arr['stability']['release'];
}
if ($field == 'api-version') {
return $arr['version']['api'];
}
if ($field == 'api-state') {
return $arr['stability']['api'];
}
if (isset($arr['old'][$field])) {
if (!is_string($arr['old'][$field])) {
return null;
}
return $arr['old'][$field];
}
if (isset($arr[$field])) {
if (!is_string($arr[$field])) {
return null;
}
return $arr[$field];
}
return null;
}
 
function getName()
{
return $this->getPackage();
}
 
function getPackage()
{
if (isset($this->_packageInfo['name'])) {
return $this->_packageInfo['name'];
}
return false;
}
 
function getChannel()
{
if (isset($this->_packageInfo['uri'])) {
return '__uri';
}
if (isset($this->_packageInfo['channel'])) {
return strtolower($this->_packageInfo['channel']);
}
return false;
}
 
function getUri()
{
if (isset($this->_packageInfo['uri'])) {
return $this->_packageInfo['uri'];
}
return false;
}
 
function getExtends()
{
if (isset($this->_packageInfo['extends'])) {
return $this->_packageInfo['extends'];
}
return false;
}
 
function getSummary()
{
if (isset($this->_packageInfo['summary'])) {
return $this->_packageInfo['summary'];
}
return false;
}
 
function getDescription()
{
if (isset($this->_packageInfo['description'])) {
return $this->_packageInfo['description'];
}
return false;
}
 
function getMaintainers($raw = false)
{
if (!isset($this->_packageInfo['lead'])) {
return false;
}
if ($raw) {
$ret = array('lead' => $this->_packageInfo['lead']);
(isset($this->_packageInfo['developer'])) ?
$ret['developer'] = $this->_packageInfo['developer'] :null;
(isset($this->_packageInfo['contributor'])) ?
$ret['contributor'] = $this->_packageInfo['contributor'] :null;
(isset($this->_packageInfo['helper'])) ?
$ret['helper'] = $this->_packageInfo['helper'] :null;
return $ret;
} else {
$ret = array();
$leads = isset($this->_packageInfo['lead'][0]) ? $this->_packageInfo['lead'] :
array($this->_packageInfo['lead']);
foreach ($leads as $lead) {
$s = $lead;
$s['handle'] = $s['user'];
unset($s['user']);
$s['role'] = 'lead';
$ret[] = $s;
}
if (isset($this->_packageInfo['developer'])) {
$leads = isset($this->_packageInfo['developer'][0]) ?
$this->_packageInfo['developer'] :
array($this->_packageInfo['developer']);
foreach ($leads as $maintainer) {
$s = $maintainer;
$s['handle'] = $s['user'];
unset($s['user']);
$s['role'] = 'developer';
$ret[] = $s;
}
}
if (isset($this->_packageInfo['contributor'])) {
$leads = isset($this->_packageInfo['contributor'][0]) ?
$this->_packageInfo['contributor'] :
array($this->_packageInfo['contributor']);
foreach ($leads as $maintainer) {
$s = $maintainer;
$s['handle'] = $s['user'];
unset($s['user']);
$s['role'] = 'contributor';
$ret[] = $s;
}
}
if (isset($this->_packageInfo['helper'])) {
$leads = isset($this->_packageInfo['helper'][0]) ?
$this->_packageInfo['helper'] :
array($this->_packageInfo['helper']);
foreach ($leads as $maintainer) {
$s = $maintainer;
$s['handle'] = $s['user'];
unset($s['user']);
$s['role'] = 'helper';
$ret[] = $s;
}
}
return $ret;
}
return false;
}
 
function getLeads()
{
if (isset($this->_packageInfo['lead'])) {
return $this->_packageInfo['lead'];
}
return false;
}
 
function getDevelopers()
{
if (isset($this->_packageInfo['developer'])) {
return $this->_packageInfo['developer'];
}
return false;
}
 
function getContributors()
{
if (isset($this->_packageInfo['contributor'])) {
return $this->_packageInfo['contributor'];
}
return false;
}
 
function getHelpers()
{
if (isset($this->_packageInfo['helper'])) {
return $this->_packageInfo['helper'];
}
return false;
}
 
function setDate($date)
{
if (!isset($this->_packageInfo['date'])) {
// ensure that the extends tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('time', 'version',
'stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
'zendextbinrelease', 'bundle', 'changelog'), array(), 'date');
}
$this->_packageInfo['date'] = $date;
$this->_isValid = 0;
}
 
function setTime($time)
{
$this->_isValid = 0;
if (!isset($this->_packageInfo['time'])) {
// ensure that the time tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('version',
'stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
'zendextbinrelease', 'bundle', 'changelog'), $time, 'time');
}
$this->_packageInfo['time'] = $time;
}
 
function getDate()
{
if (isset($this->_packageInfo['date'])) {
return $this->_packageInfo['date'];
}
return false;
}
 
function getTime()
{
if (isset($this->_packageInfo['time'])) {
return $this->_packageInfo['time'];
}
return false;
}
 
/**
* @param package|api version category to return
*/
function getVersion($key = 'release')
{
if (isset($this->_packageInfo['version'][$key])) {
return $this->_packageInfo['version'][$key];
}
return false;
}
 
function getStability()
{
if (isset($this->_packageInfo['stability'])) {
return $this->_packageInfo['stability'];
}
return false;
}
 
function getState($key = 'release')
{
if (isset($this->_packageInfo['stability'][$key])) {
return $this->_packageInfo['stability'][$key];
}
return false;
}
 
function getLicense($raw = false)
{
if (isset($this->_packageInfo['license'])) {
if ($raw) {
return $this->_packageInfo['license'];
}
if (is_array($this->_packageInfo['license'])) {
return $this->_packageInfo['license']['_content'];
} else {
return $this->_packageInfo['license'];
}
}
return false;
}
 
function getLicenseLocation()
{
if (!isset($this->_packageInfo['license']) || !is_array($this->_packageInfo['license'])) {
return false;
}
return $this->_packageInfo['license']['attribs'];
}
 
function getNotes()
{
if (isset($this->_packageInfo['notes'])) {
return $this->_packageInfo['notes'];
}
return false;
}
 
/**
* Return the <usesrole> tag contents, if any
* @return array|false
*/
function getUsesrole()
{
if (isset($this->_packageInfo['usesrole'])) {
return $this->_packageInfo['usesrole'];
}
return false;
}
 
/**
* Return the <usestask> tag contents, if any
* @return array|false
*/
function getUsestask()
{
if (isset($this->_packageInfo['usestask'])) {
return $this->_packageInfo['usestask'];
}
return false;
}
 
/**
* This should only be used to retrieve filenames and install attributes
*/
function getFilelist($preserve = false)
{
if (isset($this->_packageInfo['filelist']) && !$preserve) {
return $this->_packageInfo['filelist'];
}
$this->flattenFilelist();
if ($contents = $this->getContents()) {
$ret = array();
if (!isset($contents['dir']['file'][0])) {
$contents['dir']['file'] = array($contents['dir']['file']);
}
foreach ($contents['dir']['file'] as $file) {
$name = $file['attribs']['name'];
if (!$preserve) {
$file = $file['attribs'];
}
$ret[$name] = $file;
}
if (!$preserve) {
$this->_packageInfo['filelist'] = $ret;
}
return $ret;
}
return false;
}
 
/**
* Return configure options array, if any
*
* @return array|false
*/
function getConfigureOptions()
{
if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
return false;
}
$releases = $this->getReleases();
if (isset($releases[0])) {
$releases = $releases[0];
}
if (isset($releases['configureoption'])) {
if (!isset($releases['configureoption'][0])) {
$releases['configureoption'] = array($releases['configureoption']);
}
for ($i = 0; $i < count($releases['configureoption']); $i++) {
$releases['configureoption'][$i] = $releases['configureoption'][$i]['attribs'];
}
return $releases['configureoption'];
}
return false;
}
 
/**
* This is only used at install-time, after all serialization
* is over.
*/
function resetFilelist()
{
$this->_packageInfo['filelist'] = array();
}
 
/**
* Retrieve a list of files that should be installed on this computer
* @return array
*/
function getInstallationFilelist($forfilecheck = false)
{
$contents = $this->getFilelist(true);
if (isset($contents['dir']['attribs']['baseinstalldir'])) {
$base = $contents['dir']['attribs']['baseinstalldir'];
}
if (isset($this->_packageInfo['bundle'])) {
return PEAR::raiseError(
'Exception: bundles should be handled in download code only');
}
$release = $this->getReleases();
if ($release) {
if (!isset($release[0])) {
if (!isset($release['installconditions']) && !isset($release['filelist'])) {
if ($forfilecheck) {
return $this->getFilelist();
}
return $contents;
}
$release = array($release);
}
$depchecker = &$this->getPEARDependency2($this->_config, array(),
array('channel' => $this->getChannel(), 'package' => $this->getPackage()),
PEAR_VALIDATE_INSTALLING);
foreach ($release as $instance) {
if (isset($instance['installconditions'])) {
$installconditions = $instance['installconditions'];
if (is_array($installconditions)) {
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
foreach ($installconditions as $type => $conditions) {
if (!isset($conditions[0])) {
$conditions = array($conditions);
}
foreach ($conditions as $condition) {
$ret = $depchecker->{"validate{$type}Dependency"}($condition);
if (PEAR::isError($ret)) {
PEAR::popErrorHandling();
continue 3; // skip this release
}
}
}
PEAR::popErrorHandling();
}
}
// this is the release to use
if (isset($instance['filelist'])) {
// ignore files
if (isset($instance['filelist']['ignore'])) {
$ignore = isset($instance['filelist']['ignore'][0]) ?
$instance['filelist']['ignore'] :
array($instance['filelist']['ignore']);
foreach ($ignore as $ig) {
unset ($contents[$ig['attribs']['name']]);
}
}
// install files as this name
if (isset($instance['filelist']['install'])) {
$installas = isset($instance['filelist']['install'][0]) ?
$instance['filelist']['install'] :
array($instance['filelist']['install']);
foreach ($installas as $as) {
$contents[$as['attribs']['name']]['attribs']['install-as'] =
$as['attribs']['as'];
}
}
}
if ($forfilecheck) {
foreach ($contents as $file => $attrs) {
$contents[$file] = $attrs['attribs'];
}
}
return $contents;
}
} else { // simple release - no installconditions or install-as
if ($forfilecheck) {
return $this->getFilelist();
}
return $contents;
}
// no releases matched
return PEAR::raiseError('No releases in package.xml matched the existing operating ' .
'system, extensions installed, or architecture, cannot install');
}
 
/**
* This is only used at install-time, after all serialization
* is over.
* @param string file name
* @param string installed path
*/
function setInstalledAs($file, $path)
{
if ($path) {
return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
}
unset($this->_packageInfo['filelist'][$file]['installed_as']);
}
 
function getInstalledLocation($file)
{
if (isset($this->_packageInfo['filelist'][$file]['installed_as'])) {
return $this->_packageInfo['filelist'][$file]['installed_as'];
}
return false;
}
 
/**
* This is only used at install-time, after all serialization
* is over.
*/
function installedFile($file, $atts)
{
if (isset($this->_packageInfo['filelist'][$file])) {
$this->_packageInfo['filelist'][$file] =
array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']);
} else {
$this->_packageInfo['filelist'][$file] = $atts['attribs'];
}
}
 
/**
* Retrieve the contents tag
*/
function getContents()
{
if (isset($this->_packageInfo['contents'])) {
return $this->_packageInfo['contents'];
}
return false;
}
 
/**
* @param string full path to file
* @param string attribute name
* @param string attribute value
* @param int risky but fast - use this to choose a file based on its position in the list
* of files. Index is zero-based like PHP arrays.
* @return bool success of operation
*/
function setFileAttribute($filename, $attr, $value, $index = false)
{
$this->_isValid = 0;
if (in_array($attr, array('role', 'name', 'baseinstalldir'))) {
$this->_filesValid = false;
}
if ($index !== false &&
isset($this->_packageInfo['contents']['dir']['file'][$index]['attribs'])) {
$this->_packageInfo['contents']['dir']['file'][$index]['attribs'][$attr] = $value;
return true;
}
if (!isset($this->_packageInfo['contents']['dir']['file'])) {
return false;
}
$files = $this->_packageInfo['contents']['dir']['file'];
if (!isset($files[0])) {
$files = array($files);
$ind = false;
} else {
$ind = true;
}
foreach ($files as $i => $file) {
if (isset($file['attribs'])) {
if ($file['attribs']['name'] == $filename) {
if ($ind) {
$this->_packageInfo['contents']['dir']['file'][$i]['attribs'][$attr] = $value;
} else {
$this->_packageInfo['contents']['dir']['file']['attribs'][$attr] = $value;
}
return true;
}
}
}
return false;
}
 
function setDirtree($path)
{
if (!isset($this->_packageInfo['dirtree'])) {
$this->_packageInfo['dirtree'] = array();
}
$this->_packageInfo['dirtree'][$path] = true;
}
 
function getDirtree()
{
if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) {
return $this->_packageInfo['dirtree'];
}
return false;
}
 
function resetDirtree()
{
unset($this->_packageInfo['dirtree']);
}
 
/**
* Determines whether this package claims it is compatible with the version of
* the package that has a recommended version dependency
* @param PEAR_PackageFile_v2|PEAR_PackageFile_v1|PEAR_Downloader_Package
* @return boolean
*/
function isCompatible($pf)
{
if (!isset($this->_packageInfo['compatible'])) {
return false;
}
if (!isset($this->_packageInfo['channel'])) {
return false;
}
$me = $pf->getVersion();
$compatible = $this->_packageInfo['compatible'];
if (!isset($compatible[0])) {
$compatible = array($compatible);
}
$found = false;
foreach ($compatible as $info) {
if (strtolower($info['name']) == strtolower($pf->getPackage())) {
if (strtolower($info['channel']) == strtolower($pf->getChannel())) {
$found = true;
break;
}
}
}
if (!$found) {
return false;
}
if (isset($info['exclude'])) {
if (!isset($info['exclude'][0])) {
$info['exclude'] = array($info['exclude']);
}
foreach ($info['exclude'] as $exclude) {
if (version_compare($me, $exclude, '==')) {
return false;
}
}
}
if (version_compare($me, $info['min'], '>=') && version_compare($me, $info['max'], '<=')) {
return true;
}
return false;
}
 
/**
* @return array|false
*/
function getCompatible()
{
if (isset($this->_packageInfo['compatible'])) {
return $this->_packageInfo['compatible'];
}
return false;
}
 
function getDependencies()
{
if (isset($this->_packageInfo['dependencies'])) {
return $this->_packageInfo['dependencies'];
}
return false;
}
 
function isSubpackageOf($p)
{
return $p->isSubpackage($this);
}
 
/**
* Determines whether the passed in package is a subpackage of this package.
*
* No version checking is done, only name verification.
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @return bool
*/
function isSubpackage($p)
{
$sub = array();
if (isset($this->_packageInfo['dependencies']['required']['subpackage'])) {
$sub = $this->_packageInfo['dependencies']['required']['subpackage'];
if (!isset($sub[0])) {
$sub = array($sub);
}
}
if (isset($this->_packageInfo['dependencies']['optional']['subpackage'])) {
$sub1 = $this->_packageInfo['dependencies']['optional']['subpackage'];
if (!isset($sub1[0])) {
$sub1 = array($sub1);
}
$sub = array_merge($sub, $sub1);
}
if (isset($this->_packageInfo['dependencies']['group'])) {
$group = $this->_packageInfo['dependencies']['group'];
if (!isset($group[0])) {
$group = array($group);
}
foreach ($group as $deps) {
if (isset($deps['subpackage'])) {
$sub2 = $deps['subpackage'];
if (!isset($sub2[0])) {
$sub2 = array($sub2);
}
$sub = array_merge($sub, $sub2);
}
}
}
foreach ($sub as $dep) {
if (strtolower($dep['name']) == strtolower($p->getPackage())) {
if (isset($dep['channel'])) {
if (strtolower($dep['channel']) == strtolower($p->getChannel())) {
return true;
}
} else {
if ($dep['uri'] == $p->getURI()) {
return true;
}
}
}
}
return false;
}
 
function dependsOn($package, $channel)
{
if (!($deps = $this->getDependencies())) {
return false;
}
foreach (array('package', 'subpackage') as $type) {
foreach (array('required', 'optional') as $needed) {
if (isset($deps[$needed][$type])) {
if (!isset($deps[$needed][$type][0])) {
$deps[$needed][$type] = array($deps[$needed][$type]);
}
foreach ($deps[$needed][$type] as $dep) {
$depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
if (strtolower($dep['name']) == strtolower($package) &&
$depchannel == $channel) {
return true;
}
}
}
}
if (isset($deps['group'])) {
if (!isset($deps['group'][0])) {
$dep['group'] = array($deps['group']);
}
foreach ($deps['group'] as $group) {
if (isset($group[$type])) {
if (!is_array($group[$type])) {
$group[$type] = array($group[$type]);
}
foreach ($group[$type] as $dep) {
$depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
if (strtolower($dep['name']) == strtolower($package) &&
$depchannel == $channel) {
return true;
}
}
}
}
}
}
return false;
}
 
/**
* Get the contents of a dependency group
* @param string
* @return array|false
*/
function getDependencyGroup($name)
{
$name = strtolower($name);
if (!isset($this->_packageInfo['dependencies']['group'])) {
return false;
}
$groups = $this->_packageInfo['dependencies']['group'];
if (!isset($groups[0])) {
$groups = array($groups);
}
foreach ($groups as $group) {
if (strtolower($group['attribs']['name']) == $name) {
return $group;
}
}
return false;
}
 
/**
* Retrieve a partial package.xml 1.0 representation of dependencies
*
* a very limited representation of dependencies is returned by this method.
* The <exclude> tag for excluding certain versions of a dependency is
* completely ignored. In addition, dependency groups are ignored, with the
* assumption that all dependencies in dependency groups are also listed in
* the optional group that work with all dependency groups
* @param boolean return package.xml 2.0 <dependencies> tag
* @return array|false
*/
function getDeps($raw = false, $nopearinstaller = false)
{
if (isset($this->_packageInfo['dependencies'])) {
if ($raw) {
return $this->_packageInfo['dependencies'];
}
$ret = array();
$map = array(
'php' => 'php',
'package' => 'pkg',
'subpackage' => 'pkg',
'extension' => 'ext',
'os' => 'os',
'pearinstaller' => 'pkg',
);
foreach (array('required', 'optional') as $type) {
$optional = ($type == 'optional') ? 'yes' : 'no';
if (!isset($this->_packageInfo['dependencies'][$type])) {
continue;
}
foreach ($this->_packageInfo['dependencies'][$type] as $dtype => $deps) {
if ($dtype == 'pearinstaller' && $nopearinstaller) {
continue;
}
if (!isset($deps[0])) {
$deps = array($deps);
}
foreach ($deps as $dep) {
if (!isset($map[$dtype])) {
// no support for arch type
continue;
}
if ($dtype == 'pearinstaller') {
$dep['name'] = 'PEAR';
$dep['channel'] = 'pear.php.net';
}
$s = array('type' => $map[$dtype]);
if (isset($dep['channel'])) {
$s['channel'] = $dep['channel'];
}
if (isset($dep['uri'])) {
$s['uri'] = $dep['uri'];
}
if (isset($dep['name'])) {
$s['name'] = $dep['name'];
}
if (isset($dep['conflicts'])) {
$s['rel'] = 'not';
} else {
if (!isset($dep['min']) &&
!isset($dep['max'])) {
$s['rel'] = 'has';
$s['optional'] = $optional;
} elseif (isset($dep['min']) &&
isset($dep['max'])) {
$s['rel'] = 'ge';
$s1 = $s;
$s1['rel'] = 'le';
$s['version'] = $dep['min'];
$s1['version'] = $dep['max'];
if (isset($dep['channel'])) {
$s1['channel'] = $dep['channel'];
}
if ($dtype != 'php') {
$s['name'] = $dep['name'];
$s1['name'] = $dep['name'];
}
$s['optional'] = $optional;
$s1['optional'] = $optional;
$ret[] = $s1;
} elseif (isset($dep['min'])) {
if (isset($dep['exclude']) &&
$dep['exclude'] == $dep['min']) {
$s['rel'] = 'gt';
} else {
$s['rel'] = 'ge';
}
$s['version'] = $dep['min'];
$s['optional'] = $optional;
if ($dtype != 'php') {
$s['name'] = $dep['name'];
}
} elseif (isset($dep['max'])) {
if (isset($dep['exclude']) &&
$dep['exclude'] == $dep['max']) {
$s['rel'] = 'lt';
} else {
$s['rel'] = 'le';
}
$s['version'] = $dep['max'];
$s['optional'] = $optional;
if ($dtype != 'php') {
$s['name'] = $dep['name'];
}
}
}
$ret[] = $s;
}
}
}
if (count($ret)) {
return $ret;
}
}
return false;
}
 
/**
* @return php|extsrc|extbin|zendextsrc|zendextbin|bundle|false
*/
function getPackageType()
{
if (isset($this->_packageInfo['phprelease'])) {
return 'php';
}
if (isset($this->_packageInfo['extsrcrelease'])) {
return 'extsrc';
}
if (isset($this->_packageInfo['extbinrelease'])) {
return 'extbin';
}
if (isset($this->_packageInfo['zendextsrcrelease'])) {
return 'zendextsrc';
}
if (isset($this->_packageInfo['zendextbinrelease'])) {
return 'zendextbin';
}
if (isset($this->_packageInfo['bundle'])) {
return 'bundle';
}
return false;
}
 
/**
* @return array|false
*/
function getReleases()
{
$type = $this->getPackageType();
if ($type != 'bundle') {
$type .= 'release';
}
if ($this->getPackageType() && isset($this->_packageInfo[$type])) {
return $this->_packageInfo[$type];
}
return false;
}
 
/**
* @return array
*/
function getChangelog()
{
if (isset($this->_packageInfo['changelog'])) {
return $this->_packageInfo['changelog'];
}
return false;
}
 
function hasDeps()
{
return isset($this->_packageInfo['dependencies']);
}
 
function getPackagexmlVersion()
{
if (isset($this->_packageInfo['zendextsrcrelease'])) {
return '2.1';
}
if (isset($this->_packageInfo['zendextbinrelease'])) {
return '2.1';
}
return '2.0';
}
 
/**
* @return array|false
*/
function getSourcePackage()
{
if (isset($this->_packageInfo['extbinrelease']) ||
isset($this->_packageInfo['zendextbinrelease'])) {
return array('channel' => $this->_packageInfo['srcchannel'],
'package' => $this->_packageInfo['srcpackage']);
}
return false;
}
 
function getBundledPackages()
{
if (isset($this->_packageInfo['bundle'])) {
return $this->_packageInfo['contents']['bundledpackage'];
}
return false;
}
 
function getLastModified()
{
if (isset($this->_packageInfo['_lastmodified'])) {
return $this->_packageInfo['_lastmodified'];
}
return false;
}
 
/**
* Get the contents of a file listed within the package.xml
* @param string
* @return string
*/
function getFileContents($file)
{
if ($this->_archiveFile == $this->_packageFile) { // unpacked
$dir = dirname($this->_packageFile);
$file = $dir . DIRECTORY_SEPARATOR . $file;
$file = str_replace(array('/', '\\'),
array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file);
if (file_exists($file) && is_readable($file)) {
return implode('', file($file));
}
} else { // tgz
$tar = &new Archive_Tar($this->_archiveFile);
$tar->pushErrorHandling(PEAR_ERROR_RETURN);
if ($file != 'package.xml' && $file != 'package2.xml') {
$file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file;
}
$file = $tar->extractInString($file);
$tar->popErrorHandling();
if (PEAR::isError($file)) {
return PEAR::raiseError("Cannot locate file '$file' in archive");
}
return $file;
}
}
 
function &getRW()
{
if (!class_exists('PEAR_PackageFile_v2_rw')) {
require_once 'PEAR/PackageFile/v2/rw.php';
}
$a = new PEAR_PackageFile_v2_rw;
foreach (get_object_vars($this) as $name => $unused) {
if (!isset($this->$name)) {
continue;
}
if ($name == '_config' || $name == '_logger'|| $name == '_registry' ||
$name == '_stack') {
$a->$name = &$this->$name;
} else {
$a->$name = $this->$name;
}
}
return $a;
}
 
function &getDefaultGenerator()
{
if (!class_exists('PEAR_PackageFile_Generator_v2')) {
require_once 'PEAR/PackageFile/Generator/v2.php';
}
$a = &new PEAR_PackageFile_Generator_v2($this);
return $a;
}
 
function analyzeSourceCode($file, $string = false)
{
if (!isset($this->_v2Validator) ||
!is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
if (!class_exists('PEAR_PackageFile_v2_Validator')) {
require_once 'PEAR/PackageFile/v2/Validator.php';
}
$this->_v2Validator = new PEAR_PackageFile_v2_Validator;
}
return $this->_v2Validator->analyzeSourceCode($file, $string);
}
 
function validate($state = PEAR_VALIDATE_NORMAL)
{
if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
return false;
}
if (!isset($this->_v2Validator) ||
!is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
if (!class_exists('PEAR_PackageFile_v2_Validator')) {
require_once 'PEAR/PackageFile/v2/Validator.php';
}
$this->_v2Validator = new PEAR_PackageFile_v2_Validator;
}
if (isset($this->_packageInfo['xsdversion'])) {
unset($this->_packageInfo['xsdversion']);
}
return $this->_v2Validator->validate($this, $state);
}
 
function getTasksNs()
{
if (!isset($this->_tasksNs)) {
if (isset($this->_packageInfo['attribs'])) {
foreach ($this->_packageInfo['attribs'] as $name => $value) {
if ($value == 'http://pear.php.net/dtd/tasks-1.0') {
$this->_tasksNs = str_replace('xmlns:', '', $name);
break;
}
}
}
}
return $this->_tasksNs;
}
 
/**
* Determine whether a task name is a valid task. Custom tasks may be defined
* using subdirectories by putting a "-" in the name, as in <tasks:mycustom-task>
*
* Note that this method will auto-load the task class file and test for the existence
* of the name with "-" replaced by "_" as in PEAR/Task/mycustom/task.php makes class
* PEAR_Task_mycustom_task
* @param string
* @return boolean
*/
function getTask($task)
{
$this->getTasksNs();
// transform all '-' to '/' and 'tasks:' to '' so tasks:replace becomes replace
$task = str_replace(array($this->_tasksNs . ':', '-'), array('', ' '), $task);
$task = str_replace(' ', '/', ucwords($task));
$ps = (strtolower(substr(PHP_OS, 0, 3)) == 'win') ? ';' : ':';
foreach (explode($ps, ini_get('include_path')) as $path) {
if (file_exists($path . "/PEAR/Task/$task.php")) {
include_once "PEAR/Task/$task.php";
$task = str_replace('/', '_', $task);
if (class_exists("PEAR_Task_$task")) {
return "PEAR_Task_$task";
}
}
}
return false;
}
 
/**
* Key-friendly array_splice
* @param tagname to splice a value in before
* @param mixed the value to splice in
* @param string the new tag name
*/
function _ksplice($array, $key, $value, $newkey)
{
$offset = array_search($key, array_keys($array));
$after = array_slice($array, $offset);
$before = array_slice($array, 0, $offset);
$before[$newkey] = $value;
return array_merge($before, $after);
}
 
/**
* @param array a list of possible keys, in the order they may occur
* @param mixed contents of the new package.xml tag
* @param string tag name
* @access private
*/
function _insertBefore($array, $keys, $contents, $newkey)
{
foreach ($keys as $key) {
if (isset($array[$key])) {
return $array = $this->_ksplice($array, $key, $contents, $newkey);
}
}
$array[$newkey] = $contents;
return $array;
}
 
/**
* @param subsection of {@link $_packageInfo}
* @param array|string tag contents
* @param array format:
* <pre>
* array(
* tagname => array(list of tag names that follow this one),
* childtagname => array(list of child tag names that follow this one),
* )
* </pre>
*
* This allows construction of nested tags
* @access private
*/
function _mergeTag($manip, $contents, $order)
{
if (count($order)) {
foreach ($order as $tag => $curorder) {
if (!isset($manip[$tag])) {
// ensure that the tag is set up
$manip = $this->_insertBefore($manip, $curorder, array(), $tag);
}
if (count($order) > 1) {
$manip[$tag] = $this->_mergeTag($manip[$tag], $contents, array_slice($order, 1));
return $manip;
}
}
} else {
return $manip;
}
if (is_array($manip[$tag]) && !empty($manip[$tag]) && isset($manip[$tag][0])) {
$manip[$tag][] = $contents;
} else {
if (!count($manip[$tag])) {
$manip[$tag] = $contents;
} else {
$manip[$tag] = array($manip[$tag]);
$manip[$tag][] = $contents;
}
}
return $manip;
}
}
?>