public function onAdd($tpl = null) { $media_folder = JUri::base() . '../media/com_akeeba/'; // Get a JSON representation of GUI data $json = AkeebaHelperEscape::escapeJS(Factory::getEngineParamsProvider()->getJsonGuiDefinition(), '"\\'); $this->json = $json; // Get profile ID $profileid = Platform::getInstance()->get_active_profile(); $this->profileid = $profileid; // Get profile name $profileName = F0FModel::getTmpInstance('Profiles', 'AkeebaModel')->setId($profileid)->getItem()->description; $this->profilename = $profileName; // Get the root URI for media files $this->mediadir = AkeebaHelperEscape::escapeJS($media_folder . 'theme/'); // Are the settings secured? if (Platform::getInstance()->get_platform_configuration_option('useencryption', -1) == 0) { $this->securesettings = -1; } elseif (!Factory::getSecureSettings()->supportsEncryption()) { $this->securesettings = 0; } else { JLoader::import('joomla.filesystem.file'); $filename = JPATH_COMPONENT_ADMINISTRATOR . '/engine/serverkey.php'; if (JFile::exists($filename)) { $this->securesettings = 1; } else { $this->securesettings = 0; } } // Add live help AkeebaHelperIncludes::addHelp('config'); }
/** * Execute the JSON API task * * @param array $parameters The parameters to this task * * @return mixed * * @throws \RuntimeException In case of an error */ public function execute(array $parameters = array()) { // Get the passed configuration values $defConfig = array('profile' => 0); $defConfig = array_merge($defConfig, $parameters); $profile = (int) $defConfig['profile']; if ($profile <= 0) { $profile = 1; } // Set the active profile $session = $this->container->session; $session->set('profile', $profile); // Load the configuration Platform::getInstance()->load_configuration($profile); return Factory::getEngineParamsProvider()->getJsonGuiDefinition(); }
/** * Executes when displaying the page */ public function onBeforeMain() { $this->addJavascriptFile('media://com_akeeba/js/Configuration.min.js'); JHtml::_('behavior.modal'); // Get a JSON representation of GUI data $json = Factory::getEngineParamsProvider()->getJsonGuiDefinition(); $this->json = $json; $this->getProfileIdAndName(); // Are the settings secured? $this->securesettings = $this->getSecureSettingsOption(); // Should I show the Configuration Wizard popup prompt? $this->promptForConfigurationWizard = Factory::getConfiguration()->get('akeeba.flag.confwiz', 0) != 1; // Push translations JText::script('COM_AKEEBA_CONFIG_UI_BROWSE'); JText::script('COM_AKEEBA_CONFIG_UI_CONFIG'); JText::script('COM_AKEEBA_CONFIG_UI_REFRESH'); JText::script('COM_AKEEBA_FILEFILTERS_LABEL_UIROOT'); JText::script('COM_AKEEBA_CONFIG_UI_FTPBROWSER_TITLE'); JText::script('COM_AKEEBA_CONFIG_DIRECTFTP_TEST_OK'); JText::script('COM_AKEEBA_CONFIG_DIRECTFTP_TEST_FAIL'); JText::script('COM_AKEEBA_CONFIG_DIRECTSFTP_TEST_OK'); JText::script('COM_AKEEBA_CONFIG_DIRECTSFTP_TEST_FAIL'); }
/** * Returns the relative and absolute path to the archive */ protected function getArchiveName() { $registry = Factory::getConfiguration(); // Import volatile scripting keys to the registry Factory::getEngineParamsProvider()->importScriptingToRegistry(); // Determine the extension $force_extension = Factory::getEngineParamsProvider()->getScriptingParameter('core.forceextension', null); if (is_null($force_extension)) { $archiver = Factory::getArchiverEngine(); $extension = $archiver->getExtension(); } else { $extension = $force_extension; } // Get the template name $templateName = $registry->get('akeeba.basic.archive_name'); Factory::getLog()->log(LogLevel::DEBUG, "Archive template name: {$templateName}"); // Parse all tags $fsUtils = Factory::getFilesystemTools(); $templateName = $fsUtils->replace_archive_name_variables($templateName); Factory::getLog()->log(LogLevel::DEBUG, "Expanded template name: {$templateName}"); $ds = DIRECTORY_SEPARATOR; $relative_path = $templateName . $extension; $absolute_path = $fsUtils->TranslateWinPath($registry->get('akeeba.basic.output_directory') . $ds . $relative_path); return array($relative_path, $absolute_path); }
/** * This mess of a code is probably not one of my highlights in my code * writing career. It's logically organized, badly architectured but I can * still maintain it - and it works! */ public function onAdd($tpl = null) { /** @var AkeebaModelBackups $model */ $model = $this->getModel(); // Load the Status Helper if (!class_exists('AkeebaHelperStatus')) { JLoader::import('helpers.status', JPATH_COMPONENT_ADMINISTRATOR); } $helper = AkeebaHelperStatus::getInstance(); // Determine default description JLoader::import('joomla.utilities.date'); $jregistry = JFactory::getConfig(); if (version_compare(JVERSION, '3.0', 'ge')) { $tzDefault = $jregistry->get('offset'); } else { $tzDefault = $jregistry->getValue('config.offset'); } $user = JFactory::getUser(); $tz = $user->getParam('timezone', $tzDefault); $dateNow = new JDate('now', $tz); $default_description = JText::_('BACKUP_DEFAULT_DESCRIPTION') . ' ' . $dateNow->format(JText::_('DATE_FORMAT_LC2'), true); $default_description = AkeebaHelperEscape::escapeJS($default_description, "'"); $backup_description = $model->getState('description', $default_description); $comment = $model->getState('comment', ''); // Get a potential return URL $returnurl = $model->getState('returnurl'); if (empty($returnurl)) { $returnurl = ''; } // If a return URL is set *and* the profile's name is "Site Transfer // Wizard", we are running the Site Transfer Wizard if (!class_exists('AkeebaModelProfiles')) { JLoader::import('models.profiles', JPATH_COMPONENT_ADMINISTRATOR); } /** @var AkeebaModelCpanels $cpanelmodel */ $cpanelmodel = F0FModel::getAnInstance('Cpanels', 'AkeebaModel'); $profilemodel = new AkeebaModelProfiles(); $profilemodel->setId($cpanelmodel->getProfileID()); $profile_data = $profilemodel->getProfile(); $isSTW = $profile_data->description == 'Site Transfer Wizard (do not rename)' && !empty($returnurl); $this->isSTW = $isSTW; // Get the domain details from scripting facility $registry = Factory::getConfiguration(); $tag = $model->getState('tag'); $script = $tag == 'restorepoint' ? 'full' : $registry->get('akeeba.basic.backup_type', 'full'); $scripting = Factory::getEngineParamsProvider()->loadScripting(); $domains = array(); if (!empty($scripting)) { foreach ($scripting['scripts'][$script]['chain'] as $domain) { $description = JText::_($scripting['domains'][$domain]['text']); $domain_key = $scripting['domains'][$domain]['domain']; if ($isSTW && $domain_key == 'Packing') { $description = JText::_('BACKUP_LABEL_DOMAIN_PACKING_STW'); } $domains[] = array($domain_key, $description); } } $json_domains = AkeebaHelperEscape::escapeJS(json_encode($domains), '"\\'); // Get the maximum execution time and bias $maxexec = $registry->get('akeeba.tuning.max_exec_time', 14) * 1000; $bias = $registry->get('akeeba.tuning.run_time_bias', 75); // Check if the output directory is writable $quirks = Factory::getConfigurationChecks()->getDetailedStatus(); $unwritableOutput = array_key_exists('001', $quirks); // Pass on data $this->haserrors = !$helper->status; $this->hasquirks = $helper->hasQuirks(); $this->quirks = $helper->getQuirksCell(!$helper->status); $this->description = $backup_description; $this->default_descr = $default_description; $this->comment = $comment; $this->domains = $json_domains; $this->maxexec = $maxexec; $this->bias = $bias; $this->useiframe = $registry->get('akeeba.basic.useiframe', 0) ? 'true' : 'false'; $this->returnurl = $returnurl; $this->unwritableoutput = $unwritableOutput; if ($registry->get('akeeba.advanced.archiver_engine', 'jpa') == 'jps') { $this->showjpskey = 1; $this->jpskey = $registry->get('engine.archiver.jps.key', ''); } else { $this->showjpskey = 0; } if (AKEEBA_PRO) { $this->showangiekey = 1; $this->angiekey = $registry->get('engine.installer.angie.key', ''); } else { $this->showangiekey = 0; $this->angiekey = ''; } $this->autostart = $model->getState('autostart'); // Pass on profile info $this->profileid = $cpanelmodel->getProfileID(); // Active profile ID $this->profilelist = $cpanelmodel->getProfilesList(); // List of available profiles // Pass on state information pertaining to SRP $this->srpinfo = $model->getState('srpinfo'); // Add live help AkeebaHelperIncludes::addHelp('backup'); // Set the toolbar title if ($this->srpinfo['tag'] == 'restorepoint') { $subtitle = JText::_('AKEEBASRP'); } elseif ($isSTW) { $subtitle = JText::_('SITETRANSFERWIZARD'); } else { $subtitle = JText::_('BACKUP'); } JToolBarHelper::title(JText::_('AKEEBA') . ':: <small>' . $subtitle . '</small>', 'akeeba'); return true; }
/** * Returns the details of the latest backup as HTML * * @return string HTML * * @todo Move this into a helper class */ public function getLatestBackupDetails() { $db = $this->getDBO(); $query = $db->getQuery(true)->select('MAX(' . $db->qn('id') . ')')->from($db->qn('#__ak_stats'))->where($db->qn('origin') . ' != ' . $db->q('restorepoint')); $db->setQuery($query); $id = $db->loadResult(); $backup_types = Factory::getEngineParamsProvider()->loadScripting(); if (empty($id)) { return '<p class="label">' . JText::_('BACKUP_STATUS_NONE') . '</p>'; } $record = Platform::getInstance()->get_statistics($id); JLoader::import('joomla.utilities.date'); $statusClass = ""; switch ($record['status']) { case 'run': $status = JText::_('STATS_LABEL_STATUS_PENDING'); $statusClass = "label-warning"; break; case 'fail': $status = JText::_('STATS_LABEL_STATUS_FAIL'); $statusClass = "label-important"; break; case 'complete': $status = JText::_('STATS_LABEL_STATUS_OK'); $statusClass = "label-success"; break; default: $status = ''; $statusClass = ''; } switch ($record['origin']) { case 'frontend': $origin = JText::_('STATS_LABEL_ORIGIN_FRONTEND'); break; case 'backend': $origin = JText::_('STATS_LABEL_ORIGIN_BACKEND'); break; case 'cli': $origin = JText::_('STATS_LABEL_ORIGIN_CLI'); break; default: $origin = '–'; break; } if (array_key_exists($record['type'], $backup_types['scripts'])) { $type = Platform::getInstance()->translate($backup_types['scripts'][$record['type']]['text']); } else { $type = ''; } $startTime = new JDate($record['backupstart']); $html = '<table class="table table-striped">'; $html .= '<tr><td>' . JText::_('STATS_LABEL_START') . '</td><td>' . $startTime->format(JText::_('DATE_FORMAT_LC4'), true) . '</td></tr>'; $html .= '<tr><td>' . JText::_('STATS_LABEL_DESCRIPTION') . '</td><td>' . $record['description'] . '</td></tr>'; $html .= '<tr><td>' . JText::_('STATS_LABEL_STATUS') . '</td><td><span class="label ' . $statusClass . '">' . $status . '</span></td></tr>'; $html .= '<tr><td>' . JText::_('STATS_LABEL_ORIGIN') . '</td><td>' . $origin . '</td></tr>'; $html .= '<tr><td>' . JText::_('STATS_LABEL_TYPE') . '</td><td>' . $type . '</td></tr>'; $html .= '</table>'; return $html; }
/** * Gets the CREATE TABLE command for a given table/view/procedure/function/trigger * * @param string $table_abstract The abstracted name of the entity * @param string $table_name The name of the table * @param string $type The type of the entity to scan. If it's found to differ, the correct type is returned. * @param array $dependencies The dependencies of this table * * @return string The CREATE command, w/out newlines */ protected function get_create($table_abstract, $table_name, &$type, &$dependencies) { $configuration = Factory::getConfiguration(); $notracking = $configuration->get('engine.dump.native.nodependencies', 0); $db = $this->getDB(); if ($this->getError()) { return; } switch ($type) { case 'table': case 'merge': case 'view': default: $sql = "SHOW CREATE TABLE `{$table_abstract}`"; break; case 'procedure': $sql = "SHOW CREATE PROCEDURE `{$table_abstract}`"; break; case 'function': $sql = "SHOW CREATE FUNCTION `{$table_abstract}`"; break; case 'trigger': $sql = "SHOW CREATE TRIGGER `{$table_abstract}`"; break; } $db->setQuery($sql); try { $temp = $db->loadRowList(); } catch (\Exception $e) { // If the query failed we don't have the necessary SHOW privilege. Log the error and fake an empty reply. $entityType = $type == 'merge' ? 'table' : $type; $msg = $e->getMessage(); Factory::getLog()->log(LogLevel::WARNING, "Cannot get the structure of {$entityType} {$table_abstract}. Database returned error {$msg} running {$sql} Please check your database privileges. Your database backup may be incomplete."); $db->resetErrors(); $temp = array(array('', '', '')); } if (in_array($type, array('procedure', 'function', 'trigger'))) { $table_sql = $temp[0][2]; // These can contain comment lines, starting with a double dash. Remove them. $lines = explode("\n", $table_sql); $table_sql = ''; foreach ($lines as $line) { $line = trim($line); if (substr($line, 0, 2) == '--') { continue; } $table_sql .= $line . ' '; } $table_sql = trim($table_sql); if (substr($table_sql, -1) != ';') { $table_sql .= ';'; } } else { $table_sql = $temp[0][1]; } unset($temp); // Smart table type detection if (in_array($type, array('table', 'merge', 'view'))) { // Check for CREATE VIEW $pattern = '/^CREATE(.*) VIEW (.*)/i'; $result = preg_match($pattern, $table_sql); if ($result === 1) { // This is a view. $type = 'view'; } else { // This is a table. $type = 'table'; // # Fix 3.2.1: USING BTREE / USING HASH in indices causes issues migrating from MySQL 5.1+ hosts to // MySQL 5.0 hosts if ($configuration->get('engine.dump.native.nobtree', 1)) { $table_sql = str_replace(' USING BTREE', ' ', $table_sql); $table_sql = str_replace(' USING HASH', ' ', $table_sql); } // Translate TYPE= to ENGINE= $table_sql = str_replace('TYPE=', 'ENGINE=', $table_sql); } // Is it a VIEW but we don't have SHOW VIEW privileges? if (empty($table_sql)) { $type = 'view'; } } // Replace table name and names of referenced tables with their abstracted // forms and populate dependency tables at the same time // On DB only backup we don't want any replacing to take place, do we? if (!Factory::getEngineParamsProvider()->getScriptingParameter('db.abstractnames', 1)) { $old_table_sql = $table_sql; } // Return dependency information only if dependency tracking is enabled if (!$notracking) { // Even on simple tables, we may have foreign key references. // As a result, we need to replace those referenced table names // as well. On views and merge arrays, we have referenced tables // by definition. $dependencies = array(); // First, the table/view/merge table name itself: // We have to quote the table name, otherwise if we have a column name that starts with the same name of the // table we will have wrong results // Example: table `poll`, columns `poll_id` will become #__poll, #__poll_id $table_sql = str_replace($db->quoteName($table_name), $db->quoteName($table_abstract), $table_sql); // Now, loop for all table entries foreach ($this->table_name_map as $ref_normal => $ref_abstract) { if ($pos = strpos($table_sql, "`{$ref_normal}`")) { // Add a reference hit $this->dependencies[$ref_normal][] = $table_name; // Add the dependency to this table's metadata $dependencies[] = $ref_normal; // Do the replacement $table_sql = str_replace("`{$ref_normal}`", "`{$ref_abstract}`", $table_sql); } } // Finally, replace the prefix if it's not empty (used in constraints) if (!empty($this->prefix)) { $table_sql = str_replace('`' . $this->prefix, '`#__', $table_sql); } } // On DB only backup we don't want any replacing to take place, do we? if (!Factory::getEngineParamsProvider()->getScriptingParameter('db.abstractnames', 1)) { $table_sql = $old_table_sql; } // Replace newlines with spaces $table_sql = str_replace("\n", " ", $table_sql) . ";\n"; $table_sql = str_replace("\r", " ", $table_sql); $table_sql = str_replace("\t", " ", $table_sql); // Post-process CREATE VIEW if ($type == 'view') { $pos_view = strpos($table_sql, ' VIEW '); if ($pos_view > 7) { // Only post process if there are view properties between the CREATE and VIEW keywords $propstring = substr($table_sql, 7, $pos_view - 7); // Properties string // Fetch the ALGORITHM={UNDEFINED | MERGE | TEMPTABLE} keyword $algostring = ''; $algo_start = strpos($propstring, 'ALGORITHM='); if ($algo_start !== false) { $algo_end = strpos($propstring, ' ', $algo_start); $algostring = substr($propstring, $algo_start, $algo_end - $algo_start + 1); } // Create our modified create statement $table_sql = 'CREATE OR REPLACE ' . $algostring . substr($table_sql, $pos_view); } } elseif ($type == 'procedure') { $pos_entity = stripos($table_sql, ' PROCEDURE '); if ($pos_entity !== false) { $table_sql = 'CREATE' . substr($table_sql, $pos_entity); } } elseif ($type == 'function') { $pos_entity = stripos($table_sql, ' FUNCTION '); if ($pos_entity !== false) { $table_sql = 'CREATE' . substr($table_sql, $pos_entity); } } elseif ($type == 'trigger') { $pos_entity = stripos($table_sql, ' TRIGGER '); if ($pos_entity !== false) { $table_sql = 'CREATE' . substr($table_sql, $pos_entity); } } // Add DROP statements for DB only backup if (Factory::getEngineParamsProvider()->getScriptingParameter('db.dropstatements', 0)) { if ($type == 'table' || $type == 'merge') { // Table or merge tables, get a DROP TABLE statement $drop = "DROP TABLE IF EXISTS " . $db->quoteName($table_name) . ";\n"; } elseif ($type == 'view') { // Views get a DROP VIEW statement $drop = "DROP VIEW IF EXISTS " . $db->quoteName($table_name) . ";\n"; } elseif ($type == 'procedure') { // Procedures get a DROP PROCEDURE statement and proper delimiter strings $drop = "DROP PROCEDURE IF EXISTS " . $db->quoteName($table_name) . ";\n"; $drop .= "DELIMITER // "; $table_sql = str_replace("\r", " ", $table_sql); $table_sql = str_replace("\t", " ", $table_sql); $table_sql = rtrim($table_sql, ";\n") . " // DELIMITER ;\n"; } elseif ($type == 'function') { // Procedures get a DROP FUNCTION statement and proper delimiter strings $drop = "DROP FUNCTION IF EXISTS " . $db->quoteName($table_name) . ";\n"; $drop .= "DELIMITER // "; $table_sql = str_replace("\r", " ", $table_sql); $table_sql = rtrim($table_sql, ";\n") . "// DELIMITER ;\n"; } elseif ($type == 'trigger') { // Procedures get a DROP TRIGGER statement and proper delimiter strings $drop = "DROP TRIGGER IF EXISTS " . $db->quoteName($table_name) . ";\n"; $drop .= "DELIMITER // "; $table_sql = str_replace("\r", " ", $table_sql); $table_sql = str_replace("\t", " ", $table_sql); $table_sql = rtrim($table_sql, ";\n") . "// DELIMITER ;\n"; } $table_sql = $drop . $table_sql; } return $table_sql; }
/** * Populates database_list with the list of databases in the settings * * @return void */ protected function populate_database_list() { // Get database inclusion filters $filters = Factory::getFilters(); $this->database_list = $filters->getInclusions('db'); // Error propagation $this->propagateFromObject($filters); if ($this->getError()) { return; } if (Factory::getEngineParamsProvider()->getScriptingParameter('db.skipextradb', 0)) { // On database only backups we prune extra databases Factory::getLog()->log(LogLevel::DEBUG, __CLASS__ . " :: Adding only main database"); if (count($this->database_list) > 1) { $this->database_list = array_slice($this->database_list, 0, 1); } } }
if ($number <= 0) { return '-'; } $units = array('b', 'Kb', 'Mb', 'Gb', 'Tb'); if ($force_unit === false) { $unit = floor(log($number, 2) / 10); } else { $unit = $force_unit; } if ($unit == 0) { $decimals = 0; } return number_format($number / pow(1024, $unit), $decimals, $dec_char, $thousands_char) . ' ' . $units[$unit]; } // Load a mapping of backup types to textual representation $scripting = \Akeeba\Engine\Factory::getEngineParamsProvider()->loadScripting(); $backup_types = array(); foreach ($scripting['scripts'] as $key => $data) { $backup_types[$key] = JText::_($data['text']); } ?> <script type="text/javascript"> Joomla.orderTable = function () { table = document.getElementById("sortTable"); direction = document.getElementById("directionTable"); order = table.options[table.selectedIndex].value; if (order != '<?php echo $this->escape($this->lists->order); ?> ') {
/** * Transforms a JPA archive (containing an installer) to the native archive format * of the class. It actually extracts the source JPA in memory and instructs the * class to include each extracted file. * * @codeCoverageIgnore * * @param integer $index The index in the source JPA archive's list currently in use * @param integer $offset The source JPA archive's offset to use * * @return boolean False if an error occurred, true otherwise */ public function transformJPA($index, $offset) { static $totalSize = 0; // Do we have to open the file? if (!$this->_xform_fp) { // Get the source path $registry = Factory::getConfiguration(); $embedded_installer = $registry->get('akeeba.advanced.embedded_installer'); // Fetch the name of the installer image $installerDescriptors = Factory::getEngineParamsProvider()->getInstallerList(); $xform_source = Platform::getInstance()->get_installer_images_path() . '/foobar.jpa'; // We need this as a "safe fallback" // Try to find a sane default if we are not given a valid embedded installer if (!array_key_exists($embedded_installer, $installerDescriptors)) { $embedded_installer = 'angie'; if (!array_key_exists($embedded_installer, $installerDescriptors)) { $allInstallers = array_keys($installerDescriptors); foreach ($allInstallers as $anInstaller) { if ($anInstaller == 'none') { continue; } $embedded_installer = $anInstaller; break; } } } if (array_key_exists($embedded_installer, $installerDescriptors)) { $packages = $installerDescriptors[$embedded_installer]['package']; if (empty($packages)) { // No installer package specified. Pretend we are done! $retArray = array("filename" => '', "data" => '', "index" => 0, "offset" => 0, "skip" => false, "done" => true, "filesize" => 0); return $retArray; } $packages = explode(',', $packages); $totalSize = 0; $pathPrefix = Platform::getInstance()->get_installer_images_path() . '/'; foreach ($packages as $package) { $filePath = $pathPrefix . $package; $totalSize += (int) @filesize($filePath); } if (count($packages) < $index) { $this->setError(__CLASS__ . ":: Installer package index {$index} not found for embedded installer {$embedded_installer}"); return false; } $package = $packages[$index]; // A package is specified, use it! $xform_source = $pathPrefix . $package; } // 2.3: Try to use sane default if the indicated installer doesn't exist if (!file_exists($xform_source) && basename($xform_source) != 'angie.jpa') { $this->setError(__CLASS__ . ":: Installer package {$xform_source} of embedded installer {$embedded_installer} not found. Please go to the configuration page, select an Embedded Installer, save the configuration and try backing up again."); return false; } // Try opening the file if (file_exists($xform_source)) { $this->_xform_fp = @fopen($xform_source, 'r'); if ($this->_xform_fp === false) { $this->setError(__CLASS__ . ":: Can't seed archive with installer package " . $xform_source); return false; } } else { $this->setError(__CLASS__ . ":: Installer package " . $xform_source . " does not exist!"); return false; } } $headerDataLength = 0; if (!$offset) { // First run detected! Factory::getLog()->log(LogLevel::DEBUG, 'Initializing with JPA package ' . $xform_source); // Skip over the header and check no problem exists $offset = $this->_xformReadHeader(); if ($offset === false) { $this->setError('JPA package file was not read'); return false; // Oops! The package file doesn't exist or is corrupt } $headerDataLength = $offset; } $ret = $this->_xformExtract($offset); $ret['index'] = $index; if (is_array($ret)) { $ret['chunkProcessed'] = $headerDataLength + $ret['offset'] - $offset; $offset = $ret['offset']; if (!$ret['skip'] && !$ret['done']) { Factory::getLog()->log(LogLevel::DEBUG, ' Adding ' . $ret['filename'] . '; Next offset:' . $offset); $this->addVirtualFile($ret['filename'], '', $ret['data']); if ($this->getError()) { return false; } } elseif ($ret['done']) { $registry = Factory::getConfiguration(); $embedded_installer = $registry->get('akeeba.advanced.embedded_installer'); $installerDescriptors = Factory::getEngineParamsProvider()->getInstallerList(); $packages = $installerDescriptors[$embedded_installer]['package']; $packages = explode(',', $packages); Factory::getLog()->log(LogLevel::DEBUG, ' Done with package ' . $packages[$index]); if (count($packages) > $index + 1) { $ret['done'] = false; $ret['index'] = $index + 1; $ret['offset'] = 0; $this->_xform_fp = null; } else { Factory::getLog()->log(LogLevel::DEBUG, ' Done with installer seeding.'); } } else { $reason = ' Skipping ' . $ret['filename']; Factory::getLog()->log(LogLevel::DEBUG, $reason); } } else { $this->setError('JPA extraction returned FALSE. The installer image is corrupt.'); return false; } if ($ret['done']) { // We are finished! Close the file fclose($this->_xform_fp); Factory::getLog()->log(LogLevel::DEBUG, 'Initializing with JPA package has finished'); } $ret['filesize'] = $totalSize; return $ret; }
/** * Translates the internal backup type (e.g. cli) to a human readable string * * @param string $recordType The internal backup type * * @return string */ protected function translateBackupType($recordType) { static $backup_types = null; if (!is_array($backup_types)) { // Load a mapping of backup types to textual representation $scripting = \Akeeba\Engine\Factory::getEngineParamsProvider()->loadScripting(); $backup_types = array(); foreach ($scripting['scripts'] as $key => $data) { $backup_types[$key] = JText::_($data['text']); } } if (array_key_exists($recordType, $backup_types)) { return $backup_types[$recordType]; } return '–'; }
protected function _prepare() { // Intialize the timer class $timer = Factory::getTimer(); // Do we have a tag? if (!empty($this->_parametersArray['tag'])) { $this->tag = $this->_parametersArray['tag']; } // Make sure a tag exists (or create a new one) $this->tag = $this->getTag(); // Reset the log $logTag = $this->getLogTag(); Factory::getLog()->open($logTag); Factory::getLog()->reset($logTag); if (!static::$registeredErrorHandler) { static::$registeredErrorHandler = true; set_error_handler('\\Akeeba\\Engine\\Core\\akeebaBackupErrorHandler'); } // Reset the storage $factoryStorageTag = $this->tag . (empty($this->backup_id) ? '' : '.' . $this->backup_id); Factory::getFactoryStorage()->reset($factoryStorageTag); // Apply the configuration overrides $overrides = Platform::getInstance()->configOverrides; if (is_array($overrides) && @count($overrides)) { $registry = Factory::getConfiguration(); $protected_keys = $registry->getProtectedKeys(); $registry->resetProtectedKeys(); foreach ($overrides as $k => $v) { $registry->set($k, $v); } $registry->setProtectedKeys($protected_keys); } // Get the domain chain $this->domain_chain = Factory::getEngineParamsProvider()->getDomainChain(); $this->total_steps = count($this->domain_chain) - 1; // Init shouldn't count in the progress bar // Mark this engine for Nesting Logging $this->nest_logging = true; // Preparation is over $this->array_cache = null; $this->setState('prepared'); // Send a push message to mark the start of backup $platform = Platform::getInstance(); $timeStamp = date($platform->translate('DATE_FORMAT_LC2')); $pushSubject = sprintf($platform->translate('COM_AKEEBA_PUSH_STARTBACKUP_SUBJECT'), $platform->get_site_name(), $platform->get_host()); $pushDetails = sprintf($platform->translate('COM_AKEEBA_PUSH_STARTBACKUP_BODY'), $platform->get_site_name(), $platform->get_host(), $timeStamp, $this->getLogTag()); Factory::getPush()->message($pushSubject, $pushDetails); //restore_error_handler(); }
/** * Public constructor * * @return Part */ public function __construct() { // Fetch the installer settings $this->installerSettings = (object) array('installerroot' => 'installation', 'sqlroot' => 'installation/sql', 'databasesini' => 1, 'readme' => 1, 'extrainfo' => 1, 'password' => 0); $config = Factory::getConfiguration(); $installerKey = $config->get('akeeba.advanced.embedded_installer'); $installerDescriptors = Factory::getEngineParamsProvider()->getInstallerList(); if (array_key_exists($installerKey, $installerDescriptors)) { // The selected installer exists, use it $this->installerSettings = (object) $installerDescriptors[$installerKey]; } elseif (array_key_exists('angie', $installerDescriptors)) { // The selected installer doesn't exist, but ANGIE exists; use that instead $this->installerSettings = (object) $installerDescriptors['angie']; } }
/** * This mess of a code is probably not one of my highlights in my code * writing career. It's logically organized, badly architectured but I can * still maintain it - and it works! */ public function onAdd($tpl = null) { AkeebaStrapper::addJSfile('media://com_akeeba/js/backup.js'); /** @var AkeebaModelBackups $model */ $model = $this->getModel(); // Load the Status Helper if (!class_exists('AkeebaHelperStatus')) { JLoader::import('helpers.status', JPATH_COMPONENT_ADMINISTRATOR); } $helper = AkeebaHelperStatus::getInstance(); // Determine default description JLoader::import('joomla.utilities.date'); $jregistry = JFactory::getConfig(); $tzDefault = $jregistry->get('offset'); $user = JFactory::getUser(); $tz = $user->getParam('timezone', $tzDefault); $dateNow = new JDate('now', $tz); $default_description = JText::_('BACKUP_DEFAULT_DESCRIPTION') . ' ' . $dateNow->format(JText::_('DATE_FORMAT_LC2'), true); $default_description = AkeebaHelperEscape::escapeJS($default_description, "'"); $backup_description = $model->getState('description', $default_description); $comment = $model->getState('comment', ''); // Get a potential return URL $returnurl = $model->getState('returnurl'); if (empty($returnurl)) { $returnurl = ''; } // Only allow internal URLs for the redirection if (!JUri::isInternal($returnurl)) { $returnurl = ''; } // If a return URL is set *and* the profile's name is "Site Transfer // Wizard", we are running the Site Transfer Wizard if (!class_exists('AkeebaModelProfiles')) { JLoader::import('models.profiles', JPATH_COMPONENT_ADMINISTRATOR); } /** @var AkeebaModelCpanels $cpanelmodel */ $cpanelmodel = F0FModel::getAnInstance('Cpanels', 'AkeebaModel'); $profilemodel = new AkeebaModelProfiles(); $profilemodel->setId($cpanelmodel->getProfileID()); $profile_data = $profilemodel->getProfile(); // Get the domain details from scripting facility $registry = Factory::getConfiguration(); $tag = $model->getState('tag'); $script = $registry->get('akeeba.basic.backup_type', 'full'); $scripting = Factory::getEngineParamsProvider()->loadScripting(); $domains = array(); if (!empty($scripting)) { foreach ($scripting['scripts'][$script]['chain'] as $domain) { $description = JText::_($scripting['domains'][$domain]['text']); $domain_key = $scripting['domains'][$domain]['domain']; $domains[] = array($domain_key, $description); } } $json_domains = AkeebaHelperEscape::escapeJS(json_encode($domains), '"\\'); // Get the maximum execution time and bias $maxexec = $registry->get('akeeba.tuning.max_exec_time', 14) * 1000; $bias = $registry->get('akeeba.tuning.run_time_bias', 75); // Check if the output directory is writable $quirks = Factory::getConfigurationChecks()->getDetailedStatus(); $unwritableOutput = array_key_exists('001', $quirks); // Pass on data $this->haserrors = !$helper->status; $this->hasquirks = $helper->hasQuirks(); $this->quirks = $helper->getQuirksCell(!$helper->status); $this->description = $backup_description; $this->default_descr = $default_description; $this->comment = $comment; $this->domains = $json_domains; $this->maxexec = $maxexec; $this->bias = $bias; $this->useiframe = $registry->get('akeeba.basic.useiframe', 0) ? 'true' : 'false'; $this->returnurl = $returnurl; $this->unwritableoutput = $unwritableOutput; if ($registry->get('akeeba.advanced.archiver_engine', 'jpa') == 'jps') { $this->showjpskey = 1; $this->jpskey = $registry->get('engine.archiver.jps.key', ''); } else { $this->showjpskey = 0; } if (AKEEBA_PRO) { $this->showangiekey = 1; $this->angiekey = $registry->get('engine.installer.angie.key', ''); } else { $this->showangiekey = 0; $this->angiekey = ''; } $this->autostart = $model->getState('autostart'); // Pass on profile info $this->profileid = $cpanelmodel->getProfileID(); // Active profile ID $this->profilelist = $cpanelmodel->getProfilesList(); // List of available profiles // Should I ask for permission to display desktop notifications? JLoader::import('joomla.application.component.helper'); $this->desktop_notifications = \Akeeba\Engine\Util\Comconfig::getValue('desktop_notifications', '0') ? 1 : 0; // Set the toolbar title $subtitle = JText::_('BACKUP'); JToolBarHelper::title(JText::_('AKEEBA') . ':: <small>' . $subtitle . '</small>', 'akeeba'); return true; }
/** * Get a list of backup domain keys and titles * * @return array */ private function getDomains() { $engineConfiguration = Factory::getConfiguration(); $script = $engineConfiguration->get('akeeba.basic.backup_type', 'full'); $scripting = Factory::getEngineParamsProvider()->loadScripting(); $domains = array(); if (empty($scripting)) { return $domains; } foreach ($scripting['scripts'][$script]['chain'] as $domain) { $description = JText::_($scripting['domains'][$domain]['text']); $domain_key = $scripting['domains'][$domain]['domain']; $domains[] = array($domain_key, $description); } return $domains; }
/** * Reverse engineers the View definitions of this database * * @param DriverBase $dbi Database connection to INFORMATION_SCHEMA */ protected function reverse_engineer_views(&$dbi) { $schema_name = $this->database; $sql = 'SELECT * FROM [INFORMATION_SCHEMA].[VIEWS] WHERE [table_catalog] = ' . $dbi->quote($schema_name); $dbi->setQuery($sql); $all_views = $dbi->loadObjectList(); $registry = Factory::getConfiguration(); $root = $registry->get('volatile.database.root', '[SITEDB]'); // If we have filters, make sure the tables pass the filtering $filters = Factory::getFilters(); // First pass: populate the table_name_map if (!empty($all_views)) { foreach ($all_views as $table_object) { // Extract the table name $table_name = $table_object->TABLE_NAME; // Filter and convert if (substr($table_name, 0, 3) == '#__') { $warningMessage = __CLASS__ . " :: Table {$table_name} has a prefix of #__. This would cause restoration errors; table skipped."; $this->setWarning($warningMessage); Factory::getLog()->log(LogLevel::WARNING, $warningMessage); continue; } $table_abstract = $this->getAbstract($table_name); if (substr($table_abstract, 0, 4) != 'bak_') { // Apply exclusion filters if (!$filters->isFiltered($table_abstract, $root, 'dbobject', 'all')) { Factory::getLog()->log(LogLevel::INFO, __CLASS__ . " :: Adding {$table_name} (internal name {$table_abstract})"); $this->table_name_map[$table_name] = $table_abstract; } else { Factory::getLog()->log(LogLevel::INFO, __CLASS__ . " :: Skipping {$table_name} (internal name {$table_abstract})"); continue; } } else { Factory::getLog()->log(LogLevel::INFO, __CLASS__ . " :: Backup view {$table_name} automatically skipped."); continue; } } } // Second pass: get the create commands if (!empty($all_views)) { foreach ($all_views as $table_object) { // Extract the table name $table_name = $table_object->TABLE_NAME; if (!in_array($table_name, $this->table_name_map)) { // Skip any views which have been filtered out continue; } $table_abstract = $this->getAbstract($table_name); // Still here? The view is added. We now have to store its // create command, dependency info and so on $new_entry = array('type' => 'view', 'dump_records' => false); $dependencies = array(); $table_sql = $table_object->VIEW_DEFINITION; $old_table_sql = $table_sql; foreach ($this->table_name_map as $ref_normal => $ref_abstract) { if ($pos = strpos($table_sql, ".{$ref_normal}")) { // Add a reference hit $this->dependencies[$ref_normal][] = $table_name; // Add the dependency to this table's metadata $dependencies[] = $ref_normal; // Do the replacement $table_sql = str_replace(".{$ref_normal}", ".{$ref_abstract}", $table_sql); } } // On DB only backup we don't want any replacing to take place, do we? if (!Factory::getEngineParamsProvider()->getScriptingParameter('db.abstractnames', 1)) { $table_sql = $old_table_sql; } // Replace newlines with spaces $table_sql = str_replace("\n", " ", $table_sql) . ";\n"; $table_sql = str_replace("\r", " ", $table_sql); $table_sql = str_replace("\t", " ", $table_sql); $new_entry['create'] = $table_sql; $new_entry['dependencies'] = $dependencies; $this->tables_data[$table_name] = $new_entry; } } }
protected function is_excluded_by_api($test, $root) { static $filter_switch = null; static $last_backup = null; if (is_null($filter_switch)) { $config = Factory::getConfiguration(); $filter_switch = Factory::getEngineParamsProvider()->getScriptingParameter('filter.incremental', 0); $filter_switch = $filter_switch == 1; $last_backup = $config->get('volatile.filter.last_backup', null); if (is_null($last_backup) && $filter_switch) { // Get a list of backups on this profile $backups = Platform::getInstance()->get_statistics_list(array('filters' => array(array('field' => 'profile_id', 'value' => Platform::getInstance()->get_active_profile())))); // Find this backup's ID $model = Factory::getStatistics(); $id = $model->getId(); if (is_null($id)) { $id = -1; } // Initialise $last_backup = time(); $now = $last_backup; // Find the last time a successful backup with this profile was made if (count($backups)) { foreach ($backups as $backup) { // Skip the current backup if ($backup['id'] == $id) { continue; } // Skip non-complete backups if ($backup['status'] != 'complete') { continue; } $tzUTC = new \DateTimeZone('UTC'); $dateTime = new \DateTime($backup['backupstart'], $tzUTC); $backuptime = $dateTime->getTimestamp(); $last_backup = $backuptime; break; } } if ($last_backup == $now) { // No suitable backup found; disable this filter $config->set('volatile.scripting.incfile.filter.incremental', 0); $filter_switch = false; } else { // Cache the last backup timestamp $config->set('volatile.filter.last_backup', $last_backup); } } } if (!$filter_switch) { return false; } // Get the filesystem path for $root $config = Factory::getConfiguration(); $fsroot = $config->get('volatile.filesystem.current_root', ''); $ds = $fsroot == '' || $fsroot == '/' ? '' : DIRECTORY_SEPARATOR; $filename = $fsroot . $ds . $test; // Get the timestamp of the file $timestamp = @filemtime($filename); // If we could not get this information, include the file in the archive if ($timestamp === false) { return false; } // Compare it with the last backup timestamp and exclude if it's older than the last backup if ($timestamp <= $last_backup) { //Factory::getLog()->log(LogLevel::DEBUG, "Excluding $filename due to incremental backup restrictions"); return true; } // No match? Just include the file! return false; }
protected function _prepare() { // Intialize the timer class $timer = Factory::getTimer(); // Do we have a tag? if (!empty($this->_parametersArray['tag'])) { $this->tag = $this->_parametersArray['tag']; } // Make sure a tag exists (or create a new one) $this->tag = $this->getTag(); // Reset the log $logTag = $this->getLogTag(); Factory::getLog()->open($logTag); Factory::getLog()->reset($logTag); if (!static::$registeredErrorHandler) { static::$registeredErrorHandler = true; set_error_handler('\\Akeeba\\Engine\\Core\\akeebaBackupErrorHandler'); } // Reset the storage $factoryStorageTag = $this->tag . (empty($this->backup_id) ? '' : '.' . $this->backup_id); Factory::getFactoryStorage()->reset($factoryStorageTag); // Apply the configuration overrides $overrides = Platform::getInstance()->configOverrides; if (is_array($overrides) && @count($overrides)) { $registry = Factory::getConfiguration(); $protected_keys = $registry->getProtectedKeys(); $registry->resetProtectedKeys(); foreach ($overrides as $k => $v) { $registry->set($k, $v); } $registry->setProtectedKeys($protected_keys); } // Get the domain chain $this->domain_chain = Factory::getEngineParamsProvider()->getDomainChain(); $this->total_steps = count($this->domain_chain) - 1; // Init shouldn't count in the progress bar // Mark this engine for Nesting Logging $this->nest_logging = true; // Preparation is over $this->array_cache = null; $this->setState('prepared'); //restore_error_handler(); }
/** * Creates a new dump part */ protected function getNextDumpPart() { // On database dump only mode we mustn't create part files! if (Factory::getEngineParamsProvider()->getScriptingParameter('db.saveasname', 'normal') == 'output') { return false; } // If the archiver is still processing, quit $finished = true; $configuration = Factory::getConfiguration(); $archiver = Factory::getArchiverEngine(); if ($configuration->get('volatile.engine.archiver.processingfile', false)) { return false; } // We have to add the dump file to the archive $this->closeFile(); Factory::getLog()->log(LogLevel::DEBUG, "Adding the SQL dump part to the archive"); $archiver->addFileRenamed($this->tempFile, $this->saveAsName); if ($this->getError()) { return false; } $finished = !$configuration->get('volatile.engine.archiver.processingfile', false); if (!$finished) { return false; } // Return if the file didn't finish getting added to the archive // Remove the old file Factory::getLog()->log(LogLevel::DEBUG, "Removing dump part's temporary file"); Factory::getTempFiles()->unregisterAndDeleteTempFile($this->tempFile, true); // Create the new dump part $this->partNumber++; $this->getBackupFilePaths($this->partNumber); $null = null; $this->writeline($null); return true; }