1 ##################################################################################################
2 # MHash-384 - Language bindings for Python #
3 # Copyright(c) 2016 LoRd_MuldeR <mulder2@gmx.de> #
5 # Permission is hereby granted, free of charge, to any person obtaining a copy of this software #
6 # and associated documentation files (the "Software"), to deal in the Software without #
7 # restriction, including without limitation the rights to use, copy, modify, merge, publish, #
8 # distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the #
9 # Software is furnished to do so, subject to the following conditions: #
11 # The above copyright notice and this permission notice shall be included in all copies or #
12 # substantial portions of the Software. #
14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING #
15 # BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND #
16 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, #
17 # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, #
18 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #
19 ##################################################################################################
26 from tkinter import filedialog
27 from tkinter.ttk import *
29 from queue import Queue
30 from queue import Empty
31 from threading import Thread
33 from MHashPy384_Wrapper import MHash384
36 #############################################################################
37 # HASH COMPUTATION (THREADED)
38 #############################################################################
40 def get_file_size(input_file):
42 return path.getsize(input_file)
46 def read_chunks(fs, chunk_size=4096):
48 data = fs.read(chunk_size)
53 def compute_status(current, maximum):
54 return round(100.0 * (float(current) / float(maximum)))
56 def thread_main(text_out, input_file, queue):
58 bytes_done = update_int = status_old = status_new = 0
59 total_size = get_file_size(input_file)
60 with MHash384() as digest:
61 with open(input_file, 'rb') as fs:
62 for chunk in read_chunks(fs):
64 bytes_done += len(chunk)
66 if total_size > 0 and update_int >= 997:
67 status_new = compute_status(bytes_done, total_size)
68 if status_new > status_old:
69 queue.put(int(status_new))
70 status_old = status_new
73 queue.put(binascii.hexlify(digest.result()))
75 queue.put("Error: Something went wrong!")
78 #############################################################################
80 #############################################################################
82 def set_buttons_enabled(root, enable):
83 for child in root.winfo_children():
84 if isinstance(child, Button):
85 child.configure(state='normal' if enable else 'disabled')
87 def check_status(root, queue, text_out, progress):
89 qval = queue.get_nowait()
90 if isinstance(qval, int):
92 root.after(32, check_status, root, queue, text_out, progress)
96 set_buttons_enabled(root, True)
98 root.after(250, check_status, root, queue, text_out, progress)
100 def compute_digest(root, text_out, input_file, progress):
101 queue = Queue(maxsize=8)
102 text_out.set("Working, please wait...")
104 set_buttons_enabled(root, False)
105 thread = Thread(target=thread_main, args=(text_out, input_file, queue))
107 root.after(250, check_status, root, queue, text_out, progress)
109 def browse_for_file(root, text_hash, text_file):
110 file_name = filedialog.askopenfilename(parent=root, title='Choose a file')
113 text_file.set(file_name)
116 #############################################################################
118 #############################################################################
120 def center_window(root, width, height):
121 screen_width = root.winfo_screenwidth()
122 screen_height = root.winfo_screenheight()
123 x = (screen_width - width) / 2
124 y = (screen_height - height) / 2
125 root.geometry('%dx%d+%d+%d' % (width, height, x, y))
127 def make_spacer(root, size):
128 return Canvas(root, height=size, bd=0, highlightthickness=0)
130 def initialize_gui():
132 root.wm_title("MHashPy384 - Example App v%d.%d.%d" % MHash384.getver())
133 center_window(root, 800, 256)
135 root.minsize(root.winfo_width(), root.winfo_height())
137 text_file = StringVar()
138 text_hash = StringVar()
139 make_spacer(root, 8).pack(fill=X)
140 Label(root, text="Input file:", anchor="w").pack(fill=X, padx=8)
141 Entry(root, state="readonly", textvariable=text_file).pack(fill=X, padx=8)
142 make_spacer(root, 20).pack(fill=X)
143 Label(root, text="File Digest:", anchor="w").pack(fill=X, padx=8)
144 Entry(root, state="readonly", textvariable=text_hash).pack(fill=X, padx=8)
145 make_spacer(root, 30).pack(fill=X)
146 Progressbar(root, variable=progress).pack(fill=X, padx=8)
147 Button(root, text="Compute Hash", command=lambda: \
148 compute_digest(root, text_hash, text_file.get(), progress)) \
149 .pack(fill=X, side=RIGHT, anchor="s", padx=8, pady=8)
150 Button(root, text="Browse File", command=lambda: \
151 browse_for_file(root, text_hash, text_file)) \
152 .pack(fill=X, side=RIGHT, anchor="s", padx=8, pady=8)
155 #############################################################################
157 #############################################################################
163 if __name__ == "__main__":