News:

Join the Facebook Fan Page.

Main Menu

CalDAV Support

Started by demlak, April 06, 2014, 05:54:28 PM

Previous topic - Next topic

demlak

Hi there..

since a year or so im crying about non-existing caldav support..
now my owncloud instance is in my everyday use on my mobile device and on my desktop system...
so there is a new crying for it =)

I was looking around.. and think there is a solution not far away..
it would be nice to have a bridge between smf and caldav calendar like owncloud, sabre, calendarserver, etc..

to get it work in a usefull variant, i decided to start with a simple support of just automaticaly add/edit/delete calendar entrys.

means:
the caldav server just displays the content of the smf calendar.. if you change anything on the caldav server.. it will not update anything on the smf calendar.. this might be interessting in later stages..

so.. we need two parts:
part1 (at first start and maybe 1 time a week to verify):
read all calendar entrys on SMF and on CalDAV.. verify them (unique IDs)

  • if an event is listed on SMF but not on CalDAV.. -> add it to CalDAV
  • if an event is listed on SMF and on CalDAV.. -> Check if any data of it has changed -> update CalDAV Event with data of SMF event
  • if an event is listed on CalDAV but not on SMF.. -> delete it on CalDAV

Part2:
injected code in smf calls functions:

  • if an event is added in SMF -> automaticaly add it to CalDAV
  • if an event is modified in SMF -> automaticaly modify it on CalDAV
  • if an event is deleted on SMF -> automaticaly delete it on CalDAV

i found a php class/library to interact with caldav server here:
https://github.com/DAViCal/davical/blob/master/inc/caldav-client.php

or simple curl code:
http://trentrichardson.com/2012/06/22/put-caldav-events-to-calendar-in-php/

my researches brought me to the idea to use the SMF eventID (sql row "id_event" in table ?_calendar" also for the UID on the CalDAV server..

i did not look deeper into all of this.. so maybe it´s more simple to work with a complete new calendar on the caldav server to prevent problems on UID usage..

an SMF event looks like this in the sql database:
id_event, start_date, end_date, id_board, id_topic, title, id_member

the id_event should go -> UID
start_date and end_date are self-explanatory
board_id could be used to add board-name to event-text
id_topic should be used to readout first post in thread and generate event-text
title should be used to generate event-title..

in here, we have a standard-pattern of all event-titles like this:

CATEGORY: STARTTIME - EVENTTITLE @ LOCATION (license plate)
(sometimes no starttime.. sometimes no licenseplate)

which results in something like:
"FESTIVAL: Irish Folk Festival @ Kloster Möllenbeck (RI)"
"PARTY: 21:30 Uhr - We Love the 80´s @ Ferry Eventhall"

("Uhr" is german for "o´clock")

so we also want to match these pattern to get starttime and location of the event for appropriate parts of CalDAV event..

i would be very thankfull for any coding help!

current problems:

  • prevent/revoke event-editing by caldav users/clients?
  • individual reminders for each caldav user/client?

margarett

I'm afraid you won't get much "love" for that issue :(
The Calendar is one of those not-much-used features for the most of us...

Anyway, there are some things I'd like to point out:
* If you use a fixed pattern for posting your events, you can get the relevant informations from that string using adequate PHP functions ;)
* The "hours" are irrelevant for SMF's calendar as it only uses days for events... In the examples you gave, start_date and end_date should always  be the same, but you will have no control over the time of the day for the events.
Se forem conduzir, não bebam. Se forem beber... CHAMEM-ME!!!! :D

QuoteOver 90% of all computer problems can be traced back to the interface between the keyboard and the chair

demlak

for sure.. there are not many people interested in this... thats what we state in this forum since a long time =)
but there are some people interested in this.. for sure: ME!
so.. i´ll give it a try..
but.. as i am not a coder.. i have to tinker things together..

a good start:
sending caldav via php works here with this script calling curl:
<?php

$account
= array(
 
'server'=> 'test.server.com',
 
'user'  => 'testuser',
 
'pass'  => 'testpass',
 
'calendar'  => 'testcalendar'
);

$uid = 'x-event-123456';
$url = 'http://'.$account['server'].'/remote.php/caldav/calendars/'.$account['user'].'/'.$account['calendar'].'/' . $uid . '.ics';
$userpwd = $account['user'] .":". $account['pass'];
$description = 'the Test event description';
$summary = 'the Test event';
$tstart = gmdate("Ymd\THis\Z", strtotime("+1 days"));
$tend = gmdate("Ymd\THis\Z", strtotime("+1 days"));
$tstamp = gmdate("Ymd\THis\Z");

$body = <<<__EOD
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
DTSTAMP:
$tstamp
DTSTART:
$tstart
DTEND:
$tend
UID:
$uid
DESCRIPTION:
$description
LOCATION:Office
SUMMARY:
$summary
END:VEVENT
END:VCALENDAR
__EOD;


$headers = array(
 
'Content-Type: text/calendar; charset=utf-8',
 
'If-None-Match: *',
 
'Expect: ',
 
'Content-Length: '.strlen($body),
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $userpwd);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_exec($ch);
curl_close($ch);

?>


deleting an event works by just changing "PUT" to "DELETE" in "curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');"

QuoteIf we use an existing UID it will be understood as an update. A new UID will create a new event.
source: http://trentrichardson.com/2012/06/22/put-caldav-events-to-calendar-in-php/
Creating new event works.. but updating an existing event didn´t work in here =(
anyone got an idea why?
(i´m also asking at owncloud devs)

demlak

Update..
for updating an existing event.. i just delete it.. and send the updated version of the event..

im reading some php tutorials.. i learned what a function is.. and added one..
small helping information how to use this script is also added..

hope this monolog on such a "underdog"-topic is not seen as spam?

<?php

// Call: filename.php "UID" "TITLE" "DESCRIPTION LINE1\nLine2\nLine3" "LOCATION"
// If "TITLE" == "DELETE" -> Event with UID will be deleted

$account = array(
 
'server'=> 'http://testdomain.com', // http://host.tld/sub/folder (you can use https, no trailing /)
 
'user'  => 'testuser',        // owncloud username
 
'pass'  => 'testpass',          // owncloud password
 
'calendar'  => 'test'             // owncloud calendar name
);
           
$uid = $argv[1];
$url = $account['server'].'/remote.php/caldav/calendars/'.$account['user'].'/'.$account['calendar'].'/' . $uid . '.ics';
$userpwd = $account['user'] .":". $account['pass'];
$summary = $argv[2];
$description = $argv[3];
$location = $argv[4];
$tstart = gmdate("Ymd\THis\Z", strtotime("+1 days"));
$tend = gmdate("Ymd\THis\Z", strtotime("+1 days"));
$tstamp = gmdate("Ymd\THis\Z");

function
caldavsend($url_out, $headers_out, $userpwd_out, $command_out, $body_out)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url_out);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers_out);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $userpwd_out);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $command_out);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body_out);
curl_exec($ch);
curl_close($ch);
}


if (
$argv[2] == "DELETE")
{
$body = <<<__EOD
UID:$uid
__EOD;

$headers = array(
 
'Content-Type: text/calendar; charset=utf-8',
 
'If-None-Match: *',
 
'Expect: ',
 
'Content-Length: '.strlen($body),
);
           
caldavsend($url, $headers, $userpwd, "DELETE", $body);
EXIT();
}


$body = <<<__EOD
UID:$uid
__EOD;

$headers = array(
 
'Content-Type: text/calendar; charset=utf-8',
 
'If-None-Match: *',
 
'Expect: ',
 
'Content-Length: '.strlen($body),
);
                           
caldavsend($url, $headers, $userpwd, "DELETE", $body);

$body = <<<__EOD
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
DTSTAMP:
$tstamp
DTSTART:
$tstart
DTEND:
$tend
UID:
$uid
DESCRIPTION:
$description
LOCATION:
$location
SUMMARY:
$summary
END:VEVENT
END:VCALENDAR
__EOD;

$headers = array(
 
'Content-Type: text/calendar; charset=utf-8',
 
'If-None-Match: *',
 
'Expect: ',
 
'Content-Length: '.strlen($body),
 );
           
caldavsend($url, $headers, $userpwd, "PUT", $body);

?>

margarett

It isn't.

Please keep posting your findings. Maybe someone wants to share the effort with you ;)
Se forem conduzir, não bebam. Se forem beber... CHAMEM-ME!!!! :D

QuoteOver 90% of all computer problems can be traced back to the interface between the keyboard and the chair

demlak

can you direct me to the files where calendar events are edited/stored to the database? i want to look at these "functions".. and maybe i can inject code..

daniu

Hi demlak,

I read your code here and was quite happy to find anything.

I wrote for myself some code that does read a caldav calendar and write it on another server. I cannot really explain why but it seems like I cannot get the thing to update (when I sync once more it simply changes nothing ...)

So now I am looking for a method to delete all entries from a calendar first (since I just want to mirror a google server to a caldav server - not sync anything back). That would also make it easier to make sure that the 2 calendars contain the same.

Any hint on how to do that?

I tried this (I had to tweak the url to make the thing work at all - using a horde/kronolith server - url works for writing like this):

$uid = 'x-event-123456';
    $url = 'https://'.$to['server'].'/webmail5/rpc.php/kronolith/'.$to['user'].'/'.$to['calendar'].'/'.$uid.'.ics';
    //echo $url;
    $userpwd = $to['user'] .":". $to['pass'];
    $body = "*";
    $headers = array(
     'Content-Type: text/calendar; charset=utf-8',
     'If-None-Match: *',
     'Expect: ',
     'Content-Length: '.strlen($body),
    );

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    curl_setopt($ch, CURLOPT_USERPWD, $userpwd);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
    curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
    curl_exec($ch);
    curl_close($ch); 


which did not work.

BTW: is there any benefit in using fsockopen and if so - what does the code look like with fsockopen?

regards

Advertisement: