2000-07-24 08:05:51 +00:00
|
|
|
<?php
|
|
|
|
//
|
|
|
|
// +----------------------------------------------------------------------+
|
2001-12-11 15:32:16 +00:00
|
|
|
// | PHP Version 4 |
|
2000-07-24 08:05:51 +00:00
|
|
|
// +----------------------------------------------------------------------+
|
2001-12-11 15:32:16 +00:00
|
|
|
// | Copyright (c) 1997-2002 The PHP Group |
|
2000-07-24 08:05:51 +00:00
|
|
|
// +----------------------------------------------------------------------+
|
|
|
|
// | This source file is subject to version 2.02 of the PHP license, |
|
|
|
|
// | that is bundled with this package in the file LICENSE, and is |
|
|
|
|
// | available at through the world-wide-web at |
|
|
|
|
// | http://www.php.net/license/2_02.txt. |
|
|
|
|
// | If you did not receive a copy of the PHP license and are unable to |
|
|
|
|
// | obtain it through the world-wide-web, please send a note to |
|
|
|
|
// | license@php.net so we can mail you a copy immediately. |
|
|
|
|
// +----------------------------------------------------------------------+
|
|
|
|
// | Authors: Stig Bakken <ssb@fast.no> |
|
2001-07-18 17:29:09 +00:00
|
|
|
// | Tomas V.V.Cox <cox@idecnet.com> |
|
2001-07-19 11:15:48 +00:00
|
|
|
// | |
|
2000-07-24 08:05:51 +00:00
|
|
|
// +----------------------------------------------------------------------+
|
|
|
|
//
|
2001-07-18 17:29:09 +00:00
|
|
|
// $Id$
|
2000-07-24 08:05:51 +00:00
|
|
|
|
2001-10-07 20:16:41 +00:00
|
|
|
require_once 'PEAR/Common.php';
|
2001-10-31 05:39:11 +00:00
|
|
|
require_once 'PEAR/Registry.php';
|
2001-12-17 21:11:50 +00:00
|
|
|
require_once 'PEAR/Dependency.php';
|
2000-07-24 08:05:51 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Administration class used to install PEAR packages and maintain the
|
2001-04-17 01:17:59 +00:00
|
|
|
* installed package database.
|
2000-07-24 08:05:51 +00:00
|
|
|
*
|
2001-07-18 17:29:09 +00:00
|
|
|
* TODO:
|
2001-12-17 21:11:50 +00:00
|
|
|
* - Install the "role=doc" files in a central pear doc dir
|
2001-10-07 20:16:41 +00:00
|
|
|
* - kill FIXME's
|
2001-07-18 17:29:09 +00:00
|
|
|
*
|
2000-07-24 08:05:51 +00:00
|
|
|
* @since PHP 4.0.2
|
|
|
|
* @author Stig Bakken <ssb@fast.no>
|
|
|
|
*/
|
2001-04-22 01:09:14 +00:00
|
|
|
class PEAR_Installer extends PEAR_Common
|
2001-01-08 02:45:30 +00:00
|
|
|
{
|
2000-07-24 08:05:51 +00:00
|
|
|
// {{{ properties
|
|
|
|
|
|
|
|
/** name of the package directory, for example Foo-1.0 */
|
|
|
|
var $pkgdir;
|
|
|
|
|
|
|
|
/** directory where PHP code files go */
|
2001-04-17 01:17:59 +00:00
|
|
|
var $phpdir;
|
2000-07-24 08:05:51 +00:00
|
|
|
|
|
|
|
/** directory where PHP extension files go */
|
2001-04-17 01:17:59 +00:00
|
|
|
var $extdir;
|
2000-07-24 08:05:51 +00:00
|
|
|
|
|
|
|
/** directory where documentation goes */
|
2001-04-17 01:17:59 +00:00
|
|
|
var $docdir;
|
|
|
|
|
2000-07-24 08:05:51 +00:00
|
|
|
/** directory where the package wants to put files, relative
|
|
|
|
* to one of the three previous dirs
|
|
|
|
*/
|
|
|
|
var $destdir = '';
|
|
|
|
|
2001-05-15 14:15:09 +00:00
|
|
|
/** debug level (integer) */
|
|
|
|
var $debug = 1;
|
2000-07-24 08:05:51 +00:00
|
|
|
|
|
|
|
/** temporary directory */
|
|
|
|
var $tmpdir;
|
|
|
|
|
2001-11-13 01:05:46 +00:00
|
|
|
/** PEAR_Registry object used by the installer */
|
|
|
|
var $registry;
|
|
|
|
|
2000-07-24 08:05:51 +00:00
|
|
|
// }}}
|
|
|
|
|
|
|
|
// {{{ constructor
|
|
|
|
|
2001-04-17 01:17:59 +00:00
|
|
|
function PEAR_Installer($phpdir = PEAR_INSTALL_DIR,
|
|
|
|
$extdir = PEAR_EXTENSION_DIR,
|
2001-12-26 03:57:47 +00:00
|
|
|
$docdir = null)
|
2001-04-17 01:17:59 +00:00
|
|
|
{
|
2001-05-15 14:03:04 +00:00
|
|
|
$this->PEAR();
|
2001-04-17 01:17:59 +00:00
|
|
|
$this->phpdir = $phpdir;
|
|
|
|
$this->extdir = $extdir;
|
2001-12-26 03:57:47 +00:00
|
|
|
if ($docdir === null) {
|
|
|
|
$docdir = PHP_DATADIR . DIRECTORY_SEPARATOR . 'pear' .
|
|
|
|
DIRECTORY_SEPARATOR . 'doc';
|
|
|
|
}
|
2001-04-17 01:17:59 +00:00
|
|
|
$this->docdir = $docdir;
|
2000-07-24 08:05:51 +00:00
|
|
|
}
|
|
|
|
|
2001-12-10 17:00:32 +00:00
|
|
|
// }}}
|
|
|
|
|
2001-12-12 01:30:56 +00:00
|
|
|
// {{{ _deletePackageFiles()
|
|
|
|
|
|
|
|
function _deletePackageFiles($package)
|
|
|
|
{
|
|
|
|
$info = $this->registry->packageInfo($package);
|
|
|
|
if ($info == null) {
|
|
|
|
return $this->raiseError("$package not installed");
|
|
|
|
}
|
|
|
|
foreach ($info['filelist'] as $file => $props) {
|
2001-12-26 03:57:47 +00:00
|
|
|
$path = $props['installed_as'];
|
|
|
|
// XXX TODO: do a "rmdir -p dirname($path)" to maintain clean the fs
|
2001-12-12 01:30:56 +00:00
|
|
|
if (!@unlink($path)) {
|
|
|
|
$this->log(2, "unable to delete: $path");
|
|
|
|
} else {
|
|
|
|
$this->log(2, "+ deleted file: $path");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// }}}
|
2001-12-10 17:00:32 +00:00
|
|
|
// {{{ _installFile()
|
|
|
|
|
2001-12-26 03:57:47 +00:00
|
|
|
function _installFile($file, $atts, $tmp_path)
|
2001-12-10 17:00:32 +00:00
|
|
|
{
|
|
|
|
$type = strtolower($atts['role']);
|
|
|
|
switch ($type) {
|
|
|
|
case 'test':
|
|
|
|
// don't install test files for now
|
|
|
|
$this->log(2, "+ Test file $file won't be installed yet");
|
|
|
|
return true;
|
|
|
|
break;
|
|
|
|
case 'doc':
|
2001-12-26 03:57:47 +00:00
|
|
|
$dest_dir = $this->docdir . DIRECTORY_SEPARATOR .
|
|
|
|
$this->pkginfo['package'];
|
|
|
|
break;
|
2001-12-10 17:00:32 +00:00
|
|
|
case 'php':
|
2001-12-26 03:57:47 +00:00
|
|
|
default: {
|
|
|
|
$dest_dir = $this->phpdir;
|
|
|
|
if (isset($atts['baseinstalldir'])) {
|
|
|
|
$dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir'];
|
|
|
|
}
|
|
|
|
if (dirname($file) != '.') {
|
|
|
|
$dest_dir .= DIRECTORY_SEPARATOR . dirname($file);
|
|
|
|
}
|
2001-12-10 17:00:32 +00:00
|
|
|
break;
|
2001-12-26 03:57:47 +00:00
|
|
|
}
|
2001-12-10 17:00:32 +00:00
|
|
|
}
|
2001-12-26 03:57:47 +00:00
|
|
|
$dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file);
|
2001-12-10 17:00:32 +00:00
|
|
|
if (!@is_dir($dest_dir)) {
|
|
|
|
if (!$this->mkDirHier($dest_dir)) {
|
|
|
|
$this->log(0, "failed to mkdir $dest_dir");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
$this->log(2, "+ created dir $dest_dir");
|
|
|
|
}
|
2001-12-26 03:57:47 +00:00
|
|
|
$orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file;
|
|
|
|
$orig_perms = fileperms($orig_file);
|
|
|
|
if (!@copy($orig_file, $dest_file)) {
|
|
|
|
$this->log(0, "failed to copy $orig_file to $dest_file");
|
2001-12-10 17:00:32 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
chmod($dest_file, $orig_perms);
|
2001-12-26 03:57:47 +00:00
|
|
|
$this->log(2, "+ copy $orig_file to $dest_file");
|
|
|
|
|
|
|
|
// Store the full path where the file was installed for easy unistall
|
|
|
|
$this->pkginfo['filelist'][$file]['installed_as'] = $dest_file;
|
|
|
|
|
2001-12-10 17:00:32 +00:00
|
|
|
$this->log(1, "installed file $dest_file");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2000-07-24 08:05:51 +00:00
|
|
|
// }}}
|
|
|
|
// {{{ install()
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Installs the files within the package file specified.
|
|
|
|
*
|
|
|
|
* @param $pkgfile path to the package file
|
|
|
|
*
|
|
|
|
* @return bool true if successful, false if not
|
|
|
|
*/
|
2001-07-18 17:29:09 +00:00
|
|
|
|
2002-01-02 17:12:26 +00:00
|
|
|
function install($pkgfile, $options = array(), $config = null)
|
2001-07-18 17:29:09 +00:00
|
|
|
{
|
2001-12-12 01:30:56 +00:00
|
|
|
// recognized options:
|
|
|
|
// - register_only : update registry but don't install files
|
|
|
|
// - upgrade : upgrade existing install
|
|
|
|
//
|
2001-11-13 01:05:46 +00:00
|
|
|
if (empty($this->registry)) {
|
2002-01-24 08:24:24 +00:00
|
|
|
$this->registry = new PEAR_Registry($this->phpdir);
|
2001-11-13 01:05:46 +00:00
|
|
|
}
|
2001-10-29 14:15:43 +00:00
|
|
|
$oldcwd = getcwd();
|
2001-07-18 17:29:09 +00:00
|
|
|
$need_download = false;
|
|
|
|
if (preg_match('#^(http|ftp)://#', $pkgfile)) {
|
|
|
|
$need_download = true;
|
|
|
|
} elseif (!@is_file($pkgfile)) {
|
2002-01-02 17:12:26 +00:00
|
|
|
if (preg_match('/^[A-Z][A-Za-z0-9_]+$/', $pkgfile)) {
|
|
|
|
// valid package name
|
|
|
|
if ($config === null) {
|
|
|
|
$pkgfile = "http://pear.php.net/get/$pkgfile";
|
|
|
|
} else {
|
|
|
|
$pkgfile = "http://" . $config->get('master_server') .
|
|
|
|
"/get/$pkgfile";
|
|
|
|
}
|
|
|
|
$need_download = true;
|
|
|
|
}
|
2001-11-13 01:05:46 +00:00
|
|
|
return $this->raiseError("could not open the package file: $pkgfile");
|
2001-07-18 17:29:09 +00:00
|
|
|
}
|
2001-10-08 06:12:13 +00:00
|
|
|
|
2001-07-18 17:29:09 +00:00
|
|
|
// Download package -----------------------------------------------
|
|
|
|
if ($need_download) {
|
|
|
|
$file = basename($pkgfile);
|
2001-10-08 06:12:13 +00:00
|
|
|
if (PEAR::isError($downloaddir = $this->mkTempDir())) {
|
|
|
|
return $downloaddir;
|
2001-07-18 17:29:09 +00:00
|
|
|
}
|
2001-10-08 06:12:13 +00:00
|
|
|
$this->log(2, '+ tmp dir created at ' . $downloaddir);
|
|
|
|
$downloadfile = $downloaddir . DIRECTORY_SEPARATOR . $file;
|
2001-07-18 17:29:09 +00:00
|
|
|
$this->log(1, "downloading $pkgfile ...");
|
|
|
|
if (!$fp = @fopen($pkgfile, 'r')) {
|
|
|
|
return $this->raiseError("$pkgfile: failed to download ($php_errormsg)");
|
|
|
|
}
|
|
|
|
if (!$wp = @fopen($downloadfile, 'w')) {
|
|
|
|
return $this->raiseError("$downloadfile: write failed ($php_errormsg)");
|
|
|
|
}
|
|
|
|
$bytes = 0;
|
|
|
|
while ($data = @fread($fp, 16384)) {
|
|
|
|
$bytes += strlen($data);
|
|
|
|
if (!@fwrite($wp, $data)) {
|
|
|
|
return $this->raiseError("$downloadfile: write failed ($php_errormsg)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$pkgfile = $downloadfile;
|
|
|
|
fclose($fp);
|
|
|
|
fclose($wp);
|
|
|
|
$this->log(1, '...done: ' . number_format($bytes, 0, '', ',') . ' bytes');
|
|
|
|
}
|
|
|
|
|
|
|
|
// Decompress pack in tmp dir -------------------------------------
|
2001-07-18 23:13:56 +00:00
|
|
|
|
|
|
|
// To allow relative package file calls
|
|
|
|
if (!chdir(dirname($pkgfile))) {
|
2001-11-13 01:05:46 +00:00
|
|
|
return $this->raiseError('unable to chdir to package directory');
|
2001-07-18 23:13:56 +00:00
|
|
|
}
|
|
|
|
$pkgfile = getcwd() . DIRECTORY_SEPARATOR . basename($pkgfile);
|
|
|
|
|
2001-10-08 06:12:13 +00:00
|
|
|
if (PEAR::isError($tmpdir = $this->mkTempDir())) {
|
2001-10-29 14:15:43 +00:00
|
|
|
chdir($oldcwd);
|
2001-10-08 06:12:13 +00:00
|
|
|
return $tmpdir;
|
2001-07-18 17:29:09 +00:00
|
|
|
}
|
2001-10-08 06:12:13 +00:00
|
|
|
$this->log(2, '+ tmp dir created at ' . $tmpdir);
|
2001-10-07 20:16:41 +00:00
|
|
|
|
|
|
|
$tar = new Archive_Tar($pkgfile, true);
|
2001-12-10 17:00:32 +00:00
|
|
|
if (!@$tar->extract($tmpdir)) {
|
2001-10-29 14:15:43 +00:00
|
|
|
chdir($oldcwd);
|
2001-11-13 01:05:46 +00:00
|
|
|
return $this->raiseError("unable to unpack $pkgfile");
|
2001-07-18 23:13:56 +00:00
|
|
|
}
|
2001-10-07 20:16:41 +00:00
|
|
|
$file = basename($pkgfile);
|
|
|
|
// Assume the decompressed dir name
|
|
|
|
if (($pos = strrpos($file, '.')) === false) {
|
2001-10-29 14:15:43 +00:00
|
|
|
chdir($oldcwd);
|
2001-11-13 01:05:46 +00:00
|
|
|
return $this->raiseError("invalid package name");
|
2001-07-18 23:13:56 +00:00
|
|
|
}
|
2001-10-07 20:16:41 +00:00
|
|
|
$pkgdir = substr($file, 0, $pos);
|
2001-10-08 06:12:13 +00:00
|
|
|
$descfile = $tmpdir . DIRECTORY_SEPARATOR . $pkgdir . DIRECTORY_SEPARATOR . 'package.xml';
|
2001-10-07 20:16:41 +00:00
|
|
|
|
|
|
|
if (!is_file($descfile)) {
|
2001-10-29 14:15:43 +00:00
|
|
|
chdir($oldcwd);
|
2001-11-13 01:05:46 +00:00
|
|
|
return $this->raiseError("no package.xml file after extracting the archive");
|
2001-07-18 17:29:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Parse xml file -----------------------------------------------
|
|
|
|
$pkginfo = $this->infoFromDescriptionFile($descfile);
|
|
|
|
if (PEAR::isError($pkginfo)) {
|
2001-10-29 14:15:43 +00:00
|
|
|
chdir($oldcwd);
|
2001-07-18 17:29:09 +00:00
|
|
|
return $pkginfo;
|
|
|
|
}
|
|
|
|
|
2001-12-12 01:30:56 +00:00
|
|
|
$pkgname = $pkginfo['package'];
|
|
|
|
|
2001-12-17 21:11:50 +00:00
|
|
|
// Check dependencies -------------------------------------------
|
|
|
|
if (isset($pkginfo['release_deps']) && !isset($options['nodeps'])) {
|
|
|
|
$error = $this->checkDeps($pkginfo);
|
|
|
|
if ($error) {
|
|
|
|
$this->log(0, $error);
|
|
|
|
return $this->raiseError('Dependencies failed');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-12-12 01:30:56 +00:00
|
|
|
if (empty($options['upgrade'])) {
|
|
|
|
// checks to do only when installing new packages
|
|
|
|
if (empty($options['force']) && $this->registry->packageExists($pkgname)) {
|
|
|
|
return $this->raiseError("$pkgname already installed");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// check to do only when upgrading packages
|
|
|
|
if (!$this->registry->packageExists($pkgname)) {
|
|
|
|
return $this->raiseError("$pkgname not installed");
|
|
|
|
}
|
|
|
|
$v1 = $this->registry->packageInfo($pkgname, 'version');
|
|
|
|
$v2 = $pkginfo['version'];
|
|
|
|
$cmp = version_compare($v1, $v2, 'gt');
|
|
|
|
if (empty($options['force']) && !version_compare($v2, $v1, 'gt')) {
|
|
|
|
return $this->raiseError("upgrade to a newer version ($v2 is not newer than $v1)");
|
|
|
|
}
|
|
|
|
if (empty($options['register_only'])) {
|
|
|
|
// when upgrading, remove old release's files first:
|
|
|
|
$this->_deletePackageFiles($package);
|
|
|
|
}
|
2001-10-31 05:39:11 +00:00
|
|
|
}
|
|
|
|
|
2001-07-18 17:29:09 +00:00
|
|
|
// Copy files to dest dir ---------------------------------------
|
2001-12-26 03:57:47 +00:00
|
|
|
|
|
|
|
// info from the package it self we want to access from _installFile
|
|
|
|
$this->pkginfo = $pkginfo;
|
2001-12-11 08:39:01 +00:00
|
|
|
if (empty($options['register_only'])) {
|
|
|
|
if (!is_dir($this->phpdir)) {
|
|
|
|
chdir($oldcwd);
|
|
|
|
return $this->raiseError("no script destination directory\n",
|
|
|
|
null, PEAR_ERROR_DIE);
|
2001-08-01 13:24:55 +00:00
|
|
|
}
|
2001-12-11 08:39:01 +00:00
|
|
|
$tmp_path = dirname($descfile);
|
2001-12-26 03:57:47 +00:00
|
|
|
foreach ($pkginfo['filelist'] as $file => $atts) {
|
|
|
|
$this->_installFile($file, $atts, $tmp_path);
|
2001-08-01 13:24:55 +00:00
|
|
|
}
|
2001-12-17 21:11:50 +00:00
|
|
|
}
|
2001-12-11 08:39:01 +00:00
|
|
|
|
|
|
|
// Register that the package is installed -----------------------
|
2001-12-12 01:30:56 +00:00
|
|
|
if (empty($options['upgrade'])) {
|
2001-12-26 03:57:47 +00:00
|
|
|
$ret = $this->registry->addPackage($pkgname, $this->pkginfo);
|
2001-12-12 01:30:56 +00:00
|
|
|
} else {
|
2001-12-26 03:57:47 +00:00
|
|
|
$ret = $this->registry->updatePackage($pkgname, $this->pkginfo, false);
|
2001-12-12 01:30:56 +00:00
|
|
|
}
|
2001-10-29 14:15:43 +00:00
|
|
|
chdir($oldcwd);
|
2001-12-12 01:30:56 +00:00
|
|
|
return $ret;
|
2001-07-18 17:29:09 +00:00
|
|
|
}
|
|
|
|
|
2001-08-27 21:25:16 +00:00
|
|
|
// }}}
|
2001-12-10 17:00:32 +00:00
|
|
|
// {{{ uninstall()
|
2001-11-15 01:24:35 +00:00
|
|
|
|
|
|
|
function uninstall($package)
|
|
|
|
{
|
|
|
|
if (empty($this->registry)) {
|
2002-01-24 08:24:24 +00:00
|
|
|
$this->registry = new PEAR_Registry($this->phpdir);
|
2001-11-15 01:24:35 +00:00
|
|
|
}
|
2001-12-12 01:30:56 +00:00
|
|
|
|
|
|
|
// Delete the files
|
|
|
|
$this->_deletePackageFiles($package);
|
|
|
|
|
|
|
|
// Register that the package is no longer installed
|
|
|
|
return $this->registry->deletePackage($package);
|
2001-11-15 01:24:35 +00:00
|
|
|
}
|
2001-12-10 17:00:32 +00:00
|
|
|
|
|
|
|
// }}}
|
2002-01-02 17:12:26 +00:00
|
|
|
// {{{ checkDeps()
|
2001-12-17 21:11:50 +00:00
|
|
|
|
|
|
|
function checkDeps(&$pkginfo)
|
|
|
|
{
|
|
|
|
$deps = new PEAR_Dependency;
|
|
|
|
$errors = null;
|
|
|
|
if (is_array($pkginfo['release_deps'])) {
|
|
|
|
foreach($pkginfo['release_deps'] as $dep) {
|
|
|
|
if ($error = $deps->callCheckMethod($dep)) {
|
|
|
|
$errors .= "\n$error";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($errors) {
|
|
|
|
return $errors;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2002-01-02 17:12:26 +00:00
|
|
|
|
|
|
|
// }}}
|
2000-07-24 08:05:51 +00:00
|
|
|
}
|
2001-10-29 14:15:43 +00:00
|
|
|
|
2001-07-19 11:15:48 +00:00
|
|
|
?>
|