forked from extern/egroupware
- merged SyncML-1.2 branch with trunk:
svn merge ^/trunk/addressbook@27378 ^/branches/SyncML-1.2/addressbook . - re-added to trunk commits, which were somehow not in SyncML-1.2 branch: svn merge -c 26581 ^/trunk/addressbook svn merge -c 26582 ^/trunk/addressbook
This commit is contained in:
parent
e667e168b4
commit
d333605510
@ -5,6 +5,7 @@
|
||||
* @link http://www.egroupware.org
|
||||
* @author Cornelius Weiss <egw@von-und-zu-weiss.de>
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @author Joerg Lehrke <jlehrke@noc.de>
|
||||
* @package addressbook
|
||||
* @copyright (c) 2005-8 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @copyright (c) 2005/6 by Cornelius Weiss <egw@von-und-zu-weiss.de>
|
||||
@ -441,8 +442,13 @@ class addressbook_bo extends addressbook_so
|
||||
*/
|
||||
function fullname($contact)
|
||||
{
|
||||
if (empty($contact['n_family']) && empty($contact['n_given'])) {
|
||||
$cpart = array('org_name');
|
||||
} else {
|
||||
$cpart = array('n_prefix','n_given','n_middle','n_family','n_suffix');
|
||||
}
|
||||
$parts = array();
|
||||
foreach(array('n_prefix','n_given','n_middle','n_family','n_suffix') as $n)
|
||||
foreach($cpart as $n)
|
||||
{
|
||||
if ($contact[$n]) $parts[] = $contact[$n];
|
||||
}
|
||||
@ -611,8 +617,7 @@ class addressbook_bo extends addressbook_so
|
||||
$contact['modifier'] = $this->user;
|
||||
$contact['modified'] = $this->now_su;
|
||||
// set full name and fileas from the content
|
||||
if (isset($contact['n_family']) && isset($contact['n_given']))
|
||||
{
|
||||
if (!isset($contact['n_fn'])) {
|
||||
$contact['n_fn'] = $this->fullname($contact);
|
||||
if (isset($contact['org_name'])) $contact['n_fileas'] = $this->fileas($contact);
|
||||
}
|
||||
@ -1432,7 +1437,7 @@ class addressbook_bo extends addressbook_so
|
||||
{
|
||||
$cat_name = substr($cat_name, 2);
|
||||
}
|
||||
$cat_id = $this->categories->add(array('name' => $cat_name,'descr' => $cat_name));
|
||||
$cat_id = $this->categories->add(array('name' => $cat_name, 'descr' => $cat_name, 'access' => 'private'));
|
||||
}
|
||||
|
||||
if ($cat_id)
|
||||
@ -1474,15 +1479,273 @@ class addressbook_bo extends addressbook_so
|
||||
|
||||
function fixup_contact(&$contact)
|
||||
{
|
||||
if (!isset($contact['n_fn']) || empty($contact['n_fn']))
|
||||
if (empty($contact['n_fn']))
|
||||
{
|
||||
$contact['n_fn'] = $this->fullname($contact);
|
||||
}
|
||||
|
||||
if (!isset($contact['n_fileas']) || empty($contact['n_fileas']))
|
||||
if (empty($contact['n_fileas']))
|
||||
{
|
||||
$contact['n_fileas'] = $this->fileas($contact);
|
||||
}
|
||||
}
|
||||
|
||||
function all_empty(&$_contact, &$fields)
|
||||
{
|
||||
$retval = true;
|
||||
foreach ($fields as $field) {
|
||||
if (isset($_contact[$field]) && !empty($_contact[$field])) {
|
||||
$retval = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $retval;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Try to find a matching db entry
|
||||
*
|
||||
* @param array $contact the contact data we try to find
|
||||
* @param boolean $relax=false if asked to relax, we only match against some key fields
|
||||
* @return the contact_id of the matching entry or false (if none matches)
|
||||
*/
|
||||
function find_contact($contact, $relax=false)
|
||||
{
|
||||
if ($contact['id'] && ($found = $this->read($contact['id'])))
|
||||
{
|
||||
// We only do a simple consistency check
|
||||
if ((empty($found['n_family']) || $found['n_family'] == $contact['n_family'])
|
||||
&& (empty($found['n_given']) || $found['n_given'] == $contact['n_given'])
|
||||
&& (empty($found['org_name']) || $found['org_name'] == $contact['org_name']))
|
||||
{
|
||||
return $found['id'];
|
||||
}
|
||||
}
|
||||
unset($contact['id']);
|
||||
|
||||
$columns_to_search = array('contact_id',
|
||||
'n_family', 'n_given', 'n_middle', 'n_prefix', 'n_suffix',
|
||||
'bday', 'org_name', 'org_unit', 'title', 'role',
|
||||
'email', 'email_home', 'url', 'url_home');
|
||||
$tolerance_fields = array('contact_id',
|
||||
'n_middle', 'n_prefix', 'n_suffix',
|
||||
'org_unit', 'role',
|
||||
'bday',
|
||||
'email', 'email_home',
|
||||
'url', 'url_home');
|
||||
$addr_one_fields = array('adr_one_street', 'adr_one_street2',
|
||||
'adr_one_locality', 'adr_one_region',
|
||||
'adr_one_postalcode', 'adr_one_countryname');
|
||||
$addr_two_fields = array('adr_two_street', 'adr_two_street2',
|
||||
'adr_two_locality', 'adr_two_region',
|
||||
'adr_two_postalcode', 'adr_two_countryname');
|
||||
$no_addr_one = array();
|
||||
$no_addr_two = array();
|
||||
|
||||
$backend =& $this->get_backend();
|
||||
|
||||
// define filter for empty address one
|
||||
foreach ($addr_one_fields as $field)
|
||||
{
|
||||
if (!($db_col = array_search($field, $backend->db_cols)))
|
||||
{
|
||||
$db_col = $field;
|
||||
}
|
||||
$no_addr_one[] = "(" . $db_col . " IS NULL OR " . $db_col . " = '')";
|
||||
}
|
||||
|
||||
// define filter for empty address two
|
||||
foreach ($addr_two_fields as $field)
|
||||
{
|
||||
if (!($db_col = array_search($field, $backend->db_cols)))
|
||||
{
|
||||
$db_col = $field;
|
||||
}
|
||||
$no_addr_two[] = "(" . $db_col . " IS NULL OR " . $db_col . " = '')";
|
||||
}
|
||||
|
||||
$result = false;
|
||||
|
||||
$criteria = array();
|
||||
$empty_columns = array();
|
||||
foreach ($columns_to_search as $field)
|
||||
{
|
||||
if (!isset($contact[$field]) || empty($contact[$field])) {
|
||||
// Not every device supports all fields
|
||||
if (!in_array($field, $tolerance_fields))
|
||||
{
|
||||
if (!($db_col = array_search($field, $backend->db_cols)))
|
||||
{
|
||||
$db_col = $field;
|
||||
}
|
||||
$empty_columns[] = "(" . $db_col . " IS NULL OR " . $db_col . " = '')";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!$relax || !in_array($field, $tolerance_fields))
|
||||
{
|
||||
$criteria[$field] = $contact[$field];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$filter = $empty_columns;
|
||||
|
||||
if (!$relax)
|
||||
{
|
||||
// We use addresses only for strong matching
|
||||
|
||||
if ($this->all_empty($contact, $addr_one_fields))
|
||||
{
|
||||
$filter = $filter + $no_addr_one;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($addr_one_fields as $field)
|
||||
{
|
||||
if (!isset($contact[$field]) || empty($contact[$field]))
|
||||
{
|
||||
if (!($db_col = array_search($field, $backend->db_cols)))
|
||||
{
|
||||
$db_col = $field;
|
||||
}
|
||||
$filter[] = "(" . $db_col . " IS NULL OR " . $db_col . " = '')";
|
||||
}
|
||||
else
|
||||
{
|
||||
$criteria[$field] = $contact[$field];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->all_empty($contact, $addr_two_fields))
|
||||
{
|
||||
$filter = $filter + $no_addr_two;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($addr_two_fields as $field)
|
||||
{
|
||||
if (!isset($contact[$field]) || empty($contact[$field]))
|
||||
{
|
||||
if (!($db_col = array_search($field, $backend->db_cols)))
|
||||
{
|
||||
$db_col = $field;
|
||||
}
|
||||
$filter[] = "(" . $db_col . " IS NULL OR " . $db_col . " = '')";
|
||||
}
|
||||
else
|
||||
{
|
||||
$criteria[$field] = $contact[$field];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Horde::logMessage("Addressbook find step 1:\n" . print_r($criteria, true) .
|
||||
"filter:\n" . print_r($filter, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
|
||||
// first try full match
|
||||
if (($foundContacts = parent::search($criteria, true, '', '', '', False, 'AND', false, $filter)))
|
||||
{
|
||||
$result = $foundContacts[0]['id'];
|
||||
}
|
||||
|
||||
// No need for more searches for relaxed matching
|
||||
if (!$relax && !$result && !$this->all_empty($contact, $addr_one_fields)
|
||||
&& $this->all_empty($contact, $addr_two_fields))
|
||||
{
|
||||
// try given address and ignore the second one in EGW
|
||||
$filter = array_diff($filter, $no_addr_two);
|
||||
|
||||
Horde::logMessage("Addressbook find step 2:\n" . print_r($criteria, true) .
|
||||
"filter:\n" . print_r($filter, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
if (($foundContacts = parent::search($criteria, true, '', '', '', False, 'AND', false, $filter)))
|
||||
{
|
||||
$result = $foundContacts[0]['id'];
|
||||
}
|
||||
else
|
||||
{
|
||||
// try address as home address -- some devices don't qualify addresses
|
||||
$filter = $empty_columns;
|
||||
foreach ($addr_two_fields as $key => $field)
|
||||
{
|
||||
if (isset($criteria[$addr_one_fields[$key]]))
|
||||
{
|
||||
$criteria[$field] = $criteria[$addr_one_fields[$key]];
|
||||
unset($criteria[$addr_one_fields[$key]]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!($db_col = array_search($field,$backend->db_cols)))
|
||||
{
|
||||
$db_col = $field;
|
||||
}
|
||||
$filter[] = "(" . $db_col . " IS NULL OR " . $db_col . " = '')";
|
||||
}
|
||||
}
|
||||
|
||||
$filter = $filter + $no_addr_one;
|
||||
|
||||
Horde::logMessage("Addressbook find step 3:\n" . print_r($criteria, true) .
|
||||
"filter:\n" . print_r($filter, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
if (($foundContacts = parent::search($criteria, true, '', '', '', False, 'AND', false, $filter)))
|
||||
{
|
||||
$result = $foundContacts[0]['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif (!$relax && !$result)
|
||||
{ // No more searches for relaxed matching, try again after address swap
|
||||
|
||||
$filter = $empty_columns;
|
||||
|
||||
foreach ($addr_one_fields as $key => $field)
|
||||
{
|
||||
$_temp_set = false;
|
||||
if (isset($criteria[$field]))
|
||||
{
|
||||
$_temp = $criteria[$field];
|
||||
$_temp_set = true;
|
||||
unset($criteria[$field]);
|
||||
}
|
||||
if (isset($criteria[$addr_two_fields[$key]]))
|
||||
{
|
||||
$criteria[$field] = $criteria[$addr_two_fields[$key]];
|
||||
unset($criteria[$addr_two_fields[$key]]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!($db_col = array_search($field,$backend->db_cols)))
|
||||
{
|
||||
$db_col = $field;
|
||||
}
|
||||
$filter[] = "(" . $db_col . " IS NULL OR " . $db_col . " = '')";
|
||||
}
|
||||
if ($_temp_set)
|
||||
{
|
||||
$criteria[$addr_two_fields[$key]] = $_temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!($db_col = array_search($addr_two_fields[$key],$backend->db_cols)))
|
||||
{
|
||||
$db_col = $field;
|
||||
}
|
||||
$filter[] = "(" . $db_col . " IS NULL OR " . $db_col . " = '')";
|
||||
}
|
||||
}
|
||||
|
||||
Horde::logMessage("Addressbook find step 4:\n" . print_r($criteria, true) .
|
||||
"filter:\n" . print_r($filter, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
if(($foundContacts = parent::search($criteria, true, '', '', '', False, 'AND', false, $filter)))
|
||||
{
|
||||
$result = $foundContacts[0]['id'];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -310,7 +310,7 @@ class addressbook_groupdav extends groupdav_handler
|
||||
*/
|
||||
private function _get_handler()
|
||||
{
|
||||
$handler = new addressbook_vcal();
|
||||
$handler = new addressbook_vcal('addressbook','text/vcard');
|
||||
$handler->setSupportedFields('GroupDAV',$this->agent);
|
||||
|
||||
return $handler;
|
||||
|
@ -5,6 +5,7 @@
|
||||
* @link http://www.egroupware.org
|
||||
* @author Lars Kneschke <lkneschke@egroupware.org>
|
||||
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
|
||||
* @author Joerg Lehrke <jlehrke@noc.de>
|
||||
* @package addressbook
|
||||
* @subpackage export
|
||||
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||
@ -94,6 +95,10 @@ class addressbook_sif extends addressbook_bo
|
||||
'Folder' => '',
|
||||
);
|
||||
|
||||
// standard headers
|
||||
const xml_decl = '<?xml version="1.0" encoding="UTF-8"?>';
|
||||
const SIF_decl = '<SIFVersion>1.1</SIFVersion>';
|
||||
|
||||
function startElement($_parser, $_tag, $_attributes) {
|
||||
}
|
||||
|
||||
@ -108,13 +113,12 @@ class addressbook_sif extends addressbook_bo
|
||||
$this->sifData .= $_data;
|
||||
}
|
||||
|
||||
function siftoegw($_sifdata) {
|
||||
$sifData = base64_decode($_sifdata);
|
||||
function siftoegw($sifData) {
|
||||
|
||||
#$tmpfname = tempnam('/tmp/sync/contents','sifc_');
|
||||
|
||||
#$handle = fopen($tmpfname, "w");
|
||||
#fwrite($handle, $sifdata);
|
||||
#fwrite($handle, $sifData);
|
||||
#fclose($handle);
|
||||
|
||||
$this->xml_parser = xml_parser_create('UTF-8');
|
||||
@ -131,6 +135,7 @@ class addressbook_sif extends addressbook_bo
|
||||
}
|
||||
|
||||
foreach($this->contact as $key => $value) {
|
||||
$value = preg_replace('/<\!\[CDATA\[(.+)\]\]>/Usim', '$1', $value);
|
||||
$value = $GLOBALS['egw']->translation->convert($value, 'utf-8');
|
||||
switch($key) {
|
||||
case 'cat_id':
|
||||
@ -164,25 +169,17 @@ class addressbook_sif extends addressbook_bo
|
||||
* @param string $_sifdata
|
||||
* @return boolean/int/string contact-id or false, if not found
|
||||
*/
|
||||
function search($_sifdata,$contentID=null)
|
||||
function search($_sifdata, $contentID=null, $relax=false)
|
||||
{
|
||||
if(!$contact = $this->siftoegw($_sifdata))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
$result = false;
|
||||
|
||||
if($contact = $this->siftoegw($_sifdata)) {
|
||||
if ($contentID) {
|
||||
$contact['contact_id'] = $contentID;
|
||||
}
|
||||
// patch from Di Guest says: we need to ignore the n_fileas
|
||||
unset($contact['n_fileas']);
|
||||
// we probably need to ignore even more as we do in vcaladdressbook
|
||||
|
||||
if(($foundContacts = addressbook_bo::search($contact)))
|
||||
{
|
||||
error_log(print_r($foundContacts,true));
|
||||
return $foundContacts[0]['id'];
|
||||
$result = $this->find_contact($contact, $relax);
|
||||
}
|
||||
return false;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -191,8 +188,9 @@ class addressbook_sif extends addressbook_bo
|
||||
* @return int contact id
|
||||
* @param string $_vcard the vcard
|
||||
* @param int/string $_abID=null the internal addressbook id or !$_abID for a new enty
|
||||
* @param boolean $merge=false merge data with existing entry
|
||||
*/
|
||||
function addSIF($_sifdata, $_abID=null)
|
||||
function addSIF($_sifdata, $_abID=null, $merge=false)
|
||||
{
|
||||
#error_log('ABID: '.$_abID);
|
||||
#error_log(base64_decode($_sifdata));
|
||||
@ -209,24 +207,25 @@ class addressbook_sif extends addressbook_bo
|
||||
}
|
||||
|
||||
/**
|
||||
* return a vcard
|
||||
* return a sifc
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
$sysCharSet = $GLOBALS['egw']->translation->charset();
|
||||
|
||||
$fields = array_unique(array_values($this->sifMapping));
|
||||
sort($fields);
|
||||
|
||||
if(!($entry = $this->read($_id)))
|
||||
{
|
||||
if(!($entry = $this->read($_id))) {
|
||||
return false;
|
||||
}
|
||||
$sifContact = '<contact>';
|
||||
|
||||
$sifContact = self::xml_decl . "\n<contact>" . self::SIF_decl;
|
||||
|
||||
#error_log(print_r($entry,true));
|
||||
$sysCharSet = $GLOBALS['egw']->translation->charset();
|
||||
|
||||
// fillup some defaults such as n_fn and n_fileas is needed
|
||||
$this->fixup_contact($entry);
|
||||
@ -242,15 +241,6 @@ class addressbook_sif extends addressbook_bo
|
||||
|
||||
switch($sifField)
|
||||
{
|
||||
// TODO handle multiple categories
|
||||
case 'Categories':
|
||||
if(!empty($value)) {
|
||||
$value = implode("; ", $this->get_categories($value));
|
||||
$value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8');
|
||||
}
|
||||
$sifContact .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
|
||||
case 'Sensitivity':
|
||||
$value = 2 * $value; // eGW private is 0 (public) or 1 (private)
|
||||
$sifContact .= "<$sifField>$value</$sifField>";
|
||||
@ -261,13 +251,22 @@ class addressbook_sif extends addressbook_bo
|
||||
#$sifContact .= "<$sifField>/</$sifField>";
|
||||
break;
|
||||
|
||||
case 'Categories':
|
||||
if(!empty($value)) {
|
||||
$value = implode("; ", $this->get_categories($value));
|
||||
$value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8');
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
$sifContact .= "<$sifField>".trim($value)."</$sifField>";
|
||||
$value = @htmlspecialchars(trim($value), ENT_QUOTES, 'utf-8');
|
||||
$sifContact .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
}
|
||||
}
|
||||
$sifContact .= "</contact>";
|
||||
|
||||
return base64_encode($sifContact);
|
||||
return $sifContact;
|
||||
}
|
||||
}
|
||||
|
@ -607,11 +607,23 @@ class addressbook_sql extends so_sql
|
||||
*/
|
||||
function read($keys,$extra_cols='',$join='')
|
||||
{
|
||||
if (isset($GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'])) {
|
||||
$minimum_uid_length = $GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'];
|
||||
} else {
|
||||
$minimum_uid_length = 8;
|
||||
}
|
||||
|
||||
if (!is_array($keys) && !is_numeric($keys))
|
||||
{
|
||||
$keys = array('contact_uid' => $keys);
|
||||
}
|
||||
return parent::read($keys,$extra_cols,$join);
|
||||
$contact = parent::read($keys,$extra_cols,$join);
|
||||
// enforce a minium uid strength
|
||||
if (is_array($contact) && (!isset($contact['uid'])
|
||||
|| strlen($contact['uid']) < $minimum_uid_length)) {
|
||||
parent::update(array('uid' => common::generate_uid('addressbook',$contact['id'])));
|
||||
}
|
||||
return $contact;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -623,6 +635,12 @@ class addressbook_sql extends so_sql
|
||||
*/
|
||||
function save($keys=null)
|
||||
{
|
||||
if (isset($GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'])) {
|
||||
$minimum_uid_length = $GLOBALS['egw_info']['user']['preferences']['syncml']['minimum_uid_length'];
|
||||
} else {
|
||||
$minimum_uid_length = 8;
|
||||
}
|
||||
|
||||
if (is_array($keys) && count($keys)) $this->data_merge($keys);
|
||||
|
||||
$new_entry = !$this->data['id'];
|
||||
@ -649,8 +667,8 @@ class addressbook_sql extends so_sql
|
||||
}
|
||||
}
|
||||
// enforce a minium uid strength
|
||||
if (!$err && ($new_entry || isset($this->data['uid'])) && (strlen($this->data['uid']) < 20 || is_numeric($this->data['uid'])))
|
||||
{
|
||||
if (!$err && (!isset($this->data['uid'])
|
||||
|| strlen($this->data['uid']) < $minimum_uid_length)) {
|
||||
parent::update(array('uid' => common::generate_uid('addressbook',$this->data['id'])));
|
||||
//echo "<p>set uid={$this->data['uid']}, etag={$this->data['etag']}</p>";
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user