summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlsces <lester@lsces.co.uk>2026-04-05 11:10:49 +0100
committerlsces <lester@lsces.co.uk>2026-04-05 11:13:10 +0100
commit967669a49532860ec50931781b58d0f28975c63c (patch)
tree87422c809f35654cf18e371672bd0ce5b95896ac
parent3149004cd95b393e1de129c0087f8f058d0df264 (diff)
downloadutil-967669a49532860ec50931781b58d0f28975c63c.tar.gz
util-967669a49532860ec50931781b58d0f28975c63c.tar.bz2
util-967669a49532860ec50931781b58d0f28975c63c.zip
PEAR changes to support PHP8.4 .. Ideally need a generic package that is more modern?
-rwxr-xr-x[-rw-r--r--]includes/pear/Archive/Tar.php2877
-rwxr-xr-x[-rw-r--r--]includes/pear/HTTP.php47
-rwxr-xr-x[-rw-r--r--]includes/pear/HTTP/Download.php6
-rwxr-xr-x[-rw-r--r--]includes/pear/HTTP/Header.php17
-rwxr-xr-xincludes/pear/HTTP/Request.php1514
-rwxr-xr-xincludes/pear/HTTP2.php662
-rwxr-xr-xincludes/pear/HTTP2/Exception.php28
-rwxr-xr-x[-rw-r--r--]includes/pear/System.php50
8 files changed, 4009 insertions, 1192 deletions
diff --git a/includes/pear/Archive/Tar.php b/includes/pear/Archive/Tar.php
index 61eff98..03daa39 100644..100755
--- a/includes/pear/Archive/Tar.php
+++ b/includes/pear/Archive/Tar.php
@@ -30,85 +30,127 @@
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- *
- * @category File_Formats
- * @package Archive_Tar
- * @author Vincent Blavet <vincent@phpconcept.net>
- * @copyright 1997-2008 The Authors
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Tar.php 295988 2010-03-09 08:39:37Z mrook $
- * @link http://pear.php.net/package/Archive_Tar
+ * @category File_Formats
+ * @package Archive_Tar
+ * @author Vincent Blavet <vincent@phpconcept.net>
+ * @copyright 1997-2010 The Authors
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Archive_Tar
*/
-require_once 'PEAR.php';
+// If the PEAR class cannot be loaded via the autoloader,
+// then try to require_once it from the PHP include path.
+if (!class_exists('PEAR')) {
+ require_once 'PEAR.php';
+}
+define('ARCHIVE_TAR_ATT_SEPARATOR', 90001);
+define('ARCHIVE_TAR_END_BLOCK', pack("a512", ''));
-define ('ARCHIVE_TAR_ATT_SEPARATOR', 90001);
-define ('ARCHIVE_TAR_END_BLOCK', pack("a512", ''));
+if (!function_exists('gzopen') && function_exists('gzopen64')) {
+ function gzopen($filename, $mode, $use_include_path = 0)
+ {
+ return gzopen64($filename, $mode, $use_include_path);
+ }
+}
+
+if (!function_exists('gztell') && function_exists('gztell64')) {
+ function gztell($zp)
+ {
+ return gztell64($zp);
+ }
+}
+
+if (!function_exists('gzseek') && function_exists('gzseek64')) {
+ function gzseek($zp, $offset, $whence = SEEK_SET)
+ {
+ return gzseek64($zp, $offset, $whence);
+ }
+}
/**
-* Creates a (compressed) Tar archive
-*
-* @author Vincent Blavet <vincent@phpconcept.net>
-* @version $Revision: 295988 $
-* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
-* @package Archive_Tar
-*/
+ * Creates a (compressed) Tar archive
+ *
+ * @package Archive_Tar
+ * @author Vincent Blavet <vincent@phpconcept.net>
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @version $Revision$
+ */
class Archive_Tar extends PEAR
{
/**
- * @var string Name of the Tar
- */
- var $_tarname='';
+ * @var string Name of the Tar
+ */
+ public $_tarname = '';
+
+ /**
+ * @var boolean if true, the Tar file will be gzipped
+ */
+ public $_compress = false;
/**
- * @var boolean if true, the Tar file will be gzipped
- */
- var $_compress=false;
+ * @var string Type of compression : 'none', 'gz', 'bz2' or 'lzma2'
+ */
+ public $_compress_type = 'none';
/**
- * @var string Type of compression : 'none', 'gz' or 'bz2'
- */
- var $_compress_type='none';
+ * @var string Explode separator
+ */
+ public $_separator = ' ';
/**
- * @var string Explode separator
- */
- var $_separator=' ';
+ * @var file descriptor
+ */
+ public $_file = 0;
/**
- * @var file descriptor
- */
- var $_file=0;
+ * @var string Local Tar name of a remote Tar (http:// or ftp://)
+ */
+ public $_temp_tarname = '';
/**
- * @var string Local Tar name of a remote Tar (http:// or ftp://)
- */
- var $_temp_tarname='';
+ * @var string regular expression for ignoring files or directories
+ */
+ public $_ignore_regexp = '';
/**
- * @var string regular expression for ignoring files or directories
- */
- var $_ignore_regexp='';
+ * @var object PEAR_Error object
+ */
+ public $error_object = null;
- // {{{ 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)
+ * Format for data extraction
+ *
+ * @var string
+ */
+ public $_fmt = '';
+
+ /**
+ * @var int Length of the read buffer in bytes
+ */
+ protected $buffer_length;
+
+ /**
+ * Archive_Tar Class constructor. This flavour of the constructor only
+ * declare a new Archive_Tar object, identifying it by the name of the
+ * tar file.
+ * If the compress argument is set the tar will be read or created as a
+ * gzip or bz2 compressed TAR file.
+ *
+ * @param string $p_tarname The name of the tar archive to create
+ * @param string $p_compress can be null, 'gz', 'bz2' or 'lzma2'. This
+ * parameter indicates if gzip, bz2 or lzma2 compression
+ * is required. For compatibility reason the
+ * boolean value 'true' means 'gz'.
+ * @param int $buffer_length Length of the read buffer in bytes
+ *
+ * @return bool
+ */
+ public function __construct($p_tarname, $p_compress = null, $buffer_length = 512)
{
- $this->PEAR();
+ parent::__construct();
+
$this->_compress = false;
$this->_compress_type = 'none';
if (($p_compress === null) || ($p_compress == '')) {
@@ -120,10 +162,13 @@ class Archive_Tar extends PEAR
if ($data == "\37\213") {
$this->_compress = true;
$this->_compress_type = 'gz';
- // No sure it's enought for a magic code ....
+ // No sure it's enought for a magic code ....
} elseif ($data == "BZ") {
$this->_compress = true;
$this->_compress_type = 'bz2';
+ } elseif (file_get_contents($p_tarname, false, null, 1, 4) == '7zXZ') {
+ $this->_compress = true;
+ $this->_compress_type = 'lzma2';
}
}
} else {
@@ -133,114 +178,152 @@ class Archive_Tar extends PEAR
$this->_compress = true;
$this->_compress_type = 'gz';
} elseif ((substr($p_tarname, -3) == 'bz2') ||
- (substr($p_tarname, -2) == 'bz')) {
+ (substr($p_tarname, -2) == 'bz')
+ ) {
$this->_compress = true;
$this->_compress_type = 'bz2';
+ } else {
+ if (substr($p_tarname, -2) == 'xz') {
+ $this->_compress = true;
+ $this->_compress_type = 'lzma2';
+ }
}
}
} else {
if (($p_compress === true) || ($p_compress == 'gz')) {
$this->_compress = true;
$this->_compress_type = 'gz';
- } else if ($p_compress == 'bz2') {
- $this->_compress = true;
- $this->_compress_type = 'bz2';
} else {
- $this->_error("Unsupported compression type '$p_compress'\n".
- "Supported types are 'gz' and 'bz2'.\n");
- return false;
+ if ($p_compress == 'bz2') {
+ $this->_compress = true;
+ $this->_compress_type = 'bz2';
+ } else {
+ if ($p_compress == 'lzma2') {
+ $this->_compress = true;
+ $this->_compress_type = 'lzma2';
+ } else {
+ $this->_error(
+ "Unsupported compression type '$p_compress'\n" .
+ "Supported types are 'gz', 'bz2' and 'lzma2'.\n"
+ );
+ return false;
+ }
+ }
}
}
$this->_tarname = $p_tarname;
- if ($this->_compress) { // assert zlib or bz2 extension support
- if ($this->_compress_type == 'gz')
+ if ($this->_compress) { // assert zlib or bz2 or xz extension support
+ if ($this->_compress_type == 'gz') {
$extname = 'zlib';
- else if ($this->_compress_type == 'bz2')
- $extname = 'bz2';
+ } else {
+ if ($this->_compress_type == 'bz2') {
+ $extname = 'bz2';
+ } else {
+ if ($this->_compress_type == 'lzma2') {
+ $extname = 'xz';
+ }
+ }
+ }
if (!extension_loaded($extname)) {
PEAR::loadExtension($extname);
}
if (!extension_loaded($extname)) {
- $this->_error("The extension '$extname' couldn't be found.\n".
- "Please make sure your version of PHP was built ".
- "with '$extname' support.\n");
+ $this->_error(
+ "The extension '$extname' couldn't be found.\n" .
+ "Please make sure your version of PHP was built " .
+ "with '$extname' support.\n"
+ );
return false;
}
}
+
+
+ if (version_compare(PHP_VERSION, "5.5.0-dev") < 0) {
+ $this->_fmt = "a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/" .
+ "a8checksum/a1typeflag/a100link/a6magic/a2version/" .
+ "a32uname/a32gname/a8devmajor/a8devminor/a131prefix";
+ } else {
+ $this->_fmt = "Z100filename/Z8mode/Z8uid/Z8gid/Z12size/Z12mtime/" .
+ "Z8checksum/Z1typeflag/Z100link/Z6magic/Z2version/" .
+ "Z32uname/Z32gname/Z8devmajor/Z8devminor/Z131prefix";
+ }
+
+
+ $this->buffer_length = $buffer_length;
}
- // }}}
- // {{{ destructor
- function _Archive_Tar()
+ public function __destruct()
{
$this->_close();
// ----- Look for a local copy to delete
- if ($this->_temp_tarname != '')
+ if ($this->_temp_tarname != '' && (bool) preg_match('/^tar[[:alnum:]]*\.tmp$/', $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)
+ * This method creates the archive file and add the files / directories
+ * that are listed in $p_filelist.
+ * If a file with the same name exist and is writable, it is replaced
+ * by the new tar.
+ * The method return false and a PEAR error text.
+ * The $p_filelist parameter can be an array of string, each string
+ * representing a filename or a directory name with their path if
+ * needed. It can also be a single string with names separated by a
+ * single blank.
+ * For each directory added in the archive, the files and
+ * sub-directories are also added.
+ * See also createModify() method for more details.
+ *
+ * @param array $p_filelist An array of filenames and directory names, or a
+ * single string with names separated by a single
+ * blank space.
+ *
+ * @return bool true on success, false on error.
+ * @see createModify()
+ */
+ public function create($p_filelist)
{
return $this->createModify($p_filelist, '', '');
}
- // }}}
- // {{{ 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)
+ * This method add the files / directories that are listed in $p_filelist in
+ * the archive. If the archive does not exist it is created.
+ * The method return false and a PEAR error text.
+ * The files and directories listed are only added at the end of the archive,
+ * even if a file with the same name is already archived.
+ * See also createModify() method for more details.
+ *
+ * @param array $p_filelist An array of filenames and directory names, or a
+ * single string with names separated by a single
+ * blank space.
+ *
+ * @return bool true on success, false on error.
+ * @see createModify()
+ * @access public
+ */
+ public function add($p_filelist)
{
return $this->addModify($p_filelist, '', '');
}
- // }}}
- // {{{ extract()
- function extract($p_path='')
+ /**
+ * @param string $p_path
+ * @param bool $p_preserve
+ * @param bool $p_symlinks
+ * @return bool
+ */
+ public function extract($p_path = '', $p_preserve = false, $p_symlinks = true)
{
- return $this->extractModify($p_path, '');
+ return $this->extractModify($p_path, '', $p_preserve, $p_symlinks);
}
- // }}}
- // {{{ listContent()
- function listContent()
+ /**
+ * @return array|int
+ */
+ public function listContent()
{
$v_list_detail = array();
@@ -254,57 +337,56 @@ class Archive_Tar extends PEAR
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='')
+ * This method creates the archive file and add the files / directories
+ * that are listed in $p_filelist.
+ * If the file already exists and is writable, it is replaced by the
+ * new tar. It is a create and not an add. If the file exists and is
+ * read-only or is a directory it is not replaced. The method return
+ * false and a PEAR error text.
+ * The $p_filelist parameter can be an array of string, each string
+ * representing a filename or a directory name with their path if
+ * needed. It can also be a single string with names separated by a
+ * single blank.
+ * The path indicated in $p_remove_dir will be removed from the
+ * memorized path of each file / directory listed when this path
+ * exists. By default nothing is removed (empty path '')
+ * The path indicated in $p_add_dir will be added at the beginning of
+ * the memorized path of each file / directory listed. However it can
+ * be set to empty ''. The adding of a path is done after the removing
+ * of path.
+ * The path add/remove ability enables the user to prepare an archive
+ * for extraction in a different path than the origin files are.
+ * See also addModify() method for file adding properties.
+ *
+ * @param array $p_filelist An array of filenames and directory names,
+ * or a single string with names separated by
+ * a single blank space.
+ * @param string $p_add_dir A string which contains a path to be added
+ * to the memorized path of each element in
+ * the list.
+ * @param string $p_remove_dir A string which contains a path to be
+ * removed from the memorized path of each
+ * element in the list, when relevant.
+ *
+ * @return boolean true on success, false on error.
+ * @see addModify()
+ */
+ public function createModify($p_filelist, $p_add_dir, $p_remove_dir = '')
{
$v_result = true;
- if (!$this->_openWrite())
+ if (!$this->_openWrite()) {
return false;
+ }
if ($p_filelist != '') {
- if (is_array($p_filelist))
+ if (is_array($p_filelist)) {
$v_list = $p_filelist;
- elseif (is_string($p_filelist))
+ } elseif (is_string($p_filelist)) {
$v_list = explode($this->_separator, $p_filelist);
- else {
+ } else {
$this->_cleanFile();
$this->_error('Invalid file list');
return false;
@@ -316,67 +398,69 @@ class Archive_Tar extends PEAR
if ($v_result) {
$this->_writeFooter();
$this->_close();
- } else
+ } 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='')
+ * This method add the files / directories listed in $p_filelist at the
+ * end of the existing archive. If the archive does not yet exists it
+ * is created.
+ * The $p_filelist parameter can be an array of string, each string
+ * representing a filename or a directory name with their path if
+ * needed. It can also be a single string with names separated by a
+ * single blank.
+ * The path indicated in $p_remove_dir will be removed from the
+ * memorized path of each file / directory listed when this path
+ * exists. By default nothing is removed (empty path '')
+ * The path indicated in $p_add_dir will be added at the beginning of
+ * the memorized path of each file / directory listed. However it can
+ * be set to empty ''. The adding of a path is done after the removing
+ * of path.
+ * The path add/remove ability enables the user to prepare an archive
+ * for extraction in a different path than the origin files are.
+ * If a file/dir is already in the archive it will only be added at the
+ * end of the archive. There is no update of the existing archived
+ * file/dir. However while extracting the archive, the last file will
+ * replace the first one. This results in a none optimization of the
+ * archive size.
+ * If a file/dir does not exist the file/dir is ignored. However an
+ * error text is send to PEAR error.
+ * If a file/dir is not readable the file/dir is ignored. However an
+ * error text is send to PEAR error.
+ *
+ * @param array $p_filelist An array of filenames and directory
+ * names, or a single string with names
+ * separated by a single blank space.
+ * @param string $p_add_dir A string which contains a path to be
+ * added to the memorized path of each
+ * element in the list.
+ * @param string $p_remove_dir A string which contains a path to be
+ * removed from the memorized path of
+ * each element in the list, when
+ * relevant.
+ *
+ * @return bool true on success, false on error.
+ */
+ public function addModify($p_filelist, $p_add_dir, $p_remove_dir = '')
{
$v_result = true;
- if (!$this->_isArchive())
- $v_result = $this->createModify($p_filelist, $p_add_dir,
- $p_remove_dir);
- else {
- if (is_array($p_filelist))
+ if (!$this->_isArchive()) {
+ $v_result = $this->createModify(
+ $p_filelist,
+ $p_add_dir,
+ $p_remove_dir
+ );
+ } else {
+ if (is_array($p_filelist)) {
$v_list = $p_filelist;
- elseif (is_string($p_filelist))
+ } elseif (is_string($p_filelist)) {
$v_list = explode($this->_separator, $p_filelist);
- else {
+ } else {
$this->_error('Invalid file list');
return false;
}
@@ -386,24 +470,41 @@ class Archive_Tar extends PEAR
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)
+ * This method add a single string as a file at the
+ * end of the existing archive. If the archive does not yet exists it
+ * is created.
+ *
+ * @param string $p_filename A string which contains the full
+ * filename path that will be associated
+ * with the string.
+ * @param string $p_string The content of the file added in
+ * the archive.
+ * @param bool|int $p_datetime A custom date/time (unix timestamp)
+ * for the file (optional).
+ * @param array $p_params An array of optional params:
+ * stamp => the datetime (replaces
+ * datetime above if it exists)
+ * mode => the permissions on the
+ * file (600 by default)
+ * type => is this a link? See the
+ * tar specification for details.
+ * (default = regular file)
+ * uid => the user ID of the file
+ * (default = 0 = root)
+ * gid => the group ID of the file
+ * (default = 0 = root)
+ *
+ * @return bool true on success, false on error.
+ */
+ public function addString($p_filename, $p_string, $p_datetime = false, $p_params = array())
{
+ $p_stamp = @$p_params["stamp"] ? $p_params["stamp"] : ($p_datetime ? $p_datetime : time());
+ $p_mode = @$p_params["mode"] ? $p_params["mode"] : 0600;
+ $p_type = @$p_params["type"] ? $p_params["type"] : "";
+ $p_uid = @$p_params["uid"] ? $p_params["uid"] : "";
+ $p_gid = @$p_params["gid"] ? $p_params["gid"] : "";
$v_result = true;
if (!$this->_isArchive()) {
@@ -413,11 +514,12 @@ class Archive_Tar extends PEAR
$this->_close();
}
- if (!$this->_openAppend())
+ if (!$this->_openAppend()) {
return false;
+ }
// Need to check the get back to the temporary file ? ....
- $v_result = $this->_addString($p_filename, $p_string);
+ $v_result = $this->_addString($p_filename, $p_string, $p_datetime, $p_params);
$this->_writeFooter();
@@ -425,131 +527,142 @@ class Archive_Tar extends PEAR
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)
+ * This method extract all the content of the archive in the directory
+ * indicated by $p_path. When relevant the memorized path of the
+ * files/dir can be modified by removing the $p_remove_path path at the
+ * beginning of the file/dir path.
+ * While extracting a file, if the directory path does not exists it is
+ * created.
+ * While extracting a file, if the file already exists it is replaced
+ * without looking for last modification date.
+ * While extracting a file, if the file already exists and is write
+ * protected, the extraction is aborted.
+ * While extracting a file, if a directory with the same name already
+ * exists, the extraction is aborted.
+ * While extracting a directory, if a file with the same name already
+ * exists, the extraction is aborted.
+ * While extracting a file/directory if the destination directory exist
+ * and is write protected, or does not exist but can not be created,
+ * the extraction is aborted.
+ * If after extraction an extracted file does not show the correct
+ * stored file size, the extraction is aborted.
+ * When the extraction is aborted, a PEAR error text is set and false
+ * is returned. However the result can be a partial extraction that may
+ * need to be manually cleaned.
+ *
+ * @param string $p_path The path of the directory where the
+ * files/dir need to by extracted.
+ * @param string $p_remove_path Part of the memorized path that can be
+ * removed if present at the beginning of
+ * the file/dir path.
+ * @param boolean $p_preserve Preserve user/group ownership of files
+ * @param boolean $p_symlinks Allow symlinks.
+ *
+ * @return boolean true on success, false on error.
+ * @see extractList()
+ */
+ public function extractModify($p_path, $p_remove_path, $p_preserve = false, $p_symlinks = true)
{
$v_result = true;
$v_list_detail = array();
if ($v_result = $this->_openRead()) {
- $v_result = $this->_extractList($p_path, $v_list_detail,
- "complete", 0, $p_remove_path);
+ $v_result = $this->_extractList(
+ $p_path,
+ $v_list_detail,
+ "complete",
+ 0,
+ $p_remove_path,
+ $p_preserve,
+ $p_symlinks
+ );
$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)
+ * This method extract from the archive one file identified by $p_filename.
+ * The return value is a string with the file content, or NULL on error.
+ *
+ * @param string $p_filename The path of the file to extract in a string.
+ *
+ * @return a string with the file content or NULL.
+ */
+ public function extractInString($p_filename)
{
if ($this->_openRead()) {
$v_result = $this->_extractInString($p_filename);
$this->_close();
} else {
- $v_result = NULL;
+ $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='')
+ * This method extract from the archive only the files indicated in the
+ * $p_filelist. These files are extracted in the current directory or
+ * in the directory indicated by the optional $p_path parameter.
+ * If indicated the $p_remove_path can be used in the same way as it is
+ * used in extractModify() method.
+ *
+ * @param array $p_filelist An array of filenames and directory names,
+ * or a single string with names separated
+ * by a single blank space.
+ * @param string $p_path The path of the directory where the
+ * files/dir need to by extracted.
+ * @param string $p_remove_path Part of the memorized path that can be
+ * removed if present at the beginning of
+ * the file/dir path.
+ * @param boolean $p_preserve Preserve user/group ownership of files
+ * @param boolean $p_symlinks Allow symlinks.
+ *
+ * @return bool true on success, false on error.
+ * @see extractModify()
+ */
+ public function extractList($p_filelist, $p_path = '', $p_remove_path = '', $p_preserve = false, $p_symlinks = true)
{
$v_result = true;
$v_list_detail = array();
- if (is_array($p_filelist))
+ if (is_array($p_filelist)) {
$v_list = $p_filelist;
- elseif (is_string($p_filelist))
+ } elseif (is_string($p_filelist)) {
$v_list = explode($this->_separator, $p_filelist);
- else {
+ } 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);
+ $v_result = $this->_extractList(
+ $p_path,
+ $v_list_detail,
+ "partial",
+ $v_list,
+ $p_remove_path,
+ $p_preserve,
+ $p_symlinks
+ );
$this->_close();
}
return $v_result;
}
- // }}}
- // {{{ setAttribute()
/**
- * This method set specific attributes of the archive. It uses a variable
- * list of parameters, in the format attribute code + attribute values :
- * $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ',');
- * @param mixed $argv variable list of attributes and values
- * @return true on success, false on error.
- * @access public
- */
- function setAttribute()
+ * This method set specific attributes of the archive. It uses a variable
+ * list of parameters, in the format attribute code + attribute values :
+ * $arch->setAttribute(ARCHIVE_TAR_ATT_SEPARATOR, ',');
+ *
+ * @return bool true on success, false on error.
+ */
+ public function setAttribute()
{
$v_result = true;
@@ -559,30 +672,32 @@ class Archive_Tar extends PEAR
}
// ----- Get the arguments
- $v_att_list = &func_get_args();
+ $v_att_list = func_get_args();
// ----- Read the attributes
- $i=0;
- while ($i<$v_size) {
+ $i = 0;
+ while ($i < $v_size) {
// ----- Look for next option
switch ($v_att_list[$i]) {
// ----- Look for options that request a string value
case ARCHIVE_TAR_ATT_SEPARATOR :
// ----- Check the number of parameters
- if (($i+1) >= $v_size) {
- $this->_error('Invalid number of parameters for '
- .'attribute ARCHIVE_TAR_ATT_SEPARATOR');
+ if (($i + 1) >= $v_size) {
+ $this->_error(
+ 'Invalid number of parameters for '
+ . 'attribute ARCHIVE_TAR_ATT_SEPARATOR'
+ );
return false;
}
// ----- Get the value
- $this->_separator = $v_att_list[$i+1];
+ $this->_separator = $v_att_list[$i + 1];
$i++;
- break;
+ break;
default :
- $this->_error('Unknow attribute code '.$v_att_list[$i].'');
+ $this->_error('Unknown attribute code ' . $v_att_list[$i] . '');
return false;
}
@@ -592,179 +707,246 @@ class Archive_Tar extends PEAR
return $v_result;
}
- // }}}
- // {{{ setIgnoreRegexp()
/**
- * This method sets the regular expression for ignoring files and directories
- * at import, for example:
- * $arch->setIgnoreRegexp("#CVS|\.svn#");
- * @param string $regexp regular expression defining which files or directories to ignore
- * @access public
- */
- function setIgnoreRegexp($regexp)
+ * This method sets the regular expression for ignoring files and directories
+ * at import, for example:
+ * $arch->setIgnoreRegexp("#CVS|\.svn#");
+ *
+ * @param string $regexp regular expression defining which files or directories to ignore
+ */
+ public function setIgnoreRegexp($regexp)
{
- $this->_ignore_regexp = $regexp;
+ $this->_ignore_regexp = $regexp;
}
- // }}}
- // {{{ setIgnoreList()
/**
- * This method sets the regular expression for ignoring all files and directories
- * matching the filenames in the array list at import, for example:
- * $arch->setIgnoreList(array('CVS', '.svn', 'bin/tool'));
- * @param array $list a list of file or directory names to ignore
- * @access public
- */
- function setIgnoreList($list)
+ * This method sets the regular expression for ignoring all files and directories
+ * matching the filenames in the array list at import, for example:
+ * $arch->setIgnoreList(array('CVS', '.svn', 'bin/tool'));
+ *
+ * @param array $list a list of file or directory names to ignore
+ *
+ * @access public
+ */
+ public function setIgnoreList($list)
{
- $regexp = str_replace(array('#', '.', '^', '$'), array('\#', '\.', '\^', '\$'), $list);
- $regexp = '#/'.join('$|/', $list).'#';
- $this->setIgnoreRegexp($regexp);
+ $list = str_replace(array('#', '.', '^', '$'), array('\#', '\.', '\^', '\$'), $list);
+ $regexp = '#/' . join('$|/', $list) . '#';
+ $this->setIgnoreRegexp($regexp);
}
- // }}}
- // {{{ _error()
- function _error($p_message)
+ /**
+ * @param string $p_message
+ */
+ public function _error($p_message)
{
- // ----- To be completed
- $this->raiseError($p_message);
+ $this->error_object = $this->raiseError($p_message);
}
- // }}}
- // {{{ _warning()
- function _warning($p_message)
+ /**
+ * @param string $p_message
+ */
+ public function _warning($p_message)
{
- // ----- To be completed
- $this->raiseError($p_message);
+ $this->error_object = $this->raiseError($p_message);
}
- // }}}
- // {{{ _isArchive()
- function _isArchive($p_filename=NULL)
+ /**
+ * @param string $p_filename
+ * @return bool
+ */
+ public function _isArchive($p_filename = null)
{
- if ($p_filename == NULL) {
+ if ($p_filename == null) {
$p_filename = $this->_tarname;
}
clearstatcache();
return @is_file($p_filename) && !@is_link($p_filename);
}
- // }}}
- // {{{ _openWrite()
- function _openWrite()
+ /**
+ * @return bool
+ */
+ public function _openWrite()
{
- if ($this->_compress_type == 'gz')
+ if ($this->_compress_type == 'gz' && function_exists('gzopen')) {
$this->_file = @gzopen($this->_tarname, "wb9");
- else if ($this->_compress_type == 'bz2')
- $this->_file = @bzopen($this->_tarname, "w");
- else if ($this->_compress_type == 'none')
- $this->_file = @fopen($this->_tarname, "wb");
- else
- $this->_error('Unknown or missing compression type ('
- .$this->_compress_type.')');
+ } else {
+ if ($this->_compress_type == 'bz2' && function_exists('bzopen')) {
+ $this->_file = @bzopen($this->_tarname, "w");
+ } else {
+ if ($this->_compress_type == 'lzma2' && function_exists('xzopen')) {
+ $this->_file = @xzopen($this->_tarname, 'w');
+ } else {
+ if ($this->_compress_type == 'none') {
+ $this->_file = @fopen($this->_tarname, "wb");
+ } else {
+ $this->_error(
+ 'Unknown or missing compression type ('
+ . $this->_compress_type . ')'
+ );
+ return false;
+ }
+ }
+ }
+ }
if ($this->_file == 0) {
- $this->_error('Unable to open in write mode \''
- .$this->_tarname.'\'');
+ $this->_error(
+ 'Unable to open in write mode \''
+ . $this->_tarname . '\''
+ );
return false;
}
return true;
}
- // }}}
- // {{{ _openRead()
- function _openRead()
+ /**
+ * @return bool
+ */
+ public function _openRead()
{
if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') {
- // ----- Look if a local copy need to be done
- if ($this->_temp_tarname == '') {
- $this->_temp_tarname = uniqid('tar').'.tmp';
- if (!$v_file_from = @fopen($this->_tarname, 'rb')) {
- $this->_error('Unable to open in read mode \''
- .$this->_tarname.'\'');
- $this->_temp_tarname = '';
- return false;
- }
- if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) {
- $this->_error('Unable to open in write mode \''
- .$this->_temp_tarname.'\'');
- $this->_temp_tarname = '';
- return false;
- }
- while ($v_data = @fread($v_file_from, 1024))
- @fwrite($v_file_to, $v_data);
- @fclose($v_file_from);
- @fclose($v_file_to);
- }
+ // ----- 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;
+ // ----- File to open if the local copy
+ $v_filename = $this->_temp_tarname;
+ } else {
+ // ----- File to open if the normal Tar file
- } else
- // ----- File to open if the normal Tar file
- $v_filename = $this->_tarname;
+ $v_filename = $this->_tarname;
+ }
- if ($this->_compress_type == 'gz')
+ if ($this->_compress_type == 'gz' && function_exists('gzopen')) {
$this->_file = @gzopen($v_filename, "rb");
- else if ($this->_compress_type == 'bz2')
- $this->_file = @bzopen($v_filename, "r");
- else if ($this->_compress_type == 'none')
- $this->_file = @fopen($v_filename, "rb");
- else
- $this->_error('Unknown or missing compression type ('
- .$this->_compress_type.')');
+ } else {
+ if ($this->_compress_type == 'bz2' && function_exists('bzopen')) {
+ $this->_file = @bzopen($v_filename, "r");
+ } else {
+ if ($this->_compress_type == 'lzma2' && function_exists('xzopen')) {
+ $this->_file = @xzopen($v_filename, "r");
+ } else {
+ if ($this->_compress_type == 'none') {
+ $this->_file = @fopen($v_filename, "rb");
+ } else {
+ $this->_error(
+ 'Unknown or missing compression type ('
+ . $this->_compress_type . ')'
+ );
+ return false;
+ }
+ }
+ }
+ }
if ($this->_file == 0) {
- $this->_error('Unable to open in read mode \''.$v_filename.'\'');
+ $this->_error('Unable to open in read mode \'' . $v_filename . '\'');
return false;
}
return true;
}
- // }}}
- // {{{ _openReadWrite()
- function _openReadWrite()
+ /**
+ * @return bool
+ */
+ public function _openReadWrite()
{
- if ($this->_compress_type == 'gz')
+ if ($this->_compress_type == 'gz') {
$this->_file = @gzopen($this->_tarname, "r+b");
- else if ($this->_compress_type == 'bz2') {
- $this->_error('Unable to open bz2 in read/write mode \''
- .$this->_tarname.'\' (limitation of bz2 extension)');
- return false;
- } else if ($this->_compress_type == 'none')
- $this->_file = @fopen($this->_tarname, "r+b");
- else
- $this->_error('Unknown or missing compression type ('
- .$this->_compress_type.')');
+ } else {
+ if ($this->_compress_type == 'bz2') {
+ $this->_error(
+ 'Unable to open bz2 in read/write mode \''
+ . $this->_tarname . '\' (limitation of bz2 extension)'
+ );
+ return false;
+ } else {
+ if ($this->_compress_type == 'lzma2') {
+ $this->_error(
+ 'Unable to open lzma2 in read/write mode \''
+ . $this->_tarname . '\' (limitation of lzma2 extension)'
+ );
+ return false;
+ } else {
+ if ($this->_compress_type == 'none') {
+ $this->_file = @fopen($this->_tarname, "r+b");
+ } else {
+ $this->_error(
+ 'Unknown or missing compression type ('
+ . $this->_compress_type . ')'
+ );
+ return false;
+ }
+ }
+ }
+ }
if ($this->_file == 0) {
- $this->_error('Unable to open in read/write mode \''
- .$this->_tarname.'\'');
+ $this->_error(
+ 'Unable to open in read/write mode \''
+ . $this->_tarname . '\''
+ );
return false;
}
return true;
}
- // }}}
- // {{{ _close()
- function _close()
+ /**
+ * @return bool
+ */
+ public function _close()
{
//if (isset($this->_file)) {
if (is_resource($this->_file)) {
- if ($this->_compress_type == 'gz')
+ 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.')');
+ } else {
+ if ($this->_compress_type == 'bz2') {
+ @bzclose($this->_file);
+ } else {
+ if ($this->_compress_type == 'lzma2') {
+ @xzclose($this->_file);
+ } else {
+ if ($this->_compress_type == 'none') {
+ @fclose($this->_file);
+ } else {
+ $this->_error(
+ 'Unknown or missing compression type ('
+ . $this->_compress_type . ')'
+ );
+ }
+ }
+ }
+ }
$this->_file = 0;
}
@@ -778,10 +960,11 @@ class Archive_Tar extends PEAR
return true;
}
- // }}}
- // {{{ _cleanFile()
- function _cleanFile()
+ /**
+ * @return bool
+ */
+ public function _cleanFile()
{
$this->_close();
@@ -798,344 +981,485 @@ class Archive_Tar extends PEAR
return true;
}
- // }}}
- // {{{ _writeBlock()
- function _writeBlock($p_binary_data, $p_len=null)
+ /**
+ * @param mixed $p_binary_data
+ * @param integer $p_len
+ * @return bool
+ */
+ public function _writeBlock($p_binary_data, $p_len = null)
{
- if (is_resource($this->_file)) {
- if ($p_len === null) {
- 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;
+ if (is_resource($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 == 'lzma2') {
+ @xzwrite($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 == 'lzma2') {
+ @xzwrite($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()
+ /**
+ * @return null|string
+ */
+ public function _readBlock()
{
- $v_block = null;
- if (is_resource($this->_file)) {
- if ($this->_compress_type == 'gz')
- $v_block = @gzread($this->_file, 512);
- else if ($this->_compress_type == 'bz2')
- $v_block = @bzread($this->_file, 512);
- else if ($this->_compress_type == 'none')
- $v_block = @fread($this->_file, 512);
- else
- $this->_error('Unknown or missing compression type ('
- .$this->_compress_type.')');
- }
- return $v_block;
+ $v_block = null;
+ if (is_resource($this->_file)) {
+ if ($this->_compress_type == 'gz') {
+ $v_block = @gzread($this->_file, 512);
+ } else {
+ if ($this->_compress_type == 'bz2') {
+ $v_block = @bzread($this->_file, 512);
+ } else {
+ if ($this->_compress_type == 'lzma2') {
+ $v_block = @xzread($this->_file, 512);
+ } else {
+ if ($this->_compress_type == 'none') {
+ $v_block = @fread($this->_file, 512);
+ } else {
+ $this->_error(
+ 'Unknown or missing compression type ('
+ . $this->_compress_type . ')'
+ );
+ }
+ }
+ }
+ }
+ }
+ return $v_block;
}
- // }}}
- // {{{ _jumpBlock()
- function _jumpBlock($p_len=null)
+ /**
+ * @param null $p_len
+ * @return bool
+ */
+ public function _jumpBlock($p_len = null)
{
- if (is_resource($this->_file)) {
- if ($p_len === null)
- $p_len = 1;
-
- if ($this->_compress_type == 'gz') {
- @gzseek($this->_file, gztell($this->_file)+($p_len*512));
- }
- else if ($this->_compress_type == 'bz2') {
- // ----- Replace missing bztell() and bzseek()
- for ($i=0; $i<$p_len; $i++)
- $this->_readBlock();
- } else if ($this->_compress_type == 'none')
- @fseek($this->_file, $p_len*512, SEEK_CUR);
- else
- $this->_error('Unknown or missing compression type ('
- .$this->_compress_type.')');
+ if (is_resource($this->_file)) {
+ if ($p_len === null) {
+ $p_len = 1;
+ }
- }
- return true;
+ if ($this->_compress_type == 'gz') {
+ @gzseek($this->_file, gztell($this->_file) + ($p_len * 512));
+ } else {
+ if ($this->_compress_type == 'bz2') {
+ // ----- Replace missing bztell() and bzseek()
+ for ($i = 0; $i < $p_len; $i++) {
+ $this->_readBlock();
+ }
+ } else {
+ if ($this->_compress_type == 'lzma2') {
+ // ----- Replace missing xztell() and xzseek()
+ for ($i = 0; $i < $p_len; $i++) {
+ $this->_readBlock();
+ }
+ } else {
+ if ($this->_compress_type == 'none') {
+ @fseek($this->_file, $p_len * 512, SEEK_CUR);
+ } else {
+ $this->_error(
+ 'Unknown or missing compression type ('
+ . $this->_compress_type . ')'
+ );
+ }
+ }
+ }
+ }
+ }
+ return true;
}
- // }}}
- // {{{ _writeFooter()
- function _writeFooter()
+ /**
+ * @return bool
+ */
+ public function _writeFooter()
{
- if (is_resource($this->_file)) {
- // ----- Write the last 0 filled block for end of archive
- $v_binary_data = pack('a1024', '');
- $this->_writeBlock($v_binary_data);
- }
- return true;
+ if (is_resource($this->_file)) {
+ // ----- Write the last 0 filled block for end of archive
+ $v_binary_data = pack('a1024', '');
+ $this->_writeBlock($v_binary_data);
+ }
+ return true;
}
- // }}}
- // {{{ _addList()
- function _addList($p_list, $p_add_dir, $p_remove_dir)
+ /**
+ * @param array $p_list
+ * @param string $p_add_dir
+ * @param string $p_remove_dir
+ * @return bool
+ */
+ public function _addList($p_list, $p_add_dir, $p_remove_dir)
{
- $v_result=true;
- $v_header = array();
-
- // ----- Remove potential windows directory separator
- $p_add_dir = $this->_translateWinPath($p_add_dir);
- $p_remove_dir = $this->_translateWinPath($p_remove_dir, false);
-
- if (!$this->_file) {
- $this->_error('Invalid file descriptor');
- return false;
- }
+ $v_result = true;
+ $v_header = array();
- if (sizeof($p_list) == 0)
- return true;
+ // ----- Remove potential windows directory separator
+ $p_add_dir = $this->_translateWinPath($p_add_dir);
+ $p_remove_dir = $this->_translateWinPath($p_remove_dir, false);
- foreach ($p_list as $v_filename) {
- if (!$v_result) {
- break;
- }
+ if (!$this->_file) {
+ $this->_error('Invalid file descriptor');
+ return false;
+ }
- // ----- Skip the current tar name
- if ($v_filename == $this->_tarname)
- continue;
+ if (sizeof($p_list) == 0) {
+ return true;
+ }
- if ($v_filename == '')
- continue;
+ foreach ($p_list as $v_filename) {
+ if (!$v_result) {
+ break;
+ }
- // ----- ignore files and directories matching the ignore regular expression
- if ($this->_ignore_regexp && preg_match($this->_ignore_regexp, '/'.$v_filename)) {
- $this->_warning("File '$v_filename' ignored");
- continue;
- }
+ // ----- Skip the current tar name
+ if ($v_filename == $this->_tarname) {
+ continue;
+ }
- if (!file_exists($v_filename)) {
- $this->_warning("File '$v_filename' does not exist");
- continue;
- }
+ if ($v_filename == '') {
+ continue;
+ }
- // ----- Add the file or directory header
- if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir))
- return false;
+ // ----- ignore files and directories matching the ignore regular expression
+ if ($this->_ignore_regexp && preg_match($this->_ignore_regexp, '/' . $v_filename)) {
+ $this->_warning("File '$v_filename' ignored");
+ continue;
+ }
- if (@is_dir($v_filename) && !@is_link($v_filename)) {
- if (!($p_hdir = opendir($v_filename))) {
- $this->_warning("Directory '$v_filename' can not be read");
+ if (!file_exists($v_filename) && !is_link($v_filename)) {
+ $this->_warning("File '$v_filename' does not exist");
continue;
}
- while (false !== ($p_hitem = readdir($p_hdir))) {
- if (($p_hitem != '.') && ($p_hitem != '..')) {
- if ($v_filename != ".")
- $p_temp_list[0] = $v_filename.'/'.$p_hitem;
- else
- $p_temp_list[0] = $p_hitem;
- $v_result = $this->_addList($p_temp_list,
- $p_add_dir,
- $p_remove_dir);
- }
+ // ----- Add the file or directory header
+ if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir)) {
+ return false;
}
- unset($p_temp_list);
- unset($p_hdir);
- unset($p_hitem);
+ if (@is_dir($v_filename) && !@is_link($v_filename)) {
+ if (!($p_hdir = opendir($v_filename))) {
+ $this->_warning("Directory '$v_filename' can not be read");
+ continue;
+ }
+ while (false !== ($p_hitem = readdir($p_hdir))) {
+ if (($p_hitem != '.') && ($p_hitem != '..')) {
+ if ($v_filename != ".") {
+ $p_temp_list[0] = $v_filename . '/' . $p_hitem;
+ } else {
+ $p_temp_list[0] = $p_hitem;
+ }
+
+ $v_result = $this->_addList(
+ $p_temp_list,
+ $p_add_dir,
+ $p_remove_dir
+ );
+ }
+ }
+
+ unset($p_temp_list);
+ unset($p_hdir);
+ unset($p_hitem);
+ }
}
- }
- return $v_result;
+ return $v_result;
}
- // }}}
- // {{{ _addFile()
- function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir)
+ /**
+ * @param string $p_filename
+ * @param mixed $p_header
+ * @param string $p_add_dir
+ * @param string $p_remove_dir
+ * @param null $v_stored_filename
+ * @return bool
+ */
+ public function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $v_stored_filename = null)
{
- if (!$this->_file) {
- $this->_error('Invalid file descriptor');
- return false;
- }
+ if (!$this->_file) {
+ $this->_error('Invalid file descriptor');
+ return false;
+ }
+
+ if ($p_filename == '') {
+ $this->_error('Invalid file name');
+ return false;
+ }
+
+ if (is_null($v_stored_filename)) {
+ // ----- Calculate the stored filename
+ $p_filename = $this->_translateWinPath($p_filename, false);
+ $v_stored_filename = $p_filename;
- if ($p_filename == '') {
- $this->_error('Invalid file name');
- return false;
- }
+ if (strcmp($p_filename, $p_remove_dir) == 0) {
+ return true;
+ }
- // ----- 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 ($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;
- }
+ 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->_pathReduction($v_stored_filename);
+ $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;
+ }
+ }
- if ($this->_isArchive($p_filename)) {
- if (($v_file = @fopen($p_filename, "rb")) == 0) {
- $this->_warning("Unable to open file '".$p_filename
- ."' in binary read mode");
- return true;
- }
+ $v_stored_filename = $this->_pathReduction($v_stored_filename);
+ }
- if (!$this->_writeHeader($p_filename, $v_stored_filename))
- return false;
+ if ($this->_isArchive($p_filename)) {
+ if (($v_file = @fopen($p_filename, "rb")) == 0) {
+ $this->_warning(
+ "Unable to open file '" . $p_filename
+ . "' in binary read mode"
+ );
+ return true;
+ }
- while (($v_buffer = fread($v_file, 512)) != '') {
- $v_binary_data = pack("a512", "$v_buffer");
- $this->_writeBlock($v_binary_data);
- }
+ if (!$this->_writeHeader($p_filename, $v_stored_filename)) {
+ return false;
+ }
- fclose($v_file);
+ while (($v_buffer = fread($v_file, $this->buffer_length)) != '') {
+ $buffer_length = strlen("$v_buffer");
+ if ($buffer_length != $this->buffer_length) {
+ $pack_size = ((int)($buffer_length / 512) + ($buffer_length % 512 !== 0 ? 1 : 0)) * 512;
+ $pack_format = sprintf('a%d', $pack_size);
+ } else {
+ $pack_format = sprintf('a%d', $this->buffer_length);
+ }
+ $v_binary_data = pack($pack_format, "$v_buffer");
+ $this->_writeBlock($v_binary_data);
+ }
- } else {
- // ----- Only header for dir
- if (!$this->_writeHeader($p_filename, $v_stored_filename))
- return false;
- }
+ fclose($v_file);
+ } else {
+ // ----- Only header for dir
+ if (!$this->_writeHeader($p_filename, $v_stored_filename)) {
+ return false;
+ }
+ }
- return true;
+ return true;
}
- // }}}
- // {{{ _addString()
- function _addString($p_filename, $p_string)
+ /**
+ * @param string $p_filename
+ * @param string $p_string
+ * @param bool $p_datetime
+ * @param array $p_params
+ * @return bool
+ */
+ public function _addString($p_filename, $p_string, $p_datetime = false, $p_params = array())
{
- if (!$this->_file) {
- $this->_error('Invalid file descriptor');
- return false;
- }
+ $p_stamp = @$p_params["stamp"] ? $p_params["stamp"] : ($p_datetime ? $p_datetime : time());
+ $p_mode = @$p_params["mode"] ? $p_params["mode"] : 0600;
+ $p_type = @$p_params["type"] ? $p_params["type"] : "";
+ $p_uid = @$p_params["uid"] ? $p_params["uid"] : 0;
+ $p_gid = @$p_params["gid"] ? $p_params["gid"] : 0;
+ if (!$this->_file) {
+ $this->_error('Invalid file descriptor');
+ return false;
+ }
+
+ if ($p_filename == '') {
+ $this->_error('Invalid file name');
+ return false;
+ }
- if ($p_filename == '') {
- $this->_error('Invalid file name');
- return false;
- }
+ // ----- Calculate the stored filename
+ $p_filename = $this->_translateWinPath($p_filename, false);
- // ----- Calculate the stored filename
- $p_filename = $this->_translateWinPath($p_filename, false);;
+ // ----- If datetime is not specified, set current time
+ if ($p_datetime === false) {
+ $p_datetime = time();
+ }
- if (!$this->_writeHeaderBlock($p_filename, strlen($p_string),
- time(), 384, "", 0, 0))
- return false;
+ if (!$this->_writeHeaderBlock(
+ $p_filename,
+ strlen($p_string),
+ $p_stamp,
+ $p_mode,
+ $p_type,
+ $p_uid,
+ $p_gid
+ )
+ ) {
+ return false;
+ }
- $i=0;
- while (($v_buffer = substr($p_string, (($i++)*512), 512)) != '') {
- $v_binary_data = pack("a512", $v_buffer);
- $this->_writeBlock($v_binary_data);
- }
+ $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;
+ return true;
}
- // }}}
- // {{{ _writeHeader()
- function _writeHeader($p_filename, $p_stored_filename)
+ /**
+ * @param string $p_filename
+ * @param string $p_stored_filename
+ * @return bool
+ */
+ public function _writeHeader($p_filename, $p_stored_filename)
{
- if ($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_reduced_filename = $this->_pathReduction($p_stored_filename);
+
+ if (strlen($v_reduced_filename) > 99) {
+ if (!$this->_writeLongHeader($v_reduced_filename, false)) {
+ return false;
+ }
+ }
+
+ $v_linkname = '';
+ if (@is_link($p_filename)) {
+ $v_linkname = readlink($p_filename);
+ }
+
+ if (strlen($v_linkname) > 99) {
+ if (!$this->_writeLongHeader($v_linkname, true)) {
+ return false;
+ }
}
$v_info = lstat($p_filename);
$v_uid = sprintf("%07s", DecOct($v_info[4]));
$v_gid = sprintf("%07s", DecOct($v_info[5]));
$v_perms = sprintf("%07s", DecOct($v_info['mode'] & 000777));
-
$v_mtime = sprintf("%011s", DecOct($v_info['mtime']));
- $v_linkname = '';
-
if (@is_link($p_filename)) {
- $v_typeflag = '2';
- $v_linkname = readlink($p_filename);
- $v_size = sprintf("%011s", DecOct(0));
+ $v_typeflag = '2';
+ $v_size = sprintf("%011s", DecOct(0));
} elseif (@is_dir($p_filename)) {
- $v_typeflag = "5";
- $v_size = sprintf("%011s", DecOct(0));
+ $v_typeflag = "5";
+ $v_size = sprintf("%011s", DecOct(0));
} else {
- $v_typeflag = '0';
- clearstatcache();
- $v_size = sprintf("%011s", DecOct($v_info['size']));
+ $v_typeflag = '0';
+ clearstatcache();
+ $v_size = sprintf("%011s", DecOct($v_info['size']));
}
$v_magic = 'ustar ';
-
$v_version = ' ';
-
- if (function_exists('posix_getpwuid'))
- {
- $userinfo = posix_getpwuid($v_info[4]);
- $groupinfo = posix_getgrgid($v_info[5]);
-
- $v_uname = $userinfo['name'];
- $v_gname = $groupinfo['name'];
- }
- else
- {
- $v_uname = '';
- $v_gname = '';
+ $v_uname = '';
+ $v_gname = '';
+
+ if (function_exists('posix_getpwuid')) {
+ $userinfo = posix_getpwuid($v_info[4]);
+ $groupinfo = posix_getgrgid($v_info[5]);
+
+ if (isset($userinfo['name'])) {
+ $v_uname = $userinfo['name'];
+ }
+
+ if (isset($groupinfo['name'])) {
+ $v_gname = $groupinfo['name'];
+ }
}
$v_devmajor = '';
-
$v_devminor = '';
-
$v_prefix = '';
- $v_binary_data_first = pack("a100a8a8a8a12a12",
- $v_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, '');
+ $v_binary_data_first = pack(
+ "a100a8a8a8a12a12",
+ $v_reduced_filename,
+ $v_perms,
+ $v_uid,
+ $v_gid,
+ $v_size,
+ $v_mtime
+ );
+ $v_binary_data_last = pack(
+ "a1a100a6a2a32a32a8a8a155a12",
+ $v_typeflag,
+ $v_linkname,
+ $v_magic,
+ $v_version,
+ $v_uname,
+ $v_gname,
+ $v_devmajor,
+ $v_devminor,
+ $v_prefix,
+ ''
+ );
// ----- Calculate the checksum
$v_checksum = 0;
// ..... First part of the header
- for ($i=0; $i<148; $i++)
- $v_checksum += ord(substr($v_binary_data_first,$i,1));
+ 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++)
+ 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));
+ for ($i = 156, $j = 0; $i < 512; $i++, $j++) {
+ $v_checksum += ord(substr($v_binary_data_last, $j, 1));
+ }
// ----- Write the first 148 bytes of the header in the archive
$this->_writeBlock($v_binary_data_first, 148);
// ----- Write the calculated checksum
- $v_checksum = sprintf("%06s ", DecOct($v_checksum));
+ $v_checksum = sprintf("%06s\0 ", DecOct($v_checksum));
$v_binary_data = pack("a8", $v_checksum);
$this->_writeBlock($v_binary_data, 8);
@@ -1144,23 +1468,39 @@ class Archive_Tar extends PEAR
return true;
}
- // }}}
- // {{{ _writeHeaderBlock()
- function _writeHeaderBlock($p_filename, $p_size, $p_mtime=0, $p_perms=0,
- $p_type='', $p_uid=0, $p_gid=0)
+ /**
+ * @param string $p_filename
+ * @param int $p_size
+ * @param int $p_mtime
+ * @param int $p_perms
+ * @param string $p_type
+ * @param int $p_uid
+ * @param int $p_gid
+ * @return bool
+ */
+ public function _writeHeaderBlock(
+ $p_filename,
+ $p_size,
+ $p_mtime = 0,
+ $p_perms = 0,
+ $p_type = '',
+ $p_uid = 0,
+ $p_gid = 0
+ )
{
$p_filename = $this->_pathReduction($p_filename);
if (strlen($p_filename) > 99) {
- if (!$this->_writeLongHeader($p_filename))
- return false;
+ if (!$this->_writeLongHeader($p_filename, false)) {
+ return false;
+ }
}
if ($p_type == "5") {
- $v_size = sprintf("%011s", DecOct(0));
+ $v_size = sprintf("%011s", DecOct(0));
} else {
- $v_size = sprintf("%011s", DecOct($p_size));
+ $v_size = sprintf("%011s", DecOct($p_size));
}
$v_uid = sprintf("%07s", DecOct($p_uid));
@@ -1175,45 +1515,65 @@ class Archive_Tar extends PEAR
$v_version = ' ';
- if (function_exists('posix_getpwuid'))
- {
- $userinfo = posix_getpwuid($p_uid);
- $groupinfo = posix_getgrgid($p_gid);
-
- $v_uname = $userinfo['name'];
- $v_gname = $groupinfo['name'];
- }
- else
- {
- $v_uname = '';
- $v_gname = '';
+ if (function_exists('posix_getpwuid')) {
+ $userinfo = posix_getpwuid($p_uid);
+ $groupinfo = posix_getgrgid($p_gid);
+
+ if ($userinfo === false || $groupinfo === false) {
+ $v_uname = '';
+ $v_gname = '';
+ } else {
+ $v_uname = $userinfo['name'];
+ $v_gname = $groupinfo['name'];
+ }
+ } else {
+ $v_uname = '';
+ $v_gname = '';
}
-
+
$v_devmajor = '';
$v_devminor = '';
$v_prefix = '';
- $v_binary_data_first = pack("a100a8a8a8a12A12",
- $p_filename, $v_perms, $v_uid, $v_gid,
- $v_size, $v_mtime);
- $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12",
- $p_type, $v_linkname, $v_magic,
- $v_version, $v_uname, $v_gname,
- $v_devmajor, $v_devminor, $v_prefix, '');
+ $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));
+ 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++)
+ 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));
+ 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);
@@ -1228,55 +1588,71 @@ class Archive_Tar extends PEAR
return true;
}
- // }}}
- // {{{ _writeLongHeader()
- function _writeLongHeader($p_filename)
+ /**
+ * @param string $p_filename
+ * @return bool
+ */
+ public function _writeLongHeader($p_filename, $is_link = false)
{
- $v_size = sprintf("%11s ", DecOct(strlen($p_filename)));
-
- $v_typeflag = 'L';
-
+ $v_uid = sprintf("%07s", 0);
+ $v_gid = sprintf("%07s", 0);
+ $v_perms = sprintf("%07s", 0);
+ $v_size = sprintf("%'011s", DecOct(strlen($p_filename)));
+ $v_mtime = sprintf("%011s", 0);
+ $v_typeflag = ($is_link ? 'K' : 'L');
$v_linkname = '';
-
- $v_magic = '';
-
- $v_version = '';
-
+ $v_magic = 'ustar ';
+ $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, '');
+ $v_binary_data_first = pack(
+ "a100a8a8a8a12a12",
+ '././@LongLink',
+ $v_perms,
+ $v_uid,
+ $v_gid,
+ $v_size,
+ $v_mtime
+ );
+ $v_binary_data_last = pack(
+ "a1a100a6a2a32a32a8a8a155a12",
+ $v_typeflag,
+ $v_linkname,
+ $v_magic,
+ $v_version,
+ $v_uname,
+ $v_gname,
+ $v_devmajor,
+ $v_devminor,
+ $v_prefix,
+ ''
+ );
// ----- Calculate the checksum
$v_checksum = 0;
// ..... First part of the header
- for ($i=0; $i<148; $i++)
- $v_checksum += ord(substr($v_binary_data_first,$i,1));
+ 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++)
+ 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));
+ for ($i = 156, $j = 0; $i < 512; $i++, $j++) {
+ $v_checksum += ord(substr($v_binary_data_last, $j, 1));
+ }
// ----- Write the first 148 bytes of the header in the archive
$this->_writeBlock($v_binary_data_first, 148);
// ----- Write the calculated checksum
- $v_checksum = sprintf("%06s ", DecOct($v_checksum));
+ $v_checksum = sprintf("%06s\0 ", DecOct($v_checksum));
$v_binary_data = pack("a8", $v_checksum);
$this->_writeBlock($v_binary_data, 8);
@@ -1284,27 +1660,30 @@ class Archive_Tar extends PEAR
$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)) != '') {
+ $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)
+ /**
+ * @param mixed $v_binary_data
+ * @param mixed $v_header
+ * @return bool
+ */
+ public function _readHeader($v_binary_data, &$v_header)
{
- if (strlen($v_binary_data)==0) {
+ 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));
+ $this->_error('Invalid block size : ' . strlen($v_binary_data));
return false;
}
@@ -1314,53 +1693,65 @@ class Archive_Tar extends PEAR
// ----- 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_binary_split = str_split($v_binary_data);
+ $v_checksum += array_sum(array_map('ord', array_slice($v_binary_split, 0, 148)));
+ $v_checksum += array_sum(array_map('ord', array(' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',)));
+ $v_checksum += array_sum(array_map('ord', array_slice($v_binary_split, 156, 512)));
+
- $v_data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/"
- ."a8checksum/a1typeflag/a100link/a6magic/a2version/"
- ."a32uname/a32gname/a8devmajor/a8devminor",
- $v_binary_data);
+ $v_data = unpack($this->_fmt, $v_binary_data);
+
+ if (strlen($v_data["prefix"]) > 0) {
+ $v_data["filename"] = "$v_data[prefix]/$v_data[filename]";
+ }
// ----- Extract the checksum
- $v_header['checksum'] = OctDec(trim($v_data['checksum']));
+ $v_data_checksum = trim($v_data['checksum']);
+ if (!preg_match('/^[0-7]*$/', $v_data_checksum)) {
+ $this->_error(
+ 'Invalid checksum for file "' . $v_data['filename']
+ . '" : ' . $v_data_checksum . ' extracted'
+ );
+ return false;
+ }
+
+ $v_header['checksum'] = OctDec($v_data_checksum);
if ($v_header['checksum'] != $v_checksum) {
$v_header['filename'] = '';
// ----- Look for last block (empty block)
- if (($v_checksum == 256) && ($v_header['checksum'] == 0))
+ 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');
+ $this->_error(
+ 'Invalid checksum for file "' . $v_data['filename']
+ . '" : ' . $v_checksum . ' calculated, '
+ . $v_header['checksum'] . ' expected'
+ );
return false;
}
// ----- Extract the properties
- $v_header['filename'] = $v_data['filename'];
- if ($this->_maliciousFilename($v_header['filename'])) {
- $this->_error('Malicious .tar detected, file "' . $v_header['filename'] .
- '" will not install in desired directory tree');
+ $v_header['filename'] = rtrim($v_data['filename'], "\0");
+ if ($this->_isMaliciousFilename($v_header['filename'])) {
+ $this->_error(
+ 'Malicious .tar detected, file "' . $v_header['filename'] .
+ '" will not install in desired directory tree'
+ );
return false;
}
$v_header['mode'] = OctDec(trim($v_data['mode']));
$v_header['uid'] = OctDec(trim($v_data['uid']));
$v_header['gid'] = OctDec(trim($v_data['gid']));
- $v_header['size'] = OctDec(trim($v_data['size']));
+ $v_header['size'] = $this->_tarRecToSize($v_data['size']);
$v_header['mtime'] = OctDec(trim($v_data['mtime']));
if (($v_header['typeflag'] = $v_data['typeflag']) == "5") {
- $v_header['size'] = 0;
+ $v_header['size'] = 0;
}
$v_header['link'] = trim($v_data['link']);
/* ----- All these fields are removed form the header because
- they do not carry interesting info
+ they do not carry interesting info
$v_header[magic] = trim($v_data[magic]);
$v_header[version] = trim($v_data[version]);
$v_header[uname] = trim($v_data[uname]);
@@ -1371,404 +1762,629 @@ class Archive_Tar extends PEAR
return true;
}
- // }}}
- // {{{ _maliciousFilename()
+ /**
+ * Convert Tar record size to actual size
+ *
+ * @param string $tar_size
+ * @return size of tar record in bytes
+ */
+ private function _tarRecToSize($tar_size)
+ {
+ /*
+ * First byte of size has a special meaning if bit 7 is set.
+ *
+ * Bit 7 indicates base-256 encoding if set.
+ * Bit 6 is the sign bit.
+ * Bits 5:0 are most significant value bits.
+ */
+ $ch = ord($tar_size[0]);
+ if ($ch & 0x80) {
+ // Full 12-bytes record is required.
+ $rec_str = $tar_size . "\x00";
+
+ $size = ($ch & 0x40) ? -1 : 0;
+ $size = ($size << 6) | ($ch & 0x3f);
+
+ for ($num_ch = 1; $num_ch < 12; ++$num_ch) {
+ $size = ($size * 256) + ord($rec_str[$num_ch]);
+ }
+
+ return $size;
+
+ } else {
+ return OctDec(trim($tar_size));
+ }
+ }
+
/**
* Detect and report a malicious file name
*
* @param string $file
+ *
* @return bool
- * @access private
*/
- function _maliciousFilename($file)
+ private function _isMaliciousFilename($file)
{
- if (strpos($file, '/../') !== false) {
+ if (strpos($file, '://') !== false) {
return true;
}
- if (strpos($file, '../') === 0) {
+ if (strpos($file, '../') !== false || strpos($file, '..\\') !== false) {
return true;
}
return false;
}
- // }}}
- // {{{ _readLongHeader()
- function _readLongHeader(&$v_header)
+ /**
+ * @param $v_header
+ * @return bool
+ */
+ public 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 .= trim($v_content);
- }
+ $v_filename = '';
+ $v_filesize = $v_header['size'];
+ $n = floor($v_header['size'] / 512);
+ for ($i = 0; $i < $n; $i++) {
+ $v_content = $this->_readBlock();
+ $v_filename .= $v_content;
+ }
+ if (($v_header['size'] % 512) != 0) {
+ $v_content = $this->_readBlock();
+ $v_filename .= $v_content;
+ }
- // ----- Read the next header
- $v_binary_data = $this->_readBlock();
+ // ----- Read the next header
+ $v_binary_data = $this->_readBlock();
- if (!$this->_readHeader($v_binary_data, $v_header))
- return false;
+ if (!$this->_readHeader($v_binary_data, $v_header)) {
+ return false;
+ }
- $v_filename = trim($v_filename);
- $v_header['filename'] = $v_filename;
- if ($this->_maliciousFilename($v_filename)) {
- $this->_error('Malicious .tar detected, file "' . $v_filename .
- '" will not install in desired directory tree');
+ $v_filename = rtrim(substr($v_filename, 0, $v_filesize), "\0");
+ $v_header['filename'] = $v_filename;
+ if ($this->_isMaliciousFilename($v_filename)) {
+ $this->_error(
+ 'Malicious .tar detected, file "' . $v_filename .
+ '" will not install in desired directory tree'
+ );
return false;
- }
+ }
- return true;
+ 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)
+ * This method extract from the archive one file identified by $p_filename.
+ * The return value is a string with the file content, or null on error.
+ *
+ * @param string $p_filename The path of the file to extract in a string.
+ *
+ * @return a string with the file content or null.
+ */
+ private function _extractInString($p_filename)
{
$v_result_str = "";
- While (strlen($v_binary_data = $this->_readBlock()) != 0)
- {
- if (!$this->_readHeader($v_binary_data, $v_header))
- return NULL;
+ while (strlen($v_binary_data = $this->_readBlock()) != 0) {
+ if (!$this->_readHeader($v_binary_data, $v_header)) {
+ return null;
+ }
+
+ if ($v_header['filename'] == '') {
+ continue;
+ }
- if ($v_header['filename'] == '')
- continue;
+ switch ($v_header['typeflag']) {
+ case 'L':
+ {
+ if (!$this->_readLongHeader($v_header)) {
+ return null;
+ }
+ }
+ break;
- // ----- Look for long filename
- if ($v_header['typeflag'] == 'L') {
- if (!$this->_readLongHeader($v_header))
- return NULL;
- }
+ case 'K':
+ {
+ $v_link_header = $v_header;
+ if (!$this->_readLongHeader($v_link_header)) {
+ return null;
+ }
+ $v_header['link'] = $v_link_header['filename'];
+ }
+ break;
+ }
- if ($v_header['filename'] == $p_filename) {
- if ($v_header['typeflag'] == "5") {
- $this->_error('Unable to extract in string a directory '
- .'entry {'.$v_header['filename'].'}');
- return NULL;
- } else {
- $n = floor($v_header['size']/512);
- for ($i=0; $i<$n; $i++) {
- $v_result_str .= $this->_readBlock();
- }
- if (($v_header['size'] % 512) != 0) {
- $v_content = $this->_readBlock();
- $v_result_str .= substr($v_content, 0,
- ($v_header['size'] % 512));
- }
- return $v_result_str;
- }
- } else {
- $this->_jumpBlock(ceil(($v_header['size']/512)));
- }
+ 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;
+ return null;
}
- // }}}
- // {{{ _extractList()
- function _extractList($p_path, &$p_list_detail, $p_mode,
- $p_file_list, $p_remove_path)
+ /**
+ * @param string $p_path
+ * @param string $p_list_detail
+ * @param string $p_mode
+ * @param string $p_file_list
+ * @param string $p_remove_path
+ * @param bool $p_preserve
+ * @param bool $p_symlinks
+ * @return bool
+ */
+ public function _extractList(
+ $p_path,
+ &$p_list_detail,
+ $p_mode,
+ $p_file_list,
+ $p_remove_path,
+ $p_preserve = false,
+ $p_symlinks = true
+ )
{
- $v_result=true;
- $v_nb = 0;
- $v_extract_all = true;
- $v_listing = false;
-
- $p_path = $this->_translateWinPath($p_path, false);
- if ($p_path == '' || (substr($p_path, 0, 1) != '/'
- && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':'))) {
- $p_path = "./".$p_path;
- }
- $p_remove_path = $this->_translateWinPath($p_remove_path);
+ $v_result = true;
+ $v_nb = 0;
+ $v_extract_all = true;
+ $v_listing = false;
- // ----- 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);
+ $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);
- 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;
- }
+ // ----- 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);
- clearstatcache();
+ 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;
+ }
- while (strlen($v_binary_data = $this->_readBlock()) != 0)
- {
- $v_extract_file = FALSE;
- $v_extraction_stopped = 0;
+ clearstatcache();
- if (!$this->_readHeader($v_binary_data, $v_header))
- return false;
+ while (strlen($v_binary_data = $this->_readBlock()) != 0) {
+ $v_extract_file = false;
+ $v_extraction_stopped = 0;
- if ($v_header['filename'] == '') {
- continue;
- }
+ if (!$this->_readHeader($v_binary_data, $v_header)) {
+ return false;
+ }
- // ----- Look for long filename
- if ($v_header['typeflag'] == 'L') {
- if (!$this->_readLongHeader($v_header))
- return false;
- }
+ if ($v_header['filename'] == '') {
+ continue;
+ }
- if ((!$v_extract_all) && (is_array($p_file_list))) {
- // ----- By default no unzip if the file is not found
- $v_extract_file = false;
+ switch ($v_header['typeflag']) {
+ case 'L':
+ {
+ if (!$this->_readLongHeader($v_header)) {
+ return null;
+ }
+ }
+ break;
- 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;
+ case 'K':
+ {
+ $v_link_header = $v_header;
+ if (!$this->_readLongHeader($v_link_header)) {
+ return null;
+ }
+ $v_header['link'] = $v_link_header['filename'];
+ }
+ 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;
- }
+ // ignore extended / pax headers
+ if ($v_header['typeflag'] == 'x' || $v_header['typeflag'] == 'g') {
+ $this->_jumpBlock(ceil(($v_header['size'] / 512)));
+ continue;
+ }
- // ----- 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 ((!$v_extract_all) && (is_array($p_file_list))) {
+ // ----- By default no unzip if the file is not found
+ $v_extract_file = false;
- if (substr($v_header['filename'], 0, 1) == '/')
- $v_header['filename'] = $p_path.$v_header['filename'];
- else
- $v_header['filename'] = $p_path.'/'.$v_header['filename'];
- }
- if (file_exists($v_header['filename'])) {
- if ( (@is_dir($v_header['filename']))
- && ($v_header['typeflag'] == '')) {
- $this->_error('File '.$v_header['filename']
- .' already exists as a directory');
- return false;
- }
- if ( ($this->_isArchive($v_header['filename']))
- && ($v_header['typeflag'] == "5")) {
- $this->_error('Directory '.$v_header['filename']
- .' already exists as a file');
- return false;
- }
- if (!is_writeable($v_header['filename'])) {
- $this->_error('File '.$v_header['filename']
- .' already exists and is write protected');
- return false;
- }
- if (filemtime($v_header['filename']) > $v_header['mtime']) {
- // To be completed : An error or silent no replace ?
- }
- }
+ 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;
+ }
- // ----- 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;
- }
+ // ----- Look if this file need to be extracted
+ if (($v_extract_file) && (!$v_listing)) {
+ if (($p_remove_path != '')
+ && (substr($v_header['filename'] . '/', 0, $p_remove_path_size)
+ == $p_remove_path)
+ ) {
+ $v_header['filename'] = substr(
+ $v_header['filename'],
+ $p_remove_path_size
+ );
+ if ($v_header['filename'] == '') {
+ continue;
+ }
+ }
+ if (($p_path != './') && ($p_path != '/')) {
+ while (substr($p_path, -1) == '/') {
+ $p_path = substr($p_path, 0, strlen($p_path) - 1);
+ }
- if ($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'].'}');
+ if (substr($v_header['filename'], 0, 1) == '/') {
+ $v_header['filename'] = $p_path . $v_header['filename'];
+ } else {
+ $v_header['filename'] = $p_path . '/' . $v_header['filename'];
+ }
+ }
+ if (file_exists($v_header['filename'])) {
+ if ((@is_dir($v_header['filename']))
+ && ($v_header['typeflag'] == '')
+ ) {
+ $this->_error(
+ 'File ' . $v_header['filename']
+ . ' already exists as a directory'
+ );
+ return false;
+ }
+ if (($this->_isArchive($v_header['filename']))
+ && ($v_header['typeflag'] == "5")
+ ) {
+ $this->_error(
+ 'Directory ' . $v_header['filename']
+ . ' already exists as a file'
+ );
+ return false;
+ }
+ if (!is_writeable($v_header['filename'])) {
+ $this->_error(
+ 'File ' . $v_header['filename']
+ . ' already exists and is write protected'
+ );
+ return false;
+ }
+ if (filemtime($v_header['filename']) > $v_header['mtime']) {
+ // To be completed : An error or silent no replace ?
+ }
+ } // ----- Check the directory availability and create it if necessary
+ elseif (($v_result
+ = $this->_dirCheck(
+ ($v_header['typeflag'] == "5"
+ ? $v_header['filename']
+ : dirname($v_header['filename']))
+ )) != 1
+ ) {
+ $this->_error('Unable to create path for ' . $v_header['filename']);
return false;
}
- }
- } elseif ($v_header['typeflag'] == "2") {
- if (@file_exists($v_header['filename'])) {
- @unlink($v_header['filename']);
- }
- if (!@symlink($v_header['link'], $v_header['filename'])) {
- $this->_error('Unable to extract symbolic link {'
- .$v_header['filename'].'}');
- return false;
- }
- } else {
- if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) {
- $this->_error('Error while opening {'.$v_header['filename']
- .'} in write binary mode');
- return false;
- } else {
- $n = floor($v_header['size']/512);
- for ($i=0; $i<$n; $i++) {
- $v_content = $this->_readBlock();
- fwrite($v_dest_file, $v_content, 512);
- }
- if (($v_header['size'] % 512) != 0) {
- $v_content = $this->_readBlock();
- fwrite($v_dest_file, $v_content, ($v_header['size'] % 512));
- }
- @fclose($v_dest_file);
+ if ($v_extract_file) {
+ if ($v_header['typeflag'] == "5") {
+ if (!@file_exists($v_header['filename'])) {
+ if (!@mkdir($v_header['filename'], 0775)) {
+ $this->_error(
+ 'Unable to create directory {'
+ . $v_header['filename'] . '}'
+ );
+ return false;
+ }
+ }
+ } elseif ($v_header['typeflag'] == "2") {
+ if (!$p_symlinks) {
+ $this->_warning('Symbolic links are not allowed. '
+ . 'Unable to extract {'
+ . $v_header['filename'] . '}'
+ );
+ return false;
+ }
+ $absolute_link = FALSE;
+ $link_depth = 0;
+ if (strpos($v_header['link'], "/") === 0 || strpos($v_header['link'], ':') !== FALSE) {
+ $absolute_link = TRUE;
+ }
+ else {
+ $s_filename = preg_replace('@^' . preg_quote($p_path) . '@', "", $v_header['filename']);
+ $s_linkname = str_replace('\\', '/', $v_header['link']);
+ foreach (explode("/", $s_filename) as $dir) {
+ if ($dir === "..") {
+ $link_depth--;
+ } elseif ($dir !== "" && $dir !== "." ) {
+ $link_depth++;
+ }
+ }
+ foreach (explode("/", $s_linkname) as $dir){
+ if ($link_depth <= 0) {
+ break;
+ }
+ if ($dir === "..") {
+ $link_depth--;
+ } elseif ($dir !== "" && $dir !== ".") {
+ $link_depth++;
+ }
+ }
+ }
+ if ($absolute_link || $link_depth <= 0) {
+ $this->_error(
+ 'Out-of-path file extraction {'
+ . $v_header['filename'] . ' --> ' .
+ $v_header['link'] . '}'
+ );
+ return false;
+ }
+ if (@file_exists($v_header['filename'])) {
+ @unlink($v_header['filename']);
+ }
+ if (!@symlink($v_header['link'], $v_header['filename'])) {
+ $this->_error(
+ 'Unable to extract symbolic link {'
+ . $v_header['filename'] . '}'
+ );
+ return false;
+ }
+ } else {
+ if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) {
+ $this->_error(
+ 'Error while opening {' . $v_header['filename']
+ . '} in write binary mode'
+ );
+ return false;
+ } else {
+ $n = floor($v_header['size'] / 512);
+ for ($i = 0; $i < $n; $i++) {
+ $v_content = $this->_readBlock();
+ fwrite($v_dest_file, $v_content, 512);
+ }
+ if (($v_header['size'] % 512) != 0) {
+ $v_content = $this->_readBlock();
+ fwrite($v_dest_file, $v_content, ($v_header['size'] % 512));
+ }
- // ----- 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);
- }
- }
+ @fclose($v_dest_file);
- // ----- 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_header['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)));
- }
+ if ($p_preserve) {
+ @chown($v_header['filename'], $v_header['uid']);
+ @chgrp($v_header['filename'], $v_header['gid']);
+ }
- /* TBC : Seems to be unused ...
- if ($this->_compress)
- $v_end_of_file = @gzeof($this->_file);
- else
- $v_end_of_file = @feof($this->_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);
+ }
+ }
- 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 = '/';
+ // ----- Check the file size
+ clearstatcache();
+ if (!is_file($v_header['filename'])) {
+ $this->_error(
+ 'Extracted file ' . $v_header['filename']
+ . 'does not exist. Archive may be corrupted.'
+ );
+ return false;
+ }
- $p_list_detail[$v_nb++] = $v_header;
- if (is_array($p_file_list) && (count($p_list_detail) == count($p_file_list))) {
- return true;
+ $filesize = filesize($v_header['filename']);
+ if ($filesize != $v_header['size']) {
+ $this->_error(
+ 'Extracted file ' . $v_header['filename']
+ . ' does not have the correct file size \''
+ . $filesize
+ . '\' (' . $v_header['size']
+ . ' expected). Archive may be corrupted.'
+ );
+ return false;
+ }
+ }
+ } else {
+ $this->_jumpBlock(ceil(($v_header['size'] / 512)));
+ }
+ } else {
+ $this->_jumpBlock(ceil(($v_header['size'] / 512)));
+ }
+
+ /* TBC : Seems to be unused ...
+ if ($this->_compress)
+ $v_end_of_file = @gzeof($this->_file);
+ else
+ $v_end_of_file = @feof($this->_file);
+ */
+
+ if ($v_listing || $v_extract_file || $v_extraction_stopped) {
+ // ----- Log extracted files
+ if (($v_file_dir = dirname($v_header['filename']))
+ == $v_header['filename']
+ ) {
+ $v_file_dir = '';
+ }
+ if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == '')) {
+ $v_file_dir = '/';
+ }
+
+ $p_list_detail[$v_nb++] = $v_header;
+ if (is_array($p_file_list) && (count($p_list_detail) == count($p_file_list))) {
+ return true;
+ }
+ }
}
- }
- }
return true;
}
- // }}}
- // {{{ _openAppend()
- function _openAppend()
+ /**
+ * @return bool
+ */
+ public function _openAppend()
{
- if (filesize($this->_tarname) == 0)
- return $this->_openWrite();
+ 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\'');
+ if (!@rename($this->_tarname, $this->_tarname . ".tmp")) {
+ $this->_error(
+ 'Error while renaming \'' . $this->_tarname
+ . '\' to temporary file \'' . $this->_tarname
+ . '.tmp\''
+ );
return false;
}
- if ($this->_compress_type == 'gz')
- $v_temp_tar = @gzopen($this->_tarname.".tmp", "rb");
- elseif ($this->_compress_type == 'bz2')
- $v_temp_tar = @bzopen($this->_tarname.".tmp", "r");
+ if ($this->_compress_type == 'gz') {
+ $v_temp_tar = @gzopen($this->_tarname . ".tmp", "rb");
+ } elseif ($this->_compress_type == 'bz2') {
+ $v_temp_tar = @bzopen($this->_tarname . ".tmp", "r");
+ } elseif ($this->_compress_type == 'lzma2') {
+ $v_temp_tar = @xzopen($this->_tarname . ".tmp", "r");
+ }
+
if ($v_temp_tar == 0) {
- $this->_error('Unable to open file \''.$this->_tarname
- .'.tmp\' in binary read mode');
- @rename($this->_tarname.".tmp", $this->_tarname);
+ $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);
+ @rename($this->_tarname . ".tmp", $this->_tarname);
return false;
}
if ($this->_compress_type == 'gz') {
+ $end_blocks = 0;
+
while (!@gzeof($v_temp_tar)) {
$v_buffer = @gzread($v_temp_tar, 512);
- if ($v_buffer == ARCHIVE_TAR_END_BLOCK) {
+ if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
+ $end_blocks++;
// do not copy end blocks, we will re-make them
// after appending
continue;
+ } elseif ($end_blocks > 0) {
+ for ($i = 0; $i < $end_blocks; $i++) {
+ $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
+ }
+ $end_blocks = 0;
}
$v_binary_data = pack("a512", $v_buffer);
$this->_writeBlock($v_binary_data);
}
@gzclose($v_temp_tar);
- }
- elseif ($this->_compress_type == 'bz2') {
+ } elseif ($this->_compress_type == 'bz2') {
+ $end_blocks = 0;
+
while (strlen($v_buffer = @bzread($v_temp_tar, 512)) > 0) {
- if ($v_buffer == ARCHIVE_TAR_END_BLOCK) {
+ if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
+ $end_blocks++;
+ // do not copy end blocks, we will re-make them
+ // after appending
continue;
+ } elseif ($end_blocks > 0) {
+ for ($i = 0; $i < $end_blocks; $i++) {
+ $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
+ }
+ $end_blocks = 0;
}
$v_binary_data = pack("a512", $v_buffer);
$this->_writeBlock($v_binary_data);
}
@bzclose($v_temp_tar);
- }
+ } elseif ($this->_compress_type == 'lzma2') {
+ $end_blocks = 0;
- if (!@unlink($this->_tarname.".tmp")) {
- $this->_error('Error while deleting temporary file \''
- .$this->_tarname.'.tmp\'');
+ while (strlen($v_buffer = @xzread($v_temp_tar, 512)) > 0) {
+ if ($v_buffer == ARCHIVE_TAR_END_BLOCK || strlen($v_buffer) == 0) {
+ $end_blocks++;
+ // do not copy end blocks, we will re-make them
+ // after appending
+ continue;
+ } elseif ($end_blocks > 0) {
+ for ($i = 0; $i < $end_blocks; $i++) {
+ $this->_writeBlock(ARCHIVE_TAR_END_BLOCK);
+ }
+ $end_blocks = 0;
+ }
+ $v_binary_data = pack("a512", $v_buffer);
+ $this->_writeBlock($v_binary_data);
+ }
+
+ @xzclose($v_temp_tar);
}
+ if (!@unlink($this->_tarname . ".tmp")) {
+ $this->_error(
+ 'Error while deleting temporary file \''
+ . $this->_tarname . '.tmp\''
+ );
+ }
} else {
// ----- For not compressed tar, just add files before the last
- // one or two 512 bytes block
- if (!$this->_openReadWrite())
- return false;
+ // one or two 512 bytes block
+ if (!$this->_openReadWrite()) {
+ return false;
+ }
clearstatcache();
$v_size = filesize($this->_tarname);
@@ -1779,32 +2395,34 @@ class Archive_Tar extends PEAR
fseek($this->_file, $v_size - 1024);
if (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
fseek($this->_file, $v_size - 1024);
- }
- elseif (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
+ } elseif (fread($this->_file, 512) == ARCHIVE_TAR_END_BLOCK) {
fseek($this->_file, $v_size - 512);
}
}
return true;
}
- // }}}
- // {{{ _append()
- function _append($p_filelist, $p_add_dir='', $p_remove_dir='')
+ /**
+ * @param $p_filelist
+ * @param string $p_add_dir
+ * @param string $p_remove_dir
+ * @return bool
+ */
+ public function _append($p_filelist, $p_add_dir = '', $p_remove_dir = '')
{
- if (!$this->_openAppend())
+ if (!$this->_openAppend()) {
return false;
+ }
- if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir))
- $this->_writeFooter();
+ 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
@@ -1812,22 +2430,25 @@ class Archive_Tar extends PEAR
*
* @param string $p_dir directory to check
*
- * @return bool TRUE if the directory exists or was created
+ * @return bool true if the directory exists or was created
*/
- function _dirCheck($p_dir)
+ public function _dirCheck($p_dir)
{
clearstatcache();
- if ((@is_dir($p_dir)) || ($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;
+ (!$this->_dirCheck($p_parent_dir))
+ ) {
+ return false;
+ }
- if (!@mkdir($p_dir, 0777)) {
+ if (!@mkdir($p_dir, 0775)) {
$this->_error("Unable to create directory '$p_dir'");
return false;
}
@@ -1835,10 +2456,6 @@ class Archive_Tar extends PEAR
return true;
}
- // }}}
-
- // {{{ _pathReduction()
-
/**
* Compress path by changing for example "/dir/foo/../bar" to "/dir/bar",
* rand emove double slashes.
@@ -1846,11 +2463,8 @@ class Archive_Tar extends PEAR
* @param string $p_dir path to reduce
*
* @return string reduced path
- *
- * @access private
- *
*/
- function _pathReduction($p_dir)
+ private function _pathReduction($p_dir)
{
$v_result = '';
@@ -1860,50 +2474,57 @@ class Archive_Tar extends PEAR
$v_list = explode('/', $p_dir);
// ----- Study directories from last to first
- for ($i=sizeof($v_list)-1; $i>=0; $i--) {
+ for ($i = sizeof($v_list) - 1; $i >= 0; $i--) {
// ----- Look for current path
if ($v_list[$i] == ".") {
// ----- Ignore this directory
// Should be the first $i=0, but no check is done
- }
- else if ($v_list[$i] == "..") {
- // ----- Ignore it and ignore the $i-1
- $i--;
- }
- else if ( ($v_list[$i] == '')
- && ($i!=(sizeof($v_list)-1))
- && ($i!=0)) {
- // ----- Ignore only the double '//' in path,
- // but not the first and last /
} else {
- $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?'/'
- .$v_result:'');
+ if ($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, '\\', '/');
+
+ if (defined('OS_WINDOWS') && OS_WINDOWS) {
+ $v_result = strtr($v_result, '\\', '/');
+ }
+
return $v_result;
}
- // }}}
-
- // {{{ _translateWinPath()
- function _translateWinPath($p_path, $p_remove_disk_letter=true)
+ /**
+ * @param $p_path
+ * @param bool $p_remove_disk_letter
+ * @return string
+ */
+ public function _translateWinPath($p_path, $p_remove_disk_letter = true)
{
- if (defined('OS_WINDOWS') && OS_WINDOWS) {
- // ----- Look for potential disk letter
- if ( ($p_remove_disk_letter)
- && (($v_position = strpos($p_path, ':')) != false)) {
- $p_path = substr($p_path, $v_position+1);
- }
- // ----- Change potential windows directory separator
- if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) {
- $p_path = strtr($p_path, '\\', '/');
- }
- }
- return $p_path;
+ if (defined('OS_WINDOWS') && OS_WINDOWS) {
+ // ----- Look for potential disk letter
+ if (($p_remove_disk_letter)
+ && (($v_position = strpos($p_path, ':')) != false)
+ ) {
+ $p_path = substr($p_path, $v_position + 1);
+ }
+ // ----- Change potential windows directory separator
+ if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0, 1) == '\\')) {
+ $p_path = strtr($p_path, '\\', '/');
+ }
+ }
+ return $p_path;
}
- // }}}
-
}
-?>
diff --git a/includes/pear/HTTP.php b/includes/pear/HTTP.php
index 6ebd6db..064a42c 100644..100755
--- a/includes/pear/HTTP.php
+++ b/includes/pear/HTTP.php
@@ -471,38 +471,30 @@ location.replace("'.str_replace('"', '\\"', $url).'");
}
if (empty($protocol)) {
- if (isset($_SERVER['HTTPS']) && !strcasecmp($_SERVER['HTTPS'], 'on')) {
- $protocol = 'https';
- } else {
- $protocol = 'http';
- }
- if (!isset($port) || $port != intval($port)) {
- $port = isset($_SERVER['SERVER_PORT']) ? $_SERVER['SERVER_PORT'] : 80;
- }
- }
+ $protocol = ( isset( $_SERVER['HTTPS'] ) && !strcasecmp( $_SERVER['HTTPS'], 'on' ) ) ? 'https' : 'http';
+ if (!isset( $port ) || $port != intval( $port )) {
+ $port = isset( $_SERVER['SERVER_PORT'] ) ? $_SERVER['SERVER_PORT'] : 80;
+ }
+ }
- if ($protocol == 'http' && $port == 80) {
- unset($port);
- }
- if ($protocol == 'https' && $port == 443) {
- unset($port);
- }
+ if ($protocol == 'http' && $port == 80) {
+ unset( $port );
+ }
+ if ($protocol == 'https' && $port == 443) {
+ unset( $port );
+ }
- $server = $protocol.'://'.$host.(isset($port) ? ':'.$port : '');
+ $server = $protocol . '://' . $host . ( isset( $port ) ? ':' . $port : '' );
- $uriAll = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI']
- : $_SERVER['PHP_SELF'];
- if (false !== ($q = strpos($uriAll, '?'))) {
- $uriBase = substr($uriAll, 0, $q);
- } else {
- $uriBase = $uriAll;
- }
- if (!strlen($url) || $url{0} == '#') {
- $url = $uriAll.$url;
- } elseif ($url{0} == '?') {
+ $uriAll = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI']
+ : $_SERVER['PHP_SELF'];
+ $uriBase = ( false !== ( $q = strpos( $uriAll, '?' ) ) ) ? substr( $uriAll, 0, $q ) : $uriAll;
+ if (!strlen( $url ) || $url[0] == '#') {
+ $url = $uriAll . $url;
+ } elseif ($url[0] == '?') {
$url = $uriBase.$url;
}
- if ($url{0} == '/') {
+ if ($url[0] == '/') {
return $server . $url;
}
@@ -545,4 +537,3 @@ location.replace("'.str_replace('"', '\\"', $url).'");
}
}
-?> \ No newline at end of file
diff --git a/includes/pear/HTTP/Download.php b/includes/pear/HTTP/Download.php
index 8cfc348..de94a8f 100644..100755
--- a/includes/pear/HTTP/Download.php
+++ b/includes/pear/HTTP/Download.php
@@ -247,9 +247,9 @@ class HTTP_Download
*
* @see HTTP_Download::setContentDisposition()
*/
- function HTTP_Download($params = array())
+ function HTTP_Download($params = [])
{
- $this->HTTP = &new HTTP_Header;
+ $this->HTTP = new HTTP_Header;
$this->_error = $this->setParams($params);
}
// }}}
@@ -763,7 +763,7 @@ class HTTP_Download
*/
function staticSend($params, $guess = false)
{
- $d = &new HTTP_Download();
+ $d = new HTTP_Download();
$e = $d->setParams($params);
if (PEAR::isError($e)) {
return $e;
diff --git a/includes/pear/HTTP/Header.php b/includes/pear/HTTP/Header.php
index 14026ad..926d79d 100644..100755
--- a/includes/pear/HTTP/Header.php
+++ b/includes/pear/HTTP/Header.php
@@ -382,11 +382,7 @@ class HTTP_Header extends HTTP
if (is_array($param) && count($param)) {
if (count($param)) {
foreach ($param as $key => $val) {
- if (is_string($key)) {
- $qs[] = urlencode($key) .'='. urlencode($val);
- } else {
- $qs[] = urlencode($val) .'='. urlencode(@$GLOBALS[$val]);
- }
+ $qs[] = ( is_string( $key ) ) ? urlencode( $key ) . '=' . urlencode( $val ) : urlencode( $val ) . '=' . urlencode( @$GLOBALS[$val] );
}
}
}
@@ -457,7 +453,7 @@ class HTTP_Header extends HTTP
function isInformational($http_code)
{
if ($status_type = $this->getStatusType($http_code)) {
- return $status_type{0} == HTTP_HEADER_STATUS_INFORMATIONAL;
+ return $status_type[0] == HTTP_HEADER_STATUS_INFORMATIONAL;
} else {
return false;
}
@@ -471,7 +467,7 @@ class HTTP_Header extends HTTP
function isSuccessful($http_code)
{
if ($status_type = $this->getStatusType($http_code)) {
- return $status_type{0} == HTTP_HEADER_STATUS_SUCCESSFUL;
+ return $status_type[0] == HTTP_HEADER_STATUS_SUCCESSFUL;
} else {
return false;
}
@@ -485,7 +481,7 @@ class HTTP_Header extends HTTP
function isRedirect($http_code)
{
if ($status_type = $this->getStatusType($http_code)) {
- return $status_type{0} == HTTP_HEADER_STATUS_REDIRECT;
+ return $status_type[0] == HTTP_HEADER_STATUS_REDIRECT;
} else {
return false;
}
@@ -499,7 +495,7 @@ class HTTP_Header extends HTTP
function isClientError($http_code)
{
if ($status_type = $this->getStatusType($http_code)) {
- return $status_type{0} == HTTP_HEADER_STATUS_CLIENT_ERROR;
+ return $status_type[0] == HTTP_HEADER_STATUS_CLIENT_ERROR;
} else {
return false;
}
@@ -513,7 +509,7 @@ class HTTP_Header extends HTTP
function isServerError($http_code)
{
if ($status_type = $this->getStatusType($http_code)) {
- return $status_type{0} == HTTP_HEADER_STATUS_SERVER_ERROR;
+ return $status_type[0] == HTTP_HEADER_STATUS_SERVER_ERROR;
} else {
return false;
}
@@ -534,4 +530,3 @@ class HTTP_Header extends HTTP
}
/**#@-*/
}
-?>
diff --git a/includes/pear/HTTP/Request.php b/includes/pear/HTTP/Request.php
new file mode 100755
index 0000000..43fdbfd
--- /dev/null
+++ b/includes/pear/HTTP/Request.php
@@ -0,0 +1,1514 @@
+<?php
+/**
+ * Class for performing HTTP requests
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE:
+ *
+ * Copyright (c) 2002-2007, Richard Heyes
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * o Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * o Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * o The names of the authors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @category HTTP
+ * @package HTTP_Request
+ * @author Richard Heyes <richard@phpguru.org>
+ * @author Alexey Borzov <avb@php.net>
+ * @copyright 2002-2007 Richard Heyes
+ * @license http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version CVS: $Id: Request.php,v 1.63 2008/10/11 11:07:10 avb Exp $
+ * @link http://pear.php.net/package/HTTP_Request/
+ */
+
+/**
+ * PEAR and PEAR_Error classes (for error handling)
+ */
+require_once 'PEAR.php';
+/**
+ * Socket class
+ */
+require_once 'Net/Socket.php';
+/**
+ * URL handling class
+ */
+require_once 'Net/URL.php';
+
+/**#@+
+ * Constants for HTTP request methods
+ */
+define('HTTP_REQUEST_METHOD_GET', 'GET', true);
+define('HTTP_REQUEST_METHOD_HEAD', 'HEAD', true);
+define('HTTP_REQUEST_METHOD_POST', 'POST', true);
+define('HTTP_REQUEST_METHOD_PUT', 'PUT', true);
+define('HTTP_REQUEST_METHOD_DELETE', 'DELETE', true);
+define('HTTP_REQUEST_METHOD_OPTIONS', 'OPTIONS', true);
+define('HTTP_REQUEST_METHOD_TRACE', 'TRACE', true);
+/**#@-*/
+
+/**#@+
+ * Constants for HTTP request error codes
+ */
+define('HTTP_REQUEST_ERROR_FILE', 1);
+define('HTTP_REQUEST_ERROR_URL', 2);
+define('HTTP_REQUEST_ERROR_PROXY', 4);
+define('HTTP_REQUEST_ERROR_REDIRECTS', 8);
+define('HTTP_REQUEST_ERROR_RESPONSE', 16);
+define('HTTP_REQUEST_ERROR_GZIP_METHOD', 32);
+define('HTTP_REQUEST_ERROR_GZIP_READ', 64);
+define('HTTP_REQUEST_ERROR_GZIP_DATA', 128);
+define('HTTP_REQUEST_ERROR_GZIP_CRC', 256);
+/**#@-*/
+
+/**#@+
+ * Constants for HTTP protocol versions
+ */
+define('HTTP_REQUEST_HTTP_VER_1_0', '1.0', true);
+define('HTTP_REQUEST_HTTP_VER_1_1', '1.1', true);
+/**#@-*/
+
+if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) {
+ /**
+ * Whether string functions are overloaded by their mbstring equivalents
+ */
+ define('HTTP_REQUEST_MBSTRING', true);
+} else {
+ /**
+ * @ignore
+ */
+ define('HTTP_REQUEST_MBSTRING', false);
+}
+
+/**
+ * Class for performing HTTP requests
+ *
+ * Simple example (fetches yahoo.com and displays it):
+ * <code>
+ * $a = &new HTTP_Request('http://www.yahoo.com/');
+ * $a->sendRequest();
+ * echo $a->getResponseBody();
+ * </code>
+ *
+ * @category HTTP
+ * @package HTTP_Request
+ * @author Richard Heyes <richard@phpguru.org>
+ * @author Alexey Borzov <avb@php.net>
+ * @version Release: 1.4.4
+ */
+class HTTP_Request
+{
+ /**#@+
+ * @access private
+ */
+ /**
+ * Instance of Net_URL
+ * @var Net_URL
+ */
+ var $_url;
+
+ /**
+ * Type of request
+ * @var string
+ */
+ var $_method;
+
+ /**
+ * HTTP Version
+ * @var string
+ */
+ var $_http;
+
+ /**
+ * Request headers
+ * @var array
+ */
+ var $_requestHeaders;
+
+ /**
+ * Basic Auth Username
+ * @var string
+ */
+ var $_user;
+
+ /**
+ * Basic Auth Password
+ * @var string
+ */
+ var $_pass;
+
+ /**
+ * Socket object
+ * @var Net_Socket
+ */
+ var $_sock;
+
+ /**
+ * Proxy server
+ * @var string
+ */
+ var $_proxy_host;
+
+ /**
+ * Proxy port
+ * @var integer
+ */
+ var $_proxy_port;
+
+ /**
+ * Proxy username
+ * @var string
+ */
+ var $_proxy_user;
+
+ /**
+ * Proxy password
+ * @var string
+ */
+ var $_proxy_pass;
+
+ /**
+ * Post data
+ * @var array
+ */
+ var $_postData;
+
+ /**
+ * Request body
+ * @var string
+ */
+ var $_body;
+
+ /**
+ * A list of methods that MUST NOT have a request body, per RFC 2616
+ * @var array
+ */
+ var $_bodyDisallowed = array('TRACE');
+
+ /**
+ * Methods having defined semantics for request body
+ *
+ * Content-Length header (indicating that the body follows, section 4.3 of
+ * RFC 2616) will be sent for these methods even if no body was added
+ *
+ * @var array
+ */
+ var $_bodyRequired = array('POST', 'PUT');
+
+ /**
+ * Files to post
+ * @var array
+ */
+ var $_postFiles = array();
+
+ /**
+ * Connection timeout.
+ * @var float
+ */
+ var $_timeout;
+
+ /**
+ * HTTP_Response object
+ * @var HTTP_Response
+ */
+ var $_response;
+
+ /**
+ * Whether to allow redirects
+ * @var boolean
+ */
+ var $_allowRedirects;
+
+ /**
+ * Maximum redirects allowed
+ * @var integer
+ */
+ var $_maxRedirects;
+
+ /**
+ * Current number of redirects
+ * @var integer
+ */
+ var $_redirects;
+
+ /**
+ * Whether to append brackets [] to array variables
+ * @var bool
+ */
+ var $_useBrackets = true;
+
+ /**
+ * Attached listeners
+ * @var array
+ */
+ var $_listeners = array();
+
+ /**
+ * Whether to save response body in response object property
+ * @var bool
+ */
+ var $_saveBody = true;
+
+ /**
+ * Timeout for reading from socket (array(seconds, microseconds))
+ * @var array
+ */
+ var $_readTimeout = null;
+
+ /**
+ * Options to pass to Net_Socket::connect. See stream_context_create
+ * @var array
+ */
+ var $_socketOptions = null;
+ /**#@-*/
+
+ /**
+ * Constructor
+ *
+ * Sets up the object
+ * @param string The url to fetch/access
+ * @param array Associative array of parameters which can have the following keys:
+ * <ul>
+ * <li>method - Method to use, GET, POST etc (string)</li>
+ * <li>http - HTTP Version to use, 1.0 or 1.1 (string)</li>
+ * <li>user - Basic Auth username (string)</li>
+ * <li>pass - Basic Auth password (string)</li>
+ * <li>proxy_host - Proxy server host (string)</li>
+ * <li>proxy_port - Proxy server port (integer)</li>
+ * <li>proxy_user - Proxy auth username (string)</li>
+ * <li>proxy_pass - Proxy auth password (string)</li>
+ * <li>timeout - Connection timeout in seconds (float)</li>
+ * <li>allowRedirects - Whether to follow redirects or not (bool)</li>
+ * <li>maxRedirects - Max number of redirects to follow (integer)</li>
+ * <li>useBrackets - Whether to append [] to array variable names (bool)</li>
+ * <li>saveBody - Whether to save response body in response object property (bool)</li>
+ * <li>readTimeout - Timeout for reading / writing data over the socket (array (seconds, microseconds))</li>
+ * <li>socketOptions - Options to pass to Net_Socket object (array)</li>
+ * </ul>
+ * @access public
+ */
+ function HTTP_Request($url = '', $params = array())
+ {
+ $this->_method = HTTP_REQUEST_METHOD_GET;
+ $this->_http = HTTP_REQUEST_HTTP_VER_1_1;
+ $this->_requestHeaders = array();
+ $this->_postData = array();
+ $this->_body = null;
+
+ $this->_user = null;
+ $this->_pass = null;
+
+ $this->_proxy_host = null;
+ $this->_proxy_port = null;
+ $this->_proxy_user = null;
+ $this->_proxy_pass = null;
+
+ $this->_allowRedirects = false;
+ $this->_maxRedirects = 3;
+ $this->_redirects = 0;
+
+ $this->_timeout = null;
+ $this->_response = null;
+
+ foreach ($params as $key => $value) {
+ $this->{'_' . $key} = $value;
+ }
+
+ if (!empty($url)) {
+ $this->setURL($url);
+ }
+
+ // Default useragent
+ $this->addHeader('User-Agent', 'PEAR HTTP_Request class ( http://pear.php.net/ )');
+
+ // We don't do keep-alives by default
+ $this->addHeader('Connection', 'close');
+
+ // Basic authentication
+ if (!empty($this->_user)) {
+ $this->addHeader('Authorization', 'Basic ' . base64_encode($this->_user . ':' . $this->_pass));
+ }
+
+ // Proxy authentication (see bug #5913)
+ if (!empty($this->_proxy_user)) {
+ $this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($this->_proxy_user . ':' . $this->_proxy_pass));
+ }
+
+ // Use gzip encoding if possible
+ if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && extension_loaded('zlib')) {
+ $this->addHeader('Accept-Encoding', 'gzip');
+ }
+ }
+
+ /**
+ * Generates a Host header for HTTP/1.1 requests
+ *
+ * @access private
+ * @return string
+ */
+ function _generateHostHeader()
+ {
+ if ($this->_url->port != 80 AND strcasecmp($this->_url->protocol, 'http') == 0) {
+ $host = $this->_url->host . ':' . $this->_url->port;
+
+ } elseif ($this->_url->port != 443 AND strcasecmp($this->_url->protocol, 'https') == 0) {
+ $host = $this->_url->host . ':' . $this->_url->port;
+
+ } elseif ($this->_url->port == 443 AND strcasecmp($this->_url->protocol, 'https') == 0 AND strpos($this->_url->url, ':443') !== false) {
+ $host = $this->_url->host . ':' . $this->_url->port;
+
+ } else {
+ $host = $this->_url->host;
+ }
+
+ return $host;
+ }
+
+ /**
+ * Resets the object to its initial state (DEPRECATED).
+ * Takes the same parameters as the constructor.
+ *
+ * @param string $url The url to be requested
+ * @param array $params Associative array of parameters
+ * (see constructor for details)
+ * @access public
+ * @deprecated deprecated since 1.2, call the constructor if this is necessary
+ */
+ function reset($url, $params = array())
+ {
+ $this->HTTP_Request($url, $params);
+ }
+
+ /**
+ * Sets the URL to be requested
+ *
+ * @param string The url to be requested
+ * @access public
+ */
+ function setURL($url)
+ {
+ $this->_url = &new Net_URL($url, $this->_useBrackets);
+
+ if (!empty($this->_url->user) || !empty($this->_url->pass)) {
+ $this->setBasicAuth($this->_url->user, $this->_url->pass);
+ }
+
+ if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http) {
+ $this->addHeader('Host', $this->_generateHostHeader());
+ }
+
+ // set '/' instead of empty path rather than check later (see bug #8662)
+ if (empty($this->_url->path)) {
+ $this->_url->path = '/';
+ }
+ }
+
+ /**
+ * Returns the current request URL
+ *
+ * @return string Current request URL
+ * @access public
+ */
+ function getUrl()
+ {
+ return empty($this->_url)? '': $this->_url->getUrl();
+ }
+
+ /**
+ * Sets a proxy to be used
+ *
+ * @param string Proxy host
+ * @param int Proxy port
+ * @param string Proxy username
+ * @param string Proxy password
+ * @access public
+ */
+ function setProxy($host, $port = 8080, $user = null, $pass = null)
+ {
+ $this->_proxy_host = $host;
+ $this->_proxy_port = $port;
+ $this->_proxy_user = $user;
+ $this->_proxy_pass = $pass;
+
+ if (!empty($user)) {
+ $this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($user . ':' . $pass));
+ }
+ }
+
+ /**
+ * Sets basic authentication parameters
+ *
+ * @param string Username
+ * @param string Password
+ */
+ function setBasicAuth($user, $pass)
+ {
+ $this->_user = $user;
+ $this->_pass = $pass;
+
+ $this->addHeader('Authorization', 'Basic ' . base64_encode($user . ':' . $pass));
+ }
+
+ /**
+ * Sets the method to be used, GET, POST etc.
+ *
+ * @param string Method to use. Use the defined constants for this
+ * @access public
+ */
+ function setMethod($method)
+ {
+ $this->_method = $method;
+ }
+
+ /**
+ * Sets the HTTP version to use, 1.0 or 1.1
+ *
+ * @param string Version to use. Use the defined constants for this
+ * @access public
+ */
+ function setHttpVer($http)
+ {
+ $this->_http = $http;
+ }
+
+ /**
+ * Adds a request header
+ *
+ * @param string Header name
+ * @param string Header value
+ * @access public
+ */
+ function addHeader($name, $value)
+ {
+ $this->_requestHeaders[strtolower($name)] = $value;
+ }
+
+ /**
+ * Removes a request header
+ *
+ * @param string Header name to remove
+ * @access public
+ */
+ function removeHeader($name)
+ {
+ if (isset($this->_requestHeaders[strtolower($name)])) {
+ unset($this->_requestHeaders[strtolower($name)]);
+ }
+ }
+
+ /**
+ * Adds a querystring parameter
+ *
+ * @param string Querystring parameter name
+ * @param string Querystring parameter value
+ * @param bool Whether the value is already urlencoded or not, default = not
+ * @access public
+ */
+ function addQueryString($name, $value, $preencoded = false)
+ {
+ $this->_url->addQueryString($name, $value, $preencoded);
+ }
+
+ /**
+ * Sets the querystring to literally what you supply
+ *
+ * @param string The querystring data. Should be of the format foo=bar&x=y etc
+ * @param bool Whether data is already urlencoded or not, default = already encoded
+ * @access public
+ */
+ function addRawQueryString($querystring, $preencoded = true)
+ {
+ $this->_url->addRawQueryString($querystring, $preencoded);
+ }
+
+ /**
+ * Adds postdata items
+ *
+ * @param string Post data name
+ * @param string Post data value
+ * @param bool Whether data is already urlencoded or not, default = not
+ * @access public
+ */
+ function addPostData($name, $value, $preencoded = false)
+ {
+ $this->_postData[$name] = ( $preencoded ) ? $value : $this->_arrayMapRecursive( 'urlencode', $value );
+ }
+
+ /**
+ * Recursively applies the callback function to the value
+ *
+ * @param mixed Callback function
+ * @param mixed Value to process
+ * @access private
+ * @return mixed Processed value
+ */
+ function _arrayMapRecursive( $callback, $value )
+ {
+ if (!is_array( $value )) {
+ return call_user_func( $callback, $value );
+ }
+ else {
+ $map = array();
+ foreach ( $value as $k => $v ) {
+ $map[$k] = $this->_arrayMapRecursive( $callback, $v );
+ }
+ return $map;
+ }
+ }
+
+ /**
+ * Adds a file to form-based file upload
+ *
+ * Used to emulate file upload via a HTML form. The method also sets
+ * Content-Type of HTTP request to 'multipart/form-data'.
+ *
+ * If you just want to send the contents of a file as the body of HTTP
+ * request you should use setBody() method.
+ *
+ * @access public
+ * @param string name of file-upload field
+ * @param mixed file name(s)
+ * @param mixed content-type(s) of file(s) being uploaded
+ * @return bool true on success
+ * @throws PEAR_Error
+ */
+ function addFile( $inputName, $fileName, $contentType = 'application/octet-stream' )
+ {
+ if (!is_array( $fileName ) && !is_readable( $fileName )) {
+ return PEAR::raiseError( "File '{$fileName}' is not readable", HTTP_REQUEST_ERROR_FILE );
+ }
+ elseif (is_array( $fileName )) {
+ foreach ( $fileName as $name ) {
+ if (!is_readable( $name )) {
+ return PEAR::raiseError( "File '{$name}' is not readable", HTTP_REQUEST_ERROR_FILE );
+ }
+ }
+ }
+ $this->addHeader( 'Content-Type', 'multipart/form-data' );
+ $this->_postFiles[$inputName] = array(
+ 'name' => $fileName,
+ 'type' => $contentType,
+ );
+ return true;
+ }
+
+ /**
+ * Adds raw postdata (DEPRECATED)
+ *
+ * @param string The data
+ * @param bool Whether data is preencoded or not, default = already encoded
+ * @access public
+ * @deprecated deprecated since 1.3.0, method setBody() should be used instead
+ */
+ function addRawPostData( $postdata, $preencoded = true )
+ {
+ $this->_body = $preencoded ? $postdata : urlencode( $postdata );
+ }
+
+ /**
+ * Sets the request body (for POST, PUT and similar requests)
+ *
+ * @param string Request body
+ * @access public
+ */
+ function setBody( $body )
+ {
+ $this->_body = $body;
+ }
+
+ /**
+ * Clears any postdata that has been added (DEPRECATED).
+ *
+ * Useful for multiple request scenarios.
+ *
+ * @access public
+ * @deprecated deprecated since 1.2
+ */
+ function clearPostData()
+ {
+ $this->_postData = null;
+ }
+
+ /**
+ * Appends a cookie to "Cookie:" header
+ *
+ * @param string $name cookie name
+ * @param string $value cookie value
+ * @access public
+ */
+ function addCookie( $name, $value )
+ {
+ $cookies = isset( $this->_requestHeaders['cookie'] ) ? $this->_requestHeaders['cookie'] . '; ' : '';
+ $this->addHeader( 'Cookie', $cookies . $name . '=' . $value );
+ }
+
+ /**
+ * Clears any cookies that have been added (DEPRECATED).
+ *
+ * Useful for multiple request scenarios
+ *
+ * @access public
+ * @deprecated deprecated since 1.2
+ */
+ function clearCookies()
+ {
+ $this->removeHeader( 'Cookie' );
+ }
+
+ /**
+ * Sends the request
+ *
+ * @access public
+ * @param bool Whether to store response body in Response object property,
+ * set this to false if downloading a LARGE file and using a Listener
+ * @return mixed PEAR error on error, true otherwise
+ */
+ function sendRequest( $saveBody = true )
+ {
+ if (!is_a( $this->_url, 'Net_URL' )) {
+ return PEAR::raiseError( 'No URL given', HTTP_REQUEST_ERROR_URL );
+ }
+
+ $host = isset( $this->_proxy_host ) ? $this->_proxy_host : $this->_url->host;
+ $port = isset( $this->_proxy_port ) ? $this->_proxy_port : $this->_url->port;
+
+ if (strcasecmp( $this->_url->protocol, 'https' ) == 0) {
+ // Bug #14127, don't try connecting to HTTPS sites without OpenSSL
+ if (version_compare( PHP_VERSION, '4.3.0', '<' ) || !extension_loaded( 'openssl' )) {
+ return PEAR::raiseError( 'Need PHP 4.3.0 or later with OpenSSL support for https:// requests',
+ HTTP_REQUEST_ERROR_URL );
+ }
+ elseif (isset( $this->_proxy_host )) {
+ return PEAR::raiseError( 'HTTPS proxies are not supported', HTTP_REQUEST_ERROR_PROXY );
+ }
+ $host = 'ssl://' . $host;
+ }
+
+ // magic quotes may fuck up file uploads and chunked response processing
+ $magicQuotes = ini_get( 'magic_quotes_runtime' );
+ ini_set( 'magic_quotes_runtime', false );
+
+ // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive
+ // connection token to a proxy server...
+ if (isset( $this->_proxy_host ) && !empty( $this->_requestHeaders['connection'] ) &&
+ 'Keep-Alive' == $this->_requestHeaders['connection']) {
+ $this->removeHeader( 'connection' );
+ }
+
+ $keepAlive = ( HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && empty( $this->_requestHeaders['connection'] ) ) ||
+ ( !empty( $this->_requestHeaders['connection'] ) && 'Keep-Alive' == $this->_requestHeaders['connection'] );
+ $sockets = &PEAR::getStaticProperty( 'HTTP_Request', 'sockets' );
+ $sockKey = $host . ':' . $port;
+ unset( $this->_sock );
+
+ // There is a connected socket in the "static" property?
+ if ($keepAlive && !empty( $sockets[$sockKey] ) &&
+ !empty( $sockets[$sockKey]->fp )) {
+ $this->_sock =& $sockets[$sockKey];
+ $err = null;
+ }
+ else {
+ $this->_notify( 'connect' );
+ $this->_sock =& new Net_Socket();
+ $err = $this->_sock->connect( $host, $port, null, $this->_timeout, $this->_socketOptions );
+ }
+ PEAR::isError( $err ) or $err = $this->_sock->write( $this->_buildRequest() );
+
+ if (!PEAR::isError( $err )) {
+ if (!empty( $this->_readTimeout )) {
+ $this->_sock->setTimeout( $this->_readTimeout[0], $this->_readTimeout[1] );
+ }
+
+ $this->_notify( 'sentRequest' );
+
+ // Read the response
+ $this->_response = &new HTTP_Response( $this->_sock, $this->_listeners );
+ $err = $this->_response->process(
+ $this->_saveBody && $saveBody,
+ HTTP_REQUEST_METHOD_HEAD != $this->_method
+ );
+
+ if ($keepAlive) {
+ $keepAlive = ( isset( $this->_response->_headers['content-length'] )
+ || ( isset( $this->_response->_headers['transfer-encoding'] )
+ && strtolower( $this->_response->_headers['transfer-encoding'] ) == 'chunked' ) );
+ if ($keepAlive) {
+ $keepAlive = ( isset( $this->_response->_headers['connection'] ) ) ? strtolower( $this->_response->_headers['connection'] ) == 'keep-alive' : 'HTTP/' . HTTP_REQUEST_HTTP_VER_1_1 == $this->_response->_protocol;
+ }
+ }
+ }
+
+ ini_set( 'magic_quotes_runtime', $magicQuotes );
+
+ if (PEAR::isError( $err )) {
+ return $err;
+ }
+
+ if (!$keepAlive) {
+ $this->disconnect();
+ // Store the connected socket in "static" property
+ }
+ elseif (empty( $sockets[$sockKey] ) || empty( $sockets[$sockKey]->fp )) {
+ $sockets[$sockKey] =& $this->_sock;
+ }
+
+ // Check for redirection
+ if ($this->_allowRedirects
+ AND $this->_redirects <= $this->_maxRedirects
+ AND $this->getResponseCode() > 300
+ AND $this->getResponseCode() < 399
+ AND !empty( $this->_response->_headers['location'] )) {
+
+ $redirect = $this->_response->_headers['location'];
+
+ // Absolute URL
+ if (preg_match( '/^https?:\/\//i', $redirect )) {
+ $this->_url = &new Net_URL( $redirect );
+ $this->addHeader( 'Host', $this->_generateHostHeader() );
+ // Absolute path
+ }
+ elseif ($redirect[0] == '/') {
+ $this->_url->path = $redirect;
+
+ // Relative path
+ }
+ elseif (substr( $redirect, 0, 3 ) == '../' OR substr( $redirect, 0, 2 ) == './') {
+ $redirect = ( substr( $this->_url->path, -1 ) == '/' ) ? $this->_url->path . $redirect : dirname( $this->_url->path ) . '/' . $redirect;
+ $redirect = Net_URL::resolvePath( $redirect );
+ $this->_url->path = $redirect;
+
+ // Filename, no path
+ }
+ else {
+ $redirect = ( substr( $this->_url->path, -1 ) == '/' ) ? $this->_url->path . $redirect : dirname( $this->_url->path ) . '/' . $redirect;
+ $this->_url->path = $redirect;
+ }
+
+ $this->_redirects++;
+ return $this->sendRequest( $saveBody );
+
+ // Too many redirects
+ }
+ elseif ($this->_allowRedirects AND $this->_redirects > $this->_maxRedirects) {
+ return PEAR::raiseError( 'Too many redirects', HTTP_REQUEST_ERROR_REDIRECTS );
+ }
+
+ return true;
+ }
+
+ /**
+ * Disconnect the socket, if connected. Only useful if using Keep-Alive.
+ *
+ * @access public
+ */
+ function disconnect()
+ {
+ if (!empty( $this->_sock ) && !empty( $this->_sock->fp )) {
+ $this->_notify( 'disconnect' );
+ $this->_sock->disconnect();
+ }
+ }
+
+ /**
+ * Returns the response code
+ *
+ * @access public
+ * @return mixed Response code, false if not set
+ */
+ function getResponseCode()
+ {
+ return isset( $this->_response->_code ) ? $this->_response->_code : false;
+ }
+
+ /**
+ * Returns the response reason phrase
+ *
+ * @access public
+ * @return mixed Response reason phrase, false if not set
+ */
+ function getResponseReason()
+ {
+ return isset( $this->_response->_reason ) ? $this->_response->_reason : false;
+ }
+
+ /**
+ * Returns either the named header or all if no name given
+ *
+ * @access public
+ * @param string The header name to return, do not set to get all headers
+ * @return mixed either the value of $headername (false if header is not present)
+ * or an array of all headers
+ */
+ function getResponseHeader( $headername = null )
+ {
+ if (!isset( $headername )) {
+ return isset( $this->_response->_headers ) ? $this->_response->_headers : array();
+ }
+ else {
+ $headername = strtolower( $headername );
+ return isset( $this->_response->_headers[$headername] ) ? $this->_response->_headers[$headername] : false;
+ }
+ }
+
+ /**
+ * Returns the body of the response
+ *
+ * @access public
+ * @return mixed response body, false if not set
+ */
+ function getResponseBody()
+ {
+ return isset( $this->_response->_body ) ? $this->_response->_body : false;
+ }
+
+ /**
+ * Returns cookies set in response
+ *
+ * @access public
+ * @return mixed array of response cookies, false if none are present
+ */
+ function getResponseCookies()
+ {
+ return isset( $this->_response->_cookies ) ? $this->_response->_cookies : false;
+ }
+
+ /**
+ * Builds the request string
+ *
+ * @access private
+ * @return string The request string
+ */
+ function _buildRequest()
+ {
+ $separator = ini_get( 'arg_separator.output' );
+ ini_set( 'arg_separator.output', '&' );
+ $querystring = ( $querystring = $this->_url->getQueryString() ) ? '?' . $querystring : '';
+ ini_set( 'arg_separator.output', $separator );
+
+ $host = isset( $this->_proxy_host ) ? $this->_url->protocol . '://' . $this->_url->host : '';
+ $port = ( isset( $this->_proxy_host ) AND $this->_url->port != 80 ) ? ':' . $this->_url->port : '';
+ $path = $this->_url->path . $querystring;
+ $url = $host . $port . $path;
+
+ if (!strlen( $url )) {
+ $url = '/';
+ }
+
+ $request = $this->_method . ' ' . $url . ' HTTP/' . $this->_http . "\r\n";
+
+ if (in_array( $this->_method, $this->_bodyDisallowed ) ||
+ ( 0 == strlen( $this->_body ) && ( HTTP_REQUEST_METHOD_POST != $this->_method ||
+ ( empty( $this->_postData ) && empty( $this->_postFiles ) ) ) )) {
+ $this->removeHeader( 'Content-Type' );
+ }
+ else {
+ if (empty( $this->_requestHeaders['content-type'] )) {
+ // Add default content-type
+ $this->addHeader( 'Content-Type', 'application/x-www-form-urlencoded' );
+ }
+ elseif ('multipart/form-data' == $this->_requestHeaders['content-type']) {
+ $boundary = 'HTTP_Request_' . md5( uniqid( 'request' ) . microtime() );
+ $this->addHeader( 'Content-Type', 'multipart/form-data; boundary=' . $boundary );
+ }
+ }
+
+ // Request Headers
+ if (!empty( $this->_requestHeaders )) {
+ foreach ( $this->_requestHeaders as $name => $value ) {
+ $canonicalName = implode( '-', array_map( 'ucfirst', explode( '-', $name ) ) );
+ $request .= $canonicalName . ': ' . $value . "\r\n";
+ }
+ }
+
+ // Method does not allow a body, simply add a final CRLF
+ if (in_array( $this->_method, $this->_bodyDisallowed )) {
+
+ $request .= "\r\n";
+
+ // Post data if it's an array
+ }
+ elseif (HTTP_REQUEST_METHOD_POST == $this->_method &&
+ ( !empty( $this->_postData ) || !empty( $this->_postFiles ) )) {
+
+ // "normal" POST request
+ if (!isset( $boundary )) {
+ $postdata = implode( '&', array_map(
+ create_function( '$a', 'return $a[0] . \'=\' . $a[1];' ),
+ $this->_flattenArray( '', $this->_postData )
+ ) );
+
+ // multipart request, probably with file uploads
+ }
+ else {
+ $postdata = '';
+ if (!empty( $this->_postData )) {
+ $flatData = $this->_flattenArray( '', $this->_postData );
+ foreach ( $flatData as $item ) {
+ $postdata .= '--' . $boundary . "\r\n";
+ $postdata .= 'Content-Disposition: form-data; name="' . $item[0] . '"';
+ $postdata .= "\r\n\r\n" . urldecode( $item[1] ) . "\r\n";
+ }
+ }
+ foreach ( $this->_postFiles as $name => $value ) {
+ if (is_array( $value['name'] )) {
+ $varname = $name . ( $this->_useBrackets ? '[]' : '' );
+ }
+ else {
+ $varname = $name;
+ $value['name'] = array( $value['name'] );
+ }
+ foreach ( $value['name'] as $key => $filename ) {
+ $fp = fopen( $filename, 'r' );
+ $basename = basename( $filename );
+ $type = is_array( $value['type'] ) ? @$value['type'][$key] : $value['type'];
+
+ $postdata .= '--' . $boundary . "\r\n";
+ $postdata .= 'Content-Disposition: form-data; name="' . $varname . '"; filename="' . $basename . '"';
+ $postdata .= "\r\nContent-Type: " . $type;
+ $postdata .= "\r\n\r\n" . fread( $fp, filesize( $filename ) ) . "\r\n";
+ fclose( $fp );
+ }
+ }
+ $postdata .= '--' . $boundary . "--\r\n";
+ }
+ $request .= 'Content-Length: ' .
+ ( HTTP_REQUEST_MBSTRING ? mb_strlen( $postdata, 'iso-8859-1' ) : strlen( $postdata ) ) .
+ "\r\n\r\n";
+ $request .= $postdata;
+
+ // Explicitly set request body
+ }
+ elseif (0 < strlen( $this->_body )) {
+
+ $request .= 'Content-Length: ' .
+ ( HTTP_REQUEST_MBSTRING ? mb_strlen( $this->_body, 'iso-8859-1' ) : strlen( $this->_body ) ) .
+ "\r\n\r\n";
+ $request .= $this->_body;
+
+ // No body: send a Content-Length header nonetheless (request #12900),
+ // but do that only for methods that require a body (bug #14740)
+ }
+ else {
+
+ if (in_array( $this->_method, $this->_bodyRequired )) {
+ $request .= "Content-Length: 0\r\n";
+ }
+ $request .= "\r\n";
+ }
+
+ return $request;
+ }
+
+ /**
+ * Helper function to change the (probably multidimensional) associative array
+ * into the simple one.
+ *
+ * @param string name for item
+ * @param mixed item's values
+ * @return array array with the following items: array('item name', 'item value');
+ * @access private
+ */
+ function _flattenArray( $name, $values )
+ {
+ if (!is_array( $values )) {
+ return array( array( $name, $values ) );
+ }
+ else {
+ $ret = array();
+ foreach ( $values as $k => $v ) {
+ if (empty( $name )) {
+ $newName = $k;
+ }
+ elseif ($this->_useBrackets) {
+ $newName = $name . '[' . $k . ']';
+ }
+ else {
+ $newName = $name;
+ }
+ $ret = array_merge( $ret, $this->_flattenArray( $newName, $v ) );
+ }
+ return $ret;
+ }
+ }
+
+ /**
+ * Adds a Listener to the list of listeners that are notified of
+ * the object's events
+ *
+ * Events sent by HTTP_Request object
+ * - 'connect': on connection to server
+ * - 'sentRequest': after the request was sent
+ * - 'disconnect': on disconnection from server
+ *
+ * Events sent by HTTP_Response object
+ * - 'gotHeaders': after receiving response headers (headers are passed in $data)
+ * - 'tick': on receiving a part of response body (the part is passed in $data)
+ * - 'gzTick': on receiving a gzip-encoded part of response body (ditto)
+ * - 'gotBody': after receiving the response body (passes the decoded body in $data if it was gzipped)
+ *
+ * @param HTTP_Request_Listener listener to attach
+ * @return boolean whether the listener was successfully attached
+ * @access public
+ */
+ function attach( &$listener )
+ {
+ if (!is_a( $listener, 'HTTP_Request_Listener' )) {
+ return false;
+ }
+ $this->_listeners[$listener->getId()] =& $listener;
+ return true;
+ }
+
+ /**
+ * Removes a Listener from the list of listeners
+ *
+ * @param HTTP_Request_Listener listener to detach
+ * @return boolean whether the listener was successfully detached
+ * @access public
+ */
+ function detach( &$listener )
+ {
+ if (!is_a( $listener, 'HTTP_Request_Listener' ) ||
+ !isset( $this->_listeners[$listener->getId()] )) {
+ return false;
+ }
+ unset( $this->_listeners[$listener->getId()] );
+ return true;
+ }
+
+ /**
+ * Notifies all registered listeners of an event.
+ *
+ * @param string Event name
+ * @param mixed Additional data
+ * @access private
+ * @see HTTP_Request::attach()
+ */
+ function _notify( $event, $data = null )
+ {
+ foreach ( array_keys( $this->_listeners ) as $id ) {
+ $this->_listeners[$id]->update( $this, $event, $data );
+ }
+ }
+
+}
+
+/**
+ * Response class to complement the Request class
+ *
+ * @category HTTP
+ * @package HTTP_Request
+ * @author Richard Heyes <richard@phpguru.org>
+ * @author Alexey Borzov <avb@php.net>
+ * @version Release: 1.4.4
+ */
+class HTTP_Response
+{
+ /**
+ * Socket object
+ * @var Net_Socket
+ */
+ var $_sock;
+
+ /**
+ * Protocol
+ * @var string
+ */
+ var $_protocol;
+
+ /**
+ * Return code
+ * @var string
+ */
+ var $_code;
+
+ /**
+ * Response reason phrase
+ * @var string
+ */
+ var $_reason;
+
+ /**
+ * Response headers
+ * @var array
+ */
+ var $_headers;
+
+ /**
+ * Cookies set in response
+ * @var array
+ */
+ var $_cookies;
+
+ /**
+ * Response body
+ * @var string
+ */
+ var $_body = '';
+
+ /**
+ * Used by _readChunked(): remaining length of the current chunk
+ * @var string
+ */
+ var $_chunkLength = 0;
+
+ /**
+ * Attached listeners
+ * @var array
+ */
+ var $_listeners = array();
+
+ /**
+ * Bytes left to read from message-body
+ * @var null|int
+ */
+ var $_toRead;
+
+ /**
+ * Constructor
+ *
+ * @param Net_Socket socket to read the response from
+ * @param array listeners attached to request
+ */
+ function HTTP_Response( &$sock, &$listeners )
+ {
+ $this->_sock =& $sock;
+ $this->_listeners =& $listeners;
+ }
+
+ /**
+ * Processes a HTTP response
+ *
+ * This extracts response code, headers, cookies and decodes body if it
+ * was encoded in some way
+ *
+ * @access public
+ * @param bool Whether to store response body in object property, set
+ * this to false if downloading a LARGE file and using a Listener.
+ * This is assumed to be true if body is gzip-encoded.
+ * @param bool Whether the response can actually have a message-body.
+ * Will be set to false for HEAD requests.
+ * @throws PEAR_Error
+ * @return mixed true on success, PEAR_Error in case of malformed response
+ */
+ function process( $saveBody = true, $canHaveBody = true )
+ {
+ do {
+ $line = $this->_sock->readLine();
+ if (!preg_match( '!^(HTTP/\d\.\d) (\d[3])(?: (.+))?!', $line, $s )) {
+ return PEAR::raiseError( 'Malformed response', HTTP_REQUEST_ERROR_RESPONSE );
+ }
+ else {
+ $this->_protocol = $s[1];
+ $this->_code = intval( $s[2] );
+ $this->_reason = empty( $s[3] ) ? null : $s[3];
+ }
+ while ( '' !== ( $header = $this->_sock->readLine() ) ) {
+ $this->_processHeader( $header );
+ }
+ } while ( 100 == $this->_code );
+
+ $this->_notify( 'gotHeaders', $this->_headers );
+
+ // RFC 2616, section 4.4:
+ // 1. Any response message which "MUST NOT" include a message-body ...
+ // is always terminated by the first empty line after the header fields
+ // 3. ... If a message is received with both a
+ // Transfer-Encoding header field and a Content-Length header field,
+ // the latter MUST be ignored.
+ $canHaveBody = $canHaveBody && $this->_code >= 200 &&
+ $this->_code != 204 && $this->_code != 304;
+
+ // If response body is present, read it and decode
+ $chunked = isset( $this->_headers['transfer-encoding'] ) && ( 'chunked' == $this->_headers['transfer-encoding'] );
+ $gzipped = isset( $this->_headers['content-encoding'] ) && ( 'gzip' == $this->_headers['content-encoding'] );
+ $hasBody = false;
+ if ($canHaveBody && ( $chunked || !isset( $this->_headers['content-length'] ) ||
+ 0 != $this->_headers['content-length'] )) {
+ $this->_toRead = ( $chunked || !isset( $this->_headers['content-length'] ) ) ? null : $this->_headers['content-length'];
+ while ( !$this->_sock->eof() && ( is_null( $this->_toRead ) || 0 < $this->_toRead ) ) {
+ if ($chunked) {
+ $data = $this->_readChunked();
+ }
+ elseif (is_null( $this->_toRead )) {
+ $data = $this->_sock->read( 4096 );
+ }
+ else {
+ $data = $this->_sock->read( min( 4096, $this->_toRead ) );
+ $this->_toRead -= HTTP_REQUEST_MBSTRING? mb_strlen($data, 'iso-8859-1'): strlen($data);
+ }
+ if ('' == $data && (!$this->_chunkLength || $this->_sock->eof())) {
+ break;
+ } else {
+ $hasBody = true;
+ if ($saveBody || $gzipped) {
+ $this->_body .= $data;
+ }
+ $this->_notify($gzipped? 'gzTick': 'tick', $data);
+ }
+ }
+ }
+
+ if ($hasBody) {
+ // Uncompress the body if needed
+ if ($gzipped) {
+ $body = $this->_decodeGzip($this->_body);
+ if (PEAR::isError($body)) {
+ return $body;
+ }
+ $this->_body = $body;
+ $this->_notify('gotBody', $this->_body);
+ } else {
+ $this->_notify('gotBody');
+ }
+ }
+ return true;
+ }
+
+
+ /**
+ * Processes the response header
+ *
+ * @access private
+ * @param string HTTP header
+ */
+ function _processHeader($header)
+ {
+ if (false === strpos($header, ':')) {
+ return;
+ }
+ list($headername, $headervalue) = explode(':', $header, 2);
+ $headername = strtolower($headername);
+ $headervalue = ltrim($headervalue);
+
+ if ('set-cookie' != $headername) {
+ if (isset($this->_headers[$headername])) {
+ $this->_headers[$headername] .= ',' . $headervalue;
+ } else {
+ $this->_headers[$headername] = $headervalue;
+ }
+ } else {
+ $this->_parseCookie($headervalue);
+ }
+ }
+
+
+ /**
+ * Parse a Set-Cookie header to fill $_cookies array
+ *
+ * @access private
+ * @param string value of Set-Cookie header
+ */
+ function _parseCookie($headervalue)
+ {
+ $cookie = array(
+ 'expires' => null,
+ 'domain' => null,
+ 'path' => null,
+ 'secure' => false
+ );
+
+ // Only a name=value pair
+ if (!strpos($headervalue, ';')) {
+ $pos = strpos($headervalue, '=');
+ $cookie['name'] = trim(substr($headervalue, 0, $pos));
+ $cookie['value'] = trim(substr($headervalue, $pos + 1));
+
+ // Some optional parameters are supplied
+ } else {
+ $elements = explode(';', $headervalue);
+ $pos = strpos($elements[0], '=');
+ $cookie['name'] = trim(substr($elements[0], 0, $pos));
+ $cookie['value'] = trim(substr($elements[0], $pos + 1));
+
+ for ($i = 1; $i < count($elements); $i++) {
+ if (false === strpos($elements[$i], '=')) {
+ $elName = trim($elements[$i]);
+ $elValue = null;
+ } else {
+ list ($elName, $elValue) = array_map('trim', explode('=', $elements[$i]));
+ }
+ $elName = strtolower($elName);
+ if ('secure' == $elName) {
+ $cookie['secure'] = true;
+ } elseif ('expires' == $elName) {
+ $cookie['expires'] = str_replace('"', '', $elValue);
+ } elseif ('path' == $elName || 'domain' == $elName) {
+ $cookie[$elName] = urldecode($elValue);
+ } else {
+ $cookie[$elName] = $elValue;
+ }
+ }
+ }
+ $this->_cookies[] = $cookie;
+ }
+
+
+ /**
+ * Read a part of response body encoded with chunked Transfer-Encoding
+ *
+ * @access private
+ * @return string
+ */
+ function _readChunked()
+ {
+ // at start of the next chunk?
+ if (0 == $this->_chunkLength) {
+ $line = $this->_sock->readLine();
+ if (preg_match('/^([0-9a-f]+)/i', $line, $matches)) {
+ $this->_chunkLength = hexdec($matches[1]);
+ // Chunk with zero length indicates the end
+ if (0 == $this->_chunkLength) {
+ $this->_sock->readLine(); // make this an eof()
+ return '';
+ }
+ } else {
+ return '';
+ }
+ }
+ $data = $this->_sock->read($this->_chunkLength);
+ $this->_chunkLength -= HTTP_REQUEST_MBSTRING? mb_strlen($data, 'iso-8859-1'): strlen($data);
+ if (0 == $this->_chunkLength) {
+ $this->_sock->readLine(); // Trailing CRLF
+ }
+ return $data;
+ }
+
+
+ /**
+ * Notifies all registered listeners of an event.
+ *
+ * @param string Event name
+ * @param mixed Additional data
+ * @access private
+ * @see HTTP_Request::_notify()
+ */
+ function _notify($event, $data = null)
+ {
+ foreach (array_keys($this->_listeners) as $id) {
+ $this->_listeners[$id]->update($this, $event, $data);
+ }
+ }
+
+
+ /**
+ * Decodes the message-body encoded by gzip
+ *
+ * The real decoding work is done by gzinflate() built-in function, this
+ * method only parses the header and checks data for compliance with
+ * RFC 1952
+ *
+ * @access private
+ * @param string gzip-encoded data
+ * @return string decoded data
+ */
+ function _decodeGzip($data)
+ {
+ if (HTTP_REQUEST_MBSTRING) {
+ $oldEncoding = mb_internal_encoding();
+ mb_internal_encoding('iso-8859-1');
+ }
+ $length = strlen($data);
+ // If it doesn't look like gzip-encoded data, don't bother
+ if (18 > $length || strcmp(substr($data, 0, 2), "\x1f\x8b")) {
+ return $data;
+ }
+ $method = ord(substr($data, 2, 1));
+ if (8 != $method) {
+ return PEAR::raiseError('_decodeGzip(): unknown compression method', HTTP_REQUEST_ERROR_GZIP_METHOD);
+ }
+ $flags = ord(substr($data, 3, 1));
+ if ($flags & 224) {
+ return PEAR::raiseError('_decodeGzip(): reserved bits are set', HTTP_REQUEST_ERROR_GZIP_DATA);
+ }
+
+ // header is 10 bytes minimum. may be longer, though.
+ $headerLength = 10;
+ // extra fields, need to skip 'em
+ if ($flags & 4) {
+ if ($length - $headerLength - 2 < 8) {
+ return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
+ }
+ $extraLength = unpack('v', substr($data, 10, 2));
+ if ($length - $headerLength - 2 - $extraLength[1] < 8) {
+ return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
+ }
+ $headerLength += $extraLength[1] + 2;
+ }
+ // file name, need to skip that
+ if ($flags & 8) {
+ if ($length - $headerLength - 1 < 8) {
+ return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
+ }
+ $filenameLength = strpos(substr($data, $headerLength), chr(0));
+ if (false === $filenameLength || $length - $headerLength - $filenameLength - 1 < 8) {
+ return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
+ }
+ $headerLength += $filenameLength + 1;
+ }
+ // comment, need to skip that also
+ if ($flags & 16) {
+ if ($length - $headerLength - 1 < 8) {
+ return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
+ }
+ $commentLength = strpos(substr($data, $headerLength), chr(0));
+ if (false === $commentLength || $length - $headerLength - $commentLength - 1 < 8) {
+ return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
+ }
+ $headerLength += $commentLength + 1;
+ }
+ // have a CRC for header. let's check
+ if ($flags & 1) {
+ if ($length - $headerLength - 2 < 8) {
+ return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
+ }
+ $crcReal = 0xffff & crc32(substr($data, 0, $headerLength));
+ $crcStored = unpack('v', substr($data, $headerLength, 2));
+ if ($crcReal != $crcStored[1]) {
+ return PEAR::raiseError('_decodeGzip(): header CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC);
+ }
+ $headerLength += 2;
+ }
+ // unpacked data CRC and size at the end of encoded data
+ $tmp = unpack('V2', substr($data, -8));
+ $dataCrc = $tmp[1];
+ $dataSize = $tmp[2];
+
+ // finally, call the gzinflate() function
+ // don't pass $dataSize to gzinflate, see bugs #13135, #14370
+ $unpacked = gzinflate(substr($data, $headerLength, -8));
+ if (false === $unpacked) {
+ return PEAR::raiseError('_decodeGzip(): gzinflate() call failed', HTTP_REQUEST_ERROR_GZIP_READ);
+ } elseif ($dataSize != strlen($unpacked)) {
+ return PEAR::raiseError('_decodeGzip(): data size check failed', HTTP_REQUEST_ERROR_GZIP_READ);
+ } elseif ((0xffffffff & $dataCrc) != (0xffffffff & crc32($unpacked))) {
+ return PEAR::raiseError('_decodeGzip(): data CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC);
+ }
+ if (HTTP_REQUEST_MBSTRING) {
+ mb_internal_encoding($oldEncoding);
+ }
+ return $unpacked;
+ }
+} // End class HTTP_Response
diff --git a/includes/pear/HTTP2.php b/includes/pear/HTTP2.php
new file mode 100755
index 0000000..6db1802
--- /dev/null
+++ b/includes/pear/HTTP2.php
@@ -0,0 +1,662 @@
+<?php
+/**
+ * Part of HTTP2
+ *
+ * PHP version 5
+ *
+ * @category HTTP
+ * @package HTTP2
+ * @author Stig Bakken <ssb@fast.no>
+ * @author Sterling Hughes <sterling@php.net>
+ * @author Tomas V.V.Cox <cox@idecnet.com>
+ * @author Richard Heyes <richard@php.net>
+ * @author Philippe Jausions <jausions@php.net>
+ * @author Michael Wallner <mike@php.net>
+ * @copyright 2002-2008 The Authors
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @link http://pear.php.net/package/HTTP2
+ */
+
+/**
+ * Load exception class
+ */
+require_once 'HTTP2/Exception.php';
+
+/**
+ * Miscellaneous HTTP Utilities
+ *
+ * PEAR::HTTP2 provides shorthand methods for generating HTTP dates,
+ * issueing HTTP HEAD requests, building absolute URIs, firing redirects and
+ * negotiating user preferred language.
+ *
+ * @category HTTP
+ * @package HTTP2
+ * @author Stig Bakken <ssb@fast.no>
+ * @author Sterling Hughes <sterling@php.net>
+ * @author Tomas V.V.Cox <cox@idecnet.com>
+ * @author Richard Heyes <richard@php.net>
+ * @author Philippe Jausions <jausions@php.net>
+ * @author Michael Wallner <mike@php.net>
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.1.2
+ * @link http://pear.php.net/package/HTTP2
+ */
+class HTTP2
+{
+ /**
+ * Formats a RFC compliant GMT date HTTP header. This function honors the
+ * "y2k_compliance" php.ini directive and formats the GMT date corresponding
+ * to either RFC850 or RFC822.
+ *
+ * @param mixed $time unix timestamp or date (default = current time)
+ *
+ * @return string|boolean GMT date string, or FALSE for an invalid
+ * $time parameter
+ */
+ public function date($time = null)
+ {
+ if (!isset($time)) {
+ $time = time();
+ } elseif (!is_numeric($time) && (-1 === $time = strtotime($time))) {
+ return false;
+ }
+
+ // RFC822 or RFC850
+ $format = ini_get('y2k_compliance') ? 'D, d M Y' : 'l, d-M-y';
+
+ return gmdate($format .' H:i:s \G\M\T', $time);
+ }
+
+ /**
+ * Negotiates language with the user's browser through the Accept-Language
+ * HTTP header or the user's host address. Language codes are generally in
+ * the form "ll" for a language spoken in only one country, or "ll-CC" for a
+ * language spoken in a particular country. For example, U.S. English is
+ * "en-US", while British English is "en-UK". Portugese as spoken in
+ * Portugal is "pt-PT", while Brazilian Portugese is "pt-BR".
+ *
+ * Quality factors in the Accept-Language: header are supported, e.g.:
+ * Accept-Language: en-UK;q=0.7, en-US;q=0.6, no, dk;q=0.8
+ *
+ * <code>
+ * require_once 'HTTP2.php';
+ * $http = new HTTP2();
+ * $langs = array(
+ * 'en' => 'locales/en',
+ * 'en-US' => 'locales/en',
+ * 'en-UK' => 'locales/en',
+ * 'de' => 'locales/de',
+ * 'de-DE' => 'locales/de',
+ * 'de-AT' => 'locales/de',
+ * );
+ * $neg = $http->negotiateLanguage($langs);
+ * $dir = $langs[$neg];
+ * </code>
+ *
+ * @param array $supported An associative array of supported languages,
+ * whose values must evaluate to true.
+ * @param string $default The default language to use if none is found.
+ *
+ * @return string The negotiated language result or the supplied default.
+ */
+ public function negotiateLanguage($supported, $default = 'en-US')
+ {
+ $supp = array();
+ foreach ($supported as $lang => $isSupported) {
+ if ($isSupported) {
+ $supp[strtolower($lang)] = $lang;
+ }
+ }
+
+ if (!count($supp)) {
+ return $default;
+ }
+
+ if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
+ $match = $this->matchAccept(
+ $_SERVER['HTTP_ACCEPT_LANGUAGE'],
+ $supp
+ );
+ if (!is_null($match)) {
+ return $match;
+ }
+ }
+
+ if (isset($_SERVER['REMOTE_HOST'])) {
+ $lang = strtolower(end($h = explode('.', $_SERVER['REMOTE_HOST'])));
+ if (isset($supp[$lang])) {
+ return $supp[$lang];
+ }
+ }
+
+ return $default;
+ }
+
+ /**
+ * Negotiates charset with the user's browser through the Accept-Charset
+ * HTTP header.
+ *
+ * Quality factors in the Accept-Charset: header are supported, e.g.:
+ * Accept-Language: en-UK;q=0.7, en-US;q=0.6, no, dk;q=0.8
+ *
+ * <code>
+ * require_once 'HTTP2.php';
+ * $http = new HTTP2();
+ * $charsets = array(
+ * 'UTF-8',
+ * 'ISO-8859-1',
+ * );
+ * $charset = $http->negotiateCharset($charsets);
+ * </code>
+ *
+ * @param array $supported An array of supported charsets
+ * @param string $default The default charset to use if none is found.
+ *
+ * @return string The negotiated language result or the supplied default.
+ * @author Philippe Jausions <jausions@php.net>
+ */
+ public function negotiateCharset($supported, $default = 'ISO-8859-1')
+ {
+ $supp = array();
+ foreach ($supported as $charset) {
+ $supp[strtolower($charset)] = $charset;
+ }
+
+ if (!count($supp)) {
+ return $default;
+ }
+
+ if (isset($_SERVER['HTTP_ACCEPT_CHARSET'])) {
+ $match = $this->matchAccept(
+ $_SERVER['HTTP_ACCEPT_CHARSET'],
+ $supp
+ );
+
+ if (!is_null($match)) {
+ return $match;
+ }
+ }
+
+ return $default;
+ }
+
+ /**
+ * Negotiates content type with the user's browser through the Accept
+ * HTTP header.
+ *
+ * Quality factors in the Accept: header are supported, e.g.:
+ * Accept: application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8
+ *
+ * <code>
+ * require_once 'HTTP2.php';
+ * $http = new HTTP2();
+ * $contentType = array(
+ * 'application/xhtml+xml',
+ * 'application/xml',
+ * 'text/html',
+ * 'text/plain',
+ * );
+ * $mime = $http->negotiateMimeType($contentType);
+ * </code>
+ *
+ * @param array $supported An associative array of supported MIME types.
+ * @param string $default The default type to use if none match.
+ *
+ * @return string The negotiated MIME type result or the supplied default.
+ * @author Philippe Jausions <jausions@php.net>
+ */
+ public function negotiateMimeType($supported, $default)
+ {
+ $supp = array();
+ foreach ($supported as $type) {
+ $supp[strtolower($type)] = $type;
+ }
+
+ if (!count($supp)) {
+ return $default;
+ }
+
+ if (isset($_SERVER['HTTP_ACCEPT'])) {
+ $accepts = $this->sortAccept($_SERVER['HTTP_ACCEPT']);
+
+ foreach ($accepts as $type => $q) {
+ if (substr($type, -2) != '/*') {
+ if (isset($supp[$type])) {
+ return $supp[$type];
+ }
+ continue;
+ }
+ if ($type == '*/*') {
+ return array_shift($supp);
+ }
+ list($general, $specific) = explode('/', $type);
+ $general .= '/';
+ $len = strlen($general);
+ foreach ($supp as $mime => $t) {
+ if (strncasecmp($general, $mime, $len) == 0) {
+ return $t;
+ }
+ }
+ }
+ }
+
+ return $default;
+ }
+
+ /**
+ * Parses a weighed "Accept" HTTP header and matches it against a list
+ * of supported options
+ *
+ * @param string $header The HTTP "Accept" header to parse
+ * @param array $supported A list of supported values
+ *
+ * @return string|NULL a matched option, or NULL if no match
+ */
+ protected function matchAccept($header, $supported)
+ {
+ $matches = $this->sortAccept($header);
+ foreach ($matches as $key => $q) {
+ if (isset($supported[$key])) {
+ return $supported[$key];
+ }
+ }
+ // If any (i.e. "*") is acceptable, return the first supported format
+ if (isset($matches['*'])) {
+ return array_shift($supported);
+ }
+ return null;
+ }
+
+ /**
+ * Parses and sorts a weighed "Accept" HTTP header
+ *
+ * @param string $header The HTTP "Accept" header to parse
+ *
+ * @return array Sorted list of "accept" options
+ */
+ protected function sortAccept($header)
+ {
+ $matches = array();
+ foreach (explode(',', $header) as $option) {
+ $option = array_map('trim', explode(';', $option));
+
+ $l = strtolower($option[0]);
+ if (isset($option[1])) {
+ $q = (float) str_replace('q=', '', $option[1]);
+ } else {
+ $q = null;
+ // Assign default low weight for generic values
+ if ($l == '*/*') {
+ $q = 0.01;
+ } elseif (substr($l, -1) == '*') {
+ $q = 0.02;
+ }
+ }
+ // Unweighted values, get high weight by their position in the
+ // list
+ $matches[$l] = isset($q) ? $q : 1000 - count($matches);
+ }
+ arsort($matches, SORT_NUMERIC);
+ return $matches;
+ }
+
+ /**
+ * Sends a "HEAD" HTTP command to a server and returns the headers
+ * as an associative array.
+ *
+ * Example output could be:
+ * <code>
+ * Array
+ * (
+ * [response_code] => 200 // The HTTP response code
+ * [response] => HTTP/1.1 200 OK // The full HTTP response string
+ * [Date] => Fri, 11 Jan 2002 01:41:44 GMT
+ * [Server] => Apache/1.3.20 (Unix) PHP/4.1.1
+ * [X-Powered-By] => PHP/4.1.1
+ * [Connection] => close
+ * [Content-Type] => text/html
+ * )
+ * </code>
+ *
+ * @param string $url A valid URL, e.g.: http://pear.php.net/credits.php
+ * @param integer $timeout Timeout in seconds (default = 10)
+ *
+ * @return array Returns associative array of response headers on success
+ *
+ * @throws HTTP2_Exception When connecting fails
+ * @throws InvalidArgumentException When the protocol is not uspported
+ *
+ * @see HTTP_Client::head()
+ * @see HTTP_Request
+ */
+ public function head($url, $timeout = 10)
+ {
+ $p = parse_url($url);
+ if (!isset($p['scheme'])) {
+ $p = parse_url($this->absoluteURI($url));
+ } elseif ($p['scheme'] != 'http') {
+ throw new InvalidArgumentException(
+ 'Unsupported protocol: '. $p['scheme']
+ );
+ }
+
+ $port = isset($p['port']) ? $p['port'] : 80;
+
+ if (!$fp = @fsockopen($p['host'], $port, $eno, $estr, $timeout)) {
+ throw new HTTP2_Exception("Connection error: $estr ($eno)");
+ }
+
+ $path = !empty($p['path']) ? $p['path'] : '/';
+ $path .= !empty($p['query']) ? '?' . $p['query'] : '';
+
+ fputs($fp, "HEAD $path HTTP/1.0\r\n");
+ fputs($fp, 'Host: ' . $p['host'] . ':' . $port . "\r\n");
+ fputs($fp, "Connection: close\r\n\r\n");
+
+ $response = rtrim(fgets($fp, 4096));
+ if (preg_match("|^HTTP/[^\s]*\s(.*?)\s|", $response, $status)) {
+ $headers['response_code'] = $status[1];
+ }
+ $headers['response'] = $response;
+
+ while ($line = fgets($fp, 4096)) {
+ if (!trim($line)) {
+ break;
+ }
+ if (($pos = strpos($line, ':')) !== false) {
+ $header = substr($line, 0, $pos);
+ $value = trim(substr($line, $pos + 1));
+
+ $headers[$header] = $value;
+ }
+ }
+ fclose($fp);
+ return $headers;
+ }
+
+ /**
+ * This function redirects the client. This is done by issuing
+ * a "Location" header and exiting if wanted. If you set $rfc2616 to true
+ * HTTP will output a hypertext note with the location of the redirect.
+ *
+ * @param string $url URL where the redirect should go to.
+ * @param bool $exit Whether to exit immediately after redirection.
+ * @param bool $rfc2616 Wheter to output a hypertext note where we're
+ * redirecting to (Redirecting to
+ * <a href="...">...</a>.)
+ *
+ * @return boolean Returns TRUE on succes (or exits) or FALSE if headers
+ * have already been sent.
+ */
+ function redirect($url, $exit = true, $rfc2616 = false)
+ {
+ if (headers_sent()) {
+ return false;
+ }
+
+ $url = $this->absoluteURI($url);
+ header('Location: '. $url);
+
+ if ($rfc2616 && isset($_SERVER['REQUEST_METHOD'])
+ && $_SERVER['REQUEST_METHOD'] != 'HEAD'
+ ) {
+ echo '
+<p>Redirecting to: <a href="'.str_replace('"', '%22', $url).'">'
+ .htmlspecialchars($url).'</a>.</p>
+<script type="text/javascript">
+//<![CDATA[
+if (location.replace == null) {
+ location.replace = location.assign;
+}
+location.replace("'.str_replace('"', '\\"', $url).'");
+// ]]>
+</script>';
+ }
+ if ($exit) {
+ exit;
+ }
+ return true;
+ }
+
+ /**
+ * This function returns the absolute URI for the partial URL passed.
+ * The current scheme (HTTP/HTTPS), host server, port, current script
+ * location are used if necessary to resolve any relative URLs.
+ *
+ * Offsets potentially created by PATH_INFO are taken care of to resolve
+ * relative URLs to the current script.
+ *
+ * You can choose a new protocol while resolving the URI. This is
+ * particularly useful when redirecting a web browser using relative URIs
+ * and to switch from HTTP to HTTPS, or vice-versa, at the same time.
+ *
+ * @param string $url Absolute or relative URI the redirect should
+ * go to.
+ * @param string $protocol Protocol to use when redirecting URIs.
+ * @param integer $port A new port number.
+ *
+ * @return string The absolute URI.
+ * @author Philippe Jausions <Philippe.Jausions@11abacus.com>
+ */
+ public function absoluteURI($url = null, $protocol = null, $port = null)
+ {
+ // filter CR/LF
+ $url = str_replace(array("\r", "\n"), ' ', $url);
+
+ // Mess around protocol and port with already absolute URIs
+ if (preg_match('!^([a-z0-9]+)://!i', $url)) {
+ if (empty($protocol) && empty($port)) {
+ return $url;
+ }
+ if (!empty($protocol)) {
+ $url = $protocol .':'. end($array = explode(':', $url, 2));
+ }
+ if (!empty($port)) {
+ $url = preg_replace(
+ '!^(([a-z0-9]+)://[^/:]+)(:[\d]+)?!i',
+ '\1:'. $port,
+ $url
+ );
+ }
+ return $url;
+ }
+
+ $host = 'localhost';
+ if (!empty($_SERVER['HTTP_HOST'])) {
+ list($host) = explode(':', $_SERVER['HTTP_HOST']);
+ } elseif (!empty($_SERVER['SERVER_NAME'])) {
+ list($host) = explode(':', $_SERVER['SERVER_NAME']);
+ }
+
+ if (empty($protocol)) {
+ if (isset($_SERVER['HTTPS']) && !strcasecmp($_SERVER['HTTPS'], 'on')) {
+ $protocol = 'https';
+ } else {
+ $protocol = 'http';
+ }
+ if (!isset($port) || $port != intval($port)) {
+ $port = 80;
+ if (isset($_SERVER['SERVER_PORT'])) {
+ $port = $_SERVER['SERVER_PORT'];
+ }
+ }
+ }
+
+ if ($protocol == 'http' && $port == 80) {
+ unset($port);
+ }
+ if ($protocol == 'https' && $port == 443) {
+ unset($port);
+ }
+
+ $server = $protocol.'://'.$host.(isset($port) ? ':'.$port : '');
+
+ $uriAll = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI']
+ : $_SERVER['PHP_SELF'];
+ if (false !== ($q = strpos($uriAll, '?'))) {
+ $uriBase = substr($uriAll, 0, $q);
+ } else {
+ $uriBase = $uriAll;
+ }
+ if (!strlen($url) || $url[0] == '#') {
+ $url = $uriAll.$url;
+ } elseif ($url[0] == '?') {
+ $url = $uriBase.$url;
+ }
+ if ($url[0] == '/') {
+ return $server . $url;
+ }
+
+ // Adjust for PATH_INFO if needed
+ if (isset($_SERVER['PATH_INFO']) && strlen($_SERVER['PATH_INFO'])) {
+ $path = dirname(substr($uriBase, 0, -strlen($_SERVER['PATH_INFO'])));
+ } else {
+ /**
+ * Fixes bug #12672 PHP_SELF ending on / causes incorrect redirects
+ *
+ * @link http://pear.php.net/bugs/12672
+ */
+ $path = dirname($uriBase.'-');
+ }
+
+ if (substr($path = strtr($path, '\\', '/'), -1) != '/') {
+ $path .= '/';
+ }
+
+ return $server . $path . $url;
+ }
+
+ /**
+ * Parses a HTTP "Link" header value as specified by RFC 5988.
+ *
+ * When errors occur during parsing, all information collected to that
+ * point will be returned used and the rest of the line skipped.
+ *
+ * @param string|array $lines HTTP "Link:" header value (without "Link:"),
+ * or array of such strings
+ *
+ * @return array Array of parsed links
+ * (one single line may contain multiple links)
+ * Only params existing in the link are in the array.
+ * URI is available in key "_uri".
+ *
+ * @link http://tools.ietf.org/html/rfc5988
+ */
+ public function parseLinks($lines)
+ {
+ $lines = (array) $lines;
+ $extracted = array();
+
+ foreach ($lines as $line) {
+ $state = 'uri';
+ $pos = 0;
+ $len = strlen($line);
+ while ($pos < $len - 1) {
+ $link = array();
+ $pos = $len - strlen(ltrim(substr($line, $pos)));
+ if ($line{$pos} == ',') {
+ ++$pos;
+ continue;
+ } else if ($line{$pos} != '<') {
+ break;
+ }
+ $end = strpos($line, '>', $pos + 1);
+ if ($end === false) {
+ break;
+ }
+ $link['_uri'] = substr($line, $pos + 1, $end - $pos - 1);
+ $pos = $end + 1;
+
+ while ($pos < $len - 1) {
+ if ($line{$pos} == ',') {
+ $extracted[] = $link;
+ $link = array();
+ ++$pos;
+ continue;
+ } else if ($line{$pos} != ';') {
+ break;
+ }
+
+ ++$pos;
+ $end = strpos($line, '=', $pos + 1);
+ if ($end === false) {
+ break;
+ }
+ $pname = trim(substr($line, $pos, $end - $pos));
+ $pos = $end + 1;
+
+ $rest = trim(substr($line, $pos));
+ if ($rest[0] == '"') {
+ $pos = strpos($line, '"', $pos) + 1;
+ $end = strpos($line, '"', $pos + 1);
+ $pval = substr($line, $pos, $end - $pos);
+ $pos = $end + 1;
+ } else {
+ $end1 = strpos($line, ';', $pos + 1);
+ $end2 = strpos($line, ',', $pos + 1);
+ if ($end1 === false && $end2 === false) {
+ $end = $len;
+ } else if ($end1 === false) {
+ $end = $end2;
+ } else if ($end2 === false) {
+ $end = $end1;
+ } else {
+ $end = $end1 < $end2 ? $end1 : $end2;
+ }
+ $pval = trim(substr($line, $pos, $end - $pos));
+ $pos = $end;
+ }
+ if ($pname == 'title*') {
+ $parts = explode("'", $pval, 3);
+ if (count($parts) != 3) {
+ continue;
+ }
+ list($charset, $lang, $val) = $parts;
+ $link[$pname][$lang] = $this->convertCharset(
+ $charset, 'utf-8', urldecode($val)
+ );
+ } else if ($pname == 'rel' || $pname == 'rev') {
+ if (!isset($link[$pname])) {
+ $link[$pname] = array();
+ }
+ $link[$pname] = array_merge(
+ $link[$pname],
+ array_map('trim', explode(' ', $pval))
+ );
+ } else if (!isset($link[$pname])) {
+ $link[$pname] = $pval;
+ }
+ if ($end >= $len || $line{$end} == ',') {
+ break;
+ }
+ }
+ if (count($link) > 0) {
+ $extracted[] = $link;
+ }
+ }
+ }
+
+ return $extracted;
+ }
+
+ /**
+ * Convert the given string from one into another charset.
+ * Uses mb_convert_encoding or iconv if available.
+ *
+ * @param string $from Source charset the string is in
+ * @param string $to Target character set
+ * @param string $str String to convert
+ *
+ * @return string converted string
+ */
+ protected function convertCharset($from, $to, $str)
+ {
+ if (function_exists('mb_convert_encoding')) {
+ return mb_convert_encoding($str, $to, $from);
+ } else if (function_exists('iconv')) {
+ return iconv($from, $to, $str);
+ }
+ return $str;
+ }
+}
+?>
diff --git a/includes/pear/HTTP2/Exception.php b/includes/pear/HTTP2/Exception.php
new file mode 100755
index 0000000..319401b
--- /dev/null
+++ b/includes/pear/HTTP2/Exception.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Part of HTTP2
+ *
+ * PHP version 5
+ *
+ * @category HTTP
+ * @package HTTP2
+ * @author Daniel O'Connor <daniel.oconnor@rpdata.com>
+ * @copyright 2012-2013 The Authors
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @link http://pear.php.net/package/HTTP2
+ */
+
+/**
+ * Simple exception class for HTTP2
+ *
+ * @category HTTP
+ * @package HTTP2
+ * @author Daniel O'Connor <daniel.oconnor@rpdata.com>
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @version Release: 1.1.2
+ * @link http://pear.php.net/package/HTTP2
+ */
+class HTTP2_Exception extends Exception
+{
+}
+?>
diff --git a/includes/pear/System.php b/includes/pear/System.php
index b419605..ee4525e 100644..100755
--- a/includes/pear/System.php
+++ b/includes/pear/System.php
@@ -9,7 +9,6 @@
* @author Tomas V.V.Cox <cox@idecnet.com>
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id$
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
@@ -23,7 +22,7 @@ require_once 'Console/Getopt.php';
$GLOBALS['_System_temp_files'] = array();
/**
-* System offers cross plattform compatible system functions
+* System offers cross platform compatible system functions
*
* Static functions for different operations. Should work under
* Unix and Windows. The names and usage has been taken from its respectively
@@ -51,7 +50,7 @@ $GLOBALS['_System_temp_files'] = array();
* @author Tomas V.V. Cox <cox@idecnet.com>
* @copyright 1997-2006 The PHP Group
* @license http://opensource.org/licenses/bsd-license.php New BSD License
-* @version Release: @package_version@
+* @version Release: 1.10.16
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
* @static
@@ -75,7 +74,7 @@ class System
$offset = 0;
foreach ($av as $a) {
$b = trim($a[0]);
- if ($b{0} == '"' || $b{0} == "'") {
+ if ($b[0] == '"' || $b[0] == "'") {
continue;
}
@@ -96,6 +95,7 @@ class System
$argv[$k] = trim($a) ;
}
}
+
return Console_Getopt::getopt2($argv, $short_options, $long_options);
}
@@ -106,7 +106,7 @@ class System
* @param mixed $error a PEAR error or a string with the error message
* @return bool false
*/
- public static function raiseError($error)
+ protected static function raiseError($error)
{
if (PEAR::isError($error)) {
$error = $error->getMessage();
@@ -138,7 +138,7 @@ class System
* @param bool $silent if true, do not emit errors.
* @return array the structure of the dir
*/
- public static function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false)
+ protected static function _dirToStruct($sPath, $maxinst, $aktinst = 0, $silent = false)
{
$struct = array('dirs' => array(), 'files' => array());
if (($dir = @opendir($sPath)) === false) {
@@ -178,9 +178,10 @@ class System
*
* @param array $files Array listing files and dirs
* @return array
+ * @static
* @see System::_dirToStruct()
*/
- public static function _multipleToStruct($files)
+ protected static function _multipleToStruct($files)
{
$struct = array('dirs' => array(), 'files' => array());
settype($files, 'array');
@@ -203,6 +204,8 @@ class System
*
* @param string $args the arguments for rm
* @return mixed PEAR_Error or true for success
+ * @static
+ * @access public
*/
public static function rm($args)
{
@@ -262,7 +265,7 @@ class System
} 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') {
+ if (strlen($opt[1]) && $opt[1][0] == '0') {
$opt[1] = octdec($opt[1]);
} else {
// convert to int
@@ -312,7 +315,7 @@ class System
* 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)
+ * Note: as the class use fopen, urls should work also
*
* @param string $args the arguments
* @return boolean true on success
@@ -477,7 +480,7 @@ class System
if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) {
return $var;
}
- return realpath('/tmp');
+ return realpath(function_exists('sys_get_temp_dir') ? sys_get_temp_dir() : '/tmp');
}
/**
@@ -501,13 +504,11 @@ class System
$path_elements[] = dirname($program);
$program = basename($program);
} else {
- // Honor safe mode
- if (!ini_get('safe_mode') || !$path = ini_get('safe_mode_exec_dir')) {
- $path = getenv('PATH');
- if (!$path) {
- $path = getenv('Path'); // some OSes are just stupid enough to do this
- }
+ $path = getenv('PATH');
+ if (!$path) {
+ $path = getenv('Path'); // some OSes are just stupid enough to do this
}
+
$path_elements = explode(PATH_SEPARATOR, $path);
}
@@ -519,18 +520,23 @@ class System
if (strpos($program, '.') !== false) {
array_unshift($exe_suffixes, '');
}
- // is_executable() is not available on windows for PHP4
- $pear_is_executable = (function_exists('is_executable')) ? 'is_executable' : 'is_file';
} else {
$exe_suffixes = array('');
- $pear_is_executable = 'is_executable';
}
foreach ($exe_suffixes as $suff) {
foreach ($path_elements as $dir) {
$file = $dir . DIRECTORY_SEPARATOR . $program . $suff;
- if (@$pear_is_executable($file)) {
- return $file;
+ // It's possible to run a .bat on Windows that is_executable
+ // would return false for. The is_executable check is meaningless...
+ if (OS_WINDOWS) {
+ if (file_exists($file)) {
+ return $file;
+ }
+ } else {
+ if (is_executable($file)) {
+ return $file;
+ }
}
}
}
@@ -549,7 +555,7 @@ class System
* System::find("$dir -name *.php -name *.htm*");
* System::find("$dir -maxdepth 1");
*
- * Params implmented:
+ * Params implemented:
* $dir -> Start the search at this directory
* -type d -> return only directories
* -type f -> return only files