Last active
October 18, 2024 09:50
-
-
Save droduit/a3f9304d08a3d95d9e5d48b173e070a6 to your computer and use it in GitHub Desktop.
Fix serialized data broken due to search & replace in database
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
* The `fix_serialized` function fixes serialized data which has been corrupted by an incorrect byte count length, | |
* especially in the case of a search & replace done on a dump of a wordpress database. | |
*/ | |
$corruptedSerialization = 'a:3:{i:0;s:150:".DS_Store";i:1;s:100:".git";i:2;s:190:"node_modules";}'; | |
if (is_serialized($corruptedSerialization)) { | |
$fixed = fix_serialized($corruptedSerialization); | |
print_r(unserialize($fixed)); | |
} | |
// =================================================== | |
function fix_serialized($serialized) { | |
$fixed = fix_inner_serialized($serialized); | |
if (@unserialize($fixed)) { | |
return $fixed; | |
} | |
return fix_serialized_parts($fixed); | |
} | |
function fix_inner_serialized($string) { | |
return preg_replace_callback( | |
'/s:([0-9]+):\"(a:[0-9]+:{.*?})\";/', | |
function ($matches) { | |
$serializedString = stripslashes($matches[2]); | |
$fixed = fix_serialized_parts($serializedString); | |
return "s:".strlen($fixed).':"'.$fixed.'";'; | |
}, | |
$string | |
); | |
} | |
function fix_serialized_parts($string) { | |
if (!preg_match('/^[aOs]:/', $string) ) { | |
return $string; | |
} | |
$string = preg_replace("%\n%", "", $string); | |
return preg_replace_callback( | |
'/s:([0-9]+):\"(.*?)\";/', | |
function ($matches) { | |
if (preg_match('/a:[0-9]+:{/', $matches[2])) { | |
return $matches[0]; | |
} | |
return "s:".strlen($matches[2]).':"'.$matches[2].'";'; | |
}, | |
$string | |
); | |
} | |
function is_serialized($data) { | |
if (!is_string($data)) { | |
return false; | |
} | |
$data = trim($data); | |
if ('N;' == $data) { | |
return true; | |
} | |
if (!preg_match('/^([adObis]):/', $data, $badions)) { | |
return false; | |
} | |
switch ($badions[1]) { | |
case 'a' : | |
case 'O' : | |
case 's' : | |
if (preg_match("/^{$badions[1]}:[0-9]+:.*[;}]\$/s", $data)) { | |
return true; | |
} | |
break; | |
case 'b' : | |
case 'i' : | |
case 'd' : | |
if (preg_match("/^{$badions[1]}:[0-9.E-]+;\$/", $data)) { | |
return true; | |
} | |
break; | |
} | |
return false; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Oh god, THANK YOU !