/**
  * Delete the backup file of the stats record whose ID is set in the model
  * @return bool True on success
  */
 public function deleteFile()
 {
     $db = $this->getDBO();
     $id = $this->getState('id', 0);
     if (!is_numeric($id) || $id <= 0) {
         $this->setError(JText::_('STATS_ERROR_INVALIDID'));
         return false;
     }
     $stat = AEPlatform::getInstance()->get_statistics($id);
     $allFiles = AEUtilStatistics::get_all_filenames($stat, false);
     $aeconfig = AEFactory::getConfiguration();
     $status = true;
     JLoader::import('joomla.filesystem.file');
     foreach ($allFiles as $filename) {
         $new_status = JFile::delete($filename);
         $status = $status ? $new_status : false;
     }
     return $status;
 }
Beispiel #2
0
 /**
  * Downloads the backup file of a specific backup attempt,
  * if it's available
  *
  */
 public function download()
 {
     $model = $this->getThisModel();
     $id = $model->getId();
     $part = $this->input->get('part', -1, 'int');
     if ($this->input instanceof F0FInput) {
         $cid = $this->input->get('cid', array(), 'array');
     } else {
         $cid = $this->input->get('cid', array(), 'array');
     }
     if (empty($id)) {
         if (is_array($cid) && !empty($cid)) {
             $id = $cid[0];
         } else {
             $id = -1;
         }
     }
     if ($id <= 0) {
         $session = JFactory::getSession();
         $task = $session->get('buadmin.task', 'browse', 'akeeba');
         $this->setRedirect(JURI::base() . 'index.php?option=com_akeeba&view=buadmin&task=' . $task, JText::_('STATS_ERROR_INVALIDID'), 'error');
         parent::display();
         return true;
     }
     $stat = AEPlatform::getInstance()->get_statistics($id);
     $allFilenames = AEUtilStatistics::get_all_filenames($stat);
     // Check single part files
     if (count($allFilenames) == 1 && $part == -1) {
         $filename = array_shift($allFilenames);
     } elseif (count($allFilenames) > 0 && count($allFilenames) > $part && $part >= 0) {
         $filename = $allFilenames[$part];
     } else {
         $filename = null;
     }
     if (is_null($filename) || empty($filename) || !@file_exists($filename)) {
         $session = JFactory::getSession();
         $task = $session->get('buadmin.task', 'browse', 'akeeba');
         $this->setRedirect(JURI::base() . 'index.php?option=com_akeeba&view=buadmin&task=' . $task, JText::_('STATS_ERROR_INVALIDDOWNLOAD'), 'error');
         parent::display();
         return true;
     } else {
         // For a certain unmentionable browser -- Thank you, Nooku, for the tip
         if (function_exists('ini_get') && function_exists('ini_set')) {
             if (ini_get('zlib.output_compression')) {
                 ini_set('zlib.output_compression', 'Off');
             }
         }
         // Remove php's time limit -- Thank you, Nooku, for the tip
         if (function_exists('ini_get') && function_exists('set_time_limit')) {
             if (!ini_get('safe_mode')) {
                 @set_time_limit(0);
             }
         }
         $basename = @basename($filename);
         $filesize = @filesize($filename);
         $extension = strtolower(str_replace(".", "", strrchr($filename, ".")));
         while (@ob_end_clean()) {
         }
         @clearstatcache();
         // Send MIME headers
         header('MIME-Version: 1.0');
         header('Content-Disposition: attachment; filename="' . $basename . '"');
         header('Content-Transfer-Encoding: binary');
         header('Accept-Ranges: bytes');
         switch ($extension) {
             case 'zip':
                 // ZIP MIME type
                 header('Content-Type: application/zip');
                 break;
             default:
                 // Generic binary data MIME type
                 header('Content-Type: application/octet-stream');
                 break;
         }
         // Notify of filesize, if this info is available
         if ($filesize > 0) {
             header('Content-Length: ' . @filesize($filename));
         }
         // Disable caching
         header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
         header("Expires: 0");
         header('Pragma: no-cache');
         flush();
         if ($filesize > 0) {
             // If the filesize is reported, use 1M chunks for echoing the data to the browser
             $blocksize = 1048756;
             //1M chunks
             $handle = @fopen($filename, "r");
             // Now we need to loop through the file and echo out chunks of file data
             if ($handle !== false) {
                 while (!@feof($handle)) {
                     echo @fread($handle, $blocksize);
                     @ob_flush();
                     flush();
                 }
             }
             if ($handle !== false) {
                 @fclose($handle);
             }
         } else {
             // If the filesize is not reported, hope that readfile works
             @readfile($filename);
         }
         exit(0);
     }
 }
Beispiel #3
0
 /**
  * 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, 'log' => false, 'maxrun' => 0);
     $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::getInstance()->get_backup_origin();
     }
     // Cache the factory before proceeding
     $factory = AEFactory::serialize();
     $runningList = AEPlatform::getInstance()->get_running_backups($tag);
     // Origins we have to clean
     $origins = array(AEPlatform::getInstance()->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 < $config->maxrun) {
                         continue;
                     }
                 }
             }
             $filenames = AEUtilStatistics::get_all_filenames($running, false);
             // Process if there are files to delete...
             if (!is_null($filenames)) {
                 // Delete the failed backup's archive, if exists
                 foreach ($filenames as $failedArchive) {
                     AEPlatform::getInstance()->unlink($failedArchive);
                 }
             }
             // Mark the backup failed
             $running['status'] = 'fail';
             $running['multipart'] = 0;
             $dummy = null;
             AEPlatform::getInstance()->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, '');
     }
 }
 /**
  * Delete the backup file of the stats record whose ID is set in the model
  * @return bool True on success
  */
 public function deleteFile()
 {
     JLoader::import('joomla.filesystem.file');
     $id = $this->getState('id', 0);
     if (!is_numeric($id) || $id <= 0) {
         $this->setError(JText::_('STATS_ERROR_INVALIDID'));
         return false;
     }
     // Get the backup statistics record and the files to delete
     $stat = AEPlatform::getInstance()->get_statistics($id);
     $allFiles = AEUtilStatistics::get_all_filenames($stat, false);
     // Remove the custom log file if necessary
     $this->_deleteLogs($stat);
     // No files? Nothing to do.
     if (empty($allFiles)) {
         return true;
     }
     $status = true;
     foreach ($allFiles as $filename) {
         if (!@file_exists($filename)) {
             continue;
         }
         $new_status = @unlink($filename);
         if (!$new_status) {
             $new_status = JFile::delete($filename);
         }
         $status = $status ? $new_status : false;
     }
     return $status;
 }
Beispiel #5
0
 /**
  * Applies the size and count quotas
  *
  * @return bool
  */
 private function apply_quotas()
 {
     $this->setStep('Applying quotas');
     $this->setSubstep('');
     // If no quota settings are enabled, quit
     $registry = AEFactory::getConfiguration();
     $useDayQuotas = $registry->get('akeeba.quota.maxage.enable');
     $useCountQuotas = $registry->get('akeeba.quota.enable_count_quota');
     $useSizeQuotas = $registry->get('akeeba.quota.enable_size_quota');
     if (!($useDayQuotas || $useCountQuotas || $useSizeQuotas)) {
         $this->apply_obsolete_quotas();
         AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "No quotas were defined; old backup files will be kept intact");
         return true;
         // No quota limits were requested
     }
     // Try to find the files to be deleted due to quota settings
     $statistics = AEFactory::getStatistics();
     $latestBackupId = $statistics->getId();
     // Get quota values
     $countQuota = $registry->get('akeeba.quota.count_quota');
     $sizeQuota = $registry->get('akeeba.quota.size_quota');
     $daysQuota = $registry->get('akeeba.quota.maxage.maxdays');
     $preserveDay = $registry->get('akeeba.quota.maxage.keepday');
     // Get valid-looking backup ID's
     $validIDs = AEPlatform::getInstance()->get_valid_backup_records(true, array('NOT', 'restorepoint'));
     // Create a list of valid files
     $allFiles = array();
     if (count($validIDs)) {
         foreach ($validIDs as $id) {
             $stat = AEPlatform::getInstance()->get_statistics($id);
             try {
                 $backupstart = new DateTime($stat['backupstart']);
                 $backupTS = $backupstart->format('U');
                 $backupDay = $backupstart->format('d');
             } catch (Exception $e) {
                 $backupTS = 0;
                 $backupDay = 0;
             }
             // Multipart processing
             $filenames = AEUtilStatistics::get_all_filenames($stat, true);
             if (!is_null($filenames)) {
                 // Only process existing files
                 $filesize = 0;
                 foreach ($filenames as $filename) {
                     $filesize += @filesize($filename);
                 }
                 $allFiles[] = array('id' => $id, 'filenames' => $filenames, 'size' => $filesize, 'backupstart' => $backupTS, 'day' => $backupDay);
             }
         }
     }
     unset($validIDs);
     // If there are no files, exit early
     if (count($allFiles) == 0) {
         AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "There were no old backup files to apply quotas on");
         return true;
     }
     // Init arrays
     $killids = array();
     $ret = array();
     $leftover = array();
     // Do we need to apply maximum backup age quotas?
     if ($useDayQuotas) {
         $killDatetime = new DateTime();
         $killDatetime->modify('-' . $daysQuota . ($daysQuota == 1 ? ' day' : ' days'));
         $killTS = $killDatetime->format('U');
         foreach ($allFiles as $file) {
             if ($file['id'] == $latestBackupId) {
                 continue;
             }
             // Is this on a preserve day?
             if ($preserveDay > 0) {
                 if ($preserveDay == $file['day']) {
                     $leftover[] = $file;
                     continue;
                 }
             }
             // Otherwise, check the timestamp
             if ($file['backupstart'] < $killTS) {
                 $ret[] = $file['filenames'];
                 $killids[] = $file['id'];
             } else {
                 $leftover[] = $file;
             }
         }
     }
     // Do we need to apply count quotas?
     if ($useCountQuotas && is_numeric($countQuota) && !($countQuota <= 0) && !$useDayQuotas) {
         // Are there more files than the quota limit?
         if (!(count($allFiles) > $countQuota)) {
             // No, effectively skip the quota checking
             $leftover = $allFiles;
         } else {
             AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Processing count quotas");
             // Yes, aply the quota setting. Add to $ret all entries minus the last
             // $countQuota ones.
             $totalRecords = count($allFiles);
             $checkLimit = $totalRecords - $countQuota;
             // Only process if at least one file (current backup!) is to be left
             for ($count = 0; $count < $totalRecords; $count++) {
                 $def = array_pop($allFiles);
                 if ($def['id'] == $latestBackupId) {
                     array_push($allFiles, $def);
                     continue;
                 }
                 if (count($ret) < $checkLimit) {
                     if ($latestBackupId != $def['id']) {
                         $ret[] = $def['filenames'];
                         $killids[] = $def['id'];
                     }
                 } else {
                     $leftover[] = $def;
                 }
             }
             unset($allFiles);
         }
     } else {
         // No count quotas are applied
         $leftover = $allFiles;
     }
     // Do we need to apply size quotas?
     if ($useSizeQuotas && is_numeric($sizeQuota) && !($sizeQuota <= 0) && count($leftover) > 0 && !$useDayQuotas) {
         AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Processing size quotas");
         // OK, let's start counting bytes!
         $runningSize = 0;
         while (count($leftover) > 0) {
             // Each time, remove the last element of the backup array and calculate
             // running size. If it's over the limit, add the archive to the return array.
             $def = array_pop($leftover);
             $runningSize += $def['size'];
             if ($runningSize >= $sizeQuota) {
                 if ($latestBackupId == $def['id']) {
                     $runningSize -= $def['size'];
                 } else {
                     $ret[] = $def['filenames'];
                     $killids[] = $def['filenames'];
                 }
             }
         }
     }
     // Convert the $ret 2-dimensional array to single dimensional
     $quotaFiles = array();
     foreach ($ret as $temp) {
         foreach ($temp as $filename) {
             $quotaFiles[] = $filename;
         }
     }
     // Update the statistics record with the removed remote files
     if (!empty($killids)) {
         foreach ($killids as $id) {
             $data = array('filesexist' => '0');
             AEPlatform::getInstance()->set_or_update_statistics($id, $data, $this);
         }
     }
     // Apply quotas
     if (count($quotaFiles) > 0) {
         AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Applying quotas");
         JLoader::import('joomla.filesystem.file');
         foreach ($quotaFiles as $file) {
             if (!@AEPlatform::getInstance()->unlink($file)) {
                 $this->setWarning("Failed to remove old backup file " . $file);
             }
         }
     }
     $this->apply_obsolete_quotas();
     return true;
 }
Beispiel #6
0
	public function apply_srp_quotas($parent) {
		$parent->relayStep('Applying quotas');
		$parent->relaySubstep('');
		
		// If no quota settings are enabled, quit
		$registry =& AEFactory::getConfiguration();
		$srpQuotas = $registry->get('akeeba.quota.srp_size_quota');
		
		if($srpQuotas <= 0)
		{
			AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "No restore point quotas were defined; old restore point files will be kept intact" );
			return true; // No quota limits were requested
		}
		
		// Get valid-looking backup ID's
		$validIDs =& AEPlatform::get_valid_backup_records(true, array('restorepoint'));
		
		$statistics =& AEFactory::getStatistics();
		$latestBackupId = $statistics->getId();
		
		// Create a list of valid files
		$allFiles = array();
		if(count($validIDs))
		{
			foreach($validIDs as $id)
			{
				$stat = AEPlatform::get_statistics($id);
				// Multipart processing
				$filenames = AEUtilStatistics::get_all_filenames($stat, true);
				if(!is_null($filenames))
				{
					// Only process existing files
					$filesize = 0;
					foreach($filenames as $filename)
					{
						$filesize += @filesize($filename);
					}
					$allFiles[] = array('id' => $id, 'filenames' => $filenames, 'size' => $filesize);
				}
			}
		}
		unset($validIDs);
		
		// If there are no files, exit early
		if(count($allFiles) == 0)
		{
			AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "There were no old restore points to apply quotas on" );
			return true;
		}
		
		// Init arrays
		$killids = array();
		$ret = array();
		$leftover = array();
		
		// Do we need to apply size quotas?
		AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Processing restore point size quotas" );
		// OK, let's start counting bytes!
		$runningSize = 0;
		while(count($allFiles) > 0)
		{
			// Each time, remove the last element of the backup array and calculate
			// running size. If it's over the limit, add the archive to the return array.
			$def = array_pop($allFiles);
			$runningSize += $def['size'];
			if($runningSize >= $srpQuotas)
			{
				if($latestBackupId == $def['id'])
				{
					$runningSize -= $def['size'];
				}
				else
				{
					$ret[] = $def['filenames'];
					$killids[] = $def['filenames'];
				}
			}
		}
		
		// Convert the $ret 2-dimensional array to single dimensional
		$quotaFiles = array();
		foreach($ret as $temp)
		{
			foreach($temp as $filename)
			{
				$quotaFiles[] = $filename;
			}
		}
		
		// Update the statistics record with the removed remote files
		if(!empty($killids)) foreach($killids as $id) {
			$data = array('filesexist' => '0');
			AEPlatform::set_or_update_statistics($id, $data, $parent);
		}
		
		// Apply quotas
		if(count($quotaFiles) > 0)
		{
			AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Applying quotas" );
			jimport('joomla.filesystem.file');
			foreach($quotaFiles as $file)
			{
				if(!@AEPlatform::unlink($file))
				{
					$parent->setWarning("Failed to remove old system restore point file ".$file );
				}
			}
		}
		
		return true;
	}
Beispiel #7
0
 private function _apiDownloadDirect($config)
 {
     $defConfig = array('backup_id' => 0, 'part_id' => 1);
     $config = array_merge($defConfig, $config);
     extract($config);
     $backup_stats = AEPlatform::getInstance()->get_statistics($backup_id);
     if (empty($backup_stats)) {
         // Backup record doesn't exist
         $this->status = self::STATUS_NOT_FOUND;
         $this->encapsulation = self::ENCAPSULATION_RAW;
         @ob_end_clean();
         header('HTTP/1.1 500 Invalid backup record identifier');
         flush();
         JFactory::getApplication()->close();
     }
     $files = AEUtilStatistics::get_all_filenames($backup_stats);
     if (count($files) < $part_id || $part_id <= 0) {
         // Invalid part
         $this->status = self::STATUS_NOT_FOUND;
         $this->encapsulation = self::ENCAPSULATION_RAW;
         @ob_end_clean();
         header('HTTP/1.1 500 Invalid backup part');
         flush();
         JFactory::getApplication()->close();
     }
     $filename = $files[$part_id - 1];
     @clearstatcache();
     // For a certain unmentionable browser -- Thank you, Nooku, for the tip
     if (function_exists('ini_get') && function_exists('ini_set')) {
         if (ini_get('zlib.output_compression')) {
             ini_set('zlib.output_compression', 'Off');
         }
     }
     // Remove php's time limit -- Thank you, Nooku, for the tip
     if (function_exists('ini_get') && function_exists('set_time_limit')) {
         if (!ini_get('safe_mode')) {
             @set_time_limit(0);
         }
     }
     $basename = @basename($filename);
     $filesize = @filesize($filename);
     $extension = strtolower(str_replace(".", "", strrchr($filename, ".")));
     while (@ob_end_clean()) {
     }
     @clearstatcache();
     // Send MIME headers
     header('MIME-Version: 1.0');
     header('Content-Disposition: attachment; filename="' . $basename . '"');
     header('Content-Transfer-Encoding: binary');
     header('Accept-Ranges: bytes');
     switch ($extension) {
         case 'zip':
             // ZIP MIME type
             header('Content-Type: application/zip');
             break;
         default:
             // Generic binary data MIME type
             header('Content-Type: application/octet-stream');
             break;
     }
     // Notify of filesize, if this info is available
     if ($filesize > 0) {
         header('Content-Length: ' . @filesize($filename));
     }
     // Disable caching
     header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
     header("Expires: 0");
     header('Pragma: no-cache');
     flush();
     if ($filesize > 0) {
         // If the filesize is reported, use 1M chunks for echoing the data to the browser
         $blocksize = 1048756;
         //1M chunks
         $handle = @fopen($filename, "r");
         // Now we need to loop through the file and echo out chunks of file data
         if ($handle !== false) {
             while (!@feof($handle)) {
                 echo @fread($handle, $blocksize);
                 @ob_flush();
                 flush();
             }
         }
         if ($handle !== false) {
             @fclose($handle);
         }
     } else {
         // If the filesize is not reported, hope that readfile works
         @readfile($filename);
     }
     flush();
     JFactory::getApplication()->close();
 }