Potablog 1338.at Header

 
I was searching for solutions for using my existing iCal-calendars from Lightning/Sunbird with my new HTC Desire WITHOUT using the Google-calender (respectively without sending them your private data).

To create the calendars on the Adroid I couldn't find any other way then, just to create them at your Google-Account, sync them and afterwards disable the calendar-syncing at your Android-Phone.

Now you have to install yourself a CalDav-Server. The simplest server I found, for configuring and installing was SabreDav. Just get a XAMPP running on your machine and installing SabreDav.

Since there is no out-of-the-box possibility to import your iCal-files in the new CalDav server I wrote myself a little script, that does that for me. I know the code is messy and very imperformant, but it works and that is all it counts for me, at the moment.

Code
<?php
/* iCal-import script for SabreDav CalDav Server
* Coder: Daniel Bomze - daniel.bomze {att} gmx {dottt} net
* Last changes: 04.01.2011
* Please let me know if you find bugs, failures or just have code-improvements
*/

//the user in which the calendars should be created, the have to exists and start with 'pricipals/'
$principalUser = "principals/admin";

// settings
date_default_timezone_set('Europe/Berlin');

// If you want to run the SabreDAV server in a custom location (using mod_rewrite for instance)
// You can override the baseUri here.
// $baseUri = '/';

/* Database */
$pdo = new PDO('sqlite:data/db.sqlite');
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);

//Mapping PHP errors to exceptions
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");

// Files we need
require_once 'lib/Sabre/autoload.php';

// The object tree needs in turn to be passed to the server class
$server = new Sabre_CalDAV_Server($pdo);

if (isset($baseUri))
$server->setBaseUri($baseUri);

$backend = new Sabre_CalDAV_Backend_PDO($pdo);
$calendars = $backend->getCalendarsForUser($principalUser);
foreach($calendars as $calendar){
$calendars[$calendar["uri"]] = $calendar;
}
$dir_handle = opendir(".");
$calendar_options = array("VEVENT","VTODO", "{DAV:}description" => "");
$prepend_data = "BEGIN:VCALENDAR
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
VERSION:2.0
";
$append_data = "
END:VCALENDAR
";
while($file = readdir($dir_handle)){
if(strrchr($file, ".") == ".ics"){
$calendar_uri = substr($file, 0, strrpos($file, "."));
$calendar_options["{DAV:}displayname"] = $calendar_uri;
if(!array_key_exists($calendar_uri, $calendars)){
$calendar_id = $backend->createCalendar($principalUser, $calendar_uri, $calendar_options);
}
else{
$calendar_id = $calendars[$calendar_uri]["id"];
}
$ics_file = file_get_contents($file);

$count_matches = preg_match_all("/(BEGIN\:VEVENT)+?(.*?)(END\:VEVENT)+?/is",$ics_file, $matches,PREG_SET_ORDER );
foreach($matches as $match){
$UID = trim(preg_replace("/(.*?)\sUID:(.*?)\n(.*)/ims", "$2", $match[0])).".ics";
$date = preg_replace("/(.*?)\sLAST-MODIFIED:(.*?)\s(.*)/ims", "$2", $match[0]);
$unixtimestamp = mktime(substr($date,9,2), substr($date,11,2), substr($date,13,2), substr($date,4,2), substr($date,6,2), substr($date,0,4));
$calendar_obj = $backend->getCalendarObject($calendar_id, $UID);
if($calendar_obj === FALSE){
$backend->createCalendarObject($calendar_id, $UID, $prepend_data.$match[0].$append_data);
}
else{
if($calendar_obj["lastmodified"] <= $unixtimestamp){
$backend->updateCalendarObject($calendar_id, $UID, $prepend_data.$match[0].$append_data);
}
else{
//entry in online-calender is newer than the one in ics-file, so do not update it
}
}

}
}
}
echo "all files were imported";
?>




Just put this code in a file in the directory where your SabreDav-Server is located and put the .ics files in the same directory.

You eventually need to increase the max_execution_time in the php.ini file
A value of 600 worked fine for me.

If your iCal-files were imported to your CalDav serer you can synchronize the your Android phone with the server. To synchronize your Android calendar with your new CalDav-Server you will have to install this tiny app: Calendar (CalDAV) Sync

When configuring the app on your phone your URL to the calendar could look like this

Codehttp://192.168.0.1/dav/calendarserver.php/calendars/admin/Privat/


Also you can access the CalDav server via Lightning/Sunbird via:
New calendar->On the network->select CalDav and enter the URL to your calender. Don't forget the trailing slash! For me the URL looked for example like this
Codehttp://192.168.0.1/dav/calendarserver.php/calendars/admin/Privat/


Explaination:
192.168.0.1 is the IP of the computer where der xampp is runing,
dav is the directory where I installed my SabreDav server,
calendarserver.php is the SabreDav calendar-server file.
calendars, the virtual directory calandars is for accessing (who got it? ;-)) the calendars,
admin is the principal/user and
Privat is the name of the calandar as i created it.
Be sure to have the trailing slash at the end of the URL or this won't work properly.

Tip: If you wan't to synchronize your phone from outside the LAN you have to use a VPN or a public webserver.

If you have questions feel free to contact me via comments, email or jabber.

Update:
Added the trim() function to the UID-detection, because if synchronizing without them, apache sometimes can't find the ics-files.
Direktlink  Kommentare: 9 geschrieben von potassium am Dienstag, 04.01.2011, 14:36

Kommentar(e):
naj hat am Sonntag, 13.02.2011 um 08:56 geschrieben:
Kommentar ändern löschen

Danke für diesen Artikel! (Ein bißchen Lichtblick in der Android Geschichte....)

Ich habe dennoch einige Fragen: SabreDAV Alternativen? Ist DAViCal okay? Ich möchte es gerne am webserver laufen lassen und dort auch backups der Kalender machen können..

Der 1. Schritt über Google Calender ist wirklich trotzdem notwendig??

Hast du auch eine Idee wie ich die Kontakte ohne Google mit meinem Mac synchronisieren könnte?
potassium hat am Sonntag, 13.02.2011 um 14:30 geschrieben:
Kommentar ändern löschen

davical hab ich glaub ich ned getestet. probier es einfach, mehr kann ich da dazu leider auch ned sagen. Backups kannst mit sabredav auch machen. einfach die sqlite db backupen.
das mit Google ist leider notwendig, da die sync app keine Kalender erstellen kann. is zwar für die nachfolge app angekündigt, aber da gibts noch nix News.
Mac weiß ich ned genau, unter Windows kannst myphoneexplorer dafür benutzen. ev win emulieren auf Mac os.
LG
Evert Pot hat am Freitag, 18.02.2011 um 15:00 geschrieben:
Kommentar ändern löschen

With this you might end up with invalid iCalendar objects, because you're missing VTIMEZONE.
potassium hat am Freitag, 18.02.2011 um 15:02 geschrieben:
Kommentar ändern löschen

Is this field really used? I didn't needed it until now,but I'll have a look at it.
Evert Pot hat am Freitag, 18.02.2011 um 15:04 geschrieben:
Kommentar ändern löschen

Yea, every calendar object *should* have a list of timezones it's using.

It might also be helpful to look at this example, which does the exact opposite of what you're doing:

http://code.google.com/p/sabredav/source/browse/lib/Sabre/CalDAV/ICSExportPlugin.php
potassium hat am Freitag, 18.02.2011 um 15:08 geschrieben:
Kommentar ändern löschen

Thx, if I can spare a little time the next weeks I'll have a look at this. Atm I'm very busy and won't be able to fix this right away. May I ask if you use this code or planning to use it?
Evert Pot hat am Freitag, 18.02.2011 um 15:10 geschrieben:
Kommentar ändern löschen

I'm the author of SabreDAV, and I was just looking around =) It's good to see it's being used and hacked with.
potassium hat am Freitag, 18.02.2011 um 15:12 geschrieben:
Kommentar ändern löschen

Oh. Than I will surely come back to you if I have questions ;-)
Evert Pot hat am Freitag, 18.02.2011 um 15:13 geschrieben:
Kommentar ändern löschen

Sure thing, the mailing list is becoming pretty active too

Kommentar hinzufügen

Name*:
E-Mail-Adresse*: (Wird nicht veröffentlicht!)
WWW:


Text *:

HTML ist in den Kommentaren deaktiviert, alternativ können Sie aber (ausgewählte) bbCode-Befehle benutzen.

Privater Kommentar (Ist nur für den Autor des Eintrags lesbar.)
Benachrichtige mich, wenn es Antworten auf meinen Kommentar gibt.
Meine Eingaben merken.

Bitte geben Sie folgenden Antibot-Code ein:
Auth-Code
Antibot-Code*: