Skip to content

Commit 659b41b

Browse files
committed
fix(cardav): return correct card version on report
Signed-off-by: Hamza <hamzamahjoubi221@gmail.com>
1 parent 860867a commit 659b41b

3 files changed

Lines changed: 94 additions & 0 deletions

File tree

apps/contactsinteraction/lib/Card.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ public function getContentType(): ?string {
7979
return 'text/vcard; charset=utf-8';
8080
}
8181

82+
public function getVersion(): ?string {
83+
return '3.0';
84+
}
85+
8286
/**
8387
* @inheritDoc
8488
*/

apps/dav/lib/CardDAV/Card.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ public function getAddressbookId(): int {
3030
return (int)$this->cardData['addressbookid'];
3131
}
3232

33+
public function getVersion(): ?string {
34+
preg_match('/^VERSION:([34])\.0/mi', $this->cardData['carddata'], $matches);
35+
return isset($matches[1]) ? $matches[1] . '.0' : null;
36+
}
37+
3338
public function getPrincipalUri(): string {
3439
return $this->addressBookInfo['principaluri'];
3540
}

apps/dav/lib/CardDAV/Plugin.php

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
namespace OCA\DAV\CardDAV;
1010

1111
use OCA\DAV\CardDAV\Xml\Groups;
12+
use Sabre\DAV\Exception\ReportNotSupported;
1213
use Sabre\DAV\INode;
1314
use Sabre\DAV\PropFind;
1415
use Sabre\DAV\Server;
@@ -58,4 +59,88 @@ public function propFind(PropFind $propFind, INode $node) {
5859
});
5960
}
6061
}
62+
63+
/**
64+
* This function handles the addressbook-query REPORT.
65+
*
66+
* This report is used by the client to filter an addressbook based on a
67+
* complex query.
68+
*
69+
* @param \Sabre\CardDAV\Xml\Request\AddressBookQueryReport $report
70+
*/
71+
protected function addressbookQueryReport($report) {
72+
$depth = $this->server->getHTTPDepth(0);
73+
74+
if ($depth == 0) {
75+
$candidateNodes = [
76+
$this->server->tree->getNodeForPath($this->server->getRequestUri()),
77+
];
78+
if (!$candidateNodes[0] instanceof Card) {
79+
throw new ReportNotSupported('The addressbook-query report is not supported on this url with Depth: 0');
80+
}
81+
} else {
82+
$candidateNodes = $this->server->tree->getChildren($this->server->getRequestUri());
83+
}
84+
85+
$validNodes = [];
86+
foreach ($candidateNodes as $node) {
87+
if (!$node instanceof Card) {
88+
continue;
89+
}
90+
91+
$blob = $node->get();
92+
if (is_resource($blob)) {
93+
$blob = stream_get_contents($blob);
94+
}
95+
96+
if (!$this->validateFilters($blob, $report->filters, $report->test)) {
97+
continue;
98+
}
99+
100+
$validNodes[] = $node;
101+
102+
if ($report->limit && $report->limit <= count($validNodes)) {
103+
// We hit the maximum number of items, we can stop now.
104+
break;
105+
}
106+
}
107+
108+
$result = [];
109+
foreach ($validNodes as $validNode) {
110+
$contentType = $report->contentType;
111+
// we theoretically support versions 3.0 and 4.0 so $vcardType should be dyncamic depending on the node
112+
if ($validNode->getVersion()) {
113+
$contentType .= '; version=' . $validNode->getVersion();
114+
} elseif ($report->version) {
115+
$contentType .= '; version=' . $report->version;
116+
}
117+
$vcardType = $this->negotiateVCard(
118+
$contentType
119+
);
120+
if ($depth == 0) {
121+
$href = $this->server->getRequestUri();
122+
} else {
123+
$href = $this->server->getRequestUri() . '/' . $validNode->getName();
124+
}
125+
126+
/** @psalm-suppress DeprecatedMethod */
127+
[$props] = $this->server->getPropertiesForPath($href, $report->properties, 0);
128+
129+
if (isset($props[200]['{' . self::NS_CARDDAV . '}address-data'])) {
130+
$props[200]['{' . self::NS_CARDDAV . '}address-data'] = $this->convertVCard(
131+
$props[200]['{' . self::NS_CARDDAV . '}address-data'],
132+
$vcardType,
133+
$report->addressDataProperties
134+
);
135+
}
136+
$result[] = $props;
137+
}
138+
139+
$prefer = $this->server->getHTTPPrefer();
140+
141+
$this->server->httpResponse->setStatus(207);
142+
$this->server->httpResponse->setHeader('Content-Type', 'application/xml; charset=utf-8');
143+
$this->server->httpResponse->setHeader('Vary', 'Brief,Prefer');
144+
$this->server->httpResponse->setBody($this->server->generateMultiStatus($result, $prefer['return'] === 'minimal'));
145+
}
61146
}

0 commit comments

Comments
 (0)