Current Path : /var/www/html/clients/kampol.e-nk.ru/administrator/components/com_joomlapack/classes/core/ |
Current File : /var/www/html/clients/kampol.e-nk.ru/administrator/components/com_joomlapack/classes/core/cube.php |
<?php /** * @package JoomlaPack * @copyright Copyright (C) 2006-2009 JoomlaPack Developers. All rights reserved. * @version $Id$ * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL * @since 1.3 */ defined('_JEXEC') or die('Restricted access'); // Include required classes if(!class_exists('JoomlapackModelStatistics')) { jpimport('models.statistics', true); } if(!class_exists('JoomlapackModelRegistry')) { jpimport('models.registry', true); } if(!class_exists('JoomlapackHelperUtils')) { jpimport('helpers.utils', true); } jpimport('core.utility.logger'); jpimport('abstract.enginearchiver'); jpimport('abstract.enginelister'); jpimport('abstract.engineparts'); jpimport('abstract.filter'); jpimport('core.domain.installer'); jpimport('core.domain.dbbackup'); jpimport('core.domain.pack'); jpimport('core.utility.tables'); jpimport('core.utility.filtermanager'); jpimport('core.utility.algorunner'); jpimport('core.utility.provisioning'); jpimport('core.utility.tempfiles'); /** * Componentized Universal Backup Engine, version 2.1 * * CUBE is the heart and brains of JoomlaPack. It takes care of all the magic for * producing a backup, delegating specialised tasks to CUBE Part and Engine classes. * This class is the API exposed to the component and is kept as simple as possible. * */ class JoomlapackCUBE extends JObject { /* * ====================================================================== * Public fields * ====================================================================== */ /** * CUBE engine provisioning object * * @var JoomlapackCUBEProvisioning */ var $provisioning; /** * Backup statistics model object * * @var JoomlapackModelStatistics */ var $statmodel; /** * Statistics ID; it's needed to finalize the backup * * @var int */ var $_statID; /** * Current step number, over the whole backup procedure * * @var int */ var $stepCounter; /** * Current operation number, over the current step * * @var int */ var $operationCounter; /** * @var string The relative path to the archive's name */ var $relativeArchiveName; /** * @var array The warnings LIFO stack, holds the last 10 warnings, w/ their * timestamp. Each element is an object w/ properties datetime, warning. */ var $_warnings; /* * ====================================================================== * Private fields * ====================================================================== */ /** @var bool Indicates whether CUBE has been initialised in order to take a backup */ var $_initialised = false; /** @var JoomlapackCUBEPart Part object being used in execution */ var $_object = null; /** @var string Active execution domain */ var $_activeDomain = null; /** @var bool Set to true upon finishing, or failing with an error */ var $_isFinished = false; /** @var string Current part's step */ var $_currentStep; /** @var string Current part's substep */ var $_currentSubstep; /** @var bool used to block multipart updating while CUBE is being created */ var $_lockMultiPartUpdate = true; /* * ====================================================================== * CUBE object loading * ====================================================================== */ /** * Singleton pattern. It tries to load the CUBE off the database if it's not * found in memory. If it fails too, it creates a new object. * * @return JoomlapackCUBE */ function &getInstance() { static $instance; if(!is_object($instance)) { // Try loading from database if(JoomlapackCUBETables::CountVar('CUBEObject') == 1) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackCUBE::getInstance - Loading from database"); // Get the includes first! JoomlapackCUBEProvisioning::retrieveEngineIncludes(); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, " -- Loaded requirements"); // Then load the object $instance = JoomlapackCUBETables::UnserializeVar('CUBEObject'); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, " -- Loaded instance"); if(!is_object($instance)) { // Damn! We have some broken crap in the db. Gotta retry :( JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackCUBE::getInstance - Broken in database, creating new instance"); $instance = new JoomlapackCUBE(); } } else { // No stored object, we are forced to create a fresh object or something really // odd is going on with MySQL! JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "JoomlapackCUBE::getInstance - Not found in database, creating new instance"); $instance = new JoomlapackCUBE(); } } return $instance; } function JoomlapackCUBE() { } /* * ====================================================================== * CUBE API * ====================================================================== */ /** * Static function to reset older backups, removing their temporary files * and marking them as failed. * * @static */ function reset($do_not_log = false) { // Pause logging if so desired if($do_not_log) JoomlapackLogger::WriteLog(false,''); // 1. Detect failed backups if(!class_exists('JoomlapackModelStatistics')) { jpimport('models.statistics', true); } $model =& JoomlapackModelStatistics::getInstance(); $runningList = $model->getRunningStatisticsList(); if(is_array($runningList)) { if(!empty($runningList)) { jimport('joomla.filesystem.file'); // Mark running backups as failed foreach($runningList as $running) { $filenames = $model->getAllFilenames($running->id, false); // Process if there are files to delete... if(!is_null($filenames)) { // Delete the failed backup's archive, if exists foreach($filenames as $failedArchive) { if(JFile::exists($failedArchive)) { if(!JFile::delete($failedArchive)) { // fallback; if Joomla! used FTP to unlink the file and it failed, let's try the old-fashioned way @unlink($failedArchive); } } } } // Mark the backup failed $running->status = 'fail'; $model->save($running); } unset($model); } } // 2. Delete any stale CUBE db entry / file JoomlapackCUBETables::DeleteVar('CUBEObject'); // 3. Remove temporary files JoomlapackCUBETempfiles::deleteTempFiles(); // 4. Remove temporary data from #__jp_temp JoomlapackCUBETables::DeleteMultipleVars('%CUBE%'); // Unpause logging if it was previously paused if($do_not_log) JoomlapackLogger::WriteLog(true,''); } /** * Initialises CUBE to start a new backup * */ function start($description = '', $comment = '') { global $mainframe; $this->_enforce_minexectime(true); // Start the timing // Initialize warnings $this->_warnings = array(); // Initialize counters $this->stepCounter = 0; $this->operationCounter = 0; // Initialize CUBEObject file storage (in case we need it) JoomlapackCUBETables::DeleteMultipleVars('%CUBE%'); // Load registry $configuration =& JoomlapackModelRegistry::getInstance(); $configuration->reload(); // Load engine provisioning object $this->provisioning =& JoomlapackCUBEProvisioning::getInstance(); // Initialize statistics model $this->statmodel =& JoomlapackModelStatistics::getInstance(); // Initialize private fields $this->_activeDomain = 'init'; $this->_object = null; $this->_isFinished = false; // Load JP version JoomlapackHelperUtils::getJoomlaPackVersion(); // Initialise log file JoomlapackLogger::ResetLog(); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "--------------------------------------------------------------------------------"); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "JoomlaPack "._JP_VERSION.' ('._JP_DATE.')'); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Got backup?"); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "--------------------------------------------------------------------------------"); // PHP configuration variables are tried to be logged only for debug and info log levels if ($configuration->get('logLevel') >= 2) { JoomlapackLogger::WriteLog(_JP_LOG_INFO, "--- System Information ---" ); if( function_exists('phpversion')) JoomlapackLogger::WriteLog(_JP_LOG_INFO, "PHP Version :" . phpversion() ); if(function_exists('php_uname')) JoomlapackLogger::WriteLog(_JP_LOG_INFO, "OS Version :" . php_uname('s') ); $db =& JFactory::getDBO(); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "DB Version :" . $db->getVersion() ); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "DB Collation :" . $db->getCollation() ); if (isset($_SERVER['SERVER_SOFTWARE'])) { $server = $_SERVER['SERVER_SOFTWARE']; } else if (($sf = getenv('SERVER_SOFTWARE'))) { $server = $sf; } else { $server = JText::_( 'n/a' ); } JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Web Server :" . $server ); if(function_exists('php_sapi_name')) JoomlapackLogger::WriteLog(_JP_LOG_INFO, "PHP Interface :" . php_sapi_name() ); $version = new JVersion(); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Joomla! version :" . $version->getLongVersion() ); if(isset($_SERVER['HTTP_USER_AGENT'])) JoomlapackLogger::WriteLog(_JP_LOG_INFO, "User agent :" . phpversion() <= "4.2.1" ? getenv( "HTTP_USER_AGENT" ) : $_SERVER['HTTP_USER_AGENT'] ); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Safe mode :" . ini_get("safe_mode") ); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Display errors :" . ini_get("display_errors") ); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Error reporting :" . error2string() ); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Disabled functions :" . ini_get("disable_functions") ); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "open_basedir restr.:" . ini_get('open_basedir') ); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Max. exec. time :" . ini_get("max_execution_time") ); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Memory limit :" . ini_get("memory_limit") ); if(function_exists("memory_get_usage")) JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Current mem. usage :" . memory_get_usage() ); if(function_exists("gzcompress")) { JoomlapackLogger::WriteLog(_JP_LOG_INFO, "GZIP Compression : available (good)" ); } else { JoomlapackLogger::WriteLog(_JP_LOG_INFO, "GZIP Compression : n/a (no compression)" ); } JoomlapackLogger::WriteLog(_JP_LOG_INFO, "JPATH_BASE :" . JPATH_BASE ); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "JPATH_SITE :" . JPATH_SITE ); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "JPATH_ROOT :" . JPATH_ROOT ); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "JPATH_CACHE :" . JPATH_CACHE ); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Output directory :" . $configuration->get('OutputDirectory') ); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Temporary directory:" . $configuration->getTemporaryDirectory() ); $temp = JoomlapackCUBETables::_getBase64() ? 'Available; will be used for temp vars' : 'Not available'; JoomlapackLogger::WriteLog(_JP_LOG_INFO, "BASE64 Encoding :" . $temp ); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "CUBEObject Storage :" . (JoomlapackCUBETables::_isSetCUBEInFile() ? 'Temporary file' : 'Database') ); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "--------------------------------------------------------------------------------"); } jpimport('helpers.status',true); $statushelper =& JoomlapackHelperStatus::getInstance(); if($statushelper->hasQuirks()) { JoomlapackLogger::WriteLog(_JP_LOG_INFO, "JoomlaPack has detected the following potential problems:" ); foreach($statushelper->quirks as $q) { JoomlapackLogger::WriteLog(_JP_LOG_INFO, '- '.$q['code'].' '.$q['description'].' ('.$q['severity'].')' ); } JoomlapackLogger::WriteLog(_JP_LOG_INFO, "You probably do not have to worry about them, but you should be aware of them." ); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "--------------------------------------------------------------------------------"); } // Get current profile ID $session =& JFactory::getSession(); $profile_id = $session->get('profile', null, 'joomlapack'); JoomlapackLogger::WriteLog(_JP_LOG_INFO, "Loading profile #$profile_id"); // Get archive name switch($configuration->get('BackupType')) { case 'dbonly': JoomlapackLogger::WriteLog(_JP_LOG_INFO, "JoomlaPack is starting a new database backup"); $extension = '.sql'; break; case 'full': JoomlapackLogger::WriteLog(_JP_LOG_INFO, "JoomlaPack is starting a new full site backup"); // Instanciate archiver, only if not in DB only mode $archiver =& $this->provisioning->getArchiverEngine(true); if($this->provisioning->getError()) { $this->setError($this->provisioning->getError()); return; } $extension = $this->provisioning->archiveExtension; break; case 'extradbonly': JoomlapackLogger::WriteLog(_JP_LOG_INFO, "JoomlaPack is starting a new extra databases only backup"); // Instanciate archiver, only if not in DB only mode $archiver =& $this->provisioning->getArchiverEngine(true); if($this->provisioning->getError()) { $this->setError($this->provisioning->getError()); return; } $extension = $this->provisioning->archiveExtension; break; } $relativeArchiveName = JoomlapackHelperUtils::getExpandedTarName($extension, false); $this->relativeArchiveName = $relativeArchiveName; $absoluteArchiveName = JoomlapackHelperUtils::getExpandedTarName($extension, true); // ==== Stats initialisation === $this->statmodel->setId(0); // Detect backup origin if($mainframe->isAdmin()) { $origin = 'backend'; } else { $origin = 'frontend'; } // Get profile $session =& JFactory::getSession(); $profile_id = $session->get('profile', null, 'joomlapack'); unset($session); // Create an initial stats entry jimport('joomla.utilities.date'); $jdate = new JDate(); switch($configuration->get('BackupType')) { case 'full': $backupType = 'full'; break; case 'dbonly': $backupType = 'dbonly'; break; case 'extradbonly': $backupType = 'extradbonly'; break; } JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Backup type is now set to '" . $backupType . "'"); $temp = array( 'description' => $description, 'comment' => $comment, 'backupstart' => $jdate->toMySQL(), 'status' => 'run', 'origin' => $origin, 'type' => $backupType, 'profile_id' => $profile_id, 'archivename' => $relativeArchiveName, 'absolute_path' => $absoluteArchiveName, 'multipart' => 0 ); // Save the entry $this->statmodel->save($temp); if($this->statmodel->getError()) { $this->setError($this->statmodel->getError()); return; } unset($temp); // Get the ID! $temp = $this->statmodel->getSavedTable(); $this->_statID = $temp->id; $this->_lockMultiPartUpdate = false; // Initialize the archive. if ($configuration->get('BackupType') != 'dbonly') { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Expanded archive file name: " . $absoluteArchiveName); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Seeding archive with installer"); $installerPackage = JPATH_COMPONENT_ADMINISTRATOR.DS.'assets'.DS."installers".DS.$configuration->get('InstallerPackage'); $archiver->initialize($installerPackage, $absoluteArchiveName); $archiver->setComment($comment); // Add the comment to the archive itself. if($archiver->getError()) { $this->setError($archiver->getError()); return; } } $this->_initialised = true; $this->_enforce_minexectime(false); } /** * Updates the multipart property of the statistic record. When this value is * greater than 1, it indicates that we have a multi-part (split) archive file. * @param int $multipart How many parts we have */ function updateMultipart( $multipart ) { if($this->_lockMultiPartUpdate) return; JoomlapackLogger::WriteLog(_JP_LOG_DEBUG,'Updating multipart status to '.$multipart); $db =& JFactory::getDBO(); $sql = 'UPDATE '.$db->nameQuote('#__jp_stats').' SET '.$db->nameQuote('multipart'). ' = '.$db->Quote($multipart).' WHERE '.$db->nameQuote('id').' = '. $db->Quote($this->_statID); $db->setQuery($sql); $db->query(); } /** * Steps the CUBE, performing yet another small chunk of backup work necessary * */ function tick() { $this->_enforce_minexectime(true); if(!$this->_initialised) { $this->setError(JText::_('CUBE_NOTINIT')); } elseif( (!$this->getError()) && (!$this->_isFinished)) { // Initialize operation counter $this->operationCounter = 0; // Advance step counter $this->stepCounter++; // Log step start number JoomlapackLogger::WriteLog(_JP_LOG_DEBUG,'====== Starting Step number '.$this->stepCounter.' ======'); $algorithmRunner =& JoomlapackCUBEAlgorunner::getInstance(); $algo = $algorithmRunner->selectAlgorithm($this->_activeDomain); switch($this->_activeDomain) { case 'init': case 'finale': $ret = 1; break; default: if(!is_object($this->_object)) { $algorithmRunner->setError('Current object is not an object on '.$this->_activeDomain); $ret = 2; } else { $ret = $algorithmRunner->runAlgorithm($algo, $this->_object); $this->_currentStep = $algorithmRunner->currentStep; $this->_currentSubstep = $algorithmRunner->currentSubstep; } break; } switch($ret) { case 0: // more work to do, return OK JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "CUBE :: More work required in domain '" . $this->_activeDomain); break; case 1: // Engine part finished JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "CUBE :: Domain '" . $this->_activeDomain . "' has finished"); $this->_getNextObject(); if ($this->_activeDomain == "finale") { // We have finished the whole process. JoomlapackCUBE::_finalise(); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "CUBE :: Just finished"); } break; case 2: // An error occured... JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "CUBE :: Error occured in domain '" . $this->_activeDomain); $this->setError($algorithmRunner->getError()); $this->reset(); //$this->_isFinished = true; break; } } // Log step end JoomlapackLogger::WriteLog(_JP_LOG_DEBUG,'====== Finished Step number '.$this->stepCounter.' ======'); $this->_enforce_minexectime(false); return $this->_makeCUBEArray(); } /** * Saves the CUBE object and all of its attached objects * */ function save() { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Saving CUBEObject instance" ); JoomlapackCUBETables::SerializeVar('CUBEObject', $this); } function getCUBEArray() { return $this->_makeCUBEArray(); } /** * Get the CUBE engine provisioning object * * @return JoomlapackCUBEProvisioning */ function &getProvisioning() { return $this->provisioning; } /** * Adds a warning to the stack and the log file * @param string $message The warning message to store * @access public */ function addWarning($message) { // Add to JoomlaPack log JoomlapackLogger::WriteLog(_JP_LOG_WARNING, $message); // Crop the LIFO buffer if there are more than 10 warnings if( count($this->_warnings) == 10 ) { array_pop($this->_warnings); } // Get actual date/time stamp jimport('joomla.utilities.date'); $date = new JDate(); // Create and add the warning object $warning = new stdClass; $warning->datetime = $date->toUnix(false); $warning->warning = $message; array_unshift($this->_warnings, $warning); } /** * Gets the whole list of warnings * @return array */ function getWarnings() { return $this->_warnings; } /* * ====================================================================== * Private methods * ====================================================================== */ function _finalise() { global $mainframe; $this->_enforce_minexectime(true); // The backup is over. Did we encounter any errors? if($this->getError()) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "CUBE - Can't finalise due to errors"); // Notify Super Administrators if it's a front-end backup if(!$mainframe->isAdmin()) { $this->_mailToSuperAdministrators($this->getError()); } // Oops! Have to reset() because of the error $this->reset(); } else { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "CUBE - Finalising backup started"); // Notify Super Administrators if it's a front-end backup if(!$mainframe->isAdmin()) { $this->_mailToSuperAdministrators(); } // Remove temp files JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Removing temporary files" ); JoomlapackCUBETempfiles::deleteTempFiles(); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Updating statistics" ); // We finished normally. Fetch the stats record $this->statmodel = null; $this->statmodel = new JoomlapackModelStatistics($this->_statID); $this->statmodel->setId($this->_statID); $statRecord =& $this->statmodel->getStatistic(); jimport('joomla.utilities.date'); $jdate = new JDate(); $statRecord->backupend = $jdate->toMySQL(); $statRecord->status = 'complete'; $this->statmodel->save($statRecord); // Apply quotas $errorReporting = @error_reporting(0); $quotaFiles = $this->statmodel->getOldBackupsToDelete(); if(count($quotaFiles) > 0) { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Applying quotas" ); jimport('joomla.filesystem.file'); foreach($quotaFiles as $file) { if(!@unlink($file)) { // FIX 2.0: Using JFile::delete raised warnings which messed up XMLRPC output. After all, we write backup files from PHP, using FTP should not be necessary to delete them! $this->addWarning("Failed to remove old backup file ".$file ); } } } @error_reporting($errorReporting); // Set internal variables and go to bed... er... I mean, return control to the user $this->_isFinished = true; $this->_activeDomain = 'finale'; JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "CUBE - Finalising backup ended"); } $this->_enforce_minexectime(false); } /** * Overrides JObject's setError() method to cater for logging * * @param string $message The error message */ function setError($message) { parent::setError($message); JoomlapackLogger::WriteLog(_JP_LOG_ERROR, $message); } /** * Creates the CUBE return array * @return array A CUBE return array with timestamp data * @access private */ function _makeCUBEArray(){ $ret['HasRun'] = (int)$this->_isFinished; $ret['Domain'] = $this->_activeDomain; $ret['Step'] = htmlentities( $this->_currentStep ); $ret['Substep'] = htmlentities( $this->_currentSubstep ); $ret['Error'] = htmlentities( $this->getError() ); // + JP 2.4 : Warnings propagation if(count($this->_warnings) > 0) { // We have warnings, construct an array of warnings... $ret['Warnings'] = array(); foreach($this->_warnings as $warn_obj) { $ret['Warnings'][] = $warn_obj->warning; } } else { // No warnings, return an empty table $ret['Warnings'] = array(); } $ret['Archive'] = $this->relativeArchiveName; return $ret; } /** * Creates the next engine object based on the current execution domain * @return integer 0 = success, 1 = all done, 2 = error * @access private */ function _getNextObject(){ // Handle errors if(is_object($this->_object)) { if($this->_object->getError()) { $this->setError($this->_object->getError()); return 2; } } // Kill existing object $this->_object = null; // Try to figure out what object to spawn next switch( $this->_activeDomain ) { case "init": JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Next domain --> Installer deployment"); $this->_object = new JoomlapackCUBEDomainInstaller(); if(!is_object($this->_object)) { $this->setError('Failed to instanciate JoomlapackCUBEDomainInstaller'); return 2; } $this->_activeDomain = "installer"; return 0; break; case "installer": JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Next domain --> Database backup"); $this->_object = new JoomlapackCUBEDomainDBBackup(); if(!is_object($this->_object)) { $this->setError('Failed to instanciate JoomlapackCUBEDomainDBBackup'); return 2; } $this->_activeDomain = "PackDB"; return 0; break; case "PackDB": JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Next domain --> Packing"); $this->_object = new JoomlapackCUBEDomainPack(); if(!is_object($this->_object)) { $this->setError('Failed to instanciate JoomlapackCUBEDomainPack'); return 2; } $this->_activeDomain = "Packing"; return 0; break; case "Packing": JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Next domain --> finale"); $this->_activeDomain = "finale"; $this->_object = null; return 1; break; case "finale": default: JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Next domain not applicable; already on 'finale'"); $this->_activeDomain = "finale"; $this->_object = null; $this->_isFinished = true; return 1; break; } } /** * Sends an email to Super Administrators for successful or failed front-end * backups. As of JP 2.2 you can override this and send an email to any arbitrary * email address, so as not to bother all Super Admins. * * @param string $error If null, indicates successful backup. Otherwise, it's the last error message. */ function _mailToSuperAdministrators($error = null) { // If the mail option is disabled, do not proceed $registry =& JoomlapackModelRegistry::getInstance(); if(!$registry->get('frontendemail')) return; if( trim($registry->get('arbitraryfeemail')) !== '' ) { // Send email to an arbitrary email address JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Preparing to send e-mail to specified email address"); // Fake a Super Administrators list to avoid code duplication $dummy = new stdClass(); $dummy->email = trim($registry->get('arbitraryfeemail')); $superAdmins[] = $dummy; } else { // Send email to all Super adminsitrators JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Preparing to send e-mail to Super Administrators"); // Get a list of administrators $db =& JFactory::getDBO(); $query = 'SELECT name, email FROM #__users'. ' WHERE usertype = \'Super Administrator\' '; $db->setQuery($query); $superAdmins =& $db->loadObjectList(); } // Proceed if there are users to mail to if( count($superAdmins) > 0 ) { // Get the mailer $mailer =& JFactory::getMailer(); // Add recipients (super administrators) $recipient = array(); foreach($superAdmins as $sa) { $recipient[] = $sa->email; JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Adding address ".$sa->email); } $mailer->addRecipient($recipient); // Set message if(is_null($error)) { // Success email $mailer->setSubject(JText::_('EMAIL_SUBJECT_OK')); $mailer->setBody(JText::_('EMAIL_BODY_OK')); } else { // Failure email $mailer->setSubject(JText::_('EMAIL_SUBJECT_ERROR')); $mailer->setBody(JText::_('EMAIL_BODY_ERROR').' '.$error); } JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "I will send an email with the following subject:"); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, $mailer->Subject); // Send message ob_start(); $mailer->Send(); ob_clean(); JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "E-mail sent"); } else { JoomlapackLogger::WriteLog(_JP_LOG_DEBUG, "Oops! No Super Administrators found?!"); } } /** * Enforces the minimum execution time per step, if such a thing is set up * @param bool $starting True when starting timing the script, false otherwise */ function _enforce_minexectime($starting) { static $start_time, $end_time; if($starting) { list($usec, $sec) = explode(" ", microtime()); $start_time = ((float)$usec + (float)$sec); } else { // Try to get a sane value for PHP's maximum_execution_time INI parameter if(@function_exists('ini_get')) { $php_max_exec = @ini_get("maximum_execution_time"); } else { $php_max_exec = 10; } if ( ($php_max_exec == "") || ($php_max_exec == 0) ) { $php_max_exec = 10; } // Decrease $php_max_exec time by 500 msec we need (approx.) to tear down // the application, as well as another 500msec added for rounding // error purposes. Also make sure this is never gonna be less than 0. $php_max_exec = max($php_max_exec * 1000 - 1000, 0); // Get the "minimum execution time per step" JoomlaPack configuration variable $configuration =& JoomlapackModelRegistry::getInstance(); $minexectime = $configuration->get('minexectime',0); if(!is_numeric($minexectime)) $minexectime = 0; // Make sure we are not over PHP's time limit! if($minexectime > $php_max_exec) $minexectime = $php_max_exec; // Get current timestamp and calculate how much time has passed list($usec, $sec) = explode(" ", microtime()); $end_time = ((float)$usec + (float)$sec); $elapsed_time = 1000 * ($end_time - $start_time); // Only run a sleep delay if we haven't reached the minexectime execution time if( ($minexectime > $elapsed_time) && ($elapsed_time > 0) ) { $sleep_msec = $minexectime - $elapsed_time; if(function_exists('usleep')) { JoomlapackLogger::WriteLog( _JP_LOG_DEBUG, "Sleeping for $sleep_msec msec, using usleep()" ); usleep(1000 * $sleep_msec); } elseif(function_exists('time_nanosleep')) { JoomlapackLogger::WriteLog( _JP_LOG_DEBUG, "Sleeping for $sleep_msec msec, using time_nanosleep()" ); $sleep_sec = round($sleep_msec / 1000); $sleep_nsec = 1000000 * ($sleep_msec - ($sleep_sec * 1000)); time_nanosleep($sleep_sec, $sleep_nsec); } elseif(function_exists('time_sleep_until')) { JoomlapackLogger::WriteLog( _JP_LOG_DEBUG, "Sleeping for $sleep_msec msec, using time_sleep_until()" ); $until_timestamp = time() + $sleep_msec / 1000; time_sleep_until($until_timestamp); } elseif(function_exists('sleep')) { $sleep_sec = ceil($sleep_msec/1000); JoomlapackLogger::WriteLog( _JP_LOG_DEBUG, "Sleeping for $sleep_sec seconds, using sleep()" ); sleep( $sleep_sec ); } } elseif( $elapsed_time > 0 ) { // No sleep required, even if user configured us to be able to do so. JoomlapackLogger::WriteLog( _JP_LOG_DEBUG, "No need to sleep; execution time: $elapsed_time msec; min. exec. time: $minexectime msec" ); } } } } function error2string() { if(function_exists('error_reporting')) { $value = error_reporting(); } else { return "Not applicable; host too restrictive"; } $level_names = array( E_ERROR => 'E_ERROR', E_WARNING => 'E_WARNING', E_PARSE => 'E_PARSE', E_NOTICE => 'E_NOTICE', E_CORE_ERROR => 'E_CORE_ERROR', E_CORE_WARNING => 'E_CORE_WARNING', E_COMPILE_ERROR => 'E_COMPILE_ERROR', E_COMPILE_WARNING => 'E_COMPILE_WARNING', E_USER_ERROR => 'E_USER_ERROR', E_USER_WARNING => 'E_USER_WARNING', E_USER_NOTICE => 'E_USER_NOTICE' ); if(defined('E_STRICT')) $level_names[E_STRICT]='E_STRICT'; $levels=array(); if(($value&E_ALL)==E_ALL) { $levels[]='E_ALL'; $value&=~E_ALL; } foreach($level_names as $level=>$name) if(($value&$level)==$level) $levels[]=$name; return implode(' | ',$levels); } /** * Timeout error handler */ function deadOnTimeOut() { if( connection_status() >= 2 ) { JoomlapackLogger::WriteLog(_JP_LOG_ERROR, JText::_('CUBE_TIMEOUT') ); } } register_shutdown_function("deadOnTimeOut");