]> git.mxchange.org Git - friendica-addons.git/commitdiff
Move friendica-specific parts into an own subdirectory
authorTobias Hößl <tobias@hoessl.eu>
Sat, 4 Aug 2012 08:46:11 +0000 (08:46 +0000)
committerTobias Hößl <tobias@hoessl.eu>
Sat, 4 Aug 2012 08:46:11 +0000 (08:46 +0000)
21 files changed:
dav/FriendicaACLPlugin.inc.php [deleted file]
dav/calendar.friendica.fnk.php [deleted file]
dav/database-init.inc.php [deleted file]
dav/dav.php
dav/dav_caldav_backend_virtual_friendica.inc.php [deleted file]
dav/dav_carddav_backend_virtual_friendica.inc.php [deleted file]
dav/dav_friendica_auth.inc.php [deleted file]
dav/dav_friendica_principal.inc.php [deleted file]
dav/friendica/FriendicaACLPlugin.inc.php [new file with mode: 0644]
dav/friendica/calendar.friendica.fnk.php [new file with mode: 0644]
dav/friendica/database-init.inc.php [new file with mode: 0644]
dav/friendica/dav_caldav_backend_virtual_friendica.inc.php [new file with mode: 0644]
dav/friendica/dav_carddav_backend_virtual_friendica.inc.php [new file with mode: 0644]
dav/friendica/dav_friendica_auth.inc.php [new file with mode: 0644]
dav/friendica/dav_friendica_principal.inc.php [new file with mode: 0644]
dav/friendica/layout.fnk.php [new file with mode: 0644]
dav/friendica/main.php [new file with mode: 0644]
dav/friendica/wdcal.css [new file with mode: 0644]
dav/layout.fnk.php [deleted file]
dav/main.php [deleted file]
dav/wdcal.css [deleted file]

diff --git a/dav/FriendicaACLPlugin.inc.php b/dav/FriendicaACLPlugin.inc.php
deleted file mode 100644 (file)
index 6bb8fc9..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-
-class Sabre_DAVACL_Plugin_Friendica extends Sabre_DAVACL_Plugin {
-
-       /*
-        * A dirty hack to make iOS CalDAV work with subdirectorys.
-        * When using a Root URL like /dav/ (as it is necessary for friendica), iOS does not evaluate the current-user-principal property,
-        * but only principal-URL. Actually principal-URL is not allowed in /dav/, only for Principal collections, but this seems
-        * to be the only way to force iOS to look at the right location.
-        */
-
-       public function beforeGetProperties($uri, Sabre_DAV_INode $node, &$requestedProperties, &$returnedProperties) {
-
-               parent::beforeGetProperties($uri, $node, $requestedProperties, $returnedProperties);
-
-               if (false !== ($index = array_search('{DAV:}principal-URL', $requestedProperties))) {
-
-                       unset($requestedProperties[$index]);
-                       $returnedProperties[200]['{DAV:}principal-URL'] = new Sabre_DAV_Property_Href('principals/users/' . strtolower($_SERVER["PHP_AUTH_USER"]) . '/');
-
-               }
-               if (false !== ($index = array_search('{urn:ietf:params:xml:ns:caldav}calendar-home-set', $requestedProperties))) {
-
-                       unset($requestedProperties[$index]);
-                       $returnedProperties[200]['{urn:ietf:params:xml:ns:caldav}calendar-home-set'] = new Sabre_DAV_Property_Href('calendars/' . strtolower($_SERVER["PHP_AUTH_USER"]) . '/');
-
-               }
-
-       }
-
-}
\ No newline at end of file
diff --git a/dav/calendar.friendica.fnk.php b/dav/calendar.friendica.fnk.php
deleted file mode 100644 (file)
index 60dd9c6..0000000
+++ /dev/null
@@ -1,274 +0,0 @@
-<?php
-
-$a    = get_app();
-$uri  = parse_url($a->get_baseurl());
-$path = "/";
-if (isset($uri["path"]) && strlen($uri["path"]) > 1) {
-       $path = $uri["path"] . "/";
-}
-
-define("CALDAV_SQL_DB", "");
-define("CALDAV_SQL_PREFIX", "dav_");
-define("CALDAV_URL_PREFIX", $path . "dav/");
-define("DAV_APPNAME", "Friendica");
-
-define("CALDAV_NAMESPACE_PRIVATE", 1);
-define("CALDAV_FRIENDICA_MINE", "friendica-mine");
-define("CALDAV_FRIENDICA_CONTACTS", "friendica-contacts");
-
-$GLOBALS["CALDAV_PRIVATE_SYSTEM_CALENDARS"] = array(CALDAV_FRIENDICA_MINE, CALDAV_FRIENDICA_CONTACTS);
-$GLOBALS["CALDAV_PRIVATE_SYSTEM_BACKENDS"] = array("Sabre_CalDAV_Backend_Friendica");
-
-define("CARDDAV_NAMESPACE_PRIVATE", 1);
-define("CARDDAV_FRIENDICA_CONTACT", "friendica");
-$GLOBALS["CARDDAV_PRIVATE_SYSTEM_ADDRESSBOOKS"] = array(CARDDAV_FRIENDICA_CONTACT);
-$GLOBALS["CARDDAV_PRIVATE_SYSTEM_BACKENDS"] = array("Sabre_CardDAV_Backend_Friendica");
-
-$GLOBALS["CALDAV_ACL_PLUGIN_CLASS"] = "Sabre_DAVACL_Plugin_Friendica";
-
-define("CALDAV_MAX_YEAR", date("Y") + 5);
-
-/**
- * @return int
- */
-function getCurMicrotime()
-{
-       list($usec, $sec) = explode(" ", microtime());
-       return sprintf("%14.0f", $sec * 10000 + $usec * 10000);
-} // function getCurMicrotime
-
-/**
- *
- */
-function debug_time()
-{
-       $cur = getCurMicrotime();
-       if ($GLOBALS["debug_time_last"] > 0) {
-               echo "Zeit: " . ($cur - $GLOBALS["debug_time_last"]) . "<br>\n";
-       }
-       $GLOBALS["debug_time_last"] = $cur;
-}
-
-
-/**
- * @param string $username
- * @return int|null
- */
-function dav_compat_username2id($username = "")
-{
-       $x = q("SELECT `uid` FROM `user` WHERE `nickname`='%s' AND `account_removed` = 0 AND `account_expired` = 0", dbesc($username));
-       if (count($x) == 1) return $x[0]["uid"];
-       return null;
-}
-
-/**
- * @param int $id
- * @return string
- */
-function dav_compat_id2username($id = 0)
-{
-       $x = q("SELECT `nickname` FROM `user` WHERE `uid` = %i AND `account_removed` = 0 AND `account_expired` = 0", IntVal($id));
-       if (count($x) == 1) return $x[0]["nickname"];
-       return "";
-}
-
-/**
- * @return int
- */
-function dav_compat_get_curr_user_id()
-{
-       $a = get_app();
-       return IntVal($a->user["uid"]);
-}
-
-
-/**
- * @param string $principalUri
- * @return int|null
- */
-function dav_compat_principal2uid($principalUri = "")
-{
-       if (strlen($principalUri) == 0) return null;
-       if ($principalUri[0] == "/") $principalUri = substr($principalUri, 1);
-       if (strpos($principalUri, "principals/users/") !== 0) return null;
-       $username = substr($principalUri, strlen("principals/users/"));
-       return dav_compat_username2id($username);
-}
-
-/**
- * @param string $principalUri
- * @return array|null
- */
-function dav_compat_principal2namespace($principalUri = "")
-{
-       if (strlen($principalUri) == 0) return null;
-       if ($principalUri[0] == "/") $principalUri = substr($principalUri, 1);
-
-       if (strpos($principalUri, "principals/users/") !== 0) return null;
-       $username = substr($principalUri, strlen("principals/users/"));
-       return array("namespace" => CALDAV_NAMESPACE_PRIVATE, "namespace_id" => dav_compat_username2id($username));
-}
-
-
-/**
- * @return string
- */
-function dav_compat_currentUserPrincipal()
-{
-       $a = get_app();
-       return "principals/users/" . strtolower($a->user["nickname"]);
-}
-
-
-/**
- * @param string $name
- * @return null|string
- */
-function dav_compat_getRequestVar($name = "")
-{
-       if (isset($_REQUEST[$name])) return $_REQUEST[$name];
-       else return null;
-}
-
-/**
- * @param $text
- * @return null|string
- */
-function dav_compat_parse_text_serverside($text)
-{
-       return dav_compat_getRequestVar($text);
-}
-
-/**
- * @param string $uri
- */
-function dav_compat_redirect($uri = "")
-{
-       goaway($uri);
-}
-
-
-/**
- * @return null|int
- */
-function dav_compat_get_max_private_calendars()
-{
-       return null;
-}
-
-/**
- * @return string
- */
-function dav_compat_get_hostname() {
-       $a = get_app();
-       return $a->get_hostname();
-}
-
-/**
- * @param int $namespace
- * @param int $namespace_id
- * @param string $uri
- * @param array $calendar
- * @return Sabre_CalDAV_Backend_Common
- * @throws Exception
- */
-function wdcal_calendar_factory($namespace, $namespace_id, $uri, $calendar = null)
-{
-       switch ($namespace) {
-               case CALDAV_NAMESPACE_PRIVATE:
-                       if ($uri == CALDAV_FRIENDICA_MINE || $uri == CALDAV_FRIENDICA_CONTACTS) return Sabre_CalDAV_Backend_Friendica::getInstance();
-                       else return Sabre_CalDAV_Backend_Private::getInstance();
-       }
-       throw new Exception("Calendar Namespace not found");
-}
-
-/**
- * @param int $calendar_id
- * @return Sabre_CalDAV_Backend_Common
- * @throws Exception
- */
-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;
-}
-
-/**
- */
-function wdcal_create_std_calendars()
-{
-       $a = get_app();
-       if (!local_user()) return;
-
-       $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;
-
-       $stms = wdcal_create_std_calendars_get_statements($a->user["uid"]);
-       foreach ($stms as $stmt) q($stmt);
-}
-
-
-
-
-/**
- * @param int $user_id
- * @param bool $withcheck
- * @return array
- */
-function wdcal_create_std_addressbooks_get_statements($user_id, $withcheck = true)
-{
-       $stms = array();
-       $a = get_app();
-       $uris = array(
-               'private'                 => t("Private Addresses"),
-               CARDDAV_FRIENDICA_CONTACT     => t("Friendica Contacts"),
-       );
-       foreach ($uris as $uri => $name) {
-               $cals = q("SELECT * FROM %s%saddressbooks 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%saddressbooks (`namespace`, `namespace_id`, `displayname`, `ctag`, `uri`)
-                               VALUES (%d, %d, '%s', 1, '%s')",
-                               CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CARDDAV_NAMESPACE_PRIVATE, IntVal($user_id), dbesc($name), dbesc($uri));
-       }
-       return $stms;
-}
-
-/**
- */
-function wdcal_create_std_addressbooks()
-{
-       $a = get_app();
-       if (!local_user()) return;
-
-       $privates = q("SELECT COUNT(*) num FROM %s%addressbooks WHERE `namespace` = %d AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CARDDAV_NAMESPACE_PRIVATE, IntVal($a->user["uid"]));
-       if ($privates[0]["num"] > 0) return;
-
-       $stms = wdcal_create_std_addressbooks_get_statements($a->user["uid"]);
-       foreach ($stms as $stmt) q($stmt);
-}
diff --git a/dav/database-init.inc.php b/dav/database-init.inc.php
deleted file mode 100644 (file)
index 7c0d23a..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-<?php
-
-
-/**
- * @param int $from_version
- * @return array|string[]
- */
-function dav_get_update_statements($from_version)
-{
-       $stms = array();
-
-       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 = array_merge($stms, dav_get_create_statements(array("dav_calendarobjects")));
-
-               $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[] = "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`";
-
-       }
-
-       if (in_array($from_version, array(1, 2))) {
-               $stms[] = "DROP TABLE `dav_addressbooks_phone`";
-               $stms[] = "DROP TABLE `dav_addressbooks_community`";
-               $stms[] = "DROP TABLE `dav_cards`";
-
-               $stms[] = "CREATE TABLE IF NOT EXISTS `dav_addressbooks` (
-  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-  `namespace` mediumint(9) NOT NULL,
-  `namespace_id` int(11) unsigned NOT NULL,
-  `displayname` varchar(200) NOT NULL,
-  `description` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
-  `uri` varchar(50) NOT NULL,
-  `ctag` int(11) unsigned NOT NULL DEFAULT '1',
-  PRIMARY KEY (`id`)
-) ENGINE=InnoDB  DEFAULT CHARSET=utf8;";
-
-               $stms[] = "CREATE TABLE IF NOT EXISTS `dav_addressbookobjects` (
-  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-  `addressbook_id` int(11) unsigned NOT NULL,
-  `contact` int(11) DEFAULT NULL,
-  `carddata` mediumtext CHARACTER SET utf8 COLLATE utf8_unicode_ci,
-  `uri` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
-  `lastmodified` timestamp NULL DEFAULT NULL,
-  `manually_edited` tinyint(4) NOT NULL DEFAULT '0',
-  `manually_deleted` tinyint(4) NOT NULL DEFAULT '0',
-  `etag` varchar(15) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
-  `size` int(10) unsigned NOT NULL,
-  PRIMARY KEY (`id`),
-  UNIQUE KEY `namespace` (`addressbook_id`,`contact`),
-  KEY `contact` (`contact`)
-) ENGINE=InnoDB  DEFAULT CHARSET=utf8;";
-       }
-
-       return $stms;
-}
-
-/**
- * @param array $except
- * @return array
- */
-function dav_get_create_statements($except = array())
-{
-       $arr = array();
-
-       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,
-  `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  `method` varchar(10) NOT NULL,
-  `url` varchar(100) NOT NULL,
-  PRIMARY KEY (`id`),
-  KEY `mitglied` (`uid`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8";
-
-       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`),
-  KEY `calendar_id` (`calendar_id`)
-) ENGINE=InnoDB  DEFAULT CHARSET=utf8";
-
-       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,
-  `calendarorder` int(11) NOT NULL DEFAULT '1',
-  `calendarcolor` char(6) NOT NULL DEFAULT '5858FF',
-  `displayname` varchar(200) NOT NULL,
-  `timezone` text NOT NULL,
-  `description` varchar(500) NOT 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 (`id`),
-  UNIQUE KEY (`namespace` , `namespace_id` , `uri`),
-  KEY `uri` (`uri`)
-) ENGINE=InnoDB  DEFAULT CHARSET=utf8";
-
-       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_summary` varchar(1000) NOT NULL,
-  `data_location` varchar(1000) 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,
-  `calendardata` text NOT NULL,
-  `size` int(11) NOT NULL,
-  `etag` varchar(15) NOT NULL,
-  PRIMARY KEY (`id`),
-  KEY `data_uri` (`data_uri`),
-  KEY `ref_type` (`calendar_id`,`data_end`)
-) ENGINE=InnoDB  DEFAULT CHARSET=utf8";
-
-       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_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,
-  `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`)
-) ENGINE=InnoDB  DEFAULT CHARSET=utf8";
-
-       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,
-  `notified` tinyint(4) NOT NULL DEFAULT '0',
-  PRIMARY KEY (`id`),
-  KEY `notified` (`notified`,`alert_date`),
-  KEY `calendar_id` (`calendar_id`,`calendarobject_id`)
-) ENGINE=InnoDB  DEFAULT CHARSET=utf8";
-
-       if (!in_array("dav_addressbooks", $except)) $arr[] = "CREATE TABLE IF NOT EXISTS `dav_addressbooks` (
-  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-  `namespace` mediumint(9) NOT NULL,
-  `namespace_id` int(11) unsigned NOT NULL,
-  `displayname` varchar(200) NOT NULL,
-  `description` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
-  `uri` varchar(50) NOT NULL,
-  `ctag` int(11) unsigned NOT NULL DEFAULT '1',
-  PRIMARY KEY (`id`)
-) ENGINE=InnoDB  DEFAULT CHARSET=utf8;";
-
-       if (!in_array("dav_addressbookobjects", $except)) $arr[] = "CREATE TABLE IF NOT EXISTS `dav_addressbookobjects` (
-  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
-  `addressbook_id` int(11) unsigned NOT NULL,
-  `contact` int(11) DEFAULT NULL,
-  `carddata` mediumtext CHARACTER SET utf8 COLLATE utf8_unicode_ci,
-  `uri` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
-  `lastmodified` timestamp NULL DEFAULT NULL,
-  `manually_edited` tinyint(4) NOT NULL DEFAULT '0',
-  `manually_deleted` tinyint(4) NOT NULL DEFAULT '0',
-  `etag` varchar(15) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
-  `size` int(10) unsigned NOT NULL,
-  PRIMARY KEY (`id`),
-  UNIQUE KEY `namespace` (`addressbook_id`,`contact`),
-  KEY `contact` (`contact`)
-) ENGINE=InnoDB  DEFAULT CHARSET=utf8;";
-
-       return $arr;
-}
-
-/**
- * @return int
- */
-function dav_check_tables()
-{
-       $x = q("DESCRIBE %s%scalendars", CALDAV_SQL_DB, CALDAV_SQL_PREFIX);
-       if (!$x) return -1;
-       if (count($x) == 9) return 1; // Version 0.1
-       // @TODO Detect Version 0.2
-       if (count($x) == 12) return 0; // Correct
-       return -2; // Unknown version
-}
-
-
-/**
- * @return array
- */
-function dav_create_tables()
-{
-       $stms   = dav_get_create_statements();
-       $errors = array();
-
-       global $db;
-       foreach ($stms as $st) {
-               $db->q($st);
-               if ($db->error) $errors[] = $db->error;
-       }
-
-       return $errors;
-}
-
-/**
- * @return array
- */
-function dav_upgrade_tables()
-{
-       $ver = dav_check_tables();
-       if (!in_array($ver, array(1))) return array("Unknown error");
-
-       $stms   = dav_get_update_statements($ver);
-       $errors = array();
-
-       global $db;
-       foreach ($stms as $st) {
-               $db->q($st);
-               if ($db->error) $errors[] = $db->error;
-       }
-
-       return $errors;
-}
\ No newline at end of file
index 05916d01ff59dc6ccf1dc1e7728729910f107f85..40040dfe21521e2fee42b2c8e174a6592f984c11 100644 (file)
@@ -8,5 +8,5 @@
 
 $_v = explode(".", phpversion());
 if ($_v[0] > 5 || ($_v[0] == 5 && $_v[1] >= 3)) {
-       require(__DIR__ . "/main.php");
+       require(__DIR__ . "/friendica/main.php");
 }
\ 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
deleted file mode 100644 (file)
index d2810b4..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-<?php
-
-class Sabre_CalDAV_Backend_Friendica extends Sabre_CalDAV_Backend_Virtual
-{
-
-       /**
-        * @var null|Sabre_CalDAV_Backend_Friendica
-        */
-       private static $instance = null;
-
-       /**
-        * @static
-        * @return Sabre_CalDAV_Backend_Friendica
-        */
-       public static function getInstance()
-       {
-               if (self::$instance == null) {
-                       self::$instance = new Sabre_CalDAV_Backend_Friendica();
-               }
-               return self::$instance;
-       }
-
-       /**
-        * @return int
-        */
-       public function getNamespace()
-       {
-               return CALDAV_NAMESPACE_PRIVATE;
-       }
-
-       /**
-        * @static
-        * @return string
-        */
-       public static function getBackendTypeName() {
-               return t("Friendica-Native events");
-       }
-
-       /**
-        * @static
-        * @param int $calendarId
-        * @throws Sabre_DAV_Exception_NotFound
-        * @return void
-        */
-       protected static function createCache_internal($calendarId)
-       {
-               $calendar = Sabre_CalDAV_Backend_Common::loadCalendarById($calendarId);
-
-               switch ($calendar["uri"]) {
-                       case CALDAV_FRIENDICA_MINE:
-                               $sql_where = " AND cid = 0";
-                               break;
-                       case CALDAV_FRIENDICA_CONTACTS:
-                               $sql_where = " AND cid > 0";
-                               break;
-                       default:
-                               throw new Sabre_DAV_Exception_NotFound();
-               }
-
-               $r = q("SELECT * FROM `event` WHERE `uid` = %d " . $sql_where . " ORDER BY `start`", IntVal($calendar["namespace_id"]));
-
-               foreach ($r as $row) {
-                       $uid       = $calendar["uri"] . "-" . $row["id"];
-                       $vevent    = dav_create_empty_vevent($uid);
-                       $component = dav_get_eventComponent($vevent);
-
-                       if ($row["adjust"]) {
-                               $start  = datetime_convert('UTC', date_default_timezone_get(), $row["start"]);
-                               $finish = datetime_convert('UTC', date_default_timezone_get(), $row["finish"]);
-                       } else {
-                               $start  = $row["start"];
-                               $finish = $row["finish"];
-                       }
-
-                       $summary = ($row["summary"] != "" ? $row["summary"] : $row["desc"]);
-                       $desc    = ($row["summary"] != "" ? $row["desc"] : "");
-                       $component->add("SUMMARY", icalendar_sanitize_string($summary));
-                       $component->add("LOCATION", icalendar_sanitize_string($row["location"]));
-                       $component->add("DESCRIPTION", icalendar_sanitize_string($desc));
-
-                       $ts_start = wdcal_mySql2PhpTime($start);
-                       $ts_end   = wdcal_mySql2PhpTime($start);
-
-                       $allday = (strpos($start, "00:00:00") !== false && strpos($finish, "00:00:00") !== false);
-                       $type           = ($allday ? Sabre_VObject_Property_DateTime::DATE : Sabre_VObject_Property_DateTime::LOCALTZ);
-
-                       $datetime_start = new Sabre_VObject_Property_DateTime("DTSTART");
-                       $datetime_start->setDateTime(new DateTime(date("Y-m-d H:i:s", $ts_start)), $type);
-                       $datetime_end = new Sabre_VObject_Property_DateTime("DTEND");
-                       $datetime_end->setDateTime(new DateTime(date("Y-m-d H:i:s", $ts_end)), $type);
-
-                       $component->add($datetime_start);
-                       $component->add($datetime_end);
-
-                       $data = $vevent->serialize();
-
-                       q("INSERT INTO %s%scal_virtual_object_cache (`calendar_id`, `data_uri`, `data_summary`, `data_location`, `data_start`, `data_end`, `data_allday`, `data_type`,
-                               `calendardata`, `size`, `etag`) VALUES (%d, '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', %d, '%s')",
-                               CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calendarId, dbesc($uid), dbesc($summary), dbesc($row["location"]), dbesc($row["start"]), dbesc($row["finish"]),
-                                       ($allday ? 1 : 0), dbesc(($row["type"] == "birthday" ? "birthday" : "")), dbesc($data), strlen($data), md5($data));
-
-               }
-
-       }
-
-
-       /**
-        * @param array $row
-        * @param array $calendar
-        * @param string $base_path
-        * @return array
-        */
-       private function jqcal2wdcal($row, $calendar, $base_path)
-       {
-               if ($row["adjust"]) {
-                       $start  = datetime_convert('UTC', date_default_timezone_get(), $row["start"]);
-                       $finish = datetime_convert('UTC', date_default_timezone_get(), $row["finish"]);
-               } else {
-                       $start  = $row["start"];
-                       $finish = $row["finish"];
-               }
-
-               $allday = (strpos($start, "00:00:00") !== false && strpos($finish, "00:00:00") !== false);
-
-               $summary = (($row["summary"]) ? $row["summary"] : substr(preg_replace("/\[[^\]]*\]/", "", $row["desc"]), 0, 100));
-
-               return array(
-                       "jq_id"             => $row["id"],
-                       "ev_id"             => $row["id"],
-                       "summary"           => escape_tags($summary),
-                       "start"             => wdcal_mySql2PhpTime($start),
-                       "end"               => wdcal_mySql2PhpTime($finish),
-                       "is_allday"         => ($allday ? 1 : 0),
-                       "is_moredays"       => (substr($start, 0, 10) != substr($finish, 0, 10)),
-                       "is_recurring"      => ($row["type"] == "birthday"),
-                       "color"             => "7878ff",
-                       "is_editable"       => 0,
-                       "is_editable_quick" => 0,
-                       "location"          => $row["location"],
-                       "attendees"         => '',
-                       "has_notification"  => 0,
-                       "url_detail"        => $base_path . "/events/event/" . $row["id"],
-                       "url_edit"          => "",
-                       "special_type"      => ($row["type"] == "birthday" ? "birthday" : ""),
-               );
-       }
-
-
-       /**
-        * @param int $calendarId
-        * @param string $date_from
-        * @param string $date_to
-        * @param string $base_path
-        * @throws Sabre_DAV_Exception_NotFound
-        * @return array
-        */
-       public function listItemsByRange($calendarId, $date_from, $date_to, $base_path)
-       {
-               $calendar = Sabre_CalDAV_Backend_Common::loadCalendarById($calendarId);
-
-               if ($calendar["namespace"] != CALDAV_NAMESPACE_PRIVATE) throw new Sabre_DAV_Exception_NotFound();
-
-               switch ($calendar["uri"]) {
-                       case CALDAV_FRIENDICA_MINE:
-                               $sql_where = " AND cid = 0";
-                               break;
-                       case CALDAV_FRIENDICA_CONTACTS:
-                               $sql_where = " AND cid > 0";
-                               break;
-                       default:
-                               throw new Sabre_DAV_Exception_NotFound();
-               }
-
-               if ($date_from != "") {
-                       if (is_numeric($date_from)) $sql_where .= " AND `finish` >= '" . date("Y-m-d H:i:s", $date_from) . "'";
-                       else $sql_where .= " AND `finish` >= '" . dbesc($date_from) . "'";
-               }
-               if ($date_to != "") {
-                       if (is_numeric($date_to)) $sql_where .= " AND `start` <= '" . date("Y-m-d H:i:s", $date_to) . "'";
-                       else $sql_where .= " AND `start` <= '" . dbesc($date_to) . "'";
-               }
-               $ret = array();
-
-               $r = q("SELECT * FROM `event` WHERE `uid` = %d " . $sql_where . " ORDER BY `start`", IntVal($calendar["namespace_id"]));
-
-               $a = get_app();
-               foreach ($r as $row) {
-                       $r                = $this->jqcal2wdcal($row, $calendar, $a->get_baseurl());
-                       $r["calendar_id"] = $calendar["id"];
-                       $ret[]            = $r;
-               }
-
-               return $ret;
-       }
-
-
-       /**
-        * Returns a list of calendars for a principal.
-        *
-        * Every project is an array with the following keys:
-        *  * id, a unique id that will be used by other functions to modify the
-        *    calendar. This can be the same as the uri or a database key.
-        *  * uri, which the basename of the uri with which the calendar is
-        *    accessed.
-        *  * principaluri. The owner of the calendar. Almost always the same as
-        *    principalUri passed to this method.
-        *
-        * Furthermore it can contain webdav properties in clark notation. A very
-        * common one is '{DAV:}displayname'.
-        *
-        * @param string $principalUri
-        * @return array
-        */
-       public function getCalendarsForUser($principalUri)
-       {
-               $n = dav_compat_principal2namespace($principalUri);
-               if ($n["namespace"] != $this->getNamespace()) return array();
-
-               $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 (!in_array($cal["uri"], $GLOBALS["CALDAV_PRIVATE_SYSTEM_CALENDARS"])) continue;
-
-                       $dat = array(
-                               "id"                                                      => $cal["id"],
-                               "uri"                                                     => $cal["uri"],
-                               "principaluri"                                            => $principalUri,
-                               '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}getctag' => $cal['ctag'] ? $cal['ctag'] : '0',
-                               '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}supported-calendar-component-set' => new Sabre_CalDAV_Property_SupportedCalendarComponentSet(array("VEVENT")),
-                               "calendar_class"                                          => "Sabre_CalDAV_Calendar_Virtual",
-                       );
-                       foreach ($this->propertyMap as $key=> $field) $dat[$key] = $cal[$field];
-
-                       $ret[] = $dat;
-               }
-
-               return $ret;
-       }
-
-       /**
-        * @param int $calendar_id
-        * @param int $calendarobject_id
-        * @return string
-        */
-       function getItemDetailRedirect($calendar_id, $calendarobject_id)
-       {
-               $a    = get_app();
-               $item = q("SELECT `id` FROM `item` WHERE `event-id` = %d AND `uid` = %d AND deleted = 0", IntVal($calendarobject_id), $a->user["uid"]);
-               if (count($item) == 0) return "/events/";
-               return "/display/" . $a->user["nickname"] . "/" . IntVal($item[0]["id"]);
-
-       }
-}
diff --git a/dav/dav_carddav_backend_virtual_friendica.inc.php b/dav/dav_carddav_backend_virtual_friendica.inc.php
deleted file mode 100644 (file)
index 3d7e097..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-<?php
-
-class Sabre_CardDAV_Backend_Friendica extends Sabre_CardDAV_Backend_Virtual
-{
-
-       /**
-        * @var null|Sabre_CardDAV_Backend_Friendica
-        */
-       private static $instance = null;
-
-       /**
-        * @static
-        * @return Sabre_CardDAV_Backend_Friendica
-        */
-       public static function getInstance() {
-               if (self::$instance == null) {
-                       self::$instance = new Sabre_CardDAV_Backend_Friendica();
-               }
-               return self::$instance;
-       }
-
-
-       /**
-        * @return int
-        */
-       public function getNamespace()
-       {
-               return CARDDAV_NAMESPACE_PRIVATE;
-       }
-
-       /**
-        * @static
-        * @return string
-        */
-       public static function getBackendTypeName() {
-               return t("Friendica-Contacts");
-       }
-
-       /**
-        * Returns the list of addressbooks for a specific user.
-        *
-        * @param string $principalUri
-        * @return array
-        */
-       public function getAddressBooksForUser($principalUri)
-       {
-               $uid = dav_compat_principal2uid($principalUri);
-
-               $addressBooks = array();
-
-               $books = q("SELECT id, ctag FROM %s%saddressbooks WHERE `namespace` = %d AND `namespace_id` = %d AND `uri` = '%s'",
-                       CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CARDDAV_NAMESPACE_PRIVATE, IntVal($uid), dbesc(CARDDAV_FRIENDICA_CONTACT));
-               $ctag = $books[0]["ctag"];
-
-               $addressBooks[] = array(
-                       'id'                                                                => $books[0]["id"],
-                       'uri'                                                               => "friendica",
-                       'principaluri'                                                      => $principalUri,
-                       '{DAV:}displayname'                                                 => t("Friendica-Contacts"),
-                       '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}addressbook-description' => t("Your Friendica-Contacts"),
-                       '{http://calendarserver.org/ns/}getctag'                            => $ctag,
-                       '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}supported-address-data'  =>
-                       new Sabre_CardDAV_Property_SupportedAddressData(),
-               );
-
-               return $addressBooks;
-
-       }
-
-       /**
-        * @static
-        * @param array $contact
-        * @return array
-        */
-       private static function dav_contactarr2vcardsource($contact)
-       {
-               $name        = explode(" ", $contact["name"]);
-               $first_name  = $last_name = "";
-               $middle_name = array();
-               $num         = count($name);
-               for ($i = 0; $i < $num && $first_name == ""; $i++) if ($name[$i] != "") {
-                       $first_name = $name[$i];
-                       unset($name[$i]);
-               }
-               for ($i = $num - 1; $i >= 0 && $last_name == ""; $i--) if (isset($name[$i]) && $name[$i] != "") {
-                       $last_name = $name[$i];
-                       unset($name[$i]);
-               }
-               foreach ($name as $n) if ($n != "") $middle_name[] = $n;
-               $vcarddata              = new vcard_source_data($first_name, implode(" ", $middle_name), $last_name);
-               $vcarddata->homepages[] = new vcard_source_data_homepage("pref", $contact["url"]);
-               $vcarddata->last_update = ($contact["last-update"] > 0 ? $contact["last-update"] : $contact["created"]);
-
-               $photo = q("SELECT * FROM photo WHERE `contact-id` = %d ORDER BY scale DESC", $contact["id"]); //prefer size 80x80
-               if ($photo && count($photo) > 0) {
-                       $photodata             = new vcard_source_data_photo();
-                       $photodata->width      = $photo[0]["width"];
-                       $photodata->height     = $photo[0]["height"];
-                       $photodata->type       = "JPEG";
-                       $photodata->binarydata = $photo[0]["data"];
-                       $vcarddata->photo      = $photodata;
-               }
-
-               switch ($contact["network"]) {
-                       case "face":
-                               $vcarddata->socialnetworks[] = new vcard_source_data_socialnetwork("facebook", $contact["notify"], "http://www.facebook.com/" . $contact["notify"]);
-                               break;
-                       case "dfrn":
-                               $vcarddata->socialnetworks[] = new vcard_source_data_socialnetwork("dfrn", $contact["nick"], $contact["url"]);
-                               break;
-                       case "twitter":
-                               $vcarddata->socialnetworks[] = new vcard_source_data_socialnetwork("twitter", $contact["nick"], "http://twitter.com/" . $contact["nick"]); // @TODO Stimmt das?
-                               break;
-               }
-
-               $vcard = vcard_source_compile($vcarddata);
-               return array(
-                       "id"           => $contact["id"],
-                       "carddata"     => $vcard,
-                       "uri"          => $contact["id"] . ".vcf",
-                       "lastmodified" => wdcal_mySql2PhpTime($vcarddata->last_update),
-                       "etag"         => md5($vcard),
-                       "size"         => strlen($vcard),
-               );
-
-       }
-
-       /**
-        * @static
-        * @param int $addressbookId
-        * @throws Sabre_DAV_Exception_NotFound
-        */
-       static protected function createCache_internal($addressbookId) {
-               //$notin    = (count($exclude_ids) > 0 ? " AND id NOT IN (" . implode(", ", $exclude_ids) . ") " : "");
-               $addressbook = q("SELECT * FROM %s%saddressbooks WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($addressbookId));
-               if (count($addressbook) != 1 || $addressbook[0]["namespace"] != CARDDAV_NAMESPACE_PRIVATE) throw new Sabre_DAV_Exception_NotFound();
-               $contacts = q("SELECT * FROM `contact` WHERE `uid` = %d AND `blocked` = 0 AND `pending` = 0 AND `hidden` = 0 AND `archive` = 0 ORDER BY `name` ASC", $addressbook[0]["namespace_id"]);
-
-               $retdata = array();
-               foreach ($contacts as $contact) {
-                       $x            = static::dav_contactarr2vcardsource($contact);
-                       q("INSERT INTO %s%saddressbookobjects (`addressbook_id`, `contact`, `carddata`, `uri`, `lastmodified`, `etag`, `size`) VALUES (%d, %d, '%s', '%s', NOW(), '%s', %d)",
-                               CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $addressbookId, $contact["id"], dbesc($x["carddata"]), dbesc($x["uri"]), dbesc($x["etag"]), $x["size"]
-                       );
-               }
-       }
-
-
-       /**
-        * Updates a card.
-        *
-        * The addressbook id will be passed as the first argument. This is the
-        * same id as it is returned from the getAddressbooksForUser method.
-        *
-        * The cardUri is a base uri, and doesn't include the full path. The
-        * cardData argument is the vcard body, and is passed as a string.
-        *
-        * It is possible to return an ETag from this method. This ETag should
-        * match that of the updated resource, and must be enclosed with double
-        * quotes (that is: the string itself must contain the actual quotes).
-        *
-        * You should only return the ETag if you store the carddata as-is. If a
-        * subsequent GET request on the same card does not have the same body,
-        * byte-by-byte and you did return an ETag here, clients tend to get
-        * confused.
-        *
-        * If you don't return an ETag, you can just return null.
-        *
-        * @param string $addressBookId
-        * @param string $cardUri
-        * @param string $cardData
-        * @throws Sabre_DAV_Exception_Forbidden
-        * @return string|null
-        */
-       public function updateCard($addressBookId, $cardUri, $cardData)
-       {
-               $x = explode("-", $addressBookId);
-
-               $etag = md5($cardData);
-               q("UPDATE %s%scards SET carddata = '%s', lastmodified = %d, etag = '%s', size = %d, manually_edited = 1 WHERE uri = '%s' AND namespace = %d AND namespace_id =%d",
-                       CALDAV_SQL_DB, CALDAV_SQL_PREFIX, dbesc($cardData), time(), $etag, strlen($cardData), dbesc($cardUri), IntVal($x[10]), IntVal($x[1])
-               );
-               q('UPDATE %s%saddressbooks_community SET ctag = ctag + 1 WHERE uid = %d', CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($x[1]));
-
-               return '"' . $etag . '"';
-       }
-
-       /**
-        * Deletes a card
-        *
-        * @param string $addressBookId
-        * @param string $cardUri
-        * @throws Sabre_DAV_Exception_Forbidden
-        * @return bool
-        */
-       public function deleteCard($addressBookId, $cardUri)
-       {
-               $x = explode("-", $addressBookId);
-
-               q("UPDATE %s%scards SET manually_deleted = 1 WHERE namespace = %d AND namespace_id = %d AND uri = '%s'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($x[0]), IntVal($x[1]), dbesc($cardUri));
-               q('UPDATE %s%saddressbooks_community SET ctag = ctag + 1 WHERE uid = %d', CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($x[1]));
-
-               return true;
-       }
-}
diff --git a/dav/dav_friendica_auth.inc.php b/dav/dav_friendica_auth.inc.php
deleted file mode 100644 (file)
index acc33fa..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-<?php
-
-class Sabre_DAV_Auth_Backend_Std extends Sabre_DAV_Auth_Backend_AbstractBasic {
-
-    public function __construct() {
-    }
-
-
-       /**
-        * @var Sabre_DAV_Auth_Backend_Std|null
-        */
-       private static $intstance = null;
-
-       /**
-        * @static
-        * @return Sabre_DAV_Auth_Backend_Std
-        */
-       public static function &getInstance() {
-               if (is_null(self::$intstance)) {
-                       self::$intstance = new Sabre_DAV_Auth_Backend_Std();
-               }
-               return self::$intstance;
-       }
-
-
-       /**
-        * @return array
-        */
-       public function getUsers() {
-        return array($this->currentUser);
-    }
-
-       /**
-        * @return null|string
-        */
-       public function getCurrentUser() {
-        return $this->currentUser;
-    }
-
-       /**
-        * Authenticates the user based on the current request.
-        *
-        * If authentication is successful, true must be returned.
-        * If authentication fails, an exception must be thrown.
-        *
-        * @param Sabre_DAV_Server $server
-        * @param string $realm
-        * @throws Sabre_DAV_Exception_NotAuthenticated
-        * @return bool
-        */
-       public function authenticate(Sabre_DAV_Server $server, $realm) {
-
-               $a = get_app();
-               if (isset($a->user["uid"])) {
-                       $this->currentUser = strtolower($a->user["nickname"]);
-                       return true;
-               }
-
-               $auth = new Sabre_HTTP_BasicAuth();
-               $auth->setHTTPRequest($server->httpRequest);
-               $auth->setHTTPResponse($server->httpResponse);
-               $auth->setRealm($realm);
-               $userpass = $auth->getUserPass();
-               if (!$userpass) {
-                       $auth->requireLogin();
-                       throw new Sabre_DAV_Exception_NotAuthenticated('No basic authentication headers were found');
-               }
-
-               // Authenticates the user
-               if (!$this->validateUserPass($userpass[0],$userpass[1])) {
-                       $auth->requireLogin();
-                       throw new Sabre_DAV_Exception_NotAuthenticated('Username or password does not match');
-               }
-               $this->currentUser = strtolower($userpass[0]);
-               return true;
-       }
-
-
-       /**
-        * @param string $username
-        * @param string $password
-        * @return bool
-        */
-       protected function validateUserPass($username, $password) {
-               $encrypted = hash('whirlpool',trim($password));
-               $r = q("SELECT COUNT(*) anz FROM `user` WHERE `nickname` = '%s' AND `password` = '%s' AND `blocked` = 0 AND `account_expired` = 0 AND `verified` = 1 LIMIT 1",
-                       dbesc(trim($username)),
-                       dbesc($encrypted)
-               );
-               return ($r[0]["anz"] == 1);
-    }
-    
-}
diff --git a/dav/dav_friendica_principal.inc.php b/dav/dav_friendica_principal.inc.php
deleted file mode 100644 (file)
index 780bcd2..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-<?php
-
-
-class Sabre_DAVACL_PrincipalBackend_Std implements Sabre_DAVACL_IPrincipalBackend
-{
-
-       /**
-        * Principals prefix
-        *
-        * @var string
-        */
-       public $prefix = 'principals/users';
-
-       /**
-        * @var Sabre_DAV_Auth_Backend_AbstractBasic $authBackend;
-        */
-       protected $authBackend;
-
-       public function __construct(&$authBackend)
-       {
-
-               $this->authBackend = &$authBackend;
-
-       }
-
-
-       /**
-        * @var Sabre_DAVACL_IPrincipalBackend|null
-        */
-       private static $intstance = null;
-
-       /**
-        * @static
-        * @return Sabre_DAVACL_IPrincipalBackend
-        */
-       public static function &getInstance() {
-               if (is_null(self::$intstance)) {
-                       $authBackend              = Sabre_DAV_Auth_Backend_Std::getInstance();
-                       self::$intstance = new Sabre_DAVACL_PrincipalBackend_Std($authBackend);
-               }
-               return self::$intstance;
-       }
-
-       /**
-        * Returns a list of principals based on a prefix.
-        *
-        * This prefix will often contain something like 'principals'. You are only
-        * expected to return principals that are in this base path.
-        *
-        * You are expected to return at least a 'uri' for every user, you can
-        * return any additional properties if you wish so. Common properties are:
-        *   {DAV:}displayname
-        *   {http://sabredav.org/ns}email-address - This is a custom SabreDAV
-        *     field that's actualy injected in a number of other properties. If
-        *     you have an email address, use this property.
-        *
-        * @param string $prefixPath
-        * @return array
-        */
-       public function getPrincipalsByPrefix($prefixPath)
-       {
-
-               // This backend only support principals in one collection
-               if ($prefixPath !== $this->prefix) return array();
-
-               $users = array();
-
-               $r = q("SELECT `nickname` FROM `user` WHERE `nickname` = '%s'", escape_tags($this->authBackend->getCurrentUser()) );
-               foreach ($r as $t) {
-                       $users[] = array(
-                               'uri'               => $this->prefix . '/' . strtolower($t['nickname']),
-                               '{DAV:}displayname' => $t['nickname'],
-                       );
-               }
-
-               return $users;
-
-       }
-
-       /**
-        * Returns a specific principal, specified by it's path.
-        * The returned structure should be the exact same as from
-        * getPrincipalsByPrefix.
-        *
-        * @param string $path
-        * @return array
-        */
-       public function getPrincipalByPath($path)
-       {
-
-               list($prefixPath, $userName) = Sabre_DAV_URLUtil::splitPath($path);
-
-               // This backend only support principals in one collection
-               if ($prefixPath !== $this->prefix) return null;
-
-               $r = q("SELECT `nickname` FROM `user` WHERE `nickname` = '%s'", escape_tags($userName) );
-               if (count($r) == 0) return array();
-
-               return array(
-                       'uri'               => $this->prefix . '/' . strtolower($r[0]['nickname']),
-                       '{DAV:}displayname' => $r[0]['nickname'],
-               );
-
-       }
-
-
-       function getGroupMemberSet($principal)
-       {
-               return array();
-       }
-
-       function getGroupMembership($principal)
-       {
-               return array();
-       }
-
-
-       /**
-        * Updates the list of group members for a group principal.
-        *
-        * The principals should be passed as a list of uri's.
-        *
-        * @param string $principal
-        * @param array $members
-        * @throws Sabre_DAV_Exception
-        * @return void
-        */
-       public function setGroupMemberSet($principal, array $members)
-       {
-               throw new Sabre_DAV_Exception('Operation not supported');
-       }
-
-       /**
-        * Updates one ore more webdav properties on a principal.
-        *
-        * The list of mutations is supplied as an array. Each key in the array is
-        * a propertyname, such as {DAV:}displayname.
-        *
-        * Each value is the actual value to be updated. If a value is null, it
-        * must be deleted.
-        *
-        * This method should be atomic. It must either completely succeed, or
-        * completely fail. Success and failure can simply be returned as 'true' or
-        * 'false'.
-        *
-        * It is also possible to return detailed failure information. In that case
-        * an array such as this should be returned:
-        *
-        * array(
-        *   200 => array(
-        *      '{DAV:}prop1' => null,
-        *   ),
-        *   201 => array(
-        *      '{DAV:}prop2' => null,
-        *   ),
-        *   403 => array(
-        *      '{DAV:}prop3' => null,
-        *   ),
-        *   424 => array(
-        *      '{DAV:}prop4' => null,
-        *   ),
-        * );
-        *
-        * In this previous example prop1 was successfully updated or deleted, and
-        * prop2 was succesfully created.
-        *
-        * prop3 failed to update due to '403 Forbidden' and because of this prop4
-        * also could not be updated with '424 Failed dependency'.
-        *
-        * This last example was actually incorrect. While 200 and 201 could appear
-        * in 1 response, if there's any error (403) the other properties should
-        * always fail with 423 (failed dependency).
-        *
-        * But anyway, if you don't want to scratch your head over this, just
-        * return true or false.
-        *
-        * @param string $path
-        * @param array $mutations
-        * @return array|bool
-        */
-       function updatePrincipal($path, $mutations)
-       {
-               // TODO: Implement updatePrincipal() method.
-       }
-
-       /**
-        * This method is used to search for principals matching a set of
-        * properties.
-        *
-        * This search is specifically used by RFC3744's principal-property-search
-        * REPORT. You should at least allow searching on
-        * http://sabredav.org/ns}email-address.
-        *
-        * The actual search should be a unicode-non-case-sensitive search. The
-        * keys in searchProperties are the WebDAV property names, while the values
-        * are the property values to search on.
-        *
-        * If multiple properties are being searched on, the search should be
-        * AND'ed.
-        *
-        * This method should simply return an array with full principal uri's.
-        *
-        * If somebody attempted to search on a property the backend does not
-        * support, you should simply return 0 results.
-        *
-        * You can also just return 0 results if you choose to not support
-        * searching at all, but keep in mind that this may stop certain features
-        * from working.
-        *
-        * @param string $prefixPath
-        * @param array $searchProperties
-        * @return array
-        */
-       function searchPrincipals($prefixPath, array $searchProperties)
-       {
-               // TODO: Implement searchPrincipals() method.
-       }
-}
diff --git a/dav/friendica/FriendicaACLPlugin.inc.php b/dav/friendica/FriendicaACLPlugin.inc.php
new file mode 100644 (file)
index 0000000..6bb8fc9
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+
+class Sabre_DAVACL_Plugin_Friendica extends Sabre_DAVACL_Plugin {
+
+       /*
+        * A dirty hack to make iOS CalDAV work with subdirectorys.
+        * When using a Root URL like /dav/ (as it is necessary for friendica), iOS does not evaluate the current-user-principal property,
+        * but only principal-URL. Actually principal-URL is not allowed in /dav/, only for Principal collections, but this seems
+        * to be the only way to force iOS to look at the right location.
+        */
+
+       public function beforeGetProperties($uri, Sabre_DAV_INode $node, &$requestedProperties, &$returnedProperties) {
+
+               parent::beforeGetProperties($uri, $node, $requestedProperties, $returnedProperties);
+
+               if (false !== ($index = array_search('{DAV:}principal-URL', $requestedProperties))) {
+
+                       unset($requestedProperties[$index]);
+                       $returnedProperties[200]['{DAV:}principal-URL'] = new Sabre_DAV_Property_Href('principals/users/' . strtolower($_SERVER["PHP_AUTH_USER"]) . '/');
+
+               }
+               if (false !== ($index = array_search('{urn:ietf:params:xml:ns:caldav}calendar-home-set', $requestedProperties))) {
+
+                       unset($requestedProperties[$index]);
+                       $returnedProperties[200]['{urn:ietf:params:xml:ns:caldav}calendar-home-set'] = new Sabre_DAV_Property_Href('calendars/' . strtolower($_SERVER["PHP_AUTH_USER"]) . '/');
+
+               }
+
+       }
+
+}
\ No newline at end of file
diff --git a/dav/friendica/calendar.friendica.fnk.php b/dav/friendica/calendar.friendica.fnk.php
new file mode 100644 (file)
index 0000000..60dd9c6
--- /dev/null
@@ -0,0 +1,274 @@
+<?php
+
+$a    = get_app();
+$uri  = parse_url($a->get_baseurl());
+$path = "/";
+if (isset($uri["path"]) && strlen($uri["path"]) > 1) {
+       $path = $uri["path"] . "/";
+}
+
+define("CALDAV_SQL_DB", "");
+define("CALDAV_SQL_PREFIX", "dav_");
+define("CALDAV_URL_PREFIX", $path . "dav/");
+define("DAV_APPNAME", "Friendica");
+
+define("CALDAV_NAMESPACE_PRIVATE", 1);
+define("CALDAV_FRIENDICA_MINE", "friendica-mine");
+define("CALDAV_FRIENDICA_CONTACTS", "friendica-contacts");
+
+$GLOBALS["CALDAV_PRIVATE_SYSTEM_CALENDARS"] = array(CALDAV_FRIENDICA_MINE, CALDAV_FRIENDICA_CONTACTS);
+$GLOBALS["CALDAV_PRIVATE_SYSTEM_BACKENDS"] = array("Sabre_CalDAV_Backend_Friendica");
+
+define("CARDDAV_NAMESPACE_PRIVATE", 1);
+define("CARDDAV_FRIENDICA_CONTACT", "friendica");
+$GLOBALS["CARDDAV_PRIVATE_SYSTEM_ADDRESSBOOKS"] = array(CARDDAV_FRIENDICA_CONTACT);
+$GLOBALS["CARDDAV_PRIVATE_SYSTEM_BACKENDS"] = array("Sabre_CardDAV_Backend_Friendica");
+
+$GLOBALS["CALDAV_ACL_PLUGIN_CLASS"] = "Sabre_DAVACL_Plugin_Friendica";
+
+define("CALDAV_MAX_YEAR", date("Y") + 5);
+
+/**
+ * @return int
+ */
+function getCurMicrotime()
+{
+       list($usec, $sec) = explode(" ", microtime());
+       return sprintf("%14.0f", $sec * 10000 + $usec * 10000);
+} // function getCurMicrotime
+
+/**
+ *
+ */
+function debug_time()
+{
+       $cur = getCurMicrotime();
+       if ($GLOBALS["debug_time_last"] > 0) {
+               echo "Zeit: " . ($cur - $GLOBALS["debug_time_last"]) . "<br>\n";
+       }
+       $GLOBALS["debug_time_last"] = $cur;
+}
+
+
+/**
+ * @param string $username
+ * @return int|null
+ */
+function dav_compat_username2id($username = "")
+{
+       $x = q("SELECT `uid` FROM `user` WHERE `nickname`='%s' AND `account_removed` = 0 AND `account_expired` = 0", dbesc($username));
+       if (count($x) == 1) return $x[0]["uid"];
+       return null;
+}
+
+/**
+ * @param int $id
+ * @return string
+ */
+function dav_compat_id2username($id = 0)
+{
+       $x = q("SELECT `nickname` FROM `user` WHERE `uid` = %i AND `account_removed` = 0 AND `account_expired` = 0", IntVal($id));
+       if (count($x) == 1) return $x[0]["nickname"];
+       return "";
+}
+
+/**
+ * @return int
+ */
+function dav_compat_get_curr_user_id()
+{
+       $a = get_app();
+       return IntVal($a->user["uid"]);
+}
+
+
+/**
+ * @param string $principalUri
+ * @return int|null
+ */
+function dav_compat_principal2uid($principalUri = "")
+{
+       if (strlen($principalUri) == 0) return null;
+       if ($principalUri[0] == "/") $principalUri = substr($principalUri, 1);
+       if (strpos($principalUri, "principals/users/") !== 0) return null;
+       $username = substr($principalUri, strlen("principals/users/"));
+       return dav_compat_username2id($username);
+}
+
+/**
+ * @param string $principalUri
+ * @return array|null
+ */
+function dav_compat_principal2namespace($principalUri = "")
+{
+       if (strlen($principalUri) == 0) return null;
+       if ($principalUri[0] == "/") $principalUri = substr($principalUri, 1);
+
+       if (strpos($principalUri, "principals/users/") !== 0) return null;
+       $username = substr($principalUri, strlen("principals/users/"));
+       return array("namespace" => CALDAV_NAMESPACE_PRIVATE, "namespace_id" => dav_compat_username2id($username));
+}
+
+
+/**
+ * @return string
+ */
+function dav_compat_currentUserPrincipal()
+{
+       $a = get_app();
+       return "principals/users/" . strtolower($a->user["nickname"]);
+}
+
+
+/**
+ * @param string $name
+ * @return null|string
+ */
+function dav_compat_getRequestVar($name = "")
+{
+       if (isset($_REQUEST[$name])) return $_REQUEST[$name];
+       else return null;
+}
+
+/**
+ * @param $text
+ * @return null|string
+ */
+function dav_compat_parse_text_serverside($text)
+{
+       return dav_compat_getRequestVar($text);
+}
+
+/**
+ * @param string $uri
+ */
+function dav_compat_redirect($uri = "")
+{
+       goaway($uri);
+}
+
+
+/**
+ * @return null|int
+ */
+function dav_compat_get_max_private_calendars()
+{
+       return null;
+}
+
+/**
+ * @return string
+ */
+function dav_compat_get_hostname() {
+       $a = get_app();
+       return $a->get_hostname();
+}
+
+/**
+ * @param int $namespace
+ * @param int $namespace_id
+ * @param string $uri
+ * @param array $calendar
+ * @return Sabre_CalDAV_Backend_Common
+ * @throws Exception
+ */
+function wdcal_calendar_factory($namespace, $namespace_id, $uri, $calendar = null)
+{
+       switch ($namespace) {
+               case CALDAV_NAMESPACE_PRIVATE:
+                       if ($uri == CALDAV_FRIENDICA_MINE || $uri == CALDAV_FRIENDICA_CONTACTS) return Sabre_CalDAV_Backend_Friendica::getInstance();
+                       else return Sabre_CalDAV_Backend_Private::getInstance();
+       }
+       throw new Exception("Calendar Namespace not found");
+}
+
+/**
+ * @param int $calendar_id
+ * @return Sabre_CalDAV_Backend_Common
+ * @throws Exception
+ */
+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;
+}
+
+/**
+ */
+function wdcal_create_std_calendars()
+{
+       $a = get_app();
+       if (!local_user()) return;
+
+       $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;
+
+       $stms = wdcal_create_std_calendars_get_statements($a->user["uid"]);
+       foreach ($stms as $stmt) q($stmt);
+}
+
+
+
+
+/**
+ * @param int $user_id
+ * @param bool $withcheck
+ * @return array
+ */
+function wdcal_create_std_addressbooks_get_statements($user_id, $withcheck = true)
+{
+       $stms = array();
+       $a = get_app();
+       $uris = array(
+               'private'                 => t("Private Addresses"),
+               CARDDAV_FRIENDICA_CONTACT     => t("Friendica Contacts"),
+       );
+       foreach ($uris as $uri => $name) {
+               $cals = q("SELECT * FROM %s%saddressbooks 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%saddressbooks (`namespace`, `namespace_id`, `displayname`, `ctag`, `uri`)
+                               VALUES (%d, %d, '%s', 1, '%s')",
+                               CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CARDDAV_NAMESPACE_PRIVATE, IntVal($user_id), dbesc($name), dbesc($uri));
+       }
+       return $stms;
+}
+
+/**
+ */
+function wdcal_create_std_addressbooks()
+{
+       $a = get_app();
+       if (!local_user()) return;
+
+       $privates = q("SELECT COUNT(*) num FROM %s%addressbooks WHERE `namespace` = %d AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CARDDAV_NAMESPACE_PRIVATE, IntVal($a->user["uid"]));
+       if ($privates[0]["num"] > 0) return;
+
+       $stms = wdcal_create_std_addressbooks_get_statements($a->user["uid"]);
+       foreach ($stms as $stmt) q($stmt);
+}
diff --git a/dav/friendica/database-init.inc.php b/dav/friendica/database-init.inc.php
new file mode 100644 (file)
index 0000000..7c0d23a
--- /dev/null
@@ -0,0 +1,270 @@
+<?php
+
+
+/**
+ * @param int $from_version
+ * @return array|string[]
+ */
+function dav_get_update_statements($from_version)
+{
+       $stms = array();
+
+       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 = array_merge($stms, dav_get_create_statements(array("dav_calendarobjects")));
+
+               $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[] = "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`";
+
+       }
+
+       if (in_array($from_version, array(1, 2))) {
+               $stms[] = "DROP TABLE `dav_addressbooks_phone`";
+               $stms[] = "DROP TABLE `dav_addressbooks_community`";
+               $stms[] = "DROP TABLE `dav_cards`";
+
+               $stms[] = "CREATE TABLE IF NOT EXISTS `dav_addressbooks` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `namespace` mediumint(9) NOT NULL,
+  `namespace_id` int(11) unsigned NOT NULL,
+  `displayname` varchar(200) NOT NULL,
+  `description` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
+  `uri` varchar(50) NOT NULL,
+  `ctag` int(11) unsigned NOT NULL DEFAULT '1',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB  DEFAULT CHARSET=utf8;";
+
+               $stms[] = "CREATE TABLE IF NOT EXISTS `dav_addressbookobjects` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `addressbook_id` int(11) unsigned NOT NULL,
+  `contact` int(11) DEFAULT NULL,
+  `carddata` mediumtext CHARACTER SET utf8 COLLATE utf8_unicode_ci,
+  `uri` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
+  `lastmodified` timestamp NULL DEFAULT NULL,
+  `manually_edited` tinyint(4) NOT NULL DEFAULT '0',
+  `manually_deleted` tinyint(4) NOT NULL DEFAULT '0',
+  `etag` varchar(15) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
+  `size` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `namespace` (`addressbook_id`,`contact`),
+  KEY `contact` (`contact`)
+) ENGINE=InnoDB  DEFAULT CHARSET=utf8;";
+       }
+
+       return $stms;
+}
+
+/**
+ * @param array $except
+ * @return array
+ */
+function dav_get_create_statements($except = array())
+{
+       $arr = array();
+
+       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,
+  `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `method` varchar(10) NOT NULL,
+  `url` varchar(100) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `mitglied` (`uid`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8";
+
+       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`),
+  KEY `calendar_id` (`calendar_id`)
+) ENGINE=InnoDB  DEFAULT CHARSET=utf8";
+
+       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,
+  `calendarorder` int(11) NOT NULL DEFAULT '1',
+  `calendarcolor` char(6) NOT NULL DEFAULT '5858FF',
+  `displayname` varchar(200) NOT NULL,
+  `timezone` text NOT NULL,
+  `description` varchar(500) NOT 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 (`id`),
+  UNIQUE KEY (`namespace` , `namespace_id` , `uri`),
+  KEY `uri` (`uri`)
+) ENGINE=InnoDB  DEFAULT CHARSET=utf8";
+
+       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_summary` varchar(1000) NOT NULL,
+  `data_location` varchar(1000) 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,
+  `calendardata` text NOT NULL,
+  `size` int(11) NOT NULL,
+  `etag` varchar(15) NOT NULL,
+  PRIMARY KEY (`id`),
+  KEY `data_uri` (`data_uri`),
+  KEY `ref_type` (`calendar_id`,`data_end`)
+) ENGINE=InnoDB  DEFAULT CHARSET=utf8";
+
+       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_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,
+  `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`)
+) ENGINE=InnoDB  DEFAULT CHARSET=utf8";
+
+       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,
+  `notified` tinyint(4) NOT NULL DEFAULT '0',
+  PRIMARY KEY (`id`),
+  KEY `notified` (`notified`,`alert_date`),
+  KEY `calendar_id` (`calendar_id`,`calendarobject_id`)
+) ENGINE=InnoDB  DEFAULT CHARSET=utf8";
+
+       if (!in_array("dav_addressbooks", $except)) $arr[] = "CREATE TABLE IF NOT EXISTS `dav_addressbooks` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `namespace` mediumint(9) NOT NULL,
+  `namespace_id` int(11) unsigned NOT NULL,
+  `displayname` varchar(200) NOT NULL,
+  `description` varchar(500) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
+  `uri` varchar(50) NOT NULL,
+  `ctag` int(11) unsigned NOT NULL DEFAULT '1',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB  DEFAULT CHARSET=utf8;";
+
+       if (!in_array("dav_addressbookobjects", $except)) $arr[] = "CREATE TABLE IF NOT EXISTS `dav_addressbookobjects` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `addressbook_id` int(11) unsigned NOT NULL,
+  `contact` int(11) DEFAULT NULL,
+  `carddata` mediumtext CHARACTER SET utf8 COLLATE utf8_unicode_ci,
+  `uri` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL,
+  `lastmodified` timestamp NULL DEFAULT NULL,
+  `manually_edited` tinyint(4) NOT NULL DEFAULT '0',
+  `manually_deleted` tinyint(4) NOT NULL DEFAULT '0',
+  `etag` varchar(15) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
+  `size` int(10) unsigned NOT NULL,
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `namespace` (`addressbook_id`,`contact`),
+  KEY `contact` (`contact`)
+) ENGINE=InnoDB  DEFAULT CHARSET=utf8;";
+
+       return $arr;
+}
+
+/**
+ * @return int
+ */
+function dav_check_tables()
+{
+       $x = q("DESCRIBE %s%scalendars", CALDAV_SQL_DB, CALDAV_SQL_PREFIX);
+       if (!$x) return -1;
+       if (count($x) == 9) return 1; // Version 0.1
+       // @TODO Detect Version 0.2
+       if (count($x) == 12) return 0; // Correct
+       return -2; // Unknown version
+}
+
+
+/**
+ * @return array
+ */
+function dav_create_tables()
+{
+       $stms   = dav_get_create_statements();
+       $errors = array();
+
+       global $db;
+       foreach ($stms as $st) {
+               $db->q($st);
+               if ($db->error) $errors[] = $db->error;
+       }
+
+       return $errors;
+}
+
+/**
+ * @return array
+ */
+function dav_upgrade_tables()
+{
+       $ver = dav_check_tables();
+       if (!in_array($ver, array(1))) return array("Unknown error");
+
+       $stms   = dav_get_update_statements($ver);
+       $errors = array();
+
+       global $db;
+       foreach ($stms as $st) {
+               $db->q($st);
+               if ($db->error) $errors[] = $db->error;
+       }
+
+       return $errors;
+}
\ No newline at end of file
diff --git a/dav/friendica/dav_caldav_backend_virtual_friendica.inc.php b/dav/friendica/dav_caldav_backend_virtual_friendica.inc.php
new file mode 100644 (file)
index 0000000..d2810b4
--- /dev/null
@@ -0,0 +1,253 @@
+<?php
+
+class Sabre_CalDAV_Backend_Friendica extends Sabre_CalDAV_Backend_Virtual
+{
+
+       /**
+        * @var null|Sabre_CalDAV_Backend_Friendica
+        */
+       private static $instance = null;
+
+       /**
+        * @static
+        * @return Sabre_CalDAV_Backend_Friendica
+        */
+       public static function getInstance()
+       {
+               if (self::$instance == null) {
+                       self::$instance = new Sabre_CalDAV_Backend_Friendica();
+               }
+               return self::$instance;
+       }
+
+       /**
+        * @return int
+        */
+       public function getNamespace()
+       {
+               return CALDAV_NAMESPACE_PRIVATE;
+       }
+
+       /**
+        * @static
+        * @return string
+        */
+       public static function getBackendTypeName() {
+               return t("Friendica-Native events");
+       }
+
+       /**
+        * @static
+        * @param int $calendarId
+        * @throws Sabre_DAV_Exception_NotFound
+        * @return void
+        */
+       protected static function createCache_internal($calendarId)
+       {
+               $calendar = Sabre_CalDAV_Backend_Common::loadCalendarById($calendarId);
+
+               switch ($calendar["uri"]) {
+                       case CALDAV_FRIENDICA_MINE:
+                               $sql_where = " AND cid = 0";
+                               break;
+                       case CALDAV_FRIENDICA_CONTACTS:
+                               $sql_where = " AND cid > 0";
+                               break;
+                       default:
+                               throw new Sabre_DAV_Exception_NotFound();
+               }
+
+               $r = q("SELECT * FROM `event` WHERE `uid` = %d " . $sql_where . " ORDER BY `start`", IntVal($calendar["namespace_id"]));
+
+               foreach ($r as $row) {
+                       $uid       = $calendar["uri"] . "-" . $row["id"];
+                       $vevent    = dav_create_empty_vevent($uid);
+                       $component = dav_get_eventComponent($vevent);
+
+                       if ($row["adjust"]) {
+                               $start  = datetime_convert('UTC', date_default_timezone_get(), $row["start"]);
+                               $finish = datetime_convert('UTC', date_default_timezone_get(), $row["finish"]);
+                       } else {
+                               $start  = $row["start"];
+                               $finish = $row["finish"];
+                       }
+
+                       $summary = ($row["summary"] != "" ? $row["summary"] : $row["desc"]);
+                       $desc    = ($row["summary"] != "" ? $row["desc"] : "");
+                       $component->add("SUMMARY", icalendar_sanitize_string($summary));
+                       $component->add("LOCATION", icalendar_sanitize_string($row["location"]));
+                       $component->add("DESCRIPTION", icalendar_sanitize_string($desc));
+
+                       $ts_start = wdcal_mySql2PhpTime($start);
+                       $ts_end   = wdcal_mySql2PhpTime($start);
+
+                       $allday = (strpos($start, "00:00:00") !== false && strpos($finish, "00:00:00") !== false);
+                       $type           = ($allday ? Sabre_VObject_Property_DateTime::DATE : Sabre_VObject_Property_DateTime::LOCALTZ);
+
+                       $datetime_start = new Sabre_VObject_Property_DateTime("DTSTART");
+                       $datetime_start->setDateTime(new DateTime(date("Y-m-d H:i:s", $ts_start)), $type);
+                       $datetime_end = new Sabre_VObject_Property_DateTime("DTEND");
+                       $datetime_end->setDateTime(new DateTime(date("Y-m-d H:i:s", $ts_end)), $type);
+
+                       $component->add($datetime_start);
+                       $component->add($datetime_end);
+
+                       $data = $vevent->serialize();
+
+                       q("INSERT INTO %s%scal_virtual_object_cache (`calendar_id`, `data_uri`, `data_summary`, `data_location`, `data_start`, `data_end`, `data_allday`, `data_type`,
+                               `calendardata`, `size`, `etag`) VALUES (%d, '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', %d, '%s')",
+                               CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calendarId, dbesc($uid), dbesc($summary), dbesc($row["location"]), dbesc($row["start"]), dbesc($row["finish"]),
+                                       ($allday ? 1 : 0), dbesc(($row["type"] == "birthday" ? "birthday" : "")), dbesc($data), strlen($data), md5($data));
+
+               }
+
+       }
+
+
+       /**
+        * @param array $row
+        * @param array $calendar
+        * @param string $base_path
+        * @return array
+        */
+       private function jqcal2wdcal($row, $calendar, $base_path)
+       {
+               if ($row["adjust"]) {
+                       $start  = datetime_convert('UTC', date_default_timezone_get(), $row["start"]);
+                       $finish = datetime_convert('UTC', date_default_timezone_get(), $row["finish"]);
+               } else {
+                       $start  = $row["start"];
+                       $finish = $row["finish"];
+               }
+
+               $allday = (strpos($start, "00:00:00") !== false && strpos($finish, "00:00:00") !== false);
+
+               $summary = (($row["summary"]) ? $row["summary"] : substr(preg_replace("/\[[^\]]*\]/", "", $row["desc"]), 0, 100));
+
+               return array(
+                       "jq_id"             => $row["id"],
+                       "ev_id"             => $row["id"],
+                       "summary"           => escape_tags($summary),
+                       "start"             => wdcal_mySql2PhpTime($start),
+                       "end"               => wdcal_mySql2PhpTime($finish),
+                       "is_allday"         => ($allday ? 1 : 0),
+                       "is_moredays"       => (substr($start, 0, 10) != substr($finish, 0, 10)),
+                       "is_recurring"      => ($row["type"] == "birthday"),
+                       "color"             => "7878ff",
+                       "is_editable"       => 0,
+                       "is_editable_quick" => 0,
+                       "location"          => $row["location"],
+                       "attendees"         => '',
+                       "has_notification"  => 0,
+                       "url_detail"        => $base_path . "/events/event/" . $row["id"],
+                       "url_edit"          => "",
+                       "special_type"      => ($row["type"] == "birthday" ? "birthday" : ""),
+               );
+       }
+
+
+       /**
+        * @param int $calendarId
+        * @param string $date_from
+        * @param string $date_to
+        * @param string $base_path
+        * @throws Sabre_DAV_Exception_NotFound
+        * @return array
+        */
+       public function listItemsByRange($calendarId, $date_from, $date_to, $base_path)
+       {
+               $calendar = Sabre_CalDAV_Backend_Common::loadCalendarById($calendarId);
+
+               if ($calendar["namespace"] != CALDAV_NAMESPACE_PRIVATE) throw new Sabre_DAV_Exception_NotFound();
+
+               switch ($calendar["uri"]) {
+                       case CALDAV_FRIENDICA_MINE:
+                               $sql_where = " AND cid = 0";
+                               break;
+                       case CALDAV_FRIENDICA_CONTACTS:
+                               $sql_where = " AND cid > 0";
+                               break;
+                       default:
+                               throw new Sabre_DAV_Exception_NotFound();
+               }
+
+               if ($date_from != "") {
+                       if (is_numeric($date_from)) $sql_where .= " AND `finish` >= '" . date("Y-m-d H:i:s", $date_from) . "'";
+                       else $sql_where .= " AND `finish` >= '" . dbesc($date_from) . "'";
+               }
+               if ($date_to != "") {
+                       if (is_numeric($date_to)) $sql_where .= " AND `start` <= '" . date("Y-m-d H:i:s", $date_to) . "'";
+                       else $sql_where .= " AND `start` <= '" . dbesc($date_to) . "'";
+               }
+               $ret = array();
+
+               $r = q("SELECT * FROM `event` WHERE `uid` = %d " . $sql_where . " ORDER BY `start`", IntVal($calendar["namespace_id"]));
+
+               $a = get_app();
+               foreach ($r as $row) {
+                       $r                = $this->jqcal2wdcal($row, $calendar, $a->get_baseurl());
+                       $r["calendar_id"] = $calendar["id"];
+                       $ret[]            = $r;
+               }
+
+               return $ret;
+       }
+
+
+       /**
+        * Returns a list of calendars for a principal.
+        *
+        * Every project is an array with the following keys:
+        *  * id, a unique id that will be used by other functions to modify the
+        *    calendar. This can be the same as the uri or a database key.
+        *  * uri, which the basename of the uri with which the calendar is
+        *    accessed.
+        *  * principaluri. The owner of the calendar. Almost always the same as
+        *    principalUri passed to this method.
+        *
+        * Furthermore it can contain webdav properties in clark notation. A very
+        * common one is '{DAV:}displayname'.
+        *
+        * @param string $principalUri
+        * @return array
+        */
+       public function getCalendarsForUser($principalUri)
+       {
+               $n = dav_compat_principal2namespace($principalUri);
+               if ($n["namespace"] != $this->getNamespace()) return array();
+
+               $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 (!in_array($cal["uri"], $GLOBALS["CALDAV_PRIVATE_SYSTEM_CALENDARS"])) continue;
+
+                       $dat = array(
+                               "id"                                                      => $cal["id"],
+                               "uri"                                                     => $cal["uri"],
+                               "principaluri"                                            => $principalUri,
+                               '{' . Sabre_CalDAV_Plugin::NS_CALENDARSERVER . '}getctag' => $cal['ctag'] ? $cal['ctag'] : '0',
+                               '{' . Sabre_CalDAV_Plugin::NS_CALDAV . '}supported-calendar-component-set' => new Sabre_CalDAV_Property_SupportedCalendarComponentSet(array("VEVENT")),
+                               "calendar_class"                                          => "Sabre_CalDAV_Calendar_Virtual",
+                       );
+                       foreach ($this->propertyMap as $key=> $field) $dat[$key] = $cal[$field];
+
+                       $ret[] = $dat;
+               }
+
+               return $ret;
+       }
+
+       /**
+        * @param int $calendar_id
+        * @param int $calendarobject_id
+        * @return string
+        */
+       function getItemDetailRedirect($calendar_id, $calendarobject_id)
+       {
+               $a    = get_app();
+               $item = q("SELECT `id` FROM `item` WHERE `event-id` = %d AND `uid` = %d AND deleted = 0", IntVal($calendarobject_id), $a->user["uid"]);
+               if (count($item) == 0) return "/events/";
+               return "/display/" . $a->user["nickname"] . "/" . IntVal($item[0]["id"]);
+
+       }
+}
diff --git a/dav/friendica/dav_carddav_backend_virtual_friendica.inc.php b/dav/friendica/dav_carddav_backend_virtual_friendica.inc.php
new file mode 100644 (file)
index 0000000..3d7e097
--- /dev/null
@@ -0,0 +1,205 @@
+<?php
+
+class Sabre_CardDAV_Backend_Friendica extends Sabre_CardDAV_Backend_Virtual
+{
+
+       /**
+        * @var null|Sabre_CardDAV_Backend_Friendica
+        */
+       private static $instance = null;
+
+       /**
+        * @static
+        * @return Sabre_CardDAV_Backend_Friendica
+        */
+       public static function getInstance() {
+               if (self::$instance == null) {
+                       self::$instance = new Sabre_CardDAV_Backend_Friendica();
+               }
+               return self::$instance;
+       }
+
+
+       /**
+        * @return int
+        */
+       public function getNamespace()
+       {
+               return CARDDAV_NAMESPACE_PRIVATE;
+       }
+
+       /**
+        * @static
+        * @return string
+        */
+       public static function getBackendTypeName() {
+               return t("Friendica-Contacts");
+       }
+
+       /**
+        * Returns the list of addressbooks for a specific user.
+        *
+        * @param string $principalUri
+        * @return array
+        */
+       public function getAddressBooksForUser($principalUri)
+       {
+               $uid = dav_compat_principal2uid($principalUri);
+
+               $addressBooks = array();
+
+               $books = q("SELECT id, ctag FROM %s%saddressbooks WHERE `namespace` = %d AND `namespace_id` = %d AND `uri` = '%s'",
+                       CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CARDDAV_NAMESPACE_PRIVATE, IntVal($uid), dbesc(CARDDAV_FRIENDICA_CONTACT));
+               $ctag = $books[0]["ctag"];
+
+               $addressBooks[] = array(
+                       'id'                                                                => $books[0]["id"],
+                       'uri'                                                               => "friendica",
+                       'principaluri'                                                      => $principalUri,
+                       '{DAV:}displayname'                                                 => t("Friendica-Contacts"),
+                       '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}addressbook-description' => t("Your Friendica-Contacts"),
+                       '{http://calendarserver.org/ns/}getctag'                            => $ctag,
+                       '{' . Sabre_CardDAV_Plugin::NS_CARDDAV . '}supported-address-data'  =>
+                       new Sabre_CardDAV_Property_SupportedAddressData(),
+               );
+
+               return $addressBooks;
+
+       }
+
+       /**
+        * @static
+        * @param array $contact
+        * @return array
+        */
+       private static function dav_contactarr2vcardsource($contact)
+       {
+               $name        = explode(" ", $contact["name"]);
+               $first_name  = $last_name = "";
+               $middle_name = array();
+               $num         = count($name);
+               for ($i = 0; $i < $num && $first_name == ""; $i++) if ($name[$i] != "") {
+                       $first_name = $name[$i];
+                       unset($name[$i]);
+               }
+               for ($i = $num - 1; $i >= 0 && $last_name == ""; $i--) if (isset($name[$i]) && $name[$i] != "") {
+                       $last_name = $name[$i];
+                       unset($name[$i]);
+               }
+               foreach ($name as $n) if ($n != "") $middle_name[] = $n;
+               $vcarddata              = new vcard_source_data($first_name, implode(" ", $middle_name), $last_name);
+               $vcarddata->homepages[] = new vcard_source_data_homepage("pref", $contact["url"]);
+               $vcarddata->last_update = ($contact["last-update"] > 0 ? $contact["last-update"] : $contact["created"]);
+
+               $photo = q("SELECT * FROM photo WHERE `contact-id` = %d ORDER BY scale DESC", $contact["id"]); //prefer size 80x80
+               if ($photo && count($photo) > 0) {
+                       $photodata             = new vcard_source_data_photo();
+                       $photodata->width      = $photo[0]["width"];
+                       $photodata->height     = $photo[0]["height"];
+                       $photodata->type       = "JPEG";
+                       $photodata->binarydata = $photo[0]["data"];
+                       $vcarddata->photo      = $photodata;
+               }
+
+               switch ($contact["network"]) {
+                       case "face":
+                               $vcarddata->socialnetworks[] = new vcard_source_data_socialnetwork("facebook", $contact["notify"], "http://www.facebook.com/" . $contact["notify"]);
+                               break;
+                       case "dfrn":
+                               $vcarddata->socialnetworks[] = new vcard_source_data_socialnetwork("dfrn", $contact["nick"], $contact["url"]);
+                               break;
+                       case "twitter":
+                               $vcarddata->socialnetworks[] = new vcard_source_data_socialnetwork("twitter", $contact["nick"], "http://twitter.com/" . $contact["nick"]); // @TODO Stimmt das?
+                               break;
+               }
+
+               $vcard = vcard_source_compile($vcarddata);
+               return array(
+                       "id"           => $contact["id"],
+                       "carddata"     => $vcard,
+                       "uri"          => $contact["id"] . ".vcf",
+                       "lastmodified" => wdcal_mySql2PhpTime($vcarddata->last_update),
+                       "etag"         => md5($vcard),
+                       "size"         => strlen($vcard),
+               );
+
+       }
+
+       /**
+        * @static
+        * @param int $addressbookId
+        * @throws Sabre_DAV_Exception_NotFound
+        */
+       static protected function createCache_internal($addressbookId) {
+               //$notin    = (count($exclude_ids) > 0 ? " AND id NOT IN (" . implode(", ", $exclude_ids) . ") " : "");
+               $addressbook = q("SELECT * FROM %s%saddressbooks WHERE `id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($addressbookId));
+               if (count($addressbook) != 1 || $addressbook[0]["namespace"] != CARDDAV_NAMESPACE_PRIVATE) throw new Sabre_DAV_Exception_NotFound();
+               $contacts = q("SELECT * FROM `contact` WHERE `uid` = %d AND `blocked` = 0 AND `pending` = 0 AND `hidden` = 0 AND `archive` = 0 ORDER BY `name` ASC", $addressbook[0]["namespace_id"]);
+
+               $retdata = array();
+               foreach ($contacts as $contact) {
+                       $x            = static::dav_contactarr2vcardsource($contact);
+                       q("INSERT INTO %s%saddressbookobjects (`addressbook_id`, `contact`, `carddata`, `uri`, `lastmodified`, `etag`, `size`) VALUES (%d, %d, '%s', '%s', NOW(), '%s', %d)",
+                               CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $addressbookId, $contact["id"], dbesc($x["carddata"]), dbesc($x["uri"]), dbesc($x["etag"]), $x["size"]
+                       );
+               }
+       }
+
+
+       /**
+        * Updates a card.
+        *
+        * The addressbook id will be passed as the first argument. This is the
+        * same id as it is returned from the getAddressbooksForUser method.
+        *
+        * The cardUri is a base uri, and doesn't include the full path. The
+        * cardData argument is the vcard body, and is passed as a string.
+        *
+        * It is possible to return an ETag from this method. This ETag should
+        * match that of the updated resource, and must be enclosed with double
+        * quotes (that is: the string itself must contain the actual quotes).
+        *
+        * You should only return the ETag if you store the carddata as-is. If a
+        * subsequent GET request on the same card does not have the same body,
+        * byte-by-byte and you did return an ETag here, clients tend to get
+        * confused.
+        *
+        * If you don't return an ETag, you can just return null.
+        *
+        * @param string $addressBookId
+        * @param string $cardUri
+        * @param string $cardData
+        * @throws Sabre_DAV_Exception_Forbidden
+        * @return string|null
+        */
+       public function updateCard($addressBookId, $cardUri, $cardData)
+       {
+               $x = explode("-", $addressBookId);
+
+               $etag = md5($cardData);
+               q("UPDATE %s%scards SET carddata = '%s', lastmodified = %d, etag = '%s', size = %d, manually_edited = 1 WHERE uri = '%s' AND namespace = %d AND namespace_id =%d",
+                       CALDAV_SQL_DB, CALDAV_SQL_PREFIX, dbesc($cardData), time(), $etag, strlen($cardData), dbesc($cardUri), IntVal($x[10]), IntVal($x[1])
+               );
+               q('UPDATE %s%saddressbooks_community SET ctag = ctag + 1 WHERE uid = %d', CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($x[1]));
+
+               return '"' . $etag . '"';
+       }
+
+       /**
+        * Deletes a card
+        *
+        * @param string $addressBookId
+        * @param string $cardUri
+        * @throws Sabre_DAV_Exception_Forbidden
+        * @return bool
+        */
+       public function deleteCard($addressBookId, $cardUri)
+       {
+               $x = explode("-", $addressBookId);
+
+               q("UPDATE %s%scards SET manually_deleted = 1 WHERE namespace = %d AND namespace_id = %d AND uri = '%s'", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($x[0]), IntVal($x[1]), dbesc($cardUri));
+               q('UPDATE %s%saddressbooks_community SET ctag = ctag + 1 WHERE uid = %d', CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($x[1]));
+
+               return true;
+       }
+}
diff --git a/dav/friendica/dav_friendica_auth.inc.php b/dav/friendica/dav_friendica_auth.inc.php
new file mode 100644 (file)
index 0000000..acc33fa
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+
+class Sabre_DAV_Auth_Backend_Std extends Sabre_DAV_Auth_Backend_AbstractBasic {
+
+    public function __construct() {
+    }
+
+
+       /**
+        * @var Sabre_DAV_Auth_Backend_Std|null
+        */
+       private static $intstance = null;
+
+       /**
+        * @static
+        * @return Sabre_DAV_Auth_Backend_Std
+        */
+       public static function &getInstance() {
+               if (is_null(self::$intstance)) {
+                       self::$intstance = new Sabre_DAV_Auth_Backend_Std();
+               }
+               return self::$intstance;
+       }
+
+
+       /**
+        * @return array
+        */
+       public function getUsers() {
+        return array($this->currentUser);
+    }
+
+       /**
+        * @return null|string
+        */
+       public function getCurrentUser() {
+        return $this->currentUser;
+    }
+
+       /**
+        * Authenticates the user based on the current request.
+        *
+        * If authentication is successful, true must be returned.
+        * If authentication fails, an exception must be thrown.
+        *
+        * @param Sabre_DAV_Server $server
+        * @param string $realm
+        * @throws Sabre_DAV_Exception_NotAuthenticated
+        * @return bool
+        */
+       public function authenticate(Sabre_DAV_Server $server, $realm) {
+
+               $a = get_app();
+               if (isset($a->user["uid"])) {
+                       $this->currentUser = strtolower($a->user["nickname"]);
+                       return true;
+               }
+
+               $auth = new Sabre_HTTP_BasicAuth();
+               $auth->setHTTPRequest($server->httpRequest);
+               $auth->setHTTPResponse($server->httpResponse);
+               $auth->setRealm($realm);
+               $userpass = $auth->getUserPass();
+               if (!$userpass) {
+                       $auth->requireLogin();
+                       throw new Sabre_DAV_Exception_NotAuthenticated('No basic authentication headers were found');
+               }
+
+               // Authenticates the user
+               if (!$this->validateUserPass($userpass[0],$userpass[1])) {
+                       $auth->requireLogin();
+                       throw new Sabre_DAV_Exception_NotAuthenticated('Username or password does not match');
+               }
+               $this->currentUser = strtolower($userpass[0]);
+               return true;
+       }
+
+
+       /**
+        * @param string $username
+        * @param string $password
+        * @return bool
+        */
+       protected function validateUserPass($username, $password) {
+               $encrypted = hash('whirlpool',trim($password));
+               $r = q("SELECT COUNT(*) anz FROM `user` WHERE `nickname` = '%s' AND `password` = '%s' AND `blocked` = 0 AND `account_expired` = 0 AND `verified` = 1 LIMIT 1",
+                       dbesc(trim($username)),
+                       dbesc($encrypted)
+               );
+               return ($r[0]["anz"] == 1);
+    }
+    
+}
diff --git a/dav/friendica/dav_friendica_principal.inc.php b/dav/friendica/dav_friendica_principal.inc.php
new file mode 100644 (file)
index 0000000..780bcd2
--- /dev/null
@@ -0,0 +1,218 @@
+<?php
+
+
+class Sabre_DAVACL_PrincipalBackend_Std implements Sabre_DAVACL_IPrincipalBackend
+{
+
+       /**
+        * Principals prefix
+        *
+        * @var string
+        */
+       public $prefix = 'principals/users';
+
+       /**
+        * @var Sabre_DAV_Auth_Backend_AbstractBasic $authBackend;
+        */
+       protected $authBackend;
+
+       public function __construct(&$authBackend)
+       {
+
+               $this->authBackend = &$authBackend;
+
+       }
+
+
+       /**
+        * @var Sabre_DAVACL_IPrincipalBackend|null
+        */
+       private static $intstance = null;
+
+       /**
+        * @static
+        * @return Sabre_DAVACL_IPrincipalBackend
+        */
+       public static function &getInstance() {
+               if (is_null(self::$intstance)) {
+                       $authBackend              = Sabre_DAV_Auth_Backend_Std::getInstance();
+                       self::$intstance = new Sabre_DAVACL_PrincipalBackend_Std($authBackend);
+               }
+               return self::$intstance;
+       }
+
+       /**
+        * Returns a list of principals based on a prefix.
+        *
+        * This prefix will often contain something like 'principals'. You are only
+        * expected to return principals that are in this base path.
+        *
+        * You are expected to return at least a 'uri' for every user, you can
+        * return any additional properties if you wish so. Common properties are:
+        *   {DAV:}displayname
+        *   {http://sabredav.org/ns}email-address - This is a custom SabreDAV
+        *     field that's actualy injected in a number of other properties. If
+        *     you have an email address, use this property.
+        *
+        * @param string $prefixPath
+        * @return array
+        */
+       public function getPrincipalsByPrefix($prefixPath)
+       {
+
+               // This backend only support principals in one collection
+               if ($prefixPath !== $this->prefix) return array();
+
+               $users = array();
+
+               $r = q("SELECT `nickname` FROM `user` WHERE `nickname` = '%s'", escape_tags($this->authBackend->getCurrentUser()) );
+               foreach ($r as $t) {
+                       $users[] = array(
+                               'uri'               => $this->prefix . '/' . strtolower($t['nickname']),
+                               '{DAV:}displayname' => $t['nickname'],
+                       );
+               }
+
+               return $users;
+
+       }
+
+       /**
+        * Returns a specific principal, specified by it's path.
+        * The returned structure should be the exact same as from
+        * getPrincipalsByPrefix.
+        *
+        * @param string $path
+        * @return array
+        */
+       public function getPrincipalByPath($path)
+       {
+
+               list($prefixPath, $userName) = Sabre_DAV_URLUtil::splitPath($path);
+
+               // This backend only support principals in one collection
+               if ($prefixPath !== $this->prefix) return null;
+
+               $r = q("SELECT `nickname` FROM `user` WHERE `nickname` = '%s'", escape_tags($userName) );
+               if (count($r) == 0) return array();
+
+               return array(
+                       'uri'               => $this->prefix . '/' . strtolower($r[0]['nickname']),
+                       '{DAV:}displayname' => $r[0]['nickname'],
+               );
+
+       }
+
+
+       function getGroupMemberSet($principal)
+       {
+               return array();
+       }
+
+       function getGroupMembership($principal)
+       {
+               return array();
+       }
+
+
+       /**
+        * Updates the list of group members for a group principal.
+        *
+        * The principals should be passed as a list of uri's.
+        *
+        * @param string $principal
+        * @param array $members
+        * @throws Sabre_DAV_Exception
+        * @return void
+        */
+       public function setGroupMemberSet($principal, array $members)
+       {
+               throw new Sabre_DAV_Exception('Operation not supported');
+       }
+
+       /**
+        * Updates one ore more webdav properties on a principal.
+        *
+        * The list of mutations is supplied as an array. Each key in the array is
+        * a propertyname, such as {DAV:}displayname.
+        *
+        * Each value is the actual value to be updated. If a value is null, it
+        * must be deleted.
+        *
+        * This method should be atomic. It must either completely succeed, or
+        * completely fail. Success and failure can simply be returned as 'true' or
+        * 'false'.
+        *
+        * It is also possible to return detailed failure information. In that case
+        * an array such as this should be returned:
+        *
+        * array(
+        *   200 => array(
+        *      '{DAV:}prop1' => null,
+        *   ),
+        *   201 => array(
+        *      '{DAV:}prop2' => null,
+        *   ),
+        *   403 => array(
+        *      '{DAV:}prop3' => null,
+        *   ),
+        *   424 => array(
+        *      '{DAV:}prop4' => null,
+        *   ),
+        * );
+        *
+        * In this previous example prop1 was successfully updated or deleted, and
+        * prop2 was succesfully created.
+        *
+        * prop3 failed to update due to '403 Forbidden' and because of this prop4
+        * also could not be updated with '424 Failed dependency'.
+        *
+        * This last example was actually incorrect. While 200 and 201 could appear
+        * in 1 response, if there's any error (403) the other properties should
+        * always fail with 423 (failed dependency).
+        *
+        * But anyway, if you don't want to scratch your head over this, just
+        * return true or false.
+        *
+        * @param string $path
+        * @param array $mutations
+        * @return array|bool
+        */
+       function updatePrincipal($path, $mutations)
+       {
+               // TODO: Implement updatePrincipal() method.
+       }
+
+       /**
+        * This method is used to search for principals matching a set of
+        * properties.
+        *
+        * This search is specifically used by RFC3744's principal-property-search
+        * REPORT. You should at least allow searching on
+        * http://sabredav.org/ns}email-address.
+        *
+        * The actual search should be a unicode-non-case-sensitive search. The
+        * keys in searchProperties are the WebDAV property names, while the values
+        * are the property values to search on.
+        *
+        * If multiple properties are being searched on, the search should be
+        * AND'ed.
+        *
+        * This method should simply return an array with full principal uri's.
+        *
+        * If somebody attempted to search on a property the backend does not
+        * support, you should simply return 0 results.
+        *
+        * You can also just return 0 results if you choose to not support
+        * searching at all, but keep in mind that this may stop certain features
+        * from working.
+        *
+        * @param string $prefixPath
+        * @param array $searchProperties
+        * @return array
+        */
+       function searchPrincipals($prefixPath, array $searchProperties)
+       {
+               // TODO: Implement searchPrincipals() method.
+       }
+}
diff --git a/dav/friendica/layout.fnk.php b/dav/friendica/layout.fnk.php
new file mode 100644 (file)
index 0000000..5b65ec2
--- /dev/null
@@ -0,0 +1,535 @@
+<?php
+
+
+/**
+ *
+ */
+function wdcal_addRequiredHeaders()
+{
+       $a = get_app();
+
+       $a->page['htmlhead'] .= '<link rel="stylesheet"  type="text/css" href="' . $a->get_baseurl() . '/addon/dav/jqueryui/jquery-ui-1.8.21.custom.css' . '" media="all" />' . "\r\n";
+       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/jqueryui/jquery-ui-1.8.21.custom.min.js"></script>' . "\r\n";
+
+       $a->page['htmlhead'] .= '<link rel="stylesheet"  type="text/css" href="' . $a->get_baseurl() . '/addon/dav/colorpicker/colorPicker.css' . '" media="all" />' . "\r\n";
+       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/colorpicker/jquery.colorPicker.min.js"></script>' . "\r\n";
+
+       $a->page['htmlhead'] .= '<link rel="stylesheet"  type="text/css" href="' . $a->get_baseurl() . '/addon/dav/timepicker/timePicker.css' . '" media="all" />' . "\r\n";
+       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/timepicker/jquery.timePicker.min.js"></script>' . "\r\n";
+
+       $a->page['htmlhead'] .= '<link rel="stylesheet"  type="text/css" href="' . $a->get_baseurl() . '/addon/dav/friendica/wdcal.css' . '" media="all" />' . "\r\n";
+       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/common/wdcal.js"></script>' . "\r\n";
+
+       $a->page['htmlhead'] .= '<link rel="stylesheet"  type="text/css" href="' . $a->get_baseurl() . '/addon/dav/wdcal/css/calendar.css' . '" media="all" />' . "\r\n";
+       $a->page['htmlhead'] .= '<link rel="stylesheet"  type="text/css" href="' . $a->get_baseurl() . '/addon/dav/wdcal/css/main.css' . '" media="all" />' . "\r\n";
+
+       switch (get_config("system", "language")) {
+               case "de":
+                       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/common/wdcal/js/wdCalendar_lang_DE.js"></script>' . "\r\n";
+                       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/jqueryui/jquery.ui.datepicker-de.js"></script>' . "\r\n";
+                       break;
+               default:
+                       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/common/wdcal/js/wdCalendar_lang_EN.js"></script>' . "\r\n";
+       }
+
+       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/common/wdcal/js/jquery.calendar.js"></script>' . "\r\n";
+       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/common/wdcal/js/main.js"></script>' . "\r\n";
+}
+
+
+
+/**
+ * @param int $calendar_id
+ */
+function wdcal_print_user_ics($calendar_id)
+{
+       $calendar_id = IntVal($calendar_id);
+
+       $a = get_app();
+       header("Content-type: text/plain");
+
+       $str  = "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Friendica//DAV-Plugin//EN\r\n";
+       $cals = q("SELECT * FROM %s%scalendars WHERE `id` = %d AND `namespace` = %d AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calendar_id, CALDAV_NAMESPACE_PRIVATE, $a->user["uid"]);
+       if (count($cals) > 0) {
+               $objs = q("SELECT * FROM %s%scalendarobjects WHERE `calendar_id` = %d ORDER BY `firstOccurence`", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calendar_id);
+
+               foreach ($objs as $obj) {
+                       preg_match("/BEGIN:VEVENT(.*)END:VEVENT/siu", $obj["calendardata"], $matches);
+                       $str2 = preg_replace("/([^\\r])\\n/siu", "\\1\r\n", $matches[0]);
+                       $str2 = preg_replace("/MAILTO:.*[^:a-z0-9_\+äöüß\\n\\n@-]+.*(:|\\r\\n[^ ])/siU", "\\1", $str2);
+                       $str .= $str2 . "\r\n";
+               }
+       }
+       $str .= "END:VCALENDAR\r\n";
+
+       echo $str;
+       killme();
+}
+
+
+/**
+ * @param int $calendar_id
+ * @return string
+ */
+function wdcal_import_user_ics($calendar_id) {
+       $a = get_app();
+       $calendar_id = IntVal($calendar_id);
+       $o = "";
+
+       $server = dav_create_server(true, true, false);
+       $calendar = dav_get_current_user_calendar_by_id($server, $calendar_id, DAV_ACL_WRITE);
+       if (!$calendar) goaway($a->get_baseurl() . "/dav/wdcal/");
+
+       if (isset($_REQUEST["save"])) {
+               check_form_security_token_redirectOnErr('/dav/settings/', 'icsimport');
+
+               if ($_FILES["ics_file"]["tmp_name"] != "" && is_uploaded_file($_FILES["ics_file"]["tmp_name"])) try {
+                       $text = file_get_contents($_FILES["ics_file"]["tmp_name"]);
+
+                       /** @var Sabre_VObject_Component_VCalendar $vObject  */
+                       $vObject        = Sabre_VObject_Reader::read($text);
+                       $comp = $vObject->getComponents();
+                       $imported = array();
+                       foreach ($comp as $c) try {
+                               /** @var Sabre_VObject_Component_VEvent $c */
+                               $uid = $c->__get("UID")->value;
+                               if (!isset($imported[$uid])) $imported[$uid] = "";
+                               $imported[$uid] .= $c->serialize();
+                       } catch (Exception $e) {
+                               notice(t("Something went wrong when trying to import the file. Sorry. Maybe some events were imported anyway."));
+                       }
+
+                       if (isset($_REQUEST["overwrite"])) {
+                               $children = $calendar->getChildren();
+                               foreach ($children as $child) {
+                                       /** @var Sabre_CalDAV_CalendarObject $child */
+                                       $child->delete();
+                               }
+                               $i = 1;
+                       } else {
+                               $i = 0;
+                               $children = $calendar->getChildren();
+                               foreach ($children as $child) {
+                                       /** @var Sabre_CalDAV_CalendarObject $child */
+                                       $name = $child->getName();
+                                       if (preg_match("/import\-([0-9]+)\.ics/siu", $name, $matches)) {
+                                               if ($matches[1] > $i) $i = $matches[1];
+                                       };
+                               }
+                               $i++;
+                       }
+
+                       foreach ($imported as $object) try {
+
+                               $str = "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Friendica//DAV-Plugin//EN\r\n";
+                               $str .= trim($object);
+                               $str .= "\r\nEND:VCALENDAR\r\n";
+
+                               $calendar->createFile("import-" . $i . ".ics", $str);
+                               $i++;
+                       } catch (Exception $e) {
+                               notice(t("Something went wrong when trying to import the file. Sorry."));
+                       }
+
+                       $o = t("The ICS-File has been imported.");
+               } catch (Exception $e) {
+                       notice(t("Something went wrong when trying to import the file. Sorry. Maybe some events were imported anyway."));
+               } else {
+                       notice(t("No file was uploaded."));
+               }
+       }
+
+
+       $o .= "<a href='" . $a->get_baseurl() . "/dav/wdcal/'>" . t("Go back to the calendar") . "</a><br><br>";
+
+       $num = q("SELECT COUNT(*) num FROM %s%scalendarobjects WHERE `calendar_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calendar_id);
+
+       $o .= "<h2>" . t("Import a ICS-file") . "</h2>";
+       $o .= '<form method="POST" action="' . $a->get_baseurl() . '/dav/wdcal/' . $calendar_id . '/ics-import/" enctype="multipart/form-data">';
+       $o .= "<input type='hidden' name='form_security_token' value='" . get_form_security_token('icsimport') . "'>\n";
+       $o .= "<label for='ics_file'>" . t("ICS-File") . "</label><input type='file' name='ics_file' id='ics_file'><br>\n";
+       if ($num[0]["num"] > 0) $o .= "<label for='overwrite'>" . str_replace("#num#", $num[0]["num"], t("Overwrite all #num# existing events")) . "</label> <input name='overwrite' id='overwrite' type='checkbox'><br>\n";
+       $o .= "<input type='submit' name='save' value='" . t("Upload") . "'>";
+       $o .= '</form>';
+
+       return $o;
+}
+
+
+/**
+ * @param array|Sabre_CalDAV_Calendar[] $calendars
+ * @param array|int[] $calendars_selected
+ * @param string $data_feed_url
+ * @param string $view
+ * @param int $theme
+ * @param int $height_diff
+ * @param bool $readonly
+ * @param string $curr_day
+ * @param array $add_params
+ * @param bool $show_nav
+ * @return string
+ */
+function wdcal_printCalendar($calendars, $calendars_selected, $data_feed_url, $view = "week", $theme = 0, $height_diff = 175, $readonly = false, $curr_day = "", $add_params = array(), $show_nav = true)
+{
+
+       $a            = get_app();
+       $localization = wdcal_local::getInstanceByUser($a->user["uid"]);
+
+       if (count($calendars_selected) == 0) foreach ($calendars as $c) {
+               $prop                 = $c->getProperties(array("id"));
+               $calendars_selected[] = $prop["id"];
+       }
+
+       $opts = array(
+               "view"             => $view,
+               "theme"            => $theme,
+               "readonly"         => $readonly,
+               "height_diff"      => $height_diff,
+               "weekstartday"     => $localization->getFirstDayOfWeek(),
+               "data_feed_url"    => $data_feed_url,
+               "date_format_dm1"  => $localization->dateformat_js_dm1(),
+               "date_format_dm2"  => $localization->dateformat_js_dm2(),
+               "date_format_dm3"  => $localization->dateformat_js_dm3(),
+               "date_format_full" => $localization->dateformat_datepicker_js(),
+               "baseurl"          => $a->get_baseurl() . "/dav/wdcal/",
+       );
+
+       $x = '
+<script>
+       $(function() {
+               $("#animexxcalendar").animexxCalendar(' . json_encode($opts) . ');
+       });
+</script>
+
+<div id="animexxcalendar" class="animexxcalendar">
+       <div class="calselect"><strong>Available Calendars:</strong>';
+
+       foreach ($calendars as $cal) {
+               $cal_id = $cal->getProperties(array("id", DAV_DISPLAYNAME));
+               $x .= '<label style="margin-left: 10px; margin-right: 10px;"><input type="checkbox" name="cals[]" value="' . $cal_id["id"] . '"';
+               $found = false;
+               foreach ($calendars_selected as $pre) if ($pre["id"] == $cal_id["id"]) $found = true;
+               if ($found) $x .= ' checked';
+               $x .= '> ' . escape_tags($cal_id[DAV_DISPLAYNAME]) . '</label> ';
+       }
+
+       $x .= '</div>
+       <div class="calhead" style="padding-left:1px;padding-right:1px;">
+               <div class="ptogtitle loaderror" style="display: none;">Sorry, could not load your data, please try again later</div>
+       </div>';
+
+       if ($show_nav) {
+
+               $x .= '<div class="ctoolbar">
+               <div class="fbutton faddbtn" style="float: right;">
+                       <div><a href="' . $a->get_baseurl() . '/dav/settings/"><span>' . t("Settings") . ' / ' . t("Help") . '</span></a></div>
+               </div>
+               <div class="fbutton addcal">
+                       <div><a href="' . $a->get_baseurl() . '/dav/wdcal/new/" class="addcal">' . t("New event") . '</a></div>
+               </div>
+               <div class="btnseparator"></div>
+               <div class="fbutton showtodaybtn">
+                       <div><span class="showtoday">' . t("Today") . '</span></div>
+               </div>
+               <div class="btnseparator"></div>
+
+               <div class="fbutton showdaybtn">
+                       <div><span title="Day" class="showdayview ';
+
+               if ($view == "day") $x .= 'fcurrent';
+
+               $x .= '">' . t("Day") . '</span></div>
+               </div>
+               <div class="fbutton showweekbtn ';
+
+               if ($view == "week") $x .= "fcurrent";
+
+               $x .= '">
+                       <div><span title="Week" class="showweekview">' . t("Week") . '</span></div>
+               </div>
+               <div class="showmonthbtn fbutton ';
+
+               if ($view == "month") $x .= 'fcurrent';
+
+               $x .= '">
+                       <div><span title="Month" class="showmonthview">' . t("Month") . '</span></div>
+
+               </div>
+               <div class="btnseparator"></div>
+               <div class="fbutton showreflashbtn">
+                       <div><span class="showdayflash">' . t("Reload") . '</span></div>
+               </div>
+               <div class="btnseparator"></div>
+               <div title="' . t("Previous") . '"  class="fbutton sfprevbtn">
+                       <span class="fprev"></span>
+               </div>
+               <div title="' . t("Next") . '" class="fbutton sfnextbtn">
+                       <span class="fnext"></span>
+               </div>
+               <div class="fshowdatep fbutton" style="white-space: nowrap; position: relative;">
+                       <input name="txtshow" class="hdtxtshow" style="position: absolute; bottom: 0; left: 0; width: 0; height: 0; border: 0; padding: 0; margin: 0;">
+                       <span class="txtdatetimeshow">' . t("Date") . '</span>
+               </div>
+               <div style="float: right;">
+                       <div class="clear"></div>
+               </div>
+       </div>';
+       }
+       $x .= '
+       <div style="padding:1px;">
+               <div class="calmain printborder">
+                       <div class="gridcontainer" style="overflow-y: visible;"></div>
+               </div>
+       </div>
+</div>';
+
+       return $x;
+}
+
+
+/**
+ * @param int $calendar_id
+ * @param int $calendarobject_id
+ * @return string
+ */
+function wdcal_getDetailPage($calendar_id, $calendarobject_id)
+{
+       $a = get_app();
+
+       try {
+               $details = null;
+               $server  = dav_create_server(true, true, false);
+               $cal     = dav_get_current_user_calendar_by_id($server, $calendar_id, DAV_ACL_READ);
+               $obj     = Sabre_CalDAV_Backend_Common::loadCalendarobjectById($calendarobject_id);
+               dav_get_current_user_calendarobject($server, $cal, $obj["uri"], DAV_ACL_READ); // Check permissions
+
+               $calbackend = wdcal_calendar_factory_by_id($calendar_id);
+               $redirect   = $calbackend->getItemDetailRedirect($calendar_id, $calendarobject_id);
+
+               if ($redirect !== null) goaway($a->get_baseurl() . $redirect);
+
+               $details = $obj;
+       } catch (Exception $e) {
+               info(t("Error") . ": " . $e);
+               goaway($a->get_baseurl() . "/dav/wdcal/");
+       }
+
+       return print_r($details, true);
+}
+
+
+/**
+ * @param int $calendar_id
+ * @param int $uri
+ * @return string
+ */
+function wdcal_getEditPage($calendar_id, $uri)
+{
+       $a            = get_app();
+       $localization = wdcal_local::getInstanceByUser($a->user["uid"]);
+
+       return wdcal_getEditPage_str($localization, $a->get_baseurl(), $calendar_id, $uri);
+}
+
+/**
+ * @return string
+ */
+function wdcal_getNewPage()
+{
+       $a            = get_app();
+       $localization = wdcal_local::getInstanceByUser($a->user["uid"]);
+
+       return wdcal_getEditPage_str($localization, $a->get_baseurl(), 0, 0);
+}
+
+
+/**
+ * @param App $a
+ * @return string
+ */
+function wdcal_getSettingsPage(&$a)
+{
+
+       if (!local_user()) {
+               notice(t('Permission denied.') . EOL);
+               return '';
+       }
+
+       if (isset($_REQUEST["save"])) {
+               check_form_security_token_redirectOnErr('/dav/settings/', 'calprop');
+               set_pconfig($a->user["uid"], "dav", "dateformat", $_REQUEST["wdcal_date_format"]);
+               info(t('The new values have been saved.'));
+       }
+
+       if (isset($_REQUEST["save_cals"])) {
+               check_form_security_token_redirectOnErr('/dav/settings/', 'calprop');
+
+               $r = q("SELECT * FROM %s%scalendars WHERE `namespace` = " . CALDAV_NAMESPACE_PRIVATE . " AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($a->user["uid"]));
+               foreach ($r as $cal) {
+                       $backend = wdcal_calendar_factory($cal["namespace"], $cal["namespace_id"], $cal["uri"], $cal);
+                       $change_sql = "";
+                       $col = substr($_REQUEST["color"][$cal["id"]], 1);
+                       if (strtolower($col) != strtolower($cal["calendarcolor"])) $change_sql .= ", `calendarcolor` = '" . dbesc($col) . "'";
+                       if (!is_subclass_of($backend, "Sabre_CalDAV_Backend_Virtual")) {
+                               if ($_REQUEST["uri"][$cal["id"]] != $cal["uri"]) $change_sql .= ", `uri` = '" . dbesc($_REQUEST["uri"][$cal["id"]]) . "'";
+                               if ($_REQUEST["name"][$cal["id"]] != $cal["displayname"]) $change_sql .= ", `displayname` = '" . dbesc($_REQUEST["name"][$cal["id"]]) . "'";
+                       }
+                       if ($change_sql != "") {
+                               q("UPDATE %s%scalendars SET `ctag` = `ctag` + 1 $change_sql WHERE `id` = %d AND `namespace_id` = %d AND `namespace_id` = %d",
+                                       CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $cal["id"], CALDAV_NAMESPACE_PRIVATE, IntVal($a->user["uid"]));
+                               info(t('The calendar has been updated.'));
+                       }
+               }
+
+               if (isset($_REQUEST["uri"]["new"]) && $_REQUEST["uri"]["new"] != "" && $_REQUEST["name"]["new"] && $_REQUEST["name"]["new"] != "") {
+                       $order = q("SELECT MAX(`calendarorder`) ord FROM %s%scalendars WHERE `namespace_id` = %d AND `namespace_id` = %d",
+                               CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CALDAV_NAMESPACE_PRIVATE, IntVal($a->user["uid"]));
+                       $neworder = $order[0]["ord"] + 1;
+                       q("INSERT INTO %s%scalendars (`namespace`, `namespace_id`, `calendarorder`, `calendarcolor`, `displayname`, `timezone`, `uri`, `has_vevent`, `ctag`)
+                               VALUES (%d, %d, %d, '%s', '%s', '%s', '%s', 1, 1)",
+                               CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CALDAV_NAMESPACE_PRIVATE, IntVal($a->user["uid"]), $neworder, dbesc(strtolower(substr($_REQUEST["color"]["new"], 1))),
+                               dbesc($_REQUEST["name"]["new"]), dbesc($a->timezone), dbesc($_REQUEST["uri"]["new"])
+                       );
+                       info(t('The new calendar has been created.'));
+               }
+       }
+
+       if (isset($_REQUEST["remove_cal"])) {
+               check_form_security_token_redirectOnErr('/dav/settings/', 'del_cal', 't');
+
+               $c = q("SELECT * FROM %s%scalendars WHERE `id` = %d AND `namespace_id` = %d AND `namespace_id` = %d",
+                       CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($_REQUEST["remove_cal"]), CALDAV_NAMESPACE_PRIVATE, IntVal($a->user["uid"]));
+               if (count($c) != 1) killme();
+
+               $calobjs = q("SELECT `id` FROM %s%scalendarobjects WHERE `calendar_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($_REQUEST["remove_cal"]));
+
+               $newcal = q("SELECT * FROM %s%scalendars WHERE `id` != %d AND `namespace_id` = %d AND `namespace_id` = %d ORDER BY `calendarcolor` LIMIT 0,1",
+                       CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($_REQUEST["remove_cal"]), CALDAV_NAMESPACE_PRIVATE, IntVal($a->user["uid"]));
+               if (count($newcal) != 1) killme();
+
+               q("UPDATE %s%scalendarobjects SET `calendar_id` = %d WHERE `calendar_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($newcal[0]["id"]), IntVal($c[0]["id"]));
+
+               foreach ($calobjs as $calobj) renderCalDavEntry_calobj_id($calobj["id"]);
+
+               q("DELETE FROM %s%scalendars WHERE `id` = %s", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($_REQUEST["remove_cal"]));
+               q("UPDATE %s%scalendars SET `ctag` = `ctag` + 1 WHERE `id` = " . CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $newcal[0]["id"]);
+
+               info(t('The calendar has been deleted.'));
+       }
+
+       $o = "";
+
+       $o .= "<a href='" . $a->get_baseurl() . "/dav/wdcal/'>" . t("Go back to the calendar") . "</a><br><br>";
+
+       $o .= '<h3>' . t('Calendar Settings') . '</h3>';
+
+       $current_format = wdcal_local::getInstanceByUser($a->user["uid"]);
+       $o .= '<form method="POST" action="' . $a->get_baseurl() . '/dav/settings/">';
+       $o .= "<input type='hidden' name='form_security_token' value='" . get_form_security_token('calprop') . "'>\n";
+
+       $o .= '<label for="wdcal_date_format">' . t('Date format') . ':</label><select name="wdcal_date_format" id="wdcal_date_format" size="1">';
+       $classes = wdcal_local::getInstanceClasses();
+       foreach ($classes as $c) {
+               $o .= '<option value="' . $c::getID() . '" ';
+               if ($c::getID() == $current_format::getID()) $o .= 'selected';
+               $o .= '>' . escape_tags($c::getName()) . '</option>';
+       }
+       $o .= '</select><br>';
+
+       $o .= '<label for="wdcal_time_zone">' . t('Time zone') . ':</label><input id="wdcal_time_zone" value="' . $a->timezone . '" disabled><br>';
+
+       $o .= '<input type="submit" name="save" value="' . t('Save') . '">';
+       $o .= '</form>';
+
+
+       $o .= '<br><br><h3>' . t('Calendars') . '</h3>';
+       $o .= '<form method="POST" action="' . $a->get_baseurl() . '/dav/settings/">';
+       $o .= "<input type='hidden' name='form_security_token' value='" . get_form_security_token('calprop') . "'>\n";
+       $o .= "<table><tr><th>Type</th><th>Color</th><th>Name</th><th>URI (for CalDAV)</th><th>ICS</th></tr>";
+
+       $r = q("SELECT * FROM %s%scalendars WHERE `namespace` = " . CALDAV_NAMESPACE_PRIVATE . " AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($a->user["uid"]));
+       $private_max = 0;
+       $num_non_virtual = 0;
+       foreach ($r as $x) {
+               $backend = wdcal_calendar_factory($x["namespace"], $x["namespace_id"], $x["uri"], $x);
+               if (!is_subclass_of($backend, "Sabre_CalDAV_Backend_Virtual")) $num_non_virtual++;
+       }
+       foreach ($r as $x) {
+               $p = explode("private-", $x["uri"]);
+               if (count($p) == 2 && $p[1] > $private_max) $private_max = $p[1];
+
+               $backend = wdcal_calendar_factory($x["namespace"], $x["namespace_id"], $x["uri"], $x);
+               $disabled = (is_subclass_of($backend, "Sabre_CalDAV_Backend_Virtual") ? "disabled" : "");
+               $o .= "<tr>";
+               $o .= "<td style='padding: 2px;'>" . escape_tags($backend->getBackendTypeName()) . "</td>";
+               $o .= "<td style='padding: 2px; text-align: center;'><input style='margin-left: 10px; width: 70px;' class='cal_color' name='color[" . $x["id"] . "]' id='cal_color_" . $x["id"] . "' value='#" . (strlen($x["calendarcolor"]) != 6 ? "5858ff" : escape_tags($x["calendarcolor"])) . "'></td>";
+               $o .= "<td style='padding: 2px;'><input style='margin-left: 10px;' name='name[" . $x["id"] . "]' value='" . escape_tags($x["displayname"]) . "' $disabled></td>";
+               $o .= "<td style='padding: 2px;'><input style='margin-left: 10px; width: 150px;' name='uri[" . $x["id"] . "]' value='" . escape_tags($x["uri"]) . "' $disabled></td>";
+               $o .= "<td style='padding: 2px;'><a href='" . $a->get_baseurl() . "/dav/wdcal/" . $x["id"] . "/ics-export/'>Export</a>";
+               if (!is_subclass_of($backend, "Sabre_CalDAV_Backend_Virtual") && $num_non_virtual > 1) $o .= " / <a href='" . $a->get_baseurl() . "/dav/wdcal/" . $x["id"] . "/ics-import/'>Import</a>";
+               $o .= "</td>";
+               $o .= "<td style='padding: 2px; padding-left: 50px;'>";
+               if (!is_subclass_of($backend, "Sabre_CalDAV_Backend_Virtual") && $num_non_virtual > 1) $o .= "<a href='" . $a->get_baseurl() . "/dav/settings/?remove_cal=" . $x["id"] . "&amp;t=" . get_form_security_token("del_cal") . "' class='delete_cal'>Delete</a>";
+               $o .= "</td>\n";
+               $o .= "</tr>\n";
+       }
+
+       $private_max++;
+       $o .= "<tr class='cal_add_row' style='display: none;'>";
+       $o .= "<td style='padding: 2px;'>" . escape_tags(Sabre_CalDAV_Backend_Private::getBackendTypeName()) . "</td>";
+       $o .= "<td style='padding: 2px; text-align: center;'><input style='margin-left: 10px; width: 70px;' class='cal_color' name='color[new]' id='cal_color_new' value='#5858ff'></td>";
+       $o .= "<td style='padding: 2px;'><input style='margin-left: 10px;' name='name[new]' value='Another calendar'></td>";
+       $o .= "<td style='padding: 2px;'><input style='margin-left: 10px; width: 150px;' name='uri[new]' value='private-${private_max}'></td>";
+       $o .= "<td></td><td></td>";
+       $o .= "</tr>\n";
+
+       $o .= "</table>";
+       $o .= "<div style='text-align: center;'>[<a href='#' class='calendar_add_caller'>" . t("Create a new calendar") . "</a>]</div>";
+       $o .= '<input type="submit" name="save_cals" value="' . t('Save') . '">';
+       $o .= '</form>';
+       $baseurl = $a->get_baseurl();
+       $o .= "<script>\$(function() {
+               wdcal_edit_calendars_start('" . $current_format->dateformat_datepicker_js() . "', '${baseurl}/dav/');
+       });</script>";
+
+
+       $o .= "<br><h3>" . t("Limitations") . "</h3>";
+
+       $o .= "- The native friendica events are embedded as read-only, half-transparent in the calendar.<br>";
+
+       $o .= "<br><h3>" . t("Warning") . "</h3>";
+
+       $o .= "This plugin still is in a very early stage of development. Expect major bugs!<br>";
+
+       $o .= "<br><h3>" . t("Synchronization (iPhone, Thunderbird Lightning, Android, ...)") . "</h3>";
+
+       $o .= 'This plugin enables synchronization of your dates and contacts with CalDAV- and CardDAV-enabled programs or devices.<br>
+               As an example, the instructions how to set up two-way synchronization with an iPhone/iPodTouch are provided below.<br>
+               Unfortunately, Android does not have native support for CalDAV or CardDAV, so an app has to be installed.<br>
+               On desktops, the Lightning-extension to Mozilla Thunderbird should be able to use this plugin as a backend.<br><br>';
+
+       $o .= '<h4>' . t('Synchronizing this calendar with the iPhone') . '</h4>';
+
+       $o .= "<ul>
+       <li>Go to the settings</li>
+       <li>Mail, contacts, settings</li>
+       <li>Add a new account</li>
+       <li>Other...</li>
+       <li>Calendar -> CalDAV-Account</li>
+       <li><b>Server:</b> " . $a->get_baseurl() . "/dav/ / <b>Username/Password:</b> <em>the same as your friendica-login</em></li>
+       </ul>";
+
+       $o .= '<h4>' . t('Synchronizing your Friendica-Contacts with the iPhone') . '</h4>';
+
+       $o .= "<ul>
+       <li>Go to the settings</li>
+       <li>Mail, contacts, settings</li>
+       <li>Add a new account</li>
+       <li>Other...</li>
+       <li>Contacts -> CardDAV-Account</li>
+       <li><b>Server:</b> " . $a->get_baseurl() . "/dav/ / <b>Username/Password:</b> <em>the same as your friendica-login</em></li>
+       </ul>";
+
+       return $o;
+}
+
diff --git a/dav/friendica/main.php b/dav/friendica/main.php
new file mode 100644 (file)
index 0000000..602bda6
--- /dev/null
@@ -0,0 +1,348 @@
+<?php
+
+require_once('include/security.php');
+
+function dav_install()
+{
+       register_hook('event_created', 'addon/dav/dav.php', 'dav_event_created_hook');
+       register_hook('event_updated', 'addon/dav/dav.php', 'dav_event_updated_hook');
+       register_hook('profile_tabs', 'addon/dav/dav.php', 'dav_profile_tabs_hook');
+       register_hook('cron', 'addon/dav/dav.php', 'dav_cron');
+}
+
+
+function dav_uninstall()
+{
+       unregister_hook('event_created', 'addon/dav/dav.php', 'dav_event_created_hook');
+       unregister_hook('event_updated', 'addon/dav/dav.php', 'dav_event_updated_hook');
+       unregister_hook('profile_tabs', 'addon/dav/dav.php', 'dav_profile_tabs_hook');
+       unregister_hook('cron', 'addon/dav/dav.php', 'dav_cron');
+}
+
+
+function dav_module()
+{
+}
+
+function dav_include_files()
+{
+       require_once (__DIR__ . "/../SabreDAV/lib/Sabre/autoload.php");
+
+       require_once (__DIR__ . "/../common/calendar.fnk.php");
+       require_once (__DIR__ . "/../common/calendar_rendering.fnk.php");
+
+       require_once (__DIR__ . "/../common/dav_caldav_backend_common.inc.php");
+       require_once (__DIR__ . "/../common/dav_caldav_backend_private.inc.php");
+       require_once (__DIR__ . "/../common/dav_caldav_backend_virtual.inc.php");
+       require_once (__DIR__ . "/../common/dav_caldav_root.inc.php");
+       require_once (__DIR__ . "/../common/dav_user_calendars.inc.php");
+       require_once (__DIR__ . "/../common/dav_caldav_calendar_virtual.inc.php");
+       require_once (__DIR__ . "/../common/dav_caldav_calendar_private.inc.php");
+
+       require_once (__DIR__ . "/../common/dav_carddav_root.inc.php");
+       require_once (__DIR__ . "/../common/dav_carddav_backend_common.inc.php");
+       require_once (__DIR__ . "/../common/dav_carddav_backend_virtual.inc.php");
+       require_once (__DIR__ . "/../common/dav_carddav_backend_private.inc.php");
+       require_once (__DIR__ . "/../common/dav_user_addressbooks.inc.php");
+
+       require_once (__DIR__ . "/../common/wdcal_configuration.php");
+       require_once (__DIR__ . "/../common/wdcal_backend.inc.php");
+
+       require_once (__DIR__ . "/dav_friendica_principal.inc.php");
+       require_once (__DIR__ . "/dav_friendica_auth.inc.php");
+       require_once (__DIR__ . "/dav_carddav_backend_virtual_friendica.inc.php");
+       require_once (__DIR__ . "/dav_caldav_backend_virtual_friendica.inc.php");
+       require_once (__DIR__ . "/FriendicaACLPlugin.inc.php");
+
+       require_once (__DIR__ . "/../common/wdcal_edit.inc.php");
+       require_once (__DIR__ . "/calendar.friendica.fnk.php");
+       require_once (__DIR__ . "/layout.fnk.php");
+}
+
+
+/**
+ * @param App $a
+ */
+function dav_init(&$a)
+{
+
+       /*
+        * Recommended settings:
+        * ALTER TABLE `photo` ADD INDEX ( `contact-id` )
+        */
+
+       ini_set("display_errors", 1);
+       error_reporting(E_ALL);
+
+       dav_include_files();
+
+       if (false) {
+               dbg(true);
+               error_reporting(E_ALL);
+               ini_set("display_errors", 1);
+       }
+
+       wdcal_create_std_calendars();
+       wdcal_create_std_addressbooks();
+       wdcal_addRequiredHeaders();
+
+       if ($a->argc >= 2 && $a->argv[1] == "wdcal") {
+
+               if ($a->argc >= 3 && $a->argv[2] == "feed") {
+                       wdcal_print_feed($a->get_baseurl() . "/dav/wdcal/");
+                       killme();
+               }
+               return;
+       }
+       if ($a->argc >= 2 && $a->argv[1] == "getExceptionDates") {
+               echo wdcal_getEditPage_exception_selector();
+               killme();
+       }
+
+       if ($a->argc >= 2 && $a->argv[1] == "settings") {
+               return;
+       }
+
+
+       if (isset($_REQUEST["test"])) {
+               renderAllCalDavEntries();
+       }
+
+
+       $server  = dav_create_server();
+
+       $browser = new Sabre_DAV_Browser_Plugin();
+       $server->addPlugin($browser);
+
+       $server->exec();
+
+       killme();
+}
+
+/**
+ * @return string
+ */
+function dav_content()
+{
+       $a = get_app();
+       if (!isset($a->user["uid"]) || $a->user["uid"] == 0) {
+               return login();
+       }
+
+       $x = "";
+       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 {
+                                       $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);
+                       }
+               }
+       } 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;
+}
+
+
+/**
+ * @param App $a
+ * @param object $b
+ */
+function dav_event_created_hook(&$a, &$b)
+{
+       dav_include_files();
+       // @TODO Updating the cache instead of completely invalidating and rebuilding it
+       Sabre_CalDAV_Backend_Friendica::invalidateCache($a->user["uid"], CALDAV_FRIENDICA_CONTACTS);
+       Sabre_CalDAV_Backend_Friendica::invalidateCache($a->user["uid"], CALDAV_FRIENDICA_MINE);
+}
+
+/**
+ * @param App $a
+ * @param object $b
+ */
+function dav_event_updated_hook(&$a, &$b)
+{
+       dav_include_files();
+       // @TODO Updating the cache instead of completely invalidating and rebuilding it
+       Sabre_CalDAV_Backend_Friendica::invalidateCache($a->user["uid"], CALDAV_FRIENDICA_CONTACTS);
+       Sabre_CalDAV_Backend_Friendica::invalidateCache($a->user["uid"], CALDAV_FRIENDICA_MINE);
+}
+
+/**
+ * @param App $a
+ * @param object $b
+ */
+function dav_profile_tabs_hook(&$a, &$b)
+{
+       $b["tabs"][] = array(
+               "label" => t('Calendar'),
+               "url"   => $a->get_baseurl() . "/dav/wdcal/",
+               "sel"   => "",
+               "title" => t('Extended calendar with CalDAV-support'),
+       );
+}
+
+
+/**
+ * @param App $a
+ * @param object $b
+ */
+function dav_cron(&$a, &$b)
+{
+       dav_include_files();
+
+       $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();
+               if (count($calendar) != 1 || count($event) == 0) continue;
+               switch ($calendar[0]["namespace"]) {
+                       case CALDAV_NAMESPACE_PRIVATE:
+                               $user = q("SELECT * FROM user WHERE `uid` = %d AND `blocked` = 0", $calendar[0]["namespace_id"]);
+                               if (count($user) != 1) continue;
+                               $users[] = $user[0];
+                               break;
+               }
+               switch ($not["action"]) {
+                       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"] . "/");
+                                       $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%!<br>\n<br>\nThe event \"%event%\" is about to begin:<br>\n<a href='" . "%url%" . "'>%url%</a>");
+                                       $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');
+                                       enotify::send($params);
+                               }
+                               break;
+               }
+       }
+}
+
+
+/**
+ * @param App $a
+ * @param null|object $o
+ */
+function dav_plugin_admin_post(&$a = null, &$o = null)
+{
+       check_form_security_token_redirectOnErr('/admin/plugins/dav', 'dav_admin_save');
+
+       dav_include_files();
+       require_once(__DIR__ . "/database-init.inc.php");
+
+       if (isset($_REQUEST["install"])) {
+               $errs = dav_create_tables();
+               if (count($errs) == 0) info(t('The database tables have been installed.') . EOL);
+               else notice(t("An error occurred during the installation.") . EOL);
+       }
+       if (isset($_REQUEST["upgrade"])) {
+               $errs = dav_upgrade_tables();
+               if (count($errs) == 0) {
+                       renderAllCalDavEntries();
+                       info(t('The database tables have been updated.') . EOL);
+               }
+               else notice(t("An error occurred during the update.") . EOL);
+       }
+}
+
+/**
+ * @param App $a
+ * @param string $o
+ */
+function dav_plugin_admin(&$a, &$o)
+{
+       dav_include_files();
+       require_once(__DIR__ . "/database-init.inc.php");
+
+       $dbstatus = dav_check_tables();
+
+       $o = '<input type="hidden" name="form_security_token" value="' . get_form_security_token("dav_admin_save") . '">';
+       $o .= '<i>' . t("No system-wide settings yet.") . '</i><br><br>';
+
+
+       $o .= '<h3>' . t('Database status') . '</h3>';
+       switch ($dbstatus) {
+               case 0:
+                       $o .= t('Installed');
+                       break;
+               case 1:
+                       $o .= "<strong>" . t('Upgrade needed') . "</strong><br>" . t("Please back up all calendar data (the tables beginning with dav_*) before proceeding. While all calendar events <i>should</i> 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.") . "<br><br><input type='submit' name='upgrade' value='" . t('Upgrade') . "'>";
+                       break;
+               case -1:
+                       $o .= t('Not installed') . "<br><br><input type='submit' name='install' value='" . t('Install') . "'>";
+                       break;
+               case -2:
+               default:
+                       $o .= t('Unknown') . "<br><br>" . 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 .= "<br><br>";
+
+       $o .= "<h3>" . t("Troubleshooting") . "</h3>";
+       $o .= "<h4>" . t("Manual creation of the database tables:") . "</h4>";
+       $o .= "<a href='#' onClick='\$(\"#sqlstatements\").show(); return false;'>" . t("Show SQL-statements") . "</a><blockquote style='display: none;' id='sqlstatements'><pre>";
+       switch ($dbstatus) {
+               case 1:
+                       $tables = dav_get_update_statements(1);
+                       foreach ($tables as $t) $o .= escape_tags($t . ";\n\n");
+                       break;
+               default:
+                       $tables = dav_get_create_statements();
+                       foreach ($tables as $t) $o .= escape_tags($t . ";\n\n");
+                       break;
+       }
+       $o .= "</pre></blockquote>";
+}
diff --git a/dav/friendica/wdcal.css b/dav/friendica/wdcal.css
new file mode 100644 (file)
index 0000000..18c25c5
--- /dev/null
@@ -0,0 +1,43 @@
+
+div.colorPicker-picker { display: inline-block; }
+.colorPicker-palette { font-size: 12px; }
+.animexxcalendar label, .colorPicker-palette label { background: none; border: none; padding: 0; margin: 0; box-shadow: none; display: inline; font-size: 14px; }
+.animexxcalendar input, .colorPicker-palette input { font-size: 14px; }
+
+
+.ui-datepicker { width: 200px; }
+.ui-datepicker * { font-size: 12px; line-height: 12px; }
+.ui-datepicker th { padding: 10px 2px; }
+.ui-datepicker select.ui-datepicker-year { min-width: 0; width: 50px !important; }
+#cal_start_time, #cal_end_time { width: 5em; margin-left: 1em; }
+#cal_start_date, #cal_end_date { width: 6em;}
+
+
+label.block {
+       background: none repeat scroll 0 0 #CCCCCC;
+       border: 1px solid #EEEEEC;
+       box-shadow: 3px 3px 5px 0 #111111;
+       color: #111111;
+       display: inline-block;
+       font-size: small;
+       margin: 0 10px 1em 0;
+       padding: 3px 5px;
+       width: 38%;
+       vertical-align: top;
+}
+
+label.plain {
+       background: none;
+       border: none;
+       box-shadow: none;
+       color: black;
+       display: inline;
+       margin: 0;
+       padding: 0;
+}
+
+.rec_exceptions { display: inline-block; }
+.rec_exceptions_holder { display: inline-block; }
+.rec_exceptions .remover { }
+#rec_until_count { width: 50px; }
+#rec_until_date { width: 100px; }
\ No newline at end of file
diff --git a/dav/layout.fnk.php b/dav/layout.fnk.php
deleted file mode 100644 (file)
index 597e773..0000000
+++ /dev/null
@@ -1,535 +0,0 @@
-<?php
-
-
-/**
- *
- */
-function wdcal_addRequiredHeaders()
-{
-       $a = get_app();
-
-       $a->page['htmlhead'] .= '<link rel="stylesheet"  type="text/css" href="' . $a->get_baseurl() . '/addon/dav/jqueryui/jquery-ui-1.8.21.custom.css' . '" media="all" />' . "\r\n";
-       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/jqueryui/jquery-ui-1.8.21.custom.min.js"></script>' . "\r\n";
-
-       $a->page['htmlhead'] .= '<link rel="stylesheet"  type="text/css" href="' . $a->get_baseurl() . '/addon/dav/colorpicker/colorPicker.css' . '" media="all" />' . "\r\n";
-       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/colorpicker/jquery.colorPicker.min.js"></script>' . "\r\n";
-
-       $a->page['htmlhead'] .= '<link rel="stylesheet"  type="text/css" href="' . $a->get_baseurl() . '/addon/dav/timepicker/timePicker.css' . '" media="all" />' . "\r\n";
-       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/timepicker/jquery.timePicker.min.js"></script>' . "\r\n";
-
-       $a->page['htmlhead'] .= '<link rel="stylesheet"  type="text/css" href="' . $a->get_baseurl() . '/addon/dav/wdcal.css' . '" media="all" />' . "\r\n";
-       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/common/wdcal.js"></script>' . "\r\n";
-
-       $a->page['htmlhead'] .= '<link rel="stylesheet"  type="text/css" href="' . $a->get_baseurl() . '/addon/dav/wdcal/css/calendar.css' . '" media="all" />' . "\r\n";
-       $a->page['htmlhead'] .= '<link rel="stylesheet"  type="text/css" href="' . $a->get_baseurl() . '/addon/dav/wdcal/css/main.css' . '" media="all" />' . "\r\n";
-
-       switch (get_config("system", "language")) {
-               case "de":
-                       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/common/wdcal/js/wdCalendar_lang_DE.js"></script>' . "\r\n";
-                       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/jqueryui/jquery.ui.datepicker-de.js"></script>' . "\r\n";
-                       break;
-               default:
-                       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/common/wdcal/js/wdCalendar_lang_EN.js"></script>' . "\r\n";
-       }
-
-       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/common/wdcal/js/jquery.calendar.js"></script>' . "\r\n";
-       $a->page['htmlhead'] .= '<script type="text/javascript" src="' . $a->get_baseurl() . '/addon/dav/common/wdcal/js/main.js"></script>' . "\r\n";
-}
-
-
-
-/**
- * @param int $calendar_id
- */
-function wdcal_print_user_ics($calendar_id)
-{
-       $calendar_id = IntVal($calendar_id);
-
-       $a = get_app();
-       header("Content-type: text/plain");
-
-       $str  = "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Friendica//DAV-Plugin//EN\r\n";
-       $cals = q("SELECT * FROM %s%scalendars WHERE `id` = %d AND `namespace` = %d AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calendar_id, CALDAV_NAMESPACE_PRIVATE, $a->user["uid"]);
-       if (count($cals) > 0) {
-               $objs = q("SELECT * FROM %s%scalendarobjects WHERE `calendar_id` = %d ORDER BY `firstOccurence`", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calendar_id);
-
-               foreach ($objs as $obj) {
-                       preg_match("/BEGIN:VEVENT(.*)END:VEVENT/siu", $obj["calendardata"], $matches);
-                       $str2 = preg_replace("/([^\\r])\\n/siu", "\\1\r\n", $matches[0]);
-                       $str2 = preg_replace("/MAILTO:.*[^:a-z0-9_\+äöüß\\n\\n@-]+.*(:|\\r\\n[^ ])/siU", "\\1", $str2);
-                       $str .= $str2 . "\r\n";
-               }
-       }
-       $str .= "END:VCALENDAR\r\n";
-
-       echo $str;
-       killme();
-}
-
-
-/**
- * @param int $calendar_id
- * @return string
- */
-function wdcal_import_user_ics($calendar_id) {
-       $a = get_app();
-       $calendar_id = IntVal($calendar_id);
-       $o = "";
-
-       $server = dav_create_server(true, true, false);
-       $calendar = dav_get_current_user_calendar_by_id($server, $calendar_id, DAV_ACL_WRITE);
-       if (!$calendar) goaway($a->get_baseurl() . "/dav/wdcal/");
-
-       if (isset($_REQUEST["save"])) {
-               check_form_security_token_redirectOnErr('/dav/settings/', 'icsimport');
-
-               if ($_FILES["ics_file"]["tmp_name"] != "" && is_uploaded_file($_FILES["ics_file"]["tmp_name"])) try {
-                       $text = file_get_contents($_FILES["ics_file"]["tmp_name"]);
-
-                       /** @var Sabre_VObject_Component_VCalendar $vObject  */
-                       $vObject        = Sabre_VObject_Reader::read($text);
-                       $comp = $vObject->getComponents();
-                       $imported = array();
-                       foreach ($comp as $c) try {
-                               /** @var Sabre_VObject_Component_VEvent $c */
-                               $uid = $c->__get("UID")->value;
-                               if (!isset($imported[$uid])) $imported[$uid] = "";
-                               $imported[$uid] .= $c->serialize();
-                       } catch (Exception $e) {
-                               notice(t("Something went wrong when trying to import the file. Sorry. Maybe some events were imported anyway."));
-                       }
-
-                       if (isset($_REQUEST["overwrite"])) {
-                               $children = $calendar->getChildren();
-                               foreach ($children as $child) {
-                                       /** @var Sabre_CalDAV_CalendarObject $child */
-                                       $child->delete();
-                               }
-                               $i = 1;
-                       } else {
-                               $i = 0;
-                               $children = $calendar->getChildren();
-                               foreach ($children as $child) {
-                                       /** @var Sabre_CalDAV_CalendarObject $child */
-                                       $name = $child->getName();
-                                       if (preg_match("/import\-([0-9]+)\.ics/siu", $name, $matches)) {
-                                               if ($matches[1] > $i) $i = $matches[1];
-                                       };
-                               }
-                               $i++;
-                       }
-
-                       foreach ($imported as $object) try {
-
-                               $str = "BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Friendica//DAV-Plugin//EN\r\n";
-                               $str .= trim($object);
-                               $str .= "\r\nEND:VCALENDAR\r\n";
-
-                               $calendar->createFile("import-" . $i . ".ics", $str);
-                               $i++;
-                       } catch (Exception $e) {
-                               notice(t("Something went wrong when trying to import the file. Sorry."));
-                       }
-
-                       $o = t("The ICS-File has been imported.");
-               } catch (Exception $e) {
-                       notice(t("Something went wrong when trying to import the file. Sorry. Maybe some events were imported anyway."));
-               } else {
-                       notice(t("No file was uploaded."));
-               }
-       }
-
-
-       $o .= "<a href='" . $a->get_baseurl() . "/dav/wdcal/'>" . t("Go back to the calendar") . "</a><br><br>";
-
-       $num = q("SELECT COUNT(*) num FROM %s%scalendarobjects WHERE `calendar_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $calendar_id);
-
-       $o .= "<h2>" . t("Import a ICS-file") . "</h2>";
-       $o .= '<form method="POST" action="' . $a->get_baseurl() . '/dav/wdcal/' . $calendar_id . '/ics-import/" enctype="multipart/form-data">';
-       $o .= "<input type='hidden' name='form_security_token' value='" . get_form_security_token('icsimport') . "'>\n";
-       $o .= "<label for='ics_file'>" . t("ICS-File") . "</label><input type='file' name='ics_file' id='ics_file'><br>\n";
-       if ($num[0]["num"] > 0) $o .= "<label for='overwrite'>" . str_replace("#num#", $num[0]["num"], t("Overwrite all #num# existing events")) . "</label> <input name='overwrite' id='overwrite' type='checkbox'><br>\n";
-       $o .= "<input type='submit' name='save' value='" . t("Upload") . "'>";
-       $o .= '</form>';
-
-       return $o;
-}
-
-
-/**
- * @param array|Sabre_CalDAV_Calendar[] $calendars
- * @param array|int[] $calendars_selected
- * @param string $data_feed_url
- * @param string $view
- * @param int $theme
- * @param int $height_diff
- * @param bool $readonly
- * @param string $curr_day
- * @param array $add_params
- * @param bool $show_nav
- * @return string
- */
-function wdcal_printCalendar($calendars, $calendars_selected, $data_feed_url, $view = "week", $theme = 0, $height_diff = 175, $readonly = false, $curr_day = "", $add_params = array(), $show_nav = true)
-{
-
-       $a            = get_app();
-       $localization = wdcal_local::getInstanceByUser($a->user["uid"]);
-
-       if (count($calendars_selected) == 0) foreach ($calendars as $c) {
-               $prop                 = $c->getProperties(array("id"));
-               $calendars_selected[] = $prop["id"];
-       }
-
-       $opts = array(
-               "view"             => $view,
-               "theme"            => $theme,
-               "readonly"         => $readonly,
-               "height_diff"      => $height_diff,
-               "weekstartday"     => $localization->getFirstDayOfWeek(),
-               "data_feed_url"    => $data_feed_url,
-               "date_format_dm1"  => $localization->dateformat_js_dm1(),
-               "date_format_dm2"  => $localization->dateformat_js_dm2(),
-               "date_format_dm3"  => $localization->dateformat_js_dm3(),
-               "date_format_full" => $localization->dateformat_datepicker_js(),
-               "baseurl"          => $a->get_baseurl() . "/dav/wdcal/",
-       );
-
-       $x = '
-<script>
-       $(function() {
-               $("#animexxcalendar").animexxCalendar(' . json_encode($opts) . ');
-       });
-</script>
-
-<div id="animexxcalendar" class="animexxcalendar">
-       <div class="calselect"><strong>Available Calendars:</strong>';
-
-       foreach ($calendars as $cal) {
-               $cal_id = $cal->getProperties(array("id", DAV_DISPLAYNAME));
-               $x .= '<label style="margin-left: 10px; margin-right: 10px;"><input type="checkbox" name="cals[]" value="' . $cal_id["id"] . '"';
-               $found = false;
-               foreach ($calendars_selected as $pre) if ($pre["id"] == $cal_id["id"]) $found = true;
-               if ($found) $x .= ' checked';
-               $x .= '> ' . escape_tags($cal_id[DAV_DISPLAYNAME]) . '</label> ';
-       }
-
-       $x .= '</div>
-       <div class="calhead" style="padding-left:1px;padding-right:1px;">
-               <div class="ptogtitle loaderror" style="display: none;">Sorry, could not load your data, please try again later</div>
-       </div>';
-
-       if ($show_nav) {
-
-               $x .= '<div class="ctoolbar">
-               <div class="fbutton faddbtn" style="float: right;">
-                       <div><a href="' . $a->get_baseurl() . '/dav/settings/"><span>' . t("Settings") . ' / ' . t("Help") . '</span></a></div>
-               </div>
-               <div class="fbutton addcal">
-                       <div><a href="' . $a->get_baseurl() . '/dav/wdcal/new/" class="addcal">' . t("New event") . '</a></div>
-               </div>
-               <div class="btnseparator"></div>
-               <div class="fbutton showtodaybtn">
-                       <div><span class="showtoday">' . t("Today") . '</span></div>
-               </div>
-               <div class="btnseparator"></div>
-
-               <div class="fbutton showdaybtn">
-                       <div><span title="Day" class="showdayview ';
-
-               if ($view == "day") $x .= 'fcurrent';
-
-               $x .= '">' . t("Day") . '</span></div>
-               </div>
-               <div class="fbutton showweekbtn ';
-
-               if ($view == "week") $x .= "fcurrent";
-
-               $x .= '">
-                       <div><span title="Week" class="showweekview">' . t("Week") . '</span></div>
-               </div>
-               <div class="showmonthbtn fbutton ';
-
-               if ($view == "month") $x .= 'fcurrent';
-
-               $x .= '">
-                       <div><span title="Month" class="showmonthview">' . t("Month") . '</span></div>
-
-               </div>
-               <div class="btnseparator"></div>
-               <div class="fbutton showreflashbtn">
-                       <div><span class="showdayflash">' . t("Reload") . '</span></div>
-               </div>
-               <div class="btnseparator"></div>
-               <div title="' . t("Previous") . '"  class="fbutton sfprevbtn">
-                       <span class="fprev"></span>
-               </div>
-               <div title="' . t("Next") . '" class="fbutton sfnextbtn">
-                       <span class="fnext"></span>
-               </div>
-               <div class="fshowdatep fbutton" style="white-space: nowrap; position: relative;">
-                       <input name="txtshow" class="hdtxtshow" style="position: absolute; bottom: 0; left: 0; width: 0; height: 0; border: 0; padding: 0; margin: 0;">
-                       <span class="txtdatetimeshow">' . t("Date") . '</span>
-               </div>
-               <div style="float: right;">
-                       <div class="clear"></div>
-               </div>
-       </div>';
-       }
-       $x .= '
-       <div style="padding:1px;">
-               <div class="calmain printborder">
-                       <div class="gridcontainer" style="overflow-y: visible;"></div>
-               </div>
-       </div>
-</div>';
-
-       return $x;
-}
-
-
-/**
- * @param int $calendar_id
- * @param int $calendarobject_id
- * @return string
- */
-function wdcal_getDetailPage($calendar_id, $calendarobject_id)
-{
-       $a = get_app();
-
-       try {
-               $details = null;
-               $server  = dav_create_server(true, true, false);
-               $cal     = dav_get_current_user_calendar_by_id($server, $calendar_id, DAV_ACL_READ);
-               $obj     = Sabre_CalDAV_Backend_Common::loadCalendarobjectById($calendarobject_id);
-               dav_get_current_user_calendarobject($server, $cal, $obj["uri"], DAV_ACL_READ); // Check permissions
-
-               $calbackend = wdcal_calendar_factory_by_id($calendar_id);
-               $redirect   = $calbackend->getItemDetailRedirect($calendar_id, $calendarobject_id);
-
-               if ($redirect !== null) goaway($a->get_baseurl() . $redirect);
-
-               $details = $obj;
-       } catch (Exception $e) {
-               info(t("Error") . ": " . $e);
-               goaway($a->get_baseurl() . "/dav/wdcal/");
-       }
-
-       return print_r($details, true);
-}
-
-
-/**
- * @param int $calendar_id
- * @param int $uri
- * @return string
- */
-function wdcal_getEditPage($calendar_id, $uri)
-{
-       $a            = get_app();
-       $localization = wdcal_local::getInstanceByUser($a->user["uid"]);
-
-       return wdcal_getEditPage_str($localization, $a->get_baseurl(), $calendar_id, $uri);
-}
-
-/**
- * @return string
- */
-function wdcal_getNewPage()
-{
-       $a            = get_app();
-       $localization = wdcal_local::getInstanceByUser($a->user["uid"]);
-
-       return wdcal_getEditPage_str($localization, $a->get_baseurl(), 0, 0);
-}
-
-
-/**
- * @param App $a
- * @return string
- */
-function wdcal_getSettingsPage(&$a)
-{
-
-       if (!local_user()) {
-               notice(t('Permission denied.') . EOL);
-               return '';
-       }
-
-       if (isset($_REQUEST["save"])) {
-               check_form_security_token_redirectOnErr('/dav/settings/', 'calprop');
-               set_pconfig($a->user["uid"], "dav", "dateformat", $_REQUEST["wdcal_date_format"]);
-               info(t('The new values have been saved.'));
-       }
-
-       if (isset($_REQUEST["save_cals"])) {
-               check_form_security_token_redirectOnErr('/dav/settings/', 'calprop');
-
-               $r = q("SELECT * FROM %s%scalendars WHERE `namespace` = " . CALDAV_NAMESPACE_PRIVATE . " AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($a->user["uid"]));
-               foreach ($r as $cal) {
-                       $backend = wdcal_calendar_factory($cal["namespace"], $cal["namespace_id"], $cal["uri"], $cal);
-                       $change_sql = "";
-                       $col = substr($_REQUEST["color"][$cal["id"]], 1);
-                       if (strtolower($col) != strtolower($cal["calendarcolor"])) $change_sql .= ", `calendarcolor` = '" . dbesc($col) . "'";
-                       if (!is_subclass_of($backend, "Sabre_CalDAV_Backend_Virtual")) {
-                               if ($_REQUEST["uri"][$cal["id"]] != $cal["uri"]) $change_sql .= ", `uri` = '" . dbesc($_REQUEST["uri"][$cal["id"]]) . "'";
-                               if ($_REQUEST["name"][$cal["id"]] != $cal["displayname"]) $change_sql .= ", `displayname` = '" . dbesc($_REQUEST["name"][$cal["id"]]) . "'";
-                       }
-                       if ($change_sql != "") {
-                               q("UPDATE %s%scalendars SET `ctag` = `ctag` + 1 $change_sql WHERE `id` = %d AND `namespace_id` = %d AND `namespace_id` = %d",
-                                       CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $cal["id"], CALDAV_NAMESPACE_PRIVATE, IntVal($a->user["uid"]));
-                               info(t('The calendar has been updated.'));
-                       }
-               }
-
-               if (isset($_REQUEST["uri"]["new"]) && $_REQUEST["uri"]["new"] != "" && $_REQUEST["name"]["new"] && $_REQUEST["name"]["new"] != "") {
-                       $order = q("SELECT MAX(`calendarorder`) ord FROM %s%scalendars WHERE `namespace_id` = %d AND `namespace_id` = %d",
-                               CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CALDAV_NAMESPACE_PRIVATE, IntVal($a->user["uid"]));
-                       $neworder = $order[0]["ord"] + 1;
-                       q("INSERT INTO %s%scalendars (`namespace`, `namespace_id`, `calendarorder`, `calendarcolor`, `displayname`, `timezone`, `uri`, `has_vevent`, `ctag`)
-                               VALUES (%d, %d, %d, '%s', '%s', '%s', '%s', 1, 1)",
-                               CALDAV_SQL_DB, CALDAV_SQL_PREFIX, CALDAV_NAMESPACE_PRIVATE, IntVal($a->user["uid"]), $neworder, dbesc(strtolower(substr($_REQUEST["color"]["new"], 1))),
-                               dbesc($_REQUEST["name"]["new"]), dbesc($a->timezone), dbesc($_REQUEST["uri"]["new"])
-                       );
-                       info(t('The new calendar has been created.'));
-               }
-       }
-
-       if (isset($_REQUEST["remove_cal"])) {
-               check_form_security_token_redirectOnErr('/dav/settings/', 'del_cal', 't');
-
-               $c = q("SELECT * FROM %s%scalendars WHERE `id` = %d AND `namespace_id` = %d AND `namespace_id` = %d",
-                       CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($_REQUEST["remove_cal"]), CALDAV_NAMESPACE_PRIVATE, IntVal($a->user["uid"]));
-               if (count($c) != 1) killme();
-
-               $calobjs = q("SELECT `id` FROM %s%scalendarobjects WHERE `calendar_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($_REQUEST["remove_cal"]));
-
-               $newcal = q("SELECT * FROM %s%scalendars WHERE `id` != %d AND `namespace_id` = %d AND `namespace_id` = %d ORDER BY `calendarcolor` LIMIT 0,1",
-                       CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($_REQUEST["remove_cal"]), CALDAV_NAMESPACE_PRIVATE, IntVal($a->user["uid"]));
-               if (count($newcal) != 1) killme();
-
-               q("UPDATE %s%scalendarobjects SET `calendar_id` = %d WHERE `calendar_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($newcal[0]["id"]), IntVal($c[0]["id"]));
-
-               foreach ($calobjs as $calobj) renderCalDavEntry_calobj_id($calobj["id"]);
-
-               q("DELETE FROM %s%scalendars WHERE `id` = %s", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($_REQUEST["remove_cal"]));
-               q("UPDATE %s%scalendars SET `ctag` = `ctag` + 1 WHERE `id` = " . CALDAV_SQL_DB, CALDAV_SQL_PREFIX, $newcal[0]["id"]);
-
-               info(t('The calendar has been deleted.'));
-       }
-
-       $o = "";
-
-       $o .= "<a href='" . $a->get_baseurl() . "/dav/wdcal/'>" . t("Go back to the calendar") . "</a><br><br>";
-
-       $o .= '<h3>' . t('Calendar Settings') . '</h3>';
-
-       $current_format = wdcal_local::getInstanceByUser($a->user["uid"]);
-       $o .= '<form method="POST" action="' . $a->get_baseurl() . '/dav/settings/">';
-       $o .= "<input type='hidden' name='form_security_token' value='" . get_form_security_token('calprop') . "'>\n";
-
-       $o .= '<label for="wdcal_date_format">' . t('Date format') . ':</label><select name="wdcal_date_format" id="wdcal_date_format" size="1">';
-       $classes = wdcal_local::getInstanceClasses();
-       foreach ($classes as $c) {
-               $o .= '<option value="' . $c::getID() . '" ';
-               if ($c::getID() == $current_format::getID()) $o .= 'selected';
-               $o .= '>' . escape_tags($c::getName()) . '</option>';
-       }
-       $o .= '</select><br>';
-
-       $o .= '<label for="wdcal_time_zone">' . t('Time zone') . ':</label><input id="wdcal_time_zone" value="' . $a->timezone . '" disabled><br>';
-
-       $o .= '<input type="submit" name="save" value="' . t('Save') . '">';
-       $o .= '</form>';
-
-
-       $o .= '<br><br><h3>' . t('Calendars') . '</h3>';
-       $o .= '<form method="POST" action="' . $a->get_baseurl() . '/dav/settings/">';
-       $o .= "<input type='hidden' name='form_security_token' value='" . get_form_security_token('calprop') . "'>\n";
-       $o .= "<table><tr><th>Type</th><th>Color</th><th>Name</th><th>URI (for CalDAV)</th><th>ICS</th></tr>";
-
-       $r = q("SELECT * FROM %s%scalendars WHERE `namespace` = " . CALDAV_NAMESPACE_PRIVATE . " AND `namespace_id` = %d", CALDAV_SQL_DB, CALDAV_SQL_PREFIX, IntVal($a->user["uid"]));
-       $private_max = 0;
-       $num_non_virtual = 0;
-       foreach ($r as $x) {
-               $backend = wdcal_calendar_factory($x["namespace"], $x["namespace_id"], $x["uri"], $x);
-               if (!is_subclass_of($backend, "Sabre_CalDAV_Backend_Virtual")) $num_non_virtual++;
-       }
-       foreach ($r as $x) {
-               $p = explode("private-", $x["uri"]);
-               if (count($p) == 2 && $p[1] > $private_max) $private_max = $p[1];
-
-               $backend = wdcal_calendar_factory($x["namespace"], $x["namespace_id"], $x["uri"], $x);
-               $disabled = (is_subclass_of($backend, "Sabre_CalDAV_Backend_Virtual") ? "disabled" : "");
-               $o .= "<tr>";
-               $o .= "<td style='padding: 2px;'>" . escape_tags($backend->getBackendTypeName()) . "</td>";
-               $o .= "<td style='padding: 2px; text-align: center;'><input style='margin-left: 10px; width: 70px;' class='cal_color' name='color[" . $x["id"] . "]' id='cal_color_" . $x["id"] . "' value='#" . (strlen($x["calendarcolor"]) != 6 ? "5858ff" : escape_tags($x["calendarcolor"])) . "'></td>";
-               $o .= "<td style='padding: 2px;'><input style='margin-left: 10px;' name='name[" . $x["id"] . "]' value='" . escape_tags($x["displayname"]) . "' $disabled></td>";
-               $o .= "<td style='padding: 2px;'><input style='margin-left: 10px; width: 150px;' name='uri[" . $x["id"] . "]' value='" . escape_tags($x["uri"]) . "' $disabled></td>";
-               $o .= "<td style='padding: 2px;'><a href='" . $a->get_baseurl() . "/dav/wdcal/" . $x["id"] . "/ics-export/'>Export</a>";
-               if (!is_subclass_of($backend, "Sabre_CalDAV_Backend_Virtual") && $num_non_virtual > 1) $o .= " / <a href='" . $a->get_baseurl() . "/dav/wdcal/" . $x["id"] . "/ics-import/'>Import</a>";
-               $o .= "</td>";
-               $o .= "<td style='padding: 2px; padding-left: 50px;'>";
-               if (!is_subclass_of($backend, "Sabre_CalDAV_Backend_Virtual") && $num_non_virtual > 1) $o .= "<a href='" . $a->get_baseurl() . "/dav/settings/?remove_cal=" . $x["id"] . "&amp;t=" . get_form_security_token("del_cal") . "' class='delete_cal'>Delete</a>";
-               $o .= "</td>\n";
-               $o .= "</tr>\n";
-       }
-
-       $private_max++;
-       $o .= "<tr class='cal_add_row' style='display: none;'>";
-       $o .= "<td style='padding: 2px;'>" . escape_tags(Sabre_CalDAV_Backend_Private::getBackendTypeName()) . "</td>";
-       $o .= "<td style='padding: 2px; text-align: center;'><input style='margin-left: 10px; width: 70px;' class='cal_color' name='color[new]' id='cal_color_new' value='#5858ff'></td>";
-       $o .= "<td style='padding: 2px;'><input style='margin-left: 10px;' name='name[new]' value='Another calendar'></td>";
-       $o .= "<td style='padding: 2px;'><input style='margin-left: 10px; width: 150px;' name='uri[new]' value='private-${private_max}'></td>";
-       $o .= "<td></td><td></td>";
-       $o .= "</tr>\n";
-
-       $o .= "</table>";
-       $o .= "<div style='text-align: center;'>[<a href='#' class='calendar_add_caller'>" . t("Create a new calendar") . "</a>]</div>";
-       $o .= '<input type="submit" name="save_cals" value="' . t('Save') . '">';
-       $o .= '</form>';
-       $baseurl = $a->get_baseurl();
-       $o .= "<script>\$(function() {
-               wdcal_edit_calendars_start('" . $current_format->dateformat_datepicker_js() . "', '${baseurl}/dav/');
-       });</script>";
-
-
-       $o .= "<br><h3>" . t("Limitations") . "</h3>";
-
-       $o .= "- The native friendica events are embedded as read-only, half-transparent in the calendar.<br>";
-
-       $o .= "<br><h3>" . t("Warning") . "</h3>";
-
-       $o .= "This plugin still is in a very early stage of development. Expect major bugs!<br>";
-
-       $o .= "<br><h3>" . t("Synchronization (iPhone, Thunderbird Lightning, Android, ...)") . "</h3>";
-
-       $o .= 'This plugin enables synchronization of your dates and contacts with CalDAV- and CardDAV-enabled programs or devices.<br>
-               As an example, the instructions how to set up two-way synchronization with an iPhone/iPodTouch are provided below.<br>
-               Unfortunately, Android does not have native support for CalDAV or CardDAV, so an app has to be installed.<br>
-               On desktops, the Lightning-extension to Mozilla Thunderbird should be able to use this plugin as a backend.<br><br>';
-
-       $o .= '<h4>' . t('Synchronizing this calendar with the iPhone') . '</h4>';
-
-       $o .= "<ul>
-       <li>Go to the settings</li>
-       <li>Mail, contacts, settings</li>
-       <li>Add a new account</li>
-       <li>Other...</li>
-       <li>Calendar -> CalDAV-Account</li>
-       <li><b>Server:</b> " . $a->get_baseurl() . "/dav/ / <b>Username/Password:</b> <em>the same as your friendica-login</em></li>
-       </ul>";
-
-       $o .= '<h4>' . t('Synchronizing your Friendica-Contacts with the iPhone') . '</h4>';
-
-       $o .= "<ul>
-       <li>Go to the settings</li>
-       <li>Mail, contacts, settings</li>
-       <li>Add a new account</li>
-       <li>Other...</li>
-       <li>Contacts -> CardDAV-Account</li>
-       <li><b>Server:</b> " . $a->get_baseurl() . "/dav/ / <b>Username/Password:</b> <em>the same as your friendica-login</em></li>
-       </ul>";
-
-       return $o;
-}
-
diff --git a/dav/main.php b/dav/main.php
deleted file mode 100644 (file)
index c36d008..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-<?php
-
-require_once('include/security.php');
-
-function dav_install()
-{
-       register_hook('event_created', 'addon/dav/dav.php', 'dav_event_created_hook');
-       register_hook('event_updated', 'addon/dav/dav.php', 'dav_event_updated_hook');
-       register_hook('profile_tabs', 'addon/dav/dav.php', 'dav_profile_tabs_hook');
-       register_hook('cron', 'addon/dav/dav.php', 'dav_cron');
-}
-
-
-function dav_uninstall()
-{
-       unregister_hook('event_created', 'addon/dav/dav.php', 'dav_event_created_hook');
-       unregister_hook('event_updated', 'addon/dav/dav.php', 'dav_event_updated_hook');
-       unregister_hook('profile_tabs', 'addon/dav/dav.php', 'dav_profile_tabs_hook');
-       unregister_hook('cron', 'addon/dav/dav.php', 'dav_cron');
-}
-
-
-function dav_module()
-{
-}
-
-function dav_include_files()
-{
-       require_once (__DIR__ . "/SabreDAV/lib/Sabre/autoload.php");
-
-       require_once (__DIR__ . "/common/calendar.fnk.php");
-       require_once (__DIR__ . "/common/calendar_rendering.fnk.php");
-
-       require_once (__DIR__ . "/common/dav_caldav_backend_common.inc.php");
-       require_once (__DIR__ . "/common/dav_caldav_backend_private.inc.php");
-       require_once (__DIR__ . "/common/dav_caldav_backend_virtual.inc.php");
-       require_once (__DIR__ . "/common/dav_caldav_root.inc.php");
-       require_once (__DIR__ . "/common/dav_user_calendars.inc.php");
-       require_once (__DIR__ . "/common/dav_caldav_calendar_virtual.inc.php");
-       require_once (__DIR__ . "/common/dav_caldav_calendar_private.inc.php");
-
-       require_once (__DIR__ . "/common/dav_carddav_root.inc.php");
-       require_once (__DIR__ . "/common/dav_carddav_backend_common.inc.php");
-       require_once (__DIR__ . "/common/dav_carddav_backend_virtual.inc.php");
-       require_once (__DIR__ . "/common/dav_carddav_backend_private.inc.php");
-       require_once (__DIR__ . "/common/dav_user_addressbooks.inc.php");
-
-       require_once (__DIR__ . "/common/wdcal_configuration.php");
-       require_once (__DIR__ . "/common/wdcal_backend.inc.php");
-
-       require_once (__DIR__ . "/dav_friendica_principal.inc.php");
-       require_once (__DIR__ . "/dav_friendica_auth.inc.php");
-       require_once (__DIR__ . "/dav_carddav_backend_virtual_friendica.inc.php");
-       require_once (__DIR__ . "/dav_caldav_backend_virtual_friendica.inc.php");
-       require_once (__DIR__ . "/FriendicaACLPlugin.inc.php");
-
-       require_once (__DIR__ . "/common/wdcal_edit.inc.php");
-       require_once (__DIR__ . "/calendar.friendica.fnk.php");
-       require_once (__DIR__ . "/layout.fnk.php");
-}
-
-
-/**
- * @param App $a
- */
-function dav_init(&$a)
-{
-
-       /*
-        * Recommended settings:
-        * ALTER TABLE `photo` ADD INDEX ( `contact-id` )
-        */
-
-       ini_set("display_errors", 1);
-       error_reporting(E_ALL);
-
-       dav_include_files();
-
-       if (false) {
-               dbg(true);
-               error_reporting(E_ALL);
-               ini_set("display_errors", 1);
-       }
-
-       wdcal_create_std_calendars();
-       wdcal_create_std_addressbooks();
-       wdcal_addRequiredHeaders();
-
-       if ($a->argc >= 2 && $a->argv[1] == "wdcal") {
-
-               if ($a->argc >= 3 && $a->argv[2] == "feed") {
-                       wdcal_print_feed($a->get_baseurl() . "/dav/wdcal/");
-                       killme();
-               }
-               return;
-       }
-       if ($a->argc >= 2 && $a->argv[1] == "getExceptionDates") {
-               echo wdcal_getEditPage_exception_selector();
-               killme();
-       }
-
-       if ($a->argc >= 2 && $a->argv[1] == "settings") {
-               return;
-       }
-
-
-       if (isset($_REQUEST["test"])) {
-               renderAllCalDavEntries();
-       }
-
-
-       $server  = dav_create_server();
-
-       $browser = new Sabre_DAV_Browser_Plugin();
-       $server->addPlugin($browser);
-
-       $server->exec();
-
-       killme();
-}
-
-/**
- * @return string
- */
-function dav_content()
-{
-       $a = get_app();
-       if (!isset($a->user["uid"]) || $a->user["uid"] == 0) {
-               return login();
-       }
-
-       $x = "";
-       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 {
-                                       $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);
-                       }
-               }
-       } 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;
-}
-
-
-/**
- * @param App $a
- * @param object $b
- */
-function dav_event_created_hook(&$a, &$b)
-{
-       dav_include_files();
-       // @TODO Updating the cache instead of completely invalidating and rebuilding it
-       Sabre_CalDAV_Backend_Friendica::invalidateCache($a->user["uid"], CALDAV_FRIENDICA_CONTACTS);
-       Sabre_CalDAV_Backend_Friendica::invalidateCache($a->user["uid"], CALDAV_FRIENDICA_MINE);
-}
-
-/**
- * @param App $a
- * @param object $b
- */
-function dav_event_updated_hook(&$a, &$b)
-{
-       dav_include_files();
-       // @TODO Updating the cache instead of completely invalidating and rebuilding it
-       Sabre_CalDAV_Backend_Friendica::invalidateCache($a->user["uid"], CALDAV_FRIENDICA_CONTACTS);
-       Sabre_CalDAV_Backend_Friendica::invalidateCache($a->user["uid"], CALDAV_FRIENDICA_MINE);
-}
-
-/**
- * @param App $a
- * @param object $b
- */
-function dav_profile_tabs_hook(&$a, &$b)
-{
-       $b["tabs"][] = array(
-               "label" => t('Calendar'),
-               "url"   => $a->get_baseurl() . "/dav/wdcal/",
-               "sel"   => "",
-               "title" => t('Extended calendar with CalDAV-support'),
-       );
-}
-
-
-/**
- * @param App $a
- * @param object $b
- */
-function dav_cron(&$a, &$b)
-{
-       dav_include_files();
-
-       $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();
-               if (count($calendar) != 1 || count($event) == 0) continue;
-               switch ($calendar[0]["namespace"]) {
-                       case CALDAV_NAMESPACE_PRIVATE:
-                               $user = q("SELECT * FROM user WHERE `uid` = %d AND `blocked` = 0", $calendar[0]["namespace_id"]);
-                               if (count($user) != 1) continue;
-                               $users[] = $user[0];
-                               break;
-               }
-               switch ($not["action"]) {
-                       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"] . "/");
-                                       $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%!<br>\n<br>\nThe event \"%event%\" is about to begin:<br>\n<a href='" . "%url%" . "'>%url%</a>");
-                                       $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');
-                                       enotify::send($params);
-                               }
-                               break;
-               }
-       }
-}
-
-
-/**
- * @param App $a
- * @param null|object $o
- */
-function dav_plugin_admin_post(&$a = null, &$o = null)
-{
-       check_form_security_token_redirectOnErr('/admin/plugins/dav', 'dav_admin_save');
-
-       dav_include_files();
-       require_once(__DIR__ . "/database-init.inc.php");
-
-       if (isset($_REQUEST["install"])) {
-               $errs = dav_create_tables();
-               if (count($errs) == 0) info(t('The database tables have been installed.') . EOL);
-               else notice(t("An error occurred during the installation.") . EOL);
-       }
-       if (isset($_REQUEST["upgrade"])) {
-               $errs = dav_upgrade_tables();
-               if (count($errs) == 0) {
-                       renderAllCalDavEntries();
-                       info(t('The database tables have been updated.') . EOL);
-               }
-               else notice(t("An error occurred during the update.") . EOL);
-       }
-}
-
-/**
- * @param App $a
- * @param string $o
- */
-function dav_plugin_admin(&$a, &$o)
-{
-       dav_include_files();
-       require_once(__DIR__ . "/database-init.inc.php");
-
-       $dbstatus = dav_check_tables();
-
-       $o = '<input type="hidden" name="form_security_token" value="' . get_form_security_token("dav_admin_save") . '">';
-       $o .= '<i>' . t("No system-wide settings yet.") . '</i><br><br>';
-
-
-       $o .= '<h3>' . t('Database status') . '</h3>';
-       switch ($dbstatus) {
-               case 0:
-                       $o .= t('Installed');
-                       break;
-               case 1:
-                       $o .= "<strong>" . t('Upgrade needed') . "</strong><br>" . t("Please back up all calendar data (the tables beginning with dav_*) before proceeding. While all calendar events <i>should</i> 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.") . "<br><br><input type='submit' name='upgrade' value='" . t('Upgrade') . "'>";
-                       break;
-               case -1:
-                       $o .= t('Not installed') . "<br><br><input type='submit' name='install' value='" . t('Install') . "'>";
-                       break;
-               case -2:
-               default:
-                       $o .= t('Unknown') . "<br><br>" . 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 .= "<br><br>";
-
-       $o .= "<h3>" . t("Troubleshooting") . "</h3>";
-       $o .= "<h4>" . t("Manual creation of the database tables:") . "</h4>";
-       $o .= "<a href='#' onClick='\$(\"#sqlstatements\").show(); return false;'>" . t("Show SQL-statements") . "</a><blockquote style='display: none;' id='sqlstatements'><pre>";
-       switch ($dbstatus) {
-               case 1:
-                       $tables = dav_get_update_statements(1);
-                       foreach ($tables as $t) $o .= escape_tags($t . ";\n\n");
-                       break;
-               default:
-                       $tables = dav_get_create_statements();
-                       foreach ($tables as $t) $o .= escape_tags($t . ";\n\n");
-                       break;
-       }
-       $o .= "</pre></blockquote>";
-}
diff --git a/dav/wdcal.css b/dav/wdcal.css
deleted file mode 100644 (file)
index 18c25c5..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-
-div.colorPicker-picker { display: inline-block; }
-.colorPicker-palette { font-size: 12px; }
-.animexxcalendar label, .colorPicker-palette label { background: none; border: none; padding: 0; margin: 0; box-shadow: none; display: inline; font-size: 14px; }
-.animexxcalendar input, .colorPicker-palette input { font-size: 14px; }
-
-
-.ui-datepicker { width: 200px; }
-.ui-datepicker * { font-size: 12px; line-height: 12px; }
-.ui-datepicker th { padding: 10px 2px; }
-.ui-datepicker select.ui-datepicker-year { min-width: 0; width: 50px !important; }
-#cal_start_time, #cal_end_time { width: 5em; margin-left: 1em; }
-#cal_start_date, #cal_end_date { width: 6em;}
-
-
-label.block {
-       background: none repeat scroll 0 0 #CCCCCC;
-       border: 1px solid #EEEEEC;
-       box-shadow: 3px 3px 5px 0 #111111;
-       color: #111111;
-       display: inline-block;
-       font-size: small;
-       margin: 0 10px 1em 0;
-       padding: 3px 5px;
-       width: 38%;
-       vertical-align: top;
-}
-
-label.plain {
-       background: none;
-       border: none;
-       box-shadow: none;
-       color: black;
-       display: inline;
-       margin: 0;
-       padding: 0;
-}
-
-.rec_exceptions { display: inline-block; }
-.rec_exceptions_holder { display: inline-block; }
-.rec_exceptions .remover { }
-#rec_until_count { width: 50px; }
-#rec_until_date { width: 100px; }
\ No newline at end of file