| 146 |
147 |
| 147 /****************************************************************************** |
148 /****************************************************************************** |
| 148 * Helpers |
149 * Helpers |
| 149 *****************************************************************************/ |
150 *****************************************************************************/ |
| 150 static void |
151 static void |
| 151 purple_account_register_got_password_cb(PurpleAccount *account, |
152 purple_account_register_got_password_cb(GObject *obj, GAsyncResult *res, |
| 152 const gchar *password, GError *error, gpointer data) |
153 gpointer data) |
| 153 { |
154 { |
| 154 g_return_if_fail(PURPLE_IS_ACCOUNT(account)); |
155 PurpleCredentialManager *manager = PURPLE_CREDENTIAL_MANAGER(obj); |
| |
156 PurpleAccount *account = PURPLE_ACCOUNT(data); |
| |
157 gchar *password = NULL; |
| |
158 |
| |
159 password = purple_credential_manager_read_password_finish(manager, res, |
| |
160 NULL); |
| 155 |
161 |
| 156 _purple_connection_new(account, TRUE, password); |
162 _purple_connection_new(account, TRUE, password); |
| |
163 |
| |
164 g_free(password); |
| 157 } |
165 } |
| 158 |
166 |
| 159 void |
167 void |
| 160 purple_account_register(PurpleAccount *account) |
168 purple_account_register(PurpleAccount *account) |
| 161 { |
169 { |
| |
170 PurpleCredentialManager *manager = NULL; |
| |
171 |
| 162 g_return_if_fail(PURPLE_IS_ACCOUNT(account)); |
172 g_return_if_fail(PURPLE_IS_ACCOUNT(account)); |
| 163 |
173 |
| 164 purple_debug_info("account", "Registering account %s\n", |
174 purple_debug_info("account", "Registering account %s\n", |
| 165 purple_account_get_username(account)); |
175 purple_account_get_username(account)); |
| 166 |
176 |
| 167 purple_keyring_get_password(account, |
177 manager = purple_credential_manager_get_default(); |
| 168 purple_account_register_got_password_cb, NULL); |
178 purple_credential_manager_read_password_async(manager, account, NULL, |
| |
179 purple_account_register_got_password_cb, |
| |
180 account); |
| 169 } |
181 } |
| 170 |
182 |
| 171 static void |
183 static void |
| 172 purple_account_unregister_got_password_cb(PurpleAccount *account, |
184 purple_account_unregister_got_password_cb(GObject *obj, GAsyncResult *res, |
| 173 const gchar *password, GError *error, gpointer data) |
185 gpointer data) |
| 174 { |
186 { |
| |
187 PurpleCredentialManager *manager = PURPLE_CREDENTIAL_MANAGER(obj); |
| 175 PurpleCallbackBundle *cbb = data; |
188 PurpleCallbackBundle *cbb = data; |
| 176 PurpleAccountUnregistrationCb cb; |
189 PurpleAccountUnregistrationCb cb; |
| |
190 gchar *password = NULL; |
| 177 |
191 |
| 178 cb = (PurpleAccountUnregistrationCb)cbb->cb; |
192 cb = (PurpleAccountUnregistrationCb)cbb->cb; |
| 179 _purple_connection_new_unregister(account, password, cb, cbb->data); |
193 |
| 180 |
194 password = purple_credential_manager_read_password_finish(manager, res, |
| |
195 NULL); |
| |
196 |
| |
197 _purple_connection_new_unregister(cbb->account, password, cb, cbb->data); |
| |
198 |
| |
199 g_free(password); |
| 181 g_free(cbb); |
200 g_free(cbb); |
| 182 } |
201 } |
| 183 |
202 |
| 184 struct register_completed_closure |
203 struct register_completed_closure |
| 185 { |
204 { |
| 201 |
220 |
| 202 g_object_unref(closure->account); |
221 g_object_unref(closure->account); |
| 203 g_free(closure); |
222 g_free(closure); |
| 204 |
223 |
| 205 return FALSE; |
224 return FALSE; |
| |
225 } |
| |
226 |
| |
227 static void |
| |
228 request_password_write_cb(GObject *obj, GAsyncResult *res, gpointer data) { |
| |
229 PurpleCredentialManager *manager = PURPLE_CREDENTIAL_MANAGER(obj); |
| |
230 PurpleAccount *account = PURPLE_ACCOUNT(data); |
| |
231 GError *error = NULL; |
| |
232 gchar *password = NULL; |
| |
233 |
| |
234 /* We stash the password on the account to get it to this call back... It's |
| |
235 * kind of gross but shouldn't be a big deal because any plugin has access |
| |
236 * to the credential store, so it's not really a security leak. |
| |
237 */ |
| |
238 password = (gchar *)g_object_get_data(G_OBJECT(account), "_tmp_password"); |
| |
239 g_object_set_data(G_OBJECT(account), "_tmp_password", NULL); |
| |
240 |
| |
241 if(!purple_credential_manager_write_password_finish(manager, res, &error)) { |
| |
242 const gchar *name = purple_account_get_name_for_display(account); |
| |
243 |
| |
244 /* we can't error an account without a connection, so we just drop a |
| |
245 * debug message for now and continue to connect the account. |
| |
246 */ |
| |
247 purple_debug_info("account", |
| |
248 "failed to save password for account \"%s\": %s", |
| |
249 name, |
| |
250 error != NULL ? error->message : "unknown error"); |
| |
251 } |
| |
252 |
| |
253 _purple_connection_new(account, FALSE, password); |
| |
254 |
| |
255 g_free(password); |
| 206 } |
256 } |
| 207 |
257 |
| 208 static void |
258 static void |
| 209 request_password_ok_cb(PurpleAccount *account, PurpleRequestFields *fields) |
259 request_password_ok_cb(PurpleAccount *account, PurpleRequestFields *fields) |
| 210 { |
260 { |
| 222 return; |
272 return; |
| 223 } |
273 } |
| 224 |
274 |
| 225 purple_account_set_remember_password(account, remember); |
275 purple_account_set_remember_password(account, remember); |
| 226 |
276 |
| 227 purple_account_set_password(account, entry, NULL, NULL); |
277 if(remember) { |
| 228 _purple_connection_new(account, FALSE, entry); |
278 PurpleCredentialManager *manager = NULL; |
| |
279 |
| |
280 manager = purple_credential_manager_get_default(); |
| |
281 |
| |
282 /* The requests field can be invalidated by the time we write the |
| |
283 * password and we want to use it in the write callback, so we need to |
| |
284 * duplicate it for that callback. |
| |
285 */ |
| |
286 g_object_set_data(G_OBJECT(account), "_tmp_password", g_strdup(entry)); |
| |
287 purple_credential_manager_write_password_async(manager, account, entry, |
| |
288 NULL, |
| |
289 request_password_write_cb, |
| |
290 account); |
| |
291 } else { |
| |
292 _purple_connection_new(account, FALSE, entry); |
| |
293 } |
| 229 } |
294 } |
| 230 |
295 |
| 231 static void |
296 static void |
| 232 request_password_cancel_cb(PurpleAccount *account, PurpleRequestFields *fields) |
297 request_password_cancel_cb(PurpleAccount *account, PurpleRequestFields *fields) |
| 233 { |
298 { |
| 235 purple_account_set_enabled(account, purple_core_get_ui(), FALSE); |
300 purple_account_set_enabled(account, purple_core_get_ui(), FALSE); |
| 236 } |
301 } |
| 237 |
302 |
| 238 |
303 |
| 239 static void |
304 static void |
| 240 purple_account_connect_got_password_cb(PurpleAccount *account, |
305 purple_account_connect_got_password_cb(GObject *obj, GAsyncResult *res, |
| 241 const gchar *password, GError *error, gpointer data) |
306 gpointer data) |
| 242 { |
307 { |
| 243 PurpleProtocol *protocol = data; |
308 PurpleCredentialManager *manager = PURPLE_CREDENTIAL_MANAGER(obj); |
| 244 |
309 PurpleAccount *account = PURPLE_ACCOUNT(data); |
| 245 if ((password == NULL || *password == '\0') && |
310 PurpleProtocol *protocol = NULL; |
| |
311 gchar *password = NULL; |
| |
312 |
| |
313 password = purple_credential_manager_read_password_finish(manager, res, |
| |
314 NULL); |
| |
315 |
| |
316 protocol = purple_protocols_find(purple_account_get_protocol_id(account)); |
| |
317 |
| |
318 if((password == NULL || *password == '\0') && |
| 246 !(purple_protocol_get_options(protocol) & OPT_PROTO_NO_PASSWORD) && |
319 !(purple_protocol_get_options(protocol) & OPT_PROTO_NO_PASSWORD) && |
| 247 !(purple_protocol_get_options(protocol) & OPT_PROTO_PASSWORD_OPTIONAL)) |
320 !(purple_protocol_get_options(protocol) & OPT_PROTO_PASSWORD_OPTIONAL)) |
| |
321 { |
| 248 purple_account_request_password(account, |
322 purple_account_request_password(account, |
| 249 G_CALLBACK(request_password_ok_cb), |
323 G_CALLBACK(request_password_ok_cb), |
| 250 G_CALLBACK(request_password_cancel_cb), account); |
324 G_CALLBACK(request_password_cancel_cb), account); |
| 251 else |
325 } else { |
| 252 _purple_connection_new(account, FALSE, password); |
326 _purple_connection_new(account, FALSE, password); |
| |
327 } |
| |
328 |
| |
329 g_free(password); |
| 253 } |
330 } |
| 254 |
331 |
| 255 static PurpleAccountRequestInfo * |
332 static PurpleAccountRequestInfo * |
| 256 purple_account_request_info_unref(PurpleAccountRequestInfo *info) |
333 purple_account_request_info_unref(PurpleAccountRequestInfo *info) |
| 257 { |
334 { |
| 427 gc = purple_account_get_connection(account); |
504 gc = purple_account_get_connection(account); |
| 428 if (!gc) |
505 if (!gc) |
| 429 return PURPLE_CONNECTION_DISCONNECTED; |
506 return PURPLE_CONNECTION_DISCONNECTED; |
| 430 |
507 |
| 431 return purple_connection_get_state(gc); |
508 return purple_connection_get_state(gc); |
| 432 } |
|
| 433 |
|
| 434 static void |
|
| 435 purple_account_get_password_got(PurpleAccount *account, |
|
| 436 const gchar *password, GError *error, gpointer data) |
|
| 437 { |
|
| 438 PurpleCallbackBundle *cbb = data; |
|
| 439 PurpleKeyringReadCallback cb; |
|
| 440 PurpleAccountPrivate *priv = purple_account_get_instance_private(account); |
|
| 441 |
|
| 442 purple_debug_info("account", |
|
| 443 "Read password for account %s from async keyring.\n", |
|
| 444 purple_account_get_username(account)); |
|
| 445 |
|
| 446 purple_str_wipe(priv->password); |
|
| 447 priv->password = g_strdup(password); |
|
| 448 |
|
| 449 cb = (PurpleKeyringReadCallback)cbb->cb; |
|
| 450 if (cb != NULL) |
|
| 451 cb(account, password, error, cbb->data); |
|
| 452 |
|
| 453 g_free(cbb); |
|
| 454 } |
509 } |
| 455 |
510 |
| 456 /* |
511 /* |
| 457 * This makes sure your permit list contains all buddies from your |
512 * This makes sure your permit list contains all buddies from your |
| 458 * buddy list and ONLY buddies from your buddy list. |
513 * buddy list and ONLY buddies from your buddy list. |
| 1068 g_free(priv->current_error); |
1123 g_free(priv->current_error); |
| 1069 } |
1124 } |
| 1070 |
1125 |
| 1071 g_free(priv->username); |
1126 g_free(priv->username); |
| 1072 g_free(priv->alias); |
1127 g_free(priv->alias); |
| 1073 purple_str_wipe(priv->password); |
|
| 1074 g_free(priv->user_info); |
1128 g_free(priv->user_info); |
| 1075 g_free(priv->buddy_icon_path); |
1129 g_free(priv->buddy_icon_path); |
| 1076 g_free(priv->protocol_id); |
1130 g_free(priv->protocol_id); |
| 1077 |
1131 |
| 1078 g_hash_table_destroy(priv->settings); |
1132 g_hash_table_destroy(priv->settings); |
| 1195 NULL, purple_request_cpar_from_account(account)); |
1249 NULL, purple_request_cpar_from_account(account)); |
| 1196 g_free(message); |
1250 g_free(message); |
| 1197 return; |
1251 return; |
| 1198 } |
1252 } |
| 1199 |
1253 |
| 1200 priv = purple_account_get_instance_private(account); |
|
| 1201 |
|
| 1202 purple_debug_info("account", "Connecting to account %s.\n", username); |
1254 purple_debug_info("account", "Connecting to account %s.\n", username); |
| 1203 |
1255 |
| 1204 if (priv->password != NULL) { |
1256 manager = purple_credential_manager_get_default(); |
| 1205 purple_account_connect_got_password_cb(account, |
1257 purple_credential_manager_read_password_async(manager, account, NULL, |
| 1206 priv->password, NULL, protocol); |
1258 purple_account_connect_got_password_cb, |
| 1207 } else { |
1259 account); |
| 1208 purple_keyring_get_password(account, |
|
| 1209 purple_account_connect_got_password_cb, protocol); |
|
| 1210 } |
|
| 1211 } |
1260 } |
| 1212 |
1261 |
| 1213 void |
1262 void |
| 1214 purple_account_set_register_callback(PurpleAccount *account, PurpleAccountRegistrationCb cb, void *user_data) |
1263 purple_account_set_register_callback(PurpleAccount *account, PurpleAccountRegistrationCb cb, void *user_data) |
| 1215 { |
1264 { |
| 1236 |
1285 |
| 1237 g_timeout_add(0, purple_account_register_completed_cb, closure); |
1286 g_timeout_add(0, purple_account_register_completed_cb, closure); |
| 1238 } |
1287 } |
| 1239 |
1288 |
| 1240 void |
1289 void |
| 1241 purple_account_unregister(PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data) |
1290 purple_account_unregister(PurpleAccount *account, |
| |
1291 PurpleAccountUnregistrationCb cb, gpointer user_data) |
| 1242 { |
1292 { |
| 1243 PurpleCallbackBundle *cbb; |
1293 PurpleCallbackBundle *cbb; |
| |
1294 PurpleCredentialManager *manager = NULL; |
| 1244 |
1295 |
| 1245 g_return_if_fail(PURPLE_IS_ACCOUNT(account)); |
1296 g_return_if_fail(PURPLE_IS_ACCOUNT(account)); |
| 1246 |
1297 |
| 1247 purple_debug_info("account", "Unregistering account %s\n", |
1298 purple_debug_info("account", "Unregistering account %s\n", |
| 1248 purple_account_get_username(account)); |
1299 purple_account_get_username(account)); |
| 1249 |
1300 |
| 1250 cbb = g_new0(PurpleCallbackBundle, 1); |
1301 cbb = g_new0(PurpleCallbackBundle, 1); |
| |
1302 cbb->account = account; |
| 1251 cbb->cb = PURPLE_CALLBACK(cb); |
1303 cbb->cb = PURPLE_CALLBACK(cb); |
| 1252 cbb->data = user_data; |
1304 cbb->data = user_data; |
| 1253 |
1305 |
| 1254 purple_keyring_get_password(account, |
1306 manager = purple_credential_manager_get_default(); |
| 1255 purple_account_unregister_got_password_cb, cbb); |
1307 purple_credential_manager_read_password_async(manager, account, NULL, |
| |
1308 purple_account_unregister_got_password_cb, |
| |
1309 cbb); |
| 1256 } |
1310 } |
| 1257 |
1311 |
| 1258 void |
1312 void |
| 1259 purple_account_disconnect(PurpleAccount *account) |
1313 purple_account_disconnect(PurpleAccount *account) |
| 1260 { |
1314 { |
| 1565 * to disk with the new name */ |
1619 * to disk with the new name */ |
| 1566 purple_blist_save_account(purple_blist_get_default(), account); |
1620 purple_blist_save_account(purple_blist_get_default(), account); |
| 1567 } |
1621 } |
| 1568 |
1622 |
| 1569 void |
1623 void |
| 1570 purple_account_set_password(PurpleAccount *account, const gchar *password, |
|
| 1571 PurpleKeyringSaveCallback cb, gpointer data) |
|
| 1572 { |
|
| 1573 PurpleAccountPrivate *priv; |
|
| 1574 |
|
| 1575 g_return_if_fail(PURPLE_IS_ACCOUNT(account)); |
|
| 1576 |
|
| 1577 priv = purple_account_get_instance_private(account); |
|
| 1578 |
|
| 1579 purple_str_wipe(priv->password); |
|
| 1580 priv->password = g_strdup(password); |
|
| 1581 |
|
| 1582 purple_accounts_schedule_save(); |
|
| 1583 |
|
| 1584 if (!purple_account_get_remember_password(account)) { |
|
| 1585 purple_debug_info("account", |
|
| 1586 "Password for %s set, not sent to keyring.\n", |
|
| 1587 purple_account_get_username(account)); |
|
| 1588 |
|
| 1589 if (cb != NULL) |
|
| 1590 cb(account, NULL, data); |
|
| 1591 } else { |
|
| 1592 purple_keyring_set_password(account, password, cb, data); |
|
| 1593 } |
|
| 1594 } |
|
| 1595 |
|
| 1596 void |
|
| 1597 purple_account_set_private_alias(PurpleAccount *account, const char *alias) |
1624 purple_account_set_private_alias(PurpleAccount *account, const char *alias) |
| 1598 { |
1625 { |
| 1599 PurpleAccountPrivate *priv; |
1626 PurpleAccountPrivate *priv; |
| 1600 |
1627 |
| 1601 g_return_if_fail(PURPLE_IS_ACCOUNT(account)); |
1628 g_return_if_fail(PURPLE_IS_ACCOUNT(account)); |
| 2090 |
2117 |
| 2091 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL); |
2118 g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL); |
| 2092 |
2119 |
| 2093 priv = purple_account_get_instance_private(account); |
2120 priv = purple_account_get_instance_private(account); |
| 2094 return priv->username; |
2121 return priv->username; |
| 2095 } |
|
| 2096 |
|
| 2097 void |
|
| 2098 purple_account_get_password(PurpleAccount *account, |
|
| 2099 PurpleKeyringReadCallback cb, gpointer data) |
|
| 2100 { |
|
| 2101 PurpleAccountPrivate *priv; |
|
| 2102 |
|
| 2103 if (account == NULL) { |
|
| 2104 cb(NULL, NULL, NULL, data); |
|
| 2105 return; |
|
| 2106 } |
|
| 2107 |
|
| 2108 priv = purple_account_get_instance_private(account); |
|
| 2109 |
|
| 2110 if (priv->password != NULL) { |
|
| 2111 purple_debug_info("account", |
|
| 2112 "Reading password for account %s from cache.\n", |
|
| 2113 purple_account_get_username(account)); |
|
| 2114 cb(account, priv->password, NULL, data); |
|
| 2115 } else { |
|
| 2116 PurpleCallbackBundle *cbb = g_new0(PurpleCallbackBundle, 1); |
|
| 2117 cbb->cb = PURPLE_CALLBACK(cb); |
|
| 2118 cbb->data = data; |
|
| 2119 |
|
| 2120 purple_debug_info("account", |
|
| 2121 "Reading password for account %s from async keyring.\n", |
|
| 2122 purple_account_get_username(account)); |
|
| 2123 purple_keyring_get_password(account, |
|
| 2124 purple_account_get_password_got, cbb); |
|
| 2125 } |
|
| 2126 } |
2122 } |
| 2127 |
2123 |
| 2128 const char * |
2124 const char * |
| 2129 purple_account_get_private_alias(PurpleAccount *account) |
2125 purple_account_get_private_alias(PurpleAccount *account) |
| 2130 { |
2126 { |
| 2985 |
2981 |
| 2986 void |
2982 void |
| 2987 purple_account_change_password(PurpleAccount *account, const char *orig_pw, |
2983 purple_account_change_password(PurpleAccount *account, const char *orig_pw, |
| 2988 const char *new_pw) |
2984 const char *new_pw) |
| 2989 { |
2985 { |
| |
2986 PurpleCredentialManager *manager = NULL; |
| 2990 PurpleProtocol *protocol = NULL; |
2987 PurpleProtocol *protocol = NULL; |
| 2991 PurpleConnection *gc = purple_account_get_connection(account); |
2988 PurpleConnection *gc = purple_account_get_connection(account); |
| 2992 |
2989 |
| 2993 purple_account_set_password(account, new_pw, NULL, NULL); |
2990 /* just going to fire and forget this for now as not many protocols even |
| |
2991 * implement the change password stuff. |
| |
2992 */ |
| |
2993 manager = purple_credential_manager_get_default(); |
| |
2994 purple_credential_manager_write_password_async(manager, account, new_pw, |
| |
2995 NULL, NULL, NULL); |
| 2994 |
2996 |
| 2995 if (gc != NULL) |
2997 if (gc != NULL) |
| 2996 protocol = purple_connection_get_protocol(gc); |
2998 protocol = purple_connection_get_protocol(gc); |
| 2997 |
2999 |
| 2998 if (protocol) |
3000 if (protocol) |