diff --git a/lib/wopi/files.php b/lib/wopi/files.php index 3d280fb..2e3e2ca 100644 --- a/lib/wopi/files.php +++ b/lib/wopi/files.php @@ -1,181 +1,199 @@ | +--------------------------------------------------------------------------+ | Author: Aleksander Machniak | +--------------------------------------------------------------------------+ */ require_once __DIR__ . "/../api/common.php"; require_once __DIR__ . "/../api/document.php"; class file_wopi_files extends file_api_document { /** * Request handler */ public function handle() { if (empty($this->api->path)) { throw new Exception("File ID not specified", file_api_core::ERROR_NOT_FOUND); } $file_id = $this->api->path[0]; $command = $this->api->path[1]; if ($file_id != $_SESSION['document_session']) { throw new Exception("File ID not specified", file_api_core::ERROR_UNAUTHORIZED); } if ($this->api->method == 'GET') { if (empty($command)) { return $this->document_info($file_id); } if ($command == 'contents') { return $this->document_get($file_id); } } else if ($this->api->method == 'PUT') { if ($command == 'contents') { return $this->document_put($file_id); } } /* else if (empty($command)) { switch ($api->method) // TODO case 'UNLOCK': // TODO case 'LOCK': // TODO case 'GET_LOCK': // TODO case 'REFRESH_LOCK': // TODO case 'PUT_RELATIVE': // TODO case 'RENAME_FILE': // TODO case 'DELETE': // TODO case 'PUT_USER_INFO': // TODO case 'GET_SHARE_URL': } } */ throw new Exception("Unknown method", file_api_core::ERROR_NOT_IMPLEMENTED); } /** * Return document informations * * JSON Response (only required attributes listed): * - BaseFileName: The string name of the file without a path. Used for * display in user interface (UI), and determining the extension * of the file. * - OwnerId: A string that uniquely identifies the owner of the file. * - Size: The size of the file in bytes, expressed as a long, * a 64-bit signed integer. * - UserId: A string value uniquely identifying the user currently * accessing the file. * - Version: The current version of the file based on the server’s file * version schema, as a string. This value must change when the file changes. */ protected function document_info($id) { $info = parent::document_info($id); // Convert file metadata to Wopi format // TODO: support more properties from // https://wopirest.readthedocs.io/en/latest/files/CheckFileInfo.html $result = array( 'BaseFileName' => $info['name'], 'Size' => $info['size'], 'Version' => $info['modified'], 'OwnerId' => $info['owner'], 'UserId' => $info['user'], - 'UserFriendlyName' => $info['user_name'], + 'UserFriendlyName' => $info['user_name'] ?: preg_replace('/@.*$/', '', $info['user']), 'UserCanWrite' => empty($info['readonly']), 'PostMessageOrigin' => $info['origin'], // Tell the client we do not support PutRelativeFile yet 'UserCanNotWriteRelative' => true, // Properties specific to Collabora Online 'HideSaveOption' => true, 'HideExportOption' => true, 'HidePrintOption' => true, 'EnableOwnerTermination' => true, - // TODO: 'UserExtraInfo' => ['avatar' => 'http://url/to/user/avatar', 'mail' => 'user@server.com'] + 'WatermarkText' => '', // ?? + 'DisablePrint' => false, + 'DisableExport' => false, + 'DisableCopy' => false, + 'DisableInactiveMessages' => true, + 'DisableChangeTrackingRecord' => true, + 'DisableChangeTrackingShow' => true, + 'HideChangeTrackingControls' => true, + // TODO: 'UserExtraInfo' => ['avatar' => 'http://url/to/user/avatar', 'mail' => $info['user']] + 'UserExtraInfo' => array(), ); + if ($info['modified']) { + try { + $dt = new DateTime('@' . $info['modified'], new DateTimeZone('UTC')); + $result['LastModifiedTime'] = $dt->format('Y-m-dTH:i:s') . '.0000000Z'; + } + catch (Exception $e) { + } + } + return $result; } /** * Update document file content * * Request Headers: * - X-WOPI-Lock: A string provided by the WOPI client in a previous Lock request. * Note that this header will not be included during document creation. * Collabora-specific Request Headers: * - X-LOOL-WOPI-IsModifiedByUser: true/false indicates whether the document * was modified by the user when they saved it. * - X-LOOL-WOPI-IsAutosave: true/false indicates whether the PutFile * is a result of autosave or the user pressing the Save button. * Response Headers: * - X-WOPI-Lock: A string value identifying the current lock on the file. * This header must always be included when responding to the request with 409. * It should not be included when responding to the request with 200 OK. * - X-WOPI-LockFailureReason: An optional string value indicating the cause * of a lock failure. * - X-WOPI-ItemVersion: An optional string value indicating the version of the file. * Its value should be the same as Version value in CheckFileInfo. * Status Codes: * - 409 Conflict: Lock mismatch/locked by another interface * - 413 Request Entity Too Large: File is too large; Host limit exceeded. */ protected function document_put($file_id) { // TODO: Locking parent::document_put($file_id); } /** * Return document file content * * Request Headers: * - X-WOPI-MaxExpectedSize: An integer specifying the upper bound * of the expected size of the file being requested. Optional. * The host should use the maximum value of a 4-byte integer * if this value is not set in the request. * Response Headers: * - X-WOPI-ItemVersion: An optional string value indicating the version of the file. * Its value should be the same as Version value in CheckFileInfo. * Status Codes: * - 412 File is larger than X-WOPI-MaxExpectedSize */ protected function document_get($id) { $doc_info = parent::document_info($id, false); $max_size = rcube_utils::request_header('X-WOPI-MaxExpectedSize') ?: 1024 * 1024 * 1024; // Check max file size if ($doc_info['size'] > $max_size) { throw new Exception("File exceeds max expected size", file_api_core::ERROR_PRECONDITION_FAILED); } header("X-WOPI-ItemVersion: " . $doc_info['modified']); parent::document_get($id); } }