]> git.basschouten.com Git - openhab-addons.git/commitdiff
[plex] Use https for local connections (#15306)
authormlobstein <michael.lobstein@gmail.com>
Wed, 26 Jul 2023 21:44:57 +0000 (16:44 -0500)
committerGitHub <noreply@github.com>
Wed, 26 Jul 2023 21:44:57 +0000 (23:44 +0200)
Signed-off-by: Michael Lobstein <michael.lobstein@gmail.com>
bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/handler/PlexApiConnector.java
bundles/org.openhab.binding.plex/src/main/java/org/openhab/binding/plex/internal/handler/PlexServerHandler.java

index 6f9db9018a82544d613d1626ac698c041621400d..7a95ece6e2e0d08504af946a6ac0a0a54fca3a64 100644 (file)
@@ -17,13 +17,17 @@ import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.Base64;
 import java.util.Properties;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.api.ContentResponse;
+import org.eclipse.jetty.client.api.Request;
 import org.eclipse.jetty.http.HttpHeader;
 import org.eclipse.jetty.websocket.api.Session;
 import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
@@ -129,11 +133,12 @@ public class PlexApiConnector {
      */
     public @Nullable MediaContainer getSessionData() {
         try {
-            String url = "http://" + host + ":" + String.valueOf(port) + "/status/sessions" + "?X-Plex-Token=" + token;
+            String url = "https://" + host + ":" + String.valueOf(port) + "/status/sessions" + "?X-Plex-Token=" + token;
             logger.debug("Getting session data '{}'", url);
-            MediaContainer mediaContainer = doHttpRequest("GET", url, getClientHeaders(), MediaContainer.class);
+            MediaContainer mediaContainer = getFromXml(doHttpRequest("GET", url, getClientHeaders(), false),
+                    MediaContainer.class);
             return mediaContainer;
-        } catch (IOException e) {
+        } catch (IOException | InterruptedException | TimeoutException | ExecutionException e) {
             logger.debug("An exception occurred while polling the PLEX Server: '{}'", e.getMessage());
             return null;
         }
@@ -151,7 +156,7 @@ public class PlexApiConnector {
     }
 
     /**
-     * This method will get an X-Token from the PLEX server if one is not provided in the bridge config
+     * This method will get an X-Token from the PLEX.tv server if one is not provided in the bridge config
      * and use this in the communication with the plex server
      */
     public void getToken() {
@@ -161,8 +166,8 @@ public class PlexApiConnector {
         headers.put("Authorization", "Basic " + authString);
 
         try {
-            user = doHttpRequest("POST", SIGNIN_URL, headers, User.class);
-        } catch (IOException e) {
+            user = getFromXml(doHttpRequest("POST", SIGNIN_URL, headers, true), User.class);
+        } catch (IOException | InterruptedException | TimeoutException | ExecutionException e) {
             logger.debug("An exception occurred while fetching PLEX user token :'{}'", e.getMessage(), e);
             throw new ConfigurationException("Error occurred while fetching PLEX user token, please check config");
         }
@@ -176,11 +181,12 @@ public class PlexApiConnector {
     }
 
     /**
-     * This method will get the Api information from the PLEX servers.
+     * This method will get the Api information from the PLEX.tv servers.
      */
     public boolean getApi() {
         try {
-            MediaContainer api = doHttpRequest("GET", API_URL, getClientHeaders(), MediaContainer.class);
+            MediaContainer api = getFromXml(doHttpRequest("GET", API_URL, getClientHeaders(), true),
+                    MediaContainer.class);
             logger.debug("MediaContainer {}", api.getSize());
             if (api.getDevice() != null) {
                 for (Device tmpDevice : api.getDevice()) {
@@ -198,28 +204,58 @@ public class PlexApiConnector {
                 }
             }
             return false;
-        } catch (IOException e) {
+        } catch (IOException | InterruptedException | TimeoutException | ExecutionException e) {
             logger.debug("An exception occurred while fetching API :'{}'", e.getMessage(), e);
         }
         return false;
     }
 
     /**
-     * Make an HTTP request and return the class object that was used when calling.
+     * Make an HTTP request and return the response as a string.
      *
-     * @param <T> Class being used(dto)
      * @param method GET/POST
      * @param url What URL to call
      * @param headers Additional headers that will be used
-     * @param type class type for the XML parsing
-     * @return Returns a class object from the data returned by the call
+     * @param verify Flag to indicate if ssl certificate checking should be done
+     * @return Returns a string of the http response
      * @throws IOException
+     * @throws ExecutionException
+     * @throws TimeoutException
+     * @throws InterruptedException
      */
-    private <T> T doHttpRequest(String method, String url, Properties headers, Class<T> type) throws IOException {
-        String response = HttpUtil.executeUrl(method, url, headers, null, null, REQUEST_TIMEOUT_MS);
+    private String doHttpRequest(String method, String url, Properties headers, boolean verify)
+            throws IOException, InterruptedException, TimeoutException, ExecutionException {
+        final String response;
+        if (verify) {
+            // Requests sent to the PLEX.tv servers should use certificate checking
+            response = HttpUtil.executeUrl(method, url, headers, null, null, REQUEST_TIMEOUT_MS);
+        } else {
+            // Requests sent to the local server need to bypass certificate checking via the custom httpClient
+            final Request request = httpClient.newRequest(url).method(HttpUtil.createHttpMethod(method));
+            for (String httpHeaderKey : headers.stringPropertyNames()) {
+                if (httpHeaderKey.equalsIgnoreCase(HttpHeader.USER_AGENT.toString())) {
+                    request.agent(headers.getProperty(httpHeaderKey));
+                } else {
+                    request.header(httpHeaderKey, headers.getProperty(httpHeaderKey));
+                }
+            }
+            final ContentResponse res = request.send();
+            response = res.getContentAsString();
+        }
+        logger.debug("HTTP response: {}", response);
+        return response;
+    }
+
+    /**
+     * Return the class object that was represented by the xml input string.
+     *
+     * @param response The xml response to parse
+     * @param type Class type for the XML parsing
+     * @return Returns a class object from the input sring
+     */
+    private <T> T getFromXml(String response, Class<T> type) {
         @SuppressWarnings("unchecked")
         T obj = (T) xStream.fromXML(response);
-        logger.debug("HTTP response {}", response);
         return obj;
     }
 
@@ -230,7 +266,7 @@ public class PlexApiConnector {
      */
     private Properties getClientHeaders() {
         Properties headers = new Properties();
-        headers.put(HttpHeader.USER_AGENT, "openHAB / PLEX binding "); // + VERSION);
+        headers.put(HttpHeader.USER_AGENT, "openHAB/" + org.openhab.core.OpenHAB.getVersion() + " PLEX binding");
         headers.put("X-Plex-Client-Identifier", CLIENT_ID);
         headers.put("X-Plex-Product", "openHAB");
         headers.put("X-Plex-Version", "");
@@ -377,11 +413,11 @@ public class PlexApiConnector {
 
         if (commandPath != null) {
             try {
-                String url = "http://" + host + ":" + String.valueOf(port) + commandPath;
+                String url = "https://" + host + ":" + String.valueOf(port) + commandPath;
                 Properties headers = getClientHeaders();
                 headers.put("X-Plex-Target-Client-Identifier", playerID);
-                HttpUtil.executeUrl("GET", url, headers, null, null, REQUEST_TIMEOUT_MS);
-            } catch (IOException e) {
+                doHttpRequest("GET", url, headers, false);
+            } catch (IOException | InterruptedException | TimeoutException | ExecutionException e) {
                 logger.debug("An exception occurred trying to send command '{}' to the player: {}", commandPath,
                         e.getMessage());
             }
index ca6a93ff1c87f6754758f1a5490e9916aaad5c2b..16423c07fa4f88fb9c69f69f942628477c76b463 100644 (file)
@@ -90,6 +90,7 @@ public class PlexServerHandler extends BaseBridgeHandler implements PlexUpdateLi
         try {
             SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
             sslContextFactory.setEndpointIdentificationAlgorithm(null);
+            sslContextFactory.setTrustAll(true);
             HttpClient localHttpClient = httpClient = httpClientFactory.createHttpClient(httpClientName,
                     sslContextFactory);
             localHttpClient.start();