THIS IS STILL EXPERIMENTAL CODE do not use in production. * @note this script is supposed to be at: egw-root/icalsrv.php * * @version 0.9.08-R1 initial version for icalsrv as egw application * @date 20060318 * @author Jan van Lieshout Rewrite and extension for egw 1.2. * $Id$ * (see: @url http://www.egroupware.org ) * * Based on some code from: * @author RalfBecker@outdoor-training.de (some original code base) * @author bbeckmann (at) optaros.com (some modificationas) * @author l.tulipan (at) mpwi.at (Additional Modifications for egw 1.2). * * license:
* This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * @since 0.9.06 collect all (todos via query filter iso just 15) * @since 0.9.00 use of the new egwical class for iCalendar handling with WURH * TODO list: * @todo incorporate this icalsrv.php script in * standard egroupware access url, via a setup routine or so. * @todo make this 'ical-service' enabled/disabled from the egw * admin interface * @todo make some parameters of this 'ical-service' interface user * specific configurable, for example the vevent and vtodo export * period (define search filters..) or overwrite or duplicate mode * etc. * @todo for ical GET: get the agent name from the http header * and use to set the ical product field when exporting. * @warning the current calendar filter will export only events in the period * from one month ago till one year ahead. * @warning all and only those events and todos are exported that you have access to * according to the default calendar and infolog settings (is this correct Ralf?) */ $logdir = false; // set to false for no logging #$logdir = '/tmp'; // set to a valid (writable) directory to get log file generation # WHY THIS? IS IT NEEDED? $GLOBALS['egw_info'] = array('flags' => array('currentapp' => 'calendar', 'noheader' => True, 'nofooter' => True, ),); $GLOBALS['egw_info']['flags']['currentapp'] = 'login'; $GLOBALS['egw_info']['flags']['noapi'] = True; include ('./header.inc.php'); include ('./phpgwapi/inc/functions.inc.php'); $GLOBALS['egw_info']['flags']['currentapp'] = 'calendar'; // oke there we go ..... // exit on non authenticated http request if ((!isset($_SERVER['PHP_AUTH_USER'])) || (!$GLOBALS['egw']->auth->authenticate($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']))) { header('WWW-Authenticate: Basic realm="ICal Server"'); header('HTTP/1.1 401 Unauthorized'); exit; } $user = $GLOBALS['egw']->accounts->name2id($_SERVER['PHP_AUTH_USER']); $pw = $GLOBALS['egw']->preferences->account_id = $user; # WHY THIS? IS IT NEEDED? $GLOBALS['egw_info']['user']['preferences'] = $GLOBALS['egw']->preferences->read_repository(); $GLOBALS['egw_info']['user']['account_id'] = $user; $GLOBALS['egw_info']['user']['account_lid'] = $_SERVER['PHP_AUTH_USER']; /* WARNING: * SET $euid_export ONLY TO TRUE IF YOU NEED IT TO USE THE EXPORTED ICAL INFO * SEPARATED FROM EGW, IN A CONTEXT WHERE IT ORIGINATED FROM. SO NORMALLY LEAVE IT * TO FALSE IF WANT TO USE YOUR CLIENT REGULARY (TO SUBSCRIBE/PUBLISH TO) WITH EGW */ $euid_export = false; /* select mode for importing the ical components, * safeMode=-1 -> allows new creation and deletion (in combi with $importMode = 'OVERWRITE') * 0 -> allow new creation and change, but no deletion? * WARNING: * USE safeMode = -1 WILL DELETE EXISTING events WHEN NO VALID ATTENDEES ARE * GIVEN IN THE RELATED ICAL IMPORTED VEVENT !! * ---!!! USE WITH CARE OR YOUR DATA GETS LOST!! --------- */ $safeMode = 0; $importMode = 'OVERWRITE'; // OVERWRITE or DUPLICATE $logmsg = ""; // IO-0 setup an Egwical object, and add a Calendar and a Infolog Resource // these will do all the work $ei =& CreateObject('egwical.egwical'); // for free an Horde_iCalendar object that we may use to collect or convert ical elements $hIcal = $ei->hi; $boc =& CreateObject('calendar.bocalupdate'); $binf =& CreateObject('infolog.boinfolog'); //calendar_vevents_handler: this will allow $ei to convert events<->vevents and // store and retrieve them from the egw db $cvehnd = $ei->addRsc($boc); //infolog_vtodos_handler: this will allow $ei to convert tasks<->vtodos and // store and retrieve them from the egw db $ivthnd = $ei->addRsc($binf); // oke now process the http request... if ($_SERVER['REQUEST_METHOD'] == 'PUT') { // *** PUT Request so do an Import ************* // I0 read the payload $logmsg = 'IMPORTING in '. $importMode . ' mode'; $fpput = fopen("php://input", "r"); $putData = ""; while ($data = fread($fpput, 1024)) $putData .= $data; fclose($fpput); // I1: parse $putData using the egwical builtin ical parser $hIcal =& $ei->parsevCalendar($putData); if(!$hIcal){ $msg ="icalsrv.php: error parsing iCal import data"; fail_exit($msg); } $logmsg .= "\n parsed iCalendar data:" . count($hIcal->_components) . " components found"; // I2: now import possibly found VEVENTS into eGW calendar $vcnt = $cvehnd->importVEventsFromIcal($hIcal, $importMode, $safeMode); if($vcnt === false){ $msg = 'icalsrv.php: VEVENTS import: ERRORS'; fail_exit($msg); } else{ $logmsg .= "\n imported " . $vcnt ." VEVENTS: OK"; } // I3: now import possibly found VTODOS into eGW calendar $tcnt = $ivthnd->importVTodosFromIcal($hIcal, $importMode); if ($tcnt === false){ $msg = 'icalsrv.php: VTODOS import: ERRORS'; fail_exit($msg); } $logmsg .= "\n imported " . $tcnt . " VTODOS: OK "; if($logdir) log_ical($logmsg,"import",$putData); } else { // *** GET (or POST?) Request $logmsg = 'EXPORTING'; // Get events from 3 years (last year, current, next), rather silly.. */ $last_year = date("Y")-1; $next_year = date("Y")+1; // until it is configurable we do 1 month back and 1 year ahead $evq_start = date('Ymd',time()-2678400); $evq_end = date('Ymd',time()+65000000); // E1.1: get period to be exported for events // For productivity this should be user configurable e.g. to be set via some sort of user // preferences to be set via eGW. (config remote-iCalendar...) $events_query = array('start' => $evq_start, 'end' => $evq_end, 'filter' => 'all', 'enum_recuring' => false, 'daywise' => false, 'owner' => $GLOBALS['egw_info']['user']['account_id'], // timestamp in server time for boical class 'date_format' => 'server' ); $todos = array(); // filter == my: entries user is responsible for, // filter == own: entries the user owns or is responsible for // order == id_parent: ... // order == info_datemodified: ... // todo add a filter to limit how far back entries from the past are retrieved $todos_query = array('col_filter' => array('type' => 'task'), 'filter' => 'my', 'order' => 'id_parent', 'sort' => 'DESC' ); // E2.1: search eGW events based on the $events_query $events = & $boc->search($events_query); if (!$events){ $logmsg .="\n no eGW events found to export"; // nevertheless fall through to further ical components export } else { $logmsg .= "\n found " . count($events) . " eGW events to export"; //E2.2 convert the found eGW events and add them to the iCal container $vcnt = $cvehnd->exportEventsOntoIcal($hIcal, $events, $euid_export); if($vcnt === false){ $msg = 'icalsrv.php: eGW to VEVENTS conversion: ERRORS'; fail_exit($msg); } else { $logmsg .= "\n exported the eGW events as " . $vcnt . " VEvents: OK "; } $bove = null; //destroy object } // E3.1: search eGW todos based on the $todos_query $todos =& $binf->search($todos_query); if (!$todos){ $logmsg .="\n no eGW todos found to export"; // nevertheless fall through to further ical components export } else { $logmsg .= "\n found " . count($todos) . " eGW todos to export"; //E3.2 convert the found eGW todos and add them to the iCal container $tcnt = $ivthnd->exportTodosOntoIcal($hIcal, $todos, $euid_export); if ($tcnt === false){ $msg = 'icalsrv.php: eGW to VTODOS conversion: ERRORS'; fail_exit($msg); } else { $logmsg .= "\n exported the eGW todos as " . $tcnt . " VTODOS: OK "; } $bovt = null; //destroy object } // E4.1: add good vcal header info to iCal object $hIcal->setAttribute('PRODID', '-//eGroupWare//NONSGML eGroupWare Calendar ' . $GLOBALS['egw_info']['apps']['calendar']['version'].'//' . strtoupper($GLOBALS['egw_info']['user']['preferences']['common']['lang'])); $hIcal->setAttribute('VERSION','2.0'); $hIcal->setAttribute('METHOD','PUBLISH'); // now let Horde stringify it and deliver as result $content = $hIcal->exportvCalendar(); echo $content; // DONE exporting if($logdir) log_ical($logmsg,"export",$content); } $GLOBALS['egw']->common->egw_exit(); // --- SOME UTILITY FUNCTIONS ------- /** * Exit with an error message in html * @param $msg string * message that gets return as html error description */ function fail_exit($msg){ // log the error in the http server error logging files error_log($msg); // return http error 403 can this be done this way? header('HTTP/1.1 403' . $msg); $GLOBALS['egw']->common->egw_exit(); } /* * Log info and data to logfiles if logging is set * * @param $msg string with loginfo * @param $data data to be logged * @param $icalmethod $string value can be import or export * @global $logdir string/boolean log directory. Set to false to disab logging */ function log_ical($msg,$icalmethod="data",$data){ global $logdir; if (!$logdir) return; // loggin seems off // some info used for logging $logstamp = date("U"); $loguser = $_SERVER['PHP_AUTH_USER']; $logdate = date("Ymd:His"); // filename for log info, only used when logging is on $fnloginfo = "$logdir/ical.log"; // log info $fnlogdata = $logdir . "/ical." . $icalmethod . '.' . $logstamp . ".ics"; $fp = fopen("$fnloginfo",'a+'); fwrite($fp,"\n\n$loguser on $logdate : $msg, \n data in $fnlogdata "); fclose($fp); // log data $fp = fopen("$fnlogdata", "w"); fputs($fp, $data); fclose($fp); } ?>