mirror of
https://codeberg.org/PGPainless/sop-java.git
synced 2024-11-22 15:12:06 +01:00
Kotlin conversion: AbstractSopCmd
This commit is contained in:
parent
256d1c5960
commit
666d51384b
3 changed files with 249 additions and 283 deletions
|
@ -1,282 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2022 Paul Schaub <vanitasvitae@fsfe.org>
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package sop.cli.picocli.commands;
|
|
||||||
|
|
||||||
import sop.exception.SOPGPException;
|
|
||||||
import sop.util.UTCUtil;
|
|
||||||
import sop.util.UTF8Util;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.ResourceBundle;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract super class of SOP subcommands.
|
|
||||||
*/
|
|
||||||
public abstract class AbstractSopCmd implements Runnable {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface to modularize resolving of environment variables.
|
|
||||||
*/
|
|
||||||
public interface EnvironmentVariableResolver {
|
|
||||||
/**
|
|
||||||
* Resolve the value of the given environment variable.
|
|
||||||
* Return null if the variable is not present.
|
|
||||||
*
|
|
||||||
* @param name name of the variable
|
|
||||||
* @return variable value or null
|
|
||||||
*/
|
|
||||||
String resolveEnvironmentVariable(String name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final String PRFX_ENV = "@ENV:";
|
|
||||||
public static final String PRFX_FD = "@FD:";
|
|
||||||
public static final Date BEGINNING_OF_TIME = new Date(0);
|
|
||||||
public static final Date END_OF_TIME = new Date(8640000000000000L);
|
|
||||||
|
|
||||||
public static final Pattern PATTERN_FD = Pattern.compile("^\\d{1,20}$");
|
|
||||||
|
|
||||||
protected final ResourceBundle messages;
|
|
||||||
protected EnvironmentVariableResolver envResolver = System::getenv;
|
|
||||||
|
|
||||||
public AbstractSopCmd() {
|
|
||||||
this(Locale.getDefault());
|
|
||||||
}
|
|
||||||
|
|
||||||
public AbstractSopCmd(@Nonnull Locale locale) {
|
|
||||||
messages = ResourceBundle.getBundle("msg_sop", locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
void throwIfOutputExists(String output) {
|
|
||||||
if (output == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
File outputFile = new File(output);
|
|
||||||
if (outputFile.exists()) {
|
|
||||||
String errorMsg = getMsg("sop.error.indirect_data_type.output_file_already_exists", outputFile.getAbsolutePath());
|
|
||||||
throw new SOPGPException.OutputExists(errorMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMsg(String key) {
|
|
||||||
return messages.getString(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMsg(String key, String arg1) {
|
|
||||||
return String.format(messages.getString(key), arg1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMsg(String key, String arg1, String arg2) {
|
|
||||||
return String.format(messages.getString(key), arg1, arg2);
|
|
||||||
}
|
|
||||||
|
|
||||||
void throwIfMissingArg(Object arg, String argName) {
|
|
||||||
if (arg == null) {
|
|
||||||
String errorMsg = getMsg("sop.error.usage.argument_required", argName);
|
|
||||||
throw new SOPGPException.MissingArg(errorMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void throwIfEmptyParameters(Collection<?> arg, String parmName) {
|
|
||||||
if (arg.isEmpty()) {
|
|
||||||
String errorMsg = getMsg("sop.error.usage.parameter_required", parmName);
|
|
||||||
throw new SOPGPException.MissingArg(errorMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
<T> T throwIfUnsupportedSubcommand(T subcommand, String subcommandName) {
|
|
||||||
if (subcommand == null) {
|
|
||||||
String errorMsg = getMsg("sop.error.feature_support.subcommand_not_supported", subcommandName);
|
|
||||||
throw new SOPGPException.UnsupportedSubcommand(errorMsg);
|
|
||||||
}
|
|
||||||
return subcommand;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setEnvironmentVariableResolver(EnvironmentVariableResolver envResolver) {
|
|
||||||
if (envResolver == null) {
|
|
||||||
throw new NullPointerException("Variable envResolver cannot be null.");
|
|
||||||
}
|
|
||||||
this.envResolver = envResolver;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputStream getInput(String indirectInput) throws IOException {
|
|
||||||
if (indirectInput == null) {
|
|
||||||
throw new IllegalArgumentException("Input cannot not be null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
String trimmed = indirectInput.trim();
|
|
||||||
if (trimmed.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("Input cannot be blank.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (trimmed.startsWith(PRFX_ENV)) {
|
|
||||||
if (new File(trimmed).exists()) {
|
|
||||||
String errorMsg = getMsg("sop.error.indirect_data_type.ambiguous_filename", trimmed);
|
|
||||||
throw new SOPGPException.AmbiguousInput(errorMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
String envName = trimmed.substring(PRFX_ENV.length());
|
|
||||||
String envValue = envResolver.resolveEnvironmentVariable(envName);
|
|
||||||
if (envValue == null) {
|
|
||||||
String errorMsg = getMsg("sop.error.indirect_data_type.environment_variable_not_set", envName);
|
|
||||||
throw new IllegalArgumentException(errorMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (envValue.trim().isEmpty()) {
|
|
||||||
String errorMsg = getMsg("sop.error.indirect_data_type.environment_variable_empty", envName);
|
|
||||||
throw new IllegalArgumentException(errorMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ByteArrayInputStream(envValue.getBytes("UTF8"));
|
|
||||||
|
|
||||||
} else if (trimmed.startsWith(PRFX_FD)) {
|
|
||||||
|
|
||||||
if (new File(trimmed).exists()) {
|
|
||||||
String errorMsg = getMsg("sop.error.indirect_data_type.ambiguous_filename", trimmed);
|
|
||||||
throw new SOPGPException.AmbiguousInput(errorMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
File fdFile = fileDescriptorFromString(trimmed);
|
|
||||||
try {
|
|
||||||
FileInputStream fileIn = new FileInputStream(fdFile);
|
|
||||||
return fileIn;
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
String errorMsg = getMsg("sop.error.indirect_data_type.file_descriptor_not_found", fdFile.getAbsolutePath());
|
|
||||||
throw new IOException(errorMsg, e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
File file = new File(trimmed);
|
|
||||||
if (!file.exists()) {
|
|
||||||
String errorMsg = getMsg("sop.error.indirect_data_type.input_file_does_not_exist", file.getAbsolutePath());
|
|
||||||
throw new SOPGPException.MissingInput(errorMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file.isFile()) {
|
|
||||||
String errorMsg = getMsg("sop.error.indirect_data_type.input_not_a_file", file.getAbsolutePath());
|
|
||||||
throw new SOPGPException.MissingInput(errorMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new FileInputStream(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public OutputStream getOutput(String indirectOutput) throws IOException {
|
|
||||||
if (indirectOutput == null) {
|
|
||||||
throw new IllegalArgumentException("Output cannot be null.");
|
|
||||||
}
|
|
||||||
|
|
||||||
String trimmed = indirectOutput.trim();
|
|
||||||
if (trimmed.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("Output cannot be blank.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// @ENV not allowed for output
|
|
||||||
if (trimmed.startsWith(PRFX_ENV)) {
|
|
||||||
String errorMsg = getMsg("sop.error.indirect_data_type.illegal_use_of_env_designator");
|
|
||||||
throw new SOPGPException.UnsupportedSpecialPrefix(errorMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// File Descriptor
|
|
||||||
if (trimmed.startsWith(PRFX_FD)) {
|
|
||||||
File fdFile = fileDescriptorFromString(trimmed);
|
|
||||||
try {
|
|
||||||
FileOutputStream fout = new FileOutputStream(fdFile);
|
|
||||||
return fout;
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
String errorMsg = getMsg("sop.error.indirect_data_type.file_descriptor_not_found", fdFile.getAbsolutePath());
|
|
||||||
throw new IOException(errorMsg, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
File file = new File(trimmed);
|
|
||||||
if (file.exists()) {
|
|
||||||
String errorMsg = getMsg("sop.error.indirect_data_type.output_file_already_exists", file.getAbsolutePath());
|
|
||||||
throw new SOPGPException.OutputExists(errorMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file.createNewFile()) {
|
|
||||||
String errorMsg = getMsg("sop.error.indirect_data_type.output_file_cannot_be_created", file.getAbsolutePath());
|
|
||||||
throw new IOException(errorMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new FileOutputStream(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
public File fileDescriptorFromString(String fdString) {
|
|
||||||
File fdDir = new File("/dev/fd/");
|
|
||||||
if (!fdDir.exists()) {
|
|
||||||
String errorMsg = getMsg("sop.error.indirect_data_type.designator_fd_not_supported");
|
|
||||||
throw new SOPGPException.UnsupportedSpecialPrefix(errorMsg);
|
|
||||||
}
|
|
||||||
String fdNumber = fdString.substring(PRFX_FD.length());
|
|
||||||
if (!PATTERN_FD.matcher(fdNumber).matches()) {
|
|
||||||
throw new IllegalArgumentException("File descriptor must be a positive number.");
|
|
||||||
}
|
|
||||||
File descriptor = new File(fdDir, fdNumber);
|
|
||||||
return descriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String stringFromInputStream(InputStream inputStream) throws IOException {
|
|
||||||
try {
|
|
||||||
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
|
|
||||||
byte[] buf = new byte[4096]; int read;
|
|
||||||
while ((read = inputStream.read(buf)) != -1) {
|
|
||||||
byteOut.write(buf, 0, read);
|
|
||||||
}
|
|
||||||
// TODO: For decrypt operations we MUST accept non-UTF8 passwords
|
|
||||||
return UTF8Util.decodeUTF8(byteOut.toByteArray());
|
|
||||||
} finally {
|
|
||||||
inputStream.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date parseNotAfter(String notAfter) {
|
|
||||||
if (notAfter.equals("now")) {
|
|
||||||
return new Date();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notAfter.equals("-")) {
|
|
||||||
return END_OF_TIME;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return UTCUtil.parseUTCDate(notAfter);
|
|
||||||
} catch (ParseException e) {
|
|
||||||
String errorMsg = getMsg("sop.error.input.malformed_not_after");
|
|
||||||
throw new IllegalArgumentException(errorMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Date parseNotBefore(String notBefore) {
|
|
||||||
if (notBefore.equals("now")) {
|
|
||||||
return new Date();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notBefore.equals("-")) {
|
|
||||||
return BEGINNING_OF_TIME;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return UTCUtil.parseUTCDate(notBefore);
|
|
||||||
} catch (ParseException e) {
|
|
||||||
String errorMsg = getMsg("sop.error.input.malformed_not_before");
|
|
||||||
throw new IllegalArgumentException(errorMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,248 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package sop.cli.picocli.commands
|
||||||
|
|
||||||
|
import java.io.*
|
||||||
|
import java.text.ParseException
|
||||||
|
import java.util.*
|
||||||
|
import sop.cli.picocli.commands.AbstractSopCmd.EnvironmentVariableResolver
|
||||||
|
import sop.exception.SOPGPException.*
|
||||||
|
import sop.util.UTCUtil.Companion.parseUTCDate
|
||||||
|
import sop.util.UTF8Util.Companion.decodeUTF8
|
||||||
|
|
||||||
|
/** Abstract super class of SOP subcommands. */
|
||||||
|
abstract class AbstractSopCmd(locale: Locale = Locale.getDefault()) : Runnable {
|
||||||
|
|
||||||
|
private val messages: ResourceBundle = ResourceBundle.getBundle("msg_sop", locale)
|
||||||
|
var environmentVariableResolver = EnvironmentVariableResolver { name: String ->
|
||||||
|
System.getenv(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Interface to modularize resolving of environment variables. */
|
||||||
|
fun interface EnvironmentVariableResolver {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the value of the given environment variable. Return null if the variable is not
|
||||||
|
* present.
|
||||||
|
*
|
||||||
|
* @param name name of the variable
|
||||||
|
* @return variable value or null
|
||||||
|
*/
|
||||||
|
fun resolveEnvironmentVariable(name: String): String?
|
||||||
|
}
|
||||||
|
|
||||||
|
fun throwIfOutputExists(output: String?) {
|
||||||
|
output
|
||||||
|
?.let { File(it) }
|
||||||
|
?.let {
|
||||||
|
if (it.exists()) {
|
||||||
|
val errorMsg: String =
|
||||||
|
getMsg(
|
||||||
|
"sop.error.indirect_data_type.output_file_already_exists",
|
||||||
|
it.absolutePath)
|
||||||
|
throw OutputExists(errorMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getMsg(key: String): String = messages.getString(key)
|
||||||
|
|
||||||
|
fun getMsg(key: String, vararg args: String): String {
|
||||||
|
val msg = messages.getString(key)
|
||||||
|
return String.format(msg, *args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun throwIfMissingArg(arg: Any?, argName: String) {
|
||||||
|
if (arg == null) {
|
||||||
|
val errorMsg = getMsg("sop.error.usage.argument_required", argName)
|
||||||
|
throw MissingArg(errorMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun throwIfEmptyParameters(arg: Collection<*>, parmName: String) {
|
||||||
|
if (arg.isEmpty()) {
|
||||||
|
val errorMsg = getMsg("sop.error.usage.parameter_required", parmName)
|
||||||
|
throw MissingArg(errorMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> throwIfUnsupportedSubcommand(subcommand: T?, subcommandName: String): T {
|
||||||
|
if (subcommand == null) {
|
||||||
|
val errorMsg =
|
||||||
|
getMsg("sop.error.feature_support.subcommand_not_supported", subcommandName)
|
||||||
|
throw UnsupportedSubcommand(errorMsg)
|
||||||
|
}
|
||||||
|
return subcommand
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun getInput(indirectInput: String): InputStream {
|
||||||
|
val trimmed = indirectInput.trim()
|
||||||
|
require(trimmed.isNotBlank()) { "Input cannot be blank." }
|
||||||
|
|
||||||
|
if (trimmed.startsWith(PRFX_ENV)) {
|
||||||
|
if (File(trimmed).exists()) {
|
||||||
|
val errorMsg = getMsg("sop.error.indirect_data_type.ambiguous_filename", trimmed)
|
||||||
|
throw AmbiguousInput(errorMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
val envName = trimmed.substring(PRFX_ENV.length)
|
||||||
|
val envValue = environmentVariableResolver.resolveEnvironmentVariable(envName)
|
||||||
|
requireNotNull(envValue) {
|
||||||
|
getMsg("sop.error.indirect_data_type.environment_variable_not_set", envName)
|
||||||
|
}
|
||||||
|
|
||||||
|
require(envValue.trim().isNotEmpty()) {
|
||||||
|
getMsg("sop.error.indirect_data_type.environment_variable_empty", envName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return envValue.byteInputStream()
|
||||||
|
} else if (trimmed.startsWith(PRFX_FD)) {
|
||||||
|
|
||||||
|
if (File(trimmed).exists()) {
|
||||||
|
val errorMsg = getMsg("sop.error.indirect_data_type.ambiguous_filename", trimmed)
|
||||||
|
throw AmbiguousInput(errorMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
val fdFile: File = fileDescriptorFromString(trimmed)
|
||||||
|
return try {
|
||||||
|
fdFile.inputStream()
|
||||||
|
} catch (e: FileNotFoundException) {
|
||||||
|
val errorMsg =
|
||||||
|
getMsg(
|
||||||
|
"sop.error.indirect_data_type.file_descriptor_not_found",
|
||||||
|
fdFile.absolutePath)
|
||||||
|
throw IOException(errorMsg, e)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
val file = File(trimmed)
|
||||||
|
if (!file.exists()) {
|
||||||
|
val errorMsg =
|
||||||
|
getMsg(
|
||||||
|
"sop.error.indirect_data_type.input_file_does_not_exist", file.absolutePath)
|
||||||
|
throw MissingInput(errorMsg)
|
||||||
|
}
|
||||||
|
if (!file.isFile()) {
|
||||||
|
val errorMsg =
|
||||||
|
getMsg("sop.error.indirect_data_type.input_not_a_file", file.absolutePath)
|
||||||
|
throw MissingInput(errorMsg)
|
||||||
|
}
|
||||||
|
return file.inputStream()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun getOutput(indirectOutput: String?): OutputStream {
|
||||||
|
requireNotNull(indirectOutput) { "Output cannot be null." }
|
||||||
|
val trimmed = indirectOutput.trim()
|
||||||
|
require(trimmed.isNotEmpty()) { "Output cannot be blank." }
|
||||||
|
|
||||||
|
// @ENV not allowed for output
|
||||||
|
if (trimmed.startsWith(PRFX_ENV)) {
|
||||||
|
val errorMsg = getMsg("sop.error.indirect_data_type.illegal_use_of_env_designator")
|
||||||
|
throw UnsupportedSpecialPrefix(errorMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// File Descriptor
|
||||||
|
if (trimmed.startsWith(PRFX_FD)) {
|
||||||
|
val fdFile = fileDescriptorFromString(trimmed)
|
||||||
|
return try {
|
||||||
|
fdFile.outputStream()
|
||||||
|
} catch (e: FileNotFoundException) {
|
||||||
|
val errorMsg =
|
||||||
|
getMsg(
|
||||||
|
"sop.error.indirect_data_type.file_descriptor_not_found",
|
||||||
|
fdFile.absolutePath)
|
||||||
|
throw IOException(errorMsg, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val file = File(trimmed)
|
||||||
|
if (file.exists()) {
|
||||||
|
val errorMsg =
|
||||||
|
getMsg("sop.error.indirect_data_type.output_file_already_exists", file.absolutePath)
|
||||||
|
throw OutputExists(errorMsg)
|
||||||
|
}
|
||||||
|
if (!file.createNewFile()) {
|
||||||
|
val errorMsg =
|
||||||
|
getMsg(
|
||||||
|
"sop.error.indirect_data_type.output_file_cannot_be_created", file.absolutePath)
|
||||||
|
throw IOException(errorMsg)
|
||||||
|
}
|
||||||
|
return file.outputStream()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fileDescriptorFromString(fdString: String): File {
|
||||||
|
val fdDir = File("/dev/fd/")
|
||||||
|
if (!fdDir.exists()) {
|
||||||
|
val errorMsg = getMsg("sop.error.indirect_data_type.designator_fd_not_supported")
|
||||||
|
throw UnsupportedSpecialPrefix(errorMsg)
|
||||||
|
}
|
||||||
|
val fdNumber = fdString.substring(PRFX_FD.length)
|
||||||
|
require(PATTERN_FD.matcher(fdNumber).matches()) {
|
||||||
|
"File descriptor must be a positive number."
|
||||||
|
}
|
||||||
|
return File(fdDir, fdNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseNotAfter(notAfter: String): Date {
|
||||||
|
return when (notAfter) {
|
||||||
|
"now" -> Date()
|
||||||
|
"-" -> END_OF_TIME
|
||||||
|
else ->
|
||||||
|
try {
|
||||||
|
parseUTCDate(notAfter)
|
||||||
|
} catch (e: ParseException) {
|
||||||
|
val errorMsg = getMsg("sop.error.input.malformed_not_after")
|
||||||
|
throw IllegalArgumentException(errorMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseNotBefore(notBefore: String): Date {
|
||||||
|
return when (notBefore) {
|
||||||
|
"now" -> Date()
|
||||||
|
"-" -> DAWN_OF_TIME
|
||||||
|
else ->
|
||||||
|
try {
|
||||||
|
parseUTCDate(notBefore)
|
||||||
|
} catch (e: ParseException) {
|
||||||
|
val errorMsg = getMsg("sop.error.input.malformed_not_before")
|
||||||
|
throw IllegalArgumentException(errorMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRFX_ENV = "@ENV:"
|
||||||
|
|
||||||
|
const val PRFX_FD = "@FD:"
|
||||||
|
|
||||||
|
@JvmField val DAWN_OF_TIME = Date(0)
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
@Deprecated("Replace with DAWN_OF_TIME", ReplaceWith("DAWN_OF_TIME"))
|
||||||
|
val BEGINNING_OF_TIME = DAWN_OF_TIME
|
||||||
|
|
||||||
|
@JvmField val END_OF_TIME = Date(8640000000000000L)
|
||||||
|
|
||||||
|
@JvmField val PATTERN_FD = "^\\d{1,20}$".toPattern()
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
@JvmStatic
|
||||||
|
fun stringFromInputStream(inputStream: InputStream): String {
|
||||||
|
return inputStream.use { input ->
|
||||||
|
val byteOut = ByteArrayOutputStream()
|
||||||
|
val buf = ByteArray(4096)
|
||||||
|
var read: Int
|
||||||
|
while (input.read(buf).also { read = it } != -1) {
|
||||||
|
byteOut.write(buf, 0, read)
|
||||||
|
}
|
||||||
|
// TODO: For decrypt operations we MUST accept non-UTF8 passwords
|
||||||
|
decodeUTF8(byteOut.toByteArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,7 +36,7 @@ public class AbstractSopCmdTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getInput_NullInvalid() {
|
public void getInput_NullInvalid() {
|
||||||
assertThrows(IllegalArgumentException.class, () -> abstractCmd.getInput(null));
|
assertThrows(NullPointerException.class, () -> abstractCmd.getInput(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in a new issue