summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorThomas Müller <DeepDiver1975@users.noreply.github.com>2016-12-07 23:10:11 +0100
committerRoeland Jago Douma <roeland@famdouma.nl>2017-01-05 09:00:33 +0100
commitd5d726fc249ddaba4819b2ef0e5530517c83032f (patch)
tree58136f94c313de2b74d90f73b69b6e5fcb8e6a65 /apps
parent6a0f0403d01dc6a889157b446edef73f9af58540 (diff)
downloadnextcloud-server-d5d726fc249ddaba4819b2ef0e5530517c83032f.tar.gz
nextcloud-server-d5d726fc249ddaba4819b2ef0e5530517c83032f.zip
Fix generation of birthday, deathdate and anniversary in case where no year is set - which is allowed as per https://tools.ietf.org/html/rfc6350#section-6.2.5 (#26756)
Signed-off-by: Lukas Reschke <lukas@statuscode.ch> Signed-off-by: Roeland Jago Douma <roeland@famdouma.nl>
Diffstat (limited to 'apps')
-rw-r--r--apps/dav/lib/CalDAV/BirthdayService.php45
-rw-r--r--apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php29
2 files changed, 56 insertions, 18 deletions
diff --git a/apps/dav/lib/CalDAV/BirthdayService.php b/apps/dav/lib/CalDAV/BirthdayService.php
index 104eec6b496..702b74bf1b3 100644
--- a/apps/dav/lib/CalDAV/BirthdayService.php
+++ b/apps/dav/lib/CalDAV/BirthdayService.php
@@ -30,6 +30,11 @@ use Exception;
use OCA\DAV\CardDAV\CardDavBackend;
use OCA\DAV\DAV\GroupPrincipalBackend;
use Sabre\VObject\Component\VCalendar;
+use Sabre\VObject\Component\VCard;
+use Sabre\VObject\DateTimeParser;
+use Sabre\VObject\Document;
+use Sabre\VObject\InvalidDataException;
+use Sabre\VObject\Property\VCard\DateAndOrTime;
use Sabre\VObject\Reader;
class BirthdayService {
@@ -129,6 +134,12 @@ class BirthdayService {
}
try {
$doc = Reader::read($cardData);
+ // We're always converting to vCard 4.0 so we can rely on the
+ // VCardConverter handling the X-APPLE-OMIT-YEAR property for us.
+ if (!$doc instanceof VCard) {
+ return null;
+ }
+ $doc = $doc->convert(Document::VCARD40);
} catch (Exception $e) {
return null;
}
@@ -136,21 +147,43 @@ class BirthdayService {
if (!isset($doc->{$dateField})) {
return null;
}
+ if (!isset($doc->FN)) {
+ return null;
+ }
$birthday = $doc->{$dateField};
if (!(string)$birthday) {
return null;
}
- $title = str_replace('{name}',
- strtr((string)$doc->FN, array('\,' => ',', '\;' => ';')),
- '{name}'
- );
+ // Skip if the BDAY property is not of the right type.
+ if (!$birthday instanceof DateAndOrTime) {
+ return null;
+ }
+
+ // Skip if we can't parse the BDAY value.
+ try {
+ $dateParts = DateTimeParser::parseVCardDateTime($birthday->getValue());
+ } catch (InvalidDataException $e) {
+ return null;
+ }
+
+ $unknownYear = false;
+ if (!$dateParts['year']) {
+ $birthday = '1900-' . $dateParts['month'] . '-' . $dateParts['date'];
+
+ $unknownYear = true;
+ }
+
try {
$date = new \DateTime($birthday);
} catch (Exception $e) {
return null;
}
-
- $summary = $title . ' (' . $summarySymbol . $date->format('Y') . ')';
+ if ($unknownYear) {
+ $summary = $doc->FN->getValue() . ' ' . $summarySymbol;
+ } else {
+ $year = (int)$date->format('Y');
+ $summary = $doc->FN->getValue() . " ($summarySymbol$year)";
+ }
$vCal = new VCalendar();
$vCal->VERSION = '2.0';
$vEvent = $vCal->createComponent('VEVENT');
diff --git a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
index 5eeb6772a60..cecf07ef1d8 100644
--- a/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
+++ b/apps/dav/tests/unit/CardDAV/BirthdayServiceTest.php
@@ -55,18 +55,18 @@ class BirthdayServiceTest extends TestCase {
/**
* @dataProvider providesVCards
- * @param boolean $nullExpected
+ * @param boolean $expectedSummary
* @param string | null $data
*/
- public function testBuildBirthdayFromContact($nullExpected, $data) {
+ public function testBuildBirthdayFromContact($expectedSummary, $data) {
$cal = $this->service->buildDateFromContact($data, 'BDAY', '*');
- if ($nullExpected) {
+ if ($expectedSummary === null) {
$this->assertNull($cal);
} else {
$this->assertInstanceOf('Sabre\VObject\Component\VCalendar', $cal);
$this->assertTrue(isset($cal->VEVENT));
$this->assertEquals('FREQ=YEARLY', $cal->VEVENT->RRULE->getValue());
- $this->assertEquals('12345 (*1900)', $cal->VEVENT->SUMMARY->getValue());
+ $this->assertEquals($expectedSummary, $cal->VEVENT->SUMMARY->getValue());
$this->assertEquals('TRANSPARENT', $cal->VEVENT->TRANSP->getValue());
}
}
@@ -233,14 +233,19 @@ class BirthdayServiceTest extends TestCase {
public function providesVCards() {
return [
- [true, null],
- [true, ''],
- [true, 'yasfewf'],
- [true, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n", "Dr. Foo Bar"],
- [true, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:\r\nEND:VCARD\r\n", "Dr. Foo Bar"],
- [true, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:someday\r\nEND:VCARD\r\n", "Dr. Foo Bar"],
- [false, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:1900-01-01\r\nEND:VCARD\r\n", "Dr. Foo Bar"],
- [false, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:1900-12-31\r\nEND:VCARD\r\n", "Dr. Foo Bar"],
+ [null, null],
+ [null, ''],
+ [null, 'yasfewf'],
+ [null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nEND:VCARD\r\n", "Dr. Foo Bar"],
+ [null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:\r\nEND:VCARD\r\n", "Dr. Foo Bar"],
+ [null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:someday\r\nEND:VCARD\r\n", "Dr. Foo Bar"],
+ ['12345 (*1900)', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19000101\r\nEND:VCARD\r\n", "Dr. Foo Bar"],
+ ['12345 (*1900)', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:19001231\r\nEND:VCARD\r\n", "Dr. Foo Bar"],
+ ['12345 *', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:--1231\r\nEND:VCARD\r\n", "Dr. Foo Bar"],
+ ['12345 *', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY;X-APPLE-OMIT-YEAR=1604:16041231\r\nEND:VCARD\r\n", "Dr. Foo Bar"],
+ [null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:;VALUE=text:circa 1800\r\nEND:VCARD\r\n", "Dr. Foo Bar"],
+ [null, "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nN:12345;;;;\r\nBDAY:20031231\r\nEND:VCARD\r\n", "Dr. Foo Bar"],
+ ['12345 (*900)', "BEGIN:VCARD\r\nVERSION:3.0\r\nPRODID:-//Sabre//Sabre VObject 4.1.1//EN\r\nUID:12345\r\nFN:12345\r\nN:12345;;;;\r\nBDAY:09001231\r\nEND:VCARD\r\n", "Dr. Foo Bar"],
];
}
}