src/mn-keyring.c (5916B) - raw
1 /*
2 * Mail Notification
3 * Copyright (C) 2003-2008 Jean-Yves Lefort <jylefort@brutele.be>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "mn-keyring.h"
21
22 typedef struct
23 {
24 GMutex *mutex;
25 GCond *cond;
26 gboolean done;
27 } Request;
28
29 typedef struct
30 {
31 Request request;
32
33 const char *username;
34 const char *domain;
35 const char *server;
36 const char *protocol;
37 const char *authtype;
38 int port;
39
40 MNKeyringRequestCallback request_callback;
41 gpointer data;
42
43 char *password;
44 } GetPasswordInfo;
45
46 typedef struct
47 {
48 Request request;
49
50 const char *keyring;
51 const char *username;
52 const char *domain;
53 const char *server;
54 const char *protocol;
55 const char *authtype;
56 int port;
57 const char *password;
58
59 MNKeyringRequestCallback request_callback;
60 gpointer data;
61
62 GnomeKeyringResult result;
63 guint32 item_id;
64 } SetPasswordInfo;
65
66 static void
67 request_perform (Request *request, GSourceFunc perform_callback, gpointer data)
68 {
69 g_return_if_fail(request != NULL);
70 g_return_if_fail(perform_callback != NULL);
71
72 request->mutex = g_mutex_new();
73 request->cond = g_cond_new();
74 request->done = FALSE;
75
76 /*
77 * Work around http://bugzilla.gnome.org/show_bug.cgi?id=474695 by
78 * calling the gnome-keyring async function from a main loop
79 * callback.
80 */
81 g_idle_add(perform_callback, data);
82
83 g_mutex_lock(request->mutex);
84
85 if (! request->done)
86 g_cond_wait(request->cond, request->mutex);
87
88 g_mutex_unlock(request->mutex);
89
90 g_mutex_free(request->mutex);
91 g_cond_free(request->cond);
92 }
93
94 static void
95 request_signal (Request *request)
96 {
97 g_return_if_fail(request != NULL);
98
99 g_mutex_lock(request->mutex);
100
101 request->done = TRUE;
102 g_cond_signal(request->cond);
103
104 g_mutex_unlock(request->mutex);
105 }
106
107 static void
108 get_password_sync_cb (GnomeKeyringResult result,
109 GList *list,
110 gpointer data)
111 {
112 GetPasswordInfo *info = data;
113
114 info->request_callback(NULL, info->data);
115
116 if (result == GNOME_KEYRING_RESULT_OK && list)
117 {
118 GnomeKeyringNetworkPasswordData *password_data = list->data;
119 info->password = g_strdup(password_data->password);
120 }
121
122 request_signal(&info->request);
123 }
124
125 static gboolean
126 get_password_sync_perform_cb (gpointer data)
127 {
128 GetPasswordInfo *info = data;
129 gpointer request;
130
131 request = gnome_keyring_find_network_password(info->username,
132 info->domain,
133 info->server,
134 NULL,
135 info->protocol,
136 info->authtype,
137 info->port,
138 get_password_sync_cb,
139 info,
140 NULL);
141
142 info->request_callback(request, info->data);
143
144 return FALSE; /* remove source */
145 }
146
147 char *
148 mn_keyring_get_password_sync (const char *username,
149 const char *domain,
150 const char *server,
151 const char *protocol,
152 const char *authtype,
153 int port,
154 MNKeyringRequestCallback request_callback,
155 gpointer data)
156 {
157 GetPasswordInfo info;
158
159 g_return_val_if_fail(request_callback != NULL, NULL);
160
161 info.username = username;
162 info.domain = domain;
163 info.server = server;
164 info.protocol = protocol;
165 info.authtype = authtype;
166 info.port = port;
167
168 info.request_callback = request_callback;
169 info.data = data;
170
171 info.password = NULL;
172
173 request_perform(&info.request, get_password_sync_perform_cb, &info);
174
175 return info.password;
176 }
177
178 static void
179 set_password_sync_cb (GnomeKeyringResult result,
180 guint32 item_id,
181 gpointer data)
182 {
183 SetPasswordInfo *info = data;
184
185 info->request_callback(NULL, info->data);
186
187 info->result = result;
188 info->item_id = item_id;
189
190 request_signal(&info->request);
191 }
192
193 static gboolean
194 set_password_sync_perform_cb (gpointer data)
195 {
196 SetPasswordInfo *info = data;
197 gpointer request;
198
199 request = gnome_keyring_set_network_password(info->keyring,
200 info->username,
201 info->domain,
202 info->server,
203 NULL,
204 info->protocol,
205 info->authtype,
206 info->port,
207 info->password,
208 set_password_sync_cb,
209 info,
210 NULL);
211
212 info->request_callback(request, info->data);
213
214 return FALSE; /* remove source */
215 }
216
217 GnomeKeyringResult
218 mn_keyring_set_password_sync (const char *keyring,
219 const char *username,
220 const char *domain,
221 const char *server,
222 const char *protocol,
223 const char *authtype,
224 int port,
225 const char *password,
226 guint32 *item_id,
227 MNKeyringRequestCallback request_callback,
228 gpointer data)
229 {
230 SetPasswordInfo info;
231
232 g_return_val_if_fail(password != NULL, GNOME_KEYRING_RESULT_BAD_ARGUMENTS);
233 g_return_val_if_fail(item_id != NULL, GNOME_KEYRING_RESULT_BAD_ARGUMENTS);
234 g_return_val_if_fail(request_callback != NULL, GNOME_KEYRING_RESULT_BAD_ARGUMENTS);
235
236 info.keyring = keyring;
237 info.username = username;
238 info.domain = domain;
239 info.server = server;
240 info.protocol = protocol;
241 info.authtype = authtype;
242 info.port = port;
243 info.password = password;
244
245 info.request_callback = request_callback;
246 info.data = data;
247
248 request_perform(&info.request, set_password_sync_perform_cb, &info);
249
250 if (info.result == GNOME_KEYRING_RESULT_OK)
251 *item_id = info.item_id;
252
253 return info.result;
254 }