1
Fork 0
mirror of https://github.com/Steffo99/unimore-oop-2020-cleaver.git synced 2024-11-25 17:44:20 +00:00

I have done enough for tonight

This commit is contained in:
Steffo 2020-01-08 01:16:15 +01:00
parent b90693550a
commit 1c46967d58
29 changed files with 334 additions and 425 deletions

View file

@ -4,11 +4,9 @@ import eu.steffo.cleaver.gui.panels.rows.CreateJobButtonRow;
import eu.steffo.cleaver.gui.panels.rows.option.CompressRow;
import eu.steffo.cleaver.gui.panels.rows.option.CryptRow;
import eu.steffo.cleaver.gui.panels.rows.option.SplitRow;
import eu.steffo.cleaver.logic.config.*;
import eu.steffo.cleaver.logic.job.ChopJob;
import eu.steffo.cleaver.logic.job.Job;
import eu.steffo.cleaver.logic.config.CompressConfig;
import eu.steffo.cleaver.logic.config.CryptConfig;
import eu.steffo.cleaver.logic.config.SplitConfig;
import javax.swing.*;
import java.awt.event.ActionListener;
@ -85,7 +83,7 @@ public class ChopPanel extends CreateJobPanel {
}
for(File file : fileSelectPanel.getSelectedFiles()) {
SplitConfig sc;
ISplitConfig sc;
try {
sc = splitRow.getSplitConfig(file.length());
} catch (NumberFormatException exc) {
@ -93,9 +91,9 @@ public class ChopPanel extends CreateJobPanel {
return;
}
CryptConfig cc = cryptRow.getCryptConfig();
ICryptConfig cc = cryptRow.getCryptConfig();
CompressConfig zc = compressRow.getCompressConfig();
ICompressConfig zc = compressRow.getCompressConfig();
Job job = new ChopJob(file, sc, cc, zc, onProgressChange);
jobs.add(job);

View file

@ -1,9 +1,7 @@
package eu.steffo.cleaver.gui.panels;
import eu.steffo.cleaver.logic.config.*;
import eu.steffo.cleaver.logic.job.Job;
import eu.steffo.cleaver.logic.config.CompressConfig;
import eu.steffo.cleaver.logic.config.CryptConfig;
import eu.steffo.cleaver.logic.config.SplitConfig;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
@ -82,15 +80,15 @@ public class JobsTablePanel extends JPanel {
case 1:
return job.getFile().getAbsolutePath();
case 2:
SplitConfig s = job.getSplitConfig();
ISplitConfig s = job.getSplitConfig();
if(s == null) return "";
return s.toString();
case 3:
CryptConfig k = job.getCryptConfig();
ICryptConfig k = job.getCryptConfig();
if(k == null) return "";
return k.toString();
case 4:
CompressConfig c = job.getCompressConfig();
ICompressConfig c = job.getCompressConfig();
if(c == null) return "";
return c.toString();
case 5:

View file

@ -1,11 +1,12 @@
package eu.steffo.cleaver.gui.panels.rows.option;
import eu.steffo.cleaver.logic.config.CompressConfig;
import eu.steffo.cleaver.logic.config.DeflateConfig;
import eu.steffo.cleaver.logic.config.ICompressConfig;
import javax.swing.*;
/**
* A {@link OptionRow} allowing the {@link CompressConfig configuration of the compress step} of the file chop process.
* A {@link OptionRow} allowing the {@link DeflateConfig configuration of the compress step} of the file chop process.
*
* @see eu.steffo.cleaver.gui.panels.ChopPanel
*/
@ -32,17 +33,17 @@ public class CompressRow extends OptionRow {
}
/**
* Create a {@link CompressConfig} from the settings in this {@link OptionRow}.
* @return The resulting {@link CompressConfig}, or {@literal null} if the {@link #compressionCheckBox} is unticked.
* Create a {@link DeflateConfig} from the settings in this {@link OptionRow}.
* @return The resulting {@link DeflateConfig}, or {@literal null} if the {@link #compressionCheckBox} is unticked.
*/
public CompressConfig getCompressConfig() {
public ICompressConfig getCompressConfig() {
if(!compressionCheckBox.isSelected()) {
return null;
}
return new CompressConfig();
return new DeflateConfig();
}
public void setCompressConfig(CompressConfig cfg) {
public void setCompressConfig(DeflateConfig cfg) {
if(cfg == null) {
compressionCheckBox.setSelected(false);
}

View file

@ -1,11 +1,12 @@
package eu.steffo.cleaver.gui.panels.rows.option;
import eu.steffo.cleaver.logic.config.CryptConfig;
import eu.steffo.cleaver.logic.config.PasswordConfig;
import eu.steffo.cleaver.logic.config.ICryptConfig;
import javax.swing.*;
/**
* A {@link OptionRow} allowing the {@link CryptConfig configuration of the crypt step} of the file chop process.
* A {@link OptionRow} allowing the {@link PasswordConfig configuration of the crypt step} of the file chop process.
*
* @see eu.steffo.cleaver.gui.panels.ChopPanel
*/
@ -65,14 +66,14 @@ public class CryptRow extends OptionRow {
}
/**
* Create a {@link CryptConfig} from the settings in this {@link OptionRow}.
* @return The resulting {@link CryptConfig}, or {@literal null} if the {@link #cryptCheckBox} is unticked.
* Create a {@link PasswordConfig} from the settings in this {@link OptionRow}.
* @return The resulting {@link PasswordConfig}, or {@literal null} if the {@link #cryptCheckBox} is unticked.
*/
public CryptConfig getCryptConfig() {
public ICryptConfig getCryptConfig() {
if(!cryptCheckBox.isSelected()) {
return null;
}
return new CryptConfig(keyTextField.getText());
return new PasswordConfig(keyTextField.getText());
}
@Override

View file

@ -1,11 +1,11 @@
package eu.steffo.cleaver.gui.panels.rows.option;
import eu.steffo.cleaver.logic.config.CryptConfig;
import eu.steffo.cleaver.logic.config.PasswordConfig;
import javax.swing.*;
/**
* A {@link OptionRow} allowing the {@link CryptConfig configuration of the crypt step} of the file stitch process.
* A {@link OptionRow} allowing the {@link PasswordConfig configuration of the crypt step} of the file stitch process.
*
* This configuration is used only if the selected *.chp file specifies that the *.cXX are encrypted.
*

View file

@ -1,15 +1,16 @@
package eu.steffo.cleaver.gui.panels.rows.option;
import eu.steffo.cleaver.logic.config.SplitByPartsConfig;
import eu.steffo.cleaver.logic.config.SplitBySizeConfig;
import eu.steffo.cleaver.logic.config.SplitConfig;
import eu.steffo.cleaver.logic.config.PartsConfig;
import eu.steffo.cleaver.logic.config.ISplitConfig;
import eu.steffo.cleaver.logic.config.SizeConfig;
import eu.steffo.cleaver.logic.config.IConfig;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
/**
* A {@link OptionRow} allowing the {@link SplitConfig configuration of the split step} of the file chop process.
* A {@link OptionRow} allowing the {@link IConfig configuration of the split step} of the file chop process.
*
* @see eu.steffo.cleaver.gui.panels.ChopPanel
*/
@ -149,19 +150,19 @@ public class SplitRow extends OptionRow {
}
/**
* Create a {@link SplitConfig} from the settings in this {@link OptionRow}.
* @param fileSize The size of the file that the {@link SplitConfig} is being generated for.
* @return The resulting {@link SplitConfig}, or {@literal null} if the {@link #splitCheckBox} is unticked.
* Create a {@link IConfig} from the settings in this {@link OptionRow}.
* @param fileSize The size of the file that the {@link IConfig} is being generated for.
* @return The resulting {@link IConfig}, or {@literal null} if the {@link #splitCheckBox} is unticked.
*/
public SplitConfig getSplitConfig(long fileSize) throws NumberFormatException {
public ISplitConfig getSplitConfig(long fileSize) throws NumberFormatException {
if(!splitCheckBox.isSelected()) {
return null;
}
else if(!sizeTextField.getText().equals("")) {
return new SplitBySizeConfig(Integer.parseInt(sizeTextField.getText()), fileSize);
return new SizeConfig(Long.parseLong(sizeTextField.getText()));
}
else if(!partsTextField.getText().equals("")) {
return new SplitByPartsConfig(Integer.parseInt(partsTextField.getText()), fileSize);
return new PartsConfig(Integer.parseInt(partsTextField.getText()));
}
else return null;
}

View file

@ -1,13 +0,0 @@
package eu.steffo.cleaver.logic.config;
import eu.steffo.cleaver.logic.job.Job;
/**
* A class containing the configuration for the compression step of a {@link Job Job}.
*/
public class CompressConfig {
@Override
public String toString() {
return "Yes (Deflate)";
}
}

View file

@ -0,0 +1,11 @@
package eu.steffo.cleaver.logic.config;
/**
* A {@link IConfig} for compressing a file with the <a href="https://en.wikipedia.org/wiki/DEFLATE">Deflate</a> algorithm.
*/
public class DeflateConfig implements ICompressConfig {
@Override
public String toString() {
return "Yes (Deflate)";
}
}

View file

@ -0,0 +1,7 @@
package eu.steffo.cleaver.logic.config;
/**
* A {@link IConfig} for the Compress step of the {@link eu.steffo.cleaver.logic.job.ChopJob Chop}/{@link eu.steffo.cleaver.logic.job.StitchJob Stitch} process.
*/
public interface ICompressConfig extends IConfig {
}

View file

@ -0,0 +1,14 @@
package eu.steffo.cleaver.logic.config;
import eu.steffo.cleaver.logic.job.Job;
/**
* An interface for the configuration of a step of a {@link Job Job}.
*/
public interface IConfig {
/**
* @return The string representation of the {@link IConfig}, to be used in the jobs table.
* @see eu.steffo.cleaver.gui.panels.JobsTablePanel
*/
String toString();
}

View file

@ -0,0 +1,7 @@
package eu.steffo.cleaver.logic.config;
/**
* A {@link IConfig} for the Crypt step of the {@link eu.steffo.cleaver.logic.job.ChopJob Chop}/{@link eu.steffo.cleaver.logic.job.StitchJob Stitch} process.
*/
public interface ICryptConfig extends IConfig {
}

View file

@ -0,0 +1,7 @@
package eu.steffo.cleaver.logic.config;
/**
* A {@link IConfig} for the Split step of the {@link eu.steffo.cleaver.logic.job.ChopJob Chop}/{@link eu.steffo.cleaver.logic.job.StitchJob Stitch} process.
*/
public interface ISplitConfig extends IConfig {
}

View file

@ -1,53 +0,0 @@
package eu.steffo.cleaver.logic.config;
/**
* A {@link SplitConfig} created by reading a *.chp file, containing the number of parts and their size, but not the resulting file size.
*/
public class MergeConfig extends SplitConfig {
/**
* The size of the parts the file was split in.
*/
private long partSize;
/**
* The number of parts the file was split in.
*/
private int parts;
/**
* The total size of the original file.
*/
private long totalSize;
/**
* Construct a new MergeConfig.
* @param partSize The size of the parts the file was split in.
* @param parts The number of parts the file was split in.
* @param totalSize The total size of the original file.
*/
public MergeConfig(long partSize, int parts, long totalSize) {
this.partSize = partSize;
this.parts = parts;
this.totalSize = totalSize;
}
@Override
public long getPartSize() {
return partSize;
}
@Override
public int getPartCount() {
return parts;
}
@Override
public long getTotalSize() {
return totalSize;
}
@Override
public String toString() {
return String.format("%d parts (%d bytes)", parts, partSize);
}
}

View file

@ -0,0 +1,28 @@
package eu.steffo.cleaver.logic.config;
/**
* A {@link IConfig} for splitting a file in a specific number of parts.
*/
public class PartsConfig implements ISplitConfig {
/**
* The number of parts the file should be split in.
*/
private int parts;
/**
* Construct a new SplitByPartsConfig.
* @param parts The number of parts the file should be split in.
*/
public PartsConfig(int parts) {
this.parts = parts;
}
@Override
public String toString() {
return String.format("%d parts", this.parts);
}
public int getPartCount() {
return parts;
}
}

View file

@ -1,18 +1,16 @@
package eu.steffo.cleaver.logic.config;
import eu.steffo.cleaver.logic.job.Job;
/**
* A class containing the configuration for the encryption/decryption step of a {@link Job Job}.
* A config for encrypting a file with an arbitrary length password.
*/
public class CryptConfig {
public class PasswordConfig implements ICryptConfig {
protected final String key;
/**
* Construct a new CryptConfig with a specific encryption key.
* @param key The encryption key.
*/
public CryptConfig(String key) {
public PasswordConfig(String key) {
this.key = key;
}

View file

@ -0,0 +1,28 @@
package eu.steffo.cleaver.logic.config;
/**
* A {@link IConfig} for splitting a file in parts of a specific part size.
*/
public class SizeConfig implements ISplitConfig {
/**
* The size of the parts to split the file in.
*/
private long partSize;
/**
* Construct a new SplitBySizeConfig.
* @param partSize The size of the parts to split the file in.
*/
public SizeConfig(long partSize) {
this.partSize = partSize;
}
@Override
public String toString() {
return String.format("%d bytes", this.partSize);
}
public long getPartSize() {
return partSize;
}
}

View file

@ -1,43 +0,0 @@
package eu.steffo.cleaver.logic.config;
public class SplitByPartsConfig extends SplitConfig {
/**
* The number of parts the file should be split in.
*/
private int parts;
/**
* The total size of the file to split.
*/
private long totalSize;
/**
* Construct a new SplitByPartsConfig.
* @param parts The number of parts the file should be split in.
* @param totalSize The total size of the file to split.
*/
public SplitByPartsConfig(int parts, long totalSize) {
this.parts = parts;
this.totalSize = totalSize;
}
@Override
public String toString() {
return String.format("%d parts", this.parts);
}
@Override
public long getPartSize() {
return (int)Math.ceil((double) totalSize / (double)parts);
}
@Override
public int getPartCount() {
return parts;
}
@Override
public long getTotalSize() {
return totalSize;
}
}

View file

@ -1,46 +0,0 @@
package eu.steffo.cleaver.logic.config;
/**
* A {@link SplitConfig} for splitting a file in parts of a specific part size.
*/
public class SplitBySizeConfig extends SplitConfig {
/**
* The size of the parts to split the file in.
*/
private long partSize;
/**
* The total size of the file to split.
*/
private long totalSize;
/**
* Construct a new SplitBySizeConfig.
* @param partSize The size of the parts to split the file in.
* @param totalSize The total size of the file to split.
*/
public SplitBySizeConfig(long partSize, long totalSize) {
this.partSize = partSize;
this.totalSize = totalSize;
}
@Override
public String toString() {
return String.format("%d bytes", this.partSize);
}
@Override
public long getPartSize() {
return partSize;
}
@Override
public int getPartCount() {
return (int)Math.ceil((double) totalSize / (double)partSize);
}
@Override
public long getTotalSize() {
return totalSize;
}
}

View file

@ -1,29 +0,0 @@
package eu.steffo.cleaver.logic.config;
import eu.steffo.cleaver.logic.job.Job;
/**
* A class containing the configuration for the split/merge step of a {@link Job Job}.
*/
public abstract class SplitConfig {
/**
* @return The size in bytes of a single part of the file.
*/
public abstract long getPartSize();
/**
* @return The number of parts the file should be split in.
*/
public abstract int getPartCount();
/**
* @return The total size of the original file.
*/
public abstract long getTotalSize();
/**
* @return The string representation of the {@link SplitConfig}, to be used in the jobs table.
* @see eu.steffo.cleaver.gui.panels.JobsTablePanel
*/
public abstract String toString();
}

View file

@ -1,15 +1,12 @@
package eu.steffo.cleaver.logic.job;
import eu.steffo.cleaver.errors.ProgrammingError;
import eu.steffo.cleaver.logic.config.CompressConfig;
import eu.steffo.cleaver.logic.config.CryptConfig;
import eu.steffo.cleaver.logic.stream.output.CleaverCryptOutputStream;
import eu.steffo.cleaver.logic.config.*;
import eu.steffo.cleaver.logic.stream.output.*;
import eu.steffo.cleaver.logic.progress.ErrorProgress;
import eu.steffo.cleaver.logic.progress.FinishedProgress;
import eu.steffo.cleaver.logic.progress.Progress;
import eu.steffo.cleaver.logic.progress.WorkingProgress;
import eu.steffo.cleaver.logic.config.SplitConfig;
import eu.steffo.cleaver.logic.stream.output.CleaverSplitFileOutputStream;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@ -21,7 +18,6 @@ import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.util.zip.DeflaterOutputStream;
/**
* A {@link Job} that converts regular files into <i>chopped</i> (*.chp + *.cXX) files.
@ -29,20 +25,20 @@ import java.util.zip.DeflaterOutputStream;
public class ChopJob extends Job {
private final File file;
private final SplitConfig splitConfig;
private final CryptConfig cryptConfig;
private final CompressConfig compressConfig;
private final ISplitConfig splitConfig;
private final ICryptConfig cryptConfig;
private final ICompressConfig compressConfig;
/**
* Create a new ChopJob (with progress updates support).
* @param file The file to be chopped.
* @param splitConfig The configuration for the split step.
* @param cryptConfig The configuration for the crypt step.
* @param compressConfig The configuration for the compress step.
* @param splitConfig The configuration for the Split step.
* @param cryptConfig The configuration for the Crypt step.
* @param compressConfig The configuration for the Compress step.
* @param onProgressChange A {@link Runnable} that should be invoked when {@link #setProgress(Progress)} is called.
* @see Job#Job(Runnable)
*/
public ChopJob(File file, SplitConfig splitConfig, CryptConfig cryptConfig, CompressConfig compressConfig, Runnable onProgressChange) {
public ChopJob(File file, ISplitConfig splitConfig, ICryptConfig cryptConfig, ICompressConfig compressConfig, Runnable onProgressChange) {
super(onProgressChange);
this.file = file;
this.splitConfig = splitConfig;
@ -53,13 +49,13 @@ public class ChopJob extends Job {
/**
* Create a new ChopJob (without progress updates support).
* @param file The file to be chopped.
* @param splitConfig The configuration for the split step.
* @param cryptConfig The configuration for the crypt step.
* @param compressConfig The configuration for the compress step.
* @see ChopJob#ChopJob(File, SplitConfig, CryptConfig, CompressConfig, Runnable)
* @param splitConfig The configuration for the Split step.
* @param cryptConfig The configuration for the Crypt step.
* @param compressConfig The configuration for the Compress step.
* @see ChopJob#ChopJob(File, ISplitConfig, ICryptConfig, ICompressConfig, Runnable)
* @see Job#Job()
*/
public ChopJob(File file, SplitConfig splitConfig, CryptConfig cryptConfig, CompressConfig compressConfig) {
public ChopJob(File file, ISplitConfig splitConfig, ICryptConfig cryptConfig, ICompressConfig compressConfig) {
this(file, splitConfig, cryptConfig, compressConfig, null);
}
@ -74,17 +70,17 @@ public class ChopJob extends Job {
}
@Override
public SplitConfig getSplitConfig() {
public ISplitConfig getSplitConfig() {
return splitConfig;
}
@Override
public CryptConfig getCryptConfig() {
public ICryptConfig getCryptConfig() {
return cryptConfig;
}
@Override
public CompressConfig getCompressConfig() {
public ICompressConfig getCompressConfig() {
return compressConfig;
}
@ -94,19 +90,22 @@ public class ChopJob extends Job {
InputStream inputStream = new FileInputStream(file);
OutputStream outputStream;
if(splitConfig != null) {
outputStream = new CleaverSplitFileOutputStream(file.getAbsolutePath(), splitConfig.getPartSize());
if(splitConfig instanceof SizeConfig) {
outputStream = new CleaverSplitFileOutputStream(file.getAbsolutePath(), ((SizeConfig)splitConfig).getPartSize());
}
else if(splitConfig instanceof PartsConfig) {
outputStream = new CleaverForkFileOutputStream(file.getAbsolutePath(), ((PartsConfig)splitConfig).getPartCount());
}
else {
outputStream = new FileOutputStream(String.format("%s.c0", file.getAbsolutePath()));
outputStream = new CleaverSimpleFileOutputStream(file.getAbsolutePath());
}
if(compressConfig != null) {
outputStream = new DeflaterOutputStream(outputStream);
if(compressConfig instanceof DeflateConfig) {
outputStream = new CleaverDeflaterOutputStream(outputStream);
}
if(cryptConfig != null) {
outputStream = new CleaverCryptOutputStream(outputStream, cryptConfig.getKey());
if(cryptConfig instanceof PasswordConfig) {
outputStream = new CleaverCryptOutputStream(outputStream, ((PasswordConfig)cryptConfig).getKey());
}
//Create the .chp file
@ -121,26 +120,6 @@ public class ChopJob extends Job {
Element root = doc.createElement("Cleaver");
doc.appendChild(root);
Element original = doc.createElement("Original");
original.setTextContent(file.getName());
root.appendChild(original);
if(splitConfig != null) {
root.appendChild(splitConfig.toElement(doc));
}
if(compressConfig != null) {
root.appendChild(compressConfig.toElement(doc));
}
if(cryptConfig != null) {
root.appendChild(cryptConfig.toElement(doc));
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(String.format("%s.chp", file.getAbsolutePath()));
transformer.transform(source, result);
//Pipe everything to the output
int bytesUntilNextUpdate = 2048;
this.setProgress(new WorkingProgress());
@ -158,6 +137,14 @@ public class ChopJob extends Job {
inputStream.close();
outputStream.close();
root.appendChild(((ICleaverOutputStream)outputStream).toElement(doc));
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(String.format("%s.chp", file.getAbsolutePath()));
transformer.transform(source, result);
this.setProgress(new FinishedProgress());
} catch (Throwable e) {
e.printStackTrace();

View file

@ -3,11 +3,9 @@ package eu.steffo.cleaver.logic.job;
import java.io.File;
import javax.swing.SwingUtilities;
import eu.steffo.cleaver.logic.config.CompressConfig;
import eu.steffo.cleaver.logic.config.CryptConfig;
import eu.steffo.cleaver.logic.config.*;
import eu.steffo.cleaver.logic.progress.NotStartedProgress;
import eu.steffo.cleaver.logic.progress.Progress;
import eu.steffo.cleaver.logic.config.SplitConfig;
/**
* A {@link Thread} that allows access to the basic .
@ -62,19 +60,19 @@ public abstract class Job extends Thread {
}
/**
* @return The {@link SplitConfig} of the job. If {@literal null}, the job shouldn't handle file splitting/merging.
* @return The {@link IConfig} for the Split step of the job. If {@literal null}, the job shouldn't handle file splitting/merging.
*/
public abstract SplitConfig getSplitConfig();
public abstract ISplitConfig getSplitConfig();
/**
* @return The {@link CryptConfig} of the job. If {@literal null}, the job shouldn't handle file encryption/decryption.
* @return The {@link IConfig} for the Crypt step of the job. If {@literal null}, the job shouldn't handle file encryption/decryption.
*/
public abstract CryptConfig getCryptConfig();
public abstract ICryptConfig getCryptConfig();
/**
* @return The {@link CompressConfig} of the job. If {@literal null}, the job shouldn't handle file compression/decompression.
* @return The {@link IConfig} for the Compress step of the job. If {@literal null}, the job shouldn't handle file compression/decompression.
*/
public abstract CompressConfig getCompressConfig();
public abstract ICompressConfig getCompressConfig();
/**
* Set the progress of the job to a different value.

View file

@ -2,10 +2,7 @@ package eu.steffo.cleaver.logic.job;
import eu.steffo.cleaver.errors.ChpFileError;
import eu.steffo.cleaver.errors.ProgrammingError;
import eu.steffo.cleaver.logic.config.CompressConfig;
import eu.steffo.cleaver.logic.config.CryptConfig;
import eu.steffo.cleaver.logic.config.MergeConfig;
import eu.steffo.cleaver.logic.config.SplitConfig;
import eu.steffo.cleaver.logic.config.*;
import eu.steffo.cleaver.logic.stream.input.CryptInputStream;
import eu.steffo.cleaver.logic.progress.ErrorProgress;
import eu.steffo.cleaver.logic.progress.FinishedProgress;
@ -25,15 +22,16 @@ import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.util.zip.InflaterInputStream;
/**
* A {@link Job} that converts <i>chopped</i> (*.chp + *.cXX) files back into regular files.
*/
public class StitchJob extends Job {
private File resultFile;
private File chpFile;
private SplitConfig splitConfig = null;
private CryptConfig cryptConfig = null;
private CompressConfig compressConfig = null;
private ISplitConfig splitConfig = null;
private ICryptConfig cryptConfig = null;
private ICompressConfig compressConfig = null;
/**
* Construct a StitchJob, specifying the *.chp file to import the settings from.
@ -84,17 +82,17 @@ public class StitchJob extends Job {
}
@Override
public SplitConfig getSplitConfig() {
public ISplitConfig getSplitConfig() {
return splitConfig;
}
@Override
public CryptConfig getCryptConfig() {
public ICryptConfig getCryptConfig() {
return cryptConfig;
}
@Override
public CompressConfig getCompressConfig() {
public ICompressConfig getCompressConfig() {
return compressConfig;
}
@ -125,104 +123,17 @@ public class StitchJob extends Job {
}
/**
* Read a {@link Document} and set the {@link SplitConfig}, {@link CryptConfig} and {@link CompressConfig} of this job accordingly.
* Read a {@link Document} and set the {@link IConfig}, {@link PasswordConfig} and {@link DeflateConfig} of this job accordingly.
* @param doc The {@link Document} to be read.
* @param cryptKey The encryption key to use in the {@link CryptConfig}.
* @param cryptKey The encryption key to use in the {@link PasswordConfig}.
* @throws ChpFileError If there's an error while parsing the *.chp file.
*/
protected void parseChp(Document doc, String cryptKey) throws ChpFileError {
Element root = doc.getDocumentElement();
NodeList originals = root.getElementsByTagName("Original");
NodeList splits = root.getElementsByTagName("Split");
NodeList crypts = root.getElementsByTagName("Crypt");
NodeList compresses = root.getElementsByTagName("Compress");
Node originalNode = originals.item(0);
Node splitNode = splits.item(0);
Node cryptNode = crypts.item(0);
Node compressNode = compresses.item(0);
if(originalNode == null) {
throw new ChpFileError("No original filename found (<Original> tag)");
}
Element original = (Element)originalNode;
//The resulting file will be in the same directory of the *.chp file
resultFile = new File(chpFile.getAbsoluteFile().getParentFile().getAbsolutePath().concat("/" + original.getTextContent()));
if(splitNode != null) {
Element split = (Element)splitNode;
long partSize;
try {
partSize = Long.parseLong(split.getAttribute("part-size"));
} catch(NumberFormatException e) {
throw new ChpFileError("Corrupt part size data.");
}
int parts;
try {
parts = Integer.parseInt(split.getAttribute("parts"));
} catch(NumberFormatException e) {
throw new ChpFileError("Corrupt parts data.");
}
long totalSize;
try {
totalSize = Long.parseLong(split.getAttribute("total-size"));
} catch(NumberFormatException e) {
throw new ChpFileError("Corrupt total size data.");
}
splitConfig = new MergeConfig(partSize, parts, totalSize);
}
if(cryptNode != null) {
cryptConfig = new CryptConfig(cryptKey);
}
if(compressNode != null) {
compressConfig = new CompressConfig();
}
//TODO
}
@Override
public void run() {
try {
InputStream inputStream;
OutputStream outputStream = new FileOutputStream(resultFile);
if (splitConfig != null) {
inputStream = new CleaverSplitFileInputStream(resultFile.getPath(), splitConfig.getPartSize());
}
else {
inputStream = new FileInputStream(String.format("%s.c0", resultFile.getAbsolutePath()));
}
if (compressConfig != null) {
inputStream = new InflaterInputStream(inputStream);
}
if (cryptConfig != null) {
inputStream = new CryptInputStream(inputStream, cryptConfig.getKey());
}
//Pipe everything to the output
int bytesUntilNextUpdate = 2048;
this.setProgress(new WorkingProgress());
int i;
while((i = inputStream.read()) != -1) {
outputStream.write(i);
bytesUntilNextUpdate -= 1;
if(bytesUntilNextUpdate <= 0) {
this.setProgress(new WorkingProgress((float)(resultFile.length() - inputStream.available()) / (float)resultFile.length()));
bytesUntilNextUpdate = 2048;
}
}
this.setProgress(new FinishedProgress());
} catch (Throwable e) {
e.printStackTrace();
this.setProgress(new ErrorProgress(e));
}
//TODO
}
}

View file

@ -78,7 +78,7 @@ public class CleaverCryptOutputStream extends FilterOutputStream implements ICle
/**
* Generate a new <a href="https://en.wikipedia.org/wiki/Initialization_vector">Initialization Vector</a> with the specified size.
* @param size The size of the initialization vector.
* @param size The size in bytes of the initialization vector.
* @return The generated IV.
*/
protected IvParameterSpec generateIV(int size) {
@ -103,15 +103,18 @@ public class CleaverCryptOutputStream extends FilterOutputStream implements ICle
* @throws NoSuchAlgorithmException If the {@link #ENCRYPTION_ALGORITHM} is invalid.
* @throws InvalidKeySpecException If the generated {@link KeySpec} is invalid.
*/
private void createCipher(char[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidAlgorithmParameterException, InvalidKeyException {
private void initCipher(char[] key) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidAlgorithmParameterException, InvalidKeyException {
//Setup the cipher object
cipher = Cipher.getInstance(getTransformationString());
//"Convert" the secret key to a AES secret key
SecretKey aes = new SecretKeySpec(generatePasswordKey(key).getEncoded(), ENCRYPTION_ALGORITHM);
//Generate the initialization vector
IvParameterSpec iv = generateIV(1);
//Init the cipher instance
cipher.init(Cipher.ENCRYPT_MODE, aes, generateIV(1));
cipher.init(Cipher.ENCRYPT_MODE, aes, iv);
}
/**
@ -123,8 +126,9 @@ public class CleaverCryptOutputStream extends FilterOutputStream implements ICle
public CleaverCryptOutputStream(OutputStream out, String key) {
super(out);
try {
createCipher(key.toCharArray());
initCipher(key.toCharArray());
} catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeySpecException | InvalidAlgorithmParameterException | InvalidKeyException e) {
//This should never happen...
e.printStackTrace();
}
}
@ -169,6 +173,10 @@ public class CleaverCryptOutputStream extends FilterOutputStream implements ICle
keyLengthAttr.setValue(Integer.toString(KEY_LENGTH));
element.setAttributeNode(keyLengthAttr);
Attr ivAttr = doc.createAttribute("iv");
ivAttr.setValue(Byte.toString(cipher.getIV()[0]));
element.setAttributeNode(ivAttr);
return element;
}
}

View file

@ -8,12 +8,12 @@ import java.io.OutputStream;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
public class CleaverCompressOutputStream extends DeflaterOutputStream implements ICleaverOutputStream {
public class CleaverDeflaterOutputStream extends DeflaterOutputStream implements ICleaverOutputStream {
/**
* Construct a new CleaverCompressOutputStream and ensure the passed {@link OutputStream} implements {@link ICleaverOutputStream}.
* @see DeflaterOutputStream#DeflaterOutputStream(OutputStream, Deflater, int, boolean)
*/
public CleaverCompressOutputStream(OutputStream out, Deflater def, int size, boolean syncFlush) {
public CleaverDeflaterOutputStream(OutputStream out, Deflater def, int size, boolean syncFlush) {
super(out, def, size, syncFlush);
if(!(out instanceof ICleaverOutputStream)) {
throw new IllegalArgumentException("The OutputStream passed to the CleaverCompressOutputStream must implement ICleaverOutputStream.");
@ -24,7 +24,7 @@ public class CleaverCompressOutputStream extends DeflaterOutputStream implements
* Construct a new CleaverCompressOutputStream and ensure the passed {@link OutputStream} implements {@link ICleaverOutputStream}.
* @see DeflaterOutputStream#DeflaterOutputStream(OutputStream, Deflater, int)
*/
public CleaverCompressOutputStream(OutputStream out, Deflater def, int size) {
public CleaverDeflaterOutputStream(OutputStream out, Deflater def, int size) {
super(out, def, size);
if(!(out instanceof ICleaverOutputStream)) {
throw new IllegalArgumentException("The OutputStream passed to the CleaverCompressOutputStream must implement ICleaverOutputStream.");
@ -35,7 +35,7 @@ public class CleaverCompressOutputStream extends DeflaterOutputStream implements
* Construct a new CleaverCompressOutputStream and ensure the passed {@link OutputStream} implements {@link ICleaverOutputStream}.
* @see DeflaterOutputStream#DeflaterOutputStream(OutputStream, Deflater, boolean)
*/
public CleaverCompressOutputStream(OutputStream out, Deflater def, boolean syncFlush) {
public CleaverDeflaterOutputStream(OutputStream out, Deflater def, boolean syncFlush) {
super(out, def, syncFlush);
if(!(out instanceof ICleaverOutputStream)) {
throw new IllegalArgumentException("The OutputStream passed to the CleaverCompressOutputStream must implement ICleaverOutputStream.");
@ -46,7 +46,7 @@ public class CleaverCompressOutputStream extends DeflaterOutputStream implements
* Construct a new CleaverCompressOutputStream and ensure the passed {@link OutputStream} implements {@link ICleaverOutputStream}.
* @see DeflaterOutputStream#DeflaterOutputStream(OutputStream, Deflater)
*/
public CleaverCompressOutputStream(OutputStream out, Deflater def) {
public CleaverDeflaterOutputStream(OutputStream out, Deflater def) {
super(out, def);
if(!(out instanceof ICleaverOutputStream)) {
throw new IllegalArgumentException("The OutputStream passed to the CleaverCompressOutputStream must implement ICleaverOutputStream.");
@ -57,7 +57,7 @@ public class CleaverCompressOutputStream extends DeflaterOutputStream implements
* Construct a new CleaverCompressOutputStream and ensure the passed {@link OutputStream} implements {@link ICleaverOutputStream}.
* @see DeflaterOutputStream#DeflaterOutputStream(OutputStream, boolean)
*/
public CleaverCompressOutputStream(OutputStream out, boolean syncFlush) {
public CleaverDeflaterOutputStream(OutputStream out, boolean syncFlush) {
super(out, syncFlush);
if(!(out instanceof ICleaverOutputStream)) {
throw new IllegalArgumentException("The OutputStream passed to the CleaverCompressOutputStream must implement ICleaverOutputStream.");
@ -68,31 +68,20 @@ public class CleaverCompressOutputStream extends DeflaterOutputStream implements
* Construct a new CleaverCompressOutputStream and ensure the passed {@link OutputStream} implements {@link ICleaverOutputStream}.
* @see DeflaterOutputStream#DeflaterOutputStream(OutputStream)
*/
public CleaverCompressOutputStream(OutputStream out) {
public CleaverDeflaterOutputStream(OutputStream out) {
super(out);
if(!(out instanceof ICleaverOutputStream)) {
throw new IllegalArgumentException("The OutputStream passed to the CleaverCompressOutputStream must implement ICleaverOutputStream.");
}
}
/**
* @return The name of the used compression algorithm (currently only {@literal Deflate}).
*/
public String getAlgorithm() {
return "Deflate";
}
@Override
public Element toElement(Document doc) {
Element element = doc.createElement("Compress");
Element element = doc.createElement("Deflate");
Element child = ((ICleaverOutputStream)out).toElement(doc);
element.appendChild(child);
Attr algorithmAttr = doc.createAttribute("algorithm");
algorithmAttr.setValue(getAlgorithm());
element.setAttributeNode(algorithmAttr);
return element;
}
}

View file

@ -0,0 +1,89 @@
package eu.steffo.cleaver.logic.stream.output;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.io.*;
/**
* A custom {@link OutputStream} that writes the bytes received in input in multiple files with a progressively increasing number (.c1, .c2, .c3, and so on).
*
* Bytes are written one at a time to the files in a round-robin format until the stream is exausted.
*/
public class CleaverForkFileOutputStream extends OutputStream implements ICleaverOutputStream {
private final String fileBaseName;
private FileOutputStream[] fileOutputStreams;
private int writeTo;
private long partSize;
/**
* Construct a CleaverForkFileOutputStream.
* @param fileBaseName The name of the files without the extension. If it is {@literal example}, the created files will be {@literal example.c1}, {@literal example.c2}, and so on.
* @param parts The number of parts to be created.
*/
public CleaverForkFileOutputStream(String fileBaseName, int parts) throws FileNotFoundException {
this.fileBaseName = fileBaseName;
this.fileOutputStreams = new FileOutputStream[parts];
for(int i = 0; i < parts; i++) {
File file = new File(String.format("%s.c%s", fileBaseName, i));
this.fileOutputStreams[i] = new FileOutputStream(file);
}
this.writeTo = 0;
this.partSize = 1;
}
@Override
public Element toElement(Document doc) {
Element element = doc.createElement("Fork");
element.setTextContent(fileBaseName);
Attr partSizeAttr = doc.createAttribute("part-size");
partSizeAttr.setValue(Long.toString(partSize));
element.setAttributeNode(partSizeAttr);
Attr partCountAttr = doc.createAttribute("parts");
partCountAttr.setValue(Long.toString(fileOutputStreams.length));
element.setAttributeNode(partCountAttr);
return element;
}
@Override
public void write(int b) throws IOException {
fileOutputStreams[writeTo].write(b);
writeTo += 1;
if(writeTo >= fileOutputStreams.length) {
writeTo = 0;
partSize += 1;
}
}
/**
* @return The name of the files without the extension. If it is {@literal example}, the created files will be {@literal example.c1}, {@literal example.c2}, and so on.
*/
public String getFileBaseName() {
return fileBaseName;
}
/**
* @return The current maximum size of a part, in bytes.
*/
public long getPartSize() {
return partSize;
}
/**
* @return The number of file parts to create.
*/
public int getParts() {
return fileOutputStreams.length;
}
/**
* @return The number of the next file where a byte should be written, from 0 to the number of parts -1.
*/
public int getWriteTo() {
return writeTo;
}
}

View file

@ -0,0 +1,24 @@
package eu.steffo.cleaver.logic.stream.output;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class CleaverSimpleFileOutputStream extends FileOutputStream implements ICleaverOutputStream {
private final String fileBaseName;
public CleaverSimpleFileOutputStream(String fileBaseName) throws FileNotFoundException {
super(String.format("%s.c0", fileBaseName));
this.fileBaseName = fileBaseName;
}
@Override
public Element toElement(Document doc) {
Element element = doc.createElement("Simple");
element.setTextContent(fileBaseName);
return element;
}
}

View file

@ -17,7 +17,6 @@ public class CleaverSplitFileOutputStream extends OutputStream implements ICleav
private final String fileBaseName;
private long currentByteCount;
private long maximumByteCount;
private long totalByteCount;
private int currentFileCount;
/**
@ -60,7 +59,6 @@ public class CleaverSplitFileOutputStream extends OutputStream implements ICleav
}
currentFileOutputStream.write(b);
currentByteCount += 1;
totalByteCount += 1;
}
@Override
@ -96,13 +94,6 @@ public class CleaverSplitFileOutputStream extends OutputStream implements ICleav
return currentFileCount;
}
/**
* @return The number of bytes that have already been written.
*/
public long getTotalByteCount() {
return totalByteCount;
}
@Override
public Element toElement(Document doc) {
Element element = doc.createElement("Split");
@ -116,10 +107,6 @@ public class CleaverSplitFileOutputStream extends OutputStream implements ICleav
partCountAttr.setValue(Long.toString(currentFileCount));
element.setAttributeNode(partCountAttr);
Attr totalSizeAttr = doc.createAttribute("total-size");
totalSizeAttr.setValue(Long.toString(totalByteCount));
element.setAttributeNode(totalSizeAttr);
return element;
}
}

View file

@ -11,5 +11,5 @@ public interface ICleaverOutputStream extends ICleaverStream {
* @param doc The {@link Document} the {@link Element} should be created in.
* @return The created {@link Element}.
*/
public Element toElement(Document doc);
Element toElement(Document doc);
}

View file

@ -13,9 +13,10 @@ open module eu.steffo.cleaver {
exports eu.steffo.cleaver.gui.panels;
exports eu.steffo.cleaver.gui.panels.rows;
exports eu.steffo.cleaver.gui.panels.rows.option;
exports eu.steffo.cleaver.logic;
exports eu.steffo.cleaver.logic.compress;
exports eu.steffo.cleaver.logic.crypt;
exports eu.steffo.cleaver.logic.progress;
exports eu.steffo.cleaver.logic.split;
exports eu.steffo.cleaver.logic.config;
exports eu.steffo.cleaver.logic.job;
exports eu.steffo.cleaver.logic.stream;
exports eu.steffo.cleaver.logic.stream.input;
exports eu.steffo.cleaver.logic.stream.output;
}