|
34 | 34 | import static edu.harvard.iq.dataverse.datasetutility.FileSizeChecker.bytesToHumanReadable; |
35 | 35 | import edu.harvard.iq.dataverse.ingest.IngestReport; |
36 | 36 | import edu.harvard.iq.dataverse.ingest.IngestServiceBean; |
37 | | -import edu.harvard.iq.dataverse.ingest.IngestServiceShapefileHelper; |
38 | 37 | import edu.harvard.iq.dataverse.ingest.IngestableDataChecker; |
39 | 38 | import edu.harvard.iq.dataverse.license.License; |
40 | 39 | import edu.harvard.iq.dataverse.settings.ConfigCheckService; |
41 | 40 | import edu.harvard.iq.dataverse.settings.JvmSettings; |
42 | 41 | import edu.harvard.iq.dataverse.util.file.BagItFileHandler; |
43 | | -import edu.harvard.iq.dataverse.util.file.CreateDataFileResult; |
44 | 42 | import edu.harvard.iq.dataverse.util.file.BagItFileHandlerFactory; |
45 | 43 | import edu.harvard.iq.dataverse.util.xml.XmlUtil; |
46 | 44 | import edu.harvard.iq.dataverse.util.xml.html.HtmlFormatUtil; |
|
54 | 52 | import static edu.harvard.iq.dataverse.util.xml.html.HtmlFormatUtil.formatTableCellAlignRight; |
55 | 53 | import static edu.harvard.iq.dataverse.util.xml.html.HtmlFormatUtil.formatTableRow; |
56 | 54 |
|
| 55 | +import java.awt.image.BufferedImage; |
57 | 56 | import java.io.BufferedInputStream; |
58 | 57 | import java.io.File; |
59 | 58 | import java.io.FileInputStream; |
|
64 | 63 | import java.io.InputStream; |
65 | 64 | import java.io.OutputStream; |
66 | 65 | import java.nio.ByteBuffer; |
67 | | -import java.nio.charset.Charset; |
68 | 66 | import java.nio.file.Files; |
69 | 67 | import java.nio.file.Path; |
70 | 68 | import java.nio.file.Paths; |
|
82 | 80 | import java.util.HashMap; |
83 | 81 | import java.util.List; |
84 | 82 | import java.util.Optional; |
85 | | -import java.util.ResourceBundle; |
| 83 | +import java.util.Set; |
86 | 84 | import java.util.UUID; |
87 | 85 | import java.util.logging.Level; |
88 | 86 | import java.util.logging.Logger; |
|
92 | 90 | import jakarta.json.JsonArray; |
93 | 91 | import jakarta.json.JsonObject; |
94 | 92 |
|
| 93 | +import javax.imageio.ImageIO; |
95 | 94 | import javax.xml.stream.XMLInputFactory; |
96 | 95 | import javax.xml.stream.XMLStreamConstants; |
97 | 96 | import javax.xml.stream.XMLStreamException; |
|
106 | 105 | import edu.harvard.iq.dataverse.util.file.FileExceedsStorageQuotaException; |
107 | 106 | import java.nio.charset.StandardCharsets; |
108 | 107 | import java.util.Arrays; |
109 | | -import org.apache.commons.io.IOUtils; |
110 | 108 | import org.apache.commons.lang3.StringUtils; |
111 | 109 | import org.apache.tika.Tika; |
| 110 | +import org.primefaces.model.file.UploadedFile; |
| 111 | + |
112 | 112 | import ucar.nc2.NetcdfFile; |
113 | 113 | import ucar.nc2.NetcdfFiles; |
114 | 114 |
|
@@ -1900,5 +1900,63 @@ public static String decodeFileName(String originalFileName) { |
1900 | 1900 | } |
1901 | 1901 | return new String(originalFileName.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); |
1902 | 1902 | } |
| 1903 | + |
| 1904 | + /** |
| 1905 | + * Verifies that an uploaded file is a valid png or jpg image file. Performs both MIME type checking and content validation. |
| 1906 | + * |
| 1907 | + * Note: This is similar to the isFileOfImageType which is used for collection feature items. This method works with PrimeFaces UploadedFile vs File, limits to jpg and png (as the UI states), uses |
| 1908 | + * ImageIO to read the content, and checks size (as the caller of isFileOfImageType does). It avoids using Tika in the core (as we once tried to do) and is potentially slower but more thorough as it |
| 1909 | + * will confirm the image is not corrupt. Work could be done to merge the two use cases. |
| 1910 | + * |
| 1911 | + * @param uploadedFile |
| 1912 | + * the file to verify |
| 1913 | + * @param maxSize |
| 1914 | + * maximum allowed file size in bytes |
| 1915 | + */ |
| 1916 | + public static boolean isUploadedFileAnImage(UploadedFile uploadedFile, long maxSize) { |
| 1917 | + if (uploadedFile == null) { |
| 1918 | + return false; |
| 1919 | + } |
| 1920 | + |
| 1921 | + // Pre-filter: Check MIME type first (fast rejection) |
| 1922 | + String contentType = uploadedFile.getContentType(); |
| 1923 | + if (contentType == null || !contentType.startsWith("image/")) { |
| 1924 | + return false; |
| 1925 | + } |
| 1926 | + |
| 1927 | + // Check against allowed MIME types |
| 1928 | + Set<String> allowedMimeTypes = Set.of( |
| 1929 | + "image/jpeg", |
| 1930 | + "image/jpg", |
| 1931 | + "image/png"); |
| 1932 | + |
| 1933 | + if (!allowedMimeTypes.contains(contentType.toLowerCase())) { |
| 1934 | + return false; |
| 1935 | + } |
| 1936 | + |
| 1937 | + // Validate actual image content (security check) |
| 1938 | + try (InputStream inputStream = uploadedFile.getInputStream()) { |
| 1939 | + BufferedImage image = ImageIO.read(inputStream); |
| 1940 | + if (image == null) { |
| 1941 | + return false; |
| 1942 | + } |
| 1943 | + |
| 1944 | + // Optional: Check file size limit (similar to DataverseFeaturedItemServiceBean) |
| 1945 | + |
| 1946 | + if (uploadedFile.getSize() > maxSize) { |
| 1947 | + return false; |
| 1948 | + } |
| 1949 | + |
| 1950 | + // Optional: Check image dimensions if needed |
| 1951 | + int width = image.getWidth(); |
| 1952 | + int height = image.getHeight(); |
| 1953 | + logger.fine("Uploaded image dimensions: " + width + "x" + height); |
| 1954 | + |
| 1955 | + } catch (IOException e) { |
| 1956 | + logger.log(Level.WARNING, "Error reading uploaded image file", e); |
| 1957 | + return false; |
| 1958 | + } |
| 1959 | + return true; |
| 1960 | + } |
1903 | 1961 |
|
1904 | 1962 | } |
0 commit comments