1 |
commit: 244ace4fee1054945eb97aad31919dba71374b0b |
2 |
Author: Brian Dolbec <dolsen <AT> gentoo <DOT> org> |
3 |
AuthorDate: Fri Dec 26 21:15:22 2014 +0000 |
4 |
Commit: Brian Dolbec <dolsen <AT> gentoo <DOT> org> |
5 |
CommitDate: Tue Dec 30 21:42:25 2014 +0000 |
6 |
URL: http://sources.gentoo.org/gitweb/?p=proj/gentoo-keys.git;a=commit;h=244ace4f |
7 |
|
8 |
gkeys: Add key-search action |
9 |
|
10 |
Add _list_search() sub function. |
11 |
Add category output and grouping. |
12 |
Fix arg as a list searching as well as seed values as a list. |
13 |
Use recursion to get to single value searches. |
14 |
Make nick search to be partial unless --exact specified. |
15 |
Move main key_search code to SeedHandler class, it is much better suited to this class. |
16 |
Add 1name subparser option for single name entries only |
17 |
Add seen tracking in key_search to eliminate duplicates |
18 |
Add --all option to key-search |
19 |
If --all is specified, it filters out search results to match a seed for all criteria specified. |
20 |
|
21 |
--- |
22 |
gkeys/gkeys/actions.py | 34 ++++++++++++++++++++++++++++++++-- |
23 |
gkeys/gkeys/base.py | 17 +++++++++++++++++ |
24 |
gkeys/gkeys/seed.py | 43 ++++++++++++++++++++++++++++++++++++++++++- |
25 |
gkeys/gkeys/seedhandler.py | 25 +++++++++++++++++++++++++ |
26 |
4 files changed, 116 insertions(+), 3 deletions(-) |
27 |
|
28 |
diff --git a/gkeys/gkeys/actions.py b/gkeys/gkeys/actions.py |
29 |
index ded3df7..be1823f 100644 |
30 |
--- a/gkeys/gkeys/actions.py |
31 |
+++ b/gkeys/gkeys/actions.py |
32 |
@@ -35,7 +35,7 @@ Seed_Actions = ['----seeds----', 'add-seed', 'fetch-seed', 'list-cats', |
33 |
'list-seed', 'list-seedfiles', 'move-seed', 'remove-seed'] |
34 |
|
35 |
Key_Actions = ['----keys-----', 'check-key', 'import-key', 'installed', |
36 |
- 'install-key', 'list-key', 'move-key', 'refresh-key', 'remove-key', |
37 |
+ 'install-key', 'key-search', 'list-key', 'move-key', 'refresh-key', 'remove-key', |
38 |
'spec-check'] |
39 |
|
40 |
General_Actions = ['---general---', 'sign','verify'] |
41 |
@@ -56,6 +56,7 @@ Action_Options = { |
42 |
'move-key': ['nick', 'name', 'keydir', 'fingerprint', 'category', 'keyring', 'dest'], |
43 |
'installed': ['nick', 'name', 'keydir', 'fingerprint', 'category', 'keyring'], |
44 |
'import-key': ['nick', 'name', 'keydir', 'fingerprint', 'category', 'keyring'], |
45 |
+ 'key-search': ['nick', '1name', 'keydir', 'fingerprint', 'keyid', 'category', 'exact', 'all'], |
46 |
'verify': ['dest', 'nick', 'name', 'keydir', 'fingerprint', 'category', '1file', 'signature', 'timestamp'], |
47 |
'check-key': ['nick', 'name', 'keydir', 'fingerprint', 'category', 'keyring', 'keyid'], |
48 |
'sign': ['nick', 'name', 'keydir', 'fingerprint', 'file', 'keyring'], |
49 |
@@ -80,6 +81,7 @@ Action_Map = { |
50 |
'move-key': 'movekey', |
51 |
'installed': 'installed', |
52 |
'import-key': 'importkey', |
53 |
+ 'key-search': 'key_search', |
54 |
'verify': 'verify', |
55 |
'check-key': 'checkkey', |
56 |
'sign': 'sign', |
57 |
@@ -845,5 +847,33 @@ class Actions(object): |
58 |
return (True, ['Completed']) |
59 |
|
60 |
|
61 |
- |
62 |
+ def key_search(self, args): |
63 |
+ '''Search for a key's seed field in the installed keys db''' |
64 |
+ handler = SeedHandler(self.logger, self.config) |
65 |
+ results = {} |
66 |
+ search_args = [x for x in |
67 |
+ ['nick', 'name', 'keydir', 'fingerprint', 'keyid'] |
68 |
+ if getattr(args, x)] |
69 |
+ if args.category: |
70 |
+ handler.load_category(args.category) |
71 |
+ results[args.category] = handler.key_search(args, search_args) |
72 |
+ else: |
73 |
+ for cat in list(self.config.get_key('seeds')): |
74 |
+ handler.load_category(cat) |
75 |
+ found = handler.key_search(args, search_args) |
76 |
+ if found: |
77 |
+ if cat in results: |
78 |
+ results[cat].extend(found) |
79 |
+ else: |
80 |
+ results[cat] = found |
81 |
+ msgs = [] |
82 |
+ for cat in results: |
83 |
+ msgs.append("Category: %s" % cat) |
84 |
+ seen = [] |
85 |
+ for result in results[cat]: |
86 |
+ if result and result.nick not in seen: |
87 |
+ if isinstance(result, GKEY): |
88 |
+ seen.append(result) |
89 |
+ msgs.append(seen) |
90 |
+ return (True, msgs) |
91 |
|
92 |
|
93 |
diff --git a/gkeys/gkeys/base.py b/gkeys/gkeys/base.py |
94 |
index 499c291..541a12c 100644 |
95 |
--- a/gkeys/gkeys/base.py |
96 |
+++ b/gkeys/gkeys/base.py |
97 |
@@ -46,11 +46,23 @@ class CliBase(object): |
98 |
|
99 |
|
100 |
@staticmethod |
101 |
+ def _option_all(parser=None): |
102 |
+ parser.add_argument('-a', '--all', dest='all', |
103 |
+ action='store_true', default=False, |
104 |
+ help='Match all inputs arguments in searches') |
105 |
+ |
106 |
+ @staticmethod |
107 |
def _option_dest(parser=None): |
108 |
parser.add_argument('-d', '--dest', dest='destination', default=None, |
109 |
help='The destination seed file or keydir for move, copy operations') |
110 |
|
111 |
@staticmethod |
112 |
+ def _option_exact(parser=None): |
113 |
+ parser.add_argument('-e', '--exact', dest='exact', |
114 |
+ action='store_true', default=False, |
115 |
+ help='Use CASE matching in searches') |
116 |
+ |
117 |
+ @staticmethod |
118 |
def _option_fingerprint(parser=None): |
119 |
parser.add_argument('-f', '--fingerprint', dest='fingerprint', |
120 |
default=None, nargs='+', |
121 |
@@ -83,6 +95,11 @@ class CliBase(object): |
122 |
default=None, help='The name of the the key') |
123 |
|
124 |
@staticmethod |
125 |
+ def _option_1name(parser=None): |
126 |
+ parser.add_argument('-N', '--name', dest='name', |
127 |
+ default=None, help='The name of the the key') |
128 |
+ |
129 |
+ @staticmethod |
130 |
def _option_category(parser=None): |
131 |
parser.add_argument('-C', '--category', |
132 |
dest='category', default=None, |
133 |
|
134 |
diff --git a/gkeys/gkeys/seed.py b/gkeys/gkeys/seed.py |
135 |
index f0cb019..2406c1a 100644 |
136 |
--- a/gkeys/gkeys/seed.py |
137 |
+++ b/gkeys/gkeys/seed.py |
138 |
@@ -160,7 +160,48 @@ class Seeds(object): |
139 |
try: |
140 |
return self.seeds[nick] |
141 |
except KeyError: |
142 |
- return None |
143 |
+ return [] |
144 |
+ |
145 |
+ |
146 |
+ def field_search(self, field, value, exact=False): |
147 |
+ '''Searches the seeds for a matching nick |
148 |
+ |
149 |
+ @param keyid: string |
150 |
+ @returns GKEY instance or None |
151 |
+ ''' |
152 |
+ results = [] |
153 |
+ if field == 'nick' and exact: |
154 |
+ return self.nick_search(value) |
155 |
+ for nick in self.seeds: |
156 |
+ seed = self.seeds[nick] |
157 |
+ val = getattr(seed, field) |
158 |
+ if isinstance(val, list) or isinstance(value, list): |
159 |
+ if self._list_search(value, val, exact): |
160 |
+ results.append(seed) |
161 |
+ elif exact: |
162 |
+ if value in val: |
163 |
+ results.append(seed) |
164 |
+ else: |
165 |
+ if value.lower() in val.lower(): |
166 |
+ results.append(seed) |
167 |
+ |
168 |
+ return results |
169 |
+ |
170 |
+ |
171 |
+ def _list_search(self, find, values, exact): |
172 |
+ if isinstance(find, list): |
173 |
+ found = [] |
174 |
+ for f in find: |
175 |
+ found.append(self._list_search(f, values, exact)) |
176 |
+ return True in found |
177 |
+ for val in values: |
178 |
+ if exact: |
179 |
+ if find in val: |
180 |
+ return True |
181 |
+ else: |
182 |
+ if find.lower() in val.lower(): |
183 |
+ return True |
184 |
+ return False |
185 |
|
186 |
|
187 |
def _error(self, err): |
188 |
|
189 |
diff --git a/gkeys/gkeys/seedhandler.py b/gkeys/gkeys/seedhandler.py |
190 |
index bb233f9..2222bd2 100644 |
191 |
--- a/gkeys/gkeys/seedhandler.py |
192 |
+++ b/gkeys/gkeys/seedhandler.py |
193 |
@@ -26,6 +26,7 @@ class SeedHandler(object): |
194 |
self.logger = logger |
195 |
self.fingerprint_re = re.compile('[0-9A-Fa-f]{40}') |
196 |
self.finerprint_re2 = re.compile('[0-9A-Fa-f]{4}( [0-9A-Fa-f]{4}){9}') |
197 |
+ self.seeds = None |
198 |
|
199 |
|
200 |
def new(self, args, checkgkey=False): |
201 |
@@ -77,6 +78,7 @@ class SeedHandler(object): |
202 |
"%s" % filepath) |
203 |
seeds = Seeds(config=self.config) |
204 |
seeds.load(filepath) |
205 |
+ self.seeds = seeds |
206 |
return seeds |
207 |
|
208 |
def load_category(self, category, nicks=None): |
209 |
@@ -113,6 +115,7 @@ class SeedHandler(object): |
210 |
except OSError as error: |
211 |
self.logger.debug("SeedHandler: load_category; OSError for %s" % catdir) |
212 |
self.logger.debug("Error was: %s" % str(error)) |
213 |
+ self.seeds = seeds |
214 |
return seeds |
215 |
|
216 |
def fetch_seeds(self, seeds, args, verified_dl=None): |
217 |
@@ -188,3 +191,25 @@ class SeedHandler(object): |
218 |
self.logger.error(' GPGKey: Non hexadecimal digits in ' + 'fingerprint for fingerprint: ' + fingerprint) |
219 |
is_good = False |
220 |
return is_good, fingerprint |
221 |
+ |
222 |
+ def key_search(self, args, search_args): |
223 |
+ '''Performs a search for all listed args in the seeds''' |
224 |
+ results = [] |
225 |
+ self.logger.debug("_field_search search_args: %s" % str(search_args)) |
226 |
+ found = {} |
227 |
+ search_args.sort() |
228 |
+ for arg in search_args: |
229 |
+ seeds = self.seeds.field_search(arg, getattr(args, arg), args.exact) |
230 |
+ for seed in seeds: |
231 |
+ if seed.nick in found: |
232 |
+ found[seed.nick]['args'].append(arg) |
233 |
+ else: |
234 |
+ found[seed.nick] = {'args': [arg], 'seed': seed} |
235 |
+ if args.all: |
236 |
+ for possible in sorted(found): |
237 |
+ if search_args == found[possible]['args']: |
238 |
+ results.append(found[possible]['seed']) |
239 |
+ else: |
240 |
+ for nick in sorted(found): |
241 |
+ results.append(found[nick]['seed']) |
242 |
+ return results |