Installer: Remove system() function use (#1490139)

Move some functionality of scripts from bin/ into rcmail_utils class
dev-fontawesome
Aleksander Machniak 9 years ago
parent 76573685d9
commit e7620812b0

@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
- Installer: Remove system() function use (#1490139)
- Password plugin: Added 'kpasswd' driver by Peter Allgeyer
- Add initdb.sh to create database from initial.sql script with prefix support (#1490188)
- Plugin API: Added message_part_body hook

@ -5,7 +5,7 @@
| bin/cleandb.sh |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2010, The Roundcube Dev Team |
| Copyright (C) 2010-2015, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
@ -23,56 +23,11 @@ define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require INSTALL_PATH.'program/include/clisetup.php';
// mapping for table name => primary key
$primary_keys = array(
'contacts' => "contact_id",
'contactgroups' => "contactgroup_id",
);
// connect to DB
$RCMAIL = rcube::get_instance();
$db = $RCMAIL->get_dbh();
$db->db_connect('w');
if (!$db->is_connected() || $db->is_error()) {
rcube::raise_error("No DB connection", false, true);
}
if (!empty($_SERVER['argv'][1]))
$days = intval($_SERVER['argv'][1]);
else
$days = 7;
// remove all deleted records older than two days
$threshold = date('Y-m-d 00:00:00', time() - $days * 86400);
foreach (array('contacts','contactgroups','identities') as $table) {
$sqltable = $db->table_name($table, true);
// also delete linked records
// could be skipped for databases which respect foreign key constraints
if ($db->db_provider == 'sqlite'
&& ($table == 'contacts' || $table == 'contactgroups')
) {
$pk = $primary_keys[$table];
$memberstable = $db->table_name('contactgroupmembers');
$db->query(
"DELETE FROM " . $db->quote_identifier($memberstable).
" WHERE `$pk` IN (".
"SELECT `$pk` FROM $sqltable".
" WHERE `del` = 1 AND `changed` < ?".
")",
$threshold);
echo $db->affected_rows() . " records deleted from '$memberstable'\n";
}
// delete outdated records
$db->query("DELETE FROM $sqltable WHERE `del` = 1 AND `changed` < ?", $threshold);
echo $db->affected_rows() . " records deleted from '$table'\n";
}
rcmail_utils::db_clean($days);
?>

@ -24,31 +24,6 @@ define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require_once INSTALL_PATH.'program/include/clisetup.php';
ini_set('memory_limit', -1);
// connect to DB
$RCMAIL = rcube::get_instance();
$db = $RCMAIL->get_dbh();
$db->db_connect('w');
if (!$db->is_connected() || $db->is_error()) {
rcube::raise_error("No DB connection", false, true);
}
// iterate over all users
$sql_result = $db->query("SELECT `user_id` FROM " . $db->table_name('users', true) . " ORDER BY `user_id`");
while ($sql_result && ($sql_arr = $db->fetch_assoc($sql_result))) {
echo "Indexing contacts for user " . $sql_arr['user_id'] . "...";
$contacts = new rcube_contacts($db, $sql_arr['user_id']);
$contacts->set_pagesize(9999);
$result = $contacts->list_records();
while ($result->count && ($row = $result->next())) {
unset($row['words']);
$contacts->update($row['ID'], $row);
}
echo "done.\n";
}
rcmail_utils::indexcontacts();
?>

@ -37,39 +37,6 @@ if (!file_exists($opts['dir'])) {
rcube::raise_error("Specified database schema directory doesn't exist.", false, true);
}
$RC = rcube::get_instance();
$DB = rcube_db::factory($RC->config->get('db_dsnw'));
$DB->set_debug((bool)$RC->config->get('sql_debug'));
// Connect to database
$DB->db_connect('w');
if (!$DB->is_connected()) {
rcube::raise_error("Error connecting to database: " . $DB->is_error(), false, true);
}
$file = $opts['dir'] . '/' . $DB->db_provider . '.initial.sql';
if (!file_exists($file)) {
rcube::raise_error("DDL file $file not found", false, true);
}
echo "Creating database schema... ";
if ($sql = file_get_contents($file)) {
if (!$DB->exec_script($sql)) {
$error = $DB->is_error();
}
}
else {
$error = "Unable to read file $file or it is empty";
}
if ($error) {
echo "[FAILED]\n";
rcube::raise_error($error, false, true);
}
else {
echo "[OK]\n";
}
rcmail_utils::db_init($opts['dir']);
?>

@ -5,7 +5,7 @@
| bin/moduserprefs.sh |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2012, The Roundcube Dev Team |
| Copyright (C) 2012-2015, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
@ -46,37 +46,6 @@ else if (empty($args[0]) || (!isset($args[1]) && !$args['delete'])) {
$pref_name = trim($args[0]);
$pref_value = $args['delete'] ? null : trim($args[1]);
// connect to DB
$rcmail = rcube::get_instance();
$db = $rcmail->get_dbh();
$db->db_connect('w');
if (!$db->is_connected() || $db->is_error())
die("No DB connection\n" . $db->is_error());
$query = '1=1';
if ($args['user'])
$query = '`user_id` = ' . intval($args['user']);
// iterate over all users
$sql_result = $db->query("SELECT * FROM " . $db->table_name('users', true) . " WHERE $query");
while ($sql_result && ($sql_arr = $db->fetch_assoc($sql_result))) {
echo "Updating prefs for user " . $sql_arr['user_id'] . "...";
$user = new rcube_user($sql_arr['user_id'], $sql_arr);
$prefs = $old_prefs = $user->get_prefs();
$prefs[$pref_name] = $pref_value;
if ($prefs != $old_prefs) {
$user->save_prefs($prefs);
echo "saved.\n";
}
else {
echo "nothing changed.\n";
}
}
rcmail_utils::mod_pref($pref_name, $pref_value, $args['user']);
?>

@ -156,10 +156,8 @@ if ($RCI->configured) {
// check database schema
if ($RCI->config['db_dsnw']) {
echo "Executing database schema update.\n";
system("php " . INSTALL_PATH . "bin/updatedb.sh --package=roundcube --version=" . $opts['version']
. " --dir=" . INSTALL_PATH . "SQL", $res);
$success = !$res;
$success = rcmail_utils::db_update(INSTALL_PATH . 'SQL', 'roundcube', $opts['version'],
array('errors' => true));
}
// update composer dependencies
@ -239,7 +237,7 @@ if ($RCI->configured) {
// index contacts for fulltext searching
if ($opts['version'] && version_compare(version_parse($opts['version']), '0.6.0', '<')) {
system("php " . INSTALL_PATH . 'bin/indexcontacts.sh');
rcmail_utils::indexcontacts();
}
if ($success) {

@ -37,142 +37,6 @@ if (empty($opts['package'])) {
rcube::raise_error("Database schema package name not specified (--package).", false, true);
}
// Check if directory exists
if (!file_exists($opts['dir'])) {
rcube::raise_error("Specified database schema directory doesn't exist.", false, true);
}
$RC = rcube::get_instance();
$DB = rcube_db::factory($RC->config->get('db_dsnw'));
$DB->set_debug((bool)$RC->config->get('sql_debug'));
// Connect to database
$DB->db_connect('w');
if (!$DB->is_connected()) {
rcube::raise_error("Error connecting to database: " . $DB->is_error(), false, true);
}
// Read DB schema version from database (if 'system' table exists)
if (in_array($DB->table_name('system'), (array)$DB->list_tables())) {
$DB->query("SELECT `value`"
." FROM " . $DB->table_name('system', true)
." WHERE `name` = ?",
$opts['package'] . '-version');
$row = $DB->fetch_array();
$version = preg_replace('/[^0-9]/', '', $row[0]);
}
// DB version not found, but release version is specified
if (!$version && $opts['version']) {
// Map old release version string to DB schema version
// Note: This is for backward compat. only, do not need to be updated
$map = array(
'0.1-stable' => 1,
'0.1.1' => 2008030300,
'0.2-alpha' => 2008040500,
'0.2-beta' => 2008060900,
'0.2-stable' => 2008092100,
'0.2.1' => 2008092100,
'0.2.2' => 2008092100,
'0.3-stable' => 2008092100,
'0.3.1' => 2009090400,
'0.4-beta' => 2009103100,
'0.4' => 2010042300,
'0.4.1' => 2010042300,
'0.4.2' => 2010042300,
'0.5-beta' => 2010100600,
'0.5' => 2010100600,
'0.5.1' => 2010100600,
'0.5.2' => 2010100600,
'0.5.3' => 2010100600,
'0.5.4' => 2010100600,
'0.6-beta' => 2011011200,
'0.6' => 2011011200,
'0.7-beta' => 2011092800,
'0.7' => 2011111600,
'0.7.1' => 2011111600,
'0.7.2' => 2011111600,
'0.7.3' => 2011111600,
'0.7.4' => 2011111600,
'0.8-beta' => 2011121400,
'0.8-rc' => 2011121400,
'0.8.0' => 2011121400,
'0.8.1' => 2011121400,
'0.8.2' => 2011121400,
'0.8.3' => 2011121400,
'0.8.4' => 2011121400,
'0.8.5' => 2011121400,
'0.8.6' => 2011121400,
'0.9-beta' => 2012080700,
);
$version = $map[$opts['version']];
}
// Assume last version before the 'system' table was added
if (empty($version)) {
$version = 2012080700;
}
$dir = $opts['dir'] . '/' . $DB->db_provider;
if (!file_exists($dir)) {
rcube::raise_error("DDL Upgrade files for " . $DB->db_provider . " driver not found.", false, true);
}
$dh = opendir($dir);
$result = array();
while ($file = readdir($dh)) {
if (preg_match('/^([0-9]+)\.sql$/', $file, $m) && $m[1] > $version) {
$result[] = $m[1];
}
}
sort($result, SORT_NUMERIC);
foreach ($result as $v) {
echo "Updating database schema ($v)... ";
$error = update_db_schema($opts['package'], $v, "$dir/$v.sql");
if ($error) {
echo "[FAILED]\n";
rcube::raise_error("Error in DDL upgrade $v: $error", false, true);
}
echo "[OK]\n";
}
function update_db_schema($package, $version, $file)
{
global $DB;
// read DDL file
if ($sql = file_get_contents($file)) {
if (!$DB->exec_script($sql)) {
return $DB->is_error();
}
}
// escape if 'system' table does not exist
if ($version < 2013011000) {
return;
}
$system_table = $DB->table_name('system', true);
$DB->query("UPDATE " . $system_table
." SET `value` = ?"
." WHERE `name` = ?",
$version, $package . '-version');
if (!$DB->is_error() && !$DB->affected_rows()) {
$DB->query("INSERT INTO " . $system_table
." (`name`, `value`) VALUES (?, ?)",
$package . '-version', $version);
}
return $DB->is_error();
}
rcmail_utils::db_update($opts['dir'], $opts['package'], $opts['version'], array('errors' => true));
?>

@ -773,12 +773,8 @@ class rcmail_install
*/
function update_db($version)
{
system(INSTALL_PATH . "bin/updatedb.sh --package=roundcube"
. " --version=" . escapeshellarg($version)
. " --dir=" . INSTALL_PATH . "SQL"
. " 2>&1", $result);
return !$result;
return rcmail_utils::db_update(INSTALL_PATH . 'SQL', 'roundcube', $version,
array('quiet' => true));
}

@ -0,0 +1,362 @@
<?php
/*
+-----------------------------------------------------------------------+
| program/include/rcmail_utils.php |
| |
| This file is part of the Roundcube PHP suite |
| Copyright (C) 2005-2015 The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| CONTENTS: |
| Roundcube utilities |
| |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
/**
* Roundcube utilities
*
* @package Webmail
* @subpackage Utils
*/
class rcmail_utils
{
public static $db;
/**
* Initialize database object and connect
*
* @return rcube_db Database instance
*/
public static function db()
{
if (self::$db === null) {
$rc = rcube::get_instance();
$db = rcube_db::factory($rc->config->get('db_dsnw'));
$db->set_debug((bool)$rc->config->get('sql_debug'));
// Connect to database
$db->db_connect('w');
if (!$db->is_connected()) {
rcube::raise_error("Error connecting to database: " . $db->is_error(), false, true);
}
self::$db = $db;
}
return self::$db;
}
/**
* Initialize database schema
*
* @param string Directory with sql files
*/
public static function db_init($dir)
{
$db = self::db();
$file = $dir . '/' . $db->db_provider . '.initial.sql';
if (!file_exists($file)) {
rcube::raise_error("DDL file $file not found", false, true);
}
echo "Creating database schema... ";
if ($sql = file_get_contents($file)) {
if (!$db->exec_script($sql)) {
$error = $db->is_error();
}
}
else {
$error = "Unable to read file $file or it is empty";
}
if ($error) {
echo "[FAILED]\n";
rcube::raise_error($error, false, true);
}
else {
echo "[OK]\n";
}
}
/**
* Update database schema
*
* @param string Directory with sql files
* @param string Component name
* @param string Optional current version number
* @param array Parameters (errors, quiet)
*
* @return True on success, False on failure
*/
public static function db_update($dir, $package, $ver = null, $opts = array())
{
// Check if directory exists
if (!file_exists($dir)) {
if ($opts['errors']) {
rcube::raise_error("Specified database schema directory doesn't exist.", false, true);
}
return false;
}
$db = self::db();
// Read DB schema version from database (if 'system' table exists)
if (in_array($db->table_name('system'), (array)$db->list_tables())) {
$db->query("SELECT `value`"
. " FROM " . $db->table_name('system', true)
. " WHERE `name` = ?",
$package . '-version');
$row = $db->fetch_array();
$version = preg_replace('/[^0-9]/', '', $row[0]);
}
// DB version not found, but release version is specified
if (!$version && $ver) {
// Map old release version string to DB schema version
// Note: This is for backward compat. only, do not need to be updated
$map = array(
'0.1-stable' => 1,
'0.1.1' => 2008030300,
'0.2-alpha' => 2008040500,
'0.2-beta' => 2008060900,
'0.2-stable' => 2008092100,
'0.2.1' => 2008092100,
'0.2.2' => 2008092100,
'0.3-stable' => 2008092100,
'0.3.1' => 2009090400,
'0.4-beta' => 2009103100,
'0.4' => 2010042300,
'0.4.1' => 2010042300,
'0.4.2' => 2010042300,
'0.5-beta' => 2010100600,
'0.5' => 2010100600,
'0.5.1' => 2010100600,
'0.5.2' => 2010100600,
'0.5.3' => 2010100600,
'0.5.4' => 2010100600,
'0.6-beta' => 2011011200,
'0.6' => 2011011200,
'0.7-beta' => 2011092800,
'0.7' => 2011111600,
'0.7.1' => 2011111600,
'0.7.2' => 2011111600,
'0.7.3' => 2011111600,
'0.7.4' => 2011111600,
'0.8-beta' => 2011121400,
'0.8-rc' => 2011121400,
'0.8.0' => 2011121400,
'0.8.1' => 2011121400,
'0.8.2' => 2011121400,
'0.8.3' => 2011121400,
'0.8.4' => 2011121400,
'0.8.5' => 2011121400,
'0.8.6' => 2011121400,
'0.9-beta' => 2012080700,
);
$version = $map[$ver];
}
// Assume last version before the 'system' table was added
if (empty($version)) {
$version = 2012080700;
}
$dir .= '/' . $db->db_provider;
if (!file_exists($dir)) {
if ($opts['errors']) {
rcube::raise_error("DDL Upgrade files for " . $db->db_provider . " driver not found.", false, true);
}
return false;
}
$dh = opendir($dir);
$result = array();
while ($file = readdir($dh)) {
if (preg_match('/^([0-9]+)\.sql$/', $file, $m) && $m[1] > $version) {
$result[] = $m[1];
}
}
sort($result, SORT_NUMERIC);
foreach ($result as $v) {
if (!$opts['quiet']) {
echo "Updating database schema ($v)... ";
}
$error = self::db_update_schema($package, $v, "$dir/$v.sql");
if ($error) {
if (!$opts['quiet']) {
echo "[FAILED]\n";
}
if ($opts['errors']) {
rcube::raise_error("Error in DDL upgrade $v: $error", false, true);
}
return false;
}
else if (!$opts['quiet']) {
echo "[OK]\n";
}
}
return true;
}
/**
* Run database update from a single sql file
*/
protected static function db_update_schema($package, $version, $file)
{
$db = self::db();
// read DDL file
if ($sql = file_get_contents($file)) {
if (!$db->exec_script($sql)) {
return $db->is_error();
}
}
// escape if 'system' table does not exist
if ($version < 2013011000) {
return;
}
$system_table = $db->table_name('system', true);
$db->query("UPDATE " . $system_table
. " SET `value` = ?"
. " WHERE `name` = ?",
$version, $package . '-version');
if (!$db->is_error() && !$db->affected_rows()) {
$db->query("INSERT INTO " . $system_table
." (`name`, `value`) VALUES (?, ?)",
$package . '-version', $version);
}
return $db->is_error();
}
/**
* Removes all deleted records older than X days
*
* @param int Number of days
*/
public static function db_clean($days)
{
// mapping for table name => primary key
$primary_keys = array(
'contacts' => 'contact_id',
'contactgroups' => 'contactgroup_id',
);
$db = self::db();
$threshold = date('Y-m-d 00:00:00', time() - $days * 86400);
foreach (array('contacts','contactgroups','identities') as $table) {
$sqltable = $db->table_name($table, true);
// also delete linked records
// could be skipped for databases which respect foreign key constraints
if ($db->db_provider == 'sqlite' && ($table == 'contacts' || $table == 'contactgroups')) {
$pk = $primary_keys[$table];
$memberstable = $db->table_name('contactgroupmembers');
$db->query(
"DELETE FROM " . $db->quote_identifier($memberstable)
. " WHERE `$pk` IN ("
. "SELECT `$pk` FROM $sqltable"
. " WHERE `del` = 1 AND `changed` < ?"
. ")",
$threshold);
echo $db->affected_rows() . " records deleted from '$memberstable'\n";
}
// delete outdated records
$db->query("DELETE FROM $sqltable WHERE `del` = 1 AND `changed` < ?", $threshold);
echo $db->affected_rows() . " records deleted from '$table'\n";
}
}
/**
* Reindex contacts
*/
public static function indexcontacts()
{
$db = self::db();
// iterate over all users
$sql_result = $db->query("SELECT `user_id` FROM " . $db->table_name('users', true) . " ORDER BY `user_id`");
while ($sql_result && ($sql_arr = $db->fetch_assoc($sql_result))) {
echo "Indexing contacts for user " . $sql_arr['user_id'] . "...\n";
$contacts = new rcube_contacts($db, $sql_arr['user_id']);
$contacts->set_pagesize(9999);
$result = $contacts->list_records();
while ($result->count && ($row = $result->next())) {
unset($row['words']);
$contacts->update($row['ID'], $row);
}
}
echo "done.\n";
}
/**
* Modify user preferences
*
* @param string Option name
* @param string Option value
* @param int Optional user identifier
*/
public static function mod_pref($name, $value, $userid = null)
{
$db = self::db();
if ($userid) {
$query = '`user_id` = ' . intval($userid);
}
else {
$query = '1=1';
}
// iterate over all users
$sql_result = $db->query("SELECT * FROM " . $db->table_name('users', true) . " WHERE $query");
while ($sql_result && ($sql_arr = $db->fetch_assoc($sql_result))) {
echo "Updating prefs for user " . $sql_arr['user_id'] . "...";
$user = new rcube_user($sql_arr['user_id'], $sql_arr);
$prefs = $old_prefs = $user->get_prefs();
$prefs[$name] = $value;
if ($prefs != $old_prefs) {
$user->save_prefs($prefs);
echo "saved.\n";
}
else {
echo "nothing changed.\n";
}
}
}
}
Loading…
Cancel
Save