From f4cfe35ec5e063bf42ac99d287d63f1dfefb60de Mon Sep 17 00:00:00 2001 From: labkey-matthewb Date: Fri, 20 Mar 2026 19:15:26 -0700 Subject: [PATCH 1/2] EscapeUtil.getFormFieldName() also temporarily modfify TestDataGenerator --- src/org/labkey/test/util/EscapeUtil.java | 24 ++++++++++++------- .../labkey/test/util/TestDataGenerator.java | 6 ++--- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/org/labkey/test/util/EscapeUtil.java b/src/org/labkey/test/util/EscapeUtil.java index 6977dd0ba9..9cc0862694 100644 --- a/src/org/labkey/test/util/EscapeUtil.java +++ b/src/org/labkey/test/util/EscapeUtil.java @@ -15,6 +15,7 @@ */ package org.labkey.test.util; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.text.StringEscapeUtils; import org.apache.poi.ss.util.WorkbookUtil; import org.eclipse.jetty.util.URIUtil; @@ -271,20 +272,25 @@ public static String getFormFieldName(String columnName, boolean multiValue) return getFormFieldName(columnName, (multiValue ? "[]" : "") + FORM_FIELD_PREFIX); } + + + static final String FIELD_ENCODED_PREFIX = "%_"; + /** * Escapes special characters in a column name to be used as a form field name. - * See associated {@link org.labkey.api.query.QueryUpdateForm#getFormFieldName} + * See associated {@link org.labkey.api.util.PageFlowUtil#encodeFormName} */ public static String getFormFieldName(String columnName, @Nullable String prefix) { - StringBuilder fieldName = new StringBuilder(); - for (char c : columnName.toCharArray()) - { - if (SPECIAL_CHARS.indexOf(c) >= 0) - fieldName.append(BACKSLASH); - fieldName.append(c); - } + String name = prefix + columnName; - return prefix == null ? fieldName.toString() : prefix + fieldName; + final String escapeChar = "%"; + final String problemChars = "\\\""; + final String unclean = escapeChar + problemChars; + if (!StringUtils.containsAny(name, unclean)) + return name; + var ret = FIELD_ENCODED_PREFIX + encode(name); + assert !StringUtils.containsAny(ret, problemChars); + return ret; } } diff --git a/src/org/labkey/test/util/TestDataGenerator.java b/src/org/labkey/test/util/TestDataGenerator.java index 6f10582645..8b4f5592ff 100644 --- a/src/org/labkey/test/util/TestDataGenerator.java +++ b/src/org/labkey/test/util/TestDataGenerator.java @@ -670,16 +670,16 @@ public static String randomFieldName(@NotNull String part, @Nullable Integer num + WIDE_PLACEHOLDER + REPEAT_PLACEHOLDER + ALL_CHARS_PLACEHOLDER; int currentTries = 0; - RandomName randomFieldName = randomName(part, getNumChars(numStartChars, 5), getNumChars(numEndChars, 50), chars, exclusion); + RandomName randomFieldName = randomName(part, getNumChars(numStartChars, 5), getNumChars(numEndChars, 48), chars, exclusion); while ((maxLength != null && randomFieldName.name().length() > maxLength) || isDomainAndFieldNameInvalid(_domainKind, null, randomFieldName)) { - randomFieldName = randomName(part, getNumChars(numStartChars, 5), getNumChars(numEndChars, 50), chars, exclusion); + randomFieldName = randomName(part, getNumChars(numStartChars, 5), getNumChars(numEndChars, 48), chars, exclusion); if (++currentTries >= MAX_RANDOM_TRIES) throw new IllegalStateException("Failed to generate a valid field name after " + MAX_RANDOM_TRIES + " tries. Last generated name: " + randomFieldName); } TestLogger.log("Generated random field name for domainKind " + _domainKind + ": " + randomFieldName); - return randomFieldName.name(); + return randomFieldName.name() + "\"\'"; } private static boolean isDomainAndFieldNameInvalid(DomainKind domainKind, @Nullable RandomName domainName, @Nullable RandomName fieldName) From bde23735852d169604ed9cbe241afa51c5681917 Mon Sep 17 00:00:00 2001 From: labkey-matthewb Date: Tue, 24 Mar 2026 14:22:08 -0700 Subject: [PATCH 2/2] null check --- src/org/labkey/test/tests/list/ListTest.java | 23 +++++++++++++------- src/org/labkey/test/util/EscapeUtil.java | 2 +- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/org/labkey/test/tests/list/ListTest.java b/src/org/labkey/test/tests/list/ListTest.java index 418b3cbfc0..d82d02ce62 100644 --- a/src/org/labkey/test/tests/list/ListTest.java +++ b/src/org/labkey/test/tests/list/ListTest.java @@ -1654,7 +1654,6 @@ public void testAutoIncrementKeyEncoded() // setup a list with an auto-increment key that we need to make sure is encoded in the form input String encodedListName = "autoIncrementEncodeList"; String keyName = "'>'"; - String encodedKeyFieldName = EscapeUtil.getFormFieldName(keyName); _listHelper.createList(PROJECT_VERIFY, encodedListName, keyName, col("Name", ColumnType.String)); _listHelper.goToList(encodedListName); @@ -1666,7 +1665,7 @@ public void testAutoIncrementKeyEncoded() // insert a new row and verify the key field is not present table.clickInsertNewRow(); - checker().withScreenshot().verifyEquals("List fields on insert form.", List.of("quf_Name"), getQueryFormFieldNames()); + checker().withScreenshot().verifyEquals("List fields on insert form.", List.of("Name"), getQueryFormFieldNamesDecoded()); String nameValue = "test"; setFormElement(Locator.name(EscapeUtil.getFormFieldName("Name")), nameValue); clickButton("Submit"); @@ -1678,7 +1677,7 @@ public void testAutoIncrementKeyEncoded() // verify name value can be updated table.clickEditRow(0); - checker().withScreenshot().verifyEquals("List fields on update form.", List.of("quf_Name", encodedKeyFieldName), getQueryFormFieldNames()); + checker().withScreenshot().verifyEquals("List fields on update form.", List.of("Name", keyName), getQueryFormFieldNamesDecoded()); nameValue = "test updated"; setFormElement(Locator.name(EscapeUtil.getFormFieldName("Name")), nameValue); clickButton("Submit"); @@ -1728,12 +1727,20 @@ public void testMultiChoiceValues() _listHelper.deleteList(); } - private List getQueryFormFieldNames() + private List getQueryFormFieldNamesDecoded() { - return Locator.tag("input").attributeStartsWith("name", "quf_") - .findElements(getDriver()).stream() - .map(el -> el.getDomAttribute("name")) - .toList(); + ArrayList ret = new ArrayList<>(); + Locator.tag("input").attributeStartsWith("name", "quf_") + .findElements(getDriver()).stream() + .map(el -> el.getDomAttribute("name")) + .map(s -> s.substring(4)) + .forEach(name -> ret.add(name)); + Locator.tag("input").attributeStartsWith("name", "%_quf_") + .findElements(getDriver()).stream() + .map(el -> el.getDomAttribute("name")) + .map(name -> EscapeUtil.decode(name.substring(6))) + .forEach(name -> ret.add(name)); + return ret; } private void viewRawTableMetadata(String listName) diff --git a/src/org/labkey/test/util/EscapeUtil.java b/src/org/labkey/test/util/EscapeUtil.java index 9cc0862694..3ce61ed502 100644 --- a/src/org/labkey/test/util/EscapeUtil.java +++ b/src/org/labkey/test/util/EscapeUtil.java @@ -282,7 +282,7 @@ public static String getFormFieldName(String columnName, boolean multiValue) */ public static String getFormFieldName(String columnName, @Nullable String prefix) { - String name = prefix + columnName; + String name = Objects.toString(prefix,"") + columnName; final String escapeChar = "%"; final String problemChars = "\\\"";