Remove the GaduGadu protocol plugin
This protocol plugin depends on libgadu which hasn't been maintained since
2019. That said it is still currently functional as far as I know. However, the
protocol plugin needs a lot of work for the changes in purple 3 and at this
point, it is probably easier to rewrite it even if it still uses libgadu.
Testing Done:
Ran meson dist.
Reviewed at https://reviews.imfreedom.org/r/3051/
--- a/libpurple/protocols/gg/avatar.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,344 +0,0 @@
- * 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
- * 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 "libpurple/glibcompat.h"
-#include "oauth/oauth-purple.h"
-#define GGP_AVATAR_USERAGENT "GG Client build 11.0.0.7562"
-#define GGP_AVATAR_SIZE_MAX 1048576
-/* Buddy avatars updating */
-} ggp_avatar_buddy_update_req;
-#define GGP_AVATAR_BUDDY_URL "http://avatars.gg.pl/%u/s,big"
-/* Own avatar setting */
-struct _ggp_avatar_session_data {
-#define GGP_AVATAR_RESPONSE_MAX 10240
-/*******************************************************************************
- ******************************************************************************/
-static inline ggp_avatar_session_data *
-ggp_avatar_get_avdata(PurpleConnection *gc)
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- return accdata->avatar_data;
-void ggp_avatar_setup(PurpleConnection *gc)
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- info->avatar_data = g_new0(ggp_avatar_session_data, 1);
-void ggp_avatar_cleanup(PurpleConnection *gc)
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- g_free(info->avatar_data);
-/*******************************************************************************
- * Buddy avatars updating.
- ******************************************************************************/
-void ggp_avatar_buddy_remove(PurpleConnection *gc, uin_t uin)
- if (purple_debug_is_verbose()) {
- purple_debug_misc("gg", "ggp_avatar_buddy_remove(%p, %u)\n", gc, uin);
- purple_buddy_icons_set_for_user(purple_connection_get_account(gc),
- ggp_uin_to_str(uin), NULL, 0, NULL);
-ggp_avatar_buddy_update_received(GObject *source, GAsyncResult *result,
- ggp_avatar_buddy_update_req *pending_update = data;
- GBytes *response_body = NULL;
- const char *error_message = NULL;
- PurpleAccount *account;
- PurpleConnection *gc = pending_update->gc;
- gchar timestamp_str[20];
- PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
- if(SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(pending_update->msg))) {
- response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
- error_message = error != NULL ? error->message : "unknown";
- error_message = soup_message_get_reason_phrase(pending_update->msg);
- if(response_body == NULL) {
- purple_debug_error("gg",
- "ggp_avatar_buddy_update_received: bad response "
- "while getting avatar for %u: %s",
- pending_update->uin, error_message);
- g_object_unref(pending_update->msg);
- g_free(pending_update);
- account = purple_connection_get_account(gc);
- buddy = purple_blist_find_buddy(account,
- ggp_uin_to_str(pending_update->uin));
- "gg", "ggp_avatar_buddy_update_received: buddy %u disappeared",
- g_object_unref(pending_update->msg);
- g_free(pending_update);
- g_snprintf(timestamp_str, sizeof(timestamp_str), "%lu",
- pending_update->timestamp);
- got_data = g_bytes_unref_to_data(response_body, &got_len);
- purple_buddy_icons_set_for_user(account, purple_buddy_get_name(buddy),
- got_data, got_len, timestamp_str);
- purple_debug_info("gg",
- "ggp_avatar_buddy_update_received: got avatar for buddy "
- pending_update->uin, pending_update->timestamp);
- g_object_unref(pending_update->msg);
- g_free(pending_update);
-ggp_avatar_buddy_update(PurpleConnection *gc, uin_t uin, time_t timestamp)
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- ggp_avatar_buddy_update_req *pending_update;
- PurpleAccount *account = purple_connection_get_account(gc);
- const char *old_timestamp_str;
- if (purple_debug_is_verbose()) {
- purple_debug_misc("gg", "ggp_avatar_buddy_update(%p, %u, %lu)", gc, uin,
- buddy = purple_blist_find_buddy(account, ggp_uin_to_str(uin));
- PurpleContactInfo *info = PURPLE_CONTACT_INFO(account);
- if (ggp_str_to_uin(purple_contact_info_get_username(info)) == uin) {
- "ggp_avatar_buddy_update(%p): own avatar update requested, "
- "but we don't have ourselves on buddy list",
- purple_debug_warning("gg",
- "ggp_avatar_buddy_update(%p): %u update "
- "requested, but he's not on buddy list",
- old_timestamp_str = purple_buddy_icons_get_checksum_for_user(buddy);
- old_timestamp = old_timestamp_str ? g_ascii_strtoull(
- old_timestamp_str, NULL, 10) : 0;
- if (old_timestamp == timestamp) {
- if (purple_debug_is_verbose()) {
- purple_debug_misc("gg",
- "ggp_avatar_buddy_update(%p): %u have up to date "
- if (old_timestamp > timestamp) {
- purple_debug_warning("gg",
- "ggp_avatar_buddy_update(%p): saved timestamp for "
- "%u is newer than received (%lu > %lu)",
- gc, uin, old_timestamp, timestamp);
- purple_debug_info("gg",
- "ggp_avatar_buddy_update(%p): updating %u with ts=%lu...",
- pending_update = g_new(ggp_avatar_buddy_update_req, 1);
- pending_update->uin = uin;
- pending_update->timestamp = timestamp;
- pending_update->gc = gc;
- url = g_strdup_printf(GGP_AVATAR_BUDDY_URL, pending_update->uin);
- pending_update->msg = req = soup_message_new("GET", url);
- soup_message_headers_replace(soup_message_get_request_headers(req),
- "User-Agent", GGP_AVATAR_USERAGENT);
- // purple_http_request_set_max_len(req, GGP_AVATAR_SIZE_MAX);
- soup_session_send_and_read_async(info->http, req, G_PRIORITY_DEFAULT, NULL,
- ggp_avatar_buddy_update_received,
-/*******************************************************************************
- ******************************************************************************/
- * TODO: use new, GG11 method, when IMToken will be provided by libgadu.
- * POST https://avatars.mpa.gg.pl/avatars/user,<uin>/0
- * Authorization: IMToken 0123456789abcdef0123456789abcdef01234567
- * photo=<avatar content>
-ggp_avatar_own_sent(GObject *source, GAsyncResult *result, gpointer data) {
- SoupMessage *msg = data;
- GBytes *response_body = NULL;
- const char *buffer = NULL;
- if (!SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(msg))) {
- purple_debug_error("gg", "ggp_avatar_own_sent: avatar not sent. %s",
- soup_message_get_reason_phrase(msg));
- response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
- if(response_body == NULL) {
- purple_debug_error("gg", "ggp_avatar_own_sent: avatar not sent. %s",
- buffer = g_bytes_get_data(response_body, &size);
- purple_debug_info("gg", "ggp_avatar_own_sent: %.*s", (int)size, buffer);
- g_bytes_unref(response_body);
-ggp_avatar_own_got_token(PurpleConnection *gc, const gchar *token,
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- ggp_avatar_session_data *avdata = ggp_avatar_get_avdata(gc);
- SoupMessageHeaders *headers;
- PurpleImage *img = _img;
- gchar *img_data, *uin_str;
- PurpleAccount *account = purple_connection_get_account(gc);
- PurpleContactInfo *contact_info = PURPLE_CONTACT_INFO(account);
- uin_t uin = ggp_str_to_uin(purple_contact_info_get_username(contact_info));
- if (img != avdata->own_img) {
- purple_debug_warning("gg", "ggp_avatar_own_got_token: "
- "avatar was changed in meantime\n");
- avdata->own_img = NULL;
- img_data = g_base64_encode(purple_image_get_data(img),
- purple_image_get_data_size(img));
- uin_str = g_strdup_printf("%d", uin);
- purple_debug_misc("gg", "ggp_avatar_own_got_token: "
- "uploading new avatar...\n");
- req = soup_message_new_from_encoded_form(
- "POST", "http://avatars.nowe.gg/upload",
- soup_form_encode("uin", uin_str, "photo", img_data, NULL));
- // purple_http_request_set_max_len(req, GGP_AVATAR_RESPONSE_MAX);
- headers = soup_message_get_request_headers(req);
- soup_message_headers_replace(headers, "Authorization", token);
- soup_message_headers_replace(headers, "From", "avatars to avatars");
- soup_session_send_and_read_async(info->http, req, G_PRIORITY_DEFAULT, NULL,
- ggp_avatar_own_sent, req);
-ggp_avatar_own_set(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
- PurpleConnection *gc, PurpleImage *img)
- ggp_avatar_session_data *avdata;
- PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
- purple_debug_info("gg", "ggp_avatar_own_set(%p, %p)", gc, img);
- avdata = ggp_avatar_get_avdata(gc);
- purple_debug_warning("gg", "ggp_avatar_own_set: avatar removing is "
- "probably not possible within old protocol");
- ggp_oauth_request(gc, ggp_avatar_own_got_token, img, NULL, NULL);
--- a/libpurple/protocols/gg/avatar.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
- * 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
- * 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
-#ifndef PURPLE_GG_AVATAR_H
-#define PURPLE_GG_AVATAR_H
-typedef struct _ggp_avatar_session_data ggp_avatar_session_data;
-void ggp_avatar_setup(PurpleConnection *gc);
-void ggp_avatar_cleanup(PurpleConnection *gc);
-void ggp_avatar_buddy_update(PurpleConnection *gc, uin_t uin, time_t timestamp);
-void ggp_avatar_buddy_remove(PurpleConnection *gc, uin_t uin);
-void ggp_avatar_own_set(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleImage *img);
-#endif /* PURPLE_GG_AVATAR_H */
--- a/libpurple/protocols/gg/blist.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,201 +0,0 @@
- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
- * 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
-/* void ggp_buddylist_send(PurpleConnection *gc) {{{ */
-/* this is for for notify purposes, not synchronizing buddy list */
-void ggp_buddylist_send(PurpleConnection *gc)
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- PurpleAccount *account = purple_connection_get_account(gc);
- buddies = purple_blist_find_buddies(account, NULL);
- size = g_slist_length(buddies);
- userlist = g_new(uin_t, size);
- types = g_new(gchar, size);
- for (buddies = purple_blist_find_buddies(account, NULL); buddies;
- buddies = g_slist_delete_link(buddies, buddies), ++i)
- PurpleBuddy *buddy = buddies->data;
- const gchar *name = purple_buddy_get_name(buddy);
- userlist[i] = ggp_str_to_uin(name);
- types[i] = GG_USER_NORMAL;
- purple_debug_info("gg", "ggp_buddylist_send: adding %d\n",
- ret = gg_notify_ex(info->session, userlist, types, size);
- purple_debug_info("gg", "send: ret=%d; size=%d\n", ret, size);
-/* void ggp_buddylist_load(PurpleConnection *gc, char *buddylist) {{{ */
-void ggp_buddylist_load(PurpleConnection *gc, char *buddylist)
- char *utf8buddylist = ggp_convert_from_cp1250(buddylist);
- /* Don't limit the number of records in a buddylist. */
- users_tbl = g_strsplit(utf8buddylist, "\r\n", -1);
- for (i = 0; users_tbl[i] != NULL; i++) {
- gchar *name, *show, *g;
- data_tbl = g_strsplit(users_tbl[i], ";", 8);
- if (g_strv_length(data_tbl) < 8) {
- purple_debug_warning("gg",
- "Something is wrong on line %d of the buddylist. Skipping.\n",
- show = data_tbl[F_NICKNAME];
- name = data_tbl[F_UIN];
- if ('\0' == *name || !atol(name)) {
- purple_debug_warning("gg",
- "Identifier on line %d of the buddylist is not a number. Skipping.\n",
- purple_debug_info("gg", "got buddy: name=%s; show=%s\n", name, show);
- if (purple_blist_find_buddy(purple_connection_get_account(gc), name)) {
- g = g_strdup("Gadu-Gadu");
- if ('\0' != *(data_tbl[F_GROUP])) {
- /* XXX: Probably buddy should be added to all the groups. */
- /* Hard limit to at most 50 groups */
- gchar **group_tbl = g_strsplit(data_tbl[F_GROUP], ",", 50);
- if (g_strv_length(group_tbl) > 0) {
- g = g_strdup(group_tbl[0]);
- buddy = purple_buddy_new(purple_connection_get_account(gc),
- name, *show == '\0' ? NULL : show);
- if (!(group = purple_blist_find_group(g))) {
- group = purple_group_new(g);
- purple_blist_add_group(group, NULL);
- purple_blist_add_buddy(buddy, NULL, group, NULL);
- ggp_buddylist_send(gc);
-/* char *ggp_buddylist_dump(PurpleAccount *account) {{{ */
-char *ggp_buddylist_dump(PurpleAccount *account)
- GString *buddylist = g_string_sized_new(1024);
- for (buddies = purple_blist_find_buddies(account, NULL); buddies;
- buddies = g_slist_delete_link(buddies, buddies))
- PurpleBuddy *buddy = buddies->data;
- PurpleGroup *group = purple_buddy_get_group(buddy);
- const char *bname = purple_buddy_get_name(buddy);
- const char *gname = purple_group_get_name(group);
- const char *alias = purple_buddy_get_alias(buddy);
- g_string_append_printf(buddylist,
- "%s;%s;%s;%s;%s;%s;%s;%s%s\r\n",
- alias, alias, alias, alias,
- "", gname, bname, "", "");
- ptr = ggp_convert_to_cp1250(buddylist->str);
- g_string_free(buddylist, TRUE);
-const char * ggp_buddylist_get_buddy_name(PurpleConnection *gc, uin_t uin)
- const char *uin_s = ggp_uin_to_str(uin);
- PurpleBuddy *buddy = purple_blist_find_buddy(
- purple_connection_get_account(gc), uin_s);
- return purple_buddy_get_alias(buddy);
-/* vim: set ts=8 sts=0 sw=8 noet: */
--- a/libpurple/protocols/gg/blist.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
- * 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
-#ifndef PURPLE_GG_BLIST_H
-#define PURPLE_GG_BLIST_H
-ggp_buddylist_send(PurpleConnection *gc);
- * Load buddylist from server into the roster.
- * @param gc PurpleConnection
- * @param buddylist Pointer to the buddylist that will be loaded.
-/* void ggp_buddylist_load(PurpleConnection *gc, char *buddylist) {{{ */
-ggp_buddylist_load(PurpleConnection *gc, char *buddylist);
- * Get all the buddies in the current account.
- * @param account Current account.
- * @return List of buddies.
-ggp_buddylist_dump(PurpleAccount *account);
- * Returns the best name of a buddy from the buddylist.
- * @param gc PurpleConnection instance.
- * @param uin UIN of the buddy.
- * @return Name of the buddy, or UIN converted to string, if there is no such
-const char * ggp_buddylist_get_buddy_name(PurpleConnection *gc, uin_t uin);
-#endif /* PURPLE_GG_BLIST_H */
-/* vim: set ts=8 sts=0 sw=8 noet: */
--- a/libpurple/protocols/gg/chat.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,648 +0,0 @@
- * 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
- * Component written by Tomek Wasilczyk (http://www.wasilczyk.pl).
- * This file is dual-licensed under the GPL2+ and the X11 (MIT) licences.
- * As a recipient of this file you may choose, which license to receive the
- * code under. As a contributor, you have to ensure the new code is
- * compatible with both.
- * 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 "message-prpl.h"
-typedef struct _ggp_chat_local_info ggp_chat_local_info;
-struct _ggp_chat_session_data
- ggp_chat_local_info *chats;
- gboolean got_all_chats_info;
-struct _ggp_chat_local_info
- PurpleChatConversation *conv;
- gboolean previously_joined;
- int participants_count;
-static ggp_chat_local_info * ggp_chat_new(PurpleConnection *gc, uint64_t id);
-static ggp_chat_local_info * ggp_chat_get(PurpleConnection *gc, uint64_t id);
-static void ggp_chat_open_conv(ggp_chat_local_info *chat);
-static ggp_chat_local_info * ggp_chat_get_local(PurpleConnection *gc,
-static void ggp_chat_joined(ggp_chat_local_info *chat, uin_t uin);
-static void ggp_chat_left(ggp_chat_local_info *chat, uin_t uin);
-static const gchar * ggp_chat_get_name_from_id(uint64_t id);
-static uint64_t ggp_chat_get_id_from_name(const gchar * name);
-static void ggp_chat_join_id(PurpleConnection *gc, uint64_t id);
-static inline ggp_chat_session_data *
-ggp_chat_get_sdata(PurpleConnection *gc)
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- return accdata->chat_data;
-void ggp_chat_setup(PurpleConnection *gc)
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- ggp_chat_session_data *sdata = g_new0(ggp_chat_session_data, 1);
- accdata->chat_data = sdata;
-void ggp_chat_cleanup(PurpleConnection *gc)
- ggp_chat_session_data *sdata = ggp_chat_get_sdata(gc);
- g_slist_free_full(sdata->pending_joins, g_free);
- for (i = 0; i < sdata->chats_count; i++)
- g_free(sdata->chats[i].participants);
-static ggp_chat_local_info * ggp_chat_new(PurpleConnection *gc, uint64_t id)
- ggp_chat_session_data *sdata = ggp_chat_get_sdata(gc);
- ggp_chat_local_info *chat;
- if (NULL != (chat = ggp_chat_get(gc, id)))
- local_id = sdata->chats_count++;
- sdata->chats = g_realloc(sdata->chats,
- sdata->chats_count * sizeof(ggp_chat_local_info));
- chat = &sdata->chats[local_id];
- chat->local_id = local_id;
- chat->previously_joined = FALSE;
- chat->participants = NULL;
- chat->participants_count = 0;
-static ggp_chat_local_info * ggp_chat_get(PurpleConnection *gc, uint64_t id)
- ggp_chat_session_data *sdata = ggp_chat_get_sdata(gc);
- for (i = 0; i < sdata->chats_count; i++) {
- if (sdata->chats[i].id == id)
- return &sdata->chats[i];
-static void ggp_chat_open_conv(ggp_chat_local_info *chat)
- PurpleConversation *conv;
- if (chat->conv != NULL)
- conv = purple_serv_got_joined_chat(chat->gc, chat->local_id,
- ggp_chat_get_name_from_id(chat->id));
- chat->conv = PURPLE_CHAT_CONVERSATION(conv);
- if (chat->previously_joined) {
- purple_conversation_write_system_message(
- PURPLE_CONVERSATION(chat->conv),
- _("You have re-joined the chat"), 0);
- chat->previously_joined = TRUE;
- purple_chat_conversation_clear_users(chat->conv);
- for (i = 0; i < chat->participants_count; i++) {
- purple_chat_conversation_add_user(chat->conv,
- ggp_uin_to_str(chat->participants[i]), NULL,
- PURPLE_CHAT_USER_NONE, FALSE);
-static ggp_chat_local_info * ggp_chat_get_local(PurpleConnection *gc,
- ggp_chat_session_data *sdata = ggp_chat_get_sdata(gc);
- for (i = 0; i < sdata->chats_count; i++) {
- if (sdata->chats[i].local_id == local_id)
- return &sdata->chats[i];
-void ggp_chat_got_event(PurpleConnection *gc, const struct gg_event *ev)
- ggp_chat_session_data *sdata = ggp_chat_get_sdata(gc);
- ggp_chat_local_info *chat;
- if (ev->type == GG_EVENT_CHAT_INFO) {
- const struct gg_event_chat_info *eci = &ev->event.chat_info;
- chat = ggp_chat_new(gc, eci->id);
- for (i = 0; i < eci->participants_count; i++)
- ggp_chat_joined(chat, eci->participants[i]);
- } else if (ev->type == GG_EVENT_CHAT_INFO_GOT_ALL) {
- GSList *it = sdata->pending_joins;
- sdata->got_all_chats_info = TRUE;
- uint64_t *id_p = it->data;
- ggp_chat_join_id(gc, *id_p);
- g_clear_slist(&sdata->pending_joins, g_free);
- } else if (ev->type == GG_EVENT_CHAT_INFO_UPDATE) {
- const struct gg_event_chat_info_update *eciu =
- &ev->event.chat_info_update;
- chat = ggp_chat_get(gc, eciu->id);
- purple_debug_error("gg", "ggp_chat_got_event: "
- "chat %" G_GUINT64_FORMAT " not found\n",
- if (eciu->type == GG_CHAT_INFO_UPDATE_ENTERED)
- ggp_chat_joined(chat, eciu->participant);
- else if (eciu->type == GG_CHAT_INFO_UPDATE_EXITED)
- ggp_chat_left(chat, eciu->participant);
- purple_debug_warning("gg", "ggp_chat_got_event: "
- "unknown update type - %d", eciu->type);
- } else if (ev->type == GG_EVENT_CHAT_CREATED) {
- PurpleAccount *account = purple_connection_get_account(gc);
- PurpleContactInfo *info = PURPLE_CONTACT_INFO(account);
- const struct gg_event_chat_created *ecc = &ev->event.chat_created;
- uin_t me = ggp_str_to_uin(purple_contact_info_get_username(info));
- chat = ggp_chat_new(gc, ecc->id);
- ggp_chat_joined(chat, me);
- ggp_chat_open_conv(chat);
- } else if (ev->type == GG_EVENT_CHAT_INVITE_ACK) {
- purple_debug_error("gg", "ggp_chat_got_event: unexpected event - %d",
-static int ggp_chat_participant_find(ggp_chat_local_info *chat, uin_t uin)
- for (i = 0; i < chat->participants_count; i++)
- if (chat->participants[i] == uin)
-static void ggp_chat_joined(ggp_chat_local_info *chat, uin_t uin)
- int idx = ggp_chat_participant_find(chat, uin);
- purple_debug_warning("gg", "ggp_chat_joined: "
- "user %u is already present in chat %" G_GUINT64_FORMAT
- chat->participants_count++;
- chat->participants = g_realloc(chat->participants,
- sizeof(uin) * chat->participants_count);
- chat->participants[chat->participants_count - 1] = uin;
- purple_chat_conversation_add_user(chat->conv,
- ggp_uin_to_str(uin), NULL, PURPLE_CHAT_USER_NONE, TRUE);
-static void ggp_chat_left(ggp_chat_local_info *chat, uin_t uin)
- PurpleAccount *account = NULL;
- PurpleContactInfo *info = NULL;
- int idx = ggp_chat_participant_find(chat, uin);
- purple_debug_warning("gg", "ggp_chat_joined: "
- "user %u isn't present in chat %" G_GUINT64_FORMAT "\n",
- chat->participants[idx] =
- chat->participants[chat->participants_count - 1];
- chat->participants_count--;
- chat->participants = g_realloc(chat->participants,
- sizeof(uin) * chat->participants_count);
- if (chat->conv == NULL)
- account = purple_connection_get_account(chat->gc);
- info = PURPLE_CONTACT_INFO(account);
- me = ggp_str_to_uin(purple_contact_info_get_username(info));
- purple_conversation_write_system_message(
- PURPLE_CONVERSATION(chat->conv),
- _("You have left the chat"), 0);
- purple_serv_got_chat_left(chat->gc, chat->local_id);
- purple_chat_conversation_remove_user(chat->conv, ggp_uin_to_str(uin), NULL);
-ggp_chat_info(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
- G_GNUC_UNUSED PurpleConnection *gc)
- PurpleProtocolChatEntry *pce;
- pce = g_new0(PurpleProtocolChatEntry, 1);
- pce->label = _("_Conference identifier");
- pce->identifier = "id";
- m = g_list_append(m, pce);
-ggp_chat_info_defaults(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
- G_GNUC_UNUSED PurpleConnection *gc,
- const gchar *chat_name)
- defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
- if (chat_name != NULL && ggp_chat_get_id_from_name(chat_name) != 0)
- g_hash_table_insert(defaults, "id", g_strdup(chat_name));
-ggp_chat_get_name(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
- GHashTable *components)
- return g_strdup((gchar*)g_hash_table_lookup(components, "id"));
-static const gchar * ggp_chat_get_name_from_id(uint64_t id)
- g_snprintf(buff, sizeof(buff), "%" G_GUINT64_FORMAT, id);
-static uint64_t ggp_chat_get_id_from_name(const gchar * name)
- id = g_ascii_strtoull(name, &endptr, 10);
- if (*endptr != '\0' || id == G_MAXUINT64)
-ggp_chat_join(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
- PurpleConnection *gc, GHashTable *components)
- ggp_chat_session_data *sdata = ggp_chat_get_sdata(gc);
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- id_cs = g_hash_table_lookup(components, "id");
- id_s = g_strdup(id_cs);
- if (id_s == NULL || id_s[0] == '\0') {
- if (gg_chat_create(info->session) < 0) {
- purple_debug_error("gg", "ggp_chat_join; "
- purple_serv_got_join_chat_failed(gc, components);
- id = ggp_chat_get_id_from_name(id_s);
- char *buff = g_strdup_printf(
- _("%s is not a valid room identifier"), id_cs);
- purple_notify_error(gc, _("Invalid Room Identifier"),
- _("Invalid Room Identifier"), buff, NULL);
- purple_serv_got_join_chat_failed(gc, components);
- if (sdata->got_all_chats_info)
- ggp_chat_join_id(gc, id);
- uint64_t *id_p = g_new(uint64_t, 1);
- sdata->pending_joins = g_slist_append(sdata->pending_joins, id_p);
-static void ggp_chat_join_id(PurpleConnection *gc, uint64_t id)
- GHashTable *components;
- PurpleProtocol *protocol = purple_connection_get_protocol(gc);
- ggp_chat_local_info *chat = ggp_chat_get(gc, id);
- if (chat && !chat->left) {
- ggp_chat_open_conv(chat);
- char *id_s = g_strdup_printf("%" G_GUINT64_FORMAT, id);
- char *buff = g_strdup_printf(
- _("%s is not a valid room identifier"), id_s);
- purple_notify_error(gc, _("Invalid Room Identifier"),
- _("Invalid Room Identifier"), buff, NULL);
- } else { /* if (chat->left) */
- purple_notify_error(gc, _("Could not join chat room"),
- _("Could not join chat room"),
- _("You have to ask for invitation from another chat "
- components = ggp_chat_info_defaults(PURPLE_PROTOCOL_CHAT(protocol), gc,
- ggp_chat_get_name_from_id(id));
- purple_serv_got_join_chat_failed(gc, components);
- g_hash_table_destroy(components);
-ggp_chat_leave(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
- PurpleConnection *gc, gint local_id)
- PurpleAccount *account = NULL;
- PurpleContactInfo *contact_info = NULL;
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- ggp_chat_local_info *chat;
- chat = ggp_chat_get_local(gc, local_id);
- purple_debug_error("gg", "ggp_chat_leave: "
- "chat %u doesn't exists\n", local_id);
- if (gg_chat_leave(info->session, chat->id) < 0) {
- purple_debug_error("gg", "ggp_chat_leave: "
- "unable to leave chat %" G_GUINT64_FORMAT "\n",
- account = purple_connection_get_account(chat->gc);
- contact_info = PURPLE_CONTACT_INFO(account);
- me = ggp_str_to_uin(purple_contact_info_get_username(contact_info));
- ggp_chat_left(chat, me);
-ggp_chat_invite(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
- PurpleConnection *gc, gint local_id,
- G_GNUC_UNUSED const gchar *message, const gchar *who)
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- ggp_chat_local_info *chat;
- chat = ggp_chat_get_local(gc, local_id);
- purple_debug_error("gg", "ggp_chat_invite: "
- "chat %u doesn't exists\n", local_id);
- invited = ggp_str_to_uin(who);
- if (gg_chat_invite(info->session, chat->id, &invited, 1) < 0) {
- purple_debug_error("gg", "ggp_chat_invite: "
- "unable to invite %s to chat %" G_GUINT64_FORMAT "\n",
-ggp_chat_send(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
- PurpleConnection *gc, gint local_id,
- G_GNUC_UNUSED PurpleConversation *conversation,
- PurpleAccount *account = NULL;
- PurpleContactInfo *contact_info = NULL;
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- PurpleConversation *conv;
- PurpleConversationManager *manager;
- ggp_chat_local_info *chat;
- chat = ggp_chat_get_local(gc, local_id);
- purple_debug_error("gg", "ggp_chat_send: "
- "chat %u doesn't exists\n", local_id);
- manager = purple_conversation_manager_get_default();
- conv = purple_conversation_manager_find_chat(manager,
- purple_connection_get_account(gc),
- ggp_chat_get_name_from_id(chat->id));
- gg_msg = ggp_message_format_to_gg(conv,
- purple_message_get_contents(msg));
- if (gg_chat_send_message(info->session, chat->id, gg_msg, TRUE) < 0)
- account = purple_connection_get_account(gc);
- contact_info = PURPLE_CONTACT_INFO(account);
- me = purple_contact_info_get_username(contact_info);
- dt = purple_message_get_timestamp(msg);
- purple_serv_got_chat_in(gc, chat->local_id, me,
- purple_message_get_flags(msg),
- purple_message_get_contents(msg),
- (time_t)g_date_time_to_unix(dt));
-void ggp_chat_got_message(PurpleConnection *gc, uint64_t chat_id,
- const char *message, time_t time, uin_t who)
- PurpleAccount *account = NULL;
- PurpleContactInfo *info = NULL;
- ggp_chat_local_info *chat;
- account = purple_connection_get_account(gc);
- info = PURPLE_CONTACT_INFO(account);
- me = ggp_str_to_uin(purple_contact_info_get_username(info));
- chat = ggp_chat_get(gc, chat_id);
- purple_debug_error("gg", "ggp_chat_got_message: "
- "chat %" G_GUINT64_FORMAT " doesn't exists\n", chat_id);
- ggp_chat_open_conv(chat);
- const char *username = NULL;
- username = purple_contact_info_get_name_for_display(info);
- pmsg = purple_message_new_outgoing(username, ggp_uin_to_str(who),
- dt = g_date_time_new_from_unix_local((gint64)time);
- purple_message_set_timestamp(pmsg, dt);
- purple_conversation_write_message(
- PURPLE_CONVERSATION(chat->conv), pmsg);
- purple_serv_got_chat_in(gc, chat->local_id, ggp_uin_to_str(who),
- PURPLE_MESSAGE_RECV, message, time);
-static gboolean ggp_chat_roomlist_get_list_finish(gpointer roomlist)
- purple_roomlist_set_in_progress(PURPLE_ROOMLIST(roomlist), FALSE);
- g_object_unref(roomlist);
-ggp_chat_roomlist_get_list(G_GNUC_UNUSED PurpleProtocolRoomlist *protocol_roomlist,
- ggp_chat_session_data *sdata = ggp_chat_get_sdata(gc);
- PurpleRoomlist *roomlist;
- purple_debug_info("gg", "ggp_chat_roomlist_get_list\n");
- roomlist = purple_roomlist_new(purple_connection_get_account(gc));
- for (i = sdata->chats_count - 1; i >= 0 ; i--) {
- PurpleRoomlistRoom *room;
- ggp_chat_local_info *chat = &sdata->chats[i];
- GDateTime *date = NULL;
- int count = chat->participants_count;
- date = g_date_time_new_from_unix_local((uint32_t)(chat->id >> 32));
- } else if (chat->left) {
- /* Translators: For Gadu-Gadu, this is one possible status for a
- chat room. It means you had previously joined the chat room but
- you have since left it. You cannot rejoin without another
- status = _("Chat left");
- status = _("Can join chat");
- name = ggp_chat_get_name_from_id(chat->id);
- room = purple_roomlist_room_new(name, NULL);
- purple_roomlist_room_set_user_count(room, (guint)count);
- purple_roomlist_room_add_field(room, "id", g_strdup(name));
- purple_roomlist_room_add_field(room, "date",
- g_date_time_format(date, "%c"));
- purple_roomlist_room_add_field(room, "status", g_strdup(status));
- purple_roomlist_room_add(roomlist, room);
- g_date_time_unref(date);
- * purple_roomlist_set_in_progress(roomlist, FALSE);
- g_object_ref(roomlist);
- g_timeout_add(1, ggp_chat_roomlist_get_list_finish, roomlist);
--- a/libpurple/protocols/gg/chat.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
- * 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
- * Component written by Tomek Wasilczyk (http://www.wasilczyk.pl).
- * This file is dual-licensed under the GPL2+ and the X11 (MIT) licences.
- * As a recipient of this file you may choose, which license to receive the
- * code under. As a contributor, you have to ensure the new code is
- * compatible with both.
- * 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
-#ifndef PURPLE_GG_CHAT_H
-#define PURPLE_GG_CHAT_H
-typedef struct _ggp_chat_session_data ggp_chat_session_data;
-void ggp_chat_setup(PurpleConnection *gc);
-void ggp_chat_cleanup(PurpleConnection *gc);
-void ggp_chat_got_event(PurpleConnection *gc, const struct gg_event *ev);
-GList * ggp_chat_info(PurpleProtocolChat *protocol_chat, PurpleConnection *gc);
-GHashTable * ggp_chat_info_defaults(PurpleProtocolChat *protocol_chat, PurpleConnection *gc,
- const char *chat_name);
-char * ggp_chat_get_name(PurpleProtocolChat *protocol_chat, GHashTable *components);
-void ggp_chat_join(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, GHashTable *components);
-void ggp_chat_leave(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int local_id);
-void ggp_chat_invite(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int local_id, const char *message,
-int ggp_chat_send(PurpleProtocolChat *protocol_chat, PurpleConnection *gc, int local_id, PurpleConversation *conversation, PurpleMessage *msg);
-void ggp_chat_got_message(PurpleConnection *gc, uint64_t chat_id,
- const char *message, time_t time, uin_t who);
-PurpleRoomlist * ggp_chat_roomlist_get_list(PurpleProtocolRoomlist *protocol_roomlist, PurpleConnection *gc);
-#endif /* PURPLE_GG_CHAT_H */
--- a/libpurple/protocols/gg/edisc.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1344 +0,0 @@
- * 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
- * Component written by Tomek Wasilczyk (http://www.wasilczyk.pl).
- * This file is dual-licensed under the GPL2+ and the X11 (MIT) licences.
- * As a recipient of this file you may choose, which license to receive the
- * code under. As a contributor, you have to ensure the new code is
- * compatible with both.
- * 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 <json-glib/json-glib.h>
-#include <glib/gi18n-lib.h>
-#define GGP_EDISC_OS "WINNT x86-msvc"
-#define GGP_EDISC_TYPE "desktop"
-#define GGP_EDISC_API "6"
-#define GGP_EDISC_RESPONSE_MAX 10240
-#define GGP_EDISC_FNAME_ALLOWED "1234567890" \
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" \
-typedef struct _ggp_edisc_xfer ggp_edisc_xfer;
-struct _ggp_edisc_session_data
- GHashTable *xfers_initialized;
- GHashTable *xfers_history;
- SoupMessage *auth_request;
- GCancellable *cancellable;
- gboolean allowed, ready;
- GGP_EDISC_XFER_ACK_STATUS_UNKNOWN,
- GGP_EDISC_XFER_ACK_STATUS_ALLOWED,
- GGP_EDISC_XFER_ACK_STATUS_REJECTED
-} ggp_edisc_xfer_ack_status;
-typedef void (*ggp_ggdrive_auth_cb)(PurpleConnection *gc, gboolean success,
-/*******************************************************************************
- ******************************************************************************/
-static inline ggp_edisc_session_data *
-ggp_edisc_get_sdata(PurpleConnection *gc)
- PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
- accdata = purple_connection_get_protocol_data(gc);
- g_return_val_if_fail(accdata != NULL, NULL);
- return accdata->edisc_data;
-ggp_edisc_setup(PurpleConnection *gc, GProxyResolver *resolver)
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- ggp_edisc_session_data *sdata = g_new0(ggp_edisc_session_data, 1);
- accdata->edisc_data = sdata;
- sdata->session = soup_session_new_with_options("proxy-resolver", resolver,
- soup_session_add_feature_by_type(sdata->session, SOUP_TYPE_COOKIE_JAR);
- sdata->xfers_initialized = g_hash_table_new(g_str_hash, g_str_equal);
- sdata->xfers_history = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-void ggp_edisc_cleanup(PurpleConnection *gc)
- ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
- g_return_if_fail(sdata != NULL);
- soup_session_abort(sdata->session);
- g_slist_free_full(sdata->auth_pending, g_free);
- g_free(sdata->security_token);
- g_object_unref(sdata->session);
- g_hash_table_destroy(sdata->xfers_initialized);
- g_hash_table_destroy(sdata->xfers_history);
-/*******************************************************************************
- ******************************************************************************/
-ggp_edisc_set_defaults(SoupMessage *msg)
- SoupMessageHeaders *headers = soup_message_get_request_headers(msg);
- // purple_http_request_set_max_len(msg, GGP_EDISC_RESPONSE_MAX);
- soup_message_headers_replace(headers, "X-gged-api-version",
- soup_message_headers_replace(
- "Mozilla/5.0 (Windows NT 6.1; rv:11.0) Gecko/20120613 "
- "GG/11.0.0.8169 (WINNT_x86-msvc; pl; beta; standard)");
- soup_message_headers_replace(
- "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
- soup_message_headers_replace(headers, "Accept-Language",
- "pl,en-us;q=0.7,en;q=0.3");
- /* soup_message_headers_replace(headers, "Accept-Encoding",
- soup_message_headers_replace(headers, "Accept-Charset",
- "ISO-8859-2,utf-8;q=0.7,*;q=0.7");
- soup_message_headers_replace(headers, "Connection", "keep-alive");
- soup_message_headers_replace(
- headers, "Content-Type",
- "application/x-www-form-urlencoded; charset=UTF-8");
-static int ggp_edisc_parse_error(const gchar *data)
- parser = ggp_json_parse(data);
- result = json_node_get_object(json_parser_get_root(parser));
- result = json_object_get_object_member(result, "result");
- error_id = json_object_get_int_member(result, "appStatus");
- purple_debug_info("gg", "edisc error: %s (%d)\n",
- json_object_get_string_member(result, "errorMsg"),
- g_object_unref(parser);
-static ggp_edisc_xfer_ack_status
-ggp_edisc_xfer_parse_ack_status(const gchar *str)
- g_return_val_if_fail(str != NULL, GGP_EDISC_XFER_ACK_STATUS_UNKNOWN);
- if (g_strcmp0("unknown", str) == 0) {
- return GGP_EDISC_XFER_ACK_STATUS_UNKNOWN;
- if (g_strcmp0("allowed", str) == 0) {
- return GGP_EDISC_XFER_ACK_STATUS_ALLOWED;
- if (g_strcmp0("rejected", str) == 0) {
- return GGP_EDISC_XFER_ACK_STATUS_REJECTED;
- "gg", "ggp_edisc_xfer_parse_ack_status: unknown status (%s)", str);
- return GGP_EDISC_XFER_ACK_STATUS_UNKNOWN;
-/*******************************************************************************
- * General xfer functions.
- ******************************************************************************/
-ggp_edisc_xfer_ticket_url(const gchar *ticket_id)
- static gchar ticket_url[150];
- g_snprintf(ticket_url, sizeof(ticket_url),
- "https://drive.mpa.gg.pl/send_ticket/%s", ticket_id);
-static void ggp_edisc_xfer_error(PurpleXfer *xfer, const gchar *msg)
- if (purple_xfer_is_cancelled(xfer))
- purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE);
- purple_xfer_conversation_write(xfer, msg, TRUE);
- purple_xfer_get_xfer_type(xfer),
- purple_xfer_get_account(xfer),
- purple_xfer_get_remote_user(xfer),
-/*******************************************************************************
- ******************************************************************************/
-typedef struct _ggp_edisc_auth_data {
- ggp_ggdrive_auth_cb cb;
-ggp_ggdrive_auth_results(PurpleConnection *gc, gboolean success)
- ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
- purple_debug_info("gg", "ggp_ggdrive_auth_results(gc=%p): %d", gc, success);
- g_return_if_fail(sdata != NULL);
- for (it = sdata->auth_pending; it; it = g_slist_delete_link(it, it)) {
- ggp_edisc_auth_data *auth = it->data;
- auth->cb(gc, success, auth->user_data);
- sdata->auth_pending = NULL;
- sdata->auth_done = TRUE;
-ggp_ggdrive_auth_done(GObject *source, GAsyncResult *async_result,
- PurpleConnection *gc = data;
- ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
- GBytes *response_body = NULL;
- const char *buffer = NULL;
- SoupStatus status_code;
- g_return_if_fail(sdata != NULL);
- status_code = soup_message_get_status(sdata->auth_request);
- if (!SOUP_STATUS_IS_SUCCESSFUL(status_code)) {
- purple_debug_misc("gg",
- "ggp_ggdrive_auth_done: authentication failed due to "
- "unsuccessful request (code = %d)",
- g_clear_object(&sdata->auth_request);
- ggp_ggdrive_auth_results(gc, FALSE);
- response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
- if(response_body == NULL) {
- purple_debug_misc("gg",
- "ggp_ggdrive_auth_done: authentication failed due to "
- "unsuccessful request (%s)",
- g_clear_object(&sdata->auth_request);
- ggp_ggdrive_auth_results(gc, FALSE);
- buffer = g_bytes_get_data(response_body, &size);
- parser = ggp_json_parse(buffer);
- result = json_node_get_object(json_parser_get_root(parser));
- result = json_object_get_object_member(result, "result");
- if (json_object_has_member(result, "status"))
- status = json_object_get_int_member(result, "status");
- g_object_unref(parser);
- purple_debug_misc("gg",
- "ggp_ggdrive_auth_done: authentication failed due to "
- "bad result (status=%d)",
- if (purple_debug_is_verbose()) {
- purple_debug_misc("gg", "ggp_ggdrive_auth_done: result = %.*s",
- g_bytes_unref(response_body);
- g_clear_object(&sdata->auth_request);
- ggp_ggdrive_auth_results(gc, FALSE);
- sdata->security_token = g_strdup(soup_message_headers_get_one(
- soup_message_get_response_headers(sdata->auth_request),
- "X-gged-security-token"));
- if (!sdata->security_token) {
- purple_debug_misc("gg", "ggp_ggdrive_auth_done: authentication failed "
- "due to missing security token header");
- g_bytes_unref(response_body);
- g_clear_object(&sdata->auth_request);
- ggp_ggdrive_auth_results(gc, FALSE);
- if (purple_debug_is_unsafe()) {
- purple_debug_misc("gg", "ggp_ggdrive_auth_done: security_token=%s",
- sdata->security_token);
- g_clear_pointer(&response_body, g_bytes_unref);
- g_clear_object(&sdata->auth_request);
- ggp_ggdrive_auth_results(gc, TRUE);
-ggp_ggdrive_auth(PurpleConnection *gc, ggp_ggdrive_auth_cb cb,
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
- ggp_edisc_auth_data *auth;
- SoupMessageHeaders *headers;
- g_return_if_fail(sdata != NULL);
- imtoken = ggp_get_imtoken(gc);
- cb(gc, FALSE, user_data);
- if (sdata->auth_done) {
- cb(gc, sdata->security_token != NULL, user_data);
- auth = g_new0(ggp_edisc_auth_data, 1);
- auth->user_data = user_data;
- sdata->auth_pending = g_slist_prepend(sdata->auth_pending, auth);
- if (sdata->auth_request) {
- purple_debug_info("gg", "ggp_ggdrive_auth(gc=%p)", gc);
- msg = soup_message_new("PUT", "https://drive.mpa.gg.pl/signin");
- ggp_edisc_set_defaults(msg);
- headers = soup_message_get_request_headers(msg);
- metadata = g_strdup_printf("{"
- "\"os_version\": \"" GGP_EDISC_OS "\", "
- "\"client_version\": \"%s\", "
- "\"type\": \"" GGP_EDISC_TYPE "\"}",
- g_random_int_range(1, 1 << 16),
- g_get_host_name(), ggp_libgaduw_version(gc));
- tmp = g_strdup_printf("IMToken %s", imtoken);
- soup_message_headers_replace(headers, "Authorization", tmp);
- tmp = g_strdup_printf("gg/pl:%u", accdata->session->uin);
- soup_message_headers_replace(headers, "X-gged-user", tmp);
- soup_message_headers_replace(headers, "X-gged-client-metadata", metadata);
- sdata->auth_request = msg;
- soup_session_send_and_read_async(sdata->session, msg, G_PRIORITY_DEFAULT,
- NULL, ggp_ggdrive_auth_done, gc);
-ggp_edisc_xfer_send_ticket_changed(G_GNUC_UNUSED PurpleConnection *gc,
- PurpleXfer *xfer, gboolean is_allowed)
- GGPXfer *edisc_xfer = GGP_XFER(xfer);
- "ggp_edisc_event_ticket_changed: transfer %p already free'd",
- "gg", "ggp_edisc_event_ticket_changed: transfer %p rejected",
- purple_xfer_cancel_remote(xfer);
- if (edisc_xfer->allowed) {
- "ggp_edisc_event_ticket_changed: transfer %p already allowed",
- edisc_xfer->allowed = TRUE;
- purple_xfer_start(xfer, -1, NULL, 0);
-/*******************************************************************************
- ******************************************************************************/
-ggp_edisc_xfer_can_receive_file(G_GNUC_UNUSED PurpleProtocolXfer *prplxfer,
- PurpleConnection *gc, const char *who)
- g_return_val_if_fail(gc != NULL, FALSE);
- g_return_val_if_fail(who != NULL, FALSE);
- buddy = purple_blist_find_buddy(purple_connection_get_account(gc), who);
- /* TODO: check, if this buddy have us on his list */
- return PURPLE_BUDDY_IS_ONLINE(buddy);
-ggp_edisc_xfer_send_init_ticket_created(GObject *source, GAsyncResult *result,
- PurpleXfer *xfer = data;
- GGPXfer *edisc_xfer = GGP_XFER(xfer);
- ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(edisc_xfer->gc);
- GBytes *response_body = NULL;
- const char *buffer = NULL;
- ggp_edisc_xfer_ack_status ack_status;
- if (purple_xfer_is_cancelled(xfer))
- g_return_if_fail(sdata != NULL);
- response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
- if(response_body == NULL) {
- purple_debug_error("gg",
- "ggp_edisc_xfer_send_init_ticket_created: failed "
- "to send file: %s", error->message);
- g_clear_object(&edisc_xfer->msg);
- ggp_edisc_xfer_error(xfer, _("Unable to send file"));
- buffer = g_bytes_get_data(response_body, &size);
- if(!SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(edisc_xfer->msg))) {
- int error_id = ggp_edisc_parse_error(buffer);
- g_bytes_unref(response_body);
- g_clear_object(&edisc_xfer->msg);
- /* recipient not logged in */
- ggp_edisc_xfer_error(xfer, _("Recipient not logged in"));
- } else if(error_id == 207) {
- /* bad sender recipient relation */
- ggp_edisc_xfer_error(xfer,
- _("You aren't on the recipient's buddy list"));
- ggp_edisc_xfer_error(xfer, _("Unable to send file"));
- parser = ggp_json_parse(buffer);
- ticket = json_node_get_object(json_parser_get_root(parser));
- ticket = json_object_get_object_member(ticket, "result");
- ticket = json_object_get_object_member(ticket, "send_ticket");
- edisc_xfer->ticket_id = g_strdup(json_object_get_string_member(
- ack_status = ggp_edisc_xfer_parse_ack_status(
- json_object_get_string_member(ticket, "ack_status"));
- /* send_mode: "normal", "publink" (for legacy clients) */
- g_object_unref(parser);
- g_bytes_unref(response_body);
- g_clear_object(&edisc_xfer->msg);
- if (edisc_xfer->ticket_id == NULL) {
- purple_debug_error("gg",
- "ggp_edisc_xfer_send_init_ticket_created: "
- "couldn't get ticket id\n");
- purple_debug_info("gg", "ggp_edisc_xfer_send_init_ticket_created: "
- "ticket \"%s\" created\n", edisc_xfer->ticket_id);
- g_hash_table_insert(sdata->xfers_initialized, edisc_xfer->ticket_id, xfer);
- g_hash_table_add(sdata->xfers_history, g_strdup(edisc_xfer->ticket_id));
- if (ack_status != GGP_EDISC_XFER_ACK_STATUS_UNKNOWN)
- ggp_edisc_xfer_send_ticket_changed(edisc_xfer->gc, xfer,
- ack_status == GGP_EDISC_XFER_ACK_STATUS_ALLOWED);
-ggp_edisc_xfer_send_init_authenticated(PurpleConnection *gc, gboolean success,
- ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
- PurpleXfer *xfer = _xfer;
- GGPXfer *edisc_xfer = GGP_XFER(xfer);
- if (purple_xfer_is_cancelled(xfer)) {
- ggp_edisc_xfer_error(xfer, _("Authentication failed"));
- g_return_if_fail(sdata != NULL);
- msg = soup_message_new("PUT", "https://drive.mpa.gg.pl/send_ticket");
- ggp_edisc_set_defaults(msg);
- soup_message_headers_replace(soup_message_get_request_headers(msg),
- "X-gged-security-token",
- sdata->security_token);
- data = g_strdup_printf("{\"send_ticket\":{"
- "\"recipient\":\"%s\","
- "\"file_name\":\"%s\","
- purple_xfer_get_remote_user(xfer),
- (int)purple_xfer_get_size(xfer));
- body = g_bytes_new_take(data, strlen(data));
- soup_message_set_request_body_from_bytes(msg,
- "application/x-www-form-urlencoded; charset=UTF-8",
- soup_session_send_and_read_async(sdata->session, msg, G_PRIORITY_DEFAULT,
- edisc_xfer->cancellable,
- ggp_edisc_xfer_send_init_ticket_created,
-ggp_edisc_xfer_send_init(PurpleXfer *xfer)
- GGPXfer *edisc_xfer = GGP_XFER(xfer);
- purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_NOT_STARTED);
- edisc_xfer->filename = g_strdup(purple_xfer_get_filename(xfer));
- g_strcanon(edisc_xfer->filename, GGP_EDISC_FNAME_ALLOWED, '_');
- ggp_ggdrive_auth(edisc_xfer->gc, ggp_edisc_xfer_send_init_authenticated,
-ggp_edisc_xfer_send_done(GObject *source, GAsyncResult *async_result,
- PurpleXfer *xfer = data;
- GGPXfer *edisc_xfer = GGP_XFER(xfer);
- GBytes *response_body = NULL;
- JsonParser *parser = NULL;
- JsonObject *result = NULL;
- int result_status = -1;
- if(purple_xfer_is_cancelled(xfer)) {
- g_return_if_fail(edisc_xfer != NULL);
- if(!SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(edisc_xfer->msg))) {
- g_clear_object(&edisc_xfer->msg);
- ggp_edisc_xfer_error(xfer, _("Error while sending a file"));
- response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
- if(response_body == NULL) {
- g_clear_object(&edisc_xfer->msg);
- ggp_edisc_xfer_error(xfer, _("Error while sending a file"));
- parser = ggp_json_parse(g_bytes_get_data(response_body, NULL));
- result = json_node_get_object(json_parser_get_root(parser));
- result = json_object_get_object_member(result, "result");
- if(json_object_has_member(result, "status")) {
- result_status = json_object_get_int_member(result, "status");
- g_object_unref(parser);
- g_clear_pointer(&response_body, g_bytes_unref);
- g_clear_object(&edisc_xfer->msg);
- if(result_status == 0) {
- purple_xfer_set_completed(xfer, TRUE);
- ggp_edisc_xfer_error(xfer, _("Error while sending a file"));
-ggp_edisc_xfer_send_start_msg_cb(SoupMessage *msg, gpointer data) {
- PurpleXfer *xfer = data;
- GInputStream *stream = NULL;
- /* TODO: Actually fill in stream with something. */
- soup_message_set_request_body(msg, NULL, stream,
- purple_xfer_get_size(xfer));
-static void ggp_edisc_xfer_send_start(PurpleXfer *xfer)
- ggp_edisc_session_data *sdata;
- gchar *upload_url, *filename_e;
- SoupMessageHeaders *headers;
- g_return_if_fail(xfer != NULL);
- edisc_xfer = GGP_XFER(xfer);
- g_return_if_fail(edisc_xfer != NULL);
- sdata = ggp_edisc_get_sdata(edisc_xfer->gc);
- g_return_if_fail(sdata != NULL);
- filename_e = purple_strreplace(edisc_xfer->filename, " ", "%20");
- upload_url = g_strdup_printf("https://drive.mpa.gg.pl/me/file/outbox/"
- "%s%%2C%s", edisc_xfer->ticket_id, filename_e);
- msg = soup_message_new("PUT", upload_url);
- ggp_edisc_set_defaults(msg);
- headers = soup_message_get_request_headers(msg);
- soup_message_headers_replace(headers, "X-gged-local-revision", "0");
- soup_message_headers_replace(headers, "X-gged-security-token",
- sdata->security_token);
- soup_message_headers_replace(headers, "X-gged-metadata",
- "{\"node_type\": \"file\"}");
- soup_message_headers_set_content_length(headers,
- purple_xfer_get_size(xfer));
- g_signal_connect(msg, "starting",
- G_CALLBACK(ggp_edisc_xfer_send_start_msg_cb), xfer);
- g_signal_connect(msg, "restarted",
- G_CALLBACK(ggp_edisc_xfer_send_start_msg_cb), xfer);
- soup_session_send_and_read_async(sdata->session, msg, G_PRIORITY_DEFAULT,
- edisc_xfer->cancellable,
- ggp_edisc_xfer_send_done, xfer);
-ggp_edisc_xfer_send_new(G_GNUC_UNUSED PurpleProtocolXfer *prplxfer,
- PurpleConnection *gc, const char *who)
- g_return_val_if_fail(gc != NULL, NULL);
- g_return_val_if_fail(who != NULL, NULL);
- "account", purple_connection_get_account(gc),
- "type", PURPLE_XFER_TYPE_SEND,
- return PURPLE_XFER(xfer);
-void ggp_edisc_xfer_send_file(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *who,
- g_return_if_fail(gc != NULL);
- g_return_if_fail(who != NULL);
- /* Nothing interesting here, this code is common among protocols.
- * See ggp_edisc_xfer_send_new. */
- xfer = ggp_edisc_xfer_send_new(prplxfer, gc, who);
- purple_xfer_request_accepted(xfer, filename);
- purple_xfer_request(xfer);
-/*******************************************************************************
- ******************************************************************************/
-ggp_edisc_xfer_recv_new(PurpleConnection *gc, const char *who)
- g_return_val_if_fail(gc != NULL, NULL);
- g_return_val_if_fail(who != NULL, NULL);
- xfer = g_object_new(GGP_TYPE_XFER, "account",
- purple_connection_get_account(gc), "type",
- PURPLE_XFER_TYPE_RECEIVE, "remote-user", who, NULL);
- return PURPLE_XFER(xfer);
-ggp_edisc_xfer_recv_ack_done(GObject *source, GAsyncResult *result,
- PurpleXfer *xfer = data;
- GGPXfer *edisc_xfer = NULL;
- GBytes *response_body = NULL;
- const gchar *buffer = NULL;
- if (purple_xfer_is_cancelled(xfer)) {
- edisc_xfer = GGP_XFER(xfer);
- if(!SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(edisc_xfer->msg))) {
- g_clear_object(&edisc_xfer->msg);
- ggp_edisc_xfer_error(xfer, _("Cannot confirm file transfer."));
- response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
- if(response_body == NULL) {
- purple_debug_error("gg", "ggp_edisc_xfer_recv_ack_done: failed: %s",
- g_clear_object(&edisc_xfer->msg);
- ggp_edisc_xfer_error(xfer, _("Cannot confirm file transfer."));
- buffer = g_bytes_get_data(response_body, &size);
- purple_debug_info("gg", "ggp_edisc_xfer_recv_ack_done: [%.*s]", (int)size,
- g_bytes_unref(response_body);
- g_clear_object(&edisc_xfer->msg);
-static void ggp_edisc_xfer_recv_ack(PurpleXfer *xfer, gboolean accept)
- GGPXfer *edisc_xfer = GGP_XFER(xfer);
- ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(edisc_xfer->gc);
- SoupMessageHeaders *headers;
- g_return_if_fail(sdata != NULL);
- edisc_xfer->allowed = accept;
- msg = soup_message_new("PUT",
- ggp_edisc_xfer_ticket_url(edisc_xfer->ticket_id));
- ggp_edisc_set_defaults(msg);
- headers = soup_message_get_request_headers(msg);
- soup_message_headers_replace(headers, "X-gged-security-token",
- sdata->security_token);
- soup_message_headers_replace(headers, "X-gged-ack-status",
- accept ? "allow" : "reject");
- soup_session_send_and_read_async(sdata->session, msg,
- edisc_xfer->cancellable,
- ggp_edisc_xfer_recv_ack_done, xfer);
- edisc_xfer->msg = NULL;
- soup_session_send_and_read_async(sdata->session, msg,
- edisc_xfer->cancellable, NULL, NULL);
-ggp_edisc_xfer_recv_reject(PurpleXfer *xfer)
- ggp_edisc_xfer_recv_ack(xfer, FALSE);
-ggp_edisc_xfer_recv_accept(PurpleXfer *xfer)
- ggp_edisc_xfer_recv_ack(xfer, TRUE);
-static void ggp_edisc_xfer_recv_ticket_completed(PurpleXfer *xfer)
- GGPXfer *edisc_xfer = GGP_XFER(xfer);
- edisc_xfer->ready = TRUE;
- purple_xfer_start(xfer, -1, NULL, 0);
-ggp_edisc_xfer_recv_pollable_source_cb(GObject *pollable_stream, gpointer data)
- PurpleXfer *xfer = data;
- GGPXfer *edisc_xfer = GGP_XFER(xfer);
- len = g_pollable_input_stream_read_nonblocking(
- G_POLLABLE_INPUT_STREAM(pollable_stream), buf, sizeof(buf),
- edisc_xfer->cancellable, &error);
- if(purple_xfer_get_bytes_remaining(xfer) == 0) {
- purple_xfer_set_completed(xfer, TRUE);
- purple_debug_warning("gg", "ggp_edisc_xfer_recv_done: didn't "
- ggp_edisc_xfer_error(xfer, _("Error while receiving a file"));
- edisc_xfer->handler = 0;
- return G_SOURCE_REMOVE;
- if(error->code == G_IO_ERROR_WOULD_BLOCK) {
- return G_SOURCE_CONTINUE;
- } else if(error->code == G_IO_ERROR_CANCELLED) {
- purple_debug_warning("gg", "ggp_edisc_xfer_recv_done: lost "
- "connection with server: %s",
- ggp_edisc_xfer_error(xfer, _("Error while receiving a file"));
- edisc_xfer->handler = 0;
- return G_SOURCE_REMOVE;
- if(len > purple_xfer_get_bytes_remaining(xfer)) {
- purple_debug_error("gg", "ggp_edisc_xfer_recv_writer: saved too "
- "much (%" G_GSIZE_FORMAT
- " > %" G_GOFFSET_FORMAT ")",
- len, purple_xfer_get_bytes_remaining(xfer));
- ggp_edisc_xfer_error(xfer, _("Error while receiving a file"));
- edisc_xfer->handler = 0;
- return G_SOURCE_REMOVE;
- stored = purple_xfer_write_file(xfer, buf, len);
- purple_debug_error("gg", "ggp_edisc_xfer_recv_writer: failed to save");
- ggp_edisc_xfer_error(xfer, _("Error while receiving a file"));
- edisc_xfer->handler = 0;
- return G_SOURCE_REMOVE;
- return G_SOURCE_CONTINUE;
-ggp_edisc_xfer_recv_done_cb(GObject *source, GAsyncResult *result,
- PurpleXfer *xfer = data;
- GGPXfer *edisc_xfer = GGP_XFER(xfer);
- GInputStream *input = NULL;
- if(!SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(edisc_xfer->msg))) {
- g_clear_object(&edisc_xfer->msg);
- ggp_edisc_xfer_error(xfer, _("Error while receiving a file"));
- input = soup_session_send_finish(SOUP_SESSION(source), result, &error);
- purple_debug_warning("gg", "ggp_edisc_xfer_recv_done_cb: error "
- "receiving file: %s", error->message);
- g_clear_object(&edisc_xfer->msg);
- ggp_edisc_xfer_error(xfer, _("Error while receiving a file"));
- poll = g_pollable_input_stream_create_source(G_POLLABLE_INPUT_STREAM(input),
- edisc_xfer->cancellable);
- g_source_set_callback(poll,
- G_SOURCE_FUNC(ggp_edisc_xfer_recv_pollable_source_cb),
- edisc_xfer->handler = g_source_attach(poll, NULL);
- g_clear_object(&edisc_xfer->msg);
-ggp_edisc_xfer_recv_start(PurpleXfer *xfer)
- ggp_edisc_session_data *sdata;
- g_return_if_fail(xfer != NULL);
- edisc_xfer = GGP_XFER(xfer);
- g_return_if_fail(edisc_xfer != NULL);
- sdata = ggp_edisc_get_sdata(edisc_xfer->gc);
- g_return_if_fail(sdata != NULL);
- g_strdup_printf("https://drive.mpa.gg.pl/me/file/inbox/"
- "%s,%s?api_version=%s&security_token=%s",
- purple_url_encode(purple_xfer_get_filename(xfer)),
- GGP_EDISC_API, sdata->security_token);
- msg = soup_message_new("GET", upload_url);
- ggp_edisc_set_defaults(msg);
- // purple_http_request_set_max_len(msg, purple_xfer_get_size(xfer) + 1);
- soup_session_send_async(sdata->session, msg, G_PRIORITY_DEFAULT,
- edisc_xfer->cancellable,
- ggp_edisc_xfer_recv_done_cb, xfer);
-ggp_edisc_xfer_recv_ticket_update_got(GObject *source,
- GAsyncResult *async_result,
- SoupMessage *msg = data;
- PurpleConnection *gc = NULL;
- GBytes *response_body = NULL;
- const char *buffer = NULL;
- ggp_edisc_session_data *sdata;
- const gchar *ticket_id, *file_name, *send_mode_str;
- uin_t sender, recipient;
- SoupStatus status_code;
- status_code = soup_message_get_status(msg);
- if (!SOUP_STATUS_IS_SUCCESSFUL(status_code)) {
- purple_debug_error("gg",
- "ggp_edisc_xfer_recv_ticket_update_got: cannot "
- "fetch update for ticket (code=%d)",
- response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
- if(response_body == NULL) {
- purple_debug_error("gg",
- "ggp_edisc_xfer_recv_ticket_update_got: cannot "
- "fetch update for ticket (%s)",
- gc = g_object_get_data(G_OBJECT(msg), "purple-connection");
- sdata = ggp_edisc_get_sdata(gc);
- g_bytes_unref(response_body);
- buffer = g_bytes_get_data(response_body, &size);
- parser = ggp_json_parse(buffer);
- g_clear_pointer(&response_body, g_bytes_unref);
- result = json_node_get_object(json_parser_get_root(parser));
- result = json_object_get_object_member(result, "result");
- if (json_object_has_member(result, "status"))
- status = json_object_get_int_member(result, "status");
- result = json_object_get_object_member(result, "send_ticket");
- purple_debug_warning("gg",
- "ggp_edisc_xfer_recv_ticket_update_got: failed to "
- "get update (status=%d)",
- g_object_unref(parser);
- ticket_id = json_object_get_string_member(result, "id");
- sender = ggp_str_to_uin(json_object_get_string_member(result, "sender"));
- ggp_str_to_uin(json_object_get_string_member(result, "recipient"));
- file_size = g_ascii_strtoll(
- json_object_get_string_member(result, "file_size"), NULL, 10);
- file_name = json_object_get_string_member(result, "file_name");
- * AQQ 2.4.2.10: direct_inbox
- send_mode_str = json_object_get_string_member(result, "send_mode");
- * send_progress (float), ack_status, send_status
- if (purple_debug_is_verbose() && purple_debug_is_unsafe()) {
- purple_debug_info("gg",
- "Got ticket update: id=%s, sender=%u, recipient=%u, "
- "file name=\"%s\", file size=%d, send mode=%s)",
- ticket_id, sender, recipient, file_name, file_size,
- xfer = g_hash_table_lookup(sdata->xfers_initialized, ticket_id);
- purple_debug_misc("gg",
- "ggp_edisc_xfer_recv_ticket_update_got: ticket %s "
- purple_debug_is_unsafe() ? ticket_id : "");
- g_object_unref(parser);
- if (recipient != ggp_get_my_uin(gc)) {
- purple_debug_misc("gg",
- "ggp_edisc_xfer_recv_ticket_update_got: ticket %s is "
- "not for incoming transfer (its from %u to %u)",
- purple_debug_is_unsafe() ? ticket_id : "", sender,
- g_object_unref(parser);
- xfer = ggp_edisc_xfer_recv_new(gc, ggp_uin_to_str(sender));
- purple_xfer_set_filename(xfer, file_name);
- purple_xfer_set_size(xfer, file_size);
- purple_xfer_request(xfer);
- edisc_xfer = GGP_XFER(xfer);
- edisc_xfer->ticket_id = g_strdup(ticket_id);
- g_hash_table_insert(sdata->xfers_initialized, edisc_xfer->ticket_id, xfer);
- g_hash_table_add(sdata->xfers_history, g_strdup(ticket_id));
- g_object_unref(parser);
-ggp_edisc_xfer_recv_ticket_update_authenticated(PurpleConnection *gc,
- ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
- gchar *ticket = _ticket;
- g_return_if_fail(sdata != NULL);
- "ggp_edisc_xfer_recv_ticket_update_authenticated: update of "
- "ticket %s aborted due to authentication failure",
- msg = soup_message_new("GET", ggp_edisc_xfer_ticket_url(ticket));
- ggp_edisc_set_defaults(msg);
- soup_message_headers_replace(soup_message_get_request_headers(msg),
- "X-gged-security-token",
- sdata->security_token);
- g_object_set_data(G_OBJECT(msg), "purple-connection", gc);
- soup_session_send_and_read_async(sdata->session, msg, G_PRIORITY_DEFAULT,
- ggp_edisc_xfer_recv_ticket_update_got,
-ggp_edisc_xfer_recv_ticket_got(PurpleConnection *gc, const gchar *ticket_id)
- ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
- g_return_if_fail(sdata != NULL);
- if (g_hash_table_contains(sdata->xfers_history, ticket_id)) {
- ggp_ggdrive_auth(gc, ggp_edisc_xfer_recv_ticket_update_authenticated,
-ggp_edisc_xfer_ticket_changed(PurpleConnection *gc, const char *data)
- ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
- const gchar *ticket_id, *send_status;
- ggp_edisc_xfer_ack_status ack_status;
- g_return_if_fail(sdata != NULL);
- parser = ggp_json_parse(data);
- ticket = json_node_get_object(json_parser_get_root(parser));
- ticket_id = json_object_get_string_member(ticket, "id");
- ack_status = ggp_edisc_xfer_parse_ack_status(
- json_object_get_string_member(ticket, "ack_status"));
- send_status = json_object_get_string_member(ticket, "send_status");
- if (ticket_id == NULL) {
- xfer = g_hash_table_lookup(sdata->xfers_initialized, ticket_id);
- purple_debug_misc("gg",
- "ggp_edisc_event_ticket_changed: ticket %s not "
- "found, updating it...",
- purple_debug_is_unsafe() ? ticket_id : "");
- ggp_edisc_xfer_recv_ticket_got(gc, ticket_id);
- g_object_unref(parser);
- if (g_strcmp0("in_progress", send_status) == 0) {
- } else if (g_strcmp0("completed", send_status) == 0) {
- } else if (g_strcmp0("expired", send_status) == 0)
- ggp_edisc_xfer_error(xfer, _("File transfer expired."));
- "gg", "ggp_edisc_event_ticket_changed: unknown send_status=%s",
- g_object_unref(parser);
- g_object_unref(parser);
- if (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_RECEIVE) {
- ggp_edisc_xfer_recv_ticket_completed(xfer);
- if (ack_status != GGP_EDISC_XFER_ACK_STATUS_UNKNOWN) {
- ggp_edisc_xfer_send_ticket_changed(
- gc, xfer, ack_status == GGP_EDISC_XFER_ACK_STATUS_ALLOWED);
-/*******************************************************************************
- * GObject implementation
- ******************************************************************************/
-G_DEFINE_DYNAMIC_TYPE_EXTENDED(GGPXfer, ggp_xfer, PURPLE_TYPE_XFER,
-ggp_xfer_init_xfer(PurpleXfer *xfer) {
- PurpleXferType type = purple_xfer_get_xfer_type(xfer);
- if(type == PURPLE_XFER_TYPE_SEND) {
- ggp_edisc_xfer_send_init(xfer);
- } else if(type == PURPLE_XFER_TYPE_RECEIVE) {
- ggp_edisc_xfer_recv_accept(xfer);
-ggp_xfer_start(PurpleXfer *xfer) {
- PurpleXferType type = purple_xfer_get_xfer_type(xfer);
- if(type == PURPLE_XFER_TYPE_SEND) {
- ggp_edisc_xfer_send_start(xfer);
- } else if(type == PURPLE_XFER_TYPE_RECEIVE) {
- ggp_edisc_xfer_recv_start(xfer);
-ggp_xfer_init(GGPXfer *xfer) {
- xfer->cancellable = g_cancellable_new();
-ggp_xfer_finalize(GObject *obj) {
- GGPXfer *edisc_xfer = GGP_XFER(obj);
- ggp_edisc_session_data *sdata;
- sdata = ggp_edisc_get_sdata(edisc_xfer->gc);
- g_free(edisc_xfer->filename);
- g_cancellable_cancel(edisc_xfer->cancellable);
- g_clear_object(&edisc_xfer->cancellable);
- g_clear_object(&edisc_xfer->msg);
- g_clear_handle_id(&edisc_xfer->handler, g_source_remove);
- if (edisc_xfer->ticket_id != NULL) {
- g_hash_table_remove(sdata->xfers_initialized,
- edisc_xfer->ticket_id);
- G_OBJECT_CLASS(ggp_xfer_parent_class)->finalize(obj);
-ggp_xfer_class_finalize(G_GNUC_UNUSED GGPXferClass *klass) {
-ggp_xfer_class_init(GGPXferClass *klass) {
- GObjectClass *obj_class = G_OBJECT_CLASS(klass);
- PurpleXferClass *xfer_class = PURPLE_XFER_CLASS(klass);
- obj_class->finalize = ggp_xfer_finalize;
- xfer_class->init = ggp_xfer_init_xfer;
- xfer_class->start = ggp_xfer_start;
- xfer_class->request_denied = ggp_edisc_xfer_recv_reject;
-ggp_xfer_register(GTypeModule *module) {
- ggp_xfer_register_type(module);
--- a/libpurple/protocols/gg/edisc.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
- * 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
- * Component written by Tomek Wasilczyk (http://www.wasilczyk.pl).
- * This file is dual-licensed under the GPL2+ and the X11 (MIT) licences.
- * As a recipient of this file you may choose, which license to receive the
- * code under. As a contributor, you have to ensure the new code is
- * compatible with both.
- * 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
-#ifndef PURPLE_GG_EDISC_H
-#define PURPLE_GG_EDISC_H
-typedef struct _ggp_edisc_session_data ggp_edisc_session_data;
-#define GGP_TYPE_XFER (ggp_xfer_get_type())
-G_DECLARE_FINAL_TYPE(GGPXfer, ggp_xfer, GGP, XFER, PurpleXfer);
-void ggp_xfer_register(GTypeModule *module);
-void ggp_edisc_setup(PurpleConnection *gc, GProxyResolver *resolver);
-void ggp_edisc_cleanup(PurpleConnection *gc);
-/* General xfer functions. */
-void ggp_edisc_xfer_ticket_changed(PurpleConnection *gc,
-gboolean ggp_edisc_xfer_can_receive_file(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *who);
-void ggp_edisc_xfer_send_file(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *who,
-PurpleXfer * ggp_edisc_xfer_send_new(PurpleProtocolXfer *prplxfer, PurpleConnection *gc, const char *who);
-#endif /* PURPLE_GG_EDISC_H */
--- a/libpurple/protocols/gg/gg.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1452 +0,0 @@
- * @file gg.c Gadu-Gadu protocol plugin
- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
- * Some parts of the code are adapted or taken from the previous implementation
- * of this plugin written by Arkadiusz Miskiewicz <misiek@pld.org.pl>
- * Some parts Copyright (C) 2009 Krzysztof Klinikowski <grommasher@gmail.com>
- * Thanks to Google's Summer of Code Program.
- * 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 <gplugin-native.h>
-#include "resolver-purple.h"
-#include "libgadu-events.h"
-#include "pubdir-prpl.h"
-#include "message-prpl.h"
-/* ---------------------------------------------------------------------- */
-static PurpleProtocol *my_protocol = NULL;
-/* ---------------------------------------------------------------------- */
-ggp_buddy_data * ggp_buddy_get_data(PurpleBuddy *buddy)
- ggp_buddy_data *buddy_data = purple_buddy_get_protocol_data(buddy);
- buddy_data = g_new0(ggp_buddy_data, 1); /* TODO: leak */
- purple_buddy_set_protocol_data(buddy, buddy_data);
-ggp_buddy_free(G_GNUC_UNUSED PurpleProtocolClient *client, PurpleBuddy *buddy)
- ggp_buddy_data *buddy_data = purple_buddy_get_protocol_data(buddy);
- purple_buddy_set_protocol_data(buddy, NULL);
-const gchar * ggp_get_imtoken(PurpleConnection *gc)
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- return accdata->imtoken;
- if (accdata->imtoken_warned)
- accdata->imtoken_warned = TRUE;
- purple_notify_error(gc, _("Authentication failed"),
- _("IMToken value has not been received."),
- _("Some features will be disabled. "
- "You may try again after a while."),
- purple_request_cpar_from_connection(gc));
-ggp_own_uin(PurpleConnection *gc) {
- PurpleAccount *account = purple_connection_get_account(gc);
- PurpleContactInfo *info = PURPLE_CONTACT_INFO(account);
- return ggp_str_to_uin(purple_contact_info_get_username(info));
-/* ---------------------------------------------------------------------- */
-/* buddy list import/export from/to file */
-static void ggp_callback_buddylist_save_ok(PurpleConnection *gc, const char *filename)
- PurpleAccount *account = purple_connection_get_account(gc);
- char *buddylist = ggp_buddylist_dump(account);
- purple_debug_info("gg", "Saving...\n");
- purple_debug_info("gg", "file = %s\n", filename);
- if (buddylist == NULL) {
- purple_notify_info(account, _("Save Buddylist..."), _("Your "
- "buddylist is empty, nothing was written to the file."),
- NULL, purple_request_cpar_from_connection(gc));
- if (g_file_set_contents(filename, buddylist, -1, NULL)) {
- purple_notify_info(account, _("Save Buddylist..."),
- _("Buddylist saved successfully!"), NULL,
- purple_request_cpar_from_connection(gc));
- PurpleContactInfo *info = PURPLE_CONTACT_INFO(account);
- primary = g_strdup_printf(_("Couldn't write buddy list for %s to %s"),
- purple_contact_info_get_username(info),
- purple_notify_error(account, _("Save Buddylist..."),
- primary, NULL, purple_request_cpar_from_connection(gc));
-static void ggp_callback_buddylist_load_ok(PurpleConnection *gc, gchar *file)
- PurpleAccount *account = purple_connection_get_account(gc);
- char *buddylist = NULL;
- purple_debug_info("gg", "file_name = %s\n", file);
- if (!g_file_get_contents(file, &buddylist, &length, &error)) {
- purple_notify_error(account, _("Couldn't load buddylist"),
- _("Couldn't load buddylist"), error->message,
- purple_request_cpar_from_connection(gc));
- purple_debug_error("gg",
- "Couldn't load buddylist. file = %s; error = %s\n",
- ggp_buddylist_load(gc, buddylist);
- purple_notify_info(account, _("Load Buddylist..."),
- _("Buddylist loaded successfully!"), NULL,
- purple_request_cpar_from_connection(gc));
-ggp_action_buddylist_save(G_GNUC_UNUSED GSimpleAction *action,
- G_GNUC_UNUSED gpointer data)
- const gchar *account_id = NULL;
- PurpleAccountManager *manager = NULL;
- PurpleAccount *account = NULL;
- PurpleConnection *connection = NULL;
- if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
- g_critical("GG save buddylist action parameter is of incorrect type %s",
- g_variant_get_type_string(parameter));
- account_id = g_variant_get_string(parameter, NULL);
- manager = purple_account_manager_get_default();
- account = purple_account_manager_find_by_id(manager, account_id);
- connection = purple_account_get_connection(account);
- purple_request_file(action, _("Save buddylist..."), NULL, TRUE,
- G_CALLBACK(ggp_callback_buddylist_save_ok), NULL,
- purple_request_cpar_from_connection(connection), connection);
- g_clear_object(&account);
-ggp_action_buddylist_load(G_GNUC_UNUSED GSimpleAction *action,
- G_GNUC_UNUSED gpointer data)
- const gchar *account_id = NULL;
- PurpleAccountManager *manager = NULL;
- PurpleAccount *account = NULL;
- PurpleConnection *connection = NULL;
- if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
- g_critical("GG load buddylist action parameter is of incorrect type %s",
- g_variant_get_type_string(parameter));
- account_id = g_variant_get_string(parameter, NULL);
- manager = purple_account_manager_get_default();
- account = purple_account_manager_find_by_id(manager, account_id);
- connection = purple_account_get_connection(account);
- purple_request_file(action, _("Load buddylist from file..."), NULL,
- FALSE, G_CALLBACK(ggp_callback_buddylist_load_ok), NULL,
- purple_request_cpar_from_connection(connection), connection);
- g_clear_object(&account);
-/* ----- BLOCK BUDDIES -------------------------------------------------- */
-static void ggp_add_deny(PurpleProtocolPrivacy *privacy, PurpleConnection *gc,
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- uin_t uin = ggp_str_to_uin(who);
- purple_debug_info("gg", "ggp_add_deny: %u\n", uin);
- gg_remove_notify_ex(info->session, uin, GG_USER_NORMAL);
- gg_add_notify_ex(info->session, uin, GG_USER_BLOCKED);
-static void ggp_remove_deny(PurpleProtocolPrivacy *privacy,
- PurpleConnection *gc, const char *who)
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- uin_t uin = ggp_str_to_uin(who);
- purple_debug_info("gg", "ggp_rem_deny: %u\n", uin);
- gg_remove_notify_ex(info->session, uin, GG_USER_BLOCKED);
- gg_add_notify_ex(info->session, uin, GG_USER_NORMAL);
-/* ---------------------------------------------------------------------- */
-/* ----- INTERNAL CALLBACKS --------------------------------------------- */
-/* ---------------------------------------------------------------------- */
-static void ggp_typing_notification_handler(PurpleConnection *gc, uin_t uin, int length) {
- from = g_strdup_printf("%u", uin);
- purple_serv_got_typing(gc, from, 0, PURPLE_IM_TYPING);
- purple_serv_got_typing_stopped(gc, from);
- * Handling of XML events.
- * @param gc PurpleConnection.
- * @param data Raw XML contents.
- * @see http://toxygen.net/libgadu/protocol/#ch1.13
- * @todo: this may not be necessary anymore
-ggp_xml_event_handler(G_GNUC_UNUSED PurpleConnection *gc, char *data)
- PurpleXmlNode *xml = NULL;
- PurpleXmlNode *xmlnode_next_event;
- xml = purple_xmlnode_from_str(data, -1);
- purple_debug_error("gg", "ggp_xml_event_handler: "
- "invalid xml: [%s]\n", data);
- xmlnode_next_event = purple_xmlnode_get_child(xml, "event");
- while (xmlnode_next_event != NULL) {
- PurpleXmlNode *xmlnode_current_event = xmlnode_next_event;
- PurpleXmlNode *xmlnode_type;
- PurpleXmlNode *xmlnode_sender;
- char *event_sender_raw;
- uin_t event_sender = 0;
- xmlnode_next_event = purple_xmlnode_get_next_twin(xmlnode_next_event);
- xmlnode_type = purple_xmlnode_get_child(xmlnode_current_event, "type");
- if (xmlnode_type == NULL)
- event_type_raw = purple_xmlnode_get_data(xmlnode_type);
- if (event_type_raw != NULL)
- event_type = atoi(event_type_raw);
- g_free(event_type_raw);
- xmlnode_sender = purple_xmlnode_get_child(xmlnode_current_event, "sender");
- if (xmlnode_sender != NULL) {
- event_sender_raw = purple_xmlnode_get_data(xmlnode_sender);
- if (event_sender_raw != NULL)
- event_sender = ggp_str_to_uin(event_sender_raw);
- g_free(event_sender_raw);
- case 28: /* avatar update */
- purple_debug_info("gg",
- "ggp_xml_event_handler: avatar updated (uid: %u)\n",
- purple_debug_error("gg",
- "ggp_xml_event_handler: unsupported event type=%d from=%u\n",
- event_type, event_sender);
- purple_xmlnode_free(xml);
-ggp_callback_recv(gpointer _gc, G_GNUC_UNUSED gint fd,
- G_GNUC_UNUSED PurpleInputCondition cond)
- PurpleConnection *gc = _gc;
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- if (!(ev = gg_watch_fd(info->session))) {
- purple_debug_error("gg",
- "ggp_callback_recv: gg_watch_fd failed -- CRITICAL!\n");
- purple_connection_error (gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Unable to read from socket"));
- if (purple_debug_is_verbose()) {
- purple_debug_misc("gg", "ggp_callback_recv: got event %s",
- gg_debug_event(ev->type));
- g_source_remove(info->inpa);
- info->inpa = purple_input_add(info->session->fd,
- ggp_tcpsocket_inputcond_gg_to_purple(info->session->check),
- ggp_callback_recv, gc);
- /* Nothing happened. */
- case GG_EVENT_CONN_FAILED:
- purple_connection_error (gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Server disconnected"));
- ggp_message_got(gc, &ev->event.msg);
- case GG_EVENT_IMAGE_REPLY:
- ggp_image_recv(gc, &ev->event.image_reply);
- case GG_EVENT_IMAGE_REQUEST:
- ggp_image_send(gc, &ev->event.image_request);
- case GG_EVENT_NOTIFY60:
- case GG_EVENT_STATUS60:
- ggp_status_got_others(gc, ev);
- case GG_EVENT_TYPING_NOTIFICATION:
- ggp_typing_notification_handler(gc, ev->event.typing_notification.uin,
- ev->event.typing_notification.length);
- case GG_EVENT_XML_EVENT:
- purple_debug_info("gg", "GG_EVENT_XML_EVENT\n");
- ggp_xml_event_handler(gc, ev->event.xml_event.data);
- case GG_EVENT_USER_DATA:
- ggp_events_user_data(gc, &ev->event.user_data);
- case GG_EVENT_JSON_EVENT:
- ggp_events_json(gc, &ev->event.json_event);
- case GG_EVENT_USERLIST100_VERSION:
- ggp_roster_version(gc, &ev->event.userlist100_version);
- case GG_EVENT_USERLIST100_REPLY:
- ggp_roster_reply(gc, &ev->event.userlist100_reply);
- case GG_EVENT_MULTILOGON_MSG:
- ggp_message_got_multilogon(gc, &ev->event.multilogon_msg);
- case GG_EVENT_MULTILOGON_INFO:
- ggp_multilogon_info(gc, &ev->event.multilogon_info);
- purple_debug_info("gg", "gg11: got IMTOKEN\n");
- info->imtoken = g_strdup(ev->event.imtoken.imtoken);
- purple_debug_info("gg", "gg11: got PONG110 %lu\n",
- (long unsigned)ev->event.pong110.time);
- case GG_EVENT_CHAT_INFO:
- case GG_EVENT_CHAT_INFO_GOT_ALL:
- case GG_EVENT_CHAT_INFO_UPDATE:
- case GG_EVENT_CHAT_CREATED:
- case GG_EVENT_CHAT_INVITE_ACK:
- ggp_chat_got_event(gc, ev);
- case GG_EVENT_DISCONNECT:
- ggp_servconn_remote_disconnect(gc);
- purple_debug_warning("gg",
- "unsupported event type=%d\n", ev->type);
-ggp_async_login_handler(gpointer _gc, G_GNUC_UNUSED gint fd,
- G_GNUC_UNUSED PurpleInputCondition cond)
- PurpleConnection *gc = _gc;
- PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
- info = purple_connection_get_protocol_data(gc);
- purple_debug_info("gg", "login_handler: session: check = %d; state = %d;\n",
- info->session->check, info->session->state);
- switch (info->session->state) {
- purple_debug_info("gg", "GG_STATE_ERROR\n");
- case GG_STATE_RESOLVING:
- purple_debug_info("gg", "GG_STATE_RESOLVING\n");
- case GG_STATE_RESOLVING_GG:
- purple_debug_info("gg", "GG_STATE_RESOLVING_GG\n");
- case GG_STATE_CONNECTING_HUB:
- purple_debug_info("gg", "GG_STATE_CONNECTING_HUB\n");
- case GG_STATE_READING_DATA:
- purple_debug_info("gg", "GG_STATE_READING_DATA\n");
- case GG_STATE_CONNECTING_GG:
- purple_debug_info("gg", "GG_STATE_CONNECTING_GG\n");
- case GG_STATE_READING_KEY:
- purple_debug_info("gg", "GG_STATE_READING_KEY\n");
- case GG_STATE_READING_REPLY:
- purple_debug_info("gg", "GG_STATE_READING_REPLY\n");
- case GG_STATE_TLS_NEGOTIATION:
- purple_debug_info("gg", "GG_STATE_TLS_NEGOTIATION\n");
- case GG_STATE_RESOLVING_HUB:
- purple_debug_info("gg", "GG_STATE_RESOLVING_HUB\n");
- case GG_STATE_READING_HUB:
- purple_debug_info("gg", "GG_STATE_READING_HUB\n");
- purple_debug_error("gg", "unknown state = %d\n",
- if (!(ev = gg_watch_fd(info->session))) {
- purple_debug_error("gg", "login_handler: gg_watch_fd failed!\n");
- purple_connection_error (gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Unable to read from socket"));
- purple_debug_info("gg", "login_handler: session->fd = %d\n", info->session->fd);
- purple_debug_info("gg", "login_handler: session: check = %d; state = %d;\n",
- info->session->check, info->session->state);
- g_clear_handle_id(&info->inpa, g_source_remove);
- /** XXX I think that this shouldn't be done if ev->type is GG_EVENT_CONN_FAILED or GG_EVENT_CONN_SUCCESS -datallah */
- if (info->session->fd >= 0)
- info->inpa = purple_input_add(info->session->fd,
- (info->session->check == 1) ? PURPLE_INPUT_WRITE :
- ggp_async_login_handler, gc);
- /* Nothing happened. */
- purple_debug_info("gg", "GG_EVENT_NONE\n");
- case GG_EVENT_CONN_SUCCESS:
- purple_debug_info("gg", "GG_EVENT_CONN_SUCCESS:"
- " successfully connected to %s\n",
- info->session->connect_host);
- ggp_servconn_add_server(info->session->
- g_source_remove(info->inpa);
- info->inpa = purple_input_add(info->session->fd,
- ggp_callback_recv, gc);
- purple_connection_set_state(gc, PURPLE_CONNECTION_STATE_CONNECTED);
- ggp_buddylist_send(gc);
- ggp_roster_request_update(gc);
- case GG_EVENT_CONN_FAILED:
- g_clear_handle_id(&info->inpa, g_source_remove);
- purple_debug_info("gg", "Connection failure: %d\n",
- switch (ev->event.failure) {
- case GG_FAILURE_RESOLVING:
- purple_connection_error(gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- case GG_FAILURE_PASSWORD:
- purple_connection_error(gc,
- PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
- _("Incorrect password"));
- purple_connection_error(gc,
- PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR,
- _("SSL Connection Failed"));
- case GG_FAILURE_INTRUDER:
- purple_connection_error(gc,
- PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
- _("Your account has been "
- "disabled because too many "
- "incorrect passwords were "
- case GG_FAILURE_UNAVAILABLE:
- purple_connection_error(gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Service temporarily "
- purple_connection_error(gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Error connecting to proxy "
- purple_connection_error(gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Error connecting to master "
- case GG_FAILURE_INTERNAL:
- purple_connection_error(gc,
- PURPLE_CONNECTION_ERROR_OTHER_ERROR,
- purple_connection_error(gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Connection failed"));
- if (ev->event.msg.sender == 0) {
- if (ev->event.msg.message == NULL)
- /* system messages are mostly ads */
- purple_debug_info("gg", "System message:\n%s\n",
- ev->event.msg.message);
- purple_debug_warning("gg", "GG_EVENT_MSG: message from user %u "
- "unexpected while connecting:\n%s\n",
- ev->event.msg.message);
- purple_debug_error("gg", "strange event: %d\n", ev->type);
-gg_uri_handler_find_account(PurpleAccount *account,
- G_GNUC_UNUSED gconstpointer data)
- const gchar *protocol_id;
- protocol_id = purple_account_get_protocol_id(account);
- return (purple_strequal(protocol_id, "prpl-gg") &&
- purple_account_is_connected(account));
-gg_uri_handler(const gchar *scheme, const gchar *screenname,
- G_GNUC_UNUSED GHashTable *params)
- PurpleAccountManager *manager = NULL;
- PurpleAccount *account;
- PurpleConversation *im;
- g_return_val_if_fail(screenname != NULL, FALSE);
- if (!purple_strequal(scheme, "gg")) {
- if (screenname[0] == '\0') {
- purple_debug_warning("gg", "Invalid empty screenname in URI");
- /* Find online Gadu-Gadu account */
- manager = purple_account_manager_get_default();
- account = purple_account_manager_find_custom(manager,
- (GEqualFunc)gg_uri_handler_find_account,
- im = purple_im_conversation_new(account, screenname);
- purple_conversation_present(im);
- g_clear_object(&account);
-/* ---------------------------------------------------------------------- */
-/* ----- PurpleProtocol ----------------------------------------- */
-/* ---------------------------------------------------------------------- */
-static PurpleBuddyIconSpec *
-ggp_protocol_get_buddy_icon_spec(G_GNUC_UNUSED PurpleProtocol *protocol) {
- return purple_buddy_icon_spec_new("png",
- PURPLE_ICON_SCALE_DISPLAY |
- PURPLE_ICON_SCALE_SEND);
-ggp_protocol_get_account_options(G_GNUC_UNUSED PurpleProtocol *protocol) {
- PurpleAccountOption *option = NULL;
- PurpleKeyValuePair *kvp = NULL;
- GList *encryption_options = NULL;
- GList *protocol_version = NULL;
- option = purple_account_option_string_new(_("GG server"), "gg_server", "");
- opts = g_list_append(opts, option);
- /* setup encryption options */
- kvp = purple_key_value_pair_new(_("Use encryption if available"),
- encryption_options = g_list_append(encryption_options, kvp);
- kvp = purple_key_value_pair_new(_("Require encryption"), "require_tls");
- encryption_options = g_list_append(encryption_options, kvp);
- kvp = purple_key_value_pair_new(_("Don't use encryption"), "none");
- encryption_options = g_list_append(encryption_options, kvp);
- option = purple_account_option_list_new(_("Connection security"),
- "encryption", encryption_options);
- opts = g_list_append(opts, option);
- /* setup the protocol version */
- kvp = purple_key_value_pair_new(_("Default"), "default");
- protocol_version = g_list_append(protocol_version, kvp);
- kvp = purple_key_value_pair_new("GG 10", "gg10");
- protocol_version = g_list_append(protocol_version, kvp);
- kvp = purple_key_value_pair_new("GG 11", "gg11");
- protocol_version = g_list_append(protocol_version, kvp);
- option = purple_account_option_list_new(_("Protocol version"),
- opts = g_list_append(opts, option);
- option = purple_account_option_bool_new(_("Show links from strangers"),
- "show_links_from_strangers", 1);
- opts = g_list_append(opts, option);
-ggp_normalize(G_GNUC_UNUSED PurpleProtocolClient *client,
- G_GNUC_UNUSED PurpleAccount *account, const char *who)
- static char normalized[21]; /* maximum unsigned long long int size */
- uin_t uin = ggp_str_to_uin(who);
- g_snprintf(normalized, sizeof(normalized), "%u", uin);
-ggp_login(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleAccount *account) {
- PurpleConnection *gc = purple_account_get_connection(account);
- PurpleContactInfo *contact_info = PURPLE_CONTACT_INFO(account);
- struct gg_login_params *glp;
- const gchar *encryption_type, *protocol_version;
- GProxyResolver *resolver;
- purple_connection_set_flags(gc,
- PURPLE_CONNECTION_FLAG_HTML |
- PURPLE_CONNECTION_FLAG_NO_URLDESC);
- resolver = purple_proxy_get_proxy_resolver(account, &error);
- if (resolver == NULL) {
- purple_debug_error("gg", "Unable to get account proxy resolver: %s",
- purple_connection_take_error(gc, error);
- glp = g_new0(struct gg_login_params, 1);
- glp->struct_size = sizeof(struct gg_login_params);
- info = g_new0(GGPInfo, 1);
- purple_connection_set_protocol_data(gc, info);
- info->http = soup_session_new_with_options("proxy-resolver", resolver,
- ggp_tcpsocket_setup(gc, glp);
- ggp_multilogon_setup(gc);
- ggp_edisc_setup(gc, resolver);
- g_object_unref(resolver);
- glp->uin = ggp_str_to_uin(purple_contact_info_get_username(contact_info));
- ggp_convert_to_cp1250(purple_connection_get_password(gc));
- purple_connection_error(gc,
- PURPLE_CONNECTION_ERROR_INVALID_USERNAME,
- _("The username specified is invalid."));
- purple_str_wipe(glp->password);
- glp->status_flags = GG_STATUS_FLAG_UNKNOWN;
- if (purple_account_get_bool(account, "show_links_from_strangers", 1))
- glp->status_flags |= GG_STATUS_FLAG_SPAM;
- glp->encoding = GG_ENCODING_UTF8;
- glp->protocol_features = (GG_FEATURE_DND_FFC |
- GG_FEATURE_TYPING_NOTIFICATION | GG_FEATURE_MULTILOGON |
- encryption_type = purple_account_get_string(account, "encryption",
- purple_debug_info("gg", "Requested encryption type: %s\n",
- if (purple_strequal(encryption_type, "opportunistic_tls"))
- glp->tls = GG_SSL_ENABLED;
- else if (purple_strequal(encryption_type, "require_tls")) {
- if (gg_libgadu_check_feature(GG_LIBGADU_FEATURE_SSL))
- glp->tls = GG_SSL_REQUIRED;
- purple_connection_error(gc,
- PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
- _("SSL support unavailable"));
- purple_str_wipe(glp->password);
- else /* encryption_type == "none" */
- glp->tls = GG_SSL_DISABLED;
- purple_debug_misc("gg", "TLS mode: %d\n", glp->tls);
- protocol_version = purple_account_get_string(account,
- "protocol_version", "default");
- purple_debug_info("gg", "Requested protocol version: %s\n",
- if (purple_strequal(protocol_version, "gg10"))
- glp->protocol_version = GG_PROTOCOL_VERSION_100;
- else if (purple_strequal(protocol_version, "gg11"))
- glp->protocol_version = GG_PROTOCOL_VERSION_110;
- glp->compatibility = GG_COMPAT_1_12_0;
- ggp_status_set_initial(gc, glp);
- address = purple_account_get_string(account, "gg_server", "");
- if (address && *address)
- glp->connect_host = g_strdup(address);
- info->session = gg_login(glp);
- g_free(glp->connect_host);
- purple_str_wipe(glp->password);
- if (info->session == NULL) {
- purple_connection_error (gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Connection failed"));
- if (info->session->fd > 0) {
- info->inpa = purple_input_add(info->session->fd,
- PURPLE_INPUT_READ, ggp_async_login_handler, gc);
-ggp_close(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleConnection *gc) {
- PurpleAccount *account;
- g_return_if_fail(gc != NULL);
- account = purple_connection_get_account(gc);
- info = purple_connection_get_protocol_data(gc);
- purple_notify_close_with_handle(gc);
- if (info->session != NULL) {
- ggp_status_set_disconnected(account);
- gg_logoff(info->session);
- gg_free_session(info->session);
- ggp_avatar_cleanup(gc);
- ggp_roster_cleanup(gc);
- ggp_multilogon_cleanup(gc);
- ggp_status_cleanup(gc);
- ggp_message_cleanup(gc);
- g_clear_handle_id(&info->inpa, g_source_remove);
- soup_session_abort(info->http);
- g_object_unref(info->http);
- purple_connection_set_protocol_data(gc, NULL);
- purple_debug_info("gg", "Connection closed.\n");
-ggp_send_typing(G_GNUC_UNUSED PurpleProtocolIM *im, PurpleConnection *gc,
- const char *name, PurpleIMTypingState state)
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- int dummy_length; /* we don't send real length of typed message */
- if (state == PURPLE_IM_TYPED) /* not supported */
- if (state == PURPLE_IM_TYPING)
- dummy_length = (int)g_random_int();
- else /* PURPLE_IM_NOT_TYPING */
- gg_typing_notification(
- return 1; /* wait 1 second before another notification */
-ggp_add_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
- PurpleBuddy *buddy, PurpleGroup *group, const gchar *message)
- PurpleAccount *account = purple_connection_get_account(gc);
- PurpleContactInfo *contact_info = PURPLE_CONTACT_INFO(account);
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- const gchar *name = purple_buddy_get_name(buddy);
- gg_add_notify(info->session, ggp_str_to_uin(name));
- /* gg server won't tell us our status here */
- if(purple_strequal(purple_contact_info_get_username(contact_info), name)) {
- ggp_status_fake_to_self(gc);
- ggp_roster_add_buddy(protocol_server, gc, buddy, group, message);
- ggp_pubdir_request_buddy_alias(gc, buddy);
-ggp_remove_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
- PurpleBuddy *buddy, PurpleGroup *group)
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- gg_remove_notify(info->session, ggp_str_to_uin(purple_buddy_get_name(buddy)));
- ggp_roster_remove_buddy(protocol_server, gc, buddy, group);
-ggp_keepalive(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- /* purple_debug_info("gg", "Keeping connection alive....\n"); */
- if (gg_ping(info->session) < 0) {
- purple_debug_info("gg", "Not connected to the server "
- "or gg_session is not correct\n");
- purple_connection_error (gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Not connected to the server"));
-ggp_action_multilogon(G_GNUC_UNUSED GSimpleAction *action,
- G_GNUC_UNUSED gpointer data)
- const gchar *account_id = NULL;
- PurpleAccountManager *manager = NULL;
- PurpleAccount *account = NULL;
- PurpleConnection *connection = NULL;
- if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
- g_critical("GG multilogin action parameter is of incorrect type %s",
- g_variant_get_type_string(parameter));
- account_id = g_variant_get_string(parameter, NULL);
- manager = purple_account_manager_get_default();
- account = purple_account_manager_find_by_id(manager, account_id);
- connection = purple_account_get_connection(account);
- g_clear_object(&account);
- ggp_multilogon_dialog(connection);
-ggp_action_status_broadcasting(G_GNUC_UNUSED GSimpleAction *action,
- G_GNUC_UNUSED gpointer data)
- const gchar *account_id = NULL;
- PurpleAccountManager *manager = NULL;
- PurpleAccount *account = NULL;
- PurpleConnection *connection = NULL;
- if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
- g_critical("GG broadcast action parameter is of incorrect type %s",
- g_variant_get_type_string(parameter));
- account_id = g_variant_get_string(parameter, NULL);
- manager = purple_account_manager_get_default();
- account = purple_account_manager_find_by_id(manager, account_id);
- connection = purple_account_get_connection(account);
- g_clear_object(&account);
- ggp_status_broadcasting_dialog(connection);
-ggp_action_search(G_GNUC_UNUSED GSimpleAction *action,
- G_GNUC_UNUSED gpointer data)
- const gchar *account_id = NULL;
- PurpleAccountManager *manager = NULL;
- PurpleAccount *account = NULL;
- PurpleConnection *connection = NULL;
- if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
- g_critical("GG search action parameter is of incorrect type %s",
- g_variant_get_type_string(parameter));
- account_id = g_variant_get_string(parameter, NULL);
- manager = purple_account_manager_get_default();
- account = purple_account_manager_find_by_id(manager, account_id);
- connection = purple_account_get_connection(account);
- g_clear_object(&account);
- ggp_pubdir_search(connection, NULL);
-ggp_action_set_info(G_GNUC_UNUSED GSimpleAction *action,
- G_GNUC_UNUSED gpointer data)
- const gchar *account_id = NULL;
- PurpleAccountManager *manager = NULL;
- PurpleAccount *account = NULL;
- PurpleConnection *connection = NULL;
- if(!g_variant_is_of_type(parameter, G_VARIANT_TYPE_STRING)) {
- g_critical("GG set info action parameter is of incorrect type %s",
- g_variant_get_type_string(parameter));
- account_id = g_variant_get_string(parameter, NULL);
- manager = purple_account_manager_get_default();
- account = purple_account_manager_find_by_id(manager, account_id);
- connection = purple_account_get_connection(account);
- g_clear_object(&account);
- ggp_pubdir_set_info(connection);
-ggp_protocol_actions_get_prefix(G_GNUC_UNUSED PurpleProtocolActions *actions) {
-ggp_protocol_actions_get_action_group(G_GNUC_UNUSED PurpleProtocolActions *actions,
- G_GNUC_UNUSED PurpleConnection *connection)
- GSimpleActionGroup *group = NULL;
- GActionEntry entries[] = {
- .activate = ggp_action_multilogon,
- .name = "broadcasting",
- .activate = ggp_action_status_broadcasting,
- .activate = ggp_action_search,
- .activate = ggp_action_set_info,
- .name = "save-buddylist",
- .activate = ggp_action_buddylist_save,
- .name = "load-buddylist",
- .activate = ggp_action_buddylist_load,
- gsize nentries = G_N_ELEMENTS(entries);
- group = g_simple_action_group_new();
- g_action_map_add_action_entries(G_ACTION_MAP(group), entries, nentries,
- return G_ACTION_GROUP(group);
-ggp_protocol_actions_get_menu(G_GNUC_UNUSED PurpleProtocolActions *actions,
- G_GNUC_UNUSED PurpleConnection *connection) {
- GMenu *menu = NULL, *submenu = NULL;
- GMenuItem *item = NULL;
- item = g_menu_item_new(_("Show other sessions"), "prpl-gg.multilogon");
- g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
- g_menu_append_item(menu, item);
- item = g_menu_item_new(_("Show status only for buddies"),
- "prpl-gg.broadcasting");
- g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
- g_menu_append_item(menu, item);
- item = g_menu_item_new(_("Find buddies..."), "prpl-gg.search");
- g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
- g_menu_append_item(menu, item);
- item = g_menu_item_new(_("Set User Info"), "prpl-gg.set-info");
- g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
- g_menu_append_item(menu, item);
- /* Buddy list management. */
- submenu = g_menu_new();
- item = g_menu_item_new(_("Save to file..."), "prpl-gg.save-buddylist");
- g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
- g_menu_append_item(menu, item);
- item = g_menu_item_new(_("Load from file..."), "prpl-gg.load-buddylist");
- g_menu_item_set_attribute(item, PURPLE_MENU_ATTRIBUTE_DYNAMIC_TARGET, "s",
- g_menu_append_item(menu, item);
- g_menu_append_submenu(menu, _("Buddy list"), G_MENU_MODEL(submenu));
- g_object_unref(submenu);
-ggp_list_emblem(G_GNUC_UNUSED PurpleProtocolClient *client,
- ggp_buddy_data *buddy_data = ggp_buddy_get_data(buddy);
- if (buddy_data->blocked)
- return "not-authorized";
- if (buddy_data->not_a_friend)
-ggp_offline_message(G_GNUC_UNUSED PurpleProtocolClient *client,
- G_GNUC_UNUSED PurpleBuddy *buddy)
-ggp_get_account_text_table(G_GNUC_UNUSED PurpleProtocolClient *client,
- G_GNUC_UNUSED PurpleAccount *account)
- table = g_hash_table_new(g_str_hash, g_str_equal);
- g_hash_table_insert(table, "login_label", (gpointer)_("GG number..."));
-ggp_get_max_message_size(G_GNUC_UNUSED PurpleProtocolClient *client,
- G_GNUC_UNUSED PurpleConversation *conv)
- /* TODO: it may depend on protocol version or other factors */
- return 1200; /* no more than 1232 */
-ggp_protocol_init(G_GNUC_UNUSED GGPProtocol *self) {
-ggp_protocol_class_init(GGPProtocolClass *klass)
- PurpleProtocolClass *protocol_class = PURPLE_PROTOCOL_CLASS(klass);
- protocol_class->login = ggp_login;
- protocol_class->close = ggp_close;
- protocol_class->status_types = ggp_status_types;
- protocol_class->get_account_options = ggp_protocol_get_account_options;
- protocol_class->get_buddy_icon_spec = ggp_protocol_get_buddy_icon_spec;
-ggp_protocol_class_finalize(G_GNUC_UNUSED GGPProtocolClass *klass)
-ggp_protocol_actions_iface_init(PurpleProtocolActionsInterface *iface)
- iface->get_prefix = ggp_protocol_actions_get_prefix;
- iface->get_action_group = ggp_protocol_actions_get_action_group;
- iface->get_menu = ggp_protocol_actions_get_menu;
-ggp_protocol_client_iface_init(PurpleProtocolClientInterface *client_iface)
- client_iface->list_emblem = ggp_list_emblem;
- client_iface->buddy_free = ggp_buddy_free;
- client_iface->normalize = ggp_normalize;
- client_iface->offline_message = ggp_offline_message;
- client_iface->get_account_text_table = ggp_get_account_text_table;
- client_iface->get_max_message_size = ggp_get_max_message_size;
-ggp_protocol_server_iface_init(PurpleProtocolServerInterface *server_iface)
- server_iface->get_info = ggp_pubdir_get_info_protocol;
- server_iface->set_status = ggp_status_set_purplestatus;
- server_iface->add_buddy = ggp_add_buddy;
- server_iface->remove_buddy = ggp_remove_buddy;
- server_iface->keepalive = ggp_keepalive;
- server_iface->alias_buddy = ggp_roster_alias_buddy;
- server_iface->group_buddy = ggp_roster_group_buddy;
- server_iface->rename_group = ggp_roster_rename_group;
- server_iface->set_buddy_icon = ggp_avatar_own_set;
-ggp_protocol_im_iface_init(PurpleProtocolIMInterface *im_iface)
- im_iface->send = ggp_message_send_im;
- im_iface->send_typing = ggp_send_typing;
-ggp_protocol_chat_iface_init(PurpleProtocolChatInterface *chat_iface)
- chat_iface->info = ggp_chat_info;
- chat_iface->info_defaults = ggp_chat_info_defaults;
- chat_iface->join = ggp_chat_join;
- chat_iface->get_name = ggp_chat_get_name;
- chat_iface->invite = ggp_chat_invite;
- chat_iface->leave = ggp_chat_leave;
- chat_iface->send = ggp_chat_send;
- chat_iface->reject = NULL; /* TODO */
-ggp_protocol_roomlist_iface_init(PurpleProtocolRoomlistInterface *roomlist_iface)
- roomlist_iface->get_list = ggp_chat_roomlist_get_list;
-ggp_protocol_xfer_iface_init(PurpleProtocolXferInterface *xfer_iface)
- xfer_iface->can_receive = ggp_edisc_xfer_can_receive_file;
- xfer_iface->send_file = ggp_edisc_xfer_send_file;
- xfer_iface->new_xfer = ggp_edisc_xfer_send_new;
-G_DEFINE_DYNAMIC_TYPE_EXTENDED(
- G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_ACTIONS,
- ggp_protocol_actions_iface_init)
- G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CLIENT,
- ggp_protocol_client_iface_init)
- G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_SERVER,
- ggp_protocol_server_iface_init)
- G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_IM,
- ggp_protocol_im_iface_init)
- G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CHAT,
- ggp_protocol_chat_iface_init)
- G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_ROOMLIST,
- ggp_protocol_roomlist_iface_init)
- G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_XFER,
- ggp_protocol_xfer_iface_init))
-ggp_protocol_new(void) {
- "description", _("Gadu-Gadu is a Polish instant messaging network."),
- "icon-name", "im-gadu-gadu",
- "icon-resource-path", "/im/pidgin/libpurple/gg/icons",
-static GPluginPluginInfo *
-gg_query(G_GNUC_UNUSED GError **error)
- GPluginPluginInfo *info = NULL;
- gchar *description = NULL;
- const gchar * const authors[] = {
- "boler@sourceforge.net",
- description = g_strdup_printf(N_("Polish popular IM\nlibgadu version %s"),
- info = purple_plugin_info_new(
- "name", "Gadu-Gadu Protocol",
- "version", DISPLAY_VERSION,
- "category", N_("Protocol"),
- "summary", N_("Gadu-Gadu Protocol Plugin"),
- "description", description,
- "website", PURPLE_WEBSITE,
- "abi-version", PURPLE_ABI_VERSION,
- "flags", PURPLE_PLUGIN_INFO_FLAGS_INTERNAL |
- PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD,
-gg_load(GPluginPlugin *plugin, GError **error)
- PurpleProtocolManager *manager = purple_protocol_manager_get_default();
- ggp_protocol_register_type(G_TYPE_MODULE(plugin));
- ggp_xfer_register(G_TYPE_MODULE(plugin));
- my_protocol = ggp_protocol_new();
- if(!purple_protocol_manager_register(manager, my_protocol, error)) {
- g_clear_object(&my_protocol);
- purple_prefs_add_none("/plugins/prpl/gg");
- purple_debug_info("gg", "Loading Gadu-Gadu protocol plugin with "
- "libgadu %s...\n", gg_libgadu_version());
- ggp_resolver_purple_setup();
- ggp_servconn_setup(NULL);
- ggp_message_setup_global();
- purple_signal_connect(purple_get_core(), "uri-handler", plugin,
- G_CALLBACK(gg_uri_handler), NULL);
-gg_unload(GPluginPlugin *plugin, G_GNUC_UNUSED gboolean shutdown,
- PurpleProtocolManager *manager = purple_protocol_manager_get_default();
- if(!purple_protocol_manager_unregister(manager, my_protocol, error)) {
- purple_signal_disconnect(purple_get_core(), "uri-handler", plugin,
- G_CALLBACK(gg_uri_handler));
- ggp_servconn_cleanup();
- ggp_message_cleanup_global();
- ggp_libgaduw_cleanup();
- g_clear_object(&my_protocol);
-GPLUGIN_NATIVE_PLUGIN_DECLARE(gg)
-/* vim: set ts=8 sts=0 sw=8 noet: */
--- a/libpurple/protocols/gg/gg.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
- * 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
-#define GGP_UIN_LEN_MAX 10
-#include <libsoup/soup.h>
-#include "message-prpl.h"
-#define GGP_TYPE_PROTOCOL (ggp_protocol_get_type())
-G_DECLARE_FINAL_TYPE(GGPProtocol, ggp_protocol, GGP, PROTOCOL, PurpleProtocol)
- struct gg_session *session;
- gboolean imtoken_warned;
- ggp_image_session_data *image_data;
- ggp_avatar_session_data *avatar_data;
- ggp_roster_session_data roster_data;
- ggp_multilogon_session_data *multilogon_data;
- ggp_status_session_data *status_data;
- ggp_chat_session_data *chat_data;
- ggp_message_session_data *message_data;
- ggp_edisc_session_data *edisc_data;
-ggp_buddy_data * ggp_buddy_get_data(PurpleBuddy *buddy);
-const gchar * ggp_get_imtoken(PurpleConnection *gc);
-uin_t ggp_own_uin(PurpleConnection *gc);
-void ggp_async_login_handler(gpointer _gc, gint fd, PurpleInputCondition cond);
-#endif /* PURPLE_GG_GG_H */
--- a/libpurple/protocols/gg/html.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
- * 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
- * Component written by Tomek Wasilczyk (http://www.wasilczyk.pl).
- * This file is dual-licensed under the GPL2+ and the X11 (MIT) licences.
- * As a recipient of this file you may choose, which license to receive the
- * code under. As a contributor, you have to ensure the new code is
- * compatible with both.
- * 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
-static ggp_html_global_data global_data;
-void ggp_html_setup(void)
- global_data.re_html_attr = g_regex_new(
- "([a-z-]+)=\"([^\"]+)\"",
- G_REGEX_OPTIMIZE, 0, NULL);
- global_data.re_css_attr = g_regex_new(
- G_REGEX_OPTIMIZE, 0, NULL);
- global_data.re_color_hex = g_regex_new(
- "^#([0-9a-fA-F]+){6}$",
- G_REGEX_OPTIMIZE, 0, NULL);
- global_data.re_color_rgb = g_regex_new(
- "^rgb\\(([0-9]+), *([0-9]+), *([0-9]+)\\)$",
- G_REGEX_OPTIMIZE, 0, NULL);
-void ggp_html_cleanup(void)
- g_regex_unref(global_data.re_html_attr);
- g_regex_unref(global_data.re_css_attr);
- g_regex_unref(global_data.re_color_hex);
- g_regex_unref(global_data.re_color_rgb);
-GHashTable * ggp_html_tag_attribs(const gchar *attribs_str)
- GHashTable *attribs = g_hash_table_new_full(g_str_hash, g_str_equal,
- if (attribs_str == NULL)
- g_regex_match(global_data.re_html_attr, attribs_str, 0, &match);
- while (g_match_info_matches(match)) {
- g_hash_table_insert(attribs,
- g_match_info_fetch(match, 1),
- g_match_info_fetch(match, 2));
- g_match_info_next(match, NULL);
- g_match_info_free(match);
-GHashTable * ggp_html_css_attribs(const gchar *attribs_str)
- GHashTable *attribs = g_hash_table_new_full(g_str_hash, g_str_equal,
- if (attribs_str == NULL)
- g_regex_match(global_data.re_css_attr, attribs_str, 0, &match);
- while (g_match_info_matches(match)) {
- g_hash_table_insert(attribs,
- g_match_info_fetch(match, 1),
- g_match_info_fetch(match, 2));
- g_match_info_next(match, NULL);
- g_match_info_free(match);
-int ggp_html_decode_color(const gchar *str)
- g_regex_match(global_data.re_color_hex, str, 0, &match);
- if (g_match_info_matches(match)) {
- if (sscanf(str + 1, "%x", &color) != 1)
- g_match_info_free(match);
- g_regex_match(global_data.re_color_rgb, str, 0, &match);
- if (g_match_info_matches(match)) {
- int r = -1, g = -1, b = -1;
- c_str = g_match_info_fetch(match, 1);
- c_str = g_match_info_fetch(match, 2);
- c_str = g_match_info_fetch(match, 3);
- if (r >= 0 && r < 256 && g >= 0 && g < 256 && b >= 0 && b < 256)
- color = (r << 16) | (g << 8) | b;
- g_match_info_free(match);
-ggp_html_tag ggp_html_parse_tag(const gchar *tag_str)
- if (0 == g_ascii_strcasecmp(tag_str, "eom"))
- return GGP_HTML_TAG_EOM;
- if (0 == g_ascii_strcasecmp(tag_str, "span"))
- return GGP_HTML_TAG_SPAN;
- if (0 == g_ascii_strcasecmp(tag_str, "div"))
- return GGP_HTML_TAG_DIV;
- if (0 == g_ascii_strcasecmp(tag_str, "br"))
- return GGP_HTML_TAG_BR;
- if (0 == g_ascii_strcasecmp(tag_str, "a"))
- if (0 == g_ascii_strcasecmp(tag_str, "b"))
- if (0 == g_ascii_strcasecmp(tag_str, "i"))
- if (0 == g_ascii_strcasecmp(tag_str, "u"))
- if (0 == g_ascii_strcasecmp(tag_str, "s"))
- if (0 == g_ascii_strcasecmp(tag_str, "img"))
- return GGP_HTML_TAG_IMG;
- if (0 == g_ascii_strcasecmp(tag_str, "font"))
- return GGP_HTML_TAG_FONT;
- if (0 == g_ascii_strcasecmp(tag_str, "hr"))
- return GGP_HTML_TAG_HR;
- return GGP_HTML_TAG_UNKNOWN;
--- a/libpurple/protocols/gg/html.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
- * 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
- * Component written by Tomek Wasilczyk (http://www.wasilczyk.pl).
- * This file is dual-licensed under the GPL2+ and the X11 (MIT) licences.
- * As a recipient of this file you may choose, which license to receive the
- * code under. As a contributor, you have to ensure the new code is
- * compatible with both.
- * 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
-#ifndef PURPLE_GG_HTML_H
-#define PURPLE_GG_HTML_H
-void ggp_html_setup(void);
-void ggp_html_cleanup(void);
-GHashTable * ggp_html_tag_attribs(const gchar *attribs_str);
-GHashTable * ggp_html_css_attribs(const gchar *attribs_str);
-int ggp_html_decode_color(const gchar *str);
-ggp_html_tag ggp_html_parse_tag(const gchar *tag_str);
-#endif /* PURPLE_GG_HTML_H */
--- a/libpurple/protocols/gg/image-prpl.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,262 +0,0 @@
- * 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
- * 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>
-struct _ggp_image_session_data
- GHashTable *recv_images;
- GHashTable *sent_images;
- gchar *conv_name; /* TODO: callback */
-static void ggp_image_sent_free(gpointer _sent_image)
- ggp_image_sent *sent_image = _sent_image;
- g_object_unref(sent_image->image);
- g_free(sent_image->conv_name);
-static uint64_t ggp_image_params_to_id(uint32_t crc32, uint32_t size)
- return ((uint64_t)crc32 << 32) | size;
-static inline ggp_image_session_data *
-ggp_image_get_sdata(PurpleConnection *gc)
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- return accdata->image_data;
-void ggp_image_setup(PurpleConnection *gc)
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- ggp_image_session_data *sdata = g_new0(ggp_image_session_data, 1);
- accdata->image_data = sdata;
- sdata->recv_images = g_hash_table_new_full(
- g_int64_hash, g_int64_equal, g_free, g_object_unref);
- sdata->sent_images = g_hash_table_new_full(
- g_int64_hash, g_int64_equal, g_free,
-void ggp_image_cleanup(PurpleConnection *gc)
- ggp_image_session_data *sdata = ggp_image_get_sdata(gc);
- g_hash_table_destroy(sdata->recv_images);
- g_hash_table_destroy(sdata->sent_images);
-ggp_image_prepare_result
-ggp_image_prepare(PurpleConversation *conv, PurpleImage *image, uint64_t *id)
- PurpleConnection *gc = purple_conversation_get_connection(conv);
- ggp_image_session_data *sdata = ggp_image_get_sdata(gc);
- gconstpointer image_data;
- ggp_image_sent *sent_image;
- g_return_val_if_fail(image, GGP_IMAGE_PREPARE_FAILURE);
- image_size = purple_image_get_data_size(image);
- if (image_size > GGP_IMAGE_SIZE_MAX) {
- purple_debug_warning("gg", "ggp_image_prepare: image "
- "is too big (max bytes: %d)\n", GGP_IMAGE_SIZE_MAX);
- return GGP_IMAGE_PREPARE_TOO_BIG;
- image_data = purple_image_get_data(image);
- image_crc = gg_crc32(0, image_data, image_size);
- purple_debug_info("gg", "ggp_image_prepare: image prepared "
- "[crc=%u, size=%" G_GSIZE_FORMAT "]",
- image_crc, image_size);
- *id = ggp_image_params_to_id(image_crc, image_size);
- sent_image = g_new(ggp_image_sent, 1);
- sent_image->image = image;
- sent_image->conv_name = g_strdup(purple_conversation_get_name(conv));
- g_hash_table_insert(sdata->sent_images, ggp_uint64dup(*id),
- return GGP_IMAGE_PREPARE_OK;
-void ggp_image_recv(PurpleConnection *gc,
- const struct gg_event_image_reply *image_reply)
- ggp_image_session_data *sdata = ggp_image_get_sdata(gc);
- id = ggp_image_params_to_id(image_reply->crc32, image_reply->size);
- img = g_hash_table_lookup(sdata->recv_images, &id);
- purple_debug_warning("gg", "ggp_image_recv: "
- "image " GGP_IMAGE_ID_FORMAT " wasn't requested\n",
- purple_debug_info("gg", "ggp_image_recv: got image "
- "[crc=%u, size=%u, filename=%s, id=" GGP_IMAGE_ID_FORMAT "]",
- image_reply->crc32, image_reply->size,
- image_reply->filename, id);
- img = purple_image_new_from_data(
- (const guint8 *)image_reply->image,
- purple_image_set_friendly_filename(img, image_reply->filename);
- g_hash_table_insert(sdata->recv_images, &id, img);
-void ggp_image_send(PurpleConnection *gc,
- const struct gg_event_image_request *image_request)
- PurpleAccount *account = purple_connection_get_account(gc);
- PurpleContactInfo *info = PURPLE_CONTACT_INFO(account);
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- ggp_image_session_data *sdata = ggp_image_get_sdata(gc);
- ggp_image_sent *sent_image;
- PurpleConversation *conv;
- PurpleConversationManager *manager;
- purple_debug_info("gg", "ggp_image_send: got image request "
- "[uin=%u, crc=%u, size=%u]\n",
- id = ggp_image_params_to_id(image_request->crc32, image_request->size);
- sent_image = g_hash_table_lookup(sdata->sent_images, &id);
- sender = ggp_str_to_uin(purple_contact_info_get_username(info));
- if (sent_image == NULL && image_request->sender == sender) {
- purple_debug_misc("gg", "ggp_image_send: requested image "
- "not found, but this may be another session request\n");
- if (sent_image == NULL) {
- purple_debug_warning("gg", "ggp_image_send: requested image "
- purple_debug_misc("gg", "ggp_image_send: requested image found "
- "[id=" GGP_IMAGE_ID_FORMAT ", conv=%s]\n",
- id, sent_image->conv_name);
- g_return_if_fail(sent_image->image);
- /* TODO: check allowed recipients */
- gg_filename = g_strdup_printf(GGP_IMAGE_ID_FORMAT, id);
- gg_image_reply(accdata->session, image_request->sender,
- purple_image_get_data(sent_image->image),
- purple_image_get_data_size(sent_image->image));
- manager = purple_conversation_manager_get_default();
- conv = purple_conversation_manager_find(manager,
- purple_connection_get_account(gc),
- sent_image->conv_name);
- gchar *msg = g_strdup_printf(_("Image delivered to %u."),
- image_request->sender);
- purple_conversation_write_system_message(conv, msg,
- PURPLE_MESSAGE_NO_LOG | PURPLE_MESSAGE_NOTIFY);
-ggp_image_request(PurpleConnection *gc, uin_t uin, uint64_t id)
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- ggp_image_session_data *sdata = ggp_image_get_sdata(gc);
- uint32_t crc = id >> 32;
- if (size > GGP_IMAGE_SIZE_MAX && crc <= GGP_IMAGE_SIZE_MAX) {
- purple_debug_warning("gg", "ggp_image_request: "
- "crc and size are swapped!\n");
- id = ggp_image_params_to_id(crc, size);
- img = g_hash_table_lookup(sdata->recv_images, &id);
- purple_debug_info("gg", "ggp_image_request: "
- "image " GGP_IMAGE_ID_FORMAT " got from cache", id);
- g_hash_table_insert(sdata->recv_images, ggp_uint64dup(id), NULL);
- purple_debug_info("gg", "ggp_image_request: requesting image "
- GGP_IMAGE_ID_FORMAT, id);
- if (gg_image_request(accdata->session, uin, size, crc) != 0)
- purple_debug_error("gg", "ggp_image_request: failed");
--- a/libpurple/protocols/gg/image-prpl.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
- * 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
- * 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
-#ifndef PURPLE_GG_IMAGE_PRPL_H
-#define PURPLE_GG_IMAGE_PRPL_H
-#define GGP_IMAGE_SIZE_MAX 255000
-#define GGP_IMAGE_ID_FORMAT "%016" G_GINT64_MODIFIER "x"
-typedef struct _ggp_image_session_data ggp_image_session_data;
- GGP_IMAGE_PREPARE_OK = 0,
- GGP_IMAGE_PREPARE_FAILURE,
- GGP_IMAGE_PREPARE_TOO_BIG
-} ggp_image_prepare_result;
-ggp_image_setup(PurpleConnection *gc);
-ggp_image_cleanup(PurpleConnection *gc);
-ggp_image_prepare_result
-ggp_image_prepare(PurpleConversation *conv, PurpleImage *image, uint64_t *id);
-ggp_image_recv(PurpleConnection *gc,
- const struct gg_event_image_reply *image_reply);
-ggp_image_send(PurpleConnection *gc,
- const struct gg_event_image_request *image_request);
-ggp_image_request(PurpleConnection *gc, uin_t uin, uint64_t id);
-#endif /* PURPLE_GG_IMAGE_PRPL_H */
--- a/libpurple/protocols/gg/keymapper.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
- * 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
- * Component written by Tomek Wasilczyk (http://www.wasilczyk.pl).
- * This file is dual-licensed under the GPL2+ and the X11 (MIT) licences.
- * As a recipient of this file you may choose, which license to receive the
- * code under. As a contributor, you have to ensure the new code is
- * compatible with both.
- * 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
-/* The problem: we want to convert 64-bit unique integers into unique gpointer
- * keys (that may be 32-bit or 64-bit, or whatever else). We also want to
- * The idea: let's store every value in our internal memory. Then, its address
- * can be also an unique key. We also need a map, to quickly figure out the
- * address for any previously stored value.
- * The naming problem: values becomes the keys and vice-versa.
- * For a 64-bit gpointer, keymapper could just do nothing and return the value
- * as a key. But it have to be figured out at a compile time.
- /* Table keys: pointers to 64-bit mapped *values*.
- * Table values: keys (gpointers) corresponding to mapped values.
- * Ultimately, both keys and values are the same pointers.
- * Yes, it's hard to comment it well enough.
- GHashTable *val_to_key;
- km = g_new0(ggp_keymapper, 1);
- km->val_to_key = g_hash_table_new_full(g_int64_hash, g_int64_equal,
-ggp_keymapper_free(ggp_keymapper *km)
- g_hash_table_destroy(km->val_to_key);
-ggp_keymapper_to_key(ggp_keymapper *km, guint64 val)
- g_return_val_if_fail(km != NULL, NULL);
- key = g_hash_table_lookup(km->val_to_key, &val);
- key = g_new(guint64, 1);
- g_hash_table_insert(km->val_to_key, key, key);
-ggp_keymapper_from_key(ggp_keymapper *km, gpointer key)
- g_return_val_if_fail(km != NULL, 0);
- g_return_val_if_fail(key != NULL, 0);
- return *((guint64*)key);
--- a/libpurple/protocols/gg/keymapper.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
- * 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
- * Component written by Tomek Wasilczyk (http://www.wasilczyk.pl).
- * This file is dual-licensed under the GPL2+ and the X11 (MIT) licences.
- * As a recipient of this file you may choose, which license to receive the
- * code under. As a contributor, you have to ensure the new code is
- * compatible with both.
- * 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
-#ifndef PURPLE_GG_KEYMAPPER_H
-#define PURPLE_GG_KEYMAPPER_H
-typedef struct _ggp_keymapper ggp_keymapper;
-ggp_keymapper_new(void);
-ggp_keymapper_free(ggp_keymapper *km);
-ggp_keymapper_to_key(ggp_keymapper *km, guint64 val);
-/* The key have to be valid. */
-ggp_keymapper_from_key(ggp_keymapper *km, gpointer key);
-#endif /* PURPLE_GG_KEYMAPPER_H */
--- a/libpurple/protocols/gg/libgadu-events.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
- * 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
- * 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 "libgadu-events.h"
-void ggp_events_user_data(PurpleConnection *gc, struct gg_event_user_data *data)
- purple_debug_info("gg", "GG_EVENT_USER_DATA [type=%d, user_count=%"
- G_GSIZE_FORMAT "]\n", data->type, data->user_count);
- 1, 3: user information sent after connecting (divided by
- 20 contacts; 3 - last one; 1 - rest of them)
- is_update = (data->type == 0);
- for (user_idx = 0; user_idx < data->user_count; user_idx++) {
- struct gg_event_user_data_user *data_user =
- &data->users[user_idx];
- uin_t uin = data_user->uin;
- gboolean got_avatar = FALSE;
- for (attr_idx = 0; attr_idx < data_user->attr_count; attr_idx++) {
- struct gg_event_user_data_attr *data_attr =
- &data_user->attrs[attr_idx];
- if (strcmp(data_attr->key, "avatar") == 0) {
- if (data_attr->type == 0) {
- ggp_avatar_buddy_remove(gc, uin);
- timestamp = atoi(data_attr->value);
- ggp_avatar_buddy_update(gc, uin, timestamp);
- if (!is_update && !got_avatar)
- ggp_avatar_buddy_remove(gc, uin);
-static void ggp_events_new_version(const gchar *data)
- /* data = {"severity":"download"} */
- purple_debug_info("gg", "Gadu-Gadu server reports new client version."
-void ggp_events_json(PurpleConnection *gc, struct gg_event_json_event *ev)
- static const gchar *ignored_events[] = {
- "edisc/scope_files_changed",
- "notifications/list", /* gifts */
- if (g_strcmp0("edisc/send_ticket_changed", ev->type) == 0) {
- ggp_edisc_xfer_ticket_changed(gc, ev->data);
- if (g_strcmp0("updates/new-version", ev->type) == 0) {
- ggp_events_new_version(ev->data);
- for (it = ignored_events; *it != NULL; it++) {
- if (g_strcmp0(*it, ev->type) == 0)
- if (purple_debug_is_unsafe() && purple_debug_is_verbose())
- purple_debug_warning("gg", "ggp_events_json: "
- "unhandled event \"%s\": %s\n",
- purple_debug_warning("gg", "ggp_events_json: "
- "unhandled event \"%s\"\n", ev->type);
--- a/libpurple/protocols/gg/libgadu-events.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
- * 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
- * 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
-#ifndef PURPLE_GG_LIBGADU_EVENTS_H
-#define PURPLE_GG_LIBGADU_EVENTS_H
-void ggp_events_user_data(PurpleConnection *gc,
- struct gg_event_user_data *data);
-void ggp_events_json(PurpleConnection *gc, struct gg_event_json_event *ev);
-#endif /* PURPLE_GG_LIBGADU_EVENTS_H */
--- a/libpurple/protocols/gg/libgaduw.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,215 +0,0 @@
- * 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
- * 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
-static void ggp_libgaduw_debug_handler(int level, const char * format,
-/*******************************************************************************
- ******************************************************************************/
-void ggp_libgaduw_setup(void)
- gg_debug_handler = ggp_libgaduw_debug_handler;
-void ggp_libgaduw_cleanup(void)
- gg_debug_handler = NULL;
-/*******************************************************************************
- ******************************************************************************/
-const gchar * ggp_libgaduw_version(PurpleConnection *gc)
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- const gchar *ver = accdata->session->client_version;
- if (ver != NULL && isdigit(ver[0]))
- return GG_DEFAULT_CLIENT_VERSION;
-static void ggp_libgaduw_debug_handler(int level, const char * format,
- PurpleDebugLevel purple_level;
- if ((level & GG_DEBUG_NET) || (level & GG_DEBUG_FUNCTION) ||
- (level & GG_DEBUG_VERBOSE))
- if (!purple_debug_is_verbose())
- if ((level & GG_DEBUG_DUMP) || /* GG session protocol packets */
- (level & GG_DEBUG_TRAFFIC)) /* HTTP traffic */
- if (!purple_debug_is_verbose() || !purple_debug_is_unsafe())
- /* Don't use glib's printf family, since it might not support
- * system-specific formatting modifiers (like %Iu for size on win32). */
- ret = vsnprintf(msgbuff, sizeof(msgbuff) / sizeof(char), format, args);
- purple_debug_error("gg",
- "failed to printf the following message: %s",
- format ? format : "(null)");
- if (level & GG_DEBUG_ERROR)
- purple_level = PURPLE_DEBUG_ERROR;
- else if (level & GG_DEBUG_WARNING)
- purple_level = PURPLE_DEBUG_WARNING;
- purple_level = PURPLE_DEBUG_MISC;
- purple_debug(purple_level, "gg", "%s", msgbuff);
-/*******************************************************************************
- ******************************************************************************/
-static void ggp_libgaduw_http_processing_cancel(PurpleConnection *gc,
-static void ggp_libgaduw_http_handler(gpointer _req, gint fd,
- PurpleInputCondition cond);
-static void ggp_libgaduw_http_finish(ggp_libgaduw_http_req *req,
-/******************************************************************************/
-ggp_libgaduw_http_req * ggp_libgaduw_http_watch(PurpleConnection *gc,
- struct gg_http *h, ggp_libgaduw_http_cb cb,
- gpointer user_data, gboolean show_processing)
- ggp_libgaduw_http_req *req;
- purple_debug_misc("gg", "ggp_libgaduw_http_watch(h=%p, "
- "show_processing=%d)\n", h, show_processing);
- req = g_new(ggp_libgaduw_http_req, 1);
- req->user_data = user_data;
- req->cancelled = FALSE;
- req->processing = NULL;
- req->processing = ggp_purplew_request_processing(gc, NULL,
- req, ggp_libgaduw_http_processing_cancel);
- req->inpa = ggp_purplew_http_input_add(h, ggp_libgaduw_http_handler,
-ggp_libgaduw_http_processing_cancel(G_GNUC_UNUSED PurpleConnection *gc,
- ggp_libgaduw_http_req *req = _req;
- req->processing = NULL;
- ggp_libgaduw_http_cancel(req);
-ggp_libgaduw_http_handler(gpointer _req, G_GNUC_UNUSED gint fd,
- G_GNUC_UNUSED PurpleInputCondition cond)
- ggp_libgaduw_http_req *req = _req;
- if (req->h->callback(req->h) == -1 || req->h->state == GG_STATE_ERROR) {
- purple_debug_error("gg", "ggp_libgaduw_http_handler: failed to "
- "make http request: %d\n", req->h->error);
- ggp_libgaduw_http_finish(req, FALSE);
- if (purple_debug_is_verbose()) {
- purple_debug_misc("gg", "ggp_libgaduw_http_handler: got fd "
- "update [check=%d, state=%d]\n", req->h->check,
- if (req->h->state != GG_STATE_DONE) {
- g_source_remove(req->inpa);
- req->inpa = ggp_purplew_http_input_add(req->h,
- ggp_libgaduw_http_handler, req);
- if (!req->h->data || !req->h->body) {
- purple_debug_error("gg", "ggp_libgaduw_http_handler: got empty "
- "http response: %d\n", req->h->error);
- ggp_libgaduw_http_finish(req, FALSE);
- ggp_libgaduw_http_finish(req, TRUE);
-void ggp_libgaduw_http_cancel(ggp_libgaduw_http_req *req)
- purple_debug_misc("gg", "ggp_libgaduw_http_cancel\n");
- ggp_libgaduw_http_finish(req, FALSE);
-static void ggp_libgaduw_http_finish(ggp_libgaduw_http_req *req,
- purple_debug_misc("gg", "ggp_libgaduw_http_finish(h=%p, processing=%p):"
- " success=%d\n", req->h, req->processing, success);
- ggp_purplew_request_processing_done(req->processing);
- req->processing = NULL;
- g_source_remove(req->inpa);
- req->cb(req->h, success, req->cancelled, req->user_data);
- req->h->destroy(req->h);
--- a/libpurple/protocols/gg/libgaduw.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
- * 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
- * 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
-#ifndef PURPLE_GG_LIBGADUW_H
-#define PURPLE_GG_LIBGADUW_H
-typedef void (*ggp_libgaduw_http_cb)(struct gg_http *h, gboolean success,
- gboolean cancelled, gpointer user_data);
- ggp_libgaduw_http_cb cb;
- ggp_purplew_request_processing_handle *processing;
-} ggp_libgaduw_http_req;
-void ggp_libgaduw_setup(void);
-void ggp_libgaduw_cleanup(void);
-const gchar * ggp_libgaduw_version(PurpleConnection *gc);
-ggp_libgaduw_http_req * ggp_libgaduw_http_watch(PurpleConnection *gc,
- struct gg_http *h, ggp_libgaduw_http_cb cb, gpointer user_data,
- gboolean show_processing);
-void ggp_libgaduw_http_cancel(ggp_libgaduw_http_req *req);
-#endif /* PURPLE_GG_LIBGADUW_H */
--- a/libpurple/protocols/gg/meson.build Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
- 'oauth/oauth-purple.c',
- gg_resources = gnome.compile_resources('ggresource',
- 'resources/gg.gresource.xml',
- source_dir : 'resources',
- GG_SOURCES += gg_resources
- shared_library('gg', GG_SOURCES,
- c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="Purple-GaduGadu"'],
- gnu_symbol_visibility : 'hidden',
- dependencies : [libgadu, json, libpurple_dep, libsoup, glib],
- install : true, install_dir : PURPLE_PLUGINDIR)
- devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir())
--- a/libpurple/protocols/gg/message-prpl.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,699 +0,0 @@
- * 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
- * Component written by Tomek Wasilczyk (http://www.wasilczyk.pl).
- * This file is dual-licensed under the GPL2+ and the X11 (MIT) licences.
- * As a recipient of this file you may choose, which license to receive the
- * code under. As a contributor, you have to ensure the new code is
- * compatible with both.
- * 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 "message-prpl.h"
-#define GGP_GG10_DEFAULT_FORMAT "<span style=\"color:#000000; " \
- "font-family:'MS Shell Dlg 2'; font-size:9pt; \">"
-#define GGP_GG10_DEFAULT_FORMAT_REPLACEMENT "<span>"
-#define GGP_GG11_FORCE_COMPAT FALSE
- GGP_MESSAGE_GOT_TYPE_IM,
- GGP_MESSAGE_GOT_TYPE_CHAT,
- GGP_MESSAGE_GOT_TYPE_MULTILOGON
-} ggp_message_global_data;
-static ggp_message_global_data global_data;
-struct _ggp_message_session_data
-static ggp_font * ggp_font_new(void);
-static ggp_font * ggp_font_clone(ggp_font *font);
-static void ggp_font_free(gpointer font);
-static PurpleConversation * ggp_message_get_conv(PurpleConnection *gc,
-static void ggp_message_got_data_free(ggp_message_got_data *msg);
-static void ggp_message_got_display(PurpleConnection *gc,
- ggp_message_got_data *msg);
-static void ggp_message_format_from_gg(ggp_message_got_data *msg,
-void ggp_message_setup_global(void)
- global_data.re_html_tag = g_regex_new(
- "<(/)?([a-zA-Z]+)( [^>]+)?>",
- G_REGEX_OPTIMIZE, 0, NULL);
- global_data.re_gg_img = g_regex_new(
- "<img name=\"([0-9a-fA-F]+)\"/?>",
- G_REGEX_OPTIMIZE, 0, NULL);
-void ggp_message_cleanup_global(void)
- g_regex_unref(global_data.re_html_tag);
- g_regex_unref(global_data.re_gg_img);
-static inline ggp_message_session_data *
-ggp_message_get_sdata(PurpleConnection *gc)
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- return accdata->message_data;
-void ggp_message_setup(PurpleConnection *gc)
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- ggp_message_session_data *sdata = g_new0(ggp_message_session_data, 1);
- accdata->message_data = sdata;
-void ggp_message_cleanup(PurpleConnection *gc)
- ggp_message_session_data *sdata = ggp_message_get_sdata(gc);
-static ggp_font * ggp_font_new(void)
- font = g_new0(ggp_font, 1);
-static ggp_font * ggp_font_clone(ggp_font * font)
- ggp_font *clone = g_new0(ggp_font, 1);
- clone->face = g_strdup(font->face);
-static void ggp_font_free(gpointer _font)
- ggp_font *font = _font;
-static PurpleConversation * ggp_message_get_conv(PurpleConnection *gc,
- PurpleAccount *account = purple_connection_get_account(gc);
- PurpleConversation *im;
- PurpleConversationManager *manager;
- const gchar *who = ggp_uin_to_str(uin);
- manager = purple_conversation_manager_get_default();
- im = purple_conversation_manager_find_im(manager, account, who);
- im = purple_im_conversation_new(account, who);
-static void ggp_message_got_data_free(ggp_message_got_data *msg)
-void ggp_message_got(PurpleConnection *gc, const struct gg_event_msg *ev)
- ggp_message_got_data *msg = g_new0(ggp_message_got_data, 1);
- msg->user = ev->sender;
- if (ev->chat_id != 0) {
- msg->type = GGP_MESSAGE_GOT_TYPE_CHAT;
- msg->chat_id = ev->chat_id;
- msg->type = GGP_MESSAGE_GOT_TYPE_IM;
- ggp_message_format_from_gg(msg, ev->xhtml_message);
- ggp_message_got_display(gc, msg);
- ggp_message_got_data_free(msg);
-void ggp_message_got_multilogon(PurpleConnection *gc,
- const struct gg_event_msg *ev)
- ggp_message_got_data *msg = g_new0(ggp_message_got_data, 1);
- msg->user = ev->sender; /* not really a sender*/
- if (ev->chat_id != 0) {
- msg->type = GGP_MESSAGE_GOT_TYPE_CHAT;
- msg->chat_id = ev->chat_id;
- msg->type = GGP_MESSAGE_GOT_TYPE_MULTILOGON;
- ggp_message_format_from_gg(msg, ev->xhtml_message);
- ggp_message_got_display(gc, msg);
- ggp_message_got_data_free(msg);
-static void ggp_message_got_display(PurpleConnection *gc,
- ggp_message_got_data *msg)
- if (msg->type == GGP_MESSAGE_GOT_TYPE_IM) {
- purple_serv_got_im(gc, ggp_uin_to_str(msg->user), msg->text,
- PURPLE_MESSAGE_RECV, msg->time);
- } else if (msg->type == GGP_MESSAGE_GOT_TYPE_CHAT) {
- ggp_chat_got_message(gc, msg->chat_id, msg->text, msg->time,
- } else if (msg->type == GGP_MESSAGE_GOT_TYPE_MULTILOGON) {
- PurpleAccount *account = NULL;
- PurpleContactInfo *info = NULL;
- PurpleConversation *im = ggp_message_get_conv(gc, msg->user);
- const gchar *me = NULL;
- account = purple_connection_get_account(gc);
- info = PURPLE_CONTACT_INFO(account);
- me = purple_contact_info_get_name_for_display(info);
- pmsg = purple_message_new_outgoing(me, NULL, msg->text, 0);
- dt = g_date_time_new_from_unix_local((gint64)msg->time);
- purple_message_set_timestamp(pmsg, dt);
- purple_conversation_write_message(im, pmsg);
- purple_debug_error("gg", "ggp_message_got_display: "
- "unexpected message type: %d\n", msg->type);
-static gboolean ggp_message_format_from_gg_found_img(const GMatchInfo *info,
- GString *res, gpointer data)
- ggp_message_got_data *msg = data;
- gchar *name, *replacement;
- name = g_match_info_fetch(info, 1);
- if (sscanf(name, "%" G_GINT64_MODIFIER "x", &id) != 1)
- /* TODO: stock broken image? */
- g_string_append_printf(res, "[%s]", _("broken image"));
- image = ggp_image_request(msg->gc, msg->user, id);
- purple_debug_warning("gg", "ggp_message_format_from_gg_"
- "found_img: couldn't request image");
- g_string_append_printf(res, "[%s]", _("broken image"));
- image_id = purple_image_store_add_weak(image);
- replacement = g_strdup_printf("<img src=\""
- PURPLE_IMAGE_STORE_PROTOCOL "%u\">", image_id);
- g_string_append(res, replacement);
-static void ggp_message_format_from_gg(ggp_message_got_data *msg,
- msg->text = g_strdup("");
- text_new = g_strdup(text);
- purple_str_strip_char(text_new, '\r');
- text_new = purple_strreplace(text_new, GGP_GG10_DEFAULT_FORMAT,
- GGP_GG10_DEFAULT_FORMAT_REPLACEMENT);
- text_new = g_regex_replace_eval(global_data.re_gg_img, text_new, -1, 0,
- 0, ggp_message_format_from_gg_found_img, msg, NULL);
-ggp_message_format_to_gg(PurpleConversation *conv, const gchar *text)
- GString *reformatted_text = NULL;
- GString *pending_objects = NULL;
- GList *font_stack = NULL;
- static int html_sizes_pt[7] = { 7, 8, 9, 10, 12, 14, 16 };
- ggp_font *font_new, *font_current, *font_base;
- gboolean font_changed = FALSE;
- gboolean in_any_tag = FALSE;
- if (purple_debug_is_verbose())
- purple_debug_info("gg", "ggp formatting text: [%s]", text);
- font_base = ggp_font_new();
- font_current = ggp_font_new();
- font_new = ggp_font_new();
- /* GG11 doesn't use nbsp, it just print spaces */
- text_new = purple_strreplace(text, " ", " ");
- /* add end-of-message tag */
- if (strstr(text_new, "<eom>") != NULL) {
- text_new = purple_strreplace(text_new, "<eom>", "");
- purple_debug_warning("gg", "ggp_message_format_to_gg: "
- "unexpected <eom> tag\n");
- text_new = g_strdup_printf("%s<eom></eom>", text_new);
- reformatted_text = g_string_new(NULL);
- pending_objects = g_string_new(NULL);
- g_regex_match(global_data.re_html_tag, text_new, 0, &match);
- while (g_match_info_matches(match)) {
- int m_start, m_end, m_pos;
- gchar *tag_str, *attribs_str;
- /* reading tag and its contents */
- g_match_info_fetch_pos(match, 0, &m_start, &m_end);
- g_assert(m_start >= 0 && m_end >= 0);
- text_before = ((guint)m_start > pos);
- g_match_info_fetch_pos(match, 1, &m_pos, NULL);
- tag_close = (m_pos >= 0);
- tag_str = g_match_info_fetch(match, 2);
- tag = ggp_html_parse_tag(tag_str);
- attribs_str = g_match_info_fetch(match, 3);
- g_match_info_next(match, NULL);
- if (tag == GGP_HTML_TAG_UNKNOWN) {
- "ggp_message_format_to_gg: unknown tag %s",
- /* closing *all* formatting-related tags (GG11 weirdness)
- * and adding pending objects */
- if ((text_before && (font_changed || pending_objects->len > 0)) ||
- (tag == GGP_HTML_TAG_EOM && tag_close)) {
- if (font_current->s && !GGP_GG11_FORCE_COMPAT) {
- g_string_append(reformatted_text, "</s>");
- g_string_append(reformatted_text, "</u>");
- g_string_append(reformatted_text, "</i>");
- g_string_append(reformatted_text, "</b>");
- g_string_append(reformatted_text, "</span>");
- if (pending_objects->len > 0) {
- g_string_append(reformatted_text, pending_objects->str);
- g_string_truncate(pending_objects, 0);
- /* opening formatting-related tags again */
- if (text_before && !in_any_tag) {
- gboolean has_size = (font_new->size > 0 &&
- font_new->size <= 7 && font_new->size != 3);
- has_size || font_new->face ||
- (font_new->bgcolor >= 0 && !GGP_GG11_FORCE_COMPAT) ||
- g_string_append(reformatted_text, "<span style=\"");
- g_string_append_printf(reformatted_text, "font-size:%dpt;",
- html_sizes_pt[font_new->size - 1]);
- g_string_append_printf(reformatted_text, "font-family:%s;",
- if (font_new->bgcolor >= 0 && !GGP_GG11_FORCE_COMPAT) {
- g_string_append_printf(reformatted_text,
- "background-color:#%06x;",
- if (font_new->color >= 0) {
- g_string_append_printf(reformatted_text, "color:#%06x;",
- g_string_append(reformatted_text, "\">");
- g_string_append(reformatted_text, "<span>");
- g_string_append(reformatted_text, "<b>");
- g_string_append(reformatted_text, "<i>");
- g_string_append(reformatted_text, "<u>");
- if (font_new->s && !GGP_GG11_FORCE_COMPAT) {
- g_string_append(reformatted_text, "<s>");
- ggp_font_free(font_current);
- font_current = font_new;
- font_new = ggp_font_clone(font_current);
- g_string_append_len(reformatted_text, text_new + pos,
- /* set formatting of a following text */
- if (tag == GGP_HTML_TAG_B) {
- font_changed |= (font_new->b != !tag_close);
- font_new->b = !tag_close;
- } else if (tag == GGP_HTML_TAG_I) {
- font_changed |= (font_new->i != !tag_close);
- font_new->i = !tag_close;
- } else if (tag == GGP_HTML_TAG_U) {
- font_changed |= (font_new->u != !tag_close);
- font_new->u = !tag_close;
- } else if (tag == GGP_HTML_TAG_S) {
- font_changed |= (font_new->s != !tag_close);
- font_new->s = !tag_close;
- } else if (tag == GGP_HTML_TAG_IMG && !tag_close) {
- GHashTable *attribs = ggp_html_tag_attribs(attribs_str);
- ggp_image_prepare_result res = -1;
- PurpleImage *image = NULL;
- val = g_hash_table_lookup(attribs, "src");
- image = purple_image_store_get_from_uri(val);
- res = ggp_image_prepare(conv, image, &id);
- if (res == GGP_IMAGE_PREPARE_OK) {
- g_string_append_printf(pending_objects,
- "<img name=\"" GGP_IMAGE_ID_FORMAT "\">",
- } else if (res == GGP_IMAGE_PREPARE_TOO_BIG) {
- purple_conversation_write_system_message(conv,
- _("Image is too large, please try "
- "smaller one."), PURPLE_MESSAGE_ERROR);
- purple_conversation_write_system_message(conv,
- _("Image cannot be sent."),
- g_hash_table_destroy(attribs);
- } else if (tag == GGP_HTML_TAG_FONT && !tag_close) {
- GHashTable *attribs = ggp_html_tag_attribs(attribs_str);
- font_stack = g_list_prepend(font_stack,
- ggp_font_clone(font_new));
- if ((val = g_hash_table_lookup(attribs, "size")) != NULL
- && val[0] >= '1' && val[0] <= '7' &&
- int size = val[0] - '0';
- font_changed |= (font_new->size != size);
- if ((val = g_hash_table_lookup(attribs, "face"))
- (g_strcmp0(font_new->face, val) != 0);
- g_free(font_new->face);
- font_new->face = g_strdup(val);
- if ((val = g_hash_table_lookup(attribs, "color"))
- != NULL && val[0] == '#' && strlen(val) == 7)
- int color = ggp_html_decode_color(val);
- font_changed |= (font_new->color != color);
- font_new->color = color;
- g_hash_table_destroy(attribs);
- else if ((tag == GGP_HTML_TAG_SPAN || tag == GGP_HTML_TAG_DIV)
- GHashTable *attribs, *styles = NULL;
- attribs = ggp_html_tag_attribs(attribs_str);
- font_stack = g_list_prepend(font_stack,
- ggp_font_clone(font_new));
- if (tag == GGP_HTML_TAG_DIV) {
- g_string_append(pending_objects, "<br>");
- style = g_hash_table_lookup(attribs, "style");
- styles = ggp_html_css_attribs(style);
- if (styles && (val = g_hash_table_lookup(styles,
- "background-color")) != NULL)
- int color = ggp_html_decode_color(val);
- font_changed |= (font_new->bgcolor != color);
- font_new->bgcolor = color;
- if (styles && (val = g_hash_table_lookup(styles,
- int color = ggp_html_decode_color(val);
- font_changed |= (font_new->color != color);
- font_new->color = color;
- g_clear_pointer(&styles, g_hash_table_destroy);
- g_hash_table_destroy(attribs);
- else if ((tag == GGP_HTML_TAG_FONT || tag == GGP_HTML_TAG_SPAN
- || tag == GGP_HTML_TAG_DIV) && tag_close)
- ggp_font_free(font_new);
- font_new = (ggp_font*)font_stack->data;
- font_stack = g_list_delete_link(
- font_stack, font_stack);
- font_new = ggp_font_clone(font_base);
- } else if (tag == GGP_HTML_TAG_BR) {
- g_string_append(pending_objects, "<br>");
- } else if (tag == GGP_HTML_TAG_HR) {
- g_string_append(pending_objects, "<br><span>---</span><br>");
- } else if (tag == GGP_HTML_TAG_A || tag == GGP_HTML_TAG_EOM) {
- } else if (tag == GGP_HTML_TAG_UNKNOWN) {
- "ggp_message_format_to_gg: unknown tag %s",
- purple_debug_error("gg", "ggp_message_format_to_gg: "
- "not handled tag %s\n", tag_str);
- g_match_info_free(match);
- if (pos < strlen(text_new) || in_any_tag) {
- "ggp_message_format_to_gg: end of message not reached");
- /* releasing fonts resources */
- ggp_font_free(font_new);
- ggp_font_free(font_current);
- ggp_font_free(font_base);
- g_list_free_full(font_stack, ggp_font_free);
- /* combining reformatted text info one string */
- g_string_free(pending_objects, TRUE);
- text_new = g_string_free(reformatted_text, FALSE);
- if (purple_debug_is_verbose())
- purple_debug_info("gg", "reformatted text: [%s]", text_new);
-ggp_message_send_im(G_GNUC_UNUSED PurpleProtocolIM *pim,
- G_GNUC_UNUSED PurpleConversation *conversation,
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- PurpleConversation *im;
- PurpleConversationManager *manager;
- ggp_buddy_data *buddy_data;
- const gchar *rcpt = purple_message_get_recipient(msg);
- /* TODO: return -ENOTCONN, if not connected */
- if (purple_message_is_empty(msg))
- buddy_data = ggp_buddy_get_data(purple_blist_find_buddy(
- purple_connection_get_account(gc), rcpt));
- if (buddy_data->blocked)
- manager = purple_conversation_manager_get_default();
- im = purple_conversation_manager_find_im(manager,
- purple_connection_get_account(gc),
- gg_msg = ggp_message_format_to_gg(im,
- purple_message_get_contents(msg));
- /* TODO: splitting messages */
- if (strlen(gg_msg) > GG_MSG_MAXSIZE) {
- succ = (gg_send_message_html(info->session, GG_CLASS_CHAT,
- ggp_str_to_uin(rcpt), (unsigned char *)gg_msg) >= 0);
--- a/libpurple/protocols/gg/message-prpl.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
- * 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
- * Component written by Tomek Wasilczyk (http://www.wasilczyk.pl).
- * This file is dual-licensed under the GPL2+ and the X11 (MIT) licences.
- * As a recipient of this file you may choose, which license to receive the
- * code under. As a contributor, you have to ensure the new code is
- * compatible with both.
- * 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
-#ifndef PURPLE_GG_MESSAGE_PRPL_H
-#define PURPLE_GG_MESSAGE_PRPL_H
-typedef struct _ggp_message_session_data ggp_message_session_data;
-void ggp_message_setup_global(void);
-void ggp_message_cleanup_global(void);
-void ggp_message_setup(PurpleConnection *gc);
-void ggp_message_cleanup(PurpleConnection *gc);
-void ggp_message_got(PurpleConnection *gc, const struct gg_event_msg *ev);
-void ggp_message_got_multilogon(PurpleConnection *gc,
- const struct gg_event_msg *ev);
-int ggp_message_send_im(PurpleProtocolIM *im, PurpleConnection *gc, PurpleConversation *conversation, PurpleMessage *msg);
-gchar * ggp_message_format_to_gg(PurpleConversation *conv, const gchar *text);
-#endif /* PURPLE_GG_MESSAGE_PRPL_H */
--- a/libpurple/protocols/gg/multilogon.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,264 +0,0 @@
- * 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
- * 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 "message-prpl.h"
-} ggp_multilogon_session_info;
-struct _ggp_multilogon_session_data
- ggp_multilogon_session_info *sessions;
- PurpleRequestDatasheet *sheet_handle;
- gpointer dialog_handle;
- ggp_keymapper *sid_mapper;
-static inline ggp_multilogon_session_data *
-ggp_multilogon_get_mldata(PurpleConnection *gc);
-static inline ggp_multilogon_session_data *
-ggp_multilogon_get_mldata(PurpleConnection *gc)
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- return accdata->multilogon_data;
-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();
-ggp_multilogon_free_sessions(PurpleConnection *gc)
- ggp_multilogon_session_data *mldata = ggp_multilogon_get_mldata(gc);
- for (i = 0; i < mldata->session_count; i++) {
- g_free(mldata->sessions[i].name);
- g_clear_pointer(&mldata->sessions[i].logon_time, g_date_time_unref);
- g_free(mldata->sessions);
- mldata->sessions = NULL;
- mldata->session_count = 0;
-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);
-ggp_multilogon_sid_from_libgadu(gg_multilogon_id_t lsid)
- memcpy(&sid, lsid.id, sizeof(uint64_t));
-ggp_multilogon_sid_to_libgadu(uint64_t sid, gg_multilogon_id_t *lsid)
- g_return_if_fail(lsid != NULL);
- memcpy(lsid->id, &sid, sizeof(uint64_t));
-ggp_multilogon_fill_sessions(PurpleRequestDatasheet *sheet,
- ggp_multilogon_session_data *mldata = ggp_multilogon_get_mldata(gc);
- ggp_keymapper *km = mldata->sid_mapper;
- 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));
- tmp = g_date_time_format(sess->logon_time, "%c");
- purple_request_datasheet_record_set_string_data(rec, 1, tmp);
- purple_request_datasheet_record_set_string_data(rec, 2, sess->name);
- purple_request_datasheet_record_remove_marked(sheet);
-ggp_multilogon_info(PurpleConnection *gc, struct gg_event_multilogon_info *info)
- ggp_multilogon_session_data *mldata = ggp_multilogon_get_mldata(gc);
- 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 = g_date_time_new_from_unix_local(lsess->logon_time);
- mldata->session_count = info->count;
- if (mldata->sheet_handle != NULL)
- ggp_multilogon_fill_sessions(mldata->sheet_handle, gc);
-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);
- gg_multilogon_id_t lsid;
- key = purple_request_datasheet_record_get_key(rec);
- sid = ggp_keymapper_from_key(mldata->sid_mapper, key);
- ggp_multilogon_sid_to_libgadu(sid, &lsid);
- gg_multilogon_disconnect(accdata->session, lsid);
- purple_request_datasheet_record_remove(
- purple_request_datasheet_record_get_datasheet(rec), key);
-ggp_multilogin_close_request(ggp_multilogon_session_data *mldata)
- mldata->sheet_handle = NULL;
- mldata->dialog_handle = NULL;
-ggp_multilogon_dialog(PurpleConnection *gc)
- ggp_multilogon_session_data *mldata = ggp_multilogon_get_mldata(gc);
- PurpleRequestField *field;
- PurpleRequestPage *page;
- PurpleRequestGroup *group;
- PurpleRequestCommonParameters *cpar;
- PurpleRequestDatasheet *sheet;
- PurpleRequestDatasheetAction *action;
- gpointer dialog_handle;
- if (mldata->dialog_handle != NULL)
- page = purple_request_page_new();
- group = purple_request_group_new(NULL);
- purple_request_page_add_group(page, 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_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, page,
- NULL, NULL, _("Close"), NULL,
- mldata->sheet_handle = sheet;
- mldata->dialog_handle = dialog_handle;
- purple_request_add_close_notify(dialog_handle,
- (GDestroyNotify)ggp_multilogin_close_request, mldata);
--- a/libpurple/protocols/gg/multilogon.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
- * 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
- * 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
-#ifndef PURPLE_GG_MULTILOGON_H
-#define PURPLE_GG_MULTILOGON_H
-typedef struct _ggp_multilogon_session_data ggp_multilogon_session_data;
-void ggp_multilogon_setup(PurpleConnection *gc);
-void ggp_multilogon_cleanup(PurpleConnection *gc);
-void ggp_multilogon_info(PurpleConnection *gc,
- struct gg_event_multilogon_info *msg);
-void ggp_multilogon_dialog(PurpleConnection *gc);
-#endif /* PURPLE_GG_MULTILOGON_H */
--- a/libpurple/protocols/gg/oauth/oauth-purple.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,301 +0,0 @@
- * 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
- * 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 "oauth-purple.h"
-#define GGP_OAUTH_RESPONSE_MAX 10240
- ggp_oauth_request_cb callback;
- gchar *sign_method, *sign_url;
-static void ggp_oauth_data_free(ggp_oauth_data *data)
- g_object_unref(data->msg);
- g_free(data->token_secret);
- g_free(data->sign_method);
- g_free(data->sign_url);
-ggp_oauth_access_token_got(GObject *source, GAsyncResult *result,
- ggp_oauth_data *data = user_data;
- GBytes *response_body = NULL;
- const char *buffer = NULL;
- gchar *token = NULL, *token_secret = NULL;
- response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
- if(response_body == NULL) {
- purple_debug_error("gg", "ggp_oauth_access_token_got: failed: %s",
- ggp_oauth_data_free(data);
- buffer = g_bytes_get_data(response_body, &size);
- xml = purple_xmlnode_from_str(buffer, size);
- g_bytes_unref(response_body);
- purple_debug_error("gg", "ggp_oauth_access_token_got: invalid xml");
- ggp_oauth_data_free(data);
- succ &= ggp_xml_get_string(xml, "oauth_token", &token);
- succ &= ggp_xml_get_string(xml, "oauth_token_secret", &token_secret);
- purple_xmlnode_free(xml);
- if (!succ || strlen(token) < 10) {
- purple_debug_error("gg", "ggp_oauth_access_token_got: invalid xml - "
- "token is not present");
- ggp_oauth_data_free(data);
- PurpleAccount *account;
- PurpleContactInfo *info = NULL;
- purple_debug_misc("gg", "ggp_oauth_access_token_got: got access token, "
- "returning signed url");
- account = purple_connection_get_account(data->gc);
- info = PURPLE_CONTACT_INFO(account);
- auth = gg_oauth_generate_header(
- data->sign_method, data->sign_url,
- purple_contact_info_get_username(info),
- purple_connection_get_password(data->gc), token, token_secret);
- data->callback(data->gc, auth, data->user_data);
- "ggp_oauth_access_token_got: got access token, returning it");
- data->callback(data->gc, token, data->user_data);
- ggp_oauth_data_free(data);
-ggp_oauth_authorization_done(GObject *source,
- G_GNUC_UNUSED GAsyncResult *result,
- ggp_oauth_data *data = user_data;
- PurpleAccount *account;
- PurpleContactInfo *info = NULL;
- SoupStatus status_code;
- SoupMessage *msg = NULL;
- const char *method = "POST";
- const char *url = "http://api.gadu-gadu.pl/access_token";
- PURPLE_ASSERT_CONNECTION_IS_VALID(data->gc);
- account = purple_connection_get_account(data->gc);
- info = PURPLE_CONTACT_INFO(account);
- status_code = soup_message_get_status(data->msg);
- if (status_code != 302) {
- purple_debug_error("gg",
- "ggp_oauth_authorization_done: failed (code = %d)",
- ggp_oauth_data_free(data);
- purple_debug_misc("gg", "ggp_oauth_authorization_done: authorization done, "
- "requesting access token...");
- auth = gg_oauth_generate_header(method, url,
- purple_contact_info_get_username(info),
- purple_connection_get_password(data->gc),
- data->token, data->token_secret);
- g_clear_object(&data->msg);
- data->msg = msg = soup_message_new(method, url);
- // purple_http_request_set_max_len(req, GGP_OAUTH_RESPONSE_MAX);
- soup_message_headers_replace(soup_message_get_request_headers(msg),
- "Authorization", auth);
- soup_session_send_and_read_async(SOUP_SESSION(source), msg,
- G_PRIORITY_DEFAULT, NULL,
- ggp_oauth_access_token_got, data);
-ggp_oauth_request_token_got(GObject *source, GAsyncResult *result,
- SoupSession *session = SOUP_SESSION(source);
- ggp_oauth_data *data = user_data;
- GBytes *response_body = NULL;
- const char *buffer = NULL;
- PurpleAccount *account;
- SoupMessage *msg = NULL;
- PURPLE_ASSERT_CONNECTION_IS_VALID(data->gc);
- account = purple_connection_get_account(data->gc);
- if(!SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(data->msg))) {
- purple_debug_error("gg", "ggp_oauth_request_token_got: "
- "requested token not received\n");
- ggp_oauth_data_free(data);
- response_body = soup_session_send_and_read_finish(session, result, &error);
- if(response_body == NULL) {
- purple_debug_error("gg", "ggp_oauth_access_token_got: failed: %s",
- ggp_oauth_data_free(data);
- purple_debug_misc("gg", "ggp_oauth_request_token_got: "
- "got request token, doing authorization...\n");
- buffer = g_bytes_get_data(response_body, &size);
- xml = purple_xmlnode_from_str(buffer, size);
- g_bytes_unref(response_body);
- purple_debug_error("gg", "ggp_oauth_request_token_got: "
- ggp_oauth_data_free(data);
- succ &= ggp_xml_get_string(xml, "oauth_token", &data->token);
- succ &= ggp_xml_get_string(xml, "oauth_token_secret",
- purple_xmlnode_free(xml);
- purple_debug_error("gg", "ggp_oauth_request_token_got: "
- "invalid xml - token is not present\n");
- ggp_oauth_data_free(data);
- request_data = g_strdup_printf(
- "callback_url=http://www.mojageneracja.pl&request_token=%s&"
- "uin=%s&password=%s", data->token,
- purple_contact_info_get_username(PURPLE_CONTACT_INFO(account)),
- purple_connection_get_password(data->gc));
- g_clear_object(&data->msg);
- data->msg = msg = soup_message_new("POST",
- "https://login.gadu-gadu.pl/authorize");
- // purple_http_request_set_max_len(msg, GGP_OAUTH_RESPONSE_MAX);
- /* we don't need any results, nor 302 redirection */
- soup_message_set_flags(msg, SOUP_MESSAGE_NO_REDIRECT);
- body = g_bytes_new_take(request_data, strlen(request_data));
- soup_message_set_request_body_from_bytes(msg,
- "application/x-www-form-urlencoded",
- soup_session_send_and_read_async(session, msg, G_PRIORITY_DEFAULT, NULL,
- ggp_oauth_authorization_done, data);
-ggp_oauth_request(PurpleConnection *gc, ggp_oauth_request_cb callback,
- gpointer user_data, const gchar *sign_method,
- GGPInfo *info = purple_connection_get_protocol_data(gc);
- PurpleAccount *account = purple_connection_get_account(gc);
- const char *method = "POST";
- const char *url = "http://api.gadu-gadu.pl/request_token";
- purple_debug_misc("gg", "ggp_oauth_request: requesting token...\n");
- auth = gg_oauth_generate_header(
- purple_contact_info_get_username(PURPLE_CONTACT_INFO(account)),
- purple_connection_get_password(gc), NULL, NULL);
- data = g_new0(ggp_oauth_data, 1);
- data->callback = callback;
- data->user_data = user_data;
- data->sign_method = g_strdup(sign_method);
- data->sign_url = g_strdup(sign_url);
- data->msg = msg = soup_message_new(method, url);
- // purple_http_request_set_max_len(req, GGP_OAUTH_RESPONSE_MAX);
- soup_message_headers_replace(soup_message_get_request_headers(msg),
- "Authorization", auth);
- soup_session_send_and_read_async(info->http, msg, G_PRIORITY_DEFAULT, NULL,
- ggp_oauth_request_token_got, data);
--- a/libpurple/protocols/gg/oauth/oauth-purple.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
- * 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
- * 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
-#ifndef _GGP_OAUTH_PURPLE_H
-#define _GGP_OAUTH_PURPLE_H
-typedef void (*ggp_oauth_request_cb)(PurpleConnection *gc, const gchar *token,
-void ggp_oauth_request(PurpleConnection *gc, ggp_oauth_request_cb callback,
- gpointer user_data, const gchar *sign_method, const gchar *sign_url);
-#endif /* _GGP_OAUTH_PURPLE_H */
--- a/libpurple/protocols/gg/oauth/oauth.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,185 +0,0 @@
- * 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
- * Code adapted from libgadu (C) 2008 Wojtek Kaniewski <wojtekka@irc.pl>
- * (http://toxygen.net/libgadu/) during Google Summer of Code 2012
- * by Tomek Wasilczyk (http://www.wasilczyk.pl).
- * 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
-char *gg_oauth_static_nonce; /* dla unit testów */
-char *gg_oauth_static_timestamp; /* dla unit testów */
-static char *gg_oauth_generate_request(gboolean header, ...) G_GNUC_NULL_TERMINATED;
-static void gg_oauth_generate_nonce(char *buf, int len)
- const char charset[] = "0123456789";
- if (buf == NULL || len < 1)
- *buf++ = charset[(unsigned) (((float) sizeof(charset) - 1.0) * g_random_int() / (RAND_MAX + 1.0))];
-/* Returns a comma separated header value if header is true,
- * or a url-encoded request otherwise
-gg_oauth_generate_request(gboolean header, ...)
- GString *res = g_string_new(NULL);
- gboolean truncate = FALSE;
- res = g_string_append(res, "OAuth ");
- va_start(params, header);
- while((key = va_arg(params, const gchar *))) {
- const gchar *value = va_arg(params, const gchar *);
- gchar *escaped = g_uri_escape_string(value, NULL, FALSE);
- g_string_append_printf(res, "%s=\"%s\",", key, escaped);
- g_string_append_printf(res, "%s=%s&", key, escaped);
- /* remove trailing separator */
- res = g_string_truncate(res, res->len - 1);
- return g_string_free(res, FALSE);
-static gchar *gg_hmac_sha1(const char *key, const char *message)
- hmac = g_hmac_new(G_CHECKSUM_SHA1, (guchar *)key, strlen(key));
- g_hmac_update(hmac, (guchar *)message, -1);
- g_hmac_get_digest(hmac, digest, &digest_len);
- return g_base64_encode(digest, sizeof(digest));
-gg_oauth_generate_signature(const char *method, const char *url,
- const char *request, const char *consumer_secret,
- const char *token_secret)
- char *text, *key, *res;
- gchar *url_e, *request_e, *consumer_secret_e, *token_secret_e;
- url_e = g_uri_escape_string(url, "?", FALSE);
- g_strdelimit(url_e, "?", '\0');
- request_e = g_uri_escape_string(request, NULL, FALSE);
- text = g_strdup_printf("%s&%s&%s", method, url_e, request_e);
- consumer_secret_e = g_uri_escape_string(consumer_secret, NULL, FALSE);
- token_secret_e = token_secret ? g_uri_escape_string(token_secret, NULL, FALSE) : NULL;
- key = g_strdup_printf("%s&%s", consumer_secret_e, token_secret ? token_secret_e : "");
- g_free(consumer_secret_e);
- g_free(token_secret_e);
- res = gg_hmac_sha1(key, text);
-gg_oauth_generate_header(const char *method, const char *url,
- const char *consumer_key, const char *consumer_secret,
- const char *token, const char *token_secret)
- char *request, *signature, *res;
- char nonce[80], timestamp[16];
- if (gg_oauth_static_nonce == NULL)
- gg_oauth_generate_nonce(nonce, sizeof(nonce));
- strncpy(nonce, gg_oauth_static_nonce, sizeof(nonce) - 1);
- nonce[sizeof(nonce) - 1] = 0;
- if (gg_oauth_static_timestamp == NULL) {
- g_snprintf(timestamp, sizeof(timestamp), "%ld", time(NULL));
- strncpy(timestamp, gg_oauth_static_timestamp, sizeof(timestamp) - 1);
- timestamp[sizeof(timestamp) - 1] = 0;
- request = gg_oauth_generate_request(FALSE,
- "oauth_consumer_key", consumer_key,
- "oauth_signature_method", "HMAC-SHA1",
- "oauth_timestamp", timestamp,
- "oauth_version", "1.0",
- signature = gg_oauth_generate_signature(method, url, request, consumer_secret, token_secret);
- res = gg_oauth_generate_request(TRUE,
- "oauth_version", "1.0",
- "oauth_timestamp", timestamp,
- "oauth_consumer_key", consumer_key,
- "oauth_signature_method", "HMAC-SHA1",
- "oauth_signature", signature,
--- a/libpurple/protocols/gg/oauth/oauth.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
- * 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
- * Code adapted from libgadu (C) 2008 Wojtek Kaniewski <wojtekka@irc.pl>
- * (http://toxygen.net/libgadu/) during Google Summer of Code 2012
- * by Tomek Wasilczyk (http://www.wasilczyk.pl).
- * 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
-char * gg_oauth_generate_header(const char *method, const char *url,
- const char *consumer_key, const char *consumer_secret,
- const char *token, const char *token_secret);
-#endif /* _GGP_OAUTH_H */
--- a/libpurple/protocols/gg/pubdir-prpl.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1025 +0,0 @@
- * 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
- * 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 "pubdir-prpl.h"
-#include "oauth/oauth-purple.h"
- ggp_pubdir_request_cb cb;
- GGP_PUBDIR_REQUEST_TYPE_INFO,
- GGP_PUBDIR_REQUEST_TYPE_SEARCH,
- ggp_pubdir_search_form *search_form;
-/* Searching for buddies. */
-#define GGP_PUBDIR_SEARCH_TITLE _("Gadu-Gadu Public Directory")
-#define GGP_PUBDIR_SEARCH_PER_PAGE 20
-struct _ggp_pubdir_search_form
- ggp_pubdir_gender gender;
-/* For ggp_pubdir_search_results_next, which is called by this. */
-static void ggp_pubdir_search_results_display(PurpleConnection *gc,
- int records_count, const ggp_pubdir_record *records, int next_offset,
-/******************************************************************************/
-static const gchar *ggp_pubdir_provinces[] =
- "warmińsko-mazurskie",
-static gsize ggp_pubdir_provinces_count = sizeof(ggp_pubdir_provinces)/sizeof(gchar*);
-/******************************************************************************/
-ggp_pubdir_record_free(ggp_pubdir_record *records, int count)
- for (i = 0; i < count; i++) {
- g_free(records[i].label);
- g_free(records[i].nickname);
- g_free(records[i].first_name);
- g_free(records[i].last_name);
- g_free(records[i].city);
- g_date_time_unref(records[i].birth);
-ggp_pubdir_search_form_free(ggp_pubdir_search_form *form)
-ggp_pubdir_request_free(ggp_pubdir_request *request)
- if (request->type == GGP_PUBDIR_REQUEST_TYPE_SEARCH)
- ggp_pubdir_search_form_free(request->params.search_form);
-ggp_pubdir_got_data(GObject *source, GAsyncResult *result, gpointer data) {
- ggp_pubdir_request *request = data;
- PurpleConnection *gc = request->gc;
- GBytes *response_body = NULL;
- const char *xml_raw = NULL;
- unsigned int status, next_offset;
- ggp_pubdir_record *records;
- response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
- if (response_body == NULL) {
- purple_debug_error("gg", "ggp_pubdir_got_data: %s", error->message);
- request->cb(gc, -1, NULL, 0, request->user_data);
- ggp_pubdir_request_free(request);
- xml_raw = g_bytes_unref_to_data(response_body, &xml_size);
- if (purple_debug_is_verbose() && purple_debug_is_unsafe()) {
- purple_debug_misc("gg", "ggp_pubdir_got_data: xml=[%.*s]",
- (int)xml_size, xml_raw);
- xml = purple_xmlnode_from_str(xml_raw, xml_size);
- purple_debug_error("gg", "ggp_pubdir_got_data: "
- request->cb(gc, -1, NULL, 0, request->user_data);
- ggp_pubdir_request_free(request);
- succ &= ggp_xml_get_uint(xml, "status", &status);
- if (!ggp_xml_get_uint(xml, "nextOffset", &next_offset))
- xml = purple_xmlnode_get_child(xml, "users");
- if (!succ || status != 0 || !xml) {
- purple_debug_error("gg", "ggp_pubdir_got_data: "
- request->cb(gc, -1, NULL, 0, request->user_data);
- ggp_pubdir_request_free(request);
- record_count = ggp_xml_child_count(xml, "user");
- records = g_new0(ggp_pubdir_record, record_count);
- xml = purple_xmlnode_get_child(xml, "user");
- ggp_pubdir_record *record = &records[i++];
- gchar *city = NULL, *birth_s = NULL;
- unsigned int gender = 0;
- g_assert(i <= record_count);
- record->uin = ggp_str_to_uin(purple_xmlnode_get_attrib(xml, "uin"));
- ggp_xml_get_uint(xml, "uin", &record->uin);
- purple_debug_error("gg", "ggp_pubdir_got_data:"
- uin_s = ggp_uin_to_str(record->uin);
- ggp_xml_get_string(xml, "label", &record->label);
- ggp_xml_get_string(xml, "nick", &record->nickname);
- ggp_xml_get_string(xml, "name", &record->first_name);
- ggp_xml_get_string(xml, "surname", &record->last_name);
- ggp_xml_get_string(xml, "city", &city);
- ggp_xml_get_string(xml, "birth", &birth_s);
- ggp_xml_get_uint(xml, "gender", &gender);
- ggp_xml_get_uint(xml, "age", &record->age);
- ggp_xml_get_uint(xml, "province", &record->province);
- record->label = ggp_free_if_equal(record->label, uin_s);
- record->label = ggp_free_if_equal(record->label, "");
- record->nickname = ggp_free_if_equal(record->nickname, uin_s);
- record->nickname = ggp_free_if_equal(record->nickname, "");
- record->first_name = ggp_free_if_equal(record->first_name, "");
- record->last_name = ggp_free_if_equal(record->last_name, "");
- g_clear_pointer(&record->birth, g_date_time_unref);
- else if (record->nickname)
- record->label = g_strdup(record->nickname);
- else if (record->first_name && record->last_name)
- record->label = g_strdup_printf("%s %s",
- record->first_name, record->last_name);
- else if (record->first_name)
- record->label = g_strdup(record->first_name);
- else if (record->last_name)
- record->label = g_strdup(record->last_name);
- g_strstrip(record->label);
- g_strstrip(record->nickname);
- record->gender = GGP_PUBDIR_GENDER_FEMALE;
- record->gender = GGP_PUBDIR_GENDER_MALE;
- record->gender = GGP_PUBDIR_GENDER_UNSPECIFIED;
- if (city && city[0] != '\0')
- record->city = g_strdup(city);
- g_strstrip(record->city);
- record->birth = g_date_time_new_from_iso8601(birth_s, NULL);
- /*TODO: calculate age from birth */
- if (purple_debug_is_verbose()) {
- purple_debug_misc("gg", "ggp_pubdir_got_data: [uin:%d] "
- "[label:%s] [nick:%s] [first name:%s] "
- "[last name:%s] [city:%s] [gender:%d] [age:%d] "
- "[birth:%lu]\n", record->uin, record->label,
- record->nickname, record->first_name,
- record->last_name, record->city, record->gender,
- record->age, g_date_time_to_unix(record->birth));
- g_clear_pointer(&city, g_free);
- g_clear_pointer(&birth_s, g_free);
- xml = purple_xmlnode_get_next_twin(xml);
- request->cb(gc, record_count, records, next_offset, request->user_data);
- ggp_pubdir_request_free(request);
- ggp_pubdir_record_free(records, record_count);
-ggp_pubdir_get_info_got_token(PurpleConnection *gc, const gchar *token,
- ggp_pubdir_request *request = _request;
- PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
- request->cb(gc, -1, NULL, 0, request->user_data);
- ggp_pubdir_request_free(request);
- info = purple_connection_get_protocol_data(gc);
- url = g_strdup_printf("http://api.gadu-gadu.pl/users/%u",
- request->params.user_info.uin);
- msg = soup_message_new("GET", url);
- soup_message_headers_replace(soup_message_get_request_headers(msg),
- "Authorization", token);
- soup_session_send_and_read_async(info->http, msg, G_PRIORITY_DEFAULT, NULL,
- ggp_pubdir_got_data, request);
-ggp_pubdir_get_info(PurpleConnection *gc, uin_t uin, ggp_pubdir_request_cb cb,
- ggp_pubdir_request *request = g_new0(ggp_pubdir_request, 1);
- request->type = GGP_PUBDIR_REQUEST_TYPE_INFO;
- request->user_data = user_data;
- request->params.user_info.uin = uin;
- url = g_strdup_printf("http://api.gadu-gadu.pl/users/%u", uin);
- ggp_oauth_request(gc, ggp_pubdir_get_info_got_token, request, "GET", url);
-ggp_pubdir_get_info_protocol_got(PurpleConnection *gc, int records_count,
- const ggp_pubdir_record *records,
- G_GNUC_UNUSED int next_offset, void *_uin_p)
- uin_t uin = *((uin_t*)_uin_p);
- PurpleNotifyUserInfo *info = purple_notify_user_info_new();
- const ggp_pubdir_record *record = &records[0];
- if (records_count < 1) {
- purple_debug_error("gg", "ggp_pubdir_get_info_protocol_got: "
- "couldn't get info for %u\n", uin);
- purple_notify_user_info_add_pair_plaintext(info, NULL,
- _("Cannot get user information"));
- purple_notify_userinfo(gc, ggp_uin_to_str(uin), info,
- purple_notify_user_info_destroy(info);
- purple_debug_info("gg", "ggp_pubdir_get_info_protocol_got: %u\n", uin);
- g_assert(uin == record->uin);
- g_assert(records_count == 1);
- buddy = purple_blist_find_buddy(purple_connection_get_account(gc),
- alias = purple_buddy_get_alias_only(buddy);
- purple_notify_user_info_add_pair_plaintext(info,
- status = purple_presence_get_active_status(
- purple_buddy_get_presence(buddy));
- ggp_status_from_purplestatus(status, &status_message);
- purple_notify_user_info_add_pair_plaintext(info, _("Status"),
- purple_status_get_name(status));
- purple_notify_user_info_add_pair_plaintext(info,
- _("Message"), status_message);
- if (record->nickname) {
- purple_notify_user_info_add_pair_plaintext(info,
- _("Nickname"), record->nickname);
- if (record->first_name) {
- purple_notify_user_info_add_pair_plaintext(info,
- _("First name"), record->first_name);
- if (record->last_name) {
- purple_notify_user_info_add_pair_plaintext(info,
- _("Last name"), record->last_name);
- if (record->gender != GGP_PUBDIR_GENDER_UNSPECIFIED) {
- purple_notify_user_info_add_pair_plaintext(info, _("Gender"),
- record->gender == GGP_PUBDIR_GENDER_FEMALE ?
- _("Female") : _("Male"));
- purple_notify_user_info_add_pair_plaintext(info, _("City"),
- gchar *bday = g_date_time_format(record->birth, "%Y-%m-%d");
- purple_notify_user_info_add_pair_plaintext(info, _("Birthday"), bday);
- } else if (record->age) {
- gchar *age_s = g_strdup_printf("%d", record->age);
- purple_notify_user_info_add_pair_plaintext(info, _("Age"),
- purple_notify_userinfo(gc, ggp_uin_to_str(uin), info, NULL, NULL);
- purple_notify_user_info_destroy(info);
-ggp_pubdir_get_info_protocol(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
- PurpleConnection *gc, const gchar *name)
- uin_t uin = ggp_str_to_uin(name);
- uin_t *uin_p = g_new0(uin_t, 1);
- purple_debug_info("gg", "ggp_pubdir_get_info_protocol: %u", uin);
- ggp_pubdir_get_info(gc, uin, ggp_pubdir_get_info_protocol_got, uin_p);
-ggp_pubdir_request_buddy_alias_got(PurpleConnection *gc, int records_count,
- const ggp_pubdir_record *records,
- G_GNUC_UNUSED int next_offset,
- G_GNUC_UNUSED gpointer data)
- if (records_count < 0) {
- purple_debug_error("gg", "ggp_pubdir_request_buddy_alias_got: "
- "couldn't get info for user\n");
- alias = records[0].label;
- purple_debug_info("gg", "ggp_pubdir_request_buddy_alias_got: "
- "public alias for %u is not available\n", uin);
- purple_debug_info("gg", "ggp_pubdir_request_buddy_alias_got: "
- "public alias for %u is \"%s\"\n", uin, alias);
- purple_serv_got_alias(gc, ggp_uin_to_str(uin), alias);
-ggp_pubdir_request_buddy_alias(PurpleConnection *gc, PurpleBuddy *buddy)
- uin_t uin = ggp_str_to_uin(purple_buddy_get_name(buddy));
- purple_debug_info("gg", "ggp_pubdir_request_buddy_alias: %u", uin);
- ggp_pubdir_get_info(gc, uin, ggp_pubdir_request_buddy_alias_got, NULL);
-/*******************************************************************************
- * Searching for buddies.
- ******************************************************************************/
-static ggp_pubdir_search_form *
-ggp_pubdir_search_form_clone(const ggp_pubdir_search_form *form)
- ggp_pubdir_search_form *dup = g_new(ggp_pubdir_search_form, 1);
- dup->nick = g_strdup(form->nick);
- dup->city = g_strdup(form->city);
- dup->gender = form->gender;
- dup->offset = form->offset;
- dup->limit = form->limit;
- dup->display_handle = form->display_handle;
-static gchar * ggp_pubdir_search_make_query(const ggp_pubdir_search_form *form)
- gchar *nick, *city, *gender;
- if (form->nick && form->nick[0] != '\0') {
- gchar *nick_e = g_uri_escape_string(form->nick, NULL, FALSE);
- nick = g_strdup_printf("&nick=%s", nick_e);
- if (form->city && form->city[0] != '\0') {
- gchar *city_e = g_uri_escape_string(form->city, NULL, FALSE);
- city = g_strdup_printf("&city=%s", city_e);
- if (form->gender != GGP_PUBDIR_GENDER_UNSPECIFIED) {
- gender = g_strdup_printf("&gender=%d",
- form->gender == GGP_PUBDIR_GENDER_MALE ? 2 : 1);
- query = g_strdup_printf("/users.xml?offset=%d&limit=%d%s%s%s",
- form->offset, form->limit, nick, city, gender);
-static void ggp_pubdir_search_got_token(PurpleConnection *gc,
- const gchar *token, gpointer _request)
- ggp_pubdir_request *request = _request;
- PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
- request->cb(gc, -1, NULL, 0, request->user_data);
- ggp_pubdir_request_free(request);
- purple_debug_misc("gg", "ggp_pubdir_search_got_token\n");
- query = ggp_pubdir_search_make_query(request->params.search_form);
- info = purple_connection_get_protocol_data(gc);
- url = g_strdup_printf("http://api.gadu-gadu.pl%s", query);
- msg = soup_message_new("GET", url);
- soup_message_headers_replace(soup_message_get_request_headers(msg),
- "Authorization", token);
- soup_session_send_and_read_async(info->http, msg, G_PRIORITY_DEFAULT, NULL,
- ggp_pubdir_got_data, request);
-ggp_pubdir_search_execute(PurpleConnection *gc,
- const ggp_pubdir_search_form *form,
- ggp_pubdir_request_cb cb, void *user_data)
- ggp_pubdir_request *request = g_new0(ggp_pubdir_request, 1);
- ggp_pubdir_search_form *local_form = ggp_pubdir_search_form_clone(form);
- request->type = GGP_PUBDIR_REQUEST_TYPE_SEARCH;
- request->user_data = user_data;
- request->params.search_form = local_form;
- query = ggp_pubdir_search_make_query(form);
- purple_debug_misc("gg", "ggp_pubdir_search_execute: %s", query);
- url = g_strdup_printf("http://api.gadu-gadu.pl%s", query);
- ggp_oauth_request(gc, ggp_pubdir_search_got_token, request, "GET", url);
-ggp_pubdir_search_results_new(PurpleConnection *gc, G_GNUC_UNUSED GList *row,
- ggp_pubdir_search_form *form = _form;
- ggp_pubdir_search(gc, form);
-ggp_pubdir_search_results_close(gpointer _form)
- ggp_pubdir_search_form *form = _form;
- ggp_pubdir_search_form_free(form);
-ggp_pubdir_search_results_next(PurpleConnection *gc, G_GNUC_UNUSED GList *row,
- ggp_pubdir_search_form *form = _form;
- ggp_pubdir_search_execute(gc, form, ggp_pubdir_search_results_display,
-ggp_pubdir_search_results_add(PurpleConnection *gc, GList *row,
- G_GNUC_UNUSED gpointer form)
- purple_blist_request_add_buddy(purple_connection_get_account(gc),
- g_list_nth_data(row, 0), NULL,
- g_list_nth_data(row, 1));
-ggp_pubdir_search_results_im(PurpleConnection *gc, GList *row,
- G_GNUC_UNUSED gpointer form)
- purple_conversation_present(PURPLE_CONVERSATION(purple_im_conversation_new(
- purple_connection_get_account(gc), g_list_nth_data(row, 0))));
-ggp_pubdir_search_results_info(PurpleConnection *gc, GList *row,
- G_GNUC_UNUSED gpointer form)
- ggp_pubdir_get_info_protocol(NULL, gc, g_list_nth_data(row, 0));
-ggp_pubdir_search_results_display(PurpleConnection *gc, int records_count,
- const ggp_pubdir_record *records,
- int next_offset, void *_form)
- ggp_pubdir_search_form *form = _form;
- PurpleNotifySearchResults *results;
- purple_debug_info("gg", "ggp_pubdir_search_results_display: "
- "got %d records (next offset: %d)\n",
- records_count, next_offset);
- if (records_count < 0 ||
- (records_count == 0 && form->offset != 0))
- purple_notify_error(gc, GGP_PUBDIR_SEARCH_TITLE,
- _("Error while searching for buddies"), NULL,
- purple_request_cpar_from_connection(gc));
- ggp_pubdir_search_form_free(form);
- if (records_count == 0) {
- purple_notify_info(gc, GGP_PUBDIR_SEARCH_TITLE,
- _("No matching users found"),
- _("There are no users matching your search criteria."),
- purple_request_cpar_from_connection(gc));
- ggp_pubdir_search_form_free(form);
- form->offset = next_offset;
- results = purple_notify_searchresults_new();
- purple_notify_searchresults_column_add(results,
- purple_notify_searchresults_column_new(_("GG Number")));
- purple_notify_searchresults_column_add(results,
- purple_notify_searchresults_column_new(_("Name")));
- purple_notify_searchresults_column_add(results,
- purple_notify_searchresults_column_new(_("City")));
- purple_notify_searchresults_column_add(results,
- purple_notify_searchresults_column_new(_("Gender")));
- purple_notify_searchresults_column_add(results,
- purple_notify_searchresults_column_new(_("Age")));
- for (i = 0; i < records_count; i++) {
- const ggp_pubdir_record *record = &records[i];
- gchar *gender = NULL, *age = NULL;
- if (record->gender == GGP_PUBDIR_GENDER_MALE)
- gender = g_strdup("male");
- else if (record->gender == GGP_PUBDIR_GENDER_FEMALE)
- gender = g_strdup("female");
- age = g_strdup_printf("%d", record->age);
- row = g_list_append(row, g_strdup(ggp_uin_to_str(record->uin)));
- row = g_list_append(row, g_strdup(record->label));
- row = g_list_append(row, g_strdup(record->city));
- row = g_list_append(row, gender);
- row = g_list_append(row, age);
- purple_notify_searchresults_row_add(results, row);
- purple_notify_searchresults_button_add(results,
- PURPLE_NOTIFY_BUTTON_ADD, ggp_pubdir_search_results_add);
- purple_notify_searchresults_button_add(results,
- PURPLE_NOTIFY_BUTTON_IM, ggp_pubdir_search_results_im);
- purple_notify_searchresults_button_add(results,
- PURPLE_NOTIFY_BUTTON_INFO, ggp_pubdir_search_results_info);
- purple_notify_searchresults_button_add_labeled(results, _("New search"),
- ggp_pubdir_search_results_new);
- purple_notify_searchresults_button_add(results,
- PURPLE_NOTIFY_BUTTON_CONTINUE,
- ggp_pubdir_search_results_next);
- if (!form->display_handle)
- form->display_handle = purple_notify_searchresults(gc,
- GGP_PUBDIR_SEARCH_TITLE, _("Search results"), NULL,
- results, ggp_pubdir_search_results_close, form);
- purple_notify_searchresults_new_rows(gc, results,
- g_assert(form->display_handle);
-ggp_pubdir_search_request(PurpleConnection *gc, PurpleRequestPage *page) {
- ggp_pubdir_search_form *form = g_new0(ggp_pubdir_search_form, 1);
- purple_debug_info("gg", "ggp_pubdir_search_request");
- form->nick = g_strdup(purple_request_page_get_string(page, "name"));
- form->city = g_strdup(purple_request_page_get_string(page, "city"));
- GPOINTER_TO_INT(purple_request_page_get_choice(page, "gender"));
- form->limit = GGP_PUBDIR_SEARCH_PER_PAGE;
- ggp_pubdir_search_execute(gc, form, ggp_pubdir_search_results_display,
-ggp_pubdir_search(PurpleConnection *gc, const ggp_pubdir_search_form *form)
- PurpleRequestPage *page;
- PurpleRequestGroup *group;
- PurpleRequestField *field;
- PurpleRequestFieldChoice *choice;
- purple_debug_info("gg", "ggp_pubdir_search");
- page = purple_request_page_new();
- group = purple_request_group_new(NULL);
- purple_request_page_add_group(page, group);
- field = purple_request_field_string_new("name", _("Name"),
- form ? form->nick : NULL, FALSE);
- purple_request_group_add_field(group, field);
- field = purple_request_field_string_new("city", _("City"),
- form ? form->city : NULL, FALSE);
- purple_request_group_add_field(group, field);
- field = purple_request_field_choice_new(
- "gender", _("Gender"), form ? GINT_TO_POINTER(form->gender) : NULL);
- choice = PURPLE_REQUEST_FIELD_CHOICE(field);
- purple_request_field_choice_add(choice, _("Male or female"), NULL);
- purple_request_field_choice_add(choice, _("Male"),
- GINT_TO_POINTER(GGP_PUBDIR_GENDER_MALE));
- purple_request_field_choice_add(choice, _("Female"),
- GINT_TO_POINTER(GGP_PUBDIR_GENDER_FEMALE));
- purple_request_group_add_field(group, field);
- purple_request_fields(gc, _("Find buddies"), _("Find buddies"),
- _("Please, enter your search criteria below"), page,
- _("OK"), G_CALLBACK(ggp_pubdir_search_request),
- purple_request_cpar_from_connection(gc), gc);
-/*******************************************************************************
- ******************************************************************************/
-ggp_pubdir_set_info_got_response(GObject *source, GAsyncResult *result,
- SoupMessage *msg = data;
- GBytes *response_body = NULL;
- const char *buffer = NULL;
- if (!SOUP_STATUS_IS_SUCCESSFUL(soup_message_get_status(msg))) {
- purple_debug_error("gg", "ggp_pubdir_set_info_got_response: failed");
- response_body = soup_session_send_and_read_finish(SOUP_SESSION(source),
- if (response_body == NULL) {
- purple_debug_error("gg",
- "ggp_pubdir_set_info_got_response: failed: %s",
- buffer = g_bytes_get_data(response_body, &size);
- purple_debug_info("gg", "ggp_pubdir_set_info_got_response: [%.*s]",
- /* <result><status>0</status></result> */
- /* TODO: notify about failure */
- g_bytes_unref(response_body);
-static void ggp_pubdir_set_info_got_token(PurpleConnection *gc,
- const gchar *token, gpointer _record)
- ggp_pubdir_record *record = _record;
- gchar *name, *surname, *city;
- uin_t uin = record->uin;
- PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
- /* TODO: notify about failure */
- ggp_pubdir_record_free(record, 1);
- info = purple_connection_get_protocol_data(gc);
- name = g_uri_escape_string(record->first_name, NULL, FALSE);
- surname = g_uri_escape_string(record->last_name, NULL, FALSE);
- city = g_uri_escape_string(record->city, NULL, FALSE);
- bday = g_date_time_format(record->birth, "%Y-%m-%d");
- request_data = g_strdup_printf(
- "birth=%sT10:00:00%%2B00:00&"
- if (purple_debug_is_verbose() && purple_debug_is_unsafe()) {
- purple_debug_misc("gg", "ggp_pubdir_set_info_got_token: "
- "query [%s]\n", request_data);
- url = g_strdup_printf("http://api.gadu-gadu.pl/users/%u.xml", uin);
- msg = soup_message_new("PUT", url);
- soup_message_headers_replace(soup_message_get_request_headers(msg),
- "Authorization", token);
- body = g_bytes_new_take(request_data, strlen(request_data));
- soup_message_set_request_body_from_bytes(msg,
- "application/x-www-form-urlencoded",
- soup_session_send_and_read_async(info->http, msg, G_PRIORITY_DEFAULT, NULL,
- ggp_pubdir_set_info_got_response, msg);
- ggp_pubdir_record_free(record, 1);
-ggp_pubdir_set_info_request(PurpleConnection *gc, PurpleRequestPage *page)
- PurpleAccount *account = purple_connection_get_account(gc);
- PurpleContactInfo *info = PURPLE_CONTACT_INFO(account);
- uin_t uin = ggp_str_to_uin(purple_contact_info_get_username(info));
- ggp_pubdir_record *record = g_new0(ggp_pubdir_record, 1);
- purple_debug_info("gg", "ggp_pubdir_set_info_request");
- record->first_name = g_strdup(purple_request_page_get_string(page,
- record->last_name = g_strdup(purple_request_page_get_string(page,
- record->gender = GPOINTER_TO_INT(purple_request_page_get_choice(page,
- record->city = g_strdup(purple_request_page_get_string(page, "city"));
- record->province = GPOINTER_TO_INT(purple_request_page_get_choice(page,
- birth_s = g_strdup_printf("%sT10:00:00+00:00",
- purple_request_page_get_string(page, "birth_date"));
- record->birth = g_date_time_new_from_iso8601(birth_s, NULL);
- purple_debug_info("gg", "ggp_pubdir_set_info_request: birth [%lu][%s]",
- g_date_time_to_unix(record->birth),
- purple_request_page_get_string(page, "birth_date"));
- url = g_strdup_printf("http://api.gadu-gadu.pl/users/%u.xml", uin);
- ggp_oauth_request(gc, ggp_pubdir_set_info_got_token, record, "PUT", url);
-ggp_pubdir_set_info_dialog(PurpleConnection *gc, int records_count,
- const ggp_pubdir_record *records,
- G_GNUC_UNUSED int next_offset,
- G_GNUC_UNUSED gpointer data)
- PurpleRequestPage *page;
- PurpleRequestGroup *group;
- PurpleRequestField *field;
- PurpleRequestFieldChoice *choice;
- const ggp_pubdir_record *record;
- purple_debug_info("gg", "ggp_pubdir_set_info_dialog (record: %d)",
- record = (records_count == 1 ? &records[0] : NULL);
- page = purple_request_page_new();
- group = purple_request_group_new(NULL);
- purple_request_page_add_group(page, group);
- field = purple_request_field_string_new("first_name", _("First name"),
- record ? record->first_name : NULL,
- purple_request_group_add_field(group, field);
- field = purple_request_field_string_new("last_name", _("Last name"),
- record ? record->last_name : NULL,
- purple_request_group_add_field(group, field);
- field = purple_request_field_choice_new(
- record ? GINT_TO_POINTER(record->gender)
- : GGP_PUBDIR_GENDER_UNSPECIFIED);
- choice = PURPLE_REQUEST_FIELD_CHOICE(field);
- purple_request_field_set_required(field, TRUE);
- purple_request_field_choice_add(choice, _("Male"),
- GINT_TO_POINTER(GGP_PUBDIR_GENDER_MALE));
- purple_request_field_choice_add(choice, _("Female"),
- GINT_TO_POINTER(GGP_PUBDIR_GENDER_FEMALE));
- purple_request_group_add_field(group, field);
- if(record != NULL && record->birth != NULL) {
- bday = g_date_time_format(record->birth, "%Y-%m-%d");
- field = purple_request_field_string_new(
- "birth_date", _("Birth Day"), bday,
- purple_request_field_set_required(field, TRUE);
- purple_request_group_add_field(group, field);
- field = purple_request_field_string_new(
- "city", _("City"), record ? record->city : NULL, FALSE);
- purple_request_group_add_field(group, field);
- /* Translators: This word is basically used to describe a Polish
- province. Gadu-Gadu users outside of Poland might choose to enter some
- equivalent value for themselves. For example, users in the USA might
- use their state (e.g. New York). If there is an equivalent term for
- your language, feel free to use it. Otherwise it's probably acceptable
- to leave it changed or transliterate it into your alphabet. */
- field = purple_request_field_choice_new("province", _("Voivodeship"), 0);
- choice = PURPLE_REQUEST_FIELD_CHOICE(field);
- purple_request_group_add_field(group, field);
- for (i = 0; i < ggp_pubdir_provinces_count; i++) {
- purple_request_field_choice_add(choice, ggp_pubdir_provinces[i],
- if (record && i == record->province) {
- purple_request_field_choice_set_value(choice, GINT_TO_POINTER(i));
- purple_request_field_choice_set_default_value(choice,
- purple_request_fields(gc, _("Set User Info"), _("Set User Info"), NULL,
- G_CALLBACK(ggp_pubdir_set_info_request), _("Cancel"),
- NULL, purple_request_cpar_from_connection(gc), gc);
-ggp_pubdir_set_info(PurpleConnection *gc)
- PurpleAccount *account = purple_connection_get_account(gc);
- PurpleContactInfo *info = PURPLE_CONTACT_INFO(account);
- ggp_pubdir_get_info(gc,
- ggp_str_to_uin(purple_contact_info_get_username(info)),
- ggp_pubdir_set_info_dialog, NULL);
--- a/libpurple/protocols/gg/pubdir-prpl.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
- * 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
- * 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
-#ifndef PURPLE_GG_PUBDIR_PRPL_H
-#define PURPLE_GG_PUBDIR_PRPL_H
- GGP_PUBDIR_GENDER_UNSPECIFIED,
- GGP_PUBDIR_GENDER_FEMALE,
- GGP_PUBDIR_GENDER_MALE,
- ggp_pubdir_gender gender;
-typedef struct _ggp_pubdir_search_form ggp_pubdir_search_form;
-typedef void (*ggp_pubdir_request_cb)(PurpleConnection *gc, int records_count,
- const ggp_pubdir_record *records, int next_offset, void *user_data);
-void ggp_pubdir_get_info(PurpleConnection *gc, uin_t uin,
- ggp_pubdir_request_cb cb, void *user_data);
-void ggp_pubdir_get_info_protocol(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *name);
-void ggp_pubdir_request_buddy_alias(PurpleConnection *gc, PurpleBuddy *buddy);
-void ggp_pubdir_search(PurpleConnection *gc,
- const ggp_pubdir_search_form *form);
-void ggp_pubdir_set_info(PurpleConnection *gc);
-#endif /* PURPLE_GG_PUBDIR_PRPL_H */
--- a/libpurple/protocols/gg/purplew.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
- * 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
- * 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>
-guint ggp_purplew_http_input_add(struct gg_http *http_req,
- PurpleInputFunction func, gpointer user_data)
- if (purple_debug_is_verbose()) {
- purple_debug_misc("gg", "ggp_purplew_http_input_add: "
- "[req=%p, fd=%d, cond=%d]\n",
- http_req, http_req->fd, http_req->check);
- return purple_input_add(http_req->fd,
- ggp_tcpsocket_inputcond_gg_to_purple(http_req->check),
-ggp_purplew_request_processing_cancel(ggp_purplew_request_processing_handle *handle,
- handle->cancel_cb(handle->gc, handle->user_data);
-ggp_purplew_request_processing_handle * ggp_purplew_request_processing(
- PurpleConnection *gc, const gchar *msg, void *user_data,
- ggp_purplew_request_processing_cancel_cb cancel_cb)
- ggp_purplew_request_processing_handle *handle =
- g_new(ggp_purplew_request_processing_handle, 1);
- handle->cancel_cb = cancel_cb;
- handle->user_data = user_data;
- handle->request_handle = purple_request_action(gc, _("Please wait..."),
- (msg ? msg : _("Please wait...")), NULL,
- PURPLE_DEFAULT_ACTION_NONE,
- purple_request_cpar_from_connection(gc), handle, 1,
- _("Cancel"), G_CALLBACK(ggp_purplew_request_processing_cancel));
-void ggp_purplew_request_processing_done(
- ggp_purplew_request_processing_handle *handle)
- purple_request_close(PURPLE_REQUEST_ACTION, handle->request_handle);
-PurpleGroup * ggp_purplew_buddy_get_group_only(PurpleBuddy *buddy)
- PurpleGroup *group = purple_buddy_get_group(buddy);
- if (0 == g_strcmp0(PURPLE_BLIST_DEFAULT_GROUP_NAME,
- purple_group_get_name(group)))
- if (0 == g_strcmp0("Buddies", purple_group_get_name(group)))
-GList * ggp_purplew_group_get_buddies(PurpleGroup *group, PurpleAccount *account)
- PurpleBlistNode *gnode, *cnode, *bnode;
- g_return_val_if_fail(group != NULL, NULL);
- gnode = PURPLE_BLIST_NODE(group);
- for (cnode = gnode->child; cnode; cnode = cnode->next) {
- if (!PURPLE_IS_META_CONTACT(cnode))
- for (bnode = cnode->child; bnode; bnode = bnode->next) {
- if (!PURPLE_IS_BUDDY(bnode))
- buddy = PURPLE_BUDDY(bnode);
- purple_buddy_get_account(buddy) == account)
- buddies = g_list_append(buddies, buddy);
-GList * ggp_purplew_account_get_groups(PurpleAccount *account, gboolean exclusive)
- PurpleBlistNode *bnode;
- for (bnode = purple_blist_get_default_root(); bnode;
- gboolean have_specified = FALSE, have_others = FALSE;
- if (!PURPLE_IS_GROUP(bnode))
- group = PURPLE_GROUP(bnode);
- for (accounts = purple_group_get_accounts(group); accounts;
- accounts = g_slist_delete_link(accounts, accounts))
- if (accounts->data == account)
- if (have_specified && (!exclusive || !have_others))
- groups = g_list_append(groups, group);
--- a/libpurple/protocols/gg/purplew.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
- * 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
- * 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
-#ifndef PURPLE_GG_PURPLEW_H
-#define PURPLE_GG_PURPLEW_H
- * Adds an input handler in purple event loop for http request.
- * @see purple_input_add
- * @param http_req Http connection to watch.
- * @param func The callback function for data.
- * @param user_data User-specified data.
- * @return The resulting handle (will be greater than 0).
-guint ggp_purplew_http_input_add(struct gg_http *http_req,
- PurpleInputFunction func, gpointer user_data);
-typedef void (*ggp_purplew_request_processing_cancel_cb)(PurpleConnection *gc,
- ggp_purplew_request_processing_cancel_cb cancel_cb;
-} ggp_purplew_request_processing_handle;
-ggp_purplew_request_processing_handle * ggp_purplew_request_processing(
- PurpleConnection *gc, const gchar *msg, void *user_data,
- ggp_purplew_request_processing_cancel_cb oncancel);
-void ggp_purplew_request_processing_done(
- ggp_purplew_request_processing_handle *handle);
-/* ignores default group */
-PurpleGroup * ggp_purplew_buddy_get_group_only(PurpleBuddy *buddy);
-GList * ggp_purplew_group_get_buddies(PurpleGroup *group, PurpleAccount *account);
-/* you must g_free returned list */
-GList * ggp_purplew_account_get_groups(PurpleAccount *account, gboolean exclusive);
-#endif /* PURPLE_GG_PURPLEW_H */
--- a/libpurple/protocols/gg/resolver-purple.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,205 +0,0 @@
- * 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
- * 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 "libpurple/glibcompat.h"
-#include "resolver-purple.h"
-static int ggp_resolver_purple_start(int *fd, void **private_data,
-static void ggp_resolver_purple_cleanup(void **private_data, int force);
-static void ggp_resolver_purple_cb(GObject *sender, GAsyncResult *res, gpointer data);
- GCancellable *cancellable;
- * pipes[0] - for reading
- * pipes[1] - for writing
-} ggp_resolver_purple_data;
-extern void ggp_resolver_purple_setup(void)
- if (gg_global_set_custom_resolver(ggp_resolver_purple_start,
- ggp_resolver_purple_cleanup) != 0)
- purple_debug_error("gg", "failed to set custom resolver\n");
-void ggp_resolver_purple_cb(GObject *sender, GAsyncResult *res, gpointer cbdata) {
- GList *addresses = NULL, *in_addrs = NULL, *l = NULL;
- gsize native_size = 0; /* this is kind of dirty, but it'll be initialized before we use it */
- ggp_resolver_purple_data *data = (ggp_resolver_purple_data*)cbdata;
- const int fd = data->pipes[1];
- addresses = g_resolver_lookup_by_name_finish(G_RESOLVER(sender),
- if(addresses == NULL) {
- purple_debug_error("gg", "ggp_resolver_purple_cb failed: %s\n",
- purple_debug_misc("gg", "ggp_resolver_purple_cb succeeded: (%p, %p)\n",
- g_object_unref(data->cancellable);
- data->cancellable = NULL;
- for(l = addresses; l; l = l->next) {
- GInetAddress *inet_address = G_INET_ADDRESS(l->data);
- GSocketFamily family = G_SOCKET_FAMILY_INVALID;
- gchar *ip_address = g_inet_address_to_string(inet_address);
- family = g_inet_address_get_family(inet_address);
- case G_SOCKET_FAMILY_IPV4:
- purple_debug_misc("gg", "ggp_resolver_purple_cb "
- "ipv4: %s\n", ip_address);
- native_size = g_inet_address_get_native_size(inet_address);
- in_addrs = g_list_append(in_addrs, g_memdup2(g_inet_address_to_bytes(inet_address), native_size));
- case G_SOCKET_FAMILY_IPV6:
- purple_debug_misc("gg", "ggp_resolver_purple_cb "
- "ipv6 (ignore): %s\n", ip_address);
- purple_debug_warning("gg", "ggp_resolver_purple_cb "
- "unexpected sa_family: %d\n",
- for(l = in_addrs; l; l = l->next) {
- gint write_size = native_size;
- if(write(fd, l->data, write_size) != write_size) {
- purple_debug_error("gg",
- "ggp_resolver_purple_cb write error on %p\n", l->data);
- g_resolver_free_addresses(addresses);
-int ggp_resolver_purple_start(int *fd, void **private_data,
- ggp_resolver_purple_data *data;
- purple_debug_misc("gg", "ggp_resolver_purple_start(%p, %p, \"%s\")\n",
- fd, private_data, hostname);
- data = g_new0(ggp_resolver_purple_data, 1);
- *private_data = (void*)data;
- data->cancellable = NULL;
- if (purple_input_pipe(data->pipes) != 0) {
- purple_debug_error("gg", "ggp_resolver_purple_start: "
- "unable to create pipe\n");
- ggp_resolver_purple_cleanup(private_data, 0);
- /* account and port is unknown in this context */
- data->cancellable = g_cancellable_new();
- resolver = g_resolver_get_default();
- g_resolver_lookup_by_name_async(resolver,
- ggp_resolver_purple_cb,
- g_object_unref(resolver);
- if (!data->cancellable) {
- purple_debug_error("gg", "ggp_resolver_purple_start: "
- "unable to call purple_dnsquery_a\n");
- ggp_resolver_purple_cleanup(private_data, 0);
-void ggp_resolver_purple_cleanup(void **private_data, int force)
- ggp_resolver_purple_data *data =
- (ggp_resolver_purple_data*)(*private_data);
- purple_debug_misc("gg", "ggp_resolver_purple_cleanup(%p, %d)\n",
- if (G_IS_CANCELLABLE(data->cancellable)) {
- g_cancellable_cancel(data->cancellable);
- g_object_unref(data->cancellable);
--- a/libpurple/protocols/gg/resolver-purple.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
- * 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
- * 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
-#ifndef PURPLE_GG_RESOLVER_PURPLE_H
-#define PURPLE_GG_RESOLVER_PURPLE_H
- * Registers custom resolver for libgadu, that uses libpurple for DNS queries.
-void ggp_resolver_purple_setup(void);
-#endif /* PURPLE_GG_RESOLVER_PURPLE_H */
--- a/libpurple/protocols/gg/resources/gg.gresource.xml Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
- <gresource prefix="/im/pidgin/libpurple/gg">
- <file>icons/16x16/apps/im-gadu-gadu.png</file>
- <file>icons/16x16/apps/scalable/im-gadu-gadu.svg</file>
- <file>icons/22x22/apps/im-gadu-gadu.png</file>
- <file>icons/22x22/apps/scalable/im-gadu-gadu.svg</file>
- <file>icons/48x48/apps/im-gadu-gadu.png</file>
- <file>icons/scalable/apps/im-gadu-gadu.svg</file>
Binary file libpurple/protocols/gg/resources/icons/16x16/apps/im-gadu-gadu.png has changed
--- a/libpurple/protocols/gg/resources/icons/16x16/apps/scalable/im-gadu-gadu.svg Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,365 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- sodipodi:version="0.32"
- inkscape:version="0.46"
- sodipodi:docname="emote-select.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- inkscape:export-filename="/home/hbons/Bureaublad/gadu-gadu.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90">
- id="linearGradient8687"
- inkscape:collect="always">
- style="stop-color:#f57575;stop-opacity:1" />
- style="stop-color:#fea523;stop-opacity:0;" />
- inkscape:collect="always"
- id="linearGradient8653">
- style="stop-color:#a40000;stop-opacity:1;"
- style="stop-color:#ef2929;stop-opacity:1"
- sodipodi:type="inkscape:persp3d"
- inkscape:vp_x="0 : 8 : 1"
- inkscape:vp_y="0 : 1000 : 0"
- inkscape:vp_z="16 : 8 : 1"
- inkscape:persp3d-origin="8 : 5.3333333 : 1"
- id="linearGradient11170"
- inkscape:collect="always">
- style="stop-color:#000000;stop-opacity:1" />
- style="stop-color:#2e3436;stop-opacity:0;" />
- id="linearGradient11164"
- inkscape:collect="always">
- style="stop-color:#000000;stop-opacity:1" />
- style="stop-color:#2e3436;stop-opacity:0;" />
- inkscape:collect="always"
- id="linearGradient22870">
- style="stop-color:#ffffff;stop-opacity:1;"
- style="stop-color:#ffffff;stop-opacity:0;"
- inkscape:collect="always"
- xlink:href="#linearGradient22870"
- id="linearGradient20933"
- gradientUnits="userSpaceOnUse"
- id="linearGradient11461"
- inkscape:collect="always">
- style="stop-color:#fbfeac;stop-opacity:1" />
- style="stop-color:#eedb3c;stop-opacity:0;" />
- inkscape:collect="always"
- xlink:href="#linearGradient11461"
- id="radialGradient20931"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1.9034559,3.0329373e-8,-4.2282289e-8,2.6533656,-10.666343,-17.069444)" />
- inkscape:collect="always"
- xlink:href="#linearGradient22526"
- id="linearGradient20942"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(0.8000001,0,0,0.8980646,-0.6999993,-2.2354831)"
- inkscape:collect="always"
- id="linearGradient22526">
- style="stop-color:#f57575;stop-opacity:1"
- style="stop-color:#fea523;stop-opacity:0;"
- inkscape:collect="always"
- xlink:href="#linearGradient8687"
- id="linearGradient20915"
- gradientUnits="userSpaceOnUse"
- gradientTransform="translate(7.000002,1)"
- inkscape:collect="always"
- xlink:href="#linearGradient11164"
- id="linearGradient11158"
- gradientUnits="userSpaceOnUse"
- inkscape:collect="always"
- xlink:href="#linearGradient11170"
- id="linearGradient11160"
- gradientUnits="userSpaceOnUse"
- inkscape:collect="always"
- xlink:href="#linearGradient8653"
- id="linearGradient8659"
- gradientUnits="userSpaceOnUse" />
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="31.392433"
- inkscape:cx="15.513311"
- inkscape:current-layer="layer1"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
- inkscape:snap-nodes="false"
- inkscape:snap-bbox="true"
- inkscape:window-width="1440"
- inkscape:window-height="847"
- <dc:format>image/svg+xml</dc:format>
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- style="opacity:1;fill:#a40000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- style="opacity:1;fill:#a40000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- style="opacity:1;fill:#ef2929;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- style="opacity:1;fill:#ef2929;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- style="opacity:1;fill:#a40000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- style="opacity:1;fill:#ef2929;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- style="opacity:1;fill:#a40000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- style="opacity:1;fill:#ef2929;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- style="opacity:0;fill:#d3d7cf;fill-opacity:0;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
- transform="matrix(0.651488,0,0,0.651488,0.30843,0.8446922)"
- d="M 21.781414,10.983024 A 9.975256,9.975256 0 1 1 1.8309021,10.983024 A 9.975256,9.975256 0 1 1 21.781414,10.983024 z"
- sodipodi:cy="10.983024"
- sodipodi:cx="11.806158"
- style="opacity:1;fill:#fcaf3e;fill-opacity:1;stroke:url(#linearGradient8659);stroke-width:1.53875661000000008;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;enable-background:new"
- transform="matrix(0.5513643,0,0,0.5513643,1.490506,1.944353)"
- d="M 21.781414,10.983024 A 9.975256,9.975256 0 1 1 1.8309021,10.983024 A 9.975256,9.975256 0 1 1 21.781414,10.983024 z"
- sodipodi:cy="10.983024"
- sodipodi:cx="11.806158"
- style="opacity:1;fill:url(#radialGradient20931);fill-opacity:1;stroke:url(#linearGradient20933);stroke-width:1.81368327;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;enable-background:new"
- d="M 8.5000005,6.7451615 C 8.5000005,7.9844904 7.604002,8.9903231 6.500001,8.9903231 C 5.3959999,8.9903231 4.5000001,7.9844904 4.5000001,6.7451615 C 4.5000001,5.5058325 5.3959999,4.5000005 6.500001,4.5000005 C 7.604002,4.5000005 8.5000005,5.5058325 8.5000005,6.7451615 z"
- style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:url(#linearGradient20942);stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;display:inline;enable-background:new" />
- sodipodi:nodetypes="cscsc"
- d="M 11,10 C 10.887023,11.226829 9.4422911,12 8.0000003,12 C 6.5577095,12 5.2085418,11.396721 5,10 C 5.6322481,10.739405 6.7426661,11.065616 8.0000003,11.065616 C 9.2573337,11.065616 10.367752,10.739405 11,10 z"
- style="opacity:1;fill:#b40c0c;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;enable-background:new" />
- style="opacity:1;display:inline;enable-background:new"
- transform="matrix(0.8295523,0,0,0.9130993,-3.698956,-3.261344)">
- style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:url(#linearGradient20915);stroke-width:1.14899766;stroke-miterlimit:4;stroke-opacity:1;display:inline;enable-background:new"
- d="M 18.5,11 C 18.5,12.38 17.380001,13.5 16,13.5 C 14.62,13.5 13.5,12.38 13.5,11 C 13.5,9.62 14.62,8.5 16,8.5 C 17.380001,8.5 18.5,9.62 18.5,11 z"
- transform="matrix(0.9747196,0,0,0.5150957,-2.4615398,2.0279474)"
- d="M 10.732871,9.6526775 A 1.0259361,1.9413869 0 1 1 8.6809988,9.6526775 A 1.0259361,1.9413869 0 1 1 10.732871,9.6526775 z"
- sodipodi:ry="1.9413869"
- sodipodi:rx="1.0259361"
- sodipodi:cy="9.6526775"
- sodipodi:cx="9.7069349"
- style="opacity:1;fill:url(#linearGradient11160);fill-opacity:1;stroke:none;stroke-width:0.98640186;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;enable-background:new"
- transform="matrix(-0.9747196,0,0,0.5150957,18.46154,2.0279474)"
- d="M 10.732871,9.6526775 A 1.0259361,1.9413869 0 1 1 8.6809988,9.6526775 A 1.0259361,1.9413869 0 1 1 10.732871,9.6526775 z"
- sodipodi:ry="1.9413869"
- sodipodi:rx="1.0259361"
- sodipodi:cy="9.6526775"
- sodipodi:cx="9.7069349"
- style="opacity:1;fill:url(#linearGradient11158);fill-opacity:1;stroke:none;stroke-width:0.98640186;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;enable-background:new"
Binary file libpurple/protocols/gg/resources/icons/22x22/apps/im-gadu-gadu.png has changed
--- a/libpurple/protocols/gg/resources/icons/22x22/apps/scalable/im-gadu-gadu.svg Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,206 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- sodipodi:version="0.32"
- inkscape:version="0.46"
- sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/22/scalable"
- sodipodi:docname="gadu-gadu.svg"
- inkscape:export-filename="/home/hbons/GUI/Tango/Gaim Refresh/protocols/22/gadu-gadu.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:output_extension="org.inkscape.output.svg.inkscape">
- inkscape:collect="always"
- id="linearGradient3150">
- style="stop-color:#2e3436;stop-opacity:1;"
- style="stop-color:#2e3436;stop-opacity:0;"
- inkscape:collect="always"
- xlink:href="#linearGradient3150"
- id="radialGradient3156"
- gradientTransform="matrix(-0.842757,0,0,-0.35721,19.80716,14.19321)"
- gradientUnits="userSpaceOnUse" />
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="24.007726"
- inkscape:cx="16.146337"
- inkscape:cy="13.950539"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- inkscape:guide-bbox="true"
- inkscape:window-width="1268"
- inkscape:window-height="971"
- inkscape:window-y="25" />
- <dc:format>image/svg+xml</dc:format>
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- style="opacity:1;fill:#c00;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- transform="matrix(0.707107,-0.707107,0.707107,0.707107,-1,1)" />
- style="opacity:1;fill:#c00;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- transform="matrix(-0.707107,-0.707107,0.707107,-0.707107,-1,1)" />
- style="opacity:0.4;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- sodipodi:cx="10.748654"
- sodipodi:cy="10.457643"
- sodipodi:rx="6.6449099"
- sodipodi:ry="2.3675451"
- d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z"
- transform="matrix(1.429666,0,0,1.267135,-3.866981,6.748756)" />
- style="opacity:1;fill:#db2424;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- transform="translate(-1,1)" />
- style="opacity:1;fill:#db2424;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- transform="translate(-1,1)" />
- style="opacity:1;fill:#db2424;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- transform="matrix(0,-1,1,0,-1,1)" />
- style="opacity:1;fill:#db2424;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- transform="matrix(0,-1,1,0,-1,1)" />
- style="opacity:1;fill:#c00;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- transform="matrix(0.707107,-0.707107,0.707107,0.707107,-1,1)" />
- style="opacity:1;fill:#c00;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- transform="matrix(-0.707107,-0.707107,0.707107,-0.707107,-1,1)" />
- style="opacity:1;fill:#fce94f;fill-opacity:1;stroke:#c00;stroke-width:0.73921776;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- sodipodi:cx="8.0702047"
- sodipodi:cy="8.0363102"
- sodipodi:rx="5.5372205"
- sodipodi:ry="5.5372205"
- d="M 13.607425 8.0363102 A 5.5372205 5.5372205 0 1 1 2.5329843,8.0363102 A 5.5372205 5.5372205 0 1 1 13.607425 8.0363102 z"
- transform="matrix(1.354195,0,0,1.35137,1.070845,1.157102)" />
- style="opacity:0.7;fill:none;fill-opacity:1;stroke:#c4a000;stroke-width:0.85407299;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.4848485"
- sodipodi:cx="8.0702047"
- sodipodi:cy="8.0363102"
- sodipodi:rx="5.5372205"
- sodipodi:ry="5.5372205"
- d="M 13.607425 8.0363102 A 5.5372205 5.5372205 0 1 1 2.5329843,8.0363102 A 5.5372205 5.5372205 0 1 1 13.607425 8.0363102 z"
- transform="matrix(1.171277,0,0,1.170443,2.525066,2.61184)" />
- style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- sodipodi:cx="9.8489876"
- sodipodi:cy="10.583912"
- sodipodi:rx="1.2626907"
- sodipodi:ry="1.0417198"
- d="M 11.111678 10.583912 A 1.2626907 1.0417198 0 1 1 8.5862969,10.583912 A 1.2626907 1.0417198 0 1 1 11.111678 10.583912 z"
- transform="matrix(0,1.18426,-0.959955,0,20.16009,-1.168408)" />
- style="opacity:1;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- sodipodi:cx="9.8489876"
- sodipodi:cy="10.583912"
- sodipodi:rx="1.2626907"
- sodipodi:ry="1.0417198"
- d="M 11.111678 10.583912 A 1.2626907 1.0417198 0 1 1 8.5862969,10.583912 A 1.2626907 1.0417198 0 1 1 11.111678 10.583912 z"
- transform="matrix(0,-1.187938,0.959951,0,3.839963,22.19998)" />
- style="opacity:1;fill:#555753;fill-opacity:1;stroke:none;stroke-width:1.10482609;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 17.0113,10.955978 C 17.0113,13.182328 15.218558,14.007827 13,14.007827 C 10.819611,14.007827 9.0496187,13.101106 8.9887006,10.913915 L 8,10.942262 C 8.0756746,13.659262 10.29145,15 13,15 C 15.758926,15 17.999999,13.724591 18,10.955978 L 17.0113,10.955978 z "
- sodipodi:nodetypes="csccscc"
- transform="translate(-1,1)" />
Binary file libpurple/protocols/gg/resources/icons/48x48/apps/im-gadu-gadu.png has changed
--- a/libpurple/protocols/gg/resources/icons/scalable/apps/im-gadu-gadu.svg Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,215 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- sodipodi:version="0.32"
- inkscape:version="0.46"
- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48/scalable"
- sodipodi:docname="gadu-gadu.svg"
- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/gadu-gadu.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- inkscape:output_extension="org.inkscape.output.svg.inkscape">
- inkscape:collect="always"
- id="linearGradient2447">
- style="stop-color:#ffffff;stop-opacity:1;"
- style="stop-color:#ffffff;stop-opacity:0;"
- inkscape:collect="always"
- id="linearGradient3150">
- style="stop-color:#2e3436;stop-opacity:1;"
- style="stop-color:#2e3436;stop-opacity:0;"
- inkscape:collect="always"
- xlink:href="#linearGradient3150"
- id="radialGradient3156"
- gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
- gradientUnits="userSpaceOnUse" />
- inkscape:collect="always"
- id="linearGradient2233">
- style="stop-color:#eeeeec;stop-opacity:1;"
- style="stop-color:#eeeeec;stop-opacity:0;"
- inkscape:collect="always"
- xlink:href="#linearGradient2233"
- id="linearGradient2279"
- gradientUnits="userSpaceOnUse"
- inkscape:collect="always"
- xlink:href="#linearGradient2447"
- id="linearGradient2453"
- gradientUnits="userSpaceOnUse" />
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="15.004828"
- inkscape:cy="23.900599"
- inkscape:current-layer="layer1"
- inkscape:grid-bbox="true"
- inkscape:document-units="px"
- inkscape:guide-bbox="true"
- inkscape:window-width="1268"
- inkscape:window-height="972"
- inkscape:window-y="21" />
- <dc:format>image/svg+xml</dc:format>
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- inkscape:label="Layer 1"
- inkscape:groupmode="layer">
- style="opacity:0.5;fill:url(#radialGradient3156);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- sodipodi:cx="10.748654"
- sodipodi:cy="10.457643"
- sodipodi:rx="6.6449099"
- sodipodi:ry="2.3675451"
- d="M 17.393564 10.457643 A 6.6449099 2.3675451 0 1 1 4.1037445,10.457643 A 6.6449099 2.3675451 0 1 1 17.393564 10.457643 z"
- transform="matrix(3.160314,0,0,2.745459,-9.969125,9.788968)" />
- style="opacity:1;fill:#ef2929;fill-opacity:1;fill-rule:evenodd;stroke:#a40000;stroke-width:0.9999997;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="M 22.5,4.5130623 L 22.5,8.6366327 C 19.782905,9.0005399 17.277282,10.079925 15.21875,11.698071 L 12.0625,8.5116761 L 9.5,11.073287 L 12.6875,14.259683 C 11.068793,16.317502 9.9577835,18.791017 9.59375,21.50717 L 5.5,21.50717 L 5.5,25.505784 L 9.59375,25.505784 C 9.9535644,28.234089 11.062591,30.718808 12.6875,32.78451 L 9.5,35.970906 L 12.0625,38.501278 L 15.21875,35.346123 C 17.277282,36.964269 19.782905,38.043654 22.5,38.407561 L 22.5,42.499891 L 26.5,42.499891 L 26.5,38.407561 C 29.229107,38.042044 31.717452,36.944842 33.78125,35.314883 L 36.96875,38.501278 L 39.5,35.970906 L 36.3125,32.78451 C 37.936789,30.719597 39.014761,28.232873 39.375,25.505784 L 43.5,25.505784 L 43.5,21.50717 L 39.375,21.50717 C 39.010966,18.791018 37.931208,16.317502 36.3125,14.259683 L 39.5,11.073287 L 36.96875,8.5116761 L 33.78125,11.698071 L 33.75,11.698071 C 31.691468,10.079924 29.217095,9.0005401 26.5,8.6366327 L 26.5,4.5130623 L 22.5,4.5130623 z M 23.8125,11.354441 C 24.033452,11.344807 24.274977,11.354441 24.5,11.354441 C 31.700731,11.354441 36.65625,16.339482 36.65625,23.537717 C 36.656248,30.735953 31.700731,35.689753 24.5,35.689753 C 17.29927,35.689754 12.502002,30.735951 12.502002,23.537717 C 12.502002,16.564428 16.962974,11.653081 23.8125,11.354441 z "
- sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccssssc" />
- sodipodi:type="inkscape:offset"
- inkscape:original="M 22.5 4.5 L 22.5 8.625 C 19.782905 8.988907 17.277282 10.069354 15.21875 11.6875 L 12.0625 8.5 L 9.5 11.0625 L 12.6875 14.25 C 11.068793 16.307819 9.9577835 18.783847 9.59375 21.5 L 5.5 21.5 L 5.5 25.5 L 9.59375 25.5 C 9.9535644 28.228306 11.062591 30.715548 12.6875 32.78125 L 9.5 35.96875 L 12.0625 38.5 L 15.21875 35.34375 C 17.277282 36.961896 19.782905 38.042343 22.5 38.40625 L 22.5 42.5 L 26.5 42.5 L 26.5 38.40625 C 29.229107 38.040732 31.717452 36.942459 33.78125 35.3125 L 36.96875 38.5 L 39.5 35.96875 L 36.3125 32.78125 C 37.936789 30.716335 39.014761 28.227089 39.375 25.5 L 43.5 25.5 L 43.5 21.5 L 39.375 21.5 C 39.010966 18.783848 37.931208 16.307819 36.3125 14.25 L 39.5 11.0625 L 36.96875 8.5 L 33.78125 11.6875 L 33.75 11.6875 C 31.691468 10.069353 29.217095 8.9889074 26.5 8.625 L 26.5 4.5 L 22.5 4.5 z M 23.8125 11.34375 C 24.033452 11.334116 24.274977 11.34375 24.5 11.34375 C 31.700731 11.34375 36.65625 16.333015 36.65625 23.53125 C 36.656248 30.729485 31.700731 35.6875 24.5 35.6875 C 17.29927 35.6875 12.5 30.729484 12.5 23.53125 C 12.5 16.55796 16.962974 11.64239 23.8125 11.34375 z "
- style="opacity:0.2;fill:url(#linearGradient2453);fill-opacity:1.0;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.9999997;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- inkscape:href="#path2394"
- d="M 23.5,5.5 L 23.5,8.625 C 23.503929,9.1319208 23.127956,9.5616039 22.625,9.625 C 20.085855,9.9650737 17.762357,10.960594 15.84375,12.46875 C 15.44664,12.797268 14.864902,12.77021 14.5,12.40625 L 12.0625,9.9375 L 10.9375,11.0625 L 13.40625,13.53125 C 13.77021,13.896152 13.797268,14.47789 13.46875,14.875 C 11.953567,16.801212 10.932828,19.095048 10.59375,21.625 C 10.530354,22.127956 10.100671,22.503929 9.59375,22.5 L 6.5,22.5 L 6.5,24.5 L 9.59375,24.5 C 10.100671,24.496071 10.530354,24.872044 10.59375,25.375 C 10.929039,27.917339 11.948302,30.223346 13.46875,32.15625 C 13.797268,32.55336 13.77021,33.135098 13.40625,33.5 L 10.9375,35.96875 L 12.03125,37.09375 L 14.5,34.625 C 14.864902,34.26104 15.44664,34.233982 15.84375,34.5625 C 17.762357,36.070656 20.085855,37.066176 22.625,37.40625 C 23.127956,37.469646 23.503929,37.899329 23.5,38.40625 L 23.5,41.5 L 25.5,41.5 L 25.5,38.40625 C 25.496071,37.899329 25.872044,37.469646 26.375,37.40625 C 28.92215,37.065102 31.227806,36.054308 33.15625,34.53125 C 33.55336,34.202732 34.135098,34.22979 34.5,34.59375 L 36.96875,37.0625 L 38.0625,35.96875 L 35.59375,33.5 C 35.22979,33.135098 35.202732,32.55336 35.53125,32.15625 C 37.047015,30.229299 38.038333,27.923642 38.375,25.375 C 38.438396,24.872044 38.868079,24.496071 39.375,24.5 L 42.5,24.5 L 42.5,22.5 L 39.375,22.5 C 38.868079,22.503929 38.438396,22.127956 38.375,21.625 C 38.034921,19.087581 37.042567,16.796296 35.53125,14.875 C 35.202732,14.47789 35.22979,13.896152 35.59375,13.53125 L 38.09375,11.03125 L 36.96875,9.9375 L 34.5,12.40625 C 34.307701,12.592396 34.048815,12.693699 33.78125,12.6875 L 33.75,12.6875 C 33.522871,12.68767 33.302449,12.610522 33.125,12.46875 C 31.202527,10.957555 28.913145,9.9649402 26.375,9.625 C 25.872044,9.5616039 25.496071,9.1319208 25.5,8.625 L 25.5,5.5 L 23.5,5.5 z M 23.78125,10.34375 C 24.062872,10.331471 24.303519,10.34375 24.5,10.34375 C 32.162653,10.34375 37.65625,15.874058 37.65625,23.53125 C 37.656248,31.188442 32.15976,36.6875 24.5,36.6875 C 20.67012,36.6875 17.391923,35.341265 15.09375,33 C 12.795577,30.658735 11.5,27.35261 11.5,23.53125 C 11.5,16.131287 16.473536,10.662367 23.78125,10.34375 z " />
- style="opacity:1;fill:#edd400;fill-opacity:1;fill-rule:evenodd;stroke:#a40000;stroke-width:1.08146787;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- sodipodi:cx="24.450865"
- sodipodi:cy="23.959385"
- d="M 38.481395 23.959385 A 14.03053 14.03053 0 1 1 10.420335,23.959385 A 14.03053 14.03053 0 1 1 38.481395 23.959385 z"
- transform="matrix(0.924879,0,0,0.924459,1.889957,1.34006)" />
- style="opacity:1;fill:url(#linearGradient2279);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.12198293;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- sodipodi:cx="24.450865"
- sodipodi:cy="23.959385"
- d="M 38.481395 23.959385 A 14.03053 14.03053 0 1 1 10.420335,23.959385 A 14.03053 14.03053 0 1 1 38.481395 23.959385 z"
- transform="matrix(0.890914,0,0,0.891279,2.716374,2.14037)" />
- style="opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- sodipodi:cy="-2.7068274"
- sodipodi:rx="2.4204714"
- sodipodi:ry="1.7230475"
- d="M 12.963882 -2.7068274 A 2.4204714 1.7230475 0 1 1 8.1229389,-2.7068274 A 2.4204714 1.7230475 0 1 1 12.963882 -2.7068274 z"
- transform="matrix(0.827565,0,0,0.87352,11.27774,22.85935)" />
- style="opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- sodipodi:cy="-2.7068274"
- sodipodi:rx="2.4204714"
- sodipodi:ry="1.7230475"
- d="M 12.963882 -2.7068274 A 2.4204714 1.7230475 0 1 1 8.1229389,-2.7068274 A 2.4204714 1.7230475 0 1 1 12.963882 -2.7068274 z"
- transform="matrix(0.827567,0,0,0.87352,20.27772,22.86958)" />
- style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#2e3436;stroke-width:4.5851903;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- sodipodi:cx="24.450865"
- sodipodi:cy="23.959385"
- d="M 36.657066,30.877796 A 14.03053,14.03053 0 0 1 11.928959,30.288496"
- transform="matrix(0.453563,0,0,0.419476,13.51464,14.26249)"
- sodipodi:start="0.51564596"
- sodipodi:open="true" />
- style="opacity:0.5;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.75245398;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- sodipodi:cx="26.658085"
- sodipodi:cy="20.675463"
- sodipodi:ry="8.2640066"
- d="M 36.521577 20.675463 A 9.863492 8.2640066 0 1 1 16.794593,20.675463 A 9.863492 8.2640066 0 1 1 36.521577 20.675463 z"
- transform="matrix(1.216989,0,0,1.451287,-7.948546,-6.503855)" />
--- a/libpurple/protocols/gg/roster.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1092 +0,0 @@
- * 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
- * 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>
-#define GGP_ROSTER_SYNC_SETT "gg-synchronized"
-#define GGP_ROSTER_DEBUG 0
-#define GGP_ROSTER_GROUPID_DEFAULT "00000000-0000-0000-0000-000000000000"
-#define GGP_ROSTER_GROUPID_BOTS "0b345af6-0001-0000-0000-000000000004"
-/* TODO: ignored contacts synchronization (?) */
- PurpleXmlNode *groups_node, *contacts_node;
- * Key: (uin_t) user identifier
- * Value: (PurpleXmlNode*) xml node for contact
- GHashTable *contact_nodes;
- * Key: (gchar*) group id
- * Value: (PurpleXmlNode*) xml node for group
- GHashTable *group_nodes;
- * Key: (gchar*) group name
- * Value: (gchar*) group id
- * Key: (gchar*) group id
- * Value: (gchar*) group name
- GHashTable *group_names;
- GGP_ROSTER_CHANGE_CONTACT_UPDATE,
- GGP_ROSTER_CHANGE_CONTACT_REMOVE,
- GGP_ROSTER_CHANGE_GROUP_RENAME,
-static inline ggp_roster_session_data *
-ggp_roster_get_rdata(PurpleConnection *gc);
-static void ggp_roster_content_free(ggp_roster_content *content);
-static void ggp_roster_change_free(gpointer change);
-static int ggp_roster_get_version(PurpleConnection *gc);
-static gboolean ggp_roster_timer_cb(gpointer _gc);
-static void ggp_roster_dump(ggp_roster_content *content);
-/* synchronization control */
-static gboolean ggp_roster_is_synchronized(PurpleBuddy *buddy);
-static void ggp_roster_set_synchronized(PurpleConnection *gc,
- PurpleBuddy *buddy, gboolean synchronized);
-static gboolean ggp_roster_reply_list_read_group(PurpleXmlNode *node,
- ggp_roster_content *content);
-static gboolean ggp_roster_reply_list_read_buddy(PurpleConnection *gc,
- PurpleXmlNode *node, ggp_roster_content *content, GHashTable *remove_buddies);
-static void ggp_roster_reply_list(PurpleConnection *gc, uint32_t version,
-static const gchar * ggp_roster_send_update_group_add(
- ggp_roster_content *content, PurpleGroup *group);
-static gboolean ggp_roster_send_update_contact_update(PurpleConnection *gc,
- ggp_roster_change *change);
-static gboolean ggp_roster_send_update_contact_remove(PurpleConnection *gc,
- ggp_roster_change *change);
-static gboolean ggp_roster_send_update_group_rename(PurpleConnection *gc,
- ggp_roster_change *change);
-static void ggp_roster_send_update(PurpleConnection *gc);
-static void ggp_roster_reply_ack(PurpleConnection *gc, uint32_t version);
-static void ggp_roster_reply_reject(PurpleConnection *gc, uint32_t version);
-/******************************************************************************/
-static inline ggp_roster_session_data *
-ggp_roster_get_rdata(PurpleConnection *gc)
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- return &accdata->roster_data;
-static void ggp_roster_content_free(ggp_roster_content *content)
- g_clear_pointer(&content->xml, purple_xmlnode_free);
- g_clear_pointer(&content->contact_nodes, g_hash_table_destroy);
- g_clear_pointer(&content->group_nodes, g_hash_table_destroy);
- g_clear_pointer(&content->group_ids, g_hash_table_destroy);
- g_clear_pointer(&content->group_names, g_hash_table_destroy);
- g_free(content->bots_group_id);
-static void ggp_roster_change_free(gpointer _change)
- ggp_roster_change *change = _change;
- if (change->type == GGP_ROSTER_CHANGE_GROUP_RENAME) {
- g_free(change->data.group_rename.old_name);
- g_free(change->data.group_rename.new_name);
-static int ggp_roster_get_version(PurpleConnection *gc)
- ggp_roster_content *content = ggp_roster_get_rdata(gc)->content;
- return content->version;
-static gboolean ggp_roster_timer_cb(gpointer _gc)
- PurpleConnection *gc = _gc;
- PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
- ggp_roster_send_update(gc);
-static void ggp_roster_dump(ggp_roster_content *content)
- g_return_if_fail(content != NULL);
- g_return_if_fail(content->xml != NULL);
- str = purple_xmlnode_to_formatted_str(content->xml, &len);
- purple_debug_misc("gg", "ggp_roster_dump: [%s]\n", str);
-/*******************************************************************************
- ******************************************************************************/
-gboolean ggp_roster_enabled(void)
- static gboolean checked = FALSE;
- static gboolean enabled;
- enabled = gg_libgadu_check_feature(
- GG_LIBGADU_FEATURE_USERLIST100);
-void ggp_roster_setup(PurpleConnection *gc)
- ggp_roster_session_data *rdata = ggp_roster_get_rdata(gc);
- rdata->sent_updates = NULL;
- rdata->pending_updates = NULL;
- rdata->is_updating = FALSE;
- if (ggp_roster_enabled())
- rdata->timer = g_timeout_add_seconds(2,
- ggp_roster_timer_cb, gc);
-void ggp_roster_cleanup(PurpleConnection *gc)
- ggp_roster_session_data *rdata = ggp_roster_get_rdata(gc);
- g_clear_handle_id(&rdata->timer, g_source_remove);
- ggp_roster_content_free(rdata->content);
- g_list_free_full(rdata->sent_updates, ggp_roster_change_free);
- g_list_free_full(rdata->pending_updates, ggp_roster_change_free);
-/*******************************************************************************
- * Synchronization control.
- ******************************************************************************/
-static gboolean ggp_roster_is_synchronized(PurpleBuddy *buddy)
- gboolean ret = purple_blist_node_get_bool(PURPLE_BLIST_NODE(buddy),
-static void ggp_roster_set_synchronized(PurpleConnection *gc,
- PurpleBuddy *buddy, gboolean synchronized)
- ggp_roster_session_data *rdata = ggp_roster_get_rdata(gc);
- uin_t uin = ggp_str_to_uin(purple_buddy_get_name(buddy));
- ggp_roster_change *change;
- purple_blist_node_set_bool(PURPLE_BLIST_NODE(buddy),
- GGP_ROSTER_SYNC_SETT, synchronized);
- change = g_new0(ggp_roster_change, 1);
- change->type = GGP_ROSTER_CHANGE_CONTACT_UPDATE;
- change->data.uin = uin;
- rdata->pending_updates =
- g_list_append(rdata->pending_updates, change);
-void ggp_roster_request_update(PurpleConnection *gc)
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- int local_version = ggp_roster_get_version(gc);
- if (!ggp_roster_enabled()) {
- purple_debug_warning("gg", "ggp_roster_request_update: "
- purple_debug_info("gg", "ggp_roster_request_update: local=%u\n",
- gg_userlist100_request(accdata->session, GG_USERLIST100_GET,
- local_version, GG_USERLIST100_FORMAT_TYPE_GG100, NULL);
-/*******************************************************************************
- ******************************************************************************/
-void ggp_roster_reply(PurpleConnection *gc,
- struct gg_event_userlist100_reply *reply)
- if (GG_USERLIST100_FORMAT_TYPE_GG100 != reply->format_type) {
- purple_debug_warning("gg", "ggp_roster_reply: "
- "unsupported format type (%x)\n", reply->format_type);
- if (reply->type == GG_USERLIST100_REPLY_LIST)
- ggp_roster_reply_list(gc, reply->version, reply->reply);
- else if (reply->type == 0x01) /* list up to date (TODO: push to libgadu) */
- purple_debug_info("gg", "ggp_roster_reply: list up to date\n");
- else if (reply->type == GG_USERLIST100_REPLY_ACK)
- ggp_roster_reply_ack(gc, reply->version);
- else if (reply->type == GG_USERLIST100_REPLY_REJECT)
- ggp_roster_reply_reject(gc, reply->version);
- purple_debug_error("gg", "ggp_roster_reply: "
- "unsupported reply (%x)\n", reply->type);
-void ggp_roster_version(PurpleConnection *gc,
- struct gg_event_userlist100_version *version)
- int local_version = ggp_roster_get_version(gc);
- int remote_version = version->version;
- purple_debug_info("gg", "ggp_roster_version: local=%u, remote=%u\n",
- local_version, remote_version);
- if (local_version < remote_version)
- ggp_roster_request_update(gc);
-/*******************************************************************************
- ******************************************************************************/
-ggp_roster_alias_buddy(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
- PurpleConnection *gc, const gchar *who,
- g_return_if_fail(who != NULL);
- if (!ggp_roster_enabled())
- purple_debug_misc("gg", "ggp_roster_alias_buddy(\"%s\", \"%s\")\n",
- buddy = purple_blist_find_buddy(purple_connection_get_account(gc), who);
- g_return_if_fail(buddy != NULL);
- ggp_roster_set_synchronized(gc, buddy, FALSE);
-ggp_roster_group_buddy(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
- PurpleConnection *gc, const gchar *who,
- const gchar *old_group, const gchar *new_group)
- ggp_roster_session_data *rdata = ggp_roster_get_rdata(gc);
- ggp_roster_change *change;
- if (!ggp_roster_enabled())
- if (rdata->is_updating)
- purple_debug_misc("gg", "ggp_roster_group_buddy: "
- "who=\"%s\", group=\"%s\" -> \"%s\")\n",
- who, old_group, new_group);
- /* purple_blist_find_buddy(..., who) is not accessible at this moment */
- change = g_new0(ggp_roster_change, 1);
- change->type = GGP_ROSTER_CHANGE_CONTACT_UPDATE;
- change->data.uin = ggp_str_to_uin(who);
- rdata->pending_updates = g_list_append(rdata->pending_updates, change);
-ggp_roster_rename_group(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
- PurpleConnection *gc, const gchar *old_name,
- PurpleGroup *group, G_GNUC_UNUSED GList *moved_buddies)
- ggp_roster_session_data *rdata = ggp_roster_get_rdata(gc);
- ggp_roster_change *change;
- if (!ggp_roster_enabled())
- change = g_new0(ggp_roster_change, 1);
- change->type = GGP_ROSTER_CHANGE_GROUP_RENAME;
- change->data.group_rename.old_name = g_strdup(old_name);
- change->data.group_rename.new_name =
- g_strdup(purple_group_get_name(group));
- rdata->pending_updates = g_list_append(rdata->pending_updates, change);
-ggp_roster_add_buddy(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
- PurpleConnection *gc, PurpleBuddy *buddy,
- G_GNUC_UNUSED PurpleGroup *group,
- G_GNUC_UNUSED const gchar *message)
- g_return_if_fail(gc != NULL);
- g_return_if_fail(buddy != NULL);
- if (!ggp_roster_enabled())
- ggp_roster_set_synchronized(gc, buddy, FALSE);
-ggp_roster_remove_buddy(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
- PurpleConnection *gc, PurpleBuddy *buddy,
- G_GNUC_UNUSED PurpleGroup *group)
- ggp_roster_session_data *rdata = ggp_roster_get_rdata(gc);
- ggp_roster_change *change;
- if (!ggp_roster_enabled())
- change = g_new0(ggp_roster_change, 1);
- change->type = GGP_ROSTER_CHANGE_CONTACT_REMOVE;
- change->data.uin = ggp_str_to_uin(purple_buddy_get_name(buddy));
- rdata->pending_updates = g_list_append(rdata->pending_updates, change);
-/*******************************************************************************
- ******************************************************************************/
-static gboolean ggp_roster_reply_list_read_group(PurpleXmlNode *node,
- ggp_roster_content *content)
- gboolean succ = TRUE, is_bot, is_default;
- succ &= ggp_xml_get_string(node, "Id", &id);
- succ &= ggp_xml_get_string(node, "Name", &name);
- succ &= ggp_xml_get_bool(node, "IsRemovable", &removable);
- g_return_val_if_reached(FALSE);
- is_bot = (strcmp(id, GGP_ROSTER_GROUPID_BOTS) == 0 ||
- g_strcmp0(name, "Pomocnicy") == 0);
- is_default = (strcmp(id, GGP_ROSTER_GROUPID_DEFAULT) == 0 ||
- g_strcmp0(name, PURPLE_BLIST_DEFAULT_GROUP_NAME) == 0 ||
- g_strcmp0(name, "[default]") == 0);
- if (!content->bots_group_id && is_bot)
- content->bots_group_id = g_strdup(id);
- if (!removable || is_bot || is_default) {
- g_hash_table_insert(content->group_nodes, g_strdup(id), node);
- g_hash_table_insert(content->group_ids, g_strdup(name), g_strdup(id));
- g_hash_table_insert(content->group_names, id, name);
-static gboolean ggp_roster_reply_list_read_buddy(PurpleConnection *gc,
- PurpleXmlNode *node, ggp_roster_content *content, GHashTable *remove_buddies)
- gchar *alias, *group_name = NULL;
- PurpleXmlNode *group_list, *group_elem;
- PurpleBuddy *buddy = NULL;
- PurpleGroup *group = NULL;
- PurpleGroup *currentGroup;
- gboolean alias_changed;
- PurpleAccount *account = purple_connection_get_account(gc);
- succ &= ggp_xml_get_string(node, "ShowName", &alias);
- succ &= ggp_xml_get_uint(node, "GGNumber", &uin);
- group_list = purple_xmlnode_get_child(node, "Groups");
- succ &= (group_list != NULL);
- g_return_val_if_reached(FALSE);
- g_hash_table_insert(content->contact_nodes, GINT_TO_POINTER(uin), node);
- /* check, if alias is set */
- strcmp(alias, ggp_uin_to_str(uin)) == 0)
- /* getting (eventually creating) group */
- group_elem = purple_xmlnode_get_child(group_list, "GroupId");
- while (group_elem != NULL) {
- if (!ggp_xml_get_string(group_elem, NULL, &id))
- isbot = (0 == g_strcmp0(id, content->bots_group_id));
- group_name = g_hash_table_lookup(content->group_names, id);
- /* we don't want to import bots;
- * they are inserted to roster by default
- if (group_name != NULL)
- group_elem = purple_xmlnode_get_next_twin(group_elem);
- group = purple_blist_find_group(group_name);
- group = purple_group_new(group_name);
- purple_blist_add_group(group, NULL);
- /* add buddy, if doesn't exists */
- buddy = purple_blist_find_buddy(account, ggp_uin_to_str(uin));
- g_hash_table_remove(remove_buddies, GINT_TO_POINTER(uin));
- purple_debug_info("gg", "ggp_roster_reply_list_read_buddy: "
- "adding %u (%s) to buddy list\n", uin, alias);
- buddy = purple_buddy_new(account, ggp_uin_to_str(uin), alias);
- purple_blist_add_buddy(buddy, NULL, group, NULL);
- ggp_roster_set_synchronized(gc, buddy, TRUE);
- /* buddy exists, but is not synchronized - local list has priority */
- if (!ggp_roster_is_synchronized(buddy)) {
- purple_debug_misc("gg", "ggp_roster_reply_list_read_buddy: "
- "ignoring not synchronized %u (%s)\n",
- uin, purple_buddy_get_name(buddy));
- currentGroup = ggp_purplew_buddy_get_group_only(buddy);
- (0 != g_strcmp0(alias, purple_buddy_get_alias_only(buddy)));
- if (currentGroup == group && !alias_changed) {
- purple_debug_misc("gg", "ggp_roster_reply_list_read_buddy: "
- "updating %u (%s) - alias=\"%s\"->\"%s\", group=%p->%p (%s)\n",
- uin, purple_buddy_get_name(buddy),
- purple_buddy_get_alias(buddy), alias,
- currentGroup, group, group_name);
- purple_buddy_set_local_alias(buddy, alias);
- if (currentGroup != group)
- purple_blist_add_buddy(buddy, NULL, group, NULL);
-static void ggp_roster_reply_list(PurpleConnection *gc, uint32_t version,
- ggp_roster_session_data *rdata = ggp_roster_get_rdata(gc);
- PurpleXmlNode *xml, *xml_it;
- PurpleAccount *account;
- GHashTable *remove_buddies;
- GList *update_buddies = NULL, *local_groups, *it, *table_values;
- ggp_roster_content *content;
- g_return_if_fail(gc != NULL);
- g_return_if_fail(data != NULL);
- account = purple_connection_get_account(gc);
- purple_debug_info("gg", "ggp_roster_reply_list: got list, version=%u\n",
- xml = purple_xmlnode_from_str(data, -1);
- purple_debug_warning("gg", "ggp_roster_reply_list: "
- ggp_roster_content_free(rdata->content);
- rdata->is_updating = TRUE;
- content = g_new0(ggp_roster_content, 1);
- content->version = version;
- content->contact_nodes = g_hash_table_new(NULL, NULL);
- content->group_nodes = g_hash_table_new_full(
- g_str_hash, g_str_equal, g_free, NULL);
- content->group_ids = g_hash_table_new_full(
- g_str_hash, g_str_equal, g_free, g_free);
- content->group_names = g_hash_table_new_full(
- g_str_hash, g_str_equal, g_free, g_free);
- ggp_roster_dump(content);
- content->groups_node = purple_xmlnode_get_child(xml, "Groups");
- if (content->groups_node == NULL) {
- ggp_roster_content_free(content);
- xml_it = purple_xmlnode_get_child(content->groups_node, "Group");
- while (xml_it != NULL) {
- if (!ggp_roster_reply_list_read_group(xml_it, content)) {
- ggp_roster_content_free(content);
- xml_it = purple_xmlnode_get_next_twin(xml_it);
- /* dumping current group list */
- local_groups = ggp_purplew_account_get_groups(account, TRUE);
- /* dumping current buddy list
- * - remove synchronized ones, if not found in list at server
- * - upload not synchronized ones
- local_buddies = purple_blist_find_buddies(account, NULL);
- remove_buddies = g_hash_table_new(g_direct_hash, g_direct_equal);
- while (local_buddies) {
- PurpleBuddy *buddy = local_buddies->data;
- uin_t uin = ggp_str_to_uin(purple_buddy_get_name(buddy));
- g_slist_delete_link(local_buddies, local_buddies);
- if (ggp_roster_is_synchronized(buddy))
- g_hash_table_insert(remove_buddies,
- GINT_TO_POINTER(uin), buddy);
- update_buddies = g_list_append(update_buddies, buddy);
- content->contacts_node = purple_xmlnode_get_child(xml, "Contacts");
- if (content->contacts_node == NULL) {
- g_hash_table_destroy(remove_buddies);
- g_list_free(update_buddies);
- ggp_roster_content_free(content);
- xml_it = purple_xmlnode_get_child(content->contacts_node, "Contact");
- while (xml_it != NULL) {
- if (!ggp_roster_reply_list_read_buddy(gc, xml_it, content,
- g_hash_table_destroy(remove_buddies);
- g_list_free(update_buddies);
- ggp_roster_content_free(content);
- xml_it = purple_xmlnode_get_next_twin(xml_it);
- /* removing buddies, which are not present in roster */
- table_values = g_hash_table_get_values(remove_buddies);
- it = g_list_first(table_values);
- PurpleBuddy *buddy = it->data;
- if (!ggp_roster_is_synchronized(buddy))
- purple_debug_info("gg", "ggp_roster_reply_list: "
- "removing %s from buddy list\n",
- purple_buddy_get_name(buddy));
- purple_blist_remove_buddy(buddy);
- g_list_free(table_values);
- g_hash_table_destroy(remove_buddies);
- /* remove groups, which are empty, but had contacts before
- it = g_list_first(local_groups);
- PurpleGroup *group = it->data;
- if (purple_counting_node_get_total_size(PURPLE_COUNTING_NODE(group)) != 0)
- purple_debug_info("gg", "ggp_roster_reply_list: "
- "removing group %s\n", purple_group_get_name(group));
- purple_blist_remove_group(group);
- g_list_free(local_groups);
- /* adding not synchronized buddies */
- it = g_list_first(update_buddies);
- PurpleBuddy *buddy = it->data;
- uin_t uin = ggp_str_to_uin(purple_buddy_get_name(buddy));
- ggp_roster_change *change;
- purple_debug_misc("gg", "ggp_roster_reply_list: "
- "adding change of %u for roster\n", uin);
- change = g_new0(ggp_roster_change, 1);
- change->type = GGP_ROSTER_CHANGE_CONTACT_UPDATE;
- change->data.uin = uin;
- rdata->pending_updates =
- g_list_append(rdata->pending_updates, change);
- g_list_free(update_buddies);
- rdata->content = content;
- rdata->is_updating = FALSE;
- purple_debug_info("gg", "ggp_roster_reply_list: "
- "import done, version=%u\n", version);
-/*******************************************************************************
- ******************************************************************************/
-static const gchar * ggp_roster_send_update_group_add(
- ggp_roster_content *content, PurpleGroup *group)
- const char *id_existing, *group_name;
- PurpleXmlNode *group_node;
- group_name = purple_group_get_name(group);
- g_hash_table_lookup(content->group_ids, group_name);
- id_existing = GGP_ROSTER_GROUPID_DEFAULT;
- purple_debug_info("gg", "ggp_roster_send_update_group_add: adding %s\n",
- purple_group_get_name(group));
- id = g_uuid_string_random();
- group_node = purple_xmlnode_new_child(content->groups_node, "Group");
- succ &= ggp_xml_set_string(group_node, "Id", id);
- succ &= ggp_xml_set_string(group_node, "Name", group_name);
- succ &= ggp_xml_set_string(group_node, "IsExpanded", "true");
- succ &= ggp_xml_set_string(group_node, "IsRemovable", "true");
- content->needs_update = TRUE;
- g_hash_table_insert(content->group_ids, g_strdup(group_name),
- g_hash_table_replace(content->group_nodes, id, group_node);
- g_return_val_if_fail(succ, NULL);
-static gboolean ggp_roster_send_update_contact_update(PurpleConnection *gc,
- ggp_roster_change *change)
- PurpleAccount *account = purple_connection_get_account(gc);
- ggp_roster_content *content = ggp_roster_get_rdata(gc)->content;
- uin_t uin = change->data.uin;
- PurpleXmlNode *buddy_node, *contact_groups;
- g_return_val_if_fail(change->type == GGP_ROSTER_CHANGE_CONTACT_UPDATE,
- buddy = purple_blist_find_buddy(account, ggp_uin_to_str(uin));
- buddy_node = g_hash_table_lookup(content->contact_nodes,
- group_id = ggp_roster_send_update_group_add(content,
- ggp_purplew_buddy_get_group_only(buddy));
- if (buddy_node) { /* update existing */
- purple_debug_misc("gg", "ggp_roster_send_update_contact_update:"
- " updating %u...\n", uin);
- succ &= ggp_xml_set_string(buddy_node, "ShowName",
- purple_buddy_get_alias(buddy));
- contact_groups = purple_xmlnode_get_child(buddy_node, "Groups");
- g_assert(contact_groups);
- ggp_xmlnode_remove_children(contact_groups);
- succ &= ggp_xml_set_string(contact_groups, "GroupId", group_id);
- g_return_val_if_fail(succ, FALSE);
- guid = g_uuid_string_random();
- purple_debug_misc("gg", "ggp_roster_send_update_contact_update: "
- "adding %u...\n", uin);
- buddy_node = purple_xmlnode_new_child(content->contacts_node, "Contact");
- succ &= ggp_xml_set_string(buddy_node, "Guid", guid);
- succ &= ggp_xml_set_uint(buddy_node, "GGNumber", uin);
- succ &= ggp_xml_set_string(buddy_node, "ShowName",
- purple_buddy_get_alias(buddy));
- contact_groups = purple_xmlnode_new_child(buddy_node, "Groups");
- g_assert(contact_groups);
- succ &= ggp_xml_set_string(contact_groups, "GroupId", group_id);
- purple_xmlnode_new_child(buddy_node, "Avatars");
- succ &= ggp_xml_set_bool(buddy_node, "FlagBuddy", TRUE);
- succ &= ggp_xml_set_bool(buddy_node, "FlagNormal", TRUE);
- succ &= ggp_xml_set_bool(buddy_node, "FlagFriend", TRUE);
- /* we don't use Guid, so update is not needed
- * content->needs_update = TRUE;
- g_hash_table_insert(content->contact_nodes, GINT_TO_POINTER(uin),
- g_return_val_if_fail(succ, FALSE);
-static gboolean ggp_roster_send_update_contact_remove(PurpleConnection *gc,
- ggp_roster_change *change)
- PurpleAccount *account = purple_connection_get_account(gc);
- ggp_roster_content *content = ggp_roster_get_rdata(gc)->content;
- uin_t uin = change->data.uin;
- PurpleXmlNode *buddy_node;
- g_return_val_if_fail(change->type == GGP_ROSTER_CHANGE_CONTACT_REMOVE,
- buddy = purple_blist_find_buddy(account, ggp_uin_to_str(uin));
- purple_debug_info("gg", "ggp_roster_send_update_contact_remove:"
- " contact %u re-added\n", uin);
- buddy_node = g_hash_table_lookup(content->contact_nodes,
- if (!buddy_node) /* already removed */
- purple_debug_info("gg", "ggp_roster_send_update_contact_remove: "
- purple_xmlnode_free(buddy_node);
- g_hash_table_remove(content->contact_nodes, GINT_TO_POINTER(uin));
-static gboolean ggp_roster_send_update_group_rename(PurpleConnection *gc,
- ggp_roster_change *change)
- PurpleAccount *account = purple_connection_get_account(gc);
- ggp_roster_content *content = ggp_roster_get_rdata(gc)->content;
- const char *old_name = change->data.group_rename.old_name;
- const char *new_name = change->data.group_rename.new_name;
- PurpleXmlNode *group_node;
- g_return_val_if_fail(change->type == GGP_ROSTER_CHANGE_GROUP_RENAME,
- purple_debug_misc("gg", "ggp_roster_send_update_group_rename: "
- "\"%s\"->\"%s\"\n", old_name, new_name);
- /* moving to or from default group instead of renaming it */
- if (0 == g_strcmp0(old_name, PURPLE_BLIST_DEFAULT_GROUP_NAME) ||
- 0 == g_strcmp0(new_name, PURPLE_BLIST_DEFAULT_GROUP_NAME))
- group = purple_blist_find_group(new_name);
- purple_debug_info("gg", "ggp_roster_send_update_group_rename: "
- "invalidating buddies in default group\n");
- group_buddies = ggp_purplew_group_get_buddies(group, account);
- while (group_buddies) {
- ggp_roster_set_synchronized(gc, group_buddies->data,
- group_buddies = g_list_delete_link(group_buddies,
- group_id = g_hash_table_lookup(content->group_ids, old_name);
- purple_debug_info("gg", "ggp_roster_send_update_group_rename: "
- "%s is not present at roster\n", old_name);
- group_node = g_hash_table_lookup(content->group_nodes, group_id);
- purple_debug_error("gg", "ggp_roster_send_update_group_rename: "
- "node for %s not found, id=%s\n", old_name, group_id);
- g_hash_table_remove(content->group_ids, old_name);
- g_hash_table_remove(content->group_ids, old_name);
- g_hash_table_insert(content->group_ids, g_strdup(new_name),
- g_hash_table_insert(content->group_nodes, g_strdup(group_id),
- return ggp_xml_set_string(group_node, "Name", new_name);
-static void ggp_roster_send_update(PurpleConnection *gc)
- GGPInfo *accdata = purple_connection_get_protocol_data(gc);
- ggp_roster_session_data *rdata = ggp_roster_get_rdata(gc);
- ggp_roster_content *content = rdata->content;
- /* an update is running now */
- if (rdata->sent_updates)
- /* no pending updates found */
- if (!rdata->pending_updates)
- purple_debug_info("gg", "ggp_roster_send_update: "
- "pending updates found\n");
- rdata->sent_updates = rdata->pending_updates;
- rdata->pending_updates = NULL;
- updates_it = g_list_first(rdata->sent_updates);
- ggp_roster_change *change = updates_it->data;
- updates_it = g_list_next(updates_it);
- if (change->type == GGP_ROSTER_CHANGE_CONTACT_UPDATE) {
- succ = ggp_roster_send_update_contact_update(gc, change);
- } else if (change->type == GGP_ROSTER_CHANGE_CONTACT_REMOVE) {
- succ = ggp_roster_send_update_contact_remove(gc, change);
- } else if (change->type == GGP_ROSTER_CHANGE_GROUP_RENAME) {
- succ = ggp_roster_send_update_group_rename(gc, change);
- purple_debug_error("gg", "ggp_roster_send_update: not handled");
- g_return_if_fail(succ);
- ggp_roster_dump(content);
- str = purple_xmlnode_to_str(content->xml, &len);
- gg_userlist100_request(accdata->session, GG_USERLIST100_PUT,
- content->version, GG_USERLIST100_FORMAT_TYPE_GG100, str);
-static void ggp_roster_reply_ack(PurpleConnection *gc, uint32_t version)
- PurpleAccount *account = purple_connection_get_account(gc);
- ggp_roster_session_data *rdata = ggp_roster_get_rdata(gc);
- ggp_roster_content *content = rdata->content;
- purple_debug_info("gg", "ggp_roster_reply_ack: version=%u\n", version);
- /* set synchronization flag for all buddies, that were updated at roster */
- updates_it = g_list_first(rdata->sent_updates);
- ggp_roster_change *change = updates_it->data;
- updates_it = g_list_next(updates_it);
- if (change->type != GGP_ROSTER_CHANGE_CONTACT_UPDATE)
- buddy = purple_blist_find_buddy(account,
- ggp_uin_to_str(change->data.uin));
- ggp_roster_set_synchronized(gc, buddy, TRUE);
- /* we need to remove "synchronized" flag for all contacts, that have
- * been modified between roster update start and now
- updates_it = g_list_first(rdata->pending_updates);
- ggp_roster_change *change = updates_it->data;
- updates_it = g_list_next(updates_it);
- if (change->type != GGP_ROSTER_CHANGE_CONTACT_UPDATE)
- buddy = purple_blist_find_buddy(account,
- ggp_uin_to_str(change->data.uin));
- if (buddy && ggp_roster_is_synchronized(buddy))
- ggp_roster_set_synchronized(gc, buddy, FALSE);
- g_clear_list(&rdata->sent_updates, ggp_roster_change_free);
- /* bump roster version or update it, if needed */
- g_return_if_fail(content != NULL);
- if (content->needs_update) {
- ggp_roster_content_free(rdata->content);
- /* we have to wait for gg_event_userlist100_version
- * ggp_roster_request_update(gc);
- content->version = version;
-static void ggp_roster_reply_reject(PurpleConnection *gc, uint32_t version)
- ggp_roster_session_data *rdata = ggp_roster_get_rdata(gc);
- purple_debug_info("gg", "ggp_roster_reply_reject: version=%u\n",
- g_return_if_fail(rdata->sent_updates);
- rdata->pending_updates = g_list_concat(rdata->pending_updates,
- rdata->sent_updates = NULL;
- ggp_roster_content_free(rdata->content);
- ggp_roster_request_update(gc);
-/******************************************************************************/
--- a/libpurple/protocols/gg/roster.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
- * 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
- * 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
-#ifndef PURPLE_GG_ROSTER_H
-#define PURPLE_GG_ROSTER_H
- GList *pending_updates;
-} ggp_roster_session_data;
-gboolean ggp_roster_enabled(void);
-void ggp_roster_setup(PurpleConnection *gc);
-void ggp_roster_cleanup(PurpleConnection *gc);
-/* synchronization control */
-void ggp_roster_request_update(PurpleConnection *gc);
-void ggp_roster_reply(PurpleConnection *gc,
- struct gg_event_userlist100_reply *reply);
-void ggp_roster_version(PurpleConnection *gc,
- struct gg_event_userlist100_version *version);
-/* libpurple callbacks */
-void ggp_roster_alias_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *who,
-void ggp_roster_group_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *who,
- const char *old_group, const char *new_group);
-void ggp_roster_rename_group(PurpleProtocolServer *protocol_server, PurpleConnection *, const char *old_name,
- PurpleGroup *group, GList *moved_buddies);
-void ggp_roster_add_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleBuddy *buddy,
- PurpleGroup *group, const char *message);
-void ggp_roster_remove_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleBuddy *buddy,
-#endif /* PURPLE_GG_ROSTER_H */
--- a/libpurple/protocols/gg/servconn.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,118 +0,0 @@
- * 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
- * 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
-#define GGP_SERVCONN_HISTORY_PREF "/plugins/prpl/gg/server_history"
-#define GGP_SERVCONN_HISTORY_MAXLEN 15
- PurpleAccountOption *server_option;
-} ggp_servconn_global_data;
-static ggp_servconn_global_data global_data;
-void ggp_servconn_setup(PurpleAccountOption *server_option)
- purple_prefs_add_string_list(GGP_SERVCONN_HISTORY_PREF, NULL);
- global_data.server_option = server_option;
- global_data.server_history =
- purple_prefs_get_string_list(GGP_SERVCONN_HISTORY_PREF);
- extra = g_list_nth(global_data.server_history, GGP_SERVCONN_HISTORY_MAXLEN);
- /* Truncate the list to the maximum. */
- extra->prev->next = NULL;
- g_list_free_full(extra, g_free);
- if(server_option != NULL) {
- purple_account_option_string_set_hints(global_data.server_option,
- ggp_servconn_get_servers());
-void ggp_servconn_cleanup(void)
- g_clear_list(&global_data.server_history, g_free);
-void ggp_servconn_add_server(const gchar *server)
- old_entry = g_list_find_custom(global_data.server_history, server,
- (GCompareFunc)g_strcmp0);
- g_free(old_entry->data);
- global_data.server_history = g_list_delete_link(
- global_data.server_history, old_entry);
- global_data.server_history = g_list_prepend(global_data.server_history,
- g_list_nth(global_data.server_history, GGP_SERVCONN_HISTORY_MAXLEN);
- if (old_entry != NULL) {
- /* Truncate the list to the maximum. */
- old_entry->prev->next = NULL;
- g_list_free_full(old_entry, g_free);
- purple_prefs_set_string_list(GGP_SERVCONN_HISTORY_PREF,
- global_data.server_history);
- purple_account_option_string_set_hints(global_data.server_option,
- ggp_servconn_get_servers());
-ggp_servconn_get_servers(void)
- GSList *new_list = NULL;
- it = g_list_first(global_data.server_history);
- new_list = g_slist_append(new_list, g_strdup(it->data));
-ggp_servconn_remote_disconnect(PurpleConnection *gc)
- purple_debug_info("gg", "Server remotely closes connection");
- purple_account_disconnect(purple_connection_get_account(gc));
--- a/libpurple/protocols/gg/servconn.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
- * 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
- * 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
-#ifndef PURPLE_GG_SERVCONN_H
-#define PURPLE_GG_SERVCONN_H
-void ggp_servconn_setup(PurpleAccountOption *server_option);
-void ggp_servconn_cleanup(void);
-void ggp_servconn_add_server(const gchar *server);
-GSList * ggp_servconn_get_servers(void);
-void ggp_servconn_remote_disconnect(PurpleConnection *gc);
-#endif /* PURPLE_GG_SERVCONN_H */
--- a/libpurple/protocols/gg/status.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,449 +0,0 @@
- * 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
- * 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>
-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);
-static gchar * ggp_status_validate_description(const gchar* msg)
- if (msg == NULL || msg[0] == '\0')
- return ggp_utf8_strndup(msg, GG_STATUS_DESCR_MAXSIZE);
-ggp_status_types(G_GNUC_UNUSED PurpleProtocol *protocol,
- G_GNUC_UNUSED PurpleAccount *account)
- 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));
-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);
- gchar *stripped = purple_markup_strip_html(status_message);
- *message = ggp_status_validate_description(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)
- 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_DESCR:
- case GG_STATUS_AVAIL_DESCR:
- return purple_primitive_get_id_from_type(
- PURPLE_STATUS_AVAILABLE);
- case GG_STATUS_BUSY_DESCR:
- return purple_primitive_get_id_from_type(
- case GG_STATUS_INVISIBLE:
- case GG_STATUS_INVISIBLE_DESCR:
- return purple_primitive_get_id_from_type(
- PURPLE_STATUS_INVISIBLE);
- case GG_STATUS_DND_DESCR:
- return purple_primitive_get_id_from_type(
- PURPLE_STATUS_UNAVAILABLE);
- 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 purple_primitive_get_name_from_type(
- purple_primitive_get_type_from_id(purple_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);
- g_free(ssdata->current_description);
- ssdata->current_description = new_description;
- gg_change_status(accdata->session, status);
- gg_change_status_descr(accdata->session, status, new_description);
-ggp_status_set_purplestatus(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
- PurpleAccount *account, PurpleStatus *status)
- if (!purple_status_is_active(status))
- status_gg = ggp_status_from_purplestatus(status, &msg);
- ggp_status_set(account, status_gg, msg);
-void ggp_status_set_disconnected(PurpleAccount *account)
- ggp_status_from_purplestatus(purple_account_get_active_status(account),
- if (!ggp_status_set(account,
- msg ? GG_STATUS_NOT_AVAIL_DESCR : GG_STATUS_NOT_AVAIL, msg))
- guint64 wait_start = ggp_microtime(), now;
- while ((ev = gg_watch_fd(info->session)) != NULL)
- if (ev->type == GG_EVENT_DISCONNECT_ACK)
- if (now - wait_start + sleep_time >= 100000)
-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,
- 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);
-gboolean ggp_status_get_status_broadcasting(PurpleConnection *gc)
- return ggp_status_get_ssdata(gc)->status_broadcasting;
-void ggp_status_set_status_broadcasting(PurpleConnection *gc,
- 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));
-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"),
- _("OK"), G_CALLBACK(ggp_status_broadcasting_dialog_ok),
- purple_request_cpar_from_connection(gc), gc);
-/*******************************************************************************
- ******************************************************************************/
-void ggp_status_got_others_buddy(PurpleConnection *gc, uin_t uin, int status,
-/******************************************************************************/
-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;
- 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);
- purple_debug_error("gg", "ggp_status_got_others: unexpected event %d",
-void ggp_status_got_others_buddy(PurpleConnection *gc, uin_t uin, int status,
- 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;
- is_own = (!g_strcmp0(ggp_uin_to_str(uin),
- purple_contact_info_get_username(info)));
- purple_debug_warning("gg",
- "ggp_status_got_others_buddy: "
- "buddy %u not found\n", uin);
- ggp_buddy_get_data(buddy)->blocked = (status == GG_STATUS_BLOCKED);
- ggp_buddy_get_data(buddy)->not_a_friend = (status == GG_STATUS_UNKNOWN);
- status_message = g_strdup(descr);
- g_strstrip(status_message);
- if (status_message[0] == '\0') {
- g_free(status_message);
- 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 : "");
- purple_protocol_got_user_status(account, ggp_uin_to_str(uin),
- purple_status, "message", status_message, NULL);
- purple_protocol_got_user_status(account, ggp_uin_to_str(uin),
- g_free(status_message);
--- a/libpurple/protocols/gg/status.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
- * 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
- * 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
-#ifndef PURPLE_GG_STATUS_H
-#define PURPLE_GG_STATUS_H
-typedef struct _ggp_status_session_data ggp_status_session_data;
-void ggp_status_setup(PurpleConnection *gc);
-void ggp_status_cleanup(PurpleConnection *gc);
-GList *ggp_status_types(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleAccount *account);
-int ggp_status_from_purplestatus(PurpleStatus *status, gchar **message);
-const gchar * ggp_status_to_purplestatus(int status);
-const gchar * ggp_status_get_name(const gchar *purple_status);
-void ggp_status_set_initial(PurpleConnection *gc, struct gg_login_params *glp);
-gboolean ggp_status_set(PurpleAccount *account, int status, const gchar* msg);
-void ggp_status_set_purplestatus(PurpleProtocolServer *protocol_server, PurpleAccount *account, PurpleStatus *status);
-void ggp_status_set_disconnected(PurpleAccount *account);
-void ggp_status_fake_to_self(PurpleConnection *gc);
-gboolean ggp_status_get_status_broadcasting(PurpleConnection *gc);
-void ggp_status_set_status_broadcasting(PurpleConnection *gc,
- gboolean broadcasting);
-void ggp_status_broadcasting_dialog(PurpleConnection *gc);
-void ggp_status_got_others(PurpleConnection *gc, struct gg_event *ev);
-#endif /* PURPLE_GG_STATUS_H */
--- a/libpurple/protocols/gg/tcpsocket.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,265 +0,0 @@
- * 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
- * Component written by Tomek Wasilczyk (http://www.wasilczyk.pl).
- * This file is dual-licensed under the GPL2+ and the X11 (MIT) licences.
- * As a recipient of this file you may choose, which license to receive the
- * code under. As a contributor, you have to ensure the new code is
- * compatible with both.
- * 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
- GSocketConnection *conn;
- GCancellable *cancellable;
-ggp_tcp_socket_data_free(GGPTcpSocketData *data)
- g_return_if_fail(data != NULL);
- if (data->cancellable != NULL) {
- g_cancellable_cancel(data->cancellable);
- g_clear_object(&data->cancellable);
- if (data->conn != NULL) {
- purple_gio_graceful_close(G_IO_STREAM(data->conn), NULL, NULL);
- g_clear_object(&data->conn);
-ggp_tcpsocket_connected(GObject *source, GAsyncResult *res, gpointer user_data)
- GGPTcpSocketData *data = user_data;
- GSocketConnection *conn;
- conn = g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(source),
- if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
- /* The connection was already closed, return now */
- purple_debug_error("gg", "socket failed to connect: %s",
- socket = g_socket_connection_get_socket(data->conn);
- fd = g_socket_get_fd(socket);
- /* XXX: For some reason if you try to connect and then immediately
- * disconnect, this gets into a state where ggp_tcpsocket_close()
- * isn't called. The cancellable is therefore not cancelled, and
- * the connection is never closed. Guard against that state here.
- if (data->gc == NULL ||
- !g_list_find(purple_connections_get_all(), data->gc)) {
- purple_debug_error("gg",
- "disconnected without closing connection: %p",
- ggp_tcp_socket_data_free(data);
- if (!gg_socket_manager_connected(data, data->priv_gg, fd)) {
- purple_debug_error("gg", "socket not handled");
- ggp_tcp_socket_data_free(data);
- info = purple_connection_get_protocol_data(data->gc);
- g_clear_handle_id(&info->inpa, g_source_remove);
- if (info->session->fd < 0)
- /* XXX: This works, but not recommended to use GSocket FDs directly */
- info->inpa = purple_input_add(info->session->fd,
- ggp_tcpsocket_inputcond_gg_to_purple(info->session->check),
- ggp_async_login_handler, data->gc);
-ggp_tcpsocket_connect(void *_gc, const char *host, int port, int is_tls,
- int is_async, void *priv)
- PurpleConnection *gc = _gc;
- GGPTcpSocketData *data;
- PURPLE_ASSERT_CONNECTION_IS_VALID(gc);
- g_return_val_if_fail(host != NULL, NULL);
- g_return_val_if_fail(is_async, NULL);
- purple_debug_misc("gg", "ggp_tcpsocket_connect(%p, %s:%d, %s, %p)",
- gc, host, port, is_tls ? "tls" : "tcp", priv);
- client = purple_gio_socket_client_new(
- purple_connection_get_account(gc), &error);
- purple_debug_error("gg", "unable to connect: %s",
- g_socket_client_set_tls(client, is_tls);
- data = g_new0(GGPTcpSocketData, 1);
- data->cancellable = g_cancellable_new();
- g_socket_client_connect_to_host_async(client, host, port,
- data->cancellable, ggp_tcpsocket_connected, data);
- g_object_unref(client);
-ggp_tcpsocket_close(G_GNUC_UNUSED void *_gc, void *_data) {
- GGPTcpSocketData *data = _data;
- ggp_tcp_socket_data_free(data);
-ggp_tcpsocket_read(G_GNUC_UNUSED void *_gc, void *_data,
- unsigned char *buffer, size_t bufsize)
- GGPTcpSocketData *data = _data;
- GPollableInputStream *input;
- if (data->conn == NULL) {
- input = G_POLLABLE_INPUT_STREAM(
- g_io_stream_get_input_stream(G_IO_STREAM(data->conn)));
- ret = g_pollable_input_stream_read_nonblocking(input,
- buffer, bufsize, NULL, &error);
- if (g_error_matches(error,
- G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
- purple_debug_error("gg", "socket read error: %s",
-ggp_tcpsocket_write(G_GNUC_UNUSED void *_gc, void *_data,
- const unsigned char *data_buf, size_t len)
- GGPTcpSocketData *data = _data;
- GPollableOutputStream *output;
- if (data->conn == NULL) {
- output = G_POLLABLE_OUTPUT_STREAM(
- g_io_stream_get_output_stream(G_IO_STREAM(data->conn)));
- ret = g_pollable_output_stream_write_nonblocking(output,
- data_buf, len, NULL, &error);
- if (g_error_matches(error,
- G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
- purple_debug_error("gg", "socket write error: %s",
-ggp_tcpsocket_setup(PurpleConnection *gc, struct gg_login_params *glp)
- glp->socket_manager_type = GG_SOCKET_MANAGER_TYPE_TLS;
- glp->socket_manager.cb_data = gc;
- glp->socket_manager.connect_cb = ggp_tcpsocket_connect;
- glp->socket_manager.close_cb = ggp_tcpsocket_close;
- glp->socket_manager.read_cb = ggp_tcpsocket_read;
- glp->socket_manager.write_cb = ggp_tcpsocket_write;
-ggp_tcpsocket_inputcond_gg_to_purple(enum gg_check_t check)
- PurpleInputCondition cond = 0;
- if (check & GG_CHECK_READ)
- cond |= PURPLE_INPUT_READ;
- if (check & GG_CHECK_WRITE)
- cond |= PURPLE_INPUT_WRITE;
--- a/libpurple/protocols/gg/tcpsocket.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
- * 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
- * Component written by Tomek Wasilczyk (http://www.wasilczyk.pl).
- * This file is dual-licensed under the GPL2+ and the X11 (MIT) licences.
- * As a recipient of this file you may choose, which license to receive the
- * code under. As a contributor, you have to ensure the new code is
- * compatible with both.
- * 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
-#ifndef PURPLE_GG_TCPSOCKET_H
-#define PURPLE_GG_TCPSOCKET_H
-ggp_tcpsocket_setup(PurpleConnection *gc, struct gg_login_params *glp);
-ggp_tcpsocket_inputcond_gg_to_purple(enum gg_check_t check);
-#endif /* PURPLE_GG_TCPSOCKET_H */
--- a/libpurple/protocols/gg/utils.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,172 +0,0 @@
- * 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
- * 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
-uin_t ggp_str_to_uin(const char *str)
- if (!str || str[0] < '0' || str[0] > '9')
- uin = strtoul(str, &endptr, 10);
- if (errno == ERANGE || endptr[0] != '\0')
-const char * ggp_uin_to_str(uin_t uin)
- static char buff[GGP_UIN_LEN_MAX + 1];
- g_snprintf(buff, GGP_UIN_LEN_MAX + 1, "%u", uin);
-ggp_get_my_uin(PurpleConnection *gc) {
- PurpleAccount *account = purple_connection_get_account(gc);
- PurpleContactInfo *info = PURPLE_CONTACT_INFO(account);
- g_return_val_if_fail(gc != NULL, 0);
- return ggp_str_to_uin(purple_contact_info_get_username(info));
-static gchar * ggp_convert(const gchar *src, const char *srcenc,
- dst = g_convert_with_fallback(src, strlen(src), dstenc, srcenc, "?",
- purple_debug_error("gg", "error converting from %s to %s: %s\n",
- srcenc, dstenc, err->message);
-gchar * ggp_convert_to_cp1250(const gchar *src)
- return ggp_convert(src, "UTF-8", "CP1250");
-gchar * ggp_convert_from_cp1250(const gchar *src)
- return ggp_convert(src, "CP1250", "UTF-8");
-gchar * ggp_utf8_strndup(const gchar *str, gsize n)
- end_ptr = g_utf8_offset_to_pointer(str, g_utf8_pointer_to_offset(str, &str[n]));
- raw_len = end_ptr - str;
- end_ptr = g_utf8_prev_char(end_ptr);
- raw_len = end_ptr - str;
- g_assert(raw_len <= n);
- return g_strndup(str, raw_len);
-const gchar * ggp_ipv4_to_str(uint32_t raw_ip)
- static gchar buff[INET_ADDRSTRLEN];
- g_snprintf(buff, sizeof(buff), "%d.%d.%d.%d",
- ((raw_ip >> 0) & 0xFF),
- ((raw_ip >> 8) & 0xFF),
- ((raw_ip >> 16) & 0xFF),
- ((raw_ip >> 24) & 0xFF));
-gchar * ggp_free_if_equal(gchar *str, const gchar *pattern)
- if (g_strcmp0(str, pattern) == 0) {
-uint64_t * ggp_uint64dup(uint64_t val)
- uint64_t *ptr = g_new(uint64_t, 1);
-JsonParser * ggp_json_parse(const gchar *data)
- parser = json_parser_new();
- if (json_parser_load_from_data(parser, data, -1, NULL))
- if (purple_debug_is_unsafe())
- purple_debug_warning("gg", "Invalid JSON: %s\n", data);
--- a/libpurple/protocols/gg/utils.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
- * 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
- * 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
-#ifndef PURPLE_GG_UTILS_H
-#define PURPLE_GG_UTILS_H
-#include <json-glib/json-glib.h>
- * Converts stringified UIN to uin_t.
- * @param str The string to convert.
- * @return Converted UIN or 0 if an error occurred.
-uin_t ggp_str_to_uin(const char *str);
- * @param uin UIN to stringify.
- * @return Stringified UIN.
-const char * ggp_uin_to_str(uin_t uin);
- * Gets UIN for the account.
- * @param gc The connection, in which account is connected.
- * @return UIN for this account.
-uin_t ggp_get_my_uin(PurpleConnection *gc);
- * Converts encoding of a given string from UTF-8 to CP1250.
- * @param src Input string.
- * @return Converted string (must be freed with g_free). If src is NULL,
- * then NULL is returned.
-gchar * ggp_convert_to_cp1250(const gchar *src);
- * Converts encoding of a given string from CP1250 to UTF-8.
- * @param src Input string.
- * @return Converted string (must be freed with g_free). If src is NULL,
- * then NULL is returned.
-gchar * ggp_convert_from_cp1250(const gchar *src);
-gchar * ggp_utf8_strndup(const gchar *str, gsize n);
-const gchar * ggp_ipv4_to_str(uint32_t raw_ip);
-gchar * ggp_free_if_equal(gchar *str, const gchar *pattern);
-uint64_t * ggp_uint64dup(uint64_t val);
-JsonParser * ggp_json_parse(const gchar *data);
-#endif /* PURPLE_GG_UTILS_H */
--- a/libpurple/protocols/gg/validator.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
- * 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
- * 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>
-ggp_validator_password(PurpleRequestField *field, gchar **errmsg,
- G_GNUC_UNUSED gpointer data)
- g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD_STRING(field), FALSE);
- value = purple_request_field_string_get_value(PURPLE_REQUEST_FIELD_STRING(field));
- size_t len = strlen(value);
- if (6 <= len && len <= 15) {
- if (g_regex_match_simple(
- "^[ a-zA-Z0-9~`!@#$%^&*()_+=[\\]{};':\",./?<>\\\\|-]+$",
- *errmsg = g_strdup(_("Password can contain 6-15 alphanumeric characters"));
-gboolean ggp_validator_password_equal(PurpleRequestField *field, gchar **errmsg,
- const char *value1, *value2;
- PurpleRequestField *field2 = field2_p;
- g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD_STRING(field), FALSE);
- g_return_val_if_fail(PURPLE_IS_REQUEST_FIELD_STRING(field2), FALSE);
- value1 = purple_request_field_string_get_value(PURPLE_REQUEST_FIELD_STRING(field));
- value2 = purple_request_field_string_get_value(PURPLE_REQUEST_FIELD_STRING(field2));
- if (g_strcmp0(value1, value2) == 0)
- *errmsg = g_strdup(_("Passwords do not match"));
--- a/libpurple/protocols/gg/validator.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
- * 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
- * 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
-#ifndef PURPLE_GG_VALIDATOR_H
-#define PURPLE_GG_VALIDATOR_H
-gboolean ggp_validator_password(PurpleRequestField *field, gchar **errmsg,
-gboolean ggp_validator_password_equal(PurpleRequestField *field, gchar **errmsg,
-#endif /* PURPLE_GG_VALIDATOR_H */
--- a/libpurple/protocols/gg/xml.c Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
- * 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
- * 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
-ggp_xml_get_string(const PurpleXmlNode *xml, const gchar *childName, gchar **var)
- g_return_val_if_fail(xml != NULL, FALSE);
- g_return_val_if_fail(var != NULL, FALSE);
- if (childName != NULL) {
- xml = purple_xmlnode_get_child(xml, childName);
- str = purple_xmlnode_get_data(xml);
-ggp_xml_get_bool(const PurpleXmlNode *xml, const gchar *childName, gboolean *var)
- succ = ggp_xml_get_string(xml, childName, &str);
- *var = (strcmp(str, "true") == 0 ||
- strcmp(str, "True") == 0 ||
- strcmp(str, "TRUE") == 0 ||
- strcmp(str, "1") == 0);
-ggp_xml_get_uint(const PurpleXmlNode *xml, const gchar *childName, unsigned int *var)
- succ = ggp_xml_get_string(xml, childName, &str);
- val = strtoul(str, &endptr, 10);
- succ = (errno != ERANGE && endptr[0] == '\0');
-ggp_xml_set_string(PurpleXmlNode *xml, const gchar *childName, const gchar *val)
- g_return_val_if_fail(xml != NULL, FALSE);
- g_return_val_if_fail(val != NULL, FALSE);
- if (childName != NULL) {
- PurpleXmlNode *child = purple_xmlnode_get_child(xml, childName);
- child = purple_xmlnode_new_child(xml, childName);
- ggp_xmlnode_remove_children(xml);
- purple_xmlnode_insert_data(xml, val, -1);
-ggp_xml_set_bool(PurpleXmlNode *xml, const gchar *childName, gboolean val)
- return ggp_xml_set_string(xml, childName, val ? "true" : "false");
-ggp_xml_set_uint(PurpleXmlNode *xml, const gchar *childName, unsigned int val)
- g_snprintf(buff, sizeof(buff), "%u", val);
- return ggp_xml_set_string(xml, childName, buff);
-void ggp_xmlnode_remove_children(PurpleXmlNode *xml)
- PurpleXmlNode *child = xml->child;
- PurpleXmlNode *next = child->next;
- if (child->type != PURPLE_XMLNODE_TYPE_ATTRIB)
- purple_xmlnode_free(child);
-unsigned int ggp_xml_child_count(PurpleXmlNode *xml, const gchar *childName)
- unsigned int count = 0;
- g_return_val_if_fail(xml != NULL, 0);
- child = purple_xmlnode_get_child(xml, childName);
- child = purple_xmlnode_get_next_twin(child);
--- a/libpurple/protocols/gg/xml.h Tue Apr 09 21:50:31 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
- * 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
- * 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
-gboolean ggp_xml_get_string(const PurpleXmlNode *xml, const gchar *childName, gchar **var);
-gboolean ggp_xml_get_bool(const PurpleXmlNode *xml, const gchar *childName, gboolean *var);
-gboolean ggp_xml_get_uint(const PurpleXmlNode *xml, const gchar *childName, unsigned int *var);
-gboolean ggp_xml_set_string(PurpleXmlNode *xml, const gchar *childName, const gchar *val);
-gboolean ggp_xml_set_bool(PurpleXmlNode *xml, const gchar *childName, gboolean val);
-gboolean ggp_xml_set_uint(PurpleXmlNode *xml, const gchar *childName, unsigned int val);
-void ggp_xmlnode_remove_children(PurpleXmlNode *xml);
-unsigned int ggp_xml_child_count(PurpleXmlNode *xml, const gchar *childName);
-#endif /* PURPLE_GG_XML_H */
--- a/libpurple/protocols/meson.build Tue Apr 09 21:50:31 2024 -0500
+++ b/libpurple/protocols/meson.build Tue Apr 09 21:55:54 2024 -0500
@@ -1,3 +1,2 @@
--- a/meson.build Tue Apr 09 21:50:31 2024 -0500
+++ b/meson.build Tue Apr 09 21:55:54 2024 -0500
@@ -276,35 +276,13 @@
#######################################################################
-# Check for Gadu-Gadu protocol library (libgadu)
-#######################################################################
-libgadu = dependency('libgadu', version : '>= 1.12.0', required : get_option('libgadu'))
- if not compiler.has_function('gg_is_gpl_compliant', dependencies : libgadu)
- if get_option('libgadu').auto()
-libgadu is not compatible with the GPL when compiled with OpenSSL support.
-To link against libgadu, please recompile it using:
-./configure --with-openssl=no
-Then rerun this Meson build
-#######################################################################
# Check for Xeme XMPP Library
#######################################################################
xeme = dependency('xeme')
dependency('shoes', required : false)
-DEFAULT_PRPLS = ['bonjour', 'demo', 'gg', 'ircv3', 'jabber', 'xmpp']
+DEFAULT_PRPLS = ['bonjour', 'demo', 'ircv3', 'jabber', 'xmpp'] dynamic_list = get_option('dynamic-prpls').split(',')
if dynamic_list == ['all']
@@ -316,8 +294,6 @@
# The list was empty; do nothing.
elif prpl == 'bonjour' and not enable_avahi
- elif prpl == 'gg' and not libgadu.found()
elif prpl == 'xmpp' and not xeme.found()
@@ -327,7 +303,6 @@
DYNAMIC_BONJOUR = DYNAMIC_PRPLS.contains('bonjour')
DYNAMIC_DEMO = DYNAMIC_PRPLS.contains('demo')
-DYNAMIC_GG = DYNAMIC_PRPLS.contains('gg')
DYNAMIC_IRCV3 = DYNAMIC_PRPLS.contains('ircv3')
DYNAMIC_JABBER = DYNAMIC_PRPLS.contains('jabber')
DYNAMIC_XMPP = DYNAMIC_PRPLS.contains('xmpp')