public function import($file) { $directory = $this->getState('directory', ''); $directory = AEUtilFilesystem::translateStockDirs($directory); // Find out how many parts there are $multipart = 0; $base = substr($file, 0, -4); $ext = substr($file, -3); $found = true; $total_size = @filesize($directory . '/' . $file); while ($found) { $multipart++; $newExtension = substr($ext, 0, 1) . sprintf('%02u', $multipart); $newFile = $directory . '/' . $base . '.' . $newExtension; $found = file_exists($newFile); if ($found) { $total_size += @filesize($newFile); } } $filetime = @filemtime($directory . '/' . $file); if (empty($filetime)) { $filetime = time(); } // Create a new backup record $record = array('description' => JText::_('DISCOVER_LABEL_IMPORTEDDESCRIPTION'), 'comment' => '', 'backupstart' => date('Y-m-d H:i:s', $filetime), 'backupend' => date('Y-m-d H:i:s', $filetime + 1), 'status' => 'complete', 'origin' => 'backend', 'type' => 'full', 'profile_id' => 1, 'archivename' => $file, 'absolute_path' => $directory . '/' . $file, 'multipart' => $multipart, 'tag' => 'backend', 'filesexist' => 1, 'remote_filename' => '', 'total_size' => $total_size); $id = null; $id = AEPlatform::getInstance()->set_or_update_statistics($id, $record, $this); }
public function __construct() { $this->object = 'dir'; $this->subtype = 'inclusion'; $this->method = 'direct'; // FIXME This filter doesn't work very well on many live hosts. Disabled for now. parent::__construct(); return; if (empty($this->filter_name)) { $this->filter_name = strtolower(basename(__FILE__, '.php')); } // Get the saved library path and compare it to the default $jlibdir = AEPlatform::getInstance()->get_platform_configuration_option('jlibrariesdir', ''); if (empty($jlibdir)) { if (defined('JPATH_LIBRARIES')) { $jlibdir = JPATH_LIBRARIES; } elseif (defined('JPATH_PLATFORM')) { $jlibdir = JPATH_PLATFORM; } else { $jlibdir = false; } } if ($jlibdir !== false) { $jlibdir = AEUtilFilesystem::TranslateWinPath($jlibdir); $defaultLibraries = AEUtilFilesystem::TranslateWinPath(JPATH_SITE . '/libraries'); if ($defaultLibraries != $jlibdir) { // The path differs, add it here $this->filter_data['JPATH_LIBRARIES'] = $jlibdir; } } else { $this->filter_data = array(); } parent::__construct(); }
/** * Handle the apply task which saves settings and shows the editor again * */ public function apply() { // CSRF prevention if (!JRequest::getVar(JUtility::getToken(), false, 'POST')) { JError::raiseError('403', JText::_(version_compare(JVERSION, '1.6.0', 'ge') ? 'JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN' : 'Request Forbidden')); } // Get the var array from the request $var = JRequest::getVar('var', array(), 'default', 'array'); // Make it into Akeeba Engine array format $data = array(); foreach ($var as $key => $value) { $data[$key] = $value; } // Forbid stupidly selecting the site's root as the output or temporary directory if (array_key_exists('akeeba.basic.output_directory', $data)) { $folder = $data['akeeba.basic.output_directory']; $folder = AEUtilFilesystem::translateStockDirs($folder, true, true); $check = AEUtilFilesystem::translateStockDirs('[SITEROOT]', true, true); if ($check == $folder) { JError::raiseWarning(503, JText::_('CONFIG_OUTDIR_ROOT')); $data['akeeba.basic.output_directory'] = '[DEFAULT_OUTPUT]'; } } // Merge it $config = AEFactory::getConfiguration(); $config->mergeArray($data, false, false); // Save configuration AEPlatform::getInstance()->save_configuration(); $this->setRedirect(JURI::base() . 'index.php?option=' . JRequest::getCmd('option') . '&view=config', JText::_('CONFIG_SAVE_OK')); }
/** * Unregister and delete a temporary file * @param $fileName The filename to unregister and delte * @param $removePrefix The prefix to remove */ static function unregisterAndDeleteTempFile( $fileName, $removePrefix = false ) { $configuration =& AEFactory::getConfiguration(); if($removePrefix) { $fileName = str_replace( AEUtilFilesystem::TranslateWinPath($configuration->get('akeeba.basic.temporary_directory')) , '', $fileName); if( (substr($fileName, 0, 1) == '/') || (substr($fileName, 0, 1) == '\\') ) { $fileName = substr($fileName, 1 ); } if( (substr($fileName, -1) == '/') || (substr($fileName, -1) == '\\') ) { $fileName = substr($fileName, 0, -1 ); } } // We don't unregister the tempfile here, because on some systems (Windows & // servers on FastCGI) the files wouldn't get deleted. $file = $configuration->get('akeeba.basic.temporary_directory').DS.$fileName; AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "-- Removing temporary file $fileName" ); $platform = strtoupper(PHP_OS); if( (substr($platform,0,6) == 'CYGWIN') || (substr($platform,0,3) == 'WIN') ) { // On Windows we have to chwon() the file first to make it owned by Nobody AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "-- Windows hack: chowning $fileName" ); @chown($file, 600); } return @self::nullifyAndDelete($file); }
protected function scanFolder($folder, &$position, $forFolders = true, $threshold_key = 'dir', $threshold_default = 50) { $registry = AEFactory::getConfiguration(); // Initialize variables $arr = array(); $false = false; if (!is_dir($folder) && !is_dir($folder . '/')) { return $false; } try { $di = new DirectoryIterator($folder); } catch (Exception $e) { $this->setWarning('Unreadable directory ' . $folder); return $false; } if (!$di->valid()) { $this->setWarning('Unreadable directory ' . $folder); return $false; } if (!empty($position)) { $di->seek($position); if ($di->key() != $position) { $position = null; return $arr; } } $counter = 0; $maxCounter = $registry->get("engine.scan.large.{$threshold_key}_threshold", $threshold_default); while ($di->valid()) { if ($di->isDot()) { $di->next(); continue; } if ($di->isDir() != $forFolders) { $di->next(); continue; } $ds = $folder == '' || $folder == '/' || @substr($folder, -1) == '/' || @substr($folder, -1) == DIRECTORY_SEPARATOR ? '' : DIRECTORY_SEPARATOR; $dir = $folder . $ds . $di->getFilename(); $data = _AKEEBA_IS_WINDOWS ? AEUtilFilesystem::TranslateWinPath($dir) : $dir; if ($data) { $counter++; $arr[] = $data; } if ($counter == $maxCounter) { break; } else { $di->next(); } } // Determine the new value for the position $di->next(); if ($di->valid()) { $position = $di->key() - 1; } else { $position = null; } return $arr; }
private function get_site_path() { // FIX 1.1.0 $mosConfig_absolute_path may contain trailing slashes or backslashes incompatible with exclusion filters // FIX 1.2.2 Some hosts yield an empty string on realpath(JPATH_SITE) // FIX 2.2 On Windows, realpath might fail // FIX 2.4: Make an assumption (wild guess...) if( (JPATH_BASE == '/administrator') || (JPATH_ROOT == '') ) { $this->setWarning("Your site's root is an empty string. I am trying a workaround."); $jpath_site_real = '/'; } else { // Fix 2.4: Make sure that $jpath_site_real contains something even if realpath fails $jpath_site_real = @realpath(trim(JPATH_SITE)); $jpath_site_real = ($jpath_site_real === false) ? trim(JPATH_SITE) : $jpath_site_real; $jpath_site_real = AEUtilFilesystem::TranslateWinPath($jpath_site_real); } if( $jpath_site_real == '' ) { // The JPATH_SITE is resolved to an empty string; attempt a workaround // Windows hosts if(DIRECTORY_SEPARATOR == '\\') { if( (trim(JPATH_SITE) != '') && (trim(JPATH_SITE) != '\\') && (trim(JPATH_SITE) != '/')) { $this->setWarning("The site's root couldn't be normalized on a Windows host. Attempting workaround (filters might not work)"); $jpath_site_real = JPATH_SITE; // Forcibly use the configured JPATH_SITE } else { $this->setWarning("The normalized path to your site's root seems to be an empty string; I will attempt a workaround (Windows host)"); $jpath_site_real = '/'; // Start scanning from filesystem root (workaround mode) } } // *NIX hosts else { $this->setWarning("The normalized path to your site's root seems to be an empty string; I will attempt a workaround (*NIX host)"); # Fix 2.1 Since JPATH_SITE is an empty string, shouldn't I begin scanning from the FS root, for crying out loud? What was I thinking putting JPATH_SITE there? $jpath_site_real = '/'; // Start scanning from filesystem root (workaround mode) } } // Fix 2.4.b1 : Add the trailing slash if( (substr($jpath_site_real,-1) != '/') && !empty($jpath_site_real) ) { $jpath_site_real .= '/'; } return $jpath_site_real; }
public function processPart($absolute_filename, $upload_as = null) { // Retrieve engine configuration data $config = AEFactory::getConfiguration(); $account = trim($config->get('engine.postproc.azure.account', '')); $key = trim($config->get('engine.postproc.azure.key', '')); $container = $config->get('engine.postproc.azure.container', 0); $directory = $config->get('volatile.postproc.directory', null); if (empty($directory)) { $directory = $config->get('engine.postproc.azure.directory', 0); } // Sanity checks if (empty($account)) { $this->setWarning('You have not set up your Windows Azure account name'); return false; } if (empty($key)) { $this->setWarning('You have not set up your Windows Azure key'); return false; } if (empty($container)) { $this->setWarning('You have not set up your Windows Azure container'); return false; } // Fix the directory name, if required if (!empty($directory)) { $directory = trim($directory); $directory = ltrim(AEUtilFilesystem::TranslateWinPath($directory), '/'); } else { $directory = ''; } // Parse tags $directory = AEUtilFilesystem::replace_archive_name_variables($directory); $config->set('volatile.postproc.directory', $directory); // Calculate relative remote filename $filename = basename($absolute_filename); if (!empty($directory) && $directory != '/') { $filename = $directory . '/' . $filename; } // Store the absolute remote path in the class property $this->remote_path = $filename; // Connect and send try { $blob = new AEUtilAzure(AEUtilAzureStorage::URL_CLOUD_BLOB, $account, $key); $policyNone = new AEUtilAzureNoRetryPolicy(); $blob->setRetryPolicy($policyNone); $blob->putBlob($container, $filename, $absolute_filename); } catch (Exception $e) { $this->setWarning($e->getMessage()); return false; } return true; }
private static function treatDirectory($directory) { $site_root = AEUtilFilesystem::TrimTrailingSlash(AEUtilFilesystem::TranslateWinPath(JPATH_ROOT)); $directory = AEUtilFilesystem::TrimTrailingSlash(AEUtilFilesystem::TranslateWinPath($directory)); // Trim site root from beginning of directory if (substr($directory, 0, strlen($site_root)) == $site_root) { $directory = substr($directory, strlen($site_root)); if (substr($directory, 0, 1) == '/') { $directory = substr($directory, 1); } } return $directory; }
/** * Unregister and delete a temporary file * @param $fileName The filename to unregister and delte * @param $removePrefix The prefix to remove */ static function unregisterAndDeleteTempFile($fileName, $removePrefix = false) { $configuration = AEFactory::getConfiguration(); if ($removePrefix) { $fileName = str_replace(AEUtilFilesystem::TranslateWinPath($configuration->get('akeeba.basic.output_directory')), '', $fileName); if (substr($fileName, 0, 1) == '/' || substr($fileName, 0, 1) == '\\') { $fileName = substr($fileName, 1); } if (substr($fileName, -1) == '/' || substr($fileName, -1) == '\\') { $fileName = substr($fileName, 0, -1); } } // Make sure this file is registered $configuration = AEFactory::getConfiguration(); $tempFiles = $configuration->get('volatile.tempfiles', false); if ($tempFiles === false) { $tempFiles = array(); } else { $tempFiles = @unserialize($tempFiles); } $found = false; if (!empty($tempFiles)) { $found = in_array($fileName, $tempFiles); } if (!$found) { return false; } $file = $configuration->get('akeeba.basic.output_directory') . '/' . $fileName; AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "-- Removing temporary file {$fileName}"); $platform = strtoupper(PHP_OS); if (substr($platform, 0, 6) == 'CYGWIN' || substr($platform, 0, 3) == 'WIN') { // On Windows we have to chwon() the file first to make it owned by Nobody AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "-- Windows hack: chowning {$fileName}"); @chown($file, 600); } $result = @self::nullifyAndDelete($file); // Make sure the file is removed before unregistering it if (!@file_exists($file)) { $aPos = array_search($fileName, $tempFiles); if ($aPos !== false) { unset($tempFiles[$aPos]); $configuration->set('volatile.tempfiles', serialize($tempFiles)); } } return $result; }
public function saveEngineConfig() { $data = $this->getState('engineconfig', array()); // Forbid stupidly selecting the site's root as the output or temporary directory if (array_key_exists('akeeba.basic.output_directory', $data)) { $folder = $data['akeeba.basic.output_directory']; $folder = AEUtilFilesystem::translateStockDirs($folder, true, true); $check = AEUtilFilesystem::translateStockDirs('[SITEROOT]', true, true); if ($check == $folder) { JError::raiseWarning(503, JText::_('CONFIG_OUTDIR_ROOT')); $data['akeeba.basic.output_directory'] = '[DEFAULT_OUTPUT]'; } } // Merge it $config = AEFactory::getConfiguration(); $config->mergeArray($data, false, false); // Save configuration AEPlatform::getInstance()->save_configuration(); }
private static function treatDirectory($directory) { // Get the site's root $configuration = AEFactory::getConfiguration(); if ($configuration->get('akeeba.platform.override_root', 0)) { $root = $configuration->get('akeeba.platform.newroot', '[SITEROOT]'); if (stristr($root, '[')) { $root = AEUtilFilesystem::translateStockDirs($root); } $site_root = AEUtilFilesystem::TrimTrailingSlash(AEUtilFilesystem::TranslateWinPath($root)); } else { $site_root = AEUtilFilesystem::TrimTrailingSlash(AEUtilFilesystem::TranslateWinPath(JPATH_ROOT)); } $directory = AEUtilFilesystem::TrimTrailingSlash(AEUtilFilesystem::TranslateWinPath($directory)); // Trim site root from beginning of directory if (substr($directory, 0, strlen($site_root)) == $site_root) { $directory = substr($directory, strlen($site_root)); if (substr($directory, 0, 1) == '/') { $directory = substr($directory, 1); } } return $directory; }
function display() { jimport('joomla.filesystem.folder'); jimport('joomla.filesystem.path'); // Get the folder to browse $folder = JRequest::getString('folder', ''); $processfolder = JRequest::getInt('processfolder', 0); if (empty($folder)) { $folder = ''; $folder_raw = ''; $isFolderThere = false; $isInRoot = false; $isOpenbasedirRestricted = false; } else { $stock_dirs = AEPlatform::getInstance()->get_stock_directories(); arsort($stock_dirs); if ($processfolder == 1) { foreach ($stock_dirs as $find => $replace) { $folder = str_replace($find, $replace, $folder); } } // Normalise name, but only if realpath() really, REALLY works... $old_folder = $folder; $folder = @realpath($folder); if ($folder === false) { $folder = $old_folder; } if (AEUtilFilesystem::folderExists($folder)) { $isFolderThere = true; } else { $isFolderThere = false; } JRequest::setVar('folder', $folder); // Check if it's a subdirectory of the site's root $isInRoot = strpos($folder, JPATH_SITE) === 0; // Check open_basedir restrictions $isOpenbasedirRestricted = AEUtilQuirks::checkOpenBasedirs($folder); // -- Get the meta form of the directory name, if applicable $folder_raw = $folder; foreach ($stock_dirs as $replace => $find) { $folder_raw = str_replace($find, $replace, $folder_raw); } } // Writable check and contents listing if it's in site root and not restricted if ($isFolderThere && !$isOpenbasedirRestricted) { // Get writability status $isWritable = is_writable($folder); // Get contained folders $subfolders = JFolder::folders($folder); } else { if ($isFolderThere && !$isOpenbasedirRestricted) { $isWritable = is_writable($folder); } else { $isWritable = false; } $subfolders = array(); } // Get parent directory $pathparts = explode(DIRECTORY_SEPARATOR, $folder); if (is_array($pathparts)) { $path = ''; foreach ($pathparts as $part) { $path .= empty($path) ? $part : DIRECTORY_SEPARATOR . $part; if (empty($part)) { if (DIRECTORY_SEPARATOR != '\\') { $path = DIRECTORY_SEPARATOR; } $part = DIRECTORY_SEPARATOR; } $crumb['label'] = $part; $crumb['folder'] = $path; $breadcrumbs[] = $crumb; } $junk = array_pop($pathparts); $parent = implode(DIRECTORY_SEPARATOR, $pathparts); } else { // Can't identify parent dir, use ourselves. $parent = $folder; $breadcrumbs = array(); } $this->assign('folder', $folder); $this->assign('folder_raw', $folder_raw); $this->assign('parent', $parent); $this->assign('exists', $isFolderThere); $this->assign('inRoot', $isInRoot); $this->assign('openbasedirRestricted', $isOpenbasedirRestricted); $this->assign('writable', $isWritable); $this->assign('subfolders', $subfolders); $this->assign('breadcrumbs', $breadcrumbs); parent::display(); }
/** * 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::getInstance()->get_backup_origin() == 'backend') { return true; } $must_email = AEPlatform::getInstance()->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::getInstance()->get_platform_configuration_option('frontend_email_address', ''); $email = trim($email); if (!empty($email)) { AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Using pre-defined list of emails"); $emails = explode(',', $email); } else { AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Fetching list of Super Administrator emails"); $emails = AEPlatform::getInstance()->get_administrator_emails(); } if (!empty($emails)) { AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Creating email subject and body"); // Fetch user's preferences $subject = trim(AEPlatform::getInstance()->get_platform_configuration_option('frontend_email_subject', '')); $body = trim(AEPlatform::getInstance()->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::getInstance()->get_active_profile(); $profile_name = AEPlatform::getInstance()->get_profile_name($profile_number); $parts = AEUtilStatistics::get_all_filenames($stat, false); $stat = (object) $stat; $num_parts = $stat->multipart; // Non-split archives have a part count of 0 if ($num_parts == 0) { $num_parts = 1; } $parts_list = ''; if (!empty($parts)) { foreach ($parts as $file) { $parts_list .= "\t" . basename($file) . "\n"; } } // Get the remote storage status $remote_status = ''; $post_proc_engine = AEFactory::getConfiguration()->get('akeeba.advanced.proc_engine'); if (!empty($post_proc_engine) && $post_proc_engine != 'none') { if (empty($stat->remote_filename)) { $remote_status = AEPlatform::getInstance()->translate('COM_AKEEBA_EMAIL_POSTPROCESSING_FAILED'); } else { $remote_status = AEPlatform::getInstance()->translate('COM_AKEEBA_EMAIL_POSTPROCESSING_SUCCESS'); } } // Do we need a default subject? if (empty($subject)) { // Get the default subject $subject = AEPlatform::getInstance()->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::getInstance()->translate('EMAIL_BODY_OK'); $info_source = AEPlatform::getInstance()->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); $body = str_replace('[REMOTESTATUS]', $remote_status, $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::getInstance()->send_email($email, $subject, $body); } } else { AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "No email recipients found! Skipping email."); } return true; }
/** * Calculates the absolute path to the log file. Instead of using the path coming from * Akeeba Backup config, we will always use Joomla Tmp dir * * @param string $tag The backup run's tag * * @return string The absolute path to the log file */ public static function logName($tag = null) { if (empty($tag)) { $fileName = 'akeeba.log'; } else { $fileName = "akeeba.{$tag}.log"; } // Get log's file name return AEUtilFilesystem::TranslateWinPath(JPATH_ROOT . '/tmp' . DIRECTORY_SEPARATOR . $fileName); }
/** * Q203 - MED - Default output directory in use * * @return bool */ private static function q203() { $stock_dirs = AEPlatform::getInstance()->get_stock_directories(); $registry =& AEFactory::getConfiguration(); $outdir = $registry->get('akeeba.basic.output_directory'); foreach ($stock_dirs as $macro => $replacement) { $outdir = str_replace($macro, $replacement, $outdir); } $default = $stock_dirs['[DEFAULT_OUTPUT]']; $outdir = AEUtilFilesystem::TranslateWinPath($outdir); $default = AEUtilFilesystem::TranslateWinPath($default); return $outdir == $default; }
/** * Returns a listing of contained directories and files, as well as their * exclusion status * @param string $root The root directory * @param string $node The subdirectory to scan * @return array */ private function &get_listing($root, $node) { // Initialize the absolute directory root $directory = substr($root, 0); // Replace stock directory tags, like [SITEROOT] $stock_dirs = AEPlatform::getInstance()->get_stock_directories(); if (!empty($stock_dirs)) { foreach ($stock_dirs as $key => $replacement) { $directory = str_replace($key, $replacement, $directory); } } $directory = AEUtilFilesystem::TranslateWinPath($directory); // Clean and add the node $node = AEUtilFilesystem::TranslateWinPath($node); if ($node == '/') { $node = ''; } // Just a dir. sep. is treated as no dir at all // Trim leading and trailing slashes $node = trim($node, '/'); // Add node to directory if (!empty($node)) { $directory .= '/' . $node; } // Add any required trailing slash to the node to be used below if (!empty($node)) { $node .= '/'; } // Get a filters instance $filters = AEFactory::getFilters(); // Detect PHP 5.2.5or earlier, with broken json_decode implementation $phpversion = PHP_VERSION; $vparts = explode('.', $phpversion); if ($vparts[0] == 5 && $vparts[1] == 2 && $vparts[2] <= 5 || $vparts[0] == 5 && $vparts[1] == 1) { define('AKEEBA_SAFE_JSON', false); require_once JPATH_COMPONENT_ADMINISTRATOR . '/helpers/jsonlib.php'; } else { $test = '-test-'; $tj = json_encode($test); $test = json_decode($test); if ($test == '-test-') { define('AKEEBA_SAFE_JSON', true); } else { define('AKEEBA_SAFE_JSON', false); require_once JPATH_COMPONENT_ADMINISTRATOR . '/helpers/jsonlib.php'; } } // Get a listing of folders and process it $folders = AEUtilScanner::getFolders($directory); asort($folders); $folders_out = array(); if (!empty($folders)) { foreach ($folders as $folder) { $folder = AEUtilFilesystem::TranslateWinPath($folder); // Filter out files whose names result to an empty JSON representation if (AKEEBA_SAFE_JSON) { $json_folder = json_encode($folder); $folder = json_decode($json_folder); } else { $jsonobj = new Akeeba_Services_JSON(0); $json_folder = $jsonobj->encode($folder); $folder = $jsonobj->decode($json_folder); } if (empty($folder)) { continue; } $test = $node . $folder; $status = array(); // Check dir/all filter (exclude) $result = $filters->isFilteredExtended($test, $root, 'dir', 'all', $byFilter); $status['directories'] = !$result ? 0 : ($byFilter == 'directories' ? 1 : 2); // Check dir/content filter (skip_files) $result = $filters->isFilteredExtended($test, $root, 'dir', 'content', $byFilter); $status['skipfiles'] = !$result ? 0 : ($byFilter == 'skipfiles' ? 1 : 2); // Check dir/children filter (skip_dirs) $result = $filters->isFilteredExtended($test, $root, 'dir', 'children', $byFilter); $status['skipdirs'] = !$result ? 0 : ($byFilter == 'skipdirs' ? 1 : 2); // Add to output array $folders_out[$folder] = $status; } } unset($folders); $folders = $folders_out; // Get a listing of files and process it $files = AEUtilScanner::getFiles($directory); asort($files); $files_out = array(); if (!empty($files)) { foreach ($files as $file) { // Filter out files whose names result to an empty JSON representation if (AKEEBA_SAFE_JSON) { $json_file = json_encode($file); $file = json_decode($json_file); } else { $jsonobj = new Akeeba_Services_JSON(0); $json_file = $jsonobj->encode($file); $file = $jsonobj->decode($json_file); } if (empty($file)) { continue; } $test = $node . $file; $status = array(); // Check file/all filter (exclude) $result = $filters->isFilteredExtended($test, $root, 'file', 'all', $byFilter); $status['files'] = !$result ? 0 : ($byFilter == 'files' ? 1 : 2); $status['size'] = @filesize($directory . '/' . $file); // Add to output array $files_out[$file] = $status; } } unset($files); $files = $files_out; // Return a compiled array $retarray = array('folders' => $folders, 'files' => $files); return $retarray; /* Return array format * [array] : * 'folders' [array] : * (folder_name) => [array]: * 'directories' => 0|1|2 * 'skipfiles' => 0|1|2 * 'skipdirs' => 0|1|2 * 'files' [array] : * (file_name) => [array]: * 'files' => 0|1|2 * * Legend: * 0 -> Not excluded * 1 -> Excluded by the direct filter * 2 -> Excluded by another filter (regex, api, an unknown plugin filter...) */ }
private function _getEngineSettings() { // Retrieve engine configuration data $config = AEFactory::getConfiguration(); $email = trim($config->get('engine.postproc.sugarsync.email', '')); $password = trim($config->get('engine.postproc.sugarsync.password', '')); $directory = $config->get('volatile.postproc.directory', null); if (empty($directory)) { $directory = $config->get('engine.postproc.sugarsync.directory', 0); } // Sanity checks if (empty($email)) { $this->setWarning('You have not set up your SugarSync email address'); return false; } if (empty($password)) { $this->setWarning('You have not set up your SugarSync password'); return false; } // Fix the directory name, if required if (!empty($directory)) { $directory = trim($directory); $directory = ltrim(AEUtilFilesystem::TranslateWinPath($directory), '/'); } else { $directory = ''; } // Parse tags $directory = AEUtilFilesystem::replace_archive_name_variables($directory); $config->set('volatile.postproc.directory', $directory); return array('email' => $email, 'password' => $password, 'directory' => $directory); }
/** * Update the cached live site's URL for the front-end backup feature (altbackup.php) * and the detected Joomla! libraries path */ public function updateMagicParameters() { $component =& JComponentHelper::getComponent('com_akeeba'); if (is_object($component->params) && $component->params instanceof JRegistry) { $params = $component->params; } else { $params = new JParameter($component->params); } $params->set('siteurl', str_replace('/administrator', '', JURI::base())); if (defined('JPATH_LIBRARIES')) { $params->set('jlibrariesdir', AEUtilFilesystem::TranslateWinPath(JPATH_LIBRARIES)); } elseif (defined("JPATH_PLATFORM")) { $params->set('jlibrariesdir', AEUtilFilesystem::TranslateWinPath(JPATH_PLATFORM)); } if (AKEEBA_JVERSION == '16') { // Joomla! 1.6 $joomla16 = true; $params->set('jversion', '1.6'); } else { // Joomla! 1.5 $joomla16 = false; $params->set('jversion', '1.5'); } $db =& JFactory::getDBO(); $data = $params->toString(); if ($joomla16) { // Joomla! 1.6 $sql = 'UPDATE `#__extensions` SET `params` = ' . $db->Quote($data) . ' WHERE ' . "`element` = 'com_akeeba' AND `type` = 'component'"; } else { // Joomla! 1.5 $sql = 'UPDATE `#__components` SET `params` = ' . $db->Quote($data) . ' WHERE ' . "`option` = 'com_akeeba' AND `parent` = 0 AND `menuid` = 0"; } $db->setQuery($sql); $db->query(); }
/** * Removes the $p_remove_dir from $p_filename, while prepending it with $p_add_dir. * Largely based on code from the pclZip library. * * @param string $p_filename The absolute file name to treat * @param string $p_remove_dir The path to remove * @param string $p_add_dir The path to prefix the treated file name with * * @return string The treated file name */ private final function _addRemovePaths($p_filename, $p_remove_dir, $p_add_dir) { $p_filename = AEUtilFilesystem::TranslateWinPath($p_filename); $p_remove_dir = $p_remove_dir == '' ? '' : AEUtilFilesystem::TranslateWinPath($p_remove_dir); //should fix corrupt backups, fix by nicholas if (!($p_remove_dir == "")) { if (substr($p_remove_dir, -1) != '/') { $p_remove_dir .= "/"; } if (substr($p_filename, 0, 2) == "./" || substr($p_remove_dir, 0, 2) == "./") { if (substr($p_filename, 0, 2) == "./" && substr($p_remove_dir, 0, 2) != "./") { $p_remove_dir = "./" . $p_remove_dir; } if (substr($p_filename, 0, 2) != "./" && substr($p_remove_dir, 0, 2) == "./") { $p_remove_dir = substr($p_remove_dir, 2); } } $v_compare = $this->_PathInclusion($p_remove_dir, $p_filename); if ($v_compare > 0) { if ($v_compare == 2) { $v_stored_filename = ""; } else { $v_stored_filename = substr($p_filename, function_exists('mb_strlen') ? mb_strlen($p_remove_dir, '8bit') : strlen($p_remove_dir)); } } } else { $v_stored_filename = $p_filename; } if (!($p_add_dir == "")) { if (substr($p_add_dir, -1) == "/") { $v_stored_filename = $p_add_dir . $v_stored_filename; } else { $v_stored_filename = $p_add_dir . "/" . $v_stored_filename; } } return $v_stored_filename; }
protected function _getSettings() { // Retrieve engine configuration data $config = AEFactory::getConfiguration(); $token = trim($config->get('engine.postproc.dropbox.token', '')); $token_secret = trim($config->get('engine.postproc.dropbox.token_secret', '')); $token_uid = trim($config->get('engine.postproc.dropbox.uid', '')); $this->chunked = $config->get('engine.postproc.dropbox.chunk_upoad', true); $this->chunk_size = $config->get('engine.postproc.dropbox.chunk_upoad_size', 4); $this->directory = $config->get('volatile.postproc.directory', null); if (empty($this->directory)) { $this->directory = $config->get('engine.postproc.dropbox.directory', ''); } // Sanity checks if (empty($token) || empty($token_secret) || empty($token_uid)) { $this->setError('You have not linked Akeeba Backup with your DropBox account'); return false; } // Fix the directory name, if required if (!empty($this->directory)) { $this->directory = trim($this->directory); $this->directory = ltrim(AEUtilFilesystem::TranslateWinPath($this->directory), '/'); } else { $this->directory = ''; } // Parse tags $this->directory = AEUtilFilesystem::replace_archive_name_variables($this->directory); $config->set('volatile.postproc.directory', $this->directory); $token = (object) array('oauth_token_secret' => $token_secret, 'oauth_token' => $token, 'uid' => $token_uid); $keys = $this->_getKeys(); $this->dropbox = new AEUtilDropbox(); $this->dropbox->setAppKeys($keys); $this->dropbox->setToken($token); return true; }
public function processPart($absolute_filename) { // Retrieve engine configuration data $config = AEFactory::getConfiguration(); $accesskey = trim($config->get('engine.postproc.s3.accesskey', '')); $secret = trim($config->get('engine.postproc.s3.secretkey', '')); $usessl = $config->get('engine.postproc.s3.usessl', 0) == 0 ? false : true; $bucket = $config->get('engine.postproc.s3.bucket', ''); $legacy = $config->get('engine.postproc.s3.legacy', 0); $directory = $config->get('volatile.postproc.directory', null); $lowercase = $config->get('engine.postproc.s3.lowercase', 1); $rrs = $config->get('engine.postproc.s3.rrs', 1); $endpoint = $config->get('engine.postproc.s3.customendpoint', ''); if (empty($directory)) { $directory = $config->get('engine.postproc.s3.directory', 0); } if (!empty($directory)) { $directory = str_replace('\\', '/', $directory); $directory = rtrim($directory, '/'); } $endpoint = trim($endpoint); if (!empty($endpoint)) { $protoPos = strpos($endpoint, ':\\'); if ($protoPos !== false) { $endpoint = substr($endpoint, $protoPos + 3); } $slashPos = strpos($endpoint, '/'); if ($slashPos !== false) { $endpoint = substr($endpoint, $slashPos + 1); } } // Sanity checks if (empty($accesskey)) { $this->setError('You have not set up your Amazon S3 Access Key'); return false; } if (empty($secret)) { $this->setError('You have not set up your Amazon S3 Secret Key'); return false; } if (empty($bucket)) { $this->setError('You have not set up your Amazon S3 Bucket'); return false; } else { // Remove any slashes from the bucket $bucket = str_replace('/', '', $bucket); if ($lowercase) { $bucket = strtolower($bucket); } } // Create an S3 instance with the required credentials $s3 = AEUtilAmazons3::getInstance($accesskey, $secret, $usessl); if (!empty($endpoint)) { $s3->defaultHost = $endpoint; } // Do not use multipart uploads when in an immediate post-processing step, // i.e. we are uploading a part right after its creation $immediateEnabled = $config->get('engine.postproc.common.after_part', 0); if ($immediateEnabled) { $noMultipart = true; } else { $noMultipart = false; } // Disable multipart uploads if the user requested it if ($legacy) { $noMultipart = true; } // Are we already processing a multipart upload? if (!empty($this->cache)) { // Continue processing an existing file and return $filename = $this->cache->filename; $absolute_filename = $this->cache->absolute_filename; $partNumber = $this->cache->partnumber; $uploadID = $this->cache->uploadid; $etags = $this->cache->etags; $partNumber++; AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "S3 -- Uploading part {$partNumber} of {$uploadID}"); // DEBUG /** $flatetags = implode(', ',$etags); AEUtilLogger::WriteLog(_AE_LOG_DEBUG,"S3 -- Absolute/relative filenames: $absolute_filename ### $filename"); AEUtilLogger::WriteLog(_AE_LOG_DEBUG,"S3 -- Etags: ".$flatetags); AEUtilLogger::WriteLog(_AE_LOG_DEBUG,"S3 -- Serialized cache: ".serialize($this->cache)); /**/ $fileInfo = AEUtilAmazons3::inputFile($absolute_filename, false); $fileInfo['UploadID'] = $uploadID; $fileInfo['etags'] = $etags; $fileInfo['PartNumber'] = $partNumber; $input = $fileInfo; // So that it doesn't get overwritten $etag = AEUtilAmazons3::uploadMultipart($input, $bucket, $filename); if ($etag === 0) { // Done uploading, finalize $this->cache = null; AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "S3 -- Finalizing multipart upload of " . basename($absolute_filename) . " (part #{$partNumber})"); $result = AEUtilAmazonS3::finalizeMultipart($fileInfo, $bucket, $filename); $this->propagateFromObject($s3); if ($result === false) { // Finalization failed return false; } else { // Finalization successful return true; } } elseif ($etag === false) { // Upload failed $this->propagateFromObject($s3); return false; } else { // Successfully uploaded part $this->propagateFromObject($s3); $fileInfo['etags'][] = $etag; // Update stored values $this->cache->partnumber = $partNumber; $this->cache->etags = $fileInfo['etags']; $this->cache->uploadid = $fileInfo['UploadID']; // Return -1 so that we get called again return -1; } } // If we are here, we'll have to start uploading the file. Let's prepare ourselves for that. // Fix the directory name, if required if (!empty($directory)) { $directory = trim($directory); $directory = ltrim(AEUtilFilesystem::TranslateWinPath($directory), '/'); } else { $directory = ''; } // Parse tags $directory = AEUtilFilesystem::replace_archive_name_variables($directory); $config->set('volatile.postproc.directory', $directory); // Calculate relative remote filename $filename = basename($absolute_filename); if (!empty($directory) && $directory != '/') { $filename = $directory . '/' . $filename; } // Store the absolute remote path in the class property $this->remote_path = $filename; // Do we have to upload in one go or do a multipart upload instead? $filesize = @filesize($absolute_filename); if ($filesize > 5242880 && !$noMultipart) { AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "S3 -- Starting multipart upload of " . basename($absolute_filename)); // Start multipart processing for files over 5Mb $fileInfo = AEUtilAmazons3::inputFile($absolute_filename, false); $input = $fileInfo; // Required to avoid the original array being tampered with $uploadID = AEUtilAmazonS3::startMultipart($input, $bucket, $filename, AEUtilAmazons3::ACL_BUCKET_OWNER_FULL_CONTROL, array(), array('x-amz-storage-class' => $rrs ? 'REDUCED_REDUNDANCY' : 'STANDARD')); // Necessary warnings propagation, no matter the outcome $this->propagateFromObject($s3); if ($uploadID === false) { // We couldn't start the upload. Bail out at once! return false; } else { // Save the information we need for multipart uploading $fileInfo['UploadID'] = $uploadID; $fileInfo['etags'] = array(); $cache = array('absolute_filename' => $absolute_filename, 'filename' => $filename, 'partnumber' => 0, 'uploadid' => $uploadID, 'etags' => array()); $this->cache = (object) $cache; // Return -1 so that we get called again, even on the same step return -1; } } else { AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "S3 -- Legacy (single part) upload of " . basename($absolute_filename)); // Legacy single part uploads $result = $s3->putObject(AEUtilAmazons3::inputFile($absolute_filename, false), $bucket, $filename, AEUtilAmazons3::ACL_BUCKET_OWNER_FULL_CONTROL, array(), array('x-amz-storage-class' => $rrs ? 'REDUCED_REDUNDANCY' : 'STANDARD')); // Return the result $this->propagateFromObject($s3); return $result; } }
/** * Scans a directory for files and directories, updating the directory_list and file_list * private fields * * @return bool True if more work has to be done, false if the dirextory stack is empty */ private function scan_directory() { // Are we supposed to scan for more files? if ($this->done_scanning) { return true; } // Get the next directory to scan, if the folders and files of the last directory // have been scanned. if ($this->done_subdir_scanning && $this->done_file_scanning) { if (count($this->directory_list) == 0) { // No directories left to scan return false; } else { // Get and remove the last entry from the $directory_list array $this->current_directory = array_pop($this->directory_list); $this->setStep($this->current_directory); $this->done_subdir_scanning = false; $this->done_file_scanning = false; $this->processed_files_counter = 0; } } $engine = AEFactory::getScanEngine(); // Break directory components if (AEFactory::getConfiguration()->get('akeeba.platform.override_root', 0)) { $siteroot = AEFactory::getConfiguration()->get('akeeba.platform.newroot', '[SITEROOT]'); } else { $siteroot = '[SITEROOT]'; } $root = $this->root; if ($this->root == $siteroot) { $translated_root = AEUtilFilesystem::translateStockDirs($siteroot, true); } else { $translated_root = $this->remove_path_prefix; } $dir = AEUtilFilesystem::TrimTrailingSlash($this->current_directory); if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { $translated_root = AEUtilFilesystem::TranslateWinPath($translated_root); $dir = AEUtilFilesystem::TranslateWinPath($dir); } if (substr($dir, 0, strlen($translated_root)) == $translated_root) { $dir = substr($dir, strlen($translated_root)); } elseif (in_array(substr($translated_root, -1), array('/', '\\'))) { $new_translated_root = rtrim($translated_root, '/\\'); if (substr($dir, 0, strlen($new_translated_root)) == $new_translated_root) { $dir = substr($dir, strlen($new_translated_root)); } } if (substr($dir, 0, 1) == '/') { $dir = substr($dir, 1); } // get a filters instance $filters = AEFactory::getFilters(); // Scan subdirectories, if they have not yet been scanned. if (!$this->done_subdir_scanning) { // Apply DEF (directory exclusion filters) // Note: the !empty($dir) prevents the site's root from being filtered out if ($filters->isFiltered($dir, $root, 'dir', 'all') && !empty($dir)) { AEUtilLogger::WriteLog(_AE_LOG_INFO, "Skipping directory " . $this->current_directory); $this->done_subdir_scanning = true; $this->done_file_scanning = true; return true; } // Apply Skip Contained Directories Filters if ($filters->isFiltered($dir, $root, 'dir', 'children')) { AEUtilLogger::WriteLog(_AE_LOG_INFO, "Skipping subdirectories of directory " . $this->current_directory); $this->done_subdir_scanning = true; } else { AEUtilLogger::WriteLog(_AE_LOG_INFO, "Scanning directories of " . $this->current_directory); // Get subdirectories $subdirs = $engine->getFolders($this->current_directory); // Error propagation $this->propagateFromObject($engine); // If the list contains "too many" items, please break this step! $registry = AEFactory::getConfiguration(); if ($registry->get('volatile.breakflag', false)) { // Log the step break decision, for debugging reasons AEUtilLogger::WriteLog(_AE_LOG_INFO, "Large directory " . $this->current_directory . " while scanning for subdirectories; I will resume scanning in next step."); // Return immediately, marking that we are not done yet! return true; } // Error control if ($this->getError()) { return false; } if (!empty($subdirs) && is_array($subdirs)) { $registry = AEFactory::getConfiguration(); $dereferencesymlinks = $registry->get('engine.archiver.common.dereference_symlinks'); if ($dereferencesymlinks) { // Treat symlinks to directories as actual directories foreach ($subdirs as $subdir) { $this->directory_list[] = $subdir; $this->progressAddFolder(); } } else { // Treat symlinks to directories as simple symlink files (ONLY WORKS WITH CERTAIN ARCHIVERS!) foreach ($subdirs as $subdir) { if (is_link($subdir)) { // Symlink detected; apply file filters to it if (empty($dir)) { $dirSlash = $dir; } else { $dirSlash = $dir . '/'; } $check = $dir . basename($subdir); if (_AKEEBA_IS_WINDOWS) { $check = AEUtilFilesystem::TranslateWinPath($check); } // Do I need this? $dir contains a path relative to the root anyway... $check = ltrim(str_replace($translated_root, '', $check), '/'); if ($filters->isFiltered($check, $root, 'file', 'all')) { AEUtilLogger::WriteLog(_AE_LOG_INFO, "Skipping directory symlink " . $check); } else { AEUtilLogger::WriteLog(_AE_LOG_DEBUG, 'Adding symlink to folder as file: ' . $check); $this->file_list[] = $subdir; $this->progressAddFile(); } } else { $this->directory_list[] = $subdir; $this->progressAddFolder(); } } } } } $this->done_subdir_scanning = true; return true; // Break operation } // If we are here, we have not yet scanned the directory for files, so there // is no need to test for done_file_scanning (saves a tiny amount of CPU time) // Apply Skipfiles if ($filters->isFiltered($dir, $root, 'dir', 'content')) { AEUtilLogger::WriteLog(_AE_LOG_INFO, "Skipping files of directory " . $this->current_directory); // Try to find and include .htaccess and index.htm(l) files // # Fix 2.4: Do not add DIRECTORY_SEPARATOR if we are on the site's root and it's an empty string $ds = $this->current_directory == '' || $this->current_directory == '/' ? '' : DIRECTORY_SEPARATOR; $checkForTheseFiles = array($this->current_directory . $ds . '.htaccess', $this->current_directory . $ds . 'index.html', $this->current_directory . $ds . 'index.htm', $this->current_directory . $ds . 'robots.txt'); $this->processed_files_counter = 0; foreach ($checkForTheseFiles as $fileName) { if (@file_exists($fileName)) { // Fix 3.3 - We have to also put them through other filters, ahem! if (!$filters->isFiltered($fileName, $root, 'file', 'all')) { $this->file_list[] = $fileName; $this->processed_files_counter++; } } } $this->done_file_scanning = true; } else { AEUtilLogger::WriteLog(_AE_LOG_INFO, "Scanning files of " . $this->current_directory); // Get file listing $fileList = $engine->getFiles($this->current_directory); // Error propagation $this->propagateFromObject($engine); // If the list contains "too many" items, please break this step! $registry = AEFactory::getConfiguration(); if ($registry->get('volatile.breakflag', false)) { // Log the step break decision, for debugging reasons AEUtilLogger::WriteLog(_AE_LOG_INFO, "Large directory " . $this->current_directory . " while scanning for files; I will resume scanning in next step."); // Return immediately, marking that we are not done yet! return true; } // Error control if ($this->getError()) { return false; } $this->processed_files_counter = 0; if ($fileList === false) { // A non-browsable directory; however, it seems that I never get FALSE reported here?! $this->setWarning('Unreadable directory ' . $this->current_directory); } else { if (is_array($fileList) && !empty($fileList)) { // Add required trailing slash to $dir if (!empty($dir)) { $dir .= '/'; } // Scan all directory entries foreach ($fileList as $fileName) { $check = $dir . basename($fileName); if (_AKEEBA_IS_WINDOWS) { $check = AEUtilFilesystem::TranslateWinPath($check); } // Do I need this? $dir contains a path relative to the root anyway... $check = ltrim(str_replace($translated_root, '', $check), '/'); $skipThisFile = $filters->isFiltered($check, $root, 'file', 'all'); if ($skipThisFile) { AEUtilLogger::WriteLog(_AE_LOG_INFO, "Skipping file {$fileName}"); } else { $this->file_list[] = $fileName; $this->processed_files_counter++; $this->progressAddFile(); } } // end foreach } // end if } // end filelist not false $this->done_file_scanning = true; } // Check to see if there were no contents of this directory added to our search list if ($this->processed_files_counter == 0) { $archiver = AEFactory::getArchiverEngine(); if ($this->current_directory != $this->remove_path_prefix) { $archiver->addFile($this->current_directory, $this->remove_path_prefix, $this->path_prefix); } // Error propagation $this->propagateFromObject($archiver); if ($this->getError()) { return false; } AEUtilLogger::WriteLog(_AE_LOG_INFO, "Empty directory " . $this->current_directory); unset($archiver); $this->done_scanning = false; // Because it was an empty dir $file_list is empty and we have to scan for more files } else { // Next up, add the files to the archive! $this->done_scanning = true; } // We're done listing the contents of this directory unset($engine); return true; }
/** * Calculates the absolute path to the log file * @param string $tag The backup run's tag * @return string The absolute path to the log file */ public static function logName($tag = null) { if (empty($tag)) { $fileName = 'akeeba.log'; } else { $fileName = "akeeba.{$tag}.log"; } // Get output directory $registry =& AEFactory::getConfiguration(); $outdir = $registry->get('akeeba.basic.output_directory'); // Get log's file name return AEUtilFilesystem::TranslateWinPath($outdir . DIRECTORY_SEPARATOR . $fileName); }
public function notifyFailed() { $params = JComponentHelper::getParams('com_akeeba'); // Invalidate stale backups AECoreKettenrad::reset(array('global' => true, 'log' => false, 'maxrun' => $params->get('failure_timeout', 180))); // Get the last execution and search for failed backups AFTER that date $last = $this->getLastCheck(); // Get failed backups $filters[] = array('field' => 'status', 'operand' => '=', 'value' => 'fail'); $filters[] = array('field' => 'origin', 'operand' => '<>', 'value' => 'restorepoint'); $filters[] = array('field' => 'backupstart', 'operand' => '>', 'value' => $last); $failed = AEPlatform::getInstance()->get_statistics_list(array('filters' => $filters)); // Well, everything went ok. if (!$failed) { return array('message' => array("No need to run: no failed backups or they were already notificated"), 'result' => true); } // Whops! Something went wrong, let's start notifing $superAdmins = array(); $superAdminEmail = $params->get('failure_email_address', ''); if (!empty($superAdminEmail)) { $superAdmins = $this->getSuperAdministrators($superAdminEmail); } if (empty($superAdmins)) { $superAdmins = $this->getSuperAdministrators(); } if (empty($superAdmins)) { return array('message' => array("WARNING! Failed backup(s) detected, but there are no configured Super Administrators to receive notifications"), 'result' => false); } $failedReport = array(); foreach ($failed as $fail) { $string = "Description : " . $fail['description'] . "\n"; $string .= "Start time : " . $fail['backupstart'] . "\n"; $string .= "Origin : " . $fail['origin'] . "\n"; $string .= "Type : " . $fail['type'] . "\n"; $string .= "Profile ID : " . $fail['profile_id']; $failedReport[] = $string; } $failedReport = implode("\n#-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+#\n", $failedReport); $email_subject = $params->get('failure_email_subject', ''); if (!$email_subject) { $email_subject = <<<ENDSUBJECT THIS EMAIL IS SENT FROM YOUR SITE "[SITENAME]" - Failed backup(s) detected ENDSUBJECT; } $email_body = $params->get('failure_email_body', ''); if (!$email_body) { $email_body = <<<ENDBODY ================================================================================ FAILED BACKUP ALERT ================================================================================ Your site has determined that there are failed backups. The following backups are found to be failing: [FAILEDLIST] ================================================================================ WHY AM I RECEIVING THIS EMAIL? ================================================================================ This email has been automatically sent by scritp you, or the person who built or manages your site, has installed and explicitly configured. This script looks for failed backups and sends an email notification to all Super Users. If you do not understand what this means, please do not contact the authors of the software. They are NOT sending you this email and they cannot help you. Instead, please contact the person who built or manages your site. ================================================================================ WHO SENT ME THIS EMAIL? ================================================================================ This email is sent to you by your own site, [SITENAME] ENDBODY; } $jconfig = JFactory::getConfig(); $mailfrom = $jconfig->get('mailfrom'); $fromname = $jconfig->get('fromname'); $email_subject = AEUtilFilesystem::replace_archive_name_variables($email_subject); $email_body = AEUtilFilesystem::replace_archive_name_variables($email_body); $email_body = str_replace('[FAILEDLIST]', $failedReport, $email_body); foreach ($superAdmins as $sa) { $mailer = JFactory::getMailer(); $mailer->setSender(array($mailfrom, $fromname)); $mailer->addRecipient($sa->email); $mailer->setSubject($email_subject); $mailer->setBody($email_body); $mailer->Send(); } // Let's update the last time we check, so we will avoid to send // the same notification several times $this->updateLastCheck(intval($last)); return array('message' => array("WARNING! Found " . count($failed) . " failed backup(s)", "Sent " . count($superAdmins) . " notifications"), 'result' => true); }
protected function _getSettings() { // Retrieve engine configuration data $config = AEFactory::getConfiguration(); $username = trim($config->get('engine.postproc.idrivesync.username', '')); $password = trim($config->get('engine.postproc.idrivesync.password', '')); $pvtkey = trim($config->get('engine.postproc.idrivesync.pvtkey', '')); $this->directory = $config->get('volatile.postproc.directory', null); if (empty($this->directory)) { $this->directory = $config->get('engine.postproc.idrivesync.directory', ''); } // Sanity checks if (empty($username) || empty($password)) { $this->setError('You have not set up the connection to your iDriveSync account'); return false; } // Fix the directory name, if required if (!empty($this->directory)) { $this->directory = trim($this->directory); $this->directory = ltrim(AEUtilFilesystem::TranslateWinPath($this->directory), '/'); } else { $this->directory = ''; } // Parse tags $this->directory = AEUtilFilesystem::replace_archive_name_variables($this->directory); $config->set('volatile.postproc.directory', $this->directory); $this->idrivesync = new AEUtilIdrivesync($username, $password, $pvtkey); return true; }
/** * Get the paths for a specific section * * @param string $section The section to get the path list for (engine, installer, gui, filter) * * @return array */ public static function getPaths($section = 'gui') { // Create the key if it's not already present if (!array_key_exists($section, static::$paths)) { static::$paths[$section] = array(); } // Add the defaults if the list is empty if (empty(static::$paths[$section])) { switch ($section) { case 'engine': static::$paths[$section] = array(AEUtilFilesystem::TranslateWinPath(AEFactory::getAkeebaRoot() . '/engines'), AEUtilFilesystem::TranslateWinPath(AEFactory::getAkeebaRoot() . '/plugins/engines')); break; case 'installer': static::$paths[$section] = array(AEUtilFilesystem::TranslateWinPath(AEPlatform::getInstance()->get_installer_images_path())); break; case 'gui': // Add core GUI definitions static::$paths[$section] = array(AEUtilFilesystem::TranslateWinPath(AEFactory::getAkeebaRoot() . '/core')); // Add additional core GUI definitions if (AKEEBA_PRO) { AEUtilFilesystem::TranslateWinPath(static::$paths[$section][] = AEFactory::getAkeebaRoot() . '/plugins/core'); } // Add platform GUI definition files $platform_paths = AEPlatform::getInstance()->getPlatformDirectories(); foreach ($platform_paths as $p) { static::$paths[$section][] = AEUtilFilesystem::TranslateWinPath($p . '/config'); } break; case 'filter': static::$paths[$section] = array(AEUtilFilesystem::TranslateWinPath(AEFactory::getAkeebaRoot() . '/platform/filters/stack'), AEUtilFilesystem::TranslateWinPath(AEFactory::getAkeebaRoot() . '/filters/stack'), AEUtilFilesystem::TranslateWinPath(AEFactory::getAkeebaRoot() . '/plugins/filters/stack')); $platform_paths = AEPlatform::getInstance()->getPlatformDirectories(); foreach ($platform_paths as $p) { static::$paths[$section][] = AEUtilFilesystem::TranslateWinPath($p . '/filters/stack'); } break; } } return static::$paths[$section]; }
public function &getFolders($folder, &$position) { // Was the breakflag set BEFORE starting? -- This workaround is required due to PHP5 defaulting to assigning variables by reference $registry = AEFactory::getConfiguration(); $breakflag_before_process = $registry->get('volatile.breakflag', false); // Reset break flag before continuing $breakflag = false; // Initialize variables $arr = array(); $false = false; if (!is_dir($folder) && !is_dir($folder . '/')) { return $false; } $counter = 0; $registry = AEFactory::getConfiguration(); $maxCounter = $registry->get('engine.scan.smart.large_dir_threshold', 100); $allowBreakflag = $registry->get('volatile.operation_counter', 0) != 0 && !$breakflag_before_process; if ($this->method == 'opendir') { $handle = @opendir($folder); /* If opening the directory doesn't work, try adding a trailing slash. This is useful in cases * like this: open_basedir=/home/user/www/ and the root is /home/user/www. Trying to scan * /home/user/www results in error, trying to scan /home/user/www/ succeeds. Duh! */ if ($handle === false) { $handle = @opendir($folder . '/'); } // If directory is not accessible, just return FALSE if ($handle === false) { $this->setWarning('Unreadable directory ' . $folder); return $false; } } else { $handle = dir($folder); if ($handle->handle === false) { $handle = dir($folder . '/'); if ($handle->handle === false) { $this->setWarning('Unreadable directory ' . $folder); return $false; } } } while (($file = $this->method == 'opendir' ? @readdir($handle) : $handle->read()) !== false && !$breakflag) { if ($file != '.' && $file != '..') { // # Fix 2.4: Do not add DS if we are on the site's root and it's an empty string $ds = $folder == '' || $folder == '/' || @substr($folder, -1) == '/' || @substr($folder, -1) == DIRECTORY_SEPARATOR ? '' : DIRECTORY_SEPARATOR; $dir = $folder . $ds . $file; $isDir = is_dir($dir); if ($isDir) { $data = _AKEEBA_IS_WINDOWS ? AEUtilFilesystem::TranslateWinPath($dir) : $dir; if ($data) { $arr[] = $data; } } } $counter++; if ($counter >= $maxCounter) { $breakflag = $allowBreakflag; } } $this->method == 'opendir' ? @closedir($handle) : $handle->close(); // Save break flag status $registry->set('volatile.breakflag', $breakflag); return $arr; }
public static function &getFolders($folder, $fullpath = false) { // Initialize variables $arr = array(); $false = false; if (!is_dir($folder) && !is_dir($folder . '/')) { return $false; } $handle = @opendir($folder); if ($handle === FALSE) { $handle = @opendir($folder . '/'); } // If directory is not accessible, just return FALSE if ($handle === FALSE) { return $false; } $registry = AEFactory::getConfiguration(); $dereferencesymlinks = $registry->get('engine.archiver.common.dereference_symlinks'); while (($file = @readdir($handle)) !== false) { if ($file != '.' && $file != '..') { $dir = "{$folder}/{$file}"; $isDir = @is_dir($dir); $isLink = @is_link($dir); if ($isDir) { //if(!$dereferencesymlinks && $isLink) continue; if ($fullpath) { $data = _AKEEBA_IS_WINDOWS ? AEUtilFilesystem::TranslateWinPath($dir) : $dir; } else { $data = _AKEEBA_IS_WINDOWS ? AEUtilFilesystem::TranslateWinPath($file) : $file; } if ($data) { $arr[] = $data; } } } } @closedir($handle); return $arr; }
/** * 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::getInstance()->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 ---"); AEUtilLogger::WriteLog(_AE_LOG_INFO, "PHP Version :" . PHP_VERSION); AEUtilLogger::WriteLog(_AE_LOG_INFO, "PHP OS :" . PHP_OS); AEUtilLogger::WriteLog(_AE_LOG_INFO, "PHP SAPI :" . PHP_SAPI); 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); $platform = 'Unknown platform'; $version = '(unknown version)'; $platformData = AEPlatform::getInstance()->getPlatformVersion(); AEUtilLogger::WriteLog(_AE_LOG_INFO, $platformData['name'] . " version :" . $platformData['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::getInstance()->log_platform_special_directories(); AEUtilLogger::WriteLog(_AE_LOG_INFO, "Output directory :" . $registry->get('akeeba.basic.output_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, "--------------------------------------------------------------------------------"); } if (!version_compare(PHP_VERSION, '5.3.0', 'ge')) { AEUtilLogger::WriteLog(_AE_LOG_WARNING, "You are using an outdated version of PHP. Akeeba Engine may not work properly. Please upgrade to PHP 5.3 or later."); } // Report profile ID $profile_id = AEPlatform::getInstance()->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::getInstance()->get_backup_origin(); // Get backup origin $profile_id = AEPlatform::getInstance()->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::getInstance()->get_timestamp_database(), '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 processPart($absolute_filename, $upload_as = null) { // Retrieve engine configuration data $config = AEFactory::getConfiguration(); $accesskey = trim($config->get('engine.postproc.googlestorage.accesskey', '')); $secret = trim($config->get('engine.postproc.googlestorage.secretkey', '')); $usessl = $config->get('engine.postproc.googlestorage.usessl', 0) == 0 ? false : true; $bucket = $config->get('engine.postproc.googlestorage.bucket', ''); $directory = $config->get('volatile.postproc.directory', null); $lowercase = $config->get('engine.postproc.googlestorage.lowercase', 1); if (empty($directory)) { $directory = $config->get('engine.postproc.googlestorage.directory', 0); } // Sanity checks if (empty($accesskey)) { $this->setError('You have not set up your Google Storage Access Key'); return false; } if (empty($secret)) { $this->setError('You have not set up your Google Storage Secret Key'); return false; } if (empty($bucket)) { $this->setError('You have not set up your Google Storage Bucket'); return false; } else { // Remove any slashes from the bucket $bucket = str_replace('/', '', $bucket); if ($lowercase) { $bucket = strtolower($bucket); } } // Create an S3 instance with the required credentials $s3 = AEUtilAmazons3::getInstance($accesskey, $secret, $usessl); $s3->defaultHost = 'commondatastorage.googleapis.com'; // If we are here, we'll have to start uploading the file. Let's prepare ourselves for that. // Fix the directory name, if required if (!empty($directory)) { $directory = trim($directory); $directory = ltrim(AEUtilFilesystem::TranslateWinPath($directory), '/'); } else { $directory = ''; } // Parse tags $directory = AEUtilFilesystem::replace_archive_name_variables($directory); $config->set('volatile.postproc.directory', $directory); // Calculate relative remote filename $filename = empty($upload_as) ? basename($absolute_filename) : $upload_as; if (!empty($directory) && $directory != '/') { $filename = $directory . '/' . $filename; } // Store the absolute remote path in the class property $this->remote_path = $filename; // Do we have to upload in one go or do a multipart upload instead? $filesize = @filesize($absolute_filename); AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Google Storage -- Uploading " . basename($absolute_filename)); // Legacy single part uploads $result = $s3->putObject(AEUtilAmazons3::inputFile($absolute_filename, false), $bucket, $filename, AEUtilAmazons3::ACL_BUCKET_OWNER_FULL_CONTROL, array(), array()); // Return the result $this->propagateFromObject($s3); return $result; }