// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Stig Bakken <ssb@fast.no> |
-// | |
+// | Tomas V.V.Cox <cox@idecnet.com> |
// +----------------------------------------------------------------------+
//
+// $Id$
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 <ssb@fast.no>
*/
$this->extdir = $extdir;
$this->docdir = $docdir;
$this->statedir = "/var/lib/php"; // XXX FIXME Windows
- $this->loadPackageList("$this->statedir/packages.lst");
}
// }}}
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);
}
// }}}
- // {{{ 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()
*
* @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;
$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;
}
}
break;
}
}
-
+ */
// }}}
// {{{ classesDeclaredBy()