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 }