Update dependencies
This commit is contained in:
parent
255e3a56d0
commit
b9e765be83
|
@ -247,11 +247,8 @@ class ErrorManager
|
|||
}
|
||||
}
|
||||
|
||||
$report = self::makeReport($e);
|
||||
$log = sprintf('=========== Error ref. %s ===========', $report->context->id)
|
||||
. PHP_EOL . PHP_EOL . (string) $e . PHP_EOL . PHP_EOL
|
||||
. '<errorReport>' . PHP_EOL . json_encode($report, \JSON_PRETTY_PRINT)
|
||||
. PHP_EOL . '</errorReport>' . PHP_EOL;
|
||||
extract(self::buildExceptionReport($e, false));
|
||||
unset($e);
|
||||
|
||||
// Log exception to file
|
||||
if (ini_get('log_errors'))
|
||||
|
@ -259,21 +256,12 @@ class ErrorManager
|
|||
error_log($log);
|
||||
}
|
||||
|
||||
$exception_title = $e->getMessage();
|
||||
unset($e);
|
||||
|
||||
// Disable any output if it was buffering
|
||||
if (ob_get_level())
|
||||
{
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
$html_report = null;
|
||||
|
||||
if (self::$enabled & self::DEVELOPMENT || self::$email_errors) {
|
||||
$html_report = self::htmlReport($report);
|
||||
}
|
||||
|
||||
$is_curl = 0 === strpos($_SERVER['HTTP_USER_AGENT'] ?? '', 'curl/');
|
||||
$is_cli = PHP_SAPI == 'cli';
|
||||
|
||||
|
@ -348,7 +336,7 @@ class ErrorManager
|
|||
|
||||
// Log exception to email
|
||||
if (self::$email_errors) {
|
||||
self::sendEmail($exception_title, $report, $log, $html_report);
|
||||
self::sendEmail($title, $report, $log, $html_report);
|
||||
}
|
||||
|
||||
// Send report to URL
|
||||
|
@ -362,6 +350,21 @@ class ErrorManager
|
|||
}
|
||||
}
|
||||
|
||||
static public function reportExceptionSilent(\Throwable $e): void
|
||||
{
|
||||
extract(self::buildExceptionReport($e));
|
||||
|
||||
// Log exception to file
|
||||
if (ini_get('log_errors'))
|
||||
{
|
||||
error_log($log);
|
||||
}
|
||||
|
||||
if (self::$email_errors) {
|
||||
self::sendEmail($title, $report, $log, $html_report);
|
||||
}
|
||||
}
|
||||
|
||||
static protected function sendEmail(string $title, \stdClass $report, string $log, string $html): void
|
||||
{
|
||||
// From: sender
|
||||
|
@ -419,6 +422,25 @@ class ErrorManager
|
|||
return $file;
|
||||
}
|
||||
|
||||
static public function buildExceptionReport(\Throwable $e, bool $force_html = false): array
|
||||
{
|
||||
$report = self::makeReport($e);
|
||||
$log = sprintf('=========== Error ref. %s ===========', $report->context->id)
|
||||
. PHP_EOL . PHP_EOL . (string) $e . PHP_EOL . PHP_EOL
|
||||
. '<errorReport>' . PHP_EOL . json_encode($report, \JSON_PRETTY_PRINT)
|
||||
. PHP_EOL . '</errorReport>' . PHP_EOL;
|
||||
|
||||
$html_report = null;
|
||||
|
||||
if ($force_html || self::$enabled & self::DEVELOPMENT || self::$email_errors) {
|
||||
$html_report = self::htmlReport($report);
|
||||
}
|
||||
|
||||
$title = $e->getMessage();
|
||||
|
||||
return compact('report', 'log', 'html_report', 'title');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a report from an exception
|
||||
*/
|
||||
|
@ -743,6 +765,7 @@ class ErrorManager
|
|||
if (self::$enabled)
|
||||
return true;
|
||||
|
||||
self::$context['request_started'] = $_SERVER['REQUEST_TIME_FLOAT'] ?? microtime(true);
|
||||
|
||||
self::$enabled = $type;
|
||||
|
||||
|
@ -800,8 +823,6 @@ class ErrorManager
|
|||
self::$context[$a] = $_SERVER[$b];
|
||||
}
|
||||
}
|
||||
|
||||
self::$context['request_started'] = microtime(true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -175,6 +175,47 @@ abstract class NextCloud
|
|||
|
||||
abstract public function assembleChunks(string $login, string $name, string $target, ?int $mtime): array;
|
||||
|
||||
abstract public function listChunks(string $login, string $name): array;
|
||||
|
||||
/**
|
||||
* Thumbnail API
|
||||
* @param string $uri URI path to the file we want a thumbnail for
|
||||
* @param int $width
|
||||
* @param int $height
|
||||
* @param bool $crop TRUE if a cropped image is desired
|
||||
* @param bool $preview TRUE if the thumbnail is for preview (in NextCloud Android, see below)
|
||||
*/
|
||||
public function serveThumbnail(string $uri, int $width, int $height, bool $crop = false, bool $preview = false): void
|
||||
{
|
||||
if (!preg_match('/\.(?:jpe?g|gif|png|webp)$/', $uri)) {
|
||||
http_response_code(404);
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't support thumbnails, but you are free to generate cropped thumbnails and send them to the HTTP client
|
||||
if (!$preview) {
|
||||
http_response_code(404);
|
||||
return;
|
||||
}
|
||||
// On Android, the app is annoying and asks to download the image
|
||||
// every time ("no resized image available") if no preview is available.
|
||||
// So to avoid that you can just redirect to the file if it's not too large
|
||||
// But you are free to extend this method and resize the image on the fly instead.
|
||||
else {
|
||||
$size = $this->server->getStorage()->properties($uri, ['DAV::getcontentlength'], 0);
|
||||
$size = count($size) ? current($size) : null;
|
||||
|
||||
if ($size > 1024*1024 || !$size) {
|
||||
http_response_code(404);
|
||||
return;
|
||||
}
|
||||
|
||||
$url = '/remote.php/dav/files/' . $uri;
|
||||
$this->server->log('=> Preview: redirect to %s', $url);
|
||||
header('Location: ' . $url);
|
||||
}
|
||||
}
|
||||
|
||||
// END OF ABSTRACT METHODS
|
||||
|
||||
/**
|
||||
|
@ -187,6 +228,9 @@ abstract class NextCloud
|
|||
'remote.php/webdav/uploads/' => 'chunked',
|
||||
'remote.php/dav/uploads/' => 'chunked',
|
||||
|
||||
// There's just 3 or 4 different endpoints for avatars, this is ridiculous
|
||||
'remote.php/dav/avatars/' => 'avatar',
|
||||
|
||||
// Main routes
|
||||
'remote.php/webdav/' => 'webdav', // desktop client
|
||||
'remote.php/dav' => 'webdav', // android client
|
||||
|
@ -214,10 +258,20 @@ abstract class NextCloud
|
|||
'index.php/avatar' => 'avatar',
|
||||
'ocs/v2.php/apps/dav/api/v1/direct' => 'direct_url',
|
||||
'remote.php/direct/' => 'direct',
|
||||
'avatars/' => 'avatar',
|
||||
];
|
||||
|
||||
const AUTH_REDIRECT_URL = 'nc://login/server:%s&user:%s&password:%s';
|
||||
|
||||
// *Every* different NextCloud/ownCloud app uses a different root path
|
||||
// this is ridiculous.
|
||||
// NC Desktop: /remote.php/dav/files/user// (note the double slash at the end)
|
||||
// NC iOS: /remote.php/dav/files/user (note the missing end slash)
|
||||
// ownCloud Android: /remote.php/dav/files/ (note the missing user part)
|
||||
// -> only at first, then it queries the correct path, WTF
|
||||
// See also https://github.com/nextcloud/server/issues/25867
|
||||
const WEBDAV_BASE_REGEXP = '~^.*remote\.php/(?:webdav/|dav/files/(?:(?:(?!/).)+(?:/+|$)|/*$))~';
|
||||
|
||||
public function setRootURL(string $url)
|
||||
{
|
||||
$this->root_url = $url;
|
||||
|
@ -241,6 +295,8 @@ abstract class NextCloud
|
|||
$uri = $_SERVER['REQUEST_URI'] ?? '/';
|
||||
}
|
||||
|
||||
$uri = parse_url($uri, PHP_URL_PATH);
|
||||
|
||||
$uri = ltrim($uri, '/');
|
||||
$uri = rawurldecode($uri);
|
||||
|
||||
|
@ -252,8 +308,6 @@ abstract class NextCloud
|
|||
|
||||
$route = current($route);
|
||||
|
||||
header('Access-Control-Allow-Origin: *', true);
|
||||
|
||||
$method = $_SERVER['REQUEST_METHOD'] ?? null;
|
||||
$this->server->log('NC <= %s %s => routed to: %s', $method, $uri, $route);
|
||||
|
||||
|
@ -293,6 +347,8 @@ abstract class NextCloud
|
|||
$this->server->log("NC => Body:\n%s", $json);
|
||||
}
|
||||
|
||||
$this->server->log('NC Sent response: %d', http_response_code());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -329,6 +385,17 @@ abstract class NextCloud
|
|||
{
|
||||
$this->requireAuth();
|
||||
|
||||
$method = $_SERVER['REQUEST_METHOD'] ?? '';
|
||||
|
||||
// ownCloud-Android is using a different preview API
|
||||
// remote.php/dav/files/user/name.jpg?x=224&y=224&c=&preview=1
|
||||
if (!empty($_GET['preview'])) {
|
||||
$x = (int) $_GET['x'] ?? 0;
|
||||
$y = (int) $_GET['y'] ?? 0;
|
||||
$this->serveThumbnail($uri, $x, $y, $x == $y);
|
||||
return;
|
||||
}
|
||||
|
||||
$base_uri = null;
|
||||
|
||||
// Find out which route we are using and replace URI
|
||||
|
@ -347,11 +414,10 @@ abstract class NextCloud
|
|||
throw new Exception('Invalid WebDAV URL', 404);
|
||||
}
|
||||
|
||||
// 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/(?:[^/]+/+)?!', $uri, $match)) {
|
||||
$base_uri = $match[0];
|
||||
$ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
|
||||
|
||||
if (preg_match(self::WEBDAV_BASE_REGEXP, $uri, $match)) {
|
||||
$base_uri = rtrim($match[0], '/') . '/';
|
||||
}
|
||||
|
||||
$this->server->prefix = $this->prefix;
|
||||
|
@ -362,14 +428,23 @@ abstract class NextCloud
|
|||
|
||||
public function nc_status(): array
|
||||
{
|
||||
if (stristr($_SERVER['HTTP_USER_AGENT'], 'owncloud')) {
|
||||
$name = 'ownCloud';
|
||||
$version = '10.11.0';
|
||||
}
|
||||
else {
|
||||
$name = 'NextCloud';
|
||||
$version = '24.0.4';
|
||||
}
|
||||
|
||||
return [
|
||||
'installed' => true,
|
||||
'maintenance' => false,
|
||||
'needsDbUpgrade' => false,
|
||||
'version' => '24.0.4.1',
|
||||
'versionstring' => '24.0.4',
|
||||
'version' => $version,
|
||||
'versionstring' => $version,
|
||||
'edition' => '',
|
||||
'productname' => 'NextCloud',
|
||||
'productname' => $name,
|
||||
'extendedSupport' => false,
|
||||
];
|
||||
}
|
||||
|
@ -483,10 +558,10 @@ abstract class NextCloud
|
|||
$user = $this->getUserName() ?? 'null';
|
||||
|
||||
return $this->nc_ocs([
|
||||
'id' => $user,
|
||||
'id' => sha1($user),
|
||||
'enabled' => true,
|
||||
'email' => null,
|
||||
'storageLocation' => '/secret/whoknows/' . $user,
|
||||
'storageLocation' => '/secret/whoknows/' . sha1($user),
|
||||
'role' => '',
|
||||
'display-name' => $user,
|
||||
'quota' => [
|
||||
|
@ -509,7 +584,7 @@ abstract class NextCloud
|
|||
return $this->nc_ocs([]);
|
||||
}
|
||||
|
||||
protected function nc_avatar(): ?array
|
||||
protected function nc_avatar(): void
|
||||
{
|
||||
throw new Exception('Not implemented', 404);
|
||||
}
|
||||
|
@ -647,29 +722,10 @@ abstract class NextCloud
|
|||
$height = $_GET['y'] ?? null;
|
||||
$crop = !($_GET['a'] ?? null);
|
||||
|
||||
if (!preg_match('/\.(?:jpe?g|gif|png|webp)$/', $uri)) {
|
||||
http_response_code(404);
|
||||
return;
|
||||
}
|
||||
|
||||
// On Android, the app is annoying and asks to download the image
|
||||
// every time ("no resized image available").
|
||||
// So to avoid that we will just redirect to the file if it is not too big.
|
||||
// But you are free to extend this method and resize the image on the fly
|
||||
$url = str_replace('%2F', '/', rawurlencode(rawurldecode($_GET['file'] ?? '')));
|
||||
$url = str_replace('%2F', '/', rawurldecode($_GET['file'] ?? ''));
|
||||
$url = ltrim($url, '/');
|
||||
|
||||
$size = current($this->storage->properties($url, ['DAV::getcontentlenth'], 0));
|
||||
|
||||
// 1 MB is a large image
|
||||
if ($size > 1024*1024) {
|
||||
http_response_code(404);
|
||||
return;
|
||||
}
|
||||
|
||||
$url = '/remote.php/dav/files/' . $url;
|
||||
$this->server->log('=> Preview: redirect to %s', $url);
|
||||
header('Location: ' . $url);
|
||||
$this->serveThumbnail($url, (int) $width, (int) $height, $crop, true);
|
||||
}
|
||||
|
||||
protected function nc_thumbnail(string $uri): void
|
||||
|
@ -680,8 +736,7 @@ abstract class NextCloud
|
|||
|
||||
list($width, $height, $uri) = array_pad(explode('/', $uri, 3), 3, null);
|
||||
|
||||
// We don't support this feature, but you are free to generate cropped thumbnails here
|
||||
http_response_code(404);
|
||||
$this->serveThumbnail($uri, (int)$width, (int)$height, $width == $height);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -736,7 +791,7 @@ abstract class NextCloud
|
|||
}
|
||||
elseif ($method == 'MOVE') {
|
||||
$dest = $_SERVER['HTTP_DESTINATION'];
|
||||
$dest = preg_replace('!^.*/remote.php/(?:web)?dav/(?:files/)?[^/]*/!', '', $dest);
|
||||
$dest = preg_replace(self::WEBDAV_BASE_REGEXP, '', $dest);
|
||||
$dest = trim(rawurldecode($dest), '/');
|
||||
|
||||
if (false !== strpos($dest, '..') || false !== strpos($dest, '//')) {
|
||||
|
@ -757,6 +812,8 @@ abstract class NextCloud
|
|||
header(sprintf('OC-ETag: "%s"', $return['etag']));
|
||||
}
|
||||
|
||||
$this->server->log("=> Chunks assembled to: %s", $dest);
|
||||
|
||||
if (!empty($return['created'])) {
|
||||
http_response_code(201);
|
||||
}
|
||||
|
@ -766,6 +823,26 @@ abstract class NextCloud
|
|||
}
|
||||
elseif ($method == 'DELETE' && !$part) {
|
||||
$this->deleteChunks($login, $dir);
|
||||
$this->server->log("=> Deleted chunks");
|
||||
}
|
||||
elseif ($method == 'PROPFIND') {
|
||||
header('HTTP/1.1 207 Multi-Status', true);
|
||||
$out = '<?xml version="1.0" encoding="utf-8"?>' . PHP_EOL;
|
||||
$out .= '<d:multistatus xmlns:d="DAV:">' . PHP_EOL;
|
||||
|
||||
foreach ($this->listChunks($login, $dir) as $chunk) {
|
||||
$out .= '<d:response>' . PHP_EOL;
|
||||
$chunk = '/' . $uri . '/' . $chunk;
|
||||
$out .= sprintf('<d:href>%s</d:href>', htmlspecialchars($chunk, ENT_XML1)) . PHP_EOL;
|
||||
$out .= '<d:propstat><d:prop><d:getcontenttype>application/octet-stream</d:getcontenttype><d:resoucetype/></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat>' . PHP_EOL;
|
||||
$out .= '</d:response>' . PHP_EOL;
|
||||
}
|
||||
|
||||
$out .= '</d:multistatus>';
|
||||
|
||||
echo $out;
|
||||
|
||||
$this->server->log("=> Body:\n%s", $out);
|
||||
}
|
||||
else {
|
||||
throw new Exception('Invalid method for chunked upload', 400);
|
||||
|
|
|
@ -82,6 +82,13 @@ class Server
|
|||
const SHARED_LOCK = 'shared';
|
||||
const EXCLUSIVE_LOCK = 'exclusive';
|
||||
|
||||
/**
|
||||
* Enable on-the-fly gzip compression
|
||||
* This can use a large amount of resources
|
||||
* @var boolean
|
||||
*/
|
||||
protected bool $enable_gzip = true;
|
||||
|
||||
/**
|
||||
* Base server URI (eg. "/index.php/webdav/")
|
||||
*/
|
||||
|
@ -114,6 +121,19 @@ class Server
|
|||
$this->base_uri = rtrim($uri, '/') . '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend max_execution_time so that upload/download of files don't expire if connection is slow
|
||||
*/
|
||||
protected function extendExecutionTime(): void
|
||||
{
|
||||
if (false === strpos(@ini_get('disable_functions'), 'set_time_limit')) {
|
||||
@set_time_limit(3600);
|
||||
}
|
||||
|
||||
@ini_set('max_execution_time', '3600');
|
||||
@ini_set('max_input_time', '3600');
|
||||
}
|
||||
|
||||
protected function _prefix(string $uri): string
|
||||
{
|
||||
if (!$this->prefix) {
|
||||
|
@ -269,6 +289,8 @@ class Server
|
|||
header('X-OC-MTime: accepted');
|
||||
}
|
||||
|
||||
$this->extendExecutionTime();
|
||||
|
||||
$created = $this->storage->put($uri, fopen('php://input', 'r'), $hash, $mtime);
|
||||
|
||||
$prop = $this->storage->properties($uri, ['DAV::getetag'], 0);
|
||||
|
@ -383,6 +405,8 @@ class Server
|
|||
throw new \RuntimeException('Invalid file array returned by ::get()');
|
||||
}
|
||||
|
||||
$this->extendExecutionTime();
|
||||
|
||||
$length = $start = $end = null;
|
||||
$gzip = false;
|
||||
|
||||
|
@ -402,17 +426,20 @@ class Server
|
|||
|
||||
$this->log('HTTP Range requested: %s-%s', $start, $end);
|
||||
}
|
||||
elseif (isset($_SERVER['HTTP_ACCEPT_ENCODING'])
|
||||
elseif ($this->enable_gzip
|
||||
&& isset($_SERVER['HTTP_ACCEPT_ENCODING'])
|
||||
&& false !== strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')
|
||||
&& isset($props['DAV::getcontentlength'])
|
||||
// Don't compress if size is larger than 8 MiB
|
||||
&& $props['DAV::getcontentlength'] < 8*1024*1024
|
||||
// Don't compress already compressed content
|
||||
&& !preg_match('/\.(?:mp4|m4a|zip|docx|xlsx|ods|odt|odp|7z|gz|bz2|rar|webm|ogg|mp3|ogm|flac|ogv|mkv|avi)$/i', $uri)) {
|
||||
&& !preg_match('/\.(?:cbz|cbr|cb7|mp4|m4a|zip|docx|xlsx|pptx|ods|odt|odp|7z|gz|bz2|lzma|lz|xz|apk|dmg|jar|rar|webm|ogg|mp3|ogm|flac|ogv|mkv|avi)$/i', $uri)) {
|
||||
$gzip = true;
|
||||
header('Content-Encoding: gzip', true);
|
||||
}
|
||||
|
||||
// Try to avoid common issues with output buffering and stuff
|
||||
if (function_exists('apache_setenv'))
|
||||
{
|
||||
if (function_exists('apache_setenv')) {
|
||||
@apache_setenv('no-gzip', 1);
|
||||
}
|
||||
|
||||
|
@ -495,9 +522,9 @@ class Server
|
|||
|
||||
if ($gzip) {
|
||||
$this->log('Using gzip output compression');
|
||||
$gzip = deflate_init(ZLIB_ENCODING_GZIP, ['level' => 9]);
|
||||
$gzip = deflate_init(ZLIB_ENCODING_GZIP);
|
||||
|
||||
$fp = fopen('php://memory', 'wb');
|
||||
$fp = fopen('php://temp', 'wb');
|
||||
|
||||
while (!feof($file['resource'])) {
|
||||
fwrite($fp, deflate_add($gzip, fread($file['resource'], 8192), ZLIB_NO_FLUSH));
|
||||
|
@ -517,14 +544,16 @@ class Server
|
|||
header('Content-Length: ' . $length, true);
|
||||
}
|
||||
|
||||
$block_size = 8192*4;
|
||||
|
||||
while (!feof($file['resource']) && ($end === null || $end > 0)) {
|
||||
$l = $end !== null ? min(8192, $end) : 8192;
|
||||
$l = $end !== null ? min($block_size, $end) : $block_size;
|
||||
|
||||
echo fread($file['resource'], $l);
|
||||
flush();
|
||||
|
||||
if (null !== $end) {
|
||||
$end -= 8192;
|
||||
$end -= $block_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,11 +26,17 @@ class WOPI
|
|||
const PROP_TOKEN = self::NS . ':token';
|
||||
const PROP_TOKEN_TTL = self::NS . ':token-ttl';
|
||||
const PROP_READ_ONLY = self::NS . ':ReadOnly';
|
||||
const PROP_USER_NAME = self::NS . ':FriendlyUserName';
|
||||
const PROP_USER_NAME = self::NS . ':UserFriendlyName';
|
||||
const PROP_USER_ID = self::NS . ':UserId';
|
||||
|
||||
protected AbstractStorage $storage;
|
||||
protected Server $server;
|
||||
|
||||
public function setStorage(AbstractStorage $storage)
|
||||
{
|
||||
$this->storage = $storage;
|
||||
}
|
||||
|
||||
public function setServer(Server $server)
|
||||
{
|
||||
$this->storage = $server->getStorage();
|
||||
|
@ -88,20 +94,26 @@ class WOPI
|
|||
|
||||
$this->server->log('WOPI: => Found doc_uri: %s', $uri);
|
||||
|
||||
|
||||
// GetFile
|
||||
if ($action == 'contents' && $method == 'GET') {
|
||||
$this->server->log('WOPI: => GetFile');
|
||||
$this->server->http_get($uri);
|
||||
}
|
||||
// PutFile
|
||||
elseif ($action == 'contents' && $method == 'POST') {
|
||||
$this->server->log('WOPI: => PutFile');
|
||||
$this->server->http_put($uri);
|
||||
}
|
||||
// CheckFileInfo
|
||||
elseif (!$action && $method == 'GET') {
|
||||
$this->server->log('WOPI: => CheckFileInfo');
|
||||
$this->getInfo($uri);
|
||||
}
|
||||
else {
|
||||
throw new Exception('Invalid URI', 404);
|
||||
}
|
||||
|
||||
$this->server->log('WOPI: <= 200');
|
||||
http_response_code(200); // This is required for Collabora
|
||||
}
|
||||
catch (Exception $e) {
|
||||
|
@ -121,6 +133,7 @@ class WOPI
|
|||
'DAV::getetag',
|
||||
self::PROP_READ_ONLY,
|
||||
self::PROP_USER_NAME,
|
||||
self::PROP_USER_ID,
|
||||
], 0);
|
||||
|
||||
$modified = !empty($props['DAV::getlastmodified']) ? $props['DAV::getlastmodified']->format(DATE_ISO8601) : null;
|
||||
|
@ -128,9 +141,9 @@ class WOPI
|
|||
|
||||
$data = [
|
||||
'BaseFileName' => basename($uri),
|
||||
'UserFriendlyName' => $props['DAV::PROP_USER_NAME'] ?? 'User',
|
||||
'OwnerId' => 1,
|
||||
'UserId' => 1,
|
||||
'UserFriendlyName' => $props[self::PROP_USER_NAME] ?? 'User',
|
||||
'OwnerId' => 0,
|
||||
'UserId' => $props[self::PROP_USER_ID] ?? 0,
|
||||
'Size' => $size,
|
||||
'Version' => $props['DAV::getetag'] ?? md5($uri . $size . $modified),
|
||||
];
|
||||
|
@ -142,9 +155,16 @@ class WOPI
|
|||
$data['ReadOnly'] = $props['self::PROP_READ_ONLY'] ?? false;
|
||||
$data['UserCanWrite'] = !$data['ReadOnly'];
|
||||
$data['UserCanRename'] = !$data['ReadOnly'];
|
||||
$data['DisableCopy'] = $data['ReadOnly'];
|
||||
$data['UserCanNotWriteRelative'] = true; // This requires you to implement file name UI
|
||||
//$data['DisablePrint'] = true;
|
||||
|
||||
$json = json_encode($data, JSON_PRETTY_PRINT);
|
||||
$this->server->log('WOPI: => Info: %s', $json);
|
||||
|
||||
http_response_code(200);
|
||||
echo json_encode($data, JSON_PRETTY_PRINT);
|
||||
header('Content-Type: application/json', true);
|
||||
echo $json;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -160,13 +180,13 @@ class WOPI
|
|||
* 'application/vnd.oasis.opendocument.presentation' => ['edit' => 'http://'...],
|
||||
* ]]
|
||||
*/
|
||||
public function discover(string $url): array
|
||||
static public function discover(string $url): array
|
||||
{
|
||||
if (function_exists('curl_init')) {
|
||||
$c = curl_init($url);
|
||||
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
|
||||
$r = curl_exec($c);
|
||||
$code = curl_getinfo(CURLINFO_HTTP_CODE);
|
||||
$code = curl_getinfo($c, CURLINFO_HTTP_CODE);
|
||||
|
||||
if ($code != 200) {
|
||||
throw new \RuntimeException(sprintf("Discovery URL returned an error: %d\n%s", $code, $r));
|
||||
|
@ -269,7 +289,7 @@ class WOPI
|
|||
$url = parse_url($url);
|
||||
|
||||
// Remove available options from URL
|
||||
$url['query'] = preg_replace('/<(\w+)=(\w+)&>/i', '', $url['query']);
|
||||
$url['query'] = preg_replace('/<(\w+)=(\w+)&>/i', '', $url['query'] ?? '');
|
||||
|
||||
// Set options
|
||||
parse_str($url['query'], $params);
|
||||
|
|
|
@ -134,6 +134,14 @@ class NextCloud extends WebDAV_NextCloud
|
|||
fclose($pointer);
|
||||
}
|
||||
|
||||
public function listChunks(string $login, string $name): array
|
||||
{
|
||||
$path = $this->temporary_chunks_path . '/' . $name;
|
||||
$list = glob($path . '/*');
|
||||
$list = array_map(fn($a) => str_replace($path . '/', '', $a), $list);
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function deleteChunks(string $login, string $name): void
|
||||
{
|
||||
$path = $this->temporary_chunks_path . '/' . $login . '/' . $name;
|
||||
|
|
Loading…
Reference in a new issue