diff --git a/api/src/org/labkey/api/action/AbstractFileUploadAction.java b/api/src/org/labkey/api/action/AbstractFileUploadAction.java index 902cfa8a4d3..1279bd43be5 100644 --- a/api/src/org/labkey/api/action/AbstractFileUploadAction.java +++ b/api/src/org/labkey/api/action/AbstractFileUploadAction.java @@ -15,7 +15,6 @@ */ package org.labkey.api.action; -import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; import org.labkey.api.util.ExceptionUtil; @@ -42,7 +41,6 @@ import java.io.Writer; import java.nio.charset.StandardCharsets; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; /** @@ -192,19 +190,16 @@ private void export(FORM form, HttpServletResponse response) throws Exception return; } - HttpServletRequest basicRequest = getViewContext().getRequest(); - // Parameter name (String) -> File on disk/original file name Pair Map> savedFiles = new HashMap<>(); - if (basicRequest instanceof MultipartHttpServletRequest request) + if (getViewContext().getRequest() instanceof MultipartHttpServletRequest) { - - Iterator nameIterator = request.getFileNames(); - while (nameIterator.hasNext()) + Map fileMap = getFileMap(); + for (var e : fileMap.entrySet()) { - String formElementName = nameIterator.next(); - MultipartFile file = request.getFile(formElementName); + var formElementName = e.getKey(); + var file = e.getValue(); String filename = file.getOriginalFilename(); try (InputStream input = file.getInputStream()) diff --git a/api/src/org/labkey/api/action/BaseViewAction.java b/api/src/org/labkey/api/action/BaseViewAction.java index 0e9e69946d4..dfce3258d4f 100644 --- a/api/src/org/labkey/api/action/BaseViewAction.java +++ b/api/src/org/labkey/api/action/BaseViewAction.java @@ -76,6 +76,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.function.Predicate; @@ -185,19 +186,11 @@ public static PropertyValues getPropertyValuesForFormBinding(PropertyValues pvs, return ret; } - static final String FORM_DATE_ENCODED_PARAM = "formDataEncoded"; - /** - * When a double quote is encountered in a multipart/form-data context, it is encoded as %22 using URL-encoding by browsers. - * This process replaces the double quote with its hexadecimal equivalent in a URL-safe format, preventing it from being misinterpreted as the end of a value or a boundary. - * The consequence of such encoding is we can't distinguish '"' from the actual '%22' in parameter name. - * As a workaround, a client-side util `encodeFormDataQuote` is used to convert %22 to %2522 and " to %22 explicitly, while passing in an additional param formDataEncoded=true. - * This class converts those encoded param names back to its decoded form during PropertyValues binding. - * See Issue 52827, 52925 and 52119 for more information. - */ + /// Some characters can be mishandled by the browser in multipart/formdata requests (e.g. doublequote and backslask). + /// We support an encoding from fields to avoid these characters, see {@link PageFlowUtil#encodeFormName} and {@link PageFlowUtil#decodeFormName}. static public class ViewActionParameterPropertyValues extends ServletRequestParameterPropertyValues { - public ViewActionParameterPropertyValues(ServletRequest request) { this(request, null, null); } @@ -205,31 +198,14 @@ public ViewActionParameterPropertyValues(ServletRequest request) { public ViewActionParameterPropertyValues(ServletRequest request, @Nullable String prefix, @Nullable String prefixSeparator) { super(request, prefix, prefixSeparator); - if (isFormDataEncoded()) - { - for (int i = 0; i < getPropertyValues().length; i++) - { - PropertyValue formDataPropValue = getPropertyValues()[i]; - String propValueName = formDataPropValue.getName(); - String decoded = PageFlowUtil.decodeQuoteEncodedFormDataKey(propValueName); - if (!propValueName.equals(decoded)) - setPropertyValueAt(new PropertyValue(decoded, formDataPropValue.getValue()), i); - } - } - } - - private boolean isFormDataEncoded() - { - PropertyValue formDataPropValue = getPropertyValue(FORM_DATE_ENCODED_PARAM); - if (formDataPropValue != null) + for (int i = 0; i < getPropertyValues().length; i++) { - Object v = formDataPropValue.getValue(); - String formDataPropValueStr = v == null ? null : String.valueOf(v); - if (StringUtils.isNotBlank(formDataPropValueStr)) - return (Boolean) ConvertUtils.convert(formDataPropValueStr, Boolean.class); + PropertyValue formDataPropValue = getPropertyValues()[i]; + String propValueName = formDataPropValue.getName(); + String decoded = PageFlowUtil.decodeFormName(propValueName); + if (!propValueName.equals(decoded)) + setPropertyValueAt(new PropertyValue(decoded, formDataPropValue.getValue()), i); } - - return false; } } @@ -725,9 +701,7 @@ public T convertIfNecessary(Object value, Class requiredType, MethodParam */ protected Map getFileMap() { - if (getViewContext().getRequest() instanceof MultipartHttpServletRequest) - return ((MultipartHttpServletRequest)getViewContext().getRequest()).getFileMap(); - return Collections.emptyMap(); + return PageFlowUtil.getFileMap(getViewContext().getRequest()); } protected List getAttachmentFileList() diff --git a/api/src/org/labkey/api/assay/AssayFileWriter.java b/api/src/org/labkey/api/assay/AssayFileWriter.java index 5164c5689e3..78dc87c283e 100644 --- a/api/src/org/labkey/api/assay/AssayFileWriter.java +++ b/api/src/org/labkey/api/assay/AssayFileWriter.java @@ -31,6 +31,7 @@ import org.labkey.api.query.AbstractQueryUpdateService; import org.labkey.api.util.FileUtil; import org.labkey.api.util.NetworkDrive; +import org.labkey.api.util.PageFlowUtil; import org.labkey.api.view.ViewContext; import org.labkey.vfs.FileLike; import org.springframework.web.multipart.MultipartFile; @@ -233,7 +234,7 @@ public Map savePostedFiles(ContextType context, @NotNull Set originalFileNames = new HashSet<>(); if (context.getRequest() instanceof MultipartHttpServletRequest multipartRequest) { - Iterator>> iter = multipartRequest.getMultiFileMap().entrySet().iterator(); + Iterator>> iter = PageFlowUtil.getMultiFileMap(context.getRequest()).entrySet().iterator(); Deque overflowFiles = new ArrayDeque<>(); // using a deque for easy removal of single elements Set unusedParameterNames = new HashSet<>(parameterNames); while (iter.hasNext()) diff --git a/api/src/org/labkey/api/assay/actions/AssayRunUploadForm.java b/api/src/org/labkey/api/assay/actions/AssayRunUploadForm.java index e3847e80643..ad9e02587c1 100644 --- a/api/src/org/labkey/api/assay/actions/AssayRunUploadForm.java +++ b/api/src/org/labkey/api/assay/actions/AssayRunUploadForm.java @@ -23,6 +23,7 @@ import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.labkey.api.action.BaseViewAction; import org.labkey.api.assay.AbstractAssayProvider; import org.labkey.api.assay.AssayDataCollector; import org.labkey.api.assay.AssayFileWriter; @@ -61,6 +62,7 @@ import org.labkey.api.study.assay.ParticipantVisitResolverType; import org.labkey.api.util.FileUtil; import org.labkey.api.util.GUID; +import org.labkey.api.util.PageFlowUtil; import org.labkey.api.view.ActionURL; import org.labkey.api.view.NotFoundException; import org.labkey.api.view.UnauthorizedException; @@ -360,10 +362,11 @@ public Map getAdditionalPostedFiles(List getTypedColumns(boolean includeUntyped) for (ColumnInfo column : getTable().getColumns()) { + var fieldName = getFormFieldName(column); + if (hasTypedValue(column)) { values.put(column.getName(), getTypedValue(column)); } - else if (includeUntyped && _stringValues.containsKey(getFormFieldName(column))) + else if (includeUntyped && _stringValues.containsKey(fieldName)) { - values.put(column.getName(), _stringValues.get(getFormFieldName(column))); + values.put(column.getName(), _stringValues.get(fieldName)); } else if (getRequest() instanceof MultipartHttpServletRequest request) { - String fieldName = getMultiPartFormFieldName(column); - Object typedValue = _getTypedValues().get(fieldName); - - if (typedValue != null) - values.put(column.getName(), typedValue); - else if (File.class.equals(column.getJavaClass())) + if (File.class.equals(column.getJavaClass())) { - MultipartFile file = request.getFile(fieldName); + MultipartFile file = PageFlowUtil.getFileMap(request).get(fieldName); if (file != null) { // Check if the file was removed @@ -587,10 +584,11 @@ else if (File.class.equals(column.getJavaClass())) ColumnInfo mvColumn = getTable().getColumn(column.getMvColumnName()); if (null != mvColumn) { + var mvFieldName = getFormFieldName(mvColumn); if (hasTypedValue(mvColumn)) values.put(mvColumn.getName(), getTypedValue(mvColumn)); - else if (includeUntyped && _stringValues.containsKey(getFormFieldName(mvColumn))) - values.put(mvColumn.getName(), _stringValues.get(getFormFieldName(mvColumn))); + else if (includeUntyped && _stringValues.containsKey(mvFieldName)) + values.put(mvColumn.getName(), _stringValues.get(mvFieldName)); } } } @@ -739,11 +737,6 @@ public String getFormFieldName(@NotNull ColumnInfo column) return column.getName(); } - public String getMultiPartFormFieldName(@NotNull ColumnInfo column) - { - return getFormFieldName(column); - } - @Nullable public ColumnInfo getColumnByFormFieldName(@NotNull String name) { diff --git a/api/src/org/labkey/api/dataiterator/DataIteratorUtil.java b/api/src/org/labkey/api/dataiterator/DataIteratorUtil.java index 813c77e8668..0922be2d010 100644 --- a/api/src/org/labkey/api/dataiterator/DataIteratorUtil.java +++ b/api/src/org/labkey/api/dataiterator/DataIteratorUtil.java @@ -141,57 +141,14 @@ public static Map createTableMap(TableInfo target, boolean us // rank of a match of import column NAME matching various properties of target column // MatchType.low is used for matches based on something other than name - public enum MatchType + private enum MatchType { propertyuri, name, alias, jdbcname, tsvColumn, - multiPartFormData() - { - @Override - public String getMatchedName(@Nullable String name) - { - if (name == null) - return null; - // " is encoded as %22 when content-type is "multipart/form-data" (but is not otherwise encoded so decode() does not work) - return name.replaceAll("\"", "%22"); - } - - @Override - public boolean updateRowMap(@NotNull ColumnInfo col, Map rowMap) - { - if (col.getName().contains("\"") && File.class.equals(col.getJavaClass())) - { - // Issue 52827: File/attachment fields with special characters - String quoteEncodedName = DataIteratorUtil.MatchType.multiPartFormData.getMatchedName(col.getName()); - if (rowMap.containsKey(quoteEncodedName)) - { - rowMap.put(col.getName(), rowMap.get(quoteEncodedName)); - rowMap.remove(quoteEncodedName); - return true; - } - } - return false; - } - }, - low; - - public String getMatchedName(@Nullable String name) - { - return name; - } - - /** - * Update rowMap content based on passed in col. - * For example, the original rowMap may contain encoded field name. This util substitute the key in rowMap to reflect the actual col name - * @return If rowMap has been updated - */ - public boolean updateRowMap(@NotNull ColumnInfo col, Map rowMap) - { - return false; - } + low } @@ -209,9 +166,6 @@ protected static Map> _createTableMap(TableInf Map> targetAliasesMap = new CaseInsensitiveHashMap<>(cols.size()*4); - for (ColumnInfo col : cols) - targetAliasesMap.put(MatchType.multiPartFormData.getMatchedName(col.getName()), new Pair<>(col, MatchType.multiPartFormData)); - // should this be under the useImportAliases flag??? for (ColumnInfo col : cols) { diff --git a/api/src/org/labkey/api/dataiterator/StandardDataIteratorBuilder.java b/api/src/org/labkey/api/dataiterator/StandardDataIteratorBuilder.java index ccbd5140882..4bc1a41d7ff 100644 --- a/api/src/org/labkey/api/dataiterator/StandardDataIteratorBuilder.java +++ b/api/src/org/labkey/api/dataiterator/StandardDataIteratorBuilder.java @@ -25,7 +25,6 @@ import org.labkey.api.data.TableInfo; import org.labkey.api.data.validator.ColumnValidator; import org.labkey.api.data.validator.ColumnValidators; -import org.labkey.api.data.validator.RequiredValidator; import org.labkey.api.exp.PropertyDescriptor; import org.labkey.api.exp.PropertyType; import org.labkey.api.exp.api.ExperimentService; diff --git a/api/src/org/labkey/api/defaults/SetDefaultValuesAction.java b/api/src/org/labkey/api/defaults/SetDefaultValuesAction.java index 77bb5d3f497..dfaac707803 100644 --- a/api/src/org/labkey/api/defaults/SetDefaultValuesAction.java +++ b/api/src/org/labkey/api/defaults/SetDefaultValuesAction.java @@ -448,7 +448,7 @@ public boolean handlePost(FormType domainIdForm, BindException errors) throws Ex */ protected String encodePropertyValues(FormType domainIdForm, String propName) throws IOException { - return domainIdForm.getRequest().getParameter(propName); + return (String)getProperty(propName); } @Override diff --git a/api/src/org/labkey/api/exp/property/DomainUtil.java b/api/src/org/labkey/api/exp/property/DomainUtil.java index 010fee00f0c..32e5344b8cf 100644 --- a/api/src/org/labkey/api/exp/property/DomainUtil.java +++ b/api/src/org/labkey/api/exp/property/DomainUtil.java @@ -1587,8 +1587,6 @@ public static ValidationException validateProperties(@Nullable Domain domain, @N else { altNameMap.put(name, name); - altNameMap.put(DataIteratorUtil.MatchType.multiPartFormData.getMatchedName(name), name); - altNameMap.put(name.replaceAll("%22", "\""), name); } } diff --git a/api/src/org/labkey/api/jsp/JspBase.java b/api/src/org/labkey/api/jsp/JspBase.java index 22c7298d790..173e5b8b8b4 100644 --- a/api/src/org/labkey/api/jsp/JspBase.java +++ b/api/src/org/labkey/api/jsp/JspBase.java @@ -211,6 +211,11 @@ public static HtmlString h(URLHelper url) return h(url == null ? null : url.toString()); } + public static HtmlString hname(String name) + { + return HtmlString.of(PageFlowUtil.encodeFormName(name)); + } + // Note: If you have a stream, use LabKeyCollectors.toJsonArray() public static JSONArray toJsonArray(Collection c) { diff --git a/api/src/org/labkey/api/query/AbstractQueryImportAction.java b/api/src/org/labkey/api/query/AbstractQueryImportAction.java index 51ecac86358..0480c0fb7be 100644 --- a/api/src/org/labkey/api/query/AbstractQueryImportAction.java +++ b/api/src/org/labkey/api/query/AbstractQueryImportAction.java @@ -549,7 +549,7 @@ else if (_target != null) } else if (getViewContext().getRequest() instanceof MultipartHttpServletRequest) { - Map files = ((MultipartHttpServletRequest)getViewContext().getRequest()).getFileMap(); + Map files = getFileMap(); MultipartFile multipartfile = null==files ? null : files.get("file"); if (null != multipartfile && multipartfile.getSize() > 0) { diff --git a/api/src/org/labkey/api/query/DefaultQueryUpdateService.java b/api/src/org/labkey/api/query/DefaultQueryUpdateService.java index 1299cea69d9..3fd1c9c97a5 100644 --- a/api/src/org/labkey/api/query/DefaultQueryUpdateService.java +++ b/api/src/org/labkey/api/query/DefaultQueryUpdateService.java @@ -16,7 +16,6 @@ package org.labkey.api.query; import org.apache.commons.beanutils.ConversionException; -import org.apache.commons.beanutils.ConvertUtils; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/api/src/org/labkey/api/query/QueryUpdateForm.java b/api/src/org/labkey/api/query/QueryUpdateForm.java index c2585120947..6aca3df3c4a 100644 --- a/api/src/org/labkey/api/query/QueryUpdateForm.java +++ b/api/src/org/labkey/api/query/QueryUpdateForm.java @@ -21,7 +21,6 @@ import org.labkey.api.data.ColumnInfo; import org.labkey.api.data.TableInfo; import org.labkey.api.data.TableViewForm; -import org.labkey.api.dataiterator.DataIteratorUtil; import org.labkey.api.view.ViewContext; import org.springframework.validation.BindException; @@ -76,52 +75,16 @@ public QueryUpdateForm(@NotNull TableInfo table, @NotNull ViewContext ctx, @Null @Nullable public ColumnInfo getColumnByFormFieldName(@NotNull String fieldName) { - if (!_ignorePrefix && fieldName.length() < PREFIX.length()) - return null; - - var columnName = _ignorePrefix ? fieldName : fieldName.substring(PREFIX.length()); - - StringBuilder sb = new StringBuilder(columnName.length()); - boolean escaping = false; - for (char c : columnName.toCharArray()) - { - if (escaping) - { - sb.append(c); - escaping = false; - } - else if (c == BACKSLASH) - escaping = true; - else - sb.append(c); - } - - // Issue 54094: Ensure it works when backslash is the last character - if (escaping) - sb.append(BACKSLASH); - - return getTable().getColumn(sb.toString()); + String columnName = fieldName; + if (!_ignorePrefix && columnName.startsWith(PREFIX)) + columnName = columnName.substring(PREFIX.length()); + return getTable().getColumn(columnName); } @Override public String getFormFieldName(@NotNull ColumnInfo column) { String columnName = column.getName(); - StringBuilder sb = new StringBuilder(); - for (char c : columnName.toCharArray()) - { - if (SPECIAL_CHARS.indexOf(c) >= 0) - sb.append(BACKSLASH); - sb.append(c); - } - - String fieldName = sb.toString(); - return _ignorePrefix ? fieldName : PREFIX + fieldName; - } - - @Override - public String getMultiPartFormFieldName(@NotNull ColumnInfo column) - { - return DataIteratorUtil.MatchType.multiPartFormData.getMatchedName(getFormFieldName(column)); + return _ignorePrefix ? columnName : PREFIX + columnName; } } diff --git a/api/src/org/labkey/api/query/excelExportOptions.jsp b/api/src/org/labkey/api/query/excelExportOptions.jsp index a313c054d9c..a27644bff4a 100644 --- a/api/src/org/labkey/api/query/excelExportOptions.jsp +++ b/api/src/org/labkey/api/query/excelExportOptions.jsp @@ -64,16 +64,16 @@ %> - + - + <% if (model.getIqyURL() != null) { %> - + <% } %> diff --git a/api/src/org/labkey/api/util/DOM.java b/api/src/org/labkey/api/util/DOM.java index 1feb02da7b1..f31179179b2 100644 --- a/api/src/org/labkey/api/util/DOM.java +++ b/api/src/org/labkey/api/util/DOM.java @@ -422,7 +422,16 @@ Appendable render(Appendable builder, Object value) throws IOException min, multiple, muted, - name, + name + { + @Override + Appendable render(Appendable builder, Object value) throws IOException + { + if (value instanceof String s) + value = PageFlowUtil.encodeFormName(s); + return super.render(builder, value); + } + }, nonce, novalidate { diff --git a/api/src/org/labkey/api/util/InputBuilder.java b/api/src/org/labkey/api/util/InputBuilder.java index d28fb33ce83..3648f245284 100644 --- a/api/src/org/labkey/api/util/InputBuilder.java +++ b/api/src/org/labkey/api/util/InputBuilder.java @@ -898,6 +898,10 @@ protected final String h(int i) { return String.valueOf(i); } + protected final String hname(String name) + { + return PageFlowUtil.filter(PageFlowUtil.encodeFormName(name)); + } protected void doInput(Appendable sb) throws IOException { @@ -911,7 +915,7 @@ protected void doInput(Appendable sb) throws IOException sb.append("\""); } - sb.append(" name=\"").append(h(getName())).append("\""); + sb.append(" name=\"").append(hname(getName())).append("\""); var id = generateId("input"); diff --git a/api/src/org/labkey/api/util/PageFlowUtil.java b/api/src/org/labkey/api/util/PageFlowUtil.java index c1240a601cc..71f1a027cb7 100644 --- a/api/src/org/labkey/api/util/PageFlowUtil.java +++ b/api/src/org/labkey/api/util/PageFlowUtil.java @@ -85,6 +85,10 @@ import org.labkey.vfs.FileLike; import org.springframework.beans.PropertyValue; import org.springframework.beans.PropertyValues; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.util.WebUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -2685,19 +2689,59 @@ private static boolean shouldEscapeForExport(@NotNull String value) } - /** - * Issue 52925: App export to csv/tsv ignores filter with column containing double quote - * Issue 52119: App issues with assay run properties with special characters - * @param encodedKey The encoded form key by client side `encodeFormDataQuote` util - * @return The decoded raw field name - */ - public static String decodeQuoteEncodedFormDataKey(@Nullable String encodedKey) + static final String FIELD_ENCODED_PREFIX = "%_"; + + /// Because of various bugs related encoding of INPUT.name values in multipart/formdata, we now recommend encoding + /// all names in all forms. + /// The choice of using encodeURI component is somewhat arbitrary, any encoding that can remove + /// double-quote and backslash from the name would be fine. + /// + /// This must be kept in sync with org.labkey.test.util.EscapeUtil#getFormFieldName + public static String encodeFormName(String name) { - if (encodedKey == null) - return null; - return encodedKey.replaceAll("%22", "\"").replaceAll("%2522", "%22"); + final String escapeChar = "%"; + final String problemChars = "\\\""; + final String unclean = escapeChar + problemChars; + if (!StringUtils.containsAny(name, unclean)) + return name; + // CONSIDER: use encode(name) for simplicity or only encode the unclean chars? + var ret = FIELD_ENCODED_PREFIX + encode(name); + return ret; + } + + + public static String decodeFormName(@NotNull String name) + { + if (!name.startsWith(FIELD_ENCODED_PREFIX)) + return name; + return decode(name.substring(FIELD_ENCODED_PREFIX.length())); + } + + + /** Use in preference to {@link MultipartHttpServletRequest#getFileMap()} */ + static public Map getFileMap(HttpServletRequest req) + { + if (!(req instanceof MultipartHttpServletRequest mpreq)) + return Collections.emptyMap(); + @SuppressWarnings("SSBasedInspection") + Map htmlMap = mpreq.getFileMap(); + Map formMap = new LinkedHashMap<>(); + htmlMap.forEach((key, value) -> formMap.put(PageFlowUtil.decodeFormName(key), value)); + return formMap; + } + + static public MultiValueMap getMultiFileMap(HttpServletRequest req) + { + MultiValueMap formMap = new LinkedMultiValueMap<>(); + if (!(req instanceof MultipartHttpServletRequest mpreq)) + return formMap; + @SuppressWarnings("SSBasedInspection") + MultiValueMap htmlMap = mpreq.getMultiFileMap(); + htmlMap.forEach((key, value) -> formMap.put(PageFlowUtil.decodeFormName(key), value)); + return formMap; } + public static class TestCase extends Assert { @Test @@ -3103,19 +3147,49 @@ public void encodePath() assertEquals("/a/b/c/", PageFlowUtil.encodePath("/a/b/c/")); } + private void assertEncodeDecode(String test) + { + assertFalse(StringUtils.containsAny(encodeFormName(test), "\\\"%")); + assertEquals(test, decodeFormName(encodeFormName(test))); + } + + private void assertReencode(String a) + { + // We want to make sure there are no ambiguous encodings + var b = encodeFormName(a); + var c = encodeFormName(b); + assertFalse(StringUtils.containsAny(b, "\\\"%")); + assertFalse(StringUtils.containsAny(c, "\\\"%")); + if (a.equals(b)) + assertEquals(a,c); + else + assertNotEquals(b,c); + } + @Test - public void testDecodeQuoteEncodedFormDataKey() - { - assertEquals("test", decodeQuoteEncodedFormDataKey("test")); - assertEquals("a/b/c", decodeQuoteEncodedFormDataKey("a/b/c")); - assertEquals("a'b.c", decodeQuoteEncodedFormDataKey("a'b.c")); - assertEquals("%", decodeQuoteEncodedFormDataKey("%")); - assertEquals("\"", decodeQuoteEncodedFormDataKey("%22")); - assertEquals("\"\"", decodeQuoteEncodedFormDataKey("%22%22")); - assertEquals("%22", decodeQuoteEncodedFormDataKey("%2522")); - assertEquals("%22%22", decodeQuoteEncodedFormDataKey("%2522%2522")); - assertEquals("%22\"", decodeQuoteEncodedFormDataKey("%2522%22")); - assertEquals("\"22", decodeQuoteEncodedFormDataKey("%2222")); + public void testFormNameEncoding() + { + assertEncodeDecode("test"); + assertEncodeDecode("a/b/c"); + assertEncodeDecode("a'b.c"); + assertEncodeDecode("%"); + assertEncodeDecode("\""); + assertEncodeDecode("\"\""); + assertEncodeDecode("%22"); + assertEncodeDecode("%22%22"); + assertEncodeDecode("%22\""); + assertEncodeDecode("\"22"); + + assertReencode("test"); + assertReencode("a/b/c"); + assertReencode("a'b.c"); + assertReencode("%"); + assertReencode("\""); + assertReencode("\"\""); + assertReencode("%22"); + assertReencode("%22%22"); + assertReencode("%22\""); + assertReencode("\"22"); } } diff --git a/api/src/org/labkey/api/util/SelectBuilder.java b/api/src/org/labkey/api/util/SelectBuilder.java index 7145c4f0a51..521814cccd3 100644 --- a/api/src/org/labkey/api/util/SelectBuilder.java +++ b/api/src/org/labkey/api/util/SelectBuilder.java @@ -167,7 +167,7 @@ protected void doInput(Appendable sb) throws IOException { var id = StringUtils.defaultIfBlank(getId(), generateId("select")); - sb.append("> resolveRows( ColumnInfo col = columnInfoMap.get(entry.getKey()); if (col != null && !row.containsKey(entry.getKey())) { - if (DataIteratorUtil.MatchType.multiPartFormData.updateRowMap(col, row)) - continue; - // use column names for existing row values row.put(col.getName(), entry.getValue()); } diff --git a/assay/api-src/org/labkey/api/assay/plate/PlateSampleFilePropertyHelper.java b/assay/api-src/org/labkey/api/assay/plate/PlateSampleFilePropertyHelper.java index e749867e848..65af09c55b6 100644 --- a/assay/api-src/org/labkey/api/assay/plate/PlateSampleFilePropertyHelper.java +++ b/assay/api-src/org/labkey/api/assay/plate/PlateSampleFilePropertyHelper.java @@ -98,7 +98,7 @@ public PlateSampleFilePropertyHelper(Container container, ExpProtocol protocol, private MultipartFile getMetadataFile(HttpServletRequest request) { - if (request instanceof MultipartHttpServletRequest multipartRequest) + if (request instanceof MultipartHttpServletRequest) { String entryKeyToFind; if (_metadataInputFormat == SampleMetadataInputFormat.FILE_BASED) @@ -112,7 +112,8 @@ else if (_metadataInputFormat == SampleMetadataInputFormat.COMBINED) else return null; - for (Map.Entry entry : multipartRequest.getFileMap().entrySet()) + var fileMap = PageFlowUtil.getFileMap(request); + for (Map.Entry entry : fileMap.entrySet()) { if (entryKeyToFind.equals(entry.getKey())) { diff --git a/assay/package-lock.json b/assay/package-lock.json index 69163de7dca..bcacfe701ad 100644 --- a/assay/package-lock.json +++ b/assay/package-lock.json @@ -8,7 +8,7 @@ "name": "assay", "version": "0.0.0", "dependencies": { - "@labkey/components": "7.23.5" + "@labkey/components": "7.25.1-fb-encodeFormName.0" }, "devDependencies": { "@labkey/build": "9.0.0", @@ -2722,9 +2722,9 @@ } }, "node_modules/@labkey/api": { - "version": "1.49.1", - "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/api/-/@labkey/api-1.49.1.tgz", - "integrity": "sha512-ClFIyggEDH4PC+HB4tnZpaOfIls4MgJugS4TmE6Y5xmVzBm8L442aF/gJFMqcZQ1MMNTP7swRHbfvSvJN5Cmyw==", + "version": "1.49.2-fb-encodeFormName.0", + "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/api/-/@labkey/api-1.49.2-fb-encodeFormName.0.tgz", + "integrity": "sha512-QEghEbSY+c+GbZc4vF98zyvaWRHgW/R6mt38skV3ZcdysIY1ZONnfCKR696pC+klgGKfus/POGLUDHQ58AOnEA==", "license": "Apache-2.0" }, "node_modules/@labkey/build": { @@ -2765,13 +2765,13 @@ } }, "node_modules/@labkey/components": { - "version": "7.23.5", - "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/components/-/@labkey/components-7.23.5.tgz", - "integrity": "sha512-JABXXE84xShDhlENS8mEAp8BBnbLv9gmb05SVsJiq7tRnQZzSY1/pFfyGRY7m2fEWsxf6j4wDzlpH5odig8exg==", + "version": "7.25.1-fb-encodeFormName.0", + "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/components/-/@labkey/components-7.25.1-fb-encodeFormName.0.tgz", + "integrity": "sha512-hHUbeW9nXlQNXBGmoJzsYTQrzf52c0ldXjNCVVIrwjh1ShHXgrnRvQMWLPnMjtQirgu7GulKT9fmMqtmi+cEAA==", "license": "SEE LICENSE IN LICENSE.txt", "dependencies": { "@hello-pangea/dnd": "18.0.1", - "@labkey/api": "1.49.1", + "@labkey/api": "1.49.2-fb-encodeFormName.0", "@testing-library/dom": "~10.4.1", "@testing-library/jest-dom": "~6.9.1", "@testing-library/react": "~16.3.2", diff --git a/assay/package.json b/assay/package.json index a833e37a8b9..d26eba8d65d 100644 --- a/assay/package.json +++ b/assay/package.json @@ -12,7 +12,7 @@ "clean": "rimraf resources/web/assay/gen && rimraf resources/views/gen && rimraf resources/web/gen" }, "dependencies": { - "@labkey/components": "7.23.5" + "@labkey/components": "7.25.1-fb-encodeFormName.0" }, "devDependencies": { "@labkey/build": "9.0.0", diff --git a/assay/src/org/labkey/assay/actions/ImportRunApiAction.java b/assay/src/org/labkey/assay/actions/ImportRunApiAction.java index 54d26bc3220..36302c7d5f3 100644 --- a/assay/src/org/labkey/assay/actions/ImportRunApiAction.java +++ b/assay/src/org/labkey/assay/actions/ImportRunApiAction.java @@ -746,9 +746,9 @@ private static String parsePropertiesKey(String key) return null; // Issue 52119: account for leading/trailing single quotes and decode double quotes and % - if (key.startsWith("'") && key.endsWith("'")) + if (key.length() >= 2 && key.startsWith("'") && key.endsWith("'")) key = key.substring(1, key.length()-1); - key = PageFlowUtil.decodeQuoteEncodedFormDataKey(key); + key = PageFlowUtil.decodeFormName(key); return key; } diff --git a/core/package-lock.json b/core/package-lock.json index 03d7acadb1b..bdd01bfddb2 100644 --- a/core/package-lock.json +++ b/core/package-lock.json @@ -8,7 +8,7 @@ "name": "labkey-core", "version": "0.0.0", "dependencies": { - "@labkey/components": "7.23.5", + "@labkey/components": "7.25.1-fb-encodeFormName.0", "@labkey/themes": "1.7.0" }, "devDependencies": { @@ -3717,9 +3717,9 @@ } }, "node_modules/@labkey/api": { - "version": "1.49.1", - "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/api/-/@labkey/api-1.49.1.tgz", - "integrity": "sha512-ClFIyggEDH4PC+HB4tnZpaOfIls4MgJugS4TmE6Y5xmVzBm8L442aF/gJFMqcZQ1MMNTP7swRHbfvSvJN5Cmyw==", + "version": "1.49.2-fb-encodeFormName.0", + "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/api/-/@labkey/api-1.49.2-fb-encodeFormName.0.tgz", + "integrity": "sha512-QEghEbSY+c+GbZc4vF98zyvaWRHgW/R6mt38skV3ZcdysIY1ZONnfCKR696pC+klgGKfus/POGLUDHQ58AOnEA==", "license": "Apache-2.0" }, "node_modules/@labkey/build": { @@ -3760,13 +3760,13 @@ } }, "node_modules/@labkey/components": { - "version": "7.23.5", - "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/components/-/@labkey/components-7.23.5.tgz", - "integrity": "sha512-JABXXE84xShDhlENS8mEAp8BBnbLv9gmb05SVsJiq7tRnQZzSY1/pFfyGRY7m2fEWsxf6j4wDzlpH5odig8exg==", + "version": "7.25.1-fb-encodeFormName.0", + "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/components/-/@labkey/components-7.25.1-fb-encodeFormName.0.tgz", + "integrity": "sha512-hHUbeW9nXlQNXBGmoJzsYTQrzf52c0ldXjNCVVIrwjh1ShHXgrnRvQMWLPnMjtQirgu7GulKT9fmMqtmi+cEAA==", "license": "SEE LICENSE IN LICENSE.txt", "dependencies": { "@hello-pangea/dnd": "18.0.1", - "@labkey/api": "1.49.1", + "@labkey/api": "1.49.2-fb-encodeFormName.0", "@testing-library/dom": "~10.4.1", "@testing-library/jest-dom": "~6.9.1", "@testing-library/react": "~16.3.2", diff --git a/core/package.json b/core/package.json index 7dc26bccfb0..853547dc3b6 100644 --- a/core/package.json +++ b/core/package.json @@ -53,7 +53,7 @@ } }, "dependencies": { - "@labkey/components": "7.23.5", + "@labkey/components": "7.25.1-fb-encodeFormName.0", "@labkey/themes": "1.7.0" }, "devDependencies": { diff --git a/core/src/org/labkey/core/admin/existingExternalSources.jsp b/core/src/org/labkey/core/admin/existingExternalSources.jsp index 4a8ba828a67..0326dc64a57 100644 --- a/core/src/org/labkey/core/admin/existingExternalSources.jsp +++ b/core/src/org/labkey/core/admin/existingExternalSources.jsp @@ -92,8 +92,8 @@ String hostId = "host" + num; %> - - + + - + <% diff --git a/core/src/org/labkey/core/login/setPassword.jsp b/core/src/org/labkey/core/login/setPassword.jsp index 9cb53764bb8..33da7c36ba1 100644 --- a/core/src/org/labkey/core/login/setPassword.jsp +++ b/core/src/org/labkey/core/login/setPassword.jsp @@ -76,7 +76,7 @@ @@ -95,7 +95,7 @@ @@ -103,7 +103,6 @@ if (rule.shouldShowPasswordGuidance() && firstPassword) { firstPasswordId = input.getObject().toString(); - %> Your browser does not support the HTML5 canvas element. diff --git a/core/src/org/labkey/core/user/UserController.java b/core/src/org/labkey/core/user/UserController.java index 6cf82cd7c7b..a780d0d9b8b 100644 --- a/core/src/org/labkey/core/user/UserController.java +++ b/core/src/org/labkey/core/user/UserController.java @@ -1102,8 +1102,7 @@ public void validateCommand(QueryUpdateForm form, Errors errors) } } - String userId = form.getPkVal().toString(); - if (userId == null) + if (null == form.getPkVal()) { errors.reject(SpringActionController.ERROR_MSG, "UserId parameter must be provided."); } diff --git a/core/src/org/labkey/core/webdav/DavController.java b/core/src/org/labkey/core/webdav/DavController.java index 9909eb546a8..c882f6dfde4 100644 --- a/core/src/org/labkey/core/webdav/DavController.java +++ b/core/src/org/labkey/core/webdav/DavController.java @@ -1231,12 +1231,13 @@ public WebdavStatus doMethod() throws DavException, IOException, RedirectExcepti if (getRequest() instanceof MultipartHttpServletRequest multipartRequest) { - if (multipartRequest.getFileMap().size() > 1) + var fileMap = PageFlowUtil.getFileMap(multipartRequest); + if (fileMap.size() > 1) return WebdavStatus.SC_NOT_IMPLEMENTED; - if (multipartRequest.getFileMap().isEmpty()) + if (fileMap.isEmpty()) return WebdavStatus.SC_METHOD_NOT_ALLOWED; - Map.Entry entry = multipartRequest.getFileMap().entrySet().iterator().next(); + Map.Entry entry = fileMap.entrySet().iterator().next(); MultipartFile file = entry.getValue(); if (null == filename) { diff --git a/experiment/package-lock.json b/experiment/package-lock.json index 3b0e81e0a82..3aee48638ca 100644 --- a/experiment/package-lock.json +++ b/experiment/package-lock.json @@ -8,7 +8,7 @@ "name": "experiment", "version": "0.0.0", "dependencies": { - "@labkey/components": "7.23.5" + "@labkey/components": "7.25.1-fb-encodeFormName.0" }, "devDependencies": { "@labkey/build": "9.0.0", @@ -3568,9 +3568,9 @@ } }, "node_modules/@labkey/api": { - "version": "1.49.1", - "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/api/-/@labkey/api-1.49.1.tgz", - "integrity": "sha512-ClFIyggEDH4PC+HB4tnZpaOfIls4MgJugS4TmE6Y5xmVzBm8L442aF/gJFMqcZQ1MMNTP7swRHbfvSvJN5Cmyw==", + "version": "1.49.2-fb-encodeFormName.0", + "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/api/-/@labkey/api-1.49.2-fb-encodeFormName.0.tgz", + "integrity": "sha512-QEghEbSY+c+GbZc4vF98zyvaWRHgW/R6mt38skV3ZcdysIY1ZONnfCKR696pC+klgGKfus/POGLUDHQ58AOnEA==", "license": "Apache-2.0" }, "node_modules/@labkey/build": { @@ -3611,13 +3611,13 @@ } }, "node_modules/@labkey/components": { - "version": "7.23.5", - "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/components/-/@labkey/components-7.23.5.tgz", - "integrity": "sha512-JABXXE84xShDhlENS8mEAp8BBnbLv9gmb05SVsJiq7tRnQZzSY1/pFfyGRY7m2fEWsxf6j4wDzlpH5odig8exg==", + "version": "7.25.1-fb-encodeFormName.0", + "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/components/-/@labkey/components-7.25.1-fb-encodeFormName.0.tgz", + "integrity": "sha512-hHUbeW9nXlQNXBGmoJzsYTQrzf52c0ldXjNCVVIrwjh1ShHXgrnRvQMWLPnMjtQirgu7GulKT9fmMqtmi+cEAA==", "license": "SEE LICENSE IN LICENSE.txt", "dependencies": { "@hello-pangea/dnd": "18.0.1", - "@labkey/api": "1.49.1", + "@labkey/api": "1.49.2-fb-encodeFormName.0", "@testing-library/dom": "~10.4.1", "@testing-library/jest-dom": "~6.9.1", "@testing-library/react": "~16.3.2", diff --git a/experiment/package.json b/experiment/package.json index 56f214f87b5..edbc583ffdf 100644 --- a/experiment/package.json +++ b/experiment/package.json @@ -13,7 +13,7 @@ "test-integration": "cross-env NODE_ENV=test jest --ci --runInBand -c test/js/jest.config.integration.js" }, "dependencies": { - "@labkey/components": "7.23.5" + "@labkey/components": "7.25.1-fb-encodeFormName.0" }, "devDependencies": { "@labkey/build": "9.0.0", diff --git a/experiment/src/org/labkey/experiment/controllers/exp/ExperimentController.java b/experiment/src/org/labkey/experiment/controllers/exp/ExperimentController.java index 64c09400e43..f2bdbe61ede 100644 --- a/experiment/src/org/labkey/experiment/controllers/exp/ExperimentController.java +++ b/experiment/src/org/labkey/experiment/controllers/exp/ExperimentController.java @@ -20,6 +20,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; +import org.apache.commons.beanutils.ConversionException; import org.apache.commons.collections4.MapUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Strings; @@ -31,6 +32,7 @@ import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.jspecify.annotations.NonNull; import org.labkey.api.action.ApiJsonWriter; import org.labkey.api.action.ApiResponse; import org.labkey.api.action.ApiSimpleResponse; @@ -75,6 +77,7 @@ import org.labkey.api.data.Container; import org.labkey.api.data.ContainerFilter; import org.labkey.api.data.ContainerManager; +import org.labkey.api.data.ConvertHelper; import org.labkey.api.data.DataRegion; import org.labkey.api.data.DataRegionSelection; import org.labkey.api.data.DbSchema; @@ -6770,7 +6773,7 @@ public Object execute(Object o, BindException errors) throws Exception ExperimentPipelineJob job = new ExperimentPipelineJob(getViewBackgroundInfo(), xarFile, "Uploaded file", true, pipeRoot); PipelineService.get().queueJob(job); - + response.put("success", true); return response; } @@ -7492,15 +7495,7 @@ public BindException bindParameters(PropertyValues m) throws Exception QueryUpdateForm tableForm = (QueryUpdateForm)bind.getTarget(); - int sampleId; - try - { - sampleId = Integer.parseInt((String) tableForm.getPkVal()); - } - catch (NumberFormatException e) - { - throw new NotFoundException("Invalid RowId: " + tableForm.getPkVal()); - } + long sampleId = getSampleId(tableForm); ExpMaterial material = ExperimentService.get().getExpMaterial(sampleId); if (material == null) @@ -7509,10 +7504,25 @@ public BindException bindParameters(PropertyValues m) throws Exception return bind; } + private static long getSampleId(QueryUpdateForm tableForm) + { + Long sampleId = null; + try + { + sampleId = ConvertHelper.convert(tableForm.getPkVal(), Long.class); + } + catch (ConversionException e) + { + } + if (null == sampleId) + throw new NotFoundException("Invalid RowId: " + tableForm.getPkVal()); + return sampleId; + } + @Override public ModelAndView getView(QueryUpdateForm tableForm, boolean reshow, BindException errors) { - int sampleId = Integer.parseInt((String) tableForm.getPkVal()); + long sampleId = getSampleId(tableForm); ExpMaterial material = ExperimentService.get().getExpMaterial(sampleId); if (material == null) diff --git a/experiment/src/org/labkey/experiment/controllers/property/PropertyController.java b/experiment/src/org/labkey/experiment/controllers/property/PropertyController.java index c258ef24623..752ff23da99 100644 --- a/experiment/src/org/labkey/experiment/controllers/property/PropertyController.java +++ b/experiment/src/org/labkey/experiment/controllers/property/PropertyController.java @@ -1481,18 +1481,17 @@ public void export(InferForm inferForm, HttpServletResponse response, BindExcept // Note: caller must close writer private String getDataFromFile(Writer writer) throws IOException { - HttpServletRequest basicRequest = getViewContext().getRequest(); - - if (! (basicRequest instanceof MultipartHttpServletRequest request)) + Map fileMap = getFileMap(); + if (fileMap.isEmpty()) { error(writer, "No file uploaded"); return null; } //noinspection unchecked - Iterator nameIterator = request.getFileNames(); + Iterator nameIterator = fileMap.keySet().iterator(); String formElementName = nameIterator.next(); - MultipartFile file = request.getFile(formElementName); + MultipartFile file = fileMap.get(formElementName); String filename = file.getOriginalFilename(); int dotIndex = filename.lastIndexOf("."); if (dotIndex < 0) @@ -1537,7 +1536,7 @@ private String getDataFromFile(Writer writer) throws IOException } catch (IOException ioe) { - ExceptionUtil.logExceptionToMothership(request, ioe); + ExceptionUtil.logExceptionToMothership(getViewContext().getRequest(), ioe); error(writer, ioe.getMessage()); return null; } diff --git a/experiment/src/org/labkey/experiment/experimentRunQueryHeader.jsp b/experiment/src/org/labkey/experiment/experimentRunQueryHeader.jsp index a58220ce4e3..eccfa7725b9 100644 --- a/experiment/src/org/labkey/experiment/experimentRunQueryHeader.jsp +++ b/experiment/src/org/labkey/experiment/experimentRunQueryHeader.jsp @@ -33,7 +33,7 @@ { if (!"experimentRunFilter".equals(params.getKey())) { %> - + <% } } %>

diff --git a/pipeline/package-lock.json b/pipeline/package-lock.json index 8dc000200d3..f89e4de58bb 100644 --- a/pipeline/package-lock.json +++ b/pipeline/package-lock.json @@ -8,7 +8,7 @@ "name": "pipeline", "version": "0.0.0", "dependencies": { - "@labkey/components": "7.23.5" + "@labkey/components": "7.25.1-fb-encodeFormName.0" }, "devDependencies": { "@labkey/build": "9.0.0", @@ -2882,9 +2882,9 @@ } }, "node_modules/@labkey/api": { - "version": "1.49.1", - "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/api/-/@labkey/api-1.49.1.tgz", - "integrity": "sha512-ClFIyggEDH4PC+HB4tnZpaOfIls4MgJugS4TmE6Y5xmVzBm8L442aF/gJFMqcZQ1MMNTP7swRHbfvSvJN5Cmyw==", + "version": "1.49.2-fb-encodeFormName.0", + "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/api/-/@labkey/api-1.49.2-fb-encodeFormName.0.tgz", + "integrity": "sha512-QEghEbSY+c+GbZc4vF98zyvaWRHgW/R6mt38skV3ZcdysIY1ZONnfCKR696pC+klgGKfus/POGLUDHQ58AOnEA==", "license": "Apache-2.0" }, "node_modules/@labkey/build": { @@ -2925,13 +2925,13 @@ } }, "node_modules/@labkey/components": { - "version": "7.23.5", - "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/components/-/@labkey/components-7.23.5.tgz", - "integrity": "sha512-JABXXE84xShDhlENS8mEAp8BBnbLv9gmb05SVsJiq7tRnQZzSY1/pFfyGRY7m2fEWsxf6j4wDzlpH5odig8exg==", + "version": "7.25.1-fb-encodeFormName.0", + "resolved": "https://labkey.jfrog.io/artifactory/api/npm/libs-client/@labkey/components/-/@labkey/components-7.25.1-fb-encodeFormName.0.tgz", + "integrity": "sha512-hHUbeW9nXlQNXBGmoJzsYTQrzf52c0ldXjNCVVIrwjh1ShHXgrnRvQMWLPnMjtQirgu7GulKT9fmMqtmi+cEAA==", "license": "SEE LICENSE IN LICENSE.txt", "dependencies": { "@hello-pangea/dnd": "18.0.1", - "@labkey/api": "1.49.1", + "@labkey/api": "1.49.2-fb-encodeFormName.0", "@testing-library/dom": "~10.4.1", "@testing-library/jest-dom": "~6.9.1", "@testing-library/react": "~16.3.2", diff --git a/pipeline/package.json b/pipeline/package.json index 67420d9255f..051cb15de31 100644 --- a/pipeline/package.json +++ b/pipeline/package.json @@ -14,7 +14,7 @@ "build-prod": "npm run clean && cross-env NODE_ENV=production PROD_SOURCE_MAP=source-map webpack --config node_modules/@labkey/build/webpack/prod.config.js --color --progress --profile" }, "dependencies": { - "@labkey/components": "7.23.5" + "@labkey/components": "7.25.1-fb-encodeFormName.0" }, "devDependencies": { "@labkey/build": "9.0.0", diff --git a/query/src/org/labkey/query/controllers/QueryController.java b/query/src/org/labkey/query/controllers/QueryController.java index 5c9c92f86aa..14b4cfa9bce 100644 --- a/query/src/org/labkey/query/controllers/QueryController.java +++ b/query/src/org/labkey/query/controllers/QueryController.java @@ -141,7 +141,6 @@ import org.labkey.api.data.dialect.SqlDialect; import org.labkey.api.dataiterator.DataIteratorBuilder; import org.labkey.api.dataiterator.DataIteratorContext; -import org.labkey.api.dataiterator.DataIteratorUtil; import org.labkey.api.dataiterator.DetailedAuditLogDataIterator; import org.labkey.api.dataiterator.ListofMapsDataIterator; import org.labkey.api.exceptions.OptimisticConflictException; @@ -4653,7 +4652,7 @@ protected JSONObject executeJson(JSONObject json, CommandType commandType, boole LOG.error("Row contained conflicting casing for key names in the incoming row: {}", jsonObj); } if (allowRowAttachments()) - addRowAttachments(table, rowMap, idx, commandIndex); + addRowAttachments(rowMap, idx, commandIndex); rowsToProcess.add(rowMap); rowsAffected++; @@ -4817,7 +4816,7 @@ protected boolean allowRowAttachments() return false; } - private void addRowAttachments(TableInfo tableInfo, Map rowMap, int rowIndex, @Nullable Integer commandIndex) + private void addRowAttachments(Map rowMap, int rowIndex, @Nullable Integer commandIndex) { if (getFileMap() != null) { @@ -4861,9 +4860,6 @@ private void addRowAttachments(TableInfo tableInfo, Map rowMap, rowMap.put(fieldKey, file.isEmpty() ? null : file); } } - - for (ColumnInfo col : tableInfo.getColumns()) - DataIteratorUtil.MatchType.multiPartFormData.updateRowMap(col, rowMap); } protected boolean isSuccessOnValidationError() diff --git a/query/src/org/labkey/query/reports/view/reportsWebPartConfig.jsp b/query/src/org/labkey/query/reports/view/reportsWebPartConfig.jsp index eeca9853197..5e46ee09588 100644 --- a/query/src/org/labkey/query/reports/view/reportsWebPartConfig.jsp +++ b/query/src/org/labkey/query/reports/view/reportsWebPartConfig.jsp @@ -106,7 +106,7 @@

<% addHandler("showTabs", "click", "return onShowTabs(this.checked);"); %> - +
Maximum 1,048,576 rows and 16,384 columns.
Maximum 65,536 rows and 256 columns.
/>/> <%=isTroubleshooter ? HtmlString.EMPTY_STRING : diff --git a/core/src/org/labkey/core/admin/existingListValues.jsp b/core/src/org/labkey/core/admin/existingListValues.jsp index fe49ec75110..ccc57304a47 100644 --- a/core/src/org/labkey/core/admin/existingListValues.jsp +++ b/core/src/org/labkey/core/admin/existingListValues.jsp @@ -83,7 +83,7 @@ String inputNameExisting = "existingValue" + num; %>
/>/> <%=isTroubleshooter ? HtmlString.EMPTY_STRING : button("Delete").primary(true).onClick("return deleteExisting(\"" + h(value) + "\");") %>
Show Tabs:<%=helpPopup("Show tabs", "Some reports/charts may be rendered with multiple tabs showing. Select this option to only show the primary one.")%>>>
Visible Report Sections:<%=helpPopup("Show Report sections", @@ -120,7 +120,7 @@
- +