diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..2a29b1e4 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,13 @@ +version: 2 +updates: + # Maven/Java library updates + - package-ecosystem: "maven" + directory: "/" + schedule: + interval: "daily" + open-pull-requests-limit: 10 + # GitHub actions updates + - package-ecosystem: "github-actions" + directory: "/.github/workflows" + schedule: + interval: "daily" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2457eded..c366d4d6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,12 @@ name: CI -on: [ push, pull_request ] +on: + push: + branches: + - '**' + - '!dependabot/**' + pull_request: + branches: [ 'master' ] permissions: read-all @@ -11,22 +17,22 @@ jobs: fail-fast: false matrix: os: [ ubuntu-latest, windows-latest, macos-latest ] - java: [ 8, 11, 17, 18 ] + java: [ 8, 11, 17, 20 ] runs-on: ${{ matrix.os }} permissions: checks: write steps: - - uses: actions/checkout@v3 - - uses: actions/setup-java@v3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 with: distribution: 'temurin' java-version: ${{ matrix.java }} java-package: jdk cache: 'maven' - name: Run Tests - run: mvn --no-transfer-progress test + run: mvn --batch-mode --no-transfer-progress test - name: Publish Test Report - uses: mikepenz/action-junit-report@v3 + uses: mikepenz/action-junit-report@c0e4b81aaa0067314a2d0d06e19b512c9d8af4f5 # v3.7.7 if: ${{ !cancelled() }} with: report_paths: "**/target/surefire-reports/TEST*.xml" @@ -41,11 +47,11 @@ jobs: matrix: kcms: [ true, false ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - run: | download_url="https://javadl.oracle.com/webapps/download/AutoDL?BundleId=245038_d3c52aa6bfa54d3ca74e617f18309292" wget -O $RUNNER_TEMP/java_package.tar.gz $download_url - - uses: actions/setup-java@v3 + - uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 with: distribution: 'jdkfile' jdkFile: ${{ runner.temp }}/java_package.tar.gz @@ -58,9 +64,9 @@ jobs: - name: Display Java version run: java -version - name: Run Tests - run: mvn --no-transfer-progress test + run: mvn --batch-mode --no-transfer-progress test - name: Publish Test Report - uses: mikepenz/action-junit-report@v3 + uses: mikepenz/action-junit-report@c0e4b81aaa0067314a2d0d06e19b512c9d8af4f5 # v3.7.7 if: ${{ !cancelled() }} with: report_paths: "**/target/surefire-reports/TEST*.xml" @@ -72,9 +78,9 @@ jobs: if: github.ref == 'refs/heads/master' # only perform on latest master runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - name: Set up Maven Central - uses: actions/setup-java@v3 + uses: actions/setup-java@5ffc13f4174014e2d4d4572b3d74c3fa61aeb2c2 # v3.11.0 with: # running setup-java again overwrites the settings.xml distribution: 'temurin' java-version: '8' @@ -86,11 +92,11 @@ jobs: gpg-passphrase: MAVEN_CENTRAL_GPG_PASSPHRASE # env variable for GPG private key passphrase (3) - name: Get Project Version run: | - echo "PROJECT_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV + echo "PROJECT_VERSION=$(mvn --batch-mode help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV - name: Publish to Maven Central if: ${{ endsWith(env.PROJECT_VERSION, '-SNAPSHOT') }} - run: mvn deploy -P release -DskipTests + run: mvn --batch-mode --no-transfer-progress deploy -P release -DskipTests env: MAVEN_CENTRAL_USERNAME: ${{ secrets.SONATYPE_USERNAME }} # must be the same env variable name as (1) MAVEN_CENTRAL_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} # must be the same env variable name as (2) - MAVEN_CENTRAL_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} # must be the same env variable name as (3) \ No newline at end of file + MAVEN_CENTRAL_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} # must be the same env variable name as (3) diff --git a/README.md b/README.md index 1d286d77..86b1414a 100644 --- a/README.md +++ b/README.md @@ -382,7 +382,7 @@ Other "fat" JAR bundlers will probably have similar mechanisms to merge entries ##### Latest version (3.9.4) -Requires Java 7 or later. +The latest version that will run on Java 7 is 3.9.4. Later versions will require Java 8 or later. Common dependencies * [common-lang-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.9.4/common-lang-3.9.4.jar) @@ -419,37 +419,6 @@ Photoshop Path support for ImageIO Servlet support * [servlet-3.9.4.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.9.4/servlet-3.9.4.jar) -##### Old version (3.0.x) - -Use this version for projects that requires Java 6 or need the JMagick support. *Does not support Java 8 or later*. - -Common dependencies -* [common-lang-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-lang/3.0.2/common-lang-3.0.2.jar) -* [common-io-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-io/3.0.2/common-io-3.0.2.jar) -* [common-image-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/common/common-image/3.0.2/common-image-3.0.2.jar) - -ImageIO dependencies -* [imageio-core-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-core/3.0.2/imageio-core-3.0.2.jar) -* [imageio-metadata-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-metadata/3.0.2/imageio-metadata-3.0.2.jar) - -ImageIO plugins -* [imageio-jpeg-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jpeg/3.0.2/imageio-jpeg-3.0.2.jar) -* [imageio-tiff-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-tiff/3.0.2/imageio-tiff-3.0.2.jar) -* [imageio-psd-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-psd/3.0.2/imageio-psd-3.0.2.jar) -* [imageio-pict-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-pict/3.0.2/imageio-pict-3.0.2.jar) -* [imageio-iff-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-iff/3.0.2/imageio-iff-3.0.2.jar) -* [imageio-icns-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-icns/3.0.2/imageio-icns-3.0.2.jar) -* [imageio-ico-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-ico/3.0.2/imageio-ico-3.0.2.jar) -* [imageio-thumbsdb-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-thumbsdb/3.0.2/imageio-thumbsdb-3.0.2.jar) - -ImageIO plugins requiring 3rd party libs -* [imageio-batik-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-batik/3.0.2/imageio-batik-3.0.2.jar) -* [imageio-jmagick-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/imageio/imageio-jmagick/3.0.2/imageio-jmagick-3.0.2.jar) - -Servlet support -* [servlet-3.0.2.jar](https://search.maven.org/remotecontent?filepath=com/twelvemonkeys/servlet/servlet/3.0.2/servlet-3.0.2.jar) - - ## License This project is provided under the OSI approved [BSD license](https://opensource.org/licenses/BSD-3-Clause): diff --git a/common/common-lang/src/main/java/com/twelvemonkeys/lang/StringUtil.java b/common/common-lang/src/main/java/com/twelvemonkeys/lang/StringUtil.java index d1f88c93..3a6b1bf0 100755 --- a/common/common-lang/src/main/java/com/twelvemonkeys/lang/StringUtil.java +++ b/common/common-lang/src/main/java/com/twelvemonkeys/lang/StringUtil.java @@ -904,7 +904,7 @@ public final class StringUtil { } catch (ParseException pe) { // Wrap in RuntimeException - throw new IllegalArgumentException(pe.getMessage()); + throw new IllegalArgumentException(pe.getMessage() + " at pos " + pe.getErrorOffset()); } } diff --git a/common/common-lang/src/test/java/com/twelvemonkeys/lang/StringUtilTest.java b/common/common-lang/src/test/java/com/twelvemonkeys/lang/StringUtilTest.java index 923cffd0..c6863961 100644 --- a/common/common-lang/src/test/java/com/twelvemonkeys/lang/StringUtilTest.java +++ b/common/common-lang/src/test/java/com/twelvemonkeys/lang/StringUtilTest.java @@ -593,8 +593,8 @@ public class StringUtilTest { cal.clear(); cal.set(Calendar.HOUR, 1); cal.set(Calendar.MINUTE, 2); - date = StringUtil.toDate("1:02 am", - DateFormat.getTimeInstance(DateFormat.SHORT, Locale.US)); + format = new SimpleDateFormat("HH:mm"); + date = StringUtil.toDate("1:02", format); assertNotNull(date); assertEquals(cal.getTime(), date); } diff --git a/common/pom.xml b/common/pom.xml index 05cb02a4..a6088a44 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -47,7 +47,7 @@ junit junit - 4.13.1 + 4.13.2 test diff --git a/contrib/pom.xml b/contrib/pom.xml index 2ff3522d..b3235671 100644 --- a/contrib/pom.xml +++ b/contrib/pom.xml @@ -65,7 +65,7 @@ junit junit - 4.13.1 + 4.13.2 test diff --git a/imageio/imageio-batik/pom.xml b/imageio/imageio-batik/pom.xml index a452d6c1..e2a8fe93 100644 --- a/imageio/imageio-batik/pom.xml +++ b/imageio/imageio-batik/pom.xml @@ -51,7 +51,7 @@ commons-io commons-io - 2.11.0 + 2.12.0 provided diff --git a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/color/KCMSSanitizerStrategyTest.java b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/color/KCMSSanitizerStrategyTest.java index 3cf80a29..c8b8ae61 100644 --- a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/color/KCMSSanitizerStrategyTest.java +++ b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/color/KCMSSanitizerStrategyTest.java @@ -36,9 +36,11 @@ import java.awt.color.ColorSpace; import java.awt.color.ICC_ColorSpace; import java.awt.color.ICC_Profile; import java.io.IOException; +import java.lang.reflect.Method; import java.util.Arrays; import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assume.assumeFalse; import static org.mockito.Mockito.*; public class KCMSSanitizerStrategyTest { @@ -56,6 +58,8 @@ public class KCMSSanitizerStrategyTest { @Test public void testFixProfileUpdateHeader() throws Exception { + assumeICC_ProfileNotSealed(); // Ignores test for JDK 19+ + byte[] header = new byte[128]; header[ICC_Profile.icHdrRenderingIntent + 3] = 1; ICC_Profile profile = mock(ICC_Profile.class); @@ -69,6 +73,17 @@ public class KCMSSanitizerStrategyTest { verify(profile).setData(eq(ICC_Profile.icSigHead), any(byte[].class)); } + static void assumeICC_ProfileNotSealed() { + try { + Method isSealed = Class.class.getMethod("isSealed"); + Boolean result = (Boolean) isSealed.invoke(ICC_Profile.class); + assumeFalse("Can't mock ICC_Profile, class is sealed (as of JDK 19).", result); + } + catch (ReflectiveOperationException ignore) { + // We can't have sealed classes if we don't have the isSealed method... + } + } + @Test public void testFixProfileCorbisRGB() throws IOException { // TODO: Consider re-writing this using mocks, to avoid dependencies on the CMS implementation diff --git a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/color/LCMSSanitizerStrategyTest.java b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/color/LCMSSanitizerStrategyTest.java index d7b63ea2..cff1acbd 100644 --- a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/color/LCMSSanitizerStrategyTest.java +++ b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/color/LCMSSanitizerStrategyTest.java @@ -34,6 +34,7 @@ import org.junit.Test; import java.awt.color.ICC_Profile; +import static com.twelvemonkeys.imageio.color.KCMSSanitizerStrategyTest.assumeICC_ProfileNotSealed; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -46,6 +47,8 @@ public class LCMSSanitizerStrategyTest { @Test public void testFixProfile() throws Exception { + assumeICC_ProfileNotSealed(); // Ignores test for JDK 19+ + ICC_Profile profile = mock(ICC_Profile.class); new LCMSSanitizerStrategy().fixProfile(profile); diff --git a/imageio/imageio-metadata/src/test/java/com/twelvemonkeys/imageio/metadata/xmp/XMPReaderTest.java b/imageio/imageio-metadata/src/test/java/com/twelvemonkeys/imageio/metadata/xmp/XMPReaderTest.java index 02be1834..315274d9 100644 --- a/imageio/imageio-metadata/src/test/java/com/twelvemonkeys/imageio/metadata/xmp/XMPReaderTest.java +++ b/imageio/imageio-metadata/src/test/java/com/twelvemonkeys/imageio/metadata/xmp/XMPReaderTest.java @@ -35,8 +35,11 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; @@ -50,6 +53,7 @@ import java.util.Iterator; import javax.imageio.ImageIO; import javax.imageio.stream.ImageInputStream; +import com.twelvemonkeys.imageio.stream.DirectImageInputStream; import org.junit.Test; import com.twelvemonkeys.imageio.metadata.CompoundDirectory; @@ -490,12 +494,15 @@ public class XMPReaderTest extends MetadataReaderAbstractTest { assertThat(exif.getEntryById("http://ns.adobe.com/exif/1.0/NativeDigest"), hasValue("36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;A7F21D25E2C562F152B2C4ECC9E534DA")); } - @Test(timeout = 1500L) + @Test(timeout = 2500L) public void testNoExternalRequest() throws Exception { - // TODO: Use dynamic port? - try (HTTPServer server = new HTTPServer(7777)) { - try { - createReader().read(getResourceAsIIS("/xmp/xmp-jpeg-xxe.xml")); + String maliciousXML = resourceAsString("/xmp/xmp-jpeg-xxe.xml"); + + try (HTTPServer server = new HTTPServer()) { + String dynamicXML = maliciousXML.replace("http://localhost:7777/", "http://localhost:" + server.port() + "/"); + + try (DirectImageInputStream input = new DirectImageInputStream(new ByteArrayInputStream(dynamicXML.getBytes(StandardCharsets.UTF_8)));) { + createReader().read(input); } catch (IOException ioe) { if (ioe.getMessage().contains("501")) { throw new AssertionError("Reading should not cause external requests", ioe); @@ -507,12 +514,26 @@ public class XMPReaderTest extends MetadataReaderAbstractTest { } } + private String resourceAsString(String name) throws IOException { + StringBuilder builder = new StringBuilder(1024); + + try (BufferedReader reader = new BufferedReader(new InputStreamReader(getResource(name).openStream(), StandardCharsets.UTF_8))) { + String line; + while ((line = reader.readLine()) != null) { + builder.append(line) + .append('\n'); + } + } + + return builder.toString(); + } + private static class HTTPServer implements AutoCloseable { private final ServerSocket server; private final Thread thread; - HTTPServer(int port) throws IOException { - server = new ServerSocket(port, 1); + HTTPServer() throws IOException { + server = new ServerSocket(0, 1); thread = new Thread(new Runnable() { @Override public void run() { serve(); @@ -521,6 +542,10 @@ public class XMPReaderTest extends MetadataReaderAbstractTest { thread.start(); } + public final int port() { + return server.getLocalPort(); + } + private void serve() { try { Socket client = server.accept(); diff --git a/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSD.java b/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSD.java index da7cf425..1a1f2063 100755 --- a/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSD.java +++ b/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSD.java @@ -709,4 +709,6 @@ interface PSD extends com.twelvemonkeys.imageio.metadata.psd.PSD { int luni = 'l' << 24 | 'u' << 16 | 'n' << 8 | 'i'; int lyid = 'l' << 24 | 'y' << 16 | 'i' << 8 | 'd'; int lsct = 'l' << 24 | 's' << 16 | 'c' << 8 | 't'; + // Undocumented: Nested section divider setting + int lsdk = 'l' << 24 | 's' << 16 | 'd' << 8 | 'k'; } diff --git a/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDLayerInfo.java b/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDLayerInfo.java index 6bb0fa14..d6814d9e 100755 --- a/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDLayerInfo.java +++ b/imageio/imageio-psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDLayerInfo.java @@ -155,6 +155,7 @@ final class PSDLayerInfo { layerId = pInput.readInt(); break; + case PSD.lsdk: case PSD.lsct: if (resourceLength < 4) { throw new IIOException(String.format("Expected sectionDividerSetting length >= 4: %d", resourceLength)); diff --git a/imageio/pom.xml b/imageio/pom.xml index c73399db..964bf618 100644 --- a/imageio/pom.xml +++ b/imageio/pom.xml @@ -98,14 +98,14 @@ junit junit - 4.13.1 + 4.13.2 test org.mockito mockito-core - 3.12.4 + 4.11.0 test diff --git a/pom.xml b/pom.xml old mode 100755 new mode 100644 index e2080e98..c1c3d937 --- a/pom.xml +++ b/pom.xml @@ -98,7 +98,7 @@ org.apache.maven.plugins maven-gpg-plugin - 1.6 + 3.1.0 @@ -119,7 +119,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.2.0 + 3.5.0 attach-javadocs @@ -145,7 +145,7 @@ org.apache.maven.plugins maven-help-plugin - 3.2.0 + 3.4.0 @@ -167,14 +167,13 @@ org.apache.maven.plugins maven-source-plugin - 3.2.1 + 3.3.0 package attach-sources jar-no-fork - jar test-jar @@ -184,7 +183,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.8 + 1.6.13 true ossrh @@ -199,7 +198,7 @@ org.apache.maven.plugins maven-resources-plugin - 3.2.0 + 3.3.1 UTF-8 @@ -207,7 +206,7 @@ org.apache.maven.plugins maven-jar-plugin - 3.2.0 + 3.3.0 true @@ -222,11 +221,11 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.11.0 true - 1.7 - 1.7 + 8 + 8 false source,lines @@ -237,7 +236,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.0.0-M5 + 3.1.0 @@ -250,7 +249,7 @@ org.apache.maven.plugins maven-release-plugin - 3.0.0-M4 + 3.0.1 true release @@ -260,19 +259,19 @@ org.apache.maven.scm maven-scm-provider-gitexe - 1.11.2 + 2.0.1 org.apache.maven.plugins maven-deploy-plugin - 3.0.0-M1 + 3.1.1 org.apache.maven.plugins maven-surefire-report-plugin - 3.0.0-M5 + 3.1.0 org.codehaus.mojo @@ -282,12 +281,12 @@ org.apache.maven.plugins maven-pmd-plugin - 3.14.0 + 3.21.0 org.apache.maven.plugins maven-checkstyle-plugin - 3.1.2 + 3.3.0 diff --git a/servlet/pom.xml b/servlet/pom.xml index 756b8b45..934919e0 100644 --- a/servlet/pom.xml +++ b/servlet/pom.xml @@ -15,7 +15,7 @@ javax.servlet servlet-api - 2.4 + 2.5 provided @@ -29,7 +29,7 @@ org.mockito mockito-core - 4.1.0 + 4.11.0 test @@ -50,7 +50,7 @@ org.apache.maven.plugins maven-jar-plugin - 2.4 + 3.3.0 @@ -62,10 +62,11 @@ + org.apache.maven.plugins maven-shade-plugin - 3.2.2 + 3.4.1 jakarta