Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 35 additions & 31 deletions src/main/java/org/apache/commons/codec/cli/Digest.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.commons.codec.cli;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
Expand All @@ -36,18 +38,17 @@
*/
public class Digest {

private static final String EMPTY = "";

/**
* Runs the digest algorithm in {@code args[0]} on the file in {@code args[1]}. If there is no {@code args[1]}, use
* standard input.
* Runs the digest algorithm in {@code args[0]} on the file in {@code args[1]}. If there is no {@code args[1]}, use standard input.
*
* <p>
* The algorithm can also be {@code ALL} or {@code *} to output one line for each known algorithm.
* </p>
*
* @param args
* {@code args[0]} is one of {@link MessageDigestAlgorithms} name,
* {@link MessageDigest} name, {@code ALL}, or {@code *}.
* {@code args[1+]} is a FILE/DIRECTORY/String.
* @param args {@code args[0]} is one of {@link MessageDigestAlgorithms} name, {@link MessageDigest} name, {@code ALL}, or {@code *}. {@code args[1+]} is a
* FILE/DIRECTORY/String.
* @throws IOException if an error occurs.
*/
public static void main(final String[] args) throws IOException {
Expand All @@ -62,16 +63,11 @@ private Digest(final String[] args) {
Objects.requireNonNull(args);
final int argsLength = args.length;
if (argsLength == 0) {
throw new IllegalArgumentException(
String.format("Usage: java %s [algorithm] [FILE|DIRECTORY|string] ...", Digest.class.getName()));
throw new IllegalArgumentException(String.format("Usage: java %s [algorithm] [FILE|DIRECTORY|string] ...", Digest.class.getName()));
}
this.args = args;
this.algorithm = args[0];
if (argsLength <= 1) {
this.inputs = null;
} else {
this.inputs = Arrays.copyOfRange(args, 1, argsLength);
}
this.inputs = argsLength > 1 ? Arrays.copyOfRange(args, 1, argsLength) : null;
}

private void println(final String prefix, final byte[] digest) {
Expand All @@ -84,25 +80,26 @@ private void println(final String prefix, final byte[] digest, final String file
// where '*' is used for binary files
// shasum(1) has a -b option which generates " *" separator
// we don't distinguish binary files at present
System.out.println(prefix + Hex.encodeHexString(digest) + (fileName != null ? " " + fileName : ""));
System.out.println(prefix + Hex.encodeHexString(digest) + (fileName != null ? " " + fileName : EMPTY));
}

private void run() throws IOException {
final BufferedInputStream systemIn = inputs != null ? null : new BufferedInputStream(System.in);
if (algorithm.equalsIgnoreCase("ALL") || algorithm.equals("*")) {
run(MessageDigestAlgorithms.values());
run(systemIn, MessageDigestAlgorithms.values());
return;
}
final MessageDigest messageDigest = DigestUtils.getDigest(algorithm, null);
if (messageDigest != null) {
run("", messageDigest);
run(systemIn, EMPTY, messageDigest);
} else {
run("", DigestUtils.getDigest(algorithm.toUpperCase(Locale.ROOT)));
run(systemIn, EMPTY, DigestUtils.getDigest(algorithm.toUpperCase(Locale.ROOT)));
}
}

private void run(final String prefix, final MessageDigest messageDigest) throws IOException {
private void run(final BufferedInputStream systemIn, final String prefix, final MessageDigest messageDigest) throws IOException {
if (inputs == null) {
println(prefix, DigestUtils.digest(messageDigest, System.in));
println(prefix, DigestUtils.digest(messageDigest, systemIn));
return;
}
for (final String source : inputs) {
Expand All @@ -122,22 +119,29 @@ private void run(final String prefix, final MessageDigest messageDigest) throws
}
}

private void run(final String prefix, final MessageDigest messageDigest, final File[] files) throws IOException {
for (final File file : files) {
if (file.isFile()) {
println(prefix, DigestUtils.digest(messageDigest, file), file.getName());
}
}
}

private void run(final String prefix, final String messageDigestAlgorithm) throws IOException {
run(prefix, DigestUtils.getDigest(messageDigestAlgorithm));
private void run(final BufferedInputStream systemIn, final String prefix, final String messageDigestAlgorithm) throws IOException {
run(systemIn, prefix, DigestUtils.getDigest(messageDigestAlgorithm));
}

private void run(final String[] digestAlgorithms) throws IOException {
private void run(final BufferedInputStream systemIn, final String[] digestAlgorithms) throws IOException {
for (final String messageDigestAlgorithm : digestAlgorithms) {
if (DigestUtils.isAvailable(messageDigestAlgorithm)) {
run(messageDigestAlgorithm + " ", messageDigestAlgorithm);
if (systemIn != null) {
// 1 GB arbitrary default.
systemIn.mark(Integer.getInteger(getClass().getName() + ".markReadLimit", 1_073_741_824));
}
run(systemIn, messageDigestAlgorithm + " ", messageDigestAlgorithm);
if (systemIn != null) {
systemIn.reset();
}
}
}
}

private void run(final String prefix, final MessageDigest messageDigest, final File[] files) throws IOException {
for (final File file : files) {
if (file.isFile()) {
println(prefix, DigestUtils.digest(messageDigest, file), file.getName());
}
}
}
Expand Down
44 changes: 44 additions & 0 deletions src/test/java/org/apache/commons/codec/cli/DigestTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,58 @@
package org.apache.commons.codec.cli;

import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;

import org.apache.commons.lang3.JavaVersion;
import org.apache.commons.lang3.SystemUtils;
import org.junit.jupiter.api.Test;

/**
* Tests {@link Digest}.
*/
class DigestTest {

@Test
void testAllAlgorithmsUseTheSameStandardInput() throws Exception {
final InputStream originalIn = System.in;
final PrintStream originalOut = System.out;
final ByteArrayOutputStream captured = new ByteArrayOutputStream();
try {
System.setIn(new ByteArrayInputStream("abc".getBytes(StandardCharsets.UTF_8)));
System.setOut(new PrintStream(captured, true, StandardCharsets.UTF_8.name()));
Digest.main(new String[] { "ALL" });
} finally {
System.setIn(originalIn);
System.setOut(originalOut);
}
final String output = captured.toString(StandardCharsets.UTF_8.name());
assertTrue(output.contains("MD2 da853b0d3f88d99b30283a69e6ded6bb"), output);
assertTrue(output.contains("MD5 900150983cd24fb0d6963f7d28e17f72"), output);
assertTrue(output.contains("SHA-1 a9993e364706816aba3e25717850c26c9cd0d89d"), output);
assertTrue(output.contains("SHA-224 23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7"), output);
assertTrue(output.contains("SHA-256 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"), output);
assertTrue(output.contains("SHA-384 cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"), output);
assertTrue(output.contains(
"SHA-512 ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"),
output);
assertTrue(output.contains("SHA-512/224 4634270f707b6a54daae7530460842e20e37ed265ceee9a43e8924aa"), output);
assertTrue(output.contains("SHA-512/256 53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23"), output);
if (SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_9)) {
assertTrue(output.contains("SHA3-224 e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf"), output);
assertTrue(output.contains("SHA3-256 3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532"), output);
assertTrue(output.contains("SHA3-384 ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25"), output);
assertTrue(output.contains(
"SHA3-512 b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"),
output);
}
}

/**
* Tests if empty arguments are handled correctly.
*/
Expand Down
Loading