15
15
import pyaes
16
16
17
17
18
+ # TODO
19
+ # Remove account
20
+ # - Python 3 support
21
+ # - To use pyperclip???
22
+ # - Consider these libraries:
23
+ # https://github.com/italorossi/ishell
24
+ # https://github.com/jonathanslenders/python-prompt-toolkit
25
+ # Print and ask copy to clipboard
26
+ # To use module in pure python for symmetric encription instead of gnugpg
27
+ # Mirar esto:
28
+ # https://stackoverflow.com/questions/42568262/how-to-encrypt-text-with-a-value-in-python/44212550
29
+ # hashlib.sha256("Nobody inspects the spammish repetition").hexdigest()
30
+
18
31
WHICH_CMD = 'which'
19
32
CLIPBOARD_ENCODING = 'utf-8'
20
33
21
34
LIST_OF_TRUE_VALUES = ["y" , "yes" , "1" , "on" ]
22
35
LIST_OF_FALSE_VALUES = ["n" , "no" , "0" , "off" ]
23
36
24
37
38
+ def get_boolean (c ):
39
+ if isinstance (c , bool ):
40
+ return c
41
+ else :
42
+ c = c .strip ().lower ()
43
+ if c in LIST_OF_TRUE_VALUES :
44
+ return True
45
+ elif show_values in LIST_OF_FALSE_VALUES :
46
+ return False
47
+
48
+ def echo (m , indent = 0 ):
49
+ print (" " * indent + m )
50
+
51
+
25
52
def _executable_exists (name ):
26
53
return subprocess .call ([WHICH_CMD , name ],
27
54
stdout = subprocess .PIPE , stderr = subprocess .PIPE ) == 0
@@ -271,7 +298,7 @@ def create_account(cls, password_manager, account_name, keys):
271
298
return Account (password_manager , account_element )
272
299
273
300
274
- def print_account (self , indent = " " , show_values = False ):
301
+ def dump (self , indent = " " , show_values = False ):
275
302
account_element = self .root
276
303
277
304
name = account_element ['account_name' ].encode (sys .stdout .encoding )
@@ -295,16 +322,14 @@ def remove(self):
295
322
296
323
297
324
class Password_Manager (object ):
298
-
299
- TITLE = "Password Manager"
300
-
301
- def __init__ (self , filename ):
325
+ def __init__ (self , filename , master_password = None , title = "Password Manager" ):
302
326
self ._filename = filename
303
- self ._master_password = None
327
+ self ._master_password = master_password
304
328
305
329
self ._show_values = False
306
330
307
331
self ._root = None
332
+ self ._title = title
308
333
309
334
def all_accounts (self ):
310
335
list_of_accounts = []
@@ -515,7 +540,7 @@ def command_delete(self, index=None):
515
540
account = self .ask_account_index (index )
516
541
517
542
if self .ask_confirmation ("are you sure that you want to delete this account?" ):
518
- account .print_account (show_values = self ._show_values )
543
+ account .dump (show_values = self ._show_values )
519
544
520
545
account .remove ()
521
546
self .save_accounts ()
@@ -538,7 +563,7 @@ def command_clipboard(self, index=None, key=None):
538
563
elif num_keys == 1 :
539
564
value = account .get_key (0 )["value" ]
540
565
else :
541
- account .print_account (show_values = False )
566
+ account .dump (show_values = False )
542
567
key_index = raw_input ("\n Key index: " )
543
568
544
569
value = account .get_key (key_index )["value" ]
@@ -561,7 +586,7 @@ def command_edit(self, index=None):
561
586
562
587
while True :
563
588
print ("" )
564
- account .print_account (show_values = self ._show_values )
589
+ account .dump (show_values = self ._show_values )
565
590
566
591
print ("\n Select option:" )
567
592
print (" 1. Edit key name" )
@@ -617,7 +642,7 @@ def command_rename(self, index=None):
617
642
self ._rename (account )
618
643
619
644
620
- @cmd ("search" , "s" )
645
+ @cmd ("search" )
621
646
def command_search (self , account_pattern = None , show_values = None ):
622
647
"""Search account"""
623
648
@@ -632,7 +657,7 @@ def command_search(self, account_pattern=None, show_values=None):
632
657
if account is None :
633
658
raise AccountNotFoundException
634
659
else :
635
- account .print_account (show_values = self ._show_values )
660
+ account .dump (show_values = self ._show_values )
636
661
637
662
638
663
@cmd ("print" , "p" )
@@ -643,41 +668,40 @@ def command_print(self, index=None, show_values=None):
643
668
if show_values is None :
644
669
show_values = self ._show_values
645
670
else :
646
- show_values = show_values .strip ().lower ()
647
- if show_values in LIST_OF_TRUE_VALUES :
648
- show_values = True
649
- elif show_values in LIST_OF_FALSE_VALUES :
650
- show_values = False
651
- else :
671
+ show_values = get_boolean (show_values )
672
+ if show_values is None :
652
673
raise PasswordManagerException ("Not valid 'show_values' parameter: %s" % show_values )
653
674
654
- account .print_account (show_values = show_values )
675
+ account .dump (show_values = show_values )
655
676
656
677
657
- @cmd ("print_all" , "pa" )
678
+ @cmd ("print_all" )
658
679
def command_print_all (self , show_values = None ):
659
680
"""Print all accounts"""
660
681
661
682
if show_values is None :
662
683
show_values = self ._show_values
663
684
else :
664
- show_values = show_values .strip ().lower ()
665
- if show_values in LIST_OF_TRUE_VALUES :
666
- show_values = True
667
- elif show_values in LIST_OF_FALSE_VALUES :
668
- show_values = False
669
- else :
685
+ show_values = get_boolean (show_values )
686
+ if show_values is None :
670
687
raise PasswordManagerException ("Not valid 'show_values' parameter: %s" % show_values )
671
688
672
689
first = True
673
690
for i , account in enumerate (self .all_accounts ()):
674
691
print ("%s. " % i )
675
- account .print_account (show_values = show_values )
692
+ account .dump (show_values = show_values )
676
693
if first :
677
694
first = False
678
695
else :
679
696
print ("-" * 40 )
680
697
698
+
699
+ @cmd ("show" , "s" )
700
+ def command_show (self , index = None ):
701
+ """Show all data of specific account"""
702
+ self .command_print (index = index , show_values = True )
703
+
704
+
681
705
@cmd ("show_values" )
682
706
def command_show_values (self ):
683
707
"""Show values"""
@@ -727,39 +751,47 @@ def run(self):
727
751
info_print ("A new value file will be created." )
728
752
new_file = True
729
753
730
- try :
731
- self ._master_password = getpass .getpass ("Write the master password.\n " )
732
- except KeyboardInterrupt :
733
- sys .exit ()
734
-
735
- if new_file :
754
+ if self ._master_password is None :
736
755
try :
737
- repeated_master_password = getpass .getpass ("Repeat password.\n " )
756
+ master_password = getpass .getpass ("Write the master password.\n " )
738
757
except KeyboardInterrupt :
739
- sys . exit ()
758
+ return
740
759
741
- if self ._master_password != repeated_master_password :
742
- error_print ("values doesn't coincide" )
743
- sys .exit ()
760
+ if master_password == "" :
761
+ return
744
762
763
+ if new_file :
764
+ if self ._master_password is None :
765
+ try :
766
+ repeated_master_password = getpass .getpass ("Repeat password.\n " )
767
+ except KeyboardInterrupt :
768
+ return
769
+
770
+ if master_password != repeated_master_password :
771
+ error_print ("values doesn't coincide" )
772
+ return
773
+
774
+ self ._master_password = master_password
745
775
self ._root = {"accounts" : []}
746
776
747
777
self .save_accounts ()
748
778
else :
779
+ self ._master_password = master_password
780
+
749
781
with open (self ._filename , "rb" ) as f :
750
782
enc_data = f .read ()
751
783
752
784
try :
753
785
root = decrypt (enc_data , self ._master_password )
754
786
except DecryptionException as e :
755
787
error_print ("Error doing decryption:\n %s" % str (e ))
756
- sys . exit ()
788
+ return
757
789
758
790
self ._root = json .loads (root )
759
791
760
792
clear_screen ()
761
793
762
- header = "-" * len (self .TITLE ) + "\n " + self .TITLE + "\n " + "-" * len (self .TITLE ) + "\n "
794
+ header = "-" * len (self ._title ) + "\n " + self ._title + "\n " + "-" * len (self ._title ) + "\n "
763
795
print (header )
764
796
765
797
@@ -776,19 +808,27 @@ def run(self):
776
808
try :
777
809
user_input = raw_input ("\n \n Command: " )
778
810
except KeyboardInterrupt :
779
- sys . exit ()
811
+ return
780
812
781
813
print ("" )
782
814
783
815
command = shlex .split (user_input )
784
- command_name = command [0 ]
816
+ command_name = command [0 ]. lower ()
785
817
786
818
if command_name in self .LIST_OF_COMMANDS :
787
819
command_function = getattr (self , self .LIST_OF_COMMANDS [command_name ])
788
- command_args = command [1 :]
820
+ args = []
821
+ kwargs = {}
822
+
823
+ for t in command [1 :]:
824
+ if "=" in t :
825
+ key , value = t .split ("=" )
826
+ kwargs [key ] = value
827
+ else :
828
+ args .append (t )
789
829
790
830
try :
791
- command_function (* command_args )
831
+ command_function (* args , ** kwargs )
792
832
except PasswordManagerException as e :
793
833
error_print (str (e ))
794
834
except KeyboardInterrupt :
0 commit comments