Exemplo n.º 1
0
 /**
  * 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);
 }
Exemplo n.º 2
0
 /**
  * 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');
 }
Exemplo n.º 3
0
 /**
  * Creates a new archive part
  * @param bool $finalPart Set to true if it is the final part (therefore has the .jps extension)
  */
 private function _createNewPart($finalPart = false)
 {
     // Push the previous part if we have to post-process it immediately
     $configuration = AEFactory::getConfiguration();
     if ($configuration->get('engine.postproc.common.after_part', 0)) {
         $this->finishedPart[] = $this->_dataFileName;
     }
     $this->_totalFragments++;
     $this->_currentFragment = $this->_totalFragments;
     if ($finalPart) {
         $this->_dataFileName = $this->_dataFileNameBase . '.jps';
     } else {
         $this->_dataFileName = $this->_dataFileNameBase . '.j' . sprintf('%02d', $this->_currentFragment);
     }
     AEUtilLogger::WriteLog(_AE_LOG_INFO, 'Creating new JPS part #' . $this->_currentFragment . ', file ' . $this->_dataFileName);
     // Inform that we have chenged the multipart number
     $statistics = AEFactory::getStatistics();
     $statistics->updateMultipart($this->_totalFragments);
     // Try to remove any existing file
     @unlink($this->_dataFileName);
     // Touch the new file
     $result = @touch($this->_dataFileName);
     if (function_exists('chmod')) {
         chmod($this->_dataFileName, 0666);
     }
     return $result;
 }
Exemplo n.º 4
0
 /**
  * Performs one more step of dumping database data
  * @return type
  */
 protected function stepDatabaseDump()
 {
     // Initialize local variables
     $db = $this->getDB();
     if ($this->getError()) {
         return;
     }
     if (!is_object($db) || $db === false) {
         $this->setError(__CLASS__ . '::_run() Could not connect to database?!');
         return;
     }
     $outData = '';
     // Used for outputting INSERT INTO commands
     $this->enforceSQLCompatibility();
     // Apply MySQL compatibility option
     if ($this->getError()) {
         return;
     }
     // Touch SQL dump file
     $nada = "";
     $this->writeline($nada);
     // Get this table's information
     $tableName = $this->nextTable;
     $this->setStep($tableName);
     $this->setSubstep('');
     $tableAbstract = trim($this->table_name_map[$tableName]);
     $dump_records = $this->tables_data[$tableName]['dump_records'];
     // If it is the first run, find number of rows and get the CREATE TABLE command
     if ($this->nextRange == 0) {
         if ($this->getError()) {
             return;
         }
         $outCreate = '';
         if (is_array($this->tables_data[$tableName])) {
             if (array_key_exists('create', $this->tables_data[$tableName])) {
                 $outCreate = $this->tables_data[$tableName]['create'];
             }
         }
         if (empty($outCreate) && !empty($tableName)) {
             // The CREATE command wasn't cached. Time to create it. The $type and $dependencies
             // variables will be thrown away.
             $type = 'table';
             $dependencies = array();
             $outCreate = $this->get_create($tableAbstract, $tableName, $type, $dependencies);
         }
         // Create drop statements if required (the key is defined by the scripting engine)
         $configuration = AEFactory::getConfiguration();
         if (AEUtilScripting::getScriptingParameter('db.dropstatements', 0)) {
             if (array_key_exists('create', $this->tables_data[$tableName])) {
                 // @todo This looks cheesy...
                 $dropStatement = $this->createDrop($this->tables_data[$tableName]['create']);
             } else {
                 $type = 'table';
                 $createStatement = $this->get_create($tableAbstract, $tableName, $type, $dependencies);
                 $dropStatement = $this->createDrop($createStatement);
             }
             if (!empty($dropStatement)) {
                 $dropStatement .= "\n";
                 if (!$this->writeDump($dropStatement)) {
                     return;
                 }
             }
         }
         // Write the CREATE command after any DROP command which might be necessary.
         if (!$this->writeDump($outCreate)) {
             return;
         }
         if ($dump_records) {
             // We are dumping data from a table, get the row count
             $this->getRowCount($tableAbstract);
         } else {
             // We should not dump any data
             AEUtilLogger::WriteLog(_AE_LOG_INFO, "Skipping dumping data of " . $tableAbstract);
             $this->maxRange = 0;
             $this->nextRange = 1;
             $outData = '';
             $numRows = 0;
         }
         // Output any data preamble commands, e.g. SET IDENTITY_INSERT for SQL Server
         if ($dump_records && AEUtilScripting::getScriptingParameter('db.dropstatements', 0)) {
             AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Writing data dump preamble for " . $tableAbstract);
             $preamble = $this->getDataDumpPreamble($tableAbstract, $tableName, $this->maxRange);
             if (!empty($preamble)) {
                 if (!$this->writeDump($preamble)) {
                     return;
                 }
             }
         }
     }
     // Check if we have more work to do on this table
     $configuration = AEFactory::getConfiguration();
     $batchsize = intval($configuration->get('engine.dump.common.batchsize', 1000));
     if ($batchsize <= 0) {
         $batchsize = 1000;
     }
     if ($this->nextRange < $this->maxRange) {
         $timer = AEFactory::getTimer();
         // Get the number of rows left to dump from the current table
         $sql = $db->getQuery(true)->select('*')->from($db->nameQuote($tableAbstract));
         if ($this->nextRange == 0) {
             // First run, get a cursor to all records
             $db->setQuery($sql, 0, $batchsize);
             AEUtilLogger::WriteLog(_AE_LOG_INFO, "Beginning dump of " . $tableAbstract);
         } else {
             // Subsequent runs, get a cursor to the rest of the records
             $db->setQuery($sql, $this->nextRange, $batchsize);
             $this->setSubstep($this->nextRange . ' / ' . $this->maxRange);
             AEUtilLogger::WriteLog(_AE_LOG_INFO, "Continuing dump of " . $tableAbstract . " from record #{$this->nextRange}");
         }
         $this->query = '';
         $numRows = 0;
         $use_abstract = AEUtilScripting::getScriptingParameter('db.abstractnames', 1);
         $filters = AEFactory::getFilters();
         $mustFilter = $filters->hasFilterType('dbobject', 'children');
         try {
             $cursor = $db->query();
         } catch (Exception $exc) {
             $db->resetErrors();
             $cursor = null;
         }
         while (is_array($myRow = $db->fetchAssoc()) && $numRows < $this->maxRange - $this->nextRange) {
             $this->createNewPartIfRequired();
             $numRows++;
             $numOfFields = count($myRow);
             // On MS SQL Server there's always a RowNumber pseudocolumn added at the end, screwing up the backup (GRRRR!)
             if ($db->getDriverType() == 'mssql') {
                 $numOfFields--;
             }
             // If row-level filtering is enabled, please run the filtering
             if ($mustFilter) {
                 $isFiltered = $filters->isFiltered(array('table' => $tableAbstract, 'row' => $myRow), $configuration->get('volatile.database.root', '[SITEDB]'), 'dbobject', 'children');
                 if ($isFiltered) {
                     continue;
                 }
             }
             if (!$this->extendedInserts || $this->extendedInserts && empty($this->query)) {
                 $newQuery = true;
                 $fieldList = $this->getFieldListSQL(array_keys($myRow), $numOfFields);
                 if ($numOfFields > 0) {
                     $this->query = "INSERT INTO " . $db->nameQuote(!$use_abstract ? $tableName : $tableAbstract) . " {$fieldList} VALUES ";
                 }
             } else {
                 // On other cases, just mark that we should add a comma and start a new VALUES entry
                 $newQuery = false;
             }
             $outData = '(';
             // Step through each of the row's values
             $fieldID = 0;
             // Used in running backup fix
             $isCurrentBackupEntry = false;
             // Fix 1.2a - NULL values were being skipped
             if ($numOfFields > 0) {
                 foreach ($myRow as $value) {
                     // The ID of the field, used to determine placement of commas
                     $fieldID++;
                     if ($fieldID > $numOfFields) {
                         // This is required for SQL Server backups, do NOT remove!
                         continue;
                     }
                     // Fix 2.0: Mark currently running backup as successful in the DB snapshot
                     if ($tableAbstract == '#__ak_stats') {
                         if ($fieldID == 1) {
                             // Compare the ID to the currently running
                             $statistics = AEFactory::getStatistics();
                             $isCurrentBackupEntry = $value == $statistics->getId();
                         } elseif ($fieldID == 6) {
                             // Treat the status field
                             $value = $isCurrentBackupEntry ? 'complete' : $value;
                         }
                     }
                     // Post-process the value
                     if (is_null($value)) {
                         $outData .= "NULL";
                         // Cope with null values
                     } else {
                         // Accommodate for runtime magic quotes
                         $value = @get_magic_quotes_runtime() ? stripslashes($value) : $value;
                         $value = $db->Quote($value);
                         if ($this->postProcessValues) {
                             $value = $this->postProcessQuotedValue($value);
                         }
                         $outData .= $value;
                     }
                     if ($fieldID < $numOfFields) {
                         $outData .= ', ';
                     }
                 }
             }
             $outData .= ')';
             if ($numOfFields) {
                 // If it's an existing query and we have extended inserts
                 if ($this->extendedInserts && !$newQuery) {
                     // Check the existing query size
                     $query_length = strlen($this->query);
                     $data_length = strlen($outData);
                     if ($query_length + $data_length > $this->packetSize) {
                         // We are about to exceed the packet size. Write the data so far.
                         $this->query .= ";\n";
                         if (!$this->writeDump($this->query)) {
                             return;
                         }
                         // Then, start a new query
                         $this->query = '';
                         $this->query = "INSERT INTO " . $db->nameQuote(!$use_abstract ? $tableName : $tableAbstract) . " VALUES ";
                         $this->query .= $outData;
                     } else {
                         // We have room for more data. Append $outData to the query.
                         $this->query .= ', ';
                         $this->query .= $outData;
                     }
                 } elseif ($this->extendedInserts && $newQuery) {
                     // Append the data to the INSERT statement
                     $this->query .= $outData;
                     // Let's see the size of the dumped data...
                     $query_length = strlen($this->query);
                     if ($query_length >= $this->packetSize) {
                         // This was a BIG query. Write the data to disk.
                         $this->query .= ";\n";
                         if (!$this->writeDump($this->query)) {
                             return;
                         }
                         // Then, start a new query
                         $this->query = '';
                     }
                 } else {
                     // Append the data to the INSERT statement
                     $this->query .= $outData;
                     // Write the data to disk.
                     $this->query .= ";\n";
                     if (!$this->writeDump($this->query)) {
                         return;
                     }
                     // Then, start a new query
                     $this->query = '';
                 }
             }
             $outData = '';
             unset($myRow);
             // Check for imminent timeout
             if ($timer->getTimeLeft() <= 0) {
                 AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Breaking dump of {$tableAbstract} after {$numRows} rows; will continue on next step");
                 break;
             }
         }
         $db->freeResult($cursor);
         // Advance the _nextRange pointer
         $this->nextRange += $numRows != 0 ? $numRows : 1;
         $this->setStep($tableName);
         $this->setSubstep($this->nextRange . ' / ' . $this->maxRange);
     }
     // Finalize any pending query
     // WARNING! If we do not do that now, the query will be emptied in the next operation and all
     // accumulated data will go away...
     if (!empty($this->query)) {
         $this->query .= ";\n";
         if (!$this->writeDump($this->query)) {
             return;
         }
         $this->query = '';
     }
     // Check for end of table dump (so that it happens inside the same operation)
     if (!($this->nextRange < $this->maxRange)) {
         // Tell the user we are done with the table
         AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Done dumping " . $tableAbstract);
         // Output any data preamble commands, e.g. SET IDENTITY_INSERT for SQL Server
         if ($dump_records && AEUtilScripting::getScriptingParameter('db.dropstatements', 0)) {
             AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Writing data dump epilogue for " . $tableAbstract);
             $epilogue = $this->getDataDumpEpilogue($tableAbstract, $tableName, $this->maxRange);
             if (!empty($epilogue)) {
                 if (!$this->writeDump($epilogue)) {
                     return;
                 }
             }
         }
         if (count($this->tables) == 0) {
             // We have finished dumping the database!
             AEUtilLogger::WriteLog(_AE_LOG_INFO, "End of database detected; flushing the dump buffers...");
             $null = null;
             $this->writeDump($null);
             AEUtilLogger::WriteLog(_AE_LOG_INFO, "Database has been successfully dumped to SQL file(s)");
             $this->setState('postrun');
             $this->setStep('');
             $this->setSubstep('');
             $this->nextTable = '';
             $this->nextRange = 0;
         } elseif (count($this->tables) != 0) {
             // Switch tables
             $this->nextTable = array_shift($this->tables);
             $this->nextRange = 0;
             $this->setStep($this->nextTable);
             $this->setSubstep('');
         }
     }
 }
 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;
 }
Exemplo n.º 6
0
 /**
  * Returns a copy of the class's status array
  * @return array
  */
 public function getStatusArray()
 {
     if (empty($this->array_cache)) {
         // Get the default table
         $array = $this->_makeReturnTable();
         // Add the archive name
         $statistics = AEFactory::getStatistics();
         $record = $statistics->getRecord();
         $array['Archive'] = isset($record['archivename']) ? $record['archivename'] : '';
         // Translate HasRun to what the rest of the suite expects
         $array['HasRun'] = $this->getState() == 'finished' ? 1 : 0;
         // Translate no errors
         $array['Error'] = $array['Error'] == false ? '' : $array['Error'];
         $array['tag'] = $this->tag;
         $array['Progress'] = $this->getProgress();
         $this->array_cache = $array;
     }
     return $this->array_cache;
 }
Exemplo n.º 7
0
 private function _createNewPart($finalPart = false)
 {
     // Push the previous part if we have to post-process it immediately
     $configuration =& AEFactory::getConfiguration();
     if ($configuration->get('engine.postproc.common.after_part', 0)) {
         // The first part needs its header overwritten during archive
         // finalization. Skip it from immediate processing.
         if ($this->_currentFragment != 1) {
             $this->finishedPart[] = $this->_dataFileName;
         }
     }
     $this->_totalFragments++;
     $this->_currentFragment = $this->_totalFragments;
     if ($finalPart) {
         $this->_dataFileName = $this->_dataFileNameBase . '.jpa';
     } else {
         $this->_dataFileName = $this->_dataFileNameBase . '.j' . sprintf('%02d', $this->_currentFragment);
     }
     AEUtilLogger::WriteLog(_AE_LOG_INFO, 'Creating new JPA part #' . $this->_currentFragment . ', file ' . $this->_dataFileName);
     $statistics =& AEFactory::getStatistics();
     $statistics->updateMultipart($this->_totalFragments);
     // Try to remove any existing file
     @unlink($this->_dataFileName);
     // Touch the new file
     $result = @touch($this->_dataFileName);
     if (function_exists('chmod')) {
         chmod($this->_dataFileName, 0666);
     }
     // Try to write 6 bytes to it
     if ($result) {
         $result = @file_put_contents($this->_dataFileName, 'AKEEBA') == 6;
     }
     if ($result) {
         @unlink($this->_dataFileName);
         $result = @touch($this->_dataFileName);
         if (function_exists('chmod')) {
             chmod($this->_dataFileName, 0666);
         }
     }
     return $result;
 }
 /**
  * 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, __CLASS__ . " :: Getting temporary file");
     $this->tempFile = AEUtilTempfiles::registerTempFile(dechex(crc32(microtime())) . '.sql');
     AEUtilLogger::WriteLog(_AE_LOG_DEBUG, __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);
         }
     }
     if (empty($this->installerSettings)) {
         // Fetch the installer settings
         $this->installerSettings = (object) array('installerroot' => 'installation', 'sqlroot' => 'installation/sql', 'databasesini' => 1, 'readme' => 1, 'extrainfo' => 1);
         $config = AEFactory::getConfiguration();
         $installerKey = $config->get('akeeba.advanced.embedded_installer');
         $installerDescriptors = AEUtilInihelper::getInstallerList();
         if (array_key_exists($installerKey, $installerDescriptors)) {
             // The selected installer exists, use it
             $this->installerSettings = (object) $installerDescriptors[$installerKey];
         } elseif (array_key_exists('abi', $installerDescriptors)) {
             // The selected installer doesn't exist, but ABI exists; use that instead
             $this->installerSettings = (object) $installerDescriptors['abi'];
         }
     }
     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);
 }
Exemplo n.º 9
0
 /**
  * Returns a copy of the class's status array
  *
  * @return array
  */
 public function getStatusArray()
 {
     if (empty($this->array_cache)) {
         // Get the default table
         $array = $this->_makeReturnTable();
         // Get the current step number
         $stepCounter = AEFactory::getConfiguration()->get('volatile.step_counter', 0);
         // Add the archive name
         $statistics = AEFactory::getStatistics();
         $record = $statistics->getRecord();
         $array['Archive'] = isset($record['archivename']) ? $record['archivename'] : '';
         // Translate HasRun to what the rest of the suite expects
         $array['HasRun'] = $this->getState() == 'finished' ? 1 : 0;
         // Translate no errors
         $array['Error'] = $array['Error'] == false ? '' : $array['Error'];
         $array['tag'] = $this->tag;
         $array['Progress'] = $this->getProgress();
         $array['backupid'] = $this->getBackupId();
         $array['sleepTime'] = $this->waitTimeMsec;
         $array['stepNumber'] = $stepCounter;
         $array['stepState'] = $this->getState();
         $this->array_cache = $array;
     }
     return $this->array_cache;
 }
Exemplo n.º 10
0
 /**
  * Applies the size and count quotas
  *
  * @return bool
  */
 private function get_remote_quotas()
 {
     // Get all records with a remote filename
     $allRecords = AEPlatform::getInstance()->get_valid_remote_records();
     // Bail out if no records found
     if (empty($allRecords)) {
         return array();
     }
     // Try to find the files to be deleted due to quota settings
     $statistics = AEFactory::getStatistics();
     $latestBackupId = $statistics->getId();
     // Filter out the current record
     $temp = array();
     foreach ($allRecords as $item) {
         if ($item['id'] == $latestBackupId) {
             continue;
         }
         $item['files'] = $this->get_remote_files($item['remote_filename'], $item['multipart']);
         $temp[] = $item;
     }
     $allRecords = $temp;
     // Bail out if only the current backup was included in the list
     if (count($allRecords) == 0) {
         return array();
     }
     // Get quota values
     $registry = AEFactory::getConfiguration();
     $countQuota = $registry->get('akeeba.quota.count_quota');
     $sizeQuota = $registry->get('akeeba.quota.size_quota');
     $useCountQuotas = $registry->get('akeeba.quota.enable_count_quota');
     $useSizeQuotas = $registry->get('akeeba.quota.enable_size_quota');
     $useDayQuotas = $registry->get('akeeba.quota.maxage.enable');
     $daysQuota = $registry->get('akeeba.quota.maxage.maxdays');
     $preserveDay = $registry->get('akeeba.quota.maxage.keepday');
     $leftover = array();
     $ret = array();
     $killids = array();
     if ($useDayQuotas) {
         $killDatetime = new DateTime();
         $killDatetime->modify('-' . $daysQuota . ($daysQuota == 1 ? ' day' : ' days'));
         $killTS = $killDatetime->format('U');
         foreach ($allRecords as $def) {
             $backupstart = new DateTime($def['backupstart']);
             $backupTS = $backupstart->format('U');
             $backupDay = $backupstart->format('d');
             // Is this on a preserve day?
             if ($preserveDay > 0) {
                 if ($preserveDay == $backupDay) {
                     $leftover[] = $def;
                     continue;
                 }
             }
             // Otherwise, check the timestamp
             if ($backupTS < $killTS) {
                 $ret[] = $def['files'];
                 $killids[] = $def['id'];
             } else {
                 $leftover[] = $def;
             }
         }
     }
     // Do we need to apply count quotas?
     if ($useCountQuotas && $countQuota >= 1 && !$useDayQuotas) {
         $countQuota--;
         // Are there more files than the quota limit?
         if (!(count($allRecords) > $countQuota)) {
             // No, effectively skip the quota checking
             $leftover = $allRecords;
         } else {
             AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Processing remote count quotas");
             // Yes, apply the quota setting.
             $totalRecords = count($allRecords);
             for ($count = 0; $count <= $totalRecords; $count++) {
                 $def = array_pop($allRecords);
                 if (count($leftover) >= $countQuota) {
                     $ret[] = $def['files'];
                     $killids[] = $def['id'];
                 } else {
                     $leftover[] = $def;
                 }
             }
             unset($allRecords);
         }
     } else {
         // No count quotas are applied
         $leftover = $allRecords;
     }
     // Do we need to apply size quotas?
     if ($useSizeQuotas && $sizeQuota > 0 && count($leftover) > 0 && !$useDayQuotas) {
         AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Processing remote size quotas");
         // OK, let's start counting bytes!
         $runningSize = 0;
         while (count($leftover) > 0) {
             // Each time, remove the last element of the backup array and calculate
             // running size. If it's over the limit, add the archive to the $ret array.
             $def = array_pop($leftover);
             $runningSize += $def['total_size'];
             if ($runningSize >= $sizeQuota) {
                 $ret[] = $def['files'];
                 $killids[] = $def['id'];
             }
         }
     }
     // Convert the $ret 2-dimensional array to single dimensional
     $quotaFiles = array();
     foreach ($ret as $temp) {
         if (!is_array($temp) || empty($temp)) {
             continue;
         }
         foreach ($temp as $filename) {
             $quotaFiles[] = $filename;
         }
     }
     // Update the statistics record with the removed remote files
     if (!empty($killids)) {
         foreach ($killids as $id) {
             if (empty($id)) {
                 continue;
             }
             $data = array('remote_filename' => '');
             AEPlatform::getInstance()->set_or_update_statistics($id, $data, $this);
         }
     }
     return $quotaFiles;
 }
Exemplo n.º 11
0
	public function apply_srp_quotas($parent) {
		$parent->relayStep('Applying quotas');
		$parent->relaySubstep('');
		
		// If no quota settings are enabled, quit
		$registry =& AEFactory::getConfiguration();
		$srpQuotas = $registry->get('akeeba.quota.srp_size_quota');
		
		if($srpQuotas <= 0)
		{
			AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "No restore point quotas were defined; old restore point files will be kept intact" );
			return true; // No quota limits were requested
		}
		
		// Get valid-looking backup ID's
		$validIDs =& AEPlatform::get_valid_backup_records(true, array('restorepoint'));
		
		$statistics =& AEFactory::getStatistics();
		$latestBackupId = $statistics->getId();
		
		// Create a list of valid files
		$allFiles = array();
		if(count($validIDs))
		{
			foreach($validIDs as $id)
			{
				$stat = AEPlatform::get_statistics($id);
				// Multipart processing
				$filenames = AEUtilStatistics::get_all_filenames($stat, true);
				if(!is_null($filenames))
				{
					// Only process existing files
					$filesize = 0;
					foreach($filenames as $filename)
					{
						$filesize += @filesize($filename);
					}
					$allFiles[] = array('id' => $id, 'filenames' => $filenames, 'size' => $filesize);
				}
			}
		}
		unset($validIDs);
		
		// If there are no files, exit early
		if(count($allFiles) == 0)
		{
			AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "There were no old restore points to apply quotas on" );
			return true;
		}
		
		// Init arrays
		$killids = array();
		$ret = array();
		$leftover = array();
		
		// Do we need to apply size quotas?
		AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Processing restore point size quotas" );
		// OK, let's start counting bytes!
		$runningSize = 0;
		while(count($allFiles) > 0)
		{
			// Each time, remove the last element of the backup array and calculate
			// running size. If it's over the limit, add the archive to the return array.
			$def = array_pop($allFiles);
			$runningSize += $def['size'];
			if($runningSize >= $srpQuotas)
			{
				if($latestBackupId == $def['id'])
				{
					$runningSize -= $def['size'];
				}
				else
				{
					$ret[] = $def['filenames'];
					$killids[] = $def['filenames'];
				}
			}
		}
		
		// Convert the $ret 2-dimensional array to single dimensional
		$quotaFiles = array();
		foreach($ret as $temp)
		{
			foreach($temp as $filename)
			{
				$quotaFiles[] = $filename;
			}
		}
		
		// Update the statistics record with the removed remote files
		if(!empty($killids)) foreach($killids as $id) {
			$data = array('filesexist' => '0');
			AEPlatform::set_or_update_statistics($id, $data, $parent);
		}
		
		// Apply quotas
		if(count($quotaFiles) > 0)
		{
			AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Applying quotas" );
			jimport('joomla.filesystem.file');
			foreach($quotaFiles as $file)
			{
				if(!@AEPlatform::unlink($file))
				{
					$parent->setWarning("Failed to remove old system restore point file ".$file );
				}
			}
		}
		
		return true;
	}
Exemplo n.º 12
0
	/**
	 * Implements the _run() abstract method
	 */
	protected function _run()
	{
		// Check if we are already done
		if ($this->getState() == 'postrun') {
			AEUtilLogger::WriteLog(_AE_LOG_DEBUG, __CLASS__." :: Already finished");
			$this->setStep("");
			$this->setSubstep("");
			return;
		}

		// Mark ourselves as still running (we will test if we actually do towards the end ;) )
		$this->setState('running');

		// Check if we are still adding a database dump part to the archive, or if
		// we have to post-process a part
		if( AEUtilScripting::getScriptingParameter('db.saveasname','normal') != 'output' )
		{
			$archiver =& AEFactory::getArchiverEngine();
			$configuration =& AEFactory::getConfiguration();

			if($configuration->get('engine.postproc.common.after_part',0))
			{
				if(!empty($archiver->finishedPart))
				{
					$filename = array_shift($archiver->finishedPart);
					AEUtilLogger::WriteLog(_AE_LOG_INFO, 'Preparing to post process '.basename($filename));
					$post_proc =& AEFactory::getPostprocEngine();
					$result = $post_proc->processPart( $filename );
					$this->propagateFromObject($post_proc);

					if($result === false)
					{
						$this->setWarning('Failed to process file '.basename($filename));
					}
					else
					{
						AEUtilLogger::WriteLog(_AE_LOG_INFO, 'Successfully processed file '.basename($filename));
					}

					// Should we delete the file afterwards?
					if(
						$configuration->get('engine.postproc.common.delete_after',false)
						&& $post_proc->allow_deletes
						&& ($result !== false)
					)
					{
						AEUtilLogger::WriteLog(_AE_LOG_DEBUG, 'Deleting already processed file '.basename($filename));
						AEPlatform::unlink($filename);
					}

					if($post_proc->break_after) {
						$configuration->set('volatile.breakflag', true);
						return;
					}
				}
			}

			if($configuration->get('volatile.engine.archiver.processingfile',false))
			{
				// We had already started archiving the db file, but it needs more time
				$finished = true;
				AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Continuing adding the SQL dump part to the archive");
				$archiver->addFile(null,null,null);
				$this->propagateFromObject($archiver);
				if($this->getError()) return;
				$finished = !$configuration->get('volatile.engine.archiver.processingfile',false);
				if($finished)
				{
					$this->getNextDumpPart();
				}
				else
				{
					return;
				}
			}
		}

		// Initialize local variables
		$db =& $this->getDB();
		if($this->getError()) return;

		if( !is_object($db) || ($db === false) )
		{
			$this->setError(__CLASS__.'::_run() Could not connect to database?!');
			return;
		}

		$outData	= ''; // Used for outputting INSERT INTO commands

		$this->enforceSQLCompatibility(); // Apply MySQL compatibility option
		if($this->getError()) return;

		// Touch SQL dump file
		$nada = "";
		$this->writeline($nada);

		// Get this table's information
		$tableName = $this->nextTable;
		$tableAbstract = trim( $this->table_name_map[$tableName] );
		$dump_records = $this->tables_data[$tableName]['dump_records'];

		// If it is the first run, find number of rows and get the CREATE TABLE command
		if( $this->nextRange == 0 )
		{
			if($this->getError()) return;
			$outCreate = '';
			if(is_array($this->tables_data[$tableName])) {
				if(array_key_exists('create', $this->tables_data[$tableName])) {
					$outCreate = $this->tables_data[$tableName]['create'];
				}
			}
			
			if(empty($outCreate) && !empty($tableName)) {
				// The CREATE command wasn't cached. Time to create it. The $type and $dependencies
				// variables will be thrown away.
				$type = 'table';
				$outCreate = $this->get_create($tableAbstract, $tableName, $type, $dependencies);
			}

			// Write the CREATE command
			if(!$this->writeDump($outCreate)) return;

			// Create drop statements if required (the key is defined by the scripting engine)
			$configuration =& AEFactory::getConfiguration();
			if( AEUtilScripting::getScriptingParameter('db.dropstatements',0) )
			{
				if(array_key_exists('create', $this->tables_data[$tableName])) {
					// @todo This looks cheesy...
					$dropStatement = $this->createDrop($this->tables_data[$tableName]['create']);
				} else {
					$type = 'table';
					$createStatement = $this->get_create($tableAbstract, $tableName, $type, $dependencies);
					$dropStatement = $this->createDrop($createStatement);
				}
				if(!empty($dropStatement))
				{
					if(!$this->writeDump($outCreate)) return;
				}
			}

			if( $dump_records )
			{
				// We are dumping data from a table, get the row count
				$this->getRowCount( $tableAbstract );
			}
			else
			{
				// We should not dump any data
				AEUtilLogger::WriteLog(_AE_LOG_INFO, "Skipping dumping data of " . $tableAbstract);
				$this->maxRange = 0;
				$this->nextRange = 1;
				$outData = '';
				$numRows = 0;
			}
		}

		// Check if we have more work to do on this table
		$configuration =& AEFactory::getConfiguration();
		$batchsize = intval($configuration->get('engine.dump.common.batchsize', 1000));
		if($batchsize <= 0) $batchsize = 1000;
		if( ($this->nextRange < $this->maxRange) )
		{
			$timer =& AEFactory::getTimer();

			// Get the number of rows left to dump from the current table
			$sql = "SELECT * FROM `$tableAbstract`";
			if( $this->nextRange == 0 )
			{
				// First run, get a cursor to all records
				$db->setQuery( $sql, 0, $batchsize );
				AEUtilLogger::WriteLog(_AE_LOG_INFO, "Beginning dump of " . $tableAbstract);
			}
			else
			{
				// Subsequent runs, get a cursor to the rest of the records
				$db->setQuery( $sql, $this->nextRange, $batchsize );
				AEUtilLogger::WriteLog(_AE_LOG_INFO, "Continuing dump of " . $tableAbstract . " from record #{$this->nextRange}");
			}

			$this->query = '';
			$numRows = 0;
			$use_abstract = AEUtilScripting::getScriptingParameter('db.abstractnames', 1);
			while( is_array($myRow = $db->loadAssoc(false)) && ( $numRows < ($this->maxRange - $this->nextRange) ) ) {
				$this->createNewPartIfRequired();
				$numRows++;
				$numOfFields = count( $myRow );

				if(
					(!$this->extendedInserts) || // Add header on simple INSERTs, or...
					( $this->extendedInserts && empty($this->query) ) //...on extended INSERTs if there are no other data, yet
				)
				{
					$newQuery = true;
					if( $numOfFields > 0 ) $this->query = "INSERT INTO `" . (!$use_abstract ? $tableName : $tableAbstract) . "` VALUES ";
				}
				else
				{
					// On other cases, just mark that we should add a comma and start a new VALUES entry
					$newQuery = false;
				}

				$outData = '(';

				// Step through each of the row's values
				$fieldID = 0;

				// Used in running backup fix
				$isCurrentBackupEntry = false;

				// Fix 1.2a - NULL values were being skipped
				if( $numOfFields > 0 ) foreach( $myRow as $value )
				{
					// The ID of the field, used to determine placement of commas
					$fieldID++;

					// Fix 2.0: Mark currently running backup as successful in the DB snapshot
					if($tableAbstract == '#__ak_stats')
					{
						if($fieldID == 1)
						{
							// Compare the ID to the currently running
							$statistics =& AEFactory::getStatistics();
							$isCurrentBackupEntry = ($value == $statistics->getId());
						}
						elseif ($fieldID == 6)
						{
							// Treat the status field
							$value = $isCurrentBackupEntry ? 'complete' : $value;
						}
					}

					// Post-process the value
					if( is_null($value) )
					{
						$outData .= "NULL"; // Cope with null values
					} else {
						// Accommodate for runtime magic quotes
						$value = @get_magic_quotes_runtime() ? stripslashes( $value ) : $value;
						$outData .= $db->Quote($value);
					}
					if( $fieldID < $numOfFields ) $outData .= ', ';
				} // foreach
				$outData .= ')';

				if( $numOfFields )
				{
					// If it's an existing query and we have extended inserts
					if($this->extendedInserts && !$newQuery)
					{
						// Check the existing query size
						$query_length = strlen($this->query);
						$data_length = strlen($outData);
						if( ($query_length + $data_length) > $this->packetSize )
						{
							// We are about to exceed the packet size. Write the data so far.
							$this->query .= ";\n";
							if(!$this->writeDump($this->query)) return;
							// Then, start a new query
							$this->query = '';
							$this->query = "INSERT INTO `" . (!$use_abstract ? $tableName : $tableAbstract) . "` VALUES ";
							$this->query .= $outData;
						}
						else
						{
							// We have room for more data. Append $outData to the query.
							$this->query .= ', ';
							$this->query .= $outData;
						}
					}
					elseif($this->extendedInserts && $newQuery)
					// If it's a brand new insert statement in an extended INSERTs set
					{
						// Append the data to the INSERT statement
						$this->query .= $outData;
						// Let's see the size of the dumped data...
						$query_length = strlen($this->query);
						if($query_length >= $this->packetSize)
						{
							// This was a BIG query. Write the data to disk.
							$this->query .= ";\n";
							if(!$this->writeDump($this->query)) return;
							// Then, start a new query
							$this->query = '';
						}
					}
					else
					// It's a normal (not extended) INSERT statement
					{
						// Append the data to the INSERT statement
						$this->query .= $outData;
						// Write the data to disk.
						$this->query .= ";\n";
						if(!$this->writeDump($this->query)) return;
						// Then, start a new query
						$this->query = '';
					}
				}
				$outData = '';

				// Check for imminent timeout
				if( $timer->getTimeLeft() <= 0 ) {
					AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Breaking dump of $tableAbstract after $numRows rows; will continue on next step");
					break;
				}
			} // for (all rows left)

			// Advance the _nextRange pointer
			$this->nextRange += ($numRows != 0) ? $numRows : 1;

			$this->setStep($tableName);
			$this->setSubstep($this->nextRange . ' / ' . $this->maxRange);
		} // if more work on the table

		// Finalize any pending query
		// WARNING! If we do not do that now, the query will be emptied in the next operation and all
		// accumulated data will go away...
		if(!empty($this->query))
		{
			$this->query .= ";\n";
			if(!$this->writeDump($this->query)) return;
			$this->query = '';
		}

		// Check for end of table dump (so that it happens inside the same operation)
		if( !($this->nextRange < $this->maxRange) )
		{
			// Tell the user we are done with the table
			AEUtilLogger::WriteLog(_AE_LOG_DEBUG, "Done dumping " . $tableAbstract);

			if(count($this->tables) == 0)
			{
				// We have finished dumping the database!
				AEUtilLogger::WriteLog(_AE_LOG_INFO, "End of database detected; flushing the dump buffers...");
				$null = null;
				$this->writeDump($null);
				AEUtilLogger::WriteLog(_AE_LOG_INFO, "Database has been successfully dumped to SQL file(s)");
				$this->setState('postrun');
				$this->setStep('');
				$this->setSubstep('');
				$this->nextTable = '';
				$this->nextRange = 0;
			} elseif(count($this->tables) != 0) {
				// Switch tables
				$this->nextTable = array_shift( $this->tables );
				$this->nextRange = 0;
				$this->setStep($this->nextTable);
				$this->setSubstep('');
			}
		}

		$null = null;
		$this->writeline($null);
	}
Exemplo n.º 13
0
 private function _apiStartSRPBackup($config)
 {
     // Get the passed configuration values
     $defConfig = array('tag' => 'restorepoint', 'type' => 'component', 'name' => 'akeeba', 'group' => '', 'customdirs' => array(), 'extraprefixes' => array(), 'customtables' => array(), 'skiptables' => array(), 'xmlname' => '');
     $config = array_merge($defConfig, $config);
     foreach ($config as $key => $value) {
         if (!array_key_exists($key, $defConfig)) {
             unset($config[$key]);
         }
     }
     // Fetch the extension's version information
     require_once JPATH_ADMINISTRATOR . '/components/com_akeeba/assets/xmlslurp/xmlslurp.php';
     $slurp = new LiveUpdateXMLSlurp();
     $exttype = $config['type'];
     switch ($exttype) {
         case 'component':
             $extname = 'com_';
             break;
         case 'module':
             $extname = 'mod_';
             break;
         case 'plugin':
             $extname = 'plg_';
             break;
         case 'template':
             $extname = 'tpl_';
             break;
     }
     $extname .= $config['name'];
     $info = $slurp->getInfo($extname, '');
     $configOverrides = array('akeeba.basic.archive_name' => 'restore-point-[DATE]-[TIME]', 'akeeba.basic.backup_type' => 'full', 'akeeba.basic.backup_type' => 'full', 'akeeba.advanced.archiver_engine' => 'jpa', 'akeeba.advanced.proc_engine' => 'none', 'akeeba.advanced.embedded_installer' => 'none', 'engine.archiver.common.dereference_symlinks' => true, 'core.filters.srp.type' => $config['type'], 'core.filters.srp.group' => $config['group'], 'core.filters.srp.name' => $config['name'], 'core.filters.srp.customdirs' => $config['customdirs'], 'core.filters.srp.customfiles' => $config['customfiles'], 'core.filters.srp.extraprefixes' => $config['extraprefixes'], 'core.filters.srp.customtables' => $config['customtables'], 'core.filters.srp.skiptables' => $config['skiptables'], 'core.filters.srp.langfiles' => $config['langfiles']);
     // Parse a local file stored in (backend)/assets/srpdefs/$extname.xml
     JLoader::import('joomla.filesystem.file');
     $filename = JPATH_COMPONENT_ADMINISTRATOR . '/assets/srpdefs/' . $extname . '.xml';
     if (JFile::exists($filename)) {
         $xml = JFactory::getXMLParser('simple');
         if ($xml->loadFile($filename)) {
             $extraConfig = $this->parseRestorePointXML($xml->document);
             if ($extraConfig !== false) {
                 $this->mergeSRPConfig($configOverrides, $extraConfig);
             }
         }
         unset($xml);
     }
     // Parse the extension's manifest file and look for a <restorepoint> tag
     if (!empty($info['xmlfile'])) {
         $xml = JFactory::getXMLParser('simple');
         if ($xml->loadFile($info['xmlfile'])) {
             $restorepoint = $xml->document->getElementByPath('restorepoint');
             if ($restorepoint) {
                 $extraConfig = $this->parseRestorePointXML($restorepoint);
                 if ($extraConfig !== false) {
                     $this->mergeSRPConfig($configOverrides, $extraConfig);
                 }
             }
         }
         unset($restorepoint);
         unset($xml);
     }
     // Create an SRP descriptor
     $srpdescriptor = array('type' => $config['type'], 'name' => $config['name'], 'group' => $config['group'], 'version' => $info['version'], 'date' => $info['date']);
     // Set the description and comment
     $description = "System Restore Point - " . JText::_($exttype) . ": {$extname}";
     $comment = "---BEGIN SRP---\n" . json_encode($srpdescriptor) . "\n---END SRP---";
     $jpskey = '';
     $angiekey = '';
     // Set a custom finalization action queue
     $configOverrides['volatile.core.finalization.action_handlers'] = array(new AEFinalizationSrpquotas());
     $configOverrides['volatile.core.finalization.action_queue'] = array('remove_temp_files', 'update_statistics', 'update_filesizes', 'apply_srp_quotas');
     // Apply the configuration overrides, please
     $platform = AEPlatform::getInstance();
     $platform->configOverrides = $configOverrides;
     // Nuke the factory
     AEFactory::nuke();
     $profile = 1;
     $session = JFactory::getSession();
     $session->set('profile', $profile, 'akeeba');
     AEPlatform::getInstance()->load_configuration($profile);
     AEUtilTempvars::reset('restorepoint');
     $kettenrad = AECoreKettenrad::load('restorepoint');
     $options = array('description' => $description, 'comment' => $comment, 'tag' => 'restorepoint');
     $kettenrad->setup($options);
     // Setting up the engine
     $kettenrad->tick();
     if ($kettenrad->getState() != 'running' && $tag == 'restorepoint') {
         $kettenrad->tick();
     }
     $kettenrad->resetWarnings();
     // So as not to have duplicate warnings reports
     AECoreKettenrad::save($tag);
     $array = $kettenrad->getStatusArray();
     if ($array['Error'] != '') {
         // A backup error had occurred. Why are we here?!
         $this->status = self::STATUS_ERROR;
         $this->encapsulation = self::ENCAPSULATION_RAW;
         return 'A backup error had occurred: ' . $array['Error'];
     } else {
         $statistics = AEFactory::getStatistics();
         $array['BackupID'] = $statistics->getId();
         $array['HasRun'] = 1;
         // Force the backup to go on.
         return $array;
     }
 }
Exemplo n.º 14
0
 private function _apiStartBackup($config)
 {
     // Get the passed configuration values
     $defConfig = array('profile' => 1, 'description' => '', 'comment' => '');
     $config = array_merge($defConfig, $config);
     foreach ($config as $key => $value) {
         if (!array_key_exists($key, $defConfig)) {
             unset($config[$key]);
         }
     }
     extract($config);
     // Nuke the factory
     AEFactory::nuke();
     // Set the profile
     $profile = (int) $profile;
     if (!is_numeric($profile)) {
         $profile = 1;
     }
     $session = JFactory::getSession();
     $session->set('profile', $profile, 'akeeba');
     AEPlatform::getInstance()->load_configuration($profile);
     // Use the default description if none specified
     if (empty($description)) {
         jimport('joomla.utilities.date');
         $user = JFactory::getUser();
         $userTZ = $user->getParam('timezone', 0);
         $dateNow = new JDate();
         $dateNow->setOffset($userTZ);
         if (AKEEBA_JVERSION == '16') {
             $description = JText::_('BACKUP_DEFAULT_DESCRIPTION') . ' ' . $dateNow->format(JText::_('DATE_FORMAT_LC2'), true);
         } else {
             $description = JText::_('BACKUP_DEFAULT_DESCRIPTION') . ' ' . $dateNow->toFormat(JText::_('DATE_FORMAT_LC2'));
         }
     }
     // Start the backup
     AECoreKettenrad::reset(array('maxrun' => 0));
     AEUtilTempvars::reset(AKEEBA_BACKUP_ORIGIN);
     $kettenrad = AECoreKettenrad::load(AKEEBA_BACKUP_ORIGIN);
     $options = array('description' => $description, 'comment' => $comment, 'tag' => AKEEBA_BACKUP_ORIGIN);
     $kettenrad->setup($options);
     // Setting up the engine
     $array = $kettenrad->tick();
     // Initializes the init domain
     AECoreKettenrad::save(AKEEBA_BACKUP_ORIGIN);
     $array = $kettenrad->getStatusArray();
     if ($array['Error'] != '') {
         // A backup error had occurred. Why are we here?!
         $this->status = self::STATUS_ERROR;
         $this->encapsulation = self::ENCAPSULATION_RAW;
         return 'A backup error had occurred: ' . $array['Error'];
     } else {
         $statistics = AEFactory::getStatistics();
         $array['BackupID'] = $statistics->getId();
         $array['HasRun'] = 1;
         // Force the backup to go on.
         return $array;
     }
 }