diff options
author | Christian Stocker <chregu@php.net> | 2001-07-30 15:54:28 +0000 |
---|---|---|
committer | Christian Stocker <chregu@php.net> | 2001-07-30 15:54:28 +0000 |
commit | 410dfbe6a46e37c861b197fe0451b30c049deae9 (patch) | |
tree | bc2be60245f1beadaa362be302984da925d30868 | |
parent | 8fca87adb52eac356effd749f447eae7a805695a (diff) | |
download | php-git-410dfbe6a46e37c861b197fe0451b30c049deae9.tar.gz |
moved from the Experimental dir. the basic things should work...
-rw-r--r-- | pear/PEAR/WebInstaller.php | 627 |
1 files changed, 627 insertions, 0 deletions
diff --git a/pear/PEAR/WebInstaller.php b/pear/PEAR/WebInstaller.php new file mode 100644 index 0000000000..5fb7c46aec --- /dev/null +++ b/pear/PEAR/WebInstaller.php @@ -0,0 +1,627 @@ +<?php +/* vim: set expandtab tabstop=4 shiftwidth=4; */ +// +---------------------------------------------------------------------+ +// | PHP version 4.0 | +// +---------------------------------------------------------------------+ +// | Copyright (c) 1997-2001 The PHP Group | +// +---------------------------------------------------------------------+ +// | This source file is subject to version 2.0 of the PHP license, | +// | that is bundled with this package in the file LICENSE, and is | +// | available 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: Christian Stocker <chregu@phant.ch> | +// +---------------------------------------------------------------------+ + + +/* This class should simplify the task of installing PEAR-packages, if you + * don't have a cgi-php binary on your system or you don't have access to + * the system-wide pear directory. + * + * To use it, make the following php-script: + * + * <?php + * require("PEAR/WebInstaller.php"); + * $installer = new PEAR_WebInstaller("/path/to/your/install/dir","http://php.chregu.tv/pear/"); + * $installer->start(); + * ?> + * + * and put PEAR/WebInstaller.php (this script) anywhere in your include_path. + * + * (http://php.chregu.tv/pear/ is just for testing purposes until this + * system runs on pear.php.net, but feel free to use it till then) + * + * Both parameters are optional. If the install dir is ommitted, the + * installer takes either the system wide pear-directory (mostly + * /usr/local/lib/php on unix), if it's writeable, or else the directory + * the script is started. Be advised, that the directory, where the + * PEAR::Packages will be installed, has to be writeable for the web-server. + * + * The second parameter points to the server/directory where all the + * packages and especially Packages.xml is located. If not given, the + * standard PEAR-Repository is taken (http://pear.php.net/whatever..) + * + * After installation, just add the install-dir to your include_path and + * the packages should work. + * + * If you are System Adminisitrator and want the installed packages to be + * made available for everyone, just copy the files to the systemwide + * pear-dir after installation on the commandline. Or also add the + * install-dir to the systemwide include_path (and maybe don't forget to + * take the writeable off the directory..) + * + * TODO: + * - More Error Detection + * - Grouping of Packages + * - Show installed Packages (from /var/lib/php/packages.lst?) + * - Add possibility to install a package (.tgz) from the local file + * system without a global Packages.xml (useful if no cgi-php + * around and you need this package you downloaded installed :) ) + * - Search Function (maybe needed if we have hundreds of packages) + * - Only download Packages.xml, if it actually changed. + * + * This Code is highly experimental. + */ + +require_once "PEAR.php"; + +class PEAR_WebInstaller extends PEAR +{ + // {{{ properties + + /** stack of elements, gives some sort of XML context */ + var $element_stack; + + /** name of currently parsed XML element */ + var $current_element; + + /** array of attributes of the currently parsed XML element */ + var $current_attributes = array(); + + /** assoc with information about a package */ + var $pkginfo = array(); + + /** assoc with information about all packages */ + var $AllPackages; + + /** URL to the server containing all packages in tgz-Format and the Package.xml */ + var $remotedir = "http://php.chregu.tv/pear/"; + + /* Directory where the to be installed files should be put + per default PEAR_INSTALL_DIR (/usr/local/lib/php) if it's writeable for the webserver, + else current directory, or user defined directory (provided as first parameter in constructor) + The Directory hast to be writeable for the php-module (webserver) + */ + var $installdir; + + /** how many seconds we should cache Packages.xml */ + var $cachetime = 3600; + + var $printlogger = True; + // }}} + + // {{{ constructor + + function PEAR_Webinstaller($installdir = Null,$remotedir = Null) + { + $this->PEAR(); + if ($installdir) + { + $this->installdir = $installdir; + } + else + { + if (is_writeable(PEAR_INSTALL_DIR)) + { + $this->installdir = PEAR_INSTALL_DIR; + } + else + { + $this->installdir = getcwd(); + } + } + + if ($remotedir) + { + $this->remotedir = $remotedir; + } + } + + // }}} + // {{{ start() + + function start() { + global $HTTP_POST_VARS,$HTTP_GET_VARS; + + //print header + $this->header(); + + $this->loggerStart(); + + //if some checkboxes for installation were selected, install. + if ($HTTP_GET_VARS["help"]) { + + $this->help($HTTP_GET_VARS["help"]); + } + + elseif ($HTTP_POST_VARS["InstPack"]) { + $this->installPackages(array_keys($HTTP_POST_VARS["InstPack"])); + } + + //else print all modules + else { + $this->printTable(); + } + $this->footer(); + } + // }}} + // {{{ installPackages() + + /* installs the Packages and prints if successfull or not */ + + function installPackages($packages) + { + require_once "PEAR/Installer.php"; + $installer =& new PEAR_Installer(); + $installer->phpdir = $this->installdir; + $this->loggerEnd(); + print "<TABLE CELLSPACING=0 BORDER=0 CELLPADDING=1>"; + print "<TR><TD BGCOLOR=\"#000000\">\n"; + print "<TABLE CELLSPACING=1 BORDER=0 CELLPADDING=3 width=100%>\n"; + print " <TR BGCOLOR=\"#e0e0e0\">\n"; + print " <TH>Package</TH>\n"; + print " <TH>Status</TH>\n"; + + foreach ($packages as $package) + { + + + if (++$i % 2) { + $bg1 = "#ffffff"; + $bg2 = "#f0f0f0"; + } + else { + $bg1 = "#f0f0f0"; + $bg2 = "#e0e0e0"; + } + print " <TR>\n"; + + print "<TD BGCOLOR=\"$bg1\">"; + print $package; + print "</TD>\n"; + + + /* + print "<TD BGCOLOR=\"$bg2\">"; + print "Installing ..."; + print "</td>"; + print " <TR>\n"; + print "<TD BGCOLOR=\"$bg1\">"; + print " "; + print "</TD>\n"; + */ + print "<TD BGCOLOR=\"$bg2\">"; + if (PEAR::isError($installer->Install($this->remotedir."/".$package.".tgz"))) { + print "\ninstall failed\n"; + } + else { + + print "install ok\n"; + } + print "</td></tr>\n"; + } + print "</td></tr>"; + print "</table>"; + print "<TABLE CELLSPACING=1 BORDER=0 CELLPADDING=3 width=\"100%\">\n"; + print " <TR BGCOLOR=\"$bg1\">\n"; + print "<th colspan=\"2\">"; + print "<a href=\"$GLOBALS[PHP_SELF]\">Back to the Packages</a>\n"; + print "</th></tr></table>"; + print"</td></tr></table>"; + } + + // }}} + // {{{ printTable() + /* Prints a table with all modules available on the server-directory */ + + function printTable() + { + global $PHP_SELF; + $Packages = $this->getPackages(); + if (PEAR::IsError($Packages)) + { + if ($this->printlogger) { + $this->logger($Packages->message); + } + else + { + print $Packages->message; + } + return $Packages; + } + $this->loggerEnd(); + print "<FORM action=\"$GLOBALS[PHP_SELF]\" method=\"post\">\n"; + print "<TABLE CELLSPACING=0 BORDER=0 CELLPADDING=1>"; + print "<TR><TD BGCOLOR=\"#000000\">\n"; + print "<TABLE CELLSPACING=1 BORDER=0 CELLPADDING=3 width=\"100%\">\n"; + print " <TR BGCOLOR=\"#e0e0e0\" >\n"; + print " <TH>Inst.</TH>\n"; + print " <TH>Package</TH>\n"; + print " <TH>Summary</TH>\n"; + print " <TH>Version</TH>\n"; + print " <TH>Release date</TH>\n"; + print " <TH>Release notes</TH>\n"; + print " </TR>\n"; + $i = 0; + + ksort($Packages); + foreach ( $Packages as $package) { + + if (++$i % 2) { + $bg1 = "#ffffff"; + $bg2 = "#f0f0f0"; + } + else { + $bg1 = "#f0f0f0"; + $bg2 = "#e0e0e0"; + } + + + print "<TR>\n"; + + print "<TD align=\"middle\" BGCOLOR=\"$bg2\">"; + print "<input type=\"checkbox\" name=\"InstPack[".$package["name"]."-".$package["version"]."]\">\n"; + print "</TD>\n"; + + print " <TD BGCOLOR=\"$bg1\">"; + print $this->printCell ($package[name],"http://pear.php.net/pkginfo.php?package=$package[name]"); + print "</TD>\n"; + + print "<TD BGCOLOR=\"$bg2\">"; + $this->printCell ($package["summary"]); + print "</TD>\n"; + + print "<TD BGCOLOR=\"$bg2\">"; + $this->printCell ($package["version"],$this->remotedir."/".$package["name"]."-".$package["version"].".tgz"); + print "</TD>\n"; + + print "<TD BGCOLOR=\"$bg2\">"; + $this->printCell ($package["release_date"]); + print "</TD>\n"; + + print "<TD BGCOLOR=\"$bg2\">"; + $this->printCell ($package["release_notes"]); + print "</TD>\n"; + print " </TR>\n"; + + } + print "<tr bgcolor=\"$bg1\">"; + print "<td COLSPAN=\"6\" ><input type=\"submit\" value=\"Install\"></td>"; + print "</tr>"; + print "</TABLE> \n"; + + + print "<TABLE CELLSPACING=1 BORDER=0 CELLPADDING=3 width=\"100%\">\n"; + print " <TR BGCOLOR=\"#e0e0e0\">\n"; + + print "<th align=left width=\"10%\" nowrap>\n"; + print "Install Directory: </th><td>$this->installdir"; + if (!is_writable($this->installdir)) + { + print " <font color=\"red\">(Directory is NOT writeable!)</font>"; + } + + print "</td></tr>\n"; + + print " <TR BGCOLOR=\"#f0f0f0\">\n"; + print "<th align=left width=\"10%\" nowrap>\n"; + print "PEAR Repository: </th><td>$this->remotedir</td></tr>\n"; + + print " <TR BGCOLOR=\"#e0e0e0\">\n"; + print "<th align=left width=\"10%\" nowrap>\n"; + print "Caching Time: </th><td>$this->cachetime seconds</td></tr>\n"; + + print "</table>\n"; + print "</tr></td></table></FORM>\n"; + print "<a href=\"$PHP_SELF?help=1\">Help</A>\n"; + } + + // }}} + // {{{ getPackages() + + /** gets the Packages.xml from the server and saves it on the local disc for caching (if possible) + * If the zlib-extension is compiled in, Packages.xml.gz is used instead. + */ + + function getPackages ($TryGz = True) + { + + // if we can write to the installdir, cache the Packages.xml there + + $PackageFile = "Packages.xml"; + + // check if we have the zlib-extension compiled in + if ($TryGz && function_exists("gzfile")) { $useGz = True; $PackageFile .= ".gz";} + + // check if we can write the Package.xml file for caching + + if ( is_writeable($this->installdir."/$PackageFile") || !file_exists($this->installdir."/$PackageFile") && is_writeable($this->installdir) ) + { + $time = filemtime($this->installdir."/$PackageFile"); + + if ($time < (time () - $this->cachetime )) { + $this->logger("$PackageFile to old. Get new one."); + $fp = @fopen($this->remotedir."/$PackageFile","r"); + if (!$fp) { + if ($useGz) + { + $this->logger("$PackageFile could not be read. Try uncompressed one"); + return $this->getPackages(False); + } + else { + $this->logger("$PackageFile could not be read."); + return $this->raiseError("$PackageFile could not be read."); + } + } + $fout = fopen($this->installdir."/$PackageFile","w"); + while ($data = fread($fp,8192)) { + fwrite ($fout, $data); + } + fclose($fout); + fclose($fp); + $this->logger("Got $PackageFile"); + } + else { + $this->logger("Cached $PackageFile seems new enough"); + } + $Packages = $this->infoFromDescriptionFile($this->installdir."/$PackageFile"); + } + else + { + $this->logger("$PackageFile can not be cached, because Install-Dir or $PackageFile is not writeable. Get it each time from the server"); + $Packages = $this->infoFromDescriptionFile($this->remotedir."/Packages.xml"); + } + $this->logger("Got Packages"); + return $Packages; + } + + // }}} + // {{{ printCell() + + function printCell($text,$link = Null) + { + if ($text) + { + if ($link) { + print "<a href=\"$link\" style=\"color: #000000;\">"; + } + + print "$text"; + + if ($link) { + print "</a>"; + } + + } + else + { + print " "; + } + } + + // }}} + /* The following 4 functions are taken from PEAR/Common.php written by Stig Bakken + I had to adjust to use the Packages.xml format. + */ + // {{{ _element_start() + + + function _element_start($xp, $name, $attribs) + { + array_push($this->element_stack, $name); + $this->current_element = $name; + $this->current_attributes = $attribs; + } + + // }}} + // {{{ _element_end() + + function _element_end($xp, $name) + { + array_pop($this->element_stack); + if ($name == "Package") + { + $this->AllPackages[$this->pkginfo["name"]] = $this->pkginfo; + $this->pkginfo = array(); + + } + + $this->current_element = $this->element_stack[sizeof($this->element_stack)-1]; + } + + // }}} + // {{{ _pkginfo_cdata() + + function _pkginfo_cdata($xp, $data) + { + $next = $this->element_stack[sizeof($this->element_stack)-1]; + switch ($this->current_element) { + case "Name": + $this->pkginfo["name"] .= $data; + break; + case "Summary": + $this->pkginfo["summary"] .= $data; + break; + case "Initials": + $this->pkginfo["maintainer_handle"] .= $data; + break; + case "Email": + $this->pkginfo["maintainer_email"] .= $data; + break; + case "Version": + $this->pkginfo["version"] .= $data; + break; + case "Date": + $this->pkginfo["release_date"] .= $data; + break; + case "Notes": + $this->pkginfo["release_notes"] .= $data; + break; + case "Dir": + if (!$this->installdir) { + break; + } + $dir = trim($data); + // XXX add to file list + break; + case "File": + $role = strtolower($this->current_attributes["Role"]); + $file = trim($data); + // XXX add to file list + break; + } + } + + // }}} + // {{{ infoFromDescriptionFile() + + function infoFromDescriptionFile($descfile) + { + $fp = @fopen($descfile,"r"); + if (!$fp) { + return $this->raiseError("Unable to open $descfile in ".__FILE__.":".__LINE__); + } + $xp = @xml_parser_create(); + + if (!$xp) { + return $this->raiseError("Unable to create XML parser."); + } + + xml_set_object($xp, $this); + + xml_set_element_handler($xp, "_element_start", "_element_end"); + xml_set_character_data_handler($xp, "_pkginfo_cdata"); + xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false); + + $this->element_stack = array(); + $this->pkginfo = array(); + $this->current_element = false; + $this->destdir = ''; + + // read the whole thing so we only get one cdata callback + // for each block of cdata + + if (preg_match("/\.gz$/",$descfile)) + { + $data = implode("",gzfile($descfile)); + } + else + { + $data = implode("",file($descfile)); + } + + if (!@xml_parse($xp, $data, 1)) { + $msg = sprintf("XML error: %s at line %d", + xml_error_string(xml_get_error_code($xp)), + xml_get_current_line_number($xp)); + xml_parser_free($xp); + return $this->raiseError($msg); + } + + xml_parser_free($xp); + + foreach ($this->pkginfo as $k => $v) { + $this->pkginfo[$k] = trim($v); + } + + return $this->AllPackages; + } + + // }}} + // {{{ header() + + function header () + { + print "<html> + <head> + <title>PEAR::WebInstaller</title>\n"; + if (file_exists("./style.css")) + { + print '<link rel="stylesheet" href="/style.css">'; + } + print "</head> + <body bgcolor=\"#FFFFFF\"> + <h3>PEAR::WebInstaller</h3>"; + + } + + // }}} + // {{{ footer() + + function footer () { + print "</body></html>"; + } + + // }}} + + function logger ($text) { + + if ($this->printlogger) { + if (++$this->logcol % 2) { + $bg1 = "#ffffff"; + $bg2 = "#f0f0f0"; + } + else { + $bg1 = "#f0f0f0"; + $bg2 = "#e0e0e0"; + } + print "<TR>\n"; + print "<TD BGCOLOR=\"$bg1\">".date("h:m:i",time())."</td>"; + print "<TD BGCOLOR=\"$bg2\">"; + print "$text\n"; + print "</TD>\n"; + print "</tr>"; + } + } + function loggerStart () { + if ($this->printlogger) { + print "<TABLE CELLSPACING=0 BORDER=0 CELLPADDING=1>"; + print "<TR><TD BGCOLOR=\"#000000\">\n"; + print "<TABLE CELLSPACING=1 BORDER=0 CELLPADDING=3 width=\"100%\">\n"; + } + } + + function loggerEnd () { + if ($this->printlogger) { + print "</table></td></tr></table>"; + } + } + function help ($Full = False) { +global $PHP_SELF; + $this->loggerEnd(); + print "From the WebInstaller.php introduction: <p>"; + + // $file = implode("",file(__FILE__)); + $file = file(__FILE__); + foreach($file as $line) + { + if ($Full != 2 && strstr($line,"require_once")){ + break; + } + $help .= $line; + } + highlight_string($help); + print "<p>"; + if ($Full != 2) { + print "<a href=\"$PHP_SELF?help=2\">See the full source</a><p>\n"; + } + + print "<a href=\"$PHP_SELF\">Back to the packages overview</A>\n"; + } + +} + +?> |