1 /*
2  * Seahorse
3  *
4  * Copyright (C) 2004 Stefan Walter
5  * Copyright (C) 2011 Collabora Ltd.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15  * See the GNU General Public License for more details.
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
21 #include <config.h>
22 
23 #include "seahorse-server-source.h"
24 
25 #include "seahorse-hkp-source.h"
26 #include "seahorse-ldap-source.h"
27 #include "seahorse-pgp-key.h"
28 
29 #include "seahorse-common.h"
30 
31 #include "libseahorse/seahorse-util.h"
32 
33 #include <glib/gi18n.h>
34 
35 #include <stdlib.h>
36 #include <string.h>
37 
38 /**
39  * SECTION:seahorse-server-source
40  * @short_description: Objects for handling of internet sources of keys (hkp/ldap)
41  * @include:seahorse-server-source.h
42  *
43  **/
44 
45 enum {
46     PROP_0,
47     PROP_LABEL,
48     PROP_DESCRIPTION,
49     PROP_ICON,
50     PROP_CATEGORY,
51     PROP_URI,
52     PROP_ACTIONS,
53     PROP_ACTION_PREFIX,
54     PROP_MENU_MODEL,
55     PROP_SHOW_IF_EMPTY,
56     N_PROPS
57 };
58 
59 /* -----------------------------------------------------------------------------
60  *  SERVER SOURCE
61  */
62 
63 typedef struct _SeahorseServerSourcePrivate {
64     gchar *server;
65     gchar *uri;
66 } SeahorseServerSourcePrivate;
67 
68 static void      seahorse_server_source_collection_init    (GcrCollectionIface *iface);
69 
70 static void      seahorse_server_source_place_iface        (SeahorsePlaceIface *iface);
71 
72 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (SeahorseServerSource, seahorse_server_source, G_TYPE_OBJECT,
73                          G_ADD_PRIVATE (SeahorseServerSource)
74                          G_IMPLEMENT_INTERFACE (GCR_TYPE_COLLECTION, seahorse_server_source_collection_init);
75                          G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_PLACE, seahorse_server_source_place_iface);
76 );
77 
78 /* GObject handlers */
79 static void seahorse_server_source_finalize   (GObject *gobject);
80 static void seahorse_server_get_property      (GObject *object, guint prop_id,
81                                                GValue *value, GParamSpec *pspec);
82 static void seahorse_server_set_property      (GObject *object, guint prop_id,
83                                                const GValue *value, GParamSpec *pspec);
84 
85 static void
seahorse_server_source_class_init(SeahorseServerSourceClass * klass)86 seahorse_server_source_class_init (SeahorseServerSourceClass *klass)
87 {
88     GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
89 
90     gobject_class->finalize = seahorse_server_source_finalize;
91     gobject_class->set_property = seahorse_server_set_property;
92     gobject_class->get_property = seahorse_server_get_property;
93 
94 	g_object_class_override_property (gobject_class, PROP_LABEL, "label");
95 	g_object_class_override_property (gobject_class, PROP_DESCRIPTION, "description");
96     g_object_class_override_property (gobject_class, PROP_ICON, "icon");
97     g_object_class_override_property (gobject_class, PROP_CATEGORY, "category");
98 	g_object_class_override_property (gobject_class, PROP_ACTIONS, "actions");
99 	g_object_class_override_property (gobject_class, PROP_ACTION_PREFIX, "action-prefix");
100 	g_object_class_override_property (gobject_class, PROP_MENU_MODEL, "menu-model");
101     g_object_class_override_property (gobject_class, PROP_SHOW_IF_EMPTY, "show-if-empty");
102 
103     g_object_class_install_property (gobject_class, PROP_URI,
104             g_param_spec_string ("uri", "Key Server URI",
105                                  "Key Server full URI", "",
106                                  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
107 }
108 
109 static void
seahorse_server_source_init(SeahorseServerSource * ssrc)110 seahorse_server_source_init (SeahorseServerSource *ssrc)
111 {
112 }
113 
114 static void
seahorse_server_source_finalize(GObject * gobject)115 seahorse_server_source_finalize (GObject *gobject)
116 {
117     SeahorseServerSource *ssrc = SEAHORSE_SERVER_SOURCE (gobject);
118     SeahorseServerSourcePrivate *priv =
119         seahorse_server_source_get_instance_private (ssrc);
120 
121     g_free (priv->server);
122     g_free (priv->uri);
123 
124     G_OBJECT_CLASS (seahorse_server_source_parent_class)->finalize (gobject);
125 }
126 
127 static void
seahorse_server_source_load(SeahorsePlace * self,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)128 seahorse_server_source_load (SeahorsePlace *self,
129                               GCancellable *cancellable,
130                               GAsyncReadyCallback callback,
131                               gpointer user_data)
132 {
133 	g_return_if_reached ();
134 }
135 
136 static gboolean
seahorse_server_source_load_finish(SeahorsePlace * self,GAsyncResult * res,GError ** error)137 seahorse_server_source_load_finish (SeahorsePlace *self,
138                                      GAsyncResult *res,
139                                      GError **error)
140 {
141 	g_return_val_if_reached (FALSE);
142 }
143 
144 static gchar *
seahorse_server_source_get_label(SeahorsePlace * self)145 seahorse_server_source_get_label (SeahorsePlace* self)
146 {
147     SeahorseServerSource *ssrc = SEAHORSE_SERVER_SOURCE (self);
148     SeahorseServerSourcePrivate *priv =
149         seahorse_server_source_get_instance_private (ssrc);
150 
151 	return g_strdup (priv->server);
152 }
153 
154 static void
seahorse_server_source_set_label(SeahorsePlace * self,const char * label)155 seahorse_server_source_set_label (SeahorsePlace *self, const char *label)
156 {
157 }
158 
159 static gchar *
seahorse_server_source_get_description(SeahorsePlace * self)160 seahorse_server_source_get_description (SeahorsePlace* self)
161 {
162     SeahorseServerSource *ssrc = SEAHORSE_SERVER_SOURCE (self);
163     SeahorseServerSourcePrivate *priv =
164         seahorse_server_source_get_instance_private (ssrc);
165 
166 	return g_strdup (priv->uri);
167 }
168 
169 static gchar *
seahorse_server_source_get_uri(SeahorsePlace * self)170 seahorse_server_source_get_uri (SeahorsePlace* self)
171 {
172     SeahorseServerSource *ssrc = SEAHORSE_SERVER_SOURCE (self);
173     SeahorseServerSourcePrivate *priv =
174         seahorse_server_source_get_instance_private (ssrc);
175 
176 	return g_strdup (priv->uri);
177 }
178 
179 static GIcon *
seahorse_server_source_get_icon(SeahorsePlace * self)180 seahorse_server_source_get_icon (SeahorsePlace* self)
181 {
182 	return g_themed_icon_new (NULL);
183 }
184 
185 static SeahorsePlaceCategory
seahorse_server_source_get_category(SeahorsePlace * place)186 seahorse_server_source_get_category (SeahorsePlace *place)
187 {
188     return SEAHORSE_PLACE_CATEGORY_KEYS;
189 }
190 
191 static GActionGroup *
seahorse_server_source_get_actions(SeahorsePlace * self)192 seahorse_server_source_get_actions (SeahorsePlace* self)
193 {
194     return NULL;
195 }
196 
197 static const gchar *
seahorse_server_source_get_action_prefix(SeahorsePlace * self)198 seahorse_server_source_get_action_prefix (SeahorsePlace* self)
199 {
200     return NULL;
201 }
202 
203 static GMenuModel *
seahorse_server_source_get_menu_model(SeahorsePlace * self)204 seahorse_server_source_get_menu_model (SeahorsePlace* self)
205 {
206     return NULL;
207 }
208 
209 static gboolean
seahorse_server_source_get_show_if_empty(SeahorsePlace * place)210 seahorse_server_source_get_show_if_empty (SeahorsePlace *place)
211 {
212     return TRUE;
213 }
214 
215 static void
seahorse_server_source_place_iface(SeahorsePlaceIface * iface)216 seahorse_server_source_place_iface (SeahorsePlaceIface *iface)
217 {
218     iface->load = seahorse_server_source_load;
219     iface->load_finish = seahorse_server_source_load_finish;
220     iface->get_actions = seahorse_server_source_get_actions;
221     iface->get_action_prefix = seahorse_server_source_get_action_prefix;
222     iface->get_menu_model = seahorse_server_source_get_menu_model;
223     iface->get_description = seahorse_server_source_get_description;
224     iface->get_icon = seahorse_server_source_get_icon;
225     iface->get_category = seahorse_server_source_get_category;
226     iface->get_label = seahorse_server_source_get_label;
227     iface->set_label = seahorse_server_source_set_label;
228     iface->get_uri = seahorse_server_source_get_uri;
229     iface->get_show_if_empty = seahorse_server_source_get_show_if_empty;
230 }
231 
232 static void
seahorse_server_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)233 seahorse_server_set_property (GObject *object, guint prop_id,
234                               const GValue *value, GParamSpec *pspec)
235 {
236     SeahorseServerSource *ssrc = SEAHORSE_SERVER_SOURCE (object);
237     SeahorseServerSourcePrivate *priv =
238         seahorse_server_source_get_instance_private (ssrc);
239 
240     switch (prop_id) {
241     case PROP_LABEL:
242         seahorse_server_source_set_label (SEAHORSE_PLACE (ssrc),
243                                           g_value_get_boxed (value));
244         break;
245     case PROP_URI:
246         g_free (priv->uri);
247         priv->uri = g_strdup (g_value_get_string (value));
248         g_return_if_fail (priv->uri && priv->uri[0]);
249         break;
250     default:
251         break;
252     }
253 }
254 
255 static void
seahorse_server_get_property(GObject * obj,guint prop_id,GValue * value,GParamSpec * pspec)256 seahorse_server_get_property (GObject *obj,
257                               guint prop_id,
258                               GValue *value,
259                               GParamSpec *pspec)
260 {
261 	SeahorseServerSource *self = SEAHORSE_SERVER_SOURCE (obj);
262 	SeahorsePlace *place = SEAHORSE_PLACE (self);
263 
264 	switch (prop_id) {
265 	case PROP_LABEL:
266 		g_value_take_string (value, seahorse_server_source_get_label (place));
267 		break;
268 	case PROP_DESCRIPTION:
269 		g_value_take_string (value, seahorse_server_source_get_description (place));
270 		break;
271 	case PROP_URI:
272 		g_value_take_string (value, seahorse_server_source_get_uri (place));
273 		break;
274     case PROP_ICON:
275         g_value_take_object (value, seahorse_server_source_get_icon (place));
276         break;
277     case PROP_CATEGORY:
278         g_value_set_enum (value, seahorse_server_source_get_category (place));
279         break;
280     case PROP_ACTIONS:
281         g_value_set_object (value, seahorse_server_source_get_actions (place));
282         break;
283     case PROP_ACTION_PREFIX:
284         g_value_set_string (value, seahorse_server_source_get_action_prefix (place));
285         break;
286     case PROP_MENU_MODEL:
287         g_value_set_object (value, seahorse_server_source_get_menu_model (place));
288         break;
289     case PROP_SHOW_IF_EMPTY:
290         g_value_set_boolean (value, TRUE);
291         break;
292     default:
293         G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
294         break;
295     }
296 }
297 
298 static guint
seahorse_server_source_get_length(GcrCollection * collection)299 seahorse_server_source_get_length (GcrCollection *collection)
300 {
301 	return 0;
302 }
303 
304 static GList *
seahorse_server_source_get_objects(GcrCollection * collection)305 seahorse_server_source_get_objects (GcrCollection *collection)
306 {
307 	return NULL;
308 }
309 
310 static gboolean
seahorse_server_source_contains(GcrCollection * collection,GObject * object)311 seahorse_server_source_contains (GcrCollection *collection,
312                                  GObject *object)
313 {
314 	return FALSE;
315 }
316 
317 static void
seahorse_server_source_collection_init(GcrCollectionIface * iface)318 seahorse_server_source_collection_init (GcrCollectionIface *iface)
319 {
320 	/* This is implemented because SeahorseSource requires it */
321 	iface->get_length = seahorse_server_source_get_length;
322 	iface->get_objects = seahorse_server_source_get_objects;
323 	iface->contains = seahorse_server_source_contains;
324 }
325 
326 void
seahorse_server_source_search_async(SeahorseServerSource * self,const gchar * match,GcrSimpleCollection * results,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)327 seahorse_server_source_search_async (SeahorseServerSource *self,
328                                      const gchar *match,
329                                      GcrSimpleCollection *results,
330                                      GCancellable *cancellable,
331                                      GAsyncReadyCallback callback,
332                                      gpointer user_data)
333 {
334 	g_return_if_fail (SEAHORSE_IS_SERVER_SOURCE (self));
335 	g_return_if_fail (match != NULL);
336 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
337 	g_return_if_fail (SEAHORSE_SERVER_SOURCE_GET_CLASS (self)->search_async);
338 	SEAHORSE_SERVER_SOURCE_GET_CLASS (self)->search_async (self, match, results,
339 	                                                       cancellable, callback, user_data);
340 }
341 
342 gboolean
seahorse_server_source_search_finish(SeahorseServerSource * self,GAsyncResult * result,GError ** error)343 seahorse_server_source_search_finish (SeahorseServerSource *self,
344                                       GAsyncResult *result,
345                                       GError **error)
346 {
347 	g_return_val_if_fail (SEAHORSE_IS_SERVER_SOURCE (self), FALSE);
348 	g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
349 	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
350 	g_return_val_if_fail (SEAHORSE_SERVER_SOURCE_GET_CLASS (self)->search_finish, FALSE);
351 	return SEAHORSE_SERVER_SOURCE_GET_CLASS (self)->search_finish (self, result, error);
352 }
353 
354 void
seahorse_server_source_export_async(SeahorseServerSource * self,const gchar ** keyids,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)355 seahorse_server_source_export_async (SeahorseServerSource *self,
356                                      const gchar **keyids,
357                                      GCancellable *cancellable,
358                                      GAsyncReadyCallback callback,
359                                      gpointer user_data)
360 {
361 	SeahorseServerSourceClass *klass;
362 
363 	g_return_if_fail (SEAHORSE_IS_SERVER_SOURCE (self));
364 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
365 
366 	klass = SEAHORSE_SERVER_SOURCE_GET_CLASS (self);
367 	g_return_if_fail (klass->export_async);
368 	(klass->export_async) (self, keyids, cancellable, callback, user_data);
369 }
370 
371 gpointer
seahorse_server_source_export_finish(SeahorseServerSource * self,GAsyncResult * result,gsize * size,GError ** error)372 seahorse_server_source_export_finish (SeahorseServerSource *self,
373                                       GAsyncResult *result,
374                                       gsize *size,
375                                       GError **error)
376 {
377 	SeahorseServerSourceClass *klass;
378 
379 	g_return_val_if_fail (SEAHORSE_IS_SERVER_SOURCE (self), NULL);
380 	g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
381 	g_return_val_if_fail (size != NULL, NULL);
382 	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
383 
384 	klass = SEAHORSE_SERVER_SOURCE_GET_CLASS (self);
385 	g_return_val_if_fail (klass->export_async != NULL, NULL);
386 	g_return_val_if_fail (klass->export_finish != NULL, NULL);
387 	return (klass->export_finish) (self, result, size, error);
388 }
389 
390 void
seahorse_server_source_import_async(SeahorseServerSource * source,GInputStream * input,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)391 seahorse_server_source_import_async (SeahorseServerSource *source,
392                                      GInputStream *input,
393                                      GCancellable *cancellable,
394                                      GAsyncReadyCallback callback,
395                                      gpointer user_data)
396 {
397 	g_return_if_fail (SEAHORSE_IS_SERVER_SOURCE (source));
398 	g_return_if_fail (G_IS_INPUT_STREAM (input));
399 	g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
400 	g_return_if_fail (SEAHORSE_SERVER_SOURCE_GET_CLASS (source)->import_async);
401 	SEAHORSE_SERVER_SOURCE_GET_CLASS (source)->import_async (source, input, cancellable,
402 	                                                         callback, user_data);
403 }
404 
405 GList *
seahorse_server_source_import_finish(SeahorseServerSource * source,GAsyncResult * result,GError ** error)406 seahorse_server_source_import_finish (SeahorseServerSource *source,
407                                       GAsyncResult *result,
408                                       GError **error)
409 {
410 	g_return_val_if_fail (SEAHORSE_IS_SERVER_SOURCE (source), NULL);
411 	g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
412 	g_return_val_if_fail (error == NULL || *error == NULL, NULL);
413 	g_return_val_if_fail (SEAHORSE_SERVER_SOURCE_GET_CLASS (source)->import_finish, NULL);
414 	return SEAHORSE_SERVER_SOURCE_GET_CLASS (source)->import_finish (source, result, error);
415 }
416