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