From aacbe20355158f63d22dc93adc4ce493e427508d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Lehrke?= Date: Fri, 20 Nov 2009 14:45:26 +0000 Subject: [PATCH] Backport of Christians SyncML Category Handling --- addressbook/inc/class.addressbook_bo.inc.php | 42 ++++++++++-- addressbook/inc/class.addressbook_sif.inc.php | 21 ++++-- .../inc/class.addressbook_vcal.inc.php | 12 ++-- calendar/inc/class.calendar_boupdate.inc.php | 53 ++++++++++++--- calendar/inc/class.calendar_ical.inc.php | 10 +-- calendar/inc/class.calendar_sif.inc.php | 30 ++++----- infolog/inc/class.infolog_bo.inc.php | 65 +++++++++++++++---- infolog/inc/class.infolog_ical.inc.php | 39 +++++------ infolog/inc/class.infolog_sif.inc.php | 19 ++++-- phpgwapi/inc/class.categories.inc.php | 60 +++++++++++++++-- 10 files changed, 265 insertions(+), 86 deletions(-) diff --git a/addressbook/inc/class.addressbook_bo.inc.php b/addressbook/inc/class.addressbook_bo.inc.php index e726ebb8cd..c53b5c2b7c 100755 --- a/addressbook/inc/class.addressbook_bo.inc.php +++ b/addressbook/inc/class.addressbook_bo.inc.php @@ -1420,13 +1420,40 @@ class addressbook_bo extends addressbook_so var $categories; - function find_or_add_categories($catname_list) + /** + * Find existing categories in database by name or add categories that do not exist yet + * currently used for vcard import + * + * @param array $catname_list names of the categories which should be found or added + * @param int $contact_id=null match against existing contact and expand the returned category ids + * by the ones the user normally does not see due to category permissions - used to preserve categories + * @return array category ids (found, added and preserved categories) + */ + function find_or_add_categories($catname_list, $contact_id=null) { if (!is_object($this->categories)) { $this->categories = new categories($this->owner,'addressbook'); } + if($contact_id && $contact_id > 0) + { + // preserve categories without users read access + $old_contact = $this->read($contact_id); + $old_categories = explode(',',$old_contact['cat_id']); + $old_cats_preserve = array(); + if(is_array($old_categories) && count($old_categories) > 0) + { + foreach($old_categories as $cat_id) + { + if(!$this->categories->check_perms(EGW_ACL_READ, $cat_id)) + { + $old_cats_preserve[] = $cat_id; + } + } + } + } + $cat_id_list = array(); foreach($catname_list as $cat_name) { @@ -1435,7 +1462,7 @@ class addressbook_bo extends addressbook_so if (!$cat_id) { - // some SyncML clients (mostly phones add an X- to the category names + // some SyncML clients (mostly phones) add an X- to the category names if (strncmp($cat_name, 'X-', 2) == 0) { $cat_name = substr($cat_name, 2); @@ -1449,11 +1476,17 @@ class addressbook_bo extends addressbook_so } } + if(is_array($old_cats_preserve) && count($old_cats_preserve) > 0) + { + $cat_id_list = array_merge($cat_id_list, $old_cats_preserve); + } + if (count($cat_id_list) > 1) { $cat_id_list = array_unique($cat_id_list); sort($cat_id_list, SORT_NUMERIC); } + return $cat_id_list; } @@ -1461,7 +1494,7 @@ class addressbook_bo extends addressbook_so { if (!is_object($this->categories)) { - $this->categories = new categories($this->owner,'addressbook'); + $this->categories = new categories($this->user,'addressbook'); } if (!is_array($cat_id_list)) @@ -1471,7 +1504,8 @@ class addressbook_bo extends addressbook_so $cat_list = array(); foreach($cat_id_list as $cat_id) { - if ($cat_id && ($cat_name = $this->categories->id2name($cat_id)) && $cat_name != '--') + if ($cat_id && $this->categories->check_perms(EGW_ACL_READ, $cat_id) && + ($cat_name = $this->categories->id2name($cat_id)) && $cat_name != '--') { $cat_list[] = $cat_name; } diff --git a/addressbook/inc/class.addressbook_sif.inc.php b/addressbook/inc/class.addressbook_sif.inc.php index 158303342f..6a77af4f1c 100644 --- a/addressbook/inc/class.addressbook_sif.inc.php +++ b/addressbook/inc/class.addressbook_sif.inc.php @@ -113,7 +113,7 @@ class addressbook_sif extends addressbook_bo $this->sifData .= $_data; } - function siftoegw($sifData) { + function siftoegw($sifData, $_abID=null) { #$tmpfname = tempnam('/tmp/sync/contents','sifc_'); @@ -121,6 +121,8 @@ class addressbook_sif extends addressbook_bo #fwrite($handle, $sifData); #fclose($handle); + // Horde::logMessage("SyncML siftoegw:\n$sifData", __FILE__, __LINE__, PEAR_LOG_DEBUG); + $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); @@ -141,7 +143,10 @@ class addressbook_sif extends addressbook_bo case 'cat_id': if(!empty($value)) { - $finalContact[$key] = implode(",", $this->find_or_add_categories(explode(';', $value))); + $categories1 = explode(',', $value); + $categories2 = explode(';', $value); + $categories = count($categories1) > count($categories2) ? $categories1 : $categories2; + $finalContact[$key] = implode(',', $this->find_or_add_categories($categories, $_abID)); } else { @@ -160,6 +165,7 @@ class addressbook_sif extends addressbook_bo } $this->fixup_contact($finalContact); + // Horde::logMessage("SyncML siftoegw: " . print_r($finalContact, true), __FILE__, __LINE__, PEAR_LOG_DEBUG); return $finalContact; } @@ -173,7 +179,7 @@ class addressbook_sif extends addressbook_bo { $result = false; - if($contact = $this->siftoegw($_sifdata)) { + if($contact = $this->siftoegw($_sifdata, $contentID)) { if ($contentID) { $contact['contact_id'] = $contentID; } @@ -195,7 +201,7 @@ class addressbook_sif extends addressbook_bo #error_log('ABID: '.$_abID); #error_log(base64_decode($_sifdata)); - if(!$contact = $this->siftoegw($_sifdata)) { + if(!$contact = $this->siftoegw($_sifdata, $_abID)) { return false; } @@ -203,6 +209,11 @@ class addressbook_sif extends addressbook_bo // update entry $contact['id'] = $_abID; } + elseif (array_key_exists('filter_addressbook', $GLOBALS['egw_info']['user']['preferences']['syncml'])) + { + $contact['owner'] = (int) $GLOBALS['egw_info']['user']['preferences']['syncml']['filter_addressbook']; + } + return $this->save($contact); } @@ -253,7 +264,7 @@ class addressbook_sif extends addressbook_bo case 'Categories': if(!empty($value)) { - $value = implode("; ", $this->get_categories($value)); + $value = implode(', ', $this->get_categories($value)); $value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8'); } else { break; diff --git a/addressbook/inc/class.addressbook_vcal.inc.php b/addressbook/inc/class.addressbook_vcal.inc.php index 987ecf865d..26a69e48aa 100644 --- a/addressbook/inc/class.addressbook_vcal.inc.php +++ b/addressbook/inc/class.addressbook_vcal.inc.php @@ -119,7 +119,7 @@ class addressbook_vcal extends addressbook_bo */ function addVCard($_vcard, $_abID=null, $merge=false) { - if(!$contact = $this->vcardtoegw($_vcard)) + if(!$contact = $this->vcardtoegw($_vcard, $_abID)) { return false; } @@ -143,6 +143,10 @@ class addressbook_vcal extends addressbook_bo // update entry $contact['id'] = $_abID; } + elseif (array_key_exists('filter_addressbook', $GLOBALS['egw_info']['user']['preferences']['syncml'])) + { + $contact['owner'] = (int) $GLOBALS['egw_info']['user']['preferences']['syncml']['filter_addressbook']; + } return $this->save($contact); } @@ -395,7 +399,7 @@ class addressbook_vcal extends addressbook_bo { $result = false; - if (($contact = $this->vcardtoegw($_vcard))) + if (($contact = $this->vcardtoegw($_vcard, $contentID))) { if ($contentID) { @@ -415,7 +419,7 @@ class addressbook_vcal extends addressbook_bo if (is_array($_supportedFields)) $this->supportedFields = $_supportedFields; } - function vcardtoegw($_vcard) + function vcardtoegw($_vcard, $_abID=null) { // the horde class does the charset conversion. DO NOT CONVERT HERE. // be as flexible as possible @@ -825,7 +829,7 @@ class addressbook_vcal extends addressbook_bo break; case 'cat_id': - $contact[$fieldName] = implode(',',$this->find_or_add_categories($vcardValues[$vcardKey]['values'])); + $contact[$fieldName] = implode(',',$this->find_or_add_categories($vcardValues[$vcardKey]['values'], $_abID)); break; case 'jpegphoto': diff --git a/calendar/inc/class.calendar_boupdate.inc.php b/calendar/inc/class.calendar_boupdate.inc.php index 7280c7942d..6298869cdb 100644 --- a/calendar/inc/class.calendar_boupdate.inc.php +++ b/calendar/inc/class.calendar_boupdate.inc.php @@ -1052,21 +1052,50 @@ class calendar_boupdate extends calendar_bo var $categories; - function find_or_add_categories($catname_list) + /** + * Find existing categories in database by name or add categories that do not exist yet + * currently used for ical/sif import + * + * @param array $catname_list names of the categories which should be found or added + * @param int $cal_id=-1 match against existing event and expand the returned category ids + * by the ones the user normally does not see due to category permissions - used to preserve categories + * @return array category ids (found, added and preserved categories) + */ + function find_or_add_categories($catname_list, $cal_id=-1) { if (!is_object($this->categories)) { - $this->categories = CreateObject('phpgwapi.categories',$this->user,'calendar'); + $this->categories = new categories($this->user,'calendar'); + } + + if ($cal_id && $cal_id > 0) + { + // preserve categories without users read access + $old_event = $this->read($cal_id); + $old_categories = explode(',',$old_event['category']); + $old_cats_preserve = array(); + if (is_array($old_categories) && count($old_categories) > 0) + { + foreach ($old_categories as $cat_id) + { + if (!$this->categories->check_perms(EGW_ACL_READ, $cat_id)) + { + $old_cats_preserve[] = $cat_id; + } + } + } } $cat_id_list = array(); - foreach($catname_list as $cat_name) + foreach ($catname_list as $cat_name) { $cat_name = trim($cat_name); $cat_id = $this->categories->name2id($cat_name, 'X-'); + if (!$cat_id) { - if (strncmp($cat_name, "X-", 2) == 0) + // some SyncML clients (mostly phones) add an X- to the category names + if (strncmp($cat_name, 'X-', 2) == 0) { $cat_name = substr($cat_name, 2); } @@ -1079,11 +1108,17 @@ class calendar_boupdate extends calendar_bo } } + if (is_array($old_cats_preserve) && count($old_cats_preserve) > 0) + { + $cat_id_list = array_merge($cat_id_list, $old_cats_preserve); + } + if (count($cat_id_list) > 1) { $cat_id_list = array_unique($cat_id_list); sort($cat_id_list, SORT_NUMERIC); } + return $cat_id_list; } @@ -1091,20 +1126,20 @@ class calendar_boupdate extends calendar_bo { if (!is_object($this->categories)) { - $this->categories = CreateObject('phpgwapi.categories',$this->user,'calendar'); + $this->categories = new categories($this->user,'calendar'); } if (!is_array($cat_id_list)) { $cat_id_list = explode(',',$cat_id_list); } - $cat_list = array(); - foreach($cat_id_list as $cat_id) + foreach ($cat_id_list as $cat_id) { - if ($cat_data = $this->categories->return_single($cat_id)) + if ($cat_id && $this->categories->check_perms(EGW_ACL_READ, $cat_id) && + ($cat_name = $this->categories->id2name($cat_id)) && $cat_name != '--') { - $cat_list[] = $cat_data[0]['name']; + $cat_list[] = $cat_name; } } diff --git a/calendar/inc/class.calendar_ical.inc.php b/calendar/inc/class.calendar_ical.inc.php index 4aabe4085d..14fe19e84f 100644 --- a/calendar/inc/class.calendar_ical.inc.php +++ b/calendar/inc/class.calendar_ical.inc.php @@ -1430,7 +1430,7 @@ class calendar_ical extends calendar_boupdate { if (is_a($component, 'Horde_iCalendar_vevent')) { - if ($event = $this->vevent2egw($component, $version, $this->supportedFields)) + if ($event = $this->vevent2egw($component, $version, $this->supportedFields, $cal_id)) { //common adjustments if ($this->productManufacturer == '' && $this->productName == '' @@ -1486,10 +1486,10 @@ class calendar_ical extends calendar_boupdate * @param array $component VEVENT * @param string $version vCal version (1.0/2.0) * @param array $supportedFields supported fields of the device - * + * @param int $cal_id id of existing event in the content (only used to merge categories) * @return array|boolean event on success, false on failure */ - function vevent2egw(&$component, $version, $supportedFields) + function vevent2egw(&$component, $version, $supportedFields, $cal_id=-1) { if (!is_a($component, 'Horde_iCalendar_vevent')) return false; @@ -1829,11 +1829,11 @@ class calendar_ical extends calendar_boupdate { if($version == '1.0') { - $vcardData['category'] = $this->find_or_add_categories(explode(';',$attributes['value'])); + $vcardData['category'] = $this->find_or_add_categories(explode(';',$attributes['value']), $cal_id); } else { - $vcardData['category'] = $this->find_or_add_categories(explode(',',$attributes['value'])); + $vcardData['category'] = $this->find_or_add_categories(explode(',',$attributes['value']), $cal_id); } } else diff --git a/calendar/inc/class.calendar_sif.inc.php b/calendar/inc/class.calendar_sif.inc.php index c66d4d217f..77e4fa664f 100644 --- a/calendar/inc/class.calendar_sif.inc.php +++ b/calendar/inc/class.calendar_sif.inc.php @@ -103,7 +103,7 @@ class calendar_sif extends calendar_boupdate $this->sifData .= $_data; } - function siftoegw($sifData) + function siftoegw($sifData, $_calID=-1) { $vcal = new Horde_iCalendar; $finalEvent = array(); @@ -164,7 +164,10 @@ class calendar_sif extends calendar_boupdate case 'category': if (!empty($value)) { - $finalEvent[$key] = implode(',',$this->find_or_add_categories(explode(';', $value))); + $categories1 = explode(',', $value); + $categories2 = explode(';', $value); + $categories = count($categories1) > count($categories2) ? $categories1 : $categories2; + $finalEvent[$key] = implode(',', $this->find_or_add_categories($categories, $_calID)); } break; @@ -255,7 +258,7 @@ class calendar_sif extends calendar_boupdate { $result = false; - if ($event = $this->siftoegw($_sifdata)) + if ($event = $this->siftoegw($_sifdata, $contentID)) { if ($contentID) { $event['id'] = $contentID; @@ -266,23 +269,18 @@ class calendar_sif extends calendar_boupdate } /** - * @return int contact id - * @param string $_vcard the vcard - * @param int $_abID the internal addressbook id + * @return int event id + * @param string $_sifdata the SIFE data + * @param int $_calID=-1 the internal addressbook id * @param boolean $merge=false merge data with existing entry - * @desc import a vard into addressbook + * @desc import a SIFE into the calendar */ - function addSIF($_sifdata, $_calID, $merge=false) + function addSIF($_sifdata, $_calID=-1, $merge=false) { $state = &$_SESSION['SyncML.state']; $deviceInfo = $state->getClientDeviceInfo(); - $calID = false; - - #error_log('ABID: '.$_abID); - #error_log(base64_decode($_sifdata)); - - if (!$event = $this->siftoegw($_sifdata)) + if (!$event = $this->siftoegw($_sifdata, $_calID)) { return false; } @@ -334,7 +332,7 @@ class calendar_sif extends calendar_boupdate * return a sife * * @param int $_id the id of the event - * @return string containing the vcard + * @return string containing the SIFE */ function getSIF($_id) { @@ -560,7 +558,7 @@ class calendar_sif extends calendar_boupdate case 'Categories': if (!empty($value)) { - $value = implode('; ', $this->get_categories(explode(',',$value))); + $value = implode(', ', $this->get_categories($value)); $value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8'); } else diff --git a/infolog/inc/class.infolog_bo.inc.php b/infolog/inc/class.infolog_bo.inc.php index 6a41472eb1..37c4af5c62 100644 --- a/infolog/inc/class.infolog_bo.inc.php +++ b/infolog/inc/class.infolog_bo.inc.php @@ -119,6 +119,7 @@ class infolog_bo 'open-today' => 'open', 'open-overdue' => 'overdue', 'upcoming' => 'upcoming', + 'bydate' => 'startdate', ); /** @@ -319,7 +320,7 @@ class infolog_bo } /** - * Check if user is responsible for an entry: he or one of his memberships is in responsible + * Check if use is responsible for an entry: he or one of his memberships is in responsible * * @param array $info infolog entry as array * @return boolean @@ -610,7 +611,7 @@ class infolog_bo { $values['info_percent'] = 100; } - if ((int)$values['info_percent'] == 100 && !in_array($values['info_status'],array('done','billed','cancelled'))) + if ((int)$values['info_percent'] == 100 && !in_array($values['info_status'],array('done','billed','cancelled','archive'))) { //echo "check_defaults:"; _debug_array($this->status[$values['info_type']]); //$values['info_status'] = 'done'; @@ -1066,11 +1067,38 @@ class infolog_bo var $categories; - function find_or_add_categories($catname_list) + /** + * Find existing categories in database by name or add categories that do not exist yet + * currently used for ical/sif import + * + * @param array $catname_list names of the categories which should be found or added + * @param int $info_id=-1 match against existing infolog and expand the returned category ids + * by the ones the user normally does not see due to category permissions - used to preserve categories + * @return array category ids (found, added and preserved categories) + */ + function find_or_add_categories($catname_list, $info_id=-1) { if (!is_object($this->categories)) { - $this->categories =& CreateObject('phpgwapi.categories',$GLOBALS['egw_info']['user']['account_id'],'infolog'); + $this->categories = new categories($this->user,'infolog'); + } + + if($info_id && $info_id > 0) + { + // preserve categories without users read access + $old_infolog = $this->read($info_id); + $old_categories = explode(',',$old_infolog['info_cat']); + $old_cats_preserve = array(); + if(is_array($old_categories) && count($old_categories) > 0) + { + foreach($old_categories as $cat_id) + { + if(!$this->categories->check_perms(EGW_ACL_READ, $cat_id)) + { + $old_cats_preserve[] = $cat_id; + } + } + } } $cat_id_list = array(); @@ -1078,8 +1106,14 @@ class infolog_bo { $cat_name = trim($cat_name); $cat_id = $this->categories->name2id($cat_name, 'X-'); + if (!$cat_id) { + // some SyncML clients (mostly phones) add an X- to the category names + if (strncmp($cat_name, 'X-', 2) == 0) + { + $cat_name = substr($cat_name, 2); + } $cat_id = $this->categories->add(array('name' => $cat_name, 'descr' => $cat_name, 'access' => 'private')); } @@ -1088,12 +1122,20 @@ class infolog_bo $cat_id_list[] = $cat_id; } } + + if(is_array($old_cats_preserve) && count($old_cats_preserve) > 0) + { + $cat_id_list = array_merge($old_cats_preserve, $cat_id_list); + } if (count($cat_id_list) > 1) { $cat_id_list = array_unique($cat_id_list); - sort($cat_id_list, SORT_NUMERIC); + // disable sorting until infolog supports multiple categories + // to make sure that the preserved category takes precedence over a new one from the client + /* sort($cat_id_list, SORT_NUMERIC); */ } + return $cat_id_list; } @@ -1107,7 +1149,7 @@ class infolog_bo { if (!is_object($this->categories)) { - $this->categories =& CreateObject('phpgwapi.categories',$GLOBALS['egw_info']['user']['account_id'],'infolog'); + $this->categories = new categories($this->user,'infolog'); } if (!is_array($cat_id_list)) @@ -1117,9 +1159,10 @@ class infolog_bo $cat_list = array(); foreach($cat_id_list as $cat_id) { - if ($cat_data = $this->categories->return_single($cat_id)) + if ($cat_id && $this->categories->check_perms(EGW_ACL_READ, $cat_id) && + ($cat_name = $this->categories->id2name($cat_id)) && $cat_name != '--') { - $cat_list[] = $cat_data[0]['name']; + $cat_list[] = $cat_name; } } @@ -1137,7 +1180,7 @@ class infolog_bo { return; } - error_log("boinfolog::async_notification() users with open entries: ".implode(', ',$users)); + //error_log(__METHOD__."() users with open entries: ".implode(', ',$users)); $save_account_id = $GLOBALS['egw_info']['user']['account_id']; $save_prefs = $GLOBALS['egw_info']['user']['preferences']; @@ -1164,7 +1207,7 @@ class infolog_bo if (!($pref_value = $GLOBALS['egw_info']['user']['preferences']['infolog'][$pref])) continue; $filter .= date('Y-m-d',time()+24*60*60*(int)$pref_value); - error_log("boinfolog::async_notification() checking with filter '$filter' ($pref_value) for user $user ($email)"); + //error_log(__METHOD__."() checking with filter '$filter' ($pref_value) for user $user ($email)"); $params = array('filter' => $filter); foreach($this->so->search($params) as $info) @@ -1196,7 +1239,7 @@ class infolog_bo $this->tracking->datetime($info['info_startdate']-$this->tz_offset_s,null)); break; } - error_log("notifiying $user($email) about $info[info_subject]: $info[message]"); + //error_log("notifiying $user($email) about $info[info_subject]: $info[message]"); $this->tracking->send_notification($info,null,$email,$user,$pref); $notified_info_ids[] = $info['info_id']; diff --git a/infolog/inc/class.infolog_ical.inc.php b/infolog/inc/class.infolog_ical.inc.php index deaf0d91d3..6b3294caea 100644 --- a/infolog/inc/class.infolog_ical.inc.php +++ b/infolog/inc/class.infolog_ical.inc.php @@ -197,15 +197,8 @@ class infolog_ical extends infolog_bo if ($taskData['info_enddate']) { $parts = @getdate($taskData['info_enddate']); - if ($dateOnly) - { - $value = @mktime(0, 0, 0, $parts['mon'], $parts['mday'], $parts['year']); - } - else - { - $value = @mktime(12, 0, 0, $parts['mon'], $parts['mday'], $parts['year']); - } - self::setDateOrTime($vevent, 'DUE', $taskData['info_enddate']); + $value = @mktime(12, 0, 0, $parts['mon'], $parts['mday'], $parts['year']); + self::setDateOrTime($vevent, 'DUE', $value, $dateOnly); } if ($taskData['info_datecompleted']) @@ -268,7 +261,7 @@ class infolog_ical extends infolog_bo function searchVTODO($_vcalData, $contentID=null, $relax=false) { $result = false; - if (($egwData = $this->vtodotoegw($_vcalData))) + if (($egwData = $this->vtodotoegw($_vcalData, $contentID))) { if ($contentID) { @@ -392,7 +385,7 @@ class infolog_ical extends infolog_bo break; case 'CATEGORIES': - $cats = $this->find_or_add_categories(explode(',', $attributes['value'])); + $cats = $this->find_or_add_categories(explode(',', $attributes['value']), $_taskID); $taskData['info_cat'] = $cats[0]; break; @@ -487,16 +480,17 @@ class infolog_ical extends infolog_bo * @param Horde_iCalendar_* $vevent * @param string $attr attribute name * @param int $value timestamp + * @param boolean $force=false, set DATE in any case * @return boolean true, if date only */ - static function setDateOrTime($vevent,$attr,$value) + static function setDateOrTime($vevent,$attr,$value,$force=false) { - if (date('Hi',$value) == '0000') + if ($force || date('Hi', $value) == '0000') { $vevent->setAttribute($attr, array( - 'year' => date('Y',$value), - 'month' => date('m',$value), - 'mday' => date('d',$value), + 'year' => date('Y', $value), + 'month' => date('m', $value), + 'mday' => date('d', $value), ), array('VALUE' => 'DATE')); return true; } @@ -513,13 +507,13 @@ class infolog_ical extends infolog_bo * * @param string $_vcalData * @param string $_type content type (eg.g text/plain) - * @param int $_taskID=-1 info_id, default -1 = new entry + * @param int $_noteID=-1 info_id, default -1 = new entry * @param boolean $merge=false merge data with existing entry * @return int|boolean integer info_id or false on error */ - function importVNOTE(&$_vcalData, $_type, $_noteID = -1, $merge=false) + function importVNOTE(&$_vcalData, $_type, $_noteID=-1, $merge=false) { - if (!($note = $this->vnotetoegw($_vcalData, $_type))) return false; + if (!($note = $this->vnotetoegw($_vcalData, $_type, $_noteID))) return false; if($_noteID > 0) $note['info_id'] = $_noteID; @@ -538,7 +532,7 @@ class infolog_ical extends infolog_bo */ function searchVNOTE($_vcalData, $_type, $contentID=null) { - if (!($note = $this->vnotetoegw($_vcalData,$_type))) return false; + if (!($note = $this->vnotetoegw($_vcalData,$_type,$contentID))) return false; if ($contentID) $note['info_id'] = $contentID; @@ -575,9 +569,10 @@ class infolog_ical extends infolog_bo * * @param string $_data VNOTE data * @param string $_type content type (eg.g text/plain) + * @param int $_noteID=-1 infolog_id of the entry * @return array infolog entry or false on error */ - function vnotetoegw($_data, $_type) + function vnotetoegw($_data, $_type, $_noteID=-1) { switch ($_type) { @@ -628,7 +623,7 @@ class infolog_ical extends infolog_bo break; case 'CATEGORIES': - $cats = $this->find_or_add_categories(explode(',', $attribute['value'])); + $cats = $this->find_or_add_categories(explode(',', $attribute['value']), $_noteID); $note['info_cat'] = $cats[0]; break; } diff --git a/infolog/inc/class.infolog_sif.inc.php b/infolog/inc/class.infolog_sif.inc.php index c35e4e61ac..602e7fca21 100644 --- a/infolog/inc/class.infolog_sif.inc.php +++ b/infolog/inc/class.infolog_sif.inc.php @@ -116,9 +116,10 @@ class infolog_sif extends infolog_bo * * @param string $sifData the SIF data * @param string $_sifType type (note/task) + * @param int $_id=-1 the infolog id * @return array infolog entry or false on error */ - function siftoegw($sifData, $_sifType) + function siftoegw($sifData, $_sifType, $_id=-1) { $sysCharSet = $GLOBALS['egw']->translation->charset(); @@ -203,7 +204,10 @@ class infolog_sif extends infolog_bo case 'info_cat': if (!empty($value)) { - $categories = $this->find_or_add_categories(explode(';', $value)); + $categories1 = explode(',', $value); + $categories2 = explode(';', $value); + $categories = count($categories1) > count($categories2) ? $categories1 : $categories2; + $categories = $this->find_or_add_categories($categories, $_id); $taskData['info_cat'] = $categories[0]; } break; @@ -307,7 +311,10 @@ class infolog_sif extends infolog_bo case 'info_cat': if (!empty($value)) { - $categories = $this->find_or_add_categories(explode(';', $value)); + $categories1 = explode(',', $value); + $categories2 = explode(';', $value); + $categories = count($categories1) > count($categories2) ? $categories1 : $categories2; + $categories = $this->find_or_add_categories($categories, $_id); $noteData['info_cat'] = $categories[0]; } break; @@ -338,7 +345,7 @@ class infolog_sif extends infolog_bo */ function searchSIF($_sifData, $_sifType, $contentID=null, $relax=false) { - if (!($egwData = $this->siftoegw($_sifData, $_sifType))) return false; + if (!($egwData = $this->siftoegw($_sifData, $_sifType, $contentID))) return false; if ($contentID) $egwData['info_id'] = $contentID; @@ -372,7 +379,7 @@ class infolog_sif extends infolog_bo */ function addSIF($_sifData, $_id, $_sifType, $merge=false) { - if (!($egwData = $this->siftoegw($_sifData, $_sifType))) return false; + if (!($egwData = $this->siftoegw($_sifData, $_sifType, $_id))) return false; if ($_id > 0) $egwData['info_id'] = $_id; @@ -513,7 +520,7 @@ class infolog_sif extends infolog_bo case 'Categories': if (!empty($value) && $value) { - $value = implode('; ', $this->get_categories(array($value))); + $value = implode(', ', $this->get_categories(array($value))); $value = $GLOBALS['egw']->translation->convert($value, $sysCharSet, 'utf-8'); } else diff --git a/phpgwapi/inc/class.categories.inc.php b/phpgwapi/inc/class.categories.inc.php index 333417fd71..985b7cb6e8 100644 --- a/phpgwapi/inc/class.categories.inc.php +++ b/phpgwapi/inc/class.categories.inc.php @@ -94,7 +94,7 @@ class categories case 'mains': $where = 'cat_parent = 0'; break; default: return False; } - return $this->db->select($this->table,'COUNT(*)',$where,__LINE__,__FILE__)->fetchColumn(); + return $this->db->select($this->table,'COUNT(*)',$where,__LINE__,__FILE__)->fetchSingle(); } /** @@ -106,7 +106,7 @@ class categories */ function return_all_children($cat_id) { - $all_children = array($cat_id); + $all_children = (array) $cat_id; $children = $this->return_array('subs',0,False,'','','',True,$cat_id,-1,'id'); if (is_array($children) && count($children)) @@ -190,7 +190,7 @@ class categories $where = '(cat_appname=' . $this->db->quote($this->app_name) . ' AND ' . $grant_cats . $global_cats . ')' . $parent_filter . $querymethod . $filter; - $this->total_records = $this->db->select($this->table,'COUNT(*)',$where,__LINE__,__FILE__)->fetchColumn(); + $this->total_records = $this->db->select($this->table,'COUNT(*)',$where,__LINE__,__FILE__)->fetchSingle(); if (!$this->total_records) return false; @@ -490,6 +490,58 @@ class categories return $id; } + /** + * Checks if the current user has the necessary ACL rights + * + * If the access of a category is set to private, one needs a private grant for the application + * + * @param int $needed necessary ACL right: EGW_ACL_{READ|EDIT|DELETE} + * @param mixed $category category as array or the category_id + * @return boolean true permission granted, false for permission denied, null for category does not exist + */ + public function check_perms($needed,$category) + { + if (!is_array($category)) + { + if (!isset($this->cache_id2cat_data[$category])) + { + if (($cat = $this->db->select($this->table,'*',array('cat_id' => $category),__LINE__,__FILE__)->fetch())) + { + $cat = egw_db::strip_array_keys($cat,'cat_'); + $cat['app_name'] = $cat['appname']; + $this->cache_id2cat_data[$category] = $cat; + } + else return null; + } + $category = $this->cache_id2cat_data[$category]; + } + + // The user for the global cats has id -1, this one has full access to all global cats + if ($this->account_id == -1 && ($category['appname'] == 'phpgw' + || $category['appname'] == $this->app_name && $category['owner'] == -1)) + { + return true; + } + + // Read access to global categories + if ($needed == EGW_ACL_READ && ($category['appname'] == 'phpgw' + || $category['appname'] == $this->app_name && $category['owner'] == -1)) + { + return true; + } + + // Full access to own categories + if ($category['appname'] == $this->app_name && $category['owner'] == $this->account_id) + { + return true; + } + + // Check for ACL granted access, the -1 user must not get access by ACL to keep old behaviour + return ($this->account_id != -1 && $category['appname'] == $this->app_name && ($this->grants[$category['owner']] & $needed) && + ($category['access'] == 'public' || ($this->grants[$category['owner']] & EGW_ACL_PRIVATE))); + } + + /** * delete a category * @@ -731,7 +783,7 @@ class categories } } $where[] = $grant_cats . ")"; - return $cache[$type][$cat_name][$cat_id][$private] = $this->db->select($this->table,'cat_id',$where,__LINE__,__FILE__)->fetchColumn(); + return $cache[$type][$cat_name][$cat_id][$private] = $this->db->select($this->table,'cat_id',$where,__LINE__,__FILE__)->fetchSingle(); } /**