1 /* gpaexportserverop.c - The GpaExportServerOperation object.
2  *	Copyright (C) 2003, Miguel Coca.
3  *
4  * This file is part of GPA
5  *
6  * GPA 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  * GPA 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.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20 
21 #include <config.h>
22 
23 #include <gpgme.h>
24 #include <unistd.h>
25 #include "gpa.h"
26 #include "i18n.h"
27 #include "gtktools.h"
28 #include "gpgmetools.h"
29 #include "server-access.h"
30 #include "confdialog.h"
31 #include "gpaexportserverop.h"
32 
33 static GObjectClass *parent_class = NULL;
34 
35 static gboolean
36 gpa_export_server_operation_get_destination (GpaExportOperation *operation,
37 						gpgme_data_t *dest,
38 						gboolean *armor);
39 static void
40 gpa_export_server_operation_complete_export (GpaExportOperation *operation);
41 
42 /* GObject boilerplate */
43 
44 static void
gpa_export_server_operation_finalize(GObject * object)45 gpa_export_server_operation_finalize (GObject *object)
46 {
47   GpaExportServerOperation *op = GPA_EXPORT_SERVER_OPERATION (object);
48 
49   if (op->server)
50     {
51       g_free (op->server);
52     }
53 
54   G_OBJECT_CLASS (parent_class)->finalize (object);
55 }
56 
57 static void
gpa_export_server_operation_init(GpaExportServerOperation * op)58 gpa_export_server_operation_init (GpaExportServerOperation *op)
59 {
60   op->server = NULL;
61 }
62 
63 static GObject*
gpa_export_server_operation_constructor(GType type,guint n_construct_properties,GObjectConstructParam * construct_properties)64 gpa_export_server_operation_constructor (GType type,
65 				  guint n_construct_properties,
66 				  GObjectConstructParam *construct_properties)
67 {
68   GObject *object;
69   /* GpaExportServerOperation *op; */
70 
71   /* Invoke parent's constructor */
72   object = parent_class->constructor (type,
73 				      n_construct_properties,
74 				      construct_properties);
75   /* op = GPA_EXPORT_SERVER_OPERATION (object); */
76 
77   return object;
78 }
79 
80 static void
gpa_export_server_operation_class_init(GpaExportServerOperationClass * klass)81 gpa_export_server_operation_class_init (GpaExportServerOperationClass *klass)
82 {
83   GObjectClass *object_class = G_OBJECT_CLASS (klass);
84   GpaExportOperationClass *export_class = GPA_EXPORT_OPERATION_CLASS (klass);
85 
86   parent_class = g_type_class_peek_parent (klass);
87 
88   object_class->constructor = gpa_export_server_operation_constructor;
89   object_class->finalize = gpa_export_server_operation_finalize;
90   export_class->get_destination = gpa_export_server_operation_get_destination;
91   export_class->complete_export = gpa_export_server_operation_complete_export;
92 }
93 
94 GType
gpa_export_server_operation_get_type(void)95 gpa_export_server_operation_get_type (void)
96 {
97   static GType file_operation_type = 0;
98 
99   if (!file_operation_type)
100     {
101       static const GTypeInfo file_operation_info =
102       {
103         sizeof (GpaExportServerOperationClass),
104         (GBaseInitFunc) NULL,
105         (GBaseFinalizeFunc) NULL,
106         (GClassInitFunc) gpa_export_server_operation_class_init,
107         NULL,           /* class_finalize */
108         NULL,           /* class_data */
109         sizeof (GpaExportServerOperation),
110         0,              /* n_preallocs */
111         (GInstanceInitFunc) gpa_export_server_operation_init,
112       };
113 
114       file_operation_type = g_type_register_static (GPA_EXPORT_OPERATION_TYPE,
115 						    "GpaExportServerOperation",
116 						    &file_operation_info, 0);
117     }
118 
119   return file_operation_type;
120 }
121 
122 /* Internal */
123 
124 static gboolean
confirm_send(GtkWidget * parent,const gchar * server)125 confirm_send (GtkWidget *parent, const gchar *server)
126 {
127   GtkWidget *msgbox;
128   char *info;
129   char *keyserver = NULL;
130 
131   if (is_gpg_version_at_least ("2.1.0"))
132     {
133       keyserver = gpa_load_configured_keyserver ();
134       server = keyserver;
135     }
136 
137   if (!server)
138     {
139       keyserver = gpa_configure_keyserver (parent);
140       if (!keyserver)
141         return FALSE;
142       server = keyserver;
143     }
144 
145 
146   info = g_strdup_printf (_("The selected key(s) will be sent to a public key\n"
147                             "server (\"%s\")."), server);
148   g_free (keyserver);
149   msgbox = gtk_message_dialog_new
150     (GTK_WINDOW(parent), GTK_DIALOG_MODAL,
151      GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE,
152      "%s\n\n%s",
153      info,
154      _("Are you sure you want to distribute this key?"));
155   g_free (info);
156 
157   gtk_dialog_add_buttons (GTK_DIALOG (msgbox),
158 			  _("_Yes"), GTK_RESPONSE_YES,
159 			  _("_No"), GTK_RESPONSE_NO, NULL);
160   if (gtk_dialog_run (GTK_DIALOG (msgbox)) != GTK_RESPONSE_YES)
161     {
162       gtk_widget_destroy (msgbox);
163       return FALSE;
164     }
165   gtk_widget_destroy (msgbox);
166   return TRUE;
167 }
168 
169 /* Virtual methods */
170 
171 static gboolean
gpa_export_server_operation_get_destination(GpaExportOperation * operation,gpgme_data_t * dest,gboolean * armor)172 gpa_export_server_operation_get_destination (GpaExportOperation *operation,
173 					     gpgme_data_t *dest,
174 					     gboolean *armor)
175 {
176   if (confirm_send (GPA_OPERATION (operation)->window,
177 		    gpa_options_get_default_keyserver
178 		    (gpa_options_get_instance ())))
179     {
180       gpg_error_t err;
181       *armor = TRUE;
182       err = gpgme_data_new (dest);
183       if (err)
184 	{
185 	  gpa_gpgme_warning (err);
186 	  return FALSE;
187 	}
188       else
189 	{
190 	  return TRUE;
191 	}
192     }
193   else
194     {
195       return FALSE;
196     }
197 }
198 
199 
200 /* GnuPG 2.1 method to send keys to the keyserver.  KEYLIST has a list
201    of keys to be sent.  Returns true on success. */
202 static gboolean
send_keys(GpaExportServerOperation * op,GList * keylist)203 send_keys (GpaExportServerOperation *op, GList *keylist)
204 {
205   gpg_error_t err;
206   GList *item;
207   gpgme_key_t *keyarray;
208   gpgme_key_t key;
209   int i;
210 
211   keyarray = g_malloc0_n (g_list_length (keylist)+1, sizeof *keyarray);
212   i = 0;
213   for (item = keylist; item; i++, item = g_list_next (item))
214     {
215       key = (gpgme_key_t) item->data;
216       if (!key || key->protocol != GPGME_PROTOCOL_OpenPGP)
217         continue;
218       gpgme_key_ref (key);
219       keyarray[i++] = key;
220     }
221 
222   gpgme_set_protocol (GPA_OPERATION (op)->context->ctx, GPGME_PROTOCOL_OpenPGP);
223   err = gpgme_op_export_keys (GPA_OPERATION (op)->context->ctx,
224                               keyarray, GPGME_KEYLIST_MODE_EXTERN, NULL);
225   for (i=0; keyarray[i]; i++)
226     gpgme_key_unref (keyarray[i]);
227   g_free (keyarray);
228 
229   if (err)
230     {
231       gpa_show_warn (GPA_OPERATION (op)->window, NULL,
232                         "%s\n\n(%s <%s>)",
233                         _("Error sending key(s) to the server."),
234                         gpg_strerror (err), gpg_strsource (err));
235       return FALSE;
236     }
237 
238   return TRUE;
239 }
240 
241 
242 
243 static void
gpa_export_server_operation_complete_export(GpaExportOperation * operation)244 gpa_export_server_operation_complete_export (GpaExportOperation *operation)
245 {
246   GpaExportServerOperation *op = GPA_EXPORT_SERVER_OPERATION (operation);
247   int okay = 0;
248 
249   if (is_gpg_version_at_least ("2.1.0"))
250     {
251       /* GnuPG 2.1.0 does not anymore use the keyserver helpers and
252          thus we need to use the real API for sending keys.  */
253       if (send_keys (op, operation->keys))
254         okay = 1;
255     }
256   else
257     {
258       gpgme_key_t key = (gpgme_key_t) operation->keys->data;
259 
260       op->server = g_strdup (gpa_options_get_default_keyserver
261                              (gpa_options_get_instance ()));
262       if (server_send_keys (op->server, key->subkeys->keyid, operation->dest,
263                              GPA_OPERATION (op)->window))
264         okay = 1;
265     }
266 
267   if (okay)
268     gpa_window_message (_("The keys have been sent to the server."),
269                         GPA_OPERATION (op)->window);
270 }
271 
272 /* API */
273 
274 GpaExportServerOperation*
gpa_export_server_operation_new(GtkWidget * window,GList * keys)275 gpa_export_server_operation_new (GtkWidget *window, GList *keys)
276 {
277   GpaExportServerOperation *op;
278 
279   op = g_object_new (GPA_EXPORT_SERVER_OPERATION_TYPE,
280 		     "window", window,
281 		     "keys", keys,
282 		     NULL);
283 
284   return op;
285 }
286