commit: 244ace4fee1054945eb97aad31919dba71374b0b Author: Brian Dolbec <dolsen <AT> gentoo <DOT> org> AuthorDate: Fri Dec 26 21:15:22 2014 +0000 Commit: Brian Dolbec <dolsen <AT> gentoo <DOT> org> CommitDate: Tue Dec 30 21:42:25 2014 +0000 URL: http://sources.gentoo.org/gitweb/?p=proj/gentoo-keys.git;a=commit;h=244ace4f
gkeys: Add key-search action Add _list_search() sub function. Add category output and grouping. Fix arg as a list searching as well as seed values as a list. Use recursion to get to single value searches. Make nick search to be partial unless --exact specified. Move main key_search code to SeedHandler class, it is much better suited to this class. Add 1name subparser option for single name entries only Add seen tracking in key_search to eliminate duplicates Add --all option to key-search If --all is specified, it filters out search results to match a seed for all criteria specified. --- gkeys/gkeys/actions.py | 34 ++++++++++++++++++++++++++++++++-- gkeys/gkeys/base.py | 17 +++++++++++++++++ gkeys/gkeys/seed.py | 43 ++++++++++++++++++++++++++++++++++++++++++- gkeys/gkeys/seedhandler.py | 25 +++++++++++++++++++++++++ 4 files changed, 116 insertions(+), 3 deletions(-) diff --git a/gkeys/gkeys/actions.py b/gkeys/gkeys/actions.py index ded3df7..be1823f 100644 --- a/gkeys/gkeys/actions.py +++ b/gkeys/gkeys/actions.py @@ -35,7 +35,7 @@ Seed_Actions = ['----seeds----', 'add-seed', 'fetch-seed', 'list-cats', 'list-seed', 'list-seedfiles', 'move-seed', 'remove-seed'] Key_Actions = ['----keys-----', 'check-key', 'import-key', 'installed', - 'install-key', 'list-key', 'move-key', 'refresh-key', 'remove-key', + 'install-key', 'key-search', 'list-key', 'move-key', 'refresh-key', 'remove-key', 'spec-check'] General_Actions = ['---general---', 'sign','verify'] @@ -56,6 +56,7 @@ Action_Options = { 'move-key': ['nick', 'name', 'keydir', 'fingerprint', 'category', 'keyring', 'dest'], 'installed': ['nick', 'name', 'keydir', 'fingerprint', 'category', 'keyring'], 'import-key': ['nick', 'name', 'keydir', 'fingerprint', 'category', 'keyring'], + 'key-search': ['nick', '1name', 'keydir', 'fingerprint', 'keyid', 'category', 'exact', 'all'], 'verify': ['dest', 'nick', 'name', 'keydir', 'fingerprint', 'category', '1file', 'signature', 'timestamp'], 'check-key': ['nick', 'name', 'keydir', 'fingerprint', 'category', 'keyring', 'keyid'], 'sign': ['nick', 'name', 'keydir', 'fingerprint', 'file', 'keyring'], @@ -80,6 +81,7 @@ Action_Map = { 'move-key': 'movekey', 'installed': 'installed', 'import-key': 'importkey', + 'key-search': 'key_search', 'verify': 'verify', 'check-key': 'checkkey', 'sign': 'sign', @@ -845,5 +847,33 @@ class Actions(object): return (True, ['Completed']) - + def key_search(self, args): + '''Search for a key's seed field in the installed keys db''' + handler = SeedHandler(self.logger, self.config) + results = {} + search_args = [x for x in + ['nick', 'name', 'keydir', 'fingerprint', 'keyid'] + if getattr(args, x)] + if args.category: + handler.load_category(args.category) + results[args.category] = handler.key_search(args, search_args) + else: + for cat in list(self.config.get_key('seeds')): + handler.load_category(cat) + found = handler.key_search(args, search_args) + if found: + if cat in results: + results[cat].extend(found) + else: + results[cat] = found + msgs = [] + for cat in results: + msgs.append("Category: %s" % cat) + seen = [] + for result in results[cat]: + if result and result.nick not in seen: + if isinstance(result, GKEY): + seen.append(result) + msgs.append(seen) + return (True, msgs) diff --git a/gkeys/gkeys/base.py b/gkeys/gkeys/base.py index 499c291..541a12c 100644 --- a/gkeys/gkeys/base.py +++ b/gkeys/gkeys/base.py @@ -46,11 +46,23 @@ class CliBase(object): @staticmethod + def _option_all(parser=None): + parser.add_argument('-a', '--all', dest='all', + action='store_true', default=False, + help='Match all inputs arguments in searches') + + @staticmethod def _option_dest(parser=None): parser.add_argument('-d', '--dest', dest='destination', default=None, help='The destination seed file or keydir for move, copy operations') @staticmethod + def _option_exact(parser=None): + parser.add_argument('-e', '--exact', dest='exact', + action='store_true', default=False, + help='Use CASE matching in searches') + + @staticmethod def _option_fingerprint(parser=None): parser.add_argument('-f', '--fingerprint', dest='fingerprint', default=None, nargs='+', @@ -83,6 +95,11 @@ class CliBase(object): default=None, help='The name of the the key') @staticmethod + def _option_1name(parser=None): + parser.add_argument('-N', '--name', dest='name', + default=None, help='The name of the the key') + + @staticmethod def _option_category(parser=None): parser.add_argument('-C', '--category', dest='category', default=None, diff --git a/gkeys/gkeys/seed.py b/gkeys/gkeys/seed.py index f0cb019..2406c1a 100644 --- a/gkeys/gkeys/seed.py +++ b/gkeys/gkeys/seed.py @@ -160,7 +160,48 @@ class Seeds(object): try: return self.seeds[nick] except KeyError: - return None + return [] + + + def field_search(self, field, value, exact=False): + '''Searches the seeds for a matching nick + + @param keyid: string + @returns GKEY instance or None + ''' + results = [] + if field == 'nick' and exact: + return self.nick_search(value) + for nick in self.seeds: + seed = self.seeds[nick] + val = getattr(seed, field) + if isinstance(val, list) or isinstance(value, list): + if self._list_search(value, val, exact): + results.append(seed) + elif exact: + if value in val: + results.append(seed) + else: + if value.lower() in val.lower(): + results.append(seed) + + return results + + + def _list_search(self, find, values, exact): + if isinstance(find, list): + found = [] + for f in find: + found.append(self._list_search(f, values, exact)) + return True in found + for val in values: + if exact: + if find in val: + return True + else: + if find.lower() in val.lower(): + return True + return False def _error(self, err): diff --git a/gkeys/gkeys/seedhandler.py b/gkeys/gkeys/seedhandler.py index bb233f9..2222bd2 100644 --- a/gkeys/gkeys/seedhandler.py +++ b/gkeys/gkeys/seedhandler.py @@ -26,6 +26,7 @@ class SeedHandler(object): self.logger = logger self.fingerprint_re = re.compile('[0-9A-Fa-f]{40}') self.finerprint_re2 = re.compile('[0-9A-Fa-f]{4}( [0-9A-Fa-f]{4}){9}') + self.seeds = None def new(self, args, checkgkey=False): @@ -77,6 +78,7 @@ class SeedHandler(object): "%s" % filepath) seeds = Seeds(config=self.config) seeds.load(filepath) + self.seeds = seeds return seeds def load_category(self, category, nicks=None): @@ -113,6 +115,7 @@ class SeedHandler(object): except OSError as error: self.logger.debug("SeedHandler: load_category; OSError for %s" % catdir) self.logger.debug("Error was: %s" % str(error)) + self.seeds = seeds return seeds def fetch_seeds(self, seeds, args, verified_dl=None): @@ -188,3 +191,25 @@ class SeedHandler(object): self.logger.error(' GPGKey: Non hexadecimal digits in ' + 'fingerprint for fingerprint: ' + fingerprint) is_good = False return is_good, fingerprint + + def key_search(self, args, search_args): + '''Performs a search for all listed args in the seeds''' + results = [] + self.logger.debug("_field_search search_args: %s" % str(search_args)) + found = {} + search_args.sort() + for arg in search_args: + seeds = self.seeds.field_search(arg, getattr(args, arg), args.exact) + for seed in seeds: + if seed.nick in found: + found[seed.nick]['args'].append(arg) + else: + found[seed.nick] = {'args': [arg], 'seed': seed} + if args.all: + for possible in sorted(found): + if search_args == found[possible]['args']: + results.append(found[possible]['seed']) + else: + for nick in sorted(found): + results.append(found[nick]['seed']) + return results