diff options
author | Mark A. Hershberger <mah@debian.(none)> | 2009-03-25 00:34:21 -0400 |
---|---|---|
committer | Mark A. Hershberger <mah@debian.(none)> | 2009-03-25 00:34:21 -0400 |
commit | 0e920280a2e04b110827bb766b9f29e3d581c4ee (patch) | |
tree | 8f2125f3d00fe3089e3b94adb06f04479ee15f2a /pear | |
download | php-0e920280a2e04b110827bb766b9f29e3d581c4ee.tar.gz |
Imported Upstream version 5.0.4upstream/5.0.4
Diffstat (limited to 'pear')
164 files changed, 37016 insertions, 0 deletions
diff --git a/pear/Archive/Tar.php b/pear/Archive/Tar.php new file mode 100644 index 000000000..30e5165c6 --- /dev/null +++ b/pear/Archive/Tar.php @@ -0,0 +1,1601 @@ +<?php +/* vim: set ts=4 sw=4: */ +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Vincent Blavet <vincent@blavet.net> | +// +----------------------------------------------------------------------+ +// +// $Id: Tar.php,v 1.20 2004/01/08 17:33:09 sniper Exp $ + +require_once 'PEAR.php'; + +/** +* Creates a (compressed) Tar archive +* +* @author Vincent Blavet <vincent@blavet.net> +* @version $Revision: 1.20 $ +* @package Archive +*/ +class Archive_Tar extends PEAR +{ + /** + * @var string Name of the Tar + */ + var $_tarname=''; + + /** + * @var boolean if true, the Tar file will be gzipped + */ + var $_compress=false; + + /** + * @var string Type of compression : 'none', 'gz' or 'bz2' + */ + var $_compress_type='none'; + + /** + * @var file descriptor + */ + var $_file=0; + + /** + * @var string Local Tar name of a remote Tar (http:// or ftp://) + */ + var $_temp_tarname=''; + + // {{{ constructor + /** + * Archive_Tar Class constructor. This flavour of the constructor only + * declare a new Archive_Tar object, identifying it by the name of the + * tar file. + * If the compress argument is set the tar will be read or created as a + * gzip or bz2 compressed TAR file. + * + * @param string $p_tarname The name of the tar archive to create + * @param string $p_compress can be null, 'gz' or 'bz2'. This + * parameter indicates if gzip or bz2 compression + * is required. For compatibility reason the + * boolean value 'true' means 'gz'. + * @access public + */ + function Archive_Tar($p_tarname, $p_compress = null) + { + $this->PEAR(); + $this->_compress = false; + $this->_compress_type = 'none'; + if ($p_compress === null) { + if (@file_exists($p_tarname)) { + if ($fp = @fopen($p_tarname, "rb")) { + // look for gzip magic cookie + $data = fread($fp, 2); + fclose($fp); + if ($data == "\37\213") { + $this->_compress = true; + $this->_compress_type = 'gz'; + // No sure it's enought for a magic code .... + } elseif ($data == "BZ") { + $this->_compress = true; + $this->_compress_type = 'bz2'; + } + } + } else { + // probably a remote file or some file accessible + // through a stream interface + if (substr($p_tarname, -2) == 'gz') { + $this->_compress = true; + $this->_compress_type = 'gz'; + } elseif ((substr($p_tarname, -3) == 'bz2') || + (substr($p_tarname, -2) == 'bz')) { + $this->_compress = true; + $this->_compress_type = 'bz2'; + } + } + } else { + if (($p_compress == true) || ($p_compress == 'gz')) { + $this->_compress = true; + $this->_compress_type = 'gz'; + } else if ($p_compress == 'bz2') { + $this->_compress = true; + $this->_compress_type = 'bz2'; + } + } + $this->_tarname = $p_tarname; + if ($this->_compress) { // assert zlib or bz2 extension support + if ($this->_compress_type == 'gz') + $extname = 'zlib'; + else if ($this->_compress_type == 'bz2') + $extname = 'bz2'; + + if (!extension_loaded($extname)) { + PEAR::loadExtension($extname); + } + if (!extension_loaded($extname)) { + die("The extension '$extname' couldn't be found.\n". + "Please make sure your version of PHP was built ". + "with '$extname' support.\n"); + return false; + } + } + } + // }}} + + // {{{ destructor + function _Archive_Tar() + { + $this->_close(); + // ----- Look for a local copy to delete + if ($this->_temp_tarname != '') + @unlink($this->_temp_tarname); + $this->_PEAR(); + } + // }}} + + // {{{ create() + /** + * This method creates the archive file and add the files / directories + * that are listed in $p_filelist. + * If a file with the same name exist and is writable, it is replaced + * by the new tar. + * The method return false and a PEAR error text. + * The $p_filelist parameter can be an array of string, each string + * representing a filename or a directory name with their path if + * needed. It can also be a single string with names separated by a + * single blank. + * For each directory added in the archive, the files and + * sub-directories are also added. + * See also createModify() method for more details. + * + * @param array $p_filelist An array of filenames and directory names, or a single + * string with names separated by a single blank space. + * @return true on success, false on error. + * @see createModify() + * @access public + */ + function create($p_filelist) + { + return $this->createModify($p_filelist, '', ''); + } + // }}} + + // {{{ add() + /** + * This method add the files / directories that are listed in $p_filelist in + * the archive. If the archive does not exist it is created. + * The method return false and a PEAR error text. + * The files and directories listed are only added at the end of the archive, + * even if a file with the same name is already archived. + * See also createModify() method for more details. + * + * @param array $p_filelist An array of filenames and directory names, or a single + * string with names separated by a single blank space. + * @return true on success, false on error. + * @see createModify() + * @access public + */ + function add($p_filelist) + { + return $this->addModify($p_filelist, '', ''); + } + // }}} + + // {{{ extract() + function extract($p_path='') + { + return $this->extractModify($p_path, ''); + } + // }}} + + // {{{ listContent() + function listContent() + { + $v_list_detail = array(); + + if ($this->_openRead()) { + if (!$this->_extractList('', $v_list_detail, "list", '', '')) { + unset($v_list_detail); + $v_list_detail = 0; + } + $this->_close(); + } + + return $v_list_detail; + } + // }}} + + // {{{ createModify() + /** + * This method creates the archive file and add the files / directories + * that are listed in $p_filelist. + * If the file already exists and is writable, it is replaced by the + * new tar. It is a create and not an add. If the file exists and is + * read-only or is a directory it is not replaced. The method return + * false and a PEAR error text. + * The $p_filelist parameter can be an array of string, each string + * representing a filename or a directory name with their path if + * needed. It can also be a single string with names separated by a + * single blank. + * The path indicated in $p_remove_dir will be removed from the + * memorized path of each file / directory listed when this path + * exists. By default nothing is removed (empty path '') + * The path indicated in $p_add_dir will be added at the beginning of + * the memorized path of each file / directory listed. However it can + * be set to empty ''. The adding of a path is done after the removing + * of path. + * The path add/remove ability enables the user to prepare an archive + * for extraction in a different path than the origin files are. + * See also addModify() method for file adding properties. + * + * @param array $p_filelist An array of filenames and directory names, or a single + * string with names separated by a single blank space. + * @param string $p_add_dir A string which contains a path to be added to the + * memorized path of each element in the list. + * @param string $p_remove_dir A string which contains a path to be removed from + * the memorized path of each element in the list, when + * relevant. + * @return boolean true on success, false on error. + * @access public + * @see addModify() + */ + function createModify($p_filelist, $p_add_dir, $p_remove_dir='') + { + $v_result = true; + + if (!$this->_openWrite()) + return false; + + if ($p_filelist != '') { + if (is_array($p_filelist)) + $v_list = $p_filelist; + elseif (is_string($p_filelist)) + $v_list = explode(" ", $p_filelist); + else { + $this->_cleanFile(); + $this->_error('Invalid file list'); + return false; + } + + $v_result = $this->_addList($v_list, $p_add_dir, $p_remove_dir); + } + + if ($v_result) { + $this->_writeFooter(); + $this->_close(); + } else + $this->_cleanFile(); + + return $v_result; + } + // }}} + + // {{{ addModify() + /** + * This method add the files / directories listed in $p_filelist at the + * end of the existing archive. If the archive does not yet exists it + * is created. + * The $p_filelist parameter can be an array of string, each string + * representing a filename or a directory name with their path if + * needed. It can also be a single string with names separated by a + * single blank. + * The path indicated in $p_remove_dir will be removed from the + * memorized path of each file / directory listed when this path + * exists. By default nothing is removed (empty path '') + * The path indicated in $p_add_dir will be added at the beginning of + * the memorized path of each file / directory listed. However it can + * be set to empty ''. The adding of a path is done after the removing + * of path. + * The path add/remove ability enables the user to prepare an archive + * for extraction in a different path than the origin files are. + * If a file/dir is already in the archive it will only be added at the + * end of the archive. There is no update of the existing archived + * file/dir. However while extracting the archive, the last file will + * replace the first one. This results in a none optimization of the + * archive size. + * If a file/dir does not exist the file/dir is ignored. However an + * error text is send to PEAR error. + * If a file/dir is not readable the file/dir is ignored. However an + * error text is send to PEAR error. + * + * @param array $p_filelist An array of filenames and directory names, or a single + * string with names separated by a single blank space. + * @param string $p_add_dir A string which contains a path to be added to the + * memorized path of each element in the list. + * @param string $p_remove_dir A string which contains a path to be removed from + * the memorized path of each element in the list, when + * relevant. + * @return true on success, false on error. + * @access public + */ + function addModify($p_filelist, $p_add_dir, $p_remove_dir='') + { + $v_result = true; + + if (!@is_file($this->_tarname)) + $v_result = $this->createModify($p_filelist, $p_add_dir, $p_remove_dir); + else { + if (is_array($p_filelist)) + $v_list = $p_filelist; + elseif (is_string($p_filelist)) + $v_list = explode(" ", $p_filelist); + else { + $this->_error('Invalid file list'); + return false; + } + + $v_result = $this->_append($v_list, $p_add_dir, $p_remove_dir); + } + + return $v_result; + } + // }}} + + // {{{ addString() + /** + * This method add a single string as a file at the + * end of the existing archive. If the archive does not yet exists it + * is created. + * + * @param string $p_filename A string which contains the full filename path + * that will be associated with the string. + * @param string $p_string The content of the file added in the archive. + * @return true on success, false on error. + * @access public + */ + function addString($p_filename, $p_string) + { + $v_result = true; + + if (!@is_file($this->_tarname)) { + if (!$this->_openWrite()) { + return false; + } + $this->_close(); + } + + if (!$this->_openAppend()) + return false; + + // Need to check the get back to the temporary file ? .... + $v_result = $this->_addString($p_filename, $p_string); + + $this->_writeFooter(); + + $this->_close(); + + return $v_result; + } + // }}} + + // {{{ extractModify() + /** + * This method extract all the content of the archive in the directory + * indicated by $p_path. When relevant the memorized path of the + * files/dir can be modified by removing the $p_remove_path path at the + * beginning of the file/dir path. + * While extracting a file, if the directory path does not exists it is + * created. + * While extracting a file, if the file already exists it is replaced + * without looking for last modification date. + * While extracting a file, if the file already exists and is write + * protected, the extraction is aborted. + * While extracting a file, if a directory with the same name already + * exists, the extraction is aborted. + * While extracting a directory, if a file with the same name already + * exists, the extraction is aborted. + * While extracting a file/directory if the destination directory exist + * and is write protected, or does not exist but can not be created, + * the extraction is aborted. + * If after extraction an extracted file does not show the correct + * stored file size, the extraction is aborted. + * When the extraction is aborted, a PEAR error text is set and false + * is returned. However the result can be a partial extraction that may + * need to be manually cleaned. + * + * @param string $p_path The path of the directory where the files/dir need to by + * extracted. + * @param string $p_remove_path Part of the memorized path that can be removed if + * present at the beginning of the file/dir path. + * @return boolean true on success, false on error. + * @access public + * @see extractList() + */ + function extractModify($p_path, $p_remove_path) + { + $v_result = true; + $v_list_detail = array(); + + if ($v_result = $this->_openRead()) { + $v_result = $this->_extractList($p_path, $v_list_detail, "complete", 0, $p_remove_path); + $this->_close(); + } + + return $v_result; + } + // }}} + + // {{{ extractInString() + /** + * This method extract from the archive one file identified by $p_filename. + * The return value is a string with the file content, or NULL on error. + * @param string $p_filename The path of the file to extract in a string. + * @return a string with the file content or NULL. + * @access public + */ + function extractInString($p_filename) + { + if ($this->_openRead()) { + $v_result = $this->_extractInString($p_filename); + $this->_close(); + } else { + $v_result = NULL; + } + + return $v_result; + } + // }}} + + // {{{ extractList() + /** + * This method extract from the archive only the files indicated in the + * $p_filelist. These files are extracted in the current directory or + * in the directory indicated by the optional $p_path parameter. + * If indicated the $p_remove_path can be used in the same way as it is + * used in extractModify() method. + * @param array $p_filelist An array of filenames and directory names, or a single + * string with names separated by a single blank space. + * @param string $p_path The path of the directory where the files/dir need to by + * extracted. + * @param string $p_remove_path Part of the memorized path that can be removed if + * present at the beginning of the file/dir path. + * @return true on success, false on error. + * @access public + * @see extractModify() + */ + function extractList($p_filelist, $p_path='', $p_remove_path='') + { + $v_result = true; + $v_list_detail = array(); + + if (is_array($p_filelist)) + $v_list = $p_filelist; + elseif (is_string($p_filelist)) + $v_list = explode(" ", $p_filelist); + else { + $this->_error('Invalid string list'); + return false; + } + + if ($v_result = $this->_openRead()) { + $v_result = $this->_extractList($p_path, $v_list_detail, "partial", $v_list, $p_remove_path); + $this->_close(); + } + + return $v_result; + } + // }}} + + // {{{ _error() + function _error($p_message) + { + // ----- To be completed + $this->raiseError($p_message); + } + // }}} + + // {{{ _warning() + function _warning($p_message) + { + // ----- To be completed + $this->raiseError($p_message); + } + // }}} + + // {{{ _openWrite() + function _openWrite() + { + if ($this->_compress_type == 'gz') + $this->_file = @gzopen($this->_tarname, "wb"); + else if ($this->_compress_type == 'bz2') + $this->_file = @bzopen($this->_tarname, "wb"); + else if ($this->_compress_type == 'none') + $this->_file = @fopen($this->_tarname, "wb"); + else + $this->_error('Unknown or missing compression type ('.$this->_compress_type.')'); + + if ($this->_file == 0) { + $this->_error('Unable to open in write mode \''.$this->_tarname.'\''); + return false; + } + + return true; + } + // }}} + + // {{{ _openRead() + function _openRead() + { + if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') { + + // ----- Look if a local copy need to be done + if ($this->_temp_tarname == '') { + $this->_temp_tarname = uniqid('tar').'.tmp'; + if (!$v_file_from = @fopen($this->_tarname, 'rb')) { + $this->_error('Unable to open in read mode \''.$this->_tarname.'\''); + $this->_temp_tarname = ''; + return false; + } + if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) { + $this->_error('Unable to open in write mode \''.$this->_temp_tarname.'\''); + $this->_temp_tarname = ''; + return false; + } + while ($v_data = @fread($v_file_from, 1024)) + @fwrite($v_file_to, $v_data); + @fclose($v_file_from); + @fclose($v_file_to); + } + + // ----- File to open if the local copy + $v_filename = $this->_temp_tarname; + + } else + // ----- File to open if the normal Tar file + $v_filename = $this->_tarname; + + if ($this->_compress_type == 'gz') + $this->_file = @gzopen($v_filename, "rb"); + else if ($this->_compress_type == 'bz2') + $this->_file = @bzopen($v_filename, "rb"); + else if ($this->_compress_type == 'none') + $this->_file = @fopen($v_filename, "rb"); + else + $this->_error('Unknown or missing compression type ('.$this->_compress_type.')'); + + if ($this->_file == 0) { + $this->_error('Unable to open in read mode \''.$v_filename.'\''); + return false; + } + + return true; + } + // }}} + + // {{{ _openReadWrite() + function _openReadWrite() + { + if ($this->_compress_type == 'gz') + $this->_file = @gzopen($this->_tarname, "r+b"); + else if ($this->_compress_type == 'bz2') + $this->_file = @bzopen($this->_tarname, "r+b"); + else if ($this->_compress_type == 'none') + $this->_file = @fopen($this->_tarname, "r+b"); + else + $this->_error('Unknown or missing compression type ('.$this->_compress_type.')'); + + if ($this->_file == 0) { + $this->_error('Unable to open in read/write mode \''.$this->_tarname.'\''); + return false; + } + + return true; + } + // }}} + + // {{{ _close() + function _close() + { + if (isset($this->_file)) { + if ($this->_compress_type == 'gz') + @gzclose($this->_file); + else if ($this->_compress_type == 'bz2') + @bzclose($this->_file); + else if ($this->_compress_type == 'none') + @fclose($this->_file); + else + $this->_error('Unknown or missing compression type ('.$this->_compress_type.')'); + + $this->_file = 0; + } + + // ----- Look if a local copy need to be erase + // Note that it might be interesting to keep the url for a time : ToDo + if ($this->_temp_tarname != '') { + @unlink($this->_temp_tarname); + $this->_temp_tarname = ''; + } + + return true; + } + // }}} + + // {{{ _cleanFile() + function _cleanFile() + { + $this->_close(); + + // ----- Look for a local copy + if ($this->_temp_tarname != '') { + // ----- Remove the local copy but not the remote tarname + @unlink($this->_temp_tarname); + $this->_temp_tarname = ''; + } else { + // ----- Remove the local tarname file + @unlink($this->_tarname); + } + $this->_tarname = ''; + + return true; + } + // }}} + + // {{{ _writeBlock() + function _writeBlock($p_binary_data, $p_len=null) + { + if ($this->_file) { + if ($p_len === null) { + if ($this->_compress_type == 'gz') + @gzputs($this->_file, $p_binary_data); + else if ($this->_compress_type == 'bz2') + @bzwrite($this->_file, $p_binary_data); + else if ($this->_compress_type == 'none') + @fputs($this->_file, $p_binary_data); + else + $this->_error('Unknown or missing compression type ('.$this->_compress_type.')'); + } else { + if ($this->_compress_type == 'gz') + @gzputs($this->_file, $p_binary_data, $p_len); + else if ($this->_compress_type == 'bz2') + @bzwrite($this->_file, $p_binary_data, $p_len); + else if ($this->_compress_type == 'none') + @fputs($this->_file, $p_binary_data, $p_len); + else + $this->_error('Unknown or missing compression type ('.$this->_compress_type.')'); + + } + } + return true; + } + // }}} + + // {{{ _readBlock() + function _readBlock($p_len=null) + { + $v_block = null; + if ($this->_file) { + if ($p_len === null) + $p_len = 512; + + if ($this->_compress_type == 'gz') + $v_block = @gzread($this->_file, 512); + else if ($this->_compress_type == 'bz2') + $v_block = @bzread($this->_file, 512); + else if ($this->_compress_type == 'none') + $v_block = @fread($this->_file, 512); + else + $this->_error('Unknown or missing compression type ('.$this->_compress_type.')'); + + } + return $v_block; + } + // }}} + + // {{{ _jumpBlock() + function _jumpBlock($p_len=null) + { + if ($this->_file) { + if ($p_len === null) + $p_len = 1; + + if ($this->_compress_type == 'gz') + @gzseek($this->_file, @gztell($this->_file)+($p_len*512)); + else if ($this->_compress_type == 'bz2') { + // ----- Replace missing bztell() and bzseek() + for ($i=0; $i<$p_len; $i++) + $this->_readBlock(); + } else if ($this->_compress_type == 'none') + @fseek($this->_file, @ftell($this->_file)+($p_len*512)); + else + $this->_error('Unknown or missing compression type ('.$this->_compress_type.')'); + + } + return true; + } + // }}} + + // {{{ _writeFooter() + function _writeFooter() + { + if ($this->_file) { + // ----- Write the last 0 filled block for end of archive + $v_binary_data = pack("a512", ''); + $this->_writeBlock($v_binary_data); + } + return true; + } + // }}} + + // {{{ _addList() + function _addList($p_list, $p_add_dir, $p_remove_dir) + { + $v_result=true; + $v_header = array(); + + // ----- Remove potential windows directory separator + $p_add_dir = $this->_translateWinPath($p_add_dir); + $p_remove_dir = $this->_translateWinPath($p_remove_dir, false); + + if (!$this->_file) { + $this->_error('Invalid file descriptor'); + return false; + } + + if (sizeof($p_list) == 0) + return true; + + for ($j=0; ($j<count($p_list)) && ($v_result); $j++) { + $v_filename = $p_list[$j]; + + // ----- Skip the current tar name + if ($v_filename == $this->_tarname) + continue; + + if ($v_filename == '') + continue; + + if (!file_exists($v_filename)) { + $this->_warning("File '$v_filename' does not exist"); + continue; + } + + // ----- Add the file or directory header + if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir)) + return false; + + if (@is_dir($v_filename)) { + if (!($p_hdir = opendir($v_filename))) { + $this->_warning("Directory '$v_filename' can not be read"); + continue; + } + $p_hitem = readdir($p_hdir); // '.' directory + $p_hitem = readdir($p_hdir); // '..' directory + while (false !== ($p_hitem = readdir($p_hdir))) { + if ($v_filename != ".") + $p_temp_list[0] = $v_filename.'/'.$p_hitem; + else + $p_temp_list[0] = $p_hitem; + + $v_result = $this->_addList($p_temp_list, $p_add_dir, $p_remove_dir); + } + + unset($p_temp_list); + unset($p_hdir); + unset($p_hitem); + } + } + + return $v_result; + } + // }}} + + // {{{ _addFile() + function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir) + { + if (!$this->_file) { + $this->_error('Invalid file descriptor'); + return false; + } + + if ($p_filename == '') { + $this->_error('Invalid file name'); + return false; + } + + // ----- Calculate the stored filename + $p_filename = $this->_translateWinPath($p_filename, false);; + $v_stored_filename = $p_filename; + if (strcmp($p_filename, $p_remove_dir) == 0) { + return true; + } + if ($p_remove_dir != '') { + if (substr($p_remove_dir, -1) != '/') + $p_remove_dir .= '/'; + + if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir) + $v_stored_filename = substr($p_filename, strlen($p_remove_dir)); + } + $v_stored_filename = $this->_translateWinPath($v_stored_filename); + if ($p_add_dir != '') { + if (substr($p_add_dir, -1) == '/') + $v_stored_filename = $p_add_dir.$v_stored_filename; + else + $v_stored_filename = $p_add_dir.'/'.$v_stored_filename; + } + + $v_stored_filename = $this->_pathReduction($v_stored_filename); + + if (is_file($p_filename)) { + if (($v_file = @fopen($p_filename, "rb")) == 0) { + $this->_warning("Unable to open file '$p_filename' in binary read mode"); + return true; + } + + if (!$this->_writeHeader($p_filename, $v_stored_filename)) + return false; + + while (($v_buffer = fread($v_file, 512)) != '') { + $v_binary_data = pack("a512", "$v_buffer"); + $this->_writeBlock($v_binary_data); + } + + fclose($v_file); + + } else { + // ----- Only header for dir + if (!$this->_writeHeader($p_filename, $v_stored_filename)) + return false; + } + + return true; + } + // }}} + + // {{{ _addString() + function _addString($p_filename, $p_string) + { + if (!$this->_file) { + $this->_error('Invalid file descriptor'); + return false; + } + + if ($p_filename == '') { + $this->_error('Invalid file name'); + return false; + } + + // ----- Calculate the stored filename + $p_filename = $this->_translateWinPath($p_filename, false);; + + if (!$this->_writeHeaderBlock($p_filename, strlen($p_string), 0, 0, "", 0, 0)) + return false; + + $i=0; + while (($v_buffer = substr($p_string, (($i++)*512), 512)) != '') { + $v_binary_data = pack("a512", $v_buffer); + $this->_writeBlock($v_binary_data); + } + + return true; + } + // }}} + + // {{{ _writeHeader() + function _writeHeader($p_filename, $p_stored_filename) + { + if ($p_stored_filename == '') + $p_stored_filename = $p_filename; + $v_reduce_filename = $this->_pathReduction($p_stored_filename); + + if (strlen($v_reduce_filename) > 99) { + if (!$this->_writeLongHeader($v_reduce_filename)) + return false; + } + + $v_info = stat($p_filename); + $v_uid = sprintf("%6s ", DecOct($v_info[4])); + $v_gid = sprintf("%6s ", DecOct($v_info[5])); + $v_perms = sprintf("%6s ", DecOct(fileperms($p_filename))); + + $v_mtime = sprintf("%11s", DecOct(filemtime($p_filename))); + + if (@is_dir($p_filename)) { + $v_typeflag = "5"; + $v_size = sprintf("%11s ", DecOct(0)); + } else { + $v_typeflag = ''; + clearstatcache(); + $v_size = sprintf("%11s ", DecOct(filesize($p_filename))); + } + + $v_linkname = ''; + + $v_magic = ''; + + $v_version = ''; + + $v_uname = ''; + + $v_gname = ''; + + $v_devmajor = ''; + + $v_devminor = ''; + + $v_prefix = ''; + + $v_binary_data_first = pack("a100a8a8a8a12A12", $v_reduce_filename, $v_perms, $v_uid, $v_gid, $v_size, $v_mtime); + $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", $v_typeflag, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, ''); + + // ----- Calculate the checksum + $v_checksum = 0; + // ..... First part of the header + for ($i=0; $i<148; $i++) + $v_checksum += ord(substr($v_binary_data_first,$i,1)); + // ..... Ignore the checksum value and replace it by ' ' (space) + for ($i=148; $i<156; $i++) + $v_checksum += ord(' '); + // ..... Last part of the header + for ($i=156, $j=0; $i<512; $i++, $j++) + $v_checksum += ord(substr($v_binary_data_last,$j,1)); + + // ----- Write the first 148 bytes of the header in the archive + $this->_writeBlock($v_binary_data_first, 148); + + // ----- Write the calculated checksum + $v_checksum = sprintf("%6s ", DecOct($v_checksum)); + $v_binary_data = pack("a8", $v_checksum); + $this->_writeBlock($v_binary_data, 8); + + // ----- Write the last 356 bytes of the header in the archive + $this->_writeBlock($v_binary_data_last, 356); + + return true; + } + // }}} + + // {{{ _writeHeaderBlock() + function _writeHeaderBlock($p_filename, $p_size, $p_mtime=0, $p_perms=0, $p_type='', $p_uid=0, $p_gid=0) + { + $p_filename = $this->_pathReduction($p_filename); + + if (strlen($p_filename) > 99) { + if (!$this->_writeLongHeader($p_filename)) + return false; + } + + if ($p_type == "5") { + $v_size = sprintf("%11s ", DecOct(0)); + } else { + $v_size = sprintf("%11s ", DecOct($p_size)); + } + + $v_uid = sprintf("%6s ", DecOct($p_uid)); + $v_gid = sprintf("%6s ", DecOct($p_gid)); + $v_perms = sprintf("%6s ", DecOct($p_perms)); + + $v_mtime = sprintf("%11s", DecOct($p_mtime)); + + $v_linkname = ''; + + $v_magic = ''; + + $v_version = ''; + + $v_uname = ''; + + $v_gname = ''; + + $v_devmajor = ''; + + $v_devminor = ''; + + $v_prefix = ''; + + $v_binary_data_first = pack("a100a8a8a8a12A12", $p_filename, $v_perms, $v_uid, $v_gid, $v_size, $v_mtime); + $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", $p_type, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, ''); + + // ----- Calculate the checksum + $v_checksum = 0; + // ..... First part of the header + for ($i=0; $i<148; $i++) + $v_checksum += ord(substr($v_binary_data_first,$i,1)); + // ..... Ignore the checksum value and replace it by ' ' (space) + for ($i=148; $i<156; $i++) + $v_checksum += ord(' '); + // ..... Last part of the header + for ($i=156, $j=0; $i<512; $i++, $j++) + $v_checksum += ord(substr($v_binary_data_last,$j,1)); + + // ----- Write the first 148 bytes of the header in the archive + $this->_writeBlock($v_binary_data_first, 148); + + // ----- Write the calculated checksum + $v_checksum = sprintf("%6s ", DecOct($v_checksum)); + $v_binary_data = pack("a8", $v_checksum); + $this->_writeBlock($v_binary_data, 8); + + // ----- Write the last 356 bytes of the header in the archive + $this->_writeBlock($v_binary_data_last, 356); + + return true; + } + // }}} + + // {{{ _writeLongHeader() + function _writeLongHeader($p_filename) + { + $v_size = sprintf("%11s ", DecOct(strlen($p_filename))); + + $v_typeflag = 'L'; + + $v_linkname = ''; + + $v_magic = ''; + + $v_version = ''; + + $v_uname = ''; + + $v_gname = ''; + + $v_devmajor = ''; + + $v_devminor = ''; + + $v_prefix = ''; + + $v_binary_data_first = pack("a100a8a8a8a12A12", '././@LongLink', 0, 0, 0, $v_size, 0); + $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", $v_typeflag, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, ''); + + // ----- Calculate the checksum + $v_checksum = 0; + // ..... First part of the header + for ($i=0; $i<148; $i++) + $v_checksum += ord(substr($v_binary_data_first,$i,1)); + // ..... Ignore the checksum value and replace it by ' ' (space) + for ($i=148; $i<156; $i++) + $v_checksum += ord(' '); + // ..... Last part of the header + for ($i=156, $j=0; $i<512; $i++, $j++) + $v_checksum += ord(substr($v_binary_data_last,$j,1)); + + // ----- Write the first 148 bytes of the header in the archive + $this->_writeBlock($v_binary_data_first, 148); + + // ----- Write the calculated checksum + $v_checksum = sprintf("%6s ", DecOct($v_checksum)); + $v_binary_data = pack("a8", $v_checksum); + $this->_writeBlock($v_binary_data, 8); + + // ----- Write the last 356 bytes of the header in the archive + $this->_writeBlock($v_binary_data_last, 356); + + // ----- Write the filename as content of the block + $i=0; + while (($v_buffer = substr($p_filename, (($i++)*512), 512)) != '') { + $v_binary_data = pack("a512", "$v_buffer"); + $this->_writeBlock($v_binary_data); + } + + return true; + } + // }}} + + // {{{ _readHeader() + function _readHeader($v_binary_data, &$v_header) + { + if (strlen($v_binary_data)==0) { + $v_header['filename'] = ''; + return true; + } + + if (strlen($v_binary_data) != 512) { + $v_header['filename'] = ''; + $this->_error('Invalid block size : '.strlen($v_binary_data)); + return false; + } + + // ----- Calculate the checksum + $v_checksum = 0; + // ..... First part of the header + for ($i=0; $i<148; $i++) + $v_checksum+=ord(substr($v_binary_data,$i,1)); + // ..... Ignore the checksum value and replace it by ' ' (space) + for ($i=148; $i<156; $i++) + $v_checksum += ord(' '); + // ..... Last part of the header + for ($i=156; $i<512; $i++) + $v_checksum+=ord(substr($v_binary_data,$i,1)); + + $v_data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor", $v_binary_data); + + // ----- Extract the checksum + $v_header['checksum'] = OctDec(trim($v_data['checksum'])); + if ($v_header['checksum'] != $v_checksum) { + $v_header['filename'] = ''; + + // ----- Look for last block (empty block) + if (($v_checksum == 256) && ($v_header['checksum'] == 0)) + return true; + + $this->_error('Invalid checksum for file "'.$v_data['filename'].'" : '.$v_checksum.' calculated, '.$v_header['checksum'].' expected'); + return false; + } + + // ----- Extract the properties + $v_header['filename'] = trim($v_data['filename']); + $v_header['mode'] = OctDec(trim($v_data['mode'])); + $v_header['uid'] = OctDec(trim($v_data['uid'])); + $v_header['gid'] = OctDec(trim($v_data['gid'])); + $v_header['size'] = OctDec(trim($v_data['size'])); + $v_header['mtime'] = OctDec(trim($v_data['mtime'])); + if (($v_header['typeflag'] = $v_data['typeflag']) == "5") { + $v_header['size'] = 0; + } + /* ----- All these fields are removed form the header because they do not carry interesting info + $v_header[link] = trim($v_data[link]); + $v_header[magic] = trim($v_data[magic]); + $v_header[version] = trim($v_data[version]); + $v_header[uname] = trim($v_data[uname]); + $v_header[gname] = trim($v_data[gname]); + $v_header[devmajor] = trim($v_data[devmajor]); + $v_header[devminor] = trim($v_data[devminor]); + */ + + return true; + } + // }}} + + // {{{ _readLongHeader() + function _readLongHeader(&$v_header) + { + $v_filename = ''; + $n = floor($v_header['size']/512); + for ($i=0; $i<$n; $i++) { + $v_content = $this->_readBlock(); + $v_filename .= $v_content; + } + if (($v_header['size'] % 512) != 0) { + $v_content = $this->_readBlock(); + $v_filename .= $v_content; + } + + // ----- Read the next header + $v_binary_data = $this->_readBlock(); + + if (!$this->_readHeader($v_binary_data, $v_header)) + return false; + + $v_header['filename'] = $v_filename; + + return true; + } + // }}} + + // {{{ _extractInString() + /** + * This method extract from the archive one file identified by $p_filename. + * The return value is a string with the file content, or NULL on error. + * @param string $p_filename The path of the file to extract in a string. + * @return a string with the file content or NULL. + * @access private + */ + function _extractInString($p_filename) + { + $v_result_str = ""; + + While (strlen($v_binary_data = $this->_readBlock()) != 0) + { + if (!$this->_readHeader($v_binary_data, $v_header)) + return NULL; + + if ($v_header['filename'] == '') + continue; + + // ----- Look for long filename + if ($v_header['typeflag'] == 'L') { + if (!$this->_readLongHeader($v_header)) + return NULL; + } + + if ($v_header['filename'] == $p_filename) { + if ($v_header['typeflag'] == "5") { + $this->_error('Unable to extract in string a directory entry {'.$v_header['filename'].'}'); + return NULL; + } else { + $n = floor($v_header['size']/512); + for ($i=0; $i<$n; $i++) { + $v_result_str .= $this->_readBlock(); + } + if (($v_header['size'] % 512) != 0) { + $v_content = $this->_readBlock(); + $v_result_str .= substr($v_content, 0, ($v_header['size'] % 512)); + } + return $v_result_str; + } + } else { + $this->_jumpBlock(ceil(($v_header['size']/512))); + } + } + + return NULL; + } + // }}} + + // {{{ _extractList() + function _extractList($p_path, &$p_list_detail, $p_mode, $p_file_list, $p_remove_path) + { + $v_result=true; + $v_nb = 0; + $v_extract_all = true; + $v_listing = false; + + $p_path = $this->_translateWinPath($p_path, false); + if ($p_path == '' || (substr($p_path, 0, 1) != '/' && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':'))) { + $p_path = "./".$p_path; + } + $p_remove_path = $this->_translateWinPath($p_remove_path); + + // ----- Look for path to remove format (should end by /) + if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/')) + $p_remove_path .= '/'; + $p_remove_path_size = strlen($p_remove_path); + + switch ($p_mode) { + case "complete" : + $v_extract_all = TRUE; + $v_listing = FALSE; + break; + case "partial" : + $v_extract_all = FALSE; + $v_listing = FALSE; + break; + case "list" : + $v_extract_all = FALSE; + $v_listing = TRUE; + break; + default : + $this->_error('Invalid extract mode ('.$p_mode.')'); + return false; + } + + clearstatcache(); + + While (strlen($v_binary_data = $this->_readBlock()) != 0) + { + $v_extract_file = FALSE; + $v_extraction_stopped = 0; + + if (!$this->_readHeader($v_binary_data, $v_header)) + return false; + + if ($v_header['filename'] == '') + continue; + + // ----- Look for long filename + if ($v_header['typeflag'] == 'L') { + if (!$this->_readLongHeader($v_header)) + return false; + } + + if ((!$v_extract_all) && (is_array($p_file_list))) { + // ----- By default no unzip if the file is not found + $v_extract_file = false; + + for ($i=0; $i<sizeof($p_file_list); $i++) { + // ----- Look if it is a directory + if (substr($p_file_list[$i], -1) == '/') { + // ----- Look if the directory is in the filename path + if ((strlen($v_header['filename']) > strlen($p_file_list[$i])) && (substr($v_header['filename'], 0, strlen($p_file_list[$i])) == $p_file_list[$i])) { + $v_extract_file = TRUE; + break; + } + } + + // ----- It is a file, so compare the file names + elseif ($p_file_list[$i] == $v_header['filename']) { + $v_extract_file = TRUE; + break; + } + } + } else { + $v_extract_file = TRUE; + } + + // ----- Look if this file need to be extracted + if (($v_extract_file) && (!$v_listing)) + { + if (($p_remove_path != '') + && (substr($v_header['filename'], 0, $p_remove_path_size) == $p_remove_path)) + $v_header['filename'] = substr($v_header['filename'], $p_remove_path_size); + if (($p_path != './') && ($p_path != '/')) { + while (substr($p_path, -1) == '/') + $p_path = substr($p_path, 0, strlen($p_path)-1); + + if (substr($v_header['filename'], 0, 1) == '/') + $v_header['filename'] = $p_path.$v_header['filename']; + else + $v_header['filename'] = $p_path.'/'.$v_header['filename']; + } + if (file_exists($v_header['filename'])) { + if ((@is_dir($v_header['filename'])) && ($v_header['typeflag'] == '')) { + $this->_error('File '.$v_header['filename'].' already exists as a directory'); + return false; + } + if ((is_file($v_header['filename'])) && ($v_header['typeflag'] == "5")) { + $this->_error('Directory '.$v_header['filename'].' already exists as a file'); + return false; + } + if (!is_writeable($v_header['filename'])) { + $this->_error('File '.$v_header['filename'].' already exists and is write protected'); + return false; + } + if (filemtime($v_header['filename']) > $v_header['mtime']) { + // To be completed : An error or silent no replace ? + } + } + + // ----- Check the directory availability and create it if necessary + elseif (($v_result = $this->_dirCheck(($v_header['typeflag'] == "5"?$v_header['filename']:dirname($v_header['filename'])))) != 1) { + $this->_error('Unable to create path for '.$v_header['filename']); + return false; + } + + if ($v_extract_file) { + if ($v_header['typeflag'] == "5") { + if (!@file_exists($v_header['filename'])) { + if (!@mkdir($v_header['filename'], 0777)) { + $this->_error('Unable to create directory {'.$v_header['filename'].'}'); + return false; + } + } + } else { + if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) { + $this->_error('Error while opening {'.$v_header['filename'].'} in write binary mode'); + return false; + } else { + $n = floor($v_header['size']/512); + for ($i=0; $i<$n; $i++) { + $v_content = $this->_readBlock(); + fwrite($v_dest_file, $v_content, 512); + } + if (($v_header['size'] % 512) != 0) { + $v_content = $this->_readBlock(); + fwrite($v_dest_file, $v_content, ($v_header['size'] % 512)); + } + + @fclose($v_dest_file); + + // ----- Change the file mode, mtime + @touch($v_header['filename'], $v_header['mtime']); + if ($v_header['mode'] & 0111) { + // make file executable, obey umask + $mode = fileperms($v_header['filename']) | (~umask() & 0111); + @chmod($v_header['filename'], $mode); + } + } + + // ----- Check the file size + clearstatcache(); + if (filesize($v_header['filename']) != $v_header['size']) { + $this->_error('Extracted file '.$v_header['filename'].' does not have the correct file size \''.filesize($v_filename).'\' ('.$v_header['size'].' expected). Archive may be corrupted.'); + return false; + } + } + } else { + $this->_jumpBlock(ceil(($v_header['size']/512))); + } + } else { + $this->_jumpBlock(ceil(($v_header['size']/512))); + } + + /* TBC : Seems to be unused ... + if ($this->_compress) + $v_end_of_file = @gzeof($this->_file); + else + $v_end_of_file = @feof($this->_file); + */ + + if ($v_listing || $v_extract_file || $v_extraction_stopped) { + // ----- Log extracted files + if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename']) + $v_file_dir = ''; + if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == '')) + $v_file_dir = '/'; + + $p_list_detail[$v_nb++] = $v_header; + } + } + + return true; + } + // }}} + + // {{{ _openAppend() + function _openAppend() + { + if (filesize($this->_tarname) == 0) + return $this->_openWrite(); + + if ($this->_compress) { + $this->_close(); + + if (!@rename($this->_tarname, $this->_tarname.".tmp")) { + $this->_error('Error while renaming \''.$this->_tarname.'\' to temporary file \''.$this->_tarname.'.tmp\''); + return false; + } + + if ($this->_compress_type == 'gz') + $v_temp_tar = @gzopen($this->_tarname.".tmp", "rb"); + elseif ($this->_compress_type == 'bz2') + $v_temp_tar = @bzopen($this->_tarname.".tmp", "rb"); + + if ($v_temp_tar == 0) { + $this->_error('Unable to open file \''.$this->_tarname.'.tmp\' in binary read mode'); + @rename($this->_tarname.".tmp", $this->_tarname); + return false; + } + + if (!$this->_openWrite()) { + @rename($this->_tarname.".tmp", $this->_tarname); + return false; + } + + if ($this->_compress_type == 'gz') { + $v_buffer = @gzread($v_temp_tar, 512); + + // ----- Read the following blocks but not the last one + if (!@gzeof($v_temp_tar)) { + do{ + $v_binary_data = pack("a512", $v_buffer); + $this->_writeBlock($v_binary_data); + $v_buffer = @gzread($v_temp_tar, 512); + + } while (!@gzeof($v_temp_tar)); + } + + @gzclose($v_temp_tar); + } + elseif ($this->_compress_type == 'bz2') { + $v_buffered_lines = array(); + $v_buffered_lines[] = @bzread($v_temp_tar, 512); + + // ----- Read the following blocks but not the last one + while (strlen($v_buffered_lines[] = @bzread($v_temp_tar, 512)) > 0) { + $v_binary_data = pack("a512", array_shift($v_buffered_lines)); + $this->_writeBlock($v_binary_data); + } + + @bzclose($v_temp_tar); + } + + if (!@unlink($this->_tarname.".tmp")) { + $this->_error('Error while deleting temporary file \''.$this->_tarname.'.tmp\''); + } + + } else { + // ----- For not compressed tar, just add files before the last 512 bytes block + if (!$this->_openReadWrite()) + return false; + + clearstatcache(); + $v_size = filesize($this->_tarname); + fseek($this->_file, $v_size-512); + } + + return true; + } + // }}} + + // {{{ _append() + function _append($p_filelist, $p_add_dir='', $p_remove_dir='') + { + if (!$this->_openAppend()) + return false; + + if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir)) + $this->_writeFooter(); + + $this->_close(); + + return true; + } + // }}} + + // {{{ _dirCheck() + + /** + * Check if a directory exists and create it (including parent + * dirs) if not. + * + * @param string $p_dir directory to check + * + * @return bool TRUE if the directory exists or was created + */ + function _dirCheck($p_dir) + { + if ((@is_dir($p_dir)) || ($p_dir == '')) + return true; + + $p_parent_dir = dirname($p_dir); + + if (($p_parent_dir != $p_dir) && + ($p_parent_dir != '') && + (!$this->_dirCheck($p_parent_dir))) + return false; + + if (!@mkdir($p_dir, 0777)) { + $this->_error("Unable to create directory '$p_dir'"); + return false; + } + + return true; + } + + // }}} + + // {{{ _pathReduction() + + /** + * Compress path by changing for example "/dir/foo/../bar" to "/dir/bar", and + * remove double slashes. + * + * @param string $p_dir path to reduce + * + * @return string reduced path + * + * @access private + * + */ + function _pathReduction($p_dir) + { + $v_result = ''; + + // ----- Look for not empty path + if ($p_dir != '') { + // ----- Explode path by directory names + $v_list = explode('/', $p_dir); + + // ----- Study directories from last to first + for ($i=sizeof($v_list)-1; $i>=0; $i--) { + // ----- Look for current path + if ($v_list[$i] == ".") { + // ----- Ignore this directory + // Should be the first $i=0, but no check is done + } + else if ($v_list[$i] == "..") { + // ----- Ignore it and ignore the $i-1 + $i--; + } + else if (($v_list[$i] == '') && ($i!=(sizeof($v_list)-1)) && ($i!=0)) { + // ----- Ignore only the double '//' in path, + // but not the first and last / + } else { + $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?'/'.$v_result:''); + } + } + } + $v_result = strtr($v_result, '\\', '/'); + return $v_result; + } + + // }}} + + // {{{ _translateWinPath() + function _translateWinPath($p_path, $p_remove_disk_letter=true) + { + if (OS_WINDOWS) { + // ----- Look for potential disk letter + if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) { + $p_path = substr($p_path, $v_position+1); + } + // ----- Change potential windows directory separator + if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) { + $p_path = strtr($p_path, '\\', '/'); + } + } + return $p_path; + } + // }}} + +} +?> diff --git a/pear/Archive/docs/Tar.txt b/pear/Archive/docs/Tar.txt new file mode 100644 index 000000000..73bee0d78 --- /dev/null +++ b/pear/Archive/docs/Tar.txt @@ -0,0 +1,424 @@ +Documentation for class Archive_Tar +=================================== +Last update : 2001-08-15 + + + +Overview : +---------- + + The Archive_Tar class helps in creating and managing GNU TAR format + files compressed by GNU ZIP or not. + The class offers basic functions like creating an archive, adding + files in the archive, extracting files from the archive and listing + the archive content. + It also provide advanced functions that allow the adding and + extraction of files with path manipulation. + + +Sample : +-------- + + // ----- Creating the object (uncompressed archive) + $tar_object = new Archive_Tar("tarname.tar"); + $tar_object->setErrorHandling(PEAR_ERROR_PRINT); + + // ----- Creating the archive + $v_list[0]="file.txt"; + $v_list[1]="data/"; + $v_list[2]="file.log"; + $tar_object->create($v_list); + + // ----- Adding files + $v_list[0]="dev/file.txt"; + $v_list[1]="dev/data/"; + $v_list[2]="log/file.log"; + $tar_object->add($v_list); + + // ----- Adding more files + $tar_object->add("release/newfile.log release/readme.txt"); + + // ----- Listing the content + if (($v_list = $tar_object->listContent()) != 0) + for ($i=0; $i<sizeof($v_list); $i++) + { + echo "Filename :'".$v_list[$i][filename]."'<br>"; + echo " .size :'".$v_list[$i][size]."'<br>"; + echo " .mtime :'".$v_list[$i][mtime]."' (".date("l dS of F Y h:i:s A", $v_list[$i][mtime]).")<br>"; + echo " .mode :'".$v_list[$i][mode]."'<br>"; + echo " .uid :'".$v_list[$i][uid]."'<br>"; + echo " .gid :'".$v_list[$i][gid]."'<br>"; + echo " .typeflag :'".$v_list[$i][typeflag]."'<br>"; + } + + // ----- Extracting the archive in directory "install" + $tar_object->extract("install"); + + +Public arguments : +------------------ + +None + + +Public Methods : +---------------- + +Method : Archive_Tar($p_tarname, $compress = false) +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 compressed TAR file. +Arguments : + $p_tarname : A valid filename for the tar archive file. + $p_compress : true/false. Indicate if the archive need to be + compressed or not. +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 : 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 : listContent() +Description : + This method returns an array of arrays that describe each + file/directory present in the archive. + The array is not sorted, so it show the position of the file in the + archive. + The file informations are : + $file[filename] : Name and path of the file/dir. + $file[mode] : File permissions (result of fileperms()) + $file[uid] : user id + $file[gid] : group id + $file[size] : filesize + $file[mtime] : Last modification time (result of filemtime()) + $file[typeflag] : "" for file, "5" for directory +Arguments : +Return value : + An array of arrays or 0 on error. +Sample : + $tar_object = new Archive_Tar("tarname.tar"); + if (($v_list = $tar_object->listContent()) != 0) + for ($i=0; $i<sizeof($v_list); $i++) + { + echo "Filename :'".$v_list[$i][filename]."'<br>"; + echo " .size :'".$v_list[$i][size]."'<br>"; + echo " .mtime :'".$v_list[$i][mtime]."' (". + date("l dS of F Y h:i:s A", $v_list[$i][mtime]).")<br>"; + echo " .mode :'".$v_list[$i][mode]."'<br>"; + echo " .uid :'".$v_list[$i][uid]."'<br>"; + echo " .gid :'".$v_list[$i][gid]."'<br>"; + echo " .typeflag :'".$v_list[$i][typeflag]."'<br>"; + } +How it works : + Call the same function as an extract however with a flag to only go + through the archive without extracting the files. + +Method : extractList($p_filelist, $p_path = "", $p_remove_path = "") +Description : + This method extract from the archive only the files indicated in the + $p_filelist. These files are extracted in the current directory or + in the directory indicated by the optional $p_path parameter. + If indicated the $p_remove_path can be used in the same way as it is + used in extractModify() method. +Arguments : + $p_filelist : An array of filenames and directory names, or a single + string with names separated by a single blank space. + $p_path : The path of the directory where the files/dir need to by + extracted. + $p_remove_path : Part of the memorized path that can be removed if + present at the beginning of the file/dir path. +Return value : + true on success, false on error. +Sample : + // Imagine tarname.tar with files : + // dev/data/file.txt + // dev/data/log.txt + // readme.txt + $tar_object = new Archive_Tar("tarname.tar"); + $tar_object->extractList("dev/data/file.txt readme.txt", "install", + "dev"); + // Files will be extracted there : + // install/data/file.txt + // install/readme.txt +How it works : + Go through the archive and extract only the files present in the + list. + diff --git a/pear/CODING_STANDARDS b/pear/CODING_STANDARDS new file mode 100644 index 000000000..0d313fad0 --- /dev/null +++ b/pear/CODING_STANDARDS @@ -0,0 +1,8 @@ +=========================================================================== +| PEAR Coding Standards | +=========================================================================== + +$Id: CODING_STANDARDS,v 1.18 2004/05/04 10:43:24 mj Exp $ + +This document is no longer maintained, see +http://pear.php.net/manual/en/standards.php instead. diff --git a/pear/Console/Getopt.php b/pear/Console/Getopt.php new file mode 100644 index 000000000..17ee25dc7 --- /dev/null +++ b/pear/Console/Getopt.php @@ -0,0 +1,251 @@ +<?php +/* vim: set expandtab tabstop=4 shiftwidth=4: */ +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Andrei Zmievski <andrei@php.net> | +// +----------------------------------------------------------------------+ +// +// $Id: Getopt.php,v 1.28.4.1 2005/03/01 18:20:26 andrei Exp $ + +require_once 'PEAR.php'; + +/** + * Command-line options parsing class. + * + * @author Andrei Zmievski <andrei@php.net> + * + */ +class Console_Getopt { + /** + * Parses the command-line options. + * + * The first parameter to this function should be the list of command-line + * arguments without the leading reference to the running program. + * + * The second parameter is a string of allowed short options. Each of the + * option letters can be followed by a colon ':' to specify that the option + * requires an argument, or a double colon '::' to specify that the option + * takes an optional argument. + * + * The third argument is an optional array of allowed long options. The + * leading '--' should not be included in the option name. Options that + * require an argument should be followed by '=', and options that take an + * option argument should be followed by '=='. + * + * The return value is an array of two elements: the list of parsed + * options and the list of non-option command-line arguments. Each entry in + * the list of parsed options is a pair of elements - the first one + * specifies the option, and the second one specifies the option argument, + * if there was one. + * + * Long and short options can be mixed. + * + * Most of the semantics of this function are based on GNU getopt_long(). + * + * @param array $args an array of command-line arguments + * @param string $short_options specifies the list of allowed short options + * @param array $long_options specifies the list of allowed long options + * + * @return array two-element array containing the list of parsed options and + * the non-option arguments + * + * @access public + * + */ + function getopt2($args, $short_options, $long_options = null) + { + return Console_Getopt::doGetopt(2, $args, $short_options, $long_options); + } + + /** + * This function expects $args to start with the script name (POSIX-style). + * Preserved for backwards compatibility. + * @see getopt2() + */ + function getopt($args, $short_options, $long_options = null) + { + return Console_Getopt::doGetopt(1, $args, $short_options, $long_options); + } + + /** + * The actual implementation of the argument parsing code. + */ + function doGetopt($version, $args, $short_options, $long_options = null) + { + // in case you pass directly readPHPArgv() as the first arg + if (PEAR::isError($args)) { + return $args; + } + if (empty($args)) { + return array(array(), array()); + } + $opts = array(); + $non_opts = array(); + + settype($args, 'array'); + + if ($long_options) { + sort($long_options); + } + + /* + * Preserve backwards compatibility with callers that relied on + * erroneous POSIX fix. + */ + if ($version < 2) { + if (isset($args[0]{0}) && $args[0]{0} != '-') { + array_shift($args); + } + } + + reset($args); + while (list($i, $arg) = each($args)) { + + /* The special element '--' means explicit end of + options. Treat the rest of the arguments as non-options + and end the loop. */ + if ($arg == '--') { + $non_opts = array_merge($non_opts, array_slice($args, $i + 1)); + break; + } + + if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) { + $non_opts = array_merge($non_opts, array_slice($args, $i)); + break; + } elseif (strlen($arg) > 1 && $arg{1} == '-') { + $error = Console_Getopt::_parseLongOption(substr($arg, 2), $long_options, $opts, $args); + if (PEAR::isError($error)) + return $error; + } else { + $error = Console_Getopt::_parseShortOption(substr($arg, 1), $short_options, $opts, $args); + if (PEAR::isError($error)) + return $error; + } + } + + return array($opts, $non_opts); + } + + /** + * @access private + * + */ + function _parseShortOption($arg, $short_options, &$opts, &$args) + { + for ($i = 0; $i < strlen($arg); $i++) { + $opt = $arg{$i}; + $opt_arg = null; + + /* Try to find the short option in the specifier string. */ + if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':') + { + return PEAR::raiseError("Console_Getopt: unrecognized option -- $opt"); + } + + if (strlen($spec) > 1 && $spec{1} == ':') { + if (strlen($spec) > 2 && $spec{2} == ':') { + if ($i + 1 < strlen($arg)) { + /* Option takes an optional argument. Use the remainder of + the arg string if there is anything left. */ + $opts[] = array($opt, substr($arg, $i + 1)); + break; + } + } else { + /* Option requires an argument. Use the remainder of the arg + string if there is anything left. */ + if ($i + 1 < strlen($arg)) { + $opts[] = array($opt, substr($arg, $i + 1)); + break; + } else if (list(, $opt_arg) = each($args)) + /* Else use the next argument. */; + else + return PEAR::raiseError("Console_Getopt: option requires an argument -- $opt"); + } + } + + $opts[] = array($opt, $opt_arg); + } + } + + /** + * @access private + * + */ + function _parseLongOption($arg, $long_options, &$opts, &$args) + { + @list($opt, $opt_arg) = explode('=', $arg, 2); + $opt_len = strlen($opt); + + for ($i = 0; $i < count($long_options); $i++) { + $long_opt = $long_options[$i]; + $opt_start = substr($long_opt, 0, $opt_len); + + /* Option doesn't match. Go on to the next one. */ + if ($opt_start != $opt) + continue; + + $opt_rest = substr($long_opt, $opt_len); + + /* Check that the options uniquely matches one of the allowed + options. */ + if ($opt_rest != '' && $opt{0} != '=' && + $i + 1 < count($long_options) && + $opt == substr($long_options[$i+1], 0, $opt_len)) { + return PEAR::raiseError("Console_Getopt: option --$opt is ambiguous"); + } + + if (substr($long_opt, -1) == '=') { + if (substr($long_opt, -2) != '==') { + /* Long option requires an argument. + Take the next argument if one wasn't specified. */; + if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) { + return PEAR::raiseError("Console_Getopt: option --$opt requires an argument"); + } + } + } else if ($opt_arg) { + return PEAR::raiseError("Console_Getopt: option --$opt doesn't allow an argument"); + } + + $opts[] = array('--' . $opt, $opt_arg); + return; + } + + return PEAR::raiseError("Console_Getopt: unrecognized option --$opt"); + } + + /** + * Safely read the $argv PHP array across different PHP configurations. + * Will take care on register_globals and register_argc_argv ini directives + * + * @access public + * @return mixed the $argv PHP array or PEAR error if not registered + */ + function readPHPArgv() + { + global $argv; + if (!is_array($argv)) { + if (!@is_array($_SERVER['argv'])) { + if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) { + return PEAR::raiseError("Console_Getopt: Could not read cmd args (register_argc_argv=Off?)"); + } + return $GLOBALS['HTTP_SERVER_VARS']['argv']; + } + return $_SERVER['argv']; + } + return $argv; + } + +} + +?> diff --git a/pear/Console/tests/001-getopt.phpt b/pear/Console/tests/001-getopt.phpt new file mode 100644 index 000000000..3985dc9be --- /dev/null +++ b/pear/Console/tests/001-getopt.phpt @@ -0,0 +1,68 @@ +--TEST-- +Console_Getopt +--SKIPIF-- +skip +--FILE-- +<?php + +error_reporting(E_ALL); +chdir(dirname(__FILE__)); +include "../Getopt.php"; +PEAR::setErrorHandling(PEAR_ERROR_PRINT, "%s\n\n"); + +function test($argstr, $optstr) { + $argv = split('[[:space:]]+', $argstr); + if (PEAR::isError($options = Console_Getopt::getopt($argv, $optstr))) { + return; + } + $opts = $options[0]; + $non_opts = $options[1]; + $i = 0; + print "options: "; + foreach ($opts as $o => $d) { + if ($i++ > 0) { + print ", "; + } + print $d[0] . '=' . $d[1]; + } + print "\n"; + print "params: " . implode(", ", $non_opts) . "\n"; + print "\n"; +} + +test("-abc", "abc"); +test("-abc foo", "abc"); +test("-abc foo", "abc:"); +test("-abc foo bar gazonk", "abc"); +test("-abc foo bar gazonk", "abc:"); +test("-a -b -c", "abc"); +test("-a -b -c", "abc:"); +test("-abc", "ab:c"); +test("-abc foo -bar gazonk", "abc"); +?> +--EXPECT-- +options: a=, b=, c= +params: + +options: a=, b=, c= +params: foo + +options: a=, b=, c=foo +params: + +options: a=, b=, c= +params: foo, bar, gazonk + +options: a=, b=, c=foo +params: bar, gazonk + +options: a=, b=, c= +params: + +Console_Getopt: option requires an argument -- c + +options: a=, b=c +params: + +options: a=, b=, c= +params: foo, -bar, gazonk diff --git a/pear/Makefile.frag b/pear/Makefile.frag new file mode 100644 index 000000000..743fa9dae --- /dev/null +++ b/pear/Makefile.frag @@ -0,0 +1,22 @@ +# -*- makefile -*- + +peardir=$(PEAR_INSTALLDIR) + +# Skip all php.ini files altogether +PEAR_INSTALL_FLAGS = -n -dshort_open_tag=0 -dsafe_mode=0 + +install-pear-installer: $(top_builddir)/sapi/cli/php + @$(top_builddir)/sapi/cli/php $(PEAR_INSTALL_FLAGS) $(srcdir)/install-pear.php -d "$(peardir)" -b "$(bindir)" $(srcdir)/package-*.xml + +install-pear-packages: $(top_builddir)/sapi/cli/php + @$(top_builddir)/sapi/cli/php $(PEAR_INSTALL_FLAGS) $(srcdir)/install-pear.php -d "$(peardir)" -b "$(bindir)" $(srcdir)/packages/*.tar + +install-pear: + @echo "Installing PEAR environment: $(INSTALL_ROOT)$(peardir)/" + @if $(mkinstalldirs) $(INSTALL_ROOT)$(peardir); then \ + $(MAKE) -s install-pear-installer install-pear-packages; \ + else \ + cat $(srcdir)/install-pear.txt; \ + exit 5; \ + fi + diff --git a/pear/OS/Guess.php b/pear/OS/Guess.php new file mode 100644 index 000000000..8b536b053 --- /dev/null +++ b/pear/OS/Guess.php @@ -0,0 +1,287 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Authors: Stig Bakken <ssb@php.net> | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: Guess.php,v 1.13.4.1 2005/03/28 16:46:06 cellog Exp $ + +// {{{ uname examples + +// php_uname() without args returns the same as 'uname -a', or a PHP-custom +// string for Windows. +// PHP versions prior to 4.3 return the uname of the host where PHP was built, +// as of 4.3 it returns the uname of the host running the PHP code. +// +// PC RedHat Linux 7.1: +// Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown +// +// PC Debian Potato: +// Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown +// +// PC FreeBSD 3.3: +// FreeBSD host.example.com 3.3-STABLE FreeBSD 3.3-STABLE #0: Mon Feb 21 00:42:31 CET 2000 root@example.com:/usr/src/sys/compile/CONFIG i386 +// +// PC FreeBSD 4.3: +// FreeBSD host.example.com 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Mon Jun 25 11:19:43 EDT 2001 root@example.com:/usr/src/sys/compile/CONFIG i386 +// +// PC FreeBSD 4.5: +// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb 6 23:59:23 CET 2002 root@example.com:/usr/src/sys/compile/CONFIG i386 +// +// PC FreeBSD 4.5 w/uname from GNU shellutils: +// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb i386 unknown +// +// HP 9000/712 HP-UX 10: +// HP-UX iq B.10.10 A 9000/712 2008429113 two-user license +// +// HP 9000/712 HP-UX 10 w/uname from GNU shellutils: +// HP-UX host B.10.10 A 9000/712 unknown +// +// IBM RS6000/550 AIX 4.3: +// AIX host 3 4 000003531C00 +// +// AIX 4.3 w/uname from GNU shellutils: +// AIX host 3 4 000003531C00 unknown +// +// SGI Onyx IRIX 6.5 w/uname from GNU shellutils: +// IRIX64 host 6.5 01091820 IP19 mips +// +// SGI Onyx IRIX 6.5: +// IRIX64 host 6.5 01091820 IP19 +// +// SparcStation 20 Solaris 8 w/uname from GNU shellutils: +// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc +// +// SparcStation 20 Solaris 8: +// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20 +// +// Mac OS X (Darwin) +// Darwin home-eden.local 7.5.0 Darwin Kernel Version 7.5.0: Thu Aug 5 19:26:16 PDT 2004; root:xnu/xnu-517.7.21.obj~3/RELEASE_PPC Power Macintosh +// +// Mac OS X early versions +// + +// }}} + +/* TODO: + * - define endianness, to allow matchSignature("bigend") etc. + */ + +class OS_Guess +{ + var $sysname; + var $nodename; + var $cpu; + var $release; + var $extra; + + function OS_Guess($uname = null) + { + list($this->sysname, + $this->release, + $this->cpu, + $this->extra, + $this->nodename) = $this->parseSignature($uname); + } + + function parseSignature($uname = null) + { + static $sysmap = array( + 'HP-UX' => 'hpux', + 'IRIX64' => 'irix', + ); + static $cpumap = array( + 'i586' => 'i386', + 'i686' => 'i386', + 'ppc' => 'powerpc', + ); + if ($uname === null) { + $uname = php_uname(); + } + $parts = split('[[:space:]]+', trim($uname)); + $n = count($parts); + + $release = $machine = $cpu = ''; + $sysname = $parts[0]; + $nodename = $parts[1]; + $cpu = $parts[$n-1]; + $extra = ''; + if ($cpu == 'unknown') { + $cpu = $parts[$n-2]; + } + + switch ($sysname) { + case 'AIX': + $release = "$parts[3].$parts[2]"; + break; + case 'Windows': + switch ($parts[1]) { + case '95/98': + $release = '9x'; + break; + default: + $release = $parts[1]; + break; + } + $cpu = 'i386'; + break; + case 'Linux': + $extra = $this->_detectGlibcVersion(); + // use only the first two digits from the kernel version + $release = ereg_replace('^([[:digit:]]+\.[[:digit:]]+).*', '\1', $parts[2]); + break; + case 'Mac' : + $sysname = 'darwin'; + $nodename = $parts[2]; + $release = $parts[3]; + if ($cpu == 'Macintosh') { + if ($parts[$n - 2] == 'Power') { + $cpu = 'powerpc'; + } + } + break; + case 'Darwin' : + if ($cpu == 'Macintosh') { + if ($parts[$n - 2] == 'Power') { + $cpu = 'powerpc'; + } + } + $release = ereg_replace('^([[:digit:]]+\.[[:digit:]]+).*', '\1', $parts[2]); + break; + default: + $release = ereg_replace('-.*', '', $parts[2]); + break; + } + + + if (isset($sysmap[$sysname])) { + $sysname = $sysmap[$sysname]; + } else { + $sysname = strtolower($sysname); + } + if (isset($cpumap[$cpu])) { + $cpu = $cpumap[$cpu]; + } + return array($sysname, $release, $cpu, $extra, $nodename); + } + + function _detectGlibcVersion() + { + // Use glibc's <features.h> header file to + // get major and minor version number: + include_once "System.php"; + $tmpfile = System::mktemp("glibctest"); + $fp = fopen($tmpfile, "w"); + fwrite($fp, "#include <features.h>\n__GLIBC__ __GLIBC_MINOR__\n"); + fclose($fp); + $cpp = popen("/usr/bin/cpp $tmpfile", "r"); + $major = $minor = 0; + while ($line = fgets($cpp, 1024)) { + if ($line{0} == '#' || trim($line) == '') { + continue; + } + if (list($major, $minor) = explode(' ', trim($line))) { + break; + } + } + pclose($cpp); + unlink($tmpfile); + if (!($major && $minor) && is_link('/lib/libc.so.6')) { + // Let's try reading the libc.so.6 symlink + if (ereg('^libc-([.*])\.so$', basename(readlink('/lib/libc.so.6')), $matches)) { + list($major, $minor) = explode('.', $matches); + } + } + if (!($major && $minor)) { + return ''; + } + return "glibc{$major}.{$minor}"; + } + + function getSignature() + { + if (empty($this->extra)) { + return "{$this->sysname}-{$this->release}-{$this->cpu}"; + } + return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}"; + } + + function getSysname() + { + return $this->sysname; + } + + function getNodename() + { + return $this->nodename; + } + + function getCpu() + { + return $this->cpu; + } + + function getRelease() + { + return $this->release; + } + + function getExtra() + { + return $this->extra; + } + + function matchSignature($match) + { + if (is_array($match)) { + $fragments = $match; + } else { + $fragments = explode('-', $match); + } + $n = count($fragments); + $matches = 0; + if ($n > 0) { + $matches += $this->_matchFragment($fragments[0], $this->sysname); + } + if ($n > 1) { + $matches += $this->_matchFragment($fragments[1], $this->release); + } + if ($n > 2) { + $matches += $this->_matchFragment($fragments[2], $this->cpu); + } + if ($n > 3) { + $matches += $this->_matchFragment($fragments[3], $this->extra); + } + return ($matches == $n); + } + + function _matchFragment($fragment, $value) + { + if (strcspn($fragment, '*?') < strlen($fragment)) { + $reg = '^' . str_replace(array('*', '?', '/'), array('.*', '.', '\\/'), $fragment) . '$'; + return eregi($reg, $value); + } + return ($fragment == '*' || !strcasecmp($fragment, $value)); + } + +} +/* + * Local Variables: + * indent-tabs-mode: nil + * c-basic-offset: 4 + * End: + */ +?> diff --git a/pear/PEAR.php b/pear/PEAR.php new file mode 100644 index 000000000..865b8a155 --- /dev/null +++ b/pear/PEAR.php @@ -0,0 +1,1055 @@ +<?php +// +// +--------------------------------------------------------------------+ +// | PEAR, the PHP Extension and Application Repository | +// +--------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +--------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +--------------------------------------------------------------------+ +// | Authors: Sterling Hughes <sterling@php.net> | +// | Stig Bakken <ssb@php.net> | +// | Tomas V.V.Cox <cox@idecnet.com> | +// +--------------------------------------------------------------------+ +// +// $Id: PEAR.php,v 1.82.2.1 2005/03/28 16:46:06 cellog Exp $ +// + +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); +define('PEAR_ZE2', (function_exists('version_compare') && + version_compare(zend_version(), "2-dev", "ge"))); + +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 +} + +// instant backwards compatibility +if (!defined('PATH_SEPARATOR')) { + if (OS_WINDOWS) { + define('PATH_SEPARATOR', ';'); + } else { + define('PATH_SEPARATOR', ':'); + } +} + +$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; + * + * @since PHP 4.0.2 + * @author Stig Bakken <ssb@php.net> + * @see http://pear.php.net/manual/ + */ +class PEAR +{ + // {{{ properties + + /** + * 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(); + + // }}} + + // {{{ constructor + + /** + * 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 PEAR($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); + } + } + } + + // }}} + // {{{ destructor + + /** + * 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))); + } + } + + // }}} + // {{{ getStaticProperty() + + /** + * 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! + * + * @access public + * @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. + */ + function &getStaticProperty($class, $var) + { + static $properties; + return $properties[$class][$var]; + } + + // }}} + // {{{ registerShutdownFunc() + + /** + * Use this function to register a shutdown method for static + * classes. + * + * @access public + * @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 + */ + function registerShutdownFunc($func, $args = array()) + { + $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args); + } + + // }}} + // {{{ isError() + + /** + * 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 + * @access public + * @return bool true if parameter is an error + */ + function isError($data, $code = null) + { + if (is_a($data, 'PEAR_Error')) { + if (is_null($code)) { + return true; + } elseif (is_string($code)) { + return $data->getMessage() == $code; + } else { + return $data->getCode() == $code; + } + } + return false; + } + + // }}} + // {{{ setErrorHandling() + + /** + * 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 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 + */ + + function setErrorHandling($mode = null, $options = null) + { + if (isset($this) && is_a($this, 'PEAR')) { + $setmode = &$this->_default_error_mode; + $setoptions = &$this->_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; + } + } + + // }}} + // {{{ expectError() + + /** + * 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 sizeof($this->_expected_errors); + } + + // }}} + // {{{ popExpect() + + /** + * 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); + } + + // }}} + // {{{ _checkDelExpect() + + /** + * 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; + } + + // }}} + // {{{ delExpect() + + /** + * This method deletes all occurences 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) { + if ($this->_checkDelExpect($error)) { + $deleted = true; + } else { + $deleted = 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; + } else { + return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME + } + } else { + // $error_code is empty + return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME + } + } + + // }}} + // {{{ raiseError() + + /** + * 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. + * + * @access public + * @return object a PEAR error object + * @see PEAR::setErrorHandling + * @since PHP 4.0.5 + */ + function raiseError($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 (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_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 (isset($this) && isset($this->_default_error_mode)) { + $mode = $this->_default_error_mode; + $options = $this->_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 (isset($this) && isset($this->_error_class)) { + $ec = $this->_error_class; + } else { + $ec = 'PEAR_Error'; + } + if ($skipmsg) { + return new $ec($code, $mode, $options, $userinfo); + } else { + return new $ec($message, $code, $mode, $options, $userinfo); + } + } + + // }}} + // {{{ throwError() + + /** + * Simpler form of raiseError with fewer options. In most cases + * message, code and userinfo are enough. + * + * @param string $message + * + */ + function throwError($message = null, + $code = null, + $userinfo = null) + { + if (isset($this) && is_a($this, 'PEAR')) { + return $this->raiseError($message, $code, null, null, $userinfo); + } else { + return PEAR::raiseError($message, $code, null, null, $userinfo); + } + } + + // }}} + 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; + } + + 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; + } + + // {{{ pushErrorHandling() + + /** + * 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 + */ + function pushErrorHandling($mode, $options = null) + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + if (isset($this) && is_a($this, 'PEAR')) { + $def_mode = &$this->_default_error_mode; + $def_options = &$this->_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 (isset($this) && is_a($this, 'PEAR')) { + $this->setErrorHandling($mode, $options); + } else { + PEAR::setErrorHandling($mode, $options); + } + $stack[] = array($mode, $options); + return true; + } + + // }}} + // {{{ popErrorHandling() + + /** + * Pop the last error handler used + * + * @return bool Always true + * + * @see PEAR::pushErrorHandling + */ + function popErrorHandling() + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + array_pop($stack); + list($mode, $options) = $stack[sizeof($stack) - 1]; + array_pop($stack); + if (isset($this) && is_a($this, 'PEAR')) { + $this->setErrorHandling($mode, $options); + } else { + PEAR::setErrorHandling($mode, $options); + } + return true; + } + + // }}} + // {{{ loadExtension() + + /** + * OS independant 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 + */ + function loadExtension($ext) + { + if (!extension_loaded($ext)) { + // if either returns true dl() will produce a FATAL error, stop that + if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 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); + } + return true; + } + + // }}} +} + +// {{{ _PEAR_call_destructors() + +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); + if (@PEAR::getStaticProperty('PEAR', 'destructlifo')) { + $_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 (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) { + foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) { + call_user_func_array($value[0], $value[1]); + } + } +} + +// }}} + +class PEAR_Error +{ + // {{{ properties + + var $error_message_prefix = ''; + var $mode = PEAR_ERROR_RETURN; + var $level = E_USER_NOTICE; + var $code = -1; + var $message = ''; + var $userinfo = ''; + var $backtrace = null; + + // }}} + // {{{ constructor + + /** + * 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 PEAR_Error($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; + if (function_exists("debug_backtrace")) { + if (@!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) { + $this->backtrace = debug_backtrace(); + } + } + 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; + } + die(sprintf($format, $msg)); + } + if ($this->mode & PEAR_ERROR_CALLBACK) { + if (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_ErrorStack for exceptions", E_USER_WARNING); + eval('$e = new Exception($this->message, $this->code);$e->PEAR_Error = $this;throw($e);'); + } + } + + // }}} + // {{{ getMode() + + /** + * Get the error mode from an error object. + * + * @return int error mode + * @access public + */ + function getMode() { + return $this->mode; + } + + // }}} + // {{{ getCallback() + + /** + * Get the callback function/method from an error object. + * + * @return mixed callback function or object/method array + * @access public + */ + function getCallback() { + return $this->callback; + } + + // }}} + // {{{ getMessage() + + + /** + * Get the error message from an error object. + * + * @return string full error message + * @access public + */ + function getMessage() + { + return ($this->error_message_prefix . $this->message); + } + + + // }}} + // {{{ getCode() + + /** + * Get error code from an error object + * + * @return int error code + * @access public + */ + function getCode() + { + return $this->code; + } + + // }}} + // {{{ getType() + + /** + * Get the name of this error/exception. + * + * @return string error/exception name (type) + * @access public + */ + function getType() + { + return get_class($this); + } + + // }}} + // {{{ getUserInfo() + + /** + * Get additional user-supplied information. + * + * @return string user-supplied information + * @access public + */ + function getUserInfo() + { + return $this->userinfo; + } + + // }}} + // {{{ getDebugInfo() + + /** + * Get additional debug information supplied by the application. + * + * @return string debug information + * @access public + */ + function getDebugInfo() + { + return $this->getUserInfo(); + } + + // }}} + // {{{ getBacktrace() + + /** + * 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 ($frame === null) { + return $this->backtrace; + } + return $this->backtrace[$frame]; + } + + // }}} + // {{{ addUserInfo() + + function addUserInfo($info) + { + if (empty($this->userinfo)) { + $this->userinfo = $info; + } else { + $this->userinfo .= " ** $info"; + } + } + + // }}} + // {{{ toString() + + /** + * 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: + */ +?> diff --git a/pear/PEAR/Autoloader.php b/pear/PEAR/Autoloader.php new file mode 100644 index 000000000..de0278d61 --- /dev/null +++ b/pear/PEAR/Autoloader.php @@ -0,0 +1,208 @@ +<?php +// /* vim: set expandtab tabstop=4 shiftwidth=4: */ +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Stig Bakken <ssb@php.net> | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: Autoloader.php,v 1.11 2004/02/27 02:21:29 cellog Exp $ + +if (!extension_loaded("overload")) { + // die hard without ext/overload + die("Rebuild PHP with the `overload' extension to use PEAR_Autoloader"); +} + +require_once "PEAR.php"; + +/** + * This class is for objects where you want to separate the code for + * some methods into separate classes. This is useful if you have a + * class with not-frequently-used methods that contain lots of code + * that you would like to avoid always parsing. + * + * The PEAR_Autoloader class provides autoloading and aggregation. + * The autoloading lets you set up in which classes the separated + * methods are found. Aggregation is the technique used to import new + * methods, an instance of each class providing separated methods is + * stored and called every time the aggregated method is called. + * + * @author Stig Sæther Bakken <ssb@php.net> + */ +class PEAR_Autoloader extends PEAR +{ + // {{{ properties + + /** + * Map of methods and classes where they are defined + * + * @var array + * + * @access private + */ + var $_autoload_map = array(); + + /** + * Map of methods and aggregate objects + * + * @var array + * + * @access private + */ + var $_method_map = array(); + + // }}} + // {{{ addAutoload() + + /** + * Add one or more autoload entries. + * + * @param string $method which method to autoload + * + * @param string $classname (optional) which class to find the method in. + * If the $method parameter is an array, this + * parameter may be omitted (and will be ignored + * if not), and the $method parameter will be + * treated as an associative array with method + * names as keys and class names as values. + * + * @return void + * + * @access public + */ + function addAutoload($method, $classname = null) + { + if (is_array($method)) { + array_walk($method, create_function('$a,&$b', '$b = strtolower($b);')); + $this->_autoload_map = array_merge($this->_autoload_map, $method); + } else { + $this->_autoload_map[strtolower($method)] = $classname; + } + } + + // }}} + // {{{ removeAutoload() + + /** + * Remove an autoload entry. + * + * @param string $method which method to remove the autoload entry for + * + * @return bool TRUE if an entry was removed, FALSE if not + * + * @access public + */ + function removeAutoload($method) + { + $method = strtolower($method); + $ok = isset($this->_autoload_map[$method]); + unset($this->_autoload_map[$method]); + return $ok; + } + + // }}} + // {{{ addAggregateObject() + + /** + * Add an aggregate object to this object. If the specified class + * is not defined, loading it will be attempted following PEAR's + * file naming scheme. All the methods in the class will be + * aggregated, except private ones (name starting with an + * underscore) and constructors. + * + * @param string $classname what class to instantiate for the object. + * + * @return void + * + * @access public + */ + function addAggregateObject($classname) + { + $classname = strtolower($classname); + if (!class_exists($classname)) { + $include_file = preg_replace('/[^a-z0-9]/i', '_', $classname); + include_once $include_file; + } + $obj =& new $classname; + $methods = get_class_methods($classname); + foreach ($methods as $method) { + // don't import priviate methods and constructors + if ($method{0} != '_' && $method != $classname) { + $this->_method_map[$method] = $obj; + } + } + } + + // }}} + // {{{ removeAggregateObject() + + /** + * Remove an aggregate object. + * + * @param string $classname the class of the object to remove + * + * @return bool TRUE if an object was removed, FALSE if not + * + * @access public + */ + function removeAggregateObject($classname) + { + $ok = false; + $classname = strtolower($classname); + reset($this->_method_map); + while (list($method, $obj) = each($this->_method_map)) { + if (is_a($obj, $classname)) { + unset($this->_method_map[$method]); + $ok = true; + } + } + return $ok; + } + + // }}} + // {{{ __call() + + /** + * Overloaded object call handler, called each time an + * undefined/aggregated method is invoked. This method repeats + * the call in the right aggregate object and passes on the return + * value. + * + * @param string $method which method that was called + * + * @param string $args An array of the parameters passed in the + * original call + * + * @return mixed The return value from the aggregated method, or a PEAR + * error if the called method was unknown. + */ + function __call($method, $args, &$retval) + { + $method = strtolower($method); + if (empty($this->_method_map[$method]) && isset($this->_autoload_map[$method])) { + $this->addAggregateObject($this->_autoload_map[$method]); + } + if (isset($this->_method_map[$method])) { + $retval = call_user_func_array(array($this->_method_map[$method], $method), $args); + return true; + } + return false; + } + + // }}} +} + +overload("PEAR_Autoloader"); + +?> diff --git a/pear/PEAR/Builder.php b/pear/PEAR/Builder.php new file mode 100644 index 000000000..75d5d23d2 --- /dev/null +++ b/pear/PEAR/Builder.php @@ -0,0 +1,426 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Authors: Stig Sæther Bakken <ssb@php.net> | +// +----------------------------------------------------------------------+ +// +// $Id: Builder.php,v 1.16.2.2 2005/03/28 16:46:06 cellog Exp $ + +require_once 'PEAR/Common.php'; + +/** + * Class to handle building (compiling) extensions. + * + * @author Stig Sæther Bakken <ssb@php.net> + */ +class PEAR_Builder extends PEAR_Common +{ + // {{{ properties + + var $php_api_version = 0; + var $zend_module_api_no = 0; + var $zend_extension_api_no = 0; + + var $extensions_built = array(); + + var $current_callback = null; + + // used for msdev builds + var $_lastline = null; + var $_firstline = null; + // }}} + // {{{ constructor + + /** + * PEAR_Builder constructor. + * + * @param object $ui user interface object (instance of PEAR_Frontend_*) + * + * @access public + */ + function PEAR_Builder(&$ui) + { + parent::PEAR_Common(); + $this->setFrontendObject($ui); + } + + // }}} + + // {{{ _build_win32() + + /** + * Build an extension from source on windows. + * requires msdev + */ + function _build_win32($descfile, $callback = null) + { + if (PEAR::isError($info = $this->infoFromDescriptionFile($descfile))) { + return $info; + } + $dir = dirname($descfile); + $old_cwd = getcwd(); + + if (!@chdir($dir)) { + return $this->raiseError("could not chdir to $dir"); + } + $this->log(2, "building in $dir"); + + $dsp = $info['package'].'.dsp'; + if (!@is_file("$dir/$dsp")) { + return $this->raiseError("The DSP $dsp does not exist."); + } + // XXX TODO: make release build type configurable + $command = 'msdev '.$dsp.' /MAKE "'.$info['package']. ' - Release"'; + + $this->current_callback = $callback; + $err = $this->_runCommand($command, array(&$this, 'msdevCallback')); + if (PEAR::isError($err)) { + return $err; + } + + // figure out the build platform and type + $platform = 'Win32'; + $buildtype = 'Release'; + if (preg_match('/.*?'.$info['package'].'\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) { + $platform = $matches[1]; + $buildtype = $matches[2]; + } + + if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/',$this->_lastline,$matches)) { + if ($matches[2]) { + // there were errors in the build + return $this->raiseError("There were errors during compilation."); + } + $out = $matches[1]; + } else { + return $this->raiseError("Did not understand the completion status returned from msdev.exe."); + } + + // msdev doesn't tell us the output directory :/ + // open the dsp, find /out and use that directory + $dsptext = join(file($dsp),''); + + // this regex depends on the build platform and type having been + // correctly identified above. + $regex ='/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'. + $info['package'].'\s-\s'. + $platform.'\s'. + $buildtype.'").*?'. + '\/out:"(.*?)"/is'; + + if ($dsptext && preg_match($regex,$dsptext,$matches)) { + // what we get back is a relative path to the output file itself. + $outfile = realpath($matches[2]); + } else { + return $this->raiseError("Could not retrieve output information from $dsp."); + } + if (@copy($outfile, "$dir/$out")) { + $outfile = "$dir/$out"; + } + + $built_files[] = array( + 'file' => "$outfile", + 'php_api' => $this->php_api_version, + 'zend_mod_api' => $this->zend_module_api_no, + 'zend_ext_api' => $this->zend_extension_api_no, + ); + + return $built_files; + } + // }}} + + // {{{ msdevCallback() + function msdevCallback($what, $data) + { + if (!$this->_firstline) + $this->_firstline = $data; + $this->_lastline = $data; + } + // }}} + + // {{{ _harventInstDir + /** + * @param string + * @param string + * @param array + * @access private + */ + function _harvestInstDir($dest_prefix, $dirname, &$built_files) + { + $d = opendir($dirname); + if (!$d) + return false; + + $ret = true; + while (($ent = readdir($d)) !== false) { + if ($ent{0} == '.') + continue; + + $full = $dirname . DIRECTORY_SEPARATOR . $ent; + if (is_dir($full)) { + if (!$this->_harvestInstDir( + $dest_prefix . DIRECTORY_SEPARATOR . $ent, + $full, $built_files)) { + $ret = false; + break; + } + } else { + $dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent; + $built_files[] = array( + 'file' => $full, + 'dest' => $dest, + 'php_api' => $this->php_api_version, + 'zend_mod_api' => $this->zend_module_api_no, + 'zend_ext_api' => $this->zend_extension_api_no, + ); + } + } + closedir($d); + return $ret; + } + + // }}} + + // {{{ build() + + /** + * Build an extension from source. Runs "phpize" in the source + * directory, but compiles in a temporary directory + * (/var/tmp/pear-build-USER/PACKAGE-VERSION). + * + * @param string $descfile path to XML package description file + * + * @param mixed $callback callback function used to report output, + * see PEAR_Builder::_runCommand for details + * + * @return array an array of associative arrays with built files, + * format: + * array( array( 'file' => '/path/to/ext.so', + * 'php_api' => YYYYMMDD, + * 'zend_mod_api' => YYYYMMDD, + * 'zend_ext_api' => YYYYMMDD ), + * ... ) + * + * @access public + * + * @see PEAR_Builder::_runCommand + * @see PEAR_Common::infoFromDescriptionFile + */ + function build($descfile, $callback = null) + { + if (PEAR_OS == "Windows") { + return $this->_build_win32($descfile,$callback); + } + if (PEAR_OS != 'Unix') { + return $this->raiseError("building extensions not supported on this platform"); + } + if (PEAR::isError($info = $this->infoFromDescriptionFile($descfile))) { + return $info; + } + $dir = dirname($descfile); + $old_cwd = getcwd(); + if (!@chdir($dir)) { + return $this->raiseError("could not chdir to $dir"); + } + $vdir = "$info[package]-$info[version]"; + if (is_dir($vdir)) { + chdir($vdir); + } + $dir = getcwd(); + $this->log(2, "building in $dir"); + $this->current_callback = $callback; + putenv('PATH=' . $this->config->get('bin_dir') . ':' . getenv('PATH')); + $err = $this->_runCommand("phpize", array(&$this, 'phpizeCallback')); + if (PEAR::isError($err)) { + return $err; + } + if (!$err) { + return $this->raiseError("`phpize' failed"); + } + + // {{{ start of interactive part + $configure_command = "$dir/configure"; + if (isset($info['configure_options'])) { + foreach ($info['configure_options'] as $o) { + list($r) = $this->ui->userDialog('build', + array($o['prompt']), + array('text'), + array(@$o['default'])); + if (substr($o['name'], 0, 5) == 'with-' && + ($r == 'yes' || $r == 'autodetect')) { + $configure_command .= " --$o[name]"; + } else { + $configure_command .= " --$o[name]=".trim($r); + } + } + } + // }}} end of interactive part + + // FIXME make configurable + if(!$user=getenv('USER')){ + $user='defaultuser'; + } + $build_basedir = "/var/tmp/pear-build-$user"; + $build_dir = "$build_basedir/$info[package]-$info[version]"; + $inst_dir = "$build_basedir/install-$info[package]-$info[version]"; + $this->log(1, "building in $build_dir"); + if (is_dir($build_dir)) { + System::rm(array('-rf', $build_dir)); + } + if (!System::mkDir(array('-p', $build_dir))) { + return $this->raiseError("could not create build dir: $build_dir"); + } + $this->addTempFile($build_dir); + if (!System::mkDir(array('-p', $inst_dir))) { + return $this->raiseError("could not create temporary install dir: $inst_dir"); + } + $this->addTempFile($inst_dir); + + if (getenv('MAKE')) { + $make_command = getenv('MAKE'); + } else { + $make_command = 'make'; + } + $to_run = array( + $configure_command, + $make_command, + "$make_command INSTALL_ROOT=\"$inst_dir\" install", + "find \"$inst_dir\" -ls" + ); + if (!@chdir($build_dir)) { + return $this->raiseError("could not chdir to $build_dir"); + } + putenv('PHP_PEAR_VERSION=@PEAR-VER@'); + foreach ($to_run as $cmd) { + $err = $this->_runCommand($cmd, $callback); + if (PEAR::isError($err)) { + chdir($old_cwd); + return $err; + } + if (!$err) { + chdir($old_cwd); + return $this->raiseError("`$cmd' failed"); + } + } + if (!($dp = opendir("modules"))) { + chdir($old_cwd); + return $this->raiseError("no `modules' directory found"); + } + $built_files = array(); + $prefix = exec("php-config --prefix"); + $this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files); + chdir($old_cwd); + return $built_files; + } + + // }}} + // {{{ phpizeCallback() + + /** + * Message callback function used when running the "phpize" + * program. Extracts the API numbers used. Ignores other message + * types than "cmdoutput". + * + * @param string $what the type of message + * @param mixed $data the message + * + * @return void + * + * @access public + */ + function phpizeCallback($what, $data) + { + if ($what != 'cmdoutput') { + return; + } + $this->log(1, rtrim($data)); + if (preg_match('/You should update your .aclocal.m4/', $data)) { + return; + } + $matches = array(); + if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) { + $member = preg_replace('/[^a-z]/', '_', strtolower($matches[1])); + $apino = (int)$matches[2]; + if (isset($this->$member)) { + $this->$member = $apino; + //$msg = sprintf("%-22s : %d", $matches[1], $apino); + //$this->log(1, $msg); + } + } + } + + // }}} + // {{{ _runCommand() + + /** + * Run an external command, using a message callback to report + * output. The command will be run through popen and output is + * reported for every line with a "cmdoutput" message with the + * line string, including newlines, as payload. + * + * @param string $command the command to run + * + * @param mixed $callback (optional) function to use as message + * callback + * + * @return bool whether the command was successful (exit code 0 + * means success, any other means failure) + * + * @access private + */ + function _runCommand($command, $callback = null) + { + $this->log(1, "running: $command"); + $pp = @popen("$command 2>&1", "r"); + if (!$pp) { + return $this->raiseError("failed to run `$command'"); + } + if ($callback && $callback[0]->debug == 1) { + $olddbg = $callback[0]->debug; + $callback[0]->debug = 2; + } + + while ($line = fgets($pp, 1024)) { + if ($callback) { + call_user_func($callback, 'cmdoutput', $line); + } else { + $this->log(2, rtrim($line)); + } + } + if ($callback && isset($olddbg)) { + $callback[0]->debug = $olddbg; + } + $exitcode = @pclose($pp); + return ($exitcode == 0); + } + + // }}} + // {{{ log() + + function log($level, $msg) + { + if ($this->current_callback) { + if ($this->debug >= $level) { + call_user_func($this->current_callback, 'output', $msg); + } + return; + } + return PEAR_Common::log($level, $msg); + } + + // }}} +} + +?> diff --git a/pear/PEAR/Command.php b/pear/PEAR/Command.php new file mode 100644 index 000000000..2ea68743d --- /dev/null +++ b/pear/PEAR/Command.php @@ -0,0 +1,398 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Stig Bakken <ssb@php.net> | +// +----------------------------------------------------------------------+ +// +// $Id: Command.php,v 1.24 2004/05/16 15:43:30 pajoye Exp $ + + +require_once "PEAR.php"; + +/** + * List of commands and what classes they are implemented in. + * @var array command => implementing class + */ +$GLOBALS['_PEAR_Command_commandlist'] = 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(); + +/** + * Which user interface class is being used. + * @var string class name + */ +$GLOBALS['_PEAR_Command_uiclass'] = 'PEAR_Frontend_CLI'; + +/** + * Instance of $_PEAR_Command_uiclass. + * @var object + */ +$GLOBALS['_PEAR_Command_uiobject'] = null; + +/** + * 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(). + */ +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 + * + * @access 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])) { + return PEAR::raiseError("unknown command `$command'"); + } + $class = $GLOBALS['_PEAR_Command_commandlist'][$command]; + if (!class_exists($class)) { + return PEAR::raiseError("unknown command `$command'"); + } + $ui =& PEAR_Command::getFrontendObject(); + $obj = &new $class($ui, $config); + return $obj; + } + + // }}} + // {{{ & getFrontendObject() + + /** + * Get instance of frontend object. + * + * @return object + * @static + */ + function &getFrontendObject() + { + if (empty($GLOBALS['_PEAR_Command_uiobject'])) { + $GLOBALS['_PEAR_Command_uiobject'] = &new $GLOBALS['_PEAR_Command_uiclass']; + } + return $GLOBALS['_PEAR_Command_uiobject']; + } + + // }}} + // {{{ & setFrontendClass() + + /** + * Load current frontend class. + * + * @param string $uiclass Name of class implementing the frontend + * + * @return object the frontend object, or a PEAR error + * @static + */ + function &setFrontendClass($uiclass) + { + if (is_object($GLOBALS['_PEAR_Command_uiobject']) && + is_a($GLOBALS['_PEAR_Command_uiobject'], $uiclass)) { + return $GLOBALS['_PEAR_Command_uiobject']; + } + if (!class_exists($uiclass)) { + $file = str_replace('_', '/', $uiclass) . '.php'; + if (PEAR_Command::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 (method_exists($obj, 'userConfirm')) { + $GLOBALS['_PEAR_Command_uiobject'] = &$obj; + $GLOBALS['_PEAR_Command_uiclass'] = $uiclass; + return $obj; + } else { + $err = PEAR::raiseError("not a frontend class: $uiclass"); + return $err; + } + } + $err = PEAR::raiseError("no such class: $uiclass"); + return $err; + } + + // }}} + // {{{ setFrontendType() + + // }}} + // {{{ isIncludeable() + + /** + * @param string $path relative or absolute include path + * @return boolean + * @static + */ + function isIncludeable($path) + { + if (file_exists($path) && is_readable($path)) { + return true; + } + $ipath = explode(PATH_SEPARATOR, ini_get('include_path')); + foreach ($ipath as $include) { + $test = realpath($include . DIRECTORY_SEPARATOR . $path); + if (file_exists($test) && is_readable($test)) { + return true; + } + } + return false; + } + + /** + * Set current frontend. + * + * @param string $uitype Name of the frontend type (for example "CLI") + * + * @return object the frontend object, or a PEAR error + * @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 + * + * @access public + * @static + */ + function registerCommands($merge = false, $dir = null) + { + if ($dir === null) { + $dir = dirname(__FILE__) . '/Command'; + } + $dp = @opendir($dir); + if (empty($dp)) { + return PEAR::raiseError("registerCommands: opendir($dir) failed"); + } + if (!$merge) { + $GLOBALS['_PEAR_Command_commandlist'] = array(); + } + while ($entry = readdir($dp)) { + if ($entry{0} == '.' || substr($entry, -4) != '.php' || $entry == 'Common.php') { + continue; + } + $class = "PEAR_Command_".substr($entry, 0, -4); + $file = "$dir/$entry"; + include_once $file; + // List of commands + if (empty($GLOBALS['_PEAR_Command_objects'][$class])) { + $GLOBALS['_PEAR_Command_objects'][$class] = &new $class($ui, $config); + } + $implements = $GLOBALS['_PEAR_Command_objects'][$class]->getCommands(); + foreach ($implements as $command => $desc) { + $GLOBALS['_PEAR_Command_commandlist'][$command] = $class; + $GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc; + } + $shortcuts = $GLOBALS['_PEAR_Command_objects'][$class]->getShortcuts(); + foreach ($shortcuts as $shortcut => $command) { + $GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command; + } + } + @closedir($dp); + return true; + } + + // }}} + // {{{ getCommands() + + /** + * Get the list of currently supported commands, and what + * classes implement them. + * + * @return array command => implementing class + * + * @access 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 + * + * @access 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 + * + * @access public + * @static + */ + function getGetoptArgs($command, &$short_args, &$long_args) + { + if (empty($GLOBALS['_PEAR_Command_commandlist'])) { + PEAR_Command::registerCommands(); + } + if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { + return null; + } + $class = $GLOBALS['_PEAR_Command_commandlist'][$command]; + $obj = &$GLOBALS['_PEAR_Command_objects'][$class]; + 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 + * + * @access 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 + * + * @access public + * @static + */ + function getHelp($command) + { + $cmds = PEAR_Command::getCommands(); + if (isset($cmds[$command])) { + $class = $cmds[$command]; + return $GLOBALS['_PEAR_Command_objects'][$class]->getHelp($command); + } + return false; + } + // }}} +} + +?> diff --git a/pear/PEAR/Command/Auth.php b/pear/PEAR/Command/Auth.php new file mode 100644 index 000000000..0b9d3d396 --- /dev/null +++ b/pear/PEAR/Command/Auth.php @@ -0,0 +1,155 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Stig Bakken <ssb@php.net> | +// +----------------------------------------------------------------------+ +// +// $Id: Auth.php,v 1.15 2004/01/08 17:33:13 sniper Exp $ + +require_once "PEAR/Command/Common.php"; +require_once "PEAR/Remote.php"; +require_once "PEAR/Config.php"; + +/** + * PEAR commands for managing configuration data. + * + */ +class PEAR_Command_Auth extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'login' => array( + 'summary' => 'Connects and authenticates to remote server', + 'shortcut' => 'li', + 'function' => 'doLogin', + 'options' => array(), + 'doc' => ' +Log in to the remote server. To use remote functions in the installer +that require any kind of privileges, you need to log in first. The +username and password you enter here will be stored in your per-user +PEAR configuration (~/.pearrc on Unix-like systems). After logging +in, your username and password will be sent along in subsequent +operations on the remote server.', + ), + 'logout' => array( + 'summary' => 'Logs out from the remote server', + 'shortcut' => 'lo', + 'function' => 'doLogout', + 'options' => array(), + 'doc' => ' +Logs out from the remote server. This command does not actually +connect to the remote server, it only deletes the stored username and +password from your user configuration.', + ) + + ); + + // }}} + + // {{{ constructor + + /** + * PEAR_Command_Auth constructor. + * + * @access public + */ + function PEAR_Command_Auth(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doLogin() + + /** + * Execute the 'login' command. + * + * @param string $command command name + * + * @param array $options option_name => value + * + * @param array $params list of additional parameters + * + * @return bool TRUE on success, FALSE for unknown commands, or + * a PEAR error on failure + * + * @access public + */ + function doLogin($command, $options, $params) + { + $server = $this->config->get('master_server'); + $remote = new PEAR_Remote($this->config); + $username = $this->config->get('username'); + if (empty($username)) { + $username = @$_ENV['USER']; + } + $this->ui->outputData("Logging in to $server.", $command); + + list($username, $password) = $this->ui->userDialog( + $command, + array('Username', 'Password'), + array('text', 'password'), + array($username, '') + ); + $username = trim($username); + $password = trim($password); + + $this->config->set('username', $username); + $this->config->set('password', $password); + + $remote->expectError(401); + $ok = $remote->call('logintest'); + $remote->popExpect(); + if ($ok === true) { + $this->ui->outputData("Logged in.", $command); + $this->config->store(); + } else { + return $this->raiseError("Login failed!"); + } + + } + + // }}} + // {{{ doLogout() + + /** + * Execute the 'logout' command. + * + * @param string $command command name + * + * @param array $options option_name => value + * + * @param array $params list of additional parameters + * + * @return bool TRUE on success, FALSE for unknown commands, or + * a PEAR error on failure + * + * @access public + */ + function doLogout($command, $options, $params) + { + $server = $this->config->get('master_server'); + $this->ui->outputData("Logging out from $server.", $command); + $this->config->remove('username'); + $this->config->remove('password'); + $this->config->store(); + } + + // }}} +} + +?>
\ No newline at end of file diff --git a/pear/PEAR/Command/Build.php b/pear/PEAR/Command/Build.php new file mode 100644 index 000000000..2ecbbc92f --- /dev/null +++ b/pear/PEAR/Command/Build.php @@ -0,0 +1,89 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Stig Bakken <ssb@php.net> | +// | Tomas V.V.Cox <cox@idecnet.com> | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: Build.php,v 1.9 2004/01/08 17:33:13 sniper Exp $ + +require_once "PEAR/Command/Common.php"; +require_once "PEAR/Builder.php"; + +/** + * PEAR commands for building extensions. + * + */ +class PEAR_Command_Build extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'build' => array( + 'summary' => 'Build an Extension From C Source', + 'function' => 'doBuild', + 'shortcut' => 'b', + 'options' => array(), + 'doc' => '[package.xml] +Builds one or more extensions contained in a package.' + ), + ); + + // }}} + + // {{{ constructor + + /** + * PEAR_Command_Build constructor. + * + * @access public + */ + function PEAR_Command_Build(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doBuild() + + function doBuild($command, $options, $params) + { + if (sizeof($params) < 1) { + $params[0] = 'package.xml'; + } + $builder = &new PEAR_Builder($this->ui); + $this->debug = $this->config->get('verbose'); + $err = $builder->build($params[0], array(&$this, 'buildCallback')); + if (PEAR::isError($err)) { + return $err; + } + return true; + } + + // }}} + // {{{ buildCallback() + + function buildCallback($what, $data) + { + if (($what == 'cmdoutput' && $this->debug > 1) || + ($what == 'output' && $this->debug > 0)) { + $this->ui->outputData(rtrim($data), 'build'); + } + } + + // }}} +} diff --git a/pear/PEAR/Command/Common.php b/pear/PEAR/Command/Common.php new file mode 100644 index 000000000..c6ace694c --- /dev/null +++ b/pear/PEAR/Command/Common.php @@ -0,0 +1,249 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Stig Sæther Bakken <ssb@php.net> | +// +----------------------------------------------------------------------+ +// +// $Id: Common.php,v 1.24 2004/01/08 17:33:13 sniper Exp $ + +require_once "PEAR.php"; + +class PEAR_Command_Common extends PEAR +{ + // {{{ properties + + /** + * PEAR_Config object used to pass user system and configuration + * on when executing commands + * + * @var object + */ + var $config; + + /** + * User Interface object, for all interaction with the user. + * @var object + */ + var $ui; + + var $_deps_rel_trans = array( + 'lt' => '<', + 'le' => '<=', + 'eq' => '=', + 'ne' => '!=', + 'gt' => '>', + 'ge' => '>=', + 'has' => '==' + ); + + var $_deps_type_trans = array( + 'pkg' => 'package', + 'extension' => 'extension', + 'php' => 'PHP', + 'prog' => 'external program', + 'ldlib' => 'external library for linking', + 'rtlib' => 'external runtime library', + 'os' => 'operating system', + 'websrv' => 'web server', + 'sapi' => 'SAPI backend' + ); + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Common constructor. + * + * @access public + */ + function PEAR_Command_Common(&$ui, &$config) + { + parent::PEAR(); + $this->config = &$config; + $this->ui = &$ui; + } + + // }}} + + // {{{ getCommands() + + /** + * Return a list of all the commands defined by this class. + * @return array list of commands + * @access public + */ + function getCommands() + { + $ret = array(); + foreach (array_keys($this->commands) as $command) { + $ret[$command] = $this->commands[$command]['summary']; + } + return $ret; + } + + // }}} + // {{{ getShortcuts() + + /** + * Return a list of all the command shortcuts defined by this class. + * @return array shortcut => command + * @access public + */ + function getShortcuts() + { + $ret = array(); + foreach (array_keys($this->commands) as $command) { + if (isset($this->commands[$command]['shortcut'])) { + $ret[$this->commands[$command]['shortcut']] = $command; + } + } + return $ret; + } + + // }}} + // {{{ getOptions() + + function getOptions($command) + { + return @$this->commands[$command]['options']; + } + + // }}} + // {{{ getGetoptArgs() + + function getGetoptArgs($command, &$short_args, &$long_args) + { + $short_args = ""; + $long_args = array(); + if (empty($this->commands[$command])) { + return; + } + reset($this->commands[$command]); + while (list($option, $info) = each($this->commands[$command]['options'])) { + $larg = $sarg = ''; + if (isset($info['arg'])) { + if ($info['arg']{0} == '(') { + $larg = '=='; + $sarg = '::'; + $arg = substr($info['arg'], 1, -1); + } else { + $larg = '='; + $sarg = ':'; + $arg = $info['arg']; + } + } + if (isset($info['shortopt'])) { + $short_args .= $info['shortopt'] . $sarg; + } + $long_args[] = $option . $larg; + } + } + + // }}} + // {{{ getHelp() + /** + * Returns the help message for the given command + * + * @param string $command The command + * @return mixed A fail string if the command does not have help or + * a two elements array containing [0]=>help string, + * [1]=> help string for the accepted cmd args + */ + function getHelp($command) + { + $config = &PEAR_Config::singleton(); + $help = @$this->commands[$command]['doc']; + if (empty($help)) { + // XXX (cox) Fallback to summary if there is no doc (show both?) + if (!$help = @$this->commands[$command]['summary']) { + return "No help for command \"$command\""; + } + } + if (preg_match_all('/{config\s+([^\}]+)}/e', $help, $matches)) { + foreach($matches[0] as $k => $v) { + $help = preg_replace("/$v/", $config->get($matches[1][$k]), $help); + } + } + return array($help, $this->getHelpArgs($command)); + } + + // }}} + // {{{ getHelpArgs() + /** + * Returns the help for the accepted arguments of a command + * + * @param string $command + * @return string The help string + */ + function getHelpArgs($command) + { + if (isset($this->commands[$command]['options']) && + count($this->commands[$command]['options'])) + { + $help = "Options:\n"; + foreach ($this->commands[$command]['options'] as $k => $v) { + if (isset($v['arg'])) { + if ($v['arg']{0} == '(') { + $arg = substr($v['arg'], 1, -1); + $sapp = " [$arg]"; + $lapp = "[=$arg]"; + } else { + $sapp = " $v[arg]"; + $lapp = "=$v[arg]"; + } + } else { + $sapp = $lapp = ""; + } + if (isset($v['shortopt'])) { + $s = $v['shortopt']; + @$help .= " -$s$sapp, --$k$lapp\n"; + } else { + @$help .= " --$k$lapp\n"; + } + $p = " "; + $doc = rtrim(str_replace("\n", "\n$p", $v['doc'])); + $help .= " $doc\n"; + } + return $help; + } + return null; + } + + // }}} + // {{{ run() + + function run($command, $options, $params) + { + $func = @$this->commands[$command]['function']; + if (empty($func)) { + // look for shortcuts + foreach (array_keys($this->commands) as $cmd) { + if (@$this->commands[$cmd]['shortcut'] == $command) { + $command = $cmd; + $func = @$this->commands[$command]['function']; + if (empty($func)) { + return $this->raiseError("unknown command `$command'"); + } + break; + } + } + } + return $this->$func($command, $options, $params); + } + + // }}} +} + +?>
\ No newline at end of file diff --git a/pear/PEAR/Command/Config.php b/pear/PEAR/Command/Config.php new file mode 100644 index 000000000..474a23451 --- /dev/null +++ b/pear/PEAR/Command/Config.php @@ -0,0 +1,225 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Stig Bakken <ssb@php.net> | +// | Tomas V.V.Cox <cox@idecnet.com> | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: Config.php,v 1.27 2004/06/15 16:48:49 pajoye Exp $ + +require_once "PEAR/Command/Common.php"; +require_once "PEAR/Config.php"; + +/** + * PEAR commands for managing configuration data. + * + */ +class PEAR_Command_Config extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'config-show' => array( + 'summary' => 'Show All Settings', + 'function' => 'doConfigShow', + 'shortcut' => 'csh', + 'options' => array(), + 'doc' => ' +Displays all configuration values. An optional argument +may be used to tell which configuration layer to display. Valid +configuration layers are "user", "system" and "default". +', + ), + 'config-get' => array( + 'summary' => 'Show One Setting', + 'function' => 'doConfigGet', + 'shortcut' => 'cg', + 'options' => array(), + 'doc' => '<parameter> [layer] +Displays the value of one configuration parameter. The +first argument is the name of the parameter, an optional second argument +may be used to tell which configuration layer to look in. Valid configuration +layers are "user", "system" and "default". If no layer is specified, a value +will be picked from the first layer that defines the parameter, in the order +just specified. +', + ), + 'config-set' => array( + 'summary' => 'Change Setting', + 'function' => 'doConfigSet', + 'shortcut' => 'cs', + 'options' => array(), + 'doc' => '<parameter> <value> [layer] +Sets the value of one configuration parameter. The first argument is +the name of the parameter, the second argument is the new value. Some +parameters are subject to validation, and the command will fail with +an error message if the new value does not make sense. An optional +third argument may be used to specify in which layer to set the +configuration parameter. The default layer is "user". +', + ), + 'config-help' => array( + 'summary' => 'Show Information About Setting', + 'function' => 'doConfigHelp', + 'shortcut' => 'ch', + 'options' => array(), + 'doc' => '[parameter] +Displays help for a configuration parameter. Without arguments it +displays help for all configuration parameters. +', + ), + ); + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Config constructor. + * + * @access public + */ + function PEAR_Command_Config(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doConfigShow() + + function doConfigShow($command, $options, $params) + { + // $params[0] -> the layer + if ($error = $this->_checkLayer(@$params[0])) { + return $this->raiseError($error); + } + $keys = $this->config->getKeys(); + sort($keys); + $data = array('caption' => 'Configuration:'); + foreach ($keys as $key) { + $type = $this->config->getType($key); + $value = $this->config->get($key, @$params[0]); + if ($type == 'password' && $value) { + $value = '********'; + } + if ($value === false) { + $value = 'false'; + } elseif ($value === true) { + $value = 'true'; + } + $data['data'][$this->config->getGroup($key)][] = array($this->config->getPrompt($key) , $key, $value); + } + $this->ui->outputData($data, $command); + return true; + } + + // }}} + // {{{ doConfigGet() + + function doConfigGet($command, $options, $params) + { + // $params[0] -> the parameter + // $params[1] -> the layer + if ($error = $this->_checkLayer(@$params[1])) { + return $this->raiseError($error); + } + if (sizeof($params) < 1 || sizeof($params) > 2) { + return $this->raiseError("config-get expects 1 or 2 parameters"); + } elseif (sizeof($params) == 1) { + $this->ui->outputData($this->config->get($params[0]), $command); + } else { + $data = $this->config->get($params[0], $params[1]); + $this->ui->outputData($data, $command); + } + return true; + } + + // }}} + // {{{ doConfigSet() + + function doConfigSet($command, $options, $params) + { + // $param[0] -> a parameter to set + // $param[1] -> the value for the parameter + // $param[2] -> the layer + $failmsg = ''; + if (sizeof($params) < 2 || sizeof($params) > 3) { + $failmsg .= "config-set expects 2 or 3 parameters"; + return PEAR::raiseError($failmsg); + } + if ($error = $this->_checkLayer(@$params[2])) { + $failmsg .= $error; + return PEAR::raiseError($failmsg); + } + if (!call_user_func_array(array(&$this->config, 'set'), $params)) + { + $failmsg = "config-set (" . implode(", ", $params) . ") failed"; + } else { + $this->config->store(); + } + if ($failmsg) { + return $this->raiseError($failmsg); + } + return true; + } + + // }}} + // {{{ doConfigHelp() + + function doConfigHelp($command, $options, $params) + { + if (empty($params)) { + $params = $this->config->getKeys(); + } + $data['caption'] = "Config help" . ((count($params) == 1) ? " for $params[0]" : ''); + $data['headline'] = array('Name', 'Type', 'Description'); + $data['border'] = true; + foreach ($params as $name) { + $type = $this->config->getType($name); + $docs = $this->config->getDocs($name); + if ($type == 'set') { + $docs = rtrim($docs) . "\nValid set: " . + implode(' ', $this->config->getSetValues($name)); + } + $data['data'][] = array($name, $type, $docs); + } + $this->ui->outputData($data, $command); + } + + // }}} + // {{{ _checkLayer() + + /** + * Checks if a layer is defined or not + * + * @param string $layer The layer to search for + * @return mixed False on no error or the error message + */ + function _checkLayer($layer = null) + { + if (!empty($layer) && $layer != 'default') { + $layers = $this->config->getLayers(); + if (!in_array($layer, $layers)) { + return " only the layers: \"" . implode('" or "', $layers) . "\" are supported"; + } + } + return false; + } + + // }}} +} + +?> diff --git a/pear/PEAR/Command/Install.php b/pear/PEAR/Command/Install.php new file mode 100644 index 000000000..bd64463fa --- /dev/null +++ b/pear/PEAR/Command/Install.php @@ -0,0 +1,470 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Stig Sæther Bakken <ssb@php.net> | +// +----------------------------------------------------------------------+ +// +// $Id: Install.php,v 1.53.2.1 2004/10/25 17:14:34 cellog Exp $ + +require_once "PEAR/Command/Common.php"; +require_once "PEAR/Installer.php"; + +/** + * PEAR commands for installation or deinstallation/upgrading of + * packages. + * + */ +class PEAR_Command_Install extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'install' => array( + 'summary' => 'Install Package', + 'function' => 'doInstall', + 'shortcut' => 'i', + 'options' => array( + 'force' => array( + 'shortopt' => 'f', + 'doc' => 'will overwrite newer installed packages', + ), + 'nodeps' => array( + 'shortopt' => 'n', + 'doc' => 'ignore dependencies, install anyway', + ), + 'register-only' => array( + 'shortopt' => 'r', + 'doc' => 'do not install files, only register the package as installed', + ), + 'soft' => array( + 'shortopt' => 's', + 'doc' => 'soft install, fail silently, or upgrade if already installed', + ), + 'nobuild' => array( + 'shortopt' => 'B', + 'doc' => 'don\'t build C extensions', + ), + 'nocompress' => array( + 'shortopt' => 'Z', + 'doc' => 'request uncompressed files when downloading', + ), + 'installroot' => array( + 'shortopt' => 'R', + 'arg' => 'DIR', + 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)', + ), + 'ignore-errors' => array( + 'doc' => 'force install even if there were errors', + ), + 'alldeps' => array( + 'shortopt' => 'a', + 'doc' => 'install all required and optional dependencies', + ), + 'onlyreqdeps' => array( + 'shortopt' => 'o', + 'doc' => 'install all required dependencies', + ), + ), + 'doc' => '<package> ... +Installs one or more PEAR packages. You can specify a package to +install in four ways: + +"Package-1.0.tgz" : installs from a local file + +"http://example.com/Package-1.0.tgz" : installs from +anywhere on the net. + +"package.xml" : installs the package described in +package.xml. Useful for testing, or for wrapping a PEAR package in +another package manager such as RPM. + +"Package" : queries your configured server +({config master_server}) and downloads the newest package with +the preferred quality/state ({config preferred_state}). + +More than one package may be specified at once. It is ok to mix these +four ways of specifying packages. +'), + 'upgrade' => array( + 'summary' => 'Upgrade Package', + 'function' => 'doInstall', + 'shortcut' => 'up', + 'options' => array( + 'force' => array( + 'shortopt' => 'f', + 'doc' => 'overwrite newer installed packages', + ), + 'nodeps' => array( + 'shortopt' => 'n', + 'doc' => 'ignore dependencies, upgrade anyway', + ), + 'register-only' => array( + 'shortopt' => 'r', + 'doc' => 'do not install files, only register the package as upgraded', + ), + 'nobuild' => array( + 'shortopt' => 'B', + 'doc' => 'don\'t build C extensions', + ), + 'nocompress' => array( + 'shortopt' => 'Z', + 'doc' => 'request uncompressed files when downloading', + ), + 'installroot' => array( + 'shortopt' => 'R', + 'arg' => 'DIR', + 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)', + ), + 'ignore-errors' => array( + 'doc' => 'force install even if there were errors', + ), + 'alldeps' => array( + 'shortopt' => 'a', + 'doc' => 'install all required and optional dependencies', + ), + 'onlyreqdeps' => array( + 'shortopt' => 'o', + 'doc' => 'install all required dependencies', + ), + ), + 'doc' => '<package> ... +Upgrades one or more PEAR packages. See documentation for the +"install" command for ways to specify a package. + +When upgrading, your package will be updated if the provided new +package has a higher version number (use the -f option if you need to +upgrade anyway). + +More than one package may be specified at once. +'), + 'upgrade-all' => array( + 'summary' => 'Upgrade All Packages', + 'function' => 'doInstall', + 'shortcut' => 'ua', + 'options' => array( + 'nodeps' => array( + 'shortopt' => 'n', + 'doc' => 'ignore dependencies, upgrade anyway', + ), + 'register-only' => array( + 'shortopt' => 'r', + 'doc' => 'do not install files, only register the package as upgraded', + ), + 'nobuild' => array( + 'shortopt' => 'B', + 'doc' => 'don\'t build C extensions', + ), + 'nocompress' => array( + 'shortopt' => 'Z', + 'doc' => 'request uncompressed files when downloading', + ), + 'installroot' => array( + 'shortopt' => 'R', + 'arg' => 'DIR', + 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)', + ), + 'ignore-errors' => array( + 'doc' => 'force install even if there were errors', + ), + ), + 'doc' => ' +Upgrades all packages that have a newer release available. Upgrades are +done only if there is a release available of the state specified in +"preferred_state" (currently {config preferred_state}), or a state considered +more stable. +'), + 'uninstall' => array( + 'summary' => 'Un-install Package', + 'function' => 'doUninstall', + 'shortcut' => 'un', + 'options' => array( + 'nodeps' => array( + 'shortopt' => 'n', + 'doc' => 'ignore dependencies, uninstall anyway', + ), + 'register-only' => array( + 'shortopt' => 'r', + 'doc' => 'do not remove files, only register the packages as not installed', + ), + 'installroot' => array( + 'shortopt' => 'R', + 'arg' => 'DIR', + 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)', + ), + 'ignore-errors' => array( + 'doc' => 'force install even if there were errors', + ), + ), + 'doc' => '<package> ... +Uninstalls one or more PEAR packages. More than one package may be +specified at once. +'), + 'bundle' => array( + 'summary' => 'Unpacks a Pecl Package', + 'function' => 'doBundle', + 'shortcut' => 'bun', + 'options' => array( + 'destination' => array( + 'shortopt' => 'd', + 'arg' => 'DIR', + 'doc' => 'Optional destination directory for unpacking (defaults to current path or "ext" if exists)', + ), + 'force' => array( + 'shortopt' => 'f', + 'doc' => 'Force the unpacking even if there were errors in the package', + ), + ), + 'doc' => '<package> +Unpacks a Pecl Package into the selected location. It will download the +package if needed. +'), + ); + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Install constructor. + * + * @access public + */ + function PEAR_Command_Install(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doInstall() + + function doInstall($command, $options, $params) + { + require_once 'PEAR/Downloader.php'; + if (empty($this->installer)) { + $this->installer = &new PEAR_Installer($this->ui); + } + if ($command == 'upgrade') { + $options['upgrade'] = true; + } + if ($command == 'upgrade-all') { + include_once "PEAR/Remote.php"; + $options['upgrade'] = true; + $remote = &new PEAR_Remote($this->config); + $state = $this->config->get('preferred_state'); + if (empty($state) || $state == 'any') { + $latest = $remote->call("package.listLatestReleases"); + } else { + $latest = $remote->call("package.listLatestReleases", $state); + } + if (PEAR::isError($latest)) { + return $latest; + } + $reg = new PEAR_Registry($this->config->get('php_dir')); + $installed = array_flip($reg->listPackages()); + $params = array(); + foreach ($latest as $package => $info) { + $package = strtolower($package); + if (!isset($installed[$package])) { + // skip packages we don't have installed + continue; + } + $inst_version = $reg->packageInfo($package, 'version'); + if (version_compare("$info[version]", "$inst_version", "le")) { + // installed version is up-to-date + continue; + } + $params[] = $package; + $this->ui->outputData(array('data' => "Will upgrade $package"), $command); + } + } + $this->downloader = &new PEAR_Downloader($this->ui, $options, $this->config); + $errors = array(); + $downloaded = array(); + $this->downloader->download($params); + $errors = $this->downloader->getErrorMsgs(); + if (count($errors)) { + $err['data'] = array($errors); + $err['headline'] = 'Install Errors'; + $this->ui->outputData($err); + return $this->raiseError("$command failed"); + } + $downloaded = $this->downloader->getDownloadedPackages(); + $this->installer->sortPkgDeps($downloaded); + foreach ($downloaded as $pkg) { + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $info = $this->installer->install($pkg['file'], $options, $this->config); + PEAR::popErrorHandling(); + if (PEAR::isError($info)) { + $this->ui->outputData('ERROR: ' .$info->getMessage()); + continue; + } + if (is_array($info)) { + if ($this->config->get('verbose') > 0) { + $label = "$info[package] $info[version]"; + $out = array('data' => "$command ok: $label"); + if (isset($info['release_warnings'])) { + $out['release_warnings'] = $info['release_warnings']; + } + $this->ui->outputData($out, $command); + } + } else { + return $this->raiseError("$command failed"); + } + } + return true; + } + + // }}} + // {{{ doUninstall() + + function doUninstall($command, $options, $params) + { + if (empty($this->installer)) { + $this->installer = &new PEAR_Installer($this->ui); + } + if (sizeof($params) < 1) { + return $this->raiseError("Please supply the package(s) you want to uninstall"); + } + include_once 'PEAR/Registry.php'; + $reg = new PEAR_Registry($this->config->get('php_dir')); + $newparams = array(); + $badparams = array(); + foreach ($params as $pkg) { + $info = $reg->packageInfo($pkg); + if ($info === null) { + $badparams[] = $pkg; + } else { + $newparams[] = $info; + } + } + $this->installer->sortPkgDeps($newparams, true); + $params = array(); + foreach($newparams as $info) { + $params[] = $info['info']['package']; + } + $params = array_merge($params, $badparams); + foreach ($params as $pkg) { + if ($this->installer->uninstall($pkg, $options)) { + if ($this->config->get('verbose') > 0) { + $this->ui->outputData("uninstall ok: $pkg", $command); + } + } else { + return $this->raiseError("uninstall failed: $pkg"); + } + } + return true; + } + + // }}} + + + // }}} + // {{{ doBundle() + /* + (cox) It just downloads and untars the package, does not do + any check that the PEAR_Installer::_installFile() does. + */ + + function doBundle($command, $options, $params) + { + if (empty($this->installer)) { + $this->installer = &new PEAR_Downloader($this->ui); + } + $installer = &$this->installer; + if (sizeof($params) < 1) { + return $this->raiseError("Please supply the package you want to bundle"); + } + $pkgfile = $params[0]; + $need_download = false; + if (preg_match('#^(http|ftp)://#', $pkgfile)) { + $need_download = true; + } elseif (!@is_file($pkgfile)) { + if ($installer->validPackageName($pkgfile)) { + $pkgfile = $installer->getPackageDownloadUrl($pkgfile); + $need_download = true; + } else { + if (strlen($pkgfile)) { + return $this->raiseError("Could not open the package file: $pkgfile"); + } else { + return $this->raiseError("No package file given"); + } + } + } + + // Download package ----------------------------------------------- + if ($need_download) { + $downloaddir = $installer->config->get('download_dir'); + if (empty($downloaddir)) { + if (PEAR::isError($downloaddir = System::mktemp('-d'))) { + return $downloaddir; + } + $installer->log(2, '+ tmp dir created at ' . $downloaddir); + } + $callback = $this->ui ? array(&$installer, '_downloadCallback') : null; + $file = $installer->downloadHttp($pkgfile, $this->ui, $downloaddir, $callback); + if (PEAR::isError($file)) { + return $this->raiseError($file); + } + $pkgfile = $file; + } + + // Parse xml file ----------------------------------------------- + $pkginfo = $installer->infoFromTgzFile($pkgfile); + if (PEAR::isError($pkginfo)) { + return $this->raiseError($pkginfo); + } + $installer->validatePackageInfo($pkginfo, $errors, $warnings); + // XXX We allow warnings, do we have to do it? + if (count($errors)) { + if (empty($options['force'])) { + return $this->raiseError("The following errors where found:\n". + implode("\n", $errors)); + } else { + $this->log(0, "warning : the following errors were found:\n". + implode("\n", $errors)); + } + } + $pkgname = $pkginfo['package']; + + // Unpacking ------------------------------------------------- + + if (isset($options['destination'])) { + if (!is_dir($options['destination'])) { + System::mkdir('-p ' . $options['destination']); + } + $dest = realpath($options['destination']); + } else { + $pwd = getcwd(); + if (is_dir($pwd . DIRECTORY_SEPARATOR . 'ext')) { + $dest = $pwd . DIRECTORY_SEPARATOR . 'ext'; + } else { + $dest = $pwd; + } + } + $dest .= DIRECTORY_SEPARATOR . $pkgname; + $orig = $pkgname . '-' . $pkginfo['version']; + + $tar = new Archive_Tar($pkgfile); + if (!@$tar->extractModify($dest, $orig)) { + return $this->raiseError("unable to unpack $pkgfile"); + } + $this->ui->outputData("Package ready at '$dest'"); + // }}} + } + + // }}} + +} +?> diff --git a/pear/PEAR/Command/Mirror.php b/pear/PEAR/Command/Mirror.php new file mode 100644 index 000000000..bf56c3db6 --- /dev/null +++ b/pear/PEAR/Command/Mirror.php @@ -0,0 +1,101 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Alexander Merz <alexmerz@php.net> | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: Mirror.php,v 1.5 2004/03/18 12:23:57 mj Exp $ + +require_once "PEAR/Command/Common.php"; +require_once "PEAR/Command.php"; +require_once "PEAR/Remote.php"; +require_once "PEAR.php"; + +/** + * PEAR commands for providing file mirrors + * + */ +class PEAR_Command_Mirror extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'download-all' => array( + 'summary' => 'Downloads each available package from master_server', + 'function' => 'doDownloadAll', + 'shortcut' => 'da', + 'options' => array(), + 'doc' => ' + Requests a list of available packages from the package server + (master_server) and downloads them to current working directory' + ), + ); + + // }}} + + // {{{ constructor + + /** + * PEAR_Command_Mirror constructor. + * + * @access public + * @param object PEAR_Frontend a reference to an frontend + * @param object PEAR_Config a reference to the configuration data + */ + function PEAR_Command_Mirror(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doDownloadAll() + /** + * retrieves a list of avaible Packages from master server + * and downloads them + * + * @access public + * @param string $command the command + * @param array $options the command options before the command + * @param array $params the stuff after the command name + * @return bool true if succesful + * @throw PEAR_Error + */ + function doDownloadAll($command, $options, $params) + { + $this->config->set("php_dir", "."); + $remote = &new PEAR_Remote($this->config); + $remoteInfo = $remote->call("package.listAll"); + if (PEAR::isError($remoteInfo)) { + return $remoteInfo; + } + $cmd = &PEAR_Command::factory("download", $this->config); + if (PEAR::isError($cmd)) { + return $cmd; + } + foreach ($remoteInfo as $pkgn => $pkg) { + /** + * Error handling not neccesary, because already done by + * the download command + */ + $cmd->run("download", array(), array($pkgn)); + } + + return true; + } + + // }}} +} diff --git a/pear/PEAR/Command/Package.php b/pear/PEAR/Command/Package.php new file mode 100644 index 000000000..03a5bdf98 --- /dev/null +++ b/pear/PEAR/Command/Package.php @@ -0,0 +1,819 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Authors: Stig Bakken <ssb@php.net> | +// | Martin Jansen <mj@php.net> | +// | Greg Beaver <cellog@php.net> | +// +----------------------------------------------------------------------+ +// +// $Id: Package.php,v 1.61.2.2 2005/03/28 16:46:06 cellog Exp $ + +require_once 'PEAR/Common.php'; +require_once 'PEAR/Command/Common.php'; + +class PEAR_Command_Package extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'package' => array( + 'summary' => 'Build Package', + 'function' => 'doPackage', + 'shortcut' => 'p', + 'options' => array( + 'nocompress' => array( + 'shortopt' => 'Z', + 'doc' => 'Do not gzip the package file' + ), + 'showname' => array( + 'shortopt' => 'n', + 'doc' => 'Print the name of the packaged file.', + ), + ), + 'doc' => '[descfile] +Creates a PEAR package from its description file (usually called +package.xml). +' + ), + 'package-validate' => array( + 'summary' => 'Validate Package Consistency', + 'function' => 'doPackageValidate', + 'shortcut' => 'pv', + 'options' => array(), + 'doc' => ' +', + ), + 'cvsdiff' => array( + 'summary' => 'Run a "cvs diff" for all files in a package', + 'function' => 'doCvsDiff', + 'shortcut' => 'cd', + 'options' => array( + 'quiet' => array( + 'shortopt' => 'q', + 'doc' => 'Be quiet', + ), + 'reallyquiet' => array( + 'shortopt' => 'Q', + 'doc' => 'Be really quiet', + ), + 'date' => array( + 'shortopt' => 'D', + 'doc' => 'Diff against revision of DATE', + 'arg' => 'DATE', + ), + 'release' => array( + 'shortopt' => 'R', + 'doc' => 'Diff against tag for package release REL', + 'arg' => 'REL', + ), + 'revision' => array( + 'shortopt' => 'r', + 'doc' => 'Diff against revision REV', + 'arg' => 'REV', + ), + 'context' => array( + 'shortopt' => 'c', + 'doc' => 'Generate context diff', + ), + 'unified' => array( + 'shortopt' => 'u', + 'doc' => 'Generate unified diff', + ), + 'ignore-case' => array( + 'shortopt' => 'i', + 'doc' => 'Ignore case, consider upper- and lower-case letters equivalent', + ), + 'ignore-whitespace' => array( + 'shortopt' => 'b', + 'doc' => 'Ignore changes in amount of white space', + ), + 'ignore-blank-lines' => array( + 'shortopt' => 'B', + 'doc' => 'Ignore changes that insert or delete blank lines', + ), + 'brief' => array( + 'doc' => 'Report only whether the files differ, no details', + ), + 'dry-run' => array( + 'shortopt' => 'n', + 'doc' => 'Don\'t do anything, just pretend', + ), + ), + 'doc' => '<package.xml> +Compares all the files in a package. Without any options, this +command will compare the current code with the last checked-in code. +Using the -r or -R option you may compare the current code with that +of a specific release. +', + ), + 'cvstag' => array( + 'summary' => 'Set CVS Release Tag', + 'function' => 'doCvsTag', + 'shortcut' => 'ct', + 'options' => array( + 'quiet' => array( + 'shortopt' => 'q', + 'doc' => 'Be quiet', + ), + 'reallyquiet' => array( + 'shortopt' => 'Q', + 'doc' => 'Be really quiet', + ), + 'slide' => array( + 'shortopt' => 'F', + 'doc' => 'Move (slide) tag if it exists', + ), + 'delete' => array( + 'shortopt' => 'd', + 'doc' => 'Remove tag', + ), + 'dry-run' => array( + 'shortopt' => 'n', + 'doc' => 'Don\'t do anything, just pretend', + ), + ), + 'doc' => '<package.xml> +Sets a CVS tag on all files in a package. Use this command after you have +packaged a distribution tarball with the "package" command to tag what +revisions of what files were in that release. If need to fix something +after running cvstag once, but before the tarball is released to the public, +use the "slide" option to move the release tag. +', + ), + 'run-tests' => array( + 'summary' => 'Run Regression Tests', + 'function' => 'doRunTests', + 'shortcut' => 'rt', + 'options' => array( + 'recur' => array( + 'shortopt' => 'r', + 'doc' => 'Run tests in child directories, recursively. 4 dirs deep maximum', + ), + 'ini' => array( + 'shortopt' => 'i', + 'doc' => 'actual string of settings to pass to php in format " -d setting=blah"', + 'arg' => 'SETTINGS' + ), + 'realtimelog' => array( + 'shortopt' => 'l', + 'doc' => 'Log test runs/results as they are run', + ), + ), + 'doc' => '[testfile|dir ...] +Run regression tests with PHP\'s regression testing script (run-tests.php).', + ), + 'package-dependencies' => array( + 'summary' => 'Show package dependencies', + 'function' => 'doPackageDependencies', + 'shortcut' => 'pd', + 'options' => array(), + 'doc' => ' +List all depencies the package has.' + ), + 'sign' => array( + 'summary' => 'Sign a package distribution file', + 'function' => 'doSign', + 'shortcut' => 'si', + 'options' => array(), + 'doc' => '<package-file> +Signs a package distribution (.tar or .tgz) file with GnuPG.', + ), + 'makerpm' => array( + 'summary' => 'Builds an RPM spec file from a PEAR package', + 'function' => 'doMakeRPM', + 'shortcut' => 'rpm', + 'options' => array( + 'spec-template' => array( + 'shortopt' => 't', + 'arg' => 'FILE', + 'doc' => 'Use FILE as RPM spec file template' + ), + 'rpm-pkgname' => array( + 'shortopt' => 'p', + 'arg' => 'FORMAT', + 'doc' => 'Use FORMAT as format string for RPM package name, %s is replaced +by the PEAR package name, defaults to "PEAR::%s".', + ), + ), + 'doc' => '<package-file> + +Creates an RPM .spec file for wrapping a PEAR package inside an RPM +package. Intended to be used from the SPECS directory, with the PEAR +package tarball in the SOURCES directory: + +$ pear makerpm ../SOURCES/Net_Socket-1.0.tgz +Wrote RPM spec file PEAR::Net_Geo-1.0.spec +$ rpm -bb PEAR::Net_Socket-1.0.spec +... +Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm +', + ), + ); + + var $output; + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Package constructor. + * + * @access public + */ + function PEAR_Command_Package(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ _displayValidationResults() + + function _displayValidationResults($err, $warn, $strict = false) + { + foreach ($err as $e) { + $this->output .= "Error: $e\n"; + } + foreach ($warn as $w) { + $this->output .= "Warning: $w\n"; + } + $this->output .= sprintf('Validation: %d error(s), %d warning(s)'."\n", + sizeof($err), sizeof($warn)); + if ($strict && sizeof($err) > 0) { + $this->output .= "Fix these errors and try again."; + return false; + } + return true; + } + + // }}} + // {{{ doPackage() + + function doPackage($command, $options, $params) + { + $this->output = ''; + include_once 'PEAR/Packager.php'; + if (sizeof($params) < 1) { + $params[0] = "package.xml"; + } + $pkginfofile = isset($params[0]) ? $params[0] : 'package.xml'; + $packager =& new PEAR_Packager(); + $err = $warn = array(); + $dir = dirname($pkginfofile); + $compress = empty($options['nocompress']) ? true : false; + $result = $packager->package($pkginfofile, $compress); + if (PEAR::isError($result)) { + $this->ui->outputData($this->output, $command); + return $this->raiseError($result); + } + // Don't want output, only the package file name just created + if (isset($options['showname'])) { + $this->output = $result; + } + if (PEAR::isError($result)) { + $this->output .= "Package failed: ".$result->getMessage(); + } + $this->ui->outputData($this->output, $command); + return true; + } + + // }}} + // {{{ doPackageValidate() + + function doPackageValidate($command, $options, $params) + { + $this->output = ''; + if (sizeof($params) < 1) { + $params[0] = "package.xml"; + } + $obj = new PEAR_Common; + $info = null; + if ($fp = @fopen($params[0], "r")) { + $test = fread($fp, 5); + fclose($fp); + if ($test == "<?xml") { + $info = $obj->infoFromDescriptionFile($params[0]); + } + } + if (empty($info)) { + $info = $obj->infoFromTgzFile($params[0]); + } + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + $obj->validatePackageInfo($info, $err, $warn); + $this->_displayValidationResults($err, $warn); + $this->ui->outputData($this->output, $command); + return true; + } + + // }}} + // {{{ doCvsTag() + + function doCvsTag($command, $options, $params) + { + $this->output = ''; + $_cmd = $command; + if (sizeof($params) < 1) { + $help = $this->getHelp($command); + return $this->raiseError("$command: missing parameter: $help[0]"); + } + $obj = new PEAR_Common; + $info = $obj->infoFromDescriptionFile($params[0]); + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + $err = $warn = array(); + $obj->validatePackageInfo($info, $err, $warn); + if (!$this->_displayValidationResults($err, $warn, true)) { + $this->ui->outputData($this->output, $command); + break; + } + $version = $info['version']; + $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $version); + $cvstag = "RELEASE_$cvsversion"; + $files = array_keys($info['filelist']); + $command = "cvs"; + if (isset($options['quiet'])) { + $command .= ' -q'; + } + if (isset($options['reallyquiet'])) { + $command .= ' -Q'; + } + $command .= ' tag'; + if (isset($options['slide'])) { + $command .= ' -F'; + } + if (isset($options['delete'])) { + $command .= ' -d'; + } + $command .= ' ' . $cvstag . ' ' . escapeshellarg($params[0]); + foreach ($files as $file) { + $command .= ' ' . escapeshellarg($file); + } + if ($this->config->get('verbose') > 1) { + $this->output .= "+ $command\n"; + } + $this->output .= "+ $command\n"; + if (empty($options['dry-run'])) { + $fp = popen($command, "r"); + while ($line = fgets($fp, 1024)) { + $this->output .= rtrim($line)."\n"; + } + pclose($fp); + } + $this->ui->outputData($this->output, $_cmd); + return true; + } + + // }}} + // {{{ doCvsDiff() + + function doCvsDiff($command, $options, $params) + { + $this->output = ''; + if (sizeof($params) < 1) { + $help = $this->getHelp($command); + return $this->raiseError("$command: missing parameter: $help[0]"); + } + $obj = new PEAR_Common; + $info = $obj->infoFromDescriptionFile($params[0]); + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + $files = array_keys($info['filelist']); + $cmd = "cvs"; + if (isset($options['quiet'])) { + $cmd .= ' -q'; + unset($options['quiet']); + } + if (isset($options['reallyquiet'])) { + $cmd .= ' -Q'; + unset($options['reallyquiet']); + } + if (isset($options['release'])) { + $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $options['release']); + $cvstag = "RELEASE_$cvsversion"; + $options['revision'] = $cvstag; + unset($options['release']); + } + $execute = true; + if (isset($options['dry-run'])) { + $execute = false; + unset($options['dry-run']); + } + $cmd .= ' diff'; + // the rest of the options are passed right on to "cvs diff" + foreach ($options as $option => $optarg) { + $arg = @$this->commands[$command]['options'][$option]['arg']; + $short = @$this->commands[$command]['options'][$option]['shortopt']; + $cmd .= $short ? " -$short" : " --$option"; + if ($arg && $optarg) { + $cmd .= ($short ? '' : '=') . escapeshellarg($optarg); + } + } + foreach ($files as $file) { + $cmd .= ' ' . escapeshellarg($file); + } + if ($this->config->get('verbose') > 1) { + $this->output .= "+ $cmd\n"; + } + if ($execute) { + $fp = popen($cmd, "r"); + while ($line = fgets($fp, 1024)) { + $this->output .= rtrim($line)."\n"; + } + pclose($fp); + } + $this->ui->outputData($this->output, $command); + return true; + } + + // }}} + // {{{ doRunTests() + + function doRunTests($command, $options, $params) + { + include_once 'PEAR/RunTest.php'; + $log = new PEAR_Common; + $log->ui = &$this->ui; // slightly hacky, but it will work + $run = new PEAR_RunTest($log); + $tests = array(); + if (isset($options['recur'])) { + $depth = 4; + } else { + $depth = 1; + } + if (!count($params)) { + $params[] = '.'; + } + foreach ($params as $p) { + if (is_dir($p)) { + $dir = System::find(array($p, '-type', 'f', + '-maxdepth', $depth, + '-name', '*.phpt')); + $tests = array_merge($tests, $dir); + } else { + if (!@file_exists($p)) { + if (!preg_match('/\.phpt$/', $p)) { + $p .= '.phpt'; + } + $dir = System::find(array(dirname($p), '-type', 'f', + '-maxdepth', $depth, + '-name', $p)); + $tests = array_merge($tests, $dir); + } else { + $tests[] = $p; + } + } + } + $ini_settings = ''; + if (isset($options['ini'])) { + $ini_settings .= $options['ini']; + } + if (isset($_ENV['TEST_PHP_INCLUDE_PATH'])) { + $ini_settings .= " -d include_path={$_ENV['TEST_PHP_INCLUDE_PATH']}"; + } + if ($ini_settings) { + $this->ui->outputData('Using INI settings: "' . $ini_settings . '"'); + } + $skipped = $passed = $failed = array(); + $this->ui->outputData('Running ' . count($tests) . ' tests', $command); + $start = time(); + if (isset($options['realtimelog'])) { + @unlink('run-tests.log'); + } + foreach ($tests as $t) { + if (isset($options['realtimelog'])) { + $fp = @fopen('run-tests.log', 'a'); + if ($fp) { + fwrite($fp, "Running test $t..."); + fclose($fp); + } + } + $result = $run->run($t, $ini_settings); + if (OS_WINDOWS) { + for($i=0;$i<2000;$i++) { + $i = $i; // delay - race conditions on windows + } + } + if (isset($options['realtimelog'])) { + $fp = @fopen('run-tests.log', 'a'); + if ($fp) { + fwrite($fp, "$result\n"); + fclose($fp); + } + } + if ($result == 'FAILED') { + $failed[] = $t; + } + if ($result == 'PASSED') { + $passed[] = $t; + } + if ($result == 'SKIPPED') { + $skipped[] = $t; + } + } + $total = date('i:s', time() - $start); + if (count($failed)) { + $output = "TOTAL TIME: $total\n"; + $output .= count($passed) . " PASSED TESTS\n"; + $output .= count($skipped) . " SKIPPED TESTS\n"; + $output .= count($failed) . " FAILED TESTS:\n"; + foreach ($failed as $failure) { + $output .= $failure . "\n"; + } + if (isset($options['realtimelog'])) { + $fp = @fopen('run-tests.log', 'a'); + } else { + $fp = @fopen('run-tests.log', 'w'); + } + if ($fp) { + fwrite($fp, $output, strlen($output)); + fclose($fp); + $this->ui->outputData('wrote log to "' . realpath('run-tests.log') . '"', $command); + } + } elseif (@file_exists('run-tests.log') && !@is_dir('run-tests.log')) { + @unlink('run-tests.log'); + } + $this->ui->outputData('TOTAL TIME: ' . $total); + $this->ui->outputData(count($passed) . ' PASSED TESTS', $command); + $this->ui->outputData(count($skipped) . ' SKIPPED TESTS', $command); + if (count($failed)) { + $this->ui->outputData(count($failed) . ' FAILED TESTS:', $command); + foreach ($failed as $failure) { + $this->ui->outputData($failure, $command); + } + } + + return true; + } + + // }}} + // {{{ doPackageDependencies() + + function doPackageDependencies($command, $options, $params) + { + // $params[0] -> the PEAR package to list its information + if (sizeof($params) != 1) { + return $this->raiseError("bad parameter(s), try \"help $command\""); + } + + $obj = new PEAR_Common(); + if (PEAR::isError($info = $obj->infoFromAny($params[0]))) { + return $this->raiseError($info); + } + + if (is_array($info['release_deps'])) { + $data = array( + 'caption' => 'Dependencies for ' . $info['package'], + 'border' => true, + 'headline' => array("Type", "Name", "Relation", "Version"), + ); + + foreach ($info['release_deps'] as $d) { + + if (isset($this->_deps_rel_trans[$d['rel']])) { + $rel = $this->_deps_rel_trans[$d['rel']]; + } else { + $rel = $d['rel']; + } + + if (isset($this->_deps_type_trans[$d['type']])) { + $type = ucfirst($this->_deps_type_trans[$d['type']]); + } else { + $type = $d['type']; + } + + if (isset($d['name'])) { + $name = $d['name']; + } else { + $name = ''; + } + + if (isset($d['version'])) { + $version = $d['version']; + } else { + $version = ''; + } + + $data['data'][] = array($type, $name, $rel, $version); + } + + $this->ui->outputData($data, $command); + return true; + } + + // Fallback + $this->ui->outputData("This package does not have any dependencies.", $command); + } + + // }}} + // {{{ doSign() + + function doSign($command, $options, $params) + { + // should move most of this code into PEAR_Packager + // so it'll be easy to implement "pear package --sign" + if (sizeof($params) != 1) { + return $this->raiseError("bad parameter(s), try \"help $command\""); + } + if (!file_exists($params[0])) { + return $this->raiseError("file does not exist: $params[0]"); + } + $obj = new PEAR_Common; + $info = $obj->infoFromTgzFile($params[0]); + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + include_once "Archive/Tar.php"; + include_once "System.php"; + $tar = new Archive_Tar($params[0]); + $tmpdir = System::mktemp('-d pearsign'); + if (!$tar->extractList('package.xml package.sig', $tmpdir)) { + return $this->raiseError("failed to extract tar file"); + } + if (file_exists("$tmpdir/package.sig")) { + return $this->raiseError("package already signed"); + } + @unlink("$tmpdir/package.sig"); + $input = $this->ui->userDialog($command, + array('GnuPG Passphrase'), + array('password')); + $gpg = popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/package.xml 2>/dev/null", "w"); + if (!$gpg) { + return $this->raiseError("gpg command failed"); + } + fwrite($gpg, "$input[0]\r"); + if (pclose($gpg) || !file_exists("$tmpdir/package.sig")) { + return $this->raiseError("gpg sign failed"); + } + $tar->addModify("$tmpdir/package.sig", '', $tmpdir); + return true; + } + + // }}} + // {{{ doMakeRPM() + + /* + + (cox) + + TODO: + + - Fill the rpm dependencies in the template file. + + IDEAS: + + - Instead of mapping the role to rpm vars, perhaps it's better + + to use directly the pear cmd to install the files by itself + + in %postrun so: + + pear -d php_dir=%{_libdir}/php/pear -d test_dir=.. <package> + + */ + + function doMakeRPM($command, $options, $params) + { + if (sizeof($params) != 1) { + return $this->raiseError("bad parameter(s), try \"help $command\""); + } + if (!file_exists($params[0])) { + return $this->raiseError("file does not exist: $params[0]"); + } + include_once "Archive/Tar.php"; + include_once "PEAR/Installer.php"; + include_once "System.php"; + $tar = new Archive_Tar($params[0]); + $tmpdir = System::mktemp('-d pear2rpm'); + $instroot = System::mktemp('-d pear2rpm'); + $tmp = $this->config->get('verbose'); + $this->config->set('verbose', 0); + $installer = new PEAR_Installer($this->ui); + $info = $installer->install($params[0], + array('installroot' => $instroot, + 'nodeps' => true)); + $pkgdir = "$info[package]-$info[version]"; + $info['rpm_xml_dir'] = '/var/lib/pear'; + $this->config->set('verbose', $tmp); + if (!$tar->extractList("package.xml", $tmpdir, $pkgdir)) { + return $this->raiseError("failed to extract $params[0]"); + } + if (!file_exists("$tmpdir/package.xml")) { + return $this->raiseError("no package.xml found in $params[0]"); + } + if (isset($options['spec-template'])) { + $spec_template = $options['spec-template']; + } else { + $spec_template = $this->config->get('data_dir') . + '/PEAR/template.spec'; + } + if (isset($options['rpm-pkgname'])) { + $rpm_pkgname_format = $options['rpm-pkgname']; + } else { + $rpm_pkgname_format = "PEAR::%s"; + } + + $info['extra_headers'] = ''; + $info['doc_files'] = ''; + $info['files'] = ''; + $info['rpm_package'] = sprintf($rpm_pkgname_format, $info['package']); + $srcfiles = 0; + foreach ($info['filelist'] as $name => $attr) { + + if (!isset($attr['role'])) { + continue; + } + $name = preg_replace('![/:\\\\]!', '/', $name); + if ($attr['role'] == 'doc') { + $info['doc_files'] .= " $name"; + + // Map role to the rpm vars + } else { + + $c_prefix = '%{_libdir}/php/pear'; + + switch ($attr['role']) { + + case 'php': + + $prefix = $c_prefix; break; + + case 'ext': + + $prefix = '%{_libdir}/php'; break; // XXX good place? + + case 'src': + + $srcfiles++; + + $prefix = '%{_includedir}/php'; break; // XXX good place? + + case 'test': + + $prefix = "$c_prefix/tests/" . $info['package']; break; + + case 'data': + + $prefix = "$c_prefix/data/" . $info['package']; break; + + case 'script': + + $prefix = '%{_bindir}'; break; + + } + + $name = str_replace('\\', '/', $name); + $info['files'] .= "$prefix/$name\n"; + + } + } + if ($srcfiles > 0) { + include_once "OS/Guess.php"; + $os = new OS_Guess; + $arch = $os->getCpu(); + } else { + $arch = 'noarch'; + } + $cfg = array('master_server', 'php_dir', 'ext_dir', 'doc_dir', + 'bin_dir', 'data_dir', 'test_dir'); + foreach ($cfg as $k) { + $info[$k] = $this->config->get($k); + } + $info['arch'] = $arch; + $fp = @fopen($spec_template, "r"); + if (!$fp) { + return $this->raiseError("could not open RPM spec file template $spec_template: $php_errormsg"); + } + $spec_contents = preg_replace('/@([a-z0-9_-]+)@/e', '$info["\1"]', fread($fp, filesize($spec_template))); + fclose($fp); + $spec_file = "$info[rpm_package]-$info[version].spec"; + $wp = fopen($spec_file, "wb"); + if (!$wp) { + return $this->raiseError("could not write RPM spec file $spec_file: $php_errormsg"); + } + fwrite($wp, $spec_contents); + fclose($wp); + $this->ui->outputData("Wrote RPM spec file $spec_file", $command); + + return true; + } + + // }}} +} + +?> diff --git a/pear/PEAR/Command/Registry.php b/pear/PEAR/Command/Registry.php new file mode 100644 index 000000000..62cb4b00e --- /dev/null +++ b/pear/PEAR/Command/Registry.php @@ -0,0 +1,351 @@ +<?php +// /* vim: set expandtab tabstop=4 shiftwidth=4: */ +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Stig Bakken <ssb@php.net> | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: Registry.php,v 1.36 2004/01/08 17:33:13 sniper Exp $ + +require_once 'PEAR/Command/Common.php'; +require_once 'PEAR/Registry.php'; +require_once 'PEAR/Config.php'; + +class PEAR_Command_Registry extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'list' => array( + 'summary' => 'List Installed Packages', + 'function' => 'doList', + 'shortcut' => 'l', + 'options' => array(), + 'doc' => '[package] +If invoked without parameters, this command lists the PEAR packages +installed in your php_dir ({config php_dir)). With a parameter, it +lists the files in that package. +', + ), + 'shell-test' => array( + 'summary' => 'Shell Script Test', + 'function' => 'doShellTest', + 'shortcut' => 'st', + 'options' => array(), + 'doc' => '<package> [[relation] version] +Tests if a package is installed in the system. Will exit(1) if it is not. + <relation> The version comparison operator. One of: + <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne + <version> The version to compare with +'), + 'info' => array( + 'summary' => 'Display information about a package', + 'function' => 'doInfo', + 'shortcut' => 'in', + 'options' => array(), + 'doc' => '<package> +Displays information about a package. The package argument may be a +local package file, an URL to a package file, or the name of an +installed package.' + ) + ); + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Registry constructor. + * + * @access public + */ + function PEAR_Command_Registry(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doList() + + function _sortinfo($a, $b) + { + return strcmp($a['package'], $b['package']); + } + + function doList($command, $options, $params) + { + $reg = new PEAR_Registry($this->config->get('php_dir')); + if (sizeof($params) == 0) { + $installed = $reg->packageInfo(); + usort($installed, array(&$this, '_sortinfo')); + $i = $j = 0; + $data = array( + 'caption' => 'Installed packages:', + 'border' => true, + 'headline' => array('Package', 'Version', 'State') + ); + foreach ($installed as $package) { + $data['data'][] = array($package['package'], + $package['version'], + @$package['release_state']); + } + if (count($installed)==0) { + $data = '(no packages installed)'; + } + $this->ui->outputData($data, $command); + } else { + if (file_exists($params[0]) && !is_dir($params[0])) { + include_once "PEAR/Common.php"; + $obj = &new PEAR_Common; + $info = $obj->infoFromAny($params[0]); + $headings = array('Package File', 'Install Path'); + $installed = false; + } else { + $info = $reg->packageInfo($params[0]); + $headings = array('Type', 'Install Path'); + $installed = true; + } + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + if ($info === null) { + return $this->raiseError("`$params[0]' not installed"); + } + $list = $info['filelist']; + if ($installed) { + $caption = 'Installed Files For ' . $params[0]; + } else { + $caption = 'Contents of ' . basename($params[0]); + } + $data = array( + 'caption' => $caption, + 'border' => true, + 'headline' => $headings); + foreach ($list as $file => $att) { + if ($installed) { + if (empty($att['installed_as'])) { + continue; + } + $data['data'][] = array($att['role'], $att['installed_as']); + } else { + if (isset($att['baseinstalldir'])) { + $dest = $att['baseinstalldir'] . DIRECTORY_SEPARATOR . + $file; + } else { + $dest = $file; + } + switch ($att['role']) { + case 'test': + case 'data': + if ($installed) { + break 2; + } + $dest = '-- will not be installed --'; + break; + case 'doc': + $dest = $this->config->get('doc_dir') . DIRECTORY_SEPARATOR . + $dest; + break; + case 'php': + default: + $dest = $this->config->get('php_dir') . DIRECTORY_SEPARATOR . + $dest; + } + $dest = preg_replace('!/+!', '/', $dest); + $file = preg_replace('!/+!', '/', $file); + $data['data'][] = array($file, $dest); + } + } + $this->ui->outputData($data, $command); + + + } + return true; + } + + // }}} + // {{{ doShellTest() + + function doShellTest($command, $options, $params) + { + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $reg = &new PEAR_Registry($this->config->get('php_dir')); + // "pear shell-test Foo" + if (sizeof($params) == 1) { + if (!$reg->packageExists($params[0])) { + exit(1); + } + // "pear shell-test Foo 1.0" + } elseif (sizeof($params) == 2) { + $v = $reg->packageInfo($params[0], 'version'); + if (!$v || !version_compare("$v", "{$params[1]}", "ge")) { + exit(1); + } + // "pear shell-test Foo ge 1.0" + } elseif (sizeof($params) == 3) { + $v = $reg->packageInfo($params[0], 'version'); + if (!$v || !version_compare("$v", "{$params[2]}", $params[1])) { + exit(1); + } + } else { + $this->popErrorHandling(); + $this->raiseError("$command: expects 1 to 3 parameters"); + exit(1); + } + } + + // }}} + // {{{ doInfo + + function doInfo($command, $options, $params) + { + // $params[0] The package for showing info + if (sizeof($params) != 1) { + return $this->raiseError("This command only accepts one param: ". + "the package you want information"); + } + if (@is_file($params[0])) { + $obj = &new PEAR_Common(); + $info = $obj->infoFromAny($params[0]); + } else { + $reg = &new PEAR_Registry($this->config->get('php_dir')); + $info = $reg->packageInfo($params[0]); + } + if (PEAR::isError($info)) { + return $info; + } + if (empty($info)) { + $this->raiseError("Nothing found for `$params[0]'"); + return; + } + unset($info['filelist']); + unset($info['changelog']); + $keys = array_keys($info); + $longtext = array('description', 'summary'); + foreach ($keys as $key) { + if (is_array($info[$key])) { + switch ($key) { + case 'maintainers': { + $i = 0; + $mstr = ''; + foreach ($info[$key] as $m) { + if ($i++ > 0) { + $mstr .= "\n"; + } + $mstr .= $m['name'] . " <"; + if (isset($m['email'])) { + $mstr .= $m['email']; + } else { + $mstr .= $m['handle'] . '@php.net'; + } + $mstr .= "> ($m[role])"; + } + $info[$key] = $mstr; + break; + } + case 'release_deps': { + $i = 0; + $dstr = ''; + foreach ($info[$key] as $d) { + if (isset($this->_deps_rel_trans[$d['rel']])) { + $rel = $this->_deps_rel_trans[$d['rel']]; + } else { + $rel = $d['rel']; + } + if (isset($this->_deps_type_trans[$d['type']])) { + $type = ucfirst($this->_deps_type_trans[$d['type']]); + } else { + $type = $d['type']; + } + if (isset($d['name'])) { + $name = $d['name'] . ' '; + } else { + $name = ''; + } + if (isset($d['version'])) { + $version = $d['version'] . ' '; + } else { + $version = ''; + } + $dstr .= "$type $name$rel $version\n"; + } + $info[$key] = $dstr; + break; + } + case 'provides' : { + $debug = $this->config->get('verbose'); + if ($debug < 2) { + $pstr = 'Classes: '; + } else { + $pstr = ''; + } + $i = 0; + foreach ($info[$key] as $p) { + if ($debug < 2 && $p['type'] != "class") { + continue; + } + // Only print classes when verbosity mode is < 2 + if ($debug < 2) { + if ($i++ > 0) { + $pstr .= ", "; + } + $pstr .= $p['name']; + } else { + if ($i++ > 0) { + $pstr .= "\n"; + } + $pstr .= ucfirst($p['type']) . " " . $p['name']; + if (isset($p['explicit']) && $p['explicit'] == 1) { + $pstr .= " (explicit)"; + } + } + } + $info[$key] = $pstr; + break; + } + default: { + $info[$key] = implode(", ", $info[$key]); + break; + } + } + } + if ($key == '_lastmodified') { + $hdate = date('Y-m-d', $info[$key]); + unset($info[$key]); + $info['Last Modified'] = $hdate; + } else { + $info[$key] = trim($info[$key]); + if (in_array($key, $longtext)) { + $info[$key] = preg_replace('/ +/', ' ', $info[$key]); + } + } + } + $caption = 'About ' . $info['package'] . '-' . $info['version']; + $data = array( + 'caption' => $caption, + 'border' => true); + foreach ($info as $key => $value) { + $key = ucwords(trim(str_replace('_', ' ', $key))); + $data['data'][] = array($key, $value); + } + $data['raw'] = $info; + + $this->ui->outputData($data, 'package-info'); + } + + // }}} +} + +?> diff --git a/pear/PEAR/Command/Remote.php b/pear/PEAR/Command/Remote.php new file mode 100644 index 000000000..bbd16093f --- /dev/null +++ b/pear/PEAR/Command/Remote.php @@ -0,0 +1,435 @@ +<?php +// /* vim: set expandtab tabstop=4 shiftwidth=4: */ +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Stig Bakken <ssb@php.net> | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: Remote.php,v 1.39 2004/04/03 15:56:00 cellog Exp $ + +require_once 'PEAR/Command/Common.php'; +require_once 'PEAR/Common.php'; +require_once 'PEAR/Remote.php'; +require_once 'PEAR/Registry.php'; + +class PEAR_Command_Remote extends PEAR_Command_Common +{ + // {{{ command definitions + + var $commands = array( + 'remote-info' => array( + 'summary' => 'Information About Remote Packages', + 'function' => 'doRemoteInfo', + 'shortcut' => 'ri', + 'options' => array(), + 'doc' => '<package> +Get details on a package from the server.', + ), + 'list-upgrades' => array( + 'summary' => 'List Available Upgrades', + 'function' => 'doListUpgrades', + 'shortcut' => 'lu', + 'options' => array(), + 'doc' => ' +List releases on the server of packages you have installed where +a newer version is available with the same release state (stable etc.).' + ), + 'remote-list' => array( + 'summary' => 'List Remote Packages', + 'function' => 'doRemoteList', + 'shortcut' => 'rl', + 'options' => array(), + 'doc' => ' +Lists the packages available on the configured server along with the +latest stable release of each package.', + ), + 'search' => array( + 'summary' => 'Search remote package database', + 'function' => 'doSearch', + 'shortcut' => 'sp', + 'options' => array(), + 'doc' => ' +Lists all packages which match the search parameters (first param +is package name, second package info)', + ), + 'list-all' => array( + 'summary' => 'List All Packages', + 'function' => 'doListAll', + 'shortcut' => 'la', + 'options' => array(), + 'doc' => ' +Lists the packages available on the configured server along with the +latest stable release of each package.', + ), + 'download' => array( + 'summary' => 'Download Package', + 'function' => 'doDownload', + 'shortcut' => 'd', + 'options' => array( + 'nocompress' => array( + 'shortopt' => 'Z', + 'doc' => 'download an uncompressed (.tar) file', + ), + ), + 'doc' => '{package|package-version} +Download a package tarball. The file will be named as suggested by the +server, for example if you download the DB package and the latest stable +version of DB is 1.2, the downloaded file will be DB-1.2.tgz.', + ), + 'clear-cache' => array( + 'summary' => 'Clear XML-RPC Cache', + 'function' => 'doClearCache', + 'shortcut' => 'cc', + 'options' => array(), + 'doc' => ' +Clear the XML-RPC cache. See also the cache_ttl configuration +parameter. +', + ), + ); + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Remote constructor. + * + * @access public + */ + function PEAR_Command_Remote(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doRemoteInfo() + + function doRemoteInfo($command, $options, $params) + { + if (sizeof($params) != 1) { + return $this->raiseError("$command expects one param: the remote package name"); + } + $r = new PEAR_Remote($this->config); + $info = $r->call('package.info', $params[0]); + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + + $reg = new PEAR_Registry($this->config->get('php_dir')); + $installed = $reg->packageInfo($info['name']); + $info['installed'] = $installed['version'] ? $installed['version'] : '- no -'; + + $this->ui->outputData($info, $command); + + return true; + } + + // }}} + // {{{ doRemoteList() + + function doRemoteList($command, $options, $params) + { + $r = new PEAR_Remote($this->config); + $list_options = false; + if ($this->config->get('preferred_state') == 'stable') + $list_options = true; + $available = $r->call('package.listAll', $list_options); + if (PEAR::isError($available)) { + return $this->raiseError($available); + } + $i = $j = 0; + $data = array( + 'caption' => 'Available packages:', + 'border' => true, + 'headline' => array('Package', 'Version'), + ); + foreach ($available as $name => $info) { + $data['data'][] = array($name, isset($info['stable']) ? $info['stable'] : '-n/a-'); + } + if (count($available)==0) { + $data = '(no packages installed yet)'; + } + $this->ui->outputData($data, $command); + return true; + } + + // }}} + // {{{ doListAll() + + function doListAll($command, $options, $params) + { + $r = new PEAR_Remote($this->config); + $reg = new PEAR_Registry($this->config->get('php_dir')); + $list_options = false; + if ($this->config->get('preferred_state') == 'stable') + $list_options = true; + $available = $r->call('package.listAll', $list_options); + if (PEAR::isError($available)) { + return $this->raiseError($available); + } + if (!is_array($available)) { + return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "'.$available.'")'); + } + $data = array( + 'caption' => 'All packages:', + 'border' => true, + 'headline' => array('Package', 'Latest', 'Local'), + ); + $local_pkgs = $reg->listPackages(); + + foreach ($available as $name => $info) { + $installed = $reg->packageInfo($name); + $desc = $info['summary']; + if (isset($params[$name])) + $desc .= "\n\n".$info['description']; + + if (isset($options['mode'])) + { + if ($options['mode'] == 'installed' && !isset($installed['version'])) + continue; + if ($options['mode'] == 'notinstalled' && isset($installed['version'])) + continue; + if ($options['mode'] == 'upgrades' + && (!isset($installed['version']) || $installed['version'] == $info['stable'])) + { + continue; + } + } + $pos = array_search(strtolower($name), $local_pkgs); + if ($pos !== false) { + unset($local_pkgs[$pos]); + } + + $data['data'][$info['category']][] = array( + $name, + @$info['stable'], + @$installed['version'], + @$desc, + @$info['deps'], + ); + } + + foreach ($local_pkgs as $name) { + $info = $reg->packageInfo($name); + $data['data']['Local'][] = array( + $info['package'], + '', + $info['version'], + $info['summary'], + @$info['release_deps'] + ); + } + + $this->ui->outputData($data, $command); + return true; + } + + // }}} + // {{{ doSearch() + + function doSearch($command, $options, $params) + { + if ((!isset($params[0]) || empty($params[0])) + && (!isset($params[1]) || empty($params[1]))) + { + return $this->raiseError('no valid search string supplied'); + }; + + $r = new PEAR_Remote($this->config); + $reg = new PEAR_Registry($this->config->get('php_dir')); + $available = $r->call('package.listAll', true, false); + if (PEAR::isError($available)) { + return $this->raiseError($available); + } + $data = array( + 'caption' => 'Matched packages:', + 'border' => true, + 'headline' => array('Package', 'Stable/(Latest)', 'Local'), + ); + + foreach ($available as $name => $info) { + $found = (!empty($params[0]) && stristr($name, $params[0]) !== false); + if (!$found && !(isset($params[1]) && !empty($params[1]) + && (stristr($info['summary'], $params[1]) !== false + || stristr($info['description'], $params[1]) !== false))) + { + continue; + }; + + $installed = $reg->packageInfo($name); + $desc = $info['summary']; + if (isset($params[$name])) + $desc .= "\n\n".$info['description']; + + $unstable = ''; + if ($info['unstable']) { + $unstable = '/(' . $info['unstable'] . $info['state'] . ')'; + } + if (!isset($info['stable']) || !$info['stable']) { + $info['stable'] = 'none'; + } + $data['data'][$info['category']][] = array( + $name, + $info['stable'] . $unstable, + $installed['version'], + $desc, + ); + } + if (!isset($data['data'])) { + return $this->raiseError('no packages found'); + } + $this->ui->outputData($data, $command); + return true; + } + + // }}} + // {{{ doDownload() + + function doDownload($command, $options, $params) + { + //$params[0] -> The package to download + if (count($params) != 1) { + return PEAR::raiseError("download expects one argument: the package to download"); + } + $server = $this->config->get('master_server'); + if (!ereg('^http://', $params[0])) { + $getoption = isset($options['nocompress'])&&$options['nocompress']==1?'?uncompress=on':''; + $pkgfile = "http://$server/get/$params[0]".$getoption; + } else { + $pkgfile = $params[0]; + } + $this->bytes_downloaded = 0; + $saved = PEAR_Common::downloadHttp($pkgfile, $this->ui, '.', + array(&$this, 'downloadCallback')); + if (PEAR::isError($saved)) { + return $this->raiseError($saved); + } + $fname = basename($saved); + $this->ui->outputData("File $fname downloaded ($this->bytes_downloaded bytes)", $command); + return true; + } + + function downloadCallback($msg, $params = null) + { + if ($msg == 'done') { + $this->bytes_downloaded = $params; + } + } + + // }}} + // {{{ doListUpgrades() + + function doListUpgrades($command, $options, $params) + { + include_once "PEAR/Registry.php"; + $remote = new PEAR_Remote($this->config); + if (empty($params[0])) { + $state = $this->config->get('preferred_state'); + } else { + $state = $params[0]; + } + $caption = 'Available Upgrades'; + if (empty($state) || $state == 'any') { + $latest = $remote->call("package.listLatestReleases"); + } else { + $latest = $remote->call("package.listLatestReleases", $state); + $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')'; + } + $caption .= ':'; + if (PEAR::isError($latest)) { + return $latest; + } + $reg = new PEAR_Registry($this->config->get('php_dir')); + $inst = array_flip($reg->listPackages()); + $data = array( + 'caption' => $caption, + 'border' => 1, + 'headline' => array('Package', 'Local', 'Remote', 'Size'), + ); + foreach ((array)$latest as $pkg => $info) { + $package = strtolower($pkg); + if (!isset($inst[$package])) { + // skip packages we don't have installed + continue; + } + extract($info); + $pkginfo = $reg->packageInfo($package); + $inst_version = $pkginfo['version']; + $inst_state = $pkginfo['release_state']; + if (version_compare("$version", "$inst_version", "le")) { + // installed version is up-to-date + continue; + } + if ($filesize >= 20480) { + $filesize += 1024 - ($filesize % 1024); + $fs = sprintf("%dkB", $filesize / 1024); + } elseif ($filesize > 0) { + $filesize += 103 - ($filesize % 103); + $fs = sprintf("%.1fkB", $filesize / 1024.0); + } else { + $fs = " -"; // XXX center instead + } + $data['data'][] = array($pkg, "$inst_version ($inst_state)", "$version ($state)", $fs); + } + if (empty($data['data'])) { + $this->ui->outputData('No upgrades available'); + } else { + $this->ui->outputData($data, $command); + } + return true; + } + + // }}} + // {{{ doClearCache() + + function doClearCache($command, $options, $params) + { + $cache_dir = $this->config->get('cache_dir'); + $verbose = $this->config->get('verbose'); + $output = ''; + if (!($dp = @opendir($cache_dir))) { + return $this->raiseError("opendir($cache_dir) failed: $php_errormsg"); + } + if ($verbose >= 1) { + $output .= "reading directory $cache_dir\n"; + } + $num = 0; + while ($ent = readdir($dp)) { + if (preg_match('/^xmlrpc_cache_[a-z0-9]{32}$/', $ent)) { + $path = $cache_dir . DIRECTORY_SEPARATOR . $ent; + $ok = @unlink($path); + if ($ok) { + if ($verbose >= 2) { + $output .= "deleted $path\n"; + } + $num++; + } elseif ($verbose >= 1) { + $output .= "failed to delete $path\n"; + } + } + } + closedir($dp); + if ($verbose >= 1) { + $output .= "$num cache entries cleared\n"; + } + $this->ui->outputData(rtrim($output), $command); + return $num; + } + + // }}} +} + +?> diff --git a/pear/PEAR/Common.php b/pear/PEAR/Common.php new file mode 100644 index 000000000..0e91270b9 --- /dev/null +++ b/pear/PEAR/Common.php @@ -0,0 +1,2094 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 4 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2003 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Authors: Stig Bakken <ssb@php.net> | +// | Tomas V.V.Cox <cox@idecnet.com> | +// +----------------------------------------------------------------------+ +// +// $Id: Common.php,v 1.126.2.2 2005/03/28 16:46:06 cellog Exp $ + +require_once 'PEAR.php'; +require_once 'Archive/Tar.php'; +require_once 'System.php'; +require_once 'PEAR/Config.php'; + +// {{{ constants and globals + +/** + * PEAR_Common error when an invalid PHP file is passed to PEAR_Common::analyzeSourceCode() + */ +define('PEAR_COMMON_ERROR_INVALIDPHP', 1); +define('_PEAR_COMMON_PACKAGE_NAME_PREG', '[A-Za-z][a-zA-Z0-9_]+'); +define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '$/'); + +// this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1 +define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-zA-Z]+\d*)?'); +define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '$/i'); + +// XXX far from perfect :-) +define('PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '/^(' . _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?$/'); + +/** + * List of temporary files and directories registered by + * PEAR_Common::addTempFile(). + * @var array + */ +$GLOBALS['_PEAR_Common_tempfiles'] = array(); + +/** + * Valid maintainer roles + * @var array + */ +$GLOBALS['_PEAR_Common_maintainer_roles'] = array('lead','developer','contributor','helper'); + +/** + * Valid release states + * @var array + */ +$GLOBALS['_PEAR_Common_release_states'] = array('alpha','beta','stable','snapshot','devel'); + +/** + * Valid dependency types + * @var array + */ +$GLOBALS['_PEAR_Common_dependency_types'] = array('pkg','ext','php','prog','ldlib','rtlib','os','websrv','sapi'); + +/** + * Valid dependency relations + * @var array + */ +$GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not', 'ne'); + +/** + * Valid file roles + * @var array + */ +$GLOBALS['_PEAR_Common_file_roles'] = array('php','ext','test','doc','data','src','script'); + +/** + * Valid replacement types + * @var array + */ +$GLOBALS['_PEAR_Common_replacement_types'] = array('php-const', 'pear-config', 'package-info'); + +/** + * Valid "provide" types + * @var array + */ +$GLOBALS['_PEAR_Common_provide_types'] = array('ext', 'prog', 'class', 'function', 'feature', 'api'); + +/** + * Valid "provide" types + * @var array + */ +$GLOBALS['_PEAR_Common_script_phases'] = array('pre-install', 'post-install', 'pre-uninstall', 'post-uninstall', 'pre-build', 'post-build', 'pre-configure', 'post-configure', 'pre-setup', 'post-setup'); + +// }}} + +/** + * Class providing common functionality for PEAR administration classes. + * @deprecated This class will disappear, and its components will be spread + * into smaller classes, like the AT&T breakup + */ +class PEAR_Common extends PEAR +{ + // {{{ properties + + /** stack of elements, gives some sort of XML context */ + var $element_stack = array(); + + /** name of currently parsed XML element */ + var $current_element; + + /** array of attributes of the currently parsed XML element */ + var $current_attributes = array(); + + /** assoc with information about a package */ + var $pkginfo = array(); + + /** + * User Interface object (PEAR_Frontend_* class). If null, + * the log() method uses print. + * @var object + */ + var $ui = null; + + /** + * Configuration object (PEAR_Config). + * @var object + */ + var $config = null; + + var $current_path = null; + + /** + * PEAR_SourceAnalyzer instance + * @var object + */ + var $source_analyzer = null; + /** + * Flag variable used to mark a valid package file + * @var boolean + * @access private + */ + var $_validPackageFile; + + // }}} + + // {{{ constructor + + /** + * PEAR_Common constructor + * + * @access public + */ + function PEAR_Common() + { + parent::PEAR(); + $this->config = &PEAR_Config::singleton(); + $this->debug = $this->config->get('verbose'); + } + + // }}} + // {{{ destructor + + /** + * PEAR_Common destructor + * + * @access private + */ + function _PEAR_Common() + { + // doesn't work due to bug #14744 + //$tempfiles = $this->_tempfiles; + $tempfiles =& $GLOBALS['_PEAR_Common_tempfiles']; + while ($file = array_shift($tempfiles)) { + if (@is_dir($file)) { + System::rm(array('-rf', $file)); + } elseif (file_exists($file)) { + unlink($file); + } + } + } + + // }}} + // {{{ addTempFile() + + /** + * Register a temporary file or directory. When the destructor is + * executed, all registered temporary files and directories are + * removed. + * + * @param string $file name of file or directory + * + * @return void + * + * @access public + */ + function addTempFile($file) + { + $GLOBALS['_PEAR_Common_tempfiles'][] = $file; + } + + // }}} + // {{{ mkDirHier() + + /** + * Wrapper to System::mkDir(), creates a directory as well as + * any necessary parent directories. + * + * @param string $dir directory name + * + * @return bool TRUE on success, or a PEAR error + * + * @access public + */ + function mkDirHier($dir) + { + $this->log(2, "+ create dir $dir"); + return System::mkDir(array('-p', $dir)); + } + + // }}} + // {{{ log() + + /** + * Logging method. + * + * @param int $level log level (0 is quiet, higher is noisier) + * @param string $msg message to write to the log + * + * @return void + * + * @access public + */ + function log($level, $msg, $append_crlf = true) + { + if ($this->debug >= $level) { + if (is_object($this->ui)) { + $this->ui->log($msg, $append_crlf); + } else { + print "$msg\n"; + } + } + } + + // }}} + // {{{ mkTempDir() + + /** + * Create and register a temporary directory. + * + * @param string $tmpdir (optional) Directory to use as tmpdir. + * Will use system defaults (for example + * /tmp or c:\windows\temp) if not specified + * + * @return string name of created directory + * + * @access public + */ + function mkTempDir($tmpdir = '') + { + if ($tmpdir) { + $topt = array('-t', $tmpdir); + } else { + $topt = array(); + } + $topt = array_merge($topt, array('-d', 'pear')); + if (!$tmpdir = System::mktemp($topt)) { + return false; + } + $this->addTempFile($tmpdir); + return $tmpdir; + } + + // }}} + // {{{ setFrontendObject() + + /** + * Set object that represents the frontend to be used. + * + * @param object Reference of the frontend object + * @return void + * @access public + */ + function setFrontendObject(&$ui) + { + $this->ui = &$ui; + } + + // }}} + + // {{{ _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; + } + + // }}} + // {{{ _element_start() + + /** + * XML parser callback for starting elements. Used while package + * format version is not yet known. + * + * @param resource $xp XML parser resource + * @param string $name name of starting element + * @param array $attribs element attributes, name => value + * + * @return void + * + * @access private + */ + function _element_start($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; + switch ($name) { + case 'package': { + $this->_validPackageFile = true; + if (isset($attribs['version'])) { + $vs = preg_replace('/[^0-9a-z]/', '_', $attribs['version']); + } else { + $vs = '1_0'; + } + $elem_start = '_element_start_'. $vs; + $elem_end = '_element_end_'. $vs; + $cdata = '_pkginfo_cdata_'. $vs; + if (!method_exists($this, $elem_start) || + !method_exists($this, $elem_end) || + !method_exists($this, $cdata)) { + $this->raiseError("No handlers for package.xml version $attribs[version]"); + return; + } + xml_set_element_handler($xp, $elem_start, $elem_end); + xml_set_character_data_handler($xp, $cdata); + break; + } + } + } + + // }}} + // {{{ _element_end() + + /** + * XML parser callback for ending elements. Used while package + * format version is not yet known. + * + * @param resource $xp XML parser resource + * @param string $name name of ending element + * + * @return void + * + * @access private + */ + function _element_end($xp, $name) + { + } + + // }}} + + // 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 ($attribs['name'] != '/') { + $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 . DIRECTORY_SEPARATOR; + } + } + $path .= $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->pkginfo['maintainers'] = array(); + $this->m_i = 0; // maintainers array index + break; + case 'maintainer': + // compatibility check + if (!isset($this->pkginfo['maintainers'])) { + $this->pkginfo['maintainers'] = array(); + $this->m_i = 0; + } + $this->pkginfo['maintainers'][$this->m_i] = array(); + $this->current_maintainer =& $this->pkginfo['maintainers'][$this->m_i]; + break; + case 'changelog': + $this->pkginfo['changelog'] = array(); + $this->c_i = 0; // changelog array index + $this->in_changelog = true; + break; + case 'release': + if ($this->in_changelog) { + $this->pkginfo['changelog'][$this->c_i] = array(); + $this->current_release = &$this->pkginfo['changelog'][$this->c_i]; + } else { + $this->current_release = &$this->pkginfo; + } + break; + case 'deps': + if (!$this->in_changelog) { + $this->pkginfo['release_deps'] = array(); + } + break; + case 'dep': + // dependencies array index + if (!$this->in_changelog) { + $this->d_i++; + $this->pkginfo['release_deps'][$this->d_i] = $attribs; + } + break; + case 'configureoptions': + if (!$this->in_changelog) { + $this->pkginfo['configure_options'] = array(); + } + break; + case 'configureoption': + if (!$this->in_changelog) { + $this->pkginfo['configure_options'][] = $attribs; + } + break; + case 'provides': + if (empty($attribs['type']) || empty($attribs['name'])) { + break; + } + $attribs['explicit'] = true; + $this->pkginfo['provides']["$attribs[type];$attribs[name]"] = $attribs; + 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': + // XXX should we check the package name here? + $this->pkginfo['package'] = ereg_replace('[^a-zA-Z0-9._]', '_', $data); + break; + case 'maintainer': + $this->current_maintainer['name'] = $data; + break; + } + break; + case 'summary': + $this->pkginfo['summary'] = $data; + break; + case 'description': + $data = $this->_unIndent($this->cdata); + $this->pkginfo['description'] = $data; + break; + case 'user': + $this->current_maintainer['handle'] = $data; + break; + case 'email': + $this->current_maintainer['email'] = $data; + break; + case 'role': + $this->current_maintainer['role'] = $data; + break; + case 'version': + $data = ereg_replace ('[^a-zA-Z0-9._\-]', '_', $data); + if ($this->in_changelog) { + $this->current_release['version'] = $data; + } else { + $this->pkginfo['version'] = $data; + } + break; + case 'date': + if ($this->in_changelog) { + $this->current_release['release_date'] = $data; + } else { + $this->pkginfo['release_date'] = $data; + } + break; + case 'notes': + // try to "de-indent" release notes in case someone + // has been over-indenting their xml ;-) + $data = $this->_unIndent($this->cdata); + if ($this->in_changelog) { + $this->current_release['release_notes'] = $data; + } else { + $this->pkginfo['release_notes'] = $data; + } + break; + case 'warnings': + if ($this->in_changelog) { + $this->current_release['release_warnings'] = $data; + } else { + $this->pkginfo['release_warnings'] = $data; + } + break; + case 'state': + if ($this->in_changelog) { + $this->current_release['release_state'] = $data; + } else { + $this->pkginfo['release_state'] = $data; + } + break; + case 'license': + if ($this->in_changelog) { + $this->current_release['release_license'] = $data; + } else { + $this->pkginfo['release_license'] = $data; + } + break; + case 'dep': + if ($data && !$this->in_changelog) { + $this->pkginfo['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 . DIRECTORY_SEPARATOR; + } + } + $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->pkginfo['maintainers'][$this->m_i]['role'])) { + $this->pkginfo['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; + } + } + + // }}} + + // {{{ infoFromTgzFile() + + /** + * Returns information about a package file. Expects the name of + * a gzipped tar file as input. + * + * @param string $file name of .tgz file + * + * @return array array with package information + * + * @access public + * + */ + function infoFromTgzFile($file) + { + if (!@is_file($file)) { + return $this->raiseError("could not open file \"$file\""); + } + $tar = new Archive_Tar($file); + if ($this->debug <= 1) { + $tar->pushErrorHandling(PEAR_ERROR_RETURN); + } + $content = $tar->listContent(); + if ($this->debug <= 1) { + $tar->popErrorHandling(); + } + if (!is_array($content)) { + $file = realpath($file); + return $this->raiseError("Could not get contents of package \"$file\"". + '. Invalid tgz file.'); + } + $xml = null; + foreach ($content as $file) { + $name = $file['filename']; + if ($name == 'package.xml') { + $xml = $name; + break; + } elseif (ereg('package.xml$', $name, $match)) { + $xml = $match[0]; + break; + } + } + $tmpdir = System::mkTemp(array('-d', 'pear')); + $this->addTempFile($tmpdir); + if (!$xml || !$tar->extractList(array($xml), $tmpdir)) { + return $this->raiseError('could not extract the package.xml file'); + } + return $this->infoFromDescriptionFile("$tmpdir/$xml"); + } + + // }}} + // {{{ infoFromDescriptionFile() + + /** + * Returns information about a package file. Expects the name of + * a package xml file as input. + * + * @param string $descfile name of package xml file + * + * @return array array with package information + * + * @access public + * + */ + function infoFromDescriptionFile($descfile) + { + if (!@is_file($descfile) || !is_readable($descfile) || + (!$fp = @fopen($descfile, 'r'))) { + return $this->raiseError("Unable to open $descfile"); + } + + // read the whole thing so we only get one cdata callback + // for each block of cdata + $data = fread($fp, filesize($descfile)); + return $this->infoFromString($data); + } + + // }}} + // {{{ infoFromString() + + /** + * Returns information about a package file. Expects the contents + * of a package xml file as input. + * + * @param string $data name of package xml file + * + * @return array array with package information + * + * @access public + * + */ + function infoFromString($data) + { + require_once('PEAR/Dependency.php'); + if (PEAR_Dependency::checkExtension($error, 'xml')) { + return $this->raiseError($error); + } + $xp = @xml_parser_create(); + if (!$xp) { + return $this->raiseError('Unable to create XML parser'); + } + xml_set_object($xp, $this); + xml_set_element_handler($xp, '_element_start', '_element_end'); + xml_set_character_data_handler($xp, '_pkginfo_cdata'); + xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false); + + $this->element_stack = array(); + $this->pkginfo = array('provides' => array()); + $this->current_element = false; + unset($this->dir_install); + $this->pkginfo['filelist'] = array(); + $this->filelist =& $this->pkginfo['filelist']; + $this->dir_names = array(); + $this->in_changelog = false; + $this->d_i = 0; + $this->cdata = ''; + $this->_validPackageFile = false; + + if (!xml_parse($xp, $data, 1)) { + $code = xml_get_error_code($xp); + $msg = sprintf("XML error: %s at line %d", + xml_error_string($code), + xml_get_current_line_number($xp)); + xml_parser_free($xp); + return $this->raiseError($msg, $code); + } + + xml_parser_free($xp); + + if (!$this->_validPackageFile) { + return $this->raiseError('Invalid Package File, no <package> tag'); + } + foreach ($this->pkginfo as $k => $v) { + if (!is_array($v)) { + $this->pkginfo[$k] = trim($v); + } + } + return $this->pkginfo; + } + // }}} + // {{{ infoFromAny() + + /** + * Returns package information from different sources + * + * This method is able to extract information about a package + * from a .tgz archive or from a XML package definition file. + * + * @access public + * @param string Filename of the source ('package.xml', '<package>.tgz') + * @return string + */ + function infoFromAny($info) + { + if (is_string($info) && file_exists($info)) { + $tmp = substr($info, -4); + if ($tmp == '.xml') { + $info = $this->infoFromDescriptionFile($info); + } elseif ($tmp == '.tar' || $tmp == '.tgz') { + $info = $this->infoFromTgzFile($info); + } else { + $fp = fopen($info, "r"); + $test = fread($fp, 5); + fclose($fp); + if ($test == "<?xml") { + $info = $this->infoFromDescriptionFile($info); + } else { + $info = $this->infoFromTgzFile($info); + } + } + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + } + return $info; + } + + // }}} + // {{{ xmlFromInfo() + + /** + * Return an XML document based on the package info (as returned + * by the PEAR_Common::infoFrom* methods). + * + * @param array $pkginfo package info + * + * @return string XML data + * + * @access public + */ + function xmlFromInfo($pkginfo) + { + static $maint_map = array( + "handle" => "user", + "name" => "name", + "email" => "email", + "role" => "role", + ); + $ret = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n"; + $ret .= "<!DOCTYPE package SYSTEM \"http://pear.php.net/dtd/package-1.0\">\n"; + $ret .= "<package version=\"1.0\"> + <name>$pkginfo[package]</name> + <summary>".htmlspecialchars($pkginfo['summary'])."</summary> + <description>".htmlspecialchars($pkginfo['description'])."</description> + <maintainers> +"; + foreach ($pkginfo['maintainers'] as $maint) { + $ret .= " <maintainer>\n"; + foreach ($maint_map as $idx => $elm) { + $ret .= " <$elm>"; + $ret .= htmlspecialchars($maint[$idx]); + $ret .= "</$elm>\n"; + } + $ret .= " </maintainer>\n"; + } + $ret .= " </maintainers>\n"; + $ret .= $this->_makeReleaseXml($pkginfo); + if (@sizeof($pkginfo['changelog']) > 0) { + $ret .= " <changelog>\n"; + foreach ($pkginfo['changelog'] as $oldrelease) { + $ret .= $this->_makeReleaseXml($oldrelease, true); + } + $ret .= " </changelog>\n"; + } + $ret .= "</package>\n"; + return $ret; + } + + // }}} + // {{{ _makeReleaseXml() + + /** + * Generate part of an XML description with release information. + * + * @param array $pkginfo array with release information + * @param bool $changelog whether the result will be in a changelog element + * + * @return string XML data + * + * @access private + */ + function _makeReleaseXml($pkginfo, $changelog = false) + { + // XXX QUOTE ENTITIES IN PCDATA, OR EMBED IN CDATA BLOCKS!! + $indent = $changelog ? " " : ""; + $ret = "$indent <release>\n"; + if (!empty($pkginfo['version'])) { + $ret .= "$indent <version>$pkginfo[version]</version>\n"; + } + if (!empty($pkginfo['release_date'])) { + $ret .= "$indent <date>$pkginfo[release_date]</date>\n"; + } + if (!empty($pkginfo['release_license'])) { + $ret .= "$indent <license>$pkginfo[release_license]</license>\n"; + } + if (!empty($pkginfo['release_state'])) { + $ret .= "$indent <state>$pkginfo[release_state]</state>\n"; + } + if (!empty($pkginfo['release_notes'])) { + $ret .= "$indent <notes>".htmlspecialchars($pkginfo['release_notes'])."</notes>\n"; + } + if (!empty($pkginfo['release_warnings'])) { + $ret .= "$indent <warnings>".htmlspecialchars($pkginfo['release_warnings'])."</warnings>\n"; + } + if (isset($pkginfo['release_deps']) && sizeof($pkginfo['release_deps']) > 0) { + $ret .= "$indent <deps>\n"; + foreach ($pkginfo['release_deps'] as $dep) { + $ret .= "$indent <dep type=\"$dep[type]\" rel=\"$dep[rel]\""; + if (isset($dep['version'])) { + $ret .= " version=\"$dep[version]\""; + } + if (isset($dep['optional'])) { + $ret .= " optional=\"$dep[optional]\""; + } + if (isset($dep['name'])) { + $ret .= ">$dep[name]</dep>\n"; + } else { + $ret .= "/>\n"; + } + } + $ret .= "$indent </deps>\n"; + } + if (isset($pkginfo['configure_options'])) { + $ret .= "$indent <configureoptions>\n"; + foreach ($pkginfo['configure_options'] as $c) { + $ret .= "$indent <configureoption name=\"". + htmlspecialchars($c['name']) . "\""; + if (isset($c['default'])) { + $ret .= " default=\"" . htmlspecialchars($c['default']) . "\""; + } + $ret .= " prompt=\"" . htmlspecialchars($c['prompt']) . "\""; + $ret .= "/>\n"; + } + $ret .= "$indent </configureoptions>\n"; + } + if (isset($pkginfo['provides'])) { + foreach ($pkginfo['provides'] as $key => $what) { + $ret .= "$indent <provides type=\"$what[type]\" "; + $ret .= "name=\"$what[name]\" "; + if (isset($what['extends'])) { + $ret .= "extends=\"$what[extends]\" "; + } + $ret .= "/>\n"; + } + } + if (isset($pkginfo['filelist'])) { + $ret .= "$indent <filelist>\n"; + foreach ($pkginfo['filelist'] as $file => $fa) { + @$ret .= "$indent <file role=\"$fa[role]\""; + if (isset($fa['baseinstalldir'])) { + $ret .= ' baseinstalldir="' . + htmlspecialchars($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="' . + htmlspecialchars($fa['install-as']) . '"'; + } + $ret .= ' name="' . htmlspecialchars($file) . '"'; + if (empty($fa['replacements'])) { + $ret .= "/>\n"; + } else { + $ret .= ">\n"; + foreach ($fa['replacements'] as $r) { + $ret .= "$indent <replace"; + foreach ($r as $k => $v) { + $ret .= " $k=\"" . htmlspecialchars($v) .'"'; + } + $ret .= "/>\n"; + } + @$ret .= "$indent </file>\n"; + } + } + $ret .= "$indent </filelist>\n"; + } + $ret .= "$indent </release>\n"; + return $ret; + } + + // }}} + // {{{ validatePackageInfo() + + /** + * Validate XML package definition file. + * + * @param string $info Filename of the package archive or of the + * package definition file + * @param array $errors Array that will contain the errors + * @param array $warnings Array that will contain the warnings + * @param string $dir_prefix (optional) directory where source files + * may be found, or empty if they are not available + * @access public + * @return boolean + */ + function validatePackageInfo($info, &$errors, &$warnings, $dir_prefix = '') + { + if (PEAR::isError($info = $this->infoFromAny($info))) { + return $this->raiseError($info); + } + if (!is_array($info)) { + return false; + } + + $errors = array(); + $warnings = array(); + if (!isset($info['package'])) { + $errors[] = 'missing package name'; + } elseif (!$this->validPackageName($info['package'])) { + $errors[] = 'invalid package name'; + } + $this->_packageName = $pn = $info['package']; + + if (empty($info['summary'])) { + $errors[] = 'missing summary'; + } elseif (strpos(trim($info['summary']), "\n") !== false) { + $warnings[] = 'summary should be on a single line'; + } + if (empty($info['description'])) { + $errors[] = 'missing description'; + } + if (empty($info['release_license'])) { + $errors[] = 'missing license'; + } + if (!isset($info['version'])) { + $errors[] = 'missing version'; + } elseif (!$this->validPackageVersion($info['version'])) { + $errors[] = 'invalid package release version'; + } + if (empty($info['release_state'])) { + $errors[] = 'missing release state'; + } elseif (!in_array($info['release_state'], PEAR_Common::getReleaseStates())) { + $errors[] = "invalid release state `$info[release_state]', should be one of: " + . implode(' ', PEAR_Common::getReleaseStates()); + } + if (empty($info['release_date'])) { + $errors[] = 'missing release date'; + } elseif (!preg_match('/^\d{4}-\d\d-\d\d$/', $info['release_date'])) { + $errors[] = "invalid release date `$info[release_date]', format is YYYY-MM-DD"; + } + if (empty($info['release_notes'])) { + $errors[] = "missing release notes"; + } + if (empty($info['maintainers'])) { + $errors[] = 'no maintainer(s)'; + } else { + $i = 1; + foreach ($info['maintainers'] as $m) { + if (empty($m['handle'])) { + $errors[] = "maintainer $i: missing handle"; + } + if (empty($m['role'])) { + $errors[] = "maintainer $i: missing role"; + } elseif (!in_array($m['role'], PEAR_Common::getUserRoles())) { + $errors[] = "maintainer $i: invalid role `$m[role]', should be one of: " + . implode(' ', PEAR_Common::getUserRoles()); + } + if (empty($m['name'])) { + $errors[] = "maintainer $i: missing name"; + } + if (empty($m['email'])) { + $errors[] = "maintainer $i: missing email"; + } + $i++; + } + } + if (!empty($info['release_deps'])) { + $i = 1; + foreach ($info['release_deps'] as $d) { + if (empty($d['type'])) { + $errors[] = "dependency $i: missing type"; + } elseif (!in_array($d['type'], PEAR_Common::getDependencyTypes())) { + $errors[] = "dependency $i: invalid type '$d[type]', should be one of: " . + implode(' ', PEAR_Common::getDependencyTypes()); + } + if (empty($d['rel'])) { + $errors[] = "dependency $i: missing relation"; + } elseif (!in_array($d['rel'], PEAR_Common::getDependencyRelations())) { + $errors[] = "dependency $i: invalid relation '$d[rel]', should be one of: " + . implode(' ', PEAR_Common::getDependencyRelations()); + } + if (!empty($d['optional'])) { + if (!in_array($d['optional'], array('yes', 'no'))) { + $errors[] = "dependency $i: invalid relation optional attribute '$d[optional]', should be one of: yes no"; + } else { + if (($d['rel'] == 'not' || $d['rel'] == 'ne') && $d['optional'] == 'yes') { + $errors[] = "dependency $i: 'not' and 'ne' dependencies cannot be " . + "optional"; + } + } + } + if ($d['rel'] != 'not' && $d['rel'] != 'has' && empty($d['version'])) { + $warnings[] = "dependency $i: missing version"; + } elseif (($d['rel'] == 'not' || $d['rel'] == 'has') && !empty($d['version'])) { + $warnings[] = "dependency $i: version ignored for `$d[rel]' dependencies"; + } + if ($d['rel'] == 'not' && !empty($d['version'])) { + $warnings[] = "dependency $i: 'not' defines a total conflict, to exclude " . + "specific versions, use 'ne'"; + } + if ($d['type'] == 'php' && !empty($d['name'])) { + $warnings[] = "dependency $i: name ignored for php type dependencies"; + } elseif ($d['type'] != 'php' && empty($d['name'])) { + $errors[] = "dependency $i: missing name"; + } + if ($d['type'] == 'php' && $d['rel'] == 'not') { + $errors[] = "dependency $i: PHP dependencies cannot use 'not' " . + "rel, use 'ne' to exclude versions"; + } + $i++; + } + } + if (!empty($info['configure_options'])) { + $i = 1; + foreach ($info['configure_options'] as $c) { + if (empty($c['name'])) { + $errors[] = "configure option $i: missing name"; + } + if (empty($c['prompt'])) { + $errors[] = "configure option $i: missing prompt"; + } + $i++; + } + } + if (empty($info['filelist'])) { + $errors[] = 'no files'; + } else { + foreach ($info['filelist'] as $file => $fa) { + if (empty($fa['role'])) { + $errors[] = "file $file: missing role"; + continue; + } elseif (!in_array($fa['role'], PEAR_Common::getFileRoles())) { + $errors[] = "file $file: invalid role, should be one of: " + . implode(' ', PEAR_Common::getFileRoles()); + } + if ($fa['role'] == 'php' && $dir_prefix) { + $this->log(1, "Analyzing $file"); + $srcinfo = $this->analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file); + if ($srcinfo) { + $this->buildProvidesArray($srcinfo); + } + } + + // (ssb) Any checks we can do for baseinstalldir? + // (cox) Perhaps checks that either the target dir and + // baseInstall doesn't cointain "../../" + } + } + $this->_packageName = $pn = $info['package']; + $pnl = strlen($pn); + foreach ((array)$this->pkginfo['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; + } + $warnings[] = "in $file: class \"$name\" not prefixed with package name \"$pn\""; + } elseif ($type == 'function') { + if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) { + continue; + } + $warnings[] = "in $file: function \"$name\" not prefixed with package name \"$pn\""; + } + } + + + return true; + } + + // }}} + // {{{ buildProvidesArray() + + /** + * 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 public + * + */ + function buildProvidesArray($srcinfo) + { + $file = basename($srcinfo['source_file']); + $pn = ''; + if (isset($this->_packageName)) { + $pn = $this->_packageName; + } + $pnl = strlen($pn); + foreach ($srcinfo['declared_classes'] as $class) { + $key = "class;$class"; + if (isset($this->pkginfo['provides'][$key])) { + continue; + } + $this->pkginfo['provides'][$key] = + array('file'=> $file, 'type' => 'class', 'name' => $class); + if (isset($srcinfo['inheritance'][$class])) { + $this->pkginfo['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->pkginfo['provides'][$key])) { + continue; + } + $this->pkginfo['provides'][$key] = + array('file'=> $file, 'type' => 'function', 'name' => $function); + } + } + + foreach ($srcinfo['declared_functions'] as $function) { + $key = "function;$function"; + if ($function{0} == '_' || isset($this->pkginfo['provides'][$key])) { + continue; + } + if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) { + $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\""; + } + $this->pkginfo['provides'][$key] = + array('file'=> $file, 'type' => 'function', 'name' => $function); + } + } + + // }}} + // {{{ analyzeSourceCode() + + /** + * Analyze the source code of the given PHP file + * + * @param string Filename of the PHP file + * @return mixed + * @access public + */ + 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; + } + $contents = fread($fp, filesize($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 != '"') { + continue; + } else { + $inquote = false; + } + } + switch ($token) { + case T_WHITESPACE: + continue; + case ';': + if ($interface) { + $current_function = ''; + $current_function_level = -1; + } + break; + case '"': + $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)) { + PEAR::raiseError("Parser error: Invalid PHP 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 (version_compare(zend_version(), '2.0', '<')) { + if (in_array(strtolower($data), + array('public', 'private', 'protected', 'abstract', + 'interface', 'implements', 'clone', 'throw') + )) { + PEAR::raiseError('Error: PHP5 packages must be packaged by php 5 PEAR'); + return false; + } + } + 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)) { + PEAR::raiseError("Parser error: Invalid PHP 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, + ); + } + + // }}} + // {{{ betterStates() + + /** + * 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); + } + + // }}} + // {{{ detectDependencies() + + function detectDependencies($any, $status_callback = null) + { + if (!function_exists("token_get_all")) { + return false; + } + if (PEAR::isError($info = $this->infoFromAny($any))) { + return $this->raiseError($info); + } + if (!is_array($info)) { + return false; + } + $deps = array(); + $used_c = $decl_c = $decl_f = $decl_m = array(); + foreach ($info['filelist'] as $file => $fa) { + $tmp = $this->analyzeSourceCode($file); + $used_c = @array_merge($used_c, $tmp['used_classes']); + $decl_c = @array_merge($decl_c, $tmp['declared_classes']); + $decl_f = @array_merge($decl_f, $tmp['declared_functions']); + $decl_m = @array_merge($decl_m, $tmp['declared_methods']); + $inheri = @array_merge($inheri, $tmp['inheritance']); + } + $used_c = array_unique($used_c); + $decl_c = array_unique($decl_c); + $undecl_c = array_diff($used_c, $decl_c); + return array('used_classes' => $used_c, + 'declared_classes' => $decl_c, + 'declared_methods' => $decl_m, + 'declared_functions' => $decl_f, + 'undeclared_classes' => $undecl_c, + 'inheritance' => $inheri, + ); + } + + // }}} + // {{{ getUserRoles() + + /** + * Get the valid roles for a PEAR package maintainer + * + * @return array + * @static + */ + function getUserRoles() + { + return $GLOBALS['_PEAR_Common_maintainer_roles']; + } + + // }}} + // {{{ getReleaseStates() + + /** + * Get the valid package release states of packages + * + * @return array + * @static + */ + function getReleaseStates() + { + return $GLOBALS['_PEAR_Common_release_states']; + } + + // }}} + // {{{ getDependencyTypes() + + /** + * Get the implemented dependency types (php, ext, pkg etc.) + * + * @return array + * @static + */ + function getDependencyTypes() + { + return $GLOBALS['_PEAR_Common_dependency_types']; + } + + // }}} + // {{{ getDependencyRelations() + + /** + * Get the implemented dependency relations (has, lt, ge etc.) + * + * @return array + * @static + */ + function getDependencyRelations() + { + return $GLOBALS['_PEAR_Common_dependency_relations']; + } + + // }}} + // {{{ getFileRoles() + + /** + * Get the implemented file roles + * + * @return array + * @static + */ + function getFileRoles() + { + return $GLOBALS['_PEAR_Common_file_roles']; + } + + // }}} + // {{{ getReplacementTypes() + + /** + * Get the implemented file replacement types in + * + * @return array + * @static + */ + function getReplacementTypes() + { + return $GLOBALS['_PEAR_Common_replacement_types']; + } + + // }}} + // {{{ getProvideTypes() + + /** + * Get the implemented file replacement types in + * + * @return array + * @static + */ + function getProvideTypes() + { + return $GLOBALS['_PEAR_Common_provide_types']; + } + + // }}} + // {{{ getScriptPhases() + + /** + * Get the implemented file replacement types in + * + * @return array + * @static + */ + function getScriptPhases() + { + return $GLOBALS['_PEAR_Common_script_phases']; + } + + // }}} + // {{{ validPackageName() + + /** + * Test whether a string contains a valid package name. + * + * @param string $name the package name to test + * + * @return bool + * + * @access public + */ + function validPackageName($name) + { + return (bool)preg_match(PEAR_COMMON_PACKAGE_NAME_PREG, $name); + } + + + // }}} + // {{{ validPackageVersion() + + /** + * Test whether a string contains a valid package version. + * + * @param string $ver the package version to test + * + * @return bool + * + * @access public + */ + function validPackageVersion($ver) + { + return (bool)preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver); + } + + + // }}} + + // {{{ downloadHttp() + + /** + * Download a file through HTTP. Considers suggested file name in + * Content-disposition: header and can run a callback function for + * different events. The callback will be called with two + * parameters: the callback type, and parameters. The implemented + * callback types are: + * + * 'setup' called at the very beginning, parameter is a UI object + * that should be used for all output + * 'message' the parameter is a string with an informational message + * 'saveas' may be used to save with a different file name, the + * parameter is the filename that is about to be used. + * If a 'saveas' callback returns a non-empty string, + * that file name will be used as the filename instead. + * Note that $save_dir will not be affected by this, only + * the basename of the file. + * 'start' download is starting, parameter is number of bytes + * that are expected, or -1 if unknown + * 'bytesread' parameter is the number of bytes read so far + * 'done' download is complete, parameter is the total number + * of bytes read + * 'connfailed' if the TCP connection fails, this callback is called + * with array(host,port,errno,errmsg) + * 'writefailed' if writing to disk fails, this callback is called + * with array(destfile,errmsg) + * + * 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 object $ui PEAR_Frontend_* instance + * @param object $config PEAR_Config instance + * @param string $save_dir (optional) directory to save file in + * @param mixed $callback (optional) function/method to call for status + * updates + * + * @return string Returns the full path 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(). + * + * @access public + */ + function downloadHttp($url, &$ui, $save_dir = '.', $callback = null) + { + if ($callback) { + call_user_func($callback, 'setup', array(&$ui)); + } + if (preg_match('!^http://([^/:?#]*)(:(\d+))?(/.*)!', $url, $matches)) { + list(,$host,,$port,$path) = $matches; + } + if (isset($this)) { + $config = &$this->config; + } else { + $config = &PEAR_Config::singleton(); + } + $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; + if ($proxy = parse_url($config->get('http_proxy'))) { + $proxy_host = @$proxy['host']; + $proxy_port = @$proxy['port']; + $proxy_user = @$proxy['user']; + $proxy_pass = @$proxy['pass']; + + if ($proxy_port == '') { + $proxy_port = 8080; + } + if ($callback) { + call_user_func($callback, 'message', "Using HTTP proxy $host:$port"); + } + } + if (empty($port)) { + $port = 80; + } + if ($proxy_host != '') { + $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr); + if (!$fp) { + if ($callback) { + call_user_func($callback, 'connfailed', array($proxy_host, $proxy_port, + $errno, $errstr)); + } + return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", $errno); + } + $request = "GET $url HTTP/1.0\r\n"; + } else { + $fp = @fsockopen($host, $port, $errno, $errstr); + if (!$fp) { + if ($callback) { + call_user_func($callback, 'connfailed', array($host, $port, + $errno, $errstr)); + } + return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno); + } + $request = "GET $path HTTP/1.0\r\n"; + } + $request .= "Host: $host:$port\r\n". + "User-Agent: PHP/".PHP_VERSION."\r\n"; + if ($proxy_host != '' && $proxy_user != '') { + $request .= 'Proxy-Authorization: Basic ' . + base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n"; + } + $request .= "\r\n"; + fwrite($fp, $request); + $headers = array(); + while (trim($line = fgets($fp, 1024))) { + if (preg_match('/^([^:]+):\s+(.*)\s*$/', $line, $matches)) { + $headers[strtolower($matches[1])] = trim($matches[2]); + } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) { + if ($matches[1] != 200) { + return PEAR::raiseError("File http://$host:$port$path not valid (received: $line)"); + } + } + } + if (isset($headers['content-disposition']) && + preg_match('/\sfilename=\"([^;]*\S)\"\s*(;|$)/', $headers['content-disposition'], $matches)) { + $save_as = basename($matches[1]); + } else { + $save_as = basename($url); + } + if ($callback) { + $tmp = call_user_func($callback, 'saveas', $save_as); + if ($tmp) { + $save_as = $tmp; + } + } + $dest_file = $save_dir . DIRECTORY_SEPARATOR . $save_as; + if (!$wp = @fopen($dest_file, 'wb')) { + fclose($fp); + if ($callback) { + call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg)); + } + return PEAR::raiseError("could not open $dest_file for writing"); + } + if (isset($headers['content-length'])) { + $length = $headers['content-length']; + } else { + $length = -1; + } + $bytes = 0; + if ($callback) { + call_user_func($callback, 'start', array(basename($dest_file), $length)); + } + while ($data = @fread($fp, 1024)) { + $bytes += strlen($data); + if ($callback) { + call_user_func($callback, 'bytesread', $bytes); + } + if (!@fwrite($wp, $data)) { + fclose($fp); + if ($callback) { + call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg)); + } + return PEAR::raiseError("$dest_file: write failed ($php_errormsg)"); + } + } + fclose($fp); + fclose($wp); + if ($callback) { + call_user_func($callback, 'done', $bytes); + } + return $dest_file; + } + + // }}} + // {{{ sortPkgDeps() + + /** + * Sort a list of arrays of array(downloaded packagefilename) by dependency. + * + * It also removes duplicate dependencies + * @param array + * @param boolean Sort packages in reverse order if true + * @return array array of array(packagefilename, package.xml contents) + */ + function sortPkgDeps(&$packages, $uninstall = false) + { + $ret = array(); + if ($uninstall) { + foreach($packages as $packageinfo) { + $ret[] = array('info' => $packageinfo); + } + } else { + foreach($packages as $packagefile) { + if (!is_array($packagefile)) { + $ret[] = array('file' => $packagefile, + 'info' => $a = $this->infoFromAny($packagefile), + 'pkg' => $a['package']); + } else { + $ret[] = $packagefile; + } + } + } + $checkdupes = array(); + $newret = array(); + foreach($ret as $i => $p) { + if (!isset($checkdupes[$p['info']['package']])) { + $checkdupes[$p['info']['package']][] = $i; + $newret[] = $p; + } + } + $this->_packageSortTree = $this->_getPkgDepTree($newret); + + $func = $uninstall ? '_sortPkgDepsRev' : '_sortPkgDeps'; + usort($newret, array(&$this, $func)); + $this->_packageSortTree = null; + $packages = $newret; + } + + // }}} + // {{{ _sortPkgDeps() + + /** + * Compare two package's package.xml, and sort + * so that dependencies are installed first + * + * This is a crude compare, real dependency checking is done on install. + * The only purpose this serves is to make the command-line + * order-independent (you can list a dependent package first, and + * installation occurs in the order required) + * @access private + */ + function _sortPkgDeps($p1, $p2) + { + $p1name = $p1['info']['package']; + $p2name = $p2['info']['package']; + $p1deps = $this->_getPkgDeps($p1); + $p2deps = $this->_getPkgDeps($p2); + if (!count($p1deps) && !count($p2deps)) { + return 0; // order makes no difference + } + if (!count($p1deps)) { + return -1; // package 2 has dependencies, package 1 doesn't + } + if (!count($p2deps)) { + return 1; // package 1 has dependencies, package 2 doesn't + } + // both have dependencies + if (in_array($p1name, $p2deps)) { + return -1; // put package 1 first: package 2 depends on package 1 + } + if (in_array($p2name, $p1deps)) { + return 1; // put package 2 first: package 1 depends on package 2 + } + if ($this->_removedDependency($p1name, $p2name)) { + return -1; // put package 1 first: package 2 depends on packages that depend on package 1 + } + if ($this->_removedDependency($p2name, $p1name)) { + return 1; // put package 2 first: package 1 depends on packages that depend on package 2 + } + // doesn't really matter if neither depends on the other + return 0; + } + + // }}} + // {{{ _sortPkgDepsRev() + + /** + * Compare two package's package.xml, and sort + * so that dependencies are uninstalled last + * + * This is a crude compare, real dependency checking is done on uninstall. + * The only purpose this serves is to make the command-line + * order-independent (you can list a dependency first, and + * uninstallation occurs in the order required) + * @access private + */ + function _sortPkgDepsRev($p1, $p2) + { + $p1name = $p1['info']['package']; + $p2name = $p2['info']['package']; + $p1deps = $this->_getRevPkgDeps($p1); + $p2deps = $this->_getRevPkgDeps($p2); + if (!count($p1deps) && !count($p2deps)) { + return 0; // order makes no difference + } + if (!count($p1deps)) { + return 1; // package 2 has dependencies, package 1 doesn't + } + if (!count($p2deps)) { + return -1; // package 2 has dependencies, package 1 doesn't + } + // both have dependencies + if (in_array($p1name, $p2deps)) { + return 1; // put package 1 last + } + if (in_array($p2name, $p1deps)) { + return -1; // put package 2 last + } + if ($this->_removedDependency($p1name, $p2name)) { + return 1; // put package 1 last: package 2 depends on packages that depend on package 1 + } + if ($this->_removedDependency($p2name, $p1name)) { + return -1; // put package 2 last: package 1 depends on packages that depend on package 2 + } + // doesn't really matter if neither depends on the other + return 0; + } + + // }}} + // {{{ _getPkgDeps() + + /** + * get an array of package dependency names + * @param array + * @return array + * @access private + */ + function _getPkgDeps($p) + { + if (!isset($p['info']['releases'])) { + return $this->_getRevPkgDeps($p); + } + $rel = array_shift($p['info']['releases']); + if (!isset($rel['deps'])) { + return array(); + } + $ret = array(); + foreach($rel['deps'] as $dep) { + if ($dep['type'] == 'pkg') { + $ret[] = $dep['name']; + } + } + return $ret; + } + + // }}} + // {{{ _getPkgDeps() + + /** + * get an array representation of the package dependency tree + * @return array + * @access private + */ + function _getPkgDepTree($packages) + { + $tree = array(); + foreach ($packages as $p) { + $package = $p['info']['package']; + $deps = $this->_getPkgDeps($p); + $tree[$package] = $deps; + } + return $tree; + } + + // }}} + // {{{ _removedDependency($p1, $p2) + + /** + * get an array of package dependency names for uninstall + * @param string package 1 name + * @param string package 2 name + * @return bool + * @access private + */ + function _removedDependency($p1, $p2) + { + if (empty($this->_packageSortTree[$p2])) { + return false; + } + if (!in_array($p1, $this->_packageSortTree[$p2])) { + foreach ($this->_packageSortTree[$p2] as $potential) { + if ($this->_removedDependency($p1, $potential)) { + return true; + } + } + return false; + } + return true; + } + + // }}} + // {{{ _getRevPkgDeps() + + /** + * get an array of package dependency names for uninstall + * @param array + * @return array + * @access private + */ + function _getRevPkgDeps($p) + { + if (!isset($p['info']['release_deps'])) { + return array(); + } + $ret = array(); + foreach($p['info']['release_deps'] as $dep) { + if ($dep['type'] == 'pkg') { + $ret[] = $dep['name']; + } + } + return $ret; + } + + // }}} +} + +?> diff --git a/pear/PEAR/Config.php b/pear/PEAR/Config.php new file mode 100644 index 000000000..ba6417352 --- /dev/null +++ b/pear/PEAR/Config.php @@ -0,0 +1,1169 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Stig Bakken <ssb@php.net> | +// +----------------------------------------------------------------------+ +// +// $Id: Config.php,v 1.52 2004/01/08 17:33:12 sniper Exp $ + +require_once 'PEAR.php'; +require_once 'System.php'; + +/** + * Last created PEAR_Config instance. + * @var object + */ +$GLOBALS['_PEAR_Config_instance'] = null; +if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) { + $PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear'; +} else { + $PEAR_INSTALL_DIR = PEAR_INSTALL_DIR; +} + +// Below we define constants with default values for all configuration +// parameters except username/password. All of them can have their +// defaults set through environment variables. The reason we use the +// PHP_ prefix is for some security, PHP protects environment +// variables starting with PHP_*. + +if (getenv('PHP_PEAR_SYSCONF_DIR')) { + define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR')); +} elseif (getenv('SystemRoot')) { + define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot')); +} else { + define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR); +} + +// Default for master_server +if (getenv('PHP_PEAR_MASTER_SERVER')) { + define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER')); +} else { + define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net'); +} + +// Default for http_proxy +if (getenv('PHP_PEAR_HTTP_PROXY')) { + define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY')); +} elseif (getenv('http_proxy')) { + define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy')); +} else { + define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', ''); +} + +// Default for php_dir +if (getenv('PHP_PEAR_INSTALL_DIR')) { + define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR')); +} else { + if (@is_dir($PEAR_INSTALL_DIR)) { + define('PEAR_CONFIG_DEFAULT_PHP_DIR', + $PEAR_INSTALL_DIR); + } else { + define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR); + } +} + +// Default for ext_dir +if (getenv('PHP_PEAR_EXTENSION_DIR')) { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR')); +} else { + if (ini_get('extension_dir')) { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir')); + } elseif (defined('PEAR_EXTENSION_DIR') && @is_dir(PEAR_EXTENSION_DIR)) { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR); + } elseif (defined('PHP_EXTENSION_DIR')) { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR); + } else { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.'); + } +} + +// Default for doc_dir +if (getenv('PHP_PEAR_DOC_DIR')) { + define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_DOC_DIR', + $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs'); +} + +// Default for bin_dir +if (getenv('PHP_PEAR_BIN_DIR')) { + define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR); +} + +// Default for data_dir +if (getenv('PHP_PEAR_DATA_DIR')) { + define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_DATA_DIR', + $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data'); +} + +// Default for test_dir +if (getenv('PHP_PEAR_TEST_DIR')) { + define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_TEST_DIR', + $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests'); +} + +// Default for cache_dir +if (getenv('PHP_PEAR_CACHE_DIR')) { + define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_CACHE_DIR', + System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' . + DIRECTORY_SEPARATOR . 'cache'); +} + +// Default for php_bin +if (getenv('PHP_PEAR_PHP_BIN')) { + define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN')); +} else { + define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR. + DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : '')); +} + +// Default for verbose +if (getenv('PHP_PEAR_VERBOSE')) { + define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE')); +} else { + define('PEAR_CONFIG_DEFAULT_VERBOSE', 1); +} + +// Default for preferred_state +if (getenv('PHP_PEAR_PREFERRED_STATE')) { + define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE')); +} else { + define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable'); +} + +// Default for umask +if (getenv('PHP_PEAR_UMASK')) { + define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK')); +} else { + define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask())); +} + +// Default for cache_ttl +if (getenv('PHP_PEAR_CACHE_TTL')) { + define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL')); +} else { + define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600); +} + +// Default for sig_type +if (getenv('PHP_PEAR_SIG_TYPE')) { + define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE')); +} else { + define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg'); +} + +// Default for sig_bin +if (getenv('PHP_PEAR_SIG_BIN')) { + define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN')); +} else { + define('PEAR_CONFIG_DEFAULT_SIG_BIN', + System::which( + 'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg')); +} + +// Default for sig_keydir +if (getenv('PHP_PEAR_SIG_KEYDIR')) { + define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR')); +} else { + define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', + PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys'); +} + +/** + * This is a class for storing configuration data, keeping track of + * which are system-defined, user-defined or defaulted. + */ +class PEAR_Config extends PEAR +{ + // {{{ properties + + /** + * Array of config files used. + * + * @var array layer => config file + */ + var $files = array( + 'system' => '', + 'user' => '', + ); + + var $layers = array(); + + /** + * Configuration data, two-dimensional array where the first + * dimension is the config layer ('user', 'system' and 'default'), + * and the second dimension is keyname => value. + * + * The order in the first dimension is important! Earlier + * layers will shadow later ones when a config value is + * requested (if a 'user' value exists, it will be returned first, + * then 'system' and finally 'default'). + * + * @var array layer => array(keyname => value, ...) + */ + var $configuration = array( + 'user' => array(), + 'system' => array(), + 'default' => array(), + ); + + /** + * Information about the configuration data. Stores the type, + * default value and a documentation string for each configuration + * value. + * + * @var array layer => array(infotype => value, ...) + */ + var $configuration_info = array( + // Internet Access + 'master_server' => array( + 'type' => 'string', + 'default' => 'pear.php.net', + 'doc' => 'name of the main PEAR server', + 'prompt' => 'PEAR server', + 'group' => 'Internet Access', + ), + 'http_proxy' => array( + 'type' => 'string', + 'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY, + 'doc' => 'HTTP proxy (host:port) to use when downloading packages', + 'prompt' => 'HTTP Proxy Server Address', + 'group' => 'Internet Access', + ), + // File Locations + 'php_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_PHP_DIR, + 'doc' => 'directory where .php files are installed', + 'prompt' => 'PEAR directory', + 'group' => 'File Locations', + ), + 'ext_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_EXT_DIR, + 'doc' => 'directory where loadable extensions are installed', + 'prompt' => 'PHP extension directory', + 'group' => 'File Locations', + ), + 'doc_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_DOC_DIR, + 'doc' => 'directory where documentation is installed', + 'prompt' => 'PEAR documentation directory', + 'group' => 'File Locations', + ), + 'bin_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_BIN_DIR, + 'doc' => 'directory where executables are installed', + 'prompt' => 'PEAR executables directory', + 'group' => 'File Locations', + ), + 'data_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_DATA_DIR, + 'doc' => 'directory where data files are installed', + 'prompt' => 'PEAR data directory', + 'group' => 'File Locations (Advanced)', + ), + 'test_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_TEST_DIR, + 'doc' => 'directory where regression tests are installed', + 'prompt' => 'PEAR test directory', + 'group' => 'File Locations (Advanced)', + ), + 'cache_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR, + 'doc' => 'directory which is used for XMLRPC cache', + 'prompt' => 'PEAR Installer cache directory', + 'group' => 'File Locations (Advanced)', + ), + 'php_bin' => array( + 'type' => 'file', + 'default' => PEAR_CONFIG_DEFAULT_PHP_BIN, + 'doc' => 'PHP CLI/CGI binary for executing scripts', + 'prompt' => 'PHP CLI/CGI binary', + 'group' => 'File Locations (Advanced)', + ), + // Maintainers + 'username' => array( + 'type' => 'string', + 'default' => '', + 'doc' => '(maintainers) your PEAR account name', + 'prompt' => 'PEAR username (for maintainers)', + 'group' => 'Maintainers', + ), + 'password' => array( + 'type' => 'password', + 'default' => '', + 'doc' => '(maintainers) your PEAR account password', + 'prompt' => 'PEAR password (for maintainers)', + 'group' => 'Maintainers', + ), + // Advanced + 'verbose' => array( + 'type' => 'integer', + 'default' => PEAR_CONFIG_DEFAULT_VERBOSE, + 'doc' => 'verbosity level +0: really quiet +1: somewhat quiet +2: verbose +3: debug', + 'prompt' => 'Debug Log Level', + 'group' => 'Advanced', + ), + 'preferred_state' => array( + 'type' => 'set', + 'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE, + 'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified', + 'valid_set' => array( + 'stable', 'beta', 'alpha', 'devel', 'snapshot'), + 'prompt' => 'Preferred Package State', + 'group' => 'Advanced', + ), + 'umask' => array( + 'type' => 'mask', + 'default' => PEAR_CONFIG_DEFAULT_UMASK, + 'doc' => 'umask used when creating files (Unix-like systems only)', + 'prompt' => 'Unix file mask', + 'group' => 'Advanced', + ), + 'cache_ttl' => array( + 'type' => 'integer', + 'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL, + 'doc' => 'amount of secs where the local cache is used and not updated', + 'prompt' => 'Cache TimeToLive', + 'group' => 'Advanced', + ), + 'sig_type' => array( + 'type' => 'set', + 'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE, + 'doc' => 'which package signature mechanism to use', + 'valid_set' => array('gpg'), + 'prompt' => 'Package Signature Type', + 'group' => 'Maintainers', + ), + 'sig_bin' => array( + 'type' => 'string', + 'default' => PEAR_CONFIG_DEFAULT_SIG_BIN, + 'doc' => 'which package signature mechanism to use', + 'prompt' => 'Signature Handling Program', + 'group' => 'Maintainers', + ), + 'sig_keyid' => array( + 'type' => 'string', + 'default' => '', + 'doc' => 'which key to use for signing with', + 'prompt' => 'Signature Key Id', + 'group' => 'Maintainers', + ), + 'sig_keydir' => array( + 'type' => 'string', + 'default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR, + 'doc' => 'which package signature mechanism to use', + 'prompt' => 'Signature Key Directory', + 'group' => 'Maintainers', + ), + ); + + // }}} + + // {{{ PEAR_Config([file], [defaults_file]) + + /** + * Constructor. + * + * @param string (optional) file to read user-defined options from + * @param string (optional) file to read system-wide defaults from + * + * @access public + * + * @see PEAR_Config::singleton + */ + function PEAR_Config($user_file = '', $system_file = '') + { + $this->PEAR(); + $sl = DIRECTORY_SEPARATOR; + if (empty($user_file)) { + if (OS_WINDOWS) { + $user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini'; + } else { + $user_file = getenv('HOME') . $sl . '.pearrc'; + } + } + if (empty($system_file)) { + if (OS_WINDOWS) { + $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini'; + } else { + $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf'; + } + } + $this->layers = array_keys($this->configuration); + $this->files['user'] = $user_file; + $this->files['system'] = $system_file; + if ($user_file && file_exists($user_file)) { + $this->readConfigFile($user_file); + } + if ($system_file && file_exists($system_file)) { + $this->mergeConfigFile($system_file, false, 'system'); + } + foreach ($this->configuration_info as $key => $info) { + $this->configuration['default'][$key] = $info['default']; + } + //$GLOBALS['_PEAR_Config_instance'] = &$this; + } + + // }}} + // {{{ singleton([file], [defaults_file]) + + /** + * Static singleton method. If you want to keep only one instance + * of this class in use, this method will give you a reference to + * the last created PEAR_Config object if one exists, or create a + * new object. + * + * @param string (optional) file to read user-defined options from + * @param string (optional) file to read system-wide defaults from + * + * @return object an existing or new PEAR_Config instance + * + * @access public + * + * @see PEAR_Config::PEAR_Config + */ + function &singleton($user_file = '', $system_file = '') + { + if (is_object($GLOBALS['_PEAR_Config_instance'])) { + return $GLOBALS['_PEAR_Config_instance']; + } + $GLOBALS['_PEAR_Config_instance'] = + &new PEAR_Config($user_file, $system_file); + return $GLOBALS['_PEAR_Config_instance']; + } + + // }}} + // {{{ readConfigFile([file], [layer]) + + /** + * Reads configuration data from a file. All existing values in + * the config layer are discarded and replaced with data from the + * file. + * + * @param string (optional) file to read from, if NULL or not + * specified, the last-used file for the same layer (second param) + * is used + * + * @param string (optional) config layer to insert data into + * ('user' or 'system') + * + * @return bool TRUE on success or a PEAR error on failure + * + * @access public + */ + function readConfigFile($file = null, $layer = 'user') + { + if (empty($this->files[$layer])) { + return $this->raiseError("unknown config file type `$layer'"); + } + if ($file === null) { + $file = $this->files[$layer]; + } + $data = $this->_readConfigDataFrom($file); + if (PEAR::isError($data)) { + return $data; + } + $this->_decodeInput($data); + $this->configuration[$layer] = $data; + return true; + } + + // }}} + // {{{ mergeConfigFile(file, [override], [layer]) + + /** + * Merges data into a config layer from a file. Does the same + * thing as readConfigFile, except it does not replace all + * existing values in the config layer. + * + * @param string file to read from + * + * @param bool (optional) whether to overwrite existing data + * (default TRUE) + * + * @param string config layer to insert data into ('user' or + * 'system') + * + * @return bool TRUE on success or a PEAR error on failure + * + * @access public. + */ + function mergeConfigFile($file, $override = true, $layer = 'user') + { + if (empty($this->files[$layer])) { + return $this->raiseError("unknown config file type `$layer'"); + } + if ($file === null) { + $file = $this->files[$layer]; + } + $data = $this->_readConfigDataFrom($file); + if (PEAR::isError($data)) { + return $data; + } + $this->_decodeInput($data); + if ($override) { + $this->configuration[$layer] = array_merge($this->configuration[$layer], $data); + } else { + $this->configuration[$layer] = array_merge($data, $this->configuration[$layer]); + } + return true; + } + + // }}} + // {{{ writeConfigFile([file], [layer]) + + /** + * Writes data into a config layer from a file. + * + * @param string file to read from + * + * @param bool (optional) whether to overwrite existing data + * (default TRUE) + * + * @param string config layer to insert data into ('user' or + * 'system') + * + * @return bool TRUE on success or a PEAR error on failure + * + * @access public. + */ + function writeConfigFile($file = null, $layer = 'user', $data = null) + { + if ($layer == 'both' || $layer == 'all') { + foreach ($this->files as $type => $file) { + $err = $this->writeConfigFile($file, $type, $data); + if (PEAR::isError($err)) { + return $err; + } + } + return true; + } + if (empty($this->files[$layer])) { + return $this->raiseError("unknown config file type `$layer'"); + } + if ($file === null) { + $file = $this->files[$layer]; + } + $data = ($data === null) ? $this->configuration[$layer] : $data; + $this->_encodeOutput($data); + $opt = array('-p', dirname($file)); + if (!@System::mkDir($opt)) { + return $this->raiseError("could not create directory: " . dirname($file)); + } + if (@is_file($file) && !@is_writeable($file)) { + return $this->raiseError("no write access to $file!"); + } + $fp = @fopen($file, "w"); + if (!$fp) { + return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed"); + } + $contents = "#PEAR_Config 0.9\n" . serialize($data); + if (!@fwrite($fp, $contents)) { + return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed"); + } + return true; + } + + // }}} + // {{{ _readConfigDataFrom(file) + + /** + * Reads configuration data from a file and returns the parsed data + * in an array. + * + * @param string file to read from + * + * @return array configuration data or a PEAR error on failure + * + * @access private + */ + function _readConfigDataFrom($file) + { + $fp = @fopen($file, "r"); + if (!$fp) { + return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed"); + } + $size = filesize($file); + $rt = get_magic_quotes_runtime(); + set_magic_quotes_runtime(0); + $contents = fread($fp, $size); + set_magic_quotes_runtime($rt); + fclose($fp); + $version = '0.1'; + if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) { + $version = $matches[1]; + $contents = substr($contents, strlen($matches[0])); + } + if (version_compare("$version", '1', '<')) { + $data = unserialize($contents); + if (!is_array($data)) { + if (strlen(trim($contents)) > 0) { + $error = "PEAR_Config: bad data in $file"; +// if (isset($this)) { + return $this->raiseError($error); +// } else { +// return PEAR::raiseError($error); + } else { + $data = array(); + } + } + // add parsing of newer formats here... + } else { + return $this->raiseError("$file: unknown version `$version'"); + } + return $data; + } + + // }}} + // {{{ getConfFile(layer) + /** + * Gets the file used for storing the config for a layer + * + * @param string $layer 'user' or 'system' + */ + + function getConfFile($layer) + { + return $this->files[$layer]; + } + + // }}} + // {{{ _encodeOutput(&data) + + /** + * Encodes/scrambles configuration data before writing to files. + * Currently, 'password' values will be base64-encoded as to avoid + * that people spot cleartext passwords by accident. + * + * @param array (reference) array to encode values in + * + * @return bool TRUE on success + * + * @access private + */ + function _encodeOutput(&$data) + { + foreach ($data as $key => $value) { + if (!isset($this->configuration_info[$key])) { + continue; + } + $type = $this->configuration_info[$key]['type']; + switch ($type) { + // we base64-encode passwords so they are at least + // not shown in plain by accident + case 'password': { + $data[$key] = base64_encode($data[$key]); + break; + } + case 'mask': { + $data[$key] = octdec($data[$key]); + break; + } + } + } + return true; + } + + // }}} + // {{{ _decodeInput(&data) + + /** + * Decodes/unscrambles configuration data after reading from files. + * + * @param array (reference) array to encode values in + * + * @return bool TRUE on success + * + * @access private + * + * @see PEAR_Config::_encodeOutput + */ + function _decodeInput(&$data) + { + if (!is_array($data)) { + return true; + } + foreach ($data as $key => $value) { + if (!isset($this->configuration_info[$key])) { + continue; + } + $type = $this->configuration_info[$key]['type']; + switch ($type) { + case 'password': { + $data[$key] = base64_decode($data[$key]); + break; + } + case 'mask': { + $data[$key] = decoct($data[$key]); + break; + } + } + } + return true; + } + + // }}} + // {{{ get(key, [layer]) + + /** + * Returns a configuration value, prioritizing layers as per the + * layers property. + * + * @param string config key + * + * @return mixed the config value, or NULL if not found + * + * @access public + */ + function get($key, $layer = null) + { + if ($layer === null) { + foreach ($this->layers as $layer) { + if (isset($this->configuration[$layer][$key])) { + return $this->configuration[$layer][$key]; + } + } + } elseif (isset($this->configuration[$layer][$key])) { + return $this->configuration[$layer][$key]; + } + return null; + } + + // }}} + // {{{ set(key, value, [layer]) + + /** + * Set a config value in a specific layer (defaults to 'user'). + * Enforces the types defined in the configuration_info array. An + * integer config variable will be cast to int, and a set config + * variable will be validated against its legal values. + * + * @param string config key + * + * @param string config value + * + * @param string (optional) config layer + * + * @return bool TRUE on success, FALSE on failure + * + * @access public + */ + function set($key, $value, $layer = 'user') + { + if (empty($this->configuration_info[$key])) { + return false; + } + extract($this->configuration_info[$key]); + switch ($type) { + case 'integer': + $value = (int)$value; + break; + case 'set': { + // If a valid_set is specified, require the value to + // be in the set. If there is no valid_set, accept + // any value. + if ($valid_set) { + reset($valid_set); + if ((key($valid_set) === 0 && !in_array($value, $valid_set)) || + (key($valid_set) !== 0 && empty($valid_set[$value]))) + { + return false; + } + } + break; + } + } + $this->configuration[$layer][$key] = $value; + return true; + } + + // }}} + // {{{ getType(key) + + /** + * Get the type of a config value. + * + * @param string config key + * + * @return string type, one of "string", "integer", "file", + * "directory", "set" or "password". + * + * @access public + * + */ + function getType($key) + { + if (isset($this->configuration_info[$key])) { + return $this->configuration_info[$key]['type']; + } + return false; + } + + // }}} + // {{{ getDocs(key) + + /** + * Get the documentation for a config value. + * + * @param string config key + * + * @return string documentation string + * + * @access public + * + */ + function getDocs($key) + { + if (isset($this->configuration_info[$key])) { + return $this->configuration_info[$key]['doc']; + } + return false; + } + // }}} + // {{{ getPrompt(key) + + /** + * Get the short documentation for a config value. + * + * @param string config key + * + * @return string short documentation string + * + * @access public + * + */ + function getPrompt($key) + { + if (isset($this->configuration_info[$key])) { + return $this->configuration_info[$key]['prompt']; + } + return false; + } + // }}} + // {{{ getGroup(key) + + /** + * Get the parameter group for a config key. + * + * @param string config key + * + * @return string parameter group + * + * @access public + * + */ + function getGroup($key) + { + if (isset($this->configuration_info[$key])) { + return $this->configuration_info[$key]['group']; + } + return false; + } + + // }}} + // {{{ getGroups() + + /** + * Get the list of parameter groups. + * + * @return array list of parameter groups + * + * @access public + * + */ + function getGroups() + { + $tmp = array(); + foreach ($this->configuration_info as $key => $info) { + $tmp[$info['group']] = 1; + } + return array_keys($tmp); + } + + // }}} + // {{{ getGroupKeys() + + /** + * Get the list of the parameters in a group. + * + * @param string $group parameter group + * + * @return array list of parameters in $group + * + * @access public + * + */ + function getGroupKeys($group) + { + $keys = array(); + foreach ($this->configuration_info as $key => $info) { + if ($info['group'] == $group) { + $keys[] = $key; + } + } + return $keys; + } + + // }}} + // {{{ getSetValues(key) + + /** + * Get the list of allowed set values for a config value. Returns + * NULL for config values that are not sets. + * + * @param string config key + * + * @return array enumerated array of set values, or NULL if the + * config key is unknown or not a set + * + * @access public + * + */ + function getSetValues($key) + { + if (isset($this->configuration_info[$key]) && + isset($this->configuration_info[$key]['type']) && + $this->configuration_info[$key]['type'] == 'set') + { + $valid_set = $this->configuration_info[$key]['valid_set']; + reset($valid_set); + if (key($valid_set) === 0) { + return $valid_set; + } + return array_keys($valid_set); + } + return false; + } + + // }}} + // {{{ getKeys() + + /** + * Get all the current config keys. + * + * @return array simple array of config keys + * + * @access public + */ + function getKeys() + { + $keys = array(); + foreach ($this->layers as $layer) { + $keys = array_merge($keys, $this->configuration[$layer]); + } + return array_keys($keys); + } + + // }}} + // {{{ remove(key, [layer]) + + /** + * Remove the a config key from a specific config layer. + * + * @param string config key + * + * @param string (optional) config layer + * + * @return bool TRUE on success, FALSE on failure + * + * @access public + */ + function remove($key, $layer = 'user') + { + if (isset($this->configuration[$layer][$key])) { + unset($this->configuration[$layer][$key]); + return true; + } + return false; + } + + // }}} + // {{{ removeLayer(layer) + + /** + * Temporarily remove an entire config layer. USE WITH CARE! + * + * @param string config key + * + * @param string (optional) config layer + * + * @return bool TRUE on success, FALSE on failure + * + * @access public + */ + function removeLayer($layer) + { + if (isset($this->configuration[$layer])) { + $this->configuration[$layer] = array(); + return true; + } + return false; + } + + // }}} + // {{{ store([layer]) + + /** + * Stores configuration data in a layer. + * + * @param string config layer to store + * + * @return bool TRUE on success, or PEAR error on failure + * + * @access public + */ + function store($layer = 'user', $data = null) + { + return $this->writeConfigFile(null, $layer, $data); + } + + // }}} + // {{{ toDefault(key) + + /** + * Unset the user-defined value of a config key, reverting the + * value to the system-defined one. + * + * @param string config key + * + * @return bool TRUE on success, FALSE on failure + * + * @access public + */ + function toDefault($key) + { + trigger_error("PEAR_Config::toDefault() deprecated, use PEAR_Config::remove() instead", E_USER_NOTICE); + return $this->remove($key, 'user'); + } + + // }}} + // {{{ definedBy(key) + + /** + * Tells what config layer that gets to define a key. + * + * @param string config key + * + * @return string the config layer, or an empty string if not found + * + * @access public + */ + function definedBy($key) + { + foreach ($this->layers as $layer) { + if (isset($this->configuration[$layer][$key])) { + return $layer; + } + } + return ''; + } + + // }}} + // {{{ isDefaulted(key) + + /** + * Tells whether a config value has a system-defined value. + * + * @param string config key + * + * @return bool + * + * @access public + * + * @deprecated + */ + function isDefaulted($key) + { + trigger_error("PEAR_Config::isDefaulted() deprecated, use PEAR_Config::definedBy() instead", E_USER_NOTICE); + return $this->definedBy($key) == 'system'; + } + + // }}} + // {{{ isDefined(key) + + /** + * Tells whether a given key exists as a config value. + * + * @param string config key + * + * @return bool whether <config key> exists in this object + * + * @access public + */ + function isDefined($key) + { + foreach ($this->layers as $layer) { + if (isset($this->configuration[$layer][$key])) { + return true; + } + } + return false; + } + + // }}} + // {{{ isDefinedLayer(key) + + /** + * Tells whether a given config layer exists. + * + * @param string config layer + * + * @return bool whether <config layer> exists in this object + * + * @access public + */ + function isDefinedLayer($layer) + { + return isset($this->configuration[$layer]); + } + + // }}} + // {{{ getLayers() + + /** + * Returns the layers defined (except the 'default' one) + * + * @return array of the defined layers + */ + function getLayers() + { + $cf = $this->configuration; + unset($cf['default']); + return array_keys($cf); + } + + // }}} +} + +?> diff --git a/pear/PEAR/Dependency.php b/pear/PEAR/Dependency.php new file mode 100644 index 000000000..fcbda7b8d --- /dev/null +++ b/pear/PEAR/Dependency.php @@ -0,0 +1,487 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Authors: Tomas V.V.Cox <cox@idecnet.com> | +// | Stig Bakken <ssb@php.net> | +// +----------------------------------------------------------------------+ +// +// $Id: Dependency.php,v 1.36.4.1 2005/03/28 16:46:06 cellog Exp $ + +require_once "PEAR.php"; + +define('PEAR_DEPENDENCY_MISSING', -1); +define('PEAR_DEPENDENCY_CONFLICT', -2); +define('PEAR_DEPENDENCY_UPGRADE_MINOR', -3); +define('PEAR_DEPENDENCY_UPGRADE_MAJOR', -4); +define('PEAR_DEPENDENCY_BAD_DEPENDENCY', -5); +define('PEAR_DEPENDENCY_MISSING_OPTIONAL', -6); +define('PEAR_DEPENDENCY_CONFLICT_OPTIONAL', -7); +define('PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL', -8); +define('PEAR_DEPENDENCY_UPGRADE_MAJOR_OPTIONAL', -9); + +/** + * Dependency check for PEAR packages + * + * The class is based on the dependency RFC that can be found at + * http://cvs.php.net/cvs.php/pearweb/rfc. It requires PHP >= 4.1 + * + * @author Tomas V.V.Vox <cox@idecnet.com> + * @author Stig Bakken <ssb@php.net> + */ +class PEAR_Dependency +{ + // {{{ constructor + /** + * Constructor + * + * @access public + * @param object Registry object + * @return void + */ + function PEAR_Dependency(&$registry) + { + $this->registry = &$registry; + } + + // }}} + // {{{ callCheckMethod() + + /** + * This method maps the XML dependency definition to the + * corresponding one from PEAR_Dependency + * + * <pre> + * $opts => Array + * ( + * [type] => pkg + * [rel] => ge + * [version] => 3.4 + * [name] => HTML_Common + * [optional] => false + * ) + * </pre> + * + * @param string Error message + * @param array Options + * @return boolean + */ + function callCheckMethod(&$errmsg, $opts) + { + $rel = isset($opts['rel']) ? $opts['rel'] : 'has'; + $req = isset($opts['version']) ? $opts['version'] : null; + $name = isset($opts['name']) ? $opts['name'] : null; + $opt = (isset($opts['optional']) && $opts['optional'] == 'yes') ? + $opts['optional'] : null; + $errmsg = ''; + switch ($opts['type']) { + case 'pkg': + return $this->checkPackage($errmsg, $name, $req, $rel, $opt); + break; + case 'ext': + return $this->checkExtension($errmsg, $name, $req, $rel, $opt); + break; + case 'php': + return $this->checkPHP($errmsg, $req, $rel); + break; + case 'prog': + return $this->checkProgram($errmsg, $name); + break; + case 'os': + return $this->checkOS($errmsg, $name); + break; + case 'sapi': + return $this->checkSAPI($errmsg, $name); + break; + case 'zend': + return $this->checkZend($errmsg, $name); + break; + default: + return "'{$opts['type']}' dependency type not supported"; + } + } + + // }}} + // {{{ checkPackage() + + /** + * Package dependencies check method + * + * @param string $errmsg Empty string, it will be populated with an error message, if any + * @param string $name Name of the package to test + * @param string $req The package version required + * @param string $relation How to compare versions with each other + * @param bool $opt Whether the relationship is optional + * + * @return mixed bool false if no error or the error string + */ + function checkPackage(&$errmsg, $name, $req = null, $relation = 'has', + $opt = false) + { + if (is_string($req) && substr($req, 0, 2) == 'v.') { + $req = substr($req, 2); + } + switch ($relation) { + case 'has': + if (!$this->registry->packageExists($name)) { + if ($opt) { + $errmsg = "package `$name' is recommended to utilize some features."; + return PEAR_DEPENDENCY_MISSING_OPTIONAL; + } + $errmsg = "requires package `$name'"; + return PEAR_DEPENDENCY_MISSING; + } + return false; + case 'not': + if ($this->registry->packageExists($name)) { + $errmsg = "conflicts with package `$name'"; + return PEAR_DEPENDENCY_CONFLICT; + } + return false; + case 'lt': + case 'le': + case 'eq': + case 'ne': + case 'ge': + case 'gt': + $version = $this->registry->packageInfo($name, 'version'); + if (!$this->registry->packageExists($name) + || !version_compare("$version", "$req", $relation)) + { + $code = $this->codeFromRelation($relation, $version, $req, $opt); + if ($opt) { + $errmsg = "package `$name' version " . $this->signOperator($relation) . + " $req is recommended to utilize some features."; + if ($version) { + $errmsg .= " Installed version is $version"; + } + return $code; + } + $errmsg = "requires package `$name' " . + $this->signOperator($relation) . " $req"; + return $code; + } + return false; + } + $errmsg = "relation '$relation' with requirement '$req' is not supported (name=$name)"; + return PEAR_DEPENDENCY_BAD_DEPENDENCY; + } + + // }}} + // {{{ checkPackageUninstall() + + /** + * Check package dependencies on uninstall + * + * @param string $error The resultant error string + * @param string $warning The resultant warning string + * @param string $name Name of the package to test + * + * @return bool true if there were errors + */ + function checkPackageUninstall(&$error, &$warning, $package) + { + $error = null; + $packages = $this->registry->listPackages(); + foreach ($packages as $pkg) { + if ($pkg == $package) { + continue; + } + $deps = $this->registry->packageInfo($pkg, 'release_deps'); + if (empty($deps)) { + continue; + } + foreach ($deps as $dep) { + if ($dep['type'] == 'pkg' && strcasecmp($dep['name'], $package) == 0) { + if ($dep['rel'] == 'ne' || $dep['rel'] == 'not') { + continue; + } + if (isset($dep['optional']) && $dep['optional'] == 'yes') { + $warning .= "\nWarning: Package '$pkg' optionally depends on '$package'"; + } else { + $error .= "Package '$pkg' depends on '$package'\n"; + } + } + } + } + return ($error) ? true : false; + } + + // }}} + // {{{ checkExtension() + + /** + * Extension dependencies check method + * + * @param string $name Name of the extension to test + * @param string $req_ext_ver Required extension version to compare with + * @param string $relation How to compare versions with eachother + * @param bool $opt Whether the relationship is optional + * + * @return mixed bool false if no error or the error string + */ + function checkExtension(&$errmsg, $name, $req = null, $relation = 'has', + $opt = false) + { + if ($relation == 'not') { + if (extension_loaded($name)) { + $errmsg = "conflicts with PHP extension '$name'"; + return PEAR_DEPENDENCY_CONFLICT; + } else { + return false; + } + } + + if (!extension_loaded($name)) { + if ($relation == 'not') { + return false; + } + if ($opt) { + $errmsg = "'$name' PHP extension is recommended to utilize some features"; + return PEAR_DEPENDENCY_MISSING_OPTIONAL; + } + $errmsg = "'$name' PHP extension is not installed"; + return PEAR_DEPENDENCY_MISSING; + } + if ($relation == 'has') { + return false; + } + $code = false; + if (is_string($req) && substr($req, 0, 2) == 'v.') { + $req = substr($req, 2); + } + $ext_ver = phpversion($name); + $operator = $relation; + // Force params to be strings, otherwise the comparation will fail (ex. 0.9==0.90) + if (!version_compare("$ext_ver", "$req", $operator)) { + $errmsg = "'$name' PHP extension version " . + $this->signOperator($operator) . " $req is required"; + $code = $this->codeFromRelation($relation, $ext_ver, $req, $opt); + if ($opt) { + $errmsg = "'$name' PHP extension version " . $this->signOperator($operator) . + " $req is recommended to utilize some features"; + return $code; + } + } + return $code; + } + + // }}} + // {{{ checkOS() + + /** + * Operating system dependencies check method + * + * @param string $os Name of the operating system + * + * @return mixed bool false if no error or the error string + */ + function checkOS(&$errmsg, $os) + { + // XXX Fixme: Implement a more flexible way, like + // comma separated values or something similar to PEAR_OS + static $myos; + if (empty($myos)) { + include_once "OS/Guess.php"; + $myos = new OS_Guess(); + } + // only 'has' relation is currently supported + if ($myos->matchSignature($os)) { + return false; + } + $errmsg = "'$os' operating system not supported"; + return PEAR_DEPENDENCY_CONFLICT; + } + + // }}} + // {{{ checkPHP() + + /** + * PHP version check method + * + * @param string $req which version to compare + * @param string $relation how to compare the version + * + * @return mixed bool false if no error or the error string + */ + function checkPHP(&$errmsg, $req, $relation = 'ge') + { + // this would be a bit stupid, but oh well :) + if ($relation == 'has') { + return false; + } + if ($relation == 'not') { + $errmsg = 'Invalid dependency - "not" is not allowed for php dependencies, ' . + 'php cannot conflict with itself'; + return PEAR_DEPENDENCY_BAD_DEPENDENCY; + } + if (substr($req, 0, 2) == 'v.') { + $req = substr($req,2, strlen($req) - 2); + } + $php_ver = phpversion(); + $operator = $relation; + if (!version_compare("$php_ver", "$req", $operator)) { + $errmsg = "PHP version " . $this->signOperator($operator) . + " $req is required"; + return PEAR_DEPENDENCY_CONFLICT; + } + return false; + } + + // }}} + // {{{ checkProgram() + + /** + * External program check method. Looks for executable files in + * directories listed in the PATH environment variable. + * + * @param string $program which program to look for + * + * @return mixed bool false if no error or the error string + */ + function checkProgram(&$errmsg, $program) + { + // XXX FIXME honor safe mode + $exe_suffix = OS_WINDOWS ? '.exe' : ''; + $path_elements = explode(PATH_SEPARATOR, getenv('PATH')); + foreach ($path_elements as $dir) { + $file = $dir . DIRECTORY_SEPARATOR . $program . $exe_suffix; + if (@file_exists($file) && @is_executable($file)) { + return false; + } + } + $errmsg = "'$program' program is not present in the PATH"; + return PEAR_DEPENDENCY_MISSING; + } + + // }}} + // {{{ checkSAPI() + + /** + * SAPI backend check method. Version comparison is not yet + * available here. + * + * @param string $name name of SAPI backend + * @param string $req which version to compare + * @param string $relation how to compare versions (currently + * hardcoded to 'has') + * @return mixed bool false if no error or the error string + */ + function checkSAPI(&$errmsg, $name, $req = null, $relation = 'has') + { + // XXX Fixme: There is no way to know if the user has or + // not other SAPI backends installed than the installer one + + $sapi_backend = php_sapi_name(); + // Version comparisons not supported, sapi backends don't have + // version information yet. + if ($sapi_backend == $name) { + return false; + } + $errmsg = "'$sapi_backend' SAPI backend not supported"; + return PEAR_DEPENDENCY_CONFLICT; + } + + // }}} + // {{{ checkZend() + + /** + * Zend version check method + * + * @param string $req which version to compare + * @param string $relation how to compare the version + * + * @return mixed bool false if no error or the error string + */ + function checkZend(&$errmsg, $req, $relation = 'ge') + { + if (substr($req, 0, 2) == 'v.') { + $req = substr($req,2, strlen($req) - 2); + } + $zend_ver = zend_version(); + $operator = substr($relation,0,2); + if (!version_compare("$zend_ver", "$req", $operator)) { + $errmsg = "Zend version " . $this->signOperator($operator) . + " $req is required"; + return PEAR_DEPENDENCY_CONFLICT; + } + return false; + } + + // }}} + // {{{ signOperator() + + /** + * Converts text comparing operators to them sign equivalents + * + * Example: 'ge' to '>=' + * + * @access public + * @param string Operator + * @return string Sign equivalent + */ + function signOperator($operator) + { + switch($operator) { + case 'lt': return '<'; + case 'le': return '<='; + case 'gt': return '>'; + case 'ge': return '>='; + case 'eq': return '=='; + case 'ne': return '!='; + default: + return $operator; + } + } + + // }}} + // {{{ codeFromRelation() + + /** + * Convert relation into corresponding code + * + * @access public + * @param string Relation + * @param string Version + * @param string Requirement + * @param bool Optional dependency indicator + * @return integer + */ + function codeFromRelation($relation, $version, $req, $opt = false) + { + $code = PEAR_DEPENDENCY_BAD_DEPENDENCY; + switch ($relation) { + case 'gt': case 'ge': case 'eq': + // upgrade + $have_major = preg_replace('/\D.*/', '', $version); + $need_major = preg_replace('/\D.*/', '', $req); + if ($need_major > $have_major) { + $code = $opt ? PEAR_DEPENDENCY_UPGRADE_MAJOR_OPTIONAL : + PEAR_DEPENDENCY_UPGRADE_MAJOR; + } else { + $code = $opt ? PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL : + PEAR_DEPENDENCY_UPGRADE_MINOR; + } + break; + case 'lt': case 'le': case 'ne': + $code = $opt ? PEAR_DEPENDENCY_CONFLICT_OPTIONAL : + PEAR_DEPENDENCY_CONFLICT; + break; + } + return $code; + } + + // }}} +} +?> diff --git a/pear/PEAR/DependencyDB.php b/pear/PEAR/DependencyDB.php new file mode 100644 index 000000000..7f6606935 --- /dev/null +++ b/pear/PEAR/DependencyDB.php @@ -0,0 +1,348 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Authors: Tomas V.V.Cox <cox@idecnet.com> | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: DependencyDB.php,v 1.5 2004/01/08 17:33:12 sniper Exp $ + +/** +Experimental dependencies database handling functions (not yet in production) + +<?php +include './DependencyDB.php'; +PEAR::setErrorHandling(PEAR_ERROR_DIE); +$dep = PEAR_DependencyDB::singleton('./test.deps', '/home/cox/www/include/pear'); +//$dep->rebuildDB(); +$a = $dep->checkAction('uninstall', 'net_socket'); +print_r($a); +?> + +**/ + +require_once 'PEAR.php'; +require_once 'PEAR/Registry.php'; +require_once 'PEAR/Dependency.php'; + +class PEAR_DependencyDB extends PEAR +{ + // {{{ properties + + var $pear_reg = false; + var $pear_dep = false; + var $depdb_file = false; + var $lockfile = false; + var $lock_fp = false; + var $depdb_version = '1.0'; + + // }}} + // {{{ & singleton() + + function &singleton($depdb_file, $reg_file) + { + $obj = new PEAR_DependencyDB; + $reg = &new PEAR_Registry($reg_file); + $obj->pear_reg = $reg; + $obj->lockfile = $reg->lockfile; + $obj->pear_dep = new PEAR_Dependency($reg); + $obj->depdb_file = $depdb_file; + $obj->assertDepsDB(); + return $obj; + } + + // }}} + // {{{ assertDepsDB() + + function assertDepsDB() + { + if (!is_file($this->depdb_file)) { + $this->rebuildDB(); + } else { + $depdb = $this->_getDepDB(); + // Datatype format has been changed, rebuild the Deps DB + if ($depdb['depdb_version'] != $this->depdb_version) { + $this->rebuildDB(); + } + } + } + + // }}} + // {{{ _lock() + + function _lock($mode = LOCK_EX) + { + if (!eregi('Windows 9', php_uname())) { + if ($mode != LOCK_UN && is_resource($this->lock_fp)) { + // 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 (@!is_file($this->lockfile)) { + touch($this->lockfile); + } + $open_mode = 'r'; + } + + $this->lock_fp = @fopen($this->lockfile, $open_mode); + + if (!is_resource($this->lock_fp)) { + return $this->raiseError("could not create lock file" . + (isset($php_errormsg) ? ": " . $php_errormsg : "")); + } + if (!(int)flock($this->lock_fp, $mode)) { + switch ($mode) { + case LOCK_SH: $str = 'shared'; break; + case LOCK_EX: $str = 'exclusive'; break; + case LOCK_UN: $str = 'unlock'; break; + default: $str = 'unknown'; break; + } + return $this->raiseError("could not acquire $str lock ($this->lockfile)"); + } + } + return true; + } + + // }}} + // {{{ _unlock() + + function _unlock() + { + $ret = $this->_lock(LOCK_UN); + $this->lock_fp = null; + return $ret; + } + + // }}} + // {{{ rebuildDepsFile() + + function rebuildDB() + { + $depdb = array('depdb_version' => $this->depdb_version); + $packages = $this->pear_reg->listPackages(); + foreach ($packages as $package) { + $deps = $this->pear_reg->packageInfo($package, 'release_deps'); + $this->setPackageDep($depdb, $package, $deps); + } + print_r($depdb); + $error = $this->_writeDepDB($depdb); + if (PEAR::isError($error)) { + return $error; + } + return true; + } + + // }}} + // {{{ & _getDepDB() + + function &_getDepDB() + { + if (!$fp = fopen($this->depdb_file, 'r')) { + $err = $this->raiseError("Could not open dependencies file `".$this->depdb_file."'"); + return $err; + } + $data = unserialize(fread($fp, filesize($this->depdb_file))); + fclose($fp); + return $data; + } + + // }}} + // {{{ _writeDepDB() + + function _writeDepDB(&$deps) + { + if (PEAR::isError($e = $this->_lock(LOCK_EX))) { + return $e; + } + if (!$fp = fopen($this->depdb_file, 'wb')) { + $this->_unlock(); + return $this->raiseError("Could not open dependencies file `".$this->depfile."' for writting"); + } + fwrite($fp, serialize($deps)); + fclose($fp); + $this->_unlock(); + return true; + } + + // }}} + /* + // {{{ removePackageDep() + function removePackageDep($package) + { + $data = &$this->_depGetDepDB(); + if (PEAR::isError($data)) { + return $data; + } + // Other packages depends on this package, can't be removed + if (isset($data['deps'][$package])) { + return $data['deps'][$package]; + } + // The package depends on others, remove those dependencies + if (isset($data['pkgs'][$package])) { + foreach ($data['pkgs'][$package] as $pkg => $key) { + // remove the dependency + unset($data['deps'][$pkg][$key]); + // if no more dependencies, remove the subject too + if (!count($data['deps'][$pkg])) { + unset($data['deps'][$pkg]); + } + } + // remove the package from the index list + unset($data['pkgs'][$package]); + } + return $this->_depWriteDepDB(); + } + // }}} + */ + + // {{{ checkAction() + + function checkAction($action, $package, $new_version = null) + { + $depdb = &$this->_getDepDB(); + if (PEAR::isError($depdb)) { + return $depdb; + } + $fails = ''; + switch($action) { + case 'uninstall': + // Other packages depends on this package, can't be removed + if (isset($depdb['deps'][$package])) { + foreach ($depdb['deps'][$package] as $dep) { + if (!$dep['optional']) { + $fails .= "Package '" . $dep['depend'] . "' depends on '$package'\n"; + } + } + return $fails; + } + return true; + case 'install': + case 'upgrade': + // Other packages depend on this package, check deps. Ex: + // <dep type='pkg' rel='lt' version='1.0'>Foo</dep> and we are trying to + // update Foo to version 2.0 + if (isset($depdb['deps'][$package])) { + foreach ($depdb['deps'][$package] as $dep) { + $relation = $dep['rel']; + if ($relation == 'not') { + $fails .= "Package '" . $dep['depend'] . "' conflicts with '$package'\n"; + } elseif ($relation != 'has' && $new_version !== null) { + if (!version_compare("$new_version", "{$dep['version']}", $relation) && + !$dep['optional']) { + $fails .= "Package '" . $dep['depend'] . "' requires ". + "$package " . $this->pear_dep->signOperator($relation) . + " " . $dep['version']; + } + } + } + if (isset($fails)) { + return $fails; + } + } + return true; + } + } + + // }}} + // {{{ commitAction() + + function commitAction($action, $package) + { + + } + + // }}} + // {{{ setPackageDep() + + /** + * Update or insert a the dependencies of a package, prechecking + * that the package won't break any dependency in the process + + The data structure is as follows: + $dep_db = array( + // Other packages depends on this packages + 'deps' => array( + 'Package Name' => array( + 0 => array( + // This package depends on 'Package Name' + 'depend' => 'Package', + // Which version 'Package' needs of 'Package Name' + 'version' => '1.0', + // The requirement (version_compare() operator) + 'rel' => 'ge', + // whether the dependency is optional + 'optional' => true/false + ), + ), + ) + // This packages are dependant on other packages + 'pkgs' => array( + 'Package Dependant' => array( + // This is a index list with paths over the 'deps' array for quick + // searching things like "what dependecies has this package?" + // $dep_db['deps']['Package Name'][3] + 'Package Name' => 3 // key in array ['deps']['Package Name'] + ), + ) + ) + + Note: It only supports package dependencies no other type + */ + + function setPackageDep(&$data, $package, $rel_deps = array()) + { + // This package has no dependencies + if (!is_array($rel_deps) || !count($rel_deps)) { + return true; + } + + // The package depends on others, register that + foreach ($rel_deps as $dep) { + // We only support deps of type 'pkg's + if ($dep && $dep['type'] == 'pkg' && isset($dep['name'])) { + $dep_name = strtolower($dep['name']); + $write = array('depend' => $package, + 'rel' => $dep['rel']); + if ($dep['rel'] != 'has') { + $write['version'] = $dep['version']; + } + if (isset($dep['optional']) && $dep['optional'] == 'yes') { + $write['optional'] = true; + } else { + $write['optional'] = false; + } + settype($data['deps'][$dep_name], 'array'); + + // The dependency already exists, update it + if (isset($data['pkgs'][$package][$dep_name])) { + $key = $data['pkgs'][$package][$dep_name]; + $data['deps'][$dep_name][$key] = $write; + + // New dependency, insert it + } else { + $key = count($data['deps'][$dep_name]); + $data['deps'][$dep_name][$key] = $write; + settype($data['pkgs'][$package], 'array'); + $data['pkgs'][$package][$dep_name] = $key; + } + } + } + return true; + } + // }}} +} +?> diff --git a/pear/PEAR/Downloader.php b/pear/PEAR/Downloader.php new file mode 100644 index 000000000..07e699975 --- /dev/null +++ b/pear/PEAR/Downloader.php @@ -0,0 +1,680 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Authors: Stig Bakken <ssb@php.net> | +// | Tomas V.V.Cox <cox@idecnet.com> | +// | Martin Jansen <mj@php.net> | +// +----------------------------------------------------------------------+ +// +// $Id: Downloader.php,v 1.17.2.1 2004/10/25 17:14:33 cellog Exp $ + +require_once 'PEAR/Common.php'; +require_once 'PEAR/Registry.php'; +require_once 'PEAR/Dependency.php'; +require_once 'PEAR/Remote.php'; +require_once 'System.php'; + + +define('PEAR_INSTALLER_OK', 1); +define('PEAR_INSTALLER_FAILED', 0); +define('PEAR_INSTALLER_SKIPPED', -1); +define('PEAR_INSTALLER_ERROR_NO_PREF_STATE', 2); + +/** + * Administration class used to download PEAR packages and maintain the + * installed package database. + * + * @since PEAR 1.4 + * @author Greg Beaver <cellog@php.net> + */ +class PEAR_Downloader extends PEAR_Common +{ + /** + * @var PEAR_Config + * @access private + */ + var $_config; + + /** + * @var PEAR_Registry + * @access private + */ + var $_registry; + + /** + * @var PEAR_Remote + * @access private + */ + var $_remote; + + /** + * Preferred Installation State (snapshot, devel, alpha, beta, stable) + * @var string|null + * @access private + */ + var $_preferredState; + + /** + * Options from command-line passed to Install. + * + * Recognized options:<br /> + * - onlyreqdeps : install all required dependencies as well + * - alldeps : install all dependencies, including optional + * - installroot : base relative path to install files in + * - force : force a download even if warnings would prevent it + * @see PEAR_Command_Install + * @access private + * @var array + */ + var $_options; + + /** + * Downloaded Packages after a call to download(). + * + * Format of each entry: + * + * <code> + * array('pkg' => 'package_name', 'file' => '/path/to/local/file', + * 'info' => array() // parsed package.xml + * ); + * </code> + * @access private + * @var array + */ + var $_downloadedPackages = array(); + + /** + * Packages slated for download. + * + * This is used to prevent downloading a package more than once should it be a dependency + * for two packages to be installed. + * Format of each entry: + * + * <pre> + * array('package_name1' => parsed package.xml, 'package_name2' => parsed package.xml, + * ); + * </pre> + * @access private + * @var array + */ + var $_toDownload = array(); + + /** + * Array of every package installed, with names lower-cased. + * + * Format: + * <code> + * array('package1' => 0, 'package2' => 1, ); + * </code> + * @var array + */ + var $_installed = array(); + + /** + * @var array + * @access private + */ + var $_errorStack = array(); + + // {{{ PEAR_Downloader() + + function PEAR_Downloader(&$ui, $options, &$config) + { + $this->_options = $options; + $this->_config = &$config; + $this->_preferredState = $this->_config->get('preferred_state'); + $this->ui = &$ui; + if (!$this->_preferredState) { + // don't inadvertantly use a non-set preferred_state + $this->_preferredState = null; + } + + $php_dir = $this->_config->get('php_dir'); + if (isset($this->_options['installroot'])) { + if (substr($this->_options['installroot'], -1) == DIRECTORY_SEPARATOR) { + $this->_options['installroot'] = substr($this->_options['installroot'], 0, -1); + } + $php_dir = $this->_prependPath($php_dir, $this->_options['installroot']); + } + $this->_registry = &new PEAR_Registry($php_dir); + $this->_remote = &new PEAR_Remote($config); + + if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) { + $this->_installed = $this->_registry->listPackages(); + array_walk($this->_installed, create_function('&$v,$k','$v = strtolower($v);')); + $this->_installed = array_flip($this->_installed); + } + parent::PEAR_Common(); + } + + // }}} + // {{{ configSet() + function configSet($key, $value, $layer = 'user') + { + $this->_config->set($key, $value, $layer); + $this->_preferredState = $this->_config->get('preferred_state'); + if (!$this->_preferredState) { + // don't inadvertantly use a non-set preferred_state + $this->_preferredState = null; + } + } + + // }}} + // {{{ setOptions() + function setOptions($options) + { + $this->_options = $options; + } + + // }}} + // {{{ _downloadFile() + /** + * @param string filename to download + * @param string version/state + * @param string original value passed to command-line + * @param string|null preferred state (snapshot/devel/alpha/beta/stable) + * Defaults to configuration preferred state + * @return null|PEAR_Error|string + * @access private + */ + function _downloadFile($pkgfile, $version, $origpkgfile, $state = null) + { + if (is_null($state)) { + $state = $this->_preferredState; + } + // {{{ check the package filename, and whether it's already installed + $need_download = false; + if (preg_match('#^(http|ftp)://#', $pkgfile)) { + $need_download = true; + } elseif (!@is_file($pkgfile)) { + if ($this->validPackageName($pkgfile)) { + if ($this->_registry->packageExists($pkgfile)) { + if (empty($this->_options['upgrade']) && empty($this->_options['force'])) { + $errors[] = "$pkgfile already installed"; + return; + } + } + $pkgfile = $this->getPackageDownloadUrl($pkgfile, $version); + $need_download = true; + } else { + if (strlen($pkgfile)) { + $errors[] = "Could not open the package file: $pkgfile"; + } else { + $errors[] = "No package file given"; + } + return; + } + } + // }}} + + // {{{ Download package ----------------------------------------------- + if ($need_download) { + $downloaddir = $this->_config->get('download_dir'); + if (empty($downloaddir)) { + if (PEAR::isError($downloaddir = System::mktemp('-d'))) { + return $downloaddir; + } + $this->log(3, '+ tmp dir created at ' . $downloaddir); + } + $callback = $this->ui ? array(&$this, '_downloadCallback') : null; + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $file = $this->downloadHttp($pkgfile, $this->ui, $downloaddir, $callback); + $this->popErrorHandling(); + if (PEAR::isError($file)) { + if ($this->validPackageName($origpkgfile)) { + if (!PEAR::isError($info = $this->_remote->call('package.info', + $origpkgfile))) { + if (!count($info['releases'])) { + return $this->raiseError('Package ' . $origpkgfile . + ' has no releases'); + } else { + return $this->raiseError('No releases of preferred state "' + . $state . '" exist for package ' . $origpkgfile . + '. Use ' . $origpkgfile . '-state to install another' . + ' state (like ' . $origpkgfile .'-beta)', + PEAR_INSTALLER_ERROR_NO_PREF_STATE); + } + } else { + return $pkgfile; + } + } else { + return $this->raiseError($file); + } + } + $pkgfile = $file; + } + // }}} + return $pkgfile; + } + // }}} + // {{{ getPackageDownloadUrl() + + function getPackageDownloadUrl($package, $version = null) + { + if ($version) { + $package .= "-$version"; + } + if ($this === null || $this->_config === null) { + $package = "http://pear.php.net/get/$package"; + } else { + $package = "http://" . $this->_config->get('master_server') . + "/get/$package"; + } + if (!extension_loaded("zlib")) { + $package .= '?uncompress=yes'; + } + return $package; + } + + // }}} + // {{{ extractDownloadFileName($pkgfile, &$version) + + function extractDownloadFileName($pkgfile, &$version) + { + if (@is_file($pkgfile)) { + return $pkgfile; + } + // regex defined in Common.php + if (preg_match(PEAR_COMMON_PACKAGE_DOWNLOAD_PREG, $pkgfile, $m)) { + $version = (isset($m[3])) ? $m[3] : null; + return $m[1]; + } + $version = null; + return $pkgfile; + } + + // }}} + + // }}} + // {{{ getDownloadedPackages() + + /** + * Retrieve a list of downloaded packages after a call to {@link download()}. + * + * Also resets the list of downloaded packages. + * @return array + */ + function getDownloadedPackages() + { + $ret = $this->_downloadedPackages; + $this->_downloadedPackages = array(); + $this->_toDownload = array(); + return $ret; + } + + // }}} + // {{{ download() + + /** + * Download any files and their dependencies, if necessary + * + * BC-compatible method name + * @param array a mixed list of package names, local files, or package.xml + */ + function download($packages) + { + return $this->doDownload($packages); + } + + // }}} + // {{{ doDownload() + + /** + * Download any files and their dependencies, if necessary + * + * @param array a mixed list of package names, local files, or package.xml + */ + function doDownload($packages) + { + $mywillinstall = array(); + $state = $this->_preferredState; + + // {{{ download files in this list if necessary + foreach($packages as $pkgfile) { + $need_download = false; + if (!is_file($pkgfile)) { + if (preg_match('#^(http|ftp)://#', $pkgfile)) { + $need_download = true; + } + $pkgfile = $this->_downloadNonFile($pkgfile); + if (PEAR::isError($pkgfile)) { + return $pkgfile; + } + if ($pkgfile === false) { + continue; + } + } // end is_file() + + $tempinfo = $this->infoFromAny($pkgfile); + if ($need_download) { + $this->_toDownload[] = $tempinfo['package']; + } + if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) { + // ignore dependencies if there are any errors + if (!PEAR::isError($tempinfo)) { + $mywillinstall[strtolower($tempinfo['package'])] = @$tempinfo['release_deps']; + } + } + $this->_downloadedPackages[] = array('pkg' => $tempinfo['package'], + 'file' => $pkgfile, 'info' => $tempinfo); + } // end foreach($packages) + // }}} + + // {{{ extract dependencies from downloaded files and then download + // them if necessary + if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) { + $deppackages = array(); + foreach ($mywillinstall as $package => $alldeps) { + if (!is_array($alldeps)) { + // there are no dependencies + continue; + } + $fail = false; + foreach ($alldeps as $info) { + if ($info['type'] != 'pkg') { + continue; + } + $ret = $this->_processDependency($package, $info, $mywillinstall); + if ($ret === false) { + continue; + } + if ($ret === 0) { + $fail = true; + continue; + } + if (PEAR::isError($ret)) { + return $ret; + } + $deppackages[] = $ret; + } // foreach($alldeps + if ($fail) { + $deppackages = array(); + } + } + + if (count($deppackages)) { + $this->doDownload($deppackages); + } + } // }}} if --alldeps or --onlyreqdeps + } + + // }}} + // {{{ _downloadNonFile($pkgfile) + + /** + * @return false|PEAR_Error|string false if loop should be broken out of, + * string if the file was downloaded, + * PEAR_Error on exception + * @access private + */ + function _downloadNonFile($pkgfile) + { + $origpkgfile = $pkgfile; + $state = null; + $pkgfile = $this->extractDownloadFileName($pkgfile, $version); + if (preg_match('#^(http|ftp)://#', $pkgfile)) { + return $this->_downloadFile($pkgfile, $version, $origpkgfile); + } + if (!$this->validPackageName($pkgfile)) { + return $this->raiseError("Package name '$pkgfile' not valid"); + } + // ignore packages that are installed unless we are upgrading + $curinfo = $this->_registry->packageInfo($pkgfile); + if ($this->_registry->packageExists($pkgfile) + && empty($this->_options['upgrade']) && empty($this->_options['force'])) { + $this->log(0, "Package '{$curinfo['package']}' already installed, skipping"); + return false; + } + if (in_array($pkgfile, $this->_toDownload)) { + return false; + } + $releases = $this->_remote->call('package.info', $pkgfile, 'releases', true); + if (!count($releases)) { + return $this->raiseError("No releases found for package '$pkgfile'"); + } + // Want a specific version/state + if ($version !== null) { + // Passed Foo-1.2 + if ($this->validPackageVersion($version)) { + if (!isset($releases[$version])) { + return $this->raiseError("No release with version '$version' found for '$pkgfile'"); + } + // Passed Foo-alpha + } elseif (in_array($version, $this->getReleaseStates())) { + $state = $version; + $version = 0; + foreach ($releases as $ver => $inf) { + if ($inf['state'] == $state && version_compare("$version", "$ver") < 0) { + $version = $ver; + break; + } + } + if ($version == 0) { + return $this->raiseError("No release with state '$state' found for '$pkgfile'"); + } + // invalid suffix passed + } else { + return $this->raiseError("Invalid suffix '-$version', be sure to pass a valid PEAR ". + "version number or release state"); + } + // Guess what to download + } else { + $states = $this->betterStates($this->_preferredState, true); + $possible = false; + $version = 0; + $higher_version = 0; + $prev_hi_ver = 0; + foreach ($releases as $ver => $inf) { + if (in_array($inf['state'], $states) && version_compare("$version", "$ver") < 0) { + $version = $ver; + break; + } else { + $ver = (string)$ver; + if (version_compare($prev_hi_ver, $ver) < 0) { + $prev_hi_ver = $higher_version = $ver; + } + } + } + if ($version === 0 && !isset($this->_options['force'])) { + return $this->raiseError('No release with state equal to: \'' . implode(', ', $states) . + "' found for '$pkgfile'"); + } elseif ($version === 0) { + $this->log(0, "Warning: $pkgfile is state '" . $releases[$higher_version]['state'] . "' which is less stable " . + "than state '$this->_preferredState'"); + } + } + // Check if we haven't already the version + if (empty($this->_options['force']) && !is_null($curinfo)) { + if ($curinfo['version'] == $version) { + $this->log(0, "Package '{$curinfo['package']}-{$curinfo['version']}' already installed, skipping"); + return false; + } elseif (version_compare("$version", "{$curinfo['version']}") < 0) { + $this->log(0, "Package '{$curinfo['package']}' version '{$curinfo['version']}' " . + " is installed and {$curinfo['version']} is > requested '$version', skipping"); + return false; + } + } + $this->_toDownload[] = $pkgfile; + return $this->_downloadFile($pkgfile, $version, $origpkgfile, $state); + } + + // }}} + // {{{ _processDependency($package, $info, $mywillinstall) + + /** + * Process a dependency, download if necessary + * @param array dependency information from PEAR_Remote call + * @param array packages that will be installed in this iteration + * @return false|string|PEAR_Error + * @access private + * @todo Add test for relation 'lt'/'le' -> make sure that the dependency requested is + * in fact lower than the required value. This will be very important for BC dependencies + */ + function _processDependency($package, $info, $mywillinstall) + { + $state = $this->_preferredState; + if (!isset($this->_options['alldeps']) && isset($info['optional']) && + $info['optional'] == 'yes') { + // skip optional deps + $this->log(0, "skipping Package '$package' optional dependency '$info[name]'"); + return false; + } + // {{{ get releases + $releases = $this->_remote->call('package.info', $info['name'], 'releases', true); + if (PEAR::isError($releases)) { + return $releases; + } + if (!count($releases)) { + if (!isset($this->_installed[strtolower($info['name'])])) { + $this->pushError("Package '$package' dependency '$info[name]' ". + "has no releases"); + } + return false; + } + $found = false; + $save = $releases; + while(count($releases) && !$found) { + if (!empty($state) && $state != 'any') { + list($release_version, $release) = each($releases); + if ($state != $release['state'] && + !in_array($release['state'], $this->betterStates($state))) + { + // drop this release - it ain't stable enough + array_shift($releases); + } else { + $found = true; + } + } else { + $found = true; + } + } + if (!count($releases) && !$found) { + $get = array(); + foreach($save as $release) { + $get = array_merge($get, + $this->betterStates($release['state'], true)); + } + $savestate = array_shift($get); + $this->pushError( "Release for '$package' dependency '$info[name]' " . + "has state '$savestate', requires '$state'"); + return 0; + } + if (in_array(strtolower($info['name']), $this->_toDownload) || + isset($mywillinstall[strtolower($info['name'])])) { + // skip upgrade check for packages we will install + return false; + } + if (!isset($this->_installed[strtolower($info['name'])])) { + // check to see if we can install the specific version required + if ($info['rel'] == 'eq') { + return $info['name'] . '-' . $info['version']; + } + // skip upgrade check for packages we don't have installed + return $info['name']; + } + // }}} + + // {{{ see if a dependency must be upgraded + $inst_version = $this->_registry->packageInfo($info['name'], 'version'); + if (!isset($info['version'])) { + // this is a rel='has' dependency, check against latest + if (version_compare($release_version, $inst_version, 'le')) { + return false; + } else { + return $info['name']; + } + } + if (version_compare($info['version'], $inst_version, 'le')) { + // installed version is up-to-date + return false; + } + return $info['name']; + } + + // }}} + // {{{ _downloadCallback() + + function _downloadCallback($msg, $params = null) + { + switch ($msg) { + case 'saveas': + $this->log(1, "downloading $params ..."); + break; + case 'done': + $this->log(1, '...done: ' . number_format($params, 0, '', ',') . ' bytes'); + break; + case 'bytesread': + static $bytes; + if (empty($bytes)) { + $bytes = 0; + } + if (!($bytes % 10240)) { + $this->log(1, '.', false); + } + $bytes += $params; + break; + case 'start': + $this->log(1, "Starting to download {$params[0]} (".number_format($params[1], 0, '', ',')." bytes)"); + break; + } + if (method_exists($this->ui, '_downloadCallback')) + $this->ui->_downloadCallback($msg, $params); + } + + // }}} + // {{{ _prependPath($path, $prepend) + + function _prependPath($path, $prepend) + { + if (strlen($prepend) > 0) { + if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) { + $path = $prepend . substr($path, 2); + } else { + $path = $prepend . $path; + } + } + return $path; + } + // }}} + // {{{ pushError($errmsg, $code) + + /** + * @param string + * @param integer + */ + function pushError($errmsg, $code = -1) + { + array_push($this->_errorStack, array($errmsg, $code)); + } + + // }}} + // {{{ getErrorMsgs() + + function getErrorMsgs() + { + $msgs = array(); + $errs = $this->_errorStack; + foreach ($errs as $err) { + $msgs[] = $err[0]; + } + $this->_errorStack = array(); + return $msgs; + } + + // }}} +} +// }}} + +?> diff --git a/pear/PEAR/ErrorStack.php b/pear/PEAR/ErrorStack.php new file mode 100644 index 000000000..a0e868287 --- /dev/null +++ b/pear/PEAR/ErrorStack.php @@ -0,0 +1,981 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Gregory Beaver <cellog@php.net> | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: ErrorStack.php,v 1.7.2.2 2005/03/28 16:46:06 cellog Exp $ + +/** + * Error Stack Implementation + * + * This is an incredibly simple implementation of a very complex error handling + * facility. It contains the ability + * to track multiple errors from multiple packages simultaneously. In addition, + * it can track errors of many levels, save data along with the error, context + * information such as the exact file, line number, class and function that + * generated the error, and if necessary, it can raise a traditional PEAR_Error. + * It has built-in support for PEAR::Log, to log errors as they occur + * + * Since version 0.2alpha, it is also possible to selectively ignore errors, + * through the use of an error callback, see {@link pushCallback()} + * + * Since version 0.3alpha, it is possible to specify the exception class + * returned from {@link push()} + * + * Since version PEAR1.3.2, ErrorStack no longer instantiates an exception class. This can + * still be done quite handily in an error callback or by manipulating the returned array + * @author Greg Beaver <cellog@php.net> + * @version PEAR1.3.2 (beta) + * @package PEAR_ErrorStack + * @category Debugging + * @license http://www.php.net/license/3_0.txt PHP License v3.0 + */ + +/** + * Singleton storage + * + * Format: + * <pre> + * array( + * 'package1' => PEAR_ErrorStack object, + * 'package2' => PEAR_ErrorStack object, + * ... + * ) + * </pre> + * @access private + * @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] + */ +$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array(); + +/** + * Global error callback (default) + * + * This is only used if set to non-false. * is the default callback for + * all packages, whereas specific packages may set a default callback + * for all instances, regardless of whether they are a singleton or not. + * + * To exclude non-singletons, only set the local callback for the singleton + * @see PEAR_ErrorStack::setDefaultCallback() + * @access private + * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] + */ +$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array( + '*' => false, +); + +/** + * Global Log object (default) + * + * This is only used if set to non-false. Use to set a default log object for + * all stacks, regardless of instantiation order or location + * @see PEAR_ErrorStack::setDefaultLogger() + * @access private + * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] + */ +$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false; + +/** + * Global Overriding Callback + * + * This callback will override any error callbacks that specific loggers have set. + * Use with EXTREME caution + * @see PEAR_ErrorStack::staticPushCallback() + * @access private + * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] + */ +$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array(); + +/**#@+ + * One of four possible return values from the error Callback + * @see PEAR_ErrorStack::_errorCallback() + */ +/** + * If this is returned, then the error will be both pushed onto the stack + * and logged. + */ +define('PEAR_ERRORSTACK_PUSHANDLOG', 1); +/** + * If this is returned, then the error will only be pushed onto the stack, + * and not logged. + */ +define('PEAR_ERRORSTACK_PUSH', 2); +/** + * If this is returned, then the error will only be logged, but not pushed + * onto the error stack. + */ +define('PEAR_ERRORSTACK_LOG', 3); +/** + * If this is returned, then the error is completely ignored. + */ +define('PEAR_ERRORSTACK_IGNORE', 4); +/** + * If this is returned, then the error is logged and die() is called. + */ +define('PEAR_ERRORSTACK_DIE', 5); +/**#@-*/ + +/** + * Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in + * the singleton method. + */ +define('PEAR_ERRORSTACK_ERR_NONCLASS', 1); + +/** + * Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()} + * that has no __toString() method + */ +define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2); +/** + * Error Stack Implementation + * + * Usage: + * <code> + * // global error stack + * $global_stack = &PEAR_ErrorStack::singleton('MyPackage'); + * // local error stack + * $local_stack = new PEAR_ErrorStack('MyPackage'); + * </code> + * @copyright 2004 Gregory Beaver + * @package PEAR_ErrorStack + * @license http://www.php.net/license/3_0.txt PHP License + */ +class PEAR_ErrorStack { + /** + * Errors are stored in the order that they are pushed on the stack. + * @since 0.4alpha Errors are no longer organized by error level. + * This renders pop() nearly unusable, and levels could be more easily + * handled in a callback anyway + * @var array + * @access private + */ + var $_errors = array(); + + /** + * Storage of errors by level. + * + * Allows easy retrieval and deletion of only errors from a particular level + * @since PEAR 1.4.0dev + * @var array + * @access private + */ + var $_errorsByLevel = array(); + + /** + * Package name this error stack represents + * @var string + * @access protected + */ + var $_package; + + /** + * Determines whether a PEAR_Error is thrown upon every error addition + * @var boolean + * @access private + */ + var $_compat = false; + + /** + * If set to a valid callback, this will be used to generate the error + * message from the error code, otherwise the message passed in will be + * used + * @var false|string|array + * @access private + */ + var $_msgCallback = false; + + /** + * If set to a valid callback, this will be used to generate the error + * context for an error. For PHP-related errors, this will be a file + * and line number as retrieved from debug_backtrace(), but can be + * customized for other purposes. The error might actually be in a separate + * configuration file, or in a database query. + * @var false|string|array + * @access protected + */ + var $_contextCallback = false; + + /** + * If set to a valid callback, this will be called every time an error + * is pushed onto the stack. The return value will be used to determine + * whether to allow an error to be pushed or logged. + * + * The return value must be one an PEAR_ERRORSTACK_* constant + * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG + * @var false|string|array + * @access protected + */ + var $_errorCallback = array(); + + /** + * PEAR::Log object for logging errors + * @var false|Log + * @access protected + */ + var $_logger = false; + + /** + * Error messages - designed to be overridden + * @var array + * @abstract + */ + var $_errorMsgs = array(); + + /** + * Set up a new error stack + * + * @param string $package name of the package this error stack represents + * @param callback $msgCallback callback used for error message generation + * @param callback $contextCallback callback used for context generation, + * defaults to {@link getFileLine()} + * @param boolean $throwPEAR_Error + */ + function PEAR_ErrorStack($package, $msgCallback = false, $contextCallback = false, + $throwPEAR_Error = false) + { + $this->_package = $package; + $this->setMessageCallback($msgCallback); + $this->setContextCallback($contextCallback); + $this->_compat = $throwPEAR_Error; + } + + /** + * Return a single error stack for this package. + * + * Note that all parameters are ignored if the stack for package $package + * has already been instantiated + * @param string $package name of the package this error stack represents + * @param callback $msgCallback callback used for error message generation + * @param callback $contextCallback callback used for context generation, + * defaults to {@link getFileLine()} + * @param boolean $throwPEAR_Error + * @param string $stackClass class to instantiate + * @static + * @return PEAR_ErrorStack + */ + function &singleton($package, $msgCallback = false, $contextCallback = false, + $throwPEAR_Error = false, $stackClass = 'PEAR_ErrorStack') + { + if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { + return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]; + } + if (!class_exists($stackClass)) { + if (function_exists('debug_backtrace')) { + $trace = debug_backtrace(); + } + PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS, + 'exception', array('stackclass' => $stackClass), + 'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)', + false, $trace); + } + return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] = + &new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error); + } + + /** + * Internal error handler for PEAR_ErrorStack class + * + * Dies if the error is an exception (and would have died anyway) + * @access private + */ + function _handleError($err) + { + if ($err['level'] == 'exception') { + $message = $err['message']; + if (isset($_SERVER['REQUEST_URI'])) { + echo '<br />'; + } else { + echo "\n"; + } + var_dump($err['context']); + die($message); + } + } + + /** + * Set up a PEAR::Log object for all error stacks that don't have one + * @param Log $log + * @static + */ + function setDefaultLogger(&$log) + { + if (is_object($log) && method_exists($log, 'log') ) { + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; + } elseif (is_callable($log)) { + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; + } + } + + /** + * Set up a PEAR::Log object for this error stack + * @param Log $log + */ + function setLogger(&$log) + { + if (is_object($log) && method_exists($log, 'log') ) { + $this->_logger = &$log; + } elseif (is_callable($log)) { + $this->_logger = &$log; + } + } + + /** + * Set an error code => error message mapping callback + * + * This method sets the callback that can be used to generate error + * messages for any instance + * @param array|string Callback function/method + */ + function setMessageCallback($msgCallback) + { + if (!$msgCallback) { + $this->_msgCallback = array(&$this, 'getErrorMessage'); + } else { + if (is_callable($msgCallback)) { + $this->_msgCallback = $msgCallback; + } + } + } + + /** + * Get an error code => error message mapping callback + * + * This method returns the current callback that can be used to generate error + * messages + * @return array|string|false Callback function/method or false if none + */ + function getMessageCallback() + { + return $this->_msgCallback; + } + + /** + * Sets a default callback to be used by all error stacks + * + * This method sets the callback that can be used to generate error + * messages for a singleton + * @param array|string Callback function/method + * @param string Package name, or false for all packages + * @static + */ + function setDefaultCallback($callback = false, $package = false) + { + if (!is_callable($callback)) { + $callback = false; + } + $package = $package ? $package : '*'; + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback; + } + + /** + * Set a callback that generates context information (location of error) for an error stack + * + * This method sets the callback that can be used to generate context + * information for an error. Passing in NULL will disable context generation + * and remove the expensive call to debug_backtrace() + * @param array|string|null Callback function/method + */ + function setContextCallback($contextCallback) + { + if ($contextCallback === null) { + return $this->_contextCallback = false; + } + if (!$contextCallback) { + $this->_contextCallback = array(&$this, 'getFileLine'); + } else { + if (is_callable($contextCallback)) { + $this->_contextCallback = $contextCallback; + } + } + } + + /** + * Set an error Callback + * If set to a valid callback, this will be called every time an error + * is pushed onto the stack. The return value will be used to determine + * whether to allow an error to be pushed or logged. + * + * The return value must be one of the ERRORSTACK_* constants. + * + * This functionality can be used to emulate PEAR's pushErrorHandling, and + * the PEAR_ERROR_CALLBACK mode, without affecting the integrity of + * the error stack or logging + * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG + * @see popCallback() + * @param string|array $cb + */ + function pushCallback($cb) + { + array_push($this->_errorCallback, $cb); + } + + /** + * Remove a callback from the error callback stack + * @see pushCallback() + * @return array|string|false + */ + function popCallback() + { + if (!count($this->_errorCallback)) { + return false; + } + return array_pop($this->_errorCallback); + } + + /** + * Set a temporary overriding error callback for every package error stack + * + * Use this to temporarily disable all existing callbacks (can be used + * to emulate the @ operator, for instance) + * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG + * @see staticPopCallback(), pushCallback() + * @param string|array $cb + * @static + */ + function staticPushCallback($cb) + { + array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb); + } + + /** + * Remove a temporary overriding error callback + * @see staticPushCallback() + * @return array|string|false + * @static + */ + function staticPopCallback() + { + $ret = array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']); + if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) { + $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array(); + } + return $ret; + } + + /** + * Add an error to the stack + * + * If the message generator exists, it is called with 2 parameters. + * - the current Error Stack object + * - an array that is in the same format as an error. Available indices + * are 'code', 'package', 'time', 'params', 'level', and 'context' + * + * Next, if the error should contain context information, this is + * handled by the context grabbing method. + * Finally, the error is pushed onto the proper error stack + * @param int $code Package-specific error code + * @param string $level Error level. This is NOT spell-checked + * @param array $params associative array of error parameters + * @param string $msg Error message, or a portion of it if the message + * is to be generated + * @param array $repackage If this error re-packages an error pushed by + * another package, place the array returned from + * {@link pop()} in this parameter + * @param array $backtrace Protected parameter: use this to pass in the + * {@link debug_backtrace()} that should be used + * to find error context + * @return PEAR_Error|array|Exception + * if compatibility mode is on, a PEAR_Error is also + * thrown. If the class Exception exists, then one + * is returned to allow code like: + * <code> + * throw ($stack->push(MY_ERROR_CODE, 'error', array('username' => 'grob'))); + * </code> + * + * The errorData property of the exception class will be set to the array + * that would normally be returned. If a PEAR_Error is returned, the userinfo + * property is set to the array + * + * Otherwise, an array is returned in this format: + * <code> + * array( + * 'code' => $code, + * 'params' => $params, + * 'package' => $this->_package, + * 'level' => $level, + * 'time' => time(), + * 'context' => $context, + * 'message' => $msg, + * //['repackage' => $err] repackaged error array/Exception class + * ); + * </code> + */ + function push($code, $level = 'error', $params = array(), $msg = false, + $repackage = false, $backtrace = false) + { + $context = false; + // grab error context + if ($this->_contextCallback) { + if (!$backtrace) { + $backtrace = debug_backtrace(); + } + $context = call_user_func($this->_contextCallback, $code, $params, $backtrace); + } + + // save error + $time = explode(' ', microtime()); + $time = $time[1] + $time[0]; + $err = array( + 'code' => $code, + 'params' => $params, + 'package' => $this->_package, + 'level' => $level, + 'time' => $time, + 'context' => $context, + 'message' => $msg, + ); + + // set up the error message, if necessary + if ($this->_msgCallback) { + $msg = call_user_func_array($this->_msgCallback, + array(&$this, $err)); + $err['message'] = $msg; + } + + if ($repackage) { + $err['repackage'] = $repackage; + } + $push = $log = true; + $die = false; + // try the overriding callback first + $callback = $this->staticPopCallback(); + if ($callback) { + $this->staticPushCallback($callback); + } + if (!is_callable($callback)) { + // try the local callback next + $callback = $this->popCallback(); + if (is_callable($callback)) { + $this->pushCallback($callback); + } else { + // try the default callback + $callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ? + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] : + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*']; + } + } + if (is_callable($callback)) { + switch(call_user_func($callback, $err)){ + case PEAR_ERRORSTACK_IGNORE: + return $err; + break; + case PEAR_ERRORSTACK_PUSH: + $log = false; + break; + case PEAR_ERRORSTACK_LOG: + $push = false; + break; + case PEAR_ERRORSTACK_DIE: + $die = true; + break; + // anything else returned has the same effect as pushandlog + } + } + if ($push) { + array_unshift($this->_errors, $err); + $this->_errorsByLevel[$err['level']][] = &$this->_errors[0]; + } + if ($log) { + if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) { + $this->_log($err); + } + } + if ($die) { + die(); + } + if ($this->_compat && $push) { + return $this->raiseError($msg, $code, null, null, $err); + } + return $err; + } + + /** + * Static version of {@link push()} + * + * @param string $package Package name this error belongs to + * @param int $code Package-specific error code + * @param string $level Error level. This is NOT spell-checked + * @param array $params associative array of error parameters + * @param string $msg Error message, or a portion of it if the message + * is to be generated + * @param array $repackage If this error re-packages an error pushed by + * another package, place the array returned from + * {@link pop()} in this parameter + * @param array $backtrace Protected parameter: use this to pass in the + * {@link debug_backtrace()} that should be used + * to find error context + * @return PEAR_Error|null|Exception + * if compatibility mode is on, a PEAR_Error is also + * thrown. If the class Exception exists, then one + * is returned to allow code like: + * <code> + * throw ($stack->push(MY_ERROR_CODE, 'error', array('username' => 'grob'))); + * </code> + * @static + */ + function staticPush($package, $code, $level = 'error', $params = array(), + $msg = false, $repackage = false, $backtrace = false) + { + $s = &PEAR_ErrorStack::singleton($package); + if ($s->_contextCallback) { + if (!$backtrace) { + if (function_exists('debug_backtrace')) { + $backtrace = debug_backtrace(); + } + } + } + return $s->push($code, $level, $params, $msg, $repackage, $backtrace); + } + + /** + * Log an error using PEAR::Log + * @param array $err Error array + * @param array $levels Error level => Log constant map + * @access protected + */ + function _log($err) + { + if ($this->_logger) { + $logger = &$this->_logger; + } else { + $logger = &$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']; + } + if (is_a($logger, 'Log')) { + $levels = array( + 'exception' => PEAR_LOG_CRIT, + 'alert' => PEAR_LOG_ALERT, + 'critical' => PEAR_LOG_CRIT, + 'error' => PEAR_LOG_ERR, + 'warning' => PEAR_LOG_WARNING, + 'notice' => PEAR_LOG_NOTICE, + 'info' => PEAR_LOG_INFO, + 'debug' => PEAR_LOG_DEBUG); + if (isset($levels[$err['level']])) { + $level = $levels[$err['level']]; + } else { + $level = PEAR_LOG_INFO; + } + $logger->log($err['message'], $level, $err); + } else { // support non-standard logs + call_user_func($logger, $err); + } + } + + + /** + * Pop an error off of the error stack + * + * @return false|array + * @since 0.4alpha it is no longer possible to specify a specific error + * level to return - the last error pushed will be returned, instead + */ + function pop() + { + return @array_shift($this->_errors); + } + + /** + * Determine whether there are any errors on the stack + * @param string|array Level name. Use to determine if any errors + * of level (string), or levels (array) have been pushed + * @return boolean + */ + function hasErrors($level = false) + { + if ($level) { + return isset($this->_errorsByLevel[$level]); + } + return count($this->_errors); + } + + /** + * Retrieve all errors since last purge + * + * @param boolean set in order to empty the error stack + * @param string level name, to return only errors of a particular severity + * @return array + */ + function getErrors($purge = false, $level = false) + { + if (!$purge) { + if ($level) { + if (!isset($this->_errorsByLevel[$level])) { + return array(); + } else { + return $this->_errorsByLevel[$level]; + } + } else { + return $this->_errors; + } + } + if ($level) { + $ret = $this->_errorsByLevel[$level]; + foreach ($this->_errorsByLevel[$level] as $i => $unused) { + // entries are references to the $_errors array + $this->_errorsByLevel[$level][$i] = false; + } + // array_filter removes all entries === false + $this->_errors = array_filter($this->_errors); + unset($this->_errorsByLevel[$level]); + return $ret; + } + $ret = $this->_errors; + $this->_errors = array(); + $this->_errorsByLevel = array(); + return $ret; + } + + /** + * Determine whether there are any errors on a single error stack, or on any error stack + * + * The optional parameter can be used to test the existence of any errors without the need of + * singleton instantiation + * @param string|false Package name to check for errors + * @param string Level name to check for a particular severity + * @return boolean + * @static + */ + function staticHasErrors($package = false, $level = false) + { + if ($package) { + if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { + return false; + } + return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level); + } + foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) { + if ($obj->hasErrors($level)) { + return true; + } + } + return false; + } + + /** + * Get a list of all errors since last purge, organized by package + * @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be + * @param boolean $purge Set to purge the error stack of existing errors + * @param string $level Set to a level name in order to retrieve only errors of a particular level + * @param boolean $merge Set to return a flat array, not organized by package + * @param array $sortfunc Function used to sort a merged array - default + * sorts by time, and should be good for most cases + * @static + * @return array + */ + function staticGetErrors($purge = false, $level = false, $merge = false, + $sortfunc = array('PEAR_ErrorStack', '_sortErrors')) + { + $ret = array(); + if (!is_callable($sortfunc)) { + $sortfunc = array('PEAR_ErrorStack', '_sortErrors'); + } + foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) { + $test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level); + if ($test) { + if ($merge) { + $ret = array_merge($ret, $test); + } else { + $ret[$package] = $test; + } + } + } + if ($merge) { + usort($ret, $sortfunc); + } + return $ret; + } + + /** + * Error sorting function, sorts by time + * @access private + */ + function _sortErrors($a, $b) + { + if ($a['time'] == $b['time']) { + return 0; + } + if ($a['time'] < $b['time']) { + return 1; + } + return -1; + } + + /** + * Standard file/line number/function/class context callback + * + * This function uses a backtrace generated from {@link debug_backtrace()} + * and so will not work at all in PHP < 4.3.0. The frame should + * reference the frame that contains the source of the error. + * @return array|false either array('file' => file, 'line' => line, + * 'function' => function name, 'class' => class name) or + * if this doesn't work, then false + * @param unused + * @param integer backtrace frame. + * @param array Results of debug_backtrace() + * @static + */ + function getFileLine($code, $params, $backtrace = null) + { + if ($backtrace === null) { + return false; + } + $frame = 0; + $functionframe = 1; + if (!isset($backtrace[1])) { + $functionframe = 0; + } else { + while (isset($backtrace[$functionframe]['function']) && + $backtrace[$functionframe]['function'] == 'eval' && + isset($backtrace[$functionframe + 1])) { + $functionframe++; + } + } + if (isset($backtrace[$frame])) { + if (!isset($backtrace[$frame]['file'])) { + $frame++; + } + $funcbacktrace = $backtrace[$functionframe]; + $filebacktrace = $backtrace[$frame]; + $ret = array('file' => $filebacktrace['file'], + 'line' => $filebacktrace['line']); + // rearrange for eval'd code or create function errors + if (strpos($filebacktrace['file'], '(') && + preg_match(';^(.*?)\((\d+)\) : (.*?)$;', $filebacktrace['file'], + $matches)) { + $ret['file'] = $matches[1]; + $ret['line'] = $matches[2] + 0; + } + if (isset($funcbacktrace['function']) && isset($backtrace[1])) { + if ($funcbacktrace['function'] != 'eval') { + if ($funcbacktrace['function'] == '__lambda_func') { + $ret['function'] = 'create_function() code'; + } else { + $ret['function'] = $funcbacktrace['function']; + } + } + } + if (isset($funcbacktrace['class']) && isset($backtrace[1])) { + $ret['class'] = $funcbacktrace['class']; + } + return $ret; + } + return false; + } + + /** + * Standard error message generation callback + * + * This method may also be called by a custom error message generator + * to fill in template values from the params array, simply + * set the third parameter to the error message template string to use + * + * The special variable %__msg% is reserved: use it only to specify + * where a message passed in by the user should be placed in the template, + * like so: + * + * Error message: %msg% - internal error + * + * If the message passed like so: + * + * <code> + * $stack->push(ERROR_CODE, 'error', array(), 'server error 500'); + * </code> + * + * The returned error message will be "Error message: server error 500 - + * internal error" + * @param PEAR_ErrorStack + * @param array + * @param string|false Pre-generated error message template + * @static + * @return string + */ + function getErrorMessage(&$stack, $err, $template = false) + { + if ($template) { + $mainmsg = $template; + } else { + $mainmsg = $stack->getErrorMessageTemplate($err['code']); + } + $mainmsg = str_replace('%__msg%', $err['message'], $mainmsg); + if (count($err['params'])) { + foreach ($err['params'] as $name => $val) { + if (is_array($val)) { + // @ is needed in case $val is a multi-dimensional array + $val = @implode(', ', $val); + } + if (is_object($val)) { + if (method_exists($val, '__toString')) { + $val = $val->__toString(); + } else { + PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING, + 'warning', array('obj' => get_class($val)), + 'object %obj% passed into getErrorMessage, but has no __toString() method'); + $val = 'Object'; + } + } + $mainmsg = str_replace('%' . $name . '%', $val, $mainmsg); + } + } + return $mainmsg; + } + + /** + * Standard Error Message Template generator from code + * @return string + */ + function getErrorMessageTemplate($code) + { + if (!isset($this->_errorMsgs[$code])) { + return '%__msg%'; + } + return $this->_errorMsgs[$code]; + } + + /** + * Set the Error Message Template array + * + * The array format must be: + * <pre> + * array(error code => 'message template',...) + * </pre> + * + * Error message parameters passed into {@link push()} will be used as input + * for the error message. If the template is 'message %foo% was %bar%', and the + * parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will + * be 'message one was six' + * @return string + */ + function setErrorMessageTemplate($template) + { + $this->_errorMsgs = $template; + } + + + /** + * emulate PEAR::raiseError() + * + * @return PEAR_Error + */ + function raiseError() + { + require_once 'PEAR.php'; + $args = func_get_args(); + return call_user_func_array(array('PEAR', 'raiseError'), $args); + } +} +$stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); +$stack->pushCallback(array('PEAR_ErrorStack', '_handleError')); +?>
\ No newline at end of file diff --git a/pear/PEAR/Exception.php b/pear/PEAR/Exception.php new file mode 100644 index 000000000..c9577232b --- /dev/null +++ b/pear/PEAR/Exception.php @@ -0,0 +1,359 @@ +<?php +/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */ +// +----------------------------------------------------------------------+ +// | PEAR_Exception | +// +----------------------------------------------------------------------+ +// | Copyright (c) 2004 The PEAR Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available at through the world-wide-web at | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Authors: Tomas V.V.Cox <cox@idecnet.com> | +// | Hans Lellelid <hans@velum.net> | +// | Bertrand Mansion <bmansion@mamasam.com> | +// | Greg Beaver <cellog@php.net> | +// +----------------------------------------------------------------------+ +// +// $Id: Exception.php,v 1.4.2.2 2005/03/28 16:46:06 cellog Exp $ + + +/** + * Base PEAR_Exception Class + * + * WARNING: This code should be considered stable, but the API is + * subject to immediate and drastic change, so API stability is + * at best alpha + * + * 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 + * + * <code> + * 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; + * } + * </code> + * + * @since PHP 5 + * @package PEAR + * @version $Revision: 1.4.2.2 $ + * @author Tomas V.V.Cox <cox@idecnet.com> + * @author Hans Lellelid <hans@velum.net> + * @author Bertrand Mansion <bmansion@mamasam.com> + * + */ +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, array $causes); + * PEAR_Exception(string $message, array $causes, int $code); + */ + public function __construct($message, $p2 = null, $p3 = null) + { + if (is_int($p2)) { + $code = $p2; + $this->cause = null; + } elseif ($p2 instanceof Exception || is_array($p2)) { + $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: + * <pre> + * array('name' => $name, 'context' => array(...)) + * </pre> + * @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']; + } + } + if ($this->cause instanceof PEAR_Exception) { + $this->cause->getCauseMessage($causes); + } + if (is_array($this->cause)) { + foreach ($this->cause as $cause) { + if ($cause instanceof PEAR_Exception) { + $cause->getCauseMessage($causes); + } 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 = '<table border="1" cellspacing="0">' . "\n"; + foreach ($causes as $i => $cause) { + $html .= '<tr><td colspan="3" bgcolor="#ff9999">' + . str_repeat('-', $i) . ' <b>' . $cause['class'] . '</b>: ' + . htmlspecialchars($cause['message']) . ' in <b>' . $cause['file'] . '</b> ' + . 'on line <b>' . $cause['line'] . '</b>' + . "</td></tr>\n"; + } + $html .= '<tr><td colspan="3" bgcolor="#aaaaaa" align="center"><b>Exception trace</b></td></tr>' . "\n" + . '<tr><td align="center" bgcolor="#cccccc" width="20"><b>#</b></td>' + . '<td align="center" bgcolor="#cccccc"><b>Function</b></td>' + . '<td align="center" bgcolor="#cccccc"><b>Location</b></td></tr>' . "\n"; + + foreach ($trace as $k => $v) { + $html .= '<tr><td align="center">' . $k . '</td>' + . '<td>'; + 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) . ')' + . '</td>' + . '<td>' . $v['file'] . ':' . $v['line'] . '</td></tr>' . "\n"; + } + $html .= '<tr><td align="center">' . ($k+1) . '</td>' + . '<td>{main}</td>' + . '<td> </td></tr>' . "\n" + . '</table>'; + 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(); + } +} + +?>
\ No newline at end of file diff --git a/pear/PEAR/Frontend/CLI.php b/pear/PEAR/Frontend/CLI.php new file mode 100644 index 000000000..832ddf09b --- /dev/null +++ b/pear/PEAR/Frontend/CLI.php @@ -0,0 +1,509 @@ +<?php +/* + +----------------------------------------------------------------------+ + | PHP Version 5 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2004 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.0 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_0.txt. | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Stig Sæther Bakken <ssb@php.net> | + +----------------------------------------------------------------------+ + + $Id: CLI.php,v 1.41 2004/02/17 05:49:16 ssb Exp $ +*/ + +require_once "PEAR.php"; + +class PEAR_Frontend_CLI extends PEAR +{ + // {{{ properties + + /** + * What type of user interface this frontend is for. + * @var string + * @access public + */ + var $type = 'CLI'; + var $lp = ''; // line prefix + + var $params = array(); + var $term = array( + 'bold' => '', + 'normal' => '', + ); + + // }}} + + // {{{ constructor + + function PEAR_Frontend_CLI() + { + parent::PEAR(); + $term = getenv('TERM'); //(cox) $_ENV is empty for me in 4.1.1 + if (function_exists('posix_isatty') && !posix_isatty(1)) { + // output is being redirected to a file or through a pipe + } elseif ($term) { + // XXX can use ncurses extension here, if available + if (preg_match('/^(xterm|vt220|linux)/', $term)) { + $this->term['bold'] = sprintf("%c%c%c%c", 27, 91, 49, 109); + $this->term['normal']=sprintf("%c%c%c", 27, 91, 109); + } elseif (preg_match('/^vt100/', $term)) { + $this->term['bold'] = sprintf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0); + $this->term['normal']=sprintf("%c%c%c%c%c", 27, 91, 109, 0, 0); + } + } elseif (OS_WINDOWS) { + // XXX add ANSI codes here + } + } + + // }}} + + // {{{ displayLine(text) + + function displayLine($text) + { + trigger_error("PEAR_Frontend_CLI::displayLine deprecated", E_USER_ERROR); + } + + function _displayLine($text) + { + print "$this->lp$text\n"; + } + + // }}} + // {{{ display(text) + + function display($text) + { + trigger_error("PEAR_Frontend_CLI::display deprecated", E_USER_ERROR); + } + + function _display($text) + { + print $text; + } + + // }}} + // {{{ displayError(eobj) + + /** + * @param object PEAR_Error object + */ + function displayError($eobj) + { + return $this->_displayLine($eobj->getMessage()); + } + + // }}} + // {{{ displayFatalError(eobj) + + /** + * @param object PEAR_Error object + */ + function displayFatalError($eobj) + { + $this->displayError($eobj); + exit(1); + } + + // }}} + // {{{ displayHeading(title) + + function displayHeading($title) + { + trigger_error("PEAR_Frontend_CLI::displayHeading deprecated", E_USER_ERROR); + } + + function _displayHeading($title) + { + print $this->lp.$this->bold($title)."\n"; + print $this->lp.str_repeat("=", strlen($title))."\n"; + } + + // }}} + // {{{ userDialog(prompt, [type], [default]) + + function userDialog($command, $prompts, $types = array(), $defaults = array()) + { + $result = array(); + if (is_array($prompts)) { + $fp = fopen("php://stdin", "r"); + foreach ($prompts as $key => $prompt) { + $type = $types[$key]; + $default = @$defaults[$key]; + if ($type == 'password') { + system('stty -echo'); + } + print "$this->lp$prompt "; + if ($default) { + print "[$default] "; + } + print ": "; + $line = fgets($fp, 2048); + if ($type == 'password') { + system('stty echo'); + print "\n"; + } + if ($default && trim($line) == "") { + $result[$key] = $default; + } else { + $result[$key] = $line; + } + } + fclose($fp); + } + return $result; + } + + // }}} + // {{{ userConfirm(prompt, [default]) + + function userConfirm($prompt, $default = 'yes') + { + trigger_error("PEAR_Frontend_CLI::userConfirm not yet converted", E_USER_ERROR); + static $positives = array('y', 'yes', 'on', '1'); + static $negatives = array('n', 'no', 'off', '0'); + print "$this->lp$prompt [$default] : "; + $fp = fopen("php://stdin", "r"); + $line = fgets($fp, 2048); + fclose($fp); + $answer = strtolower(trim($line)); + if (empty($answer)) { + $answer = $default; + } + if (in_array($answer, $positives)) { + return true; + } + if (in_array($answer, $negatives)) { + return false; + } + if (in_array($default, $positives)) { + return true; + } + return false; + } + + // }}} + // {{{ startTable([params]) + + function startTable($params = array()) + { + trigger_error("PEAR_Frontend_CLI::startTable deprecated", E_USER_ERROR); + } + + function _startTable($params = array()) + { + $params['table_data'] = array(); + $params['widest'] = array(); // indexed by column + $params['highest'] = array(); // indexed by row + $params['ncols'] = 0; + $this->params = $params; + } + + // }}} + // {{{ tableRow(columns, [rowparams], [colparams]) + + function tableRow($columns, $rowparams = array(), $colparams = array()) + { + trigger_error("PEAR_Frontend_CLI::tableRow deprecated", E_USER_ERROR); + } + + function _tableRow($columns, $rowparams = array(), $colparams = array()) + { + $highest = 1; + for ($i = 0; $i < sizeof($columns); $i++) { + $col = &$columns[$i]; + if (isset($colparams[$i]) && !empty($colparams[$i]['wrap'])) { + $col = wordwrap($col, $colparams[$i]['wrap'], "\n", 0); + } + if (strpos($col, "\n") !== false) { + $multiline = explode("\n", $col); + $w = 0; + foreach ($multiline as $n => $line) { + if (strlen($line) > $w) { + $w = strlen($line); + } + } + $lines = sizeof($multiline); + } else { + $w = strlen($col); + } + if ($w > @$this->params['widest'][$i]) { + $this->params['widest'][$i] = $w; + } + $tmp = count_chars($columns[$i], 1); + // handle unix, mac and windows formats + $lines = (isset($tmp[10]) ? $tmp[10] : @$tmp[13]) + 1; + if ($lines > $highest) { + $highest = $lines; + } + } + if (sizeof($columns) > $this->params['ncols']) { + $this->params['ncols'] = sizeof($columns); + } + $new_row = array( + 'data' => $columns, + 'height' => $highest, + 'rowparams' => $rowparams, + 'colparams' => $colparams, + ); + $this->params['table_data'][] = $new_row; + } + + // }}} + // {{{ endTable() + + function endTable() + { + trigger_error("PEAR_Frontend_CLI::endTable deprecated", E_USER_ERROR); + } + + function _endTable() + { + extract($this->params); + if (!empty($caption)) { + $this->_displayHeading($caption); + } + if (count($table_data) == 0) { + return; + } + if (!isset($width)) { + $width = $widest; + } else { + for ($i = 0; $i < $ncols; $i++) { + if (!isset($width[$i])) { + $width[$i] = $widest[$i]; + } + } + } + $border = false; + if (empty($border)) { + $cellstart = ''; + $cellend = ' '; + $rowend = ''; + $padrowend = false; + $borderline = ''; + } else { + $cellstart = '| '; + $cellend = ' '; + $rowend = '|'; + $padrowend = true; + $borderline = '+'; + foreach ($width as $w) { + $borderline .= str_repeat('-', $w + strlen($cellstart) + strlen($cellend) - 1); + $borderline .= '+'; + } + } + if ($borderline) { + $this->_displayLine($borderline); + } + for ($i = 0; $i < sizeof($table_data); $i++) { + extract($table_data[$i]); + if (!is_array($rowparams)) { + $rowparams = array(); + } + if (!is_array($colparams)) { + $colparams = array(); + } + $rowlines = array(); + if ($height > 1) { + for ($c = 0; $c < sizeof($data); $c++) { + $rowlines[$c] = preg_split('/(\r?\n|\r)/', $data[$c]); + if (sizeof($rowlines[$c]) < $height) { + $rowlines[$c] = array_pad($rowlines[$c], $height, ''); + } + } + } else { + for ($c = 0; $c < sizeof($data); $c++) { + $rowlines[$c] = array($data[$c]); + } + } + for ($r = 0; $r < $height; $r++) { + $rowtext = ''; + for ($c = 0; $c < sizeof($data); $c++) { + if (isset($colparams[$c])) { + $attribs = array_merge($rowparams, $colparams); + } else { + $attribs = $rowparams; + } + $w = isset($width[$c]) ? $width[$c] : 0; + //$cell = $data[$c]; + $cell = $rowlines[$c][$r]; + $l = strlen($cell); + if ($l > $w) { + $cell = substr($cell, 0, $w); + } + if (isset($attribs['bold'])) { + $cell = $this->bold($cell); + } + if ($l < $w) { + // not using str_pad here because we may + // add bold escape characters to $cell + $cell .= str_repeat(' ', $w - $l); + } + + $rowtext .= $cellstart . $cell . $cellend; + } + if (!$border) { + $rowtext = rtrim($rowtext); + } + $rowtext .= $rowend; + $this->_displayLine($rowtext); + } + } + if ($borderline) { + $this->_displayLine($borderline); + } + } + + // }}} + // {{{ outputData() + + function outputData($data, $command = '_default') + { + switch ($command) { + case 'install': + case 'upgrade': + case 'upgrade-all': + if (isset($data['release_warnings'])) { + $this->_displayLine(''); + $this->_startTable(array( + 'border' => false, + 'caption' => 'Release Warnings' + )); + $this->_tableRow(array($data['release_warnings']), null, array(1 => array('wrap' => 55))); + $this->_endTable(); + $this->_displayLine(''); + } + $this->_displayLine($data['data']); + break; + case 'search': + $this->_startTable($data); + if (isset($data['headline']) && is_array($data['headline'])) { + $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55))); + } + + foreach($data['data'] as $category) { + foreach($category as $pkg) { + $this->_tableRow($pkg, null, array(1 => array('wrap' => 55))); + } + }; + $this->_endTable(); + break; + case 'list-all': + $this->_startTable($data); + if (isset($data['headline']) && is_array($data['headline'])) { + $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55))); + } + + foreach($data['data'] as $category) { + foreach($category as $pkg) { + unset($pkg[3]); + unset($pkg[4]); + $this->_tableRow($pkg, null, array(1 => array('wrap' => 55))); + } + }; + $this->_endTable(); + break; + case 'config-show': + $data['border'] = false; + $opts = array(0 => array('wrap' => 30), + 1 => array('wrap' => 20), + 2 => array('wrap' => 35)); + $this->_startTable($data); + if (isset($data['headline']) && is_array($data['headline'])) { + $this->_tableRow($data['headline'], + array('bold' => true), + $opts); + } + foreach($data['data'] as $group) { + foreach($group as $value) { + if ($value[2] == '') { + $value[2] = "<not set>"; + } + $this->_tableRow($value, null, $opts); + } + } + $this->_endTable(); + break; + case 'remote-info': + $data = array( + 'caption' => 'Package details:', + 'border' => false, + 'data' => array( + array("Latest", $data['stable']), + array("Installed", $data['installed']), + array("Package", $data['name']), + array("License", $data['license']), + array("Category", $data['category']), + array("Summary", $data['summary']), + array("Description", $data['description']), + ), + ); + default: { + if (is_array($data)) { + $this->_startTable($data); + $count = count($data['data'][0]); + if ($count == 2) { + $opts = array(0 => array('wrap' => 25), + 1 => array('wrap' => 48) + ); + } elseif ($count == 3) { + $opts = array(0 => array('wrap' => 30), + 1 => array('wrap' => 20), + 2 => array('wrap' => 35) + ); + } else { + $opts = null; + } + if (isset($data['headline']) && is_array($data['headline'])) { + $this->_tableRow($data['headline'], + array('bold' => true), + $opts); + } + foreach($data['data'] as $row) { + $this->_tableRow($row, null, $opts); + } + $this->_endTable(); + } else { + $this->_displayLine($data); + } + } + } + } + + // }}} + // {{{ log(text) + + + function log($text, $append_crlf = true) + { + if ($append_crlf) { + return $this->_displayLine($text); + } + return $this->_display($text); + } + + + // }}} + // {{{ bold($text) + + function bold($text) + { + if (empty($this->term['bold'])) { + return strtoupper($text); + } + return $this->term['bold'] . $text . $this->term['normal']; + } + + // }}} +} + +?> diff --git a/pear/PEAR/Installer.php b/pear/PEAR/Installer.php new file mode 100644 index 000000000..22686f236 --- /dev/null +++ b/pear/PEAR/Installer.php @@ -0,0 +1,1068 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Authors: Stig Bakken <ssb@php.net> | +// | Tomas V.V.Cox <cox@idecnet.com> | +// | Martin Jansen <mj@php.net> | +// +----------------------------------------------------------------------+ +// +// $Id: Installer.php,v 1.150.2.2 2005/03/28 16:46:06 cellog Exp $ + +require_once 'PEAR/Downloader.php'; + +/** + * Administration class used to install PEAR packages and maintain the + * installed package database. + * + * TODO: + * - Check dependencies break on package uninstall (when no force given) + * - add a guessInstallDest() method with the code from _installFile() and + * use that method in Registry::_rebuildFileMap() & Command_Registry::doList(), + * others.. + * + * @since PHP 4.0.2 + * @author Stig Bakken <ssb@php.net> + * @author Martin Jansen <mj@php.net> + * @author Greg Beaver <cellog@php.net> + */ +class PEAR_Installer extends PEAR_Downloader +{ + // {{{ properties + + /** name of the package directory, for example Foo-1.0 + * @var string + */ + var $pkgdir; + + /** directory where PHP code files go + * @var string + */ + var $phpdir; + + /** directory where PHP extension files go + * @var string + */ + var $extdir; + + /** directory where documentation goes + * @var string + */ + var $docdir; + + /** installation root directory (ala PHP's INSTALL_ROOT or + * automake's DESTDIR + * @var string + */ + var $installroot = ''; + + /** debug level + * @var int + */ + var $debug = 1; + + /** temporary directory + * @var string + */ + var $tmpdir; + + /** PEAR_Registry object used by the installer + * @var object + */ + var $registry; + + /** List of file transactions queued for an install/upgrade/uninstall. + * + * Format: + * array( + * 0 => array("rename => array("from-file", "to-file")), + * 1 => array("delete" => array("file-to-delete")), + * ... + * ) + * + * @var array + */ + var $file_operations = array(); + + // }}} + + // {{{ constructor + + /** + * PEAR_Installer constructor. + * + * @param object $ui user interface object (instance of PEAR_Frontend_*) + * + * @access public + */ + function PEAR_Installer(&$ui) + { + parent::PEAR_Common(); + $this->setFrontendObject($ui); + $this->debug = $this->config->get('verbose'); + //$this->registry = &new PEAR_Registry($this->config->get('php_dir')); + } + + // }}} + + // {{{ _deletePackageFiles() + + /** + * Delete a package's installed files, does not remove empty directories. + * + * @param string $package package name + * + * @return bool TRUE on success, or a PEAR error on failure + * + * @access private + */ + function _deletePackageFiles($package) + { + if (!strlen($package)) { + return $this->raiseError("No package to uninstall given"); + } + $filelist = $this->registry->packageInfo($package, 'filelist'); + if ($filelist == null) { + return $this->raiseError("$package not installed"); + } + foreach ($filelist as $file => $props) { + if (empty($props['installed_as'])) { + continue; + } + $path = $this->_prependPath($props['installed_as'], $this->installroot); + $this->addFileOperation('delete', array($path)); + } + return true; + } + + // }}} + // {{{ _installFile() + + /** + * @param string filename + * @param array attributes from <file> tag in package.xml + * @param string path to install the file in + * @param array options from command-line + * @access private + */ + function _installFile($file, $atts, $tmp_path, $options) + { + // {{{ return if this file is meant for another platform + static $os; + if (isset($atts['platform'])) { + if (empty($os)) { + include_once "OS/Guess.php"; + $os = new OS_Guess(); + } + if (strlen($atts['platform']) && $atts['platform']{0} == '!') { + $negate = true; + $platform = substr($atts['platform'], 1); + } else { + $negate = false; + $platform = $atts['platform']; + } + if ((bool) $os->matchSignature($platform) === $negate) { + $this->log(3, "skipped $file (meant for $atts[platform], we are ".$os->getSignature().")"); + return PEAR_INSTALLER_SKIPPED; + } + } + // }}} + + // {{{ assemble the destination paths + switch ($atts['role']) { + case 'doc': + case 'data': + case 'test': + $dest_dir = $this->config->get($atts['role'] . '_dir') . + DIRECTORY_SEPARATOR . $this->pkginfo['package']; + unset($atts['baseinstalldir']); + break; + case 'ext': + case 'php': + $dest_dir = $this->config->get($atts['role'] . '_dir'); + break; + case 'script': + $dest_dir = $this->config->get('bin_dir'); + break; + case 'src': + case 'extsrc': + $this->source_files++; + return; + default: + return $this->raiseError("Invalid role `$atts[role]' for file $file"); + } + $save_destdir = $dest_dir; + if (!empty($atts['baseinstalldir'])) { + $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir']; + } + 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_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"), + DIRECTORY_SEPARATOR, + array($dest_file, $orig_file)); + $installed_as = $dest_file; + $final_dest_file = $this->_prependPath($dest_file, $this->installroot); + $dest_dir = dirname($final_dest_file); + $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); + // }}} + + if (!@is_dir($dest_dir)) { + if (!$this->mkDirHier($dest_dir)) { + return $this->raiseError("failed to mkdir $dest_dir", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ mkdir $dest_dir"); + } + if (empty($atts['replacements'])) { + if (!file_exists($orig_file)) { + return $this->raiseError("file does not exist", + PEAR_INSTALLER_FAILED); + } + if (!@copy($orig_file, $dest_file)) { + return $this->raiseError("failed to write $dest_file", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ cp $orig_file $dest_file"); + if (isset($atts['md5sum'])) { + $md5sum = md5_file($dest_file); + } + } else { + // {{{ file with replacements + if (!file_exists($orig_file)) { + return $this->raiseError("file does not exist", + PEAR_INSTALLER_FAILED); + } + $fp = fopen($orig_file, "r"); + $contents = fread($fp, filesize($orig_file)); + fclose($fp); + if (isset($atts['md5sum'])) { + $md5sum = md5($contents); + } + $subst_from = $subst_to = array(); + foreach ($atts['replacements'] as $a) { + $to = ''; + if ($a['type'] == 'php-const') { + if (preg_match('/^[a-z0-9_]+$/i', $a['to'])) { + eval("\$to = $a[to];"); + } else { + $this->log(0, "invalid php-const replacement: $a[to]"); + continue; + } + } elseif ($a['type'] == 'pear-config') { + $to = $this->config->get($a['to']); + if (is_null($to)) { + $this->log(0, "invalid pear-config replacement: $a[to]"); + continue; + } + } elseif ($a['type'] == 'package-info') { + if (isset($this->pkginfo[$a['to']]) && is_string($this->pkginfo[$a['to']])) { + $to = $this->pkginfo[$a['to']]; + } else { + $this->log(0, "invalid package-info replacement: $a[to]"); + continue; + } + } + if (!is_null($to)) { + $subst_from[] = $a['from']; + $subst_to[] = $to; + } + } + $this->log(3, "doing ".sizeof($subst_from)." substitution(s) for $final_dest_file"); + if (sizeof($subst_from)) { + $contents = str_replace($subst_from, $subst_to, $contents); + } + $wp = @fopen($dest_file, "wb"); + if (!is_resource($wp)) { + return $this->raiseError("failed to create $dest_file: $php_errormsg", + PEAR_INSTALLER_FAILED); + } + if (!fwrite($wp, $contents)) { + return $this->raiseError("failed writing to $dest_file: $php_errormsg", + PEAR_INSTALLER_FAILED); + } + fclose($wp); + // }}} + } + // {{{ check the md5 + if (isset($md5sum)) { + if (strtolower($md5sum) == strtolower($atts['md5sum'])) { + $this->log(2, "md5sum ok: $final_dest_file"); + } else { + if (empty($options['force'])) { + // delete the file + @unlink($dest_file); + return $this->raiseError("bad md5sum for file $final_dest_file", + PEAR_INSTALLER_FAILED); + } else { + $this->log(0, "warning : bad md5sum for file $final_dest_file"); + } + } + } + // }}} + // {{{ set file permissions + if (!OS_WINDOWS) { + if ($atts['role'] == 'script') { + $mode = 0777 & ~(int)octdec($this->config->get('umask')); + $this->log(3, "+ chmod +x $dest_file"); + } else { + $mode = 0666 & ~(int)octdec($this->config->get('umask')); + } + $this->addFileOperation("chmod", array($mode, $dest_file)); + if (!@chmod($dest_file, $mode)) { + $this->log(0, "failed to change mode of $dest_file"); + } + } + // }}} + $this->addFileOperation("rename", array($dest_file, $final_dest_file)); + // Store the full path where the file was installed for easy unistall + $this->addFileOperation("installed_as", array($file, $installed_as, + $save_destdir, dirname(substr($dest_file, strlen($save_destdir))))); + + //$this->log(2, "installed: $dest_file"); + return PEAR_INSTALLER_OK; + } + + // }}} + // {{{ addFileOperation() + + /** + * Add a file operation to the current file transaction. + * + * @see startFileTransaction() + * @var string $type This can be one of: + * - rename: rename a file ($data has 2 values) + * - chmod: change permissions on a file ($data has 2 values) + * - delete: delete a file ($data has 1 value) + * - rmdir: delete a directory if empty ($data has 1 value) + * - installed_as: mark a file as installed ($data has 4 values). + * @var array $data For all file operations, this array must contain the + * full path to the file or directory that is being operated on. For + * the rename command, the first parameter must be the file to rename, + * the second its new name. + * + * The installed_as operation contains 4 elements in this order: + * 1. Filename as listed in the filelist element from package.xml + * 2. Full path to the installed file + * 3. Full path from the php_dir configuration variable used in this + * installation + * 4. Relative path from the php_dir that this file is installed in + */ + function addFileOperation($type, $data) + { + if (!is_array($data)) { + return $this->raiseError('Internal Error: $data in addFileOperation' + . ' must be an array, was ' . gettype($data)); + } + if ($type == 'chmod') { + $octmode = decoct($data[0]); + $this->log(3, "adding to transaction: $type $octmode $data[1]"); + } else { + $this->log(3, "adding to transaction: $type " . implode(" ", $data)); + } + $this->file_operations[] = array($type, $data); + } + + // }}} + // {{{ startFileTransaction() + + function startFileTransaction($rollback_in_case = false) + { + if (count($this->file_operations) && $rollback_in_case) { + $this->rollbackFileTransaction(); + } + $this->file_operations = array(); + } + + // }}} + // {{{ commitFileTransaction() + + function commitFileTransaction() + { + $n = count($this->file_operations); + $this->log(2, "about to commit $n file operations"); + // {{{ first, check permissions and such manually + $errors = array(); + foreach ($this->file_operations as $tr) { + list($type, $data) = $tr; + switch ($type) { + case 'rename': + if (!file_exists($data[0])) { + $errors[] = "cannot rename file $data[0], doesn't exist"; + } + // check that dest dir. is writable + if (!is_writable(dirname($data[1]))) { + $errors[] = "permission denied ($type): $data[1]"; + } + break; + case 'chmod': + // check that file is writable + if (!is_writable($data[1])) { + $errors[] = "permission denied ($type): $data[1] " . decoct($data[0]); + } + break; + case 'delete': + if (!file_exists($data[0])) { + $this->log(2, "warning: file $data[0] doesn't exist, can't be deleted"); + } + // check that directory is writable + if (file_exists($data[0]) && !is_writable(dirname($data[0]))) { + $errors[] = "permission denied ($type): $data[0]"; + } + break; + } + + } + // }}} + $m = sizeof($errors); + if ($m > 0) { + foreach ($errors as $error) { + $this->log(1, $error); + } + return false; + } + // {{{ really commit the transaction + foreach ($this->file_operations as $tr) { + list($type, $data) = $tr; + switch ($type) { + case 'rename': + @unlink($data[1]); + @rename($data[0], $data[1]); + $this->log(3, "+ mv $data[0] $data[1]"); + break; + case 'chmod': + @chmod($data[1], $data[0]); + $octmode = decoct($data[0]); + $this->log(3, "+ chmod $octmode $data[1]"); + break; + case 'delete': + @unlink($data[0]); + $this->log(3, "+ rm $data[0]"); + break; + case 'rmdir': + @rmdir($data[0]); + $this->log(3, "+ rmdir $data[0]"); + break; + case 'installed_as': + $this->pkginfo['filelist'][$data[0]]['installed_as'] = $data[1]; + if (!isset($this->pkginfo['filelist']['dirtree'][dirname($data[1])])) { + $this->pkginfo['filelist']['dirtree'][dirname($data[1])] = true; + while(!empty($data[3]) && $data[3] != '/' && $data[3] != '\\' + && $data[3] != '.') { + $this->pkginfo['filelist']['dirtree'] + [$this->_prependPath($data[3], $data[2])] = true; + $data[3] = dirname($data[3]); + } + } + break; + } + } + // }}} + $this->log(2, "successfully committed $n file operations"); + $this->file_operations = array(); + return true; + } + + // }}} + // {{{ rollbackFileTransaction() + + function rollbackFileTransaction() + { + $n = count($this->file_operations); + $this->log(2, "rolling back $n file operations"); + foreach ($this->file_operations as $tr) { + list($type, $data) = $tr; + switch ($type) { + case 'rename': + @unlink($data[0]); + $this->log(3, "+ rm $data[0]"); + break; + case 'mkdir': + @rmdir($data[0]); + $this->log(3, "+ rmdir $data[0]"); + break; + case 'chmod': + break; + case 'delete': + break; + case 'installed_as': + if (isset($this->pkginfo['filelist'])) { + unset($this->pkginfo['filelist'][$data[0]]['installed_as']); + } + if (isset($this->pkginfo['filelist']['dirtree'][dirname($data[1])])) { + unset($this->pkginfo['filelist']['dirtree'][dirname($data[1])]); + while(!empty($data[3]) && $data[3] != '/' && $data[3] != '\\' + && $data[3] != '.') { + unset($this->pkginfo['filelist']['dirtree'] + [$this->_prependPath($data[3], $data[2])]); + $data[3] = dirname($data[3]); + } + } + if (isset($this->pkginfo['filelist']['dirtree']) + && !count($this->pkginfo['filelist']['dirtree'])) { + unset($this->pkginfo['filelist']['dirtree']); + } + break; + } + } + $this->file_operations = array(); + } + + // }}} + // {{{ mkDirHier($dir) + + function mkDirHier($dir) + { + $this->addFileOperation('mkdir', array($dir)); + return parent::mkDirHier($dir); + } + + // }}} + // {{{ download() + + /** + * Download any files and their dependencies, if necessary + * + * @param array a mixed list of package names, local files, or package.xml + * @param PEAR_Config + * @param array options from the command line + * @param array this is the array that will be populated with packages to + * install. Format of each entry: + * + * <code> + * array('pkg' => 'package_name', 'file' => '/path/to/local/file', + * 'info' => array() // parsed package.xml + * ); + * </code> + * @param array this will be populated with any error messages + * @param false private recursion variable + * @param false private recursion variable + * @param false private recursion variable + * @deprecated in favor of PEAR_Downloader + */ + function download($packages, $options, &$config, &$installpackages, + &$errors, $installed = false, $willinstall = false, $state = false) + { + // trickiness: initialize here + parent::PEAR_Downloader($this->ui, $options, $config); + $ret = parent::download($packages); + $errors = $this->getErrorMsgs(); + $installpackages = $this->getDownloadedPackages(); + trigger_error("PEAR Warning: PEAR_Installer::download() is deprecated " . + "in favor of PEAR_Downloader class", E_USER_WARNING); + return $ret; + } + + // }}} + // {{{ install() + + /** + * Installs the files within the package file specified. + * + * @param string $pkgfile path to the package file + * @param array $options + * recognized options: + * - installroot : optional prefix directory for installation + * - force : force installation + * - register-only : update registry but don't install files + * - upgrade : upgrade existing install + * - soft : fail silently + * - nodeps : ignore dependency conflicts/missing dependencies + * - alldeps : install all dependencies + * - onlyreqdeps : install only required dependencies + * + * @return array|PEAR_Error package info if successful + */ + + function install($pkgfile, $options = array()) + { + $php_dir = $this->config->get('php_dir'); + if (isset($options['installroot'])) { + if (substr($options['installroot'], -1) == DIRECTORY_SEPARATOR) { + $options['installroot'] = substr($options['installroot'], 0, -1); + } + $php_dir = $this->_prependPath($php_dir, $options['installroot']); + $this->installroot = $options['installroot']; + } else { + $this->installroot = ''; + } + $this->registry = &new PEAR_Registry($php_dir); + // ==> XXX should be removed later on + $flag_old_format = false; + + if (substr($pkgfile, -4) == '.xml') { + $descfile = $pkgfile; + } else { + // {{{ Decompress pack in tmp dir ------------------------------------- + + // To allow relative package file names + $pkgfile = realpath($pkgfile); + + if (PEAR::isError($tmpdir = System::mktemp('-d'))) { + return $tmpdir; + } + $this->log(3, '+ tmp dir created at ' . $tmpdir); + + $tar = new Archive_Tar($pkgfile); + if (!@$tar->extract($tmpdir)) { + return $this->raiseError("unable to unpack $pkgfile"); + } + + // {{{ Look for existing package file + $descfile = $tmpdir . DIRECTORY_SEPARATOR . 'package.xml'; + + if (!is_file($descfile)) { + // ----- Look for old package archive format + // In this format the package.xml file was inside the + // Package-n.n directory + $dp = opendir($tmpdir); + do { + $pkgdir = readdir($dp); + } while ($pkgdir{0} == '.'); + + $descfile = $tmpdir . DIRECTORY_SEPARATOR . $pkgdir . DIRECTORY_SEPARATOR . 'package.xml'; + $flag_old_format = true; + $this->log(0, "warning : you are using an archive with an old format"); + } + // }}} + // <== XXX This part should be removed later on + // }}} + } + + if (!is_file($descfile)) { + return $this->raiseError("no package.xml file after extracting the archive"); + } + + // Parse xml file ----------------------------------------------- + $pkginfo = $this->infoFromDescriptionFile($descfile); + if (PEAR::isError($pkginfo)) { + return $pkginfo; + } + $this->validatePackageInfo($pkginfo, $errors, $warnings); + // XXX We allow warnings, do we have to do it? + if (count($errors)) { + if (empty($options['force'])) { + return $this->raiseError("The following errors where found (use force option to install anyway):\n". + implode("\n", $errors)); + } else { + $this->log(0, "warning : the following errors were found:\n". + implode("\n", $errors)); + } + } + + $pkgname = $pkginfo['package']; + + // {{{ Check dependencies ------------------------------------------- + if (isset($pkginfo['release_deps']) && empty($options['nodeps'])) { + $dep_errors = ''; + $error = $this->checkDeps($pkginfo, $dep_errors); + if ($error == true) { + if (empty($options['soft'])) { + $this->log(0, substr($dep_errors, 1)); + } + return $this->raiseError("$pkgname: Dependencies failed"); + } else if (!empty($dep_errors)) { + // Print optional dependencies + if (empty($options['soft'])) { + $this->log(0, $dep_errors); + } + } + } + // }}} + + // {{{ checks to do when not in "force" mode + if (empty($options['force'])) { + $test = $this->registry->checkFileMap($pkginfo); + if (sizeof($test)) { + $tmp = $test; + foreach ($tmp as $file => $pkg) { + if ($pkg == $pkgname) { + unset($test[$file]); + } + } + if (sizeof($test)) { + $msg = "$pkgname: conflicting files found:\n"; + $longest = max(array_map("strlen", array_keys($test))); + $fmt = "%${longest}s (%s)\n"; + foreach ($test as $file => $pkg) { + $msg .= sprintf($fmt, $file, $pkg); + } + return $this->raiseError($msg); + } + } + } + // }}} + + $this->startFileTransaction(); + + if (empty($options['upgrade'])) { + // checks to do only when installing new packages + if (empty($options['force']) && $this->registry->packageExists($pkgname)) { + return $this->raiseError("$pkgname already installed"); + } + } else { + if ($this->registry->packageExists($pkgname)) { + $v1 = $this->registry->packageInfo($pkgname, 'version'); + $v2 = $pkginfo['version']; + $cmp = version_compare("$v1", "$v2", 'gt'); + if (empty($options['force']) && !version_compare("$v2", "$v1", 'gt')) { + return $this->raiseError("upgrade to a newer version ($v2 is not newer than $v1)"); + } + if (empty($options['register-only'])) { + // when upgrading, remove old release's files first: + if (PEAR::isError($err = $this->_deletePackageFiles($pkgname))) { + return $this->raiseError($err); + } + } + } + } + + // {{{ Copy files to dest dir --------------------------------------- + + // info from the package it self we want to access from _installFile + $this->pkginfo = &$pkginfo; + // used to determine whether we should build any C code + $this->source_files = 0; + + if (empty($options['register-only'])) { + if (!is_dir($php_dir)) { + return $this->raiseError("no script destination directory\n", + null, PEAR_ERROR_DIE); + } + + $tmp_path = dirname($descfile); + if (substr($pkgfile, -4) != '.xml') { + $tmp_path .= DIRECTORY_SEPARATOR . $pkgname . '-' . $pkginfo['version']; + } + + // ==> XXX This part should be removed later on + if ($flag_old_format) { + $tmp_path = dirname($descfile); + } + // <== XXX This part should be removed later on + + // {{{ install files + foreach ($pkginfo['filelist'] as $file => $atts) { + $this->expectError(PEAR_INSTALLER_FAILED); + $res = $this->_installFile($file, $atts, $tmp_path, $options); + $this->popExpect(); + if (PEAR::isError($res)) { + if (empty($options['ignore-errors'])) { + $this->rollbackFileTransaction(); + if ($res->getMessage() == "file does not exist") { + $this->raiseError("file $file in package.xml does not exist"); + } + return $this->raiseError($res); + } else { + $this->log(0, "Warning: " . $res->getMessage()); + } + } + if ($res != PEAR_INSTALLER_OK) { + // Do not register files that were not installed + unset($pkginfo['filelist'][$file]); + } + } + // }}} + + // {{{ compile and install source files + if ($this->source_files > 0 && empty($options['nobuild'])) { + $this->log(1, "$this->source_files source files, building"); + $bob = &new PEAR_Builder($this->ui); + $bob->debug = $this->debug; + $built = $bob->build($descfile, array(&$this, '_buildCallback')); + if (PEAR::isError($built)) { + $this->rollbackFileTransaction(); + return $built; + } + $this->log(1, "\nBuild process completed successfully"); + foreach ($built as $ext) { + $bn = basename($ext['file']); + list($_ext_name, $_ext_suff) = explode('.', $bn); + if ($_ext_suff == '.so' || $_ext_suff == '.dll') { + if (extension_loaded($_ext_name)) { + $this->raiseError("Extension '$_ext_name' already loaded. " . + 'Please unload it in your php.ini file ' . + 'prior to install or upgrade'); + } + $role = 'ext'; + } else { + $role = 'src'; + } + $dest = $ext['dest']; + $this->log(1, "Installing '$ext[file]'"); + $copyto = $this->_prependPath($dest, $this->installroot); + $copydir = dirname($copyto); + if (!@is_dir($copydir)) { + if (!$this->mkDirHier($copydir)) { + return $this->raiseError("failed to mkdir $copydir", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ mkdir $copydir"); + } + if (!@copy($ext['file'], $copyto)) { + return $this->raiseError("failed to write $copyto", PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ cp $ext[file] $copyto"); + if (!OS_WINDOWS) { + $mode = 0666 & ~(int)octdec($this->config->get('umask')); + $this->addFileOperation('chmod', array($mode, $copyto)); + if (!@chmod($copyto, $mode)) { + $this->log(0, "failed to change mode of $copyto"); + } + } + $this->addFileOperation('rename', array($ext['file'], $copyto)); + + $pkginfo['filelist'][$bn] = array( + 'role' => $role, + 'installed_as' => $dest, + 'php_api' => $ext['php_api'], + 'zend_mod_api' => $ext['zend_mod_api'], + 'zend_ext_api' => $ext['zend_ext_api'], + ); + } + } + // }}} + } + + if (!$this->commitFileTransaction()) { + $this->rollbackFileTransaction(); + return $this->raiseError("commit failed", PEAR_INSTALLER_FAILED); + } + // }}} + + $ret = false; + // {{{ Register that the package is installed ----------------------- + if (empty($options['upgrade'])) { + // if 'force' is used, replace the info in registry + if (!empty($options['force']) && $this->registry->packageExists($pkgname)) { + $this->registry->deletePackage($pkgname); + } + $ret = $this->registry->addPackage($pkgname, $pkginfo); + } else { + // new: upgrade installs a package if it isn't installed + if (!$this->registry->packageExists($pkgname)) { + $ret = $this->registry->addPackage($pkgname, $pkginfo); + } else { + $ret = $this->registry->updatePackage($pkgname, $pkginfo, false); + } + } + if (!$ret) { + return $this->raiseError("Adding package $pkgname to registry failed"); + } + // }}} + return $pkginfo; + } + + // }}} + // {{{ uninstall() + + /** + * Uninstall a package + * + * This method removes all files installed by the application, and then + * removes any empty directories. + * @param string package name + * @param array Command-line options. Possibilities include: + * + * - installroot: base installation dir, if not the default + * - nodeps: do not process dependencies of other packages to ensure + * uninstallation does not break things + */ + function uninstall($package, $options = array()) + { + $php_dir = $this->config->get('php_dir'); + if (isset($options['installroot'])) { + if (substr($options['installroot'], -1) == DIRECTORY_SEPARATOR) { + $options['installroot'] = substr($options['installroot'], 0, -1); + } + $this->installroot = $options['installroot']; + $php_dir = $this->_prependPath($php_dir, $this->installroot); + } else { + $this->installroot = ''; + } + $this->registry = &new PEAR_Registry($php_dir); + $filelist = $this->registry->packageInfo($package, 'filelist'); + if ($filelist == null) { + return $this->raiseError("$package not installed"); + } + if (empty($options['nodeps'])) { + $depchecker = &new PEAR_Dependency($this->registry); + $error = $depchecker->checkPackageUninstall($errors, $warning, $package); + if ($error) { + return $this->raiseError($errors . 'uninstall failed'); + } + if ($warning) { + $this->log(0, $warning); + } + } + // {{{ Delete the files + $this->startFileTransaction(); + if (PEAR::isError($err = $this->_deletePackageFiles($package))) { + $this->rollbackFileTransaction(); + return $this->raiseError($err); + } + if (!$this->commitFileTransaction()) { + $this->rollbackFileTransaction(); + return $this->raiseError("uninstall failed"); + } else { + $this->startFileTransaction(); + if (!isset($filelist['dirtree']) || !count($filelist['dirtree'])) { + return $this->registry->deletePackage($package); + } + // attempt to delete empty directories + uksort($filelist['dirtree'], array($this, '_sortDirs')); + foreach($filelist['dirtree'] as $dir => $notused) { + $this->addFileOperation('rmdir', array($dir)); + } + if (!$this->commitFileTransaction()) { + $this->rollbackFileTransaction(); + } + } + // }}} + + // Register that the package is no longer installed + return $this->registry->deletePackage($package); + } + + // }}} + // {{{ _sortDirs() + function _sortDirs($a, $b) + { + if (strnatcmp($a, $b) == -1) return 1; + if (strnatcmp($a, $b) == 1) return -1; + return 0; + } + + // }}} + // {{{ checkDeps() + + /** + * Check if the package meets all dependencies + * + * @param array Package information (passed by reference) + * @param string Error message (passed by reference) + * @return boolean False when no error occured, otherwise true + */ + function checkDeps(&$pkginfo, &$errors) + { + if (empty($this->registry)) { + $this->registry = &new PEAR_Registry($this->config->get('php_dir')); + } + $depchecker = &new PEAR_Dependency($this->registry); + $error = $errors = ''; + $failed_deps = $optional_deps = array(); + if (is_array($pkginfo['release_deps'])) { + foreach($pkginfo['release_deps'] as $dep) { + $code = $depchecker->callCheckMethod($error, $dep); + if ($code) { + if (isset($dep['optional']) && $dep['optional'] == 'yes') { + $optional_deps[] = array($dep, $code, $error); + } else { + $failed_deps[] = array($dep, $code, $error); + } + } + } + // {{{ failed dependencies + $n = count($failed_deps); + if ($n > 0) { + for ($i = 0; $i < $n; $i++) { + if (isset($failed_deps[$i]['type'])) { + $type = $failed_deps[$i]['type']; + } else { + $type = 'pkg'; + } + switch ($failed_deps[$i][1]) { + case PEAR_DEPENDENCY_MISSING: + if ($type == 'pkg') { + // install + } + $errors .= "\n" . $failed_deps[$i][2]; + break; + case PEAR_DEPENDENCY_UPGRADE_MINOR: + if ($type == 'pkg') { + // upgrade + } + $errors .= "\n" . $failed_deps[$i][2]; + break; + default: + $errors .= "\n" . $failed_deps[$i][2]; + break; + } + } + return true; + } + // }}} + + // {{{ optional dependencies + $count_optional = count($optional_deps); + if ($count_optional > 0) { + $errors = "Optional dependencies:"; + + for ($i = 0; $i < $count_optional; $i++) { + if (isset($optional_deps[$i]['type'])) { + $type = $optional_deps[$i]['type']; + } else { + $type = 'pkg'; + } + switch ($optional_deps[$i][1]) { + case PEAR_DEPENDENCY_MISSING: + case PEAR_DEPENDENCY_UPGRADE_MINOR: + default: + $errors .= "\n" . $optional_deps[$i][2]; + break; + } + } + return false; + } + // }}} + } + return false; + } + + // }}} + // {{{ _buildCallback() + + function _buildCallback($what, $data) + { + if (($what == 'cmdoutput' && $this->debug > 1) || + ($what == 'output' && $this->debug > 0)) { + $this->ui->outputData(rtrim($data), 'build'); + } + } + + // }}} +} + +// {{{ md5_file() utility function +if (!function_exists("md5_file")) { + function md5_file($filename) { + $fp = fopen($filename, "r"); + if (!$fp) return null; + $contents = fread($fp, filesize($filename)); + fclose($fp); + return md5($contents); + } +} +// }}} + +?> diff --git a/pear/PEAR/Packager.php b/pear/PEAR/Packager.php new file mode 100644 index 000000000..3ed209be8 --- /dev/null +++ b/pear/PEAR/Packager.php @@ -0,0 +1,165 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Authors: Stig Bakken <ssb@php.net> | +// | Tomas V.V.Cox <cox@idecnet.com> | +// +----------------------------------------------------------------------+ +// +// $Id: Packager.php,v 1.53 2004/06/13 14:06:01 pajoye Exp $ + +require_once 'PEAR/Common.php'; +require_once 'System.php'; + +/** + * Administration class used to make a PEAR release tarball. + * + * TODO: + * - add an extra param the dir where to place the created package + * + * @since PHP 4.0.2 + * @author Stig Bakken <ssb@php.net> + */ +class PEAR_Packager extends PEAR_Common +{ + // {{{ constructor + + function PEAR_Packager() + { + parent::PEAR_Common(); + } + + // }}} + // {{{ destructor + + function _PEAR_Packager() + { + parent::_PEAR_Common(); + } + + // }}} + + // {{{ package() + + function package($pkgfile = null, $compress = true) + { + // {{{ validate supplied package.xml file + if (empty($pkgfile)) { + $pkgfile = 'package.xml'; + } + // $this->pkginfo gets populated inside + $pkginfo = $this->infoFromDescriptionFile($pkgfile); + if (PEAR::isError($pkginfo)) { + return $this->raiseError($pkginfo); + } + + $pkgdir = dirname(realpath($pkgfile)); + $pkgfile = basename($pkgfile); + + $errors = $warnings = array(); + $this->validatePackageInfo($pkginfo, $errors, $warnings, $pkgdir); + foreach ($warnings as $w) { + $this->log(1, "Warning: $w"); + } + foreach ($errors as $e) { + $this->log(0, "Error: $e"); + } + if (sizeof($errors) > 0) { + return $this->raiseError('Errors in package'); + } + // }}} + + $pkgver = $pkginfo['package'] . '-' . $pkginfo['version']; + + // {{{ Create the package file list + $filelist = array(); + $i = 0; + + foreach ($pkginfo['filelist'] as $fname => $atts) { + $file = $pkgdir . DIRECTORY_SEPARATOR . $fname; + if (!file_exists($file)) { + return $this->raiseError("File does not exist: $fname"); + } else { + $filelist[$i++] = $file; + if (empty($pkginfo['filelist'][$fname]['md5sum'])) { + $md5sum = md5_file($file); + $pkginfo['filelist'][$fname]['md5sum'] = $md5sum; + } + $this->log(2, "Adding file $fname"); + } + } + // }}} + + // {{{ regenerate package.xml + $new_xml = $this->xmlFromInfo($pkginfo); + if (PEAR::isError($new_xml)) { + return $this->raiseError($new_xml); + } + if (!($tmpdir = System::mktemp(array('-d')))) { + return $this->raiseError("PEAR_Packager: mktemp failed"); + } + $newpkgfile = $tmpdir . DIRECTORY_SEPARATOR . 'package.xml'; + $np = @fopen($newpkgfile, 'wb'); + if (!$np) { + return $this->raiseError("PEAR_Packager: unable to rewrite $pkgfile as $newpkgfile"); + } + fwrite($np, $new_xml); + fclose($np); + // }}} + + // {{{ TAR the Package ------------------------------------------- + $ext = $compress ? '.tgz' : '.tar'; + $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext; + $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($newpkgfile), '', $tmpdir); + if (PEAR::isError($ok)) { + return $this->raiseError($ok); + } elseif (!$ok) { + return $this->raiseError('PEAR_Packager: tarball creation failed'); + } + // ----- Add the content of the package + if (!$tar->addModify($filelist, $pkgver, $pkgdir)) { + return $this->raiseError('PEAR_Packager: tarball creation failed'); + } + $this->log(1, "Package $dest_package done"); + if (file_exists("$pkgdir/CVS/Root")) { + $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pkginfo['version']); + $cvstag = "RELEASE_$cvsversion"; + $this->log(1, "Tag the released code with `pear cvstag $pkgfile'"); + $this->log(1, "(or set the CVS tag $cvstag by hand)"); + } + // }}} + + return $dest_package; + } + + // }}} +} + +// {{{ md5_file() utility function +if (!function_exists('md5_file')) { + function md5_file($file) { + if (!$fd = @fopen($file, 'r')) { + return false; + } + $md5 = md5(fread($fd, filesize($file))); + fclose($fd); + return $md5; + } +} +// }}} + +?> diff --git a/pear/PEAR/Registry.php b/pear/PEAR/Registry.php new file mode 100644 index 000000000..2fda6ae59 --- /dev/null +++ b/pear/PEAR/Registry.php @@ -0,0 +1,538 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Stig Bakken <ssb@php.net> | +// | Tomas V.V.Cox <cox@idecnet.com> | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: Registry.php,v 1.50.4.2 2005/03/28 16:46:06 cellog Exp $ + +/* +TODO: + - Transform into singleton() + - Add application level lock (avoid change the registry from the cmdline + while using the GTK interface, for ex.) +*/ +require_once "System.php"; +require_once "PEAR.php"; + +define('PEAR_REGISTRY_ERROR_LOCK', -2); +define('PEAR_REGISTRY_ERROR_FORMAT', -3); +define('PEAR_REGISTRY_ERROR_FILE', -4); + +/** + * Administration class used to maintain the installed package database. + */ +class PEAR_Registry extends PEAR +{ + // {{{ properties + + /** Directory where registry files are stored. + * @var string + */ + var $statedir = ''; + + /** File where the file map is stored + * @var string + */ + var $filemap = ''; + + /** Name of file used for locking the registry + * @var string + */ + var $lockfile = ''; + + /** File descriptor used during locking + * @var resource + */ + var $lock_fp = null; + + /** Mode used during locking + * @var int + */ + var $lock_mode = 0; // XXX UNUSED + + /** Cache of package information. Structure: + * array( + * 'package' => array('id' => ... ), + * ... ) + * @var array + */ + var $pkginfo_cache = array(); + + /** Cache of file map. Structure: + * array( '/path/to/file' => 'package', ... ) + * @var array + */ + var $filemap_cache = array(); + + // }}} + + // {{{ constructor + + /** + * PEAR_Registry constructor. + * + * @param string (optional) PEAR install directory (for .php files) + * + * @access public + */ + function PEAR_Registry($pear_install_dir = PEAR_INSTALL_DIR) + { + parent::PEAR(); + $ds = DIRECTORY_SEPARATOR; + $this->install_dir = $pear_install_dir; + $this->statedir = $pear_install_dir.$ds.'.registry'; + $this->filemap = $pear_install_dir.$ds.'.filemap'; + $this->lockfile = $pear_install_dir.$ds.'.lock'; + + // XXX Compatibility code should be removed in the future + // rename all registry files if any to lowercase + if (!OS_WINDOWS && $handle = @opendir($this->statedir)) { + $dest = $this->statedir . DIRECTORY_SEPARATOR; + while (false !== ($file = readdir($handle))) { + if (preg_match('/^.*[A-Z].*\.reg$/', $file)) { + rename($dest . $file, $dest . strtolower($file)); + } + } + closedir($handle); + } + if (!file_exists($this->filemap)) { + $this->rebuildFileMap(); + } + } + + // }}} + // {{{ destructor + + /** + * PEAR_Registry destructor. Makes sure no locks are forgotten. + * + * @access private + */ + function _PEAR_Registry() + { + parent::_PEAR(); + if (is_resource($this->lock_fp)) { + $this->_unlock(); + } + } + + // }}} + + // {{{ _assertStateDir() + + /** + * Make sure the directory where we keep registry files exists. + * + * @return bool TRUE if directory exists, FALSE if it could not be + * created + * + * @access private + */ + function _assertStateDir() + { + if (!@is_dir($this->statedir)) { + if (!System::mkdir(array('-p', $this->statedir))) { + return $this->raiseError("could not create directory '{$this->statedir}'"); + } + } + return true; + } + + // }}} + // {{{ _packageFileName() + + /** + * Get the name of the file where data for a given package is stored. + * + * @param string package name + * + * @return string registry file name + * + * @access public + */ + function _packageFileName($package) + { + return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg'; + } + + // }}} + // {{{ _openPackageFile() + + function _openPackageFile($package, $mode) + { + $this->_assertStateDir(); + $file = $this->_packageFileName($package); + $fp = @fopen($file, $mode); + if (!$fp) { + return null; + } + return $fp; + } + + // }}} + // {{{ _closePackageFile() + + function _closePackageFile($fp) + { + fclose($fp); + } + + // }}} + // {{{ rebuildFileMap() + + function rebuildFileMap() + { + $packages = $this->listPackages(); + $files = array(); + foreach ($packages as $package) { + $version = $this->packageInfo($package, 'version'); + $filelist = $this->packageInfo($package, 'filelist'); + if (!is_array($filelist)) { + continue; + } + foreach ($filelist as $name => $attrs) { + if (isset($attrs['role']) && $attrs['role'] != 'php') { + continue; + } + if (isset($attrs['baseinstalldir'])) { + $file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name; + } else { + $file = $name; + } + $file = preg_replace(',^/+,', '', $file); + $files[$file] = $package; + } + } + $this->_assertStateDir(); + $fp = @fopen($this->filemap, 'wb'); + if (!$fp) { + return false; + } + $this->filemap_cache = $files; + fwrite($fp, serialize($files)); + fclose($fp); + return true; + } + + // }}} + // {{{ readFileMap() + + function readFileMap() + { + $fp = @fopen($this->filemap, 'r'); + if (!$fp) { + return $this->raiseError('PEAR_Registry: could not open filemap', PEAR_REGISTRY_ERROR_FILE, null, null, $php_errormsg); + } + $fsize = filesize($this->filemap); + $rt = get_magic_quotes_runtime(); + set_magic_quotes_runtime(0); + $data = fread($fp, $fsize); + set_magic_quotes_runtime($rt); + fclose($fp); + $tmp = unserialize($data); + if (!$tmp && $fsize > 7) { + return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data); + } + $this->filemap_cache = $tmp; + return true; + } + + // }}} + // {{{ _lock() + + /** + * Lock the registry. + * + * @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN. + * See flock manual for more information. + * + * @return bool TRUE on success, FALSE if locking failed, or a + * PEAR error if some other error occurs (such as the + * lock file not being writable). + * + * @access private + */ + function _lock($mode = LOCK_EX) + { + if (!eregi('Windows 9', php_uname())) { + if ($mode != LOCK_UN && is_resource($this->lock_fp)) { + // XXX does not check type of lock (LOCK_SH/LOCK_EX) + return true; + } + if (PEAR::isError($err = $this->_assertStateDir())) { + return $err; + } + $open_mode = 'w'; + // XXX People reported problems with LOCK_SH and 'w' + if ($mode === LOCK_SH || $mode === LOCK_UN) { + if (@!is_file($this->lockfile)) { + touch($this->lockfile); + } + $open_mode = 'r'; + } + + if (!is_resource($this->lock_fp)) { + $this->lock_fp = @fopen($this->lockfile, $open_mode); + } + + if (!is_resource($this->lock_fp)) { + return $this->raiseError("could not create lock file" . + (isset($php_errormsg) ? ": " . $php_errormsg : "")); + } + if (!(int)flock($this->lock_fp, $mode)) { + switch ($mode) { + case LOCK_SH: $str = 'shared'; break; + case LOCK_EX: $str = 'exclusive'; break; + case LOCK_UN: $str = 'unlock'; break; + default: $str = 'unknown'; break; + } + return $this->raiseError("could not acquire $str lock ($this->lockfile)", + PEAR_REGISTRY_ERROR_LOCK); + } + } + return true; + } + + // }}} + // {{{ _unlock() + + function _unlock() + { + $ret = $this->_lock(LOCK_UN); + if (is_resource($this->lock_fp)) { + fclose($this->lock_fp); + } + $this->lock_fp = null; + return $ret; + } + + // }}} + // {{{ _packageExists() + + function _packageExists($package) + { + return file_exists($this->_packageFileName($package)); + } + + // }}} + // {{{ _packageInfo() + + function _packageInfo($package = null, $key = null) + { + if ($package === null) { + return array_map(array($this, '_packageInfo'), + $this->_listPackages()); + } + $fp = $this->_openPackageFile($package, 'r'); + if ($fp === null) { + return null; + } + $rt = get_magic_quotes_runtime(); + set_magic_quotes_runtime(0); + $data = fread($fp, filesize($this->_packageFileName($package))); + set_magic_quotes_runtime($rt); + $this->_closePackageFile($fp); + $data = unserialize($data); + if ($key === null) { + return $data; + } + if (isset($data[$key])) { + return $data[$key]; + } + return null; + } + + // }}} + // {{{ _listPackages() + + function _listPackages() + { + $pkglist = array(); + $dp = @opendir($this->statedir); + if (!$dp) { + return $pkglist; + } + while ($ent = readdir($dp)) { + if ($ent{0} == '.' || substr($ent, -4) != '.reg') { + continue; + } + $pkglist[] = substr($ent, 0, -4); + } + return $pkglist; + } + + // }}} + + // {{{ packageExists() + + function packageExists($package) + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $ret = $this->_packageExists($package); + $this->_unlock(); + return $ret; + } + + // }}} + // {{{ packageInfo() + + function packageInfo($package = null, $key = null) + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $ret = $this->_packageInfo($package, $key); + $this->_unlock(); + return $ret; + } + + // }}} + // {{{ listPackages() + + function listPackages() + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $ret = $this->_listPackages(); + $this->_unlock(); + return $ret; + } + + // }}} + // {{{ addPackage() + + function addPackage($package, $info) + { + if ($this->packageExists($package)) { + return false; + } + if (PEAR::isError($e = $this->_lock(LOCK_EX))) { + return $e; + } + $fp = $this->_openPackageFile($package, 'wb'); + if ($fp === null) { + $this->_unlock(); + return false; + } + $info['_lastmodified'] = time(); + fwrite($fp, serialize($info)); + $this->_closePackageFile($fp); + $this->_unlock(); + return true; + } + + // }}} + // {{{ deletePackage() + + function deletePackage($package) + { + if (PEAR::isError($e = $this->_lock(LOCK_EX))) { + return $e; + } + $file = $this->_packageFileName($package); + $ret = @unlink($file); + $this->rebuildFileMap(); + $this->_unlock(); + return $ret; + } + + // }}} + // {{{ updatePackage() + + function updatePackage($package, $info, $merge = true) + { + $oldinfo = $this->packageInfo($package); + if (empty($oldinfo)) { + return false; + } + if (PEAR::isError($e = $this->_lock(LOCK_EX))) { + return $e; + } + $fp = $this->_openPackageFile($package, 'w'); + if ($fp === null) { + $this->_unlock(); + return false; + } + $info['_lastmodified'] = time(); + if ($merge) { + fwrite($fp, serialize(array_merge($oldinfo, $info))); + } else { + fwrite($fp, serialize($info)); + } + $this->_closePackageFile($fp); + if (isset($info['filelist'])) { + $this->rebuildFileMap(); + } + $this->_unlock(); + return true; + } + + // }}} + // {{{ checkFileMap() + + /** + * Test whether a file belongs to a package. + * + * @param string $path file path, absolute or relative to the pear + * install dir + * + * @return string which package the file belongs to, or an empty + * string if the file does not belong to an installed package + * + * @access public + */ + function checkFileMap($path) + { + if (is_array($path)) { + static $notempty; + if (empty($notempty)) { + $notempty = create_function('$a','return !empty($a);'); + } + $pkgs = array(); + foreach ($path as $name => $attrs) { + if (is_array($attrs) && isset($attrs['baseinstalldir'])) { + $name = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name; + } + $pkgs[$name] = $this->checkFileMap($name); + } + return array_filter($pkgs, $notempty); + } + if (empty($this->filemap_cache) && PEAR::isError($this->readFileMap())) { + return $err; + } + if (isset($this->filemap_cache[$path])) { + return $this->filemap_cache[$path]; + } + $l = strlen($this->install_dir); + if (substr($path, 0, $l) == $this->install_dir) { + $path = preg_replace('!^'.DIRECTORY_SEPARATOR.'+!', '', substr($path, $l)); + } + if (isset($this->filemap_cache[$path])) { + return $this->filemap_cache[$path]; + } + return ''; + } + + // }}} + +} + +?> diff --git a/pear/PEAR/Remote.php b/pear/PEAR/Remote.php new file mode 100644 index 000000000..7b1e314f9 --- /dev/null +++ b/pear/PEAR/Remote.php @@ -0,0 +1,394 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Author: Stig Bakken <ssb@php.net> | +// +----------------------------------------------------------------------+ +// +// $Id: Remote.php,v 1.50 2004/06/08 18:03:46 cellog Exp $ + +require_once 'PEAR.php'; +require_once 'PEAR/Config.php'; + +/** + * This is a class for doing remote operations against the central + * PEAR database. + * + * @nodep XML_RPC_Value + * @nodep XML_RPC_Message + * @nodep XML_RPC_Client + */ +class PEAR_Remote extends PEAR +{ + // {{{ properties + + var $config = null; + var $cache = null; + + // }}} + + // {{{ PEAR_Remote(config_object) + + function PEAR_Remote(&$config) + { + $this->PEAR(); + $this->config = &$config; + } + + // }}} + + // {{{ getCache() + + + function getCache($args) + { + $id = md5(serialize($args)); + $cachedir = $this->config->get('cache_dir'); + $filename = $cachedir . DIRECTORY_SEPARATOR . 'xmlrpc_cache_' . $id; + if (!file_exists($filename)) { + return null; + }; + + $fp = fopen($filename, 'rb'); + if (!$fp) { + return null; + } + $content = fread($fp, filesize($filename)); + fclose($fp); + $result = array( + 'age' => time() - filemtime($filename), + 'lastChange' => filemtime($filename), + 'content' => unserialize($content), + ); + return $result; + } + + // }}} + + // {{{ saveCache() + + function saveCache($args, $data) + { + $id = md5(serialize($args)); + $cachedir = $this->config->get('cache_dir'); + if (!file_exists($cachedir)) { + System::mkdir(array('-p', $cachedir)); + } + $filename = $cachedir.'/xmlrpc_cache_'.$id; + + $fp = @fopen($filename, "wb"); + if ($fp) { + fwrite($fp, serialize($data)); + fclose($fp); + }; + } + + // }}} + + // {{{ call(method, [args...]) + + function call($method) + { + $_args = $args = func_get_args(); + + $this->cache = $this->getCache($args); + $cachettl = $this->config->get('cache_ttl'); + // If cache is newer than $cachettl seconds, we use the cache! + if ($this->cache !== null && $this->cache['age'] < $cachettl) { + return $this->cache['content']; + }; + + if (extension_loaded("xmlrpc")) { + $result = call_user_func_array(array(&$this, 'call_epi'), $args); + if (!PEAR::isError($result)) { + $this->saveCache($_args, $result); + }; + return $result; + } + if (!@include_once("XML/RPC.php")) { + return $this->raiseError("For this remote PEAR operation you need to install the XML_RPC package"); + } + array_shift($args); + $server_host = $this->config->get('master_server'); + $username = $this->config->get('username'); + $password = $this->config->get('password'); + $eargs = array(); + foreach($args as $arg) $eargs[] = $this->_encode($arg); + $f = new XML_RPC_Message($method, $eargs); + if ($this->cache !== null) { + $maxAge = '?maxAge='.$this->cache['lastChange']; + } else { + $maxAge = ''; + }; + $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; + if ($proxy = parse_url($this->config->get('http_proxy'))) { + $proxy_host = @$proxy['host']; + $proxy_port = @$proxy['port']; + $proxy_user = @urldecode(@$proxy['user']); + $proxy_pass = @urldecode(@$proxy['pass']); + } + $c = new XML_RPC_Client('/xmlrpc.php'.$maxAge, $server_host, 80, $proxy_host, $proxy_port, $proxy_user, $proxy_pass); + if ($username && $password) { + $c->setCredentials($username, $password); + } + if ($this->config->get('verbose') >= 3) { + $c->setDebug(1); + } + $r = $c->send($f); + if (!$r) { + return $this->raiseError("XML_RPC send failed"); + } + $v = $r->value(); + if ($e = $r->faultCode()) { + if ($e == $GLOBALS['XML_RPC_err']['http_error'] && strstr($r->faultString(), '304 Not Modified') !== false) { + return $this->cache['content']; + } + return $this->raiseError($r->faultString(), $e); + } + + $result = XML_RPC_decode($v); + $this->saveCache($_args, $result); + return $result; + } + + // }}} + + // {{{ call_epi(method, [args...]) + + function call_epi($method) + { + do { + if (extension_loaded("xmlrpc")) { + break; + } + if (OS_WINDOWS) { + $ext = 'dll'; + } elseif (PHP_OS == 'HP-UX') { + $ext = 'sl'; + } elseif (PHP_OS == 'AIX') { + $ext = 'a'; + } else { + $ext = 'so'; + } + $ext = OS_WINDOWS ? 'dll' : 'so'; + @dl("xmlrpc-epi.$ext"); + if (extension_loaded("xmlrpc")) { + break; + } + @dl("xmlrpc.$ext"); + if (extension_loaded("xmlrpc")) { + break; + } + return $this->raiseError("unable to load xmlrpc extension"); + } while (false); + $params = func_get_args(); + array_shift($params); + $method = str_replace("_", ".", $method); + $request = xmlrpc_encode_request($method, $params); + $server_host = $this->config->get("master_server"); + if (empty($server_host)) { + return $this->raiseError("PEAR_Remote::call: no master_server configured"); + } + $server_port = 80; + if ($http_proxy = $this->config->get('http_proxy')) { + $proxy = parse_url($http_proxy); + $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; + $proxy_host = @$proxy['host']; + $proxy_port = @$proxy['port']; + $proxy_user = @urldecode(@$proxy['user']); + $proxy_pass = @urldecode(@$proxy['pass']); + $fp = @fsockopen($proxy_host, $proxy_port); + $use_proxy = true; + } else { + $use_proxy = false; + $fp = @fsockopen($server_host, $server_port); + } + if (!$fp && $http_proxy) { + return $this->raiseError("PEAR_Remote::call: fsockopen(`$proxy_host', $proxy_port) failed"); + } elseif (!$fp) { + return $this->raiseError("PEAR_Remote::call: fsockopen(`$server_host', $server_port) failed"); + } + $len = strlen($request); + $req_headers = "Host: $server_host:$server_port\r\n" . + "Content-type: text/xml\r\n" . + "Content-length: $len\r\n"; + $username = $this->config->get('username'); + $password = $this->config->get('password'); + if ($username && $password) { + $req_headers .= "Cookie: PEAR_USER=$username; PEAR_PW=$password\r\n"; + $tmp = base64_encode("$username:$password"); + $req_headers .= "Authorization: Basic $tmp\r\n"; + } + if ($this->cache !== null) { + $maxAge = '?maxAge='.$this->cache['lastChange']; + } else { + $maxAge = ''; + }; + + if ($use_proxy && $proxy_host != '' && $proxy_user != '') { + $req_headers .= 'Proxy-Authorization: Basic ' + .base64_encode($proxy_user.':'.$proxy_pass) + ."\r\n"; + } + + if ($this->config->get('verbose') > 3) { + print "XMLRPC REQUEST HEADERS:\n"; + var_dump($req_headers); + print "XMLRPC REQUEST BODY:\n"; + var_dump($request); + } + + if ($use_proxy && $proxy_host != '') { + $post_string = "POST http://".$server_host; + if ($proxy_port > '') { + $post_string .= ':'.$server_port; + } + } else { + $post_string = "POST "; + } + + fwrite($fp, ($post_string."/xmlrpc.php$maxAge HTTP/1.0\r\n$req_headers\r\n$request")); + $response = ''; + $line1 = fgets($fp, 2048); + if (!preg_match('!^HTTP/[0-9\.]+ (\d+) (.*)!', $line1, $matches)) { + return $this->raiseError("PEAR_Remote: invalid HTTP response from XML-RPC server"); + } + switch ($matches[1]) { + case "200": // OK + break; + case "304": // Not Modified + return $this->cache['content']; + case "401": // Unauthorized + if ($username && $password) { + return $this->raiseError("PEAR_Remote: authorization failed", 401); + } else { + return $this->raiseError("PEAR_Remote: authorization required, please log in first", 401); + } + default: + return $this->raiseError("PEAR_Remote: unexpected HTTP response", (int)$matches[1], null, null, "$matches[1] $matches[2]"); + } + while (trim(fgets($fp, 2048)) != ''); // skip rest of headers + while ($chunk = fread($fp, 10240)) { + $response .= $chunk; + } + fclose($fp); + if ($this->config->get('verbose') > 3) { + print "XMLRPC RESPONSE:\n"; + var_dump($response); + } + $ret = xmlrpc_decode($response); + if (is_array($ret) && isset($ret['__PEAR_TYPE__'])) { + if ($ret['__PEAR_TYPE__'] == 'error') { + if (isset($ret['__PEAR_CLASS__'])) { + $class = $ret['__PEAR_CLASS__']; + } else { + $class = "PEAR_Error"; + } + if ($ret['code'] === '') $ret['code'] = null; + if ($ret['message'] === '') $ret['message'] = null; + if ($ret['userinfo'] === '') $ret['userinfo'] = null; + if (strtolower($class) == 'db_error') { + $ret = $this->raiseError(PEAR::errorMessage($ret['code']), + $ret['code'], null, null, + $ret['userinfo']); + } else { + $ret = $this->raiseError($ret['message'], $ret['code'], + null, null, $ret['userinfo']); + } + } + } elseif (is_array($ret) && sizeof($ret) == 1 && isset($ret[0]) + && is_array($ret[0]) && + !empty($ret[0]['faultString']) && + !empty($ret[0]['faultCode'])) { + extract($ret[0]); + $faultString = "XML-RPC Server Fault: " . + str_replace("\n", " ", $faultString); + return $this->raiseError($faultString, $faultCode); + } + return $ret; + } + + // }}} + + // {{{ _encode + + // a slightly extended version of XML_RPC_encode + function _encode($php_val) + { + global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double; + global $XML_RPC_String, $XML_RPC_Array, $XML_RPC_Struct; + + $type = gettype($php_val); + $xmlrpcval = new XML_RPC_Value; + + switch($type) { + case "array": + reset($php_val); + $firstkey = key($php_val); + end($php_val); + $lastkey = key($php_val); + if ($firstkey === 0 && is_int($lastkey) && + ($lastkey + 1) == count($php_val)) { + $is_continuous = true; + reset($php_val); + $size = count($php_val); + for ($expect = 0; $expect < $size; $expect++, next($php_val)) { + if (key($php_val) !== $expect) { + $is_continuous = false; + break; + } + } + if ($is_continuous) { + reset($php_val); + $arr = array(); + while (list($k, $v) = each($php_val)) { + $arr[$k] = $this->_encode($v); + } + $xmlrpcval->addArray($arr); + break; + } + } + // fall though if not numerical and continuous + case "object": + $arr = array(); + while (list($k, $v) = each($php_val)) { + $arr[$k] = $this->_encode($v); + } + $xmlrpcval->addStruct($arr); + break; + case "integer": + $xmlrpcval->addScalar($php_val, $XML_RPC_Int); + break; + case "double": + $xmlrpcval->addScalar($php_val, $XML_RPC_Double); + break; + case "string": + case "NULL": + $xmlrpcval->addScalar($php_val, $XML_RPC_String); + break; + case "boolean": + $xmlrpcval->addScalar($php_val, $XML_RPC_Boolean); + break; + case "unknown type": + default: + return null; + } + return $xmlrpcval; + } + + // }}} + +} + +?> diff --git a/pear/PEAR/RunTest.php b/pear/PEAR/RunTest.php new file mode 100644 index 000000000..b5873a7b6 --- /dev/null +++ b/pear/PEAR/RunTest.php @@ -0,0 +1,363 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Authors: Tomas V.V.Cox <cox@idecnet.com> | +// | Greg Beaver <cellog@php.net> | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: RunTest.php,v 1.1.4.2 2005/04/01 22:02:16 cellog Exp $ +// + +/** + * Simplified version of PHP's test suite + * -- EXPERIMENTAL -- + + Try it with: + + $ php -r 'include "../PEAR/RunTest.php"; $t=new PEAR_RunTest; $o=$t->run("./pear_system.phpt");print_r($o);' + + +TODO: + +Actually finish the development and testing + + */ + +require_once 'PEAR.php'; +require_once 'PEAR/Config.php'; + +define('DETAILED', 1); +putenv("PHP_PEAR_RUNTESTS=1"); + +class PEAR_RunTest +{ + var $_logger; + + /** + * An object that supports the PEAR_Common->log() signature, or null + * @param PEAR_Common|null + */ + function PEAR_RunTest($logger = null) + { + $this->_logger = $logger; + } + + // + // Run an individual test case. + // + + function run($file, $ini_settings = '') + { + $cwd = getcwd(); + $conf = &PEAR_Config::singleton(); + $php = $conf->get('php_bin'); + //var_dump($php);exit; + global $log_format, $info_params, $ini_overwrites; + + $info_params = ''; + $log_format = 'LEOD'; + + // Load the sections of the test file. + $section_text = array( + 'TEST' => '(unnamed test)', + 'SKIPIF' => '', + 'GET' => '', + 'ARGS' => '', + ); + + 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 (ereg('^--([A-Z]+)--',$line,$r)) { + $section = $r[1]; + $section_text[$section] = ''; + continue; + } + + // Add to the section text. + $section_text[$section] .= $line; + } + fclose($fp); + + $shortname = str_replace($cwd.'/', '', $file); + $tested = trim($section_text['TEST'])." [$shortname]"; + + $tmp = realpath(dirname($file)); + $tmp_skipif = $tmp . uniqid('/phpt.'); + $tmp_file = ereg_replace('\.phpt$','.php',$file); + $tmp_post = $tmp . uniqid('/phpt.'); + + @unlink($tmp_skipif); + @unlink($tmp_file); + @unlink($tmp_post); + + // unlink old test results + @unlink(ereg_replace('\.phpt$','.diff',$file)); + @unlink(ereg_replace('\.phpt$','.log',$file)); + @unlink(ereg_replace('\.phpt$','.exp',$file)); + @unlink(ereg_replace('\.phpt$','.out',$file)); + + // Check if test should be skipped. + $info = ''; + $warn = false; + if (array_key_exists('SKIPIF', $section_text)) { + if (trim($section_text['SKIPIF'])) { + $this->save_text($tmp_skipif, $section_text['SKIPIF']); + //$extra = substr(PHP_OS, 0, 3) !== "WIN" ? + // "unset REQUEST_METHOD;": ""; + + //$output = `$extra $php $info_params -f $tmp_skipif`; + $output = `$php $info_params -f $tmp_skipif`; + unlink($tmp_skipif); + if (eregi("^skip", trim($output))) { + $skipreason = "SKIP $tested"; + $reason = (eregi("^skip[[:space:]]*(.+)\$", trim($output))) ? eregi_replace("^skip[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE; + if ($reason) { + $skipreason .= " (reason: $reason)"; + } + $this->_logger->log(0, $skipreason); + if (isset($old_php)) { + $php = $old_php; + } + return 'SKIPPED'; + } + if (eregi("^info", trim($output))) { + $reason = (ereg("^info[[:space:]]*(.+)\$", trim($output))) ? ereg_replace("^info[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE; + if ($reason) { + $info = " (info: $reason)"; + } + } + if (eregi("^warn", trim($output))) { + $reason = (ereg("^warn[[:space:]]*(.+)\$", trim($output))) ? ereg_replace("^warn[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE; + if ($reason) { + $warn = true; /* only if there is a reason */ + $info = " (warn: $reason)"; + } + } + } + } + + // We've satisfied the preconditions - run the test! + $this->save_text($tmp_file,$section_text['FILE']); + + $args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : ''; + + $cmd = "$php$ini_settings -f $tmp_file$args 2>&1"; + if (isset($this->_logger)) { + $this->_logger->log(2, 'Running command "' . $cmd . '"'); + } + + $savedir = getcwd(); // in case the test moves us around + if (isset($section_text['RETURNS'])) { + ob_start(); + system($cmd, $return_value); + $out = ob_get_contents(); + ob_end_clean(); + @unlink($tmp_post); + $section_text['RETURNS'] = (int) trim($section_text['RETURNS']); + $returnfail = ($return_value != $section_text['RETURNS']); + } else { + $out = `$cmd`; + $returnfail = false; + } + chdir($savedir); + // Does the output match what is expected? + $output = trim($out); + $output = preg_replace('/\r\n/', "\n", $output); + + 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)) { + @unlink($tmp_file); + $this->_logger->log(0, "PASS $tested$info"); + if (isset($old_php)) { + $php = $old_php; + } + return 'PASSED'; + } + + } else { + $wanted = trim($section_text['EXPECT']); + $wanted = preg_replace('/\r\n/',"\n",$wanted); + // compare and leave on success + $ok = (0 == strcmp($output,$wanted)); + if (!$returnfail && $ok) { + @unlink($tmp_file); + $this->_logger->log(0, "PASS $tested$info"); + if (isset($old_php)) { + $php = $old_php; + } + return 'PASSED'; + } + } + + // Test failed so we need to report details. + if ($warn) { + $this->_logger->log(0, "WARN $tested$info"); + } else { + $this->_logger->log(0, "FAIL $tested$info"); + } + + if (isset($section_text['RETURNS'])) { + $GLOBALS['__PHP_FAILED_TESTS__'][] = array( + 'name' => $file, + 'test_name' => $tested, + 'output' => ereg_replace('\.phpt$','.log', $file), + 'diff' => ereg_replace('\.phpt$','.diff', $file), + 'info' => $info, + 'return' => $return_value + ); + } else { + $GLOBALS['__PHP_FAILED_TESTS__'][] = array( + 'name' => $file, + 'test_name' => $tested, + 'output' => ereg_replace('\.phpt$','.log', $file), + 'diff' => ereg_replace('\.phpt$','.diff', $file), + 'info' => $info, + ); + } + + // write .exp + if (strpos($log_format,'E') !== FALSE) { + $logname = ereg_replace('\.phpt$','.exp',$file); + if (!$log = fopen($logname,'w')) { + return PEAR::raiseError("Cannot create test log - $logname"); + } + fwrite($log,$wanted); + fclose($log); + } + + // write .out + if (strpos($log_format,'O') !== FALSE) { + $logname = ereg_replace('\.phpt$','.out',$file); + if (!$log = fopen($logname,'w')) { + return PEAR::raiseError("Cannot create test log - $logname"); + } + fwrite($log,$output); + fclose($log); + } + + // write .diff + if (strpos($log_format,'D') !== FALSE) { + $logname = ereg_replace('\.phpt$','.diff',$file); + if (!$log = fopen($logname,'w')) { + return PEAR::raiseError("Cannot create test log - $logname"); + } + fwrite($log, $this->generate_diff($wanted, $output, + isset($section_text['RETURNS']) ? array(trim($section_text['RETURNS']), + $return_value) : null)); + fclose($log); + } + + // write .log + if (strpos($log_format,'L') !== FALSE) { + $logname = ereg_replace('\.phpt$','.log',$file); + if (!$log = fopen($logname,'w')) { + return PEAR::raiseError("Cannot create test log - $logname"); + } + fwrite($log," +---- EXPECTED OUTPUT +$wanted +---- ACTUAL OUTPUT +$output +---- FAILED +"); + if ($returnfail) { + fwrite($log," +---- EXPECTED RETURN +$section_text[RETURNS] +---- ACTUAL RETURN +$return_value +"); + } + fclose($log); + //error_report($file,$logname,$tested); + } + + if (isset($old_php)) { + $php = $old_php; + } + + return $warn ? 'WARNED' : 'FAILED'; + } + + function generate_diff($wanted, $output, $return_value) + { + $w = explode("\n", $wanted); + $o = explode("\n", $output); + $w1 = array_diff_assoc($w,$o); + $o1 = array_diff_assoc($o,$w); + $w2 = array(); + $o2 = array(); + foreach($w1 as $idx => $val) $w2[sprintf("%03d<",$idx)] = sprintf("%03d- ", $idx+1).$val; + foreach($o1 as $idx => $val) $o2[sprintf("%03d>",$idx)] = sprintf("%03d+ ", $idx+1).$val; + $diff = array_merge($w2, $o2); + ksort($diff); + if ($return_value) { + $extra = "##EXPECTED: $return_value[0]\r\n##RETURNED: $return_value[1]"; + } else { + $extra = ''; + } + 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 +}}} +"; + } + +} +?>
\ No newline at end of file diff --git a/pear/README b/pear/README new file mode 100644 index 000000000..c953c26b1 --- /dev/null +++ b/pear/README @@ -0,0 +1,18 @@ + PEAR - PHP Extension and Application Repository + =============================================== + Dedicated to Malin Bakken, born 1999-11-21 + +WHAT IS PEAR? + +PEAR is a code repository for PHP extensions and PHP library code +similar to TeX's CTAN and Perl's CPAN. + +The intention behind PEAR is to provide a means for library code +authors to organize their code in a defined way shared by other +developers, and to give the PHP community a single source for such +code. + + +DOCUMENTATION + +Documentation for PEAR can be found at http://pear.php.net/manual/. diff --git a/pear/System.php b/pear/System.php new file mode 100644 index 000000000..dc3acee97 --- /dev/null +++ b/pear/System.php @@ -0,0 +1,540 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Authors: Tomas V.V.Cox <cox@idecnet.com> | +// +----------------------------------------------------------------------+ +// +// $Id: System.php,v 1.36 2004/06/15 16:33:46 pajoye Exp $ +// + +require_once 'PEAR.php'; +require_once 'Console/Getopt.php'; + +$GLOBALS['_System_temp_files'] = array(); + +/** +* System offers cross plattform compatible system functions +* +* Static functions for different operations. Should work under +* Unix and Windows. The names and usage has been taken from its respectively +* GNU commands. The functions will return (bool) false on error and will +* trigger the error with the PHP trigger_error() function (you can silence +* the error by prefixing a '@' sign after the function call). +* +* Documentation on this class you can find in: +* http://pear.php.net/manual/ +* +* Example usage: +* if (!@System::rm('-r file1 dir1')) { +* print "could not delete file1 or dir1"; +* } +* +* In case you need to to pass file names with spaces, +* pass the params as an array: +* +* System::rm(array('-r', $file1, $dir1)); +* +* @package System +* @author Tomas V.V.Cox <cox@idecnet.com> +* @version $Revision: 1.36 $ +* @access public +* @see http://pear.php.net/manual/ +*/ +class System +{ + /** + * returns the commandline arguments of a function + * + * @param string $argv the commandline + * @param string $short_options the allowed option short-tags + * @param string $long_options the allowed option long-tags + * @return array the given options and there values + * @access private + */ + function _parseArgs($argv, $short_options, $long_options = null) + { + if (!is_array($argv) && $argv !== null) { + $argv = preg_split('/\s+/', $argv); + } + return Console_Getopt::getopt2($argv, $short_options); + } + + /** + * Output errors with PHP trigger_error(). You can silence the errors + * with prefixing a "@" sign to the function call: @System::mkdir(..); + * + * @param mixed $error a PEAR error or a string with the error message + * @return bool false + * @access private + */ + function raiseError($error) + { + if (PEAR::isError($error)) { + $error = $error->getMessage(); + } + trigger_error($error, E_USER_WARNING); + return false; + } + + /** + * Creates a nested array representing the structure of a directory + * + * System::_dirToStruct('dir1', 0) => + * Array + * ( + * [dirs] => Array + * ( + * [0] => dir1 + * ) + * + * [files] => Array + * ( + * [0] => dir1/file2 + * [1] => dir1/file3 + * ) + * ) + * @param string $sPath Name of the directory + * @param integer $maxinst max. deep of the lookup + * @param integer $aktinst starting deep of the lookup + * @return array the structure of the dir + * @access private + */ + + function _dirToStruct($sPath, $maxinst, $aktinst = 0) + { + $struct = array('dirs' => array(), 'files' => array()); + if (($dir = @opendir($sPath)) === false) { + System::raiseError("Could not open dir $sPath"); + return $struct; // XXX could not open error + } + $struct['dirs'][] = $sPath; // XXX don't add if '.' or '..' ? + $list = array(); + while ($file = readdir($dir)) { + if ($file != '.' && $file != '..') { + $list[] = $file; + } + } + closedir($dir); + sort($list); + if ($aktinst < $maxinst || $maxinst == 0) { + foreach($list as $val) { + $path = $sPath . DIRECTORY_SEPARATOR . $val; + if (is_dir($path)) { + $tmp = System::_dirToStruct($path, $maxinst, $aktinst+1); + $struct = array_merge_recursive($tmp, $struct); + } else { + $struct['files'][] = $path; + } + } + } + return $struct; + } + + /** + * Creates a nested array representing the structure of a directory and files + * + * @param array $files Array listing files and dirs + * @return array + * @see System::_dirToStruct() + */ + function _multipleToStruct($files) + { + $struct = array('dirs' => array(), 'files' => array()); + settype($files, 'array'); + foreach ($files as $file) { + if (is_dir($file)) { + $tmp = System::_dirToStruct($file, 0); + $struct = array_merge_recursive($tmp, $struct); + } else { + $struct['files'][] = $file; + } + } + return $struct; + } + + /** + * The rm command for removing files. + * Supports multiple files and dirs and also recursive deletes + * + * @param string $args the arguments for rm + * @return mixed PEAR_Error or true for success + * @access public + */ + function rm($args) + { + $opts = System::_parseArgs($args, 'rf'); // "f" do nothing but like it :-) + if (PEAR::isError($opts)) { + return System::raiseError($opts); + } + foreach($opts[0] as $opt) { + if ($opt[0] == 'r') { + $do_recursive = true; + } + } + $ret = true; + if (isset($do_recursive)) { + $struct = System::_multipleToStruct($opts[1]); + foreach($struct['files'] as $file) { + if (!@unlink($file)) { + $ret = false; + } + } + foreach($struct['dirs'] as $dir) { + if (!@rmdir($dir)) { + $ret = false; + } + } + } else { + foreach ($opts[1] as $file) { + $delete = (is_dir($file)) ? 'rmdir' : 'unlink'; + if (!@$delete($file)) { + $ret = false; + } + } + } + return $ret; + } + + /** + * Make directories. Note that we use call_user_func('mkdir') to avoid + * a problem with ZE2 calling System::mkDir instead of the native PHP func. + * + * @param string $args the name of the director(y|ies) to create + * @return bool True for success + * @access public + */ + function mkDir($args) + { + $opts = System::_parseArgs($args, 'pm:'); + if (PEAR::isError($opts)) { + return System::raiseError($opts); + } + $mode = 0777; // default mode + foreach($opts[0] as $opt) { + if ($opt[0] == 'p') { + $create_parents = true; + } elseif($opt[0] == 'm') { + // if the mode is clearly an octal number (starts with 0) + // convert it to decimal + if (strlen($opt[1]) && $opt[1]{0} == '0') { + $opt[1] = octdec($opt[1]); + } else { + // convert to int + $opt[1] += 0; + } + $mode = $opt[1]; + } + } + $ret = true; + if (isset($create_parents)) { + foreach($opts[1] as $dir) { + $dirstack = array(); + while (!@is_dir($dir) && $dir != DIRECTORY_SEPARATOR) { + array_unshift($dirstack, $dir); + $dir = dirname($dir); + } + while ($newdir = array_shift($dirstack)) { + if (!call_user_func('mkdir', $newdir, $mode)) { + $ret = false; + } + } + } + } else { + foreach($opts[1] as $dir) { + if (!@is_dir($dir) && !call_user_func('mkdir', $dir, $mode)) { + $ret = false; + } + } + } + return $ret; + } + + /** + * Concatenate files + * + * Usage: + * 1) $var = System::cat('sample.txt test.txt'); + * 2) System::cat('sample.txt test.txt > final.txt'); + * 3) System::cat('sample.txt test.txt >> final.txt'); + * + * Note: as the class use fopen, urls should work also (test that) + * + * @param string $args the arguments + * @return boolean true on success + * @access public + */ + function &cat($args) + { + $ret = null; + $files = array(); + if (!is_array($args)) { + $args = preg_split('/\s+/', $args); + } + for($i=0; $i < count($args); $i++) { + if ($args[$i] == '>') { + $mode = 'wb'; + $outputfile = $args[$i+1]; + break; + } elseif ($args[$i] == '>>') { + $mode = 'ab+'; + $outputfile = $args[$i+1]; + break; + } else { + $files[] = $args[$i]; + } + } + if (isset($mode)) { + if (!$outputfd = fopen($outputfile, $mode)) { + $err = System::raiseError("Could not open $outputfile"); + return $err; + } + $ret = true; + } + foreach ($files as $file) { + if (!$fd = fopen($file, 'r')) { + System::raiseError("Could not open $file"); + continue; + } + while ($cont = fread($fd, 2048)) { + if (isset($outputfd)) { + fwrite($outputfd, $cont); + } else { + $ret .= $cont; + } + } + fclose($fd); + } + if (@is_resource($outputfd)) { + fclose($outputfd); + } + return $ret; + } + + /** + * Creates temporary files or directories. This function will remove + * the created files when the scripts finish its execution. + * + * Usage: + * 1) $tempfile = System::mktemp("prefix"); + * 2) $tempdir = System::mktemp("-d prefix"); + * 3) $tempfile = System::mktemp(); + * 4) $tempfile = System::mktemp("-t /var/tmp prefix"); + * + * prefix -> The string that will be prepended to the temp name + * (defaults to "tmp"). + * -d -> A temporary dir will be created instead of a file. + * -t -> The target dir where the temporary (file|dir) will be created. If + * this param is missing by default the env vars TMP on Windows or + * TMPDIR in Unix will be used. If these vars are also missing + * c:\windows\temp or /tmp will be used. + * + * @param string $args The arguments + * @return mixed the full path of the created (file|dir) or false + * @see System::tmpdir() + * @access public + */ + function mktemp($args = null) + { + static $first_time = true; + $opts = System::_parseArgs($args, 't:d'); + if (PEAR::isError($opts)) { + return System::raiseError($opts); + } + foreach($opts[0] as $opt) { + if($opt[0] == 'd') { + $tmp_is_dir = true; + } elseif($opt[0] == 't') { + $tmpdir = $opt[1]; + } + } + $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp'; + if (!isset($tmpdir)) { + $tmpdir = System::tmpdir(); + } + if (!System::mkDir("-p $tmpdir")) { + return false; + } + $tmp = tempnam($tmpdir, $prefix); + if (isset($tmp_is_dir)) { + unlink($tmp); // be careful possible race condition here + if (!call_user_func('mkdir', $tmp, 0700)) { + return System::raiseError("Unable to create temporary directory $tmpdir"); + } + } + $GLOBALS['_System_temp_files'][] = $tmp; + if ($first_time) { + PEAR::registerShutdownFunc(array('System', '_removeTmpFiles')); + $first_time = false; + } + return $tmp; + } + + /** + * Remove temporary files created my mkTemp. This function is executed + * at script shutdown time + * + * @access private + */ + function _removeTmpFiles() + { + if (count($GLOBALS['_System_temp_files'])) { + $delete = $GLOBALS['_System_temp_files']; + array_unshift($delete, '-r'); + System::rm($delete); + } + } + + /** + * Get the path of the temporal directory set in the system + * by looking in its environments variables. + * Note: php.ini-recommended removes the "E" from the variables_order setting, + * making unavaible the $_ENV array, that s why we do tests with _ENV + * + * @return string The temporal directory on the system + */ + function tmpdir() + { + if (OS_WINDOWS) { + if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) { + return $var; + } + if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) { + return $var; + } + if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) { + return $var; + } + return getenv('SystemRoot') . '\temp'; + } + if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) { + return $var; + } + return '/tmp'; + } + + /** + * The "which" command (show the full path of a command) + * + * @param string $program The command to search for + * @return mixed A string with the full path or false if not found + * @author Stig Bakken <ssb@php.net> + */ + function which($program, $fallback = false) + { + // is_executable() is not available on windows + if (OS_WINDOWS) { + $pear_is_executable = 'is_file'; + } else { + $pear_is_executable = 'is_executable'; + } + + // full path given + if (basename($program) != $program) { + return (@$pear_is_executable($program)) ? $program : $fallback; + } + + // XXX FIXME honor safe mode + $path_delim = OS_WINDOWS ? ';' : ':'; + $exe_suffixes = OS_WINDOWS ? array('.exe','.bat','.cmd','.com') : array(''); + $path_elements = explode($path_delim, getenv('PATH')); + foreach ($exe_suffixes as $suff) { + foreach ($path_elements as $dir) { + $file = $dir . DIRECTORY_SEPARATOR . $program . $suff; + if (@is_file($file) && @$pear_is_executable($file)) { + return $file; + } + } + } + return $fallback; + } + + /** + * The "find" command + * + * Usage: + * + * System::find($dir); + * System::find("$dir -type d"); + * System::find("$dir -type f"); + * System::find("$dir -name *.php"); + * System::find("$dir -name *.php -name *.htm*"); + * System::find("$dir -maxdepth 1"); + * + * Params implmented: + * $dir -> Start the search at this directory + * -type d -> return only directories + * -type f -> return only files + * -maxdepth <n> -> max depth of recursion + * -name <pattern> -> search pattern (bash style). Multiple -name param allowed + * + * @param mixed Either array or string with the command line + * @return array Array of found files + * + */ + function find($args) + { + if (!is_array($args)) { + $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); + } + $dir = array_shift($args); + $patterns = array(); + $depth = 0; + $do_files = $do_dirs = true; + for ($i = 0; $i < count($args); $i++) { + switch ($args[$i]) { + case '-type': + if (in_array($args[$i+1], array('d', 'f'))) { + if ($args[$i+1] == 'd') { + $do_files = false; + } else { + $do_dirs = false; + } + } + $i++; + break; + case '-name': + $patterns[] = "(" . preg_replace(array('/\./', '/\*/'), + array('\.', '.*'), + $args[$i+1]) + . ")"; + $i++; + break; + case '-maxdepth': + $depth = $args[$i+1]; + break; + } + } + $path = System::_dirToStruct($dir, $depth); + if ($do_files && $do_dirs) { + $files = array_merge($path['files'], $path['dirs']); + } elseif ($do_dirs) { + $files = $path['dirs']; + } else { + $files = $path['files']; + } + if (count($patterns)) { + $patterns = implode('|', $patterns); + $ret = array(); + for ($i = 0; $i < count($files); $i++) { + if (preg_match("#^$patterns\$#", $files[$i])) { + $ret[] = $files[$i]; + } + } + return $ret; + } + return $files; + } +} +?> diff --git a/pear/catalog b/pear/catalog new file mode 100644 index 000000000..6e0c69d40 --- /dev/null +++ b/pear/catalog @@ -0,0 +1 @@ +PUBLIC "-//PHP Group//DTD PEAR Package 1.0//EN//XML" "package.dtd" diff --git a/pear/docs/Archive_Tar.txt b/pear/docs/Archive_Tar.txt new file mode 100644 index 000000000..73bee0d78 --- /dev/null +++ b/pear/docs/Archive_Tar.txt @@ -0,0 +1,424 @@ +Documentation for class Archive_Tar +=================================== +Last update : 2001-08-15 + + + +Overview : +---------- + + The Archive_Tar class helps in creating and managing GNU TAR format + files compressed by GNU ZIP or not. + The class offers basic functions like creating an archive, adding + files in the archive, extracting files from the archive and listing + the archive content. + It also provide advanced functions that allow the adding and + extraction of files with path manipulation. + + +Sample : +-------- + + // ----- Creating the object (uncompressed archive) + $tar_object = new Archive_Tar("tarname.tar"); + $tar_object->setErrorHandling(PEAR_ERROR_PRINT); + + // ----- Creating the archive + $v_list[0]="file.txt"; + $v_list[1]="data/"; + $v_list[2]="file.log"; + $tar_object->create($v_list); + + // ----- Adding files + $v_list[0]="dev/file.txt"; + $v_list[1]="dev/data/"; + $v_list[2]="log/file.log"; + $tar_object->add($v_list); + + // ----- Adding more files + $tar_object->add("release/newfile.log release/readme.txt"); + + // ----- Listing the content + if (($v_list = $tar_object->listContent()) != 0) + for ($i=0; $i<sizeof($v_list); $i++) + { + echo "Filename :'".$v_list[$i][filename]."'<br>"; + echo " .size :'".$v_list[$i][size]."'<br>"; + echo " .mtime :'".$v_list[$i][mtime]."' (".date("l dS of F Y h:i:s A", $v_list[$i][mtime]).")<br>"; + echo " .mode :'".$v_list[$i][mode]."'<br>"; + echo " .uid :'".$v_list[$i][uid]."'<br>"; + echo " .gid :'".$v_list[$i][gid]."'<br>"; + echo " .typeflag :'".$v_list[$i][typeflag]."'<br>"; + } + + // ----- Extracting the archive in directory "install" + $tar_object->extract("install"); + + +Public arguments : +------------------ + +None + + +Public Methods : +---------------- + +Method : Archive_Tar($p_tarname, $compress = false) +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 compressed TAR file. +Arguments : + $p_tarname : A valid filename for the tar archive file. + $p_compress : true/false. Indicate if the archive need to be + compressed or not. +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 : 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 : listContent() +Description : + This method returns an array of arrays that describe each + file/directory present in the archive. + The array is not sorted, so it show the position of the file in the + archive. + The file informations are : + $file[filename] : Name and path of the file/dir. + $file[mode] : File permissions (result of fileperms()) + $file[uid] : user id + $file[gid] : group id + $file[size] : filesize + $file[mtime] : Last modification time (result of filemtime()) + $file[typeflag] : "" for file, "5" for directory +Arguments : +Return value : + An array of arrays or 0 on error. +Sample : + $tar_object = new Archive_Tar("tarname.tar"); + if (($v_list = $tar_object->listContent()) != 0) + for ($i=0; $i<sizeof($v_list); $i++) + { + echo "Filename :'".$v_list[$i][filename]."'<br>"; + echo " .size :'".$v_list[$i][size]."'<br>"; + echo " .mtime :'".$v_list[$i][mtime]."' (". + date("l dS of F Y h:i:s A", $v_list[$i][mtime]).")<br>"; + echo " .mode :'".$v_list[$i][mode]."'<br>"; + echo " .uid :'".$v_list[$i][uid]."'<br>"; + echo " .gid :'".$v_list[$i][gid]."'<br>"; + echo " .typeflag :'".$v_list[$i][typeflag]."'<br>"; + } +How it works : + Call the same function as an extract however with a flag to only go + through the archive without extracting the files. + +Method : extractList($p_filelist, $p_path = "", $p_remove_path = "") +Description : + This method extract from the archive only the files indicated in the + $p_filelist. These files are extracted in the current directory or + in the directory indicated by the optional $p_path parameter. + If indicated the $p_remove_path can be used in the same way as it is + used in extractModify() method. +Arguments : + $p_filelist : An array of filenames and directory names, or a single + string with names separated by a single blank space. + $p_path : The path of the directory where the files/dir need to by + extracted. + $p_remove_path : Part of the memorized path that can be removed if + present at the beginning of the file/dir path. +Return value : + true on success, false on error. +Sample : + // Imagine tarname.tar with files : + // dev/data/file.txt + // dev/data/log.txt + // readme.txt + $tar_object = new Archive_Tar("tarname.tar"); + $tar_object->extractList("dev/data/file.txt readme.txt", "install", + "dev"); + // Files will be extracted there : + // install/data/file.txt + // install/readme.txt +How it works : + Go through the archive and extract only the files present in the + list. + diff --git a/pear/docs/rfc01_PEAR_pecl-binaries.txt b/pear/docs/rfc01_PEAR_pecl-binaries.txt new file mode 100644 index 000000000..2801c4ef5 --- /dev/null +++ b/pear/docs/rfc01_PEAR_pecl-binaries.txt @@ -0,0 +1,88 @@ +Author: Tomas V.V.Cox <cox@idecnet.com> +Revision: $Id: rfc01_PEAR_pecl-binaries.txt,v 1.1 2003/09/19 16:50:17 cox Exp $ +Abstract: Open discussion on how to handle PECL binary packages + + +pecl package name +----------------- + +The name of the extension would be: + +peclfoo-bin-<OS>-<ARCH>-3.1.2.tgz + +The os (Operating system) and arch (CPU type), would be the value +returned by the OS_Guess class. + +package creation +---------------- + +pear package [-t <type>] <package> + +-t <type> The type of package you want to generate (pear, rpm, +msi, src, etc) + +Without args it will package the extension as it does nowadays (the +same as "-t src"). + +We have now native pear packages, rpm, msi is planned and others +will surely come. Additionally of generating the native package description +file, we could perhaps also call the tools for generating the whole package. + +An idea would be to create in addition a BUILDINFO.txt file with some data about +the env where the extension was compiled at, like the +php version, the php_uname(), the extra libs versions, os vendor +version, pear version, etc. + +package.xml +----------- + +As a binary release shares the same release data with the source +distrib, the same package.xml file could be used for all kind of +distribs. Let's say something like: + +<release> + <version>... + <date> + <notes> + <filelist>.. + <file role="ext" platform=""> + </filelist> +</release> + +A package may contain many compiled extensions for different platforms, +one single extension or the sources. + + +Installation +------------ + +pear install -t bin peclfoo (download and install the binary distrib of +peclfoo for your current OS-ARCH) + +pear install peclfoo (download, build and install peclfoo) + +All the files with role="ext" would be installed +in "ext_dir" (pear cmd setting). The user can config it with "pear config-set ext_dir=XXX". +If this var is not explicitly set, the following will be used for +finding a default location: + +if (getenv('PHP_PEAR_EXTENSION_DIR')) { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR')); + } else { + if (ini_get('extension_dir')) { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir')); + } elseif (defined('PEAR_EXTENSION_DIR') && @is_dir(PEAR_EXTENSION_DIR)) { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR); + } elseif (defined('PHP_EXTENSION_DIR')) { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR); + } else { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.'); + } +} + +Listing in the web +------------------ + +A new column "Type" should be added to the release listing under the +package home page at pear.php.net, saying that the package is a binary +distrib compiled for OS X and ARCH Y or sources. diff --git a/pear/docs/rfc01_PEAR_subpackages.txt b/pear/docs/rfc01_PEAR_subpackages.txt new file mode 100644 index 000000000..af068892e --- /dev/null +++ b/pear/docs/rfc01_PEAR_subpackages.txt @@ -0,0 +1,65 @@ +RFC: subpackages +Sept. 17, 2003 +Greg Beaver + +The Problem: +------------ +Many PEAR packages consist of a core and several ancillary self-contained program elements. Examples are: + +MDB/DB and database drivers +Log and log classes +Cache and Cache drivers +phpDocumentor and Converters +HTML_QuickForm and HTML_QuickForm_Controller + +In most cases, not all packages need be installed. The most common example of this is DB: how many people need to use every single database driver? Most of them just eat up disk space, except on multi-user installations. + +In addition, each ancillary program element may have a different stability level (sqlite driver may be beta quality, while the mysql driver is stable). Currently, this results in a contradiction: the core is stable, but one driver is not. What is the stability of the package? stable or beta? People who want to only install and use stable packages may be deceived by a package that is marked stable and contains an alpha-quality driver, for example. + +Plus, many PEAR packages are criticized for their bloat. + +The Solution: +------------- +Subpackages will allow the solving of all of these problems. Note that subpackaging does not address other problems, such as bundling together related packages (PFC packages, for example, or packages needed for a framework that need not have any dependencies). Subpackages are a dependency relation. In other words, if Package Foo depends on Bar, Foo is not necessarily a subpackage of Bar, but might be. However, if Foo does not depend on Bar, Foo is definitively NOT a subpackage of Bar. + +In other words, subpackages by definition cannot function without the presence of the core package (DB drivers are pretty pointless without DB). + +Note that with the presence of subpackages, a subpackages can be released with a new version number without need to release a new version of the core, allowing rapid development on unstable subpackages, and slower development on stable components. + +How to differentiate a subpackage from a normal dependency: +----------------------------------------------------------- +An addition should be made to the package.dtd file for package.xml files. A new dependency type, "spkg" should be used to define a subpackage dependency. This dependency type should be used by subpackages to definitively link to a parent package as a subpackage. + +example package Foo_Bar's package.xml dependency: + +<dep type="spkg" rel="has">Foo</dep> <!-- this subpackage works with all Foo --> +-or- +<dep type="spkg" rel="ge" version="1.5">Foo</dep> <!-- works with v1.5 or newer --> + +All rel values would be available including "not" if a particular version of the parent package must not be installed due to a bug affecting this particular subpackage (rare case). + +package Foo's package.xml dependencies may contain an optional dependency on the subpackage: + +<dep type="pkg" rel="has" optional="yes">Foo_Bar</dep> + +standard subpackages must be listed as optional dependencies in package.xml to allow easy installation with the --alldeps switch, but third party subpackages need not be listed as optional dependencies (if someone releases a custom DB driver or specialized phpDocumentor converter, for example, on their own website) + +Note that a required subpackage must be bundled as part of the core, and is not a subpackage - a subpackage MUST be an optional dependency. + +Naming/Path Conventions: +------------------------ +Subpackages must reside in a subdirectory of the parent package, just as they would under normal circumstances as part of the package. Foo's subpackage Bar must be named Foo_Bar, and reside in Foo/Bar.php as per PEAR conventions. + +pear.php.net changes: +--------------------- +Subpackages would not be listed globally, but instead on the package page as optional components. + +Documentation for subpackages will reside as part of the main package's documentation. + +PEAR Installer changes: +----------------------- +pear info/remote-info would list available subpackages (remote-info only) and installed subpackages (info only) + +pear list would list top-level packages, with some indication of packages that have subpackages (an asterisk or something). pear list PackageWithSubpackages would list subpackages as well + +pear uninstall PackageWithSubpackages would automatically uninstall any subpackages without requiring --force or other switches, as if they were simply a part of the main application. This is due to the fact that they would be simply a part of the package if PEAR didn't support subpackages. diff --git a/pear/go-pear-list.php b/pear/go-pear-list.php new file mode 100755 index 000000000..50a81b707 --- /dev/null +++ b/pear/go-pear-list.php @@ -0,0 +1,21 @@ +<?php +/* This is a list of packages and versions + * that will be used to create the PEAR folder + * in the windows snapshot. + * See win32/build/mkdist.php for more details + * $Id: go-pear-list.php,v 1.9.2.4 2005/03/18 01:59:00 cellog Exp $ + */ +$packages = array( +// required packages for the installer +"PEAR" => "1.3.5", +"XML_RPC" => "1.2.2", +"Console_Getopt" => "1.2", +"Archive_Tar" => "1.3.1", + +// required packages for the web frontend +"PEAR_Frontend_Web" => "0.4", +"HTML_Template_IT" => "1.1", +"Net_UserAgent_Detect" => "2.0.1", +); + +?> diff --git a/pear/go-pear.bat b/pear/go-pear.bat new file mode 100644 index 000000000..4aa323a7a --- /dev/null +++ b/pear/go-pear.bat @@ -0,0 +1,4 @@ +@ECHO OFF
+set PHP_BIN=php.exe
+%PHP_BIN% -n -d output_buffering=0 PEAR\go-pear.php %1
+pause
diff --git a/pear/install-pear.php b/pear/install-pear.php new file mode 100644 index 000000000..f3db4703e --- /dev/null +++ b/pear/install-pear.php @@ -0,0 +1,137 @@ +<?php + +/* $Id: install-pear.php,v 1.15 2003/08/14 20:14:33 derick Exp $ */ + +$pear_dir = dirname(__FILE__); +ini_set('include_path', $pear_dir); +include_once 'PEAR.php'; +include_once 'PEAR/Installer.php'; +include_once 'PEAR/Registry.php'; +include_once 'PEAR/Frontend/CLI.php'; + +$force = false; +$install_files = array(); +array_shift($argv); +for ($i = 0; $i < sizeof($argv); $i++) { + $arg = $argv[$i]; + $bn = basename($arg); + if (ereg('package-(.*)\.xml$', $bn, $matches) || + ereg('([A-Za-z0-9_:]+)-.*\.(tar|tgz)$', $bn, $matches)) { + $install_files[$matches[1]] = $arg; + } elseif ($arg == '--force') { + $force = true; + } elseif ($arg == '-d') { + $with_dir = $argv[$i+1]; + $i++; + } elseif ($arg == '-b') { + $bin_dir = $argv[$i+1]; + $i++; + } +} + +$config = &PEAR_Config::singleton(); + +// make sure we use only default values +$config_layers = $config->getLayers(); +foreach ($config_layers as $layer) { + if ($layer == 'default') continue; + $config->removeLayer($layer); +} +$keys = $config->getKeys(); +$config->set('verbose', 0, 'default'); +// PEAR executables +if (!empty($bin_dir)) { + $config->set('bin_dir', $bin_dir, 'default'); +} +// User supplied a dir prefix +if (!empty($with_dir)) { + $ds = DIRECTORY_SEPARATOR; + $config->set('php_dir', $with_dir, 'default'); + $config->set('doc_dir', $with_dir . $ds . 'doc', 'default'); + $config->set('data_dir', $with_dir . $ds . 'data', 'default'); + $config->set('test_dir', $with_dir . $ds . 'test', 'default'); +} +/* Print PEAR Conf (useful for debuging do NOT REMOVE) +sort($keys); +foreach ($keys as $key) { + echo $config->getPrompt($key) . ": " . $config->get($key) . "\n"; +} +exit; +// end print +//*/ + +$php_dir = $config->get('php_dir'); +$options = array(); +$install_root = getenv('INSTALL_ROOT'); +if (!empty($install_root)) { + $options['installroot'] = $install_root; + $reg_dir = $install_root . $php_dir; +} else { + $reg_dir = $php_dir; +} + +$reg = &new PEAR_Registry($reg_dir); +$ui = &new PEAR_Frontend_CLI(); +$installer = &new PEAR_Installer($ui); +//$installer->registry = &$reg; // This should be changed in Installer/Registry + +foreach ($install_files as $package => $instfile) { + if ($reg->packageExists($package)) { + $info = $installer->infoFromAny($instfile); + if (PEAR::isError($info)) { + $ui->outputData(sprintf("[PEAR] %s: %s", $package, $info->getMessage())); + continue; + } + $new_ver = $info['version']; + $old_ver = $reg->packageInfo($package, 'version'); + if (version_compare($new_ver, $old_ver, 'gt')) { + $options['upgrade'] = true; + $err = $installer->install($instfile, $options); + if (PEAR::isError($err)) { + $ui->outputData(sprintf("[PEAR] %s: %s", $package, $err->getMessage())); + continue; + } + $ui->outputData(sprintf("[PEAR] %-15s- upgraded: %s", $package, $new_ver)); + } else { + if ($force) { + $options['force'] = true; + $err = $installer->install($instfile, $options); + if (PEAR::isError($err)) { + $ui->outputData(sprintf("[PEAR] %s: %s", $package, $err->getMessage())); + continue; + } + $ui->outputData(sprintf("[PEAR] %-15s- installed: %s", $package, $new_ver)); + } else { + $ui->outputData(sprintf("[PEAR] %-15s- already installed: %s", $package, $old_ver)); + } + } + } else { + $options['nodeps'] = true; + $err = $installer->install($instfile, $options); + if (PEAR::isError($err)) { + $ui->outputData(sprintf("[PEAR] %s: %s", $package, $err->getMessage())); + continue; + } + $new_ver = $reg->packageInfo($package, 'version'); + $ui->outputData(sprintf("[PEAR] %-15s- installed: %s", $package, $new_ver)); + } + if ($package == 'PEAR') { + if (is_file($ufile = $config->getConfFile('user'))) { + $ui->outputData('Warning! a PEAR user config file already exists from ' . + 'a previous PEAR installation at ' . + "'$ufile'. You may probably want to remove it."); + } + $config->set('verbose', 1, 'default'); + foreach ($config->getKeys() as $key) { + $data[$key] = $config->get($key); + } + $cnf_file = $config->getConfFile('system'); + if (!empty($install_root)) { + $cnf_file = $install_root . DIRECTORY_SEPARATOR . $cnf_file; + } + $config->writeConfigFile($cnf_file, 'system', $data); + $ui->outputData('Wrote PEAR system config file at: ' . $cnf_file); + $ui->outputData('You may want to add: ' . $config->get('php_dir') . ' to your php.ini include_path'); + } +} +?> diff --git a/pear/install-pear.txt b/pear/install-pear.txt new file mode 100644 index 000000000..ec632e8ad --- /dev/null +++ b/pear/install-pear.txt @@ -0,0 +1,11 @@ ++----------------------------------------------------------------------+ +| The installation process is incomplete. The following resources were | +| not installed: | +| | +| Self-contained Extension Support | +| PEAR: PHP Extension and Application Repository | +| | +| To install these components, become the superuser and execute: | +| | +| # make install-su | ++----------------------------------------------------------------------+ diff --git a/pear/package-Archive_Tar.xml b/pear/package-Archive_Tar.xml new file mode 100644 index 000000000..7d54a0173 --- /dev/null +++ b/pear/package-Archive_Tar.xml @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE package SYSTEM "package.dtd"> +<package version="1.0"> + <name>Archive_Tar</name> + <summary>Tar file management class</summary> + <description>This class provides handling of tar files in PHP. +It supports creating, listing, extracting and adding to tar files. +Gzip support is available if PHP has the zlib extension built-in or +loaded. Bz2 compression is also supported with the bz2 extension loaded. +</description> + <license>PHP License</license> + <maintainers> + <maintainer> + <user>vblavet</user> + <role>lead</role> + <name>Vincent Blavet</name> + <email>vincent@blavet.net</email> + </maintainer> + <maintainer> + <user>ssb</user> + <role>helper</role> + <name>Stig Sæther Bakken</name> + <email>stig@php.net</email> + </maintainer> + </maintainers> + <release> + <version>1.1</version> + <date>2003-05-28</date> + <notes>* Add support for BZ2 compression +* Add support for add and extract without using temporary files : methods addString() and extractInString() + +</notes> + <state>stable</state> + <filelist> + <dir name="Archive"> + <file role="php" name="Tar.php"/> + </dir> + <file role="doc" name="docs/Archive_Tar.txt" baseinstalldir="/"/> + </filelist> + </release> + <changelog> + <release> + <version>1.0</version> + <date>2003-01-24</date> + <notes>Change status to stable</notes> + <state>stable</state> + <filelist> + <dir name="Archive"> + <file role="php" name="Tar.php"/> + </dir> + <file role="doc" name="docs/Archive_Tar.txt" baseinstalldir="/"/> + </filelist> + </release> + <release> + <version>0.10-b1</version> + <date>2003-01-08</date> + <notes>Add support for long filenames (greater than 99 characters)</notes> + <state>beta</state> + </release> + <release> + <version>0.9</version> + <date>2002-05-27</date> + <notes>Auto-detect gzip'ed files</notes> + <state>stable</state> + </release> + <release> + <version>0.4</version> + <date>2002-05-20</date> + <notes>Windows bugfix: use forward slashes inside archives</notes> + <state>stable</state> + </release> + <release> + <version>0.2</version> + <date>2002-02-18</date> + <notes>From initial commit to stable</notes> + <state>stable</state> + </release> + <release> + <version>0.3</version> + <date>2002-04-13</date> + <notes>Windows bugfix: used wrong directory separators</notes> + <state>stable</state> + </release> + </changelog> +</package> diff --git a/pear/package-Console_Getopt.xml b/pear/package-Console_Getopt.xml new file mode 100644 index 000000000..57769e6b9 --- /dev/null +++ b/pear/package-Console_Getopt.xml @@ -0,0 +1,80 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE package SYSTEM "package.dtd"> +<!-- do not use the "Type" attribute here, that one is only for + generated package.xml files --> +<package version="1.0"> + <name>Console_Getopt</name> + <summary>Command-line option parser</summary> + <description>This is a PHP implementation of "getopt" supporting both +short and long options.</description> + <license>PHP License</license> + <maintainers> + <maintainer> + <user>andrei</user> + <role>lead</role> + <name>Andrei Zmievski</name> + <email>andrei@php.net</email> + </maintainer> + <maintainer> + <user>ssb</user> + <role>developer</role> + <name>Stig Bakken</name> + <email>stig@php.net</email> + </maintainer> + <maintainer> + <user>cellog</user> + <role>helper</role> + <name>Greg Beaver</name> + <email>cellog@php.net</email> + </maintainer> + </maintainers> + <release> + <version>1.2</version> + <date>2003-12-11</date> + <notes>Fix to preserve BC with 1.0 and allow correct behaviour for new users</notes> + <state>stable</state> + <filelist> + <dir name="Console"> + <file role="php" name="Getopt.php"/> + </dir> + </filelist> + </release> + <changelog> + <release> + <version>1.0</version> + <date>2002-09-13</date> + <notes>Stable release</notes> + <state>stable</state> + <filelist> + <dir name="Console"> + <file role="php" name="Getopt.php"/> + </dir> + </filelist> + </release> + <release> + <version>0.11</version> + <date>2002-05-26</date> + <notes>POSIX getopt compatibility fix: treat first element of args + array as command name + </notes> + <state>beta</state> + <filelist> + <dir name="Console"> + <file role="php" name="Getopt.php"/> + </dir> + </filelist> + </release> + <release> + <version>0.10</version> + <date>2002-05-12</date> + <notes>Packaging fix</notes> + <state>beta</state> + </release> + <release> + <version>0.9</version> + <date>2002-05-12</date> + <notes>Initial release</notes> + <state>beta</state> + </release> + </changelog> +</package> diff --git a/pear/package-PEAR.xml b/pear/package-PEAR.xml new file mode 100644 index 000000000..6aa169003 --- /dev/null +++ b/pear/package-PEAR.xml @@ -0,0 +1,201 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE package SYSTEM "package.dtd"> +<package version="1.0"> + <name>PEAR</name> + <summary>PEAR Base System</summary> + <description>The PEAR package contains: + * the PEAR installer, for creating, distributing + and installing packages + * the alpha-quality PEAR_Exception php5-only exception class + * the beta-quality PEAR_ErrorStack advanced error handling mechanism + * the PEAR_Error error handling mechanism + * the OS_Guess class for retrieving info about the OS + where PHP is running on + * the System class for quick handling common operations + with files and directories + * the PEAR base class +</description> + <maintainers> + <maintainer> + <user>ssb</user> + <role>lead</role> + <name>Stig Bakken</name> + <email>stig@php.net</email> + </maintainer> + <maintainer> + <user>cox</user> + <role>lead</role> + <name>Tomas V.V.Cox</name> + <email>cox@idecnet.com</email> + </maintainer> + <maintainer> + <user>cellog</user> + <role>lead</role> + <name>Greg Beaver</name> + <email>cellog@php.net</email> + </maintainer> + <maintainer> + <user>pajoye</user> + <role>lead</role> + <name>Pierre-Alain Joye</name> + <email>pajoye@pearfr.org</email> + </maintainer> + <maintainer> + <user>mj</user> + <role>developer</role> + <name>Martin Jansen</name> + <email>mj@php.net</email> + </maintainer> + </maintainers> + <release> + <version>1.3.5</version> + <date>2005-02-18</date> + <state>stable</state> + <license>PHP License</license> + <notes> + * fix Bug #3505: pecl can't install PDO + * enhance pear run-tests dramatically + * fix Bug #3506: pear install should export the pear version into the environment + </notes> + <provides type="class" name="OS_Guess" /> + <provides type="class" name="System" /> + <provides type="function" name="md5_file" /> + <filelist> + <dir name="OS"> + <file role="php" name="Guess.php"/> + </dir> + <dir name="PEAR"> + <dir name="Command"> + <file role="php" name="Auth.php"/> + <file role="php" name="Build.php"/> + <file role="php" name="Common.php"/> + <file role="php" name="Config.php"/> + <file role="php" name="Install.php"/> + <file role="php" name="Package.php"/> + <file role="php" name="Registry.php"/> + <file role="php" name="Remote.php"/> + <file role="php" name="Mirror.php"/> + </dir> + <dir name="Frontend"> + <file role="php" name="CLI.php"/> + </dir> + <file role="php" name="Autoloader.php"/> + <file role="php" name="Command.php"/> + <file role="php" name="Common.php"/> + <file role="php" name="Config.php"/> + <file role="php" name="Dependency.php"/> + <file role="php" name="Downloader.php"/> + <file role="php" name="Exception.php"/> + <file role="php" name="ErrorStack.php"/> + <file role="php" name="Builder.php"> + <replace from="@PEAR-VER@" to="version" type="package-info"/> + </file> + <file role="php" name="Installer.php"/> + <file role="php" name="Packager.php"/> + <file role="php" name="Registry.php"/> + <file role="php" name="Remote.php"/> + <file role="php" name="RunTest.php"/> + </dir> + <dir name="scripts" baseinstalldir="/"> + <file role="script" install-as="pear" name="pear.sh"> + <replace from="@php_bin@" to="php_bin" type="pear-config"/> + <replace from="@php_dir@" to="php_dir" type="pear-config"/> + <replace from="@pear_version@" to="version" type="package-info"/> + <replace from="@include_path@" to="php_dir" type="pear-config"/> + </file> + <file role="script" platform="windows" install-as="pear.bat" name="pear.bat"> + <replace from="@bin_dir@" to="bin_dir" type="pear-config"/> + <replace from="@php_bin@" to="php_bin" type="pear-config"/> + <replace from="@include_path@" to="php_dir" type="pear-config"/> + </file> + <file role="php" install-as="pearcmd.php" name="pearcmd.php"> + <replace from="@php_bin@" to="php_bin" type="pear-config"/> + <replace from="@php_dir@" to="php_dir" type="pear-config"/> + <replace from="@pear_version@" to="version" type="package-info"/> + <replace from="@include_path@" to="php_dir" type="pear-config"/> + </file> + </dir> + <file role="data" name="package.dtd"/> + <file role="data" name="template.spec"/> + <file role="php" name="PEAR.php"/> + <file role="php" name="System.php"/> + </filelist> + <deps> + <dep type="php" rel="ge" version="4.2"/> + <dep type="pkg" rel="ge" version="1.1">Archive_Tar</dep> + <dep type="pkg" rel="ge" version="1.2">Console_Getopt</dep> + <dep type="pkg" rel="ge" version="1.0.4">XML_RPC</dep> + <dep type="ext" rel="has">xml</dep> + <dep type="ext" rel="has">pcre</dep> + </deps> + </release> + <changelog> + <release> + <version>1.3.1</version> + <date>2004-04-06</date> + <state>stable</state> + <notes> +PEAR Installer: + + * Bug #534 pear search doesn't list unstable releases + * Bug #933 CMD Usability Patch + * Bug #937 throwError() treats every call as static + * Bug #964 PEAR_ERROR_EXCEPTION causes fatal error + * Bug #1008 safe mode raises warning + +PEAR_ErrorStack: + + * Added experimental error handling, designed to eventually replace + PEAR_Error. It should be considered experimental until explicitly marked + stable. require_once 'PEAR/ErrorStack.php' to use. + + </notes> + </release> + <release> + <version>1.3.3</version> + <date>2004-10-28</date> + <state>stable</state> + <notes> +Installer: + * fix Bug #1186 raise a notice error on PEAR::Common $_packageName + * fix Bug #1249 display the right state when using --force option + * fix Bug #2189 upgrade-all stops if dependancy fails + * fix Bug #1637 The use of interface causes warnings when packaging with PEAR + * fix Bug #1420 Parser bug for T_DOUBLE_COLON + * fix Request #2220 pear5 build fails on dual php4/php5 system + * fix Bug #1163 pear makerpm fails with packages that supply role="doc" + +Other: + * add PEAR_Exception class for PHP5 users + * fix critical problem in package.xml for linux in 1.3.2 + * fix staticPopCallback() in PEAR_ErrorStack + * fix warning in PEAR_Registry for windows 98 users + </notes> + </release> + <release> + <version>1.3.3.1</version> + <date>2004-11-08</date> + <state>stable</state> + <notes> + add RunTest.php to package.xml, make run-tests display failed tests, and use ui + </notes> + </release> + <release> + <version>1.3.4</version> + <date>2005-01-01</date> + <state>stable</state> + <notes> + * fix a serious problem caused by a bug in all versions of PHP that caused multiple registration + of the shutdown function of PEAR.php + * fix Bug #2861: package.dtd does not define NUMBER + * fix Bug #2946: ini_set warning errors + * fix Bug #3026: Dependency type "ne" is needed, "not" is not handled + properly + * fix Bug #3061: potential warnings in PEAR_Exception + * implement Request #2848: PEAR_ErrorStack logger extends, PEAR_ERRORSTACK_DIE + * implement Request #2914: Dynamic Include Path for run-tests command + * make pear help listing more useful (put how-to-use info at the bottom of the listing) + </notes> + </release> + </changelog> +</package> diff --git a/pear/package.dtd b/pear/package.dtd new file mode 100644 index 000000000..730bbec5d --- /dev/null +++ b/pear/package.dtd @@ -0,0 +1,110 @@ +<!-- + $Id: package.dtd,v 1.35.4.1 2005/03/28 16:46:06 cellog Exp $ + + This is the PEAR package description, version 1.0. + It should be used with the informal public identifier: + + "-//PHP Group//DTD PEAR Package 1.0//EN//XML" + + Copyright (c) 1997-2004 The PHP Group + + This source file is subject to version 3.0 of the PHP license, + that is bundled with this package in the file LICENSE, and is + available at through the world-wide-web at + http://www.php.net/license/3_0.txt. + If you did not receive a copy of the PHP license and are unable to + obtain it through the world-wide-web, please send a note to + license@php.net so we can mail you a copy immediately. + + Authors: + Stig S. Bakken <ssb@php.net> + + --> +<!ENTITY % NUMBER "CDATA"> +<!ELEMENT package (name|summary|description|license|maintainers|release|changelog)+> +<!ATTLIST package type (source|binary|empty) "empty" + version CDATA #REQUIRED> + +<!ELEMENT name (#PCDATA)> + +<!ELEMENT summary (#PCDATA)> + +<!ELEMENT description (#PCDATA)> + +<!ELEMENT license (#PCDATA)> + +<!ELEMENT maintainers (maintainer)+> + +<!ELEMENT maintainer (user|role|name|email)+> + +<!ELEMENT user (#PCDATA)> + +<!ELEMENT role (#PCDATA)> + +<!ELEMENT email (#PCDATA)> + +<!ELEMENT changelog (release)+> + +<!ELEMENT release (version|license|state|date|notes|filelist|deps|provides|script|configureoptions)+> + +<!ELEMENT version (#PCDATA)> + +<!ELEMENT state (#PCDATA)> + +<!ELEMENT date (#PCDATA)> + +<!ELEMENT notes (#PCDATA)> + +<!ELEMENT filelist (dir|file)+> + +<!ELEMENT dir (dir|file)+> +<!ATTLIST dir name CDATA #REQUIRED + baseinstalldir CDATA #IMPLIED> + +<!ELEMENT file (replace*)> +<!ATTLIST file role (php|ext|src|test|doc|data|script) 'php' + debug (na|on|off) 'na' + zts (na|on|off) 'na' + phpapi %NUMBER; #IMPLIED + zendapi %NUMBER; #IMPLIED + format CDATA #IMPLIED + baseinstalldir CDATA #IMPLIED + platform CDATA #IMPLIED + md5sum CDATA #IMPLIED + name CDATA #REQUIRED + install-as CDATA #IMPLIED> + +<!ELEMENT replace EMPTY> +<!ATTLIST replace from CDATA #REQUIRED + to CDATA #REQUIRED + type CDATA #REQUIRED> + +<!ELEMENT deps (dep)+> + +<!ELEMENT dep (#PCDATA)> +<!ATTLIST dep + optional (yes|no) 'no' + type (pkg|ext|php|prog|ldlib|rtlib|os|websrv|sapi|zend) #REQUIRED + rel (has|eq|lt|le|gt|ge) 'has' + version CDATA #IMPLIED> + +<!ELEMENT provides (#PCDATA)> +<!ATTLIST provides + type (ext|prog|class|function|feature|api) #REQUIRED + name CDATA #REQUIRED + extends CDATA #IMPLIED> + +<!ELEMENT script (#PCDATA)> +<!ATTLIST script + phase (pre-install |post-install | + pre-uninstall|post-uninstall| + pre-build |post-build | + pre-setup |post-setup ) #REQUIRED> + +<!ELEMENT configureoptions (configureoption*)> + +<!ELEMENT configureoption EMPTY> +<!ATTLIST configureoption + name CDATA #REQUIRED + default CDATA #IMPLIED + prompt CDATA #REQUIRED> diff --git a/pear/packages/HTML_Template_IT-1.1.tar b/pear/packages/HTML_Template_IT-1.1.tar Binary files differnew file mode 100644 index 000000000..055621e3b --- /dev/null +++ b/pear/packages/HTML_Template_IT-1.1.tar diff --git a/pear/packages/Net_UserAgent_Detect-2.0.1.tar b/pear/packages/Net_UserAgent_Detect-2.0.1.tar Binary files differnew file mode 100644 index 000000000..1d2478bd0 --- /dev/null +++ b/pear/packages/Net_UserAgent_Detect-2.0.1.tar diff --git a/pear/packages/XML_RPC-1.2.2.tar b/pear/packages/XML_RPC-1.2.2.tar Binary files differnew file mode 100644 index 000000000..8470b13b5 --- /dev/null +++ b/pear/packages/XML_RPC-1.2.2.tar diff --git a/pear/scripts/pear.bat b/pear/scripts/pear.bat new file mode 100755 index 000000000..2b30f8162 --- /dev/null +++ b/pear/scripts/pear.bat @@ -0,0 +1,69 @@ +@ECHO OFF
+
+REM ----------------------------------------------------------------------
+REM PHP version 5
+REM ----------------------------------------------------------------------
+REM Copyright (c) 1997-2004 The PHP Group
+REM ----------------------------------------------------------------------
+REM This source file is subject to version 3.0 of the PHP license,
+REM that is bundled with this package in the file LICENSE, and is
+REM available at through the world-wide-web at
+REM http://www.php.net/license/3_0.txt.
+REM If you did not receive a copy of the PHP license and are unable to
+REM obtain it through the world-wide-web, please send a note to
+REM license@php.net so we can mail you a copy immediately.
+REM ----------------------------------------------------------------------
+REM Authors: Alexander Merz (alexmerz@php.net)
+REM ----------------------------------------------------------------------
+REM
+REM Last updated 3/13/2004 ($Id$ is not replaced if the file is binary)
+
+REM change this lines to match the paths of your system
+REM -------------------
+
+@ECHO OFF
+:: Check PEAR global ENV, set them if they do not exist
+IF "%PHP_PEAR_INSTALL_DIR%"=="" SET "PHP_PEAR_INSTALL_DIR=@include_path@"
+IF "%PHP_PEAR_BIN_DIR%"=="" SET "PHP_PEAR_BIN_DIR=@bin_dir@"
+IF "%PHP_PEAR_PHP_BIN%"=="" SET "PHP_PEAR_PHP_BIN=@php_bin@"
+
+:: Check Folders and files
+IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%" GOTO PEAR_INSTALL_ERROR
+IF NOT EXIST "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" GOTO PEAR_INSTALL_ERROR2
+IF NOT EXIST "%PHP_PEAR_BIN_DIR%" GOTO PEAR_BIN_ERROR
+IF NOT EXIST "%PHP_PEAR_PHP_BIN%" GOTO PEAR_PHPBIN_ERROR
+:: launch pearcmd
+GOTO RUN
+:PEAR_INSTALL_ERROR
+ECHO PHP_PEAR_INSTALL_DIR is not set correctly.
+ECHO Please fix it using your environment variable or modify
+ECHO the default value in pear.bat
+ECHO The current value is:
+ECHO %PHP_PEAR_INSTALL_DIR%
+GOTO END
+:PEAR_INSTALL_ERROR2
+ECHO PHP_PEAR_INSTALL_DIR is not set correctly.
+ECHO pearcmd.php could not be found there.
+ECHO Please fix it using your environment variable or modify
+ECHO the default value in pear.bat
+ECHO The current value is:
+ECHO %PHP_PEAR_INSTALL_DIR%
+GOTO END
+:PEAR_BIN_ERROR
+ECHO PHP_PEAR_BIN_DIR is not set correctly.
+ECHO Please fix it using your environment variable or modify
+ECHO the default value in pear.bat
+ECHO The current value is:
+ECHO %PHP_PEAR_BIN_DIR%
+GOTO END
+:PEAR_PHPBIN_ERROR
+ECHO PHP_PEAR_PHP_BIN is not set correctly.
+ECHO Please fix it using your environment variable or modify
+ECHO the default value in pear.bat
+ECHO The current value is:
+ECHO %PHP_PEAR_PHP_BIN%
+GOTO END
+:RUN
+"%PHP_PEAR_PHP_BIN%" -C -d output_buffering=1 -d include_path="%PHP_PEAR_INSTALL_DIR%" -f "%PHP_PEAR_INSTALL_DIR%\pearcmd.php" -- %1 %2 %3 %4 %5 %6 %7 %8 %9
+:END
+@ECHO ON
diff --git a/pear/scripts/pear.sh b/pear/scripts/pear.sh new file mode 100644 index 000000000..6253b9014 --- /dev/null +++ b/pear/scripts/pear.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +# first find which PHP binary to use +if test "x$PHP_PEAR_PHP_BIN" != "x"; then + PHP="$PHP_PEAR_PHP_BIN" +else + if test "@php_bin@" = '@'php_bin'@'; then + PHP=php + else + PHP="@php_bin@" + fi +fi + +# then look for the right pear include dir +if test "x$PHP_PEAR_INSTALL_DIR" != "x"; then + INCDIR=$PHP_PEAR_INSTALL_DIR + INCARG="-d include_path=$PHP_PEAR_INSTALL_DIR" +else + if test "@php_dir@" = '@'php_dir'@'; then + INCDIR=`dirname $0` + INCARG="" + else + INCDIR="@php_dir@" + INCARG="-d include_path=@php_dir@" + fi +fi + +exec $PHP -C -q $INCARG -d output_buffering=1 $INCDIR/pearcmd.php "$@" diff --git a/pear/scripts/pearcmd.php b/pear/scripts/pearcmd.php new file mode 100644 index 000000000..36484af1d --- /dev/null +++ b/pear/scripts/pearcmd.php @@ -0,0 +1,318 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Authors: Stig Bakken <ssb@php.net> | +// | Tomas V.V.Cox <cox@idecnet.com> | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: pearcmd.php,v 1.13.2.1 2005/03/28 16:46:06 cellog Exp $ + +ob_end_clean(); +/** + * @nodep Gtk + */ +if ('@include_path@' != '@'.'include_path'.'@') { + ini_set('include_path', '@include_path@'); +} +ini_set('allow_url_fopen', true); +if (!ini_get('safe_mode')) { + @set_time_limit(0); +} +ob_implicit_flush(true); +ini_set('track_errors', true); +ini_set('html_errors', false); +ini_set('magic_quotes_runtime', false); +set_error_handler('error_handler'); + +$pear_package_version = "@pear_version@"; + +require_once 'PEAR.php'; +require_once 'PEAR/Config.php'; +require_once 'PEAR/Command.php'; +require_once 'Console/Getopt.php'; + +PEAR_Command::setFrontendType('CLI'); +$all_commands = PEAR_Command::getCommands(); + +$argv = Console_Getopt::readPHPArgv(); +/* $progname = basename($argv[0]); */ +$progname = 'pear'; +if (in_array('getopt2', get_class_methods('Console_Getopt'))) { + array_shift($argv); + $options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV"); +} else { + $options = Console_Getopt::getopt($argv, "c:C:d:D:Gh?sSqu:vV"); +} +if (PEAR::isError($options)) { + usage($options); +} + +$opts = $options[0]; + +$fetype = 'CLI'; +if ($progname == 'gpear' || $progname == 'pear-gtk') { + $fetype = 'Gtk'; +} else { + foreach ($opts as $opt) { + if ($opt[0] == 'G') { + $fetype = 'Gtk'; + } + } +} +PEAR_Command::setFrontendType($fetype); +$ui = &PEAR_Command::getFrontendObject(); +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")); +if (ini_get('safe_mode')) { + $ui->outputData('WARNING: running in safe mode requires that all files created ' . + 'be the same uid as the current script. PHP reports this script is uid: ' . + @getmyuid() . ', and current user is: ' . @get_current_user()); +} + +$pear_user_config = ''; +$pear_system_config = ''; +$store_user_config = false; +$store_system_config = false; +$verbose = 1; + +foreach ($opts as $opt) { + switch ($opt[0]) { + case 'c': + $pear_user_config = $opt[1]; + break; + case 'C': + $pear_system_config = $opt[1]; + break; + } +} + +$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config); +$verbose = $config->get("verbose"); +$cmdopts = array(); + +foreach ($opts as $opt) { + $param = !empty($opt[1]) ? $opt[1] : true; + switch ($opt[0]) { + case 'd': + list($key, $value) = explode('=', $param); + $config->set($key, $value, 'user'); + break; + case 'D': + list($key, $value) = explode('=', $param); + $config->set($key, $value, 'system'); + break; + case 's': + $store_user_config = true; + break; + case 'S': + $store_system_config = true; + break; + case 'u': + $config->remove($param, 'user'); + break; + case 'v': + $config->set('verbose', $config->get('verbose') + 1); + break; + case 'q': + $config->set('verbose', $config->get('verbose') - 1); + break; + case 'V': + usage(null, 'version'); + default: + // all non pear params goes to the command + $cmdopts[$opt[0]] = $param; + break; + } +} + +if ($store_system_config) { + $config->store('system'); +} + +if ($store_user_config) { + $config->store('user'); +} + +$command = (isset($options[1][0])) ? $options[1][0] : null; + +if (empty($command) && ($store_user_config || $store_system_config)) { + exit; +} + +if ($fetype == 'Gtk') { + Gtk::main(); +} else do { + if ($command == 'help') { + usage(null, @$options[1][1]); + } + + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $cmd = PEAR_Command::factory($command, $config); + PEAR::popErrorHandling(); + if (PEAR::isError($cmd)) { + usage(null, @$options[1][1]); + } + + $short_args = $long_args = null; + PEAR_Command::getGetoptArgs($command, $short_args, $long_args); + if (in_array('getopt2', get_class_methods('Console_Getopt'))) { + array_shift($options[1]); + $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args); + } else { + $tmp = Console_Getopt::getopt($options[1], $short_args, $long_args); + } + if (PEAR::isError($tmp)) { + break; + } + list($tmpopt, $params) = $tmp; + $opts = array(); + foreach ($tmpopt as $foo => $tmp2) { + list($opt, $value) = $tmp2; + if ($value === null) { + $value = true; // options without args + } + if (strlen($opt) == 1) { + $cmdoptions = $cmd->getOptions($command); + foreach ($cmdoptions as $o => $d) { + if (@$d['shortopt'] == $opt) { + $opts[$o] = $value; + } + } + } else { + if (substr($opt, 0, 2) == '--') { + $opts[substr($opt, 2)] = $value; + } + } + } + $ok = $cmd->run($command, $opts, $params); + if ($ok === false) { + PEAR::raiseError("unknown command `$command'"); + } +} while (false); + +// {{{ usage() + +function usage($error = null, $helpsubject = null) +{ + global $progname, $all_commands; + $stderr = fopen('php://stderr', 'w'); + if (PEAR::isError($error)) { + fputs($stderr, $error->getMessage() . "\n"); + } elseif ($error !== null) { + fputs($stderr, "$error\n"); + } + if ($helpsubject != null) { + $put = cmdHelp($helpsubject); + } else { + $put = + "Commands:\n"; + $maxlen = max(array_map("strlen", $all_commands)); + $formatstr = "%-{$maxlen}s %s\n"; + ksort($all_commands); + foreach ($all_commands as $cmd => $class) { + $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd)); + } + $put .= + "Usage: $progname [options] command [command-options] <parameters>\n". + "Type \"$progname help options\" to list all options.\n". + "Type \"$progname help shortcuts\" to list all command shortcuts.\n". + "Type \"$progname help <command>\" to get the help for the specified command."; + } + fputs($stderr, "$put\n"); + fclose($stderr); + exit; +} + +function cmdHelp($command) +{ + global $progname, $all_commands, $config; + if ($command == "options") { + return + "Options:\n". + " -v increase verbosity level (default 1)\n". + " -q be quiet, decrease verbosity level\n". + " -c file find user configuration in `file'\n". + " -C file find system configuration in `file'\n". + " -d foo=bar set user config variable `foo' to `bar'\n". + " -D foo=bar set system config variable `foo' to `bar'\n". + " -G start in graphical (Gtk) mode\n". + " -s store user configuration\n". + " -S store system configuration\n". + " -u foo unset `foo' in the user configuration\n". + " -h, -? display help/usage (this message)\n". + " -V version information\n"; + } elseif ($command == "shortcuts") { + $sc = PEAR_Command::getShortcuts(); + $ret = "Shortcuts:\n"; + foreach ($sc as $s => $c) { + $ret .= sprintf(" %-8s %s\n", $s, $c); + } + return $ret; + + } elseif ($command == "version") { + return "PEAR Version: ".$GLOBALS['pear_package_version']. + "\nPHP Version: ".phpversion(). + "\nZend Engine Version: ".zend_version(). + "\nRunning on: ".php_uname(); + + } elseif ($help = PEAR_Command::getHelp($command)) { + if (is_string($help)) { + return "$progname $command [options] $help\n"; + } + if ($help[1] === null) { + return "$progname $command $help[0]"; + } else { + return "$progname $command [options] $help[0]\n$help[1]"; + } + } + return "Command '$command' is not valid, try 'pear help'"; +} + +// }}} + +function error_handler($errno, $errmsg, $file, $line, $vars) { + if ((defined('E_STRICT') && $errno & E_STRICT) || !error_reporting()) { + return; // @silenced error + } + $errortype = array ( + E_ERROR => "Error", + E_WARNING => "Warning", + E_PARSE => "Parsing Error", + E_NOTICE => "Notice", + E_CORE_ERROR => "Core Error", + E_CORE_WARNING => "Core Warning", + E_COMPILE_ERROR => "Compile Error", + E_COMPILE_WARNING => "Compile Warning", + E_USER_ERROR => "User Error", + E_USER_WARNING => "User Warning", + E_USER_NOTICE => "User Notice" + ); + $prefix = $errortype[$errno]; + $file = basename($file); + print "\n$prefix: $errmsg in $file on line $line\n"; +} + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: nil + * mode: php + * End: + */ +// vim600:syn=php + +?> diff --git a/pear/scripts/pearwin.php b/pear/scripts/pearwin.php new file mode 100644 index 000000000..8e9b20837 --- /dev/null +++ b/pear/scripts/pearwin.php @@ -0,0 +1,233 @@ +<?php +// +// +----------------------------------------------------------------------+ +// | PHP Version 5 | +// +----------------------------------------------------------------------+ +// | Copyright (c) 1997-2004 The PHP Group | +// +----------------------------------------------------------------------+ +// | This source file is subject to version 3.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available through the world-wide-web at the following url: | +// | http://www.php.net/license/3_0.txt. | +// | If you did not receive a copy of the PHP license and are unable to | +// | obtain it through the world-wide-web, please send a note to | +// | license@php.net so we can mail you a copy immediately. | +// +----------------------------------------------------------------------+ +// | Authors: Stig Bakken <ssb@php.net> | +// | Tomas V.V.Cox <cox@idecnet.com> | +// +----------------------------------------------------------------------+ +// +// $Id: pearwin.php,v 1.12 2004/01/08 17:33:14 sniper Exp $ + +require_once 'PEAR.php'; +require_once 'PEAR/Common.php'; +require_once 'PEAR/Config.php'; +require_once 'PEAR/Remote.php'; +require_once 'PEAR/Registry.php'; +require_once 'Console/Getopt.php'; + +error_reporting(E_ALL ^ E_NOTICE); + +$progname = basename($argv[0]); + +PEAR::setErrorHandling(PEAR_ERROR_PRINT, "$progname: %s\n"); + +$argv = Console_Getopt::readPHPArgv(); +if (PEAR::isError($argv)) { + die($argv->getMessage()); +} +$options = Console_Getopt::getopt($argv, "c:C:d:D:h?sSqu:v"); +if (PEAR::isError($options)) { + usage($options); +} + + +$php_sysconfdir = getenv('PHP_SYSCONFDIR'); +if (!empty($php_sysconfdir)) { + $pear_default_config = $php_sysconfdir.DIRECTORY_SEPARATOR.'pearsys.ini'; + $pear_user_config = $php_sysconfdir.DIRECTORY_SEPARATOR.'pear.ini'; +} else { + $pear_default_config = PHP_SYSCONFDIR.DIRECTORY_SEPARATOR.'pearsys.ini'; + $pear_user_config = PHP_SYSCONFDIR.DIRECTORY_SEPARATOR.'pear.ini'; +} + +$opts = $options[0]; + +//echo "ini_get : ".ini_get("pear_install_dir")."\n"; +//echo "get_cfg_var : ".get_cfg_var("pear_install_dir")."\n"; + +foreach ($opts as $opt) { + switch ($opt[0]) { + case 'c': + $pear_user_config = $opt[1]; + break; + case 'C': + $pear_default_config = $opt[1]; + break; + } +} + +$config = new PEAR_Config($pear_user_config, $pear_default_config); +$store_user_config = false; +$store_default_config = false; +$verbose = 1; + +foreach ($opts as $opt) { + $param = $opt[1]; + switch ($opt[0]) { + case 'd': + list($key, $value) = explode('=', $param); + $config->set($key, $value); + break; + case 'D': + list($key, $value) = explode('=', $param); + $config->set($key, $value, true); + break; + case 's': + $store_user_config = true; + break; + case 'S': + $store_default_config = true; + break; + case 'u': + $config->toDefault($param); + break; + case 'v': + $verbose++; + break; + case 'q': + $verbose--; + break; + } +} + +if ($store_default_config) { + if (@is_writeable($pear_default_config)) { + $config->writeConfigFile($pear_default_config, 'default'); + } else { + die("You don't have write access to $pear_default_config, exiting!\n"); + } +} + +if ($store_user_config) { + $config->writeConfigFile($pear_user_config, 'userdefined'); +} + +$fallback_config = array( + 'master_server' => 'pear.php.net', + 'php_dir' => getenv('PEAR_INSTALL_DIR'), + 'ext_dir' => getenv('PEAR_EXTENSION_DIR'), + 'doc_dir' => getenv('PHP_DATADIR') . DIRECTORY_SEPARATOR . 'pear' . + DIRECTORY_SEPARATOR . 'doc', + 'verbose' => true, +); +$fallback_done = array(); + +foreach ($fallback_config as $key => $value) { + if (!$config->isDefined($key)) { + $config->set($key, $value); + $fallback_done[$key] = true; + } +} + +//$verbose = $config->get("verbose"); +$script_dir = $config->get("php_dir"); +$ext_dir = $config->get("ext_dir"); +$doc_dir = $config->get("doc_dir"); + +PEAR::setErrorHandling(PEAR_ERROR_PRINT); + +$command = (isset($options[1][1])) ? $options[1][1] : null; +$rest = array_slice($options[1], 2); + +if (isset($command_options[$command])) { + $tmp = Console_Getopt::getopt($rest, $command_options[$command]); + if (PEAR::isError($tmp)) { + usage($tmp); + } + $cmdopts = $tmp[0]; + $cmdargs = $tmp[1]; +} else { + $cmdopts = array(); + $cmdargs = $rest; +} + + +/* Extracted from pearcmd-common.php */ +function heading($text) +{ + $l = strlen(trim($text)); + print rtrim($text) . "\n" . str_repeat("=", $l) . "\n"; +} + +switch ($command) { + case 'install': + include 'pearcmd-install.php'; + break; + case 'uninstall': + include 'pearcmd-uninstall.php'; + break; + case 'list': + include 'pearcmd-list.php'; + break; + case 'package': + include 'pearcmd-package.php'; + break; + case 'remote-list': + include 'pearcmd-remote-list.php'; + break; + case 'show-config': + $keys = $config->getKeys(); + foreach ($keys as $key) { + $value = $config->get($key); + $xi = ""; + if ($config->isDefaulted($key)) { + $xi .= " (default)"; + } + if (isset($fallback_done[$key])) { + $xi .= " (built-in)"; + } + printf("%s = %s%s\n", $key, $value, $xi); + } + break; + default: { + if (!$store_default_config && !$store_user_config) { + usage(); + } + break; + } +} + +function usage($obj = null) +{ + $stderr = fopen('php://stderr', 'w'); + if ($obj !== null) { + fputs($stderr, $obj->getMessage()); + } + fputs($stderr, + "Usage: pear [options] command [command-options] <parameters>\n". + "Options:\n". + " -v increase verbosity level (default 1)\n". + " -q be quiet, decrease verbosity level\n". + " -c file find user configuration in `file'\n". + " -C file find system configuration in `file'\n". + " -d \"foo=bar\" set user config variable `foo' to `bar'\n". + " -D \"foo=bar\" set system config variable `foo' to `bar'\n". + " -s store user configuration\n". + " -S store system configuration\n". + " -u foo unset `foo' in the user configuration\n". + " -h, -? display help/usage (this message)\n". + "Commands:\n". + " help [command]\n". + " install [-r] <package file>\n". + " uninstall [-r] <package name>\n". + " package [package info file]\n". + " list\n". + " remote-list\n". + " show-config\n". + "\n"); + fclose($stderr); + exit; +} + +?>
\ No newline at end of file diff --git a/pear/template.spec b/pear/template.spec new file mode 100644 index 000000000..f6f91a524 --- /dev/null +++ b/pear/template.spec @@ -0,0 +1,68 @@ +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@/ +Prefix: %{_prefix} +#Docdir: @doc_dir@/@package@ +BuildArchitectures: @arch@ +@extra_headers@ + +%description +@description@ + +%prep +rm -rf %{buildroot}/* +# 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} \ + -s + +%build +echo BuildRoot=%{buildroot} + +%clean +[ -n "%{buildroot}" -a "%{buildroot}" != / ] && rm -rf %{buildroot} + +%postun +pear uninstall --nodeps -r @package@ + +%post +pear install --nodeps -r @rpm_xml_dir@/@package@.xml + +%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 +for DOCDIR in docs doc examples; do + if [ -d "%{buildroot}/docs/@package@/$DOCDIR" ]; then + rm -rf $RPM_BUILD_DIR/$DOCDIR + mv %{buildroot}/docs/@package@/$DOCDIR $RPM_BUILD_DIR + rm -rf %{buildroot}/docs + fi +done +mkdir -p %{buildroot}@rpm_xml_dir@ +tar -xzf $RPM_SOURCE_DIR/@package@-%{version}.tgz package.xml +cp -p package.xml %{buildroot}@rpm_xml_dir@/@package@.xml + +#rm -rf %{buildroot}/* +#pear -q install -R %{buildroot} -n package.xml +#mkdir -p %{buildroot}@rpm_xml_dir@ +#cp -p package.xml %{buildroot}@rpm_xml_dir@/@package@.xml + +%files + %defattr(-,root,root) + %doc @doc_files@ + / diff --git a/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrorMessage.php b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrorMessage.php new file mode 100644 index 000000000..1b712fc77 --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrorMessage.php @@ -0,0 +1,142 @@ +<?php + +/** + * API Unit tests for PEAR_ErrorStack package. + * + * @version $Id: Error_Stack_TestCase_getErrorMessage.php,v 1.2 2004/03/21 23:06:20 cellog Exp $ + * @author Laurent Laville <pear@laurent-laville.org> portions from HTML_CSS + * @author Greg Beaver + * @package PEAR_ErrorStack + */ + +class testgemessage +{ + function __toString() + { + return '__toString() called'; + } +} +class testgemessage1 {} +/** + * @package PEAR_ErrorStack + */ + +class Error_Stack_TestCase_getErrorMessage extends PHPUnit_TestCase +{ + + function Error_Stack_TestCase_getErrorMessage($name) + { + $this->PHPUnit_TestCase($name); + } + + function setUp() + { + error_reporting(E_ALL); + $this->errorOccured = false; + set_error_handler(array(&$this, 'errorHandler')); + $this->stack = new PEAR_ErrorStack('test'); + $s = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); + $s->pushCallback(array('PEAR_ErrorStack', '_handleError')); + } + + function tearDown() + { + unset($this->stack); + unset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON']); + } + + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->stack))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->stack)); + return false; + } + + function errorHandler($errno, $errstr, $errfile, $errline) { + //die("$errstr in $errfile at line $errline: $errstr"); + $this->errorOccured = true; + $this->assertTrue(false, "$errstr at line $errline, $errfile"); + } + + function returnsignore($err) + { + $this->wasCalled = true; + return PEAR_ERRORSTACK_IGNORE; + } + + function test_basic() + { + if (!$this->_methodExists('getErrorMessage')) { + return; + } + $msg = PEAR_ErrorStack::getErrorMessage($this->stack, + array('message' => 'boo', 'params' => array(), 'code' => 6)); + $this->assertEquals('boo', $msg); + } + + function test_basic_template() + { + if (!$this->_methodExists('getErrorMessage')) { + return; + } + $msg = PEAR_ErrorStack::getErrorMessage($this->stack, + array('message' => 'boo', 'params' => array()), 'far%__msg%'); + $this->assertEquals('farboo', $msg); + } + + function test_basic_params() + { + if (!$this->_methodExists('getErrorMessage')) { + return; + } + $msg = PEAR_ErrorStack::getErrorMessage($this->stack, array('message' => '', + 'params' => array('bar' => 'hello')), '%bar% foo'); + $this->assertEquals('hello foo', $msg, 'string'); + $msg = PEAR_ErrorStack::getErrorMessage($this->stack, array('message' => '', + 'params' => array('bar' => array('hello', 'there'))), '%bar% foo'); + $this->assertEquals('hello, there foo', $msg, 'array'); + $msg = PEAR_ErrorStack::getErrorMessage($this->stack, array('message' => '', + 'params' => array('bar' => new testgemessage)), '%bar% foo'); + $this->assertEquals('__toString() called foo', $msg, 'first object, __toString()'); + $msg = PEAR_ErrorStack::getErrorMessage($this->stack, array('message' => '', + 'params' => array('bar' => new testgemessage1)), '%bar% foo'); + $this->assertEquals('Object foo', $msg, 'second object, no __toString()'); + $errs = PEAR_ErrorStack::staticGetErrors(); + unset($errs['PEAR_ErrorStack'][0]['context']); + unset($errs['PEAR_ErrorStack'][0]['time']); + $this->assertEquals( + array('PEAR_ErrorStack' => + array( + array( + 'code' => PEAR_ERRORSTACK_ERR_OBJTOSTRING, + 'params' => array('obj' => 'testgemessage1'), + 'package' => 'PEAR_ErrorStack', + 'level' => 'warning', + 'message' => 'object testgemessage1 passed into getErrorMessage, but has no __toString() method', + ))), $errs, 'warning not raised'); + } + + function test_basic_params_with_template() + { + if (!$this->_methodExists('getErrorMessage')) { + return; + } + $this->stack->setErrorMessageTemplate(array(6 => '%bar% foo')); + $msg = PEAR_ErrorStack::getErrorMessage($this->stack, array('message' => '', + 'params' => array('bar' => 'hello'), 'code' => 6)); + $this->assertEquals('hello foo', $msg, 'string'); + $msg = PEAR_ErrorStack::getErrorMessage($this->stack, array('message' => '', + 'params' => array('bar' => 'hello'), 'code' => 7)); + $this->assertEquals('', $msg, 'string'); + } +} + +?> diff --git a/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrorMessageTemplate.php b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrorMessageTemplate.php new file mode 100644 index 000000000..80778e922 --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrorMessageTemplate.php @@ -0,0 +1,88 @@ +<?php + +/** + * API Unit tests for PEAR_ErrorStack package. + * + * @version $Id: Error_Stack_TestCase_getErrorMessageTemplate.php,v 1.2 2004/03/21 23:06:20 cellog Exp $ + * @author Laurent Laville <pear@laurent-laville.org> portions from HTML_CSS + * @author Greg Beaver + * @package PEAR_ErrorStack + */ + +/** + * @package PEAR_ErrorStack + */ + +class Error_Stack_TestCase_getErrorMessageTemplate extends PHPUnit_TestCase +{ + + function Error_Stack_TestCase_getErrorMessageTemplate($name) + { + $this->PHPUnit_TestCase($name); + } + + function setUp() + { + error_reporting(E_ALL); + $this->errorOccured = false; + set_error_handler(array(&$this, 'errorHandler')); + $this->stack = new PEAR_ErrorStack('test'); + $s = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); + $s->pushCallback(array('PEAR_ErrorStack', '_handleError')); + } + + function tearDown() + { + unset($this->stack); + unset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON']); + } + + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->stack))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->stack)); + return false; + } + + function errorHandler($errno, $errstr, $errfile, $errline) { + //die("$errstr in $errfile at line $errline: $errstr"); + $this->errorOccured = true; + $this->assertTrue(false, "$errstr at line $errline, $errfile"); + } + + function returnsignore($err) + { + $this->wasCalled = true; + return PEAR_ERRORSTACK_IGNORE; + } + + function test_normal() + { + if (!$this->_methodExists('getErrorMessageTemplate')) { + return; + } + $this->assertEquals('%__msg%', $this->stack->getErrorMessageTemplate(23)); + } + + function test_normal_hascode() + { + if (!$this->_methodExists('getErrorMessageTemplate')) { + return; + } + if (!$this->_methodExists('setErrorMessageTemplate')) { + return; + } + $this->stack->setErrorMessageTemplate(array(23 => '%foo% has %__msg%')); + $this->assertEquals('%foo% has %__msg%', $this->stack->getErrorMessageTemplate(23)); + } +} + +?> diff --git a/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrors.php b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrors.php new file mode 100644 index 000000000..fae81859b --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_getErrors.php @@ -0,0 +1,135 @@ +<?php + +/** + * API Unit tests for PEAR_ErrorStack package. + * + * @version $Id: Error_Stack_TestCase_getErrors.php,v 1.2 2004/03/21 23:06:20 cellog Exp $ + * @author Laurent Laville <pear@laurent-laville.org> portions from HTML_CSS + * @author Greg Beaver + * @package PEAR_ErrorStack + */ + +/** + * @package PEAR_ErrorStack + */ + +class Error_Stack_TestCase_getErrors extends PHPUnit_TestCase +{ + + function Error_Stack_TestCase_getErrors($name) + { + $this->PHPUnit_TestCase($name); + } + + function setUp() + { + error_reporting(E_ALL); + $this->errorOccured = false; + set_error_handler(array(&$this, 'errorHandler')); + $this->stack = new PEAR_ErrorStack('test'); + $s = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); + $s->pushCallback(array('PEAR_ErrorStack', '_handleError')); + } + + function tearDown() + { + unset($this->stack); + unset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON']); + } + + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->stack))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->stack)); + return false; + } + + function errorHandler($errno, $errstr, $errfile, $errline) { + //die("$errstr in $errfile at line $errline: $errstr"); + $this->errorOccured = true; + $this->assertTrue(false, "$errstr at line $errline, $errfile"); + } + + function returnsignore($err) + { + $this->wasCalled = true; + return PEAR_ERRORSTACK_IGNORE; + } + + function test_none() + { + if (!$this->_methodExists('getErrors')) { + return; + } + $this->assertEquals(array(), $this->stack->getErrors()); + $this->assertEquals(array(), $this->stack->getErrors(true)); + } + + function test_normal() + { + if (!$this->_methodExists('getErrors')) { + return; + } + $this->assertEquals(array(), $this->stack->getErrors()); + $this->stack->push(1); + $this->stack->push(2, 'warning'); + $this->stack->push(3, 'foo'); + $ret = $this->stack->getErrors(); + for ($i= 0; $i < 3; $i++) { + unset($ret[$i]['time']); + unset($ret[$i]['context']); + } + $this->assertEquals( + array( + array('code' => 3, + 'params' => array(), + 'package' => 'test', + 'level' => 'foo', + 'message' => ''), + array('code' => 2, + 'params' => array(), + 'package' => 'test', + 'level' => 'warning', + 'message' => ''), + array('code' => 1, + 'params' => array(), + 'package' => 'test', + 'level' => 'error', + 'message' => ''), + ), $ret, 'incorrect errors, non-purge'); + $ret = $this->stack->getErrors(true); + for ($i= 0; $i < 3; $i++) { + unset($ret[$i]['time']); + unset($ret[$i]['context']); + } + $this->assertEquals( + array( + array('code' => 3, + 'params' => array(), + 'package' => 'test', + 'level' => 'foo', + 'message' => ''), + array('code' => 2, + 'params' => array(), + 'package' => 'test', + 'level' => 'warning', + 'message' => ''), + array('code' => 1, + 'params' => array(), + 'package' => 'test', + 'level' => 'error', + 'message' => ''), + ), $ret, 'incorrect errors, purge'); + $this->assertEquals(array(), $this->stack->getErrors()); + } +} + +?> diff --git a/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpop.php b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpop.php new file mode 100644 index 000000000..f8452af3f --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpop.php @@ -0,0 +1,367 @@ +<?php + +/** + * API Unit tests for PEAR_ErrorStack package. + * + * @version $Id: Error_Stack_TestCase_pushpop.php,v 1.2 2004/03/21 23:06:20 cellog Exp $ + * @author Laurent Laville <pear@laurent-laville.org> portions from HTML_CSS + * @author Greg Beaver + * @package PEAR_ErrorStack + */ + +/** + * @package PEAR_ErrorStack + */ + +class Error_Stack_TestCase_pushpop extends PHPUnit_TestCase +{ + /** + * A PEAR_PackageFileManager object + * @var object + */ + var $packagexml; + + function Error_Stack_TestCase_pushpop($name) + { + $this->PHPUnit_TestCase($name); + } + + function setUp() + { + error_reporting(E_ALL); + $this->errorOccured = false; + set_error_handler(array(&$this, 'errorHandler')); + $this->stack = new PEAR_ErrorStack('test'); + $s = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); + $s->pushCallback(array('PEAR_ErrorStack', '_handleError')); + } + + function tearDown() + { + unset($this->stack); + unset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON']); + } + + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->stack))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->stack)); + return false; + } + + function errorHandler($errno, $errstr, $errfile, $errline) { + //die("$errstr in $errfile at line $errline: $errstr"); + $this->errorOccured = true; + $this->assertTrue(false, "$errstr at line $errline, $errfile"); + } + + function test_valid_basic() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack->push(1); + $err = $this->stack->pop(); + unset($err['context']); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_params() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $z = $this->stack->push(2, 'exception', array('my' => 'param'), 'hello', + array('test'), array(array('file' => 'boof', 'line' => 34))); + $err = $this->stack->pop('exception'); + $this->assertEquals($z, $err, 'popped different error'); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 2, + 'params' => array('my' => 'param'), + 'package' => 'test', + 'message' => 'hello', + 'level' => 'exception', + 'context' => + array( + 'file' => 'boof', + 'line' => 34, + ), + 'repackage' => array('test'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_paramscompat() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack = new PEAR_ErrorStack('test', false, null, true); + $z = $this->stack->push(2, 'exception', array('my' => 'param'), 'hello', + array('test'), array(array('file' => 'boof', 'line' => 34))); + $this->assertEquals('pear_error', strtolower(get_class($z)), 'not pear_error'); + $err = $this->stack->pop('exception'); + if (is_a($z, 'PEAR_Error')) { + $this->assertEquals($err, $z->getUserInfo(), 'userinfo wrong'); + } + unset($err['time']); + $this->assertEquals( + array( + 'code' => 2, + 'params' => array('my' => 'param'), + 'package' => 'test', + 'message' => 'hello', + 'level' => 'exception', + 'context' => + array( + 'file' => 'boof', + 'line' => 34, + ), + 'repackage' => array('test'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function contextcallback($code, $params, $trace) + { + $this->assertEquals(4, $code, 'wrong context code'); + $this->assertEquals(array('hello' => 6), $params, 'wrong context params'); + $this->wasCalled = true; + return array('hi' => 'there', 'you' => 'fool'); + } + + function test_valid_contextconstructor() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack = new PEAR_ErrorStack('test', false, array(&$this, 'contextcallback')); + $this->wasCalled = false; + $this->stack->push(4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'context callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + 'context' => array('hi' => 'there', 'you' => 'fool'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_contextsingleton() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test', false, array(&$this, 'contextcallback')); + $this->wasCalled = false; + $this->stack->push(4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'context callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + 'context' => array('hi' => 'there', 'you' => 'fool'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_context_setcontext() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('setContextCallback')) { + return; + } + $this->stack->setContextCallback(array(&$this, 'contextcallback')); + $this->wasCalled = false; + $this->stack->push(4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'context callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + 'context' => array('hi' => 'there', 'you' => 'fool'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function messagecallback(&$stack, $err) + { + $this->assertEquals(4, $err['code'], 'wrong message code'); + $this->assertEquals(array('hello' => 6), $err['params'], 'wrong message params'); + $this->assertEquals('test1', $err['package'], 'wrong error stack'); + $this->wasCalled = true; + return 'my silly message'; + } + + function test_valid_msgcallbackconstructor() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack = new PEAR_ErrorStack('test1', array(&$this, 'messagecallback')); + $this->wasCalled = false; + $this->stack->push(4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'message callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + unset($err['context']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test1', + 'message' => 'my silly message', + 'level' => 'error', + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_msgcallbacksingleton() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test1', array(&$this, 'messagecallback')); + $this->wasCalled = false; + $this->stack->push(4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'message callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + unset($err['context']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test1', + 'message' => 'my silly message', + 'level' => 'error', + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_msgcallback_setmsgcallback() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('setContextCallback')) { + return; + } + $this->stack = new PEAR_ErrorStack('test1'); + $this->stack->setMessageCallback(array(&$this, 'messagecallback')); + $this->wasCalled = false; + $this->stack->push(4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'message callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + unset($err['context']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test1', + 'message' => 'my silly message', + 'level' => 'error', + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } +} + +?> diff --git a/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpopcallback.php b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpopcallback.php new file mode 100644 index 000000000..a91313dd9 --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpopcallback.php @@ -0,0 +1,320 @@ +<?php + +/** + * API Unit tests for PEAR_ErrorStack package. + * + * @version $Id: Error_Stack_TestCase_pushpopcallback.php,v 1.2 2004/03/21 23:06:20 cellog Exp $ + * @author Laurent Laville <pear@laurent-laville.org> portions from HTML_CSS + * @author Greg Beaver + * @package PEAR_ErrorStack + */ + +/** + * @package PEAR_ErrorStack + */ + +class Error_Stack_TestCase_pushpopcallback extends PHPUnit_TestCase +{ + /** + * A PEAR_PackageFileManager object + * @var object + */ + var $packagexml; + + function Error_Stack_TestCase_pushpopcallback($name) + { + $this->PHPUnit_TestCase($name); + } + + function setUp() + { + error_reporting(E_ALL); + $this->errorOccured = false; + set_error_handler(array(&$this, 'errorHandler')); + $this->stack = new PEAR_ErrorStack('test'); + } + + function tearDown() + { + unset($this->stack); + unset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON']); + } + + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->stack))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->stack)); + return false; + } + + function errorHandler($errno, $errstr, $errfile, $errline) { + //die("$errstr in $errfile at line $errline: $errstr"); + $this->errorOccured = true; + $this->assertTrue(false, "$errstr at line $errline, $errfile"); + } + + function returnsignore($err) + { + $this->wasCalled = true; + return PEAR_ERRORSTACK_IGNORE; + } + + function test_return_ignore() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('pushCallback')) { + return; + } + if (!$this->_methodExists('popCallback')) { + return; + } + $this->stack->pushCallback(array(&$this, 'returnsignore')); + $this->wasCalled = false; + $this->stack->push(1); + $this->assertTrue($this->wasCalled, 'returnsignore not called'); + $err = $this->stack->pop(); + $this->assertFalse($err, 'error was not ignored!'); + $this->stack->popCallback(); + $this->wasCalled = false; + $this->stack->push(1); + $this->assertFalse($this->wasCalled, 'returnsignore called'); + $err = $this->stack->pop(); + unset($err['context']); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + ), + $err, 'popped something else' + ); + + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function returnsnothing($err) + { + $this->wasCalled = true; + } + + function test_return_nothing() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('pushCallback')) { + return; + } + if (!$this->_methodExists('popCallback')) { + return; + } + $this->stack->pushCallback(array(&$this, 'returnsnothing')); + $this->wasCalled = false; + $this->stack->push(1); + $this->assertTrue($this->wasCalled, 'returnsnothing not called'); + $err = $this->stack->pop(); + unset($err['context']); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + ), + $err, 'popped something else' + ); + $this->stack->popCallback(); + $this->wasCalled = false; + $this->stack->push(1); + $this->assertFalse($this->wasCalled, 'returnsnothing called'); + $err = $this->stack->pop(); + unset($err['context']); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + ), + $err, 'popped something else' + ); + + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function returnspush($err) + { + $this->wasCalled = true; + return PEAR_ERRORSTACK_PUSH; + } + + function test_return_push() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('pushCallback')) { + return; + } + if (!$this->_methodExists('popCallback')) { + return; + } + if (!$this->_methodExists('setLogger')) { + return; + } + $this->stack->pushCallback(array(&$this, 'returnspush')); + $log = new BurfLog; + $log->setTestCase($this); + $log->curMethod(__FUNCTION__); + $this->stack->setLogger($log); + $this->wasCalled = false; + $this->stack->push(1); + $this->assertTrue($this->wasCalled, 'returnspush not called'); + $err = $this->stack->pop(); + unset($err['context']); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + ), + $err, 'popped something else 1' + ); + $this->stack->popCallback(); + $log->pushExpect('', PEAR_LOG_ERR, array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + )); + $this->wasCalled = false; + $this->wasLogged = false; + $this->stack->push(1); + $this->assertFalse($this->wasCalled, 'returnspush called'); + $this->assertTrue($this->wasLogged, 'was not logged!'); + $err = $this->stack->pop(); + unset($err['context']); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + ), + $err, 'popped something else 2' + ); + + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function returnslog($err) + { + $this->wasCalled = true; + return PEAR_ERRORSTACK_LOG; + } + + function test_return_log() + { + if (!$this->_methodExists('push')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('pushCallback')) { + return; + } + if (!$this->_methodExists('popCallback')) { + return; + } + if (!$this->_methodExists('setLogger')) { + return; + } + $this->stack->pushCallback(array(&$this, 'returnslog')); + $log = new BurfLog; + $log->setTestCase($this); + $log->curMethod(__FUNCTION__); + $this->stack->setLogger($log); + $this->wasCalled = false; + $this->wasLogged = false; + $log->pushExpect('', PEAR_LOG_ERR, array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + )); + $this->stack->push(1); + $this->assertTrue($this->wasCalled, 'returnslog not called'); + $this->assertTrue($this->wasLogged, 'was not logged!'); + $err = $this->stack->pop(); + $this->assertFalse($err, 'an error was pushed!'); + $this->stack->popCallback(); + $log->clearExpect(); + $log->pushExpect('', PEAR_LOG_ERR, array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + )); + $this->wasCalled = false; + $this->wasLogged = false; + $this->stack->push(1); + $this->assertFalse($this->wasCalled, 'returnspush called'); + $this->assertTrue($this->wasLogged, 'was not logged!'); + $err = $this->stack->pop(); + unset($err['context']); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + ), + $err, 'popped something else 2' + ); + + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } +} + +?> diff --git a/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpopstatic.php b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpopstatic.php new file mode 100644 index 000000000..c9a45c3a4 --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_pushpopstatic.php @@ -0,0 +1,327 @@ +<?php + +/** + * API Unit tests for PEAR_ErrorStack package. + * + * @version $Id: Error_Stack_TestCase_pushpopstatic.php,v 1.2 2004/03/21 23:06:20 cellog Exp $ + * @author Laurent Laville <pear@laurent-laville.org> portions from HTML_CSS + * @author Greg Beaver + * @package PEAR_ErrorStack + */ + +/** + * @package PEAR_ErrorStack + */ + +class Error_Stack_TestCase_pushpopstatic extends PHPUnit_TestCase +{ + /** + * A PEAR_PackageFileManager object + * @var object + */ + var $packagexml; + + function Error_Stack_TestCase_pushpopstatic($name) + { + $this->PHPUnit_TestCase($name); + } + + function setUp() + { + error_reporting(E_ALL); + $this->errorOccured = false; + set_error_handler(array(&$this, 'errorHandler')); + $this->stack = new PEAR_ErrorStack(''); + $s = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); + $s->pushCallback(array('PEAR_ErrorStack', '_handleError')); + } + + function tearDown() + { + unset($this->stack); + unset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON']); + } + + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->stack))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->stack)); + return false; + } + + function errorHandler($errno, $errstr, $errfile, $errline) { + //die("$errstr in $errfile at line $errline: $errstr"); + $this->errorOccured = true; + $this->assertTrue(false, "$errstr at line $errline, $errfile"); + } + + function test_valid_basic() + { + if (!$this->_methodExists('staticPush')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test'); + PEAR_ErrorStack::staticPush('test', 1); + $err = $this->stack->pop(); + unset($err['context']); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 1, + 'params' => array(), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_params() + { + if (!$this->_methodExists('staticPush')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test'); + $z = PEAR_ErrorStack::staticPush('test', 2, 'exception', array('my' => 'param'), 'hello', + array('test'), array(array('file' => 'boof', 'line' => 34))); + $err = $this->stack->pop('exception'); + $this->assertEquals($z, $err, 'popped different error'); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 2, + 'params' => array('my' => 'param'), + 'package' => 'test', + 'message' => 'hello', + 'level' => 'exception', + 'context' => + array( + 'file' => 'boof', + 'line' => 34, + ), + 'repackage' => array('test'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_paramscompat() + { + if (!$this->_methodExists('staticPush')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test', false, null, 'PEAR_ErrorStack', true); + $z = PEAR_ErrorStack::staticPush('test', 2, 'exception', array('my' => 'param'), 'hello', + array('test'), array(array('file' => 'boof', 'line' => 34))); + $this->assertEquals('pear_error', strtolower(get_class($z)), 'not pear_error'); + $err = $this->stack->pop('exception'); + if (is_a($z, 'PEAR_Error')) { + $this->assertEquals($err, $z->getUserInfo(), 'userinfo wrong'); + } + unset($err['time']); + $this->assertEquals( + array( + 'code' => 2, + 'params' => array('my' => 'param'), + 'package' => 'test', + 'message' => 'hello', + 'level' => 'exception', + 'context' => + array( + 'file' => 'boof', + 'line' => 34, + ), + 'repackage' => array('test'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function contextcallback($code, $params, $trace) + { + $this->assertEquals(4, $code, 'wrong context code'); + $this->assertEquals(array('hello' => 6), $params, 'wrong context params'); + $this->wasCalled = true; + return array('hi' => 'there', 'you' => 'fool'); + } + + function test_valid_contextsingleton() + { + if (!$this->_methodExists('staticPush')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test', false, array(&$this, 'contextcallback')); + $this->wasCalled = false; + PEAR_ErrorStack::staticPush('test', 4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'context callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + 'context' => array('hi' => 'there', 'you' => 'fool'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_context_setcontext() + { + if (!$this->_methodExists('staticPush')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('setContextCallback')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test'); + $this->stack->setContextCallback(array(&$this, 'contextcallback')); + $this->wasCalled = false; + PEAR_ErrorStack::staticPush('test', 4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'context callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test', + 'message' => '', + 'level' => 'error', + 'context' => array('hi' => 'there', 'you' => 'fool'), + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function messagecallback(&$stack, $err) + { + $this->assertEquals(4, $err['code'], 'wrong message code'); + $this->assertEquals(array('hello' => 6), $err['params'], 'wrong message params'); + $this->assertEquals('test1', $err['package'], 'wrong error stack'); + $this->wasCalled = true; + return 'my silly message'; + } + + function test_valid_msgcallbacksingleton() + { + if (!$this->_methodExists('staticPush')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test1', array(&$this, 'messagecallback')); + $this->wasCalled = false; + PEAR_ErrorStack::staticPush('test1', 4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'message callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + unset($err['context']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test1', + 'message' => 'my silly message', + 'level' => 'error', + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } + + function test_valid_msgcallback_setmsgcallback() + { + if (!$this->_methodExists('staticPush')) { + return; + } + if (!$this->_methodExists('singleton')) { + return; + } + if (!$this->_methodExists('pop')) { + return; + } + if (!$this->_methodExists('setContextCallback')) { + return; + } + $this->stack = &PEAR_ErrorStack::singleton('test1'); + $this->stack->setMessageCallback(array(&$this, 'messagecallback')); + $this->wasCalled = false; + PEAR_ErrorStack::staticPush('test1', 4, 'error', array('hello' => 6)); + $this->assertTrue($this->wasCalled, 'message callback was not called!'); + $err = $this->stack->pop(); + unset($err['time']); + unset($err['context']); + $this->assertEquals( + array( + 'code' => 4, + 'params' => array('hello' => 6), + 'package' => 'test1', + 'message' => 'my silly message', + 'level' => 'error', + ), + $err, 'popped something else' + ); + $err = $this->stack->pop(); + $this->assertFalse($err, 'stack not empty!'); + } +} + +?> diff --git a/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_singleton.php b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_singleton.php new file mode 100644 index 000000000..1eff7c6cf --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_singleton.php @@ -0,0 +1,93 @@ +<?php + +/** + * API Unit tests for PEAR_ErrorStack package. + * + * @version $Id: Error_Stack_TestCase_singleton.php,v 1.2 2004/03/21 23:06:20 cellog Exp $ + * @author Laurent Laville <pear@laurent-laville.org> portions from HTML_CSS + * @author Greg Beaver + * @package PEAR_ErrorStack + */ + +/** + * @package PEAR_ErrorStack + */ + +class Error_Stack_TestCase_singleton extends PHPUnit_TestCase +{ + /** + * A PEAR_PackageFileManager object + * @var object + */ + var $packagexml; + + function Error_Stack_TestCase_singleton($name) + { + $this->PHPUnit_TestCase($name); + } + + function setUp() + { + error_reporting(E_ALL); + $this->errorOccured = false; + set_error_handler(array(&$this, 'errorHandler')); + $this->stack = new PEAR_ErrorStack(''); + $s = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); + $s->pushCallback(array('PEAR_ErrorStack', '_handleError')); + } + + function tearDown() + { + } + + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->stack))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->stack)); + return false; + } + + function errorHandler($errno, $errstr, $errfile, $errline) { + //die("$errstr in $errfile at line $errline: $errstr"); + $this->errorOccured = true; + $this->assertTrue(false, "$errstr at line $errline, $errfile"); + } + + function test_valid_singleton() + { + if (!$this->_methodExists('singleton')) { + return; + } + $one = &PEAR_ErrorStack::singleton('first'); + $two = &PEAR_ErrorStack::singleton('first'); + $two->testme = 2; + $this->assertEquals(2, $two->testme, 'duh test'); + $one->testme = 4; + $this->assertEquals(4, $one->testme, 'duh test 2'); + $this->assertEquals(4, $two->testme, 'same object test'); + } + + function test_invalid_singleton() + { + if (!$this->_methodExists('singleton')) { + return; + } + $one = &PEAR_ErrorStack::singleton('first'); + $two = &PEAR_ErrorStack::singleton('second'); + $two->testme = 2; + $this->assertEquals(2, $two->testme, 'duh test'); + $one->testme = 4; + $this->assertEquals(4, $one->testme, 'duh test 2'); + $this->assertEquals(2, $two->testme, 'not same object test'); + } +} + +?> diff --git a/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_staticGetErrors.php b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_staticGetErrors.php new file mode 100644 index 000000000..596cc8659 --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/Error_Stack_TestCase_staticGetErrors.php @@ -0,0 +1,225 @@ +<?php + +/** + * API Unit tests for PEAR_ErrorStack package. + * + * @version $Id: Error_Stack_TestCase_staticGetErrors.php,v 1.3 2004/05/21 03:33:51 cellog Exp $ + * @author Laurent Laville <pear@laurent-laville.org> portions from HTML_CSS + * @author Greg Beaver + * @package PEAR_ErrorStack + */ + +/** + * @package PEAR_ErrorStack + */ + +class Error_Stack_TestCase_staticGetErrors extends PHPUnit_TestCase +{ + + function Error_Stack_TestCase_staticGetErrors($name) + { + $this->PHPUnit_TestCase($name); + } + + function setUp() + { + error_reporting(E_ALL); + $this->errorOccured = false; + set_error_handler(array(&$this, 'errorHandler')); + $this->stack = &PEAR_ErrorStack::singleton('test'); + $s = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); + $s->pushCallback(array('PEAR_ErrorStack', '_handleError')); + } + + function tearDown() + { + unset($this->stack); + unset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON']); + } + + + function _stripWhitespace($str) + { + return preg_replace('/\\s+/', '', $str); + } + + function _methodExists($name) + { + if (in_array(strtolower($name), get_class_methods($this->stack))) { + return true; + } + $this->assertTrue(false, 'method '. $name . ' not implemented in ' . get_class($this->stack)); + return false; + } + + function errorHandler($errno, $errstr, $errfile, $errline) { + //die("$errstr in $errfile at line $errline: $errstr"); + $this->errorOccured = true; + $this->assertTrue(false, "$errstr at line $errline, $errfile"); + } + + function returnsignore($err) + { + $this->wasCalled = true; + return PEAR_ERRORSTACK_IGNORE; + } + + function test_none() + { + if (!$this->_methodExists('staticGetErrors')) { + return; + } + $this->assertEquals(array(), PEAR_ErrorStack::staticGetErrors()); + $this->assertEquals(array(), PEAR_ErrorStack::staticGetErrors(true)); + } + + function test_normal() + { + if (!$this->_methodExists('staticGetErrors')) { + return; + } + $this->assertEquals(array(), PEAR_ErrorStack::staticGetErrors()); + $this->stack->push(1); + $this->stack->push(2, 'warning'); + $this->stack->push(3, 'foo'); + $ret = PEAR_ErrorStack::staticGetErrors(); + for ($i= 0; $i < 3; $i++) { + unset($ret['test'][$i]['time']); + unset($ret['test'][$i]['context']); + } + $this->assertEquals( + array( 'test' => array( + array('code' => 3, + 'params' => array(), + 'package' => 'test', + 'level' => 'foo', + 'message' => ''), + array('code' => 2, + 'params' => array(), + 'package' => 'test', + 'level' => 'warning', + 'message' => ''), + array('code' => 1, + 'params' => array(), + 'package' => 'test', + 'level' => 'error', + 'message' => ''), + )), $ret, 'incorrect errors, non-purge'); + $ret = PEAR_ErrorStack::staticGetErrors(true); + for ($i= 0; $i < 3; $i++) { + unset($ret['test'][$i]['time']); + unset($ret['test'][$i]['context']); + } + $this->assertEquals( + array( 'test' => array( + array('code' => 3, + 'params' => array(), + 'package' => 'test', + 'level' => 'foo', + 'message' => ''), + array('code' => 2, + 'params' => array(), + 'package' => 'test', + 'level' => 'warning', + 'message' => ''), + array('code' => 1, + 'params' => array(), + 'package' => 'test', + 'level' => 'error', + 'message' => ''), + )), $ret, 'incorrect errors, purge'); + $this->assertEquals(array(), PEAR_ErrorStack::staticGetErrors()); + } + + function test_merge() + { + if (!$this->_methodExists('staticGetErrors')) { + return; + } + $this->assertEquals(array(), PEAR_ErrorStack::staticGetErrors()); + $this->stack->push(1); + for($i=0;$i<10000;$i++); + $this->stack->push(2, 'warning'); + for($i=0;$i<10000;$i++); + PEAR_ErrorStack::staticPush('fronk', 3, 'foo'); + $ret = PEAR_ErrorStack::staticGetErrors(true, false, true); + for ($i= 0; $i < 3; $i++) { + unset($ret[$i]['time']); + unset($ret[$i]['context']); + } + $this->assertEquals( + array( + array('code' => 3, + 'params' => array(), + 'package' => 'fronk', + 'level' => 'foo', + 'message' => ''), + array('code' => 2, + 'params' => array(), + 'package' => 'test', + 'level' => 'warning', + 'message' => ''), + array('code' => 1, + 'params' => array(), + 'package' => 'test', + 'level' => 'error', + 'message' => ''), + ), $ret, 'incorrect errors, non-purge'); + $test = PEAR_ErrorStack::staticGetErrors(); + $this->assertEquals(array(), $test, 'normal array'); + } + + function _sortErrorsRev($a, $b) + { + $this->wasCalled = true; + if ($a['time'] == $b['time']) { + return 0; + } + if ($a['time'] < $b['time']) { + return -1; + } + return 1; + } + + function test_merge_sortfunc() + { + if (!$this->_methodExists('staticGetErrors')) { + return; + } + $this->assertEquals(array(), PEAR_ErrorStack::staticGetErrors()); + $this->stack->push(1); + for($i=0;$i<10000;$i++); + $this->stack->push(2, 'warning'); + for($i=0;$i<10000;$i++); + PEAR_ErrorStack::staticPush('fronk', 3, 'foo'); + $this->wasCalled = false; + $ret = PEAR_ErrorStack::staticGetErrors(true, false, true, array(&$this, '_sortErrorsRev')); + $this->assertTrue($this->wasCalled, '_sortErrorsRev not called!'); + for ($i= 0; $i < 3; $i++) { + unset($ret[$i]['time']); + unset($ret[$i]['context']); + } + $this->assertEquals( + array( + array('code' => 1, + 'params' => array(), + 'package' => 'test', + 'level' => 'error', + 'message' => ''), + array('code' => 2, + 'params' => array(), + 'package' => 'test', + 'level' => 'warning', + 'message' => ''), + array('code' => 3, + 'params' => array(), + 'package' => 'fronk', + 'level' => 'foo', + 'message' => ''), + ), $ret, 'incorrect errors, non-purge'); + $test = PEAR_ErrorStack::staticGetErrors(); + $this->assertEquals(array(), $test, 'normal array'); + } +} + +?> diff --git a/pear/tests/PEAR_ErrorStack/HTML_TestListener.php b/pear/tests/PEAR_ErrorStack/HTML_TestListener.php new file mode 100644 index 000000000..3764d7cf8 --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/HTML_TestListener.php @@ -0,0 +1,64 @@ +<?php + +/** + * Provides a nice HTML output for PHPUnit suite tests. + * + * @version $Id: HTML_TestListener.php,v 1.1 2004/03/19 00:48:39 cellog Exp $ + * @author Laurent Laville <pear@laurent-laville.org> + * @package HTML_CSS + */ + +class HTML_TestListener extends PHPUnit_TestListener { + + function HTML_TestListener() { + +$report = <<<EOS +<table cellspacing="1" cellpadding="1" border="0" width="90%" align="center" class="details"> +<tr><th>Class</th><th>Function</th><th>Success</th><th>Meta-result</th></tr> +EOS; + echo $report; + } + + function addError(&$test, &$t) { + $this->_errors += 1; + } + + function addFailure(&$test, &$t) { + $this->_fails += 1; + } + + function endTest(&$test) { + /* Report both the test result and, for this special situation + where some tests are expected to fail, a "meta" test result + which indicates whether the test result matches the + expected result. + */ + $expect_failure = preg_match('/fail/i', $test->getName()); + $test_passed = ($this->_fails == 0 && $this->_errors == 0); + + if ($this->_errors > 0) { + $outcome = "<span class=\"Error\">ERROR</span>"; + } else if ($this->_fails > 0) { + $outcome = "<span class=\"Failure\">FAIL</span>"; + } else { + $outcome = "<span class=\"Pass\">OK</span>"; + } + if ($this->_errors > 0) { + $meta_outcome = '<span class="Unknown">unknown</span>'; + } else { + $meta_outcome = ($expect_failure xor $test_passed) + ? '<span class="Expected">as expected</span>' + : '<span class="Unexpected">UNEXPECTED</span>'; + } + printf("<td>$outcome</td><td>$meta_outcome</td></tr>"); + } + + function startTest(&$test) { + $this->_fails = 0; + $this->_errors = 0; + printf("<tr><td>%s </td><td>%s </td>", get_class($test), $test->getName()); + } + + +} +?>
\ No newline at end of file diff --git a/pear/tests/PEAR_ErrorStack/TestUnit.php b/pear/tests/PEAR_ErrorStack/TestUnit.php new file mode 100644 index 000000000..5acd102e3 --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/TestUnit.php @@ -0,0 +1,55 @@ +<?php + +/** + * TestUnit runs a TestSuite and returns a TestResult object. + * And more than PHPUnit attach a listener to TestResult. + * + * @version $Id: TestUnit.php,v 1.1 2004/03/19 00:48:39 cellog Exp $ + * @author Laurent Laville <pear@laurent-laville.org> + * @package HTML_CSS + */ + +require_once 'PHPUnit.php'; + +class TestUnit extends PHPUnit { + + function &run(&$suite, $listener) { + $result = new TestResult(); + $result->addListener($listener); + $suite->run($result); + + return $result; + } +} + +class TestResult extends PHPUnit_TestResult { + + /* report result of test run */ + function report() { + echo "</TABLE>"; + + $nRun = $this->runCount(); + $nErrors = $this->errorCount(); + $nFailures = $this->failureCount(); + echo "<h2>Summary</h2>"; + + printf("<p>%s test%s run.<br>", $nRun, ($nRun > 1) ? 's' : ''); + printf("%s error%s.<br>\n", $nErrors, ($nErrors > 1) ? 's' : ''); + printf("%s failure%s.<br>\n", $nFailures, ($nFailures > 1) ? 's' : ''); + if ($nFailures > 0) { + echo "<h2>Failure Details</h2>"; + print("<ol>\n"); + $failures = $this->failures(); + while (list($i, $failure) = each($failures)) { + $failedTest = $failure->failedTest(); + printf("<li>%s\n", $failedTest->getName() ); + print("<ul>"); + printf("<li>%s\n", $failure->thrownException() ); + print("</ul>"); + } + print("</ol>\n"); + } + } + +} +?> diff --git a/pear/tests/PEAR_ErrorStack/base_regression.php b/pear/tests/PEAR_ErrorStack/base_regression.php new file mode 100644 index 000000000..d11c04191 --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/base_regression.php @@ -0,0 +1,550 @@ +<?php +// $Revision: 1.1 $ +/** + * Basic regression test for PEAR_ErrorStack::getFileLine() + * + * phpUnit can't test global code properly because of its design, so I designed + * this instead + * @package PEAR_ErrorStack + * @subpackage tests + * @author Greg Beaver <cellog@php.net> + */ +require_once 'PEAR/ErrorStack.php'; +$result = array( +'passed' => array(), +'failed' => array() +); +$stack = &PEAR_ErrorStack::singleton('test'); +$testNumber = 1; +// test basic global file/line +$stack->push(3); +$testline = __LINE__ - 1; + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'function' => 'include_once', + 'line' => $testline)); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test basic in-function file/line #2 +function testfunc() { global $stack, $testline; +$stack->push(3); +$testline = __LINE__ - 1; +} +testfunc(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'testfunc')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test basic in-static method file/line #3 +class stclass { +function stfunc() { global $stack, $testline; +$stack->push(3); +$testline = __LINE__ - 1; +} +} +stclass::stfunc(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'stfunc', + 'class' => 'stclass')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test basic in-method file/line #4 +class normalclass { +function normalfunc() { global $stack, $testline; +$stack->push(3); +$testline = __LINE__ - 1; +} +} +$z = new normalclass; +$z->normalfunc(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'normalfunc', + 'class' => 'normalclass')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test global eval file/line #5 +eval('$stack->push(3);'); +$testline = __LINE__ - 1; + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'function' => 'include_once', + 'line' => $testline)); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test in-function eval file/line #6 +function test2() { + global $testline, $stack; +eval('$stack->push(3);'); +$testline = __LINE__ - 1; +} +test2(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'test2')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test in-static method eval file/line #7 +class test3 { +function test3() { + global $testline, $stack; +eval('$stack->push(3);'); +$testline = __LINE__ - 1; +} +} +test3::test3(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'test3', + 'class' => 'test3')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test in-method eval file/line #8 +class test4 { +function test4() { + global $testline, $stack; +eval('$stack->push(3);'); +$testline = __LINE__ - 1; +} +} +$z = new test4; +$z->test4(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'test4', + 'class' => 'test4')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test global create_function file/line #9 +$a = create_function('', '$GLOBALS["stack"]->push(3);'); +$testline = __LINE__ - 1; +$a(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'create_function() code')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test in-function create_function file/line #10 +function test7() { global $a; +$a(); +} +test7(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'create_function() code')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test in-static method create_function file/line #11 +class test8 { +function test8() { global $a; +$a(); +} +} +test8::test8(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'create_function() code')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test in-method create_function file/line #12 +class test9 { +function test9() { global $a; +$a(); +} +} +$z = new test9; +$z->test9(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'create_function() code')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$result['number'] = $testNumber; + +$testNumber++; +// test static basic global file/line #13 +PEAR_ErrorStack::staticPush('test', 3); +$testline = __LINE__ - 1; + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'function' => 'include_once', + 'line' => $testline)); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static basic in-function file/line #14 +function testfunc2() { global $stack, $testline; +PEAR_ErrorStack::staticPush('test', 3); +$testline = __LINE__ - 1; +} +testfunc2(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'testfunc2')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static basic in-static method file/line #15 +class stclass2 { +function stfunc() { global $stack, $testline; +PEAR_ErrorStack::staticPush('test', 3); +$testline = __LINE__ - 1; +} +} +stclass2::stfunc(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'stfunc', + 'class' => 'stclass2')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static basic in-method file/line #16 +class normalclass2 { +function normalfunc() { global $stack, $testline; +PEAR_ErrorStack::staticPush('test', 3); +$testline = __LINE__ - 1; +} +} +$z = new normalclass2; +$z->normalfunc(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'normalfunc', + 'class' => 'normalclass2')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static global eval file/line #17 +eval('PEAR_ErrorStack::staticPush(\'test\', 3);'); +$testline = __LINE__ - 1; + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'function' => 'include_once', + 'line' => $testline)); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static in-function eval file/line #18 +function test22() { + global $testline, $stack; +eval('PEAR_ErrorStack::staticPush("test", 3);'); +$testline = __LINE__ - 1; +} +test22(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'test22')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static in-static method eval file/line #19 +class test32 { +function test3() { + global $testline, $stack; +eval('PEAR_ErrorStack::staticPush(\'test\',3);'); +$testline = __LINE__ - 1; +} +} +test32::test3(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'test3', + 'class' => 'test32')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static in-method eval file/line #20 +class test42 { +function test4() { + global $testline, $stack; +eval('PEAR_ErrorStack::staticPush(\'test\',3);'); +$testline = __LINE__ - 1; +} +} +$z = new test42; +$z->test4(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'test4', + 'class' => 'test42')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static global create_function file/line #21 +$a = create_function('', 'PEAR_ErrorStack::staticPush("test",3);'); +$testline = __LINE__ - 1; +$a(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'create_function() code')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static in-function create_function file/line #22 +function test72() { global $a; +$a(); +} +test72(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'create_function() code')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static in-static method create_function file/line #23 +class test82 { +function test8() { global $a; +$a(); +} +} +test82::test8(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'create_function() code')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$testNumber++; +// test static in-method create_function file/line #24 +class test92 { +function test9() { global $a; +$a(); +} +} +$z = new test92; +$z->test9(); + +$ret = $stack->pop(); +$diff = array_diff_assoc($ret['context'], +array('file' => __FILE__, + 'line' => $testline, + 'function' => 'create_function() code')); + +if ($diff !== array()) { + $result['failed'][$testNumber] = $diff; +} else { + $result['passed'][$testNumber] = true; +} + +$result['number'] = $testNumber; + +return $result; +/** + * Utility function + */ +function isIncludeable($path) +{ + if (file_exists(realpath($path)) && is_readable(realpath($path))) { + return true; + } + foreach (explode(PATH_SEPARATOR, get_include_path()) as $prepend) { + $test = realpath($prepend . DIRECTORY_SEPARATOR . $path); + if (file_exists($test) && is_readable($test)) { + return true; + } + } +} +/** + * Mock PHPUnit object + */ +class Mock_PHPUnit { + var $name; + function getName() + { + return 'base regression test ' . $this->name; + } +} +?>
\ No newline at end of file diff --git a/pear/tests/PEAR_ErrorStack/stylesheet.css b/pear/tests/PEAR_ErrorStack/stylesheet.css new file mode 100644 index 000000000..f7588291b --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/stylesheet.css @@ -0,0 +1,65 @@ +/* $Id: stylesheet.css,v 1.1 2004/03/19 00:48:39 cellog Exp $ */ + +body { + font:normal 68% verdana,arial,helvetica; + color:#000000; +} +table tr td, table tr th { + font-size: 68%; +} +table.details tr th{ + font-weight: bold; + text-align:left; + background:#a6caf0; +} +table.details tr{ + background:#eeeee0; +} + +p { + line-height:1.5em; + margin-top:0.5em; margin-bottom:1.0em; +} +h1 { + margin: 0px 0px 5px; font: 165% verdana,arial,helvetica +} +h2 { + margin-top: 1em; margin-bottom: 0.5em; font: bold 125% verdana,arial,helvetica +} +h3 { + margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica +} +h4 { + margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica +} +h5 { + margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica +} +h6 { + margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica +} +.Error { + font-weight:bold; color:red; +} +.Failure, .Unexpected { + background:#ff0000; font-weight:bold; color:black; +} +.Unknown { + background:#ffff00; font-weight:bold; color:black; +} +.Pass, .Expected { + background:#00ff00; font-weight:bold; color:black; +} +.Properties { + text-align:right; +} + +CODE.expected { + color: green; background: none; font-weight: normal; +} +CODE.actual { + color: red; background: none; font-weight: normal; +} +.typeinfo { + color: gray; +} diff --git a/pear/tests/PEAR_ErrorStack/testsuite.php b/pear/tests/PEAR_ErrorStack/testsuite.php new file mode 100644 index 000000000..d3f25ba53 --- /dev/null +++ b/pear/tests/PEAR_ErrorStack/testsuite.php @@ -0,0 +1,152 @@ +<?php + +/** + * HTML output for PHPUnit suite tests. + * + * Copied for PEAR_PackageFileManager from HTML_CSS + * @version $Id: testsuite.php,v 1.2 2004/03/21 23:06:20 cellog Exp $ + * @author Laurent Laville <pear@laurent-laville.org> + * @package HTML_CSS + */ + +require_once 'TestUnit.php'; +require_once 'HTML_TestListener.php'; +require_once 'PEAR/ErrorStack.php'; + +$title = 'PhpUnit test run, PEAR_ErrorStack package'; +?> +<html> +<head> +<title><?php echo $title; ?></title> +<link rel="stylesheet" href="stylesheet.css" type="text/css" /> +</head> +<body> +<h1><?php echo $title; ?></h1> + <p> + This page runs all the phpUnit self-tests, and produces nice HTML output. + </p> + <p> + Unlike typical test run, <strong>expect many test cases to + fail</strong>. Exactly those with <code>pass</code> in their name + should succeed. + </p> + <p> + For each test we display both the test result -- <span + class="Pass">ok</span>, <span class="Failure">FAIL</span>, or + <span class="Error">ERROR</span> -- and also a meta-result -- + <span class="Expected">as expected</span>, <span + class="Unexpected">UNEXPECTED</span>, or <span + class="Unknown">unknown</span> -- that indicates whether the + expected test result occurred. Although many test results will + be 'FAIL' here, all meta-results should be 'as expected', except + for a few 'unknown' meta-results (because of errors) when running + in PHP3. + </p> + +<h2>Tests</h2> + <?php + $testcases = array( + 'Error_Stack_TestCase_singleton', + 'Error_Stack_TestCase_pushpop', + 'Error_Stack_TestCase_pushpopstatic', + 'Error_Stack_TestCase_pushpopcallback', + 'Error_Stack_TestCase_getErrorMessage', + 'Error_Stack_TestCase_getErrorMessageTemplate', + 'Error_Stack_TestCase_getErrors', + 'Error_Stack_TestCase_staticGetErrors', + ); +define('PEAR_LOG_EMERG', 0); /** System is unusable */ +define('PEAR_LOG_ALERT', 1); /** Immediate action required */ +define('PEAR_LOG_CRIT', 2); /** Critical conditions */ +define('PEAR_LOG_ERR', 3); /** Error conditions */ +define('PEAR_LOG_WARNING', 4); /** Warning conditions */ +define('PEAR_LOG_NOTICE', 5); /** Normal but significant */ +define('PEAR_LOG_INFO', 6); /** Informational */ +define('PEAR_LOG_DEBUG', 7); /** Debug-level messages */ +/** +* Mock Log object +*/ +class BurfLog { + var $testcase; + var $method; + var $expect = array(); + function setTestCase(&$testcase) + { + $this->testcase = &$testcase; + } + + function curMethod($method) + { + $this->method = $method; + } + + function pushExpect($message, $priority, $errarray) + { + unset($errarray['time']); + unset($errarray['context']); + array_push($this->expect, array($message, $priority, $errarray)); + } + + function clearExpect() + { + $this->expect = array(); + } + + function log($message, $priority, $errarray) + { + $this->testcase->wasLogged = true; + if (!is_a($this->testcase, 'PHPUnit_TestCase')) { + trigger_error('ERROR: burflog never set up', E_USER_ERROR); + return; + } + if (!isset($this->method)) { + $this->testcase->assertFalse(true, 'ERROR: burflog never set up'); + return; + } + if (!count($this->expect)) { + $this->testcase->assertFalse(true, "method $this->method: logged, but no log expected"); + $this->testcase->assertFalse(true, "method $this->method: log message = $message"); + $this->testcase->assertFalse(true, "method $this->method: log priority = $priority"); + return; + } + unset($errarray['time']); + unset($errarray['context']); + $expect = array_pop($this->expect); + $this->testcase->assertEquals($expect[0], $message, "method $this->method: wrong message"); + $this->testcase->assertEquals($expect[1], $priority, "method $this->method: wrong priority"); + $this->testcase->assertEquals($expect[2], $errarray, "method $this->method: wrong errarray"); + } +} + + $suite = new PHPUnit_TestSuite(); + + foreach ($testcases as $testcase) { + include_once $testcase . '.php'; + $suite->addTestSuite($testcase); + } + + $listener = new HTML_TestListener(); + $finalresult = TestUnit::run($suite, $listener); + $results = include_once dirname(__FILE__) . '/base_regression.php'; + $num = $results['number']; + $failed = $results['failed']; + $passed = $results['passed']; + for ($i = 1; $i <= $num; $i++) { + $bla = new Mock_PHPUnit; + $bla->name = $i; + $listener->startTest($bla); + if (isset($failed[$i])) { + $listener->addFailure($bla, $failed[$i]); + $finalresult->addFailure($bla, $a = 'context had additional ' . serialize($failed[$i])); + } + $listener->endTest($bla); + } + + $finalresult->removeListener($listener); + // hack in the base regression test count + $finalresult->_runTests += count($results['failed']) + count($results['passed']); + $finalresult->report(); + + ?> +</body> +</html> diff --git a/pear/tests/PEAR_test_mock_pearweb.php.inc b/pear/tests/PEAR_test_mock_pearweb.php.inc new file mode 100644 index 000000000..f1f7edc9c --- /dev/null +++ b/pear/tests/PEAR_test_mock_pearweb.php.inc @@ -0,0 +1,234 @@ +<?php +require_once 'XML/RPC/Server.php'; + +class PEAR_test_mock_pearweb { + var $_config; + var $_remote; + + function setRemote(&$r) + { + $this->_remote = &$r; + } + + function addHtmlConfig($address, $filename) + { + $this->_config['html'][$address] = array(basename($filename), file_get_contents($filename)); + } + + function addXmlrpcConfig($method, $params, $return) + { + $this->_config['xmlrpc'][$method][serialize($params)] = $return; + } + + function _encode($val) + { + $val = XML_RPC_encode($val); + $ser = new XML_RPC_Response($val); + return $ser->serialize(); + } + + function receiveHttp($address) + { + if (!isset($this->_config) || !is_array($this->_config)) { + return $this->do404($address); + } + if (!isset($this->_config['html'][$address])) { + return $this->do404($address); + } else { + return $this->do200() . + 'content-length: ' . strlen($this->_config['html'][$address][1]) . "\n\n" . + $this->_config['html'][$address][1]; + } + } + + function receiveXmlrpc($postpayload) + { + $info = $this->parseRequest($postpayload); + if (!isset($this->_config['xmlrpc'][$info['method']])) { + return $this->doXmlrpcFault($info); + } + if (!isset($this->_config['xmlrpc'][serialize($info['params'])])) { + var_dump($info['param']); + die("Error - parameters not configured properly for $info[method]"); + } + return $this->do200() . + $this->_encode($this->_config['xmlrpc'][$info['method']][serialize($info['params'])]); + } + + function call($method, $params) + { + if (!isset($this->_config['xmlrpc'][$method])) { + include_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'php_dump.php.inc'; + $args = $params; + switch (count($args)) { + case 0: + $result = $this->_remote->parentcall($method); + break; + case 1: + $result = $this->_remote->parentcall($method, $args[0]); + break; + case 2: + $result = $this->_remote->parentcall($method, $args[0], $args[1]); + break; + case 3: + $result = $this->_remote->parentcall($method, $args[0], $args[1], $args[2]); + break; + case 4: + $result = $this->_remote->parentcall($method, $args[0], $args[1], $args[2], $args[3]); + break; + case 5: + $result = $this->_remote->parentcall($method, $args[0], $args[1], $args[2], $args[3], $args[4]); + break; + case 6: + $result = $this->_remote->parentcall($method, $args[0], $args[1], $args[2], $args[3], $args[4], $args[5]); + break; + } + $dump = new PHP_Dump($result); + $args = new PHP_Dump($args); + if (!isset($this->_pearweb->_config['xmlrpc'][$method][serialize($args)])) + $GLOBALS['totalPHP'][$method . serialize($args)] = '$pearweb->addXmlrpcConfig("' . + $method . '", ' . + $args->toPHP() . ', ' . + $dump->toPHP() .");"; + foreach($GLOBALS['totalPHP'] as $php) { + echo $php . "\n"; + } + var_dump(array_keys($this->_config['xmlrpc'][$method]), $params); + die("Error - parameters not configured properly for $method"); + return false; + } + if (!isset($this->_config['xmlrpc'][$method][serialize($params)])) { + include_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'php_dump.php.inc'; + $args = $params; + switch (count($args)) { + case 0: + $result = $this->_remote->parentcall($method); + break; + case 1: + $result = $this->_remote->parentcall($method, $args[0]); + break; + case 2: + $result = $this->_remote->parentcall($method, $args[0], $args[1]); + break; + case 3: + $result = $this->_remote->parentcall($method, $args[0], $args[1], $args[2]); + break; + case 4: + $result = $this->_remote->parentcall($method, $args[0], $args[1], $args[2], $args[3]); + break; + case 5: + $result = $this->_remote->parentcall($method, $args[0], $args[1], $args[2], $args[3], $args[4]); + break; + case 6: + $result = $this->_remote->parentcall($method, $args[0], $args[1], $args[2], $args[3], $args[4], $args[5]); + break; + } + $dump = new PHP_Dump($result); + $args = new PHP_Dump($args); + if (!isset($this->_pearweb->_config['xmlrpc'][$method][serialize($args)])) + $GLOBALS['totalPHP'][$method . serialize($args)] = '$pearweb->addXmlrpcConfig("' . + $method . '", ' . + $args->toPHP() . ', ' . + $dump->toPHP() .");"; + foreach($GLOBALS['totalPHP'] as $php) { + echo $php . "\n"; + } + var_dump(array_keys($this->_config['xmlrpc'][$method]), $params); + die("Error - parameters not configured properly for $method"); + } + return $this->_config['xmlrpc'][$method][serialize($params)]; + } + + function doXmlrpcFault($info) + { + $r = new XML_RPC_Response(0, 1, 'Unknown method'); + return $this->do200() . $r->serialize(); + } + + function do200() + { + return "HTTP/1.1 200 \n"; + } + + function do404($address) + { + return 'HTTP/1.1 404 ' . $address . ' Is not valid'; + } + + /** + * Parse an xmlrpc request + * @param string fake HTTP_RAW_POST_DATA + * @return string|array serialized fault string, or array containing method name and parameters + */ + function parseRequest($data) + { + // copied from XML_RPC_Server + global $XML_RPC_xh; + global $XML_RPC_err, $XML_RPC_str, $XML_RPC_errxml, + $XML_RPC_defencoding, $XML_RPC_Server_dmap; + + $parser = xml_parser_create($XML_RPC_defencoding); + + $XML_RPC_xh[$parser] = array(); + $XML_RPC_xh[$parser]['st'] = ""; + $XML_RPC_xh[$parser]['cm'] = 0; + $XML_RPC_xh[$parser]['isf'] = 0; + $XML_RPC_xh[$parser]['params'] = array(); + $XML_RPC_xh[$parser]['method'] = ""; + + $plist = ''; + + // decompose incoming XML into request structure + + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); + xml_set_element_handler($parser, "XML_RPC_se", "XML_RPC_ee"); + xml_set_character_data_handler($parser, "XML_RPC_cd"); + xml_set_default_handler($parser, "XML_RPC_dh"); + if (!xml_parse($parser, $data, 1)) { + // return XML error as a faultCode + $r = new XML_RPC_Response(0, + $XML_RPC_errxml+xml_get_error_code($parser), + sprintf("XML error: %s at line %d", + xml_error_string(xml_get_error_code($parser)), + xml_get_current_line_number($parser))); + xml_parser_free($parser); + return $r->serialize(); + } else { + xml_parser_free($parser); + $params = array(); + // now add parameters in + for ($i = 0; $i < sizeof($XML_RPC_xh[$parser]['params']); $i++) { + // print "<!-- " . $XML_RPC_xh[$parser]['params'][$i]. "-->\n"; + $plist .= "$i - " . $XML_RPC_xh[$parser]['params'][$i] . " \n"; + eval('$val = ' . $XML_RPC_xh[$parser]['params'][$i] . ";"); + $param = $val->scalarval(); + $param = PEAR_test_mock_pearweb::_convertScalar($param); + $params[] = $param; + } + return array('method' => $XML_RPC_xh[$parser]['method'], 'params' => $params); + } + } + + /** + * Converts the mishmash returned from XML_RPC parsing into a regular PHP value, + * handling nested arrays gracefully. + * @param mixed + * @return mixed + */ + function _convertScalar($val) + { + if (is_a($val, 'XML_RPC_Value')) { + $val = $val->scalarval(); + } + if (!is_array($val)) { + return $val; + } + $newval = array(); + foreach ($val as $i => $contents) + { + $newval[$i] = PEAR_test_mock_pearweb::_convertScalar($contents); + } + return $newval; + } +} +?>
\ No newline at end of file diff --git a/pear/tests/common_sortPkgDeps1_package.xml b/pear/tests/common_sortPkgDeps1_package.xml new file mode 100644 index 000000000..a103b10c6 --- /dev/null +++ b/pear/tests/common_sortPkgDeps1_package.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0"> + <package version="1.0"> + <name>pkg1</name> + <summary>required test for PEAR_Installer</summary> + <description> + fake package + </description> + <license>PHP License</license> + <maintainers> + <maintainer> + <user>fakeuser</user> + <name>Joe Shmoe</name> + <email>nobody@example.com</email> + <role>lead</role> + </maintainer> + </maintainers> + <release> + <version>1.1</version> + <date>2003-09-09</date> + <state>stable</state> + <notes> + required dependency test + </notes> + <deps> + <dep type="pkg" version="1.0" rel="ge">pkg2</dep> + </deps> + <filelist> + <dir name="/" baseinstalldir="grob" role="php"> + <file>zoorb.php</file> + <dir name="goompness" role="php"> + <file>oggbrzitzkee.php</file> + <file>Mopreeb.php</file> + </dir> + </dir> + </filelist> + </release> + </package> diff --git a/pear/tests/common_sortPkgDeps2_package.xml b/pear/tests/common_sortPkgDeps2_package.xml new file mode 100644 index 000000000..3e7c03852 --- /dev/null +++ b/pear/tests/common_sortPkgDeps2_package.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0"> + <package version="1.0"> + <name>pkg2</name> + <summary>required test for PEAR_Installer</summary> + <description> + fake package + </description> + <license>PHP License</license> + <maintainers> + <maintainer> + <user>fakeuser</user> + <name>Joe Shmoe</name> + <email>nobody@example.com</email> + <role>lead</role> + </maintainer> + </maintainers> + <release> + <version>1.1</version> + <date>2003-09-09</date> + <state>stable</state> + <notes> + required dependency test + </notes> + <deps> + <dep type="pkg" version="1.0" rel="ge">pkg3</dep> + <dep type="php" version="1.0" rel="ge" /> + </deps> + <filelist> + <dir name="/" baseinstalldir="grob" role="php"> + <file>zoorb.php</file> + <dir name="goompness" role="php"> + <file>oggbrzitzkee.php</file> + <file>Mopreeb.php</file> + </dir> + </dir> + </filelist> + </release> + </package> diff --git a/pear/tests/common_sortPkgDeps3_package.xml b/pear/tests/common_sortPkgDeps3_package.xml new file mode 100644 index 000000000..830a94c70 --- /dev/null +++ b/pear/tests/common_sortPkgDeps3_package.xml @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0"> + <package version="1.0"> + <name>pkg3</name> + <summary>required test for PEAR_Installer</summary> + <description> + fake package + </description> + <license>PHP License</license> + <maintainers> + <maintainer> + <user>fakeuser</user> + <name>Joe Shmoe</name> + <email>nobody@example.com</email> + <role>lead</role> + </maintainer> + </maintainers> + <release> + <version>1.1</version> + <date>2003-09-09</date> + <state>stable</state> + <notes> + required dependency test + </notes> + <deps> + <dep type="pkg" version="1.0" rel="ge">pkg4</dep> + <dep type="pkg" version="1.0" rel="ge">pkg5</dep> + </deps> + <filelist> + <dir name="/" baseinstalldir="grob" role="php"> + <file>zoorb.php</file> + <dir name="goompness" role="php"> + <file>oggbrzitzkee.php</file> + <file>Mopreeb.php</file> + </dir> + </dir> + </filelist> + </release> + </package> diff --git a/pear/tests/common_sortPkgDeps4_package.xml b/pear/tests/common_sortPkgDeps4_package.xml new file mode 100644 index 000000000..ff3394ee5 --- /dev/null +++ b/pear/tests/common_sortPkgDeps4_package.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0"> + <package version="1.0"> + <name>pkg4</name> + <summary>required test for PEAR_Installer</summary> + <description> + fake package + </description> + <license>PHP License</license> + <maintainers> + <maintainer> + <user>fakeuser</user> + <name>Joe Shmoe</name> + <email>nobody@example.com</email> + <role>lead</role> + </maintainer> + </maintainers> + <release> + <version>1.1</version> + <date>2003-09-09</date> + <state>stable</state> + <notes> + required dependency test + </notes> + <deps> + <dep type="pkg" version="1.0" rel="ge">pkg6</dep> + </deps> + <filelist> + <dir name="/" baseinstalldir="grob" role="php"> + <file>zoorb.php</file> + <dir name="goompness" role="php"> + <file>oggbrzitzkee.php</file> + <file>Mopreeb.php</file> + </dir> + </dir> + </filelist> + </release> + </package> diff --git a/pear/tests/common_sortPkgDeps5_package.xml b/pear/tests/common_sortPkgDeps5_package.xml new file mode 100644 index 000000000..6dea22f40 --- /dev/null +++ b/pear/tests/common_sortPkgDeps5_package.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0"> + <package version="1.0"> + <name>pkg5</name> + <summary>required test for PEAR_Installer</summary> + <description> + fake package + </description> + <license>PHP License</license> + <maintainers> + <maintainer> + <user>fakeuser</user> + <name>Joe Shmoe</name> + <email>nobody@example.com</email> + <role>lead</role> + </maintainer> + </maintainers> + <release> + <version>1.1</version> + <date>2003-09-09</date> + <state>stable</state> + <notes> + required dependency test + </notes> + <deps> + <dep type="pkg" version="1.0" rel="ge">pkg6</dep> + </deps> + <filelist> + <dir name="/" baseinstalldir="grob" role="php"> + <file>zoorb.php</file> + <dir name="goompness" role="php"> + <file>oggbrzitzkee.php</file> + <file>Mopreeb.php</file> + </dir> + </dir> + </filelist> + </release> + </package> diff --git a/pear/tests/common_sortPkgDeps6_package.xml b/pear/tests/common_sortPkgDeps6_package.xml new file mode 100644 index 000000000..a196e7003 --- /dev/null +++ b/pear/tests/common_sortPkgDeps6_package.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0"> + <package version="1.0"> + <name>pkg6</name> + <summary>required test for PEAR_Installer</summary> + <description> + fake package + </description> + <license>PHP License</license> + <maintainers> + <maintainer> + <user>fakeuser</user> + <name>Joe Shmoe</name> + <email>nobody@example.com</email> + <role>lead</role> + </maintainer> + </maintainers> + <release> + <version>1.1</version> + <date>2003-09-09</date> + <state>stable</state> + <notes> + required dependency test + </notes> + <filelist> + <dir name="/" baseinstalldir="grob" role="php"> + <file>zoorb.php</file> + <dir name="goompness" role="php"> + <file>oggbrzitzkee.php</file> + <file>Mopreeb.php</file> + </dir> + </dir> + </filelist> + </release> + </package> diff --git a/pear/tests/depnoreleases-1.0.tgz b/pear/tests/depnoreleases-1.0.tgz Binary files differnew file mode 100644 index 000000000..bc1c47132 --- /dev/null +++ b/pear/tests/depnoreleases-1.0.tgz diff --git a/pear/tests/depunstable-1.0.tgz b/pear/tests/depunstable-1.0.tgz Binary files differnew file mode 100644 index 000000000..a5e8d262c --- /dev/null +++ b/pear/tests/depunstable-1.0.tgz diff --git a/pear/tests/dirtree/multiplepackages/pkg1file.php b/pear/tests/dirtree/multiplepackages/pkg1file.php new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/pear/tests/dirtree/multiplepackages/pkg1file.php diff --git a/pear/tests/dirtree/multiplepackages/pkg2file.php b/pear/tests/dirtree/multiplepackages/pkg2file.php new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/pear/tests/dirtree/multiplepackages/pkg2file.php diff --git a/pear/tests/dirtree/nestedroot/emptydir/fakefile1.php b/pear/tests/dirtree/nestedroot/emptydir/fakefile1.php new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/pear/tests/dirtree/nestedroot/emptydir/fakefile1.php diff --git a/pear/tests/dirtree/nestedroot/emptydir/nesteddir/nestedfile.php b/pear/tests/dirtree/nestedroot/emptydir/nesteddir/nestedfile.php new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/pear/tests/dirtree/nestedroot/emptydir/nesteddir/nestedfile.php diff --git a/pear/tests/dirtree/nestedroot/rootfile.php b/pear/tests/dirtree/nestedroot/rootfile.php new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/pear/tests/dirtree/nestedroot/rootfile.php diff --git a/pear/tests/dirtree/package-fail.xml b/pear/tests/dirtree/package-fail.xml new file mode 100644 index 000000000..f2bf6f15d --- /dev/null +++ b/pear/tests/dirtree/package-fail.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0"> + <package version="1.0"> + <name>pkg2</name> + <summary>required test for PEAR_Installer</summary> + <description> + fake package + </description> + <license>PHP License</license> + <maintainers> + <maintainer> + <user>fakeuser</user> + <name>Joe Shmoe</name> + <email>nobody@example.com</email> + <role>lead</role> + </maintainer> + </maintainers> + <release> + <version>1.0</version> + <date>2003-12-11</date> + <state>stable</state> + <notes> + second package + </notes> + <filelist> + <dir name="/" baseinstalldir="test" role="php"> + <dir name="multiplepackages" role="php"> + <file>pkg2file.php</file> + </dir> + <dir name="nestedroot" role="php"> + <file>rootfile.php</file> + <dir name="emptydir" role="php"> + <dir name="nesteddir" role="php"> + <file>nestedfile.php</file> + <file>doesntexist.php</file> + </dir> + </dir> + </dir> + </dir> + </filelist> + </release> + </package> diff --git a/pear/tests/dirtree/package.xml b/pear/tests/dirtree/package.xml new file mode 100644 index 000000000..8ba556e5d --- /dev/null +++ b/pear/tests/dirtree/package.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0"> + <package version="1.0"> + <name>pkg1</name> + <summary>required test for PEAR_Installer</summary> + <description> + fake package + </description> + <license>PHP License</license> + <maintainers> + <maintainer> + <user>fakeuser</user> + <name>Joe Shmoe</name> + <email>nobody@example.com</email> + <role>lead</role> + </maintainer> + </maintainers> + <release> + <version>1.0</version> + <date>2003-12-11</date> + <state>stable</state> + <notes> + first package + </notes> + <filelist> + <dir name="/" baseinstalldir="test" role="php"> + <dir name="multiplepackages" role="php"> + <file>pkg1file.php</file> + </dir> + <dir name="pkg1" role="php"> + <file>randomfile.php</file> + </dir> + </dir> + </filelist> + </release> + </package> diff --git a/pear/tests/dirtree/package2.xml b/pear/tests/dirtree/package2.xml new file mode 100644 index 000000000..c0bde59e4 --- /dev/null +++ b/pear/tests/dirtree/package2.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0"> + <package version="1.0"> + <name>pkg2</name> + <summary>required test for PEAR_Installer</summary> + <description> + fake package + </description> + <license>PHP License</license> + <maintainers> + <maintainer> + <user>fakeuser</user> + <name>Joe Shmoe</name> + <email>nobody@example.com</email> + <role>lead</role> + </maintainer> + </maintainers> + <release> + <version>1.0</version> + <date>2003-12-11</date> + <state>stable</state> + <notes> + second package + </notes> + <filelist> + <dir name="/" baseinstalldir="test" role="php"> + <dir name="multiplepackages" role="php"> + <file>pkg2file.php</file> + </dir> + <dir name="nestedroot" role="php"> + <file>rootfile.php</file> + <dir name="emptydir" role="php"> + <dir name="nesteddir" role="php"> + <file>nestedfile.php</file> + </dir> + </dir> + </dir> + </dir> + </filelist> + </release> + </package> diff --git a/pear/tests/dirtree/pkg1-1.0.tgz b/pear/tests/dirtree/pkg1-1.0.tgz Binary files differnew file mode 100644 index 000000000..ab305f74a --- /dev/null +++ b/pear/tests/dirtree/pkg1-1.0.tgz diff --git a/pear/tests/dirtree/pkg1/randomfile.php b/pear/tests/dirtree/pkg1/randomfile.php new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/pear/tests/dirtree/pkg1/randomfile.php diff --git a/pear/tests/dirtree/pkg2-1.0.tgz b/pear/tests/dirtree/pkg2-1.0.tgz Binary files differnew file mode 100644 index 000000000..18bc9d2f4 --- /dev/null +++ b/pear/tests/dirtree/pkg2-1.0.tgz diff --git a/pear/tests/download_test.config.inc b/pear/tests/download_test.config.inc new file mode 100644 index 000000000..71dd32133 --- /dev/null +++ b/pear/tests/download_test.config.inc @@ -0,0 +1,2159 @@ +<?php +$pearweb->addXmlrpcConfig("package.info", unserialize("a:3:{i:0;s:4:\"pkg6\";i:1;s:8:\"releases\";i:2;b:1;}"), array( + '2.0b1' => + array( + 'id' => + "9", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 18:34:03", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + ), + '1.1' => + array( + 'id' => + "7", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:03:37", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + )); +$pearweb->addXmlrpcConfig("package.info", unserialize("a:3:{i:0;s:4:\"pkg2\";i:1;s:8:\"releases\";i:2;b:1;}"), array( + '1.1' => + array( + 'id' => + "3", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:02:56", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + )); +$pearweb->addXmlrpcConfig("package.info", unserialize("a:3:{i:0;s:4:\"pkg3\";i:1;s:8:\"releases\";i:2;b:1;}"), array( + '1.4' => + array( + 'id' => + "11", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 18:51:31", + 'releasenotes' => + "required dependency test", + 'state' => + "alpha", + ), + '1.1' => + array( + 'id' => + "4", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:03:06", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + )); +$pearweb->addXmlrpcConfig("package.info", unserialize("a:3:{i:0;s:4:\"pkg4\";i:1;s:8:\"releases\";i:2;b:1;}"), array( + '1.1' => + array( + 'id' => + "5", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:03:17", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + )); +$pearweb->addXmlrpcConfig("package.info", unserialize("a:3:{i:0;s:4:\"pkg5\";i:1;s:8:\"releases\";i:2;b:1;}"), array( + '1.1' => + array( + 'id' => + "6", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:03:25", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + )); +$pearweb->addXmlrpcConfig("package.info", unserialize("a:3:{i:0;s:4:\"pkg1\";i:1;s:8:\"releases\";i:2;b:1;}"), array( + '2.0b1' => + array( + 'id' => + "8", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 18:29:15", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + ), + '1.1' => + array( + 'id' => + "2", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:02:43", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + )); +$pearweb->addXmlrpcConfig("package.info", unserialize("a:3:{i:0;s:12:\"pkg4AndAHalf\";i:1;s:8:\"releases\";i:2;b:1;}"), array( + '1.3' => + array( + 'id' => + "10", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 18:50:05", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + )); +$pearweb->addXmlrpcConfig("package.info", array( + 0 => + "noreleases", + 1 => + "releases", + 2 => + true, + ), array( + )); +$pearweb->addXmlrpcConfig("package.info", array( + 0 => + "pkg1", + 1 => + "releases", + 2 => + true, + ), array( + '2.0b1' => + array( + 'id' => + "8", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 18:29:15", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + ), + '1.1' => + array( + 'id' => + "2", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:02:43", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + )); +$pearweb->addXmlrpcConfig("package.info", array( + 0 => + "stabilitytoolow", + 1 => + "releases", + 2 => + true, + ), array( + '3.0dev' => + array( + 'id' => + "23", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 00:27:38", + 'releasenotes' => + "required dependency test", + 'state' => + "devel", + ), + '2.0a1' => + array( + 'id' => + "22", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 00:27:19", + 'releasenotes' => + "required dependency test", + 'state' => + "alpha", + ), + '1.0b1' => + array( + 'id' => + "21", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 00:26:42", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + ), + '0.6beta' => + array( + 'id' => + "20", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 00:26:36", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + ), + '0.5' => + array( + 'id' => + "19", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 00:26:28", + 'releasenotes' => + "required dependency test", + 'state' => + "alpha", + ), + '0.3' => + array( + 'id' => + "18", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 00:26:21", + 'releasenotes' => + "required dependency test", + 'state' => + "devel", + ), + )); +$pearweb->addXmlrpcConfig("package.info", array( + 0 => + "pkg6", + 1 => + "releases", + 2 => + true, + ), array( + '2.0b1' => + array( + 'id' => + "9", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 18:34:03", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + ), + '1.1' => + array( + 'id' => + "7", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:03:37", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + )); +$pearweb->addXmlrpcConfig("package.info", array( + 0 => + "depnoreleases", + 1 => + "releases", + 2 => + true, + ), array( + '1.0' => + array( + 'id' => + "24", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 17:10:42", + 'releasenotes' => + "dependency has no releases test", + 'state' => + "beta", + ), + )); +$pearweb->addXmlrpcConfig("package.info", array( + 0 => + "depunstable", + 1 => + "releases", + 2 => + true, + ), array( + '1.0' => + array( + 'id' => + "26", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 17:32:38", + 'releasenotes' => + "dependency stability is too low", + 'state' => + "stable", + ), + )); +$pearweb->addXmlrpcConfig("package.info", array( + 0 => + "stabilitytoolow", + ), array( + 'packageid' => + "9", + 'name' => + "stabilitytoolow", + 'type' => + "pear", + 'categoryid' => + "1", + 'category' => + "Test", + 'stable' => + "3.0dev", + 'license' => + "PHP License", + 'summary' => + "required test for PEAR_Installer", + 'homepage' => + "", + 'description' => + "fake package", + 'cvs_link' => + "", + 'doc_link' => + "", + 'releases' => + array( + '3.0dev' => + array( + 'id' => + "23", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 00:27:38", + 'releasenotes' => + "required dependency test", + 'state' => + "devel", + 'deps' => + array( + 0 => + array( + 'type' => + "pkg", + 'relation' => + "ge", + 'version' => + "1.0", + 'name' => + "pkg6", + 'optional' => + "0", + ), + ), + ), + '2.0a1' => + array( + 'id' => + "22", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 00:27:19", + 'releasenotes' => + "required dependency test", + 'state' => + "alpha", + 'deps' => + array( + 0 => + array( + 'type' => + "pkg", + 'relation' => + "ge", + 'version' => + "1.0", + 'name' => + "pkg6", + 'optional' => + "0", + ), + ), + ), + '1.0b1' => + array( + 'id' => + "21", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 00:26:42", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + 'deps' => + array( + 0 => + array( + 'type' => + "pkg", + 'relation' => + "ge", + 'version' => + "1.0", + 'name' => + "pkg6", + 'optional' => + "0", + ), + ), + ), + '0.6beta' => + array( + 'id' => + "20", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 00:26:36", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + 'deps' => + array( + 0 => + array( + 'type' => + "pkg", + 'relation' => + "ge", + 'version' => + "1.0", + 'name' => + "pkg6", + 'optional' => + "0", + ), + ), + ), + '0.5' => + array( + 'id' => + "19", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 00:26:28", + 'releasenotes' => + "required dependency test", + 'state' => + "alpha", + 'deps' => + array( + 0 => + array( + 'type' => + "pkg", + 'relation' => + "ge", + 'version' => + "1.0", + 'name' => + "pkg6", + 'optional' => + "0", + ), + ), + ), + '0.3' => + array( + 'id' => + "18", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 00:26:21", + 'releasenotes' => + "required dependency test", + 'state' => + "devel", + 'deps' => + array( + 0 => + array( + 'type' => + "pkg", + 'relation' => + "ge", + 'version' => + "1.0", + 'name' => + "pkg6", + 'optional' => + "0", + ), + ), + ), + ), + 'notes' => + array( + ), + )); +$pearweb->addXmlrpcConfig("package.info", array( + 0 => + "depnoreleases", + ), array( + 'packageid' => + "10", + 'name' => + "depnoreleases", + 'type' => + "pear", + 'categoryid' => + "1", + 'category' => + "Test", + 'stable' => + "1.0", + 'license' => + "PHP License", + 'summary' => + "required test for PEAR_Installer", + 'homepage' => + "", + 'description' => + "fake package", + 'cvs_link' => + "", + 'doc_link' => + "", + 'releases' => + array( + '1.0' => + array( + 'id' => + "24", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 17:10:42", + 'releasenotes' => + "dependency has no releases test", + 'state' => + "beta", + 'deps' => + array( + 0 => + array( + 'type' => + "pkg", + 'relation' => + "ge", + 'version' => + "1.0", + 'name' => + "noreleases", + 'optional' => + "0", + ), + ), + ), + ), + 'notes' => + array( + ), + )); +$pearweb->addXmlrpcConfig("package.info", array( + 0 => + "depunstable", + ), array( + 'packageid' => + "11", + 'name' => + "depunstable", + 'type' => + "pear", + 'categoryid' => + "1", + 'category' => + "Test", + 'stable' => + "1.0", + 'license' => + "PHP License", + 'summary' => + "required test for PEAR_Installer", + 'homepage' => + "", + 'description' => + "fake package", + 'cvs_link' => + "", + 'doc_link' => + "", + 'releases' => + array( + '1.0' => + array( + 'id' => + "26", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 17:32:38", + 'releasenotes' => + "dependency stability is too low", + 'state' => + "stable", + 'deps' => + array( + 0 => + array( + 'type' => + "pkg", + 'relation' => + "ge", + 'version' => + "1.0b1", + 'name' => + "stabilitytoolow", + 'optional' => + "0", + ), + ), + ), + ), + 'notes' => + array( + ), + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "noreleases", + 2 => + array( + 0 => + "stable", + ), + ), false); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg1", + 2 => + "1976.9.2", + ), array( + 0 => + "2.0b1", + 1 => + array( + 'id' => + "8", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 18:29:15", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + ), + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg1", + 2 => + "snapshot", + ), array( + 0 => + "2.0b1", + 1 => + array( + 'id' => + "8", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 18:29:15", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + ), + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg1", + 2 => + "burgerking", + ), array( + 0 => + "2.0b1", + 1 => + array( + 'id' => + "8", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 18:29:15", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + ), + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "stabilitytoolow", + 2 => + array( + 0 => + "stable", + ), + ), array( + 0 => + "3.0dev", + 1 => + array( + 'id' => + "23", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 00:27:38", + 'releasenotes' => + "required dependency test", + 'state' => + "devel", + ), + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "stabilitytoolow", + 2 => + "3.0dev", + ), array( + 0 => + "3.0dev", + 1 => + array( + 'id' => + "23", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 00:27:38", + 'releasenotes' => + "required dependency test", + 'state' => + "devel", + ), + 2 => + "http://pear.Chiara/get/stabilitytoolow-3.0dev", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "stabilitytoolow", + 2 => + array( + 0 => + "beta", + 1 => + "stable", + ), + ), array( + 0 => + "1.0b1", + 1 => + array( + 'id' => + "21", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 00:26:42", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + ), + 2 => + "http://pear.Chiara/get/stabilitytoolow-1.0b1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "stabilitytoolow", + 2 => + array( + 0 => + "alpha", + 1 => + "beta", + 2 => + "stable", + ), + ), array( + 0 => + "2.0a1", + 1 => + array( + 'id' => + "22", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 00:27:19", + 'releasenotes' => + "required dependency test", + 'state' => + "alpha", + ), + 2 => + "http://pear.Chiara/get/stabilitytoolow-2.0a1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "stabilitytoolow", + 2 => + array( + 0 => + "devel", + 1 => + "alpha", + 2 => + "beta", + 3 => + "stable", + ), + ), array( + 0 => + "3.0dev", + 1 => + array( + 'id' => + "23", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 00:27:38", + 'releasenotes' => + "required dependency test", + 'state' => + "devel", + ), + 2 => + "http://pear.Chiara/get/stabilitytoolow-3.0dev", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg6", + 2 => + array( + 0 => + "devel", + 1 => + "alpha", + 2 => + "beta", + 3 => + "stable", + ), + ), array( + 0 => + "2.0b1", + 1 => + array( + 'id' => + "9", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 18:34:03", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + ), + 2 => + "http://pear.Chiara/get/pkg6-2.0b1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg6", + 2 => + "1.1", + ), array( + 0 => + "1.1", + 1 => + array( + 'id' => + "7", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:03:37", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + 2 => + "http://pear.Chiara/get/pkg6-1.1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "depnoreleases", + 2 => + array( + 0 => + "devel", + 1 => + "alpha", + 2 => + "beta", + 3 => + "stable", + ), + ), array( + 0 => + "1.0", + 1 => + array( + 'id' => + "24", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 17:10:42", + 'releasenotes' => + "dependency has no releases test", + 'state' => + "beta", + ), + 2 => + "http://pear.Chiara/get/depnoreleases-1.0", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "depunstable", + 2 => + array( + 0 => + "stable", + ), + ), array( + 0 => + "1.0", + 1 => + array( + 'id' => + "26", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-06 17:32:38", + 'releasenotes' => + "dependency stability is too low", + 'state' => + "stable", + ), + 2 => + "http://pear.Chiara/get/depunstable-1.0", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg6", + 2 => + array( + 0 => + "stable", + ), + ), array( + 0 => + "1.1", + 1 => + array( + 'id' => + "7", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:03:37", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + 2 => + "http://pear.Chiara/get/pkg6-1.1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg6", + 2 => + "stable", + ), array( + 0 => + "1.1", + 1 => + array( + 'id' => + "7", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:03:37", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + 2 => + "http://pear.Chiara/get/pkg6-1.1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg6", + 2 => + "beta", + ), array( + 0 => + "2.0b1", + 1 => + array( + 'id' => + "9", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 18:34:03", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + ), + 2 => + "http://pear.Chiara/get/pkg6-2.0b1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg6", + 2 => + array( + 0 => + "beta", + 1 => + "stable", + ), + ), array( + 0 => + "2.0b1", + 1 => + array( + 'id' => + "9", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 18:34:03", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + ), + 2 => + "http://pear.Chiara/get/pkg6-2.0b1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg2", + 2 => + array( + 0 => + "stable", + ), + ), array( + 0 => + "1.1", + 1 => + array( + 'id' => + "3", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:02:56", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + 2 => + "http://pear.Chiara/get/pkg2-1.1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg3", + 2 => + array( + 0 => + "stable", + ), + ), array( + 0 => + "1.1", + 1 => + array( + 'id' => + "4", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:03:06", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + 2 => + "http://pear.Chiara/get/pkg3-1.1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg4", + 2 => + array( + 0 => + "stable", + ), + ), array( + 0 => + "1.1", + 1 => + array( + 'id' => + "5", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:03:17", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + 2 => + "http://pear.Chiara/get/pkg4-1.1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg5", + 2 => + array( + 0 => + "stable", + ), + ), array( + 0 => + "1.1", + 1 => + array( + 'id' => + "6", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:03:25", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + 2 => + "http://pear.Chiara/get/pkg5-1.1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg1", + 2 => + array( + 0 => + "stable", + ), + ), array( + 0 => + "1.1", + 1 => + array( + 'id' => + "2", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:02:43", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + 2 => + "http://pear.Chiara/get/pkg1-1.1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg1", + 2 => + array( + 0 => + "beta", + 1 => + "stable", + ), + ), array( + 0 => + "2.0b1", + 1 => + array( + 'id' => + "8", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 18:29:15", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + ), + 2 => + "http://pear.Chiara/get/pkg1-2.0b1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg2", + 2 => + array( + 0 => + "beta", + 1 => + "stable", + ), + ), array( + 0 => + "1.1", + 1 => + array( + 'id' => + "3", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:02:56", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + 2 => + "http://pear.Chiara/get/pkg2-1.1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg3", + 2 => + array( + 0 => + "beta", + 1 => + "stable", + ), + ), array( + 0 => + "1.1", + 1 => + array( + 'id' => + "4", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:03:06", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + 2 => + "http://pear.Chiara/get/pkg3-1.1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg4", + 2 => + array( + 0 => + "beta", + 1 => + "stable", + ), + ), array( + 0 => + "1.1", + 1 => + array( + 'id' => + "5", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:03:17", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + 2 => + "http://pear.Chiara/get/pkg4-1.1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg5", + 2 => + array( + 0 => + "beta", + 1 => + "stable", + ), + ), array( + 0 => + "1.1", + 1 => + array( + 'id' => + "6", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:03:25", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + 2 => + "http://pear.Chiara/get/pkg5-1.1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg1", + 2 => + array( + 0 => + "alpha", + 1 => + "beta", + 2 => + "stable", + ), + ), array( + 0 => + "2.0b1", + 1 => + array( + 'id' => + "8", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 18:29:15", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + ), + 2 => + "http://pear.Chiara/get/pkg1-2.0b1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg2", + 2 => + array( + 0 => + "alpha", + 1 => + "beta", + 2 => + "stable", + ), + ), array( + 0 => + "1.1", + 1 => + array( + 'id' => + "3", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:02:56", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + 2 => + "http://pear.Chiara/get/pkg2-1.1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg3", + 2 => + array( + 0 => + "alpha", + 1 => + "beta", + 2 => + "stable", + ), + ), array( + 0 => + "1.4", + 1 => + array( + 'id' => + "11", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 18:51:31", + 'releasenotes' => + "required dependency test", + 'state' => + "alpha", + ), + 2 => + "http://pear.Chiara/get/pkg3-1.4", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg4AndAHalf", + 2 => + array( + 0 => + "alpha", + 1 => + "beta", + 2 => + "stable", + ), + ), array( + 0 => + "1.3", + 1 => + array( + 'id' => + "10", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 18:50:05", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + 2 => + "http://pear.Chiara/get/pkg4AndAHalf-1.3", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg4", + 2 => + array( + 0 => + "alpha", + 1 => + "beta", + 2 => + "stable", + ), + ), array( + 0 => + "1.1", + 1 => + array( + 'id' => + "5", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:03:17", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + 2 => + "http://pear.Chiara/get/pkg4-1.1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg5", + 2 => + array( + 0 => + "alpha", + 1 => + "beta", + 2 => + "stable", + ), + ), array( + 0 => + "1.1", + 1 => + array( + 'id' => + "6", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 17:03:25", + 'releasenotes' => + "required dependency test", + 'state' => + "stable", + ), + 2 => + "http://pear.Chiara/get/pkg5-1.1", + )); +$pearweb->addXmlrpcConfig("package.getDownloadURL", array( + 0 => + "pear", + 1 => + "pkg6", + 2 => + array( + 0 => + "alpha", + 1 => + "beta", + 2 => + "stable", + ), + ), array( + 0 => + "2.0b1", + 1 => + array( + 'id' => + "9", + 'doneby' => + "cellog", + 'license' => + "", + 'summary' => + "", + 'description' => + "", + 'releasedate' => + "2003-12-03 18:34:03", + 'releasenotes' => + "required dependency test", + 'state' => + "beta", + ), + 2 => + "http://pear.Chiara/get/pkg6-2.0b1", + )); + +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg6-1.1.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-1.1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg6-1.1", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-1.1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg6-2.0b1", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-2.0b1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg6-2.0b1.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-2.0b1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg2-1.1", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg2-1.1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg2-1.1.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg2-1.1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg3-1.1", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg3-1.1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg3-1.1.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg3-1.1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg4-1.1", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg4-1.1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg4-1.1.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg4-1.1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg5-1.1", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg5-1.1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg5-1.1.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg5-1.1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg1-1.1", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg1-1.1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg1-1.1.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg1-1.1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg1-2.0b1", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg1-2.0b1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg1-2.0b1.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg1-2.0b1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg3-1.4", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg3-1.4.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg3-1.4.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg3-1.4.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg4AndAHalf-1.3", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg4AndAHalf-1.3.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/pkg4AndAHalf-1.3.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg4AndAHalf-1.3.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow-0.3", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-0.3.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow-0.3.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-0.3.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow-0.5", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-0.5.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow-0.5.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-0.5.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow-0.6beta", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-0.6beta.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow-0.6beta.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-0.6beta.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow-1.0b1", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-1.0b1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow-1.0b1.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-1.0b1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow-2.0a1", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-2.0a1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow-2.0a1.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-2.0a1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow-2.0b1", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-2.0b1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow-2.0b1.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-2.0b1.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow-2.0dev", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-2.0dev.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow-2.0dev.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-2.0dev.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow-3.0dev", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-3.0dev.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow-3.0dev.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-3.0dev.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/depnoreleases-1.0", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'depnoreleases-1.0.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/depnoreleases-1.0.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'depnoreleases-1.0.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/depunstable-1.0", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'depunstable-1.0.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/depunstable-1.0.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'depunstable-1.0.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-3.0dev.tgz'); +$pearweb->addHtmlConfig("http://pear.Chiara/get/stabilitytoolow-3.0dev.tgz", + dirname(__FILE__) . DIRECTORY_SEPARATOR . 'stabilitytoolow-3.0dev.tgz'); +?>
\ No newline at end of file diff --git a/pear/tests/download_test_classes.php.inc b/pear/tests/download_test_classes.php.inc new file mode 100644 index 000000000..c27696d48 --- /dev/null +++ b/pear/tests/download_test_classes.php.inc @@ -0,0 +1,404 @@ +<?php +require_once 'XML/RPC.php'; +require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'PEAR_test_mock_pearweb.php.inc'; +$GLOBALS['pearweb'] = new PEAR_test_mock_pearweb; +class test_XML_RPC_Client extends XML_RPC_Client { + function test_XML_RPC_Client() + { + $this->_fakepearweb = &$GLOBALS['pearweb']; + } + + function sendPayloadHTTP10($msg, $server, $port, $timeout=0, + $username="", $password="") + { + // Only create the payload if it was not created previously + if(empty($msg->payload)) $msg->createPayload(); + + $resp = $this->_fakepearweb->receiveXmlrpc($msg->payload); + + $resp=$msg->parseResponse($resp); + return $resp; + } +} +require_once 'PEAR/Remote.php'; + +class test_PEAR_Remote extends PEAR_Remote { + var $_pearweb; + var $_fakepearweb = true; + var $_simulateEpi = true; + function test_PEAR_Remote($config) + { + $pearweb = &$GLOBALS['pearweb']; + include dirname(__FILE__) . DIRECTORY_SEPARATOR . 'download_test.config.inc'; + $this->_pearweb = $pearweb; + parent::PEAR_Remote($config); + $this->_pearweb->setRemote($this); + } + + function parentcall() + { + $args = func_get_args(); + $method = array_shift($args); + switch (count($args)) { + case 0: + $result = PEAR_Remote::call_epi($method); + break; + case 1: + $result = PEAR_Remote::call_epi($method, $args[0]); + break; + case 2: + $result = PEAR_Remote::call_epi($method, $args[0], $args[1]); + break; + case 3: + $result = PEAR_Remote::call_epi($method, $args[0], $args[1], $args[2]); + break; + case 4: + $result = PEAR_Remote::call_epi($method, $args[0], $args[1], $args[2], $args[3]); + break; + case 5: + $result = PEAR_Remote::call_epi($method, $args[0], $args[1], $args[2], $args[3], $args[4]); + break; + case 6: + $result = PEAR_Remote::call_epi($method, $args[0], $args[1], $args[2], $args[3], $args[4], $args[5]); + break; + } + return $result; + } + + function call($method) + { + $_args = $args = func_get_args(); + + $server_channel = $this->config->get('default_channel'); + $channel = $this->_registry->getChannel($server_channel); + if ($channel) { + if (!$channel->supports('xml-rpc', $method)) { + // check for channel.list, which is implicitly supported for the PEAR channel + if (!(strtolower($server_channel) == 'pear' && $method == 'channel.list')) { + return $this->raiseError("Channel $server_channel does not support xml-rpc method $method"); + } + } + } + + array_unshift($_args, $channel); // cache by channel + $this->cache = $this->getCache($_args); + $cachettl = $this->config->get('cache_ttl'); + // If cache is newer than $cachettl seconds, we use the cache! + if ($this->cache !== null && $this->cache['age'] < $cachettl) { + return $this->cache['content']; + }; + if ($this->_simulateEpi) { + $result = call_user_func_array(array(&$this, 'call_epi'), $args); + if (!PEAR::isError($result)) { + $this->saveCache($_args, $result); + }; + return $result; + } + if (!@include_once("XML/RPC.php")) { + return $this->raiseError("For this remote PEAR operation you need to install the XML_RPC package"); + } + array_shift($args); + $server_host = $this->_registry->channelInfo($server_channel, 'server'); + $username = $this->config->get('username'); + $password = $this->config->get('password'); + $eargs = array(); + foreach($args as $arg) $eargs[] = $this->_encode($arg); + $f = new XML_RPC_Message($method, $eargs); + if ($this->cache !== null) { + $maxAge = '?maxAge='.$this->cache['lastChange']; + } else { + $maxAge = ''; + }; + $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; + if ($proxy = parse_url($this->config->get('http_proxy'))) { + $proxy_host = @$proxy['host']; + $proxy_port = @$proxy['port']; + $proxy_user = @$proxy['user']; + $proxy_pass = @$proxy['pass']; + } + $c = new test_XML_RPC_Client('/xmlrpc.php'.$maxAge, $server_host, 80, $proxy_host, $proxy_port, $proxy_user, $proxy_pass); + if ($username && $password) { + $c->setCredentials($username, $password); + } + if ($this->config->get('verbose') >= 3) { + $c->setDebug(1); + } + $r = $c->send($f); + if (!$r) { + return $this->raiseError("XML_RPC send failed"); + } + $v = $r->value(); + if ($e = $r->faultCode()) { + if ($e == $GLOBALS['XML_RPC_err']['http_error'] && strstr($r->faultString(), '304 Not Modified') !== false) { + return $this->cache['content']; + } + return $this->raiseError($r->faultString(), $e); + } + + $result = XML_RPC_decode($v); + $this->saveCache($_args, $result); + return $result; + } + + function call_epi($method) + { + $args = func_get_args(); + array_shift($args); + if ($this->_fakepearweb) { + if (count($args)) { + $result = $this->_pearweb->call($method, $args); + } else { + $result = $this->_pearweb->call($method); + } + }/* else { + switch (count($args)) { + case 0: + $result = parent::call($method); + break; + case 1: + $result = parent::call($method, $args[0]); + break; + case 2: + $result = parent::call($method, $args[0], $args[1]); + break; + case 3: + $result = parent::call($method, $args[0], $args[1], $args[2]); + break; + case 4: + $result = parent::call($method, $args[0], $args[1], $args[2], $args[3]); + break; + case 5: + $result = parent::call($method, $args[0], $args[1], $args[2], $args[3], $args[4]); + break; + case 6: + $result = parent::call($method, $args[0], $args[1], $args[2], $args[3], $args[4], $args[5]); + break; + } + }*/ + if (PEAR::isError($result)) { + return $result; + } + return $result; + } +} + +require_once 'PEAR/Installer.php'; +class test_PEAR_Installer extends PEAR_Installer { + function download($packages, $options, &$config, &$installpackages, + &$errors, $installed = false, $willinstall = false, $state = false) + { + // trickiness: initialize here + $this->PEAR_Downloader($this->ui, $options, $config); + $this->_remote = &new test_PEAR_Remote($config); + $ret = PEAR_Downloader::download($packages); + $errors = $this->getErrorMsgs(); + $installpackages = $this->getDownloadedPackages(); + trigger_error("PEAR Warning: PEAR_Installer::download() is deprecated " . + "in favor of PEAR_Downloader class", E_USER_WARNING); + return $ret; + } + + function downloadHttp($url, &$ui, $save_dir = '.', $callback = null) + { +// return parent::downloadHttp($url, $ui, $save_dir, $callback); + if ($callback) { + call_user_func($callback, 'setup', array(&$ui)); + } + if (preg_match('!^http://([^/:?#]*)(:(\d+))?(/.*)!', $url, $matches)) { + list(,$host,,$port,$path) = $matches; + } + if (isset($this)) { + $config = &$this->config; + } else { + $config = &PEAR_Config::singleton(); + } + $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; + if ($proxy = parse_url($config->get('http_proxy'))) { + $proxy_host = @$proxy['host']; + $proxy_port = @$proxy['port']; + $proxy_user = @$proxy['user']; + $proxy_pass = @$proxy['pass']; + + if ($proxy_port == '') { + $proxy_port = 8080; + } + if ($callback) { + call_user_func($callback, 'message', "Using HTTP proxy $host:$port"); + } + } + if (empty($port)) { + $port = 80; + } + // use _pearweb to get file + $retrieved = explode("\n", $this->_remote->_pearweb->receiveHttp($url)); + $headers = array(); + $line = array_shift($retrieved); + while (strlen(trim($line))) { + if (preg_match('/^([^:]+):\s+(.*)\s*$/', $line, $matches)) { + $headers[strtolower($matches[1])] = trim($matches[2]); + } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) { + if ($matches[1] != 200) { + return PEAR::raiseError("File http://$host:$port$path not valid (received: $line)"); + } + } + $line = array_shift($retrieved); + } + $retrieved = join("\n", $retrieved); + if (isset($headers['content-disposition']) && + preg_match('/\sfilename=\"([^;]*\S)\"\s*(;|$)/', $headers['content-disposition'], $matches)) { + $save_as = basename($matches[1]); + } else { + $save_as = basename($url); + } + if ($callback) { + $tmp = call_user_func($callback, 'saveas', $save_as); + if ($tmp) { + $save_as = $tmp; + } + } + $dest_file = $save_dir . DIRECTORY_SEPARATOR . $save_as; + if (!$wp = @fopen($dest_file, 'wb')) { + fclose($fp); + if ($callback) { + call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg)); + } + return PEAR::raiseError("could not open $dest_file for writing"); + } + if (isset($headers['content-length'])) { + $length = $headers['content-length']; + } else { + $length = -1; + } + $bytes = 0; + if ($callback) { + call_user_func($callback, 'start', array(basename($dest_file), $length)); + } + $start = 0; + while ($start < strlen($retrieved) - 1) { + $data = substr($retrieved, $start, 1024); + $start += 1024; + $bytes += strlen($data); + if ($callback) { + call_user_func($callback, 'bytesread', $bytes); + } + if (!@fwrite($wp, $data)) { + if ($callback) { + call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg)); + } + return PEAR::raiseError("$dest_file: write failed ($php_errormsg)"); + } + } + fclose($wp); + if ($callback) { + call_user_func($callback, 'done', $bytes); + } + return $dest_file; + } +} + +require_once 'PEAR/Downloader.php'; +class test_PEAR_Downloader extends PEAR_Downloader { + function test_PEAR_Downloader(&$ui, $options, &$config) + { + parent::PEAR_Downloader($ui, $options, $config); + $this->_remote = new test_PEAR_Remote($config); + } + + function downloadHttp($url, &$ui, $save_dir = '.', $callback = null) + { +// return parent::downloadHttp($url, $ui, $save_dir, $callback); + if ($callback) { + call_user_func($callback, 'setup', array(&$ui)); + } + if (preg_match('!^http://([^/:?#]*)(:(\d+))?(/.*)!', $url, $matches)) { + list(,$host,,$port,$path) = $matches; + } + if (isset($this)) { + $config = &$this->config; + } else { + $config = &PEAR_Config::singleton(); + } + $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; + if ($proxy = parse_url($config->get('http_proxy'))) { + $proxy_host = @$proxy['host']; + $proxy_port = @$proxy['port']; + $proxy_user = @$proxy['user']; + $proxy_pass = @$proxy['pass']; + + if ($proxy_port == '') { + $proxy_port = 8080; + } + if ($callback) { + call_user_func($callback, 'message', "Using HTTP proxy $host:$port"); + } + } + if (empty($port)) { + $port = 80; + } + // use _pearweb to get file + $retrieved = explode("\n", $this->_remote->_pearweb->receiveHttp($url)); + $headers = array(); + $line = array_shift($retrieved); + while (strlen(trim($line))) { + if (preg_match('/^([^:]+):\s+(.*)\s*$/', $line, $matches)) { + $headers[strtolower($matches[1])] = trim($matches[2]); + } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) { + if ($matches[1] != 200) { + return PEAR::raiseError("File http://$host:$port$path not valid (received: $line)"); + } + } + $line = array_shift($retrieved); + } + $retrieved = join("\n", $retrieved); + if (isset($headers['content-disposition']) && + preg_match('/\sfilename=\"([^;]*\S)\"\s*(;|$)/', $headers['content-disposition'], $matches)) { + $save_as = basename($matches[1]); + } else { + $save_as = basename($url); + } + if ($callback) { + $tmp = call_user_func($callback, 'saveas', $save_as); + if ($tmp) { + $save_as = $tmp; + } + } + $dest_file = $save_dir . DIRECTORY_SEPARATOR . $save_as; + if (!$wp = @fopen($dest_file, 'wb')) { + fclose($fp); + if ($callback) { + call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg)); + } + return PEAR::raiseError("could not open $dest_file for writing"); + } + if (isset($headers['content-length'])) { + $length = $headers['content-length']; + } else { + $length = -1; + } + $bytes = 0; + if ($callback) { + call_user_func($callback, 'start', array(basename($dest_file), $length)); + } + $start = 0; + while ($start < strlen($retrieved) - 1) { + $data = substr($retrieved, $start, 1024); + $start += 1024; + $bytes += strlen($data); + if ($callback) { + call_user_func($callback, 'bytesread', $bytes); + } + if (!@fwrite($wp, $data)) { + if ($callback) { + call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg)); + } + return PEAR::raiseError("$dest_file: write failed ($php_errormsg)"); + } + } + fclose($wp); + if ($callback) { + call_user_func($callback, 'done', $bytes); + } + return $dest_file; + } +} +?>
\ No newline at end of file diff --git a/pear/tests/merge.input b/pear/tests/merge.input new file mode 100644 index 000000000..440106ea4 --- /dev/null +++ b/pear/tests/merge.input @@ -0,0 +1 @@ +a:1:{s:7:"verbose";i:100;}
\ No newline at end of file diff --git a/pear/tests/merge2.input b/pear/tests/merge2.input new file mode 100644 index 000000000..853a6d10b --- /dev/null +++ b/pear/tests/merge2.input @@ -0,0 +1 @@ +a:2:{s:7:"verbose";i:35;s:10:"__channels";a:2:{s:5:"test1";a:1:{s:7:"verbose";i:898;}s:5:"test2";a:1:{s:7:"verbose";i:899;}}}
\ No newline at end of file diff --git a/pear/tests/package-PEARtests.xml b/pear/tests/package-PEARtests.xml new file mode 100644 index 000000000..daceee967 --- /dev/null +++ b/pear/tests/package-PEARtests.xml @@ -0,0 +1,176 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0"> +<package version="1.0"> + <name>PEARtests</name> + <summary>PEAR Base System tests</summary> + <description>This package contains all tests for the PEAR base system</description> + <maintainers> + <maintainer> + <user>cellog</user> + <name>Greg Beaver</name> + <email>cellog@php.net</email> + <role>developer</role> + </maintainer> + </maintainers> + <release> + <version>2.1</version> + <date>2004-06-04</date> + <license>PHP License</license> + <state>stable</state> + <notes>Installation package.xml for PEAR package tests</notes> + <deps> + <dep type="pkg" rel="ge" version="1.4.0dev6">PEAR</dep> + <dep type="pkg" rel="ge" version="1.1">Archive_Tar</dep> + <dep type="pkg" rel="ge" version="1.2">Console_Getopt</dep> + <dep type="pkg" rel="ge" version="1.1.0">XML_RPC</dep> + <dep type="ext" rel="has">xml</dep> + <dep type="ext" rel="has">pcre</dep> + </deps> + <filelist> + <dir baseinstalldir="PEAR" name="/"> + <dir name="dirtree"> + <file role="test" name="package-fail.xml"/> + <file role="test" name="package.xml"/> + <file role="test" name="package2.xml"/> + <file role="test" name="pkg1-1.0.tgz"/> + <file role="test" name="pkg2-1.0.tgz"/> + <dir name="multiplepackages"> + <file role="test" name="pkg1file.php"/> + <file role="test" name="pkg2file.php"/> + </dir> <!-- dirtree/multiplepackages --> + <dir name="nestedroot"> + <file role="test" name="rootfile.php"/> + <dir name="emptydir"> + <file role="test" name="fakefile1.php"/> + <dir name="nesteddir"> + <file role="test" name="nestedfile.php"/> + </dir> <!-- dirtree/nestedroot/emptydir/nesteddir --> + </dir> <!-- dirtree/nestedroot/emptydir --> + </dir> <!-- dirtree/nestedroot --> + <dir name="pkg1"> + <file role="test" name="randomfile.php"/> + </dir> <!-- dirtree/pkg1 --> + </dir> <!-- dirtree --> + <dir name="PEAR_ErrorStack"> + <file role="test" name="base_regression.php"/> + <file role="test" name="Error_Stack_TestCase_getErrorMessage.php"/> + <file role="test" name="Error_Stack_TestCase_getErrorMessageTemplate.php"/> + <file role="test" name="Error_Stack_TestCase_getErrors.php"/> + <file role="test" name="Error_Stack_TestCase_pushpop.php"/> + <file role="test" name="Error_Stack_TestCase_pushpopcallback.php"/> + <file role="test" name="Error_Stack_TestCase_pushpopstatic.php"/> + <file role="test" name="Error_Stack_TestCase_singleton.php"/> + <file role="test" name="Error_Stack_TestCase_staticGetErrors.php"/> + <file role="test" name="HTML_TestListener.php"/> + <file role="test" name="stylesheet.css"/> + <file role="test" name="testsuite.php"/> + <file role="test" name="TestUnit.php"/> + </dir> <!-- PEAR_ErrorStack --> + <dir name="test-pkg6"> + <file role="test" name="conflictpackage2.xml"/> + <file role="test" name="conflictpackage.xml"/> + <file role="test" name="invalidtgz.tgz"/> + <file role="test" name="nopackagexml.tgz"/> + <file role="test" name="package2.xml"/> + <file role="test" name="package2_invalid.xml"/> + <file role="test" name="package.xml"/> + <file role="test" name="pkg6-1.1.tgz"/> + <file role="test" name="pkg6-2.0b1.tgz"/> + <file role="test" name="zoorb.php"/> + <dir name="goompness"> + <file role="test" name="Mopreeb.php"/> + <file role="test" name="oggbrzitzkee.php"/> + <file role="test" name="test.dat"/> + </dir> <!-- test-pkg6/goompness --> + </dir> <!-- test-pkg6 --> + <file role="test" name="common_sortPkgDeps1_package.xml"/> + <file role="test" name="common_sortPkgDeps2_package.xml"/> + <file role="test" name="common_sortPkgDeps3_package.xml"/> + <file role="test" name="common_sortPkgDeps4_package.xml"/> + <file role="test" name="common_sortPkgDeps5_package.xml"/> + <file role="test" name="common_sortPkgDeps6_package.xml"/> + <file role="test" name="depnoreleases-1.0.tgz"/> + <file role="test" name="depunstable-1.0.tgz"/> + <file role="test" name="download_test.config.inc"/> + <file role="test" name="download_test_classes.php.inc"/> + <file role="test" name="merge.input"/> + <file role="test" name="merge2.input"/> + <file role="test" name="pear1.phpt"/> + <file role="test" name="pear2.phpt"/> + <file role="test" name="pear_autoloader.phpt"/> + <file role="test" name="pear_channelfile.phpt"/> + <file role="test" name="pear_common_analyzeSC.phpt"/> + <file role="test" name="pear_common_buildProvidesArray.phpt"/> + <file role="test" name="pear_common_downloadHttp.phpt"/> + <file role="test" name="pear_common_infoFromString.phpt"/> + <file role="test" name="pear_common_sortPkgDeps.phpt"/> + <file role="test" name="pear_common_validPackageVersion.phpt"/> + <file role="test" name="pear_config.phpt"/> + <file role="test" name="pear_config_1.1.phpt"/> + <file role="test" name="pear_dependency_checkExtension.phpt"/> + <file role="test" name="pear_dependency_checkPackage.phpt"/> + <file role="test" name="pear_dependency_checkPackageUninstall.phpt"/> + <file role="test" name="pear_downloader_invalid.phpt"/> + <file role="test" name="pear_downloader_new.phpt"/> + <file role="test" name="pear_downloader_old.phpt"/> + <file role="test" name="pear_error.phpt"/> + <file role="test" name="pear_error2.phpt"/> + <file role="test" name="pear_error3.phpt"/> + <file role="test" name="pear_error4.phpt"/> + <file role="test" name="pear_installer1.phpt"/> + <file role="test" name="pear_installer2.phpt"/> + <file role="test" name="pear_installer3.phpt"/> + <file role="test" name="pear_installer4.phpt"/> + <file role="test" name="pear_installer5.phpt"/> + <file role="test" name="pear_installer_installFile_channels.phpt"/> + <file role="test" name="pear_installer_install_channels.phpt"/> + <file role="test" name="pear_packager.phpt"/> + <file role="test" name="pear_registry_inc.php.inc"/> + <file role="test" name="pear_registry.phpt"/> + <file role="test" name="pear_registry_1.1.phpt"/> + <file role="test" name="pear_system.phpt"/> + <file role="test" name="PEAR_test_mock_pearweb.php.inc"/> + <file role="test" name="php.ini"/> + <file role="test" name="php_dump.php.inc"/> + <file role="test" name="pkg1-1.1.tgz"/> + <file role="test" name="pkg1-2.0b1.tgz"/> + <file role="test" name="pkg2-1.1.tgz"/> + <file role="test" name="pkg3-1.1.tgz"/> + <file role="test" name="pkg3-1.4.tgz"/> + <file role="test" name="pkg4-1.1.tgz"/> + <file role="test" name="pkg4AndAHalf-1.3.tgz"/> + <file role="test" name="pkg5-1.1.tgz"/> + <file role="test" name="stabilitytoolow-0.3.tgz"/> + <file role="test" name="stabilitytoolow-0.5.tgz"/> + <file role="test" name="stabilitytoolow-0.6beta.tgz"/> + <file role="test" name="stabilitytoolow-1.0b1.tgz"/> + <file role="test" name="stabilitytoolow-2.0a1.tgz"/> + <file role="test" name="stabilitytoolow-2.0b1.tgz"/> + <file role="test" name="stabilitytoolow-2.0dev.tgz"/> + <file role="test" name="stabilitytoolow-3.0dev.tgz"/> + <file role="test" name="system.input"/> + <file role="test" name="testdownload.tgz"/> + <file role="test" name="toonew.conf"/> + <file role="test" name="user.input"/> + <file role="test" name="user2.input"/> + <file role="test" name="user3.input"/> + </dir> <!-- / --> + </filelist> + </release> + <changelog> + <release> + <version>1.0</version> + <date>2004-03-21</date> + <license>PHP License</license> + <state>stable</state> + <notes>Installation package.xml for PEAR package tests</notes> + </release> + <release> + <version>2.0</version> + <date>2004-06-01</date> + <license>PHP License</license> + <state>stable</state> + <notes>Installation package.xml for PEAR package tests</notes> + </release> + </changelog> +</package> diff --git a/pear/tests/pear1.phpt b/pear/tests/pear1.phpt new file mode 100644 index 000000000..f65d6a4f1 --- /dev/null +++ b/pear/tests/pear1.phpt @@ -0,0 +1,90 @@ +--TEST-- +PEAR constructor/destructor test +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php + +require_once "PEAR.php"; + +class TestPEAR extends PEAR { + function TestPEAR($name) { + $this->_debug = true; + $this->name = $name; + $this->PEAR(); + } + function _TestPEAR() { + print "This is the TestPEAR($this->name) destructor\n"; + $this->_PEAR(); + } +} + +class Test2 extends PEAR { + function _Test2() { + print "This is the Test2 destructor\n"; + $this->_PEAR(); + } +} + +class Test3 extends Test2 { +} + +// test for bug http://bugs.php.net/bug.php?id=14744 +class Other extends Pear { + + var $a = 'default value'; + + function Other() { + $this->PEAR(); + } + + function _Other() { + // $a was modified but here misteriously returns to be + // the original value. That makes the destructor useless + // The correct value for $a in the destructor shoud be "new value" + echo "#bug 14744# Other class destructor: other->a == '" . $this->a ."'\n"; + } +} + +print "testing plain destructors\n"; +$o = new TestPEAR("test1"); +$p = new TestPEAR("test2"); +print "..\n"; +print "testing inherited destructors\n"; +$q = new Test3; + +echo "...\ntesting bug #14744\n"; +$other =& new Other; +echo "#bug 14744# Other class constructor: other->a == '" . $other->a ."'\n"; +// Modify $a +$other->a = 'new value'; +echo "#bug 14744# Other class modified: other->a == '" . $other->a ."'\n"; + +print "..\n"; +print "script exiting...\n"; +print "..\n"; + +?> +--EXPECT-- +testing plain destructors +PEAR constructor called, class=testpear +PEAR constructor called, class=testpear +.. +testing inherited destructors +... +testing bug #14744 +#bug 14744# Other class constructor: other->a == 'default value' +#bug 14744# Other class modified: other->a == 'new value' +.. +script exiting... +.. +This is the TestPEAR(test1) destructor +PEAR destructor called, class=testpear +This is the TestPEAR(test2) destructor +PEAR destructor called, class=testpear +This is the Test2 destructor +#bug 14744# Other class destructor: other->a == 'new value' diff --git a/pear/tests/pear2.phpt b/pear/tests/pear2.phpt new file mode 100644 index 000000000..ccf8864ef --- /dev/null +++ b/pear/tests/pear2.phpt @@ -0,0 +1,850 @@ +--TEST-- +PEAR complete set/push/pop error-handling test (run from pear/tests dir) +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php + +require_once "PEAR.php"; + +class testErrorHandlingStatic { + function doSetErrorHandlingFunction() + { + print "testing in class setErrorHandling\n"; + PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'get_error_mode'); + echoPEARVars('_PEAR_default_error_mode', $GLOBALS['_PEAR_default_error_mode'], + '_PEAR_default_error_options', $GLOBALS['_PEAR_default_error_options']); + } + + function doSetErrorHandlingStatic() + { + print "testing in class setErrorHandling array(obj, method)\n"; + $obj = new testErrorHandlingPEAR; + PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array(&$obj, 'fakeHandleError')); + echoPEARVars('_PEAR_default_error_mode', $GLOBALS['_PEAR_default_error_mode'], + '_PEAR_default_error_options', $GLOBALS['_PEAR_default_error_options']); + } + + function doSetErrorHandlingObject() + { + print "testing in class setErrorHandling array(class, method)\n"; + PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array('testErrorHandlingStatic', 'fakeHandleError')); + echoPEARVars('_PEAR_default_error_mode', $GLOBALS['_PEAR_default_error_mode'], + '_PEAR_default_error_options', $GLOBALS['_PEAR_default_error_options']); + } + + function doPushErrorHandlingFunction() + { + print "testing in class pushErrorHandling\n"; + PEAR::pushErrorHandling(PEAR_ERROR_CALLBACK, 'get_error_mode'); + echoPEARStack('_PEAR_error_handler_stack', $GLOBALS['_PEAR_error_handler_stack']); + } + + function doPushErrorHandlingObject() + { + print "testing in class pushErrorHandling array(obj, method)\n"; + $obj = new testErrorHandlingPEAR; + PEAR::pushErrorHandling(PEAR_ERROR_CALLBACK, array(&$obj, 'fakeHandleError')); + echoPEARStack('_PEAR_error_handler_stack', $GLOBALS['_PEAR_error_handler_stack']); + } + + function doPushErrorHandlingStatic() + { + print "testing in class pushErrorHandling array(class, method)\n"; + PEAR::pushErrorHandling(PEAR_ERROR_CALLBACK, array('testErrorHandlingStatic', 'fakeHandleError')); + echoPEARStack('_PEAR_error_handler_stack', $GLOBALS['_PEAR_error_handler_stack']); + } + + function doPopErrorHandling() + { + print "testing in class popErrorHandling\n"; + PEAR::popErrorHandling(); + echoPEARStack('_PEAR_error_handler_stack', $GLOBALS['_PEAR_error_handler_stack']); + } + + function fakeHandleError($err) + { + } +} + +class testErrorHandlingPEAR extends PEAR { + + function fakeHandleError($err) + { + } + + function doSetErrorHandlingFunction() + { + print "testing in PEAR setErrorHandling\n"; + PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'get_error_mode'); + echoPEARVars('_PEAR_default_error_mode', $GLOBALS['_PEAR_default_error_mode'], + '_PEAR_default_error_options', $GLOBALS['_PEAR_default_error_options']); + echoPEARVars('$this->_default_error_mode', $this->_default_error_mode, + '$this->_default_error_options', $this->_default_error_options); + } + + function doSetErrorHandlingStatic() + { + print "testing in PEAR setErrorHandling array(obj, method)\n"; + $obj = new testErrorHandlingPEAR; + PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array(&$obj, 'fakeHandleError')); + echoPEARVars('_PEAR_default_error_mode', $GLOBALS['_PEAR_default_error_mode'], + '_PEAR_default_error_options', $GLOBALS['_PEAR_default_error_options']); + echoPEARVars('$this->_default_error_mode', $this->_default_error_mode, + '$this->_default_error_options', $this->_default_error_options); + } + + function doSetErrorHandlingObject() + { + print "testing in PEAR setErrorHandling array(class, method)\n"; + PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array('testErrorHandlingStatic', 'fakeHandleError')); + echoPEARVars('_PEAR_default_error_mode', $GLOBALS['_PEAR_default_error_mode'], + '_PEAR_default_error_options', $GLOBALS['_PEAR_default_error_options']); + echoPEARVars('$this->_default_error_mode', $this->_default_error_mode, + '$this->_default_error_options', $this->_default_error_options); + } + + function doPushErrorHandlingFunction() + { + print "testing in PEAR pushErrorHandling\n"; + PEAR::pushErrorHandling(PEAR_ERROR_CALLBACK, 'get_error_mode'); + echoPEARStack('_PEAR_error_handler_stack', $GLOBALS['_PEAR_error_handler_stack']); + } + + function doPushErrorHandlingObject() + { + print "testing in PEAR pushErrorHandling array(obj, method)\n"; + $obj = new testErrorHandlingPEAR; + PEAR::pushErrorHandling(PEAR_ERROR_CALLBACK, array(&$obj, 'fakeHandleError')); + echoPEARStack('_PEAR_error_handler_stack', $GLOBALS['_PEAR_error_handler_stack']); + } + + function doPushErrorHandlingStatic() + { + print "testing in PEAR pushErrorHandling array(class, method)\n"; + PEAR::pushErrorHandling(PEAR_ERROR_CALLBACK, array('testErrorHandlingStatic', 'fakeHandleError')); + echoPEARStack('_PEAR_error_handler_stack', $GLOBALS['_PEAR_error_handler_stack']); + } + + function doPopErrorHandling() + { + print "testing in PEAR popErrorHandling\n"; + PEAR::popErrorHandling(); + echoPEARStack('_PEAR_error_handler_stack', $GLOBALS['_PEAR_error_handler_stack']); + } +} + +function echoPEARVars($name1, $mode, $name2, $options, $indent = '') +{ + $levelMap = + array( + E_USER_NOTICE => 'E_USER_NOTICE', + E_USER_WARNING => 'E_USER_WARNING', + E_USER_ERROR => 'E_USER_ERROR', + ); + $pearLevelMap = + array( + PEAR_ERROR_RETURN =>'PEAR_ERROR_RETURN', + PEAR_ERROR_PRINT =>'PEAR_ERROR_PRINT', + PEAR_ERROR_TRIGGER =>'PEAR_ERROR_TRIGGER', + PEAR_ERROR_DIE =>'PEAR_ERROR_DIE', + PEAR_ERROR_CALLBACK =>'PEAR_ERROR_CALLBACK', + PEAR_ERROR_EXCEPTION =>'PEAR_ERROR_EXCEPTION', + ); + print $indent . "echoing PEAR error-handling Variables:\n"; + print "$indent--------------------------------------\n"; + print $indent . "$name1:\n"; + $levels = get_error_mode($mode); + print $indent; + foreach($levels as $level) { + print $pearLevelMap[$level] . ','; + } + print "\n"; + print $indent . "$name2:\n"; + if (is_string($options)) { + print $indent . 'Callback: ' . $options. "()\n"; + } elseif (is_array($options)) { + print $indent . 'Callback: '; + if (is_string($options[0])) { + print '(static) ' . $options[0] . '::'; + } else { + print get_class($options[0]) . '->'; + } + print $options[1] . "()\n"; + } else { + print $indent . $levelMap[$options] . "\n"; + } + print "$indent--------------------------------------\n"; +} + +function echoPEARStack($name, $stack) +{ + print "stack $name:\n"; + foreach ($stack as $i => $item) { + print "Index $i:\n"; + echoPEARVars('mode', $item[0], 'options', $item[1], ' '); + } +} + +function get_error_mode($err) +{ + $ret = array(); + $level = 0; + while($level < 7) { + $a = ($err >> $level++) & 1; + if ($a) { + $ret[] = 1 << ($level - 1); + } + } + return $ret; +} +print "testing static error-handling global code\n"; +echoPEARVars('_PEAR_default_error_mode', $GLOBALS['_PEAR_default_error_mode'], + '_PEAR_default_error_options', $GLOBALS['_PEAR_default_error_options']); +print "testing setErrorHandling\n"; +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'get_error_mode'); +echoPEARVars('_PEAR_default_error_mode', $GLOBALS['_PEAR_default_error_mode'], + '_PEAR_default_error_options', $GLOBALS['_PEAR_default_error_options']); +print "testing setErrorHandling array(obj, method)\n"; +$obj = new testErrorHandlingPEAR; +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array(&$obj, 'fakeHandleError')); +echoPEARVars('_PEAR_default_error_mode', $GLOBALS['_PEAR_default_error_mode'], + '_PEAR_default_error_options', $GLOBALS['_PEAR_default_error_options']); +print "testing setErrorHandling array(class, method)\n"; +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array('testErrorHandlingStatic', 'fakeHandleError')); +echoPEARVars('_PEAR_default_error_mode', $GLOBALS['_PEAR_default_error_mode'], + '_PEAR_default_error_options', $GLOBALS['_PEAR_default_error_options']); + + +print "testing pushErrorHandling\n"; +PEAR::pushErrorHandling(PEAR_ERROR_CALLBACK, 'get_error_mode'); +echoPEARStack('_PEAR_error_handler_stack', $GLOBALS['_PEAR_error_handler_stack']); +print "testing pushErrorHandling array(obj, method)\n"; +$obj = new testErrorHandlingPEAR; +PEAR::pushErrorHandling(PEAR_ERROR_CALLBACK, array(&$obj, 'fakeHandleError')); +echoPEARStack('_PEAR_error_handler_stack', $GLOBALS['_PEAR_error_handler_stack']); +print "testing pushErrorHandling array(class, method)\n"; +PEAR::pushErrorHandling(PEAR_ERROR_CALLBACK, array('testErrorHandlingStatic', 'fakeHandleError')); +echoPEARStack('_PEAR_error_handler_stack', $GLOBALS['_PEAR_error_handler_stack']); + + +print "testing popErrorHandling\n"; +PEAR::popErrorHandling(); +echoPEARStack('_PEAR_error_handler_stack', $GLOBALS['_PEAR_error_handler_stack']); +print "testing popErrorHandling\n"; +$obj = new testErrorHandlingPEAR; +PEAR::popErrorHandling(); +echoPEARStack('_PEAR_error_handler_stack', $GLOBALS['_PEAR_error_handler_stack']); +print "testing popErrorHandling\n"; +PEAR::popErrorHandling(); +echoPEARStack('_PEAR_error_handler_stack', $GLOBALS['_PEAR_error_handler_stack']); +print "*******************************************\n"; +print "testing static error-handling in-class code\n"; +print "*******************************************\n"; +PEAR::setErrorHandling(PEAR_ERROR_RETURN, E_USER_NOTICE); +$obj = new testErrorHandlingStatic; +$obj->doSetErrorHandlingFunction(); +$obj->doSetErrorHandlingStatic(); +$obj->doSetErrorHandlingObject(); +$obj->doPushErrorHandlingFunction(); +$obj->doPushErrorHandlingStatic(); +$obj->doPushErrorHandlingObject(); +$obj->doPopErrorHandling(); +$obj->doPopErrorHandling(); +$obj->doPopErrorHandling(); +print "*******************************************\n"; +print "testing non-static error-handling in-class code\n"; +print "*******************************************\n"; +PEAR::setErrorHandling(PEAR_ERROR_RETURN, E_USER_NOTICE); +$obj = new testErrorHandlingPEAR; +$obj->doSetErrorHandlingFunction(); +$obj->doSetErrorHandlingStatic(); +$obj->doSetErrorHandlingObject(); +$obj->doPushErrorHandlingFunction(); +$obj->doPushErrorHandlingStatic(); +$obj->doPushErrorHandlingObject(); +$obj->doPopErrorHandling(); +$obj->doPopErrorHandling(); +$obj->doPopErrorHandling(); + +?> +--EXPECT-- +testing static error-handling global code +echoing PEAR error-handling Variables: +-------------------------------------- +_PEAR_default_error_mode: +PEAR_ERROR_RETURN, +_PEAR_default_error_options: +E_USER_NOTICE +-------------------------------------- +testing setErrorHandling +echoing PEAR error-handling Variables: +-------------------------------------- +_PEAR_default_error_mode: +PEAR_ERROR_CALLBACK, +_PEAR_default_error_options: +Callback: get_error_mode() +-------------------------------------- +testing setErrorHandling array(obj, method) +echoing PEAR error-handling Variables: +-------------------------------------- +_PEAR_default_error_mode: +PEAR_ERROR_CALLBACK, +_PEAR_default_error_options: +Callback: testerrorhandlingpear->fakeHandleError() +-------------------------------------- +testing setErrorHandling array(class, method) +echoing PEAR error-handling Variables: +-------------------------------------- +_PEAR_default_error_mode: +PEAR_ERROR_CALLBACK, +_PEAR_default_error_options: +Callback: (static) testErrorHandlingStatic::fakeHandleError() +-------------------------------------- +testing pushErrorHandling +stack _PEAR_error_handler_stack: +Index 0: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 1: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +testing pushErrorHandling array(obj, method) +stack _PEAR_error_handler_stack: +Index 0: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 1: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 2: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 3: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: testerrorhandlingpear->fakeHandleError() + -------------------------------------- +testing pushErrorHandling array(class, method) +stack _PEAR_error_handler_stack: +Index 0: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 1: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 2: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 3: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: testerrorhandlingpear->fakeHandleError() + -------------------------------------- +Index 4: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: testerrorhandlingpear->fakeHandleError() + -------------------------------------- +Index 5: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +testing popErrorHandling +stack _PEAR_error_handler_stack: +Index 0: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 1: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 2: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 3: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: testerrorhandlingpear->fakeHandleError() + -------------------------------------- +testing popErrorHandling +stack _PEAR_error_handler_stack: +Index 0: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 1: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +testing popErrorHandling +stack _PEAR_error_handler_stack: +******************************************* +testing static error-handling in-class code +******************************************* +testing in class setErrorHandling +echoing PEAR error-handling Variables: +-------------------------------------- +_PEAR_default_error_mode: +PEAR_ERROR_CALLBACK, +_PEAR_default_error_options: +Callback: get_error_mode() +-------------------------------------- +testing in class setErrorHandling array(obj, method) +echoing PEAR error-handling Variables: +-------------------------------------- +_PEAR_default_error_mode: +PEAR_ERROR_CALLBACK, +_PEAR_default_error_options: +Callback: testerrorhandlingpear->fakeHandleError() +-------------------------------------- +testing in class setErrorHandling array(class, method) +echoing PEAR error-handling Variables: +-------------------------------------- +_PEAR_default_error_mode: +PEAR_ERROR_CALLBACK, +_PEAR_default_error_options: +Callback: (static) testErrorHandlingStatic::fakeHandleError() +-------------------------------------- +testing in class pushErrorHandling +stack _PEAR_error_handler_stack: +Index 0: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 1: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +testing in class pushErrorHandling array(class, method) +stack _PEAR_error_handler_stack: +Index 0: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 1: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 2: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 3: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +testing in class pushErrorHandling array(obj, method) +stack _PEAR_error_handler_stack: +Index 0: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 1: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 2: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 3: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 4: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 5: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: testerrorhandlingpear->fakeHandleError() + -------------------------------------- +testing in class popErrorHandling +stack _PEAR_error_handler_stack: +Index 0: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 1: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 2: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 3: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +testing in class popErrorHandling +stack _PEAR_error_handler_stack: +Index 0: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 1: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +testing in class popErrorHandling +stack _PEAR_error_handler_stack: +******************************************* +testing non-static error-handling in-class code +******************************************* +testing in PEAR setErrorHandling +echoing PEAR error-handling Variables: +-------------------------------------- +_PEAR_default_error_mode: +PEAR_ERROR_RETURN, +_PEAR_default_error_options: +E_USER_NOTICE +-------------------------------------- +echoing PEAR error-handling Variables: +-------------------------------------- +$this->_default_error_mode: +PEAR_ERROR_CALLBACK, +$this->_default_error_options: +Callback: get_error_mode() +-------------------------------------- +testing in PEAR setErrorHandling array(obj, method) +echoing PEAR error-handling Variables: +-------------------------------------- +_PEAR_default_error_mode: +PEAR_ERROR_RETURN, +_PEAR_default_error_options: +E_USER_NOTICE +-------------------------------------- +echoing PEAR error-handling Variables: +-------------------------------------- +$this->_default_error_mode: +PEAR_ERROR_CALLBACK, +$this->_default_error_options: +Callback: testerrorhandlingpear->fakeHandleError() +-------------------------------------- +testing in PEAR setErrorHandling array(class, method) +echoing PEAR error-handling Variables: +-------------------------------------- +_PEAR_default_error_mode: +PEAR_ERROR_RETURN, +_PEAR_default_error_options: +E_USER_NOTICE +-------------------------------------- +echoing PEAR error-handling Variables: +-------------------------------------- +$this->_default_error_mode: +PEAR_ERROR_CALLBACK, +$this->_default_error_options: +Callback: (static) testErrorHandlingStatic::fakeHandleError() +-------------------------------------- +testing in PEAR pushErrorHandling +stack _PEAR_error_handler_stack: +Index 0: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 1: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +testing in PEAR pushErrorHandling array(class, method) +stack _PEAR_error_handler_stack: +Index 0: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 1: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 2: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 3: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +testing in PEAR pushErrorHandling array(obj, method) +stack _PEAR_error_handler_stack: +Index 0: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 1: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 2: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 3: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 4: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 5: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: testerrorhandlingpear->fakeHandleError() + -------------------------------------- +testing in PEAR popErrorHandling +stack _PEAR_error_handler_stack: +Index 0: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 1: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 2: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +Index 3: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +testing in PEAR popErrorHandling +stack _PEAR_error_handler_stack: +Index 0: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: (static) testErrorHandlingStatic::fakeHandleError() + -------------------------------------- +Index 1: + echoing PEAR error-handling Variables: + -------------------------------------- + mode: + PEAR_ERROR_CALLBACK, + options: + Callback: get_error_mode() + -------------------------------------- +testing in PEAR popErrorHandling +stack _PEAR_error_handler_stack: diff --git a/pear/tests/pear_autoloader.phpt b/pear/tests/pear_autoloader.phpt new file mode 100644 index 000000000..f25f4a411 --- /dev/null +++ b/pear/tests/pear_autoloader.phpt @@ -0,0 +1,81 @@ +--TEST-- +PEAR_Autoloader +--SKIPIF-- +skip +<?php /*if (!extension_loaded("overload")) die("skip\n"); */ ?> +--FILE-- +<?php + +include dirname(__FILE__)."/../PEAR/Autoloader.php"; + +class test1 extends PEAR_Autoloader { + function test1() { + $this->addAutoload(array( + 'testfunc1' => 'testclass1', + 'testfunca' => 'testclass1', + 'testfunc2' => 'testclass2', + 'testfuncb' => 'testclass2', + )); + } +} + +class testclass1 { + function testfunc1($a) { + print "testfunc1 arg=";var_dump($a); + return 1; + } + function testfunca($a) { + print "testfunca arg=";var_dump($a); + return 2; + } +} + +class testclass2 { + function testfunc2($b) { + print "testfunc2 arg=";var_dump($b); + return 3; + } + function testfuncb($b) { + print "testfuncb arg=";var_dump($b); + return 4; + } +} + +function dump($obj) { + print "mapped methods:"; + foreach ($obj->_method_map as $method => $object) { + print " $method"; + } + print "\n"; +} + +function call($msg, $retval) { + print "calling $msg returned $retval\n"; +} + +$obj = new test1; +dump($obj); +call("testfunc1", $obj->testfunc1(2)); +dump($obj); +call("testfunca", $obj->testfunca(2)); +dump($obj); +call("testfunc2", $obj->testfunc2(2)); +dump($obj); +call("testfuncb", $obj->testfuncb(2)); +dump($obj); + +?> +--EXPECT-- +mapped methods: +testfunc1 arg=int(2) +calling testfunc1 returned 1 +mapped methods: testfunc1 testfunca +testfunca arg=int(2) +calling testfunca returned 2 +mapped methods: testfunc1 testfunca +testfunc2 arg=int(2) +calling testfunc2 returned 3 +mapped methods: testfunc1 testfunca testfunc2 testfuncb +testfuncb arg=int(2) +calling testfuncb returned 4 +mapped methods: testfunc1 testfunca testfunc2 testfuncb diff --git a/pear/tests/pear_channelfile.phpt b/pear/tests/pear_channelfile.phpt new file mode 100644 index 000000000..838c57fbc --- /dev/null +++ b/pear/tests/pear_channelfile.phpt @@ -0,0 +1,1545 @@ +--TEST-- +PEAR_Channelfile +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php + +error_reporting(E_ALL); +chdir(dirname(__FILE__)); +include "PEAR/Channelfile.php"; +require_once 'PEAR/ErrorStack.php'; + +function logStack($err) +{ + echo "caught Error Stack error:\n"; + echo $err['message'] . "\n"; + echo 'code : ' . $err['code'] . "\n"; +} +PEAR_ErrorStack::setDefaultCallback('logStack'); +echo "test default\n"; +$chf = new PEAR_ChannelFile; +$chf->fromXmlString('<?xml version="1.0" encoding="ISO-8859-1" ?> +<channel version="1.0"> + <name>PEAR5</name> +<summary>PEAR packages for PHP 5</summary> +<server>pear.php.net</server> +<subchannels> +<subchannel name="PEAR5.qa"> +<server>qa.pear.php.net</server> +<summary>Quality Assurance releases of unmaintained packages</summary> +<deps><dep type="pkg" rel="ge" version="1.4">PEAR</dep> +<dep type="php" rel="ge" version="5.0.0"/></deps> +</subchannel> +<subchannel name="pear.boo"> +<server>boo.pear.php.net</server> +<summary>booya</summary> +<deps><dep type="pkg" rel="ge" version="1.5">PEAR</dep> +<dep type="php" rel="ge" version="5.1.0"/></deps> +</subchannel> +</subchannels> +<deps> + <dep type="php" rel="ge" version="5.0.0"/> +</deps> +</channel>'); + +echo "after parsing\n"; +var_dump($chf->validate()); +var_dump($chf->toArray()); +var_dump($chf->toXml()); +$chf->fromXmlString($chf->toXml()); + +echo "after re-parsing\n"; +var_dump($chf->validate()); +var_dump($chf->toArray()); +var_dump($chf->toXml()); + +echo "test compatibility\n"; +$chf = new PEAR_ChannelFile(true); +$chf->fromXmlString('<?xml version="1.0" encoding="ISO-8859-1" ?> +<channel version="1.0"> + <name>PEAR5</name> +<summary>PEAR packages for PHP 5</summary> +<server>pear.php.net</server> +<subchannels> +<subchannel name="PEAR5.qa"> +<server>qa.pear.php.net</server> +<summary>Quality Assurance releases of unmaintained packages</summary> +<deps><dep type="pkg" rel="ge" version="1.4">PEAR</dep> +<dep type="php" rel="ge" version="5.0.0"/></deps> +</subchannel> +<subchannel name="pear.boo"> +<server>boo.pear.php.net</server> +<summary>booya</summary> +<deps><dep type="pkg" rel="ge" version="1.5">PEAR</dep> +<dep type="php" rel="ge" version="5.1.0"/></deps> +</subchannel> +</subchannels> +<deps> + <dep type="php" rel="ge" version="5.0.0"/> +</deps> +</channel>'); + +echo "after parsing\n"; +var_dump($chf->validate()); +var_dump($chf->toArray()); +var_dump($chf->toXml()); +$chf->fromXmlString($chf->toXml()); + +echo "after re-parsing\n"; +var_dump($chf->validate()); +var_dump($chf->toArray()); +var_dump($chf->toXml()); + +echo "\ntest add packagenameregex\n"; +$chf->setPackageNameRegex('[A-Z]+'); +var_dump($chf->toArray()); +var_dump($chf->toXml()); +$chf->fromXmlString($chf->toXml()); + +echo "after re-parsing\n"; +var_dump($chf->validate()); +var_dump($chf->toArray()); +var_dump($chf->toXml()); + +echo "\ntest add protocols\n"; +$chf->addProtocol('xml-rpc', '1.0', 'package.listall'); +$chf->addProtocol('xml-rpc', '1.0', 'release.list'); +$chf->addProtocol('get', '1.0'); +var_dump($chf->toArray()); +var_dump($chf->toXml()); +$chf->fromXmlString($chf->toXml()); + +echo "after re-parsing\n"; +var_dump($chf->validate()); +var_dump($chf->toArray()); +var_dump($chf->toXml()); + +echo "\ntest add mirror\n"; +$chf->addMirror('server', 'mirror.php.net'); +$chf->addMirrorProtocol('mirror.php.net', 'xml-rpc', '1.0', 'package.listall'); +$chf->addMirrorProtocol('mirror.php.net', 'xml-rpc', '1.0', 'release.list'); +var_dump($chf->toArray()); +var_dump($chf->toXml()); +$chf->fromXmlString($chf->toXml()); + +echo "after re-parsing\n"; +var_dump($chf->validate()); +var_dump($chf->toArray()); +var_dump($chf->toXml()); +?> +--EXPECT-- +test default +after parsing +bool(true) +array(6) { + ["version"]=> + string(3) "1.0" + ["name"]=> + string(5) "pear5" + ["summary"]=> + string(23) "PEAR packages for PHP 5" + ["server"]=> + string(12) "pear.php.net" + ["subchannels"]=> + array(2) { + [1]=> + array(4) { + ["name"]=> + string(8) "pear5.qa" + ["server"]=> + string(15) "qa.pear.php.net" + ["summary"]=> + string(51) "Quality Assurance releases of unmaintained packages" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.4" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } + } + [2]=> + array(4) { + ["name"]=> + string(8) "pear.boo" + ["server"]=> + string(16) "boo.pear.php.net" + ["summary"]=> + string(5) "booya" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.5" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.1.0" + } + } + } + } + ["deps"]=> + array(1) { + [1]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } +} +string(823) "<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/channel-1.0"> +<channel version="1.0"> + <name>pear5</name> + <summary>PEAR packages for PHP 5</summary> + <server>pear.php.net</server> + <subchannels> + <subchannel name="pear5.qa" server="qa.pear.php.net"> + <summary>Quality Assurance releases of unmaintained packages</summary> + <deps> + <dep type="pkg" rel="ge" version="1.4">PEAR</dep> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> + </subchannel> + <subchannel name="pear.boo" server="boo.pear.php.net"> + <summary>booya</summary> + <deps> + <dep type="pkg" rel="ge" version="1.5">PEAR</dep> + <dep type="php" rel="ge" version="5.1.0"/> + </deps> + </subchannel> + </subchannels> + <deps> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> +</channel> +" +after re-parsing +bool(true) +array(6) { + ["version"]=> + string(3) "1.0" + ["name"]=> + string(5) "pear5" + ["summary"]=> + string(23) "PEAR packages for PHP 5" + ["server"]=> + string(12) "pear.php.net" + ["subchannels"]=> + array(2) { + [1]=> + array(4) { + ["name"]=> + string(8) "pear5.qa" + ["server"]=> + string(15) "qa.pear.php.net" + ["summary"]=> + string(51) "Quality Assurance releases of unmaintained packages" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.4" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } + } + [2]=> + array(4) { + ["name"]=> + string(8) "pear.boo" + ["server"]=> + string(16) "boo.pear.php.net" + ["summary"]=> + string(5) "booya" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.5" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.1.0" + } + } + } + } + ["deps"]=> + array(1) { + [1]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } +} +string(823) "<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/channel-1.0"> +<channel version="1.0"> + <name>pear5</name> + <summary>PEAR packages for PHP 5</summary> + <server>pear.php.net</server> + <subchannels> + <subchannel name="pear5.qa" server="qa.pear.php.net"> + <summary>Quality Assurance releases of unmaintained packages</summary> + <deps> + <dep type="pkg" rel="ge" version="1.4">PEAR</dep> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> + </subchannel> + <subchannel name="pear.boo" server="boo.pear.php.net"> + <summary>booya</summary> + <deps> + <dep type="pkg" rel="ge" version="1.5">PEAR</dep> + <dep type="php" rel="ge" version="5.1.0"/> + </deps> + </subchannel> + </subchannels> + <deps> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> +</channel> +" +test compatibility +after parsing +bool(true) +array(6) { + ["version"]=> + string(3) "1.0" + ["name"]=> + string(5) "pear5" + ["summary"]=> + string(23) "PEAR packages for PHP 5" + ["server"]=> + string(12) "pear.php.net" + ["subchannels"]=> + array(2) { + [1]=> + array(4) { + ["name"]=> + string(8) "pear5.qa" + ["server"]=> + string(15) "qa.pear.php.net" + ["summary"]=> + string(51) "Quality Assurance releases of unmaintained packages" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.4" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } + } + [2]=> + array(4) { + ["name"]=> + string(8) "pear.boo" + ["server"]=> + string(16) "boo.pear.php.net" + ["summary"]=> + string(5) "booya" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.5" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.1.0" + } + } + } + } + ["deps"]=> + array(1) { + [1]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } +} +string(823) "<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/channel-1.0"> +<channel version="1.0"> + <name>pear5</name> + <summary>PEAR packages for PHP 5</summary> + <server>pear.php.net</server> + <subchannels> + <subchannel name="pear5.qa" server="qa.pear.php.net"> + <summary>Quality Assurance releases of unmaintained packages</summary> + <deps> + <dep type="pkg" rel="ge" version="1.4">PEAR</dep> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> + </subchannel> + <subchannel name="pear.boo" server="boo.pear.php.net"> + <summary>booya</summary> + <deps> + <dep type="pkg" rel="ge" version="1.5">PEAR</dep> + <dep type="php" rel="ge" version="5.1.0"/> + </deps> + </subchannel> + </subchannels> + <deps> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> +</channel> +" +after re-parsing +bool(true) +array(6) { + ["version"]=> + string(3) "1.0" + ["name"]=> + string(5) "pear5" + ["summary"]=> + string(23) "PEAR packages for PHP 5" + ["server"]=> + string(12) "pear.php.net" + ["subchannels"]=> + array(2) { + [1]=> + array(4) { + ["name"]=> + string(8) "pear5.qa" + ["server"]=> + string(15) "qa.pear.php.net" + ["summary"]=> + string(51) "Quality Assurance releases of unmaintained packages" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.4" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } + } + [2]=> + array(4) { + ["name"]=> + string(8) "pear.boo" + ["server"]=> + string(16) "boo.pear.php.net" + ["summary"]=> + string(5) "booya" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.5" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.1.0" + } + } + } + } + ["deps"]=> + array(1) { + [1]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } +} +string(823) "<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/channel-1.0"> +<channel version="1.0"> + <name>pear5</name> + <summary>PEAR packages for PHP 5</summary> + <server>pear.php.net</server> + <subchannels> + <subchannel name="pear5.qa" server="qa.pear.php.net"> + <summary>Quality Assurance releases of unmaintained packages</summary> + <deps> + <dep type="pkg" rel="ge" version="1.4">PEAR</dep> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> + </subchannel> + <subchannel name="pear.boo" server="boo.pear.php.net"> + <summary>booya</summary> + <deps> + <dep type="pkg" rel="ge" version="1.5">PEAR</dep> + <dep type="php" rel="ge" version="5.1.0"/> + </deps> + </subchannel> + </subchannels> + <deps> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> +</channel> +" + +test add packagenameregex +array(7) { + ["version"]=> + string(3) "1.0" + ["name"]=> + string(5) "pear5" + ["summary"]=> + string(23) "PEAR packages for PHP 5" + ["server"]=> + string(12) "pear.php.net" + ["subchannels"]=> + array(2) { + [1]=> + array(4) { + ["name"]=> + string(8) "pear5.qa" + ["server"]=> + string(15) "qa.pear.php.net" + ["summary"]=> + string(51) "Quality Assurance releases of unmaintained packages" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.4" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } + } + [2]=> + array(4) { + ["name"]=> + string(8) "pear.boo" + ["server"]=> + string(16) "boo.pear.php.net" + ["summary"]=> + string(5) "booya" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.5" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.1.0" + } + } + } + } + ["deps"]=> + array(1) { + [1]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } + ["packagenameregex"]=> + string(6) "[A-Z]+" +} +string(868) "<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/channel-1.0"> +<channel version="1.0"> + <name>pear5</name> + <summary>PEAR packages for PHP 5</summary> + <server>pear.php.net</server> + <packagenameregex>[A-Z]+</packagenameregex> + <subchannels> + <subchannel name="pear5.qa" server="qa.pear.php.net"> + <summary>Quality Assurance releases of unmaintained packages</summary> + <deps> + <dep type="pkg" rel="ge" version="1.4">PEAR</dep> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> + </subchannel> + <subchannel name="pear.boo" server="boo.pear.php.net"> + <summary>booya</summary> + <deps> + <dep type="pkg" rel="ge" version="1.5">PEAR</dep> + <dep type="php" rel="ge" version="5.1.0"/> + </deps> + </subchannel> + </subchannels> + <deps> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> +</channel> +" +after re-parsing +bool(true) +array(7) { + ["version"]=> + string(3) "1.0" + ["name"]=> + string(5) "pear5" + ["summary"]=> + string(23) "PEAR packages for PHP 5" + ["server"]=> + string(12) "pear.php.net" + ["packagenameregex"]=> + string(6) "[A-Z]+" + ["subchannels"]=> + array(2) { + [1]=> + array(4) { + ["name"]=> + string(8) "pear5.qa" + ["server"]=> + string(15) "qa.pear.php.net" + ["summary"]=> + string(51) "Quality Assurance releases of unmaintained packages" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.4" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } + } + [2]=> + array(4) { + ["name"]=> + string(8) "pear.boo" + ["server"]=> + string(16) "boo.pear.php.net" + ["summary"]=> + string(5) "booya" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.5" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.1.0" + } + } + } + } + ["deps"]=> + array(1) { + [1]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } +} +string(868) "<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/channel-1.0"> +<channel version="1.0"> + <name>pear5</name> + <summary>PEAR packages for PHP 5</summary> + <server>pear.php.net</server> + <packagenameregex>[A-Z]+</packagenameregex> + <subchannels> + <subchannel name="pear5.qa" server="qa.pear.php.net"> + <summary>Quality Assurance releases of unmaintained packages</summary> + <deps> + <dep type="pkg" rel="ge" version="1.4">PEAR</dep> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> + </subchannel> + <subchannel name="pear.boo" server="boo.pear.php.net"> + <summary>booya</summary> + <deps> + <dep type="pkg" rel="ge" version="1.5">PEAR</dep> + <dep type="php" rel="ge" version="5.1.0"/> + </deps> + </subchannel> + </subchannels> + <deps> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> +</channel> +" + +test add protocols +array(8) { + ["version"]=> + string(3) "1.0" + ["name"]=> + string(5) "pear5" + ["summary"]=> + string(23) "PEAR packages for PHP 5" + ["server"]=> + string(12) "pear.php.net" + ["packagenameregex"]=> + string(6) "[A-Z]+" + ["subchannels"]=> + array(2) { + [1]=> + array(4) { + ["name"]=> + string(8) "pear5.qa" + ["server"]=> + string(15) "qa.pear.php.net" + ["summary"]=> + string(51) "Quality Assurance releases of unmaintained packages" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.4" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } + } + [2]=> + array(4) { + ["name"]=> + string(8) "pear.boo" + ["server"]=> + string(16) "boo.pear.php.net" + ["summary"]=> + string(5) "booya" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.5" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.1.0" + } + } + } + } + ["deps"]=> + array(1) { + [1]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } + ["provides"]=> + array(3) { + [1]=> + array(3) { + ["type"]=> + string(7) "xml-rpc" + ["version"]=> + string(3) "1.0" + ["name"]=> + string(15) "package.listall" + } + [2]=> + array(3) { + ["type"]=> + string(7) "xml-rpc" + ["version"]=> + string(3) "1.0" + ["name"]=> + string(12) "release.list" + } + [3]=> + array(2) { + ["type"]=> + string(3) "get" + ["version"]=> + string(3) "1.0" + } + } +} +string(1065) "<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/channel-1.0"> +<channel version="1.0"> + <name>pear5</name> + <summary>PEAR packages for PHP 5</summary> + <server>pear.php.net</server> + <provides> + <protocol type="xml-rpc" version="1.0">package.listall</protocol> + <protocol type="xml-rpc" version="1.0">release.list</protocol> + <protocol type="get" version="1.0"/> + </provides> + <packagenameregex>[A-Z]+</packagenameregex> + <subchannels> + <subchannel name="pear5.qa" server="qa.pear.php.net"> + <summary>Quality Assurance releases of unmaintained packages</summary> + <deps> + <dep type="pkg" rel="ge" version="1.4">PEAR</dep> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> + </subchannel> + <subchannel name="pear.boo" server="boo.pear.php.net"> + <summary>booya</summary> + <deps> + <dep type="pkg" rel="ge" version="1.5">PEAR</dep> + <dep type="php" rel="ge" version="5.1.0"/> + </deps> + </subchannel> + </subchannels> + <deps> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> +</channel> +" +after re-parsing +bool(true) +array(8) { + ["version"]=> + string(3) "1.0" + ["name"]=> + string(5) "pear5" + ["summary"]=> + string(23) "PEAR packages for PHP 5" + ["server"]=> + string(12) "pear.php.net" + ["provides"]=> + array(3) { + [1]=> + array(3) { + ["type"]=> + string(7) "xml-rpc" + ["version"]=> + string(3) "1.0" + ["name"]=> + string(15) "package.listall" + } + [2]=> + array(3) { + ["type"]=> + string(7) "xml-rpc" + ["version"]=> + string(3) "1.0" + ["name"]=> + string(12) "release.list" + } + [3]=> + array(2) { + ["type"]=> + string(3) "get" + ["version"]=> + string(3) "1.0" + } + } + ["packagenameregex"]=> + string(6) "[A-Z]+" + ["subchannels"]=> + array(2) { + [1]=> + array(4) { + ["name"]=> + string(8) "pear5.qa" + ["server"]=> + string(15) "qa.pear.php.net" + ["summary"]=> + string(51) "Quality Assurance releases of unmaintained packages" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.4" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } + } + [2]=> + array(4) { + ["name"]=> + string(8) "pear.boo" + ["server"]=> + string(16) "boo.pear.php.net" + ["summary"]=> + string(5) "booya" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.5" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.1.0" + } + } + } + } + ["deps"]=> + array(1) { + [1]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } +} +string(1065) "<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/channel-1.0"> +<channel version="1.0"> + <name>pear5</name> + <summary>PEAR packages for PHP 5</summary> + <server>pear.php.net</server> + <provides> + <protocol type="xml-rpc" version="1.0">package.listall</protocol> + <protocol type="xml-rpc" version="1.0">release.list</protocol> + <protocol type="get" version="1.0"/> + </provides> + <packagenameregex>[A-Z]+</packagenameregex> + <subchannels> + <subchannel name="pear5.qa" server="qa.pear.php.net"> + <summary>Quality Assurance releases of unmaintained packages</summary> + <deps> + <dep type="pkg" rel="ge" version="1.4">PEAR</dep> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> + </subchannel> + <subchannel name="pear.boo" server="boo.pear.php.net"> + <summary>booya</summary> + <deps> + <dep type="pkg" rel="ge" version="1.5">PEAR</dep> + <dep type="php" rel="ge" version="5.1.0"/> + </deps> + </subchannel> + </subchannels> + <deps> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> +</channel> +" + +test add mirror +array(9) { + ["version"]=> + string(3) "1.0" + ["name"]=> + string(5) "pear5" + ["summary"]=> + string(23) "PEAR packages for PHP 5" + ["server"]=> + string(12) "pear.php.net" + ["provides"]=> + array(3) { + [1]=> + array(3) { + ["type"]=> + string(7) "xml-rpc" + ["version"]=> + string(3) "1.0" + ["name"]=> + string(15) "package.listall" + } + [2]=> + array(3) { + ["type"]=> + string(7) "xml-rpc" + ["version"]=> + string(3) "1.0" + ["name"]=> + string(12) "release.list" + } + [3]=> + array(2) { + ["type"]=> + string(3) "get" + ["version"]=> + string(3) "1.0" + } + } + ["packagenameregex"]=> + string(6) "[A-Z]+" + ["subchannels"]=> + array(2) { + [1]=> + array(4) { + ["name"]=> + string(8) "pear5.qa" + ["server"]=> + string(15) "qa.pear.php.net" + ["summary"]=> + string(51) "Quality Assurance releases of unmaintained packages" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.4" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } + } + [2]=> + array(4) { + ["name"]=> + string(8) "pear.boo" + ["server"]=> + string(16) "boo.pear.php.net" + ["summary"]=> + string(5) "booya" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.5" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.1.0" + } + } + } + } + ["deps"]=> + array(1) { + [1]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } + ["mirrors"]=> + array(1) { + [1]=> + array(3) { + ["type"]=> + string(6) "server" + ["name"]=> + string(14) "mirror.php.net" + ["provides"]=> + array(2) { + [1]=> + array(3) { + ["type"]=> + string(7) "xml-rpc" + ["version"]=> + string(3) "1.0" + ["name"]=> + string(15) "package.listall" + } + [2]=> + array(3) { + ["type"]=> + string(7) "xml-rpc" + ["version"]=> + string(3) "1.0" + ["name"]=> + string(12) "release.list" + } + } + } + } +} +string(1313) "<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/channel-1.0"> +<channel version="1.0"> + <name>pear5</name> + <summary>PEAR packages for PHP 5</summary> + <server>pear.php.net</server> + <provides> + <protocol type="xml-rpc" version="1.0">package.listall</protocol> + <protocol type="xml-rpc" version="1.0">release.list</protocol> + <protocol type="get" version="1.0"/> + </provides> + <packagenameregex>[A-Z]+</packagenameregex> + <mirrors> + <mirror type="server" name="mirror.php.net"> + <provides> + <protocol type="xml-rpc" version="1.0">package.listall</protocol> + <protocol type="xml-rpc" version="1.0">release.list</protocol> + </provides> + </mirror> + </mirrors> + <subchannels> + <subchannel name="pear5.qa" server="qa.pear.php.net"> + <summary>Quality Assurance releases of unmaintained packages</summary> + <deps> + <dep type="pkg" rel="ge" version="1.4">PEAR</dep> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> + </subchannel> + <subchannel name="pear.boo" server="boo.pear.php.net"> + <summary>booya</summary> + <deps> + <dep type="pkg" rel="ge" version="1.5">PEAR</dep> + <dep type="php" rel="ge" version="5.1.0"/> + </deps> + </subchannel> + </subchannels> + <deps> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> +</channel> +" +after re-parsing +bool(true) +array(9) { + ["version"]=> + string(3) "1.0" + ["name"]=> + string(5) "pear5" + ["summary"]=> + string(23) "PEAR packages for PHP 5" + ["server"]=> + string(12) "pear.php.net" + ["provides"]=> + array(3) { + [1]=> + array(3) { + ["type"]=> + string(7) "xml-rpc" + ["version"]=> + string(3) "1.0" + ["name"]=> + string(15) "package.listall" + } + [2]=> + array(3) { + ["type"]=> + string(7) "xml-rpc" + ["version"]=> + string(3) "1.0" + ["name"]=> + string(12) "release.list" + } + [3]=> + array(2) { + ["type"]=> + string(3) "get" + ["version"]=> + string(3) "1.0" + } + } + ["packagenameregex"]=> + string(6) "[A-Z]+" + ["mirrors"]=> + array(1) { + [1]=> + array(3) { + ["type"]=> + string(6) "server" + ["name"]=> + string(14) "mirror.php.net" + ["provides"]=> + array(2) { + [1]=> + array(3) { + ["type"]=> + string(7) "xml-rpc" + ["version"]=> + string(3) "1.0" + ["name"]=> + string(15) "package.listall" + } + [2]=> + array(3) { + ["type"]=> + string(7) "xml-rpc" + ["version"]=> + string(3) "1.0" + ["name"]=> + string(12) "release.list" + } + } + } + } + ["subchannels"]=> + array(2) { + [1]=> + array(4) { + ["name"]=> + string(8) "pear5.qa" + ["server"]=> + string(15) "qa.pear.php.net" + ["summary"]=> + string(51) "Quality Assurance releases of unmaintained packages" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.4" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } + } + [2]=> + array(4) { + ["name"]=> + string(8) "pear.boo" + ["server"]=> + string(16) "boo.pear.php.net" + ["summary"]=> + string(5) "booya" + ["deps"]=> + array(2) { + [1]=> + array(4) { + ["type"]=> + string(3) "pkg" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(3) "1.5" + ["name"]=> + string(4) "PEAR" + } + [2]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.1.0" + } + } + } + } + ["deps"]=> + array(1) { + [1]=> + array(3) { + ["type"]=> + string(3) "php" + ["rel"]=> + string(2) "ge" + ["version"]=> + string(5) "5.0.0" + } + } +} +string(1313) "<?xml version="1.0" encoding="ISO-8859-1" ?> +<!DOCTYPE package SYSTEM "http://pear.php.net/dtd/channel-1.0"> +<channel version="1.0"> + <name>pear5</name> + <summary>PEAR packages for PHP 5</summary> + <server>pear.php.net</server> + <provides> + <protocol type="xml-rpc" version="1.0">package.listall</protocol> + <protocol type="xml-rpc" version="1.0">release.list</protocol> + <protocol type="get" version="1.0"/> + </provides> + <packagenameregex>[A-Z]+</packagenameregex> + <mirrors> + <mirror type="server" name="mirror.php.net"> + <provides> + <protocol type="xml-rpc" version="1.0">package.listall</protocol> + <protocol type="xml-rpc" version="1.0">release.list</protocol> + </provides> + </mirror> + </mirrors> + <subchannels> + <subchannel name="pear5.qa" server="qa.pear.php.net"> + <summary>Quality Assurance releases of unmaintained packages</summary> + <deps> + <dep type="pkg" rel="ge" version="1.4">PEAR</dep> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> + </subchannel> + <subchannel name="pear.boo" server="boo.pear.php.net"> + <summary>booya</summary> + <deps> + <dep type="pkg" rel="ge" version="1.5">PEAR</dep> + <dep type="php" rel="ge" version="5.1.0"/> + </deps> + </subchannel> + </subchannels> + <deps> + <dep type="php" rel="ge" version="5.0.0"/> + </deps> +</channel> +"
\ No newline at end of file diff --git a/pear/tests/pear_common_analyzeSC.phpt b/pear/tests/pear_common_analyzeSC.phpt new file mode 100644 index 000000000..0c15a66c8 --- /dev/null +++ b/pear/tests/pear_common_analyzeSC.phpt @@ -0,0 +1,165 @@ +--TEST-- +PEAR_Common::analyzeSourceCode test +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +if (!function_exists('token_get_all')) { + echo 'skip'; +} +?> +--FILE-- +<?php + +require_once "PEAR/Common.php"; + +$x = PEAR_Common::analyzeSourceCode('=+"\\//452'); +echo "first test: returns false with non-existing filename? "; +echo $x ? "no\n" : "yes\n"; + +$testdir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pear_common_analyzeSCtest'; +mkdir($testdir); + +$test1 = ' +<?php +::error(); +?> +'; +$fp = fopen($testdir . DIRECTORY_SEPARATOR . 'test1.php', 'w'); +fwrite($fp, $test1); +fclose($fp); + +$ret = PEAR_Common::analyzeSourceCode($testdir . DIRECTORY_SEPARATOR . 'test1.php'); +echo "second test: returns false with invalid PHP? "; +echo $ret ? "no\n" : "yes\n"; +unlink($testdir . DIRECTORY_SEPARATOR . 'test1.php'); + +$test3 = ' +<?php +class test +{ + class test2 { + } +} +?> +'; +$fp = fopen($testdir . DIRECTORY_SEPARATOR . 'test3.php', 'w'); +fwrite($fp, $test3); +fclose($fp); + +$ret = PEAR_Common::analyzeSourceCode($testdir . DIRECTORY_SEPARATOR . 'test3.php'); +echo "fourth test: returns false with invalid PHP? "; +echo $ret ? "no\n" : "yes\n"; +unlink($testdir . DIRECTORY_SEPARATOR . 'test3.php'); + +$test4 = ' +<?php +function test() +{ + class test2 { + } +} +?> +'; +$fp = fopen($testdir . DIRECTORY_SEPARATOR . 'test4.php', 'w'); +fwrite($fp, $test4); +fclose($fp); + +$ret = PEAR_Common::analyzeSourceCode($testdir . DIRECTORY_SEPARATOR . 'test4.php'); +echo "fifth test: returns false with invalid PHP? "; +echo $ret ? "no\n" : "yes\n"; +unlink($testdir . DIRECTORY_SEPARATOR . 'test4.php'); + +$test5 = ' +<?php +function test() +{ +} + +if (trytofool) { + function fool() + { + } +} +class test2 { + function test2() { + parent::unused(); + Greg::classes(); + $a = new Pierre; + } +} + +class blah extends test2 { + /** + * @nodep Stig + */ + function blah() + { + Stig::rules(); + } +} +?> +'; +$fp = fopen($testdir . DIRECTORY_SEPARATOR . 'test5.php', 'w'); +fwrite($fp, $test5); +fclose($fp); + +$ret = PEAR_Common::analyzeSourceCode($testdir . DIRECTORY_SEPARATOR . 'test5.php'); +echo "sixth test: returns false with valid PHP? "; +echo $ret ? "no\n" : "yes\n"; +$ret['source_file'] = str_replace(array(dirname(__FILE__),DIRECTORY_SEPARATOR), array('', '/'), $ret['source_file']); +var_dump($ret); +unlink($testdir . DIRECTORY_SEPARATOR . 'test5.php'); + +rmdir($testdir); +?> +--EXPECT-- +first test: returns false with non-existing filename? yes +second test: returns false with invalid PHP? yes +fourth test: returns false with invalid PHP? yes +fifth test: returns false with invalid PHP? yes +sixth test: returns false with valid PHP? no +array(6) { + ["source_file"]=> + string(36) "/pear_common_analyzeSCtest/test5.php" + ["declared_classes"]=> + array(2) { + [0]=> + string(5) "test2" + [1]=> + string(4) "blah" + } + ["declared_methods"]=> + array(2) { + ["test2"]=> + array(1) { + [0]=> + string(5) "test2" + } + ["blah"]=> + array(1) { + [0]=> + string(4) "blah" + } + } + ["declared_functions"]=> + array(2) { + [0]=> + string(4) "test" + [1]=> + string(4) "fool" + } + ["used_classes"]=> + array(2) { + [0]=> + string(4) "Greg" + [1]=> + string(6) "Pierre" + } + ["inheritance"]=> + array(1) { + ["blah"]=> + string(5) "test2" + } +}
\ No newline at end of file diff --git a/pear/tests/pear_common_buildProvidesArray.phpt b/pear/tests/pear_common_buildProvidesArray.phpt new file mode 100644 index 000000000..574ed4465 --- /dev/null +++ b/pear/tests/pear_common_buildProvidesArray.phpt @@ -0,0 +1,152 @@ +--TEST-- +PEAR_Common::buildProvidesArray test +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +if (!function_exists('token_get_all')) { + echo 'skip'; +} +?> +--FILE-- +<?php + +require_once "PEAR/Common.php"; + +$testdir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pear_common_buildProvidesArraytest'; +mkdir($testdir); + +$test5 = ' +<?php +function test() +{ +} + +if (trytofool) { + function fool() + { + } +} +class test2 { + function test2() { + parent::unused(); + Greg::classes(); + $a = new Pierre; + } +} + +class blah extends test2 { + /** + * @nodep Stig + */ + function blah() + { + Stig::rules(); + } +} +?> +'; +$fp = fopen($testdir . DIRECTORY_SEPARATOR . 'test5.php', 'w'); +fwrite($fp, $test5); +fclose($fp); + +$ret = PEAR_Common::analyzeSourceCode($testdir . DIRECTORY_SEPARATOR . 'test5.php'); +echo "pre-test: returns false with valid PHP? "; +echo $ret ? "no\n" : "yes\n"; +$ret['source_file'] = str_replace(array(dirname(__FILE__),DIRECTORY_SEPARATOR), array('', '/'), $ret['source_file']); +var_dump($ret); +unlink($testdir . DIRECTORY_SEPARATOR . 'test5.php'); +$common = new PEAR_Common; +$common->buildProvidesArray($ret); +var_dump($common->pkginfo); +rmdir($testdir); +?> +--EXPECT-- +pre-test: returns false with valid PHP? no +array(6) { + ["source_file"]=> + string(45) "/pear_common_buildProvidesArraytest/test5.php" + ["declared_classes"]=> + array(2) { + [0]=> + string(5) "test2" + [1]=> + string(4) "blah" + } + ["declared_methods"]=> + array(2) { + ["test2"]=> + array(1) { + [0]=> + string(5) "test2" + } + ["blah"]=> + array(1) { + [0]=> + string(4) "blah" + } + } + ["declared_functions"]=> + array(2) { + [0]=> + string(4) "test" + [1]=> + string(4) "fool" + } + ["used_classes"]=> + array(2) { + [0]=> + string(4) "Greg" + [1]=> + string(6) "Pierre" + } + ["inheritance"]=> + array(1) { + ["blah"]=> + string(5) "test2" + } +} +array(1) { + ["provides"]=> + array(4) { + ["class;test2"]=> + array(3) { + ["file"]=> + string(9) "test5.php" + ["type"]=> + string(5) "class" + ["name"]=> + string(5) "test2" + } + ["class;blah"]=> + array(4) { + ["file"]=> + string(9) "test5.php" + ["type"]=> + string(5) "class" + ["name"]=> + string(4) "blah" + ["extends"]=> + string(5) "test2" + } + ["function;test"]=> + array(3) { + ["file"]=> + string(9) "test5.php" + ["type"]=> + string(8) "function" + ["name"]=> + string(4) "test" + } + ["function;fool"]=> + array(3) { + ["file"]=> + string(9) "test5.php" + ["type"]=> + string(8) "function" + ["name"]=> + string(4) "fool" + } + } +}
\ No newline at end of file diff --git a/pear/tests/pear_common_downloadHttp.phpt b/pear/tests/pear_common_downloadHttp.phpt new file mode 100644 index 000000000..86f7cc2bf --- /dev/null +++ b/pear/tests/pear_common_downloadHttp.phpt @@ -0,0 +1,214 @@ +--TEST-- +PEAR_Common::downloadHttp test +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +$fp = @fsockopen('pear.php.net', 80); +if (!$fp) { + echo 'skip'; +} else { + fclose($fp); +} +?> +--FILE-- +<?php +mkdir($temp_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'testDownloadHttp'); +// make the fake configuration - we'll use one of these and it should work +$config = serialize(array('master_server' => 'pear.php.net', + 'php_dir' => $temp_path . DIRECTORY_SEPARATOR . 'php', + 'ext_dir' => $temp_path . DIRECTORY_SEPARATOR . 'ext', + 'data_dir' => $temp_path . DIRECTORY_SEPARATOR . 'data', + 'doc_dir' => $temp_path . DIRECTORY_SEPARATOR . 'doc', + 'test_dir' => $temp_path . DIRECTORY_SEPARATOR . 'test', + 'bin_dir' => $temp_path . DIRECTORY_SEPARATOR . 'bin',)); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.conf'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.conf', 'w'); +fwrite($fp, $config); +fclose($fp); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.ini'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.ini', 'w'); +fwrite($fp, $config); +fclose($fp); + +putenv('PHP_PEAR_SYSCONF_DIR=' . $temp_path); +$home = getenv('HOME'); +if (!empty($home)) { + // for PEAR_Config initialization + putenv('HOME="'.$temp_path); +} + +require_once "PEAR/Common.php"; + +$common = &new PEAR_Common; + +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'catchit'); + +function catchit($err) +{ + echo "Caught error: " . $err->getMessage() . "\n"; +} + +echo "Test static:\n"; + +echo "Simple: "; +PEAR_Common::downloadHttp('http://test.pear.php.net/testdownload.tgz', $ui, $temp_path); +$firstone = implode('', file(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'testdownload.tgz')); +$secondone = implode('', file($temp_path . DIRECTORY_SEPARATOR . 'testdownload.tgz')); +echo ($firstone == $secondone) ? "passed\n" : "failed\n"; + +echo "Simple fail:\n"; +PEAR_Common::downloadHttp('http://test.poop.php.net/stuff.tgz', $ui, $temp_path); + +echo "Test callback:\n"; + +$ui = 'My UI'; + +PEAR_Common::downloadHttp('http://test.pear.php.net/testdownload.tgz', $ui, $temp_path, 'myCallback'); +$firstone = implode('', file(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'testdownload.tgz')); +$secondone = implode('', file($temp_path . DIRECTORY_SEPARATOR . 'testdownload.tgz')); +echo "Working Callback: "; +echo ($firstone == $secondone) ? "passed\n" : "failed\n"; + + +function myCallback($message, $payload) +{ + $stuff = serialize($payload); + echo "Callback Message: $message\n"; + echo "Callback Payload: $stuff\n"; +} + +echo "Callback fail:\n"; +PEAR_Common::downloadHttp('http://test.poop.php.net/stuff.tgz', $ui, $temp_path, 'myCallback'); + +cleanall($temp_path); + +// ------------------------------------------------------------------------- // + +function cleanall($dir) +{ + $dp = opendir($dir); + while ($ent = readdir($dp)) { + if ($ent == '.' || $ent == '..') { + continue; + } + if (is_dir($dir . DIRECTORY_SEPARATOR . $ent)) { + cleanall($dir . DIRECTORY_SEPARATOR . $ent); + } else { + unlink($dir . DIRECTORY_SEPARATOR . $ent); + } + } + closedir($dp); + rmdir($dir); +} +?> +--EXPECT-- +Test static: +Simple: passed +Simple fail: +Caught error: Connection to `test.poop.php.net:80' failed: The operation completed successfully. + +Test callback: +Callback Message: setup +Callback Payload: a:1:{i:0;s:5:"My UI";} +Callback Message: message +Callback Payload: s:35:"Using HTTP proxy test.pear.php.net:"; +Callback Message: saveas +Callback Payload: s:16:"testdownload.tgz"; +Callback Message: start +Callback Payload: a:2:{i:0;s:16:"testdownload.tgz";i:1;s:5:"41655";} +Callback Message: bytesread +Callback Payload: i:1024; +Callback Message: bytesread +Callback Payload: i:2048; +Callback Message: bytesread +Callback Payload: i:3072; +Callback Message: bytesread +Callback Payload: i:4096; +Callback Message: bytesread +Callback Payload: i:5120; +Callback Message: bytesread +Callback Payload: i:6144; +Callback Message: bytesread +Callback Payload: i:7168; +Callback Message: bytesread +Callback Payload: i:8192; +Callback Message: bytesread +Callback Payload: i:9216; +Callback Message: bytesread +Callback Payload: i:10240; +Callback Message: bytesread +Callback Payload: i:11264; +Callback Message: bytesread +Callback Payload: i:12288; +Callback Message: bytesread +Callback Payload: i:13312; +Callback Message: bytesread +Callback Payload: i:14336; +Callback Message: bytesread +Callback Payload: i:15360; +Callback Message: bytesread +Callback Payload: i:16384; +Callback Message: bytesread +Callback Payload: i:17408; +Callback Message: bytesread +Callback Payload: i:18432; +Callback Message: bytesread +Callback Payload: i:19456; +Callback Message: bytesread +Callback Payload: i:20480; +Callback Message: bytesread +Callback Payload: i:21504; +Callback Message: bytesread +Callback Payload: i:22528; +Callback Message: bytesread +Callback Payload: i:23552; +Callback Message: bytesread +Callback Payload: i:24576; +Callback Message: bytesread +Callback Payload: i:25600; +Callback Message: bytesread +Callback Payload: i:26624; +Callback Message: bytesread +Callback Payload: i:27648; +Callback Message: bytesread +Callback Payload: i:28672; +Callback Message: bytesread +Callback Payload: i:29696; +Callback Message: bytesread +Callback Payload: i:30720; +Callback Message: bytesread +Callback Payload: i:31744; +Callback Message: bytesread +Callback Payload: i:32768; +Callback Message: bytesread +Callback Payload: i:33792; +Callback Message: bytesread +Callback Payload: i:34816; +Callback Message: bytesread +Callback Payload: i:35840; +Callback Message: bytesread +Callback Payload: i:36864; +Callback Message: bytesread +Callback Payload: i:37888; +Callback Message: bytesread +Callback Payload: i:38912; +Callback Message: bytesread +Callback Payload: i:39936; +Callback Message: bytesread +Callback Payload: i:40960; +Callback Message: bytesread +Callback Payload: i:41655; +Callback Message: done +Callback Payload: i:41655; +Working Callback: passed +Callback fail: +Callback Message: setup +Callback Payload: a:1:{i:0;s:5:"My UI";} +Callback Message: message +Callback Payload: s:35:"Using HTTP proxy test.poop.php.net:"; +Callback Message: connfailed +Callback Payload: a:4:{i:0;s:17:"test.poop.php.net";i:1;i:80;i:2;i:0;i:3;s:39:"The operation completed successfully. +";} +Caught error: Connection to `test.poop.php.net:80' failed: The operation completed successfully.
\ No newline at end of file diff --git a/pear/tests/pear_common_infoFromString.phpt b/pear/tests/pear_common_infoFromString.phpt new file mode 100644 index 000000000..f3d40464c --- /dev/null +++ b/pear/tests/pear_common_infoFromString.phpt @@ -0,0 +1,1752 @@ +--TEST-- +PEAR_Common::infoFromString test +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +if (!function_exists('token_get_all')) { + echo 'skip'; +} +?> +--FILE-- +<?php +putenv('PHP_PEAR_SYSCONF_DIR=' . dirname(__FILE__)); + +require_once "PEAR/Common.php"; + +$common = &new PEAR_Common; + +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'catchit'); + +function catchit($err) +{ + echo "Caught error: " . $err->getMessage() . "\n"; +} + +echo "Test invalid XML\n"; + +$common->infoFromString('\\goober'); + +echo "Test valid XML, not a package.xml\n"; + +$common->infoFromString('<?xml version="1.0" encoding="ISO-8859-1" ?>' . + "\n<grobbage></grobbage>"); + +echo "Test valid package.xml, invalid version number\n"; + +$common->infoFromString('<?xml version="1.0" encoding="ISO-8859-1" ?>' . + '<package version="10000000"></package>'); + +echo "Test empty package.xml\n"; + +$ret = $common->infoFromString('<?xml version="1.0" encoding="ISO-8859-1" ?>' . + '<package version="1.0"></package>'); + +var_dump($ret); + +echo "Test 1\n"; + +$ret = $common->infoFromString('<?xml version="1.0" encoding="ISO-8859-1" ?>' . + '<package version="1.0"><name>test</name></package>'); + +var_dump($ret); + +echo "Test 2\n"; + +$ret = $common->infoFromString('<?xml version="1.0" encoding="ISO-8859-1" ?>' . + '<package version="1.0"><name>test</name><summary>PEAR test</summary>' . + '</package>'); + +var_dump($ret); + +echo "Test 3\n"; + +$ret = $common->infoFromString('<?xml version="1.0" encoding="ISO-8859-1" ?>' . + '<package version="1.0"><name>test</name><summary>PEAR test</summary>' . + '<description>The test</description></package>'); + +var_dump($ret); + +echo "Test 4\n"; + +$ret = $common->infoFromString('<?xml version="1.0" encoding="ISO-8859-1" ?>' . + '<package version="1.0"><name>test</name><summary>PEAR test</summary>' . + '<description>The test</description><license>PHP License</license></package>'); + +var_dump($ret); + +echo "Test 5\n"; + +$ret = $common->infoFromString('<?xml version="1.0" encoding="ISO-8859-1" ?>' . + '<package version="1.0"><name>test</name><summary>PEAR test</summary>' . + '<description>The test</description><license>PHP License</license> <maintainers> + <maintainer> + <user>test</user> + <role>lead</role> + <name>test tester</name> + <email>test@php.net</email> + </maintainer></maintainers> +</package>'); + +var_dump($ret); + +echo "Test 6\n"; + +$ret = $common->infoFromString('<?xml version="1.0" encoding="ISO-8859-1" ?>' . + '<package version="1.0"><name>test</name><summary>PEAR test</summary>' . + '<description>The test</description><license>PHP License</license> <maintainers> + <maintainer> + <user>test</user> + <role>lead</role> + <name>test tester</name> + <email>test@php.net</email> + </maintainer></maintainers><release> + <version>1.3b4</version></release> +</package>'); + +var_dump($ret); + +echo "Test 7\n"; + +$ret = $common->infoFromString('<?xml version="1.0" encoding="ISO-8859-1" ?>' . + '<package version="1.0"><name>test</name><summary>PEAR test</summary>' . + '<description>The test</description><license>PHP License</license> <maintainers> + <maintainer> + <user>test</user> + <role>lead</role> + <name>test tester</name> + <email>test@php.net</email> + </maintainer></maintainers><release> + <version>1.3b4</version> + <date>2003-11-17</date> + <state>beta</state> + <notes>test</notes></release> +</package>'); + +var_dump($ret); + +echo "Test 8\n"; + +$ret = $common->infoFromString('<?xml version="1.0" encoding="ISO-8859-1" ?>' . + '<package version="1.0"><name>test</name><summary>PEAR test</summary>' . + '<description>The test</description><license>PHP License</license> <maintainers> + <maintainer> + <user>test</user> + <role>lead</role> + <name>test tester</name> + <email>test@php.net</email> + </maintainer></maintainers><release> + <version>1.3b4</version> + <date>2003-11-17</date> + <state>beta</state> + <notes>test</notes> + <provides type="class" name="furngy" /></release> +</package>'); + +var_dump($ret); + +echo "Test 9\n"; + +$ret = $common->infoFromString('<?xml version="1.0" encoding="ISO-8859-1" ?>' . + '<package version="1.0"><name>test</name><summary>PEAR test</summary>' . + '<description>The test</description><license>PHP License</license> <maintainers> + <maintainer> + <user>test</user> + <role>lead</role> + <name>test tester</name> + <email>test@php.net</email> + </maintainer></maintainers><release> + <version>1.3b4</version> + <date>2003-11-17</date> + <state>beta</state> + <notes>test</notes> + <provides type="class" name="furngy" /> + <deps> + <dep type="ext" rel="has" optional="yes">xmlrpc</dep> + </deps> +</release> +</package>'); + +var_dump($ret); + +echo "Test 10\n"; + +$ret = $common->infoFromString('<?xml version="1.0" encoding="ISO-8859-1" ?>' . + '<package version="1.0"><name>test</name><summary>PEAR test</summary>' . + '<description>The test</description><license>PHP License</license> <maintainers> + <maintainer> + <user>test</user> + <role>lead</role> + <name>test tester</name> + <email>test@php.net</email> + </maintainer></maintainers><release> + <version>1.3b4</version> + <date>2003-11-17</date> + <state>beta</state> + <notes>test</notes> + <provides type="class" name="furngy" /> + <deps> + <dep type="ext" rel="has" optional="yes">xmlrpc</dep> + </deps> + <filelist> + <file role="data" name="package.dtd"/> + <file role="data" name="template.spec"/> + <file role="php" name="PEAR.php"/> + <file role="php" name="System.php"/> + <dir name="PEAR"> + <file role="php" name="Autoloader.php"/> + <file role="php" name="Command.php"/> + <dir name="Command"> + <file role="php" name="Auth.php"/> + <file role="php" name="Build.php"/> + <file role="php" name="Common.php"/> + <file role="php" name="Config.php"/> + <file role="php" name="Install.php"/> + <file role="php" name="Package.php"/> + <file role="php" name="Registry.php"/> + <file role="php" name="Remote.php"/> + <file role="php" name="Mirror.php"/> + </dir> + <file role="php" name="Common.php"/> + <file role="php" name="Config.php"/> + <file role="php" name="Dependency.php"/> + <dir name="Frontend"> + <file role="php" name="CLI.php"/> + </dir> + <file role="php" name="Builder.php"/> + <file role="php" name="Installer.php"/> + <file role="php" name="Packager.php"/> + <file role="php" name="Registry.php"/> + <file role="php" name="Remote.php"/> + </dir> + <dir name="OS"> + <file role="php" name="Guess.php"/> + </dir> + <dir name="scripts" baseinstalldir="/"> + <file role="script" install-as="pear" name="pear.sh"> + <replace from="@php_bin@" to="php_bin" type="pear-config"/> + <replace from="@php_dir@" to="php_dir" type="pear-config"/> + <replace from="@pear_version@" to="version" type="package-info"/> + <replace from="@include_path@" to="php_dir" type="pear-config"/> + </file> + <file role="script" platform="windows" install-as="pear.bat" name="pear.bat"> + <replace from="@bin_dir@" to="bin_dir" type="pear-config"/> + <replace from="@php_bin@" to="php_bin" type="pear-config"/> + <replace from="@include_path@" to="php_dir" type="pear-config"/> + </file> + <file role="php" install-as="pearcmd.php" name="pearcmd.php"> + <replace from="@php_bin@" to="php_bin" type="pear-config"/> + <replace from="@php_dir@" to="php_dir" type="pear-config"/> + <replace from="@pear_version@" to="version" type="package-info"/> + <replace from="@include_path@" to="php_dir" type="pear-config"/> + </file> + </dir> + </filelist> + +</release> +</package>'); + +var_dump($ret); + +echo "Test 11\n"; + +$ret = $common->infoFromString('<?xml version="1.0" encoding="ISO-8859-1" ?>' . + '<package version="1.0"><name>test</name><summary>PEAR test</summary>' . + '<description>The test</description><license>PHP License</license> <maintainers> + <maintainer> + <user>test</user> + <role>lead</role> + <name>test tester</name> + <email>test@php.net</email> + </maintainer></maintainers><release> + <version>1.3b4</version> + <date>2003-11-17</date> + <state>beta</state> + <notes>test</notes> + <provides type="class" name="furngy" /> + <deps> + <dep type="ext" rel="has" optional="yes">xmlrpc</dep> + </deps> + <filelist> + <file role="data" name="package.dtd"/> + <file role="data" name="template.spec"/> + <file role="php" name="PEAR.php"/> + <file role="php" name="System.php"/> + <dir name="PEAR"> + <file role="php" name="Autoloader.php"/> + <file role="php" name="Command.php"/> + <dir name="Command"> + <file role="php" name="Auth.php"/> + <file role="php" name="Build.php"/> + <file role="php" name="Common.php"/> + <file role="php" name="Config.php"/> + <file role="php" name="Install.php"/> + <file role="php" name="Package.php"/> + <file role="php" name="Registry.php"/> + <file role="php" name="Remote.php"/> + <file role="php" name="Mirror.php"/> + </dir> + <file role="php" name="Common.php"/> + <file role="php" name="Config.php"/> + <file role="php" name="Dependency.php"/> + <dir name="Frontend"> + <file role="php" name="CLI.php"/> + </dir> + <file role="php" name="Builder.php"/> + <file role="php" name="Installer.php"/> + <file role="php" name="Packager.php"/> + <file role="php" name="Registry.php"/> + <file role="php" name="Remote.php"/> + </dir> + <dir name="OS"> + <file role="php" name="Guess.php"/> + </dir> + <dir name="scripts" baseinstalldir="/"> + <file role="script" install-as="pear" name="pear.sh"> + <replace from="@php_bin@" to="php_bin" type="pear-config"/> + <replace from="@php_dir@" to="php_dir" type="pear-config"/> + <replace from="@pear_version@" to="version" type="package-info"/> + <replace from="@include_path@" to="php_dir" type="pear-config"/> + </file> + <file role="script" platform="windows" install-as="pear.bat" name="pear.bat"> + <replace from="@bin_dir@" to="bin_dir" type="pear-config"/> + <replace from="@php_bin@" to="php_bin" type="pear-config"/> + <replace from="@include_path@" to="php_dir" type="pear-config"/> + </file> + <file role="php" install-as="pearcmd.php" name="pearcmd.php"> + <replace from="@php_bin@" to="php_bin" type="pear-config"/> + <replace from="@php_dir@" to="php_dir" type="pear-config"/> + <replace from="@pear_version@" to="version" type="package-info"/> + <replace from="@include_path@" to="php_dir" type="pear-config"/> + </file> + </dir> + </filelist> + <configureoptions> + <configureoption name="test" prompt="The prompt test" default="foo" /> + </configureoptions> +</release> +</package>'); + +var_dump($ret); + +echo "Test 12\n"; + +$ret = $common->infoFromString('<?xml version="1.0" encoding="ISO-8859-1" ?>' . + '<package version="1.0"><name>test</name><summary>PEAR test</summary>' . + '<description>The test</description><license>PHP License</license> <maintainers> + <maintainer> + <user>test</user> + <role>lead</role> + <name>test tester</name> + <email>test@php.net</email> + </maintainer></maintainers><release> + <version>1.3b4</version> + <date>2003-11-17</date> + <state>beta</state> + <notes>test</notes> + <provides type="class" name="furngy" /> + <deps> + <dep type="ext" rel="has" optional="yes">xmlrpc</dep> + </deps> + <filelist> + <file role="data" name="package.dtd"/> + <file role="data" name="template.spec"/> + <file role="php" name="PEAR.php"/> + <file role="php" name="System.php"/> + <dir name="PEAR"> + <file role="php" name="Autoloader.php"/> + <file role="php" name="Command.php"/> + <dir name="Command"> + <file role="php" name="Auth.php"/> + <file role="php" name="Build.php"/> + <file role="php" name="Common.php"/> + <file role="php" name="Config.php"/> + <file role="php" name="Install.php"/> + <file role="php" name="Package.php"/> + <file role="php" name="Registry.php"/> + <file role="php" name="Remote.php"/> + <file role="php" name="Mirror.php"/> + </dir> + <file role="php" name="Common.php"/> + <file role="php" name="Config.php"/> + <file role="php" name="Dependency.php"/> + <dir name="Frontend"> + <file role="php" name="CLI.php"/> + </dir> + <file role="php" name="Builder.php"/> + <file role="php" name="Installer.php"/> + <file role="php" name="Packager.php"/> + <file role="php" name="Registry.php"/> + <file role="php" name="Remote.php"/> + </dir> + <dir name="OS"> + <file role="php" name="Guess.php"/> + </dir> + <dir name="scripts" baseinstalldir="/"> + <file role="script" install-as="pear" name="pear.sh"> + <replace from="@php_bin@" to="php_bin" type="pear-config"/> + <replace from="@php_dir@" to="php_dir" type="pear-config"/> + <replace from="@pear_version@" to="version" type="package-info"/> + <replace from="@include_path@" to="php_dir" type="pear-config"/> + </file> + <file role="script" platform="windows" install-as="pear.bat" name="pear.bat"> + <replace from="@bin_dir@" to="bin_dir" type="pear-config"/> + <replace from="@php_bin@" to="php_bin" type="pear-config"/> + <replace from="@include_path@" to="php_dir" type="pear-config"/> + </file> + <file role="php" install-as="pearcmd.php" name="pearcmd.php"> + <replace from="@php_bin@" to="php_bin" type="pear-config"/> + <replace from="@php_dir@" to="php_dir" type="pear-config"/> + <replace from="@pear_version@" to="version" type="package-info"/> + <replace from="@include_path@" to="php_dir" type="pear-config"/> + </file> + </dir> + </filelist> + <configureoptions> + <configureoption name="test" prompt="The prompt test" default="foo" /> + </configureoptions> +</release> + <changelog> + <release> + <version>0.1</version> + <date>2003-07-21</date> + <license>PHP License</license> + <state>alpha</state> + <notes>First release of test</notes> + </release> + <release> + <version>0.2</version> + <date>2003-07-21</date> + <license>PHP License</license> + <state>alpha</state> + <notes>Generation of package.xml from scratch is now supported. In addition, +generation of <provides> is supported and so is addition of +maintainers and configure options + +- Fixed a bug in <release> generation +- Added _addProvides() to generate a <provides> section</notes> + </release> + </changelog> +</package>'); + +var_dump($ret); + +?> +--EXPECT-- +Test invalid XML +Caught error: XML error: not well-formed (invalid token) at line 1 +Test valid XML, not a package.xml +Caught error: Invalid Package File, no <package> tag +Test valid package.xml, invalid version number +Caught error: No handlers for package.xml version 10000000 +Test empty package.xml +array(2) { + ["provides"]=> + array(0) { + } + ["filelist"]=> + &array(0) { + } +} +Test 1 +array(3) { + ["provides"]=> + array(0) { + } + ["filelist"]=> + &array(0) { + } + ["package"]=> + string(4) "test" +} +Test 2 +array(4) { + ["provides"]=> + array(0) { + } + ["filelist"]=> + &array(0) { + } + ["package"]=> + string(4) "test" + ["summary"]=> + string(9) "PEAR test" +} +Test 3 +array(5) { + ["provides"]=> + array(0) { + } + ["filelist"]=> + &array(0) { + } + ["package"]=> + string(4) "test" + ["summary"]=> + string(9) "PEAR test" + ["description"]=> + string(8) "The test" +} +Test 4 +array(6) { + ["provides"]=> + array(0) { + } + ["filelist"]=> + &array(0) { + } + ["package"]=> + string(4) "test" + ["summary"]=> + string(9) "PEAR test" + ["description"]=> + string(8) "The test" + ["release_license"]=> + string(11) "PHP License" +} +Test 5 +array(7) { + ["provides"]=> + array(0) { + } + ["filelist"]=> + &array(0) { + } + ["package"]=> + string(4) "test" + ["summary"]=> + string(9) "PEAR test" + ["description"]=> + string(8) "The test" + ["release_license"]=> + string(11) "PHP License" + ["maintainers"]=> + array(1) { + [0]=> + &array(4) { + ["handle"]=> + string(4) "test" + ["role"]=> + string(4) "lead" + ["name"]=> + string(11) "test tester" + ["email"]=> + string(12) "test@php.net" + } + } +} +Test 6 +array(8) { + ["provides"]=> + array(0) { + } + ["filelist"]=> + &array(0) { + } + ["package"]=> + string(4) "test" + ["summary"]=> + string(9) "PEAR test" + ["description"]=> + string(8) "The test" + ["release_license"]=> + string(11) "PHP License" + ["maintainers"]=> + array(1) { + [0]=> + &array(4) { + ["handle"]=> + string(4) "test" + ["role"]=> + string(4) "lead" + ["name"]=> + string(11) "test tester" + ["email"]=> + string(12) "test@php.net" + } + } + ["version"]=> + string(5) "1.3b4" +} +Test 7 +array(11) { + ["provides"]=> + array(0) { + } + ["filelist"]=> + &array(0) { + } + ["package"]=> + string(4) "test" + ["summary"]=> + string(9) "PEAR test" + ["description"]=> + string(8) "The test" + ["release_license"]=> + string(11) "PHP License" + ["maintainers"]=> + array(1) { + [0]=> + &array(4) { + ["handle"]=> + string(4) "test" + ["role"]=> + string(4) "lead" + ["name"]=> + string(11) "test tester" + ["email"]=> + string(12) "test@php.net" + } + } + ["version"]=> + string(5) "1.3b4" + ["release_date"]=> + string(10) "2003-11-17" + ["release_state"]=> + string(4) "beta" + ["release_notes"]=> + string(4) "test" +} +Test 8 +array(11) { + ["provides"]=> + array(1) { + ["class;furngy"]=> + array(3) { + ["type"]=> + string(5) "class" + ["name"]=> + string(6) "furngy" + ["explicit"]=> + bool(true) + } + } + ["filelist"]=> + &array(0) { + } + ["package"]=> + string(4) "test" + ["summary"]=> + string(9) "PEAR test" + ["description"]=> + string(8) "The test" + ["release_license"]=> + string(11) "PHP License" + ["maintainers"]=> + array(1) { + [0]=> + &array(4) { + ["handle"]=> + string(4) "test" + ["role"]=> + string(4) "lead" + ["name"]=> + string(11) "test tester" + ["email"]=> + string(12) "test@php.net" + } + } + ["version"]=> + string(5) "1.3b4" + ["release_date"]=> + string(10) "2003-11-17" + ["release_state"]=> + string(4) "beta" + ["release_notes"]=> + string(4) "test" +} +Test 9 +array(12) { + ["provides"]=> + array(1) { + ["class;furngy"]=> + array(3) { + ["type"]=> + string(5) "class" + ["name"]=> + string(6) "furngy" + ["explicit"]=> + bool(true) + } + } + ["filelist"]=> + &array(0) { + } + ["package"]=> + string(4) "test" + ["summary"]=> + string(9) "PEAR test" + ["description"]=> + string(8) "The test" + ["release_license"]=> + string(11) "PHP License" + ["maintainers"]=> + array(1) { + [0]=> + &array(4) { + ["handle"]=> + string(4) "test" + ["role"]=> + string(4) "lead" + ["name"]=> + string(11) "test tester" + ["email"]=> + string(12) "test@php.net" + } + } + ["version"]=> + string(5) "1.3b4" + ["release_date"]=> + string(10) "2003-11-17" + ["release_state"]=> + string(4) "beta" + ["release_notes"]=> + string(4) "test" + ["release_deps"]=> + array(1) { + [1]=> + array(4) { + ["type"]=> + string(3) "ext" + ["rel"]=> + string(3) "has" + ["optional"]=> + string(3) "yes" + ["name"]=> + string(6) "xmlrpc" + } + } +} +Test 10 +array(12) { + ["provides"]=> + array(1) { + ["class;furngy"]=> + array(3) { + ["type"]=> + string(5) "class" + ["name"]=> + string(6) "furngy" + ["explicit"]=> + bool(true) + } + } + ["filelist"]=> + &array(28) { + ["package.dtd"]=> + array(1) { + ["role"]=> + string(4) "data" + } + ["template.spec"]=> + array(1) { + ["role"]=> + string(4) "data" + } + ["PEAR.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["System.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Autoloader.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Auth.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Build.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Common.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Config.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Install.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Package.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Registry.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Remote.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Mirror.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Common.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Config.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Dependency.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Frontend\CLI.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Builder.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Installer.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Packager.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Registry.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Remote.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["OS\Guess.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["scripts\pear.sh"]=> + array(4) { + ["role"]=> + string(6) "script" + ["install-as"]=> + string(4) "pear" + ["baseinstalldir"]=> + string(1) "/" + ["replacements"]=> + array(4) { + [0]=> + array(3) { + ["from"]=> + string(9) "@php_bin@" + ["to"]=> + string(7) "php_bin" + ["type"]=> + string(11) "pear-config" + } + [1]=> + array(3) { + ["from"]=> + string(9) "@php_dir@" + ["to"]=> + string(7) "php_dir" + ["type"]=> + string(11) "pear-config" + } + [2]=> + array(3) { + ["from"]=> + string(14) "@pear_version@" + ["to"]=> + string(7) "version" + ["type"]=> + string(12) "package-info" + } + [3]=> + array(3) { + ["from"]=> + string(14) "@include_path@" + ["to"]=> + string(7) "php_dir" + ["type"]=> + string(11) "pear-config" + } + } + } + ["scripts\pear.bat"]=> + array(5) { + ["role"]=> + string(6) "script" + ["platform"]=> + string(7) "windows" + ["install-as"]=> + string(8) "pear.bat" + ["baseinstalldir"]=> + string(1) "/" + ["replacements"]=> + array(3) { + [0]=> + array(3) { + ["from"]=> + string(9) "@bin_dir@" + ["to"]=> + string(7) "bin_dir" + ["type"]=> + string(11) "pear-config" + } + [1]=> + array(3) { + ["from"]=> + string(9) "@php_bin@" + ["to"]=> + string(7) "php_bin" + ["type"]=> + string(11) "pear-config" + } + [2]=> + array(3) { + ["from"]=> + string(14) "@include_path@" + ["to"]=> + string(7) "php_dir" + ["type"]=> + string(11) "pear-config" + } + } + } + ["scripts\pearcmd.php"]=> + array(4) { + ["role"]=> + string(3) "php" + ["install-as"]=> + string(11) "pearcmd.php" + ["baseinstalldir"]=> + string(1) "/" + ["replacements"]=> + array(4) { + [0]=> + array(3) { + ["from"]=> + string(9) "@php_bin@" + ["to"]=> + string(7) "php_bin" + ["type"]=> + string(11) "pear-config" + } + [1]=> + array(3) { + ["from"]=> + string(9) "@php_dir@" + ["to"]=> + string(7) "php_dir" + ["type"]=> + string(11) "pear-config" + } + [2]=> + array(3) { + ["from"]=> + string(14) "@pear_version@" + ["to"]=> + string(7) "version" + ["type"]=> + string(12) "package-info" + } + [3]=> + array(3) { + ["from"]=> + string(14) "@include_path@" + ["to"]=> + string(7) "php_dir" + ["type"]=> + string(11) "pear-config" + } + } + } + } + ["package"]=> + string(4) "test" + ["summary"]=> + string(9) "PEAR test" + ["description"]=> + string(8) "The test" + ["release_license"]=> + string(11) "PHP License" + ["maintainers"]=> + array(1) { + [0]=> + &array(4) { + ["handle"]=> + string(4) "test" + ["role"]=> + string(4) "lead" + ["name"]=> + string(11) "test tester" + ["email"]=> + string(12) "test@php.net" + } + } + ["version"]=> + string(5) "1.3b4" + ["release_date"]=> + string(10) "2003-11-17" + ["release_state"]=> + string(4) "beta" + ["release_notes"]=> + string(4) "test" + ["release_deps"]=> + array(1) { + [1]=> + array(4) { + ["type"]=> + string(3) "ext" + ["rel"]=> + string(3) "has" + ["optional"]=> + string(3) "yes" + ["name"]=> + string(6) "xmlrpc" + } + } +} +Test 11 +array(13) { + ["provides"]=> + array(1) { + ["class;furngy"]=> + array(3) { + ["type"]=> + string(5) "class" + ["name"]=> + string(6) "furngy" + ["explicit"]=> + bool(true) + } + } + ["filelist"]=> + &array(28) { + ["package.dtd"]=> + array(1) { + ["role"]=> + string(4) "data" + } + ["template.spec"]=> + array(1) { + ["role"]=> + string(4) "data" + } + ["PEAR.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["System.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Autoloader.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Auth.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Build.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Common.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Config.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Install.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Package.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Registry.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Remote.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Mirror.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Common.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Config.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Dependency.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Frontend\CLI.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Builder.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Installer.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Packager.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Registry.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Remote.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["OS\Guess.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["scripts\pear.sh"]=> + array(4) { + ["role"]=> + string(6) "script" + ["install-as"]=> + string(4) "pear" + ["baseinstalldir"]=> + string(1) "/" + ["replacements"]=> + array(4) { + [0]=> + array(3) { + ["from"]=> + string(9) "@php_bin@" + ["to"]=> + string(7) "php_bin" + ["type"]=> + string(11) "pear-config" + } + [1]=> + array(3) { + ["from"]=> + string(9) "@php_dir@" + ["to"]=> + string(7) "php_dir" + ["type"]=> + string(11) "pear-config" + } + [2]=> + array(3) { + ["from"]=> + string(14) "@pear_version@" + ["to"]=> + string(7) "version" + ["type"]=> + string(12) "package-info" + } + [3]=> + array(3) { + ["from"]=> + string(14) "@include_path@" + ["to"]=> + string(7) "php_dir" + ["type"]=> + string(11) "pear-config" + } + } + } + ["scripts\pear.bat"]=> + array(5) { + ["role"]=> + string(6) "script" + ["platform"]=> + string(7) "windows" + ["install-as"]=> + string(8) "pear.bat" + ["baseinstalldir"]=> + string(1) "/" + ["replacements"]=> + array(3) { + [0]=> + array(3) { + ["from"]=> + string(9) "@bin_dir@" + ["to"]=> + string(7) "bin_dir" + ["type"]=> + string(11) "pear-config" + } + [1]=> + array(3) { + ["from"]=> + string(9) "@php_bin@" + ["to"]=> + string(7) "php_bin" + ["type"]=> + string(11) "pear-config" + } + [2]=> + array(3) { + ["from"]=> + string(14) "@include_path@" + ["to"]=> + string(7) "php_dir" + ["type"]=> + string(11) "pear-config" + } + } + } + ["scripts\pearcmd.php"]=> + array(4) { + ["role"]=> + string(3) "php" + ["install-as"]=> + string(11) "pearcmd.php" + ["baseinstalldir"]=> + string(1) "/" + ["replacements"]=> + array(4) { + [0]=> + array(3) { + ["from"]=> + string(9) "@php_bin@" + ["to"]=> + string(7) "php_bin" + ["type"]=> + string(11) "pear-config" + } + [1]=> + array(3) { + ["from"]=> + string(9) "@php_dir@" + ["to"]=> + string(7) "php_dir" + ["type"]=> + string(11) "pear-config" + } + [2]=> + array(3) { + ["from"]=> + string(14) "@pear_version@" + ["to"]=> + string(7) "version" + ["type"]=> + string(12) "package-info" + } + [3]=> + array(3) { + ["from"]=> + string(14) "@include_path@" + ["to"]=> + string(7) "php_dir" + ["type"]=> + string(11) "pear-config" + } + } + } + } + ["package"]=> + string(4) "test" + ["summary"]=> + string(9) "PEAR test" + ["description"]=> + string(8) "The test" + ["release_license"]=> + string(11) "PHP License" + ["maintainers"]=> + array(1) { + [0]=> + &array(4) { + ["handle"]=> + string(4) "test" + ["role"]=> + string(4) "lead" + ["name"]=> + string(11) "test tester" + ["email"]=> + string(12) "test@php.net" + } + } + ["version"]=> + string(5) "1.3b4" + ["release_date"]=> + string(10) "2003-11-17" + ["release_state"]=> + string(4) "beta" + ["release_notes"]=> + string(4) "test" + ["release_deps"]=> + array(1) { + [1]=> + array(4) { + ["type"]=> + string(3) "ext" + ["rel"]=> + string(3) "has" + ["optional"]=> + string(3) "yes" + ["name"]=> + string(6) "xmlrpc" + } + } + ["configure_options"]=> + array(1) { + [0]=> + array(3) { + ["name"]=> + string(4) "test" + ["prompt"]=> + string(15) "The prompt test" + ["default"]=> + string(3) "foo" + } + } +} +Test 12 +array(14) { + ["provides"]=> + array(1) { + ["class;furngy"]=> + array(3) { + ["type"]=> + string(5) "class" + ["name"]=> + string(6) "furngy" + ["explicit"]=> + bool(true) + } + } + ["filelist"]=> + &array(28) { + ["package.dtd"]=> + array(1) { + ["role"]=> + string(4) "data" + } + ["template.spec"]=> + array(1) { + ["role"]=> + string(4) "data" + } + ["PEAR.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["System.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Autoloader.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Auth.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Build.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Common.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Config.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Install.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Package.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Registry.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Remote.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Command\Mirror.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Common.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Config.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Dependency.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Frontend\CLI.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Builder.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Installer.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Packager.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Registry.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["PEAR\Remote.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["OS\Guess.php"]=> + array(1) { + ["role"]=> + string(3) "php" + } + ["scripts\pear.sh"]=> + array(4) { + ["role"]=> + string(6) "script" + ["install-as"]=> + string(4) "pear" + ["baseinstalldir"]=> + string(1) "/" + ["replacements"]=> + array(4) { + [0]=> + array(3) { + ["from"]=> + string(9) "@php_bin@" + ["to"]=> + string(7) "php_bin" + ["type"]=> + string(11) "pear-config" + } + [1]=> + array(3) { + ["from"]=> + string(9) "@php_dir@" + ["to"]=> + string(7) "php_dir" + ["type"]=> + string(11) "pear-config" + } + [2]=> + array(3) { + ["from"]=> + string(14) "@pear_version@" + ["to"]=> + string(7) "version" + ["type"]=> + string(12) "package-info" + } + [3]=> + array(3) { + ["from"]=> + string(14) "@include_path@" + ["to"]=> + string(7) "php_dir" + ["type"]=> + string(11) "pear-config" + } + } + } + ["scripts\pear.bat"]=> + array(5) { + ["role"]=> + string(6) "script" + ["platform"]=> + string(7) "windows" + ["install-as"]=> + string(8) "pear.bat" + ["baseinstalldir"]=> + string(1) "/" + ["replacements"]=> + array(3) { + [0]=> + array(3) { + ["from"]=> + string(9) "@bin_dir@" + ["to"]=> + string(7) "bin_dir" + ["type"]=> + string(11) "pear-config" + } + [1]=> + array(3) { + ["from"]=> + string(9) "@php_bin@" + ["to"]=> + string(7) "php_bin" + ["type"]=> + string(11) "pear-config" + } + [2]=> + array(3) { + ["from"]=> + string(14) "@include_path@" + ["to"]=> + string(7) "php_dir" + ["type"]=> + string(11) "pear-config" + } + } + } + ["scripts\pearcmd.php"]=> + array(4) { + ["role"]=> + string(3) "php" + ["install-as"]=> + string(11) "pearcmd.php" + ["baseinstalldir"]=> + string(1) "/" + ["replacements"]=> + array(4) { + [0]=> + array(3) { + ["from"]=> + string(9) "@php_bin@" + ["to"]=> + string(7) "php_bin" + ["type"]=> + string(11) "pear-config" + } + [1]=> + array(3) { + ["from"]=> + string(9) "@php_dir@" + ["to"]=> + string(7) "php_dir" + ["type"]=> + string(11) "pear-config" + } + [2]=> + array(3) { + ["from"]=> + string(14) "@pear_version@" + ["to"]=> + string(7) "version" + ["type"]=> + string(12) "package-info" + } + [3]=> + array(3) { + ["from"]=> + string(14) "@include_path@" + ["to"]=> + string(7) "php_dir" + ["type"]=> + string(11) "pear-config" + } + } + } + } + ["package"]=> + string(4) "test" + ["summary"]=> + string(9) "PEAR test" + ["description"]=> + string(8) "The test" + ["release_license"]=> + string(11) "PHP License" + ["maintainers"]=> + array(1) { + [0]=> + &array(4) { + ["handle"]=> + string(4) "test" + ["role"]=> + string(4) "lead" + ["name"]=> + string(11) "test tester" + ["email"]=> + string(12) "test@php.net" + } + } + ["version"]=> + string(5) "1.3b4" + ["release_date"]=> + string(10) "2003-11-17" + ["release_state"]=> + string(4) "beta" + ["release_notes"]=> + string(4) "test" + ["release_deps"]=> + array(1) { + [1]=> + array(4) { + ["type"]=> + string(3) "ext" + ["rel"]=> + string(3) "has" + ["optional"]=> + string(3) "yes" + ["name"]=> + string(6) "xmlrpc" + } + } + ["configure_options"]=> + array(1) { + [0]=> + array(3) { + ["name"]=> + string(4) "test" + ["prompt"]=> + string(15) "The prompt test" + ["default"]=> + string(3) "foo" + } + } + ["changelog"]=> + array(2) { + [0]=> + &array(5) { + ["version"]=> + string(3) "0.1" + ["release_date"]=> + string(10) "2003-07-21" + ["release_license"]=> + string(11) "PHP License" + ["release_state"]=> + string(5) "alpha" + ["release_notes"]=> + string(22) "First release of test +" + } + [1]=> + &array(5) { + ["version"]=> + string(3) "0.2" + ["release_date"]=> + string(10) "2003-07-21" + ["release_license"]=> + string(11) "PHP License" + ["release_state"]=> + string(5) "alpha" + ["release_notes"]=> + string(260) "Generation of package.xml from scratch is now supported. In addition, +generation of <provides> is supported and so is addition of +maintainers and configure options + +- Fixed a bug in <release> generation +- Added _addProvides() to generate a <provides> section +" + } + } +}
\ No newline at end of file diff --git a/pear/tests/pear_common_sortPkgDeps.phpt b/pear/tests/pear_common_sortPkgDeps.phpt new file mode 100644 index 000000000..5097888ee --- /dev/null +++ b/pear/tests/pear_common_sortPkgDeps.phpt @@ -0,0 +1,73 @@ +--TEST-- +PEAR_Common::sortPkgDeps test +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php +$dir = getcwd(); +chdir(dirname(__FILE__)); + +require_once 'PEAR/Common.php'; + +$c = new PEAR_Common(); + +$packages = array( +'common_sortPkgDeps6_package.xml', +'common_sortPkgDeps2_package.xml', +'common_sortPkgDeps1_package.xml', +'common_sortPkgDeps4_package.xml', +'common_sortPkgDeps5_package.xml', +'common_sortPkgDeps3_package.xml', +); + +$uninstallpackages = array( +$c->infoFromAny('common_sortPkgDeps6_package.xml'), +$c->infoFromAny('common_sortPkgDeps2_package.xml'), +$c->infoFromAny('common_sortPkgDeps1_package.xml'), +$c->infoFromAny('common_sortPkgDeps4_package.xml'), +$c->infoFromAny('common_sortPkgDeps5_package.xml'), +$c->infoFromAny('common_sortPkgDeps3_package.xml'), +); + +echo "Test Install Sort:\n"; +$c->sortPkgDeps($packages); +dumpPacks($packages); + +echo "Test Uninstall Sort:\n"; +$c->sortPkgDeps($uninstallpackages, true); +dumpPacks($uninstallpackages); + +chdir($dir); + +function dumpPacks($p) +{ + echo "Packages(\n"; + foreach ($p as $inf) { + echo $inf['info']['package'] . ",\n"; + } + echo ")\n"; +} +?> +--EXPECT-- +Test Install Sort: +Packages( +pkg6, +pkg5, +pkg4, +pkg3, +pkg2, +pkg1, +) +Test Uninstall Sort: +Packages( +pkg1, +pkg2, +pkg3, +pkg5, +pkg4, +pkg6, +)
\ No newline at end of file diff --git a/pear/tests/pear_common_validPackageVersion.phpt b/pear/tests/pear_common_validPackageVersion.phpt new file mode 100644 index 000000000..c177bb202 --- /dev/null +++ b/pear/tests/pear_common_validPackageVersion.phpt @@ -0,0 +1,81 @@ +--TEST-- +PEAR_Common::validPackageVersion test +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php + +require_once 'PEAR/Common.php'; + +// '\d+(?:\.\d+)*(?:[a-z]+\d*)?' + +echo "==Valid Tests==\n"; +$a = '1'; +echo "$a "; +echo (PEAR_Common::validPackageVersion($a)) ? "valid\n" : "invalid\n"; + +$a = '1.1'; +echo "$a "; +echo (PEAR_Common::validPackageVersion($a)) ? "valid\n" : "invalid\n"; + +$a = '1.1.1'; +echo "$a "; +echo (PEAR_Common::validPackageVersion($a)) ? "valid\n" : "invalid\n"; + +$a = '1.1.1.1'; +echo "$a "; +echo (PEAR_Common::validPackageVersion($a)) ? "valid\n" : "invalid\n"; + +$a = '1.1.1abc3'; +echo "$a "; +echo (PEAR_Common::validPackageVersion($a)) ? "valid\n" : "invalid\n"; + +$a = '1.234beta4'; +echo "$a "; +echo (PEAR_Common::validPackageVersion($a)) ? "valid\n" : "invalid\n"; + +$a = '1alpha3'; +echo "$a "; +echo (PEAR_Common::validPackageVersion($a)) ? "valid\n" : "invalid\n"; + +$a = '1alpha'; +echo "$a "; +echo (PEAR_Common::validPackageVersion($a)) ? "valid\n" : "invalid\n"; + +$a = '1.1a'; +echo "$a "; +echo (PEAR_Common::validPackageVersion($a)) ? "valid\n" : "invalid\n"; + +echo "==Invalid Tests==\n"; + +$a = '1.0.0-alpha2'; +echo "$a "; +echo (PEAR_Common::validPackageVersion($a)) ? "valid\n" : "invalid\n"; + +$a = '1alpha.4'; +echo "$a "; +echo (PEAR_Common::validPackageVersion($a)) ? "valid\n" : "invalid\n"; + +$a = '1.1alpha.4'; +echo "$a "; +echo (PEAR_Common::validPackageVersion($a)) ? "valid\n" : "invalid\n"; +?> +--EXPECT-- +==Valid Tests== +1 valid +1.1 valid +1.1.1 valid +1.1.1.1 valid +1.1.1abc3 valid +1.234beta4 valid +1alpha3 valid +1alpha valid +1.1a valid +==Invalid Tests== +1.0.0-alpha2 invalid +1alpha.4 invalid +1.1alpha.4 invalid diff --git a/pear/tests/pear_config.phpt b/pear/tests/pear_config.phpt new file mode 100644 index 000000000..7578a8ad8 --- /dev/null +++ b/pear/tests/pear_config.phpt @@ -0,0 +1,303 @@ +--TEST-- +PEAR_Config +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +include 'PEAR/Config.php'; +$pv = phpversion() . ''; +$av = $pv{0} == '4' ? 'apiversion' : 'apiVersion'; +if (in_array($av, get_class_methods('PEAR_Config'))) { + echo 'skip'; +} +?> +--FILE-- +<?php + +error_reporting(E_ALL); +chdir(dirname(__FILE__)); +include "PEAR/Config.php"; +copy("system.input", "system.conf"); +copy("user.input", "user.conf"); +copy("user2.input", "user2.conf"); +copy("merge.input", "merge.conf"); +PEAR::setErrorHandling(PEAR_ERROR_PRINT, "%s\n"); + +print "\n#0 starting up\n"; +dump_files(); + +print "\n#1 testing: constructor\n"; +$config = new PEAR_Config("user.conf", "system.conf"); +dump_array("files", $config->files); + +print "\n#2 testing: singleton\n"; +$o1 = &PEAR_Config::singleton(); +$o1->blah = 'blah'; +$o2 = &PEAR_Config::singleton(); +var_dump($o1->blah); +@var_dump($o2->blah); + +print "\n#3 testing: readConfigFile\n"; +$config->readConfigFile("user2.conf", "user"); +dump_config($config); +$config->readConfigFile("user.conf"); +dump_config($config); + +print "\n#4 testing: mergeConfigFile\n"; +$config->readConfigFile("user2.conf"); +dump_config($config, "user"); +$config->mergeConfigFile("merge.conf", true); +dump_config($config, "user"); +$config->readConfigFile("user2.conf"); +$config->mergeConfigFile("merge.conf", false); +dump_config($config, "user"); +$config->readConfigFile("user.conf"); +dump_config($config, "user"); +$config->mergeConfigFile("merge.conf", true, "xyzzy"); + +print "\n#5 testing: config file version detection\n"; +$config->readConfigFile("user.conf", "user"); +$config->readConfigFile("toonew.conf", "user"); + +print "\n#6 testing: get/set/remove\n"; +var_dump($config->get("verbose")); +$config->set("verbose", 100, "system"); +var_dump($config->get("verbose")); +$config->set("verbose", 2, "user"); +var_dump($config->get("verbose")); +$config->set("verbose", 2, "system"); +$config->set("verbose", 50, "user"); +var_dump($config->get("verbose")); +$config->remove("verbose", "user"); +var_dump($config->get("verbose")); +$config->remove("verbose", "system"); +var_dump($config->get("verbose")); + +print "\n#7 testing: getType\n"; +var_dump($config->getType("__unknown__")); +var_dump($config->getType("verbose")); +var_dump($config->getType("master_server")); +var_dump($config->getType("ext_dir")); + +print "\n#8 testing: getDocs\n"; +print "master_server: " . $config->getDocs("master_server") . "\n"; + +print "\n#9 testing: getKeys\n"; +$keys = $config->getKeys(); +sort($keys); +print implode(" ", $keys) . "\n"; + +print "\n#10 testing: definedBy\n"; +var_dump($config->definedBy("verbose")); +$config->set("verbose", 6, "system"); +$config->set("verbose", 3, "user"); +var_dump($config->definedBy("verbose")); +$config->remove("verbose", "system"); +var_dump($config->definedBy("verbose")); +$config->set("verbose", 6, "system"); +$config->remove("verbose", "user"); +var_dump($config->definedBy("verbose")); +$config->remove("verbose", "system"); +var_dump($config->definedBy("verbose")); + +print "\n#11 testing: isDefined\n"; +var_dump($config->isDefined("php_dir")); +var_dump($config->isDefined("verbose")); +var_dump($config->isDefined("HTTP_GET_VARS")); +var_dump($config->isDefined("query")); + +print "\n#12 testing: getGroup\n"; +foreach ($keys as $key) { + print "$key: ".$config->getGroup($key)."\n"; +} + +print "\n#13 testing: getGroups\n"; +$groups = $config->getGroups(); +sort($groups); +print implode(", ", $groups) . "\n"; + +print "\n#14 testing: getGroupKeys\n"; +foreach ($groups as $group) { + $gk = $config->getGroupKeys($group); + sort($gk); + print "$group: " . implode(", ", $gk) . "\n"; +} + +print "\n#15 testing: getPrompt\n"; +foreach ($keys as $key) { + print "$key: ".$config->getPrompt($key)."\n"; +} + + +// + +print "done\n"; + +unlink("user.conf"); +unlink("user2.conf"); +unlink("system.conf"); +unlink("merge.conf"); + +// ------------------------------------------------------------------------- // + +function dump_file($file) +{ + print "..$file:"; + $data = PEAR_Config::_readConfigDataFrom($file); + if (empty($data)) { + print " <empty>\n"; + return; + } + foreach ($data as $k => $v) { + print " $k=\"$v\""; + } + print "\n"; +} + +function dump_files() { + dump_file("system.conf"); + dump_file("user.conf"); +} + +function dump_array($name, $arr) { + print "$name:"; + if (empty($arr)) { + print " <empty>"; + } else { + foreach ($arr as $k => $v) { + print " $k=\"$v\""; + } + } + print "\n"; +} + +function dump_config(&$obj, $layer = null) { + if ($layer !== null) { + dump_array($layer, $obj->configuration[$layer]); + return; + } + foreach ($obj->configuration as $layer => $data) { + if ($layer == "default") { + continue; + } + dump_array($layer, $data); + } +} + +?> +--EXPECT-- +#0 starting up +..system.conf: master_server="pear.php.net" +..user.conf: <empty> + +#1 testing: constructor +files: system="system.conf" user="user.conf" + +#2 testing: singleton +string(4) "blah" +string(4) "blah" + +#3 testing: readConfigFile +user: verbose="2" +system: master_server="pear.php.net" +user: <empty> +system: master_server="pear.php.net" + +#4 testing: mergeConfigFile +user: verbose="2" +user: verbose="100" +user: verbose="2" +user: <empty> +unknown config file type `xyzzy' + +#5 testing: config file version detection +toonew.conf: unknown version `2.0' + +#6 testing: get/set/remove +int(1) +int(100) +int(2) +int(50) +int(2) +int(1) + +#7 testing: getType +bool(false) +string(7) "integer" +string(6) "string" +string(9) "directory" + +#8 testing: getDocs +master_server: name of the main PEAR server + +#9 testing: getKeys +bin_dir cache_dir cache_ttl data_dir doc_dir ext_dir http_proxy master_server password php_bin php_dir preferred_state sig_bin sig_keydir sig_keyid sig_type test_dir umask username verbose + +#10 testing: definedBy +string(7) "default" +string(4) "user" +string(4) "user" +string(6) "system" +string(7) "default" + +#11 testing: isDefined +bool(true) +bool(true) +bool(false) +bool(false) + +#12 testing: getGroup +bin_dir: File Locations +cache_dir: File Locations (Advanced) +cache_ttl: Advanced +data_dir: File Locations (Advanced) +doc_dir: File Locations +ext_dir: File Locations +http_proxy: Internet Access +master_server: Internet Access +password: Maintainers +php_bin: File Locations (Advanced) +php_dir: File Locations +preferred_state: Advanced +sig_bin: Maintainers +sig_keydir: Maintainers +sig_keyid: Maintainers +sig_type: Maintainers +test_dir: File Locations (Advanced) +umask: Advanced +username: Maintainers +verbose: Advanced + +#13 testing: getGroups +Advanced, File Locations, File Locations (Advanced), Internet Access, Maintainers + +#14 testing: getGroupKeys +Advanced: cache_ttl, preferred_state, umask, verbose +File Locations: bin_dir, doc_dir, ext_dir, php_dir +File Locations (Advanced): cache_dir, data_dir, php_bin, test_dir +Internet Access: http_proxy, master_server +Maintainers: password, sig_bin, sig_keydir, sig_keyid, sig_type, username + +#15 testing: getPrompt +bin_dir: PEAR executables directory +cache_dir: PEAR Installer cache directory +cache_ttl: Cache TimeToLive +data_dir: PEAR data directory +doc_dir: PEAR documentation directory +ext_dir: PHP extension directory +http_proxy: HTTP Proxy Server Address +master_server: PEAR server +password: PEAR password (for maintainers) +php_bin: PHP CLI/CGI binary +php_dir: PEAR directory +preferred_state: Preferred Package State +sig_bin: Signature Handling Program +sig_keydir: Signature Key Directory +sig_keyid: Signature Key Id +sig_type: Package Signature Type +test_dir: PEAR test directory +umask: Unix file mask +username: PEAR username (for maintainers) +verbose: Debug Log Level +done
\ No newline at end of file diff --git a/pear/tests/pear_config_1.1.phpt b/pear/tests/pear_config_1.1.phpt new file mode 100644 index 000000000..c7a13a56d --- /dev/null +++ b/pear/tests/pear_config_1.1.phpt @@ -0,0 +1,393 @@ +--TEST-- +PEAR_Config v1.1 +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +include_once 'PEAR/Config.php'; +$pv = phpversion() . ''; +$av = $pv{0} == '4' ? 'apiversion' : 'apiVersion'; +if (!in_array($av, get_class_methods('PEAR_Config'))) { + echo 'skip'; +} +if (PEAR_Config::apiVersion() != '1.1') { + echo 'skip'; +} +?> +--FILE-- +<?php + +error_reporting(E_ALL); +chdir(dirname(__FILE__)); +include_once "PEAR/Config.php"; +copy("system.input", "system.conf"); +copy("user.input", "user.conf"); +copy("user2.input", "user2.conf"); +copy("merge.input", "merge.conf"); +copy("user3.input", "user3.conf"); +copy("merge2.input", "merge2.conf"); +PEAR::setErrorHandling(PEAR_ERROR_PRINT, "%s\n"); + +print "\n#0 starting up\n"; +dump_files(); + +print "\n#1 testing: constructor\n"; +$config = new PEAR_Config("user.conf", "system.conf"); +dump_array("files", $config->files); + +print "\n#2 testing: singleton\n"; +$o1 = &PEAR_Config::singleton(); +$o1->blah = 'blah'; +$o2 = &PEAR_Config::singleton(); +var_dump($o1->blah); +@var_dump($o2->blah); + +print "\n#3 testing: readConfigFile\n"; +$config->readConfigFile("user2.conf", "user"); +dump_config($config); +$config->readConfigFile("user.conf"); +dump_config($config); + +print "\n#4 testing: mergeConfigFile\n"; +$config->readConfigFile("user2.conf"); +dump_config($config, "user"); +$config->mergeConfigFile("merge.conf", true); +dump_config($config, "user"); +$config->readConfigFile("user2.conf"); +$config->mergeConfigFile("merge.conf", false); +dump_config($config, "user"); +$config->readConfigFile("user.conf"); +dump_config($config, "user"); +$config->mergeConfigFile("merge.conf", true, "xyzzy"); +$config->readConfigFile("user3.conf"); +dump_config($config, "user"); +$config->mergeConfigFile("merge2.conf", true); +dump_config($config, "user"); +$config->readConfigFile("user3.conf"); +$config->mergeConfigFile("merge2.conf", false); +dump_config($config, "user"); + +print "\n#5 testing: config file version detection\n"; +$config->readConfigFile("user.conf", "user"); +$config->readConfigFile("toonew.conf", "user"); + +print "\n#6 testing: get/set/remove\n"; +var_dump($config->get("verbose")); +$config->set("verbose", 100, "system"); +var_dump($config->get("verbose")); +$config->set("verbose", 2, "user"); +var_dump($config->get("verbose")); +$config->set("verbose", 2, "system"); +$config->set("verbose", 50, "user"); +var_dump($config->get("verbose")); +$config->remove("verbose", "user"); +var_dump($config->get("verbose")); +$config->remove("verbose", "system"); +var_dump($config->get("verbose")); + +print "\n#6.5 testing: get/set/remove w/channels\n"; +$config->readConfigFile('user3.conf'); +$config->setChannels(array('pear', 'test1', 'test2')); +var_dump($config->get('default_channel')); + +print "\n#7 testing: getType\n"; +var_dump($config->getType("__unknown__")); +var_dump($config->getType("verbose")); +var_dump($config->getType("master_server")); +var_dump($config->getType("ext_dir")); + +print "\n#8 testing: getDocs\n"; +print "master_server: " . $config->getDocs("master_server") . "\n"; + +print "\n#9 testing: getKeys\n"; +$keys = $config->getKeys(); +sort($keys); +print implode(" ", $keys) . "\n"; + +print "\n#10 testing: definedBy\n"; +$config->readConfigFile('user.conf'); +var_dump($config->definedBy("verbose")); +$config->set("verbose", 6, "system"); +$config->set("verbose", 3, "user"); +var_dump($config->definedBy("verbose")); +$config->remove("verbose", "system"); +var_dump($config->definedBy("verbose")); +$config->set("verbose", 6, "system"); +$config->remove("verbose", "user"); +var_dump($config->definedBy("verbose")); +$config->remove("verbose", "system"); +var_dump($config->definedBy("verbose")); + +print "\n#10.5 testing: definedBy with channel\n"; +$config->readConfigFile('user3.conf'); +var_dump($config->definedBy('verbose')); +$config->set('default_channel', 'test1'); +var_dump($config->definedBy('verbose')); +var_dump($config->definedBy('php_dir')); +var_dump($config->definedBy('gronk')); +$config->set('default_channel', 'pear'); +var_dump($config->definedBy('verbose', true)); +$config->set('default_channel', 'test1'); +var_dump($config->definedBy('verbose', true)); +var_dump($config->definedBy('php_dir', true)); +var_dump($config->definedBy('gronk', true)); + +print "\n#11 testing: isDefined\n"; +var_dump($config->isDefined("php_dir")); +var_dump($config->isDefined("verbose")); +var_dump($config->isDefined("HTTP_GET_VARS")); +var_dump($config->isDefined("query")); + +print "\n#12 testing: getGroup\n"; +foreach ($keys as $key) { + print "$key: ".$config->getGroup($key)."\n"; +} + +print "\n#13 testing: getGroups\n"; +$groups = $config->getGroups(); +sort($groups); +print implode(", ", $groups) . "\n"; + +print "\n#14 testing: getGroupKeys\n"; +foreach ($groups as $group) { + $gk = $config->getGroupKeys($group); + sort($gk); + print "$group: " . implode(", ", $gk) . "\n"; +} + +print "\n#15 testing: getPrompt\n"; +foreach ($keys as $key) { + print "$key: ".$config->getPrompt($key)."\n"; +} + + +// + +print "done\n"; + +unlink("user.conf"); +unlink("user2.conf"); +unlink("user3.conf"); +unlink("system.conf"); +unlink("merge.conf"); +unlink("merge2.conf"); + +// ------------------------------------------------------------------------- // + +function dump_file($file) +{ + print "..$file:"; + $data = PEAR_Config::_readConfigDataFrom($file); + if (empty($data)) { + print " <empty>\n"; + return; + } + foreach ($data as $k => $v) { + print " $k=\"$v\""; + } + print "\n"; +} + +function dump_files() { + dump_file("system.conf"); + dump_file("user.conf"); +} + +function dump_array($name, $arr) { + print "$name:"; + if (empty($arr)) { + print " <empty>"; + } else { + foreach ($arr as $k => $v) { + if (is_array($v)) { + print "\n "; + dump_array("${name}[$k]", $v); + continue; + } + print " $k=\"$v\""; + } + } + print "\n"; +} + +function dump_config(&$obj, $layer = null) { + if ($layer !== null) { + dump_array($layer, $obj->configuration[$layer]); + return; + } + foreach ($obj->configuration as $layer => $data) { + if ($layer == "default") { + continue; + } + dump_array($layer, $data); + } +} + +?> +--EXPECT-- +#0 starting up +..system.conf: master_server="pear.php.net" +..user.conf: <empty> + +#1 testing: constructor +files: system="system.conf" user="user.conf" + +#2 testing: singleton +string(4) "blah" +string(4) "blah" + +#3 testing: readConfigFile +user: verbose="2" +system: master_server="pear.php.net" +user: <empty> +system: master_server="pear.php.net" + +#4 testing: mergeConfigFile +user: verbose="2" +user: verbose="100" +user: verbose="2" +user: <empty> +unknown config file type `xyzzy' +user: verbose="60" + user[__channels]: + user[__channels][test1]: verbose="70" + + user[__channels][test2]: verbose="71" + + +user: + user[__channels]: + user[__channels][test1]: verbose="898" + + user[__channels][test2]: verbose="899" + + verbose="35" +user: + user[__channels]: + user[__channels][test1]: verbose="70" + + user[__channels][test2]: verbose="71" + + verbose="60" + +#5 testing: config file version detection +toonew.conf: unknown version `2.0' + +#6 testing: get/set/remove +int(1) +int(100) +int(2) +int(50) +int(2) +int(1) + +#6.5 testing: get/set/remove w/channels +string(4) "pear" + +#7 testing: getType +bool(false) +string(7) "integer" +string(6) "string" +string(9) "directory" + +#8 testing: getDocs +master_server: name of the main PEAR server + +#9 testing: getKeys +bin_dir cache_dir cache_ttl data_dir default_channel doc_dir ext_dir http_proxy master_server password php_bin php_dir preferred_state sig_bin sig_keydir sig_keyid sig_type test_dir umask username verbose + +#10 testing: definedBy +string(7) "default" +string(4) "user" +string(4) "user" +string(6) "system" +string(7) "default" + +#10.5 testing: definedBy with channel +string(4) "user" +string(4) "user" +string(7) "default" +string(0) "" +array(2) { + ["layer"]=> + string(4) "user" + ["channel"]=> + string(4) "pear" +} +array(2) { + ["layer"]=> + string(4) "user" + ["channel"]=> + string(5) "test1" +} +array(2) { + ["layer"]=> + string(7) "default" + ["channel"]=> + string(4) "pear" +} +string(0) "" + +#11 testing: isDefined +bool(true) +bool(true) +bool(false) +bool(false) + +#12 testing: getGroup +bin_dir: File Locations +cache_dir: File Locations (Advanced) +cache_ttl: Advanced +data_dir: File Locations (Advanced) +default_channel: Internet Access +doc_dir: File Locations +ext_dir: File Locations +http_proxy: Internet Access +master_server: Internet Access +password: Maintainers +php_bin: File Locations (Advanced) +php_dir: File Locations +preferred_state: Advanced +sig_bin: Maintainers +sig_keydir: Maintainers +sig_keyid: Maintainers +sig_type: Maintainers +test_dir: File Locations (Advanced) +umask: Advanced +username: Maintainers +verbose: Advanced + +#13 testing: getGroups +Advanced, File Locations, File Locations (Advanced), Internet Access, Maintainers + +#14 testing: getGroupKeys +Advanced: cache_ttl, preferred_state, umask, verbose +File Locations: bin_dir, doc_dir, ext_dir, php_dir +File Locations (Advanced): cache_dir, data_dir, php_bin, test_dir +Internet Access: default_channel, http_proxy, master_server +Maintainers: password, sig_bin, sig_keydir, sig_keyid, sig_type, username + +#15 testing: getPrompt +bin_dir: PEAR executables directory +cache_dir: PEAR Installer cache directory +cache_ttl: Cache TimeToLive +data_dir: PEAR data directory +default_channel: Default Channel +doc_dir: PEAR documentation directory +ext_dir: PHP extension directory +http_proxy: HTTP Proxy Server Address +master_server: PEAR server +password: PEAR password (for maintainers) +php_bin: PHP CLI/CGI binary +php_dir: PEAR directory +preferred_state: Preferred Package State +sig_bin: Signature Handling Program +sig_keydir: Signature Key Directory +sig_keyid: Signature Key Id +sig_type: Package Signature Type +test_dir: PEAR test directory +umask: Unix file mask +username: PEAR username (for maintainers) +verbose: Debug Log Level +done
\ No newline at end of file diff --git a/pear/tests/pear_dependency_checkExtension.phpt b/pear/tests/pear_dependency_checkExtension.phpt new file mode 100644 index 000000000..89666a833 --- /dev/null +++ b/pear/tests/pear_dependency_checkExtension.phpt @@ -0,0 +1,260 @@ +--TEST-- +PEAR_Dependency::checkExtension() test +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +if (!ini_get('enable_dl') || ini_get('safe_mode')) { + echo 'skip'; +} + +$dir = ini_get('extension_dir'); +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'; +} + +// get a list of possible extensions +$extensions = array(); +if ($handle = opendir($dir)) { + while (false !== ($file = readdir($handle))) { + if (strpos($file, $suffix) && substr($file, 0, 4) == 'php_') { + $extensions[] = $file; + } + } + closedir($handle); +} + +$loaded = false; +$notloaded = false; +// choose an extension for this test +foreach ($extensions as $ext) { + $ext = substr(substr($ext, 0, strlen($ext) - strlen($suffix)), 4); + if (!$loaded && extension_loaded($ext)) { + $loaded = $ext; + } + if (!$notloaded && !extension_loaded($ext)) { + // safe list for testing + if (in_array($ext, array('zip', 'bz2', 'sqlite', 'dbx'))) { + $notloaded = $ext; + } + } +} +if (!$notloaded || !$loaded) { + echo 'skip'; +} +?> +--FILE-- +<?php + +@mkdir(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'checkPackagetmp'); +require_once "PEAR/Registry.php"; +require_once "PEAR/Dependency.php"; + +$dir = ini_get('extension_dir'); +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'; +} + +// get a list of possible extensions +$extensions = array(); +if ($handle = opendir($dir)) { + while (false !== ($file = readdir($handle))) { + if (strpos($file, $suffix) && substr($file, 0, 4) == 'php_') { + $extensions[] = $file; + } + } + closedir($handle); +} + +$loaded = false; +$notloaded = false; +// choose an extension for this test +foreach ($extensions as $ext) { + $ext = substr(substr($ext, 0, strlen($ext) - strlen($suffix)), 4); + if (!$loaded && extension_loaded($ext)) { + $loaded = $ext; + } + if (!$notloaded && !extension_loaded($ext)) { + // safe list for testing + if (in_array($ext, array('zip', 'bz2', 'sqlite', 'dbx'))) { + $notloaded = $ext; + } + } +} + +$reg = new PEAR_Registry; +$reg->statedir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'checkPackagetmp'; +$dep = new PEAR_Dependency($reg); + +$msg = 'no error'; +$ret = $dep->checkExtension($msg, $loaded, null, 'has'); +echo 'extension 1 ok? '; +echo $ret ? "no\n" : "yes\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkExtension($msg, $notloaded, null, 'not'); +echo 'extension 2 ok? '; +echo $ret ? "no\n" : "yes\n"; +echo $msg . "\n"; + +$loadedver = phpversion($loaded); + +$msg = 'no error'; +$ret = $dep->checkExtension($msg, $loaded, $loadedver + 1, 'ge'); +echo 'extension 3 ok? '; +echo $ret ? "no\n" : "yes\n"; +echo 'message : ' . ($msg == "'$loaded' PHP extension version >= " . ($loadedver + 1) . + " is required" ? "match\n" : "$msg\n" ); + +$msg = 'no error'; +$ret = $dep->checkExtension($msg, $loaded, $loadedver + 1, 'ge', true); +echo 'extension 3 optional ok? '; +echo $ret ? "no\n" : "yes\n"; +echo 'message : ' . ($msg == "'$loaded' PHP extension version >= " . ($loadedver + 1) . + " is recommended to utilize some features" ? "match\n" : "$msg\n" ); + +$msg = 'no error'; +$ret = $dep->checkExtension($msg, $loaded, $loadedver, 'ne'); +echo 'extension 4 ok? '; +echo $ret ? "no\n" : "yes\n"; +echo 'message : ' . ($msg == "'$loaded' PHP extension version != " . $loadedver . + " is required" ? "match\n" : "$msg\n" ); + +$msg = 'no error'; +$ret = $dep->checkExtension($msg, $loaded, $loadedver, 'gt'); +echo 'extension 5 ok? '; +echo $ret ? "no\n" : "yes\n"; +echo 'message : ' . ($msg == "'$loaded' PHP extension version > " . $loadedver . + " is required" ? "match\n" : "$msg\n" ); + +$msg = 'no error'; +$ret = $dep->checkExtension($msg, $loaded, $loadedver, 'gt', true); +echo 'extension 5 optional ok? '; +echo $ret ? "no\n" : "yes\n"; +echo 'message : ' . ($msg == "'$loaded' PHP extension version > " . $loadedver . + " is recommended to utilize some features" ? "match\n" : "$msg\n" ); + +$msg = 'no error'; +$ret = $dep->checkExtension($msg, $loaded, $loadedver, 'lt'); +echo 'extension 6 ok? '; +echo $ret ? "no\n" : "yes\n"; +echo 'message : ' . ($msg == "'$loaded' PHP extension version < " . $loadedver . + " is required" ? "match\n" : "$msg\n" ); + +$msg = 'no error'; +$ret = $dep->checkExtension($msg, $loaded, $loadedver, 'lt', true); +echo 'extension 6 optional ok? '; +echo $ret ? "no\n" : "yes\n"; +echo 'message : ' . ($msg == "'$loaded' PHP extension version < " . $loadedver . + " is recommended to utilize some features" ? "match\n" : "$msg\n" ); + +if ($loadedver == 0) { + echo "extension 7 ok? no\nmessage : match\n"; + echo "extension 7 optional ok? no\nmessage : match\n"; +} else { + $msg = 'no error'; + $ret = $dep->checkExtension($msg, $loaded, $loadedver - 1, 'le'); + echo 'extension 7 ok? '; + echo $ret ? "no\n" : "yes\n"; + echo 'message : ' . ($msg == "'$loaded' PHP extension version <= " . ($loadedver - 1). + " is required" ? "match\n" : "$msg\n"); + + $msg = 'no error'; + $ret = $dep->checkExtension($msg, $loaded, $loadedver - 1, 'le', true); + echo 'extension 7 ok? '; + echo $ret ? "no\n" : "yes\n"; + echo 'message : ' . ($msg == "'$loaded' PHP extension version <= " . ($loadedver - 1). + " is recommended to utilize some features" ? "match\n" : "$msg\n"); +} + +$msg = 'no error'; +$ret = $dep->checkExtension($msg, $loaded, $loadedver, 'eq'); +echo 'extension 8 ok? '; +echo $ret ? "no\n" : "yes\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkExtension($msg, $notloaded, $loadedver, 'ne'); +echo 'extension 9 ok? '; +echo $ret ? "no\n" : "yes\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkExtension($msg, $loaded, $loadedver + 1, 'eq'); +echo 'extension 10 ok? '; +echo $ret ? "no\n" : "yes\n"; +echo 'message : ' . ($msg == "'$loaded' PHP extension version == " . ($loadedver + 1). + " is required" ? "match\n" : "$msg\n"); + +$msg = 'no error'; +$ret = $dep->checkExtension($msg, $loaded, $loadedver + 1, 'eq', true); +echo 'extension 10 optional ok? '; +echo $ret ? "no\n" : "yes\n"; +echo 'message : ' . ($msg == "'$loaded' PHP extension version == " . ($loadedver + 1). + " is recommended to utilize some features" ? "match\n" : "$msg\n"); + +cleanall(); +// ------------------------------------------------------------------------- // + +function cleanall() +{ + $dp = opendir(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'checkPackagetmp'); + while ($ent = readdir($dp)) { + if (substr($ent, -4) == ".reg") { + unlink(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'checkPackagetmp' . DIRECTORY_SEPARATOR . $ent); + } + } + closedir($dp); + rmdir(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'checkPackagetmp'); +} + +?> +--EXPECT-- +extension 1 ok? yes +no error +extension 2 ok? yes +no error +extension 3 ok? no +message : match +extension 3 optional ok? no +message : match +extension 4 ok? no +message : match +extension 5 ok? no +message : match +extension 5 optional ok? no +message : match +extension 6 ok? no +message : match +extension 6 optional ok? no +message : match +extension 7 ok? no +message : match +extension 7 optional ok? no +message : match +extension 8 ok? yes +no error +extension 9 ok? yes +no error +extension 10 ok? no +message : match +extension 10 optional ok? no +message : match diff --git a/pear/tests/pear_dependency_checkPackage.phpt b/pear/tests/pear_dependency_checkPackage.phpt new file mode 100644 index 000000000..90dfb556f --- /dev/null +++ b/pear/tests/pear_dependency_checkPackage.phpt @@ -0,0 +1,267 @@ +--TEST-- +PEAR_Dependency::checkPackage() test +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php +require_once "PEAR/Registry.php"; +require_once "PEAR/Dependency.php"; + +mkdir(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'checkPackagetmp'); +// snarfed from pear_registry.phpt +$reg = new PEAR_Registry; +$reg->statedir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'checkPackagetmp'; + +$files1 = array( + "pkg1-1.php" => array( + "role" => "php", + ), + "pkg1-2.php" => array( + "role" => "php", + "baseinstalldir" => "pkg1", + ), + ); +$reg->addPackage("pkg1", array("name" => "pkg1", "version" => "1.0", "filelist" => $files1)); + +$dep = new PEAR_Dependency($reg); +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1'); +echo 'has works? '; +echo $ret ? "no\n" : "yes\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', '1.0', 'eq'); +echo 'eq 1.0 works? '; +echo $ret ? "no\n" : "yes\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', '1.0', 'le'); +echo 'le 1.0 works? '; +echo $ret ? "no\n" : "yes\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', '1.1', 'lt'); +echo 'lt 1.1 works? '; +echo $ret ? "no\n" : "yes\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', '1.1', 'ne'); +echo 'ne 1.1 works? '; +echo $ret ? "no\n" : "yes\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', '1.0', 'ge'); +echo 'ge 1.0 works? '; +echo $ret ? "no\n" : "yes\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', '0.9', 'gt'); +echo 'ge 0.9 works? '; +echo $ret ? "no\n" : "yes\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg2', null, 'not'); +echo 'not pkg2 works? '; +echo $ret ? "no\n" : "yes\n"; +echo $msg . "\n"; + +// error conditions + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg2', null, 'has'); +echo 'has pkg2 works? '; +echo $ret ? "no\n" : "yes\n"; +echo '$ret is PEAR_DEPENDENCY_MISSING? '; +echo ($ret == PEAR_DEPENDENCY_MISSING) ? "yes\n" : "no\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg2', null, 'has', true); +echo 'has optional pkg2 works? '; +echo $ret ? "no\n" : "yes\n"; +echo '$ret is PEAR_DEPENDENCY_MISSING_OPTIONAL? '; +echo ($ret == PEAR_DEPENDENCY_MISSING_OPTIONAL) ? "yes\n" : "no\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', '0.9', 'le'); +echo 'le 0.9 works? '; +echo $ret ? "no\n" : "yes\n"; +echo '$ret is PEAR_DEPENDENCY_CONFLICT? '; +echo ($ret == PEAR_DEPENDENCY_CONFLICT) ? "yes\n" : "no\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', '0.9', 'le', true); +echo 'optional le 0.9 works? '; +echo $ret ? "no\n" : "yes\n"; +echo '$ret is PEAR_DEPENDENCY_CONFLICT_OPTIONAL? '; +echo ($ret == PEAR_DEPENDENCY_CONFLICT_OPTIONAL) ? "yes\n" : "no\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', '1.0', 'ne'); +echo 'ne 1.0 works? '; +echo $ret ? "no\n" : "yes\n"; +echo '$ret is PEAR_DEPENDENCY_CONFLICT? '; +echo ($ret == PEAR_DEPENDENCY_CONFLICT) ? "yes\n" : "no\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', '1.0', 'ne', true); +echo 'optional ne 1.0 works? '; +echo $ret ? "no\n" : "yes\n"; +echo '$ret is PEAR_DEPENDENCY_CONFLICT_OPTIONAL? '; +echo ($ret == PEAR_DEPENDENCY_CONFLICT_OPTIONAL) ? "yes\n" : "no\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', '1.1', 'ge'); +echo 'ge 1.1 works? '; +echo $ret ? "no\n" : "yes\n"; +echo '$ret is PEAR_DEPENDENCY_UPGRADE_MINOR? '; +echo ($ret == PEAR_DEPENDENCY_UPGRADE_MINOR) ? "yes\n" : "no\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', '1.1', 'ge', true); +echo 'optional ge 1.1 works? '; +echo $ret ? "no\n" : "yes\n"; +echo '$ret is PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL? '; +echo ($ret == PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL) ? "yes\n" : "no\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', '2.0', 'ge'); +echo 'ge 2.0 works? '; +echo $ret ? "no\n" : "yes\n"; +echo '$ret is PEAR_DEPENDENCY_UPGRADE_MAJOR? '; +echo ($ret == PEAR_DEPENDENCY_UPGRADE_MAJOR) ? "yes\n" : "no\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', '2.0', 'ge', true); +echo 'optional ge 2.0 works? '; +echo $ret ? "no\n" : "yes\n"; +echo '$ret is PEAR_DEPENDENCY_UPGRADE_MAJOR_OPTIONAL? '; +echo ($ret == PEAR_DEPENDENCY_UPGRADE_MAJOR_OPTIONAL) ? "yes\n" : "no\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', '1.0', 'gt'); +echo 'gt 1.0 works? '; +echo $ret ? "no\n" : "yes\n"; +echo '$ret is PEAR_DEPENDENCY_UPGRADE_MINOR? '; +echo ($ret == PEAR_DEPENDENCY_UPGRADE_MINOR) ? "yes\n" : "no\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', '1.0', 'gt', true); +echo 'optional gt 1.0 works? '; +echo $ret ? "no\n" : "yes\n"; +echo '$ret is PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL? '; +echo ($ret == PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL) ? "yes\n" : "no\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', null, 'not'); +echo 'not pkg1 works? '; +echo $ret ? "no\n" : "yes\n"; +echo '$ret is PEAR_DEPENDENCY_CONFLICT? '; +echo ($ret == PEAR_DEPENDENCY_CONFLICT) ? "yes\n" : "no\n"; +echo $msg . "\n"; + +$msg = 'no error'; +$ret = $dep->checkPackage($msg, 'pkg1', null, 'foobar'); +echo 'foobar pkg1 works? '; +echo $ret ? "no\n" : "yes\n"; +echo '$ret is PEAR_DEPENDENCY_BAD_DEPENDENCY? '; +echo ($ret == PEAR_DEPENDENCY_BAD_DEPENDENCY) ? "yes\n" : "no\n"; +echo $msg . "\n"; +cleanall(); + +// ------------------------------------------------------------------------- // + +function cleanall() +{ + $dp = opendir(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'checkPackagetmp'); + while ($ent = readdir($dp)) { + if (substr($ent, -4) == ".reg") { + unlink(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'checkPackagetmp' . DIRECTORY_SEPARATOR . $ent); + } + } + closedir($dp); + rmdir(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'checkPackagetmp'); +} + +?> +--EXPECT-- +has works? yes +no error +eq 1.0 works? yes +no error +le 1.0 works? yes +no error +lt 1.1 works? yes +no error +ne 1.1 works? yes +no error +ge 1.0 works? yes +no error +ge 0.9 works? yes +no error +not pkg2 works? yes +no error +has pkg2 works? no +$ret is PEAR_DEPENDENCY_MISSING? yes +requires package `pear::pkg2' +has optional pkg2 works? no +$ret is PEAR_DEPENDENCY_MISSING_OPTIONAL? yes +package `pear::pkg2' is recommended to utilize some features. +le 0.9 works? no +$ret is PEAR_DEPENDENCY_CONFLICT? yes +requires package `pear::pkg1' <= 0.9 +optional le 0.9 works? no +$ret is PEAR_DEPENDENCY_CONFLICT_OPTIONAL? yes +package `pear::pkg1' version <= 0.9 is recommended to utilize some features. Installed version is 1.0 +ne 1.0 works? no +$ret is PEAR_DEPENDENCY_CONFLICT? yes +requires package `pear::pkg1' != 1.0 +optional ne 1.0 works? no +$ret is PEAR_DEPENDENCY_CONFLICT_OPTIONAL? yes +package `pear::pkg1' version != 1.0 is recommended to utilize some features. Installed version is 1.0 +ge 1.1 works? no +$ret is PEAR_DEPENDENCY_UPGRADE_MINOR? yes +requires package `pear::pkg1' >= 1.1 +optional ge 1.1 works? no +$ret is PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL? yes +package `pear::pkg1' version >= 1.1 is recommended to utilize some features. Installed version is 1.0 +ge 2.0 works? no +$ret is PEAR_DEPENDENCY_UPGRADE_MAJOR? yes +requires package `pear::pkg1' >= 2.0 +optional ge 2.0 works? no +$ret is PEAR_DEPENDENCY_UPGRADE_MAJOR_OPTIONAL? yes +package `pear::pkg1' version >= 2.0 is recommended to utilize some features. Installed version is 1.0 +gt 1.0 works? no +$ret is PEAR_DEPENDENCY_UPGRADE_MINOR? yes +requires package `pear::pkg1' > 1.0 +optional gt 1.0 works? no +$ret is PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL? yes +package `pear::pkg1' version > 1.0 is recommended to utilize some features. Installed version is 1.0 +not pkg1 works? no +$ret is PEAR_DEPENDENCY_CONFLICT? yes +conflicts with package `pear::pkg1' +foobar pkg1 works? no +$ret is PEAR_DEPENDENCY_BAD_DEPENDENCY? yes +relation 'foobar' with requirement '' is not supported (name=pear::pkg1) diff --git a/pear/tests/pear_dependency_checkPackageUninstall.phpt b/pear/tests/pear_dependency_checkPackageUninstall.phpt new file mode 100644 index 000000000..b93a2ea1d --- /dev/null +++ b/pear/tests/pear_dependency_checkPackageUninstall.phpt @@ -0,0 +1,176 @@ +--TEST-- +PEAR_Dependency::checkPackageUninstall() test +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php + +require_once "PEAR/Registry.php"; +require_once "PEAR/Dependency.php"; + +// snarfed from pear_registry.phpt +$reg = new PEAR_Registry; +@mkdir(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'checkPackagetmp'); +$reg->statedir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'checkPackagetmp'; + +$files1 = array( + "pkg1-1.php" => array( + "role" => "php", + ), + "pkg1-2.php" => array( + "role" => "php", + "baseinstalldir" => "pkg1", + ), + ); +$files2 = array( + "pkg2-1.php" => array( + "role" => "php", + ), + "pkg2-2.php" => array( + "role" => "php", + "baseinstalldir" => "pkg2", + ), + ); +$files3 = array( + "pkg3-1.php" => array( + "role" => "php", + ), + "pkg3-2.php" => array( + "role" => "php", + "baseinstalldir" => "pkg3", + ), + ); + +$reg->addPackage("pkg2", array("name" => "pkg2", "version" => "2.0", "filelist" => $files2)); +$reg->addPackage("pkg3", array("name" => "pkg3", "version" => "3.0", "filelist" => $files3)); + +$reg->addPackage("pkg1", array("name" => "pkg1", "version" => "1.0", "filelist" => $files1, + 'release_deps' => array( + array('type' => 'pkg', 'name' => 'pkg3', 'rel' => 'not') + ))); + +$dep = new PEAR_Dependency($reg); +$msg = ''; +$warn = ''; +$ret = $dep->checkPackageUninstall($msg, $warn, 'pkg1'); +echo 'uninstall ok? '; +echo $ret ? "no\n" : "yes\n"; +echo $msg . "\n"; +echo $warn . "\n"; + +cleanall(); + +$reg->addPackage("pkg2", array("name" => "pkg2", "version" => "2.0", "filelist" => $files2)); +$reg->addPackage("pkg3", array("name" => "pkg3", "version" => "3.0", "filelist" => $files3)); + +$reg->addPackage("pkg1", array("name" => "pkg1", "version" => "1.0", "filelist" => $files1, + 'release_deps' => array( + array('type' => 'pkg', 'name' => 'pkg2', 'rel' => 'ne', 'version' => '6.0') + ))); + +$dep = new PEAR_Dependency($reg); +$msg = ''; +$warn = ''; +$ret = $dep->checkPackageUninstall($msg, $warn, 'pkg2'); +echo 'uninstall ok? '; +echo $ret ? "no\n" : "yes\n"; +echo $msg . "\n"; +echo $warn . "\n"; + +cleanall(); + +$reg->addPackage("pkg2", array("name" => "pkg2", "version" => "2.0", "filelist" => $files2)); +$reg->addPackage("pkg3", array("name" => "pkg3", "version" => "3.0", "filelist" => $files3)); + +$reg->addPackage("pkg1", array("name" => "pkg1", "version" => "1.0", "filelist" => $files1, + 'release_deps' => array( + array('type' => 'pkg', 'name' => 'pkg2', 'rel' => 'has') + ))); + +$dep = new PEAR_Dependency($reg); +$msg = ''; +$warn = ''; +$ret = $dep->checkPackageUninstall($msg, $warn, 'pkg2'); +echo 'uninstall ok? '; +echo $ret ? "no\n" : "yes\n"; +echo $msg . "\n"; +echo $warn . "\n"; + +cleanall(); + +$reg->addPackage("pkg2", array("name" => "pkg2", "version" => "2.0", "filelist" => $files2)); +$reg->addPackage("pkg3", array("name" => "pkg3", "version" => "3.0", "filelist" => $files3)); + +$reg->addPackage("pkg1", array("name" => "pkg1", "version" => "1.0", "filelist" => $files1, + 'release_deps' => array( + array('type' => 'pkg', 'name' => 'pkg2', 'rel' => 'has', 'optional' => 'no') + ))); + +$dep = new PEAR_Dependency($reg); +$msg = ''; +$warn = ''; +$ret = $dep->checkPackageUninstall($msg, $warn, 'pkg2'); +echo 'uninstall ok? '; +echo $ret ? "no\n" : "yes\n"; +echo $msg . "\n"; +echo $warn . "\n"; + +cleanall(); + +$reg->addPackage("pkg2", array("name" => "pkg2", "version" => "2.0", "filelist" => $files2)); +$reg->addPackage("pkg3", array("name" => "pkg3", "version" => "3.0", "filelist" => $files3)); + +$reg->addPackage("pkg1", array("name" => "pkg1", "version" => "1.0", "filelist" => $files1, + 'release_deps' => array( + array('type' => 'pkg', 'name' => 'pkg2', 'rel' => 'has', 'optional' => 'yes') + ))); + +$dep = new PEAR_Dependency($reg); +$msg = ''; +$warn = ''; +$ret = $dep->checkPackageUninstall($msg, $warn, 'pkg2'); +echo 'uninstall ok? '; +echo $ret ? "no\n" : "yes\n"; +echo $msg . "\n"; +echo $warn . "\n"; + +cleanall(); + +// ------------------------------------------------------------------------- // + +function cleanall() +{ + $dp = opendir(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'checkPackagetmp'); + while ($ent = readdir($dp)) { + if (substr($ent, -4) == ".reg") { + unlink(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'checkPackagetmp' . DIRECTORY_SEPARATOR . $ent); + } + } + closedir($dp); + rmdir(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'checkPackagetmp'); +} + +?> +--EXPECT-- +uninstall ok? yes + + +uninstall ok? yes + + +uninstall ok? no +Package 'pear::pkg1' depends on 'pear::pkg2' + + +uninstall ok? no +Package 'pear::pkg1' depends on 'pear::pkg2' + + +uninstall ok? yes + + +Warning: Package 'pear::pkg1' optionally depends on 'pear::pkg2'
\ No newline at end of file diff --git a/pear/tests/pear_downloader_invalid.phpt b/pear/tests/pear_downloader_invalid.phpt new file mode 100644 index 000000000..7c10dcd80 --- /dev/null +++ b/pear/tests/pear_downloader_invalid.phpt @@ -0,0 +1,379 @@ +--TEST-- +PEAR_Downloader::download() invalid values test +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php + +$server = 'pear.Chiara'; +//$server = 'test.pear.php.net'; +$temp_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'testinstallertemp'; +if (!is_dir($temp_path)) { + mkdir($temp_path); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'php')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'php'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'data')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'data'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'doc')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'doc'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'test')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'test'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'ext')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'ext'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'script')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'script'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'tmp')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'tmp'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'bin')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'bin'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'cache')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'cache'); +} +// make the fake configuration - we'll use one of these and it should work +$config = serialize(array('master_server' => $server, + 'preferred_state' => 'stable', + 'cache_dir' => $temp_path . DIRECTORY_SEPARATOR . 'cache', + 'php_dir' => $temp_path . DIRECTORY_SEPARATOR . 'php', + 'ext_dir' => $temp_path . DIRECTORY_SEPARATOR . 'ext', + 'data_dir' => $temp_path . DIRECTORY_SEPARATOR . 'data', + 'doc_dir' => $temp_path . DIRECTORY_SEPARATOR . 'doc', + 'test_dir' => $temp_path . DIRECTORY_SEPARATOR . 'test', + 'bin_dir' => $temp_path . DIRECTORY_SEPARATOR . 'bin',)); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.conf'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.conf', 'w'); +fwrite($fp, $config); +fclose($fp); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.ini'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.ini', 'w'); +fwrite($fp, $config); +fclose($fp); + +putenv('PHP_PEAR_SYSCONF_DIR='.$temp_path); +$home = getenv('HOME'); +if (!empty($home)) { + // for PEAR_Config initialization + putenv('HOME="'.$temp_path); +} +require_once "PEAR/Downloader.php"; +require_once 'PEAR/Installer.php'; +require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'download_test_classes.php.inc'; + +// no UI is needed for these tests +$ui = false; +$curdir = getcwd(); +chdir(dirname(__FILE__)); + +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'catchit'); +$error_to_catch = false; +function catchit($err) +{ + global $error_to_catch; + if ($error_to_catch) { + if ($err->getMessage() == $error_to_catch) { + $error_to_catch = false; + echo "Caught expected error\n"; + return; + } + } + echo "Caught error: " . $err->getMessage() . "\n"; +} + +$config = &PEAR_Config::singleton(); +// initialize fake pear channel +require_once 'PEAR/ChannelFile.php'; +$chan = new PEAR_ChannelFile; +$chan->setName('pear'); +$chan->setSummary('PEAR'); +$chan->setServer($server); +$chan->setDefaultPEARProtocols(); +$reg = new PEAR_Registry($config->get('php_dir'), $chan); +$options = array(); +$installer = &new test_PEAR_Downloader($ui, $options, $config); + +echo "-=-=-=-=-=-=-=-=- Failure Tests -=-=-=-=-=-=-=-=-=-=-\n"; + +echo "Test invalid package name:\n"; +$packages = array("/invalid+packagename"); +$a = $installer->doDownload($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump(get_class($a), $installer->getErrorMsgs(), $installpackages); + +echo "Test download of a package with no releases:\n"; +$packages = array("noreleases"); +$a = $installer->doDownload($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump(get_class($a), $installer->getErrorMsgs(), $installpackages); + +echo "Test download of a non-existing package version:\n"; +$packages = array("pkg1-1976.9.2"); +$a = $installer->doDownload($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump(get_class($a), $installer->getErrorMsgs(), $installpackages); + +echo "Test download of a non-existing package release state:\n"; +$packages = array("pkg1-snapshot"); +$a = $installer->doDownload($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump(get_class($a), $installer->getErrorMsgs(), $installpackages); + +echo "Test download of invalid release state:\n"; +$packages = array("pkg1-burgerking"); +$a = $installer->doDownload($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump(get_class($a), $installer->getErrorMsgs(), $installpackages); + +$installer->configSet('preferred_state', 'stable'); + +echo "Test automatic version resolution (stable):\n"; +$packages = array("stabilitytoolow"); +$a = $installer->doDownload($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump(get_class($a), $installer->getErrorMsgs(), $installpackages); + +echo "Test automatic version resolution (stable) with --force:\n"; +$packages = array("stabilitytoolow"); +$installer->setOptions(array('force' => true)); +$a = $installer->doDownload($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump(get_class($a), $installer->getErrorMsgs(), $installpackages[0]['info']['version']); + +$installer->configSet('preferred_state', 'beta'); +$installer->setOptions(array()); + +echo "Test automatic version resolution (beta):\n"; +$packages = array("stabilitytoolow"); +$a = $installer->doDownload($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump(get_class($a), $installer->getErrorMsgs(), $installpackages[0]['info']['version']); + +$installer->configSet('preferred_state', 'alpha'); + +echo "Test automatic version resolution (alpha):\n"; +$packages = array("stabilitytoolow"); +$a = $installer->doDownload($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump(get_class($a), $installer->getErrorMsgs(), $installpackages[0]['info']['version']); + +$installer->configSet('preferred_state', 'devel'); + +echo "Test automatic version resolution (devel):\n"; +$packages = array("stabilitytoolow"); +$a = $installer->doDownload($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump(get_class($a), $installer->getErrorMsgs(), $installpackages[0]['info']['version']); + +echo "Test download attempt if a version is already installed:\n"; + +$forinstall = &new PEAR_Installer($ui); +$forinstall->setOptions(array()); +$installer->setOptions(array()); + +$installer->doDownload(array('pkg6')); +$pkgs = $installer->getDownloadedPackages(); +$forinstall->install($pkgs[0]['file']); +$installer->doDownload(array('pkg6')); +var_dump(get_class($a), $installer->getErrorMsgs()); + +echo "Test download attempt if a version is already installed with --force:\n"; + +$installer->setOptions(array('force' => true)); + +$installer->doDownload(array('pkg6')); +$pkgs = $installer->getDownloadedPackages(); +var_dump(get_class($a), $installer->getErrorMsgs(), $pkgs[0]['info']['version']); + +echo "Test download attempt if a version is already installed with upgrade, same version:\n"; + +$installer->setOptions(array('upgrade' => true)); + +$installer->doDownload(array('pkg6')); +$pkgs = $installer->getDownloadedPackages(); +var_dump(get_class($a), $installer->getErrorMsgs()); + +echo "Test download attempt if a version is already installed with upgrade, lesser version:\n"; + +$installer->setOptions(array('upgrade' => true)); + +$installer->doDownload(array('pkg6-1.1')); +$pkgs = $installer->getDownloadedPackages(); +var_dump(get_class($a), $installer->getErrorMsgs()); + +echo "Test download attempt with --alldeps, but dependency has no releases:\n"; + +$installer->setOptions(array('alldeps' => true)); + +$installer->doDownload(array('depnoreleases')); +$pkgs = $installer->getDownloadedPackages(); +var_dump(get_class($a), $installer->getErrorMsgs()); + +echo "Test download attempt with --onlyreqdeps, but dependency has no releases:\n"; + +$installer->setOptions(array('onlyreqdeps' => true)); + +$installer->doDownload(array('depnoreleases')); +$pkgs = $installer->getDownloadedPackages(); +var_dump(get_class($a), $installer->getErrorMsgs()); + +$installer->configSet('preferred_state', 'stable'); +echo "Test download attempt with --alldeps, but dependency is too unstable:\n"; +$installer->setOptions(array('alldeps' => true)); + +$installer->doDownload(array('depunstable')); +$pkgs = $installer->getDownloadedPackages(); +var_dump(get_class($a), $installer->getErrorMsgs()); + +echo "Test download attempt with --onlyreqdeps, but dependency is too unstable:\n"; + +$installer->setOptions(array('onlyreqdeps' => true)); + +$installer->doDownload(array('depunstable')); +$pkgs = $installer->getDownloadedPackages(); +var_dump(get_class($a), $installer->getErrorMsgs()); + +chdir($curdir); +cleanall($temp_path); + +//echo implode("\n", array_values($GLOBALS['totalPHP'])); + + +// ------------------------------------------------------------------------- // + +function cleanall($dir) +{ + $dp = opendir($dir); + while ($ent = readdir($dp)) { + if ($ent == '.' || $ent == '..') { + continue; + } + if (is_dir($dir . DIRECTORY_SEPARATOR . $ent)) { + cleanall($dir . DIRECTORY_SEPARATOR . $ent); + } else { + unlink($dir . DIRECTORY_SEPARATOR . $ent); + } + } + closedir($dp); + rmdir($dir); +} +?> +--EXPECT-- +-=-=-=-=-=-=-=-=- Failure Tests -=-=-=-=-=-=-=-=-=-=- +Test invalid package name: +Caught error: Package name '/invalid+packagename' not valid for channel 'pear' +string(10) "pear_error" +array(0) { +} +array(0) { +} +Test download of a package with no releases: +Caught error: No releases found for package 'pear::noreleases' +string(10) "pear_error" +array(0) { +} +array(0) { +} +Test download of a non-existing package version: +Caught error: No release of 'pear::pkg1' with version '1976.9.2' found, latest release is version '2.0b1', stability 'beta', use --force to install +string(10) "pear_error" +array(0) { +} +array(0) { +} +Test download of a non-existing package release state: +Caught error: No release of 'pear::pkg1' with state 'snapshot' found, latest release is version '2.0b1', stability 'beta', use --force to install +string(10) "pear_error" +array(0) { +} +array(0) { +} +Test download of invalid release state: +Caught error: Invalid suffix '-burgerking', be sure to pass a valid PEAR version number or release state +string(10) "pear_error" +array(0) { +} +array(0) { +} +Test automatic version resolution (stable): +Caught error: No release of 'pear::stabilitytoolow' within preferred_state of 'stable' found, latest release is version '3.0dev', stability 'devel', use --force to install +string(10) "pear_error" +array(0) { +} +array(0) { +} +Test automatic version resolution (stable) with --force: +Warning: No release of 'pear::stabilitytoolow' within preferred_state of 'stable' found, latest release, version '3.0dev', stability 'devel' will be downloaded +bool(false) +array(0) { +} +string(6) "3.0dev" +Test automatic version resolution (beta): +bool(false) +array(0) { +} +string(5) "1.0b1" +Test automatic version resolution (alpha): +bool(false) +array(0) { +} +string(5) "2.0a1" +Test automatic version resolution (devel): +bool(false) +array(0) { +} +string(6) "3.0dev" +Test download attempt if a version is already installed: +Package 'pear::pkg6' already installed, skipping +bool(false) +array(0) { +} +Test download attempt if a version is already installed with --force: +bool(false) +array(0) { +} +string(5) "2.0b1" +Test download attempt if a version is already installed with upgrade, same version: +Package 'pear::pkg6', version '2.0b1' already installed, skipping +bool(false) +array(0) { +} +Test download attempt if a version is already installed with upgrade, lesser version: +Package 'pear::pkg6' version '2.0b1' is installed and 2.0b1 is > requested '1.1', skipping +bool(false) +array(0) { +} +Test download attempt with --alldeps, but dependency has no releases: +bool(false) +array(1) { + [0]=> + string(75) "Package 'pear::depnoreleases' dependency 'pear::noreleases' has no releases" +} +Test download attempt with --onlyreqdeps, but dependency has no releases: +bool(false) +array(1) { + [0]=> + string(75) "Package 'pear::depnoreleases' dependency 'pear::noreleases' has no releases" +} +Test download attempt with --alldeps, but dependency is too unstable: +bool(false) +array(1) { + [0]=> + string(103) "Release for 'pear::depunstable' dependency 'pear::stabilitytoolow' has state 'devel', requires 'stable'" +} +Test download attempt with --onlyreqdeps, but dependency is too unstable: +bool(false) +array(1) { + [0]=> + string(103) "Release for 'pear::depunstable' dependency 'pear::stabilitytoolow' has state 'devel', requires 'stable'" +}
\ No newline at end of file diff --git a/pear/tests/pear_downloader_new.phpt b/pear/tests/pear_downloader_new.phpt new file mode 100644 index 000000000..bcbbf026a --- /dev/null +++ b/pear/tests/pear_downloader_new.phpt @@ -0,0 +1,578 @@ +--TEST-- +PEAR_Downloader::download() test +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php + +$server = 'pear.Chiara'; +//$server = 'test.pear.php.net'; +$temp_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'testinstallertemp'; +if (!is_dir($temp_path)) { + mkdir($temp_path); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'php')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'php'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'data')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'data'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'doc')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'doc'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'test')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'test'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'ext')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'ext'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'script')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'script'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'tmp')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'tmp'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'bin')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'bin'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'cache')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'cache'); +} +// make the fake configuration - we'll use one of these and it should work +$config = serialize(array('master_server' => $server, + 'preferred_state' => 'stable', + 'cache_dir' => $temp_path . DIRECTORY_SEPARATOR . 'cache', + 'php_dir' => $temp_path . DIRECTORY_SEPARATOR . 'php', + 'ext_dir' => $temp_path . DIRECTORY_SEPARATOR . 'ext', + 'data_dir' => $temp_path . DIRECTORY_SEPARATOR . 'data', + 'doc_dir' => $temp_path . DIRECTORY_SEPARATOR . 'doc', + 'test_dir' => $temp_path . DIRECTORY_SEPARATOR . 'test', + 'bin_dir' => $temp_path . DIRECTORY_SEPARATOR . 'bin',)); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.conf'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.conf', 'w'); +fwrite($fp, $config); +fclose($fp); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.ini'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.ini', 'w'); +fwrite($fp, $config); +fclose($fp); + +putenv('PHP_PEAR_SYSCONF_DIR='.$temp_path); +$home = getenv('HOME'); +if (!empty($home)) { + // for PEAR_Config initialization + putenv('HOME="'.$temp_path); +} +require_once "PEAR/Downloader.php"; +require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'download_test_classes.php.inc'; + +// no UI is needed for these tests +$ui = false; +$curdir = getcwd(); +chdir(dirname(__FILE__)); + +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'catchit'); +$error_to_catch = false; +function catchit($err) +{ + global $error_to_catch; + if ($error_to_catch) { + if ($err->getMessage() == $error_to_catch) { + $error_to_catch = false; + echo "Caught expected error\n"; + return; + } + } + echo "Caught error: " . $err->getMessage() . "\n"; +} + +echo "Test simple direct url download:\n"; + +$config = &PEAR_Config::singleton(); +// initialize fake pear channel +require_once 'PEAR/ChannelFile.php'; +$chan = new PEAR_ChannelFile; +$chan->setName('pear'); +$chan->setSummary('PEAR'); +$chan->setServer($server); +$chan->setDefaultPEARProtocols(); + +$reg = new PEAR_Registry($config->get('php_dir'), $chan); +$packages = array("http://$server/get/pkg6-1.1.tgz"); +$options = array(); +$installer = &new test_PEAR_Downloader($ui, $options, $config); +$a = $installer->download($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump($a, $installer->getErrorMsgs()); + +echo "File exists? "; +echo (is_file($installpackages[0]['file'])) ? "yes\n" : "no\n"; +echo "File is the same? "; +$good = implode('', file(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-1.1.tgz')); +$dled = implode('', file($installpackages[0]['file'])); +echo ($good == $dled) ? "yes\n" : "no\n"; +unlink($installpackages[0]['file']); +unset($installpackages[0]['file']); +var_dump($installpackages); + +echo "Test simple package name download:\n"; +$installpackages = $errors = array(); +$packages = array('pkg6'); +$a = $installer->download($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump($a, $installer->getErrorMsgs()); + +echo "File exists? "; +echo (is_file($installpackages[0]['file'])) ? "yes\n" : "no\n"; +echo "File is the same? "; +$good = implode('', file(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-1.1.tgz')); +$dled = implode('', file($installpackages[0]['file'])); +echo ($good == $dled) ? "yes\n" : "no\n"; +unlink($installpackages[0]['file']); +unset($installpackages[0]['file']); +var_dump($installpackages); + +echo "Test package name with version download:\n"; +$installpackages = $errors = array(); +$packages = array('pkg6-1.1'); +$a = $installer->download($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump($a, $installer->getErrorMsgs()); + +echo "File exists? "; +echo (is_file($installpackages[0]['file'])) ? "yes\n" : "no\n"; +echo "File is the same? "; +$good = implode('', file(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-1.1.tgz')); +$dled = implode('', file($installpackages[0]['file'])); +echo ($good == $dled) ? "yes\n" : "no\n"; +unlink($installpackages[0]['file']); + +echo "Test package name with state stable download:\n"; +$installpackages = $errors = array(); +$packages = array('pkg6-stable'); +$a = $installer->download($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump($a, $installer->getErrorMsgs()); + +echo "File exists? "; +echo (is_file($installpackages[0]['file'])) ? "yes\n" : "no\n"; +echo "File is the same? "; +$good = implode('', file(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-1.1.tgz')); +$dled = implode('', file($installpackages[0]['file'])); +echo ($good == $dled) ? "yes\n" : "no\n"; +unlink($installpackages[0]['file']); + +echo "Test package name with state beta download:\n"; +$installpackages = $errors = array(); +$packages = array('pkg6-beta'); +$a = $installer->download($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump($a, $installer->getErrorMsgs()); + +echo "File exists? "; +echo (is_file($installpackages[0]['file'])) ? "yes\n" : "no\n"; +echo "File is the same? "; +$good = implode('', file(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-2.0b1.tgz')); +$dled = implode('', file($installpackages[0]['file'])); +echo ($good == $dled) ? "yes\n" : "no\n"; +unlink($installpackages[0]['file']); + +echo "================\nTest preferred_state = beta\n"; +$installer->configSet('preferred_state', 'beta'); + +echo "Test simple package name download:\n"; +$installpackages = $errors = array(); +$packages = array('pkg6'); +$a = $installer->download($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump($a, $installer->getErrorMsgs()); + +echo "File exists? "; +echo (is_file($installpackages[0]['file'])) ? "yes\n" : "no\n"; +echo "File is the same? "; +$good = implode('', file(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-2.0b1.tgz')); +$dled = implode('', file($installpackages[0]['file'])); +echo ($good == $dled) ? "yes\n" : "no\n"; +unlink($installpackages[0]['file']); +unset($installpackages[0]['file']); + +echo "\n================Test --alldeps\nTest preferred_state = stable\n"; +$installer->configSet('preferred_state', 'stable'); + +$installer = &new test_PEAR_Downloader($ui, array('alldeps' => true), $config); +$packages = array("http://$server/get/pkg1-1.1.tgz"); +$a = $installer->download($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump($a, $installer->getErrorMsgs()); +echo "Packages downloaded and version:\n"; +foreach ($installpackages as $package) { + echo $package['pkg'] . '-' . $package['info']['version'] . "\n"; +} +$packages = array("pkg1"); +$a = $installer->download($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump($a, $installer->getErrorMsgs()); +echo "Packages downloaded and version:\n"; +foreach ($installpackages as $package) { + echo $package['pkg'] . '-' . $package['info']['version'] . "\n"; +} + +echo "Test preferred_state = beta:\n"; +$installer->configSet('preferred_state', 'beta'); + +$packages = array("pkg1"); +$a = $installer->download($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump($a, $installer->getErrorMsgs()); +echo "Packages downloaded and version:\n"; +foreach ($installpackages as $package) { + echo $package['pkg'] . '-' . $package['info']['version'] . "\n"; +} + +echo "Test preferred_state = alpha:\n"; +$installer->configSet('preferred_state', 'alpha'); + +$packages = array("pkg1"); +$a = $installer->download($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump($a, $installer->getErrorMsgs()); +echo "Packages downloaded and version:\n"; +foreach ($installpackages as $package) { + echo $package['pkg'] . '-' . $package['info']['version'] . "\n"; +} +echo "\n================Test --onlyreqdeps\nTest preferred_state = stable\n"; +$config->set('preferred_state', 'stable'); + +$installer = &new test_PEAR_Downloader($ui, array('onlyreqdeps' => true), $config); +$packages = array("http://$server/get/pkg1-1.1.tgz"); +$a = $installer->download($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump($a, $installer->getErrorMsgs()); +echo "Packages downloaded and version:\n"; +foreach ($installpackages as $package) { + echo $package['pkg'] . '-' . $package['info']['version'] . "\n"; +} +$packages = array("pkg1"); +$a = $installer->download($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump($a, $installer->getErrorMsgs()); +echo "Packages downloaded and version:\n"; +foreach ($installpackages as $package) { + echo $package['pkg'] . '-' . $package['info']['version'] . "\n"; +} + +echo "Test preferred_state = beta:\n"; +$installer->configSet('preferred_state', 'beta'); + +$packages = array("pkg1"); +$a = $installer->download($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump($a, $installer->getErrorMsgs()); +echo "Packages downloaded and version:\n"; +foreach ($installpackages as $package) { + echo $package['pkg'] . '-' . $package['info']['version'] . "\n"; +} + +echo "Test preferred_state = alpha:\n"; +$installer->configSet('preferred_state', 'alpha'); + +$packages = array("pkg1"); +$a = $installer->download($packages); +$installpackages = $installer->getDownloadedPackages(); +var_dump($a, $installer->getErrorMsgs()); +echo "Packages downloaded and version:\n"; +foreach ($installpackages as $package) { + echo $package['pkg'] . '-' . $package['info']['version'] . "\n"; +} + + +chdir($curdir); +cleanall($temp_path); +// ------------------------------------------------------------------------- // + +function cleanall($dir) +{ + $dp = opendir($dir); + while ($ent = readdir($dp)) { + if ($ent == '.' || $ent == '..') { + continue; + } + if (is_dir($dir . DIRECTORY_SEPARATOR . $ent)) { + cleanall($dir . DIRECTORY_SEPARATOR . $ent); + } else { + unlink($dir . DIRECTORY_SEPARATOR . $ent); + } + } + closedir($dp); + rmdir($dir); +} +?> +--EXPECT-- +Test simple direct url download: +NULL +array(0) { +} +File exists? yes +File is the same? yes +array(1) { + [0]=> + array(2) { + ["pkg"]=> + string(4) "pkg6" + ["info"]=> + array(11) { + ["provides"]=> + array(0) { + } + ["filelist"]=> + array(3) { + ["zoorb.php"]=> + array(2) { + ["role"]=> + string(3) "php" + ["baseinstalldir"]=> + string(5) "groob" + } + ["goompness\oggbrzitzkee.php"]=> + array(2) { + ["role"]=> + string(3) "php" + ["baseinstalldir"]=> + string(5) "groob" + } + ["goompness\Mopreeb.php"]=> + array(2) { + ["role"]=> + string(3) "php" + ["baseinstalldir"]=> + string(5) "groob" + } + } + ["package"]=> + string(4) "pkg6" + ["summary"]=> + string(32) "required test for PEAR_Installer" + ["description"]=> + string(12) "fake package" + ["maintainers"]=> + array(1) { + [0]=> + array(4) { + ["handle"]=> + string(8) "fakeuser" + ["name"]=> + string(9) "Joe Shmoe" + ["email"]=> + string(18) "nobody@example.com" + ["role"]=> + string(4) "lead" + } + } + ["version"]=> + string(3) "1.1" + ["release_date"]=> + string(10) "2003-09-09" + ["release_license"]=> + string(11) "PHP License" + ["release_state"]=> + string(6) "stable" + ["release_notes"]=> + string(24) "required dependency test" + } + } +} +Test simple package name download: +NULL +array(0) { +} +File exists? yes +File is the same? yes +array(1) { + [0]=> + array(2) { + ["pkg"]=> + string(4) "pkg6" + ["info"]=> + array(11) { + ["provides"]=> + array(0) { + } + ["filelist"]=> + array(3) { + ["zoorb.php"]=> + array(2) { + ["role"]=> + string(3) "php" + ["baseinstalldir"]=> + string(5) "groob" + } + ["goompness\oggbrzitzkee.php"]=> + array(2) { + ["role"]=> + string(3) "php" + ["baseinstalldir"]=> + string(5) "groob" + } + ["goompness\Mopreeb.php"]=> + array(2) { + ["role"]=> + string(3) "php" + ["baseinstalldir"]=> + string(5) "groob" + } + } + ["package"]=> + string(4) "pkg6" + ["summary"]=> + string(32) "required test for PEAR_Installer" + ["description"]=> + string(12) "fake package" + ["maintainers"]=> + array(1) { + [0]=> + array(4) { + ["handle"]=> + string(8) "fakeuser" + ["name"]=> + string(9) "Joe Shmoe" + ["email"]=> + string(18) "nobody@example.com" + ["role"]=> + string(4) "lead" + } + } + ["version"]=> + string(3) "1.1" + ["release_date"]=> + string(10) "2003-09-09" + ["release_license"]=> + string(11) "PHP License" + ["release_state"]=> + string(6) "stable" + ["release_notes"]=> + string(24) "required dependency test" + } + } +} +Test package name with version download: +NULL +array(0) { +} +File exists? yes +File is the same? yes +Test package name with state stable download: +NULL +array(0) { +} +File exists? yes +File is the same? yes +Test package name with state beta download: +NULL +array(0) { +} +File exists? yes +File is the same? yes +================ +Test preferred_state = beta +Test simple package name download: +NULL +array(0) { +} +File exists? yes +File is the same? yes + +================Test --alldeps +Test preferred_state = stable +NULL +array(0) { +} +Packages downloaded and version: +pkg1-1.1 +pkg2-1.1 +pkg3-1.1 +pkg4-1.1 +pkg5-1.1 +pkg6-1.1 +NULL +array(0) { +} +Packages downloaded and version: +pkg1-1.1 +pkg2-1.1 +pkg3-1.1 +pkg4-1.1 +pkg5-1.1 +pkg6-1.1 +Test preferred_state = beta: +NULL +array(0) { +} +Packages downloaded and version: +pkg1-2.0b1 +pkg2-1.1 +pkg3-1.1 +pkg4-1.1 +pkg5-1.1 +pkg6-2.0b1 +Test preferred_state = alpha: +NULL +array(0) { +} +Packages downloaded and version: +pkg1-2.0b1 +pkg2-1.1 +pkg3-1.4 +pkg4AndAHalf-1.3 +pkg4-1.1 +pkg5-1.1 +pkg6-2.0b1 + +================Test --onlyreqdeps +Test preferred_state = stable +NULL +array(0) { +} +Packages downloaded and version: +pkg1-1.1 +pkg2-1.1 +pkg3-1.1 +pkg4-1.1 +pkg5-1.1 +pkg6-1.1 +NULL +array(0) { +} +Packages downloaded and version: +pkg1-1.1 +pkg2-1.1 +pkg3-1.1 +pkg4-1.1 +pkg5-1.1 +pkg6-1.1 +Test preferred_state = beta: +NULL +array(0) { +} +Packages downloaded and version: +pkg1-2.0b1 +pkg2-1.1 +pkg3-1.1 +pkg4-1.1 +pkg5-1.1 +pkg6-2.0b1 +Test preferred_state = alpha: +skipping Package 'pear::pkg3' optional dependency 'pear::pkg4AndAHalf' +NULL +array(0) { +} +Packages downloaded and version: +pkg1-2.0b1 +pkg2-1.1 +pkg3-1.4 +pkg4-1.1 +pkg5-1.1 +pkg6-2.0b1
\ No newline at end of file diff --git a/pear/tests/pear_downloader_old.phpt b/pear/tests/pear_downloader_old.phpt new file mode 100644 index 000000000..6e7225f44 --- /dev/null +++ b/pear/tests/pear_downloader_old.phpt @@ -0,0 +1,609 @@ +--TEST-- +PEAR_Installer test: PEAR_Installer::download() (deprecated) +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php +if (!defined('PATH_SEPARATOR')) { + define('PATH_SEPARATOR', (DIRECTORY_SEPARATOR == '/') ? ':' : ';'); +} +ini_set('include_path', dirname(__FILE__) . PATH_SEPARATOR . ini_get('include_path')); +$server = 'pear.Chiara'; +//$server = 'test.pear.php.net'; +$temp_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'testinstallertemp'; +if (!is_dir($temp_path)) { + mkdir($temp_path); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'php')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'php'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'data')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'data'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'doc')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'doc'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'test')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'test'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'ext')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'ext'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'script')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'script'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'tmp')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'tmp'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'bin')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'bin'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'cache')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'cache'); +} +// make the fake configuration - we'll use one of these and it should work +$config = serialize(array('master_server' => $server, + 'preferred_state' => 'stable', + 'cache_dir' => $temp_path . DIRECTORY_SEPARATOR . 'cache', + 'php_dir' => $temp_path . DIRECTORY_SEPARATOR . 'php', + 'ext_dir' => $temp_path . DIRECTORY_SEPARATOR . 'ext', + 'data_dir' => $temp_path . DIRECTORY_SEPARATOR . 'data', + 'doc_dir' => $temp_path . DIRECTORY_SEPARATOR . 'doc', + 'test_dir' => $temp_path . DIRECTORY_SEPARATOR . 'test', + 'bin_dir' => $temp_path . DIRECTORY_SEPARATOR . 'bin',)); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.conf'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.conf', 'w'); +fwrite($fp, $config); +fclose($fp); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.ini'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.ini', 'w'); +fwrite($fp, $config); +fclose($fp); + +putenv('PHP_PEAR_SYSCONF_DIR='.$temp_path); +$home = getenv('HOME'); +if (!empty($home)) { + // for PEAR_Config initialization + putenv('HOME="'.$temp_path); +} +require_once "PEAR/Installer.php"; +require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'download_test_classes.php.inc'; +//echo 1; +// no UI is needed for these tests +$ui = false; +$installer = new test_PEAR_Installer($ui); +$curdir = getcwd(); +chdir(dirname(__FILE__)); + +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'catchit'); +set_error_handler('catchphp'); + +function catchphp($errno, $errmsg) +{ + if (error_reporting() == 0) { + return; + } + $errlevel = array( + E_USER_NOTICE => 'Notice', + E_USER_WARNING => 'Warning', + E_USER_ERROR => 'Error', + E_WARNING => 'Warning', + E_NOTICE => 'Notice' + ); + echo $errlevel[$errno] . ': ' . $errmsg . "\n"; +} +$error_to_catch = false; +function catchit($err) +{ + global $error_to_catch; + if ($error_to_catch) { + if ($err->getMessage() == $error_to_catch) { + $error_to_catch = false; + echo "Caught expected error\n"; + return; + } + } + echo "Caught error: " . $err->getMessage() . "\n"; +} + +echo "Test simple direct url download:\n"; + +$config = &PEAR_Config::singleton(); +// initialize fake pear channel +require_once 'PEAR/ChannelFile.php'; +$chan = new PEAR_ChannelFile; +$chan->setName('pear'); +$chan->setSummary('PEAR'); +$chan->setServer($server); +$chan->setDefaultPEARProtocols(); +$reg = new PEAR_Registry($config->get('php_dir'), $chan); +$packages = array("http://$server/get/pkg6-1.1.tgz"); +$a = $installer->download($packages, array(), &$config, &$installpackages, &$errors); +var_dump($a, $errors); + +echo "File exists? "; +echo (is_file($installpackages[0]['file'])) ? "yes\n" : "no\n"; +echo "File is the same? "; +$good = implode('', file(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-1.1.tgz')); +$dled = implode('', file($installpackages[0]['file'])); +echo ($good == $dled) ? "yes\n" : "no\n"; +unlink($installpackages[0]['file']); +unset($installpackages[0]['file']); +var_dump($installpackages); + +echo "Test simple package name download:\n"; +$installpackages = $errors = array(); +$packages = array('pkg6'); +$a = $installer->download($packages, array(), &$config, &$installpackages, &$errors); +var_dump($a, $errors); + +echo "File exists? "; +echo (is_file($installpackages[0]['file'])) ? "yes\n" : "no\n"; +echo "File is the same? "; +$good = implode('', file(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-1.1.tgz')); +$dled = implode('', file($installpackages[0]['file'])); +echo ($good == $dled) ? "yes\n" : "no\n"; +unlink($installpackages[0]['file']); +unset($installpackages[0]['file']); +var_dump($installpackages); + +echo "Test package name with version download:\n"; +$installpackages = $errors = array(); +$packages = array('pkg6-1.1'); +$a = $installer->download($packages, array(), &$config, &$installpackages, &$errors); +var_dump($a, $errors); + +echo "File exists? "; +echo (is_file($installpackages[0]['file'])) ? "yes\n" : "no\n"; +echo "File is the same? "; +$good = implode('', file(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-1.1.tgz')); +$dled = implode('', file($installpackages[0]['file'])); +echo ($good == $dled) ? "yes\n" : "no\n"; +unlink($installpackages[0]['file']); + +echo "Test package name with state stable download:\n"; +$installpackages = $errors = array(); +$packages = array('pkg6-stable'); +$a = $installer->download($packages, array(), &$config, &$installpackages, &$errors); +var_dump($a, $errors); + +echo "File exists? "; +echo (is_file($installpackages[0]['file'])) ? "yes\n" : "no\n"; +echo "File is the same? "; +$good = implode('', file(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-1.1.tgz')); +$dled = implode('', file($installpackages[0]['file'])); +echo ($good == $dled) ? "yes\n" : "no\n"; +unlink($installpackages[0]['file']); + +echo "Test package name with state beta download:\n"; +$installpackages = $errors = array(); +$packages = array('pkg6-beta'); +$a = $installer->download($packages, array(), &$config, &$installpackages, &$errors); +var_dump($a, $errors); + +echo "File exists? "; +echo (is_file($installpackages[0]['file'])) ? "yes\n" : "no\n"; +echo "File is the same? "; +$good = implode('', file(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-2.0b1.tgz')); +$dled = implode('', file($installpackages[0]['file'])); +echo ($good == $dled) ? "yes\n" : "no\n"; +unlink($installpackages[0]['file']); + +echo "================\nTest preferred_state = beta\n"; +$config->set('preferred_state', 'beta'); + +echo "Test simple package name download:\n"; +$installpackages = $errors = array(); +$packages = array('pkg6'); +$a = $installer->download($packages, array(), &$config, &$installpackages, &$errors); +var_dump($a, $errors); + +echo "File exists? "; +echo (is_file($installpackages[0]['file'])) ? "yes\n" : "no\n"; +echo "File is the same? "; +$good = implode('', file(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-2.0b1.tgz')); +$dled = implode('', file($installpackages[0]['file'])); +echo ($good == $dled) ? "yes\n" : "no\n"; +unlink($installpackages[0]['file']); +unset($installpackages[0]['file']); + +echo "\n================Test --alldeps\nTest preferred_state = stable\n"; +$config->set('preferred_state', 'stable'); + +$config = &PEAR_Config::singleton(); +$packages = array("http://$server/get/pkg1-1.1.tgz"); +$a = $installer->download($packages, array('alldeps' => true), &$config, &$installpackages, &$errors); +var_dump($a, $errors); +echo "Packages downloaded and version:\n"; +foreach ($installpackages as $package) { + echo $package['pkg'] . '-' . $package['info']['version'] . "\n"; +} +$packages = array("pkg1"); +$a = $installer->download($packages, array('alldeps' => true), &$config, &$installpackages, &$errors); +var_dump($a, $errors); +echo "Packages downloaded and version:\n"; +foreach ($installpackages as $package) { + echo $package['pkg'] . '-' . $package['info']['version'] . "\n"; +} + +echo "Test preferred_state = beta:\n"; +$config->set('preferred_state', 'beta'); + +$config = &PEAR_Config::singleton(); +$packages = array("pkg1"); +$a = $installer->download($packages, array('alldeps' => true), &$config, &$installpackages, &$errors); +var_dump($a, $errors); +echo "Packages downloaded and version:\n"; +foreach ($installpackages as $package) { + echo $package['pkg'] . '-' . $package['info']['version'] . "\n"; +} + +echo "Test preferred_state = alpha:\n"; +$config->set('preferred_state', 'alpha'); + +$config = &PEAR_Config::singleton(); +$packages = array("pkg1"); +$a = $installer->download($packages, array('alldeps' => true), &$config, &$installpackages, &$errors); +var_dump($a, $errors); +echo "Packages downloaded and version:\n"; +foreach ($installpackages as $package) { + echo $package['pkg'] . '-' . $package['info']['version'] . "\n"; +} +echo "\n================Test --onlyreqdeps\nTest preferred_state = stable\n"; +$config->set('preferred_state', 'stable'); + +$config = &PEAR_Config::singleton(); +$packages = array("http://$server/get/pkg1-1.1.tgz"); +$a = $installer->download($packages, array('onlyreqdeps' => true), &$config, &$installpackages, &$errors); +var_dump($a, $errors); +echo "Packages downloaded and version:\n"; +foreach ($installpackages as $package) { + echo $package['pkg'] . '-' . $package['info']['version'] . "\n"; +} +$packages = array("pkg1"); +$a = $installer->download($packages, array('onlyreqdeps' => true), &$config, &$installpackages, &$errors); +var_dump($a, $errors); +echo "Packages downloaded and version:\n"; +foreach ($installpackages as $package) { + echo $package['pkg'] . '-' . $package['info']['version'] . "\n"; +} + +echo "Test preferred_state = beta:\n"; +$config->set('preferred_state', 'beta'); + +$config = &PEAR_Config::singleton(); +$packages = array("pkg1"); +$a = $installer->download($packages, array('onlyreqdeps' => true), &$config, &$installpackages, &$errors); +var_dump($a, $errors); +echo "Packages downloaded and version:\n"; +foreach ($installpackages as $package) { + echo $package['pkg'] . '-' . $package['info']['version'] . "\n"; +} + +echo "Test preferred_state = alpha:\n"; +$config->set('preferred_state', 'alpha'); + +$config = &PEAR_Config::singleton(); +$packages = array("pkg1"); +$a = $installer->download($packages, array('onlyreqdeps' => true), &$config, &$installpackages, &$errors); +var_dump($a, $errors); +echo "Packages downloaded and version:\n"; +foreach ($installpackages as $package) { + echo $package['pkg'] . '-' . $package['info']['version'] . "\n"; +} + + +chdir($curdir); +cleanall($temp_path); + +/* +echo "File exists? "; +echo (is_file($installpackages[0]['file'])) ? "yes\n" : "no\n"; +echo "File is the same? "; +$good = implode('', file(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-1.1.tgz')); +$dled = implode('', file($installpackages[0]['file'])); +echo ($good == $dled) ? "yes\n" : "no\n"; +unlink($installpackages[0]['file']); +unset($installpackages[0]['file']);*/ +// ------------------------------------------------------------------------- // + +function cleanall($dir) +{ + $dp = opendir($dir); + while ($ent = readdir($dp)) { + if ($ent == '.' || $ent == '..') { + continue; + } + if (is_dir($dir . DIRECTORY_SEPARATOR . $ent)) { + cleanall($dir . DIRECTORY_SEPARATOR . $ent); + } else { + unlink($dir . DIRECTORY_SEPARATOR . $ent); + } + } + closedir($dp); + rmdir($dir); +} +?> +--EXPECT-- +Test simple direct url download: +Warning: PEAR Warning: PEAR_Installer::download() is deprecated in favor of PEAR_Downloader class +NULL +array(0) { +} +File exists? yes +File is the same? yes +array(1) { + [0]=> + array(2) { + ["pkg"]=> + string(4) "pkg6" + ["info"]=> + array(11) { + ["provides"]=> + array(0) { + } + ["filelist"]=> + array(3) { + ["zoorb.php"]=> + array(2) { + ["role"]=> + string(3) "php" + ["baseinstalldir"]=> + string(5) "groob" + } + ["goompness\oggbrzitzkee.php"]=> + array(2) { + ["role"]=> + string(3) "php" + ["baseinstalldir"]=> + string(5) "groob" + } + ["goompness\Mopreeb.php"]=> + array(2) { + ["role"]=> + string(3) "php" + ["baseinstalldir"]=> + string(5) "groob" + } + } + ["package"]=> + string(4) "pkg6" + ["summary"]=> + string(32) "required test for PEAR_Installer" + ["description"]=> + string(12) "fake package" + ["maintainers"]=> + array(1) { + [0]=> + array(4) { + ["handle"]=> + string(8) "fakeuser" + ["name"]=> + string(9) "Joe Shmoe" + ["email"]=> + string(18) "nobody@example.com" + ["role"]=> + string(4) "lead" + } + } + ["version"]=> + string(3) "1.1" + ["release_date"]=> + string(10) "2003-09-09" + ["release_license"]=> + string(11) "PHP License" + ["release_state"]=> + string(6) "stable" + ["release_notes"]=> + string(24) "required dependency test" + } + } +} +Test simple package name download: +Warning: PEAR Warning: PEAR_Installer::download() is deprecated in favor of PEAR_Downloader class +NULL +array(0) { +} +File exists? yes +File is the same? yes +array(1) { + [0]=> + array(2) { + ["pkg"]=> + string(4) "pkg6" + ["info"]=> + array(11) { + ["provides"]=> + array(0) { + } + ["filelist"]=> + array(3) { + ["zoorb.php"]=> + array(2) { + ["role"]=> + string(3) "php" + ["baseinstalldir"]=> + string(5) "groob" + } + ["goompness\oggbrzitzkee.php"]=> + array(2) { + ["role"]=> + string(3) "php" + ["baseinstalldir"]=> + string(5) "groob" + } + ["goompness\Mopreeb.php"]=> + array(2) { + ["role"]=> + string(3) "php" + ["baseinstalldir"]=> + string(5) "groob" + } + } + ["package"]=> + string(4) "pkg6" + ["summary"]=> + string(32) "required test for PEAR_Installer" + ["description"]=> + string(12) "fake package" + ["maintainers"]=> + array(1) { + [0]=> + array(4) { + ["handle"]=> + string(8) "fakeuser" + ["name"]=> + string(9) "Joe Shmoe" + ["email"]=> + string(18) "nobody@example.com" + ["role"]=> + string(4) "lead" + } + } + ["version"]=> + string(3) "1.1" + ["release_date"]=> + string(10) "2003-09-09" + ["release_license"]=> + string(11) "PHP License" + ["release_state"]=> + string(6) "stable" + ["release_notes"]=> + string(24) "required dependency test" + } + } +} +Test package name with version download: +Warning: PEAR Warning: PEAR_Installer::download() is deprecated in favor of PEAR_Downloader class +NULL +array(0) { +} +File exists? yes +File is the same? yes +Test package name with state stable download: +Warning: PEAR Warning: PEAR_Installer::download() is deprecated in favor of PEAR_Downloader class +NULL +array(0) { +} +File exists? yes +File is the same? yes +Test package name with state beta download: +Warning: PEAR Warning: PEAR_Installer::download() is deprecated in favor of PEAR_Downloader class +NULL +array(0) { +} +File exists? yes +File is the same? yes +================ +Test preferred_state = beta +Test simple package name download: +Warning: PEAR Warning: PEAR_Installer::download() is deprecated in favor of PEAR_Downloader class +NULL +array(0) { +} +File exists? yes +File is the same? yes + +================Test --alldeps +Test preferred_state = stable +Warning: PEAR Warning: PEAR_Installer::download() is deprecated in favor of PEAR_Downloader class +NULL +array(0) { +} +Packages downloaded and version: +pkg1-1.1 +pkg2-1.1 +pkg3-1.1 +pkg4-1.1 +pkg5-1.1 +pkg6-1.1 +Warning: PEAR Warning: PEAR_Installer::download() is deprecated in favor of PEAR_Downloader class +NULL +array(0) { +} +Packages downloaded and version: +pkg1-1.1 +pkg2-1.1 +pkg3-1.1 +pkg4-1.1 +pkg5-1.1 +pkg6-1.1 +Test preferred_state = beta: +Warning: PEAR Warning: PEAR_Installer::download() is deprecated in favor of PEAR_Downloader class +NULL +array(0) { +} +Packages downloaded and version: +pkg1-2.0b1 +pkg2-1.1 +pkg3-1.1 +pkg4-1.1 +pkg5-1.1 +pkg6-2.0b1 +Test preferred_state = alpha: +Warning: PEAR Warning: PEAR_Installer::download() is deprecated in favor of PEAR_Downloader class +NULL +array(0) { +} +Packages downloaded and version: +pkg1-2.0b1 +pkg2-1.1 +pkg3-1.4 +pkg4AndAHalf-1.3 +pkg4-1.1 +pkg5-1.1 +pkg6-2.0b1 + +================Test --onlyreqdeps +Test preferred_state = stable +Warning: PEAR Warning: PEAR_Installer::download() is deprecated in favor of PEAR_Downloader class +NULL +array(0) { +} +Packages downloaded and version: +pkg1-1.1 +pkg2-1.1 +pkg3-1.1 +pkg4-1.1 +pkg5-1.1 +pkg6-1.1 +Warning: PEAR Warning: PEAR_Installer::download() is deprecated in favor of PEAR_Downloader class +NULL +array(0) { +} +Packages downloaded and version: +pkg1-1.1 +pkg2-1.1 +pkg3-1.1 +pkg4-1.1 +pkg5-1.1 +pkg6-1.1 +Test preferred_state = beta: +Warning: PEAR Warning: PEAR_Installer::download() is deprecated in favor of PEAR_Downloader class +NULL +array(0) { +} +Packages downloaded and version: +pkg1-2.0b1 +pkg2-1.1 +pkg3-1.1 +pkg4-1.1 +pkg5-1.1 +pkg6-2.0b1 +Test preferred_state = alpha: +skipping Package 'pear::pkg3' optional dependency 'pear::pkg4AndAHalf' +Warning: PEAR Warning: PEAR_Installer::download() is deprecated in favor of PEAR_Downloader class +NULL +array(0) { +} +Packages downloaded and version: +pkg1-2.0b1 +pkg2-1.1 +pkg3-1.4 +pkg4-1.1 +pkg5-1.1 +pkg6-2.0b1
\ No newline at end of file diff --git a/pear/tests/pear_error.phpt b/pear/tests/pear_error.phpt new file mode 100644 index 000000000..2a77cf497 --- /dev/null +++ b/pear/tests/pear_error.phpt @@ -0,0 +1,156 @@ +--TEST-- +PEAR_Error: basic test +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php // -*- PHP -*- + +// Test for: PEAR.php +// Parts tested: - PEAR_Error class +// - PEAR::isError static method + +include_once "PEAR.php"; + +function test_error_handler($errno, $errmsg, $file, $line, $vars) { + $errortype = array ( + 1 => "Error", + 2 => "Warning", + 4 => "Parsing Error", + 8 => "Notice", + 16 => "Core Error", + 32 => "Core Warning", + 64 => "Compile Error", + 128 => "Compile Warning", + 256 => "User Error", + 512 => "User Warning", + 1024=> "User Notice" + ); + if (preg_match('/^The call_user_method.. function is deprecated/', + $errmsg)) { + return; + } + $prefix = $errortype[$errno]; + $file = basename($file); + print "\n$prefix: $errmsg in $file on line XXX\n"; +} + +error_reporting(E_ALL); +set_error_handler("test_error_handler"); + +class Foo_Error extends PEAR_Error +{ + function Foo_Error($message = "unknown error", $code = null, + $mode = null, $options = null, $userinfo = null) + { + $this->PEAR_Error($message, $code, $mode, $options, $userinfo); + $this->error_message_prefix = 'Foo_Error prefix'; + } +} + +class Test1 extends PEAR { + function Test1() { + $this->PEAR("Foo_Error"); + } + function runtest() { + return $this->raiseError("test error"); + } +} + +function errorhandler(&$obj) { + print "errorhandler function called, obj=".$obj->toString()."\n"; +} + +class errorclass { + function errorhandler(&$obj) { + print "errorhandler method called, obj=".$obj->toString()."\n"; + } +} + +print "specify error class: "; +$obj = new Test1; +$err = $obj->runtest(); +print $err->toString() . "\n"; + +$eo = new errorclass; + +print "default PEAR_Error: "; +$err = new PEAR_Error; +print $err->toString() . "\n"; +print "Testing it: "; +var_dump(PEAR::isError($err)); +print "This is not an error: "; +$str = "not an error"; +var_dump(PEAR::isError($str)); + +print "Now trying a bunch of variations...\n"; + +print "different message: "; +$err = new PEAR_Error("test error"); +print $err->toString() . "\n"; + +print "different message,code: "; +$err = new PEAR_Error("test error", -42); +print $err->toString() . "\n"; + +print "mode=print: "; +$err = new PEAR_Error("test error", -42, PEAR_ERROR_PRINT); +print $err->toString() . "\n"; + +print "mode=callback(function): "; +$err = new PEAR_Error("test error", -42, PEAR_ERROR_CALLBACK, "errorhandler"); + +print "mode=callback(method): "; +$err = new PEAR_Error("test error", -42, PEAR_ERROR_CALLBACK, + array(&$eo, "errorhandler")); + +print "mode=print&trigger: "; +$err = new PEAR_Error("test error", -42, PEAR_ERROR_PRINT|PEAR_ERROR_TRIGGER); +print $err->toString() . "\n"; + +print "mode=trigger:"; +$err = new PEAR_Error("test error", -42, PEAR_ERROR_TRIGGER); +print $err->toString() . "\n"; + +print "mode=trigger,level=notice:"; +$err = new PEAR_Error("test error", -42, PEAR_ERROR_TRIGGER, E_USER_NOTICE); +print $err->toString() . "\n"; + +print "mode=trigger,level=warning:"; +$err = new PEAR_Error("test error", -42, PEAR_ERROR_TRIGGER, E_USER_WARNING); +print $err->toString() . "\n"; + +print "mode=trigger,level=error:"; +$err = new PEAR_Error("test error", -42, PEAR_ERROR_TRIGGER, E_USER_ERROR); +print $err->toString() . "\n"; + +?> +--EXPECT-- +specify error class: [foo_error: message="test error" code=0 mode=return level=notice prefix="Foo_Error prefix" info=""] +default PEAR_Error: [pear_error: message="unknown error" code=0 mode=return level=notice prefix="" info=""] +Testing it: bool(true) +This is not an error: bool(false) +Now trying a bunch of variations... +different message: [pear_error: message="test error" code=0 mode=return level=notice prefix="" info=""] +different message,code: [pear_error: message="test error" code=-42 mode=return level=notice prefix="" info=""] +mode=print: test error[pear_error: message="test error" code=-42 mode=print level=notice prefix="" info=""] +mode=callback(function): errorhandler function called, obj=[pear_error: message="test error" code=-42 mode=callback callback=errorhandler prefix="" info=""] +mode=callback(method): errorhandler method called, obj=[pear_error: message="test error" code=-42 mode=callback callback=errorclass::errorhandler prefix="" info=""] +mode=print&trigger: test error +User Notice: test error in PEAR.php on line XXX +[pear_error: message="test error" code=-42 mode=print|trigger level=notice prefix="" info=""] +mode=trigger: +User Notice: test error in PEAR.php on line XXX +[pear_error: message="test error" code=-42 mode=trigger level=notice prefix="" info=""] +mode=trigger,level=notice: +User Notice: test error in PEAR.php on line XXX +[pear_error: message="test error" code=-42 mode=trigger level=notice prefix="" info=""] +mode=trigger,level=warning: +User Warning: test error in PEAR.php on line XXX +[pear_error: message="test error" code=-42 mode=trigger level=warning prefix="" info=""] +mode=trigger,level=error: +User Error: test error in PEAR.php on line XXX +[pear_error: message="test error" code=-42 mode=trigger level=error prefix="" info=""] diff --git a/pear/tests/pear_error2.phpt b/pear/tests/pear_error2.phpt new file mode 100644 index 000000000..9dbfa3b22 --- /dev/null +++ b/pear/tests/pear_error2.phpt @@ -0,0 +1,27 @@ +--TEST-- +PEAR_Error: die mode +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php // -*- C++ -*- + +// Test for: PEAR.php +// Parts tested: - PEAR_Error class +// - PEAR::isError static method +// testing PEAR_Error + +include_once "PEAR.php"; + +error_reporting(E_ALL); + +print "mode=die: "; +$err = new PEAR_Error("test error!!\n", -42, PEAR_ERROR_DIE); +print $err->toString() . "\n"; + +?> +--EXPECT-- +mode=die: test error!! diff --git a/pear/tests/pear_error3.phpt b/pear/tests/pear_error3.phpt new file mode 100644 index 000000000..2e5ce8d2a --- /dev/null +++ b/pear/tests/pear_error3.phpt @@ -0,0 +1,58 @@ +--TEST-- +PEAR_Error: default error handling +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php // -*- PHP -*- + +// Test for: PEAR.php +// Parts tested: - PEAR_Error class +// - PEAR::setErrorHandling +// - PEAR::raiseError method + +include_once "PEAR.php"; + +error_reporting(E_ALL); + +function errorhandler($eobj) +{ + if (PEAR::isError($eobj)) { + print "errorhandler called with an error object.\n"; + print "error message: ".$eobj->getMessage()."\n"; + } else { + print "errorhandler called, but without an error object.\n"; + } +} + +// Test 1 +PEAR::setErrorHandling(PEAR_ERROR_PRINT, "OOPS: %s\n"); +$tmp = new PEAR; +$tmp->raiseError("error happens"); + +// Return PEAR to its original state +$GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN; +$GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE; +$GLOBALS['_PEAR_default_error_callback'] = ''; + +// Test 2 +$obj = new PEAR; +$obj->setErrorHandling(PEAR_ERROR_PRINT); +$obj->raiseError("error 1\n"); +$obj->setErrorHandling(null); +$obj->raiseError("error 2\n"); +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, "errorhandler"); +$obj->raiseError("error 3"); +$obj->setErrorHandling(PEAR_ERROR_PRINT); +$obj->raiseError("error 4\n"); + +?> +--EXPECT-- +OOPS: error happens +error 1 +errorhandler called with an error object. +error message: error 3 +error 4
\ No newline at end of file diff --git a/pear/tests/pear_error4.phpt b/pear/tests/pear_error4.phpt new file mode 100644 index 000000000..0d6754c88 --- /dev/null +++ b/pear/tests/pear_error4.phpt @@ -0,0 +1,108 @@ +--TEST-- +PEAR_Error: expected errors +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php // -*- PHP -*- + +// Test for: PEAR.php +// Parts tested: - PEAR_Error class +// - PEAR::expectError +// - PEAR::popExpect + +include_once "PEAR.php"; + +error_reporting(E_ALL); + +function errorhandler($eobj) +{ + if (PEAR::isError($eobj)) { + print "error: ".$eobj->getMessage()."\n"; + } else { + print "errorhandler called without error object\n"; + } +} + +$obj = new PEAR; +$obj->setErrorHandling(PEAR_ERROR_CALLBACK, "errorhandler"); + +print "subtest 1\n"; +$obj->expectError(1); +$obj->raiseError("1", 1); +$obj->popExpect(); +$obj->raiseError("2", 2); + +print "subtest 2\n"; +$obj->expectError(3); +$obj->expectError(2); +$obj->raiseError("3", 3); + +print "subtest 3\n"; +$obj->popExpect(); +$obj->raiseError("3", 3); +$obj->popExpect(); + +print "subtest 4\n"; +$obj->expectError(array(1,2,3,4,5)); +$obj->raiseError("0", 0); +$obj->raiseError("1", 1); +$obj->raiseError("2", 2); +$obj->raiseError("3", 3); +$obj->raiseError("4", 4); +$obj->raiseError("5", 5); +$obj->raiseError("6", 6); +$obj->raiseError("error"); +$obj->popExpect(); + +print "subtest 5\n"; +$obj->expectError("*"); +$obj->raiseError("42", 42); +$obj->raiseError("75", 75); +$obj->raiseError("13", 13); +$obj->popExpect(); + +print "subtest 6\n"; +$obj->expectError(); +$obj->raiseError("123", 123); +$obj->raiseError("456", 456); +$obj->raiseError("789", 789); +$obj->popExpect(); + +print "subtest 7\n"; +$obj->expectError("syntax error"); +$obj->raiseError("type mismatch"); +$obj->raiseError("syntax error"); +$obj->popExpect(); + +print "subtest 8\n"; +$obj->expectError(array(1, 2, 3)); +$obj->expectError(array(3, 4, 5)); +$obj->raiseError(4); +$obj->delExpect(2); +$obj->raiseError(3); +$obj->delExpect(1, 3, 4, 5); +$err = $obj->delExpect(2); + +?> +--EXPECT-- +subtest 1 +error: 2 +subtest 2 +error: 3 +subtest 3 +subtest 4 +error: 0 +error: 6 +error: error +subtest 5 +subtest 6 +subtest 7 +error: type mismatch +subtest 8 +error: 4 +error: 3 +error: The expected error you submitted does not exist diff --git a/pear/tests/pear_installer1.phpt b/pear/tests/pear_installer1.phpt new file mode 100644 index 000000000..9daf2ecf0 --- /dev/null +++ b/pear/tests/pear_installer1.phpt @@ -0,0 +1,213 @@ +--TEST-- +PEAR_Installer test extractDownloadFileName, checkDeps +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php + +require_once "PEAR/Installer.php"; +require_once 'PEAR/ChannelFile.php'; + +$temp_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'testinstallertemp'; +if (!is_dir($temp_path)) { + mkdir($temp_path); +} +touch($temp_path . DIRECTORY_SEPARATOR . 'user.conf'); +// no UI is needed for these tests +$ui = false; +$config = new PEAR_Config($temp_path . DIRECTORY_SEPARATOR . 'user.conf'); +$config->set('php_dir', dirname(__FILE__) . DIRECTORY_SEPARATOR . 'testinstallertemp'); +$reg = &new PEAR_Registry($config->get('php_dir')); +$chan = new PEAR_ChannelFile; +$chan->setName('oddball'); +$chan->setServer('example.com'); +$chan->setSummary('oddball'); +$chan->setPackageNameRegex('[a-z][a-z0-9]*(?:\.[a-z0-9]+)*'); +$reg->addChannel($chan); +$installer = new PEAR_Installer($ui); +$installer->config = &$config; +echo "test extractDownloadFileName:\n"; +echo 'existing file: '; +echo ($temp_path . DIRECTORY_SEPARATOR . 'user.conf' == + $installer->extractDownloadFileName($temp_path . DIRECTORY_SEPARATOR . 'user.conf', + $ui)) ? "yes\n" : "no\n"; +var_dump($ui); +echo 'invalid match: '; +echo $installer->extractDownloadFileName('27', + $ui); +echo "\n"; +var_dump($ui); +echo 'valid match, no version: '; +echo $installer->extractDownloadFileName('Testpackage', $ui); +echo "\n"; +var_dump($ui); +echo 'invalid match, has invalid version: '; +echo $installer->extractDownloadFileName('Testpackage-##', $ui); +echo "\n"; +var_dump($ui); +echo 'valid match, has version: '; +echo $installer->extractDownloadFileName('Testpackage-1.2', $ui); +echo "\n"; +var_dump($ui); +echo "valid match, has unknown channel:\n"; +var_dump($installer->extractDownloadFileName('Unknown::Testpackage', $ui)); +var_dump($ui); +echo "invalid match, has known channel, invalid package name:\n"; +var_dump($installer->extractDownloadFileName('Oddball::Testpackage', $ui)); +var_dump($ui); +echo "valid match, has known channel, valid package name:\n"; +var_dump($installer->extractDownloadFileName('Oddball::testpackage.third3', $ui)); +var_dump($ui); +echo "valid match, has known channel, valid package name, version:\n"; +var_dump($installer->extractDownloadFileName('Oddball::testpackage.third3-54.7354', $ui)); +var_dump($ui); + +echo "\ntest checkDeps 1:\n"; +$fakerel = array('release_deps' => +array( + array( + 'type' => 'pkg', + 'rel '=> 'has', + 'name' => 'foo', + 'optional' => 'yes' + ), + array( + 'type' => 'pkg', + 'rel '=> 'ge', + 'version' => '1.6', + 'name' => 'bar', + ), +)); +$res = ''; +var_dump($installer->checkDeps($fakerel, $res)); +var_dump($res); + +echo "\ntest checkDeps 1.1:\n"; +$fakerel = array('release_deps' => +array( + array( + 'type' => 'pkg', + 'rel '=> 'has', + 'name' => 'foo', + 'optional' => 'yes', + 'channel' => 'grob', + ), + array( + 'type' => 'pkg', + 'rel '=> 'ge', + 'version' => '1.6', + 'name' => 'bar', + 'channel' => 'prego', + ), +)); +$res = ''; +var_dump($installer->checkDeps($fakerel, $res)); +var_dump($res); +$fakerel = array('release_deps' => +array( + array( + 'type' => 'pkg', + 'rel '=> 'has', + 'name' => 'foo', + 'optional' => 'yes' + ), +)); +echo "\ntest checkDeps 2:\n"; +$res = ''; +var_dump($installer->checkDeps($fakerel, $res)); +var_dump($res); +$fakerel = array('release_deps' => +array( + array( + 'type' => 'pkg', + 'rel '=> 'has', + 'name' => 'foo', + 'optional' => 'yes', + 'channel' => 'purple', + ), +)); +echo "\ntest checkDeps 2.1:\n"; +$res = ''; +var_dump($installer->checkDeps($fakerel, $res)); +var_dump($res); +cleanall($temp_path); +function cleanall($dir) +{ + $dp = opendir($dir); + while ($ent = readdir($dp)) { + if ($ent == '.' || $ent == '..') { + continue; + } + if (is_dir($dir . DIRECTORY_SEPARATOR . $ent)) { + cleanall($dir . DIRECTORY_SEPARATOR . $ent); + } else { + unlink($dir . DIRECTORY_SEPARATOR . $ent); + } + } + closedir($dp); + rmdir($dir); +} +?> +--EXPECT-- +test extractDownloadFileName: +existing file: yes +bool(false) +invalid match: 27 +NULL +valid match, no version: Testpackage +NULL +invalid match, has invalid version: Testpackage-## +NULL +valid match, has version: Testpackage +string(3) "1.2" +valid match, has unknown channel: +array(2) { + ["channel"]=> + string(7) "Unknown" + ["package"]=> + string(11) "Testpackage" +} +NULL +invalid match, has known channel, invalid package name: +string(20) "Oddball::Testpackage" +NULL +valid match, has known channel, valid package name: +array(2) { + ["channel"]=> + string(7) "Oddball" + ["package"]=> + string(18) "testpackage.third3" +} +NULL +valid match, has known channel, valid package name, version: +array(2) { + ["channel"]=> + string(7) "Oddball" + ["package"]=> + string(18) "testpackage.third3" +} +string(7) "54.7354" + +test checkDeps 1: +bool(true) +string(29) " +requires package `pear::bar'" + +test checkDeps 1.1: +bool(true) +string(30) " +requires package `prego::bar'" + +test checkDeps 2: +bool(false) +string(83) "Optional dependencies: +package `pear::foo' is recommended to utilize some features." + +test checkDeps 2.1: +bool(false) +string(85) "Optional dependencies: +package `purple::foo' is recommended to utilize some features."
\ No newline at end of file diff --git a/pear/tests/pear_installer2.phpt b/pear/tests/pear_installer2.phpt new file mode 100644 index 000000000..541ad71b7 --- /dev/null +++ b/pear/tests/pear_installer2.phpt @@ -0,0 +1,398 @@ +--TEST-- +PEAR_Installer test _installFile() +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php +$temp_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'testinstallertemp'; +if (!is_dir($temp_path)) { + mkdir($temp_path); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'php')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'php'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'data')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'data'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'doc')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'doc'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'test')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'test'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'ext')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'ext'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'script')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'script'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'tmp')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'tmp'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'bin')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'bin'); +} +// make the fake configuration - we'll use one of these and it should work +$config = serialize(array('master_server' => 'pear.php.net', + 'php_dir' => $temp_path . DIRECTORY_SEPARATOR . 'php', + 'ext_dir' => $temp_path . DIRECTORY_SEPARATOR . 'ext', + 'data_dir' => $temp_path . DIRECTORY_SEPARATOR . 'data', + 'doc_dir' => $temp_path . DIRECTORY_SEPARATOR . 'doc', + 'test_dir' => $temp_path . DIRECTORY_SEPARATOR . 'test', + 'bin_dir' => $temp_path . DIRECTORY_SEPARATOR . 'bin',)); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.conf'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.conf', 'w'); +fwrite($fp, $config); +fclose($fp); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.ini'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.ini', 'w'); +fwrite($fp, $config); +fclose($fp); + +putenv('PHP_PEAR_SYSCONF_DIR='.$temp_path); +$home = getenv('HOME'); +if (!empty($home)) { + // for PEAR_Config initialization + putenv('HOME="'.$temp_path); +} +require_once "PEAR/Installer.php"; + +// no UI is needed for these tests +$ui = false; +$installer = new PEAR_Installer($ui); +$curdir = getcwd(); +chdir(dirname(__FILE__)); + +echo "test _installFile():\n"; +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'installer2.phpt.testfile.php', 'w'); +fwrite($fp, 'a'); +fclose($fp); +// pretend we just parsed a package.xml +$installer->pkginfo = array('package' => 'Foo'); + +echo "install as role=\"php\":\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'php'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo 'file ext/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +echo "install as role=\"ext\":\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'ext'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo 'file php/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'ext' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +echo "install as role=\"data\":\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'data'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo 'file data/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . + 'Foo' . DIRECTORY_SEPARATOR . '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +echo "install as role=\"doc\":\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'doc'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo 'file doc/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'doc' . DIRECTORY_SEPARATOR . + 'Foo' . DIRECTORY_SEPARATOR . '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +echo "install as role=\"test\":\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'test'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo 'file test/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . + 'Foo' . DIRECTORY_SEPARATOR . '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +echo "install as role=\"script\":\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo 'file bin/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +$installer->rollbackFileTransaction(); + +echo "install as invalid role=\"klingon\":\n"; +$err = $installer->_installFile('installer2.phpt.testfile.php', array('role' => 'klingon'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array()); +echo 'returned PEAR_Error: ' . (get_class($err) == 'pear_error' ? "yes\n" : "no\n"); +if (is_object($err)) { + echo 'message: ' . $err->getMessage() . "\n\n"; +} +echo 'file bin/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +echo "install non-existent file:\n"; +$err = $installer->_installFile('....php', array('role' => 'php'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array()); +echo 'returned PEAR_Error: ' . (get_class($err) == 'pear_error' ? "yes\n" : "no\n"); +if (is_object($err)) { + echo 'message: ' . $err->getMessage() . "\n"; +} +echo 'file bin/.tmp....php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmp....php') ? "yes\n" : "no\n"); + +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'installer2.phpt.testfile.php', 'w'); +fwrite($fp, '@TEST@ stuff'); +fclose($fp); + +echo "\ntest valid md5sum:\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', 'md5sum' => md5('@TEST@ stuff')), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo 'file bin/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +$installer->rollbackFileTransaction(); + +echo "test invalid md5sum:\n"; +$err = $installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', 'md5sum' => md5('oops stuff')), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array()); +echo 'returned PEAR_Error: ' . (get_class($err) == 'pear_error' ? "yes\n" : "no\n"); +if (is_object($err)) { + echo 'message: ' . ($err->getMessage() == 'bad md5sum for file ' . $temp_path . DIRECTORY_SEPARATOR . 'bin' . + DIRECTORY_SEPARATOR . 'installer2.phpt.testfile.php' ? 'match' : 'no match') . "\n"; +} +echo 'file bin/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +echo "test invalid md5sum with --force:\n"; +ob_start(); +$err = $installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', 'md5sum' => md5('oops stuff')), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array('force' => true)); +$warning = ob_get_contents(); +ob_end_clean(); +echo 'warning : '; +echo ($warning == 'warning : bad md5sum for file ' . $temp_path . DIRECTORY_SEPARATOR . 'bin' . + DIRECTORY_SEPARATOR . "installer2.phpt.testfile.php\n" ? "match\n" : "no match\n"); +echo 'returned PEAR_Error: ' . (get_class($err) == 'pear_error' ? "yes\n" : "no\n"); +if (is_object($err)) { + echo 'message: ' . ($err->getMessage() == 'bad md5sum for file ' . $temp_path . DIRECTORY_SEPARATOR . 'bin' . + DIRECTORY_SEPARATOR . 'installer2.phpt.testfile.php' ? 'match' : 'no match') . "\n"; +} +echo 'file bin/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +define('PEARINSTALLERTEST2_FAKE_FOO_CONST', 'good'); +echo "\ntest replacements:\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', + 'replacements' => array(array('type' => 'php-const', 'from' => '@TEST@', 'to' => 'PEARINSTALLERTEST2_FAKE_FOO_CONST'))), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo "==>test php-const replacement: equals 'good stuff'? => "; +if (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php')) +{ + $a = implode(file($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php'), ''); + echo "$a\n"; +} else { + echo "no! file installation failed\n"; +} +$installer->rollbackFileTransaction(); + +echo "==>test invalid php-const replacement:\n"; +$err = $installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', + 'replacements' => array(array('type' => 'php-const', 'from' => '@TEST@', 'to' => '%PEARINSTALLERTEST2_FAKE_FOO_CONST'))), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array()); +if (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php')) +{ + $a = implode(file($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php'), ''); + echo "$a\n"; +} else { + echo "no! file installation failed\n"; +} + +$installer->rollbackFileTransaction(); + +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', + 'replacements' => array(array('type' => 'pear-config', 'from' => '@TEST@', 'to' => 'master_server'))), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo "==>test pear-config replacement: equals 'pear.php.net stuff'? => "; +if (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php')) +{ + $a = implode(file($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php'), ''); + echo "$a\n"; +} else { + echo "no! file installation failed\n"; +} +$installer->rollbackFileTransaction(); + +echo "==>test invalid pear-config replacement\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', + 'replacements' => array(array('type' => 'pear-config', 'from' => '@TEST@', 'to' => 'blahblahblah'))), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +if (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php')) +{ + $a = implode(file($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php'), ''); + echo "$a\n"; +} else { + echo "no! file installation failed\n"; +} +$installer->rollbackFileTransaction(); + +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', + 'replacements' => array(array('type' => 'package-info', 'from' => '@TEST@', 'to' => 'package'))), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo "==>test package-info replacement: equals 'Foo stuff'? => "; +if (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php')) +{ + $a = implode(file($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php'), ''); + echo "$a\n"; +} else { + echo "no! file installation failed\n"; +} +$installer->rollbackFileTransaction(); + +echo "==>test invalid package-info replacement:\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', + 'replacements' => array(array('type' => 'package-info', 'from' => '@TEST@', 'to' => 'gronk'))), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +if (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php')) +{ + $a = implode(file($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php'), ''); + echo "$a\n"; +} else { + echo "no! file installation failed\n"; +} +$installer->rollbackFileTransaction(); + +echo "\ntest install-as:\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', + 'install-as' => 'foobar.php'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo "==>test install as 'foobar.php'. file exists? "; +if (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + '.tmpfoobar.php')) +{ + echo "yes\n"; +} else { + echo "no\n"; +} +$installer->rollbackFileTransaction(); + +echo "\ntest baseinstalldir:\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', + 'baseinstalldir' => 'Foo/Mine'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo "==>test baseinstalldir = 'Foo/Mine'. file exists? "; +if (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . + 'Foo' . DIRECTORY_SEPARATOR . 'Mine' . DIRECTORY_SEPARATOR . '.tmpinstaller2.phpt.testfile.php')) +{ + echo "yes\n"; +} else { + echo "no\n"; +} +$installer->rollbackFileTransaction(); + +//cleanup +chdir($curdir); +cleanall($temp_path); + +// ------------------------------------------------------------------------- // + +function cleanall($dir) +{ + $dp = opendir($dir); + while ($ent = readdir($dp)) { + if ($ent == '.' || $ent == '..') { + continue; + } + if (is_dir($dir . DIRECTORY_SEPARATOR . $ent)) { + cleanall($dir . DIRECTORY_SEPARATOR . $ent); + } else { + unlink($dir . DIRECTORY_SEPARATOR . $ent); + } + } + closedir($dp); + rmdir($dir); +} +?> +--EXPECT-- +test _installFile(): +install as role="php": +int(1) +file ext/.tmpinstaller2.phpt.testfile.php exists? => yes +install as role="ext": +int(1) +file php/.tmpinstaller2.phpt.testfile.php exists? => yes +install as role="data": +int(1) +file data/.tmpinstaller2.phpt.testfile.php exists? => yes +install as role="doc": +int(1) +file doc/.tmpinstaller2.phpt.testfile.php exists? => yes +install as role="test": +int(1) +file test/.tmpinstaller2.phpt.testfile.php exists? => yes +install as role="script": +int(1) +file bin/.tmpinstaller2.phpt.testfile.php exists? => yes +install as invalid role="klingon": +returned PEAR_Error: yes +message: Invalid role `klingon' for file installer2.phpt.testfile.php + +file bin/.tmpinstaller2.phpt.testfile.php exists? => no +install non-existent file: +returned PEAR_Error: yes +message: file does not exist +file bin/.tmp....php exists? => no + +test valid md5sum: +int(1) +file bin/.tmpinstaller2.phpt.testfile.php exists? => yes +test invalid md5sum: +returned PEAR_Error: yes +message: match +file bin/.tmpinstaller2.phpt.testfile.php exists? => no +test invalid md5sum with --force: +warning : match +returned PEAR_Error: no +file bin/.tmpinstaller2.phpt.testfile.php exists? => yes + +test replacements: +int(1) +==>test php-const replacement: equals 'good stuff'? => good stuff +==>test invalid php-const replacement: +invalid php-const replacement: %PEARINSTALLERTEST2_FAKE_FOO_CONST +@TEST@ stuff +int(1) +==>test pear-config replacement: equals 'pear.php.net stuff'? => pear.php.net stuff +==>test invalid pear-config replacement +invalid pear-config replacement: blahblahblah +int(1) +@TEST@ stuff +int(1) +==>test package-info replacement: equals 'Foo stuff'? => Foo stuff +==>test invalid package-info replacement: +invalid package-info replacement: gronk +int(1) +@TEST@ stuff + +test install-as: +int(1) +==>test install as 'foobar.php'. file exists? yes + +test baseinstalldir: +int(1) +==>test baseinstalldir = 'Foo/Mine'. file exists? yes + diff --git a/pear/tests/pear_installer3.phpt b/pear/tests/pear_installer3.phpt new file mode 100644 index 000000000..f997ab7e4 --- /dev/null +++ b/pear/tests/pear_installer3.phpt @@ -0,0 +1,415 @@ +--TEST-- +PEAR_Installer test #3 File Transactions +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php +$temp_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'testinstallertemp'; +if (!is_dir($temp_path)) { + mkdir($temp_path); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'php')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'php'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'data')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'data'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'doc')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'doc'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'test')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'test'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'ext')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'ext'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'script')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'script'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'tmp')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'tmp'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'bin')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'bin'); +} +// make the fake configuration - we'll use one of these and it should work +$config = serialize(array('master_server' => 'pear.php.net', + 'php_dir' => $temp_path . DIRECTORY_SEPARATOR . 'php', + 'ext_dir' => $temp_path . DIRECTORY_SEPARATOR . 'ext', + 'data_dir' => $temp_path . DIRECTORY_SEPARATOR . 'data', + 'doc_dir' => $temp_path . DIRECTORY_SEPARATOR . 'doc', + 'test_dir' => $temp_path . DIRECTORY_SEPARATOR . 'test', + 'bin_dir' => $temp_path . DIRECTORY_SEPARATOR . 'bin',)); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.conf'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.conf', 'w'); +fwrite($fp, $config); +fclose($fp); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.ini'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.ini', 'w'); +fwrite($fp, $config); +fclose($fp); + +putenv('PHP_PEAR_SYSCONF_DIR='.$temp_path); +$home = getenv('HOME'); +if (!empty($home)) { + // for PEAR_Config initialization + putenv('HOME="'.$temp_path); +} +require_once "PEAR/Installer.php"; + +// no UI is needed for these tests +$ui = false; +$installer = new PEAR_Installer($ui); +$installer->debug = 2; // hack debugging in +$curdir = getcwd(); +chdir(dirname(__FILE__)); + +echo "test addFileOperation():\n"; +echo "invalid input to addFileOperation():\n"; +$err = $installer->addFileOperation('rename', 2); +echo 'Returned PEAR_Error?'; +echo (get_class($err) == 'pear_error' ? " yes\n" : " no\n"); +if (get_class($err) == 'pear_error') { + echo $err->getMessage() . "\n"; +} +echo 'count($installer->file_operations) = '; +var_dump(count($installer->file_operations)); +echo "Do valid addFileOperation() delete\n"; +touch($temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'installertestfooblah.phpt'); +$installer->addFileOperation('delete', array($temp_path . DIRECTORY_SEPARATOR . + 'tmp' . DIRECTORY_SEPARATOR . 'installertestfooblah.phpt')); +echo 'count($installer->file_operations) = '; +var_dump(count($installer->file_operations)); + +echo "test valid commitFileTransaction():\n"; +if ($installer->commitFileTransaction()) { + echo "worked\n"; +} else { + echo "didn't work!\n"; +} + +echo "Do valid addFileOperation() rename\n"; +touch($temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'installertestfooblah.phpt'); +$installer->addFileOperation('rename', array($temp_path . DIRECTORY_SEPARATOR . + 'tmp' . DIRECTORY_SEPARATOR . 'installertestfooblah.phpt', $temp_path . + DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'renamed.phpt')); + +echo 'file renamed.phpt exists?'; +clearstatcache(); +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR + . 'renamed.phpt') ? " yes\n" : " no\n"); +echo "test valid commitFileTransaction():\n"; +if ($installer->commitFileTransaction()) { + echo "worked\n"; +} else { + echo "didn't work!\n"; +} +echo 'file renamed.phpt exists?'; +clearstatcache(); +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR + . 'renamed.phpt') ? " yes\n" : " no\n"); +unlink($temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR + . 'renamed.phpt'); + +echo "Do valid addFileOperation() chmod\n"; +touch($temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'installertestfooblah.phpt'); +clearstatcache(); +$perms = fileperms($temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'installertestfooblah.phpt'); +// check to see if chmod works on this OS +chmod($temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'installertestfooblah.phpt', 0776); +clearstatcache(); +if (fileperms($temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'installertestfooblah.phpt') + == $perms && substr(PHP_OS, 0, 3) == 'WIN') { + // we are on windows, so skip this test, but simulate success +echo <<<EOF +file permissions are: 776 +test valid commitFileTransaction(): +about to commit 1 file operations +successfully committed 1 file operations +worked +file permissions are: 640 + +EOF; +} else { + $installer->addFileOperation('chmod', array(0640, $temp_path . DIRECTORY_SEPARATOR . + 'tmp' . DIRECTORY_SEPARATOR . 'installertestfooblah.phpt')); + + echo 'file permissions are: ' . decoct(fileperms($temp_path . DIRECTORY_SEPARATOR . + 'tmp' . DIRECTORY_SEPARATOR . 'installertestfooblah.phpt')) . "\n"; + echo "test valid commitFileTransaction():\n"; + if ($installer->commitFileTransaction()) { + echo "worked\n"; + } else { + echo "didn't work!\n"; + } + echo 'file permissions are: ' . decoct(fileperms($temp_path . DIRECTORY_SEPARATOR . + 'tmp' . DIRECTORY_SEPARATOR . 'installertestfooblah.phpt')) . "\n"; +} +unlink($temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR + . 'installertestfooblah.phpt'); + +mkdir($temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR + . 'installertestfooblah'); +echo "Do valid addFileOperation() rmdir\n"; +echo 'directory exists?'; +clearstatcache(); +echo (is_dir($temp_path . DIRECTORY_SEPARATOR . + 'tmp' . DIRECTORY_SEPARATOR . 'installertestfooblah') ? " yes\n" : " no\n"); +$installer->addFileOperation('rmdir', array($temp_path . DIRECTORY_SEPARATOR . + 'tmp' . DIRECTORY_SEPARATOR . 'installertestfooblah')); + +echo "test valid commitFileTransaction():\n"; +if ($installer->commitFileTransaction()) { + echo "worked\n"; +} else { + echo "didn't work!\n"; +} +echo 'directory exists?'; + +clearstatcache(); +echo (is_dir($temp_path . DIRECTORY_SEPARATOR . + 'tmp' . DIRECTORY_SEPARATOR . 'installertestfooblah') ? " yes\n" : " no\n"); + +echo "Do valid addFileOperation() installed_as\n"; +$installer->addFileOperation('installed_as', array('test.php', + $temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . + 'glomp' . DIRECTORY_SEPARATOR . 'fromp' . DIRECTORY_SEPARATOR + . 'installertestfooblah.phpt', + $temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR, + 'glomp' . DIRECTORY_SEPARATOR . 'fromp')); +echo "test valid commitFileTransaction():\n"; +if ($installer->commitFileTransaction()) { + echo "worked\n"; +} else { + echo "didn't work!\n"; +} +if (isset($installer->pkginfo['filelist'])) { + echo "filelist created\n"; +} else { + echo "filelist not created!\n"; +} +if (isset($installer->pkginfo['filelist']['test.php'])) { + echo "filelist test.php created\n"; +} else { + echo "filelist test.php not created!\n"; +} +if (isset($installer->pkginfo['filelist']['test.php']['installed_as'])) { + echo "filelist test.php installed_as created\n"; +} else { + echo "filelist test.php installed_as not created!\n"; +} +$p = $temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . + 'glomp' . DIRECTORY_SEPARATOR . 'fromp' . DIRECTORY_SEPARATOR + . 'installertestfooblah.phpt'; +if (@$installer->pkginfo['filelist']['test.php']['installed_as'] == $p) { + echo "filelist test.php installed_as is correct\n"; +} else { + echo "filelist test.php installed_as is not correct!\n"; +} +if (isset($installer->pkginfo['filelist']['dirtree'])) { + echo "filelist dirtree created\n"; +} else { + echo "filelist dirtree not created!\n"; +} +$p = $temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . + 'glomp'; +if (isset($installer->pkginfo['filelist']['dirtree'][$p])) { + echo "filelist dirtree glomp created\n"; +} else { + echo "filelist dirtree glomp not created!\n"; +} +$p .= DIRECTORY_SEPARATOR . 'fromp'; +if (isset($installer->pkginfo['filelist']['dirtree'][$p])) { + echo "filelist dirtree fromp created\n"; +} else { + echo "filelist dirtree fromp not created!\n"; +} + +echo "Do valid addFileOperation() installed_as\n"; +$installer->addFileOperation('installed_as', array('test.php', + $temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . + 'glomp' . DIRECTORY_SEPARATOR . 'fromp' . DIRECTORY_SEPARATOR + . 'installertestfooblah.phpt', + $temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR, + 'glomp' . DIRECTORY_SEPARATOR . 'fromp')); +echo "test valid rollbackFileTransaction():\n"; +$installer->rollbackFileTransaction(); +if (isset($installer->pkginfo['filelist'])) { + echo "filelist created\n"; +} else { + echo "filelist not created!\n"; +} +if (isset($installer->pkginfo['filelist']['test.php'])) { + echo "filelist test.php created\n"; +} else { + echo "filelist test.php not created!\n"; +} +if (isset($installer->pkginfo['filelist']['test.php']['installed_as'])) { + echo "filelist test.php installed_as created\n"; +} else { + echo "filelist test.php installed_as not created!\n"; +} +$p = $temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . + 'glomp' . DIRECTORY_SEPARATOR . 'fromp' . DIRECTORY_SEPARATOR + . 'installertestfooblah.phpt'; +if (@$installer->pkginfo['filelist']['test.php']['installed_as'] == $p) { + echo "filelist test.php installed_as is correct\n"; +} else { + echo "filelist test.php installed_as is not correct!\n"; +} +if (isset($installer->pkginfo['filelist']['dirtree'])) { + echo "filelist dirtree created\n"; +} else { + echo "filelist dirtree not created!\n"; +} +$p = $temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . + 'glomp'; +if (isset($installer->pkginfo['filelist']['dirtree'][$p])) { + echo "filelist dirtree glomp created\n"; +} else { + echo "filelist dirtree glomp not created!\n"; +} +$p .= DIRECTORY_SEPARATOR . 'fromp'; +if (isset($installer->pkginfo['filelist']['dirtree'][$p])) { + echo "filelist dirtree fromp created\n"; +} else { + echo "filelist dirtree fromp not created!\n"; +} + +// invalid tests +echo "\n==>Invalid tests\n"; +echo "Do valid addFileOperation() delete with non-existing file\n"; +$installer->addFileOperation('delete', array('gloober62456.phpt')); +echo 'count($installer->file_operations) = '; +var_dump(count($installer->file_operations)); + +echo "test invalid commitFileTransaction():\n"; +if ($installer->commitFileTransaction()) { + echo "worked\n"; +} else { + echo "didn't work!\n"; + $installer->rollbackFileTransaction(); +} + +echo "Do valid addFileOperation() rename with non-existing file\n"; +$installer->addFileOperation('rename', array('gloober62456.phpt', 'faber.com')); +echo 'count($installer->file_operations) = '; +var_dump(count($installer->file_operations)); + +echo "test invalid commitFileTransaction():\n"; +if ($installer->commitFileTransaction()) { + echo "worked\n"; +} else { + echo "didn't work!\n"; + $installer->rollbackFileTransaction(); +} + +echo "Do valid addFileOperation() chmod with non-existing file\n"; +$installer->addFileOperation('chmod', array(0640, 'faber.com')); +echo 'count($installer->file_operations) = '; +var_dump(count($installer->file_operations)); + +echo "test invalid commitFileTransaction():\n"; +if ($installer->commitFileTransaction()) { + echo "worked\n"; +} else { + echo "didn't work!\n"; + $installer->rollbackFileTransaction(); +} + +//cleanup +chdir($curdir); +unlink ($temp_path . DIRECTORY_SEPARATOR . 'pear.conf'); +unlink ($temp_path . DIRECTORY_SEPARATOR . 'pear.ini'); +rmdir($temp_path . DIRECTORY_SEPARATOR . 'php'); +rmdir($temp_path . DIRECTORY_SEPARATOR . 'data'); +rmdir($temp_path . DIRECTORY_SEPARATOR . 'doc'); +rmdir($temp_path . DIRECTORY_SEPARATOR . 'test'); +rmdir($temp_path . DIRECTORY_SEPARATOR . 'script'); +rmdir($temp_path . DIRECTORY_SEPARATOR . 'ext'); +rmdir($temp_path . DIRECTORY_SEPARATOR . 'tmp'); +rmdir($temp_path . DIRECTORY_SEPARATOR . 'bin'); +rmdir($temp_path); +?> +--EXPECT-- +test addFileOperation(): +invalid input to addFileOperation(): +Returned PEAR_Error? yes +Internal Error: $data in addFileOperation must be an array, was integer +count($installer->file_operations) = int(0) +Do valid addFileOperation() delete +count($installer->file_operations) = int(1) +test valid commitFileTransaction(): +about to commit 1 file operations +successfully committed 1 file operations +worked +Do valid addFileOperation() rename +file renamed.phpt exists? no +test valid commitFileTransaction(): +about to commit 1 file operations +successfully committed 1 file operations +worked +file renamed.phpt exists? yes +Do valid addFileOperation() chmod +file permissions are: 776 +test valid commitFileTransaction(): +about to commit 1 file operations +successfully committed 1 file operations +worked +file permissions are: 640 +Do valid addFileOperation() rmdir +directory exists? yes +test valid commitFileTransaction(): +about to commit 1 file operations +successfully committed 1 file operations +worked +directory exists? no +Do valid addFileOperation() installed_as +test valid commitFileTransaction(): +about to commit 1 file operations +successfully committed 1 file operations +worked +filelist created +filelist test.php created +filelist test.php installed_as created +filelist test.php installed_as is correct +filelist dirtree created +filelist dirtree glomp created +filelist dirtree fromp created +Do valid addFileOperation() installed_as +test valid rollbackFileTransaction(): +rolling back 1 file operations +filelist created +filelist test.php created +filelist test.php installed_as not created! +filelist test.php installed_as is not correct! +filelist dirtree not created! +filelist dirtree glomp not created! +filelist dirtree fromp not created! + +==>Invalid tests +Do valid addFileOperation() delete with non-existing file +count($installer->file_operations) = int(1) +test invalid commitFileTransaction(): +about to commit 1 file operations +warning: file gloober62456.phpt doesn't exist, can't be deleted +successfully committed 1 file operations +worked +Do valid addFileOperation() rename with non-existing file +count($installer->file_operations) = int(1) +test invalid commitFileTransaction(): +about to commit 1 file operations +cannot rename file gloober62456.phpt, doesn't exist +didn't work! +rolling back 1 file operations +Do valid addFileOperation() chmod with non-existing file +count($installer->file_operations) = int(1) +test invalid commitFileTransaction(): +about to commit 1 file operations +permission denied (chmod): faber.com 640 +didn't work! +rolling back 1 file operations diff --git a/pear/tests/pear_installer4.phpt b/pear/tests/pear_installer4.phpt new file mode 100644 index 000000000..593d38ad4 --- /dev/null +++ b/pear/tests/pear_installer4.phpt @@ -0,0 +1,266 @@ +--TEST-- +PEAR_Installer test #4: PEAR_Installer::install() +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php +$temp_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'testinstallertemp'; +if (!is_dir($temp_path)) { + mkdir($temp_path); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'php')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'php'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'data')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'data'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'doc')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'doc'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'test')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'test'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'ext')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'ext'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'script')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'script'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'tmp')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'tmp'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'bin')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'bin'); +} +// make the fake configuration - we'll use one of these and it should work +$config = serialize(array('master_server' => 'pear.php.net', + 'php_dir' => $temp_path . DIRECTORY_SEPARATOR . 'php', + 'ext_dir' => $temp_path . DIRECTORY_SEPARATOR . 'ext', + 'data_dir' => $temp_path . DIRECTORY_SEPARATOR . 'data', + 'doc_dir' => $temp_path . DIRECTORY_SEPARATOR . 'doc', + 'test_dir' => $temp_path . DIRECTORY_SEPARATOR . 'test', + 'bin_dir' => $temp_path . DIRECTORY_SEPARATOR . 'bin',)); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.conf'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.conf', 'w'); +fwrite($fp, $config); +fclose($fp); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.ini'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.ini', 'w'); +fwrite($fp, $config); +fclose($fp); + +putenv('PHP_PEAR_SYSCONF_DIR='.$temp_path); +$home = getenv('HOME'); +if (!empty($home)) { + // for PEAR_Config initialization + putenv('HOME="'.$temp_path); +} +require_once "PEAR/Installer.php"; + +// no UI is needed for these tests +$ui = false; +$installer = new PEAR_Installer($ui); +$curdir = getcwd(); +chdir(dirname(__FILE__)); + +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'catchit'); + +$error_to_catch = false; +function catchit($err) +{ + global $error_to_catch; + if ($error_to_catch) { + if ($err->getMessage() == $error_to_catch) { + $error_to_catch = false; + echo "Caught expected error\n"; + return; + } + } + echo "Caught error: " . $err->getMessage() . "\n"; +} + +echo "Test package.xml direct install:\n"; +$installer->install(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'package.xml'); +$reg = &new PEAR_Registry($temp_path . DIRECTORY_SEPARATOR . 'php'); +var_dump($reg->listPackages()); +echo "zoorb.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'zoorb.php')) ? "yes\n" : "no\n"; +echo "goompness/Mopreeb.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'Mopreeb.php')) ? "yes\n" : "no\n"; +echo "goompness/oggbrzitzkee.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'oggbrzitzkee.php')) ? "yes\n" : "no\n"; + +echo "Test conflicting files:\n"; +$installer->install(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'conflictpackage.xml'); + +echo "After uninstall:\n"; +$installer->uninstall('pkg6'); +var_dump($reg->listPackages()); +echo "zoorb.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'zoorb.php')) ? "yes\n" : "no\n"; +echo "goompness/Mopreeb.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'Mopreeb.php')) ? "yes\n" : "no\n"; +echo "goompness/oggbrzitzkee.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'oggbrzitzkee.php')) ? "yes\n" : "no\n"; +echo "goompness exists? "; +echo (is_dir($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness')) + ? "yes\n" : "no\n"; + +echo "Test .tgz install:\n"; +$installer->install(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'pkg6-1.1.tgz'); +$reg = &new PEAR_Registry($temp_path . DIRECTORY_SEPARATOR . 'php'); +var_dump($reg->listPackages()); +echo "zoorb.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'zoorb.php')) ? "yes\n" : "no\n"; +echo "goompness/Mopreeb.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'Mopreeb.php')) ? "yes\n" : "no\n"; +echo "goompness/oggbrzitzkee.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'oggbrzitzkee.php')) ? "yes\n" : "no\n"; +echo "After uninstall:\n"; +$installer->uninstall('pkg6'); +var_dump($reg->listPackages()); +echo "zoorb.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'zoorb.php')) ? "yes\n" : "no\n"; +echo "goompness/Mopreeb.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'Mopreeb.php')) ? "yes\n" : "no\n"; +echo "goompness/oggbrzitzkee.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'oggbrzitzkee.php')) ? "yes\n" : "no\n"; +echo "goompness exists? "; +echo (is_dir($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness')) + ? "yes\n" : "no\n"; + +echo "Test invalid .tgz install:\n"; +$error_to_catch = 'unable to unpack ' . dirname(__FILE__) . DIRECTORY_SEPARATOR . + 'test-pkg6' . DIRECTORY_SEPARATOR . 'invalidtgz.tgz'; +$installer->install(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'invalidtgz.tgz'); +$reg = &new PEAR_Registry($temp_path . DIRECTORY_SEPARATOR . 'php'); +var_dump($reg->listPackages()); +echo "zoorb.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'zoorb.php')) ? "yes\n" : "no\n"; +echo "goompness/Mopreeb.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'Mopreeb.php')) ? "yes\n" : "no\n"; +echo "goompness/oggbrzitzkee.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'oggbrzitzkee.php')) ? "yes\n" : "no\n"; + +echo "Test missing package.xml in .tgz install:\n"; +$installer->install(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'nopackagexml.tgz'); +$reg = &new PEAR_Registry($temp_path . DIRECTORY_SEPARATOR . 'php'); +var_dump($reg->listPackages()); +echo "zoorb.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'zoorb.php')) ? "yes\n" : "no\n"; +echo "goompness/Mopreeb.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'Mopreeb.php')) ? "yes\n" : "no\n"; +echo "goompness/oggbrzitzkee.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'oggbrzitzkee.php')) ? "yes\n" : "no\n"; + +chdir($curdir); +cleanall($temp_path); + +// ------------------------------------------------------------------------- // + +function cleanall($dir) +{ + $dp = opendir($dir); + while ($ent = readdir($dp)) { + if ($ent == '.' || $ent == '..') { + continue; + } + if (is_dir($dir . DIRECTORY_SEPARATOR . $ent)) { + cleanall($dir . DIRECTORY_SEPARATOR . $ent); + } else { + unlink($dir . DIRECTORY_SEPARATOR . $ent); + } + } + closedir($dp); + rmdir($dir); +} +?> +--EXPECT-- +Test package.xml direct install: +array(1) { + [0]=> + string(4) "pkg6" +} +zoorb.php exists? yes +goompness/Mopreeb.php exists? yes +goompness/oggbrzitzkee.php exists? yes +Test conflicting files: +Caught error: pear::pkg6conflict: conflicting files found: +groob\goompness\oggbrzitzkee.php (pkg6) + groob\goompness\Mopreeb.php (pkg6) + +After uninstall: +array(0) { +} +zoorb.php exists? no +goompness/Mopreeb.php exists? no +goompness/oggbrzitzkee.php exists? no +goompness exists? no +Test .tgz install: +array(1) { + [0]=> + string(4) "pkg6" +} +zoorb.php exists? yes +goompness/Mopreeb.php exists? yes +goompness/oggbrzitzkee.php exists? yes +After uninstall: +array(0) { +} +zoorb.php exists? no +goompness/Mopreeb.php exists? no +goompness/oggbrzitzkee.php exists? no +goompness exists? no +Test invalid .tgz install: +Caught error: Invalid checksum for file "<?xml version="1.0" encoding="ISO-8859-1" ?> + <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/" : 37649 calculated, 0 expected +Caught expected error +array(0) { +} +zoorb.php exists? no +goompness/Mopreeb.php exists? no +goompness/oggbrzitzkee.php exists? no +Test missing package.xml in .tgz install: +warning : you are using an archive with an old format +Caught error: no package.xml file after extracting the archive +array(0) { +} +zoorb.php exists? no +goompness/Mopreeb.php exists? no +goompness/oggbrzitzkee.php exists? no diff --git a/pear/tests/pear_installer5.phpt b/pear/tests/pear_installer5.phpt new file mode 100644 index 000000000..2996e2e6b --- /dev/null +++ b/pear/tests/pear_installer5.phpt @@ -0,0 +1,224 @@ +--TEST-- +PEAR_Installer test #5: test directory tracking/deletion of installation +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php +$temp_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'testinstallertemp'; +if (!is_dir($temp_path)) { + mkdir($temp_path); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'php')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'php'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'data')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'data'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'doc')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'doc'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'test')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'test'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'ext')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'ext'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'script')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'script'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'tmp')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'tmp'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'bin')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'bin'); +} +// make the fake configuration - we'll use one of these and it should work +$config = serialize(array('master_server' => 'pear.php.net', + 'php_dir' => $temp_path . DIRECTORY_SEPARATOR . 'php', + 'ext_dir' => $temp_path . DIRECTORY_SEPARATOR . 'ext', + 'data_dir' => $temp_path . DIRECTORY_SEPARATOR . 'data', + 'doc_dir' => $temp_path . DIRECTORY_SEPARATOR . 'doc', + 'test_dir' => $temp_path . DIRECTORY_SEPARATOR . 'test', + 'bin_dir' => $temp_path . DIRECTORY_SEPARATOR . 'bin',)); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.conf'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.conf', 'w'); +fwrite($fp, $config); +fclose($fp); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.ini'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.ini', 'w'); +fwrite($fp, $config); +fclose($fp); + +putenv('PHP_PEAR_SYSCONF_DIR='.$temp_path); +$home = getenv('HOME'); +if (!empty($home)) { + // for PEAR_Config initialization + putenv('HOME="'.$temp_path); +} +require_once "PEAR/Installer.php"; + +// no UI is needed for these tests +$ui = false; +$installer = new PEAR_Installer($ui); +$curdir = getcwd(); +chdir(dirname(__FILE__)); + +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'catchit'); + +$error_to_catch = false; +function catchit($err) +{ + global $error_to_catch; + if ($error_to_catch) { + if ($err->getMessage() == $error_to_catch) { + $error_to_catch = false; + echo "Caught expected error\n"; + return; + } + } + echo "Caught error: " . $err->getMessage() . "\n"; +} + +$installer->install(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'dirtree' . DIRECTORY_SEPARATOR . 'package.xml'); +$installer->install(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'dirtree' . DIRECTORY_SEPARATOR . 'package2.xml'); +$reg = &new PEAR_Registry($temp_path . DIRECTORY_SEPARATOR . 'php'); +var_dump($reg->listPackages()); +$info = $reg->packageInfo('pkg1'); +echo "pkg1 dir tree contains test/? "; +echo (isset($info['filelist']['dirtree'][$temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test'])) ? "yes\n" : "no\n"; +echo "pkg1 dir tree contains test/multiplepackages? "; +echo (isset($info['filelist']['dirtree'][$temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'multiplepackages'])) ? "yes\n" : "no\n"; +echo "pkg1 dir tree contains test/pkg1? "; +echo (isset($info['filelist']['dirtree'][$temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'pkg1'])) ? "yes\n" : "no\n"; + +$info = $reg->packageInfo('pkg2'); +echo "pkg2 dir tree contains test/? "; +echo (isset($info['filelist']['dirtree'][$temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test'])) ? "yes\n" : "no\n"; +echo "pkg2 dir tree contains test/multiplepackages? "; +echo (isset($info['filelist']['dirtree'][$temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'multiplepackages'])) ? "yes\n" : "no\n"; +echo "pkg2 dir tree contains test/nestedroot? "; +echo (isset($info['filelist']['dirtree'][$temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'nestedroot'])) ? "yes\n" : "no\n"; +echo "pkg2 dir tree contains test/nestedroot/emptydir? "; +echo (isset($info['filelist']['dirtree'][$temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'nestedroot' + . DIRECTORY_SEPARATOR . 'emptydir'])) ? "yes\n" : "no\n"; +echo "pkg2 dir tree contains test/nestedroot/emptydir/nesteddir? "; +echo (isset($info['filelist']['dirtree'][$temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'nestedroot' + . DIRECTORY_SEPARATOR . 'emptydir' . DIRECTORY_SEPARATOR . 'nesteddir'])) ? "yes\n" : "no\n"; + +echo "After uninstall of pkg1:\n"; +$installer->uninstall('pkg1'); +echo "test/ exists? "; +echo (is_dir($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test')) ? "yes\n" : "no\n"; +echo "test/multiplepackages exists? "; +echo (is_dir($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'multiplepackages')) ? "yes\n" : "no\n"; +echo "test/pkg1 exists? "; +echo (is_dir($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'pkg1')) ? "yes\n" : "no\n"; +echo "test/nestedroot exists? "; +echo (is_dir($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'nestedroot')) ? "yes\n" : "no\n"; +echo "test/nestedroot/emptydir exists? "; +echo (is_dir($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'nestedroot' + . DIRECTORY_SEPARATOR . 'emptydir')) ? "yes\n" : "no\n"; +echo "test/nestedroot/emptydir/nesteddir exists? "; +echo (is_dir($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'nestedroot' + . DIRECTORY_SEPARATOR . 'emptydir'. DIRECTORY_SEPARATOR . 'nesteddir')) ? "yes\n" : "no\n"; +var_dump($reg->listPackages()); + +echo "After uninstall of pkg2:\n"; +$installer->uninstall('pkg2'); +echo "test/ exists? "; +echo (is_dir($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test')) ? "yes\n" : "no\n"; +echo "test/multiplepackages exists? "; +echo (is_dir($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'multiplepackages')) ? "yes\n" : "no\n"; +echo "test/pkg1 exists? "; +echo (is_dir($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'pkg1')) ? "yes\n" : "no\n"; +echo "test/nestedroot exists? "; +echo (is_dir($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'nestedroot')) ? "yes\n" : "no\n"; +echo "test/nestedroot/emptydir exists? "; +echo (is_dir($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'nestedroot' + . DIRECTORY_SEPARATOR . 'emptydir')) ? "yes\n" : "no\n"; +echo "test/nestedroot/emptydir/nesteddir exists? "; +echo (is_dir($temp_path . DIRECTORY_SEPARATOR . 'php' + . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'nestedroot' + . DIRECTORY_SEPARATOR . 'emptydir'. DIRECTORY_SEPARATOR . 'nesteddir')) ? "yes\n" : "no\n"; +var_dump($reg->listPackages()); + +chdir($curdir); +cleanall($temp_path); + +// ------------------------------------------------------------------------- // + +function cleanall($dir) +{ + $dp = opendir($dir); + while ($ent = readdir($dp)) { + if ($ent == '.' || $ent == '..') { + continue; + } + if (is_dir($dir . DIRECTORY_SEPARATOR . $ent)) { + cleanall($dir . DIRECTORY_SEPARATOR . $ent); + } else { + unlink($dir . DIRECTORY_SEPARATOR . $ent); + } + } + closedir($dp); + rmdir($dir); +} +?> +--EXPECT-- +array(2) { + [0]=> + string(4) "pkg1" + [1]=> + string(4) "pkg2" +} +pkg1 dir tree contains test/? yes +pkg1 dir tree contains test/multiplepackages? yes +pkg1 dir tree contains test/pkg1? yes +pkg2 dir tree contains test/? yes +pkg2 dir tree contains test/multiplepackages? yes +pkg2 dir tree contains test/nestedroot? yes +pkg2 dir tree contains test/nestedroot/emptydir? yes +pkg2 dir tree contains test/nestedroot/emptydir/nesteddir? yes +After uninstall of pkg1: +test/ exists? yes +test/multiplepackages exists? yes +test/pkg1 exists? no +test/nestedroot exists? yes +test/nestedroot/emptydir exists? yes +test/nestedroot/emptydir/nesteddir exists? yes +array(1) { + [0]=> + string(4) "pkg2" +} +After uninstall of pkg2: +test/ exists? no +test/multiplepackages exists? no +test/pkg1 exists? no +test/nestedroot exists? no +test/nestedroot/emptydir exists? no +test/nestedroot/emptydir/nesteddir exists? no +array(0) { +}
\ No newline at end of file diff --git a/pear/tests/pear_installer_installFile_channels.phpt b/pear/tests/pear_installer_installFile_channels.phpt new file mode 100644 index 000000000..376b3c530 --- /dev/null +++ b/pear/tests/pear_installer_installFile_channels.phpt @@ -0,0 +1,447 @@ +--TEST-- +PEAR_Installer test _installFile() with channels +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php +$temp_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'testinstallertemp'; +if (!is_dir($temp_path)) { + mkdir($temp_path); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'php')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'php'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'data')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'data'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'doc')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'doc'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'test')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'test'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'ext')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'ext'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'script')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'script'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'tmp')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'tmp'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'bin')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'bin'); +} +// make the fake configuration - we'll use one of these and it should work +$config = serialize(array('master_server' => 'pear.php.net', + 'default_channel' => 'pear', + 'php_dir' => $temp_path . DIRECTORY_SEPARATOR . 'php', + 'ext_dir' => $temp_path . DIRECTORY_SEPARATOR . 'ext', + 'data_dir' => $temp_path . DIRECTORY_SEPARATOR . 'data', + 'doc_dir' => $temp_path . DIRECTORY_SEPARATOR . 'doc', + 'test_dir' => $temp_path . DIRECTORY_SEPARATOR . 'tests', + 'bin_dir' => $temp_path . DIRECTORY_SEPARATOR . 'bin', + '__channels' => + array( + 'test' => array( + 'php_dir' => $temp_path . DIRECTORY_SEPARATOR . 'php' . DIRECTORY_SEPARATOR . 'test', + 'ext_dir' => $temp_path . DIRECTORY_SEPARATOR . 'ext' . DIRECTORY_SEPARATOR . 'test', + 'data_dir' => $temp_path . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'test', + 'doc_dir' => $temp_path . DIRECTORY_SEPARATOR . 'doc' . DIRECTORY_SEPARATOR . 'test', + 'test_dir' => $temp_path . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'tests', + 'bin_dir' => $temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test', + ), + ))); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.conf'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.conf', 'w'); +fwrite($fp, $config); +fclose($fp); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.ini'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.ini', 'w'); +fwrite($fp, $config); +fclose($fp); + +putenv('PHP_PEAR_SYSCONF_DIR='.$temp_path); +$home = getenv('HOME'); +if (!empty($home)) { + // for PEAR_Config initialization + putenv('HOME="'.$temp_path); +} +require_once 'PEAR/Config.php'; +$config = &PEAR_Config::singleton($temp_path . DIRECTORY_SEPARATOR . 'pear.ini'); +require_once 'PEAR/Registry.php'; +$reg = &new PEAR_Registry($config->get('php_dir', null, 'pear')); +require_once 'PEAR/ChannelFile.php'; +$chan = new PEAR_ChannelFile; +$chan->setName('test'); +$chan->setServer('test'); +$chan->setSummary('test'); +$reg->addChannel($chan); +require_once "PEAR/Installer.php"; + +// no UI is needed for these tests +$ui = false; +$installer = new PEAR_Installer($ui); +$curdir = getcwd(); +chdir(dirname(__FILE__)); + +echo "test _installFile():\n"; +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'installer2.phpt.testfile.php', 'w'); +fwrite($fp, 'a'); +fclose($fp); +// pretend we just parsed a package.xml +$installer->pkginfo = array('package' => 'Foo', 'channel' => 'test'); + +echo "install as role=\"php\":\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'php'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo 'file php/test/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' . DIRECTORY_SEPARATOR . 'test' . + DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +echo "install as role=\"ext\":\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'ext'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo 'file ext/test/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'ext' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +echo "install as role=\"data\":\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'data'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo 'file data/test/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + 'Foo' . DIRECTORY_SEPARATOR . '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +echo "install as role=\"doc\":\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'doc'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo 'file doc/test/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'doc' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + 'Foo' . DIRECTORY_SEPARATOR . '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +echo "install as role=\"test\":\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'test'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo 'file test/tests/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . 'tests' + . DIRECTORY_SEPARATOR . + 'Foo' . DIRECTORY_SEPARATOR . '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +echo "install as role=\"script\":\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo 'file bin/test/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +$installer->rollbackFileTransaction(); + +echo "install as invalid role=\"klingon\":\n"; +$err = $installer->_installFile('installer2.phpt.testfile.php', array('role' => 'klingon'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array()); +echo 'returned PEAR_Error: ' . (get_class($err) == 'pear_error' ? "yes\n" : "no\n"); +if (is_object($err)) { + echo 'message: ' . $err->getMessage() . "\n\n"; +} +echo 'file bin/test/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +echo "install non-existent file:\n"; +$err = $installer->_installFile('....php', array('role' => 'php'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array()); +echo 'returned PEAR_Error: ' . (get_class($err) == 'pear_error' ? "yes\n" : "no\n"); +if (is_object($err)) { + echo 'message: ' . $err->getMessage() . "\n"; +} +echo 'file php/test/.tmp....php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmp....php') ? "yes\n" : "no\n"); + +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'installer2.phpt.testfile.php', 'w'); +fwrite($fp, '@TEST@ stuff'); +fclose($fp); + +echo "\ntest valid md5sum:\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', 'md5sum' => md5('@TEST@ stuff')), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo 'file bin/test/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +$installer->rollbackFileTransaction(); + +echo "test invalid md5sum:\n"; +$err = $installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', 'md5sum' => md5('oops stuff')), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array()); +echo 'returned PEAR_Error: ' . (get_class($err) == 'pear_error' ? "yes\n" : "no\n"); +if (is_object($err)) { + echo 'message: ' . ($err->getMessage() == 'bad md5sum for file ' . $temp_path . DIRECTORY_SEPARATOR . 'bin' . + DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . 'installer2.phpt.testfile.php' ? 'match' : 'no match') . "\n"; +} +echo 'file bin/test/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +echo "test invalid md5sum with --force:\n"; +ob_start(); +$err = $installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', 'md5sum' => md5('oops stuff')), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array('force' => true)); +$warning = ob_get_contents(); +ob_end_clean(); +echo 'warning : '; +echo ($warning == 'warning : bad md5sum for file ' . $temp_path . DIRECTORY_SEPARATOR . 'bin' . + DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . "installer2.phpt.testfile.php\n" ? "match\n" : "no match\n"); +echo 'returned PEAR_Error: ' . (get_class($err) == 'pear_error' ? "yes\n" : "no\n"); +if (is_object($err)) { + echo 'message: ' . ($err->getMessage() == 'bad md5sum for file ' . $temp_path . DIRECTORY_SEPARATOR . 'bin' . + DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . 'installer2.phpt.testfile.php' ? 'match' : 'no match') . "\n"; +} +echo 'file bin/test/.tmpinstaller2.phpt.testfile.php exists? => '; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php') ? "yes\n" : "no\n"); + +define('PEARINSTALLERTEST2_FAKE_FOO_CONST', 'good'); +echo "\ntest replacements:\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', + 'replacements' => array(array('type' => 'php-const', 'from' => '@TEST@', 'to' => 'PEARINSTALLERTEST2_FAKE_FOO_CONST'))), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo "==>test php-const replacement: equals 'good stuff'? => "; +if (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php')) +{ + $a = implode(file($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php'), ''); + echo "$a\n"; +} else { + echo "no! file installation failed\n"; +} +$installer->rollbackFileTransaction(); + +echo "==>test invalid php-const replacement:\n"; +$err = $installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', + 'replacements' => array(array('type' => 'php-const', 'from' => '@TEST@', 'to' => '%PEARINSTALLERTEST2_FAKE_FOO_CONST'))), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array()); +if (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php')) +{ + $a = implode(file($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php'), ''); + echo "$a\n"; +} else { + echo "no! file installation failed\n"; +} + +$installer->rollbackFileTransaction(); + +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', + 'replacements' => array(array('type' => 'pear-config', 'from' => '@TEST@', 'to' => 'master_server'))), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo "==>test pear-config replacement: equals 'test stuff'? => "; +if (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php')) +{ + $a = implode(file($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php'), ''); + echo "$a\n"; +} else { + echo "no! file installation failed\n"; +} +$installer->rollbackFileTransaction(); + +echo "==>test invalid pear-config replacement\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', + 'replacements' => array(array('type' => 'pear-config', 'from' => '@TEST@', 'to' => 'blahblahblah'))), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +if (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php')) +{ + $a = implode(file($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php'), ''); + echo "$a\n"; +} else { + echo "no! file installation failed\n"; +} +$installer->rollbackFileTransaction(); + +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', + 'replacements' => array(array('type' => 'package-info', 'from' => '@TEST@', 'to' => 'package'))), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo "==>test package-info replacement: equals 'Foo stuff'? => "; +if (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php')) +{ + $a = implode(file($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php'), ''); + echo "$a\n"; +} else { + echo "no! file installation failed\n"; +} +$installer->rollbackFileTransaction(); + +echo "==>test invalid package-info replacement:\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', + 'replacements' => array(array('type' => 'package-info', 'from' => '@TEST@', 'to' => 'gronk'))), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +if (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php')) +{ + $a = implode(file($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpinstaller2.phpt.testfile.php'), ''); + echo "$a\n"; +} else { + echo "no! file installation failed\n"; +} +$installer->rollbackFileTransaction(); + +echo "\ntest install-as:\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', + 'install-as' => 'foobar.php'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo "==>test install as 'foobar.php'. file exists? "; +if (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + '.tmpfoobar.php')) +{ + echo "yes\n"; +} else { + echo "no\n"; +} +$installer->rollbackFileTransaction(); + +echo "\ntest baseinstalldir:\n"; +var_dump($installer->_installFile('installer2.phpt.testfile.php', array('role' => 'script', + 'baseinstalldir' => 'Foo/Mine'), + $temp_path . DIRECTORY_SEPARATOR . 'tmp', array())); +echo "==>test baseinstalldir = 'Foo/Mine'. file exists? "; +if (file_exists($temp_path . DIRECTORY_SEPARATOR . 'bin' . DIRECTORY_SEPARATOR . 'test' + . DIRECTORY_SEPARATOR . + 'Foo' . DIRECTORY_SEPARATOR . 'Mine' . DIRECTORY_SEPARATOR . '.tmpinstaller2.phpt.testfile.php')) +{ + echo "yes\n"; +} else { + echo "no\n"; +} +$installer->rollbackFileTransaction(); + +//cleanup +chdir($curdir); +cleanall($temp_path); +function cleanall($dir) +{ + $dp = opendir($dir); + while ($ent = readdir($dp)) { + if ($ent == '.' || $ent == '..') { + continue; + } + if (is_dir($dir . DIRECTORY_SEPARATOR . $ent)) { + cleanall($dir . DIRECTORY_SEPARATOR . $ent); + } else { + unlink($dir . DIRECTORY_SEPARATOR . $ent); + } + } + closedir($dp); + rmdir($dir); +} +?> +--GET-- +--POST-- +--EXPECT-- +test _installFile(): +install as role="php": +int(1) +file php/test/.tmpinstaller2.phpt.testfile.php exists? => yes +install as role="ext": +int(1) +file ext/test/.tmpinstaller2.phpt.testfile.php exists? => yes +install as role="data": +int(1) +file data/test/.tmpinstaller2.phpt.testfile.php exists? => yes +install as role="doc": +int(1) +file doc/test/.tmpinstaller2.phpt.testfile.php exists? => yes +install as role="test": +int(1) +file test/tests/.tmpinstaller2.phpt.testfile.php exists? => yes +install as role="script": +int(1) +file bin/test/.tmpinstaller2.phpt.testfile.php exists? => yes +install as invalid role="klingon": +returned PEAR_Error: yes +message: Invalid role `klingon' for file installer2.phpt.testfile.php + +file bin/test/.tmpinstaller2.phpt.testfile.php exists? => no +install non-existent file: +returned PEAR_Error: yes +message: file does not exist +file php/test/.tmp....php exists? => no + +test valid md5sum: +int(1) +file bin/test/.tmpinstaller2.phpt.testfile.php exists? => yes +test invalid md5sum: +returned PEAR_Error: yes +message: match +file bin/test/.tmpinstaller2.phpt.testfile.php exists? => no +test invalid md5sum with --force: +warning : match +returned PEAR_Error: no +file bin/test/.tmpinstaller2.phpt.testfile.php exists? => yes + +test replacements: +int(1) +==>test php-const replacement: equals 'good stuff'? => good stuff +==>test invalid php-const replacement: +invalid php-const replacement: %PEARINSTALLERTEST2_FAKE_FOO_CONST +@TEST@ stuff +int(1) +==>test pear-config replacement: equals 'test stuff'? => test stuff +==>test invalid pear-config replacement +invalid pear-config replacement: blahblahblah +int(1) +@TEST@ stuff +int(1) +==>test package-info replacement: equals 'Foo stuff'? => Foo stuff +==>test invalid package-info replacement: +invalid package-info replacement: gronk +int(1) +@TEST@ stuff + +test install-as: +int(1) +==>test install as 'foobar.php'. file exists? yes + +test baseinstalldir: +int(1) +==>test baseinstalldir = 'Foo/Mine'. file exists? yes + diff --git a/pear/tests/pear_installer_install_channels.phpt b/pear/tests/pear_installer_install_channels.phpt new file mode 100644 index 000000000..d4c3418d0 --- /dev/null +++ b/pear/tests/pear_installer_install_channels.phpt @@ -0,0 +1,214 @@ +--TEST-- +PEAR_Installer test #4: PEAR_Installer::install() with channels +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php +$temp_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'testinstallertemp'; +if (!is_dir($temp_path)) { + mkdir($temp_path); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'php')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'php'); + mkdir($temp_path . DIRECTORY_SEPARATOR . 'php' . DIRECTORY_SEPARATOR . 'frob'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'data')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'data'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'doc')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'doc'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'test')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'test'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'ext')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'ext'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'script')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'script'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'tmp')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'tmp'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'bin')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'bin'); +} +// make the fake configuration - we'll use one of these and it should work +$config = serialize(array('master_server' => 'pear.php.net', + 'default_channel' => 'pear', + 'php_dir' => $temp_path . DIRECTORY_SEPARATOR . 'php', + 'ext_dir' => $temp_path . DIRECTORY_SEPARATOR . 'ext', + 'data_dir' => $temp_path . DIRECTORY_SEPARATOR . 'data', + 'doc_dir' => $temp_path . DIRECTORY_SEPARATOR . 'doc', + 'test_dir' => $temp_path . DIRECTORY_SEPARATOR . 'test', + 'bin_dir' => $temp_path . DIRECTORY_SEPARATOR . 'bin', + '__channels' => array( + 'frob' => array( + 'php_dir' => $temp_path . DIRECTORY_SEPARATOR . 'php' . DIRECTORY_SEPARATOR . 'frob', + )))); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.conf'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.conf', 'w'); +fwrite($fp, $config); +fclose($fp); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.ini'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.ini', 'w'); +fwrite($fp, $config); +fclose($fp); + +putenv('PHP_PEAR_SYSCONF_DIR='.$temp_path); +$home = getenv('HOME'); +if (!empty($home)) { + // for PEAR_Config initialization + putenv('HOME="'.$temp_path); +} +require_once 'PEAR/ChannelFile.php'; +require_once 'PEAR/Registry.php'; +$reg = &new PEAR_Registry($temp_path . DIRECTORY_SEPARATOR . 'php'); +$chan = new PEAR_ChannelFile; +$chan->setName('frob'); +$chan->setSummary('test'); +$chan->setServer('test'); +$reg->addChannel($chan); +$chan->setName('groob'); +$reg->addChannel($chan); +require_once "PEAR/Installer.php"; + +// no UI is needed for these tests +$ui = false; +$installer = new PEAR_Installer($ui); +$curdir = getcwd(); +chdir(dirname(__FILE__)); + +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'catchit'); + +$error_to_catch = false; +function catchit($err) +{ + global $error_to_catch; + if ($error_to_catch) { + if ($err->getMessage() == $error_to_catch) { + $error_to_catch = false; + echo "Caught expected error\n"; + return; + } + } + echo "Caught error: " . $err->getMessage() . "\n"; +} + +echo "Test package.xml direct install:\n"; +$installer->install(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'package2.xml'); +$reg = &new PEAR_Registry($temp_path . DIRECTORY_SEPARATOR . 'php'); +var_dump($reg->listAllPackages()); +echo "zoorb.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' . DIRECTORY_SEPARATOR . 'frob' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'zoorb.php')) ? "yes\n" : "no\n"; +echo "goompness/Mopreeb.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' . DIRECTORY_SEPARATOR . 'frob' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'Mopreeb.php')) ? "yes\n" : "no\n"; +echo "goompness/oggbrzitzkee.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' . DIRECTORY_SEPARATOR . 'frob' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'oggbrzitzkee.php')) ? "yes\n" : "no\n"; +echo "goompness/test.dat exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'pkg6' + . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'test.dat')) ? "yes\n" : "no\n"; + +echo "Test conflicting files:\n"; +$installer->install(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'conflictpackage2.xml'); + +echo "Test unknown channel:\n"; +$installer->install(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'test-pkg6' . DIRECTORY_SEPARATOR . 'package2_invalid.xml'); + +echo "After uninstall:\n"; +$installer->uninstall('frob::pkg6'); +var_dump($reg->listAllPackages()); +echo "zoorb.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' . DIRECTORY_SEPARATOR . 'frob' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'zoorb.php')) ? "yes\n" : "no\n"; +echo "goompness/Mopreeb.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' . DIRECTORY_SEPARATOR . 'frob' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'Mopreeb.php')) ? "yes\n" : "no\n"; +echo "goompness/oggbrzitzkee.php exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'php' . DIRECTORY_SEPARATOR . 'frob' + . DIRECTORY_SEPARATOR . 'groob' . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'oggbrzitzkee.php')) ? "yes\n" : "no\n"; +echo "goompness/test.dat exists? "; +echo (file_exists($temp_path . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'pkg6' + . DIRECTORY_SEPARATOR . 'goompness' + . DIRECTORY_SEPARATOR . 'test.dat')) ? "yes\n" : "no\n"; + +chdir($curdir); +cleanall($temp_path); + +// ------------------------------------------------------------------------- // + +function cleanall($dir) +{ + $dp = opendir($dir); + while ($ent = readdir($dp)) { + if ($ent == '.' || $ent == '..') { + continue; + } + if (is_dir($dir . DIRECTORY_SEPARATOR . $ent)) { + cleanall($dir . DIRECTORY_SEPARATOR . $ent); + } else { + unlink($dir . DIRECTORY_SEPARATOR . $ent); + } + } + closedir($dp); + rmdir($dir); +} +?> +--GET-- +--POST-- +--EXPECT-- +Test package.xml direct install: +array(3) { + ["frob"]=> + array(1) { + [0]=> + string(4) "pkg6" + } + ["groob"]=> + array(0) { + } + ["pear"]=> + array(0) { + } +} +zoorb.php exists? yes +goompness/Mopreeb.php exists? yes +goompness/oggbrzitzkee.php exists? yes +goompness/test.dat exists? yes +Test conflicting files: +Caught error: groob::pkg6conflict: conflicting files found: +groob\goompness\oggbrzitzkee.php (frob::pkg6) + groob\goompness\Mopreeb.php (frob::pkg6) + groob\goompness\test.dat (frob::pkg6) + +Test unknown channel: +Error: Unknown channel, "gorp" +Caught error: Installation failed: invalid package file, use option force to install anyway +After uninstall: +array(3) { + ["frob"]=> + array(0) { + } + ["groob"]=> + array(0) { + } + ["pear"]=> + array(0) { + } +} +zoorb.php exists? no +goompness/Mopreeb.php exists? no +goompness/oggbrzitzkee.php exists? no +goompness/test.dat exists? no diff --git a/pear/tests/pear_packager.phpt b/pear/tests/pear_packager.phpt new file mode 100644 index 000000000..141fae06d --- /dev/null +++ b/pear/tests/pear_packager.phpt @@ -0,0 +1,396 @@ +--TEST-- +PEAR_Packager test +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php +$temp_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'testinstallertemp'; +if (!is_dir($temp_path)) { + mkdir($temp_path); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'php')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'php'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'data')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'data'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'doc')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'doc'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'test')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'test'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'ext')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'ext'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'script')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'script'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'tmp')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'tmp'); +} +if (!is_dir($temp_path . DIRECTORY_SEPARATOR . 'bin')) { + mkdir($temp_path . DIRECTORY_SEPARATOR . 'bin'); +} +// make the fake configuration - we'll use one of these and it should work +$config = serialize(array('master_server' => 'pear.php.net', + 'php_dir' => $temp_path . DIRECTORY_SEPARATOR . 'php', + 'ext_dir' => $temp_path . DIRECTORY_SEPARATOR . 'ext', + 'data_dir' => $temp_path . DIRECTORY_SEPARATOR . 'data', + 'doc_dir' => $temp_path . DIRECTORY_SEPARATOR . 'doc', + 'test_dir' => $temp_path . DIRECTORY_SEPARATOR . 'test', + 'bin_dir' => $temp_path . DIRECTORY_SEPARATOR . 'bin',)); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.conf'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.conf', 'w'); +fwrite($fp, $config); +fclose($fp); +touch($temp_path . DIRECTORY_SEPARATOR . 'pear.ini'); +$fp = fopen($temp_path . DIRECTORY_SEPARATOR . 'pear.ini', 'w'); +fwrite($fp, $config); +fclose($fp); + +putenv('PHP_PEAR_SYSCONF_DIR='.$temp_path); +$home = getenv('HOME'); +if (!empty($home)) { + // for PEAR_Config initialization + putenv('HOME="'.$temp_path); +} +require_once "PEAR/Packager.php"; +require_once 'PEAR/Registry.php'; +$reg = &new PEAR_Registry($temp_path . DIRECTORY_SEPARATOR . 'php'); +$packager = new PEAR_Packager(); +$packager->setRegistry($reg); +$curdir = getcwd(); +chdir(dirname(__FILE__)); + +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, 'catchit'); + +$error_to_catch = false; +function catchit($err) +{ + global $error_to_catch; + if ($error_to_catch) { + if ($err->getMessage() == $error_to_catch) { + $error_to_catch = false; + echo "Caught expected error\n"; + return; + } + } + echo "Caught error: " . $err->getMessage() . "\n"; +} +ob_start(); +if (!file_exists(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'dirtree' . DIRECTORY_SEPARATOR . 'CVS')) { + mkdir(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'dirtree' . DIRECTORY_SEPARATOR . 'CVS'); + touch(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'dirtree' . DIRECTORY_SEPARATOR . 'CVS' . DIRECTORY_SEPARATOR . 'Root'); +} +$packager->package(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'dirtree' . DIRECTORY_SEPARATOR . 'package.xml'); +$packager->package(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'dirtree' . DIRECTORY_SEPARATOR . 'package2.xml'); +$stuff = str_replace(array(dirname(__FILE__) . DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR), array('', '/'), + ob_get_contents()); +ob_end_clean(); +echo $stuff; + +$archive1 = &new Archive_Tar(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg1-1.0.tgz'); +$archive1c = &new Archive_Tar(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'dirtree' . + DIRECTORY_SEPARATOR . 'pkg1-1.0.tgz'); +$x1 = $archive1->listContent(); +$x2 = $archive1c->listContent(); +for($i=0;$i<count($x1); $i++) { +// if ($x1[$i]['filename'] == 'package.xml') { + unset($x1[$i]['mtime']); + unset($x1[$i]['checksum']); +// } +} +for($i=0;$i<count($x2); $i++) { +// if ($x2[$i]['filename'] == 'package.xml') { + unset($x2[$i]['mtime']); + unset($x2[$i]['checksum']); +// } +} +var_dump($x1, $x2); +$archive1 = &new Archive_Tar(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg2-1.0.tgz'); +$archive1c = &new Archive_Tar(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'dirtree' . + DIRECTORY_SEPARATOR . 'pkg2-1.0.tgz'); +$x1 = $archive1->listContent(); +$x2 = $archive1c->listContent(); +for($i=0;$i<count($x1); $i++) { +// if ($x1[$i]['filename'] == 'package.xml') { + unset($x1[$i]['mtime']); + unset($x1[$i]['checksum']); +// } +} +for($i=0;$i<count($x2); $i++) { +// if ($x2[$i]['filename'] == 'package.xml') { + unset($x2[$i]['mtime']); + unset($x2[$i]['checksum']); +// } +} +var_dump($x1, $x2); + +echo "test failure:\n"; +$packager->package(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'dirtree' . DIRECTORY_SEPARATOR . 'package-fail.xml'); + +unlink(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg1-1.0.tgz'); +unlink(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pkg2-1.0.tgz'); +chdir($curdir); +cleanall($temp_path); + +// ------------------------------------------------------------------------- // + +function cleanall($dir) +{ + $dp = opendir($dir); + while ($ent = readdir($dp)) { + if ($ent == '.' || $ent == '..') { + continue; + } + if (is_dir($dir . DIRECTORY_SEPARATOR . $ent)) { + cleanall($dir . DIRECTORY_SEPARATOR . $ent); + } else { + unlink($dir . DIRECTORY_SEPARATOR . $ent); + } + } + closedir($dp); + rmdir($dir); +} +?> +--EXPECT-- +Analyzing multiplepackages/pkg1file.php +Analyzing pkg1/randomfile.php +Package pkg1-1.0.tgz done +Tag the released code with `pear cvstag package.xml' +(or set the CVS tag RELEASE_1_0 by hand) +Analyzing multiplepackages/pkg2file.php +Analyzing nestedroot/rootfile.php +Analyzing nestedroot/emptydir/nesteddir/nestedfile.php +Package pkg2-1.0.tgz done +Tag the released code with `pear cvstag package2.xml' +(or set the CVS tag RELEASE_1_0 by hand) +array(3) { + [0]=> + array(6) { + ["filename"]=> + string(11) "package.xml" + ["mode"]=> + int(33206) + ["uid"]=> + int(0) + ["gid"]=> + int(0) + ["size"]=> + int(817) + ["typeflag"]=> + string(0) "" + } + [1]=> + array(6) { + ["filename"]=> + string(38) "pkg1-1.0/multiplepackages/pkg1file.php" + ["mode"]=> + int(33206) + ["uid"]=> + int(0) + ["gid"]=> + int(0) + ["size"]=> + int(0) + ["typeflag"]=> + string(0) "" + } + [2]=> + array(6) { + ["filename"]=> + string(28) "pkg1-1.0/pkg1/randomfile.php" + ["mode"]=> + int(33206) + ["uid"]=> + int(0) + ["gid"]=> + int(0) + ["size"]=> + int(0) + ["typeflag"]=> + string(0) "" + } +} +array(3) { + [0]=> + array(6) { + ["filename"]=> + string(11) "package.xml" + ["mode"]=> + int(33206) + ["uid"]=> + int(0) + ["gid"]=> + int(0) + ["size"]=> + int(817) + ["typeflag"]=> + string(0) "" + } + [1]=> + array(6) { + ["filename"]=> + string(38) "pkg1-1.0/multiplepackages/pkg1file.php" + ["mode"]=> + int(33206) + ["uid"]=> + int(0) + ["gid"]=> + int(0) + ["size"]=> + int(0) + ["typeflag"]=> + string(0) "" + } + [2]=> + array(6) { + ["filename"]=> + string(28) "pkg1-1.0/pkg1/randomfile.php" + ["mode"]=> + int(33206) + ["uid"]=> + int(0) + ["gid"]=> + int(0) + ["size"]=> + int(0) + ["typeflag"]=> + string(0) "" + } +} +array(4) { + [0]=> + array(6) { + ["filename"]=> + string(11) "package.xml" + ["mode"]=> + int(33206) + ["uid"]=> + int(0) + ["gid"]=> + int(0) + ["size"]=> + int(921) + ["typeflag"]=> + string(0) "" + } + [1]=> + array(6) { + ["filename"]=> + string(38) "pkg2-1.0/multiplepackages/pkg2file.php" + ["mode"]=> + int(33206) + ["uid"]=> + int(0) + ["gid"]=> + int(0) + ["size"]=> + int(0) + ["typeflag"]=> + string(0) "" + } + [2]=> + array(6) { + ["filename"]=> + string(32) "pkg2-1.0/nestedroot/rootfile.php" + ["mode"]=> + int(33206) + ["uid"]=> + int(0) + ["gid"]=> + int(0) + ["size"]=> + int(0) + ["typeflag"]=> + string(0) "" + } + [3]=> + array(6) { + ["filename"]=> + string(53) "pkg2-1.0/nestedroot/emptydir/nesteddir/nestedfile.php" + ["mode"]=> + int(33206) + ["uid"]=> + int(0) + ["gid"]=> + int(0) + ["size"]=> + int(0) + ["typeflag"]=> + string(0) "" + } +} +array(4) { + [0]=> + array(6) { + ["filename"]=> + string(11) "package.xml" + ["mode"]=> + int(33206) + ["uid"]=> + int(0) + ["gid"]=> + int(0) + ["size"]=> + int(921) + ["typeflag"]=> + string(0) "" + } + [1]=> + array(6) { + ["filename"]=> + string(38) "pkg2-1.0/multiplepackages/pkg2file.php" + ["mode"]=> + int(33206) + ["uid"]=> + int(0) + ["gid"]=> + int(0) + ["size"]=> + int(0) + ["typeflag"]=> + string(0) "" + } + [2]=> + array(6) { + ["filename"]=> + string(32) "pkg2-1.0/nestedroot/rootfile.php" + ["mode"]=> + int(33206) + ["uid"]=> + int(0) + ["gid"]=> + int(0) + ["size"]=> + int(0) + ["typeflag"]=> + string(0) "" + } + [3]=> + array(6) { + ["filename"]=> + string(53) "pkg2-1.0/nestedroot/emptydir/nesteddir/nestedfile.php" + ["mode"]=> + int(33206) + ["uid"]=> + int(0) + ["gid"]=> + int(0) + ["size"]=> + int(0) + ["typeflag"]=> + string(0) "" + } +} +test failure: +Analyzing multiplepackages\pkg2file.php +Analyzing nestedroot\rootfile.php +Analyzing nestedroot\emptydir\nesteddir\nestedfile.php +Analyzing nestedroot\emptydir\nesteddir\doesntexist.php +Caught error: File does not exist: nestedroot\emptydir\nesteddir\doesntexist.php
\ No newline at end of file diff --git a/pear/tests/pear_registry.phpt b/pear/tests/pear_registry.phpt new file mode 100644 index 000000000..26cafa303 --- /dev/null +++ b/pear/tests/pear_registry.phpt @@ -0,0 +1,140 @@ +--TEST-- +PEAR_Registry +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +$statedir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'registry_tester'; +if (file_exists($statedir)) { + // don't delete existing directories! + echo 'skip'; +} +?> +--FILE-- +<?php + +error_reporting(E_ALL); +include_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pear_registry_inc.php.inc'; +include_once "PEAR/Registry.php"; +PEAR::setErrorHandling(PEAR_ERROR_DIE, "%s\n"); +$statedir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'registry_tester'; +cleanall(); + +$files1 = array( + "pkg1-1.php" => array( + "role" => "php", + ), + "pkg1-2.php" => array( + "role" => "php", + "baseinstalldir" => "pkg1", + ), + ); +$files2 = array( + "pkg2-1.php" => array( + "role" => "php", + ), + "pkg2-2.php" => array( + "role" => "php", + "baseinstalldir" => "pkg2", + ), + ); +$files3 = array( + "pkg3-1.php" => array( + "role" => "php", + ), + "pkg3-2.php" => array( + "role" => "php", + "baseinstalldir" => "pkg3", + ), + ); +$files3_new = array( + "pkg3-3.php" => array( + "role" => "php", + "baseinstalldir" => "pkg3", + ), + "pkg3-4.php" => array( + "role" => "php", + ), + ); + +print "creating registry object\n"; +$reg = new PEAR_Registry($statedir); +dumpall($reg); + +$reg->addPackage("pkg1", array("name" => "pkg1", "version" => "1.0", "filelist" => $files1)); +dumpall($reg); + +$reg->addPackage("pkg2", array("name" => "pkg2", "version" => "2.0", "filelist" => $files2)); +$reg->addPackage("pkg3", array("name" => "pkg3", "version" => "3.0", "filelist" => $files3)); +dumpall($reg); + +$reg->updatePackage("pkg2", array("version" => "2.1")); +dumpall($reg); + +var_dump($reg->deletePackage("pkg2")); +dumpall($reg); + +var_dump($reg->deletePackage("pkg2")); +dumpall($reg); + +$reg->updatePackage("pkg3", array("version" => "3.1b1", "status" => "beta")); +dumpall($reg); + +$testing = $reg->checkFilemap(array_merge($files3, $files2)); +$ok = ($testing == array('pkg3-1.php' => 'pkg3', 'pkg3' . DIRECTORY_SEPARATOR . 'pkg3-2.php' => 'pkg3')); +echo 'filemap OK? ' . ($ok ? "yes\n" : "no\n"); +if (!$ok) { + var_dump($testing); +} + +$reg->updatePackage("pkg3", array("filelist" => $files3_new)); +dumpall($reg); + +print "tests done\n"; +?> +--EXPECT-- +creating registry object +dumping registry... +channel pear: +dump done +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +dump done +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg2: version="2.0" filelist=array(pkg2-1.php[role=php],pkg2-2.php[role=php,baseinstalldir=pkg2]) +pkg3: version="3.0" filelist=array(pkg3-1.php[role=php],pkg3-2.php[role=php,baseinstalldir=pkg3]) +dump done +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg2: version="2.1" filelist=array(pkg2-1.php[role=php],pkg2-2.php[role=php,baseinstalldir=pkg2]) +pkg3: version="3.0" filelist=array(pkg3-1.php[role=php],pkg3-2.php[role=php,baseinstalldir=pkg3]) +dump done +bool(true) +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg3: version="3.0" filelist=array(pkg3-1.php[role=php],pkg3-2.php[role=php,baseinstalldir=pkg3]) +dump done +bool(false) +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg3: version="3.0" filelist=array(pkg3-1.php[role=php],pkg3-2.php[role=php,baseinstalldir=pkg3]) +dump done +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg3: version="3.1b1" filelist=array(pkg3-1.php[role=php],pkg3-2.php[role=php,baseinstalldir=pkg3]) status="beta" +dump done +filemap OK? yes +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg3: version="3.1b1" filelist=array(pkg3-3.php[role=php,baseinstalldir=pkg3],pkg3-4.php[role=php]) status="beta" +dump done +tests done diff --git a/pear/tests/pear_registry_1.1.phpt b/pear/tests/pear_registry_1.1.phpt new file mode 100644 index 000000000..5af863607 --- /dev/null +++ b/pear/tests/pear_registry_1.1.phpt @@ -0,0 +1,290 @@ +--TEST-- +PEAR_Registry v1.1 +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +$statedir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'registry_tester'; +if (file_exists($statedir)) { + // don't delete existing directories! + echo 'skip'; +} +include_once 'PEAR/Registry.php'; +$pv = phpversion() . ''; +$av = $pv{0} == '4' ? 'apiversion' : 'apiVersion'; +if (!in_array($av, get_class_methods('PEAR_Registry'))) { + echo 'skip'; +} +if (PEAR_Registry::apiVersion() != '1.1') { + echo 'skip'; +} +?> +--FILE-- +<?php +error_reporting(E_ALL); +include_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'pear_registry_inc.php.inc'; +include_once "PEAR/Registry.php"; +PEAR::setErrorHandling(PEAR_ERROR_DIE, "%s\n"); +$statedir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'registry_tester'; +cleanall(); + +$files1 = array( + "pkg1-1.php" => array( + "role" => "php", + ), + "pkg1-2.php" => array( + "role" => "php", + "baseinstalldir" => "pkg1", + ), + ); +$files1_test = array( + "pkg12-1.php" => array( + "role" => "php", + ), + "pkg12-2.php" => array( + "role" => "php", + "baseinstalldir" => "pkg1", + ), + ); +$files1_grnok = array( + "pkg32-1.php" => array( + "role" => "php", + ), + "pkg32-2.php" => array( + "role" => "php", + "baseinstalldir" => "pkg1", + ), + ); +$files2 = array( + "pkg2-1.php" => array( + "role" => "php", + ), + "pkg2-2.php" => array( + "role" => "php", + "baseinstalldir" => "pkg2", + ), + ); +$files3 = array( + "pkg3-1.php" => array( + "role" => "php", + ), + "pkg3-2.php" => array( + "role" => "php", + "baseinstalldir" => "pkg3", + ), + ); +$files3_new = array( + "pkg3-3.php" => array( + "role" => "php", + "baseinstalldir" => "pkg3", + ), + "pkg3-4.php" => array( + "role" => "php", + ), + ); + +print "creating registry object\n"; +$reg = new PEAR_Registry($statedir); +dumpall($reg); + +$reg->addPackage("pkg1", array("name" => "pkg1", "version" => "1.0", "filelist" => $files1)); +dumpall($reg); + +$reg->addPackage("pkg2", array("name" => "pkg2", "version" => "2.0", "filelist" => $files2)); +$reg->addPackage("pkg3", array("name" => "pkg3", "version" => "3.0", "filelist" => $files3)); +dumpall($reg); + +$reg->updatePackage("pkg2", array("version" => "2.1")); +dumpall($reg); + +var_dump($reg->deletePackage("pkg2")); +dumpall($reg); + +var_dump($reg->deletePackage("pkg2")); +dumpall($reg); + +$reg->updatePackage("pkg3", array("version" => "3.1b1", "status" => "beta")); +dumpall($reg); + +$testing = $reg->checkFilemap(array_merge($files3, $files2)); +$ok = ($testing == array('pkg3-1.php' => 'pkg3', 'pkg3' . DIRECTORY_SEPARATOR . 'pkg3-2.php' => 'pkg3')); +echo 'filemap OK? ' . ($ok ? "yes\n" : "no\n"); +if (!$ok) { + var_dump($testing); +} + +$reg->updatePackage("pkg3", array("filelist" => $files3_new)); +dumpall($reg); + +echo "testing channel registry\n\n"; + +print "test add channel\n"; + +require_once 'PEAR/ChannelFile.php'; +$chan = new PEAR_ChannelFile; + +$chan->setName('test'); +$chan->setServer('pear.php.net'); +$chan->setSummary('hello'); +$reg->addChannel($chan); + +dumpall($reg); + +echo "test add bad channel\n"; +$chan = new PEAR_ChannelFile; + +$chan->setServer('pear.php.net'); +$chan->setSummary('hello'); +$reg->addChannel($chan); + +dumpall($reg); + +print "test add good package\n"; +$reg->addPackage('pkg1', array('name' => 'pkg1', 'version' => '1.0', 'filelist' => $files1_test), 'test'); + +dumpall($reg); + +echo "test add package with unknown channel\n"; + +var_dump($reg->addPackage('pkg2', array('name'=> 'pkg2', 'version' => '1.0', 'filelist' => $files1_grnok), 'grnok')); + +dumpall($reg); + +echo "test channel exists\n"; + +var_dump($reg->channelExists('test')); +var_dump($reg->channelExists('pear')); +var_dump($reg->channelExists('grnok')); + +echo "testing restart with new object\n"; + +unset($reg); + +$reg = &new PEAR_Registry($statedir); + +dumpall($reg); + +echo "test delete channel with packages\n"; +var_dump($reg->deleteChannel('test')); + +dumpall($reg); + +echo "test delete channel with no packages\n"; +$reg->deletePackage('pkg1', 'test'); + +var_dump($reg->deleteChannel('test')); + +dumpall($reg); + +print "tests done\n"; +?> +--EXPECT-- +creating registry object +dumping registry... +channel pear: +dump done +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +dump done +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg2: version="2.0" filelist=array(pkg2-1.php[role=php],pkg2-2.php[role=php,baseinstalldir=pkg2]) +pkg3: version="3.0" filelist=array(pkg3-1.php[role=php],pkg3-2.php[role=php,baseinstalldir=pkg3]) +dump done +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg2: version="2.1" filelist=array(pkg2-1.php[role=php],pkg2-2.php[role=php,baseinstalldir=pkg2]) +pkg3: version="3.0" filelist=array(pkg3-1.php[role=php],pkg3-2.php[role=php,baseinstalldir=pkg3]) +dump done +bool(true) +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg3: version="3.0" filelist=array(pkg3-1.php[role=php],pkg3-2.php[role=php,baseinstalldir=pkg3]) +dump done +bool(false) +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg3: version="3.0" filelist=array(pkg3-1.php[role=php],pkg3-2.php[role=php,baseinstalldir=pkg3]) +dump done +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg3: version="3.1b1" filelist=array(pkg3-1.php[role=php],pkg3-2.php[role=php,baseinstalldir=pkg3]) status="beta" +dump done +filemap OK? yes +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg3: version="3.1b1" filelist=array(pkg3-3.php[role=php,baseinstalldir=pkg3],pkg3-4.php[role=php]) status="beta" +dump done +testing channel registry + +test add channel +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg3: version="3.1b1" filelist=array(pkg3-3.php[role=php,baseinstalldir=pkg3],pkg3-4.php[role=php]) status="beta" +channel test: +dump done +test add bad channel +caught ErrorStack error: +message: Missing channel name +code: 6 +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg3: version="3.1b1" filelist=array(pkg3-3.php[role=php,baseinstalldir=pkg3],pkg3-4.php[role=php]) status="beta" +channel test: +dump done +test add good package +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg3: version="3.1b1" filelist=array(pkg3-3.php[role=php,baseinstalldir=pkg3],pkg3-4.php[role=php]) status="beta" +channel test: +pkg1: version="1.0" filelist=array(pkg12-1.php[role=php],pkg12-2.php[role=php,baseinstalldir=pkg1]) +dump done +test add package with unknown channel +bool(false) +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg3: version="3.1b1" filelist=array(pkg3-3.php[role=php,baseinstalldir=pkg3],pkg3-4.php[role=php]) status="beta" +channel test: +pkg1: version="1.0" filelist=array(pkg12-1.php[role=php],pkg12-2.php[role=php,baseinstalldir=pkg1]) +dump done +test channel exists +bool(true) +bool(true) +bool(false) +testing restart with new object +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg3: version="3.1b1" filelist=array(pkg3-3.php[role=php,baseinstalldir=pkg3],pkg3-4.php[role=php]) status="beta" +channel test: +pkg1: version="1.0" filelist=array(pkg12-1.php[role=php],pkg12-2.php[role=php,baseinstalldir=pkg1]) +dump done +test delete channel with packages +bool(false) +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg3: version="3.1b1" filelist=array(pkg3-3.php[role=php,baseinstalldir=pkg3],pkg3-4.php[role=php]) status="beta" +channel test: +pkg1: version="1.0" filelist=array(pkg12-1.php[role=php],pkg12-2.php[role=php,baseinstalldir=pkg1]) +dump done +test delete channel with no packages +bool(true) +dumping registry... +channel pear: +pkg1: version="1.0" filelist=array(pkg1-1.php[role=php],pkg1-2.php[role=php,baseinstalldir=pkg1]) +pkg3: version="3.1b1" filelist=array(pkg3-3.php[role=php,baseinstalldir=pkg3],pkg3-4.php[role=php]) status="beta" +dump done +tests done diff --git a/pear/tests/pear_registry_inc.php.inc b/pear/tests/pear_registry_inc.php.inc new file mode 100644 index 000000000..7cc395f08 --- /dev/null +++ b/pear/tests/pear_registry_inc.php.inc @@ -0,0 +1,74 @@ +<?php + +// ------------------------------------------------------------------------- // + +function cleanall($dir = null) +{ + if ($dir !== null) { + $statedir = $dir; + } else { + $statedir = $GLOBALS['statedir']; + } + if (file_exists($statedir)) { + $dp = opendir($statedir); + while ($ent = readdir($dp)) { + if (in_array($ent, array('.', '..'))) { + continue; + } + if (is_dir($statedir . DIRECTORY_SEPARATOR . $ent)) { + cleanall($statedir . DIRECTORY_SEPARATOR . $ent); + continue; + } + unlink($statedir . DIRECTORY_SEPARATOR . $ent); + } + closedir($dp); + rmdir($statedir); + } +} + + +function dumpall(&$reg) +{ + print "dumping registry...\n"; + $infos = $reg->allPackageInfo(); + foreach ($infos as $channel => $info) { + echo "channel $channel:\n"; + foreach ($info as $pkg) { + print $pkg["name"] . ":"; + unset($pkg["name"]); + foreach ($pkg as $k => $v) { + if ($k == '_lastmodified') continue; + if (is_array($v) && $k == 'filelist') { + print " $k=array("; + $i = 0; + foreach ($v as $k2 => $v2) { + if ($i++ > 0) print ","; + print "{$k2}["; + $j = 0; + foreach ($v2 as $k3 => $v3) { + if ($j++ > 0) print ","; + print "$k3=$v3"; + } + print "]"; + } + print ")"; + } else { + print " $k=\"$v\""; + } + } + print "\n"; + } + } + print "dump done\n"; +} + +require_once 'PEAR/ErrorStack.php'; +function dump_error($err) +{ + echo "caught ErrorStack error:\n"; + echo "message: ". $err['message'] . "\n"; + echo "code: ". $err['code'] . "\n"; +} +PEAR_ErrorStack::setDefaultCallback('dump_error'); +register_shutdown_function('cleanall'); +?>
\ No newline at end of file diff --git a/pear/tests/pear_system.phpt b/pear/tests/pear_system.phpt new file mode 100644 index 000000000..591b3b648 --- /dev/null +++ b/pear/tests/pear_system.phpt @@ -0,0 +1,110 @@ +--TEST-- +System commands tests +--SKIPIF-- +<?php +if (!getenv('PHP_PEAR_RUNTESTS')) { + echo 'skip'; +} +?> +--FILE-- +<?php +error_reporting(E_ALL); +require_once 'System.php'; + +$sep = DIRECTORY_SEPARATOR; +$ereg_sep = $sep; +if (OS_WINDOWS) { + $ereg_sep .= $sep; +} +/******************* + mkDir +********************/ +// Single directory creation +System::mkDir('singledir'); +if( !is_dir('singledir') ){ + print "System::mkDir('singledir'); failed\n"; +} +System::rm('singledir'); + +// Multiple directory creation +System::mkDir('dir1 dir2 dir3'); +if (!@is_dir('dir1') || !@is_dir('dir2') || !@is_dir('dir3')) { + print "System::mkDir('dir1 dir2 dir3'); failed\n"; +} + +// Parent creation without "-p" fail +if (@System::mkDir("dir4{$sep}dir3")) { + print "System::mkDir(\"dir4{$sep}dir3\") did not failed\n"; +} + +// Create a directory which is a file already fail +touch('file4'); +$res = @System::mkDir('file4 dir5'); +if ($res) { + print "System::mkDir('file4 dir5') did not failed\n"; +} +if (!@is_dir('dir5')) { + print "System::mkDir('file4 dir5') failed\n"; +} + +// Parent directory creation +System::mkDir("-p dir2{$sep}dir21 dir6{$sep}dir61{$sep}dir611"); +if (!@is_dir("dir2{$sep}dir21") || !@is_dir("dir6{$sep}dir61{$sep}dir611")) { + print "System::mkDir(\"-p dir2{$sep}dir21 dir6{$sep}dir61{$sep}dir611\")); failed\n"; +} + +/******************* + mkTemp +********************/ + +// Create a temporal file with "tst" as filename prefix +$tmpfile = System::mkTemp('tst'); +$tmpenv = str_replace($sep, $ereg_sep, System::tmpDir()); +if (!@is_file($tmpfile) || !ereg("^$tmpenv{$ereg_sep}tst", $tmpfile)) { + print "System::mkTemp('tst') failed\n"; + var_dump(is_file($tmpfile), $tmpfile, "^$tmpenv{$ereg_sep}tst", !ereg("^$tmpenv{$ereg_sep}tst", $tmpfile)); +} + +// Create a temporal dir in "dir1" with default prefix "tmp" +$tmpdir = System::mkTemp('-d -t dir1'); +if (!@is_dir($tmpdir) || !ereg("^dir1{$ereg_sep}tmp", $tmpdir)) { + print "System::mkTemp('-d -t dir1') failed\n"; +} + +/******************* + rm +********************/ + +// Try to delete a dir without "-r" option +if (@System::rm('dir1')) { + print "System::rm('dir1') did not fail\n"; +} + +// Multiple and recursive delete +$del = "dir1 dir2 dir3 file4 dir5 dir6"; +if (!@System::rm("-r $del")) { + print "System::rm(\"-r $del\") failed\n"; +} + +/******************* + which +********************/ + +if (OS_UNIX) { + if (System::which('ls') != '/bin/ls') { + print "System::which('ls') failed\n"; + } + if (System::which('i_am_not_a_command')) { + print "System::which('i_am_not_a_command') did not failed\n"; + } +} // XXX Windows test + +/******************* + cat +********************/ +// Missing tests yet + +print "end\n"; +?> +--EXPECT-- +end diff --git a/pear/tests/php.ini b/pear/tests/php.ini new file mode 100644 index 000000000..c75c9b4f1 --- /dev/null +++ b/pear/tests/php.ini @@ -0,0 +1,2 @@ +; php.ini for PEAR tests +include_path=.. diff --git a/pear/tests/php_dump.php.inc b/pear/tests/php_dump.php.inc new file mode 100644 index 000000000..4f7a66629 --- /dev/null +++ b/pear/tests/php_dump.php.inc @@ -0,0 +1,57 @@ +<?php +class PHP_Dump { + var $_var; + function PHP_Dump($var) + { + $this->_var = $var; + } + + function toPHP() + { + return $this->_toUnknown($this->_var); + } + + function _toUnknown($var, $indent = ' ') + { + switch (gettype($var)) { + case 'array' : + return $this->_toArray($var, $indent); + case 'boolean' : + return $this->_toBool($var, $indent); + case 'double' : + case 'integer' : + return $this->_toNumber($var, $indent); + case 'NULL' : + return "{$indent}null"; + case 'string' : + return $this->_toString($var, $indent); + } + } + + function _toString($var, $indent) + { + return $indent . '"' . addslashes($var) . '"'; + } + + function _toBool($var, $indent) + { + return $indent . ($var ? 'true' : 'false'); + } + + function _toNumber($var, $indent) + { + return $indent . $var; + } + + function _toArray($var, $indent = ' ') + { + $ret = $indent . "array(\n"; + foreach ($var as $key => $value) { + $ret .= $indent . ((is_int($key) || is_double($key)) ? $key : "'$key'") . " =>\n"; + $ret .= $this->_toUnknown($value, "$indent ") . ",\n"; + } + $ret .= $indent . ')'; + return $ret; + } +} +?>
\ No newline at end of file diff --git a/pear/tests/pkg1-1.1.tgz b/pear/tests/pkg1-1.1.tgz Binary files differnew file mode 100644 index 000000000..fb1b65ffe --- /dev/null +++ b/pear/tests/pkg1-1.1.tgz diff --git a/pear/tests/pkg1-2.0b1.tgz b/pear/tests/pkg1-2.0b1.tgz Binary files differnew file mode 100644 index 000000000..bc16f70e0 --- /dev/null +++ b/pear/tests/pkg1-2.0b1.tgz diff --git a/pear/tests/pkg2-1.1.tgz b/pear/tests/pkg2-1.1.tgz Binary files differnew file mode 100644 index 000000000..86b5d16c4 --- /dev/null +++ b/pear/tests/pkg2-1.1.tgz diff --git a/pear/tests/pkg3-1.1.tgz b/pear/tests/pkg3-1.1.tgz Binary files differnew file mode 100644 index 000000000..f3746443d --- /dev/null +++ b/pear/tests/pkg3-1.1.tgz diff --git a/pear/tests/pkg3-1.4.tgz b/pear/tests/pkg3-1.4.tgz Binary files differnew file mode 100644 index 000000000..31c9825ef --- /dev/null +++ b/pear/tests/pkg3-1.4.tgz diff --git a/pear/tests/pkg4-1.1.tgz b/pear/tests/pkg4-1.1.tgz Binary files differnew file mode 100644 index 000000000..08423ae28 --- /dev/null +++ b/pear/tests/pkg4-1.1.tgz diff --git a/pear/tests/pkg4AndAHalf-1.3.tgz b/pear/tests/pkg4AndAHalf-1.3.tgz Binary files differnew file mode 100644 index 000000000..57792b1bd --- /dev/null +++ b/pear/tests/pkg4AndAHalf-1.3.tgz diff --git a/pear/tests/pkg5-1.1.tgz b/pear/tests/pkg5-1.1.tgz Binary files differnew file mode 100644 index 000000000..37d1b50a9 --- /dev/null +++ b/pear/tests/pkg5-1.1.tgz diff --git a/pear/tests/stabilitytoolow-0.3.tgz b/pear/tests/stabilitytoolow-0.3.tgz Binary files differnew file mode 100644 index 000000000..a7d6a8676 --- /dev/null +++ b/pear/tests/stabilitytoolow-0.3.tgz diff --git a/pear/tests/stabilitytoolow-0.5.tgz b/pear/tests/stabilitytoolow-0.5.tgz Binary files differnew file mode 100644 index 000000000..28f88baec --- /dev/null +++ b/pear/tests/stabilitytoolow-0.5.tgz diff --git a/pear/tests/stabilitytoolow-0.6beta.tgz b/pear/tests/stabilitytoolow-0.6beta.tgz Binary files differnew file mode 100644 index 000000000..05dc8f9a9 --- /dev/null +++ b/pear/tests/stabilitytoolow-0.6beta.tgz diff --git a/pear/tests/stabilitytoolow-1.0b1.tgz b/pear/tests/stabilitytoolow-1.0b1.tgz Binary files differnew file mode 100644 index 000000000..1aefb6b58 --- /dev/null +++ b/pear/tests/stabilitytoolow-1.0b1.tgz diff --git a/pear/tests/stabilitytoolow-2.0a1.tgz b/pear/tests/stabilitytoolow-2.0a1.tgz Binary files differnew file mode 100644 index 000000000..d0f89060a --- /dev/null +++ b/pear/tests/stabilitytoolow-2.0a1.tgz diff --git a/pear/tests/stabilitytoolow-2.0b1.tgz b/pear/tests/stabilitytoolow-2.0b1.tgz Binary files differnew file mode 100644 index 000000000..890d2378d --- /dev/null +++ b/pear/tests/stabilitytoolow-2.0b1.tgz diff --git a/pear/tests/stabilitytoolow-2.0dev.tgz b/pear/tests/stabilitytoolow-2.0dev.tgz Binary files differnew file mode 100644 index 000000000..f5564ad8f --- /dev/null +++ b/pear/tests/stabilitytoolow-2.0dev.tgz diff --git a/pear/tests/stabilitytoolow-3.0dev.tgz b/pear/tests/stabilitytoolow-3.0dev.tgz Binary files differnew file mode 100644 index 000000000..061164e34 --- /dev/null +++ b/pear/tests/stabilitytoolow-3.0dev.tgz diff --git a/pear/tests/system.input b/pear/tests/system.input new file mode 100644 index 000000000..9c6bece15 --- /dev/null +++ b/pear/tests/system.input @@ -0,0 +1 @@ +a:1:{s:13:"master_server";s:12:"pear.php.net";}
\ No newline at end of file diff --git a/pear/tests/test-pkg6/conflictpackage.xml b/pear/tests/test-pkg6/conflictpackage.xml new file mode 100644 index 000000000..ee99a0388 --- /dev/null +++ b/pear/tests/test-pkg6/conflictpackage.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0"> + <package version="1.0"> + <name>pkg6conflict</name> + <summary>required test for PEAR_Installer</summary> + <description> + fake package + </description> + <license>PHP License</license> + <maintainers> + <maintainer> + <user>fakeuser</user> + <name>Joe Shmoe</name> + <email>nobody@example.com</email> + <role>lead</role> + </maintainer> + </maintainers> + <release> + <version>1.1</version> + <date>2003-09-09</date> + <state>stable</state> + <notes> + required dependency test + </notes> + <filelist> + <dir name="/" baseinstalldir="groob" role="php"> + <file>zoorb1.php</file> + <dir name="goompness" role="php"> + <file>oggbrzitzkee.php</file> + <file>Mopreeb.php</file> + </dir> + </dir> + </filelist> + </release> + </package> diff --git a/pear/tests/test-pkg6/conflictpackage2.xml b/pear/tests/test-pkg6/conflictpackage2.xml new file mode 100644 index 000000000..aed89651b --- /dev/null +++ b/pear/tests/test-pkg6/conflictpackage2.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.1"> + <package version="1.1"> + <name channel="groob">pkg6conflict</name> + <summary>required test for PEAR_Installer</summary> + <description> + fake package + </description> + <license>PHP License</license> + <maintainers> + <maintainer> + <user>fakeuser</user> + <name>Joe Shmoe</name> + <email>nobody@example.com</email> + <role>lead</role> + </maintainer> + </maintainers> + <release> + <version>1.1</version> + <date>2003-09-09</date> + <state>stable</state> + <notes> + required dependency test + </notes> + <filelist> + <dir name="/" baseinstalldir="groob" role="php"> + <file>zoorb1.php</file> + <dir name="goompness" role="php"> + <file>oggbrzitzkee.php</file> + <file>Mopreeb.php</file> + <file role="data">test.dat</file> + </dir> + </dir> + </filelist> + </release> + </package> diff --git a/pear/tests/test-pkg6/goompness/Mopreeb.php b/pear/tests/test-pkg6/goompness/Mopreeb.php new file mode 100644 index 000000000..0d447b850 --- /dev/null +++ b/pear/tests/test-pkg6/goompness/Mopreeb.php @@ -0,0 +1,11 @@ +<?php + +/** + * + * + * @version $Id: Mopreeb.php,v 1.1 2003/12/01 04:51:20 cellog Exp $ + * @copyright 2003 + **/ +class test1{} + +?>
\ No newline at end of file diff --git a/pear/tests/test-pkg6/goompness/oggbrzitzkee.php b/pear/tests/test-pkg6/goompness/oggbrzitzkee.php new file mode 100644 index 000000000..7ff230acb --- /dev/null +++ b/pear/tests/test-pkg6/goompness/oggbrzitzkee.php @@ -0,0 +1,11 @@ +<?php + +/** + * + * + * @version $Id: oggbrzitzkee.php,v 1.1 2003/12/01 04:51:20 cellog Exp $ + * @copyright 2003 + **/ +class test1{} + +?>
\ No newline at end of file diff --git a/pear/tests/test-pkg6/goompness/test.dat b/pear/tests/test-pkg6/goompness/test.dat new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/pear/tests/test-pkg6/goompness/test.dat diff --git a/pear/tests/test-pkg6/invalidtgz.tgz b/pear/tests/test-pkg6/invalidtgz.tgz new file mode 100644 index 000000000..909d507ca --- /dev/null +++ b/pear/tests/test-pkg6/invalidtgz.tgz @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?>
+ <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0">
+ <package version="1.0">
+ <name>pkg6</name>
+ <summary>required test for PEAR_Installer</summary>
+ <description>
+ fake package
+ </description>
+ <license>PHP License</license>
+ <maintainers>
+ <maintainer>
+ <user>fakeuser</user>
+ <name>Joe Shmoe</name>
+ <email>nobody@example.com</email>
+ <role>lead</role>
+ </maintainer>
+ </maintainers>
+ <release>
+ <version>1.1</version>
+ <date>2003-09-09</date>
+ <state>stable</state>
+ <notes>
+ required dependency test
+ </notes>
+ <filelist>
+ <dir name="/" baseinstalldir="groob" role="php">
+ <file>zoorb.php</file>
+ <dir name="goompness" role="php">
+ <file>oggbrzitzkee.php</file>
+ <file>Mopreeb.php</file>
+ </dir>
+ </dir>
+ </filelist>
+ </release>
+ </package>
diff --git a/pear/tests/test-pkg6/nopackagexml.tgz b/pear/tests/test-pkg6/nopackagexml.tgz Binary files differnew file mode 100644 index 000000000..8b9d9aad0 --- /dev/null +++ b/pear/tests/test-pkg6/nopackagexml.tgz diff --git a/pear/tests/test-pkg6/package.xml b/pear/tests/test-pkg6/package.xml new file mode 100644 index 000000000..102f97276 --- /dev/null +++ b/pear/tests/test-pkg6/package.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.0"> + <package version="1.0"> + <name>pkg6</name> + <summary>required test for PEAR_Installer</summary> + <description> + fake package + </description> + <license>PHP License</license> + <maintainers> + <maintainer> + <user>fakeuser</user> + <name>Joe Shmoe</name> + <email>nobody@example.com</email> + <role>lead</role> + </maintainer> + </maintainers> + <release> + <version>1.1</version> + <date>2003-09-09</date> + <state>stable</state> + <notes> + required dependency test + </notes> + <filelist> + <dir name="/" baseinstalldir="groob" role="php"> + <file>zoorb.php</file> + <dir name="goompness" role="php"> + <file>oggbrzitzkee.php</file> + <file>Mopreeb.php</file> + </dir> + </dir> + </filelist> + </release> + </package> diff --git a/pear/tests/test-pkg6/package2.xml b/pear/tests/test-pkg6/package2.xml new file mode 100644 index 000000000..ea015b018 --- /dev/null +++ b/pear/tests/test-pkg6/package2.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.1"> + <package version="1.1"> + <name channel="frob">pkg6</name> + <summary>required test for PEAR_Installer</summary> + <description> + fake package + </description> + <license>PHP License</license> + <maintainers> + <maintainer> + <user>fakeuser</user> + <name>Joe Shmoe</name> + <email>nobody@example.com</email> + <role>lead</role> + </maintainer> + </maintainers> + <release> + <version>1.1</version> + <date>2003-09-09</date> + <state>stable</state> + <notes> + required dependency test + </notes> + <filelist> + <dir name="/" baseinstalldir="groob" role="php"> + <file>zoorb.php</file> + <dir name="goompness" role="php"> + <file>oggbrzitzkee.php</file> + <file>Mopreeb.php</file> + <file role="data">test.dat</file> + </dir> + </dir> + </filelist> + </release> + </package> diff --git a/pear/tests/test-pkg6/package2_invalid.xml b/pear/tests/test-pkg6/package2_invalid.xml new file mode 100644 index 000000000..1dfc1ebfc --- /dev/null +++ b/pear/tests/test-pkg6/package2_invalid.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!DOCTYPE package SYSTEM "http://pear.php.net/dtd/package-1.1"> + <package version="1.1"> + <name channel="gorp">pkg6</name> + <summary>required test for PEAR_Installer</summary> + <description> + fake package + </description> + <license>PHP License</license> + <maintainers> + <maintainer> + <user>fakeuser</user> + <name>Joe Shmoe</name> + <email>nobody@example.com</email> + <role>lead</role> + </maintainer> + </maintainers> + <release> + <version>1.1</version> + <date>2003-09-09</date> + <state>stable</state> + <notes> + required dependency test + </notes> + <filelist> + <dir name="/" baseinstalldir="groob" role="php"> + <file>zoorb.php</file> + <dir name="goompness" role="php"> + <file>oggbrzitzkee.php</file> + <file>Mopreeb.php</file> + </dir> + </dir> + </filelist> + </release> + </package> diff --git a/pear/tests/test-pkg6/pkg6-1.1.tgz b/pear/tests/test-pkg6/pkg6-1.1.tgz Binary files differnew file mode 100644 index 000000000..09868cab4 --- /dev/null +++ b/pear/tests/test-pkg6/pkg6-1.1.tgz diff --git a/pear/tests/test-pkg6/pkg6-2.0b1.tgz b/pear/tests/test-pkg6/pkg6-2.0b1.tgz Binary files differnew file mode 100644 index 000000000..45e8877d6 --- /dev/null +++ b/pear/tests/test-pkg6/pkg6-2.0b1.tgz diff --git a/pear/tests/test-pkg6/zoorb.php b/pear/tests/test-pkg6/zoorb.php new file mode 100644 index 000000000..cc5717e8c --- /dev/null +++ b/pear/tests/test-pkg6/zoorb.php @@ -0,0 +1,11 @@ +<?php + +/** + * + * + * @version $Id: zoorb.php,v 1.1 2003/12/01 04:51:21 cellog Exp $ + * @copyright 2003 + **/ +class test1{} + +?>
\ No newline at end of file diff --git a/pear/tests/testdownload.tgz b/pear/tests/testdownload.tgz Binary files differnew file mode 100644 index 000000000..0ddc3df36 --- /dev/null +++ b/pear/tests/testdownload.tgz diff --git a/pear/tests/toonew.conf b/pear/tests/toonew.conf new file mode 100644 index 000000000..6f0c72fe4 --- /dev/null +++ b/pear/tests/toonew.conf @@ -0,0 +1,2 @@ +#PEAR_Config 2.0 +master_server = pear.php.net diff --git a/pear/tests/user.input b/pear/tests/user.input new file mode 100644 index 000000000..c856afcf9 --- /dev/null +++ b/pear/tests/user.input @@ -0,0 +1 @@ +a:0:{}
\ No newline at end of file diff --git a/pear/tests/user2.input b/pear/tests/user2.input new file mode 100644 index 000000000..ac9a8afc0 --- /dev/null +++ b/pear/tests/user2.input @@ -0,0 +1 @@ +a:1:{s:7:"verbose";i:2;}
\ No newline at end of file diff --git a/pear/tests/user3.input b/pear/tests/user3.input new file mode 100644 index 000000000..e4ff5f466 --- /dev/null +++ b/pear/tests/user3.input @@ -0,0 +1 @@ +a:2:{s:7:"verbose";i:60;s:10:"__channels";a:2:{s:5:"test1";a:1:{s:7:"verbose";i:70;}s:5:"test2";a:1:{s:7:"verbose";i:71;}}}
\ No newline at end of file |