From 390fee0820847f7e62652422bc8930c8bd9220a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20T=C3=A2che?= Date: Tue, 16 Feb 2021 16:56:39 +0100 Subject: [PATCH] GH-46 Encodes url if not already done --- .../org/icepdf/ri/common/SwingController.java | 3 +- .../java/org/icepdf/ri/util/UriUtils.java | 86 +++++++++++++++++++ .../java/org/icepdf/ri/viewer/Launcher.java | 8 +- 3 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 viewer/viewer-awt/src/main/java/org/icepdf/ri/util/UriUtils.java diff --git a/viewer/viewer-awt/src/main/java/org/icepdf/ri/common/SwingController.java b/viewer/viewer-awt/src/main/java/org/icepdf/ri/common/SwingController.java index cb75b923f..cfe24f0e8 100644 --- a/viewer/viewer-awt/src/main/java/org/icepdf/ri/common/SwingController.java +++ b/viewer/viewer-awt/src/main/java/org/icepdf/ri/common/SwingController.java @@ -78,6 +78,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -2776,7 +2777,7 @@ public void openDav() { } private void openDavInSomeViewer(final String url) { - final DavFileClient client = new DavFileClient(url); + final DavFileClient client = new DavFileClient(UriUtils.encodePath(url, StandardCharsets.UTF_8)); if (document == null) { openDocument(client); } else if (windowManagementCallback != null) { diff --git a/viewer/viewer-awt/src/main/java/org/icepdf/ri/util/UriUtils.java b/viewer/viewer-awt/src/main/java/org/icepdf/ri/util/UriUtils.java new file mode 100644 index 000000000..f6397724b --- /dev/null +++ b/viewer/viewer-awt/src/main/java/org/icepdf/ri/util/UriUtils.java @@ -0,0 +1,86 @@ +package org.icepdf.ri.util; + +import java.io.ByteArrayOutputStream; +import java.nio.charset.Charset; +import java.util.regex.Pattern; + +public final class UriUtils { + + private static final Pattern URL_ESCAPE_PATTERN = Pattern.compile("%[0-9]{2}"); + + private UriUtils() { + } + + public static String decode(final String source, final Charset charset) { + final int length = source.length(); + if (length == 0) { + return source; + } + + final ByteArrayOutputStream baos = new ByteArrayOutputStream(length); + boolean changed = false; + for (int i = 0; i < length; i++) { + final int ch = source.charAt(i); + if (ch == '%') { + if (i + 2 < length) { + final char hex1 = source.charAt(i + 1); + final char hex2 = source.charAt(i + 2); + final int u = Character.digit(hex1, 16); + final int l = Character.digit(hex2, 16); + if (u == -1 || l == -1) { + throw new IllegalArgumentException("Invalid encoded sequence \"" + source.substring(i) + "\""); + } + baos.write((char) ((u << 4) + l)); + i += 2; + changed = true; + } else { + throw new IllegalArgumentException("Invalid encoded sequence \"" + source.substring(i) + "\""); + } + } else { + baos.write(ch); + } + } + return (changed ? new String(baos.toByteArray(), charset) : source); + } + + public static String encodePath(final String source, final Charset charset) { + //Avoid double encoding + if (source == null || source.isEmpty() || URL_ESCAPE_PATTERN.matcher(source).find()) { + return source; + } + + final byte[] bytes = source.getBytes(charset); + boolean original = true; + for (final byte b : bytes) { + if (!isAllowedPath(b)) { + original = false; + break; + } + } + if (original) { + return source; + } + + final ByteArrayOutputStream baos = new ByteArrayOutputStream(bytes.length); + for (final byte b : bytes) { + if (isAllowedPath(b)) { + baos.write(b); + } else { + baos.write('%'); + final char hex1 = Character.toUpperCase(Character.forDigit((b >> 4) & 0xF, 16)); + final char hex2 = Character.toUpperCase(Character.forDigit(b & 0xF, 16)); + baos.write(hex1); + baos.write(hex2); + } + } + return new String(baos.toByteArray(), charset); + } + + private static boolean isAllowedPath(final int c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || + c == '/' || c == '@' || c == ':' || c == '.' || c == '-' || c == '_' || c == '~' || + c == '!' || c == '$' || c == '&' || c == '\'' || c == '(' || c == ')' || c == '*' || + c == '+' || c == ',' || c == ';' || c == '='; + } + +} diff --git a/viewer/viewer-awt/src/main/java/org/icepdf/ri/viewer/Launcher.java b/viewer/viewer-awt/src/main/java/org/icepdf/ri/viewer/Launcher.java index 11404a823..45301aab7 100644 --- a/viewer/viewer-awt/src/main/java/org/icepdf/ri/viewer/Launcher.java +++ b/viewer/viewer-awt/src/main/java/org/icepdf/ri/viewer/Launcher.java @@ -17,12 +17,10 @@ import org.icepdf.core.util.Defs; import org.icepdf.ri.common.ViewModel; -import org.icepdf.ri.util.DavFileClient; -import org.icepdf.ri.util.FontPropertiesManager; -import org.icepdf.ri.util.URLAccess; -import org.icepdf.ri.util.ViewerPropertiesManager; +import org.icepdf.ri.util.*; import javax.swing.*; +import java.nio.charset.StandardCharsets; import java.text.MessageFormat; import java.util.ResourceBundle; import java.util.logging.Level; @@ -174,7 +172,7 @@ private static void run(String contentFile, urlAccess.dispose(); } if (contentDav != null && !contentDav.isEmpty()) { - windowManager.newWindow(new DavFileClient(contentDav, user, password)); + windowManager.newWindow(new DavFileClient(UriUtils.encodePath(contentDav, StandardCharsets.UTF_8), user, password)); }