From 02e4c44624fb6f286abb5c538c5cb6963739d95c Mon Sep 17 00:00:00 2001 From: Ralf Becker Date: Tue, 18 Jun 2013 10:45:00 +0000 Subject: [PATCH] * Addressbook/LDAP: recreation of contact (eg. because of missing objectclass) failed and lead to deleted contact or account --- .../inc/class.addressbook_ldap.inc.php | 45 +++++++++---------- phpgwapi/inc/class.accounts_ldap.inc.php | 32 +------------ phpgwapi/inc/class.ldap.inc.php | 29 ++++++++++++ 3 files changed, 50 insertions(+), 56 deletions(-) diff --git a/addressbook/inc/class.addressbook_ldap.inc.php b/addressbook/inc/class.addressbook_ldap.inc.php index be9832d69d..c0e05be353 100644 --- a/addressbook/inc/class.addressbook_ldap.inc.php +++ b/addressbook/inc/class.addressbook_ldap.inc.php @@ -115,7 +115,8 @@ class addressbook_ldap var $schema2egw = array( 'posixaccount' => array( 'account_id' => 'uidnumber', - 'account_lid' => 'uid', +// 'account_lid' => 'uid', + 'id' => 'uid', 'shadowexpire', ), 'inetorgperson' => array( @@ -432,6 +433,7 @@ class addressbook_ldap */ function save($keys=null) { + //error_log(__METHOD__."(".array2string($keys).") this->data=".array2string($this->data)); if(is_array($keys)) { $this->data = is_array($this->data) ? array_merge($this->data,$keys) : $keys; @@ -505,7 +507,7 @@ class addressbook_ldap // add for all supported objectclasses the objectclass and it's attributes foreach($this->schema2egw as $objectclass => $mapping) { - if(!$this->ldapServerInfo->supportsObjectClass($objectclass) || $objectclass == 'posixaccount') continue; + if(!$this->ldapServerInfo->supportsObjectClass($objectclass)) continue; if(!in_array($objectclass, $oldObjectclasses)) { @@ -523,6 +525,7 @@ class addressbook_ldap } foreach($mapping as $egwFieldName => $ldapFieldName) { + if (is_int($egwFieldName)) continue; if(!empty($data[$egwFieldName])) { // dont convert the (binary) jpegPhoto! @@ -533,6 +536,7 @@ class addressbook_ldap { $ldapContact[$ldapFieldName] = array(); } + //error_log(__METHOD__."() ".__LINE__." objectclass=$objectclass, data['$egwFieldName']=".array2string($data[$egwFieldName])." --> ldapContact['$ldapFieldName']=".array2string($ldapContact[$ldapFieldName])); } // handling of special attributes, like cat_id in evolutionPerson $egw2objectclass = '_egw2'.$objectclass; @@ -556,7 +560,7 @@ class addressbook_ldap $needRecreation = false; // add missing objectclasses - if($ldapContact['objectClass'] && array_diff($ldapContact['objectClass'],$oldObjectclasses)) + if($ldapContact['objectClass'] && ($missing=array_diff($ldapContact['objectClass'],$oldObjectclasses))) { if (!@ldap_mod_add($this->ds, $dn, array('objectClass' => $ldapContact['objectClass']))) { @@ -564,12 +568,12 @@ class addressbook_ldap { // need to modify structural objectclass $needRecreation = true; - + //error_log(__METHOD__."() ".__LINE__." could not add objectclasses ".array2string($missing)." --> need to recreate contact"); } 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) .')'); + error_log(__METHOD__.'() '.__LINE__.' update of '. $dn .' failed errorcode: '. ldap_errno($this->ds) .' ('. ldap_error($this->ds) .')'); return $this->_error(__LINE__); } } @@ -582,14 +586,10 @@ class addressbook_ldap { $result = ldap_read($this->ds, $dn, 'objectclass=*'); $oldContact = ldap_get_entries($this->ds, $result); - foreach($oldContact[0] as $key => $value) - { - if(is_array($value)) - { - unset($value['count']); - $newContact[$key] = $value; - } - } + $oldContact = ldap::result2array($oldContact[0]); + unset($oldContact['dn']); + + $newContact = $oldContact; $newContact[$this->dn_attribute] = $ldapContact[$this->dn_attribute]; if(is_array($ldapContact['objectClass']) && count($ldapContact['objectClass']) > 0) @@ -600,15 +600,14 @@ class addressbook_ldap if(!ldap_delete($this->ds, $dn)) { - error_log('class.so_ldap.inc.php ('. __LINE__ .') delete of old '. $dn .' failed errorcode: '. ldap_errno($this->ds) .' ('. ldap_error($this->ds) .')'); + error_log(__METHOD__.'() '.__LINE__.' delete of old '. $dn .' failed errorcode: '. ldap_errno($this->ds) .' ('. ldap_error($this->ds) .')'); return $this->_error(__LINE__); } 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; - error_log('class.so_ldap.inc.php ('. __LINE__ .') re-create contact as '. $newDN .' failed errorcode: '. ldap_errno($this->ds) .' ('. ldap_error($this->ds) .')'); - error_log(print_r($newContact,true)); + error_log(__METHOD__.'() '.__LINE__.' re-create contact as '. $newDN .' failed errorcode: '. ldap_errno($this->ds) .' ('. ldap_error($this->ds) .') newContact='.array2string($newContact)); + // if adding with new objectclass or dn fails, re-add deleted contact + @ldap_add($this->ds, $dn, $oldContact); return $this->_error(__LINE__); } $dn = $newDN; @@ -622,7 +621,7 @@ class addressbook_ldap } else { - error_log(__METHOD__."() ldap_rename or $dn to $newRDN failed! ".ldap_error($this->ds)); + error_log(__METHOD__.'() '.__LINE__." ldap_rename of $dn to $newRDN failed! ".ldap_error($this->ds)); } } unset($ldapContact[$this->dn_attribute]); @@ -631,9 +630,7 @@ class addressbook_ldap if (!@ldap_modify($this->ds, $dn, $ldapContact)) { - //echo "

ldap_modify($this->ds,'$dn',".print_r($ldapContact,true).') failed errorcode: '. ldap_errno($this->ds) .' ('. ldap_error($this->ds) .")

\n"; - error_log('class.so_ldap.inc.php ('. __LINE__ .') update of '. $dn .' failed errorcode: '. ldap_errno($this->ds) .' ('. ldap_error($this->ds) .')'); - error_log(print_r($ldapContact,true)); + error_log(__METHOD__.'() '.__LINE__.' update of '. $dn .' failed errorcode: '. ldap_errno($this->ds) .' ('. ldap_error($this->ds) .') ldapContact='.array2string($ldapContact)); return $this->_error(__LINE__); } } @@ -644,9 +641,7 @@ class addressbook_ldap if (!@ldap_add($this->ds, $dn, $ldapContact)) { - //echo "

ldap_add($this->ds,'$dn',".array2string($ldapContact).") failed errorcode: ".ldap_errno($this->ds) .' ('. ldap_error($this->ds) .")

\n"; - error_log('class.so_ldap.inc.php ('. __LINE__ .') add of '. $dn .' failed errorcode: '. ldap_errno($this->ds) .' ('. ldap_error($this->ds) .')'); - error_log(array2string($ldapContact)); + error_log(__METHOD__.'() '.__LINE__.' add of '. $dn .' failed errorcode: '. ldap_errno($this->ds) .' ('. ldap_error($this->ds) .') ldapContact='.array2string($ldapContact)); return $this->_error(__LINE__); } } diff --git a/phpgwapi/inc/class.accounts_ldap.inc.php b/phpgwapi/inc/class.accounts_ldap.inc.php index f0a1f6c302..2791d154e7 100644 --- a/phpgwapi/inc/class.accounts_ldap.inc.php +++ b/phpgwapi/inc/class.accounts_ldap.inc.php @@ -189,7 +189,7 @@ class accounts_ldap } else { - $old = $this->_ldap2array($old[0]); + $old = ldap::result2array($old[0]); foreach($old['objectclass'] as $n => $class) { $old['objectclass'][$n] = strtolower($class); @@ -362,36 +362,6 @@ class accounts_ldap return $data['account_id']; } - /** - * Convert a single ldap value into a associative array - * - * @param array $ldap array with numerical and associative indexes and count's - * @return array with only associative index and no count's - */ - function _ldap2array($ldap) - { - if (!is_array($ldap)) return false; - - $arr = array(); - foreach($ldap as $var => $val) - { - if (is_int($var) || $var == 'count') continue; - - if (is_array($val) && $val['count'] == 1) - { - $arr[$var] = $val[0]; - } - else - { - if (is_array($val)) unset($val['count']); - - $arr[$var] = $val; - } - } - return $arr; - } - - /** * Delete one account, deletes also all acl-entries for that account * diff --git a/phpgwapi/inc/class.ldap.inc.php b/phpgwapi/inc/class.ldap.inc.php index 6c766bb4fd..3dffd56820 100644 --- a/phpgwapi/inc/class.ldap.inc.php +++ b/phpgwapi/inc/class.ldap.inc.php @@ -83,6 +83,35 @@ class ldap return str_replace(array('\\','*','(',')','\0',' '),array('\\\\','\*','\(','\)','\\0','\20'),$string); } + /** + * Convert a single ldap result into a associative array + * + * @param array $ldap array with numerical and associative indexes and count's + * @return boolean|array with only associative index and no count's or false on error (parm is no array) + */ + static function result2array($ldap) + { + if (!is_array($ldap)) return false; + + $arr = array(); + foreach($ldap as $var => $val) + { + if (is_int($var) || $var == 'count') continue; + + if (is_array($val) && $val['count'] == 1) + { + $arr[$var] = $val[0]; + } + else + { + if (is_array($val)) unset($val['count']); + + $arr[$var] = $val; + } + } + return $arr; + } + /** * Connect to ldap server and return a handle *