Projects
Kolab:16:Testing
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 82
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_mapstrtolower($event'free_busy')); - $event'sensitivity' = intval($this->sensitivity_mapstrtolower($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 && $sattr0 === '{') { - $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) && $sattr0 === '{') { + $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 = $statusstrtolower($attendee'email'))) { - $attendee'status' = $_status; + if (!empty($attendee'email') && !empty($statusstrtolower($attendee'email'))) { + $attendee'status' = $statusstrtolower($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' => $alarm3 ?: $alarm0)); } } - $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) { $paramsstrtoupper($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 = $values2; } - if (!$alarm'trigger') { + if (empty($alarm'trigger')) { $alarm'trigger' = rtrim(preg_replace('/(A-Z)0WDHMS/', '\\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', $alarm3, "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-listtabindex="-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 @@ inputtype=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($_SESSIONself::SESSION_KEY) && $_SESSIONself::SESSION_KEY'id' == $taskid) { + if (!empty($_SESSIONself::SESSION_KEY) && $_SESSIONself::SESSION_KEY'id' == $taskid) { if (!empty($_SESSIONself::SESSION_KEY'attachments')) { foreach ($_SESSIONself::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
.