users->fetchByIdentifier($tenant, $user); if (!$this->tenants->fetchById($tenant)?->getEnabled() || !($account['enabled'] ?? false)) { throw new HostException('Document access is unavailable.', 404); } $roles = (array) ($account['roles'] ?? []); $permissions = (array) ($account['permissions'] ?? []); if (!array_intersect(['admin', 'system.admin'], $roles) && !array_intersect(['*', 'service_wopi.*', 'service_wopi.view'], $permissions)) { throw new HostException('Document access is unavailable.', 404); } } /** @return array{label: string, content: string, version: string, size: int} */ public function read(string $tenant, string $user, string $resource, int $maxBytes): array { $this->authorize($tenant, $user); $id = ResourceIdentifier::fromString($resource); if (!$id instanceof EntityIdentifier || $id->provider() !== 'default' || $id->service() !== 'personal') { throw new HostException('This storage provider is not available for office viewing.', 404); } $service = $this->manager->serviceFetch($tenant, $user, $id->provider(), $id->service()); if (!$service instanceof PersonalService || !$service->getEnabled()) { throw new HostException('Document access is unavailable.', 404); } $entity = $this->manager->entityFetchBulk($tenant, $user, $id)[$resource] ?? null; if ($entity === null) { throw new HostException('Document access is unavailable.', 404); } if ($entity->getProperties()->size() > $maxBytes) { throw new HostException('Document exceeds the office viewing size limit.', 413); } $stream = $service->entityReadStream($id); if (!is_resource($stream)) { throw new HostException('Document access is unavailable.', 404); } try { $content = stream_get_contents($stream, $maxBytes + 1); } finally { fclose($stream); } if ($content === false) { throw new HostException('Could not read the document.', 503); } if (strlen($content) > $maxBytes) { throw new HostException('Document exceeds the office viewing size limit.', 413); } $label = $entity->getProperties()->getLabel(); return ['label' => $label, 'content' => $content, 'version' => hash('sha256', $label . "\0" . $content), 'size' => strlen($content)]; } }