]> git.mxchange.org Git - friendica-addons.git/blob - dav/common/calendar.fnk.php
Heavily refactored, including multiple calendars per user and recurring events. Not...
[friendica-addons.git] / dav / common / calendar.fnk.php
1 <?php
2
3
4 define("DAV_ACL_READ", "{DAV:}read");
5 define("DAV_ACL_WRITE", "{DAV:}write");
6 define("DAV_DISPLAYNAME", "{DAV:}displayname");
7
8
9 class vcard_source_data_email
10 {
11         public $email, $type;
12
13         function __construct($type, $email)
14         {
15                 $this->email = $email;
16                 $this->type  = $type;
17         }
18 }
19
20 class vcard_source_data_homepage
21 {
22         public $homepage, $type;
23
24         function __construct($type, $homepage)
25         {
26                 $this->homepage = $homepage;
27                 $this->type     = $type;
28         }
29 }
30
31 class vcard_source_data_telephone
32 {
33         public $telephone, $type;
34
35         function __construct($type, $telephone)
36         {
37                 $this->telephone = $telephone;
38                 $this->type      = $type;
39         }
40 }
41
42 class vcard_source_data_socialnetwork
43 {
44         public $nick, $type, $url;
45
46         function __construct($type, $nick, $url)
47         {
48                 $this->nick = $nick;
49                 $this->type = $type;
50                 $this->url  = $url;
51         }
52 }
53
54 class vcard_source_data_address
55 {
56         public $street, $street2, $zip, $city, $country, $type;
57 }
58
59 class vcard_source_data_photo
60 {
61         public $binarydata;
62         public $width, $height;
63         public $type;
64 }
65
66 class vcard_source_data
67 {
68         function __construct($name_first, $name_middle, $name_last)
69         {
70                 $this->name_first  = $name_first;
71                 $this->name_middle = $name_middle;
72                 $this->name_last   = $name_last;
73         }
74
75         public $name_first, $name_middle, $name_last;
76         public $last_update;
77         public $picture_data;
78
79         /** @var array|vcard_source_data_telephone[] $telephones */
80         public $telephones;
81
82         /** @var array|vcard_source_data_homepage[] $homepages */
83         public $homepages;
84
85         /** @var array|vcard_source_data_socialnetwork[] $socialnetworks */
86         public $socialnetworks;
87
88         /** @var array|vcard_source_data_email[] $email */
89         public $emails;
90
91         /** @var array|vcard_source_data_address[] $addresses */
92         public $addresses;
93
94         /** @var vcard_source_data_photo */
95         public $photo;
96 }
97
98 ;
99
100
101 /**
102  * @param vcard_source_data $vcardsource
103  * @return string
104  */
105 function vcard_source_compile($vcardsource)
106 {
107         $str = "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Friendica//DAV-Plugin//EN\r\n";
108         $str .= "N:" . str_replace(";", ",", $vcardsource->name_last) . ";" . str_replace(";", ",", $vcardsource->name_first) . ";" . str_replace(";", ",", $vcardsource->name_middle) . ";;\r\n";
109         $str .= "FN:" . str_replace(";", ",", $vcardsource->name_first) . " " . str_replace(";", ",", $vcardsource->name_middle) . " " . str_replace(";", ",", $vcardsource->name_last) . "\r\n";
110         $str .= "REV:" . str_replace(" ", "T", $vcardsource->last_update) . "Z\r\n";
111
112         $item_count = 0;
113         for ($i = 0; $i < count($vcardsource->homepages); $i++) {
114                 if ($i == 0) $str .= "URL;type=" . $vcardsource->homepages[0]->type . ":" . $vcardsource->homepages[0]->homepage . "\r\n";
115                 else {
116                         $c = ++$item_count;
117                         $str .= "item$c.URL;type=" . $vcardsource->homepages[0]->type . ":" . $vcardsource->homepages[0]->homepage . "\r\n";
118                         $str .= "item$c.X-ABLabel:_\$!<HomePage>!\$_\r\n";
119                 }
120         }
121
122         if (is_object($vcardsource->photo)) {
123                 $data = base64_encode($vcardsource->photo->binarydata);
124                 $str .= "PHOTO;ENCODING=BASE64;TYPE=" . $vcardsource->photo->type . ":" . $data . "\r\n";
125         }
126
127         if (isset($vcardsource->socialnetworks) && is_array($vcardsource->socialnetworks)) foreach ($vcardsource->socialnetworks as $netw) switch ($netw->type) {
128                 case "dfrn":
129                         $str .= "X-SOCIALPROFILE;type=dfrn;x-user=" . $netw->nick . ":" . $netw->url . "\r\n";
130                         break;
131                 case "facebook":
132                         $str .= "X-SOCIALPROFILE;type=facebook;x-user=" . $netw->nick . ":" . $netw->url . "\r\n";
133                         break;
134                 case "twitter":
135                         $str .= "X-SOCIALPROFILE;type=twitter;x-user=" . $netw->nick . ":" . $netw->url . "\r\n";
136                         break;
137         }
138
139         $str .= "END:VCARD\r\n";
140         return $str;
141 }
142
143
144 /**
145  * @param int $phpDate (UTC)
146  * @return string (Lokalzeit)
147  */
148 function wdcal_php2MySqlTime($phpDate)
149 {
150         return date("Y-m-d H:i:s", $phpDate);
151 }
152
153 /**
154  * @param string $sqlDate
155  * @return int
156  */
157 function wdcal_mySql2PhpTime($sqlDate)
158 {
159         $ts = DateTime::createFromFormat("Y-m-d H:i:s", $sqlDate);
160         return $ts->format("U");
161 }
162
163 /**
164  * @param string $myqlDate
165  * @return array
166  */
167 function wdcal_mySql2icalTime($myqlDate)
168 {
169         $x             = explode(" ", $myqlDate);
170         $y             = explode("-", $x[0]);
171         $ret           = array("year"=> $y[0], "month"=> $y[1], "day"=> $y[2]);
172         $y             = explode(":", $x[1]);
173         $ret["hour"]   = $y[0];
174         $ret["minute"] = $y[1];
175         $ret["second"] = $y[2];
176         return $ret;
177 }
178
179
180 /**
181  * @param string $str
182  * @return string
183  */
184 function icalendar_sanitize_string($str = "")
185 {
186         $str = str_replace("\r\n", "\n", $str);
187         $str = str_replace("\n\r", "\n", $str);
188         $str = str_replace("\r", "\n", $str);
189         $str = str_replace("\n\n", "\n", $str);
190         $str = str_replace("\n\n", "\n", $str);
191         return $str;
192 }
193
194
195 /**
196  * @return Sabre_CalDAV_AnimexxCalendarRootNode
197  */
198 function dav_createRootCalendarNode()
199 {
200         $caldavBackend_std       = Sabre_CalDAV_Backend_Private::getInstance();
201         $caldavBackend_community = Sabre_CalDAV_Backend_Friendica::getInstance();
202
203         return new Sabre_CalDAV_AnimexxCalendarRootNode(Sabre_DAVACL_PrincipalBackend_Std::getInstance(), array(
204                 $caldavBackend_std,
205                 $caldavBackend_community,
206         ));
207 }
208
209 /**
210  * @return Sabre_CardDAV_AddressBookRootFriendica
211  */
212 function dav_createRootContactsNode()
213 {
214         $carddavBackend_std       = Sabre_CardDAV_Backend_Std::getInstance();
215         $carddavBackend_community = Sabre_CardDAV_Backend_FriendicaCommunity::getInstance();
216
217         return new Sabre_CardDAV_AddressBookRootFriendica(Sabre_DAVACL_PrincipalBackend_Std::getInstance(), array(
218                 $carddavBackend_std,
219                 $carddavBackend_community,
220         ));
221 }
222
223
224 /**
225  * @param bool $force_authentication
226  * @param bool $needs_caldav
227  * @param bool $needs_carddav
228  * @return Sabre_DAV_Server
229  */
230 function dav_create_server($force_authentication = false, $needs_caldav = true, $needs_carddav = true)
231 {
232         $arr = array(
233                 new Sabre_DAV_SimpleCollection('principals', array(
234                         new Sabre_CalDAV_Principal_Collection(Sabre_DAVACL_PrincipalBackend_Std::getInstance(), "principals/users"),
235                 )),
236         );
237         if ($needs_caldav) $arr[] = dav_createRootCalendarNode();
238         if ($needs_carddav) $arr[] = dav_createRootContactsNode();
239
240
241         $tree = new Sabre_DAV_SimpleCollection('root', $arr);
242
243 // The object tree needs in turn to be passed to the server class
244         $server = new Sabre_DAV_Server($tree);
245
246         $server->setBaseUri(CALDAV_URL_PREFIX);
247
248         $authPlugin = new Sabre_DAV_Auth_Plugin(Sabre_DAV_Auth_Backend_Std::getInstance(), 'SabreDAV');
249         $server->addPlugin($authPlugin);
250
251         $aclPlugin                      = new Sabre_DAVACL_Plugin_Friendica();
252         $aclPlugin->defaultUsernamePath = "principals/users";
253         $server->addPlugin($aclPlugin);
254
255         if ($needs_caldav) {
256                 $caldavPlugin = new Sabre_CalDAV_Plugin();
257                 $server->addPlugin($caldavPlugin);
258         }
259         if ($needs_carddav) {
260                 $carddavPlugin = new Sabre_CardDAV_Plugin();
261                 $server->addPlugin($carddavPlugin);
262         }
263
264         if ($force_authentication) $server->broadcastEvent('beforeMethod', array("GET", "/")); // Make it authenticate
265
266         return $server;
267 }
268
269
270 /**
271  * @param Sabre_DAV_Server $server
272  * @param string $with_privilege
273  * @return array|Sabre_CalDAV_Calendar[]
274  */
275 function dav_get_current_user_calendars(&$server, $with_privilege = "")
276 {
277         if ($with_privilege == "") $with_privilege = DAV_ACL_READ;
278
279         $a             = get_app();
280         $calendar_path = "/calendars/" . strtolower($a->user["nickname"]) . "/";
281
282         /** @var Sabre_CalDAV_AnimexxUserCalendars $tree  */
283         $tree = $server->tree->getNodeForPath($calendar_path);
284         /** @var array|Sabre_CalDAV_Calendar[] $calendars  */
285         $children = $tree->getChildren();
286
287         $calendars = array();
288         /** @var Sabre_DAVACL_Plugin $aclplugin  */
289         $aclplugin = $server->getPlugin("acl");
290         foreach ($children as $child) if (is_a($child, "Sabre_CalDAV_Calendar")) {
291                 if ($with_privilege != "") {
292                         $caluri = $calendar_path . $child->getName();
293                         if ($aclplugin->checkPrivileges($caluri, $with_privilege, Sabre_DAVACL_Plugin::R_PARENT, false)) $calendars[] = $child;
294                 } else {
295                         $calendars[] = $child;
296                 }
297         }
298         return $calendars;
299 }
300
301
302 /**
303  * @param Sabre_DAV_Server $server
304  * @param Sabre_CalDAV_Calendar $calendar
305  * @param string $calendarobject_uri
306  * @param string $with_privilege
307  * @return null|Sabre_VObject_Component_VEvent
308  */
309 function dav_get_current_user_calendarobject(&$server, &$calendar, $calendarobject_uri, $with_privilege = "")
310 {
311         $obj = $calendar->getChild($calendarobject_uri);
312
313         if ($with_privilege == "") $with_privilege = DAV_ACL_READ;
314
315         $a   = get_app();
316         $uri = "/calendars/" . strtolower($a->user["nickname"]) . "/" . $calendar->getName() . "/" . $calendarobject_uri;
317
318         /** @var Sabre_DAVACL_Plugin $aclplugin  */
319         $aclplugin = $server->getPlugin("acl");
320         if (!$aclplugin->checkPrivileges($uri, $with_privilege, Sabre_DAVACL_Plugin::R_PARENT, false)) return null;
321
322         $data    = $obj->get();
323         $vObject = Sabre_VObject_Reader::read($data);
324
325         return $vObject;
326 }
327
328
329 /**
330  * @param Sabre_DAV_Server $server
331  * @param int $id
332  * @param string $with_privilege
333  * @return null|Sabre_CalDAV_Calendar
334  */
335 function dav_get_current_user_calendar_by_id(&$server, $id, $with_privilege = "")
336 {
337         $calendars = dav_get_current_user_calendars($server, $with_privilege);
338
339         $calendar = null;
340         foreach ($calendars as $cal) {
341                 $prop = $cal->getProperties(array("id"));
342                 if (isset($prop["id"]) && $prop["id"] == $id) $calendar = $cal;
343         }
344
345         return $calendar;
346 }
347
348
349 /**
350  * @param string $uid
351  * @return Sabre_VObject_Component_VEvent $vObject
352  */
353 function dav_create_empty_vevent($uid = "")
354 {
355         $a = get_app();
356         if ($uid == "") $uid = uniqid();
357         return Sabre_VObject_Reader::read("BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//Friendica//DAV-Plugin//EN\r\nBEGIN:VEVENT\r\nUID:" . $uid . "@" . $a->get_hostname() .
358                 "\r\nDTSTAMP:" . date("Ymd") . "T" . date("His") . "Z\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n");
359 }
360
361
362
363
364 /**
365  * @param Sabre_VObject_Component_VEvent $vObject
366  * @return Sabre_VObject_Component_VEvent|null
367  */
368 function dav_get_eventComponent(&$vObject)
369 {
370         $component     = null;
371         $componentType = "";
372         foreach ($vObject->getComponents() as $component) {
373                 if ($component->name !== 'VTIMEZONE') {
374                         $componentType = $component->name;
375                         break;
376                 }
377         }
378         if ($componentType != "VEVENT") return null;
379
380         return $component;
381 }