diff --git a/external-sop/src/main/java/sop/external/operation/InlineDetachExternal.java b/external-sop/src/main/java/sop/external/operation/InlineDetachExternal.java deleted file mode 100644 index a798006..0000000 --- a/external-sop/src/main/java/sop/external/operation/InlineDetachExternal.java +++ /dev/null @@ -1,106 +0,0 @@ -// SPDX-FileCopyrightText: 2023 Paul Schaub -// -// SPDX-License-Identifier: Apache-2.0 - -package sop.external.operation; - -import sop.ReadyWithResult; -import sop.Signatures; -import sop.exception.SOPGPException; -import sop.external.ExternalSOP; -import sop.operation.InlineDetach; - -import javax.annotation.Nonnull; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -/** - * Implementation of the {@link InlineDetach} operation using an external SOP binary. - */ -public class InlineDetachExternal implements InlineDetach { - - private final ExternalSOP.TempDirProvider tempDirProvider; - private final List commandList = new ArrayList<>(); - private final List envList; - - public InlineDetachExternal(String binary, Properties environment, ExternalSOP.TempDirProvider tempDirProvider) { - this.tempDirProvider = tempDirProvider; - commandList.add(binary); - commandList.add("inline-detach"); - envList = ExternalSOP.propertiesToEnv(environment); - } - - @Override - @Nonnull - public InlineDetach noArmor() { - commandList.add("--no-armor"); - return this; - } - - @Override - @Nonnull - public ReadyWithResult message(@Nonnull InputStream messageInputStream) throws IOException, SOPGPException.BadData { - File tempDir = tempDirProvider.provideTempDirectory(); - - File signaturesOut = new File(tempDir, "signatures"); - signaturesOut.delete(); - commandList.add("--signatures-out=" + signaturesOut.getAbsolutePath()); - - String[] command = commandList.toArray(new String[0]); - String[] env = envList.toArray(new String[0]); - - try { - Process process = Runtime.getRuntime().exec(command, env); - OutputStream processOut = process.getOutputStream(); - InputStream processIn = process.getInputStream(); - - return new ReadyWithResult() { - @Override - public Signatures writeTo(@Nonnull OutputStream outputStream) throws IOException { - byte[] buf = new byte[4096]; - int r; - while ((r = messageInputStream.read(buf)) > 0) { - processOut.write(buf, 0, r); - } - - messageInputStream.close(); - processOut.close(); - - while ((r = processIn.read(buf)) > 0) { - outputStream.write(buf, 0 , r); - } - - processIn.close(); - outputStream.close(); - - ExternalSOP.finish(process); - - FileInputStream signaturesOutIn = new FileInputStream(signaturesOut); - ByteArrayOutputStream signaturesBuffer = new ByteArrayOutputStream(); - while ((r = signaturesOutIn.read(buf)) > 0) { - signaturesBuffer.write(buf, 0, r); - } - signaturesOutIn.close(); - signaturesOut.delete(); - - final byte[] sigBytes = signaturesBuffer.toByteArray(); - return new Signatures() { - @Override - public void writeTo(@Nonnull OutputStream signatureOutputStream) throws IOException { - signatureOutputStream.write(sigBytes); - } - }; - } - }; - } catch (IOException e) { - throw new RuntimeException(e); - } - } -} diff --git a/external-sop/src/main/kotlin/sop/external/operation/InlineDetachExternal.kt b/external-sop/src/main/kotlin/sop/external/operation/InlineDetachExternal.kt new file mode 100644 index 0000000..f44e6bb --- /dev/null +++ b/external-sop/src/main/kotlin/sop/external/operation/InlineDetachExternal.kt @@ -0,0 +1,82 @@ +// SPDX-FileCopyrightText: 2023 Paul Schaub +// +// SPDX-License-Identifier: Apache-2.0 + +package sop.external.operation + +import java.io.* +import java.util.* +import sop.ReadyWithResult +import sop.Signatures +import sop.external.ExternalSOP +import sop.external.ExternalSOP.Companion.finish +import sop.operation.InlineDetach + +/** Implementation of the [InlineDetach] operation using an external SOP binary. */ +class InlineDetachExternal( + binary: String, + environment: Properties, + private val tempDirProvider: ExternalSOP.TempDirProvider +) : InlineDetach { + + private val commandList = mutableListOf(binary, "inline-detach") + private val envList = ExternalSOP.propertiesToEnv(environment) + + override fun noArmor(): InlineDetach = apply { commandList.add("--no-armor") } + + override fun message(messageInputStream: InputStream): ReadyWithResult { + val tempDir = tempDirProvider.provideTempDirectory() + + val signaturesOut = File(tempDir, "signatures") + signaturesOut.delete() + commandList.add("--signatures-out=${signaturesOut.absolutePath}") + + try { + val process = + Runtime.getRuntime().exec(commandList.toTypedArray(), envList.toTypedArray()) + val processOut = process.outputStream + val processIn = process.inputStream + + return object : ReadyWithResult() { + override fun writeTo(outputStream: OutputStream): Signatures { + val buf = ByteArray(4096) + var r: Int + while (messageInputStream.read(buf).also { r = it } > 0) { + processOut.write(buf, 0, r) + } + + messageInputStream.close() + processOut.close() + + while (processIn.read(buf).also { r = it } > 0) { + outputStream.write(buf, 0, r) + } + + processIn.close() + outputStream.close() + + finish(process) + + val signaturesOutIn = FileInputStream(signaturesOut) + val signaturesBuffer = ByteArrayOutputStream() + while (signaturesOutIn.read(buf).also { r = it } > 0) { + signaturesBuffer.write(buf, 0, r) + } + signaturesOutIn.close() + signaturesOut.delete() + + val sigBytes = signaturesBuffer.toByteArray() + + return object : Signatures() { + @Throws(IOException::class) + override fun writeTo(outputStream: OutputStream) { + outputStream.write(sigBytes) + } + } + } + } + } catch (e: IOException) { + throw RuntimeException(e) + } + } +}