Update v1.12.py

This commit is contained in:
Evan Su 2021-03-31 11:45:38 -04:00 committed by GitHub
parent 45c73c3c46
commit 4ce564b72f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 102 additions and 29 deletions

View File

@ -88,6 +88,11 @@ tk.resizable(0,0)
tk.configure(background="#f5f6f7") tk.configure(background="#f5f6f7")
ThemedStyle(tk).set_theme("arc") ThemedStyle(tk).set_theme("arc")
# Some styling
style = tkinter.ttk.Style()
style.configure("PasswordMatches.TLabel",foreground="#e3242b")
style.configure("PasswordStrength.TLabel",foreground="")
# Enable high DPI on Windows # Enable high DPI on Windows
def Get_HWND_DPI(window_handle): def Get_HWND_DPI(window_handle):
from ctypes import windll,pointer,wintypes from ctypes import windll,pointer,wintypes
@ -149,7 +154,7 @@ inputLabel.place(x=20,y=18)
clearInput = tkinter.ttk.Button( clearInput = tkinter.ttk.Button(
tk, tk,
text="Clear", text="Clear",
command=lambda:resetUI() command=lambda:[resetUI(),statusString.set("Ready.")]
) )
clearInput.place(x=400,y=12,width=60,height=28) clearInput.place(x=400,y=12,width=60,height=28)
clearInput["state"] = "disabled" clearInput["state"] = "disabled"
@ -210,7 +215,7 @@ passwordLabel["state"] = "disabled"
# Allow password input to fill width # Allow password input to fill width
passwordFrame = tkinter.Frame( passwordFrame = tkinter.Frame(
tk, tk,
width=440, width=220,
height=24 height=24
) )
passwordFrame.place(x=20,y=118) passwordFrame.place(x=20,y=118)
@ -238,7 +243,7 @@ cPasswordLabel["state"] = "disabled"
# Allow confirm password input to fill width # Allow confirm password input to fill width
cPasswordFrame = tkinter.Frame( cPasswordFrame = tkinter.Frame(
tk, tk,
width=418, width=220,
height=24 height=24
) )
cPasswordFrame.place(x=20,y=168) cPasswordFrame.place(x=20,y=168)
@ -253,21 +258,60 @@ cPasswordInput = tkinter.ttk.Entry(
cPasswordInput.grid(sticky="nesw") cPasswordInput.grid(sticky="nesw")
cPasswordInput["state"] = "disabled" cPasswordInput["state"] = "disabled"
# Check if passwords match # Show strength of password
def doPasswordsMatch(key,which): def showStrength():
if which=="p": global mode
matches = passwordInput.get()+key.char==cPasswordInput.get() if mode=="decrypt":
return
password = passwordInput.get()
containsLetters = any(i.isalpha() for i in password)
containsNumbers = any(i.isdigit() for i in password)
containsSymbols = any(not i.isalnum() for i in password)
longEnough = len(password)>8
if containsLetters and containsNumbers and containsSymbols and longEnough:
style.configure("PasswordStrength.TLabel",foreground="#149414")
elif containsLetters and containsNumbers and containsSymbols:
style.configure("PasswordStrength.TLabel",foreground="#fada52")
elif containsLetters and containsNumbers or \
(containsLetters and containsSymbols) or \
(containsNumbers and containsSymbols):
style.configure("PasswordStrength.TLabel",foreground="#ff781f")
elif not password:
style.configure("PasswordStrength.TLabel",foreground="")
else: else:
matches = passwordInput.get()==cPasswordInput.get()+key.char style.configure("PasswordStrength.TLabel",foreground="#e3242b")
# Check if passwords match
def doPasswordsMatch():
global mode
if mode=="decrypt":
return
matches = passwordInput.get()==cPasswordInput.get()
if passwordInput.get() and matches: if passwordInput.get() and matches:
passwordMatchesString.set("") passwordMatchesString.set("")
style.configure("PasswordMatches.TLabel",foreground="#149414")
startBtn["state"] = "normal" startBtn["state"] = "normal"
else: elif passwordInput.get() and not matches:
passwordMatchesString.set("×") passwordMatchesString.set("")
style.configure("PasswordMatches.TLabel",foreground="#e3242b")
startBtn["state"] = "disabled"
elif not passwordInput.get():
passwordMatchesString.set("")
startBtn["state"] = "disabled" startBtn["state"] = "disabled"
passwordInput.bind("<Key>",lambda key:doPasswordsMatch(key,"p")) passwordInput.bind("<KeyRelease>",lambda e:[showStrength(),doPasswordsMatch()])
cPasswordInput.bind("<Key>",lambda key:doPasswordsMatch(key,"c")) cPasswordInput.bind("<KeyRelease>",lambda e:doPasswordsMatch())
# Show indicator of password strength
passwordStrengthString = tkinter.StringVar(tk)
passwordStrengthString.set("")
passwordStrength = tkinter.ttk.Label(
tk,
textvariable=passwordStrengthString
)
passwordStrength.config(style="PasswordStrength.TLabel")
passwordStrength.place(x=245,y=122)
# Check box that indicates if password match # Check box that indicates if password match
passwordMatchesString = tkinter.StringVar(tk) passwordMatchesString = tkinter.StringVar(tk)
@ -275,7 +319,8 @@ passwordMatches = tkinter.ttk.Label(
tk, tk,
textvariable=passwordMatchesString textvariable=passwordMatchesString
) )
passwordMatches.place(x=441,y=170) passwordMatches.config(style="PasswordMatches.TLabel")
passwordMatches.place(x=242,y=172)
# Prompt user for optional metadata # Prompt user for optional metadata
metadataString = tkinter.StringVar(tk) metadataString = tkinter.StringVar(tk)
@ -367,14 +412,17 @@ rsBtn.place(x=18,y=369)
rsBtn["state"] = "disabled" rsBtn["state"] = "disabled"
# "Reed-Solomon" which links to Wikipedia # "Reed-Solomon" which links to Wikipedia
helpString = tkinter.StringVar(tk) rsHelpString = tkinter.StringVar(tk)
helpString.set("(?)") rsHelpString.set("(?)")
help = tkinter.ttk.Label( rsHelp = tkinter.ttk.Label(
tk, tk,
textvariable=helpString, textvariable=rsHelpString,
cursor="hand2" cursor="hand2",
font=("TkDefaultFont",7)
) )
help.place(x=279,y=373) rsHelp.place(x=259,y=374)
rsHelpLink = "https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction"
rsHelp.bind("<Button-1>",lambda e:webbrowser.open(rsHelpLink))
# Frame so start and cancel button can fill width # Frame so start and cancel button can fill width
startFrame = tkinter.Frame( startFrame = tkinter.Frame(
@ -396,10 +444,14 @@ startBtn = tkinter.ttk.Button(
startBtn.grid(row=0,column=0,stick="nesw") startBtn.grid(row=0,column=0,stick="nesw")
startBtn["state"] = "disabled" startBtn["state"] = "disabled"
def cancel():
global working
working = False
# Cancel button # Cancel button
cancelBtn = tkinter.ttk.Button( cancelBtn = tkinter.ttk.Button(
startFrame, startFrame,
text="Cancel" text="Cancel",
command=cancel
) )
cancelBtn.grid(stick="nesw") cancelBtn.grid(stick="nesw")
cancelBtn.grid(row=0,column=1) cancelBtn.grid(row=0,column=1)
@ -603,6 +655,7 @@ def filesDragged(draggedFiles):
inputString.set(inputFile.split("/")[-1]+suffix) inputString.set(inputFile.split("/")[-1]+suffix)
prompt.pack_forget() prompt.pack_forget()
statusString.set("Ready.")
# UTF-8 decode error # UTF-8 decode error
except UnicodeDecodeError: except UnicodeDecodeError:
@ -648,18 +701,13 @@ def work():
reedsoloErrors = 0 reedsoloErrors = 0
password = passwordInput.get().encode("utf-8") password = passwordInput.get().encode("utf-8")
metadata = metadataInput.get("1.0",tkinter.END).encode("utf-8") metadata = metadataInput.get("1.0",tkinter.END).encode("utf-8")
cancelBtn["state"] = "normal"
# Decide if encrypting or decrypting # Decide if encrypting or decrypting
if mode=="encrypt": if mode=="encrypt":
outputFile = outputInput.get()+".pcv" outputFile = outputInput.get()+".pcv"
else: else:
outputFile = outputInput.get() outputFile = outputInput.get()
# Make sure passwords match
if passwordInput.get()!=cPasswordInput.get() and mode=="encrypt":
setEncryptionUI()
statusString.set("Passwords don't match.")
return
# Set progress bar indeterminate # Set progress bar indeterminate
progress.config(mode="indeterminate") progress.config(mode="indeterminate")
@ -811,6 +859,18 @@ def work():
Thread(target=updateStats,daemon=True,args=(total,)).start() Thread(target=updateStats,daemon=True,args=(total,)).start()
while True: while True:
if not working:
fin.close()
fout.close()
remove(outputFile)
if mode=="encrypt":
setEncryptionUI()
else:
setDecryptionUI()
statusString.set("Operation canceled by user.")
dummy.focus()
return
if mode=="decrypt" and reedsolo: if mode=="decrypt" and reedsolo:
piece = fin.read(1104905) piece = fin.read(1104905)
else: else:
@ -976,12 +1036,12 @@ def work():
working = False working = False
def updateStats(total): def updateStats(total):
global startTime,previousTime,done,stopUpdating,reedsolo,reedsoloFixed,reedsoloErrors global startTime,previousTime,done,stopUpdating,reedsolo,reedsoloFixed,reedsoloErrors,working
while True: while True:
validStatus = ( validStatus = (
statusString.get().startswith("Working") or statusString.get().startswith("Deriving") statusString.get().startswith("Working") or statusString.get().startswith("Deriving")
) )
if not stopUpdating and validStatus: if not stopUpdating and validStatus and working:
elapsed = (datetime.now()-previousTime).total_seconds() or 0.0001 elapsed = (datetime.now()-previousTime).total_seconds() or 0.0001
sinceStart = (datetime.now()-startTime).total_seconds() or 0.0001 sinceStart = (datetime.now()-startTime).total_seconds() or 0.0001
previousTime = datetime.now() previousTime = datetime.now()
@ -1032,6 +1092,8 @@ def secureWipe(fin):
# Reset UI to state where no files are selected # Reset UI to state where no files are selected
def resetUI(): def resetUI():
global working
working = False
inputString.set(strings[18]) inputString.set(strings[18])
inputLabel["state"] = "normal" inputLabel["state"] = "normal"
clearInput["state"] = "disabled" clearInput["state"] = "disabled"
@ -1050,7 +1112,8 @@ def resetUI():
cPasswordInput["state"] = "normal" cPasswordInput["state"] = "normal"
cPasswordInput.delete(0,"end") cPasswordInput.delete(0,"end")
cPasswordInput["state"] = "disabled" cPasswordInput["state"] = "disabled"
passwordMatchesString.set("×") passwordMatchesString.set("")
style.configure("PasswordStrength.TLabel",foreground="")
metadataFrame.config(bg="#e5eaf0") metadataFrame.config(bg="#e5eaf0")
metadataInput.config(bg="#fbfcfc") metadataInput.config(bg="#fbfcfc")
metadataInput.config(fg="#000000") metadataInput.config(fg="#000000")
@ -1074,6 +1137,10 @@ def resetUI():
# Set UI to encryption state # Set UI to encryption state
def setEncryptionUI(): def setEncryptionUI():
global working
working = False
clearInput["state"] = "normal"
clearInput.config(cursor="hand2")
outputLabel["state"] = "normal" outputLabel["state"] = "normal"
outputInput["state"] = "normal" outputInput["state"] = "normal"
outputFrame.config(width=410) outputFrame.config(width=410)
@ -1090,12 +1157,17 @@ def setEncryptionUI():
eraseBtn["state"] = "normal" eraseBtn["state"] = "normal"
rsBtn["state"] = "normal" rsBtn["state"] = "normal"
startBtn["state"] = "normal" startBtn["state"] = "normal"
cancelBtn["state"] = "disabled"
progress.stop() progress.stop()
progress.config(mode="determinate") progress.config(mode="determinate")
progress["value"] = 0 progress["value"] = 0
# Set UI to decryption state # Set UI to decryption state
def setDecryptionUI(): def setDecryptionUI():
global working
working = False
clearInput["state"] = "normal"
clearInput.config(cursor="hand2")
outputLabel["state"] = "normal" outputLabel["state"] = "normal"
outputInput["state"] = "normal" outputInput["state"] = "normal"
outputFrame.config(width=440) outputFrame.config(width=440)
@ -1109,6 +1181,7 @@ def setDecryptionUI():
metadataInput["state"] = "disabled" metadataInput["state"] = "disabled"
keepBtn["state"] = "normal" keepBtn["state"] = "normal"
startBtn["state"] = "normal" startBtn["state"] = "normal"
cancelBtn["state"] = "disabled"
progress.stop() progress.stop()
progress.config(mode="determinate") progress.config(mode="determinate")
progress["value"] = 0 progress["value"] = 0