public function &getExtraSQL($root) { $empty = ''; if ($root != '[SITEDB]') { return $empty; } $sql = ''; $db = AEFactory::getDatabase(); $this->getFilters(null); // Forcibly reload the filter data // Loop all components and add SQL statements if (!empty($this->filter_data)) { foreach ($this->filter_data as $type => $items) { if (!empty($items)) { // Make sure that DB only backups get the correct prefix $configuration = AEFactory::getConfiguration(); $abstract = AEUtilScripting::getScriptingParameter('db.abstractnames', 1); if ($abstract) { $prefix = '#__'; } else { $prefix = $db->getPrefix(); } foreach ($items as $item) { if (!$this->joomla16) { $sql .= 'DELETE FROM ' . $db->quoteName($prefix . 'components') . ' WHERE ' . $db->quoteName('option') . ' = ' . $db->Quote($item) . ";\n"; } else { $sql .= 'DELETE FROM ' . $db->quoteName($prefix . 'extensions') . ' WHERE ' . $db->quoteName('element') . ' = ' . $db->Quote($item) . " AND " . $db->quoteName('type') . ' = ' . $db->Quote('component') . ";\n"; } $sql .= 'DELETE FROM ' . $db->quoteName($prefix . 'menu') . ' WHERE ' . $db->quoteName('type') . ' = ' . $db->Quote('component') . ' AND ' . $db->quoteName('link') . ' LIKE ' . $db->Quote('%option=' . $item . '%') . ";\n"; } } } } return $sql; }
public function &getExtraSQL($root) { $empty = ''; if ($root != '[SITEDB]') { return $empty; } $sql = ''; $db = AEFactory::getDatabase(); $this->getFilters(null); // Forcibly reload the filter data // Loop all components and add SQL statements if (!empty($this->filter_data)) { foreach ($this->filter_data as $type => $items) { if (!empty($items)) { // Make sure that DB only backups get the correct prefix $configuration = AEFactory::getConfiguration(); $abstract = AEUtilScripting::getScriptingParameter('db.abstractnames', 1); if ($abstract) { $prefix = '#__'; } else { $prefix = $db->getPrefix(); } foreach ($items as $item) { $client = $type == 'frontend' ? 0 : 1; $sql .= 'DELETE FROM ' . $db->quoteName($prefix . 'modules_menu') . ' WHERE ' . $db->quoteName('moduleid') . ' IN (' . 'SELECT ' . $db->quoteName('id') . ' FROM ' . $db->quoteName($prefix . 'modules') . ' WHERE ' . '(' . $db->quoteName('module') . ' = ' . $db->Quote($item) . ')' . ' AND (' . $db->quoteName('client_id') . ' = ' . $db->Quote($client) . ')' . ");\n"; $sql .= 'DELETE FROM ' . $db->quoteName($prefix . 'modules') . ' WHERE ' . '(' . $db->quoteName('module') . ' = ' . $db->Quote($item) . ')' . ' AND (' . $db->quoteName('client_id') . ' = ' . $db->Quote($client) . ')' . ";\n"; $sql .= 'DELETE FROM ' . $db->quoteName($prefix . 'extensions') . ' WHERE ' . $db->quoteName('element') . ' = ' . $db->Quote($item) . " AND " . $db->quoteName('type') . ' = ' . $db->Quote('module') . ";\n"; } } } } return $sql; }
/** * Find where to store the backup files * @param $partNumber int The SQL part number, default is 0 (.sql) */ protected function getBackupFilePaths($partNumber = 0) { AEUtilLogger::WriteLog(_AE_LOG_DEBUG, 'XXX ' . __CLASS__ . " :: Getting temporary file"); $this->tempFile = AEUtilTempfiles::registerTempFile(dechex(crc32(microtime())) . '.sql'); AEUtilLogger::WriteLog(_AE_LOG_DEBUG, 'XXX ' . __CLASS__ . " :: Temporary file is {$this->tempFile}"); // Get the base name of the dump file $partNumber = intval($partNumber); $baseName = $this->dumpFile; if ($partNumber > 0) { // The file names are in the format dbname.sql, dbname.s01, dbname.s02, etc if (strtolower(substr($baseName, -4)) == '.sql') { $baseName = substr($baseName, 0, -4) . '.s' . sprintf('%02u', $partNumber); } else { $baseName = $baseName . '.s' . sprintf('%02u', $partNumber); } } switch (AEUtilScripting::getScriptingParameter('db.saveasname', 'normal')) { case 'output': // The SQL file will be stored uncompressed in the output directory $statistics =& AEFactory::getStatistics(); $statRecord = $statistics->getRecord(); $this->saveAsName = $statRecord['absolute_path']; break; case 'normal': // The SQL file will be stored in the SQL root of the archive, as // specified by the particular embedded installer's settings $this->saveAsName = $this->installerSettings->sqlroot . '/' . $baseName; break; case 'short': // The SQL file will be stored on archive's root $this->saveAsName = $baseName; break; } if ($partNumber > 0) { AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "AkeebaDomainDBBackup :: Creating new SQL dump part #{$partNumber}"); } AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "AkeebaDomainDBBackup :: SQL temp file is " . $this->tempFile); AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "AkeebaDomainDBBackup :: SQL file location in archive is " . $this->saveAsName); }
/** * 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'); }
/** * Populates database_list with the list of databases in the settings * */ private function populate_database_list() { // Get database inclusion filters $filters = AEFactory::getFilters(); $this->database_list = $filters->getInclusions('db'); // Error propagation $this->propagateFromObject($filters); if ($this->getError()) { return false; } if (AEUtilScripting::getScriptingParameter('db.skipextradb', 0)) { // On database only backups we prune extra databases AEUtilLogger::WriteLog(_AE_LOG_DEBUG, __CLASS__ . " :: Adding only main database"); if (count($this->database_list) > 1) { $this->database_list = array_slice($this->database_list, 0, 1); } } }
/** * 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 */ private function get_create($table_abstract, $table_name, &$type, &$dependencies) { $configuration = AEFactory::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(); AEUtilLogger::WriteLog(_AE_LOG_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 Joomla! 1.6 from MySQL 5.1 to MySQL 5.0 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 (!AEUtilScripting::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: $table_sql = str_replace($table_name, $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); } } } // On DB only backup we don't want any replacing to take place, do we? if (!AEUtilScripting::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 (AEUtilScripting::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; }
protected function is_excluded_by_api($test, $root) { static $filter_switch; static $last_backup; if (is_null($filter_switch)) { $config = AEFactory::getConfiguration(); $filter_switch = AEUtilScripting::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 = AEPlatform::getInstance()->get_statistics_list(array('filters' => AEPlatform::getInstance()->get_active_profile())); // Find this backup's ID $model = AEFactory::getStatistics(); $id = $model->getId(); if (is_null($id)) { $id = -1; } // Initialise JLoader::import('joomla.utilities.date'); $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; } $jdate = new JDate($backup['backupstart']); $backuptime = $jdate->toUnix(); $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 = AEFactory::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) { //AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Excluding $filename due to incremental backup restrictions"); return true; } // No match? Just include the file! return false; }
/** * Reverse engineers the View definitions of this database * * @param AEAbstractDriver $dbi Database connection to INFORMATION_SCHEMA */ protected function reverse_engineer_views(&$dbi) { // @TODO - THIS IS NOT PORTED TO SQL SERVER YET! $schema_name = $this->database; $sql = 'SELECT * FROM `views` WHERE `table_schema` = ' . $dbi->quote($schema_name); $dbi->setQuery($sql); $all_views = $dbi->loadObjectList(); $registry = AEFactory::getConfiguration(); $root = $registry->get('volatile.database.root', '[SITEDB]'); // If we have filters, make sure the tables pass the filtering $filters = AEFactory::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) == '#__') { AEUtilLogger::WriteLog(_AE_LOG_WARNING, __CLASS__ . " :: Table {$table_name} has a prefix of #__. This would cause restoration errors; table skipped."); 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')) { AEUtilLogger::WriteLog(_AE_LOG_INFO, __CLASS__ . " :: Adding {$table_name} (internal name {$table_abstract})"); $this->table_name_map[$table_name] = $table_abstract; } else { AEUtilLogger::WriteLog(_AE_LOG_INFO, __CLASS__ . " :: Skipping {$table_name} (internal name {$table_abstract})"); continue; } } else { AEUtilLogger::WriteLog(_AE_LOG_INFO, __CLASS__ . " :: Backup table {$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 = 'CREATE OR REPLACE VIEW `' . $table_name . '` AS ' . $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 (!AEUtilScripting::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; } } }
/** * Creates a new dump part */ protected function getNextDumpPart() { // On database dump only mode we mustn't create part files! if (AEUtilScripting::getScriptingParameter('db.saveasname', 'normal') == 'output') { return false; } // If the archiver is still processing, quit $finished = true; $configuration = AEFactory::getConfiguration(); $archiver = AEFactory::getArchiverEngine(); if ($configuration->get('volatile.engine.archiver.processingfile', false)) { return false; } // We have to add the dump file to the archive $this->closeFile(); AEUtilLogger::WriteLog(_AE_LOG_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 AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Removing dump part's temporary file"); AEUtilTempfiles::unregisterAndDeleteTempFile($this->tempFile, true); // Create the new dump part $this->partNumber++; $this->getBackupFilePaths($this->partNumber); $null = null; $this->writeline($null); return true; }
/** * 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 */ private function get_create( $table_abstract, $table_name, &$type, &$dependencies ) { $configuration =& AEFactory::getConfiguration(); $notracking = $configuration->get('engine.dump.native.nodependencies', 0); $db =& $this->getDB(); if($this->getError()) return; switch($type) { case 'table': case 'merge': case 'view': $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 ); $temp = $db->loadRowList(); if( in_array($type, array('procedure','function','trigger')) ) { $table_sql = $temp[0][2]; } 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 Joomla! 1.6 from MySQL 5.1 to MySQL 5.0 if($configuration->get('engine.dump.native.nobtree',1)) { $table_sql = str_replace(' USING BTREE',' ',$table_sql); $table_sql = str_replace(' USING HASH',' ',$table_sql); } // # Fix 3.2.3 (reverts changes in 3.2.1): Translate TYPE= to ENGINE= if($configuration->get('engine.dump.common.mysql_compatibility',1)) { // MySQL 4.0 compatibility $table_sql = str_replace('ENGINE=','TYPE=',$table_sql); } else { // Default compatibility $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( !AEUtilScripting::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: $table_sql = str_replace( $table_name , $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); } } } // On DB only backup we don't want any replacing to take place, do we? if( !AEUtilScripting::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 = strpos($table_sql, ' PROCEDURE '); $table_sql = 'CREATE'.substr($table_sql, $pos_entity); } elseif($type == 'function') { $pos_entity = strpos($table_sql, ' FUNCTION '); $table_sql = 'CREATE'.substr($table_sql, $pos_entity); } elseif($type == 'trigger') { $pos_entity = strpos($table_sql, ' TRIGGER '); $table_sql = 'CREATE'.substr($table_sql, $pos_entity); } // Add DROP statements for DB only backup if( AEUtilScripting::getScriptingParameter('db.dropstatements',0) ) { if( ($type == 'table') || ($type == 'merge') ) { // Table or merge tables, get a DROP TABLE statement $drop = "DROP TABLE IF EXISTS `$table_name`;\n"; } elseif($type == 'view') { // Views get a DROP VIEW statement $drop = "DROP VIEW IF EXISTS `$table_name`;\n"; } elseif($type == 'procedure') { // Procedures get a DROP PROCEDURE statement and proper delimiter strings $drop = "DROP PROCEDURE IF EXISTS `$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 `$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 `$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; }
/** * Returns the relative and absolute path to the archive, if defined * * @param string $relative The relative path * @param string $absolute The absolute path */ public static function get_archive_name(&$relative, &$absolute) { static $relative_path = null; static $absolute_path = null; if (is_null($relative_path) || is_null($absolute_path)) { $registry = AEFactory::getConfiguration(); // Import volatile scripting keys to the registry AEUtilScripting::importScriptingToRegistry(); // Determine the extension $force_extension = AEUtilScripting::getScriptingParameter('core.forceextension', null); if (is_null($force_extension)) { $archiver = AEFactory::getArchiverEngine(); $extension = $archiver->getExtension(); } else { $extension = $force_extension; } // Get the template name $templateName = $registry->get('akeeba.basic.archive_name'); AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Archive template name: {$templateName}"); // Parse all tags $templateName = self::replace_archive_name_variables($templateName); AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Expanded template name: {$templateName}"); $ds = DIRECTORY_SEPARATOR; $relative_path = $templateName . $extension; $absolute_path = AEUtilFilesystem::TranslateWinPath($registry->get('akeeba.basic.output_directory') . $ds . $relative_path); } $relative = $relative_path; $absolute = $absolute_path; }