- Added iCal Support

- Bugfixes
- automatically generated sqlite & postgres support (not tested!)
This commit is contained in:
JodliDev 2021-08-24 12:55:41 +02:00
parent 5ee16ce9ef
commit 277e3094f7
14 changed files with 622 additions and 314 deletions

75
drivers/caldav/Isync.php Normal file
View file

@ -0,0 +1,75 @@
<?php
/**
* Interface for different sync drivers
*
* @version @package_version@
* @author JodliDev <jodlidev@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
interface Isync {
/**
* Getter for current calendar ctag (only for CalDAV).
* @return string
*/
public function get_ctag();
/**
* Determines whether current calendar needs to be synced
*
* @return boolean True if the current calendar needs to be synced, false otherwise.
*/
public function is_synced();
/**
* Synchronizes given events with server and returns updates.
*
* @param array List of hash arrays with event properties, must include "caldav_url" and "tag".
* @return array Tuple containing the following lists:
*
* Caldav properties for events to be created or to be updated with the keys:
* url: Event ical URL relative to calendar URL
* etag: Remote etag of the event
* local_event: The local event in case of an update.
* remote_event: The current event retrieved from caldav server.
*
* A list of event ids that are in sync.
*/
public function get_updates($events);
/**
* Creates the given event.
*
* @param array Hash array with event properties.
* @return array with updated "caldav_url" and "caldav_tag" attributes, null on error.
*/
public function create_event($event);
/**
* Updates the given event.
*
* @param array Hash array with event properties to update, must include "uid", "caldav_url" and "caldav_tag".
* @return boolean True on success, false on error, -1 if the given event/etag is not up to date.
*/
public function update_event($event);
/**
* Removes the given event.
*
* @param array Hash array with events properties, must include "caldav_url".
* @return boolean True on success, false on error.
*/
public function remove_event($event);
}

View file

@ -22,86 +22,89 @@
*/
CREATE TABLE IF NOT EXISTS `caldav_sources` (
`source_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`source_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`caldav_url` varchar(255) NOT NULL,
`caldav_user` varchar(255) DEFAULT NULL,
`caldav_pass` varchar(1024) DEFAULT NULL,
`caldav_url` varchar(1024) NOT NULL,
`caldav_user` varchar(255) DEFAULT NULL,
`caldav_pass` varchar(1024) DEFAULT NULL,
PRIMARY KEY(`source_id`),
CONSTRAINT `fk_caldav_sources_user_id` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE
PRIMARY KEY(`source_id`),
CONSTRAINT `fk_caldav_sources_user_id` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
CREATE TABLE IF NOT EXISTS `caldav_calendars` (
`calendar_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`source_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`name` varchar(255) NOT NULL,
`color` varchar(8) NOT NULL,
`showalarms` tinyint(1) NOT NULL DEFAULT '1',
`calendar_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`source_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`name` varchar(255) NOT NULL,
`color` varchar(8) NOT NULL,
`showalarms` tinyint(1) NOT NULL DEFAULT '1',
`caldav_tag` varchar(255) DEFAULT NULL,
`caldav_url` varchar(255) NOT NULL,
`caldav_last_change` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`caldav_tag` varchar(255) DEFAULT NULL,
`caldav_url` varchar(1024) NOT NULL,
`caldav_last_change` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`is_ical` tinyint(1) NOT NULL DEFAULT '0',
`ical_user` varchar(255) DEFAULT NULL,
`ical_pass` varchar(1024) DEFAULT NULL,
PRIMARY KEY(`calendar_id`),
INDEX `caldav_user_name_idx` (`user_id`, `name`),
CONSTRAINT `fk_caldav_calendars_user_id` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_caldav_calendars_sources` FOREIGN KEY (`source_id`)
REFERENCES `caldav_sources`(`source_id`) ON DELETE CASCADE ON UPDATE CASCADE
PRIMARY KEY(`calendar_id`),
INDEX `caldav_user_name_idx` (`user_id`, `name`),
CONSTRAINT `fk_caldav_calendars_user_id` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_caldav_calendars_sources` FOREIGN KEY (`source_id`)
REFERENCES `caldav_sources`(`source_id`) ON DELETE CASCADE ON UPDATE CASCADE
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
CREATE TABLE IF NOT EXISTS `caldav_events` (
`event_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`calendar_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
`recurrence_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
`uid` varchar(255) NOT NULL DEFAULT '',
`instance` varchar(16) NOT NULL DEFAULT '',
`isexception` tinyint(1) NOT NULL DEFAULT '0',
`created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`sequence` int(1) UNSIGNED NOT NULL DEFAULT '0',
`start` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`end` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`recurrence` varchar(255) DEFAULT NULL,
`title` varchar(255) NOT NULL,
`description` text NOT NULL,
`location` varchar(255) NOT NULL DEFAULT '',
`categories` varchar(255) NOT NULL DEFAULT '',
`url` varchar(255) NOT NULL DEFAULT '',
`all_day` tinyint(1) NOT NULL DEFAULT '0',
`free_busy` tinyint(1) NOT NULL DEFAULT '0',
`priority` tinyint(1) NOT NULL DEFAULT '0',
`sensitivity` tinyint(1) NOT NULL DEFAULT '0',
`status` varchar(32) NOT NULL DEFAULT '',
`alarms` text NULL DEFAULT NULL,
`attendees` text DEFAULT NULL,
`notifyat` datetime DEFAULT NULL,
`event_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`calendar_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
`recurrence_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
`uid` varchar(255) NOT NULL DEFAULT '',
`instance` varchar(16) NOT NULL DEFAULT '',
`isexception` tinyint(1) NOT NULL DEFAULT '0',
`created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`sequence` int(1) UNSIGNED NOT NULL DEFAULT '0',
`start` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`end` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`recurrence` varchar(255) DEFAULT NULL,
`title` varchar(255) NOT NULL,
`description` text NOT NULL,
`location` varchar(255) NOT NULL DEFAULT '',
`categories` varchar(255) NOT NULL DEFAULT '',
`url` varchar(255) NOT NULL DEFAULT '',
`all_day` tinyint(1) NOT NULL DEFAULT '0',
`free_busy` tinyint(1) NOT NULL DEFAULT '0',
`priority` tinyint(1) NOT NULL DEFAULT '0',
`sensitivity` tinyint(1) NOT NULL DEFAULT '0',
`status` varchar(32) NOT NULL DEFAULT '',
`alarms` text NULL DEFAULT NULL,
`attendees` text DEFAULT NULL,
`notifyat` datetime DEFAULT NULL,
`caldav_url` varchar(255) NOT NULL,
`caldav_tag` varchar(255) DEFAULT NULL,
`caldav_last_change` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`caldav_url` varchar(255) NOT NULL,
`caldav_tag` varchar(255) DEFAULT NULL,
`caldav_last_change` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY(`event_id`),
INDEX `caldav_uid_idx` (`uid`),
INDEX `caldav_recurrence_idx` (`recurrence_id`),
INDEX `caldav_calendar_notify_idx` (`calendar_id`,`notifyat`),
CONSTRAINT `fk_caldav_events_calendar_id` FOREIGN KEY (`calendar_id`)
REFERENCES `caldav_calendars`(`calendar_id`) ON DELETE CASCADE ON UPDATE CASCADE
PRIMARY KEY(`event_id`),
INDEX `caldav_uid_idx` (`uid`),
INDEX `caldav_recurrence_idx` (`recurrence_id`),
INDEX `caldav_calendar_notify_idx` (`calendar_id`,`notifyat`),
CONSTRAINT `fk_caldav_events_calendar_id` FOREIGN KEY (`calendar_id`)
REFERENCES `caldav_calendars`(`calendar_id`) ON DELETE CASCADE ON UPDATE CASCADE
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
CREATE TABLE IF NOT EXISTS `caldav_attachments` (
`attachment_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`event_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
`filename` varchar(255) NOT NULL DEFAULT '',
`mimetype` varchar(255) NOT NULL DEFAULT '',
`size` int(11) NOT NULL DEFAULT '0',
`data` longtext NOT NULL,
PRIMARY KEY(`attachment_id`),
CONSTRAINT `fk_caldav_attachments_event_id` FOREIGN KEY (`event_id`)
REFERENCES `caldav_events`(`event_id`) ON DELETE CASCADE ON UPDATE CASCADE
`attachment_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`event_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
`filename` varchar(255) NOT NULL DEFAULT '',
`mimetype` varchar(255) NOT NULL DEFAULT '',
`size` int(11) NOT NULL DEFAULT '0',
`data` longtext NOT NULL,
PRIMARY KEY(`attachment_id`),
CONSTRAINT `fk_caldav_attachments_event_id` FOREIGN KEY (`event_id`)
REFERENCES `caldav_events`(`event_id`) ON DELETE CASCADE ON UPDATE CASCADE
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
REPLACE INTO `system` (`name`, `value`) VALUES ('calendar-caldav-version', '2015022700');
REPLACE INTO `system` (`name`, `value`) VALUES ('calendar-caldav-version', '2021082400');

View file

@ -1,24 +0,0 @@
/**
* CalDAV Client
*
* @version @package_version@
* @author Daniel Morlock <daniel.morlock@awesome-it.de>
*
* Copyright (C) Awesome IT GbR <info@awesome-it.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
ALTER TABLE `caldav_props` change `user` `username` varchar(255);
ALTER TABLE `events` ADD `status` VARCHAR(32) NOT NULL DEFAULT '' AFTER `sensitivity`;

View file

@ -1,125 +0,0 @@
/**
* CalDAV Client
*
* @version @package_version@
* @author Daniel Morlock <daniel.morlock@awesome-it.de>
*
* Copyright (C) Awesome IT GbR <info@awesome-it.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Create new tables */
CREATE TABLE IF NOT EXISTS `caldav_calendars` (
`calendar_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` int(10) UNSIGNED NOT NULL DEFAULT '0',
`name` varchar(255) NOT NULL,
`color` varchar(8) NOT NULL,
`showalarms` tinyint(1) NOT NULL DEFAULT '1',
`caldav_url` varchar(255) NOT NULL,
`caldav_tag` varchar(255) DEFAULT NULL,
`caldav_user` varchar(255) DEFAULT NULL,
`caldav_pass` varchar(1024) DEFAULT NULL,
`caldav_last_change` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY(`calendar_id`),
INDEX `caldav_user_name_idx` (`user_id`, `name`),
CONSTRAINT `fk_caldav_calendars_user_id` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
CREATE TABLE IF NOT EXISTS `caldav_events` (
`event_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`calendar_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
`recurrence_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
`uid` varchar(255) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`sequence` int(1) UNSIGNED NOT NULL DEFAULT '0',
`start` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`end` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`recurrence` varchar(255) DEFAULT NULL,
`title` varchar(255) NOT NULL,
`description` text NOT NULL,
`location` varchar(255) NOT NULL DEFAULT '',
`categories` varchar(255) NOT NULL DEFAULT '',
`url` varchar(255) NOT NULL DEFAULT '',
`all_day` tinyint(1) NOT NULL DEFAULT '0',
`free_busy` tinyint(1) NOT NULL DEFAULT '0',
`priority` tinyint(1) NOT NULL DEFAULT '0',
`sensitivity` tinyint(1) NOT NULL DEFAULT '0',
`status` varchar(32) NOT NULL DEFAULT '',
`alarms` varchar(255) DEFAULT NULL,
`attendees` text DEFAULT NULL,
`notifyat` datetime DEFAULT NULL,
`caldav_url` varchar(255) NOT NULL,
`caldav_tag` varchar(255) DEFAULT NULL,
`caldav_last_change` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY(`event_id`),
INDEX `caldav_uid_idx` (`uid`),
INDEX `caldav_recurrence_idx` (`recurrence_id`),
INDEX `caldav_calendar_notify_idx` (`calendar_id`,`notifyat`),
CONSTRAINT `fk_caldav_events_calendar_id` FOREIGN KEY (`calendar_id`)
REFERENCES `calendars`(`calendar_id`) ON DELETE CASCADE ON UPDATE CASCADE
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
CREATE TABLE IF NOT EXISTS `caldav_attachments` (
`attachment_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`event_id` int(11) UNSIGNED NOT NULL DEFAULT '0',
`filename` varchar(255) NOT NULL DEFAULT '',
`mimetype` varchar(255) NOT NULL DEFAULT '',
`size` int(11) NOT NULL DEFAULT '0',
`data` longtext NOT NULL,
PRIMARY KEY(`attachment_id`),
CONSTRAINT `fk_caldav_attachments_event_id` FOREIGN KEY (`event_id`)
REFERENCES `events`(`event_id`) ON DELETE CASCADE ON UPDATE CASCADE
) /*!40000 ENGINE=INNODB */ /*!40101 CHARACTER SET utf8 COLLATE utf8_general_ci */;
/* Migrate Data */
INSERT INTO caldav_calendars SELECT calendar_id, user_id, `name`, color, showalarms, url as caldav_url,
tag as caldav_tag, username as caldav_user, pass as caldav_pass,
last_change as caldav_last_change
FROM calendars cal, caldav_props dav
WHERE dav.obj_id = cal.calendar_id
AND dav.obj_type = 'vcal';
INSERT INTO caldav_events SELECT e.*, dav.url as caldav_url, dav.tag as caldav_tag, dav.last_change as caldav_last_change
FROM `events` e, caldav_props dav
WHERE dav.obj_id = e.event_id
AND dav.obj_type = 'vevent';
INSERT INTO caldav_attachments SELECT * FROM attachments a
WHERE a.event_id IN (
SELECT obj_id FROM caldav_props dav
WHERE dav.obj_type = 'vevent'
);
/* Drop deprecated data */
DELETE FROM `events` WHERE event_id IN (
SELECT obj_id FROM caldav_props dav
WHERE dav.obj_type = 'vevent'
);
DELETE FROM calendars WHERE calendar_id IN (
SELECT obj_id FROM caldav_props dav
WHERE dav.obj_type = 'vcal'
);
DELETE FROM attachments WHERE event_id IN (
SELECT obj_id FROM caldav_props dav
WHERE dav.obj_type = 'vevent'
);
DROP TABLE caldav_props;

View file

@ -1,14 +0,0 @@
-- add identifier for recurring instances and exceptions
ALTER TABLE `caldav_events` ADD `instance` varchar(16) NOT NULL DEFAULT '' AFTER `uid`;
ALTER TABLE `caldav_events` ADD `isexception` tinyint(1) NOT NULL DEFAULT '0' AFTER `instance`;
UPDATE `caldav_events` SET `instance` = DATE_FORMAT(`start`, '%Y%m%d')
WHERE `recurrence_id` != 0 AND `instance` = '' AND `all_day` = 1;
UPDATE `caldav_events` SET `instance` = DATE_FORMAT(`start`, '%Y%m%dT%k%i%s')
WHERE `recurrence_id` != 0 AND `instance` = '' AND `all_day` = 0;
-- extend alarms columns for multiple values
ALTER TABLE `caldav_events` CHANGE `alarms` `alarms` TEXT NULL DEFAULT NULL;

View file

@ -1,10 +1,9 @@
/**
* CalDAV Client
* (not tested & automatically generated from mysql)
*
* @version @package_version@
* @author Hugo Slabbert <hugo@slabnet.com>
*
* Copyright (C) 2014, Hugo Slabbert <hugo@slabnet.com>
* @author JodliDev <jodlidev@gmail.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
@ -20,32 +19,107 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
CREATE TYPE caldav_type AS ENUM ('vcal','vevent','vtodo','');
-- SQLINES LICENSE FOR EVALUATION USE ONLY
CREATE SEQUENCE caldav_sources_seq;
CREATE TABLE IF NOT EXISTS caldav_props (
obj_id int NOT NULL,
obj_type caldav_type NOT NULL,
url varchar(255) NOT NULL,
tag varchar(255) DEFAULT NULL,
username varchar(255) DEFAULT NULL,
pass varchar(1024) DEFAULT NULL,
last_change timestamp without time zone DEFAULT now() NOT NULL,
PRIMARY KEY (obj_id, obj_type)
);
CREATE TABLE IF NOT EXISTS caldav_sources (
source_id int CHECK (source_id > 0) NOT NULL DEFAULT NEXTVAL ('caldav_sources_seq'),
user_id int CHECK (user_id > 0) NOT NULL DEFAULT '0',
CREATE OR REPLACE FUNCTION upd_timestamp() RETURNS TRIGGER
LANGUAGE plpgsql
AS
$$
BEGIN
NEW.last_change = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$;
caldav_url varchar(1024) NOT NULL,
caldav_user varchar(255) DEFAULT NULL,
caldav_pass varchar(1024) DEFAULT NULL,
CREATE TRIGGER update_timestamp
BEFORE INSERT OR UPDATE
ON caldav_props
FOR EACH ROW
EXECUTE PROCEDURE upd_timestamp();
PRIMARY KEY(source_id),
CONSTRAINT fk_caldav_sources_user_id FOREIGN KEY (user_id)
REFERENCES users(user_id) ON DELETE CASCADE ON UPDATE CASCADE
) /* SQLINES DEMO *** DB */ /* SQLINES DEMO *** ET utf8 COLLATE utf8_general_ci */;
-- SQLINES LICENSE FOR EVALUATION USE ONLY
CREATE SEQUENCE caldav_calendars_seq;
CREATE TABLE IF NOT EXISTS caldav_calendars (
calendar_id int CHECK (calendar_id > 0) NOT NULL DEFAULT NEXTVAL ('caldav_calendars_seq'),
user_id int CHECK (user_id > 0) NOT NULL DEFAULT '0',
source_id int CHECK (source_id > 0) NOT NULL DEFAULT '0',
name varchar(255) NOT NULL,
color varchar(8) NOT NULL,
showalarms smallint NOT NULL DEFAULT '1',
caldav_tag varchar(255) DEFAULT NULL,
caldav_url varchar(1024) NOT NULL,
caldav_last_change timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
is_ical smallint NOT NULL DEFAULT '0',
ical_user varchar(255) DEFAULT NULL,
ical_pass varchar(1024) DEFAULT NULL,
PRIMARY KEY(calendar_id)
,
CONSTRAINT fk_caldav_calendars_user_id FOREIGN KEY (user_id)
REFERENCES users(user_id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT fk_caldav_calendars_sources FOREIGN KEY (source_id)
REFERENCES caldav_sources(source_id) ON DELETE CASCADE ON UPDATE CASCADE
) /* SQLINES DEMO *** DB */ /* SQLINES DEMO *** ET utf8 COLLATE utf8_general_ci */;
CREATE INDEX caldav_user_name_idx ON caldav_calendars (user_id, name);
-- SQLINES LICENSE FOR EVALUATION USE ONLY
CREATE SEQUENCE caldav_events_seq;
CREATE TABLE IF NOT EXISTS caldav_events (
event_id int CHECK (event_id > 0) NOT NULL DEFAULT NEXTVAL ('caldav_events_seq'),
calendar_id int CHECK (calendar_id > 0) NOT NULL DEFAULT '0',
recurrence_id int CHECK (recurrence_id > 0) NOT NULL DEFAULT '0',
uid varchar(255) NOT NULL DEFAULT '',
instance varchar(16) NOT NULL DEFAULT '',
isexception smallint NOT NULL DEFAULT '0',
created timestamp(0) NOT NULL DEFAULT '1000-01-01 00:00:00',
changed timestamp(0) NOT NULL DEFAULT '1000-01-01 00:00:00',
sequence int CHECK (sequence > 0) NOT NULL DEFAULT '0',
start timestamp(0) NOT NULL DEFAULT '1000-01-01 00:00:00',
end timestamp(0) NOT NULL DEFAULT '1000-01-01 00:00:00',
recurrence varchar(255) DEFAULT NULL,
title varchar(255) NOT NULL,
description text NOT NULL,
location varchar(255) NOT NULL DEFAULT '',
categories varchar(255) NOT NULL DEFAULT '',
url varchar(255) NOT NULL DEFAULT '',
all_day smallint NOT NULL DEFAULT '0',
free_busy smallint NOT NULL DEFAULT '0',
priority smallint NOT NULL DEFAULT '0',
sensitivity smallint NOT NULL DEFAULT '0',
status varchar(32) NOT NULL DEFAULT '',
alarms text NULL DEFAULT NULL,
attendees text DEFAULT NULL,
notifyat timestamp(0) DEFAULT NULL,
caldav_url varchar(255) NOT NULL,
caldav_tag varchar(255) DEFAULT NULL,
caldav_last_change timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(event_id)
,
CONSTRAINT fk_caldav_events_calendar_id FOREIGN KEY (calendar_id)
REFERENCES caldav_calendars(calendar_id) ON DELETE CASCADE ON UPDATE CASCADE
) /* SQLINES DEMO *** DB */ /* SQLINES DEMO *** ET utf8 COLLATE utf8_general_ci */;
CREATE INDEX caldav_uid_idx ON caldav_events (uid);
CREATE INDEX caldav_recurrence_idx ON caldav_events (recurrence_id);
CREATE INDEX caldav_calendar_notify_idx ON caldav_events (calendar_id,notifyat);
-- SQLINES LICENSE FOR EVALUATION USE ONLY
CREATE SEQUENCE caldav_attachments_seq;
CREATE TABLE IF NOT EXISTS caldav_attachments (
attachment_id int CHECK (attachment_id > 0) NOT NULL DEFAULT NEXTVAL ('caldav_attachments_seq'),
event_id int CHECK (event_id > 0) NOT NULL DEFAULT '0',
filename varchar(255) NOT NULL DEFAULT '',
mimetype varchar(255) NOT NULL DEFAULT '',
size int NOT NULL DEFAULT '0',
data TEXT NOT NULL,
PRIMARY KEY(attachment_id),
CONSTRAINT fk_caldav_attachments_event_id FOREIGN KEY (event_id)
REFERENCES caldav_events(event_id) ON DELETE CASCADE ON UPDATE CASCADE
) /* SQLINES DEMO *** DB */ /* SQLINES DEMO *** ET utf8 COLLATE utf8_general_ci */;
REPLACE INTO `system` (name, value) SELECT ('calendar-caldav-version', '2021082400');

View file

@ -0,0 +1,101 @@
/**
* CalDAV Client
* (not tested & automatically generated from mysql)
*
* @version @package_version@
* @author JodliDev <jodlidev@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
CREATE TABLE IF NOT EXISTS `caldav_sources` (
`source_id` INTEGER NOT NULL PRIMARY KEY,
`user_id` INTEGER NOT NULL DEFAULT '0',
`caldav_url` TEXT NOT NULL,
`caldav_user` TEXT DEFAULT NULL,
`caldav_pass` TEXT DEFAULT NULL,
CONSTRAINT fk_itipinvitations_user_id FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE TABLE IF NOT EXISTS `caldav_calendars` (
`calendar_id` INTEGER NOT NULL PRIMARY KEY,
`user_id` INTEGER NOT NULL DEFAULT '0',
`source_id` INTEGER NOT NULL DEFAULT '0',
`name` TEXT NOT NULL,
`color` TEXT NOT NULL,
`showalarms` tinyINTEGER NOT NULL DEFAULT '1',
`caldav_tag` TEXT DEFAULT NULL,
`caldav_url` TEXT NOT NULL,
`caldav_last_change` timestamp NOT NULL ,
`is_ical` tinyINTEGER NOT NULL DEFAULT '0',
`ical_user` TEXT DEFAULT NULL,
`ical_pass` TEXT DEFAULT NULL,
CONSTRAINT `fk_caldav_calendars_user_id` FOREIGN KEY (`user_id`)
REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_caldav_calendars_sources` FOREIGN KEY (`source_id`)
REFERENCES `caldav_sources`(`source_id`) ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE TABLE IF NOT EXISTS `caldav_events` (
`event_id` INTEGER NOT NULL PRIMARY KEY,
`calendar_id` INTEGER NOT NULL DEFAULT '0',
`recurrence_id` INTEGER NOT NULL DEFAULT '0',
`uid` TEXT NOT NULL DEFAULT '',
`instance` TEXT NOT NULL DEFAULT '',
`isexception` tinyINTEGER NOT NULL DEFAULT '0',
`created` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`changed` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`sequence` INTEGER NOT NULL DEFAULT '0',
`start` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`end` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
`recurrence` TEXT DEFAULT NULL,
`title` TEXT NOT NULL,
`description` text NOT NULL,
`location` TEXT NOT NULL DEFAULT '',
`categories` TEXT NOT NULL DEFAULT '',
`url` TEXT NOT NULL DEFAULT '',
`all_day` tinyINTEGER NOT NULL DEFAULT '0',
`free_busy` tinyINTEGER NOT NULL DEFAULT '0',
`priority` tinyINTEGER NOT NULL DEFAULT '0',
`sensitivity` tinyINTEGER NOT NULL DEFAULT '0',
`status` TEXT NOT NULL DEFAULT '',
`alarms` text NULL DEFAULT NULL,
`attendees` text DEFAULT NULL,
`notifyat` datetime DEFAULT NULL,
`caldav_url` TEXT NOT NULL,
`caldav_tag` TEXT DEFAULT NULL,
`caldav_last_change` timestamp NOT NULL ,
FOREIGN KEY (`calendar_id`)
REFERENCES `caldav_calendars`(`calendar_id`) ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE TABLE IF NOT EXISTS `caldav_attachments` (
`attachment_id` INTEGER NOT NULL PRIMARY KEY,
`event_id` INTEGER NOT NULL DEFAULT '0',
`filename` TEXT NOT NULL DEFAULT '',
`mimetype` TEXT NOT NULL DEFAULT '',
`size` INTEGER NOT NULL DEFAULT '0',
`data` TEXT NOT NULL,
FOREIGN KEY (`event_id`)
REFERENCES `caldav_events`(`event_id`) ON DELETE CASCADE ON UPDATE CASCADE
);
REPLACE INTO `system` (`name`, `value`) VALUES ('calendar-caldav-version', '2021082400');
CREATE INDEX caldav_user_name_idx ON caldav_calendars(user_id, name);
CREATE INDEX caldav_uid_idx ON caldav_events(uid);
CREATE INDEX caldav_recurrence_idx ON caldav_events(recurrence_id);
CREATE INDEX caldav_calendar_notify_idx ON caldav_events(calendar_id, notifyat);

View file

@ -23,6 +23,7 @@
*/
require_once 'caldav_sync.php';
require_once 'ical_sync.php';
require_once 'encryption.php';
@ -113,7 +114,7 @@ class caldav_driver extends calendar_driver
if (!empty($this->rc->user->ID)) {
$calendar_ids = array();
$result = $this->rc->db->query('SELECT
cal.calendar_id AS `calendar_id`,
cal.calendar_id AS `id`,
cal.source_id AS `source_id`,
cal.name AS `name`,
cal.color AS `color`,
@ -123,7 +124,7 @@ class caldav_driver extends calendar_driver
s.caldav_user AS `caldav_user`,
s.caldav_pass AS `caldav_pass`,
cal.caldav_last_change AS `caldav_last_change`,
cal.calendar_id AS `id`
cal.is_ical AS `is_ical`
FROM ' . $this->db_calendars . ' AS cal
LEFT JOIN ' .$this->db_sources .' AS s ON (cal.source_id = s.source_id)
WHERE cal.user_id=?
@ -138,13 +139,18 @@ class caldav_driver extends calendar_driver
$arr['rights'] = 'lrswikxteav';
$arr['editable'] = true;
$arr['caldav_pass'] = $this->_decrypt_pass($arr['caldav_pass']);
$this->calendars[$arr['calendar_id']] = $arr;
$calendar_ids[] = $this->rc->db->quote($arr['calendar_id']);
$this->calendars[$arr['id']] = $arr;
$calendar_ids[] = $this->rc->db->quote($arr['id']);
// Init sync client
$cal_id = $arr['calendar_id'];
$this->sync_clients[$cal_id] = new caldav_sync($arr);
if($arr['is_ical']) {
$this->sync_clients[$arr['id']] = new ical_sync($arr);
$cal["readonly"] = true;
$cal["deletable"] = true;
$cal["editable_name"] = true;
}
else {
$this->sync_clients[$arr['id']] = new caldav_sync($arr);
}
}
$this->calendar_ids = join(',', $calendar_ids);
}
@ -170,8 +176,6 @@ class caldav_driver extends calendar_driver
}
}
// 'personal' is unsupported in this driver
// append the virtual birthdays calendar
if ($this->rc->config->get('calendar_contact_birthdays', false)) {
$prefs = $this->rc->config->get('birthday_calendar', array('color' => '87CEFA'));
@ -205,10 +209,23 @@ class caldav_driver extends calendar_driver
*/
public function create_calendar($cal)
{
if(isset($cal['new-source'])) {
if(isset($cal['new-source'])) { //add new source
return $this->create_source($cal);
}
else {
else if($cal['is_ical']) { //add an ics calendar
$cal['caldav_url'] = $cal['ical_url'];
$cal_id = $this->_db_create_calendar($cal);
if($cal_id) {
$this->_read_calendars();
$cal['id'] = $cal_id;
$this->sync_clients[$cal_id] = new ical_sync($cal);
$this->_sync_calendar($cal_id);
return true;
}
else
return false;
}
else { //add a calendar to a source
$result = $this->rc->db->query('SELECT source_id, caldav_url, caldav_user, caldav_pass
FROM ' . $this->db_sources . '
WHERE user_id=? AND source_id=?',
@ -332,19 +349,20 @@ class caldav_driver extends calendar_driver
*
* @return mixed ID of the calendar on success, False on error
*/
private function _db_create_calendar($prop, $source)
private function _db_create_calendar($prop, $source=null)
{
$result = $this->rc->db->query(
"INSERT INTO " . $this->db_calendars . "
(user_id, source_id, name, color, showalarms, caldav_url, caldav_tag)
VALUES (?, ?, ?, ?, ?, ?, ?)",
(user_id, source_id, name, color, showalarms, caldav_url, caldav_tag, is_ical)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
$this->rc->user->ID,
$source['source_id'],
$source ? $source['source_id'] : null,
$prop['name'],
$prop['color'],
$prop['showalarms']?1:0,
$prop['caldav_url'],
isset($prop["caldav_tag"]) ? $prop["caldav_tag"] : null
isset($prop["caldav_tag"]) ? $prop["caldav_tag"] : null,
!!$prop['is_ical']
);
if ($result)
@ -414,10 +432,11 @@ class caldav_driver extends calendar_driver
return $count;
}
else {
if(!$this->calendars[$prop['id']])
if(!isset($this->calendars[$prop['id']]))
return false;
$calendar = $this->calendars[$prop['id']];
if(!$this->sync_clients[$prop['id']]->caldav->delete_calendar())
if(!$calendar['is_ical'] && !$this->sync_clients[$prop['id']]->caldav->delete_calendar())
return false;
$query = $this->rc->db->query(
@ -455,20 +474,14 @@ class caldav_driver extends calendar_driver
return false;
if (!empty($this->calendars)) {
if ($event['calendar'] && !$this->calendars[$event['calendar']])
if (!$event['calendar'] || !$this->calendars[$event['calendar']])
return false;
if (!$event['calendar']) {
$keys = array_keys($this->calendars);
$event['calendar'] = reset($keys);
}
if($event = $this->_save_preprocess($event)) {
$sync_client = $this->sync_clients[$event["calendar"]];
// Only push event if caldav_tag is not set to avoid pushing it twice
if (isset($event["caldav_tag"]) || ($event = $sync_client->create_event($event)) !== false) {
if (isset($event["caldav_tag"]) || ($event = $sync_client->create_event($event)) !== null) {
if ($event_id = $this->_insert_event($event)) {
$this->_update_recurring($event);
}
@ -1878,17 +1891,43 @@ class caldav_driver extends calendar_driver
$this->rc->user->ID
);
if($this->rc->db->num_rows($result)) {
$select = new html_select([
$is_ical = new html_checkbox( array(
'name' => "is_ical",
'value' => 1,
'onload' => 'alert(123)',
'onclick' => '
if(this.checked) {
$("#ical_url").removeClass("hidden");
$("#caldav_url").addClass("hidden");
}
else {
$("#ical_url").addClass("hidden");
$("#caldav_url").removeClass("hidden");
}'
));
$formfields['is_ical'] = array(
'label' => $this->cal->gettext('calendar_is_ical'),
'value' => $is_ical->show(null),
'class' => 'hidden'
);
$ical_url = new html_inputfield( array(
'name' => 'ical_url',
'size' => 20,
'id' => 'ical_url',
'class' => 'hidden'
));
$caldav_url = new html_select([
'name' => 'source_id',
'id' => 'caldav_url'
]);
while($source = $this->rc->db->fetch_assoc($result)) {
$select->add($source['caldav_url'], $source['source_id']);
$caldav_url->add($source['caldav_url'], $source['source_id']);
}
$formfields['source_id'] = array(
$formfields['url'] = array(
'label' => $this->cal->gettext('url'),
'value' => $select->show(null),
'id' => 'caldav_url',
'value' => $caldav_url->show(null) .$ical_url->show(null),
);
}
else {
@ -2139,7 +2178,13 @@ class caldav_driver extends calendar_driver
"caldav_url" => $update["url"],
"caldav_tag" => $update["etag"]));
$event_id = $this->new_event($event);
try {
$event_id = $this->new_event($event);
}
catch(Exception $e) {
self::debug_log($e);
$event_id = 0;
}
if($event_id)
{
self::debug_log("Created event \"$event_id\".");

View file

@ -4,6 +4,7 @@
*
* @version @package_version@
* @author Daniel Morlock <daniel.morlock@awesome-it.de>
* @author JodliDev <jodlidev@gmail.com>
*
* Copyright (C) Awesome IT GbR <info@awesome-it.de>
*
@ -22,8 +23,9 @@
*/
require_once 'caldav_client.php';
require_once 'Isync.php';
class caldav_sync
class caldav_sync implements Isync
{
private $cal_id = null;
private $ctag = null;
@ -67,7 +69,7 @@ class caldav_sync
* Determines whether current calendar needs to be synced
* regarding the CalDAV ctag.
*
* @return True if the current calendar ctag differs from the CalDAV tag which
* @return boolean True if the current calendar ctag differs from the CalDAV tag which
* indicates that there are changes that must be synched. Returns false
* if the calendar is up to date, no sync necesarry.
*/
@ -177,7 +179,7 @@ class caldav_sync
/**
* Fetches event data and attaches it to the given update properties.
*
* @param $updates List of update properties.
* @param $updates array of update properties.
* @return array List of update properties with additional key "remote_event" containing the current caldav event.
*/
private function _get_event_data($updates)
@ -208,7 +210,7 @@ class caldav_sync
* Creates the given event on the CalDAV server.
*
* @param array Hash array with event properties.
* @return Event with updated "caldav_url" and "caldav_tag" attributes, false on error.
* @return array with updated "caldav_url" and "caldav_tag" attributes, null on error.
*/
public function create_event($event)
{
@ -220,7 +222,8 @@ class caldav_sync
caldav_driver::debug_log("Push new event to url ".$props["caldav_url"]);
$result = $this->caldav->put_event($props["caldav_url"], $event);
if($result == false || $result < 0) return false;
if($result == false || $result < 0)
return null;
return array_merge($event, $props);
}
@ -228,7 +231,7 @@ class caldav_sync
* Updates the given event on the CalDAV server.
*
* @param array Hash array with event properties to update, must include "uid", "caldav_url" and "caldav_tag".
* @return True on success, false on error, -1 if the given event/etag is not up to date.
* @return boolean True on success, false on error, -1 if the given event/etag is not up to date.
*/
public function update_event($event)
{
@ -240,7 +243,7 @@ class caldav_sync
* Removes the given event from the caldav server.
*
* @param array Hash array with events properties, must include "caldav_url".
* @return True on success, false on error.
* @return boolean True on success, false on error.
*/
public function remove_event($event)
{

View file

@ -0,0 +1,163 @@
<?php
/**
* iCalendar sync for the Calendar plugin
*
* @version @package_version@
* @author Daniel Morlock <daniel.morlock@awesome-it.de>
* @author JodliDev <jodlidev@gmail.com>
*
* Copyright (C) Awesome IT GbR <info@awesome-it.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
class ical_sync implements Isync
{
const ACTION_NONE = 1;
const ACTION_UPDATE = 2;
const ACTION_CREATE = 4;
private $cal_id = null;
private $url = null;
private $user = null;
private $pass = null;
private $ical = null;
/**
* Default constructor for calendar synchronization adapter.
*
* @param int Calendar id.
* @param array Hash array with ical properties:
* url: Absolute URL to iCAL resource.
*/
public function __construct($props)
{
$this->ical = libcalendaring::get_ical();
$this->cal_id = $props["id"];
$this->url = $props["caldav_url"];
$this->user = isset($props["ical_user"]) ? $props["ical_user"] : null;
$this->pass = isset($props["ical_pass"]) ? $props["ical_pass"] : null;
}
/**
* Determines whether current calendar needs to be synced.
*
* @return boolean True if the current calendar needs to be synced, false otherwise.
*/
public function is_synced()
{
// No change to check that so far.
return false;
}
/**
* Fetches events from iCAL resource and returns updates.
*
* @param array List of local events.
* @return array Tuple containing the following lists:
*
* Hash list for iCAL events to be created or to be updated with the keys:
* local_event: The local event in case of an update.
* remote_event: The current event retrieved from caldav server.
*
* A list of event ids that are in sync.
*/
public function get_updates($events)
{
$context = null;
if($this->user != null && $this->pass != null)
{
$context = stream_context_create(array(
'http' => array(
'header' => "Authorization: Basic " . base64_encode("$this->user:$this->pass")
)
));
}
$vcal = file_get_contents($this->url, false, $context);
$updates = array();
$synced = array();
if($vcal !== false) {
// Hash existing events by uid.
$events_hash = array();
foreach($events as $event) {
$events_hash[$event['uid']] = $event;
}
foreach ($this->ical->import($vcal) as $remote_event) {
// Attach remote event to current calendar
$remote_event['calendar'] = $this->cal_id;
$local_event = null;
if($events_hash[$remote_event['uid']])
$local_event = $events_hash[$remote_event['uid']];
// Determine whether event don't need an update.
if($local_event && $local_event['changed'] >= $remote_event['changed']) {
array_push($synced, $local_event["id"]);
}
else if($local_event) {
array_push($updates, array('local_event' => $local_event, 'remote_event' => $remote_event, 'url' => $this->url));
}
else {
array_push($updates, array('remote_event' => $remote_event, 'url' => $this->url));
}
}
}
return array($updates, $synced);
}
/**
* Getter for current calendar ctag (only for CalDAV).
* @return string
*/
public function get_ctag() {
return 'none';
}
/**
* Creates the given event.
*
* @param array Hash array with event properties.
* @return array with updated "caldav_url" and "caldav_tag" attributes, null on error.
*/
public function create_event($event) {
return $event;
}
/**
* Updates the given event.
*
* @param array Hash array with event properties to update, must include "uid", "caldav_url" and "caldav_tag".
* @return boolean True on success, false on error, -1 if the given event/etag is not up to date.
*/
public function update_event($event) {
return false;
}
/**
* Removes the given event.
*
* @param array Hash array with events properties, must include "caldav_url".
* @return boolean True on success, false on error.
*/
public function remove_event($event) {
return false;
}
}
?>

View file

@ -6,10 +6,12 @@
*
* For translation see https://www.transifex.com/projects/p/kolab/resource/calendar/
*/
$labels['addsources'] = 'Externe Quellen hinzufügen ';
$labels['deletesources'] = 'Externe Quellen löschen ';
$labels['nosources_error'] = 'Keine externen Quellen vorhanden.';
$labels['source_notadded_error'] = 'Externe Quelle konnte nicht hinzugefügt werden.';
$labels['addsources'] = 'CalDAV Quellen hinzufügen';
$labels['deletesources'] = 'CalDAV Quellen löschen';
$labels['nosources_error'] = 'Keine CalDAV Quellen vorhanden.';
$labels['source_notadded_error'] = 'CalDAV Quelle konnte nicht hinzugefügt werden.';
$labels['calendar_is_ical'] = 'Ist ics-Datei';
$labels['default_view'] = 'Standardansicht';
$labels['time_format'] = 'Zeitformatierung';
$labels['timeslots'] = 'Zeitfenster pro Stunde';

View file

@ -6,10 +6,12 @@
*
* For translation see https://www.transifex.com/projects/p/kolab/resource/calendar/
*/
$labels['addsources'] = 'Externe Quellen hinzufügen ';
$labels['deletesources'] = 'Externe Quellen löschen ';
$labels['nosources_error'] = 'Keine externen Quellen vorhanden.';
$labels['source_notadded_error'] = 'Externe Quelle konnte nicht hinzugefügt werden.';
$labels['addsources'] = 'CalDAV Quellen hinzufügen';
$labels['deletesources'] = 'CalDAV Quellen löschen';
$labels['nosources_error'] = 'Keine CalDAV Quellen vorhanden.';
$labels['source_notadded_error'] = 'CalDAV Quelle konnte nicht hinzugefügt werden.';
$labels['calendar_is_ical'] = 'Ist ics-Datei';
$labels['default_view'] = 'Standardansicht';
$labels['time_format'] = 'Zeitformatierung';
$labels['timeslots'] = 'Abschnitte pro Stunde';

View file

@ -6,10 +6,12 @@
*
* For translation see https://www.transifex.com/projects/p/kolab/resource/calendar/
*/
$labels['addsources'] = 'Externe Quellen hinzufügen';
$labels['deletesources'] = 'Externe Quellen löschen';
$labels['nosources_error'] = 'Keine externen Quellen vorhanden.';
$labels['source_notadded_error'] = 'Externe Quelle konnte nicht hinzugefügt werden.';
$labels['addsources'] = 'CalDAV Quellen hinzufügen';
$labels['deletesources'] = 'CalDAV Quellen löschen';
$labels['nosources_error'] = 'Keine CalDAV Quellen vorhanden.';
$labels['source_notadded_error'] = 'CalDAV Quelle konnte nicht hinzugefügt werden.';
$labels['calendar_is_ical'] = 'Ist ics-Datei';
$labels['default_view'] = 'Standardansicht';
$labels['time_format'] = 'Zeitformatierung';
$labels['timeslots'] = 'Zeitfenster pro Stunde';

View file

@ -11,10 +11,11 @@
$labels = array();
//caldav driver
$labels['addsources'] = 'Add external sources';
$labels['deletesources'] = 'Delete external sources';
$labels['nosources_error'] = 'No external sources available.';
$labels['source_notadded_error'] = 'External source could not be added.';
$labels['addsources'] = 'Add CalDAV sources';
$labels['deletesources'] = 'Delete CalDAV sources';
$labels['nosources_error'] = 'No CalDAV sources available.';
$labels['source_notadded_error'] = 'CalDAV source could not be added.';
$labels['calendar_is_ical'] = 'Is ics file';
// preferences
$labels['default_view'] = 'Default view';