Tue, 07 Mar 2023 01:04:42 -0600
Convert PurpleRequestPage into a GObject
And rename it from `PurpleRequestFields`.
Also, implements `GListModel` for the groups, but nothing uses it that way get.
Testing Done:
Compiled, and opened Request Fields from Demo protocol.
Reviewed at https://reviews.imfreedom.org/r/2323/
/* purple * * Purple is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * source distribution. * * Rewritten from scratch during Google Summer of Code 2012 * by Tomek Wasilczyk (http://www.wasilczyk.pl). * * Previously implemented by: * - Arkadiusz Miskiewicz <misiek@pld.org.pl> - first implementation (2001); * - Bartosz Oler <bartosz@bzimage.us> - reimplemented during GSoC 2005; * - Krzysztof Klinikowski <grommasher@gmail.com> - some parts (2009-2011). * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ #include <glib/gi18n-lib.h> #include <libgadu.h> #include "status.h" #include "gg.h" #include "utils.h" struct _ggp_status_session_data { gboolean status_broadcasting; gchar *current_description; }; static inline ggp_status_session_data * ggp_status_get_ssdata(PurpleConnection *gc); static gchar * ggp_status_validate_description(const gchar* msg); static inline ggp_status_session_data * ggp_status_get_ssdata(PurpleConnection *gc) { GGPInfo *accdata = purple_connection_get_protocol_data(gc); return accdata->status_data; } void ggp_status_setup(PurpleConnection *gc) { GGPInfo *accdata = purple_connection_get_protocol_data(gc); PurpleAccount *account = purple_connection_get_account(gc); ggp_status_session_data *ssdata = g_new0(ggp_status_session_data, 1); accdata->status_data = ssdata; ssdata->status_broadcasting = purple_account_get_bool(account, "status_broadcasting", TRUE); } void ggp_status_cleanup(PurpleConnection *gc) { ggp_status_session_data *ssdata = ggp_status_get_ssdata(gc); g_free(ssdata->current_description); g_free(ssdata); } static gchar * ggp_status_validate_description(const gchar* msg) { if (msg == NULL || msg[0] == '\0') return NULL; return ggp_utf8_strndup(msg, GG_STATUS_DESCR_MAXSIZE); } GList * ggp_status_types(G_GNUC_UNUSED PurpleProtocol *protocol, G_GNUC_UNUSED PurpleAccount *account) { GList *types = NULL; types = g_list_append(types, purple_status_type_new_with_attrs( PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE, "message", _("Message"), purple_value_new(G_TYPE_STRING), NULL)); types = g_list_append(types, purple_status_type_new_with_attrs( PURPLE_STATUS_AVAILABLE, "freeforchat", _("Chatty"), TRUE, TRUE, FALSE, "message", _("Message"), purple_value_new(G_TYPE_STRING), NULL)); types = g_list_append(types, purple_status_type_new_with_attrs( PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE, "message", _("Message"), purple_value_new(G_TYPE_STRING), NULL)); types = g_list_append(types, purple_status_type_new_with_attrs( PURPLE_STATUS_UNAVAILABLE, NULL, NULL, TRUE, TRUE, FALSE, "message", _("Message"), purple_value_new(G_TYPE_STRING), NULL)); types = g_list_append(types, purple_status_type_new_with_attrs( PURPLE_STATUS_INVISIBLE, NULL, NULL, TRUE, TRUE, FALSE, "message", _("Message"), purple_value_new(G_TYPE_STRING), NULL)); types = g_list_append(types, purple_status_type_new_with_attrs( PURPLE_STATUS_OFFLINE, NULL, NULL, TRUE, TRUE, FALSE, "message", _("Message"), purple_value_new(G_TYPE_STRING), NULL)); return types; } int ggp_status_from_purplestatus(PurpleStatus *status, gchar **message) { const char *status_id = purple_status_get_id(status); const char *status_message = purple_status_get_attr_string(status, "message"); g_return_val_if_fail(message != NULL, 0); *message = NULL; if (status_message) { gchar *stripped = purple_markup_strip_html(status_message); g_strstrip(stripped); *message = ggp_status_validate_description(stripped); g_free(stripped); } if (0 == strcmp(status_id, "available")) return status_message ? GG_STATUS_AVAIL_DESCR : GG_STATUS_AVAIL; if (0 == strcmp(status_id, "freeforchat")) return status_message ? GG_STATUS_FFC_DESCR : GG_STATUS_FFC; if (0 == strcmp(status_id, "away")) return status_message ? GG_STATUS_BUSY_DESCR : GG_STATUS_BUSY; if (0 == strcmp(status_id, "unavailable")) return status_message ? GG_STATUS_DND_DESCR : GG_STATUS_DND; if (0 == strcmp(status_id, "invisible")) return status_message ? GG_STATUS_INVISIBLE_DESCR : GG_STATUS_INVISIBLE; if (0 == strcmp(status_id, "offline")) return status_message ? GG_STATUS_NOT_AVAIL_DESCR : GG_STATUS_NOT_AVAIL; purple_debug_error("gg", "ggp_status_from_purplestatus: " "unknown status requested (%s)\n", status_id); return status_message ? GG_STATUS_AVAIL_DESCR : GG_STATUS_AVAIL; } const gchar * ggp_status_to_purplestatus(int status) { switch (status) { case GG_STATUS_NOT_AVAIL: case GG_STATUS_NOT_AVAIL_DESCR: case GG_STATUS_BLOCKED: case GG_STATUS_UNKNOWN: return purple_primitive_get_id_from_type( PURPLE_STATUS_OFFLINE); case GG_STATUS_FFC: case GG_STATUS_FFC_DESCR: return "freeforchat"; case GG_STATUS_AVAIL: case GG_STATUS_AVAIL_DESCR: return purple_primitive_get_id_from_type( PURPLE_STATUS_AVAILABLE); case GG_STATUS_BUSY: case GG_STATUS_BUSY_DESCR: return purple_primitive_get_id_from_type( PURPLE_STATUS_AWAY); case GG_STATUS_INVISIBLE: case GG_STATUS_INVISIBLE_DESCR: return purple_primitive_get_id_from_type( PURPLE_STATUS_INVISIBLE); case GG_STATUS_DND: case GG_STATUS_DND_DESCR: return purple_primitive_get_id_from_type( PURPLE_STATUS_UNAVAILABLE); default: purple_debug_warning("gg", "ggp_status_to_purplestatus: unknown status %#02x\n", status); return purple_primitive_get_id_from_type( PURPLE_STATUS_AVAILABLE); } } const gchar * ggp_status_get_name(const gchar *purple_status) { if (g_strcmp0(purple_status, "freeforchat") == 0) return _("Chatty"); return purple_primitive_get_name_from_type( purple_primitive_get_type_from_id(purple_status)); } /******************************************************************************* * Own status. ******************************************************************************/ void ggp_status_set_initial(PurpleConnection *gc, struct gg_login_params *glp) { ggp_status_session_data *ssdata = ggp_status_get_ssdata(gc); PurpleAccount *account = purple_connection_get_account(gc); glp->status = ggp_status_from_purplestatus( purple_account_get_active_status(account), &glp->status_descr); if (!ggp_status_get_status_broadcasting(gc)) glp->status |= GG_STATUS_FRIENDS_MASK; ssdata->current_description = g_strdup(glp->status_descr); } gboolean ggp_status_set(PurpleAccount *account, int status, const gchar* msg) { PurpleConnection *gc = purple_account_get_connection(account); ggp_status_session_data *ssdata = ggp_status_get_ssdata(gc); GGPInfo *accdata = purple_connection_get_protocol_data(gc); gchar *new_description = ggp_status_validate_description(msg); if (!ssdata->status_broadcasting) status |= GG_STATUS_FRIENDS_MASK; if ((status == GG_STATUS_NOT_AVAIL || status == GG_STATUS_NOT_AVAIL_DESCR) && 0 == g_strcmp0(ssdata->current_description, new_description)) { purple_debug_info("gg", "ggp_status_set: new status doesn't " "differ when closing connection - ignore\n"); g_free(new_description); return FALSE; } g_free(ssdata->current_description); ssdata->current_description = new_description; if (msg == NULL) gg_change_status(accdata->session, status); else gg_change_status_descr(accdata->session, status, new_description); return TRUE; } void ggp_status_set_purplestatus(G_GNUC_UNUSED PurpleProtocolServer *protocol_server, PurpleAccount *account, PurpleStatus *status) { int status_gg; gchar *msg = NULL; if (!purple_status_is_active(status)) return; status_gg = ggp_status_from_purplestatus(status, &msg); ggp_status_set(account, status_gg, msg); g_free(msg); } void ggp_status_set_disconnected(PurpleAccount *account) { gchar *msg = NULL; ggp_status_from_purplestatus(purple_account_get_active_status(account), &msg); if (!ggp_status_set(account, msg ? GG_STATUS_NOT_AVAIL_DESCR : GG_STATUS_NOT_AVAIL, msg)) { g_free(msg); return; } /* struct gg_event *ev; guint64 wait_start = ggp_microtime(), now; int sleep_time = 5000; while ((ev = gg_watch_fd(info->session)) != NULL) { if (ev->type == GG_EVENT_DISCONNECT_ACK) break; now = ggp_microtime(); if (now - wait_start + sleep_time >= 100000) break; usleep(sleep_time); sleep_time *= 2; } */ g_usleep(100000); g_free(msg); } void ggp_status_fake_to_self(PurpleConnection *gc) { PurpleAccount *account = purple_connection_get_account(gc); PurpleContactInfo *info = PURPLE_CONTACT_INFO(account); PurpleStatus *status = purple_presence_get_active_status( purple_account_get_presence(account)); const char *status_msg = purple_status_get_attr_string(status, "message"); gchar *status_msg_gg = NULL; if (status_msg != NULL && status_msg[0] != '\0') { status_msg_gg = g_new0(gchar, GG_STATUS_DESCR_MAXSIZE + 1); g_utf8_strncpy(status_msg_gg, status_msg, GG_STATUS_DESCR_MAXSIZE); } purple_protocol_got_user_status(account, purple_contact_info_get_username(info), purple_status_get_id(status), status_msg_gg ? "message" : NULL, status_msg_gg, NULL); g_free(status_msg_gg); } gboolean ggp_status_get_status_broadcasting(PurpleConnection *gc) { return ggp_status_get_ssdata(gc)->status_broadcasting; } void ggp_status_set_status_broadcasting(PurpleConnection *gc, gboolean broadcasting) { PurpleAccount *account = purple_connection_get_account(gc); ggp_status_get_ssdata(gc)->status_broadcasting = broadcasting; purple_account_set_bool(account, "status_broadcasting", broadcasting); ggp_status_set_purplestatus(NULL, account, purple_account_get_active_status(account)); } static void ggp_status_broadcasting_dialog_ok(PurpleConnection *gc, PurpleRequestPage *page) { gboolean buddies_only = purple_request_page_get_bool(page, "buddies_only"); ggp_status_set_status_broadcasting(gc, !buddies_only); } void ggp_status_broadcasting_dialog(PurpleConnection *gc) { PurpleRequestPage *page; PurpleRequestGroup *group; PurpleRequestField *field; page = purple_request_page_new(); group = purple_request_group_new(NULL); purple_request_page_add_group(page, group); field = purple_request_field_bool_new("buddies_only", _("Show status only for buddies"), !ggp_status_get_status_broadcasting(gc)); purple_request_group_add_field(group, field); purple_request_fields(gc, _("Change status broadcasting"), _("Please, select who can see your status"), NULL, page, _("OK"), G_CALLBACK(ggp_status_broadcasting_dialog_ok), _("Cancel"), NULL, purple_request_cpar_from_connection(gc), gc); } /******************************************************************************* * Buddy status. ******************************************************************************/ void ggp_status_got_others_buddy(PurpleConnection *gc, uin_t uin, int status, const char *descr); /******************************************************************************/ void ggp_status_got_others(PurpleConnection *gc, struct gg_event *ev) { if (ev->type == GG_EVENT_NOTIFY60) { struct gg_event_notify60 *notify = ev->event.notify60; int i; for (i = 0; notify[i].uin; i++) ggp_status_got_others_buddy(gc, notify[i].uin, GG_S(notify[i].status), notify[i].descr); } else if (ev->type == GG_EVENT_STATUS60) { struct gg_event_status60 *notify = &ev->event.status60; ggp_status_got_others_buddy(gc, notify->uin, GG_S(notify->status), notify->descr); } else { purple_debug_error("gg", "ggp_status_got_others: unexpected event %d", ev->type); } } void ggp_status_got_others_buddy(PurpleConnection *gc, uin_t uin, int status, const char *descr) { PurpleAccount *account = purple_connection_get_account(gc); PurpleContactInfo *info = PURPLE_CONTACT_INFO(account); PurpleBuddy *buddy = purple_blist_find_buddy(account, ggp_uin_to_str(uin)); const gchar *purple_status = ggp_status_to_purplestatus(status); gchar *status_message = NULL; gboolean is_own; is_own = (!g_strcmp0(ggp_uin_to_str(uin), purple_contact_info_get_username(info))); if (!buddy) { if (!is_own) { purple_debug_warning("gg", "ggp_status_got_others_buddy: " "buddy %u not found\n", uin); } return; } ggp_buddy_get_data(buddy)->blocked = (status == GG_STATUS_BLOCKED); ggp_buddy_get_data(buddy)->not_a_friend = (status == GG_STATUS_UNKNOWN); if (descr != NULL) { status_message = g_strdup(descr); g_strstrip(status_message); if (status_message[0] == '\0') { g_free(status_message); status_message = NULL; } } if (uin == ggp_str_to_uin(purple_contact_info_get_username(info))) { purple_debug_info("gg", "ggp_status_got_others_buddy: " "own status changed to %s [%s]\n", purple_status, status_message ? status_message : ""); } else if (purple_debug_is_verbose()) { purple_debug_misc("gg", "ggp_status_got_others_buddy: " "status of %u changed to %s [%s]\n", uin, purple_status, status_message ? status_message : ""); } if (status_message) { purple_protocol_got_user_status(account, ggp_uin_to_str(uin), purple_status, "message", status_message, NULL); } else { purple_protocol_got_user_status(account, ggp_uin_to_str(uin), purple_status, NULL); } g_free(status_message); } char * ggp_status_buddy_text(G_GNUC_UNUSED PurpleProtocolClient *client, PurpleBuddy *buddy) { ggp_buddy_data *buddy_data = ggp_buddy_get_data(buddy); const gchar *purple_message; if (buddy_data->blocked) return g_strdup(_("Blocked")); if (buddy_data->not_a_friend) return g_strdup(_("Not a buddy")); purple_message = purple_status_get_attr_string( purple_presence_get_active_status( purple_buddy_get_presence(buddy)), "message"); if (!purple_message) return NULL; return g_markup_escape_text(purple_message, -1); }