Skip to content

Instantly share code, notes, and snippets.

@mmj-the-fighter
Last active January 14, 2024 13:02
Show Gist options
  • Save mmj-the-fighter/aa2c5069d4813bf58fc80d523ee1c87d to your computer and use it in GitHub Desktop.
Save mmj-the-fighter/aa2c5069d4813bf58fc80d523ee1c87d to your computer and use it in GitHub Desktop.
Drag and drop utility for generating hash values for files, Supports Md5, Sha-1 and Sha-256 algorithms.
/*
MIT License
Copyright (c) 2024 Manoj M J
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/*
Commands:
To compile: javac HashTool.java
To run: java HashTool
To make executable jar: jar cvfe HashTool.jar HashTool *.class
To run jar in command line: java -jar HashTool.jar
*/
import java.awt.dnd.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.SwingWorker;
import java.awt.datatransfer.*;
import java.io.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class HashTool extends JFrame {
//
JTextArea jTextArea;
JScrollPane jScrollPane;
//
JPopupMenu popupMenu;
JMenuItem copyMenuItem;
JMenuItem lastElapsedTimeMenuItem;
JMenuItem lastHashValueMenuItem;
JMenuItem lastFilenameMenuItem;
JMenuItem clearMenuItem;
ButtonGroup algorithmGroup;
JRadioButtonMenuItem radioMd5;
JRadioButtonMenuItem radioSha1;
JRadioButtonMenuItem radioSha256;
//
String md5 = "MD5";
String sha1 = "SHA-1";
String sha256 = "SHA-256";
String algorithmSelected = md5;
//
String defaultText = "Drag a file here to calculate hash.";
String processingText = "Processing...";
String dragOnlyOneFile = "Drag and drop only one file.";
String noReadPermission = "This file has no read permission";
String emptyString="";
//
String lastHashValue = emptyString;
String lastFilename = emptyString;
File lastFile = null;
long lastElapsedTime = 0L;
//
long start, end, elapsedTime;
public HashTool() {
buildInterface();
}
void setPopupEnabled(boolean flag){
copyMenuItem.setEnabled(flag);
radioMd5.setEnabled(flag);
lastFilenameMenuItem.setEnabled(flag);
lastHashValueMenuItem.setEnabled(flag);
lastElapsedTimeMenuItem.setEnabled(flag);
radioSha1.setEnabled(flag);
radioSha256.setEnabled(flag);
radioMd5.setEnabled(flag);
clearMenuItem.setEnabled(flag);
popupMenu.setEnabled(flag);
}
private void buildInterface() {
setTitle("Hash Tool: Md5, Sha-1 and Sha-256");
setSize(800, 600);
getContentPane().setBackground(Color.WHITE);
setLayout(new FlowLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
// Create JTextArea with bigger font
jTextArea = new JTextArea(21, 58);
Font font = jTextArea.getFont();
Font biggerFont = font.deriveFont(font.getSize() + 4f);
jTextArea.setFont(biggerFont);
jTextArea.setVisible(true);
jTextArea.setEditable(false);
// Add context menu to JTextArea
popupMenu = new JPopupMenu();
copyMenuItem = new JMenuItem("Copy");
copyMenuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String selectedText = jTextArea.getSelectedText();
StringSelection selection;
if (selectedText != null) {
selection = new StringSelection(selectedText);
}
else {
//If nothing selected just copy lastMd5 string
selection = new StringSelection(lastHashValue);
}
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(selection, null);
}
});
clearMenuItem = new JMenuItem("Clear");
clearMenuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
jTextArea.setText(defaultText);
lastHashValue = emptyString;
lastFilename = emptyString;
lastFile = null;
lastElapsedTime = 0L;
}
});
lastFilenameMenuItem = new JMenuItem("Recent File Name");
lastFilenameMenuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//jTextArea.setText(lastFilename);
//Split the file path and display line by line
jTextArea.setText(emptyString);
String[] lines;
if (File.separator.equals("\\")) {
lines = lastFilename.split("\\\\");
} else {
lines = lastFilename.split("/");
}
int len = lines.length;
for (String line : lines) {
jTextArea.append(line);
--len;
if(len > 0){
if (File.separator.equals("\\")) {
jTextArea.append("\\");
} else {
jTextArea.append("/");
}
jTextArea.append("\n");
}
}
}
});
lastElapsedTimeMenuItem = new JMenuItem("Recent Elapsed Time");
lastElapsedTimeMenuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
jTextArea.setText(Long.toString(lastElapsedTime) + " milli seconds.");
}
});
lastHashValueMenuItem = new JMenuItem("Recent Hash Value");
lastHashValueMenuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
jTextArea.setText(lastHashValue);
}
});
radioMd5 = new JRadioButtonMenuItem(md5);
radioMd5.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (radioMd5.isSelected()) {
if(algorithmSelected.compareTo(md5) != 0){
//System.out.println("md5 selected");
algorithmSelected = md5;
if(lastFile != null){
generateHashAsynchronously(lastFile);
}
}
}
}
});
radioSha1 = new JRadioButtonMenuItem(sha1);
radioSha1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (radioSha1.isSelected()) {
if(algorithmSelected.compareTo(sha1) != 0){
//System.out.println("sh1 selected");
algorithmSelected = sha1;
if(lastFile != null){
generateHashAsynchronously(lastFile);
}
}
}
}
});
radioSha256 = new JRadioButtonMenuItem(sha256);
radioSha256.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (radioSha256.isSelected()) {
if(algorithmSelected.compareTo(sha256) != 0){
//System.out.println("sh256 selected");
algorithmSelected = sha256;
if(lastFile != null){
generateHashAsynchronously(lastFile);
}
}
}
}
});
algorithmGroup = new ButtonGroup();
algorithmGroup.add(radioMd5);
algorithmGroup.add(radioSha1);
algorithmGroup.add(radioSha256);
radioMd5.setSelected(true);
popupMenu.add(copyMenuItem);
popupMenu.add(lastFilenameMenuItem);
popupMenu.add(lastHashValueMenuItem);
popupMenu.add(lastElapsedTimeMenuItem);
popupMenu.add(radioMd5);
popupMenu.add(radioSha1);
popupMenu.add(radioSha256);
popupMenu.add(clearMenuItem);
jTextArea.setComponentPopupMenu(popupMenu);
//
jTextArea.setText(defaultText);
//
jScrollPane = new JScrollPane(jTextArea);
add(jScrollPane, BorderLayout.CENTER);
//
enableDragAndDrop();
//
setLocationRelativeTo(null);
pack();
setVisible(true);
}
void generateHashAsynchronously(File file){
start = System.currentTimeMillis();
jTextArea.setText(processingText);
//System.out.println("Processing...");
setPopupEnabled(false);
// Create a SwingWorker to perform the hash calculation in a separate thread
SwingWorker<String, Void> worker = new SwingWorker<String, Void>() {
@Override
protected String doInBackground() throws Exception {
return calculateHash(file);
}
@Override
protected void done() {
try
{
// Get the result from doInBackground() and update the UI
String md5 = get();
end = System.currentTimeMillis();
elapsedTime = end - start;
//System.out.println("Processing took " + elapsedTime + " milliseconds");
jTextArea.setText(md5);
lastHashValue = md5;
lastElapsedTime = elapsedTime;
}
catch (Exception ex) {
ex.printStackTrace();
}finally{
setPopupEnabled(true);
}
}
};
// Execute the SwingWorker
worker.execute();
}
private void enableDragAndDrop() {
DropTarget target = new DropTarget(jTextArea, new DropTargetListener() {
public void dragEnter(DropTargetDragEvent e) {}
public void dragExit(DropTargetEvent e) {}
public void dragOver(DropTargetDragEvent e) {}
public void dropActionChanged(DropTargetDragEvent e) {}
public void drop(DropTargetDropEvent e) {
try
{
// Accept the drop first, important!
e.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
// Get the files that are dropped as java.util.List
java.util.List list = (java.util.List) e.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
// If multiple files are dragged and dropped don't process
if(list.size() > 1){
jTextArea.setText(dragOnlyOneFile);
return;
}
// Now get the first file from the list
File file = (File) list.get(0);
// If it is not an actual file don't process
if(file.isDirectory()){
jTextArea.setText(dragOnlyOneFile);
return;
}
if(!file.canRead()){
jTextArea.setText(noReadPermission);
return;
}
lastFilename = file.getAbsolutePath().toString();
lastFile = file;
generateHashAsynchronously(file);
}
catch (Exception ex) {
}
}
});
}
private String calculateHash(File file) {
String output = "";
try {
MessageDigest md = MessageDigest.getInstance(algorithmSelected);
FileInputStream fis = new FileInputStream(file);
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
md.update(buffer, 0, bytesRead);
}
byte[] digest = md.digest();
// Convert byte array to hex string
StringBuilder hexString = new StringBuilder();
for (byte b : digest) {
String hex = Integer.toHexString(0xFF & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
output = hexString.toString();
fis.close();
} catch (NoSuchAlgorithmException | IOException e) {
return e.toString();
}
return output;
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new HashTool();
}
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment