getShare($shareId); if (!$share instanceof IShare) { return null; } $shareId = $share->getId(); $extra = $this->get($shareId); $wasInit = isset($extra["permissions"]); $checkExtra = $wasInit ? (int)$extra["permissions"] : self::NONE; [$availableExtra, $defaultPermissions] = $this->validation($share, $checkExtra, $wasInit); if ($availableExtra === 0 || ($availableExtra & $checkExtra) !== $checkExtra) { if (!empty($extra)) { $this->delete($shareId); } $this->logger->debug("Share " . $shareId . " does not support extra permissions"); return null; } if (empty($extra)) { $extra["id"] = -1; $extra["share_id"] = $share->getId(); $extra["permissions"] = $defaultPermissions; } $extra["type"] = $share->getShareType(); $extra["shareWith"] = $share->getSharedWith(); $extra["shareWithName"] = $share->getSharedWithDisplayName(); $extra["available"] = $availableExtra; return $extra; } /** * Get list extra permissions by shares */ public function getExtras(array $shares): array { $result = []; $shareIds = []; foreach ($shares as $share) { $shareIds[] = $share->getId(); } if (empty($shareIds)) { return $result; } $extras = $this->getList($shareIds); $noActualList = []; foreach ($shares as $share) { $currentExtra = []; foreach ($extras as $extra) { if ($extra["share_id"] === $share->getId()) { $currentExtra = $extra; } } $wasInit = isset($currentExtra["permissions"]); $checkExtra = $wasInit ? (int)$currentExtra["permissions"] : self::NONE; [$availableExtra, $defaultPermissions] = $this->validation($share, $checkExtra, $wasInit); if (($availableExtra === 0 || ($availableExtra & $checkExtra) !== $checkExtra) && !empty($currentExtra)) { $noActualList[] = $share->getId(); $currentExtra = []; } if ($availableExtra > 0) { if (empty($currentExtra)) { $currentExtra["id"] = -1; $currentExtra["share_id"] = $share->getId(); $currentExtra["permissions"] = $defaultPermissions; } $currentExtra["type"] = $share->getShareType(); $currentExtra["shareWith"] = $share->getSharedWith(); $currentExtra["shareWithName"] = $share->getSharedWithDisplayName(); $currentExtra["available"] = $availableExtra; if ($currentExtra["type"] === IShare::TYPE_ROOM && $this->talkManager !== null) { $rooms = $this->talkManager->searchRoomsByToken($currentExtra["shareWith"]); if (!empty($rooms)) { $room = $rooms[0]; $currentExtra["shareWith"] = $room->getName(); $currentExtra["shareWithName"] = $room->getName(); } } $result[] = $currentExtra; } } if (!empty($noActualList)) { $this->deleteList($noActualList); } return $result; } /** * Get extra permissions by share * * @param string $shareId - share identifier * @param integer $permissions - extra permissions bitmask * @param integer $extraId - extra permission identifier * * @return bool */ public function setExtra(string $shareId, int $permissions, int $extraId): bool { $result = false; $share = $this->getShare($shareId); if (!$share instanceof IShare) { return $result; } [$availableExtra, $defaultPermissions] = $this->validation($share, $permissions); if (($availableExtra & $permissions) !== $permissions) { $this->logger->debug("Share " . $shareId . " does not available to extend permissions"); return $result; } $result = $extraId > 0 ? $this->update($share->getId(), $permissions) : $this->insert($share->getId(), $permissions); return $result; } /** * Delete extra permissions for share */ public function delete(string $shareId): bool { $delete = $this->connection->prepare(" DELETE FROM `*PREFIX*" . self::TABLENAME_KEY . "` WHERE `share_id` = ? "); return (bool)$delete->execute([$shareId]); } /** * Delete list extra permissions * * @param array $shareIds - array of share identifiers */ public function deleteList(array $shareIds): bool { $condition = ""; if (count($shareIds) > 1) { $counter = count($shareIds); for ($i = 1; $i < $counter; $i++) { $condition .= " OR `share_id` = ?"; } } $delete = $this->connection->prepare(" DELETE FROM `*PREFIX*" . self::TABLENAME_KEY . "` WHERE `share_id` = ? " . $condition); return (bool)$delete->execute($shareIds); } /** * Get extra permissions for share */ private function get(string $shareId): array { $select = $this->connection->prepare(" SELECT id, share_id, permissions FROM `*PREFIX*" . self::TABLENAME_KEY . "` WHERE `share_id` = ? "); $result = $select->execute([$shareId]); $values = $result->fetch(); $value = is_array($values) ? $values : []; $result = []; if (!empty($value)) { $result = [ "id" => (int)$value["id"], "share_id" => (string)$value["share_id"], "permissions" => (int)$value["permissions"] ]; } return $result; } /** * Get list extra permissions */ private function getList(array $shareIds): array { $condition = ""; if (count($shareIds) > 1) { $counter = count($shareIds); for ($i = 1; $i < $counter; $i++) { $condition .= " OR `share_id` = ?"; } } $select = $this->connection->prepare(" SELECT id, share_id, permissions FROM `*PREFIX*" . self::TABLENAME_KEY . "` WHERE `share_id` = ? " . $condition); $result = $select->execute($shareIds); $values = $result->fetchAll(); $result = []; if (is_array($values)) { foreach ($values as $value) { $result[] = [ "id" => (int)$value["id"], "share_id" => (string)$value["share_id"], "permissions" => (int)$value["permissions"] ]; } } return $result; } /** * Store extra permissions for share * * @param string $shareId - share identifier * @param integer $permissions - permissions bitmask */ private function insert(string $shareId, int $permissions): bool { $insert = $this->connection->prepare(" INSERT INTO `*PREFIX*" . self::TABLENAME_KEY . "` (`share_id`, `permissions`) VALUES (?, ?) "); return (bool)$insert->execute([$shareId, $permissions]); } /** * Update extra permissions for share * * @param string $shareId - share identifier * @param int $permissions - permissions bitmask */ private function update(string $shareId, int $permissions): bool { $update = $this->connection->prepare(" UPDATE `*PREFIX*" . self::TABLENAME_KEY . "` SET `permissions` = ? WHERE `share_id` = ? "); return (bool)$update->execute([$permissions, $shareId]); } /** * Validation share on extend capability by extra permissions * * @param IShare $share - share * @param int $checkExtra - checkable extra permissions bitmask * @param bool $wasInit - was initialization extra */ private function validation(IShare $share, int $checkExtra, bool $wasInit = true): array { $availableExtra = self::NONE; $defaultExtra = self::NONE; if ($share->getShareType() !== IShare::TYPE_LINK && ($share->getPermissions() & Constants::PERMISSION_SHARE) === Constants::PERMISSION_SHARE && $this->config->getValueString('core', 'shareapi_allow_resharing', 'yes') === 'yes') { return [$availableExtra, $defaultExtra]; } $node = $share->getNode(); $ext = strtolower(pathinfo((string) $node->getName(), PATHINFO_EXTENSION)); $format = !empty($ext) && array_key_exists($ext, $this->appConfig->formatsSetting()) ? $this->appConfig->formatsSetting()[$ext] : null; if (!isset($format)) { return [$availableExtra, $defaultExtra]; } if (($share->getPermissions() & Constants::PERMISSION_UPDATE) === Constants::PERMISSION_UPDATE) { if (isset($format["modifyFilter"]) && $format["modifyFilter"] && ($checkExtra & self::COMMENT) !== self::COMMENT) { $availableExtra |= self::MODIFYFILTER; $defaultExtra |= self::MODIFYFILTER; } if (isset($format["review"]) && $format["review"]) { $availableExtra |= self::REVIEW; } if (isset($format["comment"]) && $format["comment"] && ($checkExtra & self::REVIEW) !== self::REVIEW && (($checkExtra & self::MODIFYFILTER) !== self::MODIFYFILTER)) { $availableExtra |= self::COMMENT; } if (isset($format["fillForms"]) && $format["fillForms"] && ($checkExtra & self::REVIEW) !== self::REVIEW) { $availableExtra |= self::FILLFORMS; } if (!$wasInit && ($defaultExtra & self::MODIFYFILTER) === self::MODIFYFILTER) { $availableExtra ^= self::COMMENT; } } return [$availableExtra, $defaultExtra]; } /** * Get origin share */ private function getShare(string $shareId): ?IShare { foreach (["ocinternal", "ocRoomShare", "ocCircleShare"] as $provider) { try { return $this->shareManager->getShareById("$provider:$shareId"); } catch (ShareNotFound) {} } $this->logger->error("getShare: share not found: $shareId"); return null; } }