From ed1d212ae2daea5e4bd043417610177093e99f19 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak <alec@alec.pl> Date: Sat, 16 Jan 2016 03:03:51 -0500 Subject: [PATCH] Improved SVG cleanup code --- program/lib/Roundcube/rcube_addressbook.php | 212 ++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 154 insertions(+), 58 deletions(-) diff --git a/program/lib/Roundcube/rcube_addressbook.php b/program/lib/Roundcube/rcube_addressbook.php index 84bd4bf..325b48a 100644 --- a/program/lib/Roundcube/rcube_addressbook.php +++ b/program/lib/Roundcube/rcube_addressbook.php @@ -1,9 +1,9 @@ <?php -/* +/** +-----------------------------------------------------------------------+ | This file is part of the Roundcube Webmail client | - | Copyright (C) 2006-2012, The Roundcube Dev Team | + | Copyright (C) 2006-2013, The Roundcube Dev Team | | | | Licensed under the GNU General Public License version 3 or | | any later version with exceptions for skins & plugins. | @@ -16,7 +16,6 @@ +-----------------------------------------------------------------------+ */ - /** * Abstract skeleton of an address book/repository * @@ -26,26 +25,32 @@ abstract class rcube_addressbook { /** constants for error reporting **/ - const ERROR_READ_ONLY = 1; + const ERROR_READ_ONLY = 1; const ERROR_NO_CONNECTION = 2; - const ERROR_VALIDATE = 3; - const ERROR_SAVING = 4; - const ERROR_SEARCH = 5; + const ERROR_VALIDATE = 3; + const ERROR_SAVING = 4; + const ERROR_SEARCH = 5; /** public properties (mandatory) */ public $primary_key; - public $groups = false; - public $readonly = true; - public $searchonly = false; - public $undelete = false; - public $ready = false; - public $group_id = null; - public $list_page = 1; - public $page_size = 10; - public $sort_col = 'name'; - public $sort_order = 'ASC'; - public $coltypes = array('name' => array('limit'=>1), 'firstname' => array('limit'=>1), 'surname' => array('limit'=>1), 'email' => array('limit'=>1)); - public $date_cols = array(); + public $groups = false; + public $export_groups = true; + public $readonly = true; + public $searchonly = false; + public $undelete = false; + public $ready = false; + public $group_id = null; + public $list_page = 1; + public $page_size = 10; + public $sort_col = 'name'; + public $sort_order = 'ASC'; + public $date_cols = array(); + public $coltypes = array( + 'name' => array('limit'=>1), + 'firstname' => array('limit'=>1), + 'surname' => array('limit'=>1), + 'email' => array('limit'=>1) + ); protected $error; @@ -133,7 +138,7 @@ abstract function get_record($id, $assoc=false); /** - * Returns the last error occured (e.g. when updating/inserting failed) + * Returns the last error occurred (e.g. when updating/inserting failed) * * @return array Hash array with the following fields: type, message */ @@ -145,7 +150,7 @@ /** * Setter for errors for internal use * - * @param int Error type (one of this class' error constants) + * @param int Error type (one of this class' error constants) * @param string Error message (name of a text label) */ protected function set_error($type, $message) @@ -162,8 +167,7 @@ /** * Set internal list page * - * @param number Page number to list - * @access public + * @param number Page number to list */ function set_page($page) { @@ -173,8 +177,7 @@ /** * Set internal page size * - * @param number Number of messages to display on one page - * @access public + * @param number Number of messages to display on one page */ function set_pagesize($size) { @@ -201,13 +204,15 @@ * Check the given data before saving. * If input isn't valid, the message to display can be fetched using get_error() * - * @param array Assoziative array with data to save + * @param array Assoziative array with data to save * @param boolean Attempt to fix/complete record automatically + * * @return boolean True if input is valid, False if not. */ public function validate(&$save_data, $autofix = false) { $rcube = rcube::get_instance(); + $valid = true; // check validity of email addresses foreach ($this->get_col_values('email', $save_data, true) as $email) { @@ -215,12 +220,28 @@ if (!rcube_utils::check_email(rcube_utils::idn_to_ascii($email))) { $error = $rcube->gettext(array('name' => 'emailformaterror', 'vars' => array('email' => $email))); $this->set_error(self::ERROR_VALIDATE, $error); - return false; + $valid = false; + break; } } } - return true; + // allow plugins to do contact validation and auto-fixing + $plugin = $rcube->plugins->exec_hook('contact_validate', array( + 'record' => $save_data, + 'autofix' => $autofix, + 'valid' => $valid, + )); + + if ($valid && !$plugin['valid']) { + $this->set_error(self::ERROR_VALIDATE, $plugin['error']); + } + + if (is_array($plugin['record'])) { + $save_data = $plugin['record']; + } + + return $plugin['valid']; } /** @@ -263,7 +284,8 @@ * @param array Assoziative array with save data * Keys: Field name with optional section in the form FIELD:SECTION * Values: Field value. Can be either a string or an array of strings for multiple values - * @return boolean True on success, False on error + * + * @return mixed On success if ID has been changed returns ID, otherwise True, False on error */ function update($id, $save_cols) { @@ -273,10 +295,10 @@ /** * Mark one or more contact records as deleted * - * @param array Record identifiers - * @param bool Remove records irreversible (see self::undelete) + * @param array Record identifiers + * @param bool Remove records irreversible (see self::undelete) */ - function delete($ids, $force=true) + function delete($ids, $force = true) { /* empty for read-only address books */ } @@ -284,7 +306,7 @@ /** * Unmark delete flag on contact record(s) * - * @param array Record identifiers + * @param array Record identifiers */ function undelete($ids) { @@ -293,8 +315,10 @@ /** * Mark all records in database as deleted + * + * @param bool $with_groups Remove also groups */ - function delete_all() + function delete_all($with_groups = false) { /* empty for read-only address books */ } @@ -423,7 +447,7 @@ * @param boolean True to return one array with all values, False for hash array with values grouped by type * @return array List of column values */ - function get_col_values($col, $data, $flat = false) + public static function get_col_values($col, $data, $flat = false) { $out = array(); foreach ((array)$data as $c => $values) { @@ -432,7 +456,7 @@ $out = array_merge($out, (array)$values); } else { - list($f, $type) = explode(':', $c); + list(, $type) = explode(':', $c); $out[$type] = array_merge((array)$out[$type], (array)$values); } } @@ -476,7 +500,8 @@ $fn = trim(join(' ', array_filter(array($contact['prefix'], $contact['firstname'], $contact['middlename'], $contact['surname'], $contact['suffix'])))); // use email address part for name - $email = is_array($contact['email']) ? $contact['email'][0] : $contact['email']; + $email = self::get_col_values('email', $contact, true); + $email = $email[0]; if ($email && (empty($fn) || $fn == $email)) { // return full email @@ -513,21 +538,95 @@ $fn = join(' ', array($contact['surname'], $contact['firstname'], $contact['middlename'])); else if ($compose_mode == 1) $fn = join(' ', array($contact['firstname'], $contact['middlename'], $contact['surname'])); - else - $fn = !empty($contact['name']) ? $contact['name'] : join(' ', array($contact['prefix'], $contact['firstname'], $contact['middlename'], $contact['surname'], $contact['suffix'])); + else if ($compose_mode == 0) + $fn = $contact['name'] ?: join(' ', array($contact['prefix'], $contact['firstname'], $contact['middlename'], $contact['surname'], $contact['suffix'])); + else { + $plugin = rcube::get_instance()->plugins->exec_hook('contact_listname', array('contact' => $contact)); + $fn = $plugin['fn']; + } $fn = trim($fn, ', '); - // fallback to display name - if (empty($fn) && $contact['name']) - $fn = $contact['name']; - - // fallback to email address - $email = is_array($contact['email']) ? $contact['email'][0] : $contact['email']; - if (empty($fn) && $email) - return $email; + // fallbacks... + if ($fn === '') { + // ... display name + if (!empty($contact['name'])) { + $fn = $contact['name']; + } + // ... organization + else if (!empty($contact['organization'])) { + $fn = $contact['organization']; + } + // ... email address + else if (($email = self::get_col_values('email', $contact, true)) && !empty($email)) { + $fn = $email[0]; + } + } return $fn; + } + + /** + * Build contact display name for autocomplete listing + * + * @param array Hash array with contact data as key-value pairs + * @param string Optional email address + * @param string Optional name (self::compose_list_name() result) + * @param string Optional template to use (defaults to the 'contact_search_name' config option) + * + * @return string Display name + */ + public static function compose_search_name($contact, $email = null, $name = null, $templ = null) + { + static $template; + + if (empty($templ) && !isset($template)) { // cache this + $template = rcube::get_instance()->config->get('contact_search_name'); + if (empty($template)) { + $template = '{name} <{email}>'; + } + } + + $result = $templ ?: $template; + + if (preg_match_all('/\{[a-z]+\}/', $result, $matches)) { + foreach ($matches[0] as $key) { + $key = trim($key, '{}'); + $value = ''; + + switch ($key) { + case 'name': + $value = $name ?: self::compose_list_name($contact); + + // If name(s) are undefined compose_list_name() may return an email address + // here we prevent from returning the same name and email + if ($name === $email && strpos($result, '{email}') !== false) { + $value = ''; + } + + break; + + case 'email': + $value = $email; + break; + } + + if (empty($value)) { + $value = strpos($key, ':') ? $contact[$key] : self::get_col_values($key, $contact, true); + if (is_array($value)) { + $value = $value[0]; + } + } + + $result = str_replace('{' . $key . '}', $value, $result); + } + } + + $result = preg_replace('/\s+/', ' ', $result); + $result = preg_replace('/\s*(<>|\(\)|\[\])/', '', $result); + $result = trim($result, '/ '); + + return $result; } /** @@ -535,16 +634,15 @@ */ public static function compose_contact_key($contact, $sort_col) { - $key = $contact[$sort_col] . ':' . $row['sourceid']; + $key = $contact[$sort_col] . ':' . $contact['sourceid']; // add email to a key to not skip contacts with the same name (#1488375) - if (!empty($contact['email'])) { - $key .= ':' . implode(':', (array)$contact['email']); - } + if (($email = self::get_col_values('email', $contact, true)) && !empty($email)) { + $key .= ':' . implode(':', (array)$email); + } - return $key; + return $key; } - /** * Compare search value with contact data @@ -562,9 +660,9 @@ // use only strict comparison (mode = 1) // @TODO: partial search, e.g. match only day and month if (in_array($colname, $this->date_cols)) { - return (($value = rcube_utils::strtotime($value)) - && ($search = rcube_utils::strtotime($search)) - && date('Ymd', $value) == date('Ymd', $search)); + return (($value = rcube_utils::anytodatetime($value)) + && ($search = rcube_utils::anytodatetime($search)) + && $value->format('Ymd') == $search->format('Ymd')); } // composite field, e.g. address @@ -590,6 +688,4 @@ return false; } - } - -- Gitblit v1.9.1