Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 34 additions & 12 deletions lib/DAV/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -1587,15 +1587,43 @@ public function getIfConditions(RequestInterface $request)
$conditions = [];

foreach ($matches as $match) {
$negate = $match['not'] ? true : false;
$token = $match['token'];
$etag = isset($match['etag']) ? $match['etag'] : '';

// Build the token entries. Per RFC 4918, 'Not' applies only to
// the immediately following resource (token or etag). When both
// a token and an etag appear in the same list and 'Not' is
// present, we must split them so that the negation applies only
// to the token, not the etag.
$tokenEntries = [];
if ($negate && $token && $etag) {
// (Not <token> [etag]) means: NOT token AND etag
$tokenEntries[] = [
'negate' => true,
'token' => $token,
'etag' => '',
];
$tokenEntries[] = [
'negate' => false,
'token' => '',
'etag' => $etag,
];
} else {
$tokenEntries[] = [
'negate' => $negate,
'token' => $token,
'etag' => $etag,
];
}

// If there was no uri specified in this match, and there were
// already conditions parsed, we add the condition to the list of
// conditions for the previous uri.
if (!$match['uri'] && count($conditions)) {
$conditions[count($conditions) - 1]['tokens'][] = [
'negate' => $match['not'] ? true : false,
'token' => $match['token'],
'etag' => isset($match['etag']) ? $match['etag'] : '',
];
foreach ($tokenEntries as $entry) {
$conditions[count($conditions) - 1]['tokens'][] = $entry;
}
} else {
if (!$match['uri']) {
$realUri = $request->getPath();
Expand All @@ -1605,13 +1633,7 @@ public function getIfConditions(RequestInterface $request)

$conditions[] = [
'uri' => $realUri,
'tokens' => [
[
'negate' => $match['not'] ? true : false,
'token' => $match['token'],
'etag' => isset($match['etag']) ? $match['etag'] : '',
],
],
'tokens' => $tokenEntries,
];
}
}
Expand Down
61 changes: 61 additions & 0 deletions tests/Sabre/DAV/GetIfConditionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,67 @@ public function test2Etags()
self::assertEquals($compare, $conditions);
}

public function testNotWithTokenAndEtag()
{
// Per RFC 4918, (Not <token> [etag]) means: NOT token AND etag
// The Not applies only to the token, not the etag.
$request = new HTTP\Request('GET', '/foo', [
'If' => '(Not <DAV:no-lock> ["c3d40b11121145ec31f5c1acc078b658"])',
]);

$conditions = $this->server->getIfConditions($request);

$compare = [
[
'uri' => 'foo',
'tokens' => [
[
'negate' => true,
'token' => 'DAV:no-lock',
'etag' => '',
],
[
'negate' => false,
'token' => '',
'etag' => '"c3d40b11121145ec31f5c1acc078b658"',
],
],
],
];

self::assertEquals($compare, $conditions);
}

public function testNotWithTokenAndEtagUrl()
{
// Same test but with a URI prefix
$request = new HTTP\Request('GET', '/foo', [
'If' => '<http://www.example.org/> (Not <DAV:no-lock> ["etag1"])',
]);

$conditions = $this->server->getIfConditions($request);

$compare = [
[
'uri' => '',
'tokens' => [
[
'negate' => true,
'token' => 'DAV:no-lock',
'etag' => '',
],
[
'negate' => false,
'token' => '',
'etag' => '"etag1"',
],
],
],
];

self::assertEquals($compare, $conditions);
}

public function testComplexIf()
{
$request = new HTTP\Request('GET', '/foo', [
Expand Down