allowedErrorCodes = array( 1262, 1263, 1264, 1265, // "Data truncated" warning 1266, 1287, 1299 // , 1406 // "Data too long" error ); // Set up allowed comment delimiters $this->comment = array( '#', '\'-- ', '---', '/*!', ); // Connect to the database $this->getDatabase(); // Suppress foreign key checks if ($this->getParam('foreignkey', 1)) { $this->db->setQuery('SET FOREIGN_KEY_CHECKS = 0'); try { $this->db->execute(); } catch (\Exception $exc) { // Do nothing if that fails. Maybe we can continue with the restoration. } } } /** * Overloaded method which will create the database (if it doesn't exist). * * @return Database\Driver */ protected function getDatabase() { // Do I have all I need? if(!isset($this->container['dbrestore']['dbname']) || !isset($this->container['dbrestore']['dbuser'])) { throw new \RuntimeException('AWF_RESTORE_ERROR_MISSINGDBDETAILS', 500); } if (!is_object($this->db)) { $db = parent::getDatabase(); try { $db->select($this->container['dbrestore']['dbname']); } catch (\Exception $exc) { // We couldn't connect to the database. Maybe we have to create // it first. Let's see... $options = (object)array( 'db_name' => $this->container['dbrestore']['dbname'], 'db_user' => $this->container['dbrestore']['dbuser'], ); $db->createDatabase($options, true); $db->select($this->container['dbrestore']['dbname']); } // Try to change the database collation, if requested if ($this->getParam('utf8db', 0)) { try { $db->alterDbCharacterSet($this->container['dbrestore']['dbname']); } catch (\Exception $exc) { // Ignore any errors } } } return $this->db; } /** * Processes and runs the query * * @param string $query The query to process * * @return boolean True on success */ protected function processQueryLine($query) { $db = $this->getDatabase(); $prefix = $this->getParam('prefix', 'awf_'); $existing = $this->getParam('existing', 'drop'); $forceutf8 = $this->getParam('utf8tables', 0); $replacesql = $this->getParam('replace', 0); $changeEncoding = false; $useDelimiter = false; // CREATE TABLE query pre-processing // If the table has a prefix, back it up (if requested). In any case, drop // the table. before attempting to create it. if (substr($query, 0, 12) == 'CREATE TABLE') { // Yes, try to get the table name $restOfQuery = trim(substr($query, 12, strlen($query) - 12)); // Rest of query, after CREATE TABLE // Is there a backtick? if (substr($restOfQuery, 0, 1) == '`') { // There is... Good, we'll just find the matching backtick $pos = strpos($restOfQuery, '`', 1); $tableName = substr($restOfQuery, 1, $pos - 1); } else { // Nope, let's assume the table name ends in the next blank character $pos = strpos($restOfQuery, ' ', 1); $tableName = substr($restOfQuery, 1, $pos - 1); } unset($restOfQuery); // Should I back the table up? if (($prefix != '') && ($existing == 'backup') && (strpos($tableName, '#__') == 0)) { // It's a table with a prefix, a prefix IS specified and we are asked to back it up. // Start by dropping any existing backup tables $backupTable = str_replace('#__', 'bak_', $tableName); try { $db->dropTable($backupTable); $db->renameTable($tableName, $backupTable); } catch (\Exception $exc) { // We can't rename the table. Try deleting it. $db->dropTable($tableName); } } else { // Try to drop the table anyway $db->dropTable($tableName); } $changeEncoding = $forceutf8; } // CREATE VIEW query pre-processing // In any case, drop the view before attempting to create it. (Views can't be renamed) elseif ((substr($query, 0, 7) == 'CREATE ') && (strpos($query, ' VIEW ') !== false)) { // Yes, try to get the view name $view_pos = strpos($query, ' VIEW '); $restOfQuery = trim(substr($query, $view_pos + 6)); // Rest of query, after VIEW string // Is there a backtick? if (substr($restOfQuery, 0, 1) == '`') { // There is... Good, we'll just find the matching backtick $pos = strpos($restOfQuery, '`', 1); $tableName = substr($restOfQuery, 1, $pos - 1); } else { // Nope, let's assume the table name ends in the next blank character $pos = strpos($restOfQuery, ' ', 1); $tableName = substr($restOfQuery, 1, $pos - 1); } unset($restOfQuery); // Try to drop the view anyway $dropQuery = 'DROP VIEW IF EXISTS `' . $tableName . '`;'; $db->setQuery(trim($dropQuery)); $db->execute(); } // CREATE PROCEDURE pre-processing elseif ((substr($query, 0, 7) == 'CREATE ') && (strpos($query, 'PROCEDURE ') !== false)) { // Try to get the procedure name $entity_keyword = ' PROCEDURE '; $entity_pos = strpos($query, $entity_keyword); $restOfQuery = trim(substr($query, $entity_pos + strlen($entity_keyword))); // Rest of query, after entity key string // Is there a backtick? if (substr($restOfQuery, 0, 1) == '`') { // There is... Good, we'll just find the matching backtick $pos = strpos($restOfQuery, '`', 1); $entity_name = substr($restOfQuery, 1, $pos - 1); } else { // Nope, let's assume the entity name ends in the next blank character $pos = strpos($restOfQuery, ' ', 1); $entity_name = substr($restOfQuery, 1, $pos - 1); } unset($restOfQuery); // Try to drop the entity anyway $dropQuery = 'DROP' . $entity_keyword . 'IF EXISTS `' . $entity_name . '`;'; $db->setQuery(trim($dropQuery)); $db->execute(); $useDelimiter = true; // Instruct the engine to change the delimiter for this query to // } // CREATE FUNCTION pre-processing elseif ((substr($query, 0, 7) == 'CREATE ') && (strpos($query, 'FUNCTION ') !== false)) { // Try to get the procedure name $entity_keyword = ' FUNCTION '; $entity_pos = strpos($query, $entity_keyword); $restOfQuery = trim(substr($query, $entity_pos + strlen($entity_keyword))); // Rest of query, after entity key string // Is there a backtick? if (substr($restOfQuery, 0, 1) == '`') { // There is... Good, we'll just find the matching backtick $pos = strpos($restOfQuery, '`', 1); $entity_name = substr($restOfQuery, 1, $pos - 1); } else { // Nope, let's assume the entity name ends in the next blank character $pos = strpos($restOfQuery, ' ', 1); $entity_name = substr($restOfQuery, 1, $pos - 1); } unset($restOfQuery); // Try to drop the entity anyway $dropQuery = 'DROP' . $entity_keyword . 'IF EXISTS `' . $entity_name . '`;'; $db->setQuery(trim($dropQuery)); $db->execute(); $useDelimiter = true; // Instruct the engine to change the delimiter for this query to // } // CREATE TRIGGER pre-processing elseif ((substr($query, 0, 7) == 'CREATE ') && (strpos($query, 'TRIGGER ') !== false)) { // Try to get the procedure name $entity_keyword = ' TRIGGER '; $entity_pos = strpos($query, $entity_keyword); $restOfQuery = trim(substr($query, $entity_pos + strlen($entity_keyword))); // Rest of query, after entity key string // Is there a backtick? if (substr($restOfQuery, 0, 1) == '`') { // There is... Good, we'll just find the matching backtick $pos = strpos($restOfQuery, '`', 1); $entity_name = substr($restOfQuery, 1, $pos - 1); } else { // Nope, let's assume the entity name ends in the next blank character $pos = strpos($restOfQuery, ' ', 1); $entity_name = substr($restOfQuery, 1, $pos - 1); } unset($restOfQuery); // Try to drop the entity anyway $dropQuery = 'DROP' . $entity_keyword . 'IF EXISTS `' . $entity_name . '`;'; $db->setQuery(trim($dropQuery)); $db->execute(); $useDelimiter = true; // Instruct the engine to change the delimiter for this query to // } elseif (substr($query, 0, 6) == 'INSERT') { if ($replacesql) { // Use REPLACE instead of INSERT selected $query = 'REPLACE ' . substr($query, 7); } } if (!empty($query)) { if ($useDelimiter) { // This doesn't work from PHP //$this->execute('DELIMITER //'); } $this->execute($query); if ($useDelimiter) { // This doesn't work from PHP //$this->execute('DELIMITER ;'); } // Do we have to force UTF8 encoding? if ($changeEncoding && isset($tableName)) { // Get a list of columns $columns = $db->getTableColumns($tableName); $mods = array(); // array to hold individual MODIFY COLUMN commands if (is_array($columns)) { foreach ($columns as $field => $column) { // Make sure we are redefining only columns which do support a collation $col = (object)$column; if (empty($col->Collation)) { continue; } $null = $col->Null == 'YES' ? 'NULL' : 'NOT NULL'; $default = is_null($col->Default) ? '' : "DEFAULT '" . $db->escape($col->Default) . "'"; $mods[] = "MODIFY COLUMN `$field` {$col->Type} $null $default COLLATE utf8_general_ci"; } } // Begin the modification statement $sql = "ALTER TABLE `$tableName` "; // Add commands to modify columns if (!empty($mods)) { $sql .= implode(', ', $mods) . ', '; } // Add commands to modify the table collation $sql .= 'DEFAULT CHARACTER SET UTF8 COLLATE utf8_general_ci;'; $db->setQuery($sql); try { $db->execute(); } catch (\Exception $exc) { // Don't fail if the collation could not be changed } } } return true; } }