pidgin/pidgin

53a26c29d26c
Parents f84f2b4ef0e5
Children 55f4486bf6bc
Move the PurpleProtocolServer interface to its own file.

Testing Done:
Compiled and ran locally. Connected with bonjour and xmpp without issues.

Bugs closed: PIDGIN-17458

Reviewed at https://reviews.imfreedom.org/r/418/
  • +7 -1
    ChangeLog.API
  • +1 -0
    doc/reference/libpurple/libpurple-docs.xml
  • +25 -117
    libpurple/account.c
  • +0 -39
    libpurple/account.h
  • +5 -2
    libpurple/buddyicon.c
  • +12 -7
    libpurple/connection.c
  • +4 -1
    libpurple/group.c
  • +2 -0
    libpurple/meson.build
  • +0 -193
    libpurple/protocol.c
  • +0 -236
    libpurple/protocol.h
  • +5 -2
    libpurple/protocols.c
  • +21 -8
    libpurple/protocols/bonjour/bonjour.c
  • +4 -3
    libpurple/protocols/facebook/facebook.c
  • +2 -1
    libpurple/protocols/gg/avatar.c
  • +1 -1
    libpurple/protocols/gg/avatar.h
  • +10 -7
    libpurple/protocols/gg/gg.c
  • +3 -2
    libpurple/protocols/gg/pubdir-prpl.c
  • +1 -1
    libpurple/protocols/gg/pubdir-prpl.h
  • +20 -10
    libpurple/protocols/gg/roster.c
  • +5 -5
    libpurple/protocols/gg/roster.h
  • +4 -2
    libpurple/protocols/gg/status.c
  • +1 -1
    libpurple/protocols/gg/status.h
  • +17 -7
    libpurple/protocols/irc/irc.c
  • +1 -1
    libpurple/protocols/irc/msgs.c
  • +15 -8
    libpurple/protocols/jabber/buddy.c
  • +3 -3
    libpurple/protocols/jabber/buddy.h
  • +30 -17
    libpurple/protocols/jabber/jabber.c
  • +6 -6
    libpurple/protocols/jabber/jabber.h
  • +3 -1
    libpurple/protocols/jabber/presence.c
  • +1 -1
    libpurple/protocols/jabber/presence.h
  • +26 -10
    libpurple/protocols/jabber/roster.c
  • +8 -8
    libpurple/protocols/jabber/roster.h
  • +21 -13
    libpurple/protocols/novell/novell.c
  • +63 -28
    libpurple/protocols/null/nullprpl.c
  • +50 -31
    libpurple/protocols/sametime/sametime.c
  • +8 -3
    libpurple/protocols/zephyr/zephyr.c
  • +4 -2
    libpurple/purpleaccountpresence.c
  • +377 -0
    libpurple/purpleprotocolserver.c
  • +414 -0
    libpurple/purpleprotocolserver.h
  • +14 -9
    libpurple/server.c
  • +4 -2
    pidgin/plugins/xmppconsole/xmppconsole.c
  • +1 -0
    po/POTFILES.in
  • --- a/ChangeLog.API Thu Jan 14 21:20:10 2021 -0600
    +++ b/ChangeLog.API Thu Jan 14 22:33:49 2021 -0600
    @@ -329,10 +329,12 @@
    * purple_account_get_check_mail
    * purple_account_get_password. Use
    purple_credential_manager_read_password_async instead.
    + * purple_account_get_public_alias
    * purple_account_set_check_mail
    + * purple_account_set_current_error
    * purple_account_set_password. Use
    purple_credential_manager_write_password_async instead.
    - * purple_account_set_current_error
    + * purple_account_set_public_alias
    * purple_base16_*
    * purple_base64_*. Use g_base64_* instead
    * purple_blist_get_ui_data
    @@ -376,6 +378,8 @@
    yourself. See GLib Main Event Loop docs.
    * purple_fd_get_ip. Use GSocket instead.
    * purple_find_pounce
    + * PurpleGetPublicAliasSuccessCallback
    + * PurpleGetPublicAliasFailureCallback
    * purple_get_host_name. Use g_get_host_name, instead.
    * purple_get_tzoff_str(). Use g_date_time_format, instead.
    * purple_ip_address_is_valid, purple_ipv4_address_is_valid, and
    @@ -494,6 +498,8 @@
    * purple_restore_default_signal_handlers
    * purple_request_certificate
    * purple_request_field_list_add
    + * PurpleSetPublicAliasFailureCallback
    + * PurpleSetPublicAliasSuccessCallback
    * purple_socket_get_family
    * purple_socket_speaks_ipv4
    * PurpleSoundUiOps
    --- a/doc/reference/libpurple/libpurple-docs.xml Thu Jan 14 21:20:10 2021 -0600
    +++ b/doc/reference/libpurple/libpurple-docs.xml Thu Jan 14 22:33:49 2021 -0600
    @@ -80,6 +80,7 @@
    <xi:include href="xml/purpleprotocolim.xml" />
    <xi:include href="xml/purpleprotocolmedia.xml" />
    <xi:include href="xml/purpleprotocolprivacy.xml" />
    + <xi:include href="xml/purpleprotocolserver.xml" />
    <xi:include href="xml/purplewhiteboard.xml" />
    <xi:include href="xml/purplewhiteboardops.xml" />
    <xi:include href="xml/purplewhiteboarduiops.xml" />
    --- a/libpurple/account.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/account.c Thu Jan 14 22:33:49 2021 -0600
    @@ -33,6 +33,7 @@
    #include "purplecredentialmanager.h"
    #include "purpleprivate.h"
    #include "purpleprotocolclient.h"
    +#include "purpleprotocolserver.h"
    #include "request.h"
    #include "server.h"
    #include "signals.h"
    @@ -428,42 +429,6 @@
    purple_serv_set_info(gc, user_info);
    }
    -struct public_alias_closure
    -{
    - PurpleAccount *account;
    - gpointer failure_cb;
    -};
    -
    -static gboolean
    -set_public_alias_unsupported(gpointer data)
    -{
    - struct public_alias_closure *closure = data;
    - PurpleSetPublicAliasFailureCallback failure_cb = closure->failure_cb;
    -
    - failure_cb(closure->account,
    - _("This protocol does not support setting a public alias."));
    -
    - g_object_unref(closure->account);
    - g_free(closure);
    -
    - return FALSE;
    -}
    -
    -static gboolean
    -get_public_alias_unsupported(gpointer data)
    -{
    - struct public_alias_closure *closure = data;
    - PurpleGetPublicAliasFailureCallback failure_cb = closure->failure_cb;
    -
    - failure_cb(closure->account,
    - _("This protocol does not support fetching the public alias."));
    -
    - g_object_unref(closure->account);
    - g_free(closure);
    -
    - return FALSE;
    -}
    -
    static void
    delete_setting(void *data)
    {
    @@ -1842,56 +1807,6 @@
    purple_accounts_schedule_save();
    }
    -void
    -purple_account_set_public_alias(PurpleAccount *account,
    - const char *alias, PurpleSetPublicAliasSuccessCallback success_cb,
    - PurpleSetPublicAliasFailureCallback failure_cb)
    -{
    - PurpleConnection *gc;
    - PurpleProtocol *protocol = NULL;
    -
    - g_return_if_fail(PURPLE_IS_ACCOUNT(account));
    - g_return_if_fail(purple_account_is_connected(account));
    -
    - gc = purple_account_get_connection(account);
    - protocol = purple_connection_get_protocol(gc);
    -
    - if (PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER, set_public_alias))
    - purple_protocol_server_iface_set_public_alias(protocol, gc, alias, success_cb, failure_cb);
    - else if (failure_cb) {
    - struct public_alias_closure *closure =
    - g_new0(struct public_alias_closure, 1);
    - closure->account = g_object_ref(account);
    - closure->failure_cb = failure_cb;
    - g_timeout_add(0, set_public_alias_unsupported, closure);
    - }
    -}
    -
    -void
    -purple_account_get_public_alias(PurpleAccount *account,
    - PurpleGetPublicAliasSuccessCallback success_cb,
    - PurpleGetPublicAliasFailureCallback failure_cb)
    -{
    - PurpleConnection *gc;
    - PurpleProtocol *protocol = NULL;
    -
    - g_return_if_fail(PURPLE_IS_ACCOUNT(account));
    - g_return_if_fail(purple_account_is_connected(account));
    -
    - gc = purple_account_get_connection(account);
    - protocol = purple_connection_get_protocol(gc);
    -
    - if (PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER, get_public_alias))
    - purple_protocol_server_iface_get_public_alias(protocol, gc, success_cb, failure_cb);
    - else if (failure_cb) {
    - struct public_alias_closure *closure =
    - g_new0(struct public_alias_closure, 1);
    - closure->account = g_object_ref(account);
    - closure->failure_cb = failure_cb;
    - g_timeout_add(0, get_public_alias_unsupported, closure);
    - }
    -}
    -
    gboolean
    purple_account_get_silence_suppression(PurpleAccount *account)
    {
    @@ -2858,9 +2773,12 @@
    if (gc != NULL)
    protocol = purple_connection_get_protocol(gc);
    - if (protocol != NULL)
    - purple_protocol_server_iface_add_buddy(protocol, gc, buddy,
    - purple_buddy_get_group(buddy), message);
    + if(PURPLE_IS_PROTOCOL_SERVER(protocol)) {
    + PurpleGroup *group = purple_buddy_get_group(buddy);
    +
    + purple_protocol_server_add_buddy(PURPLE_PROTOCOL_SERVER(protocol), gc,
    + buddy, group, message);
    + }
    }
    void
    @@ -2881,16 +2799,9 @@
    groups = g_list_append(groups, purple_buddy_get_group(buddy));
    }
    - if (PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER, add_buddies))
    - purple_protocol_server_iface_add_buddies(protocol, gc, buddies, groups, message);
    - else if (PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER, add_buddy)) {
    - GList *curb = buddies, *curg = groups;
    -
    - while ((curb != NULL) && (curg != NULL)) {
    - purple_protocol_server_iface_add_buddy(protocol, gc, curb->data, curg->data, message);
    - curb = curb->next;
    - curg = curg->next;
    - }
    + if(PURPLE_IS_PROTOCOL_SERVER(protocol)) {
    + purple_protocol_server_add_buddies(PURPLE_PROTOCOL_SERVER(protocol),
    + gc, buddies, groups, message);
    }
    g_list_free(groups);
    @@ -2907,8 +2818,10 @@
    if (gc != NULL)
    protocol = purple_connection_get_protocol(gc);
    - if (protocol)
    - purple_protocol_server_iface_remove_buddy(protocol, gc, buddy, group);
    + if(PURPLE_IS_PROTOCOL_SERVER(protocol)) {
    + purple_protocol_server_remove_buddy(PURPLE_PROTOCOL_SERVER(protocol),
    + gc, buddy, group);
    + }
    }
    void
    @@ -2920,18 +2833,9 @@
    if (gc != NULL)
    protocol = purple_connection_get_protocol(gc);
    - if (protocol) {
    - if (PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER, remove_buddies))
    - purple_protocol_server_iface_remove_buddies(protocol, gc, buddies, groups);
    - else {
    - GList *curb = buddies;
    - GList *curg = groups;
    - while ((curb != NULL) && (curg != NULL)) {
    - purple_account_remove_buddy(account, curb->data, curg->data);
    - curb = curb->next;
    - curg = curg->next;
    - }
    - }
    + if(PURPLE_IS_PROTOCOL_SERVER(protocol)) {
    + purple_protocol_server_remove_buddies(PURPLE_PROTOCOL_SERVER(protocol),
    + gc, buddies, groups);
    }
    }
    @@ -2944,8 +2848,10 @@
    if (gc != NULL)
    protocol = purple_connection_get_protocol(gc);
    - if (protocol)
    - purple_protocol_server_iface_remove_group(protocol, gc, group);
    + if(PURPLE_IS_PROTOCOL_SERVER(protocol)) {
    + purple_protocol_server_remove_group(PURPLE_PROTOCOL_SERVER(protocol),
    + gc, group);
    + }
    }
    void
    @@ -2966,8 +2872,10 @@
    if (gc != NULL)
    protocol = purple_connection_get_protocol(gc);
    - if (protocol)
    - purple_protocol_server_iface_change_passwd(protocol, gc, orig_pw, new_pw);
    + if(PURPLE_IS_PROTOCOL_SERVER(protocol)) {
    + purple_protocol_server_change_passwd(PURPLE_PROTOCOL_SERVER(protocol),
    + gc, orig_pw, new_pw);
    + }
    }
    gboolean purple_account_supports_offline_message(PurpleAccount *account, PurpleBuddy *buddy)
    --- a/libpurple/account.h Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/account.h Thu Jan 14 22:33:49 2021 -0600
    @@ -53,10 +53,6 @@
    typedef void (*PurpleAccountRequestAuthorizationCb)(const char *response, void *data);
    typedef void (*PurpleAccountRegistrationCb)(PurpleAccount *account, gboolean succeeded, void *user_data);
    typedef void (*PurpleAccountUnregistrationCb)(PurpleAccount *account, gboolean succeeded, void *user_data);
    -typedef void (*PurpleSetPublicAliasSuccessCallback)(PurpleAccount *account, const char *new_alias);
    -typedef void (*PurpleSetPublicAliasFailureCallback)(PurpleAccount *account, const char *error);
    -typedef void (*PurpleGetPublicAliasSuccessCallback)(PurpleAccount *account, const char *alias);
    -typedef void (*PurpleGetPublicAliasFailureCallback)(PurpleAccount *account, const char *error);
    #include "connection.h"
    #include "log.h"
    @@ -462,41 +458,6 @@
    const char *status_id, gboolean active, GHashTable *attrs);
    /**
    - * purple_account_set_public_alias:
    - * @account: The account
    - * @alias: The new public alias for this account or %NULL
    - * to unset the alias/nickname (or return it to
    - * a protocol-specific "default", like the username)
    - * @success_cb: (scope call): A callback which will be called if the alias
    - * is successfully set on the server (or %NULL).
    - * @failure_cb: (scope call): A callback which will be called if the alias
    - * is not successfully set on the server (or %NULL).
    - *
    - * Set a server-side (public) alias for this account. The account
    - * must already be connected.
    - *
    - * Currently, the public alias is not stored locally, although this
    - * may change in a later version.
    - */
    -void purple_account_set_public_alias(PurpleAccount *account,
    - const char *alias, PurpleSetPublicAliasSuccessCallback success_cb,
    - PurpleSetPublicAliasFailureCallback failure_cb);
    -
    -/**
    - * purple_account_get_public_alias:
    - * @account: The account
    - * @success_cb: (scope call): A callback which will be called with the alias
    - * @failure_cb: (scope call): A callback which will be called if the protocol is
    - * unable to retrieve the server-side alias.
    - *
    - * Fetch the server-side (public) alias for this account. The account
    - * must already be connected.
    - */
    -void purple_account_get_public_alias(PurpleAccount *account,
    - PurpleGetPublicAliasSuccessCallback success_cb,
    - PurpleGetPublicAliasFailureCallback failure_cb);
    -
    -/**
    * purple_account_get_silence_suppression:
    * @account: The account.
    *
    --- a/libpurple/buddyicon.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/buddyicon.c Thu Jan 14 22:33:49 2021 -0600
    @@ -25,6 +25,7 @@
    #include "debug.h"
    #include "image.h"
    #include "purpleprivate.h"
    +#include "purpleprotocolserver.h"
    #include "util.h"
    /* NOTE: Instances of this struct are allocated without zeroing the memory, so
    @@ -757,8 +758,10 @@
    gc = purple_account_get_connection(account);
    protocol = purple_connection_get_protocol(gc);
    - if (protocol)
    - purple_protocol_server_iface_set_buddy_icon(protocol, gc, img);
    + if(PURPLE_IS_PROTOCOL_SERVER(protocol)) {
    + purple_protocol_server_set_buddy_icon(PURPLE_PROTOCOL_SERVER(protocol),
    + gc, img);
    + }
    }
    if (old_img)
    --- a/libpurple/connection.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/connection.c Thu Jan 14 22:33:49 2021 -0600
    @@ -33,6 +33,7 @@
    #include "prefs.h"
    #include "proxy.h"
    #include "purpleprivate.h"
    +#include "purpleprotocolserver.h"
    #include "purpleprotocolfactory.h"
    #include "request.h"
    #include "server.h"
    @@ -125,7 +126,8 @@
    PurpleConnection *gc = data;
    PurpleConnectionPrivate *priv = purple_connection_get_instance_private(gc);
    - purple_protocol_server_iface_keepalive(priv->protocol, gc);
    + purple_protocol_server_keepalive(PURPLE_PROTOCOL_SERVER(priv->protocol),
    + gc);
    return TRUE;
    }
    @@ -140,7 +142,7 @@
    if (on && !priv->keepalive)
    {
    - int interval = purple_protocol_server_iface_get_keepalive_interval(priv->protocol);
    + int interval = purple_protocol_server_get_keepalive_interval(PURPLE_PROTOCOL_SERVER(priv->protocol));
    purple_debug_info("connection", "Activating keepalive to %d seconds.", interval);
    priv->keepalive = g_main_context_find_source_by_id(NULL, g_timeout_add_seconds(interval, send_keepalive, gc));
    }
    @@ -677,7 +679,7 @@
    * it seems unlikely that the implementation will change, we just do that
    * for now as a workaround for this API shortcoming.
    */
    - gint64 seconds_from_now = purple_protocol_server_iface_get_keepalive_interval(priv->protocol);
    + gint64 seconds_from_now = purple_protocol_server_get_keepalive_interval(PURPLE_PROTOCOL_SERVER(priv->protocol));
    g_source_set_ready_time(
    priv->keepalive,
    @@ -1038,7 +1040,8 @@
    priv = purple_connection_get_instance_private(gc);
    priv->wants_to_die = TRUE;
    - purple_protocol_server_iface_register_user(protocol, account);
    + purple_protocol_server_register_user(PURPLE_PROTOCOL_SERVER(protocol),
    + account);
    }
    else
    {
    @@ -1051,7 +1054,7 @@
    void
    _purple_connection_new_unregister(PurpleAccount *account, const char *password,
    - PurpleAccountUnregistrationCb cb, void *user_data)
    + PurpleAccountUnregistrationCb cb, gpointer user_data)
    {
    /* Lots of copy/pasted code to avoid API changes. You might want to integrate that into the previous function when posssible. */
    PurpleConnection *gc;
    @@ -1073,7 +1076,8 @@
    }
    if (!purple_account_is_disconnected(account)) {
    - purple_protocol_server_iface_unregister_user(protocol, account, cb, user_data);
    + purple_protocol_server_unregister_user(PURPLE_PROTOCOL_SERVER(protocol),
    + account, cb, user_data);
    return;
    }
    @@ -1101,7 +1105,8 @@
    purple_debug_info("connection", "Unregistering. gc = %p\n", gc);
    - purple_protocol_server_iface_unregister_user(protocol, account, cb, user_data);
    + purple_protocol_server_unregister_user(PURPLE_PROTOCOL_SERVER(protocol),
    + account, cb, user_data);
    }
    /**************************************************************************
    --- a/libpurple/group.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/group.c Thu Jan 14 22:33:49 2021 -0600
    @@ -24,6 +24,7 @@
    #include "group.h"
    #include "internal.h" /* TODO: we need to kill this */
    #include "purpleprivate.h"
    +#include "purpleprotocolserver.h"
    typedef struct _PurpleGroupPrivate PurpleGroupPrivate;
    @@ -212,7 +213,9 @@
    }
    if(PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER, rename_group)) {
    - purple_protocol_server_iface_rename_group(protocol, gc, old_name, source, buddies);
    + purple_protocol_server_rename_group(PURPLE_PROTOCOL_SERVER(protocol),
    + gc, old_name, source,
    + buddies);
    } else {
    GList *cur, *groups = NULL;
    --- a/libpurple/meson.build Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/meson.build Thu Jan 14 22:33:49 2021 -0600
    @@ -65,6 +65,7 @@
    'purpleprotocolim.c',
    'purpleprotocolmedia.c',
    'purpleprotocolprivacy.c',
    + 'purpleprotocolserver.c',
    'purpleuiinfo.c',
    'purplewhiteboard.c',
    'purplewhiteboarduiops.c',
    @@ -154,6 +155,7 @@
    'purpleprotocolim.h',
    'purpleprotocolmedia.h',
    'purpleprotocolprivacy.h',
    + 'purpleprotocolserver.h',
    'purpleuiinfo.h',
    'purplewhiteboard.h',
    'purplewhiteboardops.h',
    --- a/libpurple/protocol.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocol.c Thu Jan 14 22:33:49 2021 -0600
    @@ -209,196 +209,3 @@
    #undef DEFINE_PROTOCOL_FUNC_WITH_RETURN
    #undef DEFINE_PROTOCOL_FUNC
    -
    -/**************************************************************************
    - * Protocol Server Interface API
    - **************************************************************************/
    -#define DEFINE_PROTOCOL_FUNC(protocol,funcname,...) \
    - PurpleProtocolServerInterface *server_iface = \
    - PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol); \
    - if (server_iface && server_iface->funcname) \
    - server_iface->funcname(__VA_ARGS__);
    -
    -#define DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol,defaultreturn,funcname,...) \
    - PurpleProtocolServerInterface *server_iface = \
    - PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol); \
    - if (server_iface && server_iface->funcname) \
    - return server_iface->funcname(__VA_ARGS__); \
    - else \
    - return defaultreturn;
    -
    -GType
    -purple_protocol_server_iface_get_type(void)
    -{
    - static GType type = 0;
    -
    - if (G_UNLIKELY(type == 0)) {
    - static const GTypeInfo info = {
    - .class_size = sizeof(PurpleProtocolServerInterface),
    - };
    -
    - type = g_type_register_static(G_TYPE_INTERFACE,
    - "PurpleProtocolServerInterface", &info, 0);
    - }
    - return type;
    -}
    -
    -void
    -purple_protocol_server_iface_register_user(PurpleProtocol *protocol,
    - PurpleAccount *account)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, register_user, account);
    -}
    -
    -void
    -purple_protocol_server_iface_unregister_user(PurpleProtocol *protocol,
    - PurpleAccount *account, PurpleAccountUnregistrationCb cb,
    - void *user_data)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, unregister_user, account, cb, user_data);
    -}
    -
    -void
    -purple_protocol_server_iface_set_info(PurpleProtocol *protocol,
    - PurpleConnection *gc, const char *info)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, set_info, gc, info);
    -}
    -
    -void
    -purple_protocol_server_iface_get_info(PurpleProtocol *protocol,
    - PurpleConnection *gc, const char *who)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, get_info, gc, who);
    -}
    -
    -void
    -purple_protocol_server_iface_set_status(PurpleProtocol *protocol,
    - PurpleAccount *account, PurpleStatus *status)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, set_status, account, status);
    -}
    -
    -void
    -purple_protocol_server_iface_set_idle(PurpleProtocol *protocol,
    - PurpleConnection *gc, int idletime)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, set_idle, gc, idletime);
    -}
    -
    -void
    -purple_protocol_server_iface_change_passwd(PurpleProtocol *protocol,
    - PurpleConnection *gc, const char *old_pass, const char *new_pass)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, change_passwd, gc, old_pass, new_pass);
    -}
    -
    -void
    -purple_protocol_server_iface_add_buddy(PurpleProtocol *protocol,
    - PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group,
    - const char *message)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, add_buddy, gc, buddy, group, message);
    -}
    -
    -void
    -purple_protocol_server_iface_add_buddies(PurpleProtocol *protocol,
    - PurpleConnection *gc, GList *buddies, GList *groups,
    - const char *message)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, add_buddies, gc, buddies, groups, message);
    -}
    -
    -void
    -purple_protocol_server_iface_remove_buddy(PurpleProtocol *protocol,
    - PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, remove_buddy, gc, buddy, group);
    -}
    -
    -void
    -purple_protocol_server_iface_remove_buddies(PurpleProtocol *protocol,
    - PurpleConnection *gc, GList *buddies, GList *groups)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, remove_buddies, gc, buddies, groups);
    -}
    -
    -void
    -purple_protocol_server_iface_keepalive(PurpleProtocol *protocol,
    - PurpleConnection *gc)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, keepalive, gc);
    -}
    -
    -int
    -purple_protocol_server_iface_get_keepalive_interval(PurpleProtocol *protocol)
    -{
    - DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, 30, get_keepalive_interval);
    -}
    -
    -void
    -purple_protocol_server_iface_alias_buddy(PurpleProtocol *protocol,
    - PurpleConnection *gc, const char *who, const char *alias)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, alias_buddy, gc, who, alias);
    -}
    -
    -void
    -purple_protocol_server_iface_group_buddy(PurpleProtocol *protocol,
    - PurpleConnection *gc, const char *who, const char *old_group,
    - const char *new_group)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, group_buddy, gc, who, old_group, new_group);
    -}
    -
    -void
    -purple_protocol_server_iface_rename_group(PurpleProtocol *protocol,
    - PurpleConnection *gc, const char *old_name, PurpleGroup *group,
    - GList *moved_buddies)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, rename_group, gc, old_name, group,
    - moved_buddies);
    -}
    -
    -void
    -purple_protocol_server_iface_set_buddy_icon(PurpleProtocol *protocol,
    - PurpleConnection *gc, PurpleImage *img)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, set_buddy_icon, gc, img);
    -}
    -
    -void
    -purple_protocol_server_iface_remove_group(PurpleProtocol *protocol,
    - PurpleConnection *gc, PurpleGroup *group)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, remove_group, gc, group);
    -}
    -
    -int
    -purple_protocol_server_iface_send_raw(PurpleProtocol *protocol,
    - PurpleConnection *gc, const char *buf, int len)
    -{
    - DEFINE_PROTOCOL_FUNC_WITH_RETURN(protocol, 0, send_raw, gc, buf, len);
    -}
    -
    -void
    -purple_protocol_server_iface_set_public_alias(PurpleProtocol *protocol,
    - PurpleConnection *gc, const char *alias,
    - PurpleSetPublicAliasSuccessCallback success_cb,
    - PurpleSetPublicAliasFailureCallback failure_cb)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, set_public_alias, gc, alias, success_cb,
    - failure_cb);
    -}
    -
    -void
    -purple_protocol_server_iface_get_public_alias(PurpleProtocol *protocol,
    - PurpleConnection *gc, PurpleGetPublicAliasSuccessCallback success_cb,
    - PurpleGetPublicAliasFailureCallback failure_cb)
    -{
    - DEFINE_PROTOCOL_FUNC(protocol, get_public_alias, gc, success_cb,
    - failure_cb);
    -}
    -
    -#undef DEFINE_PROTOCOL_FUNC_WITH_RETURN
    -#undef DEFINE_PROTOCOL_FUNC
    --- a/libpurple/protocol.h Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocol.h Thu Jan 14 22:33:49 2021 -0600
    @@ -138,144 +138,6 @@
    void (*_purple_reserved4)(void);
    };
    -#define PURPLE_TYPE_PROTOCOL_SERVER (purple_protocol_server_iface_get_type())
    -
    -typedef struct _PurpleProtocolServerInterface PurpleProtocolServerInterface;
    -
    -/**
    - * PurpleProtocolServerInterface:
    - * @register_user: New user registration
    - * @unregister_user: Remove the user from the server. The account can either be
    - * connected or disconnected. After the removal is finished,
    - * the connection will stay open and has to be closed!
    - * @get_info: Should arrange for purple_notify_userinfo() to be called
    - * with @who's user info.
    - * @add_buddy: Add a buddy to a group on the server.
    - * <sbr/>This protocol function may be called in situations in
    - * which the buddy is already in the specified group. If the
    - * protocol supports authorization and the user is not already
    - * authorized to see the status of @buddy, @add_buddy should
    - * request authorization.
    - * <sbr/>If authorization is required, then use the supplied
    - * invite message.
    - * @keepalive: If implemented, this will be called regularly for this
    - * protocol's active connections. You'd want to do this if you
    - * need to repeatedly send some kind of keepalive packet to
    - * the server to avoid being disconnected. ("Regularly" is
    - * defined to be 30 unless @get_keepalive_interval is
    - * implemented to override it).
    - * <filename>libpurple/connection.c</filename>.)
    - * @get_keepalive_interval: If implemented, this will override the default
    - * keepalive interval.
    - * @alias_buddy: Save/store buddy's alias on server list/roster
    - * @group_buddy: Change a buddy's group on a server list/roster
    - * @rename_group: Rename a group on a server list/roster
    - * @set_buddy_icon: Set the buddy icon for the given connection to @img. The
    - * protocol does <emphasis>NOT</emphasis> own a reference to
    - * @img; if it needs one, it must #g_object_ref(@img)
    - * itself.
    - * @send_raw: For use in plugins that may understand the underlying
    - * protocol
    - * @set_public_alias: Set the user's "friendly name" (or alias or nickname or
    - * whatever term you want to call it) on the server. The
    - * protocol should call @success_cb or @failure_cb
    - * <emphasis>asynchronously</emphasis> (if it knows
    - * immediately that the set will fail, call one of the
    - * callbacks from an idle/0-second timeout) depending on if
    - * the nickname is set successfully. See
    - * purple_account_set_public_alias().
    - * <sbr/>@gc: The connection for which to set an alias
    - * <sbr/>@alias: The new server-side alias/nickname for this
    - * account, or %NULL to unset the
    - * alias/nickname (or return it to a
    - * protocol-specific "default").
    - * <sbr/>@success_cb: Callback to be called if the public
    - * alias is set
    - * <sbr/>@failure_cb: Callback to be called if setting the
    - * public alias fails
    - * @get_public_alias: Retrieve the user's "friendly name" as set on the server.
    - * The protocol should call @success_cb or @failure_cb
    - * <emphasis>asynchronously</emphasis> (even if it knows
    - * immediately that the get will fail, call one of the
    - * callbacks from an idle/0-second timeout) depending on if
    - * the nickname is retrieved. See
    - * purple_account_get_public_alias().
    - * <sbr/>@gc: The connection for which to retireve
    - * the alias
    - * <sbr/>@success_cb: Callback to be called with the
    - * retrieved alias
    - * <sbr/>@failure_cb: Callback to be called if the protocol
    - * is unable to retrieve the alias
    - *
    - * The protocol server interface.
    - *
    - * This interface provides a gateway between purple and the protocol's server.
    - */
    -struct _PurpleProtocolServerInterface
    -{
    - /*< private >*/
    - GTypeInterface parent_iface;
    -
    - /*< public >*/
    - void (*register_user)(PurpleAccount *account);
    -
    - void (*unregister_user)(PurpleAccount *account, PurpleAccountUnregistrationCb cb,
    - void *user_data);
    -
    - void (*set_info)(PurpleConnection *connection, const char *info);
    -
    - void (*get_info)(PurpleConnection *connection, const char *who);
    -
    - void (*set_status)(PurpleAccount *account, PurpleStatus *status);
    -
    - void (*set_idle)(PurpleConnection *connection, int idletime);
    -
    - void (*change_passwd)(PurpleConnection *connection, const char *old_pass,
    - const char *new_pass);
    -
    - void (*add_buddy)(PurpleConnection *pc, PurpleBuddy *buddy,
    - PurpleGroup *group, const char *message);
    -
    - void (*add_buddies)(PurpleConnection *pc, GList *buddies, GList *groups,
    - const char *message);
    -
    - void (*remove_buddy)(PurpleConnection *connection, PurpleBuddy *buddy,
    - PurpleGroup *group);
    -
    - void (*remove_buddies)(PurpleConnection *connection, GList *buddies, GList *groups);
    -
    - void (*keepalive)(PurpleConnection *connection);
    -
    - int (*get_keepalive_interval)(void);
    -
    - void (*alias_buddy)(PurpleConnection *connection, const char *who,
    - const char *alias);
    -
    - void (*group_buddy)(PurpleConnection *connection, const char *who,
    - const char *old_group, const char *new_group);
    -
    - void (*rename_group)(PurpleConnection *connection, const char *old_name,
    - PurpleGroup *group, GList *moved_buddies);
    -
    - void (*set_buddy_icon)(PurpleConnection *connection, PurpleImage *img);
    -
    - void (*remove_group)(PurpleConnection *gc, PurpleGroup *group);
    -
    - int (*send_raw)(PurpleConnection *gc, const char *buf, int len);
    -
    - void (*set_public_alias)(PurpleConnection *gc, const char *alias,
    - PurpleSetPublicAliasSuccessCallback success_cb,
    - PurpleSetPublicAliasFailureCallback failure_cb);
    -
    - void (*get_public_alias)(PurpleConnection *gc,
    - PurpleGetPublicAliasSuccessCallback success_cb,
    - PurpleGetPublicAliasFailureCallback failure_cb);
    -};
    -
    -#define PURPLE_IS_PROTOCOL_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_PROTOCOL_SERVER))
    -#define PURPLE_PROTOCOL_SERVER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE((obj), PURPLE_TYPE_PROTOCOL_SERVER, \
    - PurpleProtocolServerInterface))
    -
    /**
    * PURPLE_PROTOCOL_IMPLEMENTS:
    * @protocol: The protocol in which to check
    @@ -388,104 +250,6 @@
    const char *purple_protocol_class_list_icon(PurpleProtocol *protocol,
    PurpleAccount *account, PurpleBuddy *buddy);
    -/**************************************************************************/
    -/* Protocol Server Interface API */
    -/**************************************************************************/
    -
    -/**
    - * purple_protocol_server_iface_get_type:
    - *
    - * Returns: The #GType for the protocol server interface.
    - */
    -GType purple_protocol_server_iface_get_type(void);
    -
    -void purple_protocol_server_iface_register_user(PurpleProtocol *protocol,
    - PurpleAccount *account);
    -
    -/**
    - * purple_protocol_server_iface_unregister_user:
    - * @cb: (scope call):
    - */
    -void purple_protocol_server_iface_unregister_user(PurpleProtocol *protocol,
    - PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data);
    -
    -void purple_protocol_server_iface_set_info(PurpleProtocol *protocol, PurpleConnection *connection,
    - const char *info);
    -
    -void purple_protocol_server_iface_get_info(PurpleProtocol *protocol, PurpleConnection *connection,
    - const char *who);
    -
    -void purple_protocol_server_iface_set_status(PurpleProtocol *protocol,
    - PurpleAccount *account, PurpleStatus *status);
    -
    -void purple_protocol_server_iface_set_idle(PurpleProtocol *protocol, PurpleConnection *connection,
    - int idletime);
    -
    -void purple_protocol_server_iface_change_passwd(PurpleProtocol *protocol,
    - PurpleConnection *connection, const char *old_pass, const char *new_pass);
    -
    -void purple_protocol_server_iface_add_buddy(PurpleProtocol *protocol,
    - PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group,
    - const char *message);
    -
    -void purple_protocol_server_iface_add_buddies(PurpleProtocol *protocol,
    - PurpleConnection *pc, GList *buddies, GList *groups,
    - const char *message);
    -
    -void purple_protocol_server_iface_remove_buddy(PurpleProtocol *protocol,
    - PurpleConnection *connection, PurpleBuddy *buddy, PurpleGroup *group);
    -
    -void purple_protocol_server_iface_remove_buddies(PurpleProtocol *protocol,
    - PurpleConnection *connection, GList *buddies, GList *groups);
    -
    -void purple_protocol_server_iface_keepalive(PurpleProtocol *protocol,
    - PurpleConnection *connection);
    -
    -int purple_protocol_server_iface_get_keepalive_interval(PurpleProtocol *protocol);
    -
    -void purple_protocol_server_iface_alias_buddy(PurpleProtocol *protocol,
    - PurpleConnection *connection, const char *who, const char *alias);
    -
    -void purple_protocol_server_iface_group_buddy(PurpleProtocol *protocol,
    - PurpleConnection *connection, const char *who, const char *old_group,
    - const char *new_group);
    -
    -void purple_protocol_server_iface_rename_group(PurpleProtocol *protocol,
    - PurpleConnection *connection, const char *old_name, PurpleGroup *group,
    - GList *moved_buddies);
    -
    -void purple_protocol_server_iface_set_buddy_icon(PurpleProtocol *protocol,
    - PurpleConnection *connection, PurpleImage *img);
    -
    -void purple_protocol_server_iface_remove_group(PurpleProtocol *protocol,
    - PurpleConnection *gc, PurpleGroup *group);
    -
    -int purple_protocol_server_iface_send_raw(PurpleProtocol *protocol,
    - PurpleConnection *gc, const char *buf, int len);
    -
    -/**
    - * purple_protocol_server_iface_set_public_alias:
    - * @success_cb: (scope call):
    - * @failure_cb: (scope call):
    - */
    -void purple_protocol_server_iface_set_public_alias(PurpleProtocol *protocol,
    - PurpleConnection *gc, const char *alias,
    - PurpleSetPublicAliasSuccessCallback success_cb,
    - PurpleSetPublicAliasFailureCallback failure_cb);
    -
    -/**
    - * purple_protocol_server_iface_get_public_alias:
    - * @success_cb: (scope call):
    - * @failure_cb: (scope call):
    - */
    -void purple_protocol_server_iface_get_public_alias(PurpleProtocol *protocol,
    - PurpleConnection *gc, PurpleGetPublicAliasSuccessCallback success_cb,
    - PurpleGetPublicAliasFailureCallback failure_cb);
    -
    -/**************************************************************************/
    -/* Protocol Chat Interface API */
    -/**************************************************************************/
    -
    G_END_DECLS
    #endif /* PURPLE_PROTOCOL_H */
    --- a/libpurple/protocols.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols.c Thu Jan 14 22:33:49 2021 -0600
    @@ -33,6 +33,7 @@
    #include "purplecredentialmanager.h"
    #include "purpleprotocolattention.h"
    #include "purpleprotocolmedia.h"
    +#include "purpleprotocolserver.h"
    #include "request.h"
    #include "util.h"
    @@ -311,8 +312,10 @@
    if (protocol == NULL)
    return;
    - if (!purple_account_is_disconnected(account))
    - purple_protocol_server_iface_set_status(protocol, account, new_status);
    + if(!purple_account_is_disconnected(account)) {
    + purple_protocol_server_set_status(PURPLE_PROTOCOL_SERVER(protocol),
    + account, new_status);
    + }
    }
    void
    --- a/libpurple/protocols/bonjour/bonjour.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/bonjour/bonjour.c Thu Jan 14 22:33:49 2021 -0600
    @@ -216,7 +216,8 @@
    }
    static void
    -bonjour_set_status(PurpleAccount *account, PurpleStatus *status)
    +bonjour_set_status(PurpleProtocolServer *protocol_server,
    + PurpleAccount *account, PurpleStatus *status)
    {
    PurpleConnection *gc;
    BonjourData *bd;
    @@ -258,7 +259,10 @@
    * if there is no add_buddy callback.
    */
    static void
    -bonjour_fake_add_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group, const char *message) {
    +bonjour_fake_add_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *pc, PurpleBuddy *buddy,
    + PurpleGroup *group, const gchar *message)
    +{
    purple_debug_error("bonjour", "Buddy '%s' manually added; removing. "
    "Bonjour buddies must be discovered and not manually added.\n",
    purple_buddy_get_name(buddy));
    @@ -270,7 +274,11 @@
    }
    -static void bonjour_remove_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group) {
    +static void
    +bonjour_remove_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *pc, PurpleBuddy *buddy,
    + PurpleGroup *group)
    +{
    BonjourBuddy *bb = purple_buddy_get_protocol_data(buddy);
    if (bb) {
    bonjour_buddy_delete(bb);
    @@ -329,7 +337,8 @@
    }
    static void
    -bonjour_set_buddy_icon(PurpleConnection *conn, PurpleImage *img)
    +bonjour_set_buddy_icon(PurpleProtocolServer *protocol_server,
    + PurpleConnection *conn, PurpleImage *img)
    {
    BonjourData *bd = purple_connection_get_protocol_data(conn);
    bonjour_dns_sd_update_buddy_icon(bd->dns_sd_data);
    @@ -439,18 +448,22 @@
    }
    static void
    -bonjour_group_buddy(PurpleConnection *connection, const char *who, const char *old_group, const char *new_group)
    +bonjour_group_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *connection, const gchar *who,
    + const gchar *old_group, const gchar *new_group)
    {
    PurpleBuddy *buddy = purple_blist_find_buddy(purple_connection_get_account(connection), who);
    bonjour_do_group_change(buddy, new_group);
    -
    }
    static void
    -bonjour_rename_group(PurpleConnection *connection, const char *old_name, PurpleGroup *group, GList *moved_buddies)
    +bonjour_rename_group(PurpleProtocolServer *protocol_server,
    + PurpleConnection *connection,
    + const gchar *old_name, PurpleGroup *group,
    + GList *moved_buddies)
    {
    - const char *new_group;
    + const gchar *new_group;
    new_group = purple_group_get_name(group);
    --- a/libpurple/protocols/facebook/facebook.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/facebook/facebook.c Thu Jan 14 22:33:49 2021 -0600
    @@ -1167,7 +1167,8 @@
    }
    static void
    -fb_server_set_status(PurpleAccount *acct, PurpleStatus *status)
    +fb_server_set_status(PurpleProtocolServer *protocol_server,
    + PurpleAccount *acct, PurpleStatus *status)
    {
    FbApi *api;
    FbData *fata;
    @@ -1584,7 +1585,7 @@
    }
    static void
    -facebook_protocol_server_iface_init(PurpleProtocolServerInterface *iface)
    +facebook_protocol_server_init(PurpleProtocolServerInterface *iface)
    {
    iface->set_status = fb_server_set_status;
    }
    @@ -1621,7 +1622,7 @@
    G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CLIENT,
    facebook_protocol_client_iface_init)
    G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_SERVER,
    - facebook_protocol_server_iface_init)
    + facebook_protocol_server_init)
    G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_IM,
    facebook_protocol_im_iface_init)
    G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CHAT,
    --- a/libpurple/protocols/gg/avatar.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/gg/avatar.c Thu Jan 14 22:33:49 2021 -0600
    @@ -286,7 +286,8 @@
    }
    void
    -ggp_avatar_own_set(PurpleConnection *gc, PurpleImage *img)
    +ggp_avatar_own_set(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + PurpleImage *img)
    {
    ggp_avatar_session_data *avdata;
    --- a/libpurple/protocols/gg/avatar.h Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/gg/avatar.h Thu Jan 14 22:33:49 2021 -0600
    @@ -41,6 +41,6 @@
    void ggp_avatar_buddy_update(PurpleConnection *gc, uin_t uin, time_t timestamp);
    void ggp_avatar_buddy_remove(PurpleConnection *gc, uin_t uin);
    -void ggp_avatar_own_set(PurpleConnection *gc, PurpleImage *img);
    +void ggp_avatar_own_set(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleImage *img);
    #endif /* PURPLE_GG_AVATAR_H */
    --- a/libpurple/protocols/gg/gg.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/gg/gg.c Thu Jan 14 22:33:49 2021 -0600
    @@ -889,7 +889,9 @@
    return 1; /* wait 1 second before another notification */
    }
    -static void ggp_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message)
    +static void
    +ggp_add_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + PurpleBuddy *buddy, PurpleGroup *group, const gchar *message)
    {
    PurpleAccount *account = purple_connection_get_account(gc);
    GGPInfo *info = purple_connection_get_protocol_data(gc);
    @@ -901,21 +903,22 @@
    if (purple_strequal(purple_account_get_username(account), name))
    ggp_status_fake_to_self(gc);
    - ggp_roster_add_buddy(gc, buddy, group, message);
    + ggp_roster_add_buddy(protocol_server, gc, buddy, group, message);
    ggp_pubdir_request_buddy_alias(gc, buddy);
    }
    -static void ggp_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
    - PurpleGroup *group)
    +static void
    +ggp_remove_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + PurpleBuddy *buddy, PurpleGroup *group)
    {
    GGPInfo *info = purple_connection_get_protocol_data(gc);
    gg_remove_notify(info->session, ggp_str_to_uin(purple_buddy_get_name(buddy)));
    - ggp_roster_remove_buddy(gc, buddy, group);
    + ggp_roster_remove_buddy(protocol_server, gc, buddy, group);
    }
    -static void ggp_keepalive(PurpleConnection *gc)
    -{
    +static void
    +ggp_keepalive(PurpleProtocolServer *protocol_server, PurpleConnection *gc) {
    GGPInfo *info = purple_connection_get_protocol_data(gc);
    /* purple_debug_info("gg", "Keeping connection alive....\n"); */
    --- a/libpurple/protocols/gg/pubdir-prpl.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/gg/pubdir-prpl.c Thu Jan 14 22:33:49 2021 -0600
    @@ -406,7 +406,8 @@
    }
    void
    -ggp_pubdir_get_info_protocol(PurpleConnection *gc, const char *name)
    +ggp_pubdir_get_info_protocol(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const gchar *name)
    {
    uin_t uin = ggp_str_to_uin(name);
    uin_t *uin_p = g_new0(uin_t, 1);
    @@ -606,7 +607,7 @@
    static void
    ggp_pubdir_search_results_info(PurpleConnection *gc, GList *row, gpointer _form)
    {
    - ggp_pubdir_get_info_protocol(gc, g_list_nth_data(row, 0));
    + ggp_pubdir_get_info_protocol(NULL, gc, g_list_nth_data(row, 0));
    }
    static void
    --- a/libpurple/protocols/gg/pubdir-prpl.h Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/gg/pubdir-prpl.h Thu Jan 14 22:33:49 2021 -0600
    @@ -62,7 +62,7 @@
    void ggp_pubdir_get_info(PurpleConnection *gc, uin_t uin,
    ggp_pubdir_request_cb cb, void *user_data);
    -void ggp_pubdir_get_info_protocol(PurpleConnection *gc, const char *name);
    +void ggp_pubdir_get_info_protocol(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *name);
    void ggp_pubdir_request_buddy_alias(PurpleConnection *gc, PurpleBuddy *buddy);
    void ggp_pubdir_search(PurpleConnection *gc,
    --- a/libpurple/protocols/gg/roster.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/gg/roster.c Thu Jan 14 22:33:49 2021 -0600
    @@ -341,8 +341,10 @@
    * Libpurple callbacks.
    ******************************************************************************/
    -void ggp_roster_alias_buddy(PurpleConnection *gc, const char *who,
    - const char *alias)
    +void
    +ggp_roster_alias_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const gchar *who,
    + const gchar *alias)
    {
    PurpleBuddy *buddy;
    @@ -360,8 +362,10 @@
    ggp_roster_set_synchronized(gc, buddy, FALSE);
    }
    -void ggp_roster_group_buddy(PurpleConnection *gc, const char *who,
    - const char *old_group, const char *new_group)
    +void
    +ggp_roster_group_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const gchar *who,
    + const gchar *old_group, const gchar *new_group)
    {
    ggp_roster_session_data *rdata = ggp_roster_get_rdata(gc);
    ggp_roster_change *change;
    @@ -382,8 +386,10 @@
    rdata->pending_updates = g_list_append(rdata->pending_updates, change);
    }
    -void ggp_roster_rename_group(PurpleConnection *gc, const char *old_name,
    - PurpleGroup *group, GList *moved_buddies)
    +void
    +ggp_roster_rename_group(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const gchar *old_name,
    + PurpleGroup *group, GList *moved_buddies)
    {
    ggp_roster_session_data *rdata = ggp_roster_get_rdata(gc);
    ggp_roster_change *change;
    @@ -399,8 +405,10 @@
    rdata->pending_updates = g_list_append(rdata->pending_updates, change);
    }
    -void ggp_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
    - PurpleGroup *group, const char *message)
    +void
    +ggp_roster_add_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, PurpleBuddy *buddy,
    + PurpleGroup *group, const gchar *message)
    {
    g_return_if_fail(gc != NULL);
    g_return_if_fail(buddy != NULL);
    @@ -411,8 +419,10 @@
    ggp_roster_set_synchronized(gc, buddy, FALSE);
    }
    -void ggp_roster_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
    - PurpleGroup *group)
    +void
    +ggp_roster_remove_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, PurpleBuddy *buddy,
    + PurpleGroup *group)
    {
    ggp_roster_session_data *rdata = ggp_roster_get_rdata(gc);
    ggp_roster_change *change;
    --- a/libpurple/protocols/gg/roster.h Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/gg/roster.h Thu Jan 14 22:33:49 2021 -0600
    @@ -59,15 +59,15 @@
    struct gg_event_userlist100_version *version);
    /* libpurple callbacks */
    -void ggp_roster_alias_buddy(PurpleConnection *gc, const char *who,
    +void ggp_roster_alias_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *who,
    const char *alias);
    -void ggp_roster_group_buddy(PurpleConnection *gc, const char *who,
    +void ggp_roster_group_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *who,
    const char *old_group, const char *new_group);
    -void ggp_roster_rename_group(PurpleConnection *, const char *old_name,
    +void ggp_roster_rename_group(PurpleProtocolServer *protocol_server, PurpleConnection *, const char *old_name,
    PurpleGroup *group, GList *moved_buddies);
    -void ggp_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
    +void ggp_roster_add_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleBuddy *buddy,
    PurpleGroup *group, const char *message);
    -void ggp_roster_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
    +void ggp_roster_remove_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleBuddy *buddy,
    PurpleGroup *group);
    #endif /* PURPLE_GG_ROSTER_H */
    --- a/libpurple/protocols/gg/status.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/gg/status.c Thu Jan 14 22:33:49 2021 -0600
    @@ -249,7 +249,9 @@
    return TRUE;
    }
    -void ggp_status_set_purplestatus(PurpleAccount *account, PurpleStatus *status)
    +void
    +ggp_status_set_purplestatus(PurpleProtocolServer *protocol_server,
    + PurpleAccount *account, PurpleStatus *status)
    {
    int status_gg;
    gchar *msg = NULL;
    @@ -330,7 +332,7 @@
    ggp_status_get_ssdata(gc)->status_broadcasting = broadcasting;
    purple_account_set_bool(account, "status_broadcasting", broadcasting);
    - ggp_status_set_purplestatus(account,
    + ggp_status_set_purplestatus(NULL, account,
    purple_account_get_active_status(account));
    }
    --- a/libpurple/protocols/gg/status.h Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/gg/status.h Thu Jan 14 22:33:49 2021 -0600
    @@ -48,7 +48,7 @@
    void ggp_status_set_initial(PurpleConnection *gc, struct gg_login_params *glp);
    gboolean ggp_status_set(PurpleAccount *account, int status, const gchar* msg);
    -void ggp_status_set_purplestatus(PurpleAccount *account, PurpleStatus *status);
    +void ggp_status_set_purplestatus(PurpleProtocolServer *protocol_server, PurpleAccount *account, PurpleStatus *status);
    void ggp_status_set_disconnected(PurpleAccount *account);
    void ggp_status_fake_to_self(PurpleConnection *gc);
    --- a/libpurple/protocols/irc/irc.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/irc/irc.c Thu Jan 14 22:33:49 2021 -0600
    @@ -221,7 +221,9 @@
    g_free(body);
    }
    -static int irc_send_raw(PurpleConnection *gc, const char *buf, int len)
    +static int
    +irc_send_raw(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + const gchar *buf, gint len)
    {
    struct irc_conn *irc = purple_connection_get_protocol_data(gc);
    if (len == -1) {
    @@ -644,7 +646,9 @@
    return 1;
    }
    -static void irc_get_info(PurpleConnection *gc, const char *who)
    +static void
    +irc_get_info(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + const gchar *who)
    {
    struct irc_conn *irc = purple_connection_get_protocol_data(gc);
    const char *args[2];
    @@ -653,7 +657,9 @@
    irc_cmd_whois(irc, "whois", NULL, args);
    }
    -static void irc_set_status(PurpleAccount *account, PurpleStatus *status)
    +static void
    +irc_set_status(PurpleProtocolServer *protocol_server, PurpleAccount *account,
    + PurpleStatus *status)
    {
    PurpleConnection *gc = purple_account_get_connection(account);
    struct irc_conn *irc;
    @@ -678,7 +684,9 @@
    }
    }
    -static void irc_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *message)
    +static void
    +irc_add_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + PurpleBuddy *buddy, PurpleGroup *group, const gchar *message)
    {
    struct irc_conn *irc = purple_connection_get_protocol_data(gc);
    struct irc_buddy *ib;
    @@ -703,7 +711,9 @@
    irc_ison_one(irc, ib);
    }
    -static void irc_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
    +static void
    +irc_remove_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + PurpleBuddy *buddy, PurpleGroup *group)
    {
    struct irc_conn *irc = purple_connection_get_protocol_data(gc);
    struct irc_buddy *ib;
    @@ -936,8 +946,8 @@
    }
    }
    -static void irc_keepalive(PurpleConnection *gc)
    -{
    +static void
    +irc_keepalive(PurpleProtocolServer *protocol_server, PurpleConnection *gc) {
    struct irc_conn *irc = purple_connection_get_protocol_data(gc);
    if ((time(NULL) - irc->recv_time) > PING_TIMEOUT)
    irc_cmd_ping(irc, NULL, NULL, NULL);
    --- a/libpurple/protocols/irc/msgs.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/irc/msgs.c Thu Jan 14 22:33:49 2021 -0600
    @@ -104,7 +104,7 @@
    status = purple_account_get_active_status(irc->account);
    if (purple_status_type_get_primitive(purple_status_get_status_type(status)) != PURPLE_STATUS_AVAILABLE) {
    PurpleProtocol *protocol = purple_connection_get_protocol(gc);
    - purple_protocol_server_iface_set_status(protocol, irc->account, status);
    + purple_protocol_server_set_status(PURPLE_PROTOCOL_SERVER(protocol), irc->account, status);
    }
    /* this used to be in the core, but it's not now */
    --- a/libpurple/protocols/jabber/buddy.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/jabber/buddy.c Thu Jan 14 22:33:49 2021 -0600
    @@ -449,7 +449,9 @@
    /*
    * Send vCard info to Jabber server
    */
    -void jabber_set_info(PurpleConnection *gc, const char *info)
    +void
    +jabber_set_info(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + const gchar *info)
    {
    PurpleImage *img;
    JabberIq *iq;
    @@ -546,14 +548,16 @@
    }
    }
    -void jabber_set_buddy_icon(PurpleConnection *gc, PurpleImage *img)
    +void
    +jabber_set_buddy_icon(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, PurpleImage *img)
    {
    PurpleAccount *account = purple_connection_get_account(gc);
    /* Publish the avatar as specified in XEP-0084 */
    jabber_avatar_set(purple_connection_get_protocol_data(gc), img);
    /* Set the image in our vCard */
    - jabber_set_info(gc, purple_account_get_user_info(account));
    + jabber_set_info(NULL, gc, purple_account_get_user_info(account));
    /* TODO: Fake image to ourselves, since a number of servers do not echo
    * back our presence to us. To do this without uselessly copying the data
    @@ -902,7 +906,7 @@
    js->vcard_timer = 0;
    - jabber_set_info(js->gc, purple_account_get_user_info(account));
    + jabber_set_info(NULL, js->gc, purple_account_get_user_info(account));
    return FALSE;
    }
    @@ -962,11 +966,12 @@
    * it returns an error (namespaces trimmed):
    * <error code="500" type="wait"><internal-server-error/></error>.
    */
    - if (js->googletalk)
    + if (js->googletalk) {
    js->vcard_timer = g_timeout_add_seconds(10, set_own_vcard_cb,
    js);
    - else
    - jabber_set_info(js->gc, purple_account_get_user_info(account));
    + } else {
    + 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;
    @@ -1619,7 +1624,9 @@
    jbi->timeout_handle = g_timeout_add_seconds(30, jabber_buddy_get_info_timeout, jbi);
    }
    -void jabber_buddy_get_info(PurpleConnection *gc, const char *who)
    +void
    +jabber_buddy_get_info(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const char *who)
    {
    JabberStream *js = purple_connection_get_protocol_data(gc);
    JabberID *jid = jabber_id_new(who);
    --- a/libpurple/protocols/jabber/buddy.h Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/jabber/buddy.h Thu Jan 14 22:33:49 2021 -0600
    @@ -103,13 +103,13 @@
    JabberBuddyResource *jabber_buddy_track_resource(JabberBuddy *jb, const char *resource,
    int priority, JabberBuddyState state, const char *status);
    void jabber_buddy_remove_resource(JabberBuddy *jb, const char *resource);
    -void jabber_buddy_get_info(PurpleConnection *gc, const char *who);
    +void jabber_buddy_get_info(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *who);
    GList *jabber_blist_node_menu(PurpleProtocolClient *client, PurpleBlistNode *node);
    -void jabber_set_info(PurpleConnection *gc, const char *info);
    +void jabber_set_info(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *info);
    void jabber_setup_set_info(PurpleProtocolAction *action);
    -void jabber_set_buddy_icon(PurpleConnection *gc, PurpleImage *img);
    +void jabber_set_buddy_icon(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleImage *img);
    void jabber_user_search(JabberStream *js, const char *directory);
    void jabber_user_search_begin(PurpleProtocolAction *);
    --- a/libpurple/protocols/jabber/jabber.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/jabber/jabber.c Thu Jan 14 22:33:49 2021 -0600
    @@ -95,7 +95,7 @@
    js->user->domain);
    /* setup the parser fresh for each stream */
    jabber_parser_setup(js);
    - jabber_send_raw(js, open_stream, -1);
    + jabber_send_raw(NULL, js, open_stream, -1);
    js->reinit = FALSE;
    g_free(open_stream);
    }
    @@ -225,7 +225,7 @@
    * We request STARTTLS for standard XMPP connections, but we do nothing for insecure
    * BOSH connections, per XEP-0206. */
    if(!js->bosh) {
    - jabber_send_raw(js,
    + jabber_send_raw(NULL, js,
    "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>", -1);
    return TRUE;
    }
    @@ -408,7 +408,9 @@
    return success;
    }
    -void jabber_send_raw(JabberStream *js, const char *data, int len)
    +void
    +jabber_send_raw(PurpleProtocolServer *protocol_server, JabberStream *js,
    + const gchar *data, gint len)
    {
    PurpleConnection *gc;
    PurpleAccount *account;
    @@ -514,7 +516,9 @@
    do_jabber_send_raw(js, data, len);
    }
    -int jabber_protocol_send_raw(PurpleConnection *gc, const char *buf, int len)
    +gint
    +jabber_protocol_send_raw(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const gchar *buf, gint len)
    {
    JabberStream *js = purple_connection_get_protocol_data(gc);
    @@ -524,7 +528,7 @@
    * to do things during the connection process.
    */
    - jabber_send_raw(js, buf, len);
    + jabber_send_raw(NULL, js, buf, len);
    return (len < 0 ? (int)strlen(buf) : len);
    }
    @@ -551,7 +555,7 @@
    purple_strequal((*packet)->name, "presence"))
    purple_xmlnode_set_namespace(*packet, NS_XMPP_CLIENT);
    txt = purple_xmlnode_to_str(*packet, &len);
    - jabber_send_raw(js, txt, len);
    + jabber_send_raw(NULL, js, txt, len);
    g_free(txt);
    }
    @@ -569,8 +573,8 @@
    return FALSE;
    }
    -void jabber_keepalive(PurpleConnection *gc)
    -{
    +void
    +jabber_keepalive(PurpleProtocolServer *protocol_server, PurpleConnection *gc) {
    JabberStream *js = purple_connection_get_protocol_data(gc);
    if (js->keepalive_timeout == 0) {
    @@ -580,8 +584,8 @@
    }
    }
    -static int jabber_get_keepalive_interval(void)
    -{
    +static int
    +jabber_get_keepalive_interval(PurpleProtocolServer *protocol_server) {
    return PING_TIMEOUT;
    }
    @@ -731,7 +735,7 @@
    g_io_stream_get_output_stream(js->stream));
    if (js->state == JABBER_STREAM_CONNECTING) {
    - jabber_send_raw(js, "<?xml version='1.0' ?>", -1);
    + jabber_send_raw(NULL, js, "<?xml version='1.0' ?>", -1);
    }
    jabber_stream_set_state(js, JABBER_STREAM_INITIALIZING);
    @@ -1512,7 +1516,9 @@
    jabber_iq_send(iq);
    }
    -void jabber_register_account(PurpleAccount *account)
    +void
    +jabber_register_account(PurpleProtocolServer *protocol_server,
    + PurpleAccount *account)
    {
    JabberStream *js;
    @@ -1566,7 +1572,11 @@
    jabber_iq_send(iq);
    }
    -void jabber_unregister_account(PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data) {
    +void
    +jabber_unregister_account(PurpleProtocolServer *protocol_server,
    + PurpleAccount *account,
    + PurpleAccountUnregistrationCb cb, gpointer user_data)
    +{
    PurpleConnection *gc = purple_account_get_connection(account);
    JabberStream *js;
    @@ -1771,7 +1781,9 @@
    }
    -void jabber_idle_set(PurpleConnection *gc, int idle)
    +void
    +jabber_idle_set(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + gint idle)
    {
    JabberStream *js = purple_connection_get_protocol_data(gc);
    @@ -2098,10 +2110,11 @@
    */
    js->inactivity_timer = 0;
    - if (js->bosh)
    + if (js->bosh) {
    jabber_bosh_connection_send_keepalive(js->bosh);
    - else
    - jabber_send_raw(js, "\t", 1);
    + } else {
    + jabber_send_raw(NULL, js, "\t", 1);
    + }
    return FALSE;
    }
    --- a/libpurple/protocols/jabber/jabber.h Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/jabber/jabber.h Thu Jan 14 22:33:49 2021 -0600
    @@ -325,7 +325,7 @@
    void jabber_stream_features_parse(JabberStream *js, PurpleXmlNode *packet);
    void jabber_process_packet(JabberStream *js, PurpleXmlNode **packet);
    void jabber_send(JabberStream *js, PurpleXmlNode *data);
    -void jabber_send_raw(JabberStream *js, const char *data, int len);
    +void jabber_send_raw(PurpleProtocolServer *protocol_server, JabberStream *js, const char *data, int len);
    void jabber_send_signal_cb(PurpleConnection *pc, PurpleXmlNode **packet,
    gpointer unused);
    @@ -404,23 +404,23 @@
    GList *jabber_status_types(PurpleAccount *account);
    void jabber_login(PurpleAccount *account);
    void jabber_close(PurpleConnection *gc);
    -void jabber_idle_set(PurpleConnection *gc, int idle);
    +void jabber_idle_set(PurpleProtocolServer *protocol_server, PurpleConnection *gc, int idle);
    void jabber_blocklist_parse_push(JabberStream *js, const char *from,
    JabberIqType type, const char *id,
    PurpleXmlNode *child);
    void jabber_request_block_list(JabberStream *js);
    void jabber_add_deny(PurpleProtocolPrivacy *privacy, PurpleConnection *gc, const char *who);
    void jabber_remove_deny(PurpleProtocolPrivacy *privacy, PurpleConnection *gc, const char *who);
    -void jabber_keepalive(PurpleConnection *gc);
    +void jabber_keepalive(PurpleProtocolServer *protocol_server, PurpleConnection *gc);
    void jabber_register_gateway(JabberStream *js, const char *gateway);
    -void jabber_register_account(PurpleAccount *account);
    -void jabber_unregister_account(PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data);
    +void jabber_register_account(PurpleProtocolServer *protocol_server, PurpleAccount *account);
    +void jabber_unregister_account(PurpleProtocolServer *protocol_server, PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data);
    gboolean jabber_send_attention(PurpleProtocolAttention *attn, PurpleConnection *gc, const char *username, guint code);
    GList *jabber_attention_types(PurpleProtocolAttention *attn, PurpleAccount *account);
    void jabber_convo_closed(PurpleProtocolClient *client, PurpleConnection *gc, const char *who);
    PurpleChat *jabber_find_blist_chat(PurpleProtocolClient *client, PurpleAccount *account, const char *name);
    gboolean jabber_offline_message(PurpleProtocolClient *client, PurpleBuddy *buddy);
    -int jabber_protocol_send_raw(PurpleConnection *gc, const char *buf, int len);
    +int jabber_protocol_send_raw(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const char *buf, int len);
    GList *jabber_get_actions(PurpleProtocolClient *client, PurpleConnection *gc);
    gboolean jabber_audio_enabled(JabberStream *js, const char *unused);
    --- a/libpurple/protocols/jabber/presence.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/jabber/presence.c Thu Jan 14 22:33:49 2021 -0600
    @@ -140,7 +140,9 @@
    g_free(msg);
    }
    -void jabber_set_status(PurpleAccount *account, PurpleStatus *status)
    +void
    +jabber_set_status(PurpleProtocolServer *protocol_server,
    + PurpleAccount *account, PurpleStatus *status)
    {
    PurpleConnection *gc;
    JabberStream *js;
    --- a/libpurple/protocols/jabber/presence.h Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/jabber/presence.h Thu Jan 14 22:33:49 2021 -0600
    @@ -84,7 +84,7 @@
    void jabber_presence_init(void);
    void jabber_presence_uninit(void);
    -void jabber_set_status(PurpleAccount *account, PurpleStatus *status);
    +void jabber_set_status(PurpleProtocolServer *protocol_server, PurpleAccount *account, PurpleStatus *status);
    /**
    * Send a full presence stanza.
    --- a/libpurple/protocols/jabber/roster.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/jabber/roster.c Thu Jan 14 22:33:49 2021 -0600
    @@ -351,8 +351,10 @@
    jabber_iq_send(iq);
    }
    -void jabber_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
    - PurpleGroup *group, const char *message)
    +void
    +jabber_roster_add_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, PurpleBuddy *buddy,
    + PurpleGroup *group, const gchar *message)
    {
    JabberStream *js = purple_connection_get_protocol_data(gc);
    char *who;
    @@ -415,7 +417,10 @@
    g_free(who);
    }
    -void jabber_roster_alias_change(PurpleConnection *gc, const char *name, const char *alias)
    +void
    +jabber_roster_alias_change(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const gchar *name,
    + const gchar *alias)
    {
    PurpleBuddy *b = purple_blist_find_buddy(purple_connection_get_account(gc), name);
    @@ -429,8 +434,10 @@
    }
    }
    -void jabber_roster_group_change(PurpleConnection *gc, const char *name,
    - const char *old_group, const char *new_group)
    +void
    +jabber_roster_group_change(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const gchar *name,
    + const gchar *old_group, const gchar *new_group)
    {
    GSList *buddies, *groups = NULL;
    @@ -449,19 +456,28 @@
    jabber_roster_update(purple_connection_get_protocol_data(gc), name, groups);
    }
    -void jabber_roster_group_rename(PurpleConnection *gc, const char *old_name,
    - PurpleGroup *group, GList *moved_buddies)
    +void
    +jabber_roster_group_rename(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const gchar *old_name,
    + PurpleGroup *group, GList *moved_buddies)
    {
    GList *l;
    const char *gname = jabber_roster_group_get_global_name(group);
    +
    for(l = moved_buddies; l; l = l->next) {
    PurpleBuddy *buddy = l->data;
    - jabber_roster_group_change(gc, purple_buddy_get_name(buddy), old_name, gname);
    +
    + jabber_roster_group_change(protocol_server, gc,
    + purple_buddy_get_name(buddy), old_name,
    + gname);
    }
    }
    -void jabber_roster_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
    - PurpleGroup *group) {
    +void
    +jabber_roster_remove_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, PurpleBuddy *buddy,
    + PurpleGroup *group)
    +{
    const char *name = purple_buddy_get_name(buddy);
    GSList *buddies = purple_blist_find_buddies(purple_connection_get_account(gc), name);
    --- a/libpurple/protocols/jabber/roster.h Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/jabber/roster.h Thu Jan 14 22:33:49 2021 -0600
    @@ -35,15 +35,15 @@
    void jabber_roster_parse(JabberStream *js, const char *from,
    JabberIqType type, const char *id, PurpleXmlNode *query);
    -void jabber_roster_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
    - PurpleGroup *group, const char *message);
    -void jabber_roster_alias_change(PurpleConnection *gc, const char *name,
    - const char *alias);
    -void jabber_roster_group_change(PurpleConnection *gc, const char *name,
    - const char *old_group, const char *new_group);
    -void jabber_roster_group_rename(PurpleConnection *gc, const char *old_name,
    +void jabber_roster_add_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleBuddy *buddy,
    + PurpleGroup *group, const gchar *message);
    +void jabber_roster_alias_change(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const gchar *name,
    + const gchar *alias);
    +void jabber_roster_group_change(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const gchar *name,
    + const gchar *old_group, const gchar *new_group);
    +void jabber_roster_group_rename(PurpleProtocolServer *protocol_server, PurpleConnection *gc, const gchar *old_name,
    PurpleGroup *group, GList *moved_buddies);
    -void jabber_roster_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
    +void jabber_roster_remove_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc, PurpleBuddy *buddy,
    PurpleGroup *group);
    const gchar *
    --- a/libpurple/protocols/novell/novell.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/novell/novell.c Thu Jan 14 22:33:49 2021 -0600
    @@ -2557,7 +2557,8 @@
    }
    static void
    -novell_add_buddy(PurpleConnection * gc, PurpleBuddy *buddy, PurpleGroup * group, const char *message)
    +novell_add_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + PurpleBuddy *buddy, PurpleGroup * group, const gchar *message)
    {
    NMFolder *folder = NULL;
    NMContact *contact;
    @@ -2620,7 +2621,9 @@
    }
    static void
    -novell_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
    +novell_remove_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, PurpleBuddy *buddy,
    + PurpleGroup *group)
    {
    NMContact *contact;
    NMFolder *folder;
    @@ -2655,7 +2658,8 @@
    }
    static void
    -novell_remove_group(PurpleConnection * gc, PurpleGroup *group)
    +novell_remove_group(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, PurpleGroup *group)
    {
    NMUser *user;
    NMERR_T rc = NM_OK;
    @@ -2676,7 +2680,8 @@
    }
    static void
    -novell_alias_buddy(PurpleConnection * gc, const char *name, const char *alias)
    +novell_alias_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + const gchar *name, const gchar *alias)
    {
    NMContact *contact;
    NMUser *user;
    @@ -2732,9 +2737,9 @@
    }
    static void
    -novell_group_buddy(PurpleConnection * gc,
    - const char *name, const char *old_group_name,
    - const char *new_group_name)
    +novell_group_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const gchar *name,
    + const gchar *old_group_name, const gchar *new_group_name)
    {
    NMFolder *old_folder;
    NMFolder *new_folder;
    @@ -2794,7 +2799,8 @@
    }
    static void
    -novell_rename_group(PurpleConnection * gc, const char *old_name,
    +novell_rename_group(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const gchar *old_name,
    PurpleGroup *group, GList *moved_buddies)
    {
    NMERR_T rc = NM_OK;
    @@ -2894,7 +2900,8 @@
    }
    static void
    -novell_set_idle(PurpleConnection * gc, int time)
    +novell_set_idle(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + gint time)
    {
    NMUser *user;
    NMERR_T rc = NM_OK;
    @@ -2924,7 +2931,8 @@
    }
    static void
    -novell_get_info(PurpleConnection * gc, const char *name)
    +novell_get_info(PurpleProtocolServer *protocol_server, PurpleConnection * gc,
    + const gchar *name)
    {
    NMUserRecord *user_record;
    NMUser *user;
    @@ -3020,7 +3028,8 @@
    }
    static void
    -novell_set_status(PurpleAccount *account, PurpleStatus *status)
    +novell_set_status(PurpleProtocolServer *protocol_server,
    + PurpleAccount *account, PurpleStatus *status)
    {
    PurpleConnection *gc;
    gboolean connected;
    @@ -3477,8 +3486,7 @@
    }
    static void
    -novell_keepalive(PurpleConnection *gc)
    -{
    +novell_keepalive(PurpleProtocolServer *protocol_server, PurpleConnection *gc) {
    NMUser *user;
    NMERR_T rc = NM_OK;
    --- a/libpurple/protocols/null/nullprpl.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/null/nullprpl.c Thu Jan 14 22:33:49 2021 -0600
    @@ -458,7 +458,10 @@
    return 1;
    }
    -static void null_set_info(PurpleConnection *gc, const char *info) {
    +static void
    +null_set_info(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + const gchar *info)
    +{
    purple_debug_info("nullprpl", "setting %s's user info to %s\n",
    purple_account_get_username(purple_connection_get_account(gc)), info);
    }
    @@ -496,7 +499,10 @@
    return 0;
    }
    -static void null_get_info(PurpleConnection *gc, const char *username) {
    +static void
    +null_get_info(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + const gchar *username)
    +{
    const char *body;
    PurpleNotifyUserInfo *info = purple_notify_user_info_new();
    PurpleAccount *acct;
    @@ -529,7 +535,10 @@
    NULL); /* userdata for callback */
    }
    -static void null_set_status(PurpleAccount *acct, PurpleStatus *status) {
    +static void
    +null_set_status(PurpleProtocolServer *protocol_server, PurpleAccount *acct,
    + PurpleStatus *status)
    +{
    const char *msg = purple_status_get_attr_string(status, "message");
    purple_debug_info("nullprpl", "setting %s's status to %s: %s\n",
    purple_account_get_username(acct), purple_status_get_name(status), msg);
    @@ -538,20 +547,26 @@
    NULL);
    }
    -static void null_set_idle(PurpleConnection *gc, int idletime) {
    +static void
    +null_set_idle(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + gint idletime)
    +{
    purple_debug_info("nullprpl",
    "purple reports that %s has been idle for %d seconds\n",
    purple_account_get_username(purple_connection_get_account(gc)), idletime);
    }
    -static void null_change_passwd(PurpleConnection *gc, const char *old_pass,
    - const char *new_pass) {
    +static void
    +null_change_passwd(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + const gchar *old_pass, const gchar *new_pass)
    +{
    purple_debug_info("nullprpl", "%s wants to change their password\n",
    purple_account_get_username(purple_connection_get_account(gc)));
    }
    -static void null_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
    - PurpleGroup *group, const char *message)
    +static void
    +null_add_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + PurpleBuddy *buddy, PurpleGroup *group, const gchar *message)
    {
    const char *username = purple_account_get_username(purple_connection_get_account(gc));
    PurpleConnection *buddy_gc = get_null_gc(purple_buddy_get_name(buddy));
    @@ -579,38 +594,44 @@
    }
    }
    -static void null_add_buddies(PurpleConnection *gc, GList *buddies,
    - GList *groups, const char *message) {
    +static void
    +null_add_buddies(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + GList *buddies, GList *groups, const gchar *message)
    +{
    GList *buddy = buddies;
    GList *group = groups;
    purple_debug_info("nullprpl", "adding multiple buddies\n");
    while (buddy && group) {
    - null_add_buddy(gc, (PurpleBuddy *)buddy->data, (PurpleGroup *)group->data, message);
    + null_add_buddy(protocol_server, gc, PURPLE_BUDDY(buddy->data),
    + PURPLE_GROUP(group->data), message);
    buddy = g_list_next(buddy);
    group = g_list_next(group);
    }
    }
    -static void null_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
    - PurpleGroup *group)
    +static void
    +null_remove_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + PurpleBuddy *buddy, PurpleGroup *group)
    {
    purple_debug_info("nullprpl", "removing %s from %s's buddy list\n",
    purple_buddy_get_name(buddy),
    purple_account_get_username(purple_connection_get_account(gc)));
    }
    -static void null_remove_buddies(PurpleConnection *gc, GList *buddies,
    - GList *groups) {
    +static void
    +null_remove_buddies(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, GList *buddies, GList *groups)
    +{
    GList *buddy = buddies;
    GList *group = groups;
    purple_debug_info("nullprpl", "removing multiple buddies\n");
    while (buddy && group) {
    - null_remove_buddy(gc, (PurpleBuddy *)buddy->data,
    - (PurpleGroup *)group->data);
    + null_remove_buddy(protocol_server, gc, PURPLE_BUDDY(buddy->data),
    + PURPLE_GROUP(group->data));
    buddy = g_list_next(buddy);
    group = g_list_next(group);
    }
    @@ -833,26 +854,35 @@
    }
    }
    -static void null_register_user(PurpleAccount *acct) {
    +static void
    +null_register_user(PurpleProtocolServer *protocol_server, PurpleAccount *acct) {
    purple_debug_info("nullprpl", "registering account for %s\n",
    purple_account_get_username(acct));
    }
    -static void null_alias_buddy(PurpleConnection *gc, const char *who,
    - const char *alias) {
    +static void
    +null_alias_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const gchar *who,
    + const gchar *alias)
    +{
    purple_debug_info("nullprpl", "%s sets %s's alias to %s\n",
    purple_account_get_username(purple_connection_get_account(gc)), who, alias);
    }
    -static void null_group_buddy(PurpleConnection *gc, const char *who,
    - const char *old_group,
    - const char *new_group) {
    +static void
    +null_group_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const gchar *who,
    + const gchar *old_group, const gchar *new_group)
    +{
    purple_debug_info("nullprpl", "%s has moved %s from group %s to group %s\n",
    purple_account_get_username(purple_connection_get_account(gc)), who, old_group, new_group);
    }
    -static void null_rename_group(PurpleConnection *gc, const char *old_name,
    - PurpleGroup *group, GList *moved_buddies) {
    +static void
    +null_rename_group(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const gchar *old_name,
    + PurpleGroup *group, GList *moved_buddies)
    +{
    purple_debug_info("nullprpl", "%s has renamed group %s to %s\n",
    purple_account_get_username(purple_connection_get_account(gc)), old_name,
    purple_group_get_name(group));
    @@ -876,14 +906,19 @@
    return input;
    }
    -static void null_set_buddy_icon(PurpleConnection *gc,
    - PurpleImage *img) {
    +static void
    +null_set_buddy_icon(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, PurpleImage *img)
    +{
    purple_debug_info("nullprpl", "setting %s's buddy icon to %s\n",
    purple_account_get_username(purple_connection_get_account(gc)),
    img ? purple_image_get_path(img) : "(null)");
    }
    -static void null_remove_group(PurpleConnection *gc, PurpleGroup *group) {
    +static void
    +null_remove_group(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + PurpleGroup *group)
    +{
    purple_debug_info("nullprpl", "%s has removed group %s\n",
    purple_account_get_username(purple_connection_get_account(gc)),
    purple_group_get_name(group));
    --- a/libpurple/protocols/sametime/sametime.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/sametime/sametime.c Thu Jan 14 22:33:49 2021 -0600
    @@ -1424,7 +1424,7 @@
    }
    -static void mw_protocol_set_status(PurpleAccount *acct, PurpleStatus *status);
    +static void mw_protocol_set_status(PurpleProtocolServer *protocol_server, PurpleAccount *acct, PurpleStatus *status);
    /** called from mw_session_stateChange when the session's state is
    @@ -1437,7 +1437,7 @@
    /* set out initial status */
    acct = purple_connection_get_account(pd->gc);
    status = purple_account_get_active_status(acct);
    - mw_protocol_set_status(acct, status);
    + mw_protocol_set_status(NULL, acct, status);
    /* start watching for new conversations */
    purple_signal_connect(purple_conversations_get_handle(),
    @@ -3824,8 +3824,10 @@
    }
    -static void mw_protocol_get_info(PurpleConnection *gc, const char *who) {
    -
    +static void
    +mw_protocol_get_info(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const gchar *who)
    +{
    struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL };
    struct mwPurpleProtocolData *pd;
    @@ -3898,7 +3900,10 @@
    }
    -static void mw_protocol_set_status(PurpleAccount *acct, PurpleStatus *status) {
    +static void
    +mw_protocol_set_status(PurpleProtocolServer *protocol_server,
    + PurpleAccount *acct, PurpleStatus *status)
    +{
    PurpleConnection *gc;
    const char *state;
    char *message = NULL;
    @@ -3951,7 +3956,10 @@
    }
    -static void mw_protocol_set_idle(PurpleConnection *gc, int t) {
    +static void
    +mw_protocol_set_idle(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, gint t)
    +{
    struct mwSession *session;
    struct mwUserStatus stat;
    @@ -4125,11 +4133,11 @@
    }
    -static void mw_protocol_add_buddy(PurpleConnection *gc,
    - PurpleBuddy *buddy,
    - PurpleGroup *group,
    - const char *message) {
    -
    +static void
    +mw_protocol_add_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, PurpleBuddy *buddy,
    + PurpleGroup *group, const gchar *message)
    +{
    struct mwPurpleProtocolData *pd = purple_connection_get_protocol_data(gc);
    struct mwServiceResolve *srvc;
    GList *query;
    @@ -4173,7 +4181,9 @@
    }
    -static void mw_protocol_add_buddies(PurpleConnection *gc,
    +static void
    +mw_protocol_add_buddies(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc,
    GList *buddies,
    GList *groups,
    const char *message) {
    @@ -4224,9 +4234,11 @@
    }
    -static void mw_protocol_remove_buddy(PurpleConnection *gc,
    - PurpleBuddy *buddy, PurpleGroup *group) {
    -
    +static void
    +mw_protocol_remove_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, PurpleBuddy *buddy,
    + PurpleGroup *group)
    +{
    struct mwPurpleProtocolData *pd;
    struct mwAwareIdBlock idb = { mwAware_USER, (char *)purple_buddy_get_name(buddy), NULL };
    struct mwAwareList *list;
    @@ -4527,7 +4539,10 @@
    }
    -static void mw_protocol_keepalive(PurpleConnection *gc) {
    +static void
    +mw_protocol_keepalive(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc)
    +{
    struct mwSession *session;
    g_return_if_fail(gc != NULL);
    @@ -4539,10 +4554,11 @@
    }
    -static void mw_protocol_alias_buddy(PurpleConnection *gc,
    - const char *who,
    - const char *alias) {
    -
    +static void
    +mw_protocol_alias_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const gchar *who,
    + const gchar *alias)
    +{
    struct mwPurpleProtocolData *pd = purple_connection_get_protocol_data(gc);
    g_return_if_fail(pd != NULL);
    @@ -4553,11 +4569,11 @@
    }
    -static void mw_protocol_group_buddy(PurpleConnection *gc,
    - const char *who,
    - const char *old_group,
    - const char *new_group) {
    -
    +static void
    +mw_protocol_group_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const gchar *who,
    + const gchar *old_group, const gchar *new_group)
    +{
    struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL };
    GList *gl = g_list_prepend(NULL, &idb);
    @@ -4582,11 +4598,11 @@
    }
    -static void mw_protocol_rename_group(PurpleConnection *gc,
    - const char *old,
    - PurpleGroup *group,
    - GList *buddies) {
    -
    +static void
    +mw_protocol_rename_group(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, const gchar *old,
    + PurpleGroup *group, GList *buddies)
    +{
    struct mwPurpleProtocolData *pd = purple_connection_get_protocol_data(gc);
    g_return_if_fail(pd != NULL);
    @@ -4644,7 +4660,10 @@
    }
    -static void mw_protocol_remove_group(PurpleConnection *gc, PurpleGroup *group) {
    +static void
    +mw_protocol_remove_group(PurpleProtocolServer *protocol_server,
    + PurpleConnection *gc, PurpleGroup *group)
    +{
    struct mwPurpleProtocolData *pd;
    struct mwAwareList *list;
    --- a/libpurple/protocols/zephyr/zephyr.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/protocols/zephyr/zephyr.c Thu Jan 14 22:33:49 2021 -0600
    @@ -1867,7 +1867,9 @@
    return buf;
    }
    -static void zephyr_zloc(PurpleConnection *gc, const char *who)
    +static void
    +zephyr_zloc(PurpleProtocolServer *protocol_server, PurpleConnection *gc,
    + const gchar *who)
    {
    zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
    gchar* normalized_who = local_zephyr_normalize(zephyr,who);
    @@ -1894,7 +1896,10 @@
    }
    }
    -static void zephyr_set_status(PurpleAccount *account, PurpleStatus *status) {
    +static void
    +zephyr_set_status(PurpleProtocolServer *protocol_server,
    + PurpleAccount *account, PurpleStatus *status)
    +{
    PurpleConnection *gc = purple_account_get_connection(account);
    zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
    PurpleStatusPrimitive primitive = purple_status_type_get_primitive(purple_status_get_status_type(status));
    @@ -2230,7 +2235,7 @@
    static PurpleCmdRet zephyr_purple_cmd_zlocate(PurpleConversation *conv,
    const char *cmd, char **args, char **error, void *data)
    {
    - zephyr_zloc(purple_conversation_get_connection(conv),args[0]);
    + zephyr_zloc(NULL, purple_conversation_get_connection(conv),args[0]);
    return PURPLE_CMD_RET_OK;
    }
    --- a/libpurple/purpleaccountpresence.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/purpleaccountpresence.c Thu Jan 14 22:33:49 2021 -0600
    @@ -23,6 +23,8 @@
    #include "purpleaccountpresence.h"
    +#include "purpleprotocolserver.h"
    +
    struct _PurpleAccountPresence {
    PurplePresence parent;
    @@ -94,8 +96,8 @@
    protocol = purple_connection_get_protocol(gc);
    }
    - if(protocol) {
    - purple_protocol_server_iface_set_idle(protocol, gc, (idle ? (current_time - idle_time) : 0));
    + if(PURPLE_IS_PROTOCOL_SERVER(protocol)) {
    + purple_protocol_server_set_idle(PURPLE_PROTOCOL_SERVER(protocol), gc, (idle ? (current_time - idle_time) : 0));
    }
    }
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/libpurple/purpleprotocolserver.c Thu Jan 14 22:33:49 2021 -0600
    @@ -0,0 +1,377 @@
    +/*
    + * Purple - Internet Messaging Library
    + * Copyright (C) Pidgin Developers <devel@pidgin.im>
    + *
    + * 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, see <https://www.gnu.org/licenses/>.
    + */
    +
    +#include "purpleprotocolserver.h"
    +
    +/******************************************************************************
    + * GObject Implementation
    + *****************************************************************************/
    +G_DEFINE_INTERFACE(PurpleProtocolServer, purple_protocol_server, G_TYPE_INVALID)
    +
    +static void
    +purple_protocol_server_default_init(PurpleProtocolServerInterface *iface) {
    +}
    +
    +/******************************************************************************
    + * Public API
    + *****************************************************************************/
    +void
    +purple_protocol_server_register_user(PurpleProtocolServer *protocol_server,
    + PurpleAccount *account)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
    + g_return_if_fail(PURPLE_IS_ACCOUNT(account));
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->register_user != NULL) {
    + iface->register_user(protocol_server, account);
    + }
    +}
    +
    +void
    +purple_protocol_server_unregister_user(PurpleProtocolServer *protocol_server,
    + PurpleAccount *account,
    + PurpleAccountUnregistrationCb cb,
    + gpointer data)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
    + g_return_if_fail(PURPLE_IS_ACCOUNT(account));
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->unregister_user != NULL) {
    + iface->unregister_user(protocol_server, account, cb, data);
    + }
    +}
    +
    +void
    +purple_protocol_server_set_info(PurpleProtocolServer *protocol_server,
    + PurpleConnection *connection,
    + const gchar *info)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
    + g_return_if_fail(PURPLE_IS_CONNECTION(connection));
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->set_info != NULL) {
    + iface->set_info(protocol_server, connection, info);
    + }
    +}
    +
    +void
    +purple_protocol_server_get_info(PurpleProtocolServer *protocol_server,
    + PurpleConnection *connection, const gchar *who)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
    + g_return_if_fail(PURPLE_IS_CONNECTION(connection));
    + g_return_if_fail(who != NULL);
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->get_info != NULL) {
    + iface->get_info(protocol_server, connection, who);
    + }
    +}
    +
    +void
    +purple_protocol_server_set_status(PurpleProtocolServer *protocol_server,
    + PurpleAccount *account, PurpleStatus *status)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
    + g_return_if_fail(PURPLE_IS_ACCOUNT(account));
    + g_return_if_fail(PURPLE_IS_STATUS(status));
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->set_status != NULL) {
    + iface->set_status(protocol_server, account, status);
    + }
    +}
    +
    +void
    +purple_protocol_server_set_idle(PurpleProtocolServer *protocol_server,
    + PurpleConnection *connection, gint idletime)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
    + g_return_if_fail(PURPLE_IS_CONNECTION(connection));
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->set_idle != NULL) {
    + iface->set_idle(protocol_server, connection, idletime);
    + }
    +}
    +
    +void
    +purple_protocol_server_change_passwd(PurpleProtocolServer *protocol_server,
    + PurpleConnection *connection,
    + const gchar *old_pass,
    + const gchar *new_pass)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
    + g_return_if_fail(PURPLE_IS_CONNECTION(connection));
    + g_return_if_fail(old_pass != NULL);
    + g_return_if_fail(new_pass != NULL);
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->change_passwd != NULL) {
    + iface->change_passwd(protocol_server, connection, old_pass, new_pass);
    + }
    +}
    +
    +void
    +purple_protocol_server_add_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *connection,
    + PurpleBuddy *buddy, PurpleGroup *group,
    + const gchar *message)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
    + g_return_if_fail(PURPLE_IS_CONNECTION(connection));
    + g_return_if_fail(PURPLE_IS_BUDDY(buddy));
    + g_return_if_fail(PURPLE_IS_GROUP(group));
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->add_buddy != NULL) {
    + iface->add_buddy(protocol_server, connection, buddy, group, message);
    + }
    +}
    +
    +void
    +purple_protocol_server_add_buddies(PurpleProtocolServer *protocol_server,
    + PurpleConnection *connection,
    + GList *buddies, GList *groups,
    + const gchar *message)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
    + g_return_if_fail(PURPLE_IS_CONNECTION(connection));
    + g_return_if_fail(g_list_length(buddies) != g_list_length(groups));
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->add_buddies != NULL) {
    + iface->add_buddies(protocol_server, connection, buddies, groups,
    + message);
    + } else {
    + while(buddies != NULL && groups != NULL) {
    + purple_protocol_server_add_buddy(protocol_server, connection,
    + PURPLE_BUDDY(buddies->data),
    + PURPLE_GROUP(groups->data),
    + message);
    +
    + buddies = g_list_next(buddies);
    + groups = g_list_next(groups);
    + }
    + }
    +}
    +
    +void
    +purple_protocol_server_remove_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *connection,
    + PurpleBuddy *buddy, PurpleGroup *group)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
    + g_return_if_fail(PURPLE_IS_CONNECTION(connection));
    + g_return_if_fail(PURPLE_IS_BUDDY(buddy));
    + g_return_if_fail(PURPLE_IS_GROUP(group));
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->remove_buddy != NULL) {
    + iface->remove_buddy(protocol_server, connection, buddy, group);
    + }
    +}
    +
    +void
    +purple_protocol_server_remove_buddies(PurpleProtocolServer *protocol_server,
    + PurpleConnection *connection,
    + GList *buddies, GList *groups)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
    + g_return_if_fail(PURPLE_IS_CONNECTION(connection));
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->remove_buddies != NULL) {
    + iface->remove_buddies(protocol_server, connection, buddies, groups);
    + } else {
    + while(buddies != NULL && groups != NULL) {
    + purple_protocol_server_remove_buddy(protocol_server, connection,
    + PURPLE_BUDDY(buddies->data),
    + PURPLE_GROUP(groups->data));
    +
    + buddies = g_list_next(buddies);
    + groups = g_list_next(groups);
    + }
    + }
    +}
    +
    +void
    +purple_protocol_server_keepalive(PurpleProtocolServer *protocol_server,
    + PurpleConnection *connection)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
    + g_return_if_fail(PURPLE_IS_CONNECTION(connection));
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->keepalive != NULL) {
    + iface->keepalive(protocol_server, connection);
    + }
    +}
    +
    +gint
    +purple_protocol_server_get_keepalive_interval(PurpleProtocolServer *protocol_server)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_val_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server), -1);
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->get_keepalive_interval != NULL) {
    + return iface->get_keepalive_interval(protocol_server);
    + }
    +
    + return -1;
    +}
    +
    +void
    +purple_protocol_server_alias_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *connection,
    + const gchar *who, const gchar *alias)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
    + g_return_if_fail(PURPLE_IS_CONNECTION(connection));
    + g_return_if_fail(who != NULL);
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->alias_buddy != NULL) {
    + iface->alias_buddy(protocol_server, connection, who, alias);
    + }
    +}
    +
    +void
    +purple_protocol_server_group_buddy(PurpleProtocolServer *protocol_server,
    + PurpleConnection *connection,
    + const gchar *who, const gchar *old_group,
    + const gchar *new_group)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
    + g_return_if_fail(PURPLE_IS_CONNECTION(connection));
    + g_return_if_fail(who != NULL);
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->group_buddy != NULL) {
    + iface->group_buddy(protocol_server, connection, who, old_group,
    + new_group);
    + }
    +}
    +
    +void
    +purple_protocol_server_rename_group(PurpleProtocolServer *protocol_server,
    + PurpleConnection *connection,
    + const gchar *old_name, PurpleGroup *group,
    + GList *moved_buddies)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
    + g_return_if_fail(PURPLE_IS_CONNECTION(connection));
    + g_return_if_fail(PURPLE_IS_GROUP(group));
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->rename_group != NULL) {
    + iface->rename_group(protocol_server, connection, old_name, group,
    + moved_buddies);
    + }
    +}
    +
    +void
    +purple_protocol_server_set_buddy_icon(PurpleProtocolServer *protocol_server,
    + PurpleConnection *connection,
    + PurpleImage *img)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
    + g_return_if_fail(PURPLE_IS_CONNECTION(connection));
    + g_return_if_fail(PURPLE_IS_IMAGE(img));
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->set_buddy_icon != NULL) {
    + iface->set_buddy_icon(protocol_server, connection, img);
    + }
    +}
    +
    +void
    +purple_protocol_server_remove_group(PurpleProtocolServer *protocol_server,
    + PurpleConnection *connection,
    + PurpleGroup *group)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server));
    + g_return_if_fail(PURPLE_IS_CONNECTION(connection));
    + g_return_if_fail(PURPLE_IS_GROUP(group));
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->remove_group != NULL) {
    + iface->remove_group(protocol_server, connection, group);
    + }
    +}
    +
    +gint
    +purple_protocol_server_send_raw(PurpleProtocolServer *protocol_server,
    + PurpleConnection *connection,
    + const gchar *buf, gint len)
    +{
    + PurpleProtocolServerInterface *iface = NULL;
    +
    + g_return_val_if_fail(PURPLE_IS_PROTOCOL_SERVER(protocol_server), -1);
    + g_return_val_if_fail(PURPLE_IS_CONNECTION(connection), -1);
    +
    + iface = PURPLE_PROTOCOL_SERVER_GET_IFACE(protocol_server);
    + if(iface != NULL && iface->send_raw != NULL) {
    + return iface->send_raw(protocol_server, connection, buf, len);
    + }
    +
    + return -1;
    +}
    --- /dev/null Thu Jan 01 00:00:00 1970 +0000
    +++ b/libpurple/purpleprotocolserver.h Thu Jan 14 22:33:49 2021 -0600
    @@ -0,0 +1,414 @@
    +/*
    + * Purple - Internet Messaging Library
    + * Copyright (C) Pidgin Developers <devel@pidgin.im>
    + *
    + * 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, see <https://www.gnu.org/licenses/>.
    + */
    +
    +#if !defined(PURPLE_GLOBAL_HEADER_INSIDE) && !defined(PURPLE_COMPILATION)
    +# error "only <purple.h> may be included directly"
    +#endif
    +
    +#ifndef PURPLE_PROTOCOL_SERVER_H
    +#define PURPLE_PROTOCOL_SERVER_H
    +
    +/**
    + * SECTION:purpleprotocolserver
    + * @section_id: libpurple-purpleprotocolserver
    + * @short_description: Protocol Server Interface
    + * @title: ProtocolServer Interface
    + *
    + * #PurpleProtocolServer describes the API for protocols that have a central
    + * server.
    + */
    +
    +#include <glib.h>
    +#include <glib-object.h>
    +
    +#include <libpurple/account.h>
    +#include <libpurple/buddy.h>
    +#include <libpurple/connection.h>
    +#include <libpurple/group.h>
    +#include <libpurple/purplemessage.h>
    +
    +#define PURPLE_TYPE_PROTOCOL_SERVER (purple_protocol_server_get_type())
    +G_DECLARE_INTERFACE(PurpleProtocolServer, purple_protocol_server, PURPLE,
    + PROTOCOL_SERVER, GObject)
    +
    +G_BEGIN_DECLS
    +
    +/**
    + * PURPLE_TYPE_PROTOCOL_SERVER:
    + *
    + * The standard _get_type method for #PurpleProtocolServer.
    + *
    + * Since: 3.0.0
    + */
    +
    +/**
    + * PurpleProtocolServer:
    + *
    + * An opaque data structure used to reference a #PurpleProtocol that implements
    + * #PurpleProtocolServerInterface.
    + *
    + * Since: 3.0.0
    + */
    +
    +/**
    + * PurpleProtocolServerInterface:
    + * @register_user: Register a new user.
    + * @unregister_user: Remove the user from the server. The account can either be
    + * connected or disconnected. After the removal is finished,
    + * the connection will stay open and has to be closed!
    + * @set_info: Sets the user's profile.
    + * @get_info: Should arrange for purple_notify_userinfo() to be called with the
    + * requested user's profile.
    + * @set_status: Sets the active status for the given account.
    + * @set_idle: Set the idle time for the given account.
    + * @change_passwd: Changes the users password.
    + * @add_buddy: Add a buddy to a group on the server.
    + * @add_buddies: Add multiple buddies on the server at once.
    + * @remove_buddy: Removes the given buddy from the user's buddy list.
    + * @remove_buddies: Removes multiple buddies from the user's buddy list.
    + * @keepalive: If implemented, this will be called regularly for this
    + * protocol's active connections. You'd want to do this if you need
    + * to repeatedly send some kind of keepalive packet to the server
    + * to avoid being disconnected. ("Regularly" is defined to be 30
    + * unless @get_keepalive_interval is implemented to override it).
    + * @get_keepalive_interval: If implemented, this will override the default
    + * keepalive interval.
    + * @alias_buddy: Save/store buddy's alias on server list/roster
    + * @group_buddy: Change a buddy's group on a server list/roster
    + * @rename_group: Rename a group on a server list/roster
    + * @set_buddy_icon: Set the buddy icon for the given connection to @img. The
    + * protocol does <emphasis>NOT</emphasis> own a reference to
    + * @img; if it needs one, it must #g_object_ref(@img) itself.
    + * @remove_group: Removes the given group from the users buddy list.
    + * @send_raw: For use in plugins that may understand the underlying protocol.
    + *
    + * The protocol server interface.
    + *
    + * This interface provides a gateway between purple and the protocol's server.
    + */
    +struct _PurpleProtocolServerInterface {
    + /*< private >*/
    + GTypeInterface parent;
    +
    + /*< public >*/
    + void (*register_user)(PurpleProtocolServer *protocol_server, PurpleAccount *account);
    + void (*unregister_user)(PurpleProtocolServer *protocol_server, PurpleAccount *account, PurpleAccountUnregistrationCb cb, gpointer data);
    +
    + void (*set_info)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *info);
    + void (*get_info)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *who);
    +
    + void (*set_status)(PurpleProtocolServer *protocol_server, PurpleAccount *account, PurpleStatus *status);
    + void (*set_idle)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, gint idletime);
    +
    + void (*change_passwd)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *old_pass, const gchar *new_pass);
    +
    + void (*add_buddy)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, PurpleBuddy *buddy, PurpleGroup *group, const gchar *message);
    + void (*add_buddies)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, GList *buddies, GList *groups, const gchar *message);
    + void (*remove_buddy)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, PurpleBuddy *buddy, PurpleGroup *group);
    + void (*remove_buddies)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, GList *buddies, GList *groups);
    +
    + void (*keepalive)(PurpleProtocolServer *protocol_server, PurpleConnection *connection);
    + gint (*get_keepalive_interval)(PurpleProtocolServer *protocol_server);
    +
    + void (*alias_buddy)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *who, const gchar *alias);
    +
    + void (*group_buddy)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *who, const gchar *old_group, const gchar *new_group);
    +
    + void (*rename_group)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *old_name, PurpleGroup *group, GList *moved_buddies);
    +
    + void (*set_buddy_icon)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, PurpleImage *img);
    +
    + void (*remove_group)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, PurpleGroup *group);
    +
    + gint (*send_raw)(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *buf, gint len);
    +
    + /*< private >*/
    + gpointer reserved[8];
    +};
    +
    +/**
    + * purple_protocol_server_register_user:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @account: The #PurpleAccount to register.
    + *
    + * Tell @protocol_server to register the new account described by @account.
    + *
    + * Since: 3.0.0
    + */
    +void purple_protocol_server_register_user(PurpleProtocolServer *protocol_server, PurpleAccount *account);
    +
    +/**
    + * purple_protocol_server_unregister_user:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @account: The #PurpleAccount instance.
    + * @cb: (scope call): A PurpleAccountUnregistrationCb function.
    + * @data: User data to pass to @cb.
    + *
    + * Unregisters @account with @protocol_server. The account can either be
    + * connected or disconnected. After the removal is finished, the connection
    + * will stay open and has to be closed.
    + *
    + * Since: 3.0.0
    + */
    +void purple_protocol_server_unregister_user(PurpleProtocolServer *protocol_server, PurpleAccount *account, PurpleAccountUnregistrationCb cb, gpointer data);
    +
    +/**
    + * purple_protocol_server_set_info:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @connection: The #PurpleConnection instance.
    + * @info: The user info to set.
    + *
    + * Sets the user info, sometimes referred to as a user profile to @info.
    + *
    + * Since: 3.0.0
    + */
    +void purple_protocol_server_set_info(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *info);
    +
    +/**
    + * purple_protocol_server_get_info:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @connection: The #PurpleConnection instance.
    + * @who: The name of the user whose information you're asking for.
    + *
    + * Gets the user info or profile for @who and displays it in a protocol specifc
    + * way.
    + *
    + * Since: 3.0.0
    + */
    +void purple_protocol_server_get_info(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *who);
    +
    +/**
    + * purple_protocol_server_set_status:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @account: The #PurpleAccount instance.
    + * @status: The #PurpleStatus instance.
    + *
    + * Sets the status for account @account to @status.
    + *
    + * Since: 3.0.0
    + */
    +void purple_protocol_server_set_status(PurpleProtocolServer *protocol_server, PurpleAccount *account, PurpleStatus *status);
    +
    +/**
    + * purple_protocol_server_set_idle:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @connection: The #PurpleConnection instance.
    + * @idletime: The number of seconds that the user has been idle.
    + *
    + * Tells @protocol_server to set the user's idle time to @idletime.
    + *
    + * Since: 3.0.0
    + */
    +void purple_protocol_server_set_idle(PurpleProtocolServer *protocol_server, PurpleConnection *connection, gint idletime);
    +
    +/**
    + * purple_protocol_server_change_passwd:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @connection: The #PurpleConnection instance.
    + * @old_pass: The user's old password.
    + * @new_pass: The new password for the user.
    + *
    + * Changes the user's password from @old_pass to @new_pass.
    + *
    + * Since: 3.0.0
    + */
    +void purple_protocol_server_change_passwd(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *old_pass, const gchar *new_pass);
    +
    +/**
    + * purple_protocol_server_add_buddy:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @connection: The #PurpleConnection instance.
    + * @buddy: The #PurpleBuddy to add.
    + * @group: The #PurpleGroup for @buddy.
    + * @message: An optional invite message.
    + *
    + * This protocol function may be called in situations in which the buddy is
    + * already in the specified group. If the protocol supports authorization and
    + * the user is not already authorized to see the status of @buddy, this
    + * function will request authorization. If authorization is required, then
    + * @message will be used as an invite message.
    + *
    + * Since: 3.0.0
    + */
    +void purple_protocol_server_add_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *connection, PurpleBuddy *buddy, PurpleGroup *group, const gchar *message);
    +
    +/**
    + * purple_protocol_server_add_buddies:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @connection: The #PurpleConnection instance.
    + * @buddies: (element-type PurpleBuddy): A #GList of #PurpleBuddy's to add.
    + * @groups: (element-type PurpleGroup): A #GList of #PurpleGroup's that
    + * correspond to the @buddies parameter.
    + * @message: An optional invite message to send.
    + *
    + * Similar to purple_protocol_server_add_buddy() but can add multiple buddies
    + * at a time. If @protocol_server does not implement this function, this will
    + * call purple_protocol_server_add_buddy() for each buddy/group pair in
    + * @buddies/@groups.
    + *
    + * Since: 3.0.0
    + */
    +void purple_protocol_server_add_buddies(PurpleProtocolServer *protocol_server, PurpleConnection *connection, GList *buddies, GList *groups, const gchar *message);
    +
    +/**
    + * purple_protocol_server_remove_buddy:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @connection: The #PurpleConnection instance.
    + * @buddy: The #PurpleBuddy instance.
    + * @group: The #PurpleGroup instance.
    + *
    + * Removes @buddy and potentially @group from the server side list of contacts.
    + *
    + * Since: 3.0.0
    + */
    +void purple_protocol_server_remove_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *connection, PurpleBuddy *buddy, PurpleGroup *group);
    +
    +/**
    + * purple_protocol_server_remove_buddies:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @connection: The #PurpleConnection instance.
    + * @buddies: (element-type PurpleBuddy): A #GList of #PurpleBuddy's to remove.
    + * @groups: (element-type PurpleGroup): A #GList of #PurpleGroup's
    + * corresponding to @buddies.
    + *
    + * Similiar to purple_protocol_server_remove_buddy() but allows you to remove
    + * multiple at a time.
    + *
    + * If @protocol_server doesn't implement this function directly,
    + * purple_protocol_server_remove_buddy() will be called for each buddy/group
    + * pair in @buddies/@groups.
    + *
    + * Since: 3.0.0
    + */
    +void purple_protocol_server_remove_buddies(PurpleProtocolServer *protocol_server, PurpleConnection *connection, GList *buddies, GList *groups);
    +
    +/**
    + * purple_protocol_server_keepalive:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @connection: The #PurpleConnection instance.
    + *
    + * Tell @protocol_server to send its keep alive to the server.
    + *
    + * Since: 3.0.0
    + */
    +void purple_protocol_server_keepalive(PurpleProtocolServer *protocol_server, PurpleConnection *connection);
    +
    +/**
    + * purple_protocol_server_get_keepalive_interval:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + *
    + * Returns a custom interval, in seconds, that libpurple should tell
    + * @protocol_server to send its keepalive.
    + *
    + * Returns: The interval, in seconds, that the keep-alive function should be
    + * called.
    + *
    + * Since: 3.0.0
    + */
    +gint purple_protocol_server_get_keepalive_interval(PurpleProtocolServer *protocol_server);
    +
    +/**
    + * purple_protocol_server_alias_buddy:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @connection: The #PurpleConnection instance.
    + * @who: The name of the user to alias.
    + * @alias: The new alias for @who.
    + *
    + * Sets the server side alias for @who to @alias.
    + *
    + * Since: 3.0.0
    + */
    +void purple_protocol_server_alias_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *who, const gchar *alias);
    +
    +/**
    + * purple_protocol_server_group_buddy:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @connection: The #PurpleConnection instance.
    + * @who: The name of the user whose group to switch.
    + * @old_group: The name of @who's old group.
    + * @new_group: The name of the new group to add @who to.
    + *
    + * Moves @who from group @old_group to a new group of @new_group.
    + *
    + * Since: 3.0.0
    + */
    +void purple_protocol_server_group_buddy(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *who, const gchar *old_group, const gchar *new_group);
    +
    +/**
    + * purple_protocol_server_rename_group:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @connection: The #PurpleConnection instance.
    + * @old_name: The old name of the group.
    + * @group: The new #PurpleGroup instance.
    + * @moved_buddies: (element-type PurpleBuddy): A list of #PurpleBuddy's being
    + * moved as part of this rename.
    + *
    + * Renames the group named @old_name to the new @group.
    + *
    + * Since: 3.0.0
    + */
    +void purple_protocol_server_rename_group(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *old_name, PurpleGroup *group, GList *moved_buddies);
    +
    +/**
    + * purple_protocol_server_set_buddy_icon:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @connection: The #PurpleConnection instance.
    + * @img: The #PurpleImage instance.
    + *
    + * Sets the user's buddy icon to @img.
    + *
    + * Since: 3.0.0
    + */
    +void purple_protocol_server_set_buddy_icon(PurpleProtocolServer *protocol_server, PurpleConnection *connection, PurpleImage *img);
    +
    +/**
    + * purple_protocol_server_remove_group:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @connection: The #PurpleConnection instance.
    + * @group: The #PurpleGroup instance.
    + *
    + * Removes @group from the server side contact list.
    + *
    + * Since: 3.0.0
    + */
    +void purple_protocol_server_remove_group(PurpleProtocolServer *protocol_server, PurpleConnection *connection, PurpleGroup *group);
    +
    +/**
    + * purple_protocol_server_send_raw:
    + * @protocol_server: The #PurpleProtocolServer instance.
    + * @connection: The #PurpleConnection instance.
    + * @buf: The raw protocol data to send.
    + * @len: The length of @buf in bytes.
    + *
    + * Sends raw data over the protocol. This should only be called when you know
    + * the exact underlying protocol.
    + *
    + * Returns: The number of bytes that was sent.
    + *
    + * Since: 3.0.0
    + */
    +gint purple_protocol_server_send_raw(PurpleProtocolServer *protocol_server, PurpleConnection *connection, const gchar *buf, gint len);
    +
    +G_END_DECLS
    +
    +#endif /* PURPLE_PROTOCOL_SERVER_H */
    +
    --- a/libpurple/server.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/libpurple/server.c Thu Jan 14 22:33:49 2021 -0600
    @@ -38,6 +38,7 @@
    #include "purpleprotocolchat.h"
    #include "purpleprotocolim.h"
    #include "purpleprotocolprivacy.h"
    +#include "purpleprotocolserver.h"
    #include "request.h"
    #include "signals.h"
    #include "server.h"
    @@ -179,7 +180,8 @@
    if (gc) {
    protocol = purple_connection_get_protocol(gc);
    - purple_protocol_server_iface_get_info(protocol, gc, name);
    + purple_protocol_server_get_info(PURPLE_PROTOCOL_SERVER(protocol), gc,
    + name);
    }
    }
    @@ -197,7 +199,8 @@
    purple_signal_emit(purple_accounts_get_handle(),
    "account-setting-info", account, info);
    - purple_protocol_server_iface_set_info(protocol, gc, info);
    + purple_protocol_server_set_info(PURPLE_PROTOCOL_SERVER(protocol),
    + gc, info);
    purple_signal_emit(purple_accounts_get_handle(),
    "account-set-info", account, info);
    @@ -220,11 +223,12 @@
    if (account) {
    gc = purple_account_get_connection(account);
    - if (gc) {
    + if(gc) {
    protocol = purple_connection_get_protocol(gc);
    - purple_protocol_server_iface_alias_buddy(protocol, gc,
    - purple_buddy_get_name(b),
    - purple_buddy_get_local_alias(b));
    + purple_protocol_server_alias_buddy(PURPLE_PROTOCOL_SERVER(protocol),
    + gc,
    + purple_buddy_get_name(b),
    + purple_buddy_get_local_alias(b));
    }
    }
    }
    @@ -345,9 +349,10 @@
    if (gc) {
    protocol = purple_connection_get_protocol(gc);
    - purple_protocol_server_iface_group_buddy(protocol, gc, purple_buddy_get_name(buddy),
    - purple_group_get_name(orig),
    - purple_group_get_name(dest));
    + purple_protocol_server_group_buddy(PURPLE_PROTOCOL_SERVER(protocol),
    + gc, purple_buddy_get_name(buddy),
    + purple_group_get_name(orig),
    + purple_group_get_name(dest));
    }
    }
    --- a/pidgin/plugins/xmppconsole/xmppconsole.c Thu Jan 14 21:20:10 2021 -0600
    +++ b/pidgin/plugins/xmppconsole/xmppconsole.c Thu Jan 14 22:33:49 2021 -0600
    @@ -252,8 +252,10 @@
    gtk_text_buffer_get_bounds(console->entry_buffer, &start, &end);
    text = gtk_text_buffer_get_text(console->entry_buffer, &start, &end, FALSE);
    - if (protocol)
    - purple_protocol_server_iface_send_raw(protocol, gc, text, strlen(text));
    + if(PURPLE_IS_PROTOCOL_SERVER(protocol)) {
    + purple_protocol_server_send_raw(PURPLE_PROTOCOL_SERVER(protocol), gc,
    + text, strlen(text));
    + }
    g_free(text);
    gtk_text_buffer_set_text(console->entry_buffer, "", 0);
    --- a/po/POTFILES.in Thu Jan 14 21:20:10 2021 -0600
    +++ b/po/POTFILES.in Thu Jan 14 22:33:49 2021 -0600
    @@ -261,6 +261,7 @@
    libpurple/purpleprotocolim.c
    libpurple/purpleprotocolmedia.c
    libpurple/purpleprotocolprivacy.c
    +libpurple/purpleprotocolserver.c
    libpurple/purplewhiteboard.c
    libpurple/purplewhiteboarduiops.c
    libpurple/queuedoutputstream.c