From e5c788aaa20052d15f066fa73ab213c231ef30b7 Mon Sep 17 00:00:00 2001 From: tylerjmchugh Date: Mon, 28 Oct 2024 13:02:24 -0400 Subject: [PATCH 1/7] Update spring doc consumes and produces --- .../fao/geonet/api/records/attachments/AttachmentsApi.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/services/src/main/java/org/fao/geonet/api/records/attachments/AttachmentsApi.java b/services/src/main/java/org/fao/geonet/api/records/attachments/AttachmentsApi.java index e30deec309a..3e92fbfc181 100644 --- a/services/src/main/java/org/fao/geonet/api/records/attachments/AttachmentsApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/attachments/AttachmentsApi.java @@ -200,7 +200,7 @@ public void delResources( @io.swagger.v3.oas.annotations.Operation(summary = "Create a new resource for a given metadata") @PreAuthorize("hasAuthority('Editor')") @RequestMapping(method = RequestMethod.POST, - consumes = MediaType.ALL_VALUE, + consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseStatus(value = HttpStatus.CREATED) @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Attachment uploaded."), @@ -228,7 +228,9 @@ public MetadataResource putResource( @io.swagger.v3.oas.annotations.Operation(summary = "Create a new resource from a URL for a given metadata") @PreAuthorize("hasAuthority('Editor')") - @RequestMapping(method = RequestMethod.PUT) + @RequestMapping(method = RequestMethod.PUT, + consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE) @ResponseStatus(value = HttpStatus.CREATED) @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Attachment added."), @ApiResponse(responseCode = "403", description = ApiParams.API_RESPONSE_NOT_ALLOWED_CAN_EDIT)}) From cabdf0168c90aea78a71aaec340da515702e58d2 Mon Sep 17 00:00:00 2001 From: tylerjmchugh Date: Mon, 28 Oct 2024 13:03:51 -0400 Subject: [PATCH 2/7] Update putResource logic to get filename from contentDisposition header before using url --- .../records/attachments/AbstractStore.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/fao/geonet/api/records/attachments/AbstractStore.java b/core/src/main/java/org/fao/geonet/api/records/attachments/AbstractStore.java index 168e4e2a63c..43d4be81eb0 100644 --- a/core/src/main/java/org/fao/geonet/api/records/attachments/AbstractStore.java +++ b/core/src/main/java/org/fao/geonet/api/records/attachments/AbstractStore.java @@ -39,7 +39,9 @@ import org.springframework.web.multipart.MultipartFile; import java.io.BufferedInputStream; +import java.io.IOException; import java.io.InputStream; +import java.net.HttpURLConnection; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; @@ -152,6 +154,22 @@ protected int canDownload(ServiceContext context, String metadataUuid, MetadataR return metadataId; } + protected String getFilenameFromHeader(final URL fileUrl) throws IOException { + HttpURLConnection connection = (HttpURLConnection) fileUrl.openConnection(); + try { + connection.setRequestMethod("HEAD"); + connection.connect(); + String contentDisposition = connection.getHeaderField("Content-Disposition"); + + if (contentDisposition != null && contentDisposition.contains("filename=")) { + return contentDisposition.split("filename=")[1].replace("\"", ""); + } + return null; + } finally { + connection.disconnect(); + } + } + protected String getFilenameFromUrl(final URL fileUrl) { String fileName = FilenameUtils.getName(fileUrl.getPath()); if (fileName.contains("?")) { @@ -198,7 +216,11 @@ public final MetadataResource putResource(ServiceContext context, String metadat @Override public final MetadataResource putResource(ServiceContext context, String metadataUuid, URL fileUrl, MetadataResourceVisibility visibility, Boolean approved) throws Exception { - return putResource(context, metadataUuid, getFilenameFromUrl(fileUrl), fileUrl.openStream(), null, visibility, approved); + String filename = getFilenameFromHeader(fileUrl); + if (filename == null) { + filename = getFilenameFromUrl(fileUrl); + } + return putResource(context, metadataUuid, filename, fileUrl.openStream(), null, visibility, approved); } @Override From 49af24534d997b7ca111799240cdf467c793a3f6 Mon Sep 17 00:00:00 2001 From: tylerjmchugh Date: Mon, 28 Oct 2024 13:58:38 -0400 Subject: [PATCH 3/7] retrigger checks From 7794d7663ee3a14a479e57052a41601c3ce498e7 Mon Sep 17 00:00:00 2001 From: tylerjmchugh Date: Mon, 28 Oct 2024 14:29:45 -0400 Subject: [PATCH 4/7] retrigger checks From e040fab62c9c4a6ec9da935f8bfc73b7ea342b75 Mon Sep 17 00:00:00 2001 From: tylerjmchugh Date: Mon, 28 Oct 2024 14:45:55 -0400 Subject: [PATCH 5/7] Remove incorrect consumes --- .../org/fao/geonet/api/records/attachments/AttachmentsApi.java | 1 - 1 file changed, 1 deletion(-) diff --git a/services/src/main/java/org/fao/geonet/api/records/attachments/AttachmentsApi.java b/services/src/main/java/org/fao/geonet/api/records/attachments/AttachmentsApi.java index 3e92fbfc181..15da0b03d9c 100644 --- a/services/src/main/java/org/fao/geonet/api/records/attachments/AttachmentsApi.java +++ b/services/src/main/java/org/fao/geonet/api/records/attachments/AttachmentsApi.java @@ -229,7 +229,6 @@ public MetadataResource putResource( @io.swagger.v3.oas.annotations.Operation(summary = "Create a new resource from a URL for a given metadata") @PreAuthorize("hasAuthority('Editor')") @RequestMapping(method = RequestMethod.PUT, - consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseStatus(value = HttpStatus.CREATED) @ApiResponses(value = {@ApiResponse(responseCode = "201", description = "Attachment added."), From 702b3ae671ed844c453ce065e52e970eee120e5e Mon Sep 17 00:00:00 2001 From: tylerjmchugh Date: Wed, 30 Oct 2024 10:38:49 -0400 Subject: [PATCH 6/7] Update getFilenameFromHeader to return null on exception --- .../geonet/api/records/attachments/AbstractStore.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/fao/geonet/api/records/attachments/AbstractStore.java b/core/src/main/java/org/fao/geonet/api/records/attachments/AbstractStore.java index 43d4be81eb0..f0cf527face 100644 --- a/core/src/main/java/org/fao/geonet/api/records/attachments/AbstractStore.java +++ b/core/src/main/java/org/fao/geonet/api/records/attachments/AbstractStore.java @@ -35,6 +35,8 @@ import org.fao.geonet.kernel.AccessManager; import org.fao.geonet.kernel.datamanager.IMetadataUtils; import org.fao.geonet.repository.MetadataRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; import org.springframework.web.multipart.MultipartFile; @@ -55,6 +57,7 @@ public abstract class AbstractStore implements Store { protected static final String RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_SEPARATOR = ":"; protected static final String RESOURCE_MANAGEMENT_EXTERNAL_PROPERTIES_ESCAPED_SEPARATOR = "\\:"; + private static final Logger log = LoggerFactory.getLogger(AbstractStore.class); @Override public final List getResources(final ServiceContext context, final String metadataUuid, final Sort sort, @@ -162,9 +165,13 @@ protected String getFilenameFromHeader(final URL fileUrl) throws IOException { String contentDisposition = connection.getHeaderField("Content-Disposition"); if (contentDisposition != null && contentDisposition.contains("filename=")) { - return contentDisposition.split("filename=")[1].replace("\"", ""); + String filename = contentDisposition.split("filename=")[1].replace("\"", "").trim(); + return filename.isEmpty() ? null : filename; } return null; + } catch (Exception e) { + log.error("Error retrieving resource filename from header", e); + return null; } finally { connection.disconnect(); } From 77d5621e9b17871fd8e0b200e7c069a502961a14 Mon Sep 17 00:00:00 2001 From: tylerjmchugh Date: Fri, 8 Nov 2024 10:52:42 -0500 Subject: [PATCH 7/7] Update getFilenameFromHeader to return null on exception (including fileUrl.openConnection) --- .../fao/geonet/api/records/attachments/AbstractStore.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/fao/geonet/api/records/attachments/AbstractStore.java b/core/src/main/java/org/fao/geonet/api/records/attachments/AbstractStore.java index f0cf527face..0ccb8a13095 100644 --- a/core/src/main/java/org/fao/geonet/api/records/attachments/AbstractStore.java +++ b/core/src/main/java/org/fao/geonet/api/records/attachments/AbstractStore.java @@ -158,8 +158,9 @@ protected int canDownload(ServiceContext context, String metadataUuid, MetadataR } protected String getFilenameFromHeader(final URL fileUrl) throws IOException { - HttpURLConnection connection = (HttpURLConnection) fileUrl.openConnection(); + HttpURLConnection connection = null; try { + connection = (HttpURLConnection) fileUrl.openConnection(); connection.setRequestMethod("HEAD"); connection.connect(); String contentDisposition = connection.getHeaderField("Content-Disposition"); @@ -173,7 +174,9 @@ protected String getFilenameFromHeader(final URL fileUrl) throws IOException { log.error("Error retrieving resource filename from header", e); return null; } finally { - connection.disconnect(); + if (connection != null) { + connection.disconnect(); + } } }