pidgin/pidgin

645607090674
Parents 447c01698e1c
Children 9389ba16cf40
Remove Google Talk from the XMPP plugin.

Google Talk has long been on the deprecated list and with Hangouts getting
retired in June, it seems fitting that we finally remove this code.

Testing Done:
* Compiled locally
* Ran the unit tests
* Connected an XMPP account
* Had an audio call with Pidgin 2
* Had a video call with Pidgin 2

Reviewed at https://reviews.imfreedom.org/r/435/
  • +0 -3
    libpurple/protocols/jabber/auth_cyrus.c
  • +0 -3
    libpurple/protocols/jabber/auth_plain.c
  • +0 -3
    libpurple/protocols/jabber/auth_webex.c
  • +1 -38
    libpurple/protocols/jabber/buddy.c
  • +0 -4
    libpurple/protocols/jabber/caps.c
  • +2 -53
    libpurple/protocols/jabber/disco.c
  • +0 -171
    libpurple/protocols/jabber/google/google.c
  • +0 -35
    libpurple/protocols/jabber/google/google.h
  • +0 -429
    libpurple/protocols/jabber/google/google_p2p.c
  • +0 -82
    libpurple/protocols/jabber/google/google_p2p.h
  • +0 -43
    libpurple/protocols/jabber/google/google_presence.c
  • +0 -33
    libpurple/protocols/jabber/google/google_presence.h
  • +0 -199
    libpurple/protocols/jabber/google/google_roster.c
  • +0 -37
    libpurple/protocols/jabber/google/google_roster.h
  • +0 -869
    libpurple/protocols/jabber/google/google_session.c
  • +0 -56
    libpurple/protocols/jabber/google/google_session.h
  • +0 -162
    libpurple/protocols/jabber/google/jingleinfo.c
  • +0 -32
    libpurple/protocols/jabber/google/jingleinfo.h
  • +0 -128
    libpurple/protocols/jabber/google/relay.c
  • +0 -33
    libpurple/protocols/jabber/google/relay.h
  • +0 -137
    libpurple/protocols/jabber/gtalk.c
  • +0 -56
    libpurple/protocols/jabber/gtalk.h
  • +0 -9
    libpurple/protocols/jabber/iq.c
  • +4 -63
    libpurple/protocols/jabber/jabber.c
  • +0 -16
    libpurple/protocols/jabber/jabber.h
  • +2 -5
    libpurple/protocols/jabber/jingle/jingle.c
  • +1 -2
    libpurple/protocols/jabber/jingle/jingle.h
  • +0 -5
    libpurple/protocols/jabber/jingle/rtp.c
  • +0 -16
    libpurple/protocols/jabber/meson.build
  • +0 -7
    libpurple/protocols/jabber/message.c
  • +0 -16
    libpurple/protocols/jabber/namespaces.h
  • +1 -33
    libpurple/protocols/jabber/presence.c
  • +0 -18
    libpurple/protocols/jabber/roster.c
  • +2 -2
    libpurple/protocols/jabber/tests/test_jabber_caps.c
  • +0 -8
    po/POTFILES.in
  • --- a/libpurple/protocols/jabber/auth_cyrus.c Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/auth_cyrus.c Sat Jan 23 20:31:28 2021 -0600
    @@ -336,9 +336,6 @@
    purple_xmlnode_set_namespace(auth, NS_XMPP_SASL);
    purple_xmlnode_set_attrib(auth, "mechanism", js->current_mech);
    - purple_xmlnode_set_attrib(auth, "xmlns:ga", "http://www.google.com/talk/protocol/auth");
    - purple_xmlnode_set_attrib(auth, "ga:client-uses-full-bind-result", "true");
    -
    if (clientout) {
    if (coutlen == 0) {
    purple_xmlnode_insert_data(auth, "=", -1);
    --- a/libpurple/protocols/jabber/auth_plain.c Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/auth_plain.c Sat Jan 23 20:31:28 2021 -0600
    @@ -36,9 +36,6 @@
    auth = purple_xmlnode_new("auth");
    purple_xmlnode_set_namespace(auth, NS_XMPP_SASL);
    - purple_xmlnode_set_attrib(auth, "xmlns:ga", "http://www.google.com/talk/protocol/auth");
    - purple_xmlnode_set_attrib(auth, "ga:client-uses-full-bind-result", "true");
    -
    response = g_string_new("");
    response = g_string_append_c(response, '\0');
    response = g_string_append(response, js->user->node);
    --- a/libpurple/protocols/jabber/auth_webex.c Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/auth_webex.c Sat Jan 23 20:31:28 2021 -0600
    @@ -32,9 +32,6 @@
    auth = purple_xmlnode_new("auth");
    purple_xmlnode_set_namespace(auth, NS_XMPP_SASL);
    - purple_xmlnode_set_attrib(auth, "xmlns:ga", "http://www.google.com/talk/protocol/auth");
    - purple_xmlnode_set_attrib(auth, "ga:client-uses-full-bind-result", "true");
    -
    purple_xmlnode_set_attrib(auth, "mechanism", "WEBEX-TOKEN");
    purple_xmlnode_insert_data(auth, purple_connection_get_password(js->gc), -1);
    --- a/libpurple/protocols/jabber/buddy.c Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/buddy.c Sat Jan 23 20:31:28 2021 -0600
    @@ -33,7 +33,6 @@
    #include "xdata.h"
    #include "pep.h"
    #include "adhoccommands.h"
    -#include "google/google.h"
    typedef struct {
    long idle_seconds;
    @@ -478,11 +477,6 @@
    return;
    }
    - if (js->vcard_timer) {
    - g_source_remove(js->vcard_timer);
    - js->vcard_timer = 0;
    - }
    -
    g_free(js->avatar_hash);
    js->avatar_hash = NULL;
    @@ -898,19 +892,6 @@
    }
    }
    -static gboolean
    -set_own_vcard_cb(gpointer data)
    -{
    - JabberStream *js = data;
    - PurpleAccount *account = purple_connection_get_account(js->gc);
    -
    - js->vcard_timer = 0;
    -
    - jabber_set_info(NULL, js->gc, purple_account_get_user_info(account));
    -
    - return FALSE;
    -}
    -
    static void jabber_vcard_save_mine(JabberStream *js, const char *from,
    JabberIqType type, const char *id,
    PurpleXmlNode *packet, gpointer data)
    @@ -960,18 +941,7 @@
    /* Republish our vcard if the photo is different than the server's */
    if (js->initial_avatar_hash && !purple_strequal(vcard_hash, js->initial_avatar_hash)) {
    - /*
    - * Google Talk has developed the behavior that it will not accept
    - * a vcard set in the first 10 seconds (or so) of the connection;
    - * it returns an error (namespaces trimmed):
    - * <error code="500" type="wait"><internal-server-error/></error>.
    - */
    - if (js->googletalk) {
    - js->vcard_timer = g_timeout_add_seconds(10, set_own_vcard_cb,
    - js);
    - } else {
    - jabber_set_info(NULL, js->gc, purple_account_get_user_info(account));
    - }
    + jabber_set_info(NULL, js->gc, purple_account_get_user_info(account));
    } else if (vcard_hash) {
    /* A photo is in the vCard. Advertise its hash */
    js->avatar_hash = vcard_hash;
    @@ -1872,13 +1842,6 @@
    m = g_list_append(m, act);
    }
    - if (js->googletalk) {
    - act = purple_action_menu_new(_("Initiate _Chat"),
    - PURPLE_CALLBACK(google_buddy_node_chat),
    - NULL, NULL);
    - m = g_list_append(m, act);
    - }
    -
    /*
    * This if-condition implements parts of XEP-0100: Gateway Interaction
    *
    --- a/libpurple/protocols/jabber/caps.c Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/caps.c Sat Jan 23 20:31:28 2021 -0600
    @@ -336,10 +336,6 @@
    return TRUE;
    for (i = 0; exts[i]; ++i) {
    - /* Hack since we advertise the ext along with v1.5 caps but don't
    - * store any exts */
    - if (purple_strequal(exts[i], "voice-v1") && !info->exts)
    - continue;
    if (!info->exts ||
    !g_hash_table_lookup(info->exts->exts, exts[i]))
    return FALSE;
    --- a/libpurple/protocols/jabber/disco.c Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/disco.c Sat Jan 23 20:31:28 2021 -0600
    @@ -26,8 +26,6 @@
    #include "adhoccommands.h"
    #include "buddy.h"
    #include "disco.h"
    -#include "google/google.h"
    -#include "google/jingleinfo.h"
    #include "iq.h"
    #include "jabber.h"
    #include "jingle/jingle.h"
    @@ -134,44 +132,6 @@
    purple_xmlnode_set_attrib(feature, "var", feat->namespace);
    }
    }
    -#ifdef USE_VV
    - } else if (purple_strequal(node, CAPS0115_NODE "#" "voice-v1")) {
    - /*
    - * HUGE HACK! We advertise this ext (see jabber_presence_create_js
    - * where we add <c/> to the <presence/>) for the Google Talk
    - * clients that don't actually check disco#info features.
    - *
    - * This specific feature is redundant but is what
    - * node='http://mail.google.com/xmpp/client/caps', ver='1.1'
    - * advertises as 'voice-v1'.
    - */
    - PurpleXmlNode *feature = purple_xmlnode_new_child(query, "feature");
    - purple_xmlnode_set_attrib(feature, "var", NS_GOOGLE_VOICE);
    - } else if (purple_strequal(node, CAPS0115_NODE "#" "video-v1")) {
    - /*
    - * HUGE HACK! We advertise this ext (see jabber_presence_create_js
    - * where we add <c/> to the <presence/>) for the Google Talk
    - * clients that don't actually check disco#info features.
    - *
    - * This specific feature is redundant but is what
    - * node='http://mail.google.com/xmpp/client/caps', ver='1.1'
    - * advertises as 'video-v1'.
    - */
    - PurpleXmlNode *feature = purple_xmlnode_new_child(query, "feature");
    - purple_xmlnode_set_attrib(feature, "var", NS_GOOGLE_VIDEO);
    - } else if (purple_strequal(node, CAPS0115_NODE "#" "camera-v1")) {
    - /*
    - * HUGE HACK! We advertise this ext (see jabber_presence_create_js
    - * where we add <c/> to the <presence/>) for the Google Talk
    - * clients that don't actually check disco#info features.
    - *
    - * This specific feature is redundant but is what
    - * node='http://mail.google.com/xmpp/client/caps', ver='1.1'
    - * advertises as 'camera-v1'.
    - */
    - PurpleXmlNode *feature = purple_xmlnode_new_child(query, "feature");
    - purple_xmlnode_set_attrib(feature, "var", NS_GOOGLE_CAMERA);
    -#endif
    } else {
    PurpleXmlNode *error, *inf;
    @@ -508,16 +468,7 @@
    g_free(js->server_name);
    js->server_name = g_strdup(name);
    stun_ip = purple_network_get_stun_ip();
    - if (purple_strequal(name, "Google Talk")) {
    - purple_debug_info("jabber", "Google Talk!\n");
    - js->googletalk = TRUE;
    -
    - /* autodiscover stun and relays */
    - if (!stun_ip || !*stun_ip) {
    - jabber_google_send_jingle_info(js);
    - }
    - } else if (!stun_ip || !*stun_ip) {
    -
    + if (!stun_ip || !*stun_ip) {
    GResolver *resolver = g_resolver_get_default();
    g_resolver_lookup_service_async(resolver,
    "stun",
    @@ -538,9 +489,7 @@
    if (!var)
    continue;
    - if (purple_strequal(NS_GOOGLE_ROSTER, var)) {
    - js->server_caps |= JABBER_CAP_GOOGLE_ROSTER;
    - } else if (purple_strequal("http://jabber.org/protocol/commands", var)) {
    + if (purple_strequal("http://jabber.org/protocol/commands", var)) {
    js->server_caps |= JABBER_CAP_ADHOC;
    } else if (purple_strequal(NS_SIMPLE_BLOCKING, var)) {
    js->server_caps |= JABBER_CAP_BLOCKING;
    --- a/libpurple/protocols/jabber/google/google.c Sat Jan 23 20:28:06 2021 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,171 +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
    - * source distribution.
    - *
    - * 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 <purple.h>
    -
    -#include "google.h"
    -#include "jabber.h"
    -#include "chat.h"
    -
    -/* This does two passes on the string. The first pass goes through
    - * and determine if all the structured text is properly balanced, and
    - * how many instances of each there is. The second pass goes and converts
    - * everything to HTML, depending on what's figured out by the first pass.
    - * It will short circuit once it knows it has no more replacements to make
    - */
    -char *jabber_google_format_to_html(const char *text)
    -{
    - const char *p;
    -
    - /* The start of the screen may be consdiered a space for this purpose */
    - gboolean preceding_space = TRUE;
    -
    - gboolean in_bold = FALSE, in_italic = FALSE;
    - gboolean in_tag = FALSE;
    -
    - gint bold_count = 0, italic_count = 0;
    -
    - GString *str;
    -
    - for (p = text; *p != '\0'; p = g_utf8_next_char(p)) {
    - gunichar c = g_utf8_get_char(p);
    - if (c == '*' && !in_tag) {
    - if (in_bold && (g_unichar_isspace(*(p+1)) ||
    - *(p+1) == '\0' ||
    - *(p+1) == '<')) {
    - bold_count++;
    - in_bold = FALSE;
    - } else if (preceding_space && !in_bold && !g_unichar_isspace(*(p+1))) {
    - bold_count++;
    - in_bold = TRUE;
    - }
    - preceding_space = TRUE;
    - } else if (c == '_' && !in_tag) {
    - if (in_italic && (g_unichar_isspace(*(p+1)) ||
    - *(p+1) == '\0' ||
    - *(p+1) == '<')) {
    - italic_count++;
    - in_italic = FALSE;
    - } else if (preceding_space && !in_italic && !g_unichar_isspace(*(p+1))) {
    - italic_count++;
    - in_italic = TRUE;
    - }
    - preceding_space = TRUE;
    - } else if (c == '<' && !in_tag) {
    - in_tag = TRUE;
    - } else if (c == '>' && in_tag) {
    - in_tag = FALSE;
    - } else if (!in_tag) {
    - if (g_unichar_isspace(c))
    - preceding_space = TRUE;
    - else
    - preceding_space = FALSE;
    - }
    - }
    -
    - str = g_string_new(NULL);
    - in_bold = in_italic = in_tag = FALSE;
    - preceding_space = TRUE;
    -
    - for (p = text; *p != '\0'; p = g_utf8_next_char(p)) {
    - gunichar c = g_utf8_get_char(p);
    -
    - if (bold_count < 2 && italic_count < 2 && !in_bold && !in_italic) {
    - g_string_append(str, p);
    - return g_string_free(str, FALSE);
    - }
    -
    -
    - if (c == '*' && !in_tag) {
    - if (in_bold &&
    - (g_unichar_isspace(*(p+1))||*(p+1)=='<')) { /* This is safe in UTF-8 */
    - str = g_string_append(str, "</b>");
    - in_bold = FALSE;
    - bold_count--;
    - } else if (preceding_space && bold_count > 1 && !g_unichar_isspace(*(p+1))) {
    - str = g_string_append(str, "<b>");
    - bold_count--;
    - in_bold = TRUE;
    - } else {
    - str = g_string_append_unichar(str, c);
    - }
    - preceding_space = TRUE;
    - } else if (c == '_' && !in_tag) {
    - if (in_italic &&
    - (g_unichar_isspace(*(p+1))||*(p+1)=='<')) {
    - str = g_string_append(str, "</i>");
    - italic_count--;
    - in_italic = FALSE;
    - } else if (preceding_space && italic_count > 1 && !g_unichar_isspace(*(p+1))) {
    - str = g_string_append(str, "<i>");
    - italic_count--;
    - in_italic = TRUE;
    - } else {
    - str = g_string_append_unichar(str, c);
    - }
    - preceding_space = TRUE;
    - } else if (c == '<' && !in_tag) {
    - str = g_string_append_unichar(str, c);
    - in_tag = TRUE;
    - } else if (c == '>' && in_tag) {
    - str = g_string_append_unichar(str, c);
    - in_tag = FALSE;
    - } else if (!in_tag) {
    - str = g_string_append_unichar(str, c);
    - if (g_unichar_isspace(c))
    - preceding_space = TRUE;
    - else
    - preceding_space = FALSE;
    - } else {
    - str = g_string_append_unichar(str, c);
    - }
    - }
    - return g_string_free(str, FALSE);
    -}
    -
    -
    -
    -void google_buddy_node_chat(PurpleBlistNode *node, gpointer data)
    -{
    - PurpleBuddy *buddy;
    - PurpleConnection *gc;
    - JabberStream *js;
    - JabberChat *chat;
    - gchar *room;
    - gchar *uuid = g_uuid_string_random();
    -
    - g_return_if_fail(PURPLE_IS_BUDDY(node));
    -
    - buddy = PURPLE_BUDDY(node);
    - gc = purple_account_get_connection(purple_buddy_get_account(buddy));
    - g_return_if_fail(gc != NULL);
    - js = purple_connection_get_protocol_data(gc);
    -
    - room = g_strdup_printf("private-chat-%s", uuid);
    - chat = jabber_join_chat(js, room, GOOGLE_GROUPCHAT_SERVER, js->user->node,
    - NULL, NULL);
    - if (chat) {
    - chat->muc = TRUE;
    - jabber_chat_invite(gc, chat->id, "", purple_buddy_get_name(buddy));
    - }
    -
    - g_free(room);
    - g_free(uuid);
    -}
    --- a/libpurple/protocols/jabber/google/google.h Sat Jan 23 20:28:06 2021 -0600
    +++ /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
    - * source distribution.
    - *
    - * 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_JABBER_GOOGLE_H_
    -#define PURPLE_JABBER_GOOGLE_H_
    -
    -/* This is a place for Google Talk-specific XMPP extensions to live
    - * such that they don't intermingle with code for the XMPP RFCs and XEPs :) */
    -
    -#include "jabber.h"
    -
    -#define GOOGLE_GROUPCHAT_SERVER "groupchat.google.com"
    -
    -char *jabber_google_format_to_html(const char *text);
    -
    -void google_buddy_node_chat(PurpleBlistNode *node, gpointer data);
    -
    -#endif /* PURPLE_JABBER_GOOGLE_H_ */
    --- a/libpurple/protocols/jabber/google/google_p2p.c Sat Jan 23 20:28:06 2021 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,429 +0,0 @@
    -/**
    - * @file google_p2p.c
    - *
    - * purple
    - *
    - * Purple is the legal property of its developers, whose names are too numerous
    - * to list here. Please refer to the COPYRIGHT file distributed with this
    - * source distribution.
    - *
    - * 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 <purple.h>
    -
    -#include <string.h>
    -
    -#include "google_p2p.h"
    -#include "jingle/jingle.h"
    -
    -struct _JingleGoogleP2P
    -{
    - JingleTransport parent;
    -};
    -
    -typedef struct
    -{
    - GList *local_candidates;
    - GList *remote_candidates;
    -} JingleGoogleP2PPrivate;
    -
    -enum {
    - PROP_0,
    - PROP_LOCAL_CANDIDATES,
    - PROP_REMOTE_CANDIDATES,
    - PROP_LAST
    -};
    -
    -static GParamSpec *properties[PROP_LAST];
    -
    -G_DEFINE_DYNAMIC_TYPE_EXTENDED(
    - JingleGoogleP2P,
    - jingle_google_p2p,
    - JINGLE_TYPE_TRANSPORT,
    - 0,
    - G_ADD_PRIVATE_DYNAMIC(JingleGoogleP2P)
    -);
    -
    -/******************************************************************************
    - * JingleGoogleP2P Transport Implementation
    - *****************************************************************************/
    -static void
    -jingle_google_p2p_add_local_candidate(JingleTransport *transport, const gchar *id,
    - guint generation, PurpleMediaCandidate *candidate)
    -{
    - JingleGoogleP2P *google_p2p = JINGLE_GOOGLE_P2P(transport);
    - JingleGoogleP2PPrivate *priv = jingle_google_p2p_get_instance_private(google_p2p);
    - JingleGoogleP2PCandidate *google_p2p_candidate;
    - gchar *ip;
    - gchar *username;
    - gchar *password;
    - PurpleMediaCandidateType type;
    - PurpleMediaNetworkProtocol protocol;
    - GList *iter;
    -
    - ip = purple_media_candidate_get_ip(candidate);
    - username = purple_media_candidate_get_username(candidate);
    - password = purple_media_candidate_get_password(candidate);
    - type = purple_media_candidate_get_candidate_type(candidate);
    - protocol = purple_media_candidate_get_protocol(candidate);
    -
    - google_p2p_candidate = jingle_google_p2p_candidate_new(id, generation,
    - ip, purple_media_candidate_get_port(candidate),
    - purple_media_candidate_get_priority(candidate),
    - type == PURPLE_MEDIA_CANDIDATE_TYPE_HOST ? "host" :
    - type == PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX ? "srflx" :
    - type == PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX ? "prflx" :
    - type == PURPLE_MEDIA_CANDIDATE_TYPE_RELAY ? "relay" :
    - "",
    - protocol == PURPLE_MEDIA_NETWORK_PROTOCOL_UDP ? "udp" : "tcp",
    - username, password);
    -
    - g_free(password);
    - g_free(username);
    - g_free(ip);
    -
    - for (iter = priv->local_candidates; iter; iter = g_list_next(iter)) {
    - JingleGoogleP2PCandidate *c = iter->data;
    - if (!strcmp(c->id, id)) {
    - generation = c->generation + 1;
    -
    - g_boxed_free(JINGLE_TYPE_GOOGLE_P2P_CANDIDATE, c);
    - priv->local_candidates = g_list_delete_link(
    - priv->local_candidates, iter);
    -
    - google_p2p_candidate->generation = generation;
    -
    - priv->local_candidates =
    - g_list_append(priv->local_candidates, google_p2p_candidate);
    -
    - g_object_notify_by_pspec(G_OBJECT(google_p2p), properties[PROP_LOCAL_CANDIDATES]);
    -
    - return;
    - }
    - }
    -
    - priv->local_candidates = g_list_append(
    - priv->local_candidates, google_p2p_candidate);
    -
    - g_object_notify_by_pspec(G_OBJECT(google_p2p), properties[PROP_LOCAL_CANDIDATES]);
    -}
    -
    -static JingleGoogleP2PCandidate *
    -jingle_google_p2p_get_remote_candidate_by_id(JingleGoogleP2P *google_p2p,
    - const gchar *id)
    -{
    - JingleGoogleP2PPrivate *priv = jingle_google_p2p_get_instance_private(google_p2p);
    - GList *iter = priv->remote_candidates;
    - for (; iter; iter = g_list_next(iter)) {
    - JingleGoogleP2PCandidate *candidate = iter->data;
    - if (!strcmp(candidate->id, id)) {
    - return candidate;
    - }
    - }
    - return NULL;
    -}
    -
    -static void
    -jingle_google_p2p_add_remote_candidate(JingleGoogleP2P *google_p2p, JingleGoogleP2PCandidate *candidate)
    -{
    - JingleGoogleP2PPrivate *priv = jingle_google_p2p_get_instance_private(google_p2p);
    - JingleGoogleP2PCandidate *google_p2p_candidate =
    - jingle_google_p2p_get_remote_candidate_by_id(google_p2p,
    - candidate->id);
    - if (google_p2p_candidate != NULL) {
    - priv->remote_candidates = g_list_remove(priv->remote_candidates,
    - google_p2p_candidate);
    - g_boxed_free(JINGLE_TYPE_GOOGLE_P2P_CANDIDATE, google_p2p_candidate);
    - }
    - priv->remote_candidates = g_list_append(priv->remote_candidates, candidate);
    -
    - g_object_notify_by_pspec(G_OBJECT(google_p2p), properties[PROP_REMOTE_CANDIDATES]);
    -}
    -
    -static GList *
    -jingle_google_p2p_get_remote_candidates(JingleTransport *transport)
    -{
    - JingleGoogleP2P *google_p2p = JINGLE_GOOGLE_P2P(transport);
    - JingleGoogleP2PPrivate *priv = jingle_google_p2p_get_instance_private(google_p2p);
    - GList *candidates = priv->remote_candidates;
    - GList *ret = NULL;
    -
    - for (; candidates; candidates = g_list_next(candidates)) {
    - JingleGoogleP2PCandidate *candidate = candidates->data;
    - PurpleMediaCandidate *new_candidate = purple_media_candidate_new("", 0,
    - !strcmp(candidate->type, "host") ?
    - PURPLE_MEDIA_CANDIDATE_TYPE_HOST :
    - !strcmp(candidate->type, "srflx") ?
    - PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX :
    - !strcmp(candidate->type, "prflx") ?
    - PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX :
    - !strcmp(candidate->type, "relay") ?
    - PURPLE_MEDIA_CANDIDATE_TYPE_RELAY : 0,
    - !strcmp(candidate->protocol, "udp") ?
    - PURPLE_MEDIA_NETWORK_PROTOCOL_UDP :
    - PURPLE_MEDIA_NETWORK_PROTOCOL_TCP_PASSIVE,
    - candidate->address, candidate->port);
    - g_object_set(new_candidate,
    - "username", candidate->username,
    - "password", candidate->password,
    - "priority", candidate->preference,
    - NULL);
    - ret = g_list_append(ret, new_candidate);
    - }
    -
    - return ret;
    -}
    -
    -static PurpleXmlNode *
    -jingle_google_p2p_to_xml_internal(JingleTransport *transport, PurpleXmlNode *content, JingleActionType action)
    -{
    - PurpleXmlNode *node = JINGLE_TRANSPORT_CLASS(jingle_google_p2p_parent_class)->to_xml(transport, content, action);
    -
    - if (action == JINGLE_SESSION_INITIATE ||
    - action == JINGLE_SESSION_ACCEPT ||
    - action == JINGLE_TRANSPORT_INFO ||
    - action == JINGLE_CONTENT_ADD ||
    - action == JINGLE_TRANSPORT_REPLACE) {
    - JingleGoogleP2PPrivate *priv = jingle_google_p2p_get_instance_private(JINGLE_GOOGLE_P2P(transport));
    - GList *iter = priv->local_candidates;
    -
    - for (; iter; iter = g_list_next(iter)) {
    - JingleGoogleP2PCandidate *candidate = iter->data;
    - PurpleXmlNode *xmltransport;
    - gchar *generation, *network, *port, *preference;
    -
    - if (candidate->rem_known == TRUE)
    - continue;
    -
    - candidate->rem_known = TRUE;
    -
    - xmltransport = purple_xmlnode_new_child(node, "candidate");
    - generation = g_strdup_printf("%d", candidate->generation);
    - network = g_strdup_printf("%d", candidate->network);
    - port = g_strdup_printf("%d", candidate->port);
    - preference = g_strdup_printf("%d", candidate->preference);
    -
    - purple_xmlnode_set_attrib(xmltransport, "generation", generation);
    - purple_xmlnode_set_attrib(xmltransport, "name", candidate->id);
    - purple_xmlnode_set_attrib(xmltransport, "address", candidate->address);
    - purple_xmlnode_set_attrib(xmltransport, "network", network);
    - purple_xmlnode_set_attrib(xmltransport, "port", port);
    - purple_xmlnode_set_attrib(xmltransport, "preference", preference);
    - purple_xmlnode_set_attrib(xmltransport, "protocol", candidate->protocol);
    - purple_xmlnode_set_attrib(xmltransport, "type", candidate->type);
    - purple_xmlnode_set_attrib(xmltransport, "username", candidate->username);
    - purple_xmlnode_set_attrib(xmltransport, "password", candidate->password);
    -
    - g_free(generation);
    - g_free(network);
    - g_free(port);
    - g_free(preference);
    - }
    - }
    -
    - return node;
    -}
    -
    -static JingleTransport *
    -jingle_google_p2p_parse_internal(PurpleXmlNode *google_p2p)
    -{
    - JingleTransport *transport = JINGLE_TRANSPORT_CLASS(jingle_google_p2p_parent_class)->parse(google_p2p);
    - PurpleXmlNode *candidate = purple_xmlnode_get_child(google_p2p, "candidate");
    - JingleGoogleP2PCandidate *google_p2p_candidate = NULL;
    -
    - for (; candidate; candidate = purple_xmlnode_get_next_twin(candidate)) {
    - const gchar *generation = purple_xmlnode_get_attrib(candidate, "generation");
    - const gchar *id = purple_xmlnode_get_attrib(candidate, "name");
    - const gchar *address = purple_xmlnode_get_attrib(candidate, "address");
    - const gchar *port = purple_xmlnode_get_attrib(candidate, "port");
    - const gchar *preference = purple_xmlnode_get_attrib(candidate, "preference");
    - const gchar *type = purple_xmlnode_get_attrib(candidate, "type");
    - const gchar *protocol = purple_xmlnode_get_attrib(candidate, "protocol");
    - const gchar *username = purple_xmlnode_get_attrib(candidate, "username");
    - const gchar *password = purple_xmlnode_get_attrib(candidate, "password");
    -
    - if (!generation || !id || !address || !port || !preference ||
    - !type || !protocol || !username || !password)
    - continue;
    -
    - google_p2p_candidate = jingle_google_p2p_candidate_new(id,
    - atoi(generation),
    - address,
    - atoi(port),
    - atoi(preference),
    - type,
    - protocol,
    - username, password);
    - google_p2p_candidate->rem_known = TRUE;
    - jingle_google_p2p_add_remote_candidate(JINGLE_GOOGLE_P2P(transport), google_p2p_candidate);
    - }
    -
    - return transport;
    -}
    -
    -/******************************************************************************
    - * JingleGoogleP2P GObject stuff
    - *****************************************************************************/
    -static void
    -jingle_google_p2p_init(JingleGoogleP2P *google_p2p)
    -{
    -}
    -
    -static void
    -jingle_google_p2p_finalize(GObject *google_p2p)
    -{
    -/* JingleGoogleP2PPrivate *priv = JINGLE_GOOGLE_P2P_GET_PRIVATE(google_p2p); */
    - purple_debug_info("jingle","jingle_google_p2p_finalize\n");
    -
    - G_OBJECT_CLASS(jingle_google_p2p_parent_class)->finalize(google_p2p);
    -}
    -
    -static void
    -jingle_google_p2p_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
    -{
    - JingleGoogleP2P *google_p2p = JINGLE_GOOGLE_P2P(object);
    - JingleGoogleP2PPrivate *priv = jingle_google_p2p_get_instance_private(google_p2p);
    -
    - switch (prop_id) {
    - case PROP_LOCAL_CANDIDATES:
    - priv->local_candidates = g_value_get_pointer(value);
    - break;
    - case PROP_REMOTE_CANDIDATES:
    - priv->remote_candidates = g_value_get_pointer(value);
    - break;
    - default:
    - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
    - break;
    - }
    -}
    -
    -static void
    -jingle_google_p2p_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
    -{
    - JingleGoogleP2P *google_p2p = JINGLE_GOOGLE_P2P(object);
    - JingleGoogleP2PPrivate *priv = jingle_google_p2p_get_instance_private(google_p2p);
    -
    - switch (prop_id) {
    - case PROP_LOCAL_CANDIDATES:
    - g_value_set_pointer(value, priv->local_candidates);
    - break;
    - case PROP_REMOTE_CANDIDATES:
    - g_value_set_pointer(value, priv->remote_candidates);
    - break;
    - default:
    - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    - break;
    - }
    -}
    -
    -static void
    -jingle_google_p2p_class_finalize(JingleGoogleP2PClass *klass) {
    -}
    -
    -static void
    -jingle_google_p2p_class_init(JingleGoogleP2PClass *klass)
    -{
    - GObjectClass *obj_class = G_OBJECT_CLASS(klass);
    - JingleTransportClass *transport_class = JINGLE_TRANSPORT_CLASS(klass);
    -
    - obj_class->finalize = jingle_google_p2p_finalize;
    - obj_class->set_property = jingle_google_p2p_set_property;
    - obj_class->get_property = jingle_google_p2p_get_property;
    -
    - transport_class->to_xml = jingle_google_p2p_to_xml_internal;
    - transport_class->parse = jingle_google_p2p_parse_internal;
    - transport_class->transport_type = NS_GOOGLE_TRANSPORT_P2P;
    - transport_class->add_local_candidate = jingle_google_p2p_add_local_candidate;
    - transport_class->get_remote_candidates = jingle_google_p2p_get_remote_candidates;
    -
    - properties[PROP_LOCAL_CANDIDATES] = g_param_spec_pointer("local-candidates",
    - "Local candidates",
    - "The local candidates for this transport.",
    - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
    -
    - properties[PROP_REMOTE_CANDIDATES] = g_param_spec_pointer("remote-candidates",
    - "Remote candidates",
    - "The remote candidates for this transport.",
    - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
    -
    - g_object_class_install_properties(obj_class, PROP_LAST, properties);
    -}
    -
    -/******************************************************************************
    - * JingleGoogleP2PCandidate Boxed Implementation
    - *****************************************************************************/
    -static JingleGoogleP2PCandidate *
    -jingle_google_p2p_candidate_copy(JingleGoogleP2PCandidate *candidate)
    -{
    - JingleGoogleP2PCandidate *new_candidate = g_new0(JingleGoogleP2PCandidate, 1);
    - new_candidate->id = g_strdup(candidate->id);
    - new_candidate->address = g_strdup(candidate->address);
    - new_candidate->port = candidate->port;
    - new_candidate->preference = candidate->preference;
    - new_candidate->type = g_strdup(candidate->type);
    - new_candidate->protocol = g_strdup(candidate->protocol);
    - new_candidate->username = g_strdup(candidate->username);
    - new_candidate->password = g_strdup(candidate->password);
    - new_candidate->generation = candidate->generation;
    -
    - new_candidate->rem_known = candidate->rem_known;
    -
    - return new_candidate;
    -}
    -
    -static void
    -jingle_google_p2p_candidate_free(JingleGoogleP2PCandidate *candidate)
    -{
    - g_free(candidate->id);
    - g_free(candidate->address);
    - g_free(candidate->type);
    - g_free(candidate->protocol);
    - g_free(candidate->username);
    - g_free(candidate->password);
    -}
    -
    -G_DEFINE_BOXED_TYPE(JingleGoogleP2PCandidate, jingle_google_p2p_candidate,
    - jingle_google_p2p_candidate_copy, jingle_google_p2p_candidate_free)
    -
    -
    -/******************************************************************************
    - * Public API
    - *****************************************************************************/
    -void
    -jingle_google_p2p_register(PurplePlugin *plugin) {
    - jingle_google_p2p_register_type(G_TYPE_MODULE(plugin));
    -}
    -
    -JingleGoogleP2PCandidate *
    -jingle_google_p2p_candidate_new(const gchar *id, guint generation,
    - const gchar *address, guint port, guint preference,
    - const gchar *type, const gchar *protocol,
    - const gchar *username, const gchar *password)
    -{
    - JingleGoogleP2PCandidate *candidate = g_new0(JingleGoogleP2PCandidate, 1);
    - candidate->id = g_strdup(id);
    - candidate->address = g_strdup(address);
    - candidate->port = port;
    - candidate->preference = preference;
    - candidate->type = g_strdup(type);
    - candidate->protocol = g_strdup(protocol);
    - candidate->username = g_strdup(username);
    - candidate->password = g_strdup(password);
    - candidate->generation = generation;
    -
    - candidate->rem_known = FALSE;
    - return candidate;
    -}
    --- a/libpurple/protocols/jabber/google/google_p2p.h Sat Jan 23 20:28:06 2021 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,82 +0,0 @@
    -/**
    - * @file google_p2p.h
    - *
    - * purple
    - *
    - * Purple is the legal property of its developers, whose names are too numerous
    - * to list here. Please refer to the COPYRIGHT file distributed with this
    - * source distribution.
    - *
    - * 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_JABBER_JINGLE_GOOGLE_P2P_H
    -#define PURPLE_JABBER_JINGLE_GOOGLE_P2P_H
    -
    -#include <glib.h>
    -#include <glib-object.h>
    -
    -#include "jingle/transport.h"
    -
    -G_BEGIN_DECLS
    -
    -#define JINGLE_TYPE_GOOGLE_P2P jingle_google_p2p_get_type()
    -#define JINGLE_TYPE_GOOGLE_P2P_CANDIDATE jingle_google_p2p_candidate_get_type()
    -
    -/** @copydoc _JingleGoogleP2PCandidate */
    -typedef struct _JingleGoogleP2PCandidate JingleGoogleP2PCandidate;
    -
    -struct _JingleGoogleP2PCandidate
    -{
    - gchar *id;
    - gchar *address;
    - guint port;
    - guint preference;
    - gchar *type;
    - gchar *protocol;
    - guint network;
    - gchar *username;
    - gchar *password;
    - guint generation;
    -
    - gboolean rem_known; /* TRUE if the remote side knows
    - * about this candidate */
    -};
    -
    -GType jingle_google_p2p_candidate_get_type(void);
    -
    -/**
    - * Gets the Google P2P class's GType
    - *
    - * @return The Google P2P class's GType.
    - */
    -G_MODULE_EXPORT
    -G_DECLARE_FINAL_TYPE(JingleGoogleP2P, jingle_google_p2p, JINGLE, GOOGLE_P2P,
    - JingleTransport)
    -
    -/**
    - * Registers the JingleGoogleP2P type in the type system.
    - */
    -void jingle_google_p2p_register(PurplePlugin *plugin);
    -
    -JingleGoogleP2PCandidate *jingle_google_p2p_candidate_new(const gchar *id,
    - guint generation, const gchar *address, guint port, guint preference,
    - const gchar *type, const gchar *protocol,
    - const gchar *username, const gchar *password);
    -
    -G_END_DECLS
    -
    -#endif /* PURPLE_JABBER_JINGLE_GOOGLE_P2P_H */
    -
    --- a/libpurple/protocols/jabber/google/google_presence.c Sat Jan 23 20:28:06 2021 -0600
    +++ /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
    - * source distribution.
    - *
    - * 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 <purple.h>
    -
    -#include "google_presence.h"
    -
    -void jabber_google_presence_incoming(JabberStream *js, const char *user, JabberBuddyResource *jbr)
    -{
    - if (!js->googletalk)
    - return;
    - if (jbr->status && g_str_has_prefix(jbr->status, "♫ ")) {
    - purple_protocol_got_user_status(purple_connection_get_account(js->gc), user, "tune",
    - PURPLE_TUNE_TITLE, jbr->status + strlen("♫ "), NULL);
    - g_free(jbr->status);
    - jbr->status = NULL;
    - } else {
    - purple_protocol_got_user_status_deactive(purple_connection_get_account(js->gc), user, "tune");
    - }
    -}
    -
    -char *jabber_google_presence_outgoing(PurpleStatus *tune)
    -{
    - const char *attr = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE);
    - return attr ? g_strdup_printf("♫ %s", attr) : g_strdup("");
    -}
    --- a/libpurple/protocols/jabber/google/google_presence.h Sat Jan 23 20:28:06 2021 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,33 +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
    - * source distribution.
    - *
    - * 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_JABBER_GOOGLE_PRESENCE_H_
    -#define PURPLE_JABBER_GOOGLE_PRESENCE_H_
    -
    -#include <purple.h>
    -
    -#include "jabber.h"
    -#include "buddy.h"
    -
    -void jabber_google_presence_incoming(JabberStream *js, const char *who, JabberBuddyResource *jbr);
    -char *jabber_google_presence_outgoing(PurpleStatus *tune);
    -
    -
    -#endif /* PURPLE_JABBER_GOOGLE_PRESENCE_H_ */
    \ No newline at end of file
    --- a/libpurple/protocols/jabber/google/google_roster.c Sat Jan 23 20:28:06 2021 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,199 +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
    - * source distribution.
    - *
    - * 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 <purple.h>
    -
    -#include "google_roster.h"
    -#include "jabber.h"
    -#include "presence.h"
    -#include "roster.h"
    -
    -void jabber_google_roster_outgoing(JabberStream *js, PurpleXmlNode *query, PurpleXmlNode *item)
    -{
    - PurpleAccount *account = purple_connection_get_account(js->gc);
    - GSList *list = purple_account_privacy_get_denied(account);
    - const char *jid = purple_xmlnode_get_attrib(item, "jid");
    - char *jid_norm = (char *)jabber_normalize(account, jid);
    -
    - if (g_slist_find_custom(list, jid_norm, (GCompareFunc)g_strcmp0)) {
    - purple_xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER);
    - purple_xmlnode_set_attrib(query, "gr:ext", "2");
    - purple_xmlnode_set_attrib(item, "gr:t", "B");
    - }
    -}
    -
    -gboolean jabber_google_roster_incoming(JabberStream *js, PurpleXmlNode *item)
    -{
    - PurpleAccount *account = purple_connection_get_account(js->gc);
    - const char *jid = purple_xmlnode_get_attrib(item, "jid");
    - gboolean on_block_list = FALSE;
    -
    - char *jid_norm;
    -
    - const char *grt = purple_xmlnode_get_attrib_with_namespace(item, "t", NS_GOOGLE_ROSTER);
    - const char *subscription = purple_xmlnode_get_attrib(item, "subscription");
    - const char *ask = purple_xmlnode_get_attrib(item, "ask");
    -
    - if ((!subscription || purple_strequal(subscription, "none")) && !ask) {
    - /* The Google Talk servers will automatically add people from your Gmail address book
    - * with subscription=none. If we see someone with subscription=none, ignore them.
    - */
    - return FALSE;
    - }
    -
    - jid_norm = g_strdup(jabber_normalize(account, jid));
    -
    - on_block_list = NULL != g_slist_find_custom(purple_account_privacy_get_denied(account),
    - jid_norm, (GCompareFunc)strcmp);
    -
    - if (grt && (*grt == 'H' || *grt == 'h')) {
    - /* Hidden; don't show this buddy. */
    - GSList *buddies = purple_blist_find_buddies(account, jid_norm);
    - if (buddies) {
    - purple_debug_info("jabber", "Removing %s from local buddy list\n",
    - jid_norm);
    -
    - g_slist_free_full(buddies, (GDestroyNotify)purple_blist_remove_buddy);
    - }
    -
    - g_free(jid_norm);
    - return FALSE;
    - }
    -
    - if (!on_block_list && (grt && (*grt == 'B' || *grt == 'b'))) {
    - purple_debug_info("jabber", "Blocking %s\n", jid_norm);
    - purple_account_privacy_deny_add(account, jid_norm, TRUE);
    - } else if (on_block_list && (!grt || (*grt != 'B' && *grt != 'b' ))){
    - purple_debug_info("jabber", "Unblocking %s\n", jid_norm);
    - purple_account_privacy_deny_remove(account, jid_norm, TRUE);
    - }
    -
    - g_free(jid_norm);
    - return TRUE;
    -}
    -
    -void jabber_google_roster_add_deny(JabberStream *js, const char *who)
    -{
    - PurpleAccount *account;
    - GSList *buddies;
    - JabberIq *iq;
    - PurpleXmlNode *query;
    - PurpleXmlNode *item;
    - PurpleXmlNode *group;
    - PurpleBuddy *b;
    - JabberBuddy *jb;
    - const char *balias;
    -
    - jb = jabber_buddy_find(js, who, TRUE);
    -
    - account = purple_connection_get_account(js->gc);
    - buddies = purple_blist_find_buddies(account, who);
    - if(!buddies)
    - return;
    -
    - iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster");
    -
    - query = purple_xmlnode_get_child(iq->node, "query");
    - item = purple_xmlnode_new_child(query, "item");
    -
    - do {
    - PurpleGroup *g;
    -
    - b = buddies->data;
    - g = purple_buddy_get_group(b);
    -
    - group = purple_xmlnode_new_child(item, "group");
    - purple_xmlnode_insert_data(group,
    - jabber_roster_group_get_global_name(g), -1);
    -
    - buddies = g_slist_delete_link(buddies, buddies);
    - } while (buddies);
    -
    - balias = purple_buddy_get_local_alias(b);
    - purple_xmlnode_set_attrib(item, "jid", who);
    - purple_xmlnode_set_attrib(item, "name", balias ? balias : "");
    - purple_xmlnode_set_attrib(item, "gr:t", "B");
    - purple_xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER);
    - purple_xmlnode_set_attrib(query, "gr:ext", "2");
    -
    - jabber_iq_send(iq);
    -
    - /* Synthesize a sign-off */
    - if (jb) {
    - JabberBuddyResource *jbr;
    - GList *l = jb->resources;
    - while (l) {
    - jbr = l->data;
    - if (jbr && jbr->name)
    - {
    - purple_debug_misc("jabber", "Removing resource %s\n", jbr->name);
    - jabber_buddy_remove_resource(jb, jbr->name);
    - }
    - l = l->next;
    - }
    - }
    -
    - purple_protocol_got_user_status(account, who, "offline", NULL);
    -}
    -
    -void jabber_google_roster_rem_deny(JabberStream *js, const char *who)
    -{
    - GSList *buddies;
    - JabberIq *iq;
    - PurpleXmlNode *query;
    - PurpleXmlNode *item;
    - PurpleXmlNode *group;
    - PurpleBuddy *b;
    - const char *balias;
    -
    - buddies = purple_blist_find_buddies(purple_connection_get_account(js->gc), who);
    - if(!buddies)
    - return;
    -
    - iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster");
    -
    - query = purple_xmlnode_get_child(iq->node, "query");
    - item = purple_xmlnode_new_child(query, "item");
    -
    - do {
    - PurpleGroup *g;
    -
    - b = buddies->data;
    - g = purple_buddy_get_group(b);
    -
    - group = purple_xmlnode_new_child(item, "group");
    - purple_xmlnode_insert_data(group,
    - jabber_roster_group_get_global_name(g), -1);
    -
    - buddies = g_slist_delete_link(buddies, buddies);
    - } while (buddies);
    -
    - balias = purple_buddy_get_local_alias(b);
    - purple_xmlnode_set_attrib(item, "jid", who);
    - purple_xmlnode_set_attrib(item, "name", balias ? balias : "");
    - purple_xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER);
    - purple_xmlnode_set_attrib(query, "gr:ext", "2");
    -
    - jabber_iq_send(iq);
    -
    - /* See if he's online */
    - jabber_presence_subscription_set(js, who, "probe");
    -}
    -
    --- a/libpurple/protocols/jabber/google/google_roster.h Sat Jan 23 20:28:06 2021 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,37 +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
    - * source distribution.
    - *
    - * 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_JABBER_GOOGLE_ROSTER_H_
    -#define PURPLE_JABBER_GOOGLE_ROSTER_H_
    -
    -#include "jabber.h"
    -
    -void jabber_google_roster_outgoing(JabberStream *js, PurpleXmlNode *query, PurpleXmlNode *item);
    -
    -/* Returns FALSE if this should short-circuit processing of this roster item, or TRUE
    - * if this roster item should continue to be processed
    - */
    -gboolean jabber_google_roster_incoming(JabberStream *js, PurpleXmlNode *item);
    -
    -void jabber_google_roster_add_deny(JabberStream *js, const char *who);
    -void jabber_google_roster_rem_deny(JabberStream *js, const char *who);
    -
    -
    -#endif /* PURPLE_JABBER_GOOGLE_ROSTER_H_ */
    --- a/libpurple/protocols/jabber/google/google_session.c Sat Jan 23 20:28:06 2021 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,869 +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
    - * source distribution.
    - *
    - * 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 <config.h>
    -
    -#include <purple.h>
    -
    -#include "google_session.h"
    -#include "relay.h"
    -
    -#include "jingle/jingle.h"
    -
    -#ifdef USE_VV
    -
    -typedef struct {
    - PurpleMedia *media;
    - gboolean video;
    - GList *remote_audio_candidates; /* list of PurpleMediaCandidate */
    - GList *remote_video_candidates; /* list of PurpleMediaCandidate */
    - gboolean added_streams; /* this indicates if the streams have been
    - to media (ie. after getting relay credentials */
    -} GoogleAVSessionData;
    -
    -static gboolean
    -google_session_id_equal(gconstpointer a, gconstpointer b)
    -{
    - GoogleSessionId *c = (GoogleSessionId*)a;
    - GoogleSessionId *d = (GoogleSessionId*)b;
    -
    - return purple_strequal(c->id, d->id) && purple_strequal(c->initiator, d->initiator);
    -}
    -
    -static void
    -google_session_destroy(GoogleSession *session)
    -{
    - GoogleAVSessionData *session_data =
    - (GoogleAVSessionData *) session->session_data;
    - g_free(session->id.id);
    - g_free(session->id.initiator);
    - g_free(session->remote_jid);
    -
    - if (session_data->remote_audio_candidates)
    - purple_media_candidate_list_free(session_data->remote_audio_candidates);
    -
    - if (session_data->remote_video_candidates)
    - purple_media_candidate_list_free(session_data->remote_video_candidates);
    -
    - if (session->description)
    - purple_xmlnode_free(session->description);
    -
    - g_free(session->session_data);
    - g_free(session);
    -}
    -
    -static PurpleXmlNode *
    -google_session_create_xmlnode(GoogleSession *session, const char *type)
    -{
    - PurpleXmlNode *node = purple_xmlnode_new("session");
    - purple_xmlnode_set_namespace(node, NS_GOOGLE_SESSION);
    - purple_xmlnode_set_attrib(node, "id", session->id.id);
    - purple_xmlnode_set_attrib(node, "initiator", session->id.initiator);
    - purple_xmlnode_set_attrib(node, "type", type);
    - return node;
    -}
    -
    -static void
    -google_session_send_candidates(PurpleMedia *media, gchar *session_id,
    - gchar *participant, GoogleSession *session)
    -{
    - PurpleMedia *session_media =
    - ((GoogleAVSessionData *) session->session_data)->media;
    - GList *candidates =
    - purple_media_get_local_candidates(session_media, session_id,
    - session->remote_jid);
    - GList *iter;
    - PurpleMediaCandidate *transport;
    - gboolean video = FALSE;
    -
    - if (purple_strequal(session_id, "google-video"))
    - video = TRUE;
    -
    - for (iter = candidates; iter; iter = iter->next) {
    - JabberIq *iq;
    - gchar *ip, *port, *username, *password;
    - gchar pref[G_ASCII_DTOSTR_BUF_SIZE];
    - PurpleMediaCandidateType type;
    - PurpleXmlNode *sess;
    - PurpleXmlNode *candidate;
    - guint component_id;
    - transport = PURPLE_MEDIA_CANDIDATE(iter->data);
    - component_id = purple_media_candidate_get_component_id(
    - transport);
    -
    - iq = jabber_iq_new(session->js, JABBER_IQ_SET);
    - sess = google_session_create_xmlnode(session, "candidates");
    - purple_xmlnode_insert_child(iq->node, sess);
    - purple_xmlnode_set_attrib(iq->node, "to", session->remote_jid);
    -
    - candidate = purple_xmlnode_new("candidate");
    -
    - ip = purple_media_candidate_get_ip(transport);
    - port = g_strdup_printf("%d",
    - purple_media_candidate_get_port(transport));
    - g_ascii_dtostr(pref, G_ASCII_DTOSTR_BUF_SIZE,
    - purple_media_candidate_get_priority(transport) / 1000.0);
    - username = purple_media_candidate_get_username(transport);
    - password = purple_media_candidate_get_password(transport);
    - type = purple_media_candidate_get_candidate_type(transport);
    -
    - purple_xmlnode_set_attrib(candidate, "address", ip);
    - purple_xmlnode_set_attrib(candidate, "port", port);
    - purple_xmlnode_set_attrib(candidate, "name",
    - component_id == PURPLE_MEDIA_COMPONENT_RTP ?
    - video ? "video_rtp" : "rtp" :
    - component_id == PURPLE_MEDIA_COMPONENT_RTCP ?
    - video ? "video_rtcp" : "rtcp" : "none");
    - purple_xmlnode_set_attrib(candidate, "username", username);
    - /*
    - * As of this writing, Farsight 2 in Google compatibility
    - * mode doesn't provide a password. The Gmail client
    - * requires this to be set.
    - */
    - purple_xmlnode_set_attrib(candidate, "password",
    - password != NULL ? password : "");
    - purple_xmlnode_set_attrib(candidate, "preference", pref);
    - purple_xmlnode_set_attrib(candidate, "protocol",
    - purple_media_candidate_get_protocol(transport)
    - == PURPLE_MEDIA_NETWORK_PROTOCOL_UDP ?
    - "udp" : "tcp");
    - purple_xmlnode_set_attrib(candidate, "type", type ==
    - PURPLE_MEDIA_CANDIDATE_TYPE_HOST ? "local" :
    - type ==
    - PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX ? "stun" :
    - type ==
    - PURPLE_MEDIA_CANDIDATE_TYPE_RELAY ? "relay" :
    - NULL);
    - purple_xmlnode_set_attrib(candidate, "generation", "0");
    - purple_xmlnode_set_attrib(candidate, "network", "0");
    - purple_xmlnode_insert_child(sess, candidate);
    -
    - g_free(ip);
    - g_free(port);
    - g_free(username);
    - g_free(password);
    -
    - jabber_iq_send(iq);
    - }
    - purple_media_candidate_list_free(candidates);
    -}
    -
    -static void
    -google_session_ready(GoogleSession *session)
    -{
    - PurpleMedia *media =
    - ((GoogleAVSessionData *)session->session_data)->media;
    - gboolean video =
    - ((GoogleAVSessionData *)session->session_data)->video;
    - if (purple_media_codecs_ready(media, NULL) &&
    - purple_media_candidates_prepared(media, NULL, NULL)) {
    - gchar *me = g_strdup_printf("%s@%s/%s",
    - session->js->user->node,
    - session->js->user->domain,
    - session->js->user->resource);
    - JabberIq *iq;
    - PurpleXmlNode *sess, *desc, *payload;
    - GList *codecs, *iter;
    - gboolean is_initiator = purple_strequal(session->id.initiator, me);
    -
    - if (!is_initiator &&
    - !purple_media_accepted(media, NULL, NULL)) {
    - g_free(me);
    - return;
    - }
    -
    - iq = jabber_iq_new(session->js, JABBER_IQ_SET);
    -
    - if (is_initiator) {
    - purple_xmlnode_set_attrib(iq->node, "to", session->remote_jid);
    - purple_xmlnode_set_attrib(iq->node, "from", session->id.initiator);
    - sess = google_session_create_xmlnode(session, "initiate");
    - } else {
    - google_session_send_candidates(media,
    - "google-voice", session->remote_jid,
    - session);
    - google_session_send_candidates(media,
    - "google-video", session->remote_jid,
    - session);
    - purple_xmlnode_set_attrib(iq->node, "to", session->remote_jid);
    - purple_xmlnode_set_attrib(iq->node, "from", me);
    - sess = google_session_create_xmlnode(session, "accept");
    - }
    - purple_xmlnode_insert_child(iq->node, sess);
    - desc = purple_xmlnode_new_child(sess, "description");
    - if (video)
    - purple_xmlnode_set_namespace(desc, NS_GOOGLE_SESSION_VIDEO);
    - else
    - purple_xmlnode_set_namespace(desc, NS_GOOGLE_SESSION_PHONE);
    -
    - codecs = purple_media_get_codecs(media, "google-video");
    -
    - for (iter = codecs; iter; iter = g_list_next(iter)) {
    - PurpleMediaCodec *codec = (PurpleMediaCodec*)iter->data;
    - gchar *id = g_strdup_printf("%d",
    - purple_media_codec_get_id(codec));
    - gchar *encoding_name =
    - purple_media_codec_get_encoding_name(codec);
    - payload = purple_xmlnode_new_child(desc, "payload-type");
    - purple_xmlnode_set_attrib(payload, "id", id);
    - purple_xmlnode_set_attrib(payload, "name", encoding_name);
    - purple_xmlnode_set_attrib(payload, "width", "320");
    - purple_xmlnode_set_attrib(payload, "height", "200");
    - purple_xmlnode_set_attrib(payload, "framerate", "30");
    - g_free(encoding_name);
    - g_free(id);
    - }
    - purple_media_codec_list_free(codecs);
    -
    - codecs = purple_media_get_codecs(media, "google-voice");
    -
    - for (iter = codecs; iter; iter = g_list_next(iter)) {
    - PurpleMediaCodec *codec = (PurpleMediaCodec*)iter->data;
    - gchar *id = g_strdup_printf("%d",
    - purple_media_codec_get_id(codec));
    - gchar *encoding_name =
    - purple_media_codec_get_encoding_name(codec);
    - gchar *clock_rate = g_strdup_printf("%d",
    - purple_media_codec_get_clock_rate(codec));
    - payload = purple_xmlnode_new_child(desc, "payload-type");
    - if (video)
    - purple_xmlnode_set_namespace(payload, NS_GOOGLE_SESSION_PHONE);
    - purple_xmlnode_set_attrib(payload, "id", id);
    - /*
    - * Hack to make Gmail accept speex as the codec.
    - * It shouldn't have to be case sensitive.
    - */
    - if (purple_strequal(encoding_name, "SPEEX"))
    - purple_xmlnode_set_attrib(payload, "name", "speex");
    - else
    - purple_xmlnode_set_attrib(payload, "name", encoding_name);
    - purple_xmlnode_set_attrib(payload, "clockrate", clock_rate);
    - g_free(clock_rate);
    - g_free(encoding_name);
    - g_free(id);
    - }
    - purple_media_codec_list_free(codecs);
    -
    - jabber_iq_send(iq);
    -
    - if (is_initiator) {
    - google_session_send_candidates(media,
    - "google-voice", session->remote_jid,
    - session);
    - google_session_send_candidates(media,
    - "google-video", session->remote_jid,
    - session);
    - }
    -
    - g_signal_handlers_disconnect_by_func(G_OBJECT(media),
    - G_CALLBACK(google_session_ready), session);
    - }
    -}
    -
    -static void
    -google_session_state_changed_cb(PurpleMedia *media, PurpleMediaState state,
    - gchar *sid, gchar *name, GoogleSession *session)
    -{
    - if (sid == NULL && name == NULL) {
    - if (state == PURPLE_MEDIA_STATE_END) {
    - google_session_destroy(session);
    - }
    - }
    -}
    -
    -static void
    -google_session_stream_info_cb(PurpleMedia *media, PurpleMediaInfoType type,
    - gchar *sid, gchar *name, gboolean local,
    - GoogleSession *session)
    -{
    - if (sid != NULL || name != NULL)
    - return;
    -
    - if (type == PURPLE_MEDIA_INFO_HANGUP) {
    - PurpleXmlNode *sess;
    - JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);
    -
    - purple_xmlnode_set_attrib(iq->node, "to", session->remote_jid);
    - sess = google_session_create_xmlnode(session, "terminate");
    - purple_xmlnode_insert_child(iq->node, sess);
    -
    - jabber_iq_send(iq);
    - } else if (type == PURPLE_MEDIA_INFO_REJECT) {
    - PurpleXmlNode *sess;
    - JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);
    -
    - purple_xmlnode_set_attrib(iq->node, "to", session->remote_jid);
    - sess = google_session_create_xmlnode(session, "reject");
    - purple_xmlnode_insert_child(iq->node, sess);
    -
    - jabber_iq_send(iq);
    - } else if (type == PURPLE_MEDIA_INFO_ACCEPT && local == TRUE) {
    - google_session_ready(session);
    - }
    -}
    -
    -static GParameter *
    -jabber_google_session_get_params(JabberStream *js, const gchar *relay_ip,
    - guint16 relay_udp, guint16 relay_tcp, guint16 relay_ssltcp,
    - const gchar *relay_username, const gchar *relay_password, guint *num)
    -{
    - guint num_params;
    - GParameter *params =
    - jingle_get_params(js, relay_ip, relay_udp, relay_tcp, relay_ssltcp,
    - relay_username, relay_password, &num_params);
    - GParameter *new_params = g_new0(GParameter, num_params + 1);
    -
    - memcpy(new_params, params, sizeof(GParameter) * num_params);
    -
    - purple_debug_info("jabber", "setting Google jingle compatibility param\n");
    - new_params[num_params].name = "compatibility-mode";
    - g_value_init(&new_params[num_params].value, G_TYPE_UINT);
    - g_value_set_uint(&new_params[num_params].value, 1); /* NICE_COMPATIBILITY_GOOGLE */
    -
    - g_free(params);
    - *num = num_params + 1;
    - return new_params;
    -}
    -
    -
    -static void
    -jabber_google_relay_response_session_initiate_cb(GoogleSession *session,
    - const gchar *relay_ip, guint relay_udp, guint relay_tcp, guint relay_ssltcp,
    - const gchar *relay_username, const gchar *relay_password)
    -{
    - GParameter *params;
    - guint num_params;
    - JabberStream *js = session->js;
    - GoogleAVSessionData *session_data =
    - (GoogleAVSessionData *) session->session_data;
    -
    - session_data->media = purple_media_manager_create_media(
    - purple_media_manager_get(),
    - purple_connection_get_account(js->gc),
    - "fsrtpconference", session->remote_jid, TRUE);
    -
    - purple_media_set_protocol_data(session_data->media, session);
    -
    - g_signal_connect_swapped(G_OBJECT(session_data->media),
    - "candidates-prepared",
    - G_CALLBACK(google_session_ready), session);
    - g_signal_connect_swapped(G_OBJECT(session_data->media), "codecs-changed",
    - G_CALLBACK(google_session_ready), session);
    - g_signal_connect(G_OBJECT(session_data->media), "state-changed",
    - G_CALLBACK(google_session_state_changed_cb), session);
    - g_signal_connect(G_OBJECT(session_data->media), "stream-info",
    - G_CALLBACK(google_session_stream_info_cb), session);
    -
    - params =
    - jabber_google_session_get_params(js, relay_ip, relay_udp, relay_tcp,
    - relay_ssltcp, relay_username, relay_password, &num_params);
    -
    - if (purple_media_add_stream(session_data->media, "google-voice",
    - session->remote_jid, PURPLE_MEDIA_AUDIO,
    - TRUE, "nice", num_params, params) == FALSE ||
    - (session_data->video && purple_media_add_stream(
    - session_data->media, "google-video",
    - session->remote_jid, PURPLE_MEDIA_VIDEO,
    - TRUE, "nice", num_params, params) == FALSE)) {
    - purple_media_error(session_data->media, "Error adding stream.");
    - purple_media_end(session_data->media, NULL, NULL);
    - } else {
    - session_data->added_streams = TRUE;
    - }
    -
    - g_free(params);
    -}
    -
    -
    -gboolean
    -jabber_google_session_initiate(JabberStream *js, const gchar *who, PurpleMediaSessionType type)
    -{
    - GoogleSession *session;
    - JabberBuddy *jb;
    - JabberBuddyResource *jbr;
    - gchar *jid;
    - GoogleAVSessionData *session_data = NULL;
    -
    - /* construct JID to send to */
    - jb = jabber_buddy_find(js, who, FALSE);
    - if (!jb) {
    - purple_debug_error("jingle-rtp",
    - "Could not find Jabber buddy\n");
    - return FALSE;
    - }
    - jbr = jabber_buddy_find_resource(jb, NULL);
    - if (!jbr) {
    - purple_debug_error("jingle-rtp",
    - "Could not find buddy's resource\n");
    - }
    -
    - if ((strchr(who, '/') == NULL) && jbr && (jbr->name != NULL)) {
    - jid = g_strdup_printf("%s/%s", who, jbr->name);
    - } else {
    - jid = g_strdup(who);
    - }
    -
    - session = g_new0(GoogleSession, 1);
    - session->id.id = jabber_get_next_id(js);
    - session->id.initiator = g_strdup_printf("%s@%s/%s", js->user->node,
    - js->user->domain, js->user->resource);
    - session->state = SENT_INITIATE;
    - session->js = js;
    - session->remote_jid = jid;
    - session_data = g_new0(GoogleAVSessionData, 1);
    - session->session_data = session_data;
    -
    - if (type & PURPLE_MEDIA_VIDEO)
    - session_data->video = TRUE;
    -
    - /* if we got a relay token and relay host in google:jingleinfo, issue an
    - HTTP request to get that data */
    - if (js->google_relay_host && js->google_relay_token) {
    - jabber_google_do_relay_request(js, session,
    - jabber_google_relay_response_session_initiate_cb);
    - } else {
    - jabber_google_relay_response_session_initiate_cb(session, NULL, 0, 0, 0,
    - NULL, NULL);
    - }
    -
    - /* we don't actually know yet wether it succeeded... maybe this is very
    - wrong... */
    - return TRUE;
    -}
    -
    -static void
    -jabber_google_relay_response_session_handle_initiate_cb(GoogleSession *session,
    - const gchar *relay_ip, guint relay_udp, guint relay_tcp, guint relay_ssltcp,
    - const gchar *relay_username, const gchar *relay_password)
    -{
    - GParameter *params;
    - guint num_params;
    - JabberStream *js = session->js;
    - PurpleXmlNode *codec_element;
    - const gchar *xmlns;
    - PurpleMediaCodec *codec;
    - GList *video_codecs = NULL;
    - GList *codecs = NULL;
    - JabberIq *result;
    - GoogleAVSessionData *session_data =
    - (GoogleAVSessionData *) session->session_data;
    -
    - params =
    - jabber_google_session_get_params(js, relay_ip, relay_udp, relay_tcp,
    - relay_ssltcp, relay_username, relay_password, &num_params);
    -
    - if (purple_media_add_stream(session_data->media, "google-voice",
    - session->remote_jid, PURPLE_MEDIA_AUDIO, FALSE,
    - "nice", num_params, params) == FALSE ||
    - (session_data->video && purple_media_add_stream(
    - session_data->media, "google-video",
    - session->remote_jid, PURPLE_MEDIA_VIDEO,
    - FALSE, "nice", num_params, params) == FALSE)) {
    - purple_media_error(session_data->media, "Error adding stream.");
    - purple_media_stream_info(session_data->media,
    - PURPLE_MEDIA_INFO_REJECT, NULL, NULL, TRUE);
    - } else {
    - /* successfully added stream(s) */
    - session_data->added_streams = TRUE;
    -
    - if (session_data->remote_audio_candidates) {
    - purple_media_add_remote_candidates(session_data->media,
    - "google-voice", session->remote_jid,
    - session_data->remote_audio_candidates);
    - purple_media_candidate_list_free(session_data->remote_audio_candidates);
    - session_data->remote_audio_candidates = NULL;
    - }
    - if (session_data->remote_video_candidates) {
    - purple_media_add_remote_candidates(session_data->media,
    - "google-video", session->remote_jid,
    - session_data->remote_video_candidates);
    - purple_media_candidate_list_free(session_data->remote_video_candidates);
    - session_data->remote_video_candidates = NULL;
    - }
    - }
    -
    - g_free(params);
    -
    - for (codec_element = purple_xmlnode_get_child(session->description, "payload-type");
    - codec_element; codec_element = codec_element->next) {
    - const char *id, *encoding_name, *clock_rate;
    - gboolean video;
    - if (codec_element->name &&
    - !purple_strequal(codec_element->name, "payload-type"))
    - continue;
    -
    - xmlns = purple_xmlnode_get_namespace(codec_element);
    - encoding_name = purple_xmlnode_get_attrib(codec_element, "name");
    - id = purple_xmlnode_get_attrib(codec_element, "id");
    -
    - if (!session_data->video ||
    - purple_strequal(xmlns, NS_GOOGLE_SESSION_PHONE)) {
    - clock_rate = purple_xmlnode_get_attrib(
    - codec_element, "clockrate");
    - video = FALSE;
    - } else {
    - /*width = purple_xmlnode_get_attrib(codec_element, "width");
    - height = purple_xmlnode_get_attrib(codec_element, "height");
    - framerate = purple_xmlnode_get_attrib(
    - codec_element, "framerate");*/
    - clock_rate = "90000";
    - video = TRUE;
    - }
    -
    - if (id) {
    - codec = purple_media_codec_new(atoi(id), encoding_name,
    - video ? PURPLE_MEDIA_VIDEO :
    - PURPLE_MEDIA_AUDIO,
    - clock_rate ? atoi(clock_rate) : 0);
    - if (video)
    - video_codecs = g_list_append(
    - video_codecs, codec);
    - else
    - codecs = g_list_append(codecs, codec);
    - }
    - }
    -
    - if (codecs)
    - purple_media_set_remote_codecs(session_data->media, "google-voice",
    - session->remote_jid, codecs);
    - if (video_codecs)
    - purple_media_set_remote_codecs(session_data->media, "google-video",
    - session->remote_jid, video_codecs);
    -
    - purple_media_codec_list_free(codecs);
    - purple_media_codec_list_free(video_codecs);
    -
    - result = jabber_iq_new(js, JABBER_IQ_RESULT);
    - jabber_iq_set_id(result, session->iq_id);
    - purple_xmlnode_set_attrib(result->node, "to", session->remote_jid);
    - jabber_iq_send(result);
    -}
    -
    -static gboolean
    -google_session_handle_initiate(JabberStream *js, GoogleSession *session, PurpleXmlNode *sess, const char *iq_id)
    -{
    - const gchar *xmlns;
    - GoogleAVSessionData *session_data =
    - (GoogleAVSessionData *) session->session_data;
    -
    - if (session->state != UNINIT) {
    - purple_debug_error("jabber", "Received initiate for active session.\n");
    - return FALSE;
    - }
    -
    - session->description = purple_xmlnode_copy(purple_xmlnode_get_child(sess, "description"));
    - xmlns = purple_xmlnode_get_namespace(session->description);
    -
    - if (purple_strequal(xmlns, NS_GOOGLE_SESSION_PHONE))
    - session_data->video = FALSE;
    - else if (purple_strequal(xmlns, NS_GOOGLE_SESSION_VIDEO))
    - session_data->video = TRUE;
    - else {
    - purple_debug_error("jabber", "Received initiate with "
    - "invalid namespace %s.\n", xmlns);
    - return FALSE;
    - }
    -
    - session_data->media = purple_media_manager_create_media(
    - purple_media_manager_get(),
    - purple_connection_get_account(js->gc),
    - "fsrtpconference", session->remote_jid, FALSE);
    -
    - purple_media_set_protocol_data(session_data->media, session);
    -
    - g_signal_connect_swapped(G_OBJECT(session_data->media),
    - "candidates-prepared",
    - G_CALLBACK(google_session_ready), session);
    - g_signal_connect_swapped(G_OBJECT(session_data->media), "codecs-changed",
    - G_CALLBACK(google_session_ready), session);
    - g_signal_connect(G_OBJECT(session_data->media), "state-changed",
    - G_CALLBACK(google_session_state_changed_cb), session);
    - g_signal_connect(G_OBJECT(session_data->media), "stream-info",
    - G_CALLBACK(google_session_stream_info_cb), session);
    -
    - session->iq_id = g_strdup(iq_id);
    -
    - if (js->google_relay_host && js->google_relay_token) {
    - jabber_google_do_relay_request(js, session,
    - jabber_google_relay_response_session_handle_initiate_cb);
    - } else {
    - jabber_google_relay_response_session_handle_initiate_cb(session, NULL,
    - 0, 0, 0, NULL, NULL);
    - }
    -
    - return TRUE;
    -}
    -
    -
    -static void
    -google_session_handle_candidates(JabberStream *js, GoogleSession *session, PurpleXmlNode *sess, const char *iq_id)
    -{
    - JabberIq *result;
    - GList *list = NULL, *video_list = NULL;
    - PurpleXmlNode *cand;
    - static int name = 0;
    - char n[4];
    - GoogleAVSessionData *session_data =
    - (GoogleAVSessionData *) session->session_data;
    -
    - for (cand = purple_xmlnode_get_child(sess, "candidate"); cand;
    - cand = purple_xmlnode_get_next_twin(cand)) {
    - PurpleMediaCandidate *info;
    - const gchar *cname = purple_xmlnode_get_attrib(cand, "name");
    - const gchar *type = purple_xmlnode_get_attrib(cand, "type");
    - const gchar *protocol = purple_xmlnode_get_attrib(cand, "protocol");
    - const gchar *address = purple_xmlnode_get_attrib(cand, "address");
    - const gchar *port = purple_xmlnode_get_attrib(cand, "port");
    - const gchar *preference = purple_xmlnode_get_attrib(cand, "preference");
    - guint component_id;
    -
    - if (cname && type && address && port) {
    - PurpleMediaCandidateType candidate_type;
    - guint prio = preference ? g_ascii_strtod(preference, NULL) * 1000 : 0;
    -
    - g_snprintf(n, sizeof(n), "S%d", name++);
    -
    - if (purple_strequal(type, "local"))
    - candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_HOST;
    - else if (purple_strequal(type, "stun"))
    - candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX;
    - else if (purple_strequal(type, "relay"))
    - candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_RELAY;
    - else
    - candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_HOST;
    -
    - if (purple_strequal(cname, "rtcp") ||
    - purple_strequal(cname, "video_rtcp"))
    - component_id = PURPLE_MEDIA_COMPONENT_RTCP;
    - else
    - component_id = PURPLE_MEDIA_COMPONENT_RTP;
    -
    - info = purple_media_candidate_new(n, component_id,
    - candidate_type,
    - purple_strequal(protocol, "udp") ?
    - PURPLE_MEDIA_NETWORK_PROTOCOL_UDP :
    - PURPLE_MEDIA_NETWORK_PROTOCOL_TCP_PASSIVE,
    - address,
    - atoi(port));
    - g_object_set(info, "username", purple_xmlnode_get_attrib(cand, "username"),
    - "password", purple_xmlnode_get_attrib(cand, "password"),
    - "priority", prio, NULL);
    - if (!strncmp(cname, "video_", 6)) {
    - if (session_data->added_streams) {
    - video_list = g_list_append(video_list, info);
    - } else {
    - session_data->remote_video_candidates =
    - g_list_append(session_data->remote_video_candidates,
    - info);
    - }
    - } else {
    - if (session_data->added_streams) {
    - list = g_list_append(list, info);
    - } else {
    - session_data->remote_audio_candidates =
    - g_list_append(session_data->remote_audio_candidates,
    - info);
    - }
    - }
    - }
    - }
    -
    - if (list) {
    - purple_media_add_remote_candidates(session_data->media, "google-voice",
    - session->remote_jid, list);
    - purple_media_candidate_list_free(list);
    - }
    - if (video_list) {
    - purple_media_add_remote_candidates(session_data->media, "google-video",
    - session->remote_jid, video_list);
    - purple_media_candidate_list_free(video_list);
    - }
    -
    - result = jabber_iq_new(js, JABBER_IQ_RESULT);
    - jabber_iq_set_id(result, iq_id);
    - purple_xmlnode_set_attrib(result->node, "to", session->remote_jid);
    - jabber_iq_send(result);
    -}
    -
    -static void
    -google_session_handle_accept(JabberStream *js, GoogleSession *session, PurpleXmlNode *sess, const char *iq_id)
    -{
    - PurpleXmlNode *desc_element = purple_xmlnode_get_child(sess, "description");
    - PurpleXmlNode *codec_element = purple_xmlnode_get_child(
    - desc_element, "payload-type");
    - GList *codecs = NULL, *video_codecs = NULL;
    - JabberIq *result = NULL;
    - const gchar *xmlns = purple_xmlnode_get_namespace(desc_element);
    - gboolean video = purple_strequal(xmlns, NS_GOOGLE_SESSION_VIDEO);
    - GoogleAVSessionData *session_data =
    - (GoogleAVSessionData *) session->session_data;
    -
    - for (; codec_element; codec_element = codec_element->next) {
    - const gchar *xmlns, *encoding_name, *id,
    - *clock_rate;
    - gboolean video_codec = FALSE;
    -
    - if (!purple_strequal(codec_element->name, "payload-type"))
    - continue;
    -
    - xmlns = purple_xmlnode_get_namespace(codec_element);
    - encoding_name = purple_xmlnode_get_attrib(codec_element, "name");
    - id = purple_xmlnode_get_attrib(codec_element, "id");
    -
    - if (!video || purple_strequal(xmlns, NS_GOOGLE_SESSION_PHONE))
    - clock_rate = purple_xmlnode_get_attrib(
    - codec_element, "clockrate");
    - else {
    - clock_rate = "90000";
    - /*width = purple_xmlnode_get_attrib(codec_element, "width");
    - height = purple_xmlnode_get_attrib(codec_element, "height");
    - framerate = purple_xmlnode_get_attrib(
    - codec_element, "framerate");*/
    - video_codec = TRUE;
    - }
    -
    - if (id && encoding_name) {
    - PurpleMediaCodec *codec = purple_media_codec_new(
    - atoi(id), encoding_name,
    - video_codec ? PURPLE_MEDIA_VIDEO :
    - PURPLE_MEDIA_AUDIO,
    - clock_rate ? atoi(clock_rate) : 0);
    - if (video_codec)
    - video_codecs = g_list_append(
    - video_codecs, codec);
    - else
    - codecs = g_list_append(codecs, codec);
    - }
    - }
    -
    - if (codecs)
    - purple_media_set_remote_codecs(session_data->media, "google-voice",
    - session->remote_jid, codecs);
    - if (video_codecs)
    - purple_media_set_remote_codecs(session_data->media, "google-video",
    - session->remote_jid, video_codecs);
    -
    - purple_media_stream_info(session_data->media, PURPLE_MEDIA_INFO_ACCEPT,
    - NULL, NULL, FALSE);
    -
    - result = jabber_iq_new(js, JABBER_IQ_RESULT);
    - jabber_iq_set_id(result, iq_id);
    - purple_xmlnode_set_attrib(result->node, "to", session->remote_jid);
    - jabber_iq_send(result);
    -}
    -
    -static void
    -google_session_handle_reject(JabberStream *js, GoogleSession *session, PurpleXmlNode *sess)
    -{
    - GoogleAVSessionData *session_data =
    - (GoogleAVSessionData *) session->session_data;
    - purple_media_end(session_data->media, NULL, NULL);
    -}
    -
    -static void
    -google_session_handle_terminate(JabberStream *js, GoogleSession *session, PurpleXmlNode *sess)
    -{
    - GoogleAVSessionData *session_data =
    - (GoogleAVSessionData *) session->session_data;
    - purple_media_end(session_data->media, NULL, NULL);
    -}
    -
    -static void
    -google_session_parse_iq(JabberStream *js, GoogleSession *session, PurpleXmlNode *sess, const char *iq_id)
    -{
    - const char *type = purple_xmlnode_get_attrib(sess, "type");
    -
    - if (purple_strequal(type, "initiate")) {
    - google_session_handle_initiate(js, session, sess, iq_id);
    - } else if (purple_strequal(type, "accept")) {
    - google_session_handle_accept(js, session, sess, iq_id);
    - } else if (purple_strequal(type, "reject")) {
    - google_session_handle_reject(js, session, sess);
    - } else if (purple_strequal(type, "terminate")) {
    - google_session_handle_terminate(js, session, sess);
    - } else if (purple_strequal(type, "candidates")) {
    - google_session_handle_candidates(js, session, sess, iq_id);
    - }
    -}
    -
    -void
    -jabber_google_session_parse(JabberStream *js, const char *from,
    - JabberIqType type, const char *iq_id,
    - PurpleXmlNode *session_node)
    -{
    - GoogleSession *session = NULL;
    - GoogleSessionId id;
    -
    - PurpleXmlNode *desc_node;
    -
    - GList *iter = NULL;
    -
    - if (type != JABBER_IQ_SET)
    - return;
    -
    - id.id = (gchar*)purple_xmlnode_get_attrib(session_node, "id");
    - if (!id.id)
    - return;
    -
    - id.initiator = (gchar*)purple_xmlnode_get_attrib(session_node, "initiator");
    - if (!id.initiator)
    - return;
    -
    - iter = purple_media_manager_get_media_by_account(
    - purple_media_manager_get(),
    - purple_connection_get_account(js->gc));
    - for (; iter; iter = g_list_delete_link(iter, iter)) {
    - GoogleSession *gsession =
    - purple_media_get_protocol_data(iter->data);
    - if (google_session_id_equal(&(gsession->id), &id)) {
    - session = gsession;
    - break;
    - }
    - }
    - if (iter != NULL) {
    - g_list_free(iter);
    - }
    -
    - if (session) {
    - google_session_parse_iq(js, session, session_node, iq_id);
    - return;
    - }
    -
    - /* If the session doesn't exist, this has to be an initiate message */
    - if (!purple_strequal(purple_xmlnode_get_attrib(session_node, "type"), "initiate"))
    - return;
    - desc_node = purple_xmlnode_get_child(session_node, "description");
    - if (!desc_node)
    - return;
    - session = g_new0(GoogleSession, 1);
    - session->id.id = g_strdup(id.id);
    - session->id.initiator = g_strdup(id.initiator);
    - session->state = UNINIT;
    - session->js = js;
    - session->remote_jid = g_strdup(session->id.initiator);
    - session->session_data = g_new0(GoogleAVSessionData, 1);
    -
    - if (!google_session_handle_initiate(js, session, session_node, iq_id)) {
    - google_session_destroy(session);
    - }
    -}
    -#endif /* USE_VV */
    -
    -
    --- a/libpurple/protocols/jabber/google/google_session.h Sat Jan 23 20:28:06 2021 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,56 +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
    - * source distribution.
    - *
    - * 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_JABBER_GOOGLE_SESSION_H_
    -#define PURPLE_JABBER_GOOGLE_SESSION_H_
    -
    -#include "jabber.h"
    -
    -typedef struct {
    - char *id;
    - char *initiator;
    -} GoogleSessionId;
    -
    -typedef enum {
    - UNINIT,
    - SENT_INITIATE,
    - RECEIVED_INITIATE,
    - IN_PRORESS,
    - TERMINATED
    -} GoogleSessionState;
    -
    -typedef struct {
    - GoogleSessionId id;
    - GoogleSessionState state;
    - JabberStream *js;
    - char *remote_jid;
    - char *iq_id;
    - PurpleXmlNode *description; /* store incoming description through
    - relay credential fetching */
    - gpointer session_data;
    -} GoogleSession;
    -
    -gboolean jabber_google_session_initiate(JabberStream *js, const gchar *who,
    - PurpleMediaSessionType type);
    -
    -void jabber_google_session_parse(JabberStream *js, const char *from,
    - JabberIqType type, const char *iq, PurpleXmlNode *session);
    -
    -#endif /* PURPLE_JABBER_GOOGLE_SESSION_H_ */
    \ No newline at end of file
    --- a/libpurple/protocols/jabber/google/jingleinfo.c Sat Jan 23 20:28:06 2021 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,162 +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
    - * source distribution.
    - *
    - * 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 <purple.h>
    -
    -#include "jingleinfo.h"
    -
    -#include <gio/gio.h>
    -
    -static void
    -jabber_google_stun_lookup_cb(GObject *sender, GAsyncResult *result, gpointer data) {
    - GError *error = NULL;
    - GList *addresses = NULL;
    - JabberStream *js = (JabberStream *) data;
    -
    - addresses = g_resolver_lookup_by_name_finish(G_RESOLVER(sender),
    - result, &error);
    -
    - if(error) {
    - purple_debug_error("jabber", "Google STUN lookup failed: %s\n",
    - error->message);
    -
    - g_error_free(error);
    -
    - return;
    - }
    -
    - if(g_list_length(addresses) > 0) {
    - GInetAddress *inet_address = G_INET_ADDRESS(addresses->data);
    -
    - g_free(js->stun_ip);
    - js->stun_ip = g_inet_address_to_string(inet_address);
    -
    - purple_debug_info("jabber", "set Google STUN IP/port address: "
    - "%s:%d\n", js->stun_ip, js->stun_port);
    - }
    -
    - g_resolver_free_addresses(addresses);
    -}
    -
    -static void
    -jabber_google_jingle_info_common(JabberStream *js, const char *from,
    - JabberIqType type, PurpleXmlNode *query)
    -{
    - const PurpleXmlNode *stun = purple_xmlnode_get_child(query, "stun");
    - const PurpleXmlNode *relay = purple_xmlnode_get_child(query, "relay");
    - gchar *my_bare_jid;
    -
    - /*
    - * Make sure that random people aren't sending us STUN servers. Per
    - * https://developers.google.com/talk/jep_extensions/jingleinfo, these
    - * stanzas are stamped from our bare JID.
    - */
    - if (from) {
    - my_bare_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain);
    - if (!purple_strequal(from, my_bare_jid)) {
    - purple_debug_warning("jabber", "got google:jingleinfo with invalid from (%s)\n",
    - from);
    - g_free(my_bare_jid);
    - return;
    - }
    -
    - g_free(my_bare_jid);
    - }
    -
    - if (type == JABBER_IQ_ERROR || type == JABBER_IQ_GET)
    - return;
    -
    - purple_debug_info("jabber", "got google:jingleinfo\n");
    -
    - if (stun) {
    - PurpleXmlNode *server = purple_xmlnode_get_child(stun, "server");
    -
    - if (server) {
    - const gchar *host = purple_xmlnode_get_attrib(server, "host");
    - const gchar *udp = purple_xmlnode_get_attrib(server, "udp");
    -
    - if (host && udp) {
    - GResolver *resolver = g_resolver_get_default();
    -
    - js->stun_port = atoi(udp);
    -
    - g_resolver_lookup_by_name_async(resolver,
    - host,
    - NULL,
    - jabber_google_stun_lookup_cb,
    - js);
    - g_object_unref(resolver);
    - }
    - }
    - }
    -
    - if (relay) {
    - PurpleXmlNode *token = purple_xmlnode_get_child(relay, "token");
    - PurpleXmlNode *server = purple_xmlnode_get_child(relay, "server");
    -
    - if (token) {
    - gchar *relay_token = purple_xmlnode_get_data(token);
    -
    - /* we let js own the string returned from purple_xmlnode_get_data */
    - js->google_relay_token = relay_token;
    - }
    -
    - if (server) {
    - js->google_relay_host =
    - g_strdup(purple_xmlnode_get_attrib(server, "host"));
    - }
    - }
    -}
    -
    -static void
    -jabber_google_jingle_info_cb(JabberStream *js, const char *from,
    - JabberIqType type, const char *id,
    - PurpleXmlNode *packet, gpointer data)
    -{
    - PurpleXmlNode *query = purple_xmlnode_get_child_with_namespace(packet, "query",
    - NS_GOOGLE_JINGLE_INFO);
    -
    - if (query)
    - jabber_google_jingle_info_common(js, from, type, query);
    - else
    - purple_debug_warning("jabber", "Got invalid google:jingleinfo\n");
    -}
    -
    -void
    -jabber_google_handle_jingle_info(JabberStream *js, const char *from,
    - JabberIqType type, const char *id,
    - PurpleXmlNode *child)
    -{
    - jabber_google_jingle_info_common(js, from, type, child);
    -}
    -
    -void
    -jabber_google_send_jingle_info(JabberStream *js)
    -{
    - JabberIq *jingle_info =
    - jabber_iq_new_query(js, JABBER_IQ_GET, NS_GOOGLE_JINGLE_INFO);
    -
    - jabber_iq_set_callback(jingle_info, jabber_google_jingle_info_cb,
    - NULL);
    - purple_debug_info("jabber", "sending google:jingleinfo query\n");
    - jabber_iq_send(jingle_info);
    -}
    --- a/libpurple/protocols/jabber/google/jingleinfo.h Sat Jan 23 20:28:06 2021 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,32 +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
    - * source distribution.
    - *
    - * 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_JABBER_GOOGLE_ROSTER_H_
    -#define PURPLE_JABBER_GOOGLE_ROSTER_H_
    -
    -#include "jabber.h"
    -
    -void jabber_google_handle_jingle_info(JabberStream *js, const char *from,
    - JabberIqType type, const char *id,
    - PurpleXmlNode *child);
    -void jabber_google_send_jingle_info(JabberStream *js);
    -
    -
    -#endif /* PURPLE_JABBER_GOOGLE_ROSTER_H_ */
    \ No newline at end of file
    --- a/libpurple/protocols/jabber/google/relay.c Sat Jan 23 20:28:06 2021 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,128 +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
    - * source distribution.
    - *
    - * 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 <purple.h>
    -
    -#include "relay.h"
    -
    -typedef struct {
    - GoogleSession *session;
    - JabberGoogleRelayCallback *cb;
    -} JabberGoogleRelayCallbackData;
    -
    -static void
    -jabber_google_relay_parse_response(const gchar *response, gchar **ip,
    - guint *udp, guint *tcp, guint *ssltcp, gchar **username, gchar **password)
    -{
    - gchar **lines = g_strsplit(response, "\n", -1);
    - int i = 0;
    -
    - for (; lines[i] ; i++) {
    - gchar *line = lines[i];
    - gchar **parts = g_strsplit(line, "=", 2);
    -
    - if (parts[0] && parts[1]) {
    - if (purple_strequal(parts[0], "relay.ip")) {
    - *ip = g_strdup(parts[1]);
    - } else if (purple_strequal(parts[0], "relay.udp_port")) {
    - *udp = atoi(parts[1]);
    - } else if (purple_strequal(parts[0], "relay.tcp_port")) {
    - *tcp = atoi(parts[1]);
    - } else if (purple_strequal(parts[0], "relay.ssltcp_port")) {
    - *ssltcp = atoi(parts[1]);
    - } else if (purple_strequal(parts[0], "username")) {
    - *username = g_strdup(parts[1]);
    - } else if (purple_strequal(parts[0], "password")) {
    - *password = g_strdup(parts[1]);
    - }
    - }
    - g_strfreev(parts);
    - }
    -
    - g_strfreev(lines);
    -}
    -
    -static void
    -jabber_google_relay_fetch_cb(G_GNUC_UNUSED SoupSession *soup, SoupMessage *msg,
    - gpointer user_data)
    -{
    - JabberGoogleRelayCallbackData *data =
    - (JabberGoogleRelayCallbackData *) user_data;
    - GoogleSession *session = data->session;
    - JabberGoogleRelayCallback *cb = data->cb;
    - gchar *relay_ip = NULL;
    - guint relay_udp = 0;
    - guint relay_tcp = 0;
    - guint relay_ssltcp = 0;
    - gchar *relay_username = NULL;
    - gchar *relay_password = NULL;
    -
    - g_free(data);
    -
    - purple_debug_info("jabber", "got response on HTTP request to relay server\n");
    -
    - if (SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) {
    - const gchar *got_data = msg->response_body->data;
    - purple_debug_info("jabber", "got Google relay request response:\n%s\n",
    - got_data);
    - jabber_google_relay_parse_response(got_data, &relay_ip, &relay_udp,
    - &relay_tcp, &relay_ssltcp, &relay_username, &relay_password);
    - }
    -
    - if (cb)
    - cb(session, relay_ip, relay_udp, relay_tcp, relay_ssltcp,
    - relay_username, relay_password);
    -
    - g_free(relay_ip);
    - g_free(relay_username);
    - g_free(relay_password);
    -}
    -
    -void
    -jabber_google_do_relay_request(JabberStream *js, GoogleSession *session,
    - JabberGoogleRelayCallback cb)
    -{
    - SoupURI *uri;
    - SoupMessage *msg;
    - JabberGoogleRelayCallbackData *data = g_new0(JabberGoogleRelayCallbackData, 1);
    -
    - data->session = session;
    - data->cb = cb;
    - purple_debug_info("jabber", "sending Google relay request\n");
    -
    - uri = soup_uri_new(NULL);
    - soup_uri_set_scheme(uri, SOUP_URI_SCHEME_HTTP);
    - soup_uri_set_host(uri, js->google_relay_host);
    - soup_uri_set_path(uri, "/create_session");
    - msg = soup_message_new_from_uri("GET", uri);
    - g_object_unref(uri);
    -
    - /* yes, the relay token is included twice as different request headers,
    - this is apparently needed to make Google's relay servers work... */
    - soup_message_headers_replace(msg->request_headers,
    - "X-Talk-Google-Relay-Auth",
    - js->google_relay_token);
    - soup_message_headers_replace(msg->request_headers, "X-Google-Relay-Auth",
    - js->google_relay_token);
    - soup_session_queue_message(js->http_conns, msg,
    - jabber_google_relay_fetch_cb, data);
    -}
    --- a/libpurple/protocols/jabber/google/relay.h Sat Jan 23 20:28:06 2021 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,33 +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
    - * source distribution.
    - *
    - * 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 JABBER_GOOGLE_RELAY
    -#define JABBER_GOOGLE_RELAY
    -
    -#include "google_session.h"
    -
    -typedef void (JabberGoogleRelayCallback)(GoogleSession *session, const gchar *ip,
    - guint udp_port, guint tcp_port, guint tls_port,
    - const gchar *username, const gchar *password);
    -
    -void jabber_google_do_relay_request(JabberStream *js, GoogleSession *session,
    - JabberGoogleRelayCallback cb);
    -
    -#endif /* JABBER_GOOGLE_RELAY */
    --- a/libpurple/protocols/jabber/gtalk.c Sat Jan 23 20:28:06 2021 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,137 +0,0 @@
    -/* purple
    - *
    - * Purple is the legal property of its developers, whose names are too numerous
    - * to list here. Please refer to the COPYRIGHT file distributed with this
    - * source distribution.
    - *
    - * 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 <purple.h>
    -
    -#include "gtalk.h"
    -
    -static const char *
    -gtalk_list_icon(PurpleAccount *a, PurpleBuddy *b)
    -{
    - return "google-talk";
    -}
    -
    -static void
    -gtalk_protocol_init(GTalkProtocol *self)
    -{
    - PurpleProtocol *protocol = PURPLE_PROTOCOL(self);
    - PurpleAccountUserSplit *split;
    - PurpleAccountOption *option;
    - GList *encryption_values = NULL;
    -
    - protocol->id = "prpl-gtalk";
    - protocol->name = "Google Talk (XMPP)";
    -
    - /* Translators: 'domain' is used here in the context of Internet domains, e.g. pidgin.im */
    - split = purple_account_user_split_new(_("Domain"), "gmail.com", '@');
    - purple_account_user_split_set_reverse(split, FALSE);
    - protocol->user_splits = g_list_append(protocol->user_splits, split);
    -
    - split = purple_account_user_split_new(_("Resource"), "", '/');
    - purple_account_user_split_set_reverse(split, FALSE);
    - protocol->user_splits = g_list_append(protocol->user_splits, split);
    -
    -#define ADD_VALUE(list, desc, v) { \
    - PurpleKeyValuePair *kvp = purple_key_value_pair_new_full((desc), g_strdup((v)), g_free); \
    - list = g_list_prepend(list, kvp); \
    -}
    -
    - ADD_VALUE(encryption_values, _("Require encryption"), "require_tls");
    - ADD_VALUE(encryption_values, _("Use encryption if available"), "opportunistic_tls");
    - ADD_VALUE(encryption_values, _("Use old-style SSL"), "old_ssl");
    - encryption_values = g_list_reverse(encryption_values);
    -
    -#undef ADD_VALUE
    -
    - option = purple_account_option_list_new(_("Connection security"), "connection_security", encryption_values);
    - protocol->account_options = g_list_append(protocol->account_options,
    - option);
    -
    - option = purple_account_option_bool_new(
    - _("Allow plaintext auth over unencrypted streams"),
    - "auth_plain_in_clear", FALSE);
    - protocol->account_options = g_list_append(protocol->account_options,
    - option);
    -
    - option = purple_account_option_int_new(_("Connect port"), "port", 5222);
    - protocol->account_options = g_list_append(protocol->account_options,
    - option);
    -
    - option = purple_account_option_string_new(_("Connect server"),
    - "connect_server", NULL);
    - protocol->account_options = g_list_append(protocol->account_options,
    - option);
    -
    - option = purple_account_option_string_new(_("File transfer proxies"),
    - "ft_proxies", NULL);
    - protocol->account_options = g_list_append(protocol->account_options,
    - option);
    -
    - option = purple_account_option_string_new(_("BOSH URL"),
    - "bosh_url", NULL);
    - protocol->account_options = g_list_append(protocol->account_options,
    - option);
    -
    - /* this should probably be part of global smiley theme settings later on,
    - shared with MSN */
    - option = purple_account_option_bool_new(_("Show Custom Smileys"),
    - "custom_smileys", TRUE);
    - protocol->account_options = g_list_append(protocol->account_options,
    - option);
    -}
    -
    -static void
    -gtalk_protocol_class_init(GTalkProtocolClass *klass)
    -{
    - PurpleProtocolClass *protocol_class = PURPLE_PROTOCOL_CLASS(klass);
    -
    - protocol_class->list_icon = gtalk_list_icon;
    -}
    -
    -static void
    -gtalk_protocol_class_finalize(G_GNUC_UNUSED GTalkProtocolClass *klass)
    -{
    -}
    -
    -static void
    -gtalk_protocol_server_iface_init(PurpleProtocolServerInterface *server_iface)
    -{
    - /* disable xmpp functions not available for gtalk */
    - server_iface->register_user = NULL;
    - server_iface->unregister_user = NULL;
    -}
    -
    -G_DEFINE_DYNAMIC_TYPE_EXTENDED(
    - GTalkProtocol, gtalk_protocol, JABBER_TYPE_PROTOCOL, 0,
    -
    - G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_SERVER,
    - gtalk_protocol_server_iface_init));
    -
    -/* This exists solely because the above macro makes gtalk_protocol_register_type
    - * static. */
    -void
    -gtalk_protocol_register(PurplePlugin *plugin)
    -{
    - gtalk_protocol_register_type(G_TYPE_MODULE(plugin));
    -}
    --- a/libpurple/protocols/jabber/gtalk.h Sat Jan 23 20:28:06 2021 -0600
    +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
    @@ -1,56 +0,0 @@
    -/* purple
    - *
    - * Purple is the legal property of its developers, whose names are too numerous
    - * to list here. Please refer to the COPYRIGHT file distributed with this
    - * source distribution.
    - *
    - * 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_JABBER_GTALK_H
    -#define PURPLE_JABBER_GTALK_H
    -
    -#include "jabber.h"
    -
    -#define GTALK_TYPE_PROTOCOL (gtalk_protocol_get_type())
    -#define GTALK_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTALK_TYPE_PROTOCOL, GTalkProtocol))
    -#define GTALK_PROTOCOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTALK_TYPE_PROTOCOL, GTalkProtocolClass))
    -#define GTALK_IS_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTALK_TYPE_PROTOCOL))
    -#define GTALK_IS_PROTOCOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTALK_TYPE_PROTOCOL))
    -#define GTALK_PROTOCOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTALK_TYPE_PROTOCOL, GTalkProtocolClass))
    -
    -typedef struct
    -{
    - JabberProtocol parent;
    -} GTalkProtocol;
    -
    -typedef struct
    -{
    - JabberProtocolClass parent_class;
    -} GTalkProtocolClass;
    -
    -/**
    - * Registers the GTalkProtocol type in the type system.
    - */
    -G_GNUC_INTERNAL
    -void gtalk_protocol_register(PurplePlugin *plugin);
    -
    -/**
    - * Returns the GType for the GTalkProtocol object.
    - */
    -G_MODULE_EXPORT GType gtalk_protocol_get_type(void);
    -
    -#endif /* PURPLE_JABBER_GTALK_H */
    --- a/libpurple/protocols/jabber/iq.c Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/iq.c Sat Jan 23 20:31:28 2021 -0600
    @@ -26,9 +26,6 @@
    #include "buddy.h"
    #include "disco.h"
    -#include "google/google.h"
    -#include "google/jingleinfo.h"
    -#include "google/google_session.h"
    #include "iq.h"
    #include "jingle/jingle.h"
    #include "oob.h"
    @@ -546,8 +543,6 @@
    jabber_iq_register_handler("jingle", JINGLE, jingle_parse);
    jabber_iq_register_handler("ping", NS_PING, jabber_ping_parse);
    - jabber_iq_register_handler("query", NS_GOOGLE_JINGLE_INFO,
    - jabber_google_handle_jingle_info);
    jabber_iq_register_handler("query", NS_BYTESTREAMS,
    jabber_bytestreams_parse);
    jabber_iq_register_handler("query", NS_DISCO_INFO, jabber_disco_info_parse);
    @@ -560,10 +555,6 @@
    jabber_roster_parse);
    jabber_iq_register_handler("query", "jabber:iq:version",
    jabber_iq_version_parse);
    -#ifdef USE_VV
    - jabber_iq_register_handler("session", NS_GOOGLE_SESSION,
    - jabber_google_session_parse);
    -#endif
    jabber_iq_register_handler("block", NS_SIMPLE_BLOCKING, jabber_blocklist_parse_push);
    jabber_iq_register_handler("unblock", NS_SIMPLE_BLOCKING, jabber_blocklist_parse_push);
    jabber_iq_register_handler("time", NS_ENTITY_TIME, jabber_time_parse);
    --- a/libpurple/protocols/jabber/jabber.c Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/jabber.c Sat Jan 23 20:31:28 2021 -0600
    @@ -35,10 +35,6 @@
    #include "chat.h"
    #include "data.h"
    #include "disco.h"
    -#include "google/google.h"
    -#include "google/google_p2p.h"
    -#include "google/google_roster.h"
    -#include "google/google_session.h"
    #include "ibb.h"
    #include "iq.h"
    #include "jutil.h"
    @@ -54,7 +50,6 @@
    #include "pep.h"
    #include "adhoccommands.h"
    #include "xmpp.h"
    -#include "gtalk.h"
    #include "jingle/jingle.h"
    #include "jingle/content.h"
    @@ -73,7 +68,6 @@
    GList *jabber_identities = NULL;
    static PurpleProtocol *xmpp_protocol = NULL;
    -static PurpleProtocol *gtalk_protocol = NULL;
    static GHashTable *jabber_cmds = NULL; /* PurpleProtocol * => GSList of ids */
    @@ -1004,8 +998,6 @@
    js->sessions = NULL;
    js->stun_ip = NULL;
    js->stun_port = 0;
    - js->google_relay_token = NULL;
    - js->google_relay_host = NULL;
    /* if we are idle, set idle-ness on the stream (this could happen if we get
    disconnected and the reconnects while being idle. I don't think it makes
    @@ -1688,8 +1680,6 @@
    g_list_free_full(js->commands, (GDestroyNotify)jabber_adhoc_commands_free);
    g_free(js->server_name);
    g_free(js->certificate_CN);
    - g_free(js->gmail_last_time);
    - g_free(js->gmail_last_tid);
    g_free(js->old_msg);
    g_free(js->old_avatarhash);
    g_free(js->old_artist);
    @@ -1698,9 +1688,6 @@
    g_free(js->old_uri);
    g_free(js->old_track);
    - if (js->vcard_timer != 0)
    - g_source_remove(js->vcard_timer);
    -
    if (js->keepalive_timeout != 0)
    g_source_remove(js->keepalive_timeout);
    if (js->inactivity_timer != 0)
    @@ -1713,10 +1700,6 @@
    g_free(js->stun_ip);
    - /* remove Google relay-related stuff */
    - g_free(js->google_relay_token);
    - g_free(js->google_relay_host);
    -
    g_free(js);
    purple_connection_set_protocol_data(gc, NULL);
    @@ -1923,12 +1906,6 @@
    if (js == NULL)
    return;
    - if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER)
    - {
    - jabber_google_roster_add_deny(js, who);
    - return;
    - }
    -
    if (!(js->server_caps & JABBER_CAP_BLOCKING))
    {
    purple_notify_error(NULL, _("Server doesn't support blocking"),
    @@ -1961,12 +1938,6 @@
    if (js == NULL)
    return;
    - if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER)
    - {
    - jabber_google_roster_rem_deny(js, who);
    - return;
    - }
    -
    if (!(js->server_caps & JABBER_CAP_BLOCKING))
    return;
    @@ -3384,13 +3355,7 @@
    g_free(resource);
    - if (type & PURPLE_MEDIA_AUDIO &&
    - !jabber_resource_has_capability(jbr,
    - JINGLE_APP_RTP_SUPPORT_AUDIO) &&
    - jabber_resource_has_capability(jbr, NS_GOOGLE_VOICE))
    - return jabber_google_session_initiate(js, who, type);
    - else
    - return jingle_rtp_initiate_media(js, who, type);
    + return jingle_rtp_initiate_media(js, who, type);
    } else if(!jb->resources->next) {
    /* only 1 resource online (probably our most common case)
    * so no need to ask who to initiate with */
    @@ -3558,11 +3523,6 @@
    caps |= PURPLE_MEDIA_CAPS_MODIFY_SESSION |
    PURPLE_MEDIA_CAPS_CHANGE_DIRECTION;
    }
    - if (jabber_resource_has_capability(jbr, NS_GOOGLE_VOICE)) {
    - caps |= PURPLE_MEDIA_CAPS_AUDIO;
    - if (jabber_resource_has_capability(jbr, NS_GOOGLE_VIDEO))
    - caps |= PURPLE_MEDIA_CAPS_AUDIO_VIDEO;
    - }
    total |= caps;
    }
    @@ -3967,10 +3927,6 @@
    jabber_add_feature(JINGLE, NULL);
    #ifdef USE_VV
    - jabber_add_feature(NS_GOOGLE_PROTOCOL_SESSION, jabber_audio_enabled);
    - jabber_add_feature(NS_GOOGLE_VOICE, jabber_audio_enabled);
    - jabber_add_feature(NS_GOOGLE_VIDEO, jabber_video_enabled);
    - jabber_add_feature(NS_GOOGLE_CAMERA, jabber_video_enabled);
    jabber_add_feature(JINGLE_APP_RTP, NULL);
    jabber_add_feature(JINGLE_APP_RTP_SUPPORT_AUDIO, jabber_audio_enabled);
    jabber_add_feature(JINGLE_APP_RTP_SUPPORT_VIDEO, jabber_video_enabled);
    @@ -4319,8 +4275,8 @@
    "name", "XMPP Protocols",
    "version", DISPLAY_VERSION,
    "category", N_("Protocol"),
    - "summary", N_("XMPP and GTalk Protocols Plugin"),
    - "description", N_("XMPP and GTalk Protocols Plugin"),
    + "summary", N_("XMPP Protocol Plugin"),
    + "description", N_("XMPP Protocol Plugin"),
    "website", PURPLE_WEBSITE,
    "abi-version", PURPLE_ABI_VERSION,
    "flags", PURPLE_PLUGIN_INFO_FLAGS_INTERNAL |
    @@ -4337,7 +4293,6 @@
    jingle_transport_register(plugin);
    jingle_iceudp_register(plugin);
    jingle_rawudp_register(plugin);
    - jingle_google_p2p_register(plugin);
    jingle_content_register(plugin);
    #ifdef USE_VV
    @@ -4346,7 +4301,6 @@
    jabber_protocol_register_type(G_TYPE_MODULE(plugin));
    - gtalk_protocol_register(plugin);
    xmpp_protocol_register(plugin);
    jabber_si_xfer_register(G_TYPE_MODULE(plugin));
    @@ -4355,17 +4309,10 @@
    if (!xmpp_protocol)
    return FALSE;
    - gtalk_protocol = purple_protocols_add(GTALK_TYPE_PROTOCOL, error);
    - if (!gtalk_protocol)
    - return FALSE;
    -
    purple_signal_connect(purple_get_core(), "uri-handler", xmpp_protocol,
    PURPLE_CALLBACK(xmpp_uri_handler), xmpp_protocol);
    - purple_signal_connect(purple_get_core(), "uri-handler", gtalk_protocol,
    - PURPLE_CALLBACK(xmpp_uri_handler), gtalk_protocol);
    jabber_init_protocol(xmpp_protocol);
    - jabber_init_protocol(gtalk_protocol);
    return TRUE;
    }
    @@ -4375,15 +4322,9 @@
    {
    purple_signal_disconnect(purple_get_core(), "uri-handler",
    xmpp_protocol, PURPLE_CALLBACK(xmpp_uri_handler));
    - purple_signal_disconnect(purple_get_core(), "uri-handler",
    - gtalk_protocol, PURPLE_CALLBACK(xmpp_uri_handler));
    -
    - jabber_uninit_protocol(gtalk_protocol);
    +
    jabber_uninit_protocol(xmpp_protocol);
    - if (!purple_protocols_remove(gtalk_protocol, error))
    - return FALSE;
    -
    if (!purple_protocols_remove(xmpp_protocol, error))
    return FALSE;
    --- a/libpurple/protocols/jabber/jabber.h Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/jabber.h Sat Jan 23 20:31:28 2021 -0600
    @@ -37,12 +37,6 @@
    JABBER_CAP_IQ_SEARCH = 1 << 7,
    JABBER_CAP_IQ_REGISTER = 1 << 8,
    - /* Google Talk extensions:
    - * https://developers.google.com/talk/jep_extensions/extensions
    - */
    - JABBER_CAP_GMAIL_NOTIFY = 1 << 9,
    - JABBER_CAP_GOOGLE_ROSTER = 1 << 10,
    -
    JABBER_CAP_PING = 1 << 11,
    JABBER_CAP_ADHOC = 1 << 12,
    JABBER_CAP_BLOCKING = 1 << 13,
    @@ -207,12 +201,8 @@
    gboolean reinit;
    JabberCapabilities server_caps;
    - gboolean googletalk;
    char *server_name;
    - char *gmail_last_time;
    - char *gmail_last_tid;
    -
    char *serverFQDN;
    #ifdef HAVE_CYRUS_SASL
    @@ -234,8 +224,6 @@
    void *unregistration_user_data;
    gboolean vcard_fetched;
    - /* Timer at login to push updated avatar */
    - guint vcard_timer;
    /* Entity Capabilities hash */
    char *caps_hash;
    @@ -281,10 +269,6 @@
    /* maybe this should only be present when USE_VV? */
    gchar *stun_ip;
    int stun_port;
    -
    - /* stuff for Google's relay handling */
    - gchar *google_relay_token;
    - gchar *google_relay_host;
    };
    typedef gboolean (JabberFeatureEnabled)(JabberStream *js, const gchar *namespace);
    --- a/libpurple/protocols/jabber/jingle/jingle.c Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/jingle/jingle.c Sat Jan 23 20:31:28 2021 -0600
    @@ -27,7 +27,6 @@
    #include "content.h"
    #include "jingle.h"
    -#include "google/google_p2p.h"
    #include "session.h"
    #include "iceudp.h"
    #include "rawudp.h"
    @@ -51,8 +50,6 @@
    #ifdef USE_VV
    else if (purple_strequal(type, JINGLE_APP_RTP))
    return JINGLE_TYPE_RTP;
    - else if (!strcmp(type, NS_GOOGLE_TRANSPORT_P2P))
    - return JINGLE_TYPE_GOOGLE_P2P;
    #endif
    else
    return G_TYPE_NONE;
    @@ -479,13 +476,13 @@
    if (has_account_stun) {
    purple_debug_info("jabber",
    - "setting param stun-ip for stream using Google auto-config: %s\n",
    + "setting param stun-ip for stream using auto-config: %s\n",
    js->stun_ip);
    params[next_index].name = "stun-ip";
    g_value_init(&params[next_index].value, G_TYPE_STRING);
    g_value_set_string(&params[next_index].value, js->stun_ip);
    purple_debug_info("jabber",
    - "setting param stun-port for stream using Google auto-config: %d\n",
    + "setting param stun-port for stream using auto-config: %d\n",
    js->stun_port);
    next_index++;
    params[next_index].name = "stun-port";
    --- a/libpurple/protocols/jabber/jingle/jingle.h Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/jingle/jingle.h Sat Jan 23 20:31:28 2021 -0600
    @@ -75,8 +75,7 @@
    void jingle_terminate_sessions(JabberStream *js);
    #ifdef USE_VV
    -/* create a GParam array given autoconfigured STUN (and later perhaps TURN).
    - if google_talk is TRUE, set compatability mode to GOOGLE_TALK */
    +/* create a GParam array given autoconfigured STUN (and later perhaps TURN). */
    G_GNUC_BEGIN_IGNORE_DEPRECATIONS
    GParameter *jingle_get_params(JabberStream *js, const gchar *relay_ip,
    guint relay_udp, guint relay_tcp, guint relay_ssltcp,
    --- a/libpurple/protocols/jabber/jingle/rtp.c Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/jingle/rtp.c Sat Jan 23 20:31:28 2021 -0600
    @@ -32,7 +32,6 @@
    #include "jabber.h"
    #include "jingle.h"
    -#include "google/google_p2p.h"
    #include "iceudp.h"
    #include "rawudp.h"
    #include "rtp.h"
    @@ -342,8 +341,6 @@
    transmitter = "rawudp";
    else if (JINGLE_IS_ICEUDP(transport))
    transmitter = "nice";
    - else if (JINGLE_IS_GOOGLE_P2P(transport))
    - transmitter = "nice";
    else
    transmitter = "notransmitter";
    g_object_unref(transport);
    @@ -865,8 +862,6 @@
    transport_type = JINGLE_TRANSPORT_ICEUDP;
    } else if (jabber_resource_has_capability(jbr, JINGLE_TRANSPORT_RAWUDP)) {
    transport_type = JINGLE_TRANSPORT_RAWUDP;
    - } else if (jabber_resource_has_capability(jbr, NS_GOOGLE_TRANSPORT_P2P)) {
    - transport_type = NS_GOOGLE_TRANSPORT_P2P;
    } else {
    purple_debug_error("jingle-rtp", "Resource doesn't support "
    "the same transport types\n");
    --- a/libpurple/protocols/jabber/meson.build Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/meson.build Sat Jan 23 20:31:28 2021 -0600
    @@ -25,22 +25,6 @@
    'data.h',
    'disco.c',
    'disco.h',
    - 'google/google.c',
    - 'google/google.h',
    - 'google/google_p2p.c',
    - 'google/google_p2p.h',
    - 'google/google_presence.c',
    - 'google/google_presence.h',
    - 'google/google_roster.c',
    - 'google/google_roster.h',
    - 'google/google_session.c',
    - 'google/google_session.h',
    - 'google/jingleinfo.c',
    - 'google/jingleinfo.h',
    - 'google/relay.c',
    - 'google/relay.h',
    - 'gtalk.c',
    - 'gtalk.h',
    'ibb.c',
    'ibb.h',
    'iq.c',
    --- a/libpurple/protocols/jabber/message.c Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/message.c Sat Jan 23 20:31:28 2021 -0600
    @@ -28,7 +28,6 @@
    #include "buddy.h"
    #include "chat.h"
    #include "data.h"
    -#include "google/google.h"
    #include "message.h"
    #include "pep.h"
    #include "iq.h"
    @@ -163,12 +162,6 @@
    purple_serv_got_typing_stopped(gc, contact);
    }
    - if (jm->js->googletalk && jm->body && jm->xhtml == NULL) {
    - char *tmp = jm->body;
    - jm->body = jabber_google_format_to_html(jm->body);
    - g_free(tmp);
    - }
    -
    body = jm_body_with_oob(jm);
    if(body && body->len) {
    --- a/libpurple/protocols/jabber/namespaces.h Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/namespaces.h Sat Jan 23 20:31:28 2021 -0600
    @@ -104,22 +104,6 @@
    /* XEP-0297 Stanza Forwarding */
    #define NS_FORWARD "urn:xmpp:forward:0"
    -/* Google extensions */
    -#define NS_GOOGLE_CAMERA "http://www.google.com/xmpp/protocol/camera/v1"
    -#define NS_GOOGLE_VIDEO "http://www.google.com/xmpp/protocol/video/v1"
    -#define NS_GOOGLE_VOICE "http://www.google.com/xmpp/protocol/voice/v1"
    -#define NS_GOOGLE_JINGLE_INFO "google:jingleinfo"
    -
    -#define NS_GOOGLE_MAIL_NOTIFY "google:mail:notify"
    -#define NS_GOOGLE_ROSTER "google:roster"
    -
    -#define NS_GOOGLE_PROTOCOL_SESSION "http://www.google.com/xmpp/protocol/session"
    -#define NS_GOOGLE_SESSION "http://www.google.com/session"
    -#define NS_GOOGLE_SESSION_PHONE "http://www.google.com/session/phone"
    -#define NS_GOOGLE_SESSION_VIDEO "http://www.google.com/session/video"
    -
    -#define NS_GOOGLE_TRANSPORT_P2P "http://www.google.com/transport/p2p"
    -
    /* Apple extension(s) */
    #define NS_APPLE_IDLE "http://www.apple.com/xmpp/idle"
    --- a/libpurple/protocols/jabber/presence.c Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/presence.c Sat Jan 23 20:31:28 2021 -0600
    @@ -26,8 +26,6 @@
    #include "buddy.h"
    #include "chat.h"
    -#include "google/google.h"
    -#include "google/google_presence.h"
    #include "presence.h"
    #include "iq.h"
    #include "jutil.h"
    @@ -201,11 +199,6 @@
    allowBuzz = purple_status_get_attr_boolean(status,"buzz");
    /* changing the buzz state has to trigger a re-broadcasting of the presence for caps */
    - tune = purple_presence_get_status(p, "tune");
    - if (js->googletalk && !stripped && purple_status_is_active(tune)) {
    - stripped = jabber_google_presence_outgoing(tune);
    - }
    -
    /* check if there are any differences to the <presence> and send them in that case */
    if (force || allowBuzz != js->allowBuzz || js->old_state != state ||
    !purple_strequal(js->old_msg, stripped) || js->old_priority != priority ||
    @@ -248,6 +241,7 @@
    g_free(stripped);
    /* next, check if there are any changes to the tune values */
    + tune = purple_presence_get_status(p, "tune");
    if (purple_status_is_active(tune)) {
    artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST);
    title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE);
    @@ -294,9 +288,6 @@
    {
    PurpleXmlNode *show, *status, *presence, *pri, *c;
    const char *show_string = NULL;
    -#ifdef USE_VV
    - gboolean audio_enabled, video_enabled;
    -#endif
    g_return_val_if_fail(js !=NULL, NULL);
    @@ -346,28 +337,6 @@
    purple_xmlnode_set_attrib(c, "hash", "sha-1");
    purple_xmlnode_set_attrib(c, "ver", jabber_caps_get_own_hash(js));
    -#ifdef USE_VV
    - /*
    - * MASSIVE HUGE DISGUSTING HACK
    - * This is a huge hack. As far as I can tell, Google Talk's gmail client
    - * doesn't bother to check the actual features we advertise; they
    - * just assume that if we specify a 'voice-v1' ext (ignoring that
    - * these are to be assigned no semantic value), we support receiving voice
    - * calls.
    - *
    - * Ditto for 'video-v1'.
    - */
    - audio_enabled = jabber_audio_enabled(js, NULL /* unused */);
    - video_enabled = jabber_video_enabled(js, NULL /* unused */);
    -
    - if (audio_enabled && video_enabled)
    - purple_xmlnode_set_attrib(c, "ext", "voice-v1 camera-v1 video-v1");
    - else if (audio_enabled)
    - purple_xmlnode_set_attrib(c, "ext", "voice-v1");
    - else if (video_enabled)
    - purple_xmlnode_set_attrib(c, "ext", "camera-v1 video-v1");
    -#endif
    -
    return presence;
    }
    @@ -864,7 +833,6 @@
    jbr = jabber_buddy_find_resource(presence->jb, NULL);
    if (jbr) {
    - jabber_google_presence_incoming(js, buddy_name, jbr);
    purple_protocol_got_user_status(account, buddy_name,
    jabber_buddy_state_get_status_id(jbr->state),
    "priority", jbr->priority,
    --- a/libpurple/protocols/jabber/roster.c Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/roster.c Sat Jan 23 20:31:28 2021 -0600
    @@ -24,8 +24,6 @@
    #include "buddy.h"
    #include "chat.h"
    -#include "google/google.h"
    -#include "google/google_roster.h"
    #include "presence.h"
    #include "roster.h"
    #include "iq.h"
    @@ -75,15 +73,8 @@
    void jabber_roster_request(JabberStream *js)
    {
    JabberIq *iq;
    - PurpleXmlNode *query;
    iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:roster");
    - query = purple_xmlnode_get_child(iq->node, "query");
    -
    - if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) {
    - purple_xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER);
    - purple_xmlnode_set_attrib(query, "gr:ext", "2");
    - }
    jabber_iq_set_callback(iq, roster_request_cb, NULL);
    jabber_iq_send(iq);
    @@ -245,10 +236,6 @@
    } else {
    GSList *groups = NULL;
    - if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER)
    - if (!jabber_google_roster_incoming(js, item))
    - continue;
    -
    for(group = purple_xmlnode_get_child(item, "group"); group; group = purple_xmlnode_get_next_twin(group)) {
    char *group_name = purple_xmlnode_get_data(group);
    @@ -343,11 +330,6 @@
    g_slist_free(groups);
    - if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) {
    - jabber_google_roster_outgoing(js, query, item);
    - purple_xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER);
    - purple_xmlnode_set_attrib(query, "gr:ext", "2");
    - }
    jabber_iq_send(iq);
    }
    --- a/libpurple/protocols/jabber/tests/test_jabber_caps.c Sat Jan 23 20:28:06 2021 -0600
    +++ b/libpurple/protocols/jabber/tests/test_jabber_caps.c Sat Jan 23 20:31:28 2021 -0600
    @@ -39,8 +39,8 @@
    test_jabber_caps_calculate_from_xmlnode(void) {
    _test_jabber_caps_match(
    G_CHECKSUM_SHA1,
    - "<query xmlns='http://jabber.org/protocol/disco#info' node='http://tkabber.jabber.ru/#GNjxthSckUNvAIoCCJFttjl6VL8='><identity category='client' type='pc' name='Tkabber'/><x xmlns='jabber:x:data' type='result'><field var='FORM_TYPE' type='hidden'><value>urn:xmpp:dataforms:softwareinfo</value></field><field var='software'><value>Tkabber</value></field><field var='software_version'><value> ( 8.5.5 )</value></field><field var='os'><value>ATmega640-16AU</value></field><field var='os_version'><value/></field></x><feature var='games:board'/><feature var='google:mail:notify'/><feature var='http://jabber.org/protocol/activity'/><feature var='http://jabber.org/protocol/bytestreams'/><feature var='http://jabber.org/protocol/chatstates'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/disco#info'/><feature var='http://jabber.org/protocol/disco#items'/><feature var='http://jabber.org/protocol/feature-neg'/><feature var='http://jabber.org/protocol/geoloc'/><feature var='http://jabber.org/protocol/ibb'/><feature var='http://jabber.org/protocol/iqibb'/><feature var='http://jabber.org/protocol/mood'/><feature var='http://jabber.org/protocol/muc'/><feature var='http://jabber.org/protocol/mute#ancestor'/><feature var='http://jabber.org/protocol/mute#editor'/><feature var='http://jabber.org/protocol/rosterx'/><feature var='http://jabber.org/protocol/si'/><feature var='http://jabber.org/protocol/si/profile/file-transfer'/><feature var='http://jabber.org/protocol/tune'/><feature var='jabber:iq:avatar'/><feature var='jabber:iq:browse'/><feature var='jabber:iq:dtcp'/><feature var='jabber:iq:filexfer'/><feature var='jabber:iq:ibb'/><feature var='jabber:iq:inband'/><feature var='jabber:iq:jidlink'/><feature var='jabber:iq:last'/><feature var='jabber:iq:oob'/><feature var='jabber:iq:privacy'/><feature var='jabber:iq:time'/><feature var='jabber:iq:version'/><feature var='jabber:x:data'/><feature var='jabber:x:event'/><feature var='jabber:x:oob'/><feature var='urn:xmpp:ping'/><feature var='urn:xmpp:receipts'/><feature var='urn:xmpp:time'/></query>",
    - "GNjxthSckUNvAIoCCJFttjl6VL8="
    + "<query xmlns='http://jabber.org/protocol/disco#info' node='http://tkabber.jabber.ru/#GNjxthSckUNvAIoCCJFttjl6VL8='><identity category='client' type='pc' name='Tkabber'/><x xmlns='jabber:x:data' type='result'><field var='FORM_TYPE' type='hidden'><value>urn:xmpp:dataforms:softwareinfo</value></field><field var='software'><value>Tkabber</value></field><field var='software_version'><value> ( 8.5.5 )</value></field><field var='os'><value>ATmega640-16AU</value></field><field var='os_version'><value/></field></x><feature var='games:board'/><feature var='http://jabber.org/protocol/activity'/><feature var='http://jabber.org/protocol/bytestreams'/><feature var='http://jabber.org/protocol/chatstates'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/disco#info'/><feature var='http://jabber.org/protocol/disco#items'/><feature var='http://jabber.org/protocol/feature-neg'/><feature var='http://jabber.org/protocol/geoloc'/><feature var='http://jabber.org/protocol/ibb'/><feature var='http://jabber.org/protocol/iqibb'/><feature var='http://jabber.org/protocol/mood'/><feature var='http://jabber.org/protocol/muc'/><feature var='http://jabber.org/protocol/mute#ancestor'/><feature var='http://jabber.org/protocol/mute#editor'/><feature var='http://jabber.org/protocol/rosterx'/><feature var='http://jabber.org/protocol/si'/><feature var='http://jabber.org/protocol/si/profile/file-transfer'/><feature var='http://jabber.org/protocol/tune'/><feature var='jabber:iq:avatar'/><feature var='jabber:iq:browse'/><feature var='jabber:iq:dtcp'/><feature var='jabber:iq:filexfer'/><feature var='jabber:iq:ibb'/><feature var='jabber:iq:inband'/><feature var='jabber:iq:jidlink'/><feature var='jabber:iq:last'/><feature var='jabber:iq:oob'/><feature var='jabber:iq:privacy'/><feature var='jabber:iq:time'/><feature var='jabber:iq:version'/><feature var='jabber:x:data'/><feature var='jabber:x:event'/><feature var='jabber:x:oob'/><feature var='urn:xmpp:ping'/><feature var='urn:xmpp:receipts'/><feature var='urn:xmpp:time'/></query>",
    + "3V9tfR8fPykyks72jvg+bkUtQTM="
    );
    }
    --- a/po/POTFILES.in Sat Jan 23 20:28:06 2021 -0600
    +++ b/po/POTFILES.in Sat Jan 23 20:31:28 2021 -0600
    @@ -142,14 +142,6 @@
    libpurple/protocols/jabber/chat.c
    libpurple/protocols/jabber/data.c
    libpurple/protocols/jabber/disco.c
    -libpurple/protocols/jabber/google/google.c
    -libpurple/protocols/jabber/google/google_p2p.c
    -libpurple/protocols/jabber/google/google_presence.c
    -libpurple/protocols/jabber/google/google_roster.c
    -libpurple/protocols/jabber/google/google_session.c
    -libpurple/protocols/jabber/google/jingleinfo.c
    -libpurple/protocols/jabber/google/relay.c
    -libpurple/protocols/jabber/gtalk.c
    libpurple/protocols/jabber/ibb.c
    libpurple/protocols/jabber/iq.c
    libpurple/protocols/jabber/jabber.c