diff --git a/addressbook/inc/class.sifaddressbook.inc.php b/addressbook/inc/class.sifaddressbook.inc.php index ef9b9305b3..810aeadd2d 100644 --- a/addressbook/inc/class.sifaddressbook.inc.php +++ b/addressbook/inc/class.sifaddressbook.inc.php @@ -1,276 +1,282 @@ * - * -------------------------------------------- * - * This program is free software; you can redistribute it and/or modify it * - * under the terms of the GNU General Public License as published by the * - * Free Software Foundation; either version 2 of the License. * - \**************************************************************************/ +/** + * Addressbook - SIF parser + * + * @link http://www.egroupware.org + * @author Lars Kneschke + * @author Ralf Becker + * @package addressbook + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @version $Id$ + */ - /* $Id$ */ +require_once EGW_SERVER_ROOT.'/addressbook/inc/class.bocontacts.inc.php'; - require_once EGW_SERVER_ROOT.'/addressbook/inc/class.boaddressbook.inc.php'; - #require_once EGW_SERVER_ROOT.'/phpgwapi/inc/horde/Horde/iCalendar.php'; +class sifaddressbook extends bocontacts +{ + var $sifMapping = array( + 'Anniversary' => '', + 'AssistantName' => 'assistent', + 'AssistantTelephoneNumber' => 'tel_assistent', + 'BillingInformation' => '', + 'Birthday' => 'bday', + 'Body' => 'note', + 'Business2TelephoneNumber' => '', + 'BusinessAddressCity' => 'adr_one_locality', + 'BusinessAddressCountry' => 'adr_one_countryname', + 'BusinessAddressPostalCode' => 'adr_one_postalcode', + 'BusinessAddressPostOfficeBox' => 'adr_one_street2', + 'BusinessAddressState' => 'adr_one_region', + 'BusinessAddressStreet' => 'adr_one_street', + 'BusinessFaxNumber' => 'tel_fax', + 'BusinessTelephoneNumber' => 'tel_work', + 'CallbackTelephoneNumber' => '', + 'CarTelephoneNumber' => 'tel_car', + 'Categories' => 'cat_id', + 'Children' => '', + 'Companies' => '', + 'CompanyMainTelephoneNumber' => '', + 'CompanyName' => 'org_name', + 'ComputerNetworkName' => '', + 'Department' => 'org_unit', + 'Email1Address' => 'email', + 'Email1AddressType' => '', + 'Email2Address' => 'email_home', + 'Email2AddressType' => '', + 'Email3Address' => '', + 'Email3AddressType' => '', + 'FileAs' => 'n_fileas', + 'FirstName' => 'n_given', + 'Hobby' => '', + 'Home2TelephoneNumber' => '', + 'HomeAddressCity' => 'adr_two_locality', + 'HomeAddressCountry' => 'adr_two_countryname', + 'HomeAddressPostalCode' => 'adr_two_postalcode', + 'HomeAddressPostOfficeBox' => 'adr_two_street2', + 'HomeAddressState' => 'adr_two_region', + 'HomeAddressStreet' => 'adr_two_street', + 'HomeFaxNumber' => 'tel_fax_home', + 'HomeTelephoneNumber' => 'tel_home', + 'Importance' => '', + 'Initials' => '', + 'JobTitle' => 'title', + 'Language' => '', + 'LastName' => 'n_family', + 'ManagerName' => '', + 'MiddleName' => 'n_middle', + 'Mileage' => '', + 'MobileTelephoneNumber' => 'tel_cell', + 'NickName' => '', + 'OfficeLocation' => 'room', + 'OrganizationalIDNumber' => '', + 'OtherAddressCity' => '', + 'OtherAddressCountry' => '', + 'OtherAddressPostalCode' => '', + 'OtherAddressPostOfficeBox' => '', + 'OtherAddressState' => '', + 'OtherAddressStreet' => '', + 'OtherFaxNumber' => '', + 'OtherTelephoneNumber' => 'tel_other', + 'PagerNumber' => 'tel_pager', + 'PrimaryTelephoneNumber' => 'tel_prefer', + 'Profession' => 'role', + 'RadioTelephoneNumber' => '', + 'Sensitivity' => 'private', + 'Spouse' => '', + 'Subject' => '', + 'Suffix' => 'n_suffix', + 'TelexNumber' => '', + 'Title' => 'n_prefix', + 'WebPage' => 'url', + 'YomiCompanyName' => '', + 'YomiFirstName' => '', + 'YomiLastName' => '', + 'HomeWebPage' => 'url_home', + 'Folder' => '', + ); - class sifaddressbook extends boaddressbook - { - var $sifMapping = array( - 'Anniversary' => '', - 'AssistantName' => 'assistent', - 'AssistantTelephoneNumber' => 'tel_assistent', - 'BillingInformation' => '', - 'Birthday' => 'bday', - 'Body' => 'note', - 'Business2TelephoneNumber' => '', - 'BusinessAddressCity' => 'adr_one_locality', - 'BusinessAddressCountry' => 'adr_one_countryname', - 'BusinessAddressPostalCode' => 'adr_one_postalcode', - 'BusinessAddressPostOfficeBox' => 'adr_one_street2', - 'BusinessAddressState' => 'adr_one_region', - 'BusinessAddressStreet' => 'adr_one_street', - 'BusinessFaxNumber' => 'tel_fax', - 'BusinessTelephoneNumber' => 'tel_work', - 'CallbackTelephoneNumber' => '', - 'CarTelephoneNumber' => 'tel_car', - 'Categories' => 'cat_id', - 'Children' => '', - 'Companies' => '', - 'CompanyMainTelephoneNumber' => '', - 'CompanyName' => 'org_name', - 'ComputerNetworkName' => '', - 'Department' => 'org_unit', - 'Email1Address' => 'email', - 'Email1AddressType' => '', - 'Email2Address' => 'email_home', - 'Email2AddressType' => '', - 'Email3Address' => '', - 'Email3AddressType' => '', - 'FileAs' => 'n_fileas', - 'FirstName' => 'n_given', - 'Hobby' => '', - 'Home2TelephoneNumber' => '', - 'HomeAddressCity' => 'adr_two_locality', - 'HomeAddressCountry' => 'adr_two_countryname', - 'HomeAddressPostalCode' => 'adr_two_postalcode', - 'HomeAddressPostOfficeBox' => 'adr_two_street2', - 'HomeAddressState' => 'adr_two_region', - 'HomeAddressStreet' => 'adr_two_street', - 'HomeFaxNumber' => 'tel_fax_home', - 'HomeTelephoneNumber' => 'tel_home', - 'Importance' => '', - 'Initials' => '', - 'JobTitle' => 'title', - 'Language' => '', - 'LastName' => 'n_family', - 'ManagerName' => '', - 'MiddleName' => 'n_middle', - 'Mileage' => '', - 'MobileTelephoneNumber' => 'tel_cell', - 'NickName' => '', - 'OfficeLocation' => 'room', - 'OrganizationalIDNumber' => '', - 'OtherAddressCity' => '', - 'OtherAddressCountry' => '', - 'OtherAddressPostalCode' => '', - 'OtherAddressPostOfficeBox' => '', - 'OtherAddressState' => '', - 'OtherAddressStreet' => '', - 'OtherFaxNumber' => '', - 'OtherTelephoneNumber' => 'tel_other', - 'PagerNumber' => 'tel_pager', - 'PrimaryTelephoneNumber' => '', - 'Profession' => 'role', - 'RadioTelephoneNumber' => '', - 'Sensitivity' => 'private', - 'Spouse' => '', - 'Subject' => '', - 'Suffix' => 'n_suffix', - 'TelexNumber' => '', - 'Title' => 'n_prefix', - 'WebPage' => 'url', - 'YomiCompanyName' => '', - 'YomiFirstName' => '', - 'YomiLastName' => '', - 'HomeWebPage' => 'url_home', - 'Folder' => '', - ); + function startElement($_parser, $_tag, $_attributes) { + } - function startElement($_parser, $_tag, $_attributes) { + function endElement($_parser, $_tag) { + if(!empty($this->sifMapping[$_tag])) { + $this->contact[$this->sifMapping[$_tag]] = $this->sifData; } + unset($this->sifData); + } + + function characterData($_parser, $_data) { + $this->sifData .= $_data; + } + + function siftoegw($_sifdata) { + $sifData = base64_decode($_sifdata); - function endElement($_parser, $_tag) { - if(!empty($this->sifMapping[$_tag])) { - $this->contact[$this->sifMapping[$_tag]] = $this->sifData; - } - unset($this->sifData); - } - - function characterData($_parser, $_data) { - $this->sifData .= $_data; - } - - function siftoegw($_sifdata) { - $sysCharSet = $GLOBALS['egw']->translation->charset(); - $sifData = base64_decode($_sifdata); + #$tmpfname = tempnam('/tmp/sync/contents','sifc_'); - #$tmpfname = tempnam('/tmp/sync/contents','sifc_'); + #$handle = fopen($tmpfname, "w"); + #fwrite($handle, $sifdata); + #fclose($handle); - #$handle = fopen($tmpfname, "w"); - #fwrite($handle, $sifdata); - #fclose($handle); - - $this->xml_parser = xml_parser_create('UTF-8'); - xml_set_object($this->xml_parser, $this); - xml_parser_set_option($this->xml_parser, XML_OPTION_CASE_FOLDING, false); - xml_set_element_handler($this->xml_parser, "startElement", "endElement"); - xml_set_character_data_handler($this->xml_parser, "characterData"); - $this->strXmlData = xml_parse($this->xml_parser, $sifData); - if(!$this->strXmlData) { - error_log(sprintf("XML error: %s at line %d", - xml_error_string(xml_get_error_code($this->xml_parser)), - xml_get_current_line_number($this->xml_parser))); - return false; - } - - foreach($this->contact as $key => $value) { - $value = $GLOBALS['egw']->translation->convert($value, 'utf-8', $sysCharSet); - switch($key) { - case 'cat_id': - if(!empty($value)) { - $isAdmin = $GLOBALS['egw']->acl->check('run',1,'admin'); - $egwCategories =& CreateObject('phpgwapi.categories',$GLOBALS['egw_info']['user']['account_id'],'addressbook'); - $categories = explode('; ',$value); - $cat_id = ''; - foreach($categories as $categorieName) { - $categorieName = trim($categorieName); - if(!($cat_id = $egwCategories->name2id($categorieName)) && $isAdmin) { - $cat_id = $egwCategories->add(array('name' => $categorieName, 'descr' => $categorieName)); - } - if($cat_id) { - if(!empty($finalContact[$key])) $finalContact[$key] .= ','; - $finalContact[$key] .= $cat_id; - } - } - } - break; - - default: - $finalContact[$key] = $value; - break; - } - } - return $finalContact; - } - - /** - * Search an exactly matching entry (used for slow sync) - * - * @param string $_sifdata - * @return boolean/int/string contact-id or false, if not found - */ - function search($_sifdata) - { - if(!$contact = $this->siftoegw($_sifdata)) - { - return false; - } - - if(($foundContacts = $this->search($contact))) - { - error_log(print_r($foundContacts,true)); - return $foundContacts[0]['id']; - } + $this->xml_parser = xml_parser_create('UTF-8'); + xml_set_object($this->xml_parser, $this); + xml_parser_set_option($this->xml_parser, XML_OPTION_CASE_FOLDING, false); + xml_set_element_handler($this->xml_parser, "startElement", "endElement"); + xml_set_character_data_handler($this->xml_parser, "characterData"); + $this->strXmlData = xml_parse($this->xml_parser, $sifData); + if(!$this->strXmlData) { + error_log(sprintf("XML error: %s at line %d", + xml_error_string(xml_get_error_code($this->xml_parser)), + xml_get_current_line_number($this->xml_parser))); return false; } - /** - * import a vard into addressbook - * - * @return int contact id - * @param string $_vcard the vcard - * @param int $_abID the internal addressbook id - */ - function addSIF($_sifdata, $_abID) - { - #error_log('ABID: '.$_abID); - #error_log(base64_decode($_sifdata)); - - if(!$contact = $this->siftoegw($_sifdata)) { - return false; - } - - if($_abID > 0) $contact['ab_id'] = $_abID; - - return $this->save($contact); - } - - /** - * return a vcard - * - * @param int $_id the id of the contact - * @param int $_vcardProfile profile id for mapping from vcard values to egw addressbook - * @return string containing the vcard - */ - function getSIF($_id) - { - $fields = array_unique(array_values($this->sifMapping)); - sort($fields); - - if(!($entry = $this->so->read_entry($_id))) - { - return false; - } - $sifContact = ''; - #error_log(print_r($entry,true)); - $sysCharSet = $GLOBALS['egw']->translation->charset(); - - foreach($this->sifMapping as $sifField => $egwField) - { - if(empty($egwField)) continue; - - #error_log("$sifField => $egwField"); - #error_log('VALUE1: '.$entry[0][$egwField]); - $value = $GLOBALS['egw']->translation->convert($entry[0][$egwField], $sysCharSet, 'utf-8'); - #error_log('VALUE2: '.$value); - - switch($sifField) - { - // TODO handle multiple categories - case 'Categories': - if(!empty($value)) { - $egwCategories =& CreateObject('phpgwapi.categories',$GLOBALS['egw_info']['user']['account_id'],'addressbook'); - $categories = explode(',',$value); - $value = ''; - foreach($categories as $cat_id) { - if(($catData = $egwCategories->return_single($cat_id))) - { - if(!empty($value)) $value .= '; '; - $value .= $catData[0]['name']; - } + foreach($this->contact as $key => $value) { + $value = $GLOBALS['egw']->translation->convert($value, 'utf-8'); + switch($key) { + case 'cat_id': + if(!empty($value)) { + $isAdmin = $GLOBALS['egw']->acl->check('run',1,'admin'); + $egwCategories =& CreateObject('phpgwapi.categories',$GLOBALS['egw_info']['user']['account_id'],'addressbook'); + $categories = explode('; ',$value); + $cat_id = ''; + foreach($categories as $categorieName) { + $categorieName = trim($categorieName); + if(!($cat_id = $egwCategories->name2id($categorieName)) && $isAdmin) { + $cat_id = $egwCategories->add(array('name' => $categorieName, 'descr' => $categorieName)); + } + if($cat_id) { + if(!empty($finalContact[$key])) $finalContact[$key] .= ','; + $finalContact[$key] .= $cat_id; } } - $sifContact .= "<$sifField>$value"; - break; - - case 'Sensitivity': - $value = 2 * $value; // eGW private is 0 (public) or 1 (private) - $sifContact .= "<$sifField>$value"; - break; - - case 'Folder': - # skip currently. This is the folder where Outlook stores the contact. - #$sifContact .= "<$sifField>/"; - break; - - default: - $sifContact .= "<$sifField>$value"; - break; - } - } - $sifContact .= ""; + } + break; + + case 'private': + $finalContact[$key] = (int) $value > 0; // eGW private is 0 (public) or 1 (private), SIF seems to use 0 and 2 + break; - return base64_encode($sifContact); + default: + $finalContact[$key] = $value; + break; + } } + return $finalContact; } + + /** + * Search an exactly matching entry (used for slow sync) + * + * @param string $_sifdata + * @return boolean/int/string contact-id or false, if not found + */ + function search($_sifdata) + { + if(!$contact = $this->siftoegw($_sifdata)) + { + return false; + } + + if(($foundContacts = bocontact::search($contact))) + { + error_log(print_r($foundContacts,true)); + return $foundContacts[0]['id']; + } + return false; + } + + /** + * import a vard into addressbook + * + * @return int contact id + * @param string $_vcard the vcard + * @param int $_abID the internal addressbook id + */ + function addSIF($_sifdata, $_abID) + { + #error_log('ABID: '.$_abID); + #error_log(base64_decode($_sifdata)); + + if(!$contact = $this->siftoegw($_sifdata)) { + return false; + } + +// ToDo Lars: This will not work on LDAP +// either we use "if ($_abID)" and false, null, 0 as $_abID for new entries (prefered, as this works in all other apps) +// or we use something like "if ($_abID && $_abID != -1)" ... + if($_abID > 0) { + // update entry + $contact['id'] = $_abID; + } + return $this->save($contact); + } + + /** + * return a vcard + * + * @param int $_id the id of the contact + * @param int $_vcardProfile profile id for mapping from vcard values to egw addressbook + * @return string containing the vcard + */ + function getSIF($_id) + { + $fields = array_unique(array_values($this->sifMapping)); + sort($fields); + + if(!($entry = $this->read($_id))) + { + return false; + } + $sifContact = ''; + #error_log(print_r($entry,true)); + $sysCharSet = $GLOBALS['egw']->translation->charset(); + + foreach($this->sifMapping as $sifField => $egwField) + { + if(empty($egwField)) continue; + + #error_log("$sifField => $egwField"); + #error_log('VALUE1: '.$entry[0][$egwField]); + $value = $GLOBALS['egw']->translation->convert($entry[0][$egwField], $sysCharSet, 'utf-8'); + #error_log('VALUE2: '.$value); + + switch($sifField) + { + // TODO handle multiple categories + case 'Categories': + if(!empty($value)) { + $egwCategories =& CreateObject('phpgwapi.categories',$GLOBALS['egw_info']['user']['account_id'],'addressbook'); + $categories = explode(',',$value); + $value = ''; + foreach($categories as $cat_id) { + if(($catData = $egwCategories->return_single($cat_id))) + { + if(!empty($value)) $value .= '; '; + $value .= $catData[0]['name']; + } + } + } + $sifContact .= "<$sifField>$value"; + break; + + case 'Sensitivity': + $value = 2 * $value; // eGW private is 0 (public) or 1 (private) + $sifContact .= "<$sifField>$value"; + break; + + case 'Folder': + # skip currently. This is the folder where Outlook stores the contact. + #$sifContact .= "<$sifField>/"; + break; + + default: + $sifContact .= "<$sifField>$value"; + break; + } + } + $sifContact .= ""; + + return base64_encode($sifContact); + } +} diff --git a/addressbook/inc/class.vcaladdressbook.inc.php b/addressbook/inc/class.vcaladdressbook.inc.php index 654000af71..f4564acebe 100644 --- a/addressbook/inc/class.vcaladdressbook.inc.php +++ b/addressbook/inc/class.vcaladdressbook.inc.php @@ -29,16 +29,14 @@ class vcaladdressbook extends bocontacts return false; } +// ToDo Lars: This will not work on LDAP +// either we use "if ($_abID)" and false, null, 0 as $_abID for new entries (prefered, as this works in all other apps) +// or we use something like "if ($_abID && $_abID != -1)" ... if($_abID > 0) { // update entry $contact['id'] = $_abID; } - - if($this->save($contact)) { - return $contact['id']; - } - - return false; + return $this->save($contact); } /**