From aed917cbf85e693f48f61120c8ba2ef0e8dfd008 Mon Sep 17 00:00:00 2001 From: whatisfahad Date: Sun, 23 Mar 2025 03:03:58 +0500 Subject: [PATCH 01/33] Fix URL validation and handling in URLUtil Signed-off-by: whatisfahad --- .../logic/importer/util/FileFieldParser.java | 21 ++++++++------- .../java/org/jabref/logic/util/URLUtil.java | 13 ++++++--- .../org/jabref/logic/net/URLUtilTest.java | 27 +++++++++++++++++++ 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java index 59527031e4c..98a4a189aa0 100644 --- a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java +++ b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java @@ -8,7 +8,6 @@ import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.LinkedFile; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -153,14 +152,18 @@ static LinkedFile convert(List entry) { while (entry.size() < 3) { entry.add(""); } - + LinkedFile field = null; if (LinkedFile.isOnlineLink(entry.get(1))) { + String url = entry.get(1); + if (!url.startsWith("http://") && !url.startsWith("https://")) { + url = "http://" + url; + } try { - field = new LinkedFile(entry.getFirst(), URLUtil.create(entry.get(1)), entry.get(2)); + field = new LinkedFile(entry.getFirst(), URLUtil.create(url), entry.get(2)); } catch (MalformedURLException e) { - // in case the URL is malformed, store it nevertheless - field = new LinkedFile(entry.getFirst(), entry.get(1), entry.get(2)); + // if the URL is still malformed, store it as a string + field = new LinkedFile(entry.getFirst(), url, entry.get(2)); } } else { String pathStr = entry.get(1); @@ -171,19 +174,19 @@ static LinkedFile convert(List entry) { } else { try { // there is no Path.isValidPath(String) method - field = new LinkedFile(entry.getFirst(), Path.of(pathStr), entry.get(2)); + field = new LinkedFile(entry.getFirst(), Path.of(pathStr), entry.get(2)); } catch (InvalidPathException e) { - // Ignored + // If the path is invalid, store it as a string LOGGER.debug("Invalid path object, continuing with string", e); field = new LinkedFile(entry.getFirst(), pathStr, entry.get(2)); } } } - + if (entry.size() > 3) { field.setSourceURL(entry.get(3)); } - + // link is the only mandatory field if (field.getDescription().isEmpty() && field.getLink().isEmpty() && !field.getFileType().isEmpty()) { field = new LinkedFile("", Path.of(field.getFileType()), ""); diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java index 403e79115eb..be6dc722e03 100644 --- a/src/main/java/org/jabref/logic/util/URLUtil.java +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -83,9 +83,9 @@ public static String cleanGoogleSearchURL(String url) { */ public static boolean isURL(String url) { try { - create(url); - return true; - } catch (MalformedURLException | IllegalArgumentException e) { + URI uri = new URI(url); + return uri.isAbsolute(); + } catch (URISyntaxException e) { return false; } } @@ -98,7 +98,12 @@ public static boolean isURL(String url) { * @throws MalformedURLException if the URL is malformed and cannot be converted to a {@link URL}. */ public static URL create(String url) throws MalformedURLException { - return createUri(url).toURL(); + if (!url.contains("://")) { + url = "http://" + url; + } + + URI uri = createUri(url); + return uri.toURL(); } /** diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java index 7de7b641fc5..bb9264a8022 100644 --- a/src/test/java/org/jabref/logic/net/URLUtilTest.java +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -1,6 +1,7 @@ package org.jabref.logic.net; import java.net.URI; +import java.net.URL; import org.jabref.logic.util.URLUtil; @@ -87,4 +88,30 @@ void createUriShouldHandlePipeCharacter() { URI uri = URLUtil.createUri(input); assertEquals("http://example.com/test%7Cfile", uri.toString()); } + @Test + void createShouldHandleRelativeURLs() throws Exception { + URL relativeUrl = URLUtil.create("www.example.com"); + assertEquals("http://www.example.com", relativeUrl.toString()); + + URL noWwwUrl = URLUtil.create("example.com"); + assertEquals("http://example.com", noWwwUrl.toString()); + } + + @Test + void createShouldHandleAbsoluteURLs() throws Exception { + URL absoluteHttpUrl = URLUtil.create("http://www.example.com"); + assertEquals("http://www.example.com", absoluteHttpUrl.toString()); + + URL absoluteHttpsUrl = URLUtil.create("https://www.example.com"); + assertEquals("https://www.example.com", absoluteHttpsUrl.toString()); + } + + @Test + void createShouldHandleOtherProtocols() throws Exception { + URL ftpUrl = URLUtil.create("ftp://example.com"); + assertEquals("ftp://example.com", ftpUrl.toString()); + + URL fileUrl = URLUtil.create("file:///path/to/file"); + assertEquals("file:/path/to/file", fileUrl.toString()); +} } From 4b99f41a0d444508c87718a69ab50a35f68246f0 Mon Sep 17 00:00:00 2001 From: whatisfahad Date: Sun, 23 Mar 2025 03:55:58 +0500 Subject: [PATCH 02/33] refactor: Replace "://" with PROTOCOL_SEPARATOR constant --- .../logic/importer/util/FileFieldParser.java | 50 ++++++++----------- .../java/org/jabref/logic/util/URLUtil.java | 5 +- 2 files changed, 23 insertions(+), 32 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java index 98a4a189aa0..bf732a59c12 100644 --- a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java +++ b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java @@ -19,6 +19,8 @@ public class FileFieldParser { private StringBuilder charactersOfCurrentElement; private boolean windowsPath; + private static final String HTTP_PREFIX = "http://"; + private static final String HTTPS_PREFIX = "https://"; public FileFieldParser(String value) { if (value == null) { @@ -50,28 +52,18 @@ public static List parse(String value) { public List parse() { List files = new ArrayList<>(); - + if ((value == null) || value.trim().isEmpty()) { return files; } - - if (LinkedFile.isOnlineLink(value.trim())) { - // needs to be modifiable - try { - return List.of(new LinkedFile(URLUtil.create(value), "")); - } catch (MalformedURLException e) { - LOGGER.error("invalid url", e); - return files; - } - } - - // data of each LinkedFile as split string + + // Data of each LinkedFile as split string List linkedFileData = new ArrayList<>(); - + resetDataStructuresForNextElement(); boolean inXmlChar = false; boolean escaped = false; - + for (int i = 0; i < value.length(); i++) { char c = value.charAt(i); if (!escaped && (c == '\\')) { @@ -101,7 +93,7 @@ public List parse() { // We are at the second : (position 3 in the example) and "just" add it to the current element charactersOfCurrentElement.append(c); windowsPath = true; - // special case for zotero absolute path on windows that do not have a colon in front + // special case for Zotero absolute path on Windows that do not have a colon in front // e.g. A:\zotero\paper.pdf } else if (charactersOfCurrentElement.length() == 1 && value.charAt(i + 1) == '\\') { charactersOfCurrentElement.append(c); @@ -113,8 +105,9 @@ public List parse() { } } else if (!escaped && (c == ';') && !inXmlChar) { linkedFileData.add(charactersOfCurrentElement.toString()); - files.add(convert(linkedFileData)); - + LinkedFile field = convert(linkedFileData); + files.add(field); + // next iteration resetDataStructuresForNextElement(); } else { @@ -126,8 +119,10 @@ public List parse() { linkedFileData.add(charactersOfCurrentElement.toString()); } if (!linkedFileData.isEmpty()) { - files.add(convert(linkedFileData)); + LinkedFile field = convert(linkedFileData); + files.add(field); } + return files; } @@ -152,18 +147,13 @@ static LinkedFile convert(List entry) { while (entry.size() < 3) { entry.add(""); } - + LinkedFile field = null; if (LinkedFile.isOnlineLink(entry.get(1))) { - String url = entry.get(1); - if (!url.startsWith("http://") && !url.startsWith("https://")) { - url = "http://" + url; - } try { - field = new LinkedFile(entry.getFirst(), URLUtil.create(url), entry.get(2)); + field = new LinkedFile(entry.getFirst(), URLUtil.create(entry.get(1)), entry.get(2)); } catch (MalformedURLException e) { - // if the URL is still malformed, store it as a string - field = new LinkedFile(entry.getFirst(), url, entry.get(2)); + field = new LinkedFile(entry.getFirst(), entry.get(1), entry.get(2)); } } else { String pathStr = entry.get(1); @@ -174,7 +164,7 @@ static LinkedFile convert(List entry) { } else { try { // there is no Path.isValidPath(String) method - field = new LinkedFile(entry.getFirst(), Path.of(pathStr), entry.get(2)); + field = new LinkedFile(entry.getFirst(), Path.of(pathStr), entry.get(2)); } catch (InvalidPathException e) { // If the path is invalid, store it as a string LOGGER.debug("Invalid path object, continuing with string", e); @@ -182,11 +172,11 @@ static LinkedFile convert(List entry) { } } } - + if (entry.size() > 3) { field.setSourceURL(entry.get(3)); } - + // link is the only mandatory field if (field.getDescription().isEmpty() && field.getLink().isEmpty() && !field.getFileType().isEmpty()) { field = new LinkedFile("", Path.of(field.getFileType()), ""); diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java index be6dc722e03..64b3ef9fd59 100644 --- a/src/main/java/org/jabref/logic/util/URLUtil.java +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -15,6 +15,7 @@ * For GUI-oriented URL utilities see {@link org.jabref.gui.fieldeditors.URLUtil}. */ public class URLUtil { + private static final String PROTOCOL_SEPARATOR = "://"; private static final String URL_REGEX = "(?i)\\b((?:https?|ftp)://[^\\s]+)"; @@ -98,10 +99,10 @@ public static boolean isURL(String url) { * @throws MalformedURLException if the URL is malformed and cannot be converted to a {@link URL}. */ public static URL create(String url) throws MalformedURLException { - if (!url.contains("://")) { + if (!url.contains(PROTOCOL_SEPARATOR)) { url = "http://" + url; } - + URI uri = createUri(url); return uri.toURL(); } From 4ea9e06509bd62641fd461ea7e6b7c95884b3a1b Mon Sep 17 00:00:00 2001 From: whatisfahad Date: Mon, 24 Mar 2025 03:27:08 +0500 Subject: [PATCH 03/33] refactor: Remove duplicate HTTP and HTTPS prefix constants in FileFieldParser --- .../java/org/jabref/logic/importer/util/FileFieldParser.java | 5 +++-- src/test/java/org/jabref/logic/net/URLUtilTest.java | 5 ++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java index bf732a59c12..45ac752ed8f 100644 --- a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java +++ b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java @@ -8,19 +8,20 @@ import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.LinkedFile; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class FileFieldParser { private static final Logger LOGGER = LoggerFactory.getLogger(FileFieldParser.class); + private static final String HTTP_PREFIX = "http://"; + private static final String HTTPS_PREFIX = "https://"; private final String value; private StringBuilder charactersOfCurrentElement; private boolean windowsPath; - private static final String HTTP_PREFIX = "http://"; - private static final String HTTPS_PREFIX = "https://"; public FileFieldParser(String value) { if (value == null) { diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java index bb9264a8022..81aa5fdc3c8 100644 --- a/src/test/java/org/jabref/logic/net/URLUtilTest.java +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -4,12 +4,10 @@ import java.net.URL; import org.jabref.logic.util.URLUtil; - -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; class URLUtilTest { @@ -88,6 +86,7 @@ void createUriShouldHandlePipeCharacter() { URI uri = URLUtil.createUri(input); assertEquals("http://example.com/test%7Cfile", uri.toString()); } + @Test void createShouldHandleRelativeURLs() throws Exception { URL relativeUrl = URLUtil.create("www.example.com"); From 5f22761907ba3e735b2e890d66e26da136791d76 Mon Sep 17 00:00:00 2001 From: whatisfahad Date: Mon, 24 Mar 2025 04:09:01 +0500 Subject: [PATCH 04/33] refactor: Simplify LinkedFile handling in FileFieldParser and improve URL validation --- .../logic/importer/util/FileFieldParser.java | 23 ++++++++++++------- .../org/jabref/logic/net/URLUtilTest.java | 2 +- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java index 45ac752ed8f..0bad0ca3eeb 100644 --- a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java +++ b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java @@ -57,8 +57,18 @@ public List parse() { if ((value == null) || value.trim().isEmpty()) { return files; } - - // Data of each LinkedFile as split string + + if (LinkedFile.isOnlineLink(value.trim())) { + // needs to be modifiable + try { + return List.of(new LinkedFile(URLUtil.create(value), "")); + } catch (MalformedURLException e) { + LOGGER.error("invalid url", e); + return files; + } + } + + // data of each LinkedFile as split string List linkedFileData = new ArrayList<>(); resetDataStructuresForNextElement(); @@ -106,22 +116,19 @@ public List parse() { } } else if (!escaped && (c == ';') && !inXmlChar) { linkedFileData.add(charactersOfCurrentElement.toString()); - LinkedFile field = convert(linkedFileData); - files.add(field); - - // next iteration + files.add(convert(linkedFileData)); resetDataStructuresForNextElement(); } else { charactersOfCurrentElement.append(c); } escaped = false; } + if (charactersOfCurrentElement.length() > 0) { linkedFileData.add(charactersOfCurrentElement.toString()); } if (!linkedFileData.isEmpty()) { - LinkedFile field = convert(linkedFileData); - files.add(field); + files.add(convert(linkedFileData)); } return files; diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java index 81aa5fdc3c8..835533ecf09 100644 --- a/src/test/java/org/jabref/logic/net/URLUtilTest.java +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -4,10 +4,10 @@ import java.net.URL; import org.jabref.logic.util.URLUtil; +import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Test; class URLUtilTest { From 04b92feec0f30bfab2a5b9f1042e408548d20fe8 Mon Sep 17 00:00:00 2001 From: whatisfahad Date: Mon, 24 Mar 2025 04:16:04 +0500 Subject: [PATCH 05/33] refactor: Clean up whitespace and improve comments in FileFieldParser --- .../org/jabref/logic/importer/util/FileFieldParser.java | 9 ++++++--- src/test/java/org/jabref/logic/net/URLUtilTest.java | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java index 0bad0ca3eeb..7f7d956cfdf 100644 --- a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java +++ b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java @@ -53,7 +53,7 @@ public static List parse(String value) { public List parse() { List files = new ArrayList<>(); - + if ((value == null) || value.trim().isEmpty()) { return files; } @@ -70,7 +70,7 @@ public List parse() { // data of each LinkedFile as split string List linkedFileData = new ArrayList<>(); - + resetDataStructuresForNextElement(); boolean inXmlChar = false; boolean escaped = false; @@ -104,7 +104,7 @@ public List parse() { // We are at the second : (position 3 in the example) and "just" add it to the current element charactersOfCurrentElement.append(c); windowsPath = true; - // special case for Zotero absolute path on Windows that do not have a colon in front + // special case for zotero absolute path on windows that do not have a colon in front // e.g. A:\zotero\paper.pdf } else if (charactersOfCurrentElement.length() == 1 && value.charAt(i + 1) == '\\') { charactersOfCurrentElement.append(c); @@ -117,6 +117,8 @@ public List parse() { } else if (!escaped && (c == ';') && !inXmlChar) { linkedFileData.add(charactersOfCurrentElement.toString()); files.add(convert(linkedFileData)); + + // next iteration resetDataStructuresForNextElement(); } else { charactersOfCurrentElement.append(c); @@ -161,6 +163,7 @@ static LinkedFile convert(List entry) { try { field = new LinkedFile(entry.getFirst(), URLUtil.create(entry.get(1)), entry.get(2)); } catch (MalformedURLException e) { + // in case the URL is malformed, store it nevertheless field = new LinkedFile(entry.getFirst(), entry.get(1), entry.get(2)); } } else { diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java index 835533ecf09..df94456f3b8 100644 --- a/src/test/java/org/jabref/logic/net/URLUtilTest.java +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -4,7 +4,9 @@ import java.net.URL; import org.jabref.logic.util.URLUtil; + import org.junit.jupiter.api.Test; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; From 52bba0f209d0df94316994a218dd0ae1748bfa50 Mon Sep 17 00:00:00 2001 From: whatisfahad Date: Sun, 23 Mar 2025 03:03:58 +0500 Subject: [PATCH 06/33] Fix URL validation and handling in URLUtil Signed-off-by: whatisfahad --- .../logic/importer/util/FileFieldParser.java | 21 ++++++++------- .../java/org/jabref/logic/util/URLUtil.java | 13 ++++++--- .../org/jabref/logic/net/URLUtilTest.java | 27 +++++++++++++++++++ 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java index 59527031e4c..98a4a189aa0 100644 --- a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java +++ b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java @@ -8,7 +8,6 @@ import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.LinkedFile; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -153,14 +152,18 @@ static LinkedFile convert(List entry) { while (entry.size() < 3) { entry.add(""); } - + LinkedFile field = null; if (LinkedFile.isOnlineLink(entry.get(1))) { + String url = entry.get(1); + if (!url.startsWith("http://") && !url.startsWith("https://")) { + url = "http://" + url; + } try { - field = new LinkedFile(entry.getFirst(), URLUtil.create(entry.get(1)), entry.get(2)); + field = new LinkedFile(entry.getFirst(), URLUtil.create(url), entry.get(2)); } catch (MalformedURLException e) { - // in case the URL is malformed, store it nevertheless - field = new LinkedFile(entry.getFirst(), entry.get(1), entry.get(2)); + // if the URL is still malformed, store it as a string + field = new LinkedFile(entry.getFirst(), url, entry.get(2)); } } else { String pathStr = entry.get(1); @@ -171,19 +174,19 @@ static LinkedFile convert(List entry) { } else { try { // there is no Path.isValidPath(String) method - field = new LinkedFile(entry.getFirst(), Path.of(pathStr), entry.get(2)); + field = new LinkedFile(entry.getFirst(), Path.of(pathStr), entry.get(2)); } catch (InvalidPathException e) { - // Ignored + // If the path is invalid, store it as a string LOGGER.debug("Invalid path object, continuing with string", e); field = new LinkedFile(entry.getFirst(), pathStr, entry.get(2)); } } } - + if (entry.size() > 3) { field.setSourceURL(entry.get(3)); } - + // link is the only mandatory field if (field.getDescription().isEmpty() && field.getLink().isEmpty() && !field.getFileType().isEmpty()) { field = new LinkedFile("", Path.of(field.getFileType()), ""); diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java index 403e79115eb..be6dc722e03 100644 --- a/src/main/java/org/jabref/logic/util/URLUtil.java +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -83,9 +83,9 @@ public static String cleanGoogleSearchURL(String url) { */ public static boolean isURL(String url) { try { - create(url); - return true; - } catch (MalformedURLException | IllegalArgumentException e) { + URI uri = new URI(url); + return uri.isAbsolute(); + } catch (URISyntaxException e) { return false; } } @@ -98,7 +98,12 @@ public static boolean isURL(String url) { * @throws MalformedURLException if the URL is malformed and cannot be converted to a {@link URL}. */ public static URL create(String url) throws MalformedURLException { - return createUri(url).toURL(); + if (!url.contains("://")) { + url = "http://" + url; + } + + URI uri = createUri(url); + return uri.toURL(); } /** diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java index 7de7b641fc5..bb9264a8022 100644 --- a/src/test/java/org/jabref/logic/net/URLUtilTest.java +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -1,6 +1,7 @@ package org.jabref.logic.net; import java.net.URI; +import java.net.URL; import org.jabref.logic.util.URLUtil; @@ -87,4 +88,30 @@ void createUriShouldHandlePipeCharacter() { URI uri = URLUtil.createUri(input); assertEquals("http://example.com/test%7Cfile", uri.toString()); } + @Test + void createShouldHandleRelativeURLs() throws Exception { + URL relativeUrl = URLUtil.create("www.example.com"); + assertEquals("http://www.example.com", relativeUrl.toString()); + + URL noWwwUrl = URLUtil.create("example.com"); + assertEquals("http://example.com", noWwwUrl.toString()); + } + + @Test + void createShouldHandleAbsoluteURLs() throws Exception { + URL absoluteHttpUrl = URLUtil.create("http://www.example.com"); + assertEquals("http://www.example.com", absoluteHttpUrl.toString()); + + URL absoluteHttpsUrl = URLUtil.create("https://www.example.com"); + assertEquals("https://www.example.com", absoluteHttpsUrl.toString()); + } + + @Test + void createShouldHandleOtherProtocols() throws Exception { + URL ftpUrl = URLUtil.create("ftp://example.com"); + assertEquals("ftp://example.com", ftpUrl.toString()); + + URL fileUrl = URLUtil.create("file:///path/to/file"); + assertEquals("file:/path/to/file", fileUrl.toString()); +} } From fb8324b8c4ac5a662d14e962038e6a37addea918 Mon Sep 17 00:00:00 2001 From: whatisfahad Date: Sun, 23 Mar 2025 03:55:58 +0500 Subject: [PATCH 07/33] refactor: Replace "://" with PROTOCOL_SEPARATOR constant --- .../logic/importer/util/FileFieldParser.java | 50 ++++++++----------- .../java/org/jabref/logic/util/URLUtil.java | 5 +- 2 files changed, 23 insertions(+), 32 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java index 98a4a189aa0..bf732a59c12 100644 --- a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java +++ b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java @@ -19,6 +19,8 @@ public class FileFieldParser { private StringBuilder charactersOfCurrentElement; private boolean windowsPath; + private static final String HTTP_PREFIX = "http://"; + private static final String HTTPS_PREFIX = "https://"; public FileFieldParser(String value) { if (value == null) { @@ -50,28 +52,18 @@ public static List parse(String value) { public List parse() { List files = new ArrayList<>(); - + if ((value == null) || value.trim().isEmpty()) { return files; } - - if (LinkedFile.isOnlineLink(value.trim())) { - // needs to be modifiable - try { - return List.of(new LinkedFile(URLUtil.create(value), "")); - } catch (MalformedURLException e) { - LOGGER.error("invalid url", e); - return files; - } - } - - // data of each LinkedFile as split string + + // Data of each LinkedFile as split string List linkedFileData = new ArrayList<>(); - + resetDataStructuresForNextElement(); boolean inXmlChar = false; boolean escaped = false; - + for (int i = 0; i < value.length(); i++) { char c = value.charAt(i); if (!escaped && (c == '\\')) { @@ -101,7 +93,7 @@ public List parse() { // We are at the second : (position 3 in the example) and "just" add it to the current element charactersOfCurrentElement.append(c); windowsPath = true; - // special case for zotero absolute path on windows that do not have a colon in front + // special case for Zotero absolute path on Windows that do not have a colon in front // e.g. A:\zotero\paper.pdf } else if (charactersOfCurrentElement.length() == 1 && value.charAt(i + 1) == '\\') { charactersOfCurrentElement.append(c); @@ -113,8 +105,9 @@ public List parse() { } } else if (!escaped && (c == ';') && !inXmlChar) { linkedFileData.add(charactersOfCurrentElement.toString()); - files.add(convert(linkedFileData)); - + LinkedFile field = convert(linkedFileData); + files.add(field); + // next iteration resetDataStructuresForNextElement(); } else { @@ -126,8 +119,10 @@ public List parse() { linkedFileData.add(charactersOfCurrentElement.toString()); } if (!linkedFileData.isEmpty()) { - files.add(convert(linkedFileData)); + LinkedFile field = convert(linkedFileData); + files.add(field); } + return files; } @@ -152,18 +147,13 @@ static LinkedFile convert(List entry) { while (entry.size() < 3) { entry.add(""); } - + LinkedFile field = null; if (LinkedFile.isOnlineLink(entry.get(1))) { - String url = entry.get(1); - if (!url.startsWith("http://") && !url.startsWith("https://")) { - url = "http://" + url; - } try { - field = new LinkedFile(entry.getFirst(), URLUtil.create(url), entry.get(2)); + field = new LinkedFile(entry.getFirst(), URLUtil.create(entry.get(1)), entry.get(2)); } catch (MalformedURLException e) { - // if the URL is still malformed, store it as a string - field = new LinkedFile(entry.getFirst(), url, entry.get(2)); + field = new LinkedFile(entry.getFirst(), entry.get(1), entry.get(2)); } } else { String pathStr = entry.get(1); @@ -174,7 +164,7 @@ static LinkedFile convert(List entry) { } else { try { // there is no Path.isValidPath(String) method - field = new LinkedFile(entry.getFirst(), Path.of(pathStr), entry.get(2)); + field = new LinkedFile(entry.getFirst(), Path.of(pathStr), entry.get(2)); } catch (InvalidPathException e) { // If the path is invalid, store it as a string LOGGER.debug("Invalid path object, continuing with string", e); @@ -182,11 +172,11 @@ static LinkedFile convert(List entry) { } } } - + if (entry.size() > 3) { field.setSourceURL(entry.get(3)); } - + // link is the only mandatory field if (field.getDescription().isEmpty() && field.getLink().isEmpty() && !field.getFileType().isEmpty()) { field = new LinkedFile("", Path.of(field.getFileType()), ""); diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java index be6dc722e03..64b3ef9fd59 100644 --- a/src/main/java/org/jabref/logic/util/URLUtil.java +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -15,6 +15,7 @@ * For GUI-oriented URL utilities see {@link org.jabref.gui.fieldeditors.URLUtil}. */ public class URLUtil { + private static final String PROTOCOL_SEPARATOR = "://"; private static final String URL_REGEX = "(?i)\\b((?:https?|ftp)://[^\\s]+)"; @@ -98,10 +99,10 @@ public static boolean isURL(String url) { * @throws MalformedURLException if the URL is malformed and cannot be converted to a {@link URL}. */ public static URL create(String url) throws MalformedURLException { - if (!url.contains("://")) { + if (!url.contains(PROTOCOL_SEPARATOR)) { url = "http://" + url; } - + URI uri = createUri(url); return uri.toURL(); } From 59006479355aa1092660aa7e278ffac162a67f2e Mon Sep 17 00:00:00 2001 From: whatisfahad Date: Mon, 24 Mar 2025 03:27:08 +0500 Subject: [PATCH 08/33] refactor: Remove duplicate HTTP and HTTPS prefix constants in FileFieldParser --- .../java/org/jabref/logic/importer/util/FileFieldParser.java | 5 +++-- src/test/java/org/jabref/logic/net/URLUtilTest.java | 5 ++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java index bf732a59c12..45ac752ed8f 100644 --- a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java +++ b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java @@ -8,19 +8,20 @@ import org.jabref.logic.util.URLUtil; import org.jabref.model.entry.LinkedFile; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class FileFieldParser { private static final Logger LOGGER = LoggerFactory.getLogger(FileFieldParser.class); + private static final String HTTP_PREFIX = "http://"; + private static final String HTTPS_PREFIX = "https://"; private final String value; private StringBuilder charactersOfCurrentElement; private boolean windowsPath; - private static final String HTTP_PREFIX = "http://"; - private static final String HTTPS_PREFIX = "https://"; public FileFieldParser(String value) { if (value == null) { diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java index bb9264a8022..81aa5fdc3c8 100644 --- a/src/test/java/org/jabref/logic/net/URLUtilTest.java +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -4,12 +4,10 @@ import java.net.URL; import org.jabref.logic.util.URLUtil; - -import org.junit.jupiter.api.Test; - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; class URLUtilTest { @@ -88,6 +86,7 @@ void createUriShouldHandlePipeCharacter() { URI uri = URLUtil.createUri(input); assertEquals("http://example.com/test%7Cfile", uri.toString()); } + @Test void createShouldHandleRelativeURLs() throws Exception { URL relativeUrl = URLUtil.create("www.example.com"); From fabfb1d2b37d5e6dab3cbecba74dd407c2dd0bd5 Mon Sep 17 00:00:00 2001 From: whatisfahad Date: Mon, 24 Mar 2025 04:09:01 +0500 Subject: [PATCH 09/33] refactor: Simplify LinkedFile handling in FileFieldParser and improve URL validation --- .../logic/importer/util/FileFieldParser.java | 23 ++++++++++++------- .../org/jabref/logic/net/URLUtilTest.java | 2 +- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java index 45ac752ed8f..0bad0ca3eeb 100644 --- a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java +++ b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java @@ -57,8 +57,18 @@ public List parse() { if ((value == null) || value.trim().isEmpty()) { return files; } - - // Data of each LinkedFile as split string + + if (LinkedFile.isOnlineLink(value.trim())) { + // needs to be modifiable + try { + return List.of(new LinkedFile(URLUtil.create(value), "")); + } catch (MalformedURLException e) { + LOGGER.error("invalid url", e); + return files; + } + } + + // data of each LinkedFile as split string List linkedFileData = new ArrayList<>(); resetDataStructuresForNextElement(); @@ -106,22 +116,19 @@ public List parse() { } } else if (!escaped && (c == ';') && !inXmlChar) { linkedFileData.add(charactersOfCurrentElement.toString()); - LinkedFile field = convert(linkedFileData); - files.add(field); - - // next iteration + files.add(convert(linkedFileData)); resetDataStructuresForNextElement(); } else { charactersOfCurrentElement.append(c); } escaped = false; } + if (charactersOfCurrentElement.length() > 0) { linkedFileData.add(charactersOfCurrentElement.toString()); } if (!linkedFileData.isEmpty()) { - LinkedFile field = convert(linkedFileData); - files.add(field); + files.add(convert(linkedFileData)); } return files; diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java index 81aa5fdc3c8..835533ecf09 100644 --- a/src/test/java/org/jabref/logic/net/URLUtilTest.java +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -4,10 +4,10 @@ import java.net.URL; import org.jabref.logic.util.URLUtil; +import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Test; class URLUtilTest { From eaf63e3b8336b4b490a685451604ba441682235e Mon Sep 17 00:00:00 2001 From: whatisfahad Date: Mon, 24 Mar 2025 04:16:04 +0500 Subject: [PATCH 10/33] refactor: Clean up whitespace and improve comments in FileFieldParser --- .../org/jabref/logic/importer/util/FileFieldParser.java | 9 ++++++--- src/test/java/org/jabref/logic/net/URLUtilTest.java | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java index 0bad0ca3eeb..7f7d956cfdf 100644 --- a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java +++ b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java @@ -53,7 +53,7 @@ public static List parse(String value) { public List parse() { List files = new ArrayList<>(); - + if ((value == null) || value.trim().isEmpty()) { return files; } @@ -70,7 +70,7 @@ public List parse() { // data of each LinkedFile as split string List linkedFileData = new ArrayList<>(); - + resetDataStructuresForNextElement(); boolean inXmlChar = false; boolean escaped = false; @@ -104,7 +104,7 @@ public List parse() { // We are at the second : (position 3 in the example) and "just" add it to the current element charactersOfCurrentElement.append(c); windowsPath = true; - // special case for Zotero absolute path on Windows that do not have a colon in front + // special case for zotero absolute path on windows that do not have a colon in front // e.g. A:\zotero\paper.pdf } else if (charactersOfCurrentElement.length() == 1 && value.charAt(i + 1) == '\\') { charactersOfCurrentElement.append(c); @@ -117,6 +117,8 @@ public List parse() { } else if (!escaped && (c == ';') && !inXmlChar) { linkedFileData.add(charactersOfCurrentElement.toString()); files.add(convert(linkedFileData)); + + // next iteration resetDataStructuresForNextElement(); } else { charactersOfCurrentElement.append(c); @@ -161,6 +163,7 @@ static LinkedFile convert(List entry) { try { field = new LinkedFile(entry.getFirst(), URLUtil.create(entry.get(1)), entry.get(2)); } catch (MalformedURLException e) { + // in case the URL is malformed, store it nevertheless field = new LinkedFile(entry.getFirst(), entry.get(1), entry.get(2)); } } else { diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java index 835533ecf09..df94456f3b8 100644 --- a/src/test/java/org/jabref/logic/net/URLUtilTest.java +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -4,7 +4,9 @@ import java.net.URL; import org.jabref.logic.util.URLUtil; + import org.junit.jupiter.api.Test; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; From de62e9ea1337d8b1f49a9e1d6df1492cfc4925a7 Mon Sep 17 00:00:00 2001 From: whatisfahad Date: Mon, 24 Mar 2025 04:21:14 +0500 Subject: [PATCH 11/33] refactor: Remove unnecessary whitespace in FileFieldParser --- .../java/org/jabref/logic/importer/util/FileFieldParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java index 7f7d956cfdf..f3642b63ce6 100644 --- a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java +++ b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java @@ -74,7 +74,7 @@ public List parse() { resetDataStructuresForNextElement(); boolean inXmlChar = false; boolean escaped = false; - + for (int i = 0; i < value.length(); i++) { char c = value.charAt(i); if (!escaped && (c == '\\')) { From 106f978e4a6c616c193a469f71a702568ea53f71 Mon Sep 17 00:00:00 2001 From: whatisfahad Date: Tue, 25 Mar 2025 04:11:58 +0500 Subject: [PATCH 12/33] refactor: Update URL validation logic in isURL method to use create method --- src/main/java/org/jabref/logic/util/URLUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java index 64b3ef9fd59..481884c8fe2 100644 --- a/src/main/java/org/jabref/logic/util/URLUtil.java +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -84,9 +84,9 @@ public static String cleanGoogleSearchURL(String url) { */ public static boolean isURL(String url) { try { - URI uri = new URI(url); - return uri.isAbsolute(); - } catch (URISyntaxException e) { + create(url); + return true; + } catch (MalformedURLException | IllegalArgumentException e) { return false; } } From 0ff2957dc8d50e6d04bab0dee4f78050c1055c37 Mon Sep 17 00:00:00 2001 From: whatisfahad Date: Tue, 25 Mar 2025 04:15:46 +0500 Subject: [PATCH 13/33] fixed typo --- .../java/org/jabref/logic/importer/util/FileFieldParser.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java index 7f7d956cfdf..00a9fd2e2b3 100644 --- a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java +++ b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java @@ -74,7 +74,7 @@ public List parse() { resetDataStructuresForNextElement(); boolean inXmlChar = false; boolean escaped = false; - + for (int i = 0; i < value.length(); i++) { char c = value.charAt(i); if (!escaped && (c == '\\')) { @@ -125,14 +125,12 @@ public List parse() { } escaped = false; } - if (charactersOfCurrentElement.length() > 0) { linkedFileData.add(charactersOfCurrentElement.toString()); } if (!linkedFileData.isEmpty()) { files.add(convert(linkedFileData)); } - return files; } From d92779c80487a3b49b6d0fb7f2216682c23164b5 Mon Sep 17 00:00:00 2001 From: whatisfahad Date: Tue, 25 Mar 2025 04:19:41 +0500 Subject: [PATCH 14/33] reuse of isur l --- src/main/java/org/jabref/logic/util/URLUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java index 64b3ef9fd59..481884c8fe2 100644 --- a/src/main/java/org/jabref/logic/util/URLUtil.java +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -84,9 +84,9 @@ public static String cleanGoogleSearchURL(String url) { */ public static boolean isURL(String url) { try { - URI uri = new URI(url); - return uri.isAbsolute(); - } catch (URISyntaxException e) { + create(url); + return true; + } catch (MalformedURLException | IllegalArgumentException e) { return false; } } From 2bed0cb7eaf5aa4394ff0508a533f19dae122565 Mon Sep 17 00:00:00 2001 From: whatisfahad Date: Tue, 25 Mar 2025 04:19:41 +0500 Subject: [PATCH 15/33] reuse of isurl --- src/main/java/org/jabref/logic/util/URLUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java index 64b3ef9fd59..481884c8fe2 100644 --- a/src/main/java/org/jabref/logic/util/URLUtil.java +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -84,9 +84,9 @@ public static String cleanGoogleSearchURL(String url) { */ public static boolean isURL(String url) { try { - URI uri = new URI(url); - return uri.isAbsolute(); - } catch (URISyntaxException e) { + create(url); + return true; + } catch (MalformedURLException | IllegalArgumentException e) { return false; } } From ee6fb59303096a44122075c423ed09f603188074 Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Tue, 25 Mar 2025 04:44:03 +0500 Subject: [PATCH 16/33] refactor: update isURL method to use createUri for better URL handling --- src/main/java/org/jabref/logic/util/URLUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java index 481884c8fe2..fa9e96feb88 100644 --- a/src/main/java/org/jabref/logic/util/URLUtil.java +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -84,9 +84,9 @@ public static String cleanGoogleSearchURL(String url) { */ public static boolean isURL(String url) { try { - create(url); + createUri(url); return true; - } catch (MalformedURLException | IllegalArgumentException e) { + } catch (IllegalArgumentException e) { return false; } } From b67ea745d90df18b465dd05834ae86fdb3e93c35 Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Tue, 25 Mar 2025 05:04:27 +0500 Subject: [PATCH 17/33] fix: enhance URL validation by catching MalformedURLException --- src/main/java/org/jabref/logic/util/URLUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java index fa9e96feb88..3cd92169f50 100644 --- a/src/main/java/org/jabref/logic/util/URLUtil.java +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -86,7 +86,7 @@ public static boolean isURL(String url) { try { createUri(url); return true; - } catch (IllegalArgumentException e) { + } catch (MalformedURLException | IllegalArgumentException e){ return false; } } From 6cb25688a44f32b63e776fb312e64c95f706fb5b Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Tue, 25 Mar 2025 05:18:54 +0500 Subject: [PATCH 18/33] fix: improve URL validation by enforcing scheme format in isURL method --- src/main/java/org/jabref/logic/util/URLUtil.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java index 3cd92169f50..e007d3c3d87 100644 --- a/src/main/java/org/jabref/logic/util/URLUtil.java +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -83,10 +83,13 @@ public static String cleanGoogleSearchURL(String url) { * @return true if url contains a valid URL */ public static boolean isURL(String url) { + if (!url.matches("^[a-zA-Z]+://.*")) { + return false; + } try { createUri(url); return true; - } catch (MalformedURLException | IllegalArgumentException e){ + } catch (IllegalArgumentException e) { return false; } } From 6cfa087d51784d292280e3e0db503b1691d99ab2 Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Wed, 26 Mar 2025 04:33:21 +0500 Subject: [PATCH 19/33] refactor: update FileFieldParser to use URLUtil for URL validation and enhance create method to default to HTTPS --- .../logic/importer/util/FileFieldParser.java | 4 +--- .../java/org/jabref/logic/util/URLUtil.java | 8 ++++++-- .../org/jabref/logic/net/URLUtilTest.java | 19 ++++++++++--------- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java index 00a9fd2e2b3..60ffde7ebbc 100644 --- a/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java +++ b/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java @@ -14,8 +14,6 @@ public class FileFieldParser { private static final Logger LOGGER = LoggerFactory.getLogger(FileFieldParser.class); - private static final String HTTP_PREFIX = "http://"; - private static final String HTTPS_PREFIX = "https://"; private final String value; @@ -58,7 +56,7 @@ public List parse() { return files; } - if (LinkedFile.isOnlineLink(value.trim())) { + if (URLUtil.isURL(value.trim())) { // needs to be modifiable try { return List.of(new LinkedFile(URLUtil.create(value), "")); diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java index e007d3c3d87..3050539e8af 100644 --- a/src/main/java/org/jabref/logic/util/URLUtil.java +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -96,6 +96,10 @@ public static boolean isURL(String url) { /** * Creates a {@link URL} object from the given string URL. + *

+ * If the URL does not contain a protocol (e.g., "example.com"), + * "https://" is added by default to ensure a valid URL format. + * This helps avoid errors when handling URLs without protocols. * * @param url the URL string to be converted into a {@link URL}. * @return the {@link URL} object created from the string URL. @@ -103,9 +107,9 @@ public static boolean isURL(String url) { */ public static URL create(String url) throws MalformedURLException { if (!url.contains(PROTOCOL_SEPARATOR)) { - url = "http://" + url; + url = "https://" + url; } - + URI uri = createUri(url); return uri.toURL(); } diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java index df94456f3b8..bb803f40ad8 100644 --- a/src/test/java/org/jabref/logic/net/URLUtilTest.java +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -4,6 +4,8 @@ import java.net.URL; import org.jabref.logic.util.URLUtil; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.api.Test; @@ -107,12 +109,11 @@ void createShouldHandleAbsoluteURLs() throws Exception { assertEquals("https://www.example.com", absoluteHttpsUrl.toString()); } - @Test - void createShouldHandleOtherProtocols() throws Exception { - URL ftpUrl = URLUtil.create("ftp://example.com"); - assertEquals("ftp://example.com", ftpUrl.toString()); - - URL fileUrl = URLUtil.create("file:///path/to/file"); - assertEquals("file:/path/to/file", fileUrl.toString()); -} -} + @ParameterizedTest + @CsvSource({ + "ftp://example.com, ftp://example.com", + "file:///path/to/file, file:/path/to/file" + }) + void createShouldHandleOtherProtocols(String inputUrl, String expectedUrl) throws Exception { + URL actualUrl = URLUtil.create(inputUrl); + assertEquals(expectedUrl, actualUrl.toString()); From 82627f15b49f9aa9b392931dc82786b6f14ed9f4 Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Thu, 27 Mar 2025 03:12:16 +0500 Subject: [PATCH 20/33] test: add missing closing brace in URLUtilTest class --- src/test/java/org/jabref/logic/net/URLUtilTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java index bb803f40ad8..b82bca81d8a 100644 --- a/src/test/java/org/jabref/logic/net/URLUtilTest.java +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -117,3 +117,5 @@ void createShouldHandleAbsoluteURLs() throws Exception { void createShouldHandleOtherProtocols(String inputUrl, String expectedUrl) throws Exception { URL actualUrl = URLUtil.create(inputUrl); assertEquals(expectedUrl, actualUrl.toString()); + } +} From 2ff7f9b2fc4859041f8a87fe8987e540a1b6b6a4 Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Thu, 27 Mar 2025 03:58:09 +0500 Subject: [PATCH 21/33] test: update URLUtilTest to expect HTTPS for relative URLs --- src/test/java/org/jabref/logic/net/URLUtilTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java index b82bca81d8a..01946809e97 100644 --- a/src/test/java/org/jabref/logic/net/URLUtilTest.java +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -4,10 +4,10 @@ import java.net.URL; import org.jabref.logic.util.URLUtil; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -94,7 +94,7 @@ void createUriShouldHandlePipeCharacter() { @Test void createShouldHandleRelativeURLs() throws Exception { URL relativeUrl = URLUtil.create("www.example.com"); - assertEquals("http://www.example.com", relativeUrl.toString()); + assertEquals("https://www.example.com", relativeUrl.toString()); URL noWwwUrl = URLUtil.create("example.com"); assertEquals("http://example.com", noWwwUrl.toString()); From 85fe62b92d4d378365f22f50079845d5b2914015 Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Thu, 27 Mar 2025 04:14:52 +0500 Subject: [PATCH 22/33] fix: update URLUtil to handle FTP URLs and default to HTTPS for missing protocols --- src/main/java/org/jabref/logic/util/URLUtil.java | 5 ++++- src/test/java/org/jabref/logic/net/URLUtilTest.java | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java index 3050539e8af..aa15d7f525b 100644 --- a/src/main/java/org/jabref/logic/util/URLUtil.java +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -106,7 +106,10 @@ public static boolean isURL(String url) { * @throws MalformedURLException if the URL is malformed and cannot be converted to a {@link URL}. */ public static URL create(String url) throws MalformedURLException { - if (!url.contains(PROTOCOL_SEPARATOR)) { + if (url.startsWith("ftp://")) { + URI uri = createUri(url); + return uri.toURL(); + }else if (!url.contains(PROTOCOL_SEPARATOR)) { url = "https://" + url; } diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java index 01946809e97..ab24044091b 100644 --- a/src/test/java/org/jabref/logic/net/URLUtilTest.java +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -97,7 +97,7 @@ void createShouldHandleRelativeURLs() throws Exception { assertEquals("https://www.example.com", relativeUrl.toString()); URL noWwwUrl = URLUtil.create("example.com"); - assertEquals("http://example.com", noWwwUrl.toString()); + assertEquals("https://example.com", noWwwUrl.toString()); } @Test From 0cc8737815cb3f82da313076db163e92ff983761 Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Thu, 27 Mar 2025 04:24:42 +0500 Subject: [PATCH 23/33] fix: refactor URLUtil to improve protocol handling logic --- src/main/java/org/jabref/logic/util/URLUtil.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java index aa15d7f525b..afd96aac0a0 100644 --- a/src/main/java/org/jabref/logic/util/URLUtil.java +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -109,10 +109,11 @@ public static URL create(String url) throws MalformedURLException { if (url.startsWith("ftp://")) { URI uri = createUri(url); return uri.toURL(); - }else if (!url.contains(PROTOCOL_SEPARATOR)) { + } + if (!url.contains(PROTOCOL_SEPARATOR)) { url = "https://" + url; } - + URI uri = createUri(url); return uri.toURL(); } From a2fa48e770b1772266c3188102e484f0dff50c6b Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Thu, 27 Mar 2025 04:26:31 +0500 Subject: [PATCH 24/33] fix: remove unnecessary whitespace in URLUtil class --- src/main/java/org/jabref/logic/util/URLUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java index afd96aac0a0..6896cec6537 100644 --- a/src/main/java/org/jabref/logic/util/URLUtil.java +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -113,7 +113,7 @@ public static URL create(String url) throws MalformedURLException { if (!url.contains(PROTOCOL_SEPARATOR)) { url = "https://" + url; } - + URI uri = createUri(url); return uri.toURL(); } From 95e367f47c9e418af7135377fc0fc763bf78ef97 Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Thu, 27 Mar 2025 04:35:53 +0500 Subject: [PATCH 25/33] fix: remove FTP handling from URLUtil.create method --- src/main/java/org/jabref/logic/util/URLUtil.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java index 6896cec6537..734ae7f9c3d 100644 --- a/src/main/java/org/jabref/logic/util/URLUtil.java +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -106,10 +106,6 @@ public static boolean isURL(String url) { * @throws MalformedURLException if the URL is malformed and cannot be converted to a {@link URL}. */ public static URL create(String url) throws MalformedURLException { - if (url.startsWith("ftp://")) { - URI uri = createUri(url); - return uri.toURL(); - } if (!url.contains(PROTOCOL_SEPARATOR)) { url = "https://" + url; } @@ -117,7 +113,7 @@ public static URL create(String url) throws MalformedURLException { URI uri = createUri(url); return uri.toURL(); } - + /** * Creates a {@link URI} object from the given string URL. * This method attempts to convert the given URL string into a {@link URI} object. From 8dfbe88f231ffe39706232a61062cd024f61d3eb Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Sun, 30 Mar 2025 17:55:22 +0500 Subject: [PATCH 26/33] fix: enhance URL validation and streamline URL creation tests --- .../java/org/jabref/logic/util/URLUtil.java | 8 ++++-- .../org/jabref/logic/net/URLUtilTest.java | 27 +++++++++---------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java index 734ae7f9c3d..47ae4c0be76 100644 --- a/src/main/java/org/jabref/logic/util/URLUtil.java +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -16,6 +16,7 @@ */ public class URLUtil { private static final String PROTOCOL_SEPARATOR = "://"; + private static final Pattern SCHEME_PREFIX = Pattern.compile("^[a-zA-Z]+://.*"); private static final String URL_REGEX = "(?i)\\b((?:https?|ftp)://[^\\s]+)"; @@ -77,13 +78,16 @@ public static String cleanGoogleSearchURL(String url) { /** * Checks whether the given String is a URL. *

- * Currently only checks for a protocol String. + * A valid URL must have a scheme (e.g., "http", "https", + * "ftp") and an authority (e.g., "example.com"). + * See + * URL Syntax for details. * * @param url the String to check for a URL * @return true if url contains a valid URL */ public static boolean isURL(String url) { - if (!url.matches("^[a-zA-Z]+://.*")) { + if (!SCHEME_PREFIX.matcher(url).matches()) { return false; } try { diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java index ab24044091b..4de96f1e6c6 100644 --- a/src/test/java/org/jabref/logic/net/URLUtilTest.java +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -91,22 +91,19 @@ void createUriShouldHandlePipeCharacter() { assertEquals("http://example.com/test%7Cfile", uri.toString()); } - @Test - void createShouldHandleRelativeURLs() throws Exception { - URL relativeUrl = URLUtil.create("www.example.com"); - assertEquals("https://www.example.com", relativeUrl.toString()); - - URL noWwwUrl = URLUtil.create("example.com"); - assertEquals("https://example.com", noWwwUrl.toString()); - } - - @Test - void createShouldHandleAbsoluteURLs() throws Exception { - URL absoluteHttpUrl = URLUtil.create("http://www.example.com"); - assertEquals("http://www.example.com", absoluteHttpUrl.toString()); + @ParameterizedTest + @CsvSource({ + // Relative URLs (should default to HTTPS) + "www.example.com, https://www.example.com", + "example.com, https://example.com", - URL absoluteHttpsUrl = URLUtil.create("https://www.example.com"); - assertEquals("https://www.example.com", absoluteHttpsUrl.toString()); + // Absolute URLs (should remain unchanged) + "http://www.example.com, http://www.example.com", + "https://www.example.com, https://www.example.com" + }) + void createShouldHandleURLs(String input, String expected) throws Exception { + URL url = URLUtil.create(input); + assertEquals(expected, url.toString()); } @ParameterizedTest From 8b50c09d62ec47dc2f97077a19d7ba5766a84c71 Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Sun, 30 Mar 2025 18:19:54 +0500 Subject: [PATCH 27/33] fix: improve documentation for URL creation method regarding protocol handling --- src/main/java/org/jabref/logic/util/URLUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/jabref/logic/util/URLUtil.java b/src/main/java/org/jabref/logic/util/URLUtil.java index 47ae4c0be76..4712c842790 100644 --- a/src/main/java/org/jabref/logic/util/URLUtil.java +++ b/src/main/java/org/jabref/logic/util/URLUtil.java @@ -101,9 +101,9 @@ public static boolean isURL(String url) { /** * Creates a {@link URL} object from the given string URL. *

- * If the URL does not contain a protocol (e.g., "example.com"), - * "https://" is added by default to ensure a valid URL format. - * This helps avoid errors when handling URLs without protocols. + * If the given URL string does not contain a protocol (e.g., "example.com"), + * "https://" is automatically added to ensure a valid URL format. + * This prevents errors when handling URLs without explicit protocols. * * @param url the URL string to be converted into a {@link URL}. * @return the {@link URL} object created from the string URL. From 83746339e43965f4713a691225abd543c6c466d5 Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Thu, 1 May 2025 16:28:13 +0500 Subject: [PATCH 28/33] fix: correct parameter order in URL handling tests for consistency --- src/test/java/org/jabref/logic/net/URLUtilTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java index 4de96f1e6c6..9be4264f4c0 100644 --- a/src/test/java/org/jabref/logic/net/URLUtilTest.java +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -101,9 +101,9 @@ void createUriShouldHandlePipeCharacter() { "http://www.example.com, http://www.example.com", "https://www.example.com, https://www.example.com" }) - void createShouldHandleURLs(String input, String expected) throws Exception { - URL url = URLUtil.create(input); - assertEquals(expected, url.toString()); + void createShouldHandleURLs(String expected, String input) throws Exception { + URL url = URLUtil.create(input); + assertEquals(expected, url.toString()); } @ParameterizedTest @@ -111,7 +111,7 @@ void createShouldHandleURLs(String input, String expected) throws Exception { "ftp://example.com, ftp://example.com", "file:///path/to/file, file:/path/to/file" }) - void createShouldHandleOtherProtocols(String inputUrl, String expectedUrl) throws Exception { + void createShouldHandleOtherProtocols(String expectedUrl, String inputUrl) throws Exception { URL actualUrl = URLUtil.create(inputUrl); assertEquals(expectedUrl, actualUrl.toString()); } From 65570d6e3f0ddbb8f0660d57b487bbddebcd0725 Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Thu, 1 May 2025 16:45:58 +0500 Subject: [PATCH 29/33] test: add comprehensive tests for URLUtil methods --- .../org/jabref/logic/net/URLUtilTest.java | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 src/test/java/org/jabref/logic/net/URLUtilTest.java diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java new file mode 100644 index 00000000000..340b726ba73 --- /dev/null +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -0,0 +1,118 @@ +package org.jabref.logic.net; + +import java.net.URI; +import java.net.URL; + +import org.jabref.logic.util.URLUtil; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class URLUtilTest { + + @Test + void cleanGoogleSearchURL() throws Exception { + // empty text + assertEquals("", URLUtil.cleanGoogleSearchURL("")); + assertEquals(" ", URLUtil.cleanGoogleSearchURL(" ")); + // no URL + assertEquals("this is no url!", URLUtil.cleanGoogleSearchURL("this is no url!")); + // no Google search URL + assertEquals("http://dl.acm.org/citation.cfm?id=321811", URLUtil.cleanGoogleSearchURL("http://dl.acm.org/citation.cfm?id=321811")); + // malformed Google URL + assertEquals("https://www.google.de/url♥", URLUtil.cleanGoogleSearchURL("https://www.google.de/url♥")); + // no queries + assertEquals("https://www.google.de/url", URLUtil.cleanGoogleSearchURL("https://www.google.de/url")); + assertEquals("https://www.google.de/url?", URLUtil.cleanGoogleSearchURL("https://www.google.de/url?")); + // no multiple queries + assertEquals("https://www.google.de/url?key=value", URLUtil.cleanGoogleSearchURL("https://www.google.de/url?key=value")); + // no key values + assertEquals("https://www.google.de/url?key", URLUtil.cleanGoogleSearchURL("https://www.google.de/url?key")); + assertEquals("https://www.google.de/url?url", URLUtil.cleanGoogleSearchURL("https://www.google.de/url?url")); + assertEquals("https://www.google.de/url?key=", URLUtil.cleanGoogleSearchURL("https://www.google.de/url?key=")); + // no url param + assertEquals("https://www.google.de/url?key=value&key2=value2", URLUtil.cleanGoogleSearchURL("https://www.google.de/url?key=value&key2=value2")); + // no url param value + assertEquals("https://www.google.de/url?url=", URLUtil.cleanGoogleSearchURL("https://www.google.de/url?url=")); + // url param value no URL + assertEquals("https://www.google.de/url?url=this+is+no+url", URLUtil.cleanGoogleSearchURL("https://www.google.de/url?url=this+is+no+url")); + // Http + assertEquals( + "http://moz.com/ugc/the-ultimate-guide-to-the-google-search-parameters", + URLUtil.cleanGoogleSearchURL("http://www.google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0CCEQFjAAahUKEwjJurHd2sfHAhWBsxQKHSrEAaM&url=http%3A%2F%2Fmoz.com%2Fugc%2Fthe-ultimate-guide-to-the-google-search-parameters&ei=0THeVYmOJIHnUqqIh5gK&usg=AFQjCNHnid_r_d2LP8_MqvI7lQnTC3lB_g&sig2=ICzxDroG2ENTJSUGmdhI2w")); + // Https + assertEquals( + "https://moz.com/ugc/the-ultimate-guide-to-the-google-search-parameters", + URLUtil.cleanGoogleSearchURL("https://www.google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0CCEQFjAAahUKEwjJurHd2sfHAhWBsxQKHSrEAaM&url=https%3A%2F%2Fmoz.com%2Fugc%2Fthe-ultimate-guide-to-the-google-search-parameters&ei=0THeVYmOJIHnUqqIh5gK&usg=AFQjCNHnid_r_d2LP8_MqvI7lQnTC3lB_g&sig2=ICzxDroG2ENTJSUGmdhI2w")); + // root domain + assertEquals( + "https://moz.com/ugc/the-ultimate-guide-to-the-google-search-parameters", + URLUtil.cleanGoogleSearchURL("https://google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0CCEQFjAAahUKEwjJurHd2sfHAhWBsxQKHSrEAaM&url=https%3A%2F%2Fmoz.com%2Fugc%2Fthe-ultimate-guide-to-the-google-search-parameters&ei=0THeVYmOJIHnUqqIh5gK&usg=AFQjCNHnid_r_d2LP8_MqvI7lQnTC3lB_g&sig2=ICzxDroG2ENTJSUGmdhI2w")); + // foreign domain + assertEquals( + "https://moz.com/ugc/the-ultimate-guide-to-the-google-search-parameters", + URLUtil.cleanGoogleSearchURL("https://www.google.fr/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0CCEQFjAAahUKEwjJurHd2sfHAhWBsxQKHSrEAaM&url=https%3A%2F%2Fmoz.com%2Fugc%2Fthe-ultimate-guide-to-the-google-search-parameters&ei=0THeVYmOJIHnUqqIh5gK&usg=AFQjCNHnid_r_d2LP8_MqvI7lQnTC3lB_g&sig2=ICzxDroG2ENTJSUGmdhI2w")); + // foreign domain co.uk + assertEquals( + "https://moz.com/ugc/the-ultimate-guide-to-the-google-search-parameters", + URLUtil.cleanGoogleSearchURL("https://www.google.co.uk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0CCEQFjAAahUKEwjJurHd2sfHAhWBsxQKHSrEAaM&url=https%3A%2F%2Fmoz.com%2Fugc%2Fthe-ultimate-guide-to-the-google-search-parameters&ei=0THeVYmOJIHnUqqIh5gK&usg=AFQjCNHnid_r_d2LP8_MqvI7lQnTC3lB_g&sig2=ICzxDroG2ENTJSUGmdhI2w")); + // accept ftp results + assertEquals( + "ftp://moz.com/ugc/the-ultimate-guide-to-the-google-search-parameters", + URLUtil.cleanGoogleSearchURL("https://www.google.fr/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0CCEQFjAAahUKEwjJurHd2sfHAhWBsxQKHSrEAaM&url=ftp%3A%2F%2Fmoz.com%2Fugc%2Fthe-ultimate-guide-to-the-google-search-parameters&ei=0THeVYmOJIHnUqqIh5gK&usg=AFQjCNHnid_r_d2LP8_MqvI7lQnTC3lB_g&sig2=ICzxDroG2ENTJSUGmdhI2w")); + } + + @Test + void isURLshouldAcceptValidURL() { + assertTrue(URLUtil.isURL("http://www.google.com")); + assertTrue(URLUtil.isURL("https://www.google.com")); + } + + @Test + void isURLshouldRejectInvalidURL() { + assertFalse(URLUtil.isURL("www.google.com")); + assertFalse(URLUtil.isURL("google.com")); + } + + @Test + void isURLshouldRejectEmbeddedURL() { + assertFalse(URLUtil.isURL("dblp computer science bibliography, http://dblp.org")); + } + + @Test + void createUriShouldHandlePipeCharacter() { + String input = "http://example.com/test|file"; + URI uri = URLUtil.createUri(input); + assertEquals("http://example.com/test%7Cfile", uri.toString()); + } + + @ParameterizedTest + @CsvSource({ + // Relative URLs (should default to HTTPS) + "www.example.com, https://www.example.com", + "example.com, https://example.com", + + // Absolute URLs (should remain unchanged) + "http://www.example.com, http://www.example.com", + "https://www.example.com, https://www.example.com" + }) + void createShouldHandleURLs(String expected, String input) throws Exception { + URL url = URLUtil.create(input); + assertEquals(expected, url.toString()); + } + + @ParameterizedTest + @CsvSource({ + "ftp://example.com, ftp://example.com", + "file:///path/to/file, file:/path/to/file" + }) + void createShouldHandleOtherProtocols(String expectedUrl, String inputUrl) throws Exception { + URL actualUrl = URLUtil.create(inputUrl); + assertEquals(expectedUrl, actualUrl.toString()); + } +} From 95f2f5e35b2801edef1e119121f8095668eaf9f0 Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Thu, 1 May 2025 16:50:12 +0500 Subject: [PATCH 30/33] fix: remove trailing whitespace in URLUtilTest.java --- src/test/java/org/jabref/logic/net/URLUtilTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java index 340b726ba73..9be4264f4c0 100644 --- a/src/test/java/org/jabref/logic/net/URLUtilTest.java +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -115,4 +115,4 @@ void createShouldHandleOtherProtocols(String expectedUrl, String inputUrl) throw URL actualUrl = URLUtil.create(inputUrl); assertEquals(expectedUrl, actualUrl.toString()); } -} +} From 20ebfaf66751fee2755f9bf568c284561d90c5b7 Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Thu, 1 May 2025 17:03:18 +0500 Subject: [PATCH 31/33] fix: improve readability of URL validation test by storing result in a variable --- src/test/java/org/jabref/logic/net/URLUtilTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/jabref/logic/net/URLUtilTest.java b/src/test/java/org/jabref/logic/net/URLUtilTest.java index 9be4264f4c0..c7617e34a17 100644 --- a/src/test/java/org/jabref/logic/net/URLUtilTest.java +++ b/src/test/java/org/jabref/logic/net/URLUtilTest.java @@ -81,7 +81,8 @@ void isURLshouldRejectInvalidURL() { @Test void isURLshouldRejectEmbeddedURL() { - assertFalse(URLUtil.isURL("dblp computer science bibliography, http://dblp.org")); + boolean result = URLUtil.isURL("dblp computer science bibliography, http://dblp.org"); + assertEquals(false, result); } @Test From dfe54065ff8df02dd514f2e41c5565294a128430 Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Sun, 4 May 2025 16:56:51 +0500 Subject: [PATCH 32/33] fix: replace URLUtil.isURL with LinkedFile.isOnlineLink for URL validation --- .../java/org/jabref/logic/importer/util/FileFieldParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jablib/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java b/jablib/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java index 60ffde7ebbc..cb22ad91943 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java +++ b/jablib/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java @@ -56,7 +56,7 @@ public List parse() { return files; } - if (URLUtil.isURL(value.trim())) { + if (LinkedFile.isOnlineLink(value.trim())) { // needs to be modifiable try { return List.of(new LinkedFile(URLUtil.create(value), "")); From 7465a151ca22dc22306da88cd9657180766864f7 Mon Sep 17 00:00:00 2001 From: sfahaddev Date: Sun, 4 May 2025 18:17:40 +0500 Subject: [PATCH 33/33] fix: improve logging message for handling invalid paths in FileFieldParser --- .../java/org/jabref/logic/importer/util/FileFieldParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jablib/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java b/jablib/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java index cb22ad91943..0975c25ae1d 100644 --- a/jablib/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java +++ b/jablib/src/main/java/org/jabref/logic/importer/util/FileFieldParser.java @@ -173,7 +173,7 @@ static LinkedFile convert(List entry) { // there is no Path.isValidPath(String) method field = new LinkedFile(entry.getFirst(), Path.of(pathStr), entry.get(2)); } catch (InvalidPathException e) { - // If the path is invalid, store it as a string + // Use string if path is invalid LOGGER.debug("Invalid path object, continuing with string", e); field = new LinkedFile(entry.getFirst(), pathStr, entry.get(2)); }