From 65af9358cd815fed5d0df288cf5bf2eab66d0637 Mon Sep 17 00:00:00 2001 From: "Tomas V.V.Cox" Date: Wed, 18 Jul 2001 17:29:09 +0000 Subject: [PATCH] - remove the xml parser code (use PEAR_Common::infoFromDescFile) - added the new package.xml Dir tag support - killed many bugs and warnings (as it is quite usable yet, work is still in progress) --- pear/PEAR/Installer.php | 199 ++++++++++++++++++++++++++++++++-------- 1 file changed, 159 insertions(+), 40 deletions(-) diff --git a/pear/PEAR/Installer.php b/pear/PEAR/Installer.php index 5a650a4ba3..4779700340 100644 --- a/pear/PEAR/Installer.php +++ b/pear/PEAR/Installer.php @@ -14,9 +14,10 @@ // | license@php.net so we can mail you a copy immediately. | // +----------------------------------------------------------------------+ // | Authors: Stig Bakken | -// | | +// | Tomas V.V.Cox | // +----------------------------------------------------------------------+ // +// $Id$ require_once "PEAR/Common.php"; @@ -24,6 +25,12 @@ require_once "PEAR/Common.php"; * Administration class used to install PEAR packages and maintain the * installed package database. * + * TODO: + * - move the package db handler methods to its own class. + * - install also the package.xml? + * - remove unneeded code + * - only decrompress pack once + * * @since PHP 4.0.2 * @author Stig Bakken */ @@ -76,7 +83,6 @@ class PEAR_Installer extends PEAR_Common $this->extdir = $extdir; $this->docdir = $docdir; $this->statedir = "/var/lib/php"; // XXX FIXME Windows - $this->loadPackageList("$this->statedir/packages.lst"); } // }}} @@ -84,10 +90,11 @@ class PEAR_Installer extends PEAR_Common function _PEAR_Installer() { + chdir($this->pwd); if ($this->tmpdir && is_dir($this->tmpdir)) { system("rm -rf $this->tmpdir"); // XXX FIXME Windows } - if ($this->pkglist_fp && is_resource($this->pkglist_fp)) { + if (isset($this->pkglist_fp) && is_resource($this->pkglist_fp)) { flock($this->pkglist_fp, LOCK_UN); fclose($this->pkglist_fp); } @@ -98,36 +105,6 @@ class PEAR_Installer extends PEAR_Common // }}} - // {{{ mkDirHier() - - function mkDirHier($dir) - { - $dirstack = array(); - while (!@is_dir($dir) && $dir != DIRECTORY_SEPARATOR) { - array_unshift($dirstack, $dir); - $dir = dirname($dir); - } - while ($newdir = array_shift($dirstack)) { - if (mkdir($newdir, 0777)) { - $this->log(1, "created dir $newdir"); - } else { - return $this->raiseError("mkdir($newdir) failed"); - } - } - } - - // }}} - // {{{ log() - - function log($level, $msg) - { - if ($this->debug >= $level) { - print "$msg\n"; - } - } - - // }}} - // {{{ lockPackageList() function lockPackageList() @@ -234,7 +211,151 @@ class PEAR_Installer extends PEAR_Common * * @return bool true if successful, false if not */ + function install($pkgfile) + { + // XXX FIXME Add here code to manage packages database + //$this->loadPackageList("$this->statedir/packages.lst"); + $this->pwd = getcwd(); + $need_download = false; + if (preg_match('#^(http|ftp)://#', $pkgfile)) { + $need_download = true; + } elseif (!@is_file($pkgfile)) { + return $this->raiseError("$pkgfile: no such file"); + } + // Download package ----------------------------------------------- + if ($need_download) { + $file = basename($pkgfile); + // XXX FIXME use ??? on Windows, use $TMPDIR on unix (use tmpnames?) + $downloaddir = '/tmp/pearinstall'; + if (!$this->mkDirHier($downloaddir)) { + return $this->raiseError("Failed to create tmp dir: $downloaddir"); + } + $downloadfile = $downloaddir.DIRECTORY_SEPARATOR.$file; + $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)"); + } + $this->addTempFile($downloadfile); + $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'); + } + // Test for package.xml ------------------------------------------- + // XXX FIXME only decompress once + $fp = popen("gzip -dc $pkgfile | tar -tf -", 'r'); + if (!$fp) { + return $this->raiseError("Unable to examine $pkgfile (gzip or tar failed)"); + } + while ($line = fgets($fp, 4096)) { + $line = rtrim($line); + if (preg_match('!^[^/]+/package.xml$!', $line)) { + if (isset($descfile)) { + return $this->raiseError("Invalid package: multiple package.xml files at depth one!"); + } + $descfile = $line; + } + } + pclose($fp); + if (!$descfile) { + return $this->raiseError("Invalid package: no package.xml file found!"); + } + + // Decompress pack in tmp dir ------------------------------------- + // XXX FIXME Windows + $this->tmpdir = tempnam("/tmp", "pear"); + unlink($this->tmpdir); + if (!mkdir($this->tmpdir, 0755)) { + return $this->raiseError("Unable to create temporary directory $this->tmpdir."); + } else { + $this->log(2, '...tmp dir created at ' . $this->tmpdir); + } + $this->addTempFile($this->tmpdir); + + + // XXX FIXME Windows should check for drive + if (substr($pkgfile, 0, 1) == DIRECTORY_SEPARATOR) { + $pkgfilepath = $pkgfile; + } else { + $pkgfilepath = $this->pwd . DIRECTORY_SEPARATOR . $pkgfile; + } + + if (!chdir($this->tmpdir)) { + return $this->raiseError("Unable to chdir to $this->tmpdir."); + } + // XXX FIXME Windows + system("gzip -dc $pkgfilepath | tar -xf -"); + $this->log(2, "launched command: gzip -dc $pkgfilepath | tar -xf -"); + if (!is_file($descfile)) { + $this->log(2, "No desc file found: $descfile"); + return $this->raiseError("No package.xml file after extracting the archive."); + } + + // Parse xml file ----------------------------------------------- + $pkginfo = $this->infoFromDescriptionFile($descfile); + if (PEAR::isError($pkginfo)) { + return $pkginfo; + } + + // Copy files to dest dir --------------------------------------- + if (!is_dir($this->phpdir)) { + return $this->raiseError("No script destination directory found\n", + null, PEAR_ERROR_DIE); + } + foreach ($pkginfo['filelist'] as $fname => $atts) { + $dest_dir = $this->phpdir . DIRECTORY_SEPARATOR . dirname($fname); + $fname = dirname($descfile) . DIRECTORY_SEPARATOR . $fname; + $this->_copyFile($fname, $dest_dir, $atts); + } + return true; + } + + function _copyFile($file, $dest_dir, $atts) + { + $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': + case 'php': + default: + $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file); + break; + } + 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"); + } + if (!@copy($file, $dest_file)) { + $this->log(0, "failed to copy $file to $dest_file"); + return false; + } + $this->log(2, "+ copy $file to $dest_file"); + // FIXME Update Package database here + //$this->updatePackageListFrom("$d/$file"); + $this->log(1, "installed file $dest_file"); + return true; + } + + /* REMOVEME: This is the old code + function _install($pkgfile) { if (preg_match('#^(http|ftp)://#', $pkgfile)) { $need_download = true; @@ -356,12 +477,10 @@ class PEAR_Installer extends PEAR_Common $this->current_attributes = $attribs; switch ($name) { case "Package": -/* - if (strtolower($attribs["Type"]) != "binary") { - return $this->raiseError("Invalid package: only binary packages supported yet."); - } - $this->pkginfo['pkgtype'] = strtolower($attribs["Type"]); -*/ + //if (strtolower($attribs["Type"]) != "binary") { + // return $this->raiseError("Invalid package: only binary packages supported yet."); + //} + //$this->pkginfo['pkgtype'] = strtolower($attribs["Type"]); break; } } @@ -446,7 +565,7 @@ class PEAR_Installer extends PEAR_Common break; } } - + */ // }}} // {{{ classesDeclaredBy() -- 2.50.1