77namespace OCA \Richdocuments \Service ;
88
99use Exception ;
10+ use GuzzleHttp \Exception \ClientException ;
1011use OCA \Richdocuments \AppConfig ;
1112use OCA \Richdocuments \WOPI \Parser ;
13+ use OCP \Http \Client \IClientService ;
14+ use OCP \IURLGenerator ;
1215use Symfony \Component \Console \Output \OutputInterface ;
1316
1417class ConnectivityService {
1518 public function __construct (
1619 private AppConfig $ appConfig ,
1720 private DiscoveryService $ discoveryService ,
1821 private CapabilitiesService $ capabilitiesService ,
22+ private IClientService $ clientService ,
23+ private IURLGenerator $ urlGenerator ,
1924 private Parser $ parser ,
2025 ) {
2126 }
2227
2328 /**
2429 * @throws Exception
2530 */
26- public function testDiscovery (OutputInterface $ output ): void {
31+ public function testDiscovery (? OutputInterface $ output = null ): void {
2732 $ this ->discoveryService ->resetCache ();
2833 $ this ->discoveryService ->fetch ();
29- $ output ->writeln ('<info>✓ Fetched /hosting/discovery endpoint</info> ' );
34+ $ output? ->writeln('<info>✓ Fetched /hosting/discovery endpoint</info> ' );
3035
3136 $ this ->parser ->getUrlSrcValue ('application/vnd.openxmlformats-officedocument.wordprocessingml.document ' );
32- $ output ->writeln ('<info>✓ Valid mimetype response</info> ' );
37+ $ output? ->writeln('<info>✓ Valid mimetype response</info> ' );
3338
3439 // FIXME: Optional when allowing generic WOPI servers
3540 $ this ->parser ->getUrlSrcValue ('Capabilities ' );
36- $ output ->writeln ('<info>✓ Valid capabilities entry</info> ' );
41+ $ output? ->writeln('<info>✓ Valid capabilities entry</info> ' );
3742 }
3843
39- public function testCapabilities (OutputInterface $ output ): void {
44+ public function testCapabilities (? OutputInterface $ output = null ): void {
4045 $ this ->capabilitiesService ->resetCache ();
4146 $ this ->capabilitiesService ->fetch ();
42- $ output ->writeln ('<info>✓ Fetched /hosting/capabilities endpoint</info> ' );
47+ $ output? ->writeln('<info>✓ Fetched /hosting/capabilities endpoint</info> ' );
4348
4449 if ($ this ->capabilitiesService ->getCapabilities () === []) {
4550 throw new \Exception ('Empty capabilities, unexpected result from ' . $ this ->capabilitiesService ->getCapabilitiesEndpoint ());
4651 }
47- $ output ->writeln ('<info>✓ Detected WOPI server: ' . $ this ->capabilitiesService ->getServerProductName () . ' ' . $ this ->capabilitiesService ->getProductVersion () . '</info> ' );
52+ $ output ?->writeln('<info>✓ Detected WOPI server: ' . $ this ->capabilitiesService ->getServerProductName () . ' ' . $ this ->capabilitiesService ->getProductVersion () . '</info> ' );
53+ }
54+
55+ public function testWopiAccess (?OutputInterface $ output = null ): void {
56+ $ client = $ this ->clientService ->newClient ();
57+ return ;
58+ if (!$ this ->capabilitiesService ->hasWopiAccessCheck ()) {
59+ return ;
60+ }
61+
62+ $ url = str_replace ('/hosting/capabilities ' , '/hosting/wopiAccessCheck ' , $ this ->capabilitiesService ->getCapabilitiesEndpoint ());
63+ $ callbackUrl = $ this ->appConfig ->getNextcloudUrl () ?: trim ($ this ->urlGenerator ->getAbsoluteURL ('' ), '/ ' );
64+
65+ try {
66+ $ result = $ client ->post ($ url , ['body ' => json_encode (['callbackUrl ' => $ callbackUrl . '/status.php ' ]), 'headers ' => ['Content-Type ' => 'application/json ' ]]);
67+ } catch (ClientException $ e ) {
68+ $ result = $ e ->getResponse ();
69+ }
70+ $ response = json_decode ($ result ->getBody (), true );
71+
72+ $ errorMessage = match ($ response ['status ' ]) {
73+ 'Ok ' => null ,
74+ 'NotHttpSuccess ' => 'The connection was successful but the response to the request was not 200 ' ,
75+ 'HostNotFound ' => 'DNS error, the host is not known by the Collabora Online server ' ,
76+ 'WopiHostNotAllowed ' => 'the host for this request is not allowed to be used as a WOPI Host, this is likely a configuration issue in coolwsd.xml ' ,
77+ 'ConnectionAborted ' => 'the connection was aborted by the destination server ' ,
78+ 'CertificateValidation ' => 'the certificate of the response is invalid or otherwise not accepted ' ,
79+ 'SslHandshakeFail ' => 'couldn’t establish an SSL/TLS connection ' ,
80+ 'MissingSsl ' => 'the response wasn’t using SSL/TLS contrary to expected ' ,
81+ 'NotHttps ' => 'HTTPS is expected to connect to Collabora Online as the WOPI host uses it. This is necessary to prevent mixed content errors. ' ,
82+ 'NoScheme ' => 'A scheme (http:// or https://) for the WOPI host URL must be specified ' ,
83+ 'Timeout ' => 'the request didn’t get a response within the time frame allowed ' ,
84+ 'UnspecifiedError ' => 'an error not handled previously ' ,
85+ default => 'Unknown error ' ,
86+ };
87+
88+ if ($ errorMessage ) {
89+ throw new \Exception ($ errorMessage );
90+ }
91+
92+ $ output ?->writeln('WOPI access was verified ' );
4893 }
4994
5095 /**
@@ -59,4 +104,10 @@ public function autoConfigurePublicUrl(): void {
59104 $ detectedUrl = $ this ->appConfig ->domainOnly ($ determinedUrl );
60105 $ this ->appConfig ->setAppValue ('public_wopi_url ' , $ detectedUrl );
61106 }
107+
108+ public function test (?OutputInterface $ output = null ): void {
109+ $ this ->testDiscovery ($ output );
110+ $ this ->testCapabilities ($ output );
111+ $ this ->testWopiAccess ($ output );
112+ }
62113}
0 commit comments