* Backup: fix sometimes not working restore (seems like an internal error in preg_match, causing Apache to run at 100% CPU never finishing) for php 5.3+

This commit is contained in:
Ralf Becker 2012-06-17 10:10:46 +00:00
parent f48b6c244f
commit 3418c5284e

View File

@ -16,10 +16,6 @@
*/ */
class db_backup class db_backup
{ {
/**
* replaces backslashes, used in cvs_split
*/
const BACKSLASH_TOKEN = '##!!**bAcKsLaSh**!!##';
/** /**
* Configuration table. * Configuration table.
*/ */
@ -456,8 +452,16 @@ class db_backup
$this->schemas = unserialize(trim(substr($line,8))); $this->schemas = unserialize(trim(substr($line,8)));
foreach($this->schemas as $table_name => $schema) foreach($this->schemas as $table_name => $schema)
{ {
// if column is longtext in current schema, convert text to longtext, in case user already updated column
foreach($schema['fd'] as $col => &$def)
{
if ($def['type'] == 'text' && $this->db->get_column_attribute($col, $table, true, 'type') == 'longtext')
{
$def['type'] = 'longtext';
}
}
//echo "<pre>$table_name => ".self::write_array($schema,1)."</pre>\n"; //echo "<pre>$table_name => ".self::write_array($schema,1)."</pre>\n";
$this->schema_proc->CreateTable($table_name,$schema); $this->schema_proc->CreateTable($table_name, $schema);
} }
continue; continue;
} }
@ -471,6 +475,11 @@ class db_backup
$table = substr($line,7); $table = substr($line,7);
$cols = self::csv_split($line=fgets($f)); ++$n; $cols = self::csv_split($line=fgets($f)); ++$n;
$blobs = array();
foreach($this->schemas[$table]['fd'] as $col => $data)
{
if ($data['type'] == 'blob') $blobs[] = $col;
}
if (feof($f)) break; if (feof($f)) break;
continue; continue;
@ -488,8 +497,10 @@ class db_backup
if ($table) // do we already reached the data part if ($table) // do we already reached the data part
{ {
$import = true; $import = true;
$data = self::csv_split($line,$cols); $data = self::csv_split($line, $cols, $blobs);
if ($table == 'egw_async' && in_array('##last-check-run##',$data)) {
if ($table == 'egw_async' && in_array('##last-check-run##',$data))
{
//echo '<p>'.lang("Line %1: '%2'<br><b>csv data does contain ##last-check-run## of table %3 ==> ignored</b>",$n,$line,$table)."</p>\n"; //echo '<p>'.lang("Line %1: '%2'<br><b>csv data does contain ##last-check-run## of table %3 ==> ignored</b>",$n,$line,$table)."</p>\n";
//echo 'data=<pre>'.print_r($data,true)."</pre>\n"; //echo 'data=<pre>'.print_r($data,true)."</pre>\n";
$import = false; $import = false;
@ -634,15 +645,66 @@ class db_backup
//rmdir($dir); // dont remove own dir //rmdir($dir); // dont remove own dir
} }
/**
* temp. replaces backslashes
*/
const BACKSLASH_TOKEN = '##!!**bAcKsLaSh**!!##';
/**
* temp. replaces NULL
*/
const NULL_TOKEN = '##!!**NuLl**!!##';
/** /**
* Split one line of a csv file into an array and does all unescaping * Split one line of a csv file into an array and does all unescaping
* *
* @param string $line line to split * @param string $line line to split
* @param array $keys=null keys to use or null to use numeric ones * @param array $keys=null keys to use or null to use numeric ones
* @param array $blobs=array() blob columns
* @return array * @return array
*/ */
public static function csv_split($line,$keys=null) public static function csv_split($line, $keys=null, $blobs=array())
{ {
if (function_exists('str_getcsv')) // php5.3+
{
// we need to take care of literal "NULL" values, replacing them we a special token as str_getcsv removes enclosures around strings
// str_getcsv uses '""' for '"' instead of '\\"' and does not unescape '\\n', '\\r' or '\\\\' (two backslashes)
$fields = str_getcsv(strtr($line, array(
'"NULL"' => self::NULL_TOKEN,
'\\\\' => self::BACKSLASH_TOKEN,
'\\"' => '""',
'\\n' => "\n",
'\\r' => "\r")), ',', '"', '\0');
// replace NULL-token again with 'NULL', 'NULL' with null and BACKSLASH-token with a backslash
foreach($fields as &$field)
{
switch($field)
{
case self::NULL_TOKEN:
$field = 'NULL';
break;
case 'NULL':
$field = null;
break;
default:
$field = str_replace(self::BACKSLASH_TOKEN, '\\', $field);
break;
}
}
if ($keys) // if string keys are to be used --> combine keys and values
{
$fields = array_combine($keys, $fields);
// base64-decode blob columns, if they are base64 encoded
foreach($blobs as $key)
{
if (!is_null($fields[$key]) && ($tmp = base64_decode($fields[$key], true)) !== false)
{
$fields[$key] = $tmp;
}
}
}
return $fields;
}
// pre 5.3 implementation
$fields = explode(',',trim($line)); $fields = explode(',',trim($line));
$str_pending = False; $str_pending = False;
@ -958,9 +1020,12 @@ class db_backup
return $def; return $def;
} }
} }
/* /*
$line = '"de","ranking","use \\"yes\\", or \\"no, prefession\\"","benützen Sie \\"yes\\" oder \\"no, Beruf\\""'; $line = '"de","NULL","ranking",NULL,NULL,"one backslash: \\\\ here","\\\\","use \\"yes\\", or \\"no, prefession\\"","benützen Sie \\"yes\\" oder \\"no, Beruf\\"",NULL';
echo "<p>line='$line'</p>\n"; echo "<p>line='$line'</p>\n";
echo "<pre>".print_r(db_backup::csv_split($line),true)."</pre>\n"; $fields = db_backup::csv_split($line);
*/ echo "<pre>".print_r($fields,true)."</pre>\n";
//echo count($fields)." fields\n";
*/