diff --git a/plugins/libcalendaring/libcalendaring.php b/plugins/libcalendaring/libcalendaring.php index 47cf67e8..05465b06 100644 --- a/plugins/libcalendaring/libcalendaring.php +++ b/plugins/libcalendaring/libcalendaring.php @@ -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; } diff --git a/plugins/libcalendaring/libvcalendar.php b/plugins/libcalendaring/libvcalendar.php index 24781c93..245f8194 100644 --- a/plugins/libcalendaring/libvcalendar.php +++ b/plugins/libcalendaring/libvcalendar.php @@ -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; diff --git a/plugins/libcalendaring/tests/libvcalendar.php b/plugins/libcalendaring/tests/libvcalendar.php index 34044736..4bb79411 100644 --- a/plugins/libcalendaring/tests/libvcalendar.php +++ b/plugins/libcalendaring/tests/libvcalendar.php @@ -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"); } /** diff --git a/plugins/libcalendaring/tests/resources/alarms.ics b/plugins/libcalendaring/tests/resources/alarms.ics new file mode 100644 index 00000000..a9d7b195 --- /dev/null +++ b/plugins/libcalendaring/tests/resources/alarms.ics @@ -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