Handle multiple VCALENDAR blocks when reading ics files (#2884)

This commit is contained in:
Thomas Bruederli 2014-02-28 12:41:31 +01:00
parent 5602b5f3cd
commit 1ef785c8c6
3 changed files with 123 additions and 12 deletions

View file

@ -48,6 +48,7 @@ class libvcalendar implements Iterator
private $iteratorkey = 0;
private $charset;
private $forward_exceptions;
private $vhead;
private $fp;
public $method;
@ -101,6 +102,7 @@ class libvcalendar implements Iterator
*/
public function reset()
{
$this->vhead = '';
$this->method = '';
$this->objects = array();
$this->freebusy = array();
@ -202,16 +204,7 @@ class libvcalendar implements Iterator
return false;
}
// read vcalendar header (with timezone defintion)
$this->vhead = '';
fseek($this->fp, 0);
while (($line = fgets($this->fp, 512)) !== false) {
if (preg_match('/BEGIN:(VEVENT|VTODO|VFREEBUSY)/i', $line))
break;
$this->vhead .= $line;
}
fseek($this->fp, -strlen($line), SEEK_CUR);
return $this->_parse_next();
}
@ -269,12 +262,33 @@ class libvcalendar implements Iterator
private function _next_component()
{
$buffer = '';
$vcalendar_head = false;
while (($line = fgets($this->fp, 1024)) !== false) {
// ignore END:VCALENDAR lines
if (preg_match('/END:VCALENDAR/i', $line)) {
continue;
}
// read vcalendar header (with timezone defintion)
if (preg_match('/BEGIN:VCALENDAR/i', $line)) {
$this->vhead = '';
$vcalendar_head = true;
}
// end of VCALENDAR header part
if ($vcalendar_head && preg_match('/BEGIN:(VEVENT|VTODO|VFREEBUSY)/i', $line)) {
$vcalendar_head = false;
}
if ($vcalendar_head) {
$this->vhead .= $line;
}
else {
$buffer .= $line;
if (preg_match('/END:(VEVENT|VTODO|VFREEBUSY)/i', $line)) {
break;
}
}
}
return $buffer;
}

View file

@ -74,6 +74,23 @@ class libvcalendar_test extends PHPUnit_Framework_TestCase
$this->assertEmpty($events);
}
/**
* Test parsing from files with multiple VCALENDAR blocks (#2884)
*/
function test_import_from_file_multiple()
{
$ical = new libvcalendar();
$ical->fopen(__DIR__ . '/resources/multiple-rdate.ics', 'UTF-8');
$events = array();
foreach ($ical as $event) {
$events[] = $event;
}
$this->assertEquals(2, count($events));
$this->assertEquals("AAAA6A8C3CCE4EE2C1257B5C00FFFFFF-Lotus_Notes_Generated", $events[0]['uid']);
$this->assertEquals("AAAA1C572093EC3FC125799C004AFFFF-Lotus_Notes_Generated", $events[1]['uid']);
}
function test_invalid_dates()
{
$ical = new libvcalendar();

View file

@ -0,0 +1,80 @@
BEGIN:VCALENDAR
X-LOTUS-CHARSET:UTF-8
VERSION:2.0
PRODID:-//Lotus Development Corporation//NONSGML Notes 8.5.3//EN_C
METHOD:PUBLISH
BEGIN:VTIMEZONE
TZID:W. Europe
BEGIN:STANDARD
DTSTART:19501029T020000
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=-1SU;BYMONTH=10
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19500326T020000
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=-1SU;BYMONTH=3
END:DAYLIGHT
END:VTIMEZONE
BEGIN:VEVENT
DTSTART;TZID="W. Europe":20140520T040000
DTEND;TZID="W. Europe":20140520T200000
TRANSP:TRANSPARENT
RDATE;VALUE=PERIOD:20140520T020000Z/20140520T180000Z
,PERIOD:20150520T020000Z/20150520T180000Z
,20160520T020000Z/20160520T180000Z,20170520T020000Z/20170520T180000Z
,20180520T020000Z/20180520T180000Z,20190520T020000Z/20190520T180000Z
,20200520T020000Z/20200520T180000Z,20210520T020000Z/20210520T180000Z
,20220520T020000Z/20220520T180000Z
DTSTAMP:20140227T123549Z
CLASS:PUBLIC
SUMMARY:Feiertag - Pfingsmontag
UID:AAAA6A8C3CCE4EE2C1257B5C00FFFFFF-Lotus_Notes_Generated
X-LOTUS-PARITAL-REPEAT:TRUE
X-LOTUS-NOTESVERSION:2
X-LOTUS-APPTTYPE:1
END:VEVENT
END:VCALENDAR
BEGIN:VCALENDAR
X-LOTUS-CHARSET:UTF-8
VERSION:2.0
PRODID:-//Lotus Development Corporation//NONSGML Notes 8.5.3//EN_C
METHOD:PUBLISH
BEGIN:VTIMEZONE
TZID:W. Europe
BEGIN:STANDARD
DTSTART:19501029T020000
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=-1SU;BYMONTH=10
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:19500326T020000
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
RRULE:FREQ=YEARLY;BYMINUTE=0;BYHOUR=2;BYDAY=-1SU;BYMONTH=3
END:DAYLIGHT
END:VTIMEZONE
BEGIN:VEVENT
DTSTART;TZID="W. Europe":20120330T040000
DTEND;TZID="W. Europe":20120330T200000
TRANSP:TRANSPARENT
RDATE;VALUE=PERIOD:20120330T020000Z/20120330T180000Z
,20130330T030000Z/20130330T190000Z,20140330T020000Z/20140330T180000Z
,20150330T020000Z/20150330T180000Z,20160330T020000Z/20160330T180000Z
,20170330T020000Z/20170330T180000Z,20180330T020000Z/20180330T180000Z
,20190330T030000Z/20190330T190000Z,20200330T020000Z/20200330T180000Z
,20210330T020000Z/20210330T180000Z
DTSTAMP:20140227T123547Z
CLASS:PUBLIC
SUMMARY:Another RDATE repeating event
UID:AAAA1C572093EC3FC125799C004AFFFF-Lotus_Notes_Generated
END:VEVENT
END:VCALENDAR