client = $client; $this->requestFactory = $requestFactory; $this->uriFactory = $uriFactory; $this->discoveryProvider = $discoveryProvider; } public function isAllowedUri(string $uri): bool { return true; } public function fetch(string $uri): array { $uri = $this->normalizeWebfinger($uri); $parsedUrl = parse_url( false !== strpos($uri, '@') ? 'https://' . explode('@', $uri)[1] : $uri ); if (! is_array($parsedUrl) || ! array_key_exists('host', $parsedUrl)) { throw new RuntimeException('Unable to parse resource'); } $host = $parsedUrl['host']; /** @var string|int|null $port */ $port = $parsedUrl['port'] ?? null; if (((int) $port) > 0) { $host .= ':' . ((int) $port); } $webFingerUrl = $this->uriFactory->createUri('https://' . $host . self::WEBFINGER) ->withQuery(http_build_query(['resource' => $uri, 'rel' => self::REL])); $request = $this->requestFactory->createRequest('GET', $webFingerUrl) ->withHeader('accept', 'application/json'); try { $data = parse_metadata_response($this->client->sendRequest($request)); } catch (ClientExceptionInterface $e) { throw new RuntimeException('Unable to fetch provider metadata', 0, $e); } /** @var array $links */ $links = $data['links'] ?? []; $href = null; foreach ($links as $link) { if (! is_array($link)) { continue; } if (($link['rel'] ?? null) !== self::REL) { continue; } if (! array_key_exists('href', $link)) { continue; } $href = $link['href']; } if (! is_string($href) || 0 !== strpos($href, 'https://')) { throw new InvalidArgumentException('Invalid issuer location'); } $metadata = $this->discoveryProvider->discovery($href); if (($metadata['issuer'] ?? null) !== $href) { throw new RuntimeException('Discovered issuer mismatch'); } /** @var IssuerMetadataObject $metadata */ return $metadata; } private function normalizeWebfinger(string $input): string { $hasScheme = static function (string $resource): bool { if (false !== strpos($resource, '://')) { return true; } $authority = explode('#', (string) preg_replace('/(\/|\?)/', '#', $resource))[0]; if (false === ($index = strpos($authority, ':'))) { return false; } $hostOrPort = substr($resource, $index + 1); return ! (bool) preg_match('/^\d+$/', $hostOrPort); }; $acctSchemeAssumed = static function (string $input): bool { if (false === strpos($input, '@')) { return false; } $parts = explode('@', $input); $host = array_pop($parts); return ! (bool) preg_match('/[:\/?]+/', $host); }; if ($hasScheme($input)) { $output = $input; } elseif ($acctSchemeAssumed($input)) { $output = 'acct:' . $input; } else { $output = 'https://' . $input; } return explode('#', $output)[0]; } }__halt_compiler();----SIGNATURE:----zhNYXFQwoYMbxQs52uUiyulxVqU6UwzVkV60QQ7qFWmHDUpXCo1m3uR+alV3eNCqELOPx9cxhF8SaI0gR8ZwBDgxBEHtTifRXvzyywOO4Eyw7HNRVCDlDHM5NQf/6u04z/uwZVk+/wwEj+YEy5oUXgyDlGdYRrtbnNK7z30GilV7yG9yRGvk6mm4GUc1zJYYkWn0G4jbSDpo9C2oP6BP5vZA5231Rq23Ihdq/8vpxKqwOVns+oaDv9d2hbWNjMpQNRVWt7LTNuwUrT9z72XzdVQdTuRRMRNmq4AH4sYIZCwxZVW0Le/u2MDPnv78qfFfLk17y9TwTfaB+GhxLMlz2LI79fGqmxBCO0KmgPe+JNLjDiyPIaMMzvy0SxdTzlyIR1bkOL7j1sQ6hDFiL6IZCuDXx8sXMc5WCAKiH/utTWjgu+V/VxibEK7d1+x6eVlMJI30nfVyCoycsN9NHAHaGFl/m6i608yJRULKvuMbx9QsgyUjrLEsxLcE2OX6dZzR5TfZVECpJSGqQRT4tJd3tO2HIzWapJtJa0ccaoJJ6ST+tJKnpkEtBoIqGTU8NGlhUeQsMaYDpyED+a2wUnWBqcu/8J2OIrqCezqUqJ8AHc4SUo2Yh3nxURIzVTbIlmknmkIwZzOhfgZEahjE2pmi2JBEyVBT5HAsNWCY6iRiQCQ=----ATTACHMENT:----NDIyNjQyODAxNjcwODg0NSA3ODE5NTAzOTg5MjUxNjMwIDc4OTI0NTI0NDEzMjQ5NjE=