]> git.basschouten.com Git - openhab-addons.git/commitdiff
[http] fix missing escaping of URLs (#9618)
authorJ-N-K <J-N-K@users.noreply.github.com>
Thu, 31 Dec 2020 15:55:03 +0000 (16:55 +0100)
committerGitHub <noreply@github.com>
Thu, 31 Dec 2020 15:55:03 +0000 (16:55 +0100)
Signed-off-by: Jan N. Klug <jan.n.klug@rub.de>
bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/HttpThingHandler.java
bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/Util.java
bundles/org.openhab.binding.http/src/main/java/org/openhab/binding/http/internal/http/RefreshingUrlCache.java

index f7bce25725997636f37b58888b0137715a8029dd..5b833bfc5ed4b3dfa97fa19ff72c62325f29efd7 100644 (file)
@@ -12,6 +12,7 @@
  */
 package org.openhab.binding.http.internal;
 
+import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.*;
@@ -302,10 +303,10 @@ public class HttpThingHandler extends BaseThingHandler {
     private void sendHttpValue(String commandUrl, String command, boolean isRetry) {
         try {
             // format URL
-            URI finalUrl = new URI(String.format(commandUrl, new Date(), command));
+            URI uri = Util.uriFromString(String.format(commandUrl, new Date(), command));
 
             // build request
-            Request request = httpClient.newRequest(finalUrl).timeout(config.timeout, TimeUnit.MILLISECONDS)
+            Request request = httpClient.newRequest(uri).timeout(config.timeout, TimeUnit.MILLISECONDS)
                     .method(config.commandMethod);
             if (config.commandMethod != HttpMethod.GET) {
                 final String contentType = config.contentType;
@@ -326,30 +327,30 @@ public class HttpThingHandler extends BaseThingHandler {
             });
 
             if (logger.isTraceEnabled()) {
-                logger.trace("Sending to '{}': {}", finalUrl, Util.requestToLogString(request));
+                logger.trace("Sending to '{}': {}", uri, Util.requestToLogString(request));
             }
 
             CompletableFuture<@Nullable Content> f = new CompletableFuture<>();
             f.exceptionally(e -> {
                 if (e instanceof HttpAuthException) {
                     if (isRetry) {
-                        logger.warn("Retry after authentication failure failed again for '{}', failing here", finalUrl);
+                        logger.warn("Retry after authentication failure failed again for '{}', failing here", uri);
                     } else {
                         AuthenticationStore authStore = httpClient.getAuthenticationStore();
-                        Authentication.Result authResult = authStore.findAuthenticationResult(finalUrl);
+                        Authentication.Result authResult = authStore.findAuthenticationResult(uri);
                         if (authResult != null) {
                             authStore.removeAuthenticationResult(authResult);
-                            logger.debug("Cleared authentication result for '{}', retrying immediately", finalUrl);
+                            logger.debug("Cleared authentication result for '{}', retrying immediately", uri);
                             sendHttpValue(commandUrl, command, true);
                         } else {
-                            logger.warn("Could not find authentication result for '{}', failing here", finalUrl);
+                            logger.warn("Could not find authentication result for '{}', failing here", uri);
                         }
                     }
                 }
                 return null;
             });
             request.send(new HttpResponseListener(f, null, config.bufferSize));
-        } catch (IllegalArgumentException | URISyntaxException e) {
+        } catch (IllegalArgumentException | URISyntaxException | MalformedURLException e) {
             logger.warn("Creating request for '{}' failed: {}", commandUrl, e.getMessage());
         }
     }
index b29b07ddc30795897f18c0e7db53c0f4d50057bb..ebc2f5899b6db7e83d5b00ebd3d48e4edc94c71d 100644 (file)
@@ -12,6 +12,7 @@
  */
 package org.openhab.binding.http.internal;
 
+import java.net.*;
 import java.nio.charset.StandardCharsets;
 import java.util.stream.Collectors;
 import java.util.stream.StreamSupport;
@@ -23,13 +24,18 @@ import org.eclipse.jetty.http.HttpField;
 
 /**
  * The {@link Util} is a utility class
- * channels
  *
  * @author Jan N. Klug - Initial contribution
  */
 @NonNullByDefault
 public class Util {
 
+    /**
+     * create a log string from a {@link org.eclipse.jetty.client.api.Request}
+     *
+     * @param request the request to log
+     * @return the string representing the request
+     */
     public static String requestToLogString(Request request) {
         ContentProvider contentProvider = request.getContent();
         String contentString = contentProvider == null ? "null"
@@ -41,4 +47,18 @@ public class Util {
 
         return logString;
     }
+
+    /**
+     * create an URI from a string, escaping all necessary characters
+     *
+     * @param s the URI as unescaped string
+     * @return URI correspondign to the input string
+     * @throws MalformedURLException
+     * @throws URISyntaxException
+     */
+    public static URI uriFromString(String s) throws MalformedURLException, URISyntaxException {
+        URL url = new URL(s);
+        return new URI(url.getProtocol(), url.getUserInfo(), IDN.toASCII(url.getHost()), url.getPort(), url.getPath(),
+                url.getQuery(), url.getRef());
+    }
 }
index f0ae9c9ec1e2eb5f048e3d6a4e0c36fa106ec621..a8515623eaaf6c832abbb5bef7158d901b7d4050 100644 (file)
@@ -12,8 +12,7 @@
  */
 package org.openhab.binding.http.internal.http;
 
-import java.net.URI;
-import java.net.URISyntaxException;
+import java.net.*;
 import java.util.Date;
 import java.util.List;
 import java.util.Optional;
@@ -76,11 +75,10 @@ public class RefreshingUrlCache {
 
         // format URL
         try {
-            URI finalUrl = new URI(String.format(this.url, new Date()));
+            URI uri = Util.uriFromString(String.format(this.url, new Date()));
+            logger.trace("Requesting refresh (retry={}) from '{}' with timeout {}ms", isRetry, uri, timeout);
 
-            logger.trace("Requesting refresh (retry={}) from '{}' with timeout {}ms", isRetry, finalUrl, timeout);
-
-            httpClient.newRequest(finalUrl).thenAccept(request -> {
+            httpClient.newRequest(uri).thenAccept(request -> {
                 request.timeout(timeout, TimeUnit.MILLISECONDS);
 
                 headers.forEach(header -> {
@@ -96,17 +94,16 @@ public class RefreshingUrlCache {
                 response.exceptionally(e -> {
                     if (e instanceof HttpAuthException) {
                         if (isRetry) {
-                            logger.warn("Retry after authentication  failure failed again for '{}', failing here",
-                                    finalUrl);
+                            logger.warn("Retry after authentication  failure failed again for '{}', failing here", uri);
                         } else {
                             AuthenticationStore authStore = httpClient.getAuthenticationStore();
-                            Authentication.Result authResult = authStore.findAuthenticationResult(finalUrl);
+                            Authentication.Result authResult = authStore.findAuthenticationResult(uri);
                             if (authResult != null) {
                                 authStore.removeAuthenticationResult(authResult);
-                                logger.debug("Cleared authentication result for '{}', retrying immediately", finalUrl);
+                                logger.debug("Cleared authentication result for '{}', retrying immediately", uri);
                                 refresh(true);
                             } else {
-                                logger.warn("Could not find authentication result for '{}', failing here", finalUrl);
+                                logger.warn("Could not find authentication result for '{}', failing here", uri);
                             }
                         }
                     }
@@ -114,19 +111,19 @@ public class RefreshingUrlCache {
                 }).thenAccept(this::processResult);
 
                 if (logger.isTraceEnabled()) {
-                    logger.trace("Sending to '{}': {}", finalUrl, Util.requestToLogString(request));
+                    logger.trace("Sending to '{}': {}", uri, Util.requestToLogString(request));
                 }
 
                 request.send(new HttpResponseListener(response, fallbackEncoding, bufferSize));
             }).exceptionally(e -> {
                 if (e instanceof CancellationException) {
-                    logger.debug("Request to URL {} was cancelled by thing handler.", finalUrl);
+                    logger.debug("Request to URL {} was cancelled by thing handler.", uri);
                 } else {
-                    logger.warn("Request to URL {} failed: {}", finalUrl, e.getMessage());
+                    logger.warn("Request to URL {} failed: {}", uri, e.getMessage());
                 }
                 return null;
             });
-        } catch (IllegalArgumentException | URISyntaxException e) {
+        } catch (IllegalArgumentException | URISyntaxException | MalformedURLException e) {
             logger.warn("Creating request for '{}' failed: {}", url, e.getMessage());
         }
     }