| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 | #============================================================================# This file is part of Pwman3.## Pwman3 is free software; you can redistribute it and/or modify# it under the terms of the GNU General Public License, version 2# as published by the Free Software Foundation;## Pwman3 is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the# GNU General Public License for more details.## You should have received a copy of the GNU General Public License# along with Pwman3; if not, write to the Free Software# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA#============================================================================# Copyright (C) 2013 Oz Nahum <nahumoz@gmail.com>#============================================================================"""Define the CLI interface for pwman3 and the helper functions"""from __future__ import print_functionfrom pwman.util.callback import Callbackimport pwman.util.config as configimport subprocess as spimport getpassimport sysimport structimport osimport coloramafrom pwman.data.tags import TagNew as Tagfrom pwman.util.config import get_pass_confimport pwman.util.generator as generatorif sys.version_info.major > 2:    raw_input = inputif sys.platform != 'win32':    import termios    import fcntl    import tty    import readline    _readline_available = Trueelse:  # pragma: no cover    try:        #import pyreadline as readline        import readline        _readline_available = True    except ImportError as e:        _readline_available = False_defaultwidth = 10class ANSI(object):    """    ANSI Colors    """    Reset = 0    Bold = 1    Underscore = 2    Black = 30    Red = 31    Green = 32    Yellow = 33    Blue = 34    Magenta = 35    Cyan = 36    White = 37def typeset(text, color, bold=False, underline=False):  # pragma: no cover    """    print colored strings using colorama    """    if not config.get_value("Global", "colors") == 'yes':        return text    if bold:        text = colorama.Style.BRIGHT + text    if underline and not 'win32' in sys.platform:        text = ANSI.Underscore + text    return color + text + colorama.Style.RESET_ALLdef select(question, possible):  # pragma: no cover    """    select input from user    """    for i in range(0, len(possible)):        print ("%d - %-" + str(_defaultwidth) + "s") % (i + 1, possible[i])    while 1:        uinput = getonechar(question)        if uinput.isdigit() and int(uinput) in range(1, len(possible) + 1):            return possible[int(uinput) - 1]def text_to_clipboards(text):  # pragma: no cover    """    copy text to clipboard    credit:    https://pythonadventures.wordpress.com/tag/xclip/    """    # "primary":    try:        xsel_proc = sp.Popen(['xsel', '-pi'], stdin=sp.PIPE)        xsel_proc.communicate(text)        # "clipboard":        xsel_proc = sp.Popen(['xsel', '-bi'], stdin=sp.PIPE)        xsel_proc.communicate(text)    except OSError as e:        print (e, "\nExecuting xsel failed, is it installed ?\n \               please check your configuration file ... ")def text_to_mcclipboard(text):  # pragma: no cover    """    copy text to mac os x clip board    credit:    https://pythonadventures.wordpress.com/tag/xclip/    """    # "primary":    try:        pbcopy_proc = sp.Popen(['pbcopy'], stdin=sp.PIPE)        pbcopy_proc.communicate(text)    except OSError as e:        print (e, "\nExecuting pbcoy failed...")def open_url(link, macosx=False):  # pragma: no cover    """    launch xdg-open or open in MacOSX with url    """    uopen = "xdg-open"    if macosx:        uopen = "open"    try:        sp.Popen([uopen, link], stdin=sp.PIPE)    except OSError as e:        print ("Executing open_url failed with:\n", e)def getpassword(question, argsgiven=None,                width=_defaultwidth, echo=False,                reader=getpass.getpass, numerics=False, leetify=False,                symbols=False, special_signs=False,                length=None):  # pragma: no cover    # TODO: getpassword should recieve a config insatnce    #       and generate the policy according to it,    #       so that getpassword in cli would be simplified    if argsgiven == 1 or length:        while not length:            try:                default_length = config.get_value(                    'Generator', 'default_pw_length') or '7'                length = getinput(                    "Password length (default %s): " % default_length,                    default=default_length)                length = int(length)            except ValueError:                print("please enter a proper integer")        password, dumpme = generator.generate_password(            length, length, True, symbols=leetify, numerics=numerics,            special_chars=special_signs)        print ("New password: %s" % (password))        return password    # no args given    while True:        a1 = reader(question.ljust(width))        if not a1:            return getpassword(                    '', argsgiven=1, width=width, echo=echo, reader=reader,                    numerics=numerics, leetify=leetify, symbols=symbols,                    special_signs=special_signs, length=length)        a2 = reader("[Repeat] %s" % (question.ljust(width)))        if a1 == a2:            if leetify:                return generator.leetify(a1)            else:                return a1        else:            print ("Passwords don't match. Try again.")def gettermsize():  # pragma: no cover    s = struct.pack("HHHH", 0, 0, 0, 0)    f = sys.stdout.fileno()    x = fcntl.ioctl(f, termios.TIOCGWINSZ, s)    rows, cols, width, height = struct.unpack("HHHH", x)    return rows, colsdef getinput(question, default="", reader=raw_input,             completer=None, width=_defaultwidth):  # pragma: no cover    """    http://stackoverflow.com/questions/2617057/\            supply-inputs-to-python-unittests    """    if reader == raw_input:        if not _readline_available:            val = raw_input(question.ljust(width))            if val:                return val            else:                return default        else:            def defaulter():                """define default behavior startup"""                if _readline_available:                    readline.insert_text(default)                readline.set_startup_hook(defaulter)                readline.get_completer()                readline.set_completer(completer)            x = raw_input(question.ljust(width))            readline.set_completer(completer)            readline.set_startup_hook()            if not x:                return default            return x    else:        return reader()class CMDLoop(object):  # pragma: no cover    """    The menu that drives editing of a node    """    def __init__(self):        self.items = []    def add(self, item):        if (isinstance(item, CliMenuItem)):            self.items.append(item)        else:            print (item.__class__)    def run(self, new_node=None):        while True:            i = 0            for x in self.items:                i = i + 1                try:                    current = x.getter                except AttributeError:                    current = x                # when printing tags, we have list ...                currentstr = ''                if type(current) == list:                    for c in current:                        try:                            currentstr += ' ' + c                        except TypeError:                            currentstr += ' ' + c.name                # for the case we are not dealing with                # a list of tags                else:                    currentstr = current                print ("%s - %s: %s" % (i, x.name, currentstr))            print("X - Finish editing")            option = getonechar("Enter your choice:")            try:                print ("Selection, ", option)                # substract 1 because array subscripts start at 0                selection = int(option) - 1                # new value is created by calling the editor with the                # previous value as a parameter                # TODO: enable overriding password policy as if new node                # is created.                if selection == 0:                    new_node.username = getinput("Username:")                    self.items[0].getter = new_node.username                    self.items[0].setter = new_node.username                elif selection == 1:  # for password                    numerics, leet, s_chars = get_pass_conf()                    new_node.password = getpassword(                            'New Password:', numerics=numerics, leetify=leet,                            special_signs=s_chars)                    self.items[1].getter = new_node.password                    self.items[1].setter = new_node.password                elif selection == 2:                    new_node.url = getinput("Url:")                    self.items[2].getter = new_node.url                    self.items[2].setter = new_node.url                elif selection == 3:  # for notes                    # new_node.notes = getinput("Notes:")                    new_node.notes = getinput("Notes:")                    self.items[3].getter = new_node.notes                    self.items[3].setter = new_node.notes                elif selection == 4:                    taglist = getinput("Tags:")                    tagstrings = taglist.split()                    tags = [Tag(tn) for tn in tagstrings]                    new_node.tags = tags                    self.items[4].setter = new_node.tags                    self.items[4].getter = new_node.tags            except (ValueError, IndexError):                if (option.upper() == 'X'):                    break                print("Invalid selection")def getonechar(question, width=_defaultwidth):  # pragma: no cover    question = "%s " % (question)    print (question.ljust(width),)    try:        sys.stdout.flush()        fd = sys.stdin.fileno()        # tty module exists only if we are on Posix        try:            tty_mode = tty.tcgetattr(fd)            tty.setcbreak(fd)        except NameError:            pass        try:            ch = os.read(fd, 1)        finally:            try:                tty.tcsetattr(fd, tty.TCSAFLUSH, tty_mode)            except NameError:                pass    except AttributeError:        ch = sys.stdin.readline()[0]    print(ch)    return chclass CliMenuItem(object):  # pragma: no cover    def __init__(self, name, editor, getter, setter):        self.name = name        self.editor = editor        self.getter = getter        self.setter = setterclass CLICallback(Callback):  # pragma: no cover    def getinput(self, question):        return raw_input(question)    def getsecret(self, question):        return getpass.getpass(question + ":")    def getnewsecret(self, question):        return getpass.getpass(question + ":")
 |