Last active
January 14, 2024 13:02
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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