* @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:
';
print XML_Util::replaceEntities('This string contains < & >.');
print "\n
\n";
/**
* reversing XML entities
*/
print 'replace XML entities:
';
print XML_Util::reverseEntities('This string contains < & >.');
print "\n
\n";
/**
* building XML declaration
*/
print 'building XML declaration:
';
print htmlspecialchars(XML_Util::getXMLDeclaration());
print "\n
\n";
print 'building XML declaration with additional attributes:
';
print htmlspecialchars(XML_Util::getXMLDeclaration('1.0', 'UTF-8', true));
print "\n
\n";
/**
* building document type declaration
*/
print 'building DocType declaration:
';
print htmlspecialchars(XML_Util::getDocTypeDeclaration('package',
'http://pear.php.net/dtd/package-1.0'));
print "\n
\n";
print 'building DocType declaration with public ID (does not exist):
';
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
\n";
print 'building DocType declaration with internal DTD:
';
print '';
print htmlspecialchars(XML_Util::getDocTypeDeclaration('package',
'http://pear.php.net/dtd/package-1.0',
''));
print '
';
print "\n
\n";
/**
* creating an attribute string
*/
$att = array(
'foo' => 'bar',
'argh' => 'tomato'
);
print 'converting array to string:
';
print XML_Util::attributesToString($att);
print "\n
\n";
/**
* creating an attribute string with linebreaks
*/
$att = array(
'foo' => 'bar',
'argh' => 'tomato'
);
print 'converting array to string (including line breaks):
';
print '';
print XML_Util::attributesToString($att, true, true);
print '
';
print "\n
\n";
/**
* splitting a qualified tag name
*/
print 'splitting qualified tag name:
';
print '';
print_r(XML_Util::splitQualifiedName('xslt:stylesheet'));
print '
';
print "\n
\n";
/**
* splitting a qualified tag name (no namespace)
*/
print 'splitting qualified tag name (no namespace):
';
print '';
print_r(XML_Util::splitQualifiedName('foo'));
print '
';
print "\n
\n";
/**
* splitting a qualified tag name (no namespace, but default namespace specified)
*/
print 'splitting qualified tag name '
. '(no namespace, but default namespace specified):
';
print '';
print_r(XML_Util::splitQualifiedName('foo', 'bar'));
print '
';
print "\n
\n";
/**
* verifying XML names
*/
print 'verifying \'My private tag\':
';
print '';
print_r(XML_Util::isValidname('My Private Tag'));
print '
';
print "\n
\n";
print 'verifying \'-MyTag\':
';
print '';
print_r(XML_Util::isValidname('-MyTag'));
print '
';
print "\n
\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:
';
print htmlentities(XML_Util::createTagFromArray($tag));
print "\n
\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:
';
print htmlentities(XML_Util::createTagFromArray($tag));
print "\n
\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:
';
print htmlentities(XML_Util::createTagFromArray($tag));
print "\n
\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:
';
print htmlentities(XML_Util::createTagFromArray($tag));
print "\n
\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:
';
print htmlentities(XML_Util::createTagFromArray($tag, XML_UTIL_CDATA_SECTION));
print "\n
\n";
/**
* creating an XML tag with a CData Section
*/
$tag = array(
'qname' => 'foo',
'attributes' => array('key' => 'value', 'argh' => 'tt'),
'content' =>
'Also XHTML-tags can be created '
. 'and HTML entities can be replaced <>.'
);
print 'creating a tag with HTML entities:
';
print htmlentities(XML_Util::createTagFromArray($tag, XML_UTIL_ENTITIES_HTML));
print "\n
\n";
/**
* creating an XML tag with createTag
*/
print 'creating a tag with createTag:
';
print htmlentities(XML_Util::createTag('myNs:myTag',
array('foo' => 'bar'),
'This is inside the tag',
'http://www.w3c.org/myNs#'));
print "\n
\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:
';
print '';
print_r(XML_Util::createTagFromArray($tag));
print '
';
print "\n
\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:
';
print '';
print_r(XML_Util::createTagFromArray($tag));
print '
';
print "\n
\n";
?>
PK [r¦J J $ doc/Archive_Tar/docs/Archive_Tar.txtnu W+A 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";
echo " .size :'".$v_list[$i][size]."'
";
echo " .mtime :'".$v_list[$i][mtime]."' (".date("l dS of F Y h:i:s A", $v_list[$i][mtime]).")
";
echo " .mode :'".$v_list[$i][mode]."'
";
echo " .uid :'".$v_list[$i][uid]."'
";
echo " .gid :'".$v_list[$i][gid]."'
";
echo " .typeflag :'".$v_list[$i][typeflag]."'
";
}
// ----- 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";
echo " .size :'".$v_list[$i][size]."'
";
echo " .mtime :'".$v_list[$i][mtime]."' (".
date("l dS of F Y h:i:s A", $v_list[$i][mtime]).")
";
echo " .mode :'".$v_list[$i][mode]."'
";
echo " .uid :'".$v_list[$i][uid]."'
";
echo " .gid :'".$v_list[$i][gid]."'
";
echo " .typeflag :'".$v_list[$i][typeflag]."'
";
}
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 [DGe doc/Structures_Graph/LICENSEnu W+A GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
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 I doc/Structures_Graph/docs/tutorials/Structures_Graph/Structures_Graph.pkgnu W+A
Structures_Graph Tutorial
A first tour of graph datastructure manipulation
Introduction
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.
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.
Creating a Graph
Creating a graph is done using the simple constructor:
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.
To fill out the graph, we'll need to create some nodes, and then call Graph::addNode.
addNode(&$nodeOne);
$directedGraph->addNode(&$nodeTwo);
$directedGraph->addNode(&$nodeThree);
]]>
and then setup the arcs:
connectTo($nodeTwo);
$nodeOne->connectTo($nodeThree);
]]>
Note that arcs can only be created after the nodes have been inserted into the graph.
Associating Data
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.
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());
]]>
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:
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');
]]>
Querying a Graph
Structures_Graph provides for basic querying of the graph:
inDegree());
print("NodeOne's outDegree: " . $nodeOne->outDegree());
// and naturally, nodes can report on their arcs
$arcs = $nodeOne->getNeighbours();
for ($i=0;$igetData());
}
]]>
PK [ data/PEAR/template.specnu W+A Summary: PEAR: @summary@
Name: @rpm_package@
Version: @version@
Release: 1
License: @release_license@
Group: Development/Libraries
Source: http://@master_server@/get/@package@-%{version}.tgz
BuildRoot: %{_tmppath}/%{name}-root
URL: http://@master_server@/package/@package@
Prefix: %{_prefix}
BuildArchitectures: @arch@
@extra_headers@
%description
@description@
%prep
rm -rf %{buildroot}/*
%setup -c -T
# XXX Source files location is missing here in pear cmd
pear -v -c %{buildroot}/pearrc \
-d php_dir=%{_libdir}/php/pear \
-d doc_dir=/docs \
-d bin_dir=%{_bindir} \
-d data_dir=%{_libdir}/php/pear/data \
-d test_dir=%{_libdir}/php/pear/tests \
-d ext_dir=%{_libdir} \@extra_config@
-s
%build
echo BuildRoot=%{buildroot}
%postun
# if refcount = 0 then package has been removed (not upgraded)
if [ "$1" -eq "0" ]; then
pear uninstall --nodeps -r @possible_channel@@package@
rm @rpm_xml_dir@/@package@.xml
fi
%post
# if refcount = 2 then package has been upgraded
if [ "$1" -ge "2" ]; then
pear upgrade --nodeps -r @rpm_xml_dir@/@package@.xml
else
pear install --nodeps -r @rpm_xml_dir@/@package@.xml
fi
%install
pear -c %{buildroot}/pearrc install --nodeps -R %{buildroot} \
$RPM_SOURCE_DIR/@package@-%{version}.tgz
rm %{buildroot}/pearrc
rm %{buildroot}/%{_libdir}/php/pear/.filemap
rm %{buildroot}/%{_libdir}/php/pear/.lock
rm -rf %{buildroot}/%{_libdir}/php/pear/.registry
if [ "@doc_files@" != "" ]; then
mv %{buildroot}/docs/@package@/* .
rm -rf %{buildroot}/docs
fi
mkdir -p %{buildroot}@rpm_xml_dir@
tar -xzf $RPM_SOURCE_DIR/@package@-%{version}.tgz package@package2xml@.xml
cp -p package@package2xml@.xml %{buildroot}@rpm_xml_dir@/@package@.xml
#rm -rf %{buildroot}/*
#pear -q install -R %{buildroot} -n package@package2xml@.xml
#mkdir -p %{buildroot}@rpm_xml_dir@
#cp -p package@package2xml@.xml %{buildroot}@rpm_xml_dir@/@package@.xml
%files
%defattr(-,root,root)
%doc @doc_files@
/
PK [m?
?
data/PEAR/package.dtdnu W+A
PK [ڶ} } XML/Util.phpnu W+A
* 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
* @author Stephan Schmidt
* @copyright 2003-2008 Stephan Schmidt
* @license http://opensource.org/licenses/bsd-license New BSD License
* @version CVS: $Id$
* @link http://pear.php.net/package/XML_Util
*/
/**
* Error code for invalid chars in XML name
*/
define('XML_UTIL_ERROR_INVALID_CHARS', 51);
/**
* Error code for invalid chars in XML name
*/
define('XML_UTIL_ERROR_INVALID_START', 52);
/**
* Error code for non-scalar tag content
*/
define('XML_UTIL_ERROR_NON_SCALAR_CONTENT', 60);
/**
* Error code for missing tag name
*/
define('XML_UTIL_ERROR_NO_TAG_NAME', 61);
/**
* Replace XML entities
*/
define('XML_UTIL_REPLACE_ENTITIES', 1);
/**
* Embedd content in a CData Section
*/
define('XML_UTIL_CDATA_SECTION', 5);
/**
* Do not replace entitites
*/
define('XML_UTIL_ENTITIES_NONE', 0);
/**
* Replace all XML entitites
* This setting will replace <, >, ", ' and &
*/
define('XML_UTIL_ENTITIES_XML', 1);
/**
* Replace only required XML entitites
* This setting will replace <, " and &
*/
define('XML_UTIL_ENTITIES_XML_REQUIRED', 2);
/**
* Replace HTML entitites
* @link http://www.php.net/htmlentities
*/
define('XML_UTIL_ENTITIES_HTML', 3);
/**
* Do not collapse any empty tags.
*/
define('XML_UTIL_COLLAPSE_NONE', 0);
/**
* Collapse all empty tags.
*/
define('XML_UTIL_COLLAPSE_ALL', 1);
/**
* Collapse only empty XHTML tags that have no end tag.
*/
define('XML_UTIL_COLLAPSE_XHTML_ONLY', 2);
/**
* Utility class for working with XML documents
*
* @category XML
* @package XML_Util
* @author Stephan Schmidt
* @copyright 2003-2008 Stephan Schmidt
* @license http://opensource.org/licenses/bsd-license New BSD License
* @version Release: 1.4.2
* @link http://pear.php.net/package/XML_Util
*/
class XML_Util
{
/**
* Return API version
*
* @return string $version API version
*/
public static function apiVersion()
{
return '1.4';
}
/**
* Replace XML entities
*
* With the optional second parameter, you may select, which
* entities should be replaced.
*
*
* require_once 'XML/Util.php';
*
* // replace XML entites:
* $string = XML_Util::replaceEntities('This string contains < & >.');
*
*
* With the optional third parameter, you may pass the character encoding
*
* require_once 'XML/Util.php';
*
* // replace XML entites in UTF-8:
* $string = XML_Util::replaceEntities(
* 'This string contains < & > as well as ä, ö, ß, à and ê',
* XML_UTIL_ENTITIES_HTML,
* 'UTF-8'
* );
*
*
* @param string $string string where XML special chars
* should be replaced
* @param int $replaceEntities setting for entities in attribute values
* (one of XML_UTIL_ENTITIES_XML,
* XML_UTIL_ENTITIES_XML_REQUIRED,
* XML_UTIL_ENTITIES_HTML)
* @param string $encoding encoding value (if any)...
* must be a valid encoding as determined
* by the htmlentities() function
*
* @return string string with replaced chars
* @see reverseEntities()
*/
public static function replaceEntities(
$string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
) {
switch ($replaceEntities) {
case XML_UTIL_ENTITIES_XML:
return strtr(
$string,
array(
'&' => '&',
'>' => '>',
'<' => '<',
'"' => '"',
'\'' => '''
)
);
break;
case XML_UTIL_ENTITIES_XML_REQUIRED:
return strtr(
$string,
array(
'&' => '&',
'<' => '<',
'"' => '"'
)
);
break;
case XML_UTIL_ENTITIES_HTML:
return htmlentities($string, ENT_COMPAT, $encoding);
break;
}
return $string;
}
/**
* Reverse XML entities
*
* With the optional second parameter, you may select, which
* entities should be reversed.
*
*
* require_once 'XML/Util.php';
*
* // reverse XML entites:
* $string = XML_Util::reverseEntities('This string contains < & >.');
*
*
* With the optional third parameter, you may pass the character encoding
*
* require_once 'XML/Util.php';
*
* // reverse XML entites in UTF-8:
* $string = XML_Util::reverseEntities(
* 'This string contains < & > as well as'
* . ' ä, ö, ß, à and ê',
* XML_UTIL_ENTITIES_HTML,
* 'UTF-8'
* );
*
*
* @param string $string string where XML special chars
* should be replaced
* @param int $replaceEntities setting for entities in attribute values
* (one of XML_UTIL_ENTITIES_XML,
* XML_UTIL_ENTITIES_XML_REQUIRED,
* XML_UTIL_ENTITIES_HTML)
* @param string $encoding encoding value (if any)...
* must be a valid encoding as determined
* by the html_entity_decode() function
*
* @return string string with replaced chars
* @see replaceEntities()
*/
public static function reverseEntities(
$string, $replaceEntities = XML_UTIL_ENTITIES_XML, $encoding = 'ISO-8859-1'
) {
switch ($replaceEntities) {
case XML_UTIL_ENTITIES_XML:
return strtr(
$string,
array(
'&' => '&',
'>' => '>',
'<' => '<',
'"' => '"',
''' => '\''
)
);
break;
case XML_UTIL_ENTITIES_XML_REQUIRED:
return strtr(
$string,
array(
'&' => '&',
'<' => '<',
'"' => '"'
)
);
break;
case XML_UTIL_ENTITIES_HTML:
return html_entity_decode($string, ENT_COMPAT, $encoding);
break;
}
return $string;
}
/**
* Build an xml declaration
*
*
* require_once 'XML/Util.php';
*
* // get an XML declaration:
* $xmlDecl = XML_Util::getXMLDeclaration('1.0', 'UTF-8', true);
*
*
* @param string $version xml version
* @param string $encoding character encoding
* @param bool $standalone document is standalone (or not)
*
* @return string xml declaration
* @uses attributesToString() to serialize the attributes of the
* XML declaration
*/
public static function getXMLDeclaration(
$version = '1.0', $encoding = null, $standalone = null
) {
$attributes = array(
'version' => $version,
);
// add encoding
if ($encoding !== null) {
$attributes['encoding'] = $encoding;
}
// add standalone, if specified
if ($standalone !== null) {
$attributes['standalone'] = $standalone ? 'yes' : 'no';
}
return sprintf(
'',
XML_Util::attributesToString($attributes, false)
);
}
/**
* Build a document type declaration
*
*
* require_once 'XML/Util.php';
*
* // get a doctype declaration:
* $xmlDecl = XML_Util::getDocTypeDeclaration('rootTag','myDocType.dtd');
*
*
* @param string $root name of the root tag
* @param string $uri uri of the doctype definition
* (or array with uri and public id)
* @param string $internalDtd internal dtd entries
*
* @return string doctype declaration
* @since 0.2
*/
public static function getDocTypeDeclaration(
$root, $uri = null, $internalDtd = null
) {
if (is_array($uri)) {
$ref = sprintf(' PUBLIC "%s" "%s"', $uri['id'], $uri['uri']);
} elseif (!empty($uri)) {
$ref = sprintf(' SYSTEM "%s"', $uri);
} else {
$ref = '';
}
if (empty($internalDtd)) {
return sprintf('', $root, $ref);
} else {
return sprintf("", $root, $ref, $internalDtd);
}
}
/**
* Create string representation of an attribute list
*
*
* require_once 'XML/Util.php';
*
* // build an attribute string
* $att = array(
* 'foo' => 'bar',
* 'argh' => 'tomato'
* );
*
* $attList = XML_Util::attributesToString($att);
*
*
* @param array $attributes attribute array
* @param bool|array $sort sort attribute list alphabetically,
* may also be an assoc array containing
* the keys 'sort', 'multiline', 'indent',
* 'linebreak' and 'entities'
* @param bool $multiline use linebreaks, if more than
* one attribute is given
* @param string $indent string used for indentation of
* multiline attributes
* @param string $linebreak string used for linebreaks of
* multiline attributes
* @param int $entities setting for entities in attribute values
* (one of XML_UTIL_ENTITIES_NONE,
* XML_UTIL_ENTITIES_XML,
* XML_UTIL_ENTITIES_XML_REQUIRED,
* XML_UTIL_ENTITIES_HTML)
*
* @return string string representation of the attributes
* @uses replaceEntities() to replace XML entities in attribute values
* @todo allow sort also to be an options array
*/
public static function attributesToString(
$attributes, $sort = true, $multiline = false,
$indent = ' ', $linebreak = "\n", $entities = XML_UTIL_ENTITIES_XML
) {
/*
* second parameter may be an array
*/
if (is_array($sort)) {
if (isset($sort['multiline'])) {
$multiline = $sort['multiline'];
}
if (isset($sort['indent'])) {
$indent = $sort['indent'];
}
if (isset($sort['linebreak'])) {
$multiline = $sort['linebreak'];
}
if (isset($sort['entities'])) {
$entities = $sort['entities'];
}
if (isset($sort['sort'])) {
$sort = $sort['sort'];
} else {
$sort = true;
}
}
$string = '';
if (is_array($attributes) && !empty($attributes)) {
if ($sort) {
ksort($attributes);
}
if (!$multiline || count($attributes) == 1) {
foreach ($attributes as $key => $value) {
if ($entities != XML_UTIL_ENTITIES_NONE) {
if ($entities === XML_UTIL_CDATA_SECTION) {
$entities = XML_UTIL_ENTITIES_XML;
}
$value = XML_Util::replaceEntities($value, $entities);
}
$string .= ' ' . $key . '="' . $value . '"';
}
} else {
$first = true;
foreach ($attributes as $key => $value) {
if ($entities != XML_UTIL_ENTITIES_NONE) {
$value = XML_Util::replaceEntities($value, $entities);
}
if ($first) {
$string .= ' ' . $key . '="' . $value . '"';
$first = false;
} else {
$string .= $linebreak . $indent . $key . '="' . $value . '"';
}
}
}
}
return $string;
}
/**
* Collapses empty tags.
*
* @param string $xml XML
* @param int $mode Whether to collapse all empty tags (XML_UTIL_COLLAPSE_ALL)
* or only XHTML (XML_UTIL_COLLAPSE_XHTML_ONLY) ones.
*
* @return string XML
*/
public static function collapseEmptyTags($xml, $mode = XML_UTIL_COLLAPSE_ALL)
{
if (preg_match('~<([^>])+/>~s', $xml, $matches)) {
// it's already an empty tag
return $xml;
}
switch ($mode) {
case XML_UTIL_COLLAPSE_ALL:
$preg1 =
'~<' .
'(?:' .
'(https?://[^:\s]+:\w+)' . // ]*)' . // attributes ($4)
'>' .
'<\/(\1|\2|\3)>' . // 1, 2, or 3 again ($5)
'~s'
;
$preg2 =
'<' .
'${1}${2}${3}' . // tag (only one should have been populated)
'${4}' . // attributes
' />'
;
return (preg_replace($preg1, $preg2, $xml)?:$xml);
break;
case XML_UTIL_COLLAPSE_XHTML_ONLY:
return (
preg_replace(
'/<(area|base(?:font)?|br|col|frame|hr|img|input|isindex|link|meta|'
. 'param)([^>]*)><\/\\1>/s',
'<\\1\\2 />',
$xml
) ?: $xml
);
break;
case XML_UTIL_COLLAPSE_NONE:
// fall thru
default:
return $xml;
}
}
/**
* Create a tag
*
* This method will call XML_Util::createTagFromArray(), which
* is more flexible.
*
*
* require_once 'XML/Util.php';
*
* // create an XML tag:
* $tag = XML_Util::createTag('myNs:myTag',
* array('foo' => 'bar'),
* 'This is inside the tag',
* 'http://www.w3c.org/myNs#');
*
*
* @param string $qname qualified tagname (including namespace)
* @param array $attributes array containg attributes
* @param mixed $content the content
* @param string $namespaceUri URI of the namespace
* @param int $replaceEntities whether to replace XML special chars in
* content, embedd it in a CData section
* or none of both
* @param bool $multiline whether to create a multiline tag where
* each attribute gets written to a single line
* @param string $indent string used to indent attributes
* (_auto indents attributes so they start
* at the same column)
* @param string $linebreak string used for linebreaks
* @param bool $sortAttributes Whether to sort the attributes or not
* @param int $collapseTagMode How to handle a content-less, and thus collapseable, tag
*
* @return string XML tag
* @see createTagFromArray()
* @uses createTagFromArray() to create the tag
*/
public static function createTag(
$qname, $attributes = array(), $content = null,
$namespaceUri = null, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
$multiline = false, $indent = '_auto', $linebreak = "\n",
$sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
) {
$tag = array(
'qname' => $qname,
'attributes' => $attributes
);
// add tag content
if ($content !== null) {
$tag['content'] = $content;
}
// add namespace Uri
if ($namespaceUri !== null) {
$tag['namespaceUri'] = $namespaceUri;
}
return XML_Util::createTagFromArray(
$tag, $replaceEntities, $multiline,
$indent, $linebreak, $sortAttributes,
$collapseTagMode
);
}
/**
* Create a tag from an array.
* This method awaits an array in the following format
*
* array(
* // qualified name of the tag
* 'qname' => $qname
*
* // namespace prefix (optional, if qname is specified or no namespace)
* 'namespace' => $namespace
*
* // local part of the tagname (optional, if qname is specified)
* 'localpart' => $localpart,
*
* // array containing all attributes (optional)
* 'attributes' => array(),
*
* // tag content (optional)
* 'content' => $content,
*
* // namespaceUri for the given namespace (optional)
* 'namespaceUri' => $namespaceUri
* )
*
*
*
* require_once 'XML/Util.php';
*
* $tag = array(
* 'qname' => 'foo:bar',
* 'namespaceUri' => 'http://foo.com',
* 'attributes' => array('key' => 'value', 'argh' => 'fruit&vegetable'),
* 'content' => 'I\'m inside the tag',
* );
* // creating a tag with qualified name and namespaceUri
* $string = XML_Util::createTagFromArray($tag);
*
*
* @param array $tag tag definition
* @param int $replaceEntities whether to replace XML special chars in
* content, embedd it in a CData section
* or none of both
* @param bool $multiline whether to create a multiline tag where each
* attribute gets written to a single line
* @param string $indent string used to indent attributes
* (_auto indents attributes so they start
* at the same column)
* @param string $linebreak string used for linebreaks
* @param bool $sortAttributes Whether to sort the attributes or not
* @param int $collapseTagMode How to handle a content-less, and thus collapseable, tag
*
* @return string XML tag
*
* @see createTag()
* @uses attributesToString() to serialize the attributes of the tag
* @uses splitQualifiedName() to get local part and namespace of a qualified name
* @uses createCDataSection()
* @uses collapseEmptyTags()
* @uses raiseError()
*/
public static function createTagFromArray(
$tag, $replaceEntities = XML_UTIL_REPLACE_ENTITIES,
$multiline = false, $indent = '_auto', $linebreak = "\n",
$sortAttributes = true, $collapseTagMode = XML_UTIL_COLLAPSE_ALL
) {
if (isset($tag['content']) && !is_scalar($tag['content'])) {
return XML_Util::raiseError(
'Supplied non-scalar value as tag content',
XML_UTIL_ERROR_NON_SCALAR_CONTENT
);
}
if (!isset($tag['qname']) && !isset($tag['localPart'])) {
return XML_Util::raiseError(
'You must either supply a qualified name '
. '(qname) or local tag name (localPart).',
XML_UTIL_ERROR_NO_TAG_NAME
);
}
// if no attributes hav been set, use empty attributes
if (!isset($tag['attributes']) || !is_array($tag['attributes'])) {
$tag['attributes'] = array();
}
if (isset($tag['namespaces'])) {
foreach ($tag['namespaces'] as $ns => $uri) {
$tag['attributes']['xmlns:' . $ns] = $uri;
}
}
if (!isset($tag['qname'])) {
// qualified name is not given
// check for namespace
if (isset($tag['namespace']) && !empty($tag['namespace'])) {
$tag['qname'] = $tag['namespace'] . ':' . $tag['localPart'];
} else {
$tag['qname'] = $tag['localPart'];
}
} elseif (isset($tag['namespaceUri']) && !isset($tag['namespace'])) {
// namespace URI is set, but no namespace
$parts = XML_Util::splitQualifiedName($tag['qname']);
$tag['localPart'] = $parts['localPart'];
if (isset($parts['namespace'])) {
$tag['namespace'] = $parts['namespace'];
}
}
if (isset($tag['namespaceUri']) && !empty($tag['namespaceUri'])) {
// is a namespace given
if (isset($tag['namespace']) && !empty($tag['namespace'])) {
$tag['attributes']['xmlns:' . $tag['namespace']]
= $tag['namespaceUri'];
} else {
// define this Uri as the default namespace
$tag['attributes']['xmlns'] = $tag['namespaceUri'];
}
}
if (!array_key_exists('content', $tag)) {
$tag['content'] = '';
}
// check for multiline attributes
if ($multiline === true) {
if ($indent === '_auto') {
$indent = str_repeat(' ', (strlen($tag['qname'])+2));
}
}
// create attribute list
$attList = XML_Util::attributesToString(
$tag['attributes'],
$sortAttributes, $multiline, $indent, $linebreak
);
switch ($replaceEntities) {
case XML_UTIL_ENTITIES_NONE:
break;
case XML_UTIL_CDATA_SECTION:
$tag['content'] = XML_Util::createCDataSection($tag['content']);
break;
default:
$tag['content'] = XML_Util::replaceEntities(
$tag['content'], $replaceEntities
);
break;
}
$tag = sprintf(
'<%s%s>%s%s>', $tag['qname'], $attList, $tag['content'],
$tag['qname']
);
return self::collapseEmptyTags($tag, $collapseTagMode);
}
/**
* Create a start element
*
*
* require_once 'XML/Util.php';
*
* // create an XML start element:
* $tag = XML_Util::createStartElement('myNs:myTag',
* array('foo' => 'bar') ,'http://www.w3c.org/myNs#');
*
*
* @param string $qname qualified tagname (including namespace)
* @param array $attributes array containg attributes
* @param string $namespaceUri URI of the namespace
* @param bool $multiline whether to create a multiline tag where each
* attribute gets written to a single line
* @param string $indent string used to indent attributes (_auto indents
* attributes so they start at the same column)
* @param string $linebreak string used for linebreaks
* @param bool $sortAttributes Whether to sort the attributes or not
*
* @return string XML start element
* @see createEndElement(), createTag()
*/
public static function createStartElement(
$qname, $attributes = array(), $namespaceUri = null,
$multiline = false, $indent = '_auto', $linebreak = "\n",
$sortAttributes = true
) {
// if no attributes hav been set, use empty attributes
if (!isset($attributes) || !is_array($attributes)) {
$attributes = array();
}
if ($namespaceUri != null) {
$parts = XML_Util::splitQualifiedName($qname);
}
// check for multiline attributes
if ($multiline === true) {
if ($indent === '_auto') {
$indent = str_repeat(' ', (strlen($qname)+2));
}
}
if ($namespaceUri != null) {
// is a namespace given
if (isset($parts['namespace']) && !empty($parts['namespace'])) {
$attributes['xmlns:' . $parts['namespace']] = $namespaceUri;
} else {
// define this Uri as the default namespace
$attributes['xmlns'] = $namespaceUri;
}
}
// create attribute list
$attList = XML_Util::attributesToString(
$attributes, $sortAttributes,
$multiline, $indent, $linebreak
);
$element = sprintf('<%s%s>', $qname, $attList);
return $element;
}
/**
* Create an end element
*
*
* require_once 'XML/Util.php';
*
* // create an XML start element:
* $tag = XML_Util::createEndElement('myNs:myTag');
*
*
* @param string $qname qualified tagname (including namespace)
*
* @return string XML end element
* @see createStartElement(), createTag()
*/
public static function createEndElement($qname)
{
$element = sprintf('%s>', $qname);
return $element;
}
/**
* Create an XML comment
*
*
* require_once 'XML/Util.php';
*
* // create an XML start element:
* $tag = XML_Util::createComment('I am a comment');
*
*
* @param string $content content of the comment
*
* @return string XML comment
*/
public static function createComment($content)
{
$comment = sprintf('', $content);
return $comment;
}
/**
* Create a CData section
*
*
* require_once 'XML/Util.php';
*
* // create a CData section
* $tag = XML_Util::createCDataSection('I am content.');
*
*
* @param string $data data of the CData section
*
* @return string CData section with content
*/
public static function createCDataSection($data)
{
return sprintf(
'',
preg_replace('/\]\]>/', ']]]]>', strval($data))
);
}
/**
* Split qualified name and return namespace and local part
*
*
* require_once 'XML/Util.php';
*
* // split qualified tag
* $parts = XML_Util::splitQualifiedName('xslt:stylesheet');
*
* the returned array will contain two elements:
*
* array(
* 'namespace' => 'xslt',
* 'localPart' => 'stylesheet'
* );
*
*
* @param string $qname qualified tag name
* @param string $defaultNs default namespace (optional)
*
* @return array array containing namespace and local part
*/
public static function splitQualifiedName($qname, $defaultNs = null)
{
if (strstr($qname, ':')) {
$tmp = explode(':', $qname);
return array(
'namespace' => $tmp[0],
'localPart' => $tmp[1]
);
}
return array(
'namespace' => $defaultNs,
'localPart' => $qname
);
}
/**
* Check, whether string is valid XML name
*
* XML names are used for tagname, attribute names and various
* other, lesser known entities.
* An XML name may only consist of alphanumeric characters,
* dashes, undescores and periods, and has to start with a letter
* or an underscore.
*
*
* require_once 'XML/Util.php';
*
* // verify tag name
* $result = XML_Util::isValidName('invalidTag?');
* if (is_a($result, 'PEAR_Error')) {
* print 'Invalid XML name: ' . $result->getMessage();
* }
*
*
* @param string $string string that should be checked
*
* @return mixed true, if string is a valid XML name, PEAR error otherwise
*
* @todo support for other charsets
* @todo PEAR CS - unable to avoid 85-char limit on second preg_match
*/
public static function isValidName($string)
{
// check for invalid chars
if (!preg_match('/^[[:alpha:]_]\\z/', $string{0})) {
return XML_Util::raiseError(
'XML names may only start with letter or underscore',
XML_UTIL_ERROR_INVALID_START
);
}
// check for invalid chars
$match = preg_match(
'/^([[:alpha:]_]([[:alnum:]\-\.]*)?:)?'
. '[[:alpha:]_]([[:alnum:]\_\-\.]+)?\\z/',
$string
);
if (!$match) {
return XML_Util::raiseError(
'XML names may only contain alphanumeric '
. 'chars, period, hyphen, colon and underscores',
XML_UTIL_ERROR_INVALID_CHARS
);
}
// XML name is valid
return true;
}
/**
* Replacement for XML_Util::raiseError
*
* Avoids the necessity to always require
* PEAR.php
*
* @param string $msg error message
* @param int $code error code
*
* @return PEAR_Error
* @todo PEAR CS - should this use include_once instead?
*/
public static function raiseError($msg, $code)
{
include_once 'PEAR.php';
return PEAR::raiseError($msg, $code);
}
}
?>
PK [FZF PEAR.phpnu W+A
* @author Stig Bakken
* @author Tomas V.V.Cox
* @author Greg Beaver
* @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();
@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
* @author Tomas V.V. Cox
* @author Greg Beaver
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @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])) {
trigger_error(
'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR
);
}
return call_user_func_array(
array(get_class(), '_' . $method),
array_merge(array($this), $arguments)
);
}
public static function __callStatic($method, $arguments)
{
if (!isset(self::$bivalentMethods[$method])) {
trigger_error(
'Call to undefined method PEAR::' . $method . '()', E_USER_ERROR
);
}
return call_user_func_array(
array(get_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);
}
}
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);
}
while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
$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
* @author Tomas V.V. Cox
* @author Gregory Beaver
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @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;
/**
* 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 [o .channels/doc.php.net.regnu W+A a:5:{s:14:"suggestedalias";s:7:"phpdocs";s:4:"name";s:11:"doc.php.net";s:7:"summary";s:22:"PHP Documentation Team";s:7:"servers";a:1:{s:7:"primary";a:1:{s:4:"rest";a:1:{s:7:"baseurl";a:3:{i:0;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.0";}s:8:"_content";s:24:"http://doc.php.net/rest/";}i:1;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.1";}s:8:"_content";s:24:"http://doc.php.net/rest/";}i:2;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.3";}s:8:"_content";s:24:"http://doc.php.net/rest/";}}}}}s:13:"_lastmodified";i:1497974377;}PK [5m
9( ( .channels/pear.php.net.regnu W+A a:5:{s:14:"suggestedalias";s:4:"pear";s:4:"name";s:12:"pear.php.net";s:7:"summary";s:40:"PHP Extension and Application Repository";s:7:"servers";a:1:{s:7:"primary";a:1:{s:4:"rest";a:1:{s:7:"baseurl";a:3:{i:0;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.0";}s:8:"_content";s:25:"http://pear.php.net/rest/";}i:1;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.1";}s:8:"_content";s:25:"http://pear.php.net/rest/";}i:2;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.3";}s:8:"_content";s:25:"http://pear.php.net/rest/";}}}}}s:13:"_lastmodified";i:1497974377;}PK [IxO+ + .channels/pecl.php.net.regnu W+A a:6:{s:14:"suggestedalias";s:4:"pecl";s:4:"name";s:12:"pecl.php.net";s:7:"summary";s:31:"PHP Extension Community Library";s:7:"servers";a:1:{s:7:"primary";a:1:{s:4:"rest";a:1:{s:7:"baseurl";a:2:{i:0;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.0";}s:8:"_content";s:25:"http://pecl.php.net/rest/";}i:1;a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.1";}s:8:"_content";s:25:"http://pecl.php.net/rest/";}}}}}s:15:"validatepackage";a:2:{s:8:"_content";s:19:"PEAR_Validator_PECL";s:7:"attribs";a:1:{s:7:"version";s:3:"1.0";}}s:13:"_lastmodified";i:1497974377;}PK [ .channels/.alias/pear.txtnu W+A pear.php.netPK [ui< .channels/.alias/pecl.txtnu W+A pecl.php.netPK [o/ .channels/.alias/phpdocs.txtnu W+A doc.php.netPK [4Yb .channels/__uri.regnu W+A a:4:{s:4:"name";s:5:"__uri";s:7:"servers";a:1:{s:7:"primary";a:1:{s:4:"rest";a:1:{s:7:"baseurl";a:2:{s:7:"attribs";a:1:{s:4:"type";s:7:"REST1.0";}s:8:"_content";s:4:"****";}}}}s:7:"summary";s:34:"Pseudo-channel for static packages";s:13:"_lastmodified";i:1497974377;}PK [i] ] PEAR/DependencyDB.phpnu W+A
* @author Greg Beaver
* @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.php';
require_once 'PEAR/Config.php';
$GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'] = array();
/**
* Track dependency relationships between installed packages
* @category pear
* @package PEAR
* @author Greg Beaver
* @author Tomas V.V.Cox
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_DependencyDB
{
// {{{ properties
/**
* This is initialized by {@link setConfig()}
* @var PEAR_Config
* @access private
*/
var $_config;
/**
* This is initialized by {@link setConfig()}
* @var PEAR_Registry
* @access private
*/
var $_registry;
/**
* Filename of the dependency DB (usually .depdb)
* @var string
* @access private
*/
var $_depdb = false;
/**
* File name of the lockfile (usually .depdblock)
* @var string
* @access private
*/
var $_lockfile = false;
/**
* Open file resource for locking the lockfile
* @var resource|false
* @access private
*/
var $_lockFp = false;
/**
* API version of this class, used to validate a file on-disk
* @var string
* @access private
*/
var $_version = '1.0';
/**
* Cached dependency database file
* @var array|null
* @access private
*/
var $_cache;
// }}}
// {{{ & singleton()
/**
* Get a raw dependency database. Calls setConfig() and assertDepsDB()
* @param PEAR_Config
* @param string|false full path to the dependency database, or false to use default
* @return PEAR_DependencyDB|PEAR_Error
*/
public static function &singleton(&$config, $depdb = false)
{
$phpdir = $config->get('php_dir', null, 'pear.php.net');
if (!isset($GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir])) {
$a = new PEAR_DependencyDB;
$GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir] = &$a;
$a->setConfig($config, $depdb);
$e = $a->assertDepsDB();
if (PEAR::isError($e)) {
return $e;
}
}
return $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE'][$phpdir];
}
/**
* Set up the registry/location of dependency DB
* @param PEAR_Config|false
* @param string|false full path to the dependency database, or false to use default
*/
function setConfig(&$config, $depdb = false)
{
if (!$config) {
$this->_config = &PEAR_Config::singleton();
} else {
$this->_config = &$config;
}
$this->_registry = &$this->_config->getRegistry();
if (!$depdb) {
$dir = $this->_config->get('metadata_dir', null, 'pear.php.net');
if (!$dir) {
$dir = $this->_config->get('php_dir', null, 'pear.php.net');
}
$this->_depdb = $dir . DIRECTORY_SEPARATOR . '.depdb';
} else {
$this->_depdb = $depdb;
}
$this->_lockfile = dirname($this->_depdb) . DIRECTORY_SEPARATOR . '.depdblock';
}
// }}}
function hasWriteAccess()
{
if (!file_exists($this->_depdb)) {
$dir = $this->_depdb;
while ($dir && $dir != '.') {
$dir = dirname($dir); // cd ..
if ($dir != '.' && file_exists($dir)) {
if (is_writeable($dir)) {
return true;
}
return false;
}
}
return false;
}
return is_writeable($this->_depdb);
}
// {{{ assertDepsDB()
/**
* Create the dependency database, if it doesn't exist. Error if the database is
* newer than the code reading it.
* @return void|PEAR_Error
*/
function assertDepsDB()
{
if (!is_file($this->_depdb)) {
$this->rebuildDB();
return;
}
$depdb = $this->_getDepDB();
// Datatype format has been changed, rebuild the Deps DB
if ($depdb['_version'] < $this->_version) {
$this->rebuildDB();
}
if ($depdb['_version']{0} > $this->_version{0}) {
return PEAR::raiseError('Dependency database is version ' .
$depdb['_version'] . ', and we are version ' .
$this->_version . ', cannot continue');
}
}
/**
* Get a list of installed packages that depend on this package
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
* @return array|false
*/
function getDependentPackages(&$pkg)
{
$data = $this->_getDepDB();
if (is_object($pkg)) {
$channel = strtolower($pkg->getChannel());
$package = strtolower($pkg->getPackage());
} else {
$channel = strtolower($pkg['channel']);
$package = strtolower($pkg['package']);
}
if (isset($data['packages'][$channel][$package])) {
return $data['packages'][$channel][$package];
}
return false;
}
/**
* Get a list of the actual dependencies of installed packages that depend on
* a package.
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
* @return array|false
*/
function getDependentPackageDependencies(&$pkg)
{
$data = $this->_getDepDB();
if (is_object($pkg)) {
$channel = strtolower($pkg->getChannel());
$package = strtolower($pkg->getPackage());
} else {
$channel = strtolower($pkg['channel']);
$package = strtolower($pkg['package']);
}
$depend = $this->getDependentPackages($pkg);
if (!$depend) {
return false;
}
$dependencies = array();
foreach ($depend as $info) {
$temp = $this->getDependencies($info);
foreach ($temp as $dep) {
if (
isset($dep['dep'], $dep['dep']['channel'], $dep['dep']['name']) &&
strtolower($dep['dep']['channel']) == $channel &&
strtolower($dep['dep']['name']) == $package
) {
if (!isset($dependencies[$info['channel']])) {
$dependencies[$info['channel']] = array();
}
if (!isset($dependencies[$info['channel']][$info['package']])) {
$dependencies[$info['channel']][$info['package']] = array();
}
$dependencies[$info['channel']][$info['package']][] = $dep;
}
}
}
return $dependencies;
}
/**
* Get a list of dependencies of this installed package
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
* @return array|false
*/
function getDependencies(&$pkg)
{
if (is_object($pkg)) {
$channel = strtolower($pkg->getChannel());
$package = strtolower($pkg->getPackage());
} else {
$channel = strtolower($pkg['channel']);
$package = strtolower($pkg['package']);
}
$data = $this->_getDepDB();
if (isset($data['dependencies'][$channel][$package])) {
return $data['dependencies'][$channel][$package];
}
return false;
}
/**
* Determine whether $parent depends on $child, near or deep
* @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
* @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
*/
function dependsOn($parent, $child)
{
$c = array();
$this->_getDepDB();
return $this->_dependsOn($parent, $child, $c);
}
function _dependsOn($parent, $child, &$checked)
{
if (is_object($parent)) {
$channel = strtolower($parent->getChannel());
$package = strtolower($parent->getPackage());
} else {
$channel = strtolower($parent['channel']);
$package = strtolower($parent['package']);
}
if (is_object($child)) {
$depchannel = strtolower($child->getChannel());
$deppackage = strtolower($child->getPackage());
} else {
$depchannel = strtolower($child['channel']);
$deppackage = strtolower($child['package']);
}
if (isset($checked[$channel][$package][$depchannel][$deppackage])) {
return false; // avoid endless recursion
}
$checked[$channel][$package][$depchannel][$deppackage] = true;
if (!isset($this->_cache['dependencies'][$channel][$package])) {
return false;
}
foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
if (isset($info['dep']['uri'])) {
if (is_object($child)) {
if ($info['dep']['uri'] == $child->getURI()) {
return true;
}
} elseif (isset($child['uri'])) {
if ($info['dep']['uri'] == $child['uri']) {
return true;
}
}
return false;
}
if (strtolower($info['dep']['channel']) == $depchannel &&
strtolower($info['dep']['name']) == $deppackage) {
return true;
}
}
foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
if (isset($info['dep']['uri'])) {
if ($this->_dependsOn(array(
'uri' => $info['dep']['uri'],
'package' => $info['dep']['name']), $child, $checked)) {
return true;
}
} else {
if ($this->_dependsOn(array(
'channel' => $info['dep']['channel'],
'package' => $info['dep']['name']), $child, $checked)) {
return true;
}
}
}
return false;
}
/**
* Register dependencies of a package that is being installed or upgraded
* @param PEAR_PackageFile_v2|PEAR_PackageFile_v2
*/
function installPackage(&$package)
{
$data = $this->_getDepDB();
unset($this->_cache);
$this->_setPackageDeps($data, $package);
$this->_writeDepDB($data);
}
/**
* Remove dependencies of a package that is being uninstalled, or upgraded.
*
* Upgraded packages first uninstall, then install
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array If an array, then it must have
* indices 'channel' and 'package'
*/
function uninstallPackage(&$pkg)
{
$data = $this->_getDepDB();
unset($this->_cache);
if (is_object($pkg)) {
$channel = strtolower($pkg->getChannel());
$package = strtolower($pkg->getPackage());
} else {
$channel = strtolower($pkg['channel']);
$package = strtolower($pkg['package']);
}
if (!isset($data['dependencies'][$channel][$package])) {
return true;
}
foreach ($data['dependencies'][$channel][$package] as $dep) {
$found = false;
$depchannel = isset($dep['dep']['uri']) ? '__uri' : strtolower($dep['dep']['channel']);
$depname = strtolower($dep['dep']['name']);
if (isset($data['packages'][$depchannel][$depname])) {
foreach ($data['packages'][$depchannel][$depname] as $i => $info) {
if ($info['channel'] == $channel && $info['package'] == $package) {
$found = true;
break;
}
}
}
if ($found) {
unset($data['packages'][$depchannel][$depname][$i]);
if (!count($data['packages'][$depchannel][$depname])) {
unset($data['packages'][$depchannel][$depname]);
if (!count($data['packages'][$depchannel])) {
unset($data['packages'][$depchannel]);
}
} else {
$data['packages'][$depchannel][$depname] =
array_values($data['packages'][$depchannel][$depname]);
}
}
}
unset($data['dependencies'][$channel][$package]);
if (!count($data['dependencies'][$channel])) {
unset($data['dependencies'][$channel]);
}
if (!count($data['dependencies'])) {
unset($data['dependencies']);
}
if (!count($data['packages'])) {
unset($data['packages']);
}
$this->_writeDepDB($data);
}
/**
* Rebuild the dependency DB by reading registry entries.
* @return true|PEAR_Error
*/
function rebuildDB()
{
$depdb = array('_version' => $this->_version);
if (!$this->hasWriteAccess()) {
// allow startup for read-only with older Registry
return $depdb;
}
$packages = $this->_registry->listAllPackages();
if (PEAR::isError($packages)) {
return $packages;
}
foreach ($packages as $channel => $ps) {
foreach ($ps as $package) {
$package = $this->_registry->getPackage($package, $channel);
if (PEAR::isError($package)) {
return $package;
}
$this->_setPackageDeps($depdb, $package);
}
}
$error = $this->_writeDepDB($depdb);
if (PEAR::isError($error)) {
return $error;
}
$this->_cache = $depdb;
return true;
}
/**
* Register usage of the dependency DB to prevent race conditions
* @param int one of the LOCK_* constants
* @return true|PEAR_Error
* @access private
*/
function _lock($mode = LOCK_EX)
{
if (stristr(php_uname(), 'Windows 9')) {
return true;
}
if ($mode != LOCK_UN && is_resource($this->_lockFp)) {
// XXX does not check type of lock (LOCK_SH/LOCK_EX)
return true;
}
$open_mode = 'w';
// XXX People reported problems with LOCK_SH and 'w'
if ($mode === LOCK_SH) {
if (!file_exists($this->_lockfile)) {
touch($this->_lockfile);
} elseif (!is_file($this->_lockfile)) {
return PEAR::raiseError('could not create Dependency lock file, ' .
'it exists and is not a regular file');
}
$open_mode = 'r';
}
if (!is_resource($this->_lockFp)) {
$this->_lockFp = @fopen($this->_lockfile, $open_mode);
}
if (!is_resource($this->_lockFp)) {
return PEAR::raiseError("could not create Dependency lock file" .
(isset($php_errormsg) ? ": " . $php_errormsg : ""));
}
if (!(int)flock($this->_lockFp, $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;
}
return PEAR::raiseError("could not acquire $str lock ($this->_lockfile)");
}
return true;
}
/**
* Release usage of dependency DB
* @return true|PEAR_Error
* @access private
*/
function _unlock()
{
$ret = $this->_lock(LOCK_UN);
if (is_resource($this->_lockFp)) {
fclose($this->_lockFp);
}
$this->_lockFp = null;
return $ret;
}
/**
* Load the dependency database from disk, or return the cache
* @return array|PEAR_Error
*/
function _getDepDB()
{
if (!$this->hasWriteAccess()) {
return array('_version' => $this->_version);
}
if (isset($this->_cache)) {
return $this->_cache;
}
if (!$fp = fopen($this->_depdb, 'r')) {
$err = PEAR::raiseError("Could not open dependencies file `".$this->_depdb."'");
return $err;
}
clearstatcache();
fclose($fp);
$data = unserialize(file_get_contents($this->_depdb));
$this->_cache = $data;
return $data;
}
/**
* Write out the dependency database to disk
* @param array the database
* @return true|PEAR_Error
* @access private
*/
function _writeDepDB(&$deps)
{
if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
return $e;
}
if (!$fp = fopen($this->_depdb, 'wb')) {
$this->_unlock();
return PEAR::raiseError("Could not open dependencies file `".$this->_depdb."' for writing");
}
fwrite($fp, serialize($deps));
fclose($fp);
$this->_unlock();
$this->_cache = $deps;
return true;
}
/**
* Register all dependencies from a package in the dependencies database, in essence
* "installing" the package's dependency information
* @param array the database
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @access private
*/
function _setPackageDeps(&$data, &$pkg)
{
$pkg->setConfig($this->_config);
if ($pkg->getPackagexmlVersion() == '1.0') {
$gen = &$pkg->getDefaultGenerator();
$deps = $gen->dependenciesToV2();
} else {
$deps = $pkg->getDeps(true);
}
if (!$deps) {
return;
}
if (!is_array($data)) {
$data = array();
}
if (!isset($data['dependencies'])) {
$data['dependencies'] = array();
}
$channel = strtolower($pkg->getChannel());
$package = strtolower($pkg->getPackage());
if (!isset($data['dependencies'][$channel])) {
$data['dependencies'][$channel] = array();
}
$data['dependencies'][$channel][$package] = array();
if (isset($deps['required']['package'])) {
if (!isset($deps['required']['package'][0])) {
$deps['required']['package'] = array($deps['required']['package']);
}
foreach ($deps['required']['package'] as $dep) {
$this->_registerDep($data, $pkg, $dep, 'required');
}
}
if (isset($deps['optional']['package'])) {
if (!isset($deps['optional']['package'][0])) {
$deps['optional']['package'] = array($deps['optional']['package']);
}
foreach ($deps['optional']['package'] as $dep) {
$this->_registerDep($data, $pkg, $dep, 'optional');
}
}
if (isset($deps['required']['subpackage'])) {
if (!isset($deps['required']['subpackage'][0])) {
$deps['required']['subpackage'] = array($deps['required']['subpackage']);
}
foreach ($deps['required']['subpackage'] as $dep) {
$this->_registerDep($data, $pkg, $dep, 'required');
}
}
if (isset($deps['optional']['subpackage'])) {
if (!isset($deps['optional']['subpackage'][0])) {
$deps['optional']['subpackage'] = array($deps['optional']['subpackage']);
}
foreach ($deps['optional']['subpackage'] as $dep) {
$this->_registerDep($data, $pkg, $dep, 'optional');
}
}
if (isset($deps['group'])) {
if (!isset($deps['group'][0])) {
$deps['group'] = array($deps['group']);
}
foreach ($deps['group'] as $group) {
if (isset($group['package'])) {
if (!isset($group['package'][0])) {
$group['package'] = array($group['package']);
}
foreach ($group['package'] as $dep) {
$this->_registerDep($data, $pkg, $dep, 'optional',
$group['attribs']['name']);
}
}
if (isset($group['subpackage'])) {
if (!isset($group['subpackage'][0])) {
$group['subpackage'] = array($group['subpackage']);
}
foreach ($group['subpackage'] as $dep) {
$this->_registerDep($data, $pkg, $dep, 'optional',
$group['attribs']['name']);
}
}
}
}
if ($data['dependencies'][$channel][$package] == array()) {
unset($data['dependencies'][$channel][$package]);
if (!count($data['dependencies'][$channel])) {
unset($data['dependencies'][$channel]);
}
}
}
/**
* @param array the database
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @param array the specific dependency
* @param required|optional whether this is a required or an optional dep
* @param string|false dependency group this dependency is from, or false for ordinary dep
*/
function _registerDep(&$data, &$pkg, $dep, $type, $group = false)
{
$info = array(
'dep' => $dep,
'type' => $type,
'group' => $group
);
$dep = array_map('strtolower', $dep);
$depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
if (!isset($data['dependencies'])) {
$data['dependencies'] = array();
}
$channel = strtolower($pkg->getChannel());
$package = strtolower($pkg->getPackage());
if (!isset($data['dependencies'][$channel])) {
$data['dependencies'][$channel] = array();
}
if (!isset($data['dependencies'][$channel][$package])) {
$data['dependencies'][$channel][$package] = array();
}
$data['dependencies'][$channel][$package][] = $info;
if (isset($data['packages'][$depchannel][$dep['name']])) {
$found = false;
foreach ($data['packages'][$depchannel][$dep['name']] as $i => $p) {
if ($p['channel'] == $channel && $p['package'] == $package) {
$found = true;
break;
}
}
} else {
if (!isset($data['packages'])) {
$data['packages'] = array();
}
if (!isset($data['packages'][$depchannel])) {
$data['packages'][$depchannel] = array();
}
if (!isset($data['packages'][$depchannel][$dep['name']])) {
$data['packages'][$depchannel][$dep['name']] = array();
}
$found = false;
}
if (!$found) {
$data['packages'][$depchannel][$dep['name']][] = array(
'channel' => $channel,
'package' => $package
);
}
}
}
PK [Ml6 l6 PEAR/Exception.phpnu W+A
* @author Hans Lellelid
* @author Bertrand Mansion
* @author Greg Beaver
* @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.3.3
*/
/**
* Base PEAR_Exception Class
*
* 1) Features:
*
* - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception))
* - Definable triggers, shot when exceptions occur
* - Pretty and informative error messages
* - Added more context info available (like class, method or cause)
* - cause can be a PEAR_Exception or an array of mixed
* PEAR_Exceptions/PEAR_ErrorStack warnings
* - callbacks for specific exception classes and their children
*
* 2) Ideas:
*
* - Maybe a way to define a 'template' for the output
*
* 3) Inherited properties from PHP Exception Class:
*
* protected $message
* protected $code
* protected $line
* protected $file
* private $trace
*
* 4) Inherited methods from PHP Exception Class:
*
* __clone
* __construct
* getMessage
* getCode
* getFile
* getLine
* getTraceSafe
* getTraceSafeAsString
* __toString
*
* 5) Usage example
*
*
* require_once 'PEAR/Exception.php';
*
* class Test {
* function foo() {
* throw new PEAR_Exception('Error Message', ERROR_CODE);
* }
* }
*
* function myLogger($pear_exception) {
* echo $pear_exception->getMessage();
* }
* // each time a exception is thrown the 'myLogger' will be called
* // (its use is completely optional)
* PEAR_Exception::addObserver('myLogger');
* $test = new Test;
* try {
* $test->foo();
* } catch (PEAR_Exception $e) {
* print $e;
* }
*
*
* @category pear
* @package PEAR
* @author Tomas V.V.Cox
* @author Hans Lellelid
* @author Bertrand Mansion
* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.3.3
*
*/
class PEAR_Exception extends Exception
{
const OBSERVER_PRINT = -2;
const OBSERVER_TRIGGER = -4;
const OBSERVER_DIE = -8;
protected $cause;
private static $_observers = array();
private static $_uniqueid = 0;
private $_trace;
/**
* Supported signatures:
* - PEAR_Exception(string $message);
* - PEAR_Exception(string $message, int $code);
* - PEAR_Exception(string $message, Exception $cause);
* - PEAR_Exception(string $message, Exception $cause, int $code);
* - PEAR_Exception(string $message, PEAR_Error $cause);
* - PEAR_Exception(string $message, PEAR_Error $cause, int $code);
* - PEAR_Exception(string $message, array $causes);
* - PEAR_Exception(string $message, array $causes, int $code);
* @param string exception message
* @param int|Exception|PEAR_Error|array|null exception cause
* @param int|null exception code or null
*/
public function __construct($message, $p2 = null, $p3 = null)
{
if (is_int($p2)) {
$code = $p2;
$this->cause = null;
} elseif (is_object($p2) || is_array($p2)) {
// using is_object allows both Exception and PEAR_Error
if (is_object($p2) && !($p2 instanceof Exception)) {
if (!class_exists('PEAR_Error') || !($p2 instanceof PEAR_Error)) {
throw new PEAR_Exception('exception cause must be Exception, ' .
'array, or PEAR_Error');
}
}
$code = $p3;
if (is_array($p2) && isset($p2['message'])) {
// fix potential problem of passing in a single warning
$p2 = array($p2);
}
$this->cause = $p2;
} else {
$code = null;
$this->cause = null;
}
parent::__construct($message, $code);
$this->signal();
}
/**
* @param mixed $callback - A valid php callback, see php func is_callable()
* - A PEAR_Exception::OBSERVER_* constant
* - An array(const PEAR_Exception::OBSERVER_*,
* mixed $options)
* @param string $label The name of the observer. Use this if you want
* to remove it later with removeObserver()
*/
public static function addObserver($callback, $label = 'default')
{
self::$_observers[$label] = $callback;
}
public static function removeObserver($label = 'default')
{
unset(self::$_observers[$label]);
}
/**
* @return int unique identifier for an observer
*/
public static function getUniqueId()
{
return self::$_uniqueid++;
}
private function signal()
{
foreach (self::$_observers as $func) {
if (is_callable($func)) {
call_user_func($func, $this);
continue;
}
settype($func, 'array');
switch ($func[0]) {
case self::OBSERVER_PRINT :
$f = (isset($func[1])) ? $func[1] : '%s';
printf($f, $this->getMessage());
break;
case self::OBSERVER_TRIGGER :
$f = (isset($func[1])) ? $func[1] : E_USER_NOTICE;
trigger_error($this->getMessage(), $f);
break;
case self::OBSERVER_DIE :
$f = (isset($func[1])) ? $func[1] : '%s';
die(printf($f, $this->getMessage()));
break;
default:
trigger_error('invalid observer type', E_USER_WARNING);
}
}
}
/**
* Return specific error information that can be used for more detailed
* error messages or translation.
*
* This method may be overridden in child exception classes in order
* to add functionality not present in PEAR_Exception and is a placeholder
* to define API
*
* The returned array must be an associative array of parameter => value like so:
*
* array('name' => $name, 'context' => array(...))
*
* @return array
*/
public function getErrorData()
{
return array();
}
/**
* Returns the exception that caused this exception to be thrown
* @access public
* @return Exception|array The context of the exception
*/
public function getCause()
{
return $this->cause;
}
/**
* Function must be public to call on caused exceptions
* @param array
*/
public function getCauseMessage(&$causes)
{
$trace = $this->getTraceSafe();
$cause = array('class' => get_class($this),
'message' => $this->message,
'file' => 'unknown',
'line' => 'unknown');
if (isset($trace[0])) {
if (isset($trace[0]['file'])) {
$cause['file'] = $trace[0]['file'];
$cause['line'] = $trace[0]['line'];
}
}
$causes[] = $cause;
if ($this->cause instanceof PEAR_Exception) {
$this->cause->getCauseMessage($causes);
} elseif ($this->cause instanceof Exception) {
$causes[] = array('class' => get_class($this->cause),
'message' => $this->cause->getMessage(),
'file' => $this->cause->getFile(),
'line' => $this->cause->getLine());
} elseif (class_exists('PEAR_Error') && $this->cause instanceof PEAR_Error) {
$causes[] = array('class' => get_class($this->cause),
'message' => $this->cause->getMessage(),
'file' => 'unknown',
'line' => 'unknown');
} elseif (is_array($this->cause)) {
foreach ($this->cause as $cause) {
if ($cause instanceof PEAR_Exception) {
$cause->getCauseMessage($causes);
} elseif ($cause instanceof Exception) {
$causes[] = array('class' => get_class($cause),
'message' => $cause->getMessage(),
'file' => $cause->getFile(),
'line' => $cause->getLine());
} elseif (class_exists('PEAR_Error') && $cause instanceof PEAR_Error) {
$causes[] = array('class' => get_class($cause),
'message' => $cause->getMessage(),
'file' => 'unknown',
'line' => 'unknown');
} elseif (is_array($cause) && isset($cause['message'])) {
// PEAR_ErrorStack warning
$causes[] = array(
'class' => $cause['package'],
'message' => $cause['message'],
'file' => isset($cause['context']['file']) ?
$cause['context']['file'] :
'unknown',
'line' => isset($cause['context']['line']) ?
$cause['context']['line'] :
'unknown',
);
}
}
}
}
public function getTraceSafe()
{
if (!isset($this->_trace)) {
$this->_trace = $this->getTrace();
if (empty($this->_trace)) {
$backtrace = debug_backtrace();
$this->_trace = array($backtrace[count($backtrace)-1]);
}
}
return $this->_trace;
}
public function getErrorClass()
{
$trace = $this->getTraceSafe();
return $trace[0]['class'];
}
public function getErrorMethod()
{
$trace = $this->getTraceSafe();
return $trace[0]['function'];
}
public function __toString()
{
if (isset($_SERVER['REQUEST_URI'])) {
return $this->toHtml();
}
return $this->toText();
}
public function toHtml()
{
$trace = $this->getTraceSafe();
$causes = array();
$this->getCauseMessage($causes);
$html = '' . "\n";
foreach ($causes as $i => $cause) {
$html .= ''
. str_repeat('-', $i) . ' ' . $cause['class'] . ': '
. htmlspecialchars($cause['message']) . ' in ' . $cause['file'] . ' '
. 'on line ' . $cause['line'] . ''
. " |
\n";
}
$html .= 'Exception trace |
' . "\n"
. '# | '
. 'Function | '
. 'Location |
' . "\n";
foreach ($trace as $k => $v) {
$html .= '' . $k . ' | '
. '';
if (!empty($v['class'])) {
$html .= $v['class'] . $v['type'];
}
$html .= $v['function'];
$args = array();
if (!empty($v['args'])) {
foreach ($v['args'] as $arg) {
if (is_null($arg)) $args[] = 'null';
elseif (is_array($arg)) $args[] = 'Array';
elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')';
elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false';
elseif (is_int($arg) || is_double($arg)) $args[] = $arg;
else {
$arg = (string)$arg;
$str = htmlspecialchars(substr($arg, 0, 16));
if (strlen($arg) > 16) $str .= '…';
$args[] = "'" . $str . "'";
}
}
}
$html .= '(' . implode(', ',$args) . ')'
. ' | '
. '' . (isset($v['file']) ? $v['file'] : 'unknown')
. ':' . (isset($v['line']) ? $v['line'] : 'unknown')
. ' |
' . "\n";
}
$html .= '' . ($k+1) . ' | '
. '{main} | '
. ' |
' . "\n"
. '
';
return $html;
}
public function toText()
{
$causes = array();
$this->getCauseMessage($causes);
$causeMsg = '';
foreach ($causes as $i => $cause) {
$causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': '
. $cause['message'] . ' in ' . $cause['file']
. ' on line ' . $cause['line'] . "\n";
}
return $causeMsg . $this->getTraceAsString();
}
}PK [_oA A
PEAR/REST.phpnu W+A
* @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
*/
/**
* For downloading xml files
*/
require_once 'PEAR.php';
require_once 'PEAR/XMLParser.php';
require_once 'PEAR/Proxy.php';
/**
* Intelligently retrieve data, following hyperlinks if necessary, and re-directing
* as well
* @category pear
* @package PEAR
* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_REST
{
var $config;
var $_options;
function __construct(&$config, $options = array())
{
$this->config = &$config;
$this->_options = $options;
}
/**
* Retrieve REST data, but always retrieve the local cache if it is available.
*
* This is useful for elements that should never change, such as information on a particular
* release
* @param string full URL to this resource
* @param array|false contents of the accept-encoding header
* @param boolean if true, xml will be returned as a string, otherwise, xml will be
* parsed using PEAR_XMLParser
* @return string|array
*/
function retrieveCacheFirst($url, $accept = false, $forcestring = false, $channel = false)
{
$cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
md5($url) . 'rest.cachefile';
if (file_exists($cachefile)) {
return unserialize(implode('', file($cachefile)));
}
return $this->retrieveData($url, $accept, $forcestring, $channel);
}
/**
* Retrieve a remote REST resource
* @param string full URL to this resource
* @param array|false contents of the accept-encoding header
* @param boolean if true, xml will be returned as a string, otherwise, xml will be
* parsed using PEAR_XMLParser
* @return string|array
*/
function retrieveData($url, $accept = false, $forcestring = false, $channel = false)
{
$cacheId = $this->getCacheId($url);
if ($ret = $this->useLocalCache($url, $cacheId)) {
return $ret;
}
$file = $trieddownload = false;
if (!isset($this->_options['offline'])) {
$trieddownload = true;
$file = $this->downloadHttp($url, $cacheId ? $cacheId['lastChange'] : false, $accept, $channel);
}
if (PEAR::isError($file)) {
if ($file->getCode() !== -9276) {
return $file;
}
$trieddownload = false;
$file = false; // use local copy if available on socket connect error
}
if (!$file) {
$ret = $this->getCache($url);
if (!PEAR::isError($ret) && $trieddownload) {
// reset the age of the cache if the server says it was unmodified
$result = $this->saveCache($url, $ret, null, true, $cacheId);
if (PEAR::isError($result)) {
return PEAR::raiseError($result->getMessage());
}
}
return $ret;
}
if (is_array($file)) {
$headers = $file[2];
$lastmodified = $file[1];
$content = $file[0];
} else {
$headers = array();
$lastmodified = false;
$content = $file;
}
if ($forcestring) {
$result = $this->saveCache($url, $content, $lastmodified, false, $cacheId);
if (PEAR::isError($result)) {
return PEAR::raiseError($result->getMessage());
}
return $content;
}
if (isset($headers['content-type'])) {
$content_type = explode(";", $headers['content-type']);
$content_type = $content_type[0];
switch ($content_type) {
case 'text/xml' :
case 'application/xml' :
case 'text/plain' :
if ($content_type === 'text/plain') {
$check = substr($content, 0, 5);
if ($check !== 'parse($content);
PEAR::popErrorHandling();
if (PEAR::isError($err)) {
return PEAR::raiseError('Invalid xml downloaded from "' . $url . '": ' .
$err->getMessage());
}
$content = $parser->getData();
case 'text/html' :
default :
// use it as a string
}
} else {
// assume XML
$parser = new PEAR_XMLParser;
$parser->parse($content);
$content = $parser->getData();
}
$result = $this->saveCache($url, $content, $lastmodified, false, $cacheId);
if (PEAR::isError($result)) {
return PEAR::raiseError($result->getMessage());
}
return $content;
}
function useLocalCache($url, $cacheid = null)
{
if ($cacheid === null) {
$cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
md5($url) . 'rest.cacheid';
if (!file_exists($cacheidfile)) {
return false;
}
$cacheid = unserialize(implode('', file($cacheidfile)));
}
$cachettl = $this->config->get('cache_ttl');
// If cache is newer than $cachettl seconds, we use the cache!
if (time() - $cacheid['age'] < $cachettl) {
return $this->getCache($url);
}
return false;
}
function getCacheId($url)
{
$cacheidfile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
md5($url) . 'rest.cacheid';
if (!file_exists($cacheidfile)) {
return false;
}
$ret = unserialize(implode('', file($cacheidfile)));
return $ret;
}
function getCache($url)
{
$cachefile = $this->config->get('cache_dir') . DIRECTORY_SEPARATOR .
md5($url) . 'rest.cachefile';
if (!file_exists($cachefile)) {
return PEAR::raiseError('No cached content available for "' . $url . '"');
}
return unserialize(implode('', file($cachefile)));
}
/**
* @param string full URL to REST resource
* @param string original contents of the REST resource
* @param array HTTP Last-Modified and ETag headers
* @param bool if true, then the cache id file should be regenerated to
* trigger a new time-to-live value
*/
function saveCache($url, $contents, $lastmodified, $nochange = false, $cacheid = null)
{
$cache_dir = $this->config->get('cache_dir');
$d = $cache_dir . DIRECTORY_SEPARATOR . md5($url);
$cacheidfile = $d . 'rest.cacheid';
$cachefile = $d . 'rest.cachefile';
if (!is_dir($cache_dir)) {
if (System::mkdir(array('-p', $cache_dir)) === false) {
return PEAR::raiseError("The value of config option cache_dir ($cache_dir) is not a directory and attempts to create the directory failed.");
}
}
if (!is_writeable($cache_dir)) {
// If writing to the cache dir is not going to work, silently do nothing.
// An ugly hack, but retains compat with PEAR 1.9.1 where many commands
// work fine as non-root user (w/out write access to default cache dir).
return true;
}
if ($cacheid === null && $nochange) {
$cacheid = unserialize(implode('', file($cacheidfile)));
}
$idData = serialize(array(
'age' => time(),
'lastChange' => ($nochange ? $cacheid['lastChange'] : $lastmodified),
));
$result = $this->saveCacheFile($cacheidfile, $idData);
if (PEAR::isError($result)) {
return $result;
} elseif ($nochange) {
return true;
}
$result = $this->saveCacheFile($cachefile, serialize($contents));
if (PEAR::isError($result)) {
if (file_exists($cacheidfile)) {
@unlink($cacheidfile);
}
return $result;
}
return true;
}
function saveCacheFile($file, $contents)
{
$len = strlen($contents);
$cachefile_fp = @fopen($file, 'xb'); // x is the O_CREAT|O_EXCL mode
if ($cachefile_fp !== false) { // create file
if (fwrite($cachefile_fp, $contents, $len) < $len) {
fclose($cachefile_fp);
return PEAR::raiseError("Could not write $file.");
}
} else { // update file
$cachefile_fp = @fopen($file, 'r+b'); // do not truncate file
if (!$cachefile_fp) {
return PEAR::raiseError("Could not open $file for writing.");
}
if (OS_WINDOWS) {
$not_symlink = !is_link($file); // see bug #18834
} else {
$cachefile_lstat = lstat($file);
$cachefile_fstat = fstat($cachefile_fp);
$not_symlink = $cachefile_lstat['mode'] == $cachefile_fstat['mode']
&& $cachefile_lstat['ino'] == $cachefile_fstat['ino']
&& $cachefile_lstat['dev'] == $cachefile_fstat['dev']
&& $cachefile_fstat['nlink'] === 1;
}
if ($not_symlink) {
ftruncate($cachefile_fp, 0); // NOW truncate
if (fwrite($cachefile_fp, $contents, $len) < $len) {
fclose($cachefile_fp);
return PEAR::raiseError("Could not write $file.");
}
} else {
fclose($cachefile_fp);
$link = function_exists('readlink') ? readlink($file) : $file;
return PEAR::raiseError('SECURITY ERROR: Will not write to ' . $file . ' as it is symlinked to ' . $link . ' - Possible symlink attack');
}
}
fclose($cachefile_fp);
return true;
}
/**
* Efficiently Download a file through HTTP. Returns downloaded file as a string in-memory
* This is best used for small files
*
* If an HTTP proxy has been configured (http_proxy PEAR_Config
* setting), the proxy will be used.
*
* @param string $url the URL to download
* @param string $save_dir directory to save file in
* @param false|string|array $lastmodified header values to check against for caching
* use false to return the header values from this download
* @param false|array $accept Accept headers to send
* @return string|array Returns the contents of the downloaded file or a PEAR
* error on failure. If the error is caused by
* socket-related errors, the error object will
* have the fsockopen error code available through
* getCode(). If caching is requested, then return the header
* values.
*
* @access public
*/
function downloadHttp($url, $lastmodified = null, $accept = false, $channel = false)
{
static $redirect = 0;
// always reset , so we are clean case of error
$wasredirect = $redirect;
$redirect = 0;
$info = parse_url($url);
if (!isset($info['scheme']) || !in_array($info['scheme'], array('http', 'https'))) {
return PEAR::raiseError('Cannot download non-http URL "' . $url . '"');
}
if (!isset($info['host'])) {
return PEAR::raiseError('Cannot download from non-URL "' . $url . '"');
}
$host = isset($info['host']) ? $info['host'] : null;
$port = isset($info['port']) ? $info['port'] : null;
$path = isset($info['path']) ? $info['path'] : null;
$schema = (isset($info['scheme']) && $info['scheme'] == 'https') ? 'https' : 'http';
$proxy = new PEAR_Proxy($this->config);
if (empty($port)) {
$port = (isset($info['scheme']) && $info['scheme'] == 'https') ? 443 : 80;
}
if ($proxy->isProxyConfigured() && $schema === 'http') {
$request = "GET $url HTTP/1.1\r\n";
} else {
$request = "GET $path HTTP/1.1\r\n";
}
$request .= "Host: $host\r\n";
$ifmodifiedsince = '';
if (is_array($lastmodified)) {
if (isset($lastmodified['Last-Modified'])) {
$ifmodifiedsince = 'If-Modified-Since: ' . $lastmodified['Last-Modified'] . "\r\n";
}
if (isset($lastmodified['ETag'])) {
$ifmodifiedsince .= "If-None-Match: $lastmodified[ETag]\r\n";
}
} else {
$ifmodifiedsince = ($lastmodified ? "If-Modified-Since: $lastmodified\r\n" : '');
}
$request .= $ifmodifiedsince .
"User-Agent: PEAR/1.10.4/PHP/" . PHP_VERSION . "\r\n";
$username = $this->config->get('username', null, $channel);
$password = $this->config->get('password', null, $channel);
if ($username && $password) {
$tmp = base64_encode("$username:$password");
$request .= "Authorization: Basic $tmp\r\n";
}
$proxyAuth = $proxy->getProxyAuth();
if ($proxyAuth) {
$request .= 'Proxy-Authorization: Basic ' .
$proxyAuth . "\r\n";
}
if ($accept) {
$request .= 'Accept: ' . implode(', ', $accept) . "\r\n";
}
$request .= "Accept-Encoding:\r\n";
$request .= "Connection: close\r\n";
$request .= "\r\n";
$secure = ($schema == 'https');
$fp = $proxy->openSocket($host, $port, $secure);
if (PEAR::isError($fp)) {
return $fp;
}
fwrite($fp, $request);
$headers = array();
$reply = 0;
while ($line = trim(fgets($fp, 1024))) {
if (preg_match('/^([^:]+):\s+(.*)\s*\\z/', $line, $matches)) {
$headers[strtolower($matches[1])] = trim($matches[2]);
} elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) {
$reply = (int)$matches[1];
if ($reply == 304 && ($lastmodified || ($lastmodified === false))) {
return false;
}
if (!in_array($reply, array(200, 301, 302, 303, 305, 307))) {
return PEAR::raiseError("File $schema://$host:$port$path not valid (received: $line)");
}
}
}
if ($reply != 200) {
if (!isset($headers['location'])) {
return PEAR::raiseError("File $schema://$host:$port$path not valid (redirected but no location)");
}
if ($wasredirect > 4) {
return PEAR::raiseError("File $schema://$host:$port$path not valid (redirection looped more than 5 times)");
}
$redirect = $wasredirect + 1;
return $this->downloadHttp($headers['location'], $lastmodified, $accept, $channel);
}
$length = isset($headers['content-length']) ? $headers['content-length'] : -1;
$data = '';
while ($chunk = @fread($fp, 8192)) {
$data .= $chunk;
}
fclose($fp);
if ($lastmodified === false || $lastmodified) {
if (isset($headers['etag'])) {
$lastmodified = array('ETag' => $headers['etag']);
}
if (isset($headers['last-modified'])) {
if (is_array($lastmodified)) {
$lastmodified['Last-Modified'] = $headers['last-modified'];
} else {
$lastmodified = $headers['last-modified'];
}
}
return array($data, $lastmodified, $headers);
}
return $data;
}
}
PK [y:. PEAR/Installer/Role/Doc.phpnu W+A
* @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
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @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 [B] PEAR/Installer/Role/Test.xmlnu W+A
php
extsrc
extbin
zendextsrc
zendextbin
1
test_dir
PK [h&P* PEAR/Installer/Role/Doc.xmlnu W+A
php
extsrc
extbin
zendextsrc
zendextbin
1
doc_dir
PK [>1H PEAR/Installer/Role/Www.xmlnu W+A
php
extsrc
extbin
zendextsrc
zendextbin
1
www_dir
1
PK [7P PEAR/Installer/Role/Php.phpnu W+A
* @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
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @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 [ Zg PEAR/Installer/Role/Www.phpnu W+A
* @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
* @copyright 2007-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @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 [zq PEAR/Installer/Role/Php.xmlnu W+A
php
extsrc
extbin
zendextsrc
zendextbin
1
php_dir
1
1
PK [@vа PEAR/Installer/Role/Script.xmlnu W+A
php
extsrc
extbin
zendextsrc
zendextbin
1
bin_dir
1
1
PK [d^q q PEAR/Installer/Role/Src.phpnu W+A
* @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
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @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 [fsz PEAR/Installer/Role/Data.xmlnu W+A
php
extsrc
extbin
zendextsrc
zendextbin
1
data_dir
PK [8P PEAR/Installer/Role/Test.phpnu W+A
* @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
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @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 [B B PEAR/Installer/Role/Ext.xmlnu W+A
extbin
zendextbin
1
ext_dir
1
1
PK [zx~ ~ PEAR/Installer/Role/Cfg.phpnu W+A
* @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
* @copyright 2007-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @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 [ކ PEAR/Installer/Role/Script.phpnu W+A
* @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
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @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 [c$ $ PEAR/Installer/Role/Man.phpnu W+A
* @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
* @copyright 2011 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @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 [0c PEAR/Installer/Role/Man.xmlnu W+A
php
extsrc
extbin
zendextsrc
zendextbin
1
man_dir
1
PK [s PEAR/Installer/Role/Ext.phpnu W+A
* @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
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @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 [NĂ PEAR/Installer/Role/Data.phpnu W+A
* @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
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @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 [/ PEAR/Installer/Role/Cfg.xmlnu W+A
php
extsrc
extbin
zendextsrc
zendextbin
1
cfg_dir
1
PK [p" " PEAR/Installer/Role/Src.xmlnu W+A
extsrc
zendextsrc
1
temp_dir
PK [A$F F PEAR/Installer/Role/Common.phpnu W+A
* @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
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @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 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 [G d, PEAR/Installer/Role.phpnu W+A
* @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
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @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 [
y U U PEAR/Validate.phpnu W+A
* @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
*/
/**#@+
* Constants for install stage
*/
define('PEAR_VALIDATE_INSTALLING', 1);
define('PEAR_VALIDATE_UNINSTALLING', 2); // this is not bit-mapped like the others
define('PEAR_VALIDATE_NORMAL', 3);
define('PEAR_VALIDATE_DOWNLOADING', 4); // this is not bit-mapped like the others
define('PEAR_VALIDATE_PACKAGING', 7);
/**#@-*/
require_once 'PEAR/Common.php';
require_once 'PEAR/Validator/PECL.php';
/**
* Validation class for package.xml - channel-level advanced validation
* @category pear
* @package PEAR
* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Validate
{
var $packageregex = _PEAR_COMMON_PACKAGE_NAME_PREG;
/**
* @var PEAR_PackageFile_v1|PEAR_PackageFile_v2
*/
var $_packagexml;
/**
* @var int one of the PEAR_VALIDATE_* constants
*/
var $_state = PEAR_VALIDATE_NORMAL;
/**
* Format: ('error' => array('field' => name, 'reason' => reason), 'warning' => same)
* @var array
* @access private
*/
var $_failures = array('error' => array(), 'warning' => array());
/**
* Override this method to handle validation of normal package names
* @param string
* @return bool
* @access protected
*/
function _validPackageName($name)
{
return (bool) preg_match('/^' . $this->packageregex . '\\z/', $name);
}
/**
* @param string package name to validate
* @param string name of channel-specific validation package
* @final
*/
function validPackageName($name, $validatepackagename = false)
{
if ($validatepackagename) {
if (strtolower($name) == strtolower($validatepackagename)) {
return (bool) preg_match('/^[a-zA-Z0-9_]+(?:\.[a-zA-Z0-9_]+)*\\z/', $name);
}
}
return $this->_validPackageName($name);
}
/**
* This validates a bundle name, and bundle names must conform
* to the PEAR naming convention, so the method is final and static.
* @param string
* @final
*/
public static function validGroupName($name)
{
return (bool) preg_match('/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '\\z/', $name);
}
/**
* Determine whether $state represents a valid stability level
* @param string
* @return bool
* @final
*/
public static function validState($state)
{
return in_array($state, array('snapshot', 'devel', 'alpha', 'beta', 'stable'));
}
/**
* Get a list of valid stability levels
* @return array
* @final
*/
public static function getValidStates()
{
return array('snapshot', 'devel', 'alpha', 'beta', 'stable');
}
/**
* Determine whether a version is a properly formatted version number that can be used
* by version_compare
* @param string
* @return bool
* @final
*/
public static function validVersion($ver)
{
return (bool) preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver);
}
/**
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
*/
function setPackageFile(&$pf)
{
$this->_packagexml = &$pf;
}
/**
* @access private
*/
function _addFailure($field, $reason)
{
$this->_failures['errors'][] = array('field' => $field, 'reason' => $reason);
}
/**
* @access private
*/
function _addWarning($field, $reason)
{
$this->_failures['warnings'][] = array('field' => $field, 'reason' => $reason);
}
function getFailures()
{
$failures = $this->_failures;
$this->_failures = array('warnings' => array(), 'errors' => array());
return $failures;
}
/**
* @param int one of the PEAR_VALIDATE_* constants
*/
function validate($state = null)
{
if (!isset($this->_packagexml)) {
return false;
}
if ($state !== null) {
$this->_state = $state;
}
$this->_failures = array('warnings' => array(), 'errors' => array());
$this->validatePackageName();
$this->validateVersion();
$this->validateMaintainers();
$this->validateDate();
$this->validateSummary();
$this->validateDescription();
$this->validateLicense();
$this->validateNotes();
if ($this->_packagexml->getPackagexmlVersion() == '1.0') {
$this->validateState();
$this->validateFilelist();
} elseif ($this->_packagexml->getPackagexmlVersion() == '2.0' ||
$this->_packagexml->getPackagexmlVersion() == '2.1') {
$this->validateTime();
$this->validateStability();
$this->validateDeps();
$this->validateMainFilelist();
$this->validateReleaseFilelist();
//$this->validateGlobalTasks();
$this->validateChangelog();
}
return !((bool) count($this->_failures['errors']));
}
/**
* @access protected
*/
function validatePackageName()
{
if ($this->_state == PEAR_VALIDATE_PACKAGING ||
$this->_state == PEAR_VALIDATE_NORMAL) {
if (($this->_packagexml->getPackagexmlVersion() == '2.0' ||
$this->_packagexml->getPackagexmlVersion() == '2.1') &&
$this->_packagexml->getExtends()) {
$version = $this->_packagexml->getVersion() . '';
$name = $this->_packagexml->getPackage();
$a = explode('.', $version);
$test = array_shift($a);
if ($test == '0') {
return true;
}
$vlen = strlen($test);
$majver = substr($name, strlen($name) - $vlen);
while ($majver && !is_numeric($majver{0})) {
$majver = substr($majver, 1);
}
if ($majver != $test) {
$this->_addWarning('package', "package $name extends package " .
$this->_packagexml->getExtends() . ' and so the name should ' .
'have a postfix equal to the major version like "' .
$this->_packagexml->getExtends() . $test . '"');
return true;
} elseif (substr($name, 0, strlen($name) - $vlen) !=
$this->_packagexml->getExtends()) {
$this->_addWarning('package', "package $name extends package " .
$this->_packagexml->getExtends() . ' and so the name must ' .
'be an extension like "' . $this->_packagexml->getExtends() .
$test . '"');
return true;
}
}
}
if (!$this->validPackageName($this->_packagexml->getPackage())) {
$this->_addFailure('name', 'package name "' .
$this->_packagexml->getPackage() . '" is invalid');
return false;
}
}
/**
* @access protected
*/
function validateVersion()
{
if ($this->_state != PEAR_VALIDATE_PACKAGING) {
if (!$this->validVersion($this->_packagexml->getVersion())) {
$this->_addFailure('version',
'Invalid version number "' . $this->_packagexml->getVersion() . '"');
}
return false;
}
$version = $this->_packagexml->getVersion();
$versioncomponents = explode('.', $version);
if (count($versioncomponents) != 3) {
$this->_addWarning('version',
'A version number should have 3 decimals (x.y.z)');
return true;
}
$name = $this->_packagexml->getPackage();
// version must be based upon state
switch ($this->_packagexml->getState()) {
case 'snapshot' :
return true;
case 'devel' :
if ($versioncomponents[0] . 'a' == '0a') {
return true;
}
if ($versioncomponents[0] == 0) {
$versioncomponents[0] = '0';
$this->_addWarning('version',
'version "' . $version . '" should be "' .
implode('.' ,$versioncomponents) . '"');
} else {
$this->_addWarning('version',
'packages with devel stability must be < version 1.0.0');
}
return true;
break;
case 'alpha' :
case 'beta' :
// check for a package that extends a package,
// like Foo and Foo2
if ($this->_state == PEAR_VALIDATE_PACKAGING) {
if (substr($versioncomponents[2], 1, 2) == 'rc') {
$this->_addFailure('version', 'Release Candidate versions ' .
'must have capital RC, not lower-case rc');
return false;
}
}
if (!$this->_packagexml->getExtends()) {
if ($versioncomponents[0] == '1') {
if ($versioncomponents[2]{0} == '0') {
if ($versioncomponents[2] == '0') {
// version 1.*.0000
$this->_addWarning('version',
'version 1.' . $versioncomponents[1] .
'.0 probably should not be alpha or beta');
return true;
} elseif (strlen($versioncomponents[2]) > 1) {
// version 1.*.0RC1 or 1.*.0beta24 etc.
return true;
} else {
// version 1.*.0
$this->_addWarning('version',
'version 1.' . $versioncomponents[1] .
'.0 probably should not be alpha or beta');
return true;
}
} else {
$this->_addWarning('version',
'bugfix versions (1.3.x where x > 0) probably should ' .
'not be alpha or beta');
return true;
}
} elseif ($versioncomponents[0] != '0') {
$this->_addWarning('version',
'major versions greater than 1 are not allowed for packages ' .
'without an tag or an identical postfix (foo2 v2.0.0)');
return true;
}
if ($versioncomponents[0] . 'a' == '0a') {
return true;
}
if ($versioncomponents[0] == 0) {
$versioncomponents[0] = '0';
$this->_addWarning('version',
'version "' . $version . '" should be "' .
implode('.' ,$versioncomponents) . '"');
}
} else {
$vlen = strlen($versioncomponents[0] . '');
$majver = substr($name, strlen($name) - $vlen);
while ($majver && !is_numeric($majver{0})) {
$majver = substr($majver, 1);
}
if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) {
$this->_addWarning('version', 'first version number "' .
$versioncomponents[0] . '" must match the postfix of ' .
'package name "' . $name . '" (' .
$majver . ')');
return true;
}
if ($versioncomponents[0] == $majver) {
if ($versioncomponents[2]{0} == '0') {
if ($versioncomponents[2] == '0') {
// version 2.*.0000
$this->_addWarning('version',
"version $majver." . $versioncomponents[1] .
'.0 probably should not be alpha or beta');
return false;
} elseif (strlen($versioncomponents[2]) > 1) {
// version 2.*.0RC1 or 2.*.0beta24 etc.
return true;
} else {
// version 2.*.0
$this->_addWarning('version',
"version $majver." . $versioncomponents[1] .
'.0 cannot be alpha or beta');
return true;
}
} else {
$this->_addWarning('version',
"bugfix versions ($majver.x.y where y > 0) should " .
'not be alpha or beta');
return true;
}
} elseif ($versioncomponents[0] != '0') {
$this->_addWarning('version',
"only versions 0.x.y and $majver.x.y are allowed for alpha/beta releases");
return true;
}
if ($versioncomponents[0] . 'a' == '0a') {
return true;
}
if ($versioncomponents[0] == 0) {
$versioncomponents[0] = '0';
$this->_addWarning('version',
'version "' . $version . '" should be "' .
implode('.' ,$versioncomponents) . '"');
}
}
return true;
break;
case 'stable' :
if ($versioncomponents[0] == '0') {
$this->_addWarning('version', 'versions less than 1.0.0 cannot ' .
'be stable');
return true;
}
if (!is_numeric($versioncomponents[2])) {
if (preg_match('/\d+(rc|a|alpha|b|beta)\d*/i',
$versioncomponents[2])) {
$this->_addWarning('version', 'version "' . $version . '" or any ' .
'RC/beta/alpha version cannot be stable');
return true;
}
}
// check for a package that extends a package,
// like Foo and Foo2
if ($this->_packagexml->getExtends()) {
$vlen = strlen($versioncomponents[0] . '');
$majver = substr($name, strlen($name) - $vlen);
while ($majver && !is_numeric($majver{0})) {
$majver = substr($majver, 1);
}
if (($versioncomponents[0] != 0) && $majver != $versioncomponents[0]) {
$this->_addWarning('version', 'first version number "' .
$versioncomponents[0] . '" must match the postfix of ' .
'package name "' . $name . '" (' .
$majver . ')');
return true;
}
} elseif ($versioncomponents[0] > 1) {
$this->_addWarning('version', 'major version x in x.y.z may not be greater than ' .
'1 for any package that does not have an tag');
}
return true;
break;
default :
return false;
break;
}
}
/**
* @access protected
*/
function validateMaintainers()
{
// maintainers can only be truly validated server-side for most channels
// but allow this customization for those who wish it
return true;
}
/**
* @access protected
*/
function validateDate()
{
if ($this->_state == PEAR_VALIDATE_NORMAL ||
$this->_state == PEAR_VALIDATE_PACKAGING) {
if (!preg_match('/(\d\d\d\d)\-(\d\d)\-(\d\d)/',
$this->_packagexml->getDate(), $res) ||
count($res) < 4
|| !checkdate($res[2], $res[3], $res[1])
) {
$this->_addFailure('date', 'invalid release date "' .
$this->_packagexml->getDate() . '"');
return false;
}
if ($this->_state == PEAR_VALIDATE_PACKAGING &&
$this->_packagexml->getDate() != date('Y-m-d')) {
$this->_addWarning('date', 'Release Date "' .
$this->_packagexml->getDate() . '" is not today');
}
}
return true;
}
/**
* @access protected
*/
function validateTime()
{
if (!$this->_packagexml->getTime()) {
// default of no time value set
return true;
}
// packager automatically sets time, so only validate if pear validate is called
if ($this->_state = PEAR_VALIDATE_NORMAL) {
if (!preg_match('/\d\d:\d\d:\d\d/',
$this->_packagexml->getTime())) {
$this->_addFailure('time', 'invalid release time "' .
$this->_packagexml->getTime() . '"');
return false;
}
$result = preg_match('|\d{2}\:\d{2}\:\d{2}|', $this->_packagexml->getTime(), $matches);
if ($result === false || empty($matches)) {
$this->_addFailure('time', 'invalid release time "' .
$this->_packagexml->getTime() . '"');
return false;
}
}
return true;
}
/**
* @access protected
*/
function validateState()
{
// this is the closest to "final" php4 can get
if (!PEAR_Validate::validState($this->_packagexml->getState())) {
if (strtolower($this->_packagexml->getState() == 'rc')) {
$this->_addFailure('state', 'RC is not a state, it is a version ' .
'postfix, use ' . $this->_packagexml->getVersion() . 'RC1, state beta');
}
$this->_addFailure('state', 'invalid release state "' .
$this->_packagexml->getState() . '", must be one of: ' .
implode(', ', PEAR_Validate::getValidStates()));
return false;
}
return true;
}
/**
* @access protected
*/
function validateStability()
{
$ret = true;
$packagestability = $this->_packagexml->getState();
$apistability = $this->_packagexml->getState('api');
if (!PEAR_Validate::validState($packagestability)) {
$this->_addFailure('state', 'invalid release stability "' .
$this->_packagexml->getState() . '", must be one of: ' .
implode(', ', PEAR_Validate::getValidStates()));
$ret = false;
}
$apistates = PEAR_Validate::getValidStates();
array_shift($apistates); // snapshot is not allowed
if (!in_array($apistability, $apistates)) {
$this->_addFailure('state', 'invalid API stability "' .
$this->_packagexml->getState('api') . '", must be one of: ' .
implode(', ', $apistates));
$ret = false;
}
return $ret;
}
/**
* @access protected
*/
function validateSummary()
{
return true;
}
/**
* @access protected
*/
function validateDescription()
{
return true;
}
/**
* @access protected
*/
function validateLicense()
{
return true;
}
/**
* @access protected
*/
function validateNotes()
{
return true;
}
/**
* for package.xml 2.0 only - channels can't use package.xml 1.0
* @access protected
*/
function validateDependencies()
{
return true;
}
/**
* for package.xml 1.0 only
* @access private
*/
function _validateFilelist()
{
return true; // placeholder for now
}
/**
* for package.xml 2.0 only
* @access protected
*/
function validateMainFilelist()
{
return true; // placeholder for now
}
/**
* for package.xml 2.0 only
* @access protected
*/
function validateReleaseFilelist()
{
return true; // placeholder for now
}
/**
* @access protected
*/
function validateChangelog()
{
return true;
}
/**
* @access protected
*/
function validateFilelist()
{
return true;
}
/**
* @access protected
*/
function validateDeps()
{
return true;
}
}PK [wKV0 0 PEAR/Command.phpnu W+A
* @author Greg Beaver
* @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
*/
/**
* Needed for error handling
*/
require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/XMLParser.php';
/**
* List of commands and what classes they are implemented in.
* @var array command => implementing class
*/
$GLOBALS['_PEAR_Command_commandlist'] = array();
/**
* List of commands and their descriptions
* @var array command => description
*/
$GLOBALS['_PEAR_Command_commanddesc'] = array();
/**
* List of shortcuts to common commands.
* @var array shortcut => command
*/
$GLOBALS['_PEAR_Command_shortcuts'] = array();
/**
* Array of command objects
* @var array class => object
*/
$GLOBALS['_PEAR_Command_objects'] = array();
/**
* PEAR command class, a simple factory class for administrative
* commands.
*
* How to implement command classes:
*
* - The class must be called PEAR_Command_Nnn, installed in the
* "PEAR/Common" subdir, with a method called getCommands() that
* returns an array of the commands implemented by the class (see
* PEAR/Command/Install.php for an example).
*
* - The class must implement a run() function that is called with three
* params:
*
* (string) command name
* (array) assoc array with options, freely defined by each
* command, for example:
* array('force' => true)
* (array) list of the other parameters
*
* The run() function returns a PEAR_CommandResponse object. Use
* these methods to get information:
*
* int getStatus() Returns PEAR_COMMAND_(SUCCESS|FAILURE|PARTIAL)
* *_PARTIAL means that you need to issue at least
* one more command to complete the operation
* (used for example for validation steps).
*
* string getMessage() Returns a message for the user. Remember,
* no HTML or other interface-specific markup.
*
* If something unexpected happens, run() returns a PEAR error.
*
* - DON'T OUTPUT ANYTHING! Return text for output instead.
*
* - DON'T USE HTML! The text you return will be used from both Gtk,
* web and command-line interfaces, so for now, keep everything to
* plain text.
*
* - DON'T USE EXIT OR DIE! Always use pear errors. From static
* classes do PEAR::raiseError(), from other classes do
* $this->raiseError().
* @category pear
* @package PEAR
* @author Stig Bakken
* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Command
{
// {{{ factory()
/**
* Get the right object for executing a command.
*
* @param string $command The name of the command
* @param object $config Instance of PEAR_Config object
*
* @return object the command object or a PEAR error
*/
public static function &factory($command, &$config)
{
if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
PEAR_Command::registerCommands();
}
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
$command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
}
if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
$a = PEAR::raiseError("unknown command `$command'");
return $a;
}
$class = $GLOBALS['_PEAR_Command_commandlist'][$command];
if (!class_exists($class)) {
require_once $GLOBALS['_PEAR_Command_objects'][$class];
}
if (!class_exists($class)) {
$a = PEAR::raiseError("unknown command `$command'");
return $a;
}
$ui =& PEAR_Command::getFrontendObject();
$obj = new $class($ui, $config);
return $obj;
}
// }}}
// {{{ & getObject()
public static function &getObject($command)
{
$class = $GLOBALS['_PEAR_Command_commandlist'][$command];
if (!class_exists($class)) {
require_once $GLOBALS['_PEAR_Command_objects'][$class];
}
if (!class_exists($class)) {
return PEAR::raiseError("unknown command `$command'");
}
$ui =& PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton();
$obj = new $class($ui, $config);
return $obj;
}
// }}}
// {{{ & getFrontendObject()
/**
* Get instance of frontend object.
*
* @return object|PEAR_Error
*/
public static function &getFrontendObject()
{
$a = &PEAR_Frontend::singleton();
return $a;
}
// }}}
// {{{ & setFrontendClass()
/**
* Load current frontend class.
*
* @param string $uiclass Name of class implementing the frontend
*
* @return object the frontend object, or a PEAR error
*/
public static function &setFrontendClass($uiclass)
{
$a = &PEAR_Frontend::setFrontendClass($uiclass);
return $a;
}
// }}}
// {{{ setFrontendType()
/**
* Set current frontend.
*
* @param string $uitype Name of the frontend type (for example "CLI")
*
* @return object the frontend object, or a PEAR error
*/
public static function setFrontendType($uitype)
{
$uiclass = 'PEAR_Frontend_' . $uitype;
return PEAR_Command::setFrontendClass($uiclass);
}
// }}}
// {{{ registerCommands()
/**
* Scan through the Command directory looking for classes
* and see what commands they implement.
*
* @param bool (optional) if FALSE (default), the new list of
* commands should replace the current one. If TRUE,
* new entries will be merged with old.
*
* @param string (optional) where (what directory) to look for
* classes, defaults to the Command subdirectory of
* the directory from where this file (__FILE__) is
* included.
*
* @return bool TRUE on success, a PEAR error on failure
*/
public static function registerCommands($merge = false, $dir = null)
{
$parser = new PEAR_XMLParser;
if ($dir === null) {
$dir = dirname(__FILE__) . '/Command';
}
if (!is_dir($dir)) {
return PEAR::raiseError("registerCommands: opendir($dir) '$dir' does not exist or is not a directory");
}
$dp = @opendir($dir);
if (empty($dp)) {
return PEAR::raiseError("registerCommands: opendir($dir) failed");
}
if (!$merge) {
$GLOBALS['_PEAR_Command_commandlist'] = array();
}
while ($file = readdir($dp)) {
if ($file{0} == '.' || substr($file, -4) != '.xml') {
continue;
}
$f = substr($file, 0, -4);
$class = "PEAR_Command_" . $f;
// List of commands
if (empty($GLOBALS['_PEAR_Command_objects'][$class])) {
$GLOBALS['_PEAR_Command_objects'][$class] = "$dir/" . $f . '.php';
}
$parser->parse(file_get_contents("$dir/$file"));
$implements = $parser->getData();
foreach ($implements as $command => $desc) {
if ($command == 'attribs') {
continue;
}
if (isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
return PEAR::raiseError('Command "' . $command . '" already registered in ' .
'class "' . $GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
}
$GLOBALS['_PEAR_Command_commandlist'][$command] = $class;
$GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc['summary'];
if (isset($desc['shortcut'])) {
$shortcut = $desc['shortcut'];
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$shortcut])) {
return PEAR::raiseError('Command shortcut "' . $shortcut . '" already ' .
'registered to command "' . $command . '" in class "' .
$GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
}
$GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command;
}
if (isset($desc['options']) && $desc['options']) {
foreach ($desc['options'] as $oname => $option) {
if (isset($option['shortopt']) && strlen($option['shortopt']) > 1) {
return PEAR::raiseError('Option "' . $oname . '" short option "' .
$option['shortopt'] . '" must be ' .
'only 1 character in Command "' . $command . '" in class "' .
$class . '"');
}
}
}
}
}
ksort($GLOBALS['_PEAR_Command_shortcuts']);
ksort($GLOBALS['_PEAR_Command_commandlist']);
@closedir($dp);
return true;
}
// }}}
// {{{ getCommands()
/**
* Get the list of currently supported commands, and what
* classes implement them.
*
* @return array command => implementing class
*/
public static function getCommands()
{
if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
PEAR_Command::registerCommands();
}
return $GLOBALS['_PEAR_Command_commandlist'];
}
// }}}
// {{{ getShortcuts()
/**
* Get the list of command shortcuts.
*
* @return array shortcut => command
*/
public static function getShortcuts()
{
if (empty($GLOBALS['_PEAR_Command_shortcuts'])) {
PEAR_Command::registerCommands();
}
return $GLOBALS['_PEAR_Command_shortcuts'];
}
// }}}
// {{{ getGetoptArgs()
/**
* Compiles arguments for getopt.
*
* @param string $command command to get optstring for
* @param string $short_args (reference) short getopt format
* @param array $long_args (reference) long getopt format
*
* @return void
*/
public static function getGetoptArgs($command, &$short_args, &$long_args)
{
if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
PEAR_Command::registerCommands();
}
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
$command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
}
if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
return null;
}
$obj = &PEAR_Command::getObject($command);
return $obj->getGetoptArgs($command, $short_args, $long_args);
}
// }}}
// {{{ getDescription()
/**
* Get description for a command.
*
* @param string $command Name of the command
*
* @return string command description
*/
public static function getDescription($command)
{
if (!isset($GLOBALS['_PEAR_Command_commanddesc'][$command])) {
return null;
}
return $GLOBALS['_PEAR_Command_commanddesc'][$command];
}
// }}}
// {{{ getHelp()
/**
* Get help for command.
*
* @param string $command Name of the command to return help for
*/
public static function getHelp($command)
{
$cmds = PEAR_Command::getCommands();
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
$command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
}
if (isset($cmds[$command])) {
$obj = &PEAR_Command::getObject($command);
return $obj->getHelp($command);
}
return false;
}
// }}}
}PK [r} PEAR/RunTest.phpnu W+A
* @author Greg Beaver
* @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.3.3
*/
/**
* for error handling
*/
require_once 'PEAR.php';
require_once 'PEAR/Config.php';
define('DETAILED', 1);
putenv("PHP_PEAR_RUNTESTS=1");
/**
* Simplified version of PHP's test suite
*
* Try it with:
*
* $ php -r 'include "../PEAR/RunTest.php"; $t=new PEAR_RunTest; $o=$t->run("./pear_system.phpt");print_r($o);'
*
*
* @category pear
* @package PEAR
* @author Tomas V.V.Cox
* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.3.3
*/
class PEAR_RunTest
{
var $_headers = array();
var $_logger;
var $_options;
var $_php;
var $tests_count;
var $xdebug_loaded;
/**
* Saved value of php executable, used to reset $_php when we
* have a test that uses cgi
*
* @var unknown_type
*/
var $_savephp;
var $ini_overwrites = array(
'output_handler=',
'open_basedir=',
'disable_functions=',
'output_buffering=Off',
'display_errors=1',
'log_errors=0',
'html_errors=0',
'track_errors=1',
'report_memleaks=0',
'report_zend_debug=0',
'docref_root=',
'docref_ext=.html',
'error_prepend_string=',
'error_append_string=',
'auto_prepend_file=',
'auto_append_file=',
'xdebug.default_enable=0',
'allow_url_fopen=1',
);
/**
* An object that supports the PEAR_Common->log() signature, or null
* @param PEAR_Common|null
*/
function __construct($logger = null, $options = array())
{
if (!defined('E_DEPRECATED')) {
define('E_DEPRECATED', 0);
}
if (!defined('E_STRICT')) {
define('E_STRICT', 0);
}
$this->ini_overwrites[] = 'error_reporting=' . (E_ALL & ~(E_DEPRECATED | E_STRICT));
if (is_null($logger)) {
require_once 'PEAR/Common.php';
$logger = new PEAR_Common;
}
$this->_logger = $logger;
$this->_options = $options;
$conf = &PEAR_Config::singleton();
$this->_php = $conf->get('php_bin');
}
/**
* Taken from php-src/run-tests.php
*
* @param string $commandline command name
* @param array $env
* @param string $stdin standard input to pass to the command
* @return unknown
*/
function system_with_timeout($commandline, $env = null, $stdin = null)
{
$data = '';
$proc = proc_open($commandline, array(
0 => array('pipe', 'r'),
1 => array('pipe', 'w'),
2 => array('pipe', 'w')
), $pipes, null, $env, array('suppress_errors' => true));
if (!$proc) {
return false;
}
if (is_string($stdin)) {
fwrite($pipes[0], $stdin);
}
fclose($pipes[0]);
while (true) {
/* hide errors from interrupted syscalls */
$r = $pipes;
$e = $w = null;
$n = @stream_select($r, $w, $e, 60);
if ($n === 0) {
/* timed out */
$data .= "\n ** ERROR: process timed out **\n";
proc_terminate($proc);
return array(1234567890, $data);
} else if ($n > 0) {
$line = fread($pipes[1], 8192);
if (strlen($line) == 0) {
/* EOF */
break;
}
$data .= $line;
}
}
if (function_exists('proc_get_status')) {
$stat = proc_get_status($proc);
if ($stat['signaled']) {
$data .= "\nTermsig=".$stat['stopsig'];
}
}
$code = proc_close($proc);
if (function_exists('proc_get_status')) {
$code = $stat['exitcode'];
}
return array($code, $data);
}
/**
* Turns a PHP INI string into an array
*
* Turns -d "include_path=/foo/bar" into this:
* array(
* 'include_path' => array(
* 'operator' => '-d',
* 'value' => '/foo/bar',
* )
* )
* Works both with quotes and without
*
* @param string an PHP INI string, -d "include_path=/foo/bar"
* @return array
*/
function iniString2array($ini_string)
{
if (!$ini_string) {
return array();
}
$split = preg_split('/[\s]|=/', $ini_string, -1, PREG_SPLIT_NO_EMPTY);
$key = $split[1][0] == '"' ? substr($split[1], 1) : $split[1];
$value = $split[2][strlen($split[2]) - 1] == '"' ? substr($split[2], 0, -1) : $split[2];
// FIXME review if this is really the struct to go with
$array = array($key => array('operator' => $split[0], 'value' => $value));
return $array;
}
function settings2array($settings, $ini_settings)
{
foreach ($settings as $setting) {
if (strpos($setting, '=') !== false) {
$setting = explode('=', $setting, 2);
$name = trim(strtolower($setting[0]));
$value = trim($setting[1]);
$ini_settings[$name] = $value;
}
}
return $ini_settings;
}
function settings2params($ini_settings)
{
$settings = '';
foreach ($ini_settings as $name => $value) {
if (is_array($value)) {
$operator = $value['operator'];
$value = $value['value'];
} else {
$operator = '-d';
}
$value = addslashes($value);
$settings .= " $operator \"$name=$value\"";
}
return $settings;
}
function _preparePhpBin($php, $file, $ini_settings)
{
$file = escapeshellarg($file);
$cmd = $php . $ini_settings . ' -f ' . $file;
return $cmd;
}
function runPHPUnit($file, $ini_settings = '')
{
if (!file_exists($file) && file_exists(getcwd() . DIRECTORY_SEPARATOR . $file)) {
$file = realpath(getcwd() . DIRECTORY_SEPARATOR . $file);
} elseif (file_exists($file)) {
$file = realpath($file);
}
$cmd = $this->_preparePhpBin($this->_php, $file, $ini_settings);
if (isset($this->_logger)) {
$this->_logger->log(2, 'Running command "' . $cmd . '"');
}
$savedir = getcwd(); // in case the test moves us around
chdir(dirname($file));
echo `$cmd`;
chdir($savedir);
return 'PASSED'; // we have no way of knowing this information so assume passing
}
/**
* Runs an individual test case.
*
* @param string The filename of the test
* @param array|string INI settings to be applied to the test run
* @param integer Number what the current running test is of the
* whole test suite being runned.
*
* @return string|object Returns PASSED, WARNED, FAILED depending on how the
* test came out.
* PEAR Error when the tester it self fails
*/
function run($file, $ini_settings = array(), $test_number = 1)
{
$this->_restorePHPBinary();
if (empty($this->_options['cgi'])) {
// try to see if php-cgi is in the path
$res = $this->system_with_timeout('php-cgi -v');
if (false !== $res && !(is_array($res) && in_array($res[0], array(-1, 127)))) {
$this->_options['cgi'] = 'php-cgi';
}
}
if (1 < $len = strlen($this->tests_count)) {
$test_number = str_pad($test_number, $len, ' ', STR_PAD_LEFT);
$test_nr = "[$test_number/$this->tests_count] ";
} else {
$test_nr = '';
}
$file = realpath($file);
$section_text = $this->_readFile($file);
if (PEAR::isError($section_text)) {
return $section_text;
}
if (isset($section_text['POST_RAW']) && isset($section_text['UPLOAD'])) {
return PEAR::raiseError("Cannot contain both POST_RAW and UPLOAD in test file: $file");
}
$cwd = getcwd();
$pass_options = '';
if (!empty($this->_options['ini'])) {
$pass_options = $this->_options['ini'];
}
if (is_string($ini_settings)) {
$ini_settings = $this->iniString2array($ini_settings);
}
$ini_settings = $this->settings2array($this->ini_overwrites, $ini_settings);
if ($section_text['INI']) {
if (strpos($section_text['INI'], '{PWD}') !== false) {
$section_text['INI'] = str_replace('{PWD}', dirname($file), $section_text['INI']);
}
$ini = preg_split( "/[\n\r]+/", $section_text['INI']);
$ini_settings = $this->settings2array($ini, $ini_settings);
}
$ini_settings = $this->settings2params($ini_settings);
$shortname = str_replace($cwd . DIRECTORY_SEPARATOR, '', $file);
$tested = trim($section_text['TEST']);
$tested.= !isset($this->_options['simple']) ? "[$shortname]" : ' ';
if (!empty($section_text['POST']) || !empty($section_text['POST_RAW']) ||
!empty($section_text['UPLOAD']) || !empty($section_text['GET']) ||
!empty($section_text['COOKIE']) || !empty($section_text['EXPECTHEADERS'])) {
if (empty($this->_options['cgi'])) {
if (!isset($this->_options['quiet'])) {
$this->_logger->log(0, "SKIP $test_nr$tested (reason: --cgi option needed for this test, type 'pear help run-tests')");
}
if (isset($this->_options['tapoutput'])) {
return array('ok', ' # skip --cgi option needed for this test, "pear help run-tests" for info');
}
return 'SKIPPED';
}
$this->_savePHPBinary();
$this->_php = $this->_options['cgi'];
}
$temp_dir = realpath(dirname($file));
$main_file_name = basename($file, 'phpt');
$diff_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'diff';
$log_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'log';
$exp_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'exp';
$output_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'out';
$memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'mem';
$temp_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'php';
$temp_skipif = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'skip.php';
$temp_clean = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name.'clean.php';
$tmp_post = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');
// unlink old test results
$this->_cleanupOldFiles($file);
// Check if test should be skipped.
$res = $this->_runSkipIf($section_text, $temp_skipif, $tested, $ini_settings);
if (count($res) != 2) {
return $res;
}
$info = $res['info'];
$warn = $res['warn'];
// We've satisfied the preconditions - run the test!
if (isset($this->_options['coverage']) && $this->xdebug_loaded) {
$xdebug_file = $temp_dir . DIRECTORY_SEPARATOR . $main_file_name . 'xdebug';
$text = "\n" . 'function coverage_shutdown() {' .
"\n" . ' $xdebug = var_export(xdebug_get_code_coverage(), true);';
if (!function_exists('file_put_contents')) {
$text .= "\n" . ' $fh = fopen(\'' . $xdebug_file . '\', "wb");' .
"\n" . ' if ($fh !== false) {' .
"\n" . ' fwrite($fh, $xdebug);' .
"\n" . ' fclose($fh);' .
"\n" . ' }';
} else {
$text .= "\n" . ' file_put_contents(\'' . $xdebug_file . '\', $xdebug);';
}
// Workaround for http://pear.php.net/bugs/bug.php?id=17292
$lines = explode("\n", $section_text['FILE']);
$numLines = count($lines);
$namespace = '';
$coverage_shutdown = 'coverage_shutdown';
if (
substr($lines[0], 0, 2) == '' ||
substr($lines[0], 0, 5) == 'save_text($temp_file, "save_text($temp_file, $section_text['FILE']);
}
$args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : '';
$cmd = $this->_preparePhpBin($this->_php, $temp_file, $ini_settings);
$cmd.= "$args 2>&1";
if (isset($this->_logger)) {
$this->_logger->log(2, 'Running command "' . $cmd . '"');
}
// Reset environment from any previous test.
$env = $this->_resetEnv($section_text, $temp_file);
$section_text = $this->_processUpload($section_text, $file);
if (PEAR::isError($section_text)) {
return $section_text;
}
if (array_key_exists('POST_RAW', $section_text) && !empty($section_text['POST_RAW'])) {
$post = trim($section_text['POST_RAW']);
$raw_lines = explode("\n", $post);
$request = '';
$started = false;
foreach ($raw_lines as $i => $line) {
if (empty($env['CONTENT_TYPE']) &&
preg_match('/^Content-Type:(.*)/i', $line, $res)) {
$env['CONTENT_TYPE'] = trim(str_replace("\r", '', $res[1]));
continue;
}
if ($started) {
$request .= "\n";
}
$started = true;
$request .= $line;
}
$env['CONTENT_LENGTH'] = strlen($request);
$env['REQUEST_METHOD'] = 'POST';
$this->save_text($tmp_post, $request);
$cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
} elseif (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
$post = trim($section_text['POST']);
$this->save_text($tmp_post, $post);
$content_length = strlen($post);
$env['REQUEST_METHOD'] = 'POST';
$env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
$env['CONTENT_LENGTH'] = $content_length;
$cmd = "$this->_php$pass_options$ini_settings \"$temp_file\" 2>&1 < $tmp_post";
} else {
$env['REQUEST_METHOD'] = 'GET';
$env['CONTENT_TYPE'] = '';
$env['CONTENT_LENGTH'] = '';
}
if (OS_WINDOWS && isset($section_text['RETURNS'])) {
ob_start();
system($cmd, $return_value);
$out = ob_get_contents();
ob_end_clean();
$section_text['RETURNS'] = (int) trim($section_text['RETURNS']);
$returnfail = ($return_value != $section_text['RETURNS']);
} else {
$returnfail = false;
$stdin = isset($section_text['STDIN']) ? $section_text['STDIN'] : null;
$out = $this->system_with_timeout($cmd, $env, $stdin);
$return_value = $out[0];
$out = $out[1];
}
$output = preg_replace('/\r\n/', "\n", trim($out));
if (isset($tmp_post) && realpath($tmp_post) && file_exists($tmp_post)) {
@unlink(realpath($tmp_post));
}
chdir($cwd); // in case the test moves us around
/* when using CGI, strip the headers from the output */
$output = $this->_stripHeadersCGI($output);
if (isset($section_text['EXPECTHEADERS'])) {
$testheaders = $this->_processHeaders($section_text['EXPECTHEADERS']);
$missing = array_diff_assoc($testheaders, $this->_headers);
$changed = '';
foreach ($missing as $header => $value) {
if (isset($this->_headers[$header])) {
$changed .= "-$header: $value\n+$header: ";
$changed .= $this->_headers[$header];
} else {
$changed .= "-$header: $value\n";
}
}
if ($missing) {
// tack on failed headers to output:
$output .= "\n====EXPECTHEADERS FAILURE====:\n$changed";
}
}
$this->_testCleanup($section_text, $temp_clean);
// Does the output match what is expected?
do {
if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) {
if (isset($section_text['EXPECTF'])) {
$wanted = trim($section_text['EXPECTF']);
} else {
$wanted = trim($section_text['EXPECTREGEX']);
}
$wanted_re = preg_replace('/\r\n/', "\n", $wanted);
if (isset($section_text['EXPECTF'])) {
$wanted_re = preg_quote($wanted_re, '/');
// Stick to basics
$wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy
$wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re);
$wanted_re = str_replace("%d", "[0-9]+", $wanted_re);
$wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re);
$wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re);
$wanted_re = str_replace("%c", ".", $wanted_re);
// %f allows two points "-.0.0" but that is the best *simple* expression
}
/* DEBUG YOUR REGEX HERE
var_dump($wanted_re);
print(str_repeat('=', 80) . "\n");
var_dump($output);
*/
if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) {
if (file_exists($temp_file)) {
unlink($temp_file);
}
if (array_key_exists('FAIL', $section_text)) {
break;
}
if (!isset($this->_options['quiet'])) {
$this->_logger->log(0, "PASS $test_nr$tested$info");
}
if (isset($this->_options['tapoutput'])) {
return array('ok', ' - ' . $tested);
}
return 'PASSED';
}
} else {
if (isset($section_text['EXPECTFILE'])) {
$f = $temp_dir . '/' . trim($section_text['EXPECTFILE']);
if (!($fp = @fopen($f, 'rb'))) {
return PEAR::raiseError('--EXPECTFILE-- section file ' .
$f . ' not found');
}
fclose($fp);
$section_text['EXPECT'] = file_get_contents($f);
}
if (isset($section_text['EXPECT'])) {
$wanted = preg_replace('/\r\n/', "\n", trim($section_text['EXPECT']));
} else {
$wanted = '';
}
// compare and leave on success
if (!$returnfail && 0 == strcmp($output, $wanted)) {
if (file_exists($temp_file)) {
unlink($temp_file);
}
if (array_key_exists('FAIL', $section_text)) {
break;
}
if (!isset($this->_options['quiet'])) {
$this->_logger->log(0, "PASS $test_nr$tested$info");
}
if (isset($this->_options['tapoutput'])) {
return array('ok', ' - ' . $tested);
}
return 'PASSED';
}
}
} while (false);
if (array_key_exists('FAIL', $section_text)) {
// we expect a particular failure
// this is only used for testing PEAR_RunTest
$expectf = isset($section_text['EXPECTF']) ? $wanted_re : null;
$faildiff = $this->generate_diff($wanted, $output, null, $expectf);
$faildiff = preg_replace('/\r/', '', $faildiff);
$wanted = preg_replace('/\r/', '', trim($section_text['FAIL']));
if ($faildiff == $wanted) {
if (!isset($this->_options['quiet'])) {
$this->_logger->log(0, "PASS $test_nr$tested$info");
}
if (isset($this->_options['tapoutput'])) {
return array('ok', ' - ' . $tested);
}
return 'PASSED';
}
unset($section_text['EXPECTF']);
$output = $faildiff;
if (isset($section_text['RETURNS'])) {
return PEAR::raiseError('Cannot have both RETURNS and FAIL in the same test: ' .
$file);
}
}
// Test failed so we need to report details.
$txt = $warn ? 'WARN ' : 'FAIL ';
$this->_logger->log(0, $txt . $test_nr . $tested . $info);
// write .exp
$res = $this->_writeLog($exp_filename, $wanted);
if (PEAR::isError($res)) {
return $res;
}
// write .out
$res = $this->_writeLog($output_filename, $output);
if (PEAR::isError($res)) {
return $res;
}
// write .diff
$returns = isset($section_text['RETURNS']) ?
array(trim($section_text['RETURNS']), $return_value) : null;
$expectf = isset($section_text['EXPECTF']) ? $wanted_re : null;
$data = $this->generate_diff($wanted, $output, $returns, $expectf);
$res = $this->_writeLog($diff_filename, $data);
if (isset($this->_options['showdiff'])) {
$this->_logger->log(0, "========DIFF========");
$this->_logger->log(0, $data);
$this->_logger->log(0, "========DONE========");
}
if (PEAR::isError($res)) {
return $res;
}
// write .log
$data = "
---- EXPECTED OUTPUT
$wanted
---- ACTUAL OUTPUT
$output
---- FAILED
";
if ($returnfail) {
$data .= "
---- EXPECTED RETURN
$section_text[RETURNS]
---- ACTUAL RETURN
$return_value
";
}
$res = $this->_writeLog($log_filename, $data);
if (PEAR::isError($res)) {
return $res;
}
if (isset($this->_options['tapoutput'])) {
$wanted = explode("\n", $wanted);
$wanted = "# Expected output:\n#\n#" . implode("\n#", $wanted);
$output = explode("\n", $output);
$output = "#\n#\n# Actual output:\n#\n#" . implode("\n#", $output);
return array($wanted . $output . 'not ok', ' - ' . $tested);
}
return $warn ? 'WARNED' : 'FAILED';
}
function generate_diff($wanted, $output, $rvalue, $wanted_re)
{
$w = explode("\n", $wanted);
$o = explode("\n", $output);
$wr = explode("\n", $wanted_re);
$w1 = array_diff_assoc($w, $o);
$o1 = array_diff_assoc($o, $w);
$o2 = $w2 = array();
foreach ($w1 as $idx => $val) {
if (!$wanted_re || !isset($wr[$idx]) || !isset($o1[$idx]) ||
!preg_match('/^' . $wr[$idx] . '\\z/', $o1[$idx])) {
$w2[sprintf("%03d<", $idx)] = sprintf("%03d- ", $idx + 1) . $val;
}
}
foreach ($o1 as $idx => $val) {
if (!$wanted_re || !isset($wr[$idx]) ||
!preg_match('/^' . $wr[$idx] . '\\z/', $val)) {
$o2[sprintf("%03d>", $idx)] = sprintf("%03d+ ", $idx + 1) . $val;
}
}
$diff = array_merge($w2, $o2);
ksort($diff);
$extra = $rvalue ? "##EXPECTED: $rvalue[0]\r\n##RETURNED: $rvalue[1]" : '';
return implode("\r\n", $diff) . $extra;
}
// Write the given text to a temporary file, and return the filename.
function save_text($filename, $text)
{
if (!$fp = fopen($filename, 'w')) {
return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)");
}
fwrite($fp, $text);
fclose($fp);
if (1 < DETAILED) echo "
FILE $filename {{{
$text
}}}
";
}
function _cleanupOldFiles($file)
{
$temp_dir = realpath(dirname($file));
$mainFileName = basename($file, 'phpt');
$diff_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'diff';
$log_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'log';
$exp_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'exp';
$output_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'out';
$memcheck_filename = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'mem';
$temp_file = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'php';
$temp_skipif = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'skip.php';
$temp_clean = $temp_dir . DIRECTORY_SEPARATOR . $mainFileName.'clean.php';
$tmp_post = $temp_dir . DIRECTORY_SEPARATOR . uniqid('phpt.');
// unlink old test results
@unlink($diff_filename);
@unlink($log_filename);
@unlink($exp_filename);
@unlink($output_filename);
@unlink($memcheck_filename);
@unlink($temp_file);
@unlink($temp_skipif);
@unlink($tmp_post);
@unlink($temp_clean);
}
function _runSkipIf($section_text, $temp_skipif, $tested, $ini_settings)
{
$info = '';
$warn = false;
if (array_key_exists('SKIPIF', $section_text) && trim($section_text['SKIPIF'])) {
$this->save_text($temp_skipif, $section_text['SKIPIF']);
$output = $this->system_with_timeout("$this->_php$ini_settings -f \"$temp_skipif\"");
$output = $output[1];
$loutput = ltrim($output);
unlink($temp_skipif);
if (!strncasecmp('skip', $loutput, 4)) {
$skipreason = "SKIP $tested";
if (preg_match('/^\s*skip\s*(.+)\s*/i', $output, $m)) {
$skipreason .= '(reason: ' . $m[1] . ')';
}
if (!isset($this->_options['quiet'])) {
$this->_logger->log(0, $skipreason);
}
if (isset($this->_options['tapoutput'])) {
return array('ok', ' # skip ' . $reason);
}
return 'SKIPPED';
}
if (!strncasecmp('info', $loutput, 4)
&& preg_match('/^\s*info\s*(.+)\s*/i', $output, $m)) {
$info = " (info: $m[1])";
}
if (!strncasecmp('warn', $loutput, 4)
&& preg_match('/^\s*warn\s*(.+)\s*/i', $output, $m)) {
$warn = true; /* only if there is a reason */
$info = " (warn: $m[1])";
}
}
return array('warn' => $warn, 'info' => $info);
}
function _stripHeadersCGI($output)
{
$this->headers = array();
if (!empty($this->_options['cgi']) &&
$this->_php == $this->_options['cgi'] &&
preg_match("/^(.*?)(?:\n\n(.*)|\\z)/s", $output, $match)) {
$output = isset($match[2]) ? trim($match[2]) : '';
$this->_headers = $this->_processHeaders($match[1]);
}
return $output;
}
/**
* Return an array that can be used with array_diff() to compare headers
*
* @param string $text
*/
function _processHeaders($text)
{
$headers = array();
$rh = preg_split("/[\n\r]+/", $text);
foreach ($rh as $line) {
if (strpos($line, ':')!== false) {
$line = explode(':', $line, 2);
$headers[trim($line[0])] = trim($line[1]);
}
}
return $headers;
}
function _readFile($file)
{
// Load the sections of the test file.
$section_text = array(
'TEST' => '(unnamed test)',
'SKIPIF' => '',
'GET' => '',
'COOKIE' => '',
'POST' => '',
'ARGS' => '',
'INI' => '',
'CLEAN' => '',
);
if (!is_file($file) || !$fp = fopen($file, "r")) {
return PEAR::raiseError("Cannot open test file: $file");
}
$section = '';
while (!feof($fp)) {
$line = fgets($fp);
// Match the beginning of a section.
if (preg_match('/^--([_A-Z]+)--/', $line, $r)) {
$section = $r[1];
$section_text[$section] = '';
continue;
} elseif (empty($section)) {
fclose($fp);
return PEAR::raiseError("Invalid sections formats in test file: $file");
}
// Add to the section text.
$section_text[$section] .= $line;
}
fclose($fp);
return $section_text;
}
function _writeLog($logname, $data)
{
if (!$log = fopen($logname, 'w')) {
return PEAR::raiseError("Cannot create test log - $logname");
}
fwrite($log, $data);
fclose($log);
}
function _resetEnv($section_text, $temp_file)
{
$env = $_ENV;
$env['REDIRECT_STATUS'] = '';
$env['QUERY_STRING'] = '';
$env['PATH_TRANSLATED'] = '';
$env['SCRIPT_FILENAME'] = '';
$env['REQUEST_METHOD'] = '';
$env['CONTENT_TYPE'] = '';
$env['CONTENT_LENGTH'] = '';
if (!empty($section_text['ENV'])) {
if (strpos($section_text['ENV'], '{PWD}') !== false) {
$section_text['ENV'] = str_replace('{PWD}', dirname($temp_file), $section_text['ENV']);
}
foreach (explode("\n", trim($section_text['ENV'])) as $e) {
$e = explode('=', trim($e), 2);
if (!empty($e[0]) && isset($e[1])) {
$env[$e[0]] = $e[1];
}
}
}
if (array_key_exists('GET', $section_text)) {
$env['QUERY_STRING'] = trim($section_text['GET']);
} else {
$env['QUERY_STRING'] = '';
}
if (array_key_exists('COOKIE', $section_text)) {
$env['HTTP_COOKIE'] = trim($section_text['COOKIE']);
} else {
$env['HTTP_COOKIE'] = '';
}
$env['REDIRECT_STATUS'] = '1';
$env['PATH_TRANSLATED'] = $temp_file;
$env['SCRIPT_FILENAME'] = $temp_file;
return $env;
}
function _processUpload($section_text, $file)
{
if (array_key_exists('UPLOAD', $section_text) && !empty($section_text['UPLOAD'])) {
$upload_files = trim($section_text['UPLOAD']);
$upload_files = explode("\n", $upload_files);
$request = "Content-Type: multipart/form-data; boundary=---------------------------20896060251896012921717172737\n" .
"-----------------------------20896060251896012921717172737\n";
foreach ($upload_files as $fileinfo) {
$fileinfo = explode('=', $fileinfo);
if (count($fileinfo) != 2) {
return PEAR::raiseError("Invalid UPLOAD section in test file: $file");
}
if (!realpath(dirname($file) . '/' . $fileinfo[1])) {
return PEAR::raiseError("File for upload does not exist: $fileinfo[1] " .
"in test file: $file");
}
$file_contents = file_get_contents(dirname($file) . '/' . $fileinfo[1]);
$fileinfo[1] = basename($fileinfo[1]);
$request .= "Content-Disposition: form-data; name=\"$fileinfo[0]\"; filename=\"$fileinfo[1]\"\n";
$request .= "Content-Type: text/plain\n\n";
$request .= $file_contents . "\n" .
"-----------------------------20896060251896012921717172737\n";
}
if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
// encode POST raw
$post = trim($section_text['POST']);
$post = explode('&', $post);
foreach ($post as $i => $post_info) {
$post_info = explode('=', $post_info);
if (count($post_info) != 2) {
return PEAR::raiseError("Invalid POST data in test file: $file");
}
$post_info[0] = rawurldecode($post_info[0]);
$post_info[1] = rawurldecode($post_info[1]);
$post[$i] = $post_info;
}
foreach ($post as $post_info) {
$request .= "Content-Disposition: form-data; name=\"$post_info[0]\"\n\n";
$request .= $post_info[1] . "\n" .
"-----------------------------20896060251896012921717172737\n";
}
unset($section_text['POST']);
}
$section_text['POST_RAW'] = $request;
}
return $section_text;
}
function _testCleanup($section_text, $temp_clean)
{
if ($section_text['CLEAN']) {
$this->_restorePHPBinary();
// perform test cleanup
$this->save_text($temp_clean, $section_text['CLEAN']);
$output = $this->system_with_timeout("$this->_php $temp_clean 2>&1");
if (strlen($output[1])) {
echo "BORKED --CLEAN-- section! output:\n", $output[1];
}
if (file_exists($temp_clean)) {
unlink($temp_clean);
}
}
}
function _savePHPBinary()
{
$this->_savephp = $this->_php;
}
function _restorePHPBinary()
{
if (isset($this->_savephp))
{
$this->_php = $this->_savephp;
unset($this->_savephp);
}
}
}
PK [_kU) ) PEAR/Downloader/Package.phpnu W+A
* @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
*/
/**
* Error code when parameter initialization fails because no releases
* exist within preferred_state, but releases do exist
*/
define('PEAR_DOWNLOADER_PACKAGE_STATE', -1003);
/**
* Error code when parameter initialization fails because no releases
* exist that will work with the existing PHP version
*/
define('PEAR_DOWNLOADER_PACKAGE_PHPVERSION', -1004);
/**
* Coordinates download parameters and manages their dependencies
* prior to downloading them.
*
* Input can come from three sources:
*
* - local files (archives or package.xml)
* - remote files (downloadable urls)
* - abstract package names
*
* The first two elements are handled cleanly by PEAR_PackageFile, but the third requires
* accessing pearweb's xml-rpc interface to determine necessary dependencies, and the
* format returned of dependencies is slightly different from that used in package.xml.
*
* This class hides the differences between these elements, and makes automatic
* dependency resolution a piece of cake. It also manages conflicts when
* two classes depend on incompatible dependencies, or differing versions of the same
* package dependency. In addition, download will not be attempted if the php version is
* not supported, PEAR installer version is not supported, or non-PECL extensions are not
* installed.
* @category pear
* @package PEAR
* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Downloader_Package
{
/**
* @var PEAR_Downloader
*/
var $_downloader;
/**
* @var PEAR_Config
*/
var $_config;
/**
* @var PEAR_Registry
*/
var $_registry;
/**
* Used to implement packagingroot properly
* @var PEAR_Registry
*/
var $_installRegistry;
/**
* @var PEAR_PackageFile_v1|PEAR_PackageFile|v2
*/
var $_packagefile;
/**
* @var array
*/
var $_parsedname;
/**
* @var array
*/
var $_downloadURL;
/**
* @var array
*/
var $_downloadDeps = array();
/**
* @var boolean
*/
var $_valid = false;
/**
* @var boolean
*/
var $_analyzed = false;
/**
* if this or a parent package was invoked with Package-state, this is set to the
* state variable.
*
* This allows temporary reassignment of preferred_state for a parent package and all of
* its dependencies.
* @var string|false
*/
var $_explicitState = false;
/**
* If this package is invoked with Package#group, this variable will be true
*/
var $_explicitGroup = false;
/**
* Package type local|url
* @var string
*/
var $_type;
/**
* Contents of package.xml, if downloaded from a remote channel
* @var string|false
* @access private
*/
var $_rawpackagefile;
/**
* @var boolean
* @access private
*/
var $_validated = false;
/**
* @param PEAR_Downloader
*/
function __construct(&$downloader)
{
$this->_downloader = &$downloader;
$this->_config = &$this->_downloader->config;
$this->_registry = &$this->_config->getRegistry();
$options = $downloader->getOptions();
if (isset($options['packagingroot'])) {
$this->_config->setInstallRoot($options['packagingroot']);
$this->_installRegistry = &$this->_config->getRegistry();
$this->_config->setInstallRoot(false);
} else {
$this->_installRegistry = &$this->_registry;
}
$this->_valid = $this->_analyzed = false;
}
/**
* Parse the input and determine whether this is a local file, a remote uri, or an
* abstract package name.
*
* This is the heart of the PEAR_Downloader_Package(), and is used in
* {@link PEAR_Downloader::download()}
* @param string
* @return bool|PEAR_Error
*/
function initialize($param)
{
$origErr = $this->_fromFile($param);
if ($this->_valid) {
return true;
}
$options = $this->_downloader->getOptions();
if (isset($options['offline'])) {
if (PEAR::isError($origErr) && !isset($options['soft'])) {
foreach ($origErr->getUserInfo() as $userInfo) {
if (isset($userInfo['message'])) {
$this->_downloader->log(0, $userInfo['message']);
}
}
$this->_downloader->log(0, $origErr->getMessage());
}
return PEAR::raiseError('Cannot download non-local package "' . $param . '"');
}
$err = $this->_fromUrl($param);
if (PEAR::isError($err) || !$this->_valid) {
if ($this->_type == 'url') {
if (PEAR::isError($err) && !isset($options['soft'])) {
$this->_downloader->log(0, $err->getMessage());
}
return PEAR::raiseError("Invalid or missing remote package file");
}
$err = $this->_fromString($param);
if (PEAR::isError($err) || !$this->_valid) {
if (PEAR::isError($err) && $err->getCode() == PEAR_DOWNLOADER_PACKAGE_STATE) {
return false; // instruct the downloader to silently skip
}
if (isset($this->_type) && $this->_type == 'local' && PEAR::isError($origErr)) {
if (is_array($origErr->getUserInfo())) {
foreach ($origErr->getUserInfo() as $err) {
if (is_array($err)) {
$err = $err['message'];
}
if (!isset($options['soft'])) {
$this->_downloader->log(0, $err);
}
}
}
if (!isset($options['soft'])) {
$this->_downloader->log(0, $origErr->getMessage());
}
if (is_array($param)) {
$param = $this->_registry->parsedPackageNameToString($param, true);
}
if (!isset($options['soft'])) {
$this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file");
}
// Passing no message back - already logged above
return PEAR::raiseError();
}
if (PEAR::isError($err) && !isset($options['soft'])) {
$this->_downloader->log(0, $err->getMessage());
}
if (is_array($param)) {
$param = $this->_registry->parsedPackageNameToString($param, true);
}
if (!isset($options['soft'])) {
$this->_downloader->log(2, "Cannot initialize '$param', invalid or missing package file");
}
// Passing no message back - already logged above
return PEAR::raiseError();
}
}
return true;
}
/**
* Retrieve any non-local packages
* @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|PEAR_Error
*/
function &download()
{
if (isset($this->_packagefile)) {
return $this->_packagefile;
}
if (isset($this->_downloadURL['url'])) {
$this->_isvalid = false;
$info = $this->getParsedPackage();
foreach ($info as $i => $p) {
$info[$i] = strtolower($p);
}
$err = $this->_fromUrl($this->_downloadURL['url'],
$this->_registry->parsedPackageNameToString($this->_parsedname, true));
$newinfo = $this->getParsedPackage();
foreach ($newinfo as $i => $p) {
$newinfo[$i] = strtolower($p);
}
if ($info != $newinfo) {
do {
if ($info['channel'] == 'pecl.php.net' && $newinfo['channel'] == 'pear.php.net') {
$info['channel'] = 'pear.php.net';
if ($info == $newinfo) {
// skip the channel check if a pecl package says it's a PEAR package
break;
}
}
if ($info['channel'] == 'pear.php.net' && $newinfo['channel'] == 'pecl.php.net') {
$info['channel'] = 'pecl.php.net';
if ($info == $newinfo) {
// skip the channel check if a pecl package says it's a PEAR package
break;
}
}
return PEAR::raiseError('CRITICAL ERROR: We are ' .
$this->_registry->parsedPackageNameToString($info) . ', but the file ' .
'downloaded claims to be ' .
$this->_registry->parsedPackageNameToString($this->getParsedPackage()));
} while (false);
}
if (PEAR::isError($err) || !$this->_valid) {
return $err;
}
}
$this->_type = 'local';
return $this->_packagefile;
}
function &getPackageFile()
{
return $this->_packagefile;
}
function &getDownloader()
{
return $this->_downloader;
}
function getType()
{
return $this->_type;
}
/**
* Like {@link initialize()}, but operates on a dependency
*/
function fromDepURL($dep)
{
$this->_downloadURL = $dep;
if (isset($dep['uri'])) {
$options = $this->_downloader->getOptions();
if (!extension_loaded("zlib") || isset($options['nocompress'])) {
$ext = '.tar';
} else {
$ext = '.tgz';
}
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$err = $this->_fromUrl($dep['uri'] . $ext);
PEAR::popErrorHandling();
if (PEAR::isError($err)) {
if (!isset($options['soft'])) {
$this->_downloader->log(0, $err->getMessage());
}
return PEAR::raiseError('Invalid uri dependency "' . $dep['uri'] . $ext . '", ' .
'cannot download');
}
} else {
$this->_parsedname =
array(
'package' => $dep['info']->getPackage(),
'channel' => $dep['info']->getChannel(),
'version' => $dep['version']
);
if (!isset($dep['nodefault'])) {
$this->_parsedname['group'] = 'default'; // download the default dependency group
$this->_explicitGroup = false;
}
$this->_rawpackagefile = $dep['raw'];
}
}
function detectDependencies($params)
{
$options = $this->_downloader->getOptions();
if (isset($options['downloadonly'])) {
return;
}
if (isset($options['offline'])) {
$this->_downloader->log(3, 'Skipping dependency download check, --offline specified');
return;
}
$pname = $this->getParsedPackage();
if (!$pname) {
return;
}
$deps = $this->getDeps();
if (!$deps) {
return;
}
if (isset($deps['required'])) { // package.xml 2.0
return $this->_detect2($deps, $pname, $options, $params);
}
return $this->_detect1($deps, $pname, $options, $params);
}
function setValidated()
{
$this->_validated = true;
}
function alreadyValidated()
{
return $this->_validated;
}
/**
* Remove packages to be downloaded that are already installed
* @param array of PEAR_Downloader_Package objects
*/
public static function removeInstalled(&$params)
{
if (!isset($params[0])) {
return;
}
$options = $params[0]->_downloader->getOptions();
if (!isset($options['downloadonly'])) {
foreach ($params as $i => $param) {
$package = $param->getPackage();
$channel = $param->getChannel();
// remove self if already installed with this version
// this does not need any pecl magic - we only remove exact matches
if ($param->_installRegistry->packageExists($package, $channel)) {
$packageVersion = $param->_installRegistry->packageInfo($package, 'version', $channel);
if (version_compare($packageVersion, $param->getVersion(), '==')) {
if (!isset($options['force']) && !isset($options['packagingroot'])) {
$info = $param->getParsedPackage();
unset($info['version']);
unset($info['state']);
if (!isset($options['soft'])) {
$param->_downloader->log(1, 'Skipping package "' .
$param->getShortName() .
'", already installed as version ' . $packageVersion);
}
$params[$i] = false;
}
} elseif (!isset($options['force']) && !isset($options['upgrade']) &&
!isset($options['soft']) && !isset($options['packagingroot'])) {
$info = $param->getParsedPackage();
$param->_downloader->log(1, 'Skipping package "' .
$param->getShortName() .
'", already installed as version ' . $packageVersion);
$params[$i] = false;
}
}
}
}
PEAR_Downloader_Package::removeDuplicates($params);
}
function _detect2($deps, $pname, $options, $params)
{
$this->_downloadDeps = array();
$groupnotfound = false;
foreach (array('package', 'subpackage') as $packagetype) {
// get required dependency group
if (isset($deps['required'][$packagetype])) {
if (isset($deps['required'][$packagetype][0])) {
foreach ($deps['required'][$packagetype] as $dep) {
if (isset($dep['conflicts'])) {
// skip any package that this package conflicts with
continue;
}
$ret = $this->_detect2Dep($dep, $pname, 'required', $params);
if (is_array($ret)) {
$this->_downloadDeps[] = $ret;
} elseif (PEAR::isError($ret) && !isset($options['soft'])) {
$this->_downloader->log(0, $ret->getMessage());
}
}
} else {
$dep = $deps['required'][$packagetype];
if (!isset($dep['conflicts'])) {
// skip any package that this package conflicts with
$ret = $this->_detect2Dep($dep, $pname, 'required', $params);
if (is_array($ret)) {
$this->_downloadDeps[] = $ret;
} elseif (PEAR::isError($ret) && !isset($options['soft'])) {
$this->_downloader->log(0, $ret->getMessage());
}
}
}
}
// get optional dependency group, if any
if (isset($deps['optional'][$packagetype])) {
$skipnames = array();
if (!isset($deps['optional'][$packagetype][0])) {
$deps['optional'][$packagetype] = array($deps['optional'][$packagetype]);
}
foreach ($deps['optional'][$packagetype] as $dep) {
$skip = false;
if (!isset($options['alldeps'])) {
$dep['package'] = $dep['name'];
if (!isset($options['soft'])) {
$this->_downloader->log(3, 'Notice: package "' .
$this->_registry->parsedPackageNameToString($this->getParsedPackage(),
true) . '" optional dependency "' .
$this->_registry->parsedPackageNameToString(array('package' =>
$dep['name'], 'channel' => 'pear.php.net'), true) .
'" will not be automatically downloaded');
}
$skipnames[] = $this->_registry->parsedPackageNameToString($dep, true);
$skip = true;
unset($dep['package']);
}
$ret = $this->_detect2Dep($dep, $pname, 'optional', $params);
if (PEAR::isError($ret) && !isset($options['soft'])) {
$this->_downloader->log(0, $ret->getMessage());
}
if (!$ret) {
$dep['package'] = $dep['name'];
$skip = count($skipnames) ?
$skipnames[count($skipnames) - 1] : '';
if ($skip ==
$this->_registry->parsedPackageNameToString($dep, true)) {
array_pop($skipnames);
}
}
if (!$skip && is_array($ret)) {
$this->_downloadDeps[] = $ret;
}
}
if (count($skipnames)) {
if (!isset($options['soft'])) {
$this->_downloader->log(1, 'Did not download optional dependencies: ' .
implode(', ', $skipnames) .
', use --alldeps to download automatically');
}
}
}
// get requested dependency group, if any
$groupname = $this->getGroup();
$explicit = $this->_explicitGroup;
if (!$groupname) {
if (!$this->canDefault()) {
continue;
}
$groupname = 'default'; // try the default dependency group
}
if ($groupnotfound) {
continue;
}
if (isset($deps['group'])) {
if (isset($deps['group']['attribs'])) {
if (strtolower($deps['group']['attribs']['name']) == strtolower($groupname)) {
$group = $deps['group'];
} elseif ($explicit) {
if (!isset($options['soft'])) {
$this->_downloader->log(0, 'Warning: package "' .
$this->_registry->parsedPackageNameToString($pname, true) .
'" has no dependency ' . 'group named "' . $groupname . '"');
}
$groupnotfound = true;
continue;
}
} else {
$found = false;
foreach ($deps['group'] as $group) {
if (strtolower($group['attribs']['name']) == strtolower($groupname)) {
$found = true;
break;
}
}
if (!$found) {
if ($explicit) {
if (!isset($options['soft'])) {
$this->_downloader->log(0, 'Warning: package "' .
$this->_registry->parsedPackageNameToString($pname, true) .
'" has no dependency ' . 'group named "' . $groupname . '"');
}
}
$groupnotfound = true;
continue;
}
}
}
if (isset($group) && isset($group[$packagetype])) {
if (isset($group[$packagetype][0])) {
foreach ($group[$packagetype] as $dep) {
$ret = $this->_detect2Dep($dep, $pname, 'dependency group "' .
$group['attribs']['name'] . '"', $params);
if (is_array($ret)) {
$this->_downloadDeps[] = $ret;
} elseif (PEAR::isError($ret) && !isset($options['soft'])) {
$this->_downloader->log(0, $ret->getMessage());
}
}
} else {
$ret = $this->_detect2Dep($group[$packagetype], $pname,
'dependency group "' .
$group['attribs']['name'] . '"', $params);
if (is_array($ret)) {
$this->_downloadDeps[] = $ret;
} elseif (PEAR::isError($ret) && !isset($options['soft'])) {
$this->_downloader->log(0, $ret->getMessage());
}
}
}
}
}
function _detect2Dep($dep, $pname, $group, $params)
{
if (isset($dep['conflicts'])) {
return true;
}
$options = $this->_downloader->getOptions();
if (isset($dep['uri'])) {
return array('uri' => $dep['uri'], 'dep' => $dep);;
}
$testdep = $dep;
$testdep['package'] = $dep['name'];
if (PEAR_Downloader_Package::willDownload($testdep, $params)) {
$dep['package'] = $dep['name'];
if (!isset($options['soft'])) {
$this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group .
' dependency "' .
$this->_registry->parsedPackageNameToString($dep, true) .
'", will be installed');
}
return false;
}
$options = $this->_downloader->getOptions();
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
if ($this->_explicitState) {
$pname['state'] = $this->_explicitState;
}
$url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname);
if (PEAR::isError($url)) {
PEAR::popErrorHandling();
return $url;
}
$dep['package'] = $dep['name'];
$ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params, $group == 'optional' &&
!isset($options['alldeps']), true);
PEAR::popErrorHandling();
if (PEAR::isError($ret)) {
if (!isset($options['soft'])) {
$this->_downloader->log(0, $ret->getMessage());
}
return false;
}
// check to see if a dep is already installed and is the same or newer
if (!isset($dep['min']) && !isset($dep['max']) && !isset($dep['recommended'])) {
$oper = 'has';
} else {
$oper = 'gt';
}
// do not try to move this before getDepPackageDownloadURL
// we can't determine whether upgrade is necessary until we know what
// version would be downloaded
if (!isset($options['force']) && $this->isInstalled($ret, $oper)) {
$version = $this->_installRegistry->packageInfo($dep['name'], 'version', $dep['channel']);
$dep['package'] = $dep['name'];
if (!isset($options['soft'])) {
$this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group .
' dependency "' .
$this->_registry->parsedPackageNameToString($dep, true) .
'" version ' . $url['version'] . ', already installed as version ' .
$version);
}
return false;
}
if (isset($dep['nodefault'])) {
$ret['nodefault'] = true;
}
return $ret;
}
function _detect1($deps, $pname, $options, $params)
{
$this->_downloadDeps = array();
$skipnames = array();
foreach ($deps as $dep) {
$nodownload = false;
if (isset ($dep['type']) && $dep['type'] === 'pkg') {
$dep['channel'] = 'pear.php.net';
$dep['package'] = $dep['name'];
switch ($dep['rel']) {
case 'not' :
continue 2;
case 'ge' :
case 'eq' :
case 'gt' :
case 'has' :
$group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
'required' :
'optional';
if (PEAR_Downloader_Package::willDownload($dep, $params)) {
$this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group
. ' dependency "' .
$this->_registry->parsedPackageNameToString($dep, true) .
'", will be installed');
continue 2;
}
$fakedp = new PEAR_PackageFile_v1;
$fakedp->setPackage($dep['name']);
// skip internet check if we are not upgrading (bug #5810)
if (!isset($options['upgrade']) && $this->isInstalled(
$fakedp, $dep['rel'])) {
$this->_downloader->log(2, $this->getShortName() . ': Skipping ' . $group
. ' dependency "' .
$this->_registry->parsedPackageNameToString($dep, true) .
'", is already installed');
continue 2;
}
}
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
if ($this->_explicitState) {
$pname['state'] = $this->_explicitState;
}
$url = $this->_downloader->_getDepPackageDownloadUrl($dep, $pname);
$chan = 'pear.php.net';
if (PEAR::isError($url)) {
// check to see if this is a pecl package that has jumped
// from pear.php.net to pecl.php.net channel
if (!class_exists('PEAR_Dependency2')) {
require_once 'PEAR/Dependency2.php';
}
$newdep = PEAR_Dependency2::normalizeDep($dep);
$newdep = $newdep[0];
$newdep['channel'] = 'pecl.php.net';
$chan = 'pecl.php.net';
$url = $this->_downloader->_getDepPackageDownloadUrl($newdep, $pname);
$obj = &$this->_installRegistry->getPackage($dep['name']);
if (PEAR::isError($url)) {
PEAR::popErrorHandling();
if ($obj !== null && $this->isInstalled($obj, $dep['rel'])) {
$group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
'required' :
'optional';
$dep['package'] = $dep['name'];
if (!isset($options['soft'])) {
$this->_downloader->log(3, $this->getShortName() .
': Skipping ' . $group . ' dependency "' .
$this->_registry->parsedPackageNameToString($dep, true) .
'", already installed as version ' . $obj->getVersion());
}
$skip = count($skipnames) ?
$skipnames[count($skipnames) - 1] : '';
if ($skip ==
$this->_registry->parsedPackageNameToString($dep, true)) {
array_pop($skipnames);
}
continue;
} else {
if (isset($dep['optional']) && $dep['optional'] == 'yes') {
$this->_downloader->log(2, $this->getShortName() .
': Skipping optional dependency "' .
$this->_registry->parsedPackageNameToString($dep, true) .
'", no releases exist');
continue;
} else {
return $url;
}
}
}
}
PEAR::popErrorHandling();
if (!isset($options['alldeps'])) {
if (isset($dep['optional']) && $dep['optional'] == 'yes') {
if (!isset($options['soft'])) {
$this->_downloader->log(3, 'Notice: package "' .
$this->getShortName() .
'" optional dependency "' .
$this->_registry->parsedPackageNameToString(
array('channel' => $chan, 'package' =>
$dep['name']), true) .
'" will not be automatically downloaded');
}
$skipnames[] = $this->_registry->parsedPackageNameToString(
array('channel' => $chan, 'package' =>
$dep['name']), true);
$nodownload = true;
}
}
if (!isset($options['alldeps']) && !isset($options['onlyreqdeps'])) {
if (!isset($dep['optional']) || $dep['optional'] == 'no') {
if (!isset($options['soft'])) {
$this->_downloader->log(3, 'Notice: package "' .
$this->getShortName() .
'" required dependency "' .
$this->_registry->parsedPackageNameToString(
array('channel' => $chan, 'package' =>
$dep['name']), true) .
'" will not be automatically downloaded');
}
$skipnames[] = $this->_registry->parsedPackageNameToString(
array('channel' => $chan, 'package' =>
$dep['name']), true);
$nodownload = true;
}
}
// check to see if a dep is already installed
// do not try to move this before getDepPackageDownloadURL
// we can't determine whether upgrade is necessary until we know what
// version would be downloaded
if (!isset($options['force']) && $this->isInstalled(
$url, $dep['rel'])) {
$group = (!isset($dep['optional']) || $dep['optional'] == 'no') ?
'required' :
'optional';
$dep['package'] = $dep['name'];
if (isset($newdep)) {
$version = $this->_installRegistry->packageInfo($newdep['name'], 'version', $newdep['channel']);
} else {
$version = $this->_installRegistry->packageInfo($dep['name'], 'version');
}
$dep['version'] = $url['version'];
if (!isset($options['soft'])) {
$this->_downloader->log(3, $this->getShortName() . ': Skipping ' . $group .
' dependency "' .
$this->_registry->parsedPackageNameToString($dep, true) .
'", already installed as version ' . $version);
}
$skip = count($skipnames) ?
$skipnames[count($skipnames) - 1] : '';
if ($skip ==
$this->_registry->parsedPackageNameToString($dep, true)) {
array_pop($skipnames);
}
continue;
}
if ($nodownload) {
continue;
}
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
if (isset($newdep)) {
$dep = $newdep;
}
$dep['package'] = $dep['name'];
$ret = $this->_analyzeDownloadURL($url, 'dependency', $dep, $params,
isset($dep['optional']) && $dep['optional'] == 'yes' &&
!isset($options['alldeps']), true);
PEAR::popErrorHandling();
if (PEAR::isError($ret)) {
if (!isset($options['soft'])) {
$this->_downloader->log(0, $ret->getMessage());
}
continue;
}
$this->_downloadDeps[] = $ret;
}
}
if (count($skipnames)) {
if (!isset($options['soft'])) {
$this->_downloader->log(1, 'Did not download dependencies: ' .
implode(', ', $skipnames) .
', use --alldeps or --onlyreqdeps to download automatically');
}
}
}
function setDownloadURL($pkg)
{
$this->_downloadURL = $pkg;
}
/**
* Set the package.xml object for this downloaded package
*
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2 $pkg
*/
function setPackageFile(&$pkg)
{
$this->_packagefile = &$pkg;
}
function getShortName()
{
return $this->_registry->parsedPackageNameToString(array('channel' => $this->getChannel(),
'package' => $this->getPackage()), true);
}
function getParsedPackage()
{
if (isset($this->_packagefile) || isset($this->_parsedname)) {
return array('channel' => $this->getChannel(),
'package' => $this->getPackage(),
'version' => $this->getVersion());
}
return false;
}
function getDownloadURL()
{
return $this->_downloadURL;
}
function canDefault()
{
if (isset($this->_downloadURL) && isset($this->_downloadURL['nodefault'])) {
return false;
}
return true;
}
function getPackage()
{
if (isset($this->_packagefile)) {
return $this->_packagefile->getPackage();
} elseif (isset($this->_downloadURL['info'])) {
return $this->_downloadURL['info']->getPackage();
}
return false;
}
/**
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
*/
function isSubpackage(&$pf)
{
if (isset($this->_packagefile)) {
return $this->_packagefile->isSubpackage($pf);
} elseif (isset($this->_downloadURL['info'])) {
return $this->_downloadURL['info']->isSubpackage($pf);
}
return false;
}
function getPackageType()
{
if (isset($this->_packagefile)) {
return $this->_packagefile->getPackageType();
} elseif (isset($this->_downloadURL['info'])) {
return $this->_downloadURL['info']->getPackageType();
}
return false;
}
function isBundle()
{
if (isset($this->_packagefile)) {
return $this->_packagefile->getPackageType() == 'bundle';
}
return false;
}
function getPackageXmlVersion()
{
if (isset($this->_packagefile)) {
return $this->_packagefile->getPackagexmlVersion();
} elseif (isset($this->_downloadURL['info'])) {
return $this->_downloadURL['info']->getPackagexmlVersion();
}
return '1.0';
}
function getChannel()
{
if (isset($this->_packagefile)) {
return $this->_packagefile->getChannel();
} elseif (isset($this->_downloadURL['info'])) {
return $this->_downloadURL['info']->getChannel();
}
return false;
}
function getURI()
{
if (isset($this->_packagefile)) {
return $this->_packagefile->getURI();
} elseif (isset($this->_downloadURL['info'])) {
return $this->_downloadURL['info']->getURI();
}
return false;
}
function getVersion()
{
if (isset($this->_packagefile)) {
return $this->_packagefile->getVersion();
} elseif (isset($this->_downloadURL['version'])) {
return $this->_downloadURL['version'];
}
return false;
}
function isCompatible($pf)
{
if (isset($this->_packagefile)) {
return $this->_packagefile->isCompatible($pf);
} elseif (isset($this->_downloadURL['info'])) {
return $this->_downloadURL['info']->isCompatible($pf);
}
return true;
}
function setGroup($group)
{
$this->_parsedname['group'] = $group;
}
function getGroup()
{
if (isset($this->_parsedname['group'])) {
return $this->_parsedname['group'];
}
return '';
}
function isExtension($name)
{
if (isset($this->_packagefile)) {
return $this->_packagefile->isExtension($name);
} elseif (isset($this->_downloadURL['info'])) {
if ($this->_downloadURL['info']->getPackagexmlVersion() == '2.0') {
return $this->_downloadURL['info']->getProvidesExtension() == $name;
}
return false;
}
return false;
}
function getDeps()
{
if (isset($this->_packagefile)) {
$ver = $this->_packagefile->getPackagexmlVersion();
if (version_compare($ver, '2.0', '>=')) {
return $this->_packagefile->getDeps(true);
}
return $this->_packagefile->getDeps();
} elseif (isset($this->_downloadURL['info'])) {
$ver = $this->_downloadURL['info']->getPackagexmlVersion();
if (version_compare($ver, '2.0', '>=')) {
return $this->_downloadURL['info']->getDeps(true);
}
return $this->_downloadURL['info']->getDeps();
}
return array();
}
/**
* @param array Parsed array from {@link PEAR_Registry::parsePackageName()} or a dependency
* returned from getDepDownloadURL()
*/
function isEqual($param)
{
if (is_object($param)) {
$channel = $param->getChannel();
$package = $param->getPackage();
if ($param->getURI()) {
$param = array(
'channel' => $param->getChannel(),
'package' => $param->getPackage(),
'version' => $param->getVersion(),
'uri' => $param->getURI(),
);
} else {
$param = array(
'channel' => $param->getChannel(),
'package' => $param->getPackage(),
'version' => $param->getVersion(),
);
}
} else {
if (isset($param['uri'])) {
if ($this->getChannel() != '__uri') {
return false;
}
return $param['uri'] == $this->getURI();
}
$package = isset($param['package']) ? $param['package'] : $param['info']->getPackage();
$channel = isset($param['channel']) ? $param['channel'] : $param['info']->getChannel();
if (isset($param['rel'])) {
if (!class_exists('PEAR_Dependency2')) {
require_once 'PEAR/Dependency2.php';
}
$newdep = PEAR_Dependency2::normalizeDep($param);
$newdep = $newdep[0];
} elseif (isset($param['min'])) {
$newdep = $param;
}
}
if (isset($newdep)) {
if (!isset($newdep['min'])) {
$newdep['min'] = '0';
}
if (!isset($newdep['max'])) {
$newdep['max'] = '100000000000000000000';
}
// use magic to support pecl packages suddenly jumping to the pecl channel
// we need to support both dependency possibilities
if ($channel == 'pear.php.net' && $this->getChannel() == 'pecl.php.net') {
if ($package == $this->getPackage()) {
$channel = 'pecl.php.net';
}
}
if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') {
if ($package == $this->getPackage()) {
$channel = 'pear.php.net';
}
}
return (strtolower($package) == strtolower($this->getPackage()) &&
$channel == $this->getChannel() &&
version_compare($newdep['min'], $this->getVersion(), '<=') &&
version_compare($newdep['max'], $this->getVersion(), '>='));
}
// use magic to support pecl packages suddenly jumping to the pecl channel
if ($channel == 'pecl.php.net' && $this->getChannel() == 'pear.php.net') {
if (strtolower($package) == strtolower($this->getPackage())) {
$channel = 'pear.php.net';
}
}
if (isset($param['version'])) {
return (strtolower($package) == strtolower($this->getPackage()) &&
$channel == $this->getChannel() &&
$param['version'] == $this->getVersion());
}
return strtolower($package) == strtolower($this->getPackage()) &&
$channel == $this->getChannel();
}
function isInstalled($dep, $oper = '==')
{
if (!$dep) {
return false;
}
if ($oper != 'ge' && $oper != 'gt' && $oper != 'has' && $oper != '==') {
return false;
}
if (is_object($dep)) {
$package = $dep->getPackage();
$channel = $dep->getChannel();
if ($dep->getURI()) {
$dep = array(
'uri' => $dep->getURI(),
'version' => $dep->getVersion(),
);
} else {
$dep = array(
'version' => $dep->getVersion(),
);
}
} else {
if (isset($dep['uri'])) {
$channel = '__uri';
$package = $dep['dep']['name'];
} else {
$channel = $dep['info']->getChannel();
$package = $dep['info']->getPackage();
}
}
$options = $this->_downloader->getOptions();
$test = $this->_installRegistry->packageExists($package, $channel);
if (!$test && $channel == 'pecl.php.net') {
// do magic to allow upgrading from old pecl packages to new ones
$test = $this->_installRegistry->packageExists($package, 'pear.php.net');
$channel = 'pear.php.net';
}
if ($test) {
if (isset($dep['uri'])) {
if ($this->_installRegistry->packageInfo($package, 'uri', '__uri') == $dep['uri']) {
return true;
}
}
if (isset($options['upgrade'])) {
$packageVersion = $this->_installRegistry->packageInfo($package, 'version', $channel);
if (version_compare($packageVersion, $dep['version'], '>=')) {
return true;
}
return false;
}
return true;
}
return false;
}
/**
* Detect duplicate package names with differing versions
*
* If a user requests to install Date 1.4.6 and Date 1.4.7,
* for instance, this is a logic error. This method
* detects this situation.
*
* @param array $params array of PEAR_Downloader_Package objects
* @param array $errorparams empty array
* @return array array of stupid duplicated packages in PEAR_Downloader_Package obejcts
*/
public static function detectStupidDuplicates($params, &$errorparams)
{
$existing = array();
foreach ($params as $i => $param) {
$package = $param->getPackage();
$channel = $param->getChannel();
$group = $param->getGroup();
if (!isset($existing[$channel . '/' . $package])) {
$existing[$channel . '/' . $package] = array();
}
if (!isset($existing[$channel . '/' . $package][$group])) {
$existing[$channel . '/' . $package][$group] = array();
}
$existing[$channel . '/' . $package][$group][] = $i;
}
$indices = array();
foreach ($existing as $package => $groups) {
foreach ($groups as $group => $dupes) {
if (count($dupes) > 1) {
$indices = $indices + $dupes;
}
}
}
$indices = array_unique($indices);
foreach ($indices as $index) {
$errorparams[] = $params[$index];
}
return count($errorparams);
}
/**
* @param array
* @param bool ignore install groups - for final removal of dupe packages
*/
public static function removeDuplicates(&$params, $ignoreGroups = false)
{
$pnames = array();
foreach ($params as $i => $param) {
if (!$param) {
continue;
}
if ($param->getPackage()) {
$group = $ignoreGroups ? '' : $param->getGroup();
$pnames[$i] = $param->getChannel() . '/' .
$param->getPackage() . '-' . $param->getVersion() . '#' . $group;
}
}
$pnames = array_unique($pnames);
$unset = array_diff(array_keys($params), array_keys($pnames));
$testp = array_flip($pnames);
foreach ($params as $i => $param) {
if (!$param) {
$unset[] = $i;
continue;
}
if (!is_a($param, 'PEAR_Downloader_Package')) {
$unset[] = $i;
continue;
}
$group = $ignoreGroups ? '' : $param->getGroup();
if (!isset($testp[$param->getChannel() . '/' . $param->getPackage() . '-' .
$param->getVersion() . '#' . $group])) {
$unset[] = $i;
}
}
foreach ($unset as $i) {
unset($params[$i]);
}
$ret = array();
foreach ($params as $i => $param) {
$ret[] = &$params[$i];
}
$params = array();
foreach ($ret as $i => $param) {
$params[] = &$ret[$i];
}
}
function explicitState()
{
return $this->_explicitState;
}
function setExplicitState($s)
{
$this->_explicitState = $s;
}
/**
*/
public static function mergeDependencies(&$params)
{
$bundles = $newparams = array();
foreach ($params as $i => $param) {
if (!$param->isBundle()) {
continue;
}
$bundles[] = $i;
$pf = &$param->getPackageFile();
$newdeps = array();
$contents = $pf->getBundledPackages();
if (!is_array($contents)) {
$contents = array($contents);
}
foreach ($contents as $file) {
$filecontents = $pf->getFileContents($file);
$dl = &$param->getDownloader();
$options = $dl->getOptions();
if (PEAR::isError($dir = $dl->getDownloadDir())) {
return $dir;
}
$fp = @fopen($dir . DIRECTORY_SEPARATOR . $file, 'wb');
if (!$fp) {
continue;
}
// FIXME do symlink check
fwrite($fp, $filecontents, strlen($filecontents));
fclose($fp);
if ($s = $params[$i]->explicitState()) {
$obj->setExplicitState($s);
}
$obj = new PEAR_Downloader_Package($params[$i]->getDownloader());
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
if (PEAR::isError($dir = $dl->getDownloadDir())) {
PEAR::popErrorHandling();
return $dir;
}
$a = $dir . DIRECTORY_SEPARATOR . $file;
$e = $obj->_fromFile($a);
PEAR::popErrorHandling();
if (PEAR::isError($e)) {
if (!isset($options['soft'])) {
$dl->log(0, $e->getMessage());
}
continue;
}
if (!PEAR_Downloader_Package::willDownload($obj,
array_merge($params, $newparams)) && !$param->isInstalled($obj)) {
$newparams[] = $obj;
}
}
}
foreach ($bundles as $i) {
unset($params[$i]); // remove bundles - only their contents matter for installation
}
PEAR_Downloader_Package::removeDuplicates($params); // strip any unset indices
if (count($newparams)) { // add in bundled packages for install
foreach ($newparams as $i => $unused) {
$params[] = &$newparams[$i];
}
$newparams = array();
}
foreach ($params as $i => $param) {
$newdeps = array();
foreach ($param->_downloadDeps as $dep) {
$merge = array_merge($params, $newparams);
if (!PEAR_Downloader_Package::willDownload($dep, $merge)
&& !$param->isInstalled($dep)
) {
$newdeps[] = $dep;
} else {
//var_dump($dep);
// detect versioning conflicts here
}
}
// convert the dependencies into PEAR_Downloader_Package objects for the next time around
$params[$i]->_downloadDeps = array();
foreach ($newdeps as $dep) {
$obj = new PEAR_Downloader_Package($params[$i]->getDownloader());
if ($s = $params[$i]->explicitState()) {
$obj->setExplicitState($s);
}
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$e = $obj->fromDepURL($dep);
PEAR::popErrorHandling();
if (PEAR::isError($e)) {
if (!isset($options['soft'])) {
$obj->_downloader->log(0, $e->getMessage());
}
continue;
}
$e = $obj->detectDependencies($params);
if (PEAR::isError($e)) {
if (!isset($options['soft'])) {
$obj->_downloader->log(0, $e->getMessage());
}
}
$newparams[] = $obj;
}
}
if (count($newparams)) {
foreach ($newparams as $i => $unused) {
$params[] = &$newparams[$i];
}
return true;
}
return false;
}
/**
*/
public static function willDownload($param, $params)
{
if (!is_array($params)) {
return false;
}
foreach ($params as $obj) {
if ($obj->isEqual($param)) {
return true;
}
}
return false;
}
/**
* For simpler unit-testing
* @param PEAR_Config
* @param int
* @param string
*/
function &getPackagefileObject(&$c, $d)
{
$a = new PEAR_PackageFile($c, $d);
return $a;
}
/**
* This will retrieve from a local file if possible, and parse out
* a group name as well. The original parameter will be modified to reflect this.
* @param string|array can be a parsed package name as well
* @access private
*/
function _fromFile(&$param)
{
$saveparam = $param;
if (is_string($param)) {
if (!@file_exists($param)) {
$test = explode('#', $param);
$group = array_pop($test);
if (@file_exists(implode('#', $test))) {
$this->setGroup($group);
$param = implode('#', $test);
$this->_explicitGroup = true;
}
}
if (@is_file($param)) {
$this->_type = 'local';
$options = $this->_downloader->getOptions();
$pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->_debug);
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$pf = &$pkg->fromAnyFile($param, PEAR_VALIDATE_INSTALLING);
PEAR::popErrorHandling();
if (PEAR::isError($pf)) {
$this->_valid = false;
$param = $saveparam;
return $pf;
}
$this->_packagefile = &$pf;
if (!$this->getGroup()) {
$this->setGroup('default'); // install the default dependency group
}
return $this->_valid = true;
}
}
$param = $saveparam;
return $this->_valid = false;
}
function _fromUrl($param, $saveparam = '')
{
if (!is_array($param) && (preg_match('#^(http|https|ftp)://#', $param))) {
$options = $this->_downloader->getOptions();
$this->_type = 'url';
$callback = $this->_downloader->ui ?
array(&$this->_downloader, '_downloadCallback') : null;
$this->_downloader->pushErrorHandling(PEAR_ERROR_RETURN);
if (PEAR::isError($dir = $this->_downloader->getDownloadDir())) {
$this->_downloader->popErrorHandling();
return $dir;
}
$this->_downloader->log(3, 'Downloading "' . $param . '"');
$file = $this->_downloader->downloadHttp($param, $this->_downloader->ui,
$dir, $callback, null, false, $this->getChannel());
$this->_downloader->popErrorHandling();
if (PEAR::isError($file)) {
if (!empty($saveparam)) {
$saveparam = ", cannot download \"$saveparam\"";
}
$err = PEAR::raiseError('Could not download from "' . $param .
'"' . $saveparam . ' (' . $file->getMessage() . ')');
return $err;
}
if ($this->_rawpackagefile) {
require_once 'Archive/Tar.php';
$tar = new Archive_Tar($file);
$packagexml = $tar->extractInString('package2.xml');
if (!$packagexml) {
$packagexml = $tar->extractInString('package.xml');
}
if (str_replace(array("\n", "\r"), array('',''), $packagexml) !=
str_replace(array("\n", "\r"), array('',''), $this->_rawpackagefile)) {
if ($this->getChannel() != 'pear.php.net') {
return PEAR::raiseError('CRITICAL ERROR: package.xml downloaded does ' .
'not match value returned from xml-rpc');
}
// be more lax for the existing PEAR packages that have not-ok
// characters in their package.xml
$this->_downloader->log(0, 'CRITICAL WARNING: The "' .
$this->getPackage() . '" package has invalid characters in its ' .
'package.xml. The next version of PEAR may not be able to install ' .
'this package for security reasons. Please open a bug report at ' .
'http://pear.php.net/package/' . $this->getPackage() . '/bugs');
}
}
// whew, download worked!
$pkg = &$this->getPackagefileObject($this->_config, $this->_downloader->debug);
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$pf = &$pkg->fromAnyFile($file, PEAR_VALIDATE_INSTALLING);
PEAR::popErrorHandling();
if (PEAR::isError($pf)) {
if (is_array($pf->getUserInfo())) {
foreach ($pf->getUserInfo() as $err) {
if (is_array($err)) {
$err = $err['message'];
}
if (!isset($options['soft'])) {
$this->_downloader->log(0, "Validation Error: $err");
}
}
}
if (!isset($options['soft'])) {
$this->_downloader->log(0, $pf->getMessage());
}
///FIXME need to pass back some error code that we can use to match with to cancel all further operations
/// At least stop all deps of this package from being installed
$out = $saveparam ? $saveparam : $param;
$err = PEAR::raiseError('Download of "' . $out . '" succeeded, but it is not a valid package archive');
$this->_valid = false;
return $err;
}
$this->_packagefile = &$pf;
$this->setGroup('default'); // install the default dependency group
return $this->_valid = true;
}
return $this->_valid = false;
}
/**
*
* @param string|array pass in an array of format
* array(
* 'package' => 'pname',
* ['channel' => 'channame',]
* ['version' => 'version',]
* ['state' => 'state',])
* or a string of format [channame/]pname[-version|-state]
*/
function _fromString($param)
{
$options = $this->_downloader->getOptions();
$channel = $this->_config->get('default_channel');
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$pname = $this->_registry->parsePackageName($param, $channel);
PEAR::popErrorHandling();
if (PEAR::isError($pname)) {
if ($pname->getCode() == 'invalid') {
$this->_valid = false;
return false;
}
if ($pname->getCode() == 'channel') {
$parsed = $pname->getUserInfo();
if ($this->_downloader->discover($parsed['channel'])) {
if ($this->_config->get('auto_discover')) {
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$pname = $this->_registry->parsePackageName($param, $channel);
PEAR::popErrorHandling();
} else {
if (!isset($options['soft'])) {
$this->_downloader->log(0, 'Channel "' . $parsed['channel'] .
'" is not initialized, use ' .
'"pear channel-discover ' . $parsed['channel'] . '" to initialize' .
'or pear config-set auto_discover 1');
}
}
}
if (PEAR::isError($pname)) {
if (!isset($options['soft'])) {
$this->_downloader->log(0, $pname->getMessage());
}
if (is_array($param)) {
$param = $this->_registry->parsedPackageNameToString($param);
}
$err = PEAR::raiseError('invalid package name/package file "' . $param . '"');
$this->_valid = false;
return $err;
}
} else {
if (!isset($options['soft'])) {
$this->_downloader->log(0, $pname->getMessage());
}
$err = PEAR::raiseError('invalid package name/package file "' . $param . '"');
$this->_valid = false;
return $err;
}
}
if (!isset($this->_type)) {
$this->_type = 'rest';
}
$this->_parsedname = $pname;
$this->_explicitState = isset($pname['state']) ? $pname['state'] : false;
$this->_explicitGroup = isset($pname['group']) ? true : false;
$info = $this->_downloader->_getPackageDownloadUrl($pname);
if (PEAR::isError($info)) {
if ($info->getCode() != -976 && $pname['channel'] == 'pear.php.net') {
// try pecl
$pname['channel'] = 'pecl.php.net';
if ($test = $this->_downloader->_getPackageDownloadUrl($pname)) {
if (!PEAR::isError($test)) {
$info = PEAR::raiseError($info->getMessage() . ' - package ' .
$this->_registry->parsedPackageNameToString($pname, true) .
' can be installed with "pecl install ' . $pname['package'] .
'"');
} else {
$pname['channel'] = 'pear.php.net';
}
} else {
$pname['channel'] = 'pear.php.net';
}
}
return $info;
}
$this->_rawpackagefile = $info['raw'];
$ret = $this->_analyzeDownloadURL($info, $param, $pname);
if (PEAR::isError($ret)) {
return $ret;
}
if ($ret) {
$this->_downloadURL = $ret;
return $this->_valid = (bool) $ret;
}
}
/**
* @param array output of package.getDownloadURL
* @param string|array|object information for detecting packages to be downloaded, and
* for errors
* @param array name information of the package
* @param array|null packages to be downloaded
* @param bool is this an optional dependency?
* @param bool is this any kind of dependency?
* @access private
*/
function _analyzeDownloadURL($info, $param, $pname, $params = null, $optional = false,
$isdependency = false)
{
if (!is_string($param) && PEAR_Downloader_Package::willDownload($param, $params)) {
return false;
}
if ($info === false) {
$saveparam = !is_string($param) ? ", cannot download \"$param\"" : '';
// no releases exist
return PEAR::raiseError('No releases for package "' .
$this->_registry->parsedPackageNameToString($pname, true) . '" exist' . $saveparam);
}
if (strtolower($info['info']->getChannel()) != strtolower($pname['channel'])) {
$err = false;
if ($pname['channel'] == 'pecl.php.net') {
if ($info['info']->getChannel() != 'pear.php.net') {
$err = true;
}
} elseif ($info['info']->getChannel() == 'pecl.php.net') {
if ($pname['channel'] != 'pear.php.net') {
$err = true;
}
} else {
$err = true;
}
if ($err) {
return PEAR::raiseError('SECURITY ERROR: package in channel "' . $pname['channel'] .
'" retrieved another channel\'s name for download! ("' .
$info['info']->getChannel() . '")');
}
}
$preferred_state = $this->_config->get('preferred_state');
if (!isset($info['url'])) {
$package_version = $this->_registry->packageInfo($info['info']->getPackage(),
'version', $info['info']->getChannel());
if ($this->isInstalled($info)) {
if ($isdependency && version_compare($info['version'], $package_version, '<=')) {
// ignore bogus errors of "failed to download dependency"
// if it is already installed and the one that would be
// downloaded is older or the same version (Bug #7219)
return false;
}
}
if ($info['version'] === $package_version) {
if (!isset($options['soft'])) {
$this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
'/' . $pname['package'] . '-' . $package_version. ', additionally the suggested version' .
' (' . $package_version . ') is the same as the locally installed one.');
}
return false;
}
if (version_compare($info['version'], $package_version, '<=')) {
if (!isset($options['soft'])) {
$this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
'/' . $pname['package'] . '-' . $package_version . ', additionally the suggested version' .
' (' . $info['version'] . ') is a lower version than the locally installed one (' . $package_version . ').');
}
return false;
}
$instead = ', will instead download version ' . $info['version'] .
', stability "' . $info['info']->getState() . '"';
// releases exist, but we failed to get any
if (isset($this->_downloader->_options['force'])) {
if (isset($pname['version'])) {
$vs = ', version "' . $pname['version'] . '"';
} elseif (isset($pname['state'])) {
$vs = ', stability "' . $pname['state'] . '"';
} elseif ($param == 'dependency') {
if (!class_exists('PEAR_Common')) {
require_once 'PEAR/Common.php';
}
if (!in_array($info['info']->getState(),
PEAR_Common::betterStates($preferred_state, true))) {
if ($optional) {
// don't spit out confusing error message
return $this->_downloader->_getPackageDownloadUrl(
array('package' => $pname['package'],
'channel' => $pname['channel'],
'version' => $info['version']));
}
$vs = ' within preferred state "' . $preferred_state .
'"';
} else {
if (!class_exists('PEAR_Dependency2')) {
require_once 'PEAR/Dependency2.php';
}
if ($optional) {
// don't spit out confusing error message
return $this->_downloader->_getPackageDownloadUrl(
array('package' => $pname['package'],
'channel' => $pname['channel'],
'version' => $info['version']));
}
$vs = PEAR_Dependency2::_getExtraString($pname);
$instead = '';
}
} else {
$vs = ' within preferred state "' . $preferred_state . '"';
}
if (!isset($options['soft'])) {
$this->_downloader->log(1, 'WARNING: failed to download ' . $pname['channel'] .
'/' . $pname['package'] . $vs . $instead);
}
// download the latest release
return $this->_downloader->_getPackageDownloadUrl(
array('package' => $pname['package'],
'channel' => $pname['channel'],
'version' => $info['version']));
} else {
if (isset($info['php']) && $info['php']) {
$err = PEAR::raiseError('Failed to download ' .
$this->_registry->parsedPackageNameToString(
array('channel' => $pname['channel'],
'package' => $pname['package']),
true) .
', latest release is version ' . $info['php']['v'] .
', but it requires PHP version "' .
$info['php']['m'] . '", use "' .
$this->_registry->parsedPackageNameToString(
array('channel' => $pname['channel'], 'package' => $pname['package'],
'version' => $info['php']['v'])) . '" to install',
PEAR_DOWNLOADER_PACKAGE_PHPVERSION);
return $err;
}
// construct helpful error message
if (isset($pname['version'])) {
$vs = ', version "' . $pname['version'] . '"';
} elseif (isset($pname['state'])) {
$vs = ', stability "' . $pname['state'] . '"';
} elseif ($param == 'dependency') {
if (!class_exists('PEAR_Common')) {
require_once 'PEAR/Common.php';
}
if (!in_array($info['info']->getState(),
PEAR_Common::betterStates($preferred_state, true))) {
if ($optional) {
// don't spit out confusing error message, and don't die on
// optional dep failure!
return $this->_downloader->_getPackageDownloadUrl(
array('package' => $pname['package'],
'channel' => $pname['channel'],
'version' => $info['version']));
}
$vs = ' within preferred state "' . $preferred_state . '"';
} else {
if (!class_exists('PEAR_Dependency2')) {
require_once 'PEAR/Dependency2.php';
}
if ($optional) {
// don't spit out confusing error message, and don't die on
// optional dep failure!
return $this->_downloader->_getPackageDownloadUrl(
array('package' => $pname['package'],
'channel' => $pname['channel'],
'version' => $info['version']));
}
$vs = PEAR_Dependency2::_getExtraString($pname);
}
} else {
$vs = ' within preferred state "' . $this->_downloader->config->get('preferred_state') . '"';
}
$options = $this->_downloader->getOptions();
// this is only set by the "download-all" command
if (isset($options['ignorepreferred_state'])) {
$err = PEAR::raiseError(
'Failed to download ' . $this->_registry->parsedPackageNameToString(
array('channel' => $pname['channel'], 'package' => $pname['package']),
true)
. $vs .
', latest release is version ' . $info['version'] .
', stability "' . $info['info']->getState() . '", use "' .
$this->_registry->parsedPackageNameToString(
array('channel' => $pname['channel'], 'package' => $pname['package'],
'version' => $info['version'])) . '" to install',
PEAR_DOWNLOADER_PACKAGE_STATE);
return $err;
}
// Checks if the user has a package installed already and checks the release against
// the state against the installed package, this allows upgrades for packages
// with lower stability than the preferred_state
$stability = $this->_registry->packageInfo($pname['package'], 'stability', $pname['channel']);
if (!$this->isInstalled($info)
|| !in_array($info['info']->getState(), PEAR_Common::betterStates($stability['release'], true))
) {
$err = PEAR::raiseError(
'Failed to download ' . $this->_registry->parsedPackageNameToString(
array('channel' => $pname['channel'], 'package' => $pname['package']),
true)
. $vs .
', latest release is version ' . $info['version'] .
', stability "' . $info['info']->getState() . '", use "' .
$this->_registry->parsedPackageNameToString(
array('channel' => $pname['channel'], 'package' => $pname['package'],
'version' => $info['version'])) . '" to install');
return $err;
}
}
}
if (isset($info['deprecated']) && $info['deprecated']) {
$this->_downloader->log(0,
'WARNING: "' .
$this->_registry->parsedPackageNameToString(
array('channel' => $info['info']->getChannel(),
'package' => $info['info']->getPackage()), true) .
'" is deprecated in favor of "' .
$this->_registry->parsedPackageNameToString($info['deprecated'], true) .
'"');
}
return $info;
}
}
PK [^ ^ PEAR/PackageFile/v2/rw.phpnu W+A
* @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.0a8
*/
/**
* For base class
*/
require_once 'PEAR/PackageFile/v2.php';
/**
* @category pear
* @package PEAR
* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a8
*/
class PEAR_PackageFile_v2_rw extends PEAR_PackageFile_v2
{
/**
* @param string Extension name
* @return bool success of operation
*/
function setProvidesExtension($extension)
{
if (in_array($this->getPackageType(),
array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
if (!isset($this->_packageInfo['providesextension'])) {
// ensure that the channel tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
'bundle', 'changelog'),
$extension, 'providesextension');
}
$this->_packageInfo['providesextension'] = $extension;
return true;
}
return false;
}
function setPackage($package)
{
$this->_isValid = 0;
if (!isset($this->_packageInfo['attribs'])) {
$this->_packageInfo = array_merge(array('attribs' => array(
'version' => '2.0',
'xmlns' => 'http://pear.php.net/dtd/package-2.0',
'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
http://pear.php.net/dtd/tasks-1.0.xsd
http://pear.php.net/dtd/package-2.0
http://pear.php.net/dtd/package-2.0.xsd',
)), $this->_packageInfo);
}
if (!isset($this->_packageInfo['name'])) {
return $this->_packageInfo = array_merge(array('name' => $package),
$this->_packageInfo);
}
$this->_packageInfo['name'] = $package;
}
/**
* set this as a package.xml version 2.1
* @access private
*/
function _setPackageVersion2_1()
{
$info = array(
'version' => '2.1',
'xmlns' => 'http://pear.php.net/dtd/package-2.1',
'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
http://pear.php.net/dtd/tasks-1.0.xsd
http://pear.php.net/dtd/package-2.1
http://pear.php.net/dtd/package-2.1.xsd',
);
if (!isset($this->_packageInfo['attribs'])) {
$this->_packageInfo = array_merge(array('attribs' => $info), $this->_packageInfo);
} else {
$this->_packageInfo['attribs'] = $info;
}
}
function setUri($uri)
{
unset($this->_packageInfo['channel']);
$this->_isValid = 0;
if (!isset($this->_packageInfo['uri'])) {
// ensure that the uri tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('extends', 'summary', 'description', 'lead',
'developer', 'contributor', 'helper', 'date', 'time', 'version',
'stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'), $uri, 'uri');
}
$this->_packageInfo['uri'] = $uri;
}
function setChannel($channel)
{
unset($this->_packageInfo['uri']);
$this->_isValid = 0;
if (!isset($this->_packageInfo['channel'])) {
// ensure that the channel tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('extends', 'summary', 'description', 'lead',
'developer', 'contributor', 'helper', 'date', 'time', 'version',
'stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'), $channel, 'channel');
}
$this->_packageInfo['channel'] = $channel;
}
function setExtends($extends)
{
$this->_isValid = 0;
if (!isset($this->_packageInfo['extends'])) {
// ensure that the extends tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('summary', 'description', 'lead',
'developer', 'contributor', 'helper', 'date', 'time', 'version',
'stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'), $extends, 'extends');
}
$this->_packageInfo['extends'] = $extends;
}
function setSummary($summary)
{
$this->_isValid = 0;
if (!isset($this->_packageInfo['summary'])) {
// ensure that the summary tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('description', 'lead',
'developer', 'contributor', 'helper', 'date', 'time', 'version',
'stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'), $summary, 'summary');
}
$this->_packageInfo['summary'] = $summary;
}
function setDescription($desc)
{
$this->_isValid = 0;
if (!isset($this->_packageInfo['description'])) {
// ensure that the description tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('lead',
'developer', 'contributor', 'helper', 'date', 'time', 'version',
'stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'), $desc, 'description');
}
$this->_packageInfo['description'] = $desc;
}
/**
* Adds a new maintainer - no checking of duplicates is performed, use
* updatemaintainer for that purpose.
*/
function addMaintainer($role, $handle, $name, $email, $active = 'yes')
{
if (!in_array($role, array('lead', 'developer', 'contributor', 'helper'))) {
return false;
}
if (isset($this->_packageInfo[$role])) {
if (!isset($this->_packageInfo[$role][0])) {
$this->_packageInfo[$role] = array($this->_packageInfo[$role]);
}
$this->_packageInfo[$role][] =
array(
'name' => $name,
'user' => $handle,
'email' => $email,
'active' => $active,
);
} else {
$testarr = array('lead',
'developer', 'contributor', 'helper', 'date', 'time', 'version',
'stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog');
foreach (array('lead', 'developer', 'contributor', 'helper') as $testrole) {
array_shift($testarr);
if ($role == $testrole) {
break;
}
}
if (!isset($this->_packageInfo[$role])) {
// ensure that the extends tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, $testarr,
array(), $role);
}
$this->_packageInfo[$role] =
array(
'name' => $name,
'user' => $handle,
'email' => $email,
'active' => $active,
);
}
$this->_isValid = 0;
}
function updateMaintainer($newrole, $handle, $name, $email, $active = 'yes')
{
$found = false;
foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
if (!isset($this->_packageInfo[$role])) {
continue;
}
$info = $this->_packageInfo[$role];
if (!isset($info[0])) {
if ($info['user'] == $handle) {
$found = true;
break;
}
}
foreach ($info as $i => $maintainer) {
if (is_array($maintainer) && $maintainer['user'] == $handle) {
$found = $i;
break 2;
}
}
}
if ($found === false) {
return $this->addMaintainer($newrole, $handle, $name, $email, $active);
}
if ($found !== false) {
if ($found === true) {
unset($this->_packageInfo[$role]);
} else {
unset($this->_packageInfo[$role][$found]);
$this->_packageInfo[$role] = array_values($this->_packageInfo[$role]);
}
}
$this->addMaintainer($newrole, $handle, $name, $email, $active);
$this->_isValid = 0;
}
function deleteMaintainer($handle)
{
$found = false;
foreach (array('lead', 'developer', 'contributor', 'helper') as $role) {
if (!isset($this->_packageInfo[$role])) {
continue;
}
if (!isset($this->_packageInfo[$role][0])) {
$this->_packageInfo[$role] = array($this->_packageInfo[$role]);
}
foreach ($this->_packageInfo[$role] as $i => $maintainer) {
if ($maintainer['user'] == $handle) {
$found = $i;
break;
}
}
if ($found !== false) {
unset($this->_packageInfo[$role][$found]);
if (!count($this->_packageInfo[$role]) && $role == 'lead') {
$this->_isValid = 0;
}
if (!count($this->_packageInfo[$role])) {
unset($this->_packageInfo[$role]);
return true;
}
$this->_packageInfo[$role] =
array_values($this->_packageInfo[$role]);
if (count($this->_packageInfo[$role]) == 1) {
$this->_packageInfo[$role] = $this->_packageInfo[$role][0];
}
return true;
}
if (count($this->_packageInfo[$role]) == 1) {
$this->_packageInfo[$role] = $this->_packageInfo[$role][0];
}
}
return false;
}
function setReleaseVersion($version)
{
if (isset($this->_packageInfo['version']) &&
isset($this->_packageInfo['version']['release'])) {
unset($this->_packageInfo['version']['release']);
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'),
'release' => array('api')));
$this->_isValid = 0;
}
function setAPIVersion($version)
{
if (isset($this->_packageInfo['version']) &&
isset($this->_packageInfo['version']['api'])) {
unset($this->_packageInfo['version']['api']);
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $version, array(
'version' => array('stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'),
'api' => array()));
$this->_isValid = 0;
}
/**
* snapshot|devel|alpha|beta|stable
*/
function setReleaseStability($state)
{
if (isset($this->_packageInfo['stability']) &&
isset($this->_packageInfo['stability']['release'])) {
unset($this->_packageInfo['stability']['release']);
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
'stability' => array('license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'),
'release' => array('api')));
$this->_isValid = 0;
}
/**
* @param devel|alpha|beta|stable
*/
function setAPIStability($state)
{
if (isset($this->_packageInfo['stability']) &&
isset($this->_packageInfo['stability']['api'])) {
unset($this->_packageInfo['stability']['api']);
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $state, array(
'stability' => array('license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'),
'api' => array()));
$this->_isValid = 0;
}
function setLicense($license, $uri = false, $filesource = false)
{
if (!isset($this->_packageInfo['license'])) {
// ensure that the license tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'), 0, 'license');
}
if ($uri || $filesource) {
$attribs = array();
if ($uri) {
$attribs['uri'] = $uri;
}
$uri = true; // for test below
if ($filesource) {
$attribs['filesource'] = $filesource;
}
}
$license = $uri ? array('attribs' => $attribs, '_content' => $license) : $license;
$this->_packageInfo['license'] = $license;
$this->_isValid = 0;
}
function setNotes($notes)
{
$this->_isValid = 0;
if (!isset($this->_packageInfo['notes'])) {
// ensure that the notes tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('contents', 'compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'zendextsrcrelease', 'zendextbinrelease',
'extbinrelease', 'bundle', 'changelog'), $notes, 'notes');
}
$this->_packageInfo['notes'] = $notes;
}
/**
* This is only used at install-time, after all serialization
* is over.
* @param string file name
* @param string installed path
*/
function setInstalledAs($file, $path)
{
if ($path) {
return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
}
unset($this->_packageInfo['filelist'][$file]['installed_as']);
}
/**
* This is only used at install-time, after all serialization
* is over.
*/
function installedFile($file, $atts)
{
if (isset($this->_packageInfo['filelist'][$file])) {
$this->_packageInfo['filelist'][$file] =
array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']);
} else {
$this->_packageInfo['filelist'][$file] = $atts['attribs'];
}
}
/**
* Reset the listing of package contents
* @param string base installation dir for the whole package, if any
*/
function clearContents($baseinstall = false)
{
$this->_filesValid = false;
$this->_isValid = 0;
if (!isset($this->_packageInfo['contents'])) {
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('compatible',
'dependencies', 'providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
'bundle', 'changelog'), array(), 'contents');
}
if ($this->getPackageType() != 'bundle') {
$this->_packageInfo['contents'] =
array('dir' => array('attribs' => array('name' => '/')));
if ($baseinstall) {
$this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'] = $baseinstall;
}
} else {
$this->_packageInfo['contents'] = array('bundledpackage' => array());
}
}
/**
* @param string relative path of the bundled package.
*/
function addBundledPackage($path)
{
if ($this->getPackageType() != 'bundle') {
return false;
}
$this->_filesValid = false;
$this->_isValid = 0;
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $path, array(
'contents' => array('compatible', 'dependencies', 'providesextension',
'usesrole', 'usestask', 'srcpackage', 'srcuri', 'phprelease',
'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
'bundle', 'changelog'),
'bundledpackage' => array()));
}
/**
* @param string file name
* @param PEAR_Task_Common a read/write task
*/
function addTaskToFile($filename, $task)
{
if (!method_exists($task, 'getXml')) {
return false;
}
if (!method_exists($task, 'getName')) {
return false;
}
if (!method_exists($task, 'validate')) {
return false;
}
if (!$task->validate()) {
return false;
}
if (!isset($this->_packageInfo['contents']['dir']['file'])) {
return false;
}
$this->getTasksNs(); // discover the tasks namespace if not done already
$files = $this->_packageInfo['contents']['dir']['file'];
if (!isset($files[0])) {
$files = array($files);
$ind = false;
} else {
$ind = true;
}
foreach ($files as $i => $file) {
if (isset($file['attribs'])) {
if ($file['attribs']['name'] == $filename) {
if ($ind) {
$t = isset($this->_packageInfo['contents']['dir']['file'][$i]
['attribs'][$this->_tasksNs .
':' . $task->getName()]) ?
$this->_packageInfo['contents']['dir']['file'][$i]
['attribs'][$this->_tasksNs .
':' . $task->getName()] : false;
if ($t && !isset($t[0])) {
$this->_packageInfo['contents']['dir']['file'][$i]
[$this->_tasksNs . ':' . $task->getName()] = array($t);
}
$this->_packageInfo['contents']['dir']['file'][$i][$this->_tasksNs .
':' . $task->getName()][] = $task->getXml();
} else {
$t = isset($this->_packageInfo['contents']['dir']['file']
['attribs'][$this->_tasksNs .
':' . $task->getName()]) ? $this->_packageInfo['contents']['dir']['file']
['attribs'][$this->_tasksNs .
':' . $task->getName()] : false;
if ($t && !isset($t[0])) {
$this->_packageInfo['contents']['dir']['file']
[$this->_tasksNs . ':' . $task->getName()] = array($t);
}
$this->_packageInfo['contents']['dir']['file'][$this->_tasksNs .
':' . $task->getName()][] = $task->getXml();
}
return true;
}
}
}
return false;
}
/**
* @param string path to the file
* @param string filename
* @param array extra attributes
*/
function addFile($dir, $file, $attrs)
{
if ($this->getPackageType() == 'bundle') {
return false;
}
$this->_filesValid = false;
$this->_isValid = 0;
$dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir);
if ($dir == '/' || $dir == '') {
$dir = '';
} else {
$dir .= '/';
}
$attrs['name'] = $dir . $file;
if (!isset($this->_packageInfo['contents'])) {
// ensure that the contents tag is set up
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('compatible', 'dependencies', 'providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease',
'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
'bundle', 'changelog'), array(), 'contents');
}
if (isset($this->_packageInfo['contents']['dir']['file'])) {
if (!isset($this->_packageInfo['contents']['dir']['file'][0])) {
$this->_packageInfo['contents']['dir']['file'] =
array($this->_packageInfo['contents']['dir']['file']);
}
$this->_packageInfo['contents']['dir']['file'][]['attribs'] = $attrs;
} else {
$this->_packageInfo['contents']['dir']['file']['attribs'] = $attrs;
}
}
/**
* @param string Dependent package name
* @param string Dependent package's channel name
* @param string minimum version of specified package that this release is guaranteed to be
* compatible with
* @param string maximum version of specified package that this release is guaranteed to be
* compatible with
* @param string versions of specified package that this release is not compatible with
*/
function addCompatiblePackage($name, $channel, $min, $max, $exclude = false)
{
$this->_isValid = 0;
$set = array(
'name' => $name,
'channel' => $channel,
'min' => $min,
'max' => $max,
);
if ($exclude) {
$set['exclude'] = $exclude;
}
$this->_isValid = 0;
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
'compatible' => array('dependencies', 'providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
));
}
/**
* Removes the tag entirely
*/
function resetUsesrole()
{
if (isset($this->_packageInfo['usesrole'])) {
unset($this->_packageInfo['usesrole']);
}
}
/**
* @param string
* @param string package name or uri
* @param string channel name if non-uri
*/
function addUsesrole($role, $packageOrUri, $channel = false) {
$set = array('role' => $role);
if ($channel) {
$set['package'] = $packageOrUri;
$set['channel'] = $channel;
} else {
$set['uri'] = $packageOrUri;
}
$this->_isValid = 0;
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
'usesrole' => array('usestask', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
));
}
/**
* Removes the tag entirely
*/
function resetUsestask()
{
if (isset($this->_packageInfo['usestask'])) {
unset($this->_packageInfo['usestask']);
}
}
/**
* @param string
* @param string package name or uri
* @param string channel name if non-uri
*/
function addUsestask($task, $packageOrUri, $channel = false) {
$set = array('task' => $task);
if ($channel) {
$set['package'] = $packageOrUri;
$set['channel'] = $channel;
} else {
$set['uri'] = $packageOrUri;
}
$this->_isValid = 0;
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $set, array(
'usestask' => array('srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')
));
}
/**
* Remove all compatible tags
*/
function clearCompatible()
{
unset($this->_packageInfo['compatible']);
}
/**
* Reset dependencies prior to adding new ones
*/
function clearDeps()
{
if (!isset($this->_packageInfo['dependencies'])) {
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(),
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog')));
}
$this->_packageInfo['dependencies'] = array();
}
/**
* @param string minimum PHP version allowed
* @param string maximum PHP version allowed
* @param array $exclude incompatible PHP versions
*/
function setPhpDep($min, $max = false, $exclude = false)
{
$this->_isValid = 0;
$dep =
array(
'min' => $min,
);
if ($max) {
$dep['max'] = $max;
}
if ($exclude) {
if (count($exclude) == 1) {
$exclude = $exclude[0];
}
$dep['exclude'] = $exclude;
}
if (isset($this->_packageInfo['dependencies']['required']['php'])) {
$this->_stack->push(__FUNCTION__, 'warning', array('dep' =>
$this->_packageInfo['dependencies']['required']['php']),
'warning: PHP dependency already exists, overwriting');
unset($this->_packageInfo['dependencies']['required']['php']);
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
'required' => array('optional', 'group'),
'php' => array('pearinstaller', 'package', 'subpackage', 'extension', 'os', 'arch')
));
return true;
}
/**
* @param string minimum allowed PEAR installer version
* @param string maximum allowed PEAR installer version
* @param string recommended PEAR installer version
* @param array incompatible version of the PEAR installer
*/
function setPearinstallerDep($min, $max = false, $recommended = false, $exclude = false)
{
$this->_isValid = 0;
$dep =
array(
'min' => $min,
);
if ($max) {
$dep['max'] = $max;
}
if ($recommended) {
$dep['recommended'] = $recommended;
}
if ($exclude) {
if (count($exclude) == 1) {
$exclude = $exclude[0];
}
$dep['exclude'] = $exclude;
}
if (isset($this->_packageInfo['dependencies']['required']['pearinstaller'])) {
$this->_stack->push(__FUNCTION__, 'warning', array('dep' =>
$this->_packageInfo['dependencies']['required']['pearinstaller']),
'warning: PEAR Installer dependency already exists, overwriting');
unset($this->_packageInfo['dependencies']['required']['pearinstaller']);
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
'required' => array('optional', 'group'),
'pearinstaller' => array('package', 'subpackage', 'extension', 'os', 'arch')
));
}
/**
* Mark a package as conflicting with this package
* @param string package name
* @param string package channel
* @param string extension this package provides, if any
* @param string|false minimum version required
* @param string|false maximum version allowed
* @param array|false versions to exclude from installation
*/
function addConflictingPackageDepWithChannel($name, $channel,
$providesextension = false, $min = false, $max = false, $exclude = false)
{
$this->_isValid = 0;
$dep = $this->_constructDep($name, $channel, false, $min, $max, false,
$exclude, $providesextension, false, true);
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
'required' => array('optional', 'group'),
'package' => array('subpackage', 'extension', 'os', 'arch')
));
}
/**
* Mark a package as conflicting with this package
* @param string package name
* @param string package channel
* @param string extension this package provides, if any
*/
function addConflictingPackageDepWithUri($name, $uri, $providesextension = false)
{
$this->_isValid = 0;
$dep =
array(
'name' => $name,
'uri' => $uri,
'conflicts' => '',
);
if ($providesextension) {
$dep['providesextension'] = $providesextension;
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
'required' => array('optional', 'group'),
'package' => array('subpackage', 'extension', 'os', 'arch')
));
}
function addDependencyGroup($name, $hint)
{
$this->_isValid = 0;
$this->_packageInfo = $this->_mergeTag($this->_packageInfo,
array('attribs' => array('name' => $name, 'hint' => $hint)),
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
'group' => array(),
));
}
/**
* @param string package name
* @param string|false channel name, false if this is a uri
* @param string|false uri name, false if this is a channel
* @param string|false minimum version required
* @param string|false maximum version allowed
* @param string|false recommended installation version
* @param array|false versions to exclude from installation
* @param string extension this package provides, if any
* @param bool if true, tells the installer to ignore the default optional dependency group
* when installing this package
* @param bool if true, tells the installer to negate this dependency (conflicts)
* @return array
* @access private
*/
function _constructDep($name, $channel, $uri, $min, $max, $recommended, $exclude,
$providesextension = false, $nodefault = false,
$conflicts = false)
{
$dep =
array(
'name' => $name,
);
if ($channel) {
$dep['channel'] = $channel;
} elseif ($uri) {
$dep['uri'] = $uri;
}
if ($min) {
$dep['min'] = $min;
}
if ($max) {
$dep['max'] = $max;
}
if ($recommended) {
$dep['recommended'] = $recommended;
}
if ($exclude) {
if (is_array($exclude) && count($exclude) == 1) {
$exclude = $exclude[0];
}
$dep['exclude'] = $exclude;
}
if ($conflicts) {
$dep['conflicts'] = '';
}
if ($nodefault) {
$dep['nodefault'] = '';
}
if ($providesextension) {
$dep['providesextension'] = $providesextension;
}
return $dep;
}
/**
* @param package|subpackage
* @param string group name
* @param string package name
* @param string package channel
* @param string minimum version
* @param string maximum version
* @param string recommended version
* @param array|false optional excluded versions
* @param string extension this package provides, if any
* @param bool if true, tells the installer to ignore the default optional dependency group
* when installing this package
* @return bool false if the dependency group has not been initialized with
* {@link addDependencyGroup()}, or a subpackage is added with
* a providesextension
*/
function addGroupPackageDepWithChannel($type, $groupname, $name, $channel, $min = false,
$max = false, $recommended = false, $exclude = false,
$providesextension = false, $nodefault = false)
{
if ($type == 'subpackage' && $providesextension) {
return false; // subpackages must be php packages
}
$dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
$providesextension, $nodefault);
return $this->_addGroupDependency($type, $dep, $groupname);
}
/**
* @param package|subpackage
* @param string group name
* @param string package name
* @param string package uri
* @param string extension this package provides, if any
* @param bool if true, tells the installer to ignore the default optional dependency group
* when installing this package
* @return bool false if the dependency group has not been initialized with
* {@link addDependencyGroup()}
*/
function addGroupPackageDepWithURI($type, $groupname, $name, $uri, $providesextension = false,
$nodefault = false)
{
if ($type == 'subpackage' && $providesextension) {
return false; // subpackages must be php packages
}
$dep = $this->_constructDep($name, false, $uri, false, false, false, false,
$providesextension, $nodefault);
return $this->_addGroupDependency($type, $dep, $groupname);
}
/**
* @param string group name (must be pre-existing)
* @param string extension name
* @param string minimum version allowed
* @param string maximum version allowed
* @param string recommended version
* @param array incompatible versions
*/
function addGroupExtensionDep($groupname, $name, $min = false, $max = false,
$recommended = false, $exclude = false)
{
$this->_isValid = 0;
$dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
return $this->_addGroupDependency('extension', $dep, $groupname);
}
/**
* @param package|subpackage|extension
* @param array dependency contents
* @param string name of the dependency group to add this to
* @return boolean
* @access private
*/
function _addGroupDependency($type, $dep, $groupname)
{
$arr = array('subpackage', 'extension');
if ($type != 'package') {
array_shift($arr);
}
if ($type == 'extension') {
array_shift($arr);
}
if (!isset($this->_packageInfo['dependencies']['group'])) {
return false;
} else {
if (!isset($this->_packageInfo['dependencies']['group'][0])) {
if ($this->_packageInfo['dependencies']['group']['attribs']['name'] == $groupname) {
$this->_packageInfo['dependencies']['group'] = $this->_mergeTag(
$this->_packageInfo['dependencies']['group'], $dep,
array(
$type => $arr
));
$this->_isValid = 0;
return true;
} else {
return false;
}
} else {
foreach ($this->_packageInfo['dependencies']['group'] as $i => $group) {
if ($group['attribs']['name'] == $groupname) {
$this->_packageInfo['dependencies']['group'][$i] = $this->_mergeTag(
$this->_packageInfo['dependencies']['group'][$i], $dep,
array(
$type => $arr
));
$this->_isValid = 0;
return true;
}
}
return false;
}
}
}
/**
* @param optional|required
* @param string package name
* @param string package channel
* @param string minimum version
* @param string maximum version
* @param string recommended version
* @param string extension this package provides, if any
* @param bool if true, tells the installer to ignore the default optional dependency group
* when installing this package
* @param array|false optional excluded versions
*/
function addPackageDepWithChannel($type, $name, $channel, $min = false, $max = false,
$recommended = false, $exclude = false,
$providesextension = false, $nodefault = false)
{
if (!in_array($type, array('optional', 'required'), true)) {
$type = 'required';
}
$this->_isValid = 0;
$arr = array('optional', 'group');
if ($type != 'required') {
array_shift($arr);
}
$dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
$providesextension, $nodefault);
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
$type => $arr,
'package' => array('subpackage', 'extension', 'os', 'arch')
));
}
/**
* @param optional|required
* @param string name of the package
* @param string uri of the package
* @param string extension this package provides, if any
* @param bool if true, tells the installer to ignore the default optional dependency group
* when installing this package
*/
function addPackageDepWithUri($type, $name, $uri, $providesextension = false,
$nodefault = false)
{
$this->_isValid = 0;
$arr = array('optional', 'group');
if ($type != 'required') {
array_shift($arr);
}
$dep = $this->_constructDep($name, false, $uri, false, false, false, false,
$providesextension, $nodefault);
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
$type => $arr,
'package' => array('subpackage', 'extension', 'os', 'arch')
));
}
/**
* @param optional|required optional, required
* @param string package name
* @param string package channel
* @param string minimum version
* @param string maximum version
* @param string recommended version
* @param array incompatible versions
* @param bool if true, tells the installer to ignore the default optional dependency group
* when installing this package
*/
function addSubpackageDepWithChannel($type, $name, $channel, $min = false, $max = false,
$recommended = false, $exclude = false,
$nodefault = false)
{
$this->_isValid = 0;
$arr = array('optional', 'group');
if ($type != 'required') {
array_shift($arr);
}
$dep = $this->_constructDep($name, $channel, false, $min, $max, $recommended, $exclude,
$nodefault);
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
$type => $arr,
'subpackage' => array('extension', 'os', 'arch')
));
}
/**
* @param optional|required optional, required
* @param string package name
* @param string package uri for download
* @param bool if true, tells the installer to ignore the default optional dependency group
* when installing this package
*/
function addSubpackageDepWithUri($type, $name, $uri, $nodefault = false)
{
$this->_isValid = 0;
$arr = array('optional', 'group');
if ($type != 'required') {
array_shift($arr);
}
$dep = $this->_constructDep($name, false, $uri, false, false, false, false, $nodefault);
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
$type => $arr,
'subpackage' => array('extension', 'os', 'arch')
));
}
/**
* @param optional|required optional, required
* @param string extension name
* @param string minimum version
* @param string maximum version
* @param string recommended version
* @param array incompatible versions
*/
function addExtensionDep($type, $name, $min = false, $max = false, $recommended = false,
$exclude = false)
{
$this->_isValid = 0;
$arr = array('optional', 'group');
if ($type != 'required') {
array_shift($arr);
}
$dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
$type => $arr,
'extension' => array('os', 'arch')
));
}
/**
* @param string Operating system name
* @param boolean true if this package cannot be installed on this OS
*/
function addOsDep($name, $conflicts = false)
{
$this->_isValid = 0;
$dep = array('name' => $name);
if ($conflicts) {
$dep['conflicts'] = '';
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
'required' => array('optional', 'group'),
'os' => array('arch')
));
}
/**
* @param string Architecture matching pattern
* @param boolean true if this package cannot be installed on this architecture
*/
function addArchDep($pattern, $conflicts = false)
{
$this->_isValid = 0;
$dep = array('pattern' => $pattern);
if ($conflicts) {
$dep['conflicts'] = '';
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, $dep,
array(
'dependencies' => array('providesextension', 'usesrole', 'usestask',
'srcpackage', 'srcuri', 'phprelease', 'extsrcrelease', 'extbinrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle', 'changelog'),
'required' => array('optional', 'group'),
'arch' => array()
));
}
/**
* Set the kind of package, and erase all release tags
*
* - a php package is a PEAR-style package
* - an extbin package is a PECL-style extension binary
* - an extsrc package is a PECL-style source for a binary
* - an zendextbin package is a PECL-style zend extension binary
* - an zendextsrc package is a PECL-style source for a zend extension binary
* - a bundle package is a collection of other pre-packaged packages
* @param php|extbin|extsrc|zendextsrc|zendextbin|bundle
* @return bool success
*/
function setPackageType($type)
{
$this->_isValid = 0;
if (!in_array($type, array('php', 'extbin', 'extsrc', 'zendextsrc',
'zendextbin', 'bundle'))) {
return false;
}
if (in_array($type, array('zendextsrc', 'zendextbin'))) {
$this->_setPackageVersion2_1();
}
if ($type != 'bundle') {
$type .= 'release';
}
foreach (array('phprelease', 'extbinrelease', 'extsrcrelease',
'zendextsrcrelease', 'zendextbinrelease', 'bundle') as $test) {
unset($this->_packageInfo[$test]);
}
if (!isset($this->_packageInfo[$type])) {
// ensure that the release tag is set up
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('changelog'),
array(), $type);
}
$this->_packageInfo[$type] = array();
return true;
}
/**
* @return bool true if package type is set up
*/
function addRelease()
{
if ($type = $this->getPackageType()) {
if ($type != 'bundle') {
$type .= 'release';
}
$this->_packageInfo = $this->_mergeTag($this->_packageInfo, array(),
array($type => array('changelog')));
return true;
}
return false;
}
/**
* Get the current release tag in order to add to it
* @param bool returns only releases that have installcondition if true
* @return array|null
*/
function &_getCurrentRelease($strict = true)
{
if ($p = $this->getPackageType()) {
if ($strict) {
if ($p == 'extsrc' || $p == 'zendextsrc') {
$a = null;
return $a;
}
}
if ($p != 'bundle') {
$p .= 'release';
}
if (isset($this->_packageInfo[$p][0])) {
return $this->_packageInfo[$p][count($this->_packageInfo[$p]) - 1];
} else {
return $this->_packageInfo[$p];
}
} else {
$a = null;
return $a;
}
}
/**
* Add a file to the current release that should be installed under a different name
* @param string path to file
* @param string name the file should be installed as
*/
function addInstallAs($path, $as)
{
$r = &$this->_getCurrentRelease();
if ($r === null) {
return false;
}
$this->_isValid = 0;
$r = $this->_mergeTag($r, array('attribs' => array('name' => $path, 'as' => $as)),
array(
'filelist' => array(),
'install' => array('ignore')
));
}
/**
* Add a file to the current release that should be ignored
* @param string path to file
* @return bool success of operation
*/
function addIgnore($path)
{
$r = &$this->_getCurrentRelease();
if ($r === null) {
return false;
}
$this->_isValid = 0;
$r = $this->_mergeTag($r, array('attribs' => array('name' => $path)),
array(
'filelist' => array(),
'ignore' => array()
));
}
/**
* Add an extension binary package for this extension source code release
*
* Note that the package must be from the same channel as the extension source package
* @param string
*/
function addBinarypackage($package)
{
if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
return false;
}
$r = &$this->_getCurrentRelease(false);
if ($r === null) {
return false;
}
$this->_isValid = 0;
$r = $this->_mergeTag($r, $package,
array(
'binarypackage' => array('filelist'),
));
}
/**
* Add a configureoption to an extension source package
* @param string
* @param string
* @param string
*/
function addConfigureOption($name, $prompt, $default = null)
{
if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
return false;
}
$r = &$this->_getCurrentRelease(false);
if ($r === null) {
return false;
}
$opt = array('attribs' => array('name' => $name, 'prompt' => $prompt));
if ($default !== null) {
$opt['attribs']['default'] = $default;
}
$this->_isValid = 0;
$r = $this->_mergeTag($r, $opt,
array(
'configureoption' => array('binarypackage', 'filelist'),
));
}
/**
* Set an installation condition based on php version for the current release set
* @param string minimum version
* @param string maximum version
* @param false|array incompatible versions of PHP
*/
function setPhpInstallCondition($min, $max, $exclude = false)
{
$r = &$this->_getCurrentRelease();
if ($r === null) {
return false;
}
$this->_isValid = 0;
if (isset($r['installconditions']['php'])) {
unset($r['installconditions']['php']);
}
$dep = array('min' => $min, 'max' => $max);
if ($exclude) {
if (is_array($exclude) && count($exclude) == 1) {
$exclude = $exclude[0];
}
$dep['exclude'] = $exclude;
}
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
$r = $this->_mergeTag($r, $dep,
array(
'installconditions' => array('configureoption', 'binarypackage',
'filelist'),
'php' => array('extension', 'os', 'arch')
));
} else {
$r = $this->_mergeTag($r, $dep,
array(
'installconditions' => array('filelist'),
'php' => array('extension', 'os', 'arch')
));
}
}
/**
* @param optional|required optional, required
* @param string extension name
* @param string minimum version
* @param string maximum version
* @param string recommended version
* @param array incompatible versions
*/
function addExtensionInstallCondition($name, $min = false, $max = false, $recommended = false,
$exclude = false)
{
$r = &$this->_getCurrentRelease();
if ($r === null) {
return false;
}
$this->_isValid = 0;
$dep = $this->_constructDep($name, false, false, $min, $max, $recommended, $exclude);
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
$r = $this->_mergeTag($r, $dep,
array(
'installconditions' => array('configureoption', 'binarypackage',
'filelist'),
'extension' => array('os', 'arch')
));
} else {
$r = $this->_mergeTag($r, $dep,
array(
'installconditions' => array('filelist'),
'extension' => array('os', 'arch')
));
}
}
/**
* Set an installation condition based on operating system for the current release set
* @param string OS name
* @param bool whether this OS is incompatible with the current release
*/
function setOsInstallCondition($name, $conflicts = false)
{
$r = &$this->_getCurrentRelease();
if ($r === null) {
return false;
}
$this->_isValid = 0;
if (isset($r['installconditions']['os'])) {
unset($r['installconditions']['os']);
}
$dep = array('name' => $name);
if ($conflicts) {
$dep['conflicts'] = '';
}
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
$r = $this->_mergeTag($r, $dep,
array(
'installconditions' => array('configureoption', 'binarypackage',
'filelist'),
'os' => array('arch')
));
} else {
$r = $this->_mergeTag($r, $dep,
array(
'installconditions' => array('filelist'),
'os' => array('arch')
));
}
}
/**
* Set an installation condition based on architecture for the current release set
* @param string architecture pattern
* @param bool whether this arch is incompatible with the current release
*/
function setArchInstallCondition($pattern, $conflicts = false)
{
$r = &$this->_getCurrentRelease();
if ($r === null) {
return false;
}
$this->_isValid = 0;
if (isset($r['installconditions']['arch'])) {
unset($r['installconditions']['arch']);
}
$dep = array('pattern' => $pattern);
if ($conflicts) {
$dep['conflicts'] = '';
}
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
$r = $this->_mergeTag($r, $dep,
array(
'installconditions' => array('configureoption', 'binarypackage',
'filelist'),
'arch' => array()
));
} else {
$r = $this->_mergeTag($r, $dep,
array(
'installconditions' => array('filelist'),
'arch' => array()
));
}
}
/**
* For extension binary releases, this is used to specify either the
* static URI to a source package, or the package name and channel of the extsrc/zendextsrc
* package it is based on.
* @param string Package name, or full URI to source package (extsrc/zendextsrc type)
*/
function setSourcePackage($packageOrUri)
{
$this->_isValid = 0;
if (isset($this->_packageInfo['channel'])) {
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
'bundle', 'changelog'),
$packageOrUri, 'srcpackage');
} else {
$this->_packageInfo = $this->_insertBefore($this->_packageInfo, array('phprelease',
'extsrcrelease', 'extbinrelease', 'zendextsrcrelease', 'zendextbinrelease',
'bundle', 'changelog'), $packageOrUri, 'srcuri');
}
}
/**
* Generate a valid change log entry from the current package.xml
* @param string|false
*/
function generateChangeLogEntry($notes = false)
{
return array(
'version' =>
array(
'release' => $this->getVersion('release'),
'api' => $this->getVersion('api'),
),
'stability' =>
$this->getStability(),
'date' => $this->getDate(),
'license' => $this->getLicense(true),
'notes' => $notes ? $notes : $this->getNotes()
);
}
/**
* @param string release version to set change log notes for
* @param array output of {@link generateChangeLogEntry()}
*/
function setChangelogEntry($releaseversion, $contents)
{
if (!isset($this->_packageInfo['changelog'])) {
$this->_packageInfo['changelog']['release'] = $contents;
return;
}
if (!isset($this->_packageInfo['changelog']['release'][0])) {
if ($this->_packageInfo['changelog']['release']['version']['release'] == $releaseversion) {
$this->_packageInfo['changelog']['release'] = array(
$this->_packageInfo['changelog']['release']);
} else {
$this->_packageInfo['changelog']['release'] = array(
$this->_packageInfo['changelog']['release']);
return $this->_packageInfo['changelog']['release'][] = $contents;
}
}
foreach($this->_packageInfo['changelog']['release'] as $index => $changelog) {
if (isset($changelog['version']) &&
strnatcasecmp($changelog['version']['release'], $releaseversion) == 0) {
$curlog = $index;
}
}
if (isset($curlog)) {
$this->_packageInfo['changelog']['release'][$curlog] = $contents;
} else {
$this->_packageInfo['changelog']['release'][] = $contents;
}
}
/**
* Remove the changelog entirely
*/
function clearChangeLog()
{
unset($this->_packageInfo['changelog']);
}
}PK [JB`bzL zL ! PEAR/PackageFile/v2/Validator.phpnu W+A
* @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.0a8
*/
/**
* Private validation class used by PEAR_PackageFile_v2 - do not use directly, its
* sole purpose is to split up the PEAR/PackageFile/v2.php file to make it smaller
* @category pear
* @package PEAR
* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a8
* @access private
*/
class PEAR_PackageFile_v2_Validator
{
/**
* @var array
*/
var $_packageInfo;
/**
* @var PEAR_PackageFile_v2
*/
var $_pf;
/**
* @var PEAR_ErrorStack
*/
var $_stack;
/**
* @var int
*/
var $_isValid = 0;
/**
* @var int
*/
var $_filesValid = 0;
/**
* @var int
*/
var $_curState = 0;
/**
* @param PEAR_PackageFile_v2
* @param int
*/
function validate(&$pf, $state = PEAR_VALIDATE_NORMAL)
{
$this->_pf = &$pf;
$this->_curState = $state;
$this->_packageInfo = $this->_pf->getArray();
$this->_isValid = $this->_pf->_isValid;
$this->_filesValid = $this->_pf->_filesValid;
$this->_stack = &$pf->_stack;
$this->_stack->getErrors(true);
if (($this->_isValid & $state) == $state) {
return true;
}
if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
return false;
}
if (!isset($this->_packageInfo['attribs']['version']) ||
($this->_packageInfo['attribs']['version'] != '2.0' &&
$this->_packageInfo['attribs']['version'] != '2.1')
) {
$this->_noPackageVersion();
}
$structure =
array(
'name',
'channel|uri',
'*extends', // can't be multiple, but this works fine
'summary',
'description',
'+lead', // these all need content checks
'*developer',
'*contributor',
'*helper',
'date',
'*time',
'version',
'stability',
'license->?uri->?filesource',
'notes',
'contents', //special validation needed
'*compatible',
'dependencies', //special validation needed
'*usesrole',
'*usestask', // reserve these for 1.4.0a1 to implement
// this will allow a package.xml to gracefully say it
// needs a certain package installed in order to implement a role or task
'*providesextension',
'*srcpackage|*srcuri',
'+phprelease|+extsrcrelease|+extbinrelease|' .
'+zendextsrcrelease|+zendextbinrelease|bundle', //special validation needed
'*changelog',
);
$test = $this->_packageInfo;
if (isset($test['dependencies']) &&
isset($test['dependencies']['required']) &&
isset($test['dependencies']['required']['pearinstaller']) &&
isset($test['dependencies']['required']['pearinstaller']['min']) &&
'1.10.4' != '@package' . '_version@' &&
version_compare('1.10.4',
$test['dependencies']['required']['pearinstaller']['min'], '<')
) {
$this->_pearVersionTooLow($test['dependencies']['required']['pearinstaller']['min']);
return false;
}
// ignore post-installation array fields
if (array_key_exists('filelist', $test)) {
unset($test['filelist']);
}
if (array_key_exists('_lastmodified', $test)) {
unset($test['_lastmodified']);
}
if (array_key_exists('#binarypackage', $test)) {
unset($test['#binarypackage']);
}
if (array_key_exists('old', $test)) {
unset($test['old']);
}
if (array_key_exists('_lastversion', $test)) {
unset($test['_lastversion']);
}
if (!$this->_stupidSchemaValidate($structure, $test, '')) {
return false;
}
if (empty($this->_packageInfo['name'])) {
$this->_tagCannotBeEmpty('name');
}
$test = isset($this->_packageInfo['uri']) ? 'uri' :'channel';
if (empty($this->_packageInfo[$test])) {
$this->_tagCannotBeEmpty($test);
}
if (is_array($this->_packageInfo['license']) &&
(!isset($this->_packageInfo['license']['_content']) ||
empty($this->_packageInfo['license']['_content']))) {
$this->_tagCannotBeEmpty('license');
} elseif (empty($this->_packageInfo['license'])) {
$this->_tagCannotBeEmpty('license');
}
if (empty($this->_packageInfo['summary'])) {
$this->_tagCannotBeEmpty('summary');
}
if (empty($this->_packageInfo['description'])) {
$this->_tagCannotBeEmpty('description');
}
if (empty($this->_packageInfo['date'])) {
$this->_tagCannotBeEmpty('date');
}
if (empty($this->_packageInfo['notes'])) {
$this->_tagCannotBeEmpty('notes');
}
if (isset($this->_packageInfo['time']) && empty($this->_packageInfo['time'])) {
$this->_tagCannotBeEmpty('time');
}
if (isset($this->_packageInfo['dependencies'])) {
$this->_validateDependencies();
}
if (isset($this->_packageInfo['compatible'])) {
$this->_validateCompatible();
}
if (!isset($this->_packageInfo['bundle'])) {
if (empty($this->_packageInfo['contents'])) {
$this->_tagCannotBeEmpty('contents');
}
if (!isset($this->_packageInfo['contents']['dir'])) {
$this->_filelistMustContainDir('contents');
return false;
}
if (isset($this->_packageInfo['contents']['file'])) {
$this->_filelistCannotContainFile('contents');
return false;
}
}
$this->_validateMaintainers();
$this->_validateStabilityVersion();
$fail = false;
if (array_key_exists('usesrole', $this->_packageInfo)) {
$roles = $this->_packageInfo['usesrole'];
if (!is_array($roles) || !isset($roles[0])) {
$roles = array($roles);
}
foreach ($roles as $role) {
if (!isset($role['role'])) {
$this->_usesroletaskMustHaveRoleTask('usesrole', 'role');
$fail = true;
} else {
if (!isset($role['channel'])) {
if (!isset($role['uri'])) {
$this->_usesroletaskMustHaveChannelOrUri($role['role'], 'usesrole');
$fail = true;
}
} elseif (!isset($role['package'])) {
$this->_usesroletaskMustHavePackage($role['role'], 'usesrole');
$fail = true;
}
}
}
}
if (array_key_exists('usestask', $this->_packageInfo)) {
$roles = $this->_packageInfo['usestask'];
if (!is_array($roles) || !isset($roles[0])) {
$roles = array($roles);
}
foreach ($roles as $role) {
if (!isset($role['task'])) {
$this->_usesroletaskMustHaveRoleTask('usestask', 'task');
$fail = true;
} else {
if (!isset($role['channel'])) {
if (!isset($role['uri'])) {
$this->_usesroletaskMustHaveChannelOrUri($role['task'], 'usestask');
$fail = true;
}
} elseif (!isset($role['package'])) {
$this->_usesroletaskMustHavePackage($role['task'], 'usestask');
$fail = true;
}
}
}
}
if ($fail) {
return false;
}
$list = $this->_packageInfo['contents'];
if (isset($list['dir']) && is_array($list['dir']) && isset($list['dir'][0])) {
$this->_multipleToplevelDirNotAllowed();
return $this->_isValid = 0;
}
$this->_validateFilelist();
$this->_validateRelease();
if (!$this->_stack->hasErrors()) {
$chan = $this->_pf->_registry->getChannel($this->_pf->getChannel(), true);
if (PEAR::isError($chan)) {
$this->_unknownChannel($this->_pf->getChannel());
} else {
$valpack = $chan->getValidationPackage();
// for channel validator packages, always use the default PEAR validator.
// otherwise, they can't be installed or packaged
$validator = $chan->getValidationObject($this->_pf->getPackage());
if (!$validator) {
$this->_stack->push(__FUNCTION__, 'error',
array('channel' => $chan->getName(),
'package' => $this->_pf->getPackage(),
'name' => $valpack['_content'],
'version' => $valpack['attribs']['version']),
'package "%channel%/%package%" cannot be properly validated without ' .
'validation package "%channel%/%name%-%version%"');
return $this->_isValid = 0;
}
$validator->setPackageFile($this->_pf);
$validator->validate($state);
$failures = $validator->getFailures();
foreach ($failures['errors'] as $error) {
$this->_stack->push(__FUNCTION__, 'error', $error,
'Channel validator error: field "%field%" - %reason%');
}
foreach ($failures['warnings'] as $warning) {
$this->_stack->push(__FUNCTION__, 'warning', $warning,
'Channel validator warning: field "%field%" - %reason%');
}
}
}
$this->_pf->_isValid = $this->_isValid = !$this->_stack->hasErrors('error');
if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$this->_filesValid) {
if ($this->_pf->getPackageType() == 'bundle') {
if ($this->_analyzeBundledPackages()) {
$this->_filesValid = $this->_pf->_filesValid = true;
} else {
$this->_pf->_isValid = $this->_isValid = 0;
}
} else {
if (!$this->_analyzePhpFiles()) {
$this->_pf->_isValid = $this->_isValid = 0;
} else {
$this->_filesValid = $this->_pf->_filesValid = true;
}
}
}
if ($this->_isValid) {
return $this->_pf->_isValid = $this->_isValid = $state;
}
return $this->_pf->_isValid = $this->_isValid = 0;
}
function _stupidSchemaValidate($structure, $xml, $root)
{
if (!is_array($xml)) {
$xml = array();
}
$keys = array_keys($xml);
reset($keys);
$key = current($keys);
while ($key == 'attribs' || $key == '_contents') {
$key = next($keys);
}
$unfoundtags = $optionaltags = array();
$ret = true;
$mismatch = false;
foreach ($structure as $struc) {
if ($key) {
$tag = $xml[$key];
}
$test = $this->_processStructure($struc);
if (isset($test['choices'])) {
$loose = true;
foreach ($test['choices'] as $choice) {
if ($key == $choice['tag']) {
$key = next($keys);
while ($key == 'attribs' || $key == '_contents') {
$key = next($keys);
}
$unfoundtags = $optionaltags = array();
$mismatch = false;
if ($key && $key != $choice['tag'] && isset($choice['multiple'])) {
$unfoundtags[] = $choice['tag'];
$optionaltags[] = $choice['tag'];
if ($key) {
$mismatch = true;
}
}
$ret &= $this->_processAttribs($choice, $tag, $root);
continue 2;
} else {
$unfoundtags[] = $choice['tag'];
$mismatch = true;
}
if (!isset($choice['multiple']) || $choice['multiple'] != '*') {
$loose = false;
} else {
$optionaltags[] = $choice['tag'];
}
}
if (!$loose) {
$this->_invalidTagOrder($unfoundtags, $key, $root);
return false;
}
} else {
if ($key != $test['tag']) {
if (isset($test['multiple']) && $test['multiple'] != '*') {
$unfoundtags[] = $test['tag'];
$this->_invalidTagOrder($unfoundtags, $key, $root);
return false;
} else {
if ($key) {
$mismatch = true;
}
$unfoundtags[] = $test['tag'];
$optionaltags[] = $test['tag'];
}
if (!isset($test['multiple'])) {
$this->_invalidTagOrder($unfoundtags, $key, $root);
return false;
}
continue;
} else {
$unfoundtags = $optionaltags = array();
$mismatch = false;
}
$key = next($keys);
while ($key == 'attribs' || $key == '_contents') {
$key = next($keys);
}
if ($key && $key != $test['tag'] && isset($test['multiple'])) {
$unfoundtags[] = $test['tag'];
$optionaltags[] = $test['tag'];
$mismatch = true;
}
$ret &= $this->_processAttribs($test, $tag, $root);
continue;
}
}
if (!$mismatch && count($optionaltags)) {
// don't error out on any optional tags
$unfoundtags = array_diff($unfoundtags, $optionaltags);
}
if (count($unfoundtags)) {
$this->_invalidTagOrder($unfoundtags, $key, $root);
} elseif ($key) {
// unknown tags
$this->_invalidTagOrder('*no tags allowed here*', $key, $root);
while ($key = next($keys)) {
$this->_invalidTagOrder('*no tags allowed here*', $key, $root);
}
}
return $ret;
}
function _processAttribs($choice, $tag, $context)
{
if (isset($choice['attribs'])) {
if (!is_array($tag)) {
$tag = array($tag);
}
$tags = $tag;
if (!isset($tags[0])) {
$tags = array($tags);
}
$ret = true;
foreach ($tags as $i => $tag) {
if (!is_array($tag) || !isset($tag['attribs'])) {
foreach ($choice['attribs'] as $attrib) {
if ($attrib{0} != '?') {
$ret &= $this->_tagHasNoAttribs($choice['tag'],
$context);
continue 2;
}
}
}
foreach ($choice['attribs'] as $attrib) {
if ($attrib{0} != '?') {
if (!isset($tag['attribs'][$attrib])) {
$ret &= $this->_tagMissingAttribute($choice['tag'],
$attrib, $context);
}
}
}
}
return $ret;
}
return true;
}
function _processStructure($key)
{
$ret = array();
if (count($pieces = explode('|', $key)) > 1) {
$ret['choices'] = array();
foreach ($pieces as $piece) {
$ret['choices'][] = $this->_processStructure($piece);
}
return $ret;
}
$multi = $key{0};
if ($multi == '+' || $multi == '*') {
$ret['multiple'] = $key{0};
$key = substr($key, 1);
}
if (count($attrs = explode('->', $key)) > 1) {
$ret['tag'] = array_shift($attrs);
$ret['attribs'] = $attrs;
} else {
$ret['tag'] = $key;
}
return $ret;
}
function _validateStabilityVersion()
{
$structure = array('release', 'api');
$a = $this->_stupidSchemaValidate($structure, $this->_packageInfo['version'], '');
$a &= $this->_stupidSchemaValidate($structure, $this->_packageInfo['stability'], '');
if ($a) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
$this->_packageInfo['version']['release'])) {
$this->_invalidVersion('release', $this->_packageInfo['version']['release']);
}
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
$this->_packageInfo['version']['api'])) {
$this->_invalidVersion('api', $this->_packageInfo['version']['api']);
}
if (!in_array($this->_packageInfo['stability']['release'],
array('snapshot', 'devel', 'alpha', 'beta', 'stable'))) {
$this->_invalidState('release', $this->_packageInfo['stability']['release']);
}
if (!in_array($this->_packageInfo['stability']['api'],
array('devel', 'alpha', 'beta', 'stable'))) {
$this->_invalidState('api', $this->_packageInfo['stability']['api']);
}
}
}
function _validateMaintainers()
{
$structure =
array(
'name',
'user',
'email',
'active',
);
foreach (array('lead', 'developer', 'contributor', 'helper') as $type) {
if (!isset($this->_packageInfo[$type])) {
continue;
}
if (isset($this->_packageInfo[$type][0])) {
foreach ($this->_packageInfo[$type] as $lead) {
$this->_stupidSchemaValidate($structure, $lead, '<' . $type . '>');
}
} else {
$this->_stupidSchemaValidate($structure, $this->_packageInfo[$type],
'<' . $type . '>');
}
}
}
function _validatePhpDep($dep, $installcondition = false)
{
$structure = array(
'min',
'*max',
'*exclude',
);
$type = $installcondition ? '' : '';
$this->_stupidSchemaValidate($structure, $dep, $type);
if (isset($dep['min'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
$dep['min'])) {
$this->_invalidVersion($type . '', $dep['min']);
}
}
if (isset($dep['max'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
$dep['max'])) {
$this->_invalidVersion($type . '', $dep['max']);
}
}
if (isset($dep['exclude'])) {
if (!is_array($dep['exclude'])) {
$dep['exclude'] = array($dep['exclude']);
}
foreach ($dep['exclude'] as $exclude) {
if (!preg_match(
'/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?(?:-[a-zA-Z0-9]+)?\\z/',
$exclude)) {
$this->_invalidVersion($type . '', $exclude);
}
}
}
}
function _validatePearinstallerDep($dep)
{
$structure = array(
'min',
'*max',
'*recommended',
'*exclude',
);
$this->_stupidSchemaValidate($structure, $dep, '');
if (isset($dep['min'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
$dep['min'])) {
$this->_invalidVersion('',
$dep['min']);
}
}
if (isset($dep['max'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
$dep['max'])) {
$this->_invalidVersion('',
$dep['max']);
}
}
if (isset($dep['recommended'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
$dep['recommended'])) {
$this->_invalidVersion('',
$dep['recommended']);
}
}
if (isset($dep['exclude'])) {
if (!is_array($dep['exclude'])) {
$dep['exclude'] = array($dep['exclude']);
}
foreach ($dep['exclude'] as $exclude) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
$exclude)) {
$this->_invalidVersion('',
$exclude);
}
}
}
}
function _validatePackageDep($dep, $group, $type = '')
{
if (isset($dep['uri'])) {
if (isset($dep['conflicts'])) {
$structure = array(
'name',
'uri',
'conflicts',
'*providesextension',
);
} else {
$structure = array(
'name',
'uri',
'*providesextension',
);
}
} else {
if (isset($dep['conflicts'])) {
$structure = array(
'name',
'channel',
'*min',
'*max',
'*exclude',
'conflicts',
'*providesextension',
);
} else {
$structure = array(
'name',
'channel',
'*min',
'*max',
'*recommended',
'*exclude',
'*nodefault',
'*providesextension',
);
}
}
if (isset($dep['name'])) {
$type .= '' . $dep['name'] . '';
}
$this->_stupidSchemaValidate($structure, $dep, '' . $group . $type);
if (isset($dep['uri']) && (isset($dep['min']) || isset($dep['max']) ||
isset($dep['recommended']) || isset($dep['exclude']))) {
$this->_uriDepsCannotHaveVersioning('' . $group . $type);
}
if (isset($dep['channel']) && strtolower($dep['channel']) == '__uri') {
$this->_DepchannelCannotBeUri('' . $group . $type);
}
if (isset($dep['min'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
$dep['min'])) {
$this->_invalidVersion('' . $group . $type . '', $dep['min']);
}
}
if (isset($dep['max'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
$dep['max'])) {
$this->_invalidVersion('' . $group . $type . '', $dep['max']);
}
}
if (isset($dep['recommended'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
$dep['recommended'])) {
$this->_invalidVersion('' . $group . $type . '',
$dep['recommended']);
}
}
if (isset($dep['exclude'])) {
if (!is_array($dep['exclude'])) {
$dep['exclude'] = array($dep['exclude']);
}
foreach ($dep['exclude'] as $exclude) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
$exclude)) {
$this->_invalidVersion('' . $group . $type . '',
$exclude);
}
}
}
}
function _validateSubpackageDep($dep, $group)
{
$this->_validatePackageDep($dep, $group, '');
if (isset($dep['providesextension'])) {
$this->_subpackageCannotProvideExtension(isset($dep['name']) ? $dep['name'] : '');
}
if (isset($dep['conflicts'])) {
$this->_subpackagesCannotConflict(isset($dep['name']) ? $dep['name'] : '');
}
}
function _validateExtensionDep($dep, $group = false, $installcondition = false)
{
if (isset($dep['conflicts'])) {
$structure = array(
'name',
'*min',
'*max',
'*exclude',
'conflicts',
);
} else {
$structure = array(
'name',
'*min',
'*max',
'*recommended',
'*exclude',
);
}
if ($installcondition) {
$type = '';
} else {
$type = '' . $group . '';
}
if (isset($dep['name'])) {
$type .= '' . $dep['name'] . '';
}
$this->_stupidSchemaValidate($structure, $dep, $type);
if (isset($dep['min'])) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
$dep['min'])) {
$this->_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '' : '';
if ($this->_stupidSchemaValidate($structure, $dep, $type)) {
if ($dep['name'] == '*') {
if (array_key_exists('conflicts', $dep)) {
$this->_cannotConflictWithAllOs($type);
}
}
}
}
function _validateArchDep($dep, $installcondition = false)
{
$structure = array(
'pattern',
'*conflicts',
);
$type = $installcondition ? '' : '';
$this->_stupidSchemaValidate($structure, $dep, $type);
}
function _validateInstallConditions($cond, $release)
{
$structure = array(
'*php',
'*extension',
'*os',
'*arch',
);
if (!$this->_stupidSchemaValidate($structure,
$cond, $release)) {
return false;
}
foreach (array('php', 'extension', 'os', 'arch') as $type) {
if (isset($cond[$type])) {
$iter = $cond[$type];
if (!is_array($iter) || !isset($iter[0])) {
$iter = array($iter);
}
foreach ($iter as $package) {
if ($type == 'extension') {
$this->{"_validate{$type}Dep"}($package, false, true);
} else {
$this->{"_validate{$type}Dep"}($package, true);
}
}
}
}
}
function _validateDependencies()
{
$structure = array(
'required',
'*optional',
'*group->name->hint'
);
if (!$this->_stupidSchemaValidate($structure,
$this->_packageInfo['dependencies'], '')) {
return false;
}
foreach (array('required', 'optional') as $simpledep) {
if (isset($this->_packageInfo['dependencies'][$simpledep])) {
if ($simpledep == 'optional') {
$structure = array(
'*package',
'*subpackage',
'*extension',
);
} else {
$structure = array(
'php',
'pearinstaller',
'*package',
'*subpackage',
'*extension',
'*os',
'*arch',
);
}
if ($this->_stupidSchemaValidate($structure,
$this->_packageInfo['dependencies'][$simpledep],
"<$simpledep>")) {
foreach (array('package', 'subpackage', 'extension') as $type) {
if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
$iter = $this->_packageInfo['dependencies'][$simpledep][$type];
if (!isset($iter[0])) {
$iter = array($iter);
}
foreach ($iter as $package) {
if ($type != 'extension') {
if (isset($package['uri'])) {
if (isset($package['channel'])) {
$this->_UrlOrChannel($type,
$package['name']);
}
} else {
if (!isset($package['channel'])) {
$this->_NoChannel($type, $package['name']);
}
}
}
$this->{"_validate{$type}Dep"}($package, "<$simpledep>");
}
}
}
if ($simpledep == 'optional') {
continue;
}
foreach (array('php', 'pearinstaller', 'os', 'arch') as $type) {
if (isset($this->_packageInfo['dependencies'][$simpledep][$type])) {
$iter = $this->_packageInfo['dependencies'][$simpledep][$type];
if (!isset($iter[0])) {
$iter = array($iter);
}
foreach ($iter as $package) {
$this->{"_validate{$type}Dep"}($package);
}
}
}
}
}
}
if (isset($this->_packageInfo['dependencies']['group'])) {
$groups = $this->_packageInfo['dependencies']['group'];
if (!isset($groups[0])) {
$groups = array($groups);
}
$structure = array(
'*package',
'*subpackage',
'*extension',
);
foreach ($groups as $group) {
if ($this->_stupidSchemaValidate($structure, $group, '')) {
if (!PEAR_Validate::validGroupName($group['attribs']['name'])) {
$this->_invalidDepGroupName($group['attribs']['name']);
}
foreach (array('package', 'subpackage', 'extension') as $type) {
if (isset($group[$type])) {
$iter = $group[$type];
if (!isset($iter[0])) {
$iter = array($iter);
}
foreach ($iter as $package) {
if ($type != 'extension') {
if (isset($package['uri'])) {
if (isset($package['channel'])) {
$this->_UrlOrChannelGroup($type,
$package['name'],
$group['name']);
}
} else {
if (!isset($package['channel'])) {
$this->_NoChannelGroup($type,
$package['name'],
$group['name']);
}
}
}
$this->{"_validate{$type}Dep"}($package, '');
}
}
}
}
}
}
}
function _validateCompatible()
{
$compat = $this->_packageInfo['compatible'];
if (!isset($compat[0])) {
$compat = array($compat);
}
$required = array('name', 'channel', 'min', 'max', '*exclude');
foreach ($compat as $package) {
$type = '';
if (is_array($package) && array_key_exists('name', $package)) {
$type .= '' . $package['name'] . '';
}
$this->_stupidSchemaValidate($required, $package, $type);
if (is_array($package) && array_key_exists('min', $package)) {
if (!preg_match('/^\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?\\z/',
$package['min'])) {
$this->_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_invalidVersion(substr($type, 1) . '_NoBundledPackages();
}
if (!is_array($list['bundledpackage']) || !isset($list['bundledpackage'][0])) {
return $this->_AtLeast2BundledPackages();
}
foreach ($list['bundledpackage'] as $package) {
if (!is_string($package)) {
$this->_bundledPackagesMustBeFilename();
}
}
}
function _validateFilelist($list = false, $allowignore = false, $dirs = '')
{
$iscontents = false;
if (!$list) {
$iscontents = true;
$list = $this->_packageInfo['contents'];
if (isset($this->_packageInfo['bundle'])) {
return $this->_validateBundle($list);
}
}
if ($allowignore) {
$struc = array(
'*install->name->as',
'*ignore->name'
);
} else {
$struc = array(
'*dir->name->?baseinstalldir',
'*file->name->role->?baseinstalldir->?md5sum'
);
if (isset($list['dir']) && isset($list['file'])) {
// stave off validation errors without requiring a set order.
$_old = $list;
if (isset($list['attribs'])) {
$list = array('attribs' => $_old['attribs']);
}
$list['dir'] = $_old['dir'];
$list['file'] = $_old['file'];
}
}
if (!isset($list['attribs']) || !isset($list['attribs']['name'])) {
$unknown = $allowignore ? '' : '';
$dirname = $iscontents ? '' : $unknown;
} else {
$dirname = '';
if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
str_replace('\\', '/', $list['attribs']['name']))) {
// file contains .. parent directory or . cur directory
$this->_invalidDirName($list['attribs']['name']);
}
}
$res = $this->_stupidSchemaValidate($struc, $list, $dirname);
if ($allowignore && $res) {
$ignored_or_installed = array();
$this->_pf->getFilelist();
$fcontents = $this->_pf->getContents();
$filelist = array();
if (!isset($fcontents['dir']['file'][0])) {
$fcontents['dir']['file'] = array($fcontents['dir']['file']);
}
foreach ($fcontents['dir']['file'] as $file) {
$filelist[$file['attribs']['name']] = true;
}
if (isset($list['install'])) {
if (!isset($list['install'][0])) {
$list['install'] = array($list['install']);
}
foreach ($list['install'] as $file) {
if (!isset($filelist[$file['attribs']['name']])) {
$this->_notInContents($file['attribs']['name'], 'install');
continue;
}
if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
$this->_multipleInstallAs($file['attribs']['name']);
}
if (!isset($ignored_or_installed[$file['attribs']['name']])) {
$ignored_or_installed[$file['attribs']['name']] = array();
}
$ignored_or_installed[$file['attribs']['name']][] = 1;
if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
str_replace('\\', '/', $file['attribs']['as']))) {
// file contains .. parent directory or . cur directory references
$this->_invalidFileInstallAs($file['attribs']['name'],
$file['attribs']['as']);
}
}
}
if (isset($list['ignore'])) {
if (!isset($list['ignore'][0])) {
$list['ignore'] = array($list['ignore']);
}
foreach ($list['ignore'] as $file) {
if (!isset($filelist[$file['attribs']['name']])) {
$this->_notInContents($file['attribs']['name'], 'ignore');
continue;
}
if (array_key_exists($file['attribs']['name'], $ignored_or_installed)) {
$this->_ignoreAndInstallAs($file['attribs']['name']);
}
}
}
}
if (!$allowignore && isset($list['file'])) {
if (is_string($list['file'])) {
$this->_oldStyleFileNotAllowed();
return false;
}
if (!isset($list['file'][0])) {
// single file
$list['file'] = array($list['file']);
}
foreach ($list['file'] as $i => $file)
{
if (isset($file['attribs']) && isset($file['attribs']['name'])) {
if ($file['attribs']['name']{0} == '.' &&
$file['attribs']['name']{1} == '/') {
// name is something like "./doc/whatever.txt"
$this->_invalidFileName($file['attribs']['name'], $dirname);
}
if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
str_replace('\\', '/', $file['attribs']['name']))) {
// file contains .. parent directory or . cur directory
$this->_invalidFileName($file['attribs']['name'], $dirname);
}
}
if (isset($file['attribs']) && isset($file['attribs']['role'])) {
if (!$this->_validateRole($file['attribs']['role'])) {
if (isset($this->_packageInfo['usesrole'])) {
$roles = $this->_packageInfo['usesrole'];
if (!isset($roles[0])) {
$roles = array($roles);
}
foreach ($roles as $role) {
if ($role['role'] = $file['attribs']['role']) {
$msg = 'This package contains role "%role%" and requires ' .
'package "%package%" to be used';
if (isset($role['uri'])) {
$params = array('role' => $role['role'],
'package' => $role['uri']);
} else {
$params = array('role' => $role['role'],
'package' => $this->_pf->_registry->
parsedPackageNameToString(array('package' =>
$role['package'], 'channel' => $role['channel']),
true));
}
$this->_stack->push('_mustInstallRole', 'error', $params, $msg);
}
}
}
$this->_invalidFileRole($file['attribs']['name'],
$dirname, $file['attribs']['role']);
}
}
if (!isset($file['attribs'])) {
continue;
}
$save = $file['attribs'];
if ($dirs) {
$save['name'] = $dirs . '/' . $save['name'];
}
unset($file['attribs']);
if (count($file) && $this->_curState != PEAR_VALIDATE_DOWNLOADING) { // has tasks
foreach ($file as $task => $value) {
if ($tagClass = $this->_pf->getTask($task)) {
if (!is_array($value) || !isset($value[0])) {
$value = array($value);
}
foreach ($value as $v) {
$ret = call_user_func(array($tagClass, 'validateXml'),
$this->_pf, $v, $this->_pf->_config, $save);
if (is_array($ret)) {
$this->_invalidTask($task, $ret, isset($save['name']) ?
$save['name'] : '');
}
}
} else {
if (isset($this->_packageInfo['usestask'])) {
$roles = $this->_packageInfo['usestask'];
if (!isset($roles[0])) {
$roles = array($roles);
}
foreach ($roles as $role) {
if ($role['task'] = $task) {
$msg = 'This package contains task "%task%" and requires ' .
'package "%package%" to be used';
if (isset($role['uri'])) {
$params = array('task' => $role['task'],
'package' => $role['uri']);
} else {
$params = array('task' => $role['task'],
'package' => $this->_pf->_registry->
parsedPackageNameToString(array('package' =>
$role['package'], 'channel' => $role['channel']),
true));
}
$this->_stack->push('_mustInstallTask', 'error',
$params, $msg);
}
}
}
$this->_unknownTask($task, $save['name']);
}
}
}
}
}
if (isset($list['ignore'])) {
if (!$allowignore) {
$this->_ignoreNotAllowed('ignore');
}
}
if (isset($list['install'])) {
if (!$allowignore) {
$this->_ignoreNotAllowed('install');
}
}
if (isset($list['file'])) {
if ($allowignore) {
$this->_fileNotAllowed('file');
}
}
if (isset($list['dir'])) {
if ($allowignore) {
$this->_fileNotAllowed('dir');
} else {
if (!isset($list['dir'][0])) {
$list['dir'] = array($list['dir']);
}
foreach ($list['dir'] as $dir) {
if (isset($dir['attribs']) && isset($dir['attribs']['name'])) {
if ($dir['attribs']['name'] == '/' ||
!isset($this->_packageInfo['contents']['dir']['dir'])) {
// always use nothing if the filelist has already been flattened
$newdirs = '';
} elseif ($dirs == '') {
$newdirs = $dir['attribs']['name'];
} else {
$newdirs = $dirs . '/' . $dir['attribs']['name'];
}
} else {
$newdirs = $dirs;
}
$this->_validateFilelist($dir, $allowignore, $newdirs);
}
}
}
}
function _validateRelease()
{
if (isset($this->_packageInfo['phprelease'])) {
$release = 'phprelease';
if (isset($this->_packageInfo['providesextension'])) {
$this->_cannotProvideExtension($release);
}
if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
$this->_cannotHaveSrcpackage($release);
}
$releases = $this->_packageInfo['phprelease'];
if (!is_array($releases)) {
return true;
}
if (!isset($releases[0])) {
$releases = array($releases);
}
foreach ($releases as $rel) {
$this->_stupidSchemaValidate(array(
'*installconditions',
'*filelist',
), $rel, '');
}
}
foreach (array('', 'zend') as $prefix) {
$releasetype = $prefix . 'extsrcrelease';
if (isset($this->_packageInfo[$releasetype])) {
$release = $releasetype;
if (!isset($this->_packageInfo['providesextension'])) {
$this->_mustProvideExtension($release);
}
if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
$this->_cannotHaveSrcpackage($release);
}
$releases = $this->_packageInfo[$releasetype];
if (!is_array($releases)) {
return true;
}
if (!isset($releases[0])) {
$releases = array($releases);
}
foreach ($releases as $rel) {
$this->_stupidSchemaValidate(array(
'*installconditions',
'*configureoption->name->prompt->?default',
'*binarypackage',
'*filelist',
), $rel, '<' . $releasetype . '>');
if (isset($rel['binarypackage'])) {
if (!is_array($rel['binarypackage']) || !isset($rel['binarypackage'][0])) {
$rel['binarypackage'] = array($rel['binarypackage']);
}
foreach ($rel['binarypackage'] as $bin) {
if (!is_string($bin)) {
$this->_binaryPackageMustBePackagename();
}
}
}
}
}
$releasetype = 'extbinrelease';
if (isset($this->_packageInfo[$releasetype])) {
$release = $releasetype;
if (!isset($this->_packageInfo['providesextension'])) {
$this->_mustProvideExtension($release);
}
if (isset($this->_packageInfo['channel']) &&
!isset($this->_packageInfo['srcpackage'])) {
$this->_mustSrcPackage($release);
}
if (isset($this->_packageInfo['uri']) && !isset($this->_packageInfo['srcuri'])) {
$this->_mustSrcuri($release);
}
$releases = $this->_packageInfo[$releasetype];
if (!is_array($releases)) {
return true;
}
if (!isset($releases[0])) {
$releases = array($releases);
}
foreach ($releases as $rel) {
$this->_stupidSchemaValidate(array(
'*installconditions',
'*filelist',
), $rel, '<' . $releasetype . '>');
}
}
}
if (isset($this->_packageInfo['bundle'])) {
$release = 'bundle';
if (isset($this->_packageInfo['providesextension'])) {
$this->_cannotProvideExtension($release);
}
if (isset($this->_packageInfo['srcpackage']) || isset($this->_packageInfo['srcuri'])) {
$this->_cannotHaveSrcpackage($release);
}
$releases = $this->_packageInfo['bundle'];
if (!is_array($releases) || !isset($releases[0])) {
$releases = array($releases);
}
foreach ($releases as $rel) {
$this->_stupidSchemaValidate(array(
'*installconditions',
'*filelist',
), $rel, '');
}
}
foreach ($releases as $rel) {
if (is_array($rel) && array_key_exists('installconditions', $rel)) {
$this->_validateInstallConditions($rel['installconditions'],
"<$release>");
}
if (is_array($rel) && array_key_exists('filelist', $rel)) {
if ($rel['filelist']) {
$this->_validateFilelist($rel['filelist'], true);
}
}
}
}
/**
* This is here to allow role extension through plugins
* @param string
*/
function _validateRole($role)
{
return in_array($role, PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType()));
}
function _pearVersionTooLow($version)
{
$this->_stack->push(__FUNCTION__, 'error',
array('version' => $version),
'This package.xml requires PEAR version %version% to parse properly, we are ' .
'version 1.10.4');
}
function _invalidTagOrder($oktags, $actual, $root)
{
$this->_stack->push(__FUNCTION__, 'error',
array('oktags' => $oktags, 'actual' => $actual, 'root' => $root),
'Invalid tag order in %root%, found <%actual%> expected one of "%oktags%"');
}
function _ignoreNotAllowed($type)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
'<%type%> is not allowed inside global , only inside ' .
'//, use and only');
}
function _fileNotAllowed($type)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
'<%type%> is not allowed inside release , only inside ' .
', use and only');
}
function _oldStyleFileNotAllowed()
{
$this->_stack->push(__FUNCTION__, 'error', array(),
'Old-style name is not allowed. Use' .
'');
}
function _tagMissingAttribute($tag, $attr, $context)
{
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
'attribute' => $attr, 'context' => $context),
'tag <%tag%> in context "%context%" has no attribute "%attribute%"');
}
function _tagHasNoAttribs($tag, $context)
{
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag,
'context' => $context),
'tag <%tag%> has no attributes in context "%context%"');
}
function _invalidInternalStructure()
{
$this->_stack->push(__FUNCTION__, 'exception', array(),
'internal array was not generated by compatible parser, or extreme parser error, cannot continue');
}
function _invalidFileRole($file, $dir, $role)
{
$this->_stack->push(__FUNCTION__, 'error', array(
'file' => $file, 'dir' => $dir, 'role' => $role,
'roles' => PEAR_Installer_Role::getValidRoles($this->_pf->getPackageType())),
'File "%file%" in directory "%dir%" has invalid role "%role%", should be one of %roles%');
}
function _invalidFileName($file, $dir)
{
$this->_stack->push(__FUNCTION__, 'error', array(
'file' => $file),
'File "%file%" in directory "%dir%" cannot begin with "./" or contain ".."');
}
function _invalidFileInstallAs($file, $as)
{
$this->_stack->push(__FUNCTION__, 'error', array(
'file' => $file, 'as' => $as),
'File "%file%" cannot contain "./" or contain ".."');
}
function _invalidDirName($dir)
{
$this->_stack->push(__FUNCTION__, 'error', array(
'dir' => $file),
'Directory "%dir%" cannot begin with "./" or contain ".."');
}
function _filelistCannotContainFile($filelist)
{
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
'<%tag%> can only contain , contains . Use ' .
' as the first dir element');
}
function _filelistMustContainDir($filelist)
{
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $filelist),
'<%tag%> must contain . Use as the ' .
'first dir element');
}
function _tagCannotBeEmpty($tag)
{
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
'<%tag%> cannot be empty (<%tag%/>)');
}
function _UrlOrChannel($type, $name)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
'name' => $name),
'Required dependency <%type%> "%name%" can have either url OR ' .
'channel attributes, and not both');
}
function _NoChannel($type, $name)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
'name' => $name),
'Required dependency <%type%> "%name%" must have either url OR ' .
'channel attributes');
}
function _UrlOrChannelGroup($type, $name, $group)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
'name' => $name, 'group' => $group),
'Group "%group%" dependency <%type%> "%name%" can have either url OR ' .
'channel attributes, and not both');
}
function _NoChannelGroup($type, $name, $group)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type,
'name' => $name, 'group' => $group),
'Group "%group%" dependency <%type%> "%name%" must have either url OR ' .
'channel attributes');
}
function _unknownChannel($channel)
{
$this->_stack->push(__FUNCTION__, 'error', array('channel' => $channel),
'Unknown channel "%channel%"');
}
function _noPackageVersion()
{
$this->_stack->push(__FUNCTION__, 'error', array(),
'package.xml tag has no version attribute, or version is not 2.0');
}
function _NoBundledPackages()
{
$this->_stack->push(__FUNCTION__, 'error', array(),
'No tag was found in , required for bundle packages');
}
function _AtLeast2BundledPackages()
{
$this->_stack->push(__FUNCTION__, 'error', array(),
'At least 2 packages must be bundled in a bundle package');
}
function _ChannelOrUri($name)
{
$this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
'Bundled package "%name%" can have either a uri or a channel, not both');
}
function _noChildTag($child, $tag)
{
$this->_stack->push(__FUNCTION__, 'error', array('child' => $child, 'tag' => $tag),
'Tag <%tag%> is missing child tag <%child%>');
}
function _invalidVersion($type, $value)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value),
'Version type <%type%> is not a valid version (%value%)');
}
function _invalidState($type, $value)
{
$states = array('stable', 'beta', 'alpha', 'devel');
if ($type != 'api') {
$states[] = 'snapshot';
}
if (strtolower($value) == 'rc') {
$this->_stack->push(__FUNCTION__, 'error',
array('version' => $this->_packageInfo['version']['release']),
'RC is not a state, it is a version postfix, try %version%RC1, stability beta');
}
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type, 'value' => $value,
'types' => $states),
'Stability type <%type%> is not a valid stability (%value%), must be one of ' .
'%types%');
}
function _invalidTask($task, $ret, $file)
{
switch ($ret[0]) {
case PEAR_TASK_ERROR_MISSING_ATTRIB :
$info = array('attrib' => $ret[1], 'task' => $task, 'file' => $file);
$msg = 'task <%task%> is missing attribute "%attrib%" in file %file%';
break;
case PEAR_TASK_ERROR_NOATTRIBS :
$info = array('task' => $task, 'file' => $file);
$msg = 'task <%task%> has no attributes in file %file%';
break;
case PEAR_TASK_ERROR_WRONG_ATTRIB_VALUE :
$info = array('attrib' => $ret[1], 'values' => $ret[3],
'was' => $ret[2], 'task' => $task, 'file' => $file);
$msg = 'task <%task%> attribute "%attrib%" has the wrong value "%was%" '.
'in file %file%, expecting one of "%values%"';
break;
case PEAR_TASK_ERROR_INVALID :
$info = array('reason' => $ret[1], 'task' => $task, 'file' => $file);
$msg = 'task <%task%> in file %file% is invalid because of "%reason%"';
break;
}
$this->_stack->push(__FUNCTION__, 'error', $info, $msg);
}
function _unknownTask($task, $file)
{
$this->_stack->push(__FUNCTION__, 'error', array('task' => $task, 'file' => $file),
'Unknown task "%task%" passed in file ');
}
function _subpackageCannotProvideExtension($name)
{
$this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
'Subpackage dependency "%name%" cannot use , ' .
'only package dependencies can use this tag');
}
function _subpackagesCannotConflict($name)
{
$this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
'Subpackage dependency "%name%" cannot use , ' .
'only package dependencies can use this tag');
}
function _cannotProvideExtension($release)
{
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
'<%release%> packages cannot use , only extbinrelease, extsrcrelease, zendextsrcrelease, and zendextbinrelease can provide a PHP extension');
}
function _mustProvideExtension($release)
{
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
'<%release%> packages must use to indicate which PHP extension is provided');
}
function _cannotHaveSrcpackage($release)
{
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
'<%release%> packages cannot specify a source code package, only extension binaries may use the tag');
}
function _mustSrcPackage($release)
{
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
'/ packages must specify a source code package with ');
}
function _mustSrcuri($release)
{
$this->_stack->push(__FUNCTION__, 'error', array('release' => $release),
'/ packages must specify a source code package with ');
}
function _uriDepsCannotHaveVersioning($type)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
'%type%: dependencies with a tag cannot have any versioning information');
}
function _conflictingDepsCannotHaveVersioning($type)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
'%type%: conflicting dependencies cannot have versioning info, use to ' .
'exclude specific versions of a dependency');
}
function _DepchannelCannotBeUri($type)
{
$this->_stack->push(__FUNCTION__, 'error', array('type' => $type),
'%type%: channel cannot be __uri, this is a pseudo-channel reserved for uri ' .
'dependencies only');
}
function _bundledPackagesMustBeFilename()
{
$this->_stack->push(__FUNCTION__, 'error', array(),
' tags must contain only the filename of a package release ' .
'in the bundle');
}
function _binaryPackageMustBePackagename()
{
$this->_stack->push(__FUNCTION__, 'error', array(),
' tags must contain the name of a package that is ' .
'a compiled version of this extsrc/zendextsrc package');
}
function _fileNotFound($file)
{
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
'File "%file%" in package.xml does not exist');
}
function _notInContents($file, $tag)
{
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file, 'tag' => $tag),
'<%tag% name="%file%"> is invalid, file is not in ');
}
function _cannotValidateNoPathSet()
{
$this->_stack->push(__FUNCTION__, 'error', array(),
'Cannot validate files, no path to package file is set (use setPackageFile())');
}
function _usesroletaskMustHaveChannelOrUri($role, $tag)
{
$this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
'<%tag%> for role "%role%" must contain either , or and ');
}
function _usesroletaskMustHavePackage($role, $tag)
{
$this->_stack->push(__FUNCTION__, 'error', array('role' => $role, 'tag' => $tag),
'<%tag%> for role "%role%" must contain ');
}
function _usesroletaskMustHaveRoleTask($tag, $type)
{
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag, 'type' => $type),
'<%tag%> must contain <%type%> defining the %type% to be used');
}
function _cannotConflictWithAllOs($type)
{
$this->_stack->push(__FUNCTION__, 'error', array('tag' => $tag),
'%tag% cannot conflict with all OSes');
}
function _invalidDepGroupName($name)
{
$this->_stack->push(__FUNCTION__, 'error', array('name' => $name),
'Invalid dependency group name "%name%"');
}
function _multipleToplevelDirNotAllowed()
{
$this->_stack->push(__FUNCTION__, 'error', array(),
'Multiple top-level tags are not allowed. Enclose them ' .
'in a ');
}
function _multipleInstallAs($file)
{
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
'Only one tag is allowed for file "%file%"');
}
function _ignoreAndInstallAs($file)
{
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
'Cannot have both and tags for file "%file%"');
}
function _analyzeBundledPackages()
{
if (!$this->_isValid) {
return false;
}
if (!$this->_pf->getPackageType() == 'bundle') {
return false;
}
if (!isset($this->_pf->_packageFile)) {
return false;
}
$dir_prefix = dirname($this->_pf->_packageFile);
$common = new PEAR_Common;
$log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
array($common, 'log');
$info = $this->_pf->getContents();
$info = $info['bundledpackage'];
if (!is_array($info)) {
$info = array($info);
}
$pkg = new PEAR_PackageFile($this->_pf->_config);
foreach ($info as $package) {
if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $package)) {
$this->_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $package);
$this->_isValid = 0;
continue;
}
call_user_func_array($log, array(1, "Analyzing bundled package $package"));
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$ret = $pkg->fromAnyFile($dir_prefix . DIRECTORY_SEPARATOR . $package,
PEAR_VALIDATE_NORMAL);
PEAR::popErrorHandling();
if (PEAR::isError($ret)) {
call_user_func_array($log, array(0, "ERROR: package $package is not a valid " .
'package'));
$inf = $ret->getUserInfo();
if (is_array($inf)) {
foreach ($inf as $err) {
call_user_func_array($log, array(1, $err['message']));
}
}
return false;
}
}
return true;
}
function _analyzePhpFiles()
{
if (!$this->_isValid) {
return false;
}
if (!isset($this->_pf->_packageFile)) {
$this->_cannotValidateNoPathSet();
return false;
}
$dir_prefix = dirname($this->_pf->_packageFile);
$common = new PEAR_Common;
$log = isset($this->_pf->_logger) ? array(&$this->_pf->_logger, 'log') :
array(&$common, 'log');
$info = $this->_pf->getContents();
if (!$info || !isset($info['dir']['file'])) {
$this->_tagCannotBeEmpty('contents>_fileNotFound($dir_prefix . DIRECTORY_SEPARATOR . $file);
$this->_isValid = 0;
continue;
}
if (in_array($fa['role'], PEAR_Installer_Role::getPhpRoles()) && $dir_prefix) {
call_user_func_array($log, array(1, "Analyzing $file"));
$srcinfo = $this->analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
if ($srcinfo) {
$provides = array_merge($provides, $this->_buildProvidesArray($srcinfo));
}
}
}
$this->_packageName = $pn = $this->_pf->getPackage();
$pnl = strlen($pn);
foreach ($provides as $key => $what) {
if (isset($what['explicit']) || !$what) {
// skip conformance checks if the provides entry is
// specified in the package.xml file
continue;
}
extract($what);
if ($type == 'class') {
if (!strncasecmp($name, $pn, $pnl)) {
continue;
}
$this->_stack->push(__FUNCTION__, 'warning',
array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
'in %file%: %type% "%name%" not prefixed with package name "%package%"');
} elseif ($type == 'function') {
if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
continue;
}
$this->_stack->push(__FUNCTION__, 'warning',
array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn),
'in %file%: %type% "%name%" not prefixed with package name "%package%"');
}
}
return $this->_isValid;
}
/**
* Analyze the source code of the given PHP file
*
* @param string Filename of the PHP file
* @param boolean whether to analyze $file as the file contents
* @return mixed
*/
function analyzeSourceCode($file, $string = false)
{
if (!function_exists("token_get_all")) {
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
'Parser error: token_get_all() function must exist to analyze source code, PHP may have been compiled with --disable-tokenizer');
return false;
}
if (!defined('T_DOC_COMMENT')) {
define('T_DOC_COMMENT', T_COMMENT);
}
if (!defined('T_INTERFACE')) {
define('T_INTERFACE', -1);
}
if (!defined('T_IMPLEMENTS')) {
define('T_IMPLEMENTS', -1);
}
if ($string) {
$contents = $file;
} else {
if (!$fp = @fopen($file, "r")) {
return false;
}
fclose($fp);
$contents = file_get_contents($file);
}
// Silence this function so we can catch PHP Warnings and show our own custom message
$tokens = @token_get_all($contents);
if (isset($php_errormsg)) {
if (isset($this->_stack)) {
$pn = $this->_pf->getPackage();
$this->_stack->push(__FUNCTION__, 'warning',
array('file' => $file, 'package' => $pn),
'in %file%: Could not process file for unknown reasons,' .
' possibly a PHP parse error in %file% from %package%');
}
}
/*
for ($i = 0; $i < sizeof($tokens); $i++) {
@list($token, $data) = $tokens[$i];
if (is_string($token)) {
var_dump($token);
} else {
print token_name($token) . ' ';
var_dump(rtrim($data));
}
}
*/
$look_for = 0;
$paren_level = 0;
$bracket_level = 0;
$brace_level = 0;
$lastphpdoc = '';
$current_class = '';
$current_interface = '';
$current_class_level = -1;
$current_function = '';
$current_function_level = -1;
$declared_classes = array();
$declared_interfaces = array();
$declared_functions = array();
$declared_methods = array();
$used_classes = array();
$used_functions = array();
$extends = array();
$implements = array();
$nodeps = array();
$inquote = false;
$interface = false;
for ($i = 0; $i < sizeof($tokens); $i++) {
if (is_array($tokens[$i])) {
list($token, $data) = $tokens[$i];
} else {
$token = $tokens[$i];
$data = '';
}
if ($inquote) {
if ($token != '"' && $token != T_END_HEREDOC) {
continue;
} else {
$inquote = false;
continue;
}
}
switch ($token) {
case T_WHITESPACE :
continue;
case ';':
if ($interface) {
$current_function = '';
$current_function_level = -1;
}
break;
case '"':
case T_START_HEREDOC:
$inquote = true;
break;
case T_CURLY_OPEN:
case T_DOLLAR_OPEN_CURLY_BRACES:
case '{': $brace_level++; continue 2;
case '}':
$brace_level--;
if ($current_class_level == $brace_level) {
$current_class = '';
$current_class_level = -1;
}
if ($current_function_level == $brace_level) {
$current_function = '';
$current_function_level = -1;
}
continue 2;
case '[': $bracket_level++; continue 2;
case ']': $bracket_level--; continue 2;
case '(': $paren_level++; continue 2;
case ')': $paren_level--; continue 2;
case T_INTERFACE:
$interface = true;
case T_CLASS:
if (($current_class_level != -1) || ($current_function_level != -1)) {
if (isset($this->_stack)) {
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
'Parser error: invalid PHP found in file "%file%"');
} else {
PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
PEAR_COMMON_ERROR_INVALIDPHP);
}
return false;
}
case T_FUNCTION:
case T_NEW:
case T_EXTENDS:
case T_IMPLEMENTS:
$look_for = $token;
continue 2;
case T_STRING:
if ($look_for == T_CLASS) {
$current_class = $data;
$current_class_level = $brace_level;
$declared_classes[] = $current_class;
} elseif ($look_for == T_INTERFACE) {
$current_interface = $data;
$current_class_level = $brace_level;
$declared_interfaces[] = $current_interface;
} elseif ($look_for == T_IMPLEMENTS) {
$implements[$current_class] = $data;
} elseif ($look_for == T_EXTENDS) {
$extends[$current_class] = $data;
} elseif ($look_for == T_FUNCTION) {
if ($current_class) {
$current_function = "$current_class::$data";
$declared_methods[$current_class][] = $data;
} elseif ($current_interface) {
$current_function = "$current_interface::$data";
$declared_methods[$current_interface][] = $data;
} else {
$current_function = $data;
$declared_functions[] = $current_function;
}
$current_function_level = $brace_level;
$m = array();
} elseif ($look_for == T_NEW) {
$used_classes[$data] = true;
}
$look_for = 0;
continue 2;
case T_VARIABLE:
$look_for = 0;
continue 2;
case T_DOC_COMMENT:
case T_COMMENT:
if (preg_match('!^/\*\*\s!', $data)) {
$lastphpdoc = $data;
if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
$nodeps = array_merge($nodeps, $m[1]);
}
}
continue 2;
case T_DOUBLE_COLON:
$token = $tokens[$i - 1][0];
if (!($token == T_WHITESPACE || $token == T_STRING || $token == T_STATIC || $token == T_VARIABLE)) {
if (isset($this->_stack)) {
$this->_stack->push(__FUNCTION__, 'warning', array('file' => $file),
'Parser error: invalid PHP found in file "%file%"');
} else {
PEAR::raiseError("Parser error: invalid PHP found in file \"$file\"",
PEAR_COMMON_ERROR_INVALIDPHP);
}
return false;
}
$class = $tokens[$i - 1][1];
if (strtolower($class) != 'parent') {
$used_classes[$class] = true;
}
continue 2;
}
}
return array(
"source_file" => $file,
"declared_classes" => $declared_classes,
"declared_interfaces" => $declared_interfaces,
"declared_methods" => $declared_methods,
"declared_functions" => $declared_functions,
"used_classes" => array_diff(array_keys($used_classes), $nodeps),
"inheritance" => $extends,
"implements" => $implements,
);
}
/**
* Build a "provides" array from data returned by
* analyzeSourceCode(). The format of the built array is like
* this:
*
* array(
* 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
* ...
* )
*
*
* @param array $srcinfo array with information about a source file
* as returned by the analyzeSourceCode() method.
*
* @return void
*
* @access private
*
*/
function _buildProvidesArray($srcinfo)
{
if (!$this->_isValid) {
return array();
}
$providesret = array();
$file = basename($srcinfo['source_file']);
$pn = isset($this->_pf) ? $this->_pf->getPackage() : '';
$pnl = strlen($pn);
foreach ($srcinfo['declared_classes'] as $class) {
$key = "class;$class";
if (isset($providesret[$key])) {
continue;
}
$providesret[$key] =
array('file'=> $file, 'type' => 'class', 'name' => $class);
if (isset($srcinfo['inheritance'][$class])) {
$providesret[$key]['extends'] =
$srcinfo['inheritance'][$class];
}
}
foreach ($srcinfo['declared_methods'] as $class => $methods) {
foreach ($methods as $method) {
$function = "$class::$method";
$key = "function;$function";
if ($method{0} == '_' || !strcasecmp($method, $class) ||
isset($providesret[$key])) {
continue;
}
$providesret[$key] =
array('file'=> $file, 'type' => 'function', 'name' => $function);
}
}
foreach ($srcinfo['declared_functions'] as $function) {
$key = "function;$function";
if ($function{0} == '_' || isset($providesret[$key])) {
continue;
}
if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
$warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
}
$providesret[$key] =
array('file'=> $file, 'type' => 'function', 'name' => $function);
}
return $providesret;
}
}
PK [3 e e ! PEAR/PackageFile/Generator/v1.phpnu W+A
* @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 PEAR_VALIDATE_* constants
*/
require_once 'PEAR/Validate.php';
require_once 'System.php';
require_once 'PEAR/PackageFile/v2.php';
/**
* This class converts a PEAR_PackageFile_v1 object into any output format.
*
* Supported output formats include array, XML string, and a PEAR_PackageFile_v2
* object, for converting package.xml 1.0 into package.xml 2.0 with no sweat.
* @category pear
* @package PEAR
* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_PackageFile_Generator_v1
{
/**
* @var PEAR_PackageFile_v1
*/
var $_packagefile;
function __construct(&$packagefile)
{
$this->_packagefile = &$packagefile;
}
function getPackagerVersion()
{
return '1.10.4';
}
/**
* @param PEAR_Packager
* @param bool if true, a .tgz is written, otherwise a .tar is written
* @param string|null directory in which to save the .tgz
* @return string|PEAR_Error location of package or error object
*/
function toTgz(&$packager, $compress = true, $where = null)
{
require_once 'Archive/Tar.php';
if ($where === null) {
if (!($where = System::mktemp(array('-d')))) {
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: mktemp failed');
}
} elseif (!@System::mkDir(array('-p', $where))) {
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: "' . $where . '" could' .
' not be created');
}
if (file_exists($where . DIRECTORY_SEPARATOR . 'package.xml') &&
!is_file($where . DIRECTORY_SEPARATOR . 'package.xml')) {
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: unable to save package.xml as' .
' "' . $where . DIRECTORY_SEPARATOR . 'package.xml"');
}
if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) {
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: invalid package file');
}
$pkginfo = $this->_packagefile->getArray();
$ext = $compress ? '.tgz' : '.tar';
$pkgver = $pkginfo['package'] . '-' . $pkginfo['version'];
$dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext;
if (file_exists(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext) &&
!is_file(getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext)) {
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: cannot create tgz file "' .
getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext . '"');
}
if ($pkgfile = $this->_packagefile->getPackageFile()) {
$pkgdir = dirname(realpath($pkgfile));
$pkgfile = basename($pkgfile);
} else {
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: package file object must ' .
'be created from a real file');
}
// {{{ Create the package file list
$filelist = array();
$i = 0;
foreach ($this->_packagefile->getFilelist() as $fname => $atts) {
$file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
if (!file_exists($file)) {
return PEAR::raiseError("File does not exist: $fname");
} else {
$filelist[$i++] = $file;
if (!isset($atts['md5sum'])) {
$this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($file));
}
$packager->log(2, "Adding file $fname");
}
}
// }}}
$packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true);
if ($packagexml) {
$tar = new Archive_Tar($dest_package, $compress);
$tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors
// ----- Creates with the package.xml file
$ok = $tar->createModify(array($packagexml), '', $where);
if (PEAR::isError($ok)) {
return $ok;
} elseif (!$ok) {
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed');
}
// ----- Add the content of the package
if (!$tar->addModify($filelist, $pkgver, $pkgdir)) {
return PEAR::raiseError('PEAR_Packagefile_v1::toTgz: tarball creation failed');
}
return $dest_package;
}
}
/**
* @param string|null directory to place the package.xml in, or null for a temporary dir
* @param int one of the PEAR_VALIDATE_* constants
* @param string name of the generated file
* @param bool if true, then no analysis will be performed on role="php" files
* @return string|PEAR_Error path to the created file on success
*/
function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml',
$nofilechecking = false)
{
if (!$this->_packagefile->validate($state, $nofilechecking)) {
return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: invalid package.xml',
null, null, null, $this->_packagefile->getValidationWarnings());
}
if ($where === null) {
if (!($where = System::mktemp(array('-d')))) {
return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: mktemp failed');
}
} elseif (!@System::mkDir(array('-p', $where))) {
return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: "' . $where . '" could' .
' not be created');
}
$newpkgfile = $where . DIRECTORY_SEPARATOR . $name;
$np = @fopen($newpkgfile, 'wb');
if (!$np) {
return PEAR::raiseError('PEAR_Packagefile_v1::toPackageFile: unable to save ' .
"$name as $newpkgfile");
}
fwrite($np, $this->toXml($state, true));
fclose($np);
return $newpkgfile;
}
/**
* fix both XML encoding to be UTF8, and replace standard XML entities < > " & '
*
* @param string $string
* @return string
* @access private
*/
function _fixXmlEncoding($string)
{
return strtr($string, array(
'&' => '&',
'>' => '>',
'<' => '<',
'"' => '"',
'\'' => ''' ));
}
/**
* Return an XML document based on the package info (as returned
* by the PEAR_Common::infoFrom* methods).
*
* @return string XML data
*/
function toXml($state = PEAR_VALIDATE_NORMAL, $nofilevalidation = false)
{
$this->_packagefile->setDate(date('Y-m-d'));
if (!$this->_packagefile->validate($state, $nofilevalidation)) {
return false;
}
$pkginfo = $this->_packagefile->getArray();
static $maint_map = array(
"handle" => "user",
"name" => "name",
"email" => "email",
"role" => "role",
);
$ret = "\n";
$ret .= "\n";
$ret .= "\n" .
" $pkginfo[package]";
if (isset($pkginfo['extends'])) {
$ret .= "\n$pkginfo[extends]";
}
$ret .=
"\n ".$this->_fixXmlEncoding($pkginfo['summary'])."\n" .
" ".trim($this->_fixXmlEncoding($pkginfo['description']))."\n \n" .
" \n";
foreach ($pkginfo['maintainers'] as $maint) {
$ret .= " \n";
foreach ($maint_map as $idx => $elm) {
$ret .= " <$elm>";
$ret .= $this->_fixXmlEncoding($maint[$idx]);
$ret .= "$elm>\n";
}
$ret .= " \n";
}
$ret .= " \n";
$ret .= $this->_makeReleaseXml($pkginfo, false, $state);
if (isset($pkginfo['changelog']) && count($pkginfo['changelog']) > 0) {
$ret .= " \n";
foreach ($pkginfo['changelog'] as $oldrelease) {
$ret .= $this->_makeReleaseXml($oldrelease, true);
}
$ret .= " \n";
}
$ret .= "\n";
return $ret;
}
// }}}
// {{{ _makeReleaseXml()
/**
* Generate part of an XML description with release information.
*
* @param array $pkginfo array with release information
* @param bool $changelog whether the result will be in a changelog element
*
* @return string XML data
*
* @access private
*/
function _makeReleaseXml($pkginfo, $changelog = false, $state = PEAR_VALIDATE_NORMAL)
{
// XXX QUOTE ENTITIES IN PCDATA, OR EMBED IN CDATA BLOCKS!!
$indent = $changelog ? " " : "";
$ret = "$indent \n";
if (!empty($pkginfo['version'])) {
$ret .= "$indent $pkginfo[version]\n";
}
if (!empty($pkginfo['release_date'])) {
$ret .= "$indent $pkginfo[release_date]\n";
}
if (!empty($pkginfo['release_license'])) {
$ret .= "$indent $pkginfo[release_license]\n";
}
if (!empty($pkginfo['release_state'])) {
$ret .= "$indent $pkginfo[release_state]\n";
}
if (!empty($pkginfo['release_notes'])) {
$ret .= "$indent ".trim($this->_fixXmlEncoding($pkginfo['release_notes']))
."\n$indent \n";
}
if (!empty($pkginfo['release_warnings'])) {
$ret .= "$indent ".$this->_fixXmlEncoding($pkginfo['release_warnings'])."\n";
}
if (isset($pkginfo['release_deps']) && sizeof($pkginfo['release_deps']) > 0) {
$ret .= "$indent \n";
foreach ($pkginfo['release_deps'] as $dep) {
$ret .= "$indent _fixXmlEncoding($c['name']) . "\"";
if (isset($c['default'])) {
$ret .= " default=\"" . $this->_fixXmlEncoding($c['default']) . "\"";
}
$ret .= " prompt=\"" . $this->_fixXmlEncoding($c['prompt']) . "\"";
$ret .= "/>\n";
}
$ret .= "$indent \n";
}
if (isset($pkginfo['provides'])) {
foreach ($pkginfo['provides'] as $key => $what) {
$ret .= "$indent recursiveXmlFilelist($pkginfo['filelist']);
} else {
foreach ($pkginfo['filelist'] as $file => $fa) {
if (!isset($fa['role'])) {
$fa['role'] = '';
}
$ret .= "$indent _fixXmlEncoding($fa['baseinstalldir']) . '"';
}
if (isset($fa['md5sum'])) {
$ret .= " md5sum=\"$fa[md5sum]\"";
}
if (isset($fa['platform'])) {
$ret .= " platform=\"$fa[platform]\"";
}
if (!empty($fa['install-as'])) {
$ret .= ' install-as="' .
$this->_fixXmlEncoding($fa['install-as']) . '"';
}
$ret .= ' name="' . $this->_fixXmlEncoding($file) . '"';
if (empty($fa['replacements'])) {
$ret .= "/>\n";
} else {
$ret .= ">\n";
foreach ($fa['replacements'] as $r) {
$ret .= "$indent $v) {
$ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"';
}
$ret .= "/>\n";
}
$ret .= "$indent \n";
}
}
}
$ret .= "$indent \n";
}
$ret .= "$indent \n";
return $ret;
}
/**
* @param array
* @access protected
*/
function recursiveXmlFilelist($list)
{
$this->_dirs = array();
foreach ($list as $file => $attributes) {
$this->_addDir($this->_dirs, explode('/', dirname($file)), $file, $attributes);
}
return $this->_formatDir($this->_dirs);
}
/**
* @param array
* @param array
* @param string|null
* @param array|null
* @access private
*/
function _addDir(&$dirs, $dir, $file = null, $attributes = null)
{
if ($dir == array() || $dir == array('.')) {
$dirs['files'][basename($file)] = $attributes;
return;
}
$curdir = array_shift($dir);
if (!isset($dirs['dirs'][$curdir])) {
$dirs['dirs'][$curdir] = array();
}
$this->_addDir($dirs['dirs'][$curdir], $dir, $file, $attributes);
}
/**
* @param array
* @param string
* @param string
* @access private
*/
function _formatDir($dirs, $indent = '', $curdir = '')
{
$ret = '';
if (!count($dirs)) {
return '';
}
if (isset($dirs['dirs'])) {
uksort($dirs['dirs'], 'strnatcasecmp');
foreach ($dirs['dirs'] as $dir => $contents) {
$usedir = "$curdir/$dir";
$ret .= "$indent \n";
$ret .= $this->_formatDir($contents, "$indent ", $usedir);
$ret .= "$indent \n";
}
}
if (isset($dirs['files'])) {
uksort($dirs['files'], 'strnatcasecmp');
foreach ($dirs['files'] as $file => $attribs) {
$ret .= $this->_formatFile($file, $attribs, $indent);
}
}
return $ret;
}
/**
* @param string
* @param array
* @param string
* @access private
*/
function _formatFile($file, $attributes, $indent)
{
$ret = "$indent _fixXmlEncoding($attributes['baseinstalldir']) . '"';
}
if (isset($attributes['md5sum'])) {
$ret .= " md5sum=\"$attributes[md5sum]\"";
}
if (isset($attributes['platform'])) {
$ret .= " platform=\"$attributes[platform]\"";
}
if (!empty($attributes['install-as'])) {
$ret .= ' install-as="' .
$this->_fixXmlEncoding($attributes['install-as']) . '"';
}
$ret .= ' name="' . $this->_fixXmlEncoding($file) . '"';
if (empty($attributes['replacements'])) {
$ret .= "/>\n";
} else {
$ret .= ">\n";
foreach ($attributes['replacements'] as $r) {
$ret .= "$indent $v) {
$ret .= " $k=\"" . $this->_fixXmlEncoding($v) .'"';
}
$ret .= "/>\n";
}
$ret .= "$indent \n";
}
return $ret;
}
// {{{ _unIndent()
/**
* Unindent given string (?)
*
* @param string $str The string that has to be unindented.
* @return string
* @access private
*/
function _unIndent($str)
{
// remove leading newlines
$str = preg_replace('/^[\r\n]+/', '', $str);
// find whitespace at the beginning of the first line
$indent_len = strspn($str, " \t");
$indent = substr($str, 0, $indent_len);
$data = '';
// remove the same amount of whitespace from following lines
foreach (explode("\n", $str) as $line) {
if (substr($line, 0, $indent_len) == $indent) {
$data .= substr($line, $indent_len) . "\n";
}
}
return $data;
}
/**
* @return array
*/
function dependenciesToV2()
{
$arr = array();
$this->_convertDependencies2_0($arr);
return $arr['dependencies'];
}
/**
* Convert a package.xml version 1.0 into version 2.0
*
* Note that this does a basic conversion, to allow more advanced
* features like bundles and multiple releases
* @param string the classname to instantiate and return. This must be
* PEAR_PackageFile_v2 or a descendant
* @param boolean if true, only valid, deterministic package.xml 1.0 as defined by the
* strictest parameters will be converted
* @return PEAR_PackageFile_v2|PEAR_Error
*/
function &toV2($class = 'PEAR_PackageFile_v2', $strict = false)
{
if ($strict) {
if (!$this->_packagefile->validate()) {
$a = PEAR::raiseError('invalid package.xml version 1.0 cannot be converted' .
' to version 2.0', null, null, null,
$this->_packagefile->getValidationWarnings(true));
return $a;
}
}
$arr = array(
'attribs' => array(
'version' => '2.0',
'xmlns' => 'http://pear.php.net/dtd/package-2.0',
'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation' => "http://pear.php.net/dtd/tasks-1.0\n" .
"http://pear.php.net/dtd/tasks-1.0.xsd\n" .
"http://pear.php.net/dtd/package-2.0\n" .
'http://pear.php.net/dtd/package-2.0.xsd',
),
'name' => $this->_packagefile->getPackage(),
'channel' => 'pear.php.net',
);
$arr['summary'] = $this->_packagefile->getSummary();
$arr['description'] = $this->_packagefile->getDescription();
$maintainers = $this->_packagefile->getMaintainers();
foreach ($maintainers as $maintainer) {
if ($maintainer['role'] != 'lead') {
continue;
}
$new = array(
'name' => $maintainer['name'],
'user' => $maintainer['handle'],
'email' => $maintainer['email'],
'active' => 'yes',
);
$arr['lead'][] = $new;
}
if (!isset($arr['lead'])) { // some people... you know?
$arr['lead'] = array(
'name' => 'unknown',
'user' => 'unknown',
'email' => 'noleadmaintainer@example.com',
'active' => 'no',
);
}
if (count($arr['lead']) == 1) {
$arr['lead'] = $arr['lead'][0];
}
foreach ($maintainers as $maintainer) {
if ($maintainer['role'] == 'lead') {
continue;
}
$new = array(
'name' => $maintainer['name'],
'user' => $maintainer['handle'],
'email' => $maintainer['email'],
'active' => 'yes',
);
$arr[$maintainer['role']][] = $new;
}
if (isset($arr['developer']) && count($arr['developer']) == 1) {
$arr['developer'] = $arr['developer'][0];
}
if (isset($arr['contributor']) && count($arr['contributor']) == 1) {
$arr['contributor'] = $arr['contributor'][0];
}
if (isset($arr['helper']) && count($arr['helper']) == 1) {
$arr['helper'] = $arr['helper'][0];
}
$arr['date'] = $this->_packagefile->getDate();
$arr['version'] =
array(
'release' => $this->_packagefile->getVersion(),
'api' => $this->_packagefile->getVersion(),
);
$arr['stability'] =
array(
'release' => $this->_packagefile->getState(),
'api' => $this->_packagefile->getState(),
);
$licensemap =
array(
'php' => 'http://www.php.net/license',
'php license' => 'http://www.php.net/license',
'lgpl' => 'http://www.gnu.org/copyleft/lesser.html',
'bsd' => 'http://www.opensource.org/licenses/bsd-license.php',
'bsd style' => 'http://www.opensource.org/licenses/bsd-license.php',
'bsd-style' => 'http://www.opensource.org/licenses/bsd-license.php',
'mit' => 'http://www.opensource.org/licenses/mit-license.php',
'gpl' => 'http://www.gnu.org/copyleft/gpl.html',
'apache' => 'http://www.opensource.org/licenses/apache2.0.php'
);
if (isset($licensemap[strtolower($this->_packagefile->getLicense())])) {
$arr['license'] = array(
'attribs' => array('uri' =>
$licensemap[strtolower($this->_packagefile->getLicense())]),
'_content' => $this->_packagefile->getLicense()
);
} else {
// don't use bogus uri
$arr['license'] = $this->_packagefile->getLicense();
}
$arr['notes'] = $this->_packagefile->getNotes();
$temp = array();
$arr['contents'] = $this->_convertFilelist2_0($temp);
$this->_convertDependencies2_0($arr);
$release = ($this->_packagefile->getConfigureOptions() || $this->_isExtension) ?
'extsrcrelease' : 'phprelease';
if ($release == 'extsrcrelease') {
$arr['channel'] = 'pecl.php.net';
$arr['providesextension'] = $arr['name']; // assumption
}
$arr[$release] = array();
if ($this->_packagefile->getConfigureOptions()) {
$arr[$release]['configureoption'] = $this->_packagefile->getConfigureOptions();
foreach ($arr[$release]['configureoption'] as $i => $opt) {
$arr[$release]['configureoption'][$i] = array('attribs' => $opt);
}
if (count($arr[$release]['configureoption']) == 1) {
$arr[$release]['configureoption'] = $arr[$release]['configureoption'][0];
}
}
$this->_convertRelease2_0($arr[$release], $temp);
if ($release == 'extsrcrelease' && count($arr[$release]) > 1) {
// multiple extsrcrelease tags added in PEAR 1.4.1
$arr['dependencies']['required']['pearinstaller']['min'] = '1.4.1';
}
if ($cl = $this->_packagefile->getChangelog()) {
foreach ($cl as $release) {
$rel = array();
$rel['version'] =
array(
'release' => $release['version'],
'api' => $release['version'],
);
if (!isset($release['release_state'])) {
$release['release_state'] = 'stable';
}
$rel['stability'] =
array(
'release' => $release['release_state'],
'api' => $release['release_state'],
);
if (isset($release['release_date'])) {
$rel['date'] = $release['release_date'];
} else {
$rel['date'] = date('Y-m-d');
}
if (isset($release['release_license'])) {
if (isset($licensemap[strtolower($release['release_license'])])) {
$uri = $licensemap[strtolower($release['release_license'])];
} else {
$uri = 'http://www.example.com';
}
$rel['license'] = array(
'attribs' => array('uri' => $uri),
'_content' => $release['release_license']
);
} else {
$rel['license'] = $arr['license'];
}
if (!isset($release['release_notes'])) {
$release['release_notes'] = 'no release notes';
}
$rel['notes'] = $release['release_notes'];
$arr['changelog']['release'][] = $rel;
}
}
$ret = new $class;
$ret->setConfig($this->_packagefile->_config);
if (isset($this->_packagefile->_logger) && is_object($this->_packagefile->_logger)) {
$ret->setLogger($this->_packagefile->_logger);
}
$ret->fromArray($arr);
return $ret;
}
/**
* @param array
* @param bool
* @access private
*/
function _convertDependencies2_0(&$release, $internal = false)
{
$peardep = array('pearinstaller' =>
array('min' => '1.4.0b1')); // this is a lot safer
$required = $optional = array();
$release['dependencies'] = array('required' => array());
if ($this->_packagefile->hasDeps()) {
foreach ($this->_packagefile->getDeps() as $dep) {
if (!isset($dep['optional']) || $dep['optional'] == 'no') {
$required[] = $dep;
} else {
$optional[] = $dep;
}
}
foreach (array('required', 'optional') as $arr) {
$deps = array();
foreach ($$arr as $dep) {
// organize deps by dependency type and name
if (!isset($deps[$dep['type']])) {
$deps[$dep['type']] = array();
}
if (isset($dep['name'])) {
$deps[$dep['type']][$dep['name']][] = $dep;
} else {
$deps[$dep['type']][] = $dep;
}
}
do {
if (isset($deps['php'])) {
$php = array();
if (count($deps['php']) > 1) {
$php = $this->_processPhpDeps($deps['php']);
} else {
if (!isset($deps['php'][0])) {
list($key, $blah) = each ($deps['php']); // stupid buggy versions
$deps['php'] = array($blah[0]);
}
$php = $this->_processDep($deps['php'][0]);
if (!$php) {
break; // poor mans throw
}
}
$release['dependencies'][$arr]['php'] = $php;
}
} while (false);
do {
if (isset($deps['pkg'])) {
$pkg = array();
$pkg = $this->_processMultipleDepsName($deps['pkg']);
if (!$pkg) {
break; // poor mans throw
}
$release['dependencies'][$arr]['package'] = $pkg;
}
} while (false);
do {
if (isset($deps['ext'])) {
$pkg = array();
$pkg = $this->_processMultipleDepsName($deps['ext']);
$release['dependencies'][$arr]['extension'] = $pkg;
}
} while (false);
// skip sapi - it's not supported so nobody will have used it
// skip os - it's not supported in 1.0
}
}
if (isset($release['dependencies']['required'])) {
$release['dependencies']['required'] =
array_merge($peardep, $release['dependencies']['required']);
} else {
$release['dependencies']['required'] = $peardep;
}
if (!isset($release['dependencies']['required']['php'])) {
$release['dependencies']['required']['php'] =
array('min' => '4.0.0');
}
$order = array();
$bewm = $release['dependencies']['required'];
$order['php'] = $bewm['php'];
$order['pearinstaller'] = $bewm['pearinstaller'];
isset($bewm['package']) ? $order['package'] = $bewm['package'] :0;
isset($bewm['extension']) ? $order['extension'] = $bewm['extension'] :0;
$release['dependencies']['required'] = $order;
}
/**
* @param array
* @access private
*/
function _convertFilelist2_0(&$package)
{
$ret = array('dir' =>
array(
'attribs' => array('name' => '/'),
'file' => array()
)
);
$package['platform'] =
$package['install-as'] = array();
$this->_isExtension = false;
foreach ($this->_packagefile->getFilelist() as $name => $file) {
$file['name'] = $name;
if (isset($file['role']) && $file['role'] == 'src') {
$this->_isExtension = true;
}
if (isset($file['replacements'])) {
$repl = $file['replacements'];
unset($file['replacements']);
} else {
unset($repl);
}
if (isset($file['install-as'])) {
$package['install-as'][$name] = $file['install-as'];
unset($file['install-as']);
}
if (isset($file['platform'])) {
$package['platform'][$name] = $file['platform'];
unset($file['platform']);
}
$file = array('attribs' => $file);
if (isset($repl)) {
foreach ($repl as $replace ) {
$file['tasks:replace'][] = array('attribs' => $replace);
}
if (count($repl) == 1) {
$file['tasks:replace'] = $file['tasks:replace'][0];
}
}
$ret['dir']['file'][] = $file;
}
return $ret;
}
/**
* Post-process special files with install-as/platform attributes and
* make the release tag.
*
* This complex method follows this work-flow to create the release tags:
*
*
* - if any install-as/platform exist, create a generic release and fill it with
* o tags for
* o tags for
* o tags for
* o tags for
* - create a release for each platform encountered and fill with
* o tags for
* o tags for
* o tags for
* o tags for
* o tags for
* o tags for
* o tags for
*
*
* It does this by accessing the $package parameter, which contains an array with
* indices:
*
* - platform: mapping of file => OS the file should be installed on
* - install-as: mapping of file => installed name
* - osmap: mapping of OS => list of files that should be installed
* on that OS
* - notosmap: mapping of OS => list of files that should not be
* installed on that OS
*
* @param array
* @param array
* @access private
*/
function _convertRelease2_0(&$release, $package)
{
//- if any install-as/platform exist, create a generic release and fill it with
if (count($package['platform']) || count($package['install-as'])) {
$generic = array();
$genericIgnore = array();
foreach ($package['install-as'] as $file => $as) {
//o tags for
if (!isset($package['platform'][$file])) {
$generic[] = $file;
continue;
}
//o tags for
if (isset($package['platform'][$file]) &&
$package['platform'][$file]{0} == '!') {
$generic[] = $file;
continue;
}
//o tags for
if (isset($package['platform'][$file]) &&
$package['platform'][$file]{0} != '!') {
$genericIgnore[] = $file;
continue;
}
}
foreach ($package['platform'] as $file => $platform) {
if (isset($package['install-as'][$file])) {
continue;
}
if ($platform{0} != '!') {
//o tags for
$genericIgnore[] = $file;
}
}
if (count($package['platform'])) {
$oses = $notplatform = $platform = array();
foreach ($package['platform'] as $file => $os) {
// get a list of oses
if ($os{0} == '!') {
if (isset($oses[substr($os, 1)])) {
continue;
}
$oses[substr($os, 1)] = count($oses);
} else {
if (isset($oses[$os])) {
continue;
}
$oses[$os] = count($oses);
}
}
//- create a release for each platform encountered and fill with
foreach ($oses as $os => $releaseNum) {
$release[$releaseNum]['installconditions']['os']['name'] = $os;
$release[$releaseNum]['filelist'] = array('install' => array(),
'ignore' => array());
foreach ($package['install-as'] as $file => $as) {
//o tags for
if (!isset($package['platform'][$file])) {
$release[$releaseNum]['filelist']['install'][] =
array(
'attribs' => array(
'name' => $file,
'as' => $as,
),
);
continue;
}
//o tags for
//
if (isset($package['platform'][$file]) &&
$package['platform'][$file] == $os) {
$release[$releaseNum]['filelist']['install'][] =
array(
'attribs' => array(
'name' => $file,
'as' => $as,
),
);
continue;
}
//o tags for
//
if (isset($package['platform'][$file]) &&
$package['platform'][$file] != "!$os" &&
$package['platform'][$file]{0} == '!') {
$release[$releaseNum]['filelist']['install'][] =
array(
'attribs' => array(
'name' => $file,
'as' => $as,
),
);
continue;
}
//o tags for
//
if (isset($package['platform'][$file]) &&
$package['platform'][$file] == "!$os") {
$release[$releaseNum]['filelist']['ignore'][] =
array(
'attribs' => array(
'name' => $file,
),
);
continue;
}
//o tags for
//
if (isset($package['platform'][$file]) &&
$package['platform'][$file]{0} != '!' &&
$package['platform'][$file] != $os) {
$release[$releaseNum]['filelist']['ignore'][] =
array(
'attribs' => array(
'name' => $file,
),
);
continue;
}
}
foreach ($package['platform'] as $file => $platform) {
if (isset($package['install-as'][$file])) {
continue;
}
//o tags for
if ($platform == "!$os") {
$release[$releaseNum]['filelist']['ignore'][] =
array(
'attribs' => array(
'name' => $file,
),
);
continue;
}
//o tags for
if ($platform{0} != '!' && $platform != $os) {
$release[$releaseNum]['filelist']['ignore'][] =
array(
'attribs' => array(
'name' => $file,
),
);
}
}
if (!count($release[$releaseNum]['filelist']['install'])) {
unset($release[$releaseNum]['filelist']['install']);
}
if (!count($release[$releaseNum]['filelist']['ignore'])) {
unset($release[$releaseNum]['filelist']['ignore']);
}
}
if (count($generic) || count($genericIgnore)) {
$release[count($oses)] = array();
if (count($generic)) {
foreach ($generic as $file) {
if (isset($package['install-as'][$file])) {
$installas = $package['install-as'][$file];
} else {
$installas = $file;
}
$release[count($oses)]['filelist']['install'][] =
array(
'attribs' => array(
'name' => $file,
'as' => $installas,
)
);
}
}
if (count($genericIgnore)) {
foreach ($genericIgnore as $file) {
$release[count($oses)]['filelist']['ignore'][] =
array(
'attribs' => array(
'name' => $file,
)
);
}
}
}
// cleanup
foreach ($release as $i => $rel) {
if (isset($rel['filelist']['install']) &&
count($rel['filelist']['install']) == 1) {
$release[$i]['filelist']['install'] =
$release[$i]['filelist']['install'][0];
}
if (isset($rel['filelist']['ignore']) &&
count($rel['filelist']['ignore']) == 1) {
$release[$i]['filelist']['ignore'] =
$release[$i]['filelist']['ignore'][0];
}
}
if (count($release) == 1) {
$release = $release[0];
}
} else {
// no platform atts, but some install-as atts
foreach ($package['install-as'] as $file => $value) {
$release['filelist']['install'][] =
array(
'attribs' => array(
'name' => $file,
'as' => $value
)
);
}
if (count($release['filelist']['install']) == 1) {
$release['filelist']['install'] = $release['filelist']['install'][0];
}
}
}
}
/**
* @param array
* @return array
* @access private
*/
function _processDep($dep)
{
if ($dep['type'] == 'php') {
if ($dep['rel'] == 'has') {
// come on - everyone has php!
return false;
}
}
$php = array();
if ($dep['type'] != 'php') {
$php['name'] = $dep['name'];
if ($dep['type'] == 'pkg') {
$php['channel'] = 'pear.php.net';
}
}
switch ($dep['rel']) {
case 'gt' :
$php['min'] = $dep['version'];
$php['exclude'] = $dep['version'];
break;
case 'ge' :
if (!isset($dep['version'])) {
if ($dep['type'] == 'php') {
if (isset($dep['name'])) {
$dep['version'] = $dep['name'];
}
}
}
$php['min'] = $dep['version'];
break;
case 'lt' :
$php['max'] = $dep['version'];
$php['exclude'] = $dep['version'];
break;
case 'le' :
$php['max'] = $dep['version'];
break;
case 'eq' :
$php['min'] = $dep['version'];
$php['max'] = $dep['version'];
break;
case 'ne' :
$php['exclude'] = $dep['version'];
break;
case 'not' :
$php['conflicts'] = 'yes';
break;
}
return $php;
}
/**
* @param array
* @return array
*/
function _processPhpDeps($deps)
{
$test = array();
foreach ($deps as $dep) {
$test[] = $this->_processDep($dep);
}
$min = array();
$max = array();
foreach ($test as $dep) {
if (!$dep) {
continue;
}
if (isset($dep['min'])) {
$min[$dep['min']] = count($min);
}
if (isset($dep['max'])) {
$max[$dep['max']] = count($max);
}
}
if (count($min) > 0) {
uksort($min, 'version_compare');
}
if (count($max) > 0) {
uksort($max, 'version_compare');
}
if (count($min)) {
// get the highest minimum
$a = array_flip($min);
$min = array_pop($a);
} else {
$min = false;
}
if (count($max)) {
// get the lowest maximum
$a = array_flip($max);
$max = array_shift($a);
} else {
$max = false;
}
if ($min) {
$php['min'] = $min;
}
if ($max) {
$php['max'] = $max;
}
$exclude = array();
foreach ($test as $dep) {
if (!isset($dep['exclude'])) {
continue;
}
$exclude[] = $dep['exclude'];
}
if (count($exclude)) {
$php['exclude'] = $exclude;
}
return $php;
}
/**
* process multiple dependencies that have a name, like package deps
* @param array
* @return array
* @access private
*/
function _processMultipleDepsName($deps)
{
$ret = $tests = array();
foreach ($deps as $name => $dep) {
foreach ($dep as $d) {
$tests[$name][] = $this->_processDep($d);
}
}
foreach ($tests as $name => $test) {
$max = $min = $php = array();
$php['name'] = $name;
foreach ($test as $dep) {
if (!$dep) {
continue;
}
if (isset($dep['channel'])) {
$php['channel'] = 'pear.php.net';
}
if (isset($dep['conflicts']) && $dep['conflicts'] == 'yes') {
$php['conflicts'] = 'yes';
}
if (isset($dep['min'])) {
$min[$dep['min']] = count($min);
}
if (isset($dep['max'])) {
$max[$dep['max']] = count($max);
}
}
if (count($min) > 0) {
uksort($min, 'version_compare');
}
if (count($max) > 0) {
uksort($max, 'version_compare');
}
if (count($min)) {
// get the highest minimum
$a = array_flip($min);
$min = array_pop($a);
} else {
$min = false;
}
if (count($max)) {
// get the lowest maximum
$a = array_flip($max);
$max = array_shift($a);
} else {
$max = false;
}
if ($min) {
$php['min'] = $min;
}
if ($max) {
$php['max'] = $max;
}
$exclude = array();
foreach ($test as $dep) {
if (!isset($dep['exclude'])) {
continue;
}
$exclude[] = $dep['exclude'];
}
if (count($exclude)) {
$php['exclude'] = $exclude;
}
$ret[] = $php;
}
return $ret;
}
}
?>
PK [1{3Ɓ Ɓ ! PEAR/PackageFile/Generator/v2.phpnu W+A
* @author Stephan Schmidt (original XML_Serializer code)
* @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
*/
/**
* file/dir manipulation routines
*/
require_once 'System.php';
require_once 'XML/Util.php';
/**
* This class converts a PEAR_PackageFile_v2 object into any output format.
*
* Supported output formats include array, XML string (using S. Schmidt's
* XML_Serializer, slightly customized)
* @category pear
* @package PEAR
* @author Greg Beaver
* @author Stephan Schmidt (original XML_Serializer code)
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_PackageFile_Generator_v2
{
/**
* default options for the serialization
* @access private
* @var array $_defaultOptions
*/
var $_defaultOptions = array(
'indent' => ' ', // string used for indentation
'linebreak' => "\n", // string used for newlines
'typeHints' => false, // automatically add type hin attributes
'addDecl' => true, // add an XML declaration
'defaultTagName' => 'XML_Serializer_Tag', // tag used for indexed arrays or invalid names
'classAsTagName' => false, // use classname for objects in indexed arrays
'keyAttribute' => '_originalKey', // attribute where original key is stored
'typeAttribute' => '_type', // attribute for type (only if typeHints => true)
'classAttribute' => '_class', // attribute for class of objects (only if typeHints => true)
'scalarAsAttributes' => false, // scalar values (strings, ints,..) will be serialized as attribute
'prependAttributes' => '', // prepend string for attributes
'indentAttributes' => false, // indent the attributes, if set to '_auto', it will indent attributes so they all start at the same column
'mode' => 'simplexml', // use 'simplexml' to use parent name as tagname if transforming an indexed array
'addDoctype' => false, // add a doctype declaration
'doctype' => null, // supply a string or an array with id and uri ({@see XML_Util::getDoctypeDeclaration()}
'rootName' => 'package', // name of the root tag
'rootAttributes' => array(
'version' => '2.0',
'xmlns' => 'http://pear.php.net/dtd/package-2.0',
'xmlns:tasks' => 'http://pear.php.net/dtd/tasks-1.0',
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
'xsi:schemaLocation' => 'http://pear.php.net/dtd/tasks-1.0
http://pear.php.net/dtd/tasks-1.0.xsd
http://pear.php.net/dtd/package-2.0
http://pear.php.net/dtd/package-2.0.xsd',
), // attributes of the root tag
'attributesArray' => 'attribs', // all values in this key will be treated as attributes
'contentName' => '_content', // this value will be used directly as content, instead of creating a new tag, may only be used in conjunction with attributesArray
'beautifyFilelist' => false,
'encoding' => 'UTF-8',
);
/**
* options for the serialization
* @access private
* @var array $options
*/
var $options = array();
/**
* current tag depth
* @var integer $_tagDepth
*/
var $_tagDepth = 0;
/**
* serilialized representation of the data
* @var string $_serializedData
*/
var $_serializedData = null;
/**
* @var PEAR_PackageFile_v2
*/
var $_packagefile;
/**
* @param PEAR_PackageFile_v2
*/
function __construct(&$packagefile)
{
$this->_packagefile = &$packagefile;
if (isset($this->_packagefile->encoding)) {
$this->_defaultOptions['encoding'] = $this->_packagefile->encoding;
}
}
/**
* @return string
*/
function getPackagerVersion()
{
return '1.10.4';
}
/**
* @param PEAR_Packager
* @param bool generate a .tgz or a .tar
* @param string|null temporary directory to package in
*/
function toTgz(&$packager, $compress = true, $where = null)
{
$a = null;
return $this->toTgz2($packager, $a, $compress, $where);
}
/**
* Package up both a package.xml and package2.xml for the same release
* @param PEAR_Packager
* @param PEAR_PackageFile_v1
* @param bool generate a .tgz or a .tar
* @param string|null temporary directory to package in
*/
function toTgz2(&$packager, &$pf1, $compress = true, $where = null)
{
require_once 'Archive/Tar.php';
if (!$this->_packagefile->isEquivalent($pf1)) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' .
basename($pf1->getPackageFile()) .
'" is not equivalent to "' . basename($this->_packagefile->getPackageFile())
. '"');
}
if ($where === null) {
if (!($where = System::mktemp(array('-d')))) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: mktemp failed');
}
} elseif (!@System::mkDir(array('-p', $where))) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: "' . $where . '" could' .
' not be created');
}
$file = $where . DIRECTORY_SEPARATOR . 'package.xml';
if (file_exists($file) && !is_file($file)) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: unable to save package.xml as' .
' "' . $file .'"');
}
if (!$this->_packagefile->validate(PEAR_VALIDATE_PACKAGING)) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: invalid package.xml');
}
$ext = $compress ? '.tgz' : '.tar';
$pkgver = $this->_packagefile->getPackage() . '-' . $this->_packagefile->getVersion();
$dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext;
if (file_exists($dest_package) && !is_file($dest_package)) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: cannot create tgz file "' .
$dest_package . '"');
}
$pkgfile = $this->_packagefile->getPackageFile();
if (!$pkgfile) {
return PEAR::raiseError('PEAR_Packagefile_v2::toTgz: package file object must ' .
'be created from a real file');
}
$pkgdir = dirname(realpath($pkgfile));
$pkgfile = basename($pkgfile);
// {{{ Create the package file list
$filelist = array();
$i = 0;
$this->_packagefile->flattenFilelist();
$contents = $this->_packagefile->getContents();
if (isset($contents['bundledpackage'])) { // bundles of packages
$contents = $contents['bundledpackage'];
if (!isset($contents[0])) {
$contents = array($contents);
}
$packageDir = $where;
foreach ($contents as $i => $package) {
$fname = $package;
$file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
if (!file_exists($file)) {
return $packager->raiseError("File does not exist: $fname");
}
$tfile = $packageDir . DIRECTORY_SEPARATOR . $fname;
System::mkdir(array('-p', dirname($tfile)));
copy($file, $tfile);
$filelist[$i++] = $tfile;
$packager->log(2, "Adding package $fname");
}
} else { // normal packages
$contents = $contents['dir']['file'];
if (!isset($contents[0])) {
$contents = array($contents);
}
$packageDir = $where;
foreach ($contents as $i => $file) {
$fname = $file['attribs']['name'];
$atts = $file['attribs'];
$orig = $file;
$file = $pkgdir . DIRECTORY_SEPARATOR . $fname;
if (!file_exists($file)) {
return $packager->raiseError("File does not exist: $fname");
}
$origperms = fileperms($file);
$tfile = $packageDir . DIRECTORY_SEPARATOR . $fname;
unset($orig['attribs']);
if (count($orig)) { // file with tasks
// run any package-time tasks
$contents = file_get_contents($file);
foreach ($orig as $tag => $raw) {
$tag = str_replace(
array($this->_packagefile->getTasksNs() . ':', '-'),
array('', '_'), $tag);
$task = "PEAR_Task_$tag";
$task = new $task($this->_packagefile->_config,
$this->_packagefile->_logger,
PEAR_TASK_PACKAGE);
$task->init($raw, $atts, null);
$res = $task->startSession($this->_packagefile, $contents, $tfile);
if (!$res) {
continue; // skip this task
}
if (PEAR::isError($res)) {
return $res;
}
$contents = $res; // save changes
System::mkdir(array('-p', dirname($tfile)));
$wp = fopen($tfile, "wb");
fwrite($wp, $contents);
fclose($wp);
}
}
if (!file_exists($tfile)) {
System::mkdir(array('-p', dirname($tfile)));
copy($file, $tfile);
}
chmod($tfile, $origperms);
$filelist[$i++] = $tfile;
$this->_packagefile->setFileAttribute($fname, 'md5sum', md5_file($tfile), $i - 1);
$packager->log(2, "Adding file $fname");
}
}
// }}}
$name = $pf1 !== null ? 'package2.xml' : 'package.xml';
$packagexml = $this->toPackageFile($where, PEAR_VALIDATE_PACKAGING, $name);
if ($packagexml) {
$tar = new Archive_Tar($dest_package, $compress);
$tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors
// ----- Creates with the package.xml file
$ok = $tar->createModify(array($packagexml), '', $where);
if (PEAR::isError($ok)) {
return $packager->raiseError($ok);
} elseif (!$ok) {
return $packager->raiseError('PEAR_Packagefile_v2::toTgz(): adding ' . $name .
' failed');
}
// ----- Add the content of the package
if (!$tar->addModify($filelist, $pkgver, $where)) {
return $packager->raiseError(
'PEAR_Packagefile_v2::toTgz(): tarball creation failed');
}
// add the package.xml version 1.0
if ($pf1 !== null) {
$pfgen = &$pf1->getDefaultGenerator();
$packagexml1 = $pfgen->toPackageFile($where, PEAR_VALIDATE_PACKAGING, 'package.xml', true);
if (!$tar->addModify(array($packagexml1), '', $where)) {
return $packager->raiseError(
'PEAR_Packagefile_v2::toTgz(): adding package.xml failed');
}
}
return $dest_package;
}
}
function toPackageFile($where = null, $state = PEAR_VALIDATE_NORMAL, $name = 'package.xml')
{
if (!$this->_packagefile->validate($state)) {
return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: invalid package.xml',
null, null, null, $this->_packagefile->getValidationWarnings());
}
if ($where === null) {
if (!($where = System::mktemp(array('-d')))) {
return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: mktemp failed');
}
} elseif (!@System::mkDir(array('-p', $where))) {
return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: "' . $where . '" could' .
' not be created');
}
$newpkgfile = $where . DIRECTORY_SEPARATOR . $name;
$np = @fopen($newpkgfile, 'wb');
if (!$np) {
return PEAR::raiseError('PEAR_Packagefile_v2::toPackageFile: unable to save ' .
"$name as $newpkgfile");
}
fwrite($np, $this->toXml($state));
fclose($np);
return $newpkgfile;
}
function &toV2()
{
return $this->_packagefile;
}
/**
* Return an XML document based on the package info (as returned
* by the PEAR_Common::infoFrom* methods).
*
* @return string XML data
*/
function toXml($state = PEAR_VALIDATE_NORMAL, $options = array())
{
$this->_packagefile->setDate(date('Y-m-d'));
$this->_packagefile->setTime(date('H:i:s'));
if (!$this->_packagefile->validate($state)) {
return false;
}
if (is_array($options)) {
$this->options = array_merge($this->_defaultOptions, $options);
} else {
$this->options = $this->_defaultOptions;
}
$arr = $this->_packagefile->getArray();
if (isset($arr['filelist'])) {
unset($arr['filelist']);
}
if (isset($arr['_lastversion'])) {
unset($arr['_lastversion']);
}
// Fix the notes a little bit
if (isset($arr['notes'])) {
// This trims out the indenting, needs fixing
$arr['notes'] = "\n" . trim($arr['notes']) . "\n";
}
if (isset($arr['changelog']) && !empty($arr['changelog'])) {
// Fix for inconsistency how the array is filled depending on the changelog release amount
if (!isset($arr['changelog']['release'][0])) {
$release = $arr['changelog']['release'];
unset($arr['changelog']['release']);
$arr['changelog']['release'] = array();
$arr['changelog']['release'][0] = $release;
}
foreach (array_keys($arr['changelog']['release']) as $key) {
$c =& $arr['changelog']['release'][$key];
if (isset($c['notes'])) {
// This trims out the indenting, needs fixing
$c['notes'] = "\n" . trim($c['notes']) . "\n";
}
}
}
if ($state ^ PEAR_VALIDATE_PACKAGING && !isset($arr['bundle'])) {
$use = $this->_recursiveXmlFilelist($arr['contents']['dir']['file']);
unset($arr['contents']['dir']['file']);
if (isset($use['dir'])) {
$arr['contents']['dir']['dir'] = $use['dir'];
}
if (isset($use['file'])) {
$arr['contents']['dir']['file'] = $use['file'];
}
$this->options['beautifyFilelist'] = true;
}
$arr['attribs']['packagerversion'] = '1.10.4';
if ($this->serialize($arr, $options)) {
return $this->_serializedData . "\n";
}
return false;
}
function _recursiveXmlFilelist($list)
{
$dirs = array();
if (isset($list['attribs'])) {
$file = $list['attribs']['name'];
unset($list['attribs']['name']);
$attributes = $list['attribs'];
$this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes);
} else {
foreach ($list as $a) {
$file = $a['attribs']['name'];
$attributes = $a['attribs'];
unset($a['attribs']);
$this->_addDir($dirs, explode('/', dirname($file)), $file, $attributes, $a);
}
}
$this->_formatDir($dirs);
$this->_deFormat($dirs);
return $dirs;
}
function _addDir(&$dirs, $dir, $file = null, $attributes = null, $tasks = null)
{
if (!$tasks) {
$tasks = array();
}
if ($dir == array() || $dir == array('.')) {
$dirs['file'][basename($file)] = $tasks;
$attributes['name'] = basename($file);
$dirs['file'][basename($file)]['attribs'] = $attributes;
return;
}
$curdir = array_shift($dir);
if (!isset($dirs['dir'][$curdir])) {
$dirs['dir'][$curdir] = array();
}
$this->_addDir($dirs['dir'][$curdir], $dir, $file, $attributes, $tasks);
}
function _formatDir(&$dirs)
{
if (!count($dirs)) {
return array();
}
$newdirs = array();
if (isset($dirs['dir'])) {
$newdirs['dir'] = $dirs['dir'];
}
if (isset($dirs['file'])) {
$newdirs['file'] = $dirs['file'];
}
$dirs = $newdirs;
if (isset($dirs['dir'])) {
uksort($dirs['dir'], 'strnatcasecmp');
foreach ($dirs['dir'] as $dir => $contents) {
$this->_formatDir($dirs['dir'][$dir]);
}
}
if (isset($dirs['file'])) {
uksort($dirs['file'], 'strnatcasecmp');
};
}
function _deFormat(&$dirs)
{
if (!count($dirs)) {
return array();
}
$newdirs = array();
if (isset($dirs['dir'])) {
foreach ($dirs['dir'] as $dir => $contents) {
$newdir = array();
$newdir['attribs']['name'] = $dir;
$this->_deFormat($contents);
foreach ($contents as $tag => $val) {
$newdir[$tag] = $val;
}
$newdirs['dir'][] = $newdir;
}
if (count($newdirs['dir']) == 1) {
$newdirs['dir'] = $newdirs['dir'][0];
}
}
if (isset($dirs['file'])) {
foreach ($dirs['file'] as $name => $file) {
$newdirs['file'][] = $file;
}
if (count($newdirs['file']) == 1) {
$newdirs['file'] = $newdirs['file'][0];
}
}
$dirs = $newdirs;
}
/**
* reset all options to default options
*
* @access public
* @see setOption(), XML_Unserializer()
*/
function resetOptions()
{
$this->options = $this->_defaultOptions;
}
/**
* set an option
*
* You can use this method if you do not want to set all options in the constructor
*
* @access public
* @see resetOption(), XML_Serializer()
*/
function setOption($name, $value)
{
$this->options[$name] = $value;
}
/**
* sets several options at once
*
* You can use this method if you do not want to set all options in the constructor
*
* @access public
* @see resetOption(), XML_Unserializer(), setOption()
*/
function setOptions($options)
{
$this->options = array_merge($this->options, $options);
}
/**
* serialize data
*
* @access public
* @param mixed $data data to serialize
* @return boolean true on success, pear error on failure
*/
function serialize($data, $options = null)
{
// if options have been specified, use them instead
// of the previously defined ones
if (is_array($options)) {
$optionsBak = $this->options;
if (isset($options['overrideOptions']) && $options['overrideOptions'] == true) {
$this->options = array_merge($this->_defaultOptions, $options);
} else {
$this->options = array_merge($this->options, $options);
}
} else {
$optionsBak = null;
}
// start depth is zero
$this->_tagDepth = 0;
$this->_serializedData = '';
// serialize an array
if (is_array($data)) {
$tagName = isset($this->options['rootName']) ? $this->options['rootName'] : 'array';
$this->_serializedData .= $this->_serializeArray($data, $tagName, $this->options['rootAttributes']);
}
// add doctype declaration
if ($this->options['addDoctype'] === true) {
$this->_serializedData = XML_Util::getDoctypeDeclaration($tagName, $this->options['doctype'])
. $this->options['linebreak']
. $this->_serializedData;
}
// build xml declaration
if ($this->options['addDecl']) {
$atts = array();
$encoding = isset($this->options['encoding']) ? $this->options['encoding'] : null;
$this->_serializedData = XML_Util::getXMLDeclaration('1.0', $encoding)
. $this->options['linebreak']
. $this->_serializedData;
}
if ($optionsBak !== null) {
$this->options = $optionsBak;
}
return true;
}
/**
* get the result of the serialization
*
* @access public
* @return string serialized XML
*/
function getSerializedData()
{
if ($this->_serializedData === null) {
return $this->raiseError('No serialized data available. Use XML_Serializer::serialize() first.', XML_SERIALIZER_ERROR_NO_SERIALIZATION);
}
return $this->_serializedData;
}
/**
* serialize any value
*
* This method checks for the type of the value and calls the appropriate method
*
* @access private
* @param mixed $value
* @param string $tagName
* @param array $attributes
* @return string
*/
function _serializeValue($value, $tagName = null, $attributes = array())
{
if (is_array($value)) {
$xml = $this->_serializeArray($value, $tagName, $attributes);
} elseif (is_object($value)) {
$xml = $this->_serializeObject($value, $tagName);
} else {
$tag = array(
'qname' => $tagName,
'attributes' => $attributes,
'content' => $value
);
$xml = $this->_createXMLTag($tag);
}
return $xml;
}
/**
* serialize an array
*
* @access private
* @param array $array array to serialize
* @param string $tagName name of the root tag
* @param array $attributes attributes for the root tag
* @return string $string serialized data
* @uses XML_Util::isValidName() to check, whether key has to be substituted
*/
function _serializeArray(&$array, $tagName = null, $attributes = array())
{
$_content = null;
/**
* check for special attributes
*/
if ($this->options['attributesArray'] !== null) {
if (isset($array[$this->options['attributesArray']])) {
$attributes = $array[$this->options['attributesArray']];
unset($array[$this->options['attributesArray']]);
}
/**
* check for special content
*/
if ($this->options['contentName'] !== null) {
if (isset($array[$this->options['contentName']])) {
$_content = $array[$this->options['contentName']];
unset($array[$this->options['contentName']]);
}
}
}
/*
* if mode is set to simpleXML, check whether
* the array is associative or indexed
*/
if (is_array($array) && $this->options['mode'] == 'simplexml') {
$indexed = true;
if (!count($array)) {
$indexed = false;
}
foreach ($array as $key => $val) {
if (!is_int($key)) {
$indexed = false;
break;
}
}
if ($indexed && $this->options['mode'] == 'simplexml') {
$string = '';
foreach ($array as $key => $val) {
if ($this->options['beautifyFilelist'] && $tagName == 'dir') {
if (!isset($this->_curdir)) {
$this->_curdir = '';
}
$savedir = $this->_curdir;
if (isset($val['attribs'])) {
if ($val['attribs']['name'] == '/') {
$this->_curdir = '/';
} else {
if ($this->_curdir == '/') {
$this->_curdir = '';
}
$this->_curdir .= '/' . $val['attribs']['name'];
}
}
}
$string .= $this->_serializeValue( $val, $tagName, $attributes);
if ($this->options['beautifyFilelist'] && $tagName == 'dir') {
$string .= ' ';
if (empty($savedir)) {
unset($this->_curdir);
} else {
$this->_curdir = $savedir;
}
}
$string .= $this->options['linebreak'];
// do indentation
if ($this->options['indent'] !== null && $this->_tagDepth > 0) {
$string .= str_repeat($this->options['indent'], $this->_tagDepth);
}
}
return rtrim($string);
}
}
if ($this->options['scalarAsAttributes'] === true) {
foreach ($array as $key => $value) {
if (is_scalar($value) && (XML_Util::isValidName($key) === true)) {
unset($array[$key]);
$attributes[$this->options['prependAttributes'].$key] = $value;
}
}
}
// check for empty array => create empty tag
if (empty($array)) {
$tag = array(
'qname' => $tagName,
'content' => $_content,
'attributes' => $attributes
);
} else {
$this->_tagDepth++;
$tmp = $this->options['linebreak'];
foreach ($array as $key => $value) {
// do indentation
if ($this->options['indent'] !== null && $this->_tagDepth > 0) {
$tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
}
// copy key
$origKey = $key;
// key cannot be used as tagname => use default tag
$valid = XML_Util::isValidName($key);
if (PEAR::isError($valid)) {
if ($this->options['classAsTagName'] && is_object($value)) {
$key = get_class($value);
} else {
$key = $this->options['defaultTagName'];
}
}
$atts = array();
if ($this->options['typeHints'] === true) {
$atts[$this->options['typeAttribute']] = gettype($value);
if ($key !== $origKey) {
$atts[$this->options['keyAttribute']] = (string)$origKey;
}
}
if ($this->options['beautifyFilelist'] && $key == 'dir') {
if (!isset($this->_curdir)) {
$this->_curdir = '';
}
$savedir = $this->_curdir;
if (isset($value['attribs'])) {
if ($value['attribs']['name'] == '/') {
$this->_curdir = '/';
} else {
$this->_curdir .= '/' . $value['attribs']['name'];
}
}
}
if (is_string($value) && $value && ($value{strlen($value) - 1} == "\n")) {
$value .= str_repeat($this->options['indent'], $this->_tagDepth);
}
$tmp .= $this->_createXMLTag(array(
'qname' => $key,
'attributes' => $atts,
'content' => $value )
);
if ($this->options['beautifyFilelist'] && $key == 'dir') {
if (isset($value['attribs'])) {
$tmp .= ' ';
if (empty($savedir)) {
unset($this->_curdir);
} else {
$this->_curdir = $savedir;
}
}
}
$tmp .= $this->options['linebreak'];
}
$this->_tagDepth--;
if ($this->options['indent']!==null && $this->_tagDepth>0) {
$tmp .= str_repeat($this->options['indent'], $this->_tagDepth);
}
if (trim($tmp) === '') {
$tmp = null;
}
$tag = array(
'qname' => $tagName,
'content' => $tmp,
'attributes' => $attributes
);
}
if ($this->options['typeHints'] === true) {
if (!isset($tag['attributes'][$this->options['typeAttribute']])) {
$tag['attributes'][$this->options['typeAttribute']] = 'array';
}
}
$string = $this->_createXMLTag($tag, false);
return $string;
}
/**
* create a tag from an array
* this method awaits an array in the following format
* array(
* 'qname' => $tagName,
* 'attributes' => array(),
* 'content' => $content, // optional
* 'namespace' => $namespace // optional
* 'namespaceUri' => $namespaceUri // optional
* )
*
* @access private
* @param array $tag tag definition
* @param boolean $replaceEntities whether to replace XML entities in content or not
* @return string $string XML tag
*/
function _createXMLTag($tag, $replaceEntities = true)
{
if ($this->options['indentAttributes'] !== false) {
$multiline = true;
$indent = str_repeat($this->options['indent'], $this->_tagDepth);
if ($this->options['indentAttributes'] == '_auto') {
$indent .= str_repeat(' ', (strlen($tag['qname'])+2));
} else {
$indent .= $this->options['indentAttributes'];
}
} else {
$indent = $multiline = false;
}
if (is_array($tag['content'])) {
if (empty($tag['content'])) {
$tag['content'] = '';
}
} elseif(is_scalar($tag['content']) && (string)$tag['content'] == '') {
$tag['content'] = '';
}
if (is_scalar($tag['content']) || is_null($tag['content'])) {
if ($replaceEntities === true) {
$replaceEntities = XML_UTIL_ENTITIES_XML;
}
$tag = XML_Util::createTagFromArray($tag, $replaceEntities, $multiline, $indent, $this->options['linebreak']);
} elseif (is_array($tag['content'])) {
$tag = $this->_serializeArray($tag['content'], $tag['qname'], $tag['attributes']);
} elseif (is_object($tag['content'])) {
$tag = $this->_serializeObject($tag['content'], $tag['qname'], $tag['attributes']);
} elseif (is_resource($tag['content'])) {
settype($tag['content'], 'string');
$tag = XML_Util::createTagFromArray($tag, $replaceEntities);
}
return $tag;
}
}
PK [( Q PEAR/PackageFile/v1.phpnu W+A
* @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
*/
/**
* For error handling
*/
require_once 'PEAR/ErrorStack.php';
/**
* Error code if parsing is attempted with no xml extension
*/
define('PEAR_PACKAGEFILE_ERROR_NO_XML_EXT', 3);
/**
* Error code if creating the xml parser resource fails
*/
define('PEAR_PACKAGEFILE_ERROR_CANT_MAKE_PARSER', 4);
/**
* Error code used for all sax xml parsing errors
*/
define('PEAR_PACKAGEFILE_ERROR_PARSER_ERROR', 5);
/**
* Error code used when there is no name
*/
define('PEAR_PACKAGEFILE_ERROR_NO_NAME', 6);
/**
* Error code when a package name is not valid
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_NAME', 7);
/**
* Error code used when no summary is parsed
*/
define('PEAR_PACKAGEFILE_ERROR_NO_SUMMARY', 8);
/**
* Error code for summaries that are more than 1 line
*/
define('PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY', 9);
/**
* Error code used when no description is present
*/
define('PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION', 10);
/**
* Error code used when no license is present
*/
define('PEAR_PACKAGEFILE_ERROR_NO_LICENSE', 11);
/**
* Error code used when a version number is not present
*/
define('PEAR_PACKAGEFILE_ERROR_NO_VERSION', 12);
/**
* Error code used when a version number is invalid
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_VERSION', 13);
/**
* Error code when release state is missing
*/
define('PEAR_PACKAGEFILE_ERROR_NO_STATE', 14);
/**
* Error code when release state is invalid
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_STATE', 15);
/**
* Error code when release state is missing
*/
define('PEAR_PACKAGEFILE_ERROR_NO_DATE', 16);
/**
* Error code when release state is invalid
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_DATE', 17);
/**
* Error code when no release notes are found
*/
define('PEAR_PACKAGEFILE_ERROR_NO_NOTES', 18);
/**
* Error code when no maintainers are found
*/
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS', 19);
/**
* Error code when a maintainer has no handle
*/
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE', 20);
/**
* Error code when a maintainer has no handle
*/
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE', 21);
/**
* Error code when a maintainer has no name
*/
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME', 22);
/**
* Error code when a maintainer has no email
*/
define('PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL', 23);
/**
* Error code when a maintainer has no handle
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_MAINTROLE', 24);
/**
* Error code when a dependency is not a PHP dependency, but has no name
*/
define('PEAR_PACKAGEFILE_ERROR_NO_DEPNAME', 25);
/**
* Error code when a dependency has no type (pkg, php, etc.)
*/
define('PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE', 26);
/**
* Error code when a dependency has no relation (lt, ge, has, etc.)
*/
define('PEAR_PACKAGEFILE_ERROR_NO_DEPREL', 27);
/**
* Error code when a dependency is not a 'has' relation, but has no version
*/
define('PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION', 28);
/**
* Error code when a dependency has an invalid relation
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPREL', 29);
/**
* Error code when a dependency has an invalid type
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPTYPE', 30);
/**
* Error code when a dependency has an invalid optional option
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL', 31);
/**
* Error code when a dependency is a pkg dependency, and has an invalid package name
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_DEPNAME', 32);
/**
* Error code when a dependency has a channel="foo" attribute, and foo is not a registered channel
*/
define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_DEPCHANNEL', 33);
/**
* Error code when rel="has" and version attribute is present.
*/
define('PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED', 34);
/**
* Error code when type="php" and dependency name is present
*/
define('PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED', 35);
/**
* Error code when a configure option has no name
*/
define('PEAR_PACKAGEFILE_ERROR_NO_CONFNAME', 36);
/**
* Error code when a configure option has no name
*/
define('PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT', 37);
/**
* Error code when a file in the filelist has an invalid role
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE', 38);
/**
* Error code when a file in the filelist has no role
*/
define('PEAR_PACKAGEFILE_ERROR_NO_FILEROLE', 39);
/**
* Error code when analyzing a php source file that has parse errors
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE', 40);
/**
* Error code when analyzing a php source file reveals a source element
* without a package name prefix
*/
define('PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX', 41);
/**
* Error code when an unknown channel is specified
*/
define('PEAR_PACKAGEFILE_ERROR_UNKNOWN_CHANNEL', 42);
/**
* Error code when no files are found in the filelist
*/
define('PEAR_PACKAGEFILE_ERROR_NO_FILES', 43);
/**
* Error code when a file is not valid php according to _analyzeSourceCode()
*/
define('PEAR_PACKAGEFILE_ERROR_INVALID_FILE', 44);
/**
* Error code when the channel validator returns an error or warning
*/
define('PEAR_PACKAGEFILE_ERROR_CHANNELVAL', 45);
/**
* Error code when a php5 package is packaged in php4 (analysis doesn't work)
*/
define('PEAR_PACKAGEFILE_ERROR_PHP5', 46);
/**
* Error code when a file is listed in package.xml but does not exist
*/
define('PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND', 47);
/**
* Error code when a
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_PackageFile_v1
{
/**
* @access private
* @var PEAR_ErrorStack
* @access private
*/
var $_stack;
/**
* A registry object, used to access the package name validation regex for non-standard channels
* @var PEAR_Registry
* @access private
*/
var $_registry;
/**
* An object that contains a log method that matches PEAR_Common::log's signature
* @var object
* @access private
*/
var $_logger;
/**
* Parsed package information
* @var array
* @access private
*/
var $_packageInfo;
/**
* path to package.xml
* @var string
* @access private
*/
var $_packageFile;
/**
* path to package .tgz or false if this is a local/extracted package.xml
* @var string
* @access private
*/
var $_archiveFile;
/**
* @var int
* @access private
*/
var $_isValid = 0;
/**
* Determines whether this packagefile was initialized only with partial package info
*
* If this package file was constructed via parsing REST, it will only contain
*
* - package name
* - channel name
* - dependencies
* @var boolean
* @access private
*/
var $_incomplete = true;
/**
* @param bool determines whether to return a PEAR_Error object, or use the PEAR_ErrorStack
* @param string Name of Error Stack class to use.
*/
function __construct()
{
$this->_stack = new PEAR_ErrorStack('PEAR_PackageFile_v1');
$this->_stack->setErrorMessageTemplate($this->_getErrorMessage());
$this->_isValid = 0;
}
function installBinary($installer)
{
return false;
}
function isExtension($name)
{
return false;
}
function setConfig(&$config)
{
$this->_config = &$config;
$this->_registry = &$config->getRegistry();
}
function setRequestedGroup()
{
// placeholder
}
/**
* For saving in the registry.
*
* Set the last version that was installed
* @param string
*/
function setLastInstalledVersion($version)
{
$this->_packageInfo['_lastversion'] = $version;
}
/**
* @return string|false
*/
function getLastInstalledVersion()
{
if (isset($this->_packageInfo['_lastversion'])) {
return $this->_packageInfo['_lastversion'];
}
return false;
}
function getInstalledBinary()
{
return false;
}
function listPostinstallScripts()
{
return false;
}
function initPostinstallScripts()
{
return false;
}
function setLogger(&$logger)
{
if ($logger && (!is_object($logger) || !method_exists($logger, 'log'))) {
return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
}
$this->_logger = &$logger;
}
function setPackagefile($file, $archive = false)
{
$this->_packageFile = $file;
$this->_archiveFile = $archive ? $archive : $file;
}
function getPackageFile()
{
return isset($this->_packageFile) ? $this->_packageFile : false;
}
function getPackageType()
{
return 'php';
}
function getArchiveFile()
{
return $this->_archiveFile;
}
function packageInfo($field)
{
if (!is_string($field) || empty($field) ||
!isset($this->_packageInfo[$field])) {
return false;
}
return $this->_packageInfo[$field];
}
function setDirtree($path)
{
if (!isset($this->_packageInfo['dirtree'])) {
$this->_packageInfo['dirtree'] = array();
}
$this->_packageInfo['dirtree'][$path] = true;
}
function getDirtree()
{
if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) {
return $this->_packageInfo['dirtree'];
}
return false;
}
function resetDirtree()
{
unset($this->_packageInfo['dirtree']);
}
function fromArray($pinfo)
{
$this->_incomplete = false;
$this->_packageInfo = $pinfo;
}
function isIncomplete()
{
return $this->_incomplete;
}
function getChannel()
{
return 'pear.php.net';
}
function getUri()
{
return false;
}
function getTime()
{
return false;
}
function getExtends()
{
if (isset($this->_packageInfo['extends'])) {
return $this->_packageInfo['extends'];
}
return false;
}
/**
* @return array
*/
function toArray()
{
if (!$this->validate(PEAR_VALIDATE_NORMAL)) {
return false;
}
return $this->getArray();
}
function getArray()
{
return $this->_packageInfo;
}
function getName()
{
return $this->getPackage();
}
function getPackage()
{
if (isset($this->_packageInfo['package'])) {
return $this->_packageInfo['package'];
}
return false;
}
/**
* WARNING - don't use this unless you know what you are doing
*/
function setRawPackage($package)
{
$this->_packageInfo['package'] = $package;
}
function setPackage($package)
{
$this->_packageInfo['package'] = $package;
$this->_isValid = false;
}
function getVersion()
{
if (isset($this->_packageInfo['version'])) {
return $this->_packageInfo['version'];
}
return false;
}
function setVersion($version)
{
$this->_packageInfo['version'] = $version;
$this->_isValid = false;
}
function clearMaintainers()
{
unset($this->_packageInfo['maintainers']);
}
function getMaintainers()
{
if (isset($this->_packageInfo['maintainers'])) {
return $this->_packageInfo['maintainers'];
}
return false;
}
/**
* Adds a new maintainer - no checking of duplicates is performed, use
* updatemaintainer for that purpose.
*/
function addMaintainer($role, $handle, $name, $email)
{
$this->_packageInfo['maintainers'][] =
array('handle' => $handle, 'role' => $role, 'email' => $email, 'name' => $name);
$this->_isValid = false;
}
function updateMaintainer($role, $handle, $name, $email)
{
$found = false;
if (!isset($this->_packageInfo['maintainers']) ||
!is_array($this->_packageInfo['maintainers'])) {
return $this->addMaintainer($role, $handle, $name, $email);
}
foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) {
if ($maintainer['handle'] == $handle) {
$found = $i;
break;
}
}
if ($found !== false) {
unset($this->_packageInfo['maintainers'][$found]);
$this->_packageInfo['maintainers'] =
array_values($this->_packageInfo['maintainers']);
}
$this->addMaintainer($role, $handle, $name, $email);
}
function deleteMaintainer($handle)
{
$found = false;
foreach ($this->_packageInfo['maintainers'] as $i => $maintainer) {
if ($maintainer['handle'] == $handle) {
$found = $i;
break;
}
}
if ($found !== false) {
unset($this->_packageInfo['maintainers'][$found]);
$this->_packageInfo['maintainers'] =
array_values($this->_packageInfo['maintainers']);
return true;
}
return false;
}
function getState()
{
if (isset($this->_packageInfo['release_state'])) {
return $this->_packageInfo['release_state'];
}
return false;
}
function setRawState($state)
{
$this->_packageInfo['release_state'] = $state;
}
function setState($state)
{
$this->_packageInfo['release_state'] = $state;
$this->_isValid = false;
}
function getDate()
{
if (isset($this->_packageInfo['release_date'])) {
return $this->_packageInfo['release_date'];
}
return false;
}
function setDate($date)
{
$this->_packageInfo['release_date'] = $date;
$this->_isValid = false;
}
function getLicense()
{
if (isset($this->_packageInfo['release_license'])) {
return $this->_packageInfo['release_license'];
}
return false;
}
function setLicense($date)
{
$this->_packageInfo['release_license'] = $date;
$this->_isValid = false;
}
function getSummary()
{
if (isset($this->_packageInfo['summary'])) {
return $this->_packageInfo['summary'];
}
return false;
}
function setSummary($summary)
{
$this->_packageInfo['summary'] = $summary;
$this->_isValid = false;
}
function getDescription()
{
if (isset($this->_packageInfo['description'])) {
return $this->_packageInfo['description'];
}
return false;
}
function setDescription($desc)
{
$this->_packageInfo['description'] = $desc;
$this->_isValid = false;
}
function getNotes()
{
if (isset($this->_packageInfo['release_notes'])) {
return $this->_packageInfo['release_notes'];
}
return false;
}
function setNotes($notes)
{
$this->_packageInfo['release_notes'] = $notes;
$this->_isValid = false;
}
function getDeps()
{
if (isset($this->_packageInfo['release_deps'])) {
return $this->_packageInfo['release_deps'];
}
return false;
}
/**
* Reset dependencies prior to adding new ones
*/
function clearDeps()
{
unset($this->_packageInfo['release_deps']);
}
function addPhpDep($version, $rel)
{
$this->_isValid = false;
$this->_packageInfo['release_deps'][] =
array('type' => 'php',
'rel' => $rel,
'version' => $version);
}
function addPackageDep($name, $version, $rel, $optional = 'no')
{
$this->_isValid = false;
$dep =
array('type' => 'pkg',
'name' => $name,
'rel' => $rel,
'optional' => $optional);
if ($rel != 'has' && $rel != 'not') {
$dep['version'] = $version;
}
$this->_packageInfo['release_deps'][] = $dep;
}
function addExtensionDep($name, $version, $rel, $optional = 'no')
{
$this->_isValid = false;
$this->_packageInfo['release_deps'][] =
array('type' => 'ext',
'name' => $name,
'rel' => $rel,
'version' => $version,
'optional' => $optional);
}
/**
* WARNING - do not use this function directly unless you know what you're doing
*/
function setDeps($deps)
{
$this->_packageInfo['release_deps'] = $deps;
}
function hasDeps()
{
return isset($this->_packageInfo['release_deps']) &&
count($this->_packageInfo['release_deps']);
}
function getDependencyGroup($group)
{
return false;
}
function isCompatible($pf)
{
return false;
}
function isSubpackageOf($p)
{
return $p->isSubpackage($this);
}
function isSubpackage($p)
{
return false;
}
function dependsOn($package, $channel)
{
if (strtolower($channel) != 'pear.php.net') {
return false;
}
if (!($deps = $this->getDeps())) {
return false;
}
foreach ($deps as $dep) {
if ($dep['type'] != 'pkg') {
continue;
}
if (strtolower($dep['name']) == strtolower($package)) {
return true;
}
}
return false;
}
function getConfigureOptions()
{
if (isset($this->_packageInfo['configure_options'])) {
return $this->_packageInfo['configure_options'];
}
return false;
}
function hasConfigureOptions()
{
return isset($this->_packageInfo['configure_options']) &&
count($this->_packageInfo['configure_options']);
}
function addConfigureOption($name, $prompt, $default = false)
{
$o = array('name' => $name, 'prompt' => $prompt);
if ($default !== false) {
$o['default'] = $default;
}
if (!isset($this->_packageInfo['configure_options'])) {
$this->_packageInfo['configure_options'] = array();
}
$this->_packageInfo['configure_options'][] = $o;
}
function clearConfigureOptions()
{
unset($this->_packageInfo['configure_options']);
}
function getProvides()
{
if (isset($this->_packageInfo['provides'])) {
return $this->_packageInfo['provides'];
}
return false;
}
function getProvidesExtension()
{
return false;
}
function addFile($dir, $file, $attrs)
{
$dir = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'), $dir);
if ($dir == '/' || $dir == '') {
$dir = '';
} else {
$dir .= '/';
}
$file = $dir . $file;
$file = preg_replace('![\\/]+!', '/', $file);
$this->_packageInfo['filelist'][$file] = $attrs;
}
function getInstallationFilelist()
{
return $this->getFilelist();
}
function getFilelist()
{
if (isset($this->_packageInfo['filelist'])) {
return $this->_packageInfo['filelist'];
}
return false;
}
function setFileAttribute($file, $attr, $value)
{
$this->_packageInfo['filelist'][$file][$attr] = $value;
}
function resetFilelist()
{
$this->_packageInfo['filelist'] = array();
}
function setInstalledAs($file, $path)
{
if ($path) {
return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
}
unset($this->_packageInfo['filelist'][$file]['installed_as']);
}
function installedFile($file, $atts)
{
if (isset($this->_packageInfo['filelist'][$file])) {
$this->_packageInfo['filelist'][$file] =
array_merge($this->_packageInfo['filelist'][$file], $atts);
} else {
$this->_packageInfo['filelist'][$file] = $atts;
}
}
function getChangelog()
{
if (isset($this->_packageInfo['changelog'])) {
return $this->_packageInfo['changelog'];
}
return false;
}
function getPackagexmlVersion()
{
return '1.0';
}
/**
* Wrapper to {@link PEAR_ErrorStack::getErrors()}
* @param boolean determines whether to purge the error stack after retrieving
* @return array
*/
function getValidationWarnings($purge = true)
{
return $this->_stack->getErrors($purge);
}
// }}}
/**
* Validation error. Also marks the object contents as invalid
* @param error code
* @param array error information
* @access private
*/
function _validateError($code, $params = array())
{
$this->_stack->push($code, 'error', $params, false, false, debug_backtrace());
$this->_isValid = false;
}
/**
* Validation warning. Does not mark the object contents invalid.
* @param error code
* @param array error information
* @access private
*/
function _validateWarning($code, $params = array())
{
$this->_stack->push($code, 'warning', $params, false, false, debug_backtrace());
}
/**
* @param integer error code
* @access protected
*/
function _getErrorMessage()
{
return array(
PEAR_PACKAGEFILE_ERROR_NO_NAME =>
'Missing Package Name',
PEAR_PACKAGEFILE_ERROR_NO_SUMMARY =>
'No summary found',
PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY =>
'Summary should be on one line',
PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION =>
'Missing description',
PEAR_PACKAGEFILE_ERROR_NO_LICENSE =>
'Missing license',
PEAR_PACKAGEFILE_ERROR_NO_VERSION =>
'No release version found',
PEAR_PACKAGEFILE_ERROR_NO_STATE =>
'No release state found',
PEAR_PACKAGEFILE_ERROR_NO_DATE =>
'No release date found',
PEAR_PACKAGEFILE_ERROR_NO_NOTES =>
'No release notes found',
PEAR_PACKAGEFILE_ERROR_NO_LEAD =>
'Package must have at least one lead maintainer',
PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS =>
'No maintainers found, at least one must be defined',
PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE =>
'Maintainer %index% has no handle (user ID at channel server)',
PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE =>
'Maintainer %index% has no role',
PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME =>
'Maintainer %index% has no name',
PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL =>
'Maintainer %index% has no email',
PEAR_PACKAGEFILE_ERROR_NO_DEPNAME =>
'Dependency %index% is not a php dependency, and has no name',
PEAR_PACKAGEFILE_ERROR_NO_DEPREL =>
'Dependency %index% has no relation (rel)',
PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE =>
'Dependency %index% has no type',
PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED =>
'PHP Dependency %index% has a name attribute of "%name%" which will be' .
' ignored!',
PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION =>
'Dependency %index% is not a rel="has" or rel="not" dependency, ' .
'and has no version',
PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION =>
'Dependency %index% is a type="php" dependency, ' .
'and has no version',
PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED =>
'Dependency %index% is a rel="%rel%" dependency, versioning is ignored',
PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL =>
'Dependency %index% has invalid optional value "%opt%", should be yes or no',
PEAR_PACKAGEFILE_PHP_NO_NOT =>
'Dependency %index%: php dependencies cannot use "not" rel, use "ne"' .
' to exclude specific versions',
PEAR_PACKAGEFILE_ERROR_NO_CONFNAME =>
'Configure Option %index% has no name',
PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT =>
'Configure Option %index% has no prompt',
PEAR_PACKAGEFILE_ERROR_NO_FILES =>
'No files in section of package.xml',
PEAR_PACKAGEFILE_ERROR_NO_FILEROLE =>
'File "%file%" has no role, expecting one of "%roles%"',
PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE =>
'File "%file%" has invalid role "%role%", expecting one of "%roles%"',
PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME =>
'File "%file%" cannot start with ".", cannot package or install',
PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE =>
'Parser error: invalid PHP found in file "%file%"',
PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX =>
'in %file%: %type% "%name%" not prefixed with package name "%package%"',
PEAR_PACKAGEFILE_ERROR_INVALID_FILE =>
'Parser error: invalid PHP file "%file%"',
PEAR_PACKAGEFILE_ERROR_CHANNELVAL =>
'Channel validator error: field "%field%" - %reason%',
PEAR_PACKAGEFILE_ERROR_PHP5 =>
'Error, PHP5 token encountered in %file%, analysis should be in PHP5',
PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND =>
'File "%file%" in package.xml does not exist',
PEAR_PACKAGEFILE_ERROR_NON_ISO_CHARS =>
'Package.xml contains non-ISO-8859-1 characters, and may not validate',
);
}
/**
* Validate XML package definition file.
*
* @access public
* @return boolean
*/
function validate($state = PEAR_VALIDATE_NORMAL, $nofilechecking = false)
{
if (($this->_isValid & $state) == $state) {
return true;
}
$this->_isValid = true;
$info = $this->_packageInfo;
if (empty($info['package'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NAME);
$this->_packageName = $pn = 'unknown';
} else {
$this->_packageName = $pn = $info['package'];
}
if (empty($info['summary'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_SUMMARY);
} elseif (strpos(trim($info['summary']), "\n") !== false) {
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_MULTILINE_SUMMARY,
array('summary' => $info['summary']));
}
if (empty($info['description'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DESCRIPTION);
}
if (empty($info['release_license'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LICENSE);
}
if (empty($info['version'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_VERSION);
}
if (empty($info['release_state'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_STATE);
}
if (empty($info['release_date'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DATE);
}
if (empty($info['release_notes'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_NOTES);
}
if (empty($info['maintainers'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTAINERS);
} else {
$haslead = false;
$i = 1;
foreach ($info['maintainers'] as $m) {
if (empty($m['handle'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTHANDLE,
array('index' => $i));
}
if (empty($m['role'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTROLE,
array('index' => $i, 'roles' => PEAR_Common::getUserRoles()));
} elseif ($m['role'] == 'lead') {
$haslead = true;
}
if (empty($m['name'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTNAME,
array('index' => $i));
}
if (empty($m['email'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_MAINTEMAIL,
array('index' => $i));
}
$i++;
}
if (!$haslead) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_LEAD);
}
}
if (!empty($info['release_deps'])) {
$i = 1;
foreach ($info['release_deps'] as $d) {
if (!isset($d['type']) || empty($d['type'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPTYPE,
array('index' => $i, 'types' => PEAR_Common::getDependencyTypes()));
continue;
}
if (!isset($d['rel']) || empty($d['rel'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPREL,
array('index' => $i, 'rels' => PEAR_Common::getDependencyRelations()));
continue;
}
if (!empty($d['optional'])) {
if (!in_array($d['optional'], array('yes', 'no'))) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_DEPOPTIONAL,
array('index' => $i, 'opt' => $d['optional']));
}
}
if ($d['rel'] != 'has' && $d['rel'] != 'not' && empty($d['version'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPVERSION,
array('index' => $i));
} elseif (($d['rel'] == 'has' || $d['rel'] == 'not') && !empty($d['version'])) {
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPVERSION_IGNORED,
array('index' => $i, 'rel' => $d['rel']));
}
if ($d['type'] == 'php' && !empty($d['name'])) {
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_DEPNAME_IGNORED,
array('index' => $i, 'name' => $d['name']));
} elseif ($d['type'] != 'php' && empty($d['name'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPNAME,
array('index' => $i));
}
if ($d['type'] == 'php' && empty($d['version'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_DEPPHPVERSION,
array('index' => $i));
}
if (($d['rel'] == 'not') && ($d['type'] == 'php')) {
$this->_validateError(PEAR_PACKAGEFILE_PHP_NO_NOT,
array('index' => $i));
}
$i++;
}
}
if (!empty($info['configure_options'])) {
$i = 1;
foreach ($info['configure_options'] as $c) {
if (empty($c['name'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFNAME,
array('index' => $i));
}
if (empty($c['prompt'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_CONFPROMPT,
array('index' => $i));
}
$i++;
}
}
if (empty($info['filelist'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILES);
$errors[] = 'no files';
} else {
foreach ($info['filelist'] as $file => $fa) {
if (empty($fa['role'])) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_NO_FILEROLE,
array('file' => $file, 'roles' => PEAR_Common::getFileRoles()));
continue;
} elseif (!in_array($fa['role'], PEAR_Common::getFileRoles())) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILEROLE,
array('file' => $file, 'role' => $fa['role'], 'roles' => PEAR_Common::getFileRoles()));
}
if (preg_match('~/\.\.?(/|\\z)|^\.\.?/~', str_replace('\\', '/', $file))) {
// file contains .. parent directory or . cur directory references
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
array('file' => $file));
}
if (isset($fa['install-as']) &&
preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
str_replace('\\', '/', $fa['install-as']))) {
// install-as contains .. parent directory or . cur directory references
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
array('file' => $file . ' [installed as ' . $fa['install-as'] . ']'));
}
if (isset($fa['baseinstalldir']) &&
preg_match('~/\.\.?(/|\\z)|^\.\.?/~',
str_replace('\\', '/', $fa['baseinstalldir']))) {
// install-as contains .. parent directory or . cur directory references
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_FILENAME,
array('file' => $file . ' [baseinstalldir ' . $fa['baseinstalldir'] . ']'));
}
}
}
if (isset($this->_registry) && $this->_isValid) {
$chan = $this->_registry->getChannel('pear.php.net');
if (PEAR::isError($chan)) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $chan->getMessage());
return $this->_isValid = 0;
}
$validator = $chan->getValidationObject();
$validator->setPackageFile($this);
$validator->validate($state);
$failures = $validator->getFailures();
foreach ($failures['errors'] as $error) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $error);
}
foreach ($failures['warnings'] as $warning) {
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_CHANNELVAL, $warning);
}
}
if ($this->_isValid && $state == PEAR_VALIDATE_PACKAGING && !$nofilechecking) {
if ($this->_analyzePhpFiles()) {
$this->_isValid = true;
}
}
if ($this->_isValid) {
return $this->_isValid = $state;
}
return $this->_isValid = 0;
}
function _analyzePhpFiles()
{
if (!$this->_isValid) {
return false;
}
if (!isset($this->_packageFile)) {
return false;
}
$dir_prefix = dirname($this->_packageFile);
$common = new PEAR_Common;
$log = isset($this->_logger) ? array(&$this->_logger, 'log') :
array($common, 'log');
$info = $this->getFilelist();
foreach ($info as $file => $fa) {
if (!file_exists($dir_prefix . DIRECTORY_SEPARATOR . $file)) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_FILE_NOTFOUND,
array('file' => realpath($dir_prefix) . DIRECTORY_SEPARATOR . $file));
continue;
}
if ($fa['role'] == 'php' && $dir_prefix) {
call_user_func_array($log, array(1, "Analyzing $file"));
$srcinfo = $this->_analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file);
if ($srcinfo) {
$this->_buildProvidesArray($srcinfo);
}
}
}
$this->_packageName = $pn = $this->getPackage();
$pnl = strlen($pn);
if (isset($this->_packageInfo['provides'])) {
foreach ((array) $this->_packageInfo['provides'] as $key => $what) {
if (isset($what['explicit'])) {
// skip conformance checks if the provides entry is
// specified in the package.xml file
continue;
}
extract($what);
if ($type == 'class') {
if (!strncasecmp($name, $pn, $pnl)) {
continue;
}
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX,
array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn));
} elseif ($type == 'function') {
if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) {
continue;
}
$this->_validateWarning(PEAR_PACKAGEFILE_ERROR_NO_PNAME_PREFIX,
array('file' => $file, 'type' => $type, 'name' => $name, 'package' => $pn));
}
}
}
return $this->_isValid;
}
/**
* Get the default xml generator object
*
* @return PEAR_PackageFile_Generator_v1
*/
function &getDefaultGenerator()
{
if (!class_exists('PEAR_PackageFile_Generator_v1')) {
require_once 'PEAR/PackageFile/Generator/v1.php';
}
$a = new PEAR_PackageFile_Generator_v1($this);
return $a;
}
/**
* Get the contents of a file listed within the package.xml
* @param string
* @return string
*/
function getFileContents($file)
{
if ($this->_archiveFile == $this->_packageFile) { // unpacked
$dir = dirname($this->_packageFile);
$file = $dir . DIRECTORY_SEPARATOR . $file;
$file = str_replace(array('/', '\\'),
array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file);
if (file_exists($file) && is_readable($file)) {
return implode('', file($file));
}
} else { // tgz
if (!class_exists('Archive_Tar')) {
require_once 'Archive/Tar.php';
}
$tar = new Archive_Tar($this->_archiveFile);
$tar->pushErrorHandling(PEAR_ERROR_RETURN);
if ($file != 'package.xml' && $file != 'package2.xml') {
$file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file;
}
$file = $tar->extractInString($file);
$tar->popErrorHandling();
if (PEAR::isError($file)) {
return PEAR::raiseError("Cannot locate file '$file' in archive");
}
return $file;
}
}
// {{{ analyzeSourceCode()
/**
* Analyze the source code of the given PHP file
*
* @param string Filename of the PHP file
* @return mixed
* @access private
*/
function _analyzeSourceCode($file)
{
if (!function_exists("token_get_all")) {
return false;
}
if (!defined('T_DOC_COMMENT')) {
define('T_DOC_COMMENT', T_COMMENT);
}
if (!defined('T_INTERFACE')) {
define('T_INTERFACE', -1);
}
if (!defined('T_IMPLEMENTS')) {
define('T_IMPLEMENTS', -1);
}
if (!$fp = @fopen($file, "r")) {
return false;
}
fclose($fp);
$contents = file_get_contents($file);
$tokens = token_get_all($contents);
/*
for ($i = 0; $i < sizeof($tokens); $i++) {
@list($token, $data) = $tokens[$i];
if (is_string($token)) {
var_dump($token);
} else {
print token_name($token) . ' ';
var_dump(rtrim($data));
}
}
*/
$look_for = 0;
$paren_level = 0;
$bracket_level = 0;
$brace_level = 0;
$lastphpdoc = '';
$current_class = '';
$current_interface = '';
$current_class_level = -1;
$current_function = '';
$current_function_level = -1;
$declared_classes = array();
$declared_interfaces = array();
$declared_functions = array();
$declared_methods = array();
$used_classes = array();
$used_functions = array();
$extends = array();
$implements = array();
$nodeps = array();
$inquote = false;
$interface = false;
for ($i = 0; $i < sizeof($tokens); $i++) {
if (is_array($tokens[$i])) {
list($token, $data) = $tokens[$i];
} else {
$token = $tokens[$i];
$data = '';
}
if ($inquote) {
if ($token != '"' && $token != T_END_HEREDOC) {
continue;
} else {
$inquote = false;
continue;
}
}
switch ($token) {
case T_WHITESPACE :
continue;
case ';':
if ($interface) {
$current_function = '';
$current_function_level = -1;
}
break;
case '"':
case T_START_HEREDOC:
$inquote = true;
break;
case T_CURLY_OPEN:
case T_DOLLAR_OPEN_CURLY_BRACES:
case '{': $brace_level++; continue 2;
case '}':
$brace_level--;
if ($current_class_level == $brace_level) {
$current_class = '';
$current_class_level = -1;
}
if ($current_function_level == $brace_level) {
$current_function = '';
$current_function_level = -1;
}
continue 2;
case '[': $bracket_level++; continue 2;
case ']': $bracket_level--; continue 2;
case '(': $paren_level++; continue 2;
case ')': $paren_level--; continue 2;
case T_INTERFACE:
$interface = true;
case T_CLASS:
if (($current_class_level != -1) || ($current_function_level != -1)) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE,
array('file' => $file));
return false;
}
case T_FUNCTION:
case T_NEW:
case T_EXTENDS:
case T_IMPLEMENTS:
$look_for = $token;
continue 2;
case T_STRING:
if ($look_for == T_CLASS) {
$current_class = $data;
$current_class_level = $brace_level;
$declared_classes[] = $current_class;
} elseif ($look_for == T_INTERFACE) {
$current_interface = $data;
$current_class_level = $brace_level;
$declared_interfaces[] = $current_interface;
} elseif ($look_for == T_IMPLEMENTS) {
$implements[$current_class] = $data;
} elseif ($look_for == T_EXTENDS) {
$extends[$current_class] = $data;
} elseif ($look_for == T_FUNCTION) {
if ($current_class) {
$current_function = "$current_class::$data";
$declared_methods[$current_class][] = $data;
} elseif ($current_interface) {
$current_function = "$current_interface::$data";
$declared_methods[$current_interface][] = $data;
} else {
$current_function = $data;
$declared_functions[] = $current_function;
}
$current_function_level = $brace_level;
$m = array();
} elseif ($look_for == T_NEW) {
$used_classes[$data] = true;
}
$look_for = 0;
continue 2;
case T_VARIABLE:
$look_for = 0;
continue 2;
case T_DOC_COMMENT:
case T_COMMENT:
if (preg_match('!^/\*\*\s!', $data)) {
$lastphpdoc = $data;
if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) {
$nodeps = array_merge($nodeps, $m[1]);
}
}
continue 2;
case T_DOUBLE_COLON:
if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) {
$this->_validateError(PEAR_PACKAGEFILE_ERROR_INVALID_PHPFILE,
array('file' => $file));
return false;
}
$class = $tokens[$i - 1][1];
if (strtolower($class) != 'parent') {
$used_classes[$class] = true;
}
continue 2;
}
}
return array(
"source_file" => $file,
"declared_classes" => $declared_classes,
"declared_interfaces" => $declared_interfaces,
"declared_methods" => $declared_methods,
"declared_functions" => $declared_functions,
"used_classes" => array_diff(array_keys($used_classes), $nodeps),
"inheritance" => $extends,
"implements" => $implements,
);
}
/**
* Build a "provides" array from data returned by
* analyzeSourceCode(). The format of the built array is like
* this:
*
* array(
* 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'),
* ...
* )
*
*
* @param array $srcinfo array with information about a source file
* as returned by the analyzeSourceCode() method.
*
* @return void
*
* @access private
*
*/
function _buildProvidesArray($srcinfo)
{
if (!$this->_isValid) {
return false;
}
$file = basename($srcinfo['source_file']);
$pn = $this->getPackage();
$pnl = strlen($pn);
foreach ($srcinfo['declared_classes'] as $class) {
$key = "class;$class";
if (isset($this->_packageInfo['provides'][$key])) {
continue;
}
$this->_packageInfo['provides'][$key] =
array('file'=> $file, 'type' => 'class', 'name' => $class);
if (isset($srcinfo['inheritance'][$class])) {
$this->_packageInfo['provides'][$key]['extends'] =
$srcinfo['inheritance'][$class];
}
}
foreach ($srcinfo['declared_methods'] as $class => $methods) {
foreach ($methods as $method) {
$function = "$class::$method";
$key = "function;$function";
if ($method{0} == '_' || !strcasecmp($method, $class) ||
isset($this->_packageInfo['provides'][$key])) {
continue;
}
$this->_packageInfo['provides'][$key] =
array('file'=> $file, 'type' => 'function', 'name' => $function);
}
}
foreach ($srcinfo['declared_functions'] as $function) {
$key = "function;$function";
if ($function{0} == '_' || isset($this->_packageInfo['provides'][$key])) {
continue;
}
if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) {
$warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\"";
}
$this->_packageInfo['provides'][$key] =
array('file'=> $file, 'type' => 'function', 'name' => $function);
}
}
// }}}
}
?>
PK [_=@ @ PEAR/PackageFile/Parser/v1.phpnu W+A
* @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
*/
/**
* package.xml abstraction class
*/
require_once 'PEAR/PackageFile/v1.php';
/**
* Parser for package.xml version 1.0
* @category pear
* @package PEAR
* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: @PEAR-VER@
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_PackageFile_Parser_v1
{
var $_registry;
var $_config;
var $_logger;
/**
* BC hack to allow PEAR_Common::infoFromString() to sort of
* work with the version 2.0 format - there's no filelist though
* @param PEAR_PackageFile_v2
*/
function fromV2($packagefile)
{
$info = $packagefile->getArray(true);
$ret = new PEAR_PackageFile_v1;
$ret->fromArray($info['old']);
}
function setConfig(&$c)
{
$this->_config = &$c;
$this->_registry = &$c->getRegistry();
}
function setLogger(&$l)
{
$this->_logger = &$l;
}
/**
* @param string contents of package.xml file, version 1.0
* @return bool success of parsing
*/
function &parse($data, $file, $archive = false)
{
if (!extension_loaded('xml')) {
return PEAR::raiseError('Cannot create xml parser for parsing package.xml, no xml extension');
}
$xp = xml_parser_create();
if (!$xp) {
$a = &PEAR::raiseError('Cannot create xml parser for parsing package.xml');
return $a;
}
xml_set_object($xp, $this);
xml_set_element_handler($xp, '_element_start_1_0', '_element_end_1_0');
xml_set_character_data_handler($xp, '_pkginfo_cdata_1_0');
xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false);
$this->element_stack = array();
$this->_packageInfo = array('provides' => array());
$this->current_element = false;
unset($this->dir_install);
$this->_packageInfo['filelist'] = array();
$this->filelist =& $this->_packageInfo['filelist'];
$this->dir_names = array();
$this->in_changelog = false;
$this->d_i = 0;
$this->cdata = '';
$this->_isValid = true;
if (!xml_parse($xp, $data, 1)) {
$code = xml_get_error_code($xp);
$line = xml_get_current_line_number($xp);
xml_parser_free($xp);
$a = PEAR::raiseError(sprintf("XML error: %s at line %d",
$str = xml_error_string($code), $line), 2);
return $a;
}
xml_parser_free($xp);
$pf = new PEAR_PackageFile_v1;
$pf->setConfig($this->_config);
if (isset($this->_logger)) {
$pf->setLogger($this->_logger);
}
$pf->setPackagefile($file, $archive);
$pf->fromArray($this->_packageInfo);
return $pf;
}
// {{{ _unIndent()
/**
* Unindent given string
*
* @param string $str The string that has to be unindented.
* @return string
* @access private
*/
function _unIndent($str)
{
// remove leading newlines
$str = preg_replace('/^[\r\n]+/', '', $str);
// find whitespace at the beginning of the first line
$indent_len = strspn($str, " \t");
$indent = substr($str, 0, $indent_len);
$data = '';
// remove the same amount of whitespace from following lines
foreach (explode("\n", $str) as $line) {
if (substr($line, 0, $indent_len) == $indent) {
$data .= substr($line, $indent_len) . "\n";
} elseif (trim(substr($line, 0, $indent_len))) {
$data .= ltrim($line);
}
}
return $data;
}
// Support for package DTD v1.0:
// {{{ _element_start_1_0()
/**
* XML parser callback for ending elements. Used for version 1.0
* packages.
*
* @param resource $xp XML parser resource
* @param string $name name of ending element
*
* @return void
*
* @access private
*/
function _element_start_1_0($xp, $name, $attribs)
{
array_push($this->element_stack, $name);
$this->current_element = $name;
$spos = sizeof($this->element_stack) - 2;
$this->prev_element = ($spos >= 0) ? $this->element_stack[$spos] : '';
$this->current_attributes = $attribs;
$this->cdata = '';
switch ($name) {
case 'dir':
if ($this->in_changelog) {
break;
}
if (array_key_exists('name', $attribs) && $attribs['name'] != '/') {
$attribs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
$attribs['name']);
if (strrpos($attribs['name'], '/') === strlen($attribs['name']) - 1) {
$attribs['name'] = substr($attribs['name'], 0,
strlen($attribs['name']) - 1);
}
if (strpos($attribs['name'], '/') === 0) {
$attribs['name'] = substr($attribs['name'], 1);
}
$this->dir_names[] = $attribs['name'];
}
if (isset($attribs['baseinstalldir'])) {
$this->dir_install = $attribs['baseinstalldir'];
}
if (isset($attribs['role'])) {
$this->dir_role = $attribs['role'];
}
break;
case 'file':
if ($this->in_changelog) {
break;
}
if (isset($attribs['name'])) {
$path = '';
if (count($this->dir_names)) {
foreach ($this->dir_names as $dir) {
$path .= $dir . '/';
}
}
$path .= preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
$attribs['name']);
unset($attribs['name']);
$this->current_path = $path;
$this->filelist[$path] = $attribs;
// Set the baseinstalldir only if the file don't have this attrib
if (!isset($this->filelist[$path]['baseinstalldir']) &&
isset($this->dir_install))
{
$this->filelist[$path]['baseinstalldir'] = $this->dir_install;
}
// Set the Role
if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
$this->filelist[$path]['role'] = $this->dir_role;
}
}
break;
case 'replace':
if (!$this->in_changelog) {
$this->filelist[$this->current_path]['replacements'][] = $attribs;
}
break;
case 'maintainers':
$this->_packageInfo['maintainers'] = array();
$this->m_i = 0; // maintainers array index
break;
case 'maintainer':
// compatibility check
if (!isset($this->_packageInfo['maintainers'])) {
$this->_packageInfo['maintainers'] = array();
$this->m_i = 0;
}
$this->_packageInfo['maintainers'][$this->m_i] = array();
$this->current_maintainer =& $this->_packageInfo['maintainers'][$this->m_i];
break;
case 'changelog':
$this->_packageInfo['changelog'] = array();
$this->c_i = 0; // changelog array index
$this->in_changelog = true;
break;
case 'release':
if ($this->in_changelog) {
$this->_packageInfo['changelog'][$this->c_i] = array();
$this->current_release = &$this->_packageInfo['changelog'][$this->c_i];
} else {
$this->current_release = &$this->_packageInfo;
}
break;
case 'deps':
if (!$this->in_changelog) {
$this->_packageInfo['release_deps'] = array();
}
break;
case 'dep':
// dependencies array index
if (!$this->in_changelog) {
$this->d_i++;
isset($attribs['type']) ? ($attribs['type'] = strtolower($attribs['type'])) : false;
$this->_packageInfo['release_deps'][$this->d_i] = $attribs;
}
break;
case 'configureoptions':
if (!$this->in_changelog) {
$this->_packageInfo['configure_options'] = array();
}
break;
case 'configureoption':
if (!$this->in_changelog) {
$this->_packageInfo['configure_options'][] = $attribs;
}
break;
case 'provides':
if (empty($attribs['type']) || empty($attribs['name'])) {
break;
}
$attribs['explicit'] = true;
$this->_packageInfo['provides']["$attribs[type];$attribs[name]"] = $attribs;
break;
case 'package' :
if (isset($attribs['version'])) {
$this->_packageInfo['xsdversion'] = trim($attribs['version']);
} else {
$this->_packageInfo['xsdversion'] = '1.0';
}
if (isset($attribs['packagerversion'])) {
$this->_packageInfo['packagerversion'] = $attribs['packagerversion'];
}
break;
}
}
// }}}
// {{{ _element_end_1_0()
/**
* XML parser callback for ending elements. Used for version 1.0
* packages.
*
* @param resource $xp XML parser resource
* @param string $name name of ending element
*
* @return void
*
* @access private
*/
function _element_end_1_0($xp, $name)
{
$data = trim($this->cdata);
switch ($name) {
case 'name':
switch ($this->prev_element) {
case 'package':
$this->_packageInfo['package'] = $data;
break;
case 'maintainer':
$this->current_maintainer['name'] = $data;
break;
}
break;
case 'extends' :
$this->_packageInfo['extends'] = $data;
break;
case 'summary':
$this->_packageInfo['summary'] = $data;
break;
case 'description':
$data = $this->_unIndent($this->cdata);
$this->_packageInfo['description'] = $data;
break;
case 'user':
$this->current_maintainer['handle'] = $data;
break;
case 'email':
$this->current_maintainer['email'] = $data;
break;
case 'role':
$this->current_maintainer['role'] = $data;
break;
case 'version':
if ($this->in_changelog) {
$this->current_release['version'] = $data;
} else {
$this->_packageInfo['version'] = $data;
}
break;
case 'date':
if ($this->in_changelog) {
$this->current_release['release_date'] = $data;
} else {
$this->_packageInfo['release_date'] = $data;
}
break;
case 'notes':
// try to "de-indent" release notes in case someone
// has been over-indenting their xml ;-)
// Trim only on the right side
$data = rtrim($this->_unIndent($this->cdata));
if ($this->in_changelog) {
$this->current_release['release_notes'] = $data;
} else {
$this->_packageInfo['release_notes'] = $data;
}
break;
case 'warnings':
if ($this->in_changelog) {
$this->current_release['release_warnings'] = $data;
} else {
$this->_packageInfo['release_warnings'] = $data;
}
break;
case 'state':
if ($this->in_changelog) {
$this->current_release['release_state'] = $data;
} else {
$this->_packageInfo['release_state'] = $data;
}
break;
case 'license':
if ($this->in_changelog) {
$this->current_release['release_license'] = $data;
} else {
$this->_packageInfo['release_license'] = $data;
}
break;
case 'dep':
if ($data && !$this->in_changelog) {
$this->_packageInfo['release_deps'][$this->d_i]['name'] = $data;
}
break;
case 'dir':
if ($this->in_changelog) {
break;
}
array_pop($this->dir_names);
break;
case 'file':
if ($this->in_changelog) {
break;
}
if ($data) {
$path = '';
if (count($this->dir_names)) {
foreach ($this->dir_names as $dir) {
$path .= $dir . '/';
}
}
$path .= $data;
$this->filelist[$path] = $this->current_attributes;
// Set the baseinstalldir only if the file don't have this attrib
if (!isset($this->filelist[$path]['baseinstalldir']) &&
isset($this->dir_install))
{
$this->filelist[$path]['baseinstalldir'] = $this->dir_install;
}
// Set the Role
if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) {
$this->filelist[$path]['role'] = $this->dir_role;
}
}
break;
case 'maintainer':
if (empty($this->_packageInfo['maintainers'][$this->m_i]['role'])) {
$this->_packageInfo['maintainers'][$this->m_i]['role'] = 'lead';
}
$this->m_i++;
break;
case 'release':
if ($this->in_changelog) {
$this->c_i++;
}
break;
case 'changelog':
$this->in_changelog = false;
break;
}
array_pop($this->element_stack);
$spos = sizeof($this->element_stack) - 1;
$this->current_element = ($spos > 0) ? $this->element_stack[$spos] : '';
$this->cdata = '';
}
// }}}
// {{{ _pkginfo_cdata_1_0()
/**
* XML parser callback for character data. Used for version 1.0
* packages.
*
* @param resource $xp XML parser resource
* @param string $name character data
*
* @return void
*
* @access private
*/
function _pkginfo_cdata_1_0($xp, $data)
{
if (isset($this->cdata)) {
$this->cdata .= $data;
}
}
// }}}
}
?>PK [OWH H PEAR/PackageFile/Parser/v2.phpnu W+A
* @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 xml parser class
*/
require_once 'PEAR/XMLParser.php';
require_once 'PEAR/PackageFile/v2.php';
/**
* Parser for package.xml version 2.0
* @category pear
* @package PEAR
* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: @PEAR-VER@
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_PackageFile_Parser_v2 extends PEAR_XMLParser
{
var $_config;
var $_logger;
var $_registry;
function setConfig(&$c)
{
$this->_config = &$c;
$this->_registry = &$c->getRegistry();
}
function setLogger(&$l)
{
$this->_logger = &$l;
}
/**
* Unindent given string
*
* @param string $str The string that has to be unindented.
* @return string
* @access private
*/
function _unIndent($str)
{
// remove leading newlines
$str = preg_replace('/^[\r\n]+/', '', $str);
// find whitespace at the beginning of the first line
$indent_len = strspn($str, " \t");
$indent = substr($str, 0, $indent_len);
$data = '';
// remove the same amount of whitespace from following lines
foreach (explode("\n", $str) as $line) {
if (substr($line, 0, $indent_len) == $indent) {
$data .= substr($line, $indent_len) . "\n";
} else {
$data .= $line . "\n";
}
}
return $data;
}
/**
* post-process data
*
* @param string $data
* @param string $element element name
*/
function postProcess($data, $element)
{
if ($element == 'notes') {
return trim($this->_unIndent($data));
}
return trim($data);
}
/**
* @param string
* @param string file name of the package.xml
* @param string|false name of the archive this package.xml came from, if any
* @param string class name to instantiate and return. This must be PEAR_PackageFile_v2 or
* a subclass
* @return PEAR_PackageFile_v2
*/
function parse($data, $file = null, $archive = false, $class = 'PEAR_PackageFile_v2')
{
if (PEAR::isError($err = parent::parse($data))) {
return $err;
}
$ret = new $class;
$ret->encoding = $this->encoding;
$ret->setConfig($this->_config);
if (isset($this->_logger)) {
$ret->setLogger($this->_logger);
}
$ret->fromArray($this->_unserializedData);
$ret->setPackagefile($file, $archive);
return $ret;
}
}PK [gW}5 5 PEAR/PackageFile/v2.phpnu W+A
* @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
*/
/**
* For error handling
*/
require_once 'PEAR/ErrorStack.php';
/**
* @category pear
* @package PEAR
* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_PackageFile_v2
{
/**
* Parsed package information
* @var array
* @access private
*/
var $_packageInfo = array();
/**
* path to package .tgz or false if this is a local/extracted package.xml
* @var string|false
* @access private
*/
var $_archiveFile;
/**
* path to package .xml or false if this is an abstract parsed-from-string xml
* @var string|false
* @access private
*/
var $_packageFile;
/**
* This is used by file analysis routines to log progress information
* @var PEAR_Common
* @access protected
*/
var $_logger;
/**
* This is set to the highest validation level that has been validated
*
* If the package.xml is invalid or unknown, this is set to 0. If
* normal validation has occurred, this is set to PEAR_VALIDATE_NORMAL. If
* downloading/installation validation has occurred it is set to PEAR_VALIDATE_DOWNLOADING
* or INSTALLING, and so on up to PEAR_VALIDATE_PACKAGING. This allows validation
* "caching" to occur, which is particularly important for package validation, so
* that PHP files are not validated twice
* @var int
* @access private
*/
var $_isValid = 0;
/**
* True if the filelist has been validated
* @param bool
*/
var $_filesValid = false;
/**
* @var PEAR_Registry
* @access protected
*/
var $_registry;
/**
* @var PEAR_Config
* @access protected
*/
var $_config;
/**
* Optional Dependency group requested for installation
* @var string
* @access private
*/
var $_requestedGroup = false;
/**
* @var PEAR_ErrorStack
* @access protected
*/
var $_stack;
/**
* Namespace prefix used for tasks in this package.xml - use tasks: whenever possible
*/
var $_tasksNs;
/**
* Determines whether this packagefile was initialized only with partial package info
*
* If this package file was constructed via parsing REST, it will only contain
*
* - package name
* - channel name
* - dependencies
* @var boolean
* @access private
*/
var $_incomplete = true;
/**
* @var PEAR_PackageFile_v2_Validator
*/
var $_v2Validator;
/**
* The constructor merely sets up the private error stack
*/
function __construct()
{
$this->_stack = new PEAR_ErrorStack('PEAR_PackageFile_v2', false, null);
$this->_isValid = false;
}
/**
* PHP 4 style constructor for backwards compatibility.
* Used by PEAR_PackageFileManager2
*/
public function PEAR_PackageFile_v2()
{
$this->__construct();
}
/**
* To make unit-testing easier
* @param PEAR_Frontend_*
* @param array options
* @param PEAR_Config
* @return PEAR_Downloader
* @access protected
*/
function &getPEARDownloader(&$i, $o, &$c)
{
$z = new PEAR_Downloader($i, $o, $c);
return $z;
}
/**
* To make unit-testing easier
* @param PEAR_Config
* @param array options
* @param array package name as returned from {@link PEAR_Registry::parsePackageName()}
* @param int PEAR_VALIDATE_* constant
* @return PEAR_Dependency2
* @access protected
*/
function &getPEARDependency2(&$c, $o, $p, $s = PEAR_VALIDATE_INSTALLING)
{
if (!class_exists('PEAR_Dependency2')) {
require_once 'PEAR/Dependency2.php';
}
$z = new PEAR_Dependency2($c, $o, $p, $s);
return $z;
}
function getInstalledBinary()
{
return isset($this->_packageInfo['#binarypackage']) ? $this->_packageInfo['#binarypackage'] :
false;
}
/**
* Installation of source package has failed, attempt to download and install the
* binary version of this package.
* @param PEAR_Installer
* @return array|false
*/
function installBinary(&$installer)
{
if (!OS_WINDOWS) {
$a = false;
return $a;
}
if ($this->getPackageType() == 'extsrc' || $this->getPackageType() == 'zendextsrc') {
$releasetype = $this->getPackageType() . 'release';
if (!is_array($installer->getInstallPackages())) {
$a = false;
return $a;
}
foreach ($installer->getInstallPackages() as $p) {
if ($p->isExtension($this->_packageInfo['providesextension'])) {
if ($p->getPackageType() != 'extsrc' && $p->getPackageType() != 'zendextsrc') {
$a = false;
return $a; // the user probably downloaded it separately
}
}
}
if (isset($this->_packageInfo[$releasetype]['binarypackage'])) {
$installer->log(0, 'Attempting to download binary version of extension "' .
$this->_packageInfo['providesextension'] . '"');
$params = $this->_packageInfo[$releasetype]['binarypackage'];
if (!is_array($params) || !isset($params[0])) {
$params = array($params);
}
if (isset($this->_packageInfo['channel'])) {
foreach ($params as $i => $param) {
$params[$i] = array('channel' => $this->_packageInfo['channel'],
'package' => $param, 'version' => $this->getVersion());
}
}
$dl = &$this->getPEARDownloader($installer->ui, $installer->getOptions(),
$installer->config);
$verbose = $dl->config->get('verbose');
$dl->config->set('verbose', -1);
foreach ($params as $param) {
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$ret = $dl->download(array($param));
PEAR::popErrorHandling();
if (is_array($ret) && count($ret)) {
break;
}
}
$dl->config->set('verbose', $verbose);
if (is_array($ret)) {
if (count($ret) == 1) {
$pf = $ret[0]->getPackageFile();
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$err = $installer->install($ret[0]);
PEAR::popErrorHandling();
if (is_array($err)) {
$this->_packageInfo['#binarypackage'] = $ret[0]->getPackage();
// "install" self, so all dependencies will work transparently
$this->_registry->addPackage2($this);
$installer->log(0, 'Download and install of binary extension "' .
$this->_registry->parsedPackageNameToString(
array('channel' => $pf->getChannel(),
'package' => $pf->getPackage()), true) . '" successful');
$a = array($ret[0], $err);
return $a;
}
$installer->log(0, 'Download and install of binary extension "' .
$this->_registry->parsedPackageNameToString(
array('channel' => $pf->getChannel(),
'package' => $pf->getPackage()), true) . '" failed');
}
}
}
}
$a = false;
return $a;
}
/**
* @return string|false Extension name
*/
function getProvidesExtension()
{
if (in_array($this->getPackageType(),
array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
if (isset($this->_packageInfo['providesextension'])) {
return $this->_packageInfo['providesextension'];
}
}
return false;
}
/**
* @param string Extension name
* @return bool
*/
function isExtension($extension)
{
if (in_array($this->getPackageType(),
array('extsrc', 'extbin', 'zendextsrc', 'zendextbin'))) {
return $this->_packageInfo['providesextension'] == $extension;
}
return false;
}
/**
* Tests whether every part of the package.xml 1.0 is represented in
* this package.xml 2.0
* @param PEAR_PackageFile_v1
* @return bool
*/
function isEquivalent($pf1)
{
if (!$pf1) {
return true;
}
if ($this->getPackageType() == 'bundle') {
return false;
}
$this->_stack->getErrors(true);
if (!$pf1->validate(PEAR_VALIDATE_NORMAL)) {
return false;
}
$pass = true;
if ($pf1->getPackage() != $this->getPackage()) {
$this->_differentPackage($pf1->getPackage());
$pass = false;
}
if ($pf1->getVersion() != $this->getVersion()) {
$this->_differentVersion($pf1->getVersion());
$pass = false;
}
if (trim($pf1->getSummary()) != $this->getSummary()) {
$this->_differentSummary($pf1->getSummary());
$pass = false;
}
if (preg_replace('/\s+/', '', $pf1->getDescription()) !=
preg_replace('/\s+/', '', $this->getDescription())) {
$this->_differentDescription($pf1->getDescription());
$pass = false;
}
if ($pf1->getState() != $this->getState()) {
$this->_differentState($pf1->getState());
$pass = false;
}
if (!strstr(preg_replace('/\s+/', '', $this->getNotes()),
preg_replace('/\s+/', '', $pf1->getNotes()))) {
$this->_differentNotes($pf1->getNotes());
$pass = false;
}
$mymaintainers = $this->getMaintainers();
$yourmaintainers = $pf1->getMaintainers();
for ($i1 = 0; $i1 < count($yourmaintainers); $i1++) {
$reset = false;
for ($i2 = 0; $i2 < count($mymaintainers); $i2++) {
if ($mymaintainers[$i2]['handle'] == $yourmaintainers[$i1]['handle']) {
if ($mymaintainers[$i2]['role'] != $yourmaintainers[$i1]['role']) {
$this->_differentRole($mymaintainers[$i2]['handle'],
$yourmaintainers[$i1]['role'], $mymaintainers[$i2]['role']);
$pass = false;
}
if ($mymaintainers[$i2]['email'] != $yourmaintainers[$i1]['email']) {
$this->_differentEmail($mymaintainers[$i2]['handle'],
$yourmaintainers[$i1]['email'], $mymaintainers[$i2]['email']);
$pass = false;
}
if ($mymaintainers[$i2]['name'] != $yourmaintainers[$i1]['name']) {
$this->_differentName($mymaintainers[$i2]['handle'],
$yourmaintainers[$i1]['name'], $mymaintainers[$i2]['name']);
$pass = false;
}
unset($mymaintainers[$i2]);
$mymaintainers = array_values($mymaintainers);
unset($yourmaintainers[$i1]);
$yourmaintainers = array_values($yourmaintainers);
$reset = true;
break;
}
}
if ($reset) {
$i1 = -1;
}
}
$this->_unmatchedMaintainers($mymaintainers, $yourmaintainers);
$filelist = $this->getFilelist();
foreach ($pf1->getFilelist() as $file => $atts) {
if (!isset($filelist[$file])) {
$this->_missingFile($file);
$pass = false;
}
}
return $pass;
}
function _differentPackage($package)
{
$this->_stack->push(__FUNCTION__, 'error', array('package' => $package,
'self' => $this->getPackage()),
'package.xml 1.0 package "%package%" does not match "%self%"');
}
function _differentVersion($version)
{
$this->_stack->push(__FUNCTION__, 'error', array('version' => $version,
'self' => $this->getVersion()),
'package.xml 1.0 version "%version%" does not match "%self%"');
}
function _differentState($state)
{
$this->_stack->push(__FUNCTION__, 'error', array('state' => $state,
'self' => $this->getState()),
'package.xml 1.0 state "%state%" does not match "%self%"');
}
function _differentRole($handle, $role, $selfrole)
{
$this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
'role' => $role, 'self' => $selfrole),
'package.xml 1.0 maintainer "%handle%" role "%role%" does not match "%self%"');
}
function _differentEmail($handle, $email, $selfemail)
{
$this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
'email' => $email, 'self' => $selfemail),
'package.xml 1.0 maintainer "%handle%" email "%email%" does not match "%self%"');
}
function _differentName($handle, $name, $selfname)
{
$this->_stack->push(__FUNCTION__, 'error', array('handle' => $handle,
'name' => $name, 'self' => $selfname),
'package.xml 1.0 maintainer "%handle%" name "%name%" does not match "%self%"');
}
function _unmatchedMaintainers($my, $yours)
{
if ($my) {
array_walk($my, create_function('&$i, $k', '$i = $i["handle"];'));
$this->_stack->push(__FUNCTION__, 'error', array('handles' => $my),
'package.xml 2.0 has unmatched extra maintainers "%handles%"');
}
if ($yours) {
array_walk($yours, create_function('&$i, $k', '$i = $i["handle"];'));
$this->_stack->push(__FUNCTION__, 'error', array('handles' => $yours),
'package.xml 1.0 has unmatched extra maintainers "%handles%"');
}
}
function _differentNotes($notes)
{
$truncnotes = strlen($notes) < 25 ? $notes : substr($notes, 0, 24) . '...';
$truncmynotes = strlen($this->getNotes()) < 25 ? $this->getNotes() :
substr($this->getNotes(), 0, 24) . '...';
$this->_stack->push(__FUNCTION__, 'error', array('notes' => $truncnotes,
'self' => $truncmynotes),
'package.xml 1.0 release notes "%notes%" do not match "%self%"');
}
function _differentSummary($summary)
{
$truncsummary = strlen($summary) < 25 ? $summary : substr($summary, 0, 24) . '...';
$truncmysummary = strlen($this->getsummary()) < 25 ? $this->getSummary() :
substr($this->getsummary(), 0, 24) . '...';
$this->_stack->push(__FUNCTION__, 'error', array('summary' => $truncsummary,
'self' => $truncmysummary),
'package.xml 1.0 summary "%summary%" does not match "%self%"');
}
function _differentDescription($description)
{
$truncdescription = trim(strlen($description) < 25 ? $description : substr($description, 0, 24) . '...');
$truncmydescription = trim(strlen($this->getDescription()) < 25 ? $this->getDescription() :
substr($this->getdescription(), 0, 24) . '...');
$this->_stack->push(__FUNCTION__, 'error', array('description' => $truncdescription,
'self' => $truncmydescription),
'package.xml 1.0 description "%description%" does not match "%self%"');
}
function _missingFile($file)
{
$this->_stack->push(__FUNCTION__, 'error', array('file' => $file),
'package.xml 1.0 file "%file%" is not present in ');
}
/**
* WARNING - do not use this function unless you know what you're doing
*/
function setRawState($state)
{
if (!isset($this->_packageInfo['stability'])) {
$this->_packageInfo['stability'] = array();
}
$this->_packageInfo['stability']['release'] = $state;
}
/**
* WARNING - do not use this function unless you know what you're doing
*/
function setRawCompatible($compatible)
{
$this->_packageInfo['compatible'] = $compatible;
}
/**
* WARNING - do not use this function unless you know what you're doing
*/
function setRawPackage($package)
{
$this->_packageInfo['name'] = $package;
}
/**
* WARNING - do not use this function unless you know what you're doing
*/
function setRawChannel($channel)
{
$this->_packageInfo['channel'] = $channel;
}
function setRequestedGroup($group)
{
$this->_requestedGroup = $group;
}
function getRequestedGroup()
{
if (isset($this->_requestedGroup)) {
return $this->_requestedGroup;
}
return false;
}
/**
* For saving in the registry.
*
* Set the last version that was installed
* @param string
*/
function setLastInstalledVersion($version)
{
$this->_packageInfo['_lastversion'] = $version;
}
/**
* @return string|false
*/
function getLastInstalledVersion()
{
if (isset($this->_packageInfo['_lastversion'])) {
return $this->_packageInfo['_lastversion'];
}
return false;
}
/**
* Determines whether this package.xml has post-install scripts or not
* @return array|false
*/
function listPostinstallScripts()
{
$filelist = $this->getFilelist();
$contents = $this->getContents();
$contents = $contents['dir']['file'];
if (!is_array($contents) || !isset($contents[0])) {
$contents = array($contents);
}
$taskfiles = array();
foreach ($contents as $file) {
$atts = $file['attribs'];
unset($file['attribs']);
if (count($file)) {
$taskfiles[$atts['name']] = $file;
}
}
$common = new PEAR_Common;
$common->debug = $this->_config->get('verbose');
$this->_scripts = array();
$ret = array();
foreach ($taskfiles as $name => $tasks) {
if (!isset($filelist[$name])) {
// ignored files will not be in the filelist
continue;
}
$atts = $filelist[$name];
foreach ($tasks as $tag => $raw) {
$task = $this->getTask($tag);
$task = new $task($this->_config, $common, PEAR_TASK_INSTALL);
if ($task->isScript()) {
$ret[] = $filelist[$name]['installed_as'];
}
}
}
if (count($ret)) {
return $ret;
}
return false;
}
/**
* Initialize post-install scripts for running
*
* This method can be used to detect post-install scripts, as the return value
* indicates whether any exist
* @return bool
*/
function initPostinstallScripts()
{
$filelist = $this->getFilelist();
$contents = $this->getContents();
$contents = $contents['dir']['file'];
if (!is_array($contents) || !isset($contents[0])) {
$contents = array($contents);
}
$taskfiles = array();
foreach ($contents as $file) {
$atts = $file['attribs'];
unset($file['attribs']);
if (count($file)) {
$taskfiles[$atts['name']] = $file;
}
}
$common = new PEAR_Common;
$common->debug = $this->_config->get('verbose');
$this->_scripts = array();
foreach ($taskfiles as $name => $tasks) {
if (!isset($filelist[$name])) {
// file was not installed due to installconditions
continue;
}
$atts = $filelist[$name];
foreach ($tasks as $tag => $raw) {
$taskname = $this->getTask($tag);
$task = new $taskname($this->_config, $common, PEAR_TASK_INSTALL);
if (!$task->isScript()) {
continue; // scripts are only handled after installation
}
$lastversion = isset($this->_packageInfo['_lastversion']) ?
$this->_packageInfo['_lastversion'] : null;
$task->init($raw, $atts, $lastversion);
$res = $task->startSession($this, $atts['installed_as'], null);
if (!$res) {
continue; // skip this file
}
if (PEAR::isError($res)) {
return $res;
}
$this->_scripts[] = $task;
}
}
if (count($this->_scripts)) {
return true;
}
return false;
}
function runPostinstallScripts()
{
if ($this->initPostinstallScripts()) {
$ui = &PEAR_Frontend::singleton();
if ($ui) {
$ui->runPostinstallScripts($this->_scripts, $this);
}
}
}
/**
* Convert a recursive set of and tags into a single tag with
* tags.
*/
function flattenFilelist()
{
if (isset($this->_packageInfo['bundle'])) {
return;
}
$filelist = array();
if (isset($this->_packageInfo['contents']['dir']['dir'])) {
$this->_getFlattenedFilelist($filelist, $this->_packageInfo['contents']['dir']);
if (!isset($filelist[1])) {
$filelist = $filelist[0];
}
$this->_packageInfo['contents']['dir']['file'] = $filelist;
unset($this->_packageInfo['contents']['dir']['dir']);
} else {
// else already flattened but check for baseinstalldir propagation
if (isset($this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'])) {
if (isset($this->_packageInfo['contents']['dir']['file'][0])) {
foreach ($this->_packageInfo['contents']['dir']['file'] as $i => $file) {
if (isset($file['attribs']['baseinstalldir'])) {
continue;
}
$this->_packageInfo['contents']['dir']['file'][$i]['attribs']['baseinstalldir']
= $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
}
} else {
if (!isset($this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir'])) {
$this->_packageInfo['contents']['dir']['file']['attribs']['baseinstalldir']
= $this->_packageInfo['contents']['dir']['attribs']['baseinstalldir'];
}
}
}
}
}
/**
* @param array the final flattened file list
* @param array the current directory being processed
* @param string|false any recursively inherited baeinstalldir attribute
* @param string private recursion variable
* @return array
* @access protected
*/
function _getFlattenedFilelist(&$files, $dir, $baseinstall = false, $path = '')
{
if (isset($dir['attribs']) && isset($dir['attribs']['baseinstalldir'])) {
$baseinstall = $dir['attribs']['baseinstalldir'];
}
if (isset($dir['dir'])) {
if (!isset($dir['dir'][0])) {
$dir['dir'] = array($dir['dir']);
}
foreach ($dir['dir'] as $subdir) {
if (!isset($subdir['attribs']) || !isset($subdir['attribs']['name'])) {
$name = '*unknown*';
} else {
$name = $subdir['attribs']['name'];
}
$newpath = empty($path) ? $name :
$path . '/' . $name;
$this->_getFlattenedFilelist($files, $subdir,
$baseinstall, $newpath);
}
}
if (isset($dir['file'])) {
if (!isset($dir['file'][0])) {
$dir['file'] = array($dir['file']);
}
foreach ($dir['file'] as $file) {
$attrs = $file['attribs'];
$name = $attrs['name'];
if ($baseinstall && !isset($attrs['baseinstalldir'])) {
$attrs['baseinstalldir'] = $baseinstall;
}
$attrs['name'] = empty($path) ? $name : $path . '/' . $name;
$attrs['name'] = preg_replace(array('!\\\\+!', '!/+!'), array('/', '/'),
$attrs['name']);
$file['attribs'] = $attrs;
$files[] = $file;
}
}
}
function setConfig(&$config)
{
$this->_config = &$config;
$this->_registry = &$config->getRegistry();
}
function setLogger(&$logger)
{
if (!is_object($logger) || !method_exists($logger, 'log')) {
return PEAR::raiseError('Logger must be compatible with PEAR_Common::log');
}
$this->_logger = &$logger;
}
/**
* WARNING - do not use this function directly unless you know what you're doing
*/
function setDeps($deps)
{
$this->_packageInfo['dependencies'] = $deps;
}
/**
* WARNING - do not use this function directly unless you know what you're doing
*/
function setCompatible($compat)
{
$this->_packageInfo['compatible'] = $compat;
}
function setPackagefile($file, $archive = false)
{
$this->_packageFile = $file;
$this->_archiveFile = $archive ? $archive : $file;
}
/**
* Wrapper to {@link PEAR_ErrorStack::getErrors()}
* @param boolean determines whether to purge the error stack after retrieving
* @return array
*/
function getValidationWarnings($purge = true)
{
return $this->_stack->getErrors($purge);
}
function getPackageFile()
{
return $this->_packageFile;
}
function getArchiveFile()
{
return $this->_archiveFile;
}
/**
* Directly set the array that defines this packagefile
*
* WARNING: no validation. This should only be performed by internal methods
* inside PEAR or by inputting an array saved from an existing PEAR_PackageFile_v2
* @param array
*/
function fromArray($pinfo)
{
unset($pinfo['old']);
unset($pinfo['xsdversion']);
// If the changelog isn't an array then it was passed in as an empty tag
if (isset($pinfo['changelog']) && !is_array($pinfo['changelog'])) {
unset($pinfo['changelog']);
}
$this->_incomplete = false;
$this->_packageInfo = $pinfo;
}
function isIncomplete()
{
return $this->_incomplete;
}
/**
* @return array
*/
function toArray($forreg = false)
{
if (!$this->validate(PEAR_VALIDATE_NORMAL)) {
return false;
}
return $this->getArray($forreg);
}
function getArray($forReg = false)
{
if ($forReg) {
$arr = $this->_packageInfo;
$arr['old'] = array();
$arr['old']['version'] = $this->getVersion();
$arr['old']['release_date'] = $this->getDate();
$arr['old']['release_state'] = $this->getState();
$arr['old']['release_license'] = $this->getLicense();
$arr['old']['release_notes'] = $this->getNotes();
$arr['old']['release_deps'] = $this->getDeps();
$arr['old']['maintainers'] = $this->getMaintainers();
$arr['xsdversion'] = '2.0';
return $arr;
} else {
$info = $this->_packageInfo;
unset($info['dirtree']);
if (isset($info['_lastversion'])) {
unset($info['_lastversion']);
}
if (isset($info['#binarypackage'])) {
unset($info['#binarypackage']);
}
return $info;
}
}
function packageInfo($field)
{
$arr = $this->getArray(true);
if ($field == 'state') {
return $arr['stability']['release'];
}
if ($field == 'api-version') {
return $arr['version']['api'];
}
if ($field == 'api-state') {
return $arr['stability']['api'];
}
if (isset($arr['old'][$field])) {
if (!is_string($arr['old'][$field])) {
return null;
}
return $arr['old'][$field];
}
if (isset($arr[$field])) {
if (!is_string($arr[$field])) {
return null;
}
return $arr[$field];
}
return null;
}
function getName()
{
return $this->getPackage();
}
function getPackage()
{
if (isset($this->_packageInfo['name'])) {
return $this->_packageInfo['name'];
}
return false;
}
function getChannel()
{
if (isset($this->_packageInfo['uri'])) {
return '__uri';
}
if (isset($this->_packageInfo['channel'])) {
return strtolower($this->_packageInfo['channel']);
}
return false;
}
function getUri()
{
if (isset($this->_packageInfo['uri'])) {
return $this->_packageInfo['uri'];
}
return false;
}
function getExtends()
{
if (isset($this->_packageInfo['extends'])) {
return $this->_packageInfo['extends'];
}
return false;
}
function getSummary()
{
if (isset($this->_packageInfo['summary'])) {
return $this->_packageInfo['summary'];
}
return false;
}
function getDescription()
{
if (isset($this->_packageInfo['description'])) {
return $this->_packageInfo['description'];
}
return false;
}
function getMaintainers($raw = false)
{
if (!isset($this->_packageInfo['lead'])) {
return false;
}
if ($raw) {
$ret = array('lead' => $this->_packageInfo['lead']);
(isset($this->_packageInfo['developer'])) ?
$ret['developer'] = $this->_packageInfo['developer'] :null;
(isset($this->_packageInfo['contributor'])) ?
$ret['contributor'] = $this->_packageInfo['contributor'] :null;
(isset($this->_packageInfo['helper'])) ?
$ret['helper'] = $this->_packageInfo['helper'] :null;
return $ret;
} else {
$ret = array();
$leads = isset($this->_packageInfo['lead'][0]) ? $this->_packageInfo['lead'] :
array($this->_packageInfo['lead']);
foreach ($leads as $lead) {
$s = $lead;
$s['handle'] = $s['user'];
unset($s['user']);
$s['role'] = 'lead';
$ret[] = $s;
}
if (isset($this->_packageInfo['developer'])) {
$leads = isset($this->_packageInfo['developer'][0]) ?
$this->_packageInfo['developer'] :
array($this->_packageInfo['developer']);
foreach ($leads as $maintainer) {
$s = $maintainer;
$s['handle'] = $s['user'];
unset($s['user']);
$s['role'] = 'developer';
$ret[] = $s;
}
}
if (isset($this->_packageInfo['contributor'])) {
$leads = isset($this->_packageInfo['contributor'][0]) ?
$this->_packageInfo['contributor'] :
array($this->_packageInfo['contributor']);
foreach ($leads as $maintainer) {
$s = $maintainer;
$s['handle'] = $s['user'];
unset($s['user']);
$s['role'] = 'contributor';
$ret[] = $s;
}
}
if (isset($this->_packageInfo['helper'])) {
$leads = isset($this->_packageInfo['helper'][0]) ?
$this->_packageInfo['helper'] :
array($this->_packageInfo['helper']);
foreach ($leads as $maintainer) {
$s = $maintainer;
$s['handle'] = $s['user'];
unset($s['user']);
$s['role'] = 'helper';
$ret[] = $s;
}
}
return $ret;
}
return false;
}
function getLeads()
{
if (isset($this->_packageInfo['lead'])) {
return $this->_packageInfo['lead'];
}
return false;
}
function getDevelopers()
{
if (isset($this->_packageInfo['developer'])) {
return $this->_packageInfo['developer'];
}
return false;
}
function getContributors()
{
if (isset($this->_packageInfo['contributor'])) {
return $this->_packageInfo['contributor'];
}
return false;
}
function getHelpers()
{
if (isset($this->_packageInfo['helper'])) {
return $this->_packageInfo['helper'];
}
return false;
}
function setDate($date)
{
if (!isset($this->_packageInfo['date'])) {
// ensure that the extends tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('time', 'version',
'stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
'zendextbinrelease', 'bundle', 'changelog'), array(), 'date');
}
$this->_packageInfo['date'] = $date;
$this->_isValid = 0;
}
function setTime($time)
{
$this->_isValid = 0;
if (!isset($this->_packageInfo['time'])) {
// ensure that the time tag is set up in the right location
$this->_packageInfo = $this->_insertBefore($this->_packageInfo,
array('version',
'stability', 'license', 'notes', 'contents', 'compatible',
'dependencies', 'providesextension', 'srcpackage', 'srcuri',
'phprelease', 'extsrcrelease', 'extbinrelease', 'zendextsrcrelease',
'zendextbinrelease', 'bundle', 'changelog'), $time, 'time');
}
$this->_packageInfo['time'] = $time;
}
function getDate()
{
if (isset($this->_packageInfo['date'])) {
return $this->_packageInfo['date'];
}
return false;
}
function getTime()
{
if (isset($this->_packageInfo['time'])) {
return $this->_packageInfo['time'];
}
return false;
}
/**
* @param package|api version category to return
*/
function getVersion($key = 'release')
{
if (isset($this->_packageInfo['version'][$key])) {
return $this->_packageInfo['version'][$key];
}
return false;
}
function getStability()
{
if (isset($this->_packageInfo['stability'])) {
return $this->_packageInfo['stability'];
}
return false;
}
function getState($key = 'release')
{
if (isset($this->_packageInfo['stability'][$key])) {
return $this->_packageInfo['stability'][$key];
}
return false;
}
function getLicense($raw = false)
{
if (isset($this->_packageInfo['license'])) {
if ($raw) {
return $this->_packageInfo['license'];
}
if (is_array($this->_packageInfo['license'])) {
return $this->_packageInfo['license']['_content'];
} else {
return $this->_packageInfo['license'];
}
}
return false;
}
function getLicenseLocation()
{
if (!isset($this->_packageInfo['license']) || !is_array($this->_packageInfo['license'])) {
return false;
}
return $this->_packageInfo['license']['attribs'];
}
function getNotes()
{
if (isset($this->_packageInfo['notes'])) {
return $this->_packageInfo['notes'];
}
return false;
}
/**
* Return the tag contents, if any
* @return array|false
*/
function getUsesrole()
{
if (isset($this->_packageInfo['usesrole'])) {
return $this->_packageInfo['usesrole'];
}
return false;
}
/**
* Return the tag contents, if any
* @return array|false
*/
function getUsestask()
{
if (isset($this->_packageInfo['usestask'])) {
return $this->_packageInfo['usestask'];
}
return false;
}
/**
* This should only be used to retrieve filenames and install attributes
*/
function getFilelist($preserve = false)
{
if (isset($this->_packageInfo['filelist']) && !$preserve) {
return $this->_packageInfo['filelist'];
}
$this->flattenFilelist();
if ($contents = $this->getContents()) {
$ret = array();
if (!isset($contents['dir'])) {
return false;
}
if (!isset($contents['dir']['file'][0])) {
$contents['dir']['file'] = array($contents['dir']['file']);
}
foreach ($contents['dir']['file'] as $file) {
if (!isset($file['attribs']['name'])) {
continue;
}
$name = $file['attribs']['name'];
if (!$preserve) {
$file = $file['attribs'];
}
$ret[$name] = $file;
}
if (!$preserve) {
$this->_packageInfo['filelist'] = $ret;
}
return $ret;
}
return false;
}
/**
* Return configure options array, if any
*
* @return array|false
*/
function getConfigureOptions()
{
if ($this->getPackageType() != 'extsrc' && $this->getPackageType() != 'zendextsrc') {
return false;
}
$releases = $this->getReleases();
if (isset($releases[0])) {
$releases = $releases[0];
}
if (isset($releases['configureoption'])) {
if (!isset($releases['configureoption'][0])) {
$releases['configureoption'] = array($releases['configureoption']);
}
for ($i = 0; $i < count($releases['configureoption']); $i++) {
$releases['configureoption'][$i] = $releases['configureoption'][$i]['attribs'];
}
return $releases['configureoption'];
}
return false;
}
/**
* This is only used at install-time, after all serialization
* is over.
*/
function resetFilelist()
{
$this->_packageInfo['filelist'] = array();
}
/**
* Retrieve a list of files that should be installed on this computer
* @return array
*/
function getInstallationFilelist($forfilecheck = false)
{
$contents = $this->getFilelist(true);
if (isset($contents['dir']['attribs']['baseinstalldir'])) {
$base = $contents['dir']['attribs']['baseinstalldir'];
}
if (isset($this->_packageInfo['bundle'])) {
return PEAR::raiseError(
'Exception: bundles should be handled in download code only');
}
$release = $this->getReleases();
if ($release) {
if (!isset($release[0])) {
if (!isset($release['installconditions']) && !isset($release['filelist'])) {
if ($forfilecheck) {
return $this->getFilelist();
}
return $contents;
}
$release = array($release);
}
$depchecker = &$this->getPEARDependency2($this->_config, array(),
array('channel' => $this->getChannel(), 'package' => $this->getPackage()),
PEAR_VALIDATE_INSTALLING);
foreach ($release as $instance) {
if (isset($instance['installconditions'])) {
$installconditions = $instance['installconditions'];
if (is_array($installconditions)) {
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
foreach ($installconditions as $type => $conditions) {
if (!isset($conditions[0])) {
$conditions = array($conditions);
}
foreach ($conditions as $condition) {
$ret = $depchecker->{"validate{$type}Dependency"}($condition);
if (PEAR::isError($ret)) {
PEAR::popErrorHandling();
continue 3; // skip this release
}
}
}
PEAR::popErrorHandling();
}
}
// this is the release to use
if (isset($instance['filelist'])) {
// ignore files
if (isset($instance['filelist']['ignore'])) {
$ignore = isset($instance['filelist']['ignore'][0]) ?
$instance['filelist']['ignore'] :
array($instance['filelist']['ignore']);
foreach ($ignore as $ig) {
unset ($contents[$ig['attribs']['name']]);
}
}
// install files as this name
if (isset($instance['filelist']['install'])) {
$installas = isset($instance['filelist']['install'][0]) ?
$instance['filelist']['install'] :
array($instance['filelist']['install']);
foreach ($installas as $as) {
$contents[$as['attribs']['name']]['attribs']['install-as'] =
$as['attribs']['as'];
}
}
}
if ($forfilecheck) {
foreach ($contents as $file => $attrs) {
$contents[$file] = $attrs['attribs'];
}
}
return $contents;
}
} else { // simple release - no installconditions or install-as
if ($forfilecheck) {
return $this->getFilelist();
}
return $contents;
}
// no releases matched
return PEAR::raiseError('No releases in package.xml matched the existing operating ' .
'system, extensions installed, or architecture, cannot install');
}
/**
* This is only used at install-time, after all serialization
* is over.
* @param string file name
* @param string installed path
*/
function setInstalledAs($file, $path)
{
if ($path) {
return $this->_packageInfo['filelist'][$file]['installed_as'] = $path;
}
unset($this->_packageInfo['filelist'][$file]['installed_as']);
}
function getInstalledLocation($file)
{
if (isset($this->_packageInfo['filelist'][$file]['installed_as'])) {
return $this->_packageInfo['filelist'][$file]['installed_as'];
}
return false;
}
/**
* This is only used at install-time, after all serialization
* is over.
*/
function installedFile($file, $atts)
{
if (isset($this->_packageInfo['filelist'][$file])) {
$this->_packageInfo['filelist'][$file] =
array_merge($this->_packageInfo['filelist'][$file], $atts['attribs']);
} else {
$this->_packageInfo['filelist'][$file] = $atts['attribs'];
}
}
/**
* Retrieve the contents tag
*/
function getContents()
{
if (isset($this->_packageInfo['contents'])) {
return $this->_packageInfo['contents'];
}
return false;
}
/**
* @param string full path to file
* @param string attribute name
* @param string attribute value
* @param int risky but fast - use this to choose a file based on its position in the list
* of files. Index is zero-based like PHP arrays.
* @return bool success of operation
*/
function setFileAttribute($filename, $attr, $value, $index = false)
{
$this->_isValid = 0;
if (in_array($attr, array('role', 'name', 'baseinstalldir'))) {
$this->_filesValid = false;
}
if ($index !== false &&
isset($this->_packageInfo['contents']['dir']['file'][$index]['attribs'])) {
$this->_packageInfo['contents']['dir']['file'][$index]['attribs'][$attr] = $value;
return true;
}
if (!isset($this->_packageInfo['contents']['dir']['file'])) {
return false;
}
$files = $this->_packageInfo['contents']['dir']['file'];
if (!isset($files[0])) {
$files = array($files);
$ind = false;
} else {
$ind = true;
}
foreach ($files as $i => $file) {
if (isset($file['attribs'])) {
if ($file['attribs']['name'] == $filename) {
if ($ind) {
$this->_packageInfo['contents']['dir']['file'][$i]['attribs'][$attr] = $value;
} else {
$this->_packageInfo['contents']['dir']['file']['attribs'][$attr] = $value;
}
return true;
}
}
}
return false;
}
function setDirtree($path)
{
if (!isset($this->_packageInfo['dirtree'])) {
$this->_packageInfo['dirtree'] = array();
}
$this->_packageInfo['dirtree'][$path] = true;
}
function getDirtree()
{
if (isset($this->_packageInfo['dirtree']) && count($this->_packageInfo['dirtree'])) {
return $this->_packageInfo['dirtree'];
}
return false;
}
function resetDirtree()
{
unset($this->_packageInfo['dirtree']);
}
/**
* Determines whether this package claims it is compatible with the version of
* the package that has a recommended version dependency
* @param PEAR_PackageFile_v2|PEAR_PackageFile_v1|PEAR_Downloader_Package
* @return boolean
*/
function isCompatible($pf)
{
if (!isset($this->_packageInfo['compatible'])) {
return false;
}
if (!isset($this->_packageInfo['channel'])) {
return false;
}
$me = $pf->getVersion();
$compatible = $this->_packageInfo['compatible'];
if (!isset($compatible[0])) {
$compatible = array($compatible);
}
$found = false;
foreach ($compatible as $info) {
if (strtolower($info['name']) == strtolower($pf->getPackage())) {
if (strtolower($info['channel']) == strtolower($pf->getChannel())) {
$found = true;
break;
}
}
}
if (!$found) {
return false;
}
if (isset($info['exclude'])) {
if (!isset($info['exclude'][0])) {
$info['exclude'] = array($info['exclude']);
}
foreach ($info['exclude'] as $exclude) {
if (version_compare($me, $exclude, '==')) {
return false;
}
}
}
if (version_compare($me, $info['min'], '>=') && version_compare($me, $info['max'], '<=')) {
return true;
}
return false;
}
/**
* @return array|false
*/
function getCompatible()
{
if (isset($this->_packageInfo['compatible'])) {
return $this->_packageInfo['compatible'];
}
return false;
}
function getDependencies()
{
if (isset($this->_packageInfo['dependencies'])) {
return $this->_packageInfo['dependencies'];
}
return false;
}
function isSubpackageOf($p)
{
return $p->isSubpackage($this);
}
/**
* Determines whether the passed in package is a subpackage of this package.
*
* No version checking is done, only name verification.
* @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
* @return bool
*/
function isSubpackage($p)
{
$sub = array();
if (isset($this->_packageInfo['dependencies']['required']['subpackage'])) {
$sub = $this->_packageInfo['dependencies']['required']['subpackage'];
if (!isset($sub[0])) {
$sub = array($sub);
}
}
if (isset($this->_packageInfo['dependencies']['optional']['subpackage'])) {
$sub1 = $this->_packageInfo['dependencies']['optional']['subpackage'];
if (!isset($sub1[0])) {
$sub1 = array($sub1);
}
$sub = array_merge($sub, $sub1);
}
if (isset($this->_packageInfo['dependencies']['group'])) {
$group = $this->_packageInfo['dependencies']['group'];
if (!isset($group[0])) {
$group = array($group);
}
foreach ($group as $deps) {
if (isset($deps['subpackage'])) {
$sub2 = $deps['subpackage'];
if (!isset($sub2[0])) {
$sub2 = array($sub2);
}
$sub = array_merge($sub, $sub2);
}
}
}
foreach ($sub as $dep) {
if (strtolower($dep['name']) == strtolower($p->getPackage())) {
if (isset($dep['channel'])) {
if (strtolower($dep['channel']) == strtolower($p->getChannel())) {
return true;
}
} else {
if ($dep['uri'] == $p->getURI()) {
return true;
}
}
}
}
return false;
}
function dependsOn($package, $channel)
{
if (!($deps = $this->getDependencies())) {
return false;
}
foreach (array('package', 'subpackage') as $type) {
foreach (array('required', 'optional') as $needed) {
if (isset($deps[$needed][$type])) {
if (!isset($deps[$needed][$type][0])) {
$deps[$needed][$type] = array($deps[$needed][$type]);
}
foreach ($deps[$needed][$type] as $dep) {
$depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
if (strtolower($dep['name']) == strtolower($package) &&
$depchannel == $channel) {
return true;
}
}
}
}
if (isset($deps['group'])) {
if (!isset($deps['group'][0])) {
$dep['group'] = array($deps['group']);
}
foreach ($deps['group'] as $group) {
if (isset($group[$type])) {
if (!is_array($group[$type])) {
$group[$type] = array($group[$type]);
}
foreach ($group[$type] as $dep) {
$depchannel = isset($dep['channel']) ? $dep['channel'] : '__uri';
if (strtolower($dep['name']) == strtolower($package) &&
$depchannel == $channel) {
return true;
}
}
}
}
}
}
return false;
}
/**
* Get the contents of a dependency group
* @param string
* @return array|false
*/
function getDependencyGroup($name)
{
$name = strtolower($name);
if (!isset($this->_packageInfo['dependencies']['group'])) {
return false;
}
$groups = $this->_packageInfo['dependencies']['group'];
if (!isset($groups[0])) {
$groups = array($groups);
}
foreach ($groups as $group) {
if (strtolower($group['attribs']['name']) == $name) {
return $group;
}
}
return false;
}
/**
* Retrieve a partial package.xml 1.0 representation of dependencies
*
* a very limited representation of dependencies is returned by this method.
* The tag for excluding certain versions of a dependency is
* completely ignored. In addition, dependency groups are ignored, with the
* assumption that all dependencies in dependency groups are also listed in
* the optional group that work with all dependency groups
* @param boolean return package.xml 2.0 tag
* @return array|false
*/
function getDeps($raw = false, $nopearinstaller = false)
{
if (isset($this->_packageInfo['dependencies'])) {
if ($raw) {
return $this->_packageInfo['dependencies'];
}
$ret = array();
$map = array(
'php' => 'php',
'package' => 'pkg',
'subpackage' => 'pkg',
'extension' => 'ext',
'os' => 'os',
'pearinstaller' => 'pkg',
);
foreach (array('required', 'optional') as $type) {
$optional = ($type == 'optional') ? 'yes' : 'no';
if (!isset($this->_packageInfo['dependencies'][$type])
|| empty($this->_packageInfo['dependencies'][$type])) {
continue;
}
foreach ($this->_packageInfo['dependencies'][$type] as $dtype => $deps) {
if ($dtype == 'pearinstaller' && $nopearinstaller) {
continue;
}
if ((is_array($deps) && !isset($deps[0])) || !is_array($deps)) {
$deps = array($deps);
}
foreach ($deps as $dep) {
if (!isset($map[$dtype])) {
// no support for arch type
continue;
}
if ($dtype == 'pearinstaller') {
$dep['name'] = 'PEAR';
$dep['channel'] = 'pear.php.net';
}
$s = array('type' => $map[$dtype]);
if (isset($dep['channel'])) {
$s['channel'] = $dep['channel'];
}
if (isset($dep['uri'])) {
$s['uri'] = $dep['uri'];
}
if (isset($dep['name'])) {
$s['name'] = $dep['name'];
}
if (isset($dep['conflicts'])) {
$s['rel'] = 'not';
} else {
if (!isset($dep['min']) &&
!isset($dep['max'])) {
$s['rel'] = 'has';
$s['optional'] = $optional;
} elseif (isset($dep['min']) &&
isset($dep['max'])) {
$s['rel'] = 'ge';
$s1 = $s;
$s1['rel'] = 'le';
$s['version'] = $dep['min'];
$s1['version'] = $dep['max'];
if (isset($dep['channel'])) {
$s1['channel'] = $dep['channel'];
}
if ($dtype != 'php') {
$s['name'] = $dep['name'];
$s1['name'] = $dep['name'];
}
$s['optional'] = $optional;
$s1['optional'] = $optional;
$ret[] = $s1;
} elseif (isset($dep['min'])) {
if (isset($dep['exclude']) &&
$dep['exclude'] == $dep['min']) {
$s['rel'] = 'gt';
} else {
$s['rel'] = 'ge';
}
$s['version'] = $dep['min'];
$s['optional'] = $optional;
if ($dtype != 'php') {
$s['name'] = $dep['name'];
}
} elseif (isset($dep['max'])) {
if (isset($dep['exclude']) &&
$dep['exclude'] == $dep['max']) {
$s['rel'] = 'lt';
} else {
$s['rel'] = 'le';
}
$s['version'] = $dep['max'];
$s['optional'] = $optional;
if ($dtype != 'php') {
$s['name'] = $dep['name'];
}
}
}
$ret[] = $s;
}
}
}
if (count($ret)) {
return $ret;
}
}
return false;
}
/**
* @return php|extsrc|extbin|zendextsrc|zendextbin|bundle|false
*/
function getPackageType()
{
if (isset($this->_packageInfo['phprelease'])) {
return 'php';
}
if (isset($this->_packageInfo['extsrcrelease'])) {
return 'extsrc';
}
if (isset($this->_packageInfo['extbinrelease'])) {
return 'extbin';
}
if (isset($this->_packageInfo['zendextsrcrelease'])) {
return 'zendextsrc';
}
if (isset($this->_packageInfo['zendextbinrelease'])) {
return 'zendextbin';
}
if (isset($this->_packageInfo['bundle'])) {
return 'bundle';
}
return false;
}
/**
* @return array|false
*/
function getReleases()
{
$type = $this->getPackageType();
if ($type != 'bundle') {
$type .= 'release';
}
if ($this->getPackageType() && isset($this->_packageInfo[$type])) {
return $this->_packageInfo[$type];
}
return false;
}
/**
* @return array
*/
function getChangelog()
{
if (isset($this->_packageInfo['changelog'])) {
return $this->_packageInfo['changelog'];
}
return false;
}
function hasDeps()
{
return isset($this->_packageInfo['dependencies']);
}
function getPackagexmlVersion()
{
if (isset($this->_packageInfo['zendextsrcrelease'])) {
return '2.1';
}
if (isset($this->_packageInfo['zendextbinrelease'])) {
return '2.1';
}
return '2.0';
}
/**
* @return array|false
*/
function getSourcePackage()
{
if (isset($this->_packageInfo['extbinrelease']) ||
isset($this->_packageInfo['zendextbinrelease'])) {
return array('channel' => $this->_packageInfo['srcchannel'],
'package' => $this->_packageInfo['srcpackage']);
}
return false;
}
function getBundledPackages()
{
if (isset($this->_packageInfo['bundle'])) {
return $this->_packageInfo['contents']['bundledpackage'];
}
return false;
}
function getLastModified()
{
if (isset($this->_packageInfo['_lastmodified'])) {
return $this->_packageInfo['_lastmodified'];
}
return false;
}
/**
* Get the contents of a file listed within the package.xml
* @param string
* @return string
*/
function getFileContents($file)
{
if ($this->_archiveFile == $this->_packageFile) { // unpacked
$dir = dirname($this->_packageFile);
$file = $dir . DIRECTORY_SEPARATOR . $file;
$file = str_replace(array('/', '\\'),
array(DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), $file);
if (file_exists($file) && is_readable($file)) {
return implode('', file($file));
}
} else { // tgz
$tar = new Archive_Tar($this->_archiveFile);
$tar->pushErrorHandling(PEAR_ERROR_RETURN);
if ($file != 'package.xml' && $file != 'package2.xml') {
$file = $this->getPackage() . '-' . $this->getVersion() . '/' . $file;
}
$file = $tar->extractInString($file);
$tar->popErrorHandling();
if (PEAR::isError($file)) {
return PEAR::raiseError("Cannot locate file '$file' in archive");
}
return $file;
}
}
function &getRW()
{
if (!class_exists('PEAR_PackageFile_v2_rw')) {
require_once 'PEAR/PackageFile/v2/rw.php';
}
$a = new PEAR_PackageFile_v2_rw;
foreach (get_object_vars($this) as $name => $unused) {
if (!isset($this->$name)) {
continue;
}
if ($name == '_config' || $name == '_logger'|| $name == '_registry' ||
$name == '_stack') {
$a->$name = &$this->$name;
} else {
$a->$name = $this->$name;
}
}
return $a;
}
function &getDefaultGenerator()
{
if (!class_exists('PEAR_PackageFile_Generator_v2')) {
require_once 'PEAR/PackageFile/Generator/v2.php';
}
$a = new PEAR_PackageFile_Generator_v2($this);
return $a;
}
function analyzeSourceCode($file, $string = false)
{
if (!isset($this->_v2Validator) ||
!is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
if (!class_exists('PEAR_PackageFile_v2_Validator')) {
require_once 'PEAR/PackageFile/v2/Validator.php';
}
$this->_v2Validator = new PEAR_PackageFile_v2_Validator;
}
return $this->_v2Validator->analyzeSourceCode($file, $string);
}
function validate($state = PEAR_VALIDATE_NORMAL)
{
if (!isset($this->_packageInfo) || !is_array($this->_packageInfo)) {
return false;
}
if (!isset($this->_v2Validator) ||
!is_a($this->_v2Validator, 'PEAR_PackageFile_v2_Validator')) {
if (!class_exists('PEAR_PackageFile_v2_Validator')) {
require_once 'PEAR/PackageFile/v2/Validator.php';
}
$this->_v2Validator = new PEAR_PackageFile_v2_Validator;
}
if (isset($this->_packageInfo['xsdversion'])) {
unset($this->_packageInfo['xsdversion']);
}
return $this->_v2Validator->validate($this, $state);
}
function getTasksNs()
{
if (!isset($this->_tasksNs)) {
if (isset($this->_packageInfo['attribs'])) {
foreach ($this->_packageInfo['attribs'] as $name => $value) {
if ($value == 'http://pear.php.net/dtd/tasks-1.0') {
$this->_tasksNs = str_replace('xmlns:', '', $name);
break;
}
}
}
}
return $this->_tasksNs;
}
/**
* Determine whether a task name is a valid task. Custom tasks may be defined
* using subdirectories by putting a "-" in the name, as in
*
* Note that this method will auto-load the task class file and test for the existence
* of the name with "-" replaced by "_" as in PEAR/Task/mycustom/task.php makes class
* PEAR_Task_mycustom_task
* @param string
* @return boolean
*/
function getTask($task)
{
$this->getTasksNs();
// transform all '-' to '/' and 'tasks:' to '' so tasks:replace becomes replace
$task = str_replace(array($this->_tasksNs . ':', '-'), array('', ' '), $task);
$taskfile = str_replace(' ', '/', ucwords($task));
$task = str_replace(array(' ', '/'), '_', ucwords($task));
if (class_exists("PEAR_Task_$task")) {
return "PEAR_Task_$task";
}
$fp = @fopen("PEAR/Task/$taskfile.php", 'r', true);
if ($fp) {
fclose($fp);
require_once "PEAR/Task/$taskfile.php";
return "PEAR_Task_$task";
}
return false;
}
/**
* Key-friendly array_splice
* @param tagname to splice a value in before
* @param mixed the value to splice in
* @param string the new tag name
*/
function _ksplice($array, $key, $value, $newkey)
{
$offset = array_search($key, array_keys($array));
$after = array_slice($array, $offset);
$before = array_slice($array, 0, $offset);
$before[$newkey] = $value;
return array_merge($before, $after);
}
/**
* @param array a list of possible keys, in the order they may occur
* @param mixed contents of the new package.xml tag
* @param string tag name
* @access private
*/
function _insertBefore($array, $keys, $contents, $newkey)
{
foreach ($keys as $key) {
if (isset($array[$key])) {
return $array = $this->_ksplice($array, $key, $contents, $newkey);
}
}
$array[$newkey] = $contents;
return $array;
}
/**
* @param subsection of {@link $_packageInfo}
* @param array|string tag contents
* @param array format:
*
* array(
* tagname => array(list of tag names that follow this one),
* childtagname => array(list of child tag names that follow this one),
* )
*
*
* This allows construction of nested tags
* @access private
*/
function _mergeTag($manip, $contents, $order)
{
if (count($order)) {
foreach ($order as $tag => $curorder) {
if (!isset($manip[$tag])) {
// ensure that the tag is set up
$manip = $this->_insertBefore($manip, $curorder, array(), $tag);
}
if (count($order) > 1) {
$manip[$tag] = $this->_mergeTag($manip[$tag], $contents, array_slice($order, 1));
return $manip;
}
}
} else {
return $manip;
}
if (is_array($manip[$tag]) && !empty($manip[$tag]) && isset($manip[$tag][0])) {
$manip[$tag][] = $contents;
} else {
if (!count($manip[$tag])) {
$manip[$tag] = $contents;
} else {
$manip[$tag] = array($manip[$tag]);
$manip[$tag][] = $contents;
}
}
return $manip;
}
}
?>
PK [R՚ PEAR/XMLParser.phpnu W+A
* @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
* @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.4
* @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 [V PEAR/Frontend.phpnu W+A
* @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
*/
/**
* Include error handling
*/
//require_once 'PEAR.php';
/**
* Which user interface class is being used.
* @var string class name
*/
$GLOBALS['_PEAR_FRONTEND_CLASS'] = 'PEAR_Frontend_CLI';
/**
* Instance of $_PEAR_Command_uiclass.
* @var object
*/
$GLOBALS['_PEAR_FRONTEND_SINGLETON'] = null;
/**
* Singleton-based frontend for PEAR user input/output
*
* @category pear
* @package PEAR
* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Frontend extends PEAR
{
/**
* Retrieve the frontend object
* @return PEAR_Frontend_CLI|PEAR_Frontend_Web|PEAR_Frontend_Gtk
*/
public static function &singleton($type = null)
{
if ($type === null) {
if (!isset($GLOBALS['_PEAR_FRONTEND_SINGLETON'])) {
$a = false;
return $a;
}
return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
}
$a = PEAR_Frontend::setFrontendClass($type);
return $a;
}
/**
* Set the frontend class that will be used by calls to {@link singleton()}
*
* Frontends are expected to conform to the PEAR naming standard of
* _ => DIRECTORY_SEPARATOR (PEAR_Frontend_CLI is in PEAR/Frontend/CLI.php)
* @param string $uiclass full class name
* @return PEAR_Frontend
*/
public static function &setFrontendClass($uiclass)
{
if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) &&
is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], $uiclass)) {
return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
}
if (!class_exists($uiclass)) {
$file = str_replace('_', '/', $uiclass) . '.php';
if (PEAR_Frontend::isIncludeable($file)) {
include_once $file;
}
}
if (class_exists($uiclass)) {
$obj = new $uiclass;
// quick test to see if this class implements a few of the most
// important frontend methods
if (is_a($obj, 'PEAR_Frontend')) {
$GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$obj;
$GLOBALS['_PEAR_FRONTEND_CLASS'] = $uiclass;
return $obj;
}
$err = PEAR::raiseError("not a frontend class: $uiclass");
return $err;
}
$err = PEAR::raiseError("no such class: $uiclass");
return $err;
}
/**
* Set the frontend class that will be used by calls to {@link singleton()}
*
* Frontends are expected to be a descendant of PEAR_Frontend
* @param PEAR_Frontend
* @return PEAR_Frontend
*/
public static function &setFrontendObject($uiobject)
{
if (is_object($GLOBALS['_PEAR_FRONTEND_SINGLETON']) &&
is_a($GLOBALS['_PEAR_FRONTEND_SINGLETON'], get_class($uiobject))) {
return $GLOBALS['_PEAR_FRONTEND_SINGLETON'];
}
if (!is_a($uiobject, 'PEAR_Frontend')) {
$err = PEAR::raiseError('not a valid frontend class: (' .
get_class($uiobject) . ')');
return $err;
}
$GLOBALS['_PEAR_FRONTEND_SINGLETON'] = &$uiobject;
$GLOBALS['_PEAR_FRONTEND_CLASS'] = get_class($uiobject);
return $uiobject;
}
/**
* @param string $path relative or absolute include path
* @return boolean
*/
public static function isIncludeable($path)
{
if (file_exists($path) && is_readable($path)) {
return true;
}
$fp = @fopen($path, 'r', true);
if ($fp) {
fclose($fp);
return true;
}
return false;
}
/**
* @param PEAR_Config
*/
function setConfig(&$config)
{
}
/**
* This can be overridden to allow session-based temporary file management
*
* By default, all files are deleted at the end of a session. The web installer
* needs to be able to sustain a list over many sessions in order to support
* user interaction with install scripts
*/
function addTempFile($file)
{
$GLOBALS['_PEAR_Common_tempfiles'][] = $file;
}
/**
* Log an action
*
* @param string $msg the message to log
* @param boolean $append_crlf
* @return boolean true
* @abstract
*/
function log($msg, $append_crlf = true)
{
}
/**
* Run a post-installation script
*
* @param array $scripts array of post-install scripts
* @abstract
*/
function runPostinstallScripts(&$scripts)
{
}
/**
* Display human-friendly output formatted depending on the
* $command parameter.
*
* This should be able to handle basic output data with no command
* @param mixed $data data structure containing the information to display
* @param string $command command from which this method was called
* @abstract
*/
function outputData($data, $command = '_default')
{
}
/**
* Display a modal form dialog and return the given input
*
* A frontend that requires multiple requests to retrieve and process
* data must take these needs into account, and implement the request
* handling code.
* @param string $command command from which this method was called
* @param array $prompts associative array. keys are the input field names
* and values are the description
* @param array $types array of input field types (text, password,
* etc.) keys have to be the same like in $prompts
* @param array $defaults array of default values. again keys have
* to be the same like in $prompts. Do not depend
* on a default value being set.
* @return array input sent by the user
* @abstract
*/
function userDialog($command, $prompts, $types = array(), $defaults = array())
{
}
}PK [x̀+ + PEAR/REST/11.phpnu W+A
* @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.3
*/
/**
* For downloading REST xml/txt files
*/
require_once 'PEAR/REST.php';
/**
* Implement REST 1.1
*
* @category pear
* @package PEAR
* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.3
*/
class PEAR_REST_11
{
/**
* @var PEAR_REST
*/
var $_rest;
function __construct($config, $options = array())
{
$this->_rest = new PEAR_REST($config, $options);
}
function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false)
{
$categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel);
if (PEAR::isError($categorylist)) {
return $categorylist;
}
$ret = array();
if (!is_array($categorylist['c']) || !isset($categorylist['c'][0])) {
$categorylist['c'] = array($categorylist['c']);
}
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
foreach ($categorylist['c'] as $progress => $category) {
$category = $category['_content'];
$packagesinfo = $this->_rest->retrieveData($base .
'c/' . urlencode($category) . '/packagesinfo.xml', false, false, $channel);
if (PEAR::isError($packagesinfo)) {
continue;
}
if (!is_array($packagesinfo) || !isset($packagesinfo['pi'])) {
continue;
}
if (!is_array($packagesinfo['pi']) || !isset($packagesinfo['pi'][0])) {
$packagesinfo['pi'] = array($packagesinfo['pi']);
}
foreach ($packagesinfo['pi'] as $packageinfo) {
if (empty($packageinfo)) {
continue;
}
$info = $packageinfo['p'];
$package = $info['n'];
$releases = isset($packageinfo['a']) ? $packageinfo['a'] : false;
unset($latest);
unset($unstable);
unset($stable);
unset($state);
if ($releases) {
if (!isset($releases['r'][0])) {
$releases['r'] = array($releases['r']);
}
foreach ($releases['r'] as $release) {
if (!isset($latest)) {
if ($dostable && $release['s'] == 'stable') {
$latest = $release['v'];
$state = 'stable';
}
if (!$dostable) {
$latest = $release['v'];
$state = $release['s'];
}
}
if (!isset($stable) && $release['s'] == 'stable') {
$stable = $release['v'];
if (!isset($unstable)) {
$unstable = $stable;
}
}
if (!isset($unstable) && $release['s'] != 'stable') {
$unstable = $release['v'];
$state = $release['s'];
}
if (isset($latest) && !isset($state)) {
$state = $release['s'];
}
if (isset($latest) && isset($stable) && isset($unstable)) {
break;
}
}
}
if ($basic) { // remote-list command
if (!isset($latest)) {
$latest = false;
}
if ($dostable) {
// $state is not set if there are no releases
if (isset($state) && $state == 'stable') {
$ret[$package] = array('stable' => $latest);
} else {
$ret[$package] = array('stable' => '-n/a-');
}
} else {
$ret[$package] = array('stable' => $latest);
}
continue;
}
// list-all command
if (!isset($unstable)) {
$unstable = false;
$state = 'stable';
if (isset($stable)) {
$latest = $unstable = $stable;
}
} else {
$latest = $unstable;
}
if (!isset($latest)) {
$latest = false;
}
$deps = array();
if ($latest && isset($packageinfo['deps'])) {
if (!is_array($packageinfo['deps']) ||
!isset($packageinfo['deps'][0])
) {
$packageinfo['deps'] = array($packageinfo['deps']);
}
$d = false;
foreach ($packageinfo['deps'] as $dep) {
if ($dep['v'] == $latest) {
$d = unserialize($dep['d']);
}
}
if ($d) {
if (isset($d['required'])) {
if (!class_exists('PEAR_PackageFile_v2')) {
require_once 'PEAR/PackageFile/v2.php';
}
if (!isset($pf)) {
$pf = new PEAR_PackageFile_v2;
}
$pf->setDeps($d);
$tdeps = $pf->getDeps();
} else {
$tdeps = $d;
}
foreach ($tdeps as $dep) {
if ($dep['type'] !== 'pkg') {
continue;
}
$deps[] = $dep;
}
}
}
$info = array(
'stable' => $latest,
'summary' => $info['s'],
'description' => $info['d'],
'deps' => $deps,
'category' => $info['ca']['_content'],
'unstable' => $unstable,
'state' => $state
);
$ret[$package] = $info;
}
}
PEAR::popErrorHandling();
return $ret;
}
/**
* List all categories of a REST server
*
* @param string $base base URL of the server
* @return array of categorynames
*/
function listCategories($base, $channel = false)
{
$categorylist = $this->_rest->retrieveData($base . 'c/categories.xml', false, false, $channel);
if (PEAR::isError($categorylist)) {
return $categorylist;
}
if (!is_array($categorylist) || !isset($categorylist['c'])) {
return array();
}
if (isset($categorylist['c']['_content'])) {
// only 1 category
$categorylist['c'] = array($categorylist['c']);
}
return $categorylist['c'];
}
/**
* List packages in a category of a REST server
*
* @param string $base base URL of the server
* @param string $category name of the category
* @param boolean $info also download full package info
* @return array of packagenames
*/
function listCategory($base, $category, $info = false, $channel = false)
{
if ($info == false) {
$url = '%s'.'c/%s/packages.xml';
} else {
$url = '%s'.'c/%s/packagesinfo.xml';
}
$url = sprintf($url,
$base,
urlencode($category));
// gives '404 Not Found' error when category doesn't exist
$packagelist = $this->_rest->retrieveData($url, false, false, $channel);
if (PEAR::isError($packagelist)) {
return $packagelist;
}
if (!is_array($packagelist)) {
return array();
}
if ($info == false) {
if (!isset($packagelist['p'])) {
return array();
}
if (!is_array($packagelist['p']) ||
!isset($packagelist['p'][0])) { // only 1 pkg
$packagelist = array($packagelist['p']);
} else {
$packagelist = $packagelist['p'];
}
return $packagelist;
}
// info == true
if (!isset($packagelist['pi'])) {
return array();
}
if (!is_array($packagelist['pi']) ||
!isset($packagelist['pi'][0])) { // only 1 pkg
$packagelist_pre = array($packagelist['pi']);
} else {
$packagelist_pre = $packagelist['pi'];
}
$packagelist = array();
foreach ($packagelist_pre as $i => $item) {
// compatibility with r/.xml
if (isset($item['a']['r'][0])) {
// multiple releases
$item['p']['v'] = $item['a']['r'][0]['v'];
$item['p']['st'] = $item['a']['r'][0]['s'];
} elseif (isset($item['a'])) {
// first and only release
$item['p']['v'] = $item['a']['r']['v'];
$item['p']['st'] = $item['a']['r']['s'];
}
$packagelist[$i] = array('attribs' => $item['p']['r'],
'_content' => $item['p']['n'],
'info' => $item['p']);
}
return $packagelist;
}
/**
* Return an array containing all of the states that are more stable than
* or equal to the passed in state
*
* @param string Release state
* @param boolean Determines whether to include $state in the list
* @return false|array False if $state is not a valid release state
*/
function betterStates($state, $include = false)
{
static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
$i = array_search($state, $states);
if ($i === false) {
return false;
}
if ($include) {
$i--;
}
return array_slice($states, $i + 1);
}
}
?>
PK [e; ; PEAR/REST/13.phpnu W+A
* @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.0a12
*/
/**
* For downloading REST xml/txt files
*/
require_once 'PEAR/REST.php';
require_once 'PEAR/REST/10.php';
/**
* Implement REST 1.3
*
* @category pear
* @package PEAR
* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a12
*/
class PEAR_REST_13 extends PEAR_REST_10
{
/**
* Retrieve information about a remote package to be downloaded from a REST server
*
* This is smart enough to resolve the minimum PHP version dependency prior to download
* @param string $base The uri to prepend to all REST calls
* @param array $packageinfo an array of format:
*
* array(
* 'package' => 'packagename',
* 'channel' => 'channelname',
* ['state' => 'alpha' (or valid state),]
* -or-
* ['version' => '1.whatever']
*
* @param string $prefstate Current preferred_state config variable value
* @param bool $installed the installed version of this package to compare against
* @return array|false|PEAR_Error see {@link _returnDownloadURL()}
*/
function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false)
{
$states = $this->betterStates($prefstate, true);
if (!$states) {
return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
}
$channel = $packageinfo['channel'];
$package = $packageinfo['package'];
$state = isset($packageinfo['state']) ? $packageinfo['state'] : null;
$version = isset($packageinfo['version']) ? $packageinfo['version'] : null;
$restFile = $base . 'r/' . strtolower($package) . '/allreleases2.xml';
$info = $this->_rest->retrieveData($restFile, false, false, $channel);
if (PEAR::isError($info)) {
return PEAR::raiseError('No releases available for package "' .
$channel . '/' . $package . '"');
}
if (!isset($info['r'])) {
return false;
}
$release = $found = false;
if (!is_array($info['r']) || !isset($info['r'][0])) {
$info['r'] = array($info['r']);
}
$skippedphp = false;
foreach ($info['r'] as $release) {
if (!isset($this->_rest->_options['force']) && ($installed &&
version_compare($release['v'], $installed, '<'))) {
continue;
}
if (isset($state)) {
// try our preferred state first
if ($release['s'] == $state) {
if (!isset($version) && version_compare($release['m'], phpversion(), '>')) {
// skip releases that require a PHP version newer than our PHP version
$skippedphp = $release;
continue;
}
$found = true;
break;
}
// see if there is something newer and more stable
// bug #7221
if (in_array($release['s'], $this->betterStates($state), true)) {
if (!isset($version) && version_compare($release['m'], phpversion(), '>')) {
// skip releases that require a PHP version newer than our PHP version
$skippedphp = $release;
continue;
}
$found = true;
break;
}
} elseif (isset($version)) {
if ($release['v'] == $version) {
if (!isset($this->_rest->_options['force']) &&
!isset($version) &&
version_compare($release['m'], phpversion(), '>')) {
// skip releases that require a PHP version newer than our PHP version
$skippedphp = $release;
continue;
}
$found = true;
break;
}
} else {
if (in_array($release['s'], $states)) {
if (version_compare($release['m'], phpversion(), '>')) {
// skip releases that require a PHP version newer than our PHP version
$skippedphp = $release;
continue;
}
$found = true;
break;
}
}
}
if (!$found && $skippedphp) {
$found = null;
}
return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel);
}
function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage,
$prefstate = 'stable', $installed = false, $channel = false)
{
$states = $this->betterStates($prefstate, true);
if (!$states) {
return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
}
$channel = $dependency['channel'];
$package = $dependency['name'];
$state = isset($dependency['state']) ? $dependency['state'] : null;
$version = isset($dependency['version']) ? $dependency['version'] : null;
$restFile = $base . 'r/' . strtolower($package) .'/allreleases2.xml';
$info = $this->_rest->retrieveData($restFile, false, false, $channel);
if (PEAR::isError($info)) {
return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package']
. '" dependency "' . $channel . '/' . $package . '" has no releases');
}
if (!is_array($info) || !isset($info['r'])) {
return false;
}
$exclude = array();
$min = $max = $recommended = false;
if ($xsdversion == '1.0') {
$pinfo['package'] = $dependency['name'];
$pinfo['channel'] = 'pear.php.net'; // this is always true - don't change this
switch ($dependency['rel']) {
case 'ge' :
$min = $dependency['version'];
break;
case 'gt' :
$min = $dependency['version'];
$exclude = array($dependency['version']);
break;
case 'eq' :
$recommended = $dependency['version'];
break;
case 'lt' :
$max = $dependency['version'];
$exclude = array($dependency['version']);
break;
case 'le' :
$max = $dependency['version'];
break;
case 'ne' :
$exclude = array($dependency['version']);
break;
}
} else {
$pinfo['package'] = $dependency['name'];
$min = isset($dependency['min']) ? $dependency['min'] : false;
$max = isset($dependency['max']) ? $dependency['max'] : false;
$recommended = isset($dependency['recommended']) ?
$dependency['recommended'] : false;
if (isset($dependency['exclude'])) {
if (!isset($dependency['exclude'][0])) {
$exclude = array($dependency['exclude']);
}
}
}
$skippedphp = $found = $release = false;
if (!is_array($info['r']) || !isset($info['r'][0])) {
$info['r'] = array($info['r']);
}
foreach ($info['r'] as $release) {
if (!isset($this->_rest->_options['force']) && ($installed &&
version_compare($release['v'], $installed, '<'))) {
continue;
}
if (in_array($release['v'], $exclude)) { // skip excluded versions
continue;
}
// allow newer releases to say "I'm OK with the dependent package"
if ($xsdversion == '2.0' && isset($release['co'])) {
if (!is_array($release['co']) || !isset($release['co'][0])) {
$release['co'] = array($release['co']);
}
foreach ($release['co'] as $entry) {
if (isset($entry['x']) && !is_array($entry['x'])) {
$entry['x'] = array($entry['x']);
} elseif (!isset($entry['x'])) {
$entry['x'] = array();
}
if ($entry['c'] == $deppackage['channel'] &&
strtolower($entry['p']) == strtolower($deppackage['package']) &&
version_compare($deppackage['version'], $entry['min'], '>=') &&
version_compare($deppackage['version'], $entry['max'], '<=') &&
!in_array($release['v'], $entry['x'])) {
if (version_compare($release['m'], phpversion(), '>')) {
// skip dependency releases that require a PHP version
// newer than our PHP version
$skippedphp = $release;
continue;
}
$recommended = $release['v'];
break;
}
}
}
if ($recommended) {
if ($release['v'] != $recommended) { // if we want a specific
// version, then skip all others
continue;
}
if (!in_array($release['s'], $states)) {
// the stability is too low, but we must return the
// recommended version if possible
return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel);
}
}
if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions
continue;
}
if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions
continue;
}
if ($installed && version_compare($release['v'], $installed, '<')) {
continue;
}
if (in_array($release['s'], $states)) { // if in the preferred state...
if (version_compare($release['m'], phpversion(), '>')) {
// skip dependency releases that require a PHP version
// newer than our PHP version
$skippedphp = $release;
continue;
}
$found = true; // ... then use it
break;
}
}
if (!$found && $skippedphp) {
$found = null;
}
return $this->_returnDownloadURL($base, $package, $release, $info, $found, $skippedphp, $channel);
}
/**
* List package upgrades but take the PHP version into account.
*/
function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg)
{
$packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
if (PEAR::isError($packagelist)) {
return $packagelist;
}
$ret = array();
if (!is_array($packagelist) || !isset($packagelist['p'])) {
return $ret;
}
if (!is_array($packagelist['p'])) {
$packagelist['p'] = array($packagelist['p']);
}
foreach ($packagelist['p'] as $package) {
if (!isset($installed[strtolower($package)])) {
continue;
}
$inst_version = $reg->packageInfo($package, 'version', $channel);
$inst_state = $reg->packageInfo($package, 'release_state', $channel);
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
'/allreleases2.xml', false, false, $channel);
PEAR::popErrorHandling();
if (PEAR::isError($info)) {
continue; // no remote releases
}
if (!isset($info['r'])) {
continue;
}
$release = $found = false;
if (!is_array($info['r']) || !isset($info['r'][0])) {
$info['r'] = array($info['r']);
}
// $info['r'] is sorted by version number
usort($info['r'], array($this, '_sortReleasesByVersionNumber'));
foreach ($info['r'] as $release) {
if ($inst_version && version_compare($release['v'], $inst_version, '<=')) {
// not newer than the one installed
break;
}
if (version_compare($release['m'], phpversion(), '>')) {
// skip dependency releases that require a PHP version
// newer than our PHP version
continue;
}
// new version > installed version
if (!$pref_state) {
// every state is a good state
$found = true;
break;
} else {
$new_state = $release['s'];
// if new state >= installed state: go
if (in_array($new_state, $this->betterStates($inst_state, true))) {
$found = true;
break;
} else {
// only allow to lower the state of package,
// if new state >= preferred state: go
if (in_array($new_state, $this->betterStates($pref_state, true))) {
$found = true;
break;
}
}
}
}
if (!$found) {
continue;
}
$relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' .
$release['v'] . '.xml', false, false, $channel);
if (PEAR::isError($relinfo)) {
return $relinfo;
}
$ret[$package] = array(
'version' => $release['v'],
'state' => $release['s'],
'filesize' => $relinfo['f'],
);
}
return $ret;
}
}PK [t PEAR/REST/10.phpnu W+A
* @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.0a12
*/
/**
* For downloading REST xml/txt files
*/
require_once 'PEAR/REST.php';
/**
* Implement REST 1.0
*
* @category pear
* @package PEAR
* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.4
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a12
*/
class PEAR_REST_10
{
/**
* @var PEAR_REST
*/
var $_rest;
function __construct($config, $options = array())
{
$this->_rest = new PEAR_REST($config, $options);
}
/**
* Retrieve information about a remote package to be downloaded from a REST server
*
* @param string $base The uri to prepend to all REST calls
* @param array $packageinfo an array of format:
*
* array(
* 'package' => 'packagename',
* 'channel' => 'channelname',
* ['state' => 'alpha' (or valid state),]
* -or-
* ['version' => '1.whatever']
*
* @param string $prefstate Current preferred_state config variable value
* @param bool $installed the installed version of this package to compare against
* @return array|false|PEAR_Error see {@link _returnDownloadURL()}
*/
function getDownloadURL($base, $packageinfo, $prefstate, $installed, $channel = false)
{
$states = $this->betterStates($prefstate, true);
if (!$states) {
return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
}
$channel = $packageinfo['channel'];
$package = $packageinfo['package'];
$state = isset($packageinfo['state']) ? $packageinfo['state'] : null;
$version = isset($packageinfo['version']) ? $packageinfo['version'] : null;
$restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml';
$info = $this->_rest->retrieveData($restFile, false, false, $channel);
if (PEAR::isError($info)) {
return PEAR::raiseError('No releases available for package "' .
$channel . '/' . $package . '"');
}
if (!isset($info['r'])) {
return false;
}
$release = $found = false;
if (!is_array($info['r']) || !isset($info['r'][0])) {
$info['r'] = array($info['r']);
}
foreach ($info['r'] as $release) {
if (!isset($this->_rest->_options['force']) && ($installed &&
version_compare($release['v'], $installed, '<'))) {
continue;
}
if (isset($state)) {
// try our preferred state first
if ($release['s'] == $state) {
$found = true;
break;
}
// see if there is something newer and more stable
// bug #7221
if (in_array($release['s'], $this->betterStates($state), true)) {
$found = true;
break;
}
} elseif (isset($version)) {
if ($release['v'] == $version) {
$found = true;
break;
}
} else {
if (in_array($release['s'], $states)) {
$found = true;
break;
}
}
}
return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel);
}
function getDepDownloadURL($base, $xsdversion, $dependency, $deppackage,
$prefstate = 'stable', $installed = false, $channel = false)
{
$states = $this->betterStates($prefstate, true);
if (!$states) {
return PEAR::raiseError('"' . $prefstate . '" is not a valid state');
}
$channel = $dependency['channel'];
$package = $dependency['name'];
$state = isset($dependency['state']) ? $dependency['state'] : null;
$version = isset($dependency['version']) ? $dependency['version'] : null;
$restFile = $base . 'r/' . strtolower($package) . '/allreleases.xml';
$info = $this->_rest->retrieveData($restFile, false, false, $channel);
if (PEAR::isError($info)) {
return PEAR::raiseError('Package "' . $deppackage['channel'] . '/' . $deppackage['package']
. '" dependency "' . $channel . '/' . $package . '" has no releases');
}
if (!is_array($info) || !isset($info['r'])) {
return false;
}
$exclude = array();
$min = $max = $recommended = false;
if ($xsdversion == '1.0') {
switch ($dependency['rel']) {
case 'ge' :
$min = $dependency['version'];
break;
case 'gt' :
$min = $dependency['version'];
$exclude = array($dependency['version']);
break;
case 'eq' :
$recommended = $dependency['version'];
break;
case 'lt' :
$max = $dependency['version'];
$exclude = array($dependency['version']);
break;
case 'le' :
$max = $dependency['version'];
break;
case 'ne' :
$exclude = array($dependency['version']);
break;
}
} else {
$min = isset($dependency['min']) ? $dependency['min'] : false;
$max = isset($dependency['max']) ? $dependency['max'] : false;
$recommended = isset($dependency['recommended']) ?
$dependency['recommended'] : false;
if (isset($dependency['exclude'])) {
if (!isset($dependency['exclude'][0])) {
$exclude = array($dependency['exclude']);
}
}
}
$release = $found = false;
if (!is_array($info['r']) || !isset($info['r'][0])) {
$info['r'] = array($info['r']);
}
foreach ($info['r'] as $release) {
if (!isset($this->_rest->_options['force']) && ($installed &&
version_compare($release['v'], $installed, '<'))) {
continue;
}
if (in_array($release['v'], $exclude)) { // skip excluded versions
continue;
}
// allow newer releases to say "I'm OK with the dependent package"
if ($xsdversion == '2.0' && isset($release['co'])) {
if (!is_array($release['co']) || !isset($release['co'][0])) {
$release['co'] = array($release['co']);
}
foreach ($release['co'] as $entry) {
if (isset($entry['x']) && !is_array($entry['x'])) {
$entry['x'] = array($entry['x']);
} elseif (!isset($entry['x'])) {
$entry['x'] = array();
}
if ($entry['c'] == $deppackage['channel'] &&
strtolower($entry['p']) == strtolower($deppackage['package']) &&
version_compare($deppackage['version'], $entry['min'], '>=') &&
version_compare($deppackage['version'], $entry['max'], '<=') &&
!in_array($release['v'], $entry['x'])) {
$recommended = $release['v'];
break;
}
}
}
if ($recommended) {
if ($release['v'] != $recommended) { // if we want a specific
// version, then skip all others
continue;
} else {
if (!in_array($release['s'], $states)) {
// the stability is too low, but we must return the
// recommended version if possible
return $this->_returnDownloadURL($base, $package, $release, $info, true, false, $channel);
}
}
}
if ($min && version_compare($release['v'], $min, 'lt')) { // skip too old versions
continue;
}
if ($max && version_compare($release['v'], $max, 'gt')) { // skip too new versions
continue;
}
if ($installed && version_compare($release['v'], $installed, '<')) {
continue;
}
if (in_array($release['s'], $states)) { // if in the preferred state...
$found = true; // ... then use it
break;
}
}
return $this->_returnDownloadURL($base, $package, $release, $info, $found, false, $channel);
}
/**
* Take raw data and return the array needed for processing a download URL
*
* @param string $base REST base uri
* @param string $package Package name
* @param array $release an array of format array('v' => version, 's' => state)
* describing the release to download
* @param array $info list of all releases as defined by allreleases.xml
* @param bool|null $found determines whether the release was found or this is the next
* best alternative. If null, then versions were skipped because
* of PHP dependency
* @return array|PEAR_Error
* @access private
*/
function _returnDownloadURL($base, $package, $release, $info, $found, $phpversion = false, $channel = false)
{
if (!$found) {
$release = $info['r'][0];
}
$packageLower = strtolower($package);
$pinfo = $this->_rest->retrieveCacheFirst($base . 'p/' . $packageLower . '/' .
'info.xml', false, false, $channel);
if (PEAR::isError($pinfo)) {
return PEAR::raiseError('Package "' . $package .
'" does not have REST info xml available');
}
$releaseinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' .
$release['v'] . '.xml', false, false, $channel);
if (PEAR::isError($releaseinfo)) {
return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
'" does not have REST xml available');
}
$packagexml = $this->_rest->retrieveCacheFirst($base . 'r/' . $packageLower . '/' .
'deps.' . $release['v'] . '.txt', false, true, $channel);
if (PEAR::isError($packagexml)) {
return PEAR::raiseError('Package "' . $package . '" Version "' . $release['v'] .
'" does not have REST dependency information available');
}
$packagexml = unserialize($packagexml);
if (!$packagexml) {
$packagexml = array();
}
$allinfo = $this->_rest->retrieveData($base . 'r/' . $packageLower .
'/allreleases.xml', false, false, $channel);
if (PEAR::isError($allinfo)) {
return $allinfo;
}
if (!is_array($allinfo['r']) || !isset($allinfo['r'][0])) {
$allinfo['r'] = array($allinfo['r']);
}
$compatible = false;
foreach ($allinfo['r'] as $release) {
if ($release['v'] != $releaseinfo['v']) {
continue;
}
if (!isset($release['co'])) {
break;
}
$compatible = array();
if (!is_array($release['co']) || !isset($release['co'][0])) {
$release['co'] = array($release['co']);
}
foreach ($release['co'] as $entry) {
$comp = array();
$comp['name'] = $entry['p'];
$comp['channel'] = $entry['c'];
$comp['min'] = $entry['min'];
$comp['max'] = $entry['max'];
if (isset($entry['x']) && !is_array($entry['x'])) {
$comp['exclude'] = $entry['x'];
}
$compatible[] = $comp;
}
if (count($compatible) == 1) {
$compatible = $compatible[0];
}
break;
}
$deprecated = false;
if (isset($pinfo['dc']) && isset($pinfo['dp'])) {
if (is_array($pinfo['dp'])) {
$deprecated = array('channel' => (string) $pinfo['dc'],
'package' => trim($pinfo['dp']['_content']));
} else {
$deprecated = array('channel' => (string) $pinfo['dc'],
'package' => trim($pinfo['dp']));
}
}
$return = array(
'version' => $releaseinfo['v'],
'info' => $packagexml,
'package' => $releaseinfo['p']['_content'],
'stability' => $releaseinfo['st'],
'compatible' => $compatible,
'deprecated' => $deprecated,
);
if ($found) {
$return['url'] = $releaseinfo['g'];
return $return;
}
$return['php'] = $phpversion;
return $return;
}
function listPackages($base, $channel = false)
{
$packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
if (PEAR::isError($packagelist)) {
return $packagelist;
}
if (!is_array($packagelist) || !isset($packagelist['p'])) {
return array();
}
if (!is_array($packagelist['p'])) {
$packagelist['p'] = array($packagelist['p']);
}
return $packagelist['p'];
}
/**
* List all categories of a REST server
*
* @param string $base base URL of the server
* @return array of categorynames
*/
function listCategories($base, $channel = false)
{
$categories = array();
// c/categories.xml does not exist;
// check for every package its category manually
// This is SLOOOWWWW : ///
$packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
if (PEAR::isError($packagelist)) {
return $packagelist;
}
if (!is_array($packagelist) || !isset($packagelist['p'])) {
$ret = array();
return $ret;
}
if (!is_array($packagelist['p'])) {
$packagelist['p'] = array($packagelist['p']);
}
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
foreach ($packagelist['p'] as $package) {
$inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
if (PEAR::isError($inf)) {
PEAR::popErrorHandling();
return $inf;
}
$cat = $inf['ca']['_content'];
if (!isset($categories[$cat])) {
$categories[$cat] = $inf['ca'];
}
}
return array_values($categories);
}
/**
* List a category of a REST server
*
* @param string $base base URL of the server
* @param string $category name of the category
* @param boolean $info also download full package info
* @return array of packagenames
*/
function listCategory($base, $category, $info = false, $channel = false)
{
// gives '404 Not Found' error when category doesn't exist
$packagelist = $this->_rest->retrieveData($base.'c/'.urlencode($category).'/packages.xml', false, false, $channel);
if (PEAR::isError($packagelist)) {
return $packagelist;
}
if (!is_array($packagelist) || !isset($packagelist['p'])) {
return array();
}
if (!is_array($packagelist['p']) ||
!isset($packagelist['p'][0])) { // only 1 pkg
$packagelist = array($packagelist['p']);
} else {
$packagelist = $packagelist['p'];
}
if ($info == true) {
// get individual package info
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
foreach ($packagelist as $i => $packageitem) {
$url = sprintf('%s'.'r/%s/latest.txt',
$base,
strtolower($packageitem['_content']));
$version = $this->_rest->retrieveData($url, false, false, $channel);
if (PEAR::isError($version)) {
break; // skipit
}
$url = sprintf('%s'.'r/%s/%s.xml',
$base,
strtolower($packageitem['_content']),
$version);
$info = $this->_rest->retrieveData($url, false, false, $channel);
if (PEAR::isError($info)) {
break; // skipit
}
$packagelist[$i]['info'] = $info;
}
PEAR::popErrorHandling();
}
return $packagelist;
}
function listAll($base, $dostable, $basic = true, $searchpackage = false, $searchsummary = false, $channel = false)
{
$packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
if (PEAR::isError($packagelist)) {
return $packagelist;
}
if ($this->_rest->config->get('verbose') > 0) {
$ui = &PEAR_Frontend::singleton();
$ui->log('Retrieving data...0%', true);
}
$ret = array();
if (!is_array($packagelist) || !isset($packagelist['p'])) {
return $ret;
}
if (!is_array($packagelist['p'])) {
$packagelist['p'] = array($packagelist['p']);
}
// only search-packagename = quicksearch !
if ($searchpackage && (!$searchsummary || empty($searchpackage))) {
$newpackagelist = array();
foreach ($packagelist['p'] as $package) {
if (!empty($searchpackage) && stristr($package, $searchpackage) !== false) {
$newpackagelist[] = $package;
}
}
$packagelist['p'] = $newpackagelist;
}
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$next = .1;
foreach ($packagelist['p'] as $progress => $package) {
if ($this->_rest->config->get('verbose') > 0) {
if ($progress / count($packagelist['p']) >= $next) {
if ($next == .5) {
$ui->log('50%', false);
} else {
$ui->log('.', false);
}
$next += .1;
}
}
if ($basic) { // remote-list command
if ($dostable) {
$latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
'/stable.txt', false, false, $channel);
} else {
$latest = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
'/latest.txt', false, false, $channel);
}
if (PEAR::isError($latest)) {
$latest = false;
}
$info = array('stable' => $latest);
} else { // list-all command
$inf = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
if (PEAR::isError($inf)) {
PEAR::popErrorHandling();
return $inf;
}
if ($searchpackage) {
$found = (!empty($searchpackage) && stristr($package, $searchpackage) !== false);
if (!$found && !(isset($searchsummary) && !empty($searchsummary)
&& (stristr($inf['s'], $searchsummary) !== false
|| stristr($inf['d'], $searchsummary) !== false)))
{
continue;
};
}
$releases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
'/allreleases.xml', false, false, $channel);
if (PEAR::isError($releases)) {
continue;
}
if (!isset($releases['r'][0])) {
$releases['r'] = array($releases['r']);
}
unset($latest);
unset($unstable);
unset($stable);
unset($state);
foreach ($releases['r'] as $release) {
if (!isset($latest)) {
if ($dostable && $release['s'] == 'stable') {
$latest = $release['v'];
$state = 'stable';
}
if (!$dostable) {
$latest = $release['v'];
$state = $release['s'];
}
}
if (!isset($stable) && $release['s'] == 'stable') {
$stable = $release['v'];
if (!isset($unstable)) {
$unstable = $stable;
}
}
if (!isset($unstable) && $release['s'] != 'stable') {
$latest = $unstable = $release['v'];
$state = $release['s'];
}
if (isset($latest) && !isset($state)) {
$state = $release['s'];
}
if (isset($latest) && isset($stable) && isset($unstable)) {
break;
}
}
$deps = array();
if (!isset($unstable)) {
$unstable = false;
$state = 'stable';
if (isset($stable)) {
$latest = $unstable = $stable;
}
} else {
$latest = $unstable;
}
if (!isset($latest)) {
$latest = false;
}
if ($latest) {
$d = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
$latest . '.txt', false, false, $channel);
if (!PEAR::isError($d)) {
$d = unserialize($d);
if ($d) {
if (isset($d['required'])) {
if (!class_exists('PEAR_PackageFile_v2')) {
require_once 'PEAR/PackageFile/v2.php';
}
if (!isset($pf)) {
$pf = new PEAR_PackageFile_v2;
}
$pf->setDeps($d);
$tdeps = $pf->getDeps();
} else {
$tdeps = $d;
}
foreach ($tdeps as $dep) {
if ($dep['type'] !== 'pkg') {
continue;
}
$deps[] = $dep;
}
}
}
}
if (!isset($stable)) {
$stable = '-n/a-';
}
if (!$searchpackage) {
$info = array('stable' => $latest, 'summary' => $inf['s'], 'description' =>
$inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
'unstable' => $unstable, 'state' => $state);
} else {
$info = array('stable' => $stable, 'summary' => $inf['s'], 'description' =>
$inf['d'], 'deps' => $deps, 'category' => $inf['ca']['_content'],
'unstable' => $unstable, 'state' => $state);
}
}
$ret[$package] = $info;
}
PEAR::popErrorHandling();
return $ret;
}
function listLatestUpgrades($base, $pref_state, $installed, $channel, &$reg)
{
$packagelist = $this->_rest->retrieveData($base . 'p/packages.xml', false, false, $channel);
if (PEAR::isError($packagelist)) {
return $packagelist;
}
$ret = array();
if (!is_array($packagelist) || !isset($packagelist['p'])) {
return $ret;
}
if (!is_array($packagelist['p'])) {
$packagelist['p'] = array($packagelist['p']);
}
foreach ($packagelist['p'] as $package) {
if (!isset($installed[strtolower($package)])) {
continue;
}
$inst_version = $reg->packageInfo($package, 'version', $channel);
$inst_state = $reg->packageInfo($package, 'release_state', $channel);
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$info = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
'/allreleases.xml', false, false, $channel);
PEAR::popErrorHandling();
if (PEAR::isError($info)) {
continue; // no remote releases
}
if (!isset($info['r'])) {
continue;
}
$release = $found = false;
if (!is_array($info['r']) || !isset($info['r'][0])) {
$info['r'] = array($info['r']);
}
// $info['r'] is sorted by version number
usort($info['r'], array($this, '_sortReleasesByVersionNumber'));
foreach ($info['r'] as $release) {
if ($inst_version && version_compare($release['v'], $inst_version, '<=')) {
// not newer than the one installed
break;
}
// new version > installed version
if (!$pref_state) {
// every state is a good state
$found = true;
break;
} else {
$new_state = $release['s'];
// if new state >= installed state: go
if (in_array($new_state, $this->betterStates($inst_state, true))) {
$found = true;
break;
} else {
// only allow to lower the state of package,
// if new state >= preferred state: go
if (in_array($new_state, $this->betterStates($pref_state, true))) {
$found = true;
break;
}
}
}
}
if (!$found) {
continue;
}
$relinfo = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/' .
$release['v'] . '.xml', false, false, $channel);
if (PEAR::isError($relinfo)) {
return $relinfo;
}
$ret[$package] = array(
'version' => $release['v'],
'state' => $release['s'],
'filesize' => $relinfo['f'],
);
}
return $ret;
}
function packageInfo($base, $package, $channel = false)
{
PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
$pinfo = $this->_rest->retrieveData($base . 'p/' . strtolower($package) . '/info.xml', false, false, $channel);
if (PEAR::isError($pinfo)) {
PEAR::popErrorHandling();
return PEAR::raiseError('Unknown package: "' . $package . '" in channel "' . $channel . '"' . "\n". 'Debug: ' .
$pinfo->getMessage());
}
$releases = array();
$allreleases = $this->_rest->retrieveData($base . 'r/' . strtolower($package) .
'/allreleases.xml', false, false, $channel);
if (!PEAR::isError($allreleases)) {
if (!class_exists('PEAR_PackageFile_v2')) {
require_once 'PEAR/PackageFile/v2.php';
}
if (!is_array($allreleases['r']) || !isset($allreleases['r'][0])) {
$allreleases['r'] = array($allreleases['r']);
}
$pf = new PEAR_PackageFile_v2;
foreach ($allreleases['r'] as $release) {
$ds = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package) . '/deps.' .
$release['v'] . '.txt', false, false, $channel);
if (PEAR::isError($ds)) {
continue;
}
if (!isset($latest)) {
$latest = $release['v'];
}
$pf->setDeps(unserialize($ds));
$ds = $pf->getDeps();
$info = $this->_rest->retrieveCacheFirst($base . 'r/' . strtolower($package)
. '/' . $release['v'] . '.xml', false, false, $channel);
if (PEAR::isError($info)) {
continue;
}
$releases[$release['v']] = array(
'doneby' => $info['m'],
'license' => $info['l'],
'summary' => $info['s'],
'description' => $info['d'],
'releasedate' => $info['da'],
'releasenotes' => $info['n'],
'state' => $release['s'],
'deps' => $ds ? $ds : array(),
);
}
} else {
$latest = '';
}
PEAR::popErrorHandling();
if (isset($pinfo['dc']) && isset($pinfo['dp'])) {
if (is_array($pinfo['dp'])) {
$deprecated = array('channel' => (string) $pinfo['dc'],
'package' => trim($pinfo['dp']['_content']));
} else {
$deprecated = array('channel' => (string) $pinfo['dc'],
'package' => trim($pinfo['dp']));
}
} else {
$deprecated = false;
}
if (!isset($latest)) {
$latest = '';
}
return array(
'name' => $pinfo['n'],
'channel' => $pinfo['c'],
'category' => $pinfo['ca']['_content'],
'stable' => $latest,
'license' => $pinfo['l'],
'summary' => $pinfo['s'],
'description' => $pinfo['d'],
'releases' => $releases,
'deprecated' => $deprecated,
);
}
/**
* Return an array containing all of the states that are more stable than
* or equal to the passed in state
*
* @param string Release state
* @param boolean Determines whether to include $state in the list
* @return false|array False if $state is not a valid release state
*/
function betterStates($state, $include = false)
{
static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable');
$i = array_search($state, $states);
if ($i === false) {
return false;
}
if ($include) {
$i--;
}
return array_slice($states, $i + 1);
}
/**
* Sort releases by version number
*
* @access private
*/
function _sortReleasesByVersionNumber($a, $b)
{
if (version_compare($a['v'], $b['v'], '=')) {
return 0;
}
if (version_compare($a['v'], $b['v'], '>')) {
return -1;
}
if (version_compare($a['v'], $b['v'], '<')) {
return 1;
}
}
}
PK [%Fi i PEAR/Command/Test.xmlnu W+A
Run Regression Tests
doRunTests
rt
r
Run tests in child directories, recursively. 4 dirs deep maximum
i
actual string of settings to pass to php in format " -d setting=blah"
SETTINGS
l
Log test runs/results as they are run
q
Only display detail for failed tests
s
Display simple output for all tests
p
Treat parameters as installed packages from which to run tests
u
Search parameters for AllTests.php, and use that to run phpunit-based tests
If none is found, all .phpt tests will be tried instead.
t
Output run-tests.log in TAP-compliant format
c
CGI php executable (needed for tests with POST/GET section)
PHPCGI
x
Generate a code coverage report (requires Xdebug 2.0.0+)
[testfile|dir ...]
Run regression tests with PHP's regression testing script (run-tests.php).
PK [݄