From 410dfbe6a46e37c861b197fe0451b30c049deae9 Mon Sep 17 00:00:00 2001 From: Christian Stocker Date: Mon, 30 Jul 2001 15:54:28 +0000 Subject: [PATCH] moved from the Experimental dir. the basic things should work... --- pear/PEAR/WebInstaller.php | 627 +++++++++++++++++++++++++++++++++++++ 1 file changed, 627 insertions(+) create mode 100644 pear/PEAR/WebInstaller.php 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 @@ + | +// +---------------------------------------------------------------------+ + + +/* 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: + * + * 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 ""; + print "
\n"; + print "\n"; + print " \n"; + print " \n"; + print " \n"; + + foreach ($packages as $package) + { + + + if (++$i % 2) { + $bg1 = "#ffffff"; + $bg2 = "#f0f0f0"; + } + else { + $bg1 = "#f0f0f0"; + $bg2 = "#e0e0e0"; + } + print " \n"; + + print "\n"; + + + /* + print ""; + print " \n"; + print "\n"; + */ + print "\n"; + } + print ""; + print "
PackageStatus
"; + print $package; + print ""; + print "Installing ..."; + print "
"; + print " "; + print ""; + if (PEAR::isError($installer->Install($this->remotedir."/".$package.".tgz"))) { + print "\ninstall failed\n"; + } + else { + + print "install ok\n"; + } + print "
"; + print "\n"; + print " \n"; + print "
"; + print "Back to the Packages\n"; + print "
"; + print"
"; + } + + // }}} + // {{{ 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 "
\n"; + print ""; + print "
\n"; + print "\n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + print " \n"; + $i = 0; + + ksort($Packages); + foreach ( $Packages as $package) { + + if (++$i % 2) { + $bg1 = "#ffffff"; + $bg2 = "#f0f0f0"; + } + else { + $bg1 = "#f0f0f0"; + $bg2 = "#e0e0e0"; + } + + + print "\n"; + + print "\n"; + + print " \n"; + + print "\n"; + + print "\n"; + + print "\n"; + + print "\n"; + print " \n"; + + } + print ""; + print ""; + print ""; + print "
Inst.PackageSummaryVersionRelease dateRelease notes
"; + print "\n"; + print ""; + print $this->printCell ($package[name],"http://pear.php.net/pkginfo.php?package=$package[name]"); + print ""; + $this->printCell ($package["summary"]); + print ""; + $this->printCell ($package["version"],$this->remotedir."/".$package["name"]."-".$package["version"].".tgz"); + print ""; + $this->printCell ($package["release_date"]); + print ""; + $this->printCell ($package["release_notes"]); + print "
\n"; + + + print "\n"; + print " \n"; + + print "\n"; + + print " \n"; + print "\n"; + + print " \n"; + print "\n"; + + print "
\n"; + print "Install Directory: $this->installdir"; + if (!is_writable($this->installdir)) + { + print " (Directory is NOT writeable!)"; + } + + print "
\n"; + print "PEAR Repository: $this->remotedir
\n"; + print "Caching Time: $this->cachetime seconds
\n"; + print "
\n"; + print "Help\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 ""; + } + + print "$text"; + + if ($link) { + print ""; + } + + } + 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 " + + PEAR::WebInstaller\n"; + if (file_exists("./style.css")) + { + print ''; + } + print " + +

PEAR::WebInstaller

"; + + } + + // }}} + // {{{ footer() + + function footer () { + print ""; + } + + // }}} + + function logger ($text) { + + if ($this->printlogger) { + if (++$this->logcol % 2) { + $bg1 = "#ffffff"; + $bg2 = "#f0f0f0"; + } + else { + $bg1 = "#f0f0f0"; + $bg2 = "#e0e0e0"; + } + print "\n"; + print "".date("h:m:i",time()).""; + print ""; + print "$text\n"; + print "\n"; + print ""; + } + } + function loggerStart () { + if ($this->printlogger) { + print ""; + print "
\n"; + print "\n"; + } + } + + function loggerEnd () { + if ($this->printlogger) { + print "
"; + } + } + function help ($Full = False) { +global $PHP_SELF; + $this->loggerEnd(); + print "From the WebInstaller.php introduction:

"; + + // $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 "

"; + if ($Full != 2) { + print "See the full source

\n"; + } + + print "Back to the packages overview\n"; + } + +} + +?> -- 2.50.1