Mercurial > pidgin.yaz
comparison libpurple/account.c @ 24644:98ec72f8f3cc
Use ref-counting to prevent a crash if request-auth callbacks are called
immediately/synchronously. Thanks a lot to Florian Quze for the initial
patch, and for testing the alternate fix. Closes #7604.
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Thu, 11 Dec 2008 21:10:57 +0000 |
parents | eacf48c09ccc |
children | ff883620d9d4 65cfc59858cf 1260a3fb60f4 |
comparison
equal
deleted
inserted
replaced
24629:662fdd4836aa | 24644:98ec72f8f3cc |
---|---|
73 void *ui_handle; | 73 void *ui_handle; |
74 char *user; | 74 char *user; |
75 gpointer userdata; | 75 gpointer userdata; |
76 PurpleAccountRequestAuthorizationCb auth_cb; | 76 PurpleAccountRequestAuthorizationCb auth_cb; |
77 PurpleAccountRequestAuthorizationCb deny_cb; | 77 PurpleAccountRequestAuthorizationCb deny_cb; |
78 guint ref; | |
78 } PurpleAccountRequestInfo; | 79 } PurpleAccountRequestInfo; |
79 | 80 |
80 static PurpleAccountUiOps *account_ui_ops = NULL; | 81 static PurpleAccountUiOps *account_ui_ops = NULL; |
81 | 82 |
82 static GList *accounts = NULL; | 83 static GList *accounts = NULL; |
1209 | 1210 |
1210 if (ui_ops != NULL && ui_ops->request_add != NULL) | 1211 if (ui_ops != NULL && ui_ops->request_add != NULL) |
1211 ui_ops->request_add(account, remote_user, id, alias, message); | 1212 ui_ops->request_add(account, remote_user, id, alias, message); |
1212 } | 1213 } |
1213 | 1214 |
1215 static PurpleAccountRequestInfo * | |
1216 purple_account_request_info_unref(PurpleAccountRequestInfo *info) | |
1217 { | |
1218 if (--info->ref) | |
1219 return info; | |
1220 | |
1221 /* TODO: This will leak info->user_data, but there is no callback to just clean that up */ | |
1222 g_free(info->user); | |
1223 g_free(info); | |
1224 return NULL; | |
1225 } | |
1226 | |
1214 static void | 1227 static void |
1215 purple_account_request_close_info(PurpleAccountRequestInfo *info) | 1228 purple_account_request_close_info(PurpleAccountRequestInfo *info) |
1216 { | 1229 { |
1217 PurpleAccountUiOps *ops; | 1230 PurpleAccountUiOps *ops; |
1218 | 1231 |
1219 ops = purple_accounts_get_ui_ops(); | 1232 ops = purple_accounts_get_ui_ops(); |
1220 | 1233 |
1221 if (ops != NULL && ops->close_account_request != NULL) | 1234 if (ops != NULL && ops->close_account_request != NULL) |
1222 ops->close_account_request(info->ui_handle); | 1235 ops->close_account_request(info->ui_handle); |
1223 | 1236 |
1224 /* TODO: This will leak info->user_data, but there is no callback to just clean that up */ | 1237 purple_account_request_info_unref(info); |
1225 | |
1226 g_free(info->user); | |
1227 g_free(info); | |
1228 | |
1229 } | 1238 } |
1230 | 1239 |
1231 void | 1240 void |
1232 purple_account_request_close_with_account(PurpleAccount *account) | 1241 purple_account_request_close_with_account(PurpleAccount *account) |
1233 { | 1242 { |
1276 info->auth_cb(info->userdata); | 1285 info->auth_cb(info->userdata); |
1277 | 1286 |
1278 purple_signal_emit(purple_accounts_get_handle(), | 1287 purple_signal_emit(purple_accounts_get_handle(), |
1279 "account-authorization-granted", info->account, info->user); | 1288 "account-authorization-granted", info->account, info->user); |
1280 | 1289 |
1281 g_free(info->user); | 1290 purple_account_request_info_unref(info); |
1282 g_free(info); | |
1283 } | 1291 } |
1284 | 1292 |
1285 static void | 1293 static void |
1286 request_deny_cb(void *data) | 1294 request_deny_cb(void *data) |
1287 { | 1295 { |
1292 info->deny_cb(info->userdata); | 1300 info->deny_cb(info->userdata); |
1293 | 1301 |
1294 purple_signal_emit(purple_accounts_get_handle(), | 1302 purple_signal_emit(purple_accounts_get_handle(), |
1295 "account-authorization-denied", info->account, info->user); | 1303 "account-authorization-denied", info->account, info->user); |
1296 | 1304 |
1297 g_free(info->user); | 1305 purple_account_request_info_unref(info); |
1298 g_free(info); | |
1299 } | 1306 } |
1300 | 1307 |
1301 void * | 1308 void * |
1302 purple_account_request_authorization(PurpleAccount *account, const char *remote_user, | 1309 purple_account_request_authorization(PurpleAccount *account, const char *remote_user, |
1303 const char *id, const char *alias, const char *message, gboolean on_list, | 1310 const char *id, const char *alias, const char *message, gboolean on_list, |
1330 info->account = account; | 1337 info->account = account; |
1331 info->auth_cb = auth_cb; | 1338 info->auth_cb = auth_cb; |
1332 info->deny_cb = deny_cb; | 1339 info->deny_cb = deny_cb; |
1333 info->userdata = user_data; | 1340 info->userdata = user_data; |
1334 info->user = g_strdup(remote_user); | 1341 info->user = g_strdup(remote_user); |
1342 info->ref = 2; /* We hold an extra ref to make sure info remains valid | |
1343 if any of the callbacks are called synchronously. We | |
1344 unref it after the function call */ | |
1345 | |
1335 info->ui_handle = ui_ops->request_authorize(account, remote_user, id, alias, message, | 1346 info->ui_handle = ui_ops->request_authorize(account, remote_user, id, alias, message, |
1336 on_list, request_auth_cb, request_deny_cb, info); | 1347 on_list, request_auth_cb, request_deny_cb, info); |
1337 | 1348 |
1338 handles = g_list_append(handles, info); | 1349 info = purple_account_request_info_unref(info); |
1339 return info->ui_handle; | 1350 if (info) { |
1351 handles = g_list_append(handles, info); | |
1352 return info->ui_handle; | |
1353 } | |
1340 } | 1354 } |
1341 | 1355 |
1342 return NULL; | 1356 return NULL; |
1343 } | 1357 } |
1344 | 1358 |