-
Notifications
You must be signed in to change notification settings - Fork 7
Issue 52827: File/attachment fields with special characters #6580
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b2cd8f3
073a1e6
464b9b0
125329c
a902964
7f1ea44
559e794
5d32ba4
7407311
e9e8e29
666e3ff
c3405af
7453203
a4b71df
89f25aa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -67,6 +67,7 @@ | |
| 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; | ||
|
|
@@ -4491,7 +4492,7 @@ protected JSONObject executeJson(JSONObject json, CommandType commandType, boole | |
| // Use shallow copy since jsonObj.toMap() will translate contained JSONObjects into Maps, which we don't want | ||
| JsonUtil.fillMapShallow(jsonObj, rowMap); | ||
| if (allowRowAttachments()) | ||
| addRowAttachments(rowMap, idx, commandIndex); | ||
| addRowAttachments(table, rowMap, idx, commandIndex); | ||
|
|
||
| rowsToProcess.add(rowMap); | ||
| rowsAffected++; | ||
|
|
@@ -4643,34 +4644,42 @@ protected boolean allowRowAttachments() | |
| return false; | ||
| } | ||
|
|
||
| private void addRowAttachments(Map<String, Object> rowMap, int rowIndex, @Nullable Integer commandIndex) | ||
| private void addRowAttachments(TableInfo tableInfo, Map<String, Object> rowMap, int rowIndex, @Nullable Integer commandIndex) | ||
| { | ||
| if (getFileMap() != null) | ||
| { | ||
| for (Map.Entry<String, MultipartFile> fileEntry : getFileMap().entrySet()) | ||
| { | ||
| // Allow for the fileMap key to include the row index, and optionally command index, for defining | ||
| // which row to attach this file to | ||
| String fieldKey = fileEntry.getKey(); | ||
| int delimIndex = fieldKey.lastIndexOf(ROW_ATTACHMENT_INDEX_DELIM); | ||
| if (delimIndex > -1) | ||
| String fullKey = fileEntry.getKey(); | ||
| String fieldKey = fullKey; | ||
| // Issue 52827: Cannot attach a file if the field name contains :: | ||
| // use lastIndexOf instead of split to get the proper parts | ||
| int lastDelimIndex = fullKey.lastIndexOf(ROW_ATTACHMENT_INDEX_DELIM); | ||
| if (lastDelimIndex > -1) | ||
| { | ||
| String[] parts = fileEntry.getKey().split(ROW_ATTACHMENT_INDEX_DELIM); | ||
| String fieldKeyExcludeIndex = fullKey.substring(0, lastDelimIndex); | ||
| String fieldRowIndex = fullKey.substring(lastDelimIndex + ROW_ATTACHMENT_INDEX_DELIM.length()); | ||
| if (!fieldRowIndex.equals(rowIndex+"")) continue; | ||
|
|
||
| if (commandIndex == null) | ||
| { | ||
| // Single command, so we're parsing file names in the format of: FileField::0 | ||
| fieldKey = parts[0]; | ||
| String fieldRowIndex = parts[1]; | ||
| if (!fieldRowIndex.equals(rowIndex+"")) continue; | ||
| fieldKey = fieldKeyExcludeIndex; | ||
| } | ||
| else | ||
| { | ||
| // Multi-command, so we're parsing file names in the format of: FileField::0::1 | ||
| fieldKey = parts[0]; | ||
| String fieldCommandIndex = parts[1]; | ||
| String fieldRowIndex = parts[2]; | ||
| if (!fieldCommandIndex.equals(commandIndex+"") || !fieldRowIndex.equals(rowIndex+"")) | ||
| int subDelimIndex = fieldKeyExcludeIndex.lastIndexOf(ROW_ATTACHMENT_INDEX_DELIM); | ||
| if (subDelimIndex > -1) | ||
| { | ||
| fieldKey = fieldKeyExcludeIndex.substring(0, subDelimIndex); | ||
| String fieldCommandIndex = fieldKeyExcludeIndex.substring(subDelimIndex + ROW_ATTACHMENT_INDEX_DELIM.length()); | ||
| if (!fieldCommandIndex.equals(commandIndex+"")) | ||
| continue; | ||
| } | ||
| else | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the correct fix is to remove the encoded characters here (early) rather than trying to match them later. Ideally the encoded chars shouldn't "leak" out of code that is pulling values out of the request object. Then we wouldn't have to handle these characters later.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The challenge here is that a field might actually contain "%22". Both field" and field%22 will come in as field%22 and we don't know when to decode vs not here.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤯
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is really an HTTP bug (it's not OK to escape " to %22 without escaping %). So this would break any column with " in its name in a type with a file column then. Not just the file column. Since these columns could never map to a java property. I'd propose changing BaseColumnInfo.getPropertyName() to replace " with %QUOTE% or something. That should solve the problem by never using the " in the input name. That would fix the dataregion case, anyway. I'm not sure what the editable grid does.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Editable grid in apps currently doesn't support file fields. The paths supported in Apps are editing detail editing and bulk ediitng. Detail editing uses |
||
| continue; | ||
| } | ||
| } | ||
|
|
@@ -4679,6 +4688,9 @@ private void addRowAttachments(Map<String, Object> rowMap, int rowIndex, @Nullab | |
| rowMap.put(fieldKey, file.isEmpty() ? null : file); | ||
| } | ||
| } | ||
|
|
||
| for (ColumnInfo col : tableInfo.getColumns()) | ||
| DataIteratorUtil.MatchType.multiPartFormData.updateRowMap(col, rowMap); | ||
| } | ||
|
|
||
| protected boolean isSuccessOnValidationError() | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems like a lot of duplicate code from what is already there below for handling the non-slash column name case (lines 599-607). it seems like the main part is the field name to use in
request.getFile(). Could these blocks of code be collapsed and have the conditional part be using either getMultiPartFormFieldName or getFormFieldName? Then after we have the MultipartFile, the rest of the code seems pretty similar.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was how it was written in a previous commit, but that broke LKS attachment update. The different part is what value to use for file field: string or File. The only shared code is the following 2 lines so I removed the shared util in the last commit.
MultipartHttpServletRequest request = (MultipartHttpServletRequest) getRequest(); MultipartFile f = request.getFile(quoteEncodedFieldName);