--- a/libpurple/protocols/gg/multilogon.c Tue Jan 07 18:53:13 2014 +0100 +++ b/libpurple/protocols/gg/multilogon.c Tue Jan 07 19:02:19 2014 +0100 @@ -32,12 +32,25 @@ #include <debug.h> #include "gg.h" +#include "keymapper.h" #include "utils.h" #include "message-prpl.h" +typedef struct +{ + uint64_t id; + uint32_t remote_addr; + gchar *name; + time_t logon_time; +} ggp_multilogon_session_info; + struct _ggp_multilogon_session_data { int session_count; + ggp_multilogon_session_info *sessions; + PurpleRequestDatasheet *sheet_handle; + gpointer dialog_handle; + ggp_keymapper *sid_mapper; }; static inline ggp_multilogon_session_data * @@ -52,41 +65,192 @@ return accdata->multilogon_data; } -void ggp_multilogon_setup(PurpleConnection *gc) +void +ggp_multilogon_setup(PurpleConnection *gc) { GGPInfo *accdata = purple_connection_get_protocol_data(gc); - + ggp_multilogon_session_data *mldata = g_new0(ggp_multilogon_session_data, 1); accdata->multilogon_data = mldata; + + mldata->sid_mapper = ggp_keymapper_new(); } -void ggp_multilogon_cleanup(PurpleConnection *gc) +static void +ggp_multilogon_free_sessions(PurpleConnection *gc) { ggp_multilogon_session_data *mldata = ggp_multilogon_get_mldata(gc); + int i; + + for (i = 0; i < mldata->session_count; i++) + g_free(mldata->sessions[i].name); + g_free(mldata->sessions); + + mldata->sessions = NULL; + mldata->session_count = 0; +} + +void +ggp_multilogon_cleanup(PurpleConnection *gc) +{ + ggp_multilogon_session_data *mldata = ggp_multilogon_get_mldata(gc); + + if (mldata->dialog_handle) { + purple_request_close(PURPLE_REQUEST_FIELDS, + mldata->dialog_handle); + mldata->dialog_handle = NULL; + } + + ggp_multilogon_free_sessions(gc); + ggp_keymapper_free(mldata->sid_mapper); g_free(mldata); } -void ggp_multilogon_info(PurpleConnection *gc, - struct gg_event_multilogon_info *info) +static uint64_t +ggp_multilogon_sid_from_libgadu(gg_multilogon_id_t lsid) +{ + uint64_t sid; + + memcpy(&sid, lsid.id, sizeof(uint64_t)); + + return sid; +} + +static gg_multilogon_id_t +ggp_multilogon_sid_to_libgadu(uint64_t sid) +{ + gg_multilogon_id_t lsid; + + memcpy(lsid.id, &sid, sizeof(uint64_t)); + + return lsid; +} + +void +ggp_multilogon_fill_sessions(PurpleRequestDatasheet *sheet, + PurpleConnection *gc) +{ + ggp_multilogon_session_data *mldata = ggp_multilogon_get_mldata(gc); + ggp_keymapper *km = mldata->sid_mapper; + int i; + + purple_request_datasheet_record_mark_all_for_rem(sheet); + + for (i = 0; i < mldata->session_count; i++) { + ggp_multilogon_session_info *sess = &mldata->sessions[i]; + PurpleRequestDatasheetRecord *rec; + + rec = purple_request_datasheet_record_add(sheet, + ggp_keymapper_to_key(km, sess->id)); + + purple_request_datasheet_record_set_string_data(rec, 0, + ggp_ipv4_to_str(sess->remote_addr)); + purple_request_datasheet_record_set_string_data(rec, 1, + purple_date_format_full(localtime(&sess->logon_time))); + purple_request_datasheet_record_set_string_data(rec, 2, + sess->name); + } + + purple_request_datasheet_record_remove_marked(sheet); +} + +void +ggp_multilogon_info(PurpleConnection *gc, struct gg_event_multilogon_info *info) { ggp_multilogon_session_data *mldata = ggp_multilogon_get_mldata(gc); int i; - - purple_debug_info("gg", "ggp_multilogon_info: session list changed\n"); - for (i = 0; i < info->count; i++) - { - purple_debug_misc("gg", "ggp_multilogon_info: " - "session [%s] logged in at %lu\n", - info->sessions[i].name, - (unsigned long)info->sessions[i].logon_time); + + ggp_multilogon_free_sessions(gc); + + purple_debug_info("gg", "ggp_multilogon_info: session list changed " + "(count now: %d)\n", info->count); + + mldata->sessions = g_new(ggp_multilogon_session_info, info->count); + for (i = 0; i < info->count; i++) { + struct gg_multilogon_session *lsess = &info->sessions[i]; + ggp_multilogon_session_info *psess = &mldata->sessions[i]; + + psess->id = ggp_multilogon_sid_from_libgadu(lsess->id); + psess->remote_addr = lsess->remote_addr; + psess->name = g_strdup(lsess->name); + psess->logon_time = lsess->logon_time; } mldata->session_count = info->count; + + if (mldata->sheet_handle != NULL) + ggp_multilogon_fill_sessions(mldata->sheet_handle, gc); +} + +void +ggp_multilogon_disconnect(PurpleRequestDatasheetRecord *rec, gpointer _gc) +{ + PurpleConnection *gc = _gc; + ggp_multilogon_session_data *mldata = ggp_multilogon_get_mldata(gc); + GGPInfo *accdata = purple_connection_get_protocol_data(gc); + uint64_t sid; + gpointer key; + + key = purple_request_datasheet_record_get_key(rec); + sid = ggp_keymapper_from_key(mldata->sid_mapper, key); + + gg_multilogon_disconnect(accdata->session, + ggp_multilogon_sid_to_libgadu(sid)); + + purple_request_datasheet_record_remove( + purple_request_datasheet_record_get_datasheet(rec), key); } -int ggp_multilogon_get_session_count(PurpleConnection *gc) +void +ggp_multilogon_dialog(PurpleConnection *gc) { ggp_multilogon_session_data *mldata = ggp_multilogon_get_mldata(gc); - return mldata->session_count; + PurpleRequestField *field; + PurpleRequestFields *fields; + PurpleRequestFieldGroup *group; + PurpleRequestCommonParameters *cpar; + PurpleRequestDatasheet *sheet; + PurpleRequestDatasheetAction *action; + gpointer dialog_handle; + + if (mldata->dialog_handle != NULL) + return; + + fields = purple_request_fields_new(); + group = purple_request_field_group_new(NULL); + purple_request_fields_add_group(fields, group); + + sheet = purple_request_datasheet_new(); + purple_request_datasheet_add_column(sheet, + PURPLE_REQUEST_DATASHEET_COLUMN_STRING, _("IP")); + purple_request_datasheet_add_column(sheet, + PURPLE_REQUEST_DATASHEET_COLUMN_STRING, _("Logon time")); + purple_request_datasheet_add_column(sheet, + PURPLE_REQUEST_DATASHEET_COLUMN_STRING, _("Session")); + + action = purple_request_datasheet_action_new(); + purple_request_datasheet_action_set_label(action, _("Disconnect")); + purple_request_datasheet_action_set_cb(action, + ggp_multilogon_disconnect, gc); + purple_request_datasheet_add_action(sheet, action); + ggp_multilogon_fill_sessions(sheet, gc); + + field = purple_request_field_datasheet_new("sessions", NULL, sheet); + purple_request_field_group_add_field(group, field); + + cpar = purple_request_cpar_new(); + purple_request_cpar_set_icon(cpar, PURPLE_REQUEST_ICON_DIALOG); + + dialog_handle = purple_request_fields(gc, + _("Other Gadu-Gadu sessions"), NULL, NULL, fields, + NULL, NULL, _("Close"), NULL, + cpar, NULL); + mldata->sheet_handle = sheet; + mldata->dialog_handle = dialog_handle; + + purple_request_add_close_notify(dialog_handle, + purple_callback_set_zero, &mldata->sheet_handle); + purple_request_add_close_notify(dialog_handle, + purple_callback_set_zero, &mldata->dialog_handle); }