From dfdf2611a13add8da83ff73bab957e022401da4b Mon Sep 17 00:00:00 2001 From: Rajitha Kumara Date: Sun, 7 Apr 2024 20:52:12 +0530 Subject: [PATCH] Fix extension resolving issue when content-disposition unavailable --- .../impl/FileDownloaderServiceProvider.java | 65 +++++++++++++++++-- .../application/mgt/core/util/Constants.java | 10 +++ 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/impl/FileDownloaderServiceProvider.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/impl/FileDownloaderServiceProvider.java index d63a297956..f8fe6f2f94 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/impl/FileDownloaderServiceProvider.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/impl/FileDownloaderServiceProvider.java @@ -27,6 +27,7 @@ import io.entgra.device.mgt.core.application.mgt.common.exception.FileTransferSe import io.entgra.device.mgt.core.application.mgt.common.services.FileDownloaderService; import io.entgra.device.mgt.core.application.mgt.common.services.FileTransferService; import io.entgra.device.mgt.core.application.mgt.core.internal.DataHolder; +import io.entgra.device.mgt.core.application.mgt.core.util.Constants; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; @@ -112,10 +113,17 @@ public class FileDownloaderServiceProvider { } String contentDisposition = response.header("Content-Disposition"); String contentType = response.header("Content-Type"); - String[] fileNameSegments = getFileNameSegments(contentDisposition, contentType); + String[] fileNameSegments = extractFileNameSegmentsFromUrl(downloadUrl); + + // if the url parsing failed to resolve the file name segments + // falling to remote file name segment resolving + if (fileNameSegments == null) { + fileNameSegments = getFileNameSegments(contentDisposition, contentType); + } + FileMetaEntry fileMetaEntry = new FileMetaEntry(); fileMetaEntry.setSize(Long.parseLong(Objects.requireNonNull(response.header("Content-Length")))); - fileMetaEntry.setFileName(fileNameSegments[0] + "-" + UUID.randomUUID()); + fileMetaEntry.setFileName(fileNameSegments[0]); fileMetaEntry.setExtension(fileNameSegments[1]); return fileMetaEntry; } catch (IOException e) { @@ -123,6 +131,38 @@ public class FileDownloaderServiceProvider { } } + /** + * Extracting file name segments by parsing the URL + * @param url Remote URL to extract file name segments + * @return Array containing file name segments or null when failed to extract + */ + public static String[] extractFileNameSegmentsFromUrl(URL url) { + if (url == null) { + if (log.isDebugEnabled()) { + log.debug("Null received as the remote URL"); + } + return null; + } + + String []urlSegments = url.toString().split("/"); + if (urlSegments.length < 1) { + if (log.isDebugEnabled()) { + log.debug("Cannot determine the file name for the remote file"); + } + return null; + } + + String fullQualifiedName = urlSegments[urlSegments.length - 1]; + String []fileNameSegments = fullQualifiedName.split("\\.(?=[^.]+$)"); + if (fileNameSegments.length != 2) { + if (log.isDebugEnabled()) { + log.debug("Error encountered when constructing file name"); + } + return null; + } + return fileNameSegments; + } + /** * Extract file name segments(filename & extensions) from content disposition header and content type header * @param contentDisposition Content disposition header value @@ -136,11 +176,24 @@ public class FileDownloaderServiceProvider { } if (contentDisposition == null) { - String []contentTypeSegments = contentType.split("/"); - if (contentTypeSegments.length != 2) { - throw new FileDownloaderServiceException("Encountered wrong content type header value"); + String extension; + if (contentType.equals(Constants.MIME_TYPE_VND_ANDROID_PACKAGE_ARCHIVE)) { + extension = Constants.EXTENSION_APK; + } else if (contentType.equals(Constants.MIME_TYPE_OCTET_STREAM)) { + extension = Constants.EXTENSION_IPA; + } else if (contentType.equals(Constants.MIME_TYPE_VND_APPX)) { + extension = Constants.EXTENSION_APPX; + } else if (contentType.equals(Constants.MIME_TYPE_X_MS_INSTALLER) + || contentType.equals(Constants.MIME_TYPE_VND_MS_WINDOWS_MSI)) { + extension = Constants.EXTENSION_MSI; + } else { + String []contentTypeSegments = contentType.split("/"); + if (contentTypeSegments.length != 2) { + throw new FileDownloaderServiceException("Encountered wrong content type header value"); + } + extension = contentTypeSegments[contentTypeSegments.length - 1]; } - return new String[]{ UUID.randomUUID().toString(), contentTypeSegments[contentTypeSegments.length - 1]}; + return new String[]{ UUID.randomUUID().toString(), extension}; } String []contentDispositionSegments = contentDisposition.split("="); diff --git a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/Constants.java b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/Constants.java index b96fd66058..b5b5fd5154 100644 --- a/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/Constants.java +++ b/components/application-mgt/io.entgra.device.mgt.core.application.mgt.core/src/main/java/io/entgra/device/mgt/core/application/mgt/core/util/Constants.java @@ -220,4 +220,14 @@ public class Constants { */ public static final int MAX_APP_NAME_CHARACTERS = 350; public static final String APP_NAME_REGEX = "[^a-zA-Z0-9.\\s-]"; + + public static final String EXTENSION_APK = ".apk"; + public static final String EXTENSION_IPA = ".ipa"; + public static final String EXTENSION_MSI = ".msi"; + public static final String EXTENSION_APPX = ".appx"; + public static final String MIME_TYPE_OCTET_STREAM = "application/octet-stream"; + public static final String MIME_TYPE_VND_ANDROID_PACKAGE_ARCHIVE = "application/vnd.android.package-archive"; + public static final String MIME_TYPE_VND_MS_WINDOWS_MSI = "application/vnd.ms-windows.msi"; + public static final String MIME_TYPE_X_MS_INSTALLER = "application/x-ms-installer"; + public static final String MIME_TYPE_VND_APPX = "application/vnd.appx"; }