Projects
Kolab:Winterfell
roundcubemail-plugins-kolab
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 143
View file
roundcubemail-plugins-kolab.spec
Changed
@@ -35,13 +35,13 @@ %global confdir %{_sysconfdir}/roundcubemail %global tmpdir %{_var}/lib/roundcubemail -%global rc_version 3.5.4 +%global rc_version 3.5.6 #%%global rc_rel_suffix beta1 %global dot_rel_suffix %{?rc_rel_suffix:.%{rc_rel_suffix}} %global dash_rel_suffix %{?rc_rel_suffix:-%{rc_rel_suffix}} Name: roundcubemail-plugins-kolab -Version: 3.5.5 +Version: 3.5.6 Release: 1%{?dot_rel_suffix}%{?dist} @@ -2794,6 +2794,9 @@ %defattr(-,root,root,-) %changelog +* Mon Apr 12 2021 Jeroen van Meeuwen <vanmeeuwen@apheleia-it.ch> - 3.5.6-1 +- Release of version 3.5.6 + * Fri Oct 16 2020 Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> - 3.5.5-1 - Release of version 3.5.5
View file
debian.changelog
Changed
@@ -1,3 +1,9 @@ +roundcubemail-plugins-kolab (1:3.5.6-0~kolab1) unstable; urgency=low + + * Release version 3.5.6 + + -- Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com> Mon, 12 Apr 2021 11:11:11 +0200 + roundcubemail-plugins-kolab (1:3.5.5-0~kolab2) unstable; urgency=low * Release version 3.5.5
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/less-build.sh -> roundcubemail-plugins-kolab-3.5.6.tar.gz/less-build.sh
Changed
@@ -3,7 +3,4 @@ # First you have to link/copy /skins directory from Roundcube repo # into ./skins here -# Note: You can remove -x option to generate non-minified file -# (remember to remove ".min" from the output file name) - -lessc --relative-urls -x plugins/libkolab/skins/elastic/libkolab.less > plugins/libkolab/skins/elastic/libkolab.min.css +lessc --clean-css="--s1 --advanced" --rewrite-urls=all plugins/libkolab/skins/elastic/libkolab.less > plugins/libkolab/skins/elastic/libkolab.min.css
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/calendar/calendar.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/calendar/calendar.php
Changed
@@ -25,3573 +25,3946 @@ class calendar extends rcube_plugin { - const FREEBUSY_UNKNOWN = 0; - const FREEBUSY_FREE = 1; - const FREEBUSY_BUSY = 2; - const FREEBUSY_TENTATIVE = 3; - const FREEBUSY_OOF = 4; - - const SESSION_KEY = 'calendar_temp'; - - public $task = '?(?!logout).*'; - public $rc; - public $lib; - public $resources_dir; - public $home; // declare public to be used in other classes - public $urlbase; - public $timezone; - public $timezone_offset; - public $gmt_offset; - public $ui; - - public $defaults = array( - 'calendar_default_view' => "agendaWeek", - 'calendar_timeslots' => 2, - 'calendar_work_start' => 6, - 'calendar_work_end' => 18, - 'calendar_agenda_range' => 60, - 'calendar_event_coloring' => 0, - 'calendar_time_indicator' => true, - 'calendar_allow_invite_shared' => false, - 'calendar_itip_send_option' => 3, - 'calendar_itip_after_action' => 0, - ); - -// These are implemented with __get() -// private $ical; -// private $itip; -// private $driver; - - - /** - * Plugin initialization. - */ - function init() - { - $this->rc = rcube::get_instance(); - - $this->register_task('calendar', 'calendar'); - - // load calendar configuration - $this->load_config(); - - // catch iTIP confirmation requests that don're require a valid session - if ($this->rc->action == 'attend' && !empty($_REQUEST['_t'])) { - $this->add_hook('startup', array($this, 'itip_attend_response')); - } - else if ($this->rc->action == 'feed' && !empty($_REQUEST['_cal'])) { - $this->add_hook('startup', array($this, 'ical_feed_export')); - } - else if ($this->rc->task != 'login') { - // default startup routine - $this->add_hook('startup', array($this, 'startup')); - } - - $this->add_hook('user_delete', array($this, 'user_delete')); - } - - /** - * Setup basic plugin environment and UI - */ - protected function setup() - { - $this->require_plugin('libcalendaring'); - $this->require_plugin('libkolab'); - - $this->lib = libcalendaring::get_instance(); - $this->timezone = $this->lib->timezone; - $this->gmt_offset = $this->lib->gmt_offset; - $this->dst_active = $this->lib->dst_active; - $this->timezone_offset = $this->gmt_offset / 3600 - $this->dst_active; - - // load localizations - $this->add_texts('localization/', $this->rc->task == 'calendar' && (!$this->rc->action || $this->rc->action == 'print')); - - require($this->home . '/lib/calendar_ui.php'); - $this->ui = new calendar_ui($this); - } - - /** - * Startup hook - */ - public function startup($args) - { - // the calendar module can be enabled/disabled by the kolab_auth plugin - if ($this->rc->config->get('calendar_disabled', false) || !$this->rc->config->get('calendar_enabled', true)) - return; - - $this->setup(); - - // load Calendar user interface - if (!$this->rc->output->ajax_call && (!$this->rc->output->env['framed'] || $args['action'] == 'preview')) { - $this->ui->init(); - - // settings are required in (almost) every GUI step - if ($args['action'] != 'attend') - $this->rc->output->set_env('calendar_settings', $this->load_settings()); + const FREEBUSY_UNKNOWN = 0; + const FREEBUSY_FREE = 1; + const FREEBUSY_BUSY = 2; + const FREEBUSY_TENTATIVE = 3; + const FREEBUSY_OOF = 4; + + const SESSION_KEY = 'calendar_temp'; + + public $task = '?(?!logout).*'; + public $rc; + public $lib; + public $resources_dir; + public $home; // declare public to be used in other classes + public $urlbase; + public $timezone; + public $timezone_offset; + public $gmt_offset; + public $ui; + + public $defaults = [ + 'calendar_default_view' => "agendaWeek", + 'calendar_timeslots' => 2, + 'calendar_work_start' => 6, + 'calendar_work_end' => 18, + 'calendar_agenda_range' => 60, + 'calendar_show_weekno' => 0, + 'calendar_first_day' => 1, + 'calendar_first_hour' => 6, + 'calendar_time_format' => null, + 'calendar_event_coloring' => 0, + 'calendar_time_indicator' => true, + 'calendar_allow_invite_shared' => false, + 'calendar_itip_send_option' => 3, + 'calendar_itip_after_action' => 0, + ]; + + // These are implemented with __get() + // private $ical; + // private $itip; + // private $driver; + + + /** + * Plugin initialization. + */ + function init() + { + $this->rc = rcube::get_instance(); + + $this->register_task('calendar', 'calendar'); + + // load calendar configuration + $this->load_config(); + + // catch iTIP confirmation requests that don're require a valid session + if ($this->rc->action == 'attend' && !empty($_REQUEST['_t'])) { + $this->add_hook('startup', [$this, 'itip_attend_response']); + } + else if ($this->rc->action == 'feed' && !empty($_REQUEST['_cal'])) { + $this->add_hook('startup', [$this, 'ical_feed_export']); + } + else if ($this->rc->task != 'login') { + // default startup routine + $this->add_hook('startup', [$this, 'startup']); + } + + $this->add_hook('user_delete', [$this, 'user_delete']); + } + + /** + * Setup basic plugin environment and UI + */ + protected function setup() + { + $this->require_plugin('libcalendaring'); + $this->require_plugin('libkolab'); + + $this->lib = libcalendaring::get_instance(); + $this->timezone = $this->lib->timezone; + $this->gmt_offset = $this->lib->gmt_offset; + $this->dst_active = $this->lib->dst_active; + $this->timezone_offset = $this->gmt_offset / 3600 - $this->dst_active; + + // load localizations + $this->add_texts('localization/', $this->rc->task == 'calendar' && (!$this->rc->action || $this->rc->action == 'print')); + + require($this->home . '/lib/calendar_ui.php'); + $this->ui = new calendar_ui($this); + } + + /** + * Startup hook
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/calendar/composer.json -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/calendar/composer.json
Changed
@@ -4,7 +4,7 @@ "description": "Calendar plugin", "homepage": "https://git.kolab.org/diffusion/RPK/", "license": "AGPLv3", - "version": "3.5.5", + "version": "3.5.6", "authors": [ { "name": "Thomas Bruederli", @@ -24,7 +24,7 @@ } ], "require": { - "php": ">=5.3.0", + "php": ">=5.4.0", "roundcube/plugin-installer": ">=0.1.3", "kolab/libcalendaring": ">=3.4.0", "kolab/libkolab": ">=3.4.0"
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/calendar/drivers/calendar_driver.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/calendar/drivers/calendar_driver.php
Changed
@@ -94,740 +94,770 @@ */ abstract class calendar_driver { - const FILTER_ALL = 0; - const FILTER_WRITEABLE = 1; - const FILTER_INSERTABLE = 2; - const FILTER_ACTIVE = 4; - const FILTER_PERSONAL = 8; - const FILTER_PRIVATE = 16; - const FILTER_CONFIDENTIAL = 32; - const FILTER_SHARED = 64; - const BIRTHDAY_CALENDAR_ID = '__bdays__'; - - // features supported by backend - public $alarms = false; - public $attendees = false; - public $freebusy = false; - public $attachments = false; - public $undelete = false; - public $history = false; - public $categoriesimmutable = false; - public $alarm_types = array('DISPLAY'); - public $alarm_absolute = true; - public $last_error; - - protected $default_categories = array( - 'Personal' => 'c0c0c0', - 'Work' => 'ff0000', - 'Family' => '00ff00', - 'Holiday' => 'ff6600', - ); - - /** - * Get a list of available calendars from this source - * - * @param integer Bitmask defining filter criterias. - * See FILTER_* constants for possible values. - * @return array List of calendars - */ - abstract function list_calendars($filter = 0); - - /** - * Create a new calendar assigned to the current user - * - * @param array Hash array with calendar properties - * name: Calendar name - * color: The color of the calendar - * showalarms: True if alarms are enabled - * @return mixed ID of the calendar on success, False on error - */ - abstract function create_calendar($prop); - - /** - * Update properties of an existing calendar - * - * @param array Hash array with calendar properties - * id: Calendar Identifier - * name: Calendar name - * color: The color of the calendar - * showalarms: True if alarms are enabled (if supported) - * @return boolean True on success, Fales on failure - */ - abstract function edit_calendar($prop); - - /** - * Set active/subscribed state of a calendar - * - * @param array Hash array with calendar properties - * id: Calendar Identifier - * active: True if calendar is active, false if not - * @return boolean True on success, Fales on failure - */ - abstract function subscribe_calendar($prop); - - /** - * Delete the given calendar with all its contents - * - * @param array Hash array with calendar properties - * id: Calendar Identifier - * @return boolean True on success, Fales on failure - */ - abstract function delete_calendar($prop); - - /** - * Search for shared or otherwise not listed calendars the user has access - * - * @param string Search string - * @param string Section/source to search - * @return array List of calendars - */ - abstract function search_calendars($query, $source); - - /** - * Add a single event to the database - * - * @param array Hash array with event properties (see header of this file) - * @return mixed New event ID on success, False on error - */ - abstract function new_event($event); - - /** - * Update an event entry with the given data - * - * @param array Hash array with event properties (see header of this file) - * @return boolean True on success, False on error - */ - abstract function edit_event($event); - - /** - * Extended event editing with possible changes to the argument - * - * @param array Hash array with event properties - * @param string New participant status - * @param array List of hash arrays with updated attendees - * @return boolean True on success, False on error - */ - public function edit_rsvp(&$event, $status, $attendees) - { - return $this->edit_event($event); - } - - /** - * Update the participant status for the given attendee - * - * @param array Hash array with event properties - * @param array List of hash arrays each represeting an updated attendee - * @return boolean True on success, False on error - */ - public function update_attendees(&$event, $attendees) - { - return $this->edit_event($event); - } - - /** - * Move a single event - * - * @param array Hash array with event properties: - * id: Event identifier - * start: Event start date/time as DateTime object - * end: Event end date/time as DateTime object - * allday: Boolean flag if this is an all-day event - * @return boolean True on success, False on error - */ - abstract function move_event($event); - - /** - * Resize a single event - * - * @param array Hash array with event properties: - * id: Event identifier - * start: Event start date/time as DateTime object with timezone - * end: Event end date/time as DateTime object with timezone - * @return boolean True on success, False on error - */ - abstract function resize_event($event); - - /** - * Remove a single event from the database - * - * @param array Hash array with event properties: - * id: Event identifier - * @param boolean Remove event irreversible (mark as deleted otherwise, - * if supported by the backend) - * - * @return boolean True on success, False on error - */ - abstract function remove_event($event, $force = true); - - /** - * Restores a single deleted event (if supported) - * - * @param array Hash array with event properties: - * id: Event identifier - * - * @return boolean True on success, False on error - */ - public function restore_event($event) - { - return false; - } - - /** - * Return data of a single event - * - * @param mixed UID string or hash array with event properties: - * id: Event identifier - * uid: Event UID - * _instance: Instance identifier in combination with uid (optional) - * calendar: Calendar identifier (optional) - * @param integer Bitmask defining the scope to search events in. - * See FILTER_* constants for possible values. - * @param boolean If true, recurrence exceptions shall be added - * - * @return array Event object as hash array - */ - abstract function get_event($event, $scope = 0, $full = false); - - /** - * Get events from source.
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/calendar/drivers/database/database_driver.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/calendar/drivers/database/database_driver.php
Changed
@@ -136,7 +136,7 @@ $hidden = array_filter(explode(',', $this->rc->config->get('hidden_calendars', ''))); $id = self::BIRTHDAY_CALENDAR_ID; - if (!$active || !in_array($id, $hidden)) { + if (empty($active) || !in_array($id, $hidden)) { $calendars[$id] = array( 'id' => $id, 'name' => $this->cal->gettext('birthdays'), @@ -172,7 +172,7 @@ $this->rc->user->ID, $prop['name'], strval($prop['color']), - $prop['showalarms'] ? 1 : 0 + !empty($prop['showalarms']) ? 1 : 0 ); if ($result) { @@ -321,24 +321,24 @@ . " VALUES (?, $now, $now, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", $event['calendar'], strval($event['uid']), - intval($event['recurrence_id']), - strval($event['_instance']), - intval($event['isexception']), + isset($event['recurrence_id']) ? intval($event['recurrence_id']) : 0, + isset($event['_instance']) ? strval($event['_instance']) : '', + isset($event['isexception']) ? intval($event['isexception']) : 0, $event['start']->format(self::DB_DATE_FORMAT), $event['end']->format(self::DB_DATE_FORMAT), intval($event['all_day']), $event['_recurrence'], strval($event['title']), - strval($event['description']), - strval($event['location']), - join(',', (array)$event['categories']), - strval($event['url']), + isset($event['description']) ? strval($event['description']) : '', + isset($event['location']) ? strval($event['location']) : '', + isset($event['categories']) ? join(',', (array) $event['categories']) : '', + isset($event['url']) ? strval($event['url']) : '', intval($event['free_busy']), intval($event['priority']), intval($event['sensitivity']), - strval($event['status']), + isset($event['status']) ? strval($event['status']) : '', $event['attendees'], - $event['alarms'], + isset($event['alarms']) ? $event['alarms'] : null, $event['notifyat'] ); @@ -381,7 +381,7 @@ // increment sequence number if (empty($event['sequence']) && $reschedule) { - $event['sequence'] = max($event['sequence'], $old['sequence']) + 1; + $event['sequence'] = $old['sequence'] + 1; } // modify a recurring event, check submitted savemode to do the right things @@ -389,11 +389,12 @@ $master = $old['recurrence_id'] ? $this->get_event(array('id' => $old['recurrence_id'])) : $old; // keep saved exceptions (not submitted by the client) - if ($old['recurrence']['EXDATE']) { + if (!empty($old['recurrence']['EXDATE'])) { $event['recurrence']['EXDATE'] = $old['recurrence']['EXDATE']; } - switch ($event['_savemode']) { + $savemode = isset($event['_savemode']) ? $event['_savemode'] : null; + switch ($savemode) { case 'new': $event['uid'] = $this->cal->generate_uid(); return $this->new_event($event); @@ -582,10 +583,12 @@ // iterate through the list of properties considered 'significant' for scheduling foreach (self::$scheduling_properties as $prop) { - $a = $old[$prop]; - $b = $event[$prop]; + $a = isset($old[$prop]) ? $old[$prop] : null; + $b = isset($event[$prop]) ? $event[$prop] : null; - if ($event['allday'] && ($prop == 'start' || $prop == 'end') && $a instanceof DateTime && $b instanceof DateTime) { + if (!empty($event['allday']) && ($prop == 'start' || $prop == 'end') + && $a instanceof DateTime && $b instanceof DateTime + ) { $a = $a->format('Y-m-d'); $b = $b->format('Y-m-d'); } @@ -596,10 +599,10 @@ $b = array_filter($b); // advanced rrule comparison: no rescheduling if series was shortened - if ($a['COUNT'] && $b['COUNT'] && $b['COUNT'] < $a['COUNT']) { + if (!empty($a['COUNT']) && !empty($b['COUNT']) && $b['COUNT'] < $a['COUNT']) { unset($a['COUNT'], $b['COUNT']); } - else if ($a['UNTIL'] && $b['UNTIL'] && $b['UNTIL'] < $a['UNTIL']) { + else if (!empty($a['UNTIL']) && !empty($b['UNTIL']) && $b['UNTIL'] < $a['UNTIL']) { unset($a['UNTIL'], $b['UNTIL']); } } @@ -652,24 +655,24 @@ } // compose vcalendar-style recurrencue rule from structured data - $rrule = $event['recurrence'] ? libcalendaring::to_rrule($event['recurrence']) : ''; + $rrule = !empty($event['recurrence']) ? libcalendaring::to_rrule($event['recurrence']) : ''; + + $sensitivity = strtolower($event['sensitivity']); + $free_busy = strtolower($event['free_busy']); $event['_recurrence'] = rtrim($rrule, ';'); - $event['free_busy'] = intval($this->free_busy_map[strtolower($event['free_busy'])]); - $event['sensitivity'] = intval($this->sensitivity_map[strtolower($event['sensitivity'])]); + $event['free_busy'] = isset($this->free_busy_map[$free_busy]) ? $this->free_busy_map[$free_busy] : null; + $event['sensitivity'] = isset($this->sensitivity_map[$sensitivity]) ? $this->sensitivity_map[$sensitivity] : null; + $event['all_day'] = !empty($event['allday']) ? 1 : 0; if ($event['free_busy'] == 'tentative') { $event['status'] = 'TENTATIVE'; } - if (isset($event['allday'])) { - $event['all_day'] = $event['allday'] ? 1 : 0; - } - // compute absolute time to notify the user $event['notifyat'] = $this->_get_notification($event); - if (is_array($event['valarms'])) { + if (!empty($event['valarms'])) { $event['alarms'] = $this->serialize_alarms($event['valarms']); } @@ -689,7 +692,7 @@ */ private function _get_notification($event) { - if ($event['valarms'] && $event['start'] > new DateTime()) { + if (!empty($event['valarms']) && $event['start'] > new DateTime()) { $alarm = libcalendaring::get_next_alarm($event); if ($alarm['time'] && in_array($alarm['action'], $this->alarm_types)) { @@ -714,26 +717,23 @@ ); foreach ($set_cols as $col) { - if (is_object($event[$col]) && is_a($event[$col], 'DateTime')) { + if (!empty($event[$col]) && is_a($event[$col], 'DateTime')) { $sql_args[$col] = $event[$col]->format(self::DB_DATE_FORMAT); } - else if (is_array($event[$col])) { - $sql_args[$col] = join(',', $event[$col]); - } else if (array_key_exists($col, $event)) { - $sql_args[$col] = $event[$col]; + $sql_args[$col] = is_array($event[$col]) ? join(',', $event[$col]) : $event[$col]; } } - if ($event['_recurrence']) { + if (!empty($event['_recurrence'])) { $sql_args['recurrence'] = $event['_recurrence']; } - if ($event['_instance']) { + if (!empty($event['_instance'])) { $sql_args['instance'] = $event['_instance']; } - if ($event['_fromcalendar'] && $event['_fromcalendar'] != $event['calendar']) { + if (!empty($event['_fromcalendar']) && $event['_fromcalendar'] != $event['calendar']) { $sql_args['calendar_id'] = $event['calendar']; } @@ -763,7 +763,7 @@ } // remove attachments - if ($success && !empty($event['deleted_attachments'])) { + if ($success && !empty($event['deleted_attachments']) && is_array($event['deleted_attachments'])) { foreach ($event['deleted_attachments'] as $attachment) { $this->remove_attachment($attachment, $event['id']); } @@ -822,7 +822,7 @@ // skip exceptions // TODO: merge updated data from master event - if ($exdata[$datestr]) { + if (!empty($exdata[$datestr])) { continue; } @@ -831,7 +831,7 @@ $next_end->add($duration);
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/calendar/drivers/kolab/kolab_calendar.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/calendar/drivers/kolab/kolab_calendar.php
Changed
@@ -26,888 +26,933 @@ class kolab_calendar extends kolab_storage_folder_api { - public $ready = false; - public $rights = 'lrs'; - public $editable = false; - public $attachments = true; - public $alarms = false; - public $history = false; - public $subscriptions = true; - public $categories = array(); - public $storage; - - public $type = 'event'; - - protected $cal; - protected $events = array(); - protected $search_fields = array('title', 'description', 'location', 'attendees', 'categories'); - - /** - * Factory method to instantiate a kolab_calendar object - * - * @param string Calendar ID (encoded IMAP folder name) - * @param object calendar plugin object - * @return object kolab_calendar instance - */ - public static function factory($id, $calendar) - { - $imap = $calendar->rc->get_storage(); - $imap_folder = kolab_storage::id_decode($id); - $info = $imap->folder_info($imap_folder, true); - if (empty($info) || $info['noselect'] || strpos(kolab_storage::folder_type($imap_folder), 'event') !== 0) { - return new kolab_user_calendar($imap_folder, $calendar); - } - else { - return new kolab_calendar($imap_folder, $calendar); - } - } - - /** - * Default constructor - */ - public function __construct($imap_folder, $calendar) - { - $this->cal = $calendar; - $this->imap = $calendar->rc->get_storage(); - $this->name = $imap_folder; - - // ID is derrived from folder name - $this->id = kolab_storage::folder_id($this->name, true); - $old_id = kolab_storage::folder_id($this->name, false); - - // fetch objects from the given IMAP folder - $this->storage = kolab_storage::get_folder($this->name); - $this->ready = $this->storage && $this->storage->valid; - - // Set writeable and alarms flags according to folder permissions - if ($this->ready) { - if ($this->storage->get_namespace() == 'personal') { - $this->editable = true; - $this->rights = 'lrswikxteav'; - $this->alarms = true; - } - else { - $rights = $this->storage->get_myrights(); - if ($rights && !PEAR::isError($rights)) { - $this->rights = $rights; - if (strpos($rights, 't') !== false || strpos($rights, 'd') !== false) - $this->editable = strpos($rights, 'i');; - } - } - - // user-specific alarms settings win - $prefs = $this->cal->rc->config->get('kolab_calendars', array()); - if (isset($prefs[$this->id]['showalarms'])) - $this->alarms = $prefs[$this->id]['showalarms']; - else if (isset($prefs[$old_id]['showalarms'])) - $this->alarms = $prefs[$old_id]['showalarms']; - } + public $ready = false; + public $rights = 'lrs'; + public $editable = false; + public $attachments = true; + public $alarms = false; + public $history = false; + public $subscriptions = true; + public $categories = []; + public $storage; + + public $type = 'event'; + + protected $cal; + protected $events = []; + protected $search_fields = ['title', 'description', 'location', 'attendees', 'categories']; + + /** + * Factory method to instantiate a kolab_calendar object + * + * @param string Calendar ID (encoded IMAP folder name) + * @param object Calendar plugin object + * + * @return kolab_calendar Self instance + */ + public static function factory($id, $calendar) + { + $imap = $calendar->rc->get_storage(); + $imap_folder = kolab_storage::id_decode($id); + $info = $imap->folder_info($imap_folder, true); + + if ( + empty($info) + || !empty($info['noselect']) + || strpos(kolab_storage::folder_type($imap_folder), 'event') !== 0 + ) { + return new kolab_user_calendar($imap_folder, $calendar); + } - $this->default = $this->storage->default; - $this->subtype = $this->storage->subtype; - } - - - /** - * Getter for the IMAP folder name - * - * @return string Name of the IMAP folder - */ - public function get_realname() - { - return $this->name; - } - - /** - * - */ - public function get_title() - { - return null; - } - - - /** - * Return color to display this calendar - */ - public function get_color($default = null) - { - // color is defined in folder METADATA - if ($color = $this->storage->get_color()) { - return $color; + return new kolab_calendar($imap_folder, $calendar); } - // calendar color is stored in user prefs (temporary solution) - $prefs = $this->cal->rc->config->get('kolab_calendars', array()); - - if (!empty($prefs[$this->id]) && !empty($prefs[$this->id]['color'])) - return $prefs[$this->id]['color']; - - return $default ?: 'cc0000'; - } - - /** - * Compose an URL for CalDAV access to this calendar (if configured) - */ - public function get_caldav_url() - { - if ($template = $this->cal->rc->config->get('calendar_caldav_url', null)) { - return strtr($template, array( - '%h' => $_SERVER['HTTP_HOST'], - '%u' => urlencode($this->cal->rc->get_user_name()), - '%i' => urlencode($this->storage->get_uid()), - '%n' => urlencode($this->name), - )); - } + /** + * Default constructor + */ + public function __construct($imap_folder, $calendar) + { + $this->cal = $calendar; + $this->imap = $calendar->rc->get_storage(); + $this->name = $imap_folder; - return false; - } + // ID is derrived from folder name + $this->id = kolab_storage::folder_id($this->name, true); + $old_id = kolab_storage::folder_id($this->name, false); + // fetch objects from the given IMAP folder + $this->storage = kolab_storage::get_folder($this->name); + $this->ready = $this->storage && $this->storage->valid; + + // Set writeable and alarms flags according to folder permissions + if ($this->ready) { + if ($this->storage->get_namespace() == 'personal') { + $this->editable = true; + $this->rights = 'lrswikxteav'; + $this->alarms = true;
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/calendar/drivers/kolab/kolab_driver.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/calendar/drivers/kolab/kolab_driver.php
Changed
@@ -25,2409 +25,2619 @@ class kolab_driver extends calendar_driver { - const INVITATIONS_CALENDAR_PENDING = '--invitation--pending'; - const INVITATIONS_CALENDAR_DECLINED = '--invitation--declined'; - - // features this backend supports - public $alarms = true; - public $attendees = true; - public $freebusy = true; - public $attachments = true; - public $undelete = true; - public $alarm_types = array('DISPLAY','AUDIO'); - public $categoriesimmutable = true; - - private $rc; - private $cal; - private $calendars; - private $has_writeable = false; - private $freebusy_trigger = false; - private $bonnie_api = false; - - /** - * Default constructor - */ - public function __construct($cal) - { - $cal->require_plugin('libkolab'); - - // load helper classes *after* libkolab has been loaded (#3248) - require_once(dirname(__FILE__) . '/kolab_calendar.php'); - require_once(dirname(__FILE__) . '/kolab_user_calendar.php'); - require_once(dirname(__FILE__) . '/kolab_invitation_calendar.php'); - - $this->cal = $cal; - $this->rc = $cal->rc; - - $this->cal->register_action('push-freebusy', array($this, 'push_freebusy')); - $this->cal->register_action('calendar-acl', array($this, 'calendar_acl')); - - $this->freebusy_trigger = $this->rc->config->get('calendar_freebusy_trigger', false); - - if (kolab_storage::$version == '2.0') { - $this->alarm_types = array('DISPLAY'); - $this->alarm_absolute = false; - } + const INVITATIONS_CALENDAR_PENDING = '--invitation--pending'; + const INVITATIONS_CALENDAR_DECLINED = '--invitation--declined'; + + // features this backend supports + public $alarms = true; + public $attendees = true; + public $freebusy = true; + public $attachments = true; + public $undelete = true; + public $alarm_types = ['DISPLAY', 'AUDIO']; + public $categoriesimmutable = true; + + private $rc; + private $cal; + private $calendars; + private $has_writeable = false; + private $freebusy_trigger = false; + private $bonnie_api = false; + + /** + * Default constructor + */ + public function __construct($cal) + { + $cal->require_plugin('libkolab'); + + // load helper classes *after* libkolab has been loaded (#3248) + require_once(__DIR__ . '/kolab_calendar.php'); + require_once(__DIR__ . '/kolab_user_calendar.php'); + require_once(__DIR__ . '/kolab_invitation_calendar.php'); + + $this->cal = $cal; + $this->rc = $cal->rc; + + $this->cal->register_action('push-freebusy', [$this, 'push_freebusy']); + $this->cal->register_action('calendar-acl', [$this, 'calendar_acl']); + + $this->freebusy_trigger = $this->rc->config->get('calendar_freebusy_trigger', false); + + if (kolab_storage::$version == '2.0') { + $this->alarm_types = ['DISPLAY']; + $this->alarm_absolute = false; + } - // get configuration for the Bonnie API - $this->bonnie_api = libkolab::get_bonnie_api(); + // get configuration for the Bonnie API + $this->bonnie_api = libkolab::get_bonnie_api(); - // calendar uses fully encoded identifiers - kolab_storage::$encode_ids = true; - } + // calendar uses fully encoded identifiers + kolab_storage::$encode_ids = true; + } + /** + * Read available calendars from server + */ + private function _read_calendars() + { + // already read sources + if (isset($this->calendars)) { + return $this->calendars; + } - /** - * Read available calendars from server - */ - private function _read_calendars() - { - // already read sources - if (isset($this->calendars)) - return $this->calendars; + // get all folders that have "event" type, sorted by namespace/name + $folders = kolab_storage::sort_folders( + kolab_storage::get_folders('event') + kolab_storage::get_user_folders('event', true) + ); - // get all folders that have "event" type, sorted by namespace/name - $folders = kolab_storage::sort_folders(kolab_storage::get_folders('event') + kolab_storage::get_user_folders('event', true)); + $this->calendars = []; - $this->calendars = array(); - foreach ($folders as $folder) { - $calendar = $this->_to_calendar($folder); - if ($calendar->ready) { - $this->calendars[$calendar->id] = $calendar; - if ($calendar->editable) { - $this->has_writeable = true; + foreach ($folders as $folder) { + $calendar = $this->_to_calendar($folder); + if ($calendar->ready) { + $this->calendars[$calendar->id] = $calendar; + if ($calendar->editable) { + $this->has_writeable = true; + } + } } - } + + return $this->calendars; } - return $this->calendars; - } + /** + * Convert kolab_storage_folder into kolab_calendar + */ + private function _to_calendar($folder) + { + if ($folder instanceof kolab_calendar) { + return $folder; + } + + if ($folder instanceof kolab_storage_folder_user) { + $calendar = new kolab_user_calendar($folder, $this->cal); + $calendar->subscriptions = count($folder->children) > 0; + } + else { + $calendar = new kolab_calendar($folder->name, $this->cal); + } - /** - * Convert kolab_storage_folder into kolab_calendar - */ - private function _to_calendar($folder) - { - if ($folder instanceof kolab_calendar) { - return $folder; + return $calendar; } - if ($folder instanceof kolab_storage_folder_user) { - $calendar = new kolab_user_calendar($folder, $this->cal); - $calendar->subscriptions = count($folder->children) > 0; + /** + * Get a list of available calendars from this source + * + * @param int $filter Bitmask defining filter criterias + * @param object $tree Reference to hierarchical folder tree object + * + * @return array List of calendars + */ + public function list_calendars($filter = 0, &$tree = null) + { + $this->_read_calendars(); + + // attempt to create a default calendar for this user + if (!$this->has_writeable) { + if ($this->create_calendar(['name' => 'Calendar', 'color' => 'cc0000'])) { + unset($this->calendars); + $this->_read_calendars();
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/calendar/drivers/kolab/kolab_invitation_calendar.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/calendar/drivers/kolab/kolab_invitation_calendar.php
Changed
@@ -23,389 +23,402 @@ class kolab_invitation_calendar { - public $id = '__invitation__'; - public $ready = true; - public $alarms = false; - public $rights = 'lrsv'; - public $editable = false; - public $attachments = false; - public $subscriptions = false; - public $partstats = array('unknown'); - public $categories = array(); - public $name = 'Invitations'; - - - /** - * Default constructor - */ - public function __construct($id, $calendar) - { - $this->cal = $calendar; - $this->id = $id; - - switch ($this->id) { - case kolab_driver::INVITATIONS_CALENDAR_PENDING: - $this->partstats = array('NEEDS-ACTION'); - $this->name = $this->cal->gettext('invitationspending'); - if (!empty($_REQUEST['_quickview'])) - $this->partstats[] = 'TENTATIVE'; - break; - - case kolab_driver::INVITATIONS_CALENDAR_DECLINED: - $this->partstats = array('DECLINED'); - $this->name = $this->cal->gettext('invitationsdeclined'); - break; + public $id = '__invitation__'; + public $ready = true; + public $alarms = false; + public $rights = 'lrsv'; + public $editable = false; + public $attachments = false; + public $subscriptions = false; + public $partstats = ['unknown']; + public $categories = []; + public $name = 'Invitations'; + + + /** + * Default constructor + */ + public function __construct($id, $calendar) + { + $this->cal = $calendar; + $this->id = $id; + + switch ($this->id) { + case kolab_driver::INVITATIONS_CALENDAR_PENDING: + $this->partstats = ['NEEDS-ACTION']; + $this->name = $this->cal->gettext('invitationspending'); + + if (!empty($_REQUEST['_quickview'])) { + $this->partstats[] = 'TENTATIVE'; + } + break; + + case kolab_driver::INVITATIONS_CALENDAR_DECLINED: + $this->partstats = ['DECLINED']; + $this->name = $this->cal->gettext('invitationsdeclined'); + break; + } + + // user-specific alarms settings win + $prefs = $this->cal->rc->config->get('kolab_calendars', []); + if (isset($prefs[$this->id]['showalarms'])) { + $this->alarms = $prefs[$this->id]['showalarms']; + } + } + + /** + * Getter for a nice and human readable name for this calendar + * + * @return string Name of this calendar + */ + public function get_name() + { + return $this->name; } - // user-specific alarms settings win - $prefs = $this->cal->rc->config->get('kolab_calendars', array()); - if (isset($prefs[$this->id]['showalarms'])) - $this->alarms = $prefs[$this->id]['showalarms']; - } - - /** - * Getter for a nice and human readable name for this calendar - * - * @return string Name of this calendar - */ - public function get_name() - { - return $this->name; - } - - /** - * Getter for the IMAP folder owner - * - * @return string Name of the folder owner - */ - public function get_owner() - { - return $this->cal->rc->get_user_name(); - } - - /** - * - */ - public function get_title() - { - return $this->get_name(); - } - - /** - * Getter for the name of the namespace to which the IMAP folder belongs - * - * @return string Name of the namespace (personal, other, shared) - */ - public function get_namespace() - { - return 'x-special'; - } - - /** - * Getter for the top-end calendar folder name (not the entire path) - * - * @return string Name of this calendar - */ - public function get_foldername() - { - return $this->get_name(); - } - - /** - * Getter for the Cyrus mailbox identifier corresponding to this folder - * - * @return string Mailbox ID - */ - public function get_mailbox_id() - { - // this is a virtual collection and has no concrete mailbox ID - return null; - } - - /** - * Return color to display this calendar - */ - public function get_color() - { - // calendar color is stored in local user prefs - $prefs = $this->cal->rc->config->get('kolab_calendars', array()); - - if (!empty($prefs[$this->id]) && !empty($prefs[$this->id]['color'])) - return $prefs[$this->id]['color']; - - return 'ffffff'; - } - - /** - * Compose an URL for CalDAV access to this calendar (if configured) - */ - public function get_caldav_url() - { - return false; - } - - /** - * Check activation status of this folder - * - * @return boolean True if enabled, false if not - */ - public function is_active() - { - $prefs = $this->cal->rc->config->get('kolab_calendars', array()); // read local prefs - return (bool)$prefs[$this->id]['active']; - } - - /** - * Update properties of this calendar folder - * - * @see calendar_driver::edit_calendar() - */ - public function update(&$prop) - { - // don't change anything. - // let kolab_driver save props in local prefs - return $prop['id']; - } - - /**
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/calendar/drivers/kolab/kolab_user_calendar.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/calendar/drivers/kolab/kolab_user_calendar.php
Changed
@@ -23,402 +23,423 @@ class kolab_user_calendar extends kolab_calendar { - public $id = 'unknown'; - public $ready = false; - public $editable = false; - public $attachments = false; - public $subscriptions = false; - - protected $userdata = array(); - protected $timeindex = array(); - - - /** - * Default constructor - */ - public function __construct($user_or_folder, $calendar) - { - $this->cal = $calendar; - $this->imap = $calendar->rc->get_storage(); - - // full user record is provided - if (is_array($user_or_folder)) { - $this->userdata = $user_or_folder; - $this->storage = new kolab_storage_folder_user($this->userdata['kolabtargetfolder'], '', $this->userdata); + public $id = 'unknown'; + public $ready = false; + public $editable = false; + public $attachments = false; + public $subscriptions = false; + + protected $userdata = []; + protected $timeindex = []; + + + /** + * Default constructor + */ + public function __construct($user_or_folder, $calendar) + { + $this->cal = $calendar; + $this->imap = $calendar->rc->get_storage(); + + // full user record is provided + if (is_array($user_or_folder)) { + $this->userdata = $user_or_folder; + $this->storage = new kolab_storage_folder_user($this->userdata['kolabtargetfolder'], '', $this->userdata); + } + else if ($user_or_folder instanceof kolab_storage_folder_user) { + $this->storage = $user_or_folder; + $this->userdata = $this->storage->ldaprec; + } + else { + // get user record from LDAP + $this->storage = new kolab_storage_folder_user($user_or_folder); + $this->userdata = $this->storage->ldaprec; + } + + $this->ready = !empty($this->userdata['kolabtargetfolder']); + $this->storage->type = 'event'; + + if ($this->ready) { + // ID is derrived from the user's kolabtargetfolder attribute + $this->id = kolab_storage::folder_id($this->userdata['kolabtargetfolder'], true); + $this->imap_folder = $this->userdata['kolabtargetfolder']; + $this->name = $this->storage->name; + $this->parent = ''; // user calendars are top level + + // user-specific alarms settings win + $prefs = $this->cal->rc->config->get('kolab_calendars', []); + if (isset($prefs[$this->id]['showalarms'])) { + $this->alarms = $prefs[$this->id]['showalarms']; + } + } } - else if ($user_or_folder instanceof kolab_storage_folder_user) { - $this->storage = $user_or_folder; - $this->userdata = $this->storage->ldaprec; + + /** + * Getter for a nice and human readable name for this calendar + * + * @return string Name of this calendar + */ + public function get_name() + { + if (!empty($this->userdata['displayname'])) { + return $this->userdata['displayname']; + } + + return !empty($this->userdata['name']) ? $this->userdata['name'] : $this->userdata['mail']; } - else { // get user record from LDAP - $this->storage = new kolab_storage_folder_user($user_or_folder); - $this->userdata = $this->storage->ldaprec; + + /** + * Getter for the IMAP folder owner + * + * @param bool Return a fully qualified owner name (unused) + * + * @return string Name of the folder owner + */ + public function get_owner($fully_qualified = false) + { + return $this->userdata['mail']; } - $this->ready = !empty($this->userdata['kolabtargetfolder']); - $this->storage->type = 'event'; + /** + * + */ + public function get_title() + { + $title = []; + + if (!empty($this->userdata['displayname'])) { + $title[] = $this->userdata['displayname']; + } + + $title[] = $this->userdata['mail']; - if ($this->ready) { - // ID is derrived from the user's kolabtargetfolder attribute - $this->id = kolab_storage::folder_id($this->userdata['kolabtargetfolder'], true); - $this->imap_folder = $this->userdata['kolabtargetfolder']; - $this->name = $this->storage->name; - $this->parent = ''; // user calendars are top level + return implode('; ', $title); + } - // user-specific alarms settings win - $prefs = $this->cal->rc->config->get('kolab_calendars', array()); - if (isset($prefs[$this->id]['showalarms'])) - $this->alarms = $prefs[$this->id]['showalarms']; + /** + * Getter for the name of the namespace to which the IMAP folder belongs + * + * @return string Name of the namespace (personal, other, shared) + */ + public function get_namespace() + { + return 'other user'; } - } - - /** - * Getter for a nice and human readable name for this calendar - * - * @return string Name of this calendar - */ - public function get_name() - { - return $this->userdata['displayname'] ?: ($this->userdata['name'] ?: $this->userdata['mail']); - } - - /** - * Getter for the IMAP folder owner - * - * @param bool Return a fully qualified owner name (unused) - * - * @return string Name of the folder owner - */ - public function get_owner($fully_qualified = false) - { - return $this->userdata['mail']; - } - - /** - * - */ - public function get_title() - { - return trim($this->userdata['displayname'] . '; ' . $this->userdata['mail'], '; '); - } - - /** - * Getter for the name of the namespace to which the IMAP folder belongs - * - * @return string Name of the namespace (personal, other, shared) - */ - public function get_namespace() - { - return 'other user'; - } - - /** - * Getter for the top-end calendar folder name (not the entire path) - * - * @return string Name of this calendar - */ - public function get_foldername() - { - return $this->get_name(); - } - - /** - * Return color to display this calendar
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/calendar/drivers/ldap/resources_driver_ldap.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/calendar/drivers/ldap/resources_driver_ldap.php
Changed
@@ -41,72 +41,76 @@ /** * Fetch resource objects to be displayed for booking * - * @param string Search query (optional) - * @return array List of resource records available for booking + * @param string $query Search query (optional) + * @param int $num Max size of the result + * + * @return array List of resource records available for booking */ public function load_resources($query = null, $num = 5000) { - if (!($ldap = $this->connect())) { - return array(); - } - - // TODO: apply paging - $ldap->set_pagesize($num); - - if (isset($query)) { - $results = $ldap->search('*', $query, 0, true, true); - } - else { - $results = $ldap->list_records(); - } - - if ($results instanceof ArrayAccess) { - foreach ($results as $i => $rec) { - $results[$i] = $this->decode_resource($rec); + if (!($ldap = $this->connect())) { + return []; + } + + // TODO: apply paging + $ldap->set_pagesize($num); + + if (isset($query)) { + $results = $ldap->search('*', $query, 0, true, true); + } + else { + $results = $ldap->list_records(); } - } - return $results; + if ($results instanceof ArrayAccess) { + foreach ($results as $i => $rec) { + $results[$i] = $this->decode_resource($rec); + } + } + + return $results; } /** * Return properties of a single resource * - * @param string Unique resource identifier + * @param string $id Unique resource identifier + * * @return array Resource object as hash array */ public function get_resource($dn) { - $rec = null; + $rec = null; - if ($ldap = $this->connect()) { - $rec = $ldap->get_record(rcube_ldap::dn_encode($dn), true); + if ($ldap = $this->connect()) { + $rec = $ldap->get_record(rcube_ldap::dn_encode($dn), true); - if (!empty($rec)) { - $rec = $this->decode_resource($rec); + if (!empty($rec)) { + $rec = $this->decode_resource($rec); + } } - } - return $rec; + return $rec; } /** * Return properties of a resource owner * - * @param string Owner identifier - * @return array Resource object as hash array + * @param string $dn Owner identifier + * + * @return array Resource object as hash array */ public function get_resource_owner($dn) { - $owner = null; + $owner = null; - if ($ldap = $this->connect()) { - $owner = $ldap->get_record(rcube_ldap::dn_encode($dn), true); - $owner['ID'] = rcube_ldap::dn_decode($owner['ID']); - unset($owner['_raw_attrib'], $owner['_type']); - } + if ($ldap = $this->connect()) { + $owner = $ldap->get_record(rcube_ldap::dn_encode($dn), true); + $owner['ID'] = rcube_ldap::dn_decode($owner['ID']); + unset($owner['_raw_attrib'], $owner['_type']); + } - return $owner; + return $owner; } /** @@ -114,41 +118,40 @@ */ private function decode_resource($rec) { - $rec['ID'] = rcube_ldap::dn_decode($rec['ID']); - - $attributes = array(); - - foreach ((array) $rec['attributes'] as $sattr) { - $sattr = trim($sattr); - if ($sattr && $sattr[0] === '{') { - $attr = @json_decode($sattr, true); - $attributes += $attr; + $rec['ID'] = rcube_ldap::dn_decode($rec['ID']); + + $attributes = []; + + foreach ((array) $rec['attributes'] as $sattr) { + $sattr = trim($sattr); + if (!empty($sattr) && $sattr[0] === '{') { + $attr = @json_decode($sattr, true); + $attributes += $attr; + } + else if (!empty($sattr) && empty($rec['description'])) { + $rec['description'] = $sattr; + } } - else if ($sattr && empty($rec['description'])) { - $rec['description'] = $sattr; - } - } - $rec['attributes'] = $attributes; + $rec['attributes'] = $attributes; - // force $rec['members'] to be an array - if (!empty($rec['members']) && !is_array($rec['members'])) { - $rec['members'] = array($rec['members']); - } + // force $rec['members'] to be an array + if (!empty($rec['members']) && !is_array($rec['members'])) { + $rec['members'] = [$rec['members']]; + } - // remove unused cruft - unset($rec['_raw_attrib']); + // remove unused cruft + unset($rec['_raw_attrib']); - return $rec; + return $rec; } private function connect() { - if (!isset($this->ldap)) { - $this->ldap = new rcube_ldap($this->rc->config->get('calendar_resources_directory'), true); - } + if (!isset($this->ldap)) { + $this->ldap = new rcube_ldap($this->rc->config->get('calendar_resources_directory'), true); + } - return $this->ldap->ready ? $this->ldap : null; + return $this->ldap->ready ? $this->ldap : null; } - -} \ No newline at end of file +}
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/calendar/drivers/resources_driver.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/calendar/drivers/resources_driver.php
Changed
@@ -26,87 +26,93 @@ */ abstract class resources_driver { - protected $cal; + protected $cal; - /** - * Default constructor - */ - function __construct($cal) - { - $this->cal = $cal; - } + /** + * Default constructor + */ + function __construct($cal) + { + $this->cal = $cal; + } - /** - * Fetch resource objects to be displayed for booking - * - * @param string Search query (optional) - * @return array List of resource records available for booking - */ - abstract public function load_resources($query = null); + /** + * Fetch resource objects to be displayed for booking + * + * @param string $query Search query (optional) + * + * @return array List of resource records available for booking + */ + abstract public function load_resources($query = null); - /** - * Return properties of a single resource - * - * @param string Unique resource identifier - * @return array Resource object as hash array - */ - abstract public function get_resource($id); + /** + * Return properties of a single resource + * + * @param string $id Unique resource identifier + * + * @return array Resource object as hash array + */ + abstract public function get_resource($id); - /** - * Return properties of a resource owner - * - * @param string Owner identifier - * @return array Resource object as hash array - */ - public function get_resource_owner($id) - { - return null; - } + /** + * Return properties of a resource owner + * + * @param string $id Owner identifier + * + * @return array Resource object as hash array + */ + public function get_resource_owner($id) + { + return null; + } - /** - * Get event data to display a resource's calendar - * - * The default implementation extracts the resource's email address - * and fetches free-busy data using the calendar backend driver. - * - * @param integer Event's new start (unix timestamp) - * @param integer Event's new end (unix timestamp) - * @return array A list of event objects (see calendar_driver specification) - */ - public function get_resource_calendar($id, $start, $end) - { - $events = array(); - $rec = $this->get_resource($id); - if ($rec && !empty($rec['email']) && $this->cal->driver) { - $fbtypemap = array( - calendar::FREEBUSY_BUSY => 'busy', - calendar::FREEBUSY_TENTATIVE => 'tentative', - calendar::FREEBUSY_OOF => 'outofoffice', - ); + /** + * Get event data to display a resource's calendar + * + * The default implementation extracts the resource's email address + * and fetches free-busy data using the calendar backend driver. + * + * @param string $id Calendar identifier + * @param int $start Event's new start (unix timestamp) + * @param int $end Event's new end (unix timestamp) + * + * @return array A list of event objects (see calendar_driver specification) + */ + public function get_resource_calendar($id, $start, $end) + { + $events = []; + $rec = $this->get_resource($id); - // if the backend has free-busy information - $fblist = $this->cal->driver->get_freebusy_list($rec['email'], $start, $end); - if (is_array($fblist)) { - foreach ($fblist as $slot) { - list($from, $to, $type) = $slot; - if ($type == calendar::FREEBUSY_FREE || $type == calendar::FREEBUSY_UNKNOWN) { - continue; - } - if ($from < $end && $to > $start) { - $event = array( - 'id' => sha1($id . $from . $to), - 'title' => $rec['name'], - 'start' => new DateTime('@' . $from), - 'end' => new DateTime('@' . $to), - 'status' => $fbtypemap[$type], - 'calendar' => '_resource', - ); - $events[] = $event; - } - } - } - } + if ($rec && !empty($rec['email']) && !empty($this->cal->driver)) { + $fbtypemap = [ + calendar::FREEBUSY_BUSY => 'busy', + calendar::FREEBUSY_TENTATIVE => 'tentative', + calendar::FREEBUSY_OOF => 'outofoffice', + ]; - return $events; - } + // if the backend has free-busy information + $fblist = $this->cal->driver->get_freebusy_list($rec['email'], $start, $end); + if (is_array($fblist)) { + foreach ($fblist as $slot) { + list($from, $to, $type) = $slot; + if ($type == calendar::FREEBUSY_FREE || $type == calendar::FREEBUSY_UNKNOWN) { + continue; + } + + if ($from < $end && $to > $start) { + $events[] = [ + 'id' => sha1($id . $from . $to), + 'title' => $rec['name'], + 'start' => new DateTime('@' . $from), + 'end' => new DateTime('@' . $to), + 'status' => $fbtypemap[$type], + 'calendar' => '_resource', + ]; + } + } + } + } + + return $events; + } }
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/calendar/lib/calendar_itip.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/calendar/lib/calendar_itip.php
Changed
@@ -28,213 +28,231 @@ */ class calendar_itip extends libcalendaring_itip { - /** - * Constructor to set text domain to calendar - */ - function __construct($plugin, $domain = 'calendar') - { - parent::__construct($plugin, $domain); - - $this->db_itipinvitations = $this->rc->db->table_name('itipinvitations', true); - } - - /** - * Handler for calendar/itip-status requests - */ - public function get_itip_status($event, $existing = null) - { - $status = parent::get_itip_status($event, $existing); - - // don't ask for deleting events when declining - if ($this->rc->config->get('kolab_invitation_calendars')) - $status['saved'] = false; - - return $status; - } - - /** - * Find invitation record by token - * - * @param string Invitation token - * @return mixed Invitation record as hash array or False if not found - */ - public function get_invitation($token) - { - if ($parts = $this->decode_token($token)) { - $result = $this->rc->db->query("SELECT * FROM $this->db_itipinvitations WHERE `token` = ?", $parts['base']); - if ($result && ($rec = $this->rc->db->fetch_assoc($result))) { - $rec['event'] = unserialize($rec['event']); - $rec['attendee'] = $parts['attendee']; - return $rec; - } + /** + * Constructor to set text domain to calendar + */ + function __construct($plugin, $domain = 'calendar') + { + parent::__construct($plugin, $domain); + + $this->db_itipinvitations = $this->rc->db->table_name('itipinvitations', true); + } + + /** + * Handler for calendar/itip-status requests + */ + public function get_itip_status($event, $existing = null) + { + $status = parent::get_itip_status($event, $existing); + + // don't ask for deleting events when declining + if ($this->rc->config->get('kolab_invitation_calendars')) { + $status['saved'] = false; + } + + return $status; } - - return false; - } - - /** - * Update the attendee status of the given invitation record - * - * @param array Invitation record as fetched with calendar_itip::get_invitation() - * @param string Attendee email address - * @param string New attendee status - */ - public function update_invitation($invitation, $email, $newstatus) - { - if (is_string($invitation)) - $invitation = $this->get_invitation($invitation); - - if ($invitation['token'] && $invitation['event']) { - // update attendee record in event data - foreach ($invitation['event']['attendees'] as $i => $attendee) { - if ($attendee['role'] == 'ORGANIZER') { - $organizer = $attendee; + + /** + * Find invitation record by token + * + * @param string $token Invitation token + * + * @return mixed Invitation record as hash array or False if not found + */ + public function get_invitation($token) + { + if ($parts = $this->decode_token($token)) { + $result = $this->rc->db->query("SELECT * FROM $this->db_itipinvitations WHERE `token` = ?", $parts['base']); + if ($result && ($rec = $this->rc->db->fetch_assoc($result))) { + $rec['event'] = unserialize($rec['event']); + $rec['attendee'] = $parts['attendee']; + + return $rec; + } + } + + return false; + } + + /** + * Update the attendee status of the given invitation record + * + * @param array $invitation Invitation record as fetched with calendar_itip::get_invitation() + * @param string $email Attendee email address + * @param string $newstatus New attendee status + */ + public function update_invitation($invitation, $email, $newstatus) + { + if (is_string($invitation)) { + $invitation = $this->get_invitation($invitation); + } + + if (!empty($invitation['token']) && !empty($invitation['event'])) { + // update attendee record in event data + foreach ($invitation['event']['attendees'] as $i => $attendee) { + if ($attendee['role'] == 'ORGANIZER') { + $organizer = $attendee; + } + else if ($attendee['email'] == $email) { + // nothing to be done here + if ($attendee['status'] == $newstatus) { + return true; + } + + $invitation['event']['attendees'][$i]['status'] = $newstatus; + $this->sender = $attendee; + } + } + + $invitation['event']['changed'] = new DateTime(); + + // send iTIP REPLY message to organizer + if (!empty($organizer)) { + $status = strtolower($newstatus); + if ($this->send_itip_message($invitation['event'], 'REPLY', $organizer, 'itipsubject' . $status, 'itipmailbody' . $status)) { + $mailto = !empty($organizer['name']) ? $organizer['name'] : $organizer['email']; + $message = $this->plugin->gettext([ + 'name' => 'sentresponseto', + 'vars' => ['mailto' => $mailto] + ]); + $this->rc->output->command('display_message', $message, 'confirmation'); + } + else { + $this->rc->output->command('display_message', $this->plugin->gettext('itipresponseerror'), 'error'); + } + } + + // update record in DB + $query = $this->rc->db->query( + "UPDATE $this->db_itipinvitations SET `event` = ? WHERE `token` = ?", + self::serialize_event($invitation['event']), + $invitation['token'] + ); + + if ($this->rc->db->affected_rows($query)) { + return true; + } + } + + return false; + } + + /** + * Create iTIP invitation token for later replies via URL + * + * @param array $event Hash array with event properties + * @param string $attendee Attendee email address + * + * @return string Invitation token + */ + public function store_invitation($event, $attendee) + { + static $stored = []; + + if (empty($event['uid']) || !$attendee) { + return false; + } + + // generate token for this invitation + $token = $this->generate_token($event, $attendee); + $base = substr($token, 0, 40); + + // already stored this + if (!empty($stored[$base])) { + return $token; } - else if ($attendee['email'] == $email) { - // nothing to be done here
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/calendar/lib/calendar_recurrence.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/calendar/lib/calendar_recurrence.php
Changed
@@ -26,63 +26,64 @@ */ class calendar_recurrence extends libcalendaring_recurrence { - private $event; - private $duration; + private $event; + private $duration; - /** - * Default constructor - * - * @param object calendar The calendar plugin instance - * @param array The event object to operate on - */ - function __construct($cal, $event) - { - parent::__construct($cal->lib); + /** + * Default constructor + * + * @param calendar $cal The calendar plugin instance + * @param array $event The event object to operate on + */ + function __construct($cal, $event) + { + parent::__construct($cal->lib); - $this->event = $event; + $this->event = $event; - if (is_object($event['start']) && is_object($event['end'])) - $this->duration = $event['start']->diff($event['end']); + if (is_object($event['start']) && is_object($event['end'])) { + $this->duration = $event['start']->diff($event['end']); + } - $event['start']->_dateonly |= $event['allday']; - $this->init($event['recurrence'], $event['start']); - } + $event['start']->_dateonly = !empty($event['allday']); - /** - * Alias of libcalendaring_recurrence::next() - * - * @return mixed DateTime object or False if recurrence ended - */ - public function next_start() - { - return $this->next(); - } + $this->init($event['recurrence'], $event['start']); + } - /** - * Get the next recurring instance of this event - * - * @return mixed Array with event properties or False if recurrence ended - */ - public function next_instance() - { - if ($next_start = $this->next()) { - $next = $this->event; - $next['start'] = $next_start; + /** + * Alias of libcalendaring_recurrence::next() + * + * @return mixed DateTime object or False if recurrence ended + */ + public function next_start() + { + return $this->next(); + } - if ($this->duration) { - $next['end'] = clone $next_start; - $next['end']->add($this->duration); - } + /** + * Get the next recurring instance of this event + * + * @return mixed Array with event properties or False if recurrence ended + */ + public function next_instance() + { + if ($next_start = $this->next()) { + $next = $this->event; + $next['start'] = $next_start; - $next['recurrence_date'] = clone $next_start; - $next['_instance'] = libcalendaring::recurrence_instance_identifier($next, $this->event['allday']); + if ($this->duration) { + $next['end'] = clone $next_start; + $next['end']->add($this->duration); + } - unset($next['_formatobj']); + $next['recurrence_date'] = clone $next_start; + $next['_instance'] = libcalendaring::recurrence_instance_identifier($next, $this->event['allday']); - return $next; - } + unset($next['_formatobj']); - return false; - } + return $next; + } + return false; + } }
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/calendar/lib/calendar_ui.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/calendar/lib/calendar_ui.php
Changed
@@ -25,819 +25,1001 @@ class calendar_ui { - private $rc; - private $cal; - private $ready = false; - public $screen; - - function __construct($cal) - { - $this->cal = $cal; - $this->rc = $cal->rc; - $this->screen = $this->rc->task == 'calendar' ? ($this->rc->action ? $this->rc->action: 'calendar') : 'other'; - } - - /** - * Calendar UI initialization and requests handlers - */ - public function init() - { - if ($this->ready) // already done - return; - - // add taskbar button - $this->cal->add_button(array( - 'command' => 'calendar', - 'class' => 'button-calendar', - 'classsel' => 'button-calendar button-selected', - 'innerclass' => 'button-inner', - 'label' => 'calendar.calendar', - 'type' => 'link' - ), 'taskbar'); - - // load basic client script - if ($this->rc->action != 'print') { - $this->cal->include_script('calendar_base.js'); - } - - $this->addCSS(); - - $this->ready = true; - } - - /** - * Register handler methods for the template engine - */ - public function init_templates() - { - $this->cal->register_handler('plugin.calendar_css', array($this, 'calendar_css')); - $this->cal->register_handler('plugin.calendar_list', array($this, 'calendar_list')); - $this->cal->register_handler('plugin.calendar_select', array($this, 'calendar_select')); - $this->cal->register_handler('plugin.identity_select', array($this, 'identity_select')); - $this->cal->register_handler('plugin.category_select', array($this, 'category_select')); - $this->cal->register_handler('plugin.status_select', array($this, 'status_select')); - $this->cal->register_handler('plugin.freebusy_select', array($this, 'freebusy_select')); - $this->cal->register_handler('plugin.priority_select', array($this, 'priority_select')); - $this->cal->register_handler('plugin.sensitivity_select', array($this, 'sensitivity_select')); - $this->cal->register_handler('plugin.alarm_select', array($this, 'alarm_select')); - $this->cal->register_handler('plugin.recurrence_form', array($this->cal->lib, 'recurrence_form')); - $this->cal->register_handler('plugin.attendees_list', array($this, 'attendees_list')); - $this->cal->register_handler('plugin.attendees_form', array($this, 'attendees_form')); - $this->cal->register_handler('plugin.resources_form', array($this, 'resources_form')); - $this->cal->register_handler('plugin.resources_list', array($this, 'resources_list')); - $this->cal->register_handler('plugin.resources_searchform', array($this, 'resources_search_form')); - $this->cal->register_handler('plugin.resource_info', array($this, 'resource_info')); - $this->cal->register_handler('plugin.resource_calendar', array($this, 'resource_calendar')); - $this->cal->register_handler('plugin.attendees_freebusy_table', array($this, 'attendees_freebusy_table')); - $this->cal->register_handler('plugin.edit_attendees_notify', array($this, 'edit_attendees_notify')); - $this->cal->register_handler('plugin.edit_recurrence_sync', array($this, 'edit_recurrence_sync')); - $this->cal->register_handler('plugin.edit_recurring_warning', array($this, 'recurring_event_warning')); - $this->cal->register_handler('plugin.event_rsvp_buttons', array($this, 'event_rsvp_buttons')); - $this->cal->register_handler('plugin.agenda_options', array($this, 'agenda_options')); - $this->cal->register_handler('plugin.events_import_form', array($this, 'events_import_form')); - $this->cal->register_handler('plugin.events_export_form', array($this, 'events_export_form')); - $this->cal->register_handler('plugin.object_changelog_table', array('libkolab', 'object_changelog_table')); - $this->cal->register_handler('plugin.searchform', array($this->rc->output, 'search_form')); // use generic method from rcube_template - - kolab_attachments_handler::ui(); - } - - /** - * Adds CSS stylesheets to the page header - */ - public function addCSS() - { - $skin_path = $this->cal->local_skin_path(); + private $rc; + private $cal; + private $ready = false; + + public $screen; + + function __construct($cal) + { + $this->cal = $cal; + $this->rc = $cal->rc; + $this->screen = $this->rc->task == 'calendar' ? ($this->rc->action ?: 'calendar') : 'other'; + } + + /** + * Calendar UI initialization and requests handlers + */ + public function init() + { + if ($this->ready) { + // already done + return; + } + + // add taskbar button + $this->cal->add_button([ + 'command' => 'calendar', + 'class' => 'button-calendar', + 'classsel' => 'button-calendar button-selected', + 'innerclass' => 'button-inner', + 'label' => 'calendar.calendar', + 'type' => 'link' + ], + 'taskbar' + ); + + // load basic client script + if ($this->rc->action != 'print') { + $this->cal->include_script('calendar_base.js'); + } + + $this->addCSS(); + + $this->ready = true; + } + + /** + * Register handler methods for the template engine + */ + public function init_templates() + { + $this->cal->register_handler('plugin.calendar_css', [$this, 'calendar_css']); + $this->cal->register_handler('plugin.calendar_list', [$this, 'calendar_list']); + $this->cal->register_handler('plugin.calendar_select', [$this, 'calendar_select']); + $this->cal->register_handler('plugin.identity_select', [$this, 'identity_select']); + $this->cal->register_handler('plugin.category_select', [$this, 'category_select']); + $this->cal->register_handler('plugin.status_select', [$this, 'status_select']); + $this->cal->register_handler('plugin.freebusy_select', [$this, 'freebusy_select']); + $this->cal->register_handler('plugin.priority_select', [$this, 'priority_select']); + $this->cal->register_handler('plugin.sensitivity_select', [$this, 'sensitivity_select']); + $this->cal->register_handler('plugin.alarm_select', [$this, 'alarm_select']); + $this->cal->register_handler('plugin.recurrence_form', [$this->cal->lib, 'recurrence_form']); + $this->cal->register_handler('plugin.attendees_list', [$this, 'attendees_list']); + $this->cal->register_handler('plugin.attendees_form', [$this, 'attendees_form']); + $this->cal->register_handler('plugin.resources_form', [$this, 'resources_form']); + $this->cal->register_handler('plugin.resources_list', [$this, 'resources_list']); + $this->cal->register_handler('plugin.resources_searchform', [$this, 'resources_search_form']); + $this->cal->register_handler('plugin.resource_info', [$this, 'resource_info']); + $this->cal->register_handler('plugin.resource_calendar', [$this, 'resource_calendar']); + $this->cal->register_handler('plugin.attendees_freebusy_table', [$this, 'attendees_freebusy_table']); + $this->cal->register_handler('plugin.edit_attendees_notify', [$this, 'edit_attendees_notify']); + $this->cal->register_handler('plugin.edit_recurrence_sync', [$this, 'edit_recurrence_sync']); + $this->cal->register_handler('plugin.edit_recurring_warning', [$this, 'recurring_event_warning']); + $this->cal->register_handler('plugin.event_rsvp_buttons', [$this, 'event_rsvp_buttons']); + $this->cal->register_handler('plugin.agenda_options', [$this, 'agenda_options']); + $this->cal->register_handler('plugin.events_import_form', [$this, 'events_import_form']); + $this->cal->register_handler('plugin.events_export_form', [$this, 'events_export_form']); + $this->cal->register_handler('plugin.object_changelog_table', ['libkolab', 'object_changelog_table']); + $this->cal->register_handler('plugin.searchform', [$this->rc->output, 'search_form']); + + kolab_attachments_handler::ui(); + } + + /** + * Adds CSS stylesheets to the page header + */ + public function addCSS() + { + $skin_path = $this->cal->local_skin_path(); - if ($this->rc->task == 'calendar' && (!$this->rc->action || in_array($this->rc->action, array('index', 'print')))) { - // Include fullCalendar style before skin file for simpler style overriding - $this->cal->include_stylesheet($skin_path . '/fullcalendar.css'); - } - - $this->cal->include_stylesheet($skin_path . '/calendar.css'); - - if ($this->rc->task == 'calendar' && $this->rc->action == 'print') { - $this->cal->include_stylesheet($skin_path . '/print.css'); + if ( + $this->rc->task == 'calendar' + && (!$this->rc->action || in_array($this->rc->action, ['index', 'print'])) + ) { + // Include fullCalendar style before skin file for simpler style overriding + $this->cal->include_stylesheet($skin_path . '/fullcalendar.css'); + } + + $this->cal->include_stylesheet($skin_path . '/calendar.css'); + + if ($this->rc->task == 'calendar' && $this->rc->action == 'print') { + $this->cal->include_stylesheet($skin_path . '/print.css'); + } + } +
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/kolab_2fa/composer.json -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/kolab_2fa/composer.json
Changed
@@ -4,7 +4,7 @@ "description": "Kolab 2-Factor Authentication", "homepage": "https://git.kolab.org/diffusion/RPK/", "license": "AGPLv3", - "version": "3.5.2", + "version": "3.5.6", "authors": [ { "name": "Thomas Bruederli",
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/kolab_2fa/lib/Kolab2FA/Driver/Yubikey.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/kolab_2fa/lib/Kolab2FA/Driver/Yubikey.php
Changed
@@ -32,7 +32,7 @@ /** * */ - public function init(array $config) + public function init($config) { parent::init($config); @@ -89,7 +89,7 @@ /** * @override */ - public function set($key, $value) + public function set($key, $value, $persistent = true) { if ($key == 'yubikeyid' && strlen($value) > 12) { // verify the submitted code @@ -108,7 +108,7 @@ $value = substr($value, 0, 12); } - return parent::set($key, $value); + return parent::set($key, $value, $persistent); } /**
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/kolab_activesync/composer.json -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/kolab_activesync/composer.json
Changed
@@ -4,7 +4,7 @@ "description": "ActiveSync configuration utility for Kolab accounts", "homepage": "https://git.kolab.org/diffusion/RPK/", "license": "AGPLv3", - "version": "3.5.2", + "version": "3.5.6", "authors": [ { "name": "Thomas Bruederli",
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/kolab_activesync/config.inc.php.dist -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/kolab_activesync/config.inc.php.dist
Changed
@@ -2,3 +2,6 @@ // The page with Activesync clients configuration manual $config['activesync_setup_url'] = 'https://kb.kolabenterprise.com/documentation/setting-up-an-activesync-client'; +// Force a subscription state per devicetype (lowercase) and folder +// States can be: 0 => not subscribed, 1 => subscribed, 2 => subscribed with alarm +$config['activesync_force_subscriptions'] = array('windowsoutlook15' => array('INBOX' => 1, 'Sent' => 1, 'Trash' => 1, 'Calendar' => 1, 'Contacts' => 1, 'Tasks' => 1));
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/kolab_activesync/kolab_activesync.js -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/kolab_activesync/kolab_activesync.js
Changed
@@ -65,7 +65,7 @@ var fn = function(elem) { var classname = elem.className.split(' ')[0], - list = $(elem).closest('table').find('input.' + classname), + list = $(elem).closest('table').find('input.' + classname).not('[disabled]'), check = list.not(':checked').length > 0; list.prop('checked', check).change();
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/kolab_activesync/kolab_activesync_ui.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/kolab_activesync/kolab_activesync_ui.php
Changed
@@ -27,6 +27,7 @@ { private $rc; private $plugin; + private $force_subscriptions = array(); public $device = array(); const SETUP_URL = 'https://kb.kolabenterprise.com/documentation/setting-up-an-activesync-client'; @@ -39,6 +40,9 @@ $skin_path = $this->plugin->local_skin_path() . '/'; $this->skin_path = 'plugins/kolab_activesync/' . $skin_path; + $this->plugin->load_config(); + $this->force_subscriptions = $this->rc->config->get('activesync_force_subscriptions', array()); + $this->plugin->include_stylesheet($skin_path . 'config.css'); } @@ -94,6 +98,15 @@ } + private function is_protected($folder, $devicetype) + { + $devicetype = strtolower($devicetype); + if (array_key_exists($devicetype, $this->force_subscriptions)) { + return array_key_exists($folder, $this->force_subscriptions[$devicetype]); + } + return false; + } + public function folder_subscriptions($attrib = array()) { if (!$attrib['id']) { @@ -111,6 +124,9 @@ $folder_meta = $this->plugin->folder_meta(); } + $devicetype = strtolower($this->device['TYPE']); + $device_force_subscriptions = $this->force_subscriptions[$devicetype]; + foreach ($this->plugin->list_folders() as $folder) { if ($folder_types[$folder]) { list($type, ) = explode('.', $folder_types[$folder]); @@ -122,7 +138,9 @@ if (is_array($folder_groups[$type])) { $folder_groups[$type][] = $folder; - if (!empty($folder_meta) && ($meta = $folder_meta[$folder]) + if ($device_force_subscriptions && array_key_exists($folder, $device_force_subscriptions)) { + $subscribed[$folder] = intval($device_force_subscriptions[$folder]); + } else if (!empty($folder_meta) && ($meta = $folder_meta[$folder]) && $meta['FOLDER'] && $meta['FOLDER'][$imei]['S'] ) { $subscribed[$folder] = intval($meta['FOLDER'][$imei]['S']); @@ -185,7 +203,7 @@ $names = array(); foreach ($a_folders as $folder) { - $foldername = $origname = preg_replace('/^INBOX »\s+/', '', kolab_storage::object_prettyname($folder)); + $foldername = $origname = kolab_storage::object_prettyname($folder); // find folder prefix to truncate (the same code as in kolab_addressbook plugin) for ($i = count($names)-1; $i >= 0; $i--) { @@ -210,14 +228,17 @@ } $table->add_row(); + + $disabled = $this->is_protected($folder, $this->device['TYPE']); + $table->add('subscription checkbox-cell', $checkbox_sync->show( !empty($subscribed[$folder]) ? $folder : null, - array('value' => $folder, 'id' => $folder_id))); + array('value' => $folder, 'id' => $folder_id, 'disabled' => $disabled))); if ($alarms) { $table->add('alarm checkbox-cell', $checkbox_alarm->show( intval($subscribed[$folder]) > 1 ? $folder : null, - array('value' => $folder, 'id' => $folder_id.'_alarm'))); + array('value' => $folder, 'id' => $folder_id.'_alarm', 'disabled' => $disabled))); } $table->add(join(' ', $classes), html::label($folder_id, $foldername)); @@ -258,15 +279,17 @@ } } + $disabled = $this->is_protected($folder_name, $device['TYPE']); + $table->add_row(); $table->add(array('class' => 'device', 'title' => $title), $name); - $table->add('subscription checkbox-cell', $checkbox->show(!empty($folder_data[$id]['S']) ? 1 : 0)); + $table->add('subscription checkbox-cell', $checkbox->show(!empty($folder_data[$id]['S']) ? 1 : 0, array('disabled' => $disabled))); if ($alarms) { $checkbox_alarm = new html_checkbox(array('name' => "_alarms[$id]", 'value' => 1, 'onchange' => 'return activesync_object.update_sync_data(this)')); - $table->add('alarm checkbox-cell', $checkbox_alarm->show($folder_data[$id]['S'] > 1 ? 1 : 0)); + $table->add('alarm checkbox-cell', $checkbox_alarm->show($folder_data[$id]['S'] > 1 ? 1 : 0, array('disabled' => $disabled))); } }
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/kolab_addressbook/composer.json -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/kolab_addressbook/composer.json
Changed
@@ -4,7 +4,7 @@ "description": "Kolab addressbook", "homepage": "https://git.kolab.org/diffusion/RPK/", "license": "AGPLv3", - "version": "3.5.5", + "version": "3.5.6", "authors": [ { "name": "Thomas Bruederli",
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/kolab_addressbook/kolab_addressbook.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/kolab_addressbook/kolab_addressbook.php
Changed
@@ -1196,5 +1196,4 @@ $this->rc->user->save_prefs(array('calendar_birthday_adressbooks' => $bday_addressbooks)); } } - }
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php
Changed
@@ -34,52 +34,78 @@ public $undelete = true; public $groups = true; public $coltypes = array( - 'name' => array('limit' => 1), - 'firstname' => array('limit' => 1), - 'surname' => array('limit' => 1), - 'middlename' => array('limit' => 1), - 'prefix' => array('limit' => 1), - 'suffix' => array('limit' => 1), - 'nickname' => array('limit' => 1), - 'jobtitle' => array('limit' => 1), - 'organization' => array('limit' => 1), - 'department' => array('limit' => 1), - 'email' => array('subtypes' => array('home','work','other')), - 'phone' => array(), - 'address' => array('subtypes' => array('home','work','office')), - 'website' => array('subtypes' => array('homepage','blog')), - 'im' => array('subtypes' => null), - 'gender' => array('limit' => 1), - 'birthday' => array('limit' => 1), - 'anniversary' => array('limit' => 1), - 'profession' => array('type' => 'text', 'size' => 40, 'maxlength' => 80, 'limit' => 1, - 'label' => 'kolab_addressbook.profession', 'category' => 'personal'), - 'manager' => array('limit' => null), - 'assistant' => array('limit' => null), - 'spouse' => array('limit' => 1), - 'children' => array('type' => 'text', 'size' => 40, 'maxlength' => 80, 'limit' => null, - 'label' => 'kolab_addressbook.children', 'category' => 'personal'), - 'freebusyurl' => array('type' => 'text', 'size' => 40, 'limit' => 1, - 'label' => 'kolab_addressbook.freebusyurl'), - 'pgppublickey' => array('type' => 'textarea', 'size' => 70, 'rows' => 10, 'limit' => 1, - 'label' => 'kolab_addressbook.pgppublickey'), - 'pkcs7publickey' => array('type' => 'textarea', 'size' => 70, 'rows' => 10, 'limit' => 1, - 'label' => 'kolab_addressbook.pkcs7publickey'), - 'notes' => array('limit' => 1), - 'photo' => array('limit' => 1), - // TODO: define more Kolab-specific fields such as: language, latitude, longitude, crypto settings + 'name' => array('limit' => 1), + 'firstname' => array('limit' => 1), + 'surname' => array('limit' => 1), + 'middlename' => array('limit' => 1), + 'prefix' => array('limit' => 1), + 'suffix' => array('limit' => 1), + 'nickname' => array('limit' => 1), + 'jobtitle' => array('limit' => 1), + 'organization' => array('limit' => 1), + 'department' => array('limit' => 1), + 'email' => array('subtypes' => array('home','work','other')), + 'phone' => array(), + 'address' => array('subtypes' => array('home','work','office')), + 'website' => array('subtypes' => array('homepage','blog')), + 'im' => array('subtypes' => null), + 'gender' => array('limit' => 1), + 'birthday' => array('limit' => 1), + 'anniversary' => array('limit' => 1), + 'profession' => array( + 'type' => 'text', + 'size' => 40, + 'maxlength' => 80, + 'limit' => 1, + 'label' => 'kolab_addressbook.profession', + 'category' => 'personal' + ), + 'manager' => array('limit' => null), + 'assistant' => array('limit' => null), + 'spouse' => array('limit' => 1), + 'children' => array( + 'type' => 'text', + 'size' => 40, + 'maxlength' => 80, + 'limit' => null, + 'label' => 'kolab_addressbook.children', + 'category' => 'personal' + ), + 'freebusyurl' => array( + 'type' => 'text', + 'size' => 40, + 'limit' => 1, + 'label' => 'kolab_addressbook.freebusyurl' + ), + 'pgppublickey' => array( + 'type' => 'textarea', + 'size' => 70, + 'rows' => 10, + 'limit' => 1, + 'label' => 'kolab_addressbook.pgppublickey' + ), + 'pkcs7publickey' => array( + 'type' => 'textarea', + 'size' => 70, + 'rows' => 10, + 'limit' => 1, + 'label' => 'kolab_addressbook.pkcs7publickey' + ), + 'notes' => array('limit' => 1), + 'photo' => array('limit' => 1), + // TODO: define more Kolab-specific fields such as: language, latitude, longitude, crypto settings ); /** * vCard additional fields mapping */ public $vcard_map = array( - 'profession' => 'X-PROFESSION', - 'officelocation' => 'X-OFFICE-LOCATION', - 'initials' => 'X-INITIALS', - 'children' => 'X-CHILDREN', - 'freebusyurl' => 'X-FREEBUSY-URL', - 'pgppublickey' => 'KEY', + 'profession' => 'X-PROFESSION', + 'officelocation' => 'X-OFFICE-LOCATION', + 'initials' => 'X-INITIALS', + 'children' => 'X-CHILDREN', + 'freebusyurl' => 'X-FREEBUSY-URL', + 'pgppublickey' => 'KEY', ); /** @@ -102,25 +128,25 @@ // list of fields used for searching in "All fields" mode private $search_fields = array( - 'name', - 'firstname', - 'surname', - 'middlename', - 'prefix', - 'suffix', - 'nickname', - 'jobtitle', - 'organization', - 'department', - 'email', - 'phone', - 'address', - 'profession', - 'manager', - 'assistant', - 'spouse', - 'children', - 'notes', + 'name', + 'firstname', + 'surname', + 'middlename', + 'prefix', + 'suffix', + 'nickname', + 'jobtitle', + 'organization', + 'department', + 'email', + 'phone', + 'address', + 'profession', + 'manager', + 'assistant', + 'spouse', + 'children', + 'notes', ); @@ -132,15 +158,17 @@ // extend coltypes configuration $format = kolab_format::factory('contact'); - $this->coltypes['phone']['subtypes'] = array_keys($format->phonetypes); + + $this->coltypes['phone']['subtypes'] = array_keys($format->phonetypes); $this->coltypes['address']['subtypes'] = array_keys($format->addresstypes); $rcube = rcube::get_instance(); // set localized labels for proprietary cols foreach ($this->coltypes as $col => $prop) { - if (is_string($prop['label'])) + if (is_string($prop['label'])) { $this->coltypes[$col]['label'] = $rcube->gettext($prop['label']); + } } // fetch objects from the given IMAP folder @@ -157,8 +185,9 @@ $rights = $this->storagefolder->get_myrights(); if ($rights && !PEAR::isError($rights)) { $this->rights = $rights; - if (strpos($rights, 'i') !== false && strpos($rights, 't') !== false) + if (strpos($rights, 'i') !== false && strpos($rights, 't') !== false) { $this->readonly = false; + } } } } @@ -233,17 +262,17 @@ */ public function get_carddav_url() { - $rcmail = rcmail::get_instance();
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/kolab_delegation/composer.json -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/kolab_delegation/composer.json
Changed
@@ -4,7 +4,7 @@ "description": "Kolab delegation feature", "homepage": "https://git.kolab.org/diffusion/RPK/", "license": "AGPLv3", - "version": "3.5.2", + "version": "3.5.6", "authors": [ { "name": "Aleksander Machniak",
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/kolab_delegation/kolab_delegation.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/kolab_delegation/kolab_delegation.php
Changed
@@ -563,7 +563,7 @@ $names = array(); foreach ($a_folders as $folder) { - $foldername = $origname = preg_replace('/^INBOX »\s+/', '', kolab_storage::object_prettyname($folder)); + $foldername = $origname = kolab_storage::object_prettyname($folder); // find folder prefix to truncate (the same code as in kolab_addressbook plugin) for ($i = count($names)-1; $i >= 0; $i--) {
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libcalendaring/composer.json -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libcalendaring/composer.json
Changed
@@ -4,7 +4,7 @@ "description": "Library providing common functions for calendaring plugins", "homepage": "https://git.kolab.org/diffusion/RPK/", "license": "AGPLv3", - "version": "3.5.2", + "version": "3.5.6", "authors": [ { "name": "Thomas Bruederli",
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libcalendaring/lib/libcalendaring_itip.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libcalendaring/lib/libcalendaring_itip.php
Changed
@@ -118,14 +118,15 @@ // compose a list of all event attendees $attendees_list = array(); foreach ((array)$event['attendees'] as $attendee) { - $attendees_list[] = ($attendee['name'] && $attendee['email']) ? + $attendees_list[] = (!empty($attendee['name']) && !empty($attendee['email'])) ? $attendee['name'] . ' <' . $attendee['email'] . '>' : - ($attendee['name'] ? $attendee['name'] : $attendee['email']); + (!empty($attendee['name']) ? $attendee['name'] : $attendee['email']); } $recurrence_info = ''; if (!empty($event['recurrence_id'])) { - $recurrence_info = "\n\n** " . $this->gettext($event['thisandfuture'] ? 'itipmessagefutureoccurrence' : 'itipmessagesingleoccurrence') . ' **'; + $msg = $this->gettext(!empty($event['thisandfuture']) ? 'itipmessagefutureoccurrence' : 'itipmessagesingleoccurrence'); + $recurrence_info = "\n\n** $msg **"; } else if (!empty($event['recurrence'])) { $recurrence_info = sprintf("\n%s: %s", $this->gettext('recurring'), $this->lib->recurrence_text($event['recurrence'])); @@ -139,7 +140,7 @@ 'attendees' => join(",\n ", $attendees_list), 'sender' => $this->sender['name'], 'organizer' => $this->sender['name'], - 'description' => $event['description'], + 'description' => isset($event['description']) ? $event['description'] : '', ) )); @@ -243,8 +244,14 @@ // set RSVP for every attendee else if ($method == 'REQUEST') { foreach ($event['attendees'] as $i => $attendee) { - if (($rsvp || !isset($attendee['rsvp'])) && ($attendee['status'] != 'DELEGATED' && $attendee['role'] != 'NON-PARTICIPANT')) { - $event['attendees'][$i]['rsvp']= (bool)$rsvp; + if ( + ($rsvp || !isset($attendee['rsvp'])) + && ( + (empty($attendee['status']) || $attendee['status'] != 'DELEGATED') + && $attendee['role'] != 'NON-PARTICIPANT' + ) + ) { + $event['attendees'][$i]['rsvp']= (bool) $rsvp; } } } @@ -293,7 +300,7 @@ // attach ics file for this event $ical = libcalendaring::get_ical(); $ics = $ical->export(array($event), $method, false, $method == 'REQUEST' && $this->plugin->driver ? array($this->plugin->driver, 'get_attachment_body') : false); - $filename = $event['_type'] == 'task' ? 'todo.ics' : 'event.ics'; + $filename = !empty($event['_type']) && $event['_type'] == 'task' ? 'todo.ics' : 'event.ics'; $message->addAttachment($ics, 'text/calendar', $filename, false, '8bit', '', RCUBE_CHARSET . "; method=" . $method); return $message; @@ -521,7 +528,7 @@ protected function get_itip_diff($event, $existing) { - if (empty($event) || empty($existing) || empty($event['message_uid'])) { + if (empty($event) || empty($existing) || empty($event['message_uid']) || empty($event['mime_id'])) { return; } @@ -556,14 +563,14 @@ $attendee['status'] = 'ACCEPTED'; // sometimes is not set for exceptions $existing['attendees'][$idx] = $attendee; } - $existing_attendees[] = $attendee['email'].$attendee['name']; + $existing_attendees[] = $attendee['email'] . (isset($attendee['name']) ? $attendee['name'] : ''); } foreach ((array) $itip['attendees'] as $idx => $attendee) { - if ($attendee['email'] && ($_status = $status[strtolower($attendee['email'])])) { - $attendee['status'] = $_status; + if (!empty($attendee['email']) && !empty($status[strtolower($attendee['email'])])) { + $attendee['status'] = $status[strtolower($attendee['email'])]; $itip['attendees'][$idx] = $attendee; } - $itip_attendees[] = $attendee['email'].$attendee['name']; + $itip_attendees[] = $attendee['email'] . (isset($attendee['name']) ? $attendee['name'] : ''); } if ($itip_attendees != $existing_attendees) { @@ -597,14 +604,16 @@ public function mail_itip_inline_ui($event, $method, $mime_id, $task, $message_date = null, $preview_url = null) { $buttons = array(); - $dom_id = asciiwords($event['uid'], true); - $rsvp_status = 'unknown'; + $dom_id = asciiwords($event['uid'], true); + + $rsvp_status = 'unknown'; + $rsvp_buttons = ''; // pass some metadata about the event and trigger the asynchronous status check $changed = is_object($event['changed']) ? $event['changed'] : $message_date; $metadata = array( 'uid' => $event['uid'], - '_instance' => $event['_instance'], + '_instance' => isset($event['_instance']) ? $event['_instance'] : null, 'changed' => $changed ? $changed->format('U') : 0, 'sequence' => intval($event['sequence']), 'method' => $method, @@ -744,7 +753,7 @@ } // add itip reply message controls - $rsvp_buttons .= html::div('itip-reply-controls', $this->itip_rsvp_options_ui($dom_id, $metadata['nosave'])); + $rsvp_buttons .= html::div('itip-reply-controls', $this->itip_rsvp_options_ui($dom_id, !empty($metadata['nosave']))); $buttons[] = html::div(array('id' => 'rsvp-'.$dom_id, 'class' => 'rsvp-buttons', 'style' => 'display:none'), $rsvp_buttons); $buttons[] = html::div(array('id' => 'update-'.$dom_id, 'style' => 'display:none'), $update_button); @@ -759,8 +768,8 @@ $title = $this->gettext('itipcancellation'); $event_prop = array_filter(array( 'uid' => $event['uid'], - '_instance' => $event['_instance'], - '_savemode' => $event['_savemode'], + '_instance' => isset($event['_instance']) ? $event['_instance'] : null, + '_savemode' => isset($event['_savemode']) ? $event['_savemode'] : null, )); // 1. remove the event from our calendar @@ -786,7 +795,7 @@ } // append generic import button - if ($import_button) { + if (!empty($import_button)) { $buttons[] = html::div(array('id' => 'import-'.$dom_id, 'style' => 'display:none'), $import_button); } @@ -815,13 +824,16 @@ { $attrib += array('type' => 'button'); - if (!$actions) + if (!$actions) { $actions = $this->rsvp_actions; + } + + $buttons = ''; foreach ($actions as $method) { $buttons .= html::tag('input', array( 'type' => $attrib['type'], - 'name' => $attrib['iname'], + 'name' => !empty($attrib['iname']) ? $attrib['iname'] : null, 'class' => 'button', 'rel' => $method, 'value' => $this->gettext('itip' . $method), @@ -923,7 +935,7 @@ $table->add('label', $this->gettext('recurring')); $table->add('recurrence', $this->lib->recurrence_text($event['recurrence'])); } - if ($location = trim($event['location'])) { + if (isset($event['location']) && ($location = trim($event['location']))) { $table->add('label', $this->gettext('location')); $table->add('location', rcube::Q($location)); } @@ -931,11 +943,11 @@ $table->add('label', $this->gettext('sensitivity')); $table->add('sensitivity', ucfirst($this->gettext($sensitivity)) . '!'); } - if ($event['status'] == 'COMPLETED' || $event['status'] == 'CANCELLED') { + if (!empty($event['status']) && ($event['status'] == 'COMPLETED' || $event['status'] == 'CANCELLED')) { $table->add('label', $this->gettext('status')); $table->add('status', $this->gettext('status-' . strtolower($event['status']))); } - if ($comment = trim($event['comment'])) { + if (isset($event['comment']) && ($comment = trim($event['comment']))) { $table->add('label', $this->gettext('comment')); $table->add('location', rcube::Q($comment)); }
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libcalendaring/lib/libcalendaring_recurrence.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libcalendaring/lib/libcalendaring_recurrence.php
Changed
@@ -61,15 +61,15 @@ $this->set_start($start); - if (is_array($recurrence['EXDATE'])) { - foreach ($recurrence['EXDATE'] as $exdate) { + if (!empty($recurrence['EXDATE'])) { + foreach ((array) $recurrence['EXDATE'] as $exdate) { if (is_a($exdate, 'DateTime')) { $this->engine->addException($exdate->format('Y'), $exdate->format('n'), $exdate->format('j')); } } } - if (is_array($recurrence['RDATE'])) { - foreach ($recurrence['RDATE'] as $rdate) { + if (!empty($recurrence['RDATE'])) { + foreach ((array) $recurrence['RDATE'] as $rdate) { if (is_a($rdate, 'DateTime')) { $this->engine->addRDate($rdate->format('Y'), $rdate->format('n'), $rdate->format('j')); } @@ -160,9 +160,10 @@ $start = clone $this->start; $orig_start = clone $this->start; $r = $this->recurrence; - $interval = intval($r['INTERVAL'] ?: 1); + $interval = !empty($r['INTERVAL']) ? intval($r['INTERVAL']) : 1; + $frequency = isset($this->recurrence['FREQ']) ? $this->recurrence['FREQ'] : null; - switch ($this->recurrence['FREQ']) { + switch ($frequency) { case 'WEEKLY': if (empty($this->recurrence['BYDAY'])) { return $start; @@ -193,7 +194,7 @@ $r = $this->recurrence; $r['INTERVAL'] = $interval; - if ($r['COUNT']) { + if (!empty($r['COUNT'])) { // Increase count so we do not stop the loop to early $r['COUNT'] += 100; }
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libcalendaring/libcalendaring.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libcalendaring/libcalendaring.php
Changed
@@ -40,23 +40,23 @@ public $ical_message; public $defaults = array( - 'calendar_date_format' => "Y-m-d", - 'calendar_date_short' => "M-j", - 'calendar_date_long' => "F j Y", - 'calendar_date_agenda' => "l M-d", - 'calendar_time_format' => "H:m", - 'calendar_first_day' => 1, - 'calendar_first_hour' => 6, - 'calendar_date_format_sets' => array( - 'Y-m-d' => array('d M Y', 'm-d', 'l m-d'), - 'Y/m/d' => array('d M Y', 'm/d', 'l m/d'), - 'Y.m.d' => array('d M Y', 'm.d', 'l m.d'), - 'd-m-Y' => array('d M Y', 'd-m', 'l d-m'), - 'd/m/Y' => array('d M Y', 'd/m', 'l d/m'), - 'd.m.Y' => array('d M Y', 'd.m', 'l d.m'), - 'j.n.Y' => array('d M Y', 'd.m', 'l d.m'), - 'm/d/Y' => array('M d Y', 'm/d', 'l m/d'), - ), + 'calendar_date_format' => "Y-m-d", + 'calendar_date_short' => "M-j", + 'calendar_date_long' => "F j Y", + 'calendar_date_agenda' => "l M-d", + 'calendar_time_format' => "H:m", + 'calendar_first_day' => 1, + 'calendar_first_hour' => 6, + 'calendar_date_format_sets' => array( + 'Y-m-d' => array('d M Y', 'm-d', 'l m-d'), + 'Y/m/d' => array('d M Y', 'm/d', 'l m/d'), + 'Y.m.d' => array('d M Y', 'm.d', 'l m.d'), + 'd-m-Y' => array('d M Y', 'd-m', 'l d-m'), + 'd/m/Y' => array('d M Y', 'd/m', 'l d/m'), + 'd.m.Y' => array('d M Y', 'd.m', 'l d.m'), + 'j.n.Y' => array('d M Y', 'd.m', 'l d.m'), + 'm/d/Y' => array('M d Y', 'm/d', 'l m/d'), + ), ); private static $instance; @@ -187,19 +187,20 @@ */ public function adjust_timezone($dt, $dateonly = false) { - if (is_numeric($dt)) + if (is_numeric($dt)) { $dt = new DateTime('@'.$dt); - else if (is_string($dt)) + } + else if (is_string($dt)) { $dt = rcube_utils::anytodatetime($dt); + } - if ($dt instanceof DateTime && !($dt->_dateonly || $dateonly)) { + if ($dt instanceof DateTime && empty($dt->_dateonly) && !$dateonly) { $dt->setTimezone($this->timezone); } return $dt; } - /** * */ @@ -289,11 +290,12 @@ */ public function event_date_text($event, $tzinfo = false) { - $fromto = '--'; + $fromto = '--'; + $is_task = !empty($event['_type']) && $event['_type'] == 'task'; // handle task objects - if ($event['_type'] == 'task' && is_object($event['due'])) { - $date_format = $event['due']->_dateonly ? self::to_php_date_format($this->rc->config->get('calendar_date_format', $this->defaults['calendar_date_format'])) : null; + if ($is_task && !empty($event['due']) && is_object($event['due'])) { + $date_format = !empty($event['due']->_dateonly) ? self::to_php_date_format($this->rc->config->get('calendar_date_format', $this->defaults['calendar_date_format'])) : null; $fromto = $this->rc->format_date($event['due'], $date_format, false); // add timezone information @@ -351,18 +353,21 @@ $select_type = new html_select(array('name' => 'alarmtype[]', 'class' => 'edit-alarm-type form-control', 'id' => $attrib['id'])); $select_offset = new html_select(array('name' => 'alarmoffset[]', 'class' => 'edit-alarm-offset form-control')); $select_related = new html_select(array('name' => 'alarmrelated[]', 'class' => 'edit-alarm-related form-control')); - $object_type = $attrib['_type'] ?: 'event'; + $object_type = !empty($attrib['_type']) ? $attrib['_type'] : 'event'; $select_type->add($this->gettext('none'), ''); - foreach ($alarm_types as $type) + foreach ($alarm_types as $type) { $select_type->add($this->gettext(strtolower("alarm{$type}option")), $type); + } - foreach (array('-M','-H','-D','+M','+H','+D') as $trigger) + foreach (array('-M','-H','-D','+M','+H','+D') as $trigger) { $select_offset->add($this->gettext('trigger' . $trigger), $trigger); + } $select_offset->add($this->gettext('trigger0'), '0'); - if ($absolute_time) + if ($absolute_time) { $select_offset->add($this->gettext('trigger@'), '@'); + } $select_related->add($this->gettext('relatedstart'), 'start'); $select_related->add($this->gettext('relatedend' . $object_type), 'end'); @@ -399,7 +404,7 @@ } // return cached result - if (is_array($_emails[$user])) { + if (isset($_emails[$user])) { return $_emails[$user]; } @@ -610,33 +615,45 @@ */ public static function get_next_alarm($rec, $type = 'event') { - if (!($rec['valarms'] || $rec['alarms']) || $rec['cancelled'] || $rec['status'] == 'CANCELLED') + if ( + (empty($rec['valarms']) && empty($rec['alarms'])) + || !empty($rec['cancelled']) + || (!empty($rec['status']) && $rec['status'] == 'CANCELLED') + ) { return null; + } if ($type == 'task') { $timezone = self::get_instance()->timezone; - if ($rec['startdate']) - $rec['start'] = new DateTime($rec['startdate'] . ' ' . ($rec['starttime'] ?: '12:00'), $timezone); - if ($rec['date']) - $rec[($rec['start'] ? 'end' : 'start')] = new DateTime($rec['date'] . ' ' . ($rec['time'] ?: '12:00'), $timezone); + if (!empty($rec['startdate'])) { + $time = !empty($rec['starttime']) ? $rec['starttime'] : '12:00'; + $rec['start'] = new DateTime($rec['startdate'] . ' ' . $time, $timezone); + } + if (!empty($rec['date'])) { + $time = !empty($rec['time']) ? $rec['time'] : '12:00'; + $rec[!empty($rec['start']) ? 'end' : 'start'] = new DateTime($rec['date'] . ' ' . $time, $timezone); + } } - if (!$rec['end']) + if (empty($rec['end'])) { $rec['end'] = $rec['start']; + } // support legacy format - if (!$rec['valarms']) { + if (empty($rec['valarms'])) { list($trigger, $action) = explode(':', $rec['alarms'], 2); if ($alarm = self::parse_alarm_value($trigger)) { $rec['valarms'] = array(array('action' => $action, 'trigger' => $alarm[3] ?: $alarm[0])); } } - $expires = new DateTime('now - 12 hours'); - $alarm_id = $rec['id']; // alarm ID eq. record ID by default to keep backwards compatibility + // alarm ID eq. record ID by default to keep backwards compatibility + $alarm_id = isset($rec['id']) ? $rec['id'] : null; + $alarm_prop = null; + $expires = new DateTime('now - 12 hours'); + $notify_at = null; // handle multiple alarms - $notify_at = null; foreach ($rec['valarms'] as $alarm) { $notify_time = null; @@ -644,11 +661,12 @@ $notify_time = $alarm['trigger']; } else if (is_string($alarm['trigger'])) { - $refdate = $alarm['related'] == 'END' ? $rec['end'] : $rec['start']; + $refdate = !empty($alarm['related']) && $alarm['related'] == 'END' ? $rec['end'] : $rec['start']; // abort if no reference date is available to compute notification time - if (!is_a($refdate, 'DateTime')) + if (!is_a($refdate, 'DateTime')) { continue; + } // TODO: for all-day events, take start @ 00:00 as reference date ? @@ -666,19 +684,20 @@ if ($notify_time && (!$notify_at || ($notify_time > $notify_at && $notify_time > $expires))) { $notify_at = $notify_time; - $action = $alarm['action']; + $action = isset($alarm['action']) ? $alarm['action'] : null; $alarm_prop = $alarm; // generate a unique alarm ID if multiple alarms are set if (count($rec['valarms']) > 1) { - $alarm_id = substr(md5($rec['id']), 0, 16) . '-' . $notify_at->format('Ymd\THis'); + $rec_id = substr(md5(isset($rec['id']) ? $rec['id'] : 'none'), 0, 16);
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libcalendaring/libvcalendar.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libcalendaring/libvcalendar.php
Changed
@@ -326,10 +326,11 @@ $object = $this->_to_array($ve); // temporarily store this as exception - if ($object['recurrence_date']) { + if (!empty($object['recurrence_date'])) { $exceptions[] = $object; } - else if (!$seen[$object['uid']]++) { + else if (empty($seen[$object['uid']])) { + $seen[$object['uid']] = true; $this->objects[] = $object; } } @@ -343,7 +344,8 @@ $uid = $exception['uid']; // make this exception the master - if (!$seen[$uid]++) { + if (empty($seen[$uid])) { + $seen[$uid] = true; $this->objects[] = $exception; } else { @@ -412,7 +414,7 @@ // We can skip these fields, they aren't critical foreach (array('CREATED' => 'created', 'LAST-MODIFIED' => 'changed', 'DTSTAMP' => 'changed') as $attr => $field) { try { - if (!$event[$field] && $ve->{$attr}) { + if (empty($event[$field]) && !empty($ve->{$attr})) { $event[$field] = $ve->{$attr}->getDateTime(); } } catch (Exception $e) {} @@ -461,15 +463,17 @@ break; case 'RRULE': - $params = is_array($event['recurrence']) ? $event['recurrence'] : array(); + $params = !empty($event['recurrence']) && is_array($event['recurrence']) ? $event['recurrence'] : array(); // parse recurrence rule attributes foreach ($prop->getParts() as $k => $v) { $params[strtoupper($k)] = is_array($v) ? implode(',', $v) : $v; } - if ($params['UNTIL']) + if (!empty($params['UNTIL'])) { $params['UNTIL'] = date_create($params['UNTIL']); - if (!$params['INTERVAL']) + } + if (empty($params['INTERVAL'])) { $params['INTERVAL'] = 1; + } $event['recurrence'] = array_filter($params); break; @@ -477,14 +481,24 @@ case 'EXDATE': if (!empty($value)) { $exdates = array_map(function($_) { return is_array($_) ? $_[0] : $_; }, self::convert_datetime($prop, true)); - $event['recurrence']['EXDATE'] = array_merge((array)$event['recurrence']['EXDATE'], $exdates); + if (!empty($event['recurrence']['EXDATE'])) { + $event['recurrence']['EXDATE'] = array_merge($event['recurrence']['EXDATE'], $exdates); + } + else { + $event['recurrence']['EXDATE'] = $exdates; + } } break; case 'RDATE': if (!empty($value)) { $rdates = array_map(function($_) { return is_array($_) ? $_[0] : $_; }, self::convert_datetime($prop, true)); - $event['recurrence']['RDATE'] = array_merge((array)$event['recurrence']['RDATE'], $rdates); + if (!empty($event['recurrence']['RDATE'])) { + $event['recurrence']['RDATE'] = array_merge($event['recurrence']['RDATE'], $rdates); + } + else { + $event['recurrence']['RDATE'] = $rdates; + } } break; @@ -519,7 +533,12 @@ case 'CATEGORY': case 'CATEGORIES': - $event['categories'] = array_merge((array)$event['categories'], $prop->getParts()); + if (!empty($event['categories'])) { + $event['categories'] = array_merge((array) $event['categories'], $prop->getParts()); + } + else { + $event['categories'] = $prop->getParts(); + } break; case 'CLASS': @@ -528,10 +547,12 @@ break; case 'X-MICROSOFT-CDO-BUSYSTATUS': - if ($value == 'OOF') + if ($value == 'OOF') { $event['free_busy'] = 'outofoffice'; - else if (in_array($value, array('FREE', 'BUSY', 'TENTATIVE'))) + } + else if (in_array($value, array('FREE', 'BUSY', 'TENTATIVE'))) { $event['free_busy'] = strtolower($value); + } break; case 'ATTENDEE': @@ -556,7 +577,7 @@ $schedule_agent = $attendee['schedule-agent']; } } - else if ($attendee['email'] != $event['organizer']['email']) { + else if (empty($event['organizer']) || $attendee['email'] != $event['organizer']['email']) { $event['attendees'][] = $attendee; } break; @@ -596,12 +617,7 @@ // validate event dates if ($event['_type'] == 'event') { - $event['allday'] = false; - - // check for all-day dates - if ($event['start']->_dateonly) { - $event['allday'] = true; - } + $event['allday'] = !empty($event['start']->_dateonly); // events may lack the DTEND property, set it to DTSTART (RFC5545 3.6.1) if (empty($event['end'])) { @@ -647,11 +663,12 @@ $trigger = $values[2]; } - if (!$alarm['trigger']) { + if (empty($alarm['trigger'])) { $alarm['trigger'] = rtrim(preg_replace('/([A-Z])0[WDHMS]/', '\\1', $value), 'T'); // if all 0-values have been stripped, assume 'at time' - if ($alarm['trigger'] == 'P') + if ($alarm['trigger'] == 'P') { $alarm['trigger'] = 'PT0S'; + } } break; @@ -684,23 +701,26 @@ } if ($action != 'NONE') { - if ($trigger && !$event['alarms']) // store first alarm in legacy property + // store first alarm in legacy property + if ($trigger && empty($event['alarms'])) { $event['alarms'] = $trigger . ':' . $action; + } - if ($alarm['trigger']) + if (!empty($alarm['trigger'])) { $event['valarms'][] = $alarm; + } } } // assign current timezone to event start/end - if ($event['start'] instanceof DateTime) { + if (!empty($event['start']) && $event['start'] instanceof DateTime) { $this->_apply_timezone($event['start']); } else { unset($event['start']); } - if ($event['end'] instanceof DateTime) { + if (!empty($event['end']) && $event['end'] instanceof DateTime) { $this->_apply_timezone($event['end']); } else { @@ -708,7 +728,7 @@ } // some iTip CANCEL messages only contain the start date - if (!$event['end'] && $event['start'] && $this->method == 'CANCEL') { + if (empty($event['end']) && !empty($event['start']) && $this->method == 'CANCEL') { $event['end'] = clone $event['start']; } @@ -736,7 +756,7 @@ } // For date-only we'll keep the date and time intact - if ($date->_dateonly) { + if (!empty($date->_dateonly)) { $dt = new DateTime(null, $this->timezone); $dt->setDate($date->format('Y'), $date->format('n'), $date->format('j')); $dt->setTime($date->format('G'), $date->format('i'), 0); @@ -767,7 +787,13 @@ case 'DTSTAMP': case 'DTSTART':
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libcalendaring/tests/libcalendaring.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libcalendaring/tests/libcalendaring.php
Changed
@@ -21,7 +21,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -class libcalendaring_test extends PHPUnit_Framework_TestCase +class libcalendaring_test extends PHPUnit\Framework\TestCase { function setUp() {
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libcalendaring/tests/libvcalendar.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libcalendaring/tests/libvcalendar.php
Changed
@@ -21,7 +21,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -class libvcalendar_test extends PHPUnit_Framework_TestCase +class libvcalendar_test extends PHPUnit\Framework\TestCase { function setUp() { @@ -209,7 +209,7 @@ $this->assertEquals('-PT30M', $alarm[3], "Unified alarm string (stripped zero-values)"); $this->assertEquals('DISPLAY', $event['valarms'][0]['action'], "First alarm action"); - $this->assertEquals('', $event['valarms'][0]['related'], "First alarm related property"); + $this->assertTrue(empty($event['valarms'][0]['related']), "First alarm related property"); $this->assertEquals('This is the first event reminder', $event['valarms'][0]['description'], "First alarm text"); $this->assertEquals(3, count($event['valarms']), "List all VALARM blocks"); @@ -553,7 +553,7 @@ $this->assertEquals('4', $vtz->{'X-MICROSOFT-CDO-TZID'}); // check for transition to daylight saving time which is BEFORE the given date - $dst = reset($vtz->select('DAYLIGHT')); + $dst = array_first($vtz->select('DAYLIGHT')); $this->assertEquals('DAYLIGHT', $dst->name); $this->assertEquals('20140330T010000', $dst->DTSTART); $this->assertEquals('+0100', $dst->TZOFFSETFROM); @@ -561,7 +561,8 @@ $this->assertEquals('CEST', $dst->TZNAME); // check (last) transition to standard time which is AFTER the given date - $std = end($vtz->select('STANDARD')); + $std = $vtz->select('STANDARD'); + $std = end($std); $this->assertEquals('STANDARD', $std->name); $this->assertEquals('20141026T010000', $std->DTSTART); $this->assertEquals('+0200', $std->TZOFFSETFROM);
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/composer.json -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/composer.json
Changed
@@ -4,7 +4,7 @@ "description": "Plugin to setup a basic environment for the interaction with a Kolab server.", "homepage": "https://git.kolab.org/diffusion/RPK/", "license": "AGPLv3", - "version": "3.5.5", + "version": "3.5.6", "authors": [ { "name": "Thomas Bruederli",
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/config.inc.php.dist -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/config.inc.php.dist
Changed
@@ -5,10 +5,6 @@ // Enable caching of Kolab objects in local database $config['kolab_cache'] = true; -// Cache refresh interval (default is 12 hours) -// after this period, cache is forced to synchronize with IMAP -$config['kolab_cache_refresh'] = '12h'; - // Specify format version to write Kolab objects (must be a string value!) $config['kolab_format_version'] = '3.0';
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/lib/kolab_attachments_handler.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/lib/kolab_attachments_handler.php
Changed
@@ -48,7 +48,7 @@ */ public function files_list($attrib = array()) { - if (!$attrib['id']) { + if (empty($attrib['id'])) { $attrib['id'] = 'kolabattachmentlist'; } @@ -67,7 +67,7 @@ public function files_form($attrib = array()) { // add ID if not given - if (!$attrib['id']) { + if (empty($attrib['id'])) { $attrib['id'] = 'kolabuploadform'; } @@ -80,7 +80,7 @@ public function files_drop_area($attrib = array()) { // add ID if not given - if (!$attrib['id']) { + if (empty($attrib['id'])) { $attrib['id'] = 'kolabfiledroparea'; } @@ -117,7 +117,7 @@ $recid = $id_prefix . rcube_utils::get_input_value('_id', rcube_utils::INPUT_GPC); $uploadid = rcube_utils::get_input_value('_uploadid', rcube_utils::INPUT_GPC); - if (!is_array($_SESSION[$session_key]) || $_SESSION[$session_key]['id'] != $recid) { + if (empty($_SESSION[$session_key]) || $_SESSION[$session_key]['id'] != $recid) { $_SESSION[$session_key] = array(); $_SESSION[$session_key]['id'] = $recid; $_SESSION[$session_key]['attachments'] = array(); @@ -151,13 +151,16 @@ unset($attachment['status'], $attachment['abort']); $this->rc->session->append($session_key . '.attachments', $id, $attachment); - if (($icon = $_SESSION[$session_key . '_deleteicon']) && is_file($icon)) { + if (!empty($_SESSION[$session_key . '_deleteicon']) + && ($icon = $_SESSION[$session_key . '_deleteicon']) + && is_file($icon) + ) { $button = html::img(array( 'src' => $icon, 'alt' => $this->rc->gettext('delete') )); } - else if ($_SESSION[$session_key . '_textbuttons']) { + else if (!empty($_SESSION[$session_key . '_textbuttons'])) { $button = rcube::Q($this->rc->gettext('delete')); } else { @@ -181,7 +184,8 @@ 'onclick' => 'return false', // sprintf("return %s.command('load-attachment','rcmfile%s', this, event)", rcmail_output::JS_OBJECT_NAME, $id), ), $link_content); - $content .= $_SESSION[$session_key . '_icon_pos'] == 'left' ? $delete_link.$content_link : $content_link.$delete_link; + $left = !empty($_SESSION[$session_key . '_icon_pos']) && $_SESSION[$session_key . '_icon_pos'] == 'left'; + $content = $left ? $delete_link.$content_link : $content_link.$delete_link; $this->rc->output->command('add2attachment_list', "rcmfile$id", array( 'html' => $content, @@ -196,7 +200,7 @@ $msg = $this->rc->gettext(array('name' => 'filesizeerror', 'vars' => array( 'size' => $this->rc->show_bytes(parse_bytes(ini_get('upload_max_filesize')))))); } - else if ($attachment['error']) { + else if (!empty($attachment['error'])) { $msg = $attachment['error']; } else { @@ -211,11 +215,13 @@ else if ($_SERVER['REQUEST_METHOD'] == 'POST') { // if filesize exceeds post_max_size then $_FILES array is empty, // show filesizeerror instead of fileuploaderror - if ($maxsize = ini_get('post_max_size')) + if ($maxsize = ini_get('post_max_size')) { $msg = $this->rc->gettext(array('name' => 'filesizeerror', 'vars' => array( 'size' => $this->rc->show_bytes(parse_bytes($maxsize))))); - else + } + else { $msg = $this->rc->gettext('fileuploaderror'); + } $this->rc->output->command('display_message', $msg, 'error'); $this->rc->output->command('remove_from_attachment_list', $uploadid); @@ -233,7 +239,7 @@ { ob_end_clean(); - if ($attachment && $attachment['body']) { + if ($attachment && !empty($attachment['body'])) { // allow post-processing of the attachment body $part = new rcube_message_part; $part->filename = $attachment['name'];
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/lib/kolab_bonnie_api.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/lib/kolab_bonnie_api.php
Changed
@@ -93,5 +93,4 @@ { return $this->client->execute($method, $params); } - -} \ No newline at end of file +}
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/lib/kolab_bonnie_api_client.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/lib/kolab_bonnie_api_client.php
Changed
@@ -235,5 +235,4 @@ rcube::write_log('bonnie', join(";\n", $msg)); } - -} \ No newline at end of file +}
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/lib/kolab_format_task.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/lib/kolab_format_task.php
Changed
@@ -151,5 +151,4 @@ return array_unique($tags); } - }
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/lib/kolab_storage.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/lib/kolab_storage.php
Changed
@@ -47,7 +47,6 @@ private static $with_tempsubs = true; private static $subscriptions; private static $ldapcache = array(); - private static $typedata = array(); private static $ldap = array(); private static $states; private static $config; @@ -869,7 +868,8 @@ return array(); } - // In some conditions we can skip LIST command (?) + // If we only want groupware folders and don't care about the subscription state, + // then the metadata will already contain all folder names and we can avoid the LIST below. if (!$subscribed && $filter != 'mail' && $prefix == '*') { foreach ($folderdata as $folder => $type) { if (!preg_match($regexp, $type)) { @@ -1106,11 +1106,6 @@ return false; } - // return cached result - if (is_array(self::$typedata[$prefix])) { - return self::$typedata[$prefix]; - } - $type_keys = array(self::CTYPE_KEY, self::CTYPE_KEY_PRIVATE); // fetch metadata from *some* folders only @@ -1153,10 +1148,7 @@ return false; } - // keep list in memory - self::$typedata[$prefix] = array_map(array('kolab_storage', 'folder_select_metadata'), $folderdata); - - return self::$typedata[$prefix]; + return array_map(array('kolab_storage', 'folder_select_metadata'), $folderdata); } /** @@ -1185,13 +1177,6 @@ { self::setup(); - // return in-memory cached result - foreach (self::$typedata as $typedata) { - if (array_key_exists($folder, $typedata)) { - return $typedata[$folder]; - } - } - $metadata = self::$imap->get_metadata($folder, array(self::CTYPE_KEY, self::CTYPE_KEY_PRIVATE)); if (!is_array($metadata)) {
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/lib/kolab_storage_cache.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/lib/kolab_storage_cache.php
Changed
@@ -27,8 +27,6 @@ const DB_DATE_FORMAT = 'Y-m-d H:i:s'; const MAX_RECORDS = 500; - public $sync_complete = false; - protected $db; protected $imap; protected $folder; @@ -42,7 +40,6 @@ protected $synclock = false; protected $ready = false; protected $cache_table; - protected $cache_refresh = 3600; protected $folders_table; protected $max_sql_packet; protected $max_sync_lock_time = 600; @@ -85,7 +82,6 @@ $this->imap = $rcmail->get_storage(); $this->enabled = $rcmail->config->get('kolab_cache', false); $this->folders_table = $this->db->table_name('kolab_folders'); - $this->cache_refresh = get_offset_sec($rcmail->config->get('kolab_cache_refresh', '12h')); $this->server_timezone = new DateTimeZone(date_default_timezone_get()); if ($this->enabled) { @@ -174,16 +170,6 @@ if ($this->synched) return; - // increase time limit - @set_time_limit($this->max_sync_lock_time - 60); - - // get effective time limit we have for synchronization (~70% of the execution time) - $time_limit = ini_get('max_execution_time') * 0.7; - $sync_start = time(); - - // assume sync will be completed - $this->sync_complete = true; - if (!$this->ready) { // kolab cache is disabled, synchronize IMAP mailbox cache only $this->imap_mode(true); @@ -191,124 +177,312 @@ $this->imap_mode(false); } else { + $this->sync_start = time(); + // read cached folder metadata $this->_read_folder_data(); + // Read folder data from IMAP + $ctag = $this->folder->get_ctag(); + + // Validate current ctag + list($uidvalidity, $highestmodseq, $uidnext) = explode('-', $ctag); + + if (empty($uidvalidity) || empty($highestmodseq)) { + rcube::raise_error(array( + 'code' => 900, + 'message' => "Failed to sync the kolab cache (Invalid ctag)" + ), true); + } // check cache status ($this->metadata is set in _read_folder_data()) - if ( empty($this->metadata['ctag']) || - empty($this->metadata['changed']) || - $this->metadata['objectcount'] === null || - $this->metadata['changed'] < date(self::DB_DATE_FORMAT, time() - $this->cache_refresh) || - $this->metadata['ctag'] != $this->folder->get_ctag() || - intval($this->metadata['objectcount']) !== $this->count() + else if ( + empty($this->metadata['ctag']) + || empty($this->metadata['changed']) + || $this->metadata['ctag'] !== $ctag ) { // lock synchronization for this folder or wait if locked $this->_sync_lock(); - // disable messages cache if configured to do so - $this->imap_mode(true); + // Run a full-sync (initial sync or continue the aborted sync) + if (empty($this->metadata['changed']) || empty($this->metadata['ctag'])) { + $result = $this->synchronize_full(); + } + // Synchronize only the changes since last sync + else { + $result = $this->synchronize_update($ctag); + } + + // update ctag value (will be written to database in _sync_unlock()) + if ($result) { + $this->metadata['ctag'] = $ctag; + $this->metadata['changed'] = date(self::DB_DATE_FORMAT, time()); + } + + // remove lock + $this->_sync_unlock(); + } + } - // synchronize IMAP mailbox cache - $this->imap->folder_sync($this->folder->name); + $this->check_error(); + $this->synched = time(); + } - // compare IMAP index with object cache index - $imap_index = $this->imap->index($this->folder->name, null, null, true, true); + /** + * Perform full cache synchronization + */ + protected function synchronize_full() + { + // get effective time limit we have for synchronization (~70% of the execution time) + $time_limit = $this->_max_sync_lock_time() * 0.7; - $this->imap_mode(false); + if (time() - $this->sync_start > $time_limit) { + return false; + } - // determine objects to fetch or to invalidate - if (!$imap_index->is_error()) { - $imap_index = $imap_index->get(); - $old_index = array(); - $del_index = array(); + // disable messages cache if configured to do so + $this->imap_mode(true); - // read cache index - $sql_result = $this->db->query( - "SELECT `msguid`, `uid` FROM `{$this->cache_table}` WHERE `folder_id` = ?" - . " ORDER BY `msguid` DESC", $this->folder_id - ); + // synchronize IMAP mailbox cache, does nothing if messages cache is disabled + $this->imap->folder_sync($this->folder->name); - while ($sql_arr = $this->db->fetch_assoc($sql_result)) { - // Mark all duplicates for removal (note sorting order above) - // Duplicates here should not happen, but they do sometimes - if (isset($old_index[$sql_arr['uid']])) { - $del_index[] = $sql_arr['msguid']; - } - else { - $old_index[$sql_arr['uid']] = $sql_arr['msguid']; - } - } + // compare IMAP index with object cache index + $imap_index = $this->imap->index($this->folder->name, null, null, true, true); - // fetch new objects from imap - $i = 0; - foreach (array_diff($imap_index, $old_index) as $msguid) { - // Note: We'll store only objects matching the folder type - // anything else will be silently ignored - if ($object = $this->folder->read_object($msguid)) { - // Deduplication: remove older objects with the same UID - // Here we do not resolve conflicts, we just make sure - // the most recent version of the object will be used - if ($old_msguid = $old_index[$object['uid']]) { - if ($old_msguid < $msguid) { - $del_index[] = $old_msguid; - } - else { - $del_index[] = $msguid; - continue; - } - } - - $old_index[$object['uid']] = $msguid; - - $this->_extended_insert($msguid, $object); - - // check time limit and abort sync if running too long - if (++$i % 50 == 0 && time() - $sync_start > $time_limit) { - $this->sync_complete = false; - break; - } - } - } - $this->_extended_insert(0, null); + $this->imap_mode(false); - $del_index = array_unique($del_index); + if ($imap_index->is_error()) { + rcube::raise_error(array( + 'code' => 900, + 'message' => "Failed to sync the kolab cache (SEARCH failed)" + ), true); + return false; + } - // delete duplicate entries from IMAP - $rem_index = array_intersect($del_index, $imap_index); - if (!empty($rem_index)) { - $this->imap_mode(true); - $this->imap->delete_message($rem_index, $this->folder->name); - $this->imap_mode(false); - } + // determine objects to fetch or to invalidate
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/lib/kolab_storage_dataset.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/lib/kolab_storage_dataset.php
Changed
@@ -150,5 +150,4 @@ { return !empty($this->index[$this->iteratorkey]); } - }
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/lib/kolab_storage_folder.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/lib/kolab_storage_folder.php
Changed
@@ -578,6 +578,8 @@ 'line' => __LINE__, 'message' => "Could not parse Kolab object data in message $msguid ($this->name)." . $msgadd, ), true); + + self::save_user_xml("$msguid.xml", $xml); } return false; @@ -1144,4 +1146,22 @@ return true; } + + /** + * Log content to a file in per_user_loggin dir if configured + */ + private static function save_user_xml($filename, $content) + { + $rcmail = rcube::get_instance(); + + if ($rcmail->config->get('kolab_format_error_log')) { + $log_dir = $rcmail->config->get('log_dir', RCUBE_INSTALL_PATH . 'logs'); + $user_name = $rcmail->get_user_name(); + $log_dir = $log_dir . '/' . $user_name; + + if (!empty($user_name) && is_writable($log_dir)) { + file_put_contents("$log_dir/$filename", $content); + } + } + } }
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/libkolab.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/libkolab.php
Changed
@@ -60,7 +60,7 @@ $this->add_texts('localization/', false); - if ($rcmail->output->type == 'html') { + if (!empty($rcmail->output->type) && $rcmail->output->type == 'html') { $rcmail->output->add_handler('libkolab.folder_search_form', array($this, 'folder_search_form')); $this->include_stylesheet($this->local_skin_path() . '/libkolab.css'); } @@ -93,7 +93,15 @@ */ function storage_init($p) { - $p['fetch_headers'] = trim($p['fetch_headers'] .' X-KOLAB-TYPE X-KOLAB-MIME-VERSION MESSAGE-ID'); + $kolab_headers = 'X-KOLAB-TYPE X-KOLAB-MIME-VERSION MESSAGE-ID'; + + if (!empty($p['fetch_headers'])) { + $p['fetch_headers'] .= ' ' . $kolab_headers; + } + else { + $p['fetch_headers'] = $kolab_headers; + } + return $p; }
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/skins/elastic/include/calendar.less -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/skins/elastic/include/calendar.less
Changed
@@ -137,7 +137,7 @@ .event-row { white-space: nowrap; - .overflow-ellipsis; + .overflow-ellipsis(); &.current { color: #333; @@ -166,7 +166,8 @@ } #calendar.content { - overflow: hidden !important; // fullcalendar widget implements scrolling on its own + // fullcalendar widget implements scrolling on its own + overflow: hidden !important; position: relative; } @@ -567,7 +568,7 @@ @media screen and (min-width: (@screen-width-small + 1px)) and (max-width: 920px) { .fc-center { - .overflow-ellipsis; + .overflow-ellipsis(); flex: 1; h2 { @@ -715,7 +716,7 @@ span { display: block; - .overflow-ellipsis; + .overflow-ellipsis(); } } } @@ -729,7 +730,7 @@ } .event-location { - .overflow-ellipsis; + .overflow-ellipsis(); white-space: nowrap; } @@ -819,7 +820,7 @@ } &.loading:before { - .animated-icon-class; + .animated-icon-class(); content: @fa-var-circle-notch; display: block; line-height: 1; @@ -967,7 +968,7 @@ } &.loading:before { - .animated-icon-class; + .animated-icon-class(); .font-icon-solid(@fa-var-circle-notch); }
View file
roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/skins/elastic/include/darkmode.less
Added
@@ -0,0 +1,168 @@ +/** + * Kolab core library + * + * This file contains Elastic skin dark mode styles for all Kolab plugins + * + * @author Aleksander Machniak <machniak@kolabsys.com> + * + * Copyright (C) 2012-2018, Kolab Systems AG <contact@kolabsys.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +html.dark-mode { + // Use icons-only on taskmenu with small screen height + @media screen and (max-height: 750px) and (min-width: (@screen-width-small + 1px)) { + #taskmenu a { + width: @layout-menu-width-sm - 1px; + } + } + + .watermark { + background-color: @color-dark-background; + background-blend-mode: soft-light; + + &:before { + background: none; + } + } + + #filelistcontainer, + .fc-scroller { + scrollbar-width: thin; + } + + .fc { + .fc-header-toolbar { + background-color: @color-dark-list-selected-background; + } + + #timezone-display, + .fc-center h2 { + color: @color-dark-font; + } + } + + .filelist tr.session.owner > td.name::after, + .rsvp-status:not(.accepted):not(.tentative):not(.declined)::before, + .resources-dialog .listing li.resource > a { + color: @color-dark-font; + } + + .fc-unthemed th, + .fc-unthemed td, + .fc-unthemed .fc-divider, + .fc-unthemed .fc-row, + .fc-unthemed .fc-content, + .fc-unthemed .fc-popover, + .fc-unthemed .fc-list-view, + .fc-unthemed .fc-list-heading td, + #tasklist li.taskitem > div, + #tasklist li.taskitem > span { + border-color: @color-dark-list-border; + } + + .files-dialog .selection-content, + .calendar-scheduler .schedule-table td.times td, + .calendar-scheduler .attendees-list div.attendee, + .calendar-scheduler .schedule-table .timesheader, + .calendar-scheduler .schedule-table td.attendees .attendees-list, + .fc-unthemed th, + .fc-unthemed td { + border-color: @color-dark-border; + } + + #resource-availability .fc, + #resource-availability .fc-view { + border-color: @color-dark-border; + } + + .selection-dialog .form-addon, + .selection-dialog .header, + .selection-dialog .selection-list, + .edit-attendees-table th { + border-color: @color-dark-border !important; + } + + .selection-dialog .listing ul, + .selection-dialog .form-addon, + .selection-dialog .header { + background-color: transparent; + } + + .fc-unthemed .fc-divider, + .fc-unthemed .fc-popover .fc-header, + .fc-unthemed .fc-list-heading td, + body.task-calendar .ui-datepicker-inline .ui-datepicker-activerange, + .listing li.selected > div > *, + #tasklist li.taskitem div.taskhead.selected { + color: @color-dark-list-selected; + background-color: @color-dark-list-selected-background; + } + + #folder-mount-form td.source.selected { + background-color: @color-dark-list-selected-background; + } + + #tagsform option, + .tagedit-list li.tagedit-listelement-new input { + color: @color-dark-input; + } + + .fc .fc-axis, + .fc .fc-day-number, + .fc .fc-week-number, + .fc .fc-day-header, + .fc .fc-week-header, + .formcontent.text-only .faded *, + .availability span, + .invitebox td.label, + .invitebox .rsvp-status.hint, + .calendar-agenda-preview .event-row.current, + #tasklist span.date, + #kolabnoteslist td.date, + #notedetailstitle .dates { + color: @color-dark-hint; + } + + .invitebox .folder-select select { + background-color: @color-dark-input-background; + } + + .tagedit-list[tabindex="-1"] { + border-color: @color-dark-input-border-focus; + box-shadow: 0 0 0 .2rem @color-input-border-focus-shadow; + background: @color-dark-input-background-focus; + } + + #tasklist .progressbar .progressvalue { + border-color: @color-dark-warning; + } + + .listing { + li > div.readonly a:first-child, + li.readonly:not(.virtual) > div a:first-child { + &:after { + color: @color-dark-font; + background-color: @color-dark-background; + } + } + } + + .dialog-message { + opacity: 1; + color: @color-dark-font; + background-color: @color-dark-warning; + } +}
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/skins/elastic/include/kolab_activesync.less -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/skins/elastic/include/kolab_activesync.less
Changed
@@ -37,7 +37,7 @@ } span { - .overflow-ellipsis; + .overflow-ellipsis(); } }
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/skins/elastic/include/kolab_files.less -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/skins/elastic/include/kolab_files.less
Changed
@@ -492,7 +492,7 @@ td,th { padding-left: .15rem; max-width: 10vw; // needed for overflow - .overflow-ellipsis; + .overflow-ellipsis(); &:last-child { padding-right: .15rem;
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/skins/elastic/include/kolab_notes.less -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/skins/elastic/include/kolab_notes.less
Changed
@@ -67,7 +67,7 @@ } td.title { - .overflow-ellipsis; + .overflow-ellipsis(); flex: 1; &:before { @@ -89,7 +89,7 @@ } & > a { - .overflow-ellipsis; + .overflow-ellipsis(); white-space: nowrap; display: block; text-decoration: none;
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/skins/elastic/include/kolab_tags.less -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/skins/elastic/include/kolab_tags.less
Changed
@@ -62,16 +62,9 @@ select { padding: 0; margin-bottom: .5rem; - - &:focus { - box-shadow: none !important; - border: 1px solid @color-layout-border; - } } option { - color: @color-font; // fix Firefox issue caused by text-shadow below - text-shadow: none; padding: .5rem; outline: 0; border: 0;
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/skins/elastic/include/libcalendaring.less -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/skins/elastic/include/libcalendaring.less
Changed
@@ -129,7 +129,7 @@ &.loading:before { &:extend(.font-icon-class); - .animated-icon-class; + .animated-icon-class(); content: @fa-var-circle-notch; line-height: 1; } @@ -279,7 +279,7 @@ display: flex; & > :first-child { - .overflow-ellipsis; + .overflow-ellipsis(); // width and flex is required to make overflow working flex: 1; width: 1px; @@ -357,7 +357,7 @@ input[type=button] { margin-left: .5em; - .overflow-ellipsis; + .overflow-ellipsis(); } } @@ -611,7 +611,7 @@ font-size: .9rem; color: @color-black-shade-text; white-space: nowrap; - .overflow-ellipsis; + .overflow-ellipsis(); } .alarm-actions { @@ -695,7 +695,7 @@ padding: .5rem .5rem .5rem .65rem; &:before { - .font-icon-class; + .font-icon-class(); margin: 0 1rem 0 0; width: 1em; line-height: 1.2;
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/skins/elastic/include/tasklist.less -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/skins/elastic/include/tasklist.less
Changed
@@ -160,7 +160,7 @@ padding: 0 0 0 .2em; padding-left: (1 * @listing-treetoggle-width + .25rem); margin-right: 2em; - .overflow-ellipsis; + .overflow-ellipsis(); } span.tags { @@ -350,7 +350,7 @@ } .taskitem-draghelper { - .overflow-ellipsis; + .overflow-ellipsis(); } .quickview-active { @@ -360,4 +360,3 @@ #rootdroppable { // TODO ? } -
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/skins/elastic/libkolab.less -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/skins/elastic/libkolab.less
Changed
@@ -24,6 +24,10 @@ @skin: "elastic"; @skin-path: "../../../../skins/@{skin}"; +// Disable dark mode support for compatibility with Roundcube 1.4. +// The variable has been added to variables.less in Roundcube 1.5. +@dark-mode-enabled: false; + @import (reference) "@{skin-path}/styles/variables"; @import (reference) "@{skin-path}/styles/mixins"; @@ -47,7 +51,7 @@ display: flex; & > a:first-child { - .overflow-ellipsis; + .overflow-ellipsis(); position: relative; flex-grow: 1; @@ -155,7 +159,7 @@ content: @fa-var-lock; position: absolute; left: 2.25rem; - top: @listing-line-height / 2; + top: (@listing-line-height / 2); font-size: .9em !important; width: .9em; line-height: 1; @@ -166,7 +170,7 @@ opacity: .9; html.touch & { - top: @listing-touch-line-height / 2; + top: (@listing-touch-line-height / 2); left: 2.7rem; } } @@ -219,7 +223,7 @@ right: 0; min-width: 2em; line-height: 1.4rem; - margin: (@listing-line-height - 1.4 * @page-font-size)/2; + margin: ((@listing-line-height - 1.4 * @page-font-size) / 2); padding: 0 .3em; border-radius: .4em; background: @color-list-secondary; @@ -229,7 +233,7 @@ html.touch & { line-height: 2rem; - margin: (@listing-touch-line-height - 2 * @page-font-size)/2; + margin: ((@listing-touch-line-height - 2 * @page-font-size) / 2); } } } @@ -429,7 +433,7 @@ } a.messagelink { - .overflow-ellipsis; + .overflow-ellipsis(); } a.delete .inner { @@ -589,7 +593,7 @@ } // Use icons-only on taskmenu with small screen height -@media screen and (max-height: 640px) and (min-width: (@screen-width-small + 1px)) { +@media screen and (max-height: 750px) and (min-width: (@screen-width-small + 1px)) { #layout-menu .popover-header img, #layout-menu { width: @layout-menu-width-sm; @@ -598,7 +602,7 @@ #taskmenu { a { height: @layout-menu-width-sm; - width: 100%; + width: @layout-menu-width-sm; font-size: 1.2rem !important; } @@ -620,3 +624,7 @@ @import "include/kolab_tags"; @import "include/libcalendaring"; @import "include/tasklist"; + +& when (@dark-mode-enabled = true) { + @import "include/darkmode"; +}
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/tests/kolab_date_recurrence.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/tests/kolab_date_recurrence.php
Changed
@@ -21,7 +21,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -class kolab_date_recurrence_test extends PHPUnit_Framework_TestCase +class kolab_date_recurrence_test extends PHPUnit\Framework\TestCase { function setUp() {
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/tests/kolab_storage_config.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/tests/kolab_storage_config.php
Changed
@@ -1,6 +1,6 @@ <?php -class kolab_storage_config_test extends PHPUnit_Framework_TestCase +class kolab_storage_config_test extends PHPUnit\Framework\TestCase { private $params_personal = array( 'folder' => 'Archive',
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/libkolab/tests/kolab_storage_folder.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/libkolab/tests/kolab_storage_folder.php
Changed
@@ -21,7 +21,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -class kolab_storage_folder_test extends PHPUnit_Framework_TestCase +class kolab_storage_folder_test extends PHPUnit\Framework\TestCase { public static function setUpBeforeClass() {
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/tasklist/composer.json -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/tasklist/composer.json
Changed
@@ -4,7 +4,7 @@ "description": "Task management plugin", "homepage": "https://git.kolab.org/diffusion/RPK/", "license": "AGPLv3", - "version": "3.5.4", + "version": "3.5.6", "authors": [ { "name": "Thomas Bruederli",
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/tasklist/drivers/database/tasklist_database_driver.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/tasklist/drivers/database/tasklist_database_driver.php
Changed
@@ -118,8 +118,8 @@ . " VALUES (?, ?, ?, ?)", $this->rc->user->ID, strval($prop['name']), - strval($prop['color']), - $prop['showalarms'] ? 1 : 0 + isset($prop['color']) ? strval($prop['color']) : '', + !empty($prop['showalarms']) ? 1 : 0 ); if ($result) { @@ -143,8 +143,8 @@ "UPDATE " . $this->db_lists . " SET `name` = ?, `color` = ?, `showalarms` = ?" . " WHERE `tasklist_id` = ? AND `user_id` = ?", strval($prop['name']), - strval($prop['color']), - $prop['showalarms'] ? 1 : 0, + isset($prop['color']) ? strval($prop['color']) : '', + !empty($prop['showalarms']) ? 1 : 0, $prop['id'], $this->rc->user->ID ); @@ -163,7 +163,7 @@ { $hidden = array_flip(explode(',', $this->rc->config->get('hidden_tasklists', ''))); - if ($prop['active']) { + if (!empty($prop['active'])) { unset($hidden[$prop['id']]); } else { @@ -291,56 +291,53 @@ $sql_add = ''; // add filter criteria - if ($filter['from'] || ($filter['mask'] & tasklist::FILTER_MASK_TODAY)) { - $sql_add .= " AND (`date` IS NULL OR `date` >= ?)"; - $datefrom = $filter['from']; - } - if ($filter['to']) { - if ($filter['mask'] & tasklist::FILTER_MASK_OVERDUE) { - $sql_add .= " AND (`date` IS NOT NULL AND `date` <= " . $this->rc->db->quote($filter['to']) . ")"; - } - else { - $sql_add .= " AND (`date` IS NULL OR `date` <= " . $this->rc->db->quote($filter['to']) . ")"; + if ($filter) { + if (!empty($filter['from']) || ($filter['mask'] & tasklist::FILTER_MASK_TODAY)) { + $sql_add .= " AND (`date` IS NULL OR `date` >= " . $this->rc->db->quote($filter['from']) . ")"; } - } - // special case 'today': also show all events with date before today - if ($filter['mask'] & tasklist::FILTER_MASK_TODAY) { - $datefrom = date('Y-m-d', 0); - } + if (!empty($filter['to'])) { + if ($filter['mask'] & tasklist::FILTER_MASK_OVERDUE) { + $sql_add .= " AND (`date` IS NOT NULL AND `date` <= " . $this->rc->db->quote($filter['to']) . ")"; + } + else { + $sql_add .= " AND (`date` IS NULL OR `date` <= " . $this->rc->db->quote($filter['to']) . ")"; + } + } - if ($filter['mask'] & tasklist::FILTER_MASK_NODATE) { - $sql_add = " AND `date` IS NULL"; - } + if ($filter['mask'] & tasklist::FILTER_MASK_NODATE) { + $sql_add = " AND `date` IS NULL"; + } - if ($filter['mask'] & tasklist::FILTER_MASK_COMPLETE) { - $sql_add .= " AND " . self::IS_COMPLETE_SQL; - } - else if (empty($filter['since'])) { - // don't show complete tasks by default - $sql_add .= " AND NOT " . self::IS_COMPLETE_SQL; - } + if ($filter['mask'] & tasklist::FILTER_MASK_COMPLETE) { + $sql_add .= " AND " . self::IS_COMPLETE_SQL; + } + else if (empty($filter['since'])) { + // don't show complete tasks by default + $sql_add .= " AND NOT " . self::IS_COMPLETE_SQL; + } - if ($filter['mask'] & tasklist::FILTER_MASK_FLAGGED) { - $sql_add .= " AND `flagged` = 1"; - } + if ($filter['mask'] & tasklist::FILTER_MASK_FLAGGED) { + $sql_add .= " AND `flagged` = 1"; + } - // compose (slow) SQL query for searching - // FIXME: improve searching using a dedicated col and normalized values - if ($filter['search']) { - $sql_query = array(); - foreach (array('title', 'description', 'organizer', 'attendees') as $col) { - $sql_query[] = $this->rc->db->ilike($col, '%' . $filter['search'] . '%'); + // compose (slow) SQL query for searching + // FIXME: improve searching using a dedicated col and normalized values + if ($filter['search']) { + $sql_query = array(); + foreach (array('title', 'description', 'organizer', 'attendees') as $col) { + $sql_query[] = $this->rc->db->ilike($col, '%' . $filter['search'] . '%'); + } + $sql_add = " AND (" . join(" OR ", $sql_query) . ")"; } - $sql_add = " AND (" . join(" OR ", $sql_query) . ")"; - } - if ($filter['since'] && is_numeric($filter['since'])) { - $sql_add .= " AND `changed` >= " . $this->rc->db->quote(date('Y-m-d H:i:s', $filter['since'])); - } + if (!empty($filter['since']) && is_numeric($filter['since'])) { + $sql_add .= " AND `changed` >= " . $this->rc->db->quote(date('Y-m-d H:i:s', $filter['since'])); + } - if ($filter['uid']) { - $sql_add .= " AND `uid` IN (" . implode(',', array_map(array($this->rc->db, 'quote'), $filter['uid'])) . ")"; + if (!empty($filter['uid'])) { + $sql_add .= " AND `uid` IN (" . implode(',', array_map(array($this->rc->db, 'quote'), $filter['uid'])) . ")"; + } } $tasks = array(); @@ -348,8 +345,7 @@ $result = $this->rc->db->query("SELECT * FROM " . $this->db_tasks . " WHERE `tasklist_id` IN (" . join(',', $list_ids) . ")" . " AND `del` = 0" . $sql_add - . " ORDER BY `parent_id`, `task_id` ASC", - $datefrom + . " ORDER BY `parent_id`, `task_id` ASC" ); while ($result && ($rec = $this->rc->db->fetch_assoc($result))) { @@ -375,12 +371,12 @@ $prop['uid'] = $prop; } - $query_col = $prop['id'] ? 'task_id' : 'uid'; + $query_col = !empty($prop['id']) ? 'task_id' : 'uid'; $result = $this->rc->db->query("SELECT * FROM " . $this->db_tasks . " WHERE `tasklist_id` IN (" . $this->list_ids . ")" . " AND `$query_col` = ? AND `del` = 0", - $prop['id'] ? $prop['id'] : $prop['uid'] + !empty($prop['id']) ? $prop['id'] : $prop['uid'] ); if ($result && ($rec = $this->rc->db->fetch_assoc($result))) { @@ -557,22 +553,24 @@ public function create_task($prop) { // check list permissions - $list_id = $prop['list'] ? $prop['list'] : reset(array_keys($this->lists)); - if (!$this->lists[$list_id] || $this->lists[$list_id]['readonly']) { + $list_id = !empty($prop['list']) ? $prop['list'] : reset(array_keys($this->lists)); + if (empty($this->lists[$list_id]) || !empty($this->lists[$list_id]['readonly'])) { return false; } - if (is_array($prop['valarms'])) { + if (!empty($prop['valarms'])) { $prop['alarms'] = $this->serialize_alarms($prop['valarms']); } - if (is_array($prop['recurrence'])) { + + if (!empty($prop['recurrence'])) { $prop['recurrence'] = $this->serialize_recurrence($prop['recurrence']); } - if (array_key_exists('complete', $prop)) { + + if (array_key_exists('complete', $prop) && !empty($prop['complete'])) { $prop['complete'] = number_format($prop['complete'], 2, '.', ''); } - foreach (array('parent_id', 'date', 'time', 'startdate', 'starttime', 'alarms', 'recurrence', 'status') as $col) { + foreach (array('parent_id', 'date', 'time', 'startdate', 'starttime', 'alarms', 'recurrence', 'status', 'complete') as $col) { if (empty($prop[$col])) { $prop[$col] = null; } @@ -594,13 +592,13 @@ $prop['time'], $prop['startdate'], $prop['starttime'], - strval($prop['description']), - join(',', (array)$prop['tags']), - $prop['flagged'] ? 1 : 0, + isset($prop['description']) ? strval($prop['description']) : '', + !empty($prop['tags']) ? join(',', (array)$prop['tags']) : '', + !empty($prop['flagged']) ? 1 : 0, $prop['complete'] ?: 0, strval($prop['status']), - $prop['alarms'], - $prop['recurrence'], + isset($prop['alarms']) ? $prop['alarms'] : '', + isset($prop['recurrence']) ? $prop['recurrence'] : '', $notify_at );
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/tasklist/drivers/kolab/tasklist_kolab_driver.php
Changed
@@ -1682,7 +1682,7 @@ if (strlen($folder_name)) { $path_imap = explode($delim, $folder_name); array_pop($path_imap); // pop off name part - $path_imap = implode($path_imap, $delim); + $path_imap = implode($delim, $path_imap); $options = $storage->folder_info($folder_name); }
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/tasklist/tasklist.js -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/tasklist/tasklist.js
Changed
@@ -1430,8 +1430,11 @@ ) .attr('tabindex', '0') .attr('aria-labelledby', label_id) - .data('id', rec.id) - .draggable({ + .data('id', rec.id); + + // Make the task draggable, but not in the Elastic skin on touch devices, to fix scrolling + if (!window.UI || !UI.is_touch || !window.UI.is_touch()) { + div.draggable({ revert: 'invalid', addClasses: false, cursorAt: { left:-10, top:12 }, @@ -1442,6 +1445,7 @@ drag: task_draggable_move, revertDuration: 300 }); + } if (window.kolab_tags_text_block) { var tags = rec.tags || [];
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/tasklist/tasklist.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/tasklist/tasklist.php
Changed
@@ -66,6 +66,7 @@ private $collapsed_tasks = array(); private $message_tasks = array(); + private $task_titles = array(); /** @@ -139,7 +140,7 @@ } // add 'Create event' item to message menu - if ($this->api->output->type == 'html' && $_GET['_rel'] != 'task') { + if ($this->api->output->type == 'html' && (empty($_GET['_rel']) || $_GET['_rel'] != 'task')) { $this->api->add_content(html::tag('li', array('role' => 'menuitem'), $this->api->output->button(array( 'command' => 'tasklist-create-from-mail', @@ -155,7 +156,7 @@ } } - if (!$this->rc->output->ajax_call && !$this->rc->output->env['framed']) { + if (!$this->rc->output->ajax_call && empty($this->rc->output->env['framed'])) { $this->load_ui(); $this->ui->init(); } @@ -181,7 +182,7 @@ */ private function load_driver() { - if (is_object($this->driver)) { + if (!empty($this->driver)) { return; } @@ -209,15 +210,16 @@ // force notify if hidden + active $itip_send_option = (int)$this->rc->config->get('calendar_itip_send_option', 3); - if ($itip_send_option === 1 && empty($rec['_reportpartstat'])) + if ($itip_send_option === 1 && empty($rec['_reportpartstat'])) { $rec['_notify'] = 1; + } switch ($action) { case 'new': $oldrec = null; $rec = $this->prepare_task($rec); $rec['uid'] = $this->generate_uid(); - $temp_id = $rec['tempid']; + $temp_id = !empty($rec['tempid']) ? $rec['tempid'] : null; if ($success = $this->driver->create_task($rec)) { $refresh = $this->driver->get_task($rec); if ($temp_id) $refresh['tempid'] = $temp_id; @@ -514,7 +516,7 @@ } // send out notifications - if ($success && $rec['_notify'] && ($rec['attendees'] || $oldrec['attendees'])) { + if ($success && !empty($rec['_notify']) && ($rec['attendees'] || $oldrec['attendees'])) { // make sure we have the complete record $task = $action == 'delete' ? $oldrec : $this->driver->get_task($rec); @@ -528,7 +530,7 @@ } } - if ($success && $rec['_reportpartstat'] && $rec['_reportpartstat'] != 'NEEDS-ACTION') { + if ($success && !empty($rec['_reportpartstat']) && $rec['_reportpartstat'] != 'NEEDS-ACTION') { // get the full record after update if (!$task) { $task = $this->driver->get_task($rec); @@ -556,7 +558,7 @@ $this->rc->output->command('plugin.unlock_saving', $success); if ($refresh) { - if ($refresh['id']) { + if (!empty($refresh['id'])) { $this->encode_task($refresh); } else if (is_array($refresh)) { @@ -575,8 +577,8 @@ */ private function load_itip() { - if (!$this->itip) { - require_once realpath(__DIR__ . '/../libcalendaring/lib/libcalendaring_itip.php'); + if (empty($this->itip)) { + require_once __DIR__ . '/../libcalendaring/lib/libcalendaring_itip.php'; $this->itip = new libcalendaring_itip($this, 'tasklist'); $this->itip->set_rsvp_actions(array('accepted','declined','delegated')); $this->itip->set_rsvp_status(array('accepted','tentative','declined','delegated','in-process','completed')); @@ -591,7 +593,7 @@ private function prepare_task($rec) { // try to be smart and extract date from raw input - if ($rec['raw']) { + if (!empty($rec['raw'])) { foreach (array('today','tomorrow','sunday','monday','tuesday','wednesday','thursday','friday','saturday','sun','mon','tue','wed','thu','fri','sat') as $word) { $locwords[] = '/^' . preg_quote(mb_strtolower($this->gettext($word))) . '\b/i'; $normwords[] = $word; @@ -675,7 +677,7 @@ } // convert the submitted alarm values - if ($rec['valarms']) { + if (!empty($rec['valarms'])) { $valarms = array(); foreach (libcalendaring::from_client_alarms($rec['valarms']) as $alarm) { // alarms can only work with a date (either task start, due or absolute alarm date) @@ -701,7 +703,7 @@ // translate count into an absolute end date. // why? because when shifting completed tasks to the next recurrence, // the initial start date to count from gets lost. - if ($rec['recurrence']['COUNT']) { + if (!empty($rec['recurrence']['COUNT'])) { $engine = libcalendaring::get_recurrence(); $engine->init($rec['recurrence'], $refdate); if ($until = $engine->end()) { @@ -717,7 +719,7 @@ $attachments = array(); $taskid = $rec['id']; - if (is_array($_SESSION[self::SESSION_KEY]) && $_SESSION[self::SESSION_KEY]['id'] == $taskid) { + if (!empty($_SESSION[self::SESSION_KEY]) && $_SESSION[self::SESSION_KEY]['id'] == $taskid) { if (!empty($_SESSION[self::SESSION_KEY]['attachments'])) { foreach ($_SESSION[self::SESSION_KEY]['attachments'] as $id => $attachment) { if (is_array($rec['attachments']) && in_array($id, $rec['attachments'])) { @@ -736,12 +738,15 @@ } // convert invalid data - if (isset($rec['attendees']) && !is_array($rec['attendees'])) + if (isset($rec['attendees']) && !is_array($rec['attendees'])) { $rec['attendees'] = array(); + } - foreach ((array)$rec['attendees'] as $i => $attendee) { - if (is_string($attendee['rsvp'])) { - $rec['attendees'][$i]['rsvp'] = $attendee['rsvp'] == 'true' || $attendee['rsvp'] == '1'; + if (!empty($rec['attendees'])) { + foreach ((array) $rec['attendees'] as $i => $attendee) { + if (is_string($attendee['rsvp'])) { + $rec['attendees'][$i]['rsvp'] = $attendee['rsvp'] == 'true' || $attendee['rsvp'] == '1'; + } } } @@ -1000,7 +1005,7 @@ $list += array('showalarms' => true, 'active' => true, 'editable' => true); if ($insert_id = $this->driver->create_list($list)) { $list['id'] = $insert_id; - if (!$list['_reload']) { + if (empty($list['_reload'])) { $this->load_ui(); $list['html'] = $this->ui->tasklist_list_item($insert_id, $list, $jsenv); $list += (array)$jsenv[$insert_id]; @@ -1048,7 +1053,7 @@ $results[] = $prop; } // report more results available - if ($this->driver->search_more_results) { + if (!empty($this->driver->search_more_results)) { $this->rc->output->show_message('autocompletemore', 'notice'); } @@ -1056,10 +1061,12 @@ return; } - if ($success) + if ($success) { $this->rc->output->show_message('successfullysaved', 'confirmation'); - else + } + else { $this->rc->output->show_message('tasklist.errorsaving', 'error'); + } $this->rc->output->command('plugin.unlock_saving'); } @@ -1074,8 +1081,9 @@ } else { foreach ($this->driver->get_lists() as $list) { - if ($list['active']) + if (!empty($list['active'])) { $lists[] = $list['id']; + } } } $counts = $this->driver->count_tasks($lists); @@ -1161,7 +1169,7 @@ $data = $this->task_tree = $this->task_titles = array(); foreach ($records as $rec) { - if ($rec['parent_id']) { + if (!empty($rec['parent_id'])) { $this->task_tree[$rec['id']] = $rec['parent_id']; }
View file
roundcubemail-plugins-kolab-3.5.5.tar.gz/plugins/tasklist/tasklist_ui.php -> roundcubemail-plugins-kolab-3.5.6.tar.gz/plugins/tasklist/tasklist_ui.php
Changed
@@ -83,8 +83,9 @@ // get user identity to create default attendee foreach ($this->rc->user->list_emails() as $rec) { - if (!$identity) + if (empty($identity)) { $identity = $rec; + } $identity['emails'][] = $rec['email']; $settings['identities'][$rec['identity_id']] = $rec['email']; @@ -184,14 +185,15 @@ $html = ''; foreach ((array)$lists as $id => $prop) { - if ($attrib['activeonly'] && !$prop['active']) - continue; + if (!empty($attrib['activeonly']) && empty($prop['active'])) { + continue; + } $html .= html::tag('li', array( 'id' => 'rcmlitasklist' . rcube_utils::html_identifier($id), - 'class' => $prop['group'], + 'class' => isset($prop['group']) ? $prop['group'] : null, ), - $this->tasklist_list_item($id, $prop, $jsenv, $attrib['activeonly']) + $this->tasklist_list_item($id, $prop, $jsenv, !empty($attrib['activeonly'])) ); } } @@ -241,7 +243,7 @@ public function tasklist_list_item($id, $prop, &$jsenv, $activeonly = false) { // enrich list properties with settings from the driver - if (!$prop['virtual']) { + if (empty($prop['virtual'])) { unset($prop['user_id']); $prop['alarms'] = $this->plugin->driver->alarms; $prop['undelete'] = $this->plugin->driver->undelete; @@ -253,17 +255,27 @@ } $classes = array('tasklist'); - $title = $prop['title'] ?: ($prop['name'] != $prop['listname'] || strlen($prop['name']) > 25 ? - html_entity_decode($prop['name'], ENT_COMPAT, RCUBE_CHARSET) : ''); + $title = ''; - if ($prop['virtual']) + if (!empty($prop['title'])) { + $title = $prop['title']; + } + else if (empty($prop['listname']) || $prop['name'] != $prop['listname'] || strlen($prop['name']) > 25) { + html_entity_decode($prop['name'], ENT_COMPAT, RCUBE_CHARSET); + } + + if (!empty($prop['virtual'])) { $classes[] = 'virtual'; - else if (!$prop['editable']) + } + else if (empty($prop['editable'])) { $classes[] = 'readonly'; - if ($prop['subscribed']) + } + if (!empty($prop['subscribed'])) { $classes[] = 'subscribed'; - if ($prop['class']) + } + if (!empty($prop['class'])) { $classes[] = $prop['class']; + } if (!$activeonly || $prop['active']) { $label_id = 'tl:' . $id; @@ -277,9 +289,10 @@ )); return html::div(join(' ', $classes), - html::a(array('class' => 'listname', 'title' => $title, 'href' => '#', 'id' => $label_id), $prop['listname'] ?: $prop['name']) . - ($prop['virtual'] ? '' : $chbox . html::span('actions', - ($prop['removable'] ? html::a(array('href' => '#', 'class' => 'remove', 'title' => $this->plugin->gettext('removelist')), ' ') : '') + html::a(array('class' => 'listname', 'title' => $title, 'href' => '#', 'id' => $label_id), + !empty($prop['listname']) ? $prop['listname'] : $prop['name']) . + (!empty($prop['virtual']) ? '' : $chbox . html::span('actions', + (!empty($prop['removable']) ? html::a(array('href' => '#', 'class' => 'remove', 'title' => $this->plugin->gettext('removelist')), ' ') : '') . html::a(array('href' => '#', 'class' => 'quickview', 'title' => $this->plugin->gettext('focusview'), 'role' => 'checkbox', 'aria-checked' => 'false'), ' ') . (isset($prop['subscribed']) ? html::a(array('href' => '#', 'class' => 'subscribed', 'title' => $this->plugin->gettext('tasklistsubscribe'), 'role' => 'checkbox', 'aria-checked' => $prop['subscribed'] ? 'true' : 'false'), ' ') : '') ) @@ -319,15 +332,18 @@ $select = new html_select($attrib); $default = null; - foreach ((array) $attrib['extra'] as $id => $name) { - $select->add($name, $id); + if (!empty($attrib['extra'])) { + foreach ((array) $attrib['extra'] as $id => $name) { + $select->add($name, $id); + } } - foreach ((array)$this->plugin->driver->get_lists() as $id => $prop) { - if ($prop['editable'] || strpos($prop['rights'], 'i') !== false) { + foreach ((array) $this->plugin->driver->get_lists() as $id => $prop) { + if (!empty($prop['editable']) || strpos($prop['rights'], 'i') !== false) { $select->add($prop['name'], $id); - if (!$default || $prop['default']) + if (!$default || !empty($prop['default'])) { $default = $id; + } } } @@ -421,7 +437,12 @@ $attrib += array('id' => 'rcmtasktagsedit'); $this->register_gui_object('edittagline', $attrib['id']); - $input = new html_inputfield(array('name' => 'tags[]', 'class' => 'tag', 'size' => $attrib['size'], 'tabindex' => $attrib['tabindex'])); + $input = new html_inputfield(array( + 'name' => 'tags[]', + 'class' => 'tag', + 'size' => !empty($attrib['size']) ? $attrib['size'] : null, + 'tabindex' => isset($attrib['tabindex']) ? $attrib['tabindex'] : null, + )); unset($attrib['tabindex']); return html::div($attrib, $input->show('')); } @@ -461,9 +482,21 @@ */ function attendees_form($attrib = array()) { - $input = new html_inputfield(array('name' => 'participant', 'id' => 'edit-attendee-name', 'size' => $attrib['size'], 'class' => 'form-control')); - $textarea = new html_textarea(array('name' => 'comment', 'id' => 'edit-attendees-comment', - 'rows' => 4, 'cols' => 55, 'title' => $this->plugin->gettext('itipcommenttitle'), 'class' => 'form-control')); + $input = new html_inputfield(array( + 'name' => 'participant', + 'id' => 'edit-attendee-name', + 'size' => !empty($attrib['size']) ? $attrib['size'] : null, + 'class' => 'form-control' + )); + + $textarea = new html_textarea(array( + 'name' => 'comment', + 'id' => 'edit-attendees-comment', + 'rows' => 4, + 'cols' => 55, + 'title' => $this->plugin->gettext('itipcommenttitle'), + 'class' => 'form-control' + )); return html::div($attrib, html::div('form-searchbar', $input->show() . " " . @@ -488,7 +521,7 @@ */ function tasks_import_form($attrib = array()) { - if (!$attrib['id']) { + if (empty($attrib['id'])) { $attrib['id'] = 'rcmImportForm'; } @@ -503,7 +536,7 @@ 'id' => 'importfile', 'type' => 'file', 'name' => '_data', - 'size' => $attrib['uploadfieldsize'], + 'size' => !empty($attrib['uploadfieldsize']) ? $attrib['uploadfieldsize'] : null, 'accept' => $accept )); @@ -537,11 +570,11 @@ */ function tasks_export_form($attrib = array()) { - if (!$attrib['id']) { + if (empty($attrib['id'])) { $attrib['id'] = 'rcmTaskExportForm'; } - $html .= html::div('form-section form-group row', + $html = html::div('form-section form-group row', html::label(array('for' => 'task-export-list', 'class' => 'col-sm-4 col-form-label'), $this->plugin->gettext('list')) . html::div('col-sm-8', $this->tasklist_select(array( 'name' => 'source',
View file
roundcubemail-plugins-kolab.dsc
Changed
@@ -2,7 +2,7 @@ Source: roundcubemail-plugins-kolab Binary: roundcubemail-plugins-kolab Architecture: all -Version: 1:3.5.5-0~kolab2 +Version: 1:3.5.6-0~kolab1 Maintainer: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> Uploaders: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com> Standards-Version: 3.9.3 @@ -37,5 +37,5 @@ roundcubemail-plugin-tinymce-config deb web extra roundcubemail-plugin-wap-client deb web extra Files: - 00000000000000000000000000000000 0 roundcubemail-plugins-kolab-3.5.5.tar.gz + 00000000000000000000000000000000 0 roundcubemail-plugins-kolab-3.5.6.tar.gz 00000000000000000000000000000000 0 debian.tar.gz
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.