isManaged() || $this->settings->get(Setting::VirusScanningEnabled) === true; } public function isManaged(): bool { return $this->managedAddress() !== ''; } public function address(): string { if ($this->isManaged()) { return $this->managedAddress(); } $stored = $this->settings->get(Setting::VirusScannerAddress); return is_string($stored) ? trim($stored) : ''; } /** * The largest file this installation sends to the scanner, in bytes. * Zero means no limit of our own — clamd's StreamMaxLength still * applies, and answers with tooLarge when it is reached. */ public function maxScanBytes(): int { return max(0, (int) $this->settings->get(Setting::VirusScanMaxSizeMb)) * 1024 * 1024; } /** What happens to a file the scanner could not open. */ public function blocksUnscannable(): bool { return $this->settings->get(Setting::VirusUnscannablePolicy) === 'block'; } /** Whether uploads wait for a scanner that is not answering. */ public function holdsWhileUnavailable(): bool { return $this->settings->get(Setting::VirusScannerDownPolicy) === 'hold'; } /** How long a file waits for an unreachable scanner before the policy applies. */ public function unavailableWaitMinutes(): int { return max(1, (int) $this->settings->get(Setting::VirusScannerWaitMinutes)); } /** How many already-stored files an hour-long backfill may scan per minute. */ public function existingScanRatePerMinute(): int { return max(1, (int) $this->settings->get(Setting::VirusScanExistingRatePerMinute)); } public function connectTimeoutSeconds(): int { return max(1, (int) config('projectsend.scanning.connect_timeout', 5)); } public function replyTimeoutSeconds(): int { return max(1, (int) config('projectsend.scanning.reply_timeout', 600)); } private function managedAddress(): string { $address = config('projectsend.scanning.address', ''); return is_string($address) ? trim($address) : ''; } }