summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary Kramlich <grim@reaperworld.com>2023-03-29 23:22:41 -0500
committerGary Kramlich <grim@reaperworld.com>2023-03-29 23:22:41 -0500
commit05c92833692a61d687aca8317b12a6cb978810f6 (patch)
tree3c9d0ebec10dee4d1f2e1c80334542cdf69c43a8
parent92569c871d5cd91c5da8bdf7cd80a6ef1e8c74de (diff)
downloadpidgin-05c92833692a61d687aca8317b12a6cb978810f6.tar.gz
Remove the Facebook plugin
This hasn't been used in forever and is behind on patches from the purple2 version so this for sure is not going to work. This will also stop people from tryingt to update the purple2 version for this code as that's a horrible idea. Testing Done: had the turtles do their thing Reviewed at https://reviews.imfreedom.org/r/2393/
-rw-r--r--doc/reference/protocols/facebook/facebook.toml.in43
-rw-r--r--doc/reference/protocols/facebook/meson.build35
-rw-r--r--doc/reference/protocols/facebook/urlmap.js9
-rw-r--r--doc/reference/protocols/meson.build4
-rw-r--r--libpurple/protocols/facebook/api.c3468
-rw-r--r--libpurple/protocols/facebook/api.h1002
-rw-r--r--libpurple/protocols/facebook/data.c558
-rw-r--r--libpurple/protocols/facebook/data.h318
-rw-r--r--libpurple/protocols/facebook/facebook.c1740
-rw-r--r--libpurple/protocols/facebook/facebook.h51
-rw-r--r--libpurple/protocols/facebook/http.c282
-rw-r--r--libpurple/protocols/facebook/http.h266
-rw-r--r--libpurple/protocols/facebook/id.h122
-rw-r--r--libpurple/protocols/facebook/json.c658
-rw-r--r--libpurple/protocols/facebook/json.h471
-rw-r--r--libpurple/protocols/facebook/meson.build63
-rw-r--r--libpurple/protocols/facebook/mqtt.c1016
-rw-r--r--libpurple/protocols/facebook/mqtt.h520
-rw-r--r--libpurple/protocols/facebook/resources/facebook.gresource.xml8
-rw-r--r--libpurple/protocols/facebook/resources/icons/16x16/apps/im-facebook.pngbin552 -> 0 bytes
-rw-r--r--libpurple/protocols/facebook/resources/icons/22x22/apps/im-facebook.pngbin731 -> 0 bytes
-rw-r--r--libpurple/protocols/facebook/resources/icons/48x48/apps/im-facebook.pngbin1521 -> 0 bytes
-rw-r--r--libpurple/protocols/facebook/thrift.c675
-rw-r--r--libpurple/protocols/facebook/thrift.h553
-rw-r--r--libpurple/protocols/facebook/util.c619
-rw-r--r--libpurple/protocols/facebook/util.h335
-rw-r--r--libpurple/protocols/meson.build1
-rw-r--r--po/POTFILES.in8
28 files changed, 0 insertions, 12825 deletions
diff --git a/doc/reference/protocols/facebook/facebook.toml.in b/doc/reference/protocols/facebook/facebook.toml.in
deleted file mode 100644
index b94f3c564c..0000000000
--- a/doc/reference/protocols/facebook/facebook.toml.in
+++ /dev/null
@@ -1,43 +0,0 @@
-[library]
-version = "@PURPLE_VERSION@"
-browse_url = "https://keep.imfreedom.org/pidgin/pidgin/"
-repository_url = "https://keep.imfreedom.org/pidgin/pidgin/"
-website_url = "https://keep.imfreedom.org/pidgin/pidgin/"
-authors = "Pidgin Developers"
-logo_url = ""
-license = "GPL-2.0-or-later"
-description = "Purple Facebook Protocol Plugin"
-dependencies = [ "GLib-2.0", "GObject-2.0", "Purple-3.0" ]
-devhelp = true
-search_index = true
-
- [dependencies."GLib-2.0"]
- name = "GLib"
- description = "General-purpose, portable utility library."
- docs_url = "https://docs.gtk.org/glib/"
-
- [dependencies."GObject-2.0"]
- name = "GObject"
- description = "The base type system library"
- docs_url = "https://docs.gtk.org/gobject/"
-
- [dependencies."Purple-3.0"]
- name = "Purple"
- description = "Purple Universal Chat Library"
- docs_url = "https://docs.imfreedom.org/purple3/"
-
-[theme]
-name = "basic"
-show_index_summary = true
-show_class_hierarchy = true
-
-[source-location]
-base_url = "https://keep.imfreedom.org/pidgin/pidgin/file/default/"
-
-[extra]
-# The same order will be used when generating the index
-content_files = [
-]
-content_images = [
-]
-urlmap_file = "urlmap.js"
diff --git a/doc/reference/protocols/facebook/meson.build b/doc/reference/protocols/facebook/meson.build
deleted file mode 100644
index 32cae7c38d..0000000000
--- a/doc/reference/protocols/facebook/meson.build
+++ /dev/null
@@ -1,35 +0,0 @@
-facebook_doc_content_files = []
-
-if get_option('doc')
- facebook_toml = configure_file(
- input : 'facebook.toml.in',
- output : 'facebook.toml',
- configuration : version_conf,
- install : true,
- install_dir : docs_dir / 'facebook',
- )
-
- facebook_doc = custom_target('facebook-doc',
- input : [ facebook_toml, facebook_gir[0] ],
- output : 'facebook',
- command : [
- gidocgen,
- 'generate',
- '--quiet',
- '--fatal-warnings',
- '--config=@INPUT0@',
- '--output-dir=@OUTPUT@',
- '--no-namespace-dir',
- '--content-dir=@0@'.format(meson.current_source_dir()),
- '--add-include-path=@0@'.format(meson.global_build_root() / 'subprojects/gplugin/gplugin'),
- '--add-include-path=@0@'.format(meson.global_build_root() / 'libpurple'),
- '@INPUT1@'
- ],
- depends: [ libpurple_gir[0] ],
- depend_files : [ facebook_doc_content_files ],
- build_by_default : true,
- install : true,
- install_dir : docs_dir,
- )
-endif
-
diff --git a/doc/reference/protocols/facebook/urlmap.js b/doc/reference/protocols/facebook/urlmap.js
deleted file mode 100644
index 357915f508..0000000000
--- a/doc/reference/protocols/facebook/urlmap.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// SPDX-FileCopyrightText: 2021 GNOME Foundation
-// SPDX-License-Identifier: LGPL-2.1-or-later
-
-// A map between namespaces and base URLs for their online documentation
-baseURLs = [
- [ 'GLib', 'https://docs.gtk.org/glib/' ],
- [ 'GObject', 'https://docs.gtk.org/gobject/' ],
- [ 'Purple3', 'https://docs.imfreedom.org/purple3/' ],
-]
diff --git a/doc/reference/protocols/meson.build b/doc/reference/protocols/meson.build
index b81df04463..f4261c4128 100644
--- a/doc/reference/protocols/meson.build
+++ b/doc/reference/protocols/meson.build
@@ -1,6 +1,2 @@
protocols_doc = []
-if DYNAMIC_FACEBOOK
- subdir('facebook')
- protocols_doc += facebook_doc
-endif
diff --git a/libpurple/protocols/facebook/api.c b/libpurple/protocols/facebook/api.c
deleted file mode 100644
index 6e14195bcd..0000000000
--- a/libpurple/protocols/facebook/api.c
+++ /dev/null
@@ -1,3468 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#include <glib/gi18n-lib.h>
-
-#include <json-glib/json-glib.h>
-#include <libsoup/soup.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include "libpurple/glibcompat.h"
-
-#include "api.h"
-#include "http.h"
-#include "json.h"
-#include "thrift.h"
-#include "util.h"
-
-enum
-{
- PROP_0,
-
- PROP_CID,
- PROP_DID,
- PROP_MID,
- PROP_STOKEN,
- PROP_TOKEN,
- PROP_UID,
-
- PROP_N
-};
-
-/**
- * FbApi:
- *
- * Represents a Facebook Messenger connection.
- */
-struct _FbApi {
- GObject parent;
-
- FbMqtt *mqtt;
- SoupSession *cons;
- PurpleConnection *gc;
- gboolean retrying;
-
- FbId uid;
- gint64 sid;
- guint64 mid;
- gchar *cid;
- gchar *did;
- gchar *stoken;
- gchar *token;
-
- GQueue *msgs;
- gboolean invisible;
- guint unread;
- FbId lastmid;
- gchar *contacts_delta;
-};
-
-static void fb_api_error_literal(FbApi *api, FbApiError error,
- const gchar *msg);
-
-static void
-fb_api_attach(FbApi *api, FbId aid, const gchar *msgid, FbApiMessage *msg);
-
-static void
-fb_api_contacts_after(FbApi *api, const gchar *cursor);
-
-static void
-fb_api_message_send(FbApi *api, FbApiMessage *msg);
-
-static void
-fb_api_sticker(FbApi *api, FbId sid, FbApiMessage *msg);
-
-void
-fb_api_contacts_delta(FbApi *api, const gchar *delta_cursor);
-
-G_DEFINE_TYPE(FbApi, fb_api, G_TYPE_OBJECT);
-
-static void
-fb_api_set_property(GObject *obj, guint prop, const GValue *val,
- GParamSpec *pspec)
-{
- FbApi *api = FB_API(obj);
-
- switch (prop) {
- case PROP_CID:
- g_free(api->cid);
- api->cid = g_value_dup_string(val);
- break;
- case PROP_DID:
- g_free(api->did);
- api->did = g_value_dup_string(val);
- break;
- case PROP_MID:
- api->mid = g_value_get_uint64(val);
- break;
- case PROP_STOKEN:
- g_free(api->stoken);
- api->stoken = g_value_dup_string(val);
- break;
- case PROP_TOKEN:
- g_free(api->token);
- api->token = g_value_dup_string(val);
- break;
- case PROP_UID:
- api->uid = g_value_get_int64(val);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop, pspec);
- break;
- }
-}
-
-static void
-fb_api_get_property(GObject *obj, guint prop, GValue *val, GParamSpec *pspec)
-{
- FbApi *api = FB_API(obj);
-
- switch (prop) {
- case PROP_CID:
- g_value_set_string(val, api->cid);
- break;
- case PROP_DID:
- g_value_set_string(val, api->did);
- break;
- case PROP_MID:
- g_value_set_uint64(val, api->mid);
- break;
- case PROP_STOKEN:
- g_value_set_string(val, api->stoken);
- break;
- case PROP_TOKEN:
- g_value_set_string(val, api->token);
- break;
- case PROP_UID:
- g_value_set_int64(val, api->uid);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop, pspec);
- break;
- }
-}
-
-
-static void
-fb_api_dispose(GObject *obj)
-{
- FbApi *api = FB_API(obj);
-
- if(api->cons != NULL) {
- soup_session_abort(api->cons);
- }
-
- g_clear_object(&api->mqtt);
-
- g_clear_object(&api->cons);
- if(api->msgs != NULL) {
- g_queue_free_full(api->msgs, (GDestroyNotify)fb_api_message_free);
- api->msgs = NULL;
- }
-
- g_clear_pointer(&api->cid, g_free);
- g_clear_pointer(&api->did, g_free);
- g_clear_pointer(&api->stoken, g_free);
- g_clear_pointer(&api->token, g_free);
- g_clear_pointer(&api->contacts_delta, g_free);
-}
-
-static void
-fb_api_class_init(FbApiClass *klass)
-{
- GObjectClass *gklass = G_OBJECT_CLASS(klass);
- GParamSpec *props[PROP_N] = {NULL};
-
- gklass->set_property = fb_api_set_property;
- gklass->get_property = fb_api_get_property;
- gklass->dispose = fb_api_dispose;
-
- /**
- * FbApi:cid:
- *
- * The client identifier for MQTT. This value should be saved
- * and loaded for persistence.
- */
- props[PROP_CID] = g_param_spec_string(
- "cid",
- "Client ID",
- "Client identifier for MQTT",
- NULL,
- G_PARAM_READWRITE);
-
- /**
- * FbApi:did:
- *
- * The device identifier for the MQTT message queue. This value
- * should be saved and loaded for persistence.
- */
- props[PROP_DID] = g_param_spec_string(
- "did",
- "Device ID",
- "Device identifier for the MQTT message queue",
- NULL,
- G_PARAM_READWRITE);
-
- /**
- * FbApi:mid:
- *
- * The MQTT identifier. This value should be saved and loaded
- * for persistence.
- */
- props[PROP_MID] = g_param_spec_uint64(
- "mid",
- "MQTT ID",
- "MQTT identifier",
- 0, G_MAXUINT64, 0,
- G_PARAM_READWRITE);
-
- /**
- * FbApi:stoken:
- *
- * The synchronization token for the MQTT message queue. This
- * value should be saved and loaded for persistence.
- */
- props[PROP_STOKEN] = g_param_spec_string(
- "stoken",
- "Sync Token",
- "Synchronization token for the MQTT message queue",
- NULL,
- G_PARAM_READWRITE);
-
- /**
- * FbApi:token:
- *
- * The access token for authentication. This value should be
- * saved and loaded for persistence.
- */
- props[PROP_TOKEN] = g_param_spec_string(
- "token",
- "Access Token",
- "Access token for authentication",
- NULL,
- G_PARAM_READWRITE);
-
- /**
- * FbApi:uid:
- *
- * The #FbId of the user of the #FbApi.
- */
- props[PROP_UID] = g_param_spec_int64(
- "uid",
- "User ID",
- "User identifier",
- 0, G_MAXINT64, 0,
- G_PARAM_READWRITE);
- g_object_class_install_properties(gklass, PROP_N, props);
-
- /**
- * FbApi::auth:
- * @api: The #FbApi.
- *
- * Emitted upon the successful completion of the authentication
- * process. This is emitted as a result of #fb_api_auth().
- */
- g_signal_new("auth",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 0);
-
- /**
- * FbApi::connect:
- * @api: The #FbApi.
- *
- * Emitted upon the successful completion of the connection
- * process. This is emitted as a result of #fb_api_connect().
- */
- g_signal_new("connect",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 0);
-
- /**
- * FbApi::contact:
- * @api: The #FbApi.
- * @user: The #FbApiUser.
- *
- * Emitted upon the successful reply of a contact request. This
- * is emitted as a result of #fb_api_contact().
- */
- g_signal_new("contact",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 1, G_TYPE_POINTER);
-
- /**
- * FbApi::contacts:
- * @api: The #FbApi.
- * @users: The #GSList of #FbApiUser's.
- * @complete: #TRUE if the list is fetched, otherwise #FALSE.
- *
- * Emitted upon the successful reply of a contacts request.
- * This is emitted as a result of #fb_api_contacts(). This can
- * be emitted multiple times before the entire contacts list
- * has been fetched. Use @complete for detecting the completion
- * status of the list fetch.
- */
- g_signal_new("contacts",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 2, G_TYPE_POINTER, G_TYPE_BOOLEAN);
-
- /**
- * FbApi::contacts-delta:
- * @api: The #FbApi.
- * @added: The #GSList of added #FbApiUser's.
- * @removed: The #GSList of strings with removed user ids.
- *
- * Like 'contacts', but only the deltas.
- */
- g_signal_new("contacts-delta",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 2, G_TYPE_POINTER, G_TYPE_POINTER);
-
- /**
- * FbApi::error:
- * @api: The #FbApi.
- * @error: The #GError.
- *
- * Emitted whenever an error is hit within the #FbApi. This
- * should disconnect the #FbApi with #fb_api_disconnect().
- */
- g_signal_new("error",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 1, G_TYPE_POINTER);
-
- /**
- * FbApi::events:
- * @api: The #FbApi.
- * @events: The #GSList of #FbApiEvent's.
- *
- * Emitted upon incoming events from the stream.
- */
- g_signal_new("events",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 1, G_TYPE_POINTER);
-
- /**
- * FbApi::messages:
- * @api: The #FbApi.
- * @msgs: The #GSList of #FbApiMessage's.
- *
- * Emitted upon incoming messages from the stream.
- */
- g_signal_new("messages",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 1, G_TYPE_POINTER);
-
- /**
- * FbApi::presences:
- * @api: The #FbApi.
- * @press: The #GSList of #FbApiPresence's.
- *
- * Emitted upon incoming presences from the stream.
- */
- g_signal_new("presences",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 1, G_TYPE_POINTER);
-
- /**
- * FbApi::thread:
- * @api: The #FbApi.
- * @thrd: The #FbApiThread.
- *
- * Emitted upon the successful reply of a thread request. This
- * is emitted as a result of #fb_api_thread().
- */
- g_signal_new("thread",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 1, G_TYPE_POINTER);
-
- /**
- * FbApi::thread-create:
- * @api: The #FbApi.
- * @tid: The thread #FbId.
- *
- * Emitted upon the successful reply of a thread creation
- * request. This is emitted as a result of
- * #fb_api_thread_create().
- */
- g_signal_new("thread-create",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 1, FB_TYPE_ID);
-
- /**
- * FbApi::thread-kicked:
- * @api: The #FbApi.
- * @thrd: The #FbApiThread.
- *
- * Emitted upon the reply of a thread request when the user is no longer
- * part of that thread. This is emitted as a result of #fb_api_thread().
- */
- g_signal_new("thread-kicked",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 1, G_TYPE_POINTER);
-
- /**
- * FbApi::threads:
- * @api: The #FbApi.
- * @thrds: The #GSList of #FbApiThread's.
- *
- * Emitted upon the successful reply of a threads request. This
- * is emitted as a result of #fb_api_threads().
- */
- g_signal_new("threads",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 1, G_TYPE_POINTER);
-
- /**
- * FbApi::typing:
- * @api: The #FbApi.
- * @typg: The #FbApiTyping.
- *
- * Emitted upon an incoming typing state from the stream.
- */
- g_signal_new("typing",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 1, G_TYPE_POINTER);
-}
-
-static void
-fb_api_init(FbApi *api)
-{
- api->msgs = g_queue_new();
-}
-
-GQuark
-fb_api_error_quark(void)
-{
- static GQuark q = 0;
-
- if (G_UNLIKELY(q == 0)) {
- q = g_quark_from_static_string("fb-api-error-quark");
- }
-
- return q;
-}
-
-static gboolean
-fb_api_json_chk(FbApi *api, gconstpointer data, gssize size, JsonNode **node)
-{
- const gchar *str;
- FbApiError errc = FB_API_ERROR_GENERAL;
- FbJsonValues *values;
- gboolean success = TRUE;
- gchar *msg;
- GError *err = NULL;
- gint64 code;
- guint i;
- JsonNode *root;
-
- static const gchar *exprs[] = {
- "$.error.message",
- "$.error.summary",
- "$.error_msg",
- "$.errorCode",
- "$.failedSend.errorMessage",
- };
-
- g_return_val_if_fail(FB_IS_API(api), FALSE);
-
- if (G_UNLIKELY(size == 0)) {
- fb_api_error_literal(api, FB_API_ERROR_GENERAL, _("Empty JSON data"));
- return FALSE;
- }
-
- fb_util_debug(FB_UTIL_DEBUG_INFO, "Parsing JSON: %.*s\n",
- (gint) size, (const gchar *) data);
-
- root = fb_json_node_new(data, size, &err);
- FB_API_ERROR_EMIT(api, err, return FALSE);
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE, "$.error_code");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.error.type");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.errorCode");
- fb_json_values_update(values, &err);
-
- FB_API_ERROR_EMIT(api, err,
- g_object_unref(values);
- json_node_free(root);
- return FALSE
- );
-
- code = fb_json_values_next_int(values, 0);
- str = fb_json_values_next_str(values, NULL);
-
- if (purple_strequal(str, "OAuthException") || (code == 401)) {
- errc = FB_API_ERROR_AUTH;
- success = FALSE;
-
- g_clear_pointer(&api->stoken, g_free);
- g_clear_pointer(&api->token, g_free);
- }
-
- /* 509 is used for "invalid attachment id" */
- if (code == 509) {
- errc = FB_API_ERROR_NONFATAL;
- success = FALSE;
- }
-
- str = fb_json_values_next_str(values, NULL);
-
- if (purple_strequal(str, "ERROR_QUEUE_NOT_FOUND") ||
- purple_strequal(str, "ERROR_QUEUE_LOST"))
- {
- errc = FB_API_ERROR_QUEUE;
- success = FALSE;
-
- g_clear_pointer(&api->stoken, g_free);
- }
-
- g_object_unref(values);
-
- for (msg = NULL, i = 0; i < G_N_ELEMENTS(exprs); i++) {
- msg = fb_json_node_get_str(root, exprs[i], NULL);
-
- if (msg != NULL) {
- success = FALSE;
- break;
- }
- }
-
- if (!success && (msg == NULL)) {
- msg = g_strdup(_("Unknown error"));
- }
-
- if (msg != NULL) {
- fb_api_error_literal(api, errc, msg);
- json_node_free(root);
- g_free(msg);
- return FALSE;
- }
-
- if (node != NULL) {
- *node = root;
- } else {
- json_node_free(root);
- }
-
- return TRUE;
-}
-
-static gboolean
-fb_api_http_chk(FbApi *api, SoupSession *session, GAsyncResult *result,
- SoupMessage *msg, JsonNode **root)
-{
- GBytes *response_body = NULL;
- const gchar *reason = NULL;
- const gchar *data = NULL;
- GError *err = NULL;
- gint code;
- gsize size = 0;
-
- reason = soup_message_get_reason_phrase(msg);
- code = soup_message_get_status(msg);
-
- fb_util_debug(FB_UTIL_DEBUG_INFO, "HTTP Response (%p):", msg);
- if (reason != NULL) {
- fb_util_debug(FB_UTIL_DEBUG_INFO, " Response Error: %s (%d)", reason,
- code);
- } else {
- fb_util_debug(FB_UTIL_DEBUG_INFO, " Response Error: %d", code);
- }
-
- if (fb_http_error_chk(msg, &err) && (root == NULL)) {
- return TRUE;
- }
-
- response_body = soup_session_send_and_read_finish(session, result, &err);
- if(response_body != NULL) {
- data = g_bytes_get_data(response_body, &size);
- }
-
- if (G_LIKELY(size > 0)) {
- fb_util_debug(FB_UTIL_DEBUG_INFO, " Response Data: %.*s",
- (gint) size, data);
- }
-
- /* Rudimentary check to prevent wrongful error parsing */
- if ((size < 2) || (data[0] != '{') || (data[size - 1] != '}')) {
- FB_API_ERROR_EMIT(api, err, return FALSE);
- }
-
- if (!fb_api_json_chk(api, data, size, root)) {
- if (G_UNLIKELY(err != NULL)) {
- g_error_free(err);
- }
-
- return FALSE;
- }
-
- FB_API_ERROR_EMIT(api, err, return FALSE);
- return TRUE;
-}
-
-static SoupMessage *
-fb_api_http_req(FbApi *api, const gchar *url, const gchar *name,
- const gchar *method, FbHttpParams *params,
- GAsyncReadyCallback callback)
-{
- gchar *data;
- gchar *key;
- gchar *val;
- GList *keys;
- GList *l;
- GString *gstr;
- SoupMessage *msg;
-
- fb_http_params_set_str(params, "api_key", FB_API_KEY);
- fb_http_params_set_str(params, "device_id", api->did);
- fb_http_params_set_str(params, "fb_api_req_friendly_name", name);
- fb_http_params_set_str(params, "format", "json");
- fb_http_params_set_str(params, "method", method);
-
- val = fb_util_get_locale();
- fb_http_params_set_str(params, "locale", val);
- g_free(val);
-
- /* Ensure an old signature is not computed */
- g_hash_table_remove(params, "sig");
-
- gstr = g_string_new(NULL);
- keys = g_hash_table_get_keys(params);
- keys = g_list_sort(keys, (GCompareFunc) g_ascii_strcasecmp);
-
- for (l = keys; l != NULL; l = l->next) {
- key = l->data;
- val = g_hash_table_lookup(params, key);
- g_string_append_printf(gstr, "%s=%s", key, val);
- }
-
- g_string_append(gstr, FB_API_SECRET);
- data = g_compute_checksum_for_string(G_CHECKSUM_MD5, gstr->str,
- gstr->len);
- fb_http_params_set_str(params, "sig", data);
- g_string_free(gstr, TRUE);
- g_list_free(keys);
- g_free(data);
-
- msg = soup_message_new_from_encoded_form("POST", url, soup_form_encode_hash(params));
- fb_http_params_free(params);
-
- if (api->token != NULL) {
- data = g_strdup_printf("OAuth %s", api->token);
- soup_message_headers_replace(soup_message_get_request_headers(msg),
- "Authorization", data);
- g_free(data);
- }
-
- g_object_set_data(G_OBJECT(msg), "facebook-api", api);
- soup_session_send_and_read_async(api->cons, msg, G_PRIORITY_DEFAULT, NULL,
- callback, msg);
-
- fb_util_debug(FB_UTIL_DEBUG_INFO, "HTTP Request (%p):", msg);
- fb_util_debug(FB_UTIL_DEBUG_INFO, " Request URL: %s", url);
-
- return msg;
-}
-
-static SoupMessage *
-fb_api_http_query(FbApi *api, gint64 query, JsonBuilder *builder,
- GAsyncReadyCallback hcb)
-{
- const gchar *name;
- FbHttpParams *prms;
- gchar *json;
-
- switch (query) {
- case FB_API_QUERY_CONTACT:
- name = "UsersQuery";
- break;
- case FB_API_QUERY_CONTACTS:
- name = "FetchContactsFullQuery";
- break;
- case FB_API_QUERY_CONTACTS_AFTER:
- name = "FetchContactsFullWithAfterQuery";
- break;
- case FB_API_QUERY_CONTACTS_DELTA:
- name = "FetchContactsDeltaQuery";
- break;
- case FB_API_QUERY_STICKER:
- name = "FetchStickersWithPreviewsQuery";
- break;
- case FB_API_QUERY_THREAD:
- name = "ThreadQuery";
- break;
- case FB_API_QUERY_SEQ_ID:
- case FB_API_QUERY_THREADS:
- name = "ThreadListQuery";
- break;
- case FB_API_QUERY_XMA:
- name = "XMAQuery";
- break;
- default:
- g_return_val_if_reached(NULL);
- return NULL;
- }
-
- prms = fb_http_params_new();
- json = fb_json_bldr_close(builder, JSON_NODE_OBJECT, NULL);
-
- fb_http_params_set_strf(prms, "query_id", "%" G_GINT64_FORMAT, query);
- fb_http_params_set_str(prms, "query_params", json);
- g_free(json);
-
- return fb_api_http_req(api, FB_API_URL_GQL, name, "get", prms, hcb);
-}
-
-static void
-fb_api_cb_http_bool(GObject *source, GAsyncResult *result, gpointer data) {
- SoupSession *session = SOUP_SESSION(source);
- SoupMessage *soupmsg = data;
- FbApi *api = g_object_get_data(G_OBJECT(soupmsg), "facebook-api");
- JsonNode *root;
-
- if (!fb_api_http_chk(api, session, result, soupmsg, &root)) {
- g_object_unref(soupmsg);
- return;
- }
-
- if (!json_node_get_boolean(root)) {
- fb_api_error_literal(api, FB_API_ERROR,
- _("Failed generic API operation"));
- }
-
- json_node_free(root);
- g_object_unref(soupmsg);
-}
-
-static void
-fb_api_cb_mqtt_error(G_GNUC_UNUSED FbMqtt *mqtt, GError *error, gpointer data)
-{
- FbApi *api = data;
-
- if (!api->retrying) {
- api->retrying = TRUE;
- fb_util_debug_info("Attempting to reconnect the MQTT stream...");
- fb_api_connect(api, api->invisible);
- } else {
- g_signal_emit_by_name(api, "error", error);
- }
-}
-
-static void
-fb_api_cb_mqtt_open(FbMqtt *mqtt, gpointer data)
-{
- const GByteArray *bytes;
- FbApi *api = data;
- FbThrift *thft;
- GByteArray *cytes;
- GError *err = NULL;
-
- static guint8 flags = FB_MQTT_CONNECT_FLAG_USER |
- FB_MQTT_CONNECT_FLAG_PASS |
- FB_MQTT_CONNECT_FLAG_CLR;
-
- thft = fb_thrift_new(NULL, 0);
-
- /* Write the client identifier */
- fb_thrift_write_field(thft, FB_THRIFT_TYPE_STRING, 1, 0);
- fb_thrift_write_str(thft, api->cid);
-
- fb_thrift_write_field(thft, FB_THRIFT_TYPE_STRUCT, 4, 1);
-
- /* Write the user identifier */
- fb_thrift_write_field(thft, FB_THRIFT_TYPE_I64, 1, 0);
- fb_thrift_write_i64(thft, api->uid);
-
- /* Write the information string */
- fb_thrift_write_field(thft, FB_THRIFT_TYPE_STRING, 2, 1);
- fb_thrift_write_str(thft, FB_API_MQTT_AGENT);
-
- /* Write the UNKNOWN ("cp"?) */
- fb_thrift_write_field(thft, FB_THRIFT_TYPE_I64, 3, 2);
- fb_thrift_write_i64(thft, 23);
-
- /* Write the UNKNOWN ("ecp"?) */
- fb_thrift_write_field(thft, FB_THRIFT_TYPE_I64, 4, 3);
- fb_thrift_write_i64(thft, 26);
-
- /* Write the UNKNOWN */
- fb_thrift_write_field(thft, FB_THRIFT_TYPE_I32, 5, 4);
- fb_thrift_write_i32(thft, 1);
-
- /* Write the UNKNOWN ("no_auto_fg"?) */
- fb_thrift_write_field(thft, FB_THRIFT_TYPE_BOOL, 6, 5);
- fb_thrift_write_bool(thft, TRUE);
-
- /* Write the visibility state */
- fb_thrift_write_field(thft, FB_THRIFT_TYPE_BOOL, 7, 6);
- fb_thrift_write_bool(thft, !api->invisible);
-
- /* Write the device identifier */
- fb_thrift_write_field(thft, FB_THRIFT_TYPE_STRING, 8, 7);
- fb_thrift_write_str(thft, api->did);
-
- /* Write the UNKNOWN ("fg"?) */
- fb_thrift_write_field(thft, FB_THRIFT_TYPE_BOOL, 9, 8);
- fb_thrift_write_bool(thft, TRUE);
-
- /* Write the UNKNOWN ("nwt"?) */
- fb_thrift_write_field(thft, FB_THRIFT_TYPE_I32, 10, 9);
- fb_thrift_write_i32(thft, 1);
-
- /* Write the UNKNOWN ("nwst"?) */
- fb_thrift_write_field(thft, FB_THRIFT_TYPE_I32, 11, 10);
- fb_thrift_write_i32(thft, 0);
-
- /* Write the MQTT identifier */
- fb_thrift_write_field(thft, FB_THRIFT_TYPE_I64, 12, 11);
- fb_thrift_write_i64(thft, api->mid);
-
- /* Write the UNKNOWN */
- fb_thrift_write_field(thft, FB_THRIFT_TYPE_LIST, 14, 12);
- fb_thrift_write_list(thft, FB_THRIFT_TYPE_I32, 0);
- fb_thrift_write_stop(thft);
-
- /* Write the token */
- fb_thrift_write_field(thft, FB_THRIFT_TYPE_STRING, 15, 14);
- fb_thrift_write_str(thft, api->token);
-
- /* Write the STOP for the struct */
- fb_thrift_write_stop(thft);
-
- bytes = fb_thrift_get_bytes(thft);
- cytes = fb_util_zlib_deflate(bytes, &err);
-
- FB_API_ERROR_EMIT(api, err,
- g_object_unref(thft);
- return;
- );
-
- fb_util_debug_hexdump(FB_UTIL_DEBUG_INFO, bytes, "Writing connect");
- fb_mqtt_connect(mqtt, flags, cytes);
-
- g_byte_array_free(cytes, TRUE);
- g_object_unref(thft);
-}
-
-static void
-fb_api_connect_queue(FbApi *api)
-{
- FbApiMessage *msg;
- gchar *json;
- JsonBuilder *bldr;
-
- bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
- fb_json_bldr_add_int(bldr, "delta_batch_size", 125);
- fb_json_bldr_add_int(bldr, "max_deltas_able_to_process", 1250);
- fb_json_bldr_add_int(bldr, "sync_api_version", 3);
- fb_json_bldr_add_str(bldr, "encoding", "JSON");
-
- if (api->stoken == NULL) {
- fb_json_bldr_add_int(bldr, "initial_titan_sequence_id", api->sid);
- fb_json_bldr_add_str(bldr, "device_id", api->did);
- fb_json_bldr_add_int(bldr, "entity_fbid", api->uid);
-
- fb_json_bldr_obj_begin(bldr, "queue_params");
- fb_json_bldr_add_str(bldr, "buzz_on_deltas_enabled", "false");
-
- fb_json_bldr_obj_begin(bldr, "graphql_query_hashes");
- fb_json_bldr_add_str(bldr, "xma_query_id",
- G_STRINGIFY(FB_API_QUERY_XMA));
- fb_json_bldr_obj_end(bldr);
-
- fb_json_bldr_obj_begin(bldr, "graphql_query_params");
- fb_json_bldr_obj_begin(bldr, G_STRINGIFY(FB_API_QUERY_XMA));
- fb_json_bldr_add_str(bldr, "xma_id", "<ID>");
- fb_json_bldr_obj_end(bldr);
- fb_json_bldr_obj_end(bldr);
- fb_json_bldr_obj_end(bldr);
-
- json = fb_json_bldr_close(bldr, JSON_NODE_OBJECT, NULL);
- fb_api_publish(api, "/messenger_sync_create_queue", "%s",
- json);
- g_free(json);
- return;
- }
-
- fb_json_bldr_add_int(bldr, "last_seq_id", api->sid);
- fb_json_bldr_add_str(bldr, "sync_token", api->stoken);
-
- json = fb_json_bldr_close(bldr, JSON_NODE_OBJECT, NULL);
- fb_api_publish(api, "/messenger_sync_get_diffs", "%s", json);
- g_signal_emit_by_name(api, "connect");
- g_free(json);
-
- if (!g_queue_is_empty(api->msgs)) {
- msg = g_queue_peek_head(api->msgs);
- fb_api_message_send(api, msg);
- }
-
- if (api->retrying) {
- api->retrying = FALSE;
- fb_util_debug_info("Reconnected the MQTT stream");
- }
-}
-
-static void
-fb_api_cb_seqid(GObject *source, GAsyncResult *result, gpointer data) {
- SoupSession *session = SOUP_SESSION(source);
- SoupMessage *soupmsg = data;
- FbApi *api = g_object_get_data(G_OBJECT(soupmsg), "facebook-api");
- const gchar *str;
- FbJsonValues *values;
- GError *err = NULL;
- JsonNode *root;
-
- if (!fb_api_http_chk(api, session, result, soupmsg, &root)) {
- g_object_unref(soupmsg);
- return;
- }
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.viewer.message_threads.sync_sequence_id");
- fb_json_values_add(values, FB_JSON_TYPE_INT, TRUE,
- "$.viewer.message_threads.unread_count");
- fb_json_values_update(values, &err);
-
- FB_API_ERROR_EMIT(api, err,
- g_object_unref(values);
- json_node_free(root);
- g_object_unref(soupmsg);
- return;
- );
-
- str = fb_json_values_next_str(values, "0");
- api->sid = g_ascii_strtoll(str, NULL, 10);
- api->unread = fb_json_values_next_int(values, 0);
-
- if (api->sid == 0) {
- fb_api_error_literal(api, FB_API_ERROR_GENERAL,
- _("Failed to get sync_sequence_id"));
- } else {
- fb_api_connect_queue(api);
- }
-
- g_object_unref(values);
- json_node_free(root);
- g_object_unref(soupmsg);
-}
-
-static void
-fb_api_cb_mqtt_connect(FbMqtt *mqtt, gpointer data)
-{
- FbApi *api = data;
- gchar *json;
- JsonBuilder *bldr;
-
- bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
- fb_json_bldr_add_bool(bldr, "foreground", TRUE);
- fb_json_bldr_add_int(bldr, "keepalive_timeout", FB_MQTT_KA);
-
- json = fb_json_bldr_close(bldr, JSON_NODE_OBJECT, NULL);
- fb_api_publish(api, "/foreground_state", "%s", json);
- g_free(json);
-
- fb_mqtt_subscribe(mqtt,
- "/inbox", 0,
- "/mercury", 0,
- "/messaging_events", 0,
- "/orca_presence", 0,
- "/orca_typing_notifications", 0,
- "/pp", 0,
- "/t_ms", 0,
- "/t_p", 0,
- "/t_rtc", 0,
- "/webrtc", 0,
- "/webrtc_response", 0,
- NULL
- );
-
- /* Notifications seem to lead to some sort of sending rate limit */
- fb_mqtt_unsubscribe(mqtt, "/orca_message_notifications", NULL);
-
- if (api->sid == 0) {
- bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
- fb_json_bldr_add_str(bldr, "1", "0");
- fb_api_http_query(api, FB_API_QUERY_SEQ_ID, bldr,
- fb_api_cb_seqid);
- } else {
- fb_api_connect_queue(api);
- }
-}
-
-static void
-fb_api_cb_publish_mark(FbApi *api, GByteArray *pload)
-{
- FbJsonValues *values;
- GError *err = NULL;
- JsonNode *root;
-
- if (!fb_api_json_chk(api, pload->data, pload->len, &root)) {
- return;
- }
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_BOOL, FALSE, "$.succeeded");
- fb_json_values_update(values, &err);
-
- FB_API_ERROR_EMIT(api, err,
- g_object_unref(values);
- json_node_free(root);
- return;
- );
-
- if (!fb_json_values_next_bool(values, TRUE)) {
- fb_api_error_literal(api, FB_API_ERROR_GENERAL,
- _("Failed to mark thread as read"));
- }
-
- g_object_unref(values);
- json_node_free(root);
-}
-
-static GSList *
-fb_api_event_parse(G_GNUC_UNUSED FbApi *api, FbApiEvent *event, GSList *events,
- JsonNode *root, GError **error)
-{
- const gchar *str;
- FbApiEvent *devent;
- FbJsonValues *values;
- GError *err = NULL;
- guint i;
-
- static const struct {
- FbApiEventType type;
- const gchar *expr;
- } evtypes[] = {
- {
- FB_API_EVENT_TYPE_THREAD_USER_ADDED,
- "$.log_message_data.added_participants"
- }, {
- FB_API_EVENT_TYPE_THREAD_USER_REMOVED,
- "$.log_message_data.removed_participants"
- }
- };
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.log_message_type");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.author");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.log_message_data.name");
- fb_json_values_update(values, &err);
-
- if (G_UNLIKELY(err != NULL)) {
- g_propagate_error(error, err);
- g_object_unref(values);
- return events;
- }
-
- str = fb_json_values_next_str(values, NULL);
-
- if (g_strcmp0(str, "log:thread-name") == 0) {
- str = fb_json_values_next_str(values, "");
- str = strrchr(str, ':');
-
- if (str != NULL) {
- devent = g_new(FbApiEvent, 1);
- devent->type = FB_API_EVENT_TYPE_THREAD_TOPIC;
- devent->uid = FB_ID_FROM_STR(str + 1);
- devent->tid = event->tid;
- devent->text = fb_json_values_next_str_dup(values, NULL);
- events = g_slist_prepend(events, devent);
- }
- }
-
- g_object_unref(values);
-
- for (i = 0; i < G_N_ELEMENTS(evtypes); i++) {
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, "$");
- fb_json_values_set_array(values, FALSE, evtypes[i].expr);
-
- while (fb_json_values_update(values, &err)) {
- str = fb_json_values_next_str(values, "");
- str = strrchr(str, ':');
-
- if (str != NULL) {
- devent = g_new0(FbApiEvent, 1);
- devent->type = evtypes[i].type;
- devent->uid = FB_ID_FROM_STR(str + 1);
- devent->tid = event->tid;
- events = g_slist_prepend(events, devent);
- }
- }
-
- g_object_unref(values);
-
- if (G_UNLIKELY(err != NULL)) {
- g_propagate_error(error, err);
- break;
- }
- }
-
- return events;
-}
-
-static void
-fb_api_cb_publish_mercury(FbApi *api, GByteArray *pload)
-{
- const gchar *str;
- FbApiEvent event;
- FbJsonValues *values;
- GError *err = NULL;
- GSList *events = NULL;
- JsonNode *root;
- JsonNode *node;
-
- if (!fb_api_json_chk(api, pload->data, pload->len, &root)) {
- return;
- }
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, "$.thread_fbid");
- fb_json_values_set_array(values, FALSE, "$.actions");
-
- while (fb_json_values_update(values, &err)) {
- fb_api_event_reset(&event, FALSE);
- str = fb_json_values_next_str(values, "0");
- event.tid = FB_ID_FROM_STR(str);
-
- node = fb_json_values_get_root(values);
- events = fb_api_event_parse(api, &event, events, node, &err);
- }
-
- if (G_LIKELY(err == NULL)) {
- events = g_slist_reverse(events);
- g_signal_emit_by_name(api, "events", events);
- } else {
- fb_api_error_emit(api, err);
- }
-
- g_slist_free_full(events, (GDestroyNotify) fb_api_event_free);
- g_object_unref(values);
- json_node_free(root);
-
-}
-
-static void
-fb_api_cb_publish_typing(FbApi *api, GByteArray *pload)
-{
- const gchar *str;
- FbApiTyping typg;
- FbJsonValues *values;
- GError *err = NULL;
- JsonNode *root;
-
- if (!fb_api_json_chk(api, pload->data, pload->len, &root)) {
- return;
- }
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, "$.type");
- fb_json_values_add(values, FB_JSON_TYPE_INT, TRUE, "$.sender_fbid");
- fb_json_values_add(values, FB_JSON_TYPE_INT, TRUE, "$.state");
- fb_json_values_update(values, &err);
-
- FB_API_ERROR_EMIT(api, err,
- g_object_unref(values);
- json_node_free(root);
- return;
- );
-
- str = fb_json_values_next_str(values, NULL);
-
- if (g_ascii_strcasecmp(str, "typ") == 0) {
- typg.uid = fb_json_values_next_int(values, 0);
-
- if (typg.uid != api->uid) {
- typg.state = fb_json_values_next_int(values, 0);
- g_signal_emit_by_name(api, "typing", &typg);
- }
- }
-
- g_object_unref(values);
- json_node_free(root);
-}
-
-static void
-fb_api_cb_publish_ms_r(FbApi *api, GByteArray *pload)
-{
- FbApiMessage *msg;
- FbJsonValues *values;
- GError *err = NULL;
- JsonNode *root;
-
- if (!fb_api_json_chk(api, pload->data, pload->len, &root)) {
- return;
- }
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_BOOL, TRUE, "$.succeeded");
- fb_json_values_update(values, &err);
-
- FB_API_ERROR_EMIT(api, err,
- g_object_unref(values);
- json_node_free(root);
- return;
- );
-
- if (fb_json_values_next_bool(values, TRUE)) {
- /* Pop and free the successful message */
- msg = g_queue_pop_head(api->msgs);
- fb_api_message_free(msg);
-
- if (!g_queue_is_empty(api->msgs)) {
- msg = g_queue_peek_head(api->msgs);
- fb_api_message_send(api, msg);
- }
- } else {
- fb_api_error_literal(api, FB_API_ERROR_GENERAL,
- "Failed to send message");
- }
-
- g_object_unref(values);
- json_node_free(root);
-}
-
-static gchar *
-fb_api_xma_parse(G_GNUC_UNUSED FbApi *api, const char *body, JsonNode *root,
- GError **error)
-{
- const gchar *str;
- const gchar *url;
- FbHttpParams *params;
- FbJsonValues *values;
- gchar *text;
- GError *err = NULL;
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.story_attachment.target.__type__.name");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.story_attachment.url");
- fb_json_values_update(values, &err);
-
- if (G_UNLIKELY(err != NULL)) {
- g_propagate_error(error, err);
- g_object_unref(values);
- return NULL;
- }
-
- str = fb_json_values_next_str(values, NULL);
- url = fb_json_values_next_str(values, NULL);
-
- if ((str == NULL) || (url == NULL)) {
- text = g_strdup(_("<Unsupported Attachment>"));
- g_object_unref(values);
- return text;
- }
-
- if (purple_strequal(str, "ExternalUrl")) {
- params = fb_http_params_new_parse(url, TRUE);
- if (g_str_has_prefix(url, FB_API_FBRPC_PREFIX)) {
- text = fb_http_params_dup_str(params, "target_url", NULL);
- } else {
- text = fb_http_params_dup_str(params, "u", NULL);
- }
- fb_http_params_free(params);
- } else {
- text = g_strdup(url);
- }
-
- if (fb_http_urlcmp(body, text, FALSE)) {
- g_free(text);
- g_object_unref(values);
- return NULL;
- }
-
- g_object_unref(values);
- return text;
-}
-
-static GSList *
-fb_api_message_parse_attach(FbApi *api, const gchar *mid, FbApiMessage *msg,
- GSList *msgs, const gchar *body, JsonNode *root,
- GError **error)
-{
- const gchar *str;
- FbApiMessage *dmsg;
- FbId id;
- FbJsonValues *values;
- gchar *xma;
- GError *err = NULL;
- JsonNode *node;
- JsonNode *xode;
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.xmaGraphQL");
- fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE, "$.fbid");
- fb_json_values_set_array(values, FALSE, "$.attachments");
-
- while (fb_json_values_update(values, &err)) {
- str = fb_json_values_next_str(values, NULL);
-
- if (str == NULL) {
- id = fb_json_values_next_int(values, 0);
- dmsg = g_memdup2(msg, sizeof(*msg));
- fb_api_attach(api, id, mid, dmsg);
- continue;
- }
-
- node = fb_json_node_new(str, -1, &err);
-
- if (G_UNLIKELY(err != NULL)) {
- break;
- }
-
- xode = fb_json_node_get_nth(node, 0);
- xma = fb_api_xma_parse(api, body, xode, &err);
-
- if (xma != NULL) {
- dmsg = g_memdup2(msg, sizeof(*msg));
- dmsg->text = xma;
- msgs = g_slist_prepend(msgs, dmsg);
- }
-
- json_node_free(node);
-
- if (G_UNLIKELY(err != NULL)) {
- break;
- }
- }
-
- if (G_UNLIKELY(err != NULL)) {
- g_propagate_error(error, err);
- }
-
- g_object_unref(values);
- return msgs;
-}
-
-
-static GSList *
-fb_api_cb_publish_ms_new_message(FbApi *api, JsonNode *root, GSList *msgs, GError **error);
-
-static GSList *
-fb_api_cb_publish_ms_event(FbApi *api, JsonNode *root, GSList *events, FbApiEventType type, GError **error);
-
-static void
-fb_api_cb_publish_mst(FbThrift *thft, GError **error)
-{
- if (fb_thrift_read_isstop(thft)) {
- FB_API_TCHK(fb_thrift_read_stop(thft));
- } else {
- FbThriftType type;
- gint16 id;
-
- FB_API_TCHK(fb_thrift_read_field(thft, &type, &id, 0));
- FB_API_TCHK(type == FB_THRIFT_TYPE_STRING);
- // FB_API_TCHK(id == 2);
- FB_API_TCHK(fb_thrift_read_str(thft, NULL));
- FB_API_TCHK(fb_thrift_read_stop(thft));
- }
-}
-
-static void
-fb_api_cb_publish_ms(FbApi *api, GByteArray *pload)
-{
- const gchar *data;
- FbJsonValues *values;
- FbThrift *thft;
- gchar *stoken;
- GError *err = NULL;
- GList *elms, *l;
- GSList *msgs = NULL;
- GSList *events = NULL;
- guint size;
- JsonNode *root;
- JsonNode *node;
- JsonArray *arr;
-
- static const struct {
- const gchar *member;
- FbApiEventType type;
- gboolean is_message;
- } event_types[] = {
- {"deltaNewMessage", 0, 1},
- {"deltaThreadName", FB_API_EVENT_TYPE_THREAD_TOPIC, 0},
- {"deltaParticipantsAddedToGroupThread", FB_API_EVENT_TYPE_THREAD_USER_ADDED, 0},
- {"deltaParticipantLeftGroupThread", FB_API_EVENT_TYPE_THREAD_USER_REMOVED, 0},
- };
-
- /* Read identifier string (for Facebook employees) */
- thft = fb_thrift_new(pload, 0);
- fb_api_cb_publish_mst(thft, &err);
- size = fb_thrift_get_pos(thft);
- g_object_unref(thft);
-
- FB_API_ERROR_EMIT(api, err,
- return;
- );
-
- g_return_if_fail(size < pload->len);
- data = (gchar *) pload->data + size;
- size = pload->len - size;
-
- if (!fb_api_json_chk(api, data, size, &root)) {
- return;
- }
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE,
- "$.lastIssuedSeqId");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.syncToken");
- fb_json_values_update(values, &err);
-
- FB_API_ERROR_EMIT(api, err,
- g_object_unref(values);
- json_node_free(root);
- return;
- );
-
- api->sid = fb_json_values_next_int(values, 0);
- stoken = fb_json_values_next_str_dup(values, NULL);
- g_object_unref(values);
-
- if (G_UNLIKELY(stoken != NULL)) {
- g_free(api->stoken);
- api->stoken = stoken;
- g_signal_emit_by_name(api, "connect");
- json_node_free(root);
- return;
- }
-
- arr = fb_json_node_get_arr(root, "$.deltas", NULL);
- elms = json_array_get_elements(arr);
-
- for (l = elms; l != NULL; l = l->next) {
- guint i = 0;
- JsonObject *o = json_node_get_object(l->data);
-
- for (i = 0; i < G_N_ELEMENTS(event_types); i++) {
- if ((node = json_object_get_member(o, event_types[i].member))) {
- if (event_types[i].is_message) {
- msgs = fb_api_cb_publish_ms_new_message(
- api, node, msgs, &err
- );
- } else {
- events = fb_api_cb_publish_ms_event(
- api, node, events, event_types[i].type, &err
- );
- }
- }
- }
-
- if (G_UNLIKELY(err != NULL)) {
- break;
- }
- }
-
- g_list_free(elms);
- json_array_unref(arr);
-
- if (G_LIKELY(err == NULL)) {
- if (msgs) {
- msgs = g_slist_reverse(msgs);
- g_signal_emit_by_name(api, "messages", msgs);
- }
-
- if (events) {
- events = g_slist_reverse(events);
- g_signal_emit_by_name(api, "events", events);
- }
- } else {
- fb_api_error_emit(api, err);
- }
-
- g_slist_free_full(msgs, (GDestroyNotify) fb_api_message_free);
- g_slist_free_full(events, (GDestroyNotify) fb_api_event_free);
- json_node_free(root);
-}
-
-static GSList *
-fb_api_cb_publish_ms_new_message(FbApi *api, JsonNode *root, GSList *msgs, GError **error)
-{
- const gchar *body;
- const gchar *str;
- GError *err = NULL;
- FbApiMessage *dmsg;
- FbApiMessage msg;
- FbId id;
- FbId oid;
- FbJsonValues *values;
- JsonNode *node;
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE,
- "$.messageMetadata.offlineThreadingId");
- fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE,
- "$.messageMetadata.actorFbId");
- fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE,
- "$.messageMetadata"
- ".threadKey.otherUserFbId");
- fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE,
- "$.messageMetadata"
- ".threadKey.threadFbId");
- fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE,
- "$.messageMetadata.timestamp");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.body");
- fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE,
- "$.stickerId");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.messageMetadata.messageId");
-
- if (fb_json_values_update(values, &err)) {
- id = fb_json_values_next_int(values, 0);
-
- /* Ignore everything but new messages */
- if (id == 0) {
- goto beach;
- }
-
- /* Ignore sequential duplicates */
- if (id == api->lastmid) {
- fb_util_debug_info("Ignoring duplicate %" FB_ID_FORMAT, id);
- goto beach;
- }
-
- api->lastmid = id;
- fb_api_message_reset(&msg, FALSE);
- msg.uid = fb_json_values_next_int(values, 0);
- oid = fb_json_values_next_int(values, 0);
- msg.tid = fb_json_values_next_int(values, 0);
- msg.tstamp = fb_json_values_next_int(values, 0);
-
- if (msg.uid == api->uid) {
- msg.flags |= FB_API_MESSAGE_FLAG_SELF;
-
- if (msg.tid == 0) {
- msg.uid = oid;
- }
- }
-
- body = fb_json_values_next_str(values, NULL);
-
- if (body != NULL) {
- dmsg = g_memdup2(&msg, sizeof(msg));
- dmsg->text = g_strdup(body);
- msgs = g_slist_prepend(msgs, dmsg);
- }
-
- id = fb_json_values_next_int(values, 0);
-
- if (id != 0) {
- dmsg = g_memdup2(&msg, sizeof(msg));
- fb_api_sticker(api, id, dmsg);
- }
-
- str = fb_json_values_next_str(values, NULL);
-
- if (str == NULL) {
- goto beach;
- }
-
- node = fb_json_values_get_root(values);
- msgs = fb_api_message_parse_attach(api, str, &msg, msgs, body,
- node, &err);
-
- if (G_UNLIKELY(err != NULL)) {
- g_propagate_error(error, err);
- goto beach;
- }
- }
-
-beach:
- g_object_unref(values);
- return msgs;
-}
-
-static GSList *
-fb_api_cb_publish_ms_event(G_GNUC_UNUSED FbApi *api, JsonNode *root,
- GSList *events, FbApiEventType type, GError **error)
-{
- FbApiEvent *event;
- FbJsonValues *values = NULL;
- FbJsonValues *values_inner = NULL;
- GError *err = NULL;
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE,
- "$.messageMetadata.threadKey.threadFbId");
- fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE,
- "$.messageMetadata.actorFbId");
-
- switch (type) {
- case FB_API_EVENT_TYPE_THREAD_TOPIC:
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.name");
- break;
-
- case FB_API_EVENT_TYPE_THREAD_USER_ADDED:
- values_inner = fb_json_values_new(root);
-
- fb_json_values_add(values_inner, FB_JSON_TYPE_INT, FALSE,
- "$.userFbId");
-
- /* use the text field for the full name */
- fb_json_values_add(values_inner, FB_JSON_TYPE_STR, FALSE,
- "$.fullName");
-
- fb_json_values_set_array(values_inner, FALSE,
- "$.addedParticipants");
- break;
-
- case FB_API_EVENT_TYPE_THREAD_USER_REMOVED:
- fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE,
- "$.leftParticipantFbId");
-
- /* use the text field for the kick message */
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.messageMetadata.adminText");
- break;
- }
-
- fb_json_values_update(values, &err);
-
- event = g_new0(FbApiEvent, 1);
- event->type = type;
- event->tid = fb_json_values_next_int(values, 0);
- event->uid = fb_json_values_next_int(values, 0);
-
- if (type == FB_API_EVENT_TYPE_THREAD_TOPIC) {
- event->text = fb_json_values_next_str_dup(values, NULL);
- } else if (type == FB_API_EVENT_TYPE_THREAD_USER_REMOVED) {
- /* overwrite actor with subject */
- event->uid = fb_json_values_next_int(values, 0);
- event->text = fb_json_values_next_str_dup(values, NULL);
- } else if (type == FB_API_EVENT_TYPE_THREAD_USER_ADDED) {
-
- while (fb_json_values_update(values_inner, &err)) {
- FbApiEvent *devent = g_new0(FbApiEvent, 1);
-
- devent->type = event->type;
- devent->uid = fb_json_values_next_int(values_inner, 0);
- devent->tid = event->tid;
- devent->text = fb_json_values_next_str_dup(values_inner, NULL);
-
- events = g_slist_prepend(events, devent);
- }
- g_clear_pointer(&event, fb_api_event_free);
- g_object_unref(values_inner);
- }
-
- g_object_unref(values);
-
- if (G_UNLIKELY(err != NULL)) {
- g_propagate_error(error, err);
- } else if (event) {
- events = g_slist_prepend(events, event);
- }
-
- return events;
-}
-
-static void
-fb_api_cb_publish_pt(FbThrift *thft, GSList **presences, GError **error)
-{
- FbApiPresence *api_presence;
- FbThriftType type;
- gint16 id;
- gint32 i32;
- gint64 i64;
- guint i;
- guint size = 0;
-
- /* Read identifier string (for Facebook employees) */
- FB_API_TCHK(fb_thrift_read_str(thft, NULL));
-
- /* Read the full list boolean field */
- FB_API_TCHK(fb_thrift_read_field(thft, &type, &id, 0));
- FB_API_TCHK(type == FB_THRIFT_TYPE_BOOL);
- FB_API_TCHK(id == 1);
- FB_API_TCHK(fb_thrift_read_bool(thft, NULL));
-
- /* Read the list field */
- FB_API_TCHK(fb_thrift_read_field(thft, &type, &id, id));
- FB_API_TCHK(type == FB_THRIFT_TYPE_LIST);
- FB_API_TCHK(id == 2);
-
- /* Read the list */
- FB_API_TCHK(fb_thrift_read_list(thft, &type, &size));
- FB_API_TCHK(type == FB_THRIFT_TYPE_STRUCT);
-
- for (i = 0; i < size; i++) {
- /* Read the user identifier field */
- FB_API_TCHK(fb_thrift_read_field(thft, &type, &id, 0));
- FB_API_TCHK(type == FB_THRIFT_TYPE_I64);
- FB_API_TCHK(id == 1);
- FB_API_TCHK(fb_thrift_read_i64(thft, &i64));
-
- /* Read the active field */
- FB_API_TCHK(fb_thrift_read_field(thft, &type, &id, id));
- FB_API_TCHK(type == FB_THRIFT_TYPE_I32);
- FB_API_TCHK(id == 2);
- FB_API_TCHK(fb_thrift_read_i32(thft, &i32));
-
- api_presence = g_new0(FbApiPresence, 1);
- api_presence->uid = i64;
- api_presence->active = i32 != 0;
- *presences = g_slist_prepend(*presences, api_presence);
-
- fb_util_debug_info("Presence: %" FB_ID_FORMAT " (%d) id: %d",
- i64, i32 != 0, id);
-
- while (id <= 6) {
- if (fb_thrift_read_isstop(thft)) {
- break;
- }
-
- FB_API_TCHK(fb_thrift_read_field(thft, &type, &id, id));
-
- switch (id) {
- case 3:
- /* Read the last active timestamp field */
- FB_API_TCHK(type == FB_THRIFT_TYPE_I64);
- FB_API_TCHK(fb_thrift_read_i64(thft, NULL));
- break;
-
- case 4:
- /* Read the active client bits field */
- FB_API_TCHK(type == FB_THRIFT_TYPE_I16);
- FB_API_TCHK(fb_thrift_read_i16(thft, NULL));
- break;
-
- case 5:
- /* Read the VoIP compatibility bits field */
- FB_API_TCHK(type == FB_THRIFT_TYPE_I64);
- FB_API_TCHK(fb_thrift_read_i64(thft, NULL));
- break;
-
- case 6:
- /* Unknown new field */
- FB_API_TCHK(type == FB_THRIFT_TYPE_I64);
- FB_API_TCHK(fb_thrift_read_i64(thft, NULL));
- break;
-
- default:
- /* Try to read unknown fields as varint */
- FB_API_TCHK(type == FB_THRIFT_TYPE_I16 ||
- type == FB_THRIFT_TYPE_I32 ||
- type == FB_THRIFT_TYPE_I64);
- FB_API_TCHK(fb_thrift_read_i64(thft, NULL));
- break;
- }
- }
-
- /* Read the field stop */
- FB_API_TCHK(fb_thrift_read_stop(thft));
- }
-
- /* Read the field stop */
- if (fb_thrift_read_isstop(thft)) {
- FB_API_TCHK(fb_thrift_read_stop(thft));
- }
-}
-
-static void
-fb_api_cb_publish_p(FbApi *api, GByteArray *pload)
-{
- FbThrift *thft;
- GError *err = NULL;
- GSList *presences = NULL;
-
- thft = fb_thrift_new(pload, 0);
- fb_api_cb_publish_pt(thft, &presences, &err);
- g_object_unref(thft);
-
- if (G_LIKELY(err == NULL)) {
- g_signal_emit_by_name(api, "presences", presences);
- } else {
- fb_api_error_emit(api, err);
- }
-
- g_slist_free_full(presences, (GDestroyNotify)fb_api_presence_free);
-}
-
-static void
-fb_api_cb_mqtt_publish(G_GNUC_UNUSED FbMqtt *mqtt, const char *topic,
- GByteArray *pload, gpointer data)
-{
- FbApi *api = data;
- gboolean comp;
- GByteArray *bytes;
- GError *err = NULL;
- guint i;
-
- static const struct {
- const gchar *topic;
- void (*func) (FbApi *api, GByteArray *pload);
- } parsers[] = {
- {"/mark_thread_response", fb_api_cb_publish_mark},
- {"/mercury", fb_api_cb_publish_mercury},
- {"/orca_typing_notifications", fb_api_cb_publish_typing},
- {"/send_message_response", fb_api_cb_publish_ms_r},
- {"/t_ms", fb_api_cb_publish_ms},
- {"/t_p", fb_api_cb_publish_p}
- };
-
- comp = fb_util_zlib_test(pload);
-
- if (G_LIKELY(comp)) {
- bytes = fb_util_zlib_inflate(pload, &err);
- FB_API_ERROR_EMIT(api, err, return);
- } else {
- bytes = (GByteArray *) pload;
- }
-
- fb_util_debug_hexdump(FB_UTIL_DEBUG_INFO, bytes,
- "Reading message (topic: %s)",
- topic);
-
- for (i = 0; i < G_N_ELEMENTS(parsers); i++) {
- if (g_ascii_strcasecmp(topic, parsers[i].topic) == 0) {
- parsers[i].func(api, bytes);
- break;
- }
- }
-
- if (G_LIKELY(comp)) {
- g_byte_array_free(bytes, TRUE);
- }
-}
-
-FbApi *
-fb_api_new(PurpleConnection *gc, GProxyResolver *resolver)
-{
- FbApi *api;
-
- api = g_object_new(FB_TYPE_API, NULL);
-
- api->gc = gc;
- api->cons = soup_session_new_with_options(
- "proxy-resolver", resolver,
- "user-agent", FB_API_AGENT,
- NULL);
- api->mqtt = fb_mqtt_new(gc);
-
- g_signal_connect(api->mqtt,
- "connect",
- G_CALLBACK(fb_api_cb_mqtt_connect),
- api);
- g_signal_connect(api->mqtt,
- "error",
- G_CALLBACK(fb_api_cb_mqtt_error),
- api);
- g_signal_connect(api->mqtt,
- "open",
- G_CALLBACK(fb_api_cb_mqtt_open),
- api);
- g_signal_connect(api->mqtt,
- "publish",
- G_CALLBACK(fb_api_cb_mqtt_publish),
- api);
-
- return api;
-}
-
-void
-fb_api_rehash(FbApi *api)
-{
- g_return_if_fail(FB_IS_API(api));
-
- if (api->cid == NULL) {
- api->cid = fb_util_rand_alnum(32);
- }
-
- if (api->did == NULL) {
- api->did = g_uuid_string_random();
- }
-
- if (api->mid == 0) {
- api->mid = g_random_int();
- }
-
- if (strlen(api->cid) > 20) {
- api->cid = g_realloc_n(api->cid , 21, sizeof *api->cid);
- api->cid[20] = 0;
- }
-}
-
-gboolean
-fb_api_is_invisible(FbApi *api)
-{
- g_return_val_if_fail(FB_IS_API(api), FALSE);
-
- return api->invisible;
-}
-
-static void
-fb_api_error_literal(FbApi *api, FbApiError error, const gchar *msg)
-{
- GError *err;
-
- g_return_if_fail(FB_IS_API(api));
-
- err = g_error_new_literal(FB_API_ERROR, error, msg);
-
- fb_api_error_emit(api, err);
-}
-
-void
-fb_api_error(FbApi *api, FbApiError error, const gchar *format, ...)
-{
- GError *err;
- va_list ap;
-
- g_return_if_fail(FB_IS_API(api));
-
- va_start(ap, format);
- err = g_error_new_valist(FB_API_ERROR, error, format, ap);
- va_end(ap);
-
- fb_api_error_emit(api, err);
-}
-
-void
-fb_api_error_emit(FbApi *api, GError *error)
-{
- g_return_if_fail(FB_IS_API(api));
- g_return_if_fail(error != NULL);
-
- g_signal_emit_by_name(api, "error", error);
- g_error_free(error);
-}
-
-static void
-fb_api_cb_attach(GObject *source, GAsyncResult *result, gpointer data) {
- SoupSession *session = SOUP_SESSION(source);
- SoupMessage *soupmsg = data;
- FbApi *api = g_object_get_data(G_OBJECT(soupmsg), "facebook-api");
- const gchar *str;
- FbApiMessage *msg;
- FbJsonValues *values;
- gchar *name;
- GError *err = NULL;
- GSList *msgs = NULL;
- guint i;
- JsonNode *root;
-
- static const gchar *imgexts[] = {".jpg", ".png", ".gif"};
-
- if (!fb_api_http_chk(api, session, result, soupmsg, &root)) {
- g_object_unref(soupmsg);
- return;
- }
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, "$.filename");
- fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, "$.redirect_uri");
- fb_json_values_update(values, &err);
-
- FB_API_ERROR_EMIT(api, err,
- g_object_unref(values);
- json_node_free(root);
- g_object_unref(soupmsg);
- return;
- );
-
- msg = g_object_steal_data(G_OBJECT(soupmsg), "fb-api-msg");
- str = fb_json_values_next_str(values, NULL);
- name = g_ascii_strdown(str, -1);
-
- for (i = 0; i < G_N_ELEMENTS(imgexts); i++) {
- if (g_str_has_suffix(name, imgexts[i])) {
- msg->flags |= FB_API_MESSAGE_FLAG_IMAGE;
- break;
- }
- }
-
- g_free(name);
- msg->text = fb_json_values_next_str_dup(values, NULL);
- msgs = g_slist_prepend(msgs, msg);
-
- g_signal_emit_by_name(api, "messages", msgs);
- g_slist_free_full(msgs, (GDestroyNotify) fb_api_message_free);
- g_object_unref(values);
- json_node_free(root);
- g_object_unref(soupmsg);
-}
-
-static void
-fb_api_attach(FbApi *api, FbId aid, const gchar *msgid, FbApiMessage *msg)
-{
- FbHttpParams *prms;
- SoupMessage *http;
-
- prms = fb_http_params_new();
- fb_http_params_set_str(prms, "mid", msgid);
- fb_http_params_set_strf(prms, "aid", "%" FB_ID_FORMAT, aid);
-
- http = fb_api_http_req(api, FB_API_URL_ATTACH, "getAttachment",
- "messaging.getAttachment", prms,
- fb_api_cb_attach);
- g_object_set_data_full(G_OBJECT(http), "fb-api-msg", msg,
- (GDestroyNotify)fb_api_message_free);
-}
-
-static void
-fb_api_cb_auth(GObject *source, GAsyncResult *result, gpointer data) {
- SoupSession *session = SOUP_SESSION(source);
- SoupMessage *soupmsg = data;
- FbApi *api = g_object_get_data(G_OBJECT(soupmsg), "facebook-api");
- FbJsonValues *values;
- GError *err = NULL;
- JsonNode *root;
-
- if (!fb_api_http_chk(api, session, result, soupmsg, &root)) {
- g_object_unref(soupmsg);
- return;
- }
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, "$.access_token");
- fb_json_values_add(values, FB_JSON_TYPE_INT, TRUE, "$.uid");
- fb_json_values_update(values, &err);
-
- FB_API_ERROR_EMIT(api, err,
- g_object_unref(values);
- json_node_free(root);
- g_object_unref(soupmsg);
- return;
- );
-
- g_free(api->token);
- api->token = fb_json_values_next_str_dup(values, NULL);
- api->uid = fb_json_values_next_int(values, 0);
-
- g_signal_emit_by_name(api, "auth");
- g_object_unref(values);
- json_node_free(root);
- g_object_unref(soupmsg);
-}
-
-void
-fb_api_auth(FbApi *api, const gchar *user, const gchar *pass)
-{
- FbHttpParams *prms;
-
- prms = fb_http_params_new();
- fb_http_params_set_str(prms, "email", user);
- fb_http_params_set_str(prms, "password", pass);
- fb_api_http_req(api, FB_API_URL_AUTH, "authenticate", "auth.login",
- prms, fb_api_cb_auth);
-}
-
-static gchar *
-fb_api_user_icon_checksum(gchar *icon)
-{
- gchar *csum;
- FbHttpParams *prms;
-
- if (G_UNLIKELY(icon == NULL)) {
- return NULL;
- }
-
- prms = fb_http_params_new_parse(icon, TRUE);
- csum = fb_http_params_dup_str(prms, "oh", NULL);
- fb_http_params_free(prms);
-
- if (G_UNLIKELY(csum == NULL)) {
- /* Revert to the icon URL as the unique checksum */
- csum = g_strdup(icon);
- }
-
- return csum;
-}
-
-static void
-fb_api_cb_contact(GObject *source, GAsyncResult *result, gpointer data) {
- SoupSession *session = SOUP_SESSION(source);
- SoupMessage *soupmsg = data;
- FbApi *api = g_object_get_data(G_OBJECT(soupmsg), "facebook-api");
- const gchar *str;
- FbApiUser user;
- FbJsonValues *values;
- GError *err = NULL;
- JsonNode *node;
- JsonNode *root;
-
- if (!fb_api_http_chk(api, session, result, soupmsg, &root)) {
- g_object_unref(soupmsg);
- return;
- }
-
- node = fb_json_node_get_nth(root, 0);
-
- if (node == NULL) {
- fb_api_error_literal(api, FB_API_ERROR_GENERAL,
- _("Failed to obtain contact information"));
- json_node_free(root);
- g_object_unref(soupmsg);
- return;
- }
-
- values = fb_json_values_new(node);
- fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, "$.id");
- fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, "$.name");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.profile_pic_large.uri");
- fb_json_values_update(values, &err);
-
- FB_API_ERROR_EMIT(api, err,
- g_object_unref(values);
- json_node_free(root);
- g_object_unref(soupmsg);
- return;
- );
-
- fb_api_user_reset(&user, FALSE);
- str = fb_json_values_next_str(values, "0");
- user.uid = FB_ID_FROM_STR(str);
- user.name = fb_json_values_next_str_dup(values, NULL);
- user.icon = fb_json_values_next_str_dup(values, NULL);
-
- user.csum = fb_api_user_icon_checksum(user.icon);
-
- g_signal_emit_by_name(api, "contact", &user);
- fb_api_user_reset(&user, TRUE);
- g_object_unref(values);
- json_node_free(root);
- g_object_unref(soupmsg);
-}
-
-void
-fb_api_contact(FbApi *api, FbId uid)
-{
- JsonBuilder *bldr;
-
- bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
- fb_json_bldr_arr_begin(bldr, "0");
- fb_json_bldr_add_strf(bldr, NULL, "%" FB_ID_FORMAT, uid);
- fb_json_bldr_arr_end(bldr);
-
- fb_json_bldr_add_str(bldr, "1", "true");
- fb_api_http_query(api, FB_API_QUERY_CONTACT, bldr, fb_api_cb_contact);
-}
-
-static GSList *
-fb_api_cb_contacts_nodes(FbApi *api, JsonNode *root, GSList *users)
-{
- const gchar *str;
- FbApiUser *user;
- FbId uid;
- FbJsonValues *values;
- gboolean is_array;
- GError *err = NULL;
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.represented_profile.id");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.represented_profile.friendship_status");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.structured_name.text");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.hugePictureUrl.uri");
-
- is_array = (JSON_NODE_TYPE(root) == JSON_NODE_ARRAY);
-
- if (is_array) {
- fb_json_values_set_array(values, FALSE, "$");
- }
-
- while (fb_json_values_update(values, &err)) {
- str = fb_json_values_next_str(values, "0");
- uid = FB_ID_FROM_STR(str);
- str = fb_json_values_next_str(values, NULL);
-
- if ((!purple_strequal(str, "ARE_FRIENDS") &&
- (uid != api->uid)) || (uid == 0))
- {
- if (!is_array) {
- break;
- }
- continue;
- }
-
- user = g_new0(FbApiUser, 1);
- user->uid = uid;
- user->name = fb_json_values_next_str_dup(values, NULL);
- user->icon = fb_json_values_next_str_dup(values, NULL);
-
- user->csum = fb_api_user_icon_checksum(user->icon);
-
- users = g_slist_prepend(users, user);
-
- if (!is_array) {
- break;
- }
- }
-
- g_object_unref(values);
-
- return users;
-}
-
-/* base64(contact:<our id>:<their id>:<whatever>) */
-static GSList *
-fb_api_cb_contacts_parse_removed(G_GNUC_UNUSED FbApi *api, JsonNode *node,
- GSList *users)
-{
- gsize len;
- char **split;
- char *decoded = (char *) g_base64_decode(json_node_get_string(node), &len);
-
- g_return_val_if_fail(decoded[len] == '\0', users);
- g_return_val_if_fail(len == strlen(decoded), users);
- g_return_val_if_fail(g_str_has_prefix(decoded, "contact:"), users);
-
- split = g_strsplit_set(decoded, ":", 4);
-
- if (g_strv_length(split) != 4) {
- g_strfreev(split);
- g_return_val_if_reached(users);
- }
-
- users = g_slist_prepend(users, g_strdup(split[2]));
-
- g_strfreev(split);
- g_free(decoded);
-
- return users;
-}
-
-static void
-fb_api_cb_contacts(GObject *source, GAsyncResult *result, gpointer data) {
- SoupSession *session = SOUP_SESSION(source);
- SoupMessage *soupmsg = data;
- FbApi *api = g_object_get_data(G_OBJECT(soupmsg), "facebook-api");
- const gchar *cursor;
- const gchar *delta_cursor;
- FbJsonValues *values;
- gboolean complete;
- gboolean is_delta;
- GError *err = NULL;
- GList *l;
- GSList *users = NULL;
- JsonNode *root;
- JsonNode *croot;
- JsonNode *node;
-
- if (!fb_api_http_chk(api, session, result, soupmsg, &root)) {
- g_object_unref(soupmsg);
- return;
- }
-
- croot = fb_json_node_get(root, "$.viewer.messenger_contacts.deltas", NULL);
- is_delta = (croot != NULL);
-
- if (!is_delta) {
- croot = fb_json_node_get(root, "$.viewer.messenger_contacts", NULL);
- node = fb_json_node_get(croot, "$.nodes", NULL);
- users = fb_api_cb_contacts_nodes(api, node, users);
- json_node_free(node);
-
- } else {
- GSList *added = NULL;
- GSList *removed = NULL;
- JsonArray *arr = fb_json_node_get_arr(croot, "$.nodes", NULL);
- GList *elms = json_array_get_elements(arr);
-
- for (l = elms; l != NULL; l = l->next) {
- if ((node = fb_json_node_get(l->data, "$.added", NULL))) {
- added = fb_api_cb_contacts_nodes(api, node, added);
- json_node_free(node);
- }
-
- if ((node = fb_json_node_get(l->data, "$.removed", NULL))) {
- removed = fb_api_cb_contacts_parse_removed(api, node, removed);
- json_node_free(node);
- }
- }
-
- g_signal_emit_by_name(api, "contacts-delta", added, removed);
-
- g_slist_free_full(added, (GDestroyNotify) fb_api_user_free);
- g_slist_free_full(removed, g_free);
-
- g_list_free(elms);
- json_array_unref(arr);
- }
-
- values = fb_json_values_new(croot);
- fb_json_values_add(values, FB_JSON_TYPE_BOOL, FALSE,
- "$.page_info.has_next_page");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.page_info.delta_cursor");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.page_info.end_cursor");
- fb_json_values_update(values, NULL);
-
- complete = !fb_json_values_next_bool(values, FALSE);
-
- delta_cursor = fb_json_values_next_str(values, NULL);
-
- cursor = fb_json_values_next_str(values, NULL);
-
- if (G_UNLIKELY(err == NULL)) {
- if (is_delta || complete) {
- g_free(api->contacts_delta);
- api->contacts_delta = g_strdup(is_delta ? cursor : delta_cursor);
- }
-
- if (users) {
- g_signal_emit_by_name(api, "contacts", users, complete);
- }
-
- if (!complete) {
- fb_api_contacts_after(api, cursor);
- }
- } else {
- fb_api_error_emit(api, err);
- }
-
- g_slist_free_full(users, (GDestroyNotify) fb_api_user_free);
- g_object_unref(values);
-
- json_node_free(croot);
- json_node_free(root);
- g_object_unref(soupmsg);
-}
-
-void
-fb_api_contacts(FbApi *api)
-{
- JsonBuilder *bldr;
-
- g_return_if_fail(FB_IS_API(api));
-
- if (api->contacts_delta) {
- fb_api_contacts_delta(api, api->contacts_delta);
- return;
- }
-
- bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
- fb_json_bldr_arr_begin(bldr, "0");
- fb_json_bldr_add_str(bldr, NULL, "user");
- fb_json_bldr_arr_end(bldr);
-
- fb_json_bldr_add_str(bldr, "1", G_STRINGIFY(FB_API_CONTACTS_COUNT));
- fb_api_http_query(api, FB_API_QUERY_CONTACTS, bldr,
- fb_api_cb_contacts);
-}
-
-static void
-fb_api_contacts_after(FbApi *api, const gchar *cursor)
-{
- JsonBuilder *bldr;
-
- bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
- fb_json_bldr_arr_begin(bldr, "0");
- fb_json_bldr_add_str(bldr, NULL, "user");
- fb_json_bldr_arr_end(bldr);
-
- fb_json_bldr_add_str(bldr, "1", cursor);
- fb_json_bldr_add_str(bldr, "2", G_STRINGIFY(FB_API_CONTACTS_COUNT));
- fb_api_http_query(api, FB_API_QUERY_CONTACTS_AFTER, bldr,
- fb_api_cb_contacts);
-}
-
-void
-fb_api_contacts_delta(FbApi *api, const gchar *delta_cursor)
-{
- JsonBuilder *bldr;
-
- bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
-
- fb_json_bldr_add_str(bldr, "0", delta_cursor);
-
- fb_json_bldr_arr_begin(bldr, "1");
- fb_json_bldr_add_str(bldr, NULL, "user");
- fb_json_bldr_arr_end(bldr);
-
- fb_json_bldr_add_str(bldr, "2", G_STRINGIFY(FB_API_CONTACTS_COUNT));
- fb_api_http_query(api, FB_API_QUERY_CONTACTS_DELTA, bldr,
- fb_api_cb_contacts);
-}
-
-void
-fb_api_connect(FbApi *api, gboolean invisible)
-{
- g_return_if_fail(FB_IS_API(api));
-
- api->invisible = invisible;
- fb_mqtt_open(api->mqtt, FB_MQTT_HOST, FB_MQTT_PORT);
-}
-
-void
-fb_api_disconnect(FbApi *api)
-{
- g_return_if_fail(FB_IS_API(api));
-
- fb_mqtt_disconnect(api->mqtt);
-}
-
-static void
-fb_api_message_send(FbApi *api, FbApiMessage *msg)
-{
- const gchar *tpfx;
- FbId id;
- FbId mid;
- gchar *json;
- JsonBuilder *bldr;
-
- mid = FB_API_MSGID(g_get_real_time() / 1000, g_random_int());
- api->lastmid = mid;
-
- if (msg->tid != 0) {
- tpfx = "tfbid_";
- id = msg->tid;
- } else {
- tpfx = "";
- id = msg->uid;
- }
-
- bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
- fb_json_bldr_add_str(bldr, "body", msg->text);
- fb_json_bldr_add_strf(bldr, "msgid", "%" FB_ID_FORMAT, mid);
- fb_json_bldr_add_strf(bldr, "sender_fbid", "%" FB_ID_FORMAT, api->uid);
- fb_json_bldr_add_strf(bldr, "to", "%s%" FB_ID_FORMAT, tpfx, id);
-
- json = fb_json_bldr_close(bldr, JSON_NODE_OBJECT, NULL);
- fb_api_publish(api, "/send_message2", "%s", json);
- g_free(json);
-}
-
-void
-fb_api_message(FbApi *api, FbId id, gboolean thread, const gchar *text)
-{
- FbApiMessage *msg;
- gboolean empty;
-
- g_return_if_fail(FB_IS_API(api));
- g_return_if_fail(text != NULL);
-
- msg = g_new0(FbApiMessage, 1);
- msg->text = g_strdup(text);
-
- if (thread) {
- msg->tid = id;
- } else {
- msg->uid = id;
- }
-
- empty = g_queue_is_empty(api->msgs);
- g_queue_push_tail(api->msgs, msg);
-
- if (empty && fb_mqtt_connected(api->mqtt, FALSE)) {
- fb_api_message_send(api, msg);
- }
-}
-
-void
-fb_api_publish(FbApi *api, const gchar *topic, const gchar *format, ...)
-{
- GByteArray *bytes;
- GByteArray *cytes;
- gchar *msg;
- GError *err = NULL;
- va_list ap;
-
- g_return_if_fail(FB_IS_API(api));
- g_return_if_fail(topic != NULL);
- g_return_if_fail(format != NULL);
-
- va_start(ap, format);
- msg = g_strdup_vprintf(format, ap);
- va_end(ap);
-
- bytes = g_byte_array_new_take((guint8 *) msg, strlen(msg));
- cytes = fb_util_zlib_deflate(bytes, &err);
-
- FB_API_ERROR_EMIT(api, err,
- g_byte_array_free(bytes, TRUE);
- return;
- );
-
- fb_util_debug_hexdump(FB_UTIL_DEBUG_INFO, bytes,
- "Writing message (topic: %s)",
- topic);
-
- fb_mqtt_publish(api->mqtt, topic, cytes);
- g_byte_array_free(cytes, TRUE);
- g_byte_array_free(bytes, TRUE);
-}
-
-void
-fb_api_read(FbApi *api, FbId id, gboolean thread)
-{
- const gchar *key;
- gchar *json;
- JsonBuilder *bldr;
-
- g_return_if_fail(FB_IS_API(api));
-
- bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
- fb_json_bldr_add_bool(bldr, "state", TRUE);
- fb_json_bldr_add_int(bldr, "syncSeqId", api->sid);
- fb_json_bldr_add_str(bldr, "mark", "read");
-
- key = thread ? "threadFbId" : "otherUserFbId";
- fb_json_bldr_add_strf(bldr, key, "%" FB_ID_FORMAT, id);
-
- json = fb_json_bldr_close(bldr, JSON_NODE_OBJECT, NULL);
- fb_api_publish(api, "/mark_thread", "%s", json);
- g_free(json);
-}
-
-static GSList *
-fb_api_cb_unread_parse_attach(FbApi *api, const gchar *mid, FbApiMessage *msg,
- GSList *msgs, JsonNode *root, GError **error)
-{
- const gchar *str;
- FbApiMessage *dmsg;
- FbId id;
- FbJsonValues *values;
- GError *err = NULL;
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE,
- "$.attachment_fbid");
- fb_json_values_set_array(values, FALSE, "$.blob_attachments");
-
- while (fb_json_values_update(values, &err)) {
- str = fb_json_values_next_str(values, NULL);
- id = FB_ID_FROM_STR(str);
- dmsg = g_memdup2(msg, sizeof(*msg));
- fb_api_attach(api, id, mid, dmsg);
- }
-
- if (G_UNLIKELY(err != NULL)) {
- g_propagate_error(error, err);
- }
-
- g_object_unref(values);
- return msgs;
-}
-
-static void
-fb_api_cb_unread_msgs(GObject *source, GAsyncResult *result, gpointer data) {
- SoupSession *session = SOUP_SESSION(source);
- SoupMessage *soupmsg = data;
- FbApi *api = g_object_get_data(G_OBJECT(soupmsg), "facebook-api");
- const gchar *body;
- const gchar *str;
- FbApiMessage *dmsg;
- FbApiMessage msg;
- FbId id;
- FbId tid;
- FbJsonValues *values;
- gchar *xma;
- GError *err = NULL;
- GSList *msgs = NULL;
- JsonNode *node;
- JsonNode *root;
- JsonNode *xode;
-
- if (!fb_api_http_chk(api, session, result, soupmsg, &root)) {
- g_object_unref(soupmsg);
- return;
- }
-
- node = fb_json_node_get_nth(root, 0);
-
- if (node == NULL) {
- fb_api_error_literal(api, FB_API_ERROR_GENERAL,
- _("Failed to obtain unread messages"));
- json_node_free(root);
- g_object_unref(soupmsg);
- return;
- }
-
- values = fb_json_values_new(node);
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.thread_key.thread_fbid");
- fb_json_values_update(values, &err);
-
- FB_API_ERROR_EMIT(api, err,
- g_object_unref(values);
- g_object_unref(soupmsg);
- return;
- );
-
- fb_api_message_reset(&msg, FALSE);
- str = fb_json_values_next_str(values, "0");
- tid = FB_ID_FROM_STR(str);
- g_object_unref(values);
-
- values = fb_json_values_new(node);
- fb_json_values_add(values, FB_JSON_TYPE_BOOL, TRUE, "$.unread");
- fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE,
- "$.message_sender.messaging_actor.id");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.message.text");
- fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE,
- "$.timestamp_precise");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.sticker.id");
- fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, "$.message_id");
- fb_json_values_set_array(values, FALSE, "$.messages.nodes");
-
- while (fb_json_values_update(values, &err)) {
- if (!fb_json_values_next_bool(values, FALSE)) {
- continue;
- }
-
- str = fb_json_values_next_str(values, "0");
- body = fb_json_values_next_str(values, NULL);
-
- fb_api_message_reset(&msg, FALSE);
- msg.uid = FB_ID_FROM_STR(str);
- msg.tid = tid;
-
- str = fb_json_values_next_str(values, "0");
- msg.tstamp = g_ascii_strtoll(str, NULL, 10);
-
- if (body != NULL) {
- dmsg = g_memdup2(&msg, sizeof(msg));
- dmsg->text = g_strdup(body);
- msgs = g_slist_prepend(msgs, dmsg);
- }
-
- str = fb_json_values_next_str(values, NULL);
-
- if (str != NULL) {
- dmsg = g_memdup2(&msg, sizeof(msg));
- id = FB_ID_FROM_STR(str);
- fb_api_sticker(api, id, dmsg);
- }
-
- node = fb_json_values_get_root(values);
- xode = fb_json_node_get(node, "$.extensible_attachment", NULL);
-
- if (xode != NULL) {
- xma = fb_api_xma_parse(api, body, xode, &err);
-
- if (xma != NULL) {
- dmsg = g_memdup2(&msg, sizeof(msg));
- dmsg->text = xma;
- msgs = g_slist_prepend(msgs, dmsg);
- }
-
- json_node_free(xode);
-
- if (G_UNLIKELY(err != NULL)) {
- break;
- }
- }
-
- str = fb_json_values_next_str(values, NULL);
-
- if (str == NULL) {
- continue;
- }
-
- msgs = fb_api_cb_unread_parse_attach(api, str, &msg, msgs,
- node, &err);
-
- if (G_UNLIKELY(err != NULL)) {
- break;
- }
- }
-
- if (G_UNLIKELY(err == NULL)) {
- msgs = g_slist_reverse(msgs);
- g_signal_emit_by_name(api, "messages", msgs);
- } else {
- fb_api_error_emit(api, err);
- }
-
- g_slist_free_full(msgs, (GDestroyNotify) fb_api_message_free);
- g_object_unref(values);
- json_node_free(root);
- g_object_unref(soupmsg);
-}
-
-static void
-fb_api_cb_unread(GObject *source, GAsyncResult *result, gpointer data) {
- SoupSession *session = SOUP_SESSION(source);
- SoupMessage *soupmsg = data;
- FbApi *api = g_object_get_data(G_OBJECT(soupmsg), "facebook-api");
- const gchar *id;
- FbJsonValues *values;
- GError *err = NULL;
- gint64 count;
- JsonBuilder *bldr;
- JsonNode *root;
-
- if (!fb_api_http_chk(api, session, result, soupmsg, &root)) {
- g_object_unref(soupmsg);
- return;
- }
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_INT, TRUE, "$.unread_count");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.thread_key.other_user_id");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.thread_key.thread_fbid");
- fb_json_values_set_array(values, FALSE, "$.viewer.message_threads"
- ".nodes");
-
- while (fb_json_values_update(values, &err)) {
- count = fb_json_values_next_int(values, -5);
-
- if (count < 1) {
- continue;
- }
-
- id = fb_json_values_next_str(values, NULL);
-
- if (id == NULL) {
- id = fb_json_values_next_str(values, "0");
- }
-
- bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
- fb_json_bldr_arr_begin(bldr, "0");
- fb_json_bldr_add_str(bldr, NULL, id);
- fb_json_bldr_arr_end(bldr);
-
- fb_json_bldr_add_str(bldr, "10", "true");
- fb_json_bldr_add_str(bldr, "11", "true");
- fb_json_bldr_add_int(bldr, "12", count);
- fb_json_bldr_add_str(bldr, "13", "false");
- fb_api_http_query(api, FB_API_QUERY_THREAD, bldr,
- fb_api_cb_unread_msgs);
- }
-
- if (G_UNLIKELY(err != NULL)) {
- fb_api_error_emit(api, err);
- }
-
- g_object_unref(values);
- json_node_free(root);
- g_object_unref(soupmsg);
-}
-
-void
-fb_api_unread(FbApi *api)
-{
- JsonBuilder *bldr;
-
- g_return_if_fail(FB_IS_API(api));
-
- if (api->unread < 1) {
- return;
- }
-
- bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
- fb_json_bldr_add_str(bldr, "2", "true");
- fb_json_bldr_add_int(bldr, "1", api->unread);
- fb_json_bldr_add_str(bldr, "12", "true");
- fb_json_bldr_add_str(bldr, "13", "false");
- fb_api_http_query(api, FB_API_QUERY_THREADS, bldr,
- fb_api_cb_unread);
-}
-
-static void
-fb_api_cb_sticker(GObject *source, GAsyncResult *result, gpointer data) {
- SoupSession *session = SOUP_SESSION(source);
- SoupMessage *soupmsg = data;
- FbApi *api = g_object_get_data(G_OBJECT(soupmsg), "facebook-api");
- FbApiMessage *msg;
- FbJsonValues *values;
- GError *err = NULL;
- GSList *msgs = NULL;
- JsonNode *node;
- JsonNode *root;
-
- if (!fb_api_http_chk(api, session, result, soupmsg, &root)) {
- g_object_unref(soupmsg);
- return;
- }
-
- node = fb_json_node_get_nth(root, 0);
- values = fb_json_values_new(node);
- fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE,
- "$.thread_image.uri");
- fb_json_values_update(values, &err);
-
- FB_API_ERROR_EMIT(api, err,
- g_object_unref(values);
- json_node_free(root);
- g_object_unref(soupmsg);
- return;
- );
-
- msg = g_object_steal_data(G_OBJECT(soupmsg), "fb-api-msg");
- msg->flags |= FB_API_MESSAGE_FLAG_IMAGE;
- msg->text = fb_json_values_next_str_dup(values, NULL);
- msgs = g_slist_prepend(msgs, msg);
-
- g_signal_emit_by_name(api, "messages", msgs);
- g_slist_free_full(msgs, (GDestroyNotify) fb_api_message_free);
- g_object_unref(values);
- json_node_free(root);
- g_object_unref(soupmsg);
-}
-
-static void
-fb_api_sticker(FbApi *api, FbId sid, FbApiMessage *msg)
-{
- JsonBuilder *bldr;
- SoupMessage *http;
-
- bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
- fb_json_bldr_arr_begin(bldr, "0");
- fb_json_bldr_add_strf(bldr, NULL, "%" FB_ID_FORMAT, sid);
- fb_json_bldr_arr_end(bldr);
-
- http = fb_api_http_query(api, FB_API_QUERY_STICKER, bldr,
- fb_api_cb_sticker);
- g_object_set_data_full(G_OBJECT(http), "fb-api-msg", msg,
- (GDestroyNotify)fb_api_message_free);
-}
-
-static gboolean
-fb_api_thread_parse(FbApi *api, FbApiThread *thrd, JsonNode *root,
- GError **error)
-{
- const gchar *str;
- FbApiUser *user;
- FbId uid;
- FbJsonValues *values;
- gboolean haself = FALSE;
- guint num_users = 0;
- GError *err = NULL;
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
- "$.thread_key.thread_fbid");
- fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.name");
- fb_json_values_update(values, &err);
-
- if (G_UNLIKELY(err != NULL)) {
- g_propagate_error(error, err);
- g_object_unref(values);
- return FALSE;
- }
-
- str = fb_json_values_next_str(values, NULL);
-
- if (str == NULL) {
- g_object_unref(values);
- return FALSE;
- }
-
- thrd->tid = FB_ID_FROM_STR(str);
- thrd->topic = fb_json_values_next_str_dup(values, NULL);
- g_object_unref(values);
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE,
- "$.messaging_actor.id");
- fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE,
- "$.messaging_actor.name");
- fb_json_values_set_array(values, TRUE, "$.all_participants.nodes");
-
- while (fb_json_values_update(values, &err)) {
- str = fb_json_values_next_str(values, "0");
- uid = FB_ID_FROM_STR(str);
- num_users++;
-
- if (uid != api->uid) {
- user = g_new0(FbApiUser, 1);
- user->uid = uid;
- user->name = fb_json_values_next_str_dup(values, NULL);
- thrd->users = g_slist_prepend(thrd->users, user);
- } else {
- haself = TRUE;
- }
- }
-
- if (G_UNLIKELY(err != NULL)) {
- g_propagate_error(error, err);
- fb_api_thread_reset(thrd, TRUE);
- g_object_unref(values);
- return FALSE;
- }
-
- if (num_users < 2 || !haself) {
- g_object_unref(values);
- return FALSE;
- }
-
- g_object_unref(values);
- return TRUE;
-}
-
-static void
-fb_api_cb_thread(GObject *source, GAsyncResult *result, gpointer data) {
- SoupSession *session = SOUP_SESSION(source);
- SoupMessage *soupmsg = data;
- FbApi *api = g_object_get_data(G_OBJECT(soupmsg), "facebook-api");
- FbApiThread thrd;
- GError *err = NULL;
- JsonNode *node;
- JsonNode *root;
-
- if (!fb_api_http_chk(api, session, result, soupmsg, &root)) {
- g_object_unref(soupmsg);
- return;
- }
-
- node = fb_json_node_get_nth(root, 0);
-
- if (node == NULL) {
- fb_api_error_literal(api, FB_API_ERROR_GENERAL,
- _("Failed to obtain thread information"));
- json_node_free(root);
- g_object_unref(soupmsg);
- return;
- }
-
- fb_api_thread_reset(&thrd, FALSE);
-
- if (!fb_api_thread_parse(api, &thrd, node, &err)) {
- if (G_LIKELY(err == NULL)) {
- if (thrd.tid) {
- g_signal_emit_by_name(api, "thread-kicked", &thrd);
- } else {
- fb_api_error_literal(api, FB_API_ERROR_GENERAL,
- _("Failed to parse thread information"));
- }
- } else {
- fb_api_error_emit(api, err);
- }
- } else {
- g_signal_emit_by_name(api, "thread", &thrd);
- }
-
- fb_api_thread_reset(&thrd, TRUE);
- json_node_free(root);
- g_object_unref(soupmsg);
-}
-
-void
-fb_api_thread(FbApi *api, FbId tid)
-{
- JsonBuilder *bldr;
-
- bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
- fb_json_bldr_arr_begin(bldr, "0");
- fb_json_bldr_add_strf(bldr, NULL, "%" FB_ID_FORMAT, tid);
- fb_json_bldr_arr_end(bldr);
-
- fb_json_bldr_add_str(bldr, "10", "false");
- fb_json_bldr_add_str(bldr, "11", "false");
- fb_json_bldr_add_str(bldr, "13", "false");
- fb_api_http_query(api, FB_API_QUERY_THREAD, bldr, fb_api_cb_thread);
-}
-
-static void
-fb_api_cb_thread_create(GObject *source, GAsyncResult *result, gpointer data) {
- SoupSession *session = SOUP_SESSION(source);
- SoupMessage *soupmsg = data;
- FbApi *api = g_object_get_data(G_OBJECT(soupmsg), "facebook-api");
- const gchar *str;
- FbId tid;
- FbJsonValues *values;
- GError *err = NULL;
- JsonNode *root;
-
- if (!fb_api_http_chk(api, session, result, soupmsg, &root)) {
- g_object_unref(soupmsg);
- return;
- }
-
- values = fb_json_values_new(root);
- fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, "$.id");
- fb_json_values_update(values, &err);
-
- FB_API_ERROR_EMIT(api, err,
- g_object_unref(values);
- json_node_free(root);
- g_object_unref(soupmsg);
- return;
- );
-
- str = fb_json_values_next_str(values, "0");
- tid = FB_ID_FROM_STR(str);
- g_signal_emit_by_name(api, "thread-create", tid);
-
- g_object_unref(values);
- json_node_free(root);
- g_object_unref(soupmsg);
-}
-
-void
-fb_api_thread_create(FbApi *api, GSList *uids)
-{
- FbHttpParams *prms;
- FbId *uid;
- gchar *json;
- GSList *l;
- JsonBuilder *bldr;
-
- g_return_if_fail(FB_IS_API(api));
- g_warn_if_fail(g_slist_length(uids) > 1);
-
- bldr = fb_json_bldr_new(JSON_NODE_ARRAY);
- fb_json_bldr_obj_begin(bldr, NULL);
- fb_json_bldr_add_str(bldr, "type", "id");
- fb_json_bldr_add_strf(bldr, "id", "%" FB_ID_FORMAT, api->uid);
- fb_json_bldr_obj_end(bldr);
-
- for (l = uids; l != NULL; l = l->next) {
- uid = l->data;
- fb_json_bldr_obj_begin(bldr, NULL);
- fb_json_bldr_add_str(bldr, "type", "id");
- fb_json_bldr_add_strf(bldr, "id", "%" FB_ID_FORMAT, *uid);
- fb_json_bldr_obj_end(bldr);
- }
-
- json = fb_json_bldr_close(bldr, JSON_NODE_ARRAY, NULL);
- prms = fb_http_params_new();
- fb_http_params_set_str(prms, "recipients", json);
- fb_api_http_req(api, FB_API_URL_THREADS, "createGroup", "POST",
- prms, fb_api_cb_thread_create);
- g_free(json);
-}
-
-void
-fb_api_thread_invite(FbApi *api, FbId tid, FbId uid)
-{
- FbHttpParams *prms;
- gchar *json;
- JsonBuilder *bldr;
-
- bldr = fb_json_bldr_new(JSON_NODE_ARRAY);
- fb_json_bldr_obj_begin(bldr, NULL);
- fb_json_bldr_add_str(bldr, "type", "id");
- fb_json_bldr_add_strf(bldr, "id", "%" FB_ID_FORMAT, uid);
- fb_json_bldr_obj_end(bldr);
- json = fb_json_bldr_close(bldr, JSON_NODE_ARRAY, NULL);
-
- prms = fb_http_params_new();
- fb_http_params_set_str(prms, "to", json);
- fb_http_params_set_strf(prms, "id", "t_%" FB_ID_FORMAT, tid);
- fb_api_http_req(api, FB_API_URL_PARTS, "addMembers", "POST",
- prms, fb_api_cb_http_bool);
- g_free(json);
-}
-
-void
-fb_api_thread_remove(FbApi *api, FbId tid, FbId uid)
-{
- FbHttpParams *prms;
- gchar *json;
- JsonBuilder *bldr;
-
- g_return_if_fail(FB_IS_API(api));
-
- prms = fb_http_params_new();
- fb_http_params_set_strf(prms, "id", "t_%" FB_ID_FORMAT, tid);
-
- if (uid == 0) {
- uid = api->uid;
- }
-
- if (uid != api->uid) {
- bldr = fb_json_bldr_new(JSON_NODE_ARRAY);
- fb_json_bldr_add_strf(bldr, NULL, "%" FB_ID_FORMAT, uid);
- json = fb_json_bldr_close(bldr, JSON_NODE_ARRAY, NULL);
- fb_http_params_set_str(prms, "to", json);
- g_free(json);
- }
-
- fb_api_http_req(api, FB_API_URL_PARTS, "removeMembers", "DELETE",
- prms, fb_api_cb_http_bool);
-}
-
-void
-fb_api_thread_topic(FbApi *api, FbId tid, const gchar *topic)
-{
- FbHttpParams *prms;
-
- prms = fb_http_params_new();
- fb_http_params_set_str(prms, "name", topic);
- fb_http_params_set_int(prms, "tid", tid);
- fb_api_http_req(api, FB_API_URL_TOPIC, "setThreadName",
- "messaging.setthreadname", prms, fb_api_cb_http_bool);
-}
-
-static void
-fb_api_cb_threads(GObject *source, GAsyncResult *result, gpointer data) {
- SoupSession *session = SOUP_SESSION(source);
- SoupMessage *soupmsg = data;
- FbApi *api = g_object_get_data(G_OBJECT(soupmsg), "facebook-api");
- FbApiThread *dthrd;
- FbApiThread thrd;
- GError *err = NULL;
- GList *elms;
- GList *l;
- GSList *thrds = NULL;
- JsonArray *arr;
- JsonNode *root;
-
- if (!fb_api_http_chk(api, session, result, soupmsg, &root)) {
- g_object_unref(soupmsg);
- return;
- }
-
- arr = fb_json_node_get_arr(root, "$.viewer.message_threads.nodes",
- &err);
- FB_API_ERROR_EMIT(api, err,
- json_node_free(root);
- g_object_unref(soupmsg);
- return;
- );
-
- elms = json_array_get_elements(arr);
-
- for (l = elms; l != NULL; l = l->next) {
- fb_api_thread_reset(&thrd, FALSE);
-
- if (fb_api_thread_parse(api, &thrd, l->data, &err)) {
- dthrd = g_memdup2(&thrd, sizeof(thrd));
- thrds = g_slist_prepend(thrds, dthrd);
- } else {
- fb_api_thread_reset(&thrd, TRUE);
- }
-
- if (G_UNLIKELY(err != NULL)) {
- break;
- }
- }
-
- if (G_LIKELY(err == NULL)) {
- thrds = g_slist_reverse(thrds);
- g_signal_emit_by_name(api, "threads", thrds);
- } else {
- fb_api_error_emit(api, err);
- }
-
- g_slist_free_full(thrds, (GDestroyNotify) fb_api_thread_free);
- g_list_free(elms);
- json_array_unref(arr);
- json_node_free(root);
- g_object_unref(soupmsg);
-}
-
-void
-fb_api_threads(FbApi *api)
-{
- JsonBuilder *bldr;
-
- bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
- fb_json_bldr_add_str(bldr, "2", "true");
- fb_json_bldr_add_str(bldr, "12", "false");
- fb_json_bldr_add_str(bldr, "13", "false");
- fb_api_http_query(api, FB_API_QUERY_THREADS, bldr, fb_api_cb_threads);
-}
-
-void
-fb_api_typing(FbApi *api, FbId uid, gboolean state)
-{
- gchar *json;
- JsonBuilder *bldr;
-
- bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
- fb_json_bldr_add_int(bldr, "state", state != 0);
- fb_json_bldr_add_strf(bldr, "to", "%" FB_ID_FORMAT, uid);
-
- json = fb_json_bldr_close(bldr, JSON_NODE_OBJECT, NULL);
- fb_api_publish(api, "/typing", "%s", json);
- g_free(json);
-}
-
-FbApiEvent *
-fb_api_event_dup(const FbApiEvent *event)
-{
- FbApiEvent *ret;
-
- if (event == NULL) {
- return NULL;
- }
-
- ret = g_memdup2(event, sizeof *event);
- ret->text = g_strdup(event->text);
-
- return ret;
-}
-
-void
-fb_api_event_reset(FbApiEvent *event, gboolean deep)
-{
- g_return_if_fail(event != NULL);
-
- if (deep) {
- g_free(event->text);
- }
-
- memset(event, 0, sizeof *event);
-}
-
-void
-fb_api_event_free(FbApiEvent *event)
-{
- if (G_LIKELY(event != NULL)) {
- g_free(event->text);
- g_free(event);
- }
-}
-
-G_DEFINE_BOXED_TYPE(FbApiEvent, fb_api_event, fb_api_event_dup,
- fb_api_event_free)
-
-FbApiMessage *
-fb_api_message_dup(const FbApiMessage *msg)
-{
- FbApiMessage *ret;
-
- if (msg == NULL) {
- return NULL;
- }
-
- ret = g_memdup2(msg, sizeof *msg);
- ret->text = g_strdup(msg->text);
-
- return ret;
-}
-
-void
-fb_api_message_reset(FbApiMessage *msg, gboolean deep)
-{
- g_return_if_fail(msg != NULL);
-
- if (deep) {
- g_free(msg->text);
- }
-
- memset(msg, 0, sizeof *msg);
-}
-
-void
-fb_api_message_free(FbApiMessage *msg)
-{
- if (G_LIKELY(msg != NULL)) {
- g_free(msg->text);
- g_free(msg);
- }
-}
-
-G_DEFINE_BOXED_TYPE(FbApiMessage, fb_api_message, fb_api_message_dup,
- fb_api_message_free)
-
-FbApiPresence *
-fb_api_presence_dup(const FbApiPresence *presence)
-{
- return g_memdup2(presence, sizeof *presence);
-}
-
-void
-fb_api_presence_reset(FbApiPresence *presence)
-{
- g_return_if_fail(presence != NULL);
- memset(presence, 0, sizeof *presence);
-}
-
-void
-fb_api_presence_free(FbApiPresence *presence)
-{
- if (G_LIKELY(presence != NULL)) {
- g_free(presence);
- }
-}
-
-G_DEFINE_BOXED_TYPE(FbApiPresence, fb_api_presence, fb_api_presence_dup,
- fb_api_presence_free)
-
-FbApiThread *
-fb_api_thread_dup(const FbApiThread *thrd)
-{
- FbApiThread *ret;
-
- if (thrd == NULL) {
- return NULL;
- }
-
- ret = g_memdup2(thrd, sizeof *thrd);
- ret->topic = g_strdup(thrd->topic);
- ret->users = g_slist_copy_deep(thrd->users,
- (GCopyFunc)(GCallback)fb_api_user_dup,
- NULL);
-
- return ret;
-}
-
-void
-fb_api_thread_reset(FbApiThread *thrd, gboolean deep)
-{
- g_return_if_fail(thrd != NULL);
-
- if (deep) {
- g_slist_free_full(thrd->users, (GDestroyNotify) fb_api_user_free);
- g_free(thrd->topic);
- }
-
- memset(thrd, 0, sizeof *thrd);
-}
-
-void
-fb_api_thread_free(FbApiThread *thrd)
-{
- if (G_LIKELY(thrd != NULL)) {
- g_slist_free_full(thrd->users, (GDestroyNotify) fb_api_user_free);
- g_free(thrd->topic);
- g_free(thrd);
- }
-}
-
-G_DEFINE_BOXED_TYPE(FbApiThread, fb_api_thread, fb_api_thread_dup,
- fb_api_thread_free)
-
-FbApiTyping *
-fb_api_typing_dup(const FbApiTyping *typg)
-{
- return g_memdup2(typg, sizeof *typg);
-}
-
-void
-fb_api_typing_reset(FbApiTyping *typg)
-{
- g_return_if_fail(typg != NULL);
- memset(typg, 0, sizeof *typg);
-}
-
-void
-fb_api_typing_free(FbApiTyping *typg)
-{
- if (G_LIKELY(typg != NULL)) {
- g_free(typg);
- }
-}
-
-G_DEFINE_BOXED_TYPE(FbApiTyping, fb_api_typing, fb_api_typing_dup,
- fb_api_typing_free)
-
-FbApiUser *
-fb_api_user_dup(const FbApiUser *user)
-{
- FbApiUser *ret;
-
- if (user == NULL) {
- return NULL;
- }
-
- ret = g_memdup2(user, sizeof *user);
- ret->name = g_strdup(user->name);
- ret->icon = g_strdup(user->icon);
- ret->csum = g_strdup(user->csum);
-
- return ret;
-}
-
-void
-fb_api_user_reset(FbApiUser *user, gboolean deep)
-{
- g_return_if_fail(user != NULL);
-
- if (deep) {
- g_free(user->name);
- g_free(user->icon);
- g_free(user->csum);
- }
-
- memset(user, 0, sizeof *user);
-}
-
-void
-fb_api_user_free(FbApiUser *user)
-{
- if (G_LIKELY(user != NULL)) {
- g_free(user->name);
- g_free(user->icon);
- g_free(user->csum);
- g_free(user);
- }
-}
-
-G_DEFINE_BOXED_TYPE(FbApiUser, fb_api_user, fb_api_user_dup, fb_api_user_free)
diff --git a/libpurple/protocols/facebook/api.h b/libpurple/protocols/facebook/api.h
deleted file mode 100644
index 04a9dbb3ae..0000000000
--- a/libpurple/protocols/facebook/api.h
+++ /dev/null
@@ -1,1002 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#ifndef PURPLE_FACEBOOK_API_H
-#define PURPLE_FACEBOOK_API_H
-
-#include <glib.h>
-
-#include <purple.h>
-
-#include "http.h"
-#include "id.h"
-#include "mqtt.h"
-
-#define FB_TYPE_API fb_api_get_type()
-
-/**
- * FB_API_AHOST:
- *
- * The HTTP host for the Facebook API.
- */
-#define FB_API_AHOST "https://api.facebook.com"
-
-/**
- * FB_API_BHOST:
- *
- * The HTTP host for the Facebook BAPI.
- */
-#define FB_API_BHOST "https://b-api.facebook.com"
-
-/**
- * FB_API_GHOST:
- *
- * The HTTP host for the Facebook Graph API.
- */
-#define FB_API_GHOST "https://graph.facebook.com"
-
-/**
- * FB_API_WHOST:
- *
- * The HTTP host for the Facebook website.
- */
-#define FB_API_WHOST "https://www.facebook.com"
-
-/**
- * FB_API_FBRPC_PREFIX
- *
- * The fbrpc URL prefix used in links shared from the mobile app.
- */
-#define FB_API_FBRPC_PREFIX "fbrpc://facebook/nativethirdparty"
-
-/**
- * FB_API_KEY:
- *
- * The Facebook API key.
- */
-#define FB_API_KEY "256002347743983"
-
-/**
- * FB_API_SECRET:
- *
- * The Facebook API secret.
- */
-#define FB_API_SECRET "374e60f8b9bb6b8cbb30f78030438895"
-
-/**
- * FB_ORCA_AGENT
- *
- * The part of the user agent that looks like the official client, since the
- * server started checking this.
- */
-
-#define FB_ORCA_AGENT "[FBAN/Orca-Android;FBAV/537.0.0.31.101;FBPN/com.facebook.orca;FBLC/en_US;FBBV/52182662]"
-
-/**
- * FB_API_AGENT:
- *
- * The HTTP User-Agent header.
- */
-#define FB_API_AGENT "Facebook plugin / Purple / 0.9.5 " FB_ORCA_AGENT
-
-/**
- * FB_API_MQTT_AGENT
- *
- * The client information string sent in the MQTT CONNECT message
- */
-
-#define FB_API_MQTT_AGENT FB_API_AGENT
-
-/**
- * FB_API_URL_ATTACH:
- *
- * The URL for attachment URL requests.
- */
-#define FB_API_URL_ATTACH FB_API_AHOST "/method/messaging.getAttachment"
-//#define FB_API_URL_ATTACH FB_API_AHOST "/method/messaging.attachmentRedirect"
-
-/**
- * FB_API_URL_AUTH:
- *
- * The URL for authentication requests.
- */
-#define FB_API_URL_AUTH FB_API_BHOST "/method/auth.login"
-
-/**
- * FB_API_URL_GQL:
- *
- * The URL for GraphQL requests.
- */
-#define FB_API_URL_GQL FB_API_GHOST "/graphql"
-
-/**
- * FB_API_URL_MESSAGES:
- *
- * The URL for linking message threads.
- */
-#define FB_API_URL_MESSAGES FB_API_WHOST "/messages"
-
-/**
- * FB_API_URL_PARTS:
- *
- * The URL for participant management requests.
- */
-#define FB_API_URL_PARTS FB_API_GHOST "/participants"
-
-/**
- * FB_API_URL_THREADS:
- *
- * The URL for thread management requests.
- */
-#define FB_API_URL_THREADS FB_API_GHOST "/me/group_threads"
-
-/**
- * FB_API_URL_TOPIC:
- *
- * The URL for thread topic requests.
- */
-#define FB_API_URL_TOPIC FB_API_AHOST "/method/messaging.setthreadname"
-
-/**
- * FB_API_QUERY_CONTACT:
- *
- * The query hash for the `UsersQuery`.
- *
- * Key mapping:
- * 0: user_fbids
- * 1: include_full_user_info
- * 2: profile_pic_large_size
- * 3: profile_pic_medium_size
- * 4: profile_pic_small_size
- */
-#define FB_API_QUERY_CONTACT 10153915107411729
-
-/**
- * FB_API_QUERY_CONTACTS:
- *
- * The query hash for the `FetchContactsFullQuery`.
- *
- * Key mapping:
- * 0: profile_types
- * 1: limit
- * 2: big_img_size
- * 3: huge_img_size
- * 4: small_img_size
- */
-#define FB_API_QUERY_CONTACTS 10154444360806729
-
-/**
- * FB_API_QUERY_CONTACTS_AFTER:
- *
- * The query hash for the `FetchContactsFullWithAfterQuery`.
- *
- * Key mapping:
- * 0: profile_types
- * 1: after
- * 2: limit
- * 3: big_img_size
- * 4: huge_img_size
- * 5: small_img_size
- */
-#define FB_API_QUERY_CONTACTS_AFTER 10154444360816729
-
-
-/**
- * FB_API_QUERY_CONTACTS_DELTA:
- *
- * The query hash for the `FetchContactsDeltaQuery`.
- *
- * Key mapping:
- * 0: after
- * 1: profile_types
- * 2: limit
- * 3: big_img_size
- * 4: huge_img_size
- * 5: small_img_size
- */
-#define FB_API_QUERY_CONTACTS_DELTA 10154444360801729
-
-/**
- * FB_API_QUERY_STICKER:
- *
- * The query hash for the `FetchStickersWithPreviewsQuery`.
- *
- * Key mapping:
- * 0: sticker_ids
- * 1: media_type
- * 2: preview_size
- * 3: scaling_factor
- * 4: animated_media_type
- */
-#define FB_API_QUERY_STICKER 10152877994321729
-
-/**
- * FB_API_QUERY_THREAD:
- *
- * The query hash for the `ThreadQuery`.
- *
- * Key mapping:
- * 0: thread_ids
- * 1: verification_type
- * 2: hash_key
- * 3: small_preview_size
- * 4: large_preview_size
- * 5: item_count
- * 6: event_count
- * 7: full_screen_height
- * 8: full_screen_width
- * 9: medium_preview_size
- * 10: fetch_users_separately
- * 11: include_message_info
- * 12: msg_count
- * 13: include_full_user_info
- * 14: profile_pic_large_size
- * 15: profile_pic_medium_size
- * 16: profile_pic_small_size
- */
-#define FB_API_QUERY_THREAD 10153919752036729
-
-/**
- * FB_API_QUERY_THREADS:
- *
- * The query hash for the `ThreadListQuery`.
- *
- * Key mapping:
- * 0: folder_tag
- * 1: thread_count
- * 2: include_thread_info
- * 3: verification_type
- * 4: hash_key
- * 5: small_preview_size
- * 6: large_preview_size
- * 7: item_count
- * 8: event_count
- * 9: full_screen_height
- * 10: full_screen_width
- * 11: medium_preview_size
- * 12: fetch_users_separately
- * 13: include_message_info
- * 14: msg_count
- * 15: UNKNOWN
- * 16: profile_pic_large_size
- * 17: profile_pic_medium_size
- * 18: profile_pic_small_size
- */
-#define FB_API_QUERY_THREADS 10153919752026729
-
-/**
- * FB_API_QUERY_SEQ_ID:
- *
- * A variant of ThreadListQuery with sequence ID
- *
- * TODO: parameters.
- */
-
-#define FB_API_QUERY_SEQ_ID 10155268192741729
-
-/**
- * FB_API_QUERY_XMA:
- *
- * The query hash for the `XMAQuery`.
- *
- * Key mapping:
- * 0: xma_id
- */
-#define FB_API_QUERY_XMA 10153919431161729
-
-/**
- * FB_API_CONTACTS_COUNT:
- *
- * The maximum amount of contacts to fetch in a single request. If this
- * value is set too high, HTTP request will fail. This is due to the
- * request data being too large.
- */
-#define FB_API_CONTACTS_COUNT 500
-
-/**
- * FB_API_TCHK:
- * @e: The expression.
- *
- * Checks the Thrift related expression to ensure that it evaluates to
- * #TRUE. If the expression evaluates to #FALSE, a #GError is assigned
- * to the local `error` variable, then returns with no value.
- *
- * This macro is meant to only be used for Thrift related expressions,
- * where the calling function has a `void` return type. This macro also
- * requires the existence of a predefined `error` variable, which is a
- * pointer of a pointer to a #GError.
- */
-#define FB_API_TCHK(e) \
- G_STMT_START { \
- if (G_UNLIKELY(!(e))) { \
- g_set_error(error, FB_API_ERROR, FB_API_ERROR_GENERAL, \
- "Failed to read thrift: %s:%d " \
- "%s: assertion '%s' failed", \
- __FILE__, __LINE__, G_STRFUNC, #e); \
- return; \
- } \
- } G_STMT_END
-
-/**
- * FB_API_MSGID:
- * @m: The time in milliseconds.
- * @i: The random integer.
- *
- * Creates a 64-bit message identifier in the Facebook format.
- *
- * Returns: The message identifier.
- */
-#define FB_API_MSGID(m, i) ((guint64) ( \
- (((guint32) i) & 0x3FFFFF) | \
- (((guint64) m) << 22) \
- ))
-
-/**
- * FB_API_ERROR_EMIT:
- * @a: The #FbApi.
- * @e: The #FbApiError.
- * @c: The code to execute.
- *
- * Emits a #GError on behalf of the #FbApi.
- */
-#define FB_API_ERROR_EMIT(a, e, c) \
- G_STMT_START { \
- if (G_UNLIKELY((e) != NULL)) { \
- fb_api_error_emit(a, e); \
- {c;} \
- } \
- } G_STMT_END
-
-/**
- * FB_API_ERROR:
- *
- * The #GQuark of the domain of API errors.
- */
-#define FB_API_ERROR fb_api_error_quark()
-
-typedef struct _FbApiEvent FbApiEvent;
-typedef struct _FbApiMessage FbApiMessage;
-typedef struct _FbApiPresence FbApiPresence;
-typedef struct _FbApiThread FbApiThread;
-typedef struct _FbApiTyping FbApiTyping;
-typedef struct _FbApiUser FbApiUser;
-
-/**
- * FbApiError:
- * @FB_API_ERROR_GENERAL: General failure.
- * @FB_API_ERROR_AUTH: Authentication failure.
- * @FB_API_ERROR_QUEUE: Queue failure.
- * @FB_API_ERROR_NONFATAL: Other non-fatal errors.
- *
- * The error codes for the #FB_API_ERROR domain.
- */
-typedef enum
-{
- FB_API_ERROR_GENERAL,
- FB_API_ERROR_AUTH,
- FB_API_ERROR_QUEUE,
- FB_API_ERROR_NONFATAL
-} FbApiError;
-
-/**
- * FbApiEventType:
- * @FB_API_EVENT_TYPE_THREAD_TOPIC: The thread topic was changed.
- * @FB_API_EVENT_TYPE_THREAD_USER_ADDED: A thread user was added.
- * @FB_API_EVENT_TYPE_THREAD_USER_REMOVED: A thread user was removed.
- *
- * The #FbApiEvent types.
- */
-typedef enum
-{
- FB_API_EVENT_TYPE_THREAD_TOPIC,
- FB_API_EVENT_TYPE_THREAD_USER_ADDED,
- FB_API_EVENT_TYPE_THREAD_USER_REMOVED
-} FbApiEventType;
-
-/**
- * FbApiMessageFlags:
- * @FB_API_MESSAGE_FLAG_DONE: The text has been processed.
- * @FB_API_MESSAGE_FLAG_IMAGE: The text is a URL to an image.
- * @FB_API_MESSAGE_FLAG_SELF: The text is from the #FbApi user.
- *
- * The #FbApiMessage flags.
- */
-typedef enum
-{
- FB_API_MESSAGE_FLAG_DONE = 1 << 0,
- FB_API_MESSAGE_FLAG_IMAGE = 1 << 1,
- FB_API_MESSAGE_FLAG_SELF = 1 << 2
-} FbApiMessageFlags;
-
-#define FB_TYPE_API_EVENT (fb_api_event_get_type())
-
-/**
- * FbApiEvent:
- * @type: The #FbApiEventType.
- * @uid: The user #FbId.
- * @tid: The thread #FbId.
- * @text: The event text.
- *
- * Represents a Facebook update event.
- */
-struct _FbApiEvent
-{
- FbApiEventType type;
- FbId uid;
- FbId tid;
- gchar *text;
-};
-
-#define FB_TYPE_API_MESSAGE (fb_api_message_get_type())
-
-/**
- * FbApiMessage:
- * @flags: The #FbApiMessageFlags.
- * @uid: The user #FbId.
- * @tid: The thread #FbId.
- * @tstamp: The timestamp in milliseconds (UTC).
- * @text: The message text.
- *
- * Represents a Facebook user message.
- */
-struct _FbApiMessage
-{
- FbApiMessageFlags flags;
- FbId uid;
- FbId tid;
- gint64 tstamp;
- gchar *text;
-};
-
-#define FB_TYPE_API_PRESENCE (fb_api_presence_get_type())
-
-/**
- * FbApiPresence:
- * @uid: The user #FbId.
- * @active: #TRUE if the user is active, otherwise #FALSE.
- *
- * Represents a Facebook presence message.
- */
-struct _FbApiPresence
-{
- FbId uid;
- gboolean active;
-};
-
-#define FB_TYPE_API_THREAD (fb_api_thread_get_type())
-
-/**
- * FbApiThread:
- * @tid: The thread #FbId.
- * @topic: The topic.
- * @users: The #GSList of #FbApiUser's.
- *
- * Represents a Facebook message thread.
- */
-struct _FbApiThread
-{
- FbId tid;
- gchar *topic;
- GSList *users;
-};
-
-#define FB_TYPE_API_TYPING (fb_api_typing_get_type())
-
-/**
- * FbApiTyping:
- * @uid: The user #FbId.
- * @state: #TRUE if the user is typing, otherwise #FALSE.
- *
- * Represents a Facebook typing message.
- */
-struct _FbApiTyping
-{
- FbId uid;
- gboolean state;
-};
-
-#define FB_TYPE_API_USER (fb_api_user_get_type())
-
-/**
- * FbApiUser:
- * @uid: The user #FbId.
- * @name: The name of the user.
- * @icon: The icon URL.
- * @csum: The checksum of @icon.
- *
- * Represents a Facebook user.
- */
-struct _FbApiUser
-{
- FbId uid;
- gchar *name;
- gchar *icon;
- gchar *csum;
-};
-
-G_DECLARE_FINAL_TYPE(FbApi, fb_api, FB, API, GObject)
-
-/**
- * fb_api_error_quark:
- *
- * Gets the #GQuark of the domain of API errors.
- *
- * Returns: The #GQuark of the domain.
- */
-GQuark
-fb_api_error_quark(void);
-
-/**
- * fb_api_new:
- * @gc: The #PurpleConnection.
- * @resolver: The proxy resolver to use from the account.
- *
- * Creates a new #FbApi. The returned #FbApi should be freed with
- * #g_object_unref() when no longer needed.
- *
- * Returns: The new #FbApi.
- */
-FbApi *fb_api_new(PurpleConnection *gc, GProxyResolver *resolver);
-
-/**
- * fb_api_rehash:
- * @api: The #FbApi.
- *
- * Rehashes and updates internal data of the #FbApi. This should be
- * called whenever properties are modified.
- */
-void
-fb_api_rehash(FbApi *api);
-
-/**
- * fb_api_is_invisible:
- * @api: The #FbApi.
- *
- * Determines if the user of the #FbApi is invisible.
- *
- * Returns: #TRUE if the #FbApi user is invisible, otherwise #FALSE.
- */
-gboolean
-fb_api_is_invisible(FbApi *api);
-
-/**
- * fb_api_error:
- * @api: The #FbApi.
- * @error: The #FbApiError.
- * @format: The format string literal.
- * @...: The arguments for @format.
- *
- * Emits an #FbApiError.
- */
-void
-fb_api_error(FbApi *api, FbApiError error, const gchar *format, ...)
- G_GNUC_PRINTF(3, 4);
-
-/**
- * fb_api_error_emit:
- * @api: The #FbApi.
- * @error: The #GError.
- *
- * Emits a #GError on an #FbApiError.
- */
-void
-fb_api_error_emit(FbApi *api, GError *error);
-
-/**
- * fb_api_auth:
- * @api: The #FbApi.
- * @user: The Facebook user name, email, or phone number.
- * @pass: The Facebook password.
- *
- * Sends an authentication request to Facebook. This will obtain
- * session information, which is required for all other requests.
- */
-void
-fb_api_auth(FbApi *api, const gchar *user, const gchar *pass);
-
-/**
- * fb_api_contact:
- * @api: The #FbApi.
- * @uid: The user #FbId.
- *
- * Sends a contact request. This will obtain the general information of
- * a single contact.
- */
-void
-fb_api_contact(FbApi *api, FbId uid);
-
-/**
- * fb_api_contacts:
- * @api: The #FbApi.
- *
- * Sends a contacts request. This will obtain a full list of detailed
- * contact information about the friends of the #FbApi user.
- */
-void
-fb_api_contacts(FbApi *api);
-
-/**
- * fb_api_connect:
- * @api: The #FbApi.
- * @invisible: #TRUE to make the user invisible, otherwise #FALSE.
- *
- * Initializes and establishes the underlying MQTT connection.
- */
-void
-fb_api_connect(FbApi *api, gboolean invisible);
-
-/**
- * fb_api_disconnect:
- * @api: The #FbApi.
- *
- * Closes the underlying MQTT connection.
- */
-void
-fb_api_disconnect(FbApi *api);
-
-/**
- * fb_api_message:
- * @api: The #FbApi.
- * @id: The user or thread #FbId.
- * @thread: #TRUE if @id is a thread, otherwise #FALSE.
- * @text: The message text.
- *
- * Sends a message as the user of the #FbApi to a user or a thread.
- */
-void
-fb_api_message(FbApi *api, FbId id, gboolean thread, const gchar *text);
-
-/**
- * fb_api_publish:
- * @api: The #FbApi.
- * @topic: The topic.
- * @format: The format string literal.
- * @...: The arguments for @format.
- *
- * Publishes an MQTT message.
- */
-void
-fb_api_publish(FbApi *api, const gchar *topic, const gchar *format, ...)
- G_GNUC_PRINTF(3, 4);
-
-/**
- * fb_api_read:
- * @api: The #FbApi.
- * @id: The user or thread #FbId.
- * @thread: #TRUE if @id is a thread, otherwise #FALSE.
- *
- * Marks a message thread as read.
- */
-void
-fb_api_read(FbApi *api, FbId id, gboolean thread);
-
-/**
- * fb_api_unread:
- * @api: The #FbApi.
- *
- * Sends an unread message request.
- */
-void
-fb_api_unread(FbApi *api);
-
-/**
- * fb_api_thread:
- * @api: The #FbApi.
- * @tid: The thread #FbId.
- *
- * Sends a thread request. This will obtain the general information of
- * a single thread.
- */
-void
-fb_api_thread(FbApi *api, FbId tid);
-
-/**
- * fb_api_thread_create:
- * @api: The #FbApi.
- * @uids: (element-type FbId): The #GSList of #FbId's.
- *
- * Sends a thread creation request. In order to create a thread, there
- * must be at least two other users in @uids.
- */
-void
-fb_api_thread_create(FbApi *api, GSList *uids);
-
-/**
- * fb_api_thread_invite:
- * @api: The #FbApi.
- * @tid: The thread #FbId.
- * @uid: The user #FbId.
- *
- * Sends a thread user invitation request.
- */
-void
-fb_api_thread_invite(FbApi *api, FbId tid, FbId uid);
-
-/**
- * fb_api_thread_remove:
- * @api: The #FbApi.
- * @tid: The thread #FbId.
- * @uid: The user #FbId.
- *
- * Sends a thread user removal request.
- */
-void
-fb_api_thread_remove(FbApi *api, FbId tid, FbId uid);
-
-/**
- * fb_api_thread_topic:
- * @api: The #FbApi.
- * @tid: The thread #FbId.
- * @topic: The topic.
- *
- * Sends a thread topic change request.
- */
-void
-fb_api_thread_topic(FbApi *api, FbId tid, const gchar *topic);
-
-/**
- * fb_api_threads:
- * @api: The #FbApi.
- *
- * Sends a threads request. This will obtain a full list of detailed
- * thread information about the threads of the #FbApi user.
- */
-void
-fb_api_threads(FbApi *api);
-
-/**
- * fb_api_typing:
- * @api: The #FbApi.
- * @uid: The user #FbId.
- * @state: #TRUE if the #FbApi user is typing, otherwise #FALSE.
- *
- * Sends a typing state message for the user of the #FbApi.
- */
-void
-fb_api_typing(FbApi *api, FbId uid, gboolean state);
-
-/**
- * fb_api_event_get_type:
- *
- * Returns: The #GType for the #FbApiEvent boxed structure.
- */
-GType fb_api_event_get_type(void);
-
-/**
- * fb_api_event_dup:
- * @event: The #FbApiEvent or #NULL.
- *
- * Duplicates an #FbApiEvent. The returned #FbApiEvent should be freed with
- * #fb_api_event_free() when no longer needed.
- *
- * Returns: The new #FbApiEvent.
- */
-FbApiEvent *
-fb_api_event_dup(const FbApiEvent *event);
-
-/**
- * fb_api_event_reset:
- * @event: The #FbApiEvent.
- * @deep: #TRUE to free allocated data, otherwise #FALSE.
- *
- * Resets an #FbApiEvent.
- */
-void
-fb_api_event_reset(FbApiEvent *event, gboolean deep);
-
-/**
- * fb_api_event_free:
- * @event: The #FbApiEvent.
- *
- * Frees all memory used by the #FbApiEvent.
- */
-void
-fb_api_event_free(FbApiEvent *event);
-
-/**
- * fb_api_message_get_type:
- *
- * Returns: The #GType for the #FbApiMessage boxed structure.
- */
-GType fb_api_message_get_type(void);
-
-/**
- * fb_api_message_dup:
- * @msg: The #FbApiMessage or #NULL.
- *
- * Duplicates an #FbApiMessage. The returned #FbApiMessage should be freed with
- * #fb_api_message_free() when no longer needed.
- *
- * Returns: The new #FbApiMessage.
- */
-FbApiMessage *
-fb_api_message_dup(const FbApiMessage *msg);
-
-/**
- * fb_api_message_reset:
- * @msg: The #FbApiMessage.
- * @deep: #TRUE to free allocated data, otherwise #FALSE.
- *
- * Resets an #FbApiMessage.
- */
-void
-fb_api_message_reset(FbApiMessage *msg, gboolean deep);
-
-/**
- * fb_api_message_free:
- * @msg: The #FbApiMessage.
- *
- * Frees all memory used by the #FbApiMessage.
- */
-void
-fb_api_message_free(FbApiMessage *msg);
-
-/**
- * fb_api_presence_get_type:
- *
- * Returns: The #GType for the #FbApiPresence boxed structure.
- */
-GType fb_api_presence_get_type(void);
-
-/**
- * fb_api_presence_dup:
- * @presence: The #FbApiPresence or %NULL.
- *
- * Duplicates an #FbApiPresence. The returned #FbApiPresence should be freed
- * with #fb_api_presence_free() when no longer needed.
- *
- * Returns: The new #FbApiPresence.
- */
-FbApiPresence *
-fb_api_presence_dup(const FbApiPresence *presence);
-
-/**
- * fb_api_presence_reset:
- * @presence: The #FbApiPresence.
- *
- * Resets an #FbApiPresence.
- */
-void
-fb_api_presence_reset(FbApiPresence *presence);
-
-/**
- * fb_api_presence_free:
- * @presence: The #FbApiPresence.
- *
- * Frees all memory used by the #FbApiPresence.
- */
-void
-fb_api_presence_free(FbApiPresence *presence);
-
-/**
- * fb_api_thread_get_type:
- *
- * Returns: The #GType for the #FbApiThread boxed structure.
- */
-GType fb_api_thread_get_type(void);
-
-/**
- * fb_api_thread_dup:
- * @thrd: The #FbApiThread or #NULL.
- *
- * Duplicates an #FbApiThread. The returned #FbApiThread should be freed with
- * #fb_api_thread_free() when no longer needed.
- *
- * Returns: The new #FbApiThread.
- */
-FbApiThread *
-fb_api_thread_dup(const FbApiThread *thrd);
-
-/**
- * fb_api_thread_reset:
- * @thrd: The #FbApiThread.
- * @deep: #TRUE to free allocated data, otherwise #FALSE.
- *
- * Resets an #FbApiThread.
- */
-void
-fb_api_thread_reset(FbApiThread *thrd, gboolean deep);
-
-/**
- * fb_api_thread_free:
- * @thrd: The #FbApiThread.
- *
- * Frees all memory used by the #FbApiThread.
- */
-void
-fb_api_thread_free(FbApiThread *thrd);
-
-/**
- * fb_api_typing_get_type:
- *
- * Returns: The #GType for the #FbApiTyping boxed structure.
- */
-GType fb_api_typing_get_type(void);
-
-/**
- * fb_api_typing_dup:
- * @typg: The #FbApiTyping or #NULL.
- *
- * Duplicates an #FbApiTyping. The returned #FbApiTyping should be freed with
- * #fb_api_typing_free() when no longer needed.
- *
- * Returns: The new #FbApiTyping.
- */
-FbApiTyping *
-fb_api_typing_dup(const FbApiTyping *typg);
-
-/**
- * fb_api_typing_reset:
- * @typg: The #FbApiTyping.
- *
- * Resets an #FbApiTyping.
- */
-void
-fb_api_typing_reset(FbApiTyping *typg);
-
-/**
- * fb_api_typing_free:
- * @typg: The #FbApiTyping.
- *
- * Frees all memory used by the #FbApiTyping.
- */
-void
-fb_api_typing_free(FbApiTyping *typg);
-
-/**
- * fb_api_user_get_type:
- *
- * Returns: The #GType for the #FbApiUser boxed structure.
- */
-GType fb_api_user_get_type(void);
-
-/**
- * fb_api_user_dup:
- * @user: The #FbApiUser or #NULL.
- *
- * Duplicates an #FbApiUser. The returned #FbApiUser should be freed with
- * #fb_api_user_free() when no longer needed.
- *
- * Returns: The new #FbApiUser.
- */
-FbApiUser *
-fb_api_user_dup(const FbApiUser *user);
-
-/**
- * fb_api_user_reset:
- * @user: The #FbApiUser.
- * @deep: #TRUE to free allocated data, otherwise #FALSE.
- *
- * Resets an #FbApiUser.
- */
-void
-fb_api_user_reset(FbApiUser *user, gboolean deep);
-
-/**
- * fb_api_user_free:
- * @user: The #FbApiUser.
- *
- * Frees all memory used by the #FbApiUser.
- */
-void
-fb_api_user_free(FbApiUser *user);
-
-#endif /* PURPLE_FACEBOOK_API_H */
diff --git a/libpurple/protocols/facebook/data.c b/libpurple/protocols/facebook/data.c
deleted file mode 100644
index b9288162ad..0000000000
--- a/libpurple/protocols/facebook/data.c
+++ /dev/null
@@ -1,558 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#include <libsoup/soup.h>
-#include <string.h>
-
-#include <purple.h>
-#include "libpurple/glibcompat.h"
-
-#include "api.h"
-#include "data.h"
-
-/**
- * FbData:
- *
- * Represents the connection data used by #FacebookProtocol.
- */
-struct _FbData {
- GObject parent;
-
- FbApi *api;
- SoupSession *cons;
- PurpleConnection *gc;
- PurpleRoomlist *roomlist;
- GQueue *msgs;
- GHashTable *imgs;
- GHashTable *unread;
- GHashTable *evs;
-};
-
-/**
- * FbDataImage:
- *
- * Represents the data used for fetching images.
- */
-struct _FbDataImage {
- GObject parent;
-
- FbData *fata;
- gchar *url;
- FbDataImageFunc func;
- gpointer data;
- GDestroyNotify dunc;
-
- gboolean active;
- const guint8 *image;
- gsize size;
-};
-
-static const gchar *fb_props_strs[] = {
- "cid",
- "did",
- "stoken",
- "token"
-};
-
-G_DEFINE_TYPE(FbData, fb_data, G_TYPE_OBJECT);
-G_DEFINE_TYPE(FbDataImage, fb_data_image, G_TYPE_OBJECT);
-
-static void
-fb_data_dispose(GObject *obj)
-{
- FbData *fata = FB_DATA(obj);
-
- if(fata->cons != NULL) {
- soup_session_abort(fata->cons);
- }
-
- if(fata->evs != NULL) {
- GHashTableIter iter;
- gpointer ptr = NULL;
-
- g_hash_table_iter_init(&iter, fata->evs);
- while (g_hash_table_iter_next(&iter, NULL, &ptr)) {
- g_source_remove(GPOINTER_TO_UINT(ptr));
- }
- }
-
- g_clear_object(&fata->api);
-
- g_clear_object(&fata->cons);
- if(fata->msgs != NULL) {
- g_queue_free_full(fata->msgs, (GDestroyNotify)fb_api_message_free);
- fata->msgs = NULL;
- }
-
- g_clear_pointer(&fata->imgs, g_hash_table_destroy);
- g_clear_pointer(&fata->unread, g_hash_table_destroy);
- g_clear_pointer(&fata->evs, g_hash_table_destroy);
-}
-
-static void
-fb_data_class_init(FbDataClass *klass)
-{
- GObjectClass *gklass = G_OBJECT_CLASS(klass);
-
- gklass->dispose = fb_data_dispose;
-}
-
-static void
-fb_data_init(FbData *fata)
-{
- fata->msgs = g_queue_new();
-
- fata->imgs = g_hash_table_new_full(g_direct_hash, g_direct_equal,
- g_object_unref, NULL);
- fata->unread = g_hash_table_new_full(fb_id_hash, fb_id_equal,
- g_free, NULL);
- fata->evs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-}
-
-static void
-fb_data_image_dispose(GObject *obj)
-{
- FbDataImage *img = FB_DATA_IMAGE(obj);
- FbData *fata = img->fata;
-
- if (img->dunc != NULL && img->data != NULL) {
- img->dunc(img->data);
- img->dunc = NULL;
- }
-
- g_clear_pointer(&img->url, g_free);
- g_hash_table_steal(fata->imgs, img);
-}
-
-static void
-fb_data_image_class_init(FbDataImageClass *klass)
-{
- GObjectClass *gklass = G_OBJECT_CLASS(klass);
-
- gklass->dispose = fb_data_image_dispose;
-}
-
-static void
-fb_data_image_init(G_GNUC_UNUSED FbDataImage *img)
-{
-}
-
-FbData *
-fb_data_new(PurpleConnection *gc, GProxyResolver *resolver)
-{
- FbData *fata;
-
- fata = g_object_new(FB_TYPE_DATA, NULL);
-
- fata->cons = soup_session_new_with_options("proxy-resolver", resolver,
- NULL);
- fata->api = fb_api_new(gc, resolver);
- fata->gc = gc;
-
- return fata;
-}
-
-gboolean
-fb_data_load(FbData *fata)
-{
- const gchar *str;
- FbId id;
- gboolean ret = TRUE;
- guint i;
- guint64 uint;
- GValue val = G_VALUE_INIT;
- PurpleAccount *acct;
-
- g_return_val_if_fail(FB_IS_DATA(fata), FALSE);
- acct = purple_connection_get_account(fata->gc);
-
- for (i = 0; i < G_N_ELEMENTS(fb_props_strs); i++) {
- str = purple_account_get_string(acct, fb_props_strs[i], NULL);
-
- if (str == NULL) {
- ret = FALSE;
- }
-
- g_value_init(&val, G_TYPE_STRING);
- g_value_set_string(&val, str);
- g_object_set_property(G_OBJECT(fata->api), fb_props_strs[i],
- &val);
- g_value_unset(&val);
- }
-
- str = purple_account_get_string(acct, "mid", NULL);
-
- if (str != NULL) {
- uint = g_ascii_strtoull(str, NULL, 10);
- g_value_init(&val, G_TYPE_UINT64);
- g_value_set_uint64(&val, uint);
- g_object_set_property(G_OBJECT(fata->api), "mid", &val);
- g_value_unset(&val);
- } else {
- ret = FALSE;
- }
-
- str = purple_account_get_string(acct, "uid", NULL);
-
- if (str != NULL) {
- id = FB_ID_FROM_STR(str);
- g_value_init(&val, FB_TYPE_ID);
- g_value_set_int64(&val, id);
- g_object_set_property(G_OBJECT(fata->api), "uid", &val);
- g_value_unset(&val);
- } else {
- ret = FALSE;
- }
-
- fb_api_rehash(fata->api);
- return ret;
-}
-
-void
-fb_data_save(FbData *fata)
-{
- const gchar *str;
- gchar *dup;
- guint i;
- guint64 uint;
- GValue val = G_VALUE_INIT;
- PurpleAccount *acct;
-
- g_return_if_fail(FB_IS_DATA(fata));
- acct = purple_connection_get_account(fata->gc);
-
- for (i = 0; i < G_N_ELEMENTS(fb_props_strs); i++) {
- g_value_init(&val, G_TYPE_STRING);
- g_object_get_property(G_OBJECT(fata->api), fb_props_strs[i],
- &val);
- str = g_value_get_string(&val);
-
- if (purple_strequal(fb_props_strs[i], "token") && !purple_account_get_remember_password(acct)) {
- str = "";
- }
- purple_account_set_string(acct, fb_props_strs[i], str);
- g_value_unset(&val);
- }
-
- g_value_init(&val, G_TYPE_UINT64);
- g_object_get_property(G_OBJECT(fata->api), "mid", &val);
- uint = g_value_get_uint64(&val);
- g_value_unset(&val);
-
- dup = g_strdup_printf("%" G_GINT64_FORMAT, uint);
- purple_account_set_string(acct, "mid", dup);
- g_free(dup);
-
- g_value_init(&val, G_TYPE_INT64);
- g_object_get_property(G_OBJECT(fata->api), "uid", &val);
- uint = g_value_get_int64(&val);
- g_value_unset(&val);
-
- dup = g_strdup_printf("%" FB_ID_FORMAT, uint);
- purple_account_set_string(acct, "uid", dup);
- g_free(dup);
-}
-
-void
-fb_data_save_timeout(FbData *fata, const gchar *name, guint id)
-{
- g_return_if_fail(FB_IS_DATA(fata));
-
- fb_data_clear_timeout(fata, name, TRUE);
-
- g_hash_table_replace(fata->evs, g_strdup(name), GUINT_TO_POINTER(id));
-}
-
-void
-fb_data_clear_timeout(FbData *fata, const gchar *name, gboolean remove)
-{
- gpointer ptr;
- guint id;
-
- g_return_if_fail(FB_IS_DATA(fata));
-
- ptr = g_hash_table_lookup(fata->evs, name);
- id = GPOINTER_TO_UINT(ptr);
-
- if(remove) {
- g_clear_handle_id(&id, g_source_remove);
- }
-
- g_hash_table_remove(fata->evs, name);
-}
-
-FbApi *
-fb_data_get_api(FbData *fata)
-{
-
- g_return_val_if_fail(FB_IS_DATA(fata), NULL);
-
- return fata->api;
-}
-
-PurpleConnection *
-fb_data_get_connection(FbData *fata)
-{
- g_return_val_if_fail(FB_IS_DATA(fata), NULL);
-
- return fata->gc;
-}
-
-PurpleRoomlist *
-fb_data_get_roomlist(FbData *fata)
-{
- g_return_val_if_fail(FB_IS_DATA(fata), NULL);
-
- return fata->roomlist;
-}
-
-gboolean
-fb_data_get_unread(FbData *fata, FbId id)
-{
- gpointer *ptr;
-
- g_return_val_if_fail(FB_IS_DATA(fata), FALSE);
- g_return_val_if_fail(id != 0, FALSE);
-
- ptr = g_hash_table_lookup(fata->unread, &id);
- return GPOINTER_TO_INT(ptr);
-}
-
-void
-fb_data_set_roomlist(FbData *fata, PurpleRoomlist *list)
-{
- g_return_if_fail(FB_IS_DATA(fata));
-
- fata->roomlist = list;
-}
-
-void
-fb_data_set_unread(FbData *fata, FbId id, gboolean unread)
-{
- gpointer key;
-
- g_return_if_fail(FB_IS_DATA(fata));
- g_return_if_fail(id != 0);
-
- if (!unread) {
- g_hash_table_remove(fata->unread, &id);
- return;
- }
-
- key = g_memdup2(&id, sizeof id);
- g_hash_table_replace(fata->unread, key, GINT_TO_POINTER(unread));
-}
-
-void
-fb_data_add_message(FbData *fata, FbApiMessage *msg)
-{
- g_return_if_fail(FB_IS_DATA(fata));
-
- g_queue_push_tail(fata->msgs, msg);
-}
-
-void
-fb_data_remove_message(FbData *fata, FbApiMessage *msg)
-{
- g_return_if_fail(FB_IS_DATA(fata));
-
- g_queue_remove(fata->msgs, msg);
-}
-
-GSList *
-fb_data_take_messages(FbData *fata, FbId uid)
-{
- FbApiMessage *msg;
- GList *l;
- GList *prev;
- GSList *msgs = NULL;
-
- g_return_val_if_fail(FB_IS_DATA(fata), NULL);
- l = fata->msgs->tail;
-
- while (l != NULL) {
- msg = l->data;
- prev = l->prev;
-
- if (msg->uid == uid) {
- msgs = g_slist_prepend(msgs, msg);
- g_queue_delete_link(fata->msgs, l);
- }
-
- l = prev;
- }
-
- return msgs;
-}
-
-FbDataImage *
-fb_data_image_add(FbData *fata, const gchar *url, FbDataImageFunc func,
- gpointer data, GDestroyNotify dunc)
-{
- FbDataImage *img;
-
- g_return_val_if_fail(FB_IS_DATA(fata), NULL);
- g_return_val_if_fail(url != NULL, NULL);
- g_return_val_if_fail(func != NULL, NULL);
-
- img = g_object_new(FB_TYPE_DATA_IMAGE, NULL);
-
- img->fata = fata;
- img->url = g_strdup(url);
- img->func = func;
- img->data = data;
- img->dunc = dunc;
-
- g_hash_table_add(fata->imgs, img);
- return img;
-}
-
-gboolean
-fb_data_image_get_active(FbDataImage *img)
-{
- g_return_val_if_fail(FB_IS_DATA_IMAGE(img), FALSE);
-
- return img->active;
-}
-
-gpointer
-fb_data_image_get_data(FbDataImage *img)
-{
- g_return_val_if_fail(FB_IS_DATA_IMAGE(img), NULL);
-
- return img->data;
-}
-
-FbData *
-fb_data_image_get_fata(FbDataImage *img)
-{
- g_return_val_if_fail(FB_IS_DATA_IMAGE(img), NULL);
-
- return img->fata;
-}
-
-const guint8 *
-fb_data_image_get_image(FbDataImage *img, gsize *size)
-{
- g_return_val_if_fail(FB_IS_DATA_IMAGE(img), NULL);
-
- if (size != NULL) {
- *size = img->size;
- }
-
- return img->image;
-}
-
-guint8 *
-fb_data_image_dup_image(FbDataImage *img, gsize *size)
-{
- g_return_val_if_fail(FB_IS_DATA_IMAGE(img), NULL);
-
- if (size != NULL) {
- *size = img->size;
- }
-
- if (img->size < 1) {
- return NULL;
- }
-
- return g_memdup2(img->image, img->size);
-}
-
-const gchar *
-fb_data_image_get_url(FbDataImage *img)
-{
- g_return_val_if_fail(FB_IS_DATA_IMAGE(img), NULL);
-
- return img->url;
-}
-
-static void
-fb_data_image_cb(GObject *source, GAsyncResult *result, gpointer data) {
- SoupMessage *msg = data;
- FbDataImage *img = g_object_get_data(G_OBJECT(msg), "facebook-data-image");
- GError *err = NULL;
-
- if(fb_http_error_chk(msg, &err)) {
- GBytes *bytes = NULL;
-
- bytes = soup_session_send_and_read_finish(SOUP_SESSION(source),
- result, &err);
- if(bytes != NULL) {
- img->image = g_bytes_unref_to_data(bytes, &img->size);
- }
- }
-
- img->func(img, err);
-
- if (G_LIKELY(err == NULL)) {
- fb_data_image_queue(img->fata);
- } else {
- g_error_free(err);
- }
-
- g_object_unref(img);
- g_object_unref(msg);
-}
-
-void
-fb_data_image_queue(FbData *fata)
-{
- const gchar *url;
- FbDataImage *img;
- GHashTableIter iter;
- guint active = 0;
-
- g_return_if_fail(FB_IS_DATA(fata));
-
- g_hash_table_iter_init(&iter, fata->imgs);
- while (g_hash_table_iter_next(&iter, (gpointer *) &img, NULL)) {
- if (fb_data_image_get_active(img)) {
- active++;
- }
- }
-
- if (active >= FB_DATA_ICON_MAX) {
- return;
- }
-
- g_hash_table_iter_init(&iter, fata->imgs);
- while (g_hash_table_iter_next(&iter, (gpointer *) &img, NULL)) {
- SoupMessage *msg;
-
- if (fb_data_image_get_active(img)) {
- continue;
- }
-
- img->active = TRUE;
- url = fb_data_image_get_url(img);
-
- msg = soup_message_new("GET", url);
- g_object_set_data(G_OBJECT(msg), "facebook-data-image", img);
- // purple_http_request_set_max_len(req, FB_DATA_ICON_SIZE_MAX);
- soup_session_send_and_read_async(fata->cons, msg, G_PRIORITY_DEFAULT,
- NULL, fb_data_image_cb, msg);
-
- if (++active >= FB_DATA_ICON_MAX) {
- break;
- }
- }
-}
diff --git a/libpurple/protocols/facebook/data.h b/libpurple/protocols/facebook/data.h
deleted file mode 100644
index 1e3fbae596..0000000000
--- a/libpurple/protocols/facebook/data.h
+++ /dev/null
@@ -1,318 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#ifndef PURPLE_FACEBOOK_DATA_H
-#define PURPLE_FACEBOOK_DATA_H
-
-#include <glib.h>
-
-#include <purple.h>
-
-#include "api.h"
-#include "http.h"
-#include "id.h"
-
-#define FB_TYPE_DATA fb_data_get_type()
-#define FB_TYPE_DATA_IMAGE fb_data_image_get_type()
-
-/**
- * FB_DATA_ICON_MAX:
- *
- * The maximum of number of concurrent icon fetches.
- */
-#define FB_DATA_ICON_MAX 4
-
-/**
- * FB_DATA_ICON_SIZE_MAX:
- *
- * The maximum size of a fetched icon.
- */
-#define FB_DATA_ICON_SIZE_MAX 0xa00000 /* 10MiB */
-
-G_DECLARE_FINAL_TYPE(FbData, fb_data, FB, DATA, GObject)
-
-G_DECLARE_FINAL_TYPE(FbDataImage, fb_data_image, FB, DATA_IMAGE, GObject)
-
-/**
- * FbDataImageFunc:
- * @img: The #FbDataImage.
- * @error: The #GError or #NULL.
- *
- * The callback for a fetched #FbDataImage.
- */
-typedef void (*FbDataImageFunc) (FbDataImage *img, GError *error);
-
-/**
- * fb_data_new:
- * @gc: The #PurpleConnection.
- * @resolver: The proxy resolver to use from the account.
- *
- * Creates a new #FbData. The returned #FbData should be freed with
- * #g_object_unref() when no longer needed.
- *
- * Returns: The new #FbData.
- */
-FbData *fb_data_new(PurpleConnection *gc, GProxyResolver *resolver);
-
-/**
- * fb_data_load:
- * @fata: The #FbData.
- *
- * Loads the internal data from the underlying #PurpleAccount.
- *
- * Return: #TRUE if all of the data was loaded, otherwise #FALSE.
- */
-gboolean
-fb_data_load(FbData *fata);
-
-/**
- * fb_data_save:
- * @fata: The #FbData.
- *
- * Saves the internal data to the underlying #PurpleAccount.
- */
-void
-fb_data_save(FbData *fata);
-
-/**
- * fb_data_save_timeout:
- * @fata: The #FbData.
- * @name: The name of the timeout.
- * @id: The source id of the timeout.
- *
- * Saves a new callback timer. The callback should be added to the main loop
- * with `g_timeout_add` or similar, and the returned source identifier passed
- * to this function. The timeout should be cleared with
- * #fb_data_clear_timeout() when no longer needed.
- */
-void
-fb_data_save_timeout(FbData *fata, const gchar *name, guint id);
-
-/**
- * fb_data_clear_timeout:
- * @fata: The #FbData.
- * @name: The name of the timeout.
- * @remove: #TRUE to remove from the event loop, otherwise #FALSE.
- *
- * Clears and removes a callback timer. The only time @remove should be
- * #FALSE, is when being called from a #GSourceFunc, which is returning
- * #FALSE.
- */
-void
-fb_data_clear_timeout(FbData *fata, const gchar *name, gboolean remove);
-
-/**
- * fb_data_get_api:
- * @fata: The #FbData.
- *
- * Gets the #FbApi from the #FbData.
- *
- * Return: (transfer none): The #FbApi.
- */
-FbApi *
-fb_data_get_api(FbData *fata);
-
-/**
- * fb_data_get_connection:
- * @fata: The #FbData.
- *
- * Gets the #PurpleConnection from the #FbData.
- *
- * Return: (transfer none): The #PurpleConnection.
- */
-PurpleConnection *
-fb_data_get_connection(FbData *fata);
-
-/**
- * fb_data_get_roomlist:
- * @fata: The #FbData.
- *
- * Gets the #PurpleRoomlist from the #FbData.
- *
- * Return: (transfer none): The #PurpleRoomlist.
- */
-PurpleRoomlist *
-fb_data_get_roomlist(FbData *fata);
-
-/**
- * fb_data_get_unread:
- * @fata: The #FbData.
- * @id: The #FbId.
- *
- * Gets the unread state of an #FbId.
- *
- * Return: #TRUE if the #FbId is unread, otherwise #FALSE.
- */
-gboolean
-fb_data_get_unread(FbData *fata, FbId id);
-
-/**
- * fb_data_set_roomlist:
- * @fata: The #FbData.
- * @list: The #PurpleRoomlist.
- *
- * Sets the #PurpleRoomlist to the #FbData.
- */
-void
-fb_data_set_roomlist(FbData *fata, PurpleRoomlist *list);
-
-/**
- * fb_data_set_unread:
- * @fata: The #FbData.
- * @id: The #FbId.
- * @unread: #TRUE if the #FbId is unread, otherwise #FALSE.
- *
- * Sets the unread state of an #FbId to the #FbData.
- */
-void
-fb_data_set_unread(FbData *fata, FbId id, gboolean unread);
-
-/**
- * fb_data_add_message:
- * @fata: The #FbData.
- * @msg: The #FbApiMessage.
- *
- * Adds an #FbApiMessage to the #FbData.
- */
-void
-fb_data_add_message(FbData *fata, FbApiMessage *msg);
-
-/**
- * fb_data_remove_message:
- * @fata: The #FbData.
- * @msg: The #FbApiMessage.
- *
- * Removes an #FbApiMessage from the #FbData.
- */
-void
-fb_data_remove_message(FbData *fata, FbApiMessage *msg);
-
-/**
- * fb_data_take_messages:
- * @fata: The #FbData.
- * @uid: The user #FbId.
- *
- * Gets a #GSList of messages by the user #FbId from the #FbData. The
- * #FbApiMessage's are removed from the #FbData.
- *
- * Returns: (element-type FbApiMessage) (transfer full): The messages from the
- * user.
- */
-GSList *
-fb_data_take_messages(FbData *fata, FbId uid);
-
-/**
- * fb_data_image_add:
- * @fata: The #FbData.
- * @url: The image URL.
- * @func: The #FbDataImageFunc.
- * @data: The user-defined data.
- * @dunc: The #GDestroyNotify for @data or #NULL.
- *
- * Adds a new #FbDataImage to the #FbData. This is used to fetch images
- * from HTTP sources. After calling this, #fb_data_image_queue() should
- * be called to queue the fetching process.
- *
- * Return: (transfer none): The #FbDataImage.
- */
-FbDataImage *
-fb_data_image_add(FbData *fata, const gchar *url, FbDataImageFunc func,
- gpointer data, GDestroyNotify dunc);
-
-/**
- * fb_data_image_get_active:
- * @img: The #FbDataImage.
- *
- * Gets the active fetching state from the #FbDataImage.
- *
- * Returns: #TRUE if the image is being fetched, otherwise #FALSE.
- */
-gboolean
-fb_data_image_get_active(FbDataImage *img);
-
-/**
- * fb_data_image_get_data:
- * @img: The #FbDataImage.
- *
- * Gets the user-defined data from the #FbDataImage.
- *
- * Returns: The user-defined data.
- */
-gpointer
-fb_data_image_get_data(FbDataImage *img);
-
-/**
- * fb_data_image_get_fata:
- * @img: The #FbDataImage.
- *
- * Gets the #FbData from the #FbDataImage.
- *
- * Returns: (transfer none): The #FbData.
- */
-FbData *
-fb_data_image_get_fata(FbDataImage *img);
-
-/**
- * fb_data_image_get_image:
- * @img: The #FbDataImage.
- * @size: The return location for the image size or #NULL.
- *
- * Gets the image data from the #FbDataImage.
- *
- * Returns: The image data.
- */
-const guint8 *
-fb_data_image_get_image(FbDataImage *img, gsize *size);
-
-/**
- * fb_data_image_dup_image:
- * @img: The #FbDataImage.
- * @size: The return location for the image size or #NULL.
- *
- * Gets the duplicated image data from the #FbDataImage. The returned
- * data should be freed with #g_free() when no longer needed.
- *
- * Returns: The duplicated image data.
- */
-guint8 *
-fb_data_image_dup_image(FbDataImage *img, gsize *size);
-
-/**
- * fb_data_image_get_url:
- * @img: The #FbDataImage.
- *
- * Gets the image URL from the #FbDataImage.
- *
- * Returns: The image URL.
- */
-const gchar *
-fb_data_image_get_url(FbDataImage *img);
-
-/**
- * fb_data_image_queue:
- * @fata: The #FbData.
- *
- * Queues the next #FbDataImage fetches.
- */
-void
-fb_data_image_queue(FbData *fata);
-
-#endif /* PURPLE_FACEBOOK_DATA_H */
diff --git a/libpurple/protocols/facebook/facebook.c b/libpurple/protocols/facebook/facebook.c
deleted file mode 100644
index 04ed88e349..0000000000
--- a/libpurple/protocols/facebook/facebook.c
+++ /dev/null
@@ -1,1740 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#include <glib/gi18n-lib.h>
-
-#include <gplugin.h>
-#include <gplugin-native.h>
-
-#include <purple.h>
-
-#include "libpurple/glibcompat.h"
-
-#include "api.h"
-#include "data.h"
-#include "facebook.h"
-#include "http.h"
-#include "util.h"
-
-struct _FacebookProtocol {
- PurpleProtocol parent;
-};
-
-static GSList *fb_cmds = NULL;
-static PurpleProtocol *fb_protocol = NULL;
-
-static void
-fb_cb_api_messages(FbApi *api, GSList *msgs, gpointer data);
-
-static PurpleGroup *
-fb_get_group(gboolean friend)
-{
- PurpleBlistNode *n;
- PurpleBlistNode *node;
- PurpleGroup *grp;
- const gchar *title;
-
- if (friend) {
- title = _("Facebook Friends");
- } else {
- title = _("Facebook Non-Friends");
- }
-
- grp = purple_blist_find_group(title);
-
- if (G_UNLIKELY(grp == NULL)) {
- grp = purple_group_new(title);
- node = NULL;
-
- for (n = purple_blist_get_default_root(); n != NULL;
- n = n->next) {
- node = n;
- }
-
- /* Append to the end of the buddy list */
- purple_blist_add_group(grp, node);
-
- if (!friend) {
- node = PURPLE_BLIST_NODE(grp);
- purple_blist_node_set_bool(node, "collapsed", TRUE);
- }
- }
-
- return grp;
-}
-
-static void
-fb_buddy_add_nonfriend(PurpleAccount *acct, FbApiUser *user)
-{
- gchar uid[FB_ID_STRMAX];
- PurpleBuddy *bdy;
- PurpleGroup *grp;
-
- FB_ID_TO_STR(user->uid, uid);
- bdy = purple_buddy_new(acct, uid, user->name);
- grp = fb_get_group(FALSE);
-
- purple_buddy_set_server_alias(bdy, user->name);
- purple_blist_add_buddy(bdy, NULL, grp, NULL);
-}
-
-static void
-fb_cb_api_auth(FbApi *api, gpointer data)
-{
- FbData *fata = data;
-
- fb_data_save(fata);
- fb_api_contacts(api);
-}
-
-static void
-fb_cb_api_connect(FbApi *api, gpointer data)
-{
- FbData *fata = data;
- PurpleAccount *acct;
- PurpleConnection *gc;
-
- gc = fb_data_get_connection(fata);
- acct = purple_connection_get_account(gc);
-
- fb_data_save(fata);
- purple_connection_set_state(gc, PURPLE_CONNECTION_STATE_CONNECTED);
-
- if (purple_account_get_bool(acct, "show-unread", TRUE)) {
- fb_api_unread(api);
- }
-}
-
-static void
-fb_cb_api_contact(FbApi *api, FbApiUser *user, gpointer data)
-{
- FbData *fata = data;
- gchar uid[FB_ID_STRMAX];
- GSList *msgs;
- PurpleAccount *acct;
- PurpleConnection *gc;
-
- gc = fb_data_get_connection(fata);
- acct = purple_connection_get_account(gc);
- FB_ID_TO_STR(user->uid, uid);
-
- if (purple_blist_find_buddy(acct, uid) == NULL) {
- fb_buddy_add_nonfriend(acct, user);
- }
-
- msgs = fb_data_take_messages(fata, user->uid);
-
- if (msgs != NULL) {
- fb_cb_api_messages(api, msgs, fata);
- g_slist_free_full(msgs, (GDestroyNotify) fb_api_message_free);
- }
-}
-
-static gboolean
-fb_cb_sync_contacts(gpointer data)
-{
- FbApi *api;
- FbData *fata = data;
-
- api = fb_data_get_api(fata);
- fb_data_clear_timeout(fata, "sync-contacts", FALSE);
- fb_api_contacts(api);
- return FALSE;
-}
-
-static void
-fb_cb_icon(FbDataImage *img, GError *error)
-{
- const gchar *csum;
- const gchar *name;
- const gchar *str;
- FbHttpParams *params;
- gsize size;
- guint8 *image;
- PurpleAccount *acct;
- PurpleBuddy *bdy;
-
- bdy = fb_data_image_get_data(img);
- acct = purple_buddy_get_account(bdy);
- name = purple_buddy_get_name(bdy);
-
- if (G_UNLIKELY(error != NULL)) {
- fb_util_debug_warning("Failed to retrieve icon for %s: %s",
- name, error->message);
- return;
- }
-
- str = fb_data_image_get_url(img);
- params = fb_http_params_new_parse(str, TRUE);
- csum = fb_http_params_get_str(params, "oh", NULL);
-
- image = fb_data_image_dup_image(img, &size);
- purple_buddy_icons_set_for_user(acct, name, image, size, csum);
- fb_http_params_free(params);
-}
-
-static void
-fb_sync_contacts_add_timeout(FbData *fata)
-{
- gint sync;
- PurpleConnection *gc;
- PurpleAccount *acct;
-
- gc = fb_data_get_connection(fata);
- acct = purple_connection_get_account(gc);
-
- sync = purple_account_get_int(acct, "sync-interval", 5);
-
- if (sync < 1) {
- purple_account_set_int(acct, "sync-interval", 1);
- sync = 1;
- }
-
- sync *= 60;
- fb_data_save_timeout(fata, "sync-contacts",
- g_timeout_add_seconds(sync, fb_cb_sync_contacts, fata));
-}
-
-static void
-fb_cb_api_contacts(FbApi *api, GSList *users, gboolean complete, gpointer data)
-{
- const gchar *alias;
- const gchar *csum;
- FbApiUser *user;
- FbData *fata = data;
- FbId muid;
- gchar uid[FB_ID_STRMAX];
- GSList *l;
- GValue val = G_VALUE_INIT;
- PurpleAccount *acct;
- PurpleBuddy *bdy;
- PurpleConnection *gc;
- PurpleConnectionState state;
- PurpleGroup *grp;
- PurpleGroup *grpn;
- PurpleStatus *status;
- PurpleStatusPrimitive pstat;
- PurpleStatusType *type;
-
- gc = fb_data_get_connection(fata);
- acct = purple_connection_get_account(gc);
- grp = fb_get_group(TRUE);
- grpn = fb_get_group(FALSE);
- alias = purple_contact_info_get_alias(PURPLE_CONTACT_INFO(acct));
- state = purple_connection_get_state(gc);
-
- g_value_init(&val, FB_TYPE_ID);
- g_object_get_property(G_OBJECT(api), "uid", &val);
- muid = g_value_get_int64(&val);
- g_value_unset(&val);
-
- for (l = users; l != NULL; l = l->next) {
- user = l->data;
- FB_ID_TO_STR(user->uid, uid);
-
- if (G_UNLIKELY(user->uid == muid)) {
- PurpleContactInfo *info = NULL;
-
- if (G_UNLIKELY(alias != NULL)) {
- continue;
- }
-
- info = PURPLE_CONTACT_INFO(acct);
- purple_contact_info_set_alias(info, user->name);
-
- continue;
- }
-
- bdy = purple_blist_find_buddy(acct, uid);
-
- if ((bdy != NULL) && (purple_buddy_get_group(bdy) == grpn)) {
- purple_blist_remove_buddy(bdy);
- bdy = NULL;
- }
-
- if (bdy == NULL) {
- bdy = purple_buddy_new(acct, uid, NULL);
- purple_blist_add_buddy(bdy, NULL, grp, NULL);
- }
-
- purple_buddy_set_server_alias(bdy, user->name);
- csum = purple_buddy_icons_get_checksum_for_user(bdy);
-
- if (!purple_strequal(csum, user->csum)) {
- fb_data_image_add(fata, user->icon, fb_cb_icon,
- bdy, NULL);
- }
- }
-
- fb_data_image_queue(fata);
-
- if (!complete) {
- return;
- }
-
- if (state != PURPLE_CONNECTION_STATE_CONNECTED) {
- status = purple_account_get_active_status(acct);
- type = purple_status_get_status_type(status);
- pstat = purple_status_type_get_primitive(type);
-
- fb_api_connect(api, pstat == PURPLE_STATUS_INVISIBLE);
- }
-
- fb_sync_contacts_add_timeout(fata);
-}
-
-static void
-fb_cb_api_contacts_delta(G_GNUC_UNUSED FbApi *api, GSList *added,
- GSList *removed, gpointer data)
-{
- FbApiUser *user;
- FbData *fata = data;
- gchar uid[FB_ID_STRMAX];
- GSList *l;
- PurpleAccount *acct;
- PurpleBuddy *bdy;
- PurpleConnection *gc;
- PurpleGroup *grp;
- PurpleGroup *grpn;
-
- gc = fb_data_get_connection(fata);
- acct = purple_connection_get_account(gc);
- grp = fb_get_group(TRUE);
- grpn = fb_get_group(FALSE);
-
- for (l = added; l != NULL; l = l->next) {
- user = l->data;
- FB_ID_TO_STR(user->uid, uid);
-
- bdy = purple_blist_find_buddy(acct, uid);
-
- if ((bdy != NULL) && (purple_buddy_get_group(bdy) == grpn)) {
- purple_blist_remove_buddy(bdy);
- }
-
- bdy = purple_buddy_new(acct, uid, NULL);
- purple_blist_add_buddy(bdy, NULL, grp, NULL);
-
- purple_buddy_set_server_alias(bdy, user->name);
- }
-
- for (l = removed; l != NULL; l = l->next) {
- bdy = purple_blist_find_buddy(acct, l->data);
-
- if (bdy != NULL) {
- purple_blist_remove_buddy(bdy);
- }
- }
-
- fb_sync_contacts_add_timeout(fata);
-}
-
-static void
-fb_cb_api_error(G_GNUC_UNUSED FbApi *api, GError *error, gpointer data)
-{
- FbData *fata = data;
- PurpleConnection *gc;
- PurpleConnectionError errc;
-
- gc = fb_data_get_connection(fata);
-
- if (error->domain == G_IO_ERROR) {
- purple_connection_g_error(gc, error);
- return;
- }
-
- if (g_error_matches(error, FB_API_ERROR, FB_API_ERROR_QUEUE)) {
- /* Save the reset data */
- fb_data_save(fata);
- }
-
- if ((error->domain == FB_HTTP_ERROR) &&
- (error->code >= 400) &&
- (error->code <= 500))
- {
- errc = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
- } else if (g_error_matches(error, FB_API_ERROR, FB_API_ERROR_AUTH)) {
- errc = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
- } else {
- errc = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
- }
-
-
- if (!g_error_matches(error, FB_API_ERROR, FB_API_ERROR_NONFATAL)) {
- purple_connection_error(gc, errc, error->message);
- }
-}
-
-static void
-fb_cb_api_events(FbApi *api, GSList *events, gpointer data)
-{
- FbData *fata = data;
- FbApiEvent *event;
- gchar uid[FB_ID_STRMAX];
- gchar tid[FB_ID_STRMAX];
- GHashTable *fetch;
- GHashTableIter iter;
- GSList *l;
- PurpleAccount *acct;
- PurpleConversation *chat;
- PurpleConversationManager *manager;
- PurpleConnection *gc;
-
- gc = fb_data_get_connection(fata);
- acct = purple_connection_get_account(gc);
- fetch = g_hash_table_new(fb_id_hash, fb_id_equal);
-
- manager = purple_conversation_manager_get_default();
-
- for (l = events; l != NULL; l = l->next) {
- event = l->data;
-
- FB_ID_TO_STR(event->tid, tid);
- chat = purple_conversation_manager_find_chat(manager, acct, tid);
-
- if (chat == NULL) {
- continue;
- }
-
- FB_ID_TO_STR(event->uid, uid);
-
- switch (event->type) {
- case FB_API_EVENT_TYPE_THREAD_TOPIC:
- purple_chat_conversation_set_topic(PURPLE_CHAT_CONVERSATION(chat), uid,
- event->text);
- break;
-
- case FB_API_EVENT_TYPE_THREAD_USER_ADDED:
- if (purple_blist_find_buddy(acct, uid) == NULL) {
- if (event->text) {
- FbApiUser *user = g_new0(FbApiUser, 1);
- user->uid = event->uid;
- user->name = g_strdup(event->text);
-
- fb_buddy_add_nonfriend(acct, user);
-
- fb_api_user_free(user);
- } else {
- g_hash_table_insert(fetch, &event->tid, event);
- break;
- }
- }
-
- purple_chat_conversation_add_user(PURPLE_CHAT_CONVERSATION(chat), uid, NULL, 0,
- TRUE);
- break;
-
- case FB_API_EVENT_TYPE_THREAD_USER_REMOVED:
- purple_chat_conversation_remove_user(PURPLE_CHAT_CONVERSATION(chat), uid, event->text);
- break;
- }
- }
-
- g_hash_table_iter_init(&iter, fetch);
-
- while (g_hash_table_iter_next(&iter, NULL, (gpointer) &event)) {
- fb_api_thread(api, event->tid);
- }
-
- g_hash_table_destroy(fetch);
-}
-
-static void
-fb_cb_image(FbDataImage *img, GError *error)
-{
- const gchar *url;
- FbApi *api;
- FbApiMessage *msg;
- FbData *fata;
- gsize size;
- GSList *msgs = NULL;
- guint id;
- guint8 *image;
- PurpleImage *pimg;
-
- fata = fb_data_image_get_fata(img);
- msg = fb_data_image_get_data(img);
-
- if (G_UNLIKELY(error != NULL)) {
- url = fb_data_image_get_url(img);
- fb_util_debug_warning("Failed to retrieve image %s: %s",
- url, error->message);
- return;
- }
-
- api = fb_data_get_api(fata);
- image = fb_data_image_dup_image(img, &size);
- pimg = purple_image_new_from_data(image, size);
- id = purple_image_store_add_weak(pimg);
-
- g_free(msg->text);
- msg->text = g_strdup_printf("<img src=\""
- PURPLE_IMAGE_STORE_PROTOCOL
- "%u\">", id);
- msg->flags |= FB_API_MESSAGE_FLAG_DONE;
-
- msgs = g_slist_prepend(msgs, msg);
- fb_cb_api_messages(api, msgs, fata);
- g_slist_free(msgs);
-}
-
-static void
-fb_cb_api_messages(FbApi *api, GSList *msgs, gpointer data)
-{
- const gchar *text;
- FbApiMessage *msg;
- FbData *fata = data;
- gboolean isself;
- gboolean mark;
- gboolean open;
- gboolean self;
- gchar *html;
- gchar tid[FB_ID_STRMAX];
- gchar uid[FB_ID_STRMAX];
- gint id;
- gint64 tstamp;
- GSList *l;
- PurpleAccount *acct;
- PurpleConversation *chat;
- PurpleConversationManager *manager;
- PurpleConnection *gc;
- PurpleMessageFlags flags;
-
- gc = fb_data_get_connection(fata);
- acct = purple_connection_get_account(gc);
- mark = purple_account_get_bool(acct, "mark-read", TRUE);
- open = purple_account_get_bool(acct, "group-chat-open", TRUE);
- self = purple_account_get_bool(acct, "show-self", TRUE);
-
- manager = purple_conversation_manager_get_default();
-
- for (l = msgs; l != NULL; l = l->next) {
- msg = l->data;
- FB_ID_TO_STR(msg->uid, uid);
-
- if (purple_blist_find_buddy(acct, uid) == NULL) {
- msg = fb_api_message_dup(msg);
- fb_data_add_message(fata, msg);
- fb_api_contact(api, msg->uid);
- continue;
- }
-
- isself = (msg->flags & FB_API_MESSAGE_FLAG_SELF) != 0;
-
- if (isself && !self) {
- continue;
- }
-
- flags = isself ? PURPLE_MESSAGE_SEND : PURPLE_MESSAGE_RECV;
- tstamp = msg->tstamp / 1000;
-
- if (msg->flags & FB_API_MESSAGE_FLAG_IMAGE) {
- if (!(msg->flags & FB_API_MESSAGE_FLAG_DONE)) {
- msg = fb_api_message_dup(msg);
- fb_data_image_add(fata, msg->text, fb_cb_image,
- msg, (GDestroyNotify)
- fb_api_message_free);
- fb_data_image_queue(fata);
- continue;
- }
-
- flags |= PURPLE_MESSAGE_IMAGES;
- text = msg->text;
- html = NULL;
- } else {
- html = g_markup_escape_text(msg->text, -1);
- text = html;
- }
-
- if (msg->tid == 0) {
- if (mark && !isself) {
- fb_data_set_unread(fata, msg->uid, TRUE);
- }
-
- fb_util_serv_got_im(gc, uid, text, flags, tstamp);
- g_free(html);
- continue;
- }
-
- FB_ID_TO_STR(msg->tid, tid);
- chat = purple_conversation_manager_find_chat(manager, acct, tid);
-
- if (chat == NULL) {
- if (!open) {
- g_free(html);
- continue;
- }
-
- id = fb_id_hash(&msg->tid);
- purple_serv_got_joined_chat(gc, id, tid);
- fb_api_thread(api, msg->tid);
- } else {
- id = purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat));
- }
-
- if (mark && !isself) {
- fb_data_set_unread(fata, msg->tid, TRUE);
- }
-
- fb_util_serv_got_chat_in(gc, id, uid, text, flags, tstamp);
- g_free(html);
- }
-}
-
-static void
-fb_cb_api_presences(G_GNUC_UNUSED FbApi *api, GSList *presences, gpointer data)
-{
- const gchar *statid;
- FbData *fata = data;
- gchar uid[FB_ID_STRMAX];
- GSList *l;
- PurpleAccount *acct;
- PurpleConnection *gc;
- PurpleStatusPrimitive pstat;
-
- gc = fb_data_get_connection(fata);
- acct = purple_connection_get_account(gc);
-
- for (l = presences; l != NULL; l = l->next) {
- FbApiPresence *api_presence = l->data;
-
- if (api_presence->active) {
- pstat = PURPLE_STATUS_AVAILABLE;
- } else {
- pstat = PURPLE_STATUS_OFFLINE;
- }
-
- FB_ID_TO_STR(api_presence->uid, uid);
- statid = purple_primitive_get_id_from_type(pstat);
- purple_protocol_got_user_status(acct, uid, statid, NULL);
- }
-}
-
-static void
-fb_cb_api_thread(G_GNUC_UNUSED FbApi *api, FbApiThread *thrd, gpointer data)
-{
- const gchar *name;
- FbApiUser *user;
- FbData *fata = data;
- gboolean active;
- gchar tid[FB_ID_STRMAX];
- gchar uid[FB_ID_STRMAX];
- gint id;
- GSList *l;
- PurpleAccount *acct;
- PurpleConversation *conv;
- PurpleConversationManager *manager;
- PurpleChatConversation *chat;
- PurpleConnection *gc;
-
- gc = fb_data_get_connection(fata);
- acct = purple_connection_get_account(gc);
- id = fb_id_hash(&thrd->tid);
- FB_ID_TO_STR(thrd->tid, tid);
-
- manager = purple_conversation_manager_get_default();
- conv = purple_conversation_manager_find_chat(manager, acct, tid);
- if((conv == NULL) || purple_chat_conversation_has_left(PURPLE_CHAT_CONVERSATION(conv))) {
- conv = purple_serv_got_joined_chat(gc, id, tid);
- chat = PURPLE_CHAT_CONVERSATION(conv);
- active = FALSE;
- } else {
- /* If there are no users in the group chat, including
- * the local user, then the group chat has yet to be
- * setup by this function. As a result, any group chat
- * without users is inactive.
- */
- chat = PURPLE_CHAT_CONVERSATION(conv);
- active = purple_chat_conversation_get_users_count(chat) > 0;
- }
-
- if (!active) {
- name = purple_contact_info_get_username(PURPLE_CONTACT_INFO(acct));
- purple_chat_conversation_add_user(chat, name, NULL, 0, FALSE);
- }
-
- purple_chat_conversation_set_topic(chat, NULL, thrd->topic);
-
- for (l = thrd->users; l != NULL; l = l->next) {
- user = l->data;
- FB_ID_TO_STR(user->uid, uid);
-
- if (purple_chat_conversation_has_user(chat, uid)) {
- continue;
- }
-
- if (purple_blist_find_buddy(acct, uid) == NULL) {
- fb_buddy_add_nonfriend(acct, user);
- }
-
- purple_chat_conversation_add_user(chat, uid, NULL, 0, active);
- }
-}
-
-static void
-fb_cb_api_thread_create(G_GNUC_UNUSED FbApi *api, FbId tid, gpointer data)
-{
- FbData *fata = data;
- gchar sid[FB_ID_STRMAX];
- GHashTable *table;
- PurpleConnection *gc;
-
- gc = fb_data_get_connection(fata);
- FB_ID_TO_STR(tid, sid);
-
- table = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
- g_hash_table_insert(table, "name", g_strdup(sid));
- purple_serv_join_chat(gc, table);
- g_hash_table_destroy(table);
-}
-
-static void
-fb_cb_api_thread_kicked(G_GNUC_UNUSED FbApi *api, FbApiThread *thrd,
- gpointer data)
-{
- FbData *fata = data;
- gchar tid[FB_ID_STRMAX];
- PurpleAccount *acct;
- PurpleConnection *gc;
- PurpleConversation *chat;
- PurpleConversationManager *manager;
-
- FB_ID_TO_STR(thrd->tid, tid);
-
- gc = fb_data_get_connection(fata);
- acct = purple_connection_get_account(gc);
-
- manager = purple_conversation_manager_get_default();
- chat = purple_conversation_manager_find_chat(manager, acct, tid);
-
- if (chat == NULL) {
- PurpleRequestCommonParameters *cpar;
-
- cpar = purple_request_cpar_from_connection(gc);
- purple_notify_error(gc,
- _("Join a Chat"),
- _("Failed to Join Chat"),
- _("You have been removed from this chat"),
- cpar);
- return;
- }
-
- purple_conversation_write_system_message(chat,
- _("You have been removed from this chat"), 0);
-
- purple_serv_got_chat_left(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(chat)));
-}
-
-static void
-fb_cb_api_threads(G_GNUC_UNUSED FbApi *api, GSList *thrds, gpointer data)
-{
- const gchar *alias;
- FbApiUser *user;
- FbData *fata = data;
- gchar tid[FB_ID_STRMAX];
- gchar uid[FB_ID_STRMAX];
- GSList *l;
- GSList *m;
- GString *gstr;
- FbApiThread *thrd;
- PurpleAccount *acct;
- PurpleBuddy *bdy;
- PurpleConnection *gc;
- PurpleRoomlist *list;
- PurpleRoomlistRoom *room;
-
- list = fb_data_get_roomlist(fata);
-
- if (G_UNLIKELY(list == NULL)) {
- return;
- }
-
- gc = fb_data_get_connection(fata);
- acct = purple_connection_get_account(gc);
- gstr = g_string_new(NULL);
-
- for (l = thrds; l != NULL; l = l->next) {
- thrd = l->data;
- FB_ID_TO_STR(thrd->tid, tid);
- g_string_truncate(gstr, 0);
-
- for (m = thrd->users; m != NULL; m = m->next) {
- user = m->data;
- FB_ID_TO_STR(user->uid, uid);
- bdy = purple_blist_find_buddy(acct, uid);
-
- if (bdy != NULL) {
- alias = purple_buddy_get_alias(bdy);
- } else {
- alias = user->name;
- }
-
- if (gstr->len > 0) {
- g_string_append(gstr, ", ");
- }
-
- g_string_append(gstr, alias);
- }
-
- room = purple_roomlist_room_new(tid, thrd->topic);
- purple_roomlist_room_add_field(room, "topic", g_strdup(thrd->topic));
- purple_roomlist_room_add_field(room, "users", g_strdup(gstr->str));
- purple_roomlist_room_add(list, room);
- g_object_unref(room);
- }
-
- purple_roomlist_set_in_progress(list, FALSE);
- fb_data_set_roomlist(fata, NULL);
- g_string_free(gstr, TRUE);
-}
-
-static void
-fb_cb_api_typing(G_GNUC_UNUSED FbApi *api, FbApiTyping *typg, gpointer data)
-{
- FbData *fata = data;
- gchar uid[FB_ID_STRMAX];
- PurpleConnection *gc;
-
- gc = fb_data_get_connection(fata);
- FB_ID_TO_STR(typg->uid, uid);
-
- if (typg->state) {
- purple_serv_got_typing(gc, uid, 0, PURPLE_IM_TYPING);
- } else {
- purple_serv_got_typing_stopped(gc, uid);
- }
-}
-
-static void
-fb_mark_read(FbData *fata, FbId id, gboolean thread)
-{
- FbApi *api;
- PurpleAccount *acct;
- PurpleConnection *gc;
-
- gc = fb_data_get_connection(fata);
- acct = purple_connection_get_account(gc);
- api = fb_data_get_api(fata);
-
- if (!fb_data_get_unread(fata, id) ||
- (purple_account_get_bool(acct, "mark-read-available", FALSE) &&
- fb_api_is_invisible(api)))
- {
- return;
- }
-
- fb_data_set_unread(fata, id, FALSE);
- fb_api_read(api, id, thread);
-}
-
-static gboolean
-fb_cb_conv_read(gpointer data)
-{
- const gchar *name;
- FbData *fata;
- FbId id;
- gchar *tname;
- PurpleConnection *gc;
- PurpleConversation *conv = data;
-
- gc = purple_conversation_get_connection(conv);
- fata = purple_connection_get_protocol_data(gc);
- name = purple_conversation_get_name(conv);
- id = FB_ID_FROM_STR(name);
-
- tname = g_strconcat("conv-read-", name, NULL);
- fb_data_clear_timeout(fata, tname, FALSE);
- g_free(tname);
-
- if (purple_conversation_has_focus(conv)) {
- fb_mark_read(fata, id, PURPLE_IS_CHAT_CONVERSATION(conv));
- }
- return FALSE;
-}
-
-static void
-fb_cb_conv_updated(PurpleConversation *conv, PurpleConversationUpdateType type,
- gpointer data)
-{
- const gchar *name;
- const gchar *pid;
- FbData *fata = data;
- gchar *tname;
- PurpleAccount *acct;
-
- acct = purple_conversation_get_account(conv);
- pid = purple_account_get_protocol_id(acct);
-
- if ((type == PURPLE_CONVERSATION_UPDATE_UNSEEN) &&
- purple_strequal(pid, FB_PROTOCOL_ID) &&
- purple_account_get_bool(acct, "mark-read", TRUE))
- {
- /* Use event loop for purple_conversation_has_focus() */
- name = purple_conversation_get_name(conv);
- tname = g_strconcat("conv-read-", name, NULL);
- fb_data_save_timeout(fata, tname,
- g_timeout_add_seconds(0, fb_cb_conv_read, conv));
- g_free(tname);
- }
-}
-
-static void
-fb_cb_conv_deleting(PurpleConversation *conv, gpointer data)
-{
- const gchar *name;
- const gchar *pid;
- FbData *fata = data;
- gchar *tname;
- PurpleAccount *acct;
-
- acct = purple_conversation_get_account(conv);
- pid = purple_account_get_protocol_id(acct);
-
- if (!purple_strequal(pid, FB_PROTOCOL_ID)) {
- return;
- }
-
- name = purple_conversation_get_name(conv);
- tname = g_strconcat("conv-read-", name, NULL);
- fb_data_clear_timeout(fata, tname, TRUE);
- g_free(tname);
-}
-
-static void
-fb_blist_chat_create(GSList *buddies, gpointer data)
-{
- const gchar *name;
- FbApi *api;
- FbData *fata = data;
- FbId *did;
- FbId uid;
- GSList *l;
- GSList *uids = NULL;
- PurpleConnection *gc;
- PurpleRequestCommonParameters *cpar;
-
- gc = fb_data_get_connection(fata);
- api = fb_data_get_api(fata);
-
- if (g_slist_length(buddies) < 2) {
- cpar = purple_request_cpar_from_connection(gc);
- purple_notify_error(gc,
- _("Initiate Chat"),
- _("Failed to Initiate Chat"),
- _("At least two initial chat participants"
- " are required."),
- cpar);
- return;
- }
-
- for (l = buddies; l != NULL; l = l->next) {
- name = purple_buddy_get_name(l->data);
- uid = FB_ID_FROM_STR(name);
- did = g_memdup2(&uid, sizeof uid);
- uids = g_slist_prepend(uids, did);
- }
-
- fb_api_thread_create(api, uids);
- g_slist_free_full(uids, g_free);
-}
-
-static void
-fb_blist_chat_init(PurpleBlistNode *node, gpointer data)
-{
- FbData *fata = data;
- GSList *select = NULL;
- PurpleConnection *gc;
-
- if (!PURPLE_IS_BUDDY(node)) {
- return;
- }
-
- gc = fb_data_get_connection(fata);
- select = g_slist_prepend(select, PURPLE_BUDDY(node));
-
- fb_util_request_buddy(gc,
- _("Initiate Chat"),
- _("Initial Chat Participants"),
- _("Select at least two initial participants."),
- select, TRUE,
- G_CALLBACK(fb_blist_chat_create), NULL,
- fata);
- g_slist_free(select);
-}
-
-static GList *
-fb_get_account_options(G_GNUC_UNUSED PurpleProtocol *protocol) {
- GList *opts = NULL;
- PurpleAccountOption *opt;
-
- opt = purple_account_option_int_new(_("Buddy list sync interval"),
- "sync-interval", 5);
- opts = g_list_prepend(opts, opt);
-
- opt = purple_account_option_bool_new(_("Mark messages as read on focus"),
- "mark-read", TRUE);
- opts = g_list_prepend(opts, opt);
-
- opt = purple_account_option_bool_new(_("Mark messages as read only when available"),
- "mark-read-available", FALSE);
- opts = g_list_prepend(opts, opt);
-
- opt = purple_account_option_bool_new(_("Show self messages"),
- "show-self", TRUE);
- opts = g_list_prepend(opts, opt);
-
- opt = purple_account_option_bool_new(_("Show unread messages"),
- "show-unread", TRUE);
- opts = g_list_prepend(opts, opt);
-
- opt = purple_account_option_bool_new(_("Open new group chats with "
- "incoming messages"),
- "group-chat-open", TRUE);
- opts = g_list_prepend(opts, opt);
-
- return g_list_reverse(opts);
-}
-
-static void
-fb_login(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleAccount *acct) {
- const gchar *pass;
- const gchar *user;
- FbApi *api;
- FbData *fata;
- gpointer convh;
- PurpleConnection *gc;
- GProxyResolver *resolver;
- GError *error = NULL;
-
- gc = purple_account_get_connection(acct);
-
- resolver = purple_proxy_get_proxy_resolver(acct, &error);
- if (resolver == NULL) {
- fb_util_debug_error("Unable to get account proxy resolver: %s",
- error->message);
- purple_connection_take_error(gc, error);
- return;
- }
-
- fata = fb_data_new(gc, resolver);
- api = fb_data_get_api(fata);
- convh = purple_conversations_get_handle();
- purple_connection_set_protocol_data(gc, fata);
-
- g_signal_connect(api,
- "auth",
- G_CALLBACK(fb_cb_api_auth),
- fata);
- g_signal_connect(api,
- "connect",
- G_CALLBACK(fb_cb_api_connect),
- fata);
- g_signal_connect(api,
- "contact",
- G_CALLBACK(fb_cb_api_contact),
- fata);
- g_signal_connect(api,
- "contacts",
- G_CALLBACK(fb_cb_api_contacts),
- fata);
- g_signal_connect(api,
- "contacts-delta",
- G_CALLBACK(fb_cb_api_contacts_delta),
- fata);
- g_signal_connect(api,
- "error",
- G_CALLBACK(fb_cb_api_error),
- fata);
- g_signal_connect(api,
- "events",
- G_CALLBACK(fb_cb_api_events),
- fata);
- g_signal_connect(api,
- "messages",
- G_CALLBACK(fb_cb_api_messages),
- fata);
- g_signal_connect(api,
- "presences",
- G_CALLBACK(fb_cb_api_presences),
- fata);
- g_signal_connect(api,
- "thread",
- G_CALLBACK(fb_cb_api_thread),
- fata);
- g_signal_connect(api,
- "thread-create",
- G_CALLBACK(fb_cb_api_thread_create),
- fata);
- g_signal_connect(api,
- "thread-kicked",
- G_CALLBACK(fb_cb_api_thread_kicked),
- fata);
- g_signal_connect(api,
- "threads",
- G_CALLBACK(fb_cb_api_threads),
- fata);
- g_signal_connect(api,
- "typing",
- G_CALLBACK(fb_cb_api_typing),
- fata);
-
- purple_signal_connect(convh,
- "conversation-updated",
- gc,
- G_CALLBACK(fb_cb_conv_updated),
- fata);
- purple_signal_connect(convh,
- "deleting-conversation",
- gc,
- G_CALLBACK(fb_cb_conv_deleting),
- fata);
-
- if (!fb_data_load(fata) || !purple_account_get_remember_password(acct)) {
- user = purple_contact_info_get_username(PURPLE_CONTACT_INFO(acct));
- pass = purple_connection_get_password(gc);
- fb_api_auth(api, user, pass);
- return;
- }
-
- fb_api_contacts(api);
-}
-
-static void
-fb_close(G_GNUC_UNUSED PurpleProtocol *protocol, PurpleConnection *gc) {
- FbApi *api;
- FbData *fata;
-
- fata = purple_connection_get_protocol_data(gc);
- api = fb_data_get_api(fata);
-
- fb_data_save(fata);
- fb_api_disconnect(api);
- g_object_unref(fata);
-
- purple_connection_set_protocol_data(gc, NULL);
- purple_signals_disconnect_by_handle(gc);
-}
-
-static GList *
-fb_status_types(G_GNUC_UNUSED PurpleProtocol *protocol,
- G_GNUC_UNUSED PurpleAccount *acct)
-{
- PurpleStatusType *type;
- GList *types = NULL;
-
- type = purple_status_type_new(PURPLE_STATUS_AVAILABLE,
- NULL, NULL, TRUE);
- types = g_list_prepend(types, type);
-
- /* Just a NULL state (as of now) for compatibility */
- type = purple_status_type_new(PURPLE_STATUS_AWAY,
- NULL, NULL, TRUE);
- types = g_list_prepend(types, type);
-
- type = purple_status_type_new(PURPLE_STATUS_INVISIBLE,
- NULL, NULL, TRUE);
- types = g_list_prepend(types, type);
-
- type = purple_status_type_new(PURPLE_STATUS_OFFLINE,
- NULL, NULL, TRUE);
- types = g_list_prepend(types, type);
-
- return g_list_reverse(types);
-}
-
-static GList *
-fb_client_blist_node_menu(G_GNUC_UNUSED PurpleProtocolClient *client,
- PurpleBlistNode *node)
-{
- FbData *fata;
- GList *acts = NULL;
- PurpleAccount *acct;
- PurpleConnection *gc;
- PurpleActionMenu *act;
-
- if (!PURPLE_IS_BUDDY(node)) {
- return NULL;
- }
-
- acct = purple_buddy_get_account(PURPLE_BUDDY(node));
- gc = purple_account_get_connection(acct);
- fata = purple_connection_get_protocol_data(gc);
-
- act = purple_action_menu_new(_("Initiate _Chat"),
- G_CALLBACK(fb_blist_chat_init),
- fata, NULL);
- acts = g_list_prepend(acts, act);
-
- return g_list_reverse(acts);
-}
-
-static gboolean
-fb_client_offline_message(G_GNUC_UNUSED PurpleProtocolClient *client,
- G_GNUC_UNUSED PurpleBuddy *buddy)
-{
- return TRUE;
-}
-
-static void
-fb_server_set_status(G_GNUC_UNUSED PurpleProtocolServer *protocol_server,
- PurpleAccount *acct, PurpleStatus *status)
-{
- FbApi *api;
- FbData *fata;
- gboolean invis;
- PurpleConnection *gc;
- PurpleStatusPrimitive pstat;
- PurpleStatusType *type;
-
- gc = purple_account_get_connection(acct);
- fata = purple_connection_get_protocol_data(gc);
- api = fb_data_get_api(fata);
-
- type = purple_status_get_status_type(status);
- pstat = purple_status_type_get_primitive(type);
- invis = fb_api_is_invisible(api);
-
- if ((pstat == PURPLE_STATUS_INVISIBLE) && !invis) {
- fb_api_connect(api, TRUE);
- } else if ((pstat != PURPLE_STATUS_OFFLINE) && invis) {
- fb_api_connect(api, FALSE);
- }
-}
-
-static gint
-fb_im_send(G_GNUC_UNUSED PurpleProtocolIM *im, PurpleConnection *gc,
- PurpleMessage *msg)
-{
- const gchar *name;
- const gchar *text;
- FbApi *api;
- FbData *fata;
- FbId uid;
- gchar *sext;
-
- fata = purple_connection_get_protocol_data(gc);
- api = fb_data_get_api(fata);
-
- name = purple_message_get_recipient(msg);
- uid = FB_ID_FROM_STR(name);
-
- text = purple_message_get_contents(msg);
- sext = purple_markup_strip_html(text);
- fb_api_message(api, uid, FALSE, sext);
- g_free(sext);
- return 1;
-}
-
-static guint
-fb_im_send_typing(G_GNUC_UNUSED PurpleProtocolIM *im, PurpleConnection *gc,
- const gchar *name, PurpleIMTypingState state)
-{
- FbApi *api;
- FbData *fata;
- FbId uid;
-
- fata = purple_connection_get_protocol_data(gc);
- api = fb_data_get_api(fata);
- uid = FB_ID_FROM_STR(name);
-
- fb_api_typing(api, uid, state != PURPLE_IM_NOT_TYPING);
- return 0;
-}
-
-static GList *
-fb_chat_info(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
- G_GNUC_UNUSED PurpleConnection *connection)
-{
- GList *pces = NULL;
- PurpleProtocolChatEntry *pce;
-
- pce = g_new0(PurpleProtocolChatEntry, 1);
- pce->label = _("Chat _Name");
- pce->identifier = "name";
- pce->required = TRUE;
- pces = g_list_prepend(pces, pce);
-
- return g_list_reverse(pces);
-}
-
-static GHashTable *
-fb_chat_info_defaults(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
- G_GNUC_UNUSED PurpleConnection *connection,
- const gchar *name)
-{
- GHashTable *data;
-
- data = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
- g_hash_table_insert(data, "name", g_strdup(name));
-
- return data;
-}
-
-static void
-fb_chat_join(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
- PurpleConnection *gc, GHashTable *data)
-{
- const gchar *name;
- FbApi *api;
- FbData *fata;
- FbId tid;
- gint id;
- PurpleConversation *chat;
- PurpleConversationManager *manager;
- PurpleRequestCommonParameters *cpar;
-
- name = g_hash_table_lookup(data, "name");
- g_return_if_fail(name != NULL);
-
- if (!FB_ID_IS_STR(name)) {
- cpar = purple_request_cpar_from_connection(gc);
- purple_notify_error(gc,
- _("Join a Chat"),
- _("Failed to Join Chat"),
- _("Invalid Facebook identifier."),
- cpar);
- return;
- }
-
- tid = FB_ID_FROM_STR(name);
- id = fb_id_hash(&tid);
-
- manager = purple_conversation_manager_get_default();
- chat = purple_conversation_manager_find_chat_by_id(manager,
- purple_connection_get_account(gc),
- id);
-
- if ((chat != NULL) && !purple_chat_conversation_has_left(PURPLE_CHAT_CONVERSATION(chat))) {
- purple_conversation_present(chat);
- return;
- }
-
- fata = purple_connection_get_protocol_data(gc);
- api = fb_data_get_api(fata);
- fb_api_thread(api, tid);
-}
-
-static gchar *
-fb_chat_get_name(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
- GHashTable *data)
-{
- const gchar *name;
-
- name = g_hash_table_lookup(data, "name");
- g_return_val_if_fail(name != NULL, NULL);
-
- return g_strdup(name);
-}
-
-static void
-fb_chat_invite(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
- PurpleConnection *gc, gint id, G_GNUC_UNUSED const char *msg,
- const char *who)
-{
- const gchar *name;
- FbApi *api;
- FbData *fata;
- FbId tid;
- FbId uid;
- PurpleConversation *chat;
- PurpleConversationManager *manager;
- PurpleRequestCommonParameters *cpar;
-
- if (!FB_ID_IS_STR(who)) {
- cpar = purple_request_cpar_from_connection(gc);
- purple_notify_error(gc,
- _("Invite Buddy Into Chat Room"),
- _("Failed to Invite User"),
- _("Invalid Facebook identifier."),
- cpar);
- return;
- }
-
- fata = purple_connection_get_protocol_data(gc);
- api = fb_data_get_api(fata);
-
- manager = purple_conversation_manager_get_default();
- chat = purple_conversation_manager_find_chat_by_id(manager,
- purple_connection_get_account(gc),
- id);
-
- name = purple_conversation_get_name(chat);
- tid = FB_ID_FROM_STR(name);
- uid = FB_ID_FROM_STR(who);
-
- fb_api_thread_invite(api, tid, uid);
-}
-
-static gint
-fb_chat_send(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
- PurpleConnection *gc, gint id, PurpleMessage *msg)
-{
- const gchar *name;
- const gchar *text;
- FbApi *api;
- FbData *fata;
- FbId tid;
- gchar *sext;
- PurpleAccount *acct;
- PurpleConversation *chat;
- PurpleConversationManager *manager;
-
- acct = purple_connection_get_account(gc);
- fata = purple_connection_get_protocol_data(gc);
- api = fb_data_get_api(fata);
-
- manager = purple_conversation_manager_get_default();
- chat = purple_conversation_manager_find_chat_by_id(manager, acct, id);
-
- name = purple_conversation_get_name(chat);
- tid = FB_ID_FROM_STR(name);
-
- text = purple_message_get_contents(msg);
- sext = purple_markup_strip_html(text);
- fb_api_message(api, tid, TRUE, sext);
- g_free(sext);
-
- name = purple_contact_info_get_username(PURPLE_CONTACT_INFO(acct));
- purple_serv_got_chat_in(gc, id, name,
- purple_message_get_flags(msg),
- purple_message_get_contents(msg),
- time(NULL));
- return 0;
-}
-
-static void
-fb_chat_set_topic(G_GNUC_UNUSED PurpleProtocolChat *protocol_chat,
- PurpleConnection *gc, gint id, const char *topic)
-{
- const gchar *name;
- FbApi *api;
- FbData *fata;
- FbId tid;
- PurpleConversation *chat;
- PurpleConversationManager *manager;
-
- fata = purple_connection_get_protocol_data(gc);
- api = fb_data_get_api(fata);
-
- manager = purple_conversation_manager_get_default();
- chat = purple_conversation_manager_find_chat_by_id(manager,
- purple_connection_get_account(gc),
- id);
-
- name = purple_conversation_get_name(chat);
- tid = FB_ID_FROM_STR(name);
- fb_api_thread_topic(api, tid, topic);
-}
-
-static PurpleRoomlist *
-fb_roomlist_get_list(G_GNUC_UNUSED PurpleProtocolRoomlist *protocol_roomlist,
- PurpleConnection *gc)
-{
- FbApi *api;
- FbData *fata;
- PurpleAccount *acct;
- PurpleRoomlist *list;
-
- fata = purple_connection_get_protocol_data(gc);
- list = fb_data_get_roomlist(fata);
- g_return_val_if_fail(list == NULL, NULL);
-
- api = fb_data_get_api(fata);
- acct = purple_connection_get_account(gc);
- list = purple_roomlist_new(acct);
- fb_data_set_roomlist(fata, list);
-
- purple_roomlist_set_in_progress(list, TRUE);
- fb_api_threads(api);
- return list;
-}
-
-static void
-fb_roomlist_cancel(G_GNUC_UNUSED PurpleProtocolRoomlist *protocol_roomlist,
- PurpleRoomlist *list)
-{
- FbData *fata;
- PurpleAccount *acct;
- PurpleConnection *gc;
- PurpleRoomlist *cist;
-
- acct = purple_roomlist_get_account(list);
- gc = purple_account_get_connection(acct);
- fata = purple_connection_get_protocol_data(gc);
- cist = fb_data_get_roomlist(fata);
-
- if (G_LIKELY(cist == list)) {
- fb_data_set_roomlist(fata, NULL);
- }
-
- purple_roomlist_set_in_progress(list, FALSE);
- g_object_unref(list);
-}
-
-static PurpleCmdRet
-fb_cmd_kick(PurpleConversation *conv, G_GNUC_UNUSED const char *cmd,
- char **args, char **error, G_GNUC_UNUSED gpointer data)
-{
- const gchar *name;
- FbApi *api;
- FbData *fata;
- FbId tid;
- FbId uid;
- GError *err = NULL;
- PurpleAccount *acct;
- PurpleBuddy *bdy;
- PurpleConnection *gc;
- PurpleChatConversation *chat;
-
- g_return_val_if_fail(PURPLE_IS_CHAT_CONVERSATION(conv),
- PURPLE_CMD_RET_FAILED);
-
- gc = purple_conversation_get_connection(conv);
- acct = purple_connection_get_account(gc);
- chat = PURPLE_CHAT_CONVERSATION(conv);
- bdy = fb_util_account_find_buddy(acct, chat, args[0], &err);
-
- if (err != NULL) {
- *error = g_strdup_printf(_("%s."), err->message);
- g_error_free(err);
- return PURPLE_CMD_RET_FAILED;
- }
-
- fata = purple_connection_get_protocol_data(gc);
- api = fb_data_get_api(fata);
-
- name = purple_conversation_get_name(conv);
- tid = FB_ID_FROM_STR(name);
-
- name = purple_buddy_get_name(bdy);
- uid = FB_ID_FROM_STR(name);
-
- fb_api_thread_remove(api, tid, uid);
- return PURPLE_CMD_RET_OK;
-}
-
-static PurpleCmdRet
-fb_cmd_leave(PurpleConversation *conv, G_GNUC_UNUSED const char *cmd,
- G_GNUC_UNUSED char **args, G_GNUC_UNUSED char **error,
- G_GNUC_UNUSED gpointer data)
-{
- const gchar *name;
- FbApi *api;
- FbData *fata;
- FbId tid;
- gint id;
- PurpleConnection *gc;
- PurpleChatConversation *chat;
-
- g_return_val_if_fail(PURPLE_IS_CHAT_CONVERSATION(conv),
- PURPLE_CMD_RET_FAILED);
-
- gc = purple_conversation_get_connection(conv);
- fata = purple_connection_get_protocol_data(gc);
- api = fb_data_get_api(fata);
-
- chat = PURPLE_CHAT_CONVERSATION(conv);
- id = purple_chat_conversation_get_id(chat);
-
- name = purple_conversation_get_name(conv);
- tid = FB_ID_FROM_STR(name);
-
- purple_serv_got_chat_left(gc, id);
- fb_api_thread_remove(api, tid, 0);
- return PURPLE_CMD_RET_OK;
-}
-
-static void
-facebook_protocol_init(G_GNUC_UNUSED FacebookProtocol *self) {
-}
-
-static void
-facebook_protocol_class_init(FacebookProtocolClass *klass)
-{
- PurpleProtocolClass *protocol_class = PURPLE_PROTOCOL_CLASS(klass);
-
- protocol_class->get_account_options = fb_get_account_options;
-
- protocol_class->login = fb_login;
- protocol_class->close = fb_close;
- protocol_class->status_types = fb_status_types;
-}
-
-static void
-facebook_protocol_class_finalize(G_GNUC_UNUSED FacebookProtocolClass *klass)
-{
-}
-
-static void
-facebook_protocol_client_iface_init(PurpleProtocolClientInterface *iface)
-{
- iface->blist_node_menu = fb_client_blist_node_menu;
- iface->offline_message = fb_client_offline_message;
-}
-
-static void
-facebook_protocol_server_init(PurpleProtocolServerInterface *iface)
-{
- iface->set_status = fb_server_set_status;
-}
-
-static void
-facebook_protocol_im_iface_init(PurpleProtocolIMInterface *iface)
-{
- iface->send = fb_im_send;
- iface->send_typing = fb_im_send_typing;
-}
-
-static void
-facebook_protocol_chat_iface_init(PurpleProtocolChatInterface *iface)
-{
- iface->info = fb_chat_info;
- iface->info_defaults = fb_chat_info_defaults;
- iface->join = fb_chat_join;
- iface->get_name = fb_chat_get_name;
- iface->invite = fb_chat_invite;
- iface->send = fb_chat_send;
- iface->set_topic = fb_chat_set_topic;
-}
-
-static void
-facebook_protocol_roomlist_iface_init(PurpleProtocolRoomlistInterface *iface)
-{
- iface->get_list = fb_roomlist_get_list;
- iface->cancel = fb_roomlist_cancel;
-}
-
-G_DEFINE_DYNAMIC_TYPE_EXTENDED(
- FacebookProtocol,
- facebook_protocol,
- PURPLE_TYPE_PROTOCOL,
- G_TYPE_FLAG_FINAL,
- G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_CLIENT,
- facebook_protocol_client_iface_init)
- G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_SERVER,
- 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,
- facebook_protocol_chat_iface_init)
- G_IMPLEMENT_INTERFACE_DYNAMIC(PURPLE_TYPE_PROTOCOL_ROOMLIST,
- facebook_protocol_roomlist_iface_init))
-
-static void
-fb_cmds_register(void)
-{
- PurpleCmdId id;
-
- static PurpleCmdFlag cflags =
- PURPLE_CMD_FLAG_CHAT |
- PURPLE_CMD_FLAG_PROTOCOL_ONLY;
-
- g_return_if_fail(fb_cmds == NULL);
-
- id = purple_cmd_register("kick", "s", PURPLE_CMD_P_PROTOCOL, cflags,
- FB_PROTOCOL_ID, fb_cmd_kick,
- _("kick: Kick someone from the chat"),
- NULL);
- fb_cmds = g_slist_prepend(fb_cmds, GUINT_TO_POINTER(id));
-
- id = purple_cmd_register("leave", "", PURPLE_CMD_P_PROTOCOL, cflags,
- FB_PROTOCOL_ID, fb_cmd_leave,
- _("leave: Leave the chat"),
- NULL);
- fb_cmds = g_slist_prepend(fb_cmds, GUINT_TO_POINTER(id));
-}
-
-static void
-fb_cmds_unregister_free(gpointer data)
-{
- PurpleCmdId id = GPOINTER_TO_UINT(data);
- purple_cmd_unregister(id);
-}
-
-static void
-fb_cmds_unregister(void)
-{
- g_clear_slist(&fb_cmds, fb_cmds_unregister_free);
-}
-
-static GPluginPluginInfo *
-facebook_query(G_GNUC_UNUSED GError **error)
-{
- return purple_plugin_info_new(
- "id", FB_PROTOCOL_ID,
- "name", "Facebook Protocol",
- "version", DISPLAY_VERSION,
- "category", N_("Protocol"),
- "summary", N_("Facebook Protocol Plugin"),
- "description", N_("Facebook Protocol Plugin"),
- "website", PURPLE_WEBSITE,
- "abi-version", PURPLE_ABI_VERSION,
- "flags", PURPLE_PLUGIN_INFO_FLAGS_INTERNAL |
- PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD,
- NULL
- );
-}
-
-static gboolean
-facebook_load(GPluginPlugin *plugin, GError **error)
-{
- PurpleProtocolManager *manager = purple_protocol_manager_get_default();
-
- facebook_protocol_register_type(G_TYPE_MODULE(plugin));
- fb_protocol = g_object_new(FACEBOOK_TYPE_PROTOCOL,
- "id", FB_PROTOCOL_ID,
- "name", "Facebook",
- "description", _("Facebook Messenger allows "
- "you to talk with your "
- "friends on Facebook."),
- "icon-name", "im-facebook",
- "icon-resource-path", "/im/pidgin/libpurple/facebook/icons",
- "options", OPT_PROTO_CHAT_TOPIC,
- NULL);
-
- if(!purple_protocol_manager_register(manager, fb_protocol, error)) {
- g_clear_object(&fb_protocol);
-
- return FALSE;
- }
-
- fb_cmds_register();
- return TRUE;
-}
-
-static gboolean
-facebook_unload(G_GNUC_UNUSED GPluginPlugin *plugin,
- G_GNUC_UNUSED gboolean shutdown, GError **error)
-{
- PurpleProtocolManager *manager = purple_protocol_manager_get_default();
-
- if(!purple_protocol_manager_unregister(manager, fb_protocol, error)) {
- return FALSE;
- }
-
- fb_cmds_unregister();
-
- g_clear_object(&fb_protocol);
-
- return TRUE;
-}
-
-GPLUGIN_NATIVE_PLUGIN_DECLARE(facebook)
diff --git a/libpurple/protocols/facebook/facebook.h b/libpurple/protocols/facebook/facebook.h
deleted file mode 100644
index 17c3bfda8a..0000000000
--- a/libpurple/protocols/facebook/facebook.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#ifndef PURPLE_FACEBOOK_FACEBOOK_H
-#define PURPLE_FACEBOOK_FACEBOOK_H
-
-#include <glib.h>
-#include <gmodule.h>
-
-#define FACEBOOK_TYPE_PROTOCOL (facebook_protocol_get_type())
-G_DECLARE_FINAL_TYPE(FacebookProtocol, facebook_protocol, FACEBOOK, PROTOCOL,
- PurpleProtocol)
-
-/**
- * FB_PROTOCOL_ID:
- *
- * The Facebook protocol identifier.
- */
-#define FB_PROTOCOL_ID "prpl-facebook"
-
-/**
- * FacebookProtocol:
- *
- * Represents the Facebook #PurpleProtocol.
- */
-
-/**
- * FacebookProtocolClass:
- *
- * The base class for all #FacebookProtocol's.
- */
-
-#endif /* PURPLE_FACEBOOK_FACEBOOK_H */
diff --git a/libpurple/protocols/facebook/http.c b/libpurple/protocols/facebook/http.c
deleted file mode 100644
index 86ff94c304..0000000000
--- a/libpurple/protocols/facebook/http.c
+++ /dev/null
@@ -1,282 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#include <glib/gi18n-lib.h>
-
-#include <string.h>
-
-#include "http.h"
-
-GQuark
-fb_http_error_quark(void)
-{
- static GQuark q = 0;
-
- if (G_UNLIKELY(q == 0)) {
- q = g_quark_from_static_string("fb-http-error-quark");
- }
-
- return q;
-}
-
-gboolean
-fb_http_error_chk(SoupMessage *res, GError **error)
-{
- SoupStatus status_code = soup_message_get_status(res);
-
- if (SOUP_STATUS_IS_SUCCESSFUL(status_code)) {
- return TRUE;
- }
-
- g_set_error(error, FB_HTTP_ERROR, status_code, "%s",
- soup_message_get_reason_phrase(res));
- return FALSE;
-}
-
-FbHttpParams *
-fb_http_params_new(void)
-{
- return g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
-}
-
-FbHttpParams *
-fb_http_params_new_parse(const gchar *data, gboolean isurl)
-{
- gchar *query = NULL;
- FbHttpParams *params;
-
- if (data == NULL) {
- return fb_http_params_new();
- }
-
- if (isurl) {
- if (!g_uri_split(data, G_URI_FLAGS_ENCODED_QUERY, NULL, NULL, NULL,
- NULL, NULL, &query, NULL, NULL))
- {
- return fb_http_params_new();
- }
-
- data = query;
- }
-
- params = soup_form_decode(data);
-
- g_free(query);
-
- return params;
-}
-
-void
-fb_http_params_free(FbHttpParams *params)
-{
- g_hash_table_destroy(params);
-}
-
-static const gchar *
-fb_http_params_get(FbHttpParams *params, const gchar *name, GError **error)
-{
- const gchar *ret;
-
- ret = g_hash_table_lookup(params, name);
-
- if (ret == NULL) {
- g_set_error(error, FB_HTTP_ERROR, FB_HTTP_ERROR_NOMATCH,
- _("No matches for %s"), name);
- return NULL;
- }
-
- return ret;
-}
-
-gboolean
-fb_http_params_get_bool(FbHttpParams *params, const gchar *name,
- GError **error)
-{
- const gchar *val;
-
- val = fb_http_params_get(params, name, error);
-
- if (val == NULL) {
- return FALSE;
- }
-
- return g_ascii_strcasecmp(val, "TRUE") == 0;
-}
-
-gdouble
-fb_http_params_get_dbl(FbHttpParams *params, const gchar *name,
- GError **error)
-{
- const gchar *val;
-
- val = fb_http_params_get(params, name, error);
-
- if (val == NULL) {
- return 0.0;
- }
-
- return g_ascii_strtod(val, NULL);
-}
-
-gint64
-fb_http_params_get_int(FbHttpParams *params, const gchar *name,
- GError **error)
-{
- const gchar *val;
-
- val = fb_http_params_get(params, name, error);
-
- if (val == NULL) {
- return 0;
- }
-
- return g_ascii_strtoll(val, NULL, 10);
-}
-
-const gchar *
-fb_http_params_get_str(FbHttpParams *params, const gchar *name,
- GError **error)
-{
- return fb_http_params_get(params, name, error);
-}
-
-gchar *
-fb_http_params_dup_str(FbHttpParams *params, const gchar *name,
- GError **error)
-{
- const gchar *str;
-
- str = fb_http_params_get(params, name, error);
- return g_strdup(str);
-}
-
-static void
-fb_http_params_set(FbHttpParams *params, const gchar *name, gchar *value)
-{
- gchar *key;
-
- key = g_strdup(name);
- g_hash_table_replace(params, key, value);
-}
-
-void
-fb_http_params_set_bool(FbHttpParams *params, const gchar *name,
- gboolean value)
-{
- gchar *val;
-
- val = g_strdup(value ? "true" : "false");
- fb_http_params_set(params, name, val);
-}
-
-void
-fb_http_params_set_dbl(FbHttpParams *params, const gchar *name, gdouble value)
-{
- gchar *val;
-
- val = g_strdup_printf("%f", value);
- fb_http_params_set(params, name, val);
-}
-
-void
-fb_http_params_set_int(FbHttpParams *params, const gchar *name, gint64 value)
-{
- gchar *val;
-
- val = g_strdup_printf("%" G_GINT64_FORMAT, value);
- fb_http_params_set(params, name, val);
-}
-
-void
-fb_http_params_set_str(FbHttpParams *params, const gchar *name,
- const gchar *value)
-{
- gchar *val;
-
- val = g_strdup(value);
- fb_http_params_set(params, name, val);
-}
-
-void
-fb_http_params_set_strf(FbHttpParams *params, const gchar *name,
- const gchar *format, ...)
-{
- gchar *val;
- va_list ap;
-
- va_start(ap, format);
- val = g_strdup_vprintf(format, ap);
- va_end(ap);
-
- fb_http_params_set(params, name, val);
-}
-
-gboolean
-fb_http_urlcmp(const gchar *url1, const gchar *url2, gboolean protocol)
-{
- gboolean ret = TRUE;
- GUri *uri1, *uri2;
-
- if ((url1 == NULL) || (url2 == NULL)) {
- return url1 == url2;
- }
-
- if (strstr(url1, url2) != NULL || strstr(url2, url1) != NULL) {
- return TRUE;
- }
-
- uri1 = g_uri_parse(url1, SOUP_HTTP_URI_FLAGS, NULL);
- if (uri1 == NULL) {
- return g_ascii_strcasecmp(url1, url2) == 0;
- }
-
- uri2 = g_uri_parse(url2, SOUP_HTTP_URI_FLAGS, NULL);
- if (uri2 == NULL) {
- g_uri_unref(uri1);
- return g_ascii_strcasecmp(url1, url2) == 0;
- }
-
- if (!protocol) {
- /* Force the same scheme (and same port). */
- GUri *tmp = NULL;
-
- tmp = soup_uri_copy(uri1,
- SOUP_URI_SCHEME, "https",
- SOUP_URI_PORT, 443,
- SOUP_URI_NONE);
- g_uri_unref(uri1);
- uri1 = tmp;
-
- tmp = soup_uri_copy(uri2,
- SOUP_URI_SCHEME, "https",
- SOUP_URI_PORT, 443,
- SOUP_URI_NONE);
- g_uri_unref(uri2);
- uri2 = tmp;
- }
-
- ret = soup_uri_equal(uri1, uri2);
-
- g_uri_unref(uri1);
- g_uri_unref(uri2);
-
- return ret;
-}
diff --git a/libpurple/protocols/facebook/http.h b/libpurple/protocols/facebook/http.h
deleted file mode 100644
index 05be2c3eff..0000000000
--- a/libpurple/protocols/facebook/http.h
+++ /dev/null
@@ -1,266 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#ifndef PURPLE_FACEBOOK_HTTP_H
-#define PURPLE_FACEBOOK_HTTP_H
-
-#include <glib.h>
-#include <libsoup/soup.h>
-
-/**
- * FB_HTTP_ERROR:
- *
- * The #GQuark of the domain of HTTP errors.
- */
-#define FB_HTTP_ERROR fb_http_error_quark()
-
-/**
- * FbHttpParams:
- *
- * Represents a set of key/value HTTP parameters.
- */
-typedef GHashTable FbHttpParams;
-
-/**
- * FbHttpError:
- * @FB_HTTP_ERROR_SUCCESS: There is no error.
- * @FB_HTTP_ERROR_NOMATCH: The name does not match anything.
- *
- * The error codes for the #FB_HTTP_ERROR domain.
- */
-typedef enum
-{
- FB_HTTP_ERROR_SUCCESS = 0,
- FB_HTTP_ERROR_NOMATCH
-} FbHttpError;
-
-/**
- * fb_http_error_quark:
- *
- * Gets the #GQuark of the domain of HTTP errors.
- *
- * Returns: The #GQuark of the domain.
- */
-GQuark
-fb_http_error_quark(void);
-
-/**
- * fb_http_error_chk:
- * @res: The #SoupMessage.
- * @error: The return location for the #GError or #NULL.
- *
- * Checks a #SoupMessage for success. This optionally assigns an
- * appropriate #GError upon failure.
- *
- * Returns: #TRUE if the request was successful, otherwise #FALSE.
- */
-gboolean fb_http_error_chk(SoupMessage *res, GError **error);
-
-/**
- * fb_http_params_new:
- *
- * Creates a new #FbHttpParams. The returned #FbHttpParams should be
- * freed with #fb_http_params_free() when no longer needed. Optionally,
- * instead of freeing, the returned #FbHttpParams can be closed with
- * #fb_http_params_close().
- *
- * Returns: (transfer full): The new #FbHttpParams.
- */
-FbHttpParams *
-fb_http_params_new(void);
-
-/**
- * fb_http_params_new_parse:
- * @data: The string containing HTTP parameters.
- * @isurl: #TRUE if @data is a URL, otherwise #FALSE.
- *
- * Creates a new #FbHttpParams. This parses the #FbHttpParams from a
- * string, which can be a URL. The returned #FbHttpParams should be
- * freed with #fb_http_params_free() when no longer needed. Optionally,
- * instead of freeing, the returned #FbHttpParams can be closed with
- * #fb_http_params_close().
- *
- * Returns: (transfer full): The new #FbHttpParams.
- */
-FbHttpParams *
-fb_http_params_new_parse(const gchar *data, gboolean isurl);
-
-/**
- * fb_http_params_free:
- * @params: The #FbHttpParams.
- *
- * Frees all memory used by the #FbHttpParams.
- */
-void
-fb_http_params_free(FbHttpParams *params);
-
-/**
- * fb_http_params_get_bool:
- * @params: The #FbHttpParams.
- * @name: The parameter name.
- * @error: The return location for the #GError or #NULL.
- *
- * Gets a boolean value from the #FbHttpParams. This optionally assigns
- * an appropriate #GError upon failure.
- *
- * Return: The boolean value.
- */
-gboolean
-fb_http_params_get_bool(FbHttpParams *params, const gchar *name,
- GError **error);
-
-/**
- * fb_http_params_get_dbl:
- * @params: The #FbHttpParams.
- * @name: The parameter name.
- * @error: The return location for the #GError or #NULL.
- *
- * Gets a floating point value from the #FbHttpParams. This optionally
- * assigns an appropriate #GError upon failure.
- *
- * Return: The floating point value.
- */
-gdouble
-fb_http_params_get_dbl(FbHttpParams *params, const gchar *name,
- GError **error);
-
-/**
- * fb_http_params_get_int:
- * @params: The #FbHttpParams.
- * @name: The parameter name.
- * @error: The return location for the #GError or #NULL.
- *
- * Gets an integer value from the #FbHttpParams. This optionally
- * assigns an appropriate #GError upon failure.
- *
- * Return: The integer value.
- */
-gint64
-fb_http_params_get_int(FbHttpParams *params, const gchar *name,
- GError **error);
-
-/**
- * fb_http_params_get_str:
- * @params: The #FbHttpParams.
- * @name: The parameter name.
- * @error: The return location for the #GError or #NULL.
- *
- * Gets a string value from the #FbHttpParams. This optionally assigns
- * an appropriate #GError upon failure.
- *
- * Return: The string value.
- */
-const gchar *
-fb_http_params_get_str(FbHttpParams *params, const gchar *name,
- GError **error);
-
-/**
- * fb_http_params_dup_str:
- * @params: The #FbHttpParams.
- * @name: The parameter name.
- * @error: The return location for the #GError or #NULL.
- *
- * Gets a duplicated string value from the #FbHttpParams. This
- * optionally assigns an appropriate #GError upon failure. The returned
- * string should be freed with #g_free() when no longer needed.
- *
- * Return: The duplicated string value.
- */
-gchar *
-fb_http_params_dup_str(FbHttpParams *params, const gchar *name,
- GError **error);
-
-/**
- * fb_http_params_set_bool:
- * @params: The #FbHttpParams.
- * @name: The parameter name.
- * @value: The value.
- *
- * Sets a boolean value to the #FbHttpParams.
- */
-void
-fb_http_params_set_bool(FbHttpParams *params, const gchar *name,
- gboolean value);
-
-/**
- * fb_http_params_set_dbl:
- * @params: The #FbHttpParams.
- * @name: The parameter name.
- * @value: The value.
- *
- * Sets a floating point value to the #FbHttpParams.
- */
-void
-fb_http_params_set_dbl(FbHttpParams *params, const gchar *name, gdouble value);
-
-/**
- * fb_http_params_set_int:
- * @params: The #FbHttpParams.
- * @name: The parameter name.
- * @value: The value.
- *
- * Sets an integer value to the #FbHttpParams.
- */
-void
-fb_http_params_set_int(FbHttpParams *params, const gchar *name, gint64 value);
-
-/**
- * fb_http_params_set_str:
- * @params: The #FbHttpParams.
- * @name: The parameter name.
- * @value: The value.
- *
- * Sets a string value to the #FbHttpParams.
- */
-void
-fb_http_params_set_str(FbHttpParams *params, const gchar *name,
- const gchar *value);
-
-/**
- * fb_http_params_set_strf:
- * @params: The #FbHttpParams.
- * @name: The parameter name.
- * @format: The format string literal.
- * @...: The arguments for @format.
- *
- * Sets a formatted string value to the #FbHttpParams.
- */
-void
-fb_http_params_set_strf(FbHttpParams *params, const gchar *name,
- const gchar *format, ...)
- G_GNUC_PRINTF(3, 4);
-
-/**
- * fb_http_urlcmp:
- * @url1: The first URL.
- * @url2: The second URL.
- * @protocol: #TRUE to match the protocols, otherwise #FALSE.
- *
- * Compares two URLs. This is more reliable than just comparing two URL
- * strings, as it avoids casing in some areas, while not in others. It
- * can also, optionally, ignore the matching of the URL protocol.
- *
- * Returns: #TRUE if the URLs match, otherwise #FALSE.
- */
-gboolean
-fb_http_urlcmp(const gchar *url1, const gchar *url2, gboolean protocol);
-
-#endif /* PURPLE_FACEBOOK_HTTP_H */
diff --git a/libpurple/protocols/facebook/id.h b/libpurple/protocols/facebook/id.h
deleted file mode 100644
index c88128c86a..0000000000
--- a/libpurple/protocols/facebook/id.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#ifndef PURPLE_FACEBOOK_ID_H
-#define PURPLE_FACEBOOK_ID_H
-
-#include <glib.h>
-#include <glib/gprintf.h>
-
-#include "util.h"
-
-/**
- * FB_ID_FORMAT:
- *
- * The format specifier for printing and scanning an #FbId.
- */
-#define FB_ID_FORMAT G_GINT64_FORMAT
-
-/**
- * FB_ID_MODIFIER:
- *
- * The length modifier for printing an #FbId.
- */
-#define FB_ID_MODIFIER G_GINT64_MODIFIER
-
-/**
- * FB_ID_STRMAX:
- *
- * The maximum length, including a null-terminating character, of the
- * string representation of an #FbId.
- */
-#define FB_ID_STRMAX 21
-
-/**
- * FB_TYPE_ID:
- *
- * The #GType of an #FbId.
- */
-#define FB_TYPE_ID G_TYPE_INT64
-
-/**
- * FB_ID_CONSTANT:
- * @v: The value.
- *
- * Inserts a literal #FbId into source code.
- *
- * Return: The literal #FbId value.
- */
-#define FB_ID_CONSTANT(v) G_GINT64_CONSTANT(v)
-
-/**
- * FB_ID_FROM_STR:
- * @s: The string value.
- *
- * Converts a string to an #FbId.
- *
- * Return: The converted #FbId value.
- */
-#define FB_ID_FROM_STR(s) g_ascii_strtoll(s, NULL, 10)
-
-/**
- * FB_ID_IS_STR:
- * @s: The string value.
- *
- * Determines if a string is an #FbId.
- *
- * Return: #TRUE if the string is an #FbId, otherwise #FALSE.
- */
-#define FB_ID_IS_STR(s) fb_util_strtest(s, G_ASCII_DIGIT)
-
-/**
- * FB_ID_TO_STR:
- * @i: The #FbId.
- * @s: The string buffer.
- *
- * Converts an #FbId to a string. The buffer should be at least the
- * size of #FB_ID_STRMAX.
- *
- * Return: The converted string value.
- */
-#define FB_ID_TO_STR(i, s) g_sprintf(s, "%" FB_ID_FORMAT, (FbId) i)
-
-/**
- * fb_id_equal:
- *
- * Compares the values of two #FbId's for equality. See #g_int64_equal.
- */
-#define fb_id_equal g_int64_equal
-
-/**
- * fb_id_hash:
- *
- * Converts a pointer to a #FbId hash value. See #g_int64_hash.
- */
-#define fb_id_hash g_int64_hash
-
-/**
- * FbId:
- *
- * Represents a numeric Facebook identifier.
- */
-typedef gint64 FbId;
-
-#endif /* PURPLE_FACEBOOK_ID_H */
diff --git a/libpurple/protocols/facebook/json.c b/libpurple/protocols/facebook/json.c
deleted file mode 100644
index 565f794036..0000000000
--- a/libpurple/protocols/facebook/json.c
+++ /dev/null
@@ -1,658 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#include <glib/gi18n-lib.h>
-
-#include <stdarg.h>
-#include <string.h>
-
-#include "json.h"
-#include "util.h"
-
-typedef struct _FbJsonValue FbJsonValue;
-
-struct _FbJsonValue
-{
- const gchar *expr;
- FbJsonType type;
- gboolean required;
- GValue value;
-};
-
-/**
- * FbJsonValues:
- *
- * Represents a JSON value handler.
- */
-struct _FbJsonValues
-{
- GObject parent;
-
- JsonNode *root;
- GQueue *queue;
- GList *next;
-
- gboolean isarray;
- JsonArray *array;
- guint index;
-
- GError *error;
-};
-
-G_DEFINE_TYPE(FbJsonValues, fb_json_values, G_TYPE_OBJECT);
-
-static void
-fb_json_values_dispose(GObject *obj)
-{
- FbJsonValues *values = FB_JSON_VALUES(obj);
-
- if(values->queue != NULL) {
- while(!g_queue_is_empty(values->queue)) {
- FbJsonValue *value = g_queue_pop_head(values->queue);
-
- if(G_IS_VALUE(&value->value)) {
- g_value_unset(&value->value);
- }
-
- g_free(value);
- }
- }
-
- g_clear_pointer(&values->array, json_array_unref);
- g_clear_error(&values->error);
- g_clear_pointer(&values->queue, g_queue_free);
-}
-
-static void
-fb_json_values_class_init(FbJsonValuesClass *klass)
-{
- GObjectClass *gklass = G_OBJECT_CLASS(klass);
-
- gklass->dispose = fb_json_values_dispose;
-}
-
-static void
-fb_json_values_init(FbJsonValues *values)
-{
- values->queue = g_queue_new();
-}
-
-GQuark
-fb_json_error_quark(void)
-{
- static GQuark q = 0;
-
- if (G_UNLIKELY(q == 0)) {
- q = g_quark_from_static_string("fb-json-error-quark");
- }
-
- return q;
-}
-
-JsonBuilder *
-fb_json_bldr_new(JsonNodeType type)
-{
- JsonBuilder *bldr;
-
- bldr = json_builder_new();
-
- switch (type) {
- case JSON_NODE_ARRAY:
- fb_json_bldr_arr_begin(bldr, NULL);
- break;
-
- case JSON_NODE_OBJECT:
- fb_json_bldr_obj_begin(bldr, NULL);
- break;
-
- default:
- break;
- }
-
- return bldr;
-}
-
-gchar *
-fb_json_bldr_close(JsonBuilder *bldr, JsonNodeType type, gsize *size)
-{
- gchar *ret;
- JsonGenerator *genr;
- JsonNode *root;
-
- switch (type) {
- case JSON_NODE_ARRAY:
- fb_json_bldr_arr_end(bldr);
- break;
-
- case JSON_NODE_OBJECT:
- fb_json_bldr_obj_end(bldr);
- break;
-
- default:
- break;
- }
-
- genr = json_generator_new();
- root = json_builder_get_root(bldr);
-
- json_generator_set_root(genr, root);
- ret = json_generator_to_data(genr, size);
-
- json_node_free(root);
- g_object_unref(genr);
- g_object_unref(bldr);
-
- return ret;
-}
-
-void
-fb_json_bldr_arr_begin(JsonBuilder *bldr, const gchar *name)
-{
- if (name != NULL) {
- json_builder_set_member_name(bldr, name);
- }
-
- json_builder_begin_array(bldr);
-}
-
-void
-fb_json_bldr_arr_end(JsonBuilder *bldr)
-{
- json_builder_end_array(bldr);
-}
-
-void
-fb_json_bldr_obj_begin(JsonBuilder *bldr, const gchar *name)
-{
- if (name != NULL) {
- json_builder_set_member_name(bldr, name);
- }
-
- json_builder_begin_object(bldr);
-}
-
-void
-fb_json_bldr_obj_end(JsonBuilder *bldr)
-{
- json_builder_end_object(bldr);
-}
-
-void
-fb_json_bldr_add_bool(JsonBuilder *bldr, const gchar *name, gboolean value)
-{
- if (name != NULL) {
- json_builder_set_member_name(bldr, name);
- }
-
- json_builder_add_boolean_value(bldr, value);
-}
-
-void
-fb_json_bldr_add_dbl(JsonBuilder *bldr, const gchar *name, gdouble value)
-{
- if (name != NULL) {
- json_builder_set_member_name(bldr, name);
- }
-
- json_builder_add_double_value(bldr, value);
-}
-
-void
-fb_json_bldr_add_int(JsonBuilder *bldr, const gchar *name, gint64 value)
-{
- if (name != NULL) {
- json_builder_set_member_name(bldr, name);
- }
-
- json_builder_add_int_value(bldr, value);
-}
-
-void
-fb_json_bldr_add_str(JsonBuilder *bldr, const gchar *name, const gchar *value)
-{
- if (name != NULL) {
- json_builder_set_member_name(bldr, name);
- }
-
- json_builder_add_string_value(bldr, value);
-}
-
-void
-fb_json_bldr_add_strf(JsonBuilder *bldr, const gchar *name,
- const gchar *format, ...)
-{
- gchar *value;
- va_list ap;
-
- va_start(ap, format);
- value = g_strdup_vprintf(format, ap);
- va_end(ap);
-
- fb_json_bldr_add_str(bldr, name, value);
- g_free(value);
-}
-
-JsonNode *
-fb_json_node_new(const gchar *data, gssize size, GError **error)
-{
- gchar *slice;
- JsonNode *root;
- JsonParser *prsr;
-
- g_return_val_if_fail(data != NULL, NULL);
-
- if (size < 0) {
- size = strlen(data);
- }
-
- /* Ensure data is null terminated for json-glib < 1.0.2 */
- slice = g_strndup(data, size);
- prsr = json_parser_new();
-
- if (!json_parser_load_from_data(prsr, slice, size, error)) {
- g_object_unref(prsr);
- g_free(slice);
- return NULL;
- }
-
- root = json_parser_get_root(prsr);
- root = json_node_copy(root);
-
- g_object_unref(prsr);
- g_free(slice);
- return root;
-}
-
-JsonNode *
-fb_json_node_get(JsonNode *root, const gchar *expr, GError **error)
-{
- GError *err = NULL;
- guint size;
- JsonArray *rslt;
- JsonNode *node;
- JsonNode *ret;
-
- /* Special case for json-glib < 0.99.2 */
- if (purple_strequal(expr, "$")) {
- return json_node_copy(root);
- }
-
- node = json_path_query(expr, root, &err);
-
- if (err != NULL) {
- g_propagate_error(error, err);
- json_node_free(node);
- return NULL;
- }
-
- rslt = json_node_get_array(node);
- size = json_array_get_length(rslt);
-
- if (size < 1) {
- g_set_error(error, FB_JSON_ERROR, FB_JSON_ERROR_NOMATCH,
- _("No matches for %s"), expr);
- json_node_free(node);
- return NULL;
- }
-
- if (size > 1) {
- g_set_error(error, FB_JSON_ERROR, FB_JSON_ERROR_AMBIGUOUS,
- _("Ambiguous matches for %s"), expr);
- json_node_free(node);
- return NULL;
- }
-
- if (json_array_get_null_element(rslt, 0)) {
- g_set_error(error, FB_JSON_ERROR, FB_JSON_ERROR_NULL,
- _("Null value for %s"), expr);
- json_node_free(node);
- return NULL;
- }
-
- ret = json_array_dup_element(rslt, 0);
- json_node_free(node);
- return ret;
-}
-
-JsonNode *
-fb_json_node_get_nth(JsonNode *root, guint n)
-{
- GList *vals;
- JsonNode *ret;
- JsonObject *obj;
-
- obj = json_node_get_object(root);
- vals = json_object_get_values(obj);
- ret = g_list_nth_data(vals, n);
-
- g_list_free(vals);
- return ret;
-}
-
-JsonArray *
-fb_json_node_get_arr(JsonNode *root, const gchar *expr, GError **error)
-{
- JsonArray *ret;
- JsonNode *rslt;
-
- rslt = fb_json_node_get(root, expr, error);
-
- if (rslt == NULL) {
- return NULL;
- }
-
- ret = json_node_dup_array(rslt);
- json_node_free(rslt);
- return ret;
-}
-
-gboolean
-fb_json_node_get_bool(JsonNode *root, const gchar *expr, GError **error)
-{
- gboolean ret;
- JsonNode *rslt;
-
- rslt = fb_json_node_get(root, expr, error);
-
- if (rslt == NULL) {
- return FALSE;
- }
-
- ret = json_node_get_boolean(rslt);
- json_node_free(rslt);
- return ret;
-}
-
-gdouble
-fb_json_node_get_dbl(JsonNode *root, const gchar *expr, GError **error)
-{
- gdouble ret;
- JsonNode *rslt;
-
- rslt = fb_json_node_get(root, expr, error);
-
- if (rslt == NULL) {
- return 0.0;
- }
-
- ret = json_node_get_double(rslt);
- json_node_free(rslt);
- return ret;
-}
-
-gint64
-fb_json_node_get_int(JsonNode *root, const gchar *expr, GError **error)
-{
- gint64 ret;
- JsonNode *rslt;
-
- rslt = fb_json_node_get(root, expr, error);
-
- if (rslt == NULL) {
- return 0;
- }
-
- ret = json_node_get_int(rslt);
- json_node_free(rslt);
- return ret;
-}
-
-gchar *
-fb_json_node_get_str(JsonNode *root, const gchar *expr, GError **error)
-{
- gchar *ret;
- JsonNode *rslt;
-
- rslt = fb_json_node_get(root, expr, error);
-
- if (rslt == NULL) {
- return NULL;
- }
-
- ret = json_node_dup_string(rslt);
- json_node_free(rslt);
- return ret;
-}
-
-FbJsonValues *
-fb_json_values_new(JsonNode *root)
-{
- FbJsonValues *values;
-
- g_return_val_if_fail(root != NULL, NULL);
-
- values = g_object_new(FB_TYPE_JSON_VALUES, NULL);
- values->root = root;
-
- return values;
-}
-
-void
-fb_json_values_add(FbJsonValues *values, FbJsonType type, gboolean required,
- const gchar *expr)
-{
- FbJsonValue *value;
-
- g_return_if_fail(values != NULL);
- g_return_if_fail(expr != NULL);
-
- value = g_new0(FbJsonValue, 1);
- value->expr = expr;
- value->type = type;
- value->required = required;
-
- g_queue_push_tail(values->queue, value);
-}
-
-JsonNode *
-fb_json_values_get_root(FbJsonValues *values)
-{
- guint index;
-
- g_return_val_if_fail(values != NULL, NULL);
-
- if(values->array == NULL) {
- return values->root;
- }
-
- g_return_val_if_fail(values->index > 0, NULL);
- index = values->index - 1;
-
- if(json_array_get_length(values->array) <= index) {
- return NULL;
- }
-
- return json_array_get_element(values->array, index);
-}
-
-void
-fb_json_values_set_array(FbJsonValues *values, gboolean required,
- const gchar *expr)
-{
- g_return_if_fail(values != NULL);
-
- values->array = fb_json_node_get_arr(values->root, expr, &values->error);
- values->isarray = TRUE;
-
- if(!required) {
- g_clear_error(&values->error);
- }
-}
-
-gboolean
-fb_json_values_update(FbJsonValues *values, GError **error)
-{
- FbJsonValue *value;
- GError *err = NULL;
- GList *l;
- GType type;
- JsonNode *root;
- JsonNode *node;
-
- g_return_val_if_fail(values != NULL, FALSE);
-
- if(G_UNLIKELY(values->error != NULL)) {
- g_propagate_error(error, values->error);
- values->error = NULL;
- return FALSE;
- }
-
- if(values->isarray) {
- if(values->array == NULL ||
- json_array_get_length(values->array) <= values->index)
- {
- return FALSE;
- }
-
- root = json_array_get_element(values->array, values->index++);
- } else {
- root = values->root;
- }
-
- g_return_val_if_fail(root != NULL, FALSE);
-
- for(l = values->queue->head; l != NULL; l = l->next) {
- value = l->data;
- node = fb_json_node_get(root, value->expr, &err);
-
- if (G_IS_VALUE(&value->value)) {
- g_value_unset(&value->value);
- }
-
- if (err != NULL) {
- json_node_free(node);
-
- if (value->required) {
- g_propagate_error(error, err);
- return FALSE;
- }
-
- g_clear_error(&err);
- continue;
- }
-
- type = json_node_get_value_type(node);
-
- if (G_UNLIKELY(type != value->type)) {
- g_set_error(error, FB_JSON_ERROR, FB_JSON_ERROR_TYPE,
- _("Expected a %s but got a %s for %s"),
- g_type_name(value->type),
- g_type_name(type),
- value->expr);
- json_node_free(node);
- return FALSE;
- }
-
- json_node_get_value(node, &value->value);
- json_node_free(node);
- }
-
- values->next = values->queue->head;
- return TRUE;
-}
-
-const GValue *
-fb_json_values_next(FbJsonValues *values)
-{
- FbJsonValue *value;
-
- g_return_val_if_fail(values != NULL, NULL);
-
- g_return_val_if_fail(values->next != NULL, NULL);
- value = values->next->data;
- values->next = values->next->next;
-
- if (!G_IS_VALUE(&value->value)) {
- return NULL;
- }
-
- return &value->value;
-}
-
-gboolean
-fb_json_values_next_bool(FbJsonValues *values, gboolean defval)
-{
- const GValue *value;
-
- value = fb_json_values_next(values);
-
- if (G_UNLIKELY(value == NULL)) {
- return defval;
- }
-
- return g_value_get_boolean(value);
-}
-
-gdouble
-fb_json_values_next_dbl(FbJsonValues *values, gdouble defval)
-{
- const GValue *value;
-
- value = fb_json_values_next(values);
-
- if (G_UNLIKELY(value == NULL)) {
- return defval;
- }
-
- return g_value_get_double(value);
-}
-
-gint64
-fb_json_values_next_int(FbJsonValues *values, gint64 defval)
-{
- const GValue *value;
-
- value = fb_json_values_next(values);
-
- if (G_UNLIKELY(value == NULL)) {
- return defval;
- }
-
- return g_value_get_int64(value);
-}
-
-const gchar *
-fb_json_values_next_str(FbJsonValues *values, const gchar *defval)
-{
- const GValue *value;
-
- value = fb_json_values_next(values);
-
- if (G_UNLIKELY(value == NULL)) {
- return defval;
- }
-
- return g_value_get_string(value);
-}
-
-gchar *
-fb_json_values_next_str_dup(FbJsonValues *values, const gchar *defval)
-{
- const GValue *value;
-
- value = fb_json_values_next(values);
-
- if (G_UNLIKELY(value == NULL)) {
- return g_strdup(defval);
- }
-
- return g_value_dup_string(value);
-}
diff --git a/libpurple/protocols/facebook/json.h b/libpurple/protocols/facebook/json.h
deleted file mode 100644
index 807d6ed2dc..0000000000
--- a/libpurple/protocols/facebook/json.h
+++ /dev/null
@@ -1,471 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#ifndef PURPLE_FACEBOOK_JSON_H
-#define PURPLE_FACEBOOK_JSON_H
-
-#include <glib.h>
-#include <json-glib/json-glib.h>
-
-#define FB_TYPE_JSON_VALUES fb_json_values_get_type()
-
-/**
- * FB_JSON_ERROR:
- *
- * The #GQuark of the domain of JSON errors.
- */
-#define FB_JSON_ERROR fb_json_error_quark()
-
-/**
- * FbJsonError:
- * @FB_JSON_ERROR_SUCCESS: There is no error.
- * @FB_JSON_ERROR_AMBIGUOUS: The node has ambiguous matches.
- * @FB_JSON_ERROR_GENERAL: General failure.
- * @FB_JSON_ERROR_NOMATCH: The node does not match anything.
- * @FB_JSON_ERROR_NULL: The node is of type NULL.
- * @FB_JSON_ERROR_TYPE: The node has an unexpected type.
- *
- * The error codes for the #FB_JSON_ERROR domain.
- */
-typedef enum
-{
- FB_JSON_ERROR_SUCCESS = 0,
- FB_JSON_ERROR_AMBIGUOUS,
- FB_JSON_ERROR_GENERAL,
- FB_JSON_ERROR_NOMATCH,
- FB_JSON_ERROR_NULL,
- FB_JSON_ERROR_TYPE
-} FbJsonError;
-
-/**
- * FbJsonType:
- * @FB_JSON_TYPE_NULL: An unknown value.
- * @FB_JSON_TYPE_BOOL: A boolean (#TRUE or #FALSE).
- * @FB_JSON_TYPE_DBL: A floating point number.
- * @FB_JSON_TYPE_INT: A signed integer.
- * @FB_JSON_TYPE_STR: A string.
- *
- * The JSON data types.
- */
-typedef enum
-{
- FB_JSON_TYPE_NULL = 0,
- FB_JSON_TYPE_BOOL = G_TYPE_BOOLEAN,
- FB_JSON_TYPE_DBL = G_TYPE_DOUBLE,
- FB_JSON_TYPE_INT = G_TYPE_INT64,
- FB_JSON_TYPE_STR = G_TYPE_STRING
-} FbJsonType;
-
-G_DECLARE_FINAL_TYPE(FbJsonValues, fb_json_values, FB, JSON_VALUES,
- GObject)
-
-/**
- * fb_json_error_quark:
- *
- * Gets the #GQuark of the domain of JSON errors.
- *
- * Returns: The #GQuark of the domain.
- */
-GQuark
-fb_json_error_quark(void);
-
-/**
- * fb_json_bldr_new:
- * @type: The starting #JsonNodeType.
- *
- * Creates a new #JsonBuilder. The starting #JsonNodeType is likely to
- * be #JSON_NODE_OBJECT. The returned #JsonBuilder should be freed with
- * #g_object_unref() when no longer needed. Optionally, instead of
- * freeing, the returned #JsonBuilder can be closed with
- * #fb_json_bldr_close().
- *
- * Returns: (transfer full): The new #JsonBuilder.
- */
-JsonBuilder *
-fb_json_bldr_new(JsonNodeType type);
-
-/**
- * fb_json_bldr_close:
- * @bldr: The #JsonBuilder.
- * @type: The ending #JsonNodeType.
- * @size: The return local for the size of the returned string.
- *
- * Closes the #JsonBuilder by returning a string representing the
- * #JsonBuilder. The ending #JsonNodeType is likely to be
- * #JSON_NODE_OBJECT. This calls #g_object_unref(). The returned
- * string should be freed with #g_free() when no longer needed.
- *
- * Returns: The string representation of the #JsonBuilder.
- */
-gchar *
-fb_json_bldr_close(JsonBuilder *bldr, JsonNodeType type, gsize *size);
-
-/**
- * fb_json_bldr_arr_begin:
- * @bldr: The #JsonBuilder.
- * @name: The member name or #NULL.
- *
- * Begins an array member in the #JsonBuilder.
- */
-void
-fb_json_bldr_arr_begin(JsonBuilder *bldr, const gchar *name);
-
-/**
- * fb_json_bldr_arr_end:
- * @bldr: The #JsonBuilder.
- *
- * Ends an array member in the #JsonBuilder.
- */
-void
-fb_json_bldr_arr_end(JsonBuilder *bldr);
-
-/**
- * fb_json_bldr_obj_begin:
- * @bldr: The #JsonBuilder.
- * @name: The member name or #NULL.
- *
- * Begins an object member in the #JsonBuilder.
- */
-void
-fb_json_bldr_obj_begin(JsonBuilder *bldr, const gchar *name);
-
-/**
- * fb_json_bldr_obj_end:
- * @bldr: The #JsonBuilder.
- *
- * Ends an array member in the #JsonBuilder.
- */
-void
-fb_json_bldr_obj_end(JsonBuilder *bldr);
-
-/**
- * fb_json_bldr_add_bool:
- * @bldr: The #JsonBuilder.
- * @name: The member name or #NULL.
- * @value: The value.
- *
- * Adds a boolean member to the #JsonBuilder.
- */
-void
-fb_json_bldr_add_bool(JsonBuilder *bldr, const gchar *name, gboolean value);
-
-/**
- * fb_json_bldr_add_dbl:
- * @bldr: The #JsonBuilder.
- * @name: The member name or #NULL.
- * @value: The value.
- *
- * Adds a floating point member to the #JsonBuilder.
- */
-void
-fb_json_bldr_add_dbl(JsonBuilder *bldr, const gchar *name, gdouble value);
-
-/**
- * fb_json_bldr_add_int:
- * @bldr: The #JsonBuilder.
- * @name: The member name or #NULL.
- * @value: The value.
- *
- * Adds an integer member to the #JsonBuilder.
- */
-void
-fb_json_bldr_add_int(JsonBuilder *bldr, const gchar *name, gint64 value);
-
-/**
- * fb_json_bldr_add_str:
- * @bldr: The #JsonBuilder.
- * @name: The member name or #NULL.
- * @value: The value.
- *
- * Adds a string member to the #JsonBuilder.
- */
-void
-fb_json_bldr_add_str(JsonBuilder *bldr, const gchar *name, const gchar *value);
-
-/**
- * fb_json_bldr_add_strf:
- * @bldr: The #JsonBuilder.
- * @name: The member name or #NULL.
- * @format: The format string literal.
- * @...: The arguments for @format.
- *
- * Adds a formatted string member to the #JsonBuilder.
- */
-void
-fb_json_bldr_add_strf(JsonBuilder *bldr, const gchar *name,
- const gchar *format, ...)
- G_GNUC_PRINTF(3, 4);
-
-/**
- * fb_json_node_new:
- * @data: The string JSON.
- * @size: The size of @json or -1 if null-terminated.
- * @error: The return location for the #GError or #NULL.
- *
- * Creates a new #JsonNode. The returned #JsonBuilder should be freed
- * wuth #json_node_free() when no longer needed.
- *
- * Returns: The new #JsonNode.
- */
-JsonNode *
-fb_json_node_new(const gchar *data, gssize size, GError **error);
-
-/**
- * fb_json_node_get:
- * @root: The root #JsonNode.
- * @expr: The #JsonPath expression.
- * @error: The return location for the #GError or #NULL.
- *
- * Gets a new #JsonNode value from a parent #JsonNode with a #JsonPath
- * expression. The returned #JsonNode should be freed with
- * #json_node_free() when no longer needed.
- *
- * Returns: The new #JsonNode.
- */
-JsonNode *
-fb_json_node_get(JsonNode *root, const gchar *expr, GError **error);
-
-/**
- * fb_json_node_get_nth:
- * @root: The root #JsonNode.
- * @n: The index number.
- *
- * Gets a #JsonNode value from a parent #JsonNode by index. The
- * returned #JsonNode should not be freed.
- *
- * Return: The #JsonNode.
- */
-JsonNode *
-fb_json_node_get_nth(JsonNode *root, guint n);
-
-/**
- * fb_json_node_get_arr:
- * @root: The root #JsonNode.
- * @expr: The #JsonPath expression.
- * @error: The return location for the #GError or #NULL.
- *
- * Gets a new #JsonArray value from a parent #JsonNode with a #JsonPath
- * expression. The returned #JsonArray should be freed with
- * #json_array_unref() when no longer needed.
- *
- * Returns: The new #JsonArray.
- */
-JsonArray *
-fb_json_node_get_arr(JsonNode *root, const gchar *expr, GError **error);
-
-/**
- * fb_json_node_get_bool:
- * @root: The root #JsonNode.
- * @expr: The #JsonPath expression.
- * @error: The return location for the #GError or #NULL.
- *
- * Gets a boolean value from a parent #JsonNode with a #JsonPath
- * expression.
- *
- * Returns: The boolean value.
- */
-gboolean
-fb_json_node_get_bool(JsonNode *root, const gchar *expr, GError **error);
-
-/**
- * fb_json_node_get_dbl:
- * @root: The root #JsonNode.
- * @expr: The #JsonPath expression.
- * @error: The return location for the #GError or #NULL.
- *
- * Gets a floating point value from a parent #JsonNode with a #JsonPath
- * expression.
- *
- * Returns: The floating point value.
- */
-gdouble
-fb_json_node_get_dbl(JsonNode *root, const gchar *expr, GError **error);
-
-/**
- * fb_json_node_get_int:
- * @root: The root #JsonNode.
- * @expr: The #JsonPath expression.
- * @error: The return location for the #GError or #NULL.
- *
- * Gets an integer value from a parent #JsonNode with a #JsonPath
- * expression.
- *
- * Returns: The integer value.
- */
-gint64
-fb_json_node_get_int(JsonNode *root, const gchar *expr, GError **error);
-
-/**
- * fb_json_node_get_str:
- * @root: The root #JsonNode.
- * @expr: The #JsonPath expression.
- * @error: The return location for the #GError or #NULL.
- *
- * Gets an string value from a parent #JsonNode with a #JsonPath
- * expression. The returned string should be freed with #g_free()
- * when no longer needed.
- *
- * Returns: The string value.
- */
-gchar *
-fb_json_node_get_str(JsonNode *root, const gchar *expr, GError **error);
-
-/**
- * fb_json_values_new:
- * @root: The root #JsonNode.
- *
- * Creates a new #FbJsonValues. The returned #FbJsonValues should be
- * freed with #g_object_unref when no longer needed.
- *
- * Returns: The new #FbJsonValues.
- */
-FbJsonValues *
-fb_json_values_new(JsonNode *root);
-
-/**
- * fb_json_values_add:
- * @values: The #FbJsonValues.
- * @type: The #FbJsonType.
- * @required: #TRUE if the node is required, otherwise #FALSE.
- * @expr: The #JsonPath expression.
- *
- * Adds a new #FbJsonValue to the #FbJsonValues.
- */
-void
-fb_json_values_add(FbJsonValues *values, FbJsonType type, gboolean required,
- const gchar *expr);
-
-/**
- * fb_json_values_get_root:
- * @values: The #FbJsonValues.
- *
- * Gets the current working root #JsonNode. This is either the current
- * array #JsonNode or the root #JsonNode. The returned #JsonNode should
- * not be freed.
- */
-JsonNode *
-fb_json_values_get_root(FbJsonValues *values);
-
-/**
- * fb_json_values_set_array:
- * @values: The #FbJsonValues.
- * @required: #TRUE if the node is required, otherwise #FALSE.
- * @expr: The #JsonPath expression.
- *
- * Sets the #JsonPath for an array to base all #FbJsonValue's off.
- */
-void
-fb_json_values_set_array(FbJsonValues *values, gboolean required,
- const gchar *expr);
-
-/**
- * fb_json_values_update:
- * @values: The #FbJsonValues.
- * @error: The return location for the #GError or #NULL.
- *
- * Updates the current working root. This should be called after all of
- * the #FbJsonValue's have been added with #fb_json_values_add(). If an
- * array was set with #fb_json_values_set_array(), then this should be
- * called in a while loop, until #FALSE is returned.
- *
- * Returns: #TRUE if the values were updated, otherwise #FALSE.
- */
-gboolean
-fb_json_values_update(FbJsonValues *values, GError **error);
-
-/**
- * fb_json_values_next:
- * @values: The #FbJsonValues.
- *
- * Gets the next #GValue from the #FbJsonValues. Before calling this
- * function, #fb_json_values_update() must be called.
- *
- * Returns: The #GValue.
- */
-const GValue *
-fb_json_values_next(FbJsonValues *values);
-
-/**
- * fb_json_values_next_bool:
- * @values: The #FbJsonValues.
- * @defval: The default value.
- *
- * Gets the next boolean value from the #FbJsonValues. Before calling
- * this function, #fb_json_values_update() must be called.
- *
- * Returns: The boolean value.
- */
-gboolean
-fb_json_values_next_bool(FbJsonValues *values, gboolean defval);
-
-/**
- * fb_json_values_next_dbl:
- * @values: The #FbJsonValues.
- * @defval: The default value.
- *
- * Gets the next floating point value from the #FbJsonValues. Before
- * calling this function, #fb_json_values_update() must be called.
- *
- * Returns: The floating point value.
- */
-gdouble
-fb_json_values_next_dbl(FbJsonValues *values, gdouble defval);
-
-/**
- * fb_json_values_next_int:
- * @values: The #FbJsonValues.
- * @defval: The default value.
- *
- * Gets the next integer value from the #FbJsonValues. Before calling
- * this function, #fb_json_values_update() must be called.
- *
- * Returns: The integer value.
- */
-gint64
-fb_json_values_next_int(FbJsonValues *values, gint64 defval);
-
-/**
- * fb_json_values_next_str:
- * @values: The #FbJsonValues.
- * @defval: The default value.
- *
- * Gets the next string value from the #FbJsonValues. Before calling
- * this function, #fb_json_values_update() must be called.
- *
- * Returns: The string value.
- */
-const gchar *
-fb_json_values_next_str(FbJsonValues *values, const gchar *defval);
-
-/**
- * fb_json_values_next_str_dup:
- * @values: The #FbJsonValues.
- * @defval: The default value.
- *
- * Gets the next duplicate string value from the #FbJsonValues. Before
- * calling this function, #fb_json_values_update() must be called.
- *
- * Returns: The duplicate string value.
- */
-gchar *
-fb_json_values_next_str_dup(FbJsonValues *values, const gchar *defval);
-
-#endif /* PURPLE_FACEBOOK_JSON_H */
diff --git a/libpurple/protocols/facebook/meson.build b/libpurple/protocols/facebook/meson.build
deleted file mode 100644
index c89e280409..0000000000
--- a/libpurple/protocols/facebook/meson.build
+++ /dev/null
@@ -1,63 +0,0 @@
-FACEBOOK_SOURCES = [
- 'api.c',
- 'api.h',
- 'data.c',
- 'data.h',
- 'facebook.h',
- 'facebook.c',
- 'http.c',
- 'http.h',
- 'id.h',
- 'json.c',
- 'json.h',
- 'mqtt.c',
- 'mqtt.h',
- 'thrift.c',
- 'thrift.h',
- 'util.c',
- 'util.h'
-]
-
-FACEBOOK_BUILT_SOURCES = []
-
-if DYNAMIC_FACEBOOK
- facebook_resources = gnome.compile_resources('facebookresource',
- 'resources/facebook.gresource.xml',
- source_dir : 'resources',
- c_name : 'facebook')
- FACEBOOK_BUILT_SOURCES += facebook_resources
-
- facebook_prpl = shared_library('facebook',
- FACEBOOK_SOURCES + FACEBOOK_BUILT_SOURCES,
- c_args : ['-DG_LOG_USE_STRUCTURED', '-DG_LOG_DOMAIN="Purple-Facebook"'],
- dependencies : [json, libpurple_dep, libsoup, glib],
- install : true,
- install_dir : PURPLE_PLUGINDIR)
-
- # Used to produce docs.
- facebook_inc = include_directories('.')
- facebook_dep = declare_dependency(
- link_with : facebook_prpl,
- dependencies : [json, libpurple_dep, glib])
-
- devenv.append('PURPLE_PLUGIN_PATH', meson.current_build_dir())
-
- if enable_introspection
- introspection_sources = FACEBOOK_SOURCES
-
- facebook_gir_includes = ['GObject-2.0', 'Gio-2.0', 'Gst-1.0',
- 'Json-1.0', 'Soup-3.0', libpurple_gir[0]]
-
- facebook_gir = gnome.generate_gir(facebook_prpl,
- sources : introspection_sources,
- includes : facebook_gir_includes,
- namespace : 'Facebook',
- symbol_prefix : 'fb',
- identifier_prefix : 'Fb',
- nsversion : f'@purple_major_version@.@purple_minor_version@',
- dependencies: [gplugin_dep, libpurple_dep],
- install : false,
- extra_args : ['-DPURPLE_COMPILATION', '--quiet'])
- endif
-
-endif
diff --git a/libpurple/protocols/facebook/mqtt.c b/libpurple/protocols/facebook/mqtt.c
deleted file mode 100644
index b666010b0e..0000000000
--- a/libpurple/protocols/facebook/mqtt.c
+++ /dev/null
@@ -1,1016 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#include <glib/gi18n-lib.h>
-
-#include <glib/gprintf.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include <purple.h>
-
-#include "mqtt.h"
-#include "util.h"
-
-/**
- * FbMqtt:
- *
- * Represents an MQTT connection.
- */
-struct _FbMqtt
-{
- GObject parent;
-
- PurpleConnection *gc;
- GIOStream *conn;
- GBufferedInputStream *input;
- PurpleQueuedOutputStream *output;
- GCancellable *cancellable;
- gboolean connected;
- guint16 mid;
-
- GByteArray *rbuf;
- gsize remz;
-
- gint tev;
-};
-
-G_DEFINE_TYPE(FbMqtt, fb_mqtt, G_TYPE_OBJECT);
-
-/**
- * FbMqttMessage:
- *
- * Represents a reader/writer for an MQTT message.
- */
-struct _FbMqttMessage
-{
- GObject parent;
-
- FbMqttMessageType type;
- FbMqttMessageFlags flags;
-
- GByteArray *bytes;
- guint offset;
- guint pos;
-
- gboolean local;
-};
-
-G_DEFINE_TYPE(FbMqttMessage, fb_mqtt_message, G_TYPE_OBJECT);
-
-static void fb_mqtt_read_packet(FbMqtt *mqtt);
-
-static void
-fb_mqtt_dispose(GObject *obj)
-{
- FbMqtt *mqtt = FB_MQTT(obj);
-
- fb_mqtt_close(mqtt);
- g_byte_array_free(mqtt->rbuf, TRUE);
-}
-
-static void
-fb_mqtt_class_init(FbMqttClass *klass)
-{
- GObjectClass *gklass = G_OBJECT_CLASS(klass);
-
- gklass->dispose = fb_mqtt_dispose;
- /**
- * FbMqtt::connect:
- * @mqtt: The #FbMqtt.
- *
- * Emitted upon the successful completion of the connection
- * process. This is emitted as a result of #fb_mqtt_connect().
- */
- g_signal_new("connect",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 0);
-
- /**
- * FbMqtt::error:
- * @mqtt: The #FbMqtt.
- * @error: The #GError.
- *
- * Emitted whenever an error is hit within the #FbMqtt. This
- * should close the #FbMqtt with #fb_mqtt_close().
- */
- g_signal_new("error",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 1, G_TYPE_ERROR);
-
- /**
- * FbMqtt::open:
- * @mqtt: The #FbMqtt.
- *
- * Emitted upon the successful opening of the remote socket.
- * This is emitted as a result of #fb_mqtt_open(). This should
- * call #fb_mqtt_connect().
- */
- g_signal_new("open",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 0);
-
- /**
- * FbMqtt::publish:
- * @mqtt: The #FbMqtt.
- * @topic: The topic.
- * @pload: The payload.
- *
- * Emitted upon an incoming message from the steam.
- */
- g_signal_new("publish",
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_ACTION,
- 0,
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 2, G_TYPE_STRING, G_TYPE_BYTE_ARRAY);
-}
-
-static void
-fb_mqtt_init(FbMqtt *mqtt)
-{
- mqtt->rbuf = g_byte_array_new();
-}
-
-static void
-fb_mqtt_message_dispose(GObject *obj)
-{
- FbMqttMessage *msg = FB_MQTT_MESSAGE(obj);
-
- if(msg->bytes != NULL && msg->local) {
- g_byte_array_free(msg->bytes, TRUE);
- msg->bytes = NULL;
- }
-}
-
-static void
-fb_mqtt_message_class_init(FbMqttMessageClass *klass)
-{
- GObjectClass *gklass = G_OBJECT_CLASS(klass);
-
- gklass->dispose = fb_mqtt_message_dispose;
-}
-
-static void
-fb_mqtt_message_init(G_GNUC_UNUSED FbMqttMessage *msg)
-{
-}
-
-GQuark
-fb_mqtt_error_quark(void)
-{
- static GQuark q = 0;
-
- if (G_UNLIKELY(q == 0)) {
- q = g_quark_from_static_string("fb-mqtt-error-quark");
- }
-
- return q;
-}
-
-FbMqtt *
-fb_mqtt_new(PurpleConnection *gc)
-{
- FbMqtt *mqtt;
-
- g_return_val_if_fail(PURPLE_IS_CONNECTION(gc), NULL);
-
- mqtt = g_object_new(FB_TYPE_MQTT, NULL);
- mqtt->gc = gc;
-
- return mqtt;
-};
-
-void
-fb_mqtt_close(FbMqtt *mqtt)
-{
- g_return_if_fail(FB_IS_MQTT(mqtt));
-
- g_clear_handle_id(&mqtt->tev, g_source_remove);
-
- if(mqtt->cancellable != NULL) {
- g_cancellable_cancel(mqtt->cancellable);
- g_clear_object(&mqtt->cancellable);
- }
-
- if(mqtt->conn != NULL) {
- purple_gio_graceful_close(mqtt->conn,
- G_INPUT_STREAM(mqtt->input),
- G_OUTPUT_STREAM(mqtt->output));
- g_clear_object(&mqtt->input);
- g_clear_object(&mqtt->output);
- g_clear_object(&mqtt->conn);
- }
-
- mqtt->connected = FALSE;
- g_byte_array_set_size(mqtt->rbuf, 0);
-}
-
-static void
-fb_mqtt_take_error(FbMqtt *mqtt, GError *err, const gchar *prefix)
-{
- if (g_error_matches(err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
- /* Return as cancelled means the connection is closing */
- g_error_free(err);
- return;
- }
-
- /* Now we can check for programming errors */
- g_return_if_fail(FB_IS_MQTT(mqtt));
-
- if (prefix != NULL) {
- g_prefix_error(&err, "%s: ", prefix);
- }
-
- g_signal_emit_by_name(mqtt, "error", err);
- g_error_free(err);
-}
-
-static void
-fb_mqtt_error_literal(FbMqtt *mqtt, FbMqttError error, const gchar *msg)
-{
- GError *err;
-
- g_return_if_fail(FB_IS_MQTT(mqtt));
-
- err = g_error_new_literal(FB_MQTT_ERROR, error, msg);
-
- g_signal_emit_by_name(mqtt, "error", err);
- g_error_free(err);
-}
-
-void
-fb_mqtt_error(FbMqtt *mqtt, FbMqttError error, const gchar *format, ...)
-{
- GError *err;
- va_list ap;
-
- g_return_if_fail(FB_IS_MQTT(mqtt));
-
- va_start(ap, format);
- err = g_error_new_valist(FB_MQTT_ERROR, error, format, ap);
- va_end(ap);
-
- g_signal_emit_by_name(mqtt, "error", err);
- g_error_free(err);
-}
-
-static gboolean
-fb_mqtt_cb_timeout(gpointer data)
-{
- FbMqtt *mqtt = data;
-
- mqtt->tev = 0;
- fb_mqtt_error_literal(mqtt, FB_MQTT_ERROR_GENERAL,
- _("Connection timed out"));
- return FALSE;
-}
-
-static void
-fb_mqtt_timeout_clear(FbMqtt *mqtt)
-{
- g_clear_handle_id(&mqtt->tev, g_source_remove);
-}
-
-static void
-fb_mqtt_timeout(FbMqtt *mqtt)
-{
- fb_mqtt_timeout_clear(mqtt);
- mqtt->tev = g_timeout_add_seconds(FB_MQTT_TIMEOUT_CONN, fb_mqtt_cb_timeout,
- mqtt);
-}
-
-static gboolean
-fb_mqtt_cb_ping(gpointer data)
-{
- FbMqtt *mqtt = data;
- FbMqttMessage *msg;
-
- msg = fb_mqtt_message_new(FB_MQTT_MESSAGE_TYPE_PINGREQ, 0);
- fb_mqtt_write(mqtt, msg);
- g_object_unref(msg);
-
- mqtt->tev = 0;
- fb_mqtt_timeout(mqtt);
- return FALSE;
-}
-
-static void
-fb_mqtt_ping(FbMqtt *mqtt)
-{
- fb_mqtt_timeout_clear(mqtt);
- mqtt->tev = g_timeout_add_seconds(FB_MQTT_TIMEOUT_PING, fb_mqtt_cb_ping,
- mqtt);
-}
-
-static void
-fb_mqtt_cb_fill(GObject *source, GAsyncResult *res, gpointer data)
-{
- GBufferedInputStream *input = G_BUFFERED_INPUT_STREAM(source);
- FbMqtt *mqtt = data;
- gssize ret;
- GError *err = NULL;
-
- ret = g_buffered_input_stream_fill_finish(input, res, &err);
-
- if (ret < 1) {
- if (ret == 0) {
- err = g_error_new_literal(G_IO_ERROR,
- G_IO_ERROR_CONNECTION_CLOSED,
- _("Connection closed"));
- }
-
- fb_mqtt_take_error(mqtt, err, _("Failed to read fixed header"));
- return;
- }
-
- fb_mqtt_read_packet(mqtt);
-}
-
-static void
-fb_mqtt_cb_read_packet(GObject *source, GAsyncResult *res, gpointer data)
-{
- FbMqtt *mqtt = data;
- gssize ret;
- FbMqttMessage *msg;
- GError *err = NULL;
-
- ret = g_input_stream_read_finish(G_INPUT_STREAM(source), res, &err);
-
- if (ret < 1) {
- if (ret == 0) {
- err = g_error_new_literal(G_IO_ERROR,
- G_IO_ERROR_CONNECTION_CLOSED,
- _("Connection closed"));
- }
-
- fb_mqtt_take_error(mqtt, err, _("Failed to read packet data"));
- return;
- }
-
- mqtt->remz -= ret;
-
- if(mqtt->remz > 0) {
- g_input_stream_read_async(G_INPUT_STREAM(source),
- mqtt->rbuf->data + mqtt->rbuf->len - mqtt->remz,
- mqtt->remz, G_PRIORITY_DEFAULT,
- mqtt->cancellable, fb_mqtt_cb_read_packet,
- mqtt);
- return;
- }
-
- msg = fb_mqtt_message_new_bytes(mqtt->rbuf);
-
- if (G_UNLIKELY(msg == NULL)) {
- fb_mqtt_error_literal(mqtt, FB_MQTT_ERROR_GENERAL,
- _("Failed to parse message"));
- return;
- }
-
- fb_mqtt_read(mqtt, msg);
- g_object_unref(msg);
-
- /* Read another packet if connection wasn't reset in fb_mqtt_read() */
- if (fb_mqtt_connected(mqtt, FALSE)) {
- fb_mqtt_read_packet(mqtt);
- }
-}
-
-static void
-fb_mqtt_read_packet(FbMqtt *mqtt)
-{
- const guint8 *buf;
- gsize count = 0;
- gsize pos;
- guint mult = 1;
- guint8 byte;
- gsize size = 0;
-
- buf = g_buffered_input_stream_peek_buffer(mqtt->input, &count);
-
- /* Start at 1 to skip the first byte */
- pos = 1;
-
- do {
- if (pos >= count) {
- /* Not enough data yet, try again later */
- g_buffered_input_stream_fill_async(mqtt->input, -1,
- G_PRIORITY_DEFAULT,
- mqtt->cancellable,
- fb_mqtt_cb_fill, mqtt);
- return;
- }
-
- byte = *(buf + pos++);
-
- size += (byte & 127) * mult;
- mult *= 128;
- } while ((byte & 128) != 0);
-
- /* Add header to size */
- size += pos;
-
- g_byte_array_set_size(mqtt->rbuf, size);
- mqtt->remz = size;
-
- /* TODO: Use g_input_stream_read_all_async() when available. */
- /* TODO: Alternately, it would be nice to let the
- * FbMqttMessage directly use the GBufferedInputStream
- * buffer instead of copying it, provided it's consumed
- * before the next read.
- */
- g_input_stream_read_async(G_INPUT_STREAM(mqtt->input), mqtt->rbuf->data,
- mqtt->rbuf->len, G_PRIORITY_DEFAULT,
- mqtt->cancellable, fb_mqtt_cb_read_packet, mqtt);
-}
-
-void
-fb_mqtt_read(FbMqtt *mqtt, FbMqttMessage *msg)
-{
- FbMqttMessage *nsg;
- GByteArray *wytes;
- gchar *str;
- guint8 chr;
- guint16 mid;
-
- g_return_if_fail(FB_IS_MQTT(mqtt));
-
- fb_util_debug_hexdump(FB_UTIL_DEBUG_INFO, msg->bytes,
- "Reading %d (flags: 0x%0X)",
- msg->type, msg->flags);
-
- switch (msg->type) {
- case FB_MQTT_MESSAGE_TYPE_CONNACK:
- if (!fb_mqtt_message_read_byte(msg, NULL) ||
- !fb_mqtt_message_read_byte(msg, &chr))
- {
- break;
- }
-
- if (chr != FB_MQTT_ERROR_SUCCESS) {
- fb_mqtt_error(mqtt, chr, _("Connection failed (%u)"),
- chr);
- return;
- }
-
- mqtt->connected = TRUE;
- fb_mqtt_ping(mqtt);
- g_signal_emit_by_name(mqtt, "connect");
- return;
-
- case FB_MQTT_MESSAGE_TYPE_PUBLISH:
- if (!fb_mqtt_message_read_str(msg, &str)) {
- break;
- }
-
- if((msg->flags & FB_MQTT_MESSAGE_FLAG_QOS1) ||
- (msg->flags & FB_MQTT_MESSAGE_FLAG_QOS2))
- {
- if(msg->flags & FB_MQTT_MESSAGE_FLAG_QOS1) {
- chr = FB_MQTT_MESSAGE_TYPE_PUBACK;
- } else {
- chr = FB_MQTT_MESSAGE_TYPE_PUBREC;
- }
-
- if (!fb_mqtt_message_read_mid(msg, &mid)) {
- g_free(str);
- break;
- }
-
- nsg = fb_mqtt_message_new(chr, 0);
- fb_mqtt_message_write_u16(nsg, mid);
- fb_mqtt_write(mqtt, nsg);
- g_object_unref(nsg);
- }
-
- wytes = g_byte_array_new();
- fb_mqtt_message_read_r(msg, wytes);
- g_signal_emit_by_name(mqtt, "publish", str, wytes);
- g_byte_array_free(wytes, TRUE);
- g_free(str);
- return;
-
- case FB_MQTT_MESSAGE_TYPE_PUBREL:
- if (!fb_mqtt_message_read_mid(msg, &mid)) {
- break;
- }
-
- nsg = fb_mqtt_message_new(FB_MQTT_MESSAGE_TYPE_PUBCOMP, 0);
- fb_mqtt_message_write_u16(nsg, mid); /* Message identifier */
- fb_mqtt_write(mqtt, nsg);
- g_object_unref(nsg);
- return;
-
- case FB_MQTT_MESSAGE_TYPE_PINGRESP:
- fb_mqtt_ping(mqtt);
- return;
-
- case FB_MQTT_MESSAGE_TYPE_PUBACK:
- case FB_MQTT_MESSAGE_TYPE_PUBCOMP:
- case FB_MQTT_MESSAGE_TYPE_SUBACK:
- case FB_MQTT_MESSAGE_TYPE_UNSUBACK:
- return;
-
- default:
- fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL,
- _("Unknown packet (%u)"), msg->type);
- return;
- }
-
- /* Since no case returned, there was a parse error. */
- fb_mqtt_error_literal(mqtt, FB_MQTT_ERROR_GENERAL,
- _("Failed to parse message"));
-}
-
-static void
-fb_mqtt_cb_push_bytes(GObject *source, GAsyncResult *res, gpointer data)
-{
- PurpleQueuedOutputStream *stream = PURPLE_QUEUED_OUTPUT_STREAM(source);
- FbMqtt *mqtt = data;
- GError *err = NULL;
-
- if (!purple_queued_output_stream_push_bytes_finish(stream,
- res, &err)) {
- purple_queued_output_stream_clear_queue(stream);
-
- fb_mqtt_take_error(mqtt, err, _("Failed to write data"));
- return;
- }
-}
-
-void
-fb_mqtt_write(FbMqtt *mqtt, FbMqttMessage *msg)
-{
- const GByteArray *bytes;
- GBytes *gbytes;
-
- g_return_if_fail(FB_IS_MQTT(mqtt));
- g_return_if_fail(FB_IS_MQTT_MESSAGE(msg));
-
- bytes = fb_mqtt_message_bytes(msg);
-
- if (G_UNLIKELY(bytes == NULL)) {
- fb_mqtt_error_literal(mqtt, FB_MQTT_ERROR_GENERAL,
- _("Failed to format data"));
- return;
- }
-
- fb_util_debug_hexdump(FB_UTIL_DEBUG_INFO, msg->bytes,
- "Writing %d (flags: 0x%0X)",
- msg->type, msg->flags);
-
- /* TODO: Would be nice to refactor this to not require copying bytes */
- gbytes = g_bytes_new(bytes->data, bytes->len);
- purple_queued_output_stream_push_bytes_async(mqtt->output, gbytes,
- G_PRIORITY_DEFAULT,
- mqtt->cancellable,
- fb_mqtt_cb_push_bytes, mqtt);
- g_bytes_unref(gbytes);
-}
-
-static void
-fb_mqtt_cb_open(GObject *source, GAsyncResult *res, gpointer data)
-{
- FbMqtt *mqtt = data;
- GSocketConnection *conn;
- GError *err = NULL;
-
- conn = g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(source),
- res, &err);
-
- if (conn == NULL) {
- fb_mqtt_take_error(mqtt, err, NULL);
- return;
- }
-
- fb_mqtt_timeout_clear(mqtt);
-
- mqtt->conn = G_IO_STREAM(conn);
- mqtt->input = G_BUFFERED_INPUT_STREAM(g_buffered_input_stream_new(
- g_io_stream_get_input_stream(mqtt->conn)));
- mqtt->output = purple_queued_output_stream_new(
- g_io_stream_get_output_stream(mqtt->conn));
-
- fb_mqtt_read_packet(mqtt);
-
- g_signal_emit_by_name(mqtt, "open");
-}
-
-void
-fb_mqtt_open(FbMqtt *mqtt, const gchar *host, gint port)
-{
- PurpleAccount *acc;
- GSocketClient *client;
- GError *err = NULL;
-
- g_return_if_fail(FB_IS_MQTT(mqtt));
-
- acc = purple_connection_get_account(mqtt->gc);
- fb_mqtt_close(mqtt);
-
- client = purple_gio_socket_client_new(acc, &err);
-
- if (client == NULL) {
- fb_mqtt_take_error(mqtt, err, NULL);
- return;
- }
-
- mqtt->cancellable = g_cancellable_new();
-
- g_socket_client_set_tls(client, TRUE);
- g_socket_client_connect_to_host_async(client, host, port,
- mqtt->cancellable, fb_mqtt_cb_open,
- mqtt);
- g_object_unref(client);
-
- fb_mqtt_timeout(mqtt);
-}
-
-void
-fb_mqtt_connect(FbMqtt *mqtt, guint8 flags, const GByteArray *pload)
-{
- FbMqttMessage *msg;
-
- g_return_if_fail(!fb_mqtt_connected(mqtt, FALSE));
- g_return_if_fail(pload != NULL);
-
- /* Facebook always sends a CONNACK, use QoS1 */
- flags |= FB_MQTT_CONNECT_FLAG_QOS1;
-
- msg = fb_mqtt_message_new(FB_MQTT_MESSAGE_TYPE_CONNECT, 0);
- fb_mqtt_message_write_str(msg, FB_MQTT_NAME); /* Protocol name */
- fb_mqtt_message_write_byte(msg, FB_MQTT_LEVEL); /* Protocol level */
- fb_mqtt_message_write_byte(msg, flags); /* Flags */
- fb_mqtt_message_write_u16(msg, FB_MQTT_KA); /* Keep alive */
-
- fb_mqtt_message_write(msg, pload->data, pload->len);
- fb_mqtt_write(mqtt, msg);
-
- fb_mqtt_timeout(mqtt);
- g_object_unref(msg);
-}
-
-gboolean
-fb_mqtt_connected(FbMqtt *mqtt, gboolean error)
-{
- gboolean connected;
-
- g_return_val_if_fail(FB_IS_MQTT(mqtt), FALSE);
- connected = (mqtt->conn != NULL) && mqtt->connected;
-
- if (!connected && error) {
- fb_mqtt_error_literal(mqtt, FB_MQTT_ERROR_GENERAL, _("Not connected"));
- }
-
- return connected;
-}
-
-void
-fb_mqtt_disconnect(FbMqtt *mqtt)
-{
- FbMqttMessage *msg;
-
- if (G_UNLIKELY(!fb_mqtt_connected(mqtt, FALSE))) {
- return;
- }
-
- msg = fb_mqtt_message_new(FB_MQTT_MESSAGE_TYPE_DISCONNECT, 0);
- fb_mqtt_write(mqtt, msg);
- g_object_unref(msg);
- fb_mqtt_close(mqtt);
-}
-
-void
-fb_mqtt_publish(FbMqtt *mqtt, const gchar *topic, const GByteArray *pload)
-{
- FbMqttMessage *msg;
-
- g_return_if_fail(FB_IS_MQTT(mqtt));
- g_return_if_fail(fb_mqtt_connected(mqtt, FALSE));
-
- /* Message identifier not required, but for consistency use QoS1 */
- msg = fb_mqtt_message_new(FB_MQTT_MESSAGE_TYPE_PUBLISH,
- FB_MQTT_MESSAGE_FLAG_QOS1);
-
- fb_mqtt_message_write_str(msg, topic); /* Message topic */
- fb_mqtt_message_write_mid(msg, &mqtt->mid); /* Message identifier */
-
- if (pload != NULL) {
- fb_mqtt_message_write(msg, pload->data, pload->len);
- }
-
- fb_mqtt_write(mqtt, msg);
- g_object_unref(msg);
-}
-
-void
-fb_mqtt_subscribe(FbMqtt *mqtt, ...)
-{
- const gchar *topic;
- FbMqttMessage *msg;
- guint16 qos;
- va_list ap;
-
- g_return_if_fail(FB_IS_MQTT(mqtt));
- g_return_if_fail(fb_mqtt_connected(mqtt, FALSE));
-
- /* Facebook requires a message identifier, use QoS1 */
- msg = fb_mqtt_message_new(FB_MQTT_MESSAGE_TYPE_SUBSCRIBE,
- FB_MQTT_MESSAGE_FLAG_QOS1);
-
- fb_mqtt_message_write_mid(msg, &mqtt->mid); /* Message identifier */
-
- va_start(ap, mqtt);
-
- while ((topic = va_arg(ap, const gchar*)) != NULL) {
- qos = va_arg(ap, guint);
- fb_mqtt_message_write_str(msg, topic);
- fb_mqtt_message_write_byte(msg, qos);
- }
-
- va_end(ap);
-
- fb_mqtt_write(mqtt, msg);
- g_object_unref(msg);
-}
-
-void
-fb_mqtt_unsubscribe(FbMqtt *mqtt, const gchar *topic1, ...)
-{
- const gchar *topic;
- FbMqttMessage *msg;
- va_list ap;
-
- g_return_if_fail(FB_IS_MQTT(mqtt));
- g_return_if_fail(fb_mqtt_connected(mqtt, FALSE));
-
- /* Facebook requires a message identifier, use QoS1 */
- msg = fb_mqtt_message_new(FB_MQTT_MESSAGE_TYPE_UNSUBSCRIBE,
- FB_MQTT_MESSAGE_FLAG_QOS1);
-
- fb_mqtt_message_write_mid(msg, &mqtt->mid); /* Message identifier */
- fb_mqtt_message_write_str(msg, topic1); /* First topic */
-
- va_start(ap, topic1);
-
- while ((topic = va_arg(ap, const gchar*)) != NULL) {
- fb_mqtt_message_write_str(msg, topic); /* Remaining topics */
- }
-
- va_end(ap);
-
- fb_mqtt_write(mqtt, msg);
- g_object_unref(msg);
-}
-
-FbMqttMessage *
-fb_mqtt_message_new(FbMqttMessageType type, FbMqttMessageFlags flags)
-{
- FbMqttMessage *msg;
-
- msg = g_object_new(FB_TYPE_MQTT_MESSAGE, NULL);
-
- msg->type = type;
- msg->flags = flags;
- msg->bytes = g_byte_array_new();
- msg->local = TRUE;
-
- return msg;
-}
-
-FbMqttMessage *
-fb_mqtt_message_new_bytes(GByteArray *bytes)
-{
- FbMqttMessage *msg;
- guint8 *byte;
-
- g_return_val_if_fail(bytes != NULL, NULL);
- g_return_val_if_fail(bytes->len >= 2, NULL);
-
- msg = g_object_new(FB_TYPE_MQTT_MESSAGE, NULL);
-
- msg->bytes = bytes;
- msg->local = FALSE;
- msg->type = (*bytes->data & 0xF0) >> 4;
- msg->flags = *bytes->data & 0x0F;
-
- /* Skip the fixed header */
- byte = msg->bytes->data + 1;
- while((*byte & 128) != 0) {
- byte++;
- }
- byte++;
- msg->offset = byte - bytes->data;
- msg->pos = msg->offset;
-
- return msg;
-}
-
-void
-fb_mqtt_message_reset(FbMqttMessage *msg)
-{
- g_return_if_fail(FB_IS_MQTT_MESSAGE(msg));
-
- if(msg->offset > 0) {
- g_byte_array_remove_range(msg->bytes, 0, msg->offset);
- msg->offset = 0;
- msg->pos = 0;
- }
-}
-
-const GByteArray *
-fb_mqtt_message_bytes(FbMqttMessage *msg)
-{
- guint i;
- guint8 byte;
- guint8 sbuf[4];
- guint32 size;
-
- g_return_val_if_fail(FB_IS_MQTT_MESSAGE(msg), NULL);
-
- i = 0;
- size = msg->bytes->len - msg->offset;
-
- do {
- if (G_UNLIKELY(i >= G_N_ELEMENTS(sbuf))) {
- return NULL;
- }
-
- byte = size % 128;
- size /= 128;
-
- if (size > 0) {
- byte |= 128;
- }
-
- sbuf[i++] = byte;
- } while (size > 0);
-
- fb_mqtt_message_reset(msg);
- g_byte_array_prepend(msg->bytes, sbuf, i);
-
- byte = ((msg->type & 0x0F) << 4) | (msg->flags & 0x0F);
- g_byte_array_prepend(msg->bytes, &byte, sizeof byte);
-
- msg->pos = (i + 1) * (sizeof byte);
- return msg->bytes;
-}
-
-gboolean
-fb_mqtt_message_read(FbMqttMessage *msg, gpointer data, guint size)
-{
- g_return_val_if_fail(FB_IS_MQTT_MESSAGE(msg), FALSE);
-
- if((msg->pos + size) > msg->bytes->len) {
- return FALSE;
- }
-
- if ((data != NULL) && (size > 0)) {
- memcpy(data, msg->bytes->data + msg->pos, size);
- }
-
- msg->pos += size;
- return TRUE;
-}
-
-gboolean
-fb_mqtt_message_read_r(FbMqttMessage *msg, GByteArray *bytes)
-{
- guint size;
-
- g_return_val_if_fail(FB_IS_MQTT_MESSAGE(msg), FALSE);
- size = msg->bytes->len - msg->pos;
-
- if (G_LIKELY(size > 0)) {
- g_byte_array_append(bytes, msg->bytes->data + msg->pos, size);
- }
-
- return TRUE;
-}
-
-gboolean
-fb_mqtt_message_read_byte(FbMqttMessage *msg, guint8 *value)
-{
- return fb_mqtt_message_read(msg, value, sizeof *value);
-}
-
-gboolean
-fb_mqtt_message_read_mid(FbMqttMessage *msg, guint16 *value)
-{
- return fb_mqtt_message_read_u16(msg, value);
-}
-
-gboolean
-fb_mqtt_message_read_u16(FbMqttMessage *msg, guint16 *value)
-{
- if (!fb_mqtt_message_read(msg, value, sizeof *value)) {
- return FALSE;
- }
-
- if (value != NULL) {
- *value = g_ntohs(*value);
- }
-
- return TRUE;
-}
-
-gboolean
-fb_mqtt_message_read_str(FbMqttMessage *msg, gchar **value)
-{
- guint8 *data;
- guint16 size;
-
- if (!fb_mqtt_message_read_u16(msg, &size)) {
- return FALSE;
- }
-
- if (value != NULL) {
- data = g_new(guint8, size + 1);
- data[size] = 0;
- } else {
- data = NULL;
- }
-
- if (!fb_mqtt_message_read(msg, data, size)) {
- g_free(data);
- return FALSE;
- }
-
- if (value != NULL) {
- *value = (gchar *) data;
- }
-
- return TRUE;
-}
-
-void
-fb_mqtt_message_write(FbMqttMessage *msg, gconstpointer data, guint size)
-{
- g_return_if_fail(FB_IS_MQTT_MESSAGE(msg));
-
- g_byte_array_append(msg->bytes, data, size);
- msg->pos += size;
-}
-
-void
-fb_mqtt_message_write_byte(FbMqttMessage *msg, guint8 value)
-{
- fb_mqtt_message_write(msg, &value, sizeof value);
-}
-
-void
-fb_mqtt_message_write_mid(FbMqttMessage *msg, guint16 *value)
-{
- g_return_if_fail(value != NULL);
- fb_mqtt_message_write_u16(msg, ++(*value));
-}
-
-void
-fb_mqtt_message_write_u16(FbMqttMessage *msg, guint16 value)
-{
- value = g_htons(value);
- fb_mqtt_message_write(msg, &value, sizeof value);
-}
-
-void
-fb_mqtt_message_write_str(FbMqttMessage *msg, const gchar *value)
-{
- gint16 size;
-
- g_return_if_fail(value != NULL);
-
- size = strlen(value);
- fb_mqtt_message_write_u16(msg, size);
- fb_mqtt_message_write(msg, value, size);
-}
diff --git a/libpurple/protocols/facebook/mqtt.h b/libpurple/protocols/facebook/mqtt.h
deleted file mode 100644
index 2913c49468..0000000000
--- a/libpurple/protocols/facebook/mqtt.h
+++ /dev/null
@@ -1,520 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#ifndef PURPLE_FACEBOOK_MQTT_H
-#define PURPLE_FACEBOOK_MQTT_H
-
-#include <glib.h>
-#include <string.h>
-
-#include <purple.h>
-
-#define FB_TYPE_MQTT fb_mqtt_get_type()
-#define FB_TYPE_MQTT_MESSAGE fb_mqtt_message_get_type()
-
-/**
- * FB_MQTT_NAME:
- *
- * The name of the MQTT version.
- */
-#define FB_MQTT_NAME "MQTToT"
-
-/**
- * FB_MQTT_LEVEL:
- *
- * The level of the MQTT version.
- */
-#define FB_MQTT_LEVEL 3
-
-/**
- * FB_MQTT_KA:
- *
- * The keep-alive timeout, in seconds, of the MQTT connection.
- */
-#define FB_MQTT_KA 60
-
-/**
- * FB_MQTT_HOST:
- *
- * The MQTT host name for Facebook.
- */
-#define FB_MQTT_HOST "mqtt.facebook.com"
-
-/**
- * FB_MQTT_PORT:
- *
- * The MQTT host port for Facebook.
- */
-#define FB_MQTT_PORT 443
-
-/**
- * FB_MQTT_TIMEOUT_CONN:
- *
- * The timeout, in seconds, to wait for a PING back from the server.
- */
-#define FB_MQTT_TIMEOUT_CONN ((guint)(FB_MQTT_KA * 1.5))
-
-/**
- * FB_MQTT_TIMEOUT_PING:
- *
- * The timeout, in seconds, to send a PING to the server.
- */
-#define FB_MQTT_TIMEOUT_PING (FB_MQTT_KA)
-
-/**
- * FB_MQTT_ERROR:
- *
- * The #GQuark of the domain of MQTT errors.
- */
-#define FB_MQTT_ERROR fb_mqtt_error_quark()
-
-/**
- * FbMqttConnectFlags:
- * @FB_MQTT_CONNECT_FLAG_CLR: Clear the session.
- * @FB_MQTT_CONNECT_FLAG_WILL: A will message is in the payload.
- * @FB_MQTT_CONNECT_FLAG_RET: Retain the will message.
- * @FB_MQTT_CONNECT_FLAG_PASS: A password is in the payload.
- * @FB_MQTT_CONNECT_FLAG_USER: A user name is in the payload.
- * @FB_MQTT_CONNECT_FLAG_QOS0: Use no quality of service.
- * @FB_MQTT_CONNECT_FLAG_QOS1: Use level one quality of service.
- * @FB_MQTT_CONNECT_FLAG_QOS2: Use level two quality of service.
- *
- * The #FbMqttMessage flags for the CONNECT message.
- */
-typedef enum
-{
- FB_MQTT_CONNECT_FLAG_CLR = 1 << 1,
- FB_MQTT_CONNECT_FLAG_WILL = 1 << 2,
- FB_MQTT_CONNECT_FLAG_RET = 1 << 5,
- FB_MQTT_CONNECT_FLAG_PASS = 1 << 6,
- FB_MQTT_CONNECT_FLAG_USER = 1 << 7,
- FB_MQTT_CONNECT_FLAG_QOS0 = 0 << 3,
- FB_MQTT_CONNECT_FLAG_QOS1 = 1 << 3,
- FB_MQTT_CONNECT_FLAG_QOS2 = 2 << 3
-} FbMqttConnectFlags;
-
-/**
- * FbMqttError:
- * @FB_MQTT_ERROR_SUCCESS: There is no error.
- * @FB_MQTT_ERROR_PRTVERS: Unacceptable protocol version.
- * @FB_MQTT_ERROR_IDREJECT: Identifier rejected.
- * @FB_MQTT_ERROR_SRVGONE: Server unavailable.
- * @FB_MQTT_ERROR_USERPASS: Bad user name or password.
- * @FB_MQTT_ERROR_UNAUTHORIZED: Not authorized.
- * @FB_MQTT_ERROR_GENERAL: General failure.
- *
- * The error codes for the #FB_MQTT_ERROR domain.
- */
-typedef enum
-{
- FB_MQTT_ERROR_SUCCESS = 0,
- FB_MQTT_ERROR_PRTVERS = 1,
- FB_MQTT_ERROR_IDREJECT = 2,
- FB_MQTT_ERROR_SRVGONE = 3,
- FB_MQTT_ERROR_USERPASS = 4,
- FB_MQTT_ERROR_UNAUTHORIZED = 5,
- FB_MQTT_ERROR_GENERAL
-} FbMqttError;
-
-/**
- * FbMqttMessageFlags:
- * @FB_MQTT_MESSAGE_FLAG_RET: Retain messages.
- * @FB_MQTT_MESSAGE_FLAG_DUP: Duplicate delivery of control packet.
- * @FB_MQTT_MESSAGE_FLAG_QOS0: Use no quality of service.
- * @FB_MQTT_MESSAGE_FLAG_QOS1: Use level one quality of service.
- * @FB_MQTT_MESSAGE_FLAG_QOS2: Use level two quality of service.
- *
- * The #FbMqttMessage flags.
- */
-typedef enum
-{
- FB_MQTT_MESSAGE_FLAG_RET = 1 << 0,
- FB_MQTT_MESSAGE_FLAG_DUP = 1 << 3,
- FB_MQTT_MESSAGE_FLAG_QOS0 = 0 << 1,
- FB_MQTT_MESSAGE_FLAG_QOS1 = 1 << 1,
- FB_MQTT_MESSAGE_FLAG_QOS2 = 2 << 1
-} FbMqttMessageFlags;
-
-/**
- * FbMqttMessageType:
- * @FB_MQTT_MESSAGE_TYPE_CONNECT: Requests a connection.
- * @FB_MQTT_MESSAGE_TYPE_CONNACK: Connection acknowledgment.
- * @FB_MQTT_MESSAGE_TYPE_PUBLISH: Requests a message publication.
- * @FB_MQTT_MESSAGE_TYPE_PUBACK: Publication acknowledgment.
- * @FB_MQTT_MESSAGE_TYPE_PUBREC: Publication received.
- * @FB_MQTT_MESSAGE_TYPE_PUBREL: Publication released.
- * @FB_MQTT_MESSAGE_TYPE_PUBCOMP: Publication complete.
- * @FB_MQTT_MESSAGE_TYPE_SUBSCRIBE: Requests a subscription.
- * @FB_MQTT_MESSAGE_TYPE_SUBACK: Subscription acknowledgment.
- * @FB_MQTT_MESSAGE_TYPE_UNSUBSCRIBE: Requests an unsubscription.
- * @FB_MQTT_MESSAGE_TYPE_UNSUBACK: Unsubscription acknowledgment.
- * @FB_MQTT_MESSAGE_TYPE_PINGREQ: Requests a ping response.
- * @FB_MQTT_MESSAGE_TYPE_PINGRESP: Ping response.
- * @FB_MQTT_MESSAGE_TYPE_DISCONNECT: Requests a disconnection.
- *
- * The #FbMqttMessage types.
- */
-typedef enum
-{
- FB_MQTT_MESSAGE_TYPE_CONNECT = 1,
- FB_MQTT_MESSAGE_TYPE_CONNACK = 2,
- FB_MQTT_MESSAGE_TYPE_PUBLISH = 3,
- FB_MQTT_MESSAGE_TYPE_PUBACK = 4,
- FB_MQTT_MESSAGE_TYPE_PUBREC = 5,
- FB_MQTT_MESSAGE_TYPE_PUBREL = 6,
- FB_MQTT_MESSAGE_TYPE_PUBCOMP = 7,
- FB_MQTT_MESSAGE_TYPE_SUBSCRIBE = 8,
- FB_MQTT_MESSAGE_TYPE_SUBACK = 9,
- FB_MQTT_MESSAGE_TYPE_UNSUBSCRIBE = 10,
- FB_MQTT_MESSAGE_TYPE_UNSUBACK = 11,
- FB_MQTT_MESSAGE_TYPE_PINGREQ = 12,
- FB_MQTT_MESSAGE_TYPE_PINGRESP = 13,
- FB_MQTT_MESSAGE_TYPE_DISCONNECT = 14
-} FbMqttMessageType;
-
-G_DECLARE_FINAL_TYPE(FbMqtt, fb_mqtt, FB, MQTT, GObject)
-
-G_DECLARE_FINAL_TYPE(FbMqttMessage, fb_mqtt_message, FB, MQTT_MESSAGE,
- GObject)
-
-/**
- * fb_mqtt_error_quark:
- *
- * Gets the #GQuark of the domain of MQTT errors.
- *
- * Returns: The #GQuark of the domain.
- */
-GQuark
-fb_mqtt_error_quark(void);
-
-/**
- * fb_mqtt_new:
- * @gc: The #PurpleConnection.
- *
- * Creates a new #FbMqtt. The returned #FbMqtt should be freed with
- * #g_object_unref() when no longer needed.
- *
- * Returns: The new #FbMqtt.
- */
-FbMqtt *
-fb_mqtt_new(PurpleConnection *gc);
-
-/**
- * fb_mqtt_close:
- * @mqtt: The #FbMqtt.
- *
- * Closes the MQTT without sending the `DISCONNECT` message. The #FbMqtt
- * may be reopened after calling this.
- */
-void
-fb_mqtt_close(FbMqtt *mqtt);
-
-/**
- * fb_mqtt_error:
- * @mqtt: The #FbMqtt.
- * @error: The #FbMqttError.
- * @format: The format string literal.
- * @...: The arguments for @format.
- *
- * Emits an #FbMqttError and closes the #FbMqtt.
- */
-void
-fb_mqtt_error(FbMqtt *mqtt, FbMqttError error, const gchar *format, ...)
- G_GNUC_PRINTF(3, 4);
-
-/**
- * fb_mqtt_read:
- * @mqtt: The #FbMqtt.
- * @msg: The #FbMqttMessage.
- *
- * Reads an #FbMqttMessage into the #FbMqtt for processing.
- */
-void
-fb_mqtt_read(FbMqtt *mqtt, FbMqttMessage *msg);
-
-/**
- * fb_mqtt_write:
- * @mqtt: The #FbMqtt.
- * @msg: The #FbMqttMessage.
- *
- * Writes an #FbMqttMessage to the wire.
- */
-void
-fb_mqtt_write(FbMqtt *mqtt, FbMqttMessage *msg);
-
-/**
- * fb_mqtt_open:
- * @mqtt: The #FbMqtt.
- * @host: The host name.
- * @port: The port.
- *
- * Opens an SSL connection to the remote server.
- */
-void
-fb_mqtt_open(FbMqtt *mqtt, const gchar *host, gint port);
-
-/**
- * fb_mqtt_connect:
- * @mqtt: The #FbMqtt.
- * @flags: The #FbMqttConnectFlags.
- * @pload: The payload.
- *
- * Sends a message of type #FB_MQTT_MESSAGE_TYPE_CONNECT.
- */
-void
-fb_mqtt_connect(FbMqtt *mqtt, guint8 flags, const GByteArray *pload);
-
-/**
- * fb_mqtt_connected:
- * @mqtt: The #FbMqtt.
- * @error: #TRUE to error with no connection, otherwise #FALSE.
- *
- * Determines the connection state of the #FbMqtt, and optionally emits
- * an error.
- *
- * Returns: #TRUE if the #FbMqtt is connected, otherwise #FALSE.
- */
-gboolean
-fb_mqtt_connected(FbMqtt *mqtt, gboolean error);
-
-/**
- * fb_mqtt_disconnect:
- * @mqtt: The #FbMqtt.
- *
- * Sends a message of type #FB_MQTT_MESSAGE_TYPE_DISCONNECT, and closes
- * the connection.
- */
-void
-fb_mqtt_disconnect(FbMqtt *mqtt);
-
-/**
- * fb_mqtt_publish:
- * @mqtt: The #FbMqtt.
- * @topic: The topic.
- * @pload: The payload.
- *
- * Sends a message of type #FB_MQTT_MESSAGE_TYPE_PUBLISH.
- */
-void
-fb_mqtt_publish(FbMqtt *mqtt, const gchar *topic, const GByteArray *pload);
-
-/**
- * fb_mqtt_subscribe:
- * @mqtt: The #FbMqtt.
- * @...: The %NULL-terminated list of topic/QoS pairs.
- *
- * Sends a message of type #FB_MQTT_MESSAGE_TYPE_SUBSCRIBE.
- */
-void fb_mqtt_subscribe(FbMqtt *mqtt, ...) G_GNUC_NULL_TERMINATED;
-
-/**
- * fb_mqtt_unsubscribe:
- * @mqtt: The #FbMqtt.
- * @topic1: The first topic.
- * @...: The %NULL-terminated list of topics.
- *
- * Sends a message of type #FB_MQTT_MESSAGE_TYPE_UNSUBSCRIBE.
- */
-void
-fb_mqtt_unsubscribe(FbMqtt *mqtt, const gchar *topic1, ...)
- G_GNUC_NULL_TERMINATED;
-
-/**
- * fb_mqtt_message_new:
- * @type: The #FbMqttMessageType.
- * @flags: The #FbMqttMessageFlags.
- *
- * Creates a new #FbMqttMessage. The returned #FbMqttMessage should be
- * freed with #g_object_unref() when no longer needed.
- *
- * Returns: The new #FbMqttMessage.
- */
-FbMqttMessage *
-fb_mqtt_message_new(FbMqttMessageType type, FbMqttMessageFlags flags);
-
-/**
- * fb_mqtt_message_new_bytes:
- * @bytes: The #GByteArray.
- *
- * Creates a new #FbMqttMessage from a #GByteArray. The returned
- * #FbMqttMessage should be freed with #g_object_unref() when no
- * longer needed.
- *
- * Returns: The new #FbMqttMessage.
- */
-FbMqttMessage *
-fb_mqtt_message_new_bytes(GByteArray *bytes);
-
-/**
- * fb_mqtt_message_reset:
- * @msg: The #FbMqttMessage.
- *
- * Resets an #FbMqttMessage. This resets the cursor position, and
- * removes any sort of fixed header.
- */
-void
-fb_mqtt_message_reset(FbMqttMessage *msg);
-
-/**
- * fb_mqtt_message_bytes:
- * @msg: The #FbMqttMessage.
- *
- * Formats the internal #GByteArray of the #FbMqttMessage with the
- * required fixed header. This resets the cursor position.
- *
- * Returns: The internal #GByteArray.
- */
-const GByteArray *
-fb_mqtt_message_bytes(FbMqttMessage *msg);
-
-/**
- * fb_mqtt_message_read:
- * @msg: The #FbMqttMessage.
- * @data: The data buffer.
- * @size: The size of @buffer.
- *
- * Reads data from the #FbMqttMessage into a buffer. If @data is #NULL,
- * this will simply advance the cursor position.
- *
- * Returns: #TRUE if the data was read, otherwise #FALSE.
- */
-gboolean
-fb_mqtt_message_read(FbMqttMessage *msg, gpointer data, guint size);
-
-/**
- * fb_mqtt_message_read_r:
- * @msg: The #FbMqttMessage.
- * @bytes: The #GByteArray.
- *
- * Reads the remaining data from the #FbMqttMessage into a #GByteArray.
- * This is useful for obtaining the payload of a message.
- *
- * Returns: #TRUE if the data was read, otherwise #FALSE.
- */
-gboolean
-fb_mqtt_message_read_r(FbMqttMessage *msg, GByteArray *bytes);
-
-/**
- * fb_mqtt_message_read_byte:
- * @msg: The #FbMqttMessage.
- * @value: The return location for the value or #NULL.
- *
- * Reads an 8-bit integer value from the #FbMqttMessage. If @value is
- * #NULL, this will simply advance the cursor position.
- *
- * Returns: #TRUE if the value was read, otherwise #FALSE.
- */
-gboolean
-fb_mqtt_message_read_byte(FbMqttMessage *msg, guint8 *value);
-
-/**
- * fb_mqtt_message_read_mid:
- * @msg: The #FbMqttMessage.
- * @value: The return location for the value or #NULL.
- *
- * Reads a message identifier from the #FbMqttMessage. If @value is
- * #NULL, this will simply advance the cursor position.
- *
- * Returns: #TRUE if the value was read, otherwise #FALSE.
- */
-gboolean
-fb_mqtt_message_read_mid(FbMqttMessage *msg, guint16 *value);
-
-/**
- * fb_mqtt_message_read_u16:
- * @msg: The #FbMqttMessage.
- * @value: The return location for the value or #NULL.
- *
- * Reads a 16-bit integer value from the #FbMqttMessage. If @value is
- * #NULL, this will simply advance the cursor position.
- *
- * Returns: #TRUE if the value was read, otherwise #FALSE.
- */
-gboolean
-fb_mqtt_message_read_u16(FbMqttMessage *msg, guint16 *value);
-
-/**
- * fb_mqtt_message_read_str:
- * @msg: The #FbMqttMessage.
- * @value: The return location for the value or #NULL.
- *
- * Reads a string value from the #FbMqttMessage. The value returned to
- * @value should be freed with #g_free() when no longer needed. If
- * @value is #NULL, this will simply advance the cursor position.
- *
- * Returns: #TRUE if the value was read, otherwise #FALSE.
- */
-gboolean
-fb_mqtt_message_read_str(FbMqttMessage *msg, gchar **value);
-
-/**
- * fb_mqtt_message_write:
- * @msg: The #FbMqttMessage.
- * @data: The data buffer.
- * @size: The size of @buffer.
- *
- * Writes data to the #FbMqttMessage.
- */
-void
-fb_mqtt_message_write(FbMqttMessage *msg, gconstpointer data, guint size);
-
-/**
- * fb_mqtt_message_write_byte:
- * @msg: The #FbMqttMessage.
- * @value: The value.
- *
- * Writes an 8-bit integer value to the #FbMqttMessage.
- */
-void
-fb_mqtt_message_write_byte(FbMqttMessage *msg, guint8 value);
-
-/**
- * fb_mqtt_message_write_mid:
- * @msg: The #FbMqttMessage.
- * @value: The value.
- *
- * Writes a message identifier to the #FbMqttMessage. This increments
- * @value for the next message.
- */
-void
-fb_mqtt_message_write_mid(FbMqttMessage *msg, guint16 *value);
-
-/**
- * fb_mqtt_message_write_u16:
- * @msg: The #FbMqttMessage.
- * @value: The value.
- *
- * Writes a 16-bit integer value to the #FbMqttMessage.
- */
-void
-fb_mqtt_message_write_u16(FbMqttMessage *msg, guint16 value);
-
-/**
- * fb_mqtt_message_write_str:
- * @msg: The #FbMqttMessage.
- * @value: The value.
- *
- * Writes a string value to the #FbMqttMessage.
- */
-void
-fb_mqtt_message_write_str(FbMqttMessage *msg, const gchar *value);
-
-#endif /* PURPLE_FACEBOOK_MQTT_H */
diff --git a/libpurple/protocols/facebook/resources/facebook.gresource.xml b/libpurple/protocols/facebook/resources/facebook.gresource.xml
deleted file mode 100644
index dcfbbdb67d..0000000000
--- a/libpurple/protocols/facebook/resources/facebook.gresource.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<gresources>
- <gresource prefix="/im/pidgin/libpurple/facebook">
- <file>icons/16x16/apps/im-facebook.png</file>
- <file>icons/22x22/apps/im-facebook.png</file>
- <file>icons/48x48/apps/im-facebook.png</file>
- </gresource>
-</gresources>
diff --git a/libpurple/protocols/facebook/resources/icons/16x16/apps/im-facebook.png b/libpurple/protocols/facebook/resources/icons/16x16/apps/im-facebook.png
deleted file mode 100644
index bc42cf9b0b..0000000000
--- a/libpurple/protocols/facebook/resources/icons/16x16/apps/im-facebook.png
+++ /dev/null
Binary files differ
diff --git a/libpurple/protocols/facebook/resources/icons/22x22/apps/im-facebook.png b/libpurple/protocols/facebook/resources/icons/22x22/apps/im-facebook.png
deleted file mode 100644
index 8036b198b3..0000000000
--- a/libpurple/protocols/facebook/resources/icons/22x22/apps/im-facebook.png
+++ /dev/null
Binary files differ
diff --git a/libpurple/protocols/facebook/resources/icons/48x48/apps/im-facebook.png b/libpurple/protocols/facebook/resources/icons/48x48/apps/im-facebook.png
deleted file mode 100644
index 2501acaab5..0000000000
--- a/libpurple/protocols/facebook/resources/icons/48x48/apps/im-facebook.png
+++ /dev/null
Binary files differ
diff --git a/libpurple/protocols/facebook/thrift.c b/libpurple/protocols/facebook/thrift.c
deleted file mode 100644
index 3d909a90dc..0000000000
--- a/libpurple/protocols/facebook/thrift.c
+++ /dev/null
@@ -1,675 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#include <string.h>
-
-#include "thrift.h"
-
-/**
- * FbThrift:
- *
- * Represents a reader/writer for compact Thrift data.
- */
-struct _FbThrift {
- GObject parent;
-
- GByteArray *bytes;
- gboolean internal;
- guint offset;
- guint pos;
- guint lastbool;
-};
-
-G_DEFINE_TYPE(FbThrift, fb_thrift, G_TYPE_OBJECT);
-
-static void
-fb_thrift_dispose(GObject *obj)
-{
- FbThrift* thft = FB_THRIFT(obj);
-
- if (thft->internal) {
- g_byte_array_free(thft->bytes, TRUE);
- thft->bytes = NULL;
- thft->internal = FALSE;
- }
-}
-
-static void
-fb_thrift_class_init(FbThriftClass *klass)
-{
- GObjectClass *gklass = G_OBJECT_CLASS(klass);
-
- gklass->dispose = fb_thrift_dispose;
-}
-
-static void
-fb_thrift_init(G_GNUC_UNUSED FbThrift *thft)
-{
-}
-
-FbThrift *
-fb_thrift_new(GByteArray *bytes, guint offset)
-{
- FbThrift *thft;
-
- thft = g_object_new(FB_TYPE_THRIFT, NULL);
-
- if (bytes != NULL) {
- thft->bytes = bytes;
- thft->offset = offset;
- thft->pos = offset;
- } else {
- thft->bytes = g_byte_array_new();
- thft->internal = TRUE;
- }
-
- return thft;
-}
-
-const GByteArray *
-fb_thrift_get_bytes(FbThrift *thft)
-{
- g_return_val_if_fail(FB_IS_THRIFT(thft), NULL);
-
- return thft->bytes;
-}
-
-guint
-fb_thrift_get_pos(FbThrift *thft)
-{
- g_return_val_if_fail(FB_IS_THRIFT(thft), 0);
-
- return thft->pos;
-}
-
-void
-fb_thrift_set_pos(FbThrift *thft, guint pos)
-{
- g_return_if_fail(FB_IS_THRIFT(thft));
-
- thft->pos = pos;
-}
-
-void
-fb_thrift_reset(FbThrift *thft)
-{
- g_return_if_fail(FB_IS_THRIFT(thft));
-
- thft->pos = thft->offset;
-}
-
-gboolean
-fb_thrift_read(FbThrift *thft, gpointer data, guint size)
-{
- g_return_val_if_fail(FB_IS_THRIFT(thft), FALSE);
-
- if ((thft->pos + size) > thft->bytes->len) {
- return FALSE;
- }
-
- if ((data != NULL) && (size > 0)) {
- memcpy(data, thft->bytes->data + thft->pos, size);
- }
-
- thft->pos += size;
- return TRUE;
-}
-
-gboolean
-fb_thrift_read_bool(FbThrift *thft, gboolean *value)
-{
- guint8 byte;
-
- g_return_val_if_fail(FB_IS_THRIFT(thft), FALSE);
-
- if ((thft->lastbool & 0x03) != 0x01) {
- if (!fb_thrift_read_byte(thft, &byte)) {
- return FALSE;
- }
-
- if (value != NULL) {
- *value = (byte & 0x0F) == 0x01;
- }
-
- thft->lastbool = 0;
- return TRUE;
- }
-
- if (value != NULL) {
- *value = ((thft->lastbool & 0x04) >> 2) != 0;
- }
-
- thft->lastbool = 0;
- return TRUE;
-}
-
-gboolean
-fb_thrift_read_byte(FbThrift *thft, guint8 *value)
-{
- return fb_thrift_read(thft, value, sizeof *value);
-}
-
-gboolean
-fb_thrift_read_dbl(FbThrift *thft, gdouble *value)
-{
- gint64 i64;
-
- /* Almost always 8, but check anyways */
- static const gsize size = MIN(sizeof value, sizeof i64);
-
- if (!fb_thrift_read_i64(thft, &i64)) {
- return FALSE;
- }
-
- if (value != NULL) {
- memcpy(value, &i64, size);
- }
-
- return TRUE;
-}
-
-gboolean
-fb_thrift_read_i16(FbThrift *thft, gint16 *value)
-{
- gint64 i64;
-
- if (!fb_thrift_read_i64(thft, &i64)) {
- return FALSE;
- }
-
- if (value != NULL) {
- *value = i64;
- }
-
- return TRUE;
-}
-
-gboolean
-fb_thrift_read_vi16(FbThrift *thft, guint16 *value)
-{
- guint64 u64;
-
- if (!fb_thrift_read_vi64(thft, &u64)) {
- return FALSE;
- }
-
- if (value != NULL) {
- *value = u64;
- }
-
- return TRUE;
-}
-
-gboolean
-fb_thrift_read_i32(FbThrift *thft, gint32 *value)
-{
- gint64 i64;
-
- if (!fb_thrift_read_i64(thft, &i64)) {
- return FALSE;
- }
-
- if (value != NULL) {
- *value = i64;
- }
-
- return TRUE;
-}
-
-gboolean
-fb_thrift_read_vi32(FbThrift *thft, guint32 *value)
-{
- guint64 u64;
-
- if (!fb_thrift_read_vi64(thft, &u64)) {
- return FALSE;
- }
-
- if (value != NULL) {
- *value = u64;
- }
-
- return TRUE;
-}
-
-gboolean
-fb_thrift_read_i64(FbThrift *thft, gint64 *value)
-{
- guint64 u64;
-
- if (!fb_thrift_read_vi64(thft, &u64)) {
- return FALSE;
- }
-
- if (value != NULL) {
- /* Convert from zigzag to integer */
- *value = (u64 >> 0x01) ^ -(u64 & 0x01);
- }
-
- return TRUE;
-}
-
-gboolean
-fb_thrift_read_vi64(FbThrift *thft, guint64 *value)
-{
- guint i = 0;
- guint8 byte;
- guint64 u64 = 0;
-
- do {
- if (!fb_thrift_read_byte(thft, &byte)) {
- return FALSE;
- }
-
- u64 |= ((guint64) (byte & 0x7F)) << i;
- i += 7;
- } while ((byte & 0x80) == 0x80);
-
- if (value != NULL) {
- *value = u64;
- }
-
- return TRUE;
-}
-
-gboolean
-fb_thrift_read_str(FbThrift *thft, gchar **value)
-{
- guint8 *data;
- guint32 size;
-
- if (!fb_thrift_read_vi32(thft, &size)) {
- return FALSE;
- }
-
- if (value != NULL) {
- data = g_new(guint8, size + 1);
- data[size] = 0;
- } else {
- data = NULL;
- }
-
- if (!fb_thrift_read(thft, data, size)) {
- g_free(data);
- return FALSE;
- }
-
- if (value != NULL) {
- *value = (gchar *) data;
- }
-
- return TRUE;
-}
-
-gboolean
-fb_thrift_read_field(FbThrift *thft, FbThriftType *type, gint16 *id,
- gint16 lastid)
-{
- gint16 i16;
- guint8 byte;
-
- g_return_val_if_fail(FB_IS_THRIFT(thft), FALSE);
- g_return_val_if_fail(type != NULL, FALSE);
- g_return_val_if_fail(id != NULL, FALSE);
-
- if (!fb_thrift_read_byte(thft, &byte)) {
- return FALSE;
- }
-
- if (byte == FB_THRIFT_TYPE_STOP) {
- *type = FB_THRIFT_TYPE_STOP;
- return FALSE;
- }
-
- *type = fb_thrift_ct2t(byte & 0x0F);
- i16 = (byte & 0xF0) >> 4;
-
- if (i16 == 0) {
- if (!fb_thrift_read_i16(thft, id)) {
- return FALSE;
- }
- } else {
- *id = lastid + i16;
- }
-
- if (*type == FB_THRIFT_TYPE_BOOL) {
- thft->lastbool = 0x01;
-
- if ((byte & 0x0F) == 0x01) {
- thft->lastbool |= 0x01 << 2;
- }
- }
-
- return TRUE;
-}
-
-gboolean
-fb_thrift_read_stop(FbThrift *thft)
-{
- guint8 byte;
-
- return fb_thrift_read_byte(thft, &byte) &&
- (byte == FB_THRIFT_TYPE_STOP);
-}
-
-gboolean
-fb_thrift_read_isstop(FbThrift *thft)
-{
- guint8 byte;
-
- g_return_val_if_fail(FB_IS_THRIFT(thft), FALSE);
-
- if (!fb_thrift_read_byte(thft, &byte)) {
- return FALSE;
- }
-
- thft->pos--;
- return byte == FB_THRIFT_TYPE_STOP;
-}
-
-gboolean
-fb_thrift_read_list(FbThrift *thft, FbThriftType *type, guint *size)
-{
- guint8 byte;
- guint32 u32;
-
- g_return_val_if_fail(type != NULL, FALSE);
- g_return_val_if_fail(size != NULL, FALSE);
-
- if (!fb_thrift_read_byte(thft, &byte)) {
- return FALSE;
- }
-
- *type = fb_thrift_ct2t(byte & 0x0F);
- *size = (byte & 0xF0) >> 4;
-
- if (*size == 0x0F) {
- if (!fb_thrift_read_vi32(thft, &u32)) {
- return FALSE;
- }
-
- *size = u32;
- }
-
- return TRUE;
-}
-
-gboolean
-fb_thrift_read_map(FbThrift *thft, FbThriftType *ktype, FbThriftType *vtype,
- guint *size)
-{
- gint32 i32;
- guint8 byte;
-
- g_return_val_if_fail(ktype != NULL, FALSE);
- g_return_val_if_fail(vtype != NULL, FALSE);
- g_return_val_if_fail(size != NULL, FALSE);
-
- if (!fb_thrift_read_i32(thft, &i32)) {
- return FALSE;
- }
-
- if (i32 != 0) {
- if (!fb_thrift_read_byte(thft, &byte)) {
- return FALSE;
- }
-
- *ktype = fb_thrift_ct2t((byte & 0xF0) >> 4);
- *vtype = fb_thrift_ct2t(byte & 0x0F);
- } else {
- *ktype = 0;
- *vtype = 0;
- }
-
- *size = i32;
- return TRUE;
-}
-
-gboolean
-fb_thrift_read_set(FbThrift *thft, FbThriftType *type, guint *size)
-{
- return fb_thrift_read_list(thft, type, size);
-}
-
-void
-fb_thrift_write(FbThrift *thft, gconstpointer data, guint size)
-{
- g_return_if_fail(FB_IS_THRIFT(thft));
-
- g_byte_array_append(thft->bytes, data, size);
- thft->pos += size;
-}
-
-void
-fb_thrift_write_bool(FbThrift *thft, gboolean value)
-{
- guint pos;
-
- g_return_if_fail(FB_IS_THRIFT(thft));
-
- if ((thft->lastbool & 0x03) != 0x02) {
- fb_thrift_write_byte(thft, value ? 0x01 : 0x02);
- return;
- }
-
- pos = thft->lastbool >> 3;
- thft->lastbool = 0;
-
- if ((pos >= thft->offset) && (pos < thft->bytes->len)) {
- thft->bytes->data[pos] &= ~0x0F;
- thft->bytes->data[pos] |= value ? 0x01 : 0x02;
- }
-}
-
-void
-fb_thrift_write_byte(FbThrift *thft, guint8 value)
-{
- fb_thrift_write(thft, &value, sizeof value);
-}
-
-void
-fb_thrift_write_dbl(FbThrift *thft, gdouble value)
-{
- gint64 i64;
-
- /* Almost always 8, but check anyways */
- static const gsize size = MIN(sizeof value, sizeof i64);
-
- memcpy(&i64, &value, size);
- fb_thrift_write_i64(thft, i64);
-}
-
-void
-fb_thrift_write_i16(FbThrift *thft, gint16 value)
-{
- fb_thrift_write_i64(thft, value);
-}
-
-void
-fb_thrift_write_vi16(FbThrift *thft, guint16 value)
-{
- fb_thrift_write_vi64(thft, value);
-}
-
-void
-fb_thrift_write_i32(FbThrift *thft, gint32 value)
-{
- value = (value << 1) ^ (value >> 31);
- fb_thrift_write_vi64(thft, value);
-}
-
-void
-fb_thrift_write_vi32(FbThrift *thft, guint32 value)
-{
- fb_thrift_write_vi64(thft, value);
-}
-
-void
-fb_thrift_write_i64(FbThrift *thft, gint64 value)
-{
- value = (value << 1) ^ (value >> 63);
- fb_thrift_write_vi64(thft, value);
-}
-
-void
-fb_thrift_write_vi64(FbThrift *thft, guint64 value)
-{
- gboolean last;
- guint8 byte;
-
- do {
- last = (value & ~0x7F) == 0;
- byte = value & 0x7F;
-
- if (!last) {
- byte |= 0x80;
- value >>= 7;
- }
-
- fb_thrift_write_byte(thft, byte);
- } while (!last);
-}
-
-void
-fb_thrift_write_str(FbThrift *thft, const gchar *value)
-{
- guint32 size;
-
- g_return_if_fail(value != NULL);
-
- size = strlen(value);
- fb_thrift_write_vi32(thft, size);
- fb_thrift_write(thft, value, size);
-}
-
-void
-fb_thrift_write_field(FbThrift *thft, FbThriftType type, gint16 id,
- gint16 lastid)
-{
- gint16 diff;
-
- g_return_if_fail(FB_IS_THRIFT(thft));
-
- if (type == FB_THRIFT_TYPE_BOOL) {
- thft->lastbool = (thft->pos << 3) | 0x02;
- }
-
- type = fb_thrift_t2ct(type);
- diff = id - lastid;
-
- if ((id <= lastid) || (diff > 0x0F)) {
- fb_thrift_write_byte(thft, type);
- fb_thrift_write_i16(thft, id);
- } else {
- fb_thrift_write_byte(thft, (diff << 4) | type);
- }
-}
-
-void
-fb_thrift_write_stop(FbThrift *thft)
-{
- fb_thrift_write_byte(thft, FB_THRIFT_TYPE_STOP);
-}
-
-void
-fb_thrift_write_list(FbThrift *thft, FbThriftType type, guint size)
-{
- type = fb_thrift_t2ct(type);
-
- if (size <= 14) {
- fb_thrift_write_byte(thft, (size << 4) | type);
- return;
- }
-
- fb_thrift_write_vi32(thft, size);
- fb_thrift_write_byte(thft, 0xF0 | type);
-}
-
-void
-fb_thrift_write_map(FbThrift *thft, FbThriftType ktype, FbThriftType vtype,
- guint size)
-{
- if (size == 0) {
- fb_thrift_write_byte(thft, 0);
- return;
- }
-
- ktype = fb_thrift_t2ct(ktype);
- vtype = fb_thrift_t2ct(vtype);
-
- fb_thrift_write_vi32(thft, size);
- fb_thrift_write_byte(thft, (ktype << 4) | vtype);
-}
-
-void
-fb_thrift_write_set(FbThrift *thft, FbThriftType type, guint size)
-{
- fb_thrift_write_list(thft, type, size);
-}
-
-guint8
-fb_thrift_t2ct(FbThriftType type)
-{
- static const guint8 types[] = {
- [FB_THRIFT_TYPE_STOP] = 0,
- [FB_THRIFT_TYPE_VOID] = 0,
- [FB_THRIFT_TYPE_BOOL] = 2,
- [FB_THRIFT_TYPE_BYTE] = 3,
- [FB_THRIFT_TYPE_DOUBLE] = 7,
- [5] = 0,
- [FB_THRIFT_TYPE_I16] = 4,
- [7] = 0,
- [FB_THRIFT_TYPE_I32] = 5,
- [9] = 0,
- [FB_THRIFT_TYPE_I64] = 6,
- [FB_THRIFT_TYPE_STRING] = 8,
- [FB_THRIFT_TYPE_STRUCT] = 12,
- [FB_THRIFT_TYPE_MAP] = 11,
- [FB_THRIFT_TYPE_SET] = 10,
- [FB_THRIFT_TYPE_LIST] = 9
- };
-
- g_return_val_if_fail(type < G_N_ELEMENTS(types), 0);
- return types[type];
-}
-
-FbThriftType
-fb_thrift_ct2t(guint8 type)
-{
- static const guint8 types[] = {
- [0] = FB_THRIFT_TYPE_STOP,
- [1] = FB_THRIFT_TYPE_BOOL,
- [2] = FB_THRIFT_TYPE_BOOL,
- [3] = FB_THRIFT_TYPE_BYTE,
- [4] = FB_THRIFT_TYPE_I16,
- [5] = FB_THRIFT_TYPE_I32,
- [6] = FB_THRIFT_TYPE_I64,
- [7] = FB_THRIFT_TYPE_DOUBLE,
- [8] = FB_THRIFT_TYPE_STRING,
- [9] = FB_THRIFT_TYPE_LIST,
- [10] = FB_THRIFT_TYPE_SET,
- [11] = FB_THRIFT_TYPE_MAP,
- [12] = FB_THRIFT_TYPE_STRUCT
- };
-
- g_return_val_if_fail(type < G_N_ELEMENTS(types), 0);
- return types[type];
-}
diff --git a/libpurple/protocols/facebook/thrift.h b/libpurple/protocols/facebook/thrift.h
deleted file mode 100644
index fbb02d9cc1..0000000000
--- a/libpurple/protocols/facebook/thrift.h
+++ /dev/null
@@ -1,553 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#ifndef PURPLE_FACEBOOK_THRIFT_H
-#define PURPLE_FACEBOOK_THRIFT_H
-
-#include <glib.h>
-#include <glib-object.h>
-
-#define FB_TYPE_THRIFT fb_thrift_get_type()
-
-/**
- * FbThriftType:
- * @FB_THRIFT_TYPE_STOP: A stopper for certain types.
- * @FB_THRIFT_TYPE_VOID: A void or empty value.
- * @FB_THRIFT_TYPE_BOOL: A boolean (#TRUE or #FALSE).
- * @FB_THRIFT_TYPE_BYTE: A signed 8-bit integer.
- * @FB_THRIFT_TYPE_DOUBLE: A 64-bit floating point number.
- * @FB_THRIFT_TYPE_I16: A signed 16-bit integer.
- * @FB_THRIFT_TYPE_I32: A signed 32-bit integer.
- * @FB_THRIFT_TYPE_I64: A signed 64-bit integer.
- * @FB_THRIFT_TYPE_STRING: A UTF-8 encoded string.
- * @FB_THRIFT_TYPE_STRUCT: A set of typed fields.
- * @FB_THRIFT_TYPE_MAP: A map of unique keys to values.
- * @FB_THRIFT_TYPE_SET: A unique set of values.
- * @FB_THRIFT_TYPE_LIST: A ordered list of values.
- * @FB_THRIFT_TYPE_ENUM: A 32-bit enumerated list.
- * @FB_THRIFT_TYPE_UNKNOWN: An unknown type.
- *
- * The Thrift data types.
- */
-typedef enum
-{
- FB_THRIFT_TYPE_STOP = 0,
- FB_THRIFT_TYPE_VOID = 1,
- FB_THRIFT_TYPE_BOOL = 2,
- FB_THRIFT_TYPE_BYTE = 3,
- FB_THRIFT_TYPE_DOUBLE = 4,
- FB_THRIFT_TYPE_I16 = 6,
- FB_THRIFT_TYPE_I32 = 8,
- FB_THRIFT_TYPE_I64 = 10,
- FB_THRIFT_TYPE_STRING = 11,
- FB_THRIFT_TYPE_STRUCT = 12,
- FB_THRIFT_TYPE_MAP = 13,
- FB_THRIFT_TYPE_SET = 14,
- FB_THRIFT_TYPE_LIST = 15,
- FB_THRIFT_TYPE_ENUM = 16,
-
- FB_THRIFT_TYPE_UNKNOWN
-} FbThriftType;
-
-G_DECLARE_FINAL_TYPE(FbThrift, fb_thrift, FB, THRIFT, GObject)
-
-/**
- * fb_thrift_new:
- * @bytes: The #GByteArray to read or write.
- * @offset: The offset in bytes of the data in @bytes.
- *
- * Creates a new #FbThrift. The returned #FbThrift should be freed with
- * #g_object_unref() when no longer needed. This will optionally use a
- * #GByteArray at an offset, rather than a newly created and internal
- * #GByteArray.
- *
- * Returns: The new #FbThrift.
- */
-FbThrift *
-fb_thrift_new(GByteArray *bytes, guint offset);
-
-/**
- * fb_thrift_get_bytes:
- * @thft: The #FbThrift.
- *
- * Gets the underlying #GByteArray of an #FbThrift.
- *
- * Returns: The #GByteArray.
- */
-const GByteArray *
-fb_thrift_get_bytes(FbThrift *thft);
-
-/**
- * fb_thrift_get_pos:
- * @thft: The #FbThrift.
- *
- * Gets the cursor position of an #FbThrift.
- *
- * Returns: The cursor position.
- */
-guint
-fb_thrift_get_pos(FbThrift *thft);
-
-/**
- * fb_thrift_set_pos:
- * @thft: The #FbThrift.
- * @pos: The position.
- *
- * Sets the cursor position of an #FbThrift.
- */
-void
-fb_thrift_set_pos(FbThrift *thft, guint pos);
-
-/**
- * fb_thrift_reset:
- * @thft: The #FbThrift.
- *
- * Resets the cursor position of an #FbThrift.
- */
-void
-fb_thrift_reset(FbThrift *thft);
-
-/**
- * fb_thrift_read:
- * @thft: The #FbThrift.
- * @data: The data buffer.
- * @size: The size of @buffer.
- *
- * Reads data from the #FbThrift into a buffer. If @data is #NULL, this
- * will simply advance the cursor position.
- *
- * Returns: #TRUE if the data was read, otherwise #FALSE.
- */
-gboolean
-fb_thrift_read(FbThrift *thft, gpointer data, guint size);
-
-/**
- * fb_thrift_read_bool:
- * @thft: The #FbThrift.
- * @value: The return location for the value or #NULL.
- *
- * Reads a boolean value from the #FbThrift. If @value is #NULL, this
- * will simply advance the cursor position.
- *
- * Returns: #TRUE if the value was read, otherwise #FALSE.
- */
-gboolean
-fb_thrift_read_bool(FbThrift *thft, gboolean *value);
-
-/**
- * fb_thrift_read_byte:
- * @thft: The #FbThrift.
- * @value: The return location for the value or #NULL.
- *
- * Reads an 8-bit integer value from the #FbThrift. If @value is #NULL,
- * this will simply advance the cursor position.
- *
- * Returns: #TRUE if the value was read, otherwise #FALSE.
- */
-gboolean
-fb_thrift_read_byte(FbThrift *thft, guint8 *value);
-
-/**
- * fb_thrift_read_dbl:
- * @thft: The #FbThrift.
- * @value: The return location for the value or #NULL.
- *
- * Reads a 64-bit floating point value from the #FbThrift. If @value
- * is #NULL, this will simply advance the cursor position.
- *
- * Returns: #TRUE if the value was read, otherwise #FALSE.
- */
-gboolean
-fb_thrift_read_dbl(FbThrift *thft, gdouble *value);
-
-/**
- * fb_thrift_read_i16:
- * @thft: The #FbThrift.
- * @value: The return location for the value or #NULL.
- *
- * Reads a signed 16-bit integer value from the #FbThrift. This will
- * convert the integer from the zig-zag format. If @value is #NULL,
- * this will simply advance the cursor position.
- *
- * Returns: #TRUE if the value was read, otherwise #FALSE.
- */
-gboolean
-fb_thrift_read_i16(FbThrift *thft, gint16 *value);
-
-/**
- * fb_thrift_read_vi16:
- * @thft: The #FbThrift.
- * @value: The return location for the value or #NULL.
- *
- * Reads a 16-bit integer value from the #FbThrift. This reads the raw
- * integer value without converting it from the zig-zag format. If
- * @value is #NULL, this will simply advance the cursor position.
- *
- * Returns: #TRUE if the value was read, otherwise #FALSE.
- */
-gboolean
-fb_thrift_read_vi16(FbThrift *thft, guint16 *value);
-
-/**
- * fb_thrift_read_i32:
- * @thft: The #FbThrift.
- * @value: The return location for the value or #NULL.
- *
- * Reads a signed 32-bit integer value from the #FbThrift. This will
- * convert the integer from the zig-zag format. If @value is #NULL,
- * this will simply advance the cursor position.
- *
- * Returns: #TRUE if the value was read, otherwise #FALSE.
- */
-gboolean
-fb_thrift_read_i32(FbThrift *thft, gint32 *value);
-
-/**
- * fb_thrift_read_vi32:
- * @thft: The #FbThrift.
- * @value: The return location for the value or #NULL.
- *
- * Reads a 32-bit integer value from the #FbThrift. This reads the raw
- * integer value without converting it from the zig-zag format. If
- * @value is #NULL, this will simply advance the cursor position.
- *
- * Returns: #TRUE if the value was read, otherwise #FALSE.
- */
-gboolean
-fb_thrift_read_vi32(FbThrift *thft, guint32 *value);
-
-/**
- * fb_thrift_read_i64:
- * @thft: The #FbThrift.
- * @value: The return location for the value or #NULL.
- *
- * Reads a signed 64-bit integer value from the #FbThrift. This will
- * convert the integer from the zig-zag format. If @value is #NULL,
- * this will simply advance the cursor position.
- *
- * Returns: #TRUE if the value was read, otherwise #FALSE.
- */
-gboolean
-fb_thrift_read_i64(FbThrift *thft, gint64 *value);
-
-/**
- * fb_thrift_read_vi64:
- * @thft: The #FbThrift.
- * @value: The return location for the value or #NULL.
- *
- * Reads a 64-bit integer value from the #FbThrift. This reads the raw
- * integer value without converting it from the zig-zag format. If
- * @value is #NULL, this will simply advance the cursor position.
- *
- * Returns: #TRUE if the value was read, otherwise #FALSE.
- */
-gboolean
-fb_thrift_read_vi64(FbThrift *thft, guint64 *value);
-
-/**
- * fb_thrift_read_str:
- * @thft: The #FbThrift.
- * @value: The return location for the value or #NULL.
- *
- * Reads a string value from the #FbThrift. The value returned to
- * @value should be freed with #g_free() when no longer needed. If
- * @value is #NULL, this will simply advance the cursor position.
- *
- * Returns: #TRUE if the value was read, otherwise #FALSE.
- */
-gboolean
-fb_thrift_read_str(FbThrift *thft, gchar **value);
-
-/**
- * fb_thrift_read_field:
- * @thft: The #FbThrift.
- * @type: The return location for the #FbThriftType.
- * @id: The return location for the identifier.
- * @lastid: The identifier of the previous field.
- *
- * Reads a field header from the #FbThrift.
- *
- * Returns: #TRUE if the field header was read, otherwise #FALSE.
- */
-gboolean
-fb_thrift_read_field(FbThrift *thft, FbThriftType *type, gint16 *id,
- gint16 lastid);
-
-/**
- * fb_thrift_read_stop:
- * @thft: The #FbThrift.
- *
- * Reads a field stop from the #FbThrift.
- *
- * Returns: #TRUE if the field stop was read, otherwise #FALSE.
- */
-gboolean
-fb_thrift_read_stop(FbThrift *thft);
-
-/**
- * fb_thrift_read_isstop:
- * @thft: The #FbThrift.
- *
- * Determines if the next byte of the #FbThrift is a field stop.
- *
- * Returns: #TRUE if the next byte is a field stop, otherwise #FALSE.
- */
-gboolean
-fb_thrift_read_isstop(FbThrift *thft);
-
-/**
- * fb_thrift_read_list:
- * @thft: The #FbThrift.
- * @type: The return location for the #FbThriftType.
- * @size: The return location for the size.
- *
- * Reads a list header from the #FbThrift.
- *
- * Returns: #TRUE if the list header was read, otherwise #FALSE.
- */
-gboolean
-fb_thrift_read_list(FbThrift *thft, FbThriftType *type, guint *size);
-
-/**
- * fb_thrift_read_map:
- * @thft: The #FbThrift.
- * @ktype: The return location for the key #FbThriftType.
- * @vtype: The return location for the value #FbThriftType.
- * @size: The return location for the size.
- *
- * Reads a map header from the #FbThrift.
- *
- * Returns: #TRUE if the map header was read, otherwise #FALSE.
- */
-gboolean
-fb_thrift_read_map(FbThrift *thft, FbThriftType *ktype, FbThriftType *vtype,
- guint *size);
-
-/**
- * fb_thrift_read_set:
- * @thft: The #FbThrift.
- * @type: The return location for the #FbThriftType.
- * @size: The return location for the size.
- *
- * Reads a set header from the #FbThrift.
- *
- * Returns: #TRUE if the set header was read, otherwise #FALSE.
- */
-gboolean
-fb_thrift_read_set(FbThrift *thft, FbThriftType *type, guint *size);
-
-/**
- * fb_thrift_write:
- * @thft: The #FbThrift.
- * @data: The data buffer.
- * @size: The size of @buffer.
- *
- * Writes data to the #FbThrift.
- */
-void
-fb_thrift_write(FbThrift *thft, gconstpointer data, guint size);
-
-/**
- * fb_thrift_write_bool:
- * @thft: The #FbThrift.
- * @value: The value.
- *
- * Writes a boolean value to the #FbThrift.
- */
-void
-fb_thrift_write_bool(FbThrift *thft, gboolean value);
-
-/**
- * fb_thrift_write_byte:
- * @thft: The #FbThrift.
- * @value: The value.
- *
- * Writes an 8-bit integer value to the #FbThrift.
- */
-void
-fb_thrift_write_byte(FbThrift *thft, guint8 value);
-
-/**
- * fb_thrift_write_dbl:
- * @thft: The #FbThrift.
- * @value: The value.
- *
- * Writes a 64-bit floating point value to the #FbThrift.
- */
-void
-fb_thrift_write_dbl(FbThrift *thft, gdouble value);
-
-/**
- * fb_thrift_write_i16:
- * @thft: The #FbThrift.
- * @value: The value.
- *
- * Writes a signed 16-bit integer value to the #FbThrift. This will
- * convert the integer to the zig-zag format.
- */
-void
-fb_thrift_write_i16(FbThrift *thft, gint16 value);
-
-/**
- * fb_thrift_write_vi16:
- * @thft: The #FbThrift.
- * @value: The value.
- *
- * Writes a 16-bit integer value to the #FbThrift. This writes the raw
- * integer value without converting it to the zig-zag format.
- */
-void
-fb_thrift_write_vi16(FbThrift *thft, guint16 value);
-
-/**
- * fb_thrift_write_i32:
- * @thft: The #FbThrift.
- * @value: The value.
- *
- * Writes a signed 32-bit integer value to the #FbThrift. This will
- * convert the integer to the zig-zag format.
- */
-void
-fb_thrift_write_i32(FbThrift *thft, gint32 value);
-
-/**
- * fb_thrift_write_vi32:
- * @thft: The #FbThrift.
- * @value: The value.
- *
- * Writes a 32-bit integer value to the #FbThrift. This writes the raw
- * integer value without converting it to the zig-zag format.
- */
-void
-fb_thrift_write_vi32(FbThrift *thft, guint32 value);
-
-/**
- * fb_thrift_write_i64:
- * @thft: The #FbThrift.
- * @value: The value.
- *
- * Writes a signed 64-bit integer value to the #FbThrift. This will
- * convert the integer to the zig-zag format.
- */
-void
-fb_thrift_write_i64(FbThrift *thft, gint64 value);
-
-/**
- * fb_thrift_write_vi64:
- * @thft: The #FbThrift.
- * @value: The value.
- *
- * Writes a 64-bit integer value to the #FbThrift. This writes the raw
- * integer value without converting it to the zig-zag format.
- */
-void
-fb_thrift_write_vi64(FbThrift *thft, guint64 value);
-
-/**
- * fb_thrift_write_str:
- * @thft: The #FbThrift.
- * @value: The value.
- *
- * Writes a string value to the #FbThrift.
- */
-void
-fb_thrift_write_str(FbThrift *thft, const gchar *value);
-
-/**
- * fb_thrift_write_field:
- * @thft: The #FbThrift.
- * @type: The #FbThriftType.
- * @id: The identifier.
- * @lastid: The identifier of the previous field.
- *
- * Writes a field header to the #FbThrift.
- */
-void
-fb_thrift_write_field(FbThrift *thft, FbThriftType type, gint16 id,
- gint16 lastid);
-
-/**
- * fb_thrift_write_stop:
- * @thft: The #FbThrift.
- *
- * Writes a field stop to the #FbThrift.
- */
-void
-fb_thrift_write_stop(FbThrift *thft);
-
-/**
- * fb_thrift_write_list:
- * @thft: The #FbThrift.
- * @type: The #FbThriftType.
- * @size: The size.
- *
- * Writes a list header to the #FbThrift.
- */
-void
-fb_thrift_write_list(FbThrift *thft, FbThriftType type, guint size);
-
-/**
- * fb_thrift_write_map:
- * @thft: The #FbThrift.
- * @ktype: The key #FbThriftType.
- * @vtype: The value #FbThriftType.
- * @size: The size.
- *
- * Writes a map header to the #FbThrift.
- */
-void
-fb_thrift_write_map(FbThrift *thft, FbThriftType ktype, FbThriftType vtype,
- guint size);
-
-/**
- * fb_thrift_write_set:
- * @thft: The #FbThrift.
- * @type: The #FbThriftType.
- * @size: The size.
- *
- * Writes a set header to the #FbThrift.
- */
-void
-fb_thrift_write_set(FbThrift *thft, FbThriftType type, guint size);
-
-/**
- * fb_thrift_t2ct:
- * @type: The #FbThriftType.
- *
- * Converts a #FbThriftType to a compact type.
- *
- * Return: The equivalent compact type.
- */
-guint8
-fb_thrift_t2ct(FbThriftType type);
-
-/**
- * fb_thrift_ct2t:
- * @type: The compact type.
- *
- * Converts a compact type to an #FbThriftType.
- *
- * Return: The equivalent #FbThriftType.
- */
-FbThriftType
-fb_thrift_ct2t(guint8 type);
-
-#endif /* PURPLE_FACEBOOK_THRIFT_H */
diff --git a/libpurple/protocols/facebook/util.c b/libpurple/protocols/facebook/util.c
deleted file mode 100644
index 4590e746dc..0000000000
--- a/libpurple/protocols/facebook/util.c
+++ /dev/null
@@ -1,619 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#include <glib.h>
-#include <glib/gi18n-lib.h>
-
-#include <gio/gio.h>
-#include <stdarg.h>
-#include <string.h>
-
-#include <purple.h>
-
-#include "util.h"
-
-GQuark
-fb_util_error_quark(void)
-{
- static GQuark q = 0;
-
- if (G_UNLIKELY(q == 0)) {
- q = g_quark_from_static_string("fb-util-error-quark");
- }
-
- return q;
-}
-
-PurpleBuddy *
-fb_util_account_find_buddy(PurpleAccount *acct, PurpleChatConversation *chat,
- const gchar *search, GError **error)
-{
- const gchar *alias;
- const gchar *name;
- GSList *buddies;
- GSList *l;
- guint retc;
- PurpleBuddy *ret = NULL;
-
- g_return_val_if_fail(PURPLE_IS_ACCOUNT(acct), NULL);
- g_return_val_if_fail(search != NULL, NULL);
-
- buddies = purple_blist_find_buddies(acct, NULL);
-
- for (retc = 0, l = buddies; l != NULL; l = l->next) {
- name = purple_buddy_get_name(l->data);
- alias = purple_buddy_get_alias(l->data);
-
- if ((chat != NULL) &&
- !purple_chat_conversation_has_user(chat, name))
- {
- continue;
- }
-
- if (g_ascii_strcasecmp(name, search) == 0) {
- ret = l->data;
- retc++;
- }
-
- if (g_ascii_strcasecmp(alias, search) == 0) {
- ret = l->data;
- retc++;
- }
- }
-
- if (retc == 0) {
- g_set_error(error, FB_UTIL_ERROR, FB_UTIL_ERROR_GENERAL,
- _("Buddy %s not found"), search);
- } else if (retc > 1) {
- g_set_error(error, FB_UTIL_ERROR, FB_UTIL_ERROR_GENERAL,
- _("Buddy name %s is ambiguous"), search);
- ret = NULL;
- }
-
- g_slist_free(buddies);
- return ret;
-}
-
-void
-fb_util_debug(PurpleDebugLevel level, const gchar *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- fb_util_vdebug(level, format, ap);
- va_end(ap);
-}
-
-void
-fb_util_vdebug(PurpleDebugLevel level, const gchar *format, va_list ap)
-{
- gboolean unsafe;
- gboolean verbose;
- gchar *str;
-
- g_return_if_fail(format != NULL);
-
- unsafe = (level & FB_UTIL_DEBUG_FLAG_UNSAFE) != 0;
- verbose = (level & FB_UTIL_DEBUG_FLAG_VERBOSE) != 0;
-
- if ((unsafe && !purple_debug_is_unsafe()) ||
- (verbose && !purple_debug_is_verbose()))
- {
- return;
- }
-
- /* Ensure all local flags are removed */
- level &= ~FB_UTIL_DEBUG_FLAG_ALL;
-
- str = g_strdup_vprintf(format, ap);
- purple_debug(level, "facebook", "%s", str);
- g_free(str);
-}
-
-void
-fb_util_debug_misc(const gchar *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- fb_util_vdebug(PURPLE_DEBUG_MISC, format, ap);
- va_end(ap);
-}
-
-void
-fb_util_debug_info(const gchar *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- fb_util_vdebug(PURPLE_DEBUG_INFO, format, ap);
- va_end(ap);
-}
-
-void
-fb_util_debug_warning(const gchar *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- fb_util_vdebug(PURPLE_DEBUG_WARNING, format, ap);
- va_end(ap);
-}
-
-void
-fb_util_debug_error(const gchar *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- fb_util_vdebug(PURPLE_DEBUG_ERROR, format, ap);
- va_end(ap);
-}
-
-void
-fb_util_debug_fatal(const gchar *format, ...)
-{
- va_list ap;
-
- va_start(ap, format);
- fb_util_vdebug(PURPLE_DEBUG_FATAL, format, ap);
- va_end(ap);
-}
-
-void
-fb_util_debug_hexdump(PurpleDebugLevel level, const GByteArray *bytes,
- const gchar *format, ...)
-{
- gchar c;
- guint i;
- guint j;
- GString *gstr;
- va_list ap;
-
- static const gchar *indent = " ";
-
- g_return_if_fail(bytes != NULL);
-
- if (format != NULL) {
- va_start(ap, format);
- fb_util_vdebug(level, format, ap);
- va_end(ap);
- }
-
- gstr = g_string_sized_new(80);
-
- for (i = 0; i < bytes->len; i += 16) {
- g_string_append_printf(gstr, "%s%08x ", indent, i);
-
- for (j = 0; j < 16; j++) {
- if ((i + j) < bytes->len) {
- g_string_append_printf(gstr, "%02x ",
- bytes->data[i + j]);
- } else {
- g_string_append(gstr, " ");
- }
-
- if (j == 7) {
- g_string_append_c(gstr, ' ');
- }
- }
-
- g_string_append(gstr, " |");
-
- for (j = 0; (j < 16) && ((i + j) < bytes->len); j++) {
- c = bytes->data[i + j];
-
- if (!g_ascii_isprint(c) || g_ascii_isspace(c)) {
- c = '.';
- }
-
- g_string_append_c(gstr, c);
- }
-
- g_string_append_c(gstr, '|');
- fb_util_debug(level, "%s", gstr->str);
- g_string_erase(gstr, 0, -1);
- }
-
- g_string_append_printf(gstr, "%s%08x", indent, i);
- fb_util_debug(level, "%s", gstr->str);
- g_string_free(gstr, TRUE);
-}
-
-gchar *
-fb_util_get_locale(void)
-{
- const gchar * const *langs;
- const gchar *lang;
- gchar *chr;
- guint i;
-
- static const gchar chrs[] = {'.', '@'};
-
- langs = g_get_language_names();
- lang = langs[0];
-
- if (purple_strequal(lang, "C")) {
- return g_strdup("en_US");
- }
-
- for (i = 0; i < G_N_ELEMENTS(chrs); i++) {
- chr = strchr(lang, chrs[i]);
-
- if (chr != NULL) {
- return g_strndup(lang, chr - lang);
- }
- }
-
- return g_strdup(lang);
-}
-
-gchar *
-fb_util_rand_alnum(guint len)
-{
- gchar *ret;
- GRand *rand;
- guint i;
- guint j;
-
- static const gchar chars[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789";
- static const gsize charc = G_N_ELEMENTS(chars) - 1;
-
- g_return_val_if_fail(len > 0, NULL);
- rand = g_rand_new();
- ret = g_new(gchar, len + 1);
-
- for (i = 0; i < len; i++) {
- j = g_rand_int_range(rand, 0, charc);
- ret[i] = chars[j];
- }
-
- ret[len] = 0;
- g_rand_free(rand);
- return ret;
-}
-
-static void
-fb_util_request_buddy_ok(gpointer *request_data, PurpleRequestPage *page) {
- FbUtilRequestBuddyFunc func = request_data[0];
- GList *l;
- GList *select;
- gpointer data = request_data[2];
- GSList *ret = NULL;
- PurpleBuddy *bdy;
- PurpleRequestFieldList *field;
-
- if (func == NULL) {
- g_free(request_data);
- return;
- }
-
- field = PURPLE_REQUEST_FIELD_LIST(purple_request_page_get_field(page,
- "buddy"));
- select = purple_request_field_list_get_selected(field);
-
- for (l = select; l != NULL; l = l->next) {
- bdy = purple_request_field_list_get_data(field, l->data);
- ret = g_slist_prepend(ret, bdy);
- }
-
- ret = g_slist_reverse(ret);
- func(ret, data);
-
- g_slist_free(ret);
- g_free(request_data);
-}
-
-static void
-fb_util_request_buddy_cancel(gpointer *request_data,
- G_GNUC_UNUSED PurpleRequestPage *page)
-{
- FbUtilRequestBuddyFunc func = request_data[1];
- gpointer data = request_data[2];
-
- if (func != NULL) {
- func(NULL, data);
- }
-
- g_free(request_data);
-}
-
-static gint
-fb_buddy_cmp(gconstpointer a, gconstpointer b)
-{
- PurpleBuddy *pba, *pbb;
- gint alias_verdict, name_verdict;
- gchar *astr, *bstr;
-
- pba = PURPLE_BUDDY(a);
- pbb = PURPLE_BUDDY(b);
-
- astr = g_utf8_casefold(purple_buddy_get_alias(pba), -1);
- bstr = g_utf8_casefold(purple_buddy_get_alias(pbb), -1);
- alias_verdict = g_utf8_collate(astr, bstr);
- g_free(astr);
- g_free(bstr);
- if (alias_verdict != 0) {
- return alias_verdict;
- }
- astr = g_utf8_casefold(purple_buddy_get_name(pba), -1);
- bstr = g_utf8_casefold(purple_buddy_get_name(pbb), -1);
- name_verdict = g_utf8_collate(astr, bstr);
- g_free(astr);
- g_free(bstr);
- return name_verdict;
-}
-
-gpointer
-fb_util_request_buddy(PurpleConnection *gc, const gchar *title,
- const gchar *primary, const gchar *secondary,
- GSList *select, gboolean multi, GCallback ok_cb,
- GCallback cancel_cb, gpointer data)
-{
- const gchar *alias;
- const gchar *name;
- gchar *str;
- GList *items = NULL;
- gpointer *request_data;
- GSList *buddies;
- GSList *l;
- PurpleAccount *acct;
- PurpleRequestCommonParameters *cpar;
- PurpleRequestField *field;
- PurpleRequestFieldList *list;
- PurpleRequestGroup *group;
- PurpleRequestPage *page;
-
- request_data = g_new0(gpointer, 3);
- request_data[0] = ok_cb;
- request_data[1] = cancel_cb;
- request_data[2] = data;
-
- acct = purple_connection_get_account(gc);
- buddies = purple_blist_find_buddies(acct, NULL);
- buddies = g_slist_sort(buddies, fb_buddy_cmp);
-
- page = purple_request_page_new();
- group = purple_request_group_new(NULL);
- purple_request_page_add_group(page, group);
-
- field = purple_request_field_list_new("buddy", NULL);
- list = PURPLE_REQUEST_FIELD_LIST(field);
- purple_request_field_list_set_multi_select(list, multi);
- purple_request_field_set_required(field, TRUE);
- purple_request_group_add_field(group, field);
-
- for (l = buddies; l != NULL; l = l->next) {
- name = purple_buddy_get_name(l->data);
- alias = purple_buddy_get_alias(l->data);
- str = g_strdup_printf("%s (%s)", alias, name);
- purple_request_field_list_add_icon(list, str, NULL, l->data);
- g_free(str);
- }
-
- for (l = select; l != NULL; l = l->next) {
- name = purple_buddy_get_name(l->data);
- alias = purple_buddy_get_alias(l->data);
- str = g_strdup_printf("%s (%s)", alias, name);
- items = g_list_append(items, str);
- }
-
- purple_request_field_list_set_selected(list, items);
- g_slist_free(buddies);
- g_list_free_full(items, g_free);
-
- cpar = purple_request_cpar_from_connection(gc);
- return purple_request_fields(gc, title, primary, secondary, page,
- _("Ok"),
- G_CALLBACK(fb_util_request_buddy_ok),
- _("Cancel"),
- G_CALLBACK(fb_util_request_buddy_cancel),
- cpar, request_data);
-}
-
-void
-fb_util_serv_got_im(PurpleConnection *gc, const gchar *who, const gchar *text,
- PurpleMessageFlags flags, guint64 timestamp)
-{
- GDateTime *dt = NULL;
- const gchar *name, *me;
- PurpleAccount *acct;
- PurpleContactInfo *info = NULL;
- PurpleConversation *conv;
- PurpleConversationManager *manager;
- PurpleMessage *msg;
-
- if (!(flags & PURPLE_MESSAGE_SEND)) {
- purple_serv_got_im(gc, who, text, flags, timestamp);
- return;
- }
-
- acct = purple_connection_get_account(gc);
- info = PURPLE_CONTACT_INFO(acct);
- manager = purple_conversation_manager_get_default();
-
- conv = purple_conversation_manager_find_im(manager, acct, who);
-
- if (conv == NULL) {
- conv = purple_im_conversation_new(acct, who);
- }
-
- me = purple_contact_info_get_name_for_display(info);
- name = purple_contact_info_get_username(info);
- msg = purple_message_new_outgoing(acct, me, name, text, flags);
-
- dt = g_date_time_new_from_unix_local((gint64)timestamp);
- purple_message_set_timestamp(msg, dt);
- g_date_time_unref(dt);
-
- purple_conversation_write_message(conv, msg);
-
- g_object_unref(G_OBJECT(msg));
-}
-
-void
-fb_util_serv_got_chat_in(PurpleConnection *gc, gint id, const gchar *who,
- const gchar *text, PurpleMessageFlags flags,
- guint64 timestamp)
-{
- GDateTime *dt = NULL;
- const gchar *name;
- PurpleAccount *acct;
- PurpleContactInfo *info = NULL;
- PurpleConversation *conv;
- PurpleConversationManager *manager;
- PurpleMessage *msg;
- const gchar *me;
-
- if (!(flags & PURPLE_MESSAGE_SEND)) {
- purple_serv_got_chat_in(gc, id, who, flags, text, timestamp);
- return;
- }
-
- acct = purple_connection_get_account(gc);
- info = PURPLE_CONTACT_INFO(acct);
- manager = purple_conversation_manager_get_default();
-
- conv = purple_conversation_manager_find_chat_by_id(manager, acct, id);
-
- me = purple_contact_info_get_name_for_display(info);
- name = purple_contact_info_get_username(info);
-
- msg = purple_message_new_outgoing(acct, me, name, text, flags);
-
- dt = g_date_time_new_from_unix_local((gint64)timestamp);
- purple_message_set_timestamp(msg, dt);
- g_date_time_unref(dt);
-
- purple_conversation_write_message(conv, msg);
-
- g_object_unref(G_OBJECT(msg));
-}
-
-gboolean
-fb_util_strtest(const gchar *str, GAsciiType type)
-{
- gsize i;
- gsize size;
- guchar c;
-
- g_return_val_if_fail(str != NULL, FALSE);
- size = strlen(str);
-
- for (i = 0; i < size; i++) {
- c = (guchar) str[i];
-
- if ((g_ascii_table[c] & type) == 0) {
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-gboolean
-fb_util_zlib_test(const GByteArray *bytes)
-{
- guint8 b0;
- guint8 b1;
-
- g_return_val_if_fail(bytes != NULL, FALSE);
-
- if (bytes->len < 2) {
- return FALSE;
- }
-
- b0 = *(bytes->data + 0);
- b1 = *(bytes->data + 1);
-
- return ((((b0 << 8) | b1) % 31) == 0) && /* Check the header */
- ((b0 & 0x0F) == 8 /* Z_DEFLATED */); /* Check the method */
-}
-
-static GByteArray *
-fb_util_zlib_conv(GConverter *conv, const GByteArray *bytes, GError **error)
-{
- GByteArray *ret;
- GConverterResult res;
- gsize cize = 0;
- gsize rize;
- gsize wize;
- guint8 data[1024];
-
- ret = g_byte_array_new();
-
- while (TRUE) {
- rize = 0;
- wize = 0;
-
- res = g_converter_convert(conv,
- bytes->data + cize,
- bytes->len - cize,
- data, sizeof data,
- G_CONVERTER_INPUT_AT_END,
- &rize, &wize, error);
-
- switch (res) {
- case G_CONVERTER_CONVERTED:
- g_byte_array_append(ret, data, wize);
- cize += rize;
- break;
-
- case G_CONVERTER_ERROR:
- g_byte_array_free(ret, TRUE);
- return NULL;
-
- case G_CONVERTER_FINISHED:
- g_byte_array_append(ret, data, wize);
- return ret;
-
- default:
- break;
- }
- }
-}
-
-GByteArray *
-fb_util_zlib_deflate(const GByteArray *bytes, GError **error)
-{
- GByteArray *ret;
- GZlibCompressor *conv;
-
- conv = g_zlib_compressor_new(G_ZLIB_COMPRESSOR_FORMAT_ZLIB, -1);
- ret = fb_util_zlib_conv(G_CONVERTER(conv), bytes, error);
- g_object_unref(conv);
- return ret;
-}
-
-GByteArray *
-fb_util_zlib_inflate(const GByteArray *bytes, GError **error)
-{
- GByteArray *ret;
- GZlibDecompressor *conv;
-
- conv = g_zlib_decompressor_new(G_ZLIB_COMPRESSOR_FORMAT_ZLIB);
- ret = fb_util_zlib_conv(G_CONVERTER(conv), bytes, error);
- g_object_unref(conv);
- return ret;
-}
diff --git a/libpurple/protocols/facebook/util.h b/libpurple/protocols/facebook/util.h
deleted file mode 100644
index 99a75f960f..0000000000
--- a/libpurple/protocols/facebook/util.h
+++ /dev/null
@@ -1,335 +0,0 @@
-/* purple
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
- */
-
-#ifndef PURPLE_FACEBOOK_UTIL_H
-#define PURPLE_FACEBOOK_UTIL_H
-
-#include <glib.h>
-
-#include <purple.h>
-
-/**
- * FB_UTIL_DEBUG_INFO:
- *
- * Shortcut #PurpleDebugLevel for unsafe and verbose info messages.
- */
-#define FB_UTIL_DEBUG_INFO ( \
- PURPLE_DEBUG_INFO | \
- FB_UTIL_DEBUG_FLAG_UNSAFE | \
- FB_UTIL_DEBUG_FLAG_VERBOSE \
- )
-
-/**
- * FB_UTIL_ERROR:
- *
- * The #GQuark of the domain of utility errors.
- */
-#define FB_UTIL_ERROR fb_util_error_quark()
-
-/**
- * FbUtilRequestBuddyFunc:
- * @buddies: The list of #PurpleBuddy's.
- * @data: The user-defined data.
- *
- * The callback for requested buddies.
- */
-typedef void (*FbUtilRequestBuddyFunc) (GSList *buddies, gpointer data);
-
-/**
- * FbUtilDebugFlags:
- * @FB_UTIL_DEBUG_FLAG_UNSAFE: The message is unsafe.
- * @FB_UTIL_DEBUG_FLAG_VERBOSE: The message is verbose.
- * @FB_UTIL_DEBUG_FLAG_ALL: All of the flags.
- *
- * The debugging message flags. These flags are inserted on top of
- * a #PurpleDebugLevel.
- */
-typedef enum
-{
- FB_UTIL_DEBUG_FLAG_UNSAFE = 1 << 25,
- FB_UTIL_DEBUG_FLAG_VERBOSE = 1 << 26,
- FB_UTIL_DEBUG_FLAG_ALL = 3 << 25
-} FbUtilDebugFlags;
-
-/**
- * FbUtilError:
- * @FB_UTIL_ERROR_GENERAL: General failure.
- *
- * The error codes for the #FB_UTIL_ERROR domain.
- */
-typedef enum
-{
- FB_UTIL_ERROR_GENERAL
-} FbUtilError;
-
-/**
- * fb_util_error_quark:
- *
- * Gets the #GQuark of the domain of utility errors.
- *
- * Returns: The #GQuark of the domain.
- */
-GQuark
-fb_util_error_quark(void);
-
-/**
- * fb_util_account_find_buddy:
- * @acct: The #PurpleAccount.
- * @chat: The #PurpleChatConversation.
- * @name: The name of the buddy.
- * @error: The return location for the #GError or #NULL.
- *
- * Finds a buddy by their name or alias.
- *
- * Returns: (transfer none): The #PurpleBuddy if found, otherwise #NULL.
- */
-PurpleBuddy *
-fb_util_account_find_buddy(PurpleAccount *acct, PurpleChatConversation *chat,
- const gchar *name, GError **error);
-
-/**
- * fb_util_debug:
- * @level: The #PurpleDebugLevel.
- * @format: The format string literal.
- * @...: The arguments for @format.
- *
- * Logs a debugging message. If the messages is unsafe or verbose,
- * apply the appropriate #FbUtilDebugFlags.
- */
-void
-fb_util_debug(PurpleDebugLevel level, const gchar *format, ...)
- G_GNUC_PRINTF(2, 3);
-
-/**
- * fb_util_vdebug:
- * @level: The #PurpleDebugLevel.
- * @format: The format string literal.
- * @ap: The #va_list.
- *
- * Logs a debugging message. If the messages is unsafe or verbose,
- * apply the appropriate #FbUtilDebugFlags.
- */
-void
-fb_util_vdebug(PurpleDebugLevel level, const gchar *format, va_list ap);
-
-/**
- * fb_util_debug_misc:
- * @format: The format string literal.
- * @...: The arguments for @format.
- *
- * Logs a debugging message with the level of #PURPLE_DEBUG_MISC.
- */
-void
-fb_util_debug_misc(const gchar *format, ...)
- G_GNUC_PRINTF(1, 2);
-
-/**
- * fb_util_debug_info:
- * @format: The format string literal.
- * @...: The arguments for @format.
- *
- * Logs a debugging message with the level of #PURPLE_DEBUG_INFO.
- */
-void
-fb_util_debug_info(const gchar *format, ...)
- G_GNUC_PRINTF(1, 2);
-
-/**
- * fb_util_debug_warning:
- * @format: The format string literal.
- * @...: The arguments for @format.
- *
- * Logs a debugging message with the level of #PURPLE_DEBUG_WARNING.
- */
-void
-fb_util_debug_warning(const gchar *format, ...)
- G_GNUC_PRINTF(1, 2);
-
-/**
- * fb_util_debug_error:
- * @format: The format string literal.
- * @...: The arguments for @format.
- *
- * Logs a debugging message with the level of #PURPLE_DEBUG_ERROR.
- */
-void
-fb_util_debug_error(const gchar *format, ...)
- G_GNUC_PRINTF(1, 2);
-
-/**
- * fb_util_debug_fatal:
- * @format: The format string literal.
- * @...: The arguments for @format.
- *
- * Logs a debugging message with the level of #PURPLE_DEBUG_FATAL.
- */
-void
-fb_util_debug_fatal(const gchar *format, ...)
- G_GNUC_PRINTF(1, 2);
-
-/**
- * fb_util_debug_hexdump:
- * @level: The #PurpleDebugLevel.
- * @bytes: The #GByteArray.
- * @format: The format string literal.
- * @...: The arguments for @format.
- *
- * Logs a hexdump of a #GByteArray. If the messages is unsafe or
- * verbose, apply the appropriate #FbUtilDebugFlags.
- */
-void
-fb_util_debug_hexdump(PurpleDebugLevel level, const GByteArray *bytes,
- const gchar *format, ...)
- G_GNUC_PRINTF(3, 4);
-
-/**
- * fb_util_get_locale:
- *
- * Gets the locale string (ex: en_US) from the system. The returned
- * string should be freed with #g_free() when no longer needed.
- *
- * Returns: The locale string.
- */
-gchar *
-fb_util_get_locale(void);
-
-/**
- * fb_util_rand_alnum:
- * @len: The length of the string.
- *
- * Gets a random alphanumeric (A-Za-z0-9) string. This function should
- * *not* be relied on for cryptographic operations. The returned string
- * should be freed with #g_free() when no longer needed.
- *
- * Returns: The alphanumeric string.
- */
-gchar *
-fb_util_rand_alnum(guint len);
-
-/**
- * fb_util_request_buddy:
- * @gc: The #PurpleConnection.
- * @title: The title of the message or #NULL.
- * @primary: The main point of the message or #NULL.
- * @secondary: The secondary information or #NULL.
- * @select: (element-type PurpleBuddy): A #GSList of selected buddies or #NULL.
- * @multi: #TRUE to for multiple buddy selections, otherwise #FALSE.
- * @ok_cb: (scope async): The callback for the `OK` button or #NULL.
- * @cancel_cb: (scope async): The callback for the `Cancel` button or #NULL.
- * @data: The user-defined data.
- *
- * Displays a buddy list selection form.
- *
- * Returns: The UI-specific handle.
- */
-gpointer
-fb_util_request_buddy(PurpleConnection *gc, const gchar *title,
- const gchar *primary, const gchar *secondary,
- GSList *select, gboolean multi, GCallback ok_cb,
- GCallback cancel_cb, gpointer data);
-
-/**
- * fb_util_serv_got_im:
- * @gc: The #PurpleConnection.
- * @who: The message sender or receiver.
- * @text: The message text.
- * @flags: The #PurpleMessageFlags.
- * @timestamp: The message timestamp.
- *
- * Handles an incoming IM message. This function is special in that it
- * handles self messages. This function determines the direction of the
- * message from the #PurpleMessageFlags.
- */
-void
-fb_util_serv_got_im(PurpleConnection *gc, const gchar *who, const gchar *text,
- PurpleMessageFlags flags, guint64 timestamp);
-
-/**
- * fb_util_serv_got_chat_in:
- * @gc: The #PurpleConnection.
- * @id: The id of the chat.
- * @who: The message sender or receiver.
- * @text: The message text.
- * @flags: The #PurpleMessageFlags.
- * @timestamp: The message timestamp.
- *
- * Handles an incoming chat message. This function is special in that
- * it handles self messages. This function determines the direction of
- * the message from the #PurpleMessageFlags.
- */
-void
-fb_util_serv_got_chat_in(PurpleConnection *gc, gint id, const gchar *who,
- const gchar *text, PurpleMessageFlags flags,
- guint64 timestamp);
-
-/**
- * fb_util_strtest:
- * @str: The string.
- * @type: The #GAsciiType.
- *
- * Tests if the string only contains characters allowed by the
- * #GAsciiType. More than one type can be specified by ORing the types
- * together.
- *
- * Returns: #TRUE if the string only contains characters allowed by the
- * #GAsciiType, otherwise #FALSE.
- */
-gboolean
-fb_util_strtest(const gchar *str, GAsciiType type);
-
-/**
- * fb_util_zlib_test:
- * @bytes: The #GByteArray.
- *
- * Tests if the #GByteArray is zlib compressed.
- *
- * Returns: #TRUE if the #GByteArray is compressed, otherwise #FALSE.
- */
-gboolean
-fb_util_zlib_test(const GByteArray *bytes);
-
-/**
- * fb_util_zlib_deflate:
- * @bytes: The #GByteArray.
- * @error: The return location for the #GError or #NULL.
- *
- * Deflates a #GByteArray with zlib. The returned #GByteArray should be
- * freed with #g_byte_array_free() when no longer needed.
- *
- * Returns: (transfer full): The deflated #GByteArray or #NULL on error.
- */
-GByteArray *
-fb_util_zlib_deflate(const GByteArray *bytes, GError **error);
-
-/**
- * fb_util_zlib_inflate:
- * @bytes: The #GByteArray.
- * @error: The return location for the #GError or #NULL.
- *
- * Inflates a #GByteArray with zlib. The returned #GByteArray should be
- * freed with #g_byte_array_free() when no longer needed.
- *
- * Returns: (transfer full): The inflated #GByteArray or #NULL on error.
- */
-GByteArray *
-fb_util_zlib_inflate(const GByteArray *bytes, GError **error);
-
-#endif /* PURPLE_FACEBOOK_UTIL_H */
diff --git a/libpurple/protocols/meson.build b/libpurple/protocols/meson.build
index 256aaf4868..b6d7530c76 100644
--- a/libpurple/protocols/meson.build
+++ b/libpurple/protocols/meson.build
@@ -1,6 +1,5 @@
subdir('bonjour')
subdir('demo')
-subdir('facebook')
subdir('gg')
subdir('ircv3')
subdir('jabber')
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 37a8f3610f..6e48a9eec0 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -79,14 +79,6 @@ libpurple/protocols.c
libpurple/protocols/demo/purpledemocontacts.c
libpurple/protocols/demo/purpledemoplugin.c
libpurple/protocols/demo/purpledemoprotocol.c
-libpurple/protocols/facebook/api.c
-libpurple/protocols/facebook/data.c
-libpurple/protocols/facebook/facebook.c
-libpurple/protocols/facebook/http.c
-libpurple/protocols/facebook/json.c
-libpurple/protocols/facebook/mqtt.c
-libpurple/protocols/facebook/thrift.c
-libpurple/protocols/facebook/util.c
libpurple/protocols/gg/avatar.c
libpurple/protocols/gg/blist.c
libpurple/protocols/gg/chat.c