From 4a3b2a8a07a76bc164643f3624eb489298214570 Mon Sep 17 00:00:00 2001 From: Silvio Hermann Date: Wed, 13 Nov 2024 11:59:25 +0100 Subject: [PATCH 1/4] MCR-3299 Added index check to lambda --- .../classification/MCRClassificationMappingEventHandler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/mycore-mods/src/main/java/org/mycore/mods/classification/MCRClassificationMappingEventHandler.java b/mycore-mods/src/main/java/org/mycore/mods/classification/MCRClassificationMappingEventHandler.java index 211cd2c466..d38e02a670 100644 --- a/mycore-mods/src/main/java/org/mycore/mods/classification/MCRClassificationMappingEventHandler.java +++ b/mycore-mods/src/main/java/org/mycore/mods/classification/MCRClassificationMappingEventHandler.java @@ -97,6 +97,7 @@ private static List> getXMappings(MCRCat String label = labelOptional.get().getText(); return Stream.of(label.split("\\s")) .map(categIdString -> categIdString.split(":")) + .filter(categIdArr -> categIdArr != null && categIdArr.length > 1) .map(categIdArr -> new MCRCategoryID(categIdArr[0], categIdArr[1])) .filter(dao::exist) .map(mappingTarget -> new AbstractMap.SimpleEntry<>(category.getId(), mappingTarget)) From 2641cb4e196fe528c64fe387d3984e6fe26d552f Mon Sep 17 00:00:00 2001 From: Antoniafriedrich Date: Wed, 13 Nov 2024 09:58:08 +0100 Subject: [PATCH 2/4] MCR-3298 escape special characters --- .../java/org/mycore/solr/search/MCRQLSearchServlet.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mycore-solr/src/main/java/org/mycore/solr/search/MCRQLSearchServlet.java b/mycore-solr/src/main/java/org/mycore/solr/search/MCRQLSearchServlet.java index 861adc7a1f..fea92a4246 100644 --- a/mycore-solr/src/main/java/org/mycore/solr/search/MCRQLSearchServlet.java +++ b/mycore-solr/src/main/java/org/mycore/solr/search/MCRQLSearchServlet.java @@ -28,6 +28,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.solr.client.solrj.SolrQuery; +import org.apache.solr.client.solrj.util.ClientUtils; import org.jdom2.Document; import org.jdom2.output.XMLOutputter; import org.mycore.common.config.MCRConfiguration2; @@ -63,7 +64,13 @@ public void doGetPost(MCRServletJob job) throws IOException, ServletException, T HttpServletRequest request = job.getRequest(); HttpServletResponse response = job.getResponse(); String searchString = getReqParameter(request, "search", null); + if (searchString != null) { + searchString = ClientUtils.escapeQueryChars(searchString); + } String queryString = getReqParameter(request, "query", null); + if (queryString != null) { + queryString = ClientUtils.escapeQueryChars(queryString); + } Document input = (Document) request.getAttribute("MCRXEditorSubmission"); MCRQuery query; From 655903cf3eba8f08067acf85eae5271afd0ea206 Mon Sep 17 00:00:00 2001 From: Thomas Scheffler Date: Wed, 20 Nov 2024 10:34:44 +0100 Subject: [PATCH 3/4] MCR-3299 better fix for ArrayOutOfBoundException (#2325) skip unnecessary null check and re-use code from MCRCategoryID throw exception on invalid MCRCategoryID --- .../MCRClassificationMappingEventHandler.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/mycore-mods/src/main/java/org/mycore/mods/classification/MCRClassificationMappingEventHandler.java b/mycore-mods/src/main/java/org/mycore/mods/classification/MCRClassificationMappingEventHandler.java index d38e02a670..f0292edb9c 100644 --- a/mycore-mods/src/main/java/org/mycore/mods/classification/MCRClassificationMappingEventHandler.java +++ b/mycore-mods/src/main/java/org/mycore/mods/classification/MCRClassificationMappingEventHandler.java @@ -21,9 +21,9 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -96,9 +96,8 @@ private static List> getXMappings(MCRCat final MCRCategoryDAO dao = MCRCategoryDAOFactory.getInstance(); String label = labelOptional.get().getText(); return Stream.of(label.split("\\s")) - .map(categIdString -> categIdString.split(":")) - .filter(categIdArr -> categIdArr != null && categIdArr.length > 1) - .map(categIdArr -> new MCRCategoryID(categIdArr[0], categIdArr[1])) + .map(MCRCategoryID::fromString) + .filter(id -> !id.isRootID()) .filter(dao::exist) .map(mappingTarget -> new AbstractMap.SimpleEntry<>(category.getId(), mappingTarget)) .collect(Collectors.toList()); From 44d60af682f32028f8a97220a5114d7dd121a466 Mon Sep 17 00:00:00 2001 From: Thomas Scheffler Date: Wed, 20 Nov 2024 10:37:55 +0100 Subject: [PATCH 4/4] MCR-3302 fix edge cases for MCRCategoryID.fromString() (#2327) --- mycore-base/pom.xml | 5 +++ .../classifications2/MCRCategoryID.java | 30 +++++++-------- .../classifications2/MCRCategoryIDTest.java | 38 +++++++++++++------ 3 files changed, 47 insertions(+), 26 deletions(-) diff --git a/mycore-base/pom.xml b/mycore-base/pom.xml index be2e390c9e..52735d716e 100644 --- a/mycore-base/pom.xml +++ b/mycore-base/pom.xml @@ -456,6 +456,11 @@ junit-jupiter-api test + + org.junit.jupiter + junit-jupiter-params + test + org.junit.vintage junit-vintage-engine diff --git a/mycore-base/src/main/java/org/mycore/datamodel/classifications2/MCRCategoryID.java b/mycore-base/src/main/java/org/mycore/datamodel/classifications2/MCRCategoryID.java index 0bb4e0cbd2..7ddd6cad87 100644 --- a/mycore-base/src/main/java/org/mycore/datamodel/classifications2/MCRCategoryID.java +++ b/mycore-base/src/main/java/org/mycore/datamodel/classifications2/MCRCategoryID.java @@ -21,7 +21,6 @@ import java.io.Serializable; import java.text.MessageFormat; import java.util.Locale; -import java.util.StringTokenizer; import java.util.regex.Pattern; import org.mycore.common.MCRException; @@ -40,7 +39,7 @@ /** * The composite identifier of a MCRCategory. If rootID == ID the * associated MCRCategory instance is a root category (a classification). - * + * * @author Thomas Scheffler (yagee) * @since 2.0 */ @@ -88,19 +87,20 @@ public static MCRCategoryID rootID(String rootID) { /** * @param categoryId must be in format classificationId:categoryId * @return the {@link MCRCategoryID} if any + * @throws IllegalArgumentException if the given categoryId is invalid */ @JsonCreator(mode = JsonCreator.Mode.DELEGATING) public static MCRCategoryID fromString(String categoryId) { - StringTokenizer tok = new StringTokenizer(categoryId, ":"); - String rootId = tok.nextToken(); - if (!tok.hasMoreTokens()) { - return rootID(rootId); - } - String categId = tok.nextToken(); - if (tok.hasMoreTokens()) { - throw new IllegalArgumentException("CategoryId is ambiguous: " + categoryId); + String[] parts = categoryId.split(":"); + try { + return switch (parts.length) { + case 1 -> rootID(parts[0]); + case 2 -> new MCRCategoryID(parts[0], parts[1]); + default -> throw new IllegalArgumentException("CategoryId is ambiguous: " + categoryId); + }; + } catch (MCRException e) { + throw new IllegalArgumentException("Invalid category ID: " + categoryId, e); } - return new MCRCategoryID(rootId, categId); } @Transient @@ -110,7 +110,7 @@ public boolean isRootID() { /* * (non-Javadoc) - * + * * @see java.lang.Object#hashCode() */ @Override @@ -124,7 +124,7 @@ public int hashCode() { /* * (non-Javadoc) - * + * * @see java.lang.Object#equals(java.lang.Object) */ @Override @@ -220,7 +220,7 @@ private void setRootID(String rootID) { } if (rootID.length() > ROOT_ID_LENGTH) { throw new MCRException(String.format(Locale.ENGLISH, - "classification ID ''%s'' is more than %d chracters long: %d", rootID, ROOT_ID_LENGTH, + "classification ID ''%s'' is more than %d characters long: %d", rootID, ROOT_ID_LENGTH, rootID.length())); } this.rootID = rootID.intern(); @@ -228,7 +228,7 @@ private void setRootID(String rootID) { /* * (non-Javadoc) - * + * * @see java.lang.Object#toString() */ @Override diff --git a/mycore-base/src/test/java/org/mycore/datamodel/classifications2/MCRCategoryIDTest.java b/mycore-base/src/test/java/org/mycore/datamodel/classifications2/MCRCategoryIDTest.java index e9491a526d..0b52540002 100644 --- a/mycore-base/src/test/java/org/mycore/datamodel/classifications2/MCRCategoryIDTest.java +++ b/mycore-base/src/test/java/org/mycore/datamodel/classifications2/MCRCategoryIDTest.java @@ -19,16 +19,19 @@ package org.mycore.datamodel.classifications2; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; -import org.junit.Test; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.mycore.common.MCRException; -import org.mycore.common.MCRTestCase; /** * @author Thomas Scheffler (yagee) * */ -public class MCRCategoryIDTest extends MCRTestCase { +public class MCRCategoryIDTest { private static final String invalidID = "identifier:.sub"; private static final String validRootID = "rootID"; @@ -56,23 +59,36 @@ public void testRootID() { assertEquals("RootIds do not match", validRootID, MCRCategoryID.rootID(validRootID).getRootID()); } - @Test(expected = MCRException.class) + @Test public void testInvalidRootID() { - new MCRCategoryID(invalidID, validCategID); + assertThrows(MCRException.class, () -> new MCRCategoryID(invalidID, validCategID)); } - @Test(expected = MCRException.class) + @Test public void testInvalidCategID() { - new MCRCategoryID(validRootID, invalidID); + assertThrows(MCRException.class, () -> new MCRCategoryID(validRootID, invalidID)); } - @Test(expected = MCRException.class) + @Test public void testLongCategID() { - new MCRCategoryID(validRootID, toLongCategID); + assertThrows(MCRException.class, () -> new MCRCategoryID(validRootID, toLongCategID)); } - @Test(expected = MCRException.class) + @Test public void testLongRootID() { - new MCRCategoryID(toLongRootID, validCategID); + assertThrows(MCRException.class, () -> new MCRCategoryID(toLongRootID, validCategID)); } + + /** + * @see MCR-3302 + */ + @ParameterizedTest + @Tag("MCR-3302") + @ValueSource(strings = { + "", "foo:bar:baz", ":bar", ":bar:", ":bar:baz", "foo::bar", "foo::bar::", "foo::bar::baz", "::bar", "::bar::baz" + }) + public void testInvalidEdgeCases(String invalidCategoryId) { + assertThrows(IllegalArgumentException.class, () -> MCRCategoryID.fromString(invalidCategoryId)); + } + }