Improve ical parser to read alarms with zero-values exported by Google (e.g. TRIGGER:-P0DT0H30M0S)

This commit is contained in:
Thomas Bruederli 2013-10-16 14:28:17 +02:00
parent 6dbbdba8a0
commit fbf3207dfb
4 changed files with 79 additions and 11 deletions

View file

@ -313,10 +313,16 @@ class libcalendaring extends rcube_plugin
*/
public static function parse_alaram_value($val)
{
if ($val[0] == '@')
if ($val[0] == '@') {
return array(substr($val, 1));
else if (preg_match('/([+-])P?T?(\d+)([HMSDW])/', $val, $m))
return array($m[2], $m[1].$m[3]);
}
else if (preg_match('/([+-])P?(T?\d+[HMSDW])+/', $val, $m) && preg_match_all('/T?(\d+)([HMSDW])/', $val, $m2, PREG_SET_ORDER)) {
foreach ($m2 as $seg) {
if ($seg[1] > 0) { // ignore zero values
return array($seg[1], $m[1].$seg[2], $m[1].$seg[1].$seg[2]);
}
}
}
return false;
}

View file

@ -115,10 +115,9 @@ class libvcalendar
try {
// estimate the memory usage and try to avoid fatal errors when allowed memory gets exhausted
$count = substr_count($vcal, 'BEGIN:VEVENT');
$memory_available = parse_bytes(ini_get('memory_limit')) - (function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024);
$expected_memory = $count * 70*1024; // assume ~ 70K per event (empirically determined)
if ($memory_available > 0 && $expected_memory > $memory_available) {
if (!rcube_utils::mem_check($expected_memory)) {
throw new Exception("iCal file too big");
}
@ -448,8 +447,8 @@ class libvcalendar
$trigger = '@' . $prop->getDateTime()->format('U');
}
}
if (!$trigger) {
$trigger = preg_replace('/PT?/', '', $prop->value);
if (!$trigger && ($values = libcalendaring::parse_alaram_value($prop->value))) {
$trigger = $values[2];
}
break;

View file

@ -139,15 +139,35 @@ class libvcalendar_test extends PHPUnit_Framework_TestCase
$this->assertEquals(2, count($rrule['EXDATE']), "Recurrence EXDATEs");
$this->assertInstanceOf('DateTime', $rrule['EXDATE'][0], "Recurrence EXDATE as DateTime");
// alarms
// categories, class
$this->assertEquals('libcalendaring tests', join(',', (array)$event['categories']), "Event categories");
$this->assertEquals('confidential', $event['sensitivity'], "Class/sensitivity = confidential");
}
/**
* @depends test_import_from_file
*/
function test_alarms()
{
$ical = new libvcalendar();
$events = $ical->import_from_file(__DIR__ . '/resources/recurring.ics', 'UTF-8');
$event = $events[0];
$this->assertEquals('-12H:DISPLAY', $event['alarms'], "Serialized alarms string");
$alarm = libcalendaring::parse_alaram_value($event['alarms']);
$this->assertEquals('12', $alarm[0], "Alarm value");
$this->assertEquals('-H', $alarm[1], "Alarm unit");
// categories, class
$this->assertEquals('libcalendaring tests', join(',', (array)$event['categories']), "Event categories");
$this->assertEquals('confidential', $event['sensitivity'], "Class/sensitivity = confidential");
// alarm trigger with 0 values
$events = $ical->import_from_file(__DIR__ . '/resources/alarms.ics', 'UTF-8');
$event = $events[0];
$this->assertEquals('-30M:DISPLAY', $event['alarms'], "Stripped alarm string");
$alarm = libcalendaring::parse_alaram_value($event['alarms']);
$this->assertEquals('30', $alarm[0], "Alarm value");
$this->assertEquals('-M', $alarm[1], "Alarm unit");
$this->assertEquals('-30M', $alarm[2], "Alarm string");
}
/**

View file

@ -0,0 +1,43 @@
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Apple Inc.//iCal 5.0.3//EN
CALSCALE:GREGORIAN
BEGIN:VTIMEZONE
TZID:Europe/Zurich
BEGIN:DAYLIGHT
TZOFFSETFROM:+0100
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
DTSTART:19810329T020000
TZNAME:CEST
TZOFFSETTO:+0200
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:+0200
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
DTSTART:19961027T030000
TZNAME:CET
TZOFFSETTO:+0100
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
UID:1dq52u617gkfqrr4uo1i2uh70
CREATED:20130924T221822Z
DESCRIPTION:
DTSTART:20130818T230000Z
DTEND:20130819T010000Z
DTSTAMP:20130824T235608Z
LAST-MODIFIED:20130924T222118Z
LOCATION:
SEQUENCE:2
STATUS:CONFIRMED
SUMMARY:Alarms test
TRANSP:OPAQUE
BEGIN:VALARM
ACTION:DISPLAY
DESCRIPTION:This is an event reminder
TRIGGER:-P0DT0H30M0S
END:VALARM
END:VEVENT
END:VCALENDAR