From 5e0d628d9326fda4b7c8195bce55e8aa87308709 Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Tue, 13 Jun 2006 21:53:00 +0000 Subject: [PATCH] - added LDAP ACL stuff to the readme - reworked Admin >> Addressbook >> Site config - fixed for LDAP and SQL (eg. LDAP error are now forwarded to the UI) --- addressbook/doc/README | 97 +++++++++++- addressbook/inc/class.bocontacts.inc.php | 12 +- .../inc/class.contacts_admin_prefs.inc.php | 30 ++-- addressbook/inc/class.so_ldap.inc.php | 148 +++++++++++------- addressbook/inc/class.socontacts.inc.php | 1 - addressbook/inc/class.socontacts_sql.inc.php | 4 + addressbook/inc/class.uicontacts.inc.php | 28 +++- addressbook/inc/hook_config_validate.inc.php | 54 ------- addressbook/templates/default/config.tpl | 35 ++--- 9 files changed, 249 insertions(+), 160 deletions(-) delete mode 100644 addressbook/inc/hook_config_validate.inc.php diff --git a/addressbook/doc/README b/addressbook/doc/README index 19769726c0..eb437dcfc2 100644 --- a/addressbook/doc/README +++ b/addressbook/doc/README @@ -10,9 +10,100 @@ like eg. the home-address you need to use some other supported schema: - mozillaOrgPerson older mozilla schema (depricated, but mostly compatible to mozillaAbPersonAlpha) Please note: -You can install the evolutionPerson schema together with ONE +You can or should install the evolutionPerson schema together with ONE of the mozilla schemas. You can NOT install both mozilla schema! -If the addressbook detects the schemas, it fills the extra fields of each schema. +If the addressbook detects a schema, it fills the extra fields of that schema. -Ralf +LDAP layout used for the eGroupWare addressbook +----------------------------------------------- + +dc=domain,dc=com base DN of your LDAP server +| ++-o=default base DN for the addressbook of eGroupWare domain / DB instance "default" +| | (specified in Admin >> Addressbook >> Site config) +| | +| +-ou=accounts base DN for accounts (specified in Setup >> Configuration) +| | +-uid=ralf entry for user ralf +| | +-uid=lars entry for user lars +| | +-uid=... other users +| | +| +-ou=groups base DN for groups (specified in Setup >> Configuration) +| | +-cn=Default entry for the group Default +| | +-cn=... other groups +| | +| +ou=contacts +| | +| +-ou=shared shared addressbooks of the groups +| | +-cn=default addressbook of group Default +| | +-cn=... +| | +| +-ou=personal personal addressbooks of the users +| +-cn=ralf addressbook of user ralf +| +-cn=lars addressbook of user lars +| +-cn=... +| ++-o=other other eGroupWare domain / DB instance + +-... + +The contact base DN must include the accounts and groups base DN, otherwise they will not be +searched AND the ACL given below does NOT work! + +The following ACL in slapd conf allow: +------------------------------------- +- everyone to read the account addressbook +- the user to edit his account (incl. password) +- the egwadmin user for each domain to edit all accounts (eGW uses it when admins edit accounts) +- only the user to read, edit or delete in his personal addressbook +- group-members to read, edit or delete in their group addressbook + +Add or include the rows after the line behind the exiting ACL rules in your slapd.conf + +Please note: +----------- +- You need to change all dc=domain,dc=com with the base DN your LDAP uses!!! +- If you want to use the old mozillaOrgPerson schema, you need to change it here too! +--------------------------------------------------------------------------------------------------- +# Access to users personal addressbooks + +# allow read of addressbook by owner and egwadmin account +access to dn.regex="^cn=([^,]+),ou=personal,ou=contacts,o=([^,]+),dc=domain,dc=com$" + attrs=entry + by dn.regex="uid=$1,ou=accounts,o=$2,dc=domain,dc=com" read + by dn.regex="cn=egwadmin,o=$2,dc=domain,dc=com" write + by users none + +# allow user to create entries in own addressbook; no-one else can access it +# needs write access to the entries ENTRY attribute ... +access to dn.regex="cn=([^,]+),ou=personal,ou=contacts,o=([^,]+),dc=domain,dc=com$" + attrs=children + by dn.regex="uid=$1,ou=accounts,o=$2,dc=domain,dc=com" write + by users none + +# ... and the entries CHILDREN +access to dn.regex="cn=([^,]+),ou=personal,ou=contacts,o=([^,]+),dc=domain,dc=com$" + attrs=entry,@inetOrgPerson,@mozillaAbPersonAlpha,@evolutionPerson + by dn.regex="uid=$1,ou=accounts,o=$2,dc=domain,dc=com" write + by users none + +# Access to groups addressbooks + +# allow read of addressbook by members and egwadmin account +access to dn.regex="^cn=([^,]+),ou=shared,ou=contacts,o=([^,]+),dc=domain,dc=com$" + attrs=entry + by group.expand="cn=$1,ou=groups,o=$2,dc=domain,dc=com" read + by dn.regex="cn=egwadmin,o=$2,dc=domain,dc=com" write + by users none + +# allow members to create entries in there group addressbooks; no-one else can access it +# needs write access to the entries ENTRY attribute ... +access to dn.regex="cn=([^,]+),ou=shared,ou=contacts,o=([^,]+),dc=domain,dc=com$" + attrs=children + by group.expand="cn=$1,ou=groups,o=$2,dc=domain,dc=com" write + by users none + +# ... and the entries CHILDREN +access to dn.regex="cn=([^,]+),ou=shared,ou=contacts,o=([^,]+),dc=domain,dc=com$" + attrs=entry,@inetOrgPerson,@mozillaAbPersonAlpha,@evolutionPerson + by group.expand="cn=$1,ou=groups,o=$2,dc=domain,dc=com" write + by users none diff --git a/addressbook/inc/class.bocontacts.inc.php b/addressbook/inc/class.bocontacts.inc.php index d582bcebb9..6c790a939a 100755 --- a/addressbook/inc/class.bocontacts.inc.php +++ b/addressbook/inc/class.bocontacts.inc.php @@ -91,6 +91,13 @@ class bocontacts extends socontacts var $business_contact_fields = array(); var $home_contact_fields = array(); + /** + * Number and message of last error or false if no error, atm. only used for saving + * + * @var string/boolean + */ + var $error; + function bocontacts($contact_app='addressbook') { $this->socontacts($contact_app); @@ -403,6 +410,7 @@ class bocontacts extends socontacts } if($contact['id'] && !$this->check_perms(EGW_ACL_EDIT,$contact)) { + $this->error = 'access denied'; return false; } // convert categories @@ -414,11 +422,11 @@ class bocontacts extends socontacts $contact['n_fn'] = $this->fullname($contact); $contact['n_fileas'] = $this->fileas($contact); - if(!($error_nr = parent::save($contact))) + if(!($this->error = parent::save($contact))) { $GLOBALS['egw']->contenthistory->updateTimeStamp('contacts', $contact['id'],$isUpdate ? 'modify' : 'add', time()); } - return !$error_nr; + return !$this->error; } /** diff --git a/addressbook/inc/class.contacts_admin_prefs.inc.php b/addressbook/inc/class.contacts_admin_prefs.inc.php index e77afbf753..9a892629a9 100644 --- a/addressbook/inc/class.contacts_admin_prefs.inc.php +++ b/addressbook/inc/class.contacts_admin_prefs.inc.php @@ -1,16 +1,14 @@ * -* ------------------------------------------------------------------------ * -* This program is free software; you can redistribute it and/or modify it * -* under the terms of the GNU General Public License as published by the * -* Free Software Foundation; either version 2 of the License, or (at your * -* option) any later version. * -\**************************************************************************/ - -/* $Id$ */ +/** + * Addressbook - admin, preferences and sidebox-menus + * + * @link http://www.egroupware.org + * @package addressbook + * @author Ralf Becker + * @copyright (c) 2006 by Ralf Becker + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @version $Id$ + */ /** * Class containing admin, preferences and sidebox-menus (used as hooks) @@ -22,14 +20,14 @@ */ class contacts_admin_prefs { - var $contacts_repository = 'sql'; + var $contact_repository = 'sql'; /** * constructor */ function contacts_admin_prefs() { - if($GLOBALS['egw_info']['server']['contact_repository'] == 'ldap') $this->contacts_repository = 'ldap'; + if($GLOBALS['egw_info']['server']['contact_repository'] == 'ldap') $this->contact_repository = 'ldap'; } /** @@ -69,7 +67,7 @@ class contacts_admin_prefs 'Grant Access' => $GLOBALS['egw']->link('/index.php','menuaction=preferences.uiaclprefs.index&acl_app='.$appname), 'Edit Categories' => $GLOBALS['egw']->link('/index.php','menuaction=preferences.uicategories.index&cats_app=' . $appname . '&cats_level=True&global_cats=True') ); - if ($this->contacts_repository == 'ldap' || $GLOBALS['egw_info']['server']['deny_user_grants_access']) + if ($this->contact_repository == 'ldap' || $GLOBALS['egw_info']['server']['deny_user_grants_access']) { unset($file['Grant Access']); } @@ -176,7 +174,7 @@ class contacts_admin_prefs 'admin' => false, ); - if ($this->contacts_repository == 'sql') + if ($this->contact_repository == 'sql') { $GLOBALS['settings']['private_addressbook'] = array( 'type' => 'check', diff --git a/addressbook/inc/class.so_ldap.inc.php b/addressbook/inc/class.so_ldap.inc.php index d3e6fae140..a401af98c8 100644 --- a/addressbook/inc/class.so_ldap.inc.php +++ b/addressbook/inc/class.so_ldap.inc.php @@ -294,7 +294,7 @@ class so_ldap if((int)$data['owner']) { // group address book - if(!$cn = strtolower($GLOBALS['egw']->accounts->id2name((int)$data['owner']))) + if(!($cn = strtolower($GLOBALS['egw']->accounts->id2name((int)$data['owner'])))) { return true; } @@ -313,49 +313,27 @@ class so_ldap return true; // only admin is allowd to write accounts! } - // check if $baseDN exists. If not create new one - if(!($result = ldap_read($this->ds, $baseDN, 'objectclass=*'))) + // check if $baseDN exists. If not create it + if (($err = $this->_check_create_dn($baseDN))) { - if(ldap_errno($this->ds) == 32 && $cn) - { - // create a admin connection to add the needed DN - $adminLDAP =& new ldap; - $adminDS = $adminLDAP->ldapConnect(); - - // emtry does not exist, lets try to create it - $baseDNData['objectClass'] = 'organizationalRole'; - $baseDNData['cn'] = $cn; - if(!ldap_add($adminDS, $baseDN, $baseDNData)) - { - $adminLDAP->ldapDisconnect(); - return true; - } - $adminLDAP->ldapDisconnect(); - } - else - { - return true; - } + return $err; } // check the existing objectclasses of an entry, none = array() for new ones $oldObjectclasses = array(); $attributes = array('dn','cn','objectClass','uid'); - if(!empty($this->data[$this->contacts_id])) + $contactUID = $this->data[$this->contacts_id]; + if(!empty($contactUID) && + ($result = ldap_search($this->ds, $GLOBALS['egw_info']['server']['ldap_contact_context'], + '(|(entryUUID='.ldap::quote($contactUID).')(uid='.ldap::quote($contactUID).'))', $attributes)) && + ($oldContactInfo = ldap_get_entries($this->ds, $result)) && $oldContactInfo['count']) { - $contactUID = $this->data[$this->contacts_id]; - - $result = ldap_search($this->ds, $GLOBALS['egw_info']['server']['ldap_contact_context'], - '(|(entryUUID='.ldap::quote($contactUID).')(uid='.ldap::quote($contactUID).'))', $attributes); - - $oldContactInfo = ldap_get_entries($this->ds, $result); foreach($oldContactInfo[0]['objectclass'] as $objectclass) { $oldObjectclasses[] = strtolower($objectclass); } $isUpdate = true; } - if(!$contactUID) { $contactUID = md5($GLOBALS['egw']->common->randomstring(15)); @@ -370,7 +348,7 @@ class so_ldap if(!in_array($objectclass, $oldObjectclasses)) { - $newObjectClasses['objectClass'][] = $objectclass; + $ldapContact['objectClass'][] = $objectclass; } if (isset($this->required_subs[$objectclass])) { @@ -378,7 +356,7 @@ class so_ldap { if(!in_array($sub, $oldObjectclasses)) { - $newObjectClasses['objectClass'][] = $sub; + $ldapContact['objectClass'][] = $sub; } } } @@ -410,20 +388,21 @@ class so_ldap $needRecreation = false; // add missing objectclasses - if(count($newObjectClasses) > 0) + if($ldapContact['objectClass'] && array_diff($ldapContact['objectClass'],$oldObjectclasses)) { - $result = @ldap_mod_add($this->ds, $dn, $newObjectClasses); - if(!$result) + if (!@ldap_mod_add($this->ds, $dn, array('objectClass' => $ldapContact['objectClass']))) { if(ldap_errno($this->ds) == 69) { // need to modify structural objectclass $needRecreation = true; + } else { + //echo "

ldap_mod_add($this->ds,'$dn',array(objectClass =>".print_r($ldapContact['objectClass'],true)."))

\n"; error_log('class.so_ldap.inc.php ('. __LINE__ .') update of '. $dn .' failed errorcode: '. ldap_errno($this->ds) .' ('. ldap_error($this->ds) .')'); - return ldap_errno($this->ds).': '.ldap_error($this->ds); + return $this->_error(__LINE__); } } } @@ -445,45 +424,46 @@ class so_ldap } $newContact['uid'] = $contactUID; - if(is_array($newObjectClasses['objectClass']) && count($newObjectClasses['objectClass']) > 0) + if(is_array($ldapContact['objectClass']) && count($ldapContact['objectClass']) > 0) { - $newContact['objectclass'] = array_merge($newContact['objectclass'], $newObjectClasses['objectClass']); + $newContact['objectclass'] = array_merge($newContact['objectclass'], $ldapContact['objectClass']); } if(ldap_delete($this->ds, $dn)) { - if(!ldap_add($this->ds, $newDN, $newContact)) + if(!@ldap_add($this->ds, $newDN, $newContact)) { + //echo "

recreate: ldap_add($this->ds,'$newDN',".print_r($newContact,true).")

\n"; //print 'class.so_ldap.inc.php ('. __LINE__ .') update of '. $dn .' failed errorcode: '. ldap_errno($this->ds) .' ('. ldap_error($this->ds) .')';_debug_array($newContact);exit; - return ldap_errno($this->ds).': '.ldap_error($this->ds); + return $this->_error(__LINE__); } - } + } else { error_log('class.so_ldap.inc.php ('. __LINE__ .') delete of old '. $dn .' failed errorcode: '. ldap_errno($this->ds) .' ('. ldap_error($this->ds) .')'); - return ldap_errno($this->ds).': '.ldap_error($this->ds); + return $this->_error(__LINE__); } $dn = $newDN; } + unset($ldapContact['objectClass']); - $result = ldap_modify($this->ds, $dn, $ldapContact); - if (!$result) + if (!@ldap_modify($this->ds, $dn, $ldapContact)) { + //echo "

ldap_modify($this->ds,'$dn',".print_r($ldapContact,true).")

\n"; error_log('class.so_ldap.inc.php ('. __LINE__ .') update of '. $dn .' failed errorcode: '. ldap_errno($this->ds) .' ('. ldap_error($this->ds) .')'); - return ldap_errno($this->ds).': '.ldap_error($this->ds); + return $this->_error(__LINE__); } - } - else + } + else { $dn = 'uid='. ldap::quote($ldapContact['uid']) .','. $baseDN; - $result = ldap_add($this->ds, $dn, $ldapContact); - - if (!$result) + if (!@ldap_add($this->ds, $dn, $ldapContact)) { + //echo "

ldap_add($this->ds,'$dn',".print_r($ldapContact,true).")

\n"; error_log('class.so_ldap.inc.php ('. __LINE__ .') add of '. $dn .' failed errorcode: '. ldap_errno($this->ds) .' ('. ldap_error($this->ds) .')'); - return ldap_errno($this->ds).': '.ldap_error($this->ds); + return $this->_error(__LINE__); } } return 0; // Ok, no error @@ -516,7 +496,7 @@ class so_ldap "(|(entryUUID=$entry)(uid=$entry))", $attributes)) { $contactInfo = ldap_get_entries($this->ds, $result); - if(ldap_delete($this->ds, $contactInfo[0]['dn'])) + if(@ldap_delete($this->ds, $contactInfo[0]['dn'])) { $ret++; } @@ -861,6 +841,68 @@ class so_ldap return mktime(substr($date,8,2),substr($date,10,2),substr($date,12,2), substr($date,4,2),substr($date,6,2),substr($date,0,4)); } + + /** + * check if $baseDN exists. If not create it + * + * @param string $baseDN cn=xxx,ou=yyy,ou=contacts,$GLOBALS['egw_info']['server']['ldap_contact_context'] + * @return boolean/string fase on success or string with error-message + */ + function _check_create_dn($baseDN) + { + // check if $baseDN exists. If not create new one + if(@ldap_read($this->ds, $baseDN, 'objectclass=*')) + { + return false; + } + if(ldap_errno($this->ds) != 32 || substr($baseDN,0,3) != 'cn=') + { + return $this->_error(__LINE__); // baseDN does NOT exist and we cant/wont create it + } + // create a admin connection to add the needed DN + $adminLDAP =& new ldap; + $adminDS = $adminLDAP->ldapConnect(); + + list(,$ou) = explode(',',$baseDN); + foreach(array( + 'ou=contacts,'.$GLOBALS['egw_info']['server']['ldap_contact_context'], + $ou.',ou=contacts,'.$GLOBALS['egw_info']['server']['ldap_contact_context'], + $baseDN, + ) as $dn) + { + if (!@ldap_read($this->ds, $dn, 'objectclass=*') && ldap_errno($this->ds) == 32) + { + // entry does not exist, lets try to create it + list($top) = explode(',',$dn); + list($var,$val) = explode('=',$top); + $data = array( + 'objectClass' => $var == 'cn' ? 'organizationalRole' : 'organizationalUnit', + $var => $val, + ); + if(!@ldap_add($adminDS, $dn, $data)) + { + //echo "

ldap_add($adminDS,'$dn',".print_r($data,true).")

\n"; + $err = $this->_error(__LINE__,$adminDS); + $adminLDAP->ldapDisconnect(); + return $err; + } + } + } + $adminLDAP->ldapDisconnect(); + + return false; + } + + /** + * error message for failed ldap operation + * + * @param int $line + * @return string + */ + function _error($line,$ds=null) + { + return ldap_error($ds ? $ds : $this->ds).': so_ldap: '.$line; + } /** * Special handling for mapping of eGW contact-data to the evolutionPerson objectclass diff --git a/addressbook/inc/class.socontacts.inc.php b/addressbook/inc/class.socontacts.inc.php index e2fe4f4fc7..fb90ca456b 100755 --- a/addressbook/inc/class.socontacts.inc.php +++ b/addressbook/inc/class.socontacts.inc.php @@ -643,7 +643,6 @@ class socontacts $rows[$n] = $this->db2data($row); } } - // ToDo: read custom-fields, if displayed in the index page return $rows; } diff --git a/addressbook/inc/class.socontacts_sql.inc.php b/addressbook/inc/class.socontacts_sql.inc.php index 1b8943be3e..4aafde960b 100644 --- a/addressbook/inc/class.socontacts_sql.inc.php +++ b/addressbook/inc/class.socontacts_sql.inc.php @@ -295,6 +295,10 @@ class socontacts_sql extends so_sql $join .= $this->extra_join; if (is_string($only_keys)) $only_keys = 'DISTINCT '.str_replace(array('contact_id','contact_owner'), array($this->table_name.'.contact_id',$this->table_name.'.contact_owner'),$only_keys); + + // only return the egw_addressbook columns, to not generate dublicates by the left join + // and to not return the NULL for contact_{id|owner} of not found custom fields! + if (is_bool($only_keys)) $only_keys = 'DISTINCT '.$this->table_name.'.*'; if (isset($filter['owner'])) { diff --git a/addressbook/inc/class.uicontacts.inc.php b/addressbook/inc/class.uicontacts.inc.php index c5e03cd904..ad8c9becc1 100644 --- a/addressbook/inc/class.uicontacts.inc.php +++ b/addressbook/inc/class.uicontacts.inc.php @@ -57,8 +57,8 @@ class uicontacts extends bocontacts $this->$my = &$GLOBALS['egw']->$class; } $this->prefs =& $GLOBALS['egw_info']['user']['preferences']['addressbook']; - $this->private_addressbook = $this->contacts_repository == 'sql' && $this->prefs['private_addressbook']; - + $this->private_addressbook = $this->contact_repository == 'sql' && $this->prefs['private_addressbook']; + $this->org_views = array( 'org_name' => lang('Organisations'), 'org_name,adr_one_locality' => lang('Organisations by location'), @@ -187,7 +187,7 @@ class uicontacts extends bocontacts $sel_options['org_view'][(string) $content['nm']['org_view']] = $org_name; } $content['nm']['org_view_label'] = $sel_options['org_view'][(string) $content['nm']['org_view']]; - + $this->tmpl->read('addressbook.index'); return $this->tmpl->exec('addressbook.uicontacts.index',$content,$sel_options,$readonlys,$preserv); } @@ -339,6 +339,20 @@ class uicontacts extends bocontacts //echo "

uicontacts::get_rows(".print_r($query,true).")

\n"; if (!$id_only) { + // check if accounts are stored in ldap, which does NOT yet support the org-views + if ($this->so_accounts && $query['filter'] === '0' && $query['org_view']) + { + $old_state = $GLOBALS['egw']->session->appsession('index','addressbook'); + if ($old_state['filter'] === '0') // user changed to org_view + { + $query['filter'] = ''; // --> change filter to all contacts + } + else // user changed to accounts + { + $query['org_view'] = ''; // --> change to regular contacts view + } + unset($old_state); + } $GLOBALS['egw']->session->appsession('index','addressbook',$query); // save the state of the index in the user prefs $state = serialize(array( @@ -352,7 +366,8 @@ class uicontacts extends bocontacts if ($state != $this->prefs['index_state']) { $GLOBALS['egw']->preferences->add('addressbook','index_state',$state); - $GLOBALS['egw']->preferences->save_repository(); + // save prefs, but do NOT invalid the cache (unnecessary) + $GLOBALS['egw']->preferences->save_repository(false,'user',false); } } if (isset($query['col_filter']['cat_id'])) unset($query['col_filter']['cat_id']); @@ -426,7 +441,7 @@ class uicontacts extends bocontacts } $rows = parent::search($query['search'],$id_only ? array('id','org_name','n_family','n_given','n_fileas') : false, $order,'','%',false,'OR',array((int)$query['start'],(int) $query['num_rows']),$query['col_filter']); - + if (!$id_only && $this->prefs['custom_colum'] != 'never' && $rows) // do we need the custom fields { foreach((array) $rows as $n => $val) @@ -718,7 +733,8 @@ class uicontacts extends bocontacts } else { - $content['msg'] = lang('Error saving the contact !!!'); + $content['msg'] = lang('Error saving the contact !!!'). + ($this->error ? ' '.$this->error : ''); $button = 'apply'; // to not leave the dialog } // writing links for new entry, existing ones are handled by the widget itself diff --git a/addressbook/inc/hook_config_validate.inc.php b/addressbook/inc/hook_config_validate.inc.php deleted file mode 100644 index 7dd1c4e0a6..0000000000 --- a/addressbook/inc/hook_config_validate.inc.php +++ /dev/null @@ -1,54 +0,0 @@ - * - * -------------------------------------------- * - * This program is free software; you can redistribute it and/or modify it * - * under the terms of the GNU General Public License as published by the * - * Free Software Foundation; either version 2 of the License, or (at your * - * option) any later version. * - \**************************************************************************/ - - /* $Id$ */ - - /* - Set a global flag to indicate this file was found by admin/config.php. - config.php will unset it after parsing the form values. - */ - $GLOBALS['egw_info']['server']['found_validation_hook'] = True; - - /* Check a specific setting. Name must match the setting. */ - function ldap_contact_context($value='') - { - if($value == $GLOBALS['egw_info']['server']['ldap_context']) - { - $GLOBALS['config_error'] = 'Contact context for ldap must be different from the context used for accounts'; - } - elseif($value == $GLOBALS['egw_info']['server']['ldap_group_context']) - { - $GLOBALS['config_error'] = 'Contact context for ldap must be different from the context used for groups'; - } - else - { - $GLOBALS['config_error'] = ''; - } - } - - /* Check all settings to validate input. Name must be 'final_validation' */ - function final_validation($value='') - { - if($value['contact_repository'] == 'ldap' && !$value['ldap_contact_dn']) - { - $GLOBALS['config_error'] = 'Contact dn must be set'; - } - elseif($value['contact_repository'] == 'ldap' && !$value['ldap_contact_context']) - { - $GLOBALS['config_error'] = 'Contact context must be set'; - } - else - { - $GLOBALS['config_error'] = ''; - } - } -?> diff --git a/addressbook/templates/default/config.tpl b/addressbook/templates/default/config.tpl index a9ebaf3ad0..29b05acd8e 100644 --- a/addressbook/templates/default/config.tpl +++ b/addressbook/templates/default/config.tpl @@ -5,22 +5,14 @@  {title} - -  {error} + +  {error} -  {lang_Addressbook}/{lang_Contact_Settings} +  {lang_Addressbook}/{lang_Contact_Settings} - {lang_Select_where_you_want_to_store_/_retrieve_contacts}. @@ -38,22 +30,15 @@ {lang_LDAP_context_for_contacts}: - - {lang_LDAP_root_dn_for_contacts}: - - - - {lang_LDAP_root_pw_for_contacts}: - - + + + {lang_Additional_information_about_using_LDAP_as_contact_repository}: + README + + - - -  - - - +