From 99f904adcc37d93c90defcd8ce898598e25be212 Mon Sep 17 00:00:00 2001 From: Hugues Hiegel Date: Wed, 11 Mar 2015 16:55:04 +0100 Subject: Lot of plugins --- libgpl/caldav/caldav_sync.php | 284 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 libgpl/caldav/caldav_sync.php (limited to 'libgpl/caldav/caldav_sync.php') diff --git a/libgpl/caldav/caldav_sync.php b/libgpl/caldav/caldav_sync.php new file mode 100644 index 0000000..0266af4 --- /dev/null +++ b/libgpl/caldav/caldav_sync.php @@ -0,0 +1,284 @@ + + * + * Copyright (C) 2013, Awesome IT GbR + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +require_once (dirname(__FILE__) . '/caldav-client.php'); + +class caldav_sync +{ + const ACTION_NONE = 1; + const ACTION_UPDATE = 2; + const ACTION_CREATE = 4; + + private $cal_id = null; + private $ctag = null; + private $user = null; + private $pass = null; + private $url = null; + private $env; + + public $sync = 0; + + /** + * Default constructor for calendar synchronization adapter. + * + * @param int Calendar id. + * @param array Hash array with caldav properties: + * url: Caldav calendar URL. + * user: Caldav http basic auth user. + * pass: Password für caldav user. + * ctag: Caldav ctag for calendar. + * @param boolean verify SSL Cert // Mod by Rosali (https://gitlab.awesome-it.de/kolab/roundcube-plugins/issues/1) + */ + public function __construct($cal_id, $props, $verifySSL, $env) + { + $this->env = $env; + $this->cal_id = $cal_id; + + $this->url = $props["url"]; + $this->ctag = isset($props["tag"]) ? $props["tag"] : null; + $this->user = isset($props["user"]) ? $props["user"] : null; + $this->pass = isset($props["pass"]) ? $props["pass"] : null; + $this->sync = isset($props["sync"]) ? $props["sync"] : 0; + + $this->caldav = new caldav_client($this->url, $this->user, $this->pass, $verifySSL); // Mod by Rosali (https://gitlab.awesome-it.de/kolab/roundcube-plugins/issues/1) + } + + /** + * Getter for current calendar ctag. + * @return string + */ + public function get_ctag() + { + return $this->ctag; + } + + /** + * Determines whether current calendar needs to be synced + * regarding the CalDAV ctag. + * + * @return True if the current calendar ctag differs from the CalDAV tag which + * indicates that there are changes that must be synched. Returns false + * if the calendar is up to date, no sync necesarry. + */ + public function is_synced($force = false) + { + $is_synced = $this->ctag == $this->caldav->get_ctag() && $this->ctag; + $env = $this->env; + $env::debug_log("Ctag indicates that calendar \"$this->cal_id\" ".($is_synced ? "is synced." : "needs update!")); + + return $is_synced; + } + + /** + * Synchronizes given events with caldav server and returns updates. + * + * @param array List of local events. + * @param array List of caldav properties for each event. + * @return array Tuple containing the following lists: + * + * Caldav properties for events to be created or to be updated with the keys: + * url: Event ical URL relative to calendar URL + * etag: Remote etag of the event + * local_event: The local event in case of an update. + * remote_event: The current event retrieved from caldav server. + * + * A list of event ids that are in sync. + */ + public function get_updates($events, $caldav_props) + { + $ctag = $this->caldav->get_ctag(); + + if($ctag) + { + $this->ctag = $ctag; + $etags = $this->caldav->get_etags(); + list($updates, $synced_event_ids) = $this->_get_event_updates($events, $caldav_props, $etags); + return array($this->_get_event_data($updates), $synced_event_ids); + } + else + { + $env = $this->env; + $env::debug_log("Unkown error while fetching calendar ctag for calendar \"$this->cal_id\"!"); + } + + return null; + } + + /** + * Determines sync status and requried updates for the given events using given list of etags. + * + * @param array List of local events. + * @param array List of caldav properties for each event. + * @param array List of current remote etags. + * @return array Tuple containing the following lists: + * + * Caldav properties for events to be created or to be updated with the keys: + * url: Event ical URL relative to calendar URL + * etag: Remote etag of the event + * local_event: The local event in case of an update. + * + * A list of event ids that are in sync. + */ + private function _get_event_updates($events, $caldav_props, $etags) + { + $updates = array(); + $in_sync = array(); + + foreach ($etags as $etag) + { + $url = $etag["url"]; + $etag = $etag["etag"]; + $event_found = false; + for($i = 0; $i < sizeof($events); $i ++) + { + if ($caldav_props[$i]["url"] == $url) + { + $event_found = true; + + if ($caldav_props[$i]["tag"] != $etag) + { + $env = $this->env; + $env::debug_log("Event ".$events[$i]["uid"]." needs update."); + + array_push($updates, array( + "local_event" => $events[$i], + "etag" => $etag, + "url" => $url + )); + } + else + { + array_push($in_sync, $events[$i]["id"]); + } + } + } + + if (!$event_found) + { + $env = $this->env; + $env::debug_log("Found new event ".$url); + + array_push($updates, array( + "url" => $url, + "etag" => $etag + )); + } + } + + return array($updates, $in_sync); + } + + /** + * Fetches event data and attaches it to the given update properties. + * + * @param $updates List of update properties. + * @return array List of update properties with additional key "remote_event" containing the current caldav event. + */ + private function _get_event_data($updates) + { + $urls = array(); + + foreach ($updates as $update) + { + array_push($urls, $update["url"]); + } + + $events = $this->caldav->get_events($urls); + + foreach($updates as &$update) + { + // Attach remote events to the appropriate updates. + // Note that this assumes unique event URL's! + $url = $update["url"]; + if($events[$url]) { + $update["remote_event"] = $events[$url]; + $update["remote_event"]["calendar"] = $this->cal_id; + } + } + + return $updates; + } + + /** + * Creates the given event on the caldav server. + * + * @param array Hash array with event properties. + * @return Caldav properties with created URL on success, false on error. + */ + public function create_event($event) + { + $props = array( + "url" => parse_url($this->url, PHP_URL_PATH)."/".$event["uid"].".ics", + "tag" => null + ); + + $env = $this->env; + $env::debug_log("Push new event to url ".$props["url"]); + $result = $this->caldav->put_event($props["url"], $event); + + if($result == false || $result < 0) return false; + return $props; + } + + /** + * Updates the given event on the caldav server. + * + * @param array Hash array with event properties to update. + * @param array Hash array with caldav properties "url" and "tag" for the event. + * @return True on success, false on error, -1 if the given event/etag is not up to date. + */ + public function update_event($event, $props) + { + $env = $this->env; + $env::debug_log("Updating event uid \"".$event["uid"]."\"."); + return $this->caldav->put_event($props["url"], $event, $props["tag"]); + } + + /** + * Removes the given event from the caldav server. + * + * @param array Hash array with caldav properties "url" and "tag" for the event. + * @return True on success, false on error. + */ + public function remove_event($props) + { + $env = $this->env; + $env::debug_log("Removing event url \"".$props["url"]."\"."); + return $this->caldav->remove_event($props["url"]); + } + + /** + * Freebusy request for a given user. + * + * @param string username + * @param string relative path to caldav base uri + * @param integer unix timestamp + * @param integer unix timestamp + * @retrun array List of busy timeslots within the requested range + */ + public function freebusy($user, $path, $start, $end) + { + return $this->caldav->freebusy($user, $path, $start, $end); + } +}; +?> \ No newline at end of file -- cgit v1.2.3