452 lines
12 KiB
PHP
452 lines
12 KiB
PHP
#!/usr/local/bin/php -c/usr/local/directadmin/scripts/php_clean.ini
|
|
<?php
|
|
|
|
$version = 0.1;
|
|
|
|
/*
|
|
Restore script for the per-domain RoundCube settings.
|
|
Backup/Restore written by DirectAdmin: http://www.directadmin.com
|
|
RoundCube Webmail Client: http://roundcube.net
|
|
|
|
This script will take an XML output (generated by backup_roundcube.php)
|
|
and restore all elements for a given User, merging them into an active roundcube database.
|
|
New IDs are generated, where applicable, so they will not be any conflicts if the IDs are differnt.
|
|
Existing accounts will be respected, and only missing data is merged in.
|
|
|
|
See the DirectAdmin versions system for more info:
|
|
http://www.directadmin.com/features.php?id=1062
|
|
|
|
All variables are passed via environment, not command line options
|
|
But you can specify environmental variables... via command line options before the script (see the showHelp() function)
|
|
|
|
RETURN VALUES
|
|
0: All is well
|
|
>1: an error worthy or reporting has occured. Message on stderr.
|
|
1: an error, most likely due to not actually having RoundCube installed or no restore data, has occured.
|
|
|
|
*/
|
|
|
|
/***********************
|
|
* Environmental variables
|
|
*/
|
|
$domain = getenv("domain"); //for security reasons, it must match the XML values.
|
|
$system_username = getenv("username"); //only this account is allowed to be restored.
|
|
$xml_file = getenv("xml_file"); //Name of the file to restore.
|
|
|
|
/***********************
|
|
* Enabling debug lets you see which Email is seen,
|
|
* and what values are being restored, and shows you their respective IDs (found or set)
|
|
* Keep this set to FALSE if the dataksq is calling it, so as to not fill the stdin buffer (dataskq only reads from stderr for this script)
|
|
*/
|
|
$is_debug = FALSE;
|
|
|
|
/***********************
|
|
* this restores as da_admin instead of da_roundube. It is less secure, avoid using it if possible.
|
|
*/
|
|
$high_access_connection = FALSE;
|
|
|
|
|
|
/***********************
|
|
* is the host value set within the da_roundcube.users table.
|
|
*/
|
|
$rc_mail_host = 'localhost';
|
|
|
|
/***********************
|
|
* If $high_access_restore is false, this is used for the mysql credentials.
|
|
*/
|
|
$rc_config = "/var/www/html/roundcube/config/config.inc.php";
|
|
|
|
//****************************************************************
|
|
//****************************************************************
|
|
|
|
if (!isset($xml_file) || $xml_file == "")
|
|
show_help();
|
|
|
|
if (!isset($domain) || $domain == "")
|
|
show_help();
|
|
|
|
if (!file_exists($xml_file))
|
|
{
|
|
echo_stderr("Cannot find path: $xml_file. Skipping RoundCube restore.\n");
|
|
exit(1);
|
|
}
|
|
|
|
if (filesize($xml_file) == 0)
|
|
{
|
|
echo_stderr("Size of $xml_file is 0. Skipping RoundCube restore.\n");
|
|
exit(1);
|
|
}
|
|
|
|
//****************************************************************
|
|
//****************************************************************
|
|
|
|
if ($high_access_connection)
|
|
{
|
|
if (version_compare(PHP_VERSION, '5.3.0', '<'))
|
|
{
|
|
$mysql_conf = @parse_ini_file("/usr/local/directadmin/conf/mysql.conf", false);
|
|
}
|
|
else
|
|
{
|
|
$mysql_conf = @parse_ini_file("/usr/local/directadmin/conf/mysql.conf", false, INI_SCANNER_RAW);
|
|
}
|
|
}
|
|
|
|
if ($high_access_connection && $mysql_conf && strlen($mysql_conf['passwd']) > 4)
|
|
{
|
|
$mysql_conf = parse_ini_file("/usr/local/directadmin/conf/mysql.conf");
|
|
$mysql_user = $mysql_conf['user'];
|
|
$mysql_pass = $mysql_conf['passwd'];
|
|
$mysql_host = 'localhost';
|
|
$mysql_db = 'da_roundcube';
|
|
|
|
if (isset($mysql_conf['host']) && $mysql_conf['host'] != "")
|
|
$mysql_host = $mysql_conf['host'];
|
|
}
|
|
else
|
|
{
|
|
if (!file_exists($rc_config))
|
|
{
|
|
echo_stderr("Cannot find RoundCube config at $rc_config. Is RC installed and up to date?\n");
|
|
exit(5);
|
|
}
|
|
|
|
include_once($rc_config);
|
|
|
|
if (!isset($config) || !isset($config['db_dsnw']) || $config['db_dsnw'] == '')
|
|
{
|
|
echo_stderr("Cannot find \$config['db_dsnw'] variable in $rc_config\n");
|
|
exit(6);
|
|
}
|
|
|
|
//$config['db_dsnw'] = 'mysql://da_roundcube:password@localhost/da_roundcube';
|
|
|
|
$values = explode('/', $config['db_dsnw']);
|
|
$connect = explode('@', $values[2]);
|
|
$auth = explode(':', $connect[0]);
|
|
|
|
$mysql_user = $auth[0];
|
|
$mysql_pass = $auth[1];
|
|
$mysql_host = $connect[1];
|
|
$mysql_db = $values[3];
|
|
}
|
|
|
|
$mysqli = new mysqli($mysql_host, $mysql_user, $mysql_pass);
|
|
if ($mysqli->connect_errno) {
|
|
echo_stderr("Failed to connect to MySQL: (".$mysqli->connect_errno.") ".$mysqli->connect_error."\n");
|
|
exit(3);
|
|
}
|
|
$mysqli->set_charset('utf8');
|
|
|
|
if (!$mysqli->select_db($mysql_db))
|
|
{
|
|
echo_stderr("There is no $mysql_db database. Skipping RoundCube restore.\n");
|
|
exit(1);
|
|
}
|
|
|
|
//****************************************************************
|
|
//****************************************************************
|
|
|
|
$xml = simplexml_load_file($xml_file);
|
|
|
|
if ($xml === FALSE)
|
|
{
|
|
echo_stderr("Error reading in XML file with with simplexml_load_file('$xml_file')\n");
|
|
exit(4);
|
|
}
|
|
|
|
foreach($xml->children() as $email)
|
|
{
|
|
$username = urldecode($email->USERNAME);
|
|
|
|
if ($username != $system_username)
|
|
{
|
|
$data = explode('@', $username);
|
|
|
|
if ($data[1] != $domain)
|
|
{
|
|
echo_stderr($username. " is not part of domain '".$domain."': Skipping.\n");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
$user_id = ensure_user($email);
|
|
if ($user_id == -1)
|
|
continue;
|
|
|
|
echo_debug("username $username : $user_id\n");
|
|
|
|
foreach($email->INDENTITIES->children() as $identity)
|
|
{
|
|
$id_id = ensure_identity($user_id, $identity);
|
|
|
|
if ($id_id == -1)
|
|
continue;
|
|
|
|
$id_email = urldecode($identity->EMAIL);
|
|
echo_debug(" identity $id_email : $id_id\n");
|
|
}
|
|
|
|
|
|
$groups = Array();
|
|
|
|
foreach($email->CONTACTS->children() as $contact)
|
|
{
|
|
//first, ensure all groups exisrt for this user_id.
|
|
foreach($contact->GROUPS->children() as $group)
|
|
{
|
|
$group_id = ensure_group($user_id, $group);
|
|
$group_name = urldecode($group->NAME);
|
|
|
|
//save it for later.
|
|
$groups[$group_name] = $group_id;
|
|
}
|
|
|
|
//next, ensure the contact exists, and add to contactgroupsmembers.
|
|
$contact_id = ensure_contact($user_id, $contact);
|
|
|
|
$contact_email = urldecode($contact->EMAIL);
|
|
echo_debug(" contact $contact_email : $contact_id\n");
|
|
|
|
//link contact to their groups.
|
|
link_contact_to_group($contact, $contact_id, $groups);
|
|
|
|
}
|
|
}
|
|
|
|
$mysqli->close();
|
|
|
|
exit(0);
|
|
|
|
//**********************************************************************
|
|
//**********************************************************************
|
|
|
|
/**********************************************************************
|
|
* ensure that the contact has been assigned to their groups.
|
|
*/
|
|
function link_contact_to_group($contact, $contact_id, $groups)
|
|
{
|
|
global $mysqli;
|
|
|
|
foreach($contact->GROUPS->children() as $group)
|
|
{
|
|
$group_name = urldecode($group->NAME);
|
|
$group_created = mes(urldecode($group->CREATED));
|
|
$query = "REPLACE INTO `contactgroupmembers` (contactgroup_id, contact_id, created) VALUES (".mes($groups[$group_name]).", $contact_id, '$group_created')";
|
|
|
|
if (!$mysqli->query($query))
|
|
{
|
|
echo_stderr("Query error:\n".$query."\n".$mysqli->error."\n");
|
|
return -1;
|
|
}
|
|
|
|
echo_debug(" group $group_name : ".$groups[$group_name]."\n");
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* ensure that the Group exists for this user_id.
|
|
*/
|
|
function ensure_group($user_id, $group)
|
|
{
|
|
global $mysqli;
|
|
|
|
$group_name = mes(urldecode($group->NAME));
|
|
|
|
$query = "SELECT contactgroup_id FROM `contactgroups` WHERE user_id=$user_id AND name='$group_name'";
|
|
if (!$group_ids = $mysqli->query($query))
|
|
{
|
|
echo_stderr("Query error:\n".$query."\n".$mysqli->error."\n");
|
|
return -1;
|
|
}
|
|
|
|
if ($group_ids->num_rows > 0)
|
|
{
|
|
$data = $group_ids->fetch_array();
|
|
return $data['contactgroup_id'];
|
|
}
|
|
|
|
//No group, must add it.
|
|
|
|
$group_changed = mes(urldecode($group->CHANGED));
|
|
|
|
$query = "INSERT INTO `contactgroups` (user_id, changed, name) VALUES ($user_id, '$group_changed', '$group_name')";
|
|
|
|
if (!$groups = $mysqli->query($query))
|
|
{
|
|
echo_stderr("Query error:\n".$query."\n".$mysqli->error."\n");
|
|
return -1;
|
|
}
|
|
|
|
return $mysqli->insert_id;
|
|
}
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
* ensure that the Contact exists for this user_id.
|
|
*/
|
|
function ensure_contact($user_id, $contact)
|
|
{
|
|
global $mysqli;
|
|
|
|
$contact_email = mes(urldecode($contact->EMAIL));
|
|
$contact_name = mes(urldecode($contact->NAME));
|
|
|
|
$query = "SELECT contact_id FROM `contacts` WHERE user_id=$user_id AND name='$contact_name' AND email='$contact_email' LIMIT 1";
|
|
if (!$contact_ids = $mysqli->query($query))
|
|
{
|
|
echo_stderr("Query error:\n".$query."\n".$mysqli->error."\n");
|
|
return -1;
|
|
}
|
|
|
|
if ($contact_ids->num_rows > 0)
|
|
{
|
|
$data = $contact_ids->fetch_array();
|
|
return $data['contact_id'];
|
|
}
|
|
|
|
//No contact, must add it.
|
|
|
|
$contact_changed = mes(urldecode($contact->CHANGED));
|
|
$contact_firstname = mes(urldecode($contact->FIRSTNAME));
|
|
$contact_surname = mes(urldecode($contact->SURNAME));
|
|
$contact_vcard = mes(urldecode($contact->VCARD));
|
|
$contact_words = mes(urldecode($contact->WORDS));
|
|
|
|
$query = "INSERT INTO `contacts` (changed, name, email, firstname, surname, vcard, words, user_id) VALUES ('$contact_changed', '$contact_name', '$contact_email', '$contact_firstname', '$contact_surname', '$contact_vcard', '$contact_words', $user_id)";
|
|
if (!$contact_ids = $mysqli->query($query))
|
|
{
|
|
echo_stderr("Query error:\n".$query."\n".$mysqli->error."\n");
|
|
return -1;
|
|
}
|
|
|
|
return $mysqli->insert_id;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* ensure that the Identity exists for this user_id.
|
|
* no need to worry about the return value
|
|
*/
|
|
function ensure_identity($user_id, $identity)
|
|
{
|
|
global $mysqli;
|
|
|
|
$id_email = mes(urldecode($identity->EMAIL));
|
|
$id_name = mes(urldecode($identity->NAME));
|
|
|
|
$query = "SELECT identity_id FROM `identities` WHERE user_id=$user_id AND name='$id_name' AND email='$id_email' LIMIT 1";
|
|
if (!$ids = $mysqli->query($query))
|
|
{
|
|
echo_stderr("Query error:\n".$query."\n".$mysqli->error."\n");
|
|
return -1;
|
|
}
|
|
|
|
if ($ids->num_rows > 0)
|
|
{
|
|
$data = $ids->fetch_array();
|
|
return $data['identity_id'];
|
|
}
|
|
|
|
//No identity, must add it.
|
|
$id_changed = mes(urldecode($identity->CHANGED));
|
|
$id_standard = mes(urldecode($identity->STANDARD));
|
|
$id_organization = mes(urldecode($identity->ORGANIZATION));
|
|
$id_reply_to = mes(urldecode($identity['REPLY-TO']));
|
|
$id_bcc = mes(urldecode($identity->BCC));
|
|
$id_signature = mes(urldecode($identity->SIGNATURE));
|
|
$id_html_signature =mes(urldecode($identity->HTML_SIGNATURE));
|
|
|
|
$query = "INSERT INTO `identities` (user_id, changed, standard, name, organization, email, `reply-to`, bcc, signature, html_signature) VALUES ($user_id, '$id_changed', $id_standard, '$id_name', '$id_organization', '$id_email', '$id_reply_to', '$id_bcc', '$id_signature', $id_html_signature)";
|
|
if (!$ids = $mysqli->query($query))
|
|
{
|
|
echo_stderr("Query error:\n".$query."\n".$mysqli->error."\n");
|
|
return -1;
|
|
}
|
|
|
|
return $mysqli->insert_id;
|
|
}
|
|
|
|
/**********************************************************************
|
|
* ensure that the User exists
|
|
* yes: return user_id
|
|
* no: add user, set data, resturn user_id
|
|
*/
|
|
function ensure_user($email)
|
|
{
|
|
global $mysqli, $rc_mail_host;
|
|
$username = mes(urldecode($email->USERNAME));
|
|
$query = "SELECT user_id FROM `users` WHERE username='$username' LIMIT 1";
|
|
if (!$users = $mysqli->query($query))
|
|
{
|
|
echo_stderr("Query error:\n".$query."\n".$mysqli->error."\n");
|
|
return -1;
|
|
}
|
|
|
|
if ($users->num_rows > 0)
|
|
{
|
|
$data = $users->fetch_array();
|
|
return $data['user_id'];
|
|
}
|
|
|
|
//No User, must add it.
|
|
$created=mes(urldecode($email->CREATED));
|
|
$last_login=mes(urldecode($email->LAST_LOGIN));
|
|
$language=mes(urldecode($email->LANGUAGE));
|
|
$preferences=mes(urldecode($email->PREFERENCES));
|
|
|
|
$query = "INSERT INTO `users` (username, mail_host, created, last_login, language, preferences) VALUES ('$username', '$rc_mail_host', '$created', '$last_login', '$language', '$preferences')";
|
|
if (!$users = $mysqli->query($query))
|
|
{
|
|
echo_stderr("Query error:\n".$query."\n".$mysqli->error."\n");
|
|
return -1;
|
|
}
|
|
|
|
return $mysqli->insert_id;
|
|
}
|
|
|
|
//**********************************************************************
|
|
|
|
function show_help()
|
|
{
|
|
global $mysql_db, $version;
|
|
|
|
echo_stderr("Roundcube $version restore script to restore Users.\n\n");
|
|
echo_stderr("Usage:\n");
|
|
echo_stderr(" username=username domain=domain.com xml_file=/path/to/rc.xml ".__FILE__."\n\n");
|
|
|
|
echo_stderr("The script will read in the XML specified by xml_file.\n");
|
|
echo_stderr("It will insert the data into the $mysql_db database.\n");
|
|
exit(2);
|
|
}
|
|
|
|
function die_stderr($str)
|
|
{
|
|
echo_stderr($str);
|
|
die();
|
|
}
|
|
|
|
function echo_stderr($str)
|
|
{
|
|
$fd = fopen('php://stderr', 'w');
|
|
fwrite($fd, $str);
|
|
fclose($fd);
|
|
}
|
|
|
|
function echo_debug($str)
|
|
{
|
|
global $is_debug;
|
|
|
|
if ($is_debug)
|
|
echo $str;
|
|
}
|
|
|
|
function mes($str)
|
|
{
|
|
global $mysqli;
|
|
return $mysqli->real_escape_string($str);
|
|
}
|
|
|
|
?>
|