Branch 'roundcubemail-plugins-kolab-3.0' - 38 commits - plugins/calendar plugins/kolab_activesync plugins/kolab_addressbook plugins/kolab_auth plugins/kolab_delegation plugins/kolab_folders plugins/libcalendaring plugins/libkolab plugins/owncloud plugins/tasklist .tx/config
Aleksander Machniak
machniak at kolabsys.com
Fri Jun 21 11:24:39 CEST 2013
.tx/config | 2
plugins/calendar/calendar.php | 51 +
plugins/calendar/calendar_ui.js | 120 ++-
plugins/calendar/drivers/database/database_driver.php | 20
plugins/calendar/drivers/kolab/kolab_driver.php | 15
plugins/calendar/lib/calendar_ical.php | 33
plugins/calendar/lib/calendar_recurrence.php | 8
plugins/calendar/localization/cs_CZ.inc | 381 +++++-----
plugins/calendar/localization/de_CH.inc | 2
plugins/calendar/localization/de_DE.inc | 2
plugins/calendar/localization/en.inc | 230 ------
plugins/calendar/localization/en_US.inc | 2
plugins/calendar/localization/fr_FR.inc | 2
plugins/calendar/skins/classic/iehacks.css | 8
plugins/calendar/skins/classic/templates/calendar.html | 6
plugins/calendar/skins/classic/templates/eventedit.html | 4
plugins/calendar/skins/larry/calendar.css | 30
plugins/calendar/skins/larry/iehacks.css | 44 -
plugins/calendar/skins/larry/templates/calendar.html | 9
plugins/calendar/skins/larry/templates/eventedit.html | 6
plugins/kolab_activesync/kolab_activesync.js | 4
plugins/kolab_activesync/localization/en.inc | 33
plugins/kolab_addressbook/lib/rcube_kolab_contacts.php | 57 -
plugins/kolab_addressbook/localization/en.inc | 47 -
plugins/kolab_auth/localization/en.inc | 5
plugins/kolab_delegation/localization/en.inc | 30
plugins/kolab_folders/localization/en.inc | 26
plugins/libcalendaring/libcalendaring.js | 6
plugins/libcalendaring/localization/cs_CZ.inc | 30
plugins/libcalendaring/localization/fr_FR.inc | 30
plugins/libkolab/lib/kolab_format.php | 61 +
plugins/libkolab/lib/kolab_format_contact.php | 64 +
plugins/libkolab/lib/kolab_format_distributionlist.php | 19
plugins/libkolab/lib/kolab_format_event.php | 14
plugins/libkolab/lib/kolab_format_file.php | 17
plugins/libkolab/lib/kolab_format_journal.php | 20
plugins/libkolab/lib/kolab_format_note.php | 20
plugins/libkolab/lib/kolab_format_task.php | 4
plugins/libkolab/lib/kolab_format_xcal.php | 44 -
plugins/libkolab/lib/kolab_storage_folder.php | 36
plugins/owncloud/localization/en.inc | 6
plugins/tasklist/drivers/database/tasklist_database_driver.php | 2
plugins/tasklist/jquery.tagedit.js | 2
plugins/tasklist/localization/cs_CZ.inc | 68 +
plugins/tasklist/localization/de_CH.inc | 2
plugins/tasklist/localization/de_DE.inc | 97 +-
plugins/tasklist/localization/en.inc | 68 -
plugins/tasklist/localization/en_US.inc | 2
plugins/tasklist/skins/larry/templates/mainview.html | 10
plugins/tasklist/skins/larry/templates/taskedit.html | 12
plugins/tasklist/tasklist.js | 7
51 files changed, 834 insertions(+), 984 deletions(-)
New commits:
commit 326be4e92b978c7a3b9bc058a9edebdf0cd6be3b
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Mar 28 18:06:45 2013 +0100
Avoid duplicate entries for attendees that are already listed as organizer
diff --git a/plugins/libkolab/lib/kolab_format_xcal.php b/plugins/libkolab/lib/kolab_format_xcal.php
index b975332..68f4d0d 100644
--- a/plugins/libkolab/lib/kolab_format_xcal.php
+++ b/plugins/libkolab/lib/kolab_format_xcal.php
@@ -124,13 +124,15 @@ abstract class kolab_format_xcal extends kolab_format
for ($i=0; $i < $attvec->size(); $i++) {
$attendee = $attvec->get($i);
$cr = $attendee->contact();
- $object['attendees'][] = array(
- 'role' => $role_map[$attendee->role()],
- 'status' => $part_status_map[$attendee->partStat()],
- 'rsvp' => $attendee->rsvp(),
- 'email' => $cr->email(),
- 'name' => $cr->name(),
- );
+ if ($cr->email() != $object['organizer']['email']) {
+ $object['attendees'][] = array(
+ 'role' => $role_map[$attendee->role()],
+ 'status' => $part_status_map[$attendee->partStat()],
+ 'rsvp' => $attendee->rsvp(),
+ 'email' => $cr->email(),
+ 'name' => $cr->name(),
+ );
+ }
}
// read recurrence rule
@@ -238,7 +240,7 @@ abstract class kolab_format_xcal extends kolab_format
if ($attendee['role'] == 'ORGANIZER') {
$object['organizer'] = $attendee;
}
- else {
+ else if ($attendee['email'] != $object['organizer']['email']) {
$cr = new ContactReference(ContactReference::EmailReference, $attendee['email']);
$cr->setName($attendee['name']);
commit 0b5e5c5733832a13b9677c8a86da56bbc4828525
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Mar 27 11:15:14 2013 +0100
Fix wrong participant status mapping for event attendees (#1722)
diff --git a/plugins/libkolab/lib/kolab_format_xcal.php b/plugins/libkolab/lib/kolab_format_xcal.php
index 6dcd328..b975332 100644
--- a/plugins/libkolab/lib/kolab_format_xcal.php
+++ b/plugins/libkolab/lib/kolab_format_xcal.php
@@ -244,7 +244,7 @@ abstract class kolab_format_xcal extends kolab_format
$att = new Attendee;
$att->setContact($cr);
- $att->setPartStat($this->status_map[$attendee['status']]);
+ $att->setPartStat($this->part_status_map[$attendee['status']]);
$att->setRole($this->role_map[$attendee['role']] ? $this->role_map[$attendee['role']] : kolabformat::Required);
$att->setRSVP((bool)$attendee['rsvp']);
commit cb74b9ca4c12d5ea75f7aeaadbb0ab4a0f0c9bd4
Author: Aleksander Machniak <machniak at kolabsys.com>
Date: Fri Mar 22 13:02:21 2013 +0100
Fix title (undefined label) on more actions button
diff --git a/plugins/calendar/skins/classic/templates/calendar.html b/plugins/calendar/skins/classic/templates/calendar.html
index 0725987..80255ff 100644
--- a/plugins/calendar/skins/classic/templates/calendar.html
+++ b/plugins/calendar/skins/classic/templates/calendar.html
@@ -21,7 +21,7 @@
</div>
<div class="boxfooter">
<roundcube:button command="calendar-create" type="link" title="calendar.createcalendar" class="buttonPas addgroup" classAct="button addgroup" content=" " />
- <roundcube:button name="calendaroptionslink" id="calendaroptionslink" type="link" title="calendaractions" class="button groupactions" onclick="rcmail_ui.show_popup('calendaroptions');return false" content=" " />
+ <roundcube:button name="calendaroptionslink" id="calendaroptionslink" type="link" title="moreactions" class="button groupactions" onclick="rcmail_ui.show_popup('calendaroptions');return false" content=" " />
</div>
</div>
</div>
diff --git a/plugins/calendar/skins/larry/templates/calendar.html b/plugins/calendar/skins/larry/templates/calendar.html
index a814345..458bd2a 100644
--- a/plugins/calendar/skins/larry/templates/calendar.html
+++ b/plugins/calendar/skins/larry/templates/calendar.html
@@ -26,7 +26,7 @@
<roundcube:object name="plugin.calendar_list" id="calendarslist" class="listing" />
</div>
<div class="boxfooter">
- <roundcube:button command="calendar-create" type="link" title="calendar.createcalendar" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" content="+" /><roundcube:button name="calendaroptionslink" id="calendaroptionsmenulink" type="link" title="calendar.calendaractions" class="listbutton groupactions" onclick="UI.show_popup('calendaroptionsmenu', undefined, { above:true });return false" innerClass="inner" content="⚙" />
+ <roundcube:button command="calendar-create" type="link" title="calendar.createcalendar" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" content="+" /><roundcube:button name="calendaroptionslink" id="calendaroptionsmenulink" type="link" title="moreactions" class="listbutton groupactions" onclick="UI.show_popup('calendaroptionsmenu', undefined, { above:true });return false" innerClass="inner" content="⚙" />
</div>
</div>
</div>
commit 9fc4a17451e2e700de8e29e68033bc5479f68ca0
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Mar 21 10:02:35 2013 +0100
Adapt libkolab and kolab_addressbook to support type parameters for email addresses
diff --git a/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php b/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php
index 6e32bc7..9e3ea91 100644
--- a/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php
+++ b/plugins/kolab_addressbook/lib/rcube_kolab_contacts.php
@@ -44,7 +44,7 @@ class rcube_kolab_contacts extends rcube_addressbook
'jobtitle' => array('limit' => 1),
'organization' => array('limit' => 1),
'department' => array('limit' => 1),
- 'email' => array('subtypes' => null),
+ 'email' => array('subtypes' => array('home','work','other')),
'phone' => array(),
'address' => array('subtypes' => array('home','work','office')),
'website' => array('subtypes' => array('homepage','blog')),
@@ -1035,21 +1035,15 @@ class rcube_kolab_contacts extends rcube_addressbook
{
$record['ID'] = $this->_uid2id($record['uid']);
- if (is_array($record['phone'])) {
- $phones = $record['phone'];
- unset($record['phone']);
- foreach ((array)$phones as $i => $phone) {
- $key = 'phone' . ($phone['type'] ? ':' . $phone['type'] : '');
- $record[$key][] = $phone['number'];
- }
- }
-
- if (is_array($record['website'])) {
- $urls = $record['website'];
- unset($record['website']);
- foreach ((array)$urls as $i => $url) {
- $key = 'website' . ($url['type'] ? ':' . $url['type'] : '');
- $record[$key][] = $url['url'];
+ // convert email, website, phone values
+ foreach (array('email'=>'address', 'website'=>'url', 'phone'=>'number') as $col => $propname) {
+ if (is_array($record[$col])) {
+ $values = $record[$col];
+ unset($record[$col]);
+ foreach ((array)$values as $i => $val) {
+ $key = $col . ($val['type'] ? ':' . $val['type'] : '');
+ $record[$key][] = $val[$propname];
+ }
}
}
@@ -1093,31 +1087,22 @@ class rcube_kolab_contacts extends rcube_addressbook
else if (!$contact['uid'] && $old['uid'])
$contact['uid'] = $old['uid'];
- $contact['email'] = array_filter($this->get_col_values('email', $contact, true));
$contact['im'] = array_filter($this->get_col_values('im', $contact, true));
- $websites = array();
- $phones = array();
- $addresses = array();
-
- foreach ($this->get_col_values('website', $contact) as $type => $values) {
- foreach ((array)$values as $url) {
- if (!empty($url)) {
- $websites[] = array('url' => $url, 'type' => $type);
- }
- }
- unset($contact['website:'.$type]);
- }
-
- foreach ($this->get_col_values('phone', $contact) as $type => $values) {
- foreach ((array)$values as $phone) {
- if (!empty($phone)) {
- $phones[] = array('number' => $phone, 'type' => $type);
+ // convert email, website, phone values
+ foreach (array('email'=>'address', 'website'=>'url', 'phone'=>'number') as $col => $propname) {
+ $contact[$col] = array();
+ foreach ($this->get_col_values($col, $contact) as $type => $values) {
+ foreach ((array)$values as $val) {
+ if (!empty($val)) {
+ $contact[$col][] = array($propname => $val, 'type' => $type);
+ }
}
+ unset($contact[$col.':'.$type]);
}
- unset($contact['phone:'.$type]);
}
+ $addresses = array();
foreach ($this->get_col_values('address', $contact) as $type => $values) {
foreach ((array)$values as $adr) {
// skip empty address
@@ -1138,8 +1123,6 @@ class rcube_kolab_contacts extends rcube_addressbook
unset($contact['address:'.$type]);
}
- $contact['website'] = $websites;
- $contact['phone'] = $phones;
$contact['address'] = $addresses;
// copy meta data (starting with _) from old object
diff --git a/plugins/libkolab/lib/kolab_format_contact.php b/plugins/libkolab/lib/kolab_format_contact.php
index 2f8bd14..b350559 100644
--- a/plugins/libkolab/lib/kolab_format_contact.php
+++ b/plugins/libkolab/lib/kolab_format_contact.php
@@ -47,6 +47,12 @@ class kolab_format_contact extends kolab_format
'other' => Telephone::Textphone,
);
+ public $emailtypes = array(
+ 'home' => Email::Home,
+ 'work' => Email::Work,
+ 'other' => Email::Other,
+ );
+
public $addresstypes = array(
'home' => Address::Home,
'work' => Address::Work,
@@ -125,10 +131,21 @@ class kolab_format_contact extends kolab_format
}
$org->setRelateds($rels);
- // email, im, url
- $this->obj->setEmailAddresses(self::array2vector($object['email']));
+ // im, email, url
$this->obj->setIMaddresses(self::array2vector($object['im']));
+ if (class_exists('vectoremail')) {
+ $vemails = new vectoremail;
+ foreach ((array)$object['email'] as $email) {
+ $type = $this->emailtypes[$email['type']];
+ $vemails->push(new Email($email['address'], intval($type)));
+ }
+ }
+ else {
+ $vemails = self::array2vector(array_map(function($v){ return $v['address']; }, $object['email']));
+ }
+ $this->obj->setEmailAddresses($vemails);
+
$vurls = new vectorurl;
foreach ((array)$object['website'] as $url) {
$type = $url['type'] == 'blog' ? Url::Blog : Url::NoType;
@@ -288,8 +305,19 @@ class kolab_format_contact extends kolab_format
$this->read_relateds($org->relateds(), $object);
}
- $object['email'] = self::vector2array($this->obj->emailAddresses());
- $object['im'] = self::vector2array($this->obj->imAddresses());
+ $object['im'] = self::vector2array($this->obj->imAddresses());
+
+ $emails = $this->obj->emailAddresses();
+ if ($emails instanceof vectoremail) {
+ $emailtypes = array_flip($this->emailtypes);
+ for ($i=0; $i < $emails->size(); $i++) {
+ $email = $emails->get($i);
+ $object['email'][] = array('address' => $email->address(), 'type' => $emailtypes[$email->types()]);
+ }
+ }
+ else {
+ $object['email'] = self::vector2array($emails);
+ }
$urls = $this->obj->urls();
for ($i=0; $i < $urls->size(); $i++) {
commit 8d3efd344d3310911b51f643ce8395a50799a58d
Author: Aleksander Machniak <machniak at kolabsys.com>
Date: Fri Jun 21 11:22:42 2013 +0200
Added Czech translations
Conflicts:
plugins/calendar/localization/cs_CZ.inc
diff --git a/plugins/calendar/localization/cs_CZ.inc b/plugins/calendar/localization/cs_CZ.inc
index 5d4b950..dbc1a52 100644
--- a/plugins/calendar/localization/cs_CZ.inc
+++ b/plugins/calendar/localization/cs_CZ.inc
@@ -2,229 +2,234 @@
$labels = array();
-// preferences
+// config
$labels['default_view'] = 'Výchozà pohled';
$labels['time_format'] = 'Formát data';
$labels['timeslots'] = 'Slotů na hodinu';
$labels['first_day'] = 'Prvnà den v týdnu';
-$labels['first_hour'] = 'First hour to show';
-$labels['workinghours'] = 'Working hours';
-$labels['add_category'] = 'Add category';
-$labels['remove_category'] = 'Remove category';
-$labels['defaultcalendar'] = 'Create new events in';
-$labels['eventcoloring'] = 'Event coloring';
-$labels['coloringmode0'] = 'According to calendar';
-$labels['coloringmode1'] = 'According to category';
-$labels['coloringmode2'] = 'Calendar for outline, category for content';
-$labels['coloringmode3'] = 'Category for outline, calendar for content';
+
+// preferences
+$labels['default_view'] = 'Výchozà pohled';
+$labels['time_format'] = 'Formát Äasu';
+$labels['timeslots'] = 'Slotů na hodinu';
+$labels['first_day'] = 'Prvnà den týdne';
+$labels['first_hour'] = 'Prvnà hodina k zobrazenÃ';
+$labels['workinghours'] = 'Pracovnà hodiny';
+$labels['add_category'] = 'PÅidat kategorii';
+$labels['remove_category'] = 'Odstranit kategorii';
+$labels['defaultcalendar'] = 'VytváÅet nové události v';
+$labels['eventcoloring'] = 'Barvy událostÃ';
+$labels['coloringmode0'] = 'Podle kalendáÅe';
+$labels['coloringmode1'] = 'Podle kategorie';
+$labels['coloringmode2'] = 'KalendáŠpro orámovánÃ, kategorie pro obsah';
+$labels['coloringmode3'] = 'Kategorie pro orámovánÃ, kalendáŠpro obsah';
// calendar
$labels['calendar'] = 'KalendáÅ';
-$labels['calendars'] = 'Calendars';
+$labels['calendars'] = 'KalendáÅe';
$labels['category'] = 'Kategorie';
-$labels['categories'] = 'Categories';
-$labels['createcalendar'] = 'Create new calendar';
-$labels['editcalendar'] = 'Edit calendar properties';
-$labels['name'] = 'Name';
-$labels['color'] = 'Color';
+$labels['categories'] = 'Kategorie';
+$labels['createcalendar'] = 'VytvoÅit nový kalendáÅ';
+$labels['editcalendar'] = 'Upravit vlastnosti kalendáÅe';
+$labels['name'] = 'Název';
+$labels['color'] = 'Barva';
$labels['day'] = 'Den';
$labels['week'] = 'Týden';
$labels['month'] = 'MÄsÃc';
$labels['agenda'] = 'Agenda';
-$labels['new'] = 'New';
+$labels['new'] = 'Nová';
$labels['new_event'] = 'Nová událost';
-$labels['edit_event'] = 'Editovat událost';
-$labels['edit'] = 'Edit';
+$labels['edit_event'] = 'Upravit událost';
+$labels['edit'] = 'Upravit';
$labels['save'] = 'Uložit';
$labels['remove'] = 'Odstranit';
$labels['cancel'] = 'Storno';
-$labels['select'] = 'Select';
-$labels['print'] = 'Print';
-$labels['printtitle'] = 'Print calendars';
+$labels['select'] = 'Vybrat';
+$labels['print'] = 'Tisk';
+$labels['printtitle'] = 'Vytisknout kalendáÅe';
$labels['title'] = 'Souhrn';
$labels['description'] = 'Popis';
$labels['all-day'] = 'celý den';
$labels['export'] = 'Exportovat do ICS';
-$labels['exporttitle'] = 'Export to iCalendar';
-$labels['location'] = 'Location';
-$labels['date'] = 'Date';
-$labels['start'] = 'Start';
-$labels['end'] = 'End';
-$labels['selectdate'] = 'Choose date';
-$labels['freebusy'] = 'Show me as';
-$labels['free'] = 'Free';
-$labels['busy'] = 'Busy';
-$labels['outofoffice'] = 'Out of Office';
-$labels['tentative'] = 'Tentative';
-$labels['priority'] = 'Priority';
-$labels['sensitivity'] = 'Privacy';
-$labels['public'] = 'public';
-$labels['private'] = 'private';
-$labels['confidential'] = 'confidential';
-$labels['alarms'] = 'Reminder';
-$labels['generated'] = 'generated at';
-$labels['printdescriptions'] = 'Print descriptions';
-$labels['parentcalendar'] = 'Insert inside';
-$labels['searchearlierdates'] = '« Search for earlier events';
-$labels['searchlaterdates'] = 'Search for later events »';
-$labels['andnmore'] = '$nr more...';
-$labels['togglerole'] = 'Click to toggle role';
-$labels['createfrommail'] = 'Save as event';
-$labels['importevents'] = 'Import events';
-$labels['importrange'] = 'Events from';
-$labels['onemonthback'] = '1 month back';
-$labels['nmonthsback'] = '$nr months back';
-$labels['showurl'] = 'Show calendar URL';
-$labels['showurldescription'] = 'Use the following address to access (read only) your calendar from other applications. You can copy and paste this into any calendar software that supports the iCal format.';
+$labels['exporttitle'] = 'Exportovat souhrn do ICS';
+$labels['location'] = 'MÃsto';
+$labels['date'] = 'Datum';
+$labels['start'] = 'ZaÄátek';
+$labels['end'] = 'Konec';
+$labels['selectdate'] = 'Vyberte datum';
+$labels['freebusy'] = 'Zobrazovat Äasový úsek jako';
+$labels['free'] = 'volno';
+$labels['busy'] = 'obsazeno';
+$labels['outofoffice'] = 'mimo kanceláÅ';
+$labels['tentative'] = 'nezávaznÄ';
+$labels['priority'] = 'Priorita';
+$labels['sensitivity'] = 'SoukromÃ';
+$labels['public'] = 'veÅejné';
+$labels['private'] = 'soukromé';
+$labels['confidential'] = 'důvÄrné';
+$labels['alarms'] = 'PÅipomenutÃ';
+$labels['generated'] = 'vygenerováno';
+$labels['printdescriptions'] = 'Vytisknout popisy';
+$labels['parentcalendar'] = 'Vložit dovnitÅ';
+$labels['searchearlierdates'] = '« Hledat dÅÃvÄjÅ¡Ã události';
+$labels['searchlaterdates'] = 'Hledat pozdÄjÅ¡Ã události »';
+$labels['andnmore'] = 'dalÅ¡Ãch $nr...';
+$labels['togglerole'] = 'KliknÄte k pÅepnutà role';
+$labels['createfrommail'] = 'Uložit jako událost';
+$labels['importevents'] = 'Importovat události';
+$labels['importrange'] = 'Události od';
+$labels['onemonthback'] = '1 mÄsÃc nazpátek';
+$labels['nmonthsback'] = '$nr mÄsÃců nazpátek';
+$labels['showurl'] = 'Ukázat URL kalendáÅe';
+$labels['showurldescription'] = 'Tuto adresu použijte pro pÅÃstup (jen ke ÄtenÃ) ke kalendáÅi z jiných aplikacÃ. Můžete ji zkopÃrovat a vložit do jakéhokoli kalendáÅového softwaru, který podporuje formát iCal.';
// agenda view
-$labels['listrange'] = 'Range to display:';
-$labels['listsections'] = 'Divide into:';
-$labels['smartsections'] = 'Smart sections';
-$labels['until'] = 'until';
-$labels['today'] = 'Today';
-$labels['tomorrow'] = 'Tomorrow';
-$labels['thisweek'] = 'This week';
-$labels['nextweek'] = 'Next week';
-$labels['thismonth'] = 'This month';
-$labels['nextmonth'] = 'Next month';
-$labels['weekofyear'] = 'Week';
-$labels['pastevents'] = 'Past';
-$labels['futureevents'] = 'Future';
+$labels['listrange'] = 'Rozsah k zobrazenÃ:';
+$labels['listsections'] = 'RozdÄlit na:';
+$labels['smartsections'] = 'Chytré sekce';
+$labels['until'] = 'do';
+$labels['today'] = 'Dnes';
+$labels['tomorrow'] = 'ZÃtra';
+$labels['thisweek'] = 'Tento týden';
+$labels['nextweek'] = 'PÅÃÅ¡tà týden';
+$labels['thismonth'] = 'Tento mÄsÃc';
+$labels['nextmonth'] = 'PÅÃÅ¡tà mÄsÃc';
+$labels['weekofyear'] = 'Týden';
+$labels['pastevents'] = 'Minulost';
+$labels['futureevents'] = 'Budoucnost';
// alarm/reminder settings
-$labels['showalarms'] = 'Show alarms';
-$labels['defaultalarmtype'] = 'Default reminder setting';
-$labels['defaultalarmoffset'] = 'Default reminder time';
+$labels['showalarms'] = 'Zobrazit upozornÄnÃ';
+$labels['defaultalarmtype'] = 'Výchozà nastavenà pÅipomenutÃ';
+$labels['defaultalarmoffset'] = 'Výchozà Äas pÅipomenutÃ';
// attendees
-$labels['attendee'] = 'Participant';
+$labels['attendee'] = 'ÃÄastnÃk';
$labels['role'] = 'Role';
-$labels['availability'] = 'Avail.';
-$labels['confirmstate'] = 'Status';
-$labels['addattendee'] = 'Add participant';
-$labels['roleorganizer'] = 'Organizer';
-$labels['rolerequired'] = 'Required';
-$labels['roleoptional'] = 'Optional';
-$labels['roleresource'] = 'Resource';
-$labels['availfree'] = 'Free';
-$labels['availbusy'] = 'Busy';
-$labels['availunknown'] = 'Unknown';
-$labels['availtentative'] = 'Tentative';
-$labels['availoutofoffice'] = 'Out of Office';
-$labels['scheduletime'] = 'Find availability';
-$labels['sendinvitations'] = 'Send invitations';
-$labels['sendnotifications'] = 'Notify participants about modifications';
-$labels['sendcancellation'] = 'Notify participants about event cancellation';
-$labels['onlyworkinghours'] = 'Find availability within my working hours';
-$labels['reqallattendees'] = 'Required/all participants';
-$labels['prevslot'] = 'Previous Slot';
-$labels['nextslot'] = 'Next Slot';
-$labels['noslotfound'] = 'Unable to find a free time slot';
-$labels['invitationsubject'] = 'You\'ve been invited to "$title"';
-$labels['invitationmailbody'] = "*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees\n\nPlease find attached an iCalendar file with all the event details which you can import to your calendar application.";
-$labels['invitationattendlinks'] = "In case your email client doesn't support iTip requests you can use the following link to either accept or decline this invitation:\n\$url";
-$labels['eventupdatesubject'] = '"$title" has been updated';
-$labels['eventupdatesubjectempty'] = 'An event that concerns you has been updated';
-$labels['eventupdatemailbody'] = "*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees\n\nPlease find attached an iCalendar file with the updated event details which you can import to your calendar application.";
-$labels['eventcancelsubject'] = '"$title" has been canceled';
-$labels['eventcancelmailbody'] = "*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees\n\nThe event has been cancelled by \$organizer.\n\nPlease find attached an iCalendar file with the updated event details.";
+$labels['availability'] = 'Dost.';
+$labels['confirmstate'] = 'Stav';
+$labels['addattendee'] = 'PÅidat úÄastnÃka';
+$labels['roleorganizer'] = 'Organizátor';
+$labels['rolerequired'] = 'Povinný';
+$labels['roleoptional'] = 'Nepovinný';
+$labels['roleresource'] = 'ProstÅedek';
+$labels['availfree'] = 'volno';
+$labels['availbusy'] = 'obsazeno';
+$labels['availunknown'] = 'neznámý';
+$labels['availtentative'] = 'nezávaznÄ';
+$labels['availoutofoffice'] = 'mimo kanceláÅ';
+$labels['scheduletime'] = 'NajÃt dostupnost';
+$labels['sendinvitations'] = 'Poslat pozvánky';
+$labels['sendnotifications'] = 'UvÄdomit úÄastnÃky o zmÄnách';
+$labels['sendcancellation'] = 'UvÄdomit úÄastnÃky o zruÅ¡enà události';
+$labels['onlyworkinghours'] = 'NajÃt dostupnost v mé pracovnà dobÄ';
+$labels['reqallattendees'] = 'PovinnÃ/vÅ¡ichni úÄastnÃci';
+$labels['prevslot'] = 'PÅedchozà slot';
+$labels['nextslot'] = 'Dalšà slot';
+$labels['noslotfound'] = 'Nelze najÃt volný slot';
+$labels['invitationsubject'] = 'Byl(a) jste pozván(a) na událost "$title"';
+$labels['invitationmailbody'] = "*\$title*\n\nKdy: \$date\n\nPozváni: \$attendees\n\nPodrobnosti o události najdete v pÅiloženém souboru typu iCalendar. Můžete si ho naimportovat do kalendáÅového programu.";
+$labels['invitationattendlinks'] = "Pokud váš poÅ¡tovnà klient nepodporuje pozvánky iTip, použijte prosÃm následujÃcà odkaz k potvrzenà nebo odmÃtnutà pozvánÃ:\n\$url";
+$labels['eventupdatesubject'] = 'Událost "$title" byla aktualizována';
+$labels['eventupdatesubjectempty'] = 'Událost, která se vás týká, byla aktualizována';
+$labels['eventupdatemailbody'] = "*\$title*\n\nKdy: \$date\n\nPozváni: \$attendees\n\nPodrobnosti o aktualizované události najdete v pÅiloženém souboru typu iCalendar. Můžete si ho naimportovat do kalendáÅového programu.";
+$labels['eventcancelsubject'] = 'Událost "$title" byla zrušena';
+$labels['eventcancelmailbody'] = "*\$title*\n\nKdy: \$date\n\nPozváni: \$attendees\n\nUdálost byla zruÅ¡ena organizátorem (\$organizer).\n\nPodrobnosti najdete v pÅiloženém souboru ve formátu iCalendar.";
// invitation handling
-$labels['itipinvitation'] = 'Invitation to';
-$labels['itipupdate'] = 'Update of';
-$labels['itipcancellation'] = 'Cancelled:';
-$labels['itipreply'] = 'Reply to';
-$labels['itipaccepted'] = 'Accept';
-$labels['itiptentative'] = 'Maybe';
-$labels['itipdeclined'] = 'Decline';
-$labels['itipsubjectaccepted'] = '"$title" has been accepted by $name';
-$labels['itipsubjecttentative'] = '"$title" has been tentatively accepted by $name';
-$labels['itipsubjectdeclined'] = '"$title" has been declined by $name';
-$labels['itipmailbodyaccepted'] = "\$sender has accepted the invitation to the following event:\n\n*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees";
-$labels['itipmailbodytentative'] = "\$sender has tentatively accepted the invitation to the following event:\n\n*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees";
-$labels['itipmailbodydeclined'] = "\$sender has declined the invitation to the following event:\n\n*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees";
-$labels['itipdeclineevent'] = 'Do you want to decline your invitation to this event?';
-$labels['importtocalendar'] = 'Save to my calendar';
-$labels['removefromcalendar'] = 'Remove from my calendar';
-$labels['updateattendeestatus'] = 'Update the participant\'s status';
-$labels['acceptinvitation'] = 'Do you accept this invitation?';
-$labels['youhaveaccepted'] = 'You have accepted this invitation';
-$labels['youhavetentative'] = 'You have tentatively accepted this invitation';
-$labels['youhavedeclined'] = 'You have declined this invitation';
-$labels['notanattendee'] = 'You\'re not listed as an attendee of this event';
-$labels['eventcancelled'] = 'The event has been cancelled';
-$labels['saveincalendar'] = 'save in';
+$labels['itipinvitation'] = 'Pozvánà na událost';
+$labels['itipupdate'] = 'Aktualizace události';
+$labels['itipcancellation'] = 'Zrušeno:';
+$labels['itipreply'] = 'OdpovÄÄ na';
+$labels['itipaccepted'] = 'Potvrdit';
+$labels['itiptentative'] = 'Možná';
+$labels['itipdeclined'] = 'OdmÃtnout';
+$labels['itipsubjectaccepted'] = '$name potvrdil(a) úÄas na události "$title"';
+$labels['itipsubjecttentative'] = '$name nezávaznÄ potvrdil(a) úÄast na události "$title"';
+$labels['itipsubjectdeclined'] = '$name odmÃtl(a) úÄast na události "$title"';
+$labels['itipmailbodyaccepted'] = "\$sender pÅijal(a) pozvánà na tuto událost:\n\n*\$title*\n\nKdy: \$date\n\nPozváni: \$attendees";
+$labels['itipmailbodytentative'] = "\$sender nezávaznÄ pÅijal(a) pozvánà na tuto událost:\n\n*\$title*\n\nKdy: \$date\n\nPozváni: \$attendees";
+$labels['itipmailbodydeclined'] = "\$sender odmÃtl(a) pozvánà na tuto událost:\n\n*\$title*\n\nKdy: \$date\n\nPozváni: \$attendees";
+$labels['itipdeclineevent'] = 'Opravdu chcete odmÃtnout pozvánà na tuto událost?';
+$labels['importtocalendar'] = 'Uložit do kalendáÅe';
+$labels['removefromcalendar'] = 'Odstranit z kalendáÅe';
+$labels['updateattendeestatus'] = 'Aktualizovat stav úÄastnÃka';
+$labels['acceptinvitation'] = 'Chcete pÅijmout toto pozvánà (potvrdit úÄast)?';
+$labels['youhaveaccepted'] = 'PÅijal(a) jste toto pozvánÃ';
+$labels['youhavetentative'] = 'NezávaznÄ jste pÅijal(a) toto pozvánÃ';
+$labels['youhavedeclined'] = 'OdmÃtl(a) jste toto pozvánÃ';
+$labels['notanattendee'] = 'Nejste na seznamu úÄastnÃků této události';
+$labels['eventcancelled'] = 'Tato událost byla zrušena';
+$labels['saveincalendar'] = 'uložit do';
// event dialog tabs
$labels['tabsummary'] = 'Souhrn';
-$labels['tabrecurrence'] = 'Recurrence';
-$labels['tabattendees'] = 'Participants';
-$labels['tabattachments'] = 'Attachments';
-$labels['tabsharing'] = 'Sharing';
+$labels['tabrecurrence'] = 'OpakovánÃ';
+$labels['tabattendees'] = 'ÃÄastnÃci';
+$labels['tabattachments'] = 'PÅÃlohy';
+$labels['tabsharing'] = 'SdÃlenÃ';
// messages
-$labels['deleteventconfirm'] = 'Do you really want to delete this event?';
-$labels['deletecalendarconfirm'] = 'Do you really want to delete this calendar with all its events?';
-$labels['savingdata'] = 'Saving data...';
-$labels['errorsaving'] = 'Failed to save changes.';
-$labels['operationfailed'] = 'The requested operation failed.';
-$labels['invalideventdates'] = 'Invalid dates entered! Please check your input.';
-$labels['invalidcalendarproperties'] = 'Invalid calendar properties! Please set a valid name.';
-$labels['searchnoresults'] = 'No events found in the selected calendars.';
-$labels['successremoval'] = 'The event has been deleted successfully.';
-$labels['successrestore'] = 'The event has been restored successfully.';
-$labels['errornotifying'] = 'Failed to send notifications to event participants';
-$labels['errorimportingevent'] = 'Failed to import the event';
-$labels['newerversionexists'] = 'A newer version of this event already exists! Aborted.';
-$labels['nowritecalendarfound'] = 'No calendar found to save the event';
-$labels['importedsuccessfully'] = 'The event was successfully added to \'$calendar\'';
-$labels['attendeupdateesuccess'] = 'Successfully updated the participant\'s status';
-$labels['itipsendsuccess'] = 'Invitation sent to participants.';
-$labels['itipresponseerror'] = 'Failed to send the response to this event invitation';
-$labels['itipinvalidrequest'] = 'This invitation is no longer valid';
-$labels['sentresponseto'] = 'Successfully sent invitation response to $mailto';
-$labels['localchangeswarning'] = 'You are about to make changes that will only be reflected on your personal calendar';
-$labels['importsuccess'] = 'Successfully imported $nr events';
-$labels['importnone'] = 'No events found to be imported';
-$labels['importerror'] = 'An error occured while importing';
-$labels['aclnorights'] = 'You do not have administrator rights on this calendar.';
+$labels['deleteventconfirm'] = 'Opravdu chcete smazat tuto událost?';
+$labels['deletecalendarconfirm'] = 'Opravdu chcete smazat tento kalendáŠse všemi událostmi?';
+$labels['savingdata'] = 'Ukládám data...';
+$labels['errorsaving'] = 'Nelze uložit zmÄny.';
+$labels['operationfailed'] = 'Požavovaná operace selhala.';
+$labels['invalideventdates'] = 'Vložená data nejsou platná! Zkontrolujte prosÃm zadávané údaje.';
+$labels['invalidcalendarproperties'] = 'Neplatné vlastnosti kalendáÅe! Vložte prosÃm platné jméno.';
+$labels['searchnoresults'] = 'Ve vybraných kalendáÅÃch nebyly nalezeny žádné události.';
+$labels['successremoval'] = 'Událost byla úspÄÅ¡nÄ smazána.';
+$labels['successrestore'] = 'Událost byla úspÄÅ¡nÄ obnovena.';
+$labels['errornotifying'] = 'Nelze odeslat notifikace úÄastnÃkům události';
+$labels['errorimportingevent'] = 'Nelze naimportovat událost';
+$labels['newerversionexists'] = 'Existuje již novÄjÅ¡Ã verze této události! Operace byla zruÅ¡ena.';
+$labels['nowritecalendarfound'] = 'Nebyl nalezen žádný kalendáÅ, do kterého by Å¡lo uložit tuto událost.';
+$labels['importedsuccessfully'] = 'Událost byla úspÄÅ¡nÄ pÅidána do kalendáÅe \'$calendar\'';
+$labels['attendeupdateesuccess'] = 'Stav úÄastnÃka byl úspÄÅ¡nÄ aktualizován';
+$labels['itipsendsuccess'] = 'Pozvánky byly rozeslány úÄastnÃkům.';
+$labels['itipresponseerror'] = 'Nelze odeslat odpovÄÄ na tuto pozvánku';
+$labels['itipinvalidrequest'] = 'Tato pozvánka již nenà platná';
+$labels['sentresponseto'] = 'OdpovÄÄ na pozvánku byla úspÄÅ¡nÄ odeslána na adresu $mailto';
+$labels['localchangeswarning'] = 'Chystáte se provést zmÄny, které se projevà jen ve vaÅ¡em vlastnÃm kalendáÅi a nelze je poslat organizátorovi události.';
+$labels['importsuccess'] = 'ÃspÄÅ¡nÄ importováno $nr událostÃ';
+$labels['importnone'] = 'Nebyly nalezeny žádné události k importu';
+$labels['importerror'] = 'PÅi importu doÅ¡lo k chybÄ';
+$labels['aclnorights'] = 'Nemáte administrátorská práva k tomuto kalendáÅi.';
// recurrence form
-$labels['repeat'] = 'Repeat';
-$labels['frequency'] = 'Repeat';
-$labels['never'] = 'never';
-$labels['daily'] = 'daily';
-$labels['weekly'] = 'weekly';
-$labels['monthly'] = 'monthly';
-$labels['yearly'] = 'annually';
-$labels['every'] = 'Every';
-$labels['days'] = 'day(s)';
-$labels['weeks'] = 'week(s)';
-$labels['months'] = 'month(s)';
-$labels['years'] = 'year(s) in:';
-$labels['bydays'] = 'On';
-$labels['untildate'] = 'the';
-$labels['each'] = 'Each';
-$labels['onevery'] = 'On every';
-$labels['onsamedate'] = 'On the same date';
-$labels['forever'] = 'forever';
-$labels['recurrencend'] = 'until';
-$labels['forntimes'] = 'for $nr time(s)';
-$labels['first'] = 'first';
-$labels['second'] = 'second';
-$labels['third'] = 'third';
-$labels['fourth'] = 'fourth';
-$labels['last'] = 'last';
-$labels['dayofmonth'] = 'Day of month';
+$labels['repeat'] = 'OpakovánÃ';
+$labels['frequency'] = 'Opakovat';
+$labels['never'] = 'nikdy';
+$labels['daily'] = 'dennÄ';
+$labels['weekly'] = 'týdnÄ';
+$labels['monthly'] = 'mÄsÃÄnÄ';
+$labels['yearly'] = 'roÄnÄ';
+$labels['every'] = 'Každý';
+$labels['days'] = 'den (dny)';
+$labels['weeks'] = 'týden (týdny)';
+$labels['months'] = 'mÄsÃc(e/ů)';
+$labels['years'] = 'rok(y/ů) v:';
+$labels['bydays'] = ' ';
+$labels['untildate'] = 'do';
+$labels['each'] = 'Každý';
+$labels['onevery'] = 'Vždy v';
+$labels['onsamedate'] = 'Ve stejné datum';
+$labels['forever'] = 'trvale';
+$labels['recurrencend'] = 'do';
+$labels['forntimes'] = 'jen $nrkrát';
+$labels['first'] = 'prvnÃ';
+$labels['second'] = 'druhý';
+$labels['third'] = 'tÅetÃ';
+$labels['fourth'] = 'Ätvrtý';
+$labels['last'] = 'poslednÃ';
+$labels['dayofmonth'] = 'Den v mÄsÃci';
-$labels['changeeventconfirm'] = 'Change event';
-$labels['removeeventconfirm'] = 'Remove event';
-$labels['changerecurringeventwarning'] = 'This is a recurring event. Would you like to edit the current event only, this and all future occurences, all occurences or save it as a new event?';
-$labels['removerecurringeventwarning'] = 'This is a recurring event. Would you like to remove the current event only, this and all future occurences or all occurences of this event?';
-$labels['currentevent'] = 'Current';
-$labels['futurevents'] = 'Future';
-$labels['allevents'] = 'All';
-$labels['saveasnew'] = 'Save as new';
+$labels['changeeventconfirm'] = 'ZmÄnit událost';
+$labels['removeeventconfirm'] = 'Odstranit událost';
+$labels['changerecurringeventwarning'] = 'Toto je opakovaná událost. Chcete upravit jen toto konánÃ, toto a vÅ¡echna následujÃcà konánÃ, úplnÄ vÅ¡echna konánà nebo uložit událost jako novou?';
+$labels['removerecurringeventwarning'] = 'Toto je opakovaná událost. Chcete odstranit jen toto konánÃ, toto a následujÃcà konánà nebo úplnÄ vÅ¡echna konánà této události?';
+$labels['currentevent'] = 'AktuálnÃ';
+$labels['futurevents'] = 'BudoucÃ';
+$labels['allevents'] = 'VÅ¡echny';
+$labels['saveasnew'] = 'Uložit jako novou';
-?>
diff --git a/plugins/libcalendaring/localization/cs_CZ.inc b/plugins/libcalendaring/localization/cs_CZ.inc
new file mode 100755
index 0000000..0515e19
--- /dev/null
+++ b/plugins/libcalendaring/localization/cs_CZ.inc
@@ -0,0 +1,30 @@
+<?php
+
+$labels = array();
+
+$labels['alarmemail'] = 'Poslat e-mail';
+$labels['alarmdisplay'] = 'Zobrazit zprávu';
+$labels['alarmdisplayoption'] = 'Zpráva';
+$labels['alarmemailoption'] = 'E-mail';
+$labels['alarmat'] = '$datetime';
+$labels['trigger@'] = 'dne';
+$labels['trigger-M'] = 'minut pÅed';
+$labels['trigger-H'] = 'hodin pÅed';
+$labels['trigger-D'] = 'dnů pÅed';
+$labels['trigger+M'] = 'minut po';
+$labels['trigger+H'] = 'hodin po';
+$labels['trigger+D'] = 'dnů po';
+$labels['addalarm'] = 'pÅidat upozornÄnÃ';
+
+$labels['alarmtitle'] = 'BlÞÃcà se události';
+$labels['dismissall'] = 'Zrušit vše';
+$labels['dismiss'] = 'Zrušit';
+$labels['snooze'] = 'Odložit';
+$labels['repeatinmin'] = 'Zopakovat za $min minut';
+$labels['repeatinhr'] = 'Zopakovat za 1 hodinu';
+$labels['repeatinhrs'] = 'Zopakovat za $hrs hodin';
+$labels['repeattomorrow'] = 'Zopakovat zÃtra';
+$labels['repeatinweek'] = 'Zopakovat za týden';
+
+$labels['showmore'] = 'Ukázat vÃc...';
+
diff --git a/plugins/tasklist/localization/cs_CZ.inc b/plugins/tasklist/localization/cs_CZ.inc
new file mode 100644
index 0000000..1ad5b0b
--- /dev/null
+++ b/plugins/tasklist/localization/cs_CZ.inc
@@ -0,0 +1,68 @@
+<?php
+
+$labels = array();
+$labels['navtitle'] = 'Ãkoly';
+$labels['lists'] = 'Seznamy úkolů';
+$labels['list'] = 'Seznam úkolů';
+$labels['tags'] = 'Å tÃtky';
+
+$labels['newtask'] = 'Nový úkol';
+$labels['createnewtask'] = 'VytvoÅit nový úkol (napÅ. sobota, posekat trávnÃk)';
+$labels['createfrommail'] = 'Uložit úkol';
+$labels['mark'] = 'OznaÄit';
+$labels['unmark'] = 'OdznaÄit';
+$labels['edit'] = 'Upravit';
+$labels['delete'] = 'Smazat';
+$labels['title'] = 'Titulek';
+$labels['description'] = 'Popis';
+$labels['datetime'] = 'Konec';
+$labels['start'] = 'ZaÄátek';
+$labels['alarms'] = 'PÅipomenutÃ';
+
+$labels['all'] = 'VÅ¡echny';
+$labels['flagged'] = 'OznaÄkované';
+$labels['complete'] = 'DokonÄené';
+$labels['overdue'] = 'ZpoždÄné';
+$labels['today'] = 'Dnes';
+$labels['tomorrow'] = 'ZÃtra';
+$labels['next7days'] = 'PÅÃÅ¡tÃch 7 dnů';
+$labels['later'] = 'PozdÄji';
+$labels['nodate'] = 'Žádné datum';
+$labels['removetag'] = 'Odstranit';
+
+$labels['taskdetails'] = 'Podrobnosti';
+$labels['newtask'] = 'Nový úkol';
+$labels['edittask'] = 'Upravit úkol';
+$labels['save'] = 'Uložit';
+$labels['cancel'] = 'Storno';
+$labels['addsubtask'] = 'PÅidat podúkol';
+$labels['deletetask'] = 'Smazat úkol';
+$labels['deletethisonly'] = 'Smazat pouze tento úkol';
+$labels['deletewithchilds'] = 'Smazat se všemi podúkoly';
+
+$labels['tabsummary'] = 'Souhrn';
+$labels['tabrecurrence'] = 'OpakovánÃ';
+$labels['tabattachments'] = 'PÅÃlohy';
+$labels['tabsharing'] = 'SdÃlenÃ';
+
+$labels['editlist'] = 'Upravit seznam';
+$labels['createlist'] = 'PÅidat seznam';
+$labels['listactions'] = 'Možnosti seznamu...';
+$labels['listname'] = 'Název';
+$labels['showalarms'] = 'Ukázat upozornÄnÃ';
+$labels['import'] = 'Import';
+
+// date words
+$labels['on'] = ' ';
+$labels['at'] = ' ';
+$labels['this'] = 'tento';
+$labels['next'] = 'pÅÃÅ¡tÃ';
+
+// messages
+$labels['savingdata'] = 'Ukládám data...';
+$labels['errorsaving'] = 'Nelze uložit data.';
+$labels['notasksfound'] = 'Nebyly nalezeny žádné úkoly vyhovujÃcà daným kritériÃm';
+$labels['invalidstartduedates'] = 'PoÄáteÄnà datum nesmà být pozdÄjÅ¡Ã než koncové datum.';
+$labels['deletetasktconfirm'] = 'Opravdu chcete smazat tento úkol?';
+$labels['deleteparenttasktconfirm'] = 'Opravdu chcete smazat tento úkol a všechny jeho podúkoly?';
+$labels['deletelistconfirm'] = 'Opravdu chcete smazat tento seznam vÄetnÄ vÅ¡ech úkolů?';
commit 0768490fff69c2521cc57fe0e66a173c25b44fe4
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Mar 14 09:43:29 2013 +0100
Mention the correct RFC section for iCal value escaping
diff --git a/plugins/calendar/lib/calendar_ical.php b/plugins/calendar/lib/calendar_ical.php
index a8769bc..e4c8e74 100644
--- a/plugins/calendar/lib/calendar_ical.php
+++ b/plugins/calendar/lib/calendar_ical.php
@@ -465,7 +465,7 @@ class calendar_ical
}
/**
- * Escape values according to RFC 2426 2.5
+ * Escape values according to RFC 2445 4.3.11
*/
private function escape($str)
{
commit 39707d3458188ab26bd883e52192fcc68304f1fe
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Mar 14 09:30:12 2013 +0100
Fix iCal newline escaping (#1694) + typo
diff --git a/plugins/calendar/lib/calendar_ical.php b/plugins/calendar/lib/calendar_ical.php
index 6d7474e..a8769bc 100644
--- a/plugins/calendar/lib/calendar_ical.php
+++ b/plugins/calendar/lib/calendar_ical.php
@@ -364,7 +364,7 @@ class calendar_ical
foreach ($events as $event) {
$vevent = "BEGIN:VEVENT" . self::EOL;
- $vevent .= "UID:" . self::escpape($event['uid']) . self::EOL;
+ $vevent .= "UID:" . self::escape($event['uid']) . self::EOL;
$vevent .= $this->format_datetime("DTSTAMP", $event['changed'] ?: new DateTime(), false, true) . self::EOL;
if ($event['sequence'])
$vevent .= "SEQUENCE:" . intval($event['sequence']) . self::EOL;
@@ -379,21 +379,21 @@ class calendar_ical
$vevent .= $this->format_datetime("DTSTART", $event['start'], false) . self::EOL;
$vevent .= $this->format_datetime("DTEND", $event['end'], false) . self::EOL;
}
- $vevent .= "SUMMARY:" . self::escpape($event['title']) . self::EOL;
- $vevent .= "DESCRIPTION:" . self::escpape($event['description']) . self::EOL;
+ $vevent .= "SUMMARY:" . self::escape($event['title']) . self::EOL;
+ $vevent .= "DESCRIPTION:" . self::escape($event['description']) . self::EOL;
if (!empty($event['attendees'])){
$vevent .= $this->_get_attendees($event['attendees']);
}
if (!empty($event['location'])) {
- $vevent .= "LOCATION:" . self::escpape($event['location']) . self::EOL;
+ $vevent .= "LOCATION:" . self::escape($event['location']) . self::EOL;
}
if ($event['recurrence']) {
$vevent .= "RRULE:" . libcalendaring::to_rrule($event['recurrence'], self::EOL) . self::EOL;
}
if(!empty($event['categories'])) {
- $vevent .= "CATEGORIES:" . self::escpape(strtoupper($event['categories'])) . self::EOL;
+ $vevent .= "CATEGORIES:" . self::escape(strtoupper($event['categories'])) . self::EOL;
}
if ($event['sensitivity'] > 0) {
$vevent .= "CLASS:" . ($event['sensitivity'] == 2 ? 'CONFIDENTIAL' : 'PRIVATE') . self::EOL;
@@ -405,7 +405,7 @@ class calendar_ical
$vevent .= "BEGIN:VALARM\n";
if ($val[1]) $vevent .= "TRIGGER:" . preg_replace('/^([-+])(.+)/', '\\1PT\\2', $trigger) . self::EOL;
else $vevent .= "TRIGGER;VALUE=DATE-TIME:" . gmdate('Ymd\THis\Z', $val[0]) . self::EOL;
- if ($action) $vevent .= "ACTION:" . self::escpape(strtoupper($action)) . self::EOL;
+ if ($action) $vevent .= "ACTION:" . self::escape(strtoupper($action)) . self::EOL;
$vevent .= "END:VALARM\n";
}
@@ -421,7 +421,7 @@ class calendar_ical
$vevent .= "STATUS:TENTATIVE" . self::EOL;
foreach ((array)$event['x-custom'] as $prop)
- $vevent .= $prop[0] . ':' . $this->escpape($prop[1]) . self::EOL;
+ $vevent .= $prop[0] . ':' . self::escape($prop[1]) . self::EOL;
// TODO: export attachments
@@ -459,7 +459,7 @@ class calendar_ical
// <ATTR>;TZID=Europe/Zurich:20120706T210000
$tz = $dt->getTimezone();
$tzname = $tz ? $tz->getName() : null;
- $tzid = $tzname && $tzname != 'UTC' && $tzname != '+00:00' ? ';TZID=' . $tzname : '';
+ $tzid = $tzname && $tzname != 'UTC' && $tzname != '+00:00' ? ';TZID=' . self::escape($tzname) : '';
return $attr . $tzid . ':' . $dt->format('Ymd\THis' . ($tzid ? '' : '\Z'));
}
}
@@ -467,9 +467,9 @@ class calendar_ical
/**
* Escape values according to RFC 2426 2.5
*/
- private function escpape($str)
+ private function escape($str)
{
- return strtr($str, array('\\' => '\\\\', ';' => '\\;', ',' => '\\,'));
+ return strtr($str, array('\\' => '\\\\', "\n" => '\n', ';' => '\;', ',' => '\,'));
}
/**
commit 2068b37422d53c5a6b20aec2c4f23a7026119a8d
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Mar 14 09:28:53 2013 +0100
Don't set empty attendees array for move/resize actions; otherwise attendees are deleted
diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index a70cbdd..f2cca86 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -1286,9 +1286,10 @@ class calendar extends rcube_plugin
$event['attachments'] = $attachments;
// check for organizer in attendees
- if (!$event['attendees'])
- $event['attendees'] = array();
if ($action == 'new' || $action == 'edit') {
+ if (!$event['attendees'])
+ $event['attendees'] = array();
+
$emails = $this->get_user_emails();
$organizer = $owner = false;
foreach ((array)$event['attendees'] as $i => $attendee) {
commit 7b7b037073f59b75e5316135be3188fd60722d25
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Mar 13 15:30:12 2013 +0100
Don't display local-change warning if calendar owner is organizer; Better wording for wanring text (#1693)
diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index 95e1d53..c25cf68 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -170,19 +170,20 @@ function rcube_calendar_ui(settings)
};
// check if the current user is an attendee of this event
- var is_attendee = function(event, role)
+ var is_attendee = function(event, role, email)
{
+ var emails = email ? ';'+email : settings.identity.emails;
for (var i=0; event.attendees && i < event.attendees.length; i++) {
- if ((!role || event.attendees[i].role == role) && event.attendees[i].email && settings.identity.emails.indexOf(';'+event.attendees[i].email) >= 0)
+ if ((!role || event.attendees[i].role == role) && event.attendees[i].email && emails.indexOf(';'+event.attendees[i].email) >= 0)
return event.attendees[i];
}
return false;
};
// check if the current user is the organizer
- var is_organizer = function(event)
+ var is_organizer = function(event, email)
{
- return is_attendee(event, 'ORGANIZER') || !event.id;
+ return is_attendee(event, 'ORGANIZER', email) || !event.id;
};
var load_attachment = function(event, att)
@@ -533,7 +534,7 @@ function rcube_calendar_ui(settings)
event_attendees = [];
attendees_list = $('#edit-attendees-table > tbody').html('');
$('#edit-attendees-notify')[(notify.checked && organizer ? 'show' : 'hide')]();
- $('#edit-localchanges-warning')[(has_attendees(event) && !organizer ? 'show' : 'hide')]();
+ $('#edit-localchanges-warning')[(has_attendees(event) && !(organizer || (calendar.owner && is_organizer(event, calendar.owner))) ? 'show' : 'hide')]();
var load_attendees_tab = function()
{
diff --git a/plugins/calendar/drivers/kolab/kolab_driver.php b/plugins/calendar/drivers/kolab/kolab_driver.php
index 7be31e2..019b6d6 100644
--- a/plugins/calendar/drivers/kolab/kolab_driver.php
+++ b/plugins/calendar/drivers/kolab/kolab_driver.php
@@ -128,6 +128,7 @@ class kolab_driver extends calendar_driver
'class_name' => $cal->get_namespace(),
'default' => $cal->storage->default,
'active' => $cal->storage->is_active(),
+ 'owner' => $cal->get_owner(),
);
}
diff --git a/plugins/calendar/localization/de_CH.inc b/plugins/calendar/localization/de_CH.inc
index 0479bd0..20311a2 100644
--- a/plugins/calendar/localization/de_CH.inc
+++ b/plugins/calendar/localization/de_CH.inc
@@ -184,7 +184,7 @@ $labels['itipsendsuccess'] = 'Einladung an Teilnehmer versendet.';
$labels['itipresponseerror'] = 'Die Antwort auf diese Einladung konnte nicht versendet werden';
$labels['itipinvalidrequest'] = 'Diese Einladung ist nicht mehr gültig';
$labels['sentresponseto'] = 'Antwort auf diese Einladung erfolgreich an $mailto gesendet';
-$labels['localchangeswarning'] = 'Die Ãnderungen an diesem Termin können nur in Ihrem persönlichen Kalender gespeichert werden.';
+$labels['localchangeswarning'] = 'Ãnderungen an diesem Termin werden nur in Ihrem Kalender gespeichert und nicht an den Organisator des Termins gesendet.';
$labels['importsuccess'] = 'Es wurden $nr Termine erfolgreich importiert';
$labels['importnone'] = 'Keine Termine zum Importieren gefunden';
$labels['importerror'] = 'Fehler beim Importieren';
diff --git a/plugins/calendar/localization/de_DE.inc b/plugins/calendar/localization/de_DE.inc
index 5ad1563..a3b0058 100644
--- a/plugins/calendar/localization/de_DE.inc
+++ b/plugins/calendar/localization/de_DE.inc
@@ -184,7 +184,7 @@ $labels['itipsendsuccess'] = 'Einladung an Teilnehmer versendet.';
$labels['itipresponseerror'] = 'Die Antwort auf diese Einladung konnte nicht versendet werden';
$labels['itipinvalidrequest'] = 'Diese Einladung ist nicht mehr gültig.';
$labels['sentresponseto'] = 'Antwort auf diese Einladung erfolgreich an $mailto gesendet';
-$labels['localchangeswarning'] = 'Die Ãnderungen an diesem Termin können nur in Ihrem persönlichen Kalender gespeichert werden.';
+$labels['localchangeswarning'] = 'Ãnderungen an diesem Termin werden nur in Ihrem Kalender gespeichert und nicht an den Organisator des Termins gesendet.';
$labels['importsuccess'] = 'Es wurden $nr Termine erfolgreich importiert';
$labels['importnone'] = 'Keine Termine zum Importieren gefunden';
$labels['importerror'] = 'Fehler beim Importieren';
diff --git a/plugins/calendar/localization/en_US.inc b/plugins/calendar/localization/en_US.inc
index 6cc76d7..4164d89 100644
--- a/plugins/calendar/localization/en_US.inc
+++ b/plugins/calendar/localization/en_US.inc
@@ -184,7 +184,7 @@ $labels['itipsendsuccess'] = 'Invitation sent to participants.';
$labels['itipresponseerror'] = 'Failed to send the response to this event invitation';
$labels['itipinvalidrequest'] = 'This invitation is no longer valid';
$labels['sentresponseto'] = 'Successfully sent invitation response to $mailto';
-$labels['localchangeswarning'] = 'You are about to make changes that will only be reflected on your personal calendar';
+$labels['localchangeswarning'] = 'You are about to make changes that will only be reflected on your calendar and not be sent to the organizer of the event.';
$labels['importsuccess'] = 'Successfully imported $nr events';
$labels['importnone'] = 'No events found to be imported';
$labels['importerror'] = 'An error occured while importing';
commit 6cc6f2e33220a3e5f311b702c1729b35124d9508
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Mar 13 10:45:29 2013 +0100
Cleanup Transifex localization files. en => en_US
diff --git a/.tx/config b/.tx/config
index 94f402b..034cd6d 100644
--- a/.tx/config
+++ b/.tx/config
@@ -1,6 +1,6 @@
[main]
host = https://www.transifex.com
-lang_map = de: de_DE, es: es_ES, fr: fr_FR, ja: ja_JP, nl: nl_NL
+lang_map = en: en_US, de: de_DE, es: es_ES, fr: fr_FR, ja: ja_JP, nl: nl_NL
type = PHP_ALT_ARRAY
[kolab.calendar]
diff --git a/plugins/calendar/localization/en.inc b/plugins/calendar/localization/en.inc
deleted file mode 100644
index 6cc76d7..0000000
--- a/plugins/calendar/localization/en.inc
+++ /dev/null
@@ -1,230 +0,0 @@
-<?php
-
-$labels = array();
-
-// preferences
-$labels['default_view'] = 'Default view';
-$labels['time_format'] = 'Time format';
-$labels['timeslots'] = 'Timeslots per hour';
-$labels['first_day'] = 'First weekday';
-$labels['first_hour'] = 'First hour to show';
-$labels['workinghours'] = 'Working hours';
-$labels['add_category'] = 'Add category';
-$labels['remove_category'] = 'Remove category';
-$labels['defaultcalendar'] = 'Create new events in';
-$labels['eventcoloring'] = 'Event coloring';
-$labels['coloringmode0'] = 'According to calendar';
-$labels['coloringmode1'] = 'According to category';
-$labels['coloringmode2'] = 'Calendar for outline, category for content';
-$labels['coloringmode3'] = 'Category for outline, calendar for content';
-
-// calendar
-$labels['calendar'] = 'Calendar';
-$labels['calendars'] = 'Calendars';
-$labels['category'] = 'Category';
-$labels['categories'] = 'Categories';
-$labels['createcalendar'] = 'Create new calendar';
-$labels['editcalendar'] = 'Edit calendar properties';
-$labels['name'] = 'Name';
-$labels['color'] = 'Color';
-$labels['day'] = 'Day';
-$labels['week'] = 'Week';
-$labels['month'] = 'Month';
-$labels['agenda'] = 'Agenda';
-$labels['new'] = 'New';
-$labels['new_event'] = 'New event';
-$labels['edit_event'] = 'Edit event';
-$labels['edit'] = 'Edit';
-$labels['save'] = 'Save';
-$labels['remove'] = 'Remove';
-$labels['cancel'] = 'Cancel';
-$labels['select'] = 'Select';
-$labels['print'] = 'Print';
-$labels['printtitle'] = 'Print calendars';
-$labels['title'] = 'Summary';
-$labels['description'] = 'Description';
-$labels['all-day'] = 'all-day';
-$labels['export'] = 'Export';
-$labels['exporttitle'] = 'Export to iCalendar';
-$labels['location'] = 'Location';
-$labels['date'] = 'Date';
-$labels['start'] = 'Start';
-$labels['end'] = 'End';
-$labels['selectdate'] = 'Choose date';
-$labels['freebusy'] = 'Show me as';
-$labels['free'] = 'Free';
-$labels['busy'] = 'Busy';
-$labels['outofoffice'] = 'Out of Office';
-$labels['tentative'] = 'Tentative';
-$labels['priority'] = 'Priority';
-$labels['sensitivity'] = 'Privacy';
-$labels['public'] = 'public';
-$labels['private'] = 'private';
-$labels['confidential'] = 'confidential';
-$labels['alarms'] = 'Reminder';
-$labels['generated'] = 'generated at';
-$labels['printdescriptions'] = 'Print descriptions';
-$labels['parentcalendar'] = 'Insert inside';
-$labels['searchearlierdates'] = '« Search for earlier events';
-$labels['searchlaterdates'] = 'Search for later events »';
-$labels['andnmore'] = '$nr more...';
-$labels['togglerole'] = 'Click to toggle role';
-$labels['createfrommail'] = 'Save as event';
-$labels['importevents'] = 'Import events';
-$labels['importrange'] = 'Events from';
-$labels['onemonthback'] = '1 month back';
-$labels['nmonthsback'] = '$nr months back';
-$labels['showurl'] = 'Show calendar URL';
-$labels['showurldescription'] = 'Use the following address to access (read only) your calendar from other applications. You can copy and paste this into any calendar software that supports the iCal format.';
-
-// agenda view
-$labels['listrange'] = 'Range to display:';
-$labels['listsections'] = 'Divide into:';
-$labels['smartsections'] = 'Smart sections';
-$labels['until'] = 'until';
-$labels['today'] = 'Today';
-$labels['tomorrow'] = 'Tomorrow';
-$labels['thisweek'] = 'This week';
-$labels['nextweek'] = 'Next week';
-$labels['thismonth'] = 'This month';
-$labels['nextmonth'] = 'Next month';
-$labels['weekofyear'] = 'Week';
-$labels['pastevents'] = 'Past';
-$labels['futureevents'] = 'Future';
-
-// alarm/reminder settings
-$labels['showalarms'] = 'Show alarms';
-$labels['defaultalarmtype'] = 'Default reminder setting';
-$labels['defaultalarmoffset'] = 'Default reminder time';
-
-// attendees
-$labels['attendee'] = 'Participant';
-$labels['role'] = 'Role';
-$labels['availability'] = 'Avail.';
-$labels['confirmstate'] = 'Status';
-$labels['addattendee'] = 'Add participant';
-$labels['roleorganizer'] = 'Organizer';
-$labels['rolerequired'] = 'Required';
-$labels['roleoptional'] = 'Optional';
-$labels['roleresource'] = 'Resource';
-$labels['availfree'] = 'Free';
-$labels['availbusy'] = 'Busy';
-$labels['availunknown'] = 'Unknown';
-$labels['availtentative'] = 'Tentative';
-$labels['availoutofoffice'] = 'Out of Office';
-$labels['scheduletime'] = 'Find availability';
-$labels['sendinvitations'] = 'Send invitations';
-$labels['sendnotifications'] = 'Notify participants about modifications';
-$labels['sendcancellation'] = 'Notify participants about event cancellation';
-$labels['onlyworkinghours'] = 'Find availability within my working hours';
-$labels['reqallattendees'] = 'Required/all participants';
-$labels['prevslot'] = 'Previous Slot';
-$labels['nextslot'] = 'Next Slot';
-$labels['noslotfound'] = 'Unable to find a free time slot';
-$labels['invitationsubject'] = 'You\'ve been invited to "$title"';
-$labels['invitationmailbody'] = "*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees\n\nPlease find attached an iCalendar file with all the event details which you can import to your calendar application.";
-$labels['invitationattendlinks'] = "In case your email client doesn't support iTip requests you can use the following link to either accept or decline this invitation:\n\$url";
-$labels['eventupdatesubject'] = '"$title" has been updated';
-$labels['eventupdatesubjectempty'] = 'An event that concerns you has been updated';
-$labels['eventupdatemailbody'] = "*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees\n\nPlease find attached an iCalendar file with the updated event details which you can import to your calendar application.";
-$labels['eventcancelsubject'] = '"$title" has been canceled';
-$labels['eventcancelmailbody'] = "*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees\n\nThe event has been cancelled by \$organizer.\n\nPlease find attached an iCalendar file with the updated event details.";
-
-// invitation handling
-$labels['itipinvitation'] = 'Invitation to';
-$labels['itipupdate'] = 'Update of';
-$labels['itipcancellation'] = 'Cancelled:';
-$labels['itipreply'] = 'Reply to';
-$labels['itipaccepted'] = 'Accept';
-$labels['itiptentative'] = 'Maybe';
-$labels['itipdeclined'] = 'Decline';
-$labels['itipsubjectaccepted'] = '"$title" has been accepted by $name';
-$labels['itipsubjecttentative'] = '"$title" has been tentatively accepted by $name';
-$labels['itipsubjectdeclined'] = '"$title" has been declined by $name';
-$labels['itipmailbodyaccepted'] = "\$sender has accepted the invitation to the following event:\n\n*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees";
-$labels['itipmailbodytentative'] = "\$sender has tentatively accepted the invitation to the following event:\n\n*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees";
-$labels['itipmailbodydeclined'] = "\$sender has declined the invitation to the following event:\n\n*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees";
-$labels['itipdeclineevent'] = 'Do you want to decline your invitation to this event?';
-$labels['importtocalendar'] = 'Save to my calendar';
-$labels['removefromcalendar'] = 'Remove from my calendar';
-$labels['updateattendeestatus'] = 'Update the participant\'s status';
-$labels['acceptinvitation'] = 'Do you accept this invitation?';
-$labels['youhaveaccepted'] = 'You have accepted this invitation';
-$labels['youhavetentative'] = 'You have tentatively accepted this invitation';
-$labels['youhavedeclined'] = 'You have declined this invitation';
-$labels['notanattendee'] = 'You\'re not listed as an attendee of this event';
-$labels['eventcancelled'] = 'The event has been cancelled';
-$labels['saveincalendar'] = 'save in';
-
-// event dialog tabs
-$labels['tabsummary'] = 'Summary';
-$labels['tabrecurrence'] = 'Recurrence';
-$labels['tabattendees'] = 'Participants';
-$labels['tabattachments'] = 'Attachments';
-$labels['tabsharing'] = 'Sharing';
-
-// messages
-$labels['deleteventconfirm'] = 'Do you really want to delete this event?';
-$labels['deletecalendarconfirm'] = 'Do you really want to delete this calendar with all its events?';
-$labels['savingdata'] = 'Saving data...';
-$labels['errorsaving'] = 'Failed to save changes.';
-$labels['operationfailed'] = 'The requested operation failed.';
-$labels['invalideventdates'] = 'Invalid dates entered! Please check your input.';
-$labels['invalidcalendarproperties'] = 'Invalid calendar properties! Please set a valid name.';
-$labels['searchnoresults'] = 'No events found in the selected calendars.';
-$labels['successremoval'] = 'The event has been deleted successfully.';
-$labels['successrestore'] = 'The event has been restored successfully.';
-$labels['errornotifying'] = 'Failed to send notifications to event participants';
-$labels['errorimportingevent'] = 'Failed to import the event';
-$labels['newerversionexists'] = 'A newer version of this event already exists! Aborted.';
-$labels['nowritecalendarfound'] = 'No calendar found to save the event';
-$labels['importedsuccessfully'] = 'The event was successfully added to \'$calendar\'';
-$labels['attendeupdateesuccess'] = 'Successfully updated the participant\'s status';
-$labels['itipsendsuccess'] = 'Invitation sent to participants.';
-$labels['itipresponseerror'] = 'Failed to send the response to this event invitation';
-$labels['itipinvalidrequest'] = 'This invitation is no longer valid';
-$labels['sentresponseto'] = 'Successfully sent invitation response to $mailto';
-$labels['localchangeswarning'] = 'You are about to make changes that will only be reflected on your personal calendar';
-$labels['importsuccess'] = 'Successfully imported $nr events';
-$labels['importnone'] = 'No events found to be imported';
-$labels['importerror'] = 'An error occured while importing';
-$labels['aclnorights'] = 'You do not have administrator rights on this calendar.';
-
-// recurrence form
-$labels['repeat'] = 'Repeat';
-$labels['frequency'] = 'Repeat';
-$labels['never'] = 'never';
-$labels['daily'] = 'daily';
-$labels['weekly'] = 'weekly';
-$labels['monthly'] = 'monthly';
-$labels['yearly'] = 'annually';
-$labels['every'] = 'Every';
-$labels['days'] = 'day(s)';
-$labels['weeks'] = 'week(s)';
-$labels['months'] = 'month(s)';
-$labels['years'] = 'year(s) in:';
-$labels['bydays'] = 'On';
-$labels['untildate'] = 'the';
-$labels['each'] = 'Each';
-$labels['onevery'] = 'On every';
-$labels['onsamedate'] = 'On the same date';
-$labels['forever'] = 'forever';
-$labels['recurrencend'] = 'until';
-$labels['forntimes'] = 'for $nr time(s)';
-$labels['first'] = 'first';
-$labels['second'] = 'second';
-$labels['third'] = 'third';
-$labels['fourth'] = 'fourth';
-$labels['last'] = 'last';
-$labels['dayofmonth'] = 'Day of month';
-
-$labels['changeeventconfirm'] = 'Change event';
-$labels['removeeventconfirm'] = 'Remove event';
-$labels['changerecurringeventwarning'] = 'This is a recurring event. Would you like to edit the current event only, this and all future occurences, all occurences or save it as a new event?';
-$labels['removerecurringeventwarning'] = 'This is a recurring event. Would you like to remove the current event only, this and all future occurences or all occurences of this event?';
-$labels['currentevent'] = 'Current';
-$labels['futurevents'] = 'Future';
-$labels['allevents'] = 'All';
-$labels['saveasnew'] = 'Save as new';
-
-?>
diff --git a/plugins/kolab_activesync/localization/en.inc b/plugins/kolab_activesync/localization/en.inc
deleted file mode 100644
index 2399b13..0000000
--- a/plugins/kolab_activesync/localization/en.inc
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-$labels = array();
-$labels['tabtitle'] = 'Activesync';
-$labels['devices'] = 'Devices';
-$labels['devicealias'] = 'Device name';
-$labels['syncmode'] = 'Sync Mode';
-$labels['modeauto'] = 'Determine automatically';
-$labels['modeflat'] = 'Force flat mode';
-$labels['modefolder'] = 'Force folder mode';
-$labels['synchronize'] = 'Synchronize';
-$labels['withalarms'] = 'With alarms';
-$labels['syncsettings'] = 'Synchronization settings';
-$labels['deviceconfig'] = 'Device configration';
-$labels['folderstosync'] = 'Folders to synchronize';
-$labels['mail'] = 'Email';
-$labels['contact'] = 'Address Books';
-$labels['event'] = 'Calendars';
-$labels['task'] = 'Tasks';
-$labels['note'] = 'Notes';
-$labels['configuration'] = 'Configuration';
-$labels['deletedevice'] = 'Delete device';
-$labels['imageformat'] = 'Image format';
-$labels['laxpiclabel'] = 'Allow PNG and GIF images';
-$labels['nodevices'] = 'There are currently no devices registered.<br/><br/>In order to register a device, please connect it to the server first, using <a href="http://wiki.kolab.org/Z_push#Clients">the instructions in the Wiki</a>. Afterwards the device should become available for configuration here.';
-$labels['savingdata'] = 'Saving data...';
-$labels['savingerror'] = 'Failed to save configuration';
-$labels['notsupported'] = 'Your server does not support metadata/annotations';
-$labels['devicedeleteconfirm'] = 'Do you really want to delete the configuration for this device?';
-$labels['successfullydeleted'] = 'The device configuration was successfully removed';
-$labels['devicenotfound'] = 'Unable to read device configuration';
-
-?>
diff --git a/plugins/kolab_addressbook/localization/en.inc b/plugins/kolab_addressbook/localization/en.inc
deleted file mode 100644
index a66426f..0000000
--- a/plugins/kolab_addressbook/localization/en.inc
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-$labels = array();
-$labels['initials'] = 'Initials';
-$labels['profession'] = 'Profession';
-$labels['officelocation'] = 'Office location';
-$labels['children'] = 'Children';
-$labels['pgppublickey'] = 'PGP public key';
-$labels['pkcs7publickey'] = 'S/MIME public key';
-$labels['freebusyurl'] = 'Free-busy URL';
-$labels['typebusiness'] = 'Business';
-$labels['typebusinessfax'] = 'Business Fax';
-$labels['typecompany'] = 'Company';
-$labels['typeprimary'] = 'Primary';
-$labels['typetelex'] = 'Telex';
-$labels['typeradio'] = 'Radio';
-$labels['typeisdn'] = 'ISDN';
-$labels['typettytdd'] = 'TTY/TDD';
-$labels['typecallback'] = 'Callback';
-$labels['settings'] = 'Settings';
-
-$labels['bookcreate'] = 'Create address book';
-$labels['bookedit'] = 'Edit address book';
-$labels['bookdelete'] = 'Delete address book';
-$labels['bookproperties'] = 'Address book properties';
-$labels['bookname'] = 'Book name';
-$labels['parentbook'] = 'Superior book';
-
-$labels['addressbookprio'] = 'Address book(s) selection/behaviour';
-$labels['personalfirst'] = 'Personal address book(s) first';
-$labels['globalfirst'] = 'Global address book(s) first';
-$labels['personalonly'] = 'Personal address book(s) only';
-$labels['globalonly'] = 'Global address book(s) only';
-
-$messages['bookdeleteconfirm'] = 'Do you really want to delete the selected address book and all contacts in it?';
-$messages['bookdeleting'] = 'Deleting address book...';
-$messages['booksaving'] = 'Saving address book...';
-$messages['bookdeleted'] = 'Address book deleted successfully.';
-$messages['bookupdated'] = 'Address book updated successfully.';
-$messages['bookcreated'] = 'Address book created successfully.';
-$messages['bookdeleteerror'] = 'An error occured while deleting address book.';
-$messages['bookupdateerror'] = 'An error occured while updating address book.';
-$messages['bookcreateerror'] = 'An error occured while creating address book.';
-$messages['nobooknamewarning'] = 'Please, enter address book name.';
-$messages['noemailnamewarning'] = 'Please, enter email address or contact name.';
-
-?>
diff --git a/plugins/kolab_auth/localization/en.inc b/plugins/kolab_auth/localization/en.inc
deleted file mode 100644
index e1adb3f..0000000
--- a/plugins/kolab_auth/localization/en.inc
+++ /dev/null
@@ -1,5 +0,0 @@
-<?php
-
-$labels['loginas'] = 'Login As';
-
-?>
diff --git a/plugins/kolab_delegation/localization/en.inc b/plugins/kolab_delegation/localization/en.inc
deleted file mode 100644
index c445f7f..0000000
--- a/plugins/kolab_delegation/localization/en.inc
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-$labels = array();
-
-$labels['tabtitle'] = 'Delegation';
-$labels['delegates'] = 'Delegates';
-$labels['delegate'] = 'Delegate';
-$labels['mail'] = 'Email';
-$labels['contact'] = 'Address Books';
-$labels['event'] = 'Calendars';
-$labels['task'] = 'Tasks';
-$labels['note'] = 'Notes';
-$labels['yes'] = 'Yes';
-$labels['no'] = 'No';
-
-$labels['adddelegate'] = 'Add delegate';
-$labels['deletedelegate'] = 'Delete delegate';
-
-$labels['savingdata'] = 'Saving data...';
-$labels['delegatedeleteconfirm'] = 'Do you really want to delete this delegate?';
-$labels['delegateremoveacl'] = 'remove access rights on folders assigned to this user';
-$labels['deleteconfirm'] = 'Confirmation';
-$labels['deletesuccess'] = 'The delegate was successfully removed.';
-$labels['deleteerror'] = 'Could not remove delegate.';
-$labels['updatesuccess'] = 'The delegate was successfully updated.';
-$labels['updateerror'] = 'Could not update delegate.';
-$labels['createsuccess'] = 'The delegate was successfully added.';
-$labels['createerror'] = 'Could not add delegate.';
-
-?>
diff --git a/plugins/kolab_folders/localization/en.inc b/plugins/kolab_folders/localization/en.inc
deleted file mode 100644
index 856f59d..0000000
--- a/plugins/kolab_folders/localization/en.inc
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-
-$labels = array();
-
-$labels['folderctype'] = 'Content type';
-$labels['foldertypemail'] = 'Mail';
-$labels['foldertypeevent'] = 'Calendar'; // Events?
-$labels['foldertypejournal'] = 'Journal';
-$labels['foldertypetask'] = 'Tasks';
-$labels['foldertypenote'] = 'Notes';
-$labels['foldertypecontact'] = 'Contacts';
-$labels['foldertypeconfiguration'] = 'Configuration';
-$labels['foldertypefile'] = 'Files';
-$labels['foldertypefreebusy'] = 'Free-Busy';
-
-$labels['default'] = 'Default';
-$labels['inbox'] = 'Inbox';
-$labels['drafts'] = 'Drafts';
-$labels['sentitems'] = 'Sent';
-$labels['outbox'] = 'Outbox';
-$labels['wastebasket'] = 'Trash';
-$labels['junkemail'] = 'Junk';
-
-$messages['defaultfolderexists'] = 'There is already default folder of specified type';
-
-?>
diff --git a/plugins/owncloud/localization/en.inc b/plugins/owncloud/localization/en.inc
deleted file mode 100644
index f5cb8fb..0000000
--- a/plugins/owncloud/localization/en.inc
+++ /dev/null
@@ -1,6 +0,0 @@
-<?php
-
-$labels = array();
-$labels['owncloud'] = 'Files';
-
-?>
diff --git a/plugins/tasklist/localization/en.inc b/plugins/tasklist/localization/en.inc
deleted file mode 100644
index 7d5415a..0000000
--- a/plugins/tasklist/localization/en.inc
+++ /dev/null
@@ -1,68 +0,0 @@
-<?php
-
-$labels = array();
-$labels['navtitle'] = 'Tasks';
-$labels['lists'] = 'Tasklists';
-$labels['list'] = 'Tasklist';
-$labels['tags'] = 'Tags';
-
-$labels['newtask'] = 'New Task';
-$labels['createnewtask'] = 'Create new Task (e.g. Saturday, Mow the lawn)';
-$labels['createfrommail'] = 'Save as task';
-$labels['mark'] = 'Mark';
-$labels['unmark'] = 'Unmark';
-$labels['edit'] = 'Edit';
-$labels['delete'] = 'Delete';
-$labels['title'] = 'Title';
-$labels['description'] = 'Description';
-$labels['datetime'] = 'Date/Time';
-$labels['start'] = 'Start';
-$labels['alarms'] = 'Reminder';
-
-$labels['all'] = 'All';
-$labels['flagged'] = 'Flagged';
-$labels['complete'] = 'Complete';
-$labels['overdue'] = 'Overdue';
-$labels['today'] = 'Today';
-$labels['tomorrow'] = 'Tomorrow';
-$labels['next7days'] = 'Next 7 days';
-$labels['later'] = 'Later';
-$labels['nodate'] = 'no date';
-$labels['removetag'] = 'Remove';
-
-$labels['taskdetails'] = 'Details';
-$labels['newtask'] = 'New Task';
-$labels['edittask'] = 'Edit Task';
-$labels['save'] = 'Save';
-$labels['cancel'] = 'Cancel';
-$labels['addsubtask'] = 'Add subtask';
-$labels['deletetask'] = 'Delete task';
-$labels['deletethisonly'] = 'Delete this task only';
-$labels['deletewithchilds'] = 'Delete with all subtasks';
-
-$labels['tabsummary'] = 'Summary';
-$labels['tabrecurrence'] = 'Recurrence';
-$labels['tabattachments'] = 'Attachments';
-$labels['tabsharing'] = 'Sharing';
-
-$labels['editlist'] = 'Edit list';
-$labels['createlist'] = 'Add list';
-$labels['listactions'] = 'List options...';
-$labels['listname'] = 'Name';
-$labels['showalarms'] = 'Show alarms';
-$labels['import'] = 'Import';
-
-// date words
-$labels['on'] = 'on';
-$labels['at'] = 'at';
-$labels['this'] = 'this';
-$labels['next'] = 'next';
-
-// mesages
-$labels['savingdata'] = 'Saving data...';
-$labels['errorsaving'] = 'Failed to save data.';
-$labels['notasksfound'] = 'No tasks found for the given criteria';
-$labels['invalidstartduedates'] = 'Start date must not be greater than due date.';
-$labels['deletetasktconfirm'] = 'Do you really want to delete this task?';
-$labels['deleteparenttasktconfirm'] = 'Do you really want to delete this task and all its subtasks?';
-$labels['deletelistconfirm'] = 'Do you really want to delete this list with all its tasks?';
commit cb37ba3978a603332794a81877886918ce40db06
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Mar 13 10:43:48 2013 +0100
Better name and placement of the due date field (#1692); copied de_CH localization to de_DE
diff --git a/plugins/tasklist/localization/de_CH.inc b/plugins/tasklist/localization/de_CH.inc
index 857df01..740b0db 100644
--- a/plugins/tasklist/localization/de_CH.inc
+++ b/plugins/tasklist/localization/de_CH.inc
@@ -15,7 +15,7 @@ $labels['edit'] = 'Bearbeiten';
$labels['delete'] = 'Löschen';
$labels['title'] = 'Titel';
$labels['description'] = 'Beschreibung';
-$labels['datetime'] = 'Datum/Zeit';
+$labels['datetime'] = 'Fällig';
$labels['start'] = 'Beginn';
$labels['alarms'] = 'Erinnerung';
diff --git a/plugins/tasklist/localization/de_DE.inc b/plugins/tasklist/localization/de_DE.inc
index e8c0ada..1cbd2c0 100644
--- a/plugins/tasklist/localization/de_DE.inc
+++ b/plugins/tasklist/localization/de_DE.inc
@@ -2,67 +2,68 @@
$labels = array();
$labels['navtitle'] = 'Aufgaben';
-$labels['lists'] = 'Tasklists';
-$labels['list'] = 'Tasklist';
+$labels['lists'] = 'Aufgabenlisten';
+$labels['list'] = 'Liste';
$labels['tags'] = 'Tags';
-$labels['newtask'] = 'New Task';
-$labels['createnewtask'] = 'Create new Task (e.g. Saturday, Mow the lawn)';
-$labels['createfrommail'] = 'Save as task';
-$labels['mark'] = 'Mark';
-$labels['unmark'] = 'Unmark';
-$labels['edit'] = 'Edit';
+$labels['newtask'] = 'Neue Aufgabe';
+$labels['createnewtask'] = 'Neue Aufgabe eingeben (z.B. Samstag, Rasenmähen)';
+$labels['createfrommail'] = 'Als Aufgabe speichern';
+$labels['mark'] = 'Markieren';
+$labels['unmark'] = 'Markierung aufheben';
+$labels['edit'] = 'Bearbeiten';
$labels['delete'] = 'Löschen';
$labels['title'] = 'Titel';
-$labels['description'] = 'Description';
-$labels['datetime'] = 'Date/Time';
-$labels['start'] = 'Start';
-$labels['alarms'] = 'Reminder';
+$labels['description'] = 'Beschreibung';
+$labels['datetime'] = 'Fällig';
+$labels['start'] = 'Beginn';
+$labels['alarms'] = 'Erinnerung';
-$labels['all'] = 'All';
-$labels['flagged'] = 'Flagged';
-$labels['complete'] = 'Complete';
-$labels['overdue'] = 'Overdue';
-$labels['today'] = 'Today';
-$labels['tomorrow'] = 'Tomorrow';
-$labels['next7days'] = 'Next 7 days';
-$labels['later'] = 'Later';
-$labels['nodate'] = 'no date';
-$labels['removetag'] = 'Remove';
+$labels['all'] = 'Alle';
+$labels['flagged'] = 'Markiert';
+$labels['complete'] = 'Erledigt';
+$labels['overdue'] = 'Ãberfällig';
+$labels['today'] = 'Heute';
+$labels['tomorrow'] = 'Morgen';
+$labels['next7days'] = 'Nächste 7 Tage';
+$labels['later'] = 'Später';
+$labels['nodate'] = 'kein Datum';
+$labels['removetag'] = 'Löschen';
$labels['taskdetails'] = 'Details';
-$labels['newtask'] = 'New Task';
-$labels['edittask'] = 'Edit Task';
+$labels['newtask'] = 'Neue Aufgabe';
+$labels['edittask'] = 'Aufgabe bearbeiten';
$labels['save'] = 'Speichern';
-$labels['cancel'] = 'Cancel';
-$labels['addsubtask'] = 'Add subtask';
-$labels['deletetask'] = 'Delete task';
-$labels['deletethisonly'] = 'Delete this task only';
-$labels['deletewithchilds'] = 'Delete with all subtasks';
+$labels['cancel'] = 'Abbrechen';
+$labels['addsubtask'] = 'Neue Teilaufgabe';
+$labels['deletetask'] = 'Aufgabe löschen';
+$labels['deletethisonly'] = 'Nur diese Aufgabe löschen';
+$labels['deletewithchilds'] = 'Mit allen Teilaufhaben löschen';
-$labels['tabsummary'] = 'Summary';
-$labels['tabrecurrence'] = 'Recurrence';
-$labels['tabattachments'] = 'Attachments';
-$labels['tabsharing'] = 'Sharing';
-$labels['editlist'] = 'Edit list';
-$labels['createlist'] = 'Add list';
-$labels['listactions'] = 'List options...';
+$labels['tabsummary'] = 'Ãbersicht';
+$labels['tabrecurrence'] = 'Wiederholung';
+$labels['tabattachments'] = 'Anhänge';
+$labels['tabsharing'] = 'Freigabe';
+
+$labels['editlist'] = 'Liste bearbeiten';
+$labels['createlist'] = 'Neue Liste';
+$labels['listactions'] = 'Listenoptionen...';
$labels['listname'] = 'Name';
-$labels['showalarms'] = 'Show alarms';
-$labels['import'] = 'Import';
+$labels['showalarms'] = 'Erinnerungen anzeigen';
+$labels['import'] = 'Importieren';
// date words
-$labels['on'] = 'on';
-$labels['at'] = 'at';
-$labels['this'] = 'this';
-$labels['next'] = 'next';
+$labels['on'] = 'am';
+$labels['at'] = 'um';
+$labels['this'] = 'diesen';
+$labels['next'] = 'nächsten';
// mesages
$labels['savingdata'] = 'Daten werden gespeichert...';
-$labels['errorsaving'] = 'Failed to save data.';
-$labels['notasksfound'] = 'No tasks found for the given criteria';
-$labels['invalidstartduedates'] = 'Start date must not be greater than due date.';
-$labels['deletetasktconfirm'] = 'Do you really want to delete this task?';
-$labels['deleteparenttasktconfirm'] = 'Do you really want to delete this task and all its subtasks?';
-$labels['deletelistconfirm'] = 'Do you really want to delete this list with all its tasks?';
+$labels['errorsaving'] = 'Fehler beim Speichern.';
+$labels['notasksfound'] = 'Für die aktuellen Kriterien wurden keine Aufgaben gefunden.';
+$labels['invalidstartduedates'] = 'Beginn der Aufgabe darf nicht gröÃer als das Enddatum sein.';
+$labels['deletetasktconfirm'] = 'Möchten Sie diese Aufgabe wirklich löschen?';
+$labels['deleteparenttasktconfirm'] = 'Möchten Sie diese Aufgabe inklusive aller Teilaufgaben wirklich löschen?';
+$labels['deletelistconfirm'] = 'Möchten Sie diese Liste mit allen Aufgaben wirklich löschen?';
diff --git a/plugins/tasklist/localization/en_US.inc b/plugins/tasklist/localization/en_US.inc
index 7d5415a..8a31be3 100644
--- a/plugins/tasklist/localization/en_US.inc
+++ b/plugins/tasklist/localization/en_US.inc
@@ -15,7 +15,7 @@ $labels['edit'] = 'Edit';
$labels['delete'] = 'Delete';
$labels['title'] = 'Title';
$labels['description'] = 'Description';
-$labels['datetime'] = 'Date/Time';
+$labels['datetime'] = 'Due';
$labels['start'] = 'Start';
$labels['alarms'] = 'Reminder';
diff --git a/plugins/tasklist/skins/larry/templates/mainview.html b/plugins/tasklist/skins/larry/templates/mainview.html
index 4b8b49a..93914e1 100644
--- a/plugins/tasklist/skins/larry/templates/mainview.html
+++ b/plugins/tasklist/skins/larry/templates/mainview.html
@@ -103,16 +103,16 @@
<label><roundcube:label name="tasklist.tags" /></label>
<span class="task-text"></span>
</div>
- <div id="task-date" class="form-section">
- <label><roundcube:label name="tasklist.datetime" /></label>
- <span class="task-text"></span>
- <span id="task-time"></span>
- </div>
<div id="task-start" class="form-section">
<label><roundcube:label name="tasklist.start" /></label>
<span class="task-text"></span>
<span id="task-starttime"></span>
</div>
+ <div id="task-date" class="form-section">
+ <label><roundcube:label name="tasklist.datetime" /></label>
+ <span class="task-text"></span>
+ <span id="task-time"></span>
+ </div>
<div id="task-alarm" class="form-section">
<label><roundcube:label name="tasklist.alarms" /></label>
<span class="task-text"></span>
diff --git a/plugins/tasklist/skins/larry/templates/taskedit.html b/plugins/tasklist/skins/larry/templates/taskedit.html
index f67d20a..1c9aa4e 100644
--- a/plugins/tasklist/skins/larry/templates/taskedit.html
+++ b/plugins/tasklist/skins/larry/templates/taskedit.html
@@ -20,17 +20,17 @@
<roundcube:object name="plugin.tags_editline" id="taskedit-tagline" class="tagedit" tabindex="3" />
</div>
<div class="form-section">
- <label for="taskedit-date"><roundcube:label name="tasklist.datetime" /></label>
- <input type="text" name="date" size="10" id="taskedit-date" tabindex="20" />
- <input type="text" name="time" size="6" id="taskedit-time" tabindex="21" />
- <a href="#nodate" style="margin-left:1em" class="edit-nodate" rel="#taskedit-date,#taskedit-time"><roundcube:label name="tasklist.nodate" /></a>
- </div>
- <div class="form-section">
<label for="taskedit-startdate"><roundcube:label name="tasklist.start" /></label>
<input type="text" name="startdate" size="10" id="taskedit-startdate" tabindex="23" />
<input type="text" name="starttime" size="6" id="taskedit-starttime" tabindex="24" />
<a href="#nodate" style="margin-left:1em" class="edit-nodate" rel="#taskedit-startdate,#taskedit-starttime"><roundcube:label name="tasklist.nodate" /></a>
</div>
+ <div class="form-section">
+ <label for="taskedit-date"><roundcube:label name="tasklist.datetime" /></label>
+ <input type="text" name="date" size="10" id="taskedit-date" tabindex="20" />
+ <input type="text" name="time" size="6" id="taskedit-time" tabindex="21" />
+ <a href="#nodate" style="margin-left:1em" class="edit-nodate" rel="#taskedit-date,#taskedit-time"><roundcube:label name="tasklist.nodate" /></a>
+ </div>
<div class="form-section" id="taskedit-alarms">
<label for="taskedit-alarm"><roundcube:label name="tasklist.alarms" /></label>
<roundcube:object name="plugin.alarm_select" />
commit 93b83e6df1dd36632271674d8dc9e855f1e4fc7f
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Mar 13 10:26:59 2013 +0100
Remove alarm type 'email' until we have a cron job that actually sends out such reminders
diff --git a/plugins/calendar/drivers/database/database_driver.php b/plugins/calendar/drivers/database/database_driver.php
index 958e8ca..7669350 100644
--- a/plugins/calendar/drivers/database/database_driver.php
+++ b/plugins/calendar/drivers/database/database_driver.php
@@ -34,7 +34,7 @@ class database_driver extends calendar_driver
public $attendees = true;
public $freebusy = false;
public $attachments = true;
- public $alarm_types = array('DISPLAY','EMAIL');
+ public $alarm_types = array('DISPLAY');
private $rc;
private $cal;
diff --git a/plugins/calendar/drivers/kolab/kolab_driver.php b/plugins/calendar/drivers/kolab/kolab_driver.php
index 1c6a578..7be31e2 100644
--- a/plugins/calendar/drivers/kolab/kolab_driver.php
+++ b/plugins/calendar/drivers/kolab/kolab_driver.php
@@ -33,7 +33,7 @@ class kolab_driver extends calendar_driver
public $freebusy = true;
public $attachments = true;
public $undelete = true;
- public $alarm_types = array('DISPLAY','EMAIL');
+ public $alarm_types = array('DISPLAY');
public $categoriesimmutable = true;
private $rc;
commit c2c20b692cb9324feadfd5815d5046fdbeae23f6
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Mar 7 18:02:36 2013 +0100
Read/write catgories property for contact objects
diff --git a/plugins/libkolab/lib/kolab_format_contact.php b/plugins/libkolab/lib/kolab_format_contact.php
index d78a82d..2f8bd14 100644
--- a/plugins/libkolab/lib/kolab_format_contact.php
+++ b/plugins/libkolab/lib/kolab_format_contact.php
@@ -97,6 +97,7 @@ class kolab_format_contact extends kolab_format
$nc->setSuffixes(self::array2vector($object['suffix']));
$this->obj->setNameComponents($nc);
$this->obj->setName($object['name']);
+ $this->obj->setCategories(self::array2vector($object['categories']));
if (isset($object['nickname']))
$this->obj->setNickNames(self::array2vector($object['nickname']));
@@ -275,6 +276,7 @@ class kolab_format_contact extends kolab_format
$object['suffix'] = join(' ', self::vector2array($nc->suffixes()));
$object['nickname'] = join(' ', self::vector2array($this->obj->nickNames()));
$object['profession'] = join(' ', self::vector2array($this->obj->titles()));
+ $object['categories'] = self::vector2array($this->obj->categories());
// organisation related properties (affiliation)
$orgs = $this->obj->affiliations();
commit 34cd551370617b0bafbb44a3958685288189c485
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Mar 6 15:47:30 2013 +0100
Fix task reminder saving/rendering (#1680)
diff --git a/plugins/tasklist/drivers/database/tasklist_database_driver.php b/plugins/tasklist/drivers/database/tasklist_database_driver.php
index fe2733c..ae2b5e2 100644
--- a/plugins/tasklist/drivers/database/tasklist_database_driver.php
+++ b/plugins/tasklist/drivers/database/tasklist_database_driver.php
@@ -656,7 +656,7 @@ class tasklist_database_driver extends tasklist_driver
private function _get_notification($task)
{
if ($task['alarms'] && $task['complete'] < 1 || strpos($task['alarms'], '@') !== false) {
- $alarm = libcalendaring::get_next_alarm($task);
+ $alarm = libcalendaring::get_next_alarm($task, 'task');
if ($alarm['time'] && $alarm['action'] == 'DISPLAY')
return date('Y-m-d H:i:s', $alarm['time']);
diff --git a/plugins/tasklist/tasklist.js b/plugins/tasklist/tasklist.js
index f3c26fd..7a10484 100644
--- a/plugins/tasklist/tasklist.js
+++ b/plugins/tasklist/tasklist.js
@@ -100,7 +100,6 @@ function rcube_tasklist_ui(settings)
var Q = this.quote_html;
var text2html = this.text2html;
var event_date_text = this.event_date_text;
- var format_datetime = this.format_datetime;
var parse_datetime = this.parse_datetime;
var date2unixtime = this.date2unixtime;
var fromunixtime = this.fromunixtime;
@@ -1019,8 +1018,8 @@ function rcube_tasklist_ui(settings)
if (alarm[0].match(/@(\d+)/)) {
var ondate = fromunixtime(parseInt(RegExp.$1));
$('#taskedit select.edit-alarm-offset').val('@');
- $('#taskedit input.edit-alarm-date').val(format_datetime(ondate, 1));
- $('#taskedit input.edit-alarm-time').val(format_datetime(ondate, 2));
+ $('#taskedit input.edit-alarm-date').val(me.format_datetime(ondate, 1));
+ $('#taskedit input.edit-alarm-time').val(me.format_datetime(ondate, 2));
}
else if (alarm[0].match(/([-+])(\d+)([MHD])/)) {
$('#taskedit input.edit-alarm-value').val(RegExp.$2);
commit e35d2a3a52af59a7c60957885cb95abd7e69f26f
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Mar 6 15:37:19 2013 +0100
Fix invalid class reference (#1679)
diff --git a/plugins/tasklist/drivers/database/tasklist_database_driver.php b/plugins/tasklist/drivers/database/tasklist_database_driver.php
index 56f4cf7..fe2733c 100644
--- a/plugins/tasklist/drivers/database/tasklist_database_driver.php
+++ b/plugins/tasklist/drivers/database/tasklist_database_driver.php
@@ -656,7 +656,7 @@ class tasklist_database_driver extends tasklist_driver
private function _get_notification($task)
{
if ($task['alarms'] && $task['complete'] < 1 || strpos($task['alarms'], '@') !== false) {
- $alarm = calendarlibcalendaring::get_next_alarm($task);
+ $alarm = libcalendaring::get_next_alarm($task);
if ($alarm['time'] && $alarm['action'] == 'DISPLAY')
return date('Y-m-d H:i:s', $alarm['time']);
commit 5fa81b2041c4e576aee53bdf66d1d25ce9380c32
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Mar 6 15:25:45 2013 +0100
Correctly quote procted column names such as 'start' and 'end' (#1675)
diff --git a/plugins/calendar/drivers/database/database_driver.php b/plugins/calendar/drivers/database/database_driver.php
index 5a518f7..958e8ca 100644
--- a/plugins/calendar/drivers/database/database_driver.php
+++ b/plugins/calendar/drivers/database/database_driver.php
@@ -240,8 +240,10 @@ class database_driver extends calendar_driver
$event = $this->_save_preprocess($event);
$query = $this->rc->db->query(sprintf(
"INSERT INTO " . $this->db_events . "
- (calendar_id, created, changed, uid, start, end, all_day, recurrence, title, description, location, categories, free_busy, priority, sensitivity, attendees, alarms, notifyat)
+ (calendar_id, created, changed, uid, %s, %s, all_day, recurrence, title, description, location, categories, free_busy, priority, sensitivity, attendees, alarms, notifyat)
VALUES (?, %s, %s, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
+ $this->rc->db->quote_identifier('start'),
+ $this->rc->db->quote_identifier('end'),
$this->rc->db->now(),
$this->rc->db->now()
),
@@ -341,9 +343,10 @@ class database_driver extends calendar_driver
$sqlresult = $this->rc->db->query(sprintf(
"SELECT event_id FROM " . $this->db_events . "
WHERE calendar_id IN (%s)
- AND start >= ?
+ AND %s >= ?
AND recurrence_id=?",
- $this->calendar_ids
+ $this->calendar_ids,
+ $this->rc->db->quote_identifier('start')
),
$fromdate->format(self::DB_DATE_FORMAT),
$master['id']);
@@ -538,9 +541,11 @@ class database_driver extends calendar_driver
$notify_at = $this->_get_notification(array('alarms' => $event['alarms'], 'start' => $next_start, 'end' => $next_end));
$query = $this->rc->db->query(sprintf(
"INSERT INTO " . $this->db_events . "
- (calendar_id, recurrence_id, created, changed, uid, start, end, all_day, recurrence, title, description, location, categories, free_busy, priority, sensitivity, alarms, notifyat)
+ (calendar_id, recurrence_id, created, changed, uid, %s, %s, all_day, recurrence, title, description, location, categories, free_busy, priority, sensitivity, alarms, notifyat)
SELECT calendar_id, ?, %s, %s, uid, ?, ?, all_day, recurrence, title, description, location, categories, free_busy, priority, sensitivity, alarms, ?
FROM " . $this->db_events . " WHERE event_id=? AND calendar_id IN (" . $this->calendar_ids . ")",
+ $this->rc->db->quote_identifier('start'),
+ $this->rc->db->quote_identifier('end'),
$this->rc->db->now(),
$this->rc->db->now()
),
@@ -636,7 +641,7 @@ class database_driver extends calendar_driver
$query = $this->rc->db->query(
"DELETE FROM " . $this->db_events . "
WHERE calendar_id IN (" . $this->calendar_ids . ")
- AND start >= ?
+ AND " . $this->rc->db->quote_identifier('start') . " >= ?
AND recurrence_id=?",
$fromdate->format(self::DB_DATE_FORMAT),
$master['id']
@@ -836,9 +841,10 @@ class database_driver extends calendar_driver
$result = $this->rc->db->query(sprintf(
"SELECT * FROM " . $this->db_events . "
WHERE calendar_id IN (%s)
- AND notifyat <= %s AND end > %s",
+ AND notifyat <= %s AND %s > %s",
join(',', $calendar_ids),
$this->rc->db->fromunixtime($time),
+ $this->rc->db->quote_identifier('end'),
$this->rc->db->fromunixtime($time)
));
commit 67fbd4d6f088a0210f340073f0bfcdf2db11d32e
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Mar 6 15:23:31 2013 +0100
Fix javascript errors about invalid method calls
diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index dbd8b47..95e1d53 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -2487,8 +2487,8 @@ function rcube_calendar_ui(settings)
widget.children().each(function(){
li = $(this);
html = li.children().first().html().replace(/\s+\(.+\)$/, '').replace(amregex, '0:$1').replace(pmregex, '1:$1');
- if (html == val)
- menu.activate($.Event({ type:'keypress' }), li);
+ if (html.indexOf(val) == 0)
+ menu._scrollIntoView(li);
});
};
commit e1286178e85393f918841256100f803ed4d61bb7
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Mar 6 12:56:15 2013 +0100
Avoid javascript errors while free/busy data isn't fully loaded
diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index 66b126b..dbd8b47 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -1251,6 +1251,10 @@ function rcube_calendar_ui(settings)
// attempt to find a time slot where all attemdees are available
var freebusy_find_slot = function(dir)
{
+ // exit if free-busy data isn't available yet
+ if (!freebusy_data || !freebusy_data.start)
+ return false;
+
var event = me.selected_event,
eventstart = clone_date(event.start, event.allDay ? 1 : 0).getTime(), // calculate with integers
eventend = clone_date(event.end, event.allDay ? 2 : 0).getTime(),
commit 6e484c5934a03455e1b8031f9ea2a6e6ceb78725
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Mar 6 12:43:56 2013 +0100
Avoid rendering the next day in free/busy grid (can happen on DST transitions)
diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index 5cd1d7d..66b126b 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -933,6 +933,7 @@ function rcube_calendar_ui(settings)
curdate.setTime(t);
datestr = fc.fullCalendar('formatDate', curdate, date_format);
if (datestr != lastdate) {
+ if (lastdate && !allday) break;
dates_row += '<th colspan="' + dayslots + '" class="boxtitle date' + $.fullCalendar.formatDate(curdate, 'ddMMyyyy') + '">' + Q(datestr) + '</th>';
lastdate = datestr;
}
commit b03f2bfbff89f2b67b0905f3fe0b1022e2d067ab
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Mar 6 12:30:12 2013 +0100
Minor calendar UI improvements: make date fields wide enough; display client's current timezone name
diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index c2c7371..a70cbdd 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -275,6 +275,7 @@ class calendar extends rcube_plugin
// initialize attendees autocompletion
rcube_autocomplete_init();
+ $this->rc->output->set_env('timezone', $this->timezone->getName());
$this->rc->output->set_env('calendar_driver', $this->rc->config->get('calendar_driver'), false);
$this->rc->output->set_env('mscolors', $this->driver->get_color_values());
$this->rc->output->set_env('identities-selector', $this->ui->identity_select(array('id' => 'edit-identities-list')));
diff --git a/plugins/calendar/skins/classic/templates/calendar.html b/plugins/calendar/skins/classic/templates/calendar.html
index 6e70a16..0725987 100644
--- a/plugins/calendar/skins/classic/templates/calendar.html
+++ b/plugins/calendar/skins/classic/templates/calendar.html
@@ -106,12 +106,12 @@
<div style="float:left; width:28em">
<div class="form-section">
<label for="schedule-startdate"><roundcube:label name="calendar.start" /></label>
- <input type="text" name="startdate" size="10" id="schedule-startdate" disabled="true" />
+ <input type="text" name="startdate" size="11" id="schedule-startdate" disabled="true" />
<input type="text" name="starttime" size="6" id="schedule-starttime" disabled="true" />
</div>
<div class="form-section">
<label for="schedule-enddate"><roundcube:label name="calendar.end" /></label>
- <input type="text" name="enddate" size="10" id="schedule-enddate" disabled="true" />
+ <input type="text" name="enddate" size="11" id="schedule-enddate" disabled="true" />
<input type="text" name="endtime" size="6" id="schedule-endtime" disabled="true" />
</div>
</div>
diff --git a/plugins/calendar/skins/classic/templates/eventedit.html b/plugins/calendar/skins/classic/templates/eventedit.html
index 3548478..a5ace0d 100644
--- a/plugins/calendar/skins/classic/templates/eventedit.html
+++ b/plugins/calendar/skins/classic/templates/eventedit.html
@@ -26,12 +26,12 @@
<div class="event-section">
<label style="float:right;padding-right:0.5em"><input type="checkbox" name="allday" id="edit-allday" value="1" /><roundcube:label name="calendar.all-day" /></label>
<label for="edit-startdate"><roundcube:label name="calendar.start" /></label>
- <input type="text" name="startdate" size="10" id="edit-startdate" />
+ <input type="text" name="startdate" size="11" id="edit-startdate" />
<input type="text" name="starttime" size="6" id="edit-starttime" />
</div>
<div class="event-section">
<label for="edit-enddate"><roundcube:label name="calendar.end" /></label>
- <input type="text" name="enddate" size="10" id="edit-enddate" />
+ <input type="text" name="enddate" size="11" id="edit-enddate" />
<input type="text" name="endtime" size="6" id="edit-endtime" />
</div>
<div class="event-section" id="edit-alarms">
diff --git a/plugins/calendar/skins/larry/calendar.css b/plugins/calendar/skins/larry/calendar.css
index 8d6162b..9e617e7 100644
--- a/plugins/calendar/skins/larry/calendar.css
+++ b/plugins/calendar/skins/larry/calendar.css
@@ -125,6 +125,14 @@ div.sidebarclosed {
border-bottom-color: #ababab;
}
+#calendar .timezonedisplay {
+ position: absolute;
+ bottom: 9px;
+ right: 8px;
+ font-size: 0.85em;
+ color: #666;
+}
+
#print {
width: 680px;
}
diff --git a/plugins/calendar/skins/larry/templates/calendar.html b/plugins/calendar/skins/larry/templates/calendar.html
index 3f914f8..a814345 100644
--- a/plugins/calendar/skins/larry/templates/calendar.html
+++ b/plugins/calendar/skins/larry/templates/calendar.html
@@ -41,6 +41,7 @@
<div id="calendar">
<roundcube:object name="plugin.angenda_options" class="boxfooter" id="agendaoptions" />
<roundcube:object name="message" id="message" class="statusbar" />
+ <div class="timezonedisplay"><roundcube:var name="env:timezone" /></div>
</div>
</div>
@@ -119,13 +120,13 @@
<div style="float:left; width:28em">
<div class="form-section">
<label for="schedule-startdate"><roundcube:label name="calendar.start" /></label>
- <input type="text" name="startdate" size="10" id="schedule-startdate" disabled="true" />
+ <input type="text" name="startdate" size="11" id="schedule-startdate" disabled="true" />
<input type="text" name="starttime" size="6" id="schedule-starttime" disabled="true" />
</div>
<div class="form-section">
<label for="schedule-enddate"><roundcube:label name="calendar.end" /></label>
- <input type="text" name="enddate" size="10" id="schedule-enddate" disabled="true" />
- <input type="text" name="endtime" size="6" id="schedule-endtime" disabled="true" />
+ <input type="text" name="enddate" size="11" id="schedule-enddate" disabled="true" />
+ <input type="text" name="endtime" size="6" id="schedule-endtime" disabled="true" />
</div>
</div>
<div style="float:left">
diff --git a/plugins/calendar/skins/larry/templates/eventedit.html b/plugins/calendar/skins/larry/templates/eventedit.html
index 841baf7..6784891 100644
--- a/plugins/calendar/skins/larry/templates/eventedit.html
+++ b/plugins/calendar/skins/larry/templates/eventedit.html
@@ -23,13 +23,13 @@
<div class="event-section">
<label style="float:right;padding-right:0.5em"><input type="checkbox" name="allday" id="edit-allday" value="1" /><roundcube:label name="calendar.all-day" /></label>
<label for="edit-startdate"><roundcube:label name="calendar.start" /></label>
- <input type="text" name="startdate" size="10" id="edit-startdate" />
+ <input type="text" name="startdate" size="11" id="edit-startdate" />
<input type="text" name="starttime" size="6" id="edit-starttime" />
</div>
<div class="event-section">
<label for="edit-enddate"><roundcube:label name="calendar.end" /></label>
- <input type="text" name="enddate" size="10" id="edit-enddate" />
- <input type="text" name="endtime" size="6" id="edit-endtime" />
+ <input type="text" name="enddate" size="11" id="edit-enddate" />
+ <input type="text" name="endtime" size="6" id="edit-endtime" />
</div>
<div class="event-section" id="edit-alarms">
<label for="edit-alarm"><roundcube:label name="calendar.alarms" /></label>
commit 6a2ebfa3719d365b434efcad87d9e2f2ecd1c0a1
Author: Thomas Bruederli <thomas at roundcube.net>
Date: Wed Mar 6 11:45:40 2013 +0100
Fix free/busy finder for all-day events
diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index d9e855c..5cd1d7d 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -1231,10 +1231,10 @@ function rcube_calendar_ui(settings)
{
// fix all-day evebt times
if (me.selected_event.allDay) {
+ var numdays = Math.floor((me.selected_event.end.getTime() - me.selected_event.start.getTime()) / DAY_MS);
start.setHours(12);
start.setMinutes(0);
- if (end.getHours() == 0)
- end.setHours(-1);
+ end.setTime(start.getTime() + numdays * DAY_MS);
end.setHours(13);
end.setMinutes(0);
}
@@ -1251,13 +1251,13 @@ function rcube_calendar_ui(settings)
var freebusy_find_slot = function(dir)
{
var event = me.selected_event,
- eventstart = event.start.getTime(), // calculate with integers
- eventend = event.end.getTime(),
- duration = eventend - eventstart,
+ eventstart = clone_date(event.start, event.allDay ? 1 : 0).getTime(), // calculate with integers
+ eventend = clone_date(event.end, event.allDay ? 2 : 0).getTime(),
+ duration = eventend - eventstart - (event.allDay ? HOUR_MS : 0), // make sure we don't cross day borders on DST change
sinterval = freebusy_data.interval * 60000,
intvlslots = 1,
numslots = Math.ceil(duration / sinterval),
- checkdate, slotend, email, ts, slot, slotdate = new Date(), slotenddate = new Date();
+ checkdate, slotend, email, ts, slot, slotdate = new Date();
// shift event times to next possible slot
eventstart += sinterval * intvlslots * dir;
@@ -1268,9 +1268,13 @@ function rcube_calendar_ui(settings)
for (slot = dir > 0 ? freebusy_data.start.getTime() : freebusy_data.end.getTime() - sinterval;
(dir > 0 && slot < freebusy_data.end.getTime()) || (dir < 0 && slot >= freebusy_data.start.getTime());
slot += sinterval * dir) {
- slotend = slot + sinterval;
slotdate.setTime(slot);
- slotenddate.setTime(slotend);
+ // fix slot if just crossed a DST change
+ if (event.allDay) {
+ fix_date(slotdate);
+ slot = slotdate.getTime();
+ }
+ slotend = slot + sinterval;
if ((dir > 0 && slotend <= eventstart) || (dir < 0 && slot >= eventend)) // skip
continue;
commit af73e0c6902fba55074cf1cfd73afe4261d8822a
Author: Thomas Bruederli <thomas at roundcube.net>
Date: Wed Mar 6 10:57:56 2013 +0100
Make free/busy finder DST aware (#1676)
diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php
index 5f4cc6b..c2c7371 100644
--- a/plugins/calendar/calendar.php
+++ b/plugins/calendar/calendar.php
@@ -1382,6 +1382,16 @@ class calendar extends rcube_plugin
$start = get_input_value('start', RCUBE_INPUT_GPC);
$end = get_input_value('end', RCUBE_INPUT_GPC);
+ // convert dates into unix timestamps
+ if (!empty($start) && !is_numeric($start)) {
+ $dts = new DateTime($start, $this->timezone);
+ $start = $dts->format('U');
+ }
+ if (!empty($end) && !is_numeric($end)) {
+ $dte = new DateTime($end, $this->timezone);
+ $end = $dte->format('U');
+ }
+
if (!$start) $start = time();
if (!$end) $end = $start + 3600;
@@ -1419,11 +1429,27 @@ class calendar extends rcube_plugin
$start = get_input_value('start', RCUBE_INPUT_GPC);
$end = get_input_value('end', RCUBE_INPUT_GPC);
$interval = intval(get_input_value('interval', RCUBE_INPUT_GPC));
-
+ $strformat = $interval > 60 ? 'Ymd' : 'YmdHis';
+
+ // convert dates into unix timestamps
+ if (!empty($start) && !is_numeric($start)) {
+ $dts = new DateTime($start, $this->timezone);
+ $start = $dts->format('U');
+ }
+ if (!empty($end) && !is_numeric($end)) {
+ $dte = new DateTime($end, $this->timezone);
+ $end = $dte->format('U');
+ }
+
if (!$start) $start = time();
if (!$end) $end = $start + 86400 * 30;
if (!$interval) $interval = 60; // 1 hour
+ if (!$dte) {
+ $dts = new DateTime('@'.$start);
+ $dts->setTimezone($this->timezone);
+ }
+
$fblist = $this->driver->get_freebusy_list($email, $start, $end);
$slots = array();
@@ -1431,7 +1457,9 @@ class calendar extends rcube_plugin
for ($s = 0, $t = $start; $t <= $end; $s++) {
$status = self::FREEBUSY_UNKNOWN;
$t_end = $t + $interval * 60;
-
+ $dt = new DateTime('@'.$t);
+ $dt->setTimezone($this->timezone);
+
// determine attendee's status
if (is_array($fblist)) {
$status = self::FREEBUSY_FREE;
@@ -1446,13 +1474,24 @@ class calendar extends rcube_plugin
}
$slots[$s] = $status;
+ $times[$s] = intval($dt->format($strformat));
$t = $t_end;
}
+ $dte = new DateTime('@'.$t_end);
+ $dte->setTimezone($this->timezone);
+
// let this information be cached for 5min
send_future_expire_header(300);
- echo json_encode(array('email' => $email, 'start' => intval($start), 'end' => intval($t_end), 'interval' => $interval, 'slots' => $slots));
+ echo json_encode(array(
+ 'email' => $email,
+ 'start' => $dts->format('c'),
+ 'end' => $dte->format('c'),
+ 'interval' => $interval,
+ 'slots' => $slots,
+ 'times' => $times,
+ ));
exit;
}
diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js
index 24d7bd6..d9e855c 100644
--- a/plugins/calendar/calendar_ui.js
+++ b/plugins/calendar/calendar_ui.js
@@ -74,6 +74,7 @@ function rcube_calendar_ui(settings)
var parse_datetime = this.parse_datetime;
var date2unixtime = this.date2unixtime;
var fromunixtime = this.fromunixtime;
+ var parseISO8601 = this.parseISO8601;
var init_alarms_edit = this.init_alarms_edit;
@@ -122,6 +123,15 @@ function rcube_calendar_ui(settings)
return d;
};
+ // fix date if jumped over a DST change
+ var fix_date = function(date)
+ {
+ if (date.getHours() == 23)
+ date.setTime(date.getTime() + HOUR_MS);
+ else if (date.getHours() > 0)
+ date.setHours(0);
+ };
+
// turn the given date into an ISO 8601 date string understandable by PHPs strtotime()
var date2servertime = function(date)
{
@@ -129,6 +139,11 @@ function rcube_calendar_ui(settings)
+ 'T'+zeropad(date.getHours())+':'+zeropad(date.getMinutes())+':'+zeropad(date.getSeconds());
}
+ var date2timestring = function(date, dateonly)
+ {
+ return date2servertime(date).replace(/[^0-9]/g, '').substr(0, (dateonly ? 8 : 14));
+ }
+
var zeropad = function(num)
{
return (num < 10 ? '0' : '') + num;
@@ -469,7 +484,7 @@ function rcube_calendar_ui(settings)
recurrence = $('#edit-recurrence-frequency').val(event.recurrence ? event.recurrence.FREQ : '').change();
interval = $('#eventedit select.edit-recurrence-interval').val(event.recurrence ? event.recurrence.INTERVAL : 1);
rrtimes = $('#edit-recurrence-repeat-times').val(event.recurrence ? event.recurrence.COUNT : 1);
- rrenddate = $('#edit-recurrence-enddate').val(event.recurrence && event.recurrence.UNTIL ? $.fullCalendar.formatDate($.fullCalendar.parseISO8601(event.recurrence.UNTIL), settings['date_format']) : '');
+ rrenddate = $('#edit-recurrence-enddate').val(event.recurrence && event.recurrence.UNTIL ? $.fullCalendar.formatDate(parseISO8601(event.recurrence.UNTIL), settings['date_format']) : '');
$('#eventedit input.edit-recurrence-until:checked').prop('checked', false);
var weekdays = ['SU','MO','TU','WE','TH','FR','SA'];
@@ -893,10 +908,13 @@ function rcube_calendar_ui(settings)
{
if (delta) {
freebusy_ui.start.setTime(freebusy_ui.start.getTime() + DAY_MS * delta);
+ fix_date(freebusy_ui.start);
+
// skip weekends if in workinhoursonly-mode
if (Math.abs(delta) == 1 && freebusy_ui.workinhoursonly) {
while (is_weekend(freebusy_ui.start))
freebusy_ui.start.setTime(freebusy_ui.start.getTime() + DAY_MS * delta);
+ fix_date(freebusy_ui.start);
}
freebusy_ui.end = new Date(freebusy_ui.start.getTime() + DAY_MS * freebusy_ui.numdays);
@@ -965,7 +983,7 @@ function rcube_calendar_ui(settings)
// if we have loaded free-busy data, show it
if (!freebusy_ui.loading) {
- if (date2unixtime(freebusy_ui.start) < freebusy_data.start || date2unixtime(freebusy_ui.end) > freebusy_data.end || freebusy_ui.interval != freebusy_data.interval) {
+ if (freebusy_ui.start < freebusy_data.start || freebusy_ui.end > freebusy_data.end || freebusy_ui.interval != freebusy_data.interval) {
load_freebusy_data(freebusy_ui.start, freebusy_ui.interval);
}
else {
@@ -1069,12 +1087,13 @@ function rcube_calendar_ui(settings)
// fetch free-busy information for each attendee from server
var load_freebusy_data = function(from, interval)
{
- var start = new Date(from.getTime() - DAY_MS * 2); // start 1 days before event
+ var start = new Date(from.getTime() - DAY_MS * 2); // start 2 days before event
+ fix_date(start);
var end = new Date(start.getTime() + DAY_MS * Math.max(14, freebusy_ui.numdays + 7)); // load min. 14 days
freebusy_ui.numrequired = 0;
freebusy_data.all = [];
freebusy_data.required = [];
-
+
// load free-busy information for every attendee
var domid, email;
for (var i=0; i < event_attendees.length; i++) {
@@ -1087,7 +1106,7 @@ function rcube_calendar_ui(settings)
type: 'GET',
dataType: 'json',
url: rcmail.url('freebusy-times'),
- data: { email:email, start:date2unixtime(clone_date(start, 1)), end:date2unixtime(clone_date(end, 2)), interval:interval, _remote:1 },
+ data: { email:email, start:date2servertime(clone_date(start, 1)), end:date2servertime(clone_date(end, 2)), interval:interval, _remote:1 },
success: function(data) {
freebusy_ui.loading--;
@@ -1101,11 +1120,11 @@ function rcube_calendar_ui(settings)
}
// copy data to member var
- var req = attendee.role != 'OPT-PARTICIPANT';
- var ts = data.start - 0;
- freebusy_data.start = ts;
+ var ts, req = attendee.role != 'OPT-PARTICIPANT';
+ freebusy_data.start = parseISO8601(data.start);
freebusy_data[data.email] = {};
for (var i=0; i < data.slots.length; i++) {
+ ts = data.times[i] + '';
freebusy_data[data.email][ts] = data.slots[i];
// set totals
@@ -1117,10 +1136,8 @@ function rcube_calendar_ui(settings)
if (!freebusy_data.all[ts])
freebusy_data.all[ts] = [0,0,0,0];
freebusy_data.all[ts][data.slots[i]]++;
-
- ts += data.interval * 60;
}
- freebusy_data.end = ts;
+ freebusy_data.end = parseISO8601(data.end);
freebusy_data.interval = data.interval;
// hide loading indicator
@@ -1177,13 +1194,18 @@ function rcube_calendar_ui(settings)
var domid = String(email).replace(rcmail.identifier_expr, '');
var row = $('#fbrow' + domid);
var rowall = $('#fbrowall').children();
- var ts = date2unixtime(freebusy_ui.start);
- var fbdata = freebusy_data[email];
-
+ var dateonly = freebusy_ui.interval > 60,
+ t, ts = date2timestring(freebusy_ui.start, dateonly),
+ curdate = new Date(),
+ fbdata = freebusy_data[email];
+
if (fbdata && fbdata[ts] !== undefined && row.length) {
+ t = freebusy_ui.start.getTime();
row.children().each(function(i, cell){
+ curdate.setTime(t);
+ ts = date2timestring(curdate, dateonly);
cell.className = cell.className.replace('unknown', fbdata[ts] ? status_classes[fbdata[ts]] : 'unknown');
-
+
// also update total row if all data was loaded
if (freebusy_ui.loading == 0 && freebusy_data.all[ts] && (cell = rowall.get(i))) {
var workinghours = cell.className.indexOf('workinghours') >= 0;
@@ -1199,7 +1221,7 @@ function rcube_calendar_ui(settings)
cell.className = (workinghours ? 'workinghours ' : 'offhours ') + req_status + ' all-' + all_status;
}
- ts += freebusy_ui.interval * 60;
+ t += freebusy_ui.interval * 60000;
});
}
};
@@ -1207,9 +1229,12 @@ function rcube_calendar_ui(settings)
// write changed event date/times back to form fields
var update_freebusy_dates = function(start, end)
{
+ // fix all-day evebt times
if (me.selected_event.allDay) {
start.setHours(12);
start.setMinutes(0);
+ if (end.getHours() == 0)
+ end.setHours(-1);
end.setHours(13);
end.setMinutes(0);
}
@@ -1226,13 +1251,13 @@ function rcube_calendar_ui(settings)
var freebusy_find_slot = function(dir)
{
var event = me.selected_event,
- eventstart = date2unixtime(event.start), // calculate with unixtimes
- eventend = date2unixtime(event.end),
+ eventstart = event.start.getTime(), // calculate with integers
+ eventend = event.end.getTime(),
duration = eventend - eventstart,
- sinterval = freebusy_data.interval * 60,
+ sinterval = freebusy_data.interval * 60000,
intvlslots = 1,
numslots = Math.ceil(duration / sinterval),
- checkdate, slotend, email, curdate;
+ checkdate, slotend, email, ts, slot, slotdate = new Date(), slotenddate = new Date();
// shift event times to next possible slot
eventstart += sinterval * intvlslots * dir;
@@ -1240,27 +1265,32 @@ function rcube_calendar_ui(settings)
// iterate through free-busy slots and find candidates
var candidatecount = 0, candidatestart = candidateend = success = false;
- for (var slot = dir > 0 ? freebusy_data.start : freebusy_data.end - sinterval; (dir > 0 && slot < freebusy_data.end) || (dir < 0 && slot >= freebusy_data.start); slot += sinterval * dir) {
+ for (slot = dir > 0 ? freebusy_data.start.getTime() : freebusy_data.end.getTime() - sinterval;
+ (dir > 0 && slot < freebusy_data.end.getTime()) || (dir < 0 && slot >= freebusy_data.start.getTime());
+ slot += sinterval * dir) {
slotend = slot + sinterval;
+ slotdate.setTime(slot);
+ slotenddate.setTime(slotend);
+
if ((dir > 0 && slotend <= eventstart) || (dir < 0 && slot >= eventend)) // skip
continue;
-
+
// respect workingours setting
if (freebusy_ui.workinhoursonly) {
- curdate = fromunixtime(dir > 0 || !candidateend ? slot : (candidateend - duration));
- if (is_weekend(curdate) || (freebusy_data.interval <= 60 && !is_workinghour(curdate))) { // skip off-hours
+ if (is_weekend(slotdate) || (freebusy_data.interval <= 60 && !is_workinghour(slotdate))) { // skip off-hours
candidatestart = candidateend = false;
candidatecount = 0;
continue;
}
}
-
+
if (!candidatestart)
candidatestart = slot;
-
+
// check freebusy data for all attendees
+ ts = date2timestring(slotdate, freebusy_data.interval > 60);
for (var i=0; i < event_attendees.length; i++) {
- if (freebusy_ui.attendees[i].role != 'OPT-PARTICIPANT' && (email = freebusy_ui.attendees[i].email) && freebusy_data[email] && freebusy_data[email][slot] > 1) {
+ if (freebusy_ui.attendees[i].role != 'OPT-PARTICIPANT' && (email = freebusy_ui.attendees[i].email) && freebusy_data[email] && freebusy_data[email][ts] > 1) {
candidatestart = candidateend = false;
break;
}
@@ -1281,12 +1311,12 @@ function rcube_calendar_ui(settings)
// if candidate is big enough, this is it!
if (candidatecount == numslots) {
if (dir > 0) {
- event.start = fromunixtime(candidatestart);
- event.end = fromunixtime(candidatestart + duration);
+ event.start.setTime(candidatestart);
+ event.end.setTime(candidatestart + duration);
}
else {
- event.end = fromunixtime(candidateend);
- event.start = fromunixtime(candidateend - duration);
+ event.end.setTime(candidateend);
+ event.start.setTime(candidateend - duration);
}
success = true;
break;
@@ -1456,7 +1486,7 @@ function rcube_calendar_ui(settings)
type: 'GET',
dataType: 'html',
url: rcmail.url('freebusy-status'),
- data: { email:email, start:date2unixtime(clone_date(event.start, event.allDay?1:0)), end:date2unixtime(clone_date(event.end, event.allDay?2:0)), _remote: 1 },
+ data: { email:email, start:date2servertime(clone_date(event.start, event.allDay?1:0)), end:date2servertime(clone_date(event.end, event.allDay?2:0)), _remote: 1 },
success: function(status){
icon.removeClass('loading').addClass(String(status).toLowerCase());
},
diff --git a/plugins/libcalendaring/libcalendaring.js b/plugins/libcalendaring/libcalendaring.js
index 35897d7..b2ae597 100644
--- a/plugins/libcalendaring/libcalendaring.js
+++ b/plugins/libcalendaring/libcalendaring.js
@@ -110,7 +110,7 @@ function rcube_libcalendaring(settings)
* Convert an ISO 8601 formatted date string from the server into a Date object.
* Timezone information will be ignored, the server already provides dates in user's timezone.
*/
- function parseISO8601(s)
+ this.parseISO8601 = function(s)
{
// force d to be on check's YMD, for daylight savings purposes
var fixDate = function(d, check) {
@@ -319,8 +319,8 @@ function rcube_libcalendaring(settings)
var actions, adismiss, asnooze, alarm, html, event_ids = [];
for (var i=0; i < alarms.length; i++) {
alarm = alarms[i];
- alarm.start = parseISO8601(alarm.start);
- alarm.end = parseISO8601(alarm.end);
+ alarm.start = this.parseISO8601(alarm.start);
+ alarm.end = this.parseISO8601(alarm.end);
event_ids.push(alarm.id);
html = '<h3 class="event-title">' + Q(alarm.title) + '</h3>';
commit 6aacc89876228687ca03233a26a79ef022f19283
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Mar 6 10:19:22 2013 +0100
Improve behavior when deleting recurring events (#1677)
diff --git a/plugins/calendar/drivers/kolab/kolab_driver.php b/plugins/calendar/drivers/kolab/kolab_driver.php
index 2b3694a..1c6a578 100644
--- a/plugins/calendar/drivers/kolab/kolab_driver.php
+++ b/plugins/calendar/drivers/kolab/kolab_driver.php
@@ -430,6 +430,13 @@ class kolab_driver extends calendar_driver
// removing the first instance => just move to next occurence
if ($master['id'] == $event['id']) {
$recurring = reset($storage->_get_recurring_events($event, $event['start'], null, $event['id'].'-1'));
+
+ // no future instances found: delete the master event (bug #1677)
+ if (!$recurring['start']) {
+ $success = $storage->delete_event($master, $force);
+ break;
+ }
+
$master['start'] = $recurring['start'];
$master['end'] = $recurring['end'];
if ($master['recurrence']['COUNT'])
@@ -449,6 +456,11 @@ class kolab_driver extends calendar_driver
$master['recurrence']['UNTIL'] = clone $event['start'];
$master['recurrence']['UNTIL']->sub(new DateInterval('P1D'));
unset($master['recurrence']['COUNT']);
+
+ // if all future instances are deleted, remove recurrence rule entirely (bug #1677)
+ if ($master['recurrence']['UNTIL']->format('Ymd') == $master['start']->format('Ymd'))
+ $master['recurrence'] = array();
+
$success = $storage->update_event($master);
break;
}
commit d772476b3ab480f263b6d30d54455f941d07e281
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Feb 28 16:02:16 2013 +0100
Adapt fix for #349
diff --git a/plugins/libkolab/lib/kolab_storage_folder.php b/plugins/libkolab/lib/kolab_storage_folder.php
index b3fe9fe..0c12423 100644
--- a/plugins/libkolab/lib/kolab_storage_folder.php
+++ b/plugins/libkolab/lib/kolab_storage_folder.php
@@ -932,7 +932,11 @@ class kolab_storage_folder
case 'event':
if ($this->get_namespace() == 'personal') {
$result = $this->trigger_url(
- sprintf('%s/trigger/%s/%s.pfb', kolab_storage::get_freebusy_server(), $owner, $this->imap->mod_folder($this->name)),
+ sprintf('%s/trigger/%s/%s.pfb',
+ kolab_storage::get_freebusy_server(),
+ urlencode($owner),
+ urlencode($this->imap->mod_folder($this->name))
+ ),
$this->imap->options['user'],
$this->imap->options['password']
);
commit 79ce7fd64c5cbdb595f692ec60ea17e1760de4f1
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Feb 28 15:26:56 2013 +0100
Fix overflowing calendar widget in French localization (#1665)
diff --git a/plugins/calendar/skins/larry/calendar.css b/plugins/calendar/skins/larry/calendar.css
index 5072ce2..8d6162b 100644
--- a/plugins/calendar/skins/larry/calendar.css
+++ b/plugins/calendar/skins/larry/calendar.css
@@ -920,31 +920,21 @@ a.dropdown-link:after {
.ui-dialog-buttonset a.dropdown-link {
margin-right: 1em;
}
-/*
-.ui-datepicker-calendar .ui-datepicker-today .ui-state-default {
- border-color: #cccccc;
- background: #ffffcc;
- color: #000;
+
+#calendarsidebar .ui-datepicker-calendar {
+ table-layout: fixed;
}
-*/
+
.ui-datepicker-calendar .ui-datepicker-week-col {
border: 0;
color: #999;
font-size: 90%;
text-align: right;
padding-right: 6px;
-}
-/*
-.ui-datepicker th {
- padding: 0.3em 0;
- font-size: 10px;
+ width: 20px;
+ overflow: hidden;
}
-.ui-datepicker td span,
-.ui-datepicker td a {
- padding-left: 0.1em;
-}
-*/
.ui-autocomplete {
max-height: 160px;
overflow-y: auto;
commit 88d95b24a118d3ea18bd2edf47cec3e5fbc7ddaf
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Feb 28 15:25:47 2013 +0100
Fix javascript errors trown by CSS expressions
diff --git a/plugins/calendar/skins/classic/iehacks.css b/plugins/calendar/skins/classic/iehacks.css
index 2b6d6be..42bd736 100644
--- a/plugins/calendar/skins/classic/iehacks.css
+++ b/plugins/calendar/skins/classic/iehacks.css
@@ -5,13 +5,13 @@
height: expression(Math.max(300, parseInt(document.documentElement.clientHeight)-100)+'px');
}
-#sidebar,
-#sidebartoggle {
+#calendarsidebar,
+#calendarsidebartoggle {
height: expression((parseInt(this.parentNode.offsetHeight)-37)+'px');
}
#calendar {
- width: expression((parseInt(this.parentNode.offsetWidth)-parseInt(document.getElementById('sidebartoggle').offsetWidth)-parseInt(document.getElementById('sidebartoggle').offsetLeft)-4)+'px');
+ width: expression((parseInt(this.parentNode.offsetWidth)-parseInt(document.getElementById('calendarsidebartoggle').offsetWidth)-parseInt(document.getElementById('calendarsidebartoggle').offsetLeft)-4)+'px');
height: expression(parseInt(this.parentNode.offsetHeight)+'px');
}
diff --git a/plugins/calendar/skins/larry/iehacks.css b/plugins/calendar/skins/larry/iehacks.css
index 529b029..d6e122d 100644
--- a/plugins/calendar/skins/larry/iehacks.css
+++ b/plugins/calendar/skins/larry/iehacks.css
@@ -1,17 +1,17 @@
/* CSS hacks for IE 7 */
-#sidebar,
-#sidebartoggle {
+#calendarsidebar,
+#calendarsidebartoggle {
height: expression((parseInt(this.parentNode.offsetHeight)-37)+'px');
}
#calendar {
- width: expression((parseInt(this.parentNode.offsetWidth)-parseInt(document.getElementById('sidebartoggle').offsetWidth)-parseInt(document.getElementById('sidebartoggle').offsetLeft)-4)+'px');
+ width: expression((parseInt(this.parentNode.offsetWidth)-parseInt(document.getElementById('calendarsidebartoggle').offsetWidth)-parseInt(document.getElementById('calendarsidebartoggle').offsetLeft)-4)+'px');
height: expression((parseInt(this.parentNode.offsetHeight)-30)+'px');
}
#calendars {
- height: expression((parseInt(this.parentNode.offsetHeight)-280)+'px');
+ height: expression((parseInt(this.parentNode.offsetHeight)-240)+'px');
}
#agendaoptions {
commit b21abe6618b226f640fa12bd28f615f725ca4af1
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Feb 28 15:04:03 2013 +0100
Fix IE css hacks for Larry and Kolab skin
diff --git a/plugins/calendar/skins/larry/iehacks.css b/plugins/calendar/skins/larry/iehacks.css
index 0993754..529b029 100644
--- a/plugins/calendar/skins/larry/iehacks.css
+++ b/plugins/calendar/skins/larry/iehacks.css
@@ -1,10 +1,5 @@
/* CSS hacks for IE 7 */
-#main {
- width: expression(Math.max(300, parseInt(document.documentElement.clientWidth)-10)+'px');
- height: expression(Math.max(300, parseInt(document.documentElement.clientHeight)-100)+'px');
-}
-
#sidebar,
#sidebartoggle {
height: expression((parseInt(this.parentNode.offsetHeight)-37)+'px');
@@ -12,11 +7,11 @@
#calendar {
width: expression((parseInt(this.parentNode.offsetWidth)-parseInt(document.getElementById('sidebartoggle').offsetWidth)-parseInt(document.getElementById('sidebartoggle').offsetLeft)-4)+'px');
- height: expression(parseInt(this.parentNode.offsetHeight)+'px');
+ height: expression((parseInt(this.parentNode.offsetHeight)-30)+'px');
}
#calendars {
- height: expression((parseInt(this.parentNode.offsetHeight)-220)+'px');
+ height: expression((parseInt(this.parentNode.offsetHeight)-280)+'px');
}
#agendaoptions {
@@ -31,19 +26,36 @@
filter: alpha(opacity=40);
}
-#datepicker .ui-widget-header {
- width: 102%;
+.calendarmain .fc-day-content {
+ cursor: default;
+}
+
+.calendarmain .fc-view-table col.fc-event-date {
+ width: 8em;
}
-.fc-day-content {
- cursor: default;
+.calendarmain .fc-view-table col.fc-event-time {
+ width: 9em;
}
-.fc-header-title h2 {
+.calendarmain .fc-header-title h2 {
font-size: 16px;
}
-.fc-event-temp .fc-event-bg {
+.calendarmain .fc-header-left {
+ width: 248px;
+}
+
+.calendarmain .fc-header-center {
+ width: auto;
+}
+
+.calendarmain .fc-header-right {
+ width: 144px;
+ white-space: nowrap;
+}
+
+.calendarmain .fc-event-temp .fc-event-bg {
display: none; /* nested opacity filters while dragging don't work */
}
commit 481ef522132ab1abdfcaa7010a0066721521b7ac
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Feb 28 14:20:41 2013 +0100
Fix javascript syntax to work on IE7
diff --git a/plugins/kolab_activesync/kolab_activesync.js b/plugins/kolab_activesync/kolab_activesync.js
index c28a877..c5fb6d1 100644
--- a/plugins/kolab_activesync/kolab_activesync.js
+++ b/plugins/kolab_activesync/kolab_activesync.js
@@ -108,7 +108,7 @@ function kolab_activesync_config()
var data = {
cmd: 'save',
id: rcmail.env.active_device,
- devicealias: $('#config-device-alias').val(),
+ devicealias: $('#config-device-alias').val()
// syncmode: $('#config-device-mode option:selected').val(),
// laxpic: $('#config-device-laxpic').get(0).checked ? 1 : 0
};
@@ -137,7 +137,7 @@ function kolab_activesync_config()
parent.window.activesync_object.update_list(p.id, p.alias);
// device deleted
- if (p.success && p.id && p.delete) {
+ if (p.success && p.id && p['delete']) {
active_device = null;
device_select();
devicelist.remove_row(p.id);
commit 5dc65cbd7ed2aab58eeefb161a6f35de1b346d60
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Feb 28 14:19:58 2013 +0100
Fix background image in calendars listing
diff --git a/plugins/calendar/skins/classic/iehacks.css b/plugins/calendar/skins/classic/iehacks.css
index 831266f..2b6d6be 100644
--- a/plugins/calendar/skins/classic/iehacks.css
+++ b/plugins/calendar/skins/classic/iehacks.css
@@ -36,7 +36,7 @@ html #calendartoolbar a.buttonPas {
filter: alpha(opacity=40);
}
-#calendarslist li span {
+#calendarslist li span.handle {
background-image: url(images/calendars.gif);
}
commit ee8e315df086ccb5f340a2b76b78fbf9eb955dfd
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Feb 27 19:48:01 2013 +0100
Fix placeholder in French translations
diff --git a/plugins/calendar/localization/fr_FR.inc b/plugins/calendar/localization/fr_FR.inc
index dfe9c59..cb4e3f8 100644
--- a/plugins/calendar/localization/fr_FR.inc
+++ b/plugins/calendar/localization/fr_FR.inc
@@ -123,7 +123,7 @@ $labels['nextslot'] = 'Créneau suivant';
$labels['noslotfound'] = 'Impossible de trouver un créneau disponible';
$labels['invitationsubject'] = 'Vous avez invité à "$title"';
$labels['invitationmailbody'] = "*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees\n\nVous trouverez ci-joint un fichier iCalendar avec tous les détails de l'évènement que vous pourrez importer dans votre agenda électronique.";
-$labels['invitationattendlinks'] = "Dans le cas où votre application de messagerie ne gère pas les demandes \"iTip\". Vous pouvez utiliser ce lien pour accepter ou refuser l'invitation : n$url";
+$labels['invitationattendlinks'] = "Dans le cas où votre application de messagerie ne gère pas les demandes \"iTip\". Vous pouvez utiliser ce lien pour accepter ou refuser l'invitation :\n\$url";
$labels['eventupdatesubject'] = '"$title" a été modifié';
$labels['eventupdatesubjectempty'] = 'Un évènement vous concernant a été modifié';
$labels['eventupdatemailbody'] = "*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees\n\nVous trouverez ci-joint un fichier iCalendar avec tous les modifications de l'évènement que vous pourrez importer dans votre agenda électronique.";
commit b111a369e3485b751fa8a2c010f1a358210d62e7
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Feb 27 17:05:10 2013 +0100
Expose URI attachments as 'links' for event objects
diff --git a/plugins/libkolab/lib/kolab_format_event.php b/plugins/libkolab/lib/kolab_format_event.php
index 489d16e..bb2b3b7 100644
--- a/plugins/libkolab/lib/kolab_format_event.php
+++ b/plugins/libkolab/lib/kolab_format_event.php
@@ -86,6 +86,13 @@ class kolab_format_event extends kolab_format_xcal
$attach->setUri('cid:' . $cid, $attr['mimetype']);
$vattach->push($attach);
}
+
+ foreach ((array)$object['links'] as $link) {
+ $attach = new Attachment;
+ $attach->setUri($link, null);
+ $vattach->push($attach);
+ }
+
$this->obj->setAttachments($vattach);
// cache this data
@@ -152,6 +159,9 @@ class kolab_format_event extends kolab_format_xcal
'content' => $data,
);
}
+ else if (substr($attach->uri(), 0, 4) == 'http') {
+ $object['links'][] = $attach->uri();
+ }
}
$this->data = $object;
commit c7164cbc22a3099d674218fec701c565eb98dc35
Author: Torsten Grote <t at grobox.de>
Date: Wed Feb 27 15:33:16 2013 +0100
added French translation for libcalendaring
diff --git a/plugins/libcalendaring/localization/fr_FR.inc b/plugins/libcalendaring/localization/fr_FR.inc
new file mode 100644
index 0000000..c33f29e
--- /dev/null
+++ b/plugins/libcalendaring/localization/fr_FR.inc
@@ -0,0 +1,30 @@
+<?php
+
+$labels = array();
+
+$labels['alarmemail'] = 'Envoyer un email';
+$labels['alarmdisplay'] = 'Voir le message';
+$labels['alarmdisplayoption'] = 'Message';
+$labels['alarmemailoption'] = 'Email';
+$labels['alarmat'] = 'Ã $datetime';
+$labels['trigger@'] = 'Ã la date';
+$labels['trigger-M'] = 'minutes avant';
+$labels['trigger-H'] = 'heures avant';
+$labels['trigger-D'] = 'jours avant';
+$labels['trigger+M'] = 'minutes après';
+$labels['trigger+H'] = 'heures après';
+$labels['trigger+D'] = 'jours après';
+$labels['addalarm'] = 'ajouter alarme';
+
+$labels['alarmtitle'] = 'Evénements à venir';
+$labels['dismissall'] = 'Tout supprimer';
+$labels['dismiss'] = 'Abandonner';
+$labels['snooze'] = 'En pause';
+$labels['repeatinmin'] = 'Répéter dans $min minutes';
+$labels['repeatinhr'] = 'Répéter dans 1 heure';
+$labels['repeatinhrs'] = 'Répéter dans $hrs heures';
+$labels['repeattomorrow'] = 'Répéter demain';
+$labels['repeatinweek'] = 'Répéter dans une semaine';
+
+$labels['showmore'] = 'Afficher plus...';
+
commit b13b5b5806d64936d19a48d37fe4da5bd3b8cc68
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Feb 27 12:16:27 2013 +0100
Fix selecting tags from autocompletion (#1329)
diff --git a/plugins/tasklist/jquery.tagedit.js b/plugins/tasklist/jquery.tagedit.js
index 7c3a5e6..d70cb32 100755
--- a/plugins/tasklist/jquery.tagedit.js
+++ b/plugins/tasklist/jquery.tagedit.js
@@ -455,7 +455,7 @@
// If there is an entry for that already in the autocomplete, don't use it (Check could be case sensitive or not)
for (var i = 0; i < result.length; i++) {
var label = typeof result[i] == 'string' ? result[i] : result[i].label;
- if (options.checkNewEntriesCaseSensitive == true)
+ if (options.checkNewEntriesCaseSensitive == false)
label = label.toLowerCase();
if (label == compareValue) {
isNew = false;
diff --git a/plugins/tasklist/tasklist.js b/plugins/tasklist/tasklist.js
index daf157e..f3c26fd 100644
--- a/plugins/tasklist/tasklist.js
+++ b/plugins/tasklist/tasklist.js
@@ -1077,7 +1077,7 @@ function rcube_tasklist_ui(settings)
}
}
- $('input[name="tags[]"]', rcmail.gui_objects.edittagline).each(function(i,elem){
+ $('input[type="hidden"]', rcmail.gui_objects.edittagline).each(function(i,elem){
if (elem.value)
me.selected_task.tags.push(elem.value);
});
commit cad6551c5d60556e458bfcd95a8dc8631c2c0356
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Feb 27 10:04:05 2013 +0100
Fix computation of yearly recurring events using the Horde_Date_Recurrence class (database backend)
diff --git a/plugins/calendar/lib/calendar_recurrence.php b/plugins/calendar/lib/calendar_recurrence.php
index bf534f5..d4a3641 100644
--- a/plugins/calendar/lib/calendar_recurrence.php
+++ b/plugins/calendar/lib/calendar_recurrence.php
@@ -70,7 +70,13 @@ class calendar_recurrence
public function next_start()
{
$time = false;
- if ($this->next && ($next = $this->engine->nextActiveRecurrence(array('year' => $this->next->year, 'month' => $this->next->month, 'mday' => $this->next->mday + 1, 'hour' => $this->next->hour, 'min' => $this->next->min, 'sec' => $this->next->sec)))) {
+ $after = clone $this->next;
+ $after->mday = $after->mday + 1;
+ if ($this->next && ($next = $this->engine->nextActiveRecurrence($after))) {
+ if (!$next->after($this->next)) {
+ // avoid endless loops if recurrence computation fails
+ return false;
+ }
if ($this->event['allday']) {
$next->hour = $this->hour; # fix time for all-day events
$next->min = 0;
commit 2423d5ba31f614640c3af9e5b979d5f4b2226ba2
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Wed Feb 27 09:49:07 2013 +0100
Gracefully handle buggy messages with either missing or duplicated X-Kolab-Type headers
diff --git a/plugins/libkolab/lib/kolab_storage_folder.php b/plugins/libkolab/lib/kolab_storage_folder.php
index 2811886..b3fe9fe 100644
--- a/plugins/libkolab/lib/kolab_storage_folder.php
+++ b/plugins/libkolab/lib/kolab_storage_folder.php
@@ -458,12 +458,40 @@ class kolab_storage_folder
$this->imap->set_folder($folder);
$headers = $this->imap->get_message_headers($msguid);
+ $message = null;
// Message doesn't exist?
if (empty($headers)) {
return false;
}
+ // extract the X-Kolab-Type header from the XML attachment part if missing
+ if (empty($headers->others['x-kolab-type'])) {
+ $message = new rcube_message($msguid);
+ foreach ((array)$message->attachments as $part) {
+ if (strpos($part->mimetype, kolab_format::KTYPE_PREFIX) === 0) {
+ $headers->others['x-kolab-type'] = $part->mimetype;
+ break;
+ }
+ }
+ }
+ // fix buggy messages stating the X-Kolab-Type header twice
+ else if (is_array($headers->others['x-kolab-type'])) {
+ $headers->others['x-kolab-type'] = reset($headers->others['x-kolab-type']);
+ }
+
+ // no object type header found: abort
+ if (empty($headers->others['x-kolab-type'])) {
+ rcube::raise_error(array(
+ 'code' => 600,
+ 'type' => 'php',
+ 'file' => __FILE__,
+ 'line' => __LINE__,
+ 'message' => "No X-Kolab-Type information found in message $msguid ($this->name).",
+ ), true);
+ return false;
+ }
+
$object_type = kolab_format::mime2object_type($headers->others['x-kolab-type']);
$content_type = kolab_format::KTYPE_PREFIX . $object_type;
@@ -471,7 +499,7 @@ class kolab_storage_folder
if ($type != '*' && $object_type != $type)
return false;
- $message = new rcube_message($msguid);
+ if (!$message) $message = new rcube_message($msguid);
$attachments = array();
// get XML part
commit 83dc7e097f852b132e6d646b9cdf923964a6fa49
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Feb 21 17:41:41 2013 +0100
Support import/export of custom properties
diff --git a/plugins/calendar/lib/calendar_ical.php b/plugins/calendar/lib/calendar_ical.php
index 0fea74e..6d7474e 100644
--- a/plugins/calendar/lib/calendar_ical.php
+++ b/plugins/calendar/lib/calendar_ical.php
@@ -9,7 +9,7 @@
* @author Bogomil "Bogo" Shopov <shopov at kolabsys.com>
*
* Copyright (C) 2010, Lazlo Westerhof <hello at lazlo.me>
- * Copyright (C) 2011, Kolab Systems AG <contact at kolabsys.com>
+ * Copyright (C) 2013, Kolab Systems AG <contact at kolabsys.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -258,6 +258,10 @@ class calendar_ical
else if (in_array($attr['value'], array('FREE', 'BUSY', 'TENTATIVE')))
$event['free_busy'] = strtolower($attr['value']);
break;
+
+ default:
+ if (substr($attr['name'], 0, 2) == 'X-')
+ $event['x-custom'][] = array($attr['name'], $attr['value']);
}
}
@@ -416,6 +420,9 @@ class calendar_ical
else if ($event['free_busy'] == 'tentative')
$vevent .= "STATUS:TENTATIVE" . self::EOL;
+ foreach ((array)$event['x-custom'] as $prop)
+ $vevent .= $prop[0] . ':' . $this->escpape($prop[1]) . self::EOL;
+
// TODO: export attachments
$vevent .= "END:VEVENT" . self::EOL;
commit 410bc481477c14fe396d58ece5a5fe5090dc97ea
Author: Thomas Bruederli <bruederli at kolabsys.com>
Date: Thu Feb 21 17:33:17 2013 +0100
Fix typos and read STATUS:CANCELLED
diff --git a/plugins/calendar/lib/calendar_ical.php b/plugins/calendar/lib/calendar_ical.php
index cec2040..0fea74e 100644
--- a/plugins/calendar/lib/calendar_ical.php
+++ b/plugins/calendar/lib/calendar_ical.php
@@ -205,7 +205,9 @@ class calendar_ical
case 'STATUS':
if ($attr['value'] == 'TENTATIVE')
- $event['free_busy'] == 'tentative';
+ $event['free_busy'] = 'tentative';
+ else if ($attr['value'] == 'CANCELLED')
+ $event['cancelled'] = true;
break;
case 'PRIORITY':
commit f286c67e02773617e55036b5dfcacde666a26857
Author: Aleksander Machniak <machniak at kolabsys.com>
Date: Fri Jun 21 11:04:12 2013 +0200
Small refactoring: use base class methods to read/set common properties; add support for custom properties in all objects
Conflicts:
plugins/libkolab/lib/kolab_format.php
diff --git a/plugins/libkolab/lib/kolab_format.php b/plugins/libkolab/lib/kolab_format.php
index ccc7e46..cb77e18 100644
--- a/plugins/libkolab/lib/kolab_format.php
+++ b/plugins/libkolab/lib/kolab_format.php
@@ -381,19 +381,68 @@ abstract class kolab_format
*
* @param array Object data as hash array
*/
- abstract public function set(&$object);
+ public function set(&$object)
+ {
+ $this->init();
- /**
- *
- */
- abstract public function is_valid();
+ if (!empty($object['uid']))
+ $this->obj->setUid($object['uid']);
+
+ // set some automatic values if missing
+ if (method_exists($this->obj, 'setCreated') && !$this->obj->created()) {
+ if (empty($object['created']))
+ $object['created'] = new DateTime('now', self::$timezone);
+ $this->obj->setCreated(self::get_datetime($object['created']));
+ }
+
+ $object['changed'] = new DateTime('now', self::$timezone);
+ $this->obj->setLastModified(self::get_datetime($object['changed'], new DateTimeZone('UTC')));
+
+ // Save custom properties of the given object
+ if (!empty($object['x-custom'])) {
+ $vcustom = new vectorcs;
+ foreach ($object['x-custom'] as $cp) {
+ if (is_array($cp))
+ $vcustom->push(new CustomProperty($cp[0], $cp[1]));
+ }
+ $this->obj->setCustomProperties($vcustom);
+ }
+ }
/**
* Convert the Kolab object into a hash array data structure
*
* @return array Kolab object data as hash array
*/
- abstract public function to_array();
+ public function to_array($data = array())
+ {
+ $this->init();
+
+ // read object properties into local data object
+ $object = array(
+ 'uid' => $this->obj->uid(),
+ 'changed' => self::php_datetime($this->obj->lastModified()),
+ );
+
+ // not all container support the created property
+ if (method_exists($this->obj, 'created')) {
+ $object['created'] = self::php_datetime($this->obj->created());
+ }
+
+ // read custom properties
+ $vcustom = $this->obj->customProperties();
+ for ($i=0; $i < $vcustom->size(); $i++) {
+ $cp = $vcustom->get($i);
+ $object['x-custom'][] = array($cp->identifier, $cp->value);
+ }
+
+ return $object;
+ }
+
+ /**
+ * Object validation method to be implemented by derived classes
+ */
+ abstract public function is_valid();
/**
* Callback for kolab_storage_cache to get object specific tags to cache
diff --git a/plugins/libkolab/lib/kolab_format_contact.php b/plugins/libkolab/lib/kolab_format_contact.php
index 39e579c..d78a82d 100644
--- a/plugins/libkolab/lib/kolab_format_contact.php
+++ b/plugins/libkolab/lib/kolab_format_contact.php
@@ -85,20 +85,8 @@ class kolab_format_contact extends kolab_format
*/
public function set(&$object)
{
- $this->init();
-
- // set some automatic values if missing
- if (false && !$this->obj->created()) {
- if (!empty($object['created']))
- $object['created'] = new DateTime('now', self::$timezone);
- $this->obj->setCreated(self::get_datetime($object['created']));
- }
-
- if (!empty($object['uid']))
- $this->obj->setUid($object['uid']);
-
- $object['changed'] = new DateTime('now', self::$timezone);
- $this->obj->setLastModified(self::get_datetime($object['changed'], new DateTimeZone('UTC')));
+ // set common object properties
+ parent::set($object);
// do the hard work of setting object values
$nc = new NameComponents;
@@ -274,14 +262,10 @@ class kolab_format_contact extends kolab_format
if (!empty($this->data))
return $this->data;
- $this->init();
+ // read common object props into local data object
+ $object = parent::to_array();
- // read object properties into local data object
- $object = array(
- 'uid' => $this->obj->uid(),
- 'name' => $this->obj->name(),
- 'changed' => self::php_datetime($this->obj->lastModified()),
- );
+ $object['name'] = $this->obj->name();
$nc = $this->obj->nameComponents();
$object['surname'] = join(' ', self::vector2array($nc->surnames()));
diff --git a/plugins/libkolab/lib/kolab_format_distributionlist.php b/plugins/libkolab/lib/kolab_format_distributionlist.php
index 5622fc5..b966700 100644
--- a/plugins/libkolab/lib/kolab_format_distributionlist.php
+++ b/plugins/libkolab/lib/kolab_format_distributionlist.php
@@ -39,14 +39,8 @@ class kolab_format_distributionlist extends kolab_format
*/
public function set(&$object)
{
- $this->init();
-
- // set some automatic values if missing
- if (!empty($object['uid']))
- $this->obj->setUid($object['uid']);
-
- $object['changed'] = new DateTime('now', self::$timezone);
- $this->obj->setLastModified(self::get_datetime($object['changed'], new DateTimeZone('UTC')));
+ // set common object properties
+ parent::set($object);
$this->obj->setName($object['name']);
@@ -91,12 +85,11 @@ class kolab_format_distributionlist extends kolab_format
if (!empty($this->data))
return $this->data;
- $this->init();
+ // read common object props into local data object
+ $object = parent::to_array();
- // read object properties
- $object = array(
- 'uid' => $this->obj->uid(),
- 'changed' => self::php_datetime($this->obj->lastModified()),
+ // add object properties
+ $object += array(
'name' => $this->obj->name(),
'member' => array(),
'_type' => 'distribution-list',
diff --git a/plugins/libkolab/lib/kolab_format_event.php b/plugins/libkolab/lib/kolab_format_event.php
index 4ef6735..489d16e 100644
--- a/plugins/libkolab/lib/kolab_format_event.php
+++ b/plugins/libkolab/lib/kolab_format_event.php
@@ -61,8 +61,6 @@ class kolab_format_event extends kolab_format_xcal
*/
public function set(&$object)
{
- $this->init();
-
// set common xcal properties
parent::set($object);
@@ -114,8 +112,6 @@ class kolab_format_event extends kolab_format_xcal
if (!empty($this->data))
return $this->data;
- $this->init();
-
// read common xcal props
$object = parent::to_array();
diff --git a/plugins/libkolab/lib/kolab_format_file.php b/plugins/libkolab/lib/kolab_format_file.php
index b3ab158..e73622a 100644
--- a/plugins/libkolab/lib/kolab_format_file.php
+++ b/plugins/libkolab/lib/kolab_format_file.php
@@ -49,14 +49,9 @@ class kolab_format_file extends kolab_format
*/
public function set(&$object)
{
- $this->init();
+ // set common object properties
+ parent::set($object);
- // set some automatic values if missing
- if (!empty($object['uid']))
- $this->obj->setUid($object['uid']);
-
- $object['changed'] = new DateTime('now', self::$timezone);
- $this->obj->setLastModified(self::get_datetime($object['changed'], new DateTimeZone('UTC')));
$this->obj->setClassification($this->sensitivity_map[$object['sensitivity']]);
$this->obj->setCategories(self::array2vector($object['categories']));
@@ -109,15 +104,13 @@ class kolab_format_file extends kolab_format
if (!empty($this->data))
return $this->data;
- $this->init();
+ // read common object props into local data object
+ $object = parent::to_array();
$sensitivity_map = array_flip($this->sensitivity_map);
// read object properties
- $object = array(
- 'uid' => $this->obj->uid(),
- 'created' => self::php_datetime($this->obj->created()),
- 'changed' => self::php_datetime($this->obj->lastModified()),
+ $object += array(
'sensitivity' => $sensitivity_map[$this->obj->classification()],
'categories' => self::vector2array($this->obj->categories()),
'notes' => $this->obj->note(),
diff --git a/plugins/libkolab/lib/kolab_format_journal.php b/plugins/libkolab/lib/kolab_format_journal.php
index daab1ac..7e02244 100644
--- a/plugins/libkolab/lib/kolab_format_journal.php
+++ b/plugins/libkolab/lib/kolab_format_journal.php
@@ -39,14 +39,8 @@ class kolab_format_journal extends kolab_format
*/
public function set(&$object)
{
- $this->init();
-
- // set some automatic values if missing
- if (!empty($object['uid']))
- $this->obj->setUid($object['uid']);
-
- $object['changed'] = new DateTime('now', self::$timezone);
- $this->obj->setLastModified(self::get_datetime($object['changed'], new DateTimeZone('UTC')));
+ // set common object properties
+ parent::set($object);
// TODO: set object propeties
@@ -74,14 +68,8 @@ class kolab_format_journal extends kolab_format
if (!empty($this->data))
return $this->data;
- $this->init();
-
- // read object properties
- $object = array(
- 'uid' => $this->obj->uid(),
- 'created' => self::php_datetime($this->obj->created()),
- 'changed' => self::php_datetime($this->obj->lastModified()),
- );
+ // read common object props into local data object
+ $object = parent::to_array();
// TODO: read object properties
diff --git a/plugins/libkolab/lib/kolab_format_note.php b/plugins/libkolab/lib/kolab_format_note.php
index 5af9343..849c61a 100644
--- a/plugins/libkolab/lib/kolab_format_note.php
+++ b/plugins/libkolab/lib/kolab_format_note.php
@@ -39,14 +39,8 @@ class kolab_format_note extends kolab_format
*/
public function set(&$object)
{
- $this->init();
-
- // set some automatic values if missing
- if (!empty($object['uid']))
- $this->obj->setUid($object['uid']);
-
- $object['changed'] = new DateTime('now', self::$timezone);
- $this->obj->setLastModified(self::get_datetime($object['changed'], new DateTimeZone('UTC')));
+ // set common object properties
+ parent::set($object);
// TODO: set object propeties
@@ -74,14 +68,8 @@ class kolab_format_note extends kolab_format
if (!empty($this->data))
return $this->data;
- $this->init();
-
- // read object properties
- $object = array(
- 'uid' => $this->obj->uid(),
- 'created' => self::php_datetime($this->obj->created()),
- 'changed' => self::php_datetime($this->obj->lastModified()),
- );
+ // read common object props into local data object
+ $object = parent::to_array();
// TODO: read object properties
diff --git a/plugins/libkolab/lib/kolab_format_task.php b/plugins/libkolab/lib/kolab_format_task.php
index 77870c7..e44eebf 100644
--- a/plugins/libkolab/lib/kolab_format_task.php
+++ b/plugins/libkolab/lib/kolab_format_task.php
@@ -38,8 +38,6 @@ class kolab_format_task extends kolab_format_xcal
*/
public function set(&$object)
{
- $this->init();
-
// set common xcal properties
parent::set($object);
@@ -79,8 +77,6 @@ class kolab_format_task extends kolab_format_xcal
if (!empty($this->data))
return $this->data;
- $this->init();
-
// read common xcal props
$object = parent::to_array();
diff --git a/plugins/libkolab/lib/kolab_format_xcal.php b/plugins/libkolab/lib/kolab_format_xcal.php
index 3e1a721..6dcd328 100644
--- a/plugins/libkolab/lib/kolab_format_xcal.php
+++ b/plugins/libkolab/lib/kolab_format_xcal.php
@@ -92,13 +92,13 @@ abstract class kolab_format_xcal extends kolab_format
*/
public function to_array()
{
+ // read common object props
+ $object = parent::to_array();
+
$status_map = array_flip($this->status_map);
$sensitivity_map = array_flip($this->sensitivity_map);
- $object = array(
- 'uid' => $this->obj->uid(),
- 'created' => self::php_datetime($this->obj->created()),
- 'changed' => self::php_datetime($this->obj->lastModified()),
+ $object += array(
'sequence' => intval($this->obj->sequence()),
'title' => $this->obj->summary(),
'location' => $this->obj->location(),
@@ -214,20 +214,12 @@ abstract class kolab_format_xcal extends kolab_format
*/
public function set(&$object)
{
- $is_new = !$this->obj->uid();
+ $this->init();
- // set some automatic values if missing
- if (!$this->obj->created()) {
- if (!empty($object['created']))
- $object['created'] = new DateTime('now', self::$timezone);
- $this->obj->setCreated(self::get_datetime($object['created']));
- }
-
- if (!empty($object['uid']))
- $this->obj->setUid($object['uid']);
+ $is_new = !$this->obj->uid();
- $object['changed'] = new DateTime('now', self::$timezone);
- $this->obj->setLastModified(self::get_datetime($object['changed'], new DateTimeZone('UTC')));
+ // set common object properties
+ parent::set($object);
// increment sequence on updates
$object['sequence'] = !$is_new ? $this->obj->sequence()+1 : 0;
More information about the commits
mailing list