forked from extern/egroupware
* 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:
parent
f48b6c244f
commit
3418c5284e
@ -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";
|
||||||
|
*/
|
Loading…
Reference in New Issue
Block a user