diff --git a/doc/NEXTCLOUD.md b/doc/NEXTCLOUD.md index 0b5b112..3b6a6fb 100644 --- a/doc/NEXTCLOUD.md +++ b/doc/NEXTCLOUD.md @@ -57,6 +57,8 @@ After you have set up the sync you get a bunch of requests: ### Etags are mandatory +If you don't provide an etag, eg. for a directory, the app will fail to sync with a message about missing data. + ### Don't use text/xml > PROPFIND reply is not XML formatted diff --git a/lib/KD2/WebDAV/NextCloud.php b/lib/KD2/WebDAV/NextCloud.php index 3ae97f8..2cf89d5 100644 --- a/lib/KD2/WebDAV/NextCloud.php +++ b/lib/KD2/WebDAV/NextCloud.php @@ -260,6 +260,18 @@ abstract class NextCloud catch (Exception $e) { $this->server->log('NC => %d - %s', $e->getCode(), $e->getMessage()); http_response_code($e->getCode()); + + if ($route == 'direct') { + // Do not return any error message for the direct API endpoint. + // If you return anything, the client will consider it is part of the file + // and will generate a corrupted file! + // so if you return a 20-byte long error message, the client + // will do a normal GET on the regular URL, but with 'Range: bytes=20-'! + // see https://github.com/nextcloud/desktop/issues/5170 + header('X-Error: ' . $e->getMessage()); + return true; + } + echo json_encode(['error' => $e->getMessage()]); return true; } @@ -329,7 +341,7 @@ abstract class NextCloud // Android app is using "/remote.php/dav/files/user//" as root // so let's alias that as well // ownCloud Android is requesting just /dav/files/ - if (preg_match('!^' . preg_quote($base_uri, '!') . 'files/(?:[a-z]+/+)?!', $uri, $match)) { + if (preg_match('!^' . preg_quote($base_uri, '!') . 'files/(?:[^/]+/+)?!', $uri, $match)) { $base_uri = $match[0]; } diff --git a/lib/KD2/WebDAV/Server.php b/lib/KD2/WebDAV/Server.php index 6f2e866..0e0a49b 100644 --- a/lib/KD2/WebDAV/Server.php +++ b/lib/KD2/WebDAV/Server.php @@ -123,7 +123,7 @@ class Server table { border-collapse: collapse; } th, td { padding: .5em; text-align: left; border: 2px solid #ccc; } span { font-size: 40px; line-height: 40px; } - ', $this->base_uri); + ', '/' . ltrim($this->base_uri, '/')); $out .= sprintf('%s

%1$s

', htmlspecialchars($uri ? str_replace('/', ' / ', $uri) . ' - Files' : 'Files')); @@ -622,7 +622,7 @@ class Server $properties[$url . ':' . $name] = [ 'name' => $name, - 'ns_alias' => $found[3] ?: null, + 'ns_alias' => $found[3] ?? null, 'ns_url' => $url, ]; } @@ -646,6 +646,10 @@ class Server // We don't really care about having a correct XML string, // but we can get better WebDAV compliance if we do if (isset($_SERVER['HTTP_X_LITMUS'])) { + if (false !== strpos($body, 'getTimestamp(); } + // ownCloud app crashes if mimetype is provided for a directory + // https://github.com/owncloud/android/issues/3768 + elseif ($name == 'DAV::getcontenttype' + && ($item['DAV::resourcetype'] ?? null) == 'collection') { + $value = null; + } if ($name == 'DAV::resourcetype' && $value == 'collection') { $value = ''; @@ -767,6 +777,9 @@ class Server $value = '"' . $value . '"'; } elseif ($value instanceof \DateTimeInterface) { + // Change value to GMT + $value = clone $value; + $value->setTimezone(new \DateTimeZone('GMT')); $value = $value->format(DATE_RFC7231); } elseif (is_array($value)) { diff --git a/lib/KaraDAV/Storage.php b/lib/KaraDAV/Storage.php index ba120af..cac731b 100644 --- a/lib/KaraDAV/Storage.php +++ b/lib/KaraDAV/Storage.php @@ -78,7 +78,7 @@ class Storage extends AbstractStorage // or https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile/ if (ENABLE_XSENDFILE) { header('X-SendFile: ' . $path); - exit; + return ['stop' => true]; } return ['path' => $path];