diff --git a/dav/README.md b/dav/README.md index b4e7f3ac..a8243972 100644 --- a/dav/README.md +++ b/dav/README.md @@ -6,12 +6,14 @@ It's still in a very early stage, so expect major bugs. Please feel free to repo At the moment, the calendar system supports the following features: - A web-based drag&drop interface for managing events - All-Day-Events, Multi-Day-Events, and time-based events +- Giving the subject, a description, a location and a color for the event (the color is not available through CalDAV, though) - Recurrences (not the whole set of options given in the iCalendar spec, but the most important ones) +- Notification by e-mail. Multiple notifications can be set per event - Multiple calendars per user - Access to the events using CalDAV (using iPhone, Thunderbird Lightning etc., see below) - Read-only access to the friendica-native events (also using CalDAV) - The friendica-contacts are made available using CardDAV (confirmed to work with iOS) -- Giving the subject, a description, a location and a color for the event (the color is not available through CalDAV, though) +- The events of a calendar can be exported as ICS file. ICS files can be imported into a calendar Internationalization: @@ -33,7 +35,6 @@ In case of errors, the SQL-statement to create the tables manually are shown in Functuality missing: (a.k.a. "Roadmap") - Sharing events; all events are private at the moment, therefore this system is not a complete replacement for the friendica-native events - Attendees / Collaboration -- ICS Export and Import Used libraries diff --git a/dav/calendar.friendica.fnk.php b/dav/calendar.friendica.fnk.php index b1b0b3b3..fff3447e 100644 --- a/dav/calendar.friendica.fnk.php +++ b/dav/calendar.friendica.fnk.php @@ -21,8 +21,6 @@ $GLOBALS["CALDAV_PRIVATE_SYSTEM_CALENDARS"] = array(CALDAV_FRIENDICA_MINE, CALDA define("CARDDAV_NAMESPACE_COMMUNITYCONTACTS", 1); define("CARDDAV_NAMESPACE_PHONECONTACTS", 2); -define("CALDAV_DB_VERSION", 2); - define("CALDAV_MAX_YEAR", date("Y") + 5); /** @@ -107,7 +105,11 @@ function dav_compat_principal2namespace($principalUri = "") } -function dav_compat_currentUserPrincipal() { +/** + * @return string + */ +function dav_compat_currentUserPrincipal() +{ $a = get_app(); return "principals/users/" . strtolower($a->user["nickname"]); } @@ -172,12 +174,36 @@ function wdcal_calendar_factory($namespace, $namespace_id, $uri, $calendar = nul * @return Sabre_CalDAV_Backend_Common * @throws Exception */ -function wdcal_calendar_factory_by_id($calendar_id) { +function wdcal_calendar_factory_by_id($calendar_id) +{ $calendar = Sabre_CalDAV_Backend_Common::loadCalendarById($calendar_id); return wdcal_calendar_factory($calendar["namespace"], $calendar["namespace_id"], $calendar["uri"], $calendar); } - +/** + * @param int $user_id + * @param bool $withcheck + * @return array + */ +function wdcal_create_std_calendars_get_statements($user_id, $withcheck = true) +{ + $stms = array(); + $a = get_app(); + $uris = array( + 'private' => t("Private Calendar"), + CALDAV_FRIENDICA_MINE => t("Friendica Events: Mine"), + CALDAV_FRIENDICA_CONTACTS => t("Friendica Events: Contacts"), + ); + foreach ($uris as $uri => $name) { + $cals = q("SELECT * FROM %s%scalendars WHERE `namespace` = %d AND `namespace_id` = %d AND `uri` = '%s'", + CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CALDAV_NAMESPACE_PRIVATE, IntVal($user_id), dbesc($uri)); + if (count($cals) == 0 || !$withcheck) $stms[] = + sprintf("INSERT INTO %s%scalendars (`namespace`, `namespace_id`, `displayname`, `timezone`, `ctag`, `uri`, `has_vevent`, `has_vtodo`) + VALUES (%d, %d, '%s', '%s', 1, '%s', 1, 0)", + CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CALDAV_NAMESPACE_PRIVATE, IntVal($user_id), dbesc($name), dbesc($a->timezone), dbesc($uri)); + } + return $stms; +} /** */ @@ -189,19 +215,6 @@ function wdcal_create_std_calendars() $privates = q("SELECT COUNT(*) num FROM %s%scalendars WHERE `namespace` = %d AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CALDAV_NAMESPACE_PRIVATE, IntVal($a->user["uid"])); if ($privates[0]["num"] > 0) return; - $uris = array( - 'private' => t("Private Calendar"), - CALDAV_FRIENDICA_MINE => t("Friendica Events: Mine"), - CALDAV_FRIENDICA_CONTACTS => t("Friendica Events: Contacts"), - ); - foreach ($uris as $uri => $name) { - $cals = q("SELECT * FROM %s%scalendars WHERE `namespace` = %d AND `namespace_id` = %d AND `uri` = '%s'", - CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CALDAV_NAMESPACE_PRIVATE, $a->user["uid"], dbesc($uri)); - if (count($cals) == 0) { - q("INSERT INTO %s%scalendars (`namespace`, `namespace_id`, `displayname`, `timezone`, `ctag`, `uri`, `has_vevent`, `has_vtodo`) VALUES (%d, %d, '%s', '%s', 1, '%s', 1, 0)", - CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CALDAV_NAMESPACE_PRIVATE, IntVal($a->user["uid"]), dbesc($name), dbesc($a->timezone), dbesc($uri) - ); - } - } - + $stms = wdcal_create_std_calendars_get_statements($a->user["uid"]); + foreach ($stms as $stmt) q($stmt); } diff --git a/dav/common/calendar.fnk.php b/dav/common/calendar.fnk.php index 01af64fb..b03ed7be 100644 --- a/dav/common/calendar.fnk.php +++ b/dav/common/calendar.fnk.php @@ -7,6 +7,8 @@ define("DAV_DISPLAYNAME", "{DAV:}displayname"); define("DAV_CALENDARCOLOR", "{http://apple.com/ns/ical/}calendar-color"); +class DAVVersionMismatchException extends Exception {} + class vcard_source_data_email { @@ -357,8 +359,8 @@ function dav_create_empty_vevent($uid = "") /** - * @param Sabre_VObject_Component_VCalendar $vObject - * @return Sabre_VObject_Component_VEvent|null + * @param Sabre_VObject_Component_VEvent $vObject + * @return Sabre_VObject_Component|null */ function dav_get_eventComponent(&$vObject) { diff --git a/dav/common/dav_caldav_backend_private.inc.php b/dav/common/dav_caldav_backend_private.inc.php index 86da0270..6ca24c28 100644 --- a/dav/common/dav_caldav_backend_private.inc.php +++ b/dav/common/dav_caldav_backend_private.inc.php @@ -152,6 +152,7 @@ class Sabre_CalDAV_Backend_Private extends Sabre_CalDAV_Backend_Common * common one is '{DAV:}displayname'. * * @param string $principalUri + * @throws DAVVersionMismatchException * @return array */ public function getCalendarsForUser($principalUri) @@ -162,6 +163,7 @@ class Sabre_CalDAV_Backend_Private extends Sabre_CalDAV_Backend_Common $cals = q("SELECT * FROM %s%scalendars WHERE `namespace` = %d AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $this->getNamespace(), IntVal($n["namespace_id"])); $ret = array(); foreach ($cals as $cal) { + if (!isset($cal["uri"])) throw new DAVVersionMismatchException(); if (in_array($cal["uri"], $GLOBALS["CALDAV_PRIVATE_SYSTEM_CALENDARS"])) continue; $dat = array( diff --git a/dav/database-init.inc.php b/dav/database-init.inc.php index 6372bf44..8cdd9b9b 100644 --- a/dav/database-init.inc.php +++ b/dav/database-init.inc.php @@ -9,103 +9,71 @@ function dav_get_update_statements($from_version) { $stms = array(); - if ($from_version <= 0) { - $stms[] = "ALTER TABLE `dav_calendars` ADD `uri` VARCHAR( 50 ) NULL DEFAULT NULL AFTER `description` , ADD `has_vevent` TINYINT NOT NULL DEFAULT '1' AFTER `uri` , ADD `has_vtodo` TINYINT NOT NULL DEFAULT '1' AFTER `has_vevent`"; + if ($from_version == 1) { + $stms[] = "ALTER TABLE `dav_calendarobjects` + ADD `calendar_id` INT NOT NULL AFTER `namespace_id` , + ADD `user_temp` INT NOT NULL AFTER `calendar_id` "; + $stms[] = "ALTER TABLE `dav_calendarobjects` + ADD `componentType` ENUM( 'VEVENT', 'VTODO' ) NOT NULL DEFAULT 'VEVENT' AFTER `lastmodified` , + ADD `firstOccurence` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `componentType` , + ADD `lastOccurence` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' AFTER `firstOccurence`"; + $stms[] = "UPDATE dav_calendarobjects a JOIN dav_calendars b ON a.namespace = b.namespace AND a.namespace_id = b.namespace_id SET a.user_temp = b.uid"; + $stms[] = "DROP TABLE IF EXISTS + `dav_addressbooks_community` , + `dav_addressbooks_phone` , + `dav_cache_synchronized` , + `dav_caldav_log` , + `dav_calendars` , + `dav_cal_virtual_object_cache` , + `dav_cards` , + `dav_jqcalendar` , + `dav_locks` , + `dav_notifications` ;"; - $stms[] = "UPDATE `dav_calendars` SET `uri` = 'private' WHERE `namespace` = 1"; - $stms[] = "UPDATE `dav_calendars` SET `uri` = 'friendica-mine' WHERE `namespace` = 2 AND `namespace_id` = 1"; - $stms[] = "UPDATE `dav_calendars` SET `uri` = 'friendica-contacts' WHERE `namespace` = 2 AND `namespace_id` = 2"; - $stms[] = "ALTER TABLE `dav_calendars` DROP PRIMARY KEY "; - $stms[] = "ALTER TABLE `dav_calendars` ADD `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST "; + $stms = array_merge($stms, dav_get_create_statements(array("dav_calendarobjects"))); - $stms[] = "ALTER TABLE `dav_calendarobjects` ADD `calendar_id` INT NOT NULL AFTER `id` "; - $stms[] = "UPDATE `dav_calendarobjects` a JOIN `dav_calendars` b ON a.`namespace` = b.`namespace` AND a.`namespace_id` = b.`namespace_id` SET a.`calendar_id` = b.`id`"; - $stms[] = "ALTER TABLE `dav_calendarobjects` DROP `namespace` , DROP `namespace_id` ;"; - $stms[] = "ALTER TABLE `dav_calendarobjects` ADD INDEX ( `calendar_id` ) "; - $stms[] = "ALTER TABLE `dav_calendarobjects` ADD `componentType` ENUM( 'VEVENT', 'VTODO' ) NOT NULL DEFAULT 'VEVENT' AFTER `calendardata` , - ADD `firstOccurence` TIMESTAMP NOT NULL AFTER `lastmodified` , - ADD `lastOccurence` TIMESTAMP NOT NULL AFTER `firstOccurence`"; + $user_ids = q("SELECT DISTINCT `uid` FROM %s%scalendars", CALDAV_SQL_DB, CALDAV_SQL_PREFIX); + foreach ($user_ids as $user) $stms = array_merge($stms, wdcal_create_std_calendars_get_statements($user["uid"], false)); - $stms[] = "DROP TABLE `dav_jqcalendar`"; - $stms[] = "CREATE TABLE IF NOT EXISTS `dav_jqcalendar` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `ical_recurr_uri` varchar(100) DEFAULT NULL, - `calendar_id` int(10) unsigned NOT NULL, - `calendarobject_id` int(10) unsigned NOT NULL, - `Subject` varchar(1000) NOT NULL, - `StartTime` timestamp NULL DEFAULT NULL, - `EndTime` timestamp NULL DEFAULT NULL, - `IsEditable` tinyint(3) unsigned NOT NULL, - `IsAllDayEvent` tinyint(4) NOT NULL, - `IsRecurring` tinyint(4) NOT NULL, - `Color` CHAR(6) DEFAULT NULL, - PRIMARY KEY (`id`), - KEY `calendarByStart` (`calendar_id`,`StartTime`), - KEY `calendarobject_id` (`calendarobject_id`,`ical_recurr_uri`) - ) DEFAULT CHARSET=utf8 "; + $stms[] = "UPDATE dav_calendarobjects a JOIN dav_calendars b + ON b.`namespace` = " . CALDAV_NAMESPACE_PRIVATE . " AND a.`user_temp` = b.`namespace_id` AND b.`uri` = 'private' + SET a.`calendar_id` = b.`id`"; + $stms[] = "ALTER TABLE `dav_calendarobjects` DROP `namespace`, DROP `namespace_id`, DROP `user_temp`"; - $stms[] = "ALTER TABLE `dav_notifications` ADD `calendar_id` INT NOT NULL AFTER `ical_recurr_uri` "; - $stms[] = "ALTER TABLE `dav_notifications` DROP INDEX `ical_uri` , ADD INDEX `ical_uri` ( `calendar_id` , `ical_uri` , `ical_recurr_uri` ) "; - $stms[] = "TRUNCATE TABLE `dav_notifications`"; - $stms[] = "ALTER TABLE `dav_notifications` DROP `namespace` , DROP `namespace_id`"; - - $stms[] = "TRUNCATE TABLE `dav_cal_virtual_object_cache`"; - $stme[] = "ALTER TABLE `dav_cal_virtual_object_cache` ADD `calendar_id` INT UNSIGNED NOT NULL AFTER `id` "; - $stms[] = "ALTER TABLE `dav_cal_virtual_object_cache` DROP INDEX `ref_type` , ADD INDEX `ref_type` ( `calendar_id` , `data_end` ) "; - $stms[] = "ALTER TABLE `dav_cal_virtual_object_cache` DROP `uid`, DROP `namespace` , DROP `namespace_id` "; - - $stms[] = "CREATE TABLE `friendica`.`dav_cal_virtual_object_sync` ( - `calendar_id` INT UNSIGNED NOT NULL , - `date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP , - PRIMARY KEY ( `calendar_id` ) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8"; - - $stms[] = "DROP TABLE `dav_cache_synchronized` "; - - $stms[] = "UPDATE `dav_calendars` SET `namespace` = 1, `namespace_id` = `uid`"; // last - $stms[] = "ALTER TABLE `dav_calendars` DROP `uid`"; } return $stms; } /** + * @param array $except * @return array */ -function dav_get_create_statements() +function dav_get_create_statements($except = array()) { $arr = array(); - $arr[] = "CREATE TABLE IF NOT EXISTS `dav_addressbooks_community` ( - `uid` int(11) NOT NULL, + if (!in_array("dav_addressbooks_community", $except)) $arr[] = "CREATE TABLE IF NOT EXISTS `dav_addressbooks_community` ( + `uid` int(11) NOT NULL, `ctag` int(11) unsigned NOT NULL DEFAULT '1', PRIMARY KEY (`uid`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8"; +) ENGINE=MyISAM DEFAULT CHARSET=utf8"; - $arr[] = "CREATE TABLE IF NOT EXISTS `dav_addressbooks_phone` ( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + if (!in_array("dav_addressbooks_phone", $except)) $arr[] = "CREATE TABLE IF NOT EXISTS `dav_addressbooks_phone` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `uid` int(11) NOT NULL, - `principaluri` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL, - `displayname` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, - `uri` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL, - `description` text COLLATE utf8_unicode_ci, + `principaluri` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL, + `displayname` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL, + `uri` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL, + `description` text CHARACTER SET utf8 COLLATE utf8_unicode_ci, `ctag` int(11) unsigned NOT NULL DEFAULT '1', PRIMARY KEY (`id`), UNIQUE KEY `principaluri` (`principaluri`,`uri`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8"; - $arr[] = "CREATE TABLE IF NOT EXISTS `dav_cache_synchronized` ( - `uid` mediumint(8) unsigned NOT NULL, - `namespace` smallint(6) NOT NULL, - `namespace_id` int(11) NOT NULL, - `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (`uid`,`namespace`,`namespace_id`), - KEY `namespace` (`namespace`,`namespace_id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8"; - - $arr[] = "CREATE TABLE IF NOT EXISTS `dav_caldav_log` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + if (!in_array("dav_caldav_log", $except)) $arr[] = "CREATE TABLE IF NOT EXISTS `dav_caldav_log` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `uid` mediumint(9) NOT NULL, `ip` varchar(15) NOT NULL, `user_agent` varchar(100) NOT NULL, @@ -116,127 +84,111 @@ function dav_get_create_statements() KEY `mitglied` (`uid`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8"; - $arr[] = "CREATE TABLE IF NOT EXISTS `dav_calendarobjects` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `namespace` mediumint(9) NOT NULL, - `namespace_id` int(10) unsigned NOT NULL, + if (!in_array("dav_calendarobjects", $except)) $arr[] = "CREATE TABLE IF NOT EXISTS `dav_calendarobjects` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `calendar_id` int(11) NOT NULL, `calendardata` text, `uri` varchar(200) NOT NULL, `lastmodified` timestamp NULL DEFAULT NULL, + `componentType` enum('VEVENT','VTODO') NOT NULL DEFAULT 'VEVENT', + `firstOccurence` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `lastOccurence` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `etag` varchar(15) NOT NULL, `size` int(10) unsigned NOT NULL, PRIMARY KEY (`id`), - UNIQUE KEY `uri` (`uri`,`namespace`,`namespace_id`), - KEY `namespace` (`namespace`,`namespace_id`) + UNIQUE KEY `uri` (`uri`), + KEY `calendar_id` (`calendar_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8"; - $arr[] = "CREATE TABLE IF NOT EXISTS `dav_calendars` ( - `namespace` mediumint(9) NOT NULL, + if (!in_array("dav_calendars", $except)) $arr[] = "CREATE TABLE IF NOT EXISTS `dav_calendars` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `namespace` mediumint(9) NOT NULL, `namespace_id` int(10) unsigned NOT NULL, - `uid` mediumint(8) unsigned NOT NULL, `calendarorder` int(11) NOT NULL DEFAULT '1', - `calendarcolor` varchar(20) NOT NULL DEFAULT '#5858FF', + `calendarcolor` char(6) NOT NULL DEFAULT '5858FF', `displayname` varchar(200) NOT NULL, `timezone` text NOT NULL, `description` varchar(500) NOT NULL, - `uri` varchar(50) DEFAULT NULL, + `uri` varchar(50) NOT NULL DEFAULT '', `has_vevent` tinyint(4) NOT NULL DEFAULT '1', `has_vtodo` tinyint(4) NOT NULL DEFAULT '1', `ctag` int(10) unsigned NOT NULL, - PRIMARY KEY (`namespace`,`namespace_id`), - KEY `uid` (`uid`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8"; + PRIMARY KEY (`id`), + UNIQUE KEY (`namespace` , `namespace_id` , `uri`), + KEY `uri` (`uri`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8"; - $arr[] = "CREATE TABLE IF NOT EXISTS `dav_cal_virtual_object_cache` ( - `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, - `uid` mediumint(8) unsigned NOT NULL, - `namespace` mediumint(9) NOT NULL, - `namespace_id` int(11) NOT NULL DEFAULT '0', + if (!in_array("dav_cal_virtual_object_cache", $except)) $arr[] = "CREATE TABLE IF NOT EXISTS `dav_cal_virtual_object_cache` ( + `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, + `calendar_id` int(10) unsigned NOT NULL, `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `data_uri` char(80) NOT NULL, - `data_subject` varchar(1000) NOT NULL, + `data_summary` varchar(1000) NOT NULL, `data_location` varchar(1000) NOT NULL, - `data_description` text NOT NULL, `data_start` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `data_end` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `data_allday` tinyint(4) NOT NULL, `data_type` varchar(20) NOT NULL, - `ical` text NOT NULL, - `ical_size` int(11) NOT NULL, - `ical_etag` varchar(15) NOT NULL, + `calendardata` text NOT NULL, + `size` int(11) NOT NULL, + `etag` varchar(15) NOT NULL, PRIMARY KEY (`id`), - KEY `ref_type` (`namespace`,`namespace_id`), - KEY `mitglied` (`uid`,`data_end`), - KEY `data_uri` (`data_uri`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8"; + KEY `data_uri` (`data_uri`), + KEY `ref_type` (`calendar_id`,`data_end`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8"; - $arr[] = "CREATE TABLE IF NOT EXISTS `dav_cards` ( - `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + if (!in_array("dav_cal_virtual_object_sync", $except)) $arr[] = "CREATE TABLE IF NOT EXISTS `dav_cal_virtual_object_sync` ( + `calendar_id` int(10) unsigned NOT NULL, + `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`calendar_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8"; + + if (!in_array("dav_cards", $except)) $arr[] = "CREATE TABLE IF NOT EXISTS `dav_cards` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `namespace` tinyint(3) unsigned NOT NULL, `namespace_id` int(11) unsigned NOT NULL, `contact` int(11) DEFAULT NULL, - `carddata` mediumtext COLLATE utf8_unicode_ci, - `uri` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL, + `carddata` mediumtext CHARACTER SET utf8 COLLATE utf8_unicode_ci, + `uri` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL, `lastmodified` int(11) unsigned DEFAULT NULL, `manually_edited` tinyint(4) NOT NULL DEFAULT '0', `manually_deleted` tinyint(4) NOT NULL DEFAULT '0', - `etag` varchar(15) COLLATE utf8_unicode_ci NOT NULL, + `etag` varchar(15) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, `size` int(10) unsigned NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `namespace` (`namespace`,`namespace_id`,`contact`), KEY `contact` (`contact`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8"; +) ENGINE=InnoDB DEFAULT CHARSET=utf8"; - $arr[] = "CREATE TABLE IF NOT EXISTS `dav_jqcalendar` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `uid` int(10) unsigned NOT NULL, - `ical_uri` varchar(200) NOT NULL, - `ical_recurr_uri` varchar(100) NOT NULL, - `namespace` mediumint(9) NOT NULL, - `namespace_id` int(11) NOT NULL, - `permission_edit` tinyint(4) NOT NULL DEFAULT '1', - `Subject` varchar(1000) DEFAULT NULL, - `Location` varchar(1000) DEFAULT NULL, - `Description` text, + if (!in_array("dav_jqcalendar", $except)) $arr[] = "CREATE TABLE IF NOT EXISTS `dav_jqcalendar` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `ical_recurr_uri` varchar(100) DEFAULT NULL, + `calendar_id` int(10) unsigned NOT NULL, + `calendarobject_id` int(10) unsigned NOT NULL, + `Summary` varchar(100) NOT NULL, `StartTime` timestamp NULL DEFAULT NULL, `EndTime` timestamp NULL DEFAULT NULL, - `IsAllDayEvent` smallint(6) NOT NULL, - `Color` varchar(20) DEFAULT NULL, - `RecurringRule` varchar(500) DEFAULT NULL, + `IsEditable` tinyint(3) unsigned NOT NULL, + `IsAllDayEvent` tinyint(4) NOT NULL, + `IsRecurring` tinyint(4) NOT NULL, + `Color` char(6) DEFAULT NULL, PRIMARY KEY (`id`), - KEY `user` (`uid`,`StartTime`), - KEY `zuord_typ` (`namespace`,`namespace_id`), - KEY `ical_uri` (`ical_uri`,`ical_recurr_uri`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8"; + KEY `calendarByStart` (`calendar_id`,`StartTime`), + KEY `calendarobject_id` (`calendarobject_id`,`ical_recurr_uri`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8"; - $arr[] = "CREATE TABLE IF NOT EXISTS `dav_locks` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `owner` varchar(100) DEFAULT NULL, - `timeout` int(10) unsigned DEFAULT NULL, - `created` int(11) DEFAULT NULL, - `token` varchar(100) DEFAULT NULL, - `scope` tinyint(4) DEFAULT NULL, - `depth` tinyint(4) DEFAULT NULL, - `uri` text, - PRIMARY KEY (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8"; - - - $arr[] = "CREATE TABLE IF NOT EXISTS `dav_notifications` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `uid` int(10) unsigned NOT NULL, - `ical_uri` varchar(200) NOT NULL, - `ical_recurr_uri` varchar(100) NOT NULL, - `namespace` mediumint(8) unsigned NOT NULL, - `namespace_id` int(10) unsigned NOT NULL, + if (!in_array("dav_notifications", $except)) $arr[] = "CREATE TABLE IF NOT EXISTS `dav_notifications` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `ical_recurr_uri` varchar(100) DEFAULT NULL, + `calendar_id` int(11) NOT NULL, + `calendarobject_id` int(10) unsigned NOT NULL, + `action` enum('email','display') NOT NULL DEFAULT 'email', `alert_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `rel_type` enum('second','minute','hour','day','week','month','year') NOT NULL, - `rel_value` mediumint(9) NOT NULL, `notified` tinyint(4) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `notified` (`notified`,`alert_date`), - KEY `ical_uri` (`uid`,`ical_uri`,`ical_recurr_uri`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8"; + KEY `calendar_id` (`calendar_id`,`calendarobject_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8"; return $arr; } @@ -246,10 +198,11 @@ function dav_get_create_statements() */ function dav_check_tables() { - $dbv = get_config("dav", "db_version"); - if ($dbv == CALDAV_DB_VERSION) return 0; // Correct - if (is_numeric($dbv) || $dbv == "CALDAV_DB_VERSION") return 1; // Older version (update needed) - return -1; // Not installed + $x = q("DESCRIBE %s%scalendars", CALDAV_SQL_DB, CALDAV_SQL_PREFIX); + if (!$x) return -1; + if (count($x) == 9) return 1; // Version 0.1 + if (count($x) == 12) return 0; // Correct + return -2; // Unknown version } @@ -267,8 +220,6 @@ function dav_create_tables() if ($db->error) $errors[] = $db->error; } - if (count($errors) == 0) set_config("dav", "db_version", CALDAV_DB_VERSION); - return $errors; } @@ -277,9 +228,9 @@ function dav_create_tables() */ function dav_upgrade_tables() { - $dbv = get_config("dav", "db_version"); - if ($dbv == "CALDAV_DB_VERSION") $ver = 0; - else $ver = IntVal($dbv); + $ver = dav_check_tables(); + if (!in_array($ver, array(1) )) return array("Unknown error"); + $stms = dav_get_update_statements($ver); $errors = array(); @@ -289,7 +240,5 @@ function dav_upgrade_tables() if ($db->error) $errors[] = $db->error; } - if (count($errors) == 0) set_config("dav", "db_version", CALDAV_DB_VERSION); - return $errors; } \ No newline at end of file diff --git a/dav/dav_caldav_backend_virtual_friendica.inc.php b/dav/dav_caldav_backend_virtual_friendica.inc.php index e25dce36..4f761da1 100644 --- a/dav/dav_caldav_backend_virtual_friendica.inc.php +++ b/dav/dav_caldav_backend_virtual_friendica.inc.php @@ -133,7 +133,7 @@ class Sabre_CalDAV_Backend_Friendica extends Sabre_CalDAV_Backend_Virtual "is_allday" => ($allday ? 1 : 0), "is_moredays" => (substr($start, 0, 10) != substr($finish, 0, 10)), "is_recurring" => ($row["type"] == "birthday"), - "color" => "#f8f8ff", + "color" => "7878ff", "is_editable" => 0, "is_editable_quick" => 0, "location" => $row["location"], diff --git a/dav/main.php b/dav/main.php index e8932034..86c365c0 100644 --- a/dav/main.php +++ b/dav/main.php @@ -118,52 +118,55 @@ function dav_content() } $x = ""; - - if ($a->argv[1] == "settings") { - return wdcal_getSettingsPage($a); - } elseif ($a->argv[1] == "wdcal") { - if (isset($a->argv[2]) && strlen($a->argv[2]) > 0) { - if ($a->argv[2] == "new") { - $o = ""; - if (isset($_REQUEST["save"])) { - check_form_security_token_redirectOnErr($a->get_baseurl() . "/dav/wdcal/", "caledit"); - $ret = wdcal_postEditPage("new", "", $a->user["uid"], $a->timezone, $a->get_baseurl() . "/dav/wdcal/"); - if ($ret["ok"]) notice($ret["msg"]); - else info($ret["msg"]); - goaway($a->get_baseurl() . "/dav/wdcal/"); - } - $o .= wdcal_getNewPage(); - return $o; - } else { - $calendar_id = IntVal($a->argv[2]); - if (isset($a->argv[3]) && $a->argv[3] == "ics-export") { - wdcal_print_user_ics($calendar_id); - } elseif (isset($a->argv[3]) && $a->argv[3] == "ics-import") { - return wdcal_import_user_ics($calendar_id); - } elseif (isset($a->argv[3]) && $a->argv[3] > 0) { - if (isset($a->argv[4]) && $a->argv[4] == "edit") { - $o = ""; - if (isset($_REQUEST["save"])) { - check_form_security_token_redirectOnErr($a->get_baseurl() . "/dav/wdcal/", "caledit"); - $ret = wdcal_postEditPage($a->argv[3], $a->user["uid"], $a->timezone, $a->get_baseurl() . "/dav/wdcal/"); - if ($ret["ok"]) notice($ret["msg"]); - else info($ret["msg"]); - goaway($a->get_baseurl() . "/dav/wdcal/"); - } - $o .= wdcal_getEditPage($calendar_id, $a->argv[3]); - return $o; - } else { - return wdcal_getDetailPage($calendar_id, $a->argv[3]); + try { + if ($a->argv[1] == "settings") { + return wdcal_getSettingsPage($a); + } elseif ($a->argv[1] == "wdcal") { + if (isset($a->argv[2]) && strlen($a->argv[2]) > 0) { + if ($a->argv[2] == "new") { + $o = ""; + if (isset($_REQUEST["save"])) { + check_form_security_token_redirectOnErr($a->get_baseurl() . "/dav/wdcal/", "caledit"); + $ret = wdcal_postEditPage("new", "", $a->user["uid"], $a->timezone, $a->get_baseurl() . "/dav/wdcal/"); + if ($ret["ok"]) notice($ret["msg"]); + else info($ret["msg"]); + goaway($a->get_baseurl() . "/dav/wdcal/"); } + $o .= wdcal_getNewPage(); + return $o; } else { - // @TODO Edit Calendar + $calendar_id = IntVal($a->argv[2]); + if (isset($a->argv[3]) && $a->argv[3] == "ics-export") { + wdcal_print_user_ics($calendar_id); + } elseif (isset($a->argv[3]) && $a->argv[3] == "ics-import") { + return wdcal_import_user_ics($calendar_id); + } elseif (isset($a->argv[3]) && $a->argv[3] > 0) { + if (isset($a->argv[4]) && $a->argv[4] == "edit") { + $o = ""; + if (isset($_REQUEST["save"])) { + check_form_security_token_redirectOnErr($a->get_baseurl() . "/dav/wdcal/", "caledit"); + $ret = wdcal_postEditPage($a->argv[3], $a->user["uid"], $a->timezone, $a->get_baseurl() . "/dav/wdcal/"); + if ($ret["ok"]) notice($ret["msg"]); + else info($ret["msg"]); + goaway($a->get_baseurl() . "/dav/wdcal/"); + } + $o .= wdcal_getEditPage($calendar_id, $a->argv[3]); + return $o; + } else { + return wdcal_getDetailPage($calendar_id, $a->argv[3]); + } + } else { + // @TODO Edit Calendar + } } + } else { + $server = dav_create_server(true, true, false); + $cals = dav_get_current_user_calendars($server, DAV_ACL_READ); + $x = wdcal_printCalendar($cals, array(), $a->get_baseurl() . "/dav/wdcal/feed/", "week", 0, 200); } - } else { - $server = dav_create_server(true, true, false); - $cals = dav_get_current_user_calendars($server, DAV_ACL_READ); - $x = wdcal_printCalendar($cals, array(), $a->get_baseurl() . "/dav/wdcal/feed/", "week", 0, 200); } + } catch (DAVVersionMismatchException $e) { + $x = t("The current version of this plugin has not been set up correctly. Please contact the system administrator of your installation of friendica to fix this."); } return $x; } @@ -208,7 +211,6 @@ function dav_profile_tabs_hook(&$a, &$b) } - /** * @param App $a * @param object $b @@ -220,9 +222,9 @@ function dav_cron(&$a, &$b) $r = q("SELECT * FROM %s%snotifications WHERE `notified` = 0 AND `alert_date` <= NOW()", CALDAV_SQL_DB, CALDAV_SQL_PREFIX); foreach ($r as $not) { q("UPDATE %s%snotifications SET `notified` = 1 WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $not["id"]); - $event = q("SELECT * FROM %s%sjqcalendar WHERE `calendarobject_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $not["calendarobject_id"]); - $calendar = q("SELECT * FROM %s%scalendars WHERE `id` = %d", CALDAV_SQL_DB,CALDAV_SQL_PREFIX, $not["calendar_id"]); - $users = array(); + $event = q("SELECT * FROM %s%sjqcalendar WHERE `calendarobject_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $not["calendarobject_id"]); + $calendar = q("SELECT * FROM %s%scalendars WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $not["calendar_id"]); + $users = array(); if (count($calendar) != 1 || count($event) == 0) continue; switch ($calendar[0]["namespace"]) { case CALDAV_NAMESPACE_PRIVATE: @@ -232,20 +234,21 @@ function dav_cron(&$a, &$b) break; } switch ($not["action"]) { - case "email": case "display": // @TODO implement "Display" + case "email": + case "display": // @TODO implement "Display" foreach ($users as $user) { - $find = array( "%to%" , "%event%", "%url%"); - $repl = array($user["username"], $event[0]["Summary"], $a->get_baseurl() . "/dav/wdcal/" . $calendar[0]["id"] . "/" . $not["calendarobject_id"] . "/"); + $find = array("%to%", "%event%", "%url%"); + $repl = array($user["username"], $event[0]["Summary"], $a->get_baseurl() . "/dav/wdcal/" . $calendar[0]["id"] . "/" . $not["calendarobject_id"] . "/"); $text_text = str_replace($find, $repl, "Hi %to%!\n\nThe event \"%event%\" is about to begin:\n%url%"); $text_html = str_replace($find, $repl, "Hi %to%!
\n
\nThe event \"%event%\" is about to begin:
\n%url%"); - $params = array( - 'fromName' => FRIENDICA_PLATFORM, - 'fromEmail' => t('noreply') . '@' . $a->get_hostname(), - 'replyTo' => t('noreply') . '@' . $a->get_hostname(), - 'toEmail' => $user["email"], - 'messageSubject' => t("Notification: " . $event[0]["Summary"]), - 'htmlVersion' => $text_html, - 'textVersion' => $text_text, + $params = array( + 'fromName' => FRIENDICA_PLATFORM, + 'fromEmail' => t('noreply') . '@' . $a->get_hostname(), + 'replyTo' => t('noreply') . '@' . $a->get_hostname(), + 'toEmail' => $user["email"], + 'messageSubject' => t("Notification: " . $event[0]["Summary"]), + 'htmlVersion' => $text_html, + 'textVersion' => $text_text, 'additionalMailHeader' => "", ); require_once('include/enotify.php'); @@ -257,8 +260,6 @@ function dav_cron(&$a, &$b) } - - /** * @param App $a * @param null|object $o @@ -277,7 +278,10 @@ function dav_plugin_admin_post(&$a = null, &$o = null) } if (isset($_REQUEST["upgrade"])) { $errs = dav_upgrade_tables(); - if (count($errs) == 0) info(t('The database tables have been updated.') . EOL); + if (count($errs) == 0) { + renderAllCalDavEntries(); + info(t('The database tables have been updated.') . EOL); + } else notice(t("An error occurred during the update.") . EOL); } } @@ -303,18 +307,30 @@ function dav_plugin_admin(&$a, &$o) $o .= t('Installed'); break; case 1: - $o .= t('Upgrade needed') . "

"; + $o .= "" . t('Upgrade needed') . "
" . t("Please back up all calendar data (the tables beginning with dav_*) before proceeding. While all calendar events should be converted to the new database structure, it's always safe to have a backup. Below, you can have a look at the database-queries that will be made when pressing the 'update'-button.") . "

"; break; case -1: $o .= t('Not installed') . "

"; break; + case -2: + default: + $o .= t('Unknown') . "

" . t("Something really went wrong. I cannot recover from this state automatically, sorry. Please go to the database backend, back up the data, and delete all tables beginning with 'dav_' manually. Afterwards, this installation routine should be able to reinitialize the tables automatically."); + break; } $o .= "

"; $o .= "

" . t("Troubleshooting") . "

"; $o .= "

" . t("Manual creation of the database tables:") . "

"; $o .= "" . t("Show SQL-statements") . ""; }