OSDN Git Service

a8a2b9cc68696bdb4f746813a0ec983d42a2554f
[mhash384/mhash384.git] / bindings / Python / example / MHashPy384_Example.py
1 ##################################################################################################
2 # MHash-384 - Language bindings for Python                                                       #
3 # Copyright(c) 2016 LoRd_MuldeR <mulder2@gmx.de>                                                 #
4 #                                                                                                #
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:                           #
10 #                                                                                                #
11 # The above copyright notice and this permission notice shall be included in all copies or       #
12 # substantial portions of the Software.                                                          #
13 #                                                                                                #
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 ##################################################################################################
20
21 import sys
22 import binascii
23 import time
24
25 from tkinter import *
26 from tkinter import filedialog
27 from tkinter.ttk import *
28 from os import path
29 from queue import Queue
30 from queue import Empty
31 from threading import Thread
32
33 from MHashPy384_Wrapper import MHash384
34
35
36 #############################################################################
37 # HASH COMPUTATION (THREADED)
38 #############################################################################
39
40 def get_file_size(input_file):
41     try:
42         return path.getsize(input_file)
43     except:
44         return 0
45
46 def read_chunks(fs, chunk_size=4096):
47     while True:
48         data = fs.read(chunk_size)
49         if not data:
50             break
51         yield data
52
53 def compute_status(current, maximum):
54     return round(100.0 * (float(current) / float(maximum)))
55
56 def thread_main(text_out, input_file, queue):
57     try:
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):
63                     digest.update(chunk)
64                     bytes_done += len(chunk)
65                     update_int += 1
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
71                             time.sleep(0.01)
72                         update_int = 0
73                 queue.put(binascii.hexlify(digest.result()))
74     except:
75         queue.put("Error: Something went wrong!")
76
77
78 #############################################################################
79 # CALLBACK FUNCTIONS
80 #############################################################################
81
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')
86
87 def check_status(root, queue, text_out, progress):
88     try:
89         qval = queue.get_nowait()
90         if isinstance(qval, int):
91             progress.set(qval)
92             root.after(32, check_status, root, queue, text_out, progress)
93         else:
94             text_out.set(qval)
95             progress.set(100)
96             set_buttons_enabled(root, True)
97     except Empty:
98         root.after(250, check_status, root, queue, text_out, progress)
99
100 def compute_digest(root, text_out, input_file, progress):
101     queue = Queue(maxsize=8)
102     text_out.set("Working, please wait...")
103     progress.set(0)
104     set_buttons_enabled(root, False)
105     thread = Thread(target=thread_main, args=(text_out, input_file, queue))
106     thread.start()
107     root.after(250, check_status, root, queue, text_out, progress)
108
109 def browse_for_file(root, text_hash, text_file):
110     file_name = filedialog.askopenfilename(parent=root, title='Choose a file')
111     if file_name:
112         text_hash.set("")
113         text_file.set(file_name)
114
115
116 #############################################################################
117 # GUI FUNCTIONS
118 #############################################################################
119
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))
126
127 def make_spacer(root, size):
128     return Canvas(root, height=size, bd=0, highlightthickness=0)
129
130 def initialize_gui():
131     root = Tk()
132     root.wm_title("MHashPy384 - Example App v%d.%d.%d" % MHash384.getver())
133     center_window(root, 800, 256)
134     root.update()
135     root.minsize(root.winfo_width(), root.winfo_height())
136     progress = IntVar()
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)
153
154
155 #############################################################################
156 # MAIN
157 #############################################################################
158
159 def main():
160     initialize_gui()
161     mainloop()
162
163 if __name__ == "__main__":
164     main()