From 78547e8c683410730b8305ca024b136e052c61a2 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Tue, 15 Oct 2024 22:00:33 +0200 Subject: [PATCH] Resolve #1806 --- .../app/libraries/Sabre/VObject/Component.php | 3 +- .../Sabre/VObject/Component/VAlarm.php | 8 +- .../Sabre/VObject/Component/VCalendar.php | 150 +++++----- .../Sabre/VObject/Component/VCard.php | 2 +- .../Sabre/VObject/Component/VTodo.php | 2 +- .../Sabre/VObject/DateTimeParser.php | 16 +- .../app/libraries/Sabre/VObject/Document.php | 10 +- .../Sabre/VObject/FreeBusyGenerator.php | 4 +- .../libraries/Sabre/VObject/ITip/Broker.php | 30 +- .../libraries/Sabre/VObject/Parser/Json.php | 2 +- .../Sabre/VObject/Parser/MimeDir.php | 8 +- .../app/libraries/Sabre/VObject/Property.php | 24 +- .../VObject/Property/ICalendar/DateTime.php | 4 +- .../VObject/Property/ICalendar/Recur.php | 9 +- .../libraries/Sabre/VObject/Property/Text.php | 2 +- .../Sabre/VObject/Recur/EventIterator.php | 2 +- .../Sabre/VObject/Recur/RRuleIterator.php | 89 +++++- .../Sabre/VObject/Splitter/ICalendar.php | 2 +- .../Sabre/VObject/Splitter/VCard.php | 2 +- .../libraries/Sabre/VObject/TimeZoneUtil.php | 4 +- .../Sabre/VObject/VCardConverter.php | 14 +- .../VObject/timezonedata/windowszones.php | 276 +++++++++--------- .../libraries/Sabre/Xml/ContextStackTrait.php | 2 +- .../0.0.0/app/libraries/Sabre/Xml/Service.php | 22 +- .../0.0.0/app/libraries/Sabre/Xml/Version.php | 2 +- .../0.0.0/app/libraries/Sabre/Xml/Writer.php | 2 +- 26 files changed, 403 insertions(+), 288 deletions(-) diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component.php index da2c5ebd4..95bde3d40 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component.php @@ -2,7 +2,6 @@ namespace Sabre\VObject; -use Sabre\VObject; use Sabre\Xml; /** @@ -15,7 +14,7 @@ use Sabre\Xml; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License * - * @property VObject\Property\FlatText UID + * @property Property\FlatText UID */ class Component extends Node { diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component/VAlarm.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component/VAlarm.php index 3e5797b0a..abe61768e 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component/VAlarm.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component/VAlarm.php @@ -39,13 +39,7 @@ class VAlarm extends VObject\Component /** @var VEvent|VTodo $parentComponent */ $parentComponent = $this->parent; if ('START' === $related) { - if ('VTODO' === $parentComponent->name) { - $propName = 'DUE'; - } else { - $propName = 'DTSTART'; - } - - $effectiveTrigger = $parentComponent->$propName->getDateTime(); + $effectiveTrigger = $parentComponent->DTSTART->getDateTime(); } else { if ('VTODO' === $parentComponent->name) { $endProp = 'DUE'; diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component/VCalendar.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component/VCalendar.php index b317e02c8..7b6e66e88 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component/VCalendar.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component/VCalendar.php @@ -20,8 +20,8 @@ use Sabre\VObject\Recur\NoInstancesException; * * @property VEvent VEVENT * @property VJournal VJOURNAL - * @property VObject\Property\Text ORG - * @property VObject\Property\FlatText METHOD + * @property Property\Text ORG + * @property Property\FlatText METHOD */ class VCalendar extends VObject\Document { @@ -51,21 +51,21 @@ class VCalendar extends VObject\Document * List of value-types, and which classes they map to. */ public static array $valueMap = [ - 'BINARY' => VObject\Property\Binary::class, - 'BOOLEAN' => VObject\Property\Boolean::class, - 'CAL-ADDRESS' => VObject\Property\ICalendar\CalAddress::class, - 'DATE' => VObject\Property\ICalendar\Date::class, - 'DATE-TIME' => VObject\Property\ICalendar\DateTime::class, - 'DURATION' => VObject\Property\ICalendar\Duration::class, - 'FLOAT' => VObject\Property\FloatValue::class, - 'INTEGER' => VObject\Property\IntegerValue::class, - 'PERIOD' => VObject\Property\ICalendar\Period::class, - 'RECUR' => VObject\Property\ICalendar\Recur::class, - 'TEXT' => VObject\Property\Text::class, - 'TIME' => VObject\Property\Time::class, - 'UNKNOWN' => VObject\Property\Unknown::class, // jCard / jCal-only. - 'URI' => VObject\Property\Uri::class, - 'UTC-OFFSET' => VObject\Property\UtcOffset::class, + 'BINARY' => Property\Binary::class, + 'BOOLEAN' => Property\Boolean::class, + 'CAL-ADDRESS' => Property\ICalendar\CalAddress::class, + 'DATE' => Property\ICalendar\Date::class, + 'DATE-TIME' => Property\ICalendar\DateTime::class, + 'DURATION' => Property\ICalendar\Duration::class, + 'FLOAT' => Property\FloatValue::class, + 'INTEGER' => Property\IntegerValue::class, + 'PERIOD' => Property\ICalendar\Period::class, + 'RECUR' => Property\ICalendar\Recur::class, + 'TEXT' => Property\Text::class, + 'TIME' => Property\Time::class, + 'UNKNOWN' => Property\Unknown::class, // jCard / jCal-only. + 'URI' => Property\Uri::class, + 'UTC-OFFSET' => Property\UtcOffset::class, ]; /** @@ -73,78 +73,78 @@ class VCalendar extends VObject\Document */ public static array $propertyMap = [ // Calendar properties - 'CALSCALE' => VObject\Property\FlatText::class, - 'METHOD' => VObject\Property\FlatText::class, - 'PRODID' => VObject\Property\FlatText::class, - 'VERSION' => VObject\Property\FlatText::class, + 'CALSCALE' => Property\FlatText::class, + 'METHOD' => Property\FlatText::class, + 'PRODID' => Property\FlatText::class, + 'VERSION' => Property\FlatText::class, // Component properties - 'ATTACH' => VObject\Property\Uri::class, - 'CATEGORIES' => VObject\Property\Text::class, - 'CLASS' => VObject\Property\FlatText::class, - 'COMMENT' => VObject\Property\FlatText::class, - 'DESCRIPTION' => VObject\Property\FlatText::class, - 'GEO' => VObject\Property\FloatValue::class, - 'LOCATION' => VObject\Property\FlatText::class, - 'PERCENT-COMPLETE' => VObject\Property\IntegerValue::class, - 'PRIORITY' => VObject\Property\IntegerValue::class, - 'RESOURCES' => VObject\Property\Text::class, - 'STATUS' => VObject\Property\FlatText::class, - 'SUMMARY' => VObject\Property\FlatText::class, + 'ATTACH' => Property\Uri::class, + 'CATEGORIES' => Property\Text::class, + 'CLASS' => Property\FlatText::class, + 'COMMENT' => Property\FlatText::class, + 'DESCRIPTION' => Property\FlatText::class, + 'GEO' => Property\FloatValue::class, + 'LOCATION' => Property\FlatText::class, + 'PERCENT-COMPLETE' => Property\IntegerValue::class, + 'PRIORITY' => Property\IntegerValue::class, + 'RESOURCES' => Property\Text::class, + 'STATUS' => Property\FlatText::class, + 'SUMMARY' => Property\FlatText::class, // Date and Time Component Properties - 'COMPLETED' => VObject\Property\ICalendar\DateTime::class, - 'DTEND' => VObject\Property\ICalendar\DateTime::class, - 'DUE' => VObject\Property\ICalendar\DateTime::class, - 'DTSTART' => VObject\Property\ICalendar\DateTime::class, - 'DURATION' => VObject\Property\ICalendar\Duration::class, - 'FREEBUSY' => VObject\Property\ICalendar\Period::class, - 'TRANSP' => VObject\Property\FlatText::class, + 'COMPLETED' => Property\ICalendar\DateTime::class, + 'DTEND' => Property\ICalendar\DateTime::class, + 'DUE' => Property\ICalendar\DateTime::class, + 'DTSTART' => Property\ICalendar\DateTime::class, + 'DURATION' => Property\ICalendar\Duration::class, + 'FREEBUSY' => Property\ICalendar\Period::class, + 'TRANSP' => Property\FlatText::class, // Time Zone Component Properties - 'TZID' => VObject\Property\FlatText::class, - 'TZNAME' => VObject\Property\FlatText::class, - 'TZOFFSETFROM' => VObject\Property\UtcOffset::class, - 'TZOFFSETTO' => VObject\Property\UtcOffset::class, - 'TZURL' => VObject\Property\Uri::class, + 'TZID' => Property\FlatText::class, + 'TZNAME' => Property\FlatText::class, + 'TZOFFSETFROM' => Property\UtcOffset::class, + 'TZOFFSETTO' => Property\UtcOffset::class, + 'TZURL' => Property\Uri::class, // Relationship Component Properties - 'ATTENDEE' => VObject\Property\ICalendar\CalAddress::class, - 'CONTACT' => VObject\Property\FlatText::class, - 'ORGANIZER' => VObject\Property\ICalendar\CalAddress::class, - 'RECURRENCE-ID' => VObject\Property\ICalendar\DateTime::class, - 'RELATED-TO' => VObject\Property\FlatText::class, - 'URL' => VObject\Property\Uri::class, - 'UID' => VObject\Property\FlatText::class, + 'ATTENDEE' => Property\ICalendar\CalAddress::class, + 'CONTACT' => Property\FlatText::class, + 'ORGANIZER' => Property\ICalendar\CalAddress::class, + 'RECURRENCE-ID' => Property\ICalendar\DateTime::class, + 'RELATED-TO' => Property\FlatText::class, + 'URL' => Property\Uri::class, + 'UID' => Property\FlatText::class, // Recurrence Component Properties - 'EXDATE' => VObject\Property\ICalendar\DateTime::class, - 'RDATE' => VObject\Property\ICalendar\DateTime::class, - 'RRULE' => VObject\Property\ICalendar\Recur::class, - 'EXRULE' => VObject\Property\ICalendar\Recur::class, // Deprecated since rfc5545 + 'EXDATE' => Property\ICalendar\DateTime::class, + 'RDATE' => Property\ICalendar\DateTime::class, + 'RRULE' => Property\ICalendar\Recur::class, + 'EXRULE' => Property\ICalendar\Recur::class, // Deprecated since rfc5545 // Alarm Component Properties - 'ACTION' => VObject\Property\FlatText::class, - 'REPEAT' => VObject\Property\IntegerValue::class, - 'TRIGGER' => VObject\Property\ICalendar\Duration::class, + 'ACTION' => Property\FlatText::class, + 'REPEAT' => Property\IntegerValue::class, + 'TRIGGER' => Property\ICalendar\Duration::class, // Change Management Component Properties - 'CREATED' => VObject\Property\ICalendar\DateTime::class, - 'DTSTAMP' => VObject\Property\ICalendar\DateTime::class, - 'LAST-MODIFIED' => VObject\Property\ICalendar\DateTime::class, - 'SEQUENCE' => VObject\Property\IntegerValue::class, + 'CREATED' => Property\ICalendar\DateTime::class, + 'DTSTAMP' => Property\ICalendar\DateTime::class, + 'LAST-MODIFIED' => Property\ICalendar\DateTime::class, + 'SEQUENCE' => Property\IntegerValue::class, // Request Status - 'REQUEST-STATUS' => VObject\Property\Text::class, + 'REQUEST-STATUS' => Property\Text::class, // Additions from draft-daboo-valarm-extensions-04 - 'ALARM-AGENT' => VObject\Property\Text::class, - 'ACKNOWLEDGED' => VObject\Property\ICalendar\DateTime::class, - 'PROXIMITY' => VObject\Property\Text::class, - 'DEFAULT-ALARM' => VObject\Property\Boolean::class, + 'ALARM-AGENT' => Property\Text::class, + 'ACKNOWLEDGED' => Property\ICalendar\DateTime::class, + 'PROXIMITY' => Property\Text::class, + 'DEFAULT-ALARM' => Property\Boolean::class, // Additions from draft-daboo-calendar-availability-05 - 'BUSYTYPE' => VObject\Property\Text::class, + 'BUSYTYPE' => Property\Text::class, ]; /** @@ -166,10 +166,10 @@ class VCalendar extends VObject\Document * * @return VObject\Component[] */ - public function getBaseComponents(string $componentName = null): array + public function getBaseComponents(?string $componentName = null): array { $isBaseComponent = function ($component): bool { - if (!$component instanceof VObject\Component) { + if (!$component instanceof Component) { return false; } if ('VTIMEZONE' === $component->name) { @@ -214,13 +214,11 @@ class VCalendar extends VObject\Document * If there is no such component, null will be returned. * * @param string|null $componentName filter by component name - * - * @return VObject\Component|null */ - public function getBaseComponent(string $componentName = null): ?Component + public function getBaseComponent(?string $componentName = null): ?Component { $isBaseComponent = function ($component): bool { - if (!$component instanceof VObject\Component) { + if (!$component instanceof Component) { return false; } if ('VTIMEZONE' === $component->name) { @@ -275,7 +273,7 @@ class VCalendar extends VObject\Document * @throws InvalidDataException * @throws VObject\Recur\MaxInstancesExceededException */ - public function expand(\DateTimeInterface $start, \DateTimeInterface $end, \DateTimeZone $timeZone = null): VCalendar + public function expand(\DateTimeInterface $start, \DateTimeInterface $end, ?\DateTimeZone $timeZone = null): VCalendar { $newChildren = []; $recurringEvents = []; diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component/VCard.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component/VCard.php index 81f78f422..9ec4c88cc 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component/VCard.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component/VCard.php @@ -82,7 +82,7 @@ class VCard extends VObject\Document 'ROLE' => VObject\Property\FlatText::class, 'LOGO' => VObject\Property\Binary::class, // 'AGENT' => 'Sabre\\VObject\\Property\\', // Todo: is an embedded vCard. Probably rare, so - // not supported at the moment + // not supported at the moment 'ORG' => VObject\Property\Text::class, 'NOTE' => VObject\Property\FlatText::class, 'REV' => VObject\Property\VCard\TimeStamp::class, diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component/VTodo.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component/VTodo.php index bda49da74..cab672ce5 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component/VTodo.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Component/VTodo.php @@ -104,7 +104,7 @@ class VTodo extends VObject\Component 'LAST-MODIFIED' => '?', 'LOCATION' => '?', 'ORGANIZER' => '?', - 'PERCENT' => '?', + 'PERCENT-COMPLETE' => '?', 'PRIORITY' => '?', 'RECURRENCE-ID' => '?', 'SEQUENCE' => '?', diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/DateTimeParser.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/DateTimeParser.php index 8dbb6cfdb..e8777b7fe 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/DateTimeParser.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/DateTimeParser.php @@ -27,7 +27,7 @@ class DateTimeParser * * @throws InvalidDataException */ - public static function parseDateTime(string $dt, \DateTimeZone $tz = null): \DateTimeImmutable + public static function parseDateTime(string $dt, ?\DateTimeZone $tz = null): \DateTimeImmutable { // Format is YYYYMMDD + "T" + hhmmss $result = preg_match('/^([0-9]{4})([0-1][0-9])([0-3][0-9])T([0-2][0-9])([0-5][0-9])([0-5][0-9])([Z]?)$/', $dt, $matches); @@ -54,7 +54,7 @@ class DateTimeParser * * @throws InvalidDataException */ - public static function parseDate(string $date, \DateTimeZone $tz = null): \DateTimeImmutable + public static function parseDate(string $date, ?\DateTimeZone $tz = null): \DateTimeImmutable { // Format is YYYYMMDD $result = preg_match('/^([0-9]{4})([0-1][0-9])([0-3][0-9])$/', $date, $matches); @@ -98,12 +98,12 @@ class DateTimeParser } $parts = [ - 'week', - 'day', - 'hour', - 'minute', - 'second', - ]; + 'week', + 'day', + 'hour', + 'minute', + 'second', + ]; foreach ($parts as $part) { $matches[$part] = isset($matches[$part]) && $matches[$part] ? (int) $matches[$part] : 0; diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Document.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Document.php index b311987d7..02eaf13c7 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Document.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Document.php @@ -2,8 +2,6 @@ namespace Sabre\VObject; -use Sabre\VObject; - /** * Document. * @@ -18,7 +16,7 @@ use Sabre\VObject; * @author Evert Pot (http://evertpot.com/) * @license http://sabre.io/license/ Modified BSD License * - * @property VObject\Property\FlatText VERSION + * @property Property\FlatText VERSION */ abstract class Document extends Component { @@ -140,7 +138,7 @@ abstract class Document extends Component * an iCalendar object, this may be something like CALSCALE:GREGORIAN. To * ensure that this does not happen, set $defaults to false. */ - public function createComponent(string $name, array $children = null, bool $defaults = true): Component + public function createComponent(string $name, ?array $children = null, bool $defaults = true): Component { $name = strtoupper($name); $class = Component::class; @@ -169,7 +167,7 @@ abstract class Document extends Component * * @throws InvalidDataException */ - public function createProperty(string $name, $value = null, array $parameters = null, string $valueType = null): Property + public function createProperty(string $name, $value = null, ?array $parameters = null, ?string $valueType = null, ?int $lineIndex = null, ?string $lineString = null): Property { // If there's a . in the name, it means it's prefixed by a group name. if (false !== ($i = strpos($name, '.'))) { @@ -203,7 +201,7 @@ abstract class Document extends Component $parameters = []; } - return new $class($this, $name, $value, $parameters, $group); + return new $class($this, $name, $value, $parameters, $group, $lineIndex, $lineString); } /** diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/FreeBusyGenerator.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/FreeBusyGenerator.php index 2f222e4e5..424826034 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/FreeBusyGenerator.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/FreeBusyGenerator.php @@ -72,7 +72,7 @@ class FreeBusyGenerator * Check the setTimeRange and setObjects methods for details about the * arguments. */ - public function __construct(\DateTimeInterface $start = null, \DateTimeInterface $end = null, $objects = null, \DateTimeZone $timeZone = null) + public function __construct(?\DateTimeInterface $start = null, ?\DateTimeInterface $end = null, $objects = null, ?\DateTimeZone $timeZone = null) { $this->setTimeRange($start, $end); @@ -138,7 +138,7 @@ class FreeBusyGenerator * * @throws \Exception */ - public function setTimeRange(\DateTimeInterface $start = null, \DateTimeInterface $end = null): void + public function setTimeRange(?\DateTimeInterface $start = null, ?\DateTimeInterface $end = null): void { if (!$start) { $start = new \DateTimeImmutable(Settings::$minDate); diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/ITip/Broker.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/ITip/Broker.php index f792fd990..76ee0c71e 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/ITip/Broker.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/ITip/Broker.php @@ -113,7 +113,7 @@ class Broker * @throws MaxInstancesExceededException * @throws NoInstancesException */ - public function processMessage(Message $itipMessage, VCalendar $existingObject = null) + public function processMessage(Message $itipMessage, ?VCalendar $existingObject = null) { // We only support events at the moment. if ('VEVENT' !== $itipMessage->component) { @@ -268,7 +268,7 @@ class Broker * This is message from an organizer, and is either a new event * invite, or an update to an existing one. */ - protected function processMessageRequest(Message $itipMessage, VCalendar $existingObject = null): ?VCalendar + protected function processMessageRequest(Message $itipMessage, ?VCalendar $existingObject = null): ?VCalendar { if (!$existingObject) { // This is a new invite, and we're just going to copy over @@ -296,7 +296,7 @@ class Broker * attendee got removed from an event, or an event got cancelled * altogether. */ - protected function processMessageCancel(Message $itipMessage, VCalendar $existingObject = null): ?VCalendar + protected function processMessageCancel(Message $itipMessage, ?VCalendar $existingObject = null): ?VCalendar { if (!$existingObject) { // The event didn't exist in the first place, so we're just @@ -321,7 +321,7 @@ class Broker * @throws MaxInstancesExceededException * @throws NoInstancesException */ - protected function processMessageReply(Message $itipMessage, VCalendar $existingObject = null): ?VCalendar + protected function processMessageReply(Message $itipMessage, ?VCalendar $existingObject = null): ?VCalendar { // A reply can only be processed based on an existing object. // If the object is not available, the reply is ignored. @@ -333,7 +333,10 @@ class Broker // Finding all the instances the attendee replied to. foreach ($itipMessage->message->VEVENT as $vevent) { - $recurId = isset($vevent->{'RECURRENCE-ID'}) ? $vevent->{'RECURRENCE-ID'}->getValue() : 'master'; + // Use the Unix timestamp returned by getTimestamp as a unique identifier for the recurrence. + // The Unix timestamp will be the same for an event, even if the reply from the attendee + // used a different format/timezone to express the event date-time. + $recurId = isset($vevent->{'RECURRENCE-ID'}) ? $vevent->{'RECURRENCE-ID'}->getDateTime()->getTimestamp() : 'master'; $attendee = $vevent->ATTENDEE; $instances[$recurId] = $attendee['PARTSTAT']->getValue(); if (isset($vevent->{'REQUEST-STATUS'})) { @@ -346,7 +349,8 @@ class Broker // all the instances where we have a reply for. $masterObject = null; foreach ($existingObject->VEVENT as $vevent) { - $recurId = isset($vevent->{'RECURRENCE-ID'}) ? $vevent->{'RECURRENCE-ID'}->getValue() : 'master'; + // Use the Unix timestamp returned by getTimestamp as a unique identifier for the recurrence. + $recurId = isset($vevent->{'RECURRENCE-ID'}) ? $vevent->{'RECURRENCE-ID'}->getDateTime()->getTimestamp() : 'master'; if ('master' === $recurId) { $masterObject = $vevent; } @@ -393,7 +397,10 @@ class Broker $newObject = $recurrenceIterator->getEventObject(); $recurrenceIterator->next(); - if (isset($newObject->{'RECURRENCE-ID'}) && $newObject->{'RECURRENCE-ID'}->getValue() === $recurId) { + // Compare the Unix timestamp returned by getTimestamp with the previously calculated timestamp. + // If they are the same, then this is a matching recurrence, even though its date-time may have + // been expressed in a different format/timezone. + if (isset($newObject->{'RECURRENCE-ID'}) && $newObject->{'RECURRENCE-ID'}->getDateTime()->getTimestamp() === $recurId) { $found = true; } --$iterations; @@ -496,10 +503,11 @@ class Broker $icalMsg->add(clone $timezone); } - if (!$attendee['newInstances']) { - // If there are no instances the attendee is a part of, it - // means the attendee was removed and we need to send him a - // CANCEL. + if (!$attendee['newInstances'] || 'CANCELLED' === $eventInfo['status']) { + // If there are no instances the attendee is a part of, it means + // the attendee was removed and we need to send them a CANCEL message. + // Also If the meeting STATUS property was changed to CANCELLED + // we need to send the attendee a CANCEL message. $message->method = 'CANCEL'; $icalMsg->METHOD = $message->method; diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Parser/Json.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Parser/Json.php index a732075d5..9729afe86 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Parser/Json.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Parser/Json.php @@ -131,7 +131,7 @@ class Json extends Parser list( $propertyName, $parameters, - $valueType + $valueType, ) = $jProp; $propertyName = strtoupper($propertyName); diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Parser/MimeDir.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Parser/MimeDir.php index bbef0ea6b..be5d87baf 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Parser/MimeDir.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Parser/MimeDir.php @@ -79,6 +79,12 @@ class MimeDir extends Parser $this->setInput($input); } + if (!\is_resource($this->input)) { + // Null was passed as input, but there was no existing input buffer + // There is nothing to parse. + throw new ParseException('No input provided to parse'); + } + if (0 !== $options) { $this->options = $options; } @@ -445,7 +451,7 @@ class MimeDir extends Parser } } - $propObj = $this->root->createProperty($property['name'], null, $namedParameters); + $propObj = $this->root->createProperty($property['name'], null, $namedParameters, null, $this->startLine, $line); foreach ($namelessParameters as $namelessParameter) { $propObj->add(null, $namelessParameter); diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Property.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Property.php index 53a252fb2..f4d0bdc0b 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Property.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Property.php @@ -51,6 +51,20 @@ abstract class Property extends Node */ public string $delimiter = ';'; + /** + * The line number in the original iCalendar / vCard file + * that corresponds with the current node + * if the node was read from a file. + */ + public ?int $lineIndex; + + /** + * The line string from the original iCalendar / vCard file + * that corresponds with the current node + * if the node was read from a file. + */ + public ?string $lineString; + /** * Creates the generic property. * @@ -61,7 +75,7 @@ abstract class Property extends Node * @param array $parameters List of parameters * @param string|null $group The vcard property group */ - public function __construct(Component $root, ?string $name, $value = null, array $parameters = [], string $group = null) + public function __construct(Component $root, ?string $name, $value = null, array $parameters = [], ?string $group = null, ?int $lineIndex = null, ?string $lineString = null) { $this->name = $name; $this->group = $group; @@ -75,6 +89,14 @@ abstract class Property extends Node if (!is_null($value)) { $this->setValue($value); } + + if (!is_null($lineIndex)) { + $this->lineIndex = $lineIndex; + } + + if (!is_null($lineString)) { + $this->lineString = $lineString; + } } /** diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Property/ICalendar/DateTime.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Property/ICalendar/DateTime.php index 7ee907972..631a73b08 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Property/ICalendar/DateTime.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Property/ICalendar/DateTime.php @@ -128,7 +128,7 @@ class DateTime extends Property * * @throws InvalidDataException */ - public function getDateTime(\DateTimeZone $timeZone = null): ?\DateTimeImmutable + public function getDateTime(?\DateTimeZone $timeZone = null): ?\DateTimeImmutable { $dt = $this->getDateTimes($timeZone); if (!$dt) { @@ -149,7 +149,7 @@ class DateTime extends Property * * @throws InvalidDataException */ - public function getDateTimes(\DateTimeZone $timeZone = null): array + public function getDateTimes(?\DateTimeZone $timeZone = null): array { // Does the property have a TZID? /** @var Property\FlatText $tzid */ diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Property/ICalendar/Recur.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Property/ICalendar/Recur.php index 9a1e9e643..10081673e 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Property/ICalendar/Recur.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Property/ICalendar/Recur.php @@ -189,7 +189,14 @@ class Recur extends Property if (empty($part)) { continue; } - list($partName, $partValue) = explode('=', $part); + + $parts = explode('=', $part); + + if (2 !== count($parts)) { + throw new InvalidDataException('The supplied iCalendar RRULE part is incorrect: '.$part); + } + + list($partName, $partValue) = $parts; // The value itself had multiple values.. if (false !== strpos($partValue, ',')) { diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Property/Text.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Property/Text.php index c606ad812..c59029059 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Property/Text.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Property/Text.php @@ -64,7 +64,7 @@ class Text extends Property * @param array $parameters List of parameters * @param string|null $group The vcard property group */ - public function __construct(Component $root, string $name, $value = null, array $parameters = [], string $group = null) + public function __construct(Component $root, string $name, $value = null, array $parameters = [], ?string $group = null) { // There's two types of multi-valued text properties: // 1. multivalue properties. diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Recur/EventIterator.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Recur/EventIterator.php index d79cf3132..2c93bcf4e 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Recur/EventIterator.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Recur/EventIterator.php @@ -89,7 +89,7 @@ class EventIterator implements \Iterator * @throws NoInstancesException * @throws InvalidDataException */ - public function __construct($input, string $uid = null, \DateTimeZone $timeZone = null) + public function __construct($input, ?string $uid = null, ?\DateTimeZone $timeZone = null) { if (is_null($timeZone)) { $timeZone = new \DateTimeZone('UTC'); diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Recur/RRuleIterator.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Recur/RRuleIterator.php index 888556eea..ff276a697 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Recur/RRuleIterator.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Recur/RRuleIterator.php @@ -159,6 +159,14 @@ class RRuleIterator implements \Iterator */ protected ?\DateTimeInterface $currentDate; + /** + * The number of hours that the next occurrence of an event + * jumped forward, usually because summer time started and + * the requested time-of-day like 0230 did not exist on that + * day. And so the event was scheduled 1 hour later at 0330. + */ + protected int $hourJump = 0; + /** * Frequency is one of: secondly, minutely, hourly, daily, weekly, monthly, * yearly. @@ -276,12 +284,65 @@ class RRuleIterator implements \Iterator /* Functions that advance the iterator {{{ */ + /** + * Gets the original start time of the RRULE. + * + * The value is formatted as a string with 24-hour:minute:second + */ + protected function startTime(): string + { + return $this->startDate->format('H:i:s'); + } + + /** + * Advances currentDate by the interval. + * The time is set from the original startDate. + * If the recurrence is on a day when summer time started, then the + * time on that day may have jumped forward, for example, from 0230 to 0330. + * Using the original time means that the next recurrence will be calculated + * based on the original start time and the day/week/month/year interval. + * So the start time of the next occurrence can correctly revert to 0230. + */ + protected function advanceTheDate(string $interval): void + { + $this->currentDate = $this->currentDate->modify($interval.' '.$this->startTime()); + } + + /** + * Does the processing for adjusting the time of multi-hourly events when summer time starts. + */ + protected function adjustForTimeJumpsOfHourlyEvent(\DateTimeInterface $previousEventDateTime): void + { + if (0 === $this->hourJump) { + // Remember if the clock time jumped forward on the next occurrence. + // That happens if the next event time is on a day when summer time starts + // and the event time is in the non-existent hour of the day. + // For example, an event that normally starts at 02:30 will + // have to start at 03:30 on that day. + // If the interval is just 1 hour, then there is no "jumping back" to do. + // The events that day will happen, for example, at 0030 0130 0330 0430 0530... + if ($this->interval > 1) { + $expectedHourOfNextDate = ((int) $previousEventDateTime->format('G') + $this->interval) % 24; + $actualHourOfNextDate = (int) $this->currentDate->format('G'); + $this->hourJump = $actualHourOfNextDate - $expectedHourOfNextDate; + } + } else { + // The hour "jumped" for the previous occurrence, to avoid the non-existent time. + // currentDate got set ahead by (usually) 1 hour on that day. + // Adjust it back for this next occurrence. + $this->currentDate = $this->currentDate->sub(new \DateInterval('PT'.$this->hourJump.'H')); + $this->hourJump = 0; + } + } + /** * Does the processing for advancing the iterator for hourly frequency. */ protected function nextHourly(): void { + $previousEventDateTime = clone $this->currentDate; $this->currentDate = $this->currentDate->modify('+'.$this->interval.' hours'); + $this->adjustForTimeJumpsOfHourlyEvent($previousEventDateTime); } /** @@ -290,7 +351,7 @@ class RRuleIterator implements \Iterator protected function nextDaily(): void { if (!$this->byHour && !$this->byDay) { - $this->currentDate = $this->currentDate->modify('+'.$this->interval.' days'); + $this->advanceTheDate('+'.$this->interval.' days'); return; } @@ -349,7 +410,7 @@ class RRuleIterator implements \Iterator protected function nextWeekly(): void { if (!$this->byHour && !$this->byDay) { - $this->currentDate = $this->currentDate->modify('+'.$this->interval.' weeks'); + $this->advanceTheDate('+'.$this->interval.' weeks'); return; } @@ -371,7 +432,7 @@ class RRuleIterator implements \Iterator if ($this->byHour) { $this->currentDate = $this->currentDate->modify('+1 hours'); } else { - $this->currentDate = $this->currentDate->modify('+1 days'); + $this->advanceTheDate('+1 days'); } // Current day of the week @@ -408,13 +469,13 @@ class RRuleIterator implements \Iterator // occur to the next month. We Must skip these invalid // entries. if ($currentDayOfMonth < 29) { - $this->currentDate = $this->currentDate->modify('+'.$this->interval.' months'); + $this->advanceTheDate('+'.$this->interval.' months'); } else { $increase = 0; do { ++$increase; $tempDate = clone $this->currentDate; - $tempDate = $tempDate->modify('+ '.($this->interval * $increase).' months'); + $tempDate = $tempDate->modify('+ '.($this->interval * $increase).' months '.$this->startTime()); } while ($tempDate->format('j') != $currentDayOfMonth); $this->currentDate = $tempDate; } @@ -465,11 +526,15 @@ class RRuleIterator implements \Iterator } } + // Set the currentDate to the year and month that we are in, and the day of the month that we have selected. + // That day could be a day when summer time starts, and if the time of the event is, for example, 0230, + // then 0230 will not be a valid time on that day. So always apply the start time from the original startDate. + // The "modify" method will set the time forward to 0330, for example, if needed. $this->currentDate = $this->currentDate->setDate( (int) $this->currentDate->format('Y'), (int) $this->currentDate->format('n'), (int) $occurrence - ); + )->modify($this->startTime()); } /** @@ -586,7 +651,7 @@ class RRuleIterator implements \Iterator } // The easiest form - $this->currentDate = $this->currentDate->modify('+'.$this->interval.' years'); + $this->advanceTheDate('+'.$this->interval.' years'); return; } @@ -610,7 +675,11 @@ class RRuleIterator implements \Iterator // If we advanced to the next month or year, the first // occurrence is always correct. if ($occurrence > $currentDayOfMonth || $advancedToNewMonth) { - break 2; + // only consider byMonth matches, + // otherwise, we don't follow RRule correctly + if (in_array($currentMonth, $this->byMonth)) { + break 2; + } } } @@ -646,7 +715,7 @@ class RRuleIterator implements \Iterator (int) $currentYear, (int) $currentMonth, (int) $occurrence - ); + )->modify($this->startTime()); return; } else { @@ -663,7 +732,7 @@ class RRuleIterator implements \Iterator (int) $currentYear, (int) $currentMonth, (int) $currentDayOfMonth - ); + )->modify($this->startTime()); return; } diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Splitter/ICalendar.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Splitter/ICalendar.php index ccf0d1add..79f0bd443 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Splitter/ICalendar.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Splitter/ICalendar.php @@ -46,7 +46,7 @@ class ICalendar implements SplitterInterface { $data = VObject\Reader::read($input, $options); - if (!$data instanceof VObject\Component\VCalendar) { + if (!$data instanceof VCalendar) { throw new VObject\ParseException('Supplied input could not be parsed as VCALENDAR.'); } diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Splitter/VCard.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Splitter/VCard.php index e63ae837d..40775a335 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Splitter/VCard.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/Splitter/VCard.php @@ -61,7 +61,7 @@ class VCard implements SplitterInterface try { $object = $this->parser->parse(); - if (!$object instanceof VObject\Component\VCard) { + if (!$object instanceof Component\VCard) { throw new VObject\ParseException('The supplied input contained non-VCARD data.'); } } catch (VObject\EofException $e) { diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/TimeZoneUtil.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/TimeZoneUtil.php index 8c2a374fb..2cd458578 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/TimeZoneUtil.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/TimeZoneUtil.php @@ -72,7 +72,7 @@ class TimeZoneUtil * Alternatively, if $failIfUncertain is set to true, it will throw an * exception if we cannot accurately determine the timezone. */ - private function findTimeZone(string $tzid, Component $vcalendar = null, bool $failIfUncertain = false): \DateTimeZone + private function findTimeZone(string $tzid, ?Component $vcalendar = null, bool $failIfUncertain = false): \DateTimeZone { foreach ($this->timezoneFinders as $timezoneFinder) { $timezone = $timezoneFinder->find($tzid, $failIfUncertain); @@ -117,7 +117,7 @@ class TimeZoneUtil self::getInstance()->addFinder($key, $finder); } - public static function getTimeZone(string $tzid, Component $vcalendar = null, bool $failIfUncertain = false): \DateTimeZone + public static function getTimeZone(string $tzid, ?Component $vcalendar = null, bool $failIfUncertain = false): \DateTimeZone { return self::getInstance()->findTimeZone($tzid, $vcalendar, $failIfUncertain); } diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/VCardConverter.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/VCardConverter.php index 88d74602c..ff8fe3f81 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/VCardConverter.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/VCardConverter.php @@ -93,8 +93,8 @@ class VCardConverter ); if (Document::VCARD30 === $targetVersion) { - if ($property instanceof Property\Uri && in_array($property->name, ['PHOTO', 'LOGO', 'SOUND'])) { - /** @var Property\Uri $newProperty */ + if ($property instanceof Uri && in_array($property->name, ['PHOTO', 'LOGO', 'SOUND'])) { + /** @var Uri $newProperty */ $newProperty = $this->convertUriToBinary($output, $newProperty); } elseif ($property instanceof Property\VCard\DateAndOrTime) { // In vCard 4, the birth year may be optional. This is not the @@ -153,8 +153,8 @@ class VCardConverter return; } - if ($property instanceof Property\Binary) { - /** @var Property\Binary $newProperty */ + if ($property instanceof Binary) { + /** @var Binary $newProperty */ $newProperty = $this->convertBinaryToUri($output, $newProperty, $parameters); } elseif ($property instanceof Property\VCard\DateAndOrTime && isset($parameters['X-APPLE-OMIT-YEAR'])) { // If a property such as BDAY contained 'X-APPLE-OMIT-YEAR', @@ -256,7 +256,7 @@ class VCardConverter * * @throws InvalidDataException */ - protected function convertBinaryToUri(Component\VCard $output, Property\Binary $newProperty, array &$parameters): Uri + protected function convertBinaryToUri(Component\VCard $output, Binary $newProperty, array &$parameters): Uri { $value = $newProperty->getValue(); /** @var Uri $newProperty */ @@ -304,11 +304,11 @@ class VCardConverter * be valid in vCard 3.0 as well, we should convert those to BINARY if * possible, to improve compatibility. * - * @return Property\Binary|Property\Uri|null + * @return Binary|Uri|null * * @throws InvalidDataException */ - protected function convertUriToBinary(Component\VCard $output, Property\Uri $newProperty): Property + protected function convertUriToBinary(Component\VCard $output, Uri $newProperty): Property { $value = $newProperty->getValue(); diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/timezonedata/windowszones.php b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/timezonedata/windowszones.php index 2049a95c1..335007983 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/VObject/timezonedata/windowszones.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/VObject/timezonedata/windowszones.php @@ -11,142 +11,142 @@ */ return [ - 'AUS Central Standard Time' => 'Australia/Darwin', - 'AUS Eastern Standard Time' => 'Australia/Sydney', - 'Afghanistan Standard Time' => 'Asia/Kabul', - 'Alaskan Standard Time' => 'America/Anchorage', - 'Aleutian Standard Time' => 'America/Adak', - 'Altai Standard Time' => 'Asia/Barnaul', - 'Arab Standard Time' => 'Asia/Riyadh', - 'Arabian Standard Time' => 'Asia/Dubai', - 'Arabic Standard Time' => 'Asia/Baghdad', - 'Argentina Standard Time' => 'America/Buenos_Aires', - 'Astrakhan Standard Time' => 'Europe/Astrakhan', - 'Atlantic Standard Time' => 'America/Halifax', - 'Aus Central W. Standard Time' => 'Australia/Eucla', - 'Azerbaijan Standard Time' => 'Asia/Baku', - 'Azores Standard Time' => 'Atlantic/Azores', - 'Bahia Standard Time' => 'America/Bahia', - 'Bangladesh Standard Time' => 'Asia/Dhaka', - 'Belarus Standard Time' => 'Europe/Minsk', - 'Bougainville Standard Time' => 'Pacific/Bougainville', - 'Canada Central Standard Time' => 'America/Regina', - 'Cape Verde Standard Time' => 'Atlantic/Cape_Verde', - 'Caucasus Standard Time' => 'Asia/Yerevan', - 'Cen. Australia Standard Time' => 'Australia/Adelaide', - 'Central America Standard Time' => 'America/Guatemala', - 'Central Asia Standard Time' => 'Asia/Almaty', - 'Central Brazilian Standard Time' => 'America/Cuiaba', - 'Central Europe Standard Time' => 'Europe/Budapest', - 'Central European Standard Time' => 'Europe/Warsaw', - 'Central Pacific Standard Time' => 'Pacific/Guadalcanal', - 'Central Standard Time' => 'America/Chicago', - 'Central Standard Time (Mexico)' => 'America/Mexico_City', - 'Chatham Islands Standard Time' => 'Pacific/Chatham', - 'China Standard Time' => 'Asia/Shanghai', - 'Cuba Standard Time' => 'America/Havana', - 'Dateline Standard Time' => 'Etc/GMT+12', - 'E. Africa Standard Time' => 'Africa/Nairobi', - 'E. Australia Standard Time' => 'Australia/Brisbane', - 'E. Europe Standard Time' => 'Europe/Chisinau', - 'E. South America Standard Time' => 'America/Sao_Paulo', - 'Easter Island Standard Time' => 'Pacific/Easter', - 'Eastern Standard Time' => 'America/New_York', - 'Eastern Standard Time (Mexico)' => 'America/Cancun', - 'Egypt Standard Time' => 'Africa/Cairo', - 'Ekaterinburg Standard Time' => 'Asia/Yekaterinburg', - 'FLE Standard Time' => 'Europe/Kiev', - 'Fiji Standard Time' => 'Pacific/Fiji', - 'GMT Standard Time' => 'Europe/London', - 'GTB Standard Time' => 'Europe/Bucharest', - 'Georgian Standard Time' => 'Asia/Tbilisi', - 'Greenland Standard Time' => 'America/Godthab', - 'Greenwich Standard Time' => 'Atlantic/Reykjavik', - 'Haiti Standard Time' => 'America/Port-au-Prince', - 'Hawaiian Standard Time' => 'Pacific/Honolulu', - 'India Standard Time' => 'Asia/Calcutta', - 'Iran Standard Time' => 'Asia/Tehran', - 'Israel Standard Time' => 'Asia/Jerusalem', - 'Jordan Standard Time' => 'Asia/Amman', - 'Kaliningrad Standard Time' => 'Europe/Kaliningrad', - 'Korea Standard Time' => 'Asia/Seoul', - 'Libya Standard Time' => 'Africa/Tripoli', - 'Line Islands Standard Time' => 'Pacific/Kiritimati', - 'Lord Howe Standard Time' => 'Australia/Lord_Howe', - 'Magadan Standard Time' => 'Asia/Magadan', - 'Magallanes Standard Time' => 'America/Punta_Arenas', - 'Marquesas Standard Time' => 'Pacific/Marquesas', - 'Mauritius Standard Time' => 'Indian/Mauritius', - 'Middle East Standard Time' => 'Asia/Beirut', - 'Montevideo Standard Time' => 'America/Montevideo', - 'Morocco Standard Time' => 'Africa/Casablanca', - 'Mountain Standard Time' => 'America/Denver', - 'Mountain Standard Time (Mexico)' => 'America/Chihuahua', - 'Myanmar Standard Time' => 'Asia/Rangoon', - 'N. Central Asia Standard Time' => 'Asia/Novosibirsk', - 'Namibia Standard Time' => 'Africa/Windhoek', - 'Nepal Standard Time' => 'Asia/Katmandu', - 'New Zealand Standard Time' => 'Pacific/Auckland', - 'Newfoundland Standard Time' => 'America/St_Johns', - 'Norfolk Standard Time' => 'Pacific/Norfolk', - 'North Asia East Standard Time' => 'Asia/Irkutsk', - 'North Asia Standard Time' => 'Asia/Krasnoyarsk', - 'North Korea Standard Time' => 'Asia/Pyongyang', - 'Omsk Standard Time' => 'Asia/Omsk', - 'Pacific SA Standard Time' => 'America/Santiago', - 'Pacific Standard Time' => 'America/Los_Angeles', - 'Pacific Standard Time (Mexico)' => 'America/Tijuana', - 'Pakistan Standard Time' => 'Asia/Karachi', - 'Paraguay Standard Time' => 'America/Asuncion', - 'Qyzylorda Standard Time' => 'Asia/Qyzylorda', - 'Romance Standard Time' => 'Europe/Paris', - 'Russia Time Zone 10' => 'Asia/Srednekolymsk', - 'Russia Time Zone 11' => 'Asia/Kamchatka', - 'Russia Time Zone 3' => 'Europe/Samara', - 'Russian Standard Time' => 'Europe/Moscow', - 'SA Eastern Standard Time' => 'America/Cayenne', - 'SA Pacific Standard Time' => 'America/Bogota', - 'SA Western Standard Time' => 'America/La_Paz', - 'SE Asia Standard Time' => 'Asia/Bangkok', - 'Saint Pierre Standard Time' => 'America/Miquelon', - 'Sakhalin Standard Time' => 'Asia/Sakhalin', - 'Samoa Standard Time' => 'Pacific/Apia', - 'Sao Tome Standard Time' => 'Africa/Sao_Tome', - 'Saratov Standard Time' => 'Europe/Saratov', - 'Singapore Standard Time' => 'Asia/Singapore', - 'South Africa Standard Time' => 'Africa/Johannesburg', - 'Sri Lanka Standard Time' => 'Asia/Colombo', - 'Sudan Standard Time' => 'Africa/Khartoum', - 'Syria Standard Time' => 'Asia/Damascus', - 'Taipei Standard Time' => 'Asia/Taipei', - 'Tasmania Standard Time' => 'Australia/Hobart', - 'Tocantins Standard Time' => 'America/Araguaina', - 'Tokyo Standard Time' => 'Asia/Tokyo', - 'Tomsk Standard Time' => 'Asia/Tomsk', - 'Tonga Standard Time' => 'Pacific/Tongatapu', - 'Transbaikal Standard Time' => 'Asia/Chita', - 'Turkey Standard Time' => 'Europe/Istanbul', - 'Turks And Caicos Standard Time' => 'America/Grand_Turk', - 'US Eastern Standard Time' => 'America/Indianapolis', - 'US Mountain Standard Time' => 'America/Phoenix', - 'UTC' => 'Etc/GMT', - 'UTC+12' => 'Etc/GMT-12', - 'UTC+13' => 'Etc/GMT-13', - 'UTC-02' => 'Etc/GMT+2', - 'UTC-08' => 'Etc/GMT+8', - 'UTC-09' => 'Etc/GMT+9', - 'UTC-11' => 'Etc/GMT+11', - 'Ulaanbaatar Standard Time' => 'Asia/Ulaanbaatar', - 'Venezuela Standard Time' => 'America/Caracas', - 'Vladivostok Standard Time' => 'Asia/Vladivostok', - 'Volgograd Standard Time' => 'Europe/Volgograd', - 'W. Australia Standard Time' => 'Australia/Perth', - 'W. Central Africa Standard Time' => 'Africa/Lagos', - 'W. Europe Standard Time' => 'Europe/Berlin', - 'W. Mongolia Standard Time' => 'Asia/Hovd', - 'West Asia Standard Time' => 'Asia/Tashkent', - 'West Bank Standard Time' => 'Asia/Hebron', - 'West Pacific Standard Time' => 'Pacific/Port_Moresby', - 'Yakutsk Standard Time' => 'Asia/Yakutsk', - 'Yukon Standard Time' => 'America/Whitehorse', + 'AUS Central Standard Time' => 'Australia/Darwin', + 'AUS Eastern Standard Time' => 'Australia/Sydney', + 'Afghanistan Standard Time' => 'Asia/Kabul', + 'Alaskan Standard Time' => 'America/Anchorage', + 'Aleutian Standard Time' => 'America/Adak', + 'Altai Standard Time' => 'Asia/Barnaul', + 'Arab Standard Time' => 'Asia/Riyadh', + 'Arabian Standard Time' => 'Asia/Dubai', + 'Arabic Standard Time' => 'Asia/Baghdad', + 'Argentina Standard Time' => 'America/Buenos_Aires', + 'Astrakhan Standard Time' => 'Europe/Astrakhan', + 'Atlantic Standard Time' => 'America/Halifax', + 'Aus Central W. Standard Time' => 'Australia/Eucla', + 'Azerbaijan Standard Time' => 'Asia/Baku', + 'Azores Standard Time' => 'Atlantic/Azores', + 'Bahia Standard Time' => 'America/Bahia', + 'Bangladesh Standard Time' => 'Asia/Dhaka', + 'Belarus Standard Time' => 'Europe/Minsk', + 'Bougainville Standard Time' => 'Pacific/Bougainville', + 'Canada Central Standard Time' => 'America/Regina', + 'Cape Verde Standard Time' => 'Atlantic/Cape_Verde', + 'Caucasus Standard Time' => 'Asia/Yerevan', + 'Cen. Australia Standard Time' => 'Australia/Adelaide', + 'Central America Standard Time' => 'America/Guatemala', + 'Central Asia Standard Time' => 'Asia/Almaty', + 'Central Brazilian Standard Time' => 'America/Cuiaba', + 'Central Europe Standard Time' => 'Europe/Budapest', + 'Central European Standard Time' => 'Europe/Warsaw', + 'Central Pacific Standard Time' => 'Pacific/Guadalcanal', + 'Central Standard Time' => 'America/Chicago', + 'Central Standard Time (Mexico)' => 'America/Mexico_City', + 'Chatham Islands Standard Time' => 'Pacific/Chatham', + 'China Standard Time' => 'Asia/Shanghai', + 'Cuba Standard Time' => 'America/Havana', + 'Dateline Standard Time' => 'Etc/GMT+12', + 'E. Africa Standard Time' => 'Africa/Nairobi', + 'E. Australia Standard Time' => 'Australia/Brisbane', + 'E. Europe Standard Time' => 'Europe/Chisinau', + 'E. South America Standard Time' => 'America/Sao_Paulo', + 'Easter Island Standard Time' => 'Pacific/Easter', + 'Eastern Standard Time' => 'America/New_York', + 'Eastern Standard Time (Mexico)' => 'America/Cancun', + 'Egypt Standard Time' => 'Africa/Cairo', + 'Ekaterinburg Standard Time' => 'Asia/Yekaterinburg', + 'FLE Standard Time' => 'Europe/Kiev', + 'Fiji Standard Time' => 'Pacific/Fiji', + 'GMT Standard Time' => 'Europe/London', + 'GTB Standard Time' => 'Europe/Bucharest', + 'Georgian Standard Time' => 'Asia/Tbilisi', + 'Greenland Standard Time' => 'America/Godthab', + 'Greenwich Standard Time' => 'Atlantic/Reykjavik', + 'Haiti Standard Time' => 'America/Port-au-Prince', + 'Hawaiian Standard Time' => 'Pacific/Honolulu', + 'India Standard Time' => 'Asia/Calcutta', + 'Iran Standard Time' => 'Asia/Tehran', + 'Israel Standard Time' => 'Asia/Jerusalem', + 'Jordan Standard Time' => 'Asia/Amman', + 'Kaliningrad Standard Time' => 'Europe/Kaliningrad', + 'Korea Standard Time' => 'Asia/Seoul', + 'Libya Standard Time' => 'Africa/Tripoli', + 'Line Islands Standard Time' => 'Pacific/Kiritimati', + 'Lord Howe Standard Time' => 'Australia/Lord_Howe', + 'Magadan Standard Time' => 'Asia/Magadan', + 'Magallanes Standard Time' => 'America/Punta_Arenas', + 'Marquesas Standard Time' => 'Pacific/Marquesas', + 'Mauritius Standard Time' => 'Indian/Mauritius', + 'Middle East Standard Time' => 'Asia/Beirut', + 'Montevideo Standard Time' => 'America/Montevideo', + 'Morocco Standard Time' => 'Africa/Casablanca', + 'Mountain Standard Time' => 'America/Denver', + 'Mountain Standard Time (Mexico)' => 'America/Chihuahua', + 'Myanmar Standard Time' => 'Asia/Rangoon', + 'N. Central Asia Standard Time' => 'Asia/Novosibirsk', + 'Namibia Standard Time' => 'Africa/Windhoek', + 'Nepal Standard Time' => 'Asia/Katmandu', + 'New Zealand Standard Time' => 'Pacific/Auckland', + 'Newfoundland Standard Time' => 'America/St_Johns', + 'Norfolk Standard Time' => 'Pacific/Norfolk', + 'North Asia East Standard Time' => 'Asia/Irkutsk', + 'North Asia Standard Time' => 'Asia/Krasnoyarsk', + 'North Korea Standard Time' => 'Asia/Pyongyang', + 'Omsk Standard Time' => 'Asia/Omsk', + 'Pacific SA Standard Time' => 'America/Santiago', + 'Pacific Standard Time' => 'America/Los_Angeles', + 'Pacific Standard Time (Mexico)' => 'America/Tijuana', + 'Pakistan Standard Time' => 'Asia/Karachi', + 'Paraguay Standard Time' => 'America/Asuncion', + 'Qyzylorda Standard Time' => 'Asia/Qyzylorda', + 'Romance Standard Time' => 'Europe/Paris', + 'Russia Time Zone 10' => 'Asia/Srednekolymsk', + 'Russia Time Zone 11' => 'Asia/Kamchatka', + 'Russia Time Zone 3' => 'Europe/Samara', + 'Russian Standard Time' => 'Europe/Moscow', + 'SA Eastern Standard Time' => 'America/Cayenne', + 'SA Pacific Standard Time' => 'America/Bogota', + 'SA Western Standard Time' => 'America/La_Paz', + 'SE Asia Standard Time' => 'Asia/Bangkok', + 'Saint Pierre Standard Time' => 'America/Miquelon', + 'Sakhalin Standard Time' => 'Asia/Sakhalin', + 'Samoa Standard Time' => 'Pacific/Apia', + 'Sao Tome Standard Time' => 'Africa/Sao_Tome', + 'Saratov Standard Time' => 'Europe/Saratov', + 'Singapore Standard Time' => 'Asia/Singapore', + 'South Africa Standard Time' => 'Africa/Johannesburg', + 'Sri Lanka Standard Time' => 'Asia/Colombo', + 'Sudan Standard Time' => 'Africa/Khartoum', + 'Syria Standard Time' => 'Asia/Damascus', + 'Taipei Standard Time' => 'Asia/Taipei', + 'Tasmania Standard Time' => 'Australia/Hobart', + 'Tocantins Standard Time' => 'America/Araguaina', + 'Tokyo Standard Time' => 'Asia/Tokyo', + 'Tomsk Standard Time' => 'Asia/Tomsk', + 'Tonga Standard Time' => 'Pacific/Tongatapu', + 'Transbaikal Standard Time' => 'Asia/Chita', + 'Turkey Standard Time' => 'Europe/Istanbul', + 'Turks And Caicos Standard Time' => 'America/Grand_Turk', + 'US Eastern Standard Time' => 'America/Indianapolis', + 'US Mountain Standard Time' => 'America/Phoenix', + 'UTC' => 'Etc/GMT', + 'UTC+12' => 'Etc/GMT-12', + 'UTC+13' => 'Etc/GMT-13', + 'UTC-02' => 'Etc/GMT+2', + 'UTC-08' => 'Etc/GMT+8', + 'UTC-09' => 'Etc/GMT+9', + 'UTC-11' => 'Etc/GMT+11', + 'Ulaanbaatar Standard Time' => 'Asia/Ulaanbaatar', + 'Venezuela Standard Time' => 'America/Caracas', + 'Vladivostok Standard Time' => 'Asia/Vladivostok', + 'Volgograd Standard Time' => 'Europe/Volgograd', + 'W. Australia Standard Time' => 'Australia/Perth', + 'W. Central Africa Standard Time' => 'Africa/Lagos', + 'W. Europe Standard Time' => 'Europe/Berlin', + 'W. Mongolia Standard Time' => 'Asia/Hovd', + 'West Asia Standard Time' => 'Asia/Tashkent', + 'West Bank Standard Time' => 'Asia/Hebron', + 'West Pacific Standard Time' => 'Pacific/Port_Moresby', + 'Yakutsk Standard Time' => 'Asia/Yakutsk', + 'Yukon Standard Time' => 'America/Whitehorse', ]; diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/Xml/ContextStackTrait.php b/snappymail/v/0.0.0/app/libraries/Sabre/Xml/ContextStackTrait.php index b514f3754..7c082f5fb 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/Xml/ContextStackTrait.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/Xml/ContextStackTrait.php @@ -110,7 +110,7 @@ trait ContextStackTrait $this->elementMap, $this->contextUri, $this->namespaceMap, - $this->classMap + $this->classMap, ) = array_pop($this->contextStack); } } diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Service.php b/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Service.php index ad18b6f4e..6e225bdfd 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Service.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Service.php @@ -109,10 +109,17 @@ class Service */ public function parse($input, ?string $contextUri = null, ?string &$rootElementName = null) { - if (is_resource($input)) { + if (!is_string($input)) { // Unfortunately the XMLReader doesn't support streams. When it // does, we can optimize this. - $input = (string) stream_get_contents($input); + if (is_resource($input)) { + $input = (string) stream_get_contents($input); + } else { + // Input is not a string and not a resource. + // Therefore, it has to be a closed resource. + // Effectively empty input has been passed in. + $input = ''; + } } // If input is empty, then it's safe to throw an exception @@ -153,10 +160,17 @@ class Service */ public function expect($rootElementName, $input, ?string $contextUri = null) { - if (is_resource($input)) { + if (!is_string($input)) { // Unfortunately the XMLReader doesn't support streams. When it // does, we can optimize this. - $input = (string) stream_get_contents($input); + if (is_resource($input)) { + $input = (string) stream_get_contents($input); + } else { + // Input is not a string and not a resource. + // Therefore, it has to be a closed resource. + // Effectively empty input has been passed in. + $input = ''; + } } // If input is empty, then it's safe to throw an exception diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Version.php b/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Version.php index f38e87c27..340393169 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Version.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Version.php @@ -16,5 +16,5 @@ class Version /** * Full version number. */ - public const VERSION = '4.0.5'; + public const VERSION = '4.0.6'; } diff --git a/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Writer.php b/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Writer.php index 77bdae02c..d2fb04ccd 100644 --- a/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Writer.php +++ b/snappymail/v/0.0.0/app/libraries/Sabre/Xml/Writer.php @@ -236,7 +236,7 @@ class Writer extends \XMLWriter list( $namespace, - $localName + $localName, ) = Service::parseClarkNotation($name); if (array_key_exists($namespace, $this->namespaceMap)) {