X

An Oracle blog about Openomics

  • sun
    December 8, 2008

Sun Calendar Sync for Apple iCal

Guest Author

Building off the work by John Littell and Jason Carolan, I am releasing here icalds 2.0 that enables you to subscribe to a Sun Calendar Server
from an Apple iCal client on Mac OS X, and subsequently sync with
"any" mobile device thru iSync. I am myself using it on Mac OS X 10.5.5 with Sun Calendar Server 6.3. icalds will prove useful until Sun Calendar Server adds native CalDAV support.

Compared to the previous releases of the icald/icalds scripts, fixes include:

  • session id now recognizes non-alphabetic characters (presence of % character)
  • http post request now conforms to what Sun Cal expects (6.3 responded Unauthorized to export.wcap)
  • now using http post request at login for increased security (password no longer visible in web server log)
  • strip out html tags generated by Namefinder for better readability
  • suid no longer required by default values for log/pid file location
  • organizer field is now kept and passed on to iCal

You
would want to use icalds if you maintain your calendar online on a Sun
Calendar Server --like we do at Sun Microsystems-- but want to have a copy on your
Mac and/or sync it to a non-3G mobile device --you can directly sync a 3G
device to Sun Calendar Server through SyncML. I myself sync it with a Nokia
cellphone and an old Palm PDA. icalds runs as a daemon
on your Mac so you do not need to explicitely run it, iCal will simply
sync at the frequency you tell it to. You could also use icalds to
maintain your calendar on a Mac and publish it to a Sun Calendar
Server but I haven't tried/debugged that use-case so you may run into
issues; let we know if you do.

To get going with icalds, download the icalds.pl Perl script then follow these steps:

  1. Create directories, copy files
    • create a bin folder in home folder (if not already there)
    • copy icalds.pl and icalds.command into bin/
    • make both scripts executable (chmod a+x icalds\*)
  2. Update Perl
    • login as root if you've enabled that, use sudo otherwise
    • start CPAN (perl -MCPAN -e shell)
    • install all modules listed in icalds.pl
    • if missing, download SSL module
  3. Edit files
    • edit UserName, CalendarServer, PortNumber in icalds.command
    • optionally, edit paths in for PIDFILE and LOGFILE icalds.pl
    • in the unlikely event your calendar server is accessible via http and not https, change the 4 occurences of https to http in icalds.pl
  4. Make run on login
    • add icalds.command execute on login in Preferences>Accounts>Login Items
    • logout and log back in, or just run icalds.command at the command line
  5. Subscribe in iCal
    • suscribe to http://locahost:7081/login/<username>
    • use username and password
    • you can subscribe to sub-calendars using http://locahost:7081/login/<username>/<calname>

If you are a heavy user of recurring events and multiple timezones, you will see that iCal does not display properly these events. I believe I know how to fix icalds for it to work --change DTSTART time from a UTC time to a local time-- but I haven't had the time to do it. Events are displayed fine in my Nokia and my Palm though so the buggy display is not transmitted thru iSync.

Join the discussion

Comments ( 38 )
  • Frederic Pariente Tuesday, December 9, 2008

    I have submitted BugID 6430273 to Apple on this. Synopsis is : iCal does not deal with UTC times in DTSTART and DTEND when importing ICS file.


  • Anthony Tuesday, December 9, 2008

    I can get connected and see my calendar entries but it seems that it displays repeating events that I've deleted in the past. I have a debug file if you'd like to see it.


  • Anthony Mayes Tuesday, December 9, 2008

    After digging a little more I've found that my problem does not involve your script. It was a export/import problem. Thanks for the script!


  • Frederic Pariente Wednesday, December 10, 2008

    Anthony, I'm glad icalds is proving useful. You may still see some errors with recurring events. DST seems not to be taken into account when DTSTART and DTEND times are specified in Zulu timezone, as it is the case for my work Calendar Server. iCal accepts Zulu times in other fields though (e.g. RRULE, EXCLUDE). I submitted BugID 6430273 on this but do not expect any quick fix from Apple. I also googled for some Perl code to convert ICS dates between timezones with no success. My last resort will be to write my own subroutine, when I can dedicate more time to icalds.


  • chrid Saturday, February 14, 2009

    i get an error:

    error subscribing to the calendar

    code 30

    any idea?

    thank you


  • Frederic Pariente Sunday, February 15, 2009

    There is a debug mode that you can turn on (launch script with -d or edit Perl script to set $DEBUG=1). It creates an add'l log file where you see the exchange with the Calendar Server. Can you try it? What does it say?


  • chrid Sunday, February 15, 2009

    in the logfile it says:

    Use of uninitialized value in string ne at /users/chrid/bin/icalds.pl line 314.

    192.168.1.103 - - [15/Feb/2009:23:54:53 +0100] "GET /login/chrid" 401 539

    Can't call method "code" on an undefined value at /users/chrid/bin/icalds.pl line 211.

    sorry i am not a perl user at all

    thx for any help!


  • chrid Sunday, February 15, 2009

    hi frederic,

    i fixed this one. i put the url in the command file with https and / etc. without that it now connects but says it:

    No calendar was found on http://localh...... . Please check the URL.

    And a lot of stuff in the debug file, requests to the calendar. This are for sections

    1. Request: https://www.xxx.xxx:xx/get_calprops.wcap with the X-NSCP-WCAP-ERRNO:29

    2. Request: https://www.xxx.xxx:xx/login.wcap with the X-NSCP-WCAP-ERRNO:0

    3. Request: https://www.xxx.xxx:xx/get_calprops.wcap with the X-NSCP-WCAP-ERRNO:29

    4. Request: https://www.xxx.xxx:xx/logout.wcap

    with the X-NSCP-WCAP-ERRNO:-1

    In the log it says

    se of uninitialized value in string ne at ..../bin/icalds.pl line 314.

    Useless content call in void context at ..../bin/icalds.pl line 521

    thx for any help

    christian


  • Frederic Pariente Monday, February 16, 2009

    From the Sun Calendar documentation on docs.sun.com, error 29 is CALENDAR_DOES_NOT_EXIST (see http://docs.sun.com/source/816-6416-10/pr10WCAP.html#53182). It could be a typo in your calname. It could also be that it does not exist yet. Can you connect to the Calendar Server through the Calendar Express web interface? Should simply be https://www.xxx.xxx/ in your case. The calendar will be created at login in case it did not exist before. If you simply cannot login through Calendar Express, there is no way the Perl script will work either. Check with your sysadmin then what is your username for the Calendar Server, it could be different from your Unix login.

    As for the warning (uninitialized variable, void content), that's normal.

    Hope this helps.


  • chrid Monday, February 16, 2009

    Hi,

    the calendar works fine in the webclient and also in thunderbird lightning.


  • chrid Monday, February 16, 2009

    Hi Frederic,

    i could just solve the problem. as url i had to put in the full user name including @domain. no it works fine.

    THANK YOU VERY MUCH FOR THIS TOOL! I NOW CAN SYNC TO MY IPHONE without using a google calendar account etc....

    best regards from vienna,

    christian


  • anke Friday, February 20, 2009

    Dear Frederic,

    thank you for this script!

    Unfortunately, I cannot make it work just yet.

    I downloaded your script and it runs fine. I can subscribe to my calendar (which I could not until I got the port straight), but now, I do not see any calendar contents, and I get an unexpected error when updating the calendar, error 4 (this is my translation from German).

    I turned debug on, and I receive this message in the error log:

    127.0.0.1 - - [20/Feb/2009:10:58:40 +0100] "GET /login/Anke" 401 539

    127.0.0.1 - Anke [20/Feb/2009:10:58:40 +0100] "GET /login/Anke" 200 431852

    and this one in the terminal, where the scrip runs:

    Use of uninitialized value in string ne at /Users/hildebra/bin/icalds.pl line 314.

    Useless content call in void context at /Users/hildebra/bin/icalds.pl line 521

    sorry, I am a perl novice.

    Thank you for any hints.

    Anke


  • Frederic Pariente Friday, February 20, 2009

    Could it be that you have sub-calendars? If so, from iCal, subscribe to .../Anke/calname.

    As for the debug log, you need to look in the other file /var/tmp/icalds.debug. What do you see there?


  • Anke Friday, February 20, 2009

    Hi,

    Wow. The icalds.debug file shows my calendar and to do list. It is pretty long .. Can you point me to a particular place I should check?

    I have only one calendar, but I am subscribed to others, which I tihnk would not qualify as sub-calendar .. ?


  • Frederic Pariente Friday, February 20, 2009

    If you see your calendar, that's a good start, the connection to the server works. Some ideas...

    1. Look at the WCAP commands and check that X-NSCP-WCAP-ERRNO is 0 (means ok).

    2. Cut-n-paste your calendar data (from BEGIN:VCALENDAR to END:VCALENDAR) into a file called test.ics and try to open it with iCal.

    3. Try deleting some calendars in iCal and restarting it. iCal has been unstable at times for me.

    4. Try subscribing to your calendar without ToDo's or alarms. I have not tested these myself, maybe there's a bug in icalds with these.

    That's all I can think of right now... time for lunch :)


  • Anke Friday, February 20, 2009

    SUCCESS!!!

    Thank you, I got it.

    The problem was with one particular event. This had been an invitation to the entire Company, and had apparently been to the emaillist subscribers of mycompany_all@mycompany.de . iCal liked all my other invitations except this particular one. I figured it out be sequentially removing events from the calendar, and importing the file per hand as you said, until it worked.

    Fix: I removed this particular event from my work calendar and the everything works fine now.

    Thank you very much for this Tool and your help with making it work!


  • Frederic Pariente Friday, February 20, 2009

    I'm glad you got it to work, Anke. Could you post here the "bad" calendar entry? So I could try to debug & update icalds to make it work with it. Make sure to anonymize the data first, of course. Thanks!


  • Anke Saturday, February 21, 2009

    Hi Frederic,

    here is the event that caused problems, cut from the debug file.

    Again, thanks for the help and getting this to run!

    anke

    BEGIN:VEVENT

    UID:00000000000000000000000000000000d9da7d497e7c0000d8020000e5030000

    DTSTAMP:20090220T125605Z

    SUMMARY:IT Infoveranstaltung 11.02.2009

    DTSTART:20090211T090000Z

    DTEND:20090211T100000Z

    CREATED:20090126T154704Z

    LAST-MODIFIED:20090211T115307Z

    PRIORITY:0

    SEQUENCE:0

    DESCRIPTION:\\r\\nLots of invitation text which I erased (anke)\\r\\n

    CLASS:PUBLIC

    ORGANIZER;CN="Max Organizer"

    ;X-S1CS-EMAIL=max.organizer@mycompany.de

    :orginizerloginname

    STATUS:CONFIRMED

    TRANSP:OPAQUE

    ATTENDEE;ROLE=REQ-PARTICIPANT;CUTYPE=INDIVIDUAL

    ;PARTSTAT=NEEDS-ACTION;CN="Max FirstInvitee"

    ;MEMBER="mycompany_all@mycompany.de"

    ;RSVP=TRUE

    ;X-NSCP-ATTENDEE-GSE-STATUS=2

    ;X-S1CS-EMAIL=max.firstinvitee@myconpany.de

    :firstinviteeloginname

    ATTENDEE;ROLE=REQ-PARTICIPANT;CUTYPE=INDIVIDUAL

    ;PARTSTAT=NEEDS-ACTION;CN="Max SecondInvitee"

    ;MEMBER="mycompany_all@mycompany.de"

    ;RSVP=TRUE

    ;X-NSCP-ATTENDEE-GSE-STATUS=2

    ;X-S1CS-EMAIL=max.firstinvitee@myconpany.de

    :secondinviteeloginname

    many more invitees here, I have 10000 lines of this

    after the last invitee the end is:

    X-NSCP-ORIGINAL-DTSTART:20090211T090000Z

    X-NSCP-LANGUAGE:de

    X-NSCP-TOMBSTONE:0

    X-NSCP-ONGOING:0

    X-NSCP-ORGANIZER-EMAIL:max.organizer@mycompany.de

    X-NSCP-GSE-COMPONENT-STATE;X-NSCP-GSE-COMMENT="REPLY-ACCEPTED":262176

    END:VEVENT


  • Frederic Pariente Friday, February 27, 2009

    I think I have traced back the issue to the MEMBER param that iCal does not seem to like. I have a modified version of icalds for you to test at http://opensolaris.free.fr/icalds/icalds.pl . Can you verify the fix? If it works, I'll post a quick blog to "officially" release this new version :) Thanks again!


  • Wulf Kaiser Wednesday, April 1, 2009

    Hi all,

    i wrote a function in PHP to export a calendar for Mac iCal some days ago; recently, i have patched the scripts to get rid of the ";MEMBER" lines. If anyone has interest, please contact me!

    Best,

    - Wulf


  • Karl H. Beckers Tuesday, April 7, 2009

    When you say this ...

    "You could also use icalds to maintain your calendar on a Mac and publish it to a Sun Calendar Server but I haven't tried/debugged that use-case so you may run into issues; let we know if you do."

    ... you mean you haven't even tested it ever once? When I try to publish a given calendar to one specifically created on the server for that purpose (called "work") I always get a message that /login/<username>/work/Work.ics was not found on the server. Or am I doing smth. blatantly wrong?

    Also, the the pull variant does not synch todos, does it?

    TIA,

    Karl.


  • Frederic Pariente Wednesday, April 8, 2009

    Yes, that's what I meant, I haven't tested it, nor (much) changed the PUT part of the script from its original version, in fact. Now that there is a user though (you), I'll give it a try. Ditto for TODO's.

    Will post back soon with my findings...


  • Frederic Pariente Wednesday, April 8, 2009

    So I tried... it seems the script is passing work.ics instead of username:work as it should... Sun Calendar Server logically returns with an error 29 CALENDAR_DOES_NOT_EXIST... should not be too hard to fix. To be cont'd.


  • Frederic Pariente Wednesday, April 8, 2009

    Error 29 is in fact the result of not properly inputing the URL string in the Publish window. If you have created a sub-calendar "work" on the Sun server, you should use in iCal "Publish Calendar as: work" and "Base URL : http://localhost:7081/username/" for the "private server". Along with login and password info.

    I am myself however getting an error 35 next; nothing is eventually written on the Sun side. I may need to strip out some of the iCal extensions in the data sent back to the Sun server. Unless it's because I was publishing a calendar with date-to-date events..?

    Karl, are you getting past error 29 now? Are you seeing your data on the Sun side?


  • Wulf Kaiser Thursday, April 9, 2009

    Here is the mentioned PHP script for exporting a calendar for Mac iCal:

    <code>

    #!/usr/local/bin/php -q

    <?php

    setlocale(LC_ALL, 'de_DE.UTF8');

    require('dateTime.php');

    function URLopen($url) {

    ini_set('user_agent','MSIE 4\\.0b2;');

    $dh = fopen("$url",'r');

    $result = fread($dh,8192);

    return $result;}

    $start = mktime(0, 0, 0, date("m")-2, date("d"), date("Y"));

    $startExport = date("Y-m-d", $start);

    $startJahr = substr($startExport, 0, 4);

    $startMonat = substr($startExport, 5, 2);

    $startTag = substr($startExport, 8, 2);

    $startZeit = "08:00";

    function gmt2utc($day,$month,$year,$time) {

    $isSummertime = date("I", mktime(0,0,0,$month,$day,$year));

    $Hour = substr($time, 0, 2);

    switch ($isSummertime) {

    case '0': $HourUTCin = $Hour - 1; break;

    case '1': $HourUTCin = $Hour - 2; break;}

    if (($HourUTCin >= '1') && ($HourUTCin <= '9')) {

    $HourUTCout = "0$HourUTCin";}

    else {

    $HourUTCout = $HourUTCin;}

    return $HourUTCout;}

    $u_startDate = "$startJahr" . "$startMonat" . "$startTag";

    $u_startHour = gmt2utc($startTag,$startMonat,$startJahr,$startZeit);

    $u_startMinute = substr($startZeit, 3);

    $u_startDate = $u_startDate . "T" . "$u_startHour" . "$u_startMinute" . "00" . "Z";

    $end = mktime(0, 0, 0, date("m")+3, date("d"), date("Y"));

    $endExport = date("Y-m-d", $end);

    $endJahr = substr($endExport, 0, 4);

    $endMonat = substr($endExport, 5, 2);

    $endTag = substr($endExport, 8, 2);

    $endZeit = "08:00";

    $u_endDate = "$endJahr" . "$endMonat" . "$endTag";

    $u_endHour = gmt2utc($endTag,$endMonat,$endJahr,$endZeit);

    $u_endMinute = substr($endZeit, 3);

    $u_endDate = $u_endDate . "T" . "$u_endHour" . "$u_endMinute" . "00" . "Z";

    $curl = curl_init();

    if (!$curl) {

    die("Unable to create a cURL Session");}

    $wcapConnect = curl_setopt($curl, CURLOPT_URL,"https://yourcalendar.com/login.wcap?refresh=1&user=wcapuser&password=wcappass");

    $wcapConnect = curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);

    $wcapConnect = curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

    $wcapConnect = curl_exec($curl);

    $count1 = strpos($wcapConnect, "X-NSCP-WCAP-SESSION-ID:");

    $count1 = $count1 + 23;

    $count2 = strpos($wcapConnect, "X-NSCP-WCAP-USER-ID:");

    $diff = $count2 - $count1;

    $calSessID = substr($wcapConnect, $count1, $diff);

    $calSessID = trim($calSessID);

    global $calSessID;

    $curlExport = curl_init();

    $export = curl_setopt($curlExport, CURLOPT_URL,"https://yourcalendar.com/export.wcap");

    $export = curl_setopt($curlExport, CURLOPT_POSTFIELDS, "calid=calendar2export&dtstart=$u_startDate&dtend=$u_endDate&content-out=text/calendar");

    $export = curl_setopt($curlExport, CURLOPT_SSLVERSION, 3);

    $export = curl_setopt($curlExport, CURLOPT_SSL_VERIFYPEER, 0);

    $export = curl_setopt($curlExport, CURLOPT_POST, 1);

    $export = curl_setopt($curlExport, CURLOPT_HEADER, 0);

    $export = curl_setopt($curlExport, CURLOPT_RETURNTRANSFER, 1);

    $export = curl_exec($curlExport);

    unlink("/tmp/calendar2export.ics");

    $export = trim($export);

    global $export;

    $file = fopen("/tmp/calendar2export.ics", "w+");

    $text = $export;

    fwrite($file, $text);

    fclose($file);

    chmod("/tmp/calendar2export.ics", 0777);

    curl_close($curlExport);

    curl_close($curl);

    sleep(3);

    $replace4Mac = ";MEMBER";

    $original = file("/tmp/calendar2export.ics");

    $output = fopen("/tmp/calendar2export.ics", "w");

    foreach($original as $zeile) {

    if(!preg_match("/".$replace4Mac."/i", $zeile)) {

    fputs($output, $zeile);}}

    ?>

    </code>

    It runs as cron on the command line.


  • Karl H. Beckers Saturday, April 11, 2009

    Well,

    I can finish the publish calendar dialog.

    Only, if I add an event locally, nothing gets written. I'm also getting error 35 ... dunno if the 401 first is related, can't quit correlate icald.debug and icald.log. Here's what I get in the log:

    127.0.0.1 - - [11/Apr/2009:22:18:31 +0200] "PUT " 401 495

    Useless content call in void context at /Users/name/bin/icalds.pl line 609

    Useless content call in void context at /Users/name/bin/icalds.pl line 532

    127.0.0.1 - name [11/Apr/2009:22:18:34 +0200] "PUT /name/work.ics" 200 26

    Use of uninitialized value in string ne at /Users/name/bin/icalds.pl line 229.

    Use of uninitialized value in concatenation (.) or string at /Users/name/bin/icalds.pl line 294.

    127.0.0.1 - - [11/Apr/2009:22:19:07 +0200] "PUT " 401 495

    Useless content call in void context at /Users/name/bin/icalds.pl line 609

    Useless content call in void context at /Users/name/bin/icalds.pl line 532

    127.0.0.1 - name [11/Apr/2009:22:19:09 +0200] "PUT /name/work.ics" 200 26

    Also, what I'd really want to do is sync to the main calendar, eventually. But maybe that's smth. for later.

    Thanks,

    Karl.


  • Frederic Pariente Wednesday, April 15, 2009

    Karl, just a quick note to let you know I have a fix. I need a few days to get to it then will post it to the main blog. Tschuss.


  • Karl H. Beckers Wednesday, April 15, 2009

    Cool ... looking forward to that. Thanks!


  • Manuel Monday, June 29, 2009

    Hi all.

    I'm trying to install this tool, and I get this error using the debug mode, when I try tu subscribe to the SUN Calendar:

    $ ./icalds.command

    Use of uninitialized value in string ne at /Users/mgil/bin/icalds.pl line 326.

    Can't call method "code" on an undefined value at /Users/mgil/bin/icalds.pl line 211.

    I can use Lighting extension under thunderbird without problems, I can login to the SUN Calendar too without problems.

    Thanks.


  • Frederic Pariente Monday, June 29, 2009

    The first error/warning message ("use of uninitialized value") is harmless, I think. The second seems to tell that you did not get a proper HTTP::Response initialized. Is your Perl environment ok? Are you writing your log in a writeable location? Can you show which line you use for subscribing? the debug log?

    Thanks.


  • chrid Wednesday, September 9, 2009

    hi frederic,

    as i updatet to osx10.6 icalds does not work anymore any idea what could have happend i am not a perl guy at all sorry.

    here is the error message

    Can't locate Crypt/SSLeay.pm in @INC (@INC contains: /Library/Perl/Updates/5.10.0 /System/Library/Perl/5.10.0/darwin-thread-multi-2level /System/Library/Perl/5.10.0 /Library/Perl/5.10.0/darwin-thread-multi-2level /Library/Perl/5.10.0 /Network/Library/Perl/5.10.0/darwin-thread-multi-2level /Network/Library/Perl/5.10.0 /Network/Library/Perl /System/Library/Perl/Extras/5.10.0/darwin-thread-multi-2level /System/Library/Perl/Extras/5.10.0 .) at /users/chrid/bin/icalds.pl line 24.

    BEGIN failed--compilation aborted at /users/chrid/bin/icalds.pl line 24.

    thx a lot

    christian


  • Frederic Pariente Thursday, September 10, 2009

    I'm answering your question on the latest icalds blog post at http://blogs.sun.com/openomics/entry/releasing_icalds_2_1#comments since I'm been sending that URL around lately.


  • Manuel Monday, October 19, 2009

    Hi Frederic.

    I'm using your tool right now. I did not have to do more test until now, and everything is working good.

    Many Thanks for the job.

    BYe...


  • Romain Sunday, April 25, 2010

    You say : "you can directly sync a 3G device to Sun Calendar Server through SyncML".

    Can you explain how could I natively sync my nokia with a Sun Calendar Server ?

    Do I need CalDAV support and icalds, or can I do it natively?

    Thanks


  • Frederic Pariente Monday, April 26, 2010

    Romain, you need to talk to your IT guys to check whether they have a SyncML gateway running --essentially, they need to give you a URL to point to. Then, browse the Nokia forums for help on how to configure your cellphone. HTH, Frederic.


  • Romain Monday, April 26, 2010

    Frederic,

    I'm the IT guy ;-)... But I admit I didn't pay a lot of attention to our sun calendar server... It's an aging v6.2, maybe that's why I've never seen a syncml connector... ?


  • Frederic Pariente Monday, April 26, 2010

    Romain, I would point you to this forum :

    http://forums.sun.com/forum.jspa?forumID=737. I don't know myself enough about the product --I'm neither an admin nor a developer of the Sun Calendar-- to tell you how to set up a SyncML gateway for the Sun Calendar server. I just know it's possible b/c our IT guys have done it for our own installation. If you google "sun calendar syncml gateway", there are also some interesting links but again I do not know if this is what we Sun have in use. Good luck!


  • Romain Tuesday, April 27, 2010

    Fréderic : Thanks for pointing me this... It's seem there is no native support for SyncML in Sun calendar server.

    Although, there are third-parties connectors providing SyncML that might support WCAP backend... I might turn to developing an ActiveSync connector based on Zpush for WCAP.

    I don't give up on SyncML, I'll give a try to Funambol and maybe add a WCAP connector for it...


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.