diff --git a/README.md b/README.md index 9c5a292..b09f1f9 100644 --- a/README.md +++ b/README.md @@ -21,13 +21,14 @@ If you drop the [`index.php`](https://github.com/kd2org/picodav/raw/main/index.p * Download all files of a directory * Manage users and password with only a text file! * Restrict users to some directories, control where they can write! +* Support for [rclone](https://rclone.org) as a NextCloud provider ## WebDAV clients You can use any WebDAV client, but we recommend these: * Windows/OSX: [CyberDuck](https://cyberduck.io/download/) -* Linux: Any file manager should be able to connect to WebDAV (Dolphin, Thunar, Nautilus, etc.), but you can also use [FUSE webdavfs](https://github.com/miquels/webdavfs) +* Linux: Any file manager should be able to connect to WebDAV (Dolphin, Thunar, Nautilus, etc.), but you can also use [FUSE webdavfs](https://github.com/miquels/webdavfs), or [rclone](https://rclone.org) * Android: [RCX](https://f-droid.org/en/packages/io.github.x0b.rcx/) and [DAVx⁵](https://www.davx5.com/), see [the manual](https://manual.davx5.com/webdav_mounts.html) ## Install diff --git a/index.php b/index.php index f3aa02c..64f8649 100644 --- a/index.php +++ b/index.php @@ -196,11 +196,20 @@ namespace KD2\WebDAV } $hash = null; + $hash_algo = null; // Support for checksum matching // https://dcache.org/old/manuals/UserGuide-6.0/webdav.shtml#checksums if (!empty($_SERVER['HTTP_CONTENT_MD5'])) { $hash = bin2hex(base64_decode($_SERVER['HTTP_CONTENT_MD5'])); + $hash_algo = 'MD5'; + } + // Support for ownCloud/NextCloud checksum + // https://github.com/owncloud-archive/documentation/issues/2964 + elseif (!empty($_SERVER['HTTP_OC_CHECKSUM']) + && preg_match('/MD5:[a-f0-9]{32}|SHA1:[a-f0-9]{40}/', $_SERVER['HTTP_OC_CHECKSUM'], $match)) { + $hash_algo = strtok($match[0], ':'); + $hash = strtok(false); } $uri = $this->_prefix($uri); @@ -216,7 +225,8 @@ namespace KD2\WebDAV } } - // Specific to NextCloud/ownCloud + // Specific to NextCloud/ownCloud, to allow setting file mtime + // This expects a UNIX timestamp $mtime = (int)($_SERVER['HTTP_X_OC_MTIME'] ?? 0) ?: null; if ($mtime) { @@ -225,7 +235,7 @@ namespace KD2\WebDAV $this->extendExecutionTime(); - $created = $this->storage->put($uri, fopen('php://input', 'r'), $hash, $mtime); + $created = $this->storage->put($uri, fopen('php://input', 'r'), $hash_algo, $hash, $mtime); $prop = $this->storage->properties($uri, ['DAV::getetag'], 0); @@ -1273,7 +1283,7 @@ namespace KD2\WebDAV // By default, properties are not saved } - abstract public function put(string $uri, $pointer, ?string $hash, ?int $mtime): bool; + abstract public function put(string $uri, $pointer, ?string $hash_algo, ?string $hash, ?int $mtime): bool; abstract public function delete(string $uri): void; @@ -1546,7 +1556,7 @@ namespace PicoDAV return $permissions; case Server::PROP_DIGEST_MD5: - if (!is_file($target)) { + if (!is_file($target) || is_dir($target) || !is_readable($target)) { return null; } @@ -1583,7 +1593,7 @@ namespace PicoDAV return $out; } - public function put(string $uri, $pointer, ?string $hash, ?int $mtime): bool + public function put(string $uri, $pointer, ?string $hash_algo, ?string $hash, ?int $mtime): bool { if (preg_match(self::PUT_IGNORE_PATTERN, basename($uri))) { return false; @@ -1631,10 +1641,14 @@ namespace PicoDAV @unlink($tmp_file); throw new WebDAV_Exception('Your quota is exhausted', 403); } - elseif ($hash && md5_file($tmp_file) != $hash) { + elseif ($hash && $hash_algo == 'MD5' && md5_file($tmp_file) != $hash) { @unlink($tmp_file); throw new WebDAV_Exception('The data sent does not match the supplied MD5 hash', 400); } + elseif ($hash && $hash_algo == 'SHA1' && sha1_file($tmp_file) != $hash) { + @unlink($tmp_file); + throw new WebDAV_Exception('The data sent does not match the supplied SHA1 hash', 400); + } else { rename($tmp_file, $target); } @@ -1909,11 +1923,11 @@ RewriteRule ^.*$ /index.php [END] $fp = fopen(__FILE__, 'r'); if ($relative_uri == '.webdav/webdav.js') { - fseek($fp, 51249, SEEK_SET); - echo fread($fp, 27769); + fseek($fp, 52012, SEEK_SET); + echo fread($fp, 27789); } else { - fseek($fp, 51249 + 27769, SEEK_SET); + fseek($fp, 52012 + 27789, SEEK_SET); echo fread($fp, 7004); } @@ -1991,7 +2005,7 @@ RewriteRule ^.*$ /index.php [END] if (!$dav->route($uri)) { http_response_code(404); - die('Invalid URL, sorry'); + die('Unknown URL, sorry.'); } exit; @@ -2004,7 +2018,7 @@ const WebDAVNavigator = (url, options) => { // https://github.com/commit-intl/micro-down const microdown=function(){function l(n,e,r){return"<"+n+(r?" "+Object.keys(r).map(function(n){return r[n]?n+'="'+(a(r[n])||"")+'"':""}).join(" "):"")+">"+e+""+n+">"}function c(n,e){return e=n.match(/^[+-]/m)?"ul":"ol",n?"<"+e+">"+n.replace(/(?:[+-]|\d+\.) +(.*)\n?(([ \t].*\n?)*)/g,function(n,e,r){return"