349 lines
8.1 KiB
Python
349 lines
8.1 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import string
|
|
import random
|
|
import easymacro as app
|
|
from stats import PasswordStats
|
|
|
|
|
|
_ = None
|
|
PREFIX = 'zazpass'
|
|
DEFAULT_LENGTH = 25
|
|
DEFAULT_CHARACTERS = (
|
|
string.ascii_uppercase +
|
|
string.ascii_lowercase +
|
|
string.digits +
|
|
string.punctuation)
|
|
|
|
|
|
def main(id_extension, args, path_locales):
|
|
global _
|
|
|
|
if args == 'insert':
|
|
_password_insert()
|
|
return
|
|
|
|
if args == 'copy':
|
|
_password_copy()
|
|
return
|
|
|
|
_ = app.install_locales(path_locales)
|
|
_password_generate(id_extension)
|
|
|
|
return
|
|
|
|
|
|
def _from_config():
|
|
characters = ''
|
|
config = app.get_config('setting', PREFIX)
|
|
length = config.get('length', DEFAULT_LENGTH)
|
|
if config:
|
|
if config['letters']:
|
|
characters += string.ascii_uppercase
|
|
if config['letters2']:
|
|
characters += string.ascii_lowercase
|
|
if config['digits']:
|
|
characters += string.digits
|
|
if config['punctuation']:
|
|
characters += string.punctuation
|
|
else:
|
|
characters = DEFAULT_CHARACTERS
|
|
|
|
return list(characters), length
|
|
|
|
|
|
def _from_controls(dialog):
|
|
characters = ''
|
|
|
|
length = int(dialog.txt_length.value)
|
|
if dialog.chk_letters.value:
|
|
characters += string.ascii_uppercase
|
|
if dialog.chk_letters2.value:
|
|
characters += string.ascii_lowercase
|
|
if dialog.chk_digits.value:
|
|
characters += string.digits
|
|
if dialog.chk_punctuation.value:
|
|
characters += string.punctuation
|
|
|
|
if not characters:
|
|
dialog.chk_letters.value = True
|
|
characters = string.ascii_uppercase
|
|
|
|
return list(characters), length
|
|
|
|
|
|
def _get_data(dialog):
|
|
if dialog is None:
|
|
characters, lenght = _from_config()
|
|
else:
|
|
characters, lenght = _from_controls(dialog)
|
|
return characters, lenght
|
|
|
|
|
|
def _generate(dialog=None):
|
|
characters, length = _get_data(dialog)
|
|
random.shuffle(characters)
|
|
password = [random.choice(characters) for i in range(length)]
|
|
random.shuffle(password)
|
|
password = ''.join(password)
|
|
return password
|
|
|
|
|
|
def _password_insert():
|
|
for cell in app.selection:
|
|
cell.str = _generate()
|
|
return
|
|
|
|
|
|
def _password_copy():
|
|
app.clipboard.set(_generate())
|
|
return
|
|
|
|
|
|
def _password_generate(id_extension):
|
|
config = app.get_config('setting', prefix=PREFIX)
|
|
dialog = _create_dialog(id_extension)
|
|
|
|
length = config.get('length', DEFAULT_LENGTH)
|
|
letters = True
|
|
letters2 = True
|
|
digits = True
|
|
punctuation = True
|
|
if config:
|
|
letters = config['letters']
|
|
letters2 = config['letters2']
|
|
digits = config['digits']
|
|
punctuation = config['punctuation']
|
|
|
|
dialog.chk_letters.value = letters
|
|
dialog.chk_letters2.value = letters2
|
|
dialog.chk_digits.value = digits
|
|
dialog.chk_punctuation.value = punctuation
|
|
|
|
dialog.txt_length.value = length
|
|
dialog.txt_password.value = _generate(dialog)
|
|
dialog.open()
|
|
return
|
|
|
|
|
|
class Controllers(object):
|
|
|
|
def __init__(self, dialog):
|
|
self.d = dialog
|
|
|
|
def cmd_close_action(self, event):
|
|
self.d.close()
|
|
return
|
|
|
|
def cmd_switch_action(self, event):
|
|
char = self.d.txt_password.echochar
|
|
name_image = 'eye-close.svg'
|
|
if char == '*':
|
|
self.d.txt_password.echochar = ''
|
|
name_image = 'eye-open.svg'
|
|
else:
|
|
self.d.txt_password.echochar = '*'
|
|
|
|
path_image = app.paths.join(self.d.path_images, name_image)
|
|
self.d.cmd_switch.image = path_image
|
|
self.d.txt_password.set_focus()
|
|
|
|
return
|
|
|
|
def cmd_insert_action(self, event):
|
|
for cell in app.selection:
|
|
cell.str = self.d.txt_password.value
|
|
self.d.close()
|
|
return
|
|
|
|
def _save_config(self):
|
|
data = dict(
|
|
length = self.d.txt_length.int,
|
|
letters = self.d.chk_letters.value,
|
|
letters2 = self.d.chk_letters2.value,
|
|
digits = self.d.chk_digits.value,
|
|
punctuation = self.d.chk_punctuation.value,
|
|
)
|
|
app.set_config('setting', data, PREFIX)
|
|
return
|
|
|
|
|
|
def _new_password(self, save=True):
|
|
stats = PasswordStats(_generate(self.d))
|
|
self.d.txt_password.value = stats.password
|
|
if save:
|
|
self._save_config()
|
|
return
|
|
|
|
def cmd_new_action(self, event):
|
|
self._new_password(False)
|
|
return
|
|
|
|
def txt_length_after_click(self, event):
|
|
self._new_password()
|
|
return
|
|
|
|
def chk_letters_after_click(self, event):
|
|
self._new_password()
|
|
return
|
|
|
|
def chk_letters2_after_click(self, event):
|
|
self._new_password()
|
|
return
|
|
|
|
def chk_digits_after_click(self, event):
|
|
self._new_password()
|
|
return
|
|
|
|
def chk_punctuation_after_click(self, event):
|
|
self._new_password()
|
|
return
|
|
|
|
|
|
@app.catch_exception
|
|
def _create_dialog(id_extension):
|
|
BUTTON_WH = 16
|
|
CHK_WIDTH = 25
|
|
|
|
attr = dict(
|
|
Name = 'Dialog',
|
|
Title = _('Generate Password'),
|
|
Width = 200,
|
|
Height = 100,
|
|
)
|
|
dialog = app.create_dialog(attr)
|
|
dialog.id = id_extension
|
|
dialog.events = Controllers
|
|
|
|
attr = dict(
|
|
Type = 'Text',
|
|
Name = 'txt_password',
|
|
Width = 150,
|
|
Height = 12,
|
|
X = 5,
|
|
Y = 10,
|
|
EchoChar = ord('*'),
|
|
)
|
|
dialog.add_control(attr)
|
|
|
|
attr = dict(
|
|
Type = 'Button',
|
|
Name = 'cmd_switch',
|
|
Width = BUTTON_WH,
|
|
Height = BUTTON_WH,
|
|
ImageURL = 'eye-close.svg',
|
|
FocusOnClick = True,
|
|
)
|
|
dialog.add_control(attr)
|
|
|
|
attr = dict(
|
|
Type = 'Button',
|
|
Name = 'cmd_new',
|
|
Width = BUTTON_WH,
|
|
Height = BUTTON_WH,
|
|
ImageURL = 'new.svg',
|
|
)
|
|
dialog.add_control(attr)
|
|
|
|
attr = dict(
|
|
Type = 'Label',
|
|
Name = 'lbl_title_length',
|
|
Label = _('Length: '),
|
|
Width = 50,
|
|
Height = BUTTON_WH,
|
|
Border = 1,
|
|
Align = 2,
|
|
VerticalAlign = 1,
|
|
)
|
|
dialog.add_control(attr)
|
|
|
|
attr = dict(
|
|
Type = 'Numeric',
|
|
Name = 'txt_length',
|
|
Width = 50,
|
|
Height = BUTTON_WH,
|
|
DecimalAccuracy = 0,
|
|
Spin = True,
|
|
Value = 25,
|
|
ValueStep = 1,
|
|
ValueMin = 10,
|
|
ValueMax = 100,
|
|
)
|
|
dialog.add_control(attr)
|
|
|
|
attr = dict(
|
|
Type = 'CheckBox',
|
|
Name = 'chk_letters',
|
|
Label = 'A-Z',
|
|
Width = CHK_WIDTH,
|
|
Height = BUTTON_WH,
|
|
)
|
|
dialog.add_control(attr)
|
|
|
|
attr = dict(
|
|
Type = 'CheckBox',
|
|
Name = 'chk_letters2',
|
|
Label = 'a-z',
|
|
Width = CHK_WIDTH,
|
|
Height = BUTTON_WH,
|
|
)
|
|
dialog.add_control(attr)
|
|
|
|
attr = dict(
|
|
Type = 'CheckBox',
|
|
Name = 'chk_digits',
|
|
Label = '0-9',
|
|
Width = CHK_WIDTH,
|
|
Height = BUTTON_WH,
|
|
)
|
|
dialog.add_control(attr)
|
|
|
|
attr = dict(
|
|
Type = 'CheckBox',
|
|
Name = 'chk_punctuation',
|
|
Label = string.punctuation,
|
|
Width = CHK_WIDTH * 4,
|
|
Height = BUTTON_WH,
|
|
)
|
|
dialog.add_control(attr)
|
|
|
|
attr = dict(
|
|
Type = 'Button',
|
|
Name = 'cmd_insert',
|
|
Label = _('~Insert'),
|
|
Width = 70,
|
|
Height = BUTTON_WH,
|
|
ImageURL = 'insert.svg',
|
|
ImagePosition = 1,
|
|
)
|
|
dialog.add_control(attr)
|
|
|
|
attr = dict(
|
|
Type = 'Button',
|
|
Name = 'cmd_close',
|
|
Label = _('~Close'),
|
|
Width = 70,
|
|
Height = BUTTON_WH,
|
|
ImageURL = 'close.svg',
|
|
ImagePosition = 1,
|
|
)
|
|
dialog.add_control(attr)
|
|
|
|
dialog.cmd_switch.move(dialog.txt_password, x=3, y=-2)
|
|
dialog.cmd_new.move(dialog.cmd_switch, x=3, y=0)
|
|
dialog.lbl_title_length.move(dialog.txt_password)
|
|
dialog.txt_length.move(dialog.lbl_title_length, x=3, y=0)
|
|
dialog.chk_letters.move(dialog.lbl_title_length)
|
|
dialog.chk_letters2.move(dialog.chk_letters, x=3, y=0)
|
|
dialog.chk_digits.move(dialog.chk_letters2, x=3, y=0)
|
|
dialog.chk_punctuation.move(dialog.chk_digits, x=3, y=0)
|
|
|
|
dialog.center(dialog.cmd_insert, y=-5)
|
|
dialog.center(dialog.cmd_close, y=-5)
|
|
dialog.center((dialog.cmd_close, dialog.cmd_insert))
|
|
|
|
return dialog
|
|
|
|
|
|
|