baseui.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. # ===========================================================================
  2. # This file is part of Pwman3.
  3. #
  4. # Pwman3 is free software; you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License, version 2
  6. # as published by the Free Software Foundation;
  7. #
  8. # Pwman3 is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with Pwman3; if not, write to the Free Software
  15. # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. # ============================================================================
  17. # Copyright (C) 2013, 2014 Oz Nahum Tiram <nahumoz@gmail.com>
  18. # ============================================================================
  19. from __future__ import print_function
  20. from pwman.util.crypto_engine import CryptoEngine
  21. import sys
  22. import os
  23. from pwman.ui import tools
  24. from colorama import Fore
  25. from pwman.data.nodes import Node
  26. import getpass
  27. import ast
  28. import csv
  29. if sys.version_info.major > 2:
  30. raw_input = input
  31. from .base import HelpUI
  32. class BaseCommands(HelpUI):
  33. def do_copy(self, args): # pargma: no cover
  34. """copy item to clipboard"""
  35. pass
  36. def do_open(self, args): # pragma: no cover
  37. ids = self.get_ids(args)
  38. if not args:
  39. self.help_open()
  40. return
  41. nodes = self._db.getnodes(ids)
  42. for node in nodes:
  43. ce = CryptoEngine.get()
  44. url = ce.decrypt(node[3])
  45. tools.open_url(url)
  46. def do_exit(self, args): # pragma: no cover
  47. """close the text console"""
  48. self._db.close()
  49. return True
  50. def do_cls(self, args): # pragma: no cover
  51. """clear the screen"""
  52. os.system("clear")
  53. def do_edit(self, args):
  54. """edit a node"""
  55. pass
  56. def do_export(self, args):
  57. """export the database to a given format"""
  58. try:
  59. args = ast.literal_eval(args)
  60. except Exception:
  61. args = {}
  62. filename = args.get('filename', 'pwman-export.csv')
  63. delim = args.get('delimiter', ';')
  64. nodeids = self._db.listnodes()
  65. nodes = self._db.getnodes(nodeids)
  66. with open(filename, 'w') as csvfile:
  67. writer = csv.writer(csvfile, delimiter=delim)
  68. writer.writerow(['Username', 'URL', 'Password', 'Notes',
  69. 'Tags'])
  70. for node in nodes:
  71. n = Node.from_encrypted_entries(node[1], node[2], node[3],
  72. node[4],
  73. node[5:])
  74. tags = n.tags
  75. tags = ','.join(t.strip().decode() for t in tags)
  76. r = list(map(bytes.decode, [n.username, n.url, n.password,
  77. n.notes]))
  78. writer.writerow(r + [tags])
  79. print("Successfuly exported database to {}".format(
  80. os.path.join(os.getcwd(), filename)))
  81. def do_forget(self, args):
  82. """
  83. drop saved key forcing the user to re-enter the master
  84. password
  85. """
  86. enc = CryptoEngine.get()
  87. enc.forget()
  88. def do_passwd(self, args):
  89. """change the master password of the database"""
  90. pass
  91. def do_tags(self, args):
  92. """
  93. print all existing tags
  94. """
  95. ce = CryptoEngine.get()
  96. print("Tags:")
  97. tags = self._db.listtags()
  98. for t in tags:
  99. print(ce.decrypt(t).decode())
  100. def _get_tags(self, default=None, reader=raw_input):
  101. """
  102. Read tags from user input.
  103. Tags are simply returned as a list
  104. """
  105. # TODO: add method to read tags from db, so they
  106. # could be used for tab completer
  107. print("Tags: ", end="")
  108. sys.stdout.flush()
  109. taglist = sys.stdin.readline()
  110. tagstrings = taglist.split()
  111. tags = [tn for tn in tagstrings]
  112. return tags
  113. def _prep_term(self):
  114. self.do_cls('')
  115. if sys.platform != 'win32':
  116. rows, cols = tools.gettermsize()
  117. else:
  118. rows, cols = 18, 80 # fix this !
  119. cols -= 8
  120. return rows, cols
  121. def _format_line(self, tag_pad, nid="ID", user="USER", url="URL",
  122. tags="TAGS"):
  123. return ("{ID:<3} {USER:<{us}}{URL:<{ur}}{Tags:<{tg}}"
  124. "".format(ID=nid, USER=user,
  125. URL=url, Tags=tags, us=12,
  126. ur=20, tg=tag_pad - 32))
  127. def _print_node_line(self, node, rows, cols):
  128. tagstring = ','.join([t.decode() for t in node.tags])
  129. fmt = self._format_line(cols - 32, node._id, node.username.decode(),
  130. node.url.decode(),
  131. tagstring)
  132. formatted_entry = tools.typeset(fmt, Fore.YELLOW, False)
  133. print(formatted_entry)
  134. def _get_node_ids(self, args):
  135. filter = None
  136. if args:
  137. filter = args.split()[0]
  138. ce = CryptoEngine.get()
  139. filter = ce.encrypt(filter)
  140. nodeids = self._db.listnodes(filter=filter)
  141. return nodeids
  142. def do_list(self, args):
  143. """list all existing nodes in database"""
  144. rows, cols = self._prep_term()
  145. nodeids = self._get_node_ids(args)
  146. nodes = self._db.getnodes(nodeids)
  147. _nodes_inst = []
  148. # user, pass, url, notes
  149. for node in nodes:
  150. _nodes_inst.append(Node.from_encrypted_entries(
  151. node[1],
  152. node[2],
  153. node[3],
  154. node[4],
  155. node[5:]))
  156. _nodes_inst[-1]._id = node[0]
  157. head = self._format_line(cols-32)
  158. print(tools.typeset(head, Fore.YELLOW, False))
  159. for idx, node in enumerate(_nodes_inst):
  160. self._print_node_line(node, rows, cols)
  161. def _get_input(self, prompt):
  162. print(prompt, end="")
  163. sys.stdout.flush()
  164. return sys.stdin.readline()
  165. def _get_secret(self):
  166. # TODO: enable old functionallity, with password generator.
  167. if sys.stdin.isatty(): # pragma: no cover
  168. p = getpass.getpass()
  169. else:
  170. p = sys.stdin.readline().rstrip()
  171. return p
  172. def do_new(self, args):
  173. node = {}
  174. node['username'] = self._get_input("Username: ")
  175. node['password'] = self._get_secret()
  176. node['url'] = self._get_input("Url: ")
  177. node['notes'] = self._get_input("Notes: ")
  178. node['tags'] = self._get_tags()
  179. node = Node(clear_text=True, **node)
  180. self._db.add_node(node)
  181. return node