1 /*
2 * Seahorse
3 *
4 * Copyright (C) 2005 Stefan Walter
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 */
18 #include "config.h"
19
20 #include <string.h>
21
22 #include <glib/gi18n.h>
23
24 #include "seahorse-gtkstock.h"
25 #include "seahorse-object-list.h"
26 #include "seahorse-pgp.h"
27 #include "seahorse-pgp-key.h"
28 #include "seahorse-pgp-uid.h"
29 #include "seahorse-pgp-subkey.h"
30 #include "seahorse-source.h"
31 #include "seahorse-util.h"
32
33 enum {
34 PROP_0,
35 PROP_SUBKEYS,
36 PROP_UIDS,
37 PROP_FINGERPRINT,
38 PROP_VALIDITY,
39 PROP_VALIDITY_STR,
40 PROP_TRUST,
41 PROP_TRUST_STR,
42 PROP_EXPIRES,
43 PROP_EXPIRES_STR,
44 PROP_LENGTH,
45 PROP_ALGO
46 };
47
48 G_DEFINE_TYPE (SeahorsePgpKey, seahorse_pgp_key, SEAHORSE_TYPE_OBJECT);
49
50 struct _SeahorsePgpKeyPrivate {
51 GList *uids; /* All the UID objects */
52 GList *subkeys; /* All the Subkey objects */
53 };
54
55 /* -----------------------------------------------------------------------------
56 * INTERNAL HELPERS
57 */
58
59 static const gchar*
calc_short_name(SeahorsePgpKey * self)60 calc_short_name (SeahorsePgpKey *self)
61 {
62 GList *uids = seahorse_pgp_key_get_uids (self);
63 return uids ? seahorse_pgp_uid_get_name (uids->data) : NULL;
64 }
65
66 static gchar*
calc_name(SeahorsePgpKey * self)67 calc_name (SeahorsePgpKey *self)
68 {
69 GList *uids = seahorse_pgp_key_get_uids (self);
70 return uids ? seahorse_pgp_uid_calc_label (seahorse_pgp_uid_get_name (uids->data),
71 seahorse_pgp_uid_get_email (uids->data),
72 seahorse_pgp_uid_get_comment (uids->data)) : g_strdup ("");
73 }
74
75 static gchar*
calc_markup(SeahorsePgpKey * self,guint flags)76 calc_markup (SeahorsePgpKey *self, guint flags)
77 {
78 GList *uids = seahorse_pgp_key_get_uids (self);
79 return uids ? seahorse_pgp_uid_calc_markup (seahorse_pgp_uid_get_name (uids->data),
80 seahorse_pgp_uid_get_email (uids->data),
81 seahorse_pgp_uid_get_comment (uids->data), flags) : g_strdup ("");
82 }
83
84 /* -----------------------------------------------------------------------------
85 * OBJECT
86 */
87
88 static GList*
_seahorse_pgp_key_get_uids(SeahorsePgpKey * self)89 _seahorse_pgp_key_get_uids (SeahorsePgpKey *self)
90 {
91 g_return_val_if_fail (SEAHORSE_IS_PGP_KEY (self), NULL);
92 return self->pv->uids;
93 }
94
95 static void
_seahorse_pgp_key_set_uids(SeahorsePgpKey * self,GList * uids)96 _seahorse_pgp_key_set_uids (SeahorsePgpKey *self, GList *uids)
97 {
98 guint index;
99 GQuark id;
100 GList *l;
101
102 g_return_if_fail (SEAHORSE_IS_PGP_KEY (self));
103
104 id = seahorse_object_get_id (SEAHORSE_OBJECT (self));
105
106 /* Remove the parent on each old one */
107 for (l = self->pv->uids; l; l = g_list_next (l))
108 seahorse_object_set_parent (l->data, NULL);
109
110 seahorse_object_list_free (self->pv->uids);
111 self->pv->uids = seahorse_object_list_copy (uids);
112
113 /* Set parent and source on each new one, except the first */
114 for (l = self->pv->uids, index = 0; l; l = g_list_next (l), ++index) {
115 g_object_set (l->data, "id", seahorse_pgp_uid_calc_id (id, index), NULL);
116 if (l != self->pv->uids)
117 seahorse_object_set_parent (l->data, SEAHORSE_OBJECT (self));
118 }
119
120 g_object_notify (G_OBJECT (self), "uids");
121 }
122
123 static GList*
_seahorse_pgp_key_get_subkeys(SeahorsePgpKey * self)124 _seahorse_pgp_key_get_subkeys (SeahorsePgpKey *self)
125 {
126 g_return_val_if_fail (SEAHORSE_IS_PGP_KEY (self), NULL);
127 return self->pv->subkeys;
128 }
129
130 static void
_seahorse_pgp_key_set_subkeys(SeahorsePgpKey * self,GList * subkeys)131 _seahorse_pgp_key_set_subkeys (SeahorsePgpKey *self, GList *subkeys)
132 {
133 GQuark id;
134
135 g_return_if_fail (SEAHORSE_IS_PGP_KEY (self));
136 g_return_if_fail (subkeys);
137
138 seahorse_object_list_free (self->pv->subkeys);
139 self->pv->subkeys = seahorse_object_list_copy (subkeys);
140
141 id = seahorse_pgp_key_canonize_id (seahorse_pgp_subkey_get_keyid (subkeys->data));
142 g_object_set (self, "id", id, NULL);
143
144 g_object_notify (G_OBJECT (self), "subkeys");
145 }
146
147 static void
seahorse_pgp_key_realize(SeahorseObject * obj)148 seahorse_pgp_key_realize (SeahorseObject *obj)
149 {
150 SeahorsePgpKey *self = SEAHORSE_PGP_KEY (obj);
151 const gchar *nickname, *keyid;
152 const gchar *description, *icon;
153 gchar *markup, *name, *identifier;
154 SeahorseUsage usage;
155 GList *subkeys;
156
157
158 SEAHORSE_OBJECT_CLASS (seahorse_pgp_key_parent_class)->realize (obj);
159
160 subkeys = seahorse_pgp_key_get_subkeys (self);
161 if (subkeys) {
162 keyid = seahorse_pgp_subkey_get_keyid (subkeys->data);
163 identifier = seahorse_pgp_key_calc_identifier (keyid);
164 } else {
165 identifier = g_strdup ("");
166 }
167
168 name = calc_name (self);
169 markup = calc_markup (self, seahorse_object_get_flags (obj));
170 nickname = calc_short_name (self);
171
172 g_object_get (obj, "usage", &usage, NULL);
173
174 /* The type */
175 if (usage == SEAHORSE_USAGE_PRIVATE_KEY) {
176 description = _("Private PGP Key");
177 icon = SEAHORSE_STOCK_SECRET;
178 } else {
179 description = _("Public PGP Key");
180 icon = SEAHORSE_STOCK_KEY;
181 if (usage == SEAHORSE_USAGE_NONE)
182 g_object_set (obj, "usage", SEAHORSE_USAGE_PUBLIC_KEY, NULL);
183 }
184
185 g_object_set (obj,
186 "label", name,
187 "markup", markup,
188 "nickname", nickname,
189 "identifier", identifier,
190 "description", description,
191 "icon", icon,
192 NULL);
193
194 g_free (identifier);
195 g_free (markup);
196 g_free (name);
197 }
198
199 static void
seahorse_pgp_key_init(SeahorsePgpKey * self)200 seahorse_pgp_key_init (SeahorsePgpKey *self)
201 {
202 self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_PGP_KEY, SeahorsePgpKeyPrivate);
203 }
204
205 static void
seahorse_pgp_key_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)206 seahorse_pgp_key_get_property (GObject *object, guint prop_id,
207 GValue *value, GParamSpec *pspec)
208 {
209 SeahorsePgpKey *self = SEAHORSE_PGP_KEY (object);
210
211 switch (prop_id) {
212 case PROP_SUBKEYS:
213 g_value_set_boxed (value, seahorse_pgp_key_get_subkeys (self));
214 break;
215 case PROP_UIDS:
216 g_value_set_boxed (value, seahorse_pgp_key_get_uids (self));
217 break;
218 case PROP_FINGERPRINT:
219 g_value_set_string (value, seahorse_pgp_key_get_fingerprint (self));
220 break;
221 case PROP_VALIDITY_STR:
222 g_value_set_string (value, seahorse_pgp_key_get_validity_str (self));
223 break;
224 case PROP_TRUST_STR:
225 g_value_set_string (value, seahorse_pgp_key_get_trust_str (self));
226 break;
227 case PROP_EXPIRES:
228 g_value_set_ulong (value, seahorse_pgp_key_get_expires (self));
229 break;
230 case PROP_EXPIRES_STR:
231 g_value_take_string (value, seahorse_pgp_key_get_expires_str (self));
232 break;
233 case PROP_LENGTH:
234 g_value_set_uint (value, seahorse_pgp_key_get_length (self));
235 break;
236 case PROP_ALGO:
237 g_value_set_string (value, seahorse_pgp_key_get_algo (self));
238 break;
239 case PROP_VALIDITY:
240 g_value_set_uint (value, SEAHORSE_VALIDITY_UNKNOWN);
241 break;
242 case PROP_TRUST:
243 g_value_set_uint (value, SEAHORSE_VALIDITY_UNKNOWN);
244 break;
245 }
246 }
247
248 static void
seahorse_pgp_key_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)249 seahorse_pgp_key_set_property (GObject *object, guint prop_id, const GValue *value,
250 GParamSpec *pspec)
251 {
252 SeahorsePgpKey *self = SEAHORSE_PGP_KEY (object);
253
254 switch (prop_id) {
255 case PROP_UIDS:
256 seahorse_pgp_key_set_uids (self, g_value_get_boxed (value));
257 break;
258 case PROP_SUBKEYS:
259 seahorse_pgp_key_set_subkeys (self, g_value_get_boxed (value));
260 break;
261 }
262 }
263
264 static void
seahorse_pgp_key_object_dispose(GObject * obj)265 seahorse_pgp_key_object_dispose (GObject *obj)
266 {
267 SeahorsePgpKey *self = SEAHORSE_PGP_KEY (obj);
268
269 GList *l;
270
271 /* Free all the attached UIDs */
272 for (l = self->pv->uids; l; l = g_list_next (l))
273 seahorse_object_set_parent (l->data, NULL);
274
275 seahorse_object_list_free (self->pv->uids);
276 self->pv->uids = NULL;
277
278 /* Free all the attached Subkeys */
279 seahorse_object_list_free (self->pv->subkeys);
280 self->pv->subkeys = NULL;
281
282 G_OBJECT_CLASS (seahorse_pgp_key_parent_class)->dispose (obj);
283 }
284
285 static void
seahorse_pgp_key_object_finalize(GObject * obj)286 seahorse_pgp_key_object_finalize (GObject *obj)
287 {
288 SeahorsePgpKey *self = SEAHORSE_PGP_KEY (obj);
289
290 g_assert (self->pv->uids == NULL);
291 g_assert (self->pv->subkeys == NULL);
292
293 G_OBJECT_CLASS (seahorse_pgp_key_parent_class)->finalize (obj);
294 }
295
296 static void
seahorse_pgp_key_class_init(SeahorsePgpKeyClass * klass)297 seahorse_pgp_key_class_init (SeahorsePgpKeyClass *klass)
298 {
299 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
300 SeahorseObjectClass *seahorse_class = SEAHORSE_OBJECT_CLASS (klass);
301
302 seahorse_pgp_key_parent_class = g_type_class_peek_parent (klass);
303 g_type_class_add_private (klass, sizeof (SeahorsePgpKeyPrivate));
304
305 gobject_class->dispose = seahorse_pgp_key_object_dispose;
306 gobject_class->finalize = seahorse_pgp_key_object_finalize;
307 gobject_class->set_property = seahorse_pgp_key_set_property;
308 gobject_class->get_property = seahorse_pgp_key_get_property;
309
310 seahorse_class->realize = seahorse_pgp_key_realize;
311
312 klass->get_uids = _seahorse_pgp_key_get_uids;
313 klass->set_uids = _seahorse_pgp_key_set_uids;
314 klass->get_subkeys = _seahorse_pgp_key_get_subkeys;
315 klass->set_subkeys = _seahorse_pgp_key_set_subkeys;
316
317 g_object_class_install_property (gobject_class, PROP_SUBKEYS,
318 g_param_spec_boxed ("subkeys", "PGP subkeys", "PGP subkeys",
319 SEAHORSE_BOXED_OBJECT_LIST, G_PARAM_READWRITE));
320
321 g_object_class_install_property (gobject_class, PROP_UIDS,
322 g_param_spec_boxed ("uids", "PGP User Ids", "PGP User Ids",
323 SEAHORSE_BOXED_OBJECT_LIST, G_PARAM_READWRITE));
324
325 g_object_class_install_property (gobject_class, PROP_FINGERPRINT,
326 g_param_spec_string ("fingerprint", "Fingerprint", "Unique fingerprint for this key",
327 "", G_PARAM_READABLE));
328
329 g_object_class_install_property (gobject_class, PROP_VALIDITY,
330 g_param_spec_uint ("validity", "Validity", "Validity of this key",
331 0, G_MAXUINT, 0, G_PARAM_READABLE));
332
333 g_object_class_install_property (gobject_class, PROP_VALIDITY_STR,
334 g_param_spec_string ("validity-str", "Validity String", "Validity of this key as a string",
335 "", G_PARAM_READABLE));
336
337 g_object_class_install_property (gobject_class, PROP_TRUST,
338 g_param_spec_uint ("trust", "Trust", "Trust in this key",
339 0, G_MAXUINT, 0, G_PARAM_READABLE));
340
341 g_object_class_install_property (gobject_class, PROP_TRUST_STR,
342 g_param_spec_string ("trust-str", "Trust String", "Trust in this key as a string",
343 "", G_PARAM_READABLE));
344
345 g_object_class_install_property (gobject_class, PROP_EXPIRES,
346 g_param_spec_ulong ("expires", "Expires On", "Date this key expires on",
347 0, G_MAXULONG, 0, G_PARAM_READABLE));
348
349 g_object_class_install_property (gobject_class, PROP_EXPIRES_STR,
350 g_param_spec_string ("expires-str", "Expires String", "Readable expiry date",
351 "", G_PARAM_READABLE));
352
353 g_object_class_install_property (gobject_class, PROP_LENGTH,
354 g_param_spec_uint ("length", "Length", "The length of this key.",
355 0, G_MAXUINT, 0, G_PARAM_READABLE));
356
357 g_object_class_install_property (gobject_class, PROP_ALGO,
358 g_param_spec_string ("algo", "Algorithm", "The algorithm of this key.",
359 "", G_PARAM_READABLE));
360 }
361
362
363 /* -----------------------------------------------------------------------------
364 * PUBLIC
365 */
366
367 GQuark
seahorse_pgp_key_canonize_id(const gchar * keyid)368 seahorse_pgp_key_canonize_id (const gchar *keyid)
369 {
370 gchar *str;
371 GQuark id;
372
373 str = seahorse_pgp_key_calc_id (keyid, 0);
374 g_return_val_if_fail (str, 0);
375
376 id = g_quark_from_string (str);
377 g_free (str);
378
379 return id;
380 }
381
382 gchar*
seahorse_pgp_key_calc_id(const gchar * keyid,guint index)383 seahorse_pgp_key_calc_id (const gchar *keyid, guint index)
384 {
385 guint len;
386
387 g_return_val_if_fail (keyid, 0);
388 len = strlen (keyid);
389
390 if (len < 16)
391 g_message ("invalid keyid (less than 16 chars): %s", keyid);
392
393 if (len > 16)
394 keyid += len - 16;
395
396 if (index == 0)
397 return g_strdup_printf ("%s:%s", SEAHORSE_PGP_STR, keyid);
398 else
399 return g_strdup_printf ("%s:%s:%u", SEAHORSE_PGP_STR, keyid, index);
400 }
401
402 const gchar*
seahorse_pgp_key_calc_rawid(GQuark id)403 seahorse_pgp_key_calc_rawid (GQuark id)
404 {
405 const gchar* keyid, *strid;
406
407 strid = g_quark_to_string (id);
408 g_return_val_if_fail (strid != NULL, NULL);
409
410 keyid = strchr (strid, ':');
411 return keyid ? keyid + 1 : strid;
412 }
413
414 gchar*
seahorse_pgp_key_calc_identifier(const gchar * keyid)415 seahorse_pgp_key_calc_identifier (const gchar *keyid)
416 {
417 guint len;
418
419 g_return_val_if_fail (keyid, NULL);
420
421 len = strlen (keyid);
422 if (len > 8)
423 keyid += len - 8;
424
425 return g_strdup (keyid);
426 }
427
428 SeahorsePgpKey*
seahorse_pgp_key_new(void)429 seahorse_pgp_key_new (void)
430 {
431 return g_object_new (SEAHORSE_TYPE_PGP_KEY, NULL);
432 }
433
434 GList*
seahorse_pgp_key_get_uids(SeahorsePgpKey * self)435 seahorse_pgp_key_get_uids (SeahorsePgpKey *self)
436 {
437 g_return_val_if_fail (SEAHORSE_IS_PGP_KEY (self), NULL);
438 if (!SEAHORSE_PGP_KEY_GET_CLASS (self)->get_uids)
439 return NULL;
440 return SEAHORSE_PGP_KEY_GET_CLASS (self)->get_uids (self);
441 }
442
443 void
seahorse_pgp_key_set_uids(SeahorsePgpKey * self,GList * uids)444 seahorse_pgp_key_set_uids (SeahorsePgpKey *self, GList *uids)
445 {
446 g_return_if_fail (SEAHORSE_IS_PGP_KEY (self));
447 g_return_if_fail (SEAHORSE_PGP_KEY_GET_CLASS (self)->set_uids);
448 SEAHORSE_PGP_KEY_GET_CLASS (self)->set_uids (self, uids);
449 }
450
451 GList*
seahorse_pgp_key_get_subkeys(SeahorsePgpKey * self)452 seahorse_pgp_key_get_subkeys (SeahorsePgpKey *self)
453 {
454 g_return_val_if_fail (SEAHORSE_IS_PGP_KEY (self), NULL);
455 if (!SEAHORSE_PGP_KEY_GET_CLASS (self)->get_subkeys)
456 return NULL;
457 return SEAHORSE_PGP_KEY_GET_CLASS (self)->get_subkeys (self);
458 }
459
460 void
seahorse_pgp_key_set_subkeys(SeahorsePgpKey * self,GList * subkeys)461 seahorse_pgp_key_set_subkeys (SeahorsePgpKey *self, GList *subkeys)
462 {
463 g_return_if_fail (SEAHORSE_IS_PGP_KEY (self));
464 g_return_if_fail (SEAHORSE_PGP_KEY_GET_CLASS (self)->set_subkeys);
465 SEAHORSE_PGP_KEY_GET_CLASS (self)->set_subkeys (self, subkeys);
466 }
467
468 const gchar*
seahorse_pgp_key_get_fingerprint(SeahorsePgpKey * self)469 seahorse_pgp_key_get_fingerprint (SeahorsePgpKey *self)
470 {
471 GList *subkeys;
472
473 g_return_val_if_fail (SEAHORSE_IS_PGP_KEY (self), NULL);
474
475 subkeys = seahorse_pgp_key_get_subkeys (self);
476 if (!subkeys)
477 return "";
478
479 return seahorse_pgp_subkey_get_fingerprint (subkeys->data);
480 }
481
482 SeahorseValidity
seahorse_pgp_key_get_validity(SeahorsePgpKey * self)483 seahorse_pgp_key_get_validity (SeahorsePgpKey *self)
484 {
485 guint validity = SEAHORSE_VALIDITY_UNKNOWN;
486 g_object_get (self, "validity", &validity, NULL);
487 return validity;
488 }
489
490 const gchar*
seahorse_pgp_key_get_validity_str(SeahorsePgpKey * self)491 seahorse_pgp_key_get_validity_str (SeahorsePgpKey *self)
492 {
493 return seahorse_validity_get_string (seahorse_pgp_key_get_validity (self));
494 }
495
496 gulong
seahorse_pgp_key_get_expires(SeahorsePgpKey * self)497 seahorse_pgp_key_get_expires (SeahorsePgpKey *self)
498 {
499 GList *subkeys;
500
501 g_return_val_if_fail (SEAHORSE_IS_PGP_KEY (self), 0);
502
503 subkeys = seahorse_pgp_key_get_subkeys (self);
504 if (!subkeys)
505 return 0;
506
507 return seahorse_pgp_subkey_get_expires (subkeys->data);
508 }
509
510 gchar*
seahorse_pgp_key_get_expires_str(SeahorsePgpKey * self)511 seahorse_pgp_key_get_expires_str (SeahorsePgpKey *self)
512 {
513 GTimeVal timeval;
514 gulong expires;
515
516 g_return_val_if_fail (SEAHORSE_IS_PGP_KEY (self), NULL);
517
518 expires = seahorse_pgp_key_get_expires (self);
519 if (expires == 0)
520 return g_strdup ("");
521
522 g_get_current_time (&timeval);
523 if (timeval.tv_sec > expires)
524 return g_strdup (_("Expired"));
525
526 return seahorse_util_get_date_string (expires);
527 }
528
529 SeahorseValidity
seahorse_pgp_key_get_trust(SeahorsePgpKey * self)530 seahorse_pgp_key_get_trust (SeahorsePgpKey *self)
531 {
532 guint trust = SEAHORSE_VALIDITY_UNKNOWN;
533 g_object_get (self, "trust", &trust, NULL);
534 return trust;
535 }
536
537 const gchar*
seahorse_pgp_key_get_trust_str(SeahorsePgpKey * self)538 seahorse_pgp_key_get_trust_str (SeahorsePgpKey *self)
539 {
540 return seahorse_validity_get_string (seahorse_pgp_key_get_trust (self));
541 }
542
543 guint
seahorse_pgp_key_get_length(SeahorsePgpKey * self)544 seahorse_pgp_key_get_length (SeahorsePgpKey *self)
545 {
546 GList *subkeys;
547
548 g_return_val_if_fail (SEAHORSE_IS_PGP_KEY (self), 0);
549
550 subkeys = seahorse_pgp_key_get_subkeys (self);
551 if (!subkeys)
552 return 0;
553
554 return seahorse_pgp_subkey_get_length (subkeys->data);
555 }
556
557 const gchar*
seahorse_pgp_key_get_algo(SeahorsePgpKey * self)558 seahorse_pgp_key_get_algo (SeahorsePgpKey *self)
559 {
560 GList *subkeys;
561
562 g_return_val_if_fail (SEAHORSE_IS_PGP_KEY (self), 0);
563
564 subkeys = seahorse_pgp_key_get_subkeys (self);
565 if (!subkeys)
566 return 0;
567
568 return seahorse_pgp_subkey_get_algorithm (subkeys->data);
569 }
570
571 const gchar*
seahorse_pgp_key_get_keyid(SeahorsePgpKey * self)572 seahorse_pgp_key_get_keyid (SeahorsePgpKey *self)
573 {
574 GList *subkeys;
575
576 g_return_val_if_fail (SEAHORSE_IS_PGP_KEY (self), 0);
577
578 subkeys = seahorse_pgp_key_get_subkeys (self);
579 if (!subkeys)
580 return 0;
581
582 return seahorse_pgp_subkey_get_keyid (subkeys->data);
583 }
584
585 gboolean
seahorse_pgp_key_has_keyid(SeahorsePgpKey * self,const gchar * match)586 seahorse_pgp_key_has_keyid (SeahorsePgpKey *self, const gchar *match)
587 {
588 GList *subkeys, *l;
589 SeahorsePgpSubkey *subkey;
590 const gchar *keyid;
591 guint n_match, n_keyid;
592
593 g_return_val_if_fail (SEAHORSE_IS_PGP_KEY (self), FALSE);
594 g_return_val_if_fail (match, FALSE);
595
596 subkeys = seahorse_pgp_key_get_subkeys (self);
597 if (!subkeys)
598 return FALSE;
599
600 n_match = strlen (match);
601
602 for (l = subkeys; l && (subkey = SEAHORSE_PGP_SUBKEY (l->data)); l = g_list_next (l)) {
603 keyid = seahorse_pgp_subkey_get_keyid (subkey);
604 g_return_val_if_fail (keyid, FALSE);
605 n_keyid = strlen (keyid);
606 if (n_match <= n_keyid) {
607 keyid += (n_keyid - n_match);
608 if (strncmp (keyid, match, n_match) == 0)
609 return TRUE;
610 }
611 }
612
613 return FALSE;
614 }
615
616