diff --git a/phpgwapi/inc/class.accounts_ldap.inc.php b/phpgwapi/inc/class.accounts_ldap.inc.php new file mode 100644 index 0000000000..b720a15fa9 --- /dev/null +++ b/phpgwapi/inc/class.accounts_ldap.inc.php @@ -0,0 +1,1124 @@ + * + * and Lars Kneschke * + * and Miles Lott * + * and Bettina Gille * + * View and manipulate account records using LDAP * + * Copyright (C) 2000 - 2002 Joseph Engo, Lars Kneschke * + * Copyright (C) 2003 Lars Kneschke, Bettina Gille * + * ------------------------------------------------------------------------ * + * This library is part of the eGroupWare API * + * http://www.egroupware.org * + * ------------------------------------------------------------------------ * + * This library is free software; you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as published by * + * the Free Software Foundation; either version 2.1 of the License, * + * or any later version. * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU Lesser General Public License for more details. * + * You should have received a copy of the GNU Lesser General Public License * + * along with this library; if not, write to the Free Software Foundation, * + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + \**************************************************************************/ + /* $Id$ */ + + class accounts_ + { + var $db; + var $ds; + var $account_id; + var $data; + var $user_context = ''; + var $group_context = ''; + var $total; + + var $requiredObjectClasses = array( + 'user' => array( + 'top','organizationalperson','inetorgperson','posixaccount','shadowaccount','phpgwaccount' + ), + 'group' => array( + 'top','posixgroup','phpgwaccount' + ) + ); + + function accounts_() + { + $this->ds = $GLOBALS['egw']->common->ldapConnect(); + if(!@is_object($GLOBALS['egw']->translation)) + { + $GLOBALS['egw']->translation =& CreateObject('phpgwapi.translation'); + } + $this->user_context = $GLOBALS['egw_info']['server']['ldap_context']; + $this->group_context = $GLOBALS['egw_info']['server']['ldap_group_context'] ? + $GLOBALS['egw_info']['server']['ldap_group_context'] : $GLOBALS['egw_info']['server']['ldap_context']; + } + + function read_repository() + { + $acct_type = $this->get_type($this->account_id); + + /* search the dn for the given uid */ + if(($acct_type == 'g') && $this->group_context) + { + $sri = ldap_search($this->ds, $this->group_context, 'gidnumber=' . abs((int)$this->account_id)); + } + else + { + $sri = ldap_search($this->ds, $this->user_context, 'uidnumber=' . (int)$this->account_id); + } + $allValues = ldap_get_entries($this->ds, $sri); + + /* Now dump it into the array; take first entry found */ + if($acct_type =='g') + { + $this->data['account_id'] = -$allValues[0]['gidnumber'][0]; + $this->data['account_lid'] = $allValues[0]['cn'][0]; + $this->data['firstname'] = $GLOBALS['egw']->translation->convert($allValues[0]['cn'][0],'utf-8'); + $this->data['lastname'] = lang('Group'); + } + else + { + $this->data['account_id'] = $allValues[0]['uidnumber'][0]; + $this->data['account_primary_group'] = -$allValues[0]['gidnumber'][0]; + $this->data['account_lid'] = $allValues[0]['uid'][0]; + $this->data['firstname'] = $GLOBALS['egw']->translation->convert($allValues[0]['givenname'][0],'utf-8'); + $this->data['lastname'] = $GLOBALS['egw']->translation->convert($allValues[0]['sn'][0],'utf-8'); + if(isset($allValues[0]['mail'][0])) + { + $this->data['email'] = $allValues[0]['mail'][0]; + } + } + $this->data['account_dn'] = $allValues[0]['dn']; + $this->data['fullname'] = $GLOBALS['egw']->translation->convert($allValues[0]['cn'][0],'utf-8'); + + if ($GLOBALS['egw_info']['server']['ldap_extra_attributes']) + { + $this->data['homedirectory'] = $allValues[0]['homedirectory'][0]; + $this->data['loginshell'] = $allValues[0]['loginshell'][0]; + } + + $this->data['lastlogin'] = $allValues[0]['phpgwaccountlastlogin'][0]; + $this->data['lastloginfrom'] = $allValues[0]['phpgwaccountlastloginfrom'][0]; + $this->data['lastpasswd_change'] = @$allValues[0]['phpgwlastpasswdchange'][0]; + $this->data['status'] = trim($allValues[0]['phpgwaccountstatus'][0]); + $this->data['type'] = $allValues[0]['phpgwaccounttype'][0]; + $this->data['expires'] = $allValues[0]['phpgwaccountexpires'][0]; + + return $this->data; + } + + function save_repository() + { + + $acct_type = $this->get_type($this->account_id); + + /* search the dn for the given u/gidnumber */ + if(($acct_type == 'g') && $this->group_context) + { + $sri = ldap_search($this->ds, $this->group_context, 'gidnumber=' . abs((int)$this->account_id)); + } + else + { + $sri = ldap_search($this->ds, $this->user_context, 'uidnumber=' . (int)$this->account_id); + } + $allValues = ldap_get_entries($this->ds, $sri); + + $this->data['account_type'] = $allValues[0]['phpgwaccounttype'][0]; + + if($acct_type == 'u') + { + // data for posixaccount + $newData['cn'] = $GLOBALS['egw']->translation->convert(sprintf("%s %s", + $this->data['firstname'], + $this->data['lastname']),$GLOBALS['egw']->translation->charset(),'utf-8' + ); + $newData['uid'] = $GLOBALS['egw']->translation->convert( + $this->data['account_lid'], + $GLOBALS['egw']->translation->charset(),'utf-8' + ); + if($this->data['lastname']) + { + $newData['sn'] = $GLOBALS['egw']->translation->convert( + $this->data['lastname'], + $GLOBALS['egw']->translation->charset(),'utf-8' + ); + } + + if($this->data['firstname']) + { + $newData['givenname'] = $GLOBALS['egw']->translation->convert( + $this->data['firstname'], + $GLOBALS['egw']->translation->charset(),'utf-8' + ); + } + if ($GLOBALS['egw_info']['server']['ldap_extra_attributes']) + { + $newData['homedirectory'] = $this->data['homedirectory']; + $newData['loginshell'] = $this->data['loginshell']; + } + else + { + // the posixaccount schema requires this + $entry['homedirectory'] = '/home/'.$this->data['account_lid']; + $entry['loginshell'] = '/bin/false'; + } + if($this->data['account_primary_group']) + { + $newData['gidnumber'] = abs($this->data['account_primary_group']); + } + if($this->data['lastlogin']) + { + $newData['phpgwaccountlastlogin'] = $this->data['lastlogin']; + } + if($this->data['lastloginfrom']) + { + $newData['phpgwaccountlastloginfrom'] = $this->data['lastloginfrom']; + } + if($this->data['lastpasswd_change']) + { + $newData['phpgwlastpasswdchange'] = $this->data['lastpasswd_change']; + } + if($this->data['status']) + { + $newData['phpgwaccountstatus'] = $this->data['status']; + } + else + { + $newData['phpgwaccountstatus'] = array(); + } + if($this->data['expires']) + { + $newData['phpgwaccountexpires'] = $this->data['expires']; + } + if($this->data['email']) + { + $newData['mail'] = $this->data['email']; + } + + // check that we have all required objectclasses + unset($allValues[0]['objectclass']['count']); + // convert all values to lowercase + $currentObjectClasses = array_flip(array_change_key_case(array_flip($allValues[0]['objectclass']))); + $missingObjectClasses = array_diff($this->requiredObjectClasses['user'],$currentObjectClasses); + if(count($missingObjectClasses) > 0) + { + $newData['objectclass'] = array_merge($currentObjectClasses, $missingObjectClasses); + } + $newAccountID = $newData['uid']; + $oldAccountID = $newData['uid']; + } + else + { + // data for posixgroup + $newData['cn'] = $GLOBALS['egw']->translation->convert( + $this->data['account_lid'], + $GLOBALS['egw']->translation->charset(), 'utf-8' + ); + $newData['gidnumber'] = abs($this->account_id); + $newGroupID = $newData['cn']; + $oldGroupID = $newData['cn']; + } + if($this->data['account_type']) + { + $newData['phpgwaccounttype'] = $this->data['account_type']; + } + + /* + Changing the uid: Need to delete and add new, since + PHP cannot change the dn for the entry. + */ + if ($acct_type == 'g') + { + $test = $allValues[0]['cn'][0]; + } + else + { + $test = $allValues[0]['uid'][0]; + } + if($GLOBALS['egw']->translation->convert($test,'utf-8') != $this->data['account_lid']) + { + $oldData = $allValues[0]; + $oldDN = $oldData['dn']; + // remove all unneeded fields + unset($oldData['dn']); + unset($oldData['count']); + foreach($oldData as $key => $value) + { + if(is_numeric($key)) + { + // remove the key, its no ldap key + unset($oldData[$key]); + } + else + { + // remove the count key + if($oldData[$key]['count'] == 1) + { + $oldData[$key] = $value[0]; + } + else + { + unset($oldData[$key]['count']); + } + } + } + + $oldAccountID = $oldData['uid']; + $oldGroupID = $oldData['cn']; + + // merge the old data with the new one + $newData = array_merge($oldData, $newData); + + /* Groups */ + if($this->data['account_type'] == 'g' && $this->group_context ) + { + $newDN = 'cn='.$this->data['account_lid'].','.$this->group_context; + $members = $this->member($this->account_id); + $newData['memberuid'] = array(); + for($i=0;$iid2name($members[$i]['account_id']); + if(!in_array($currname,$entry['memberuid'])) + { + $newData['memberuid'][] = $currname; + } + } + } + /* Accounts */ + else + { + $newDN = 'uid='.$this->data['account_lid'].','.$this->user_context; + } + // delete the old account + ldap_delete($this->ds,$oldDN); + + // add the new account + #_debug_array($newData); + ldap_add($this->ds, $newDN, $newData); + } + /* Normal behavior for save_repository + update Account */ + else + { + // add the list group members + if($this->data['account_type'] == 'g' && $this->group_context ) + { + $members = $this->member($this->account_id) ? $this->member($this->account_id) : NULL; + + #_debug_array($members); + $newData['memberuid'] = array(); + for($i=0;$iid2name($members[$i]['account_id']); + if(!in_array($currname,$newData['memberuid'])) + { + $newData['memberuid'][] = $currname; + } + } + } + // modify the DN + ldap_modify($this->ds, $allValues[0]['dn'], $newData); + } + + if ($this->data['account_type'] == 'u') + { + // lets check for groups, the user needs to be removed + + // first lets search for the groups, the user is currently member of + // and from which he needs to be removed + $filter = "(&(objectclass=posixgroup)(memberuid=" . (int)$oldAccountID . "))"; + $justThese = array('memberuid','gidnumber'); + $sri = ldap_search($this->ds, $this->group_context, $filter, $justThese); + if($sri) + { + $allValues = ldap_get_entries($this->ds, $sri); + if($allValues['count'] > 0) + { + unset($allValues['count']); + foreach($allValues as $key) + { + #_debug_array($key); + #_debug_array($this->data['account_groups']); + // delete the old accountid from any group + if($newAccountID != $oldAccountID) + { + $dn = $key['dn']; + $newData = array(); + $newData['memberuid'] = $key['memberuid']; + unset($newData['memberuid']['count']); + // remove the uid from memberuid + $newData['memberuid'] = array_flip($newData['memberuid']); + unset($newData['memberuid'][$oldAccountID]); + # $newData['memberuid'] = array_values(sort(array_flip($newData['memberuid']))); + $newData['memberuid'] = array_values(array_flip($newData['memberuid'])); + ldap_mod_replace($this->ds, $dn, $newData); + #print ldap_error($this->ds); + } + else + { + if(!in_array($key['gidnumber'][0],$this->data['account_groups'])) + { + $dn = $key['dn']; + $newData = array(); + $newData['memberuid'] = $key['memberuid']; + unset($newData['memberuid']['count']); + // remove the uid from memberuid + $newData['memberuid'] = array_flip($newData['memberuid']); + unset($newData['memberuid'][$oldAccountID]); + $newData['memberuid'] = array_values(sort(array_flip($newData['memberuid']))); + ldap_mod_replace($this->ds, $dn, $newData); + #print ldap_error($this->ds); + } + } + } + } + } + + // lets check group the user needs to be added + foreach($this->data['account_groups'] as $key => $value) + { + // search for the group + $filter = 'gidnumber=' . abs((int)$value); + $justThese = array('memberuid'); + $sri = ldap_search($this->ds, $this->group_context, $filter, $justThese); + if($sri) + { + $allValues = ldap_get_entries($this->ds, $sri); + // if the user is not member of this group, add him + if(is_array($allValues[0]['memberuid'])) + { + // this group has already some members + if(!in_array($newData['uid'],$allValues[0]['memberuid'])) + { + $dn = $allValues[0]['dn']; + $newData = array(); + $newData['memberuid'] = $allValues[0]['memberuid']; + unset($newData['memberuid']['count']); + $newData['memberuid'][] = $newAccountID; + $newData['memberuid'] = array_values(array_unique($newData['memberuid'])); + ldap_mod_replace($this->ds, $dn, $newData); + } + } + else + { + // this group has no members + $dn = $allValues[0]['dn']; + $newData = array(); + $newData['memberuid'][] = $newAccountID; + ldap_mod_replace($this->ds, $dn, $newData); + } + } + } + } + } + + function delete($accountid = '') + { + $account_id = get_account_id($accountid); + $account_lid = $this->id2name((int)$account_id); + + if ($account_id < 0) + { + $filter = 'gidnumber=' . abs((int)$account_id); + $context = $this->group_context; + } + else + { + $filter = 'uid=' . (string)$account_lid; + $context = $this->user_context; + $wasAccount = True; + } + + $sri = ldap_search($this->ds, $context, $filter); + if($sri) + { + $allValues = ldap_get_entries($this->ds, $sri); + $accountID = $allValues['0']['uid'][0]; + } + + if ($allValues[0]['dn']) + { + $del = ldap_delete($this->ds, $allValues[0]['dn']); + } + + if($wasAccount) + { + // remove the user from any group he is member of + $filter = "(&(objectclass=posixgroup)(memberuid=" . $accountID . "))"; + $justThese = array('memberuid','gidnumber'); + $sri = ldap_search($this->ds, $this->group_context, $filter, $justThese); + if($sri) + { + $allValues = ldap_get_entries($this->ds, $sri); + if($allValues['count'] > 0) + { + unset($allValues['count']); + foreach($allValues as $key) + { + $dn = $key['dn']; + $newData = array(); + $newData['memberuid'] = $key['memberuid']; + unset($newData['memberuid']['count']); + // remove the uid from memberuid + $newData['memberuid'] = array_flip($newData['memberuid']); + unset($newData['memberuid'][$accountID]); + $newData['memberuid'] = array_unique(array_flip($newData['memberuid'])); + ldap_mod_replace($this->ds, $dn, $newData); + } + } + } + } + } + + function get_list($_type='both', $start = '',$sort = '', $order = '', $query = '', $offset = '', $query_type='') + { + //print "\$_type=$_type, \$start=$start , \$sort=$sort, \$order=$order, \$query=$query, \$offset=$offset, \$query_type=$query_type
"; + $query = strtolower($query); + + if($_type != 'groups') + { + $filter = "(&(uidnumber=*)(phpgwaccounttype=u)"; + if (!empty($query) && $query != '*') + { + switch($query_type) + { + case 'all': + default: + $query = '*'.$query; + // fall-through + case 'start': + $query .= '*'; + // fall-through + case 'exact': + $filter .= "(|(uid=$query)(sn=$query)(cn=$query)(givenname=$query)(mail=$query))"; + break; + case 'firstname': + case 'lastname': + case 'lid': + case 'email': + $to_ldap = array( + 'firstname' => 'givenname', + 'lastname' => 'sn', + 'lid' => 'uid', + 'email' => 'mail', + ); + $filter .= '('.$to_ldap[$query_type].'=*'.$query.'*)'; + break; + } + } + $filter .= ')'; + + $sri = ldap_search($this->ds, $this->user_context, $filter); + $allValues = ldap_get_entries($this->ds, $sri); + while (list($null,$allVals) = @each($allValues)) + { + settype($allVals,'array'); + $test = @$allVals['uid'][0]; + if (!$GLOBALS['egw_info']['server']['global_denied_users'][$test] && $allVals['uid'][0]) + { + $accounts[] = Array( + 'account_id' => $allVals['uidnumber'][0], + 'account_lid' => $allVals['uid'][0], + 'account_type' => $allVals['phpgwaccounttype'][0], + 'account_firstname' => $GLOBALS['egw']->translation->convert($allVals['givenname'][0],'utf-8'), + 'account_lastname' => $GLOBALS['egw']->translation->convert($allVals['sn'][0],'utf-8'), + 'account_status' => $allVals['phpgwaccountstatus'][0], + 'account_email' => $allVals['mail'][0], + ); + } + } + } + if ($_type != 'accounts') + { + if(empty($query) || $query == '*') + { + $filter = '(&(gidnumber=*)(phpgwaccounttype=g))'; + } + else + { + $filter = "(&(gidnumber=*)(phpgwaccounttype=g)(|(uid=*$query*)(sn=*$query*)(cn=*$query*)(givenname=*$query*)))"; + } + $sri = ldap_search($this->ds, $this->group_context, $filter); + $allValues = ldap_get_entries($this->ds, $sri); + while (list($null,$allVals) = @each($allValues)) + { + settype($allVals,'array'); + $test = $allVals['cn'][0]; + if (!$GLOBALS['egw_info']['server']['global_denied_groups'][$test] && $allVals['cn'][0]) + { + $accounts[] = Array( + 'account_id' => -$allVals['gidnumber'][0], + 'account_lid' => $allVals['cn'][0], + 'account_type' => $allVals['phpgwaccounttype'][0], + 'account_firstname' => $GLOBALS['egw']->translation->convert($allVals['givenname'][0],'utf-8'), + 'account_lastname' => $GLOBALS['egw']->translation->convert($allVals['sn'][0],'utf-8'), + 'account_status' => $allVals['phpgwaccountstatus'][0], + 'account_email' => $allVals['mail'][0], + ); + } + } + } + // sort the array + $arrayFunctions =& CreateObject('phpgwapi.arrayfunctions'); + if(empty($order)) + { + $order = 'account_lid'; + } + $sortedAccounts = $arrayFunctions->arfsort($accounts,explode(',',$order),$sort); + $this->total = count($accounts); + // return only the wanted accounts + if (is_array($sortedAccounts)) + { + reset($sortedAccounts); + if(is_numeric($start) && is_numeric($offset)) + { + return array_slice($sortedAccounts, $start, $offset); + } + elseif(is_numeric($start)) + { + return array_slice($sortedAccounts, $start, $GLOBALS['egw_info']['user']['preferences']['common']['maxmatchs']); + } + else + { + return $sortedAccounts; + } + } + return False; + } + + function name2id($name,$which='account_lid') + { + if ($which == 'account_lid') // groups only support account_lid + { + $sri = ldap_search($this->ds, $this->group_context, '(&(cn=' . (string)$name . ')(phpgwaccounttype=g))'); + $allValues = ldap_get_entries($this->ds, $sri); + + if (@$allValues[0]['gidnumber'][0]) + { + return -(int)$allValues[0]['gidnumber'][0]; + } + } + $to_ldap = array( + 'account_lid' => 'uid', + 'account_email' => 'mail', + ); + if (!isset($to_ldap[$which])) return False; + + $sri = ldap_search($this->ds, $this->user_context, '(&('.$to_ldap[$which].'=' . (string)$name . ')(phpgwaccounttype=u))'); + + $allValues = ldap_get_entries($this->ds, $sri); + + if (@$allValues[0]['uidnumber'][0]) + { + return (int)$allValues[0]['uidnumber'][0]; + } + + return False; + } + + function id2name($account_id,$which='account_lid') + { + if (($which == 'account_lid' || $which == 'account_type') && $account_id < 0) // groups only support account_lid and account_type + { + $allValues = array(); + $sri = ldap_search($this->ds, $this->group_context, '(&(gidnumber=' . abs((int)$account_id) . ')(phpgwaccounttype=g))'); + $allValues = ldap_get_entries($this->ds, $sri); + + $attr = $which == 'account_lid' ? 'cn' : 'phpgwaccounttype'; + if (@$allValues[0]['cn'][0]) + { + return $allValues[0]['cn'][0]; + } + } + $to_ldap = array( + 'account_lid' => 'uid', + 'account_email' => 'mail', + 'account_firstname' => 'surname', + 'account_lastname' => 'cn', + 'account_type' => 'phpgwaccounttype', + ); + if (!isset($to_ldap[$which])) return False; + + $allValues = array(); + $sri = ldap_search($this->ds, $this->user_context, '(&(uidnumber=' . (int)$account_id . ')(phpgwaccounttype=u))'); + $allValues = ldap_get_entries($this->ds, $sri); + + if (@$allValues[0][$to_ldap[$which]][0]) + { + return $allValues[0][$to_ldap[$which]][0]; + } + return False; + } + + /* + * returns nonzero if $account exists in LDAP: 0: nowhere 1: user accounts, 2: group accounts, 3: both + * $account can be an account_id (LDAP: uidnumber) or an account_lid (LDAP: uid) (is determinded by ettype($account) == 'integer') + */ + function exists($account) + { + /* This sets up internal caching variables for this functon */ + static $by_id, $by_lid; + $users = array(); + $groups = array(); + + if(is_numeric($account)) + { + $ldapgroup = 'gidnumber'; + $ldapacct = 'uidnumber'; + /* If data is cached, use it. */ + if(isset($by_id[$account])) + { + return $by_id[$account]; + } + } + else + { + $ldapgroup = 'cn'; + $ldapacct = 'uid'; + /* If data is cached, use it. */ + if(@isset($by_lid[$account]) && @$by_lid[$account]) + { + return $by_lid[$account]; + } + } + + $acct_type = $this->get_type($account) ? $this->get_type($account) : $this->account_type; + + if ($acct_type == 'g' && $this->group_context) + { + $sri = ldap_search($this->ds, $this->group_context, $ldapgroup . '=' . abs($account)); + $groups = ldap_get_entries($this->ds, $sri); + } + $sri = ldap_search($this->ds, $this->user_context, $ldapacct . '=' . $account); + $users = ldap_get_entries($this->ds, $sri); + + if ($users[0]['dn']) + { + $in += 1; + } + if ($groups[0]['dn']) + { + $in += 2; + } + /* This sets up internal caching for this function */ + if($ldapgroup == 'gidnumber') + { + $by_id[$account] = $in; + $by_lid[$this->id2name($account)] = $in; + } + else + { + $by_lid[$account] = $in; + $by_id[$this->name2id($account)] = $in; + } + return $in; + } + + function create($account_info,$default_prefs=True) + { + /* echo '
in create for account_lid: "'.$account_lid.'"'; */ + if (empty($account_info['account_id']) || !$account_info['account_id']) + { + $account_id = $this->get_nextid($account_info['account_type']); + /* echo '
using'.$account_id;exit; */ + } + else + { + $account_id = abs($account_info['account_id']); + } + $entry['userpassword'] = $account_info['account_passwd']; + $entry['phpgwaccounttype'] = $account_info['account_type']; + $entry['phpgwaccountexpires'] = $account_info['account_expires']; + + if($account_info['account_type'] == 'g') + { + $sri = ldap_search($this->ds, $this->group_context, 'cn=' . (string)$account_info['account_lid']); + } + else + { + $sri = ldap_search($this->ds, $this->user_context, 'uid=' . (string)$account_info['account_lid']); + } + $allValues = ldap_get_entries($this->ds, $sri); + + if ($GLOBALS['egw_info']['server']['ldap_extra_attributes'] && $account_info['account_type'] != 'g') + { + $entry['homedirectory'] = $account_info['homedirectory'] && $account_info['homedirectory'] != $GLOBALS['egw_info']['server']['ldap_account_home'] ? $account_info['homedirectory'] : $GLOBALS['egw_info']['server']['ldap_account_home'].SEP.$account_info['account_lid']; + $entry['loginshell'] = $account_info['loginshell'] ? $account_info['loginshell'] : $GLOBALS['egw_info']['server']['ldap_account_shell']; + } + elseif($account_info['account_type'] != 'g') + { + $entry['homedirectory'] = '/home/'.$account_info['account_lid']; + $entry['loginshell'] = '/bin/false'; + } + + if ($allValues[0]['dn']) + { + /* This should keep the password from being overwritten here on ldap import */ + unset($entry['userpassword']); + $entry['gidnumber'] = $account_id; + + while (list($key,$val) = each($entry)) + { + $tmpentry = ''; + $tmpentry[$key] = trim($val); /* must trim! */ + /* echo '
'.$key.' '.$val; */ + if ($tmpentry[$key]) + { + if (!$allValues[0][$key][0]) + { + /* attribute was not in LDAP, add it */ + ldap_mod_add($this->ds, $allValues[0]['dn'], $tmpentry); + } + else + { + /* attribute was in LDAP, modify it */ + ldap_modify($this->ds, $allValues[0]['dn'], $tmpentry); + } + } + } + + if ($account_info['account_type'] == 'g') + { + $tmpentry['objectclass'][0] = 'top'; + $tmpentry['objectclass'][1] = 'posixGroup'; + $tmpentry['objectclass'][2] = 'phpgwAccount'; + #$tmpentry['objectclass'][3] = 'namedObject'; + } + else + { + $tmpentry['uidnumber'] = $account_id; + $tmpentry['objectclass'][0] = 'top'; + $tmpentry['objectclass'][1] = 'person'; + $tmpentry['objectclass'][2] = 'organizationalPerson'; + $tmpentry['objectclass'][3] = 'inetOrgPerson'; + $tmpentry['userpassword'] = $GLOBALS['egw']->common->encrypt_password($account_info['account_passwd'],False); + /* $tmpentry['objectclass'][4] = 'account'; Causes problems with some LDAP servers */ + $tmpentry['objectclass'][4] = 'posixAccount'; + $tmpentry['objectclass'][5] = 'shadowAccount'; + $tmpentry['objectclass'][6] = 'phpgwAccount'; + $tmpentry['phpgwaccountstatus'] = $account_info['account_status']; + $tmpentry['phpgwaccounttype'] = $account_info['account_type']; + $tmpentry['phpgwaccountexpires'] = $account_info['account_expires']; + } + ldap_modify($this->ds, $allValues[0]['dn'], $tmpentry); + } + else + { + /* Not already there, we will add it */ + if ($account_info['account_type'] == 'g') + { + $dn = 'cn='.$account_info['account_lid'] . ',' . $this->group_context; + unset($entry['homedirectory']); + unset($entry['loginshell']); + unset($entry['userpassword']); + $entry['objectclass'][0] = 'top'; + $entry['objectclass'][1] = 'posixGroup'; + $entry['objectclass'][2] = 'phpgwAccount'; + #$entry['objectclass'][3] = 'namedObject'; + $entry['cn'] = $GLOBALS['egw']->translation->convert($account_info['account_lid'],$GLOBALS['egw']->translation->charset(),'utf-8'); + $entry['gidnumber'] = $account_id; + $entry['description'] = 'eGW-created group'; + } + else + { + $dn = 'uid=' . $account_info['account_lid'] . ',' . $this->user_context; + + $entry['cn'] = $GLOBALS['egw']->translation->convert( + sprintf( + "%s %s", + $account_info['account_firstname'], + $account_info['account_lastname'] + ), + $GLOBALS['egw']->translation->charset(), + 'utf-8' + ); + + $entry['sn'] = $GLOBALS['egw']->translation->convert( + $account_info['account_lastname'] ? $account_info['account_lastname'] : 'not set', + $GLOBALS['egw']->translation->charset(), + 'utf-8' + ); + + if($account_info['account_firstname']) + { + $entry['givenname'] = $GLOBALS['egw']->translation->convert( + $account_info['account_firstname'], + $GLOBALS['egw']->translation->charset(), + 'utf-8' + ); + } + if($account_info['account_email']) + { + $entry['mail'] = $GLOBALS['egw']->translation->convert( + $account_info['account_email'], + $GLOBALS['egw']->translation->charset(), + 'utf-8' + ); + } + $entry['uid'] = $account_info['account_lid']; + $entry['uidnumber'] = $account_id; + $entry['gidnumber'] = abs($account_info['account_primary_group']); + $entry['userpassword'] = $GLOBALS['egw']->common->encrypt_password($account_info['account_passwd']); + $entry['objectclass'][0] = 'top'; + $entry['objectclass'][1] = 'person'; + $entry['objectclass'][2] = 'organizationalPerson'; + $entry['objectclass'][3] = 'inetOrgPerson'; + $entry['objectclass'][4] = 'posixAccount'; + $entry['objectclass'][5] = 'shadowAccount'; + $entry['objectclass'][6] = 'phpgwAccount'; + if($account_info['account_status']) + { + $entry['phpgwaccountstatus'] = $account_info['account_status']; + } + $entry['phpgwaccounttype'] = $account_info['account_type']; + $entry['phpgwaccountexpires'] = $account_info['account_expires']; + } + + #_debug_array($entry); + + // stop processing if ldap_add fails + if(!ldap_add($this->ds, $dn, $entry)) + { + return false; + } + } + // print ldap_error($this->ds); + + // lets check group the user needs to be added + if($account_info['account_type'] == 'u') + { + @settype($account_info['account_groups'],'array'); + foreach($account_info['account_groups'] as $key => $value) + { + // search for the group + $filter = 'gidnumber=' . abs($value); + $justThese = array('memberuid'); + $sri = ldap_search($this->ds, $this->group_context, $filter, $justThese); + if($sri) + { + $allValues = ldap_get_entries($this->ds, $sri); + // if the user is not member of this group, add him + if(is_array($allValues[0]['memberuid'])) + { + // this group has already some members + if(!in_array($account_info['account_lid'],$allValues[0]['memberuid'])) + { + $dn = $allValues[0]['dn']; + $newData = array(); + $newData['memberuid'] = $allValues[0]['memberuid']; + unset($newData['memberuid']['count']); + $newData['memberuid'][] = $account_info['account_lid']; + $newData['memberuid'] = array_unique($newData['memberuid']); + ldap_mod_replace($this->ds, $dn, $newData); + #print ldap_error($this->ds)."
"; + } + } + else + { + // this group has no members + $dn = $allValues[0]['dn']; + $newData = array(); + $newData['memberuid'][] = $account_info['account_lid']; + ldap_mod_replace($this->ds, $dn, $newData); + } + } + } + } + + if($account_id && is_object($GLOBALS['egw']->preferences) && $default_prefs) + { + $GLOBALS['egw']->preferences->create_defaults($account_id); + } + + if($account_info['account_type'] == 'g') + { + return -$account_id; + } + else + { + return $account_id; + } + } + + function auto_add($accountname, $passwd, $default_prefs = False, $default_acls = False, $expiredate = 0, $account_status = 'A') + { + if ($expiredate == 0) + { + if(isset($GLOBALS['egw_info']['server']['auto_create_expire']) == True) + { + if($GLOBALS['egw_info']['server']['auto_create_expire'] == 'never') + { + $expires = -1; + } + else + { + $expiredate = time() + $GLOBALS['egw_info']['server']['auto_create_expire']; + } + } + } + else + { + /* expire in 30 days by default */ + $expiredate = time() + ((60 * 60) * (30 * 24)); + } + + if ($expires != -1) + { + $expires = mktime(2,0,0,date('n',$expiredate), (int)date('d',$expiredate), date('Y',$expiredate)); + } + + $default_group_id = $this->name2id($GLOBALS['egw_info']['server']['default_group_lid']); + if (!$default_group_id) + { + $default_group_id = abs((int)$this->name2id('Default')); + } + $primary_group = $GLOBALS['auto_create_acct']['primary_group'] && + $this->get_type((int)$GLOBALS['auto_create_acct']['primary_group']) == 'g' ? + (int)$GLOBALS['auto_create_acct']['primary_group'] : $default_group_id; + + $acct_info = array( + 'account_lid' => $accountname, + 'account_type' => 'u', + 'account_passwd' => $passwd, + 'account_firstname' => $GLOBALS['auto_create_acct']['firstname'] ? $GLOBALS['auto_create_acct']['firstname'] : 'New', + 'account_lastname' => $GLOBALS['auto_create_acct']['lastname'] ? $GLOBALS['auto_create_acct']['lastname'] : 'User', + 'account_status' => $account_status, + 'account_expires' => $expires, + 'account_primary_group' => $primary_group, + ); + + /* attempt to set an email address */ + if (isset($GLOBALS['auto_create_acct']['email']) == True && $GLOBALS['auto_create_acct']['email'] != '') + { + $acct_info['account_email'] = $GLOBALS['auto_create_acct']['email']; + } + elseif(isset($GLOBALS['egw_info']['server']['mail_suffix']) == True && $GLOBALS['egw_info']['server']['mail_suffix'] != '') + { + $acct_info['account_email'] = $accountname . '@' . $GLOBALS['egw_info']['server']['mail_suffix']; + } + + $this->db->transaction_begin(); + + $this->create($acct_info,$default_prefs); /* create the account */ + + $accountid = $this->name2id($accountname); /* grab the account id or an error code */ + + if ($accountid) /* begin account setup */ + { + if($primary_group) + { + $GLOBALS['egw']->acl->add_repository('phpgw_group', $primary_group,$accountid,1); + } + + /* if we have an mail address set it in the users' email preference */ + if (isset($GLOBALS['auto_create_acct']['email']) && $GLOBALS['auto_create_acct']['email'] != '') + { + $GLOBALS['egw']->acl->acl($accountid); /* needed als preferences::save_repository calls acl */ + $GLOBALS['egw']->preferences->preferences($accountid); + $GLOBALS['egw']->preferences->read_repository(); + $GLOBALS['egw']->preferences->add('email','address',$GLOBALS['auto_create_acct']['email']); + $GLOBALS['egw']->preferences->save_repository(); + } + /* use the default mail domain to set the uesrs' email preference */ + elseif(isset($GLOBALS['egw_info']['server']['mail_suffix']) && $GLOBALS['egw_info']['server']['mail_suffix'] != '') + { + $GLOBALS['egw']->acl->acl($accountid); /* needed als preferences::save_repository calls acl */ + $GLOBALS['egw']->preferences->preferences($accountid); + $GLOBALS['egw']->preferences->read_repository(); + $GLOBALS['egw']->preferences->add('email','address', $accountname . '@' . $GLOBALS['egw_info']['server']['mail_suffix']); + $GLOBALS['egw']->preferences->save_repository(); + } + + /* commit the new account transaction */ + $this->db->transaction_commit(); + + // call hook to notify interested apps about the new account + $GLOBALS['hook_values']['account_lid'] = $acct_info['account_lid']; + $GLOBALS['hook_values']['account_id'] = $accountid; + $GLOBALS['hook_values']['new_passwd'] = $acct_info['account_passwd']; + $GLOBALS['hook_values']['account_status'] = $acct_info['account_status']; + $GLOBALS['hook_values']['account_firstname'] = $acct_info['account_firstname']; + $GLOBALS['hook_values']['account_lastname'] = $acct_info['account_lastname']; + $GLOBALS['egw']->hooks->process($GLOBALS['hook_values']+array( + 'location' => 'addaccount', + // at login-time only the hooks from the following apps will be called + 'order' => array('felamimail','fudforum'), + ),False,True); // called for every app now, not only enabled ones + } /* end account setup */ + else /* if no account id abort the account creation */ + { + $this->db->transaction_abort(); + } + + /* + * If we succeeded in creating the account (above), return the accountid, else, + * return the error value from $this->name2id($accountname) + */ + return $accountid; + } /* end auto_add() */ + + function get_account_name($account_id,&$lid,&$fname,&$lname) + { + $acct_type = $this->get_type($account_id); + + /* search the dn for the given uid */ + if(($acct_type == 'g') && $this->group_context) + { + $sri = ldap_search($this->ds, $this->group_context, 'gidnumber=' . abs((int)$account_id)); + } + else + { + $sri = ldap_search($this->ds, $this->user_context, 'uidnumber=' . (int)$account_id); + } + $allValues = ldap_get_entries($this->ds, $sri); + + if($acct_type =='g') + { + $lid = $GLOBALS['egw']->translation->convert($allValues[0]['cn'][0],'utf-8'); + $fname = $GLOBALS['egw']->translation->convert($allValues[0]['cn'][0],'utf-8'); + $lname = lang('Group'); + } + else + { + $lid = $GLOBALS['egw']->translation->convert($allValues[0]['uid'][0],'utf-8'); + $fname = $GLOBALS['egw']->translation->convert($allValues[0]['givenname'][0],'utf-8'); + $lname = $GLOBALS['egw']->translation->convert($allValues[0]['sn'][0],'utf-8'); + } + return !empty($lid); + } + + function getDNforID($_accountid = '') + { + $_account_id = get_account_id($_accountid); + + $sri = ldap_search($this->ds, $this->user_context, 'uidnumber=' . (int)$_account_id); + $allValues = ldap_get_entries($this->ds, $sri); + + return $allValues[0]['dn']; + } + + /** + * Update the last login timestamps and the IP + * + * @param int $account_id + * @param string $ip + * @return int lastlogin time + */ + function update_lastlogin($_account_id, $ip) + { + $entry['phpgwaccountlastlogin'] = time(); + $entry['phpgwaccountlastloginfrom'] = $ip; + + $sri = ldap_search($this->ds, $GLOBALS['egw_info']['server']['ldap_context'], 'uidnumber=' . (int)$_account_id); + $allValues = ldap_get_entries($this->ds, $sri); + + $dn = $allValues[0]['dn']; + @ldap_modify($this->ds, $dn, $entry); + + return $allValues[0]['phpgwaccountlastlogin'][0]; + } + }