File: /home/boxelikax/public_html/demoltec.com/pear.zip
PK �=]� 2�z z channel.xmlnu �[��� <?xml version="1.0" encoding="ISO-8859-1"?>
<channel version="1.0" xmlns="http://pear.php.net/channel-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/channel-1.0
http://pear.php.net/dtd/channel-1.0.xsd">
<name>pear.php.net</name>
<suggestedalias>pear</suggestedalias>
<summary>PHP Extension and Application Repository</summary>
<servers>
<primary>
<rest>
<baseurl type="REST1.0">http://pear.php.net/rest/</baseurl>
<baseurl type="REST1.1">http://pear.php.net/rest/</baseurl>
<baseurl type="REST1.2">http://pear.php.net/rest/</baseurl>
<baseurl type="REST1.3">http://pear.php.net/rest/</baseurl>
</rest>
</primary>
<mirror host="us.pear.php.net">
<rest>
<baseurl type="REST1.0">http://us.pear.php.net/rest/</baseurl>
<baseurl type="REST1.1">http://us.pear.php.net/rest/</baseurl>
<baseurl type="REST1.2">http://us.pear.php.net/rest/</baseurl>
<baseurl type="REST1.3">http://us.pear.php.net/rest/</baseurl>
</rest>
</mirror>
<mirror host="de.pear.php.net" ssl="yes">
<rest>
<baseurl type="REST1.0">https://de.pear.php.net/rest/</baseurl>
<baseurl type="REST1.1">https://de.pear.php.net/rest/</baseurl>
<baseurl type="REST1.2">https://de.pear.php.net/rest/</baseurl>
<baseurl type="REST1.3">https://de.pear.php.net/rest/</baseurl>
</rest>
</mirror>
</servers>
</channel>
PK �]�f� � XML_Util/examples/example2.phpnu �[��� <?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Examples (file #2)
*
* several examples for the methods of XML_Util
*
* PHP versions 4 and 5
*
* LICENSE:
*
* Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category XML
* @package XML_Util
* @subpackage Examples
* @author Stephan Schmidt <schst@php.net>
* @copyright 2003-2008 Stephan Schmidt <schst@php.net>
* @license http://opensource.org/licenses/bsd-license New BSD License
* @version CVS: $Id$
* @link http://pear.php.net/package/XML_Util
*/
/**
* set error level
*/
error_reporting(E_ALL);
require_once 'XML/Util.php';
/**
* creating a start element
*/
print 'creating a start element:<br>';
print htmlentities(XML_Util::createStartElement('myNs:myTag',
array('foo' => 'bar'), 'http://www.w3c.org/myNs#'));
print "\n<br><br>\n";
/**
* creating a start element
*/
print 'creating a start element:<br>';
print htmlentities(XML_Util::createStartElement('myTag',
array(), 'http://www.w3c.org/myNs#'));
print "\n<br><br>\n";
/**
* creating a start element
*/
print 'creating a start element:<br>';
print '<pre>';
print htmlentities(XML_Util::createStartElement('myTag',
array('foo' => 'bar', 'argh' => 'tomato'),
'http://www.w3c.org/myNs#', true));
print '</pre>';
print "\n<br><br>\n";
/**
* creating an end element
*/
print 'creating an end element:<br>';
print htmlentities(XML_Util::createEndElement('myNs:myTag'));
print "\n<br><br>\n";
/**
* creating a CData section
*/
print 'creating a CData section:<br>';
print htmlentities(XML_Util::createCDataSection('I am content.'));
print "\n<br><br>\n";
/**
* creating a comment
*/
print 'creating a comment:<br>';
print htmlentities(XML_Util::createComment('I am a comment.'));
print "\n<br><br>\n";
/**
* creating an XML tag with multiline mode
*/
$tag = array(
'qname' => 'foo:bar',
'namespaceUri' => 'http://foo.com',
'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'),
'content' => 'I\'m inside the tag & contain dangerous chars'
);
print 'creating a tag with qualified name and namespaceUri:<br>';
print '<pre>';
print htmlentities(XML_Util::createTagFromArray($tag,
XML_UTIL_REPLACE_ENTITIES, true));
print '</pre>';
print "\n<br><br>\n";
/**
* create an attribute string without replacing the entities
*/
$atts = array('series' => 'Starsky & Hutch', 'channel' => 'ABC');
print 'creating a attribute string, '
. 'entities in values already had been replaced:<br>';
print htmlentities(XML_Util::attributesToString($atts,
true, false, false, false, XML_UTIL_ENTITIES_NONE));
print "\n<br><br>\n";
/**
* using the array-syntax for attributesToString()
*/
$atts = array('series' => 'Starsky & Hutch', 'channel' => 'ABC');
print 'using the array-syntax for attributesToString()<br>';
print htmlentities(XML_Util::attributesToString($atts,
array('entities' => XML_UTIL_ENTITIES_NONE)));
print "\n<br><br>\n";
?>
PK �]5k��# �# XML_Util/examples/example.phpnu �[��� <?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Examples (file #1)
*
* several examples for the methods of XML_Util
*
* PHP versions 4 and 5
*
* LICENSE:
*
* Copyright (c) 2003-2008 Stephan Schmidt <schst@php.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category XML
* @package XML_Util
* @subpackage Examples
* @author Stephan Schmidt <schst@php.net>
* @copyright 2003-2008 Stephan Schmidt <schst@php.net>
* @license http://opensource.org/licenses/bsd-license New BSD License
* @version CVS: $Id$
* @link http://pear.php.net/package/XML_Util
*/
/**
* set error level
*/
error_reporting(E_ALL);
require_once 'XML/Util.php';
/**
* replacing XML entities
*/
print 'replace XML entities:<br>';
print XML_Util::replaceEntities('This string contains < & >.');
print "\n<br><br>\n";
/**
* reversing XML entities
*/
print 'replace XML entities:<br>';
print XML_Util::reverseEntities('This string contains < & >.');
print "\n<br><br>\n";
/**
* building XML declaration
*/
print 'building XML declaration:<br>';
print htmlspecialchars(XML_Util::getXMLDeclaration());
print "\n<br><br>\n";
print 'building XML declaration with additional attributes:<br>';
print htmlspecialchars(XML_Util::getXMLDeclaration('1.0', 'UTF-8', true));
print "\n<br><br>\n";
/**
* building document type declaration
*/
print 'building DocType declaration:<br>';
print htmlspecialchars(XML_Util::getDocTypeDeclaration('package',
'http://pear.php.net/dtd/package-1.0'));
print "\n<br><br>\n";
print 'building DocType declaration with public ID (does not exist):<br>';
print htmlspecialchars(XML_Util::getDocTypeDeclaration('package',
array('uri' => 'http://pear.php.net/dtd/package-1.0',
'id' => '-//PHP//PEAR/DTD PACKAGE 0.1')));
print "\n<br><br>\n";
print 'building DocType declaration with internal DTD:<br>';
print '<pre>';
print htmlspecialchars(XML_Util::getDocTypeDeclaration('package',
'http://pear.php.net/dtd/package-1.0',
'<!ELEMENT additionalInfo (#PCDATA)>'));
print '</pre>';
print "\n<br><br>\n";
/**
* creating an attribute string
*/
$att = array(
'foo' => 'bar',
'argh' => 'tomato'
);
print 'converting array to string:<br>';
print XML_Util::attributesToString($att);
print "\n<br><br>\n";
/**
* creating an attribute string with linebreaks
*/
$att = array(
'foo' => 'bar',
'argh' => 'tomato'
);
print 'converting array to string (including line breaks):<br>';
print '<pre>';
print XML_Util::attributesToString($att, true, true);
print '</pre>';
print "\n<br><br>\n";
/**
* splitting a qualified tag name
*/
print 'splitting qualified tag name:<br>';
print '<pre>';
print_r(XML_Util::splitQualifiedName('xslt:stylesheet'));
print '</pre>';
print "\n<br>\n";
/**
* splitting a qualified tag name (no namespace)
*/
print 'splitting qualified tag name (no namespace):<br>';
print '<pre>';
print_r(XML_Util::splitQualifiedName('foo'));
print '</pre>';
print "\n<br>\n";
/**
* splitting a qualified tag name (no namespace, but default namespace specified)
*/
print 'splitting qualified tag name '
. '(no namespace, but default namespace specified):<br>';
print '<pre>';
print_r(XML_Util::splitQualifiedName('foo', 'bar'));
print '</pre>';
print "\n<br>\n";
/**
* verifying XML names
*/
print 'verifying \'My private tag\':<br>';
print '<pre>';
print_r(XML_Util::isValidname('My Private Tag'));
print '</pre>';
print "\n<br><br>\n";
print 'verifying \'-MyTag\':<br>';
print '<pre>';
print_r(XML_Util::isValidname('-MyTag'));
print '</pre>';
print "\n<br><br>\n";
/**
* creating an XML tag
*/
$tag = array(
'namespace' => 'foo',
'localPart' => 'bar',
'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'),
'content' => 'I\'m inside the tag'
);
print 'creating a tag with namespace and local part:<br>';
print htmlentities(XML_Util::createTagFromArray($tag));
print "\n<br><br>\n";
/**
* creating an XML tag
*/
$tag = array(
'qname' => 'foo:bar',
'namespaceUri' => 'http://foo.com',
'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'),
'content' => 'I\'m inside the tag'
);
print 'creating a tag with qualified name and namespaceUri:<br>';
print htmlentities(XML_Util::createTagFromArray($tag));
print "\n<br><br>\n";
/**
* creating an XML tag
*/
$tag = array(
'qname' => 'bar',
'namespaceUri' => 'http://foo.com',
'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable')
);
print 'creating an empty tag without namespace but namespace Uri:<br>';
print htmlentities(XML_Util::createTagFromArray($tag));
print "\n<br><br>\n";
/**
* creating an XML tag with more namespaces
*/
$tag = array(
'namespace' => 'foo',
'localPart' => 'bar',
'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'),
'content' => 'I\'m inside the tag',
'namespaces' => array(
'bar' => 'http://bar.com',
'pear' => 'http://pear.php.net',
)
);
print 'creating an XML tag with more namespaces:<br />';
print htmlentities(XML_Util::createTagFromArray($tag));
print "\n<br><br>\n";
/**
* creating an XML tag with a CData Section
*/
$tag = array(
'qname' => 'foo',
'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'),
'content' => 'I\'m inside the tag'
);
print 'creating a tag with CData section:<br>';
print htmlentities(XML_Util::createTagFromArray($tag, XML_UTIL_CDATA_SECTION));
print "\n<br><br>\n";
/**
* creating an XML tag with a CData Section
*/
$tag = array(
'qname' => 'foo',
'attributes' => array('key' => 'value', 'argh' => 't�t�'),
'content' =>
'Also XHTML-tags can be created '
. 'and HTML entities can be replaced � � � � <>.'
);
print 'creating a tag with HTML entities:<br>';
print htmlentities(XML_Util::createTagFromArray($tag, XML_UTIL_ENTITIES_HTML));
print "\n<br><br>\n";
/**
* creating an XML tag with createTag
*/
print 'creating a tag with createTag:<br>';
print htmlentities(XML_Util::createTag('myNs:myTag',
array('foo' => 'bar'),
'This is inside the tag',
'http://www.w3c.org/myNs#'));
print "\n<br><br>\n";
/**
* trying to create an XML tag with an array as content
*/
$tag = array(
'qname' => 'bar',
'content' => array('foo' => 'bar')
);
print 'trying to create an XML tag with an array as content:<br>';
print '<pre>';
print_r(XML_Util::createTagFromArray($tag));
print '</pre>';
print "\n<br><br>\n";
/**
* trying to create an XML tag without a name
*/
$tag = array(
'attributes' => array('foo' => 'bar'),
);
print 'trying to create an XML tag without a name:<br>';
print '<pre>';
print_r(XML_Util::createTagFromArray($tag));
print '</pre>';
print "\n<br><br>\n";
?>
PK �]�r¦J �J Archive_Tar/docs/Archive_Tar.txtnu �[��� Documentation for class Archive_Tar
===================================
Last update : 2001-08-15
Overview :
----------
The Archive_Tar class helps in creating and managing GNU TAR format
files compressed by GNU ZIP or not.
The class offers basic functions like creating an archive, adding
files in the archive, extracting files from the archive and listing
the archive content.
It also provide advanced functions that allow the adding and
extraction of files with path manipulation.
Sample :
--------
// ----- Creating the object (uncompressed archive)
$tar_object = new Archive_Tar("tarname.tar");
$tar_object->setErrorHandling(PEAR_ERROR_PRINT);
// ----- Creating the archive
$v_list[0]="file.txt";
$v_list[1]="data/";
$v_list[2]="file.log";
$tar_object->create($v_list);
// ----- Adding files
$v_list[0]="dev/file.txt";
$v_list[1]="dev/data/";
$v_list[2]="log/file.log";
$tar_object->add($v_list);
// ----- Adding more files
$tar_object->add("release/newfile.log release/readme.txt");
// ----- Listing the content
if (($v_list = $tar_object->listContent()) != 0)
for ($i=0; $i<sizeof($v_list); $i++)
{
echo "Filename :'".$v_list[$i][filename]."'<br>";
echo " .size :'".$v_list[$i][size]."'<br>";
echo " .mtime :'".$v_list[$i][mtime]."' (".date("l dS of F Y h:i:s A", $v_list[$i][mtime]).")<br>";
echo " .mode :'".$v_list[$i][mode]."'<br>";
echo " .uid :'".$v_list[$i][uid]."'<br>";
echo " .gid :'".$v_list[$i][gid]."'<br>";
echo " .typeflag :'".$v_list[$i][typeflag]."'<br>";
}
// ----- Extracting the archive in directory "install"
$tar_object->extract("install");
Public arguments :
------------------
None
Public Methods :
----------------
Method : Archive_Tar($p_tarname, $compress = null)
Description :
Archive_Tar Class constructor. This flavour of the constructor only
declare a new Archive_Tar object, identifying it by the name of the
tar file.
If the compress argument is set the tar will be read or created as a
gzip or bz2 compressed TAR file.
Arguments :
$p_tarname : A valid filename for the tar archive file.
$p_compress : can be null, 'gz' or 'bz2'. For
compatibility reason it can also be true. This
parameter indicates if gzip or bz2 compression
is required.
Return value :
The Archive_Tar object.
Sample :
$tar_object = new Archive_Tar("tarname.tar");
$tar_object_compressed = new Archive_Tar("tarname.tgz", true);
How it works :
Initialize the object.
Method : create($p_filelist)
Description :
This method creates the archive file and add the files / directories
that are listed in $p_filelist.
If the file already exists and is writable, it is replaced by the
new tar. It is a create and not an add. If the file exists and is
read-only or is a directory it is not replaced. The method return
false and a PEAR error text.
The $p_filelist parameter can be an array of string, each string
representing a filename or a directory name with their path if
needed. It can also be a single string with names separated by a
single blank.
See also createModify() method for more details.
Arguments :
$p_filelist : An array of filenames and directory names, or a single
string with names separated by a single blank space.
Return value :
true on success, false on error.
Sample 1 :
$tar_object = new Archive_Tar("tarname.tar");
$tar_object->setErrorHandling(PEAR_ERROR_PRINT); // Optional error handling
$v_list[0]="file.txt";
$v_list[1]="data/"; (Optional '/' at the end)
$v_list[2]="file.log";
$tar_object->create($v_list);
Sample 2 :
$tar_object = new Archive_Tar("tarname.tar");
$tar_object->setErrorHandling(PEAR_ERROR_PRINT); // Optional error handling
$tar_object->create("file.txt data/ file.log");
How it works :
Just calling the createModify() method with the right parameters.
Method : createModify($p_filelist, $p_add_dir, $p_remove_dir = "")
Description :
This method creates the archive file and add the files / directories
that are listed in $p_filelist.
If the file already exists and is writable, it is replaced by the
new tar. It is a create and not an add. If the file exists and is
read-only or is a directory it is not replaced. The method return
false and a PEAR error text.
The $p_filelist parameter can be an array of string, each string
representing a filename or a directory name with their path if
needed. It can also be a single string with names separated by a
single blank.
The path indicated in $p_remove_dir will be removed from the
memorized path of each file / directory listed when this path
exists. By default nothing is removed (empty path "")
The path indicated in $p_add_dir will be added at the beginning of
the memorized path of each file / directory listed. However it can
be set to empty "". The adding of a path is done after the removing
of path.
The path add/remove ability enables the user to prepare an archive
for extraction in a different path than the origin files are.
See also addModify() method for file adding properties.
Arguments :
$p_filelist : An array of filenames and directory names, or a single
string with names separated by a single blank space.
$p_add_dir : A string which contains a path to be added to the
memorized path of each element in the list.
$p_remove_dir : A string which contains a path to be removed from
the memorized path of each element in the list, when
relevant.
Return value :
true on success, false on error.
Sample 1 :
$tar_object = new Archive_Tar("tarname.tar");
$tar_object->setErrorHandling(PEAR_ERROR_PRINT); // Optional error handling
$v_list[0]="file.txt";
$v_list[1]="data/"; (Optional '/' at the end)
$v_list[2]="file.log";
$tar_object->createModify($v_list, "install");
// files are stored in the archive as :
// install/file.txt
// install/data
// install/data/file1.txt
// install/data/... all the files and sub-dirs of data/
// install/file.log
Sample 2 :
$tar_object = new Archive_Tar("tarname.tar");
$tar_object->setErrorHandling(PEAR_ERROR_PRINT); // Optional error handling
$v_list[0]="dev/file.txt";
$v_list[1]="dev/data/"; (Optional '/' at the end)
$v_list[2]="log/file.log";
$tar_object->createModify($v_list, "install", "dev");
// files are stored in the archive as :
// install/file.txt
// install/data
// install/data/file1.txt
// install/data/... all the files and sub-dirs of data/
// install/log/file.log
How it works :
Open the file in write mode (erasing the existing one if one),
call the _addList() method for adding the files in an empty archive,
add the tar footer (512 bytes block), close the tar file.
Method : addModify($p_filelist, $p_add_dir, $p_remove_dir="")
Description :
This method add the files / directories listed in $p_filelist at the
end of the existing archive. If the archive does not yet exists it
is created.
The $p_filelist parameter can be an array of string, each string
representing a filename or a directory name with their path if
needed. It can also be a single string with names separated by a
single blank.
The path indicated in $p_remove_dir will be removed from the
memorized path of each file / directory listed when this path
exists. By default nothing is removed (empty path "")
The path indicated in $p_add_dir will be added at the beginning of
the memorized path of each file / directory listed. However it can
be set to empty "". The adding of a path is done after the removing
of path.
The path add/remove ability enables the user to prepare an archive
for extraction in a different path than the origin files are.
If a file/dir is already in the archive it will only be added at the
end of the archive. There is no update of the existing archived
file/dir. However while extracting the archive, the last file will
replace the first one. This results in a none optimization of the
archive size.
If a file/dir does not exist the file/dir is ignored. However an
error text is send to PEAR error.
If a file/dir is not readable the file/dir is ignored. However an
error text is send to PEAR error.
If the resulting filename/dirname (after the add/remove option or
not) string is greater than 99 char, the file/dir is
ignored. However an error text is send to PEAR error.
Arguments :
$p_filelist : An array of filenames and directory names, or a single
string with names separated by a single blank space.
$p_add_dir : A string which contains a path to be added to the
memorized path of each element in the list.
$p_remove_dir : A string which contains a path to be removed from
the memorized path of each element in the list, when
relevant.
Return value :
true on success, false on error.
Sample 1 :
$tar_object = new Archive_Tar("tarname.tar");
[...]
$v_list[0]="dev/file.txt";
$v_list[1]="dev/data/"; (Optional '/' at the end)
$v_list[2]="log/file.log";
$tar_object->addModify($v_list, "install");
// files are stored in the archive as :
// install/file.txt
// install/data
// install/data/file1.txt
// install/data/... all the files and sub-dirs of data/
// install/file.log
Sample 2 :
$tar_object = new Archive_Tar("tarname.tar");
[...]
$v_list[0]="dev/file.txt";
$v_list[1]="dev/data/"; (Optional '/' at the end)
$v_list[2]="log/file.log";
$tar_object->addModify($v_list, "install", "dev");
// files are stored in the archive as :
// install/file.txt
// install/data
// install/data/file1.txt
// install/data/... all the files and sub-dirs of data/
// install/log/file.log
How it works :
If the archive does not exists it create it and add the files.
If the archive does exists and is not compressed, it open it, jump
before the last empty 512 bytes block (tar footer) and add the files
at this point.
If the archive does exists and is compressed, a temporary copy file
is created. This temporary file is then 'gzip' read block by block
until the last empty block. The new files are then added in the
compressed file.
The adding of files is done by going through the file/dir list,
adding files per files, in a recursive way through the
directory. Each time a path need to be added/removed it is done
before writing the file header in the archive.
Method : add($p_filelist)
Description :
This method add the files / directories listed in $p_filelist at the
end of the existing archive. If the archive does not yet exists it
is created.
The $p_filelist parameter can be an array of string, each string
representing a filename or a directory name with their path if
needed. It can also be a single string with names separated by a
single blank.
See addModify() method for details and limitations.
Arguments :
$p_filelist : An array of filenames and directory names, or a single
string with names separated by a single blank space.
Return value :
true on success, false on error.
Sample 1 :
$tar_object = new Archive_Tar("tarname.tar");
[...]
$v_list[0]="dev/file.txt";
$v_list[1]="dev/data/"; (Optional '/' at the end)
$v_list[2]="log/file.log";
$tar_object->add($v_list);
Sample 2 :
$tar_object = new Archive_Tar("tarname.tgz", true);
[...]
$v_list[0]="dev/file.txt";
$v_list[1]="dev/data/"; (Optional '/' at the end)
$v_list[2]="log/file.log";
$tar_object->add($v_list);
How it works :
Simply call the addModify() method with the right parameters.
Method : addString($p_filename, $p_string, $p_datetime, $p_params)
Description :
This method add a single string as a file at the
end of the existing archive. If the archive does not yet exists it
is created.
Arguments :
$p_filename : A string which contains the full filename path
that will be associated with the string.
$p_string : The content of the file added in the archive.
$p_datetime : (Optional) Timestamp of the file (default = now)
$p_params : (Optional) Various file metadata:
stamp - As above, timestamp of the file
mode - UNIX-style permissions (default 0600)
type - Is this a regular file or link (see TAR
format spec for how to create a hard/symlink)
uid - UNIX-style user ID (default 0 = root)
gid - UNIX-style group ID (default 0 = root)
Return value :
true on success, false on error.
Sample 1 :
$v_archive = & new Archive_Tar($p_filename);
$v_archive->setErrorHandling(PEAR_ERROR_PRINT);
$v_result = $v_archive->addString('data/test.txt', 'This is the text of the string');
$v_result = $v_archive->addString(
'data/test.sh',
"#!/bin/sh\necho 'Hello'",
time(),
array( "mode" => 0755, "uid" => 34 )
);
Method : extract($p_path = "")
Description :
This method extract all the content of the archive in the directory
indicated by $p_path.If $p_path is optional, if not set the archive
is extracted in the current directory.
While extracting a file, if the directory path does not exists it is
created.
See extractModify() for details and limitations.
Arguments :
$p_path : Optional path where the files/dir need to by extracted.
Return value :
true on success, false on error.
Sample :
$tar_object = new Archive_Tar("tarname.tar");
$tar_object->extract();
How it works :
Simply call the extractModify() method with appropriate parameters.
Method : extractModify($p_path, $p_remove_path)
Description :
This method extract all the content of the archive in the directory
indicated by $p_path. When relevant the memorized path of the
files/dir can be modified by removing the $p_remove_path path at the
beginning of the file/dir path.
While extracting a file, if the directory path does not exists it is
created.
While extracting a file, if the file already exists it is replaced
without looking for last modification date.
While extracting a file, if the file already exists and is write
protected, the extraction is aborted.
While extracting a file, if a directory with the same name already
exists, the extraction is aborted.
While extracting a directory, if a file with the same name already
exists, the extraction is aborted.
While extracting a file/directory if the destination directory exist
and is write protected, or does not exist but can not be created,
the extraction is aborted.
If after extraction an extracted file does not show the correct
stored file size, the extraction is aborted.
When the extraction is aborted, a PEAR error text is set and false
is returned. However the result can be a partial extraction that may
need to be manually cleaned.
Arguments :
$p_path : The path of the directory where the files/dir need to by
extracted.
$p_remove_path : Part of the memorized path that can be removed if
present at the beginning of the file/dir path.
Return value :
true on success, false on error.
Sample :
// Imagine tarname.tar with files :
// dev/data/file.txt
// dev/data/log.txt
// readme.txt
$tar_object = new Archive_Tar("tarname.tar");
$tar_object->extractModify("install", "dev");
// Files will be extracted there :
// install/data/file.txt
// install/data/log.txt
// install/readme.txt
How it works :
Open the archive and call a more generic function that can extract
only a part of the archive or all the archive.
See extractList() method for more details.
Method : extractInString($p_filename)
Description :
This method extract from the archive one file identified by $p_filename.
The return value is a string with the file content, or NULL on error.
Arguments :
$p_filename : The path of the file to extract in a string.
Return value :
a string with the file content or NULL.
Sample :
// Imagine tarname.tar with files :
// dev/data/file.txt
// dev/data/log.txt
// dev/readme.txt
$v_archive = & new Archive_Tar('tarname.tar');
$v_archive->setErrorHandling(PEAR_ERROR_PRINT);
$v_string = $v_archive->extractInString('dev/readme.txt');
echo $v_string;
Method : listContent()
Description :
This method returns an array of arrays that describe each
file/directory present in the archive.
The array is not sorted, so it show the position of the file in the
archive.
The file informations are :
$file[filename] : Name and path of the file/dir.
$file[mode] : File permissions (result of fileperms())
$file[uid] : user id
$file[gid] : group id
$file[size] : filesize
$file[mtime] : Last modification time (result of filemtime())
$file[typeflag] : "" for file, "5" for directory
Arguments :
Return value :
An array of arrays or 0 on error.
Sample :
$tar_object = new Archive_Tar("tarname.tar");
if (($v_list = $tar_object->listContent()) != 0)
for ($i=0; $i<sizeof($v_list); $i++)
{
echo "Filename :'".$v_list[$i][filename]."'<br>";
echo " .size :'".$v_list[$i][size]."'<br>";
echo " .mtime :'".$v_list[$i][mtime]."' (".
date("l dS of F Y h:i:s A", $v_list[$i][mtime]).")<br>";
echo " .mode :'".$v_list[$i][mode]."'<br>";
echo " .uid :'".$v_list[$i][uid]."'<br>";
echo " .gid :'".$v_list[$i][gid]."'<br>";
echo " .typeflag :'".$v_list[$i][typeflag]."'<br>";
}
How it works :
Call the same function as an extract however with a flag to only go
through the archive without extracting the files.
Method : extractList($p_filelist, $p_path = "", $p_remove_path = "")
Description :
This method extract from the archive only the files indicated in the
$p_filelist. These files are extracted in the current directory or
in the directory indicated by the optional $p_path parameter.
If indicated the $p_remove_path can be used in the same way as it is
used in extractModify() method.
Arguments :
$p_filelist : An array of filenames and directory names, or a single
string with names separated by a single blank space.
$p_path : The path of the directory where the files/dir need to by
extracted.
$p_remove_path : Part of the memorized path that can be removed if
present at the beginning of the file/dir path.
Return value :
true on success, false on error.
Sample :
// Imagine tarname.tar with files :
// dev/data/file.txt
// dev/data/log.txt
// readme.txt
$tar_object = new Archive_Tar("tarname.tar");
$tar_object->extractList("dev/data/file.txt readme.txt", "install",
"dev");
// Files will be extracted there :
// install/data/file.txt
// install/readme.txt
How it works :
Go through the archive and extract only the files present in the
list.
PK �]�E�� � PEAR/README.rstnu �[��� *************************
PEAR - The PEAR Installer
*************************
.. image:: https://travis-ci.org/pear/pear-core.svg?branch=stable
:target: https://travis-ci.org/pear/pear-core
=========================================
What is the PEAR Installer? What is PEAR?
=========================================
PEAR is the PHP Extension and Application Repository, found at
http://pear.php.net.
The **PEAR Installer** is this software, which contains executable
files and PHP code that is used to **download and install** PEAR code
from pear.php.net.
PEAR contains useful **software libraries and applications** such as
MDB2 (database abstraction), HTML_QuickForm (HTML forms management),
PhpDocumentor (auto-documentation generator), DB_DataObject
(Data Access Abstraction), and many hundreds more.
Browse all available packages at http://pear.php.net, the list is
constantly growing and updating to reflect improvements in the PHP language.
.. warning::
Do not run PEAR without installing it - if you downloaded this
tarball manually, you MUST install it. Read the instructions in INSTALL
prior to use.
=============
Documentation
=============
Documentation for PEAR can be found at http://pear.php.net/manual/.
Installation documentation can be found in the INSTALL file included
in this tarball.
=====
Tests
=====
Run the tests without installation as follows::
$ ./scripts/pear.sh run-tests -r tests
You should have the ``Text_Diff`` package installed to get nicer error output.
To run the tests with another PHP version, modify ``php_bin`` and set the
``PHP_PEAR_PHP_BIN`` environment variable::
$ pear config-set php_bin /usr/local/bin/php7
$ PHP_PEAR_PHP_BIN=/usr/local/bin/php7 ./scripts/pear.sh run-tests -r tests
Happy PHPing, we hope PEAR will be a great tool for your development work!
Test dependencies
=================
* ``zlib``
=========
Releasing
=========
Create a PEAR package, as well as phars for pear-less installation,
simply run ``build-release.sh``).
``go-pear.phar`` contains the PEAR installer installer that asks where to install it.
It is available from http://pear.php.net/go-pear.phar.
``install-pear-nozlib.phar`` installs PEAR automatically without asking anything.
It is shipped with PHP itself.
PK �]�u��� � PEAR/LICENSEnu �[��� Copyright (c) 1997-2009,
Stig Bakken <ssb@php.net>,
Gregory Beaver <cellog@php.net>,
Helgi Þormar Þorbjörnsson <helgi@php.net>,
Tomas V.V.Cox <cox@idecnet.com>,
Martin Jansen <mj@php.net>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
PK �]���x x PEAR/INSTALLnu �[��� PEAR - The PEAR Installer
=========================
Installing the PEAR Installer.
You should install PEAR on a local development machine first. Installing
PEAR on a remote production machine should only be done after you are
familiar with PEAR and have tested code using PEAR on your development
machine.
There are two methods of installing PEAR
- PEAR bundled in PHP
- go-pear
We will first examine how to install PEAR that is bundled with PHP.
Microsoft Windows
=================
If you are running PHP 5.2.0 or newer, simply download and
run the windows installer (.msi) and PEAR can be automatically
installed.
Otherwise, for older PHP versions, download the .zip of windows,
there is a script included with your PHP distribution that is called
"go-pear". You must open a command box in order to run it. Click
"start" then click "Run..." and type "cmd.exe" to open a command box.
Use "cd" to change directory to the location of PHP where you unzipped it,
and run the go-pear command.
Unix
====
When compiling PHP from source, you simply need to include the
--with-pear directive on the "./configure" command. This is "on"
by default in most PHP versions, but it doesn't hurt to list it
explicitly. You should also consider enabling the zlib extension via
--enable-zlib, so that the PEAR installer will be able to handle gzipped
files (i.e. smaller package files for faster downloads). Later, when you
run "make install" to install PHP itself, part of the process will be
prompts that ask you where you want PEAR to be installed.
go-pear
=======
For users who cannot perform the above steps, or who wish to obtain the
latest PEAR with a slightly higher risk of failure, use go-pear. go-pear
is obtained by downloading http://pear.php.net/go-pear and saving it as go-pear.php.
After downloading, simply run "php go-pear.php" or open it in a web browser
(windows only) to download and install PEAR.
You can always ask general installation questions on pear-general@lists.php.net,
a public mailing list devoted to support for PEAR packages and installation-
related issues.
Happy PHPing, we hope PEAR will be a great tool for your development work!
PK �]DG�e� � Structures_Graph/LICENSEnu �[��� GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
PK �]x� �� � E Structures_Graph/docs/tutorials/Structures_Graph/Structures_Graph.pkgnu �[��� <refentry id="{@id package.database.structures_graph.tutorial}">
<refnamediv>
<refname><classname>Structures_Graph</classname> Tutorial</refname>
<refpurpose>A first tour of graph datastructure manipulation</refpurpose>
</refnamediv>
<refsect1 id="{@id package.database.structures_graph.tutorial.intro}">
<title>Introduction</title>
<para>
Structures_Graph is a package for creating and manipulating graph datastructures. A graph is a set of objects, called nodes, connected by arcs. When used as a datastructure, usually nodes contain data, and arcs represent relationships between nodes. When arcs have a direction, and can be travelled only one way, graphs are said to be directed. When arcs have no direction, and can always be travelled both ways, graphs are said to be non directed.
</para>
<para>
Structures_Graph provides an object oriented API to create and directly query a graph, as well as a set of Manipulator classes to extract information from the graph.
</para>
</refsect1>
<refsect1 id="{@id package.database.structures_graph.tutorial.creation}">
<title>Creating a Graph</title>
<para>
Creating a graph is done using the simple constructor:
<programlisting>
<![CDATA[
require_once 'Structures/Graph.php';
$directedGraph =& new Structures_Graph(true);
$nonDirectedGraph =& new Structures_Graph(false);
]]>
</programlisting>
and passing the constructor a flag telling it whether the graph should be directed. A directed graph will always be directed during its lifetime. It's a permanent characteristic.
</para>
<para>
To fill out the graph, we'll need to create some nodes, and then call Graph::addNode.
<programlisting>
<![CDATA[
require_once 'Structures/Graph/Node.php';
$nodeOne =& new Structures_Graph_Node();
$nodeTwo =& new Structures_Graph_Node();
$nodeThree =& new Structures_Graph_Node();
$directedGraph->addNode(&$nodeOne);
$directedGraph->addNode(&$nodeTwo);
$directedGraph->addNode(&$nodeThree);
]]>
</programlisting>
and then setup the arcs:
<programlisting>
<![CDATA[
$nodeOne->connectTo($nodeTwo);
$nodeOne->connectTo($nodeThree);
]]>
</programlisting>
Note that arcs can only be created after the nodes have been inserted into the graph.
</para>
</refsect1>
<refsect1 id="{@id package.database.structures_graph.tutorial.nodesanddata}">
<title>Associating Data</title>
<para>
Graphs are only useful as datastructures if they can hold data. Structure_Graph stores data in nodes. Each node contains a setter and a getter for its data.
<programlisting>
<![CDATA[
$nodeOne->setData("Node One's Data is a String");
$nodeTwo->setData(1976);
$nodeThree->setData('Some other string');
print("NodeTwo's Data is an integer: " . $nodeTwo->getData());
]]>
</programlisting>
</para>
<para>
Structure_Graph nodes can also store metadata, alongside with the main data. Metadata differs from regular data just because it is stored under a key, making it possible to store more than one data reference per node. The metadata getter and setter need the key to perform the operation:
<programlisting>
<![CDATA[
$nodeOne->setMetadata('example key', "Node One's Sample Metadata");
print("Metadata stored under key 'example key' in node one: " . $nodeOne->getMetadata('example key'));
$nodeOne->unsetMetadata('example key');
]]>
</programlisting>
</para>
</refsect1>
<refsect1 id="{@id package.database.structures_graph.tutorial.querying}">
<title>Querying a Graph</title>
<para>
Structures_Graph provides for basic querying of the graph:
<programlisting>
<![CDATA[
// Nodes are able to calculate their indegree and outdegree
print("NodeOne's inDegree: " . $nodeOne->inDegree());
print("NodeOne's outDegree: " . $nodeOne->outDegree());
// and naturally, nodes can report on their arcs
$arcs = $nodeOne->getNeighbours();
for ($i=0;$i<sizeof($arcs);$i++) {
print("NodeOne has an arc to " . $arcs[$i]->getData());
}
]]>
</programlisting>
</para>
</refsect1>
</refentry>
PK �]���� � PEAR.phpnu �[��� <?php
/**
* PEAR, the PHP Extension and Application Repository
*
* PEAR class and PEAR_Error class
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Sterling Hughes <sterling@php.net>
* @author Stig Bakken <ssb@php.net>
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2010 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**#@+
* ERROR constants
*/
define('PEAR_ERROR_RETURN', 1);
define('PEAR_ERROR_PRINT', 2);
define('PEAR_ERROR_TRIGGER', 4);
define('PEAR_ERROR_DIE', 8);
define('PEAR_ERROR_CALLBACK', 16);
/**
* WARNING: obsolete
* @deprecated
*/
define('PEAR_ERROR_EXCEPTION', 32);
/**#@-*/
if (substr(PHP_OS, 0, 3) == 'WIN') {
define('OS_WINDOWS', true);
define('OS_UNIX', false);
define('PEAR_OS', 'Windows');
} else {
define('OS_WINDOWS', false);
define('OS_UNIX', true);
define('PEAR_OS', 'Unix'); // blatant assumption
}
$GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN;
$GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE;
$GLOBALS['_PEAR_destructor_object_list'] = array();
$GLOBALS['_PEAR_shutdown_funcs'] = array();
$GLOBALS['_PEAR_error_handler_stack'] = array();
if(function_exists('ini_set')) {
@ini_set('track_errors', true);
}
/**
* Base class for other PEAR classes. Provides rudimentary
* emulation of destructors.
*
* If you want a destructor in your class, inherit PEAR and make a
* destructor method called _yourclassname (same name as the
* constructor, but with a "_" prefix). Also, in your constructor you
* have to call the PEAR constructor: $this->PEAR();.
* The destructor method will be called without parameters. Note that
* at in some SAPI implementations (such as Apache), any output during
* the request shutdown (in which destructors are called) seems to be
* discarded. If you need to get any debug information from your
* destructor, use error_log(), syslog() or something similar.
*
* IMPORTANT! To use the emulated destructors you need to create the
* objects by reference: $obj =& new PEAR_child;
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Tomas V.V. Cox <cox@idecnet.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @see PEAR_Error
* @since Class available since PHP 4.0.2
* @link http://pear.php.net/manual/en/core.pear.php#core.pear.pear
*/
class PEAR
{
/**
* Whether to enable internal debug messages.
*
* @var bool
* @access private
*/
var $_debug = false;
/**
* Default error mode for this object.
*
* @var int
* @access private
*/
var $_default_error_mode = null;
/**
* Default error options used for this object when error mode
* is PEAR_ERROR_TRIGGER.
*
* @var int
* @access private
*/
var $_default_error_options = null;
/**
* Default error handler (callback) for this object, if error mode is
* PEAR_ERROR_CALLBACK.
*
* @var string
* @access private
*/
var $_default_error_handler = '';
/**
* Which class to use for error objects.
*
* @var string
* @access private
*/
var $_error_class = 'PEAR_Error';
/**
* An array of expected errors.
*
* @var array
* @access private
*/
var $_expected_errors = array();
/**
* List of methods that can be called both statically and non-statically.
* @var array
*/
protected static $bivalentMethods = array(
'setErrorHandling' => true,
'raiseError' => true,
'throwError' => true,
'pushErrorHandling' => true,
'popErrorHandling' => true,
);
/**
* Constructor. Registers this object in
* $_PEAR_destructor_object_list for destructor emulation if a
* destructor object exists.
*
* @param string $error_class (optional) which class to use for
* error objects, defaults to PEAR_Error.
* @access public
* @return void
*/
function __construct($error_class = null)
{
$classname = strtolower(get_class($this));
if ($this->_debug) {
print "PEAR constructor called, class=$classname\n";
}
if ($error_class !== null) {
$this->_error_class = $error_class;
}
while ($classname && strcasecmp($classname, "pear")) {
$destructor = "_$classname";
if (method_exists($this, $destructor)) {
global $_PEAR_destructor_object_list;
$_PEAR_destructor_object_list[] = $this;
if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
register_shutdown_function("_PEAR_call_destructors");
$GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
}
break;
} else {
$classname = get_parent_class($classname);
}
}
}
/**
* Only here for backwards compatibility.
* E.g. Archive_Tar calls $this->PEAR() in its constructor.
*
* @param string $error_class Which class to use for error objects,
* defaults to PEAR_Error.
*/
public function PEAR($error_class = null)
{
self::__construct($error_class);
}
/**
* Destructor (the emulated type of...). Does nothing right now,
* but is included for forward compatibility, so subclass
* destructors should always call it.
*
* See the note in the class desciption about output from
* destructors.
*
* @access public
* @return void
*/
function _PEAR() {
if ($this->_debug) {
printf("PEAR destructor called, class=%s\n", strtolower(get_class($this)));
}
}
public function __call($method, $arguments)
{
if (!isset(self::$bivalentMethods[$method])) {
if (PHP_VERSION_ID < 70000) {
trigger_error(
'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR
);
} else {
throw new Error('Call to undefined method PEAR::' . $method . '()');
}
}
return call_user_func_array(
array(__CLASS__, '_' . $method),
array_merge(array($this), $arguments)
);
}
public static function __callStatic($method, $arguments)
{
if (!isset(self::$bivalentMethods[$method])) {
if (PHP_VERSION_ID < 70000) {
trigger_error(
'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR
);
} else {
throw new Error('Call to undefined method PEAR::' . $method . '()');
}
}
return call_user_func_array(
array(__CLASS__, '_' . $method),
array_merge(array(null), $arguments)
);
}
/**
* If you have a class that's mostly/entirely static, and you need static
* properties, you can use this method to simulate them. Eg. in your method(s)
* do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
* You MUST use a reference, or they will not persist!
*
* @param string $class The calling classname, to prevent clashes
* @param string $var The variable to retrieve.
* @return mixed A reference to the variable. If not set it will be
* auto initialised to NULL.
*/
public static function &getStaticProperty($class, $var)
{
static $properties;
if (!isset($properties[$class])) {
$properties[$class] = array();
}
if (!array_key_exists($var, $properties[$class])) {
$properties[$class][$var] = null;
}
return $properties[$class][$var];
}
/**
* Use this function to register a shutdown method for static
* classes.
*
* @param mixed $func The function name (or array of class/method) to call
* @param mixed $args The arguments to pass to the function
*
* @return void
*/
public static function registerShutdownFunc($func, $args = array())
{
// if we are called statically, there is a potential
// that no shutdown func is registered. Bug #6445
if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
register_shutdown_function("_PEAR_call_destructors");
$GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
}
$GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
}
/**
* Tell whether a value is a PEAR error.
*
* @param mixed $data the value to test
* @param int $code if $data is an error object, return true
* only if $code is a string and
* $obj->getMessage() == $code or
* $code is an integer and $obj->getCode() == $code
*
* @return bool true if parameter is an error
*/
public static function isError($data, $code = null)
{
if (!is_a($data, 'PEAR_Error')) {
return false;
}
if (is_null($code)) {
return true;
} elseif (is_string($code)) {
return $data->getMessage() == $code;
}
return $data->getCode() == $code;
}
/**
* Sets how errors generated by this object should be handled.
* Can be invoked both in objects and statically. If called
* statically, setErrorHandling sets the default behaviour for all
* PEAR objects. If called in an object, setErrorHandling sets
* the default behaviour for that object.
*
* @param object $object
* Object the method was called on (non-static mode)
*
* @param int $mode
* One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
* PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
* PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
*
* @param mixed $options
* When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
* of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
*
* When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
* to be the callback function or method. A callback
* function is a string with the name of the function, a
* callback method is an array of two elements: the element
* at index 0 is the object, and the element at index 1 is
* the name of the method to call in the object.
*
* When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
* a printf format string used when printing the error
* message.
*
* @access public
* @return void
* @see PEAR_ERROR_RETURN
* @see PEAR_ERROR_PRINT
* @see PEAR_ERROR_TRIGGER
* @see PEAR_ERROR_DIE
* @see PEAR_ERROR_CALLBACK
* @see PEAR_ERROR_EXCEPTION
*
* @since PHP 4.0.5
*/
protected static function _setErrorHandling(
$object, $mode = null, $options = null
) {
if ($object !== null) {
$setmode = &$object->_default_error_mode;
$setoptions = &$object->_default_error_options;
} else {
$setmode = &$GLOBALS['_PEAR_default_error_mode'];
$setoptions = &$GLOBALS['_PEAR_default_error_options'];
}
switch ($mode) {
case PEAR_ERROR_EXCEPTION:
case PEAR_ERROR_RETURN:
case PEAR_ERROR_PRINT:
case PEAR_ERROR_TRIGGER:
case PEAR_ERROR_DIE:
case null:
$setmode = $mode;
$setoptions = $options;
break;
case PEAR_ERROR_CALLBACK:
$setmode = $mode;
// class/object method callback
if (is_callable($options)) {
$setoptions = $options;
} else {
trigger_error("invalid error callback", E_USER_WARNING);
}
break;
default:
trigger_error("invalid error mode", E_USER_WARNING);
break;
}
}
/**
* This method is used to tell which errors you expect to get.
* Expected errors are always returned with error mode
* PEAR_ERROR_RETURN. Expected error codes are stored in a stack,
* and this method pushes a new element onto it. The list of
* expected errors are in effect until they are popped off the
* stack with the popExpect() method.
*
* Note that this method can not be called statically
*
* @param mixed $code a single error code or an array of error codes to expect
*
* @return int the new depth of the "expected errors" stack
* @access public
*/
function expectError($code = '*')
{
if (is_array($code)) {
array_push($this->_expected_errors, $code);
} else {
array_push($this->_expected_errors, array($code));
}
return count($this->_expected_errors);
}
/**
* This method pops one element off the expected error codes
* stack.
*
* @return array the list of error codes that were popped
*/
function popExpect()
{
return array_pop($this->_expected_errors);
}
/**
* This method checks unsets an error code if available
*
* @param mixed error code
* @return bool true if the error code was unset, false otherwise
* @access private
* @since PHP 4.3.0
*/
function _checkDelExpect($error_code)
{
$deleted = false;
foreach ($this->_expected_errors as $key => $error_array) {
if (in_array($error_code, $error_array)) {
unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
$deleted = true;
}
// clean up empty arrays
if (0 == count($this->_expected_errors[$key])) {
unset($this->_expected_errors[$key]);
}
}
return $deleted;
}
/**
* This method deletes all occurrences of the specified element from
* the expected error codes stack.
*
* @param mixed $error_code error code that should be deleted
* @return mixed list of error codes that were deleted or error
* @access public
* @since PHP 4.3.0
*/
function delExpect($error_code)
{
$deleted = false;
if ((is_array($error_code) && (0 != count($error_code)))) {
// $error_code is a non-empty array here; we walk through it trying
// to unset all values
foreach ($error_code as $key => $error) {
$deleted = $this->_checkDelExpect($error) ? true : false;
}
return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
} elseif (!empty($error_code)) {
// $error_code comes alone, trying to unset it
if ($this->_checkDelExpect($error_code)) {
return true;
}
return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
}
// $error_code is empty
return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
}
/**
* This method is a wrapper that returns an instance of the
* configured error class with this object's default error
* handling applied. If the $mode and $options parameters are not
* specified, the object's defaults are used.
*
* @param mixed $message a text error message or a PEAR error object
*
* @param int $code a numeric error code (it is up to your class
* to define these if you want to use codes)
*
* @param int $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
* PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
* PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
*
* @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
* specifies the PHP-internal error level (one of
* E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
* If $mode is PEAR_ERROR_CALLBACK, this
* parameter specifies the callback function or
* method. In other error modes this parameter
* is ignored.
*
* @param string $userinfo If you need to pass along for example debug
* information, this parameter is meant for that.
*
* @param string $error_class The returned error object will be
* instantiated from this class, if specified.
*
* @param bool $skipmsg If true, raiseError will only pass error codes,
* the error message parameter will be dropped.
*
* @return object a PEAR error object
* @see PEAR::setErrorHandling
* @since PHP 4.0.5
*/
protected static function _raiseError($object,
$message = null,
$code = null,
$mode = null,
$options = null,
$userinfo = null,
$error_class = null,
$skipmsg = false)
{
// The error is yet a PEAR error object
if (is_object($message)) {
$code = $message->getCode();
$userinfo = $message->getUserInfo();
$error_class = $message->getType();
$message->error_message_prefix = '';
$message = $message->getMessage();
}
if (
$object !== null &&
isset($object->_expected_errors) &&
count($object->_expected_errors) > 0 &&
count($exp = end($object->_expected_errors))
) {
if ($exp[0] === "*" ||
(is_int(reset($exp)) && in_array($code, $exp)) ||
(is_string(reset($exp)) && in_array($message, $exp))
) {
$mode = PEAR_ERROR_RETURN;
}
}
// No mode given, try global ones
if ($mode === null) {
// Class error handler
if ($object !== null && isset($object->_default_error_mode)) {
$mode = $object->_default_error_mode;
$options = $object->_default_error_options;
// Global error handler
} elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
$mode = $GLOBALS['_PEAR_default_error_mode'];
$options = $GLOBALS['_PEAR_default_error_options'];
}
}
if ($error_class !== null) {
$ec = $error_class;
} elseif ($object !== null && isset($object->_error_class)) {
$ec = $object->_error_class;
} else {
$ec = 'PEAR_Error';
}
if ($skipmsg) {
$a = new $ec($code, $mode, $options, $userinfo);
} else {
$a = new $ec($message, $code, $mode, $options, $userinfo);
}
return $a;
}
/**
* Simpler form of raiseError with fewer options. In most cases
* message, code and userinfo are enough.
*
* @param mixed $message a text error message or a PEAR error object
*
* @param int $code a numeric error code (it is up to your class
* to define these if you want to use codes)
*
* @param string $userinfo If you need to pass along for example debug
* information, this parameter is meant for that.
*
* @return object a PEAR error object
* @see PEAR::raiseError
*/
protected static function _throwError($object, $message = null, $code = null, $userinfo = null)
{
if ($object !== null) {
$a = $object->raiseError($message, $code, null, null, $userinfo);
return $a;
}
$a = PEAR::raiseError($message, $code, null, null, $userinfo);
return $a;
}
public static function staticPushErrorHandling($mode, $options = null)
{
$stack = &$GLOBALS['_PEAR_error_handler_stack'];
$def_mode = &$GLOBALS['_PEAR_default_error_mode'];
$def_options = &$GLOBALS['_PEAR_default_error_options'];
$stack[] = array($def_mode, $def_options);
switch ($mode) {
case PEAR_ERROR_EXCEPTION:
case PEAR_ERROR_RETURN:
case PEAR_ERROR_PRINT:
case PEAR_ERROR_TRIGGER:
case PEAR_ERROR_DIE:
case null:
$def_mode = $mode;
$def_options = $options;
break;
case PEAR_ERROR_CALLBACK:
$def_mode = $mode;
// class/object method callback
if (is_callable($options)) {
$def_options = $options;
} else {
trigger_error("invalid error callback", E_USER_WARNING);
}
break;
default:
trigger_error("invalid error mode", E_USER_WARNING);
break;
}
$stack[] = array($mode, $options);
return true;
}
public static function staticPopErrorHandling()
{
$stack = &$GLOBALS['_PEAR_error_handler_stack'];
$setmode = &$GLOBALS['_PEAR_default_error_mode'];
$setoptions = &$GLOBALS['_PEAR_default_error_options'];
array_pop($stack);
list($mode, $options) = $stack[sizeof($stack) - 1];
array_pop($stack);
switch ($mode) {
case PEAR_ERROR_EXCEPTION:
case PEAR_ERROR_RETURN:
case PEAR_ERROR_PRINT:
case PEAR_ERROR_TRIGGER:
case PEAR_ERROR_DIE:
case null:
$setmode = $mode;
$setoptions = $options;
break;
case PEAR_ERROR_CALLBACK:
$setmode = $mode;
// class/object method callback
if (is_callable($options)) {
$setoptions = $options;
} else {
trigger_error("invalid error callback", E_USER_WARNING);
}
break;
default:
trigger_error("invalid error mode", E_USER_WARNING);
break;
}
return true;
}
/**
* Push a new error handler on top of the error handler options stack. With this
* you can easily override the actual error handler for some code and restore
* it later with popErrorHandling.
*
* @param mixed $mode (same as setErrorHandling)
* @param mixed $options (same as setErrorHandling)
*
* @return bool Always true
*
* @see PEAR::setErrorHandling
*/
protected static function _pushErrorHandling($object, $mode, $options = null)
{
$stack = &$GLOBALS['_PEAR_error_handler_stack'];
if ($object !== null) {
$def_mode = &$object->_default_error_mode;
$def_options = &$object->_default_error_options;
} else {
$def_mode = &$GLOBALS['_PEAR_default_error_mode'];
$def_options = &$GLOBALS['_PEAR_default_error_options'];
}
$stack[] = array($def_mode, $def_options);
if ($object !== null) {
$object->setErrorHandling($mode, $options);
} else {
PEAR::setErrorHandling($mode, $options);
}
$stack[] = array($mode, $options);
return true;
}
/**
* Pop the last error handler used
*
* @return bool Always true
*
* @see PEAR::pushErrorHandling
*/
protected static function _popErrorHandling($object)
{
$stack = &$GLOBALS['_PEAR_error_handler_stack'];
array_pop($stack);
list($mode, $options) = $stack[sizeof($stack) - 1];
array_pop($stack);
if ($object !== null) {
$object->setErrorHandling($mode, $options);
} else {
PEAR::setErrorHandling($mode, $options);
}
return true;
}
/**
* OS independent PHP extension load. Remember to take care
* on the correct extension name for case sensitive OSes.
*
* @param string $ext The extension name
* @return bool Success or not on the dl() call
*/
public static function loadExtension($ext)
{
if (extension_loaded($ext)) {
return true;
}
// if either returns true dl() will produce a FATAL error, stop that
if (
function_exists('dl') === false ||
ini_get('enable_dl') != 1
) {
return false;
}
if (OS_WINDOWS) {
$suffix = '.dll';
} elseif (PHP_OS == 'HP-UX') {
$suffix = '.sl';
} elseif (PHP_OS == 'AIX') {
$suffix = '.a';
} elseif (PHP_OS == 'OSX') {
$suffix = '.bundle';
} else {
$suffix = '.so';
}
return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
}
/**
* Get SOURCE_DATE_EPOCH environment variable
* See https://reproducible-builds.org/specs/source-date-epoch/
*
* @return int
* @access public
*/
static function getSourceDateEpoch()
{
if ($source_date_epoch = getenv('SOURCE_DATE_EPOCH')) {
if (preg_match('/^\d+$/', $source_date_epoch)) {
return (int) $source_date_epoch;
} else {
// "If the value is malformed, the build process SHOULD exit with a non-zero error code."
self::raiseError("Invalid SOURCE_DATE_EPOCH: $source_date_epoch");
exit(1);
}
} else {
return time();
}
}
}
function _PEAR_call_destructors()
{
global $_PEAR_destructor_object_list;
if (is_array($_PEAR_destructor_object_list) &&
sizeof($_PEAR_destructor_object_list))
{
reset($_PEAR_destructor_object_list);
$destructLifoExists = PEAR::getStaticProperty('PEAR', 'destructlifo');
if ($destructLifoExists) {
$_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
}
foreach ($_PEAR_destructor_object_list as $k => $objref) {
$classname = get_class($objref);
while ($classname) {
$destructor = "_$classname";
if (method_exists($objref, $destructor)) {
$objref->$destructor();
break;
} else {
$classname = get_parent_class($classname);
}
}
}
// Empty the object list to ensure that destructors are
// not called more than once.
$_PEAR_destructor_object_list = array();
}
// Now call the shutdown functions
if (
isset($GLOBALS['_PEAR_shutdown_funcs']) &&
is_array($GLOBALS['_PEAR_shutdown_funcs']) &&
!empty($GLOBALS['_PEAR_shutdown_funcs'])
) {
foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
call_user_func_array($value[0], $value[1]);
}
}
}
/**
* Standard PEAR error class for PHP 4
*
* This class is supserseded by {@link PEAR_Exception} in PHP 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Tomas V.V. Cox <cox@idecnet.com>
* @author Gregory Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/manual/en/core.pear.pear-error.php
* @see PEAR::raiseError(), PEAR::throwError()
* @since Class available since PHP 4.0.2
*/
class PEAR_Error
{
var $error_message_prefix = '';
var $mode = PEAR_ERROR_RETURN;
var $level = E_USER_NOTICE;
var $code = -1;
var $message = '';
var $userinfo = '';
var $backtrace = null;
var $callback = null;
/**
* PEAR_Error constructor
*
* @param string $message message
*
* @param int $code (optional) error code
*
* @param int $mode (optional) error mode, one of: PEAR_ERROR_RETURN,
* PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
* PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
*
* @param mixed $options (optional) error level, _OR_ in the case of
* PEAR_ERROR_CALLBACK, the callback function or object/method
* tuple.
*
* @param string $userinfo (optional) additional user/debug info
*
* @access public
*
*/
function __construct($message = 'unknown error', $code = null,
$mode = null, $options = null, $userinfo = null)
{
if ($mode === null) {
$mode = PEAR_ERROR_RETURN;
}
$this->message = $message;
$this->code = $code;
$this->mode = $mode;
$this->userinfo = $userinfo;
$skiptrace = PEAR::getStaticProperty('PEAR_Error', 'skiptrace');
if (!$skiptrace) {
$this->backtrace = debug_backtrace();
if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
unset($this->backtrace[0]['object']);
}
}
if ($mode & PEAR_ERROR_CALLBACK) {
$this->level = E_USER_NOTICE;
$this->callback = $options;
} else {
if ($options === null) {
$options = E_USER_NOTICE;
}
$this->level = $options;
$this->callback = null;
}
if ($this->mode & PEAR_ERROR_PRINT) {
if (is_null($options) || is_int($options)) {
$format = "%s";
} else {
$format = $options;
}
printf($format, $this->getMessage());
}
if ($this->mode & PEAR_ERROR_TRIGGER) {
trigger_error($this->getMessage(), $this->level);
}
if ($this->mode & PEAR_ERROR_DIE) {
$msg = $this->getMessage();
if (is_null($options) || is_int($options)) {
$format = "%s";
if (substr($msg, -1) != "\n") {
$msg .= "\n";
}
} else {
$format = $options;
}
printf($format, $msg);
exit($code);
}
if ($this->mode & PEAR_ERROR_CALLBACK && is_callable($this->callback)) {
call_user_func($this->callback, $this);
}
if ($this->mode & PEAR_ERROR_EXCEPTION) {
trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
eval('$e = new Exception($this->message, $this->code);throw($e);');
}
}
/**
* Only here for backwards compatibility.
*
* Class "Cache_Error" still uses it, among others.
*
* @param string $message Message
* @param int $code Error code
* @param int $mode Error mode
* @param mixed $options See __construct()
* @param string $userinfo Additional user/debug info
*/
public function PEAR_Error(
$message = 'unknown error', $code = null, $mode = null,
$options = null, $userinfo = null
) {
self::__construct($message, $code, $mode, $options, $userinfo);
}
/**
* Get the error mode from an error object.
*
* @return int error mode
* @access public
*/
function getMode()
{
return $this->mode;
}
/**
* Get the callback function/method from an error object.
*
* @return mixed callback function or object/method array
* @access public
*/
function getCallback()
{
return $this->callback;
}
/**
* Get the error message from an error object.
*
* @return string full error message
* @access public
*/
function getMessage()
{
return ($this->error_message_prefix . $this->message);
}
/**
* Get error code from an error object
*
* @return int error code
* @access public
*/
function getCode()
{
return $this->code;
}
/**
* Get the name of this error/exception.
*
* @return string error/exception name (type)
* @access public
*/
function getType()
{
return get_class($this);
}
/**
* Get additional user-supplied information.
*
* @return string user-supplied information
* @access public
*/
function getUserInfo()
{
return $this->userinfo;
}
/**
* Get additional debug information supplied by the application.
*
* @return string debug information
* @access public
*/
function getDebugInfo()
{
return $this->getUserInfo();
}
/**
* Get the call backtrace from where the error was generated.
* Supported with PHP 4.3.0 or newer.
*
* @param int $frame (optional) what frame to fetch
* @return array Backtrace, or NULL if not available.
* @access public
*/
function getBacktrace($frame = null)
{
if (defined('PEAR_IGNORE_BACKTRACE')) {
return null;
}
if ($frame === null) {
return $this->backtrace;
}
return $this->backtrace[$frame];
}
function addUserInfo($info)
{
if (empty($this->userinfo)) {
$this->userinfo = $info;
} else {
$this->userinfo .= " ** $info";
}
}
function __toString()
{
return $this->getMessage();
}
/**
* Make a string representation of this object.
*
* @return string a string with an object summary
* @access public
*/
function toString()
{
$modes = array();
$levels = array(E_USER_NOTICE => 'notice',
E_USER_WARNING => 'warning',
E_USER_ERROR => 'error');
if ($this->mode & PEAR_ERROR_CALLBACK) {
if (is_array($this->callback)) {
$callback = (is_object($this->callback[0]) ?
strtolower(get_class($this->callback[0])) :
$this->callback[0]) . '::' .
$this->callback[1];
} else {
$callback = $this->callback;
}
return sprintf('[%s: message="%s" code=%d mode=callback '.
'callback=%s prefix="%s" info="%s"]',
strtolower(get_class($this)), $this->message, $this->code,
$callback, $this->error_message_prefix,
$this->userinfo);
}
if ($this->mode & PEAR_ERROR_PRINT) {
$modes[] = 'print';
}
if ($this->mode & PEAR_ERROR_TRIGGER) {
$modes[] = 'trigger';
}
if ($this->mode & PEAR_ERROR_DIE) {
$modes[] = 'die';
}
if ($this->mode & PEAR_ERROR_RETURN) {
$modes[] = 'return';
}
return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
'prefix="%s" info="%s"]',
strtolower(get_class($this)), $this->message, $this->code,
implode("|", $modes), $levels[$this->level],
$this->error_message_prefix,
$this->userinfo);
}
}
/*
* Local Variables:
* mode: php
* tab-width: 4
* c-basic-offset: 4
* End:
*/
PK �]�C� + + Structures/Graph/Node.phpnu �[��� <?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +-----------------------------------------------------------------------------+
// | Copyright (c) 2003 S�rgio Gon�alves Carvalho |
// +-----------------------------------------------------------------------------+
// | This file is part of Structures_Graph. |
// | |
// | Structures_Graph is free software; you can redistribute it and/or modify |
// | it under the terms of the GNU Lesser General Public License as published by |
// | the Free Software Foundation; either version 2.1 of the License, or |
// | (at your option) any later version. |
// | |
// | Structures_Graph is distributed in the hope that it will be useful, |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// | GNU Lesser General Public License for more details. |
// | |
// | You should have received a copy of the GNU Lesser General Public License |
// | along with Structures_Graph; if not, write to the Free Software |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
// | 02111-1307 USA |
// +-----------------------------------------------------------------------------+
// | Author: S�rgio Carvalho <sergio.carvalho@portugalmail.com> |
// +-----------------------------------------------------------------------------+
//
/**
* This file contains the definition of the Structures_Graph_Node class
*
* @see Structures_Graph_Node
* @package Structures_Graph
*/
/* dependencies {{{ */
/** */
require_once 'PEAR.php';
/** */
require_once 'Structures/Graph.php';
/* }}} */
/* class Structures_Graph_Node {{{ */
/**
* The Structures_Graph_Node class represents a Node that can be member of a
* graph node set.
*
* A graph node can contain data. Under this API, the node contains default data,
* and key index data. It behaves, thus, both as a regular data node, and as a
* dictionary (or associative array) node.
*
* Regular data is accessed via getData and setData. Key indexed data is accessed
* via getMetadata and setMetadata.
*
* @author S�rgio Carvalho <sergio.carvalho@portugalmail.com>
* @copyright (c) 2004 by S�rgio Carvalho
* @package Structures_Graph
*/
/* }}} */
class Structures_Graph_Node {
/* fields {{{ */
/**
* @access private
*/
var $_data = null;
/** @access private */
var $_metadata = array();
/** @access private */
var $_arcs = array();
/** @access private */
var $_graph = null;
/* }}} */
/* Constructor {{{ */
/**
*
* Constructor
*
* @access public
*/
function __construct() {
}
/* }}} */
/* getGraph {{{ */
/**
*
* Node graph getter
*
* @return Structures_Graph Graph where node is stored
* @access public
*/
function &getGraph() {
return $this->_graph;
}
/* }}} */
/* setGraph {{{ */
/**
*
* Node graph setter. This method should not be called directly. Use Graph::addNode instead.
*
* @param Structures_Graph Set the graph for this node.
* @see Structures_Graph::addNode()
* @access public
*/
function setGraph(&$graph) {
$this->_graph =& $graph;
}
/* }}} */
/* getData {{{ */
/**
*
* Node data getter.
*
* Each graph node can contain a reference to one variable. This is the getter for that reference.
*
* @return mixed Data stored in node
* @access public
*/
function &getData() {
return $this->_data;
}
/* }}} */
/* setData {{{ */
/**
*
* Node data setter
*
* Each graph node can contain a reference to one variable. This is the setter for that reference.
*
* @return mixed Data to store in node
* @access public
*/
function setData(&$data) {
$this->_data =& $data;
}
/* }}} */
/* metadataKeyExists {{{ */
/**
*
* Test for existence of metadata under a given key.
*
* Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an
* associative array or in a dictionary. This method tests whether a given metadata key exists for this node.
*
* @param string Key to test
* @return boolean
* @access public
*/
function metadataKeyExists($key) {
return array_key_exists($key, $this->_metadata);
}
/* }}} */
/* getMetadata {{{ */
/**
*
* Node metadata getter
*
* Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an
* associative array or in a dictionary. This method gets the data under the given key. If the key does
* not exist, an error will be thrown, so testing using metadataKeyExists might be needed.
*
* @param string Key
* @param boolean nullIfNonexistent (defaults to false).
* @return mixed Metadata Data stored in node under given key
* @see metadataKeyExists
* @access public
*/
function &getMetadata($key, $nullIfNonexistent = false) {
if (array_key_exists($key, $this->_metadata)) {
return $this->_metadata[$key];
} else {
if ($nullIfNonexistent) {
$a = null;
return $a;
} else {
$a = Pear::raiseError('Structures_Graph_Node::getMetadata: Requested key does not exist', STRUCTURES_GRAPH_ERROR_GENERIC);
return $a;
}
}
}
/* }}} */
/* unsetMetadata {{{ */
/**
*
* Delete metadata by key
*
* Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an
* associative array or in a dictionary. This method removes any data that might be stored under the provided key.
* If the key does not exist, no error is thrown, so it is safe using this method without testing for key existence.
*
* @param string Key
* @access public
*/
function unsetMetadata($key) {
if (array_key_exists($key, $this->_metadata)) unset($this->_metadata[$key]);
}
/* }}} */
/* setMetadata {{{ */
/**
*
* Node metadata setter
*
* Each graph node can contain multiple 'metadata' entries, each stored under a different key, as in an
* associative array or in a dictionary. This method stores data under the given key. If the key already exists,
* previously stored data is discarded.
*
* @param string Key
* @param mixed Data
* @access public
*/
function setMetadata($key, &$data) {
$this->_metadata[$key] =& $data;
}
/* }}} */
/* _connectTo {{{ */
/** @access private */
function _connectTo(&$destinationNode) {
$this->_arcs[] =& $destinationNode;
}
/* }}} */
/* connectTo {{{ */
/**
*
* Connect this node to another one.
*
* If the graph is not directed, the reverse arc, connecting $destinationNode to $this is also created.
*
* @param Structures_Graph_Node Node to connect to
* @access public
*/
function connectTo(&$destinationNode) {
// We only connect to nodes
if (!is_a($destinationNode, 'Structures_Graph_Node')) return Pear::raiseError('Structures_Graph_Node::connectTo received an object that is not a Structures_Graph_Node', STRUCTURES_GRAPH_ERROR_GENERIC);
// Nodes must already be in graphs to be connected
if ($this->_graph == null) return Pear::raiseError('Structures_Graph_Node::connectTo Tried to connect a node that is not in a graph', STRUCTURES_GRAPH_ERROR_GENERIC);
if ($destinationNode->getGraph() == null) return Pear::raiseError('Structures_Graph_Node::connectTo Tried to connect to a node that is not in a graph', STRUCTURES_GRAPH_ERROR_GENERIC);
// Connect here
$this->_connectTo($destinationNode);
// If graph is undirected, connect back
if (!$this->_graph->isDirected()) {
$destinationNode->_connectTo($this);
}
}
/* }}} */
/* getNeighbours {{{ */
/**
*
* Return nodes connected to this one.
*
* @return array Array of nodes
* @access public
*/
function getNeighbours() {
return $this->_arcs;
}
/* }}} */
/* connectsTo {{{ */
/**
*
* Test wether this node has an arc to the target node
*
* @return boolean True if the two nodes are connected
* @access public
*/
function connectsTo(&$target) {
if (version_compare(PHP_VERSION, '5.0.0') >= 0) {
return in_array($target, $this->getNeighbours(), true);
}
$copy = $target;
$arcKeys = array_keys($this->_arcs);
foreach($arcKeys as $key) {
/* ZE1 chokes on this expression:
if ($target === $arc) return true;
so, we'll use more convoluted stuff
*/
$arc =& $this->_arcs[$key];
$target = true;
if ($arc === true) {
$target = false;
if ($arc === false) {
$target = $copy;
return true;
}
}
}
$target = $copy;
return false;
}
/* }}} */
/* inDegree {{{ */
/**
*
* Calculate the in degree of the node.
*
* The indegree for a node is the number of arcs entering the node. For non directed graphs,
* the indegree is equal to the outdegree.
*
* @return integer In degree of the node
* @access public
*/
function inDegree() {
if ($this->_graph == null) return 0;
if (!$this->_graph->isDirected()) return $this->outDegree();
$result = 0;
$graphNodes =& $this->_graph->getNodes();
foreach (array_keys($graphNodes) as $key) {
if ($graphNodes[$key]->connectsTo($this)) $result++;
}
return $result;
}
/* }}} */
/* outDegree {{{ */
/**
*
* Calculate the out degree of the node.
*
* The outdegree for a node is the number of arcs exiting the node. For non directed graphs,
* the outdegree is always equal to the indegree.
*
* @return integer Out degree of the node
* @access public
*/
function outDegree() {
if ($this->_graph == null) return 0;
return sizeof($this->_arcs);
}
/* }}} */
}
?>
PK �]~(�ht t 2 Structures/Graph/Manipulator/TopologicalSorter.phpnu �[��� <?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +-----------------------------------------------------------------------------+
// | Copyright (c) 2003 S�rgio Gon�alves Carvalho |
// +-----------------------------------------------------------------------------+
// | This file is part of Structures_Graph. |
// | |
// | Structures_Graph is free software; you can redistribute it and/or modify |
// | it under the terms of the GNU Lesser General Public License as published by |
// | the Free Software Foundation; either version 2.1 of the License, or |
// | (at your option) any later version. |
// | |
// | Structures_Graph is distributed in the hope that it will be useful, |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// | GNU Lesser General Public License for more details. |
// | |
// | You should have received a copy of the GNU Lesser General Public License |
// | along with Structures_Graph; if not, write to the Free Software |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
// | 02111-1307 USA |
// +-----------------------------------------------------------------------------+
// | Author: S�rgio Carvalho <sergio.carvalho@portugalmail.com> |
// +-----------------------------------------------------------------------------+
//
/**
* This file contains the definition of the Structures_Graph_Manipulator_TopologicalSorter class.
*
* @package Structures_Graph
*/
require_once 'PEAR.php';
require_once 'Structures/Graph.php';
require_once 'Structures/Graph/Node.php';
require_once 'Structures/Graph/Manipulator/AcyclicTest.php';
/**
* The Structures_Graph_Manipulator_TopologicalSorter is a manipulator
* which is able to return the set of nodes in a graph, sorted by topological
* order.
*
* A graph may only be sorted topologically iff it's a DAG. You can test it
* with the Structures_Graph_Manipulator_AcyclicTest.
*
* @author S�rgio Carvalho <sergio.carvalho@portugalmail.com>
* @copyright (c) 2004 by S�rgio Carvalho
* @see Structures_Graph_Manipulator_AcyclicTest
* @package Structures_Graph
*/
class Structures_Graph_Manipulator_TopologicalSorter
{
/**
* This is a variant of Structures_Graph::inDegree which does
* not count nodes marked as visited.
*
* @param object $node Node to check
*
* @return integer Number of non-visited nodes that link to this one
*/
protected static function _nonVisitedInDegree(&$node)
{
$result = 0;
$graphNodes =& $node->_graph->getNodes();
foreach (array_keys($graphNodes) as $key) {
if ((!$graphNodes[$key]->getMetadata('topological-sort-visited'))
&& $graphNodes[$key]->connectsTo($node)
) {
$result++;
}
}
return $result;
}
/**
* Sort implementation
*
* @param object $graph Graph to sort
*
* @return void
*/
protected static function _sort(&$graph)
{
// Mark every node as not visited
$nodes =& $graph->getNodes();
$nodeKeys = array_keys($nodes);
$refGenerator = array();
foreach ($nodeKeys as $key) {
$refGenerator[] = false;
$nodes[$key]->setMetadata(
'topological-sort-visited',
$refGenerator[sizeof($refGenerator) - 1]
);
}
// Iteratively peel off leaf nodes
$topologicalLevel = 0;
do {
// Find out which nodes are leafs (excluding visited nodes)
$leafNodes = array();
foreach ($nodeKeys as $key) {
if ((!$nodes[$key]->getMetadata('topological-sort-visited'))
&& static::_nonVisitedInDegree($nodes[$key]) == 0
) {
$leafNodes[] =& $nodes[$key];
}
}
// Mark leafs as visited
$refGenerator[] = $topologicalLevel;
for ($i = sizeof($leafNodes) - 1; $i>=0; $i--) {
$visited =& $leafNodes[$i]->getMetadata('topological-sort-visited');
$visited = true;
$leafNodes[$i]->setMetadata('topological-sort-visited', $visited);
$leafNodes[$i]->setMetadata(
'topological-sort-level',
$refGenerator[sizeof($refGenerator) - 1]
);
}
$topologicalLevel++;
} while (sizeof($leafNodes) > 0);
// Cleanup visited marks
foreach ($nodeKeys as $key) {
$nodes[$key]->unsetMetadata('topological-sort-visited');
}
}
/**
* Sort returns the graph's nodes, sorted by topological order.
*
* The result is an array with as many entries as topological levels.
* Each entry in this array is an array of nodes within
* the given topological level.
*
* @param object $graph Graph to sort
*
* @return array The graph's nodes, sorted by topological order.
*/
public static function sort(&$graph)
{
// We only sort graphs
if (!is_a($graph, 'Structures_Graph')) {
return Pear::raiseError(
'Structures_Graph_Manipulator_TopologicalSorter::sort received'
. ' an object that is not a Structures_Graph',
STRUCTURES_GRAPH_ERROR_GENERIC
);
}
if (!Structures_Graph_Manipulator_AcyclicTest::isAcyclic($graph)) {
return Pear::raiseError(
'Structures_Graph_Manipulator_TopologicalSorter::sort'
. ' received an graph that has cycles',
STRUCTURES_GRAPH_ERROR_GENERIC
);
}
Structures_Graph_Manipulator_TopologicalSorter::_sort($graph);
$result = array();
// Fill out result array
$nodes =& $graph->getNodes();
$nodeKeys = array_keys($nodes);
foreach ($nodeKeys as $key) {
if (!array_key_exists($nodes[$key]->getMetadata('topological-sort-level'), $result)) {
$result[$nodes[$key]->getMetadata('topological-sort-level')]
= array();
}
$result[$nodes[$key]->getMetadata('topological-sort-level')][]
=& $nodes[$key];
$nodes[$key]->unsetMetadata('topological-sort-level');
}
return $result;
}
}
?>
PK �]9��� � , Structures/Graph/Manipulator/AcyclicTest.phpnu �[��� <?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +-----------------------------------------------------------------------------+
// | Copyright (c) 2003 S�rgio Gon�alves Carvalho |
// +-----------------------------------------------------------------------------+
// | This file is part of Structures_Graph. |
// | |
// | Structures_Graph is free software; you can redistribute it and/or modify |
// | it under the terms of the GNU Lesser General Public License as published by |
// | the Free Software Foundation; either version 2.1 of the License, or |
// | (at your option) any later version. |
// | |
// | Structures_Graph is distributed in the hope that it will be useful, |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// | GNU Lesser General Public License for more details. |
// | |
// | You should have received a copy of the GNU Lesser General Public License |
// | along with Structures_Graph; if not, write to the Free Software |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
// | 02111-1307 USA |
// +-----------------------------------------------------------------------------+
// | Author: S�rgio Carvalho <sergio.carvalho@portugalmail.com> |
// +-----------------------------------------------------------------------------+
//
/**
* This file contains the definition of the Structures_Graph_Manipulator_AcyclicTest graph manipulator.
*
* @see Structures_Graph_Manipulator_AcyclicTest
* @package Structures_Graph
*/
/* dependencies {{{ */
/** */
require_once 'PEAR.php';
/** */
require_once 'Structures/Graph.php';
/** */
require_once 'Structures/Graph/Node.php';
/* }}} */
/* class Structures_Graph_Manipulator_AcyclicTest {{{ */
/**
* The Structures_Graph_Manipulator_AcyclicTest is a graph manipulator
* which tests whether a graph contains a cycle.
*
* The definition of an acyclic graph used in this manipulator is that of a
* DAG. The graph must be directed, or else it is considered cyclic, even when
* there are no arcs.
*
* @author S�rgio Carvalho <sergio.carvalho@portugalmail.com>
* @copyright (c) 2004 by S�rgio Carvalho
* @package Structures_Graph
*/
class Structures_Graph_Manipulator_AcyclicTest {
/* _nonVisitedInDegree {{{ */
/**
*
* This is a variant of Structures_Graph::inDegree which does
* not count nodes marked as visited.
*
* @return integer Number of non-visited nodes that link to this one
*/
protected static function _nonVisitedInDegree(&$node) {
$result = 0;
$graphNodes =& $node->_graph->getNodes();
foreach (array_keys($graphNodes) as $key) {
if ((!$graphNodes[$key]->getMetadata('acyclic-test-visited')) && $graphNodes[$key]->connectsTo($node)) $result++;
}
return $result;
}
/* }}} */
/* _isAcyclic {{{ */
/**
* Check if the graph is acyclic
*/
protected static function _isAcyclic(&$graph) {
// Mark every node as not visited
$nodes =& $graph->getNodes();
$nodeKeys = array_keys($nodes);
$refGenerator = array();
foreach($nodeKeys as $key) {
$refGenerator[] = false;
$nodes[$key]->setMetadata('acyclic-test-visited', $refGenerator[sizeof($refGenerator) - 1]);
}
// Iteratively peel off leaf nodes
do {
// Find out which nodes are leafs (excluding visited nodes)
$leafNodes = array();
foreach($nodeKeys as $key) {
if ((!$nodes[$key]->getMetadata('acyclic-test-visited')) && Structures_Graph_Manipulator_AcyclicTest::_nonVisitedInDegree($nodes[$key]) == 0) {
$leafNodes[] =& $nodes[$key];
}
}
// Mark leafs as visited
for ($i=sizeof($leafNodes) - 1; $i>=0; $i--) {
$visited =& $leafNodes[$i]->getMetadata('acyclic-test-visited');
$visited = true;
$leafNodes[$i]->setMetadata('acyclic-test-visited', $visited);
}
} while (sizeof($leafNodes) > 0);
// If graph is a DAG, there should be no non-visited nodes. Let's try to prove otherwise
$result = true;
foreach($nodeKeys as $key) if (!$nodes[$key]->getMetadata('acyclic-test-visited')) $result = false;
// Cleanup visited marks
foreach($nodeKeys as $key) $nodes[$key]->unsetMetadata('acyclic-test-visited');
return $result;
}
/* }}} */
/* isAcyclic {{{ */
/**
*
* isAcyclic returns true if a graph contains no cycles, false otherwise.
*
* @return boolean true iff graph is acyclic
*/
public static function isAcyclic(&$graph) {
// We only test graphs
if (!is_a($graph, 'Structures_Graph')) return Pear::raiseError('Structures_Graph_Manipulator_AcyclicTest::isAcyclic received an object that is not a Structures_Graph', STRUCTURES_GRAPH_ERROR_GENERIC);
if (!$graph->isDirected()) return false; // Only directed graphs may be acyclic
return Structures_Graph_Manipulator_AcyclicTest::_isAcyclic($graph);
}
/* }}} */
}
/* }}} */
?>
PK �]Uyv� Structures/Graph.phpnu �[��� <?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +-----------------------------------------------------------------------------+
// | Copyright (c) 2003 S�rgio Gon�alves Carvalho |
// +-----------------------------------------------------------------------------+
// | This file is part of Structures_Graph. |
// | |
// | Structures_Graph is free software; you can redistribute it and/or modify |
// | it under the terms of the GNU Lesser General Public License as published by |
// | the Free Software Foundation; either version 2.1 of the License, or |
// | (at your option) any later version. |
// | |
// | Structures_Graph is distributed in the hope that it will be useful, |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// | GNU Lesser General Public License for more details. |
// | |
// | You should have received a copy of the GNU Lesser General Public License |
// | along with Structures_Graph; if not, write to the Free Software |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
// | 02111-1307 USA |
// +-----------------------------------------------------------------------------+
// | Author: S�rgio Carvalho <sergio.carvalho@portugalmail.com> |
// +-----------------------------------------------------------------------------+
//
/**
* The Graph.php file contains the definition of the Structures_Graph class
*
* @package Structures_Graph
*/
/* dependencies {{{ */
require_once 'PEAR.php';
require_once 'Structures/Graph/Node.php';
/* }}} */
define('STRUCTURES_GRAPH_ERROR_GENERIC', 100);
/* class Structures_Graph {{{ */
/**
* The Structures_Graph class represents a graph data structure.
*
* A Graph is a data structure composed by a set of nodes, connected by arcs.
* Graphs may either be directed or undirected. In a directed graph, arcs are
* directional, and can be traveled only one way. In an undirected graph, arcs
* are bidirectional, and can be traveled both ways.
*
* @author S�rgio Carvalho <sergio.carvalho@portugalmail.com>
* @copyright (c) 2004 by S�rgio Carvalho
* @package Structures_Graph
*/
/* }}} */
class Structures_Graph
{
/**
* List of node objects in this graph
* @access private
*/
var $_nodes = array();
/**
* If the graph is directed or not
* @access private
*/
var $_directed = false;
/**
* Constructor
*
* @param boolean $directed Set to true if the graph is directed.
* Set to false if it is not directed.
*/
public function __construct($directed = true)
{
$this->_directed = $directed;
}
/**
* Old constructor (PHP4-style; kept for BC with extending classes)
*
* @param boolean $directed Set to true if the graph is directed.
* Set to false if it is not directed.
*
* @return void
*/
public function Structures_Graph($directed = true)
{
$this->__construct($directed);
}
/**
* Return true if a graph is directed
*
* @return boolean true if the graph is directed
*/
public function isDirected()
{
return (boolean) $this->_directed;
}
/**
* Add a Node to the Graph
*
* @param Structures_Graph_Node $newNode The node to be added.
*
* @return void
*/
public function addNode(&$newNode)
{
// We only add nodes
if (!is_a($newNode, 'Structures_Graph_Node')) {
return Pear::raiseError(
'Structures_Graph::addNode received an object that is not'
. ' a Structures_Graph_Node',
STRUCTURES_GRAPH_ERROR_GENERIC
);
}
//Graphs are node *sets*, so duplicates are forbidden.
// We allow nodes that are exactly equal, but disallow equal references.
foreach ($this->_nodes as $key => $node) {
/*
ZE1 equality operators choke on the recursive cycle introduced
by the _graph field in the Node object.
So, we'll check references the hard way
(change $this->_nodes[$key] and check if the change reflects in
$node)
*/
$savedData = $this->_nodes[$key];
$referenceIsEqualFlag = false;
$this->_nodes[$key] = true;
if ($node === true) {
$this->_nodes[$key] = false;
if ($node === false) {
$referenceIsEqualFlag = true;
}
}
$this->_nodes[$key] = $savedData;
if ($referenceIsEqualFlag) {
return Pear::raiseError(
'Structures_Graph::addNode received an object that is'
. ' a duplicate for this dataset',
STRUCTURES_GRAPH_ERROR_GENERIC
);
}
}
$this->_nodes[] =& $newNode;
$newNode->setGraph($this);
}
/**
* Remove a Node from the Graph
*
* @param Structures_Graph_Node $node The node to be removed from the graph
*
* @return void
* @todo This is unimplemented
*/
public function removeNode(&$node)
{
}
/**
* Return the node set, in no particular order.
* For ordered node sets, use a Graph Manipulator insted.
*
* @return array The set of nodes in this graph
* @see Structures_Graph_Manipulator_TopologicalSorter
*/
public function &getNodes()
{
return $this->_nodes;
}
}
?>
PK �]1%x�cU cU Archive/Tar.phpnu �[��� <?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* File::CSV
*
* PHP versions 4 and 5
*
* Copyright (c) 1997-2008,
* Vincent Blavet <vincent@phpconcept.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @category File_Formats
* @package Archive_Tar
* @author Vincent Blavet <vincent@phpconcept.net>
* @copyright 1997-2010 The Authors
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @version CVS: $Id$
* @link http://pear.php.net/package/Archive_Tar
*/
// If the PEAR class cannot be loaded via the autoloader,
// then try to require_once it from the PHP include path.
if (!class_exists('PEAR')) {
require_once 'PEAR.php';
}
define('ARCHIVE_TAR_ATT_SEPARATOR', 90001);
define('ARCHIVE_TAR_END_BLOCK', pack("a512", ''));
/**
* Creates a (compressed) Tar archive
*
* @package Archive_Tar
* @author Vincent Blavet <vincent@phpconcept.net>
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @version $Revision$
*/
class Archive_Tar extends PEAR
{
/**
* @var string Name of the Tar
*/
public $_tarname = '';
/**
* @var boolean if true, the Tar file will be gzipped
*/
public $_compress = false;
/**
* @var string Type of compression : 'none', 'gz', 'bz2' or 'lzma2'
*/
public $_compress_type = 'none';
/**
* @var string Explode separator
*/
public $_separator = ' ';
/**
* @var file descriptor
*/
public $_file = 0;
/**
* @var string Local Tar name of a remote Tar (http:// or ftp://)
*/
public $_temp_tarname = '';
/**
* @var string regular expression for ignoring files or directories
*/
public $_ignore_regexp = '';
/**
* @var object PEAR_Error object
*/
public $error_object = null;
/**
* Format for data extraction
*
* @var string
*/
public $_fmt = '';
/**
* @var int Length of the read buffer in bytes
*/
protected $buffer_length;
/**
* Archive_Tar Class constructor. This flavour of the constructor only
* declare a new Archive_Tar object, identifying it by the name of the
* tar file.
* If the compress argument is set the tar will be read or created as a
* gzip or bz2 compressed TAR file.
*
* @param string $p_tarname The name of the tar archive to create
* @param string $p_compress can be null, 'gz', 'bz2' or 'lzma2'. This
* parameter indicates if gzip, bz2 or lzma2 compression
* is required. For compatibility reason the
* boolean value 'true' means 'gz'.
* @param int $buffer_length Length of the read buffer in bytes
*
* @return bool
*/
public function __construct($p_tarname, $p_compress = null, $buffer_length = 512)
{
parent::__construct();
$this->_compress = false;
$this->_compress_type = 'none';
if (($p_compress === null) || ($p_compress == '')) {
if (@file_exists($p_tarname)) {
if ($fp = @fopen($p_tarname, "rb")) {
// look for gzip magic cookie
$data = fread($fp, 2);
fclose($fp);
if ($data == "\37\213") {
$this->_compress = true;
$this->_compress_type = 'gz';
// No sure it's enought for a magic code ....
} elseif ($data == "BZ") {
$this->_compress = true;
$this->_compress_type = 'bz2';
} elseif (file_get_contents($p_tarname, false, null, 1, 4) == '7zXZ') {
$this->_compress = true;
$this->_compress_type = 'lzma2';
}
}
} else {
// probably a remote file or some file accessible
// through a stream interface
if (substr($p_tarname, -2) == 'gz') {
$this->_compress = true;
$this->_compress_type = 'gz';
} elseif ((substr($p_tarname, -3) == 'bz2') ||
(substr($p_tarname, -2) == 'bz')
) {
$this->_compress = true;
$this->_compress_type = 'bz2';
} else {
if (substr($p_tarname, -2) == 'xz') {
$this->_compress = true;
$this->_compress_type = 'lzma2';
}
}
}
} else {
if (($p_compress === true) || ($p_compress == 'gz')) {
$this->_compress = true;
$this->_compress_type = 'gz';
} else {
if ($p_compress == 'bz2') {
$this->_compress = true;
$this->_compress_type = 'bz2';
} else {
if ($p_compress == 'lzma2') {
$this->_compress = true;
$this->_compress_type = 'lzma2';
} else {
$this->_error(
"Unsupported compression type '$p_compress'\n" .
"Supported types are 'gz', 'bz2' and 'lzma2'.\n"
);
return false;
}
}
}
}
$this->_tarname = $p_tarname;
if ($this->_compress) { // assert zlib or bz2 or xz extension support
if ($this->_compress_type == 'gz') {
$extname = 'zlib';
} else {
if ($this->_compress_type == 'bz2') {
$extname = 'bz2';
} else {
if ($this->_compress_type == 'lzma2') {
$extname = 'xz';
}
}
}
if (!extension_loaded($extname)) {
PEAR::loadExtension($extname);
}
if (!extension_loaded($extname)) {
$this->_error(
"The extension '$extname' couldn't be found.\n" .
"Please make sure your version of PHP was built " .
"with '$extname' support.\n"
);
return false;
}
}
if (version_compare(PHP_VERSION, "5.5.0-dev") < 0) {
$this->_fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" .
"a8checksum/a1typeflag/a100link/a6magic/a2version/" .
"a32uname/a32gname/a8devmajor/a8devminor/a131prefix";
} else {
$this->_fmt = "Z100filename/Z8mode/Z8uid/Z8gid/a12size/Z12mtime/" .
"Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" .
"Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix";
}
$this->buffer_length = $buffer_length;
}
public function __destruct()
{
$this->_close();
// ----- Look for a local copy to delete
if ($this->_temp_tarname != '' && (bool) preg_match('/^tar[[:alnum:]]*\.tmp$/', $this->_temp_tarname)) {
@unlink($this->_temp_tarname);
}
}
/**
* This method creates the archive file and add the files / directories
* that are listed in $p_filelist.
* If a file with the same name exist and is writable, it is replaced
* by the new tar.
* The method return false and a PEAR error text.
* The $p_filelist parameter can be an array of string, each string
* representing a filename or a directory name with their path if
* needed. It can also be a single string with names separated by a
* single blank.
* For each directory added in the archive, the files and
* sub-directories are also added.
* See also createModify() method for more details.
*
* @param array $p_filelist An array of filenames and directory names, or a
* single string with names separated by a single
* blank space.
*
* @return bool true on success, false on error.
* @see createModify()
*/
public function create($p_filelist)
{
return $this->createModify($p_filelist, '', '');
}
/**
* This method add the files / directories that are listed in $p_filelist in
* the archive. If the archive does not exist it is created.
* The method return false and a PEAR error text.
* The files and directories listed are only added at the end of the archive,
* even if a file with the same name is already archived.
* See also createModify() method for more details.
*
* @param array $p_filelist An array of filenames and directory names, or a
* single string with names separated by a single
* blank space.
*
* @return bool true on success, false on error.
* @see createModify()
* @access public
*/
public function add($p_filelist)
{
return $this->addModify($p_filelist, '', '');
}
/**
* @param string $p_path
* @param bool $p_preserve
* @param bool $p_symlinks
* @return bool
*/
public function extract($p_path = '', $p_preserve = false, $p_symlinks = true)
{
return $this->extractModify($p_path, '', $p_preserve, $p_symlinks);
}
/**
* @return array|int
*/
public function listContent()
{
$v_list_detail = array();
if ($this->_openRead()) {
if (!$this->_extractList('', $v_list_detail, "list", '', '')) {
unset($v_list_detail);
$v_list_detail = 0;
}
$this->_close();
}
return $v_list_detail;
}
/**
* This method creates the archive file and add the files / directories
* that are listed in $p_filelist.
* If the file already exists and is writable, it is replaced by the
* new tar. It is a create and not an add. If the file exists and is
* read-only or is a directory it is not replaced. The method return
* false and a PEAR error text.
* The $p_filelist parameter can be an array of string, each string
* representing a filename or a directory name with their path if
* needed. It can also be a single string with names separated by a
* single blank.
* The path indicated in $p_remove_dir will be removed from the
* memorized path of each file / directory listed when this path
* exists. By default nothing is removed (empty path '')
* The path indicated in $p_add_dir will be added at the beginning of
* the memorized path of each file / directory listed. However it can
* be set to empty ''. The adding of a path is done after the removing
* of path.
* The path add/remove ability enables the user to prepare an archive
* for extraction in a different path than the origin files are.
* See also addModify() method for file adding properties.
*
* @param array $p_filelist An array of filenames and directory names,
* or a single string with names separated by
* a single blank space.
* @param string $p_add_dir A string which contains a path to be added
* to the memorized path of each element in
* the list.
* @param string $p_remove_dir A string which contains a path to be
* removed from the memorized path of each
* element in the list, when relevant.
*
* @return boolean true on success, false on error.
* @see addModify()
*/
public function createModify($p_filelist, $p_add_dir, $p_remove_dir = '')
{
$v_result = true;
if (!$this->_openWrite()) {
return false;
}
if ($p_filelist != '') {
if (is_array($p_filelist)) {
$v_list = $p_filelist;
} elseif (is_string($p_filelist)) {
$v_list = explode($this->_separator, $p_filelist);
} else {
$this->_cleanFile();
$this->_error('Invalid file list');
return false;
}
$v_result = $this->_addList($v_list, $p_add_dir, $p_remove_dir);
}
if ($v_result) {
$this->_writeFooter();
$this->_close();
} else {
$this->_cleanFile();
}
return $v_result;
}
/**
* This method add the files / directories listed in $p_filelist at the
* end of the existing archive. If the archive does not yet exists it
* is created.
* The $p_filelist parameter can be an array of string, each string
* representing a filename or a directory name with their path if
* needed. It can also be a single string with names separated by a
* single blank.
* The path indicated in $p_remove_dir will be removed from the
* memorized path of each file / directory listed when this path
* exists. By default nothing is removed (empty path '')
* The path indicated in $p_add_dir will be added at the beginning of
* the memorized path of each file / directory listed. However it can
* be set to empty ''. The adding of a path is done after the removing
* of path.
* The path add/remove ability enables the user to prepare an archive
* for extraction in a different path than the origin files are.
* If a file/dir is already in the archive it will only be added at the
* end of the archive. There is no update of the existing archived
* file/dir. However while extracting the archive, the last file will
* replace the first one. This results in a none optimization of the
* archive size.
* If a file/dir does not exist the file/dir is ignored. However an
* error text is send to PEAR error.
* If a file/dir is not readable the file/dir is ignored. However an
* error text is send to PEAR error.
*
* @param array $p_filelist An array of filenames and directory
* names, or a single string with names
* separated by a single blank space.
* @param string $p_add_dir A string which contains a path to be
* added to the memorized path of each
* element in the list.
* @param string $p_remove_dir A string which contains a path to be
* removed from the memorized path of
* each element in the list, when
* relevant.
*
* @return bool true on success, false on error.
*/
public function addModify($p_filelist, $p_add_dir, $p_remove_dir = '')
{
$v_result = true;
if (!$this->_isArchive()) {
$v_result = $this->createModify(
$p_filelist,
$p_add_dir,
$p_remove_dir
);
} else {
if (is_array($p_filelist)) {
$v_list = $p_filelist;
} elseif (is_string($p_filelist)) {
$v_list = explode($this->_separator, $p_filelist);
} else {
$this->_error('Invalid file list');
return false;
}
$v_result = $this->_append($v_list, $p_add_dir, $p_remove_dir);
}
return $v_result;
}
/**
* This method add a single string as a file at the
* end of the existing archive. If the archive does not yet exists it
* is created.
*
* @param string $p_filename A string which contains the full
* filename path that will be associated
* with the string.
* @param string $p_string The content of the file added in
* the archive.
* @param bool|int $p_datetime A custom date/time (unix timestamp)
* for the file (optional).
* @param array $p_params An array of optional params:
* stamp => the datetime (replaces
* datetime above if it exists)
* mode => the permissions on the
* file (600 by default)
* type => is this a link? See the
* tar specification for details.
* (default = regular file)
* uid => the user ID of the file
* (default = 0 = root)
* gid => the group ID of the file
* (default = 0 = root)
*
* @return bool true on success, false on error.
*/
public function addString($p_filename, $p_string, $p_datetime = false, $p_params = array())
{
$p_stamp = @$p_params["stamp"] ? $p_params["stamp"] : ($p_datetime ? $p_datetime : time());
$p_mode = @$p_params["mode"] ? $p_params["mode"] : 0600;
$p_type = @$p_params["type"] ? $p_params["type"] : "";
$p_uid = @$p_params["uid"] ? $p_params["uid"] : "";
$p_gid = @$p_params["gid"] ? $p_params["gid"] : "";
$v_result = true;
if (!$this->_isArchive()) {
if (!$this->_openWrite()) {
return false;
}
$this->_close();
}
if (!$this->_openAppend()) {
return false;
}
// Need to check the get back to the temporary file ? ....
$v_result = $this->_addString($p_filename, $p_string, $p_datetime, $p_params);
$this->_writeFooter();
$this->_close();
return $v_result;
}
/**
* This method extract all the content of the archive in the directory
* indicated by $p_path. When relevant the memorized path of the
* files/dir can be modified by removing the $p_remove_path path at the
* beginning of the file/dir path.
* While extracting a file, if the directory path does not exists it is
* created.
* While extracting a file, if the file already exists it is replaced
* without looking for last modification date.
* While extracting a file, if the file already exists and is write
* protected, the extraction is aborted.
* While extracting a file, if a directory with the same name already
* exists, the extraction is aborted.
* While extracting a directory, if a file with the same name already
* exists, the extraction is aborted.
* While extracting a file/directory if the destination directory exist
* and is write protected, or does not exist but can not be created,
* the extraction is aborted.
* If after extraction an extracted file does not show the correct
* stored file size, the extraction is aborted.
* When the extraction is aborted, a PEAR error text is set and false
* is returned. However the result can be a partial extraction that may
* need to be manually cleaned.
*
* @param string $p_path The path of the directory where the
* files/dir need to by extracted.
* @param string $p_remove_path Part of the memorized path that can be
* removed if present at the beginning of
* the file/dir path.
* @param boolean $p_preserve Preserve user/group ownership of files
* @param boolean $p_symlinks Allow symlinks.
*
* @return boolean true on success, false on error.
* @see extractList()
*/
public function extractModify($p_path, $p_remove_path, $p_preserve = false, $p_symlinks = true)
{
$v_result = true;
$v_list_detail = array();
if ($v_result = $this->_openRead()) {
$v_result = $this->_extractList(
$p_path,
$v_list_detail,
"complete",
0,
$p_remove_path,
$p_preserve,
$p_symlinks
);
$this->_close();
}
return $v_result;
}
/**
* This method extract from the archive one file identified by $p_filename.
* The return value is a string with the file content, or NULL on error.
*
* @param string $p_filename The path of the file to extract in a string.
*
* @return a string with the file content or NULL.
*/
public function extractInString($p_filename)
{
if ($this->_openRead()) {
$v_result = $this->_extractInString($p_filename);
$this->_close();
} else {
$v_result = null;
}
return $v_result;
}
/**
* This method extract from the archive only the files indicated in the
* $p_filelist. These files are extracted in the current directory or
* in the directory indicated by the optional $p_path parameter.
* If indicated the $p_remove_path can be used in the same way as it is
* used in extractModify() method.
*
* @param array $p_filelist An array of filenames and directory names,
* or a single string with names separated
* by a single blank space.
* @param string $p_path The path of the directory where the
* files/dir need to by extracted.
* @param string $p_remove_path Part of the memorized path that can be
* removed if present at the beginning of
* the file/dir path.
* @param boolean $p_preserve Preserve user/group ownership of files
* @param boolean $p_symlinks Allow symlinks.
*
* @return bool true on success, false on error.
* @see extractModify()
*/
public function extractList($p_filelist, $p_path = '', $p_remove_path = '', $p_preserve = false, $p_symlinks = true)
{
$v_result = true;
$v_list_detail = array();
if (is_array($p_filelist)) {
$v_list = $p_filelist;
} elseif (is_string($p_filelist)) {
$v_list = explode($this->_separator, $p_filelist);
} else {
$this->_error('Invalid string list');
return false;
}
if ($v_result = $this->_openRead()) {
$v_result = $this->_extractList(
$p_path,
$v_list_detail,
"partial",
$v_list,
$p_remove_path,
$p_preserve,
$p_symlinks
);
$this->_close();
}
return $v_result;
}
/**
* This method set specific attributes of the archive. It uses a variable
* list of parameters, in the format attribute code + attribute values :
* $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ',');
*
* @return bool true on success, false on error.
*/
public function setAttribute()
{
$v_result = true;
// ----- Get the number of variable list of arguments
if (($v_size = func_num_args()) == 0) {
return true;
}
// ----- Get the arguments
$v_att_list = func_get_args();
// ----- Read the attributes
$i = 0;
while ($i < $v_size) {
// ----- Look for next option
switch ($v_att_list[$i]) {
// ----- Look for options that request a string value
case ARCHIVE_TAR_ATT_SEPARATOR :
// ----- Check the number of parameters
if (($i + 1) >= $v_size) {
$this->_error(
'Invalid number of parameters for '
. 'attribute ARCHIVE_TAR_ATT_SEPARATOR'
);
return false;
}
// ----- Get the value
$this->_separator = $v_att_list[$i + 1];
$i++;
break;
default :
$this->_error('Unknown attribute code ' . $v_att_list[$i] . '');
return false;
}
// ----- Next attribute
$i++;
}
return $v_result;
}
/**
* This method sets the regular expression for ignoring files and directories
* at import, for example:
* $arch->setIgnoreRegexp("#CVS|\.svn#");
*
* @param string $regexp regular expression defining which files or directories to ignore
*/
public function setIgnoreRegexp($regexp)
{
$this->_ignore_regexp = $regexp;
}
/**
* This method sets the regular expression for ignoring all files and directories
* matching the filenames in the array list at import, for example:
* $arch->setIgnoreList(array('CVS', '.svn', 'bin/tool'));
*
* @param array $list a list of file or directory names to ignore
*
* @access public
*/
public function setIgnoreList($list)
{
$list = str_replace(array('#', '.', '^', '$'), array('\#', '\.', '\^', '\$'), $list);
$regexp = '#/' . join('$|/', $list) . '#';
$this->setIgnoreRegexp($regexp);
}
/**
* @param string $p_message
*/
public function _error($p_message)
{
$this->error_object = $this->raiseError($p_message);
}
/**
* @param string $p_message
*/
public function _warning($p_message)
{
$this->error_object = $this->raiseError($p_message);
}
/**
* @param string $p_filename
* @return bool
*/
public function _isArchive($p_filename = null)
{
if ($p_filename == null) {
$p_filename = $this->_tarname;
}
clearstatcache();
return @is_file($p_filename) && !@is_link($p_filename);
}
/**
* @return bool
*/
public function _openWrite()
{
if ($this->_compress_type == 'gz' && function_exists('gzopen')) {
$this->_file = @gzopen($this->_tarname, "wb9");
} else {
if ($this->_compress_type == 'bz2' && function_exists('bzopen')) {
$this->_file = @bzopen($this->_tarname, "w");
} else {
if ($this->_compress_type == 'lzma2' && function_exists('xzopen')) {
$this->_file = @xzopen($this->_tarname, 'w');
} else {
if ($this->_compress_type == 'none') {
$this->_file = @fopen($this->_tarname, "wb");
} else {
$this->_error(
'Unknown or missing compression type ('
. $this->_compress_type . ')'
);
return false;
}
}
}
}
if ($this->_file == 0) {
$this->_error(
'Unable to open in write mode \''
. $this->_tarname . '\''
);
return false;
}
return true;
}
/**
* @return bool
*/
public function _openRead()
{
if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') {
// ----- Look if a local copy need to be done
if ($this->_temp_tarname == '') {
$this->_temp_tarname = uniqid('tar') . '.tmp';
if (!$v_file_from = @fopen($this->_tarname, 'rb')) {
$this->_error(
'Unable to open in read mode \''
. $this->_tarname . '\''
);
$this->_temp_tarname = '';
return false;
}
if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) {
$this->_error(
'Unable to open in write mode \''
. $this->_temp_tarname . '\''
);
$this->_temp_tarname = '';
return false;
}
while ($v_data = @fread($v_file_from, 1024)) {
@fwrite($v_file_to, $v_data);
}
@fclose($v_file_from);
@fclose($v_file_to);
}
// ----- File to open if the local copy
$v_filename = $this->_temp_tarname;
} else {
// ----- File to open if the normal Tar file
$v_filename = $this->_tarname;
}
if ($this->_compress_type == 'gz' && function_exists('gzopen')) {
$this->_file = @gzopen($v_filename, "rb");
} else {
if ($this->_compress_type == 'bz2' && function_exists('bzopen')) {
$this->_file = @bzopen($v_filename, "r");
} else {
if ($this->_compress_type == 'lzma2' && function_exists('xzopen')) {
$this->_file = @xzopen($v_filename, "r");
} else {
if ($this->_compress_type == 'none') {
$this->_file = @fopen($v_filename, "rb");
} else {
$this->_error(
'Unknown or missing compression type ('
. $this->_compress_type . ')'
);
return false;
}
}
}
}
if ($this->_file == 0) {
$this->_error('Unable to open in read mode \'' . $v_filename . '\'');
return false;
}
return true;
}
/**
* @return bool
*/
public function _openReadWrite()
{
if ($this->_compress_type == 'gz') {
$this->_file = @gzopen($this->_tarname, "r+b");
} else {
if ($this->_compress_type == 'bz2') {
$this->_error(
'Unable to open bz2 in read/write mode \''
. $this->_tarname . '\' (limitation of bz2 extension)'
);
return false;
} else {
if ($this->_compress_type == 'lzma2') {
$this->_error(
'Unable to open lzma2 in read/write mode \''
. $this->_tarname . '\' (limitation of lzma2 extension)'
);
return false;
} else {
if ($this->_compress_type == 'none') {
$this->_file = @fopen($this->_tarname, "r+b");
} else {
$this->_error(
'Unknown or missing compression type ('
. $this->_compress_type . ')'
);
return false;
}
}
}
}
if ($this->_file == 0) {
$this->_error(
'Unable to open in read/write mode \''
. $this->_tarname . '\''
);
return false;
}
return true;
}
/**
* @return bool
*/
public function _close()
{
//if (isset($this->_file)) {
if (is_resource($this->_file)) {
if ($this->_compress_type == 'gz') {
@gzclose($this->_file);
} else {
if ($this->_compress_type == 'bz2') {
@bzclose($this->_file);
} else {
if ($this->_compress_type == 'lzma2') {
@xzclose($this->_file);
} else {
if ($this->_compress_type == 'none') {
@fclose($this->_file);
} else {
$this->_error(
'Unknown or missing compression type ('
. $this->_compress_type . ')'
);
}
}
}
}
$this->_file = 0;
}
// ----- Look if a local copy need to be erase
// Note that it might be interesting to keep the url for a time : ToDo
if ($this->_temp_tarname != '') {
@unlink($this->_temp_tarname);
$this->_temp_tarname = '';
}
return true;
}
/**
* @return bool
*/
public function _cleanFile()
{
$this->_close();
// ----- Look for a local copy
if ($this->_temp_tarname != '') {
// ----- Remove the local copy but not the remote tarname
@unlink($this->_temp_tarname);
$this->_temp_tarname = '';
} else {
// ----- Remove the local tarname file
@unlink($this->_tarname);
}
$this->_tarname = '';
return true;
}
/**
* @param mixed $p_binary_data
* @param integer $p_len
* @return bool
*/
public function _writeBlock($p_binary_data, $p_len = null)
{
if (is_resource($this->_file)) {
if ($p_len === null) {
switch ($this->_compress_type)
{
case 'gz':
$bytes = @gzwrite($this->_file, $p_binary_data);
break;
case 'bz2':
$bytes = @bzwrite($this->_file, $p_binary_data);
break;
case 'lzma2':
$bytes = @xzwrite($this->_file, $p_binary_data);
break;
case 'none':
$bytes = @fwrite($this->_file, $p_binary_data);
break;
default:
$this->_error('Unknown or missing compression type (' . $this->_compress_type . ')');
return false;
}
} else {
switch ($this->_compress_type)
{
case 'gz':
$bytes = @gzwrite($this->_file, $p_binary_data, $p_len);
break;
case 'bz2':
$bytes = @bzwrite($this->_file, $p_binary_data, $p_len);
break;
case 'lzma2':
$bytes = @xzwrite($this->_file, $p_binary_data, $p_len);
break;
case 'none':
$bytes = @fwrite($this->_file, $p_binary_data, $p_len);
break;
default:
$this->_error('Unknown or missing compression type (' . $this->_compress_type . ')');
return false;
}
}
return $bytes !== false;
}
return true;
}
/**
* @return null|string
*/
public function _readBlock()
{
$v_block = null;
if (is_resource($this->_file)) {
if ($this->_compress_type == 'gz') {
$v_block = @gzread($this->_file, 512);
} else {
if ($this->_compress_type == 'bz2') {
$v_block = @bzread($this->_file, 512);
} else {
if ($this->_compress_type == 'lzma2') {
$v_block = @xzread($this->_file, 512);
} else {
if ($this->_compress_type == 'none') {
$v_block = @fread($this->_file, 512);
} else {
$this->_error(
'Unknown or missing compression type ('
. $this->_compress_type . ')'
);
}
}
}
}
}
return $v_block;
}
/**
* @param null $p_len
* @return bool
*/
public function _jumpBlock($p_len = null)
{
if (is_resource($this->_file)) {
if ($p_len === null) {
$p_len = 1;
}
if ($this->_compress_type == 'gz') {
@gzseek($this->_file, gztell($this->_file) + ($p_len * 512));
} else {
if ($this->_compress_type == 'bz2') {
// ----- Replace missing bztell() and bzseek()
for ($i = 0; $i < $p_len; $i++) {
$this->_readBlock();
}
} else {
if ($this->_compress_type == 'lzma2') {
// ----- Replace missing xztell() and xzseek()
for ($i = 0; $i < $p_len; $i++) {
$this->_readBlock();
}
} else {
if ($this->_compress_type == 'none') {
@fseek($this->_file, $p_len * 512, SEEK_CUR);
} else {
$this->_error(
'Unknown or missing compression type ('
. $this->_compress_type . ')'
);
}
}
}
}
}
return true;
}
/**
* @return bool
*/
public function _writeFooter()
{
if (is_resource($this->_file)) {
// ----- Write the last 0 filled block for end of archive
$v_binary_data = pack('a1024', '');
return $this->_writeBlock($v_binary_data);
}
return true;
}
/**
* @param array $p_list
* @param string $p_add_dir
* @param string $p_remove_dir
* @return bool
*/
public function _addList($p_list, $p_add_dir, $p_remove_dir)
{
$v_result = true;
$v_header = array();
// ----- Remove potential windows directory separator
$p_add_dir = $this->_translateWinPath($p_add_dir);
$p_remove_dir = $this->_translateWinPath($p_remove_dir, false);
if (!$this->_file) {
$this->_error('Invalid file descriptor');
return false;
}
if (sizeof($p_list) == 0) {
return true;
}
foreach ($p_list as $v_filename) {
if (!$v_result) {
break;
}
// ----- Skip the current tar name
if ($v_filename == $this->_tarname) {
continue;
}
if ($v_filename == '') {
continue;
}
// ----- ignore files and directories matching the ignore regular expression
if ($this->_ignore_regexp && preg_match($this->_ignore_regexp, '/' . $v_filename)) {
$this->_warning("File '$v_filename' ignored");
continue;
}
if (!file_exists($v_filename) && !is_link($v_filename)) {
$this->_warning("File '$v_filename' does not exist");
continue;
}
// ----- Add the file or directory header
if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir)) {
return false;
}
if (@is_dir($v_filename) && !@is_link($v_filename)) {
if (!($p_hdir = opendir($v_filename))) {
$this->_warning("Directory '$v_filename' can not be read");
continue;
}
while (false !== ($p_hitem = readdir($p_hdir))) {
if (($p_hitem != '.') && ($p_hitem != '..')) {
if ($v_filename != ".") {
$p_temp_list[0] = $v_filename . '/' . $p_hitem;
} else {
$p_temp_list[0] = $p_hitem;
}
$v_result = $this->_addList(
$p_temp_list,
$p_add_dir,
$p_remove_dir
);
}
}
unset($p_temp_list);
unset($p_hdir);
unset($p_hitem);
}
}
return $v_result;
}
/**
* @param string $p_filename
* @param mixed $p_header
* @param string $p_add_dir
* @param string $p_remove_dir
* @param null $v_stored_filename
* @return bool
*/
public function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $v_stored_filename = null)
{
if (!$this->_file) {
$this->_error('Invalid file descriptor');
return false;
}
if ($p_filename == '') {
$this->_error('Invalid file name');
return false;
}
if (is_null($v_stored_filename)) {
// ----- Calculate the stored filename
$p_filename = $this->_translateWinPath($p_filename, false);
$v_stored_filename = $p_filename;
if (strcmp($p_filename, $p_remove_dir) == 0) {
return true;
}
if ($p_remove_dir != '') {
if (substr($p_remove_dir, -1) != '/') {
$p_remove_dir .= '/';
}
if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir) {
$v_stored_filename = substr($p_filename, strlen($p_remove_dir));
}
}
$v_stored_filename = $this->_translateWinPath($v_stored_filename);
if ($p_add_dir != '') {
if (substr($p_add_dir, -1) == '/') {
$v_stored_filename = $p_add_dir . $v_stored_filename;
} else {
$v_stored_filename = $p_add_dir . '/' . $v_stored_filename;
}
}
$v_stored_filename = $this->_pathReduction($v_stored_filename);
}
if ($this->_isArchive($p_filename)) {
if (($v_file = @fopen($p_filename, "rb")) == 0) {
$this->_warning(
"Unable to open file '" . $p_filename
. "' in binary read mode"
);
return true;
}
if (!$this->_writeHeader($p_filename, $v_stored_filename)) {
return false;
}
while (($v_buffer = fread($v_file, $this->buffer_length)) != '') {
$buffer_length = strlen("$v_buffer");
if ($buffer_length != $this->buffer_length) {
$pack_size = ((int)($buffer_length / 512) + ($buffer_length % 512 !== 0 ? 1 : 0)) * 512;
$pack_format = sprintf('a%d', $pack_size);
} else {
$pack_format = sprintf('a%d', $this->buffer_length);
}
$v_binary_data = pack($pack_format, "$v_buffer");
if(!$this->_writeBlock($v_binary_data)) {
return false;
}
}
fclose($v_file);
} else {
// ----- Only header for dir
if (!$this->_writeHeader($p_filename, $v_stored_filename)) {
return false;
}
}
return true;
}
/**
* @param string $p_filename
* @param string $p_string
* @param bool $p_datetime
* @param array $p_params
* @return bool
*/
public function _addString($p_filename, $p_string, $p_datetime = false, $p_params = array())
{
$p_stamp = @$p_params["stamp"] ? $p_params["stamp"] : ($p_datetime ? $p_datetime : time());
$p_mode = @$p_params["mode"] ? $p_params["mode"] : 0600;
$p_type = @$p_params["type"] ? $p_params["type"] : "";
$p_uid = @$p_params["uid"] ? $p_params["uid"] : 0;
$p_gid = @$p_params["gid"] ? $p_params["gid"] : 0;
if (!$this->_file) {
$this->_error('Invalid file descriptor');
return false;
}
if ($p_filename == '') {
$this->_error('Invalid file name');
return false;
}
// ----- Calculate the stored filename
$p_filename = $this->_translateWinPath($p_filename, false);
// ----- If datetime is not specified, set current time
if ($p_datetime === false) {
$p_datetime = time();
}
if (!$this->_writeHeaderBlock(
$p_filename,
strlen($p_string),
$p_stamp,
$p_mode,
$p_type,
$p_uid,
$p_gid
)
) {
return false;
}
$i = 0;
while (($v_buffer = substr($p_string, (($i++) * 512), 512)) != '') {
$v_binary_data = pack("a512", $v_buffer);
if (!$this->_writeBlock($v_binary_data)) {
return false;
}
}
return true;
}
/**
* @param string $p_filename
* @param string $p_stored_filename
* @return bool
*/
public function _writeHeader($p_filename, $p_stored_filename)
{
if ($p_stored_filename == '') {
$p_stored_filename = $p_filename;
}
$v_reduced_filename = $this->_pathReduction($p_stored_filename);
if (strlen($v_reduced_filename) > 99) {
if (!$this->_writeLongHeader($v_reduced_filename, false)) {
return false;
}
}
$v_linkname = '';
if (@is_link($p_filename)) {
$v_linkname = readlink($p_filename);
}
if (strlen($v_linkname) > 99) {
if (!$this->_writeLongHeader($v_linkname, true)) {
return false;
}
}
$v_info = lstat($p_filename);
$v_uid = sprintf("%07s", DecOct($v_info[4]));
$v_gid = sprintf("%07s", DecOct($v_info[5]));
$v_perms = sprintf("%07s", DecOct($v_info['mode'] & 000777));
$v_mtime = sprintf("%011s", DecOct($v_info['mtime']));
if (@is_link($p_filename)) {
$v_typeflag = '2';
$v_size = sprintf("%011s", DecOct(0));
} elseif (@is_dir($p_filename)) {
$v_typeflag = "5";
$v_size = sprintf("%011s", DecOct(0));
} else {
$v_typeflag = '0';
clearstatcache();
$v_size = sprintf("%011s", DecOct($v_info['size']));
}
$v_magic = 'ustar ';
$v_version = ' ';
$v_uname = '';
$v_gname = '';
if (function_exists('posix_getpwuid')) {
$userinfo = posix_getpwuid($v_info[4]);
$groupinfo = posix_getgrgid($v_info[5]);
if (isset($userinfo['name'])) {
$v_uname = $userinfo['name'];
}
if (isset($groupinfo['name'])) {
$v_gname = $groupinfo['name'];
}
}
$v_devmajor = '';
$v_devminor = '';
$v_prefix = '';
$v_binary_data_first = pack(
"a100a8a8a8a12a12",
$v_reduced_filename,
$v_perms,
$v_uid,
$v_gid,
$v_size,
$v_mtime
);
$v_binary_data_last = pack(
"a1a100a6a2a32a32a8a8a155a12",
$v_typeflag,
$v_linkname,
$v_magic,
$v_version,
$v_uname,
$v_gname,
$v_devmajor,
$v_devminor,
$v_prefix,
''
);
// ----- Calculate the checksum
$v_checksum = 0;
// ..... First part of the header
for ($i = 0; $i < 148; $i++) {
$v_checksum += ord(substr($v_binary_data_first, $i, 1));
}
// ..... Ignore the checksum value and replace it by ' ' (space)
for ($i = 148; $i < 156; $i++) {
$v_checksum += ord(' ');
}
// ..... Last part of the header
for ($i = 156, $j = 0; $i < 512; $i++, $j++) {
$v_checksum += ord(substr($v_binary_data_last, $j, 1));
}
// ----- Write the first 148 bytes of the header in the archive
$this->_writeBlock($v_binary_data_first, 148);
// ----- Write the calculated checksum
$v_checksum = sprintf("%06s\0 ", DecOct($v_checksum));
$v_binary_data = pack("a8", $v_checksum);
$this->_writeBlock($v_binary_data, 8);
// ----- Write the last 356 bytes of the header in the archive
$this->_writeBlock($v_binary_data_last, 356);
return true;
}
/**
* @param string $p_filename
* @param int $p_size
* @param int $p_mtime
* @param int $p_perms
* @param string $p_type
* @param int $p_uid
* @param int $p_gid
* @return bool
*/
public function _writeHeaderBlock(
$p_filename,
$p_size,
$p_mtime = 0,
$p_perms = 0,
$p_type = '',
$p_uid = 0,
$p_gid = 0
)
{
$p_filename = $this->_pathReduction($p_filename);
if (strlen($p_filename) > 99) {
if (!$this->_writeLongHeader($p_filename, false)) {
return false;
}
}
if ($p_type == "5") {
$v_size = sprintf("%011s", DecOct(0));
} else {
$v_size = sprintf("%011s", DecOct($p_size));
}
$v_uid = sprintf("%07s", DecOct($p_uid));
$v_gid = sprintf("%07s", DecOct($p_gid));
$v_perms = sprintf("%07s", DecOct($p_perms & 000777));
$v_mtime = sprintf("%11s", DecOct($p_mtime));
$v_linkname = '';
$v_magic = 'ustar ';
$v_version = ' ';
if (function_exists('posix_getpwuid')) {
$userinfo = posix_getpwuid($p_uid);
$groupinfo = posix_getgrgid($p_gid);
if ($userinfo === false || $groupinfo === false) {
$v_uname = '';
$v_gname = '';
} else {
$v_uname = $userinfo['name'];
$v_gname = $groupinfo['name'];
}
} else {
$v_uname = '';
$v_gname = '';
}
$v_devmajor = '';
$v_devminor = '';
$v_prefix = '';
$v_binary_data_first = pack(
"a100a8a8a8a12A12",
$p_filename,
$v_perms,
$v_uid,
$v_gid,
$v_size,
$v_mtime
);
$v_binary_data_last = pack(
"a1a100a6a2a32a32a8a8a155a12",
$p_type,
$v_linkname,
$v_magic,
$v_version,
$v_uname,
$v_gname,
$v_devmajor,
$v_devminor,
$v_prefix,
''
);
// ----- Calculate the checksum
$v_checksum = 0;
// ..... First part of the header
for ($i = 0; $i < 148; $i++) {
$v_checksum += ord(substr($v_binary_data_first, $i, 1));
}
// ..... Ignore the checksum value and replace it by ' ' (space)
for ($i = 148; $i < 156; $i++) {
$v_checksum += ord(' ');
}
// ..... Last part of the header
for ($i = 156, $j = 0; $i < 512; $i++, $j++) {
$v_checksum += ord(substr($v_binary_data_last, $j, 1));
}
// ----- Write the first 148 bytes of the header in the archive
$this->_writeBlock($v_binary_data_first, 148);
// ----- Write the calculated checksum
$v_checksum = sprintf("%06s ", DecOct($v_checksum));
$v_binary_data = pack("a8", $v_checksum);
$this->_writeBlock($v_binary_data, 8);
// ----- Write the last 356 bytes of the header in the archive
$this->_writeBlock($v_binary_data_last, 356);
return true;
}
/**
* @param string $p_filename
* @return bool
*/
public function _writeLongHeader($p_filename, $is_link = false)
{
$v_uid = sprintf("%07s", 0);
$v_gid = sprintf("%07s", 0);
$v_perms = sprintf("%07s", 0);
$v_size = sprintf("%'011s", DecOct(strlen($p_filename)));
$v_mtime = sprintf("%011s", 0);
$v_typeflag = ($is_link ? 'K' : 'L');
$v_linkname = '';
$v_magic = 'ustar ';
$v_version = ' ';
$v_uname = '';
$v_gname = '';
$v_devmajor = '';
$v_devminor = '';
$v_prefix = '';
$v_binary_data_first = pack(
"a100a8a8a8a12a12",
'././@LongLink',
$v_perms,
$v_uid,
$v_gid,
$v_size,
$v_mtime
);
$v_binary_data_last = pack(
"a1a100a6a2a32a32a8a8a155a12",
$v_typeflag,
$v_linkname,
$v_magic,
$v_version,
$v_uname,
$v_gname,
$v_devmajor,
$v_devminor,
$v_prefix,
''
);
// ----- Calculate the checksum
$v_checksum = 0;
// ..... First part of the header
for ($i = 0; $i < 148; $i++) {
$v_checksum += ord(substr($v_binary_data_first, $i, 1));
}
// ..... Ignore the checksum value and replace it by ' ' (space)
for ($i = 148; $i < 156; $i++) {
$v_checksum += ord(' ');
}
// ..... Last part of the header
for ($i = 156, $j = 0; $i < 512; $i++, $j++) {
$v_checksum += ord(substr($v_binary_data_last, $j, 1));
}
// ----- Write the first 148 bytes of the header in the archive
$this->_writeBlock($v_binary_data_first, 148);
// ----- Write the calculated checksum
$v_checksum = sprintf("%06s\0 ", DecOct($v_checksum));
$v_binary_data = pack("a8", $v_checksum);
$this->_writeBlock($v_binary_data, 8);
// ----- Write the last 356 bytes of the header in the archive
$this->_writeBlock($v_binary_data_last, 356);
// ----- Write the filename as content of the block
$i = 0;
while (($v_buffer = substr($p_filename, (($i++) * 512), 512)) != '') {
$v_binary_data = pack("a512", "$v_buffer");
$this->_writeBlock($v_binary_data);
}
return true;
}
/**
* @param mixed $v_binary_data
* @param mixed $v_header
* @return bool
*/
public function _readHeader($v_binary_data, &$v_header)
{
if (strlen($v_binary_data) == 0) {
$v_header['filename'] = '';
return true;
}
if (strlen($v_binary_data) != 512) {
$v_header['filename'] = '';
$this->_error('Invalid block size : ' . strlen($v_binary_data));
return false;
}
if (!is_array($v_header)) {
$v_header = array();
}
// ----- Calculate the checksum
$v_checksum = 0;
// ..... First part of the header
$v_binary_split = str_split($v_binary_data);
$v_checksum += array_sum(array_map('ord', array_slice($v_binary_split, 0, 148)));
$v_checksum += array_sum(array_map('ord', array(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',)));
$v_checksum += array_sum(array_map('ord', array_slice($v_binary_split, 156, 512)));
$v_data = unpack($this->_fmt, $v_binary_data);
if (strlen($v_data["prefix"]) > 0) {
$v_data["filename"] = "$v_data[prefix]/$v_data[filename]";
}
// ----- Extract the checksum
$v_data_checksum = trim($v_data['checksum']);
if (!preg_match('/^[0-7]*$/', $v_data_checksum)) {
$this->_error(
'Invalid checksum for file "' . $v_data['filename']
. '" : ' . $v_data_checksum . ' extracted'
);
return false;
}
$v_header['checksum'] = OctDec($v_data_checksum);
if ($v_header['checksum'] != $v_checksum) {
$v_header['filename'] = '';
// ----- Look for last block (empty block)
if (($v_checksum == 256) && ($v_header['checksum'] == 0)) {
return true;
}
$this->_error(
'Invalid checksum for file "' . $v_data['filename']
. '" : ' . $v_checksum . ' calculated, '
. $v_header['checksum'] . ' expected'
);
return false;
}
// ----- Extract the properties
$v_header['filename'] = rtrim($v_data['filename'], "\0");
if ($this->_isMaliciousFilename($v_header['filename'])) {
$this->_error(
'Malicious .tar detected, file "' . $v_header['filename'] .
'" will not install in desired directory tree'
);
return false;
}
$v_header['mode'] = OctDec(trim($v_data['mode']));
$v_header['uid'] = OctDec(trim($v_data['uid']));
$v_header['gid'] = OctDec(trim($v_data['gid']));
$v_header['size'] = $this->_tarRecToSize($v_data['size']);
$v_header['mtime'] = OctDec(trim($v_data['mtime']));
if (($v_header['typeflag'] = $v_data['typeflag']) == "5") {
$v_header['size'] = 0;
}
$v_header['link'] = trim($v_data['link']);
/* ----- All these fields are removed form the header because
they do not carry interesting info
$v_header[magic] = trim($v_data[magic]);
$v_header[version] = trim($v_data[version]);
$v_header[uname] = trim($v_data[uname]);
$v_header[gname] = trim($v_data[gname]);
$v_header[devmajor] = trim($v_data[devmajor]);
$v_header[devminor] = trim($v_data[devminor]);
*/
return true;
}
/**
* Convert Tar record size to actual size
*
* @param string $tar_size
* @return size of tar record in bytes
*/
private function _tarRecToSize($tar_size)
{
/*
* First byte of size has a special meaning if bit 7 is set.
*
* Bit 7 indicates base-256 encoding if set.
* Bit 6 is the sign bit.
* Bits 5:0 are most significant value bits.
*/
$ch = ord($tar_size[0]);
if ($ch & 0x80) {
// Full 12-bytes record is required.
$rec_str = $tar_size . "\x00";
$size = ($ch & 0x40) ? -1 : 0;
$size = ($size << 6) | ($ch & 0x3f);
for ($num_ch = 1; $num_ch < 12; ++$num_ch) {
$size = ($size * 256) + ord($rec_str[$num_ch]);
}
return $size;
} else {
return OctDec(trim($tar_size));
}
}
/**
* Detect and report a malicious file name
*
* @param string $file
*
* @return bool
*/
private function _isMaliciousFilename($file)
{
if (strpos($file, '://') !== false) {
return true;
}
if (strpos($file, '../') !== false || strpos($file, '..\\') !== false) {
return true;
}
return false;
}
/**
* @param $v_header
* @return bool
*/
public function _readLongHeader(&$v_header)
{
$v_filename = '';
$v_filesize = $v_header['size'];
$n = floor($v_header['size'] / 512);
for ($i = 0; $i < $n; $i++) {
$v_content = $this->_readBlock();
$v_filename .= $v_content;
}
if (($v_header['size'] % 512) != 0) {
$v_content = $this->_readBlock();
$v_filename .= $v_content;
}
// ----- Read the next header
$v_binary_data = $this->_readBlock();
if (!$this->_readHeader($v_binary_data, $v_header)) {
return false;
}
$v_filename = rtrim(substr($v_filename, 0, $v_filesize), "\0");
$v_header['filename'] = $v_filename;
if ($this->_isMaliciousFilename($v_filename)) {
$this->_error(
'Malicious .tar detected, file "' . $v_filename .
'" will not install in desired directory tree'
);
return false;
}
return true;
}
/**
* This method extract from the archive one file identified by $p_filename.
* The return value is a string with the file content, or null on error.
*
* @param string $p_filename The path of the file to extract in a string.
*
* @return a string with the file content or null.
*/
private function _extractInString($p_filename)
{
$v_result_str = "";
while (strlen($v_binary_data = $this->_readBlock()) != 0) {
if (!$this->_readHeader($v_binary_data, $v_header)) {
return null;
}
if ($v_header['filename'] == '') {
continue;
}
switch ($v_header['typeflag']) {
case 'L':
{
if (!$this->_readLongHeader($v_header)) {
return null;
}
}
break;
case 'K':
{
$v_link_header = $v_header;
if (!$this->_readLongHeader($v_link_header)) {
return null;
}
$v_header['link'] = $v_link_header['filename'];
}
break;
}
if ($v_header['filename'] == $p_filename) {
if ($v_header['typeflag'] == "5") {
$this->_error(
'Unable to extract in string a directory '
. 'entry {' . $v_header['filename'] . '}'
);
return null;
} else {
$n = floor($v_header['size'] / 512);
for ($i = 0; $i < $n; $i++) {
$v_result_str .= $this->_readBlock();
}
if (($v_header['size'] % 512) != 0) {
$v_content = $this->_readBlock();
$v_result_str .= substr(
$v_content,
0,
($v_header['size'] % 512)
);
}
return $v_result_str;
}
} else {
$this->_jumpBlock(ceil(($v_header['size'] / 512)));
}
}
return null;
}
/**
* @param string $p_path
* @param string $p_list_detail
* @param string $p_mode
* @param string $p_file_list
* @param string $p_remove_path
* @param bool $p_preserve
* @param bool $p_symlinks
* @return bool
*/
public function _extractList(
$p_path,
&$p_list_detail,
$p_mode,
$p_file_list,
$p_remove_path,
$p_preserve = false,
$p_symlinks = true
)
{
$v_result = true;
$v_nb = 0;
$v_extract_all = true;
$v_listing = false;
$p_path = $this->_translateWinPath($p_path, false);
if ($p_path == '' || (substr($p_path, 0, 1) != '/'
&& substr($p_path, 0, 3) != "../" && !strpos($p_path, ':'))
) {
$p_path = "./" . $p_path;
}
$p_remove_path = $this->_translateWinPath($p_remove_path);
// ----- Look for path to remove format (should end by /)
if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/')) {
$p_remove_path .= '/';
}
$p_remove_path_size = strlen($p_remove_path);
switch ($p_mode) {
case "complete" :
$v_extract_all = true;
$v_listing = false;
break;
case "partial" :
$v_extract_all = false;
$v_listing = false;
break;
case "list" :
$v_extract_all = false;
$v_listing = true;
break;
default :
$this->_error('Invalid extract mode (' . $p_mode . ')');
return false;
}
clearstatcache();
while (strlen($v_binary_data = $this->_readBlock()) != 0) {
$v_extract_file = false;
$v_extraction_stopped = 0;
if (!$this->_readHeader($v_binary_data, $v_header)) {
return false;
}
if ($v_header['filename'] == '') {
continue;
}
switch ($v_header['typeflag']) {
case 'L':
{
if (!$this->_readLongHeader($v_header)) {
return null;
}
}
break;
case 'K':
{
$v_link_header = $v_header;
if (!$this->_readLongHeader($v_link_header)) {
return null;
}
$v_header['link'] = $v_link_header['filename'];
}
break;
}
// ignore extended / pax headers
if ($v_header['typeflag'] == 'x' || $v_header['typeflag'] == 'g') {
$this->_jumpBlock(ceil(($v_header['size'] / 512)));
continue;
}
if ((!$v_extract_all) && (is_array($p_file_list))) {
// ----- By default no unzip if the file is not found
$v_extract_file = false;
for ($i = 0; $i < sizeof($p_file_list); $i++) {
// ----- Look if it is a directory
if (substr($p_file_list[$i], -1) == '/') {
// ----- Look if the directory is in the filename path
if ((strlen($v_header['filename']) > strlen($p_file_list[$i]))
&& (substr($v_header['filename'], 0, strlen($p_file_list[$i]))
== $p_file_list[$i])
) {
$v_extract_file = true;
break;
}
} // ----- It is a file, so compare the file names
elseif ($p_file_list[$i] == $v_header['filename']) {
$v_extract_file = true;
break;
}
}
} else {
$v_extract_file = true;
}
// ----- Look if this file need to be extracted
if (($v_extract_file) && (!$v_listing)) {
if (($p_remove_path != '')
&& (substr($v_header['filename'] . '/', 0, $p_remove_path_size)
== $p_remove_path)
) {
$v_header['filename'] = substr(
$v_header['filename'],
$p_remove_path_size
);
if ($v_header['filename'] == '') {
continue;
}
}
if (($p_path != './') && ($p_path != '/')) {
while (substr($p_path, -1) == '/') {
$p_path = substr($p_path, 0, strlen($p_path) - 1);
}
if (substr($v_header['filename'], 0, 1) == '/') {
$v_header['filename'] = $p_path . $v_header['filename'];
} else {
$v_header['filename'] = $p_path . '/' . $v_header['filename'];
}
}
if (file_exists($v_header['filename'])) {
if ((@is_dir($v_header['filename']))
&& ($v_header['typeflag'] == '')
) {
$this->_error(
'File ' . $v_header['filename']
. ' already exists as a directory'
);
return false;
}
if (($this->_isArchive($v_header['filename']))
&& ($v_header['typeflag'] == "5")
) {
$this->_error(
'Directory ' . $v_header['filename']
. ' already exists as a file'
);
return false;
}
if (!is_writeable($v_header['filename'])) {
$this->_error(
'File ' . $v_header['filename']
. ' already exists and is write protected'
);
return false;
}
if (filemtime($v_header['filename']) > $v_header['mtime']) {
// To be completed : An error or silent no replace ?
}
} // ----- Check the directory availability and create it if necessary
elseif (($v_result
= $this->_dirCheck(
($v_header['typeflag'] == "5"
? $v_header['filename']
: dirname($v_header['filename']))
)) != 1
) {
$this->_error('Unable to create path for ' . $v_header['filename']);
return false;
}
if ($v_extract_file) {
if ($v_header['typeflag'] == "5") {
if (!@file_exists($v_header['filename'])) {
if (!@mkdir($v_header['filename'], 0775)) {
$this->_error(
'Unable to create directory {'
. $v_header['filename'] . '}'
);
return false;
}
}
} elseif ($v_header['typeflag'] == "2") {
if (!$p_symlinks) {
$this->_warning('Symbolic links are not allowed. '
. 'Unable to extract {'
. $v_header['filename'] . '}'
);
return false;
}
$absolute_link = FALSE;
$link_depth = 0;
if (strpos($v_header['link'], "/") === 0 || strpos($v_header['link'], ':') !== FALSE) {
$absolute_link = TRUE;
}
else {
$s_filename = preg_replace('@^' . preg_quote($p_path) . '@', "", $v_header['filename']);
$s_linkname = str_replace('\\', '/', $v_header['link']);
foreach (explode("/", $s_filename) as $dir) {
if ($dir === "..") {
$link_depth--;
} elseif ($dir !== "" && $dir !== "." ) {
$link_depth++;
}
}
foreach (explode("/", $s_linkname) as $dir){
if ($link_depth <= 0) {
break;
}
if ($dir === "..") {
$link_depth--;
} elseif ($dir !== "" && $dir !== ".") {
$link_depth++;
}
}
}
if ($absolute_link || $link_depth <= 0) {
$this->_error(
'Out-of-path file extraction {'
. $v_header['filename'] . ' --> ' .
$v_header['link'] . '}'
);
return false;
}
if (@file_exists($v_header['filename'])) {
@unlink($v_header['filename']);
}
if (!@symlink($v_header['link'], $v_header['filename'])) {
$this->_error(
'Unable to extract symbolic link {'
. $v_header['filename'] . '}'
);
return false;
}
} else {
if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) {
$this->_error(
'Error while opening {' . $v_header['filename']
. '} in write binary mode'
);
return false;
} else {
$n = floor($v_header['size'] / 512);
for ($i = 0; $i < $n; $i++) {
$v_content = $this->_readBlock();
fwrite($v_dest_file, $v_content, 512);
}
if (($v_header['size'] % 512) != 0) {
$v_content = $this->_readBlock();
fwrite($v_dest_file, $v_content, ($v_header['size'] % 512));
}
@fclose($v_dest_file);
if ($p_preserve) {
@chown($v_header['filename'], $v_header['uid']);
@chgrp($v_header['filename'], $v_header['gid']);
}
// ----- Change the file mode, mtime
@touch($v_header['filename'], $v_header['mtime']);
if ($v_header['mode'] & 0111) {
// make file executable, obey umask
$mode = fileperms($v_header['filename']) | (~umask() & 0111);
@chmod($v_header['filename'], $mode);
}
}
// ----- Check the file size
clearstatcache();
if (!is_file($v_header['filename'])) {
$this->_error(
'Extracted file ' . $v_header['filename']
. 'does not exist. Archive may be corrupted.'
);
return false;
}
$filesize = filesize($v_header['filename']);
if ($filesize != $v_header['size']) {
$this->_error(
'Extracted file ' . $v_header['filename']
. ' does not have the correct file size \''
. $filesize
. '\' (' . $v_header['size']
. ' expected). Archive may be corrupted.'
);
return false;
}
}
} else {
$this->_jumpBlock(ceil(($v_header['size'] / 512)));
}
} else {
$this->_jumpBlock(ceil(($v_header['size'] / 512)));
}
/* TBC : Seems to be unused ...
if ($this->_compress)
$v_end_of_file = @gzeof($this->_file);
else
$v_end_of_file = @feof($this->_file);
*/
if ($v_listing || $v_extract_file || $v_extraction_stopped) {
// ----- Log extracted files
if (($v_file_dir = dirname($v_header['filename']))
== $v_header['filename']
) {
$v_file_dir = '';
}
if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == '')) {
$v_file_dir = '/';
}
$p_list_detail[$v_nb++] = $v_header;
if (is_array($p_file_list) && (count($p_list_detail) == count($p_file_list))) {
return true;
}
}
}
return true;
}
/**
* @return bool
*/
public function _openAppend()
{
if (filesize($this->_tarname) == 0) {
return $this->_openWrite();
}
if ($this->_compress) {
$this->_close();
if (!@rename($this->_tarname, $this->_tarname . ".tmp")) {
$this->_error(
'Error while renaming \'' . $this->_tarname
. '\' to temporary file \'' . $this->_tarname
. '.tmp\''
);
return false;
}
if ($this->_compress_type == 'gz') {
$v_temp_tar = @gzopen($this->_tarname . ".tmp", "rb");
} elseif ($this->_compress_type == 'bz2') {
$v_temp_tar = @bzopen($this->_tarname . ".tmp", "r");
} elseif ($this->_compress_type == 'lzma2') {
$v_temp_tar = @xzopen($this->_tarname . ".tmp", "r");
}
if ($v_temp_tar == 0) {
$this->_error(
'Unable to open file \'' . $this->_tarname
. '.tmp\' in binary read mode'
);
@rename($this->_tarname . ".tmp", $this->_tarname);
return false;
}
if (!$this->_openWrite()) {
@rename($this->_tarname . ".tmp", $this->_tarname);
return false;
}
if ($this->_compress_type == 'gz') {
$end_blocks = 0;
while (!@gzeof($v_temp_tar)) {
$v_buffer = @gzread($v_temp_tar, 512);
if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
$end_blocks++;
// do not copy end blocks, we will re-make them
// after appending
continue;
} elseif ($end_blocks > 0) {
for ($i = 0; $i < $end_blocks; $i++) {
$this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
}
$end_blocks = 0;
}
$v_binary_data = pack("a512", $v_buffer);
$this->_writeBlock($v_binary_data);
}
@gzclose($v_temp_tar);
} elseif ($this->_compress_type == 'bz2') {
$end_blocks = 0;
while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) {
if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
$end_blocks++;
// do not copy end blocks, we will re-make them
// after appending
continue;
} elseif ($end_blocks > 0) {
for ($i = 0; $i < $end_blocks; $i++) {
$this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
}
$end_blocks = 0;
}
$v_binary_data = pack("a512", $v_buffer);
$this->_writeBlock($v_binary_data);
}
@bzclose($v_temp_tar);
} elseif ($this->_compress_type == 'lzma2') {
$end_blocks = 0;
while (strlen($v_buffer = @xzread($v_temp_tar, 512)) > 0) {
if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
$end_blocks++;
// do not copy end blocks, we will re-make them
// after appending
continue;
} elseif ($end_blocks > 0) {
for ($i = 0; $i < $end_blocks; $i++) {
$this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
}
$end_blocks = 0;
}
$v_binary_data = pack("a512", $v_buffer);
$this->_writeBlock($v_binary_data);
}
@xzclose($v_temp_tar);
}
if (!@unlink($this->_tarname . ".tmp")) {
$this->_error(
'Error while deleting temporary file \''
. $this->_tarname . '.tmp\''
);
}
} else {
// ----- For not compressed tar, just add files before the last
// one or two 512 bytes block
if (!$this->_openReadWrite()) {
return false;
}
clearstatcache();
$v_size = filesize($this->_tarname);
// We might have zero, one or two end blocks.
// The standard is two, but we should try to handle
// other cases.
fseek($this->_file, $v_size - 1024);
if (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
fseek($this->_file, $v_size - 1024);
} elseif (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
fseek($this->_file, $v_size - 512);
}
}
return true;
}
/**
* @param $p_filelist
* @param string $p_add_dir
* @param string $p_remove_dir
* @return bool
*/
public function _append($p_filelist, $p_add_dir = '', $p_remove_dir = '')
{
if (!$this->_openAppend()) {
return false;
}
if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir)) {
$this->_writeFooter();
}
$this->_close();
return true;
}
/**
* Check if a directory exists and create it (including parent
* dirs) if not.
*
* @param string $p_dir directory to check
*
* @return bool true if the directory exists or was created
*/
public function _dirCheck($p_dir)
{
clearstatcache();
if ((@is_dir($p_dir)) || ($p_dir == '')) {
return true;
}
$p_parent_dir = dirname($p_dir);
if (($p_parent_dir != $p_dir) &&
($p_parent_dir != '') &&
(!$this->_dirCheck($p_parent_dir))
) {
return false;
}
if (!@mkdir($p_dir, 0775)) {
$this->_error("Unable to create directory '$p_dir'");
return false;
}
return true;
}
/**
* Compress path by changing for example "/dir/foo/../bar" to "/dir/bar",
* rand emove double slashes.
*
* @param string $p_dir path to reduce
*
* @return string reduced path
*/
private function _pathReduction($p_dir)
{
$v_result = '';
// ----- Look for not empty path
if ($p_dir != '') {
// ----- Explode path by directory names
$v_list = explode('/', $p_dir);
// ----- Study directories from last to first
for ($i = sizeof($v_list) - 1; $i >= 0; $i--) {
// ----- Look for current path
if ($v_list[$i] == ".") {
// ----- Ignore this directory
// Should be the first $i=0, but no check is done
} else {
if ($v_list[$i] == "..") {
// ----- Ignore it and ignore the $i-1
$i--;
} else {
if (($v_list[$i] == '')
&& ($i != (sizeof($v_list) - 1))
&& ($i != 0)
) {
// ----- Ignore only the double '//' in path,
// but not the first and last /
} else {
$v_result = $v_list[$i] . ($i != (sizeof($v_list) - 1) ? '/'
. $v_result : '');
}
}
}
}
}
if (defined('OS_WINDOWS') && OS_WINDOWS) {
$v_result = strtr($v_result, '\\', '/');
}
return $v_result;
}
/**
* @param $p_path
* @param bool $p_remove_disk_letter
* @return string
*/
public function _translateWinPath($p_path, $p_remove_disk_letter = true)
{
if (defined('OS_WINDOWS') && OS_WINDOWS) {
// ----- Look for potential disk letter
if (($p_remove_disk_letter)
&& (($v_position = strpos($p_path, ':')) != false)
) {
$p_path = substr($p_path, $v_position + 1);
}
// ----- Change potential windows directory separator
if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0, 1) == '\\')) {
$p_path = strtr($p_path, '\\', '/');
}
}
return $p_path;
}
}
PK �]��0AC5 C5 Console/Getopt.phpnu �[��� <?php
/* vim: set expandtab tabstop=4 shiftwidth=4: */
/**
* PHP Version 5
*
* Copyright (c) 2001-2015, The PEAR developers
*
* This source file is subject to the BSD-2-Clause license,
* that is bundled with this package in the file LICENSE, and is
* available through the world-wide-web at the following url:
* http://opensource.org/licenses/bsd-license.php.
*
* @category Console
* @package Console_Getopt
* @author Andrei Zmievski <andrei@php.net>
* @license http://opensource.org/licenses/bsd-license.php BSD-2-Clause
* @version CVS: $Id$
* @link http://pear.php.net/package/Console_Getopt
*/
require_once 'PEAR.php';
/**
* Command-line options parsing class.
*
* @category Console
* @package Console_Getopt
* @author Andrei Zmievski <andrei@php.net>
* @license http://opensource.org/licenses/bsd-license.php BSD-2-Clause
* @link http://pear.php.net/package/Console_Getopt
*/
class Console_Getopt
{
/**
* Parses the command-line options.
*
* The first parameter to this function should be the list of command-line
* arguments without the leading reference to the running program.
*
* The second parameter is a string of allowed short options. Each of the
* option letters can be followed by a colon ':' to specify that the option
* requires an argument, or a double colon '::' to specify that the option
* takes an optional argument.
*
* The third argument is an optional array of allowed long options. The
* leading '--' should not be included in the option name. Options that
* require an argument should be followed by '=', and options that take an
* option argument should be followed by '=='.
*
* The return value is an array of two elements: the list of parsed
* options and the list of non-option command-line arguments. Each entry in
* the list of parsed options is a pair of elements - the first one
* specifies the option, and the second one specifies the option argument,
* if there was one.
*
* Long and short options can be mixed.
*
* Most of the semantics of this function are based on GNU getopt_long().
*
* @param array $args an array of command-line arguments
* @param string $short_options specifies the list of allowed short options
* @param array $long_options specifies the list of allowed long options
* @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
*
* @return array two-element array containing the list of parsed options and
* the non-option arguments
*/
public static function getopt2($args, $short_options, $long_options = null, $skip_unknown = false)
{
return Console_Getopt::doGetopt(2, $args, $short_options, $long_options, $skip_unknown);
}
/**
* This function expects $args to start with the script name (POSIX-style).
* Preserved for backwards compatibility.
*
* @param array $args an array of command-line arguments
* @param string $short_options specifies the list of allowed short options
* @param array $long_options specifies the list of allowed long options
*
* @see getopt2()
* @return array two-element array containing the list of parsed options and
* the non-option arguments
*/
public static function getopt($args, $short_options, $long_options = null, $skip_unknown = false)
{
return Console_Getopt::doGetopt(1, $args, $short_options, $long_options, $skip_unknown);
}
/**
* The actual implementation of the argument parsing code.
*
* @param int $version Version to use
* @param array $args an array of command-line arguments
* @param string $short_options specifies the list of allowed short options
* @param array $long_options specifies the list of allowed long options
* @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
*
* @return array
*/
public static function doGetopt($version, $args, $short_options, $long_options = null, $skip_unknown = false)
{
// in case you pass directly readPHPArgv() as the first arg
if (PEAR::isError($args)) {
return $args;
}
if (empty($args)) {
return array(array(), array());
}
$non_opts = $opts = array();
settype($args, 'array');
if ($long_options) {
sort($long_options);
}
/*
* Preserve backwards compatibility with callers that relied on
* erroneous POSIX fix.
*/
if ($version < 2) {
if (isset($args[0][0]) && $args[0][0] != '-') {
array_shift($args);
}
}
for ($i = 0; $i < count($args); $i++) {
$arg = $args[$i];
/* The special element '--' means explicit end of
options. Treat the rest of the arguments as non-options
and end the loop. */
if ($arg == '--') {
$non_opts = array_merge($non_opts, array_slice($args, $i + 1));
break;
}
if ($arg[0] != '-' || (strlen($arg) > 1 && $arg[1] == '-' && !$long_options)) {
$non_opts = array_merge($non_opts, array_slice($args, $i));
break;
} elseif (strlen($arg) > 1 && $arg[1] == '-') {
$error = Console_Getopt::_parseLongOption(substr($arg, 2),
$long_options,
$opts,
$i,
$args,
$skip_unknown);
if (PEAR::isError($error)) {
return $error;
}
} elseif ($arg == '-') {
// - is stdin
$non_opts = array_merge($non_opts, array_slice($args, $i));
break;
} else {
$error = Console_Getopt::_parseShortOption(substr($arg, 1),
$short_options,
$opts,
$i,
$args,
$skip_unknown);
if (PEAR::isError($error)) {
return $error;
}
}
}
return array($opts, $non_opts);
}
/**
* Parse short option
*
* @param string $arg Argument
* @param string[] $short_options Available short options
* @param string[][] &$opts
* @param int &$argIdx
* @param string[] $args
* @param boolean $skip_unknown suppresses Console_Getopt: unrecognized option
*
* @return void
*/
protected static function _parseShortOption($arg, $short_options, &$opts, &$argIdx, $args, $skip_unknown)
{
for ($i = 0; $i < strlen($arg); $i++) {
$opt = $arg[$i];
$opt_arg = null;
/* Try to find the short option in the specifier string. */
if (($spec = strstr($short_options, $opt)) === false || $arg[$i] == ':') {
if ($skip_unknown === true) {
break;
}
$msg = "Console_Getopt: unrecognized option -- $opt";
return PEAR::raiseError($msg);
}
if (strlen($spec) > 1 && $spec[1] == ':') {
if (strlen($spec) > 2 && $spec[2] == ':') {
if ($i + 1 < strlen($arg)) {
/* Option takes an optional argument. Use the remainder of
the arg string if there is anything left. */
$opts[] = array($opt, substr($arg, $i + 1));
break;
}
} else {
/* Option requires an argument. Use the remainder of the arg
string if there is anything left. */
if ($i + 1 < strlen($arg)) {
$opts[] = array($opt, substr($arg, $i + 1));
break;
} else if (isset($args[++$argIdx])) {
$opt_arg = $args[$argIdx];
/* Else use the next argument. */;
if (Console_Getopt::_isShortOpt($opt_arg)
|| Console_Getopt::_isLongOpt($opt_arg)) {
$msg = "option requires an argument --$opt";
return PEAR::raiseError("Console_Getopt: " . $msg);
}
} else {
$msg = "option requires an argument --$opt";
return PEAR::raiseError("Console_Getopt: " . $msg);
}
}
}
$opts[] = array($opt, $opt_arg);
}
}
/**
* Checks if an argument is a short option
*
* @param string $arg Argument to check
*
* @return bool
*/
protected static function _isShortOpt($arg)
{
return strlen($arg) == 2 && $arg[0] == '-'
&& preg_match('/[a-zA-Z]/', $arg[1]);
}
/**
* Checks if an argument is a long option
*
* @param string $arg Argument to check
*
* @return bool
*/
protected static function _isLongOpt($arg)
{
return strlen($arg) > 2 && $arg[0] == '-' && $arg[1] == '-' &&
preg_match('/[a-zA-Z]+$/', substr($arg, 2));
}
/**
* Parse long option
*
* @param string $arg Argument
* @param string[] $long_options Available long options
* @param string[][] &$opts
* @param int &$argIdx
* @param string[] $args
*
* @return void|PEAR_Error
*/
protected static function _parseLongOption($arg, $long_options, &$opts, &$argIdx, $args, $skip_unknown)
{
@list($opt, $opt_arg) = explode('=', $arg, 2);
$opt_len = strlen($opt);
for ($i = 0; $i < count($long_options); $i++) {
$long_opt = $long_options[$i];
$opt_start = substr($long_opt, 0, $opt_len);
$long_opt_name = str_replace('=', '', $long_opt);
/* Option doesn't match. Go on to the next one. */
if ($long_opt_name != $opt) {
continue;
}
$opt_rest = substr($long_opt, $opt_len);
/* Check that the options uniquely matches one of the allowed
options. */
if ($i + 1 < count($long_options)) {
$next_option_rest = substr($long_options[$i + 1], $opt_len);
} else {
$next_option_rest = '';
}
if ($opt_rest != '' && $opt[0] != '=' &&
$i + 1 < count($long_options) &&
$opt == substr($long_options[$i+1], 0, $opt_len) &&
$next_option_rest != '' &&
$next_option_rest[0] != '=') {
$msg = "Console_Getopt: option --$opt is ambiguous";
return PEAR::raiseError($msg);
}
if (substr($long_opt, -1) == '=') {
if (substr($long_opt, -2) != '==') {
/* Long option requires an argument.
Take the next argument if one wasn't specified. */;
if (!strlen($opt_arg)) {
if (!isset($args[++$argIdx])) {
$msg = "Console_Getopt: option requires an argument --$opt";
return PEAR::raiseError($msg);
}
$opt_arg = $args[$argIdx];
}
if (Console_Getopt::_isShortOpt($opt_arg)
|| Console_Getopt::_isLongOpt($opt_arg)) {
$msg = "Console_Getopt: option requires an argument --$opt";
return PEAR::raiseError($msg);
}
}
} else if ($opt_arg) {
$msg = "Console_Getopt: option --$opt doesn't allow an argument";
return PEAR::raiseError($msg);
}
$opts[] = array('--' . $opt, $opt_arg);
return;
}
if ($skip_unknown === true) {
return;
}
return PEAR::raiseError("Console_Getopt: unrecognized option --$opt");
}
/**
* Safely read the $argv PHP array across different PHP configurations.
* Will take care on register_globals and register_argc_argv ini directives
*
* @return mixed the $argv PHP array or PEAR error if not registered
*/
public static function readPHPArgv()
{
global $argv;
if (!is_array($argv)) {
if (!@is_array($_SERVER['argv'])) {
if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) {
$msg = "Could not read cmd args (register_argc_argv=Off?)";
return PEAR::raiseError("Console_Getopt: " . $msg);
}
return $GLOBALS['HTTP_SERVER_VARS']['argv'];
}
return $_SERVER['argv'];
}
return $argv;
}
}
PK �]E�_ PEAR/Packager.phpnu �[��� <?php
/**
* PEAR_Packager for generating releases
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Tomas V. V. Cox <cox@idecnet.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* base class
*/
require_once 'PEAR/Common.php';
require_once 'PEAR/PackageFile.php';
require_once 'System.php';
/**
* Administration class used to make a PEAR release tarball.
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Packager extends PEAR_Common
{
/**
* @var PEAR_Registry
*/
var $_registry;
function package($pkgfile = null, $compress = true, $pkg2 = null)
{
// {{{ validate supplied package.xml file
if (empty($pkgfile)) {
$pkgfile = 'package.xml';
}
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$pkg = new PEAR_PackageFile($this->config, $this->debug);
$pf = &$pkg->fromPackageFile($pkgfile, PEAR_VALIDATE_NORMAL);
$main = &$pf;
PEAR::staticPopErrorHandling();
if (PEAR::isError($pf)) {
if (is_array($pf->getUserInfo())) {
foreach ($pf->getUserInfo() as $error) {
$this->log(0, 'Error: ' . $error['message']);
}
}
$this->log(0, $pf->getMessage());
return $this->raiseError("Cannot package, errors in package file");
}
foreach ($pf->getValidationWarnings() as $warning) {
$this->log(1, 'Warning: ' . $warning['message']);
}
// }}}
if ($pkg2) {
$this->log(0, 'Attempting to process the second package file');
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$pf2 = &$pkg->fromPackageFile($pkg2, PEAR_VALIDATE_NORMAL);
PEAR::staticPopErrorHandling();
if (PEAR::isError($pf2)) {
if (is_array($pf2->getUserInfo())) {
foreach ($pf2->getUserInfo() as $error) {
$this->log(0, 'Error: ' . $error['message']);
}
}
$this->log(0, $pf2->getMessage());
return $this->raiseError("Cannot package, errors in second package file");
}
foreach ($pf2->getValidationWarnings() as $warning) {
$this->log(1, 'Warning: ' . $warning['message']);
}
if ($pf2->getPackagexmlVersion() == '2.0' ||
$pf2->getPackagexmlVersion() == '2.1'
) {
$main = &$pf2;
$other = &$pf;
} else {
$main = &$pf;
$other = &$pf2;
}
if ($main->getPackagexmlVersion() != '2.0' &&
$main->getPackagexmlVersion() != '2.1') {
return PEAR::raiseError('Error: cannot package two package.xml version 1.0, can ' .
'only package together a package.xml 1.0 and package.xml 2.0');
}
if ($other->getPackagexmlVersion() != '1.0') {
return PEAR::raiseError('Error: cannot package two package.xml version 2.0, can ' .
'only package together a package.xml 1.0 and package.xml 2.0');
}
}
$main->setLogger($this);
if (!$main->validate(PEAR_VALIDATE_PACKAGING)) {
foreach ($main->getValidationWarnings() as $warning) {
$this->log(0, 'Error: ' . $warning['message']);
}
return $this->raiseError("Cannot package, errors in package");
}
foreach ($main->getValidationWarnings() as $warning) {
$this->log(1, 'Warning: ' . $warning['message']);
}
if ($pkg2) {
$other->setLogger($this);
$a = false;
if (!$other->validate(PEAR_VALIDATE_NORMAL) || $a = !$main->isEquivalent($other)) {
foreach ($other->getValidationWarnings() as $warning) {
$this->log(0, 'Error: ' . $warning['message']);
}
foreach ($main->getValidationWarnings() as $warning) {
$this->log(0, 'Error: ' . $warning['message']);
}
if ($a) {
return $this->raiseError('The two package.xml files are not equivalent!');
}
return $this->raiseError("Cannot package, errors in package");
}
foreach ($other->getValidationWarnings() as $warning) {
$this->log(1, 'Warning: ' . $warning['message']);
}
$gen = &$main->getDefaultGenerator();
$tgzfile = $gen->toTgz2($this, $other, $compress);
if (PEAR::isError($tgzfile)) {
return $tgzfile;
}
$dest_package = basename($tgzfile);
$pkgdir = dirname($pkgfile);
// TAR the Package -------------------------------------------
$this->log(1, "Package $dest_package done");
if (file_exists("$pkgdir/CVS/Root")) {
$cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion());
$cvstag = "RELEASE_$cvsversion";
$this->log(1, 'Tag the released code with "pear cvstag ' .
$main->getPackageFile() . '"');
$this->log(1, "(or set the CVS tag $cvstag by hand)");
} elseif (file_exists("$pkgdir/.svn")) {
$svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion());
$svntag = $pf->getName() . "-$svnversion";
$this->log(1, 'Tag the released code with "pear svntag ' .
$main->getPackageFile() . '"');
$this->log(1, "(or set the SVN tag $svntag by hand)");
}
} else { // this branch is executed for single packagefile packaging
$gen = &$pf->getDefaultGenerator();
$tgzfile = $gen->toTgz($this, $compress);
if (PEAR::isError($tgzfile)) {
$this->log(0, $tgzfile->getMessage());
return $this->raiseError("Cannot package, errors in package");
}
$dest_package = basename($tgzfile);
$pkgdir = dirname($pkgfile);
// TAR the Package -------------------------------------------
$this->log(1, "Package $dest_package done");
if (file_exists("$pkgdir/CVS/Root")) {
$cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pf->getVersion());
$cvstag = "RELEASE_$cvsversion";
$this->log(1, "Tag the released code with `pear cvstag $pkgfile'");
$this->log(1, "(or set the CVS tag $cvstag by hand)");
} elseif (file_exists("$pkgdir/.svn")) {
$svnversion = preg_replace('/[^a-z0-9]/i', '.', $pf->getVersion());
$svntag = $pf->getName() . "-$svnversion";
$this->log(1, "Tag the released code with `pear svntag $pkgfile'");
$this->log(1, "(or set the SVN tag $svntag by hand)");
}
}
return $dest_package;
}
}PK �]h:3N� � PEAR/Dependency2.phpnu �[��� <?php
/**
* PEAR_Dependency2, advanced dependency validation
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* Required for the PEAR_VALIDATE_* constants
*/
require_once 'PEAR/Validate.php';
/**
* Dependency check for PEAR packages
*
* This class handles both version 1.0 and 2.0 dependencies
* WARNING: *any* changes to this class must be duplicated in the
* test_PEAR_Dependency2 class found in tests/PEAR_Dependency2/setup.php.inc,
* or unit tests will not actually validate the changes
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Dependency2
{
/**
* One of the PEAR_VALIDATE_* states
* @see PEAR_VALIDATE_NORMAL
* @var integer
*/
var $_state;
/**
* Command-line options to install/upgrade/uninstall commands
* @param array
*/
var $_options;
/**
* @var OS_Guess
*/
var $_os;
/**
* @var PEAR_Registry
*/
var $_registry;
/**
* @var PEAR_Config
*/
var $_config;
/**
* @var PEAR_DependencyDB
*/
var $_dependencydb;
/**
* Output of PEAR_Registry::parsedPackageName()
* @var array
*/
var $_currentPackage;
/**
* @param PEAR_Config
* @param array installation options
* @param array format of PEAR_Registry::parsedPackageName()
* @param int installation state (one of PEAR_VALIDATE_*)
*/
function __construct(&$config, $installoptions, $package,
$state = PEAR_VALIDATE_INSTALLING)
{
$this->_config = &$config;
if (!class_exists('PEAR_DependencyDB')) {
require_once 'PEAR/DependencyDB.php';
}
if (isset($installoptions['packagingroot'])) {
// make sure depdb is in the right location
$config->setInstallRoot($installoptions['packagingroot']);
}
$this->_registry = &$config->getRegistry();
$this->_dependencydb = &PEAR_DependencyDB::singleton($config);
if (isset($installoptions['packagingroot'])) {
$config->setInstallRoot(false);
}
$this->_options = $installoptions;
$this->_state = $state;
if (!class_exists('OS_Guess')) {
require_once 'OS/Guess.php';
}
$this->_os = new OS_Guess;
$this->_currentPackage = $package;
}
static function _getExtraString($dep)
{
$extra = ' (';
if (isset($dep['uri'])) {
return '';
}
if (isset($dep['recommended'])) {
$extra .= 'recommended version ' . $dep['recommended'];
} else {
if (isset($dep['min'])) {
$extra .= 'version >= ' . $dep['min'];
}
if (isset($dep['max'])) {
if ($extra != ' (') {
$extra .= ', ';
}
$extra .= 'version <= ' . $dep['max'];
}
if (isset($dep['exclude'])) {
if (!is_array($dep['exclude'])) {
$dep['exclude'] = array($dep['exclude']);
}
if ($extra != ' (') {
$extra .= ', ';
}
$extra .= 'excluded versions: ';
foreach ($dep['exclude'] as $i => $exclude) {
if ($i) {
$extra .= ', ';
}
$extra .= $exclude;
}
}
}
$extra .= ')';
if ($extra == ' ()') {
$extra = '';
}
return $extra;
}
/**
* This makes unit-testing a heck of a lot easier
*/
function getPHP_OS()
{
return PHP_OS;
}
/**
* This makes unit-testing a heck of a lot easier
*/
function getsysname()
{
return $this->_os->getSysname();
}
/**
* Specify a dependency on an OS. Use arch for detailed os/processor information
*
* There are two generic OS dependencies that will be the most common, unix and windows.
* Other options are linux, freebsd, darwin (OS X), sunos, irix, hpux, aix
*/
function validateOsDependency($dep)
{
if ($this->_state != PEAR_VALIDATE_INSTALLING && $this->_state != PEAR_VALIDATE_DOWNLOADING) {
return true;
}
if ($dep['name'] == '*') {
return true;
}
$not = isset($dep['conflicts']) ? true : false;
switch (strtolower($dep['name'])) {
case 'windows' :
if ($not) {
if (strtolower(substr($this->getPHP_OS(), 0, 3)) == 'win') {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError("Cannot install %s on Windows");
}
return $this->warning("warning: Cannot install %s on Windows");
}
} else {
if (strtolower(substr($this->getPHP_OS(), 0, 3)) != 'win') {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError("Can only install %s on Windows");
}
return $this->warning("warning: Can only install %s on Windows");
}
}
break;
case 'unix' :
$unices = array('linux', 'freebsd', 'darwin', 'sunos', 'irix', 'hpux', 'aix');
if ($not) {
if (in_array($this->getSysname(), $unices)) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError("Cannot install %s on any Unix system");
}
return $this->warning( "warning: Cannot install %s on any Unix system");
}
} else {
if (!in_array($this->getSysname(), $unices)) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError("Can only install %s on a Unix system");
}
return $this->warning("warning: Can only install %s on a Unix system");
}
}
break;
default :
if ($not) {
if (strtolower($dep['name']) == strtolower($this->getSysname())) {
if (!isset($this->_options['nodeps']) &&
!isset($this->_options['force'])) {
return $this->raiseError('Cannot install %s on ' . $dep['name'] .
' operating system');
}
return $this->warning('warning: Cannot install %s on ' .
$dep['name'] . ' operating system');
}
} else {
if (strtolower($dep['name']) != strtolower($this->getSysname())) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('Cannot install %s on ' .
$this->getSysname() .
' operating system, can only install on ' . $dep['name']);
}
return $this->warning('warning: Cannot install %s on ' .
$this->getSysname() .
' operating system, can only install on ' . $dep['name']);
}
}
}
return true;
}
/**
* This makes unit-testing a heck of a lot easier
*/
function matchSignature($pattern)
{
return $this->_os->matchSignature($pattern);
}
/**
* Specify a complex dependency on an OS/processor/kernel version,
* Use OS for simple operating system dependency.
*
* This is the only dependency that accepts an eregable pattern. The pattern
* will be matched against the php_uname() output parsed by OS_Guess
*/
function validateArchDependency($dep)
{
if ($this->_state != PEAR_VALIDATE_INSTALLING) {
return true;
}
$not = isset($dep['conflicts']) ? true : false;
if (!$this->matchSignature($dep['pattern'])) {
if (!$not) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s Architecture dependency failed, does not ' .
'match "' . $dep['pattern'] . '"');
}
return $this->warning('warning: %s Architecture dependency failed, does ' .
'not match "' . $dep['pattern'] . '"');
}
return true;
}
if ($not) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s Architecture dependency failed, required "' .
$dep['pattern'] . '"');
}
return $this->warning('warning: %s Architecture dependency failed, ' .
'required "' . $dep['pattern'] . '"');
}
return true;
}
/**
* This makes unit-testing a heck of a lot easier
*/
function extension_loaded($name)
{
return extension_loaded($name);
}
/**
* This makes unit-testing a heck of a lot easier
*/
function phpversion($name = null)
{
if ($name !== null) {
return phpversion($name);
}
return phpversion();
}
function validateExtensionDependency($dep, $required = true)
{
if ($this->_state != PEAR_VALIDATE_INSTALLING &&
$this->_state != PEAR_VALIDATE_DOWNLOADING) {
return true;
}
$loaded = $this->extension_loaded($dep['name']);
$extra = self::_getExtraString($dep);
if (isset($dep['exclude'])) {
if (!is_array($dep['exclude'])) {
$dep['exclude'] = array($dep['exclude']);
}
}
if (!isset($dep['min']) && !isset($dep['max']) &&
!isset($dep['recommended']) && !isset($dep['exclude'])
) {
if ($loaded) {
if (isset($dep['conflicts'])) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s conflicts with PHP extension "' .
$dep['name'] . '"' . $extra);
}
return $this->warning('warning: %s conflicts with PHP extension "' .
$dep['name'] . '"' . $extra);
}
return true;
}
if (isset($dep['conflicts'])) {
return true;
}
if ($required) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s requires PHP extension "' .
$dep['name'] . '"' . $extra);
}
return $this->warning('warning: %s requires PHP extension "' .
$dep['name'] . '"' . $extra);
}
return $this->warning('%s can optionally use PHP extension "' .
$dep['name'] . '"' . $extra);
}
if (!$loaded) {
if (isset($dep['conflicts'])) {
return true;
}
if (!$required) {
return $this->warning('%s can optionally use PHP extension "' .
$dep['name'] . '"' . $extra);
}
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s requires PHP extension "' . $dep['name'] .
'"' . $extra);
}
return $this->warning('warning: %s requires PHP extension "' . $dep['name'] .
'"' . $extra);
}
$version = (string) $this->phpversion($dep['name']);
if (empty($version)) {
$version = '0';
}
$fail = false;
if (isset($dep['min']) && !version_compare($version, $dep['min'], '>=')) {
$fail = true;
}
if (isset($dep['max']) && !version_compare($version, $dep['max'], '<=')) {
$fail = true;
}
if ($fail && !isset($dep['conflicts'])) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s requires PHP extension "' . $dep['name'] .
'"' . $extra . ', installed version is ' . $version);
}
return $this->warning('warning: %s requires PHP extension "' . $dep['name'] .
'"' . $extra . ', installed version is ' . $version);
} elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail && isset($dep['conflicts'])) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s conflicts with PHP extension "' .
$dep['name'] . '"' . $extra . ', installed version is ' . $version);
}
return $this->warning('warning: %s conflicts with PHP extension "' .
$dep['name'] . '"' . $extra . ', installed version is ' . $version);
}
if (isset($dep['exclude'])) {
foreach ($dep['exclude'] as $exclude) {
if (version_compare($version, $exclude, '==')) {
if (isset($dep['conflicts'])) {
continue;
}
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s is not compatible with PHP extension "' .
$dep['name'] . '" version ' .
$exclude);
}
return $this->warning('warning: %s is not compatible with PHP extension "' .
$dep['name'] . '" version ' .
$exclude);
} elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s conflicts with PHP extension "' .
$dep['name'] . '"' . $extra . ', installed version is ' . $version);
}
return $this->warning('warning: %s conflicts with PHP extension "' .
$dep['name'] . '"' . $extra . ', installed version is ' . $version);
}
}
}
if (isset($dep['recommended'])) {
if (version_compare($version, $dep['recommended'], '==')) {
return true;
}
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s dependency: PHP extension ' . $dep['name'] .
' version "' . $version . '"' .
' is not the recommended version "' . $dep['recommended'] .
'", but may be compatible, use --force to install');
}
return $this->warning('warning: %s dependency: PHP extension ' .
$dep['name'] . ' version "' . $version . '"' .
' is not the recommended version "' . $dep['recommended'].'"');
}
return true;
}
function validatePhpDependency($dep)
{
if ($this->_state != PEAR_VALIDATE_INSTALLING &&
$this->_state != PEAR_VALIDATE_DOWNLOADING) {
return true;
}
$version = $this->phpversion();
$extra = self::_getExtraString($dep);
if (isset($dep['exclude'])) {
if (!is_array($dep['exclude'])) {
$dep['exclude'] = array($dep['exclude']);
}
}
if (isset($dep['min'])) {
if (!version_compare($version, $dep['min'], '>=')) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s requires PHP' .
$extra . ', installed version is ' . $version);
}
return $this->warning('warning: %s requires PHP' .
$extra . ', installed version is ' . $version);
}
}
if (isset($dep['max'])) {
if (!version_compare($version, $dep['max'], '<=')) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s requires PHP' .
$extra . ', installed version is ' . $version);
}
return $this->warning('warning: %s requires PHP' .
$extra . ', installed version is ' . $version);
}
}
if (isset($dep['exclude'])) {
foreach ($dep['exclude'] as $exclude) {
if (version_compare($version, $exclude, '==')) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s is not compatible with PHP version ' .
$exclude);
}
return $this->warning(
'warning: %s is not compatible with PHP version ' .
$exclude);
}
}
}
return true;
}
/**
* This makes unit-testing a heck of a lot easier
*/
function getPEARVersion()
{
return '1.10.18';
}
function validatePearinstallerDependency($dep)
{
$pearversion = $this->getPEARVersion();
$extra = self::_getExtraString($dep);
if (isset($dep['exclude'])) {
if (!is_array($dep['exclude'])) {
$dep['exclude'] = array($dep['exclude']);
}
}
if (version_compare($pearversion, $dep['min'], '<')) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s requires PEAR Installer' . $extra .
', installed version is ' . $pearversion);
}
return $this->warning('warning: %s requires PEAR Installer' . $extra .
', installed version is ' . $pearversion);
}
if (isset($dep['max'])) {
if (version_compare($pearversion, $dep['max'], '>')) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s requires PEAR Installer' . $extra .
', installed version is ' . $pearversion);
}
return $this->warning('warning: %s requires PEAR Installer' . $extra .
', installed version is ' . $pearversion);
}
}
if (isset($dep['exclude'])) {
if (!isset($dep['exclude'][0])) {
$dep['exclude'] = array($dep['exclude']);
}
foreach ($dep['exclude'] as $exclude) {
if (version_compare($exclude, $pearversion, '==')) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s is not compatible with PEAR Installer ' .
'version ' . $exclude);
}
return $this->warning('warning: %s is not compatible with PEAR ' .
'Installer version ' . $exclude);
}
}
}
return true;
}
function validateSubpackageDependency($dep, $required, $params)
{
return $this->validatePackageDependency($dep, $required, $params);
}
/**
* @param array dependency information (2.0 format)
* @param boolean whether this is a required dependency
* @param array a list of downloaded packages to be installed, if any
* @param boolean if true, then deps on pear.php.net that fail will also check
* against pecl.php.net packages to accommodate extensions that have
* moved to pecl.php.net from pear.php.net
*/
function validatePackageDependency($dep, $required, $params, $depv1 = false)
{
if ($this->_state != PEAR_VALIDATE_INSTALLING &&
$this->_state != PEAR_VALIDATE_DOWNLOADING) {
return true;
}
if (isset($dep['providesextension'])) {
if ($this->extension_loaded($dep['providesextension'])) {
$save = $dep;
$subdep = $dep;
$subdep['name'] = $subdep['providesextension'];
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$ret = $this->validateExtensionDependency($subdep, $required);
PEAR::popErrorHandling();
if (!PEAR::isError($ret)) {
return true;
}
}
}
if ($this->_state == PEAR_VALIDATE_INSTALLING) {
return $this->_validatePackageInstall($dep, $required, $depv1);
}
if ($this->_state == PEAR_VALIDATE_DOWNLOADING) {
return $this->_validatePackageDownload($dep, $required, $params, $depv1);
}
}
function _validatePackageDownload($dep, $required, $params, $depv1 = false)
{
$dep['package'] = $dep['name'];
if (isset($dep['uri'])) {
$dep['channel'] = '__uri';
}
$depname = $this->_registry->parsedPackageNameToString($dep, true);
$found = false;
foreach ($params as $param) {
if ($param->isEqual(
array('package' => $dep['name'],
'channel' => $dep['channel']))) {
$found = true;
break;
}
if ($depv1 && $dep['channel'] == 'pear.php.net') {
if ($param->isEqual(
array('package' => $dep['name'],
'channel' => 'pecl.php.net'))) {
$found = true;
break;
}
}
}
if (!$found && isset($dep['providesextension'])) {
foreach ($params as $param) {
if ($param->isExtension($dep['providesextension'])) {
$found = true;
break;
}
}
}
if ($found) {
$version = $param->getVersion();
$installed = false;
$downloaded = true;
} else {
if ($this->_registry->packageExists($dep['name'], $dep['channel'])) {
$installed = true;
$downloaded = false;
$version = $this->_registry->packageinfo($dep['name'], 'version',
$dep['channel']);
} else {
if ($dep['channel'] == 'pecl.php.net' && $this->_registry->packageExists($dep['name'],
'pear.php.net')) {
$installed = true;
$downloaded = false;
$version = $this->_registry->packageinfo($dep['name'], 'version',
'pear.php.net');
} else {
$version = 'not installed or downloaded';
$installed = false;
$downloaded = false;
}
}
}
$extra = self::_getExtraString($dep);
if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
$dep['exclude'] = array($dep['exclude']);
}
if (!isset($dep['min']) && !isset($dep['max']) &&
!isset($dep['recommended']) && !isset($dep['exclude'])
) {
if ($installed || $downloaded) {
$installed = $installed ? 'installed' : 'downloaded';
if (isset($dep['conflicts'])) {
$rest = '';
if ($version) {
$rest = ", $installed version is " . $version;
}
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra . $rest);
}
return $this->warning('warning: %s conflicts with package "' . $depname . '"' . $extra . $rest);
}
return true;
}
if (isset($dep['conflicts'])) {
return true;
}
if ($required) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s requires package "' . $depname . '"' . $extra);
}
return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
}
return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
}
if (!$installed && !$downloaded) {
if (isset($dep['conflicts'])) {
return true;
}
if ($required) {
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s requires package "' . $depname . '"' . $extra);
}
return $this->warning('warning: %s requires package "' . $depname . '"' . $extra);
}
return $this->warning('%s can optionally use package "' . $depname . '"' . $extra);
}
$fail = false;
if (isset($dep['min']) && version_compare($version, $dep['min'], '<')) {
$fail = true;
}
if (isset($dep['max']) && version_compare($version, $dep['max'], '>')) {
$fail = true;
}
if ($fail && !isset($dep['conflicts'])) {
$installed = $installed ? 'installed' : 'downloaded';
$dep['package'] = $dep['name'];
$dep = $this->_registry->parsedPackageNameToString($dep, true);
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s requires package "' . $depname . '"' .
$extra . ", $installed version is " . $version);
}
return $this->warning('warning: %s requires package "' . $depname . '"' .
$extra . ", $installed version is " . $version);
} elseif ((isset($dep['min']) || isset($dep['max'])) && !$fail &&
isset($dep['conflicts']) && !isset($dep['exclude'])) {
$installed = $installed ? 'installed' : 'downloaded';
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s conflicts with package "' . $depname . '"' . $extra .
", $installed version is " . $version);
}
return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
$extra . ", $installed version is " . $version);
}
if (isset($dep['exclude'])) {
$installed = $installed ? 'installed' : 'downloaded';
foreach ($dep['exclude'] as $exclude) {
if (version_compare($version, $exclude, '==') && !isset($dep['conflicts'])) {
if (!isset($this->_options['nodeps']) &&
!isset($this->_options['force'])
) {
return $this->raiseError('%s is not compatible with ' .
$installed . ' package "' .
$depname . '" version ' .
$exclude);
}
return $this->warning('warning: %s is not compatible with ' .
$installed . ' package "' .
$depname . '" version ' .
$exclude);
} elseif (version_compare($version, $exclude, '!=') && isset($dep['conflicts'])) {
$installed = $installed ? 'installed' : 'downloaded';
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('%s conflicts with package "' . $depname . '"' .
$extra . ", $installed version is " . $version);
}
return $this->warning('warning: %s conflicts with package "' . $depname . '"' .
$extra . ", $installed version is " . $version);
}
}
}
if (isset($dep['recommended'])) {
$installed = $installed ? 'installed' : 'downloaded';
if (version_compare($version, $dep['recommended'], '==')) {
return true;
}
if (!$found && $installed) {
$param = $this->_registry->getPackage($dep['name'], $dep['channel']);
}
if ($param) {
$found = false;
foreach ($params as $parent) {
if ($parent->isEqual($this->_currentPackage)) {
$found = true;
break;
}
}
if ($found) {
if ($param->isCompatible($parent)) {
return true;
}
} else { // this is for validPackage() calls
$parent = $this->_registry->getPackage($this->_currentPackage['package'],
$this->_currentPackage['channel']);
if ($parent !== null && $param->isCompatible($parent)) {
return true;
}
}
}
if (!isset($this->_options['nodeps']) && !isset($this->_options['force']) &&
!isset($this->_options['loose'])
) {
return $this->raiseError('%s dependency package "' . $depname .
'" ' . $installed . ' version ' . $version .
' is not the recommended version ' . $dep['recommended'] .
', but may be compatible, use --force to install');
}
return $this->warning('warning: %s dependency package "' . $depname .
'" ' . $installed . ' version ' . $version .
' is not the recommended version ' . $dep['recommended']);
}
return true;
}
function _validatePackageInstall($dep, $required, $depv1 = false)
{
return $this->_validatePackageDownload($dep, $required, array(), $depv1);
}
/**
* Verify that uninstalling packages passed in to command line is OK.
*
* @param PEAR_Installer $dl
* @return PEAR_Error|true
*/
function validatePackageUninstall(&$dl)
{
if (PEAR::isError($this->_dependencydb)) {
return $this->_dependencydb;
}
$params = array();
// construct an array of "downloaded" packages to fool the package dependency checker
// into using these to validate uninstalls of circular dependencies
$downloaded = &$dl->getUninstallPackages();
foreach ($downloaded as $i => $pf) {
if (!class_exists('PEAR_Downloader_Package')) {
require_once 'PEAR/Downloader/Package.php';
}
$dp = new PEAR_Downloader_Package($dl);
$dp->setPackageFile($downloaded[$i]);
$params[$i] = $dp;
}
// check cache
$memyselfandI = strtolower($this->_currentPackage['channel']) . '/' .
strtolower($this->_currentPackage['package']);
if (isset($dl->___uninstall_package_cache)) {
$badpackages = $dl->___uninstall_package_cache;
if (isset($badpackages[$memyselfandI]['warnings'])) {
foreach ($badpackages[$memyselfandI]['warnings'] as $warning) {
$dl->log(0, $warning[0]);
}
}
if (isset($badpackages[$memyselfandI]['errors'])) {
foreach ($badpackages[$memyselfandI]['errors'] as $error) {
if (is_array($error)) {
$dl->log(0, $error[0]);
} else {
$dl->log(0, $error->getMessage());
}
}
if (isset($this->_options['nodeps']) || isset($this->_options['force'])) {
return $this->warning(
'warning: %s should not be uninstalled, other installed packages depend ' .
'on this package');
}
return $this->raiseError(
'%s cannot be uninstalled, other installed packages depend on this package');
}
return true;
}
// first, list the immediate parents of each package to be uninstalled
$perpackagelist = array();
$allparents = array();
foreach ($params as $i => $param) {
$a = array(
'channel' => strtolower($param->getChannel()),
'package' => strtolower($param->getPackage())
);
$deps = $this->_dependencydb->getDependentPackages($a);
if ($deps) {
foreach ($deps as $d) {
$pardeps = $this->_dependencydb->getDependencies($d);
foreach ($pardeps as $dep) {
if (strtolower($dep['dep']['channel']) == $a['channel'] &&
strtolower($dep['dep']['name']) == $a['package']) {
if (!isset($perpackagelist[$a['channel'] . '/' . $a['package']])) {
$perpackagelist[$a['channel'] . '/' . $a['package']] = array();
}
$perpackagelist[$a['channel'] . '/' . $a['package']][]
= array($d['channel'] . '/' . $d['package'], $dep);
if (!isset($allparents[$d['channel'] . '/' . $d['package']])) {
$allparents[$d['channel'] . '/' . $d['package']] = array();
}
if (!isset($allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']])) {
$allparents[$d['channel'] . '/' . $d['package']][$a['channel'] . '/' . $a['package']] = array();
}
$allparents[$d['channel'] . '/' . $d['package']]
[$a['channel'] . '/' . $a['package']][]
= array($d, $dep);
}
}
}
}
}
// next, remove any packages from the parents list that are not installed
$remove = array();
foreach ($allparents as $parent => $d1) {
foreach ($d1 as $d) {
if ($this->_registry->packageExists($d[0][0]['package'], $d[0][0]['channel'])) {
continue;
}
$remove[$parent] = true;
}
}
// next remove any packages from the parents list that are not passed in for
// uninstallation
foreach ($allparents as $parent => $d1) {
foreach ($d1 as $d) {
foreach ($params as $param) {
if (strtolower($param->getChannel()) == $d[0][0]['channel'] &&
strtolower($param->getPackage()) == $d[0][0]['package']) {
// found it
continue 3;
}
}
$remove[$parent] = true;
}
}
// remove all packages whose dependencies fail
// save which ones failed for error reporting
$badchildren = array();
do {
$fail = false;
foreach ($remove as $package => $unused) {
if (!isset($allparents[$package])) {
continue;
}
foreach ($allparents[$package] as $kid => $d1) {
foreach ($d1 as $depinfo) {
if ($depinfo[1]['type'] != 'optional') {
if (isset($badchildren[$kid])) {
continue;
}
$badchildren[$kid] = true;
$remove[$kid] = true;
$fail = true;
continue 2;
}
}
}
if ($fail) {
// start over, we removed some children
continue 2;
}
}
} while ($fail);
// next, construct the list of packages that can't be uninstalled
$badpackages = array();
$save = $this->_currentPackage;
foreach ($perpackagelist as $package => $packagedeps) {
foreach ($packagedeps as $parent) {
if (!isset($remove[$parent[0]])) {
continue;
}
$packagename = $this->_registry->parsePackageName($parent[0]);
$packagename['channel'] = $this->_registry->channelAlias($packagename['channel']);
$pa = $this->_registry->getPackage($packagename['package'], $packagename['channel']);
$packagename['package'] = $pa->getPackage();
$this->_currentPackage = $packagename;
// parent is not present in uninstall list, make sure we can actually
// uninstall it (parent dep is optional)
$parentname['channel'] = $this->_registry->channelAlias($parent[1]['dep']['channel']);
$pa = $this->_registry->getPackage($parent[1]['dep']['name'], $parent[1]['dep']['channel']);
$parentname['package'] = $pa->getPackage();
$parent[1]['dep']['package'] = $parentname['package'];
$parent[1]['dep']['channel'] = $parentname['channel'];
if ($parent[1]['type'] == 'optional') {
$test = $this->_validatePackageUninstall($parent[1]['dep'], false, $dl);
if ($test !== true) {
$badpackages[$package]['warnings'][] = $test;
}
} else {
$test = $this->_validatePackageUninstall($parent[1]['dep'], true, $dl);
if ($test !== true) {
$badpackages[$package]['errors'][] = $test;
}
}
}
}
$this->_currentPackage = $save;
$dl->___uninstall_package_cache = $badpackages;
if (isset($badpackages[$memyselfandI])) {
if (isset($badpackages[$memyselfandI]['warnings'])) {
foreach ($badpackages[$memyselfandI]['warnings'] as $warning) {
$dl->log(0, $warning[0]);
}
}
if (isset($badpackages[$memyselfandI]['errors'])) {
foreach ($badpackages[$memyselfandI]['errors'] as $error) {
if (is_array($error)) {
$dl->log(0, $error[0]);
} else {
$dl->log(0, $error->getMessage());
}
}
if (isset($this->_options['nodeps']) || isset($this->_options['force'])) {
return $this->warning(
'warning: %s should not be uninstalled, other installed packages depend ' .
'on this package');
}
return $this->raiseError(
'%s cannot be uninstalled, other installed packages depend on this package');
}
}
return true;
}
function _validatePackageUninstall($dep, $required, $dl)
{
$depname = $this->_registry->parsedPackageNameToString($dep, true);
$version = $this->_registry->packageinfo($dep['package'], 'version', $dep['channel']);
if (!$version) {
return true;
}
$extra = self::_getExtraString($dep);
if (isset($dep['exclude']) && !is_array($dep['exclude'])) {
$dep['exclude'] = array($dep['exclude']);
}
if (isset($dep['conflicts'])) {
return true; // uninstall OK - these packages conflict (probably installed with --force)
}
if (!isset($dep['min']) && !isset($dep['max'])) {
if (!$required) {
return $this->warning('"' . $depname . '" can be optionally used by ' .
'installed package %s' . $extra);
}
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError('"' . $depname . '" is required by ' .
'installed package %s' . $extra);
}
return $this->warning('warning: "' . $depname . '" is required by ' .
'installed package %s' . $extra);
}
$fail = false;
if (isset($dep['min']) && version_compare($version, $dep['min'], '>=')) {
$fail = true;
}
if (isset($dep['max']) && version_compare($version, $dep['max'], '<=')) {
$fail = true;
}
// we re-use this variable, preserve the original value
$saverequired = $required;
if (!$required) {
return $this->warning($depname . $extra . ' can be optionally used by installed package' .
' "%s"');
}
if (!isset($this->_options['nodeps']) && !isset($this->_options['force'])) {
return $this->raiseError($depname . $extra . ' is required by installed package' .
' "%s"');
}
return $this->raiseError('warning: ' . $depname . $extra .
' is required by installed package "%s"');
}
/**
* validate a downloaded package against installed packages
*
* As of PEAR 1.4.3, this will only validate
*
* @param array|PEAR_Downloader_Package|PEAR_PackageFile_v1|PEAR_PackageFile_v2
* $pkg package identifier (either
* array('package' => blah, 'channel' => blah) or an array with
* index 'info' referencing an object)
* @param PEAR_Downloader $dl
* @param array $params full list of packages to install
* @return true|PEAR_Error
*/
function validatePackage($pkg, &$dl, $params = array())
{
if (is_array($pkg) && isset($pkg['info'])) {
$deps = $this->_dependencydb->getDependentPackageDependencies($pkg['info']);
} else {
$deps = $this->_dependencydb->getDependentPackageDependencies($pkg);
}
$fail = false;
if ($deps) {
if (!class_exists('PEAR_Downloader_Package')) {
require_once 'PEAR/Downloader/Package.php';
}
$dp = new PEAR_Downloader_Package($dl);
if (is_object($pkg)) {
$dp->setPackageFile($pkg);
} else {
$dp->setDownloadURL($pkg);
}
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
foreach ($deps as $channel => $info) {
foreach ($info as $package => $ds) {
foreach ($params as $packd) {
if (strtolower($packd->getPackage()) == strtolower($package) &&
$packd->getChannel() == $channel) {
$dl->log(3, 'skipping installed package check of "' .
$this->_registry->parsedPackageNameToString(
array('channel' => $channel, 'package' => $package),
true) .
'", version "' . $packd->getVersion() . '" will be ' .
'downloaded and installed');
continue 2; // jump to next package
}
}
foreach ($ds as $d) {
$checker = new PEAR_Dependency2($this->_config, $this->_options,
array('channel' => $channel, 'package' => $package), $this->_state);
$dep = $d['dep'];
$required = $d['type'] == 'required';
$ret = $checker->_validatePackageDownload($dep, $required, array(&$dp));
if (is_array($ret)) {
$dl->log(0, $ret[0]);
} elseif (PEAR::isError($ret)) {
$dl->log(0, $ret->getMessage());
$fail = true;
}
}
}
}
PEAR::popErrorHandling();
}
if ($fail) {
return $this->raiseError(
'%s cannot be installed, conflicts with installed packages');
}
return true;
}
/**
* validate a package.xml 1.0 dependency
*/
function validateDependency1($dep, $params = array())
{
if (!isset($dep['optional'])) {
$dep['optional'] = 'no';
}
list($newdep, $type) = self::normalizeDep($dep);
if (!$newdep) {
return $this->raiseError("Invalid Dependency");
}
if (method_exists($this, "validate{$type}Dependency")) {
return $this->{"validate{$type}Dependency"}($newdep, $dep['optional'] == 'no',
$params, true);
}
}
/**
* Convert a 1.0 dep into a 2.0 dep
*/
static function normalizeDep($dep)
{
$types = array(
'pkg' => 'Package',
'ext' => 'Extension',
'os' => 'Os',
'php' => 'Php'
);
if (!isset($types[$dep['type']])) {
return array(false, false);
}
$type = $types[$dep['type']];
$newdep = array();
switch ($type) {
case 'Package' :
$newdep['channel'] = 'pear.php.net';
case 'Extension' :
case 'Os' :
$newdep['name'] = $dep['name'];
break;
}
$dep['rel'] = PEAR_Dependency2::signOperator($dep['rel']);
switch ($dep['rel']) {
case 'has' :
return array($newdep, $type);
break;
case 'not' :
$newdep['conflicts'] = true;
break;
case '>=' :
case '>' :
$newdep['min'] = $dep['version'];
if ($dep['rel'] == '>') {
$newdep['exclude'] = $dep['version'];
}
break;
case '<=' :
case '<' :
$newdep['max'] = $dep['version'];
if ($dep['rel'] == '<') {
$newdep['exclude'] = $dep['version'];
}
break;
case 'ne' :
case '!=' :
$newdep['min'] = '0';
$newdep['max'] = '100000';
$newdep['exclude'] = $dep['version'];
break;
case '==' :
$newdep['min'] = $dep['version'];
$newdep['max'] = $dep['version'];
break;
}
if ($type == 'Php') {
if (!isset($newdep['min'])) {
$newdep['min'] = '4.4.0';
}
if (!isset($newdep['max'])) {
$newdep['max'] = '6.0.0';
}
}
return array($newdep, $type);
}
/**
* Converts text comparing operators to them sign equivalents
*
* Example: 'ge' to '>='
*
* @access public
* @param string Operator
* @return string Sign equivalent
*/
static function signOperator($operator)
{
switch($operator) {
case 'lt': return '<';
case 'le': return '<=';
case 'gt': return '>';
case 'ge': return '>=';
case 'eq': return '==';
case 'ne': return '!=';
default:
return $operator;
}
}
function raiseError($msg)
{
if (isset($this->_options['ignore-errors'])) {
return $this->warning($msg);
}
return PEAR::raiseError(sprintf($msg, $this->_registry->parsedPackageNameToString(
$this->_currentPackage, true)));
}
function warning($msg)
{
return array(sprintf($msg, $this->_registry->parsedPackageNameToString(
$this->_currentPackage, true)));
}
}
PK �]�\t;� � PEAR/XMLParser.phpnu �[��� <?php
/**
* PEAR_XMLParser
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @author Stephan Schmidt (original XML_Unserializer code)
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* Parser for any xml file
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @author Stephan Schmidt (original XML_Unserializer code)
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_XMLParser
{
/**
* unserilialized data
* @var string $_serializedData
*/
var $_unserializedData = null;
/**
* name of the root tag
* @var string $_root
*/
var $_root = null;
/**
* stack for all data that is found
* @var array $_dataStack
*/
var $_dataStack = array();
/**
* stack for all values that are generated
* @var array $_valStack
*/
var $_valStack = array();
/**
* current tag depth
* @var int $_depth
*/
var $_depth = 0;
/**
* The XML encoding to use
* @var string $encoding
*/
var $encoding = 'ISO-8859-1';
/**
* @return array
*/
function getData()
{
return $this->_unserializedData;
}
/**
* @param string xml content
* @return true|PEAR_Error
*/
function parse($data)
{
if (!extension_loaded('xml')) {
include_once 'PEAR.php';
return PEAR::raiseError("XML Extension not found", 1);
}
$this->_dataStack = $this->_valStack = array();
$this->_depth = 0;
if (
strpos($data, 'encoding="UTF-8"')
|| strpos($data, 'encoding="utf-8"')
|| strpos($data, "encoding='UTF-8'")
|| strpos($data, "encoding='utf-8'")
) {
$this->encoding = 'UTF-8';
}
$xp = xml_parser_create($this->encoding);
xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, 0);
xml_set_object($xp, $this);
xml_set_element_handler($xp, 'startHandler', 'endHandler');
xml_set_character_data_handler($xp, 'cdataHandler');
if (!xml_parse($xp, $data)) {
$msg = xml_error_string(xml_get_error_code($xp));
$line = xml_get_current_line_number($xp);
xml_parser_free($xp);
include_once 'PEAR.php';
return PEAR::raiseError("XML Error: '$msg' on line '$line'", 2);
}
xml_parser_free($xp);
return true;
}
/**
* Start element handler for XML parser
*
* @access private
* @param object $parser XML parser object
* @param string $element XML element
* @param array $attribs attributes of XML tag
* @return void
*/
function startHandler($parser, $element, $attribs)
{
$this->_depth++;
$this->_dataStack[$this->_depth] = null;
$val = array(
'name' => $element,
'value' => null,
'type' => 'string',
'childrenKeys' => array(),
'aggregKeys' => array()
);
if (count($attribs) > 0) {
$val['children'] = array();
$val['type'] = 'array';
$val['children']['attribs'] = $attribs;
}
array_push($this->_valStack, $val);
}
/**
* post-process data
*
* @param string $data
* @param string $element element name
*/
function postProcess($data, $element)
{
return trim($data);
}
/**
* End element handler for XML parser
*
* @access private
* @param object XML parser object
* @param string
* @return void
*/
function endHandler($parser, $element)
{
$value = array_pop($this->_valStack);
$data = $this->postProcess($this->_dataStack[$this->_depth], $element);
// adjust type of the value
switch (strtolower($value['type'])) {
// unserialize an array
case 'array':
if ($data !== '') {
$value['children']['_content'] = $data;
}
$value['value'] = isset($value['children']) ? $value['children'] : array();
break;
/*
* unserialize a null value
*/
case 'null':
$data = null;
break;
/*
* unserialize any scalar value
*/
default:
settype($data, $value['type']);
$value['value'] = $data;
break;
}
$parent = array_pop($this->_valStack);
if ($parent === null) {
$this->_unserializedData = &$value['value'];
$this->_root = &$value['name'];
return true;
}
// parent has to be an array
if (!isset($parent['children']) || !is_array($parent['children'])) {
$parent['children'] = array();
if ($parent['type'] != 'array') {
$parent['type'] = 'array';
}
}
if (!empty($value['name'])) {
// there already has been a tag with this name
if (in_array($value['name'], $parent['childrenKeys'])) {
// no aggregate has been created for this tag
if (!in_array($value['name'], $parent['aggregKeys'])) {
if (isset($parent['children'][$value['name']])) {
$parent['children'][$value['name']] = array($parent['children'][$value['name']]);
} else {
$parent['children'][$value['name']] = array();
}
array_push($parent['aggregKeys'], $value['name']);
}
array_push($parent['children'][$value['name']], $value['value']);
} else {
$parent['children'][$value['name']] = &$value['value'];
array_push($parent['childrenKeys'], $value['name']);
}
} else {
array_push($parent['children'],$value['value']);
}
array_push($this->_valStack, $parent);
$this->_depth--;
}
/**
* Handler for character data
*
* @access private
* @param object XML parser object
* @param string CDATA
* @return void
*/
function cdataHandler($parser, $cdata)
{
$this->_dataStack[$this->_depth] .= $cdata;
}
}PK �]��� � PEAR/ErrorStack.phpnu �[��� <?php
/**
* Error Stack Implementation
*
* This is an incredibly simple implementation of a very complex error handling
* facility. It contains the ability
* to track multiple errors from multiple packages simultaneously. In addition,
* it can track errors of many levels, save data along with the error, context
* information such as the exact file, line number, class and function that
* generated the error, and if necessary, it can raise a traditional PEAR_Error.
* It has built-in support for PEAR::Log, to log errors as they occur
*
* Since version 0.2alpha, it is also possible to selectively ignore errors,
* through the use of an error callback, see {@link pushCallback()}
*
* Since version 0.3alpha, it is possible to specify the exception class
* returned from {@link push()}
*
* Since version PEAR1.3.2, ErrorStack no longer instantiates an exception class. This can
* still be done quite handily in an error callback or by manipulating the returned array
* @category Debugging
* @package PEAR_ErrorStack
* @author Greg Beaver <cellog@php.net>
* @copyright 2004-2008 Greg Beaver
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR_ErrorStack
*/
/**
* Singleton storage
*
* Format:
* <pre>
* array(
* 'package1' => PEAR_ErrorStack object,
* 'package2' => PEAR_ErrorStack object,
* ...
* )
* </pre>
* @access private
* @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON']
*/
$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array();
/**
* Global error callback (default)
*
* This is only used if set to non-false. * is the default callback for
* all packages, whereas specific packages may set a default callback
* for all instances, regardless of whether they are a singleton or not.
*
* To exclude non-singletons, only set the local callback for the singleton
* @see PEAR_ErrorStack::setDefaultCallback()
* @access private
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']
*/
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array(
'*' => false,
);
/**
* Global Log object (default)
*
* This is only used if set to non-false. Use to set a default log object for
* all stacks, regardless of instantiation order or location
* @see PEAR_ErrorStack::setDefaultLogger()
* @access private
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
*/
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false;
/**
* Global Overriding Callback
*
* This callback will override any error callbacks that specific loggers have set.
* Use with EXTREME caution
* @see PEAR_ErrorStack::staticPushCallback()
* @access private
* @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']
*/
$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
/**#@+
* One of four possible return values from the error Callback
* @see PEAR_ErrorStack::_errorCallback()
*/
/**
* If this is returned, then the error will be both pushed onto the stack
* and logged.
*/
define('PEAR_ERRORSTACK_PUSHANDLOG', 1);
/**
* If this is returned, then the error will only be pushed onto the stack,
* and not logged.
*/
define('PEAR_ERRORSTACK_PUSH', 2);
/**
* If this is returned, then the error will only be logged, but not pushed
* onto the error stack.
*/
define('PEAR_ERRORSTACK_LOG', 3);
/**
* If this is returned, then the error is completely ignored.
*/
define('PEAR_ERRORSTACK_IGNORE', 4);
/**
* If this is returned, then the error is logged and die() is called.
*/
define('PEAR_ERRORSTACK_DIE', 5);
/**#@-*/
/**
* Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in
* the singleton method.
*/
define('PEAR_ERRORSTACK_ERR_NONCLASS', 1);
/**
* Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()}
* that has no __toString() method
*/
define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2);
/**
* Error Stack Implementation
*
* Usage:
* <code>
* // global error stack
* $global_stack = &PEAR_ErrorStack::singleton('MyPackage');
* // local error stack
* $local_stack = new PEAR_ErrorStack('MyPackage');
* </code>
* @author Greg Beaver <cellog@php.net>
* @version 1.10.18
* @package PEAR_ErrorStack
* @category Debugging
* @copyright 2004-2008 Greg Beaver
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR_ErrorStack
*/
class PEAR_ErrorStack {
/**
* Errors are stored in the order that they are pushed on the stack.
* @since 0.4alpha Errors are no longer organized by error level.
* This renders pop() nearly unusable, and levels could be more easily
* handled in a callback anyway
* @var array
* @access private
*/
var $_errors = array();
/**
* Storage of errors by level.
*
* Allows easy retrieval and deletion of only errors from a particular level
* @since PEAR 1.4.0dev
* @var array
* @access private
*/
var $_errorsByLevel = array();
/**
* Package name this error stack represents
* @var string
* @access protected
*/
var $_package;
/**
* Determines whether a PEAR_Error is thrown upon every error addition
* @var boolean
* @access private
*/
var $_compat = false;
/**
* If set to a valid callback, this will be used to generate the error
* message from the error code, otherwise the message passed in will be
* used
* @var false|string|array
* @access private
*/
var $_msgCallback = false;
/**
* If set to a valid callback, this will be used to generate the error
* context for an error. For PHP-related errors, this will be a file
* and line number as retrieved from debug_backtrace(), but can be
* customized for other purposes. The error might actually be in a separate
* configuration file, or in a database query.
* @var false|string|array
* @access protected
*/
var $_contextCallback = false;
/**
* If set to a valid callback, this will be called every time an error
* is pushed onto the stack. The return value will be used to determine
* whether to allow an error to be pushed or logged.
*
* The return value must be one an PEAR_ERRORSTACK_* constant
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
* @var false|string|array
* @access protected
*/
var $_errorCallback = array();
/**
* PEAR::Log object for logging errors
* @var false|Log
* @access protected
*/
var $_logger = false;
/**
* Error messages - designed to be overridden
* @var array
* @abstract
*/
var $_errorMsgs = array();
/**
* Set up a new error stack
*
* @param string $package name of the package this error stack represents
* @param callback $msgCallback callback used for error message generation
* @param callback $contextCallback callback used for context generation,
* defaults to {@link getFileLine()}
* @param boolean $throwPEAR_Error
*/
function __construct($package, $msgCallback = false, $contextCallback = false,
$throwPEAR_Error = false)
{
$this->_package = $package;
$this->setMessageCallback($msgCallback);
$this->setContextCallback($contextCallback);
$this->_compat = $throwPEAR_Error;
}
/**
* Return a single error stack for this package.
*
* Note that all parameters are ignored if the stack for package $package
* has already been instantiated
* @param string $package name of the package this error stack represents
* @param callback $msgCallback callback used for error message generation
* @param callback $contextCallback callback used for context generation,
* defaults to {@link getFileLine()}
* @param boolean $throwPEAR_Error
* @param string $stackClass class to instantiate
*
* @return PEAR_ErrorStack
*/
public static function &singleton(
$package, $msgCallback = false, $contextCallback = false,
$throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack'
) {
if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
}
if (!class_exists($stackClass)) {
if (function_exists('debug_backtrace')) {
$trace = debug_backtrace();
}
PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS,
'exception', array('stackclass' => $stackClass),
'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)',
false, $trace);
}
$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] =
new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error);
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package];
}
/**
* Internal error handler for PEAR_ErrorStack class
*
* Dies if the error is an exception (and would have died anyway)
* @access private
*/
function _handleError($err)
{
if ($err['level'] == 'exception') {
$message = $err['message'];
if (isset($_SERVER['REQUEST_URI'])) {
echo '<br />';
} else {
echo "\n";
}
var_dump($err['context']);
die($message);
}
}
/**
* Set up a PEAR::Log object for all error stacks that don't have one
* @param Log $log
*/
public static function setDefaultLogger(&$log)
{
if (is_object($log) && method_exists($log, 'log') ) {
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
} elseif (is_callable($log)) {
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log;
}
}
/**
* Set up a PEAR::Log object for this error stack
* @param Log $log
*/
function setLogger(&$log)
{
if (is_object($log) && method_exists($log, 'log') ) {
$this->_logger = &$log;
} elseif (is_callable($log)) {
$this->_logger = &$log;
}
}
/**
* Set an error code => error message mapping callback
*
* This method sets the callback that can be used to generate error
* messages for any instance
* @param array|string Callback function/method
*/
function setMessageCallback($msgCallback)
{
if (!$msgCallback) {
$this->_msgCallback = array(&$this, 'getErrorMessage');
} else {
if (is_callable($msgCallback)) {
$this->_msgCallback = $msgCallback;
}
}
}
/**
* Get an error code => error message mapping callback
*
* This method returns the current callback that can be used to generate error
* messages
* @return array|string|false Callback function/method or false if none
*/
function getMessageCallback()
{
return $this->_msgCallback;
}
/**
* Sets a default callback to be used by all error stacks
*
* This method sets the callback that can be used to generate error
* messages for a singleton
* @param array|string Callback function/method
* @param string Package name, or false for all packages
*/
public static function setDefaultCallback($callback = false, $package = false)
{
if (!is_callable($callback)) {
$callback = false;
}
$package = $package ? $package : '*';
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback;
}
/**
* Set a callback that generates context information (location of error) for an error stack
*
* This method sets the callback that can be used to generate context
* information for an error. Passing in NULL will disable context generation
* and remove the expensive call to debug_backtrace()
* @param array|string|null Callback function/method
*/
function setContextCallback($contextCallback)
{
if ($contextCallback === null) {
return $this->_contextCallback = false;
}
if (!$contextCallback) {
$this->_contextCallback = array(&$this, 'getFileLine');
} else {
if (is_callable($contextCallback)) {
$this->_contextCallback = $contextCallback;
}
}
}
/**
* Set an error Callback
* If set to a valid callback, this will be called every time an error
* is pushed onto the stack. The return value will be used to determine
* whether to allow an error to be pushed or logged.
*
* The return value must be one of the ERRORSTACK_* constants.
*
* This functionality can be used to emulate PEAR's pushErrorHandling, and
* the PEAR_ERROR_CALLBACK mode, without affecting the integrity of
* the error stack or logging
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
* @see popCallback()
* @param string|array $cb
*/
function pushCallback($cb)
{
array_push($this->_errorCallback, $cb);
}
/**
* Remove a callback from the error callback stack
* @see pushCallback()
* @return array|string|false
*/
function popCallback()
{
if (!count($this->_errorCallback)) {
return false;
}
return array_pop($this->_errorCallback);
}
/**
* Set a temporary overriding error callback for every package error stack
*
* Use this to temporarily disable all existing callbacks (can be used
* to emulate the @ operator, for instance)
* @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG
* @see staticPopCallback(), pushCallback()
* @param string|array $cb
*/
public static function staticPushCallback($cb)
{
array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb);
}
/**
* Remove a temporary overriding error callback
* @see staticPushCallback()
* @return array|string|false
*/
public static function staticPopCallback()
{
$ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']);
if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) {
$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array();
}
return $ret;
}
/**
* Add an error to the stack
*
* If the message generator exists, it is called with 2 parameters.
* - the current Error Stack object
* - an array that is in the same format as an error. Available indices
* are 'code', 'package', 'time', 'params', 'level', and 'context'
*
* Next, if the error should contain context information, this is
* handled by the context grabbing method.
* Finally, the error is pushed onto the proper error stack
* @param int $code Package-specific error code
* @param string $level Error level. This is NOT spell-checked
* @param array $params associative array of error parameters
* @param string $msg Error message, or a portion of it if the message
* is to be generated
* @param array $repackage If this error re-packages an error pushed by
* another package, place the array returned from
* {@link pop()} in this parameter
* @param array $backtrace Protected parameter: use this to pass in the
* {@link debug_backtrace()} that should be used
* to find error context
* @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
* thrown. If a PEAR_Error is returned, the userinfo
* property is set to the following array:
*
* <code>
* array(
* 'code' => $code,
* 'params' => $params,
* 'package' => $this->_package,
* 'level' => $level,
* 'time' => time(),
* 'context' => $context,
* 'message' => $msg,
* //['repackage' => $err] repackaged error array/Exception class
* );
* </code>
*
* Normally, the previous array is returned.
*/
function push($code, $level = 'error', $params = array(), $msg = false,
$repackage = false, $backtrace = false)
{
$context = false;
// grab error context
if ($this->_contextCallback) {
if (!$backtrace) {
$backtrace = debug_backtrace();
}
$context = call_user_func($this->_contextCallback, $code, $params, $backtrace);
}
// save error
$time = explode(' ', microtime());
$time = $time[1] + $time[0];
$err = array(
'code' => $code,
'params' => $params,
'package' => $this->_package,
'level' => $level,
'time' => $time,
'context' => $context,
'message' => $msg,
);
if ($repackage) {
$err['repackage'] = $repackage;
}
// set up the error message, if necessary
if ($this->_msgCallback) {
$msg = call_user_func_array($this->_msgCallback,
array(&$this, $err));
$err['message'] = $msg;
}
$push = $log = true;
$die = false;
// try the overriding callback first
$callback = $this->staticPopCallback();
if ($callback) {
$this->staticPushCallback($callback);
}
if (!is_callable($callback)) {
// try the local callback next
$callback = $this->popCallback();
if (is_callable($callback)) {
$this->pushCallback($callback);
} else {
// try the default callback
$callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ?
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] :
$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*'];
}
}
if (is_callable($callback)) {
switch(call_user_func($callback, $err)){
case PEAR_ERRORSTACK_IGNORE:
return $err;
break;
case PEAR_ERRORSTACK_PUSH:
$log = false;
break;
case PEAR_ERRORSTACK_LOG:
$push = false;
break;
case PEAR_ERRORSTACK_DIE:
$die = true;
break;
// anything else returned has the same effect as pushandlog
}
}
if ($push) {
array_unshift($this->_errors, $err);
if (!isset($this->_errorsByLevel[$err['level']])) {
$this->_errorsByLevel[$err['level']] = array();
}
$this->_errorsByLevel[$err['level']][] = &$this->_errors[0];
}
if ($log) {
if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) {
$this->_log($err);
}
}
if ($die) {
die();
}
if ($this->_compat && $push) {
return $this->raiseError($msg, $code, null, null, $err);
}
return $err;
}
/**
* Static version of {@link push()}
*
* @param string $package Package name this error belongs to
* @param int $code Package-specific error code
* @param string $level Error level. This is NOT spell-checked
* @param array $params associative array of error parameters
* @param string $msg Error message, or a portion of it if the message
* is to be generated
* @param array $repackage If this error re-packages an error pushed by
* another package, place the array returned from
* {@link pop()} in this parameter
* @param array $backtrace Protected parameter: use this to pass in the
* {@link debug_backtrace()} that should be used
* to find error context
* @return PEAR_Error|array if compatibility mode is on, a PEAR_Error is also
* thrown. see docs for {@link push()}
*/
public static function staticPush(
$package, $code, $level = 'error', $params = array(),
$msg = false, $repackage = false, $backtrace = false
) {
$s = &PEAR_ErrorStack::singleton($package);
if ($s->_contextCallback) {
if (!$backtrace) {
if (function_exists('debug_backtrace')) {
$backtrace = debug_backtrace();
}
}
}
return $s->push($code, $level, $params, $msg, $repackage, $backtrace);
}
/**
* Log an error using PEAR::Log
* @param array $err Error array
* @param array $levels Error level => Log constant map
* @access protected
*/
function _log($err)
{
if ($this->_logger) {
$logger = &$this->_logger;
} else {
$logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'];
}
if (is_a($logger, 'Log')) {
$levels = array(
'exception' => PEAR_LOG_CRIT,
'alert' => PEAR_LOG_ALERT,
'critical' => PEAR_LOG_CRIT,
'error' => PEAR_LOG_ERR,
'warning' => PEAR_LOG_WARNING,
'notice' => PEAR_LOG_NOTICE,
'info' => PEAR_LOG_INFO,
'debug' => PEAR_LOG_DEBUG);
if (isset($levels[$err['level']])) {
$level = $levels[$err['level']];
} else {
$level = PEAR_LOG_INFO;
}
$logger->log($err['message'], $level, $err);
} else { // support non-standard logs
call_user_func($logger, $err);
}
}
/**
* Pop an error off of the error stack
*
* @return false|array
* @since 0.4alpha it is no longer possible to specify a specific error
* level to return - the last error pushed will be returned, instead
*/
function pop()
{
$err = @array_shift($this->_errors);
if (!is_null($err)) {
@array_pop($this->_errorsByLevel[$err['level']]);
if (!count($this->_errorsByLevel[$err['level']])) {
unset($this->_errorsByLevel[$err['level']]);
}
}
return $err;
}
/**
* Pop an error off of the error stack, static method
*
* @param string package name
* @return boolean
* @since PEAR1.5.0a1
*/
static function staticPop($package)
{
if ($package) {
if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
return false;
}
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->pop();
}
}
/**
* Determine whether there are any errors on the stack
* @param string|array Level name. Use to determine if any errors
* of level (string), or levels (array) have been pushed
* @return boolean
*/
function hasErrors($level = false)
{
if ($level) {
return isset($this->_errorsByLevel[$level]);
}
return count($this->_errors);
}
/**
* Retrieve all errors since last purge
*
* @param boolean set in order to empty the error stack
* @param string level name, to return only errors of a particular severity
* @return array
*/
function getErrors($purge = false, $level = false)
{
if (!$purge) {
if ($level) {
if (!isset($this->_errorsByLevel[$level])) {
return array();
} else {
return $this->_errorsByLevel[$level];
}
} else {
return $this->_errors;
}
}
if ($level) {
$ret = $this->_errorsByLevel[$level];
foreach ($this->_errorsByLevel[$level] as $i => $unused) {
// entries are references to the $_errors array
$this->_errorsByLevel[$level][$i] = false;
}
// array_filter removes all entries === false
$this->_errors = array_filter($this->_errors);
unset($this->_errorsByLevel[$level]);
return $ret;
}
$ret = $this->_errors;
$this->_errors = array();
$this->_errorsByLevel = array();
return $ret;
}
/**
* Determine whether there are any errors on a single error stack, or on any error stack
*
* The optional parameter can be used to test the existence of any errors without the need of
* singleton instantiation
* @param string|false Package name to check for errors
* @param string Level name to check for a particular severity
* @return boolean
*/
public static function staticHasErrors($package = false, $level = false)
{
if ($package) {
if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) {
return false;
}
return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level);
}
foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
if ($obj->hasErrors($level)) {
return true;
}
}
return false;
}
/**
* Get a list of all errors since last purge, organized by package
* @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be
* @param boolean $purge Set to purge the error stack of existing errors
* @param string $level Set to a level name in order to retrieve only errors of a particular level
* @param boolean $merge Set to return a flat array, not organized by package
* @param array $sortfunc Function used to sort a merged array - default
* sorts by time, and should be good for most cases
*
* @return array
*/
public static function staticGetErrors(
$purge = false, $level = false, $merge = false,
$sortfunc = array('PEAR_ErrorStack', '_sortErrors')
) {
$ret = array();
if (!is_callable($sortfunc)) {
$sortfunc = array('PEAR_ErrorStack', '_sortErrors');
}
foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) {
$test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level);
if ($test) {
if ($merge) {
$ret = array_merge($ret, $test);
} else {
$ret[$package] = $test;
}
}
}
if ($merge) {
usort($ret, $sortfunc);
}
return $ret;
}
/**
* Error sorting function, sorts by time
* @access private
*/
public static function _sortErrors($a, $b)
{
if ($a['time'] == $b['time']) {
return 0;
}
if ($a['time'] < $b['time']) {
return 1;
}
return -1;
}
/**
* Standard file/line number/function/class context callback
*
* This function uses a backtrace generated from {@link debug_backtrace()}
* and so will not work at all in PHP < 4.3.0. The frame should
* reference the frame that contains the source of the error.
* @return array|false either array('file' => file, 'line' => line,
* 'function' => function name, 'class' => class name) or
* if this doesn't work, then false
* @param unused
* @param integer backtrace frame.
* @param array Results of debug_backtrace()
*/
public static function getFileLine($code, $params, $backtrace = null)
{
if ($backtrace === null) {
return false;
}
$frame = 0;
$functionframe = 1;
if (!isset($backtrace[1])) {
$functionframe = 0;
} else {
while (isset($backtrace[$functionframe]['function']) &&
$backtrace[$functionframe]['function'] == 'eval' &&
isset($backtrace[$functionframe + 1])) {
$functionframe++;
}
}
if (isset($backtrace[$frame])) {
if (!isset($backtrace[$frame]['file'])) {
$frame++;
}
$funcbacktrace = $backtrace[$functionframe];
$filebacktrace = $backtrace[$frame];
$ret = array('file' => $filebacktrace['file'],
'line' => $filebacktrace['line']);
// rearrange for eval'd code or create function errors
if (strpos($filebacktrace['file'], '(') &&
preg_match(';^(.*?)\((\d+)\) : (.*?)\\z;', $filebacktrace['file'],
$matches)) {
$ret['file'] = $matches[1];
$ret['line'] = $matches[2] + 0;
}
if (isset($funcbacktrace['function']) && isset($backtrace[1])) {
if ($funcbacktrace['function'] != 'eval') {
if ($funcbacktrace['function'] == '__lambda_func') {
$ret['function'] = 'create_function() code';
} else {
$ret['function'] = $funcbacktrace['function'];
}
}
}
if (isset($funcbacktrace['class']) && isset($backtrace[1])) {
$ret['class'] = $funcbacktrace['class'];
}
return $ret;
}
return false;
}
/**
* Standard error message generation callback
*
* This method may also be called by a custom error message generator
* to fill in template values from the params array, simply
* set the third parameter to the error message template string to use
*
* The special variable %__msg% is reserved: use it only to specify
* where a message passed in by the user should be placed in the template,
* like so:
*
* Error message: %msg% - internal error
*
* If the message passed like so:
*
* <code>
* $stack->push(ERROR_CODE, 'error', array(), 'server error 500');
* </code>
*
* The returned error message will be "Error message: server error 500 -
* internal error"
* @param PEAR_ErrorStack
* @param array
* @param string|false Pre-generated error message template
*
* @return string
*/
public static function getErrorMessage(&$stack, $err, $template = false)
{
if ($template) {
$mainmsg = $template;
} else {
$mainmsg = $stack->getErrorMessageTemplate($err['code']);
}
$mainmsg = str_replace('%__msg%', $err['message'], $mainmsg);
if (is_array($err['params']) && count($err['params'])) {
foreach ($err['params'] as $name => $val) {
if (is_array($val)) {
// @ is needed in case $val is a multi-dimensional array
$val = @implode(', ', $val);
}
if (is_object($val)) {
if (method_exists($val, '__toString')) {
$val = $val->__toString();
} else {
PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING,
'warning', array('obj' => get_class($val)),
'object %obj% passed into getErrorMessage, but has no __toString() method');
$val = 'Object';
}
}
$mainmsg = str_replace('%' . $name . '%', $val, $mainmsg);
}
}
return $mainmsg;
}
/**
* Standard Error Message Template generator from code
* @return string
*/
function getErrorMessageTemplate($code)
{
if (!isset($this->_errorMsgs[$code])) {
return '%__msg%';
}
return $this->_errorMsgs[$code];
}
/**
* Set the Error Message Template array
*
* The array format must be:
* <pre>
* array(error code => 'message template',...)
* </pre>
*
* Error message parameters passed into {@link push()} will be used as input
* for the error message. If the template is 'message %foo% was %bar%', and the
* parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will
* be 'message one was six'
* @return string
*/
function setErrorMessageTemplate($template)
{
$this->_errorMsgs = $template;
}
/**
* emulate PEAR::raiseError()
*
* @return PEAR_Error
*/
function raiseError()
{
require_once 'PEAR.php';
$args = func_get_args();
return call_user_func_array(array('PEAR', 'raiseError'), $args);
}
}
$stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack');
$stack->pushCallback(array('PEAR_ErrorStack', '_handleError'));
?>
PK �]Ga���� �� PEAR/ChannelFile.phpnu �[��� <?php
/**
* PEAR_ChannelFile, the channel handling class
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* Needed for error handling
*/
require_once 'PEAR/ErrorStack.php';
require_once 'PEAR/XMLParser.php';
require_once 'PEAR/Common.php';
/**
* Error code if the channel.xml <channel> tag does not contain a valid version
*/
define('PEAR_CHANNELFILE_ERROR_NO_VERSION', 1);
/**
* Error code if the channel.xml <channel> tag version is not supported (version 1.0 is the only supported version,
* currently
*/
define('PEAR_CHANNELFILE_ERROR_INVALID_VERSION', 2);
/**
* Error code if parsing is attempted with no xml extension
*/
define('PEAR_CHANNELFILE_ERROR_NO_XML_EXT', 3);
/**
* Error code if creating the xml parser resource fails
*/
define('PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER', 4);
/**
* Error code used for all sax xml parsing errors
*/
define('PEAR_CHANNELFILE_ERROR_PARSER_ERROR', 5);
/**#@+
* Validation errors
*/
/**
* Error code when channel name is missing
*/
define('PEAR_CHANNELFILE_ERROR_NO_NAME', 6);
/**
* Error code when channel name is invalid
*/
define('PEAR_CHANNELFILE_ERROR_INVALID_NAME', 7);
/**
* Error code when channel summary is missing
*/
define('PEAR_CHANNELFILE_ERROR_NO_SUMMARY', 8);
/**
* Error code when channel summary is multi-line
*/
define('PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY', 9);
/**
* Error code when channel server is missing for protocol
*/
define('PEAR_CHANNELFILE_ERROR_NO_HOST', 10);
/**
* Error code when channel server is invalid for protocol
*/
define('PEAR_CHANNELFILE_ERROR_INVALID_HOST', 11);
/**
* Error code when a mirror name is invalid
*/
define('PEAR_CHANNELFILE_ERROR_INVALID_MIRROR', 21);
/**
* Error code when a mirror type is invalid
*/
define('PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE', 22);
/**
* Error code when an attempt is made to generate xml, but the parsed content is invalid
*/
define('PEAR_CHANNELFILE_ERROR_INVALID', 23);
/**
* Error code when an empty package name validate regex is passed in
*/
define('PEAR_CHANNELFILE_ERROR_EMPTY_REGEX', 24);
/**
* Error code when a <function> tag has no version
*/
define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION', 25);
/**
* Error code when a <function> tag has no name
*/
define('PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME', 26);
/**
* Error code when a <validatepackage> tag has no name
*/
define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME', 27);
/**
* Error code when a <validatepackage> tag has no version attribute
*/
define('PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION', 28);
/**
* Error code when a mirror does not exist but is called for in one of the set*
* methods.
*/
define('PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND', 32);
/**
* Error code when a server port is not numeric
*/
define('PEAR_CHANNELFILE_ERROR_INVALID_PORT', 33);
/**
* Error code when <static> contains no version attribute
*/
define('PEAR_CHANNELFILE_ERROR_NO_STATICVERSION', 34);
/**
* Error code when <baseurl> contains no type attribute in a <rest> protocol definition
*/
define('PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE', 35);
/**
* Error code when a mirror is defined and the channel.xml represents the __uri pseudo-channel
*/
define('PEAR_CHANNELFILE_URI_CANT_MIRROR', 36);
/**
* Error code when ssl attribute is present and is not "yes"
*/
define('PEAR_CHANNELFILE_ERROR_INVALID_SSL', 37);
/**#@-*/
/**
* Mirror types allowed. Currently only internet servers are recognized.
*/
$GLOBALS['_PEAR_CHANNELS_MIRROR_TYPES'] = array('server');
/**
* The Channel handling class
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_ChannelFile
{
/**
* @access private
* @var PEAR_ErrorStack
* @access private
*/
var $_stack;
/**
* Supported channel.xml versions, for parsing
* @var array
* @access private
*/
var $_supportedVersions = array('1.0');
/**
* Parsed channel information
* @var array
* @access private
*/
var $_channelInfo;
/**
* index into the subchannels array, used for parsing xml
* @var int
* @access private
*/
var $_subchannelIndex;
/**
* index into the mirrors array, used for parsing xml
* @var int
* @access private
*/
var $_mirrorIndex;
/**
* Flag used to determine the validity of parsed content
* @var boolean
* @access private
*/
var $_isValid = false;
function __construct()
{
$this->_stack = new PEAR_ErrorStack('PEAR_ChannelFile');
$this->_stack->setErrorMessageTemplate($this->_getErrorMessage());
$this->_isValid = false;
}
/**
* @return array
* @access protected
*/
function _getErrorMessage()
{
return
array(
PEAR_CHANNELFILE_ERROR_INVALID_VERSION =>
'While parsing channel.xml, an invalid version number "%version% was passed in, expecting one of %versions%',
PEAR_CHANNELFILE_ERROR_NO_VERSION =>
'No version number found in <channel> tag',
PEAR_CHANNELFILE_ERROR_NO_XML_EXT =>
'%error%',
PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER =>
'Unable to create XML parser',
PEAR_CHANNELFILE_ERROR_PARSER_ERROR =>
'%error%',
PEAR_CHANNELFILE_ERROR_NO_NAME =>
'Missing channel name',
PEAR_CHANNELFILE_ERROR_INVALID_NAME =>
'Invalid channel %tag% "%name%"',
PEAR_CHANNELFILE_ERROR_NO_SUMMARY =>
'Missing channel summary',
PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY =>
'Channel summary should be on one line, but is multi-line',
PEAR_CHANNELFILE_ERROR_NO_HOST =>
'Missing channel server for %type% server',
PEAR_CHANNELFILE_ERROR_INVALID_HOST =>
'Server name "%server%" is invalid for %type% server',
PEAR_CHANNELFILE_ERROR_INVALID_MIRROR =>
'Invalid mirror name "%name%", mirror type %type%',
PEAR_CHANNELFILE_ERROR_INVALID_MIRRORTYPE =>
'Invalid mirror type "%type%"',
PEAR_CHANNELFILE_ERROR_INVALID =>
'Cannot generate xml, contents are invalid',
PEAR_CHANNELFILE_ERROR_EMPTY_REGEX =>
'packagenameregex cannot be empty',
PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION =>
'%parent% %protocol% function has no version',
PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME =>
'%parent% %protocol% function has no name',
PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE =>
'%parent% rest baseurl has no type',
PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME =>
'Validation package has no name in <validatepackage> tag',
PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION =>
'Validation package "%package%" has no version',
PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND =>
'Mirror "%mirror%" does not exist',
PEAR_CHANNELFILE_ERROR_INVALID_PORT =>
'Port "%port%" must be numeric',
PEAR_CHANNELFILE_ERROR_NO_STATICVERSION =>
'<static> tag must contain version attribute',
PEAR_CHANNELFILE_URI_CANT_MIRROR =>
'The __uri pseudo-channel cannot have mirrors',
PEAR_CHANNELFILE_ERROR_INVALID_SSL =>
'%server% has invalid ssl attribute "%ssl%" can only be yes or not present',
);
}
/**
* @param string contents of package.xml file
* @return bool success of parsing
*/
function fromXmlString($data)
{
if (preg_match('/<channel\s+version="([0-9]+\.[0-9]+)"/', $data, $channelversion)) {
if (!in_array($channelversion[1], $this->_supportedVersions)) {
$this->_stack->push(PEAR_CHANNELFILE_ERROR_INVALID_VERSION, 'error',
array('version' => $channelversion[1]));
return false;
}
$parser = new PEAR_XMLParser;
$result = $parser->parse($data);
if ($result !== true) {
if ($result->getCode() == 1) {
$this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_XML_EXT, 'error',
array('error' => $result->getMessage()));
} else {
$this->_stack->push(PEAR_CHANNELFILE_ERROR_CANT_MAKE_PARSER, 'error');
}
return false;
}
$this->_channelInfo = $parser->getData();
return true;
} else {
$this->_stack->push(PEAR_CHANNELFILE_ERROR_NO_VERSION, 'error', array('xml' => $data));
return false;
}
}
/**
* @return array
*/
function toArray()
{
if (!$this->_isValid && !$this->validate()) {
return false;
}
return $this->_channelInfo;
}
/**
* @param array
*
* @return PEAR_ChannelFile|false false if invalid
*/
public static function &fromArray(
$data, $compatibility = false, $stackClass = 'PEAR_ErrorStack'
) {
$a = new PEAR_ChannelFile($compatibility, $stackClass);
$a->_fromArray($data);
if (!$a->validate()) {
$a = false;
return $a;
}
return $a;
}
/**
* Unlike {@link fromArray()} this does not do any validation
*
* @param array
*
* @return PEAR_ChannelFile
*/
public static function &fromArrayWithErrors(
$data, $compatibility = false, $stackClass = 'PEAR_ErrorStack'
) {
$a = new PEAR_ChannelFile($compatibility, $stackClass);
$a->_fromArray($data);
return $a;
}
/**
* @param array
* @access private
*/
function _fromArray($data)
{
$this->_channelInfo = $data;
}
/**
* Wrapper to {@link PEAR_ErrorStack::getErrors()}
* @param boolean determines whether to purge the error stack after retrieving
* @return array
*/
function getErrors($purge = false)
{
return $this->_stack->getErrors($purge);
}
/**
* 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;
}
/**
* Parse a channel.xml file. Expects the name of
* a channel xml file as input.
*
* @param string $descfile name of channel xml file
* @return bool success of parsing
*/
function fromXmlFile($descfile)
{
if (!file_exists($descfile) || !is_file($descfile) || !is_readable($descfile) ||
(!$fp = fopen($descfile, 'r'))) {
require_once 'PEAR.php';
return PEAR::raiseError("Unable to open $descfile");
}
// read the whole thing so we only get one cdata callback
// for each block of cdata
fclose($fp);
$data = file_get_contents($descfile);
return $this->fromXmlString($data);
}
/**
* Parse channel information from different sources
*
* This method is able to extract information about a channel
* from an .xml file or a string
*
* @access public
* @param string Filename of the source or the source itself
* @return bool
*/
function fromAny($info)
{
if (is_string($info) && file_exists($info) && strlen($info) < 255) {
$tmp = substr($info, -4);
if ($tmp == '.xml') {
$info = $this->fromXmlFile($info);
} else {
$fp = fopen($info, "r");
$test = fread($fp, 5);
fclose($fp);
if ($test == "<?xml") {
$info = $this->fromXmlFile($info);
}
}
if (PEAR::isError($info)) {
require_once 'PEAR.php';
return PEAR::raiseError($info);
}
}
if (is_string($info)) {
$info = $this->fromXmlString($info);
}
return $info;
}
/**
* Return an XML document based on previous parsing and modifications
*
* @return string XML data
*
* @access public
*/
function toXml()
{
if (!$this->_isValid && !$this->validate()) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID);
return false;
}
if (!isset($this->_channelInfo['attribs']['version'])) {
$this->_channelInfo['attribs']['version'] = '1.0';
}
$channelInfo = $this->_channelInfo;
$ret = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n";
$ret .= "<channel version=\"" .
$channelInfo['attribs']['version'] . "\" xmlns=\"http://pear.php.net/channel-1.0\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xsi:schemaLocation=\"http://pear.php.net/dtd/channel-"
. $channelInfo['attribs']['version'] . " http://pear.php.net/dtd/channel-" .
$channelInfo['attribs']['version'] . ".xsd\">
<name>$channelInfo[name]</name>
<summary>" . htmlspecialchars($channelInfo['summary'])."</summary>
";
if (isset($channelInfo['suggestedalias'])) {
$ret .= ' <suggestedalias>' . $channelInfo['suggestedalias'] . "</suggestedalias>\n";
}
if (isset($channelInfo['validatepackage'])) {
$ret .= ' <validatepackage version="' .
$channelInfo['validatepackage']['attribs']['version']. '">' .
htmlspecialchars($channelInfo['validatepackage']['_content']) .
"</validatepackage>\n";
}
$ret .= " <servers>\n";
$ret .= ' <primary';
if (isset($channelInfo['servers']['primary']['attribs']['ssl'])) {
$ret .= ' ssl="' . $channelInfo['servers']['primary']['attribs']['ssl'] . '"';
}
if (isset($channelInfo['servers']['primary']['attribs']['port'])) {
$ret .= ' port="' . $channelInfo['servers']['primary']['attribs']['port'] . '"';
}
$ret .= ">\n";
if (isset($channelInfo['servers']['primary']['rest'])) {
$ret .= $this->_makeRestXml($channelInfo['servers']['primary']['rest'], ' ');
}
$ret .= " </primary>\n";
if (isset($channelInfo['servers']['mirror'])) {
$ret .= $this->_makeMirrorsXml($channelInfo);
}
$ret .= " </servers>\n";
$ret .= "</channel>";
return str_replace("\r", "\n", str_replace("\r\n", "\n", $ret));
}
/**
* Generate the <rest> tag
* @access private
*/
function _makeRestXml($info, $indent)
{
$ret = $indent . "<rest>\n";
if (isset($info['baseurl']) && !isset($info['baseurl'][0])) {
$info['baseurl'] = array($info['baseurl']);
}
if (isset($info['baseurl'])) {
foreach ($info['baseurl'] as $url) {
$ret .= "$indent <baseurl type=\"" . $url['attribs']['type'] . "\"";
$ret .= ">" . $url['_content'] . "</baseurl>\n";
}
}
$ret .= $indent . "</rest>\n";
return $ret;
}
/**
* Generate the <mirrors> tag
* @access private
*/
function _makeMirrorsXml($channelInfo)
{
$ret = "";
if (!isset($channelInfo['servers']['mirror'][0])) {
$channelInfo['servers']['mirror'] = array($channelInfo['servers']['mirror']);
}
foreach ($channelInfo['servers']['mirror'] as $mirror) {
$ret .= ' <mirror host="' . $mirror['attribs']['host'] . '"';
if (isset($mirror['attribs']['port'])) {
$ret .= ' port="' . $mirror['attribs']['port'] . '"';
}
if (isset($mirror['attribs']['ssl'])) {
$ret .= ' ssl="' . $mirror['attribs']['ssl'] . '"';
}
$ret .= ">\n";
if (isset($mirror['rest'])) {
if (isset($mirror['rest'])) {
$ret .= $this->_makeRestXml($mirror['rest'], ' ');
}
$ret .= " </mirror>\n";
} else {
$ret .= "/>\n";
}
}
return $ret;
}
/**
* Generate the <functions> tag
* @access private
*/
function _makeFunctionsXml($functions, $indent, $rest = false)
{
$ret = '';
if (!isset($functions[0])) {
$functions = array($functions);
}
foreach ($functions as $function) {
$ret .= "$indent<function version=\"" . $function['attribs']['version'] . "\"";
if ($rest) {
$ret .= ' uri="' . $function['attribs']['uri'] . '"';
}
$ret .= ">" . $function['_content'] . "</function>\n";
}
return $ret;
}
/**
* 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);
$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);
}
/**
* Validate parsed file.
*
* @access public
* @return boolean
*/
function validate()
{
$this->_isValid = true;
$info = $this->_channelInfo;
if (empty($info['name'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_NAME);
} elseif (!$this->validChannelServer($info['name'])) {
if ($info['name'] != '__uri') {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME, array('tag' => 'name',
'name' => $info['name']));
}
}
if (empty($info['summary'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
} elseif (strpos(trim($info['summary']), "\n") !== false) {
$this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
array('summary' => $info['summary']));
}
if (isset($info['suggestedalias'])) {
if (!$this->validChannelServer($info['suggestedalias'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
array('tag' => 'suggestedalias', 'name' =>$info['suggestedalias']));
}
}
if (isset($info['localalias'])) {
if (!$this->validChannelServer($info['localalias'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
array('tag' => 'localalias', 'name' =>$info['localalias']));
}
}
if (isset($info['validatepackage'])) {
if (!isset($info['validatepackage']['_content'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_NAME);
}
if (!isset($info['validatepackage']['attribs']['version'])) {
$content = isset($info['validatepackage']['_content']) ?
$info['validatepackage']['_content'] :
null;
$this->_validateError(PEAR_CHANNELFILE_ERROR_NOVALIDATE_VERSION,
array('package' => $content));
}
}
if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['port']) &&
!is_numeric($info['servers']['primary']['attribs']['port'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_PORT,
array('port' => $info['servers']['primary']['attribs']['port']));
}
if (isset($info['servers']['primary']['attribs'], $info['servers']['primary']['attribs']['ssl']) &&
$info['servers']['primary']['attribs']['ssl'] != 'yes') {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
array('ssl' => $info['servers']['primary']['attribs']['ssl'],
'server' => $info['name']));
}
if (isset($info['servers']['primary']['rest']) &&
isset($info['servers']['primary']['rest']['baseurl'])) {
$this->_validateFunctions('rest', $info['servers']['primary']['rest']['baseurl']);
}
if (isset($info['servers']['mirror'])) {
if ($this->_channelInfo['name'] == '__uri') {
$this->_validateError(PEAR_CHANNELFILE_URI_CANT_MIRROR);
}
if (!isset($info['servers']['mirror'][0])) {
$info['servers']['mirror'] = array($info['servers']['mirror']);
}
foreach ($info['servers']['mirror'] as $mirror) {
if (!isset($mirror['attribs']['host'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_HOST,
array('type' => 'mirror'));
} elseif (!$this->validChannelServer($mirror['attribs']['host'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_HOST,
array('server' => $mirror['attribs']['host'], 'type' => 'mirror'));
}
if (isset($mirror['attribs']['ssl']) && $mirror['attribs']['ssl'] != 'yes') {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_SSL,
array('ssl' => $info['ssl'], 'server' => $mirror['attribs']['host']));
}
if (isset($mirror['rest'])) {
$this->_validateFunctions('rest', $mirror['rest']['baseurl'],
$mirror['attribs']['host']);
}
}
}
return $this->_isValid;
}
/**
* @param string rest - protocol name this function applies to
* @param array the functions
* @param string the name of the parent element (mirror name, for instance)
*/
function _validateFunctions($protocol, $functions, $parent = '')
{
if (!isset($functions[0])) {
$functions = array($functions);
}
foreach ($functions as $function) {
if (!isset($function['_content']) || empty($function['_content'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONNAME,
array('parent' => $parent, 'protocol' => $protocol));
}
if ($protocol == 'rest') {
if (!isset($function['attribs']['type']) ||
empty($function['attribs']['type'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NOBASEURLTYPE,
array('parent' => $parent, 'protocol' => $protocol));
}
} else {
if (!isset($function['attribs']['version']) ||
empty($function['attribs']['version'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_FUNCTIONVERSION,
array('parent' => $parent, 'protocol' => $protocol));
}
}
}
}
/**
* Test whether a string contains a valid channel server.
* @param string $ver the package version to test
* @return bool
*/
function validChannelServer($server)
{
if ($server == '__uri') {
return true;
}
return (bool) preg_match(PEAR_CHANNELS_SERVER_PREG, $server);
}
/**
* @return string|false
*/
function getName()
{
if (isset($this->_channelInfo['name'])) {
return $this->_channelInfo['name'];
}
return false;
}
/**
* @return string|false
*/
function getServer()
{
if (isset($this->_channelInfo['name'])) {
return $this->_channelInfo['name'];
}
return false;
}
/**
* @return int|80 port number to connect to
*/
function getPort($mirror = false)
{
if ($mirror) {
if ($mir = $this->getMirror($mirror)) {
if (isset($mir['attribs']['port'])) {
return $mir['attribs']['port'];
}
if ($this->getSSL($mirror)) {
return 443;
}
return 80;
}
return false;
}
if (isset($this->_channelInfo['servers']['primary']['attribs']['port'])) {
return $this->_channelInfo['servers']['primary']['attribs']['port'];
}
if ($this->getSSL()) {
return 443;
}
return 80;
}
/**
* @return bool Determines whether secure sockets layer (SSL) is used to connect to this channel
*/
function getSSL($mirror = false)
{
if ($mirror) {
if ($mir = $this->getMirror($mirror)) {
if (isset($mir['attribs']['ssl'])) {
return true;
}
return false;
}
return false;
}
if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
return true;
}
return false;
}
/**
* @return string|false
*/
function getSummary()
{
if (isset($this->_channelInfo['summary'])) {
return $this->_channelInfo['summary'];
}
return false;
}
/**
* @param string protocol type
* @param string Mirror name
* @return array|false
*/
function getFunctions($protocol, $mirror = false)
{
if ($this->getName() == '__uri') {
return false;
}
$function = $protocol == 'rest' ? 'baseurl' : 'function';
if ($mirror) {
if ($mir = $this->getMirror($mirror)) {
if (isset($mir[$protocol][$function])) {
return $mir[$protocol][$function];
}
}
return false;
}
if (isset($this->_channelInfo['servers']['primary'][$protocol][$function])) {
return $this->_channelInfo['servers']['primary'][$protocol][$function];
}
return false;
}
/**
* @param string Protocol type
* @param string Function name (null to return the
* first protocol of the type requested)
* @param string Mirror name, if any
* @return array
*/
function getFunction($type, $name = null, $mirror = false)
{
$protocols = $this->getFunctions($type, $mirror);
if (!$protocols) {
return false;
}
foreach ($protocols as $protocol) {
if ($name === null) {
return $protocol;
}
if ($protocol['_content'] != $name) {
continue;
}
return $protocol;
}
return false;
}
/**
* @param string protocol type
* @param string protocol name
* @param string version
* @param string mirror name
* @return boolean
*/
function supports($type, $name = null, $mirror = false, $version = '1.0')
{
$protocols = $this->getFunctions($type, $mirror);
if (!$protocols) {
return false;
}
foreach ($protocols as $protocol) {
if ($protocol['attribs']['version'] != $version) {
continue;
}
if ($name === null) {
return true;
}
if ($protocol['_content'] != $name) {
continue;
}
return true;
}
return false;
}
/**
* Determines whether a channel supports Representational State Transfer (REST) protocols
* for retrieving channel information
* @param string
* @return bool
*/
function supportsREST($mirror = false)
{
if ($mirror == $this->_channelInfo['name']) {
$mirror = false;
}
if ($mirror) {
if ($mir = $this->getMirror($mirror)) {
return isset($mir['rest']);
}
return false;
}
return isset($this->_channelInfo['servers']['primary']['rest']);
}
/**
* Get the URL to access a base resource.
*
* Hyperlinks in the returned xml will be used to retrieve the proper information
* needed. This allows extreme extensibility and flexibility in implementation
* @param string Resource Type to retrieve
*/
function getBaseURL($resourceType, $mirror = false)
{
if ($mirror == $this->_channelInfo['name']) {
$mirror = false;
}
if ($mirror) {
$mir = $this->getMirror($mirror);
if (!$mir) {
return false;
}
$rest = $mir['rest'];
} else {
$rest = $this->_channelInfo['servers']['primary']['rest'];
}
if (!isset($rest['baseurl'][0])) {
$rest['baseurl'] = array($rest['baseurl']);
}
foreach ($rest['baseurl'] as $baseurl) {
if (strtolower($baseurl['attribs']['type']) == strtolower($resourceType)) {
return $baseurl['_content'];
}
}
return false;
}
/**
* Since REST does not implement RPC, provide this as a logical wrapper around
* resetFunctions for REST
* @param string|false mirror name, if any
*/
function resetREST($mirror = false)
{
return $this->resetFunctions('rest', $mirror);
}
/**
* Empty all protocol definitions
* @param string protocol type
* @param string|false mirror name, if any
*/
function resetFunctions($type, $mirror = false)
{
if ($mirror) {
if (isset($this->_channelInfo['servers']['mirror'])) {
$mirrors = $this->_channelInfo['servers']['mirror'];
if (!isset($mirrors[0])) {
$mirrors = array($mirrors);
}
foreach ($mirrors as $i => $mir) {
if ($mir['attribs']['host'] == $mirror) {
if (isset($this->_channelInfo['servers']['mirror'][$i][$type])) {
unset($this->_channelInfo['servers']['mirror'][$i][$type]);
}
return true;
}
}
return false;
}
return false;
}
if (isset($this->_channelInfo['servers']['primary'][$type])) {
unset($this->_channelInfo['servers']['primary'][$type]);
}
return true;
}
/**
* Set a channel's protocols to the protocols supported by pearweb
*/
function setDefaultPEARProtocols($version = '1.0', $mirror = false)
{
switch ($version) {
case '1.0' :
$this->resetREST($mirror);
if (!isset($this->_channelInfo['servers'])) {
$this->_channelInfo['servers'] = array('primary' =>
array('rest' => array()));
} elseif (!isset($this->_channelInfo['servers']['primary'])) {
$this->_channelInfo['servers']['primary'] = array('rest' => array());
}
return true;
break;
default :
return false;
break;
}
}
/**
* @return array
*/
function getMirrors()
{
if (isset($this->_channelInfo['servers']['mirror'])) {
$mirrors = $this->_channelInfo['servers']['mirror'];
if (!isset($mirrors[0])) {
$mirrors = array($mirrors);
}
return $mirrors;
}
return array();
}
/**
* Get the unserialized XML representing a mirror
* @return array|false
*/
function getMirror($server)
{
foreach ($this->getMirrors() as $mirror) {
if ($mirror['attribs']['host'] == $server) {
return $mirror;
}
}
return false;
}
/**
* @param string
* @return string|false
* @error PEAR_CHANNELFILE_ERROR_NO_NAME
* @error PEAR_CHANNELFILE_ERROR_INVALID_NAME
*/
function setName($name)
{
return $this->setServer($name);
}
/**
* Set the socket number (port) that is used to connect to this channel
* @param integer
* @param string|false name of the mirror server, or false for the primary
*/
function setPort($port, $mirror = false)
{
if ($mirror) {
if (!isset($this->_channelInfo['servers']['mirror'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
array('mirror' => $mirror));
return false;
}
if (isset($this->_channelInfo['servers']['mirror'][0])) {
foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
if ($mirror == $mir['attribs']['host']) {
$this->_channelInfo['servers']['mirror'][$i]['attribs']['port'] = $port;
return true;
}
}
return false;
} elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
$this->_channelInfo['servers']['mirror']['attribs']['port'] = $port;
$this->_isValid = false;
return true;
}
}
$this->_channelInfo['servers']['primary']['attribs']['port'] = $port;
$this->_isValid = false;
return true;
}
/**
* Set the socket number (port) that is used to connect to this channel
* @param bool Determines whether to turn on SSL support or turn it off
* @param string|false name of the mirror server, or false for the primary
*/
function setSSL($ssl = true, $mirror = false)
{
if ($mirror) {
if (!isset($this->_channelInfo['servers']['mirror'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
array('mirror' => $mirror));
return false;
}
if (isset($this->_channelInfo['servers']['mirror'][0])) {
foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
if ($mirror == $mir['attribs']['host']) {
if (!$ssl) {
if (isset($this->_channelInfo['servers']['mirror'][$i]
['attribs']['ssl'])) {
unset($this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl']);
}
} else {
$this->_channelInfo['servers']['mirror'][$i]['attribs']['ssl'] = 'yes';
}
return true;
}
}
return false;
} elseif ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
if (!$ssl) {
if (isset($this->_channelInfo['servers']['mirror']['attribs']['ssl'])) {
unset($this->_channelInfo['servers']['mirror']['attribs']['ssl']);
}
} else {
$this->_channelInfo['servers']['mirror']['attribs']['ssl'] = 'yes';
}
$this->_isValid = false;
return true;
}
}
if ($ssl) {
$this->_channelInfo['servers']['primary']['attribs']['ssl'] = 'yes';
} else {
if (isset($this->_channelInfo['servers']['primary']['attribs']['ssl'])) {
unset($this->_channelInfo['servers']['primary']['attribs']['ssl']);
}
}
$this->_isValid = false;
return true;
}
/**
* @param string
* @return string|false
* @error PEAR_CHANNELFILE_ERROR_NO_SERVER
* @error PEAR_CHANNELFILE_ERROR_INVALID_SERVER
*/
function setServer($server, $mirror = false)
{
if (empty($server)) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SERVER);
return false;
} elseif (!$this->validChannelServer($server)) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
array('tag' => 'name', 'name' => $server));
return false;
}
if ($mirror) {
$found = false;
foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
if ($mirror == $mir['attribs']['host']) {
$found = true;
break;
}
}
if (!$found) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
array('mirror' => $mirror));
return false;
}
$this->_channelInfo['mirror'][$i]['attribs']['host'] = $server;
return true;
}
$this->_channelInfo['name'] = $server;
return true;
}
/**
* @param string
* @return boolean success
* @error PEAR_CHANNELFILE_ERROR_NO_SUMMARY
* @warning PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY
*/
function setSummary($summary)
{
if (empty($summary)) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_NO_SUMMARY);
return false;
} elseif (strpos(trim($summary), "\n") !== false) {
$this->_validateWarning(PEAR_CHANNELFILE_ERROR_MULTILINE_SUMMARY,
array('summary' => $summary));
}
$this->_channelInfo['summary'] = $summary;
return true;
}
/**
* @param string
* @param boolean determines whether the alias is in channel.xml or local
* @return boolean success
*/
function setAlias($alias, $local = false)
{
if (!$this->validChannelServer($alias)) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_INVALID_NAME,
array('tag' => 'suggestedalias', 'name' => $alias));
return false;
}
if ($local) {
$this->_channelInfo['localalias'] = $alias;
} else {
$this->_channelInfo['suggestedalias'] = $alias;
}
return true;
}
/**
* @return string
*/
function getAlias()
{
if (isset($this->_channelInfo['localalias'])) {
return $this->_channelInfo['localalias'];
}
if (isset($this->_channelInfo['suggestedalias'])) {
return $this->_channelInfo['suggestedalias'];
}
if (isset($this->_channelInfo['name'])) {
return $this->_channelInfo['name'];
}
return '';
}
/**
* Set the package validation object if it differs from PEAR's default
* The class must be includeable via changing _ in the classname to path separator,
* but no checking of this is made.
* @param string|false pass in false to reset to the default packagename regex
* @return boolean success
*/
function setValidationPackage($validateclass, $version)
{
if (empty($validateclass)) {
unset($this->_channelInfo['validatepackage']);
}
$this->_channelInfo['validatepackage'] = array('_content' => $validateclass);
$this->_channelInfo['validatepackage']['attribs'] = array('version' => $version);
}
/**
* Add a protocol to the provides section
* @param string protocol type
* @param string protocol version
* @param string protocol name, if any
* @param string mirror name, if this is a mirror's protocol
* @return bool
*/
function addFunction($type, $version, $name = '', $mirror = false)
{
if ($mirror) {
return $this->addMirrorFunction($mirror, $type, $version, $name);
}
$set = array('attribs' => array('version' => $version), '_content' => $name);
if (!isset($this->_channelInfo['servers']['primary'][$type]['function'])) {
if (!isset($this->_channelInfo['servers'])) {
$this->_channelInfo['servers'] = array('primary' =>
array($type => array()));
} elseif (!isset($this->_channelInfo['servers']['primary'])) {
$this->_channelInfo['servers']['primary'] = array($type => array());
}
$this->_channelInfo['servers']['primary'][$type]['function'] = $set;
$this->_isValid = false;
return true;
} elseif (!isset($this->_channelInfo['servers']['primary'][$type]['function'][0])) {
$this->_channelInfo['servers']['primary'][$type]['function'] = array(
$this->_channelInfo['servers']['primary'][$type]['function']);
}
$this->_channelInfo['servers']['primary'][$type]['function'][] = $set;
return true;
}
/**
* Add a protocol to a mirror's provides section
* @param string mirror name (server)
* @param string protocol type
* @param string protocol version
* @param string protocol name, if any
*/
function addMirrorFunction($mirror, $type, $version, $name = '')
{
if (!isset($this->_channelInfo['servers']['mirror'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
array('mirror' => $mirror));
return false;
}
$setmirror = false;
if (isset($this->_channelInfo['servers']['mirror'][0])) {
foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
if ($mirror == $mir['attribs']['host']) {
$setmirror = &$this->_channelInfo['servers']['mirror'][$i];
break;
}
}
} else {
if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
$setmirror = &$this->_channelInfo['servers']['mirror'];
}
}
if (!$setmirror) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
array('mirror' => $mirror));
return false;
}
$set = array('attribs' => array('version' => $version), '_content' => $name);
if (!isset($setmirror[$type]['function'])) {
$setmirror[$type]['function'] = $set;
$this->_isValid = false;
return true;
} elseif (!isset($setmirror[$type]['function'][0])) {
$setmirror[$type]['function'] = array($setmirror[$type]['function']);
}
$setmirror[$type]['function'][] = $set;
$this->_isValid = false;
return true;
}
/**
* @param string Resource Type this url links to
* @param string URL
* @param string|false mirror name, if this is not a primary server REST base URL
*/
function setBaseURL($resourceType, $url, $mirror = false)
{
if ($mirror) {
if (!isset($this->_channelInfo['servers']['mirror'])) {
$this->_validateError(PEAR_CHANNELFILE_ERROR_MIRROR_NOT_FOUND,
array('mirror' => $mirror));
return false;
}
$setmirror = false;
if (isset($this->_channelInfo['servers']['mirror'][0])) {
foreach ($this->_channelInfo['servers']['mirror'] as $i => $mir) {
if ($mirror == $mir['attribs']['host']) {
$setmirror = &$this->_channelInfo['servers']['mirror'][$i];
break;
}
}
} else {
if ($this->_channelInfo['servers']['mirror']['attribs']['host'] == $mirror) {
$setmirror = &$this->_channelInfo['servers']['mirror'];
}
}
} else {
$setmirror = &$this->_channelInfo['servers']['primary'];
}
$set = array('attribs' => array('type' => $resourceType), '_content' => $url);
if (!isset($setmirror['rest'])) {
$setmirror['rest'] = array();
}
if (!isset($setmirror['rest']['baseurl'])) {
$setmirror['rest']['baseurl'] = $set;
$this->_isValid = false;
return true;
} elseif (!isset($setmirror['rest']['baseurl'][0])) {
$setmirror['rest']['baseurl'] = array($setmirror['rest']['baseurl']);
}
foreach ($setmirror['rest']['baseurl'] as $i => $url) {
if ($url['attribs']['type'] == $resourceType) {
$this->_isValid = false;
$setmirror['rest']['baseurl'][$i] = $set;
return true;
}
}
$setmirror['rest']['baseurl'][] = $set;
$this->_isValid = false;
return true;
}
/**
* @param string mirror server
* @param int mirror http port
* @return boolean
*/
function addMirror($server, $port = null)
{
if ($this->_channelInfo['name'] == '__uri') {
return false; // the __uri channel cannot have mirrors by definition
}
$set = array('attribs' => array('host' => $server));
if (is_numeric($port)) {
$set['attribs']['port'] = $port;
}
if (!isset($this->_channelInfo['servers']['mirror'])) {
$this->_channelInfo['servers']['mirror'] = $set;
return true;
}
if (!isset($this->_channelInfo['servers']['mirror'][0])) {
$this->_channelInfo['servers']['mirror'] =
array($this->_channelInfo['servers']['mirror']);
}
$this->_channelInfo['servers']['mirror'][] = $set;
return true;
}
/**
* Retrieve the name of the validation package for this channel
* @return string|false
*/
function getValidationPackage()
{
if (!$this->_isValid && !$this->validate()) {
return false;
}
if (!isset($this->_channelInfo['validatepackage'])) {
return array('attribs' => array('version' => 'default'),
'_content' => 'PEAR_Validate');
}
return $this->_channelInfo['validatepackage'];
}
/**
* Retrieve the object that can be used for custom validation
* @param string|false the name of the package to validate. If the package is
* the channel validation package, PEAR_Validate is returned
* @return PEAR_Validate|false false is returned if the validation package
* cannot be located
*/
function &getValidationObject($package = false)
{
if (!class_exists('PEAR_Validate')) {
require_once 'PEAR/Validate.php';
}
if (!$this->_isValid) {
if (!$this->validate()) {
$a = false;
return $a;
}
}
if (isset($this->_channelInfo['validatepackage'])) {
if ($package == $this->_channelInfo['validatepackage']) {
// channel validation packages are always validated by PEAR_Validate
$val = new PEAR_Validate;
return $val;
}
if (!class_exists(str_replace('.', '_',
$this->_channelInfo['validatepackage']['_content']))) {
if ($this->isIncludeable(str_replace('_', '/',
$this->_channelInfo['validatepackage']['_content']) . '.php')) {
include_once str_replace('_', '/',
$this->_channelInfo['validatepackage']['_content']) . '.php';
$vclass = str_replace('.', '_',
$this->_channelInfo['validatepackage']['_content']);
$val = new $vclass;
} else {
$a = false;
return $a;
}
} else {
$vclass = str_replace('.', '_',
$this->_channelInfo['validatepackage']['_content']);
$val = new $vclass;
}
} else {
$val = new PEAR_Validate;
}
return $val;
}
function isIncludeable($path)
{
$possibilities = explode(PATH_SEPARATOR, ini_get('include_path'));
foreach ($possibilities as $dir) {
if (file_exists($dir . DIRECTORY_SEPARATOR . $path)
&& is_readable($dir . DIRECTORY_SEPARATOR . $path)) {
return true;
}
}
return false;
}
/**
* This function is used by the channel updater and retrieves a value set by
* the registry, or the current time if it has not been set
* @return string
*/
function lastModified()
{
if (isset($this->_channelInfo['_lastmodified'])) {
return $this->_channelInfo['_lastmodified'];
}
return time();
}
}
PK �]��X� � PEAR/Installer/Role.phpnu �[��� <?php
/**
* PEAR_Installer_Role
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* base class for installer roles
*/
require_once 'PEAR/Installer/Role/Common.php';
require_once 'PEAR/XMLParser.php';
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role
{
/**
* Set up any additional configuration variables that file roles require
*
* Never call this directly, it is called by the PEAR_Config constructor
* @param PEAR_Config
*/
public static function initializeConfig(&$config)
{
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
PEAR_Installer_Role::registerRoles();
}
foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $class => $info) {
if (!$info['config_vars']) {
continue;
}
$config->_addConfigVars($class, $info['config_vars']);
}
}
/**
* @param PEAR_PackageFile_v2
* @param string role name
* @param PEAR_Config
* @return PEAR_Installer_Role_Common
*/
public static function &factory($pkg, $role, &$config)
{
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
PEAR_Installer_Role::registerRoles();
}
if (!in_array($role, PEAR_Installer_Role::getValidRoles($pkg->getPackageType()))) {
$a = false;
return $a;
}
$a = 'PEAR_Installer_Role_' . ucfirst($role);
if (!class_exists($a)) {
require_once str_replace('_', '/', $a) . '.php';
}
$b = new $a($config);
return $b;
}
/**
* Get a list of file roles that are valid for the particular release type.
*
* For instance, src files serve no purpose in regular php releases.
* @param string
* @param bool clear cache
* @return array
*/
public static function getValidRoles($release, $clear = false)
{
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
PEAR_Installer_Role::registerRoles();
}
static $ret = array();
if ($clear) {
$ret = array();
}
if (isset($ret[$release])) {
return $ret[$release];
}
$ret[$release] = array();
foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
if (in_array($release, $okreleases['releasetypes'])) {
$ret[$release][] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
}
}
return $ret[$release];
}
/**
* Get a list of roles that require their files to be installed
*
* Most roles must be installed, but src and package roles, for instance
* are pseudo-roles. src files are compiled into a new extension. Package
* roles are actually fully bundled releases of a package
* @param bool clear cache
* @return array
*/
public static function getInstallableRoles($clear = false)
{
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
PEAR_Installer_Role::registerRoles();
}
static $ret;
if ($clear) {
unset($ret);
}
if (isset($ret)) {
return $ret;
}
$ret = array();
foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
if ($okreleases['installable']) {
$ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
}
}
return $ret;
}
/**
* Return an array of roles that are affected by the baseinstalldir attribute
*
* Most roles ignore this attribute, and instead install directly into:
* PackageName/filepath
* so a tests file tests/file.phpt is installed into PackageName/tests/filepath.php
* @param bool clear cache
* @return array
*/
public static function getBaseinstallRoles($clear = false)
{
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
PEAR_Installer_Role::registerRoles();
}
static $ret;
if ($clear) {
unset($ret);
}
if (isset($ret)) {
return $ret;
}
$ret = array();
foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
if ($okreleases['honorsbaseinstall']) {
$ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
}
}
return $ret;
}
/**
* Return an array of file roles that should be analyzed for PHP content at package time,
* like the "php" role.
* @param bool clear cache
* @return array
*/
public static function getPhpRoles($clear = false)
{
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'])) {
PEAR_Installer_Role::registerRoles();
}
static $ret;
if ($clear) {
unset($ret);
}
if (isset($ret)) {
return $ret;
}
$ret = array();
foreach ($GLOBALS['_PEAR_INSTALLER_ROLES'] as $role => $okreleases) {
if ($okreleases['phpfile']) {
$ret[] = strtolower(str_replace('PEAR_Installer_Role_', '', $role));
}
}
return $ret;
}
/**
* Scan through the Command directory looking for classes
* and see what commands they implement.
* @param string which directory to look for classes, defaults to
* the Installer/Roles subdirectory of
* the directory from where this file (__FILE__) is
* included.
*
* @return bool TRUE on success, a PEAR error on failure
*/
public static function registerRoles($dir = null)
{
$GLOBALS['_PEAR_INSTALLER_ROLES'] = array();
$parser = new PEAR_XMLParser;
if ($dir === null) {
$dir = dirname(__FILE__) . '/Role';
}
if (!file_exists($dir) || !is_dir($dir)) {
return PEAR::raiseError("registerRoles: opendir($dir) failed: does not exist/is not directory");
}
$dp = @opendir($dir);
if (empty($dp)) {
return PEAR::raiseError("registerRoles: opendir($dir) failed: $php_errmsg");
}
while ($entry = readdir($dp)) {
if ($entry[0] == '.' || substr($entry, -4) != '.xml') {
continue;
}
$class = "PEAR_Installer_Role_".substr($entry, 0, -4);
// List of roles
if (!isset($GLOBALS['_PEAR_INSTALLER_ROLES'][$class])) {
$file = "$dir/$entry";
$parser->parse(file_get_contents($file));
$data = $parser->getData();
if (!is_array($data['releasetypes'])) {
$data['releasetypes'] = array($data['releasetypes']);
}
$GLOBALS['_PEAR_INSTALLER_ROLES'][$class] = $data;
}
}
closedir($dp);
ksort($GLOBALS['_PEAR_INSTALLER_ROLES']);
PEAR_Installer_Role::getBaseinstallRoles(true);
PEAR_Installer_Role::getInstallableRoles(true);
PEAR_Installer_Role::getPhpRoles(true);
PEAR_Installer_Role::getValidRoles('****', true);
return true;
}
}PK �]���B B PEAR/Installer/Role/Ext.xmlnu �[��� <role version="1.0">
<releasetypes>extbin</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>ext_dir</locationconfig>
<honorsbaseinstall>1</honorsbaseinstall>
<unusualbaseinstall />
<phpfile />
<executable />
<phpextension>1</phpextension>
<config_vars />
</role>PK �]h&P*� � PEAR/Installer/Role/Doc.xmlnu �[��� <role version="1.0">
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>doc_dir</locationconfig>
<honorsbaseinstall />
<unusualbaseinstall />
<phpfile />
<executable />
<phpextension />
<config_vars />
</role>PK �]��/� � PEAR/Installer/Role/Cfg.xmlnu �[��� <role version="1.0">
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>cfg_dir</locationconfig>
<honorsbaseinstall />
<unusualbaseinstall>1</unusualbaseinstall>
<phpfile />
<executable />
<phpextension />
<config_vars />
</role>PK �]>l�
PEAR/Installer/Role/Php.phpnu �[��� <?php
/**
* PEAR_Installer_Role_Php
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Php extends PEAR_Installer_Role_Common {}
?>PK �]p��" " PEAR/Installer/Role/Src.xmlnu �[��� <role version="1.0">
<releasetypes>extsrc</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<installable>1</installable>
<locationconfig>temp_dir</locationconfig>
<honorsbaseinstall />
<unusualbaseinstall />
<phpfile />
<executable />
<phpextension />
<config_vars />
</role>PK �]ç
PEAR/Installer/Role/Doc.phpnu �[��� <?php
/**
* PEAR_Installer_Role_Doc
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Doc extends PEAR_Installer_Role_Common {}
?>PK �]3�]� PEAR/Installer/Role/Www.phpnu �[��� <?php
/**
* PEAR_Installer_Role_Www
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 2007-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.7.0
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 2007-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.7.0
*/
class PEAR_Installer_Role_Www extends PEAR_Installer_Role_Common {}
?>PK �]f�sz� � PEAR/Installer/Role/Data.xmlnu �[��� <role version="1.0">
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>data_dir</locationconfig>
<honorsbaseinstall />
<unusualbaseinstall />
<phpfile />
<executable />
<phpextension />
<config_vars />
</role>PK �]̊К
PEAR/Installer/Role/Ext.phpnu �[��� <?php
/**
* PEAR_Installer_Role_Ext
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Ext extends PEAR_Installer_Role_Common {}
?>PK �]�0�c� � PEAR/Installer/Role/Man.xmlnu �[��� <role version="1.0">
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>man_dir</locationconfig>
<honorsbaseinstall>1</honorsbaseinstall>
<unusualbaseinstall />
<phpfile />
<executable />
<phpextension />
<config_vars />
</role>
PK �]��P' PEAR/Installer/Role/Script.phpnu �[��� <?php
/**
* PEAR_Installer_Role_Script
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Script extends PEAR_Installer_Role_Common {}
?>PK �]<��( PEAR/Installer/Role/Cfg.phpnu �[��� <?php
/**
* PEAR_Installer_Role_Cfg
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 2007-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.7.0
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 2007-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.7.0
*/
class PEAR_Installer_Role_Cfg extends PEAR_Installer_Role_Common
{
/**
* @var PEAR_Installer
*/
var $installer;
/**
* the md5 of the original file
*
* @var unknown_type
*/
var $md5 = null;
/**
* Do any unusual setup here
* @param PEAR_Installer
* @param PEAR_PackageFile_v2
* @param array file attributes
* @param string file name
*/
function setup(&$installer, $pkg, $atts, $file)
{
$this->installer = &$installer;
$reg = &$this->installer->config->getRegistry();
$package = $reg->getPackage($pkg->getPackage(), $pkg->getChannel());
if ($package) {
$filelist = $package->getFilelist();
if (isset($filelist[$file]) && isset($filelist[$file]['md5sum'])) {
$this->md5 = $filelist[$file]['md5sum'];
}
}
}
function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null)
{
$test = parent::processInstallation($pkg, $atts, $file, $tmp_path, $layer);
if (@file_exists($test[2]) && @file_exists($test[3])) {
$md5 = md5_file($test[2]);
// configuration has already been installed, check for mods
if ($md5 !== $this->md5 && $md5 !== md5_file($test[3])) {
// configuration has been modified, so save our version as
// configfile-version
$old = $test[2];
$test[2] .= '.new-' . $pkg->getVersion();
// backup original and re-install it
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$tmpcfg = $this->config->get('temp_dir');
$newloc = System::mkdir(array('-p', $tmpcfg));
if (!$newloc) {
// try temp_dir
$newloc = System::mktemp(array('-d'));
if (!$newloc || PEAR::isError($newloc)) {
PEAR::popErrorHandling();
return PEAR::raiseError('Could not save existing configuration file '.
$old . ', unable to install. Please set temp_dir ' .
'configuration variable to a writeable location and try again');
}
} else {
$newloc = $tmpcfg;
}
$temp_file = $newloc . DIRECTORY_SEPARATOR . uniqid('savefile');
if (!@copy($old, $temp_file)) {
PEAR::popErrorHandling();
return PEAR::raiseError('Could not save existing configuration file '.
$old . ', unable to install. Please set temp_dir ' .
'configuration variable to a writeable location and try again');
}
PEAR::popErrorHandling();
$this->installer->log(0, "WARNING: configuration file $old is being installed as $test[2], you should manually merge in changes to the existing configuration file");
$this->installer->addFileOperation('rename', array($temp_file, $old, false));
$this->installer->addFileOperation('delete', array($temp_file));
}
}
return $test;
}
}PK �]@v�а � PEAR/Installer/Role/Script.xmlnu �[��� <role version="1.0">
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>bin_dir</locationconfig>
<honorsbaseinstall>1</honorsbaseinstall>
<unusualbaseinstall />
<phpfile />
<executable>1</executable>
<phpextension />
<config_vars />
</role>PK �]�(�G G PEAR/Installer/Role/Common.phpnu �[��� <?php
/**
* Base class for all installation roles.
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* Base class for all installation roles.
*
* This class allows extensibility of file roles. Packages with complex
* customization can now provide custom file roles along with the possibility of
* adding configuration values to match.
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Common
{
/**
* @var PEAR_Config
* @access protected
*/
var $config;
/**
* @param PEAR_Config
*/
function __construct(&$config)
{
$this->config = $config;
}
/**
* Retrieve configuration information about a file role from its XML info
*
* @param string $role Role Classname, as in "PEAR_Installer_Role_Data"
* @return array
*/
function getInfo($role)
{
if (empty($GLOBALS['_PEAR_INSTALLER_ROLES'][$role])) {
return PEAR::raiseError('Unknown Role class: "' . $role . '"');
}
return $GLOBALS['_PEAR_INSTALLER_ROLES'][$role];
}
/**
* This is called for each file to set up the directories and files
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @param array attributes from the <file> tag
* @param string file name
* @return array an array consisting of:
*
* 1 the original, pre-baseinstalldir installation directory
* 2 the final installation directory
* 3 the full path to the final location of the file
* 4 the location of the pre-installation file
*/
function processInstallation($pkg, $atts, $file, $tmp_path, $layer = null)
{
$roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' .
ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
if (PEAR::isError($roleInfo)) {
return $roleInfo;
}
if (!$roleInfo['locationconfig']) {
return false;
}
if ($roleInfo['honorsbaseinstall']) {
$dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'], $layer,
$pkg->getChannel());
if (!empty($atts['baseinstalldir'])) {
$dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
}
} elseif ($roleInfo['unusualbaseinstall']) {
$dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'],
$layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage();
if (!empty($atts['baseinstalldir'])) {
$dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
}
} else {
$dest_dir = $save_destdir = $this->config->get($roleInfo['locationconfig'],
$layer, $pkg->getChannel()) . DIRECTORY_SEPARATOR . $pkg->getPackage();
}
if (dirname($file) != '.' && empty($atts['install-as'])) {
$dest_dir .= DIRECTORY_SEPARATOR . dirname($file);
}
if (empty($atts['install-as'])) {
$dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file);
} else {
$dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as'];
}
$orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file;
// Clean up the DIRECTORY_SEPARATOR mess
$ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
list($dest_dir, $dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"),
array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR,
DIRECTORY_SEPARATOR),
array($dest_dir, $dest_file, $orig_file));
return array($save_destdir, $dest_dir, $dest_file, $orig_file);
}
/**
* Get the name of the configuration variable that specifies the location of this file
* @return string|false
*/
function getLocationConfig()
{
$roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' .
ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
if (PEAR::isError($roleInfo)) {
return $roleInfo;
}
return $roleInfo['locationconfig'];
}
/**
* Do any unusual setup here
* @param PEAR_Installer
* @param PEAR_PackageFile_v2
* @param array file attributes
* @param string file name
*/
function setup(&$installer, $pkg, $atts, $file)
{
}
function isExecutable()
{
$roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' .
ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
if (PEAR::isError($roleInfo)) {
return $roleInfo;
}
return $roleInfo['executable'];
}
function isInstallable()
{
$roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' .
ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
if (PEAR::isError($roleInfo)) {
return $roleInfo;
}
return $roleInfo['installable'];
}
function isExtension()
{
$roleInfo = PEAR_Installer_Role_Common::getInfo('PEAR_Installer_Role_' .
ucfirst(str_replace('pear_installer_role_', '', strtolower(get_class($this)))));
if (PEAR::isError($roleInfo)) {
return $roleInfo;
}
return $roleInfo['phpextension'];
}
}
?>
PK �]�r+k PEAR/Installer/Role/Data.phpnu �[��� <?php
/**
* PEAR_Installer_Role_Data
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Data extends PEAR_Installer_Role_Common {}
?>PK �]>1H�� � PEAR/Installer/Role/Www.xmlnu �[��� <role version="1.0">
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>www_dir</locationconfig>
<honorsbaseinstall>1</honorsbaseinstall>
<unusualbaseinstall />
<phpfile />
<executable />
<phpextension />
<config_vars />
</role>PK �]�iL� PEAR/Installer/Role/Test.phpnu �[��� <?php
/**
* PEAR_Installer_Role_Test
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Test extends PEAR_Installer_Role_Common {}
?>PK �]�X}�% % PEAR/Installer/Role/Man.phpnu �[��� <?php
/**
* PEAR_Installer_Role_Man
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Hannes Magnusson <bjori@php.net>
* @copyright 2011 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version SVN: $Id: $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.10.0
*/
/**
* @category pear
* @package PEAR
* @author Hannes Magnusson <bjori@php.net>
* @copyright 2011 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.10.0
*/
class PEAR_Installer_Role_Man extends PEAR_Installer_Role_Common {}
?>
PK �]z�q�� � PEAR/Installer/Role/Php.xmlnu �[��� <role version="1.0">
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>php_dir</locationconfig>
<honorsbaseinstall>1</honorsbaseinstall>
<unusualbaseinstall />
<phpfile>1</phpfile>
<executable />
<phpextension />
<config_vars />
</role>PK �]B] � � PEAR/Installer/Role/Test.xmlnu �[��� <role version="1.0">
<releasetypes>php</releasetypes>
<releasetypes>extsrc</releasetypes>
<releasetypes>extbin</releasetypes>
<releasetypes>zendextsrc</releasetypes>
<releasetypes>zendextbin</releasetypes>
<installable>1</installable>
<locationconfig>test_dir</locationconfig>
<honorsbaseinstall />
<unusualbaseinstall />
<phpfile />
<executable />
<phpextension />
<config_vars />
</role>PK �]ؗ�?r r PEAR/Installer/Role/Src.phpnu �[��� <?php
/**
* PEAR_Installer_Role_Src
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Installer_Role_Src extends PEAR_Installer_Role_Common
{
function setup(&$installer, $pkg, $atts, $file)
{
$installer->source_files++;
}
}
?>PK �]�x_��( �( PEAR/Registry.phpnu �[��� <?php
/**
* PEAR_Registry
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Tomas V. V. Cox <cox@idecnet.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* for PEAR_Error
*/
require_once 'PEAR.php';
require_once 'PEAR/DependencyDB.php';
define('PEAR_REGISTRY_ERROR_LOCK', -2);
define('PEAR_REGISTRY_ERROR_FORMAT', -3);
define('PEAR_REGISTRY_ERROR_FILE', -4);
define('PEAR_REGISTRY_ERROR_CONFLICT', -5);
define('PEAR_REGISTRY_ERROR_CHANNEL_FILE', -6);
/**
* Administration class used to maintain the installed package database.
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Tomas V. V. Cox <cox@idecnet.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Registry extends PEAR
{
/**
* File containing all channel information.
* @var string
*/
var $channels = '';
/** Directory where registry files are stored.
* @var string
*/
var $statedir = '';
/** File where the file map is stored
* @var string
*/
var $filemap = '';
/** Directory where registry files for channels are stored.
* @var string
*/
var $channelsdir = '';
/** Name of file used for locking the registry
* @var string
*/
var $lockfile = '';
/** File descriptor used during locking
* @var resource
*/
var $lock_fp = null;
/** Mode used during locking
* @var int
*/
var $lock_mode = 0; // XXX UNUSED
/** Cache of package information. Structure:
* array(
* 'package' => array('id' => ... ),
* ... )
* @var array
*/
var $pkginfo_cache = array();
/** Cache of file map. Structure:
* array( '/path/to/file' => 'package', ... )
* @var array
*/
var $filemap_cache = array();
/**
* @var false|PEAR_ChannelFile
*/
var $_pearChannel;
/**
* @var false|PEAR_ChannelFile
*/
var $_peclChannel;
/**
* @var false|PEAR_ChannelFile
*/
var $_docChannel;
/**
* @var PEAR_DependencyDB
*/
var $_dependencyDB;
/**
* @var PEAR_Config
*/
var $_config;
/**
* PEAR_Registry constructor.
*
* @param string (optional) PEAR install directory (for .php files)
* @param PEAR_ChannelFile PEAR_ChannelFile object representing the PEAR channel, if
* default values are not desired. Only used the very first time a PEAR
* repository is initialized
* @param PEAR_ChannelFile PEAR_ChannelFile object representing the PECL channel, if
* default values are not desired. Only used the very first time a PEAR
* repository is initialized
*
* @access public
*/
function __construct($pear_install_dir = PEAR_INSTALL_DIR, $pear_channel = false,
$pecl_channel = false, $pear_metadata_dir = '')
{
parent::__construct();
$this->setInstallDir($pear_install_dir, $pear_metadata_dir);
$this->_pearChannel = $pear_channel;
$this->_peclChannel = $pecl_channel;
$this->_config = false;
}
function setInstallDir($pear_install_dir = PEAR_INSTALL_DIR, $pear_metadata_dir = '')
{
$ds = DIRECTORY_SEPARATOR;
$this->install_dir = $pear_install_dir;
if (!$pear_metadata_dir) {
$pear_metadata_dir = $pear_install_dir;
}
$this->channelsdir = $pear_metadata_dir.$ds.'.channels';
$this->statedir = $pear_metadata_dir.$ds.'.registry';
$this->filemap = $pear_metadata_dir.$ds.'.filemap';
$this->lockfile = $pear_metadata_dir.$ds.'.lock';
}
function hasWriteAccess()
{
if (!file_exists($this->install_dir)) {
$dir = $this->install_dir;
while ($dir && $dir != '.') {
$olddir = $dir;
$dir = dirname($dir);
if ($dir != '.' && file_exists($dir)) {
if (is_writeable($dir)) {
return true;
}
return false;
}
if ($dir == $olddir) { // this can happen in safe mode
return @is_writable($dir);
}
}
return false;
}
return is_writeable($this->install_dir);
}
function setConfig(&$config, $resetInstallDir = true)
{
$this->_config = &$config;
if ($resetInstallDir) {
$this->setInstallDir($config->get('php_dir'), $config->get('metadata_dir'));
}
}
function _initializeChannelDirs()
{
static $running = false;
if (!$running) {
$running = true;
$ds = DIRECTORY_SEPARATOR;
if (!is_dir($this->channelsdir) ||
!file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
!file_exists($this->channelsdir . $ds . 'doc.php.net.reg') ||
!file_exists($this->channelsdir . $ds . '__uri.reg')) {
if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
$pear_channel = $this->_pearChannel;
if (!is_a($pear_channel, 'PEAR_ChannelFile') || !$pear_channel->validate()) {
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$pear_channel = new PEAR_ChannelFile;
$pear_channel->setAlias('pear');
$pear_channel->setServer('pear.php.net');
$pear_channel->setSummary('PHP Extension and Application Repository');
$pear_channel->setDefaultPEARProtocols();
$pear_channel->setBaseURL('REST1.0', 'https://pear.php.net/rest/');
$pear_channel->setBaseURL('REST1.1', 'https://pear.php.net/rest/');
$pear_channel->setBaseURL('REST1.3', 'https://pear.php.net/rest/');
//$pear_channel->setBaseURL('REST1.4', 'https://pear.php.net/rest/');
} else {
$pear_channel->setServer('pear.php.net');
$pear_channel->setAlias('pear');
}
$pear_channel->validate();
$this->_addChannel($pear_channel);
}
if (!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg')) {
$pecl_channel = $this->_peclChannel;
if (!is_a($pecl_channel, 'PEAR_ChannelFile') || !$pecl_channel->validate()) {
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$pecl_channel = new PEAR_ChannelFile;
$pecl_channel->setAlias('pecl');
$pecl_channel->setServer('pecl.php.net');
$pecl_channel->setSummary('PHP Extension Community Library');
$pecl_channel->setDefaultPEARProtocols();
$pecl_channel->setBaseURL('REST1.0', 'https://pecl.php.net/rest/');
$pecl_channel->setBaseURL('REST1.1', 'https://pecl.php.net/rest/');
$pecl_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
} else {
$pecl_channel->setServer('pecl.php.net');
$pecl_channel->setAlias('pecl');
}
$pecl_channel->validate();
$this->_addChannel($pecl_channel);
}
if (!file_exists($this->channelsdir . $ds . 'doc.php.net.reg')) {
$doc_channel = $this->_docChannel;
if (!is_a($doc_channel, 'PEAR_ChannelFile') || !$doc_channel->validate()) {
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$doc_channel = new PEAR_ChannelFile;
$doc_channel->setAlias('phpdocs');
$doc_channel->setServer('doc.php.net');
$doc_channel->setSummary('PHP Documentation Team');
$doc_channel->setDefaultPEARProtocols();
$doc_channel->setBaseURL('REST1.0', 'https://doc.php.net/rest/');
$doc_channel->setBaseURL('REST1.1', 'https://doc.php.net/rest/');
$doc_channel->setBaseURL('REST1.3', 'https://doc.php.net/rest/');
} else {
$doc_channel->setServer('doc.php.net');
$doc_channel->setAlias('doc');
}
$doc_channel->validate();
$this->_addChannel($doc_channel);
}
if (!file_exists($this->channelsdir . $ds . '__uri.reg')) {
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$private = new PEAR_ChannelFile;
$private->setName('__uri');
$private->setDefaultPEARProtocols();
$private->setBaseURL('REST1.0', '****');
$private->setSummary('Pseudo-channel for static packages');
$this->_addChannel($private);
}
$this->_rebuildFileMap();
}
$running = false;
}
}
function _initializeDirs()
{
$ds = DIRECTORY_SEPARATOR;
// XXX Compatibility code should be removed in the future
// rename all registry files if any to lowercase
if (!OS_WINDOWS && file_exists($this->statedir) && is_dir($this->statedir) &&
$handle = opendir($this->statedir)) {
$dest = $this->statedir . $ds;
while (false !== ($file = readdir($handle))) {
if (preg_match('/^.*[A-Z].*\.reg\\z/', $file)) {
rename($dest . $file, $dest . strtolower($file));
}
}
closedir($handle);
}
$this->_initializeChannelDirs();
if (!file_exists($this->filemap)) {
$this->_rebuildFileMap();
}
$this->_initializeDepDB();
}
function _initializeDepDB()
{
if (!isset($this->_dependencyDB)) {
static $initializing = false;
if (!$initializing) {
$initializing = true;
if (!$this->_config) { // never used?
$file = OS_WINDOWS ? 'pear.ini' : '.pearrc';
$this->_config = new PEAR_Config($this->statedir . DIRECTORY_SEPARATOR .
$file);
$this->_config->setRegistry($this);
$this->_config->set('php_dir', $this->install_dir);
}
$this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
if (PEAR::isError($this->_dependencyDB)) {
// attempt to recover by removing the dep db
if (file_exists($this->_config->get('metadata_dir', null, 'pear.php.net') .
DIRECTORY_SEPARATOR . '.depdb')) {
@unlink($this->_config->get('metadata_dir', null, 'pear.php.net') .
DIRECTORY_SEPARATOR . '.depdb');
}
$this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config);
if (PEAR::isError($this->_dependencyDB)) {
echo $this->_dependencyDB->getMessage();
echo 'Unrecoverable error';
exit(1);
}
}
$initializing = false;
}
}
}
/**
* PEAR_Registry destructor. Makes sure no locks are forgotten.
*
* @access private
*/
function _PEAR_Registry()
{
parent::_PEAR();
if (is_resource($this->lock_fp)) {
$this->_unlock();
}
}
/**
* Make sure the directory where we keep registry files exists.
*
* @return bool TRUE if directory exists, FALSE if it could not be
* created
*
* @access private
*/
function _assertStateDir($channel = false)
{
if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
return $this->_assertChannelStateDir($channel);
}
static $init = false;
if (!file_exists($this->statedir)) {
if (!$this->hasWriteAccess()) {
return false;
}
require_once 'System.php';
if (!System::mkdir(array('-p', $this->statedir))) {
return $this->raiseError("could not create directory '{$this->statedir}'");
}
$init = true;
} elseif (!is_dir($this->statedir)) {
return $this->raiseError('Cannot create directory ' . $this->statedir . ', ' .
'it already exists and is not a directory');
}
$ds = DIRECTORY_SEPARATOR;
if (!file_exists($this->channelsdir)) {
if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg') ||
!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') ||
!file_exists($this->channelsdir . $ds . 'doc.php.net.reg') ||
!file_exists($this->channelsdir . $ds . '__uri.reg')) {
$init = true;
}
} elseif (!is_dir($this->channelsdir)) {
return $this->raiseError('Cannot create directory ' . $this->channelsdir . ', ' .
'it already exists and is not a directory');
}
if ($init) {
static $running = false;
if (!$running) {
$running = true;
$this->_initializeDirs();
$running = false;
$init = false;
}
} else {
$this->_initializeDepDB();
}
return true;
}
/**
* Make sure the directory where we keep registry files exists for a non-standard channel.
*
* @param string channel name
* @return bool TRUE if directory exists, FALSE if it could not be
* created
*
* @access private
*/
function _assertChannelStateDir($channel)
{
$ds = DIRECTORY_SEPARATOR;
if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
$this->_initializeChannelDirs();
}
return $this->_assertStateDir($channel);
}
$channelDir = $this->_channelDirectoryName($channel);
if (!is_dir($this->channelsdir) ||
!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) {
$this->_initializeChannelDirs();
}
if (!file_exists($channelDir)) {
if (!$this->hasWriteAccess()) {
return false;
}
require_once 'System.php';
if (!System::mkdir(array('-p', $channelDir))) {
return $this->raiseError("could not create directory '" . $channelDir .
"'");
}
} elseif (!is_dir($channelDir)) {
return $this->raiseError("could not create directory '" . $channelDir .
"', already exists and is not a directory");
}
return true;
}
/**
* Make sure the directory where we keep registry files for channels exists
*
* @return bool TRUE if directory exists, FALSE if it could not be
* created
*
* @access private
*/
function _assertChannelDir()
{
if (!file_exists($this->channelsdir)) {
if (!$this->hasWriteAccess()) {
return false;
}
require_once 'System.php';
if (!System::mkdir(array('-p', $this->channelsdir))) {
return $this->raiseError("could not create directory '{$this->channelsdir}'");
}
} elseif (!is_dir($this->channelsdir)) {
return $this->raiseError("could not create directory '{$this->channelsdir}" .
"', it already exists and is not a directory");
}
if (!file_exists($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
if (!$this->hasWriteAccess()) {
return false;
}
require_once 'System.php';
if (!System::mkdir(array('-p', $this->channelsdir . DIRECTORY_SEPARATOR . '.alias'))) {
return $this->raiseError("could not create directory '{$this->channelsdir}/.alias'");
}
} elseif (!is_dir($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) {
return $this->raiseError("could not create directory '{$this->channelsdir}" .
"/.alias', it already exists and is not a directory");
}
return true;
}
/**
* Get the name of the file where data for a given package is stored.
*
* @param string channel name, or false if this is a PEAR package
* @param string package name
*
* @return string registry file name
*
* @access public
*/
function _packageFileName($package, $channel = false)
{
if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
return $this->_channelDirectoryName($channel) . DIRECTORY_SEPARATOR .
strtolower($package) . '.reg';
}
return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg';
}
/**
* Get the name of the file where data for a given channel is stored.
* @param string channel name
* @return string registry file name
*/
function _channelFileName($channel, $noaliases = false)
{
if (!$noaliases) {
if (file_exists($this->_getChannelAliasFileName($channel))) {
$channel = implode('', file($this->_getChannelAliasFileName($channel)));
}
}
return $this->channelsdir . DIRECTORY_SEPARATOR . str_replace('/', '_',
strtolower($channel)) . '.reg';
}
/**
* @param string
* @return string
*/
function _getChannelAliasFileName($alias)
{
return $this->channelsdir . DIRECTORY_SEPARATOR . '.alias' .
DIRECTORY_SEPARATOR . str_replace('/', '_', strtolower($alias)) . '.txt';
}
/**
* Get the name of a channel from its alias
*/
function _getChannelFromAlias($channel)
{
if (!$this->_channelExists($channel)) {
if ($channel == 'pear.php.net') {
return 'pear.php.net';
}
if ($channel == 'pecl.php.net') {
return 'pecl.php.net';
}
if ($channel == 'doc.php.net') {
return 'doc.php.net';
}
if ($channel == '__uri') {
return '__uri';
}
return false;
}
$channel = strtolower($channel);
if (file_exists($this->_getChannelAliasFileName($channel))) {
// translate an alias to an actual channel
return implode('', file($this->_getChannelAliasFileName($channel)));
}
return $channel;
}
/**
* Get the alias of a channel from its alias or its name
*/
function _getAlias($channel)
{
if (!$this->_channelExists($channel)) {
if ($channel == 'pear.php.net') {
return 'pear';
}
if ($channel == 'pecl.php.net') {
return 'pecl';
}
if ($channel == 'doc.php.net') {
return 'phpdocs';
}
return false;
}
$channel = $this->_getChannel($channel);
if (PEAR::isError($channel)) {
return $channel;
}
return $channel->getAlias();
}
/**
* Get the name of the file where data for a given package is stored.
*
* @param string channel name, or false if this is a PEAR package
* @param string package name
*
* @return string registry file name
*
* @access public
*/
function _channelDirectoryName($channel)
{
if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
return $this->statedir;
}
$ch = $this->_getChannelFromAlias($channel);
if (!$ch) {
$ch = $channel;
}
return $this->statedir . DIRECTORY_SEPARATOR . strtolower('.channel.' .
str_replace('/', '_', $ch));
}
function _openPackageFile($package, $mode, $channel = false)
{
if (!$this->_assertStateDir($channel)) {
return null;
}
if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
return null;
}
$file = $this->_packageFileName($package, $channel);
if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
return null;
}
$fp = @fopen($file, $mode);
if (!$fp) {
return null;
}
return $fp;
}
function _closePackageFile($fp)
{
fclose($fp);
}
function _openChannelFile($channel, $mode)
{
if (!$this->_assertChannelDir()) {
return null;
}
if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) {
return null;
}
$file = $this->_channelFileName($channel);
if (!file_exists($file) && $mode == 'r' || $mode == 'rb') {
return null;
}
$fp = @fopen($file, $mode);
if (!$fp) {
return null;
}
return $fp;
}
function _closeChannelFile($fp)
{
fclose($fp);
}
function _rebuildFileMap()
{
if (!class_exists('PEAR_Installer_Role')) {
require_once 'PEAR/Installer/Role.php';
}
$channels = $this->_listAllPackages();
$files = array();
foreach ($channels as $channel => $packages) {
foreach ($packages as $package) {
$version = $this->_packageInfo($package, 'version', $channel);
$filelist = $this->_packageInfo($package, 'filelist', $channel);
if (!is_array($filelist)) {
continue;
}
foreach ($filelist as $name => $attrs) {
if (isset($attrs['attribs'])) {
$attrs = $attrs['attribs'];
}
// it is possible for conflicting packages in different channels to
// conflict with data files/doc files
if ($name == 'dirtree') {
continue;
}
if (isset($attrs['role']) && !in_array($attrs['role'],
PEAR_Installer_Role::getInstallableRoles())) {
// these are not installed
continue;
}
if (isset($attrs['role']) && !in_array($attrs['role'],
PEAR_Installer_Role::getBaseinstallRoles())) {
$attrs['baseinstalldir'] = $package;
}
if (isset($attrs['baseinstalldir'])) {
$file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name;
} else {
$file = $name;
}
$file = preg_replace(',^/+,', '', $file);
if ($channel != 'pear.php.net') {
if (!isset($files[$attrs['role']])) {
$files[$attrs['role']] = array();
}
$files[$attrs['role']][$file] = array(strtolower($channel),
strtolower($package));
} else {
if (!isset($files[$attrs['role']])) {
$files[$attrs['role']] = array();
}
$files[$attrs['role']][$file] = strtolower($package);
}
}
}
}
$this->_assertStateDir();
if (!$this->hasWriteAccess()) {
return false;
}
$fp = @fopen($this->filemap, 'wb');
if (!$fp) {
return false;
}
$this->filemap_cache = $files;
fwrite($fp, serialize($files));
fclose($fp);
return true;
}
function _readFileMap()
{
if (!file_exists($this->filemap)) {
return array();
}
$fp = @fopen($this->filemap, 'r');
if (!$fp) {
$last_errormsg = '';
$last_error = error_get_last();
if (!empty($last_error['message'])) {
$last_errormsg = $last_error['message'];
}
return $this->raiseError('PEAR_Registry: could not open filemap "' . $this->filemap . '"', PEAR_REGISTRY_ERROR_FILE, null, null, $last_errormsg);
}
clearstatcache();
$fsize = filesize($this->filemap);
fclose($fp);
$data = file_get_contents($this->filemap);
$tmp = unserialize($data);
if (!$tmp && $fsize > 7) {
return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data);
}
$this->filemap_cache = $tmp;
return true;
}
/**
* Lock the registry.
*
* @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN.
* See flock manual for more information.
*
* @return bool TRUE on success, FALSE if locking failed, or a
* PEAR error if some other error occurs (such as the
* lock file not being writable).
*
* @access private
*/
function _lock($mode = LOCK_EX)
{
if (stristr(php_uname(), 'Windows 9')) {
return true;
}
if ($mode != LOCK_UN && is_resource($this->lock_fp)) {
// XXX does not check type of lock (LOCK_SH/LOCK_EX)
return true;
}
if (!$this->_assertStateDir()) {
if ($mode == LOCK_EX) {
return $this->raiseError('Registry directory is not writeable by the current user');
}
return true;
}
$open_mode = 'w';
// XXX People reported problems with LOCK_SH and 'w'
if ($mode === LOCK_SH || $mode === LOCK_UN) {
if (!file_exists($this->lockfile)) {
touch($this->lockfile);
}
$open_mode = 'r';
}
if (!is_resource($this->lock_fp)) {
$this->lock_fp = @fopen($this->lockfile, $open_mode);
}
if (!is_resource($this->lock_fp)) {
$this->lock_fp = null;
return $this->raiseError("could not create lock file" .
(isset($php_errormsg) ? ": " . $php_errormsg : ""));
}
if (!(int)flock($this->lock_fp, $mode)) {
switch ($mode) {
case LOCK_SH: $str = 'shared'; break;
case LOCK_EX: $str = 'exclusive'; break;
case LOCK_UN: $str = 'unlock'; break;
default: $str = 'unknown'; break;
}
//is resource at this point, close it on error.
fclose($this->lock_fp);
$this->lock_fp = null;
return $this->raiseError("could not acquire $str lock ($this->lockfile)",
PEAR_REGISTRY_ERROR_LOCK);
}
return true;
}
function _unlock()
{
$ret = $this->_lock(LOCK_UN);
if (is_resource($this->lock_fp)) {
fclose($this->lock_fp);
}
$this->lock_fp = null;
return $ret;
}
function _packageExists($package, $channel = false)
{
return file_exists($this->_packageFileName($package, $channel));
}
/**
* Determine whether a channel exists in the registry
*
* @param string Channel name
* @param bool if true, then aliases will be ignored
* @return boolean
*/
function _channelExists($channel, $noaliases = false)
{
$a = file_exists($this->_channelFileName($channel, $noaliases));
if (!$a && $channel == 'pear.php.net') {
return true;
}
if (!$a && $channel == 'pecl.php.net') {
return true;
}
if (!$a && $channel == 'doc.php.net') {
return true;
}
return $a;
}
/**
* Determine whether a mirror exists within the default channel in the registry
*
* @param string Channel name
* @param string Mirror name
*
* @return boolean
*/
function _mirrorExists($channel, $mirror)
{
$data = $this->_channelInfo($channel);
if (!isset($data['servers']['mirror'])) {
return false;
}
foreach ($data['servers']['mirror'] as $m) {
if ($m['attribs']['host'] == $mirror) {
return true;
}
}
return false;
}
/**
* @param PEAR_ChannelFile Channel object
* @param donotuse
* @param string Last-Modified HTTP tag from remote request
* @return boolean|PEAR_Error True on creation, false if it already exists
*/
function _addChannel($channel, $update = false, $lastmodified = false)
{
if (!is_a($channel, 'PEAR_ChannelFile')) {
return false;
}
if (!$channel->validate()) {
return false;
}
if (file_exists($this->_channelFileName($channel->getName()))) {
if (!$update) {
return false;
}
$checker = $this->_getChannel($channel->getName());
if (PEAR::isError($checker)) {
return $checker;
}
if ($channel->getAlias() != $checker->getAlias()) {
if (file_exists($this->_getChannelAliasFileName($checker->getAlias()))) {
@unlink($this->_getChannelAliasFileName($checker->getAlias()));
}
}
} else {
if ($update && !in_array($channel->getName(), array('pear.php.net', 'pecl.php.net', 'doc.php.net'))) {
return false;
}
}
$ret = $this->_assertChannelDir();
if (PEAR::isError($ret)) {
return $ret;
}
$ret = $this->_assertChannelStateDir($channel->getName());
if (PEAR::isError($ret)) {
return $ret;
}
if ($channel->getAlias() != $channel->getName()) {
if (file_exists($this->_getChannelAliasFileName($channel->getAlias())) &&
$this->_getChannelFromAlias($channel->getAlias()) != $channel->getName()) {
$channel->setAlias($channel->getName());
}
if (!$this->hasWriteAccess()) {
return false;
}
$fp = @fopen($this->_getChannelAliasFileName($channel->getAlias()), 'w');
if (!$fp) {
return false;
}
fwrite($fp, $channel->getName());
fclose($fp);
}
if (!$this->hasWriteAccess()) {
return false;
}
$fp = @fopen($this->_channelFileName($channel->getName()), 'wb');
if (!$fp) {
return false;
}
$info = $channel->toArray();
if ($lastmodified) {
$info['_lastmodified'] = $lastmodified;
} else {
$info['_lastmodified'] = self::getSourceDateEpoch();
}
fwrite($fp, serialize($info));
fclose($fp);
return true;
}
/**
* Deletion fails if there are any packages installed from the channel
* @param string|PEAR_ChannelFile channel name
* @return boolean|PEAR_Error True on deletion, false if it doesn't exist
*/
function _deleteChannel($channel)
{
if (!is_string($channel)) {
if (!is_a($channel, 'PEAR_ChannelFile')) {
return false;
}
if (!$channel->validate()) {
return false;
}
$channel = $channel->getName();
}
if ($this->_getChannelFromAlias($channel) == '__uri') {
return false;
}
if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
return false;
}
if ($this->_getChannelFromAlias($channel) == 'doc.php.net') {
return false;
}
if (!$this->_channelExists($channel)) {
return false;
}
if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') {
return false;
}
$channel = $this->_getChannelFromAlias($channel);
if ($channel == 'pear.php.net') {
return false;
}
$test = $this->_listChannelPackages($channel);
if (count($test)) {
return false;
}
$test = @rmdir($this->_channelDirectoryName($channel));
if (!$test) {
return false;
}
$file = $this->_getChannelAliasFileName($this->_getAlias($channel));
if (file_exists($file)) {
$test = @unlink($file);
if (!$test) {
return false;
}
}
$file = $this->_channelFileName($channel);
$ret = true;
if (file_exists($file)) {
$ret = @unlink($file);
}
return $ret;
}
/**
* Determine whether a channel exists in the registry
* @param string Channel Alias
* @return boolean
*/
function _isChannelAlias($alias)
{
return file_exists($this->_getChannelAliasFileName($alias));
}
/**
* @param string|null
* @param string|null
* @param string|null
* @return array|null
* @access private
*/
function _packageInfo($package = null, $key = null, $channel = 'pear.php.net')
{
if ($package === null) {
if ($channel === null) {
$channels = $this->_listChannels();
$ret = array();
foreach ($channels as $channel) {
$channel = strtolower($channel);
$ret[$channel] = array();
$packages = $this->_listPackages($channel);
foreach ($packages as $package) {
$ret[$channel][] = $this->_packageInfo($package, null, $channel);
}
}
return $ret;
}
$ps = $this->_listPackages($channel);
if (!count($ps)) {
return array();
}
return array_map(array(&$this, '_packageInfo'),
$ps, array_fill(0, count($ps), null),
array_fill(0, count($ps), $channel));
}
$fp = $this->_openPackageFile($package, 'r', $channel);
if ($fp === null) {
return null;
}
clearstatcache();
$this->_closePackageFile($fp);
$data = file_get_contents($this->_packageFileName($package, $channel));
$data = @unserialize($data);
if ($key === null) {
return $data;
}
// compatibility for package.xml version 2.0
if (isset($data['old'][$key])) {
return $data['old'][$key];
}
if (isset($data[$key])) {
return $data[$key];
}
return null;
}
/**
* @param string Channel name
* @param bool whether to strictly retrieve info of channels, not just aliases
* @return array|null
*/
function _channelInfo($channel, $noaliases = false)
{
if (!$this->_channelExists($channel, $noaliases)) {
return null;
}
$fp = $this->_openChannelFile($channel, 'r');
if ($fp === null) {
return null;
}
clearstatcache();
$this->_closeChannelFile($fp);
$data = file_get_contents($this->_channelFileName($channel));
$data = unserialize($data);
return $data;
}
function _listChannels()
{
$channellist = array();
if (!file_exists($this->channelsdir) || !is_dir($this->channelsdir)) {
return array('pear.php.net', 'pecl.php.net', 'doc.php.net', '__uri');
}
$dp = opendir($this->channelsdir);
while ($ent = readdir($dp)) {
if ($ent[0] == '.' || substr($ent, -4) != '.reg') {
continue;
}
if ($ent == '__uri.reg') {
$channellist[] = '__uri';
continue;
}
$channellist[] = str_replace('_', '/', substr($ent, 0, -4));
}
closedir($dp);
if (!in_array('pear.php.net', $channellist)) {
$channellist[] = 'pear.php.net';
}
if (!in_array('pecl.php.net', $channellist)) {
$channellist[] = 'pecl.php.net';
}
if (!in_array('doc.php.net', $channellist)) {
$channellist[] = 'doc.php.net';
}
if (!in_array('__uri', $channellist)) {
$channellist[] = '__uri';
}
natsort($channellist);
return $channellist;
}
function _listPackages($channel = false)
{
if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') {
return $this->_listChannelPackages($channel);
}
if (!file_exists($this->statedir) || !is_dir($this->statedir)) {
return array();
}
$pkglist = array();
$dp = opendir($this->statedir);
if (!$dp) {
return $pkglist;
}
while ($ent = readdir($dp)) {
if ($ent[0] == '.' || substr($ent, -4) != '.reg') {
continue;
}
$pkglist[] = substr($ent, 0, -4);
}
closedir($dp);
sort($pkglist);
return $pkglist;
}
function _listChannelPackages($channel)
{
$pkglist = array();
if (!file_exists($this->_channelDirectoryName($channel)) ||
!is_dir($this->_channelDirectoryName($channel))) {
return array();
}
$dp = opendir($this->_channelDirectoryName($channel));
if (!$dp) {
return $pkglist;
}
while ($ent = readdir($dp)) {
if ($ent[0] == '.' || substr($ent, -4) != '.reg') {
continue;
}
$pkglist[] = substr($ent, 0, -4);
}
closedir($dp);
return $pkglist;
}
function _listAllPackages()
{
$ret = array();
foreach ($this->_listChannels() as $channel) {
$ret[$channel] = $this->_listPackages($channel);
}
return $ret;
}
/**
* Add an installed package to the registry
* @param string package name
* @param array package info (parsed by PEAR_Common::infoFrom*() methods)
* @return bool success of saving
* @access private
*/
function _addPackage($package, $info)
{
if ($this->_packageExists($package)) {
return false;
}
$fp = $this->_openPackageFile($package, 'wb');
if ($fp === null) {
return false;
}
$info['_lastmodified'] = self::getSourceDateEpoch();
fwrite($fp, serialize($info));
$this->_closePackageFile($fp);
if (isset($info['filelist'])) {
$this->_rebuildFileMap();
}
return true;
}
/**
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @return bool
* @access private
*/
function _addPackage2($info)
{
if (!is_a($info, 'PEAR_PackageFile_v1') && !is_a($info, 'PEAR_PackageFile_v2')) {
return false;
}
if (!$info->validate()) {
if (class_exists('PEAR_Common')) {
$ui = PEAR_Frontend::singleton();
if ($ui) {
foreach ($info->getValidationWarnings() as $err) {
$ui->log($err['message'], true);
}
}
}
return false;
}
$channel = $info->getChannel();
$package = $info->getPackage();
$save = $info;
if ($this->_packageExists($package, $channel)) {
return false;
}
if (!$this->_channelExists($channel, true)) {
return false;
}
$info = $info->toArray(true);
if (!$info) {
return false;
}
$fp = $this->_openPackageFile($package, 'wb', $channel);
if ($fp === null) {
return false;
}
$info['_lastmodified'] = self::getSourceDateEpoch();
fwrite($fp, serialize($info));
$this->_closePackageFile($fp);
$this->_rebuildFileMap();
return true;
}
/**
* @param string Package name
* @param array parsed package.xml 1.0
* @param bool this parameter is only here for BC. Don't use it.
* @access private
*/
function _updatePackage($package, $info, $merge = true)
{
$oldinfo = $this->_packageInfo($package);
if (empty($oldinfo)) {
return false;
}
$fp = $this->_openPackageFile($package, 'w');
if ($fp === null) {
return false;
}
if (is_object($info)) {
$info = $info->toArray();
}
$info['_lastmodified'] = self::getSourceDateEpoch();
$newinfo = $info;
if ($merge) {
$info = array_merge($oldinfo, $info);
} else {
$diff = $info;
}
fwrite($fp, serialize($info));
$this->_closePackageFile($fp);
if (isset($newinfo['filelist'])) {
$this->_rebuildFileMap();
}
return true;
}
/**
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @return bool
* @access private
*/
function _updatePackage2($info)
{
if (!$this->_packageExists($info->getPackage(), $info->getChannel())) {
return false;
}
$fp = $this->_openPackageFile($info->getPackage(), 'w', $info->getChannel());
if ($fp === null) {
return false;
}
$save = $info;
$info = $save->getArray(true);
$info['_lastmodified'] = self::getSourceDateEpoch();
fwrite($fp, serialize($info));
$this->_closePackageFile($fp);
$this->_rebuildFileMap();
return true;
}
/**
* @param string Package name
* @param string Channel name
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
* @access private
*/
function &_getPackage($package, $channel = 'pear.php.net')
{
$info = $this->_packageInfo($package, null, $channel);
if ($info === null) {
return $info;
}
$a = $this->_config;
if (!$a) {
$this->_config = new PEAR_Config;
$this->_config->set('php_dir', $this->statedir);
}
if (!class_exists('PEAR_PackageFile')) {
require_once 'PEAR/PackageFile.php';
}
$pkg = new PEAR_PackageFile($this->_config);
$pf = &$pkg->fromArray($info);
return $pf;
}
/**
* @param string channel name
* @param bool whether to strictly retrieve channel names
* @return PEAR_ChannelFile|PEAR_Error
* @access private
*/
function &_getChannel($channel, $noaliases = false)
{
$ch = false;
if ($this->_channelExists($channel, $noaliases)) {
$chinfo = $this->_channelInfo($channel, $noaliases);
if ($chinfo) {
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$ch = &PEAR_ChannelFile::fromArrayWithErrors($chinfo);
}
}
if ($ch) {
if ($ch->validate()) {
return $ch;
}
foreach ($ch->getErrors(true) as $err) {
$message = $err['message'] . "\n";
}
$ch = PEAR::raiseError($message);
return $ch;
}
if ($this->_getChannelFromAlias($channel) == 'pear.php.net') {
// the registry is not properly set up, so use defaults
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$pear_channel = new PEAR_ChannelFile;
$pear_channel->setServer('pear.php.net');
$pear_channel->setAlias('pear');
$pear_channel->setSummary('PHP Extension and Application Repository');
$pear_channel->setDefaultPEARProtocols();
$pear_channel->setBaseURL('REST1.0', 'https://pear.php.net/rest/');
$pear_channel->setBaseURL('REST1.1', 'https://pear.php.net/rest/');
$pear_channel->setBaseURL('REST1.3', 'https://pear.php.net/rest/');
return $pear_channel;
}
if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') {
// the registry is not properly set up, so use defaults
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$pear_channel = new PEAR_ChannelFile;
$pear_channel->setServer('pecl.php.net');
$pear_channel->setAlias('pecl');
$pear_channel->setSummary('PHP Extension Community Library');
$pear_channel->setDefaultPEARProtocols();
$pear_channel->setBaseURL('REST1.0', 'https://pecl.php.net/rest/');
$pear_channel->setBaseURL('REST1.1', 'https://pecl.php.net/rest/');
$pear_channel->setValidationPackage('PEAR_Validator_PECL', '1.0');
return $pear_channel;
}
if ($this->_getChannelFromAlias($channel) == 'doc.php.net') {
// the registry is not properly set up, so use defaults
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$doc_channel = new PEAR_ChannelFile;
$doc_channel->setServer('doc.php.net');
$doc_channel->setAlias('phpdocs');
$doc_channel->setSummary('PHP Documentation Team');
$doc_channel->setDefaultPEARProtocols();
$doc_channel->setBaseURL('REST1.0', 'https://doc.php.net/rest/');
$doc_channel->setBaseURL('REST1.1', 'https://doc.php.net/rest/');
$doc_channel->setBaseURL('REST1.3', 'https://doc.php.net/rest/');
return $doc_channel;
}
if ($this->_getChannelFromAlias($channel) == '__uri') {
// the registry is not properly set up, so use defaults
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$private = new PEAR_ChannelFile;
$private->setName('__uri');
$private->setDefaultPEARProtocols();
$private->setBaseURL('REST1.0', '****');
$private->setSummary('Pseudo-channel for static packages');
return $private;
}
return $ch;
}
/**
* @param string Package name
* @param string Channel name
* @return bool
*/
function packageExists($package, $channel = 'pear.php.net')
{
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
$ret = $this->_packageExists($package, $channel);
$this->_unlock();
return $ret;
}
// }}}
// {{{ channelExists()
/**
* @param string channel name
* @param bool if true, then aliases will be ignored
* @return bool
*/
function channelExists($channel, $noaliases = false)
{
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
$ret = $this->_channelExists($channel, $noaliases);
$this->_unlock();
return $ret;
}
// }}}
/**
* @param string channel name mirror is in
* @param string mirror name
*
* @return bool
*/
function mirrorExists($channel, $mirror)
{
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
$ret = $this->_mirrorExists($channel, $mirror);
$this->_unlock();
return $ret;
}
// {{{ isAlias()
/**
* Determines whether the parameter is an alias of a channel
* @param string
* @return bool
*/
function isAlias($alias)
{
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
$ret = $this->_isChannelAlias($alias);
$this->_unlock();
return $ret;
}
// }}}
// {{{ packageInfo()
/**
* @param string|null
* @param string|null
* @param string
* @return array|null
*/
function packageInfo($package = null, $key = null, $channel = 'pear.php.net')
{
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
$ret = $this->_packageInfo($package, $key, $channel);
$this->_unlock();
return $ret;
}
// }}}
// {{{ channelInfo()
/**
* Retrieve a raw array of channel data.
*
* Do not use this, instead use {@link getChannel()} for normal
* operations. Array structure is undefined in this method
* @param string channel name
* @param bool whether to strictly retrieve information only on non-aliases
* @return array|null|PEAR_Error
*/
function channelInfo($channel = null, $noaliases = false)
{
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
$ret = $this->_channelInfo($channel, $noaliases);
$this->_unlock();
return $ret;
}
// }}}
/**
* @param string
*/
function channelName($channel)
{
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
$ret = $this->_getChannelFromAlias($channel);
$this->_unlock();
return $ret;
}
/**
* @param string
*/
function channelAlias($channel)
{
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
$ret = $this->_getAlias($channel);
$this->_unlock();
return $ret;
}
// {{{ listPackages()
function listPackages($channel = false)
{
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
$ret = $this->_listPackages($channel);
$this->_unlock();
return $ret;
}
// }}}
// {{{ listAllPackages()
function listAllPackages()
{
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
$ret = $this->_listAllPackages();
$this->_unlock();
return $ret;
}
// }}}
// {{{ listChannel()
function listChannels()
{
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
$ret = $this->_listChannels();
$this->_unlock();
return $ret;
}
// }}}
// {{{ addPackage()
/**
* Add an installed package to the registry
* @param string|PEAR_PackageFile_v1|PEAR_PackageFile_v2 package name or object
* that will be passed to {@link addPackage2()}
* @param array package info (parsed by PEAR_Common::infoFrom*() methods)
* @return bool success of saving
*/
function addPackage($package, $info)
{
if (is_object($info)) {
return $this->addPackage2($info);
}
if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
return $e;
}
$ret = $this->_addPackage($package, $info);
$this->_unlock();
if ($ret) {
if (!class_exists('PEAR_PackageFile_v1')) {
require_once 'PEAR/PackageFile/v1.php';
}
$pf = new PEAR_PackageFile_v1;
$pf->setConfig($this->_config);
$pf->fromArray($info);
$this->_dependencyDB->uninstallPackage($pf);
$this->_dependencyDB->installPackage($pf);
}
return $ret;
}
// }}}
// {{{ addPackage2()
function addPackage2($info)
{
if (!is_object($info)) {
return $this->addPackage($info['package'], $info);
}
if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
return $e;
}
$ret = $this->_addPackage2($info);
$this->_unlock();
if ($ret) {
$this->_dependencyDB->uninstallPackage($info);
$this->_dependencyDB->installPackage($info);
}
return $ret;
}
// }}}
// {{{ updateChannel()
/**
* For future expandibility purposes, separate this
* @param PEAR_ChannelFile
*/
function updateChannel($channel, $lastmodified = null)
{
if ($channel->getName() == '__uri') {
return false;
}
return $this->addChannel($channel, $lastmodified, true);
}
// }}}
// {{{ deleteChannel()
/**
* Deletion fails if there are any packages installed from the channel
* @param string|PEAR_ChannelFile channel name
* @return boolean|PEAR_Error True on deletion, false if it doesn't exist
*/
function deleteChannel($channel)
{
if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
return $e;
}
$ret = $this->_deleteChannel($channel);
$this->_unlock();
if ($ret && is_a($this->_config, 'PEAR_Config')) {
$this->_config->setChannels($this->listChannels());
}
return $ret;
}
// }}}
// {{{ addChannel()
/**
* @param PEAR_ChannelFile Channel object
* @param string Last-Modified header from HTTP for caching
* @return boolean|PEAR_Error True on creation, false if it already exists
*/
function addChannel($channel, $lastmodified = false, $update = false)
{
if (!is_a($channel, 'PEAR_ChannelFile') || !$channel->validate()) {
return false;
}
if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
return $e;
}
$ret = $this->_addChannel($channel, $update, $lastmodified);
$this->_unlock();
if (!$update && $ret && is_a($this->_config, 'PEAR_Config')) {
$this->_config->setChannels($this->listChannels());
}
return $ret;
}
// }}}
// {{{ deletePackage()
function deletePackage($package, $channel = 'pear.php.net')
{
if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
return $e;
}
$file = $this->_packageFileName($package, $channel);
$ret = file_exists($file) ? @unlink($file) : false;
$this->_rebuildFileMap();
$this->_unlock();
$p = array('channel' => $channel, 'package' => $package);
$this->_dependencyDB->uninstallPackage($p);
return $ret;
}
// }}}
// {{{ updatePackage()
function updatePackage($package, $info, $merge = true)
{
if (is_object($info)) {
return $this->updatePackage2($info, $merge);
}
if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
return $e;
}
$ret = $this->_updatePackage($package, $info, $merge);
$this->_unlock();
if ($ret) {
if (!class_exists('PEAR_PackageFile_v1')) {
require_once 'PEAR/PackageFile/v1.php';
}
$pf = new PEAR_PackageFile_v1;
$pf->setConfig($this->_config);
$pf->fromArray($this->packageInfo($package));
$this->_dependencyDB->uninstallPackage($pf);
$this->_dependencyDB->installPackage($pf);
}
return $ret;
}
// }}}
// {{{ updatePackage2()
function updatePackage2($info)
{
if (!is_object($info)) {
return $this->updatePackage($info['package'], $info, $merge);
}
if (!$info->validate(PEAR_VALIDATE_DOWNLOADING)) {
return false;
}
if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
return $e;
}
$ret = $this->_updatePackage2($info);
$this->_unlock();
if ($ret) {
$this->_dependencyDB->uninstallPackage($info);
$this->_dependencyDB->installPackage($info);
}
return $ret;
}
// }}}
// {{{ getChannel()
/**
* @param string channel name
* @param bool whether to strictly return raw channels (no aliases)
* @return PEAR_ChannelFile|PEAR_Error
*/
function getChannel($channel, $noaliases = false)
{
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
$ret = $this->_getChannel($channel, $noaliases);
$this->_unlock();
if (!$ret) {
return PEAR::raiseError('Unknown channel: ' . $channel);
}
return $ret;
}
// }}}
// {{{ getPackage()
/**
* @param string package name
* @param string channel name
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
*/
function &getPackage($package, $channel = 'pear.php.net')
{
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
$pf = &$this->_getPackage($package, $channel);
$this->_unlock();
return $pf;
}
// }}}
/**
* Get PEAR_PackageFile_v[1/2] objects representing the contents of
* a dependency group that are installed.
*
* This is used at uninstall-time
* @param array
* @return array|false
*/
function getInstalledGroup($group)
{
$ret = array();
if (isset($group['package'])) {
if (!isset($group['package'][0])) {
$group['package'] = array($group['package']);
}
foreach ($group['package'] as $package) {
$depchannel = isset($package['channel']) ? $package['channel'] : '__uri';
$p = &$this->getPackage($package['name'], $depchannel);
if ($p) {
$save = &$p;
$ret[] = &$save;
}
}
}
if (isset($group['subpackage'])) {
if (!isset($group['subpackage'][0])) {
$group['subpackage'] = array($group['subpackage']);
}
foreach ($group['subpackage'] as $package) {
$depchannel = isset($package['channel']) ? $package['channel'] : '__uri';
$p = &$this->getPackage($package['name'], $depchannel);
if ($p) {
$save = &$p;
$ret[] = &$save;
}
}
}
if (!count($ret)) {
return false;
}
return $ret;
}
// {{{ getChannelValidator()
/**
* @param string channel name
* @return PEAR_Validate|false
*/
function &getChannelValidator($channel)
{
$chan = $this->getChannel($channel);
if (PEAR::isError($chan)) {
return $chan;
}
$val = $chan->getValidationObject();
return $val;
}
// }}}
// {{{ getChannels()
/**
* @param string channel name
* @return array an array of PEAR_ChannelFile objects representing every installed channel
*/
function &getChannels()
{
$ret = array();
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
foreach ($this->_listChannels() as $channel) {
$e = &$this->_getChannel($channel);
if (!$e || PEAR::isError($e)) {
continue;
}
$ret[] = $e;
}
$this->_unlock();
return $ret;
}
// }}}
// {{{ checkFileMap()
/**
* Test whether a file or set of files belongs to a package.
*
* If an array is passed in
* @param string|array file path, absolute or relative to the pear
* install dir
* @param string|array name of PEAR package or array('package' => name, 'channel' =>
* channel) of a package that will be ignored
* @param string API version - 1.1 will exclude any files belonging to a package
* @param array private recursion variable
* @return array|false which package and channel the file belongs to, or an empty
* string if the file does not belong to an installed package,
* or belongs to the second parameter's package
*/
function checkFileMap($path, $package = false, $api = '1.0', $attrs = false)
{
if (is_array($path)) {
static $notempty;
if (empty($notempty)) {
if (!class_exists('PEAR_Installer_Role')) {
require_once 'PEAR/Installer/Role.php';
}
$notempty = function($a) { return !empty($a); };
}
$package = is_array($package) ? array(strtolower($package[0]), strtolower($package[1]))
: strtolower($package);
$pkgs = array();
foreach ($path as $name => $attrs) {
if (is_array($attrs)) {
if (isset($attrs['install-as'])) {
$name = $attrs['install-as'];
}
if (!in_array($attrs['role'], PEAR_Installer_Role::getInstallableRoles())) {
// these are not installed
continue;
}
if (!in_array($attrs['role'], PEAR_Installer_Role::getBaseinstallRoles())) {
$attrs['baseinstalldir'] = is_array($package) ? $package[1] : $package;
}
if (isset($attrs['baseinstalldir'])) {
$name = $attrs['baseinstalldir'] . DIRECTORY_SEPARATOR . $name;
}
}
$pkgs[$name] = $this->checkFileMap($name, $package, $api, $attrs);
if (PEAR::isError($pkgs[$name])) {
return $pkgs[$name];
}
}
return array_filter($pkgs, $notempty);
}
if (empty($this->filemap_cache)) {
if (PEAR::isError($e = $this->_lock(LOCK_SH))) {
return $e;
}
$err = $this->_readFileMap();
$this->_unlock();
if (PEAR::isError($err)) {
return $err;
}
}
if (!$attrs) {
$attrs = array('role' => 'php'); // any old call would be for PHP role only
}
if (isset($this->filemap_cache[$attrs['role']][$path])) {
if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
return false;
}
return $this->filemap_cache[$attrs['role']][$path];
}
$l = strlen($this->install_dir);
if (substr($path, 0, $l) == $this->install_dir) {
$path = preg_replace('!^'.DIRECTORY_SEPARATOR.'+!', '', substr($path, $l));
}
if (isset($this->filemap_cache[$attrs['role']][$path])) {
if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) {
return false;
}
return $this->filemap_cache[$attrs['role']][$path];
}
return false;
}
// }}}
// {{{ flush()
/**
* Force a reload of the filemap
* @since 1.5.0RC3
*/
function flushFileMap()
{
$this->filemap_cache = null;
clearstatcache(); // ensure that the next read gets the full, current filemap
}
// }}}
// {{{ apiVersion()
/**
* Get the expected API version. Channels API is version 1.1, as it is backwards
* compatible with 1.0
* @return string
*/
function apiVersion()
{
return '1.1';
}
// }}}
/**
* Parse a package name, or validate a parsed package name array
* @param string|array pass in an array of format
* array(
* 'package' => 'pname',
* ['channel' => 'channame',]
* ['version' => 'version',]
* ['state' => 'state',]
* ['group' => 'groupname'])
* or a string of format
* [channel://][channame/]pname[-version|-state][/group=groupname]
* @return array|PEAR_Error
*/
function parsePackageName($param, $defaultchannel = 'pear.php.net')
{
$saveparam = $param;
if (is_array($param)) {
// convert to string for error messages
$saveparam = $this->parsedPackageNameToString($param);
// process the array
if (!isset($param['package'])) {
return PEAR::raiseError('parsePackageName(): array $param ' .
'must contain a valid package name in index "param"',
'package', null, null, $param);
}
if (!isset($param['uri'])) {
if (!isset($param['channel'])) {
$param['channel'] = $defaultchannel;
}
} else {
$param['channel'] = '__uri';
}
} else {
$components = @parse_url((string) $param);
if (isset($components['scheme'])) {
if ($components['scheme'] == 'http') {
// uri package
$param = array('uri' => $param, 'channel' => '__uri');
} elseif($components['scheme'] != 'channel') {
return PEAR::raiseError('parsePackageName(): only channel:// uris may ' .
'be downloaded, not "' . $param . '"', 'invalid', null, null, $param);
}
}
if (!isset($components['path'])) {
return PEAR::raiseError('parsePackageName(): array $param ' .
'must contain a valid package name in "' . $param . '"',
'package', null, null, $param);
}
if (isset($components['host'])) {
// remove the leading "/"
$components['path'] = substr($components['path'], 1);
}
if (!isset($components['scheme'])) {
if (strpos($components['path'], '/') !== false) {
if ($components['path'][0] == '/') {
return PEAR::raiseError('parsePackageName(): this is not ' .
'a package name, it begins with "/" in "' . $param . '"',
'invalid', null, null, $param);
}
$parts = explode('/', $components['path']);
$components['host'] = array_shift($parts);
if (count($parts) > 1) {
$components['path'] = array_pop($parts);
$components['host'] .= '/' . implode('/', $parts);
} else {
$components['path'] = implode('/', $parts);
}
} else {
$components['host'] = $defaultchannel;
}
} else {
if (strpos($components['path'], '/')) {
$parts = explode('/', $components['path']);
$components['path'] = array_pop($parts);
$components['host'] .= '/' . implode('/', $parts);
}
}
if (is_array($param)) {
$param['package'] = $components['path'];
} else {
$param = array(
'package' => $components['path']
);
if (isset($components['host'])) {
$param['channel'] = $components['host'];
}
}
if (isset($components['fragment'])) {
$param['group'] = $components['fragment'];
}
if (isset($components['user'])) {
$param['user'] = $components['user'];
}
if (isset($components['pass'])) {
$param['pass'] = $components['pass'];
}
if (isset($components['query'])) {
parse_str($components['query'], $param['opts']);
}
// check for extension
$pathinfo = pathinfo($param['package']);
if (isset($pathinfo['extension']) &&
in_array(strtolower($pathinfo['extension']), array('tgz', 'tar'))) {
$param['extension'] = $pathinfo['extension'];
$param['package'] = substr($pathinfo['basename'], 0,
strlen($pathinfo['basename']) - 4);
}
// check for version
if (strpos($param['package'], '-')) {
$test = explode('-', $param['package']);
if (count($test) != 2) {
return PEAR::raiseError('parsePackageName(): only one version/state ' .
'delimiter "-" is allowed in "' . $saveparam . '"',
'version', null, null, $param);
}
list($param['package'], $param['version']) = $test;
}
}
// validation
$info = $this->channelExists($param['channel']);
if (PEAR::isError($info)) {
return $info;
}
if (!$info) {
return PEAR::raiseError('unknown channel "' . $param['channel'] .
'" in "' . $saveparam . '"', 'channel', null, null, $param);
}
$chan = $this->getChannel($param['channel']);
if (PEAR::isError($chan)) {
return $chan;
}
if (!$chan) {
return PEAR::raiseError("Exception: corrupt registry, could not " .
"retrieve channel " . $param['channel'] . " information",
'registry', null, null, $param);
}
$param['channel'] = $chan->getName();
$validate = $chan->getValidationObject();
$vpackage = $chan->getValidationPackage();
// validate package name
if (!$validate->validPackageName($param['package'], $vpackage['_content'])) {
return PEAR::raiseError('parsePackageName(): invalid package name "' .
$param['package'] . '" in "' . $saveparam . '"',
'package', null, null, $param);
}
if (isset($param['group'])) {
if (!PEAR_Validate::validGroupName($param['group'])) {
return PEAR::raiseError('parsePackageName(): dependency group "' . $param['group'] .
'" is not a valid group name in "' . $saveparam . '"', 'group', null, null,
$param);
}
}
if (isset($param['state'])) {
if (!in_array(strtolower($param['state']), $validate->getValidStates())) {
return PEAR::raiseError('parsePackageName(): state "' . $param['state']
. '" is not a valid state in "' . $saveparam . '"',
'state', null, null, $param);
}
}
if (isset($param['version'])) {
if (isset($param['state'])) {
return PEAR::raiseError('parsePackageName(): cannot contain both ' .
'a version and a stability (state) in "' . $saveparam . '"',
'version/state', null, null, $param);
}
// check whether version is actually a state
if (in_array(strtolower($param['version']), $validate->getValidStates())) {
$param['state'] = strtolower($param['version']);
unset($param['version']);
} else {
if (!$validate->validVersion($param['version'])) {
return PEAR::raiseError('parsePackageName(): "' . $param['version'] .
'" is neither a valid version nor a valid state in "' .
$saveparam . '"', 'version/state', null, null, $param);
}
}
}
return $param;
}
/**
* @param array
* @return string
*/
function parsedPackageNameToString($parsed, $brief = false)
{
if (is_string($parsed)) {
return $parsed;
}
if (is_object($parsed)) {
$p = $parsed;
$parsed = array(
'package' => $p->getPackage(),
'channel' => $p->getChannel(),
'version' => $p->getVersion(),
);
}
if (isset($parsed['uri'])) {
return $parsed['uri'];
}
if ($brief) {
if ($channel = $this->channelAlias($parsed['channel'])) {
return $channel . '/' . $parsed['package'];
}
}
$upass = '';
if (isset($parsed['user'])) {
$upass = $parsed['user'];
if (isset($parsed['pass'])) {
$upass .= ':' . $parsed['pass'];
}
$upass = "$upass@";
}
$ret = 'channel://' . $upass . $parsed['channel'] . '/' . $parsed['package'];
if (isset($parsed['version']) || isset($parsed['state'])) {
$ver = isset($parsed['version']) ? $parsed['version'] : '';
$ver .= isset($parsed['state']) ? $parsed['state'] : '';
$ret .= '-' . $ver;
}
if (isset($parsed['extension'])) {
$ret .= '.' . $parsed['extension'];
}
if (isset($parsed['opts'])) {
$ret .= '?';
foreach ($parsed['opts'] as $name => $value) {
$parsed['opts'][$name] = "$name=$value";
}
$ret .= implode('&', $parsed['opts']);
}
if (isset($parsed['group'])) {
$ret .= '#' . $parsed['group'];
}
return $ret;
}
}
PK �]�W�z
PEAR/Command/Auth.phpnu �[��� <?php
/**
* PEAR_Command_Auth (login, logout commands)
*
* PHP versions 4 and 5
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
* @deprecated since 1.8.0alpha1
*/
/**
* base class
*/
require_once 'PEAR/Command/Channels.php';
/**
* PEAR commands for login/logout
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.18
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
* @deprecated since 1.8.0alpha1
*/
class PEAR_Command_Auth extends PEAR_Command_Channels
{
var $commands = array(
'login' => array(
'summary' => 'Connects and authenticates to remote server [Deprecated in favor of channel-login]',
'shortcut' => 'li',
'function' => 'doLogin',
'options' => array(),
'doc' => '<channel name>
WARNING: This function is deprecated in favor of using channel-login
Log in to a remote channel server. If <channel name> is not supplied,
the default channel is used. To use remote functions in the installer
that require any kind of privileges, you need to log in first. The
username and password you enter here will be stored in your per-user
PEAR configuration (~/.pearrc on Unix-like systems). After logging
in, your username and password will be sent along in subsequent
operations on the remote server.',
),
'logout' => array(
'summary' => 'Logs out from the remote server [Deprecated in favor of channel-logout]',
'shortcut' => 'lo',
'function' => 'doLogout',
'options' => array(),
'doc' => '
WARNING: This function is deprecated in favor of using channel-logout
Logs out from the remote server. This command does not actually
connect to the remote server, it only deletes the stored username and
password from your user configuration.',
)
);
/**
* PEAR_Command_Auth constructor.
*
* @access public
*/
function __construct(&$ui, &$config)
{
parent::__construct($ui, $config);
}
}
PK �]���s6
6
PEAR/Command/Config.xmlnu �[��� <commands version="1.0">
<config-show>
<summary>Show All Settings</summary>
<function>doConfigShow</function>
<shortcut>csh</shortcut>
<options>
<channel>
<shortopt>c</shortopt>
<doc>show configuration variables for another channel</doc>
<arg>CHAN</arg>
</channel>
</options>
<doc>[layer]
Displays all configuration values. An optional argument
may be used to tell which configuration layer to display. Valid
configuration layers are "user", "system" and "default". To display
configurations for different channels, set the default_channel
configuration variable and run config-show again.
</doc>
</config-show>
<config-get>
<summary>Show One Setting</summary>
<function>doConfigGet</function>
<shortcut>cg</shortcut>
<options>
<channel>
<shortopt>c</shortopt>
<doc>show configuration variables for another channel</doc>
<arg>CHAN</arg>
</channel>
</options>
<doc><parameter> [layer]
Displays the value of one configuration parameter. The
first argument is the name of the parameter, an optional second argument
may be used to tell which configuration layer to look in. Valid configuration
layers are "user", "system" and "default". If no layer is specified, a value
will be picked from the first layer that defines the parameter, in the order
just specified. The configuration value will be retrieved for the channel
specified by the default_channel configuration variable.
</doc>
</config-get>
<config-set>
<summary>Change Setting</summary>
<function>doConfigSet</function>
<shortcut>cs</shortcut>
<options>
<channel>
<shortopt>c</shortopt>
<doc>show configuration variables for another channel</doc>
<arg>CHAN</arg>
</channel>
</options>
<doc><parameter> <value> [layer]
Sets the value of one configuration parameter. The first argument is
the name of the parameter, the second argument is the new value. Some
parameters are subject to validation, and the command will fail with
an error message if the new value does not make sense. An optional
third argument may be used to specify in which layer to set the
configuration parameter. The default layer is "user". The
configuration value will be set for the current channel, which
is controlled by the default_channel configuration variable.
</doc>
</config-set>
<config-help>
<summary>Show Information About Setting</summary>
<function>doConfigHelp</function>
<shortcut>ch</shortcut>
<options />
<doc>[parameter]
Displays help for a configuration parameter. Without arguments it
displays help for all configuration parameters.
</doc>
</config-help>
<config-create>
<summary>Create a Default configuration file</summary>
<function>doConfigCreate</function>
<shortcut>coc</shortcut>
<options>
<windows>
<shortopt>w</shortopt>
<doc>create a config file for a windows install</doc>
</windows>
</options>
<doc><root path> <filename>
Create a default configuration file with all directory configuration
variables set to subdirectories of <root path>, and save it as <filename>.
This is useful especially for creating a configuration file for a remote
PEAR installation (using the --remoteconfig option of install, upgrade,
and uninstall).
</doc>
</config-create>
</commands>PK �]
u�� � PEAR/Command/Build.xmlnu �[��� <commands version="1.0">
<build>
<summary>Build an Extension From C Source</summary>
<function>doBuild</function>
<shortcut>b</shortcut>
<options>
<configureoptions>
<shortopt>D</shortopt>
<arg>OPTION1=VALUE[ OPTION2=VALUE]</arg>
</configureoptions>
</options>
<doc>[package.xml]
Builds one or more extensions contained in a package.</doc>
</build>
</commands>PK �]��>