diff --git a/src/main/java/me/hatter/tools/tinyencrypt/TinyEncryptArgs.java b/src/main/java/me/hatter/tools/tinyencrypt/TinyEncryptArgs.java index 36b52ff..ed2f449 100644 --- a/src/main/java/me/hatter/tools/tinyencrypt/TinyEncryptArgs.java +++ b/src/main/java/me/hatter/tools/tinyencrypt/TinyEncryptArgs.java @@ -13,6 +13,9 @@ public class TinyEncryptArgs { @CommandLine.Option(names = {"-d", "--decrypt"}, description = "Decrypt file") boolean decrypt = false; + @CommandLine.Option(names = {"-s", "--show"}, description = "Show decrypted text in window") + boolean showInWindow = false; + @CommandLine.Option(names = {"-k", "--key"}, description = "Encrypt key") String key; diff --git a/src/main/java/me/hatter/tools/tinyencrypt/TinyEncryptMain.java b/src/main/java/me/hatter/tools/tinyencrypt/TinyEncryptMain.java index a536eb7..fd8fa48 100644 --- a/src/main/java/me/hatter/tools/tinyencrypt/TinyEncryptMain.java +++ b/src/main/java/me/hatter/tools/tinyencrypt/TinyEncryptMain.java @@ -164,7 +164,12 @@ public class TinyEncryptMain { if (tinyEncryptArgs.encrypt) { result = EncryptedFileUtil.encryptFile(config, tinyEncryptArgs.key, f, tinyEncryptArgs.compress, tinyEncryptArgs.comment); } else { - result = EncryptedFileUtil.decryptFile(config, f); + if (tinyEncryptArgs.showInWindow) { + EncryptedFileUtil.decryptInWindow(config, f); + result = false; // do not delete file + } else { + result = EncryptedFileUtil.decryptFile(config, f); + } } if (result && tinyEncryptArgs.removeFile) { log.info("Remove file: " + f); @@ -176,5 +181,6 @@ public class TinyEncryptMain { log.error(joe.getMessage()); log.debug(joe.getMessage(), joe); } + System.exit(0); } } diff --git a/src/main/java/me/hatter/tools/tinyencrypt/config/TinyEncryptConstant.java b/src/main/java/me/hatter/tools/tinyencrypt/config/TinyEncryptConstant.java index caad395..5d6c503 100644 --- a/src/main/java/me/hatter/tools/tinyencrypt/config/TinyEncryptConstant.java +++ b/src/main/java/me/hatter/tools/tinyencrypt/config/TinyEncryptConstant.java @@ -1,7 +1,7 @@ package me.hatter.tools.tinyencrypt.config; public class TinyEncryptConstant { - public static final String VERSION = "0.3.1"; + public static final String VERSION = "0.3.2"; public static final String ENC_FILE_EXT = ".tinyenc"; } diff --git a/src/main/java/me/hatter/tools/tinyencrypt/encrypt/EncryptedFileUtil.java b/src/main/java/me/hatter/tools/tinyencrypt/encrypt/EncryptedFileUtil.java index e35d829..a913375 100644 --- a/src/main/java/me/hatter/tools/tinyencrypt/encrypt/EncryptedFileUtil.java +++ b/src/main/java/me/hatter/tools/tinyencrypt/encrypt/EncryptedFileUtil.java @@ -11,14 +11,53 @@ import me.hatter.tools.commons.tlv.Tlv; import me.hatter.tools.commons.tlv.TlvUtil; import me.hatter.tools.tinyencrypt.config.TinyEncryptConfig; import me.hatter.tools.tinyencrypt.config.TinyEncryptConstant; +import me.hatter.tools.tinyencrypt.win.SwingWindow; import java.io.*; +import java.nio.charset.StandardCharsets; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; public class EncryptedFileUtil { private static final LogTool log = LogTools.getLogTool(EncryptedFileUtil.class); + public static boolean decryptToOutputStream(TinyEncryptConfig config, File file, OutputStream os) { + try { + try (FileInputStream fis = new FileInputStream(file)) { + Tlv tlv = TlvUtil.readTlv(fis); + TinyEncryptMeta meta = tlv.getValueAsBytes().asJSONObject(TinyEncryptMeta.class); + byte[] dataKey = TinyEncryptMetaUtil.decryptDataKey(config, meta); + meta.setDataKey(dataKey); + try (InputStream newIs = getDecryptInputStream(fis, meta)) { + boolean isCompressed = (meta.getCompress() != null) && meta.getCompress(); + if (isCompressed) { + GZIPInputStream gzIs = new GZIPInputStream(newIs); + IOUtil.copy(gzIs, os, new DefaultRollCounter().prefix("Decrypting, ")); + } else { + IOUtil.copy(newIs, os, new DefaultRollCounter().prefix("Decrypting, ")); + } + os.flush(); + } + } + log.info("Decrypt file success: " + file); + return true; + } catch (Exception e) { + log.error("Decrypt file filed: " + file + ", reason: " + e.getMessage()); + log.debug("Decrypt file filed: " + file + ", reason: " + e.getMessage(), e); + return false; + } + } + + public static void decryptInWindow(TinyEncryptConfig config, File file) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + decryptToOutputStream(config, file, baos); + SwingWindow.create("Decrypted file: " + file.getName()) + .message("File: " + file) + .text(new String(baos.toByteArray(), StandardCharsets.UTF_8)) + .show().getResult(); +// return false; + } + public static boolean decryptFile(TinyEncryptConfig config, File file) { File decFile = getDecryptFile(file); if (decFile == null) { @@ -30,25 +69,9 @@ public class EncryptedFileUtil { return false; } try { - try (FileInputStream fis = new FileInputStream(file)) { - Tlv tlv = TlvUtil.readTlv(fis); - TinyEncryptMeta meta = tlv.getValueAsBytes().asJSONObject(TinyEncryptMeta.class); - byte[] dataKey = TinyEncryptMetaUtil.decryptDataKey(config, meta); - meta.setDataKey(dataKey); - try (InputStream newIs = getDecryptInputStream(fis, meta)) { - try (FileOutputStream fos = new FileOutputStream(decFile)) { - boolean isCompressed = (meta.getCompress() != null) && meta.getCompress(); - if (isCompressed) { - GZIPInputStream gzIs = new GZIPInputStream(newIs); - IOUtil.copy(gzIs, fos, new DefaultRollCounter().prefix("Decrypting, ")); - } else { - IOUtil.copy(newIs, fos, new DefaultRollCounter().prefix("Decrypting, ")); - } - } - } + try (FileOutputStream fos = new FileOutputStream(decFile)) { + return decryptToOutputStream(config, file, fos); } - log.info("Decrypt file success: " + file); - return true; } catch (Exception e) { log.error("Decrypt file filed: " + file + ", reason: " + e.getMessage()); log.debug("Decrypt file filed: " + file + ", reason: " + e.getMessage(), e); diff --git a/src/main/java/me/hatter/tools/tinyencrypt/win/MacDockerHelper.java b/src/main/java/me/hatter/tools/tinyencrypt/win/MacDockerHelper.java new file mode 100644 index 0000000..d9cfd59 --- /dev/null +++ b/src/main/java/me/hatter/tools/tinyencrypt/win/MacDockerHelper.java @@ -0,0 +1,34 @@ +package me.hatter.tools.tinyencrypt.win; + +import me.hatter.tools.commons.classloader.ClassLoaderUtil; +import me.hatter.tools.commons.io.RResource; +import me.hatter.tools.commons.reflect.ReflectUtil; + +import java.awt.*; +import java.lang.reflect.Method; + +public class MacDockerHelper { + static final String COM_APPLE_EAWT_APPLICATION = "com.apple.eawt.Application"; + + static { + if (ClassLoaderUtil.isClassCanBeLoad(COM_APPLE_EAWT_APPLICATION)) { + try { + Class comAppleEawtApplication = ClassLoaderUtil.loadClass(COM_APPLE_EAWT_APPLICATION); + Method getApplicationMetohd = ReflectUtil.getDeclaredMethod(comAppleEawtApplication, "getApplication", new Class[0]); + Object application = ReflectUtil.invokeMethod(getApplicationMetohd, null, new Object[0]); + byte[] iconBytes = RResource.from(SwingWindow.class.getClassLoader()).rStream("icon.png").bytesAndClose(); + Image image = Toolkit.getDefaultToolkit().createImage(iconBytes); + Method setDockIconImageMethod = ReflectUtil.getDeclaredMethod(comAppleEawtApplication, "setDockIconImage", new Class[]{Image.class}); + ReflectUtil.invokeMethod(setDockIconImageMethod, application, new Object[]{image}); + } catch (Error e) { + e.printStackTrace(); + // IGNORE + } + } else { + System.setProperty("java.awt.headless", "true"); + } + } + + public static void init() { + } +} diff --git a/src/main/java/me/hatter/tools/tinyencrypt/win/SwingWindow.java b/src/main/java/me/hatter/tools/tinyencrypt/win/SwingWindow.java new file mode 100644 index 0000000..9a8b250 --- /dev/null +++ b/src/main/java/me/hatter/tools/tinyencrypt/win/SwingWindow.java @@ -0,0 +1,115 @@ +package me.hatter.tools.tinyencrypt.win; + +import me.hatter.tools.commons.string.StringUtil; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.WindowEvent; +import java.util.concurrent.CountDownLatch; + +public class SwingWindow { + private String title; + private String text; + private String message; + private boolean editable; + private String result = null; + private CountDownLatch countDownLatch; + + static { + try { + MacDockerHelper.init(); + } catch (Error e) { + // IGNORE + } + } + + public SwingWindow(String title, String text, String message, boolean editable) { + this.title = title; + this.text = text; + this.message = message; + this.editable = editable; + } + + public static SwingWindow create(String title) { + return new SwingWindow(title, "", "", false); + } + + public SwingWindow message(String message) { + this.message = message; + return this; + } + + public SwingWindow text(String text) { + this.text = text; + return this; + } + + public SwingWindow editable(boolean editable) { + this.editable = editable; + return this; + } + + public String getResult() { + try { + countDownLatch.await(); + return result; + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + public SwingWindow show() { + countDownLatch = new CountDownLatch(1); + JFrame frame = new JFrame((StringUtil.isEmpty(title) ? "" : (title + " - ")) + "Tiny Encrypt Window"); + frame.addWindowListener(new WindowListenerImpl() { + @Override + public void windowClosing(WindowEvent e) { + frame.setVisible(false); + frame.dispose(); + countDownLatch.countDown(); + } + }); + JTextArea text = new JTextArea(StringUtil.def(this.text, ""), 30, 80); + text.setWrapStyleWord(true); + text.setLineWrap(true); + text.setEditable(editable); + JScrollPane textScrollPane = new JScrollPane(text); + JLabel label = new JLabel(StringUtil.def(message, "Tiny Encrypt default message.")); + JButton btnOk = null; + if (editable) { + btnOk = new JButton("OK!"); + btnOk.addActionListener((e) -> { + String t = text.getText(); + frame.setVisible(false); + frame.dispose(); + this.result = t; + countDownLatch.countDown(); + }); + } + JButton btnCancel = new JButton("Cancel"); + btnCancel.addActionListener((e) -> { + frame.setVisible(false); + frame.dispose(); + countDownLatch.countDown(); + }); + JPanel pane = new JPanel(); + if (btnOk != null) { + pane.add(btnOk); + } + pane.add(btnCancel); + + frame.getContentPane().add(label, BorderLayout.NORTH); + frame.getContentPane().add(pane, BorderLayout.SOUTH); + frame.getContentPane().add(textScrollPane, BorderLayout.CENTER); + + frame.pack(); + + Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); + frame.setLocation( + (dim.width / 2) - (frame.getSize().width / 2), + (dim.height / 2) - (frame.getSize().height / 2) + ); + frame.setVisible(true); + return this; + } +} diff --git a/src/main/java/me/hatter/tools/tinyencrypt/win/WindowListenerImpl.java b/src/main/java/me/hatter/tools/tinyencrypt/win/WindowListenerImpl.java new file mode 100644 index 0000000..86591f8 --- /dev/null +++ b/src/main/java/me/hatter/tools/tinyencrypt/win/WindowListenerImpl.java @@ -0,0 +1,34 @@ +package me.hatter.tools.tinyencrypt.win; + +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; + +public class WindowListenerImpl implements WindowListener { + @Override + public void windowOpened(WindowEvent e) { + } + + @Override + public void windowClosing(WindowEvent e) { + } + + @Override + public void windowClosed(WindowEvent e) { + } + + @Override + public void windowIconified(WindowEvent e) { + } + + @Override + public void windowDeiconified(WindowEvent e) { + } + + @Override + public void windowActivated(WindowEvent e) { + } + + @Override + public void windowDeactivated(WindowEvent e) { + } +} diff --git a/src/main/resources/icon.png b/src/main/resources/icon.png new file mode 100644 index 0000000..fecf634 Binary files /dev/null and b/src/main/resources/icon.png differ