diff --git a/phpgwapi/inc/class.contacts.inc.php b/phpgwapi/inc/class.contacts.inc.php index 1c5f686942..e2ac7df2df 100644 --- a/phpgwapi/inc/class.contacts.inc.php +++ b/phpgwapi/inc/class.contacts.inc.php @@ -1,7 +1,8 @@ diff --git a/phpgwapi/inc/class.contacts_ldap.inc.php b/phpgwapi/inc/class.contacts_ldap.inc.php new file mode 100644 index 0000000000..697397ca1d --- /dev/null +++ b/phpgwapi/inc/class.contacts_ldap.inc.php @@ -0,0 +1,845 @@ + * + * View and manipulate contact records using LDAP * + * -------------------------------------------------------------------------* + * This library is part of the phpGroupWare API * + * http://www.phpgroupware.org/api * + * ------------------------------------------------------------------------ * + * 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 contacts + @abstract Contact List System + @discussion Author: jengo/Milosch
+ This class provides a contact database scheme.
+ It attempts to be based on the vcard 2.1 standard, with mods as needed to make for more reasonable sql storage.
+ The LDAP schema used here may require installation of schema files available in the phpgwapi/doc/ldap dir. + Please see the README file there. + Syntax: CreateObject('phpgwapi.contacts');
+ Example1: $contacts = CreateObject('phpgwapi.contacts'); + */ + class contacts_ + { + var $db; + var $ldap; + var $nextid; + var $std_table=''; + var $ext_table='phpgw_addressbook_extra'; + + var $account_id; + var $stock_contact_fields; + var $non_contact_fields; + var $email_types; + var $total_records; + var $grants; + + function contacts_() + { + global $phpgw, $phpgw_info; + + $this->db = $phpgw->db; + $this->ldap = $phpgw->common->ldapConnect( + $phpgw_info['server']['ldap_contact_host'], + $phpgw_info['server']['ldap_contact_dn'], + $phpgw_info['server']['ldap_contact_pw'] + ); + $this->account_id = $phpgw_info['user']['account_id']; + $this->grants = $phpgw->acl->get_grants('addressbook'); + + /* The left side are the array elements used throughout phpgw, right side are the ldap attributes */ + $this->stock_contact_fields = array( + 'fn' => 'cn', + 'n_given' => 'givenname', + 'n_family' => 'sn', + 'n_middle' => 'phpgwmiddlename', + 'n_prefix' => 'phpgwprefix', + 'n_suffix' => 'phpgwsuffix', + 'sound' => 'phpgwaudio', + 'bday' => 'phpgwbirthday', + 'note' => 'description', + 'tz' => 'phpgwtz', + 'geo' => 'phpgwgeo', + 'url' => 'phpgwurl', + 'pubkey' => 'phpgwpublickey', + + 'org_name' => 'o', + 'org_unit' => 'ou', + 'title' => 'title', + + 'adr_one_street' => 'street', + 'adr_one_locality' => 'l', + 'adr_one_region' => 'st', + 'adr_one_postalcode' => 'postalcode', + 'adr_one_countryname' => 'co', + 'adr_one_type' => 'phpgwadronetype', + 'label' => 'phpgwaddresslabel', + + 'adr_two_street' => 'phpgwadrtwostreet', + 'adr_two_locality' => 'phpgwadrtwolocality', + 'adr_two_region' => 'phpgwadrtworegion', + 'adr_two_postalcode' => 'phpgwadrtwopostalcode', + 'adr_two_countryname' => 'phpgwadrtwocountryname', + 'adr_two_type' => 'phpgwadrtwotype', + + 'tel_work' => 'telephonenumber', + 'tel_home' => 'homephone', + 'tel_voice' => 'phpgwvoicetelephonenumber', + 'tel_fax' => 'facsimiletelephonenumber', + 'tel_msg' => 'phpgwmsgtelephonenumber', + 'tel_cell' => 'phpgwcelltelephonenumber', + 'tel_pager' => 'phpgwpagertelephonenumber', + 'tel_bbs' => 'phpgwbbstelephonenumber', + 'tel_modem' => 'phpgwmodemtelephonenumber', + 'tel_car' => 'phpgwmobiletelephonenumber', + 'tel_isdn' => 'phpgwisdnphonenumber', + 'tel_video' => 'phpgwvideophonenumber', + 'tel_prefer' => 'phpgwpreferphone', + 'email' => 'mail', + 'email_type' => 'phpgwmailtype', + 'email_home' => 'phpgwmailhome', + 'email_home_type' => 'phpgwmailhometype' + ); + + $this->non_contact_fields = array( + 'id' => 'uidnumber', + 'lid' => 'uid', + 'tid' => 'phpgwcontacttypeid', + 'cat_id' => 'phpgwcontactcatid', + 'access' => 'phpgwcontactaccess', + 'owner' => 'phpgwcontactowner' + ); + + /* Used to flag an address as being: + domestic OR international(default) + parcel(default) + postal(default) + work(default) OR home + */ + $this->adr_types = array( + 'dom' => lang('Domestic'), + 'intl' => lang('International'), + 'parcel' => lang('Parcel'), + 'postal' => lang('Postal') + ); + + /* Used to set preferphone field */ + $this->tel_types = array( + 'work' => 'work', + 'home' => 'home', + 'voice' => 'voice', + 'fax' => 'fax', + 'msg' => 'msg', + 'cell' => 'cell', + 'pager' => 'pager', + 'bbs' => 'bbs', + 'modem' => 'modem', + 'car' => 'car', + 'isdn' => 'isdn', + 'video' => 'video' + ); + + /* Used to set mail_type fields */ + $this->email_types = array( + 'INTERNET' => 'INTERNET', + 'CompuServe' => 'CompuServe', + 'AOL' => 'AOL', + 'Prodigy' => 'Prodigy', + 'eWorld' => 'eWorld', + 'AppleLink' => 'AppleLink', + 'AppleTalk' => 'AppleTalk', + 'PowerShare' => 'PowerShare', + 'IBMMail' => 'IBMMail', + 'ATTMail' => 'ATTMail', + 'MCIMail' => 'MCIMail', + 'X.400' => 'X.400', + 'TLX' => 'TLX' + ); + } + + /* send this the id and whatever fields you want to see */ + function read_single_entry($id,$fields = '') + { + global $phpgw_info; + if (!$fields || empty($fields)) { $fields = $this->stock_contact_fields; } + list($stock_fields,$stock_fieldnames,$extra_fields) = + $this->split_stock_and_extras($fields); + + if (count($stock_fieldnames)) + { + $t_fields = "," . implode(",",$stock_fieldnames); + if ($t_fields == ",") + { + unset($t_fields); + } + } + + $sri = ldap_search($this->ldap, $phpgw_info['server']['ldap_contact_context'], 'uidnumber='.$id); + $ldap_fields = ldap_get_entries($this->ldap, $sri); + + $return_fields[0]['id'] = $ldap_fields[0]['uidnumber'][0]; + $return_fields[0]['lid'] = $ldap_fields[0]['uid'][0]; + $return_fields[0]['tid'] = $ldap_fields[0]['phpgwcontacttypeid'][0]; + $return_fields[0]['owner'] = $ldap_fields[0]['phpgwcontactowner'][0]; + $return_fields[0]['access'] = $ldap_fields[0]['phpgwcontactaccess'][0]; + $return_fields[0]['cat_id'] = $ldap_fields[0]['phpgwcontactcatid'][0]; + if (gettype($stock_fieldnames) == 'array') + { + while(list($name,$value)=each($stock_fieldnames)) + { + $return_fields[0][$name] = $ldap_fields[0][$value][0]; + } + } + + /* Setup address type fields */ + if ($return_fields[0]['adr_one_type']) + { + $one_type = $return_fields[0]['adr_one_type']; + reset($this->adr_types); + while (list($name,$val) = each($this->adr_types)) + { + eval("if (strstr(\$one_type,\$name)) { \$return_fields[0][\"one_\$name\"] = \"on\"; }"); + } + } + if ($return_fields[0]["adr_two_type"]) + { + $two_type = $return_fields[0]['adr_two_type']; + reset($this->adr_types); + while (list($name,$val) = each($this->adr_types)) + { + eval("if (strstr(\$two_type,\$name)) { \$return_fields[0][\"two_\$name\"] = \"on\"; }"); + } + } + + $this->db->query("SELECT contact_name,contact_value FROM $this->ext_table WHERE contact_id='" . $id . "'",__LINE__,__FILE__); + while ($this->db->next_record()) + { + if ($extra_fields[$this->db->f('contact_name')]) + { + $return_fields[0][$this->db->f('contact_name')] = $this->db->f('contact_value'); + } + } + return $return_fields; + } + + function read_last_entry($fields = '') + { + global $phpgw_info; + + if (!$fields || empty($fields)) { $fields = $this->stock_contact_fields; } + list($stock_fields,$stock_fieldnames,$extra_fields) = + $this->split_stock_and_extras($fields); + + if (count($stock_fieldnames)) + { + $t_fields = "," . implode(",",$stock_fieldnames); + if ($t_fields == ",") + { + unset($t_fields); + } + } + + $id = $this->nextid; + if ($id == -1) { $id = 1; } + + $sri = ldap_search($this->ldap, $phpgw_info['server']['ldap_contact_context'], 'uidnumber='.$id); + $ldap_fields = ldap_get_entries($this->ldap, $sri); + + $return_fields[0]['id'] = $ldap_fields[0]['uidnumber'][0]; + $return_fields[0]['lid'] = $ldap_fields[0]['uid'][0]; + $return_fields[0]['tid'] = $ldap_fields[0]['phpgwcontacttypeid'][0]; + $return_fields[0]['owner'] = $ldap_fields[0]['phpgwcontactowner'][0]; + $return_fields[0]['access'] = $ldap_fields[0]['phpgwcontactaccess'][0]; + $return_fields[0]['cat_id'] = $ldap_fields[0]['phpgwcontactcatid'][0]; + + if (gettype($stock_fieldnames) == 'array') + { + while(list($name,$value)=each($stock_fieldnames)) + { + $return_fields[0][$name] = $ldap_fields[0][$value][0]; + } + } + + /* Setup address type fields */ + if ($return_fields[0]['adr_one_type']) + { + $one_type = $return_fields[0]['adr_one_type']; + reset($this->adr_types); + while (list($name,$val) = each($this->adr_types)) + { + eval("if (strstr(\$one_type,\$name)) { \$return_fields[0][\"one_\$name\"] = \"on\"; }"); + } + } + if ($return_fields[0]['adr_two_type']) + { + $two_type = $return_fields[0]['adr_two_type']; + reset($this->adr_types); + while (list($name,$val) = each($this->adr_types)) + { + eval("if (strstr(\$two_type,\$name)) { \$return_fields[0][\"two_\$name\"] = \"on\"; }"); + } + } + + $this->db->query("SELECT contact_name,contact_value FROM $this->ext_table WHERE contact_id='" . $id . "'",__LINE__,__FILE__); + while ($this->db->next_record()) + { + if ($extra_fields[$this->db->f('contact_name')]) + { + $return_fields[0][$this->db->f('contact_name')] = $this->db->f('contact_value'); + } + } + return $return_fields; + } + + /* send this the range, query, sort, order and whatever fields you want to see */ + function read($start=0,$limit=0,$fields="",$query="",$filter="",$sort="",$order="") + { + global $phpgw,$phpgw_info; + + if (!$fields || empty($fields)) { $fields = $this->stock_contact_fields; } + $DEBUG = 0; + + list($stock_fields,$stock_fieldnames,$extra_fields) = $this->split_stock_and_extras($fields); + + $filterfields = array(); + /* turn filter's a=b,c=d OR a=b into an array */ + if ($filter) + { + if ($DEBUG) { echo "DEBUG - Inbound filter is: #".$filter."#"; } + $filterarray = split(',',$filter); + if ($filterarray[1]) + { + $i=0; + for ($i=0;$iDEBUG - Filter strings: #".$this->non_contact_fields[$name]."# => #".$value."#"; } + $filterfields[$this->non_contact_fields[$name]] = $value; + } + } + } + else + { + list($name,$value) = split('=',$filter); + if ($DEBUG) + { + echo "
DEBUG - Filter strings: #".$this->non_contact_fields[$name]."# => #".$value."#"; + } + $filterfields = array($this->non_contact_fields[$name] => $value); + } + } + else + { + $filterfields += array('phpgwcontacttypeid' => 'n'); + if ($DEBUG) { echo "
DEBUG - Filter strings: #phpgwtypeid=n#"; } + } + + if (is_array($this->grants)) + { + $filterfields += array('phpgwcontactaccess' => 'public'); + $grants = $this->grants; + while (list($user) = each($grants)) + { + if ($DEBUG) { echo "
DEBUG - Grant from owner: ".$user; } + $filterfields += array('phpgwcontactowner' => $user); + } + } + /* + if ($DEBUG) { + while(list($name,$value) = each($filterfields)) { + echo "
DEBUG - Filter strings: #".$name.",".$value."#"; + } + } + */ + + if (!$sort) { $sort = "ASC"; } + + if (!$order) + { + $order = "n_family"; + } + + if ($DEBUG && $order) + { + echo "
DEBUG - ORDER by $order"; + } + + if ($query) + { + $ldap_fields = array(); + $total = 0; + /* + Query each field seperately instead of using ldap OR search. + This should be changed to use ldap and/or syntax + */ + reset($stock_fieldnames); + while (list($name,$value) = each($stock_fieldnames) ) + { + $lquery = $value.'=*'.$query.'*'; + /* echo $lquery; exit; */ + $sri = ldap_search($this->ldap, $phpgw_info['server']['ldap_contact_context'], $lquery); + /* append the results */ + $ldap_fields += ldap_get_entries($this->ldap, $sri); + /* add the # rows to our total */ + $total = $total + ldap_count_entries($this->ldap, $sri); + } + + if ($filterfields) + { + $ldap_fields = $this->filter_ldap($ldap_fields,$filterfields,$DEBUG); + } + + /* Now, remove duplicate rows */ + $ldap_fields = $this->asortbyindex($ldap_fields,'uidnumber'); + @reset($ldap_fields); + if (count($ldap_fields) > 0) + { + for ($a = 0; $a < count($ldap_fields); $a++) + { + if ($ldap_fields[$a]) + { + /* + echo '
comparing "'.$ldap_fields[$a]['uidnumber'][0] + .'" to "'.$ldap_fields[$a - 1]['uidnumber'][0].'"'; + */ + if (($ldap_fields[$a]['uidnumber'][0] <> $ldap_fields[$a - 1]['uidnumber'][0])) + { + $uniquearray[$a] = $ldap_fields[$a]; + } + else + { + /* echo '
deleting "'.$ldap_fields[$a -1 ]['uidnumber'][0]; */ + } + } + } + $ldap_fields = $uniquearray; + } + + $this->total_records = count($ldap_fields); + /* echo '
total="'.$this->total_records.'"'; */ + } + else + { + $sri = ldap_search($this->ldap, $phpgw_info['server']['ldap_contact_context'], 'phpgwcontactowner=*'); + $ldap_fields = ldap_get_entries($this->ldap, $sri); + $this->total_records = ldap_count_entries($this->ldap, $sri); + + if ($filterfields) + { + $ldap_fields = $this->filter_ldap($ldap_fields,$filterfields,$DEBUG); + } + } + + /* Use shared sorting routines, based on sort and order */ + if ($sort == 'ASC') + { + $ldap_fields = $this->asortbyindex($ldap_fields, $this->stock_contact_fields[$order]); + } + else + { + $ldap_fields = $this->arsortbyindex($ldap_fields, $this->stock_contact_fields[$order]); + } + + /* + This logic allows you to limit rows, or not. + The export feature, for example, does not limit rows. + This way, it can retrieve all rows at once. + */ + if ($start && $limit) + { + $limit = $start + $limit; + } + elseif ($start && !$limit) + { + $limit = $start; + } + elseif(!$start && !$limit) + { + $limit = $this->total_records; + } + else + { + $start = 0; + $limit = $limit; + } + /* echo '('.$start.','.$limit.')'; */ + + @reset($ldap_fields); + $j=0; + for ($i=$start;$i<$limit;$i++) + { + if ($i<$this->total_records && $ldap_fields[$i]['uid'][0]) + { + $return_fields[$j]['id'] = $ldap_fields[$i]['uidnumber'][0]; + $return_fields[$j]['lid'] = $ldap_fields[$i]['uid'][0]; + $return_fields[$j]['tid'] = $ldap_fields[$i]['phpgwcontacttypeid'][0]; + $return_fields[$j]['owner'] = $ldap_fields[$i]['phpgwcontactowner'][0]; + $return_fields[$j]['access'] = $ldap_fields[$i]['phpgwcontactaccess'][0]; + $return_fields[$j]['cat_id'] = $ldap_fields[$i]['phpgwcontactcatId'][0]; + + if (gettype($stock_fieldnames) == 'array') + { + reset($stock_fieldnames); + while (list($f_name,$f_value) = each($stock_fieldnames)) + { + $return_fields[$j][$f_name] = $ldap_fields[$i][$f_value][0]; + } + reset($stock_fieldnames); + } + $this->db->query("SELECT contact_name,contact_value FROM $this->ext_table WHERE contact_id='" + . $ldap_fields[$i]['id'] . "'",__LINE__,__FILE__); + while ($this->db->next_record()) + { + if ($extra_fields[$this->db->f('contact_name')]) + { + $return_fields[$j][$this->db->f('contact_name')] = $this->db->f('contact_value'); + } + } + $j++; + } + } + return $return_fields; + } + + function add($owner,$fields,$access='private',$cat_id='0',$tid='n') + { + global $phpgw,$phpgw_info; + + if (!$phpgw_info['server']['ldap_contact_context']) + { + return False; + } + + list($stock_fields,$stock_fieldnames,$extra_fields) = $this->split_stock_and_extras($fields); + + $free = 0; + $this->nextid = $phpgw->common->last_id('contacts'); + /* Loop until we find a free id */ + while (!$free) + { + $ldap_fields = ''; + $sri = ldap_search($this->ldap, $phpgw_info['server']['ldap_contact_context'], 'uidnumber='.$this->nextid); + $ldap_fields = ldap_get_entries($this->ldap, $sri); + if ($ldap_fields[0]['dn'][0]) + { + $this->nextid = $phpgw->common->next_id('contacts'); + } + else + { + $free = True; + } + } + + $ldap_fields = ''; + if (gettype($stock_fieldnames) == 'array') + { + while(list($name,$value)=each($stock_fieldnames)) + { + if ($stock_fields[$name] != '') + { + $ldap_fields[$value] = $stock_fields[$name]; + } + } + } + + $time = gettimeofday(); + $ldap_fields['uid'] = time().$time['usec'].':'.$ldap_fields['givenname']; + + $dn = 'uid=' . $ldap_fields['uid'].',' . $phpgw_info['server']['ldap_contact_context']; + $ldap_fields['phpgwcontacttypeid'] = $tid; + $ldap_fields['phpgwcontactowner'] = $owner; + $ldap_fields['phpgwcontactaccess'] = $access; + $ldap_fields['phpgwcontactcatid'] = $cat_id; + $ldap_fields['uidnumber'] = $this->nextid; + /* $ldap_fields['objectclass'][0] = 'person'; */ + $ldap_fields['objectclass'][0] = 'organizationalPerson'; + $ldap_fields['objectclass'][1] = 'inetOrgPerson'; + $ldap_fields['objectclass'][2] = 'phpgwContact'; + + $err = ldap_add($this->ldap, $dn, $ldap_fields); + + if (count($extra_fields)) + { + while (list($name,$value) = each($extra_fields)) + { + $this->db->query("INSERT INTO $this->ext_table VALUES ('".$this->nextid."','" . $this->account_id . "','" + . addslashes($name) . "','" . addslashes($value) . "')",__LINE__,__FILE__); + } + } + } + + function field_exists($id,$field_name) + { + $this->db->query("select count(*) from $this->ext_table where contact_id='$id' and contact_name='" + . addslashes($field_name) . "'",__LINE__,__FILE__); + $this->db->next_record(); + return $this->db->f(0); + } + + function add_single_extra_field($id,$owner,$field_name,$field_value) + { + $this->db->query("insert into $this->ext_table values ($id,'$owner','" . addslashes($field_name) + . "','" . addslashes($field_value) . "')",__LINE__,__FILE__); + } + + function delete_single_extra_field($id,$field_name) + { + $this->db->query("delete from $this->ext_table where contact_id='$id' and contact_name='" + . addslashes($field_name) . "'",__LINE__,__FILE__); + } + + function update($id,$owner,$fields,$access='private',$cat_id='0',$tid='n') + { + global $phpgw_info; + $nonfields = $this->non_contact_fields; + + if (!$phpgw_info['server']['ldap_contact_context']) + { + return False; + } + + /* First make sure that id number exists */ + $sri = ldap_search($this->ldap, $phpgw_info['server']['ldap_contact_context'], 'uidnumber='.$id); + $ldap_fields = ldap_get_entries($this->ldap, $sri); + + if ($ldap_fields[0]['dn']) + { + $dn = $ldap_fields[0]['dn']; + list($stock_fields,$stock_fieldnames,$extra_fields) = $this->split_stock_and_extras($fields); + if (gettype($stock_fieldnames) == 'array') + { + /* + Check each value, add our extra attributes if they are missing, and + otherwise fix the entry while we can. + */ + /* Verify uidnumber */ + $stock_fields['id'] = $id; + if (empty($ldap_fields[0]['uidnumber'])) + { + $err = ldap_modify($this->ldap,$dn,array('uidnumber' => $stock_fields['uidnumber'])); + } + elseif (!$ldap_fields[0]['uidnumber']) + { + $err = ldap_mod_add($this->ldap,$dn,array('uidnumber' => $stock_fields['uidnumber'])); + } + + /* Verify uid */ + $uids = split(',',$dn); + $stock_fields['lid'] = $uids[0]; + if (empty($ldap_fields[0]['uid'])) + { + $err = ldap_modify($this->ldap,$dn,array('uid' => $stock_fields['lid'])); + } + elseif (!$ldap_fields[0]['uid']) + { + $err = ldap_mod_add($this->ldap,$dn,array('uid' => $stock_fields['lid'])); + } + + /* Verify objectclasses are there */ + if (empty($ldap_fields[0]['objectclass'])) + { + /* $stock_fields['objectclass'][0] = 'person'; */ + $stock_fields['objectclass'][0] = 'organizationalPerson'; + $stock_fields['objectclass'][1] = 'inetOrgPerson'; + $stock_fields['objectclass'][2] = 'phpgwContact'; + $err = ldap_modify($this->ldap,$dn,array('objectclass' => $stock_fields['objectclass'])); + } + elseif (!$ldap_fields[0]['objectclass']) + { + /* $stock_fields['objectclass'][0] = 'person'; */ + $stock_fields['objectclass'][0] = 'organizationalPerson'; + $stock_fields['objectclass'][1] = 'inetOrgPerson'; + $stock_fields['objectclass'][2] = 'phpgwContact'; + $err = ldap_mod_add($this->ldap,$dn,array('objectclass' => $stock_fields['objectclass'])); + } + + /* Verify owner */ + $stock_fields['owner'] = $owner; + if (empty($ldap_fields[0]['phpgwcontactowner'])) + { + $err = ldap_modify($this->ldap,$dn,array('phpgwcontactowner' => $stock_fields['owner'])); + } + elseif (!$ldap_fields[0]['phpgwcontactowner']) + { + $err = ldap_mod_add($this->ldap,$dn,array('phpgwcontactowner' => $stock_fields['owner'])); + } + + /* Verify access */ + $stock_fields['access'] = $access; + if (empty($ldap_fields[0]['phpgwcontactaccess'])) + { + $err = ldap_modify($this->ldap,$dn,array('phpgwcontactaccess' => $stock_fields['access'])); + } + elseif (!$ldap_fields[0]['phpgwcontactaccess']) + { + $err = ldap_mod_add($this->ldap,$dn,array('phpgwcontactaccess' => $stock_fields['access'])); + } + + /* Verify cat_id */ + $stock_fields['cat_id'] = $cat_id; + if (empty($ldap_fields[0]['phpgwcontactcatid'])) + { + $err = ldap_modify($this->ldap,$dn,array('phpgwcontactcatid' => $stock_fields['cat_id'])); + } + elseif (!$ldap_fields[0]['phpgwcontactcatid']) + { + $err = ldap_mod_add($this->ldap,$dn,array('phpgwcontactcatid' => $stock_fields['cat_id'])); + } + + /* Verify tid */ + $stock_fields['tid'] = $tid; + if (empty($ldap_fields[0]['phpgwcontacttypeid'])) + { + $err = ldap_modify($this->ldap,$dn,array('phpgwcontacttypeid' => $stock_fields['tid'])); + } + elseif (!$ldap_fields[0]['phpgwcontacttypeid']) + { + $err = ldap_mod_add($this->ldap,$dn,array('phpgwcontacttypeid' => $stock_fields['tid'])); + } + + /* OK, just mod the data already */ + $allfields = $stock_fieldnames + $nonfields; + while ( list($fname,$fvalue) = each($allfields) ) + { + /* if ($ldap_fields[0][$fvalue]) */ + if ($ldap_fields[0][$fvalue] && $stock_fields[$fname] && $ldap_fields[0][$fvalue][0] != $stock_fields[$fname] ) + { + /* echo "
".$fname." => ".$fvalue." was there"; */ + $err = ldap_modify($this->ldap,$dn,array($fvalue => $stock_fields[$fname])); + } + elseif (!$ldap_fields[0][$fvalue] && $stock_fields[$fname]) + { + /* echo "
".$fname." not there - '".$fvalue."'"; */ + $err = ldap_mod_add($this->ldap,$dn,array($fvalue => $stock_fields[$fname])); + } + elseif ($ldap_fields[0][$fvalue] && !$stock_fields[$fname]) + { + /* + echo "
".$fname." gone... deleting - '".$fvalue."'"; + NOTE: we use the ldap_fields because we need to send the + _ORIGINAL_ contents as the value. see: + http://www.php.net/manual/en/function.ldap-mod-del.php + */ + $err = ldap_mod_del($this->ldap,$dn,array($fvalue => $ldap_fields[0][$fvalue][0])); + } + /* Else we have nothing to do. */ + } + } + + while (list($x_name,$x_value) = each($extra_fields)) + { + if ($this->field_exists($id,$x_name)) + { + if (! $x_value) + { + $this->delete_single_extra_field($id,$x_name); + } + else + { + $this->db->query("UPDATE $this->ext_table SET contact_value='" . addslashes($x_value) + . "',contact_owner='$owner' WHERE contact_name='" . addslashes($x_name) + . "' AND contact_id='$id'",__LINE__,__FILE__); + } + } + else + { + $this->add_single_extra_field($id,$owner,$x_name,$x_value); + } + } + } + else + { + return False; + } + } + + /* Used by admin to change ownership on account delete */ + function change_owner($old_owner='',$new_owner='') + { + if (!($new_owner && $old_owner)) + { + return False; + } + + $sri = ldap_search($this->ldap, $phpgw_info['server']['ldap_contact_context'], 'phpgwcontactowner='.$old_owner); + $ldap_fields = ldap_get_entries($this->ldap, $sri); + + $entry = ""; + while (list($null,$entry) = each($ldap_fields)) + { + $err = ldap_modify($this->ldap,$dn,array('phpgwcontactowner' => $new_owner)); + } + + $this->db->query("UPDATE $this->ext_table SET contact_owner='$new_owner' WHERE contact_owner=$owner",__LINE__,__FILE__); + return; + } + + /* This is where the real work of delete() is done, shared class file contains calling function */ + function delete_($id) + { + global $phpgw_info; + + if (!$phpgw_info['server']['ldap_contact_context']) + { + return False; + } + + $sri = ldap_search($this->ldap, $phpgw_info['server']['ldap_contact_context'], 'uidnumber='.$id); + $ldap_fields = ldap_get_entries($this->ldap, $sri); + + if ($ldap_fields[0]['dn']) + { + $err = ldap_delete($this->ldap,$ldap_fields[0]['dn']); + + $this->db->query("DELETE FROM $this->ext_table WHERE contact_id='$id' AND contact_owner='" + . $this->account_id . "'",__LINE__,__FILE__); + } + else + { + return False; + } + } + + // This is for the admin script deleteaccount.php + function delete_all($owner=0) + { + global $phpgw_info; + + if (!$phpgw_info['server']['ldap_contact_context']) + { + return False; + } + + if ($owner) + { + $sri = ldap_search($this->ldap, $phpgw_info['server']['ldap_contact_context'], 'phpgwcontactowner='.$owner); + $ldap_fields = ldap_get_entries($this->ldap, $sri); + + $entry = ''; + while (list($null,$entry) = each($ldap_fields)) + { + $err = ldap_delete($this->ldap,$entry['dn']); + } + + $this->db->query("DELETE FROM $this->ext_table WHERE contact_owner=$owner",__LINE__,__FILE__); + } + return; + } + } +?> diff --git a/phpgwapi/inc/class.contacts_shared.inc.php b/phpgwapi/inc/class.contacts_shared.inc.php new file mode 100644 index 0000000000..a525a27fd9 --- /dev/null +++ b/phpgwapi/inc/class.contacts_shared.inc.php @@ -0,0 +1,345 @@ + * + * and Miles Lott * + * and Bettina Gille * + * View and manipulate contact records * + * Copyright (C) 2001 Joseph Engo * + * -------------------------------------------------------------------------* + * This library is part of the phpGroupWare API * + * http://www.phpgroupware.org/api * + * ------------------------------------------------------------------------ * + * 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 contacts extends contacts_ + { + function check_perms($has, $needed) + { + return (!!($has & $needed) == True); + } + + function split_stock_and_extras($fields) + { + while (list($field,$value) = each($fields)) + { + /* Depending on how the array was built, this is needed. */ + if (gettype($value) == "integer") + { + $value = $field; + } + if ($this->stock_contact_fields[$field]) + { + $stock_fields[$field] = $value; + $stock_fieldnames[$field] = $this->stock_contact_fields[$field]; + } + else + { + $extra_fields[$field] = $value; + } + } + return array($stock_fields,$stock_fieldnames,$extra_fields); + } + + function loop_addslashes($fields) + { + $absf = $this->stock_contact_fields; + while ($t = each($absf)) { + $ta[] = addslashes($fields[$t[0]]); + } + reset($absf); + return $ta; + } + + /* This will take an array or integer */ + function delete($id) + { + if (gettype($id) == "array") + { + while (list($null,$t_id) = each($id)) + { + $this->delete_($t_id); + } + } + else + { + $this->delete_($id); + } + } + + function asc_sort($a,$b) + { + echo "
A:'".$a."' B:'".$b; + if($a[1]==$b[1]) return 0; + return ($a[1]>$b[1])?1:-1; + } + + function desc_sort($a,$b) + { + echo "
A:'".$a."' B:'".$b; + if($a[1]==$b[1]) return 0; + return ($a[1]<$b[1])?1:-1; + } + + /* + comesafter ($s1, $s2) + Returns 1 if $s1 comes after $s2 alphabetically, 0 if not. + */ + function comesafter ($s1, $s2) + { + /* + We don't want to overstep the bounds of one of the strings and segfault, + so let's see which one is shorter. + */ + $order = 1; + + if ( (strlen($s1) == 0) ) + { + return 0; + } + + if ( (strlen($s2) == 0) ) + { + return 1; + } + + if (strlen ($s1) > strlen ($s2)) + { + $temp = $s1; + $s1 = $s2; + $s2 = $temp; + $order = 0; + } + + for ($index = 0; $index < strlen ($s1); $index++) + { + /* $s1 comes after $s2 */ + if (strtolower($s1[$index]) > strtolower($s2[$index])) { return ($order); } + + /* $s1 comes before $s2 */ + if (strtolower($s1[$index]) < strtolower($s2[$index])) { return (1 - $order); } + } + /* Special case in which $s1 is a substring of $s2 */ + + return ($order); + } + + /* + * asortbyindex ($sortarray, $index) + * + * Sort a multi-dimensional array by a second-degree index. For instance, the 0th index + * of the Ith member of both the group and user arrays is a string identifier. In the + * case of a user array this is the username; with the group array it is the group name. + * asortby + */ + function asortbyindex ($sortarray, $index) + { + $lastindex = count($sortarray) - 2; + for ($subindex = 0; $subindex < $lastindex; $subindex++) + { + $lastiteration = $lastindex - $subindex; + for ($iteration = 0; $iteration < $lastiteration; $iteration++) + { + $nextchar = 0; + if ($this->comesafter($sortarray[$iteration][$index], $sortarray[$iteration + 1][$index])) + { + $temp = $sortarray[$iteration]; + $sortarray[$iteration] = $sortarray[$iteration + 1]; + $sortarray[$iteration + 1] = $temp; + } + } + } + return ($sortarray); + } + + function arsortbyindex ($sortarray, $index) + { + $lastindex = count($sortarray) - 1; + for ($subindex = $lastindex; $subindex > 0; $subindex--) + { + $lastiteration = $lastindex - $subindex; + for ($iteration = $lastiteration; $iteration > 0; $iteration--) + { + $nextchar = 0; + if ($this->comesafter($sortarray[$iteration][$index], $sortarray[$iteration - 1][$index])) + { + $temp = $sortarray[$iteration]; + $sortarray[$iteration] = $sortarray[$iteration - 1]; + $sortarray[$iteration - 1] = $temp; + } + } + } + return ($sortarray); + } + + function filter_ldap ($ldap_fields,$filterfields,$DEBUG=0) + { + $match = 0; + if($DEBUG) { echo "
"; } + for($i=0;$i"; } + $new_ldap[] = $ldap_fields[$i]; + } + else + { + if($DEBUG) { echo $ldap_fields[$i]["uidnumber"][0].' did not match all.'."
"; } + } + } + } + if($DEBUG) + { + if($match) + { + echo '
'.$match.' total matches.'."\n"; + } + else + { + echo '
No matches :('."\n"; + } + } + $this->total_records = count($new_ldap); + + return $new_ldap; + } + + function formatted_address($id = '',$fields = '',$business = True) + { + global $phpgw,$phpgw_info; + + $font = $phpgw_info['theme']['font']; + + $t = CreateObject('phpgwapi.Template',$phpgw->common->get_tpl_dir('addressbook')); + + $s = CreateObject('phpgwapi.sbox'); + + $address = $this->read_single_entry($id,$fields); + + if ($address[0]['title']) + { + $title = $address[0]['title'] . ' '; + } + + if ($business) + { + $street = $address[0]['adr_one_street']; + $city = $address[0]['adr_one_locality']; + $zip = $address[0]['adr_one_postalcode']; + $state = $address[0]['adr_one_region']; + $country = $address[0]['adr_one_countryname']; + } + else + { + $street = $address[0]['adr_two_street']; + $city = $address[0]['adr_two_locality']; + $zip = $address[0]['adr_two_postalcode']; + $state = $address[0]['adr_two_region']; + $country = $address[0]['adr_two_countryname']; + } + + if (! $country) + { + $country = $phpgw_info['user']['preferences']['common']['country']; + } + + if (file_exists(PHPGW_SERVER_ROOT . SEP . 'addressbook' . SEP . 'templates' . SEP .'default' . SEP . 'format_' . strtolower($country) . '.tpl')) + { + $a = $t->set_file(array('address_format' => 'format_' . strtolower($country) . '.tpl')); + } + else + { + $a = $t->set_file(array('address_format' => 'format_us.tpl')); + } + + $a .= $t->set_var('font',$font); + $a .= $t->set_var('title',$title); + $a .= $t->set_var('firstname',$address[0]['n_given']); + $a .= $t->set_var('lastname',$address[0]['n_family']); + $a .= $t->set_var('company',$address[0]['org_name']); + $a .= $t->set_var('department',$address[0]['org_unit']); + $a .= $t->set_var('street',$street); + $a .= $t->set_var('city',$city); + $a .= $t->set_var('zip',$zip); + $a .= $t->set_var('state',$state); + + $countryname = $s->get_full_name($country); + $a .= $t->set_var('country',lang($countryname)); + + $a .= $t->fp('out','address_format'); + return $a; + } + } +?> diff --git a/phpgwapi/inc/class.contacts_sql.inc.php b/phpgwapi/inc/class.contacts_sql.inc.php new file mode 100644 index 0000000000..9d99356868 --- /dev/null +++ b/phpgwapi/inc/class.contacts_sql.inc.php @@ -0,0 +1,678 @@ + * + * and Miles Lott * + * View and manipulate contact records using SQL * + * Copyright (C) 2001 Joseph Engo * + * -------------------------------------------------------------------------* + * This library is part of the phpGroupWare API * + * http://www.phpgroupware.org/api * + * ------------------------------------------------------------------------ * + * 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 contacts_ + @abstract Contact Management System + @discussion Author: jengo/Milosch
+ This class provides a contact database scheme.
+ It attempts to be based on the vcard 2.1 standard, with mods as needed to make for more reasonable sql storage.
+ Note that changes here must also work in the LDAP version.
+ Syntax: CreateObject('phpgwapi.contacts');
+ Example1: $contacts = CreateObject('phpgwapi.contacts'); + */ + class contacts_ + { + var $db; + var $std_table='phpgw_addressbook'; + var $ext_table='phpgw_addressbook_extra'; + + var $account_id; + var $stock_contact_fields; /* This is an array of almost the fields in the phpgw_addressbook table, except id,owner,lid,tid,access,cat_id */ + var $non_contact_fields; /* Here are the rest */ + var $email_types; /* VCard email type array */ + var $total_records; /* This will contain numrows for data retrieved */ + var $grants; /* This holds all of the users that have granted access to there entrys */ + + function contacts_($useacl=True) + { + global $phpgw, $phpgw_info; + + $this->db = $phpgw->db; + if($useacl) + { + $this->grants = $phpgw->acl->get_grants('addressbook'); + } + $this->account_id = $phpgw_info['user']['account_id']; + + /* The left side are the array elements used throughout phpgw, right side are the db field names. */ + $this->stock_contact_fields = array( + 'fn' => 'fn', + 'n_given' => 'n_given', + 'n_family' => 'n_family', + 'n_middle' => 'n_middle', + 'n_prefix' => 'n_prefix', + 'n_suffix' => 'n_suffix', + 'sound' => 'sound', + 'bday' => 'bday', + 'note' => 'note', + 'tz' => 'tz', + 'geo' => 'geo', + 'url' => 'url', + 'pubkey' => 'pubkey', + + 'org_name' => 'org_name', + 'org_unit' => 'org_unit', + 'title' => 'title', + + 'adr_one_street' => 'adr_one_street', + 'adr_one_locality' => 'adr_one_locality', + 'adr_one_region' => 'adr_one_region', + 'adr_one_postalcode' => 'adr_one_postalcode', + 'adr_one_countryname' => 'adr_one_countryname', + 'adr_one_type' => 'adr_one_type', + 'label' => 'label', + + 'adr_two_street' => 'adr_two_street', + 'adr_two_locality' => 'adr_two_locality', + 'adr_two_region' => 'adr_two_region', + 'adr_two_postalcode' => 'adr_two_postalcode', + 'adr_two_countryname' => 'adr_two_countryname', + 'adr_two_type' => 'adr_two_type', + + 'tel_work' => 'tel_work', + 'tel_home' => 'tel_home', + 'tel_voice' => 'tel_voice', + 'tel_fax' => 'tel_fax', + 'tel_msg' => 'tel_msg', + 'tel_cell' => 'tel_cell', + 'tel_pager' => 'tel_pager', + 'tel_bbs' => 'tel_bbs', + 'tel_modem' => 'tel_modem', + 'tel_car' => 'tel_car', + 'tel_isdn' => 'tel_isdn', + 'tel_video' => 'tel_video', + 'tel_prefer' => 'tel_prefer', + 'email' => 'email', + 'email_type' => 'email_type', + 'email_home' => 'email_home', + 'email_home_type' => 'email_home_type' + ); + + $this->non_contact_fields = array( + 'id' => 'id', + 'lid' => 'lid', + 'tid' => 'tid', + 'cat_id' => 'cat_id', + 'access' => 'access', + 'owner' => 'owner' + ); + + /* Used to flag an address as being: + domestic AND/OR international(default) + parcel(default) + postal(default) + */ + $this->adr_types = array( + 'dom' => lang('Domestic'), + 'intl' => lang('International'), + 'parcel' => lang('Parcel'), + 'postal' => lang('Postal') + ); + + /* Used to set preferred number field */ + $this->tel_types = array( + 'work' => 'work', + 'home' => 'home', + 'voice' => 'voice', + 'fax' => 'fax', + 'msg' => 'msg', + 'cell' => 'cell', + 'pager' => 'pager', + 'bbs' => 'bbs', + 'modem' => 'modem', + 'car' => 'car', + 'isdn' => 'isdn', + 'video' => 'video' + ); + + /* Used to set email_type fields */ + $this->email_types = array( + 'INTERNET' => 'INTERNET', + 'CompuServe' => 'CompuServe', + 'AOL' => 'AOL', + 'Prodigy' => 'Prodigy', + 'eWorld' => 'eWorld', + 'AppleLink' => 'AppleLink', + 'AppleTalk' => 'AppleTalk', + 'PowerShare' => 'PowerShare', + 'IBMMail' => 'IBMMail', + 'ATTMail' => 'ATTMail', + 'MCIMail' => 'MCIMail', + 'X.400' => 'X.400', + 'TLX' => 'TLX' + ); + } + + /* send this the id and whatever fields you want to see */ + function read_single_entry($id,$fields="") + { + if (!$fields || empty($fields)) { $fields = $this->stock_contact_fields; } + list($stock_fields,$stock_fieldnames,$extra_fields) = + $this->split_stock_and_extras($fields); + + if (count($stock_fieldnames)) + { + $t_fields = "," . implode(",",$stock_fieldnames); + if ($t_fields == ",") + { + unset($t_fields); + } + } + + $this->db2 = $this->db; + + $this->db->query("SELECT id,lid,tid,owner,access,cat_id $t_fields FROM $this->std_table WHERE id='$id'"); + $this->db->next_record(); + + $return_fields[0]['id'] = $this->db->f('id'); + $return_fields[0]['lid'] = $this->db->f('lid'); + $return_fields[0]['tid'] = $this->db->f('tid'); + $return_fields[0]['owner'] = $this->db->f('owner'); + $return_fields[0]['access'] = $this->db->f('access'); + $return_fields[0]['cat_id'] = $this->db->f('cat_id'); + + if (gettype($stock_fieldnames) == 'array') + { + while (list($f_name) = each($stock_fieldnames)) + { + $return_fields[0][$f_name] = $this->db->f($f_name); + } + } + + /* Setup address type fields */ + if ($this->db->f('adr_one_type')) + { + $one_type = $this->db->f('adr_one_type'); + reset($this->adr_types); + while (list($name,$val) = each($this->adr_types)) + { + eval("if (strstr(\$one_type,\$name)) { \$return_fields[0][\"one_\$name\"] = \"on\"; }"); + } + } + if ($this->db->f('adr_two_type')) + { + $two_type = $this->db->f('adr_two_type'); + reset($this->adr_types); + while (list($name,$val) = each($this->adr_types)) + { + eval("if (strstr(\$two_type,\$name)) { \$return_fields[0][\"two_\$name\"] = \"on\"; }"); + } + } + + $this->db2->query("SELECT contact_name,contact_value FROM $this->ext_table where contact_id='" . $this->db->f('id') . "'",__LINE__,__FILE__); + while ($this->db2->next_record()) + { + if ($extra_fields[$this->db2->f('contact_name')]) + { + $return_fields[0][$this->db2->f('contact_name')] = $this->db2->f('contact_value'); + } + } + return $return_fields; + } + + function read_last_entry($fields='') + { + if (!$fields || empty($fields)) { $fields = $this->stock_contact_fields; } + list($stock_fields,$stock_fieldnames,$extra_fields) = + $this->split_stock_and_extras($fields); + + if (count($stock_fieldnames)) + { + $t_fields = "," . implode(",",$stock_fieldnames); + if ($t_fields == ",") + { + unset($t_fields); + } + } + + $this->db2 = $this->db; + + $this->db->query('SELECT max(id) FROM '.$this->std_table,__LINE__,__FILE__); + $this->db->next_record(); + + $id = $this->db->f(0); + + $this->db->query("SELECT id,lid,tid,owner,access,cat_id $t_fields FROM $this->std_table WHERE id='$id'",__LINE__,__FILE__); + $this->db->next_record(); + + $return_fields[0]['id'] = $this->db->f('id'); + $return_fields[0]['lid'] = $this->db->f('lid'); + $return_fields[0]['tid'] = $this->db->f('tid'); + $return_fields[0]['owner'] = $this->db->f('owner'); + $return_fields[0]['access'] = $this->db->f('access'); + $return_fields[0]['cat_id'] = $this->db->f('cat_id'); + + if (gettype($stock_fieldnames) == 'array') + { + while (list($f_name) = each($stock_fieldnames)) + { + $return_fields[0][$f_name] = $this->db->f($f_name); + } + } + + /* Setup address type fields */ + if ($this->db->f('adr_one_type')) + { + $one_type = $this->db->f('adr_one_type'); + reset($this->adr_types); + while (list($name,$val) = each($this->adr_types)) + { + eval("if (strstr(\$one_type,\$name)) { \$return_fields[0][\"one_\$name\"] = \"on\"; }"); + } + } + if ($this->db->f('adr_two_type')) + { + $two_type = $this->db->f('adr_two_type'); + reset($this->adr_types); + while (list($name,$val) = each($this->adr_types)) + { + eval("if (strstr(\$two_type,\$name)) { \$return_fields[0][\"two_\$name\"] = \"on\"; }"); + } + } + + $this->db2->query("SELECT contact_name,contact_value FROM $this->ext_table WHERE contact_id='" . $this->db->f('id') . "'",__LINE__,__FILE__); + while ($this->db2->next_record()) + { + if ($extra_fields[$this->db2->f('contact_name')]) + { + $return_fields[0][$this->db2->f('contact_name')] = $this->db2->f('contact_value'); + } + } + return $return_fields; + } + + /* send this the range, query, sort, order and whatever fields you want to see */ + function read($start=0,$limit=0,$fields="",$query="",$filter="",$sort="",$order="") + { + global $phpgw,$phpgw_info; + + if (!$fields || empty($fields)) { $fields = $this->stock_contact_fields; } + $DEBUG = 0; + + list($stock_fields,$stock_fieldnames,$extra_fields) = $this->split_stock_and_extras($fields); + if (count($stock_fieldnames)) + { + $t_fields = ',' . implode(',',$stock_fieldnames); + if ($t_fields == ',') + { + unset($t_fields); + } + } + + /* turn filter's a=b,c=d OR a=b into an array */ + if ($filter) + { + $check_stock = $this->stock_contact_fields + $this->non_contact_fields; + + if ($DEBUG) { echo "DEBUG - Inbound filter is: #".$filter."#"; } + $filterarray = split(',',$filter); + if ($filterarray[1]) + { + $i=0; + for ($i=0;$iDEBUG - Filter intermediate strings 1: #".$name."# => #".$value."#"; } + $filterfields[$name] = $value; + } + } + } + else + { + list($name,$value) = split('=',$filter); + if ($DEBUG) + { + echo '
DEBUG - Filter intermediate strings 1: #'.$name.'# => #'.$value.'#'; + } + $filterfields = array($name => $value); + } + + /* now check each element of the array and convert into SQL for queries below */ + $i=0; + reset($filterfields); + while (list($name,$value) = each($filterfields)) + { + if ($DEBUG) { echo '
DEBUG - Filter intermediate strings 2: #'.$name.'# => #'.$value.'#'; } + $isstd=0; + if ($name && empty($value)) + { + if ($DEBUG) { echo '
DEBUG - filter field "'.$name.'" is empty (NULL)'; } + while (list($fname,$fvalue)=each($check_stock)) + { + if ($fvalue==$name) + { + $filterlist .= $name.' is NULL,'; + if ($DEBUG) { echo '
DEBUG - filter field "'.$name.'" is a stock field'; } + break; + } + } + } + elseif($name && $value) + { + reset($check_stock); + while (list($fname,$fvalue)=each($check_stock)) + { + if ($fvalue==$name) + { + if ($name == 'cat_id') + { + $filterlist .= "(" . $name . " LIKE '%," . $value . ",%' OR " . $name."='".$value."');"; + } + elseif (gettype($value) == "integer") + { + $filterlist .= $name."=".$value.";"; + } + else + { + $filterlist .= $name."='".$value."';"; + } + break; + } + } + } + $i++; + } + $filterlist = substr($filterlist,0,-1); + $filterlist = ereg_replace(";"," AND ",$filterlist); + + if ($DEBUG) + { + echo "
DEBUG - Filter output string: #".$filterlist."#"; + } + + if ($filterlist) + { + $filtermethod = '('.$filterlist.') '; + $fwhere = ' WHERE '; $fand = ' AND '; + } + } + else + { + $filtermethod = " AND (tid='n' OR tid is null)"; + } + + if (!$filtermethod) + { + if($phpgw_info['user']['account_id']) + { + $fwhere .= " (owner=" . $phpgw_info['user']['account_id']; + $fand .= " (owner=" . $phpgw_info['user']['account_id']; + } + } + else + { + if($phpgw_info['user']['account_id']) + { + $fwhere .= $filtermethod . " AND (owner=" . $phpgw_info['user']['account_id']; + $fand .= $filtermethod . " AND (owner=" . $phpgw_info['user']['account_id']; + } + else + { + $filtermethod = substr($filtermethod,0,-2); + $fwhere .= $filtermethod; + $fand .= $filtermethod; + } + } + + if (is_array($this->grants)) + { + $grants = $this->grants; + while (list($user) = each($grants)) + { + $public_user_list[] = $user; + } + reset($public_user_list); + $fwhere .= " OR (access='public' AND owner in(" . implode(',',$public_user_list) . "))) "; + $fand .= " OR (access='public' AND owner in(" . implode(',',$public_user_list) . "))) "; + } + else + { + $fwhere .= ') '; $fand .= ') '; + } + + if ($DEBUG && $filtermethod) + { + echo "
DEBUG - Filtering with: #" . $filtermethod . "#"; + } + + if (!$sort) { $sort = "ASC"; } + + if ($order) + { + $ordermethod = "order by $order $sort "; + } + else + { + $ordermethod = "order by n_family,n_given,email $sort"; + } + + if ($DEBUG && $ordermethod) + { + echo "
DEBUG - $ordermethod"; + } + + $filtermethod = ""; + + if ($query) + { + $sql = "SELECT * FROM $this->std_table WHERE (bday LIKE '%$query%' OR n_family LIKE '" + . "%$query%' OR n_given LIKE '%$query%' OR email LIKE '%$query%' OR " + . "adr_one_street LIKE '%$query%' OR adr_one_locality LIKE '%$query%' OR adr_one_region LIKE '%$query%' OR " + . "adr_one_postalcode LIKE '%$query%' OR adr_one_countryname LIKE '%$query%' OR " + . "adr_two_street LIKE '%$query%' OR adr_two_locality LIKE '%$query%' OR adr_two_region LIKE '%$query%' OR " + . "adr_two_postalcode LIKE '%$query%' OR adr_two_countryname LIKE '%$query%' OR " + . "org_name LIKE '%$query%' OR org_unit LIKE '%$query%') " . $fand . $filtermethod . $ordermethod; + } + else + { + $sql = "SELECT id,lid,tid,owner,access,cat_id $t_fields FROM $this->std_table " . $fwhere + . $filtermethod . " " . $ordermethod; + } + + if ($DEBUG) { echo "
$sql"; } + + $this->db2 = $this->db; + $this->db2->query($sql,__LINE__,__FILE__); + + $this->total_records = $this->db2->num_rows(); + + if ($start && $limit) + { + $this->db->limit_query($sql,array($start,$limit),__LINE__,__FILE__); + } + elseif (!$limit) + { + $this->db->query($sql,__LINE__,__FILE__); + } + else + { + $this->db->limit_query($sql,$start,__LINE__,__FILE__); + } + + $i=0; + while ($this->db->next_record()) + { + $return_fields[$i]['id'] = $this->db->f('id'); + $return_fields[$i]['lid'] = $this->db->f('lid'); + $return_fields[$i]['tid'] = $this->db->f('tid'); + $return_fields[$i]['owner'] = $this->db->f('owner'); + $return_fields[$i]['access'] = $this->db->f('access'); + $return_fields[$i]['cat_id'] = $this->db->f('cat_id'); + + if (gettype($stock_fieldnames) == 'array') + { + while (list($f_name) = each($stock_fieldnames)) + { + $return_fields[$i][$f_name] = $this->db->f($f_name); + } + reset($stock_fieldnames); + } + $this->db2->query("SELECT contact_name,contact_value FROM $this->ext_table WHERE contact_id='" + . $this->db->f('id') . "'" .$filterextra,__LINE__,__FILE__); + while ($this->db2->next_record()) + { + if ($extra_fields[$this->db2->f('contact_name')]) + { + $return_fields[$i][$this->db2->f('contact_name')] = $this->db2->f('contact_value'); + } + } + $i++; + } + return $return_fields; + } + + function add($owner,$fields,$access='',$cat_id='',$tid='n') + { + list($stock_fields,$stock_fieldnames,$extra_fields) = $this->split_stock_and_extras($fields); + + if ($fields['lid']) + { + $lid[0] = 'lid,'; + $lid[1] = $fields['lid']."','"; + } + $this->db->query("INSERT INTO $this->std_table (owner,access,cat_id,tid,".$lid[0] + . implode(",",$this->stock_contact_fields) + . ") VALUES ('$owner','$access','$cat_id','$tid','".$lid[1] + . implode("','",$this->loop_addslashes($stock_fields)) . "')",__LINE__,__FILE__); + + $this->db->query("SELECT max(id) FROM $this->std_table ",__LINE__,__FILE__); + $this->db->next_record(); + $id = $this->db->f(0); + + if (count($extra_fields)) + { + while (list($name,$value) = each($extra_fields)) + { + $this->db->query("INSERT INTO $this->ext_table VALUES ('$id','" . $this->account_id . "','" + . addslashes($name) . "','" . addslashes($value) . "')",__LINE__,__FILE__); + } + } + } + + function field_exists($id,$field_name) + { + $this->db->query("SELECT COUNT(*) FROM $this->ext_table WHERE contact_id='$id' AND contact_name='" + . addslashes($field_name) . "'",__LINE__,__FILE__); + $this->db->next_record(); + return $this->db->f(0); + } + + function add_single_extra_field($id,$owner,$field_name,$field_value) + { + $this->db->query("INSERT INTO $this->ext_table VALUES ($id,'$owner','" . addslashes($field_name) + . "','" . addslashes($field_value) . "')",__LINE__,__FILE__); + } + + function delete_single_extra_field($id,$field_name) + { + $this->db->query("DELETE FROM $this->ext_table WHERE contact_id='$id' AND contact_name='" + . addslashes($field_name) . "'",__LINE__,__FILE__); + } + + function update($id,$owner,$fields,$access='',$cat_id='',$tid='n') + { + /* First make sure that id number exists */ + $this->db->query("SELECT COUNT(*) FROM $this->std_table WHERE id='$id'",__LINE__,__FILE__); + $this->db->next_record(); + if (!$this->db->f(0)) + { + return False; + } + + list($stock_fields,$stock_fieldnames,$extra_fields) = $this->split_stock_and_extras($fields); + if (count($stock_fields)) + { + while (list($stock_fieldname) = each($stock_fieldnames)) + { + $ta[] = $stock_fieldname . "='" . addslashes($stock_fields[$stock_fieldname]) . "'"; + } + $fields_s = "," . implode(",",$ta); + if ($field_s == ",") + { + unset($field_s); + } + $this->db->query("UPDATE $this->std_table SET access='$access',cat_id='$cat_id', tid='$tid' $fields_s WHERE " + . "id='$id'",__LINE__,__FILE__); + } + + while (list($x_name,$x_value) = @each($extra_fields)) + { + if ($this->field_exists($id,$x_name)) + { + if (!$x_value) + { + $this->delete_single_extra_field($id,$x_name); + } + else + { + $this->db->query("UPDATE $this->ext_table SET contact_value='" . addslashes($x_value) + . "',contact_owner='$owner' WHERE contact_name='" . addslashes($x_name) + . "' AND contact_id='$id'",__LINE__,__FILE__); + } + } + else + { + $this->add_single_extra_field($id,$owner,$x_name,$x_value); + } + } + } + + /* Used by admin to change ownership on account delete */ + function change_owner($old_owner='',$new_owner='') + { + if (!($new_owner && $old_owner)) + { + return False; + } + + $this->db->query("UPDATE $this->std_table SET owner='$new_owner' WHERE owner=$old_owner",__LINE__,__FILE__); + $this->db->query("UPDATE $this->ext_table SET contact_owner='$new_owner' WHERE contact_owner=$old_owner",__LINE__,__FILE__); + + return; + } + + /* This is where the real work of delete() is done, shared class file contains calling function */ + function delete_($id) + { + $this->db->query("DELETE FROM $this->std_table WHERE id='$id'",__LINE__,__FILE__); + $this->db->query("DELETE FROM $this->ext_table WHERE contact_id='$id'",__LINE__,__FILE__); + } + + /* This is for the admin script deleteaccount.php */ + function delete_all($owner=0) + { + if ($owner) + { + $this->db->query("DELETE FROM $this->std_table WHERE owner=$owner",__LINE__,__FILE__); + $this->db->query("DELETE FROM $this->ext_table WHERE contact_owner=$owner",__LINE__,__FILE__); + } + return; + } + } +?> diff --git a/phpgwapi/inc/class.vcard.inc.php b/phpgwapi/inc/class.vcard.inc.php index f48964d447..65c7199691 100644 --- a/phpgwapi/inc/class.vcard.inc.php +++ b/phpgwapi/inc/class.vcard.inc.php @@ -1,7 +1,818 @@ * + * Parse vcards->contacts class fields, and vice-versa * + * Copyright (C) 2001 Miles Lott * + * -------------------------------------------------------------------------* + * This library is part of the phpGroupWare API * + * http://www.phpgroupware.org/api * + * ------------------------------------------------------------------------ * + * 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 vcard { - $phpgw_info['server']['contacts_application'] = 'addressbook'; - } - include(PHPGW_INCLUDE_ROOT.'/'.$phpgw_info['server']['contacts_application'].'/inc/class.vcard.inc.php'); + var $import = array( + 'n' => 'n', + 'sound' => 'sound', + 'bday' => 'bday', + 'note' => 'note', + 'tz' => 'tz', + 'geo' => 'geo', + 'url' => 'url', + 'pubkey' => 'pubkey', + 'org' => 'org', + 'title' => 'title', + 'adr' => 'adr', + 'label' => 'label', + 'tel' => 'tel', + 'email' => 'email' + ); + + var $export = array( + 'fn' => 'FN', + 'n_given' => 'N;GIVEN', + 'n_family' => 'N;FAMILY', + 'n_middle' => 'N;MIDDLE', + 'n_prefix' => 'N;PREFIX', + 'n_suffix' => 'N;SUFFIX', + 'sound' => 'SOUND', + 'bday' => 'BDAY', + 'note' => 'NOTE', + 'tz' => 'TZ', + 'geo' => 'GEO', + 'url' => 'URL', + 'pubkey' => 'PUBKEY', + 'org_name' => 'ORG;NAME', + 'org_unit' => 'ORG;UNIT', + 'title' => 'TITLE', + + 'adr_one_type' => 'ADR;TYPE;WORK', + 'adr_two_type' => 'ADR;TYPE;HOME', + 'tel_prefer' => 'TEL;PREFER', + 'email_type' => 'EMAIL;TYPE;WORK', + 'email_home_type' => 'EMAIL;TYPE;HOME', + + 'adr_one_street' => 'ADR;WORK;STREET', + 'adr_one_locality' => 'ADR;WORK;LOCALITY', + 'adr_one_region' => 'ADR;WORK;REGION', + 'adr_one_postalcode' => 'ADR;WORK;POSTALCODE', + 'adr_one_countryname' => 'ADR;WORK;COUNTRYNAME', + 'address2' => 'EXT', + 'label' => 'LABEL', + + 'adr_two_street' => 'ADR;HOME;STREET', + 'adr_two_locality' => 'ADR;HOME;LOCALITY', + 'adr_two_region' => 'ADR;HOME;REGION', + 'adr_two_postalcode' => 'ADR;HOME;POSTALCODE', + 'adr_two_countryname' => 'ADR;HOME;COUNTRYNAME', + + 'tel_work' => 'TEL;WORK', + 'tel_home' => 'TEL;HOME', + 'tel_voice' => 'TEL;VOICE', + 'tel_fax' => 'TEL;FAX', + 'tel_msg' => 'TEL;MSG', + 'tel_cell' => 'TEL;CELL', + 'tel_pager' => 'TEL;PAGER', + 'tel_bbs' => 'TEL;BBS', + 'tel_modem' => 'TEL;MODEM', + 'tel_car' => 'TEL;CAR', + 'tel_isdn' => 'TEL;ISDN', + 'tel_video' => 'TEL;VIDEO', + 'email' => 'EMAIL;WORK', + 'email_home' => 'EMAIL;HOME' + ); + + var $names = array( + 'family' => 'family', + 'given' => 'given', + 'middle' => 'middle', + 'prefix' => 'prefix', + 'suffix' => 'suffix' + ); + + function vcard() + { + /* _debug_array($this); */ + } + + /* + This now takes the upload filename + and parses using the class string and array processors. + The return is a contacts class entry, ready for add. + */ + function in_file($filename='') + { + if (!$filename) + { + return array(); + } + + $buffer = array(); + + $fp = fopen($filename,'r'); + while ($data = fgets($fp,8000)) + { + list($name,$value,$extra) = split(':', $data); + if (substr($value,0,5) == 'http') + { + $value = $value . ':'.$extra; + } + if ($name && $value) + { + reset($this->import); + while ( list($fname,$fvalue) = each($this->import) ) + { + if ( strstr(strtolower($name), $this->import[$fname]) ) + { + $value = trim($value); + $value = ereg_replace("=0D=0A","\n",$value); + $buffer += array($name => $value); + } + } + } + } + fclose($fp); + + $entry = $this->in($buffer); + /* _debug_array($entry);exit; */ + + return $entry; + } + + /* + This is here to match the old in() function, now called _parse_in(). + It is called now also by in_file() above. + It takes a pre-parsed file using the methods in in_file(), returns a clean contacts class array. + */ + function in($buffer) + { + $buffer = $this->_parse_in($buffer); + + $contacts = CreateObject('phpgwapi.contacts'); /* RB 2001/05/08 Lotus Organizer uses/needs extrafields from edit.php */ + $all_fields = $contacts->stock_contact_fields + array("ophone" => "ophone","address2" => "address2","address3" => "address3"); + + while (list($fname,$fvalue) = each($all_fields)) + { + if($buffer[$fname]) + { + $entry[$fname] = $buffer[$fname]; + /* echo '
'.$fname.' = "'.$entry[$fname].'"'."\n"; */ + } + } + return $entry; + } + + /* + Pass this an associative array of fieldnames and values + returns a clean array based on contacts class std fields + This array can then be passed via $phpgw->contacts->add($ownerid,$buffer) + */ + function _parse_in($buffer) + { + /* Following is a lot of pain and little magic */ + while ( list($name,$value) = @each($buffer) ) + { + $field = split(";",$name); + $field[0] = ereg_replace("A\.","",$field[0]); + $field[0] = ereg_replace("B\.","",$field[0]); + $field[0] = ereg_replace("C\.","",$field[0]); + $field[0] = ereg_replace("D\.","",$field[0]); + $values = split(";",$value); + if ($field[1]) + { + //echo $field[0]; + switch ($field[0]) + { + case 'LABEL': + $entry['label'] = ereg_replace("=0D=0A","\n",$values[0]); + break; + case 'NOTE': + $entry['note'] = ereg_replace("=0D=0A","\n",$values[0]); + break; + case 'ADR': + switch ($field[1]) + { + case 'INTL': + switch ($field[2]) + { + case 'WORK': + if ( !stristr($buffer['adr_one_type'],$field[1])) + { + $entry['adr_one_type'] .= 'intl;'; + } + if (!$buffer['adr_one_street']) + { + $entry['address2'] = $values[1]; + $entry['adr_one_street'] = $values[2]; + $entry['adr_one_locality'] = $values[3]; + $entry['adr_one_region'] = $values[4]; + $entry['adr_one_postalcode'] = $values[5]; + $entry['adr_one_countryname'] = $values[6]; + } + break; + case 'HOME': + if ( !stristr($buffer['adr_two_type'],$field[1]) ) + { + $entry['adr_two_type'] .= 'intl;'; + } + if (!$buffer['adr_two_street']) + { + $entry['adr_two_street'] = $values[2]; + $entry['adr_two_locality'] = $values[3]; + $entry['adr_two_region'] = $values[4]; + $entry['adr_two_postalcode'] = $values[5]; + $entry['adr_two_countryname'] = $values[6]; + } + break; + default: + break; + } + break; + case 'DOM': + switch ($field[2]) + { + case 'WORK': + if ( !stristr($buffer['adr_one_type'],$field[1])) + { + $entry['adr_one_type'] .= 'dom;'; + } + if (!$buffer['adr_one_street']) + { + $entry['address2'] = $values[1]; + $entry['adr_one_street'] = $values[2]; + $entry['adr_one_locality'] = $values[3]; + $entry['adr_one_region'] = $values[4]; + $entry['adr_one_postalcode'] = $values[5]; + $entry['adr_one_countryname'] = $values[6]; + } + break; + case 'HOME': + if ( !stristr($buffer['adr_two_type'],$field[1]) ) + { + $entry['adr_two_type'] .= 'dom;'; + } + if (!$buffer['adr_two_street']) + { + $entry['adr_two_street'] = $values[2]; + $entry['adr_two_locality'] = $values[3]; + $entry['adr_two_region'] = $values[4]; + $entry['adr_two_postalcode'] = $values[5]; + $entry['adr_two_countryname'] = $values[6]; + } + break; + default: + break; + } + break; + case 'PARCEL': + switch ($field[2]) + { + case 'WORK': + if ( !stristr($buffer['adr_one_type'],$field[1])) + { + $entry['adr_one_type'] .= 'parcel;'; + } + if (!$buffer['adr_one_street']) + { + $entry['address2'] = $values[1]; + $entry['adr_one_street'] = $values[2]; + $entry['adr_one_locality'] = $values[3]; + $entry['adr_one_region'] = $values[4]; + $entry['adr_one_postalcode'] = $values[5]; + $entry['adr_one_countryname'] = $values[6]; + } + break; + case 'HOME': + if ( !stristr($buffer['adr_two_type'],$field[1]) ) + { + $entry['adr_two_type'] .= 'parcel;'; + } + if (!$buffer['adr_two_street']) + { + $entry['adr_two_street'] = $values[2]; + $entry['adr_two_locality'] = $values[3]; + $entry['adr_two_region'] = $values[4]; + $entry['adr_two_postalcode'] = $values[5]; + $entry['adr_two_countryname'] = $values[6]; + } + break; + default: + break; + } + break; + case 'POSTAL': + switch ($field[2]) + { + case 'WORK': + if ( !stristr($buffer['adr_one_type'],$field[1])) + { + $entry['adr_one_type'] .= 'postal;'; + } + if (!$buffer['adr_one_street']) + { + $entry['address2'] = $values[1]; + $entry['adr_one_street'] = $values[2]; + $entry['adr_one_locality'] = $values[3]; + $entry['adr_one_region'] = $values[4]; + $entry['adr_one_postalcode'] = $values[5]; + $entry['adr_one_countryname'] = $values[6]; + } + break; + case 'HOME': + if ( !stristr($buffer['adr_two_type'],$field[1]) ) + { + $entry['adr_two_type'] .= 'postal;'; + } + if (!$buffer['adr_two_street']) + { + $entry['adr_two_street'] = $values[2]; + $entry['adr_two_locality'] = $values[3]; + $entry['adr_two_region'] = $values[4]; + $entry['adr_two_postalcode'] = $values[5]; + $entry['adr_two_countryname'] = $values[6]; + } + break; + default: + break; + } + break; + case 'WORK': + if (!$buffer['adr_one_street']) + { + $entry['address2'] = $values[1]; + $entry['adr_one_street'] = $values[2]; + $entry['adr_one_locality'] = $values[3]; + $entry['adr_one_region'] = $values[4]; + $entry['adr_one_postalcode'] = $values[5]; + $entry['adr_one_countryname'] = $values[6]; + } + break; + case 'HOME': + $entry['adr_two_street'] = $values[2]; + $entry['adr_two_locality'] = $values[3]; + $entry['adr_two_region'] = $values[4]; + $entry['adr_two_postalcode'] = $values[5]; + $entry['adr_two_countryname'] = $values[6]; + break; + default: + if (!$buffer['adr_one_street']) + { + $entry['address2'] = $values[1]; + $entry['adr_one_street'] = $values[2]; + $entry['adr_one_locality'] = $values[3]; + $entry['adr_one_region'] = $values[4]; + $entry['adr_one_postalcode'] = $values[5]; + $entry['adr_one_countryname'] = $values[6]; + } + break; + } + break; + case 'TEL': // RB 2001/05/07 added for Lotus Organizer ueses TEL;{WORK|HOME};{VOICE|FAX}[;PREF] + if ($field[2] == 'FAX' && ($field[1] == 'WORK' || $field[i] == 'HOME')) + { + /* TODO This is PHP4 only */ + array_shift($field); // --> ignore the WORK or HOME if FAX follows, HOME;FAX and HOME;TEL are maped later + } + switch ($field[1]) + { + case 'PREF': + //echo $field[2]." is preferred"; + if ($field[2]) + { + $buffer['tel_prefer'] .= strtolower($field[2]) . ';'; + } + break; + case 'WORK': // RB don't overwrite TEL;WORK;VOICE (main nr.) with TEL;WORK, TEL;WORK --> tel_isdn + $entry[$buffer['tel_work'] ? 'tel_isdn' : 'tel_work'] = $values[0]; + if ($field[2] == 'PREF') + { + $entry['tel_prefer'] .= strtolower($field[1]) . ';'; + } + break; + case 'HOME': // RB don't overwrite TEL;HOME;VOICE (main nr.) with TEL;HOME, TEL;HOME --> ophone + $entry[$buffer['tel_home'] ? 'ophone' : 'tel_home' ] = $values[0]; + if ($field[2] == 'PREF') + { + $entry['tel_prefer'] .= strtolower($field[1]) . ';'; + } + break; + case 'VOICE': + $entry["tel_voice"] = $values[0]; + if ($field[2] == "PREF") + { + $entry['tel_prefer'] .= strtolower($field[1]) . ';'; + } + break; + case 'FAX': + if ($entry['tel_fax']) + { + // RB don't overwrite TEL;WORK;FAX with TEL;HOME;FAX, TEL;HOME;FAX --> ophone + $entry['ophone'] = $values[0] . ' Fax'; + break; + } + $entry['tel_fax'] = $values[0]; + if ($field[2] == 'PREF') + { + $entry['tel_prefer'] .= strtolower($field[1]) . ';'; + } + break; + case 'MSG': + $entry['tel_msg'] = $values[0]; + if ($field[2] == 'PREF') + { + $entry['tel_prefer'] .= strtolower($field[1]) . ';'; + } + break; + case 'CELL': + $entry['tel_cell'] = $values[0]; + if ($field[2] == 'PREF') + { + $entry['tel_prefer'] .= strtolower($field[1]) . ';'; + } + break; + case 'PAGER': + $entry['tel_pager'] = $values[0]; + if ($field[2] == 'PREF') + { + $entry['tel_prefer'] .= strtolower($field[1]) . ';'; + } + break; + case 'BBS': + $entry['tel_bbs'] = $values[0]; + if ($field[2] == 'PREF') + { + $entry['tel_prefer'] .= strtolower($field[1]) . ';'; + } + break; + case 'MODEM': + $entry['tel_modem'] = $values[0]; + if ($field[2] == 'PREF') + { + $entry['tel_prefer'] .= strtolower($field[1]) . ';'; + } + break; + case 'CAR': + $entry['tel_car'] = $values[0]; + if ($field[2] == 'PREF') + { + $entry['tel_prefer'] .= strtolower($field[1]) . ';'; + } + break; + case 'ISDN': + $entry['tel_isdn'] = $values[0]; + if ($field[2] == 'PREF') + { + $entry['tel_prefer'] .= strtolower($field[1]) . ';'; + } + break; + case 'VIDEO': + $entry['tel_video'] = $values[0]; + if ($field[2] == 'PREF') + { + $entry['tel_prefer'] .= strtolower($field[1]) . ';'; + } + break; + default: + break; + } + break; + case 'EMAIL': + switch ($field[1]) + { + case 'WORK': + $entry['email'] = $values[0]; + $entry['email_type'] = $field[2]; + break; + case 'HOME': + $entry['email_home'] = $values[0]; + $entry['email_home_type'] = $field[2]; + break; + default: + if($buffer['email']) + { + $entry['email_type'] = $field[2]; + } + elseif (!$buffer['email']) + { + $entry['email'] = $values[0]; + $entry['email_type'] = $field[1]; + } + break; + } + break; + case 'URL': // RB 2001/05/08 Lotus Organizer uses URL;WORK and URL;HOME (URL;HOME droped if both) + $entry['url'] = $values[0]; + break; + default: + break; + } + } + else + { + switch ($field[0]) + { + case 'N': + reset($this->names); + $j=0; + while(list($myname,$myval) = each($this->names) ) + { + $namel = 'n_' . $myname; + $entry[$namel] = $values[$j]; + $j++; + } + break; + case 'FN': + $entry['fn'] = $values[0]; + break; + case 'TITLE': + $entry['title'] = $values[0]; + break; + case 'TZ': + $entry['tz'] = $values[0]; + break; + case 'GEO': + $entry['geo'] = $values[0]; + break; + case 'URL': + $entry['url'] = $values[0]; + break; + case 'NOTE': + $entry['note'] = ereg_replace("=0D=0A","\n",$values[0]); + break; + case 'KEY': + $entry['key'] = ereg_replace("=0D=0A","\n",$values[0]); + break; + case 'LABEL': + $entry['label'] = ereg_replace("=0D=0A","\n",$values[0]); + break; + case 'BDAY': #1969-12-31 + $tmp = split('-',$values[0]); + if ($tmp[0]) + { + $entry['bday'] = $tmp[1] . '/' . $tmp[2] . '/' . $tmp[0]; + } + break; + case 'ORG': // RB 2001/05/07 added for Lotus Organizer: ORG:Company;Department + $entry['org_name'] = $values[0]; + $entry['org_unit'] = $values[1]; + break; + } + } + } + $entry['tel_prefer'] = substr($buffer['tel_prefer'],0,-1); + $entry['adr_one_type'] = substr($buffer['adr_one_type'],0,-1); + $entry['adr_two_type'] = substr($buffer['adr_two_type'],0,-1); + + if (count($street = split("\r*\n",$buffer['adr_one_street'],3)) > 1) + { + $entry['adr_one_street'] = $street[0]; // RB 2001/05/08 added for Lotus Organizer to split multiline adresses + $entry['address2'] = $street[1]; + $entry['address3'] = $street[2]; + } + + return $entry; + } + + // Takes an array of contacts class fields/values, turns it into a vcard string: + // + // for ($i=0;$ivcard->out($buffer[$i]); + // } + // + function out($buffer) + { + $entry = ''; + $header = 'BEGIN:VCARD' . "\n"; + $header .= 'VERSION:2.1' . "\n"; + $header .= 'X-PHPGROUPWARE-FILE-AS:phpGroupWare.org' . "\n"; + + reset($this->export); + while ( list($name,$value) = each($this->export) ) + { + if (!empty($buffer[$value])) + { + $mult = explode(';',$value); + if (!$mult[1]) + { // Normal + if (strstr($buffer[$value],"\r\n") || strstr($buffer[$value],"\n")) + { + $buffer[$value] = ereg_replace("\r\n","=0D=0A",$buffer[$value]); + $buffer[$value] = ereg_replace("\n","=0D=0A",$buffer[$value]); + $entry .= $value . ';QUOTED-PRINTABLE:' . $buffer[$value]."\n"; + } + elseif ($value == 'BDAY') + { + $tmp = split('/',$buffer[$value]); # 12/31/1969 -> 1969-12-31 + if ($tmp[0]) + { + if (strlen($tmp[0]) == 1) { $tmp[0] = '0'.$tmp[0]; } + if (strlen($tmp[0]) == 1) { $tmp[1] = '0'.$tmp[1]; } + $entry .= 'BDAY:' . $tmp[2] . '-' . $tmp[0] . '-' . $tmp[1] . "\n"; + } + } + else + { + $entry .= $value . ':' . $buffer[$value] . "\n"; + } + } + else + { + switch ($mult[0]) + { + case 'N': + switch ($mult[1]) + { + case 'PREFIX': + $prefix = ';' . $buffer[$value]; + break; + case 'GIVEN': + $firstname = ';' . $buffer[$value]; + break; + case 'MIDDLE': + $middle = ';' . $buffer[$value]; + break; + case 'FAMILY': + $lastname = $buffer[$value]; + break; + case 'SUFFIX': + $suffix = ';' . $buffer[$value]; + break; + } + break; + case 'ORG': + switch ($mult[1]) + { + case 'NAME': + $org_name = $buffer[$value]; + break; + case 'UNIT': + $org_unit = ';' . $buffer[$value]; + break; + } + break; + case 'ADR': + switch ($mult[1]) + { + case 'TYPE': + $types = explode(';',$buffer[$value]); + if ($types[1]) + { + while ( $type = each($types) ) + { + $typei[$i][$mult[2]] .= ';' . strtoupper($type[1]); + } + } + elseif ($types[0]) + { + $typei[$i][$mult[2]] .= ';' . strtoupper($types[0]); + } + else + { + $typei[$i][$mult[2]] .= ';' . strtoupper($buffer[$value]); + } + //echo "TYPE=".$typei[$i][$mult[2]]; + break; + case 'WORK': + $workaddr .= $buffer[$value] . ';'; + $workattr = $mult[0] . ';' . $mult[1] . $typei[$i][$mult[1]]; + break; + case 'HOME': + $homeaddr .= $buffer[$value] . ';'; + $homeattr = $mult[0] . ';' . $mult[1] . $typei[$i][$mult[1]]; + break; + default: + break; + } + break; + case 'TEL': + switch($mult[1]) + { + case 'PREFER': + $prefer = explode(";",$buffer[$value]); + if ($prefer[1]) + { + while ($pref = strtoupper(each($prefer))) + { + $prefi[$i][$pref] = ';PREF'; + } + //echo "PREF1"; + } + elseif ($prefer[0]) + { + $prefi[$i][strtoupper($prefer[0])] = ';PREF'; + //echo "PREF=".strtoupper($prefer[0]); + } + elseif ($buffer[$value]) + { + $prefi[$i][$buffer[$value]] = ';PREF'; + //echo "PREF3"; + } + break; + case 'WORK': + // Wow, this is fun! + $entry .= 'A.' . $mult[0] . ';' . $mult[1] . $prefi[$i][$mult[1]] . ':' . $buffer[$value] . "\n"; + break; + case 'HOME': + $entry .= 'B.' . $mult[0] . ';' . $mult[1] . $prefi[$i][$mult[1]] . ':' . $buffer[$value] . "\n"; + break; + default: + $entry .= $mult[0] . ';' . $mult[1] . $prefi[$i][$mult[1]] . ':' . $buffer[$value] . "\n"; + break; + } + break; + case 'EMAIL': + switch($mult[1]) + { + case 'TYPE': + if ($mult[2] == 'WORK') { $emailtype = ';' . $buffer[$value]; } + if ($mult[2] == 'HOME') { $hemailtype = ';' . $buffer[$value]; } + break; + case 'WORK': + $newval = 'A.'.$value; + $entry .= $newval . $emailtype . ':' . $buffer[$value] . "\n"; + break; + case 'HOME': + $newval = 'B.' . $value; + $entry .= $newval . $hemailtype . ':' . $buffer[$value] . "\n"; + break; + default: + break; + } + break; + default: + break; + } //end switch ($mult[0]) + } //end else + } //end if (!empty) + } //end while + + if ($lastname && $firstname) + { + $entries .= $header; + $entries .= 'N:' . $lastname . $firstname . $middle . $prefix . $suffix . "\n"; + $entries .= $entry; + + if (!$buffer["FN"]) + { + if ($lastname || $firstname ) + { + $entries .= 'FN:' . substr($firstname,1) . ' ' . $lastname . "\n"; + } + } + if ($org_name || $org_unit) + { + $entries .= "ORG:" . $org_name . $org_unit . "\n"; + } + + $workattr = ereg_replace("ADR;",'',$workattr); + $homeattr = ereg_replace("ADR;",'',$homeattr); + if (!$buffer['EXT']) { $buffer['EXT'] = ';'; } + if ($workaddr) + { + $work = 'A.ADR;' . $workattr . ':;' . $buffer['EXT'] . substr($workaddr,0,-1) . "\n"; + if (!$buffer['LABEL']) + { + $wlabel = substr($workaddr,0,-1); + $wlabel = ereg_replace(";","=0D=0A",$wlabel); + //$wlabel = ereg_replace("(",",",$wlabel); + //$wlabel = ereg_replace(")",",",$wlabel); + $wlabel = 'LABEL;WORK;QUOTED-PRINTABLE:' . $wlabel . "\n"; + } + } + if ($homeaddr) + { + $home = "B.ADR;".$homeattr.":;;".substr($homeaddr,0,-1)."\n"; + $hlabel = substr($homeaddr,0,-1); + $hlabel = ereg_replace(";","=0D=0A",$hlabel); + //$hlabel = ereg_replace("(",",",$hlabel); + //$hlabel = ereg_replace(")",",",$hlabel); + $hlabel = 'LABEL;HOME;QUOTED-PRINTABLE:' . $hlabel . "\n"; + } + $entries = ereg_replace('PUBKEY','KEY',$entries); + $entries .= $work . $home . $wlabel . $hlabel . 'END:VCARD' . "\n"; + $entries .= "\n"; + + $buffer = $entries; + return $buffer; + } + else + { + return; + } + } //end function + } //end class ?>