From 238ec39583299a29b87de102463c29da1e0a2493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Cuj=C3=A9?= Date: Wed, 27 Jul 2016 13:38:41 +0200 Subject: [PATCH 1/2] add option to use external database --- sql_global_addressbooks/config.inc.php.dist | 11 +++++++ .../sql_global_backend.php | 33 ++++++++++++++----- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/sql_global_addressbooks/config.inc.php.dist b/sql_global_addressbooks/config.inc.php.dist index ad889f9..13c54db 100644 --- a/sql_global_addressbooks/config.inc.php.dist +++ b/sql_global_addressbooks/config.inc.php.dist @@ -6,6 +6,17 @@ All Configuration Options are Tabbed. Default Disabled Configuration starts '//' Any line being Commented Out or Removed is the Same as Leaving it at Default, or Disabled. So Remove Lines for any Books you do not wish to use to simplify this Configuration File. */ +/* +Use these parameters to connect to an external database. +If the database type value is empty (default), the roundcube database is used. */ +// $config['_database_type'] = ''; +// $config['_database_host'] = 'localhost'; +/* If the port value is empty (default), it's set by the database driver */ +// $config['_database_port'] = ''; +// $config['_database_user'] = 'roundcube'; +// $config['_database_pass'] = ''; +// $config['_database_name'] = 'roundcubemail'; + /* The `Domain Book` is an Address Book which will contain all the members which have the same e-mail domain as the logged in user themself, the only values for configuration are: diff --git a/sql_global_addressbooks/sql_global_backend.php b/sql_global_addressbooks/sql_global_backend.php index d267211..4a00333 100644 --- a/sql_global_addressbooks/sql_global_backend.php +++ b/sql_global_addressbooks/sql_global_backend.php @@ -16,11 +16,26 @@ class sql_global_backend extends rcube_addressbook { public $primary_key = 'ID'; public $readonly = true; - private $filter, $result, $name; + private $filter, $result, $name, $db; public function __construct($name) { $this->ready = true; $this->name = $name; + $dbtype = rcmail::get_instance()->config->get('_database_type', ''); + if (empty($dbtype)) { + // use roundcube native database + $this->db = rcube::get_instance()->db; + } else { + // setup connection to external database + $dbhost = rcmail::get_instance()->config->get('_database_host', ''); + $dbport = rcmail::get_instance()->config->get('_database_port', ''); + $dbuser = rcmail::get_instance()->config->get('_database_user', 'roundcube'); + $dbpass = rcmail::get_instance()->config->get('_database_pass', ''); + $dbname = rcmail::get_instance()->config->get('_database_name', 'roundcubemail'); + if (!empty($dbport)) { $dbport = ':'.$dbport; } + $dsn = $dbtype.'://'.$dbuser.':'.$dbpass.'@'.$dbhost.$dbport.'/'.$dbname; + $this->db = rcube_db::factory($dsn); + } } public function get_name() { return $this->name; } @@ -33,7 +48,7 @@ public function reset() { } public function get_record($id, $assoc=false) { - $db = rcube::get_instance()->db; + $db = $this->db; $db->query('SELECT * FROM global_addressbook WHERE `ID`=?', $id); if ($sql_arr = $db->fetch_assoc()) { $sql_arr['email'] = explode(',', $sql_arr['email']); @@ -47,7 +62,7 @@ public function get_record($id, $assoc=false) { public function list_records($cols=null, $subset=0) { $this->result = $this->count(); - $db = rcube::get_instance()->db; + $db = $this->db; if (empty($this->group_id)) { @@ -104,21 +119,21 @@ function list_groups($search = null, $mode=0) { if ($search) { switch (intval($mode)) { case 1: - $x = $rc->db->ilike('domain', $search); + $x = $db->ilike('domain', $search); break; case 2: - $x = $rc->db->ilike('domain', $search . '%'); + $x = $db->ilike('domain', $search . '%'); break; default: - $x = $rc->db->ilike('domain', '%' . $search . '%'); + $x = $db->ilike('domain', '%' . $search . '%'); } $x = ' WHERE ' . $x . ' '; } else { $x = ' '; } if ($cf === array('*')) { $cf = array(); - $rc->db->query('SELECT domain FROM global_addressbook' . $x . 'GROUP BY domain'); - while ($ret = $rc->db->fetch_assoc()) {$cf[] = $ret['domain']; } + $db->query('SELECT domain FROM global_addressbook' . $x . 'GROUP BY domain'); + while ($ret = $db->fetch_assoc()) {$cf[] = $ret['domain']; } } $co = array(); @@ -133,7 +148,7 @@ public function search($fields, $value, $strict=false, $select=true, $nocount=fa if (!is_array($required) && !empty($required)) { $required = array($required); } - $db = rcube::get_instance()->db; + $db = $this->db; $where = array(); $mode = intval($mode); $WS = ' '; From 43c0a2cf52772dbd30c642c0fbf327c9f52e394c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Cuj=C3=A9?= Date: Wed, 27 Jul 2016 14:11:38 +0200 Subject: [PATCH 2/2] fix indentation --- .../sql_global_backend.php | 218 +++++++++--------- 1 file changed, 104 insertions(+), 114 deletions(-) diff --git a/sql_global_addressbooks/sql_global_backend.php b/sql_global_addressbooks/sql_global_backend.php index 4a00333..e3d6232 100644 --- a/sql_global_addressbooks/sql_global_backend.php +++ b/sql_global_addressbooks/sql_global_backend.php @@ -20,7 +20,7 @@ class sql_global_backend extends rcube_addressbook { public function __construct($name) { $this->ready = true; - $this->name = $name; + $this->name = $name; $dbtype = rcmail::get_instance()->config->get('_database_type', ''); if (empty($dbtype)) { // use roundcube native database @@ -67,31 +67,33 @@ public function list_records($cols=null, $subset=0) { if (empty($this->group_id)) { switch ($this->name) { - case 'global': - $cf = rcmail::get_instance()->config->get('_sql_gb_data_allowed', array('*')); - $fc = rcmail::get_instance()->config->get('_sql_gb_data_hidden', array()); - if ($cf === array('*')) { - $cf = array(); - } else { $x[] = 'domain IN (' . $db->array2list($cf) . ')'; } - if ($this->filter) { $x[] = '(' . $this->filter .')'; } - if (count($fc) > 0) { $x[] = 'domain NOT IN (' . $db->array2list($fc) . ')'; } - $x = count($x) > 0 ? (' WHERE ' . implode(' AND ', $x)):''; - $db->query('SELECT * FROM global_addressbook' . $x); - break; - - case 'domain': - $x = $this->filter ? (' (' . $this->filter . ') AND '):' '; - $db->query('SELECT * FROM global_addressbook WHERE' . $x . 'domain=?', rcmail::get_instance()->user->get_username('domain')); - break; - - default: - $d = rcmail::get_instance()->config->get('_sql_supportbook', array()); - $f = array_flip(sql_global_addressbooks::ac($d, 0)); - array_shift($z = $d[$f[$this->name]]); - if ($this->filter) { $x[] = '(' . $this->filter .')'; } - if (count($z) > 0) { $x[] = 'domain IN (' . $db->array2list($z) . ')'; } - $x = count($x)> 0 ? (' WHERE ' . implode(' AND ', $x)):''; - $db->query('SELECT * FROM global_addressbook' . $x); + case 'global': + $cf = rcmail::get_instance()->config->get('_sql_gb_data_allowed', array('*')); + $fc = rcmail::get_instance()->config->get('_sql_gb_data_hidden', array()); + if ($cf === array('*')) { + $cf = array(); + } else { + $x[] = 'domain IN (' . $db->array2list($cf) . ')'; + } + if ($this->filter) { $x[] = '(' . $this->filter .')'; } + if (count($fc) > 0) { $x[] = 'domain NOT IN (' . $db->array2list($fc) . ')'; } + $x = count($x) > 0 ? (' WHERE ' . implode(' AND ', $x)):''; + $db->query('SELECT * FROM global_addressbook' . $x); + break; + + case 'domain': + $x = $this->filter ? (' (' . $this->filter . ') AND '):' '; + $db->query('SELECT * FROM global_addressbook WHERE' . $x . 'domain=?', rcmail::get_instance()->user->get_username('domain')); + break; + + default: + $d = rcmail::get_instance()->config->get('_sql_supportbook', array()); + $f = array_flip(sql_global_addressbooks::ac($d, 0)); + array_shift($z = $d[$f[$this->name]]); + if ($this->filter) { $x[] = '(' . $this->filter .')'; } + if (count($z) > 0) { $x[] = 'domain IN (' . $db->array2list($z) . ')'; } + $x = count($x)> 0 ? (' WHERE ' . implode(' AND ', $x)):''; + $db->query('SELECT * FROM global_addressbook' . $x); } } else { @@ -101,9 +103,6 @@ public function list_records($cols=null, $subset=0) { while ($ret = $db->fetch_assoc()) { $ret['email'] = explode(',', $ret['email']); - //$names = explode(' ', $ret['name']); - //$ret['surname'] = array_push($names); - //$ret['firsname']= implode(' ', $names); $this->result->add($ret); } return $this->result; @@ -118,16 +117,16 @@ function list_groups($search = null, $mode=0) { if ($search) { switch (intval($mode)) { - case 1: - $x = $db->ilike('domain', $search); - break; - case 2: - $x = $db->ilike('domain', $search . '%'); - break; - default: - $x = $db->ilike('domain', '%' . $search . '%'); - } - $x = ' WHERE ' . $x . ' '; + case 1: + $x = $db->ilike('domain', $search); + break; + case 2: + $x = $db->ilike('domain', $search . '%'); + break; + default: + $x = $db->ilike('domain', '%' . $search . '%'); + } + $x = ' WHERE ' . $x . ' '; } else { $x = ' '; } if ($cf === array('*')) { @@ -138,94 +137,85 @@ function list_groups($search = null, $mode=0) { $co = array(); foreach (array_diff($cf, $fc) as $v) { $co[] = array('ID' => $v, 'name' => $v); } - //file_put_contents('/var/www/test.log', print_r([$co, $search, $mode, $this->groups, $this->name, $this->group_id], true)); return $co; } public function search($fields, $value, $strict=false, $select=true, $nocount=false, $required=array()) { if (!is_array($fields)) { $fields = array($fields); } - if (!is_array($required) && !empty($required)) { $required = array($required); } - - - $db = $this->db; - $where = array(); - $mode = intval($mode); - $WS = ' '; - - foreach ($fields as $idx => $col) { - - if ($col == 'ID' || $col == $this->primary_key) { - $ids = !is_array($value) ? explode(',', $value) : $value; - $ids = $db->array2list($ids, 'integer'); - $where[] = 'c.' . $this->primary_key.' IN ('.$ids.')'; - continue; - } else if ($col == '*') { - $words = array(); - foreach (explode($WS, rcube_utils::normalize_string($value)) as $word) { - switch ($mode) { - case 1: // Strict - $words[]='(' . $db->ilike('name', $word . '%') - . ' OR ' . $db->ilike('email',$word . '%') - . ' OR ' . $db->ilike('name', '%' . $WS . $word . $WS . '%') - . ' OR ' . $db->ilike('email','%' . $WS . $word . $WS . '%') - . ' OR ' . $db->ilike('name', '%' . $WS . $word) - . ' OR ' . $db->ilike('email','%' . $WS . $word). ')'; - break; - - case 2: // Prefix - $words[]='(' . $db->ilike('name', $word . '%') - . ' OR ' . $db->ilike('email',$word . '%') - . ' OR ' . $db->ilike('name', '%' . $WS . $word . '%') - . ' OR ' . $db->ilike('email','%' . $WS . $word . '%') . ')'; - break; - - default: // Partial - $words[]='(' . $db->ilike('name', '%' . $word . '%') - . ' OR ' . $db->ilike('email','%' . $word . '%') . ')'; - break; - } - } - $where[] = '(' . join(' AND ', $words) . ')'; - //} else { - } elseif ($col !== 'firstname' && $col !== 'surname') { - $val = is_array($value) ? $value[$idx] : $value; - - switch ($mode) { - case 1: // strict - $where[] = '(' . $db->quote_identifier($col) . ' = ' . $db->quote($val) - . ' OR ' . $db->ilike($col, $val . $AS . '%') - . ' OR ' . $db->ilike($col, '%' . $AS . $val . $AS . '%') - . ' OR ' . $db->ilike($col, '%' . $AS . $val) . ')'; - break; - case 2: // prefix - $where[] = '(' . $db->ilike($col, $val . '%') - . ' OR ' . $db->ilike($col, $AS . $val . '%') . ')'; - break; - default: // partial - $where[] = $db->ilike($col, '%' . $val . '%'); - } - } - - if (!empty($where)) { - $this->set_search_set(join(is_array($value) ? ' AND ' : ' OR ', $where)); - /*if ($select) { - $this->list_records(null, 0, $nocount); - } else { $this->result = $this->count(); */ - } - - } + if (!is_array($required) && !empty($required)) { $required = array($required); } + + $db = $this->db; + $where = array(); + $mode = intval($mode); + $WS = ' '; + + foreach ($fields as $idx => $col) { + + if ($col == 'ID' || $col == $this->primary_key) { + $ids = !is_array($value) ? explode(',', $value) : $value; + $ids = $db->array2list($ids, 'integer'); + $where[] = 'c.' . $this->primary_key.' IN ('.$ids.')'; + continue; + } else if ($col == '*') { + $words = array(); + foreach (explode($WS, rcube_utils::normalize_string($value)) as $word) { + switch ($mode) { + case 1: // strict + $words[]='(' . $db->ilike('name', $word . '%') + . ' OR ' . $db->ilike('email',$word . '%') + . ' OR ' . $db->ilike('name', '%' . $WS . $word . $WS . '%') + . ' OR ' . $db->ilike('email','%' . $WS . $word . $WS . '%') + . ' OR ' . $db->ilike('name', '%' . $WS . $word) + . ' OR ' . $db->ilike('email','%' . $WS . $word). ')'; + break; + + case 2: // prefix + $words[]='(' . $db->ilike('name', $word . '%') + . ' OR ' . $db->ilike('email',$word . '%') + . ' OR ' . $db->ilike('name', '%' . $WS . $word . '%') + . ' OR ' . $db->ilike('email','%' . $WS . $word . '%') . ')'; + break; + + default: // partial + $words[]='(' . $db->ilike('name', '%' . $word . '%') + . ' OR ' . $db->ilike('email','%' . $word . '%') . ')'; + break; + } + } + $where[] = '(' . join(' AND ', $words) . ')'; + } elseif ($col !== 'firstname' && $col !== 'surname') { + $val = is_array($value) ? $value[$idx] : $value; + + switch ($mode) { + case 1: // strict + $where[] = '(' . $db->quote_identifier($col) . ' = ' . $db->quote($val) + . ' OR ' . $db->ilike($col, $val . $AS . '%') + . ' OR ' . $db->ilike($col, '%' . $AS . $val . $AS . '%') + . ' OR ' . $db->ilike($col, '%' . $AS . $val) . ')'; + break; + case 2: // prefix + $where[] = '(' . $db->ilike($col, $val . '%') + . ' OR ' . $db->ilike($col, $AS . $val . '%') . ')'; + break; + default: // partial + $where[] = $db->ilike($col, '%' . $val . '%'); + } + } + if (!empty($where)) { + $this->set_search_set(join(is_array($value) ? ' AND ' : ' OR ', $where)); + } + + } return $this->list_records(); } + function get_group($group_id) { return $this->groups ? array('ID' => $group_id, 'name' => $group_id) : null; } public function count() { return new rcube_result_set(1, ($this->list_page-1) * $this->page_size); } public function get_result() { return $this->result; } - public function set_group($gid) { - $this->group_id = $gid; - $this->cache = null; - } + public function set_group($gid) { $this->group_id = $gid; $this->cache = null; } function create_group($name) { return false; } function delete_group($gid) { return false; } function rename_group($gid, $newname) { return $newname; }