Annotation of /mambo/trunk/administrator/components/com_installer/installer.class.php
Parent Directory
|
Revision Log
Revision 1 - (view) (download)
| 1 : | root | 1 | <?php |
| 2 : | /** | ||
| 3 : | * @version $Id: installer.class.php,v 1.1 2005/07/22 01:52:29 eddieajau Exp $ | ||
| 4 : | * @package Mambo | ||
| 5 : | * @subpackage Installer | ||
| 6 : | * @copyright (C) 2000 - 2005 Miro International Pty Ltd | ||
| 7 : | * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL | ||
| 8 : | * Mambo is Free Software | ||
| 9 : | */ | ||
| 10 : | |||
| 11 : | /** ensure this file is being included by a parent file */ | ||
| 12 : | defined( '_VALID_MOS' ) or die( 'Direct Access to this location is not allowed.' ); | ||
| 13 : | |||
| 14 : | /** | ||
| 15 : | * Installer class | ||
| 16 : | * @package Mambo | ||
| 17 : | * @subpackage Installer | ||
| 18 : | * @abstract | ||
| 19 : | */ | ||
| 20 : | class mosInstaller { | ||
| 21 : | // name of the XML file with installation information | ||
| 22 : | var $i_installfilename = ""; | ||
| 23 : | var $i_installarchive = ""; | ||
| 24 : | var $i_installdir = ""; | ||
| 25 : | var $i_iswin = false; | ||
| 26 : | var $i_errno = 0; | ||
| 27 : | var $i_error = ""; | ||
| 28 : | var $i_installtype = ""; | ||
| 29 : | var $i_unpackdir = ""; | ||
| 30 : | var $i_docleanup = true; | ||
| 31 : | |||
| 32 : | /** @var string The directory where the element is to be installed */ | ||
| 33 : | var $i_elementdir = ''; | ||
| 34 : | /** @var string The name of the Mambo element */ | ||
| 35 : | var $i_elementname = ''; | ||
| 36 : | /** @var string The name of a special atttibute in a tag */ | ||
| 37 : | var $i_elementspecial = ''; | ||
| 38 : | /** @var object A DOMIT XML document */ | ||
| 39 : | var $i_xmldoc = null; | ||
| 40 : | |||
| 41 : | var $i_hasinstallfile = null; | ||
| 42 : | var $i_installfile = null; | ||
| 43 : | |||
| 44 : | /** | ||
| 45 : | * Constructor | ||
| 46 : | */ | ||
| 47 : | function mosInstaller() { | ||
| 48 : | $this->i_iswin = (substr(PHP_OS, 0, 3) == 'WIN'); | ||
| 49 : | } | ||
| 50 : | /** | ||
| 51 : | * Uploads and unpacks a file | ||
| 52 : | * @param string The uploaded package filename or install directory | ||
| 53 : | * @param boolean True if the file is an archive file | ||
| 54 : | * @return boolean True on success, False on error | ||
| 55 : | */ | ||
| 56 : | function upload($p_filename = null, $p_unpack = true) { | ||
| 57 : | $this->i_iswin = (substr(PHP_OS, 0, 3) == 'WIN'); | ||
| 58 : | $this->installArchive( $p_filename ); | ||
| 59 : | |||
| 60 : | if ($p_unpack) { | ||
| 61 : | if ($this->extractArchive()) { | ||
| 62 : | return $this->findInstallFile(); | ||
| 63 : | } else { | ||
| 64 : | return false; | ||
| 65 : | } | ||
| 66 : | } | ||
| 67 : | } | ||
| 68 : | /** | ||
| 69 : | * Extracts the package archive file | ||
| 70 : | * @return boolean True on success, False on error | ||
| 71 : | */ | ||
| 72 : | function extractArchive() { | ||
| 73 : | global $mosConfig_absolute_path; | ||
| 74 : | |||
| 75 : | $base_Dir = mosPathName( $mosConfig_absolute_path . '/media' ); | ||
| 76 : | |||
| 77 : | $archivename = $base_Dir . $this->installArchive(); | ||
| 78 : | $tmpdir = uniqid( 'install_' ); | ||
| 79 : | |||
| 80 : | $extractdir = mosPathName( $base_Dir . $tmpdir ); | ||
| 81 : | $archivename = mosPathName( $archivename, false ); | ||
| 82 : | |||
| 83 : | $this->unpackDir( $extractdir ); | ||
| 84 : | |||
| 85 : | if (eregi( '.zip$', $archivename )) { | ||
| 86 : | // Extract functions | ||
| 87 : | require_once( $mosConfig_absolute_path . '/administrator/includes/pcl/pclzip.lib.php' ); | ||
| 88 : | require_once( $mosConfig_absolute_path . '/administrator/includes/pcl/pclerror.lib.php' ); | ||
| 89 : | //require_once( $mosConfig_absolute_path . '/administrator/includes/pcl/pcltrace.lib.php' ); | ||
| 90 : | //require_once( $mosConfig_absolute_path . '/administrator/includes/pcl/pcltar.lib.php' ); | ||
| 91 : | $zipfile = new PclZip( $archivename ); | ||
| 92 : | if($this->isWindows()) { | ||
| 93 : | define('OS_WINDOWS',1); | ||
| 94 : | } else { | ||
| 95 : | define('OS_WINDOWS',0); | ||
| 96 : | } | ||
| 97 : | |||
| 98 : | $ret = $zipfile->extract( PCLZIP_OPT_PATH, $extractdir ); | ||
| 99 : | if($ret == 0) { | ||
| 100 : | $this->setError( 1, 'Unrecoverable error "'.$zipfile->errorName(true).'"' ); | ||
| 101 : | return false; | ||
| 102 : | } | ||
| 103 : | } else { | ||
| 104 : | require_once( $mosConfig_absolute_path . '/includes/Archive/Tar.php' ); | ||
| 105 : | $archive =& new Archive_Tar( $archivename ); | ||
| 106 : | $archive->setErrorHandling( PEAR_ERROR_PRINT ); | ||
| 107 : | |||
| 108 : | if (!$archive->extractModify( $extractdir, '' )) { | ||
| 109 : | $this->setError( 1, 'Extract Error' ); | ||
| 110 : | return false; | ||
| 111 : | } | ||
| 112 : | } | ||
| 113 : | |||
| 114 : | $this->installDir( $extractdir ); | ||
| 115 : | |||
| 116 : | // Try to find the correct install dir. in case that the package have subdirs | ||
| 117 : | // Save the install dir for later cleanup | ||
| 118 : | $filesindir = mosReadDirectory( $this->installDir(), '' ); | ||
| 119 : | |||
| 120 : | if (count( $filesindir ) == 1) { | ||
| 121 : | if (is_dir( $extractdir . $filesindir[0] )) { | ||
| 122 : | $this->installDir( mosPathName( $extractdir . $filesindir[0] ) ); | ||
| 123 : | } | ||
| 124 : | } | ||
| 125 : | return true; | ||
| 126 : | } | ||
| 127 : | /** | ||
| 128 : | * Tries to find the package XML file | ||
| 129 : | * @return boolean True on success, False on error | ||
| 130 : | */ | ||
| 131 : | function findInstallFile() { | ||
| 132 : | $found = false; | ||
| 133 : | // Search the install dir for an xml file | ||
| 134 : | $files = mosReadDirectory( $this->installDir(), '.xml$', true, true ); | ||
| 135 : | |||
| 136 : | if (count( $files ) > 0) { | ||
| 137 : | foreach ($files as $file) { | ||
| 138 : | $packagefile = $this->isPackageFile( $file ); | ||
| 139 : | if (!is_null( $packagefile ) && !$found ) { | ||
| 140 : | $this->xmlDoc( $packagefile ); | ||
| 141 : | return true; | ||
| 142 : | } | ||
| 143 : | } | ||
| 144 : | $this->setError( 1, 'ERROR: Could not find a Mambo XML setup file in the package.' ); | ||
| 145 : | return false; | ||
| 146 : | } else { | ||
| 147 : | $this->setError( 1, 'ERROR: Could not find an XML setup file in the package.' ); | ||
| 148 : | return false; | ||
| 149 : | } | ||
| 150 : | } | ||
| 151 : | /** | ||
| 152 : | * @param string A file path | ||
| 153 : | * @return object A DOMIT XML document, or null if the file failed to parse | ||
| 154 : | */ | ||
| 155 : | function isPackageFile( $p_file ) { | ||
| 156 : | $xmlDoc =& new DOMIT_Lite_Document(); | ||
| 157 : | $xmlDoc->resolveErrors( true ); | ||
| 158 : | |||
| 159 : | if (!$xmlDoc->loadXML( $p_file, false, true )) { | ||
| 160 : | return null; | ||
| 161 : | } | ||
| 162 : | $element = &$xmlDoc->documentElement; | ||
| 163 : | |||
| 164 : | if ($element->getTagName() != 'mosinstall') { | ||
| 165 : | return null; | ||
| 166 : | } | ||
| 167 : | // Set the type | ||
| 168 : | $this->installType( $element->getAttribute( 'type' ) ); | ||
| 169 : | $this->installFilename( $p_file ); | ||
| 170 : | return $xmlDoc; | ||
| 171 : | } | ||
| 172 : | /** | ||
| 173 : | * Loads and parses the XML setup file | ||
| 174 : | * @return boolean True on success, False on error | ||
| 175 : | */ | ||
| 176 : | function readInstallFile() { | ||
| 177 : | |||
| 178 : | if ($this->installFilename() == "") { | ||
| 179 : | $this->setError( 1, 'No filename specified' ); | ||
| 180 : | return false; | ||
| 181 : | } | ||
| 182 : | |||
| 183 : | $this->i_xmldoc =& new DOMIT_Lite_Document(); | ||
| 184 : | $this->i_xmldoc->resolveErrors( true ); | ||
| 185 : | if (!$this->i_xmldoc->loadXML( $this->installFilename(), false, true )) { | ||
| 186 : | return false; | ||
| 187 : | } | ||
| 188 : | $main_element = &$this->i_xmldoc->documentElement; | ||
| 189 : | |||
| 190 : | // Check that it's am installation file | ||
| 191 : | if ($main_element->getTagName() != 'mosinstall') { | ||
| 192 : | $this->setError( 1, 'File :"' . $this->installFilename() . '" is not a valid Mambo installation file' ); | ||
| 193 : | return false; | ||
| 194 : | } | ||
| 195 : | |||
| 196 : | $this->installType( $main_element->getAttribute( 'type' ) ); | ||
| 197 : | return true; | ||
| 198 : | } | ||
| 199 : | /** | ||
| 200 : | * Abstract install method | ||
| 201 : | */ | ||
| 202 : | function install() { | ||
| 203 : | die( 'Method "install" cannot be called by class ' . strtolower(get_class( $this )) ); | ||
| 204 : | } | ||
| 205 : | /** | ||
| 206 : | * Abstract uninstall method | ||
| 207 : | */ | ||
| 208 : | function uninstall() { | ||
| 209 : | die( 'Method "uninstall" cannot be called by class ' . strtolower(get_class( $this )) ); | ||
| 210 : | } | ||
| 211 : | /** | ||
| 212 : | * return to method | ||
| 213 : | */ | ||
| 214 : | function returnTo( $option, $element ) { | ||
| 215 : | return "index2.php?option=$option&element=$element"; | ||
| 216 : | } | ||
| 217 : | /** | ||
| 218 : | * @param string Install from directory | ||
| 219 : | * @param string The install type | ||
| 220 : | * @return boolean | ||
| 221 : | */ | ||
| 222 : | function preInstallCheck( $p_fromdir, $type ) { | ||
| 223 : | |||
| 224 : | if (!is_null($p_fromdir)) { | ||
| 225 : | $this->installDir($p_fromdir); | ||
| 226 : | } | ||
| 227 : | |||
| 228 : | if (!$this->installfile()) { | ||
| 229 : | $this->findInstallFile(); | ||
| 230 : | } | ||
| 231 : | |||
| 232 : | if (!$this->readInstallFile()) { | ||
| 233 : | $this->setError( 1, 'Installation file not found:<br />' . $this->installDir() ); | ||
| 234 : | return false; | ||
| 235 : | } | ||
| 236 : | |||
| 237 : | if ($this->installType() != $type) { | ||
| 238 : | $this->setError( 1, 'XML setup file is not for a "'.$type.'".' ); | ||
| 239 : | return false; | ||
| 240 : | } | ||
| 241 : | |||
| 242 : | // In case there where an error doring reading or extracting the archive | ||
| 243 : | if ($this->errno()) { | ||
| 244 : | return false; | ||
| 245 : | } | ||
| 246 : | |||
| 247 : | return true; | ||
| 248 : | } | ||
| 249 : | /** | ||
| 250 : | * @param string The tag name to parse | ||
| 251 : | * @param string An attribute to search for in a filename element | ||
| 252 : | * @param string The value of the 'special' element if found | ||
| 253 : | * @param boolean True for Administrator components | ||
| 254 : | * @return mixed Number of file or False on error | ||
| 255 : | */ | ||
| 256 : | function parseFiles( $tagName='files', $special='', $specialError='', $adminFiles=0 ) { | ||
| 257 : | global $mosConfig_absolute_path; | ||
| 258 : | // Find files to copy | ||
| 259 : | $xml =& $this->xmlDoc(); | ||
| 260 : | |||
| 261 : | $files_element =& $xml->getElementsByPath( $tagName, 1 ); | ||
| 262 : | if (is_null( $files_element )) { | ||
| 263 : | return 0; | ||
| 264 : | } | ||
| 265 : | |||
| 266 : | if (!$files_element->hasChildNodes()) { | ||
| 267 : | // no files | ||
| 268 : | return 0; | ||
| 269 : | } | ||
| 270 : | $files = $files_element->childNodes; | ||
| 271 : | $copyfiles = array(); | ||
| 272 : | if (count( $files ) == 0) { | ||
| 273 : | // nothing more to do | ||
| 274 : | return 0; | ||
| 275 : | } | ||
| 276 : | |||
| 277 : | if ($folder = $files_element->getAttribute( 'folder' )) { | ||
| 278 : | $temp = mosPathName( $this->unpackDir() . $folder ); | ||
| 279 : | if ($temp == $this->installDir()) { | ||
| 280 : | // this must be only an admin component | ||
| 281 : | $installFrom = $this->installDir(); | ||
| 282 : | } else { | ||
| 283 : | $installFrom = mosPathName( $this->installDir() . $folder ); | ||
| 284 : | } | ||
| 285 : | } else { | ||
| 286 : | $installFrom = $this->installDir(); | ||
| 287 : | } | ||
| 288 : | |||
| 289 : | foreach ($files as $file) { | ||
| 290 : | if (basename( $file->getText() ) != $file->getText()) { | ||
| 291 : | $newdir = dirname( $file->getText() ); | ||
| 292 : | |||
| 293 : | if ($adminFiles){ | ||
| 294 : | if (!mosMakePath( $this->componentAdminDir(), $newdir )) { | ||
| 295 : | $this->setError( 1, 'Failed to create directory "' . ($this->componentAdminDir()) . $newdir . '"' ); | ||
| 296 : | return false; | ||
| 297 : | } | ||
| 298 : | } else { | ||
| 299 : | if (!mosMakePath( $this->elementDir(), $newdir )) { | ||
| 300 : | $this->setError( 1, 'Failed to create directory "' . ($this->elementDir()) . $newdir . '"' ); | ||
| 301 : | return false; | ||
| 302 : | } | ||
| 303 : | } | ||
| 304 : | } | ||
| 305 : | $copyfiles[] = $file->getText(); | ||
| 306 : | |||
| 307 : | // check special for attribute | ||
| 308 : | if ($file->getAttribute( $special )) { | ||
| 309 : | $this->elementSpecial( $file->getAttribute( $special ) ); | ||
| 310 : | } | ||
| 311 : | } | ||
| 312 : | |||
| 313 : | if ($specialError) { | ||
| 314 : | if ($this->elementSpecial() == '') { | ||
| 315 : | $this->setError( 1, $specialError ); | ||
| 316 : | return false; | ||
| 317 : | } | ||
| 318 : | } | ||
| 319 : | |||
| 320 : | if ($tagName == 'media') { | ||
| 321 : | // media is a special tag | ||
| 322 : | $installTo = mosPathName( $mosConfig_absolute_path . '/images/stories' ); | ||
| 323 : | } else if ($adminFiles) { | ||
| 324 : | $installTo = $this->componentAdminDir(); | ||
| 325 : | } else { | ||
| 326 : | $installTo = $this->elementDir(); | ||
| 327 : | } | ||
| 328 : | $result = $this->copyFiles( $installFrom, $installTo, $copyfiles ); | ||
| 329 : | |||
| 330 : | return $result; | ||
| 331 : | } | ||
| 332 : | /** | ||
| 333 : | * @param string Source directory | ||
| 334 : | * @param string Destination directory | ||
| 335 : | * @param array array with filenames | ||
| 336 : | * @param boolean True is existing files can be replaced | ||
| 337 : | * @return boolean True on success, False on error | ||
| 338 : | */ | ||
| 339 : | function copyFiles( $p_sourcedir, $p_destdir, $p_files, $overwrite=false ) { | ||
| 340 : | if (is_array( $p_files ) && count( $p_files ) > 0) { | ||
| 341 : | foreach($p_files as $_file) { | ||
| 342 : | $filesource = mosPathName( mosPathName( $p_sourcedir ) . $_file, false ); | ||
| 343 : | $filedest = mosPathName( mosPathName( $p_destdir ) . $_file, false ); | ||
| 344 : | |||
| 345 : | if (!file_exists( $filesource )) { | ||
| 346 : | $this->setError( 1, "File $filesource does not exist!" ); | ||
| 347 : | return false; | ||
| 348 : | } else if (file_exists( $filedest ) && !$overwrite) { | ||
| 349 : | $this->setError( 1, "There is already a file called $filedest - Are you trying to install the same CMT twice?" ); | ||
| 350 : | return false; | ||
| 351 : | } else { | ||
| 352 : | if( !( copy($filesource,$filedest) && mosChmod($filedest) ) ) { | ||
| 353 : | $this->setError( 1, "Failed to copy file: $filesource to $filedest" ); | ||
| 354 : | return false; | ||
| 355 : | } | ||
| 356 : | } | ||
| 357 : | } | ||
| 358 : | } else { | ||
| 359 : | return false; | ||
| 360 : | } | ||
| 361 : | return count( $p_files ); | ||
| 362 : | } | ||
| 363 : | /** | ||
| 364 : | * Copies the XML setup file to the element Admin directory | ||
| 365 : | * Used by Components/Modules/Mambot Installer Installer | ||
| 366 : | * @return boolean True on success, False on error | ||
| 367 : | */ | ||
| 368 : | function copySetupFile( $where='admin' ) { | ||
| 369 : | if ($where == 'admin') { | ||
| 370 : | return $this->copyFiles( $this->installDir(), $this->componentAdminDir(), array( basename( $this->installFilename() ) ), true ); | ||
| 371 : | } else if ($where == 'front') { | ||
| 372 : | return $this->copyFiles( $this->installDir(), $this->elementDir(), array( basename( $this->installFilename() ) ), true ); | ||
| 373 : | } | ||
| 374 : | } | ||
| 375 : | |||
| 376 : | /** | ||
| 377 : | * @param int The error number | ||
| 378 : | * @param string The error message | ||
| 379 : | */ | ||
| 380 : | function setError( $p_errno, $p_error ) { | ||
| 381 : | $this->errno( $p_errno ); | ||
| 382 : | $this->error( $p_error ); | ||
| 383 : | } | ||
| 384 : | /** | ||
| 385 : | * @param boolean True to display both number and message | ||
| 386 : | * @param string The error message | ||
| 387 : | * @return string | ||
| 388 : | */ | ||
| 389 : | function getError($p_full = false) { | ||
| 390 : | if ($p_full) { | ||
| 391 : | return $this->errno() . " " . $this->error(); | ||
| 392 : | } else { | ||
| 393 : | return $this->error(); | ||
| 394 : | } | ||
| 395 : | } | ||
| 396 : | /** | ||
| 397 : | * @param string The name of the property to set/get | ||
| 398 : | * @param mixed The value of the property to set | ||
| 399 : | * @return The value of the property | ||
| 400 : | */ | ||
| 401 : | function setVar( $name, $value=null ) { | ||
| 402 : | if (!is_null( $value )) { | ||
| 403 : | $this->$name = $value; | ||
| 404 : | } | ||
| 405 : | return $this->$name; | ||
| 406 : | } | ||
| 407 : | |||
| 408 : | function installFilename( $p_filename = null ) { | ||
| 409 : | if(!is_null($p_filename)) { | ||
| 410 : | if($this->isWindows()) { | ||
| 411 : | $this->i_installfilename = str_replace('/','\\',$p_filename); | ||
| 412 : | } else { | ||
| 413 : | $this->i_installfilename = str_replace('\\','/',$p_filename); | ||
| 414 : | } | ||
| 415 : | } | ||
| 416 : | return $this->i_installfilename; | ||
| 417 : | } | ||
| 418 : | |||
| 419 : | function installType( $p_installtype = null ) { | ||
| 420 : | return $this->setVar( 'i_installtype', $p_installtype ); | ||
| 421 : | } | ||
| 422 : | |||
| 423 : | function error( $p_error = null ) { | ||
| 424 : | return $this->setVar( 'i_error', $p_error ); | ||
| 425 : | } | ||
| 426 : | |||
| 427 : | function xmlDoc( $p_xmldoc = null ) { | ||
| 428 : | return $this->setVar( 'i_xmldoc', $p_xmldoc ); | ||
| 429 : | } | ||
| 430 : | |||
| 431 : | function installArchive( $p_filename = null ) { | ||
| 432 : | return $this->setVar( 'i_installarchive', $p_filename ); | ||
| 433 : | } | ||
| 434 : | |||
| 435 : | function installDir( $p_dirname = null ) { | ||
| 436 : | return $this->setVar( 'i_installdir', $p_dirname ); | ||
| 437 : | } | ||
| 438 : | |||
| 439 : | function unpackDir( $p_dirname = null ) { | ||
| 440 : | return $this->setVar( 'i_unpackdir', $p_dirname ); | ||
| 441 : | } | ||
| 442 : | |||
| 443 : | function isWindows() { | ||
| 444 : | return $this->i_iswin; | ||
| 445 : | } | ||
| 446 : | |||
| 447 : | function errno( $p_errno = null ) { | ||
| 448 : | return $this->setVar( 'i_errno', $p_errno ); | ||
| 449 : | } | ||
| 450 : | |||
| 451 : | function hasInstallfile( $p_hasinstallfile = null ) { | ||
| 452 : | return $this->setVar( 'i_hasinstallfile', $p_hasinstallfile ); | ||
| 453 : | } | ||
| 454 : | |||
| 455 : | function installfile( $p_installfile = null ) { | ||
| 456 : | return $this->setVar( 'i_installfile', $p_installfile ); | ||
| 457 : | } | ||
| 458 : | |||
| 459 : | function elementDir( $p_dirname = null ) { | ||
| 460 : | return $this->setVar( 'i_elementdir', $p_dirname ); | ||
| 461 : | } | ||
| 462 : | |||
| 463 : | function elementName( $p_name = null ) { | ||
| 464 : | return $this->setVar( 'i_elementname', $p_name ); | ||
| 465 : | } | ||
| 466 : | function elementSpecial( $p_name = null ) { | ||
| 467 : | return $this->setVar( 'i_elementspecial', $p_name ); | ||
| 468 : | } | ||
| 469 : | } | ||
| 470 : | |||
| 471 : | function cleanupInstall( $userfile_name, $resultdir) { | ||
| 472 : | global $mosConfig_absolute_path; | ||
| 473 : | |||
| 474 : | if (file_exists( $resultdir )) { | ||
| 475 : | deldir( $resultdir ); | ||
| 476 : | unlink( mosPathName( $mosConfig_absolute_path . '/media/' . $userfile_name, false ) ); | ||
| 477 : | } | ||
| 478 : | } | ||
| 479 : | |||
| 480 : | function deldir( $dir ) { | ||
| 481 : | $current_dir = opendir( $dir ); | ||
| 482 : | while ($entryname = readdir( $current_dir )) { | ||
| 483 : | if ($entryname != '.' and $entryname != '..') { | ||
| 484 : | if (is_dir( $dir . $entryname )) { | ||
| 485 : | deldir( mosPathName( $dir . $entryname ) ); | ||
| 486 : | } else { | ||
| 487 : | unlink( $dir . $entryname ); | ||
| 488 : | } | ||
| 489 : | } | ||
| 490 : | } | ||
| 491 : | closedir( $current_dir ); | ||
| 492 : | return rmdir( $dir ); | ||
| 493 : | } | ||
| 494 : | ?> |
| ViewVC Help | |
| Powered by ViewVC 1.0.0 |
Web Hosting provided by Network Redux.

