* * and Dan Kuykendall * * and Bettina Gille [ceb@phpgroupware.org] * * View and manipulate account records using SQL * * Copyright (C) 2000 - 2002 Joseph Engo * * Copyright (C) 2003 Joseph Engo, 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 for handling user and group accounts in SQL */ class accounts_ { var $db; var $account_id; var $data; var $total; var $table = 'egw_accounts'; function accounts_() { } function list_methods($_type='xmlrpc') { if (is_array($_type)) { $_type = $_type['type'] ? $_type['type'] : $_type[0]; } switch($_type) { case 'xmlrpc': $xml_functions = array( 'get_list' => array( 'function' => 'get_list', 'signature' => array(array(xmlrpcStruct)), 'docstring' => lang('Returns a full list of accounts on the system. Warning: This is return can be quite large') ), 'list_methods' => array( 'function' => 'list_methods', 'signature' => array(array(xmlrpcStruct,xmlrpcString)), 'docstring' => lang('Read this list of methods.') ) ); return $xml_functions; break; case 'soap': return $this->soap_functions; break; default: return array(); break; } } /** * grabs the records from the data store * */ function read_repository() { $this->db->select($this->table,'*',array('account_id'=>abs($this->account_id)),__LINE__,__FILE__); $this->data['account_id'] = $this->db->next_record() ? $this->account_id : null; $this->data['account_lid'] = $this->data['userid'] = $this->db->f('account_lid'); $this->data['firstname'] = $this->db->f('account_firstname'); $this->data['lastname'] = $this->db->f('account_lastname'); $this->data['fullname'] = $this->db->f('account_firstname') . ' ' . $this->db->f('account_lastname'); $this->data['lastlogin'] = $this->db->f('account_lastlogin'); $this->data['lastloginfrom'] = $this->db->f('account_lastloginfrom'); $this->data['lastpasswd_change'] = $this->db->f('account_lastpwd_change'); $this->data['status'] = $this->db->f('account_status'); $this->data['expires'] = $this->db->f('account_expires'); $this->data['person_id'] = $this->db->f('person_id'); $this->data['account_primary_group'] = $this->db->f('account_primary_group'); $this->data['email'] = $this->db->f('account_email'); return $this->data; } /** * saves the records to the data store * */ function save_repository() { $data = array( 'account_firstname' => $this->data['firstname'], 'account_lastname' => $this->data['lastname'], 'account_status' => $this->data['status'], 'account_expires' => $this->data['expires'], 'account_lid' => $this->data['account_lid'], 'account_primary_group' => $this->data['account_primary_group'], 'account_email' => $this->data['email'], ); // overwrite person_id only if it's set in this->data! if (isset($this->data['person_id'])) { $data['person_id'] = $this->data['person_id']; } $this->db->update($this->table,$data,array( 'account_id' => abs($this->account_id) ),__LINE__,__FILE__); } function delete($accountid = '') { $account_id = get_account_id($accountid); /* Do this last since we are depending upon this record to get the account_lid above */ $this->db->lock(Array($this->table)); $this->db->delete($this->table,array('account_id'=>abs($account_id)),__LINE__,__FILE__); $this->db->unlock(); } function get_list($_type='both',$start = '',$sort = '', $order = '', $query = '', $offset = '',$query_type='') { if (! $sort) { $sort = "DESC"; } if (!empty($order) && preg_match('/^[a-zA-Z_0-9, ]+$/',$order) && (empty($sort) || preg_match('/^(DESC|ASC|desc|asc)$/',$sort))) { $orderclause = "ORDER BY $order $sort"; } else { $orderclause = "ORDER BY account_lid ASC"; } switch($_type) { case 'accounts': $whereclause = "WHERE account_type = 'u'"; break; case 'groups': $whereclause = "WHERE account_type = 'g'"; break; default: $whereclause = ''; } if ($query) { if ($whereclause) { $whereclause .= ' AND ( '; } else { $whereclause = ' WHERE ( '; } switch($query_type) { case 'all': default: $query = '%'.$query; // fall-through case 'start': $query .= '%'; // fall-through case 'exact': $query = $this->db->quote($query); $whereclause .= " account_firstname LIKE $query OR account_lastname LIKE $query OR account_lid LIKE $query )"; break; case 'firstname': case 'lastname': case 'lid': case 'email': $query = $this->db->quote('%'.$query.'%'); $whereclause .= " account_$query_type LIKE $query )"; break; } } $sql = "SELECT * FROM $this->table $whereclause $orderclause"; if ($offset) { $this->db->limit_query($sql,$start,__LINE__,__FILE__,$offset); } elseif (is_numeric($start)) { $this->db->limit_query($sql,$start,__LINE__,__FILE__); } else { $this->db->query($sql,__LINE__,__FILE__); } while ($this->db->next_record()) { $accounts[] = Array( 'account_id' => ($this->db->f('account_type') == 'g' ? -1 : 1) * $this->db->f('account_id'), 'account_lid' => $this->db->f('account_lid'), 'account_type' => $this->db->f('account_type'), 'account_firstname' => $this->db->f('account_firstname'), 'account_lastname' => $this->db->f('account_lastname'), 'account_status' => $this->db->f('account_status'), 'account_expires' => $this->db->f('account_expires'), 'person_id' => $this->db->f('person_id'), 'account_primary_group' => $this->db->f('account_primary_group'), 'account_email' => $this->db->f('account_email'), ); } $this->db->query("SELECT count(*) FROM $this->table $whereclause"); $this->total = $this->db->next_record() ? $this->db->f(0) : 0; return $accounts; } /** * converts a name / unique value from the accounts-table (account_lid,account_email) to an id */ function name2id($name,$which='account_lid') { $where = $which == 'account_fullname' ? '('.$this->db->concat('account_firstname',"' '",'account_lastname').')='.$this->db->quote($name) : array($which => $name); $this->db->select($this->table,'account_id,account_type',$where,__LINE__,__FILE__); if($this->db->next_record()) { return ($this->db->f('account_type') == 'g' ? -1 : 1) * $this->db->f('account_id'); } return False; } /** * converts an id to the corresponding value of the accounts-table (account_lid,account_email,account_firstname,...) */ function id2name($account_id,$which='account_lid') { $this->db->select($this->table,$this->db->name_quote($which),array('account_id'=>abs($account_id)),__LINE__,__FILE__); if($this->db->next_record()) { return $this->db->f(0); } return False; } function exists($account_lid) { static $by_id, $by_lid; $where = array(); if(is_numeric($account_lid)) { if(@isset($by_id[$account_lid]) && $by_id[$account_lid] != '') { return $by_id[$account_lid]; } $where['account_id'] = abs($account_lid); } else { if(@isset($by_lid[$account_lid]) && $by_lid[$account_lid] != '') { return $by_lid[$account_lid]; } $where['account_lid'] = $account_lid; } $this->db->select($this->table,'count(*)',$where,__LINE__,__FILE__); $this->db->next_record(); $ret_val = $this->db->f(0) > 0; if(is_numeric($account_lid)) { $by_id[$account_lid] = $ret_val; $by_lid[$this->id2name($account_lid)] = $ret_val; } else { $by_lid[$account_lid] = $ret_val; $by_id[$this->name2id($account_lid)] = $ret_val; } return $ret_val; } function create($account_info) { $account_data = array( 'account_lid' => $account_info['account_lid'], 'account_pwd' => $GLOBALS['egw']->common->encrypt_password($account_info['account_passwd'],True), 'account_firstname' => $account_info['account_firstname'], 'account_lastname' => $account_info['account_lastname'], 'account_status' => $account_info['account_status'], 'account_expires' => $account_info['account_expires'], 'account_type' => $account_info['account_type'], 'person_id' => $account_info['person_id'], 'account_primary_group' => $account_info['account_primary_group'], 'account_email' => $account_info['account_email'], ); if (isset($account_info['account_id']) && (int)$account_info['account_id'] && !$this->id2name($account_info['account_id'])) { // only use account_id, if it's not already used $account_data['account_id'] = abs($account_info['account_id']); } if (!$this->db->insert($this->table,$account_data,False,__LINE__,__FILE__)) { return false; } $id = $account_data['account_id'] ? $account_data['account_id'] : $this->db->get_last_insert_id($this->table,'account_id'); if ($account_info['account_type'] == 'g' && $id > 0) // create negative id for groups { $id = -$id; } return $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 = (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_id' => (int) $GLOBALS['auto_create_acct']['id'], '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(); $accountid = $this->create($acct_info); /* create the account */ if ($accountid) /* begin account setup */ { /* If we have a primary_group, add it as "regular" eGW group (via ACL) too. */ 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($accountid,&$lid,&$fname,&$lname) { $this->db->select($this->table,'account_lid,account_firstname,account_lastname',array('account_id'=>abs($accountid)),__LINE__,__FILE__); if (!$this->db->next_record()) { return False; } $lid = $this->db->f('account_lid'); $fname = $this->db->f('account_firstname'); $lname = $this->db->f('account_lastname'); return True; } /** * 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) { $this->db->select($this->table,'account_lastlogin',array('account_id'=>abs($account_id)),__LINE__,__FILE__); $previous_login = $this->db->next_record() ? $this->db->f('account_lastlogin') : false; $this->db->update($this->table,array( 'account_lastloginfrom' => $ip, 'account_lastlogin' => time(), ),array( 'account_id' => abs($account_id), ),__LINE__,__FILE__); return $previous_login; } }