From 084bc7198bf83c3d14a7ae31457021588cc57de1 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Sat, 5 Jun 2021 00:22:46 +0800 Subject: [PATCH] feat: add --show --- .../tools/tinyencrypt/TinyEncryptArgs.java | 3 + .../tools/tinyencrypt/TinyEncryptMain.java | 8 +- .../config/TinyEncryptConstant.java | 2 +- .../encrypt/EncryptedFileUtil.java | 59 ++++++--- .../tinyencrypt/win/MacDockerHelper.java | 34 ++++++ .../tools/tinyencrypt/win/SwingWindow.java | 115 ++++++++++++++++++ .../tinyencrypt/win/WindowListenerImpl.java | 34 ++++++ src/main/resources/icon.png | Bin 0 -> 5007 bytes 8 files changed, 235 insertions(+), 20 deletions(-) create mode 100644 src/main/java/me/hatter/tools/tinyencrypt/win/MacDockerHelper.java create mode 100644 src/main/java/me/hatter/tools/tinyencrypt/win/SwingWindow.java create mode 100644 src/main/java/me/hatter/tools/tinyencrypt/win/WindowListenerImpl.java create mode 100644 src/main/resources/icon.png 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 0000000000000000000000000000000000000000..fecf63443b0474c4784421681021741dd2a45617 GIT binary patch literal 5007 zcmV;A6L9Q_P)*zrR~ccc;@y$U+F4fFS!m3JSxb;^Tt;SO zm_fnOg90M@d^0LbTzEPPj*2^C90;I*fIvhb`_gMw-QWA8lMsSr@2Up5=hO+I(^Ylv z=l+)Oy|-==;;^LO^d<_HTn+#jQpE1f0Mt(ikPLErDo9aRxZ8JHTK<32xBTLOT+EDr5uxu!R=>OXo>?%B`(!Yf3?ZCt z2`M2wo>HjVpZn*`U$BYDx|j@ zC&FsZpqa}#68>+T#6`G0FOAr|;Kuifte9RW7AH-)ekB0Fb z-{sG?$a$6Ko}krruTjStmwJjm3+^;ai_UXgPuQFuvuX5D+6=qiH+FH@_<-fCP zp9}`vzhD>uKx~=1k$-5P;&ychd}OnQOro^wF6&*oX;Us65u7eHySRX!nbj}&(c@bI zKgS$M;-ycMmXz47e9JdGPQ$1JN@{vfD-zxj+0;1q)hHk-*St(xM(g&)|9*QvN5ZEY zzP_|Lv;7%h>p*bBgAIn#;26^S&iB!7#g_nB!ClO1tQ4EO2tiA4a51vd!kE+bR>Fo zC_;e2uq=s^@(}hMD8T1m@5YMkFR*X-Pf)xrz?p$%Cf&8q+`6!Hivw{FnX}p`%AWwT zpM@1RFm!NNEPQAZhV<`r%x5JgU_>MUhNde>QIGxZ#@v0l^?{d>vvnU7O?3bXL-8eL zM{?#*XfYt(3;%Xi=!adeIwAV3U<9u`cN->MG6(>$C9e#BU-lkWuit{=o%;cjM`ssV z0;D0eTYF3x-5a-Ge*p$`Ne2MDwB`$3_xq(#5?uB}krI0QPLqNk-uGIwfFxh@4+vdt zRsQ9MB9`_KhcJNe-+v69+ohr~U}609W%%UXFQ6tRMCY~$uuO^Si7p~2ssK33$Se!s zywQX3=91fx=2fwC?-6vrU=9>bvESngfs_%Kq%v`F;d5h~ZXsIVnYl6?>f?lE?D_03 z=-fUHA8-8$BgQ@o)ujMnn8kh!7}_1bIkyM8cFls<=LHd=qO1bDb{@pqPqt%w&i7DL zyZ{JhMB_Y!it4c zD`6bOh>IVDq6?V*5XN3O5QV#*#W!!mk-MGxT9@AA>}%rSfB7}*E4JtEf}+-)FzlLj;aA_|{PBN+>Px`j0bTLMD>L!gH+wN`+*~Lg`-8mVOI{KAdfp8Ua#RqQGR{qjI|lP|HJhIIdEqOgm!(m z*eQiO?YF}L08c;vE|jDMNGMoz|CPAw$$ug5hl7n;Im8U)?LUOOo_Gg~AGsPCl_V|0H*wIWc1wYasdEc&ujzBl1^F4gf{oDZ(S!4B0^yEm-8GO z05VN<=@1oi{=9rxro_-eo$>tI&49ZZ+Cd{Me>)c!jOYc+uu$>C!RYv0YGO1IaAZ)0 zQS{Eb`E>$$m|0li@MPzJNTenupg;nU5x}(2tz$a2eY+ou(sUq-reN#VJvh7X89>AY z*hGE=@FlvP0|G#X0@qbA(+Pph8#?C?kPa?TV1~=3!mJvswIni9eaJ5?Z?@z=Qc#Ze zS!sY_0wiFBO?X^7oEmim05%Pz4}Wyl34zFP=w3%>VmX=}K~`qumPAsb8#2=TiLgj0 z1kwZ`E62Vp3vQQMc`b(u5oExB@6Q5hb;HWuvZAaNoGi=`HC+=kTrLd}v-$HIfl#D! zi49lN_qcUOT^0aXWu<9pQ(y0O91wqQ&NK)G&K8Cc%26l6fTF747HBlXu%folM}@sh zSK;^yd__UU=8e;icUh)!1K>Ch2!)On5<;|ym$zyzX{|hATmS*UM&yQLfV8=PW0qA> zo`g6cLZX(%DAZ!GYZsTUI_|P6HA!;YhjTIkK%`E|M)A7rtDKk#{Mi^%dz6ii2Edl# zLDlEfH7zbI1Vku&XZ6+TH@yY5==m$4^`AA$ZXj0JKt^UOv~8UXK>!ItS*af?02cx0 zj~^BFSO5kO?tze=(5&kX?A8VZVAK_(AQSUJe${7~I%_!;w{F`th0ARi zxliiU?;Cb)yXw}Eofguia~5{~YYv!!9}g8{`5RwBG97gv3`7M2RqBSyU#lDs*Zj%R z|K^|j>_oLEfCL}}psFC38=mAO+;Vw;_;djxpxv{w7Uno zM6|Jr%0uWdVh$AXbE5-|>>$*b@A9!ho*679X5VR`bk8y*xdhH=+sa-b0Je;MXrzz< z{{XwiIaONYbFY00g{;a3tbH^gYF8gz&vCpDCq;qqXjt}Ebd*`sHQNKbRZ%`rz%tv} zJzP=+gvn_kdVHfq0)ePrQysWB%WN+I?&?6jPpA!?~ zxBDg{CB+M`#|4*5g|4X(LO>A&AqYg#pH*2AGoY%X+VwC;fd)bm2p^>8b%|9 zrhP>PkqJPHM<9x(L3e3zyEJI30zm|3hLjRg0;1lH&Y}l>8Er-kUcijP*_ zgTw?E5pLCgqQjQrwqg#BSC zF120~PK;@d`*_ZW>fUR$klJeovuQZ8J44;VP(k*(|5W}R;kc>S2A}`vck6^vBLlRX zhwymAuM(M6-EFNC2GR(9cmiSAknc6}yH&H9HWML5tc`;C^<0opKRB&JYR5MlfiOey zcsFF+^9e-o;|HN;X05W-M#-_z+2EVA)k2t&_S@@T$)7(wx^gr4{yhgs)BSdLL!vmG zHFQ9SC`rl1c{4j70RXi|p8f)W>GsC*`YpsVt?F#)*mzJ&chv6DwHs6bP!*_dy`HwV z+d>#Z)mK#gRt-dN({5>a-}lpNEkAcu80wmeHA`=Y&+A5Ff(x3aRO%2qMuP|;qB?{b zLJ=U~n29K6ARIAK5eTE-e?11Xj@>D$=lkvAAte$ApSv`)u@;cP`n$KNeSTlek%-N6 z?0iB%!C(a0@8qCudJXbq3`5b?xbay^Qc8Zo z;!D3h&O!h{(cO=mk;weG(IKk9^J_k@3^p~^>^8K`sK!O8s*Y;>q`k}#9?xHDd)Dgm z`>*FMuyd0#YG_oi**H{Vxhd6i)FjUJ17xtRE{jwR!A~Apa6%ySiKOCkzZiQbRkh(* zoNY^9)A%^{kLLo@4;Sk8}BJrPUs@{Hfl5HVu7 z;~bHIZ{X0I`+whn?U}X>Ar!8-x6N!J49n?QAI3*C)8GHH`KMrqu!QQd)~2?Ewguv#*nfA^1oY*^kfg> zvFzA$7(GVZ*Wz2r3YTZIk^97eCTnHS$Ui|E;WV?bpr9p#FA-pxj44;1i+1TgkRm{u z2B8Ru$_3Fxl}8Jv#w?@DP?;H$87w*aZ_@${6U-8Yr9nLN@`v>+`o`8-2zYu8NL9Q^ z#U=kUsp%F10Ipx%d$n0w^3RxLUQ}ypmSevnifRp$96QXyEkBIK3@xqoRiQ8bxU!j} zNk@y;Z`NuV@=y3>zuBnCu4;{u`^1%v>MRX{()X@CG92uL(^ML48>A@v&2OLX)L?iG z{livM*5Is{7xWamD|EV@8yq)`r2a#Dx<~!F@$R%CC28XGMPdxI1;~UGe$$Z&9*5_OH#WF3B?}ZQ`%Hm45l@j?

*_f(^ zgsx|GFI)H3E(Bj}Qu5sN!K%`yIFetmEA66j9fZs6M||!BU|TjN+@3(n$cx)s!Elpd zG!F=X@;7hg@Sz`nJbS|vsUpFY>~< z2!@AS6|dj=l-6ZT9}We2f#??lLru+iHL~gP5#it%tFCuT#Xg3dpm=`$*p){9;Z-bu z0WY}EY&RkJ(f!#idfr&vtZ&kbDWPpSAIWgI-zjG;%pl#hC85`Vk!34yC~5IwmRQ`g z0GAkB7xh<{P zOJIgb@RpFGyx=;c>$39KZ{F^>amJgs$a-L7X3_e$Cdr_G6iYdl!y)yURqV|HfasRq z5Mr%xxj#%kZ}e+N7L7R+PxX&Wk&t@h8Wb&$zJ9#Ri+=ZkCm$Ip!@+^XdyAqe$@P^k4PZhK(I50sv_@u14YVE90*2 Z{|~6M-mrx!s*L~u002ovPDHLkV1ki8cxM0r literal 0 HcmV?d00001