mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-21 23:43:17 +01:00
SyncML patches from patrick.bihan-faou-AT-mindstep.com (without
logout+mbstring stuff), small modification to use the already exiting methodes to generate full name and fileas) The code is commited to trunk only at the moment to allow testing of it. If everything goes well, we intend to commit it to 1.4 branch too. Here's the original description of the patch by Patrick: - handles the default config for current versions of funambol (i.e. the scard/stask/snote/scal locations) - tries to be a bit smarter on how the data content should be encoded based on what the client specified (sif+base64/vcard, / fragmented or not, etc.) - workaround a bug in some versions of funambol, where funambol does not specify the proper sif type for the type of requested data - imported patch #117 from egw's tracker - make sure that the logs generated by the horde code go to stderr so they can be view in the webserver's logs - as much as possible reduce code duplication. For example, the categories are handled in the parent classes for both the SIF avn VCAL formats for each type of data (addressbook,infolog,calendar). - make sure the code can handle more than one categories in each direction - treat the 'sony ericsson' vendor string just like 'sonyericsson', the newer phones apparently have a space in the vendor string... (this touches some files in the icalsrv as well) - handle notes: these should now work with everything (funambol or other) - remove more code duplication: the syncml "api" for the various data types (calendar, contacts, infolog) is now common for both the vcard and sif data formats (cf the files that need to be removed) - handle the "privat" filter in infolog like the "private" filter (some part of the code use the name without the trailing e) - imported patch # 267 from egw's tracker
This commit is contained in:
parent
82f2b4e91f
commit
7b6a1013fc
@ -1108,4 +1108,86 @@ class bocontacts extends socontacts
|
||||
//echo "<p>bocontacts::addr_format_by_country('$country'='$code') = '$adr_format'</p>\n";
|
||||
return $adr_format;
|
||||
}
|
||||
|
||||
var $app_cat;
|
||||
var $glob_cat;
|
||||
|
||||
function find_or_add_categories($catname_list)
|
||||
{
|
||||
if (!is_object($this->glob_cat))
|
||||
{
|
||||
if (!is_object($GLOBALS['egw']->categories))
|
||||
{
|
||||
$GLOBALS['egw']->categories =& CreateObject('phpgwapi.categories',$this->owner,'phpgw');
|
||||
}
|
||||
$this->glob_cat =& $GLOBALS['egw']->categories;
|
||||
}
|
||||
|
||||
if (!is_object($this->app_cat))
|
||||
{
|
||||
$this->app_cat =& CreateObject('phpgwapi.categories',$this->owner,'addressbook');
|
||||
}
|
||||
|
||||
$cat_id_list = array();
|
||||
foreach($catname_list as $cat_name)
|
||||
{
|
||||
$cat_name = trim($cat_name);
|
||||
if (!($cat_id = $this->glob_cat->name2id($cat_name))
|
||||
&& !($cat_id = $this->app_cat->name2id($cat_name)))
|
||||
{
|
||||
$cat_id = $this->app_cat->add( array('name' => $cat_name,'descr' => $cat_name ));
|
||||
}
|
||||
|
||||
$cat_id_list[] = $cat_id;
|
||||
}
|
||||
|
||||
if (count($cat_id_list) > 1)
|
||||
{
|
||||
sort($cat_id_list, SORT_NUMERIC);
|
||||
}
|
||||
return $cat_id_list;
|
||||
}
|
||||
|
||||
function get_categories($cat_id_list)
|
||||
{
|
||||
if (!is_object($this->glob_cat))
|
||||
{
|
||||
if (!is_object($GLOBALS['egw']->categories))
|
||||
{
|
||||
$GLOBALS['egw']->categories =& CreateObject('phpgwapi.categories',$this->owner,'phpgw');
|
||||
}
|
||||
$this->glob_cat =& $GLOBALS['egw']->categories;
|
||||
}
|
||||
|
||||
if (!is_object($this->app_cat))
|
||||
{
|
||||
$this->app_cat =& CreateObject('phpgwapi.categories',$this->owner,'addressbook');
|
||||
}
|
||||
|
||||
$cat_list = array();
|
||||
foreach(explode(',',$cat_id_list) as $cat_id)
|
||||
{
|
||||
if ( ($cat_data = $this->glob_cat->return_single($cat_id))
|
||||
|| ($cat_data = $this->app_cat->return_single($cat_id)) )
|
||||
{
|
||||
$cat_list[] = $cat_data[0]['name'];
|
||||
}
|
||||
}
|
||||
|
||||
return $cat_list;
|
||||
}
|
||||
|
||||
function fixup_contact(&$contact)
|
||||
{
|
||||
if (!isset($contact['n_fn']) || empty($contact['n_fn']))
|
||||
{
|
||||
$contact['n_fn'] = $this->fullname($contact);
|
||||
}
|
||||
|
||||
if (!isset($contact['n_fileas']) || empty($contact['n_fileas']))
|
||||
{
|
||||
$contact['n_fileas'] = $this->fileas($contact);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -135,23 +135,9 @@ class sifaddressbook extends bocontacts
|
||||
$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);
|
||||
// add missing categories as personal categories as needed
|
||||
foreach($categories as $categorieName) {
|
||||
$cat_id = false;
|
||||
$categorieName = trim($categorieName);
|
||||
if(!($cat_id = $egwCategories->name2id($categorieName))) {
|
||||
$cat_id = $egwCategories->add(array('name' => $categorieName, 'descr' => lang('added by synchronisation')));
|
||||
error_log("added $cat_id => $categorieName");
|
||||
}
|
||||
if($cat_id) {
|
||||
if(!empty($finalContact[$key])) $finalContact[$key] .= ',';
|
||||
$finalContact[$key] .= $cat_id;
|
||||
}
|
||||
}
|
||||
if(!empty($value))
|
||||
{
|
||||
$finalContact[$key] = implode(",", $this->find_or_add_categories(explode(';', $value)));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -164,6 +150,8 @@ class sifaddressbook extends bocontacts
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->fixup_contact($finalContact);
|
||||
return $finalContact;
|
||||
}
|
||||
|
||||
@ -231,6 +219,9 @@ class sifaddressbook extends bocontacts
|
||||
#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);
|
||||
|
||||
foreach($this->sifMapping as $sifField => $egwField)
|
||||
{
|
||||
if(empty($egwField)) continue;
|
||||
@ -245,16 +236,8 @@ class sifaddressbook extends bocontacts
|
||||
// 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'];
|
||||
}
|
||||
}
|
||||
$value = implode("; ", $this->get_categories($value));
|
||||
$value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8');
|
||||
}
|
||||
$sifContact .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
@ -270,7 +253,7 @@ class sifaddressbook extends bocontacts
|
||||
break;
|
||||
|
||||
default:
|
||||
$sifContact .= "<$sifField>$value</$sifField>";
|
||||
$sifContact .= "<$sifField>".trim($value)."</$sifField>";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -57,52 +57,83 @@ class vcaladdressbook extends bocontacts
|
||||
if(!($entry = $this->read($_id))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach($this->supportedFields as $vcardField => $databaseFields) {
|
||||
$options = array();
|
||||
$value = '';
|
||||
foreach($databaseFields as $databaseField) {
|
||||
$tempVal = ';';
|
||||
if(!empty($databaseField)) {
|
||||
$tempVal = trim($entry[$databaseField]).';';
|
||||
}
|
||||
$value .= $tempVal;
|
||||
}
|
||||
// remove the last ;
|
||||
$value = substr($value, 0, -1);
|
||||
|
||||
switch($vcardField) {
|
||||
// TODO handle multiple categories
|
||||
case 'CATEGORIES':
|
||||
$catData = ExecMethod('phpgwapi.categories.return_single',$value);
|
||||
$value = $catData[0]['name'];
|
||||
break;
|
||||
case 'CLASS':
|
||||
$value = $value ? 'PRIVATE' : 'PUBLIC';
|
||||
break;
|
||||
case 'BDAY':
|
||||
if(!empty($value)) {
|
||||
$value = str_replace('-','',$value).'T000000Z';
|
||||
}
|
||||
break;
|
||||
$this->fixup_contact($entry);
|
||||
|
||||
foreach($this->supportedFields as $vcardField => $databaseFields)
|
||||
{
|
||||
$values = array();
|
||||
$options = array();
|
||||
$hasdata = 0;
|
||||
foreach($databaseFields as $databaseField)
|
||||
{
|
||||
$value = "";
|
||||
|
||||
if (!empty($databaseField))
|
||||
{
|
||||
$value = trim($entry[$databaseField]);
|
||||
}
|
||||
|
||||
switch($databaseField)
|
||||
{
|
||||
case 'private':
|
||||
$value = $value ? 'PRIVATE' : 'PUBLIC';
|
||||
$hasdata++;
|
||||
break;
|
||||
|
||||
case 'bday':
|
||||
if (!empty($value))
|
||||
{
|
||||
$value = str_replace('-','',$value).'T000000Z';
|
||||
$hasdata++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'jpegphoto':
|
||||
if(!empty($value))
|
||||
{
|
||||
error_log("PHOTO='".$value."'");
|
||||
$hasdata++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'cat_id':
|
||||
if (!empty($value))
|
||||
{
|
||||
$value = implode(",", $this->get_categories($value));
|
||||
}
|
||||
// fall-through to the normal processing of string values
|
||||
default:
|
||||
if(!empty($value))
|
||||
{
|
||||
$value = $GLOBALS['egw']->translation->convert(trim($value), $sysCharSet, 'utf-8');
|
||||
$options['CHARSET'] = 'UTF-8';
|
||||
|
||||
if(preg_match('/([\000-\012\015\016\020-\037\075])/',$value))
|
||||
{
|
||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}
|
||||
|
||||
$hasdata++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (empty($value))
|
||||
{
|
||||
$value = "";
|
||||
}
|
||||
|
||||
$values[] = $value;
|
||||
}
|
||||
|
||||
if ($databaseField != 'jpegphoto') {
|
||||
$value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8');
|
||||
|
||||
if ($hasdata <= 0)
|
||||
{
|
||||
// don't add the entry if there is no data for this field
|
||||
continue;
|
||||
}
|
||||
|
||||
// don't add the entry if it contains only ';'
|
||||
// exeptions for mendatory fields
|
||||
if( ( strlen(str_replace(';','',$value)) != 0 ) || in_array($vcardField,array('FN','ORG','N')) ) {
|
||||
$vCard->setAttribute($vcardField, $value);
|
||||
}
|
||||
if(preg_match('/([\000-\012\015\016\020-\037\075])/',$value)) {
|
||||
$options['ENCODING'] = 'QUOTED-PRINTABLE';
|
||||
}
|
||||
if(preg_match('/([\177-\377])/',$value)) {
|
||||
$options['CHARSET'] = 'UTF-8';
|
||||
}
|
||||
|
||||
|
||||
$vCard->setAttribute($vcardField, implode(';', $values));
|
||||
$vCard->setParameter($vcardField, $options);
|
||||
}
|
||||
|
||||
@ -177,6 +208,7 @@ class vcaladdressbook extends bocontacts
|
||||
'CLASS' => array('private'),
|
||||
'EMAIL' => array('email'),
|
||||
'N' => array('n_family','n_given','','',''),
|
||||
'FN' => array('n_fn'),
|
||||
'NOTE' => array('note'),
|
||||
'ORG' => array('org_name',''),
|
||||
'TEL;CELL' => array('tel_cell'),
|
||||
@ -196,6 +228,7 @@ class vcaladdressbook extends bocontacts
|
||||
'EMAIL;INTERNET;WORK' => array('email'),
|
||||
'EMAIL;INTERNET;HOME' => array('email_home'),
|
||||
'N' => array('n_family','n_given','n_middle','n_prefix','n_suffix'),
|
||||
'FN' => array('n_fn'),
|
||||
'NOTE' => array('note'),
|
||||
'ORG' => array('org_name','org_unit'),
|
||||
'TEL;CELL;WORK' => array('tel_cell'),
|
||||
@ -216,6 +249,7 @@ class vcaladdressbook extends bocontacts
|
||||
'CLASS' => array('private'),
|
||||
'EMAIL' => array('email'),
|
||||
'N' => array('n_family','n_given','','',''),
|
||||
'FN' => array('n_fn'),
|
||||
'NOTE' => array('note'),
|
||||
'ORG' => array('org_name',''),
|
||||
'TEL;CELL;WORK' => array('tel_cell'),
|
||||
@ -235,6 +269,7 @@ class vcaladdressbook extends bocontacts
|
||||
'EMAIL;INTERNET;WORK' => array('email'),
|
||||
'EMAIL;INTERNET;HOME' => array('email_home'),
|
||||
'N' => array('n_family','n_given','','',''),
|
||||
'FN' => array('n_fn'),
|
||||
'NOTE' => array('note'),
|
||||
'ORG' => array('org_name','org_unit'),
|
||||
'TEL;CELL;WORK' => array('tel_cell'),
|
||||
@ -255,6 +290,7 @@ class vcaladdressbook extends bocontacts
|
||||
'EMAIL;INTERNET;WORK' => array('email'),
|
||||
'EMAIL;INTERNET;HOME' => array('email_home'),
|
||||
'N' => array('n_family','n_given','','',''),
|
||||
'FN' => array('n_fn'),
|
||||
'NOTE' => array('note'),
|
||||
'ORG' => array('org_name',''),
|
||||
'TEL;CELL;WORK' => array('tel_cell'),
|
||||
@ -278,6 +314,7 @@ class vcaladdressbook extends bocontacts
|
||||
'EMAIL;INTERNET;WORK' => array('email'),
|
||||
'EMAIL;INTERNET;HOME' => array('email_home'),
|
||||
'N' => array('n_family','n_given','','n_prefix','n_suffix'),
|
||||
'FN' => array('n_fn'),
|
||||
'NOTE' => array('note'),
|
||||
'ORG' => array('org_name',''),
|
||||
'TEL;CELL;WORK' => array('tel_cell'),
|
||||
@ -293,32 +330,38 @@ class vcaladdressbook extends bocontacts
|
||||
);
|
||||
|
||||
$defaultFields[6] = array(
|
||||
'ADR;WORK' => array('','','adr_one_street','adr_one_locality','adr_one_region',
|
||||
'adr_one_postalcode','adr_one_countryname'),
|
||||
'ADR;HOME' => array('','','adr_two_street','adr_two_locality','adr_two_region',
|
||||
'adr_two_postalcode','adr_two_countryname'),
|
||||
'EMAIL' => array('email'),
|
||||
'EMAIL;HOME' => array('email_home'),
|
||||
'N' => array('n_family','n_given','','',''),
|
||||
'NOTE' => array('note'),
|
||||
'ORG' => array('org_name','org_unit'),
|
||||
'TEL;CELL' => array('tel_cell'),
|
||||
'TEL;HOME;FAX' => array('tel_fax'),
|
||||
'ADR;WORK' => array('','','adr_one_street','adr_one_locality','adr_one_region',
|
||||
'adr_one_postalcode','adr_one_countryname'),
|
||||
'ADR;HOME' => array('','','adr_two_street','adr_two_locality','adr_two_region',
|
||||
'adr_two_postalcode','adr_two_countryname'),
|
||||
'EMAIL' => array('email'),
|
||||
'EMAIL;HOME' => array('email_home'),
|
||||
'N' => array('n_family','n_given','','',''),
|
||||
'FN' => array('n_fn'),
|
||||
'NOTE' => array('note'),
|
||||
'ORG' => array('org_name','org_unit'),
|
||||
'TEL;CELL' => array('tel_cell'),
|
||||
'TEL;HOME;FAX' => array('tel_fax'),
|
||||
'TEL;HOME;VOICE' => array('tel_home'),
|
||||
'TEL;PAGER' => array('tel_pager'),
|
||||
'TEL;PAGER' => array('tel_pager'),
|
||||
'TEL;WORK;VOICE' => array('tel_work'),
|
||||
'TITLE' => array('title'),
|
||||
'URL;WORK' => array('url'),
|
||||
'URL' => array('url_home'),
|
||||
'TITLE' => array('title'),
|
||||
'URL;WORK' => array('url'),
|
||||
'URL' => array('url_home'),
|
||||
);
|
||||
|
||||
//error_log("Client: $_productManufacturer $_productName");
|
||||
switch(strtolower($_productManufacturer))
|
||||
{
|
||||
case 'funambol':
|
||||
switch(strtolower($_productName))
|
||||
switch (strtolower($_productName))
|
||||
{
|
||||
case 'fmz-thunderbird-plugin':
|
||||
case 'thunderbird':
|
||||
$this->supportedFields = $defaultFields[6];
|
||||
break;
|
||||
|
||||
default:
|
||||
error_log("Funambol product '$_productName', assuming same as thunderbird");
|
||||
$this->supportedFields = $defaultFields[6];
|
||||
break;
|
||||
}
|
||||
@ -328,7 +371,10 @@ class vcaladdressbook extends bocontacts
|
||||
switch(strtolower($_productName))
|
||||
{
|
||||
case 'syncje outlook edition':
|
||||
$this->supportedFields = $defaultFields[1];
|
||||
break;
|
||||
default:
|
||||
error_log("Nethaus product '$_productName', assuming same as 'syncje outlook'");
|
||||
$this->supportedFields = $defaultFields[1];
|
||||
break;
|
||||
}
|
||||
@ -341,7 +387,10 @@ class vcaladdressbook extends bocontacts
|
||||
$this->supportedFields = $defaultFields[5];
|
||||
break;
|
||||
case '6600':
|
||||
$this->supportedFields = $defaultFields[4];
|
||||
break;
|
||||
default:
|
||||
error_log("Unknown Nokia phone '$_productName', assuming same as '6600'");
|
||||
$this->supportedFields = $defaultFields[4];
|
||||
break;
|
||||
}
|
||||
@ -363,17 +412,25 @@ class vcaladdressbook extends bocontacts
|
||||
switch(strtolower($_productName))
|
||||
{
|
||||
case 'sx1':
|
||||
$this->supportedFields = $defaultFields[3];
|
||||
break;
|
||||
default:
|
||||
error_log("Unknown Siemens phone '$_productName', assuming same as 'sx1'");
|
||||
$this->supportedFields = $defaultFields[3];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'sonyericsson':
|
||||
case 'sony ericsson':
|
||||
switch(strtolower($_productName))
|
||||
{
|
||||
case 'd750i':
|
||||
$this->supportedFields = $defaultFields[2];
|
||||
break;
|
||||
case 'p910i':
|
||||
default:
|
||||
error_log("unknown Sony Ericsson phone '$_productName', assuming same as 'd750i'");
|
||||
$this->supportedFields = $defaultFields[2];
|
||||
break;
|
||||
}
|
||||
@ -387,6 +444,7 @@ class vcaladdressbook extends bocontacts
|
||||
#$this->supportedFields['PHOTO'] = array('jpegphoto');
|
||||
break;
|
||||
default:
|
||||
error_log("Synthesis connector '$_productName', using default fields");
|
||||
$this->supportedFields = $defaultFields[0];
|
||||
break;
|
||||
}
|
||||
@ -398,7 +456,7 @@ class vcaladdressbook extends bocontacts
|
||||
|
||||
// the fallback for SyncML
|
||||
default:
|
||||
error_log("Client not found: $_productManufacturer $_productName");
|
||||
error_log("Client not found: '$_productManufacturer' '$_productName'");
|
||||
$this->supportedFields = $defaultFields[0];
|
||||
break;
|
||||
}
|
||||
@ -500,30 +558,6 @@ class vcaladdressbook extends bocontacts
|
||||
}
|
||||
break;
|
||||
|
||||
case 'CATEGORIES':
|
||||
#cat_id = 7,8
|
||||
$vcardData['category'] = array();
|
||||
if ($attributes['value'])
|
||||
{
|
||||
if (!is_object($this->cat))
|
||||
{
|
||||
if (!is_object($GLOBALS['egw']->categories))
|
||||
{
|
||||
$GLOBALS['egw']->categories =& CreateObject('phpgwapi.categories',$this->owner,'addressbook');
|
||||
}
|
||||
$this->cat =& $GLOBALS['egw']->categories;
|
||||
}
|
||||
foreach(explode(',',$attributes['value']) as $cat_name)
|
||||
{
|
||||
if (!($cat_id = $this->cat->name2id($cat_name)))
|
||||
{
|
||||
$cat_id = $this->cat->add( array('name' => $cat_name,'descr' => $cat_name ));
|
||||
}
|
||||
$vcardData['category'][] = $cat_id;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'VERSION':
|
||||
break;
|
||||
|
||||
@ -546,38 +580,30 @@ class vcaladdressbook extends bocontacts
|
||||
{
|
||||
if(!empty($fieldName))
|
||||
{
|
||||
$value = trim($vcardValues[$vcardKey]['values'][$fieldKey]);
|
||||
switch($fieldName)
|
||||
{
|
||||
case 'bday':
|
||||
if(!empty($vcardValues[$vcardKey]['values'][$fieldKey])) {
|
||||
$contact[$fieldName] = date('Y-m-d', $vcardValues[$vcardKey]['values'][$fieldKey]);
|
||||
if(!empty($value)) {
|
||||
$contact[$fieldName] = date('Y-m-d', $value);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'private':
|
||||
(int)$contact[$fieldName] = $vcardValues[$vcardKey]['values'][$fieldKey] == 'PRIVATE';
|
||||
(int)$contact[$fieldName] = $value == 'PRIVATE';
|
||||
break;
|
||||
|
||||
case 'cat_id':
|
||||
if (!is_object($this->cat)) {
|
||||
if (!is_object($GLOBALS['egw']->categories)) {
|
||||
$GLOBALS['egw']->categories =& CreateObject('phpgwapi.categories',$GLOBALS['egw_info']['user']['account_id'],'addressbook');
|
||||
}
|
||||
$this->cat =& $GLOBALS['egw']->categories;
|
||||
}
|
||||
foreach(explode(',',$vcardValues[$vcardKey]['values'][$fieldKey]) as $cat_name) {
|
||||
if (!($cat_id = $this->cat->name2id($cat_name))) {
|
||||
$cat_id = $this->cat->add( array('name' => $cat_name, 'descr' => $cat_name ));
|
||||
}
|
||||
$contact[$fieldName] = $cat_id;
|
||||
}
|
||||
$contact[$fieldName] = implode(",",$this->find_or_add_categories(explode(',',$value)));
|
||||
break;
|
||||
|
||||
case 'note':
|
||||
// note may contain ','s but maybe this needs to be fixed in vcard parser...
|
||||
$contact[$fieldName] = trim($vcardValues[$vcardKey]['value']);
|
||||
break;
|
||||
//$contact[$fieldName] = trim($vcardValues[$vcardKey]['value']);
|
||||
//break;
|
||||
|
||||
default:
|
||||
$contact[$fieldName] = trim($vcardValues[$vcardKey]['values'][$fieldKey]);
|
||||
$contact[$fieldName] = $value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -585,7 +611,7 @@ class vcaladdressbook extends bocontacts
|
||||
}
|
||||
}
|
||||
|
||||
$contact['n_fn'] = trim($contact['n_given'].' '.$contact['n_family']);
|
||||
$this->fixup_contact($contact);
|
||||
return $contact;
|
||||
}
|
||||
|
||||
|
@ -121,6 +121,21 @@ class bocalupdate extends bocal
|
||||
!$event['id'] && !$this->check_perms(EGW_ACL_EDIT,0,$event['owner'])) &&
|
||||
!$this->check_perms(EGW_ACL_ADD,0,$event['owner']))
|
||||
{
|
||||
// Just update the status, if the user is in the event already
|
||||
// is user is in both original and updated event
|
||||
$egw_event = $this->read($event['id']);
|
||||
|
||||
if ( isset($egw_event['participants'][$this->user])
|
||||
&& isset($event['participants'][$this->user]))
|
||||
{
|
||||
// Update their status in the event and say we're done.
|
||||
// Admittedly, this is false, it's dropping any changes on the floor,
|
||||
// But this will work better than dropping -everything- silently on
|
||||
// the floor
|
||||
$this->set_status($event['id'],'u',$this->user,$event['participants'][$this->user],0);
|
||||
unset($egw_event);
|
||||
return $event['id'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// check for conflicts only happens !$ignore_conflicts AND if start + end date are given
|
||||
@ -1017,4 +1032,65 @@ class bocalupdate extends bocal
|
||||
}
|
||||
return $this->so->delete_alarm($id);
|
||||
}
|
||||
|
||||
var $app_cat;
|
||||
var $glob_cat;
|
||||
|
||||
function find_or_add_categories($catname_list)
|
||||
{
|
||||
if (!is_object($this->glob_cat))
|
||||
{
|
||||
$this->glob_cat =& CreateObject('phpgwapi.categories',$GLOBALS['egw_info']['user']['account_id'],'phpgw');
|
||||
}
|
||||
|
||||
if (!is_object($this->app_cat))
|
||||
{
|
||||
$this->app_cat =& CreateObject('phpgwapi.categories',$GLOBALS['egw_info']['user']['account_id'],'calendar');
|
||||
}
|
||||
|
||||
$cat_id_list = array();
|
||||
foreach($catname_list as $cat_name)
|
||||
{
|
||||
$cat_name = trim($cat_name);
|
||||
if (!($cat_id = $this->glob_cat->name2id($cat_name))
|
||||
&& !($cat_id = $this->app_cat->name2id($cat_name)))
|
||||
{
|
||||
$cat_id = $this->app_cat->add( array('name' => $cat_name,'descr' => $cat_name ));
|
||||
}
|
||||
|
||||
$cat_id_list[] = $cat_id;
|
||||
}
|
||||
|
||||
if (count($cat_id_list) > 1)
|
||||
{
|
||||
sort($cat_id_list, SORT_NUMERIC);
|
||||
}
|
||||
return $cat_id_list;
|
||||
}
|
||||
|
||||
function get_categories($cat_id_list)
|
||||
{
|
||||
if (!is_object($this->glob_cat))
|
||||
{
|
||||
$this->glob_cat =& CreateObject('phpgwapi.categories',$GLOBALS['egw_info']['user']['account_id'],'phpgw');
|
||||
}
|
||||
|
||||
if (!is_object($this->app_cat))
|
||||
{
|
||||
$this->app_cat =& CreateObject('phpgwapi.categories',$GLOBALS['egw_info']['user']['account_id'],'calendar');
|
||||
}
|
||||
|
||||
$cat_list = array();
|
||||
foreach(explode(',',$cat_id_list) as $cat_id)
|
||||
{
|
||||
if ( ($cat_data = $this->glob_cat->return_single($cat_id))
|
||||
|| ($cat_data = $this->app_cat->return_single($cat_id)) )
|
||||
{
|
||||
$cat_list[] = $cat_data[0]['name'];
|
||||
}
|
||||
}
|
||||
|
||||
return $cat_list;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -117,24 +117,38 @@
|
||||
function &exportVCal($events,$version='1.0', $method='PUBLISH')
|
||||
{
|
||||
$egwSupportedFields = array(
|
||||
'CLASS' => array('dbName' => 'public'),
|
||||
'SUMMARY' => array('dbName' => 'title'),
|
||||
'CLASS' => array('dbName' => 'public'),
|
||||
'SUMMARY' => array('dbName' => 'title'),
|
||||
'DESCRIPTION' => array('dbName' => 'description'),
|
||||
'LOCATION' => array('dbName' => 'location'),
|
||||
'DTSTART' => array('dbName' => 'start'),
|
||||
'DTEND' => array('dbName' => 'end'),
|
||||
'ORGANIZER' => array('dbName' => 'owner'),
|
||||
'ATTENDEE' => array('dbName' => 'participants'),
|
||||
'RRULE' => array('dbName' => 'recur_type'),
|
||||
'EXDATE' => array('dbName' => 'recur_exception'),
|
||||
'PRIORITY' => array('dbName' => 'priority'),
|
||||
'TRANSP' => array('dbName' => 'non_blocking'),
|
||||
'LOCATION' => array('dbName' => 'location'),
|
||||
'DTSTART' => array('dbName' => 'start'),
|
||||
'DTEND' => array('dbName' => 'end'),
|
||||
'ORGANIZER' => array('dbName' => 'owner'),
|
||||
'ATTENDEE' => array('dbName' => 'participants'),
|
||||
'RRULE' => array('dbName' => 'recur_type'),
|
||||
'EXDATE' => array('dbName' => 'recur_exception'),
|
||||
'PRIORITY' => array('dbName' => 'priority'),
|
||||
'TRANSP' => array('dbName' => 'non_blocking'),
|
||||
'CATEGORIES' => array('dbName' => 'category'),
|
||||
);
|
||||
if(!is_array($this->supportedFields))
|
||||
{
|
||||
$this->setSupportedFields();
|
||||
}
|
||||
|
||||
if($this->productManufacturer == '' )
|
||||
{ // syncevolution is broken
|
||||
$version = "2.0";
|
||||
}
|
||||
|
||||
$palm_enddate_workaround=False;
|
||||
if($this->productManufacturer == 'Synthesis AG'
|
||||
&& strpos($this->productName, "PalmOS") )
|
||||
{
|
||||
// This workaround adds 1 day to the recur_enddate if it exists, to fix a palm bug
|
||||
$palm_enddate_workaround=True;
|
||||
}
|
||||
|
||||
$vcal = &new Horde_iCalendar;
|
||||
$vcal->setAttribute('PRODID','-//eGroupWare//NONSGML eGroupWare Calendar '.$GLOBALS['egw_info']['apps']['calendar']['version'].'//'.
|
||||
strtoupper($GLOBALS['egw_info']['user']['preferences']['common']['lang']));
|
||||
@ -186,7 +200,22 @@
|
||||
// PARTSTAT={NEEDS-ACTION|ACCEPTED|DECLINED|TENTATIVE|DELEGATED|COMPLETED|IN-PROGRESS} everything from delegated is NOT used by eGW atm.
|
||||
$status = $this->status_egw2ical[$status];
|
||||
// CUTYPE={INDIVIDUAL|GROUP|RESOURCE|ROOM|UNKNOWN}
|
||||
$cutype = $GLOBALS['egw']->accounts->get_type($uid) == 'g' ? 'GROUP' : 'INDIVIDUAL';
|
||||
switch (is_nummeric($uid) ? $GLOBALS['egw']->accounts->get_type($uid) : $uid{0})
|
||||
{
|
||||
case 'g':
|
||||
$cutype = 'GROUP';
|
||||
break;
|
||||
case 'r':
|
||||
$cutype = 'RESOURCE';
|
||||
break;
|
||||
case 'u':
|
||||
$cutype = 'INDIVIDUAL';
|
||||
break;
|
||||
default:
|
||||
$cutype = 'UNKNOWN';
|
||||
$cutype = 'INDIVIDUAL';
|
||||
break;
|
||||
};
|
||||
$parameters['ATTENDEE'][] = array(
|
||||
'CN' => $cn,
|
||||
'ROLE' => $role,
|
||||
@ -242,7 +271,20 @@
|
||||
$rrule['FREQ'] = $rrule['FREQ'].' '.$rrule['BYDAY'];
|
||||
break;
|
||||
}
|
||||
$rrule['UNTIL'] = ($event['recur_enddate']) ? date('Ymd',$event['recur_enddate']).'T'.date('His',$event['start']) : '#0';
|
||||
|
||||
if ($event['recur_enddate'])
|
||||
{
|
||||
$recur_enddate = (int)$event['recur_enddate'];
|
||||
if ($palm_enddate_workaround)
|
||||
{
|
||||
$recur_enddate += 86400;
|
||||
}
|
||||
$rrule['UNTIL'] = date('Ymd',$recur_enddate);
|
||||
}
|
||||
else
|
||||
{
|
||||
$rrule['UNTIL'] = '#0';
|
||||
}
|
||||
|
||||
$attributes['RRULE'] = $rrule['FREQ'].' '.$rrule['UNTIL'];
|
||||
} else {
|
||||
@ -289,7 +331,7 @@
|
||||
{
|
||||
$days[] = date('Ymd',$day);
|
||||
}
|
||||
$attributes['EXDATE'] = implode(';',$days);
|
||||
$attributes['EXDATE'] = implode(',',$days);
|
||||
$parameters['EXDATE']['VALUE'] = 'DATE';
|
||||
}
|
||||
break;
|
||||
@ -309,9 +351,10 @@
|
||||
case 'CATEGORIES':
|
||||
if ($event['category'])
|
||||
{
|
||||
$attributes['CATEGORIES'] = implode(',',$this->categories($event['category'],$nul));
|
||||
$attributes['CATEGORIES'] = implode(',',$this->get_categories($event['category']));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if ($event[$egwFieldInfo['dbName']]) // dont write empty fields
|
||||
{
|
||||
@ -394,6 +437,13 @@
|
||||
}
|
||||
//echo "supportedFields="; _debug_array($this->supportedFields);
|
||||
|
||||
$syncevo_enddate_fix = False;
|
||||
if( $this->productManufacturer == '' && $this->productName == '' )
|
||||
{
|
||||
// syncevolution needs an adjusted recur_enddate
|
||||
$syncevo_enddate_fix = True;
|
||||
}
|
||||
|
||||
$Ok = false; // returning false, if file contains no components
|
||||
foreach($vcal->getComponents() as $component)
|
||||
{
|
||||
@ -403,7 +453,10 @@
|
||||
#$event = array('participants' => array());
|
||||
$event = array();
|
||||
$alarms = array();
|
||||
$vcardData = array('recur_type' => 0);
|
||||
$vcardData = array(
|
||||
'recur_type' => MCAL_RECUR_NONE,
|
||||
'recur_exception' => array(),
|
||||
);
|
||||
|
||||
// lets see what we can get from the vcard
|
||||
foreach($component->_attributes as $attributes)
|
||||
@ -429,6 +482,11 @@
|
||||
$alarms[$alarmTime] = array(
|
||||
'time' => $alarmTime
|
||||
);
|
||||
} elseif (preg_match('/(........T......)$/',$attributes['value'],$matches)) {
|
||||
$alarmTime = $vcal->_parseDateTime($attributes['value']);
|
||||
$alarms[$alarmTime] = array(
|
||||
'time' => $alarmTime
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'CLASS':
|
||||
@ -440,7 +498,7 @@
|
||||
case 'DTEND':
|
||||
$dtend_ts = is_numeric($attributes['value']) ? $attributes['value'] : $this->date2ts($attributes['value']);
|
||||
if(date('H:i:s',$dtend_ts) == '00:00:00') {
|
||||
$dtend_ts--;
|
||||
$dtend_ts -= 60;
|
||||
}
|
||||
$vcardData['end'] = $dtend_ts;
|
||||
break;
|
||||
@ -458,9 +516,14 @@
|
||||
{
|
||||
$vcardData['recur_enddate'] = $vcal->_parseDateTime($matches[1]);
|
||||
}
|
||||
elseif (preg_match('/COUNT=([0-9]+)/',$recurence,$matches))
|
||||
{
|
||||
$vcardData['recur_count'] = (int)$matches[1];
|
||||
}
|
||||
if (preg_match('/INTERVAL=([0-9]+)/',$recurence,$matches))
|
||||
{
|
||||
$vcardData['recur_interval'] = (int) $matches[1];
|
||||
// 1 is invalid,, egw uses 0 for interval
|
||||
$vcardData['recur_interval'] = (int) $matches[1] != 0 ? (int) $matches[1] : 0;
|
||||
}
|
||||
$vcardData['recur_data'] = 0;
|
||||
switch($type)
|
||||
@ -492,6 +555,14 @@
|
||||
}
|
||||
$vcardData['recur_type'] = MCAL_RECUR_WEEKLY;
|
||||
}
|
||||
|
||||
if (!empty($vcardData['recur_count']))
|
||||
{
|
||||
$vcardData['recur_enddate'] = mktime(0,0,0,
|
||||
date('m',$vcardData['start']),
|
||||
date('d',$vcardData['start']) + ($vcardData['recur_interval']*($vcardData['recur_count']-1)*7),
|
||||
date('Y',$vcardData['start']));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'D': // 1.0
|
||||
@ -518,6 +589,14 @@
|
||||
// fall-through
|
||||
case 'DAILY': // 2.0
|
||||
$vcardData['recur_type'] = MCAL_RECUR_DAILY;
|
||||
|
||||
if (!empty($vcardData['recur_count']))
|
||||
{
|
||||
$vcardData['recur_enddate'] = mktime(0,0,0,
|
||||
date('m',$vcardData['start']),
|
||||
date('d',$vcardData['start']) + ($vcardData['recur_interval']*($vcardData['recur_count']-1)),
|
||||
date('Y',$vcardData['start']));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
@ -551,6 +630,14 @@
|
||||
case 'MONTHLY':
|
||||
$vcardData['recur_type'] = strpos($recurence,'BYDAY') !== false ?
|
||||
MCAL_RECUR_MONTHLY_WDAY : MCAL_RECUR_MONTHLY_MDAY;
|
||||
|
||||
if (!empty($vcardData['recur_count']))
|
||||
{
|
||||
$vcardData['recur_enddate'] = mktime(0,0,0,
|
||||
date('m',$vcardData['start']) + ($vcardData['recur_interval']*($vcardData['recur_count']-1)),
|
||||
date('d',$vcardData['start']),
|
||||
date('Y',$vcardData['start']));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Y': // 1.0
|
||||
@ -577,11 +664,24 @@
|
||||
// fall-through
|
||||
case 'YEARLY': // 2.0
|
||||
$vcardData['recur_type'] = MCAL_RECUR_YEARLY;
|
||||
|
||||
if (!empty($vcardData['recur_count']))
|
||||
{
|
||||
$vcardData['recur_enddate'] = mktime(0,0,0,
|
||||
date('m',$vcardData['start']),
|
||||
date('d',$vcardData['start']),
|
||||
date('Y',$vcardData['start']) + ($vcardData['recur_interval']*($vcardData['recur_count']-1)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if( $syncevo_enddate_fix && $vcardData['recur_enddate'] )
|
||||
{
|
||||
// Does syncevolution need to adjust recur_enddate
|
||||
$vcardData['recur_enddate'] = (int)$vcardData['recur_enddate'] + 86400;
|
||||
}
|
||||
break;
|
||||
case 'EXDATE':
|
||||
$vcardData['recur_exception'] = $attributes['value'];
|
||||
$vcardData['recur_exception'] = array_merge($vcardData['recur_exception'],$attributes['value']);
|
||||
break;
|
||||
case 'SUMMARY':
|
||||
$vcardData['title'] = $attributes['value'];
|
||||
@ -605,26 +705,14 @@
|
||||
$vcardData['priority'] = (int) $this->priority_ical2egw[$attributes['value']];
|
||||
break;
|
||||
case 'CATEGORIES':
|
||||
$vcardData['category'] = array();
|
||||
if ($attributes['value'])
|
||||
{
|
||||
if (!is_object($this->cat))
|
||||
{
|
||||
if (!is_object($GLOBALS['egw']->categories))
|
||||
{
|
||||
$GLOBALS['egw']->categories =& CreateObject('phpgwapi.categories',$this->owner,'calendar');
|
||||
}
|
||||
$this->cat =& $GLOBALS['egw']->categories;
|
||||
}
|
||||
foreach(explode(',',$attributes['value']) as $cat_name)
|
||||
{
|
||||
if (!($cat_id = $this->cat->name2id($cat_name)))
|
||||
{
|
||||
$cat_id = $this->cat->add( array('name' => $cat_name,'descr' => $cat_name ));
|
||||
}
|
||||
$vcardData['category'][] = $cat_id;
|
||||
}
|
||||
$vcardData['category'] = $this->find_or_add_categorie(explode(',',$attributes['value']));
|
||||
}
|
||||
else
|
||||
{
|
||||
$vcardData['category'] = array();
|
||||
}
|
||||
break;
|
||||
case 'ATTENDEE':
|
||||
if (preg_match('/MAILTO:([@.a-z0-9_-]+)/i',$attributes['value'],$matches) &&
|
||||
@ -734,6 +822,38 @@
|
||||
$event['participants'] = array($GLOBALS['egw_info']['user']['account_id'] => 'A');
|
||||
}
|
||||
|
||||
// If this is an updated meeting, and the client doesn't support
|
||||
// participants, add them back
|
||||
if( $cal_id >0 && !isset($this->supportedFields['participants']))
|
||||
{
|
||||
$egw_event = $this->read($cal_id);
|
||||
if ($egw_event)
|
||||
{
|
||||
$event['participants'] = $egw_event['participants'];
|
||||
$event['participant_types'] = $egw_event['participant_types'];
|
||||
}
|
||||
}
|
||||
|
||||
// Check for resources, and don't remove them
|
||||
if( $cal_id > 0 )
|
||||
{
|
||||
// for each existing participant:
|
||||
$egw_event = $this->read($cal_id);
|
||||
if ( $egw_event )
|
||||
{
|
||||
foreach( $egw_event['participants'] as $uid => $status )
|
||||
{
|
||||
// Is it a resource?
|
||||
if ( preg_match("/^r(.*)/", $uid, $matches) )
|
||||
{
|
||||
// Add it back in
|
||||
$event['participants'][$uid] = 'A';
|
||||
$event['participant_types']['r'][$matches[1]] = 'A';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#error_log('ALARMS');
|
||||
#error_log(print_r($event, true));
|
||||
|
||||
@ -773,28 +893,55 @@
|
||||
$this->productManufacturer = $_productManufacturer;
|
||||
$this->productName = $_productName;
|
||||
|
||||
$defaultFields[0] = array('public' => 'public', 'description' => 'description', 'end' => 'end',
|
||||
'start' => 'start', 'location' => 'location', 'recur_type' => 'recur_type',
|
||||
'recur_interval' => 'recur_interval', 'recur_data' => 'recur_data', 'recur_enddate' => 'recur_enddate',
|
||||
'title' => 'title', 'priority' => 'priority', 'alarms' => 'alarms',
|
||||
$defaultFields['minimal'] = array(
|
||||
'public' => 'public',
|
||||
'description' => 'description',
|
||||
'end' => 'end',
|
||||
'start' => 'start',
|
||||
'location' => 'location',
|
||||
'recur_type' => 'recur_type',
|
||||
'recur_interval' => 'recur_interval',
|
||||
'recur_data' => 'recur_data',
|
||||
'recur_enddate' => 'recur_enddate',
|
||||
'title' => 'title',
|
||||
'alarms' => 'alarms',
|
||||
);
|
||||
|
||||
$defaultFields['basic'] = $defaultFields['minimal'] + array(
|
||||
'recur_exception' => 'recur_exception',
|
||||
'priority' => 'priority',
|
||||
);
|
||||
|
||||
$defaultFields['nexthaus'] = $defaultFields['basic'] + array(
|
||||
'participants' => 'participants',
|
||||
);
|
||||
|
||||
$defaultFields[1] = array('public' => 'public', 'description' => 'description', 'end' => 'end',
|
||||
'start' => 'start', 'location' => 'location', 'recur_type' => 'recur_type',
|
||||
'recur_interval' => 'recur_interval', 'recur_data' => 'recur_data', 'recur_enddate' => 'recur_enddate',
|
||||
'title' => 'title', 'alarms' => 'alarms',
|
||||
|
||||
$defaultFields['synthesis'] = $defaultFields['basic'] + array(
|
||||
'non_blocking' => 'non_blocking',
|
||||
'category' => 'category',
|
||||
);
|
||||
|
||||
$defaultFields['evolution'] = $defaultFields['basic'] + array(
|
||||
'participants' => 'participants',
|
||||
'owner' => 'owner',
|
||||
'category' => 'category',
|
||||
);
|
||||
|
||||
$defaultFields['full'] = $defaultFields['basic'] + array(
|
||||
'participants' => 'participants',
|
||||
'owner' => 'owner',
|
||||
'category' => 'category',
|
||||
'non_blocking' => 'non_blocking',
|
||||
);
|
||||
|
||||
|
||||
switch(strtolower($_productManufacturer))
|
||||
{
|
||||
case 'nexthaus corporation':
|
||||
switch(strtolower($_productName))
|
||||
{
|
||||
default:
|
||||
$this->supportedFields = $defaultFields[0] + array('participants' => 'participants');
|
||||
#$this->supportedFields = $defaultFields;
|
||||
$this->supportedFields = $defaultFields['nexthaus'];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -805,7 +952,7 @@
|
||||
switch(strtolower($_productName))
|
||||
{
|
||||
default:
|
||||
$this->supportedFields = $defaultFields[0];
|
||||
$this->supportedFields = $defaultFields['basic'];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -814,18 +961,26 @@
|
||||
switch(strtolower($_productName))
|
||||
{
|
||||
case 'e61':
|
||||
$this->supportedFields = $defaultFields['minimal'];
|
||||
break;
|
||||
default:
|
||||
$this->supportedFields = $defaultFields[1];
|
||||
error_log("Unknown Nokia phone '$_productName', assuming E61");
|
||||
$this->supportedFields = $defaultFields['minimal'];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'sonyericsson':
|
||||
case 'sony ericsson':
|
||||
switch(strtolower($_productName))
|
||||
{
|
||||
case 'd750i':
|
||||
case 'p910i':
|
||||
$this->supportedFields = $defaultFields['basic'];
|
||||
break;
|
||||
default:
|
||||
$this->supportedFields = $defaultFields[0];
|
||||
error_log("Unknown Sony Ericsson phone '$_productName' assuming d750i");
|
||||
$this->supportedFields = $defaultFields['basic'];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -834,41 +989,35 @@
|
||||
switch(strtolower($_productName))
|
||||
{
|
||||
default:
|
||||
$this->supportedFields = $defaultFields[0] + array(
|
||||
'recur_exception' => 'recur_exception',
|
||||
'non_blocking' => 'non_blocking',
|
||||
);
|
||||
$this->supportedFields = $defaultFields['synthesis'];
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
//Syncevolution compatibility
|
||||
case 'patrick ohly':
|
||||
$this->supportedFields = $defaultFields[1] + array(
|
||||
'participants' => 'participants',
|
||||
'owner' => 'owner',
|
||||
'category' => 'category',
|
||||
);
|
||||
$this->supportedFields = $defaultFields['evolution'];
|
||||
break;
|
||||
|
||||
case '': // seems syncevolution 0.5 doesn't send a manufacturer
|
||||
error_log("No vendor name, assuming syncevolution 0.5");
|
||||
$this->supportedFields = $defaultFields['evolution'];
|
||||
break;
|
||||
|
||||
case 'file': // used outside of SyncML, eg. by the calendar itself ==> all possible fields
|
||||
$this->supportedFields = $defaultFields[0] + array(
|
||||
'participants' => 'participants',
|
||||
'owner' => 'owner',
|
||||
'non_blocking' => 'non_blocking',
|
||||
'category' => 'category',
|
||||
);
|
||||
$this->supportedFields = $defaultFields['full'];
|
||||
break;
|
||||
|
||||
// the fallback for SyncML
|
||||
default:
|
||||
error_log("Client not found: $_productManufacturer $_productName");
|
||||
$this->supportedFields = $defaultFields[0];
|
||||
error_log("Unknown calendar SyncML client: manufacturer='$_productManufacturer' product='$_productName'");
|
||||
$this->supportedFields = $defaultFields['full'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function icaltoegw($_vcalData) {
|
||||
function icaltoegw($_vcalData)
|
||||
{
|
||||
// our (patched) horde classes, do NOT unfold folded lines, which causes a lot trouble in the import
|
||||
$_vcalData = preg_replace("/[\r\n]+ /",'',$_vcalData);
|
||||
|
||||
@ -1043,26 +1192,14 @@
|
||||
}
|
||||
break;
|
||||
case 'CATEGORIES':
|
||||
$vcardData['category'] = array();
|
||||
if ($attributes['value'])
|
||||
{
|
||||
if (!is_object($this->cat))
|
||||
{
|
||||
if (!is_object($GLOBALS['egw']->categories))
|
||||
{
|
||||
$GLOBALS['egw']->categories =& CreateObject('phpgwapi.categories',$this->owner,'calendar');
|
||||
}
|
||||
$this->cat =& $GLOBALS['egw']->categories;
|
||||
}
|
||||
foreach(explode(',',$attributes['value']) as $cat_name)
|
||||
{
|
||||
if (!($cat_id = $this->cat->name2id($cat_name)))
|
||||
{
|
||||
$cat_id = $this->cat->add( array('name' => $cat_name,'descr' => $cat_name ));
|
||||
}
|
||||
$vcardData['category'][] = $cat_id;
|
||||
}
|
||||
}
|
||||
$vcardData['category'] = $this->find_or_add_categories(explode(',',$attributes['value']));
|
||||
}
|
||||
else
|
||||
{
|
||||
$vcardData['category'] = array();
|
||||
}
|
||||
break;
|
||||
case 'ATTENDEE':
|
||||
if (preg_match('/MAILTO:([@.a-z0-9_-]+)/i',$attributes['value'],$matches) &&
|
||||
@ -1114,6 +1251,10 @@
|
||||
{
|
||||
switch($fieldName)
|
||||
{
|
||||
case 'recur_interval':
|
||||
case 'recur_enddate':
|
||||
case 'recur_data':
|
||||
case 'recur_exception':
|
||||
case 'alarms':
|
||||
// not handled here
|
||||
break;
|
||||
@ -1129,17 +1270,12 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($supportedFields['recur_type']);
|
||||
unset($supportedFields['recur_interval']);
|
||||
unset($supportedFields['recur_enddate']);
|
||||
unset($supportedFields['recur_data']);
|
||||
break;
|
||||
default:
|
||||
if (isset($vcardData[$fieldName]))
|
||||
{
|
||||
$event[$fieldName] = $vcardData[$fieldName];
|
||||
}
|
||||
unset($supportedFields[$fieldName]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1212,20 +1348,24 @@
|
||||
{
|
||||
$vfreebusy->setAttribute($attr, $value, $parameters[$name]);
|
||||
}
|
||||
foreach(parent::search(array(
|
||||
'start' => $this->now_su,
|
||||
'end' => $end,
|
||||
'users' => $user,
|
||||
'date_format' => 'server',
|
||||
'show_rejected' => false,
|
||||
)) as $event)
|
||||
$fbdata = parent::search(array(
|
||||
'start' => $this->now_su,
|
||||
'end' => $end,
|
||||
'users' => $user,
|
||||
'date_format' => 'server',
|
||||
'show_rejected' => false,
|
||||
));
|
||||
if (is_array($fbdata))
|
||||
{
|
||||
if ($event['non_blocking']) continue;
|
||||
foreach ($fbdata as $event)
|
||||
{
|
||||
if ($event['non_blocking']) continue;
|
||||
|
||||
$vfreebusy->setAttribute('FREEBUSY',array(array(
|
||||
'start' => $event['start'],
|
||||
'end' => $event['end'],
|
||||
)));
|
||||
$vfreebusy->setAttribute('FREEBUSY',array(array(
|
||||
'start' => $event['start'],
|
||||
'end' => $event['end'],
|
||||
)));
|
||||
}
|
||||
}
|
||||
$vcal->addComponent($vfreebusy);
|
||||
|
||||
|
@ -71,7 +71,7 @@
|
||||
}
|
||||
|
||||
function endElement($_parser, $_tag) {
|
||||
#error_log($_tag .' => '. $this->sifData);
|
||||
//error_log('endElem: ' . $_tag .' => '. trim($this->sifData));
|
||||
if(!empty($this->sifMapping[$_tag])) {
|
||||
$this->event[$this->sifMapping[$_tag]] = trim($this->sifData);
|
||||
}
|
||||
@ -128,19 +128,7 @@
|
||||
|
||||
case 'category':
|
||||
if(!empty($value)) {
|
||||
$egwCategories =& CreateObject('phpgwapi.categories', $GLOBALS['egw_info']['user']['account_id'], 'calendar');
|
||||
$categories = explode(';',$value);
|
||||
foreach($categories as $categorieName) {
|
||||
$cat_id = false;
|
||||
$categorieName = trim($categorieName);
|
||||
if(!($cat_id = $egwCategories->name2id($categorieName))) {
|
||||
$cat_id = $egwCategories->add(array('name' => $categorieName, 'descr' => lang('added by synchronisation')));
|
||||
}
|
||||
if($cat_id) {
|
||||
if(!empty($finalEvent[$key])) $finalEvent[$key] .= ',';
|
||||
$finalEvent[$key] .= $cat_id;
|
||||
}
|
||||
}
|
||||
$finalEvent[$key] = implode(',',$this->find_or_add_categories(explode(';', $value)));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -148,6 +136,7 @@
|
||||
case 'start':
|
||||
if($this->event['alldayevent'] < 1) {
|
||||
$finalEvent[$key] = $vcal->_parseDateTime($value);
|
||||
error_log("event ".$key." val=".$value.", parsed=".$finalEvent[$key]);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -348,15 +337,8 @@
|
||||
{
|
||||
case 'Categories':
|
||||
if(!empty($value)) {
|
||||
$egwCategories =& CreateObject('phpgwapi.categories',$GLOBALS['egw_info']['user']['account_id'],'calendar');
|
||||
$categories = explode(',',$value);
|
||||
$value = '';
|
||||
foreach($categories as $cat_id) {
|
||||
if($catData = $egwCategories->return_single($cat_id)) {
|
||||
if(!empty($value)) $value .= '; ';
|
||||
$value .= $GLOBALS['egw']->translation->convert($catData[0]['name'], $sysCharSet, 'utf-8');
|
||||
}
|
||||
}
|
||||
$value = implode('; ', $this->get_categories(explode(',',$value)));
|
||||
$value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8');
|
||||
}
|
||||
$sifEvent .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
|
@ -563,7 +563,7 @@ ORDER BY cal_user_type, cal_usre_id
|
||||
$exceptions = $event['recur_exception'] ? explode(',',$event['recur_exception']) : array();
|
||||
$set_recurrences = $event['recur_type'] != $old_recur['recur_type'] || $event['recur_data'] != $old_recur['recur_data'] ||
|
||||
$event['recur_interval'] != $old_recur['recur_interval'] || $event['recur_enddate'] != $old_recur['recur_enddate'] ||
|
||||
count(array_diff($old_exceptions,$exceptions)); // exception deleted
|
||||
count(array_diff($old_exceptions,$exceptions)) || count(array_diff($exceptions, $old_exceptions)); // exception deleted or added
|
||||
}
|
||||
if($event['recur_type'] != MCAL_RECUR_NONE)
|
||||
{
|
||||
|
@ -1270,7 +1270,75 @@ class boinfolog
|
||||
}
|
||||
return $icons;
|
||||
}
|
||||
|
||||
|
||||
var $app_cat;
|
||||
var $glob_cat;
|
||||
|
||||
function find_or_add_categories($catname_list)
|
||||
{
|
||||
if (!is_object($this->glob_cat))
|
||||
{
|
||||
if (!is_object($GLOBALS['egw']->categories))
|
||||
{
|
||||
$GLOBALS['egw']->categories =& CreateObject('phpgwapi.categories',$GLOBALS['egw_info']['user']['account_id'],'phpgw');
|
||||
}
|
||||
$this->glob_cat =& $GLOBALS['egw']->categories;
|
||||
}
|
||||
|
||||
if (!is_object($this->app_cat))
|
||||
{
|
||||
$this->app_cat =& CreateObject('phpgwapi.categories',$GLOBALS['egw_info']['user']['account_id'],'infolog');
|
||||
}
|
||||
|
||||
$cat_id_list = array();
|
||||
foreach($catname_list as $cat_name)
|
||||
{
|
||||
$cat_name = trim($cat_name);
|
||||
if (!($cat_id = $this->glob_cat->name2id($cat_name))
|
||||
&& !($cat_id = $this->app_cat->name2id($cat_name)))
|
||||
{
|
||||
$cat_id = $this->app_cat->add( array('name' => $cat_name,'descr' => $cat_name ));
|
||||
}
|
||||
|
||||
$cat_id_list[] = $cat_id;
|
||||
}
|
||||
|
||||
if (count($cat_id_list) > 1)
|
||||
{
|
||||
sort($cat_id_list, SORT_NUMERIC);
|
||||
}
|
||||
return $cat_id_list;
|
||||
}
|
||||
|
||||
function get_categories($cat_id_list)
|
||||
{
|
||||
if (!is_object($this->glob_cat))
|
||||
{
|
||||
if (!is_object($GLOBALS['egw']->categories))
|
||||
{
|
||||
$GLOBALS['egw']->categories =& CreateObject('phpgwapi.categories',$GLOBALS['egw_info']['user']['account_id'],'phpgw');
|
||||
}
|
||||
$this->glob_cat =& $GLOBALS['egw']->categories;
|
||||
}
|
||||
|
||||
if (!is_object($this->app_cat))
|
||||
{
|
||||
$this->app_cat =& CreateObject('phpgwapi.categories',$GLOBALS['egw_info']['user']['account_id'],'infolog');
|
||||
}
|
||||
|
||||
$cat_list = array();
|
||||
foreach(explode(',',$cat_id_list) as $cat_id)
|
||||
{
|
||||
if ( ($cat_data = $this->glob_cat->return_single($cat_id))
|
||||
|| ($cat_data = $this->app_cat->return_single($cat_id)) )
|
||||
{
|
||||
$cat_list[] = $cat_data[0]['name'];
|
||||
}
|
||||
}
|
||||
|
||||
return $cat_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send all async infolog notification
|
||||
*
|
||||
@ -1352,3 +1420,4 @@ class boinfolog
|
||||
$GLOBALS['egw_info']['user']['preferences'] = $save_prefs;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,12 +21,24 @@
|
||||
// array containing the current mappings(task or note)
|
||||
var $_currentSIFMapping;
|
||||
|
||||
var $_sifNoteMapping = array(
|
||||
'Body' => 'info_des',
|
||||
'Categories' => 'info_cat',
|
||||
'Color' => '',
|
||||
'Date' => 'info_startdate',
|
||||
'Height' => '',
|
||||
'Left' => '',
|
||||
'Subject' => 'info_subject',
|
||||
'Top' => '',
|
||||
'Width' => '',
|
||||
);
|
||||
|
||||
// mappings for SIFTask to InfologTask
|
||||
var $_sifTaskMapping = array(
|
||||
'ActualWork' => '',
|
||||
'BillingInformation' => '',
|
||||
'Body' => 'info_des',
|
||||
'Categories' => '',
|
||||
'Categories' => 'info_cat',
|
||||
'Companies' => '',
|
||||
'Complete' => '',
|
||||
'DateCompleted' => 'info_datecompleted',
|
||||
@ -61,8 +73,9 @@
|
||||
}
|
||||
|
||||
function endElement($_parser, $_tag) {
|
||||
error_log("infolog: tag=$_tag data=".trim($this->sifData));
|
||||
if(!empty($this->_currentSIFMapping[$_tag])) {
|
||||
$this->_extractedSIFData[$this->_currentSIFMapping[$_tag]] = $this->sifData;
|
||||
$this->_extractedSIFData[$this->_currentSIFMapping[$_tag]] = trim($this->sifData);
|
||||
}
|
||||
unset($this->sifData);
|
||||
}
|
||||
@ -81,7 +94,18 @@
|
||||
#fwrite($handle, $sifData);
|
||||
#fclose($handle);
|
||||
|
||||
$this->_currentSIFMapping = $this->_sifTaskMapping;
|
||||
switch ($_sifType)
|
||||
{
|
||||
case 'note':
|
||||
$this->_currentSIFMapping = $this->_sifNoteMapping;
|
||||
break;
|
||||
|
||||
case 'task':
|
||||
default:
|
||||
$this->_currentSIFMapping = $this->_sifTaskMapping;
|
||||
break;
|
||||
}
|
||||
|
||||
$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);
|
||||
@ -108,6 +132,8 @@
|
||||
|
||||
foreach($this->_extractedSIFData as $key => $value) {
|
||||
$value = $GLOBALS['egw']->translation->convert($value, 'utf-8', $sysCharSet);
|
||||
error_log("infolog key=$key => value=$value");
|
||||
|
||||
switch($key) {
|
||||
case 'info_access':
|
||||
$taskData[$key] = ((int)$value > 0) ? 'private' : 'public';
|
||||
@ -127,6 +153,13 @@
|
||||
break;
|
||||
|
||||
|
||||
case 'info_cat':
|
||||
if (!empty($value)) {
|
||||
$categories = $this->find_or_add_categories(explode(';', $value));
|
||||
$taskData['info_cat'] = $categories[0];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'info_priority':
|
||||
$taskData[$key] = (int)$value;
|
||||
break;
|
||||
@ -156,11 +189,52 @@
|
||||
$taskData[$key] = $value;
|
||||
break;
|
||||
}
|
||||
error_log("infolog task key=$key => value=".$taskData[$key]);
|
||||
}
|
||||
|
||||
return $taskData;
|
||||
break;
|
||||
|
||||
case 'note':
|
||||
$noteData = array();
|
||||
$noteData['info_type'] = 'note';
|
||||
$vcal = &new Horde_iCalendar;
|
||||
|
||||
foreach($this->_extractedSIFData as $key => $value)
|
||||
{
|
||||
$value = $GLOBALS['egw']->translation->convert($value, 'utf-8', $sysCharSet);
|
||||
|
||||
error_log("infolog client key=$key => value=".$value);
|
||||
switch ($key)
|
||||
{
|
||||
case 'info_startdate':
|
||||
if(!empty($value)) {
|
||||
$noteData[$key] = $vcal->_parseDateTime($value);
|
||||
// somehow the client always deliver a timestamp about 3538 seconds, when no startdate set.
|
||||
if($noteData[$key] < 10000)
|
||||
$noteData[$key] = '';
|
||||
} else {
|
||||
$noteData[$key] = '';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'info_cat':
|
||||
if (!empty($value)) {
|
||||
$categories = $this->find_or_add_categories(explode(';', $value));
|
||||
$taskData['info_cat'] = $categories[0];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
$noteData[$key] = $value;
|
||||
break;
|
||||
}
|
||||
error_log("infolog note key=$key => value=".$noteData[$key]);
|
||||
}
|
||||
return $noteData;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@ -251,6 +325,15 @@
|
||||
$sifTask .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
|
||||
case 'Categories':
|
||||
if (!empty($value))
|
||||
{
|
||||
$value = implode('; ', $this->get_categories(array($value)));
|
||||
$value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8');
|
||||
}
|
||||
$sifTask .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
|
||||
default:
|
||||
$sifTask .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
@ -296,6 +379,52 @@
|
||||
}
|
||||
break;
|
||||
|
||||
case 'note':
|
||||
if($taskData = $this->read($_id)) {
|
||||
$sysCharSet = $GLOBALS['egw']->translation->charset();
|
||||
$vcal = &new Horde_iCalendar;
|
||||
|
||||
$sifNote = '<note>';
|
||||
|
||||
foreach($this->_sifNoteMapping as $sifField => $egwField)
|
||||
{
|
||||
if(empty($egwField)) continue;
|
||||
|
||||
$value = $GLOBALS['egw']->translation->convert($taskData[$egwField], $sysCharSet, 'utf-8');
|
||||
|
||||
switch($sifField) {
|
||||
case 'Date':
|
||||
if(!empty($value)) {
|
||||
$value = $vcal->_exportDateTime($value);
|
||||
}
|
||||
$sifNote .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
|
||||
case 'Body':
|
||||
$value = $GLOBALS['egw']->translation->convert($taskData['info_subject'], $sysCharSet, 'utf-8') . "\n" . $value;
|
||||
$sifNote .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
|
||||
case 'Categories':
|
||||
if (!empty($value))
|
||||
{
|
||||
$value = implode('; ', $this->get_categories(array($value)));
|
||||
$value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8');
|
||||
}
|
||||
$sifNote .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
$sifNote .= "<$sifField>$value</$sifField>";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return base64_encode($sifNote);
|
||||
}
|
||||
break;
|
||||
|
||||
default;
|
||||
return false;
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ class soinfolog // DB-Layer
|
||||
*/
|
||||
function aclFilter($filter = False)
|
||||
{
|
||||
preg_match('/(my|responsible|delegated|own|privat|all|none|user)([0-9]*)/',$filter_was=$filter,$vars);
|
||||
preg_match('/(my|responsible|delegated|own|privat|private|all|none|user)([0-9]*)/',$filter_was=$filter,$vars);
|
||||
$filter = $vars[1];
|
||||
$f_user = intval($vars[2]);
|
||||
|
||||
@ -230,7 +230,7 @@ class soinfolog // DB-Layer
|
||||
$filtermethod .= " OR (".$this->responsible_filter($this->user)." AND info_access='public')";
|
||||
|
||||
// private: own entries plus the one user is responsible for
|
||||
if ($filter == 'private' || $filter == 'own')
|
||||
if ($filter == 'private' || $filter == 'privat' || $filter == 'own')
|
||||
{
|
||||
$filtermethod .= " OR (".$this->responsible_filter($this->user).
|
||||
($filter == 'own' && count($public_user_list) ? // offer's should show up in own, eg. startpage, but need read-access
|
||||
|
@ -86,6 +86,12 @@
|
||||
$this->status2vtodo[$taskData['info_status']] : 'NEEDS-ACTION');
|
||||
$vevent->setAttribute('PRIORITY',$this->egw_priority2vcal_priority[$taskData['info_priority']]);
|
||||
|
||||
if (!empty($taskData['info_cat']))
|
||||
{
|
||||
$cats = $this->get_categories(array($taskData['info_cat']));
|
||||
$vevent->setAttribute('CATEGORIES', $cats[0]);
|
||||
}
|
||||
|
||||
#$vevent->setAttribute('TRANSP','OPAQUE');
|
||||
# status
|
||||
# ATTENDEE
|
||||
@ -122,7 +128,8 @@
|
||||
return $this->write($taskData);
|
||||
}
|
||||
|
||||
function searchVTODO($_vcalData) {
|
||||
function searchVTODO($_vcalData)
|
||||
{
|
||||
if(!$egwData = $this->vtodotoegw($_vcalData)) {
|
||||
return false;
|
||||
}
|
||||
@ -140,7 +147,8 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
function vtodotoegw($_vcalData) {
|
||||
function vtodotoegw($_vcalData)
|
||||
{
|
||||
$vcal = &new Horde_iCalendar;
|
||||
if(!$vcal->parsevCalendar($_vcalData)) {
|
||||
return FALSE;
|
||||
@ -196,6 +204,13 @@
|
||||
case 'SUMMARY':
|
||||
$taskData['info_subject'] = $attributes['value'];
|
||||
break;
|
||||
|
||||
case 'CATEGORIES':
|
||||
{
|
||||
$cats = $this->find_or_add_categories(explode(',', $attributes['value']));
|
||||
$taskData['info_cat'] = $cats[0];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
# the horde ical class does already convert in parsevCalendar
|
||||
@ -207,4 +222,147 @@
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
function exportVNOTE($_noteID, $_type)
|
||||
{
|
||||
$note = $this->read($_noteID);
|
||||
$note = $GLOBALS['egw']->translation->convert($note, $GLOBALS['egw']->translation->charset(), 'UTF-8');
|
||||
|
||||
switch($_type)
|
||||
{
|
||||
case 'text/plain':
|
||||
$txt = $note['info_subject']."\n\n".$note['info_des'];
|
||||
return $txt;
|
||||
break;
|
||||
|
||||
case 'text/x-vnote':
|
||||
$noteGUID = $GLOBALS['egw']->common->generate_uid('infolog_note',$_noteID);
|
||||
$vnote = &new Horde_iCalendar_vnote();
|
||||
$vNote->setAttribute('VERSION', '1.1');
|
||||
$vnote->setAttribute('SUMMARY',$note['info_subject']);
|
||||
$vnote->setAttribute('BODY',$note['info_des']);
|
||||
if($note['info_startdate'])
|
||||
$vnote->setAttribute('DCREATED',$note['info_startdate']);
|
||||
$vnote->setAttribute('DCREATED',$GLOBALS['egw']->contenthistory->getTSforAction($eventGUID,'add'));
|
||||
$vnote->setAttribute('LAST-MODIFIED',$GLOBALS['egw']->contenthistory->getTSforAction($eventGUID,'modify'));
|
||||
if (!empty($note['info_cat']))
|
||||
{
|
||||
$cats = $this->get_categories(array($note['info_cat']));
|
||||
$vnote->setAttribute('CATEGORIES', $cats[0]);
|
||||
}
|
||||
|
||||
#$vnote->setAttribute('UID',$noteGUID);
|
||||
#$vnote->setAttribute('CLASS',$taskData['info_access'] == 'public' ? 'PUBLIC' : 'PRIVATE');
|
||||
|
||||
#$options = array('CHARSET' => 'UTF-8','ENCODING' => 'QUOTED-PRINTABLE');
|
||||
#$vnote->setParameter('SUMMARY', $options);
|
||||
#$vnote->setParameter('DESCRIPTION', $options);
|
||||
|
||||
return $vnote->exportvCalendar();
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function importVNOTE(&$_vcalData, $_type, $_noteID = -1)
|
||||
{
|
||||
if(!$note = $this->vnotetoegw($_vcalData, $_type))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if($_noteID > 0)
|
||||
{
|
||||
$note['info_id'] = $_noteID;
|
||||
}
|
||||
|
||||
if(empty($note['info_status'])) {
|
||||
$note['info_status'] = 'done';
|
||||
}
|
||||
|
||||
#_debug_array($taskData);exit;
|
||||
return $this->write($note);
|
||||
}
|
||||
|
||||
function searchVNOTE($_vcalData, $_type)
|
||||
{
|
||||
if(!$note = $this->vnotetoegw($_vcalData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$filter = array('col_filter' => $egwData);
|
||||
if($foundItems = $this->search($filter)) {
|
||||
if(count($foundItems) > 0) {
|
||||
$itemIDs = array_keys($foundItems);
|
||||
return $itemIDs[0];
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function vnotetoegw($_data, $_type)
|
||||
{
|
||||
switch($_type)
|
||||
{
|
||||
case 'text/plain':
|
||||
$note = array();
|
||||
$note['info_type'] = 'note';
|
||||
$botranslation =& CreateObject('phpgwapi.translation');
|
||||
$txt = $botranslation->convert($_data, 'utf-8');
|
||||
$txt = str_replace("\r\n", "\n", $txt);
|
||||
|
||||
if (preg_match("/^(^\n)\n\n(.*)$/", $txt, $match))
|
||||
{
|
||||
$note['info_subject'] = $match[0];
|
||||
$note['info_des'] = $match[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
$note['info_des'] = $txt;
|
||||
}
|
||||
|
||||
return $note;
|
||||
break;
|
||||
|
||||
case 'text/x-vnote':
|
||||
$vnote = &new Horde_iCalendar;
|
||||
if (!$vcal->parsevCalendar($_data))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
$components = $vnote->getComponent();
|
||||
if(count($components) > 0)
|
||||
{
|
||||
$component = $components[0];
|
||||
if(is_a($component, 'Horde_iCalendar_vnote'))
|
||||
{
|
||||
$note = array();
|
||||
$note['info_type'] = 'note';
|
||||
|
||||
foreach($component->_attributes as $attribute)
|
||||
{
|
||||
switch ($attribute['name'])
|
||||
{
|
||||
case 'BODY':
|
||||
$note['info_des'] = $attribute['value'];
|
||||
break;
|
||||
case 'SUMMARY':
|
||||
$note['info_subject'] = $attribute['value'];
|
||||
break;
|
||||
case 'CATEGORIES':
|
||||
{
|
||||
$cats = $this->find_or_add_categories(explode(',', $attribute['value']));
|
||||
$note['info_cat'] = $cats[0];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $note;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,6 +134,49 @@ class Horde_SyncML_Command_Put extends Horde_SyncML_Command {
|
||||
switch($element) {
|
||||
case 'CTType':
|
||||
$this->_contentType = trim($this->_chars);
|
||||
if (substr($this->_contentType, 0, 14) == "text/x-s4j-sif")
|
||||
{
|
||||
// workaround a little bug in sync4j for mobile v3.1.3 (and possibly others)
|
||||
// where the content-type is set to just one value regardless of
|
||||
// the source... this further leads to a failure to send updates
|
||||
// by the server since it does not know how to convert say tasks to text/x-s4j-sifc
|
||||
// (it should be text/x-s4j-sift).
|
||||
switch ($this->_sourceReference)
|
||||
{
|
||||
case 'contact':
|
||||
if ($this->_contentType != "text/x-s4j-sifc")
|
||||
{
|
||||
error_log("forcing 'contact' content type to 'text/x-s4j-sifc' instead of '".$this->_contentType."'");
|
||||
$this->_contentType = "text/x-s4j-sifc";
|
||||
}
|
||||
break;
|
||||
case 'calendar':
|
||||
case 'appointment':
|
||||
if ($this->_contentType != "text/x-s4j-sife")
|
||||
{
|
||||
error_log("forcing 'calendar' content type to 'text/x-s4j-sife' instead of '".$this->_contentType."'");
|
||||
$this->_contentType = "text/x-s4j-sife";
|
||||
}
|
||||
break;
|
||||
case 'task':
|
||||
if ($this->_contentType != "text/x-s4j-sift")
|
||||
{
|
||||
error_log("forcing 'task' content type to 'text/x-s4j-sift' instead of '".$this->_contentType."'");
|
||||
$this->_contentType = "text/x-s4j-sift";
|
||||
}
|
||||
break;
|
||||
case 'note':
|
||||
if ($this->_contentType != "text/x-s4j-sifn")
|
||||
{
|
||||
error_log("forcing 'note' content type to 'text/x-s4j-sifn' instead of '".$this->_contentType."'");
|
||||
$this->_contentType = "text/x-s4j-sifn";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
#error_log("Leaving ContentType='".$this->_contentType."' as is for source '".$this->_sourceReference."'");
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'SyncType':
|
||||
|
@ -40,17 +40,18 @@ class Horde_SyncML_Command_Results extends Horde_SyncML_Command {
|
||||
break;
|
||||
|
||||
case 'DevID':
|
||||
switch(trim($this->_chars)) {
|
||||
$devid = trim($this->_chars);
|
||||
$this->_deviceInfo['deviceID'] = $devid;
|
||||
switch ($devid)
|
||||
{
|
||||
case 'fmz-thunderbird-plugin':
|
||||
$this->_deviceInfo['deviceID'] = trim($this->_chars);
|
||||
$this->_deviceInfo['manufacturer'] = 'funambol';
|
||||
$this->_deviceInfo['model'] = trim($this->_chars);
|
||||
if (empty($this->_devinceInfo['manufacturer']))
|
||||
$this->_deviceInfo['manufacturer'] = 'funambol';
|
||||
if (empty($this->_devinceInfo['model']))
|
||||
$this->_deviceInfo['model'] = 'thunderbird';
|
||||
if (empty($this->_devinceInfo['softwareVersion']))
|
||||
$this->_deviceInfo['softwareVersion'] = '0.3';
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->_deviceInfo['deviceID'] = trim($this->_chars);
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -655,28 +655,82 @@ class Horde_SyncML_State {
|
||||
/**
|
||||
* This function should use DevINF information.
|
||||
*/
|
||||
function getPreferedContentType($type) {
|
||||
switch($type) {
|
||||
function adjustContentType($type, $target = null)
|
||||
{
|
||||
$ctype;
|
||||
if (is_array($type))
|
||||
{
|
||||
$ctype = $type['ContentType'];
|
||||
$res = $type;
|
||||
}
|
||||
else
|
||||
{
|
||||
$ctype = $type;
|
||||
$res = array();
|
||||
$res['ContentType'] = $ctype;
|
||||
}
|
||||
|
||||
switch($ctype)
|
||||
{
|
||||
case 'text/x-vcard':
|
||||
case 'text/x-vcalendar':
|
||||
case 'text/x-vnote':
|
||||
case 'text/calendar':
|
||||
case 'text/plain':
|
||||
$res['mayFragment'] = 1;
|
||||
break;
|
||||
|
||||
case 'text/x-s4j-sifc':
|
||||
case 'text/x-s4j-sife':
|
||||
case 'text/x-s4j-sift':
|
||||
case 'text/x-s4j-sifn':
|
||||
$res['ContentFormat'] = 'b64';
|
||||
$res['mayFragment'] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!isset($res['mayFragment']))
|
||||
{
|
||||
$res['mayFragment'] = 0;
|
||||
}
|
||||
|
||||
if ($target != null)
|
||||
{
|
||||
switch($target)
|
||||
{
|
||||
case 'calendar':
|
||||
case 'tasks':
|
||||
case 'notes':
|
||||
case 'contacts':
|
||||
$res['mayFragment'] = 1;
|
||||
break;
|
||||
|
||||
case 'sifcalendar':
|
||||
case 'siftasks':
|
||||
case 'sifnotes':
|
||||
case 'sifcontacts':
|
||||
case 'scard':
|
||||
case 'scalendar':
|
||||
case 'stask':
|
||||
case 'snote':
|
||||
default:
|
||||
$res['mayFragment'] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
function getPreferedContentType($type)
|
||||
{
|
||||
$_type = str_replace('./','',$type);
|
||||
switch($_type)
|
||||
{
|
||||
case 'contacts':
|
||||
case './contacts':
|
||||
return 'text/x-vcard';
|
||||
break;
|
||||
|
||||
case 'sifcalendar':
|
||||
case './sifcalendar':
|
||||
return 'text/x-s4j-sife';
|
||||
break;
|
||||
|
||||
case 'sifcontacts':
|
||||
case './sifcontacts':
|
||||
return 'text/x-s4j-sifc';
|
||||
break;
|
||||
|
||||
case 'siftasks':
|
||||
case './siftasks':
|
||||
return 'text/x-s4j-sift';
|
||||
break;
|
||||
|
||||
|
||||
case 'notes':
|
||||
return 'text/x-vnote';
|
||||
break;
|
||||
@ -684,14 +738,84 @@ class Horde_SyncML_State {
|
||||
case 'tasks':
|
||||
return 'text/x-vcalendar';
|
||||
break;
|
||||
|
||||
|
||||
case 'calendar':
|
||||
case './calendar':
|
||||
return 'text/x-vcalendar';
|
||||
break;
|
||||
|
||||
case 'sifcalendar':
|
||||
case 'scal':
|
||||
return 'text/x-s4j-sife';
|
||||
break;
|
||||
|
||||
case 'sifcontacts':
|
||||
case 'scard':
|
||||
return 'text/x-s4j-sifc';
|
||||
break;
|
||||
|
||||
case 'siftasks':
|
||||
case 'stask':
|
||||
return 'text/x-s4j-sift';
|
||||
break;
|
||||
|
||||
case 'sifnotes':
|
||||
case 'snote':
|
||||
return 'text/x-s4j-sifn';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function getHordeType($type)
|
||||
{
|
||||
$_type = str_replace('./','',$type);
|
||||
switch($_type)
|
||||
{
|
||||
case 'contacts':
|
||||
return 'contacts';
|
||||
break;
|
||||
|
||||
case 'notes':
|
||||
return 'notes';
|
||||
break;
|
||||
|
||||
case 'tasks':
|
||||
return 'tasks';
|
||||
break;
|
||||
|
||||
case 'calendar':
|
||||
return 'calendar';
|
||||
break;
|
||||
|
||||
# funambol related types
|
||||
|
||||
case 'sifcalendar':
|
||||
case 'scal':
|
||||
return 'sifcalendar';
|
||||
break;
|
||||
|
||||
case 'sifcontacts':
|
||||
case 'scard':
|
||||
return 'sifcontacts';
|
||||
break;
|
||||
|
||||
case 'siftasks':
|
||||
case 'stask':
|
||||
return 'siftasks';
|
||||
break;
|
||||
|
||||
case 'sifnotes':
|
||||
case 'snote':
|
||||
return 'sifnotes';
|
||||
break;
|
||||
|
||||
default:
|
||||
Horde::logMessage("unknown hordeType for type=$type ($_type)", __FILE__, __LINE__, PEAR_LOG_INFO);
|
||||
return $_type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns the preferred contenttype of the client for the given
|
||||
* sync data type (database).
|
||||
@ -699,15 +823,21 @@ class Horde_SyncML_State {
|
||||
* This is passed as an option to the Horde API export functions.
|
||||
*/
|
||||
|
||||
function getPreferedContentTypeClient($_sourceLocURI) {
|
||||
function getPreferedContentTypeClient($_sourceLocURI, $_targetLocURI = null) {
|
||||
$deviceInfo = $this->getClientDeviceInfo();
|
||||
|
||||
if(isset($deviceInfo['dataStore'][$_sourceLocURI]['rxPreference']['contentType'])) {
|
||||
return array('ContentType' => $deviceInfo['dataStore'][$_sourceLocURI]['rxPreference']['contentType']);
|
||||
if(isset($deviceInfo['dataStore'][$_sourceLocURI]['rxPreference']['contentType']))
|
||||
{
|
||||
return $this->adjustContentType($deviceInfo['dataStore'][$_sourceLocURI]['rxPreference']['contentType'], $_targetLocURI);
|
||||
}
|
||||
|
||||
Horde::logMessage('SyncML: sourceLocURI ' . $_sourceLocURI .' not found', __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
|
||||
if ($_targetLocURI != null)
|
||||
{
|
||||
return $this->adjustContentType($this->getPreferedContentType($_targetLocURI), $_targetLocURI);
|
||||
}
|
||||
|
||||
return PEAR::raiseError(_('sourceLocURI not found'));
|
||||
}
|
||||
|
||||
|
@ -141,13 +141,14 @@ class Horde_SyncML_Sync {
|
||||
}
|
||||
|
||||
$hordeType = $type = $this->_targetLocURI;
|
||||
// remove the './' from the beginning
|
||||
$hordeType = str_replace('./','',$hordeType);
|
||||
$hordeType = $state->getHordeType($hordeType);
|
||||
if(!$contentType = $command->getContentType()) {
|
||||
$contentType = $state->getPreferedContentType($type);
|
||||
}
|
||||
|
||||
if ($this->_targetLocURI == 'calendar' && strpos($command->getContent(), 'BEGIN:VTODO') !== false) {
|
||||
if (($contentType == 'text/x-vcalendar' || $contentType == 'text/calendar')
|
||||
&& strpos($command->getContent(), 'BEGIN:VTODO') !== false)
|
||||
{
|
||||
$hordeType = 'tasks';
|
||||
}
|
||||
|
||||
|
@ -36,28 +36,27 @@ class Horde_SyncML_Sync_RefreshFromServerSync extends Horde_SyncML_Sync_TwoWaySy
|
||||
continue;
|
||||
}
|
||||
|
||||
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI);
|
||||
if(is_a($contentType, 'PEAR_Error')) {
|
||||
// Client did not sent devinfo
|
||||
$contentType = array('ContentType' => $state->getPreferedContentType($this->_targetLocURI));
|
||||
}
|
||||
|
||||
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI, $this->_targetLocURI);
|
||||
$cmd = &new Horde_SyncML_Command_Sync_ContentSyncElement();
|
||||
$c = $registry->call($hordeType . '/export', array('guid' => $guid, 'contentType' => $contentType));
|
||||
Horde::logMessage("SyncML: slowsync add $guid to client ". print_r($c, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
if (!is_a($c, 'PEAR_Error')) {
|
||||
$cmd->setContent($c);
|
||||
if($hordeType == 'sifcalendar' || $hordeType == 'sifcontacts' || $hordeType == 'siftasks') {
|
||||
$cmd->setContentFormat('b64');
|
||||
$cmd->setContentType($contentType['ContentType']);
|
||||
if (isset($contentType['ContentFormat']))
|
||||
{
|
||||
$cmd->setContentFormat($contentType['ContentFormat']);
|
||||
}
|
||||
|
||||
$cmd->setContentType($contentType['ContentType']);
|
||||
$cmd->setSourceURI($guid);
|
||||
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Add');
|
||||
$state->log('Server-Add');
|
||||
|
||||
// return if we have to much data
|
||||
if(++$counter >= MAX_ENTRIES && $hordeType != 'sifcalendar' && $hordeType != 'sifcontacts' && $hordeType != 'siftasks') {
|
||||
if(++$counter >= MAX_ENTRIES
|
||||
&& isset($contentType['mayFragment'])
|
||||
&& $contentType['mayFragment'])
|
||||
{
|
||||
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
|
||||
return $currentCmdID;
|
||||
}
|
||||
@ -77,7 +76,7 @@ class Horde_SyncML_Sync_RefreshFromServerSync extends Horde_SyncML_Sync_TwoWaySy
|
||||
|
||||
$state = &$_SESSION['SyncML.state'];
|
||||
$syncType = $this->_targetLocURI;
|
||||
$hordeType = str_replace('./','',$syncType);
|
||||
$hordeType = $state->getHordeType($syncType);
|
||||
|
||||
Horde::logMessage("SyncML: reading added items from database for $hordeType", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
$state->setAddedItems($hordeType, $registry->call($hordeType. '/list', array()));
|
||||
|
@ -38,28 +38,27 @@ class Horde_SyncML_Sync_SlowSync extends Horde_SyncML_Sync_TwoWaySync {
|
||||
continue;
|
||||
}
|
||||
|
||||
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI);
|
||||
if(is_a($contentType, 'PEAR_Error')) {
|
||||
// Client did not sent devinfo
|
||||
$contentType = array('ContentType' => $state->getPreferedContentType($this->_targetLocURI));
|
||||
}
|
||||
|
||||
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI, $this->_targetLocURI);
|
||||
$cmd = &new Horde_SyncML_Command_Sync_ContentSyncElement();
|
||||
$c = $registry->call($hordeType . '/export', array('guid' => $guid, 'contentType' => $contentType));
|
||||
#Horde::logMessage("SyncML: slowsync add guid $guid to client ". print_r($c, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
if (!is_a($c, 'PEAR_Error')) {
|
||||
$cmd->setContent($c);
|
||||
if($hordeType == 'sifcalendar' || $hordeType == 'sifcontacts' || $hordeType == 'siftasks') {
|
||||
$cmd->setContentFormat('b64');
|
||||
$cmd->setContentType($contentType['ContentType']);
|
||||
if (isset($contentType['ContentFormat']))
|
||||
{
|
||||
$cmd->setContentFormat($contentType['ContentFormat']);
|
||||
}
|
||||
|
||||
$cmd->setContentType($contentType['ContentType']);
|
||||
$cmd->setSourceURI($guid);
|
||||
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Add');
|
||||
$state->log('Server-Add');
|
||||
|
||||
// return if we have to much data
|
||||
if(++$counter >= MAX_ENTRIES && $hordeType != 'sifcalendar' && $hordeType != 'sifcontacts' && $hordeType != 'siftasks') {
|
||||
if(++$counter >= MAX_ENTRIES
|
||||
&& isset($contentType['mayFragment'])
|
||||
&& $contentType['mayFragment'])
|
||||
{
|
||||
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
|
||||
return $currentCmdID;
|
||||
}
|
||||
@ -129,9 +128,8 @@ class Horde_SyncML_Sync_SlowSync extends Horde_SyncML_Sync_TwoWaySync {
|
||||
return;
|
||||
}
|
||||
|
||||
$hordeType = $type = $this->_targetLocURI;
|
||||
// remove the './' from the beginning
|
||||
$hordeType = str_replace('./','',$hordeType);
|
||||
$type = $this->_targetLocURI;
|
||||
$hordeType = $state->getHordeType($type);
|
||||
|
||||
$syncElementItems = $command->getSyncElementItems();
|
||||
|
||||
@ -140,7 +138,9 @@ class Horde_SyncML_Sync_SlowSync extends Horde_SyncML_Sync_TwoWaySync {
|
||||
$contentType = $state->getPreferedContentType($type);
|
||||
}
|
||||
|
||||
if ($this->_targetLocURI == 'calendar' && strpos($syncItem->getContent(), 'BEGIN:VTODO') !== false) {
|
||||
if (($contentType == 'text/x-vcalendar' || $contentType == 'text/calendar')
|
||||
&& strpos($syncItem->getContent(), 'BEGIN:VTODO') !== false)
|
||||
{
|
||||
$hordeType = 'tasks';
|
||||
}
|
||||
|
||||
@ -179,7 +179,7 @@ class Horde_SyncML_Sync_SlowSync extends Horde_SyncML_Sync_TwoWaySync {
|
||||
|
||||
$state = &$_SESSION['SyncML.state'];
|
||||
$syncType = $this->_targetLocURI;
|
||||
$hordeType = str_replace('./','',$syncType);
|
||||
$hordeType = $state->getHordeType($syncType);
|
||||
|
||||
Horde::logMessage("SyncML: reading added items from database for $hordeType", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
$state->setAddedItems($hordeType, $registry->call($hordeType. '/list', array()));
|
||||
|
@ -27,7 +27,7 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
|
||||
|
||||
$syncType = $this->_targetLocURI;
|
||||
|
||||
$hordeType = str_replace('./','',$syncType);
|
||||
$hordeType = $state->getHordeType($syncType);
|
||||
|
||||
$refts = $state->getServerAnchorLast($syncType);
|
||||
$currentCmdID = $this->handleSync($currentCmdID,
|
||||
@ -79,11 +79,7 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
|
||||
}
|
||||
|
||||
// Create a replace request for client.
|
||||
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI);
|
||||
if(is_a($contentType, 'PEAR_Error')) {
|
||||
// Client did not sent devinfo
|
||||
$contentType = array('ContentType' => $state->getPreferedContentType($this->_targetLocURI));
|
||||
}
|
||||
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI, $this->_targetLocURI);
|
||||
$c = $registry->call($hordeType. '/export',
|
||||
array('guid' => $guid, 'contentType' => $contentType));
|
||||
if (!is_a($c, 'PEAR_Error')) {
|
||||
@ -95,14 +91,19 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
|
||||
$cmd->setSourceURI($guid);
|
||||
$cmd->setTargetURI($locid);
|
||||
$cmd->setContentType($contentType['ContentType']);
|
||||
if($hordeType == 'sifcalendar' || $hordeType == 'sifcontacts' || $hordeType == 'siftasks') {
|
||||
$cmd->setContentFormat('b64');
|
||||
if (isset($contentType['ContentFormat']))
|
||||
{
|
||||
$cmd->setContentFormat($contentType['ContentFormat']);
|
||||
}
|
||||
|
||||
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Replace');
|
||||
$state->log('Server-Replace');
|
||||
|
||||
// return if we have to much data
|
||||
if(++$counter >= MAX_ENTRIES && $hordeType != 'sifcalendar' && $hordeType != 'sifcontacts' && $hordeType != 'siftasks') {
|
||||
if (++$counter >= MAX_ENTRIES
|
||||
&& isset($contentType['mayFragment'])
|
||||
&& $contentType['mayFragment'])
|
||||
{
|
||||
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
|
||||
return $currentCmdID;
|
||||
}
|
||||
@ -139,8 +140,12 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
|
||||
$state->log('Server-Delete');
|
||||
$state->removeUID($syncType, $locid);
|
||||
|
||||
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI, $this->_targetLocURI);
|
||||
// return if we have to much data
|
||||
if(++$counter >= MAX_ENTRIES && $hordeType != 'sifcalender' && $hordeType != 'sifcontacts' &&$hordeType != 'siftasks') {
|
||||
if(++$counter >= MAX_ENTRIES
|
||||
&& isset($contentType['mayFragment'])
|
||||
&& $contentType['mayFragment'])
|
||||
{
|
||||
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
|
||||
return $currentCmdID;
|
||||
}
|
||||
@ -180,11 +185,7 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
|
||||
Horde::logMessage("SyncML: add: $guid", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
|
||||
// Create an Add request for client.
|
||||
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI);
|
||||
if(is_a($contentType, 'PEAR_Error')) {
|
||||
// Client did not sent devinfo
|
||||
$contentType = array('ContentType' => $state->getPreferedContentType($this->_targetLocURI));
|
||||
}
|
||||
$contentType = $state->getPreferedContentTypeClient($this->_sourceLocURI, $this->_targetLocURI);
|
||||
|
||||
$cmd = &new Horde_SyncML_Command_Sync_ContentSyncElement();
|
||||
$c = $registry->call($hordeType . '/export',
|
||||
@ -197,16 +198,20 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
|
||||
if (!is_a($c, 'PEAR_Error')) {
|
||||
// Item in history but not in database. Strange, but can happen.
|
||||
$cmd->setContent($c);
|
||||
if($hordeType == 'sifcalendar' || $hordeType == 'sifcontacts' || $hordeType == 'siftasks') {
|
||||
$cmd->setContentFormat('b64');
|
||||
}
|
||||
$cmd->setContentType($contentType['ContentType']);
|
||||
if (isset($contentType['ContentFormat']))
|
||||
{
|
||||
$cmd->setContentFormat($contentType['ContentFormat']);
|
||||
}
|
||||
$cmd->setSourceURI($guid);
|
||||
$currentCmdID = $cmd->outputCommand($currentCmdID, $output, 'Add');
|
||||
$state->log('Server-Add');
|
||||
|
||||
// return if we have to much data
|
||||
if(++$counter >= MAX_ENTRIES && $hordeType != 'sifcalendar' && $hordeType != 'sifcontacts' &&$hordeType != 'siftasks') {
|
||||
if(++$counter >= MAX_ENTRIES
|
||||
&& isset($contentType['mayFragment'])
|
||||
&& $contentType['mayFragment'])
|
||||
{
|
||||
$state->setSyncStatus(SERVER_SYNC_DATA_PENDING);
|
||||
return $currentCmdID;
|
||||
}
|
||||
@ -225,7 +230,7 @@ class Horde_SyncML_Sync_TwoWaySync extends Horde_SyncML_Sync {
|
||||
|
||||
$state = &$_SESSION['SyncML.state'];
|
||||
$syncType = $this->_targetLocURI;
|
||||
$hordeType = str_replace('./','',$syncType);
|
||||
$hordeType = $state->getHordeType($syncType);
|
||||
$refts = $state->getServerAnchorLast($syncType);
|
||||
|
||||
Horde::logMessage("SyncML: reading changed items from database for $hordeType", __FILE__, __LINE__, PEAR_LOG_DEBUG);
|
||||
|
@ -510,18 +510,11 @@ class Horde_iCalendar {
|
||||
case 'CREATED':
|
||||
case 'LAST-MODIFIED':
|
||||
case 'BDAY':
|
||||
$this->setAttribute($tag, $this->_parseDateTime($value), $params);
|
||||
break;
|
||||
|
||||
case 'DTEND':
|
||||
case 'DTSTART':
|
||||
case 'DUE':
|
||||
case 'RECURRENCE-ID':
|
||||
if (isset($params['VALUE']) && $params['VALUE'] == 'DATE') {
|
||||
$this->setAttribute($tag, $this->_parseDate($value), $params);
|
||||
} else {
|
||||
$this->setAttribute($tag, $this->_parseDateTime($value), $params);
|
||||
}
|
||||
$this->setAttribute($tag, $this->_parseDateTime($value), $params);
|
||||
break;
|
||||
|
||||
case 'RDATE':
|
||||
@ -902,7 +895,7 @@ class Horde_iCalendar {
|
||||
if (!$date = $this->_parseDate($text)) {
|
||||
return $date;
|
||||
}
|
||||
return @gmmktime(0, 0, 0, $date['month'], $date['mday'], $date['year']);
|
||||
return @mktime(0, 0, 0, $date['month'], $date['mday'], $date['year']);
|
||||
}
|
||||
|
||||
if (!$date = $this->_parseDate($dateParts[0])) {
|
||||
@ -912,6 +905,8 @@ class Horde_iCalendar {
|
||||
return $time;
|
||||
}
|
||||
|
||||
error_log("parseDateTime: ".$text." => ".print_r($time, true));
|
||||
|
||||
if ($time['zone'] == 'UTC') {
|
||||
return @gmmktime($time['hour'], $time['minute'], $time['second'],
|
||||
$date['month'], $date['mday'], $date['year']);
|
||||
@ -1016,7 +1011,12 @@ class Horde_iCalendar {
|
||||
*/
|
||||
function _parseDate($text)
|
||||
{
|
||||
if (strlen($text) != 8) {
|
||||
if (strlen($text) == 10)
|
||||
{
|
||||
$text = str_replace('-','',$text);
|
||||
}
|
||||
if (strlen($text) != 8)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -18,12 +18,12 @@ $conf['auth']['checkip'] = true;
|
||||
$conf['auth']['params']['username'] = 'Administrator';
|
||||
$conf['auth']['params']['requestuser'] = false;
|
||||
$conf['auth']['driver'] = 'auto';
|
||||
$conf['log']['priority'] = PEAR_LOG_INFO;
|
||||
$conf['log']['priority'] = PEAR_LOG_DEBUG;
|
||||
$conf['log']['ident'] = 'EGWSYNC';
|
||||
$conf['log']['params'] = array();
|
||||
$conf['log']['name'] = '/tmp/egroupware_syncml.log';
|
||||
$conf['log']['params']['append'] = true;
|
||||
$conf['log']['type'] = 'file';
|
||||
$conf['log']['type'] = 'error_log';
|
||||
$conf['log']['enabled'] = true;
|
||||
$conf['log_accesskeys'] = false;
|
||||
$conf['prefs']['driver'] = 'none';
|
||||
|
@ -77,7 +77,7 @@ $this->applications['egwnotessync'] = array(
|
||||
'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
|
||||
'name' => _("Notes"),
|
||||
'status' => 'active',
|
||||
'provides' => 'notes',
|
||||
'provides' => array('notes', 'sifnotes', 'snote'),
|
||||
'menu_parent' => 'organizing'
|
||||
);
|
||||
|
||||
@ -87,19 +87,19 @@ $this->applications['egwcontactssync'] = array(
|
||||
'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
|
||||
'name' => _("Contacts"),
|
||||
'status' => 'active',
|
||||
'provides' => 'contacts',
|
||||
'provides' => array('contacts', 'sifcontacts', 'scard'),
|
||||
'menu_parent' => 'organizing'
|
||||
);
|
||||
|
||||
$this->applications['egwsifcontactssync'] = array(
|
||||
'fileroot' => EGW_SERVER_ROOT.'/syncml/sifcontacts',
|
||||
'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
|
||||
'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
|
||||
'name' => _("SIF Contacts"),
|
||||
'status' => 'active',
|
||||
'provides' => 'sifcontacts',
|
||||
'menu_parent' => 'organizing'
|
||||
);
|
||||
#$this->applications['egwsifcontactssync'] = array(
|
||||
# 'fileroot' => EGW_SERVER_ROOT.'/syncml/sifcontacts',
|
||||
# 'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
|
||||
# 'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
|
||||
# 'name' => _("SIF Contacts"),
|
||||
# 'status' => 'active',
|
||||
# 'provides' => 'sifcontacts',
|
||||
# 'menu_parent' => 'organizing'
|
||||
#);
|
||||
|
||||
$this->applications['egwcalendarsync'] = array(
|
||||
'fileroot' => EGW_SERVER_ROOT.'/syncml/calendar',
|
||||
@ -107,19 +107,19 @@ $this->applications['egwcalendarsync'] = array(
|
||||
'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
|
||||
'name' => _("Calendar"),
|
||||
'status' => 'active',
|
||||
'provides' => 'calendar',
|
||||
'provides' => array('calendar', 'sifcalendar', 'scal'),
|
||||
'menu_parent' => 'organizing'
|
||||
);
|
||||
|
||||
$this->applications['egwsifcalendarsync'] = array(
|
||||
'fileroot' => EGW_SERVER_ROOT.'/syncml/sifcalendar',
|
||||
'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
|
||||
'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
|
||||
'name' => _("Calendar"),
|
||||
'status' => 'active',
|
||||
'provides' => 'sifcalendar',
|
||||
'menu_parent' => 'organizing'
|
||||
);
|
||||
#$this->applications['egwsifcalendarsync'] = array(
|
||||
# 'fileroot' => EGW_SERVER_ROOT.'/syncml/sifcalendar',
|
||||
# 'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
|
||||
# 'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
|
||||
# 'name' => _("Calendar"),
|
||||
# 'status' => 'active',
|
||||
# 'provides' => 'sifcalendar',
|
||||
# 'menu_parent' => 'organizing'
|
||||
#);
|
||||
|
||||
$this->applications['egwtaskssync'] = array(
|
||||
'fileroot' => EGW_SERVER_ROOT.'/syncml/tasks',
|
||||
@ -127,19 +127,19 @@ $this->applications['egwtaskssync'] = array(
|
||||
'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
|
||||
'name' => _("Tasks"),
|
||||
'status' => 'active',
|
||||
'provides' => 'tasks',
|
||||
'provides' => array('tasks', 'siftasks', 'stask'),
|
||||
'menu_parent' => 'organizing'
|
||||
);
|
||||
|
||||
$this->applications['egwsiftaskssync'] = array(
|
||||
'fileroot' => EGW_SERVER_ROOT.'/syncml/siftasks',
|
||||
'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
|
||||
'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
|
||||
'name' => _("SIFTasks"),
|
||||
'status' => 'active',
|
||||
'provides' => 'siftasks',
|
||||
'menu_parent' => 'organizing'
|
||||
);
|
||||
#$this->applications['egwsiftaskssync'] = array(
|
||||
# 'fileroot' => EGW_SERVER_ROOT.'/syncml/siftasks',
|
||||
# 'webroot' => $this->applications['horde']['webroot'] . '/mnemo',
|
||||
# 'icon' => $this->applications['horde']['webroot'] . '/mnemo/graphics/mnemo.gif',
|
||||
# 'name' => _("SIFTasks"),
|
||||
# 'status' => 'active',
|
||||
# 'provides' => array('siftasks', 'stask'),
|
||||
# 'menu_parent' => 'organizing'
|
||||
#);
|
||||
|
||||
$this->applications['egwcaltaskssync'] = array(
|
||||
'fileroot' => EGW_SERVER_ROOT.'/syncml/caltasks',
|
||||
|
Loading…
Reference in New Issue
Block a user