[kronolith] Script: Subscribe to Kronolith calendars with Apple iCal

John Adams jna at retina.net
Tue Feb 1 12:06:31 PST 2005


I think kronolith is pretty cool, but one of the major issues I have with 
the way that you export calendar records to iCal is that you have to keep 
logging in and exporting the data. I modified data.php and produced a 
script that will allow you to -subscribe- iCal to kronolith calendars. It 
dumps all events for the specified calendar in icalendar format.

Some caveats I found out the hard way: Apple iCal doesn't support pulling 
calendar data over SSL (lame!!!) so you have to run this on an unsecured 
server until they get around to fixing that. You should be okay with other 
apps like thunderbird/outlook/etc, though.

Granted, there's some security issues here - I've disabled authentication 
to view the calendars and I'm just dumping all events for the requested 
calendar, but you get the idea. You can modify this script to have some 
sort of md5 variable/security/whatever and then modify the URL to require 
that variable if you're concerned about security. For most users it won't 
matter. Hey, the data is read-only anyway, so don't panic too much ;)

Save this script as 'icalsub.php', and access data using the following URL:
http://your.server.com/horde/kronolith/icalsub.php/<id>

You can also subscribe to multiple calendars and combine them as one like:
http://your.server.com/horde/kronolith/icalsub.php?c=<id1>|<id2>|<id3>

<id> should match the calendar_id in the database (you can get it 
also by looking at the "Free/busy" URL that appears in the "My Calendars" 
page.)

Enjoy. 

--john

--cut here--

<?php
/**
 * icalsub.php: subscribe to a calendar in kronolith as a subscription
 *
 * J. Adams <jna at retina.net>
 * 1/30/2005
 */

@define('AUTH_HANDLER', true);
@define('KRONOLITH_BASE', dirname(__FILE__));

require_once KRONOLITH_BASE . '/lib/base.php';
require_once 'Horde/Data.php';

if (!$conf['menu']['import_export']) {
    require KRONOLITH_BASE . '/index.php';
    exit;
}

/* Templates for the different import steps. */
$templates = array(
    IMPORT_FILE => array(KRONOLITH_TEMPLATES . '/data/import.inc', KRONOLITH_TEMPLATES . '/data/export.inc'),
    IMPORT_CSV => array($registry->get('templates', 'horde') . '/data/csvinfo.inc'),
    IMPORT_MAPPED => array($registry->get('templates', 'horde') . '/data/csvmap.inc'),
    IMPORT_DATETIME => array($registry->get('templates', 'horde') . '/data/datemap.inc')
);

/* Initial values. */
$actionID      = "export";
$next_step     = IMPORT_FILE;
$error         = false;

/* Loop through the action handlers. */

/* always get all events */
$start = null;
$end = null;

$events = array();

# apparently this is calendars to display; note support for multiple calendars here. 
if (!empty($_SERVER['PATH_INFO'])) {
    $cal = basename($_SERVER['PATH_INFO']);
} else {
    $cal = Util::getFormData('c');
    if (is_array($cal)) {
        $cal = implode('|', $cal);
    }
}

$kronolith->open($cal);
$events[$cal] = $kronolith->listEvents(null,null);

if (!count($events)) {
     print "no events.\n";
     exit;
} else {
     require_once 'Horde/Identity.php';
     require_once 'Horde/iCalendar.php';
     $iCal = &new Horde_iCalendar();
     
     foreach ($events as $cal => $calevents) {
          if ($kronolith->getCalendar() != $cal) {
               $kronolith->close();
               $kronolith->open($cal);
          }
          
          $identity = &$kronolith_shares->getIdentityByShare($kronolith_shares->getShare($cal));
          foreach ($calevents as $id) {
               $event = &$kronolith->getEvent($id);
               $iCal->addComponent($event->toiCalendar($iCal, $identity));
          }
     }
     $data = $iCal->exportvCalendar();
     $browser->downloadHeaders(_("events.ics"), 'text/calendar', false, strlen($data));
     echo $data;
     exit;
}

/* We have a final result set. */
if (is_array($next_step)) {
    $events = array();
    $kronolith->open($_SESSION['import_data']['import_cal']);
    $error = false;
    foreach ($next_step as $row) {
        $event = &$kronolith->getEvent();
        if (!$event || is_a($event, 'PEAR_Error')) {
            $msg = _("Can't create a new event.");
            if (is_a($event, 'PEAR_Error')) {
                $msg .= ' ' . sprintf(_("This is what the server said: %s"), $event->getMessage());
            }
            $notification->push($msg, 'horde.error');
            $error = true;
            break;
        }
        if (is_a($row, 'Horde_iCalendar_vevent')) {
            $event->fromiCalendar($row);
        } elseif (is_a($row, 'Horde_iCalendar')) {
            // Skip other iCalendar components for now.
            continue;
        } else {
            $event->fromHash($row);
        }

        $success = $event->save();
        if (is_a($success, 'PEAR_Error')) {
            $notification->push($success, 'horde.error');
            $error = true;
            break;
        }
    }
    if (!$error) {
        $notification->push(sprintf(_("%s file successfully imported"),
                                    
$file_types[$_SESSION['import_data']['format']]), 'horde.success');
    }
    $next_step = $data->cleanup();
}

$title = _("Import/Export Calendar");
require KRONOLITH_TEMPLATES . '/common-header.inc';
require KRONOLITH_TEMPLATES . '/menu.inc';

foreach ($templates[$next_step] as $template) {
    require $template;
}

require $registry->get('templates', 'horde') . '/common-footer.inc';
?>




More information about the kronolith mailing list