Use consistent PHP code style

This commit is contained in:
Aleksander Machniak 2024-01-24 11:24:41 +01:00
parent f3319891d5
commit 5271b6e787
339 changed files with 8405 additions and 8522 deletions

43
.php-cs-fixer.php Normal file
View file

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
use PhpCsFixer\Config;
use PhpCsFixer\Finder;
$finder = Finder::create()
->in([__DIR__ . '/plugins'])
->ignoreDotFiles(false)
->name('*.inc')
->name('*.php.dist');
return (new Config())
->setRiskyAllowed(true)
->setRules([
'@PHP74Migration' => true,
'@PHP74Migration:risky' => true,
'@PHP80Migration' => true,
'@PSR1' => true,
'@PSR12' => true,
'concat_space' => [
'spacing' => 'one',
],
'declare_strict_types' => false,
'phpdoc_add_missing_param_annotation' => false,
'use_arrow_functions' => false,
'void_return' => false,
'yoda_style' => [
'equal' => false,
'identical' => false,
],
// TODO - risky
'no_unset_on_property' => false,
'random_api_migration' => false,
'strict_param' => false,
])
->setFinder($finder)
->setCacheFile(sys_get_temp_dir() . '/php-cs-fixer.' . md5(__DIR__) . '.cache');

File diff suppressed because it is too large Load diff

View file

@ -81,12 +81,12 @@ $config['calendar_default_alarm_offset'] = '-15M';
$config['calendar_event_coloring'] = 0;
// event categories
$config['calendar_categories'] = array(
$config['calendar_categories'] = [
'Personal' => 'c0c0c0',
'Work' => 'ff0000',
'Family' => '00ff00',
'Holiday' => 'ff6600',
);
];
// enable users to invite/edit attendees for shared events organized by others
$config['calendar_allow_invite_shared'] = false;

View file

@ -59,8 +59,7 @@ class caldav_calendar extends kolab_storage_dav_folder
{
if ($folder_or_id instanceof kolab_storage_dav_folder) {
$this->storage = $folder_or_id;
}
else {
} else {
// $this->storage = kolab_storage_dav::get_folder($folder_or_id, 'event');
}
@ -78,13 +77,13 @@ class caldav_calendar extends kolab_storage_dav_folder
if ($this->storage->get_namespace() == 'personal') {
$this->editable = true;
$this->rights = 'lrswikxteav';
}
else {
} else {
$rights = $this->storage->get_myrights();
if ($rights) {
$this->rights = $rights;
if (strpos($rights, 't') !== false || strpos($rights, 'd') !== false) {
$this->editable = strpos($rights, 'i');;
$this->editable = strpos($rights, 'i');
;
}
}
}
@ -118,16 +117,16 @@ class caldav_calendar extends kolab_storage_dav_folder
*/
public function get_caldav_url()
{
/*
if ($template = $this->cal->rc->config->get('calendar_caldav_url', null)) {
return strtr($template, [
'%h' => $_SERVER['HTTP_HOST'],
'%u' => urlencode($this->cal->rc->get_user_name()),
'%i' => urlencode($this->storage->get_uid()),
'%n' => urlencode($this->name),
]);
}
*/
/*
if ($template = $this->cal->rc->config->get('calendar_caldav_url', null)) {
return strtr($template, [
'%h' => $_SERVER['HTTP_HOST'],
'%u' => urlencode($this->cal->rc->get_user_name()),
'%i' => urlencode($this->storage->get_uid()),
'%n' => urlencode($this->name),
]);
}
*/
return false;
}
@ -166,8 +165,7 @@ class caldav_calendar extends kolab_storage_dav_folder
// check for match on the first instance already
if (!empty($master['_instance']) && $master['_instance'] == $instance_id) {
$this->events[$id] = $master;
}
else if (!empty($master['recurrence'])) {
} elseif (!empty($master['recurrence'])) {
$start_date = $master['start'];
// For performance reasons we'll get only the specific instance
if (($date = substr($id, strlen($master_id) + 1, 8)) && strlen($date) == 8 && is_numeric($date)) {
@ -190,15 +188,15 @@ class caldav_calendar extends kolab_storage_dav_folder
{
$event = $this->get_event($event['id']);
$data = $this->storage->get_attachment($id, $event);
/*
if ($data === false) {
// try again with master UID
$uid = preg_replace('/-\d+(T\d{6})?$/', '', $event['id']);
if ($uid != $event['id']) {
$data = $this->storage->get_attachment($uid, $id); // TODO
}
}
*/
/*
if ($data === false) {
// try again with master UID
$uid = preg_replace('/-\d+(T\d{6})?$/', '', $event['id']);
if ($uid != $event['id']) {
$data = $this->storage->get_attachment($uid, $id); // TODO
}
}
*/
return $data;
}
@ -219,14 +217,12 @@ class caldav_calendar extends kolab_storage_dav_folder
// to workaround possible timezone differences
try {
$start = new DateTime('@' . ($start - 12 * 3600));
}
catch (Exception $e) {
} catch (Exception $e) {
$start = new DateTime('@0');
}
try {
$end = new DateTime('@' . ($end + 12 * 3600));
}
catch (Exception $e) {
} catch (Exception $e) {
$end = new DateTime('today +10 years');
}
@ -323,7 +319,7 @@ class caldav_calendar extends kolab_storage_dav_folder
$events = array_merge($events, $this->get_recurring_events($event, $start, $end));
}
// add top-level exceptions (aka loose single occurrences)
else if (!empty($record['exceptions'])) {
elseif (!empty($record['exceptions'])) {
foreach ($record['exceptions'] as $ex) {
$component = $this->_to_driver_event($ex, false, false, $record);
if ($component['start'] <= $end && $component['end'] >= $start) {
@ -335,7 +331,7 @@ class caldav_calendar extends kolab_storage_dav_folder
// post-filter all events by fulltext search and partstat values
$me = $this;
$events = array_filter($events, function($event) use ($words, $partstat_exclude, $user_emails, $me) {
$events = array_filter($events, function ($event) use ($words, $partstat_exclude, $user_emails, $me) {
// fulltext search
if (count($words)) {
$hits = 0;
@ -382,16 +378,14 @@ class caldav_calendar extends kolab_storage_dav_folder
{
// convert to DateTime for comparisons
try {
$start = new DateTime('@'.$start);
}
catch (Exception $e) {
$start = new DateTime('@' . $start);
} catch (Exception $e) {
$start = new DateTime('@0');
}
if ($end) {
try {
$end = new DateTime('@'.$end);
}
catch (Exception $e) {
$end = new DateTime('@' . $end);
} catch (Exception $e) {
$end = null;
}
}
@ -409,8 +403,7 @@ class caldav_calendar extends kolab_storage_dav_folder
$query[] = ['tags', '!=', 'x-partstat:' . $email . ':needs-action'];
$query[] = ['tags', '!=', 'x-partstat:' . $email . ':declined'];
}
}
else if (is_array($filter_query)) {
} elseif (is_array($filter_query)) {
$query = array_merge($query, $filter_query);
}
@ -439,11 +432,13 @@ class caldav_calendar extends kolab_storage_dav_folder
$saved = $this->storage->save($object, 'event');
if (!$saved) {
rcube::raise_error([
rcube::raise_error(
[
'code' => 600, 'file' => __FILE__, 'line' => __LINE__,
'message' => "Error saving event object to DAV server"
'message' => "Error saving event object to DAV server",
],
true, false
true,
false
);
return false;
}
@ -483,14 +478,15 @@ class caldav_calendar extends kolab_storage_dav_folder
$saved = $this->storage->save($object, 'event', $old['uid']);
if (!$saved) {
rcube::raise_error([
rcube::raise_error(
[
'code' => 600, 'file' => __FILE__, 'line' => __LINE__,
'message' => "Error saving event object to CalDAV server"
'message' => "Error saving event object to CalDAV server",
],
true, false
true,
false
);
}
else {
} else {
// save links in configuration.relation object
// if ($this->save_links($event['uid'], $links)) {
// $object['links'] = $links;
@ -521,11 +517,13 @@ class caldav_calendar extends kolab_storage_dav_folder
$deleted = $this->storage->delete($uid, $force);
if (!$deleted) {
rcube::raise_error([
rcube::raise_error(
[
'code' => 600, 'file' => __FILE__, 'line' => __LINE__,
'message' => "Error deleting event '{$uid}' from CalDAV server"
'message' => "Error deleting event '{$uid}' from CalDAV server",
],
true, false
true,
false
);
}
@ -697,8 +695,7 @@ class caldav_calendar extends kolab_storage_dav_folder
if ($limit && count($events) >= $limit) {
return $events;
}
}
else if ($next_event['start'] > $end) {
} elseif ($next_event['start'] > $end) {
// stop loop if out of range
break;
}
@ -746,14 +743,13 @@ class caldav_calendar extends kolab_storage_dav_folder
&& empty($record['recurrence_id']) && empty($record['_instance'])
) {
$record['_instance'] = $record['start']->format($recurrence_id_format);
}
else if (isset($record['recurrence_date']) && $record['recurrence_date'] instanceof DateTimeInterface) {
} elseif (isset($record['recurrence_date']) && $record['recurrence_date'] instanceof DateTimeInterface) {
$record['_instance'] = $record['recurrence_date']->format($recurrence_id_format);
}
// clean up exception data
if (!empty($record['recurrence']) && !empty($record['recurrence']['EXCEPTIONS'])) {
array_walk($record['recurrence']['EXCEPTIONS'], function(&$exception) {
array_walk($record['recurrence']['EXCEPTIONS'], function (&$exception) {
unset($exception['_attachments']);
});
}
@ -804,7 +800,7 @@ class caldav_calendar extends kolab_storage_dav_folder
}
// remove some internal properties which should not be cached
$cleanup_fn = function(&$event) {
$cleanup_fn = function (&$event) {
unset($event['_savemode'], $event['_fromcalendar'], $event['_identity'], $event['_folder_id'],
$event['calendar'], $event['className'], $event['recurrence_id'],
$event['attachments'], $event['deleted_attachments']);
@ -866,13 +862,11 @@ class caldav_calendar extends kolab_storage_dav_folder
foreach ($prop as $key => $val) {
if (is_numeric($key)) {
$out .= self::_complex2string($val);
}
else if (!in_array($key, $ignorekeys)) {
} elseif (!in_array($key, $ignorekeys)) {
$out .= $val . ' ';
}
}
}
else if (is_string($prop) || is_numeric($prop)) {
} elseif (is_string($prop) || is_numeric($prop)) {
$out .= $prop . ' ';
}

View file

@ -80,7 +80,7 @@ class caldav_driver extends kolab_driver
// get all folders that support VEVENT, sorted by namespace/name
$folders = $this->storage->get_folders('event');
// + $this->storage->get_user_folders('event', true);
// + $this->storage->get_user_folders('event', true);
$this->calendars = [];
@ -109,8 +109,7 @@ class caldav_driver extends kolab_driver
if ($folder instanceof kolab_storage_folder_user) {
$calendar = new kolab_user_calendar($folder, $this->cal);
$calendar->subscriptions = count($folder->children) > 0;
}
else {
} else {
$calendar = new caldav_calendar($folder, $this->cal);
}
@ -134,121 +133,121 @@ class caldav_driver extends kolab_driver
$prefs = $this->rc->config->get('kolab_calendars', []);
// include virtual folders for a full folder tree
/*
if (!is_null($tree)) {
$folders = $this->storage->folder_hierarchy($folders, $tree);
}
*/
/*
if (!is_null($tree)) {
$folders = $this->storage->folder_hierarchy($folders, $tree);
}
*/
$parents = array_keys($this->calendars);
foreach ($folders as $id => $cal) {
$parent_id = null;
/*
$path = explode('/', $cal->name);
/*
$path = explode('/', $cal->name);
// find parent
do {
array_pop($path);
$parent_id = $this->storage->folder_id(implode('/', $path));
}
while (count($path) > 1 && !in_array($parent_id, $parents));
// find parent
do {
array_pop($path);
$parent_id = $this->storage->folder_id(implode('/', $path));
}
while (count($path) > 1 && !in_array($parent_id, $parents));
// restore "real" parent ID
if ($parent_id && !in_array($parent_id, $parents)) {
$parent_id = $this->storage->folder_id($cal->get_parent());
}
// restore "real" parent ID
if ($parent_id && !in_array($parent_id, $parents)) {
$parent_id = $this->storage->folder_id($cal->get_parent());
}
$parents[] = $cal->id;
$parents[] = $cal->id;
if ($cal instanceof kolab_storage_folder_virtual) {
$calendars[$cal->id] = [
'id' => $cal->id,
'name' => $cal->get_name(),
'listname' => $cal->get_foldername(),
'editname' => $cal->get_foldername(),
'virtual' => true,
'editable' => false,
'group' => $cal->get_namespace(),
if ($cal instanceof kolab_storage_folder_virtual) {
$calendars[$cal->id] = [
'id' => $cal->id,
'name' => $cal->get_name(),
'listname' => $cal->get_foldername(),
'editname' => $cal->get_foldername(),
'virtual' => true,
'editable' => false,
'group' => $cal->get_namespace(),
];
}
else {
*/
// additional folders may come from kolab_storage_dav::folder_hierarchy() above
// make sure we deal with caldav_calendar instances
$cal = $this->_to_calendar($cal);
$this->calendars[$cal->id] = $cal;
$is_user = false; // ($cal instanceof caldav_user_calendar);
$calendars[$cal->id] = [
'id' => $cal->id,
'name' => $cal->get_name(),
'listname' => $cal->get_foldername(),
'editname' => $cal->get_foldername(),
'title' => '', // $cal->get_title(),
'color' => $cal->get_color(),
'editable' => $cal->editable,
'group' => $is_user ? 'other user' : $cal->get_namespace(),
'active' => !isset($prefs[$cal->id]['active']) || !empty($prefs[$cal->id]['active']),
'owner' => $cal->get_owner(),
'removable' => !$cal->default,
// extras to hide some elements in the UI
'subscriptions' => $cal->subscriptions,
'driver' => 'caldav',
];
if (!$is_user) {
$calendars[$cal->id] += [
'default' => $cal->default,
'rights' => $cal->rights,
'showalarms' => $cal->alarms,
'history' => !empty($this->bonnie_api),
'children' => true, // TODO: determine if that folder indeed has child folders
'parent' => $parent_id,
'subtype' => $cal->subtype,
'caldavurl' => '', // $cal->get_caldav_url(),
];
}
else {
*/
// additional folders may come from kolab_storage_dav::folder_hierarchy() above
// make sure we deal with caldav_calendar instances
$cal = $this->_to_calendar($cal);
$this->calendars[$cal->id] = $cal;
$is_user = false; // ($cal instanceof caldav_user_calendar);
$calendars[$cal->id] = [
'id' => $cal->id,
'name' => $cal->get_name(),
'listname' => $cal->get_foldername(),
'editname' => $cal->get_foldername(),
'title' => '', // $cal->get_title(),
'color' => $cal->get_color(),
'editable' => $cal->editable,
'group' => $is_user ? 'other user' : $cal->get_namespace(),
'active' => !isset($prefs[$cal->id]['active']) || !empty($prefs[$cal->id]['active']),
'owner' => $cal->get_owner(),
'removable' => !$cal->default,
// extras to hide some elements in the UI
'subscriptions' => $cal->subscriptions,
'driver' => 'caldav',
];
if (!$is_user) {
$calendars[$cal->id] += [
'default' => $cal->default,
'rights' => $cal->rights,
'showalarms' => $cal->alarms,
'history' => !empty($this->bonnie_api),
'children' => true, // TODO: determine if that folder indeed has child folders
'parent' => $parent_id,
'subtype' => $cal->subtype,
'caldavurl' => '', // $cal->get_caldav_url(),
];
}
/*
}
*/
/*
}
*/
if ($cal->subscriptions) {
$calendars[$cal->id]['subscribed'] = $cal->is_subscribed();
}
}
/*
// list virtual calendars showing invitations
if ($this->rc->config->get('kolab_invitation_calendars') && !($filter & self::FILTER_INSERTABLE)) {
foreach ([self::INVITATIONS_CALENDAR_PENDING, self::INVITATIONS_CALENDAR_DECLINED] as $id) {
$cal = new caldav_invitation_calendar($id, $this->cal);
if (!($filter & self::FILTER_ACTIVE) || $cal->is_active()) {
$calendars[$id] = [
'id' => $cal->id,
'name' => $cal->get_name(),
'listname' => $cal->get_name(),
'editname' => $cal->get_foldername(),
'title' => $cal->get_title(),
'color' => $cal->get_color(),
'editable' => $cal->editable,
'rights' => $cal->rights,
'showalarms' => $cal->alarms,
'history' => !empty($this->bonnie_api),
'group' => 'x-invitations',
'default' => false,
'active' => $cal->is_active(),
'owner' => $cal->get_owner(),
'children' => false,
'counts' => $id == self::INVITATIONS_CALENDAR_PENDING,
];
/*
// list virtual calendars showing invitations
if ($this->rc->config->get('kolab_invitation_calendars') && !($filter & self::FILTER_INSERTABLE)) {
foreach ([self::INVITATIONS_CALENDAR_PENDING, self::INVITATIONS_CALENDAR_DECLINED] as $id) {
$cal = new caldav_invitation_calendar($id, $this->cal);
if (!($filter & self::FILTER_ACTIVE) || $cal->is_active()) {
$calendars[$id] = [
'id' => $cal->id,
'name' => $cal->get_name(),
'listname' => $cal->get_name(),
'editname' => $cal->get_foldername(),
'title' => $cal->get_title(),
'color' => $cal->get_color(),
'editable' => $cal->editable,
'rights' => $cal->rights,
'showalarms' => $cal->alarms,
'history' => !empty($this->bonnie_api),
'group' => 'x-invitations',
'default' => false,
'active' => $cal->is_active(),
'owner' => $cal->get_owner(),
'children' => false,
'counts' => $id == self::INVITATIONS_CALENDAR_PENDING,
];
if (is_object($tree)) {
$tree->children[] = $cal;
if (is_object($tree)) {
$tree->children[] = $cal;
}
}
}
}
}
}
*/
*/
// append the virtual birthdays calendar
if ($this->rc->config->get('calendar_contact_birthdays', false) && !($filter & self::FILTER_INSERTABLE)) {
$id = self::BIRTHDAY_CALENDAR_ID;
@ -353,8 +352,7 @@ class caldav_driver extends kolab_driver
if (isset($prop['showalarms']) && $id == self::BIRTHDAY_CALENDAR_ID) {
$prefs['calendar_birthdays_alarm_type'] = $prop['showalarms'] ? $this->alarm_types[0] : '';
}
else if (isset($prop['showalarms'])) {
} elseif (isset($prop['showalarms'])) {
$prefs['kolab_calendars'][$id]['showalarms'] = !empty($prop['showalarms']);
}
@ -422,40 +420,40 @@ class caldav_driver extends kolab_driver
{
$this->calendars = [];
$this->search_more_results = false;
/*
// find unsubscribed IMAP folders that have "event" type
if ($source == 'folders') {
foreach ((array) $this->storage->search_folders('event', $query, ['other']) as $folder) {
$calendar = new kolab_calendar($folder->name, $this->cal);
$this->calendars[$calendar->id] = $calendar;
}
}
// find other user's virtual calendars
else if ($source == 'users') {
// we have slightly more space, so display twice the number
$limit = $this->rc->config->get('autocomplete_max', 15) * 2;
foreach ($this->storage->search_users($query, 0, [], $limit, $count) as $user) {
$calendar = new caldav_user_calendar($user, $this->cal);
$this->calendars[$calendar->id] = $calendar;
// search for calendar folders shared by this user
foreach ($this->storage->list_user_folders($user, 'event', false) as $foldername) {
$cal = new caldav_calendar($foldername, $this->cal);
$this->calendars[$cal->id] = $cal;
$calendar->subscriptions = true;
/*
// find unsubscribed IMAP folders that have "event" type
if ($source == 'folders') {
foreach ((array) $this->storage->search_folders('event', $query, ['other']) as $folder) {
$calendar = new kolab_calendar($folder->name, $this->cal);
$this->calendars[$calendar->id] = $calendar;
}
}
}
// find other user's virtual calendars
else if ($source == 'users') {
// we have slightly more space, so display twice the number
$limit = $this->rc->config->get('autocomplete_max', 15) * 2;
if ($count > $limit) {
$this->search_more_results = true;
}
}
foreach ($this->storage->search_users($query, 0, [], $limit, $count) as $user) {
$calendar = new caldav_user_calendar($user, $this->cal);
$this->calendars[$calendar->id] = $calendar;
// don't list the birthday calendar
$this->rc->config->set('calendar_contact_birthdays', false);
$this->rc->config->set('kolab_invitation_calendars', false);
*/
// search for calendar folders shared by this user
foreach ($this->storage->list_user_folders($user, 'event', false) as $foldername) {
$cal = new caldav_calendar($foldername, $this->cal);
$this->calendars[$cal->id] = $cal;
$calendar->subscriptions = true;
}
}
if ($count > $limit) {
$this->search_more_results = true;
}
}
// don't list the birthday calendar
$this->rc->config->set('calendar_contact_birthdays', false);
$this->rc->config->set('kolab_invitation_calendars', false);
*/
return $this->list_calendars();
}
@ -475,8 +473,7 @@ class caldav_driver extends kolab_driver
{
if ($calendars && is_string($calendars)) {
$calendars = explode(',', $calendars);
}
else if (!$calendars) {
} elseif (!$calendars) {
$this->_read_calendars();
$calendars = array_keys($this->calendars);
}
@ -506,7 +503,7 @@ class caldav_driver extends kolab_driver
$newcats = array_udiff(
array_keys($categories),
array_keys($old_categories),
function($a, $b) { return strcasecmp($a, $b); }
function ($a, $b) { return strcasecmp($a, $b); }
);
if (!empty($newcats)) {
@ -579,8 +576,7 @@ class caldav_driver extends kolab_driver
&& in_array(strtolower($attendee['email']), $emails)
) {
$is_organizer = true;
}
else if ($attendee['role'] != 'ORGANIZER'
} elseif ($attendee['role'] != 'ORGANIZER'
&& $attendee['role'] != 'NON-PARTICIPANT'
&& $attendee['status'] != 'DELEGATED'
) {
@ -600,7 +596,7 @@ class caldav_driver extends kolab_driver
/**
* Identify changes considered relevant for scheduling
*
*
* @param array Hash array with NEW object properties
* @param array Hash array with OLD object properties
*
@ -631,8 +627,7 @@ class caldav_driver extends kolab_driver
// advanced rrule comparison: no rescheduling if series was shortened
if ($a['COUNT'] && $b['COUNT'] && $b['COUNT'] < $a['COUNT']) {
unset($a['COUNT'], $b['COUNT']);
}
else if ($a['UNTIL'] && $b['UNTIL'] && $b['UNTIL'] < $a['UNTIL']) {
} elseif ($a['UNTIL'] && $b['UNTIL'] && $b['UNTIL'] < $a['UNTIL']) {
unset($a['UNTIL'], $b['UNTIL']);
}
}
@ -660,7 +655,7 @@ class caldav_driver extends kolab_driver
$special_calendars = [
self::BIRTHDAY_CALENDAR_ID,
self::INVITATIONS_CALENDAR_PENDING,
self::INVITATIONS_CALENDAR_DECLINED
self::INVITATIONS_CALENDAR_DECLINED,
];
// show default dialog for birthday calendar

View file

@ -94,15 +94,15 @@
*/
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__';
public const FILTER_ALL = 0;
public const FILTER_WRITEABLE = 1;
public const FILTER_INSERTABLE = 2;
public const FILTER_ACTIVE = 4;
public const FILTER_PERSONAL = 8;
public const FILTER_PRIVATE = 16;
public const FILTER_CONFIDENTIAL = 32;
public const FILTER_SHARED = 64;
public const BIRTHDAY_CALENDAR_ID = '__bdays__';
// features supported by backend
public $alarms = false;
@ -131,7 +131,7 @@ abstract class calendar_driver
*
* @return array List of calendars
*/
abstract function list_calendars($filter = 0);
abstract public function list_calendars($filter = 0);
/**
* Create a new calendar assigned to the current user
@ -143,7 +143,7 @@ abstract class calendar_driver
*
* @return mixed ID of the calendar on success, False on error
*/
abstract function create_calendar($prop);
abstract public function create_calendar($prop);
/**
* Update properties of an existing calendar
@ -156,7 +156,7 @@ abstract class calendar_driver
*
* @return bool True on success, Fales on failure
*/
abstract function edit_calendar($prop);
abstract public function edit_calendar($prop);
/**
* Set active/subscribed state of a calendar
@ -167,7 +167,7 @@ abstract class calendar_driver
*
* @return bool True on success, Fales on failure
*/
abstract function subscribe_calendar($prop);
abstract public function subscribe_calendar($prop);
/**
* Delete the given calendar with all its contents
@ -177,7 +177,7 @@ abstract class calendar_driver
*
* @return bool True on success, Fales on failure
*/
abstract function delete_calendar($prop);
abstract public function delete_calendar($prop);
/**
* Search for shared or otherwise not listed calendars the user has access
@ -187,7 +187,7 @@ abstract class calendar_driver
*
* @return array List of calendars
*/
abstract function search_calendars($query, $source);
abstract public function search_calendars($query, $source);
/**
* Add a single event to the database
@ -196,7 +196,7 @@ abstract class calendar_driver
*
* @return mixed New event ID on success, False on error
*/
abstract function new_event($event);
abstract public function new_event($event);
/**
* Update an event entry with the given data
@ -205,7 +205,7 @@ abstract class calendar_driver
*
* @return bool True on success, False on error
*/
abstract function edit_event($event);
abstract public function edit_event($event);
/**
* Extended event editing with possible changes to the argument
@ -245,7 +245,7 @@ abstract class calendar_driver
*
* @return bool True on success, False on error
*/
abstract function move_event($event);
abstract public function move_event($event);
/**
* Resize a single event
@ -257,7 +257,7 @@ abstract class calendar_driver
*
* @return bool True on success, False on error
*/
abstract function resize_event($event);
abstract public function resize_event($event);
/**
* Remove a single event from the database
@ -269,7 +269,7 @@ abstract class calendar_driver
*
* @return bool True on success, False on error
*/
abstract function remove_event($event, $force = true);
abstract public function remove_event($event, $force = true);
/**
* Restores a single deleted event (if supported)
@ -298,7 +298,7 @@ abstract class calendar_driver
*
* @return array Event object as hash array
*/
abstract function get_event($event, $scope = 0, $full = false);
abstract public function get_event($event, $scope = 0, $full = false);
/**
* Get events from source.
@ -312,7 +312,7 @@ abstract class calendar_driver
*
* @return array A list of event objects (see header of this file for struct of an event)
*/
abstract function load_events($start, $end, $query = null, $calendars = null, $virtual = 1, $modifiedsince = null);
abstract public function load_events($start, $end, $query = null, $calendars = null, $virtual = 1, $modifiedsince = null);
/**
* Get number of events in the given calendar
@ -323,7 +323,7 @@ abstract class calendar_driver
*
* @return array Hash array with counts grouped by calendar ID
*/
abstract function count_events($calendars, $start, $end = null);
abstract public function count_events($calendars, $start, $end = null);
/**
* Get a list of pending alarms to be displayed to the user
@ -340,7 +340,7 @@ abstract class calendar_driver
* title: Event title/summary
* location: Location string
*/
abstract function pending_alarms($time, $calendars = null);
abstract public function pending_alarms($time, $calendars = null);
/**
* (User) feedback after showing an alarm notification
@ -349,7 +349,7 @@ abstract class calendar_driver
* @param string $event_id Event identifier
* @param int $snooze Suspend the alarm for this number of seconds
*/
abstract function dismiss_alarm($event_id, $snooze = 0);
abstract public function dismiss_alarm($event_id, $snooze = 0);
/**
* Check the given event object for validity
@ -455,17 +455,23 @@ abstract class calendar_driver
/**
* Create a new category
*/
public function add_category($name, $color) { }
public function add_category($name, $color)
{
}
/**
* Remove the given category
*/
public function remove_category($name) { }
public function remove_category($name)
{
}
/**
* Update/replace a category
*/
public function replace_category($oldname, $name, $color) { }
public function replace_category($oldname, $name, $color)
{
}
/**
* Fetch free/busy information from a person within the given range
@ -502,9 +508,12 @@ abstract class calendar_driver
// determine a reasonable end date if none given
if (!$end) {
switch ($event['recurrence']['FREQ']) {
case 'YEARLY': $intvl = 'P100Y'; break;
case 'MONTHLY': $intvl = 'P20Y'; break;
default: $intvl = 'P10Y'; break;
case 'YEARLY': $intvl = 'P100Y';
break;
case 'MONTHLY': $intvl = 'P20Y';
break;
default: $intvl = 'P10Y';
break;
}
$end = clone $event['start'];
@ -519,8 +528,7 @@ abstract class calendar_driver
$next_event['id'] = $next_event['uid'] . '-' . $next_event['_instance'];
$next_event['recurrence_id'] = $event['uid'];
$events[] = $next_event;
}
else if ($next_event['start'] > $end) { // stop loop if out of range
} elseif ($next_event['start'] > $end) { // stop loop if out of range
break;
}
@ -650,8 +658,8 @@ abstract class calendar_driver
}
// convert to DateTime for comparisons
$start = new DateTime('@'.$start);
$end = new DateTime('@'.$end);
$start = new DateTime('@' . $start);
$end = new DateTime('@' . $end);
// extract the current year
$year = $start->format('Y');
$year2 = $end->format('Y');
@ -762,7 +770,7 @@ abstract class calendar_driver
public function get_birthday_event($id)
{
// decode $id
list(, $source, $contact_id, $year) = explode(':', rcube_ldap::dn_decode($id));
[, $source, $contact_id, $year] = explode(':', rcube_ldap::dn_decode($id));
$rcmail = rcmail::get_instance();
@ -797,15 +805,16 @@ abstract class calendar_driver
try {
$bday = libcalendaring_datetime::createFromAny($contact['birthday'], true);
}
catch (Exception $e) {
rcube::raise_error([
} catch (Exception $e) {
rcube::raise_error(
[
'code' => 600,
'file' => __FILE__,
'line' => __LINE__,
'message' => 'Failed to parse contact birthday: ' . $e->getMessage()
'message' => 'Failed to parse contact birthday: ' . $e->getMessage(),
],
true, false
true,
false
);
return;
}

View file

@ -26,24 +26,24 @@
class database_driver extends calendar_driver
{
const DB_DATE_FORMAT = 'Y-m-d H:i:s';
public const DB_DATE_FORMAT = 'Y-m-d H:i:s';
public static $scheduling_properties = array('start', 'end', 'allday', 'recurrence', 'location', 'cancelled');
public static $scheduling_properties = ['start', 'end', 'allday', 'recurrence', 'location', 'cancelled'];
// features this backend supports
public $alarms = true;
public $attendees = true;
public $freebusy = false;
public $attachments = true;
public $alarm_types = array('DISPLAY');
public $alarm_types = ['DISPLAY'];
private $rc;
private $cal;
private $cache = array();
private $calendars = array();
private $cache = [];
private $calendars = [];
private $calendar_ids = '';
private $free_busy_map = array('free' => 0, 'busy' => 1, 'out-of-office' => 2, 'outofoffice' => 2, 'tentative' => 3);
private $sensitivity_map = array('public' => 0, 'private' => 1, 'confidential' => 2);
private $free_busy_map = ['free' => 0, 'busy' => 1, 'out-of-office' => 2, 'outofoffice' => 2, 'tentative' => 3];
private $sensitivity_map = ['public' => 0, 'private' => 1, 'confidential' => 2];
private $server_timezone;
private $db_events = 'events';
@ -77,7 +77,7 @@ class database_driver extends calendar_driver
$hidden = array_filter(explode(',', $this->rc->config->get('hidden_calendars', '')));
if (!empty($this->rc->user->ID)) {
$calendar_ids = array();
$calendar_ids = [];
$result = $this->rc->db->query(
"SELECT *, `calendar_id` AS id FROM `{$this->db_calendars}`"
. " WHERE `user_id` = ?"
@ -97,7 +97,7 @@ class database_driver extends calendar_driver
$calendar_ids[] = $this->rc->db->quote($arr['calendar_id']);
}
$this->calendar_ids = join(',', $calendar_ids);
$this->calendar_ids = implode(',', $calendar_ids);
}
}
@ -112,7 +112,7 @@ class database_driver extends calendar_driver
{
// attempt to create a default calendar for this user
if (empty($this->calendars)) {
if ($this->create_calendar(array('name' => 'Default', 'color' => 'cc0000', 'showalarms' => true))) {
if ($this->create_calendar(['name' => 'Default', 'color' => 'cc0000', 'showalarms' => true])) {
$this->_read_calendars();
}
}
@ -132,12 +132,12 @@ class database_driver extends calendar_driver
// append the virtual birthdays calendar
if ($this->rc->config->get('calendar_contact_birthdays', false)) {
$prefs = $this->rc->config->get('birthday_calendar', array('color' => '87CEFA'));
$prefs = $this->rc->config->get('birthday_calendar', ['color' => '87CEFA']);
$hidden = array_filter(explode(',', $this->rc->config->get('hidden_calendars', '')));
$id = self::BIRTHDAY_CALENDAR_ID;
if (!in_array($id, $hidden)) {
$calendars[$id] = array(
$calendars[$id] = [
'id' => $id,
'name' => $this->cal->gettext('birthdays'),
'listname' => $this->cal->gettext('birthdays'),
@ -148,7 +148,7 @@ class database_driver extends calendar_driver
'editable' => false,
'default' => false,
'children' => false,
);
];
}
}
@ -191,7 +191,7 @@ class database_driver extends calendar_driver
{
// birthday calendar properties are saved in user prefs
if ($prop['id'] == self::BIRTHDAY_CALENDAR_ID) {
$prefs['birthday_calendar'] = $this->rc->config->get('birthday_calendar', array('color' => '87CEFA'));
$prefs['birthday_calendar'] = $this->rc->config->get('birthday_calendar', ['color' => '87CEFA']);
if (isset($prop['color'])) {
$prefs['birthday_calendar']['color'] = $prop['color'];
}
@ -229,12 +229,11 @@ class database_driver extends calendar_driver
if ($prop['active']) {
unset($hidden[$prop['id']]);
}
else {
} else {
$hidden[$prop['id']] = 1;
}
return $this->rc->user->save_prefs(array('hidden_calendars' => join(',', array_keys($hidden))));
return $this->rc->user->save_prefs(['hidden_calendars' => implode(',', array_keys($hidden))]);
}
/**
@ -270,7 +269,7 @@ class database_driver extends calendar_driver
public function search_calendars($query, $source)
{
// not implemented
return array();
return [];
}
/**
@ -331,14 +330,14 @@ class database_driver extends calendar_driver
strval($event['title']),
isset($event['description']) ? strval($event['description']) : '',
isset($event['location']) ? strval($event['location']) : '',
isset($event['categories']) ? join(',', (array) $event['categories']) : '',
isset($event['categories']) ? implode(',', (array) $event['categories']) : '',
isset($event['url']) ? strval($event['url']) : '',
intval($event['free_busy']),
intval($event['priority']),
intval($event['sensitivity']),
isset($event['status']) ? strval($event['status']) : '',
$event['attendees'],
isset($event['alarms']) ? $event['alarms'] : null,
$event['alarms'] ?? null,
$event['notifyat']
);
@ -386,117 +385,118 @@ class database_driver extends calendar_driver
// modify a recurring event, check submitted savemode to do the right things
if ($old['recurrence'] || $old['recurrence_id']) {
$master = $old['recurrence_id'] ? $this->get_event(array('id' => $old['recurrence_id'])) : $old;
$master = $old['recurrence_id'] ? $this->get_event(['id' => $old['recurrence_id']]) : $old;
// keep saved exceptions (not submitted by the client)
if (!empty($old['recurrence']['EXDATE'])) {
$event['recurrence']['EXDATE'] = $old['recurrence']['EXDATE'];
}
$savemode = isset($event['_savemode']) ? $event['_savemode'] : null;
$savemode = $event['_savemode'] ?? null;
switch ($savemode) {
case 'new':
$event['uid'] = $this->cal->generate_uid();
return $this->new_event($event);
case 'new':
$event['uid'] = $this->cal->generate_uid();
return $this->new_event($event);
case 'current':
// save as exception
$event['isexception'] = 1;
$update_recurring = false;
case 'current':
// save as exception
$event['isexception'] = 1;
$update_recurring = false;
// set exception to first instance (= master)
if ($event['id'] == $master['id']) {
$event += $old;
$event['recurrence_id'] = $master['id'];
$event['_instance'] = libcalendaring::recurrence_instance_identifier($old, $master['allday']);
$event['isexception'] = 1;
$event_id = $this->_insert_event($event);
// set exception to first instance (= master)
if ($event['id'] == $master['id']) {
$event += $old;
$event['recurrence_id'] = $master['id'];
$event['_instance'] = libcalendaring::recurrence_instance_identifier($old, $master['allday']);
$event['isexception'] = 1;
$event_id = $this->_insert_event($event);
return $event_id;
}
break;
case 'future':
if ($master['id'] != $event['id']) {
// set until-date on master event, then save this instance as new recurring event
$master['recurrence']['UNTIL'] = clone $event['start'];
$master['recurrence']['UNTIL']->sub(new DateInterval('P1D'));
unset($master['recurrence']['COUNT']);
$update_master = true;
// if recurrence COUNT, update value to the correct number of future occurences
if ($event['recurrence']['COUNT']) {
$fromdate = clone $event['start'];
$fromdate->setTimezone($this->server_timezone);
$query = $this->rc->db->query(
"SELECT `event_id` FROM `{$this->db_events}`"
. " WHERE `calendar_id` IN ({$this->calendar_ids})"
. " AND `start` >= ? AND `recurrence_id` = ?",
$fromdate->format(self::DB_DATE_FORMAT),
$master['id']
);
if ($count = $this->rc->db->num_rows($query)) {
$event['recurrence']['COUNT'] = $count;
}
return $event_id;
}
$update_recurring = true;
$event['recurrence_id'] = 0;
$event['isexception'] = 0;
$event['_instance'] = '';
break;
}
// else: 'future' == 'all' if modifying the master event
default: // 'all' is default
$event['id'] = $master['id'];
$event['recurrence_id'] = 0;
case 'future':
if ($master['id'] != $event['id']) {
// set until-date on master event, then save this instance as new recurring event
$master['recurrence']['UNTIL'] = clone $event['start'];
$master['recurrence']['UNTIL']->sub(new DateInterval('P1D'));
unset($master['recurrence']['COUNT']);
$update_master = true;
// use start date from master but try to be smart on time or duration changes
$old_start_date = $old['start']->format('Y-m-d');
$old_start_time = $old['allday'] ? '' : $old['start']->format('H:i');
$old_duration = $old['end']->format('U') - $old['start']->format('U');
// if recurrence COUNT, update value to the correct number of future occurences
if ($event['recurrence']['COUNT']) {
$fromdate = clone $event['start'];
$fromdate->setTimezone($this->server_timezone);
$new_start_date = $event['start']->format('Y-m-d');
$new_start_time = $event['allday'] ? '' : $event['start']->format('H:i');
$new_duration = $event['end']->format('U') - $event['start']->format('U');
$query = $this->rc->db->query(
"SELECT `event_id` FROM `{$this->db_events}`"
. " WHERE `calendar_id` IN ({$this->calendar_ids})"
. " AND `start` >= ? AND `recurrence_id` = ?",
$fromdate->format(self::DB_DATE_FORMAT),
$master['id']
);
$diff = $old_start_date != $new_start_date || $old_start_time != $new_start_time || $old_duration != $new_duration;
$date_shift = $old['start']->diff($event['start']);
if ($count = $this->rc->db->num_rows($query)) {
$event['recurrence']['COUNT'] = $count;
}
}
// shifted or resized
if ($diff && ($old_start_date == $new_start_date || $old_duration == $new_duration)) {
$event['start'] = $master['start']->add($old['start']->diff($event['start']));
$event['end'] = clone $event['start'];
$event['end']->add(new DateInterval('PT'.$new_duration.'S'));
}
// dates did not change, use the ones from master
else if ($new_start_date . $new_start_time == $old_start_date . $old_start_time) {
$event['start'] = $master['start'];
$event['end'] = $master['end'];
}
$update_recurring = true;
$event['recurrence_id'] = 0;
$event['isexception'] = 0;
$event['_instance'] = '';
break;
}
// else: 'future' == 'all' if modifying the master event
// adjust recurrence-id when start changed and therefore the entire recurrence chain changes
if (is_array($event['recurrence'])
&& ($old_start_date != $new_start_date || $old_start_time != $new_start_time)
&& ($exceptions = $this->_load_exceptions($old))
) {
$recurrence_id_format = libcalendaring::recurrence_id_format($event);
// no break
default: // 'all' is default
$event['id'] = $master['id'];
$event['recurrence_id'] = 0;
foreach ($exceptions as $exception) {
$recurrence_id = rcube_utils::anytodatetime($exception['_instance'], $old['start']->getTimezone());
if (is_a($recurrence_id, 'DateTime')) {
$recurrence_id->add($date_shift);
$exception['_instance'] = $recurrence_id->format($recurrence_id_format);
$this->_update_event($exception, false);
// use start date from master but try to be smart on time or duration changes
$old_start_date = $old['start']->format('Y-m-d');
$old_start_time = $old['allday'] ? '' : $old['start']->format('H:i');
$old_duration = $old['end']->format('U') - $old['start']->format('U');
$new_start_date = $event['start']->format('Y-m-d');
$new_start_time = $event['allday'] ? '' : $event['start']->format('H:i');
$new_duration = $event['end']->format('U') - $event['start']->format('U');
$diff = $old_start_date != $new_start_date || $old_start_time != $new_start_time || $old_duration != $new_duration;
$date_shift = $old['start']->diff($event['start']);
// shifted or resized
if ($diff && ($old_start_date == $new_start_date || $old_duration == $new_duration)) {
$event['start'] = $master['start']->add($old['start']->diff($event['start']));
$event['end'] = clone $event['start'];
$event['end']->add(new DateInterval('PT' . $new_duration . 'S'));
}
// dates did not change, use the ones from master
elseif ($new_start_date . $new_start_time == $old_start_date . $old_start_time) {
$event['start'] = $master['start'];
$event['end'] = $master['end'];
}
// adjust recurrence-id when start changed and therefore the entire recurrence chain changes
if (is_array($event['recurrence'])
&& ($old_start_date != $new_start_date || $old_start_time != $new_start_time)
&& ($exceptions = $this->_load_exceptions($old))
) {
$recurrence_id_format = libcalendaring::recurrence_id_format($event);
foreach ($exceptions as $exception) {
$recurrence_id = rcube_utils::anytodatetime($exception['_instance'], $old['start']->getTimezone());
if (is_a($recurrence_id, 'DateTime')) {
$recurrence_id->add($date_shift);
$exception['_instance'] = $recurrence_id->format($recurrence_id_format);
$this->_update_event($exception, false);
}
}
}
}
$ret = $event['id']; // return master ID
break;
$ret = $event['id']; // return master ID
break;
}
}
@ -527,17 +527,16 @@ class database_driver extends calendar_driver
// apply changes to master (and all exceptions)
if ($event['_savemode'] == 'all' && $event['recurrence_id']) {
$update_event = $this->get_event(array('id' => $event['recurrence_id']));
$update_event = $this->get_event(['id' => $event['recurrence_id']]);
$update_event['_savemode'] = $event['_savemode'];
calendar::merge_attendee_data($update_event, $attendees);
}
if ($ret = $this->update_attendees($update_event, $attendees)) {
// replace $event with effectively updated event (for iTip reply)
if ($ret !== true && $ret != $update_event['id'] && ($new_event = $this->get_event(array('id' => $ret)))) {
if ($ret !== true && $ret != $update_event['id'] && ($new_event = $this->get_event(['id' => $ret]))) {
$event = $new_event;
}
else {
} else {
$event = $update_event;
}
}
@ -583,8 +582,8 @@ class database_driver extends calendar_driver
// iterate through the list of properties considered 'significant' for scheduling
foreach (self::$scheduling_properties as $prop) {
$a = isset($old[$prop]) ? $old[$prop] : null;
$b = isset($event[$prop]) ? $event[$prop] : null;
$a = $old[$prop] ?? null;
$b = $event[$prop] ?? null;
if (!empty($event['allday']) && ($prop == 'start' || $prop == 'end')
&& $a instanceof DateTimeInterface
@ -602,8 +601,7 @@ class database_driver extends calendar_driver
// advanced rrule comparison: no rescheduling if series was shortened
if (!empty($a['COUNT']) && !empty($b['COUNT']) && $b['COUNT'] < $a['COUNT']) {
unset($a['COUNT'], $b['COUNT']);
}
else if (!empty($a['UNTIL']) && !empty($b['UNTIL']) && $b['UNTIL'] < $a['UNTIL']) {
} elseif (!empty($a['UNTIL']) && !empty($b['UNTIL']) && $b['UNTIL'] < $a['UNTIL']) {
unset($a['UNTIL'], $b['UNTIL']);
}
}
@ -623,8 +621,7 @@ class database_driver extends calendar_driver
foreach ($attendees as $i => $attendee) {
if ($attendee['role'] == 'ORGANIZER' && $attendee['email'] && in_array(strtolower($attendee['email']), $emails)) {
$is_organizer = true;
}
else if ($attendee['role'] != 'ORGANIZER'
} elseif ($attendee['role'] != 'ORGANIZER'
&& $attendee['role'] != 'NON-PARTICIPANT'
&& $attendee['status'] != 'DELEGATED'
) {
@ -662,8 +659,8 @@ class database_driver extends calendar_driver
$free_busy = isset($event['free_busy']) ? strtolower($event['free_busy']) : '';
$event['_recurrence'] = rtrim($rrule, ';');
$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] : 0;
$event['free_busy'] = $this->free_busy_map[$free_busy] ?? null;
$event['sensitivity'] = $this->sensitivity_map[$sensitivity] ?? 0;
$event['all_day'] = !empty($event['allday']) ? 1 : 0;
if ($event['free_busy'] == 'tentative') {
@ -680,8 +677,7 @@ class database_driver extends calendar_driver
// process event attendees
if (!empty($event['attendees'])) {
$event['attendees'] = json_encode((array)$event['attendees']);
}
else {
} else {
$event['attendees'] = '';
}
@ -711,18 +707,17 @@ class database_driver extends calendar_driver
private function _update_event($event, $update_recurring = true)
{
$event = $this->_save_preprocess($event);
$sql_args = array();
$set_cols = array('start', 'end', 'all_day', 'recurrence_id', 'isexception', 'sequence',
$sql_args = [];
$set_cols = ['start', 'end', 'all_day', 'recurrence_id', 'isexception', 'sequence',
'title', 'description', 'location', 'categories', 'url', 'free_busy', 'priority',
'sensitivity', 'status', 'attendees', 'alarms', 'notifyat'
);
'sensitivity', 'status', 'attendees', 'alarms', 'notifyat',
];
foreach ($set_cols as $col) {
if (!empty($event[$col]) && is_a($event[$col], 'DateTime')) {
$sql_args[$col] = $event[$col]->format(self::DB_DATE_FORMAT);
}
else if (array_key_exists($col, $event)) {
$sql_args[$col] = is_array($event[$col]) ? join(',', $event[$col]) : $event[$col];
} elseif (array_key_exists($col, $event)) {
$sql_args[$col] = is_array($event[$col]) ? implode(',', $event[$col]) : $event[$col];
}
}
@ -790,7 +785,7 @@ class database_driver extends calendar_driver
}
if (!empty($event['recurrence'])) {
$exdata = array();
$exdata = [];
$exceptions = $this->_load_exceptions($event);
foreach ($exceptions as $exception) {
@ -828,12 +823,12 @@ class database_driver extends calendar_driver
$next_end = clone $next_start;
$next_end->add($duration);
$notify_at = $this->_get_notification(array(
$notify_at = $this->_get_notification([
'alarms' => !empty($event['alarms']) ? $event['alarms'] : null,
'start' => $next_start,
'end' => $next_end,
'status' => $event['status']
));
'status' => $event['status'],
]);
$now = $this->rc->db->now();
$query = $this->rc->db->query(
@ -895,7 +890,7 @@ class database_driver extends calendar_driver
$instance_id
);
$exceptions = array();
$exceptions = [];
while (($sql_arr = $this->rc->db->fetch_assoc($result)) && $sql_arr['event_id']) {
$exception = $this->_read_postprocess($sql_arr);
$instance = $exception['_instance'] ?: $exception['start']->format($exception['allday'] ? 'Ymd' : 'Ymd\THis');
@ -948,56 +943,57 @@ class database_driver extends calendar_driver
// read master if deleting a recurring event
if ($event['recurrence'] || $event['recurrence_id']) {
$master = $event['recurrence_id'] ? $this->get_event(array('id' => $event['recurrence_id'])) : $event;
$master = $event['recurrence_id'] ? $this->get_event(['id' => $event['recurrence_id']]) : $event;
$savemode = $event['_savemode'];
}
switch ($savemode) {
case 'current':
// add exception to master event
$master['recurrence']['EXDATE'][] = $event['start'];
$update_master = true;
// just delete this single occurence
$query = $this->rc->db->query(
"DELETE FROM `{$this->db_events}`"
. " WHERE `calendar_id` IN ({$this->calendar_ids}) AND `event_id` = ?",
$event['id']
);
break;
case 'future':
if ($master['id'] != $event['id']) {
// set until-date on master event
$master['recurrence']['UNTIL'] = clone $event['start'];
$master['recurrence']['UNTIL']->sub(new DateInterval('P1D'));
unset($master['recurrence']['COUNT']);
case 'current':
// add exception to master event
$master['recurrence']['EXDATE'][] = $event['start'];
$update_master = true;
// delete this and all future instances
$fromdate = clone $event['start'];
$fromdate->setTimezone($this->server_timezone);
// just delete this single occurence
$query = $this->rc->db->query(
"DELETE FROM `{$this->db_events}`"
. " WHERE `calendar_id` IN ({$this->calendar_ids}) AND `start` >= ? AND `recurrence_id` = ?",
$fromdate->format(self::DB_DATE_FORMAT),
. " WHERE `calendar_id` IN ({$this->calendar_ids}) AND `event_id` = ?",
$event['id']
);
break;
case 'future':
if ($master['id'] != $event['id']) {
// set until-date on master event
$master['recurrence']['UNTIL'] = clone $event['start'];
$master['recurrence']['UNTIL']->sub(new DateInterval('P1D'));
unset($master['recurrence']['COUNT']);
$update_master = true;
// delete this and all future instances
$fromdate = clone $event['start'];
$fromdate->setTimezone($this->server_timezone);
$query = $this->rc->db->query(
"DELETE FROM `{$this->db_events}`"
. " WHERE `calendar_id` IN ({$this->calendar_ids}) AND `start` >= ? AND `recurrence_id` = ?",
$fromdate->format(self::DB_DATE_FORMAT),
$master['id']
);
$ret = $master['id'];
break;
}
// else: future == all if modifying the master event
// no break
default: // 'all' is default
$query = $this->rc->db->query(
"DELETE FROM `{$this->db_events}`"
. " WHERE (`event_id` = ? OR `recurrence_id` = ?) AND `calendar_id` IN ({$this->calendar_ids})",
$master['id'],
$master['id']
);
$ret = $master['id'];
break;
}
// else: future == all if modifying the master event
default: // 'all' is default
$query = $this->rc->db->query(
"DELETE FROM `{$this->db_events}`"
. " WHERE (`event_id` = ? OR `recurrence_id` = ?) AND `calendar_id` IN ({$this->calendar_ids})",
$master['id'],
$master['id']
);
break;
}
$success = $this->rc->db->affected_rows($query);
@ -1048,9 +1044,8 @@ class database_driver extends calendar_driver
$calendars[] = $idx;
}
}
$cals = join(',', $calendars);
}
else {
$cals = implode(',', $calendars);
} else {
$cals = $this->calendar_ids;
}
@ -1087,22 +1082,21 @@ class database_driver extends calendar_driver
{
if (empty($calendars)) {
$calendars = array_keys($this->calendars);
}
else if (!is_array($calendars)) {
} elseif (!is_array($calendars)) {
$calendars = explode(',', strval($calendars));
}
// only allow to select from calendars of this use
$calendar_ids = array_map(array($this->rc->db, 'quote'), array_intersect($calendars, array_keys($this->calendars)));
$calendar_ids = array_map([$this->rc->db, 'quote'], array_intersect($calendars, array_keys($this->calendars)));
// compose (slow) SQL query for searching
// FIXME: improve searching using a dedicated col and normalized values
$sql_add = '';
if ($query) {
foreach (array('title','location','description','categories','attendees') as $col) {
$sql_query[] = $this->rc->db->ilike($col, '%'.$query.'%');
foreach (['title','location','description','categories','attendees'] as $col) {
$sql_query[] = $this->rc->db->ilike($col, '%' . $query . '%');
}
$sql_add .= " AND (" . join(' OR ', $sql_query) . ")";
$sql_add .= " AND (" . implode(' OR ', $sql_query) . ")";
}
if (!$virtual) {
@ -1113,13 +1107,13 @@ class database_driver extends calendar_driver
$sql_add .= " AND e.changed >= " . $this->rc->db->quote(date('Y-m-d H:i:s', $modifiedsince));
}
$events = array();
$events = [];
if (!empty($calendar_ids)) {
$result = $this->rc->db->query(
"SELECT e.*, (SELECT COUNT(`attachment_id`) FROM `{$this->db_attachments}`"
. " WHERE `event_id` = e.event_id OR `event_id` = e.recurrence_id) AS _attachments"
. " FROM `{$this->db_events}` e"
. " WHERE e.calendar_id IN (" . join(',', $calendar_ids) . ")"
. " WHERE e.calendar_id IN (" . implode(',', $calendar_ids) . ")"
. " AND e.start <= " . $this->rc->db->fromunixtime($end)
. " AND e.end >= " . $this->rc->db->fromunixtime($start)
. $sql_add
@ -1172,7 +1166,7 @@ class database_driver extends calendar_driver
public function count_events($calendars, $start, $end = null)
{
// not implemented
return array();
return [];
}
/**
@ -1197,18 +1191,15 @@ class database_driver extends calendar_driver
// parse recurrence rule
if ($event['recurrence'] && preg_match_all('/([A-Z]+)=([^;]+);?/', $event['recurrence'], $m, PREG_SET_ORDER)) {
$event['recurrence'] = array();
$event['recurrence'] = [];
foreach ($m as $rr) {
if (is_numeric($rr[2])) {
$rr[2] = intval($rr[2]);
}
else if ($rr[1] == 'UNTIL') {
} elseif ($rr[1] == 'UNTIL') {
$rr[2] = date_create($rr[2]);
}
else if ($rr[1] == 'RDATE') {
} elseif ($rr[1] == 'RDATE') {
$rr[2] = array_map('date_create', explode(',', $rr[2]));
}
else if ($rr[1] == 'EXDATE') {
} elseif ($rr[1] == 'EXDATE') {
$rr[2] = array_map('date_create', explode(',', $rr[2]));
}
@ -1235,9 +1226,8 @@ class database_driver extends calendar_driver
// decode serialized event attendees
if (strlen($event['attendees'])) {
$event['attendees'] = $this->unserialize_attendees($event['attendees']);
}
else {
$event['attendees'] = array();
} else {
$event['attendees'] = [];
}
// decode serialized alarms
@ -1259,27 +1249,26 @@ class database_driver extends calendar_driver
{
if (empty($calendars)) {
$calendars = array_keys($this->calendars);
}
else if (!is_array($calendars)) {
} elseif (!is_array($calendars)) {
$calendars = explode(',', (array) $calendars);
}
// only allow to select from calendars with activated alarms
$calendar_ids = array();
$calendar_ids = [];
foreach ($calendars as $cid) {
if ($this->calendars[$cid] && $this->calendars[$cid]['showalarms']) {
$calendar_ids[] = $cid;
}
}
$calendar_ids = array_map(array($this->rc->db, 'quote'), $calendar_ids);
$alarms = array();
$calendar_ids = array_map([$this->rc->db, 'quote'], $calendar_ids);
$alarms = [];
if (!empty($calendar_ids)) {
$stime = $this->rc->db->fromunixtime($time);
$result = $this->rc->db->query(
"SELECT * FROM `{$this->db_events}`"
. " WHERE `calendar_id` IN (" . join(',', $calendar_ids) . ")"
. " WHERE `calendar_id` IN (" . implode(',', $calendar_ids) . ")"
. " AND `notifyat` <= $stime AND `end` > $stime"
);
@ -1319,11 +1308,9 @@ class database_driver extends calendar_driver
{
if (isset($attachment['data'])) {
$data = $attachment['data'];
}
else if (!empty($attachment['path'])) {
} elseif (!empty($attachment['path'])) {
$data = file_get_contents($attachment['path']);
}
else {
} else {
return false;
}
@ -1363,7 +1350,7 @@ class database_driver extends calendar_driver
*/
public function list_attachments($event)
{
$attachments = array();
$attachments = [];
if (!empty($this->calendar_ids)) {
$result = $this->rc->db->query(
@ -1486,18 +1473,17 @@ class database_driver extends calendar_driver
if ($alarm['trigger'][0] == '@') {
try {
$valarms[$i]['trigger'] = new DateTime(substr($alarm['trigger'], 1));
}
catch (Exception $e) {
} catch (Exception $e) {
unset($valarms[$i]);
}
}
}
}
// convert legacy alarms data
else if (strlen($alarms)) {
list($trigger, $action) = explode(':', $alarms, 2);
elseif (strlen($alarms)) {
[$trigger, $action] = explode(':', $alarms, 2);
if ($trigger = libcalendaring::parse_alarm_value($trigger)) {
$valarms = array(array('action' => $action, 'trigger' => $trigger[3] ?: $trigger[0]));
$valarms = [['action' => $action, 'trigger' => $trigger[3] ?: $trigger[0]]];
}
}
@ -1509,7 +1495,7 @@ class database_driver extends calendar_driver
*/
private function unserialize_attendees($s_attendees)
{
$attendees = array();
$attendees = [];
// decode json serialized string
if ($s_attendees[0] == '[') {
@ -1518,9 +1504,9 @@ class database_driver extends calendar_driver
// decode the old serialization format
else {
foreach (explode("\n", $s_attendees) as $line) {
$att = array();
$att = [];
foreach (rcube_utils::explode_quoted_string(';', $line) as $prop) {
list($key, $value) = explode("=", $prop);
[$key, $value] = explode("=", $prop);
$att[strtolower($key)] = stripslashes(trim($value, '""'));
}
$attendees[] = $att;

View file

@ -90,13 +90,13 @@ class kolab_calendar extends kolab_storage_folder_api
$this->editable = true;
$this->rights = 'lrswikxteav';
$this->alarms = true;
}
else {
} 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');;
$this->editable = strpos($rights, 'i');
;
}
}
}
@ -105,8 +105,7 @@ class kolab_calendar extends kolab_storage_folder_api
$prefs = $this->cal->rc->config->get('kolab_calendars', []);
if (isset($prefs[$this->id]['showalarms'])) {
$this->alarms = $prefs[$this->id]['showalarms'];
}
else if (isset($prefs[$old_id]['showalarms'])) {
} elseif (isset($prefs[$old_id]['showalarms'])) {
$this->alarms = $prefs[$old_id]['showalarms'];
}
}
@ -216,10 +215,9 @@ class kolab_calendar extends kolab_storage_folder_api
$this->events[$id] = $this->_to_driver_event($instance, false, true, $master);
}
// check for match on the first instance already
else if (!empty($master['_instance']) && $master['_instance'] == $instance_id) {
elseif (!empty($master['_instance']) && $master['_instance'] == $instance_id) {
$this->events[$id] = $master;
}
else if (!empty($master['recurrence'])) {
} elseif (!empty($master['recurrence'])) {
$start_date = $master['start'];
// For performance reasons we'll get only the specific instance
if (($date = substr($id, strlen($master_id) + 1, 8)) && strlen($date) == 8 && is_numeric($date)) {
@ -274,14 +272,12 @@ class kolab_calendar extends kolab_storage_folder_api
// to workaround possible timezone differences
try {
$start = new DateTime('@' . ($start - 12 * 3600));
}
catch (Exception $e) {
} catch (Exception $e) {
$start = new DateTime('@0');
}
try {
$end = new DateTime('@' . ($end + 12 * 3600));
}
catch (Exception $e) {
} catch (Exception $e) {
$end = new DateTime('today +10 years');
}
@ -373,7 +369,7 @@ class kolab_calendar extends kolab_storage_folder_api
$events = array_merge($events, $this->get_recurring_events($record, $start, $end));
}
// add top-level exceptions (aka loose single occurrences)
else if (!empty($record['exceptions'])) {
elseif (!empty($record['exceptions'])) {
foreach ($record['exceptions'] as $ex) {
$component = $this->_to_driver_event($ex, false, false, $record);
if ($component['start'] <= $end && $component['end'] >= $start) {
@ -385,7 +381,7 @@ class kolab_calendar extends kolab_storage_folder_api
// post-filter all events by fulltext search and partstat values
$me = $this;
$events = array_filter($events, function($event) use ($words, $partstat_exclude, $user_emails, $me) {
$events = array_filter($events, function ($event) use ($words, $partstat_exclude, $user_emails, $me) {
// fulltext search
if (count($words)) {
$hits = 0;
@ -435,16 +431,14 @@ class kolab_calendar extends kolab_storage_folder_api
{
// convert to DateTime for comparisons
try {
$start = new DateTime('@'.$start);
}
catch (Exception $e) {
$start = new DateTime('@' . $start);
} catch (Exception $e) {
$start = new DateTime('@0');
}
if ($end) {
try {
$end = new DateTime('@'.$end);
}
catch (Exception $e) {
$end = new DateTime('@' . $end);
} catch (Exception $e) {
$end = null;
}
}
@ -462,8 +456,7 @@ class kolab_calendar extends kolab_storage_folder_api
$query[] = ['tags', '!=', 'x-partstat:' . $email . ':needs-action'];
$query[] = ['tags', '!=', 'x-partstat:' . $email . ':declined'];
}
}
else if (is_array($filter_query)) {
} elseif (is_array($filter_query)) {
$query = array_merge($query, $filter_query);
}
@ -493,15 +486,16 @@ class kolab_calendar extends kolab_storage_folder_api
$saved = $this->storage->save($object, 'event');
if (!$saved) {
rcube::raise_error([
rcube::raise_error(
[
'code' => 600, 'file' => __FILE__, 'line' => __LINE__,
'message' => "Error saving event object to Kolab server"
'message' => "Error saving event object to Kolab server",
],
true, false
true,
false
);
$saved = false;
}
else {
} else {
// save links in configuration.relation object
if ($this->save_links($event['uid'], $links)) {
$object['links'] = $links;
@ -542,14 +536,15 @@ class kolab_calendar extends kolab_storage_folder_api
$saved = $this->storage->save($object, 'event', $old['uid']);
if (!$saved) {
rcube::raise_error([
rcube::raise_error(
[
'code' => 600, 'file' => __FILE__, 'line' => __LINE__,
'message' => "Error saving event object to Kolab server"
'message' => "Error saving event object to Kolab server",
],
true, false
true,
false
);
}
else {
} else {
// save links in configuration.relation object
if ($this->save_links($event['uid'], $links)) {
$object['links'] = $links;
@ -579,11 +574,13 @@ class kolab_calendar extends kolab_storage_folder_api
$deleted = $this->storage->delete(!empty($event['uid']) ? $event['uid'] : $event['id'], $force);
if (!$deleted) {
rcube::raise_error([
rcube::raise_error(
[
'code' => 600, 'file' => __FILE__, 'line' => __LINE__,
'message' => sprintf("Error deleting event object '%s' from Kolab server", $event['id'])
'message' => sprintf("Error deleting event object '%s' from Kolab server", $event['id']),
],
true, false
true,
false
);
}
@ -606,11 +603,13 @@ class kolab_calendar extends kolab_storage_folder_api
return true;
}
rcube::raise_error([
rcube::raise_error(
[
'code' => 600, 'file' => __FILE__, 'line' => __LINE__,
'message' => sprintf("Error undeleting the event object '%s' from the Kolab server", $event['id'])
'message' => sprintf("Error undeleting the event object '%s' from the Kolab server", $event['id']),
],
true, false
true,
false
);
return false;
@ -650,8 +649,7 @@ class kolab_calendar extends kolab_storage_folder_api
if (empty($event['_formatobj'])) {
$rec = $this->storage->get_object(!empty($event['uid']) ? $event['uid'] : $event['id']);
$object = $rec['_formatobj'];
}
else {
} else {
$object = $event['_formatobj'];
}
@ -778,8 +776,7 @@ class kolab_calendar extends kolab_storage_folder_api
if ($limit && count($events) >= $limit) {
return $events;
}
}
else if ($next_event['start'] > $end) {
} elseif ($next_event['start'] > $end) {
// stop loop if out of range
break;
}
@ -825,14 +822,13 @@ class kolab_calendar extends kolab_storage_folder_api
$recurrence_id_format = libcalendaring::recurrence_id_format($master_event ? $master_event : $record);
if (!$noinst && !empty($record['recurrence']) && empty($record['recurrence_id']) && empty($record['_instance'])) {
$record['_instance'] = $record['start']->format($recurrence_id_format);
}
else if (isset($record['recurrence_date']) && $record['recurrence_date'] instanceof DateTimeInterface) {
} elseif (isset($record['recurrence_date']) && $record['recurrence_date'] instanceof DateTimeInterface) {
$record['_instance'] = $record['recurrence_date']->format($recurrence_id_format);
}
// clean up exception data
if (!empty($record['recurrence']) && !empty($record['recurrence']['EXCEPTIONS'])) {
array_walk($record['recurrence']['EXCEPTIONS'], function(&$exception) {
array_walk($record['recurrence']['EXCEPTIONS'], function (&$exception) {
unset($exception['_mailbox'], $exception['_msguid'], $exception['_formatobj'], $exception['_attachments']);
});
}
@ -883,7 +879,7 @@ class kolab_calendar extends kolab_storage_folder_api
}
// remove some internal properties which should not be cached
$cleanup_fn = function(&$event) {
$cleanup_fn = function (&$event) {
unset($event['_savemode'], $event['_fromcalendar'], $event['_identity'], $event['_folder_id'],
$event['calendar'], $event['className'], $event['recurrence_id'],
$event['attachments'], $event['deleted_attachments']);
@ -893,7 +889,7 @@ class kolab_calendar extends kolab_storage_folder_api
// clean up exception data
if (!empty($event['exceptions'])) {
array_walk($event['exceptions'], function(&$exception) use ($cleanup_fn) {
array_walk($event['exceptions'], function (&$exception) use ($cleanup_fn) {
unset($exception['_mailbox'], $exception['_msguid'], $exception['_formatobj']);
$cleanup_fn($exception);
});
@ -948,13 +944,11 @@ class kolab_calendar extends kolab_storage_folder_api
foreach ($prop as $key => $val) {
if (is_numeric($key) || is_array($val)) {
$out .= self::_complex2string($val);
}
else if (!in_array($key, $ignorekeys)) {
} elseif (!in_array($key, $ignorekeys)) {
$out .= $val . ' ';
}
}
}
else if (is_string($prop) || is_numeric($prop)) {
} elseif (is_string($prop) || is_numeric($prop)) {
$out .= $prop . ' ';
}

File diff suppressed because it is too large Load diff

View file

@ -45,19 +45,19 @@ class kolab_invitation_calendar
$this->id = $id;
switch ($this->id) {
case kolab_driver::INVITATIONS_CALENDAR_PENDING:
$this->partstats = ['NEEDS-ACTION'];
$this->name = $this->cal->gettext('invitationspending');
case kolab_driver::INVITATIONS_CALENDAR_PENDING:
$this->partstats = ['NEEDS-ACTION'];
$this->name = $this->cal->gettext('invitationspending');
if (!empty($_REQUEST['_quickview'])) {
$this->partstats[] = 'TENTATIVE';
}
break;
if (!empty($_REQUEST['_quickview'])) {
$this->partstats[] = 'TENTATIVE';
}
break;
case kolab_driver::INVITATIONS_CALENDAR_DECLINED:
$this->partstats = ['DECLINED'];
$this->name = $this->cal->gettext('invitationsdeclined');
break;
case kolab_driver::INVITATIONS_CALENDAR_DECLINED:
$this->partstats = ['DECLINED'];
$this->name = $this->cal->gettext('invitationsdeclined');
break;
}
// user-specific alarms settings win
@ -213,8 +213,7 @@ class kolab_invitation_calendar
// find the actual folder this event resides in
if (!empty($event['_folder_id'])) {
$cal = $this->cal->driver->get_calendar($event['_folder_id']);
}
else {
} else {
$cal = null;
foreach (kolab_storage::list_folders('', '*', 'event', null) as $foldername) {
$cal = $this->_get_calendar($foldername);
@ -313,7 +312,7 @@ class kolab_invitation_calendar
$filter = [
['tags', '!=', 'x-status:cancelled'],
[$subquery, 'OR']
[$subquery, 'OR'],
];
// aggregate counts from all calendar folders

View file

@ -45,12 +45,10 @@ class kolab_user_calendar extends kolab_calendar
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) {
} elseif ($user_or_folder instanceof kolab_storage_folder_user) {
$this->storage = $user_or_folder;
$this->userdata = $this->storage->ldaprec;
}
else {
} else {
// get user record from LDAP
$this->storage = new kolab_storage_folder_user($user_or_folder);
$this->userdata = $this->storage->ldaprec;
@ -187,7 +185,7 @@ class kolab_user_calendar extends kolab_calendar
public function get_event($id)
{
// TODO: implement this
return isset($this->events[$id]) ? $this->events[$id] : null;
return $this->events[$id] ?? null;
}
/**
@ -221,15 +219,13 @@ class kolab_user_calendar extends kolab_calendar
{
// convert to DateTime for comparisons
try {
$start_dt = new DateTime('@'.$start);
}
catch (Exception $e) {
$start_dt = new DateTime('@' . $start);
} catch (Exception $e) {
$start_dt = new DateTime('@0');
}
try {
$end_dt = new DateTime('@'.$end);
}
catch (Exception $e) {
$end_dt = new DateTime('@' . $end);
} catch (Exception $e) {
$end_dt = new DateTime('today +10 years');
}
@ -238,8 +234,10 @@ class kolab_user_calendar extends kolab_calendar
if (!empty($query)) {
foreach ($query as $q) {
if ($q[0] == 'changed' && $q[1] == '>=') {
try { $limit_changed = new DateTime('@'.$q[2]); }
catch (Exception $e) { /* ignore */ }
try {
$limit_changed = new DateTime('@' . $q[2]);
} catch (Exception $e) { /* ignore */
}
}
}
}
@ -318,13 +316,14 @@ class kolab_user_calendar extends kolab_calendar
}
unset($request, $response);
}
catch (Exception $e) {
rcube::raise_error([
} catch (Exception $e) {
rcube::raise_error(
[
'code' => 900, 'file' => __FILE__, 'line' => __LINE__,
'message' => "Error fetching free/busy information: " . $e->getMessage()
'message' => "Error fetching free/busy information: " . $e->getMessage(),
],
true, false
true,
false
);
return false;
@ -360,7 +359,7 @@ class kolab_user_calendar extends kolab_calendar
}
foreach ($fb['periods'] as $tuple) {
list($from, $to, $type) = $tuple;
[$from, $to, $type] = $tuple;
$event = [
'uid' => md5($this->id . $from->format('U') . '/' . $to->format('U')),
'calendar' => $this->id,
@ -372,7 +371,7 @@ class kolab_user_calendar extends kolab_calendar
'className' => 'fc-type-freebusy',
'organizer' => [
'email' => $this->userdata['mail'],
'name' => isset($this->userdata['displayname']) ? $this->userdata['displayname'] : null,
'name' => $this->userdata['displayname'] ?? null,
],
];

View file

@ -32,7 +32,7 @@ class resources_driver_ldap extends resources_driver
/**
* Default constructor
*/
function __construct($cal)
public function __construct($cal)
{
$this->cal = $cal;
$this->rc = $cal->rc;
@ -59,8 +59,7 @@ class resources_driver_ldap extends resources_driver
if (isset($query)) {
$mode = $searchField == 'owner' ? rcube_addressbook::SEARCH_STRICT : 0;
$results = $ldap->search($searchField, $query, $mode, true, true);
}
else {
} else {
$results = $ldap->list_records();
}
@ -130,8 +129,7 @@ class resources_driver_ldap extends resources_driver
if (!empty($sattr) && $sattr[0] === '{') {
$attr = @json_decode($sattr, true);
$attributes += $attr;
}
else if (!empty($sattr) && empty($rec['description'])) {
} elseif (!empty($sattr) && empty($rec['description'])) {
$rec['description'] = $sattr;
}
}

View file

@ -31,7 +31,7 @@ abstract class resources_driver
/**
* Default constructor
*/
function __construct($cal)
public function __construct($cal)
{
$this->cal = $cal;
}
@ -94,7 +94,7 @@ abstract class resources_driver
$fblist = $this->cal->driver->get_freebusy_list($rec['email'], $start, $end);
if (is_array($fblist)) {
foreach ($fblist as $slot) {
list($from, $to, $type) = $slot;
[$from, $to, $type] = $slot;
if ($type == calendar::FREEBUSY_FREE || $type == calendar::FREEBUSY_UNKNOWN) {
continue;
}

View file

@ -31,7 +31,7 @@ class calendar_itip extends libcalendaring_itip
/**
* Constructor to set text domain to calendar
*/
function __construct($plugin, $domain = 'calendar')
public function __construct($plugin, $domain = 'calendar')
{
parent::__construct($plugin, $domain);
@ -93,8 +93,7 @@ class calendar_itip extends libcalendaring_itip
foreach ($invitation['event']['attendees'] as $i => $attendee) {
if ($attendee['role'] == 'ORGANIZER') {
$organizer = $attendee;
}
else if ($attendee['email'] == $email) {
} elseif ($attendee['email'] == $email) {
// nothing to be done here
if ($attendee['status'] == $newstatus) {
return true;
@ -114,11 +113,10 @@ class calendar_itip extends libcalendaring_itip
$mailto = !empty($organizer['name']) ? $organizer['name'] : $organizer['email'];
$message = $this->plugin->gettext([
'name' => 'sentresponseto',
'vars' => ['mailto' => $mailto]
'vars' => ['mailto' => $mailto],
]);
$this->rc->output->command('display_message', $message, 'confirmation');
}
else {
} else {
$this->rc->output->command('display_message', $this->plugin->gettext('itipresponseerror'), 'error');
}
}
@ -200,8 +198,8 @@ class calendar_itip extends libcalendaring_itip
$this->rc->db->query(
"UPDATE $this->db_itipinvitations SET `cancelled` = 1"
. " WHERE `event_uid` = ? AND `user_id` = ?",
$event_uid,
$this->rc->user->ID
$event_uid,
$this->rc->user->ID
);
}
@ -230,7 +228,7 @@ class calendar_itip extends libcalendaring_itip
*/
public function decode_token($token)
{
list($base, $mail, $hash) = explode('.', $token);
[$base, $mail, $hash] = explode('.', $token);
// validate and return parts
if ($mail && $hash && $hash == substr(md5($base . $mail . $this->rc->config->get('des_key')), 0, 6)) {

View file

@ -22,13 +22,12 @@
*/
class calendar_nextcloud_api
{
const PARTICIPANT_OWNER = 1;
const PARTICIPANT_MODERATOR = 2;
const PARTICIPANT_USER = 3;
const PARTICIPANT_GUEST = 4;
const PARTICIPANT_PUBLIC = 5;
const PARTICIPANT_GUEST_MODERATOR = 6;
public const PARTICIPANT_OWNER = 1;
public const PARTICIPANT_MODERATOR = 2;
public const PARTICIPANT_USER = 3;
public const PARTICIPANT_GUEST = 4;
public const PARTICIPANT_PUBLIC = 5;
public const PARTICIPANT_GUEST_MODERATOR = 6;
/**
@ -66,8 +65,7 @@ class calendar_nextcloud_api
if (!empty($params)) {
if ($method == 'POST') {
$request->addPostParameter($params);
}
else {
} else {
$request->setUrl($url . '?' . http_build_query($params));
}
}
@ -91,14 +89,12 @@ class calendar_nextcloud_api
$doc->loadXML($body);
$code = $doc->getElementsByTagName('statuscode')->item(0)->textContent;
$msg = $doc->getElementsByTagName('message')->item(0)->textContent;
}
else {
} else {
$msg = 'Unknown error';
}
throw new Exception("Nextcloud API Error: [$code] $msg");
}
catch (Exception $e) {
} catch (Exception $e) {
rcube::raise_error($e, true, false);
}

View file

@ -34,7 +34,7 @@ class calendar_ui
public $calendar;
function __construct($cal)
public function __construct($cal)
{
$this->cal = $cal;
$this->rc = $cal->rc;
@ -52,13 +52,14 @@ class calendar_ui
}
// add taskbar button
$this->cal->add_button([
$this->cal->add_button(
[
'command' => 'calendar',
'class' => 'button-calendar',
'classsel' => 'button-calendar button-selected',
'innerclass' => 'button-inner',
'label' => 'calendar.calendar',
'type' => 'link'
'type' => 'link',
],
'taskbar'
);
@ -115,7 +116,7 @@ class calendar_ui
public function addCSS()
{
$skin_path = $this->cal->local_skin_path();
if (
$this->rc->task == 'calendar'
&& (!$this->rc->action || in_array($this->rc->action, ['index', 'print']))
@ -141,8 +142,7 @@ class calendar_ui
if ($this->rc->task == 'calendar' && $this->rc->action == 'print') {
$this->cal->include_script('print.js');
}
else {
} else {
$this->rc->output->include_script('treelist.js');
$this->cal->api->include_script('libkolab/libkolab.js');
$this->cal->include_script('calendar_ui.js');
@ -153,7 +153,7 @@ class calendar_ui
/**
* Add custom style for the calendar UI
*/
function calendar_css($attrib = [])
public function calendar_css($attrib = [])
{
$categories = $this->cal->driver->list_categories();
$calendars = $this->cal->driver->list_calendars();
@ -208,7 +208,7 @@ class calendar_ui
/**
* Generate HTML content of the calendars list (or metadata only)
*/
function calendar_list($attrib = [], $js_only = false)
public function calendar_list($attrib = [], $js_only = false)
{
$html = '';
$jsenv = [];
@ -223,12 +223,10 @@ class calendar_ui
if (!empty($calendars[calendar_driver::BIRTHDAY_CALENDAR_ID])) {
$bdaycal = $calendars[calendar_driver::BIRTHDAY_CALENDAR_ID];
$calendars = [calendar_driver::BIRTHDAY_CALENDAR_ID => $bdaycal];
}
else {
} else {
$calendars = []; // clear array for flat listing
}
}
else if (isset($attrib['class'])) {
} elseif (isset($attrib['class'])) {
// fall-back to flat folder listing
$attrib['class'] .= ' flat';
}
@ -241,7 +239,7 @@ class calendar_ui
$li_content = $this->calendar_list_item($id, $prop, $jsenv, !empty($attrib['activeonly']));
$li_attr = [
'id' => 'rcmlical' . $id,
'class' => isset($prop['group']) ? $prop['group'] : null,
'class' => $prop['group'] ?? null,
];
$html .= html::tag('li', $li_attr, $li_content);
@ -273,7 +271,9 @@ class calendar_ui
$content = $this->calendar_list_item($id, $prop, $jsenv, !empty($attrib['activeonly']));
if (!empty($folder->children)) {
$content .= html::tag('ul', ['style' => $is_collapsed ? "display:none;" : null],
$content .= html::tag(
'ul',
['style' => $is_collapsed ? "display:none;" : null],
$this->list_tree_html($folder, $data, $jsenv, $attrib)
);
}
@ -304,9 +304,10 @@ class calendar_ui
$prop['freebusy'] = $this->cal->driver->freebusy;
$prop['attachments'] = $this->cal->driver->attachments;
$prop['undelete'] = $this->cal->driver->undelete;
$prop['feedurl'] = $this->cal->get_url([
$prop['feedurl'] = $this->cal->get_url(
[
'_cal' => $this->cal->ical_feed_hash($id) . '.ics',
'action' => 'feed'
'action' => 'feed',
]
);
@ -315,20 +316,17 @@ class calendar_ui
if (!empty($prop['title'])) {
$title = $prop['title'];
}
else if ($prop['name'] != $prop['listname'] || strlen($prop['name']) > 25) {
} elseif ($prop['name'] != $prop['listname'] || strlen($prop['name']) > 25) {
$title = html_entity_decode($prop['name'], ENT_COMPAT, RCUBE_CHARSET);
}
else {
} else {
$title = '';
}
$classes = ['calendar', 'cal-' . asciiwords($id, true)];
$classes = ['calendar', 'cal-' . asciiwords($id, true)];
if (!empty($prop['virtual'])) {
$classes[] = 'virtual';
}
else if (empty($prop['editable'])) {
} elseif (empty($prop['editable'])) {
$classes[] = 'readonly';
}
if (!empty($prop['subscribed'])) {
@ -356,32 +354,38 @@ class calendar_ui
$actions = '';
if (!empty($prop['removable'])) {
$actions .= html::a([
$actions .= html::a(
[
'href' => '#',
'class' => 'remove',
'title' => $this->cal->gettext('removelist')
], ' '
'title' => $this->cal->gettext('removelist'),
],
' '
);
}
$actions .= html::a([
$actions .= html::a(
[
'href' => '#',
'class' => 'quickview',
'title' => $this->cal->gettext('quickview'),
'role' => 'checkbox',
'aria-checked' => 'false'
], ''
'aria-checked' => 'false',
],
''
);
if (!isset($prop['subscriptions']) || $prop['subscriptions'] !== false) {
if (!empty($prop['subscribed'])) {
$actions .= html::a([
$actions .= html::a(
[
'href' => '#',
'class' => 'subscribed',
'title' => $this->cal->gettext('calendarsubscribe'),
'role' => 'checkbox',
'aria-checked' => !empty($prop['subscribed']) ? 'true' : 'false'
], ' '
'aria-checked' => !empty($prop['subscribed']) ? 'true' : 'false',
],
' '
);
}
}
@ -391,13 +395,13 @@ class calendar_ui
'name' => '_cal[]',
'value' => $id,
'checked' => !empty($prop['active']),
'aria-labelledby' => $label_id
'aria-labelledby' => $label_id,
])
. html::span('actions', $actions)
. html::span(['class' => 'handle', 'style' => "background-color: #$color"], '&nbsp;');
}
$content = html::div(join(' ', $classes), $content);
$content = html::div(implode(' ', $classes), $content);
}
return $content;
@ -406,7 +410,7 @@ class calendar_ui
/**
* Render a HTML for agenda options form
*/
function agenda_options($attrib = [])
public function agenda_options($attrib = [])
{
$attrib += ['id' => 'agendaoptions'];
$attrib['style'] = 'display:none';
@ -418,8 +422,10 @@ class calendar_ui
$select_range->add($days . ' ' . preg_replace('/\(|\)/', '', $this->cal->lib->gettext('days')), $days);
}
$html = html::span('input-group',
html::label(['for' => 'agenda-listrange', 'class' => 'input-group-prepend'],
$html = html::span(
'input-group',
html::label(
['for' => 'agenda-listrange', 'class' => 'input-group-prepend'],
html::span('input-group-text', $this->cal->gettext('listrange'))
)
. $select_range->show($this->rc->config->get('calendar_agenda_range', $this->cal->defaults['calendar_agenda_range']))
@ -431,7 +437,7 @@ class calendar_ui
/**
* Render a HTML select box for calendar selection
*/
function calendar_select($attrib = [])
public function calendar_select($attrib = [])
{
$attrib['name'] = 'calendar';
$attrib['is_escaped'] = true;
@ -453,7 +459,7 @@ class calendar_ui
/**
* Render a HTML select box for user identity selection
*/
function identity_select($attrib = [])
public function identity_select($attrib = [])
{
$attrib['name'] = 'identity';
@ -470,14 +476,14 @@ class calendar_ui
/**
* Render a HTML select box to select an event category
*/
function category_select($attrib = [])
public function category_select($attrib = [])
{
$attrib['name'] = 'categories';
$select = new html_select($attrib);
$select->add('---', '');
foreach (array_keys((array) $this->cal->driver->list_categories()) as $cat) {
$select->add($cat, $cat);
$select->add($cat, $cat);
}
return $select->show(null);
@ -486,7 +492,7 @@ class calendar_ui
/**
* Render a HTML select box for status property
*/
function status_select($attrib = [])
public function status_select($attrib = [])
{
$attrib['name'] = 'status';
@ -502,7 +508,7 @@ class calendar_ui
/**
* Render a HTML select box for free/busy/out-of-office property
*/
function freebusy_select($attrib = [])
public function freebusy_select($attrib = [])
{
$attrib['name'] = 'freebusy';
@ -519,7 +525,7 @@ class calendar_ui
/**
* Render a HTML select for event priorities
*/
function priority_select($attrib = [])
public function priority_select($attrib = [])
{
$attrib['name'] = 'priority';
@ -533,7 +539,7 @@ class calendar_ui
$select->add('6 ', '6');
$select->add('7 ', '7');
$select->add('8 ' . $this->cal->gettext('low'), '8');
$select->add('9 ' . $this->cal->gettext('lowest'), '9');
$select->add('9 ' . $this->cal->gettext('lowest'), '9');
return $select->show(null);
}
@ -541,7 +547,7 @@ class calendar_ui
/**
* Render HTML form for alarm configuration
*/
function alarm_select($attrib = [])
public function alarm_select($attrib = [])
{
return $this->cal->lib->alarm_select($attrib, $this->cal->driver->alarm_types, $this->cal->driver->alarm_absolute);
}
@ -549,7 +555,7 @@ class calendar_ui
/**
* Render HTML for attendee notification warning
*/
function edit_attendees_notify($attrib = [])
public function edit_attendees_notify($attrib = [])
{
$checkbox = new html_checkbox(['name' => '_notify', 'id' => 'edit-attendees-donotify', 'value' => 1, 'class' => 'pretty-checkbox']);
return html::div($attrib, html::label(null, $checkbox->show(1) . ' ' . $this->cal->gettext('sendnotifications')));
@ -558,7 +564,7 @@ class calendar_ui
/**
* Render HTML for recurrence option to align start date with the recurrence rule
*/
function edit_recurrence_sync($attrib = [])
public function edit_recurrence_sync($attrib = [])
{
$checkbox = new html_checkbox(['name' => '_start_sync', 'value' => 1, 'class' => 'pretty-checkbox']);
return html::div($attrib, html::label(null, $checkbox->show(1) . ' ' . $this->cal->gettext('eventstartsync')));
@ -567,7 +573,7 @@ class calendar_ui
/**
* Generate the form for recurrence settings
*/
function recurring_event_warning($attrib = [])
public function recurring_event_warning($attrib = [])
{
$attrib['id'] = 'edit-recurring-warning';
@ -578,7 +584,8 @@ class calendar_ui
. html::label(null, $radio->show('all', ['value' => 'all']) . $this->cal->gettext('allevents')) . ' '
. html::label(null, $radio->show('', ['value' => 'new']) . $this->cal->gettext('saveasnew'));
return html::div($attrib,
return html::div(
$attrib,
html::div('message', $this->cal->gettext('changerecurringeventwarning'))
. html::div('savemode', $form)
);
@ -587,7 +594,7 @@ class calendar_ui
/**
* Form for uploading and importing events
*/
function events_import_form($attrib = [])
public function events_import_form($attrib = [])
{
if (empty($attrib['id'])) {
$attrib['id'] = 'rcmImportForm';
@ -606,39 +613,48 @@ class calendar_ui
'type' => 'file',
'name' => '_data',
'size' => !empty($attrib['uploadfieldsize']) ? $attrib['uploadfieldsize'] : null,
'accept' => $accept
'accept' => $accept,
]);
$select = new html_select(['name' => '_range', 'id' => 'event-import-range']);
$select->add([
$select->add(
[
$this->cal->gettext('onemonthback'),
$this->cal->gettext(['name' => 'nmonthsback', 'vars' => ['nr'=>2]]),
$this->cal->gettext(['name' => 'nmonthsback', 'vars' => ['nr'=>3]]),
$this->cal->gettext(['name' => 'nmonthsback', 'vars' => ['nr'=>6]]),
$this->cal->gettext(['name' => 'nmonthsback', 'vars' => ['nr'=>12]]),
$this->cal->gettext(['name' => 'nmonthsback', 'vars' => ['nr' => 2]]),
$this->cal->gettext(['name' => 'nmonthsback', 'vars' => ['nr' => 3]]),
$this->cal->gettext(['name' => 'nmonthsback', 'vars' => ['nr' => 6]]),
$this->cal->gettext(['name' => 'nmonthsback', 'vars' => ['nr' => 12]]),
$this->cal->gettext('all'),
],
['1','2','3','6','12',0]
);
$html = html::div('form-section form-group row',
html::label(['class' => 'col-sm-4 col-form-label', 'for' => 'importfile'],
$html = html::div(
'form-section form-group row',
html::label(
['class' => 'col-sm-4 col-form-label', 'for' => 'importfile'],
rcube::Q($this->rc->gettext('importfromfile'))
)
. html::div('col-sm-8', $input->show()
. html::div(
'col-sm-8',
$input->show()
. html::div('hint', $this->rc->gettext(['name' => 'maxuploadsize', 'vars' => ['size' => $max_filesize]]))
)
);
$html .= html::div('form-section form-group row',
html::label(['for' => 'event-import-calendar', 'class' => 'col-form-label col-sm-4'],
$html .= html::div(
'form-section form-group row',
html::label(
['for' => 'event-import-calendar', 'class' => 'col-form-label col-sm-4'],
$this->cal->gettext('calendar')
)
. html::div('col-sm-8', $this->calendar_select(['name' => 'calendar', 'id' => 'event-import-calendar']))
);
$html .= html::div('form-section form-group row',
html::label(['for' => 'event-import-range', 'class' => 'col-form-label col-sm-4'],
$html .= html::div(
'form-section form-group row',
html::label(
['for' => 'event-import-range', 'class' => 'col-form-label col-sm-4'],
$this->cal->gettext('importrange')
)
. html::div('col-sm-8', $select->show(1))
@ -648,26 +664,31 @@ class calendar_ui
$this->rc->output->add_label('import');
return html::tag('p', null, $this->cal->gettext('importtext'))
. html::tag('form', [
. html::tag(
'form',
[
'action' => $this->rc->url(['task' => 'calendar', 'action' => 'import_events']),
'method' => 'post',
'enctype' => 'multipart/form-data',
'id' => $attrib['id']
], $html
'id' => $attrib['id'],
],
$html
);
}
/**
* Form to select options for exporting events
*/
function events_export_form($attrib = [])
public function events_export_form($attrib = [])
{
if (empty($attrib['id'])) {
$attrib['id'] = 'rcmExportForm';
}
$html = html::div('form-section form-group row',
html::label(['for' => 'event-export-calendar', 'class' => 'col-sm-4 col-form-label'],
$html = html::div(
'form-section form-group row',
html::label(
['for' => 'event-export-calendar', 'class' => 'col-sm-4 col-form-label'],
$this->cal->gettext('calendar')
)
. html::div('col-sm-8', $this->calendar_select(['name' => 'calendar', 'id' => 'event-export-calendar', 'class' => 'form-control custom-select']))
@ -676,10 +697,11 @@ class calendar_ui
$select = new html_select([
'name' => 'range',
'id' => 'event-export-range',
'class' => 'form-control custom-select rounded-right'
'class' => 'form-control custom-select rounded-right',
]);
$select->add([
$select->add(
[
$this->cal->gettext('all'),
$this->cal->gettext('onemonthback'),
$this->cal->gettext(['name' => 'nmonthsback', 'vars' => ['nr' => 2]]),
@ -695,11 +717,13 @@ class calendar_ui
'name' => 'start',
'size' => 11,
'id' => 'event-export-startdate',
'style' => 'display:none'
'style' => 'display:none',
]);
$html .= html::div('form-section form-group row',
html::label(['for' => 'event-export-range', 'class' => 'col-sm-4 col-form-label'],
$html .= html::div(
'form-section form-group row',
html::label(
['for' => 'event-export-range', 'class' => 'col-sm-4 col-form-label'],
$this->cal->gettext('exportrange')
)
. html::div('col-sm-8 input-group', $select->show(0) . $startdate->show())
@ -709,11 +733,13 @@ class calendar_ui
'name' => 'attachments',
'id' => 'event-export-attachments',
'value' => 1,
'class' => 'form-check-input pretty-checkbox'
'class' => 'form-check-input pretty-checkbox',
]);
$html .= html::div('form-section form-check row',
html::label(['for' => 'event-export-attachments', 'class' => 'col-sm-4 col-form-label'],
$html .= html::div(
'form-section form-check row',
html::label(
['for' => 'event-export-attachments', 'class' => 'col-sm-4 col-form-label'],
$this->cal->gettext('exportattachments')
)
. html::div('col-sm-8', $checkbox->show(1))
@ -721,10 +747,12 @@ class calendar_ui
$this->rc->output->add_gui_object('exportform', $attrib['id']);
return html::tag('form', $attrib + [
return html::tag(
'form',
$attrib + [
'action' => $this->rc->url(['task' => 'calendar', 'action' => 'export_events']),
'method' => 'post',
'id' => $attrib['id']
'id' => $attrib['id'],
],
$html
);
@ -734,7 +762,7 @@ class calendar_ui
* Handler for calendar form template.
* The form content could be overriden by the driver
*/
function calendar_editform($action, $calendar = [])
public function calendar_editform($action, $calendar = [])
{
$this->action = $action;
$this->calendar = $calendar;
@ -751,7 +779,7 @@ class calendar_ui
* Handler for calendar form template.
* The form content could be overriden by the driver
*/
function calendarform($attrib)
public function calendarform($attrib)
{
// compose default calendar form fields
$input_name = new html_inputfield(['name' => 'name', 'id' => 'calendar-name', 'size' => 20]);
@ -760,12 +788,12 @@ class calendar_ui
$formfields = [
'name' => [
'label' => $this->cal->gettext('name'),
'value' => $input_name->show(isset($this->calendar['name']) ? $this->calendar['name'] : ''),
'value' => $input_name->show($this->calendar['name'] ?? ''),
'id' => 'calendar-name',
],
'color' => [
'label' => $this->cal->gettext('color'),
'value' => $input_color->show(isset($this->calendar['color']) ? $this->calendar['color'] : ''),
'value' => $input_color->show($this->calendar['color'] ?? ''),
'id' => 'calendar-color',
],
];
@ -781,7 +809,9 @@ class calendar_ui
}
// allow driver to extend or replace the form content
return html::tag('form', $attrib + ['action' => '#', 'method' => 'get', 'id' => 'calendarpropform'],
return html::tag(
'form',
$attrib + ['action' => '#', 'method' => 'get', 'id' => 'calendarpropform'],
$this->cal->driver->calendar_form($this->action, $this->calendar, $formfields)
);
}
@ -789,7 +819,7 @@ class calendar_ui
/**
* Render HTML for attendees table
*/
function attendees_list($attrib = [])
public function attendees_list($attrib = [])
{
// add "noreply" checkbox to attendees table only
$invitations = strpos($attrib['id'], 'attend') !== false;
@ -803,7 +833,8 @@ class calendar_ui
$table->add_header('confirmstate', $this->cal->gettext('confirmstate'));
if ($invitations) {
$table->add_header(['class' => 'invite', 'title' => $this->cal->gettext('sendinvitations')],
$table->add_header(
['class' => 'invite', 'title' => $this->cal->gettext('sendinvitations')],
$invite->show(1)
. html::label('edit-attendees-invite', html::span('inner', $this->cal->gettext('sendinvitations')))
);
@ -824,12 +855,12 @@ class calendar_ui
/**
* Render HTML for attendees adding form
*/
function attendees_form($attrib = [])
public function attendees_form($attrib = [])
{
$input = new html_inputfield([
'name' => 'participant',
'id' => 'edit-attendee-name',
'class' => 'form-control'
'class' => 'form-control',
]);
$textarea = new html_textarea([
'name' => 'comment',
@ -837,25 +868,27 @@ class calendar_ui
'class' => 'form-control',
'rows' => 4,
'cols' => 55,
'title' => $this->cal->gettext('itipcommenttitle')
'title' => $this->cal->gettext('itipcommenttitle'),
]);
return html::div($attrib,
html::div('form-searchbar',
return html::div(
$attrib,
html::div(
'form-searchbar',
$input->show()
. ' ' .
html::tag('input', [
'type' => 'button',
'class' => 'button',
'id' => 'edit-attendee-add',
'value' => $this->cal->gettext('addattendee')
'value' => $this->cal->gettext('addattendee'),
])
. ' ' .
html::tag('input', [
'type' => 'button',
'class' => 'button',
'id' => 'edit-attendee-schedule',
'value' => $this->cal->gettext('scheduletime') . '...'
'value' => $this->cal->gettext('scheduletime') . '...',
])
)
. html::p('attendees-commentbox', html::label('edit-attendees-comment', $this->cal->gettext('itipcomment')) . $textarea->show())
@ -865,26 +898,28 @@ class calendar_ui
/**
* Render HTML for resources adding form
*/
function resources_form($attrib = [])
public function resources_form($attrib = [])
{
$input = new html_inputfield(['name' => 'resource', 'id' => 'edit-resource-name', 'class' => 'form-control']);
return html::div($attrib,
html::div('form-searchbar',
return html::div(
$attrib,
html::div(
'form-searchbar',
$input->show()
. ' ' .
html::tag('input', [
'type' => 'button',
'class' => 'button',
'id' => 'edit-resource-add',
'value' => $this->cal->gettext('addresource')
'value' => $this->cal->gettext('addresource'),
])
. ' ' .
html::tag('input', [
'type' => 'button',
'class' => 'button',
'id' => 'edit-resource-find',
'value' => $this->cal->gettext('findresources') . '...'
'value' => $this->cal->gettext('findresources') . '...',
])
)
);
@ -893,7 +928,7 @@ class calendar_ui
/**
* Render HTML for resources list
*/
function resources_list($attrib = [])
public function resources_list($attrib = [])
{
$attrib += ['id' => 'calendar-resources-list'];
@ -913,14 +948,20 @@ class calendar_ui
$this->rc->output->add_gui_object('resourceownerinfo', $attrib['id'] . '-owner');
// copy address book labels for owner details to client
$this->rc->output->add_label('name','firstname','surname','department','jobtitle','email','phone','address');
$this->rc->output->add_label('name', 'firstname', 'surname', 'department', 'jobtitle', 'email', 'phone', 'address');
$table_attrib = ['id','class','style','width','summary','cellpadding','cellspacing','border'];
return html::tag('table', $attrib, html::tag('tbody', null, ''), $table_attrib)
. html::tag('table', ['id' => $attrib['id'] . '-owner', 'style' => 'display:none'] + $attrib,
html::tag('thead', null,
html::tag('tr', null,
. html::tag(
'table',
['id' => $attrib['id'] . '-owner', 'style' => 'display:none'] + $attrib,
html::tag(
'thead',
null,
html::tag(
'tr',
null,
html::tag('td', ['colspan' => 2], rcube::Q($this->cal->gettext('resourceowner')))
)
)
@ -948,7 +989,7 @@ class calendar_ui
*
* @return string HTML code for the gui object
*/
function resources_search_form($attrib)
public function resources_search_form($attrib)
{
$attrib += [
'command' => 'search-resource',
@ -966,17 +1007,22 @@ class calendar_ui
/**
*
*/
function attendees_freebusy_table($attrib = [])
public function attendees_freebusy_table($attrib = [])
{
$table = new html_table(['cols' => 2, 'border' => 0, 'cellspacing' => 0]);
$table->add('attendees',
$table->add(
'attendees',
html::tag('h3', 'boxtitle', $this->cal->gettext('tabattendees'))
. html::div('timesheader', '&nbsp;')
. html::div(['id' => 'schedule-attendees-list', 'class' => 'attendees-list'], '')
);
$table->add('times',
html::div('scroll',
html::tag('table', ['id' => 'schedule-freebusy-times', 'border' => 0, 'cellspacing' => 0],
$table->add(
'times',
html::div(
'scroll',
html::tag(
'table',
['id' => 'schedule-freebusy-times', 'border' => 0, 'cellspacing' => 0],
html::tag('thead') . html::tag('tbody')
)
. html::div(['id' => 'schedule-event-time', 'style' => 'display:none'], '&nbsp;')
@ -989,10 +1035,11 @@ class calendar_ui
/**
*
*/
function event_invitebox($attrib = [])
public function event_invitebox($attrib = [])
{
if (!empty($this->cal->event)) {
return html::div($attrib,
return html::div(
$attrib,
$this->cal->itip->itip_object_details_table($this->cal->event, $this->cal->itip->gettext('itipinvitation'))
. $this->cal->invitestatus
);
@ -1001,7 +1048,7 @@ class calendar_ui
return '';
}
function event_rsvp_buttons($attrib = [])
public function event_rsvp_buttons($attrib = [])
{
$actions = ['accepted', 'tentative', 'declined'];

View file

@ -194,4 +194,3 @@ $labels['birthdays'] = 'Рождени дни';
$labels['arialabelcalendarview'] = 'Преглед на календара';
$labels['arialabeleventattendees'] = 'Списък с участниците в събитието';
$labels['arialabelresourceselection'] = 'Налични ресурси';
?>

View file

@ -251,4 +251,3 @@ $labels['arialabeleventattendees'] = 'Llista de participants de l\'esdeveniment'
$labels['arialabeleventresources'] = 'Llista de recursos de l\'esdeveniment';
$labels['arialabelresourcesearchform'] = 'Formulari de cerca de recursos';
$labels['arialabelresourceselection'] = 'Recursos disponibles';
?>

View file

@ -279,4 +279,3 @@ $labels['arialabeleventresources'] = 'Seznam zdrojů události';
$labels['arialabelresourcesearchform'] = 'Hledání zdrojů';
$labels['arialabelresourceselection'] = 'Dostupné zdroje';
$labels['arialabeleventform'] = 'Úprava události';
?>

View file

@ -285,4 +285,3 @@ $labels['arialabeleventresources'] = 'Ressourceliste for begivenhed';
$labels['arialabelresourcesearchform'] = 'Søgeformular for ressourcer';
$labels['arialabelresourceselection'] = 'Tilgængelige ressourcer';
$labels['arialabeleventform'] = 'Formular til redigering af begivenhed';
?>

View file

@ -283,4 +283,3 @@ $labels['arialabeleventresources'] = 'Liste der Terminressourcen';
$labels['arialabelresourcesearchform'] = 'Suchformular für Ressourcen';
$labels['arialabelresourceselection'] = 'Verfügbare Ressourcen';
$labels['arialabeleventform'] = 'Ereignisbearbeitungsformular';
?>

View file

@ -265,4 +265,3 @@ $labels['arialabeleventattendees'] = 'Teilehmerliste';
$labels['arialabeleventresources'] = 'Liste der Terminressourcen';
$labels['arialabelresourcesearchform'] = 'Suchformular für Ressourcen';
$labels['arialabelresourceselection'] = 'Verfügbare Ressourcen';
?>

View file

@ -265,4 +265,3 @@ $labels['arialabeleventattendees'] = 'Teilehmerliste';
$labels['arialabeleventresources'] = 'Liste der Terminressourcen';
$labels['arialabelresourcesearchform'] = 'Suchformular für Ressourcen';
$labels['arialabelresourceselection'] = 'Verfügbare Ressourcen';
?>

View file

@ -92,4 +92,3 @@ $labels['availoutofoffice'] = 'Εκτός γραφείου';
$labels['tabsummary'] = 'Περίληψη';
$labels['savingdata'] = 'Αποθήκευση δεδομένων...';
$labels['objectchangelog'] = 'Αλλαγή ιστορικού';
?>

View file

@ -8,7 +8,7 @@
* For translation see https://www.transifex.com/projects/p/kolab/resource/calendar/
*/
$labels = array();
$labels = [];
// preferences
$labels['default_view'] = 'Default view';
@ -327,4 +327,3 @@ $labels['createtalkroom'] = 'Create Talk room';
$labels['talkroomcreating'] = 'Creating a Talk room for the event...';
$labels['talkroomcreateerror'] = 'Failed to create a Talk room.';
$labels['talkroomname'] = 'Room for an event';
?>

View file

@ -278,4 +278,3 @@ $labels['arialabeleventresources'] = 'Lista de recursos del evento';
$labels['arialabelresourcesearchform'] = 'Formulario de búsqueda de recursos';
$labels['arialabelresourceselection'] = 'Recursos disponibles';
$labels['arialabeleventform'] = 'Formulario de edición de evento';
?>

View file

@ -285,4 +285,3 @@ $labels['arialabeleventresources'] = 'Lista de recursos del evento';
$labels['arialabelresourcesearchform'] = 'Formulario de búsqueda de recursos';
$labels['arialabelresourceselection'] = 'Recursos disponibles';
$labels['arialabeleventform'] = 'Formulario de edición de eventos';
?>

View file

@ -160,4 +160,3 @@ $labels['arialabelcalendarview'] = 'Kalendri vaade';
$labels['calendaractions'] = 'Kalendri toimingud';
$labels['calendarprops'] = 'Kalendri omadused';
$labels['arialabelresourceselection'] = 'Saadaolevad ressursid';
?>

View file

@ -277,4 +277,3 @@ $labels['arialabeleventresources'] = 'Tapahtuman resurssilista';
$labels['arialabelresourcesearchform'] = 'Resurssien hakulomake';
$labels['arialabelresourceselection'] = 'Saatavilla olevat resurssit';
$labels['arialabeleventform'] = 'Tapahtuman muokkauslomake';
?>

View file

@ -264,4 +264,3 @@ $labels['arialabeleventattendees'] = 'Liste des participants à l\'événement';
$labels['arialabeleventresources'] = 'Liste des ressources de l\'événement';
$labels['arialabelresourcesearchform'] = 'Formulaire de recherche des ressources';
$labels['arialabelresourceselection'] = 'Ressources disponibles';
?>

View file

@ -21,4 +21,3 @@ $labels['calendars'] = 'Kalendari';
$labels['category'] = 'Kategorija';
$labels['categories'] = 'Kategorije';
$labels['status-tentative'] = 'Tentative';
?>

View file

@ -211,4 +211,3 @@ $labels['displaybirthdayscalendar'] = 'Születésnapok megjelenítése';
$labels['birthdayscalendarsources'] = 'Alábbi címjegyzékekből:';
$labels['birthdayeventtitle'] = '$name születésnapja';
$labels['birthdayage'] = '$age éves';
?>

View file

@ -259,4 +259,3 @@ $labels['arialabeleventattendees'] = 'Lista partecipanti all\'evento';
$labels['arialabeleventresources'] = 'Lista risorse dell\'evento';
$labels['arialabelresourcesearchform'] = 'Modulo ricerca risorse';
$labels['arialabelresourceselection'] = 'Risorse disponibili';
?>

View file

@ -263,4 +263,3 @@ $labels['arialabeleventattendees'] = 'イベント参加者リスト';
$labels['arialabeleventresources'] = 'イベントリソースリスト';
$labels['arialabelresourcesearchform'] = 'リソース検索元';
$labels['arialabelresourceselection'] = '利用可能なリソース';
?>

View file

@ -219,4 +219,3 @@ $labels['arialabelcalendarview'] = '캘린더 보기';
$labels['arialabelsearchform'] = '일정 검색 폼';
$labels['arialabelquicksearchbox'] = '일정 검색 항목';
$labels['arialabelcalsearchform'] = '캘린더 검색 폼';
?>

View file

@ -263,4 +263,3 @@ $labels['arialabeleventattendees'] = 'Dalībnieku saraksts';
$labels['arialabeleventresources'] = 'Resursu saraksts';
$labels['arialabelresourcesearchform'] = 'Resursu meklēšanas forma';
$labels['arialabelresourceselection'] = 'Pieejamie resursi';
?>

View file

@ -264,4 +264,3 @@ $labels['arialabeleventattendees'] = 'Lijst met deelnemers van activiteit';
$labels['arialabeleventresources'] = 'Lijst met resources voor activiteit';
$labels['arialabelresourcesearchform'] = 'Zoekformulier voor resources';
$labels['arialabelresourceselection'] = 'Beschikbare resources';
?>

View file

@ -264,4 +264,3 @@ $labels['arialabeleventattendees'] = 'Lista uczestników zdarzenia';
$labels['arialabeleventresources'] = 'Lista zasobów zdarzenia';
$labels['arialabelresourcesearchform'] = 'Formularz wyszukiwania zasobów';
$labels['arialabelresourceselection'] = 'Dostępne zasoby';
?>

View file

@ -285,4 +285,3 @@ $labels['arialabeleventresources'] = 'Lista zasobów zdarzenia';
$labels['arialabelresourcesearchform'] = 'Formularz wyszukiwania zasobów';
$labels['arialabelresourceselection'] = 'Dostępne zasoby';
$labels['arialabeleventform'] = 'Formularz edycji wydarzenia';
?>

View file

@ -266,4 +266,3 @@ $labels['arialabeleventattendees'] = 'Lista de participantes do evento';
$labels['arialabeleventresources'] = 'Lista de recursos para eventos';
$labels['arialabelresourcesearchform'] = 'Formulário de pesquisa de recursos';
$labels['arialabelresourceselection'] = 'Recursos disponíveis';
?>

View file

@ -262,4 +262,3 @@ $labels['arialabeleventattendees'] = 'Lista de participantes do evento';
$labels['arialabeleventresources'] = 'Lista de recursos para eventos';
$labels['arialabelresourcesearchform'] = 'Quadro de pesquisa de recursos';
$labels['arialabelresourceselection'] = 'Recursos disponíveis';
?>

View file

@ -285,4 +285,3 @@ $labels['arialabeleventresources'] = 'Ресурсы события';
$labels['arialabelresourcesearchform'] = 'Форма поиска ресурсов';
$labels['arialabelresourceselection'] = 'Доступные ресурсы';
$labels['arialabeleventform'] = 'Форма редактирования события';
?>

View file

@ -79,4 +79,3 @@ $labels['availbusy'] = 'Zaneprázdnený';
$labels['availtentative'] = 'Nezáväzne';
$labels['availoutofoffice'] = 'Mimo kancelárie';
$labels['tabsummary'] = 'Sumár';
?>

View file

@ -258,4 +258,3 @@ $labels['arialabeleventattendees'] = 'Seznam sodelujočih na dogodku';
$labels['arialabeleventresources'] = 'Seznam virov za dogodek';
$labels['arialabelresourcesearchform'] = 'Obrazec za iskanje virov';
$labels['arialabelresourceselection'] = 'Viri na voljo';
?>

View file

@ -257,4 +257,3 @@ $labels['arialabeleventattendees'] = 'Händelse deltagarlista';
$labels['arialabeleventresources'] = 'Händelse resurslista';
$labels['arialabelresourcesearchform'] = 'Resurser sökformulär';
$labels['arialabelresourceselection'] = 'Tillgängliga resurser';
?>

View file

@ -263,4 +263,3 @@ $labels['arialabeleventattendees'] = 'Händelse deltagarlista';
$labels['arialabeleventresources'] = 'Händelse resurslista';
$labels['arialabelresourcesearchform'] = 'Resurser sökformulär';
$labels['arialabelresourceselection'] = 'Tillgängliga resurser';
?>

View file

@ -244,4 +244,3 @@ $labels['arialabeleventattendees'] = 'รายชื่อผู้เข้า
$labels['arialabeleventresources'] = 'รายการทรัพยากรที่ใช้ในเหตุการณ์';
$labels['arialabelresourcesearchform'] = 'ฟอร์มค้นหาทรัพยากร';
$labels['arialabelresourceselection'] = 'ทรัพยากรที่ยังว่าง';
?>

View file

@ -212,4 +212,3 @@ $labels['arialabeleventattendees'] = 'Учасники події';
$labels['arialabeleventresources'] = 'Ресурси подій';
$labels['arialabelresourcesearchform'] = 'Форма пошуку ресурсів';
$labels['arialabelresourceselection'] = 'Доступні ресурси';
?>

View file

@ -120,4 +120,3 @@ $labels['tabsharing'] = '分享';
$labels['savingdata'] = '保存数据...';
$labels['futurevents'] = '未来';
$labels['allevents'] = '全部';
?>

View file

@ -25,20 +25,20 @@
class html_converter extends rcube_plugin
{
private static $replaces = array(
private static $replaces = [
"<blockquote>" => "<br>&amp;&raquo;&amp;<br>",
"</blockquote>" => "<br>&amp;&laquo;&amp;<br>",
"\x02\x03" => "***^^^SIG^^^***",
);
];
/**
* Plugin initialization.
*/
function init()
public function init()
{
// register hook to convert HTML to Text
$this->add_hook('html2text', array($this, 'html2text'));
$this->add_hook('html2text', [$this, 'html2text']);
}
/**
@ -82,17 +82,17 @@ class html_converter extends rcube_plugin
return false;
}
$args = array(
$args = [
'{path}' => $tmpfname,
'{width}' => (int) $p['width'],
'{charset}' => $p['charset'],
'{links}' => $p['links'] ? 1 : 0,
);
/*
$command = 'links -force-html -no-connect -no-g -codepage {charset}'
. ' -aggressive-cache 0 -html-margin 0 -html-numbered-links {links}'
. ' -width {width} -dump {path}';
*/
];
/*
$command = 'links -force-html -no-connect -no-g -codepage {charset}'
. ' -aggressive-cache 0 -html-margin 0 -html-numbered-links {links}'
. ' -width {width} -dump {path}';
*/
$command = 'lynx -force_html -noreferer -nomargins -dont_wrap_pre'
. ' -nolist -display_charset={charset} -width={width} -dump {path}';
@ -112,11 +112,11 @@ class html_converter extends rcube_plugin
unlink($tmpfname);
if ($status) {
rcube::raise_error(array(
rcube::raise_error([
'line' => __LINE__,
'file' => __FILE__,
'message' => "Failed executing: $command (code: $status)"
), true, false);
'message' => "Failed executing: $command (code: $status)",
], true, false);
return false;
}
@ -142,7 +142,7 @@ class html_converter extends rcube_plugin
/**
* Post-filtering on plain text content.
*/
function postfilter($text)
public function postfilter($text)
{
$replaces = self::$replaces;
@ -168,25 +168,21 @@ class html_converter extends rcube_plugin
$level++;
$last = true;
unset($result[$idx]);
}
else if ($line === $end) {
} elseif ($line === $end) {
$level--;
$last = true;
unset($result[$idx]);
}
else if ($last && !strlen($line)) {
} elseif ($last && !strlen($line)) {
unset($result[$idx]);
$last = false;
}
else if ($level) {
} elseif ($level) {
$len = strlen($line);
if (!$len && isset($result[$idx+1])
&& ($result[$idx+1] === $end || $result[$idx+1] === $start)
if (!$len && isset($result[$idx + 1])
&& ($result[$idx + 1] === $end || $result[$idx + 1] === $start)
) {
unset($result[$idx]);
}
else {
} else {
$result[$idx] = str_repeat('>', $level) . ($len ? ' ' . $line : '');
}
}

View file

@ -20,7 +20,7 @@
*/
// available methods/providers. Supported methods are: 'totp','hotp','yubikey'
$config['kolab_2fa_drivers'] = array('totp');
$config['kolab_2fa_drivers'] = ['totp'];
// backend for storing 2-factor-auth related per-user settings
// available backends are: 'roundcube', 'ldap', 'sql'
@ -28,9 +28,9 @@ $config['kolab_2fa_storage'] = 'roundcube';
// additional config options for the above storage backend
// here an example for the LDAP backend:
$config['kolab_2fa_storage_config'] = array(
$config['kolab_2fa_storage_config'] = [
'debug' => false,
'hosts' => array('localhost'),
'hosts' => ['localhost'],
'port' => 389,
'bind_dn' => 'uid=kolab-auth-service,ou=Special Users,dc=example,dc=org',
'bind_pass' => 'Welcome2KolabSystems',
@ -39,7 +39,7 @@ $config['kolab_2fa_storage_config'] = array(
'filter' => '(&(objectClass=ipaToken)(objectclass=ldapSubEntry)(ipatokenOwner=%fu))',
'scope' => 'sub',
// translates driver properties to LDAP attributes
'fieldmap' => array(
'fieldmap' => [
'label' => 'cn',
'id' => 'ipatokenUniqueID',
'active' => 'ipatokenDisabled',
@ -50,49 +50,49 @@ $config['kolab_2fa_storage_config'] = array(
'counter' => 'ipatokenHOTPcounter',
'digest' => 'ipatokenOTPalgorithm',
'digits' => 'ipatokenOTPdigits',
),
],
// LDAP object classes derived from factor IDs (prefix)
// will be translated into the %c placeholder
'classmap' => array(
'classmap' => [
'totp:' => 'ipatokenTOTP',
'hotp:' => 'ipatokenHOTP',
'*' => 'ipaToken',
),
],
// translates property values into LDAP attribute values and vice versa
'valuemap' => array(
'active' => array(
'valuemap' => [
'active' => [
false => 'TRUE',
true => 'FALSE',
),
),
],
],
// specify non-string data types for properties for implicit conversion
'attrtypes' => array(
'attrtypes' => [
'created' => 'datetime',
'counter' => 'integer',
'digits' => 'integer',
),
],
// apply these default values to factor records if not specified by the drivers
'defaults' => array(
'defaults' => [
'active' => false,
// these are required for ipatokenHOTP records and should match the kolab_2fa_hotp parameters
'digest' => 'sha1',
'digits' => 6,
),
],
// use this LDAP attribute to compose DN values for factor entries
'rdn' => 'ipatokenUniqueID',
// assign these object classes to new factor entries
'objectclass' => array(
'objectclass' => [
'top',
'ipaToken',
'%c',
'ldapSubEntry',
),
],
// add these roles to the user's LDAP record if key prefix-matches a factor entry
'user_roles' => array(
'user_roles' => [
'totp:' => 'cn=totp-user,dc=example,dc=org',
'hotp:' => 'cn=hotp-user,dc=example,dc=org',
),
);
],
];
// force a lookup for active authentication factors for this user.
// to be set by another plugin (e.g. kolab_auth based on LDAP roles)
@ -102,24 +102,24 @@ $config['kolab_2fa_storage_config'] = array(
$config['kolab_2fa_timeout'] = 120;
// configuration parameters for TOTP (uncomment to adjust)
$config['kolab_2fa_totp'] = array(
$config['kolab_2fa_totp'] = [
// 'digits' => 6,
// 'interval' => 30,
// 'digest' => 'sha1',
// 'issuer' => 'Roundcube',
);
];
// configuration parameters for HOTP (uncomment to adjust)
$config['kolab_2fa_hotp'] = array(
$config['kolab_2fa_hotp'] = [
// 'digits' => 6,
// 'window' => 4,
// 'digest' => 'sha1',
);
];
// configuration parameters for Yubikey (uncomment to adjust)
$config['kolab_2fa_yubikey'] = array(
$config['kolab_2fa_yubikey'] = [
'clientid' => '123456',
'apikey' => '<your-server-api-key>',
// 'hosts' => array('api.myhost1.com','api2.myhost.com'),
'use_https' => true, // connect via https if set to true
);
];

View file

@ -26,8 +26,8 @@ class kolab_2fa extends rcube_plugin
public $task = '(login|settings)';
protected $login_verified = null;
protected $login_factors = array();
protected $drivers = array();
protected $login_factors = [];
protected $drivers = [];
protected $storage;
/**
@ -36,7 +36,7 @@ class kolab_2fa extends rcube_plugin
public function init()
{
$this->load_config();
$this->add_hook('startup', array($this, 'startup'));
$this->add_hook('startup', [$this, 'startup']);
}
/**
@ -48,24 +48,23 @@ class kolab_2fa extends rcube_plugin
// register library namespace to autoloader
$loader = include(INSTALL_PATH . 'vendor/autoload.php');
$loader->set('Kolab2FA', array($this->home . '/lib'));
$loader->set('Kolab2FA', [$this->home . '/lib']);
if ($args['task'] === 'login' && $this->api->output) {
$this->add_texts('localization/', false);
$this->add_hook('authenticate', array($this, 'authenticate'));
$this->add_hook('authenticate', [$this, 'authenticate']);
// process 2nd factor auth step after regular login
if ($args['action'] === 'plugin.kolab-2fa-login' /* || !empty($_SESSION['kolab_2fa_factors']) */) {
return $this->login_verify($args);
}
}
else if ($args['task'] === 'settings') {
} elseif ($args['task'] === 'settings') {
$this->add_texts('localization/', !$this->api->output->ajax_call);
$this->add_hook('settings_actions', array($this, 'settings_actions'));
$this->register_action('plugin.kolab-2fa', array($this, 'settings_view'));
$this->register_action('plugin.kolab-2fa-data', array($this, 'settings_data'));
$this->register_action('plugin.kolab-2fa-save', array($this, 'settings_save'));
$this->register_action('plugin.kolab-2fa-verify', array($this, 'settings_verify'));
$this->add_hook('settings_actions', [$this, 'settings_actions']);
$this->register_action('plugin.kolab-2fa', [$this, 'settings_view']);
$this->register_action('plugin.kolab-2fa-data', [$this, 'settings_data']);
$this->register_action('plugin.kolab-2fa-save', [$this, 'settings_save']);
$this->register_action('plugin.kolab-2fa-verify', [$this, 'settings_verify']);
}
return $args;
@ -98,8 +97,7 @@ class kolab_2fa extends rcube_plugin
if (!empty($username_domain[$hostname])) {
$domain = $username_domain[$hostname];
}
}
else {
} else {
$domain = $username_domain;
}
@ -111,7 +109,7 @@ class kolab_2fa extends rcube_plugin
$username = substr($username, 0, $pos) . '@' . $domain;
}
// just add domain if not specified
else if ($pos === false) {
elseif ($pos === false) {
$username .= '@' . $domain;
}
}
@ -122,28 +120,27 @@ class kolab_2fa extends rcube_plugin
if ($login_lc) {
if ($login_lc == 2 || $login_lc === true) {
$username = mb_strtolower($username);
}
else if (strpos($username, '@')) {
} elseif (strpos($username, '@')) {
// lowercase domain name
list($local, $domain) = explode('@', $username);
[$local, $domain] = explode('@', $username);
$username = $local . '@' . mb_strtolower($domain);
}
}
// 2a. let plugins provide the list of active authentication factors
$lookup = $rcmail->plugins->exec_hook('kolab_2fa_lookup', array(
$lookup = $rcmail->plugins->exec_hook('kolab_2fa_lookup', [
'user' => $username,
'host' => $hostname,
'factors' => null,
'check' => $rcmail->config->get('kolab_2fa_check', true),
));
]);
$factors = [];
if (isset($lookup['factors'])) {
$factors = (array)$lookup['factors'];
}
// 2b. check storage if this user has 2FA enabled
else if ($lookup['check'] !== false && ($storage = $this->get_storage($username))) {
elseif ($lookup['check'] !== false && ($storage = $this->get_storage($username))) {
$factors = (array)$storage->enumerate();
}
@ -174,7 +171,7 @@ class kolab_2fa extends rcube_plugin
{
// replace handler for login form
$this->login_factors = array_values($factors);
$this->api->output->add_handler('loginform', array($this, 'auth_form'));
$this->api->output->add_handler('loginform', [$this, 'auth_form']);
// focus the code input field on load
$this->api->output->add_script('$("input.kolab2facode").first().select();', 'docready');
@ -202,7 +199,7 @@ class kolab_2fa extends rcube_plugin
// try to verify each configured factor
foreach ($factors as $factor) {
list($method) = explode(':', $factor, 2);
[$method] = explode(':', $factor, 2);
// verify the submitted code
$code = rcube_utils::get_input_value("_${nonce}_${method}", rcube_utils::INPUT_POST);
@ -252,8 +249,7 @@ class kolab_2fa extends rcube_plugin
try {
// verify the submitted code
return $driver->verify($code, $_SESSION['kolab_2fa_time']);
}
catch (Exception $e) {
} catch (Exception $e) {
rcube::raise_error($e, true, false);
}
}
@ -264,26 +260,27 @@ class kolab_2fa extends rcube_plugin
/**
* Render 2nd factor authentication form in place of the regular login form
*/
public function auth_form($attrib = array())
public function auth_form($attrib = [])
{
$form_name = !empty($attrib['form']) ? $attrib['form'] : 'form';
$nonce = $_SESSION['kolab_2fa_nonce'];
$methods = array_unique(array_map(function($factor) {
list($method, $id) = explode(':', $factor);
$methods = array_unique(array_map(
function ($factor) {
[$method, $id] = explode(':', $factor);
return $method;
},
$this->login_factors
));
// forward these values as the regular login screen would submit them
$input_task = new html_hiddenfield(array('name' => '_task', 'value' => 'login'));
$input_action = new html_hiddenfield(array('name' => '_action', 'value' => 'plugin.kolab-2fa-login'));
$input_tzone = new html_hiddenfield(array('name' => '_timezone', 'id' => 'rcmlogintz', 'value' => rcube_utils::get_input_value('_timezone', rcube_utils::INPUT_POST)));
$input_url = new html_hiddenfield(array('name' => '_url', 'id' => 'rcmloginurl', 'value' => rcube_utils::get_input_value('_url', rcube_utils::INPUT_POST)));
$input_task = new html_hiddenfield(['name' => '_task', 'value' => 'login']);
$input_action = new html_hiddenfield(['name' => '_action', 'value' => 'plugin.kolab-2fa-login']);
$input_tzone = new html_hiddenfield(['name' => '_timezone', 'id' => 'rcmlogintz', 'value' => rcube_utils::get_input_value('_timezone', rcube_utils::INPUT_POST)]);
$input_url = new html_hiddenfield(['name' => '_url', 'id' => 'rcmloginurl', 'value' => rcube_utils::get_input_value('_url', rcube_utils::INPUT_POST)]);
// create HTML table with two cols
$table = new html_table(array('cols' => 2));
$table = new html_table(['cols' => 2]);
$required = count($methods) > 1 ? null : 'required';
$row = 0;
@ -297,14 +294,14 @@ class kolab_2fa extends rcube_plugin
}
$field_id = "rcmlogin2fa$method";
$input_code = new html_inputfield(array(
$input_code = new html_inputfield([
'name' => "_${nonce}_${method}",
'class' => 'kolab2facode',
'id' => $field_id,
'required' => $required,
'autocomplete' => 'off',
'data-icon' => 'key' // for Elastic
) + $attrib);
'data-icon' => 'key', // for Elastic
] + $attrib);
$table->add('title', html::label($field_id, html::quote($this->gettext($method))));
$table->add('input', $input_code->show(''));
}
@ -317,17 +314,19 @@ class kolab_2fa extends rcube_plugin
// add submit button
if (rcube_utils::get_boolean($attrib['submit'])) {
$out .= html::p('formbuttons', html::tag('button', array(
$out .= html::p(
'formbuttons',
html::tag('button', [
'type' => 'submit',
'id' => 'rcmloginsubmit',
'class' => 'button mainaction save',
), $this->gettext('continue'))
], $this->gettext('continue'))
);
}
// surround html output with a form tag
if (empty($attrib['form'])) {
$out = $this->api->output->form_tag(array('name' => $form_name, 'method' => 'post'), $out);
$out = $this->api->output->form_tag(['name' => $form_name, 'method' => 'post'], $out);
}
return $out;
@ -341,7 +340,7 @@ class kolab_2fa extends rcube_plugin
*/
public function get_driver($factor)
{
list($method) = explode(':', $factor, 2);
[$method] = explode(':', $factor, 2);
$rcmail = rcmail::get_instance();
@ -349,7 +348,7 @@ class kolab_2fa extends rcube_plugin
return $this->drivers[$factor];
}
$config = $rcmail->config->get('kolab_2fa_' . $method, array());
$config = $rcmail->config->get('kolab_2fa_' . $method, []);
// use product name as "issuer""
if (empty($config['issuer'])) {
@ -370,18 +369,20 @@ class kolab_2fa extends rcube_plugin
$this->drivers[$factor] = $driver;
return $driver;
}
catch (Exception $e) {
} catch (Exception $e) {
$error = strval($e);
}
rcube::raise_error(array(
rcube::raise_error(
[
'code' => 600,
'type' => 'php',
'file' => __FILE__,
'line' => __LINE__,
'message' => $error),
true, false);
'message' => $error],
true,
false
);
return false;
}
@ -396,7 +397,7 @@ class kolab_2fa extends rcube_plugin
try {
$this->storage = \Kolab2FA\Storage\Base::factory(
$rcmail->config->get('kolab_2fa_storage', 'roundcube'),
$rcmail->config->get('kolab_2fa_storage_config', array())
$rcmail->config->get('kolab_2fa_storage_config', [])
);
$this->storage->set_username($for);
@ -406,17 +407,19 @@ class kolab_2fa extends rcube_plugin
if (!empty($_SESSION['kolab_dn'])) {
$this->storage->userdn = $_SESSION['kolab_dn'];
}
}
catch (Exception $e) {
} catch (Exception $e) {
$this->storage = false;
rcube::raise_error(array(
rcube::raise_error(
[
'code' => 600,
'type' => 'php',
'file' => __FILE__,
'line' => __LINE__,
'message' => $e->getMessage()),
true, false);
'message' => $e->getMessage()],
true,
false
);
}
}
@ -429,13 +432,13 @@ class kolab_2fa extends rcube_plugin
public function settings_actions($args)
{
// register as settings action
$args['actions'][] = array(
$args['actions'][] = [
'action' => 'plugin.kolab-2fa',
'class' => 'twofactorauth',
'label' => 'settingslist',
'title' => 'settingstitle',
'domain' => 'kolab_2fa',
);
];
return $args;
}
@ -445,16 +448,16 @@ class kolab_2fa extends rcube_plugin
*/
public function settings_view()
{
$this->register_handler('plugin.settingsform', array($this, 'settings_form'));
$this->register_handler('plugin.settingslist', array($this, 'settings_list'));
$this->register_handler('plugin.factoradder', array($this, 'settings_factoradder'));
$this->register_handler('plugin.highsecuritydialog', array($this, 'settings_highsecuritydialog'));
$this->register_handler('plugin.settingsform', [$this, 'settings_form']);
$this->register_handler('plugin.settingslist', [$this, 'settings_list']);
$this->register_handler('plugin.factoradder', [$this, 'settings_factoradder']);
$this->register_handler('plugin.highsecuritydialog', [$this, 'settings_highsecuritydialog']);
$this->include_script('kolab2fa.js');
$this->include_stylesheet($this->local_skin_path() . '/kolab2fa.css');
$this->api->output->set_env('session_secured', $this->check_secure_mode());
$this->api->output->add_label('save','cancel');
$this->api->output->add_label('save', 'cancel');
$this->api->output->set_pagetitle($this->gettext('settingstitle'));
$this->api->output->send('kolab_2fa.config');
}
@ -470,7 +473,7 @@ class kolab_2fa extends rcube_plugin
$select = new html_select($attrib);
$select->add($this->gettext('addfactor') . '...', '');
foreach ((array)$rcmail->config->get('kolab_2fa_drivers', array()) as $method) {
foreach ((array)$rcmail->config->get('kolab_2fa_drivers', []) as $method) {
$select->add($this->gettext($method), $method);
}
@ -480,10 +483,10 @@ class kolab_2fa extends rcube_plugin
/**
* Render a list of active factor this user has configured
*/
public function settings_list($attrib = array())
public function settings_list($attrib = [])
{
$attrib['id'] = 'kolab2fa-factors';
$table = new html_table(array('cols' => 3));
$table = new html_table(['cols' => 3]);
$table->add_header('name', $this->gettext('factor'));
$table->add_header('created', $this->gettext('created'));
@ -495,28 +498,28 @@ class kolab_2fa extends rcube_plugin
/**
* Render the settings form template object
*/
public function settings_form($attrib = array())
public function settings_form($attrib = [])
{
$rcmail = rcmail::get_instance();
$storage = $this->get_storage($rcmail->get_user_name());
$factors = $storage ? (array)$storage->enumerate() : array();
$drivers = (array)$rcmail->config->get('kolab_2fa_drivers', array());
$factors = $storage ? (array)$storage->enumerate() : [];
$drivers = (array)$rcmail->config->get('kolab_2fa_drivers', []);
$out = '';
$env_methods = array();
$env_methods = [];
foreach ($drivers as $j => $method) {
$out .= $this->settings_factor($method, $attrib);
$env_methods[$method] = array(
$env_methods[$method] = [
'name' => $this->gettext($method),
'active' => 0,
);
];
}
$me = $this;
$factors = array_combine(
$factors,
array_map(function($id) use ($me, &$env_methods) {
$props = array('id' => $id);
array_map(function ($id) use ($me, &$env_methods) {
$props = ['id' => $id];
if ($driver = $me->get_driver($id)) {
$props += $this->format_props($driver->props());
@ -532,7 +535,7 @@ class kolab_2fa extends rcube_plugin
$this->api->output->set_env('kolab_2fa_methods', $env_methods);
$this->api->output->set_env('kolab_2fa_factors', !empty($factors) ? $factors : null);
return html::div(array('id' => 'kolab2fapropform'), $out);
return html::div(['id' => 'kolab2fapropform'], $out);
}
/**
@ -542,10 +545,10 @@ class kolab_2fa extends rcube_plugin
{
$out = '';
$rcmail = rcmail::get_instance();
$attrib += array('class' => 'propform');
$attrib += ['class' => 'propform'];
if ($driver = $this->get_driver($method)) {
$table = new html_table(array('cols' => 2, 'class' => $attrib['class']));
$table = new html_table(['cols' => 2, 'class' => $attrib['class']]);
foreach ($driver->props() as $field => $prop) {
if (!$prop['editable']) {
@ -555,20 +558,20 @@ class kolab_2fa extends rcube_plugin
switch ($prop['type']) {
case 'boolean':
case 'checkbox':
$input = new html_checkbox(array('value' => '1'));
$input = new html_checkbox(['value' => '1']);
break;
case 'enum':
case 'select':
$input = new html_select(array('disabled' => !empty($prop['readonly'])));
$input->add(array_map(array($this, 'gettext'), $prop['options']), $prop['options']);
$input = new html_select(['disabled' => !empty($prop['readonly'])]);
$input->add(array_map([$this, 'gettext'], $prop['options']), $prop['options']);
break;
default:
$input = new html_inputfield(array(
$input = new html_inputfield([
'size' => !empty($prop['size']) ? $prop['size'] : 30,
'disabled' => empty($prop['editable'])
));
'disabled' => empty($prop['editable']),
]);
}
$explain_label = $field . 'explain' . $method;
@ -576,38 +579,44 @@ class kolab_2fa extends rcube_plugin
$field_id = 'rcmk2fa' . $method . $field;
$table->add('title', html::label($field_id, $this->gettext($field)));
$table->add(null, $input->show('', array('id' => $field_id, 'name' => "_prop[$field]")) . $explain_html);
$table->add(null, $input->show('', ['id' => $field_id, 'name' => "_prop[$field]"]) . $explain_html);
}
// add row for displaying the QR code
if (method_exists($driver, 'get_provisioning_uri')) {
$gif = 'data:image/gif;base64,R0lGODlhDwAPAIAAAMDAwAAAACH5BAEAAAAALAAAAAAPAA8AQAINhI+py+0Po5y02otnAQA7';
$table->add('title', $this->gettext('qrcode'));
$table->add('pl-3 pr-3',
$table->add(
'pl-3 pr-3',
html::div('explain form-text', $this->gettext("qrcodeexplain$method"))
. html::tag('img', array('src' => $gif, 'class' => 'qrcode mt-2', 'rel' => $method))
. html::tag('img', ['src' => $gif, 'class' => 'qrcode mt-2', 'rel' => $method])
);
// add row for testing the factor
$field_id = 'rcmk2faverify' . $method;
$table->add('title', html::label($field_id, $this->gettext('verifycode')));
$table->add(null,
html::tag('input', array('type' => 'text', 'name' => '_verify_code', 'id' => $field_id, 'class' => 'k2fa-verify', 'size' => 20, 'required' => true)) .
$table->add(
null,
html::tag('input', ['type' => 'text', 'name' => '_verify_code', 'id' => $field_id, 'class' => 'k2fa-verify', 'size' => 20, 'required' => true]) .
html::div('explain form-text', $this->gettext("verifycodeexplain$method"))
);
}
$input_id = new html_hiddenfield(array('name' => '_prop[id]', 'value' => ''));
$input_id = new html_hiddenfield(['name' => '_prop[id]', 'value' => '']);
$out .= html::tag('form', array(
$out .= html::tag(
'form',
[
'method' => 'post',
'action' => '#',
'id' => 'kolab2fa-prop-' . $method,
'style' => 'display:none',
'class' => 'propform',
),
html::tag('fieldset', array(),
html::tag('legend', array(), $this->gettext($method)) .
],
html::tag(
'fieldset',
[],
html::tag('legend', [], $this->gettext($method)) .
html::div('factorprop', $table->show()) .
$input_id->show()
)
@ -620,15 +629,16 @@ class kolab_2fa extends rcube_plugin
/**
* Render the high-security-dialog content
*/
public function settings_highsecuritydialog($attrib = array())
public function settings_highsecuritydialog($attrib = [])
{
$attrib += array('id' => 'kolab2fa-highsecuritydialog');
$attrib += ['id' => 'kolab2fa-highsecuritydialog'];
$field_id = 'rcmk2facode';
$input = new html_inputfield(array('name' => '_code', 'id' => $field_id, 'class' => 'verifycode', 'size' => 20));
$label = html::label(array('for' => $field_id, 'class' => 'col-form-label col-sm-4'), '$name');
$input = new html_inputfield(['name' => '_code', 'id' => $field_id, 'class' => 'verifycode', 'size' => 20]);
$label = html::label(['for' => $field_id, 'class' => 'col-form-label col-sm-4'], '$name');
return html::div($attrib,
return html::div(
$attrib,
html::div('explain form-text', $this->gettext('highsecuritydialog'))
. html::div('propform row form-group', $label . html::div('col-sm-8', $input->show('')))
);
@ -646,30 +656,28 @@ class kolab_2fa extends rcube_plugin
$storage = $this->get_storage($rcmail->get_user_name());
$success = false;
$errors = 0;
$save_data = array();
$save_data = [];
if ($driver = $this->get_driver($method)) {
if ($data === false) {
if ($this->check_secure_mode()) {
// remove method from active factors and clear stored settings
$success = $driver->clear();
}
else {
} else {
$errors++;
}
}
else {
} else {
// verify the submitted code before saving
$verify_code = rcube_utils::get_input_value('_verify_code', rcube_utils::INPUT_POST);
$timestamp = intval(rcube_utils::get_input_value('_timestamp', rcube_utils::INPUT_POST));
if (!empty($verify_code)) {
if (!$driver->verify($verify_code, $timestamp)) {
$this->api->output->command('plugin.verify_response', array(
$this->api->output->command('plugin.verify_response', [
'id' => $driver->id,
'method' => $driver->method,
'success' => false,
'message' => str_replace('$method', $this->gettext($driver->method), $this->gettext('codeverificationfailed'))
));
'message' => str_replace('$method', $this->gettext($driver->method), $this->gettext('codeverificationfailed')),
]);
$this->api->output->send();
}
}
@ -686,9 +694,8 @@ class kolab_2fa extends rcube_plugin
// commit changes to the user properties
if (!$errors) {
if ($success = $driver->commit()) {
$save_data = $data !== false ? $this->format_props($driver->props()) : array();
}
else {
$save_data = $data !== false ? $this->format_props($driver->props()) : [];
} else {
$errors++;
}
}
@ -696,12 +703,11 @@ class kolab_2fa extends rcube_plugin
if ($success) {
$this->api->output->show_message($data === false ? $this->gettext('factorremovesuccess') : $this->gettext('factorsavesuccess'), 'confirmation');
$this->api->output->command('plugin.save_success', array(
$this->api->output->command('plugin.save_success', [
'method' => $method,
'active' => $data !== false,
'id' => $driver->id) + $save_data);
}
else if ($errors) {
'id' => $driver->id] + $save_data);
} elseif ($errors) {
$this->api->output->show_message($this->gettext('factorsaveerror'), 'error');
$this->api->output->command('plugin.reset_form', $data !== false ? $method : null);
}
@ -717,7 +723,7 @@ class kolab_2fa extends rcube_plugin
$method = rcube_utils::get_input_value('_method', rcube_utils::INPUT_POST);
if ($driver = $this->get_driver($method)) {
$data = array('method' => $method, 'id' => $driver->id);
$data = ['method' => $method, 'id' => $driver->id];
foreach ($driver->props(true) as $field => $prop) {
$data[$field] = $prop['text'] ?: $prop['value'];
@ -733,11 +739,10 @@ class kolab_2fa extends rcube_plugin
->setSize(240)
->setPadding(10)
->setErrorCorrection('high')
->setForegroundColor(array('r' => 0, 'g' => 0, 'b' => 0, 'a' => 0))
->setBackgroundColor(array('r' => 255, 'g' => 255, 'b' => 255, 'a' => 0));
->setForegroundColor(['r' => 0, 'g' => 0, 'b' => 0, 'a' => 0])
->setBackgroundColor(['r' => 255, 'g' => 255, 'b' => 255, 'a' => 0]);
$data['qrcode'] = base64_encode($qr->get());
}
catch (Exception $e) {
} catch (Exception $e) {
rcube::raise_error($e, true, false);
}
}
@ -776,12 +781,15 @@ class kolab_2fa extends rcube_plugin
$_SESSION['kolab_2fa_secure_mode'] = time();
}
$this->api->output->command('plugin.verify_response', array(
$this->api->output->command('plugin.verify_response', [
'method' => $method,
'success' => $success,
'message' => str_replace('$method', $this->gettext($method),
$this->gettext($success ? 'codeverificationpassed' : 'codeverificationfailed'))
));
'message' => str_replace(
'$method',
$this->gettext($method),
$this->gettext($success ? 'codeverificationpassed' : 'codeverificationfailed')
),
]);
$this->api->output->send();
}
@ -792,7 +800,7 @@ class kolab_2fa extends rcube_plugin
protected function format_props($props)
{
$rcmail = rcmail::get_instance();
$values = array();
$values = [];
foreach ($props as $key => $prop) {
switch ($prop['type']) {

View file

@ -29,47 +29,47 @@ abstract class Base
public $id;
public $storage;
protected $config = array();
protected $props = array();
protected $user_props = array();
protected $config = [];
protected $props = [];
protected $user_props = [];
protected $pending_changes = false;
protected $temporary = false;
protected $allowed_props = array('username');
protected $allowed_props = ['username'];
public $user_settings = array(
'active' => array(
public $user_settings = [
'active' => [
'type' => 'boolean',
'editable' => false,
'hidden' => false,
'default' => false,
),
'label' => array(
],
'label' => [
'type' => 'text',
'editable' => true,
'label' => 'label',
'generator' => 'default_label',
),
'created' => array(
],
'created' => [
'type' => 'datetime',
'editable' => false,
'hidden' => false,
'label' => 'created',
'generator' => 'time',
),
);
],
];
/**
* Static factory method
*/
public static function factory($id, $config)
{
list($method) = explode(':', $id);
[$method] = explode(':', $id);
$classmap = array(
$classmap = [
'totp' => '\\Kolab2FA\\Driver\\TOTP',
'hotp' => '\\Kolab2FA\\Driver\\HOTP',
'yubikey' => '\\Kolab2FA\\Driver\\Yubikey',
);
];
$cls = $classmap[strtolower($method)];
if ($cls && class_exists($cls)) {
@ -88,8 +88,7 @@ abstract class Base
if (!empty($id) && $id != $this->method) {
$this->id = $id;
}
else { // generate random ID
} else { // generate random ID
$this->id = $this->method . ':' . bin2hex(openssl_random_pseudo_bytes(12));
$this->temporary = true;
}
@ -117,27 +116,27 @@ abstract class Base
*
* @return bool True if valid, false otherwise
*/
abstract function verify($code, $timestamp = null);
abstract public function verify($code, $timestamp = null);
/**
* Getter for user-visible properties
*/
public function props($force = false)
{
$data = array();
$data = [];
foreach ($this->user_settings as $key => $p) {
if (!empty($p['private'])) {
continue;
}
$data[$key] = array(
$data[$key] = [
'type' => $p['type'],
'editable' => $p['editable'] ?? false,
'hidden' => $p['hidden'] ?? false,
'label' => $p['label'] ?? '',
'value' => $this->get($key, $force),
);
];
// format value into text
switch ($p['type']) {
@ -152,6 +151,7 @@ abstract class Base
break;
}
// no break
default:
$data[$key]['text'] = $data[$key]['value'];
}
@ -171,12 +171,12 @@ abstract class Base
public function generate_secret($length = 16)
{
// Base32 characters
$chars = array(
$chars = [
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 7
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23
'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31
);
];
$secret = '';
for ($i = 0; $i < $length; $i++) {
@ -211,7 +211,7 @@ abstract class Base
if (!isset($value) && $force && !empty($this->user_settings[$key]['generator'])) {
$func = $this->user_settings[$key]['generator'];
if (is_string($func) && !is_callable($func)) {
$func = array($this, $func);
$func = [$this, $func];
}
if (is_callable($func)) {
$value = call_user_func($func);
@ -220,8 +220,7 @@ abstract class Base
$this->set_user_prop($key, $value);
}
}
}
else {
} else {
$value = $this->props[$key] ?? null;
}
@ -243,9 +242,8 @@ abstract class Base
$setter = 'set_' . $key;
if (method_exists($this, $setter)) {
call_user_func(array($this, $setter), $value);
}
else if (in_array($key, $this->allowed_props)) {
call_user_func([$this, $setter], $value);
} elseif (in_array($key, $this->allowed_props)) {
$this->props[$key] = $value;
}

View file

@ -4,5 +4,4 @@ namespace Kolab2FA\Driver;
class Exception extends \Exception
{
}

View file

@ -27,11 +27,11 @@ class HOTP extends Base
{
public $method = 'hotp';
protected $config = array(
protected $config = [
'digits' => 6,
'window' => 4,
'digest' => 'sha1',
);
];
protected $backend;
@ -42,22 +42,22 @@ class HOTP extends Base
{
parent::init($config);
$this->user_settings += array(
'secret' => array(
$this->user_settings += [
'secret' => [
'type' => 'text',
'private' => true,
'label' => 'secret',
'generator' => 'generate_secret',
),
'counter' => array(
],
'counter' => [
'type' => 'integer',
'editable' => false,
'hidden' => true,
'generator' => 'random_counter',
),
);
],
];
if (!in_array($this->config['digest'], array('md5', 'sha1', 'sha256', 'sha512'))) {
if (!in_array($this->config['digest'], ['md5', 'sha1', 'sha256', 'sha512'])) {
throw new \Exception("'{$this->config['digest']}' digest is not supported.");
}
@ -106,8 +106,7 @@ class HOTP extends Base
// store incremented counter value
$this->set('counter', $this->backend->getCounter());
$this->commit();
}
catch (\Exception $e) {
} catch (\Exception $e) {
// LOG: exception
// rcube::console("VERIFY HOTP: $this->id, " . strval($e));
$pass = false;

View file

@ -27,11 +27,11 @@ class TOTP extends Base
{
public $method = 'totp';
protected $config = array(
protected $config = [
'digits' => 6,
'interval' => 30,
'digest' => 'sha1',
);
];
protected $backend;
@ -42,16 +42,16 @@ class TOTP extends Base
{
parent::init($config);
$this->user_settings += array(
'secret' => array(
$this->user_settings += [
'secret' => [
'type' => 'text',
'private' => true,
'label' => 'secret',
'generator' => 'generate_secret',
),
);
],
];
if (!in_array($this->config['digest'], array('md5', 'sha1', 'sha256', 'sha512'))) {
if (!in_array($this->config['digest'], ['md5', 'sha1', 'sha256', 'sha512'])) {
throw new \Exception("'{$this->config['digest']}' digest is not supported.");
}

View file

@ -36,13 +36,13 @@ class Yubikey extends Base
{
parent::init($config);
$this->user_settings += array(
'yubikeyid' => array(
$this->user_settings += [
'yubikeyid' => [
'type' => 'text',
'editable' => true,
'label' => 'secret',
),
);
],
];
// initialize validator
$this->backend = new \Yubikey\Validate($this->config['apikey'], $this->config['clientid']);
@ -76,8 +76,7 @@ class Yubikey extends Base
try {
$response = $this->backend->check($code);
$pass = $response->success() === true;
}
catch (\Exception $e) {
} catch (\Exception $e) {
// TODO: log exception
}
}
@ -99,8 +98,7 @@ class Yubikey extends Base
// TODO: report error
return false;
}
}
catch (\Exception $e) {
} catch (\Exception $e) {
return false;
}

View file

@ -24,7 +24,7 @@
namespace Kolab2FA\Log;
use \rcube;
use rcube;
class RcubeLogger implements Logger
{
@ -55,26 +55,25 @@ class RcubeLogger implements Logger
}
switch ($level) {
case LOG_DEBUG:
case LOG_INFO:
case LOG_NOTICE:
if ($level >= $this->level) {
rcube::write_log($this->name ?: 'console', $message);
}
break;
case LOG_DEBUG:
case LOG_INFO:
case LOG_NOTICE:
if ($level >= $this->level) {
rcube::write_log($this->name ?: 'console', $message);
}
break;
case LOG_EMERG:
case LOG_ALERT:
case LOG_CRIT:
case LOG_ERR:
case LOG_WARNING:
rcube::raise_error(array(
'code' => 600,
'type' => 'php',
'message' => $message,
), true, false);
break;
case LOG_EMERG:
case LOG_ALERT:
case LOG_CRIT:
case LOG_ERR:
case LOG_WARNING:
rcube::raise_error([
'code' => 600,
'type' => 'php',
'message' => $message,
], true, false);
break;
}
}
}

View file

@ -24,7 +24,7 @@
namespace Kolab2FA\Log;
use \rcube;
use rcube;
class Syslog implements Logger
{

View file

@ -23,13 +23,12 @@
namespace Kolab2FA\Storage;
use \Kolab2FA\Log;
use Kolab2FA\Log;
abstract class Base
{
public $username = null;
protected $config = array();
protected $config = [];
protected $logger;
/**
@ -37,11 +36,11 @@ abstract class Base
*/
public static function factory($backend, $config)
{
$classmap = array(
$classmap = [
'ldap' => '\\Kolab2FA\\Storage\\LDAP',
'roundcube' => '\\Kolab2FA\\Storage\\RcubeUser',
'rcubeuser' => '\\Kolab2FA\\Storage\\RcubeUser',
);
];
$cls = $classmap[strtolower($backend)];
if ($cls && class_exists($cls)) {
@ -73,7 +72,7 @@ abstract class Base
}
/**
*
*
*/
public function set_logger(Log\Logger $logger)
{
@ -81,8 +80,7 @@ abstract class Base
if (!empty($this->config['debug'])) {
$this->logger->set_level(LOG_DEBUG);
}
else if (!empty($this->config['loglevel'])) {
} elseif (!empty($this->config['loglevel'])) {
$this->logger->set_level($this->config['loglevel']);
}
}

View file

@ -4,5 +4,4 @@ namespace Kolab2FA\Storage;
class Exception extends \Exception
{
}

View file

@ -23,15 +23,15 @@
namespace Kolab2FA\Storage;
use \Net_LDAP3;
use \Kolab2FA\Log\Logger;
use Net_LDAP3;
use Kolab2FA\Log\Logger;
class LDAP extends Base
{
public $userdn;
private $cache = array();
private $ldapcache = array();
private $cache = [];
private $ldapcache = [];
private $conn;
private $error;
private $ready = false;
@ -42,7 +42,7 @@ class LDAP extends Base
parent::init($config);
$this->conn = new Net_LDAP3($config);
$this->conn->config_set('log_hook', array($this, 'log'));
$this->conn->config_set('log_hook', [$this, 'log']);
$this->conn->connect();
@ -62,12 +62,12 @@ class LDAP extends Base
*/
public function enumerate($active = true)
{
$filter = $this->parse_vars($this->config['filter'], '*');
$filter = $this->parse_vars($this->config['filter'], '*');
$base_dn = $this->parse_vars($this->config['base_dn'], '*');
$scope = $this->config['scope'] ?: 'sub';
$ids = array();
$ids = [];
if ($this->ready && ($result = $this->conn->search($base_dn, $filter, $scope, array($this->config['fieldmap']['id'], $this->config['fieldmap']['active'])))) {
if ($this->ready && ($result = $this->conn->search($base_dn, $filter, $scope, [$this->config['fieldmap']['id'], $this->config['fieldmap']['active']]))) {
foreach ($result as $dn => $entry) {
$rec = $this->field_mapping($dn, Net_LDAP3::normalize_entry($entry, true));
if (!empty($rec['id']) && ($active === null || $active == $rec['active'])) {
@ -99,19 +99,18 @@ class LDAP extends Base
public function write($key, $value)
{
$success = false;
$ldap_attrs = array();
$ldap_attrs = [];
if (is_array($value)) {
// add some default values
$value += (array)$this->config['defaults'] + array('active' => false, 'username' => $this->username, 'userdn' => $this->userdn);
$value += (array)$this->config['defaults'] + ['active' => false, 'username' => $this->username, 'userdn' => $this->userdn];
foreach ($value as $k => $val) {
if ($attr = $this->config['fieldmap'][$k]) {
$ldap_attrs[$attr] = $this->value_mapping($k, $val, false);
}
}
}
else {
} else {
// invalid data structure
return false;
}
@ -125,12 +124,12 @@ class LDAP extends Base
$success = !empty($result);
}
// insert new record
else if ($this->ready) {
elseif ($this->ready) {
$entry_dn = $this->get_entry_dn($this->username, $key);
// add object class attribute
$me = $this;
$ldap_attrs['objectclass'] = array_map(function($cls) use ($me, $key) {
$ldap_attrs['objectclass'] = array_map(function ($cls) use ($me, $key) {
return $me->parse_vars($cls, $key);
}, (array)$this->config['objectclass']);
@ -139,7 +138,7 @@ class LDAP extends Base
if ($success) {
$this->cache[$key] = $value;
$this->ldapcache = array();
$this->ldapcache = [];
// cleanup: remove disabled/inactive/temporary entries
if ($value['active']) {
@ -185,8 +184,8 @@ class LDAP extends Base
parent::set_username($username);
// reset cached values
$this->cache = array();
$this->ldapcache = array();
$this->cache = [];
$this->ldapcache = [];
}
/**
@ -198,7 +197,7 @@ class LDAP extends Base
return false;
}
$auth_roles = array();
$auth_roles = [];
foreach ($this->enumerate(true) as $id) {
foreach ($this->config['user_roles'] as $prefix => $role) {
if (strpos($id, $prefix) === 0) {
@ -208,12 +207,12 @@ class LDAP extends Base
}
$role_attr = $this->config['fieldmap']['roles'] ?: 'nsroledn';
if ($user_attrs = $this->conn->get_entry($this->userdn, array($role_attr))) {
if ($user_attrs = $this->conn->get_entry($this->userdn, [$role_attr])) {
$internals = array_values($this->config['user_roles']);
$new_attrs = $old_attrs = Net_LDAP3::normalize_entry($user_attrs);
$new_attrs[$role_attr] = array_merge(
array_unique($auth_roles),
array_filter((array)$old_attrs[$role_attr], function($f) use ($internals) { return !in_array($f, $internals); })
array_filter((array)$old_attrs[$role_attr], function ($f) use ($internals) { return !in_array($f, $internals); })
);
$result = $this->conn->modify_entry($this->userdn, $old_attrs, $new_attrs);
@ -231,7 +230,7 @@ class LDAP extends Base
$entry_dn = $this->get_entry_dn($user, $key);
if (!isset($this->ldapcache[$entry_dn])) {
$this->ldapcache[$entry_dn] = array();
$this->ldapcache[$entry_dn] = [];
if ($this->ready && ($entry = $this->conn->get_entry($entry_dn, array_values($this->config['fieldmap'])))) {
$this->ldapcache[$entry_dn] = $this->field_mapping($entry_dn, Net_LDAP3::normalize_entry($entry, true));
@ -263,8 +262,7 @@ class LDAP extends Base
$attr_lc = strtolower($attr);
if (isset($entry[$attr_lc])) {
$entry[$field] = $this->value_mapping($field, $entry[$attr_lc], true);
}
else if (isset($entry[$attr])) {
} elseif (isset($entry[$attr])) {
$entry[$field] = $this->value_mapping($field, $entry[$attr], true);
}
}
@ -283,11 +281,10 @@ class LDAP extends Base
}
if (is_array($value)) {
$value = array_filter(array_map(function($val) use ($map) {
$value = array_filter(array_map(function ($val) use ($map) {
return $map[$val];
}, $value));
}
else {
} else {
$value = $map[$value];
}
}
@ -317,9 +314,8 @@ class LDAP extends Base
$user = $this->username;
if (strpos($user, '@') > 0) {
list($u, $d) = explode('@', $user);
}
else if ($this->userdn) {
[$u, $d] = explode('@', $user);
} elseif ($this->userdn) {
$u = $this->userdn;
$d = trim(str_replace(',dc=', '.', substr($u, strpos($u, ',dc='))), '.');
}
@ -343,7 +339,7 @@ class LDAP extends Base
}
}
$replaces = array('%dc' => $dc, '%d' => $d ?? '', '%fu' => $user, '%u' => $u ?? '', '%c' => $class);
$replaces = ['%dc' => $dc, '%d' => $d ?? '', '%fu' => $user, '%u' => $u ?? '', '%c' => $class];
return strtr($str, $replaces);
}

View file

@ -23,17 +23,17 @@
namespace Kolab2FA\Storage;
use \rcmail;
use \rcube_user;
use rcmail;
use rcube_user;
class RcubeUser extends Base
{
// sefault config
protected $config = array(
'keymap' => array(),
);
protected $config = [
'keymap' => [],
];
private $cache = array();
private $cache = [];
private $user;
public function init(array $config)
@ -50,12 +50,12 @@ class RcubeUser extends Base
public function enumerate()
{
if ($factors = $this->get_factors()) {
return array_keys(array_filter($factors, function($prop) {
return array_keys(array_filter($factors, function ($prop) {
return !empty($prop['active']);
}));
}
return array();
return [];
}
/**
@ -86,7 +86,7 @@ class RcubeUser extends Base
$factors[$key] = $value;
$pkey = $this->key2property('blob');
$save_data = array($pkey => $factors);
$save_data = [$pkey => $factors];
$update_index = false;
// remove entry
@ -95,8 +95,8 @@ class RcubeUser extends Base
$update_index = true;
}
// remove non-active entries
else if (!empty($value['active'])) {
$factors = array_filter($factors, function($prop) {
elseif (!empty($value['active'])) {
$factors = array_filter($factors, function ($prop) {
return !empty($prop['active']);
});
$update_index = true;
@ -105,7 +105,7 @@ class RcubeUser extends Base
// update the index of active factors
if ($update_index) {
$save_data[$this->key2property('factors')] = array_keys(
array_filter($factors, function($prop) {
array_filter($factors, function ($prop) {
return !empty($prop['active']);
})
);
@ -139,7 +139,7 @@ class RcubeUser extends Base
parent::set_username($username);
// reset cached values
$this->cache = array();
$this->cache = [];
$this->user = null;
}

View file

@ -4,4 +4,4 @@
$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));
$config['activesync_force_subscriptions'] = ['windowsoutlook15' => ['INBOX' => 1, 'Sent' => 1, 'Trash' => 1, 'Calendar' => 1, 'Contacts' => 1, 'Tasks' => 1]];

View file

@ -34,8 +34,8 @@ class kolab_activesync extends rcube_plugin
private $folder_meta;
private $root_meta;
const ROOT_MAILBOX = 'INBOX';
const ASYNC_KEY = '/private/vendor/kolab/activesync';
public const ROOT_MAILBOX = 'INBOX';
public const ASYNC_KEY = '/private/vendor/kolab/activesync';
/**
@ -47,12 +47,12 @@ class kolab_activesync extends rcube_plugin
$this->require_plugin('libkolab');
$this->register_action('plugin.activesync', array($this, 'config_view'));
$this->register_action('plugin.activesync-config', array($this, 'config_frame'));
$this->register_action('plugin.activesync-json', array($this, 'json_command'));
$this->register_action('plugin.activesync', [$this, 'config_view']);
$this->register_action('plugin.activesync-config', [$this, 'config_frame']);
$this->register_action('plugin.activesync-json', [$this, 'json_command']);
$this->add_hook('settings_actions', array($this, 'settings_actions'));
$this->add_hook('folder_form', array($this, 'folder_form'));
$this->add_hook('settings_actions', [$this, 'settings_actions']);
$this->add_hook('folder_form', [$this, 'folder_form']);
$this->add_texts('localization/');
@ -65,15 +65,15 @@ class kolab_activesync extends rcube_plugin
/**
* Adds Activesync section in Settings
*/
function settings_actions($args)
public function settings_actions($args)
{
$args['actions'][] = array(
$args['actions'][] = [
'action' => 'plugin.activesync',
'class' => 'activesync',
'label' => 'tabtitle',
'domain' => 'kolab_activesync',
'title' => 'activesynctitle',
);
];
return $args;
}
@ -82,7 +82,7 @@ class kolab_activesync extends rcube_plugin
* Handler for folder info/edit form (folder_form hook).
* Adds ActiveSync section.
*/
function folder_form($args)
public function folder_form($args)
{
$mbox_imap = $args['options']['name'] ?? '';
@ -98,8 +98,8 @@ class kolab_activesync extends rcube_plugin
return $args;
}
list($type, ) = explode('.', (string) kolab_storage::folder_type($mbox_imap));
if ($type && !in_array($type, array('mail', 'event', 'contact', 'task', 'note'))) {
[$type, ] = explode('.', (string) kolab_storage::folder_type($mbox_imap));
if ($type && !in_array($type, ['mail', 'event', 'contact', 'task', 'note'])) {
return $args;
}
@ -107,10 +107,10 @@ class kolab_activesync extends rcube_plugin
$this->ui = new kolab_activesync_ui($this);
if ($content = $this->ui->folder_options_table($mbox_imap, $devices, $type)) {
$args['form']['activesync'] = array(
$args['form']['activesync'] = [
'name' => $this->gettext('tabtitle'),
'content' => $content,
);
];
}
return $args;
@ -125,68 +125,70 @@ class kolab_activesync extends rcube_plugin
$imei = rcube_utils::get_input_value('id', rcube_utils::INPUT_POST);
switch ($cmd) {
case 'save':
$devices = $this->list_devices();
$device = $devices[$imei];
$subscriptions = (array) rcube_utils::get_input_value('subscribed', rcube_utils::INPUT_POST);
$devicealias = rcube_utils::get_input_value('devicealias', rcube_utils::INPUT_POST, true);
$device['ALIAS'] = $devicealias;
case 'save':
$devices = $this->list_devices();
$device = $devices[$imei];
$subscriptions = (array) rcube_utils::get_input_value('subscribed', rcube_utils::INPUT_POST);
$devicealias = rcube_utils::get_input_value('devicealias', rcube_utils::INPUT_POST, true);
$device['ALIAS'] = $devicealias;
$err = !$this->device_update($device, $imei);
$err = !$this->device_update($device, $imei);
if (!$err) {
// iterate over folders list and update metadata if necessary
// old subscriptions
foreach (array_keys($this->folder_meta()) as $folder) {
$err |= !$this->folder_set($folder, $imei, intval($subscriptions[$folder]));
unset($subscriptions[$folder]);
}
// new subscription
foreach ($subscriptions as $folder => $flag) {
$err |= !$this->folder_set($folder, $imei, intval($flag));
if (!$err) {
// iterate over folders list and update metadata if necessary
// old subscriptions
foreach (array_keys($this->folder_meta()) as $folder) {
$err |= !$this->folder_set($folder, $imei, intval($subscriptions[$folder]));
unset($subscriptions[$folder]);
}
// new subscription
foreach ($subscriptions as $folder => $flag) {
$err |= !$this->folder_set($folder, $imei, intval($flag));
}
$this->rc->output->command('plugin.activesync_save_complete', [
'success' => !$err, 'id' => $imei, 'alias' => rcube::Q($devicealias)]);
}
$this->rc->output->command('plugin.activesync_save_complete', array(
'success' => !$err, 'id' => $imei, 'alias' => rcube::Q($devicealias)));
}
if ($err) {
$this->rc->output->show_message($this->gettext('savingerror'), 'error');
} else {
$this->rc->output->show_message($this->gettext('successfullysaved'), 'confirmation');
}
if ($err)
$this->rc->output->show_message($this->gettext('savingerror'), 'error');
else
$this->rc->output->show_message($this->gettext('successfullysaved'), 'confirmation');
break;
break;
case 'delete':
foreach ((array) $imei as $id) {
$success = $this->device_delete($id);
}
case 'delete':
foreach ((array) $imei as $id) {
$success = $this->device_delete($id);
}
if (!empty($success)) {
$this->rc->output->show_message($this->gettext('successfullydeleted'), 'confirmation');
$this->rc->output->command('plugin.activesync_save_complete', [
'success' => true,
'delete' => true,
'id' => count($imei) > 1 ? 'ALL' : $imei[0],
]);
} else {
$this->rc->output->show_message($this->gettext('savingerror'), 'error');
}
if (!empty($success)) {
$this->rc->output->show_message($this->gettext('successfullydeleted'), 'confirmation');
$this->rc->output->command('plugin.activesync_save_complete', array(
'success' => true,
'delete' => true,
'id' => count($imei) > 1 ? 'ALL' : $imei[0],
));
}
else
$this->rc->output->show_message($this->gettext('savingerror'), 'error');
break;
break;
case 'update':
$subscription = (int) rcube_utils::get_input_value('flag', rcube_utils::INPUT_POST);
$folder = rcube_utils::get_input_value('folder', rcube_utils::INPUT_POST);
case 'update':
$subscription = (int) rcube_utils::get_input_value('flag', rcube_utils::INPUT_POST);
$folder = rcube_utils::get_input_value('folder', rcube_utils::INPUT_POST);
$err = !$this->folder_set($folder, $imei, $subscription);
$err = !$this->folder_set($folder, $imei, $subscription);
if ($err) {
$this->rc->output->show_message($this->gettext('savingerror'), 'error');
} else {
$this->rc->output->show_message($this->gettext('successfullysaved'), 'confirmation');
}
if ($err)
$this->rc->output->show_message($this->gettext('savingerror'), 'error');
else
$this->rc->output->show_message($this->gettext('successfullysaved'), 'confirmation');
break;
break;
}
$this->rc->output->send();
@ -208,7 +210,7 @@ class kolab_activesync extends rcube_plugin
$this->ui = new kolab_activesync_ui($this);
$this->register_handler('plugin.devicelist', array($this->ui, 'device_list'));
$this->register_handler('plugin.devicelist', [$this->ui, 'device_list']);
$this->rc->output->send('kolab_activesync.config');
}
@ -233,8 +235,8 @@ class kolab_activesync extends rcube_plugin
return $this->ui->init_message();
}
$this->register_handler('plugin.deviceconfigform', array($this->ui, 'device_config_form'));
$this->register_handler('plugin.foldersubscriptions', array($this->ui, 'folder_subscriptions'));
$this->register_handler('plugin.deviceconfigform', [$this->ui, 'device_config_form']);
$this->register_handler('plugin.foldersubscriptions', [$this->ui, 'folder_subscriptions']);
$imei = rcube_utils::get_input_value('_id', rcube_utils::INPUT_GPC);
$devices = $this->list_devices();
@ -243,9 +245,8 @@ class kolab_activesync extends rcube_plugin
$this->ui->device = $device;
$this->ui->device['_id'] = $imei;
$this->rc->output->set_env('active_device', $imei);
$this->rc->output->command('parent.enable_command','plugin.delete-device', true);
}
else {
$this->rc->output->command('parent.enable_command', 'plugin.delete-device', true);
} else {
$this->rc->output->show_message($this->gettext('devicenotfound'), 'error');
}
@ -276,9 +277,8 @@ class kolab_activesync extends rcube_plugin
// @TODO: consider server annotation instead of INBOX
if ($meta = $storage->get_metadata(self::ROOT_MAILBOX, self::ASYNC_KEY)) {
$this->root_meta = $this->unserialize_metadata($meta[self::ROOT_MAILBOX][self::ASYNC_KEY]);
}
else {
$this->root_meta = array();
} else {
$this->root_meta = [];
}
}
@ -286,7 +286,7 @@ class kolab_activesync extends rcube_plugin
return $this->root_meta['DEVICE'];
}
return array();
return [];
}
/**
@ -297,7 +297,7 @@ class kolab_activesync extends rcube_plugin
public function folder_meta()
{
if (!isset($this->folder_meta)) {
$this->folder_meta = array();
$this->folder_meta = [];
$storage = $this->rc->get_storage();
// get folders activesync config
@ -332,17 +332,17 @@ class kolab_activesync extends rcube_plugin
$metadata = $this->folder_meta();
$metadata = $metadata[$name];
if ($flag) {
if ($flag) {
if (empty($metadata)) {
$metadata = array();
$metadata = [];
}
if (empty($metadata['FOLDER'])) {
$metadata['FOLDER'] = array();
$metadata['FOLDER'] = [];
}
if (empty($metadata['FOLDER'][$deviceid])) {
$metadata['FOLDER'][$deviceid] = array();
$metadata['FOLDER'][$deviceid] = [];
}
// Z-Push uses:
@ -376,8 +376,8 @@ class kolab_activesync extends rcube_plugin
$storage = $this->rc->get_storage();
return $storage->set_metadata($name, array(
self::ASYNC_KEY => $this->serialize_metadata($metadata)));
return $storage->set_metadata($name, [
self::ASYNC_KEY => $this->serialize_metadata($metadata)]);
}
/**
@ -406,7 +406,7 @@ class kolab_activesync extends rcube_plugin
$metadata = $this->root_meta;
$metadata['DEVICE'][$id] = $device;
$metadata = array(self::ASYNC_KEY => $this->serialize_metadata($metadata));
$metadata = [self::ASYNC_KEY => $this->serialize_metadata($metadata)];
$storage = $this->rc->get_storage();
$result = $storage->set_metadata(self::ROOT_MAILBOX, $metadata);
@ -445,7 +445,7 @@ class kolab_activesync extends rcube_plugin
}
$metadata = $this->serialize_metadata($this->root_meta);
$metadata = array(self::ASYNC_KEY => $metadata);
$metadata = [self::ASYNC_KEY => $metadata];
$storage = $this->rc->get_storage();
// update meta data
@ -455,8 +455,9 @@ class kolab_activesync extends rcube_plugin
// remove device annotation for every folder
foreach ($this->folder_meta() as $folder => $meta) {
// skip root folder (already handled above)
if ($folder == self::ROOT_MAILBOX)
if ($folder == self::ROOT_MAILBOX) {
continue;
}
if (!empty($meta['FOLDER']) && isset($meta['FOLDER'][$id])) {
unset($meta['FOLDER'][$id]);
@ -470,7 +471,7 @@ class kolab_activesync extends rcube_plugin
$meta = null;
}
$metadata = array(self::ASYNC_KEY => $this->serialize_metadata($meta));
$metadata = [self::ASYNC_KEY => $this->serialize_metadata($meta)];
$res = $storage->set_metadata($folder, $metadata);
if ($res && $meta) {
@ -484,8 +485,11 @@ class kolab_activesync extends rcube_plugin
$table = $db->table_name('syncroton_device');
if (in_array($table, $db->list_tables())) {
$db->query("DELETE FROM $table WHERE owner_id = ? AND deviceid = ?",
$this->rc->user->ID, $id);
$db->query(
"DELETE FROM $table WHERE owner_id = ? AND deviceid = ?",
$this->rc->user->ID,
$id
);
}
}
@ -505,12 +509,15 @@ class kolab_activesync extends rcube_plugin
$table = $db->table_name('syncroton_device');
if (in_array($table, $db->list_tables())) {
$fields = array('devicetype', 'acsversion', 'useragent', 'friendlyname', 'os',
'oslanguage', 'phonenumber');
$fields = ['devicetype', 'acsversion', 'useragent', 'friendlyname', 'os',
'oslanguage', 'phonenumber'];
$result = $db->query("SELECT " . $db->array2list($fields, 'ident')
$result = $db->query(
"SELECT " . $db->array2list($fields, 'ident')
. " FROM $table WHERE owner_id = ? AND id = ?",
$this->rc->user->ID, $id);
$this->rc->user->ID,
$id
);
if ($result && ($sql_arr = $db->fetch_assoc($result))) {
return $sql_arr;

View file

@ -25,14 +25,14 @@
class kolab_activesync_ui
{
public $device = [];
public $device = [];
private $rc;
private $plugin;
private $force_subscriptions = [];
private $skin_path;
const SETUP_URL = 'https://kb.kolabenterprise.com/documentation/setting-up-an-activesync-client';
public const SETUP_URL = 'https://kb.kolabenterprise.com/documentation/setting-up-an-activesync-client';
public function __construct($plugin)
@ -131,9 +131,8 @@ class kolab_activesync_ui
foreach ($this->plugin->list_folders() as $folder) {
if (!empty($folder_types[$folder])) {
list($type, ) = explode('.', $folder_types[$folder]);
}
else {
[$type, ] = explode('.', $folder_types[$folder]);
} else {
$type = 'mail';
}
@ -142,7 +141,7 @@ class kolab_activesync_ui
if ($device_force_subscriptions && array_key_exists($folder, $device_force_subscriptions)) {
$subscribed[$folder] = intval($device_force_subscriptions[$folder]);
} else if (!empty($folder_meta[$folder]['FOLDER'][$imei]['S'])) {
} elseif (!empty($folder_meta[$folder]['FOLDER'][$imei]['S'])) {
$subscribed[$folder] = intval($folder_meta[$folder]['FOLDER'][$imei]['S']);
}
}
@ -161,8 +160,7 @@ class kolab_activesync_ui
if ($use_fieldsets) {
$html .= html::tag('fieldset', 'subscriptionblock', html::tag('legend', $type, $label) . $table);
}
else {
} else {
$html .= html::div('subscriptionblock', html::tag('h3', $type, $label) . $table);
}
}
@ -177,19 +175,21 @@ class kolab_activesync_ui
$alarms = ($attrib['type'] == 'event' || $attrib['type'] == 'task');
$table = new html_table(['cellspacing' => 0, 'class' => 'table-striped']);
$table->add_header([
$table->add_header(
[
'class' => 'subscription checkbox-cell',
'title' => $this->plugin->gettext('synchronize'),
'tabindex' => 0
'tabindex' => 0,
],
!empty($attrib['syncicon']) ? html::img(['src' => $this->skin_path . $attrib['syncicon']]) : $this->plugin->gettext('synchronize')
);
if ($alarms) {
$table->add_header([
$table->add_header(
[
'class' => 'alarm checkbox-cell',
'title' => $this->plugin->gettext('withalarms'),
'tabindex' => 0
'tabindex' => 0,
],
!empty($attrib['alarmicon']) ? html::img(['src' => $this->skin_path . $attrib['alarmicon']]) : $this->plugin->gettext('withalarms')
);
@ -205,12 +205,12 @@ class kolab_activesync_ui
$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--) {
if (strpos($foldername, $names[$i].' &raquo; ') === 0) {
$length = strlen($names[$i].' &raquo; ');
for ($i = count($names) - 1; $i >= 0; $i--) {
if (strpos($foldername, $names[$i] . ' &raquo; ') === 0) {
$length = strlen($names[$i] . ' &raquo; ');
$prefix = substr($foldername, 0, $length);
$count = count(explode(' &raquo; ', $prefix));
$foldername = str_repeat('&nbsp;&nbsp;', $count-1) . '&raquo; ' . substr($foldername, $length);
$foldername = str_repeat('&nbsp;&nbsp;', $count - 1) . '&raquo; ' . substr($foldername, $length);
break;
}
}
@ -232,15 +232,17 @@ class kolab_activesync_ui
$table->add('subscription checkbox-cell', $checkbox_sync->show(
!empty($subscribed[$folder]) ? $folder : null,
['value' => $folder, 'id' => $folder_id, 'disabled' => $disabled]));
['value' => $folder, 'id' => $folder_id, 'disabled' => $disabled]
));
if ($alarms) {
$table->add('alarm checkbox-cell', $checkbox_alarm->show(
intval($subscribed[$folder] ?? 0) > 1 ? $folder : null,
['value' => $folder, 'id' => $folder_id.'_alarm', 'disabled' => $disabled]));
['value' => $folder, 'id' => $folder_id . '_alarm', 'disabled' => $disabled]
));
}
$table->add(join(' ', $classes), html::label($folder_id, $foldername));
$table->add(implode(' ', $classes), html::label($folder_id, $foldername));
}
return $table->show();
@ -252,13 +254,13 @@ class kolab_activesync_ui
$meta = $this->plugin->folder_meta();
$folder_data = (array) ($meta[$folder_name] ? $meta[$folder_name]['FOLDER'] : null);
$table = new html_table(array('cellspacing' => 0, 'id' => 'folder-sync-options', 'class' => 'records-table'));
$table = new html_table(['cellspacing' => 0, 'id' => 'folder-sync-options', 'class' => 'records-table']);
// table header
$table->add_header(array('class' => 'device'), $this->plugin->gettext('devicealias'));
$table->add_header(array('class' => 'subscription'), $this->plugin->gettext('synchronize'));
$table->add_header(['class' => 'device'], $this->plugin->gettext('devicealias'));
$table->add_header(['class' => 'subscription'], $this->plugin->gettext('synchronize'));
if ($alarms) {
$table->add_header(array('class' => 'alarm'), $this->plugin->gettext('withalarms'));
$table->add_header(['class' => 'alarm'], $this->plugin->gettext('withalarms'));
}
// table records
@ -266,8 +268,8 @@ class kolab_activesync_ui
$info = $this->plugin->device_info($device['ID']);
$name = $id;
$title = '';
$checkbox = new html_checkbox(array('name' => "_subscriptions[$id]", 'value' => 1,
'onchange' => 'return activesync_object.update_sync_data(this)'));
$checkbox = new html_checkbox(['name' => "_subscriptions[$id]", 'value' => 1,
'onchange' => 'return activesync_object.update_sync_data(this)']);
if (!empty($info)) {
$_name = trim($info['friendlyname'] . ' ' . $info['os']);
@ -281,14 +283,14 @@ class kolab_activesync_ui
$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, array('disabled' => $disabled)));
$table->add(['class' => 'device', 'title' => $title], $name);
$table->add('subscription checkbox-cell', $checkbox->show(!empty($folder_data[$id]['S']) ? 1 : 0, ['disabled' => $disabled]));
if ($alarms) {
$checkbox_alarm = new html_checkbox(array('name' => "_alarms[$id]", 'value' => 1,
'onchange' => 'return activesync_object.update_sync_data(this)'));
$checkbox_alarm = new html_checkbox(['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, array('disabled' => $disabled)));
$table->add('alarm checkbox-cell', $checkbox_alarm->show($folder_data[$id]['S'] > 1 ? 1 : 0, ['disabled' => $disabled]));
}
}
@ -298,13 +300,13 @@ class kolab_activesync_ui
/**
* Displays initial page (when no devices are registered)
*/
function init_message()
public function init_message()
{
$this->plugin->load_config();
$this->rc->output->add_handlers(array(
'initmessage' => array($this, 'init_message_content')
));
$this->rc->output->add_handlers([
'initmessage' => [$this, 'init_message_content'],
]);
$this->rc->output->send('kolab_activesync.configempty');
}
@ -312,11 +314,11 @@ class kolab_activesync_ui
/**
* Handler for initmessage template object
*/
function init_message_content()
public function init_message_content()
{
$url = $this->rc->config->get('activesync_setup_url', self::SETUP_URL);
$vars = array('url' => $url);
$msg = $this->plugin->gettext(array('name' => 'nodevices', 'vars' => $vars));
$vars = ['url' => $url];
$msg = $this->plugin->gettext(['name' => 'nodevices', 'vars' => $vars]);
return $msg;
}

View file

@ -1,3 +1,3 @@
<?php
$labels['task'] = 'Задачи';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'Activesync';
$labels['devices'] = 'Устройства';
$labels['devicealias'] = 'Име на устройство';
@ -19,4 +20,3 @@ $labels['notsupported'] = 'Your server does not support metadata/annotations';
$labels['devicedeleteconfirm'] = 'Наистина ли искате да изтриете конфигурацията за това устройство?';
$labels['successfullydeleted'] = 'Конфигурацията за устройството беше премахната успешно';
$labels['devicenotfound'] = 'Невъзможно прочитането на конфигурацията на устройството';
?>

View file

@ -1,6 +1,6 @@
<?php
$labels['contact'] = 'Contacts';
$labels['event'] = 'Calendaris';
$labels['task'] = 'Tasques';
$labels['savingdata'] = 'S\'estan desant les dades...';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'Activesync';
$labels['activesynctitle'] = 'Správa zařízení Avtivesync';
$labels['devices'] = 'Zařízení';
@ -30,4 +31,3 @@ $labels['os'] = 'Operační systém';
$labels['oslanguage'] = 'Jazyk operačního systému';
$labels['phonenumber'] = 'Telefonní číslo';
$labels['arialabeldeviceframe'] = 'Nastavení synchronizace zařízení';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'Activesync';
$labels['activesynctitle'] = 'Manage Activesync devices';
$labels['devices'] = 'Enheder';
@ -30,4 +31,3 @@ $labels['os'] = 'Operativsystem';
$labels['oslanguage'] = 'Sprog for OS';
$labels['phonenumber'] = 'Telefonnummer';
$labels['arialabeldeviceframe'] = 'Device synchronization settings form';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'ActiveSync';
$labels['activesynctitle'] = 'Verwalte ActiveSync-Geräte';
$labels['devices'] = 'Geräte';
@ -30,4 +31,3 @@ $labels['os'] = 'Betriebssystem';
$labels['oslanguage'] = 'Betriebssystemsprache';
$labels['phonenumber'] = 'Telefonnummer';
$labels['arialabeldeviceframe'] = 'Formular für die Einstellungen zur Gerätesynchronisation';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'Activesync';
$labels['activesynctitle'] = 'Verwalte ActiveSync-Geräte';
$labels['devices'] = 'Geräte';
@ -30,4 +31,3 @@ $labels['os'] = 'Betriebssystem';
$labels['oslanguage'] = 'Betriebssystemsprache';
$labels['phonenumber'] = 'Telefonnummer';
$labels['arialabeldeviceframe'] = 'Formular für die Einstellungen zur Gerätesynchronisation';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'ActiveSync';
$labels['activesynctitle'] = 'Verwalte ActiveSync-Geräte';
$labels['devices'] = 'Geräte';
@ -30,4 +31,3 @@ $labels['os'] = 'Betriebssystem';
$labels['oslanguage'] = 'Betriebssystemsprache';
$labels['phonenumber'] = 'Telefonnummer';
$labels['arialabeldeviceframe'] = 'Formular für die Einstellungen zur Gerätesynchronisation';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'Activesync';
$labels['activesynctitle'] = 'Διαχείριση συσκευών Activesync';
$labels['devices'] = 'Συσκευές';
@ -27,4 +28,3 @@ $labels['os'] = 'Λειτουργικό σύστημα';
$labels['oslanguage'] = 'Γλώσσα λειτουργικού συστήματος';
$labels['phonenumber'] = 'Αριθμός τηλεφώνου';
$labels['arialabeldeviceframe'] = 'Ρυθμίσεις συγχρονισμού συσκευής από';
?>

View file

@ -31,5 +31,3 @@ $labels['os'] = 'Operating system';
$labels['oslanguage'] = 'OS language';
$labels['phonenumber'] = 'Phone number';
$labels['arialabeldeviceframe'] = 'Device synchronization settings form';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'Activesync';
$labels['activesynctitle'] = 'Administrar dispositivos Activesync';
$labels['devices'] = 'Dispositivos';
@ -30,4 +31,3 @@ $labels['os'] = 'Sistema operativo';
$labels['oslanguage'] = 'Idioma del SO';
$labels['phonenumber'] = 'Número de teléfono';
$labels['arialabeldeviceframe'] = 'Formulario de configuración de sincronización del dispositivo';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'Activesync';
$labels['activesynctitle'] = 'Administrar dispositivos ActiveSync';
$labels['devices'] = 'Dispositivos';
@ -30,4 +31,3 @@ $labels['os'] = 'Sistema operativo';
$labels['oslanguage'] = 'Idioma del SI';
$labels['phonenumber'] = 'Número de teléfono';
$labels['arialabeldeviceframe'] = 'Formulario de configuración de sincronización de dispositivos';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['devices'] = 'Seadmed';
$labels['devicealias'] = 'Seadme nimi';
$labels['synchronize'] = 'Sünkrooni';
@ -17,4 +18,3 @@ $labels['friendlyname'] = 'Inimsõbralik nimi';
$labels['os'] = 'Operatsioonisüsteem';
$labels['oslanguage'] = 'OS-i keel';
$labels['phonenumber'] = 'Telefoninumber';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'Activesync';
$labels['activesynctitle'] = 'Hallitse Activesync-laitteita';
$labels['devices'] = 'Laitteet';
@ -30,4 +31,3 @@ $labels['os'] = 'Käyttöjärjestelmä';
$labels['oslanguage'] = 'Käyttöjärjestelmän kieli';
$labels['phonenumber'] = 'Puhelinnumero';
$labels['arialabeldeviceframe'] = 'Laitesynkronointiasetusten lomake';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'Activesync';
$labels['activesynctitle'] = 'Gestion des périphériques Activesync';
$labels['devices'] = 'Périphériques';
@ -30,4 +31,3 @@ $labels['os'] = 'Système d\'exploitation';
$labels['oslanguage'] = 'Langue de l\'OS';
$labels['phonenumber'] = 'Numéro de téléphone';
$labels['arialabeldeviceframe'] = 'Paramètres de synchronisation du périphérique';
?>

View file

@ -1,3 +1,3 @@
<?php
$labels['event'] = 'Kalendari';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'Activesync';
$labels['activesynctitle'] = 'Manage Activesync devices';
$labels['devices'] = 'Készülékek';
@ -29,4 +30,3 @@ $labels['os'] = 'Operációs rendszer';
$labels['oslanguage'] = 'Készülék nyelve';
$labels['phonenumber'] = 'Telefonszám';
$labels['arialabeldeviceframe'] = 'Device synchronization settings form';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'Activesync';
$labels['activesynctitle'] = 'Gestisci dispositivi Activesync';
$labels['devices'] = 'Dispositivi';
@ -29,4 +30,3 @@ $labels['os'] = 'Sistema operativo';
$labels['oslanguage'] = 'Lingua SO';
$labels['phonenumber'] = 'Numero di telefono';
$labels['arialabeldeviceframe'] = 'Modulo impostazioni di sincronizzazione del dispositivo';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'アクティブシンク';
$labels['activesynctitle'] = 'アクティブシンクデバイス管理';
$labels['devices'] = '機器';
@ -30,4 +31,3 @@ $labels['os'] = 'OS';
$labels['oslanguage'] = 'OS言語';
$labels['phonenumber'] = '電話番号';
$labels['arialabeldeviceframe'] = 'デバイス同期設定元';
?>

View file

@ -1,4 +1,4 @@
<?php
$labels['event'] = '캘린더';
$labels['savingdata'] = '자료 저장중...';
?>

View file

@ -1,6 +1,6 @@
<?php
$labels['devices'] = 'Ierīces';
$labels['mail'] = 'E-pasts';
$labels['event'] = 'Kalendāri';
$labels['savingdata'] = 'Saglabājam...';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'Activesync';
$labels['activesynctitle'] = 'Activesync-apparaten beheren';
$labels['devices'] = 'Apparaten';
@ -30,4 +31,3 @@ $labels['os'] = 'Besturingssysteem';
$labels['oslanguage'] = 'Taal van besturingssysteem';
$labels['phonenumber'] = 'Telefoonnummer';
$labels['arialabeldeviceframe'] = 'Formulier met instellingen voor synchronisatie van apparaat';
?>

View file

@ -1,5 +1,5 @@
<?php
$labels['event'] = 'Kalendarze';
$labels['task'] = 'Zadania';
$labels['savingdata'] = 'Zapisuję dane...';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'ActiveSync';
$labels['activesynctitle'] = 'Zarządzaj urządzeniami ActiveSync';
$labels['devices'] = 'Urządzenia';
@ -30,4 +31,3 @@ $labels['os'] = 'System operacyjny';
$labels['oslanguage'] = 'Język systemu';
$labels['phonenumber'] = 'Numer telefonu';
$labels['arialabeldeviceframe'] = 'Formularz ustawień synchronizacji urządzenia';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'Activesync';
$labels['devices'] = 'Dispositivos';
$labels['devicealias'] = 'Nome do dispositivo';
@ -20,4 +21,3 @@ $labels['devicedeleteconfirm'] = 'Você deseja realmente remover a configuraçã
$labels['successfullydeleted'] = 'A configuração do dispositivo foi removida com sucesso';
$labels['devicenotfound'] = 'Não foi possível ler a configuração do dispositivo';
$labels['phonenumber'] = 'Telefone';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'Activesync';
$labels['activesynctitle'] = 'Gerir dispositivos Activesync';
$labels['devices'] = 'Dispostivos';
@ -16,4 +17,3 @@ $labels['configuration'] = 'Configuração';
$labels['deletedevice'] = 'Remover dispositivo';
$labels['savingdata'] = 'A guardar os dados...';
$labels['savingerror'] = 'Falha ao guardar as alterações.';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'Activesync';
$labels['activesynctitle'] = 'Управление устройствами ActiveSync';
$labels['devices'] = 'Устройства';
@ -30,4 +31,3 @@ $labels['os'] = 'Операционная система';
$labels['oslanguage'] = 'Язык ОС';
$labels['phonenumber'] = 'Телефон';
$labels['arialabeldeviceframe'] = 'Форма управления настройками синхронизации';
?>

View file

@ -1,3 +1,3 @@
<?php
$labels['event'] = 'Kalendáre';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['mail'] = 'Email';
$labels['contact'] = 'Kontakti';
$labels['event'] = 'Koledarji';
@ -6,4 +7,3 @@ $labels['task'] = 'Naloge';
$labels['note'] = 'Zapiski';
$labels['configuration'] = 'Nastavitve';
$labels['savingdata'] = 'Shranjujem...';
?>

View file

@ -1,8 +1,8 @@
<?php
$labels['contact'] = 'Kontakter';
$labels['event'] = 'Kalendrar';
$labels['task'] = 'Uppgifter';
$labels['note'] = 'Anteckningar';
$labels['configuration'] = 'Konfiguration';
$labels['savingdata'] = 'Sparar data ...';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'Activesync';
$labels['activesynctitle'] = 'Hantera Activesync-enheter';
$labels['devices'] = 'Enheter';
@ -30,4 +31,3 @@ $labels['os'] = 'Operativsystem';
$labels['oslanguage'] = 'OS-språk';
$labels['phonenumber'] = 'Telefonnummer';
$labels['arialabeldeviceframe'] = 'Inställningsformulär för enhetssynkronisering';
?>

View file

@ -1,4 +1,5 @@
<?php
$labels['tabtitle'] = 'Activesync';
$labels['activesynctitle'] = 'จัดการอุปกรณ์ที่ใช้ Activesync';
$labels['devices'] = 'อุปกรณ์';
@ -27,4 +28,3 @@ $labels['os'] = 'ระบบปฎิบัติการ';
$labels['oslanguage'] = 'ภาษาของระบบปฎิบัติการ';
$labels['phonenumber'] = 'หมายเลขโทรศัพท์';
$labels['arialabeldeviceframe'] = 'ฟอร์มการตั้งค่าการปรับปรุงให้สอดคล้องของอุปกรณ์';
?>

View file

@ -1,7 +1,7 @@
<?php
$labels['mail'] = 'Пошта';
$labels['event'] = 'Календарі';
$labels['task'] = 'Задачі';
$labels['note'] = 'Нотатки';
$labels['savingdata'] = 'Збереження даних...';
?>

View file

@ -1,7 +1,7 @@
<?php
$labels['activesynctitle'] = '管理Activesync设备';
$labels['devices'] = '设备';
$labels['mail'] = '邮件';
$labels['note'] = '笔记';
$labels['savingdata'] = '保存数据...';
?>

Some files were not shown because too many files have changed in this diff Show more