libpurple/account.c

changeset 40680
f9ea6d5e8992
parent 40634
4d3018b00ad4
child 40683
dcc53af7a4fb
equal deleted inserted replaced
40679:062a4574af3e 40680:f9ea6d5e8992
29 #include "network.h" 29 #include "network.h"
30 #include "notify.h" 30 #include "notify.h"
31 #include "pounce.h" 31 #include "pounce.h"
32 #include "prefs.h" 32 #include "prefs.h"
33 #include "purpleaccountpresence.h" 33 #include "purpleaccountpresence.h"
34 #include "purplecredentialmanager.h"
34 #include "purpleprivate.h" 35 #include "purpleprivate.h"
35 #include "purpleprotocolclient.h" 36 #include "purpleprotocolclient.h"
36 #include "request.h" 37 #include "request.h"
37 #include "server.h" 38 #include "server.h"
38 #include "signals.h" 39 #include "signals.h"
50 51
51 typedef struct 52 typedef struct
52 { 53 {
53 char *username; /* The username. */ 54 char *username; /* The username. */
54 char *alias; /* How you appear to yourself. */ 55 char *alias; /* How you appear to yourself. */
55 char *password; /* The account password. */
56 char *user_info; /* User information. */ 56 char *user_info; /* User information. */
57 57
58 char *buddy_icon_path; /* The buddy icon's non-cached path. */ 58 char *buddy_icon_path; /* The buddy icon's non-cached path. */
59 59
60 gboolean remember_pass; /* Remember the password. */ 60 gboolean remember_pass; /* Remember the password. */
117 guint ref; 117 guint ref;
118 } PurpleAccountRequestInfo; 118 } PurpleAccountRequestInfo;
119 119
120 typedef struct 120 typedef struct
121 { 121 {
122 PurpleAccount *account;
122 PurpleCallback cb; 123 PurpleCallback cb;
123 gpointer data; 124 gpointer data;
124 } PurpleCallbackBundle; 125 } PurpleCallbackBundle;
125 126
126 /* GObject Property enums */ 127 /* GObject Property enums */
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);
1169 } 1223 }
1170 1224
1171 void 1225 void
1172 purple_account_connect(PurpleAccount *account) 1226 purple_account_connect(PurpleAccount *account)
1173 { 1227 {
1174 const char *username; 1228 PurpleCredentialManager *manager = NULL;
1175 PurpleProtocol *protocol; 1229 PurpleProtocol *protocol = NULL;
1176 PurpleAccountPrivate *priv; 1230 const char *username = NULL;
1177 1231
1178 g_return_if_fail(PURPLE_IS_ACCOUNT(account)); 1232 g_return_if_fail(PURPLE_IS_ACCOUNT(account));
1179 1233
1180 username = purple_account_get_username(account); 1234 username = purple_account_get_username(account);
1181 1235
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)

mercurial