Skip to content

Commit

Permalink
#54 - Handle file size not enough in case of embed watermark operatio…
Browse files Browse the repository at this point in the history
…n. Also handle case where some files fails processing during wildcard operations.
  • Loading branch information
Samir Vaidya committed Sep 25, 2022
1 parent b0377ff commit 9c86c50
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 23 deletions.
5 changes: 3 additions & 2 deletions src/main/java/com/openstego/desktop/OpenStego.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import javax.swing.*;
import java.io.*;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPInputStream;
Expand Down Expand Up @@ -118,7 +119,7 @@ public byte[] embedData(File msgFile, File coverFile, String stegoFileName) thro
String filename = null;

// If no message file is provided, then read the data from stdin
try (InputStream is = (msgFile == null ? System.in : new FileInputStream(msgFile))) {
try (InputStream is = (msgFile == null ? System.in : Files.newInputStream(msgFile.toPath()))) {
if (msgFile != null) {
filename = msgFile.getName();
}
Expand Down Expand Up @@ -170,7 +171,7 @@ public byte[] embedMark(File sigFile, File coverFile, String stegoFileName) thro
String filename = null;

// If no signature file is provided, then read the data from stdin
try (InputStream is = (sigFile == null ? System.in : new FileInputStream(sigFile))) {
try (InputStream is = (sigFile == null ? System.in : Files.newInputStream(sigFile.toPath()))) {
if (sigFile != null) {
filename = sigFile.getName();
}
Expand Down
60 changes: 60 additions & 0 deletions src/main/java/com/openstego/desktop/OpenStegoBulkException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Steganography utility to hide messages into cover files
* Author: Samir Vaidya (mailto:[email protected])
* Copyright (c) Samir Vaidya
*/

package com.openstego.desktop;

import java.util.ArrayList;
import java.util.List;

/**
* Custom exception class to store multiple errors
*/
public class OpenStegoBulkException extends Exception {

/**
* List of keys for the exception
*/
private final List<String> keys = new ArrayList<>();
/**
* List of exceptions
*/
private final List<OpenStegoException> exceptions = new ArrayList<>();

/**
* Add an exception to this bulk list
*
* @param key Key for the exception (e.g. filename)
* @param e Exception to be added
*/
public void add(String key, OpenStegoException e) {
keys.add(key);
exceptions.add(e);
}

/**
* Return the current list of keys
*/
public List<String> getKeys() {
return keys;
}

/**
* Return the current list of exceptions
*/
public List<OpenStegoException> getExceptions() {
return exceptions;
}

/**
* Throw this exception if list is not empty
*/
public void throwIfRequired() throws OpenStegoBulkException {
if (!exceptions.isEmpty()) {
throw this;
}
}

}
41 changes: 33 additions & 8 deletions src/main/java/com/openstego/desktop/OpenStegoCmd.java
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,15 @@ public static void execute(String[] args) {
} else {
System.err.println(osEx.getMessage());
}
} catch (OpenStegoBulkException bulkEx) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bulkEx.getExceptions().size(); i++) {
sb.append(" ").append(i + 1).append(". ").append(bulkEx.getKeys().get(i)).append(": ")
.append(bulkEx.getExceptions().get(i).getMessage()).append("\n");
}
System.err.println();
System.err.println(labelUtil.getString("cmd.label.bulkerror.header"));
System.err.println(sb);
} catch (Exception ex) {
ex.printStackTrace();
}
Expand All @@ -182,9 +191,11 @@ public static void execute(String[] args) {
*
* @param options Command-line options
* @param stego {@link OpenStego} object
* @throws OpenStegoException Processing issues
* @throws OpenStegoException Processing issues
* @throws OpenStegoBulkException Errors for multiple files
*/
private static void executeEmbed(CmdLineOptions options, OpenStego stego) throws OpenStegoException {
private static void executeEmbed(CmdLineOptions options, OpenStego stego)
throws OpenStegoException, OpenStegoBulkException {
String msgFileName = options.getStringValue("-mf");
String coverFileName = options.getStringValue("-cf");
String stegoFileName = options.getStringValue("-sf");
Expand Down Expand Up @@ -216,12 +227,18 @@ private static void executeEmbed(CmdLineOptions options, OpenStego stego) throws
System.err.println(labelUtil.getString("cmd.warn.stegoFileIgnored"));
}

OpenStegoBulkException bulkException = new OpenStegoBulkException();
// Loop through all cover files
for (File file : coverFileList) {
coverFileName = file.getName();
CommonUtil.writeFile(stego.embedData(msgFile, file, coverFileName), coverFileName);
System.err.println(labelUtil.getString("cmd.msg.coverProcessed", coverFileName));
try {
CommonUtil.writeFile(stego.embedData(msgFile, file, coverFileName), coverFileName);
System.err.println(labelUtil.getString("cmd.msg.coverProcessed", coverFileName));
} catch (OpenStegoException e) {
bulkException.add(coverFileName, e);
}
}
bulkException.throwIfRequired();
}
}

Expand All @@ -230,9 +247,11 @@ private static void executeEmbed(CmdLineOptions options, OpenStego stego) throws
*
* @param options Command-line options
* @param stego {@link OpenStego} object
* @throws OpenStegoException Processing issues
* @throws OpenStegoException Processing issues
* @throws OpenStegoBulkException Errors for multiple files
*/
private static void executeEmbedMark(CmdLineOptions options, OpenStego stego) throws OpenStegoException {
private static void executeEmbedMark(CmdLineOptions options, OpenStego stego)
throws OpenStegoException, OpenStegoBulkException {
String sigFileName = options.getStringValue("-gf");
String coverFileName = options.getStringValue("-cf");
String stegoFileName = options.getStringValue("-sf");
Expand All @@ -258,12 +277,18 @@ private static void executeEmbedMark(CmdLineOptions options, OpenStego stego) th
System.err.println(labelUtil.getString("cmd.warn.stegoFileIgnored"));
}

OpenStegoBulkException bulkException = new OpenStegoBulkException();
// Loop through all cover files
for (File file : coverFileList) {
coverFileName = file.getName();
CommonUtil.writeFile(stego.embedMark(sigFile, file, coverFileName), coverFileName);
System.err.println(labelUtil.getString("cmd.msg.coverProcessed", coverFileName));
try {
CommonUtil.writeFile(stego.embedMark(sigFile, file, coverFileName), coverFileName);
System.err.println(labelUtil.getString("cmd.msg.coverProcessed", coverFileName));
} catch (OpenStegoException e) {
bulkException.add(coverFileName, e);
}
}
bulkException.throwIfRequired();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,17 @@ public class DWTDugadErrors {
*/
public static final int ERR_SIG_NOT_VALID = 2;

/**
* Error Code - file size not enough to embed watermark
*/
public static final int ERR_FILE_TOO_SMALL = 3;

/**
* Initialize the error code - message key map
*/
public static void init() {
OpenStegoException.addErrorCode(DWTDugadPlugin.NAMESPACE, ERR_NO_COVER_FILE, "err.cover.missing");
OpenStegoException.addErrorCode(DWTDugadPlugin.NAMESPACE, ERR_SIG_NOT_VALID, "err.signature.invalid");
OpenStegoException.addErrorCode(DWTDugadPlugin.NAMESPACE, ERR_FILE_TOO_SMALL, "err.file.too.small");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ public byte[] embedData(byte[] msg, String msgFileName, byte[] cover, String cov

// Embed watermark in all subbands of a decomposition level
for (int i = 0; i < sig.decompositionLevel; i++) {
if (s.getHorizontal() == null || s.getVertical() == null || s.getDiagonal() == null) {
throw new OpenStegoException(null, NAMESPACE, DWTDugadErrors.ERR_FILE_TOO_SMALL);
}
wmSubBand(s.getHorizontal().getImage(), sig.watermark, sig.watermarkLength, sig.alpha, sig.castingThreshold);
wmSubBand(s.getVertical().getImage(), sig.watermark, sig.watermarkLength, sig.alpha, sig.castingThreshold);
wmSubBand(s.getDiagonal().getImage(), sig.watermark, sig.watermarkLength, sig.alpha, sig.castingThreshold);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ public class DWTKimErrors {
*/
public static final int ERR_SIG_NOT_VALID = 3;

/**
* Error Code - file size not enough to embed watermark
*/
public static final int ERR_FILE_TOO_SMALL = 3;

/**
* Initialize the error code - message key map
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ public byte[] embedData(byte[] msg, String msgFileName, byte[] cover, String cov

// process each decomposition level
while (p.getCoarse() != null) {
if (p.getHorizontal() == null || p.getVertical() == null || p.getDiagonal() == null) {
throw new OpenStegoException(null, NAMESPACE, DWTKimErrors.ERR_FILE_TOO_SMALL);
}

double threshold;

// Get current decomposition level number
Expand Down
68 changes: 55 additions & 13 deletions src/main/java/com/openstego/desktop/ui/OpenStegoUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@
*/
package com.openstego.desktop.ui;

import com.openstego.desktop.OpenStego;
import com.openstego.desktop.OpenStegoConfig;
import com.openstego.desktop.OpenStegoException;
import com.openstego.desktop.OpenStegoPlugin;
import com.openstego.desktop.*;
import com.openstego.desktop.util.CommonUtil;
import com.openstego.desktop.util.LabelUtil;
import com.openstego.desktop.util.ui.WorkerTask;
Expand Down Expand Up @@ -237,6 +234,7 @@ protected Object doInBackground() throws Exception {
coverFileList.add(null);
}

OpenStegoBulkException bulkException = new OpenStegoBulkException();
for (int i = 0; i < coverFileList.size(); i++) {
setProgress(i * 100 / coverFileList.size());
cvrFile = coverFileList.get(i);
Expand Down Expand Up @@ -266,11 +264,16 @@ protected Object doInBackground() throws Exception {
}

processCount++;
stegoData = openStego.embedData(
dataFileName == null || dataFileName.equals("") ? null : new File(dataFileName),
cvrFile, outputFileName);
CommonUtil.writeFile(stegoData, outputFileName);
try {
stegoData = openStego.embedData(
dataFileName == null || dataFileName.equals("") ? null : new File(dataFileName),
cvrFile, outputFileName);
CommonUtil.writeFile(stegoData, outputFileName);
} catch (OpenStegoException e) {
bulkException.add(cvrFile == null ? "-" : cvrFile.getName(), e);
}
}
bulkException.throwIfRequired();

return new Integer[]{processCount, skipCount};
}
Expand Down Expand Up @@ -501,6 +504,7 @@ protected Object doInBackground() throws Exception {
outputFileName = getEmbedWmPanel().getOutputWmFileTextField().getText();
outputFile = new File(outputFileName);

OpenStegoBulkException bulkException = new OpenStegoBulkException();
for (int i = 0; i < inputFileList.size(); i++) {
setProgress(i * 100 / inputFileList.size());
inputFile = inputFileList.get(i);
Expand Down Expand Up @@ -529,10 +533,15 @@ protected Object doInBackground() throws Exception {
}

processCount++;
wmData = openStego.embedMark(sigFileName == null || sigFileName.equals("") ? null : new File(sigFileName), inputFile,
outputFileName);
CommonUtil.writeFile(wmData, outputFileName);
try {
wmData = openStego.embedMark(sigFileName == null || sigFileName.equals("") ? null : new File(sigFileName), inputFile,
outputFileName);
CommonUtil.writeFile(wmData, outputFileName);
} catch (OpenStegoException e) {
bulkException.add(inputFile.getName(), e);
}
}
bulkException.throwIfRequired();

return new Integer[]{processCount, skipCount};
}
Expand Down Expand Up @@ -826,22 +835,26 @@ private void showHelpAbout() {
* @param ex Exception to be handled
*/
private void handleException(Throwable ex) {
String msg;
Object msg;

if (ex instanceof OutOfMemoryError) {
msg = labelUtil.getString("err.memory.full");
} else if (ex instanceof OpenStegoException) {
msg = ex.getMessage();
} else if (ex instanceof OpenStegoBulkException) {
msg = getBulkMessage((OpenStegoBulkException) ex);
} else {
Throwable cause = ex.getCause();
if (cause instanceof OpenStegoException) {
msg = cause.getMessage();
} else if (cause instanceof OpenStegoBulkException) {
msg = getBulkMessage((OpenStegoBulkException) cause);
} else {
msg = ex.getMessage();
}
}

if ((msg == null) || (msg.trim().equals(""))) {
if (msg == null || (msg instanceof String && ((String) msg).trim().equals(""))) {
StringWriter writer = new StringWriter();
ex.printStackTrace(new PrintWriter(writer));
msg = writer.toString();
Expand All @@ -851,6 +864,35 @@ private void handleException(Throwable ex) {
JOptionPane.showMessageDialog(this, msg, labelUtil.getString("gui.msg.title.err"), JOptionPane.ERROR_MESSAGE);
}

/**
* Helper method to build single output component out of all exceptions within a Bulk Exception
*
* @param ex Bulk Exception
* @return Output message component
*/
private Object getBulkMessage(OpenStegoBulkException ex) {
int len = ex.getExceptions().size();
if (len == 1) {
return ex.getExceptions().get(0);
}

String prefix = "<html><head><style type='text/css'>" +
"table, th, td { border: 1px solid #333; }" +
"table { border-width: 0 0 1px 1px }" +
"th, td { border-width: 1px 1px 0 0 }" +
"td { background-color: white }" +
"</style></head><body><table border='0' cellspacing='0' cellpadding='5'>";
StringBuilder sb = new StringBuilder(prefix).append("<tr><th>")
.append(labelUtil.getString("gui.msg.err.header.file")).append("</th><th>")
.append(labelUtil.getString("gui.msg.err.header.error")).append("</th></tr>");
for (int i = 0; i < ex.getKeys().size(); i++) {
sb.append("<tr><td>").append(ex.getKeys().get(i)).append("</td><td>")
.append(ex.getExceptions().get(i).getMessage()).append("</td></tr>");
}
sb.append("</table></body></html>");
return new JLabel(sb.toString());
}

/**
* Method to check whether value is provided or not; and display message box in case it is not provided
*
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/i18n/DWTDugadPluginLabels.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ plugin.description = Digital watermarking plugin using DWT (Discrete Wavelet Tra
# Error messages
err.cover.missing = Cover file is not provided
err.signature.invalid = Signature file is invalid
err.file.too.small = File size is not enough to embed the watermark

# Labels for command line interface
plugin.usage = Digital watermarking plugin based on DWT algorithm by Dugad for OpenStego.\n\
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/i18n/DWTKimPluginLabels.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ plugin.description = Digital watermarking plugin using DWT (Discrete Wavelet Tra
err.cover.missing = Cover file is not provided
err.image.decompLevel.notEnough = Image decomposition levels are not enough to embed the watermark
err.signature.invalid = Signature file is invalid
err.file.too.small = File size is not enough to embed the watermark

# Labels for command line interface
plugin.usage = Digital watermarking plugin based on DWT algorithm by Kim for\n\
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/i18n/OpenStegoLabels.properties
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ gui.msg.title.results = Results
gui.msg.err.browserLaunch = Error occurred while launching browser
gui.msg.err.mandatoryCheck = Please provide the value for {0}
gui.msg.warn.fileExists = File {0} already exists. Overwrite?
gui.msg.err.header.file = File
gui.msg.err.header.error = Error

gui.msg.err.dhEmbed.passwordMismatch = Password does not match the Confirm password
gui.msg.err.dhEmbed.coverFileNotFound = No match found for cover file: {0}
Expand Down Expand Up @@ -324,3 +326,4 @@ cmd.warn.stegoFileIgnored = WARNING: Stegofile name has been ignored, because mu
cmd.label.purpose.caption = Purpose:
cmd.label.purpose.DATA_HIDING = Data Hiding
cmd.label.purpose.WATERMARKING = Watermarking
cmd.label.bulkerror.header = Some files failed processing:

0 comments on commit 9c86c50

Please sign in to comment.