Skip to content

Instantly share code, notes, and snippets.

@yavir-me
Last active November 15, 2017 09:13
Show Gist options
  • Save yavir-me/2b49b6e833899814fdb646400551351d to your computer and use it in GitHub Desktop.
Save yavir-me/2b49b6e833899814fdb646400551351d to your computer and use it in GitHub Desktop.
Replace domain wordpress (whole db)
<?php
require 'DBConnector.php';
class DBProcessor
{
protected $textFieldTypes = ['text', 'blob', 'varchar', 'longtext', 'tinytext', 'text', 'mediumtext'];
public $replacement;
public $replacementWith;
public $dbName;
/**
* DBProcessor constructor.
* @param string $replacement
* @param string $replacementWith
*/
public function __construct($dbName, $replacement, $replacementWith)
{
$this->replacement = $replacement;
$this->replacementWith = $replacementWith;
$this->dbName = $dbName;
}
public function process()
{
$dbh = DBConnector::getConnection();
$sth = $dbh->query('SHOW TABLES');
$sth->execute();
foreach ($sth->fetchAll() as $table) {
$tableName = $table["Tables_in_$this->dbName"];
$tableFieldsStmt = $dbh->query('DESCRIBE ' . $tableName);
$tableFieldsStmt->execute();
$primaryKey = '';
foreach ($tableFieldsStmt->fetchAll() as $columnName) {
// set primary key for a table. do not process replacements in the primary key column
if (!$primaryKey) {
$primaryKey = $columnName['Field'];
continue;
}
// check if filed type is text
if ($this->checkAppropriateType($columnName['Type'])) {
$specifiedColumnData = $dbh->query("SELECT `{$primaryKey}`, `{$columnName['Field']}` FROM `{$tableName}`");
// skip iteration for empty strings
if (!$specifiedColumnData) {
continue;
}
$specifiedColumnData->execute();
// for each row of the given column check for unserialized data and replace needed content
foreach ($specifiedColumnData->fetchAll() as $curRow) {
$rowValue = array_slice($curRow, 1, 1);
$currentId = $curRow[key($curRow)];
if (!isset($rowValue[key($rowValue)])) {
continue; // for null values
}
$curValue = $rowValue[key($rowValue)];
// check for serializing
if ($this->is_serialized($curValue)) { // data serialized
$deserialize = $this->maybe_unserialize($curValue);
if (is_array($deserialize)) {
try {
$updatedValue = serialize($this->parseSerializedData($deserialize));
} catch (Exception $e) {
print $e->getMessage();
}
} elseif (is_object($deserialize)) {
print 'value has object type' . PHP_EOL;
} elseif (is_array($deserialize)) {
print 'value has array type' . PHP_EOL;
} else {
$updatedValue = str_ireplace("'", "\'", $curValue);
}
// update reserialized value
try {
$this->updateValue($tableName, $primaryKey, $columnName['Field'], $currentId, $updatedValue);
} catch (Exception $e) {
print $e->getMessage() . ' [SERIALIZED DATA ERROR]' . PHP_EOL;
}
print 'Serialized data updated' . PHP_EOL;
} elseif (stripos($curValue, $this->replacement)) {
$updatedValue = str_ireplace($this->replacement, $this->replacementWith, $curValue);
try {
$this->updateValue($tableName, $primaryKey, $columnName['Field'], $currentId, $updatedValue);
} catch (Exception $e) {
print $e->getMessage() . ' [UNSERIALIZED DATA ERROR]' . PHP_EOL;
}
print 'Unserialized data updated' . PHP_EOL;
}
}
}
}
}
}
/*
* Checks for an appropriate type in a field
* @fieldType mixed - type of the given string
* @return bool
*/
function maybe_unserialize($original)
{
if ($this->is_serialized($original)) // don't attempt to unserialize data that wasn't serialized going in
return @unserialize($original);
return $original;
}
protected function is_serialized($data, $strict = true)
{
// if it isn't a string, it isn't serialized.
if (!is_string($data)) {
return false;
}
$data = trim($data);
if ('N;' == $data) {
return true;
}
if (strlen($data) < 4) {
return false;
}
if (':' !== $data[1]) {
return false;
}
if ($strict) {
$lastc = substr($data, - 1);
if (';' !== $lastc && '}' !== $lastc) {
return false;
}
} else {
$semicolon = strpos($data, ';');
$brace = strpos($data, '}');
// Either ; or } must exist.
if (false === $semicolon && false === $brace)
return false;
// But neither must be in the first X characters.
if (false !== $semicolon && $semicolon < 3)
return false;
if (false !== $brace && $brace < 4)
return false;
}
$token = $data[0];
switch ($token) {
case 's' :
if ($strict) {
if ('"' !== substr($data, - 2, 1)) {
return false;
}
} elseif (false === strpos($data, '"')) {
return false;
}
// or else fall through
case 'a' :
case 'O' :
return (bool) preg_match("/^{$token}:[0-9]+:/s", $data);
case 'b' :
case 'i' :
case 'd' :
$end = $strict ? '$' : '';
return (bool) preg_match("/^{$token}:[0-9.E-]+;$end/", $data);
}
return false;
}
protected function checkAppropriateType($fieldType)
{
$fieldType = strtolower(explode('(', $fieldType)[0]);
return in_array($fieldType, $this->textFieldTypes);
}
protected function parseSerializedData($deserialize)
{
foreach ($deserialize as $key => $value) {
if (is_string($value)) {
$deserialize[$key] = str_ireplace($this->replacement, $this->replacementWith, $value);
} elseif (is_array($value)) {
$deserialize[$key] = $this->parseSerializedData($value);
} elseif (is_object($value)) {
continue;
// throw new Exception("We don't support object");
}
}
return $deserialize;
}
protected function updateValue($tableName, $primaryKey, $columnName, $curRowId, $newValue)
{
$dbh = DBConnector::getConnection();
$sql = "UPDATE `$tableName` SET `$columnName` = :newValue WHERE `$primaryKey` = $curRowId";
$sth = $dbh->prepare($sql);
$sth->bindParam(':newValue', $newValue);
$result = $sth->execute();
if (!$result) {
throw new Exception($sth->errorInfo());
}
}
}
$processor = new DBProcessor('gsm_replacement', '//gsm-uk.co.uk', '//gsm-uk.co.uk.allbugs.info');
$processor->process();
echo 'Script completed', PHP_EOL;
die();
#!/usr/bin/php
<?php
/*
* Blogestudio Fix Serialization 1.2
* Fixer script of length attributes for serialized strings (e.g. Wordpress databases)
* License: GPL version 3 or later - http://www.gnu.org/licenses/gpl.txt
* By Pau Iglesias
* http://blogestudio.com
*
* Inspiration and regular expression code base from David Coveney:
* http://davidcoveney.com/575/php-serialization-fix-for-wordpress-migrations/
*
* Usage:
*
* /usr/bin/php fix-serialization.php my-sql-file.sql
*
* Versions:
*
* 1.0 2011-08-03 Initial release
* 1.1 2011-08-18 Support for backslashed quotes, added some code warnings
* 1.2 2011-09-29 Support for null or zero length strings after preg_replace is called, and explain how to handle these errors
*
* Knowed errors:
*
* - Memory size exhausted
* Allowed memory size of 67108864 bytes exhausted (tried to allocate 35266489 bytes)
* How to fix: update php.ini memory_limit to 512M or more, and restart cgi service or web server
*
* - Function preg_replace returns null or 0 length string
* If preg_last_error = PREG_BACKTRACK_LIMIT_ERROR (value 2), increase pcre.backtrack_limit in php.ini (by default 100k, change to 2M by example)
* Same way for others preg_last_error codes: http://www.php.net/manual/en/function.preg-last-error.php
*
* TODO next versions
*
* - Check if needed UTF-8 support detecting and adding u PCRE modifier
*
*/
// Unescape to avoid dump-text issues
function unescape_mysql($value) {
return str_replace(array("\\\\", "\\0", "\\n", "\\r", "\Z", "\'", '\"'),
array("\\", "\0", "\n", "\r", "\x1a", "'", '"'),
$value);
}
// Fix strange behaviour if you have escaped quotes in your replacement
function unescape_quotes($value) {
return str_replace('\"', '"', $value);
}
// Check command line arguments
if (!(isset($argv) && isset($argv[1]))) {
// Error
echo 'Error: no input file specified'."\n\n";
// With arguments
} else {
// Compose path from argument
$path = dirname(__FILE__).'/'.$argv[1];
if (!file_exists($path)) {
// Error
echo 'Error: input file does not exists'."\n";
echo $path."\n\n";
// File exists
} else {
// Get file contents
if (!($fp = fopen($path, 'r'))) {
// Error
echo 'Error: can`t open input file for read'."\n";
echo $path."\n\n";
// File opened for read
} else {
// Initializations
$do_preg_replace = false;
// Copy data
if (!($data = fread($fp, filesize($path)))) {
// Error
echo 'Error: can`t read entire data from input file'."\n";
echo $path."\n\n";
// Check data
} elseif (!(isset($data) && strlen($data) > 0)) {
// Warning
echo "Warning: the file is empty or can't read contents\n";
echo $path."\n\n";
// Data ok
} else {
// Tag context
$do_preg_replace = true;
// Replace serialized string values
$data = preg_replace('!s:(\d+):([\\\\]?"[\\\\]?"|[\\\\]?"((.*?)[^\\\\])[\\\\]?");!e', "'s:'.strlen(unescape_mysql('$3')).':\"'.unescape_quotes('$3').'\";'", $data);
}
// Close file
fclose($fp);
// Check data
if (!(isset($data) && strlen($data) > 0)) {
// Check origin
if ($do_preg_replace) {
// Error
echo "Error: preg_replace returns nothing\n";
if (function_exists('preg_last_error')) echo "preg_last_error() = ".preg_last_error()."\n";
echo $path."\n\n";
}
// Data Ok
} else {
// And finally write data
if (!($fp = fopen($path, 'w'))) {
// Error
echo "Error: can't open input file for writing\n";
echo $path."\n\n";
// Open for write
} else {
// Write file data
if (!fwrite($fp, $data)) {
// Error
echo "Error: can't write input file\n";
echo $path."\n\n";
}
// Close file
fclose($fp);
}
}
}
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment