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) public static function parse_alaram_value($val)
{ {
if ($val[0] == '@') if ($val[0] == '@') {
return array(substr($val, 1)); 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; return false;
} }

View file

@ -115,10 +115,9 @@ class libvcalendar
try { try {
// estimate the memory usage and try to avoid fatal errors when allowed memory gets exhausted // estimate the memory usage and try to avoid fatal errors when allowed memory gets exhausted
$count = substr_count($vcal, 'BEGIN:VEVENT'); $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) $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"); throw new Exception("iCal file too big");
} }
@ -448,8 +447,8 @@ class libvcalendar
$trigger = '@' . $prop->getDateTime()->format('U'); $trigger = '@' . $prop->getDateTime()->format('U');
} }
} }
if (!$trigger) { if (!$trigger && ($values = libcalendaring::parse_alaram_value($prop->value))) {
$trigger = preg_replace('/PT?/', '', $prop->value); $trigger = $values[2];
} }
break; break;

View file

@ -139,15 +139,35 @@ class libvcalendar_test extends PHPUnit_Framework_TestCase
$this->assertEquals(2, count($rrule['EXDATE']), "Recurrence EXDATEs"); $this->assertEquals(2, count($rrule['EXDATE']), "Recurrence EXDATEs");
$this->assertInstanceOf('DateTime', $rrule['EXDATE'][0], "Recurrence EXDATE as DateTime"); $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"); $this->assertEquals('-12H:DISPLAY', $event['alarms'], "Serialized alarms string");
$alarm = libcalendaring::parse_alaram_value($event['alarms']); $alarm = libcalendaring::parse_alaram_value($event['alarms']);
$this->assertEquals('12', $alarm[0], "Alarm value"); $this->assertEquals('12', $alarm[0], "Alarm value");
$this->assertEquals('-H', $alarm[1], "Alarm unit"); $this->assertEquals('-H', $alarm[1], "Alarm unit");
// categories, class // alarm trigger with 0 values
$this->assertEquals('libcalendaring tests', join(',', (array)$event['categories']), "Event categories"); $events = $ical->import_from_file(__DIR__ . '/resources/alarms.ics', 'UTF-8');
$this->assertEquals('confidential', $event['sensitivity'], "Class/sensitivity = confidential"); $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