/** * Resets the Kettenrad state, wipping out any pending backups and/or stale * temporary data. * @param array $config Configuration parameters for the reset operation */ public static function reset( $config = array() ) { $default_config = array( 'global' => true, // Reset all origins when true 'log' => false, // Log our actions ); $config = (object)array_merge($default_config, $config); // Pause logging if so desired if(!$config->log) AEUtilLogger::WriteLog(false,''); $tag = null; if(!$config->global) { // If we're not resetting globally, get a list of running backups per tag $tag = AEPlatform::get_backup_origin(); } // Cache the factory before proceeding $factory = AEFactory::serialize(); $runningList = AEPlatform::get_running_backups($tag); // Origins we have to clean $origins = array( AEPlatform::get_backup_origin() ); // 1. Detect failed backups if(is_array($runningList) && !empty($runningList)) { // The current timestamp $now = time(); // Mark running backups as failed foreach($runningList as $running) { if(empty($tag)) { // Check the timestamp of the log file to decide if it's stuck, // but only if a tag is not set $tstamp = @filemtime( AEUtilLogger::logName($running['origin']) ); if($tstamp !== false) { // We can only check the timestamp if it's returned. If not, we assume the backup is stale $difference = abs($now - $tstamp); // Backups less than 3 minutes old are not considered stale if($difference < 180) continue; } } $filenames = AEUtilStatistics::get_all_filenames($running); // Process if there are files to delete... if(!is_null($filenames)) { // Delete the failed backup's archive, if exists foreach($filenames as $failedArchive) { AEPlatform::unlink($failedArchive); } } // Mark the backup failed $running['status'] = 'fail'; $running['multipart'] = 0; $dummy = null; AEPlatform::set_or_update_statistics( $running['id'], $running, $dummy ); $origins[] = $running['origin']; } } if(!empty($origins)) { $origins = array_unique($origins); foreach($origins as $tag) { AECoreKettenrad::load($tag); // Remove temporary files AEUtilTempfiles::deleteTempFiles(); // Delete any stale temporary data AEUtilTempvars::reset($tag); } } // Reload the factory AEFactory::unserialize($factory); unset($factory); // Unpause logging if it was previously paused if(!$config->log) AEUtilLogger::WriteLog(true,''); }
/** * Implements the _run() abstract method */ protected function _run() { if( $this->getState() == 'postrun' ) { AEUtilLogger::WriteLog(_AE_LOG_DEBUG, __CLASS__." :: Already finished"); $this->setStep(''); $this->setSubstep(''); return; } else { $this->setState('running'); } // Load the version defines AEPlatform::load_version_defines(); $registry =& AEFactory::getConfiguration(); // Write log file's header AEUtilLogger::WriteLog(_AE_LOG_INFO, "--------------------------------------------------------------------------------"); AEUtilLogger::WriteLog(_AE_LOG_INFO, "Akeeba Backup ".AKEEBA_VERSION.' ('.AKEEBA_DATE.')'); AEUtilLogger::WriteLog(_AE_LOG_INFO, "Got backup?"); AEUtilLogger::WriteLog(_AE_LOG_INFO, "--------------------------------------------------------------------------------"); // PHP configuration variables are tried to be logged only for debug and info log levels if ($registry->get('akeeba.basic.log_level') >= _AE_LOG_INFO ) { AEUtilLogger::WriteLog(_AE_LOG_INFO, "--- System Information ---" ); if( function_exists('phpversion')) AEUtilLogger::WriteLog(_AE_LOG_INFO, "PHP Version :" . phpversion() ); if(function_exists('php_uname')) AEUtilLogger::WriteLog(_AE_LOG_INFO, "OS Version :" . php_uname('s') ); $db =& AEFactory::getDatabase(); AEUtilLogger::WriteLog(_AE_LOG_INFO, "DB Version :" . $db->getVersion() ); if (isset($_SERVER['SERVER_SOFTWARE'])) { $server = $_SERVER['SERVER_SOFTWARE']; } else if (($sf = getenv('SERVER_SOFTWARE'))) { $server = $sf; } else { $server = 'n/a'; } AEUtilLogger::WriteLog(_AE_LOG_INFO, "Web Server :" . $server ); if(function_exists('php_sapi_name')) AEUtilLogger::WriteLog(_AE_LOG_INFO, "PHP Interface :" . php_sapi_name() ); AEPlatform::getPlatformVersion( $platform, $version ); AEUtilLogger::WriteLog(_AE_LOG_INFO, "$platform version :" . $version ); if(isset($_SERVER['HTTP_USER_AGENT'])) AEUtilLogger::WriteLog(_AE_LOG_INFO, "User agent :" . phpversion() <= "4.2.1" ? getenv( "HTTP_USER_AGENT" ) : $_SERVER['HTTP_USER_AGENT'] ); AEUtilLogger::WriteLog(_AE_LOG_INFO, "Safe mode :" . ini_get("safe_mode") ); AEUtilLogger::WriteLog(_AE_LOG_INFO, "Display errors :" . ini_get("display_errors") ); AEUtilLogger::WriteLog(_AE_LOG_INFO, "Error reporting :" . self::error2string() ); AEUtilLogger::WriteLog(_AE_LOG_INFO, "Error display :" . self::errordisplay() ); AEUtilLogger::WriteLog(_AE_LOG_INFO, "Disabled functions :" . ini_get("disable_functions") ); AEUtilLogger::WriteLog(_AE_LOG_INFO, "open_basedir restr.:" . ini_get('open_basedir') ); AEUtilLogger::WriteLog(_AE_LOG_INFO, "Max. exec. time :" . ini_get("max_execution_time") ); AEUtilLogger::WriteLog(_AE_LOG_INFO, "Memory limit :" . ini_get("memory_limit") ); if(function_exists("memory_get_usage")) AEUtilLogger::WriteLog(_AE_LOG_INFO, "Current mem. usage :" . memory_get_usage() ); if(function_exists("gzcompress")) { AEUtilLogger::WriteLog(_AE_LOG_INFO, "GZIP Compression : available (good)" ); } else { AEUtilLogger::WriteLog(_AE_LOG_INFO, "GZIP Compression : n/a (no compression)" ); } AEPlatform::log_platform_special_directories(); AEUtilLogger::WriteLog(_AE_LOG_INFO, "Output directory :" . $registry->get('akeeba.basic.output_directory') ); AEUtilLogger::WriteLog(_AE_LOG_INFO, "Temporary directory:" . $registry->get('akeeba.basic.temporary_directory') ); AEUtilLogger::WriteLog(_AE_LOG_INFO, "--------------------------------------------------------------------------------"); } // Quirks reporting $quirks = AEUtilQuirks::get_quirks(true); if( !empty($quirks) ) { AEUtilLogger::WriteLog(_AE_LOG_INFO, "Akeeba Backup has detected the following potential problems:" ); foreach($quirks as $q) { AEUtilLogger::WriteLog(_AE_LOG_INFO, '- '.$q['code'].' '.$q['description'].' ('.$q['severity'].')' ); } AEUtilLogger::WriteLog(_AE_LOG_INFO, "You probably do not have to worry about them, but you should be aware of them." ); AEUtilLogger::WriteLog(_AE_LOG_INFO, "--------------------------------------------------------------------------------"); } // Report profile ID $profile_id = AEPlatform::get_active_profile(); AEUtilLogger::WriteLog(_AE_LOG_INFO, "Loaded profile #$profile_id"); // Get archive name AEUtilFilesystem::get_archive_name($relativeArchiveName, $absoluteArchiveName); // ==== Stats initialisation === $origin = AEPlatform::get_backup_origin(); // Get backup origin $profile_id = AEPlatform::get_active_profile(); // Get active profile $registry =& AEFactory::getConfiguration(); $backupType = $registry->get('akeeba.basic.backup_type'); AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Backup type is now set to '" . $backupType . "'"); // Substitute "variables" in the archive name $description = AEUtilFilesystem::replace_archive_name_variables($this->description); $comment = AEUtilFilesystem::replace_archive_name_variables($this->comment); if($registry->get('volatile.writer.store_on_server', true) ) { // Archive files are stored on our server $stat_relativeArchiveName = $relativeArchiveName; $stat_absoluteArchiveName = $absoluteArchiveName; } else { // Archive files are not stored on our server (FTP backup, cloud backup, sent by email, etc) $stat_relativeArchiveName = ''; $stat_absoluteArchiveName = ''; } $kettenrad =& AEFactory::getKettenrad(); $temp = array( 'description' => $description, 'comment' => $comment, 'backupstart' => AEPlatform::get_timestamp_mysql(), 'status' => 'run', 'origin' => $origin, 'type' => $backupType, 'profile_id' => $profile_id, 'archivename' => $stat_relativeArchiveName, 'absolute_path' => $stat_absoluteArchiveName, 'multipart' => 0, 'filesexist' => 1, 'tag' => $kettenrad->getTag() ); // Save the entry $statistics =& AEFactory::getStatistics(); $statistics->setStatistics($temp); if($statistics->getError()) { $this->setError($statistics->getError()); return; } $statistics->release_multipart_lock(); // Initialize the archive. if (AEUtilScripting::getScriptingParameter('core.createarchive',true)) { AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Expanded archive file name: " . $absoluteArchiveName); AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Initializing archiver engine"); $archiver =& AEFactory::getArchiverEngine(); $archiver->initialize($absoluteArchiveName); $archiver->setComment($comment); // Add the comment to the archive itself. $archiver->propagateToObject($this); if($this->getError()) { return; } } $this->setState('postrun'); }
public function runBackup() { $ret_array = array(); $ajaxTask = $this->getState('ajax'); switch($ajaxTask) { case 'start': // Description is passed through a strict filter which removes HTML $description = $this->getState('description'); // The comment is passed through the Safe HTML filter (note: use 2 to force no filtering) $comment = $this->getState('comment'); $jpskey = $this->getState('jpskey'); $tag = $this->getState('tag'); // Try resetting the engine AECoreKettenrad::reset(); // Remove any stale memory files left over from the previous step if(empty($tag)) $tag = AEPlatform::get_backup_origin(); AEUtilTempvars::reset($tag); $kettenrad =& AECoreKettenrad::load($tag); // Take care of System Restore Point setup if($tag == 'restorepoint') { // Fetch the extension's version information require_once JPATH_COMPONENT_ADMINISTRATOR.DS.'liveupdate'.DS.'classes'.DS.'xmlslurp.php'; $slurp = new LiveUpdateXMLSlurp(); $exttype = $this->getState('type'); switch($exttype) { case 'component': $extname = 'com_'; break; case 'module': $extname = 'mod_'; break; case 'plugin': $extname = 'plg_'; break; case 'template': $extname = 'tpl_'; break; } $extname .= $this->getState('name'); $info = $slurp->getInfo($extname, ''); // Get the configOverrides for this extension AEPlatform::$configOverrides = $this->getConfigOverridesForSRP($extname, $info); // Create an SRP descriptor $srpdescriptor = array( 'type' => $this->getState('type'), 'name' => $this->getState('name'), 'group' => $this->getState('group'), 'version' => $info['version'], 'date' => $info['date'] ); // Set the description and comment $description = "System Restore Point - ".JText::_($exttype).": $extname"; $comment = "---BEGIN SRP---\n".json_encode($srpdescriptor)."\n---END SRP---"; $jpskey = ''; // Set a custom finalization action queue AEPlatform::$configOverrides['volatile.core.finalization.action_handlers'] = array( new AEFinalizationSrpquotas() ); AEPlatform::$configOverrides['volatile.core.finalization.action_queue'] = array( 'remove_temp_files', 'update_statistics', 'update_filesizes', 'apply_srp_quotas' ); } $options = array( 'description' => $description, 'comment' => $comment, 'jpskey' => $jpskey ); $kettenrad->setup($options); $kettenrad->tick(); if( ($kettenrad->getState() != 'running') && ($tag == 'restorepoint') ) { $kettenrad->tick(); } $ret_array = $kettenrad->getStatusArray(); $kettenrad->resetWarnings(); // So as not to have duplicate warnings reports AECoreKettenrad::save($tag); break; case 'step': $tag = $this->getState('tag'); $kettenrad =& AECoreKettenrad::load($tag); $kettenrad->tick(); $ret_array = $kettenrad->getStatusArray(); $kettenrad->resetWarnings(); // So as not to have duplicate warnings reports AECoreKettenrad::save($tag); if($ret_array['HasRun'] == 1) { // Clean up AEFactory::nuke(); AEUtilTempvars::reset($tag); } break; default: break; } return $ret_array; }
/** * Sends an email to the administrators * @return bool */ private function mail_administrators() { $this->setStep('Processing emails to administrators'); $this->setSubstep(''); // Skip email for back-end backups if(AEPlatform::get_backup_origin() == 'backend' ) return true; $must_email = AEPlatform::get_platform_configuration_option('frontend_email_on_finish', 0) != 0; if(!$must_email) return true; AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Preparing to send e-mail to administrators"); $email = AEPlatform::get_platform_configuration_option('frontend_email_address', ''); $email = trim($email); if( !empty($email) ) { $emails = array($email); } else { $emails = AEPlatform::get_administrator_emails(); } if(!empty($emails)) { // Fetch user's preferences $subject = trim(AEPlatform::get_platform_configuration_option('frontend_email_subject','')); $body = trim(AEPlatform::get_platform_configuration_option('frontend_email_body','')); // Get the statistics $statistics =& AEFactory::getStatistics(); $stat = $statistics->getRecord(); $parts = AEUtilStatistics::get_all_filenames($stat, false); $profile_number = AEPlatform::get_active_profile(); $profile_name = AEPlatform::get_profile_name($profile_number); $parts = AEUtilStatistics::get_all_filenames($stat, false); $stat = (object)$stat; $num_parts = $stat->multipart; if($num_parts == 0) $num_parts = 1; // Non-split archives have a part count of 0 $parts_list = ''; if(!empty($parts)) foreach($parts as $file) { $parts_list .= "\t".basename($file)."\n"; } // Do we need a default subject? if(empty($subject)) { // Get the default subject $subject = AEPlatform::translate('EMAIL_SUBJECT_OK'); } else { // Post-process the subject $subject = AEUtilFilesystem::replace_archive_name_variables($subject); } // Do we need a default body? if(empty($body)) { $body = AEPlatform::translate('EMAIL_BODY_OK'); $info_source = AEPlatform::translate('EMAIL_BODY_INFO'); $body .= "\n\n" . sprintf($info_source, $profile_number, $num_parts) . "\n\n"; $body .= $parts_list; } else { // Post-process the body $body = AEUtilFilesystem::replace_archive_name_variables($body); $body = str_replace('[PROFILENUMBER]', $profile_number, $body); $body = str_replace('[PROFILENAME]', $profile_name, $body); $body = str_replace('[PARTCOUNT]', $num_parts, $body); $body = str_replace('[FILELIST]', $parts_list, $body); } // Sometimes $body contains literal \n instead of newlines $body = str_replace('\\n',"\n", $body); foreach($emails as $email) { AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Sending email to $email"); AEPlatform::send_email($email, $subject, $body); } } return true; }