Roundcube Community Forum

Third Party Contributions => API Based Plugins => Topic started by: Naatan85 on April 13, 2010, 12:56:45 PM

Title: "Accept" vcal events (to google calendar) - Prototype (unsupported)
Post by: Naatan85 on April 13, 2010, 12:56:45 PM
Hi guys,

I just installed roundcube on my work pc a while ago cause I was getting sick of Thunderbird using 100mb+ memory and could not find a decent alternative. I have it setup to check exchange mail through imap but unfortunately it does not integrate with meeting invitations.

So I made a very simple plugin that will detect vcal elements in e-mails and show a "Add to google calendar" link at the bottom of the e-mail.

Note that this should really be considered a prototype, I am absolutely certain there are better ways to go about this but I just wanted something simple that would work for me. I am sharing this so that someone that does have the time can pick it up and turn it into something nice.

To install create a folder called vcal_gcal in your plugins folder and create a new file inside it called vcal_gcal.php with the following contents:


/**
 * "Accept" vcal events and send them to google calendar
 *
 * @version 0.1 Alpha
 * @author Nathan Rijksen
 * @website http://roundcube.net
 */
class vcal_gcal extends rcube_plugin {
public $task = 'mail';
private $event = null;
private $subject = 'Generic';

function init() {
$this->task = 'mail';
$this->add_hook('message_load', array($this, 'scan'));
$this->add_hook('message_part_after', array($this, 'put'));

$this->register_action('plugin.gcal_vcal', array($this, 'request_handler'));
}

function scan($msg) {
$c = 1;
$content = true;

while ($content!=null) {
$content = $msg['object']->get_part_content($c);

if (preg_match('/\(.*?)\<\/title\>/is',$content,$match))
$this->subject = $match[1];

if (strripos($content,'BEGIN:VCALENDAR')!==false)
$this->parse_event($content);
$c++;
}
}

function put($args) {
if ($this->event==null)
return null;

$data = array();
$data['body'] = strip_tags($args['body']);
if (strlen($data['body'])>1000)
$data['body'] = substr($data['body'],0,1000).' [...]';

$data['subject'] = $this->subject;
$data['start'] = $this->event['DTSTARTTZID'];
$data['end'] = $this->event['DTENDTZID'];

$data = strtr(base64_encode(addslashes(gzcompress(serialize($data),9))), '+/=', '-_,');

$args['body'] .= '

Add this event to google calendar

';

return $args;
}
 
function parse_event($vcal_raw) {
$vcal_bits = explode("\n",$vcal_raw);
$event = array();

foreach ($vcal_bits AS $bit) {
$bit_e = explode(':',$bit);

if (count($bit_e)<2)
continue;

$bit_e[0] = str_replace(';','',$bit_e[0]);
$bit_e[0] = preg_replace('/([a-z]+).*/is','$1',$bit_e[0]);

$event[$bit_e[0]] = $bit_e[1];
}

$this->event = $event;
}

function request_handler() {
$data = unserialize(gzuncompress(stripslashes(base64_decode(strtr($_GET['data'], '-_,', '+/=')))));

if ($data==false) return false;

$date_start = strtotime($data['start']);
$date_end = strtotime($data['end']);

$startDate = date('Y-m-d',$date_start);
$startTime = date('H:i',$date_start);
$endDate = date('Y-m-d',$date_end);
$endTime = date('H:i',$date_end);
$tzOffset = '-05';

$subject = $data['subject'];
$body = $data['body'];

// Zend SUCKS - thanks google for forcing me to use this ..
$old_inc = get_include_path();
set_include_path(dirname(__FILE__));

require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_AuthSub');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Calendar');

if (!isset($_GET['token']))
return $this->login_google();

$token = Zend_Gdata_AuthSub::getAuthSubSessionToken($_GET['token']);
$client = Zend_Gdata_AuthSub::getHttpClient($token);

$gdataCal = new Zend_Gdata_Calendar($client);
$newEvent = $gdataCal->newEventEntry();

$newEvent->title = $gdataCal->newTitle($subject);
$newEvent->content = $gdataCal->newContent($body);

$when = $gdataCal->newWhen();

$when->startTime = "{$startDate}T{$startTime}:00.000{$tzOffset}:00";
$when->endTime = "{$endDate}T{$endTime}:00.000{$tzOffset}:00";

$newEvent->when = array($when);

// Upload the event to the calendar server
// A copy of the event as it is recorded on the server is returned
$createdEvent = $gdataCal->insertEvent($newEvent);

set_include_path($old_inc);

die('Added to calendar');
}

function login_google() {
$next = $this->getCurrentUrl();
$scope = 'http://www.google.com/calendar/feeds/';
$secure = false;
$session = true;
$url = Zend_Gdata_AuthSub::getAuthSubTokenUri($next, $scope, $secure,
$session);
header('Location: '.$url);
}

function getCurrentUrl() {
$pageURL = 'http';
if ($_SERVER["HTTPS] == "on") {$pageURL .= "s";}
$pageURL .= "://";
if ($_SERVER["SERVER_PORT"] != "80") {
$pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
} else {
$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
}
return $pageURL;
}

}


Then create a folder inside vcal_gcal and call it Zedge. Download the following: Zend Framework: Downloads: Downloads (http://framework.zend.com/download/gdata). Extract in the Zedge folder.

Enable the plugin and you're done (note that it won't work for e-mails that have been cached prior to this plugin being enabled).

Again this is a very simplistic script that does exactly what it had to do for me to be usable and is by no means production ready.. I am just sharing it so that other devs may benefit from it.