summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthomascube <thomas@roundcube.net>2011-10-07 11:07:23 +0000
committerthomascube <thomas@roundcube.net>2011-10-07 11:07:23 +0000
commit39cafac3f5e9cff676b379c1ecb1c847eec558e2 (patch)
tree80a79eaf7e4c05d993c3a075fac442ee97eef523
parentbf9644b2192380bb2d41d3510a00266871613efe (diff)
Autocomplete LDAP records when adding contacts from mail (#1488073)
-rw-r--r--CHANGELOG1
-rw-r--r--program/include/rcube_addressbook.php7
-rw-r--r--program/include/rcube_contacts.php7
-rw-r--r--program/include/rcube_ldap.php84
-rw-r--r--program/steps/mail/addcontact.inc10
5 files changed, 80 insertions, 29 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 748d9300f..f9c1ff036 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
+- Autocomplete LDAP records when adding contacts from mail (#1488073)
- Plugin API: added 'ready' hook (#1488063)
- Ignore DSN request when it isn't supported by SMTP server (#1487800)
- Make sure LDAP name fields aren't arrays (#1488108)
diff --git a/program/include/rcube_addressbook.php b/program/include/rcube_addressbook.php
index 94a715bae..88f0aa900 100644
--- a/program/include/rcube_addressbook.php
+++ b/program/include/rcube_addressbook.php
@@ -30,7 +30,7 @@ abstract class rcube_addressbook
/** constants for error reporting **/
const ERROR_READ_ONLY = 1;
const ERROR_NO_CONNECTION = 2;
- const ERROR_INCOMPLETE = 3;
+ const ERROR_VALIDATE = 3;
const ERROR_SAVING = 4;
const ERROR_SEARCH = 5;
@@ -182,15 +182,16 @@ abstract class rcube_addressbook
* If input isn't valid, the message to display can be fetched using get_error()
*
* @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)
+ public function validate(&$save_data, $autofix = false)
{
// check validity of email addresses
foreach ($this->get_col_values('email', $save_data, true) as $email) {
if (strlen($email)) {
if (!check_email(rcube_idn_to_ascii($email))) {
- $this->set_error('warning', rcube_label(array('name' => 'emailformaterror', 'vars' => array('email' => $email))));
+ $this->set_error(self::ERROR_VALIDATE, rcube_label(array('name' => 'emailformaterror', 'vars' => array('email' => $email))));
return false;
}
}
diff --git a/program/include/rcube_contacts.php b/program/include/rcube_contacts.php
index 3ad53a6db..c810ce60e 100644
--- a/program/include/rcube_contacts.php
+++ b/program/include/rcube_contacts.php
@@ -500,16 +500,17 @@ class rcube_contacts extends rcube_addressbook
* If input not valid, the message to display can be fetched using get_error()
*
* @param array Assoziative array with data to save
+ * @param boolean Try to fix/complete record automatically
* @return boolean True if input is valid, False if not.
*/
- public function validate($save_data)
+ public function validate(&$save_data, $autofix = false)
{
// validate e-mail addresses
- $valid = parent::validate($save_data);
+ $valid = parent::validate($save_data, $autofix);
// require at least one e-mail address (syntax check is already done)
if ($valid && !array_filter($this->get_col_values('email', $save_data, true))) {
- $this->set_error('warning', 'noemailwarning');
+ $this->set_error(self::ERROR_VALIDATE, 'noemailwarning');
$valid = false;
}
diff --git a/program/include/rcube_ldap.php b/program/include/rcube_ldap.php
index a3f6dc56d..3af343f2d 100644
--- a/program/include/rcube_ldap.php
+++ b/program/include/rcube_ldap.php
@@ -448,13 +448,6 @@ class rcube_ldap extends rcube_addressbook
return $this->result;
}
- // add general filter to query
- if (!empty($this->prop['filter']) && empty($this->filter))
- {
- $filter = $this->prop['filter'];
- $this->set_search_set($filter);
- }
-
// query URL is given by the selected group
if ($this->group_id && $this->group_url)
{
@@ -463,10 +456,14 @@ class rcube_ldap extends rcube_addressbook
{
$this->base_dn = $m[1];
$this->prop['scope'] = $m[2];
- $this->filter = $m[3];
+ $this->filter = $this->filter ? '(&(' . $m[3] . ')(' . $this->filter . '))' : $m[3];
}
}
+ // add general filter to query
+ if (!empty($this->prop['filter']) && empty($this->filter))
+ $this->set_search_set($this->prop['filter']);
+
// exec LDAP search if no result resource is stored
if ($this->conn && !$this->ldap_result)
$this->_exec_search();
@@ -689,19 +686,49 @@ class rcube_ldap extends rcube_addressbook
* If input not valid, the message to display can be fetched using get_error()
*
* @param array Assoziative array with data to save
- *
+ * @param boolean Try to fix/complete record automatically
* @return boolean True if input is valid, False if not.
*/
- public function validate($save_data)
+ public function validate(&$save_data, $autofix = false)
{
// check for name input
if (empty($save_data['name'])) {
- $this->set_error('warning', 'nonamewarning');
+ $this->set_error(self::ERROR_VALIDATE, 'nonamewarning');
+ return false;
+ }
+
+ // Verify that the required fields are set.
+ $missing = null;
+ $ldap_data = $this->_map_data($save_data);
+ foreach ($this->prop['required_fields'] as $fld) {
+ if (!isset($ldap_data[$fld])) {
+ $missing[$fld] = 1;
+ }
+ }
+
+ if ($missing) {
+ // try to complete record automatically
+ if ($autofix) {
+ $reverse_map = array_flip($this->fieldmap);
+ $name_parts = preg_split('/[\s,.]+/', $save_data['name']);
+ if ($missing['sn']) {
+ $sn_field = $reverse_map['sn'];
+ $save_data[$sn_field] = array_pop ($name_parts);
+ }
+ if ($missing[($fn_field = $this->fieldmap['firstname'])]) {
+ $save_data['firstname'] = array_shift($name_parts);
+ }
+
+ return $this->validate($save_data, false);
+ }
+
+ // TODO: generate message saying which fields are missing
+ $this->set_error(self::ERROR_VALIDATE, 'formincomplete');
return false;
}
// validate e-mail addresses
- return parent::validate($save_data);
+ return parent::validate($save_data, $autofix);
}
@@ -715,17 +742,8 @@ class rcube_ldap extends rcube_addressbook
function insert($save_cols)
{
// Map out the column names to their LDAP ones to build the new entry.
- $newentry = array();
+ $newentry = $this->_map_data($save_cols);
$newentry['objectClass'] = $this->prop['LDAP_Object_Classes'];
- foreach ($this->fieldmap as $col => $fld) {
- $val = $save_cols[$col];
- if (is_array($val))
- $val = array_filter($val); // remove empty entries
- if ($fld && $val) {
- // The field does exist, add it to the entry.
- $newentry[$fld] = $val;
- } // end if
- } // end foreach
// Verify that the required fields are set.
$missing = null;
@@ -738,7 +756,7 @@ class rcube_ldap extends rcube_addressbook
// abort process if requiered fields are missing
// TODO: generate message saying which fields are missing
if ($missing) {
- $this->set_error(self::ERROR_INCOMPLETE, 'formincomplete');
+ $this->set_error(self::ERROR_VALIDATE, 'formincomplete');
return false;
}
@@ -1052,6 +1070,26 @@ class rcube_ldap extends rcube_addressbook
/**
+ * Convert a record data set into LDAP field attributes
+ */
+ private function _map_data($save_cols)
+ {
+ $ldap_data = array();
+ foreach ($this->fieldmap as $col => $fld) {
+ $val = $save_cols[$col];
+ if (is_array($val))
+ $val = array_filter($val); // remove empty entries
+ if ($fld && $val) {
+ // The field does exist, add it to the entry.
+ $ldap_data[$fld] = $val;
+ }
+ }
+
+ return $ldap_data;
+ }
+
+
+ /**
* Returns unified attribute name (resolving aliases)
*/
private static function _attr_name($name)
diff --git a/program/steps/mail/addcontact.inc b/program/steps/mail/addcontact.inc
index b74d95faa..dafb2763c 100644
--- a/program/steps/mail/addcontact.inc
+++ b/program/steps/mail/addcontact.inc
@@ -60,6 +60,16 @@ if (!empty($_POST['_address']) && is_object($CONTACTS))
$contact['email'] = rcube_idn_to_utf8($contact['email']);
$contact['name'] = rcube_addressbook::compose_display_name($contact);
+ // validate contact record
+ if (!$CONTACTS->validate($contact, true)) {
+ $error = $CONTACTS->get_error();
+ // TODO: show dialog to complete record
+ // if ($error['type'] == rcube_addressbook::ERROR_VALIDATE) { }
+
+ $OUTPUT->show_message($error['message'] ? $error['message'] : 'errorsavingcontact', 'error');
+ $OUTPUT->send();
+ }
+
// check for existing contacts
$existing = $CONTACTS->search('email', $contact['email'], true, false);