purple-facebook icon indicating copy to clipboard operation
purple-facebook copied to clipboard

Updating to the latest hg

Open 1ay1 opened this issue 3 years ago • 2 comments

1ay1 avatar Jun 13 '21 11:06 1ay1

``From 63f48e9d479ad7fd0471174ab84f4b694b8f63bd Mon Sep 17 00:00:00 2001 From: Ayush [email protected] Date: Sun, 13 Jun 2021 16:55:21 +0530 Subject: [PATCH] Updating to the latest hg


.gitignore | 1 + pidgin/libpurple/glibcompat.h | 27 ++ pidgin/libpurple/http.c | 305 +++++---------- .../libpurple/protocols/facebook/Makefile.am | 30 +- .../protocols/facebook/Makefile.mingw | 20 +- pidgin/libpurple/protocols/facebook/api.c | 80 ++-- pidgin/libpurple/protocols/facebook/api.h | 4 +- pidgin/libpurple/protocols/facebook/data.c | 4 +- .../libpurple/protocols/facebook/facebook.c | 250 ++++++------- .../libpurple/protocols/facebook/facebook.h | 50 --- pidgin/libpurple/protocols/facebook/http.c | 2 +- pidgin/libpurple/protocols/facebook/json.c | 3 +- pidgin/libpurple/protocols/facebook/mqtt.c | 346 ++++++++---------- pidgin/libpurple/protocols/facebook/mqtt.h | 17 + pidgin/libpurple/protocols/facebook/thrift.c | 3 +- 15 files changed, 515 insertions(+), 627 deletions(-)

diff --git a/.gitignore b/.gitignore index a632a291..db0c607c 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ Makefile Makefile.in pidgin win32-install-dir +.idea \ No newline at end of file diff --git a/pidgin/libpurple/glibcompat.h b/pidgin/libpurple/glibcompat.h index ccc303d4..03826511 100644 --- a/pidgin/libpurple/glibcompat.h +++ b/pidgin/libpurple/glibcompat.h @@ -71,6 +71,30 @@ purple_g_stat(const gchar filename, GStatBufW32 buf) /****************************************************************************

  • g_assert_* macros *****************************************************************************/

+#if !GLIB_CHECK_VERSION(2, 32, 0) +static inline GByteArray * g_byte_array_new_take(guint8 *data, gsize len) +{

  • GByteArray *array;
  • array = g_byte_array_new();
  • g_byte_array_append(array, data, len);
  • g_free(data);
  • return array; +}

+static inline void g_queue_free_full(GQueue *queue, GDestroyNotify free_func) +{

  • g_queue_foreach(queue, (GFunc)free_func, NULL);
  • g_queue_free(queue); +} +#endif

+#if !GLIB_CHECK_VERSION(2, 30, 0) +#define G_VALUE_INIT {0, {{0}}} +#endif + #if !GLIB_CHECK_VERSION(2, 38, 0) #define g_assert_true(expr) G_STMT_START {
if G_LIKELY (expr) ; else
@@ -86,6 +110,9 @@ purple_g_stat(const gchar *filename, GStatBufW32 *buf) g_assertion_message (G_LOG_DOMAIN, FILE, LINE, G_STRFUNC,
"'" #expr "' should be NULL");
} G_STMT_END +#define G_ADD_PRIVATE(TypeName) G_STMT_START { } G_STMT_END +#else +#define g_type_class_add_private(k,s) G_STMT_START { } G_STMT_END #endif

#if !GLIB_CHECK_VERSION(2, 40, 0) diff --git a/pidgin/libpurple/http.c b/pidgin/libpurple/http.c index fd882947..75e390ab 100644 --- a/pidgin/libpurple/http.c +++ b/pidgin/libpurple/http.c @@ -27,7 +27,12 @@

#include "debug.h" #include "proxy.h" -#include "purple-gio.h" +#include "purple-socket.h" + +#include <zlib.h> +#ifndef z_const +#define z_const +#endif

#define PURPLE_HTTP_URL_CREDENTIALS_CHARS "a-z0-9.,~_/*!&%?=+\^-" #define PURPLE_HTTP_MAX_RECV_BUFFER_LEN 10240 @@ -51,15 +56,9 @@ typedef struct _PurpleHttpKeepaliveRequest PurpleHttpKeepaliveRequest;

typedef struct _PurpleHttpGzStream PurpleHttpGzStream;

-typedef void (*PurpleHttpSocketConnectCb)(PurpleHttpSocket *hs,

  •   const gchar *error, gpointer _hc);
    

struct _PurpleHttpSocket {

  • GSocketConnection *conn;
  • GCancellable *cancellable;
  • guint input_source;
  • guint output_source;
  • PurpleSocket *ps;

    gboolean is_busy; guint use_count; @@ -175,7 +174,7 @@ struct _PurpleHttpCookieJar struct _PurpleHttpKeepaliveRequest { PurpleConnection *gc;

  • PurpleHttpSocketConnectCb cb;
  • PurpleSocketConnectCb cb; gpointer user_data;

    PurpleHttpKeepaliveHost *host; @@ -218,7 +217,7 @@ struct _PurpleHttpConnectionSet struct _PurpleHttpGzStream { gboolean failed;

  • GZlibDecompressor *decompressor;
  • z_stream zs; gsize max_output; gsize decompressed; GString *pending; @@ -266,7 +265,7 @@ gchar * purple_http_cookie_jar_dump(PurpleHttpCookieJar *cjar); static PurpleHttpKeepaliveRequest * purple_http_keepalive_pool_request(PurpleHttpKeepalivePool *pool, PurpleConnection *gc, const gchar *host, int port, gboolean is_ssl,
  • PurpleHttpSocketConnectCb cb, gpointer user_data);
  • PurpleSocketConnectCb cb, gpointer user_data); static void purple_http_keepalive_pool_request_cancel(PurpleHttpKeepaliveRequest *req); static void @@ -366,14 +365,19 @@ static PurpleHttpGzStream * purple_http_gz_new(gsize max_output, gboolean is_deflate) { PurpleHttpGzStream *gzs = g_new0(PurpleHttpGzStream, 1);
  • GZlibCompressorFormat format;
  • int windowBits;

    if (is_deflate)

  •   format = G_ZLIB_COMPRESSOR_FORMAT_RAW;
    
  •   windowBits = -MAX_WBITS;
    
    else /* is gzip */
  •   format = G_ZLIB_COMPRESSOR_FORMAT_GZIP;
    
  •   windowBits = MAX_WBITS + 32;
    
  • if (inflateInit2(&gzs->zs, windowBits) != Z_OK) {
  •   purple_debug_error("http", "Cannot initialize zlib stream\n");
    
  •   g_free(gzs);
    
  •   return NULL;
    
  • }
  • gzs->decompressor = g_zlib_decompressor_new(format); gzs->max_output = max_output;

    return gzs; @@ -385,6 +389,7 @@ purple_http_gz_put(PurpleHttpGzStream *gzs, const gchar *buf, gsize len) const gchar *compressed_buff; gsize compressed_len; GString *ret;

  • z_stream *zs;

    g_return_val_if_fail(gzs != NULL, NULL); g_return_val_if_fail(buf != NULL, NULL); @@ -392,6 +397,8 @@ purple_http_gz_put(PurpleHttpGzStream *gzs, const gchar *buf, gsize len) if (gzs->failed) return NULL;

  • zs = &gzs->zs;

  • if (gzs->pending) { g_string_append_len(gzs->pending, buf, len); compressed_buff = gzs->pending->str; @@ -401,26 +408,22 @@ purple_http_gz_put(PurpleHttpGzStream *gzs, const gchar *buf, gsize len) compressed_len = len; }

  • zs->next_in = (z_const Bytef*)compressed_buff;

  • zs->avail_in = compressed_len;

  • ret = g_string_new(NULL);

  • while (compressed_len > 0) {
  •   GConverterResult gzres;
    
  • while (zs->avail_in > 0) {
  •   int gzres;
      gchar decompressed_buff[PURPLE_HTTP_GZ_BUFF_LEN];
    
  •   gsize decompressed_len = 0;
    
  •   gsize bytes_read = 0;
    
  •   GError *error = NULL;
    
  •   gzres = g_converter_convert(G_CONVERTER(gzs->decompressor),
    
  •   	       compressed_buff, compressed_len,
    
  •          	       decompressed_buff, sizeof(decompressed_buff),
    
  •   	       G_CONVERTER_NO_FLAGS,
    
  •   	       &bytes_read,
    
  •   	       &decompressed_len,
    
  •   	       &error);
    
  •   compressed_buff += bytes_read;
    
  •   compressed_len -= bytes_read;
    
  •   if (gzres == G_CONVERTER_CONVERTED || G_CONVERTER_FINISHED) {
    
  •   gsize decompressed_len;
    
  •   zs->next_out = (Bytef*)decompressed_buff;
    
  •   zs->avail_out = sizeof(decompressed_buff);
    
  •   decompressed_len = zs->avail_out = sizeof(decompressed_buff);
    
  •   gzres = inflate(zs, Z_FULL_FLUSH);
    
  •   decompressed_len -= zs->avail_out;
    
  •   if (gzres == Z_OK || gzres == Z_STREAM_END) {
      	if (decompressed_len == 0)
      		break;
      	if (gzs->decompressed + decompressed_len >=
    

@@ -430,18 +433,17 @@ purple_http_gz_put(PurpleHttpGzStream *gzs, const gchar *buf, gsize len) " decompressed data is reached\n"); decompressed_len = gzs->max_output - gzs->decompressed;

  •   		gzres = G_CONVERTER_FINISHED;
    
  •   		gzres = Z_STREAM_END;
      	}
      	gzs->decompressed += decompressed_len;
      	g_string_append_len(ret, decompressed_buff,
      		decompressed_len);
    
  •   	if (gzres == G_CONVERTER_FINISHED)
    
  •   	if (gzres == Z_STREAM_END)
      		break;
      } else {
      	purple_debug_error("http",
      		"Decompression failed (%d): %s\n", gzres,
    
  •   		error->message);
    
  •   	g_clear_error(&error);
    
  •   		zs->msg);
      	gzs->failed = TRUE;
      	return NULL;
      }
    

@@ -452,9 +454,9 @@ purple_http_gz_put(PurpleHttpGzStream *gzs, const gchar *buf, gsize len) gzs->pending = NULL; }

  • if (compressed_len > 0) {
  •   gzs->pending = g_string_new_len(compressed_buff,
    
  •   	compressed_len);
    
  • if (zs->avail_in > 0) {

  •   gzs->pending = g_string_new_len((gchar*)zs->next_in,
    
  •   	zs->avail_in);
    

    }

    return ret; @@ -465,7 +467,7 @@ purple_http_gz_free(PurpleHttpGzStream *gzs) { if (gzs == NULL) return;

  • g_object_unref(gzs->decompressor);
  • inflateEnd(&gzs->zs); if (gzs->pending) g_string_free(gzs->pending, TRUE); g_free(gzs); @@ -529,69 +531,23 @@ purple_http_socket_hash(const gchar *host, int port, gboolean is_ssl) return g_strdup_printf("%c:%s:%d", (is_ssl ? 'S' : 'R'), host, port); }

-static void -purple_http_socket_connect_new_cb(GObject *source, GAsyncResult *res,

  •   gpointer user_data)
    

-{

  • PurpleHttpSocket *hs = user_data;
  • GSocketConnection *conn;
  • PurpleHttpSocketConnectCb cb;
  • gpointer cb_data;
  • GError *error = NULL;
  • conn = g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(source),
  •   	res, &error);
    
  • cb = g_object_steal_data(source, "cb");
  • cb_data = g_object_steal_data(source, "cb_data");
  • if (conn == NULL) {
  •   if (!g_error_matches(error,
    
  •   		G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
    
  •   	cb(hs, error->message, cb_data);
    
  •   }
    
  •   g_clear_error(&error);
    
  •   return;
    
  • }
  • hs->conn = conn;
  • cb(hs, NULL, cb_data); -}

static PurpleHttpSocket * purple_http_socket_connect_new(PurpleConnection *gc, const gchar *host,

  •   int port, gboolean is_ssl,
    
  •   PurpleHttpSocketConnectCb cb, gpointer user_data)
    

-{

  • PurpleHttpSocket *hs;
  • GSocketClient *client;
  • GError *error = NULL;
  • client = purple_gio_socket_client_new(
  •   	purple_connection_get_account(gc), &error);
    
  • if (client == NULL) {
  •   purple_debug_error("http", "Error connecting to '%s:%d': %s",
    
  •   		host, port, error->message);
    
  •   g_clear_error(&error);
    
  • int port, gboolean is_ssl, PurpleSocketConnectCb cb, gpointer user_data) +{
  • PurpleHttpSocket *hs = g_new0(PurpleHttpSocket, 1);
  • hs->ps = purple_socket_new(gc);
  • purple_socket_set_data(hs->ps, "hs", hs);
  • purple_socket_set_tls(hs->ps, is_ssl);
  • purple_socket_set_host(hs->ps, host);
  • purple_socket_set_port(hs->ps, port);
  • if (!purple_socket_connect(hs->ps, cb, user_data)) {
  •   purple_socket_destroy(hs->ps);
    
  •   g_free(hs);
      return NULL;
    
    }
  • hs = g_new0(PurpleHttpSocket, 1);
  • hs->cancellable = g_cancellable_new();
  • g_socket_client_set_tls(client, is_ssl);
  • g_object_set_data(G_OBJECT(client), "cb", cb);
  • g_object_set_data(G_OBJECT(client), "cb_data", user_data);
  • g_socket_client_connect_to_host_async(client,
  •   	host, port, hs->cancellable,
    
  •   	purple_http_socket_connect_new_cb, hs);
    
  • g_object_unref(client);
  • if (purple_debug_is_verbose()) purple_debug_misc("http", "new socket created: %p\n", hs);

@@ -607,26 +563,7 @@ purple_http_socket_close_free(PurpleHttpSocket *hs) if (purple_debug_is_verbose()) purple_debug_misc("http", "destroying socket: %p\n", hs);

  • if (hs->input_source > 0) {
  •   g_source_remove(hs->input_source);
    
  •   hs->input_source = 0;
    
  • }
  • if (hs->output_source > 0) {
  •   g_source_remove(hs->output_source);
    
  •   hs->output_source = 0;
    
  • }
  • if (hs->cancellable != NULL) {
  •   g_cancellable_cancel(hs->cancellable);
    
  •   g_clear_object(&hs->cancellable);
    
  • }
  • if (hs->conn != NULL) {
  •   purple_gio_graceful_close(G_IO_STREAM(hs->conn), NULL, NULL);
    
  •   g_clear_object(&hs->conn);
    
  • }
  • purple_socket_destroy(hs->ps); g_free(hs); }

@@ -813,9 +750,10 @@ static void _purple_http_disconnect(PurpleHttpConnection *hc, gboolean is_graceful);

static void _purple_http_gen_headers(PurpleHttpConnection *hc); -static gboolean _purple_http_recv_loopbody(PurpleHttpConnection *hc); -static gboolean _purple_http_recv(GObject *source, gpointer _hc); -static gboolean _purple_http_send(GObject *source, gpointer _hc); +static gboolean _purple_http_recv_loopbody(PurpleHttpConnection *hc, gint fd); +static void _purple_http_recv(gpointer _hc, gint fd,

  • PurpleInputCondition cond); +static void _purple_http_send(gpointer _hc, gint fd, PurpleInputCondition cond);

/* closes current connection (if exists), estabilishes one and proceeds with

  • request */ @@ -1208,33 +1146,21 @@ static gboolean _purple_http_recv_body(PurpleHttpConnection *hc, return _purple_http_recv_body_data(hc, buf, len); }

-static gboolean _purple_http_recv_loopbody(PurpleHttpConnection *hc) +static gboolean _purple_http_recv_loopbody(PurpleHttpConnection *hc, gint fd) { int len; gchar buf[4096]; gboolean got_anything;

  • GError *error = NULL;
  • len = g_pollable_input_stream_read_nonblocking(
  •   		G_POLLABLE_INPUT_STREAM(
    
  •   		g_io_stream_get_input_stream(
    
  •   		G_IO_STREAM(hc->socket->conn))),
    
  •   		buf, sizeof(buf), hc->socket->cancellable,
    
  •   		&error);
    
  • len = purple_socket_read(hc->socket->ps, (guchar*)buf, sizeof(buf)); got_anything = (len > 0);
  • if (len < 0 && (g_error_matches(error,
  •   	G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK) ||
    
  •   	g_error_matches(error,
    
  •   	G_IO_ERROR, G_IO_ERROR_CANCELLED))) {
    
  •   g_clear_error(&error);
    
  • if (len < 0 && errno == EAGAIN) return FALSE;
  • }

    if (len < 0) { _purple_http_error(hc, _("Error reading from %s: %s"),

  •   	hc->url->host, error->message);
    
  •   g_clear_error(&error);
    
  •   	hc->url->host, g_strerror(errno));
      return FALSE;
    
    }

@@ -1413,13 +1339,11 @@ static gboolean _purple_http_recv_loopbody(PurpleHttpConnection *hc) return got_anything; }

-static gboolean _purple_http_recv(GObject *source, gpointer _hc) +static void _purple_http_recv(gpointer _hc, gint fd, PurpleInputCondition cond) { PurpleHttpConnection *hc = _hc;

  • while (_purple_http_recv_loopbody(hc));
  • return G_SOURCE_CONTINUE;
  • while (_purple_http_recv_loopbody(hc, fd)); }

static void _purple_http_send_got_data(PurpleHttpConnection *hc, @@ -1450,19 +1374,17 @@ static void _purple_http_send_got_data(PurpleHttpConnection *hc, hc->request->contents_length = estimated_length; }

-static gboolean _purple_http_send(GObject *source, gpointer _hc) +static void _purple_http_send(gpointer _hc, gint fd, PurpleInputCondition cond) { PurpleHttpConnection *hc = _hc; int written, write_len; const gchar *write_from; gboolean writing_headers;

  • GError *error = NULL;

  • GSource *gsource;

    /* Waiting for data. This could be written more efficiently, by removing

    • (and later, adding) hs->inpa. */ if (hc->contents_reader_requested)
  •   return G_SOURCE_CONTINUE;
    
  •   return;
    
    _purple_http_gen_headers(hc);

@@ -1475,7 +1397,7 @@ static gboolean _purple_http_send(GObject *source, gpointer _hc) hc->request_header_written; } else if (hc->request->contents_reader) { if (hc->contents_reader_requested)

  •   	return G_SOURCE_CONTINUE; /* waiting for data */
    
  •   	return; /* waiting for data */
      if (!hc->contents_reader_buffer)
      	hc->contents_reader_buffer = g_string_new("");
      if (hc->contents_reader_buffer->len == 0) {
    

@@ -1488,7 +1410,7 @@ static gboolean _purple_http_send(GObject *source, gpointer _hc) PURPLE_HTTP_MAX_READ_BUFFER_LEN, hc->request->contents_reader_data, _purple_http_send_got_data);

  •   	return G_SOURCE_CONTINUE;
    
  •   	return;
      }
      write_from = hc->contents_reader_buffer->str;
      write_len = hc->contents_reader_buffer->len;
    

@@ -1503,21 +1425,12 @@ static gboolean _purple_http_send(GObject *source, gpointer _hc) purple_debug_warning("http", "Nothing to write\n"); written = 0; } else {

  •   written = g_pollable_output_stream_write_nonblocking(
    
  •   		G_POLLABLE_OUTPUT_STREAM(
    
  •   		g_io_stream_get_output_stream(
    
  •   		G_IO_STREAM(hc->socket->conn))),
    
  •   		write_from, write_len, hc->socket->cancellable,
    
  •   		&error);
    
  •   written = purple_socket_write(hc->socket->ps,
    
  •   	(const guchar*)write_from, write_len);
    
    }
  • if (written < 0 && (g_error_matches(error,
  •   	G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK) ||
    
  •   	g_error_matches(error,
    
  •   	G_IO_ERROR, G_IO_ERROR_CANCELLED))) {
    
  •   g_clear_error(&error);
    
  •   return G_SOURCE_CONTINUE;
    
  • }
  • if (written < 0 && errno == EAGAIN)
  •   return;
    
    if (written < 0) { if (hc->request_header_written == 0 && @@ -1526,22 +1439,21 @@ static gboolean _purple_http_send(GObject *source, gpointer _hc) purple_debug_info("http", "Keep-alive connection " "expired (when writing), retrying...\n"); purple_http_conn_retry(hc);
  •   } else {
    
  •   	_purple_http_error(hc, _("Error writing to %s: %s"),
    
  •   		hc->url->host, error->message);
    
  •   	return;
      }
    
  •   g_clear_error(&error);
    
  •   return G_SOURCE_CONTINUE;
    
  •   _purple_http_error(hc, _("Error writing to %s: %s"),
    
  •   	hc->url->host, g_strerror(errno));
    
  •   return;
    

    }

    if (writing_headers) { hc->request_header_written += written; purple_http_conn_notify_progress_watcher(hc); if (hc->request_header_written < hc->request_header->len)

  •   	return G_SOURCE_CONTINUE;
    
  •   	return;
      if (hc->request->contents_length > 0)
    
  •   	return G_SOURCE_CONTINUE;
    
  •   	return;
    
    } else { hc->request_contents_written += written; purple_http_conn_notify_progress_watcher(hc); @@ -1551,24 +1463,14 @@ static gboolean _purple_http_send(GObject *source, gpointer _hc) hc->request_contents_written < (guint)hc->request->contents_length) {
  •   	return G_SOURCE_CONTINUE;
    
  •   	return;
      }
    

    }

    /* request is completely written, let's read the response */ hc->is_reading = TRUE;

  • gsource = g_pollable_input_stream_create_source(
  •   	G_POLLABLE_INPUT_STREAM(
    
  •   	g_io_stream_get_input_stream(
    
  •   	G_IO_STREAM(hc->socket->conn))),
    
  •   	NULL);
    
  • g_source_set_callback(gsource,
  •   (GSourceFunc)_purple_http_recv, hc, NULL);
    
  • hc->socket->input_source = g_source_attach(gsource, NULL);
  • g_source_unref(gsource);
  • hc->socket->output_source = 0;
  • return G_SOURCE_REMOVE;
  • purple_socket_watch(hc->socket->ps, PURPLE_INPUT_READ,
  •   _purple_http_recv, hc);
    

}

static void _purple_http_disconnect(PurpleHttpConnection *hc, @@ -1593,10 +1495,13 @@ static void _purple_http_disconnect(PurpleHttpConnection *hc, }

static void -_purple_http_connected(PurpleHttpSocket *hs, const gchar *error, gpointer _hc) +_purple_http_connected(PurpleSocket *ps, const gchar *error, gpointer _hc) {

  • PurpleHttpSocket *hs = NULL; PurpleHttpConnection *hc = _hc;
  • GSource *source;
  • if (ps != NULL)
  •   hs = purple_socket_get_data(ps, "hs");
    
    hc->socket_request = NULL; hc->socket = hs; @@ -1607,14 +1512,7 @@ _purple_http_connected(PurpleHttpSocket *hs, const gchar *error, gpointer _hc) return; }
  • source = g_pollable_output_stream_create_source(
  •   	G_POLLABLE_OUTPUT_STREAM(
    
  •   	g_io_stream_get_output_stream(G_IO_STREAM(hs->conn))),
    
  •   	NULL);
    
  • g_source_set_callback(source,
  •   	(GSourceFunc)_purple_http_send, hc, NULL);
    
  • hc->socket->output_source = g_source_attach(source, NULL);
  • g_source_unref(source);
  • purple_socket_watch(ps, PURPLE_INPUT_WRITE, _purple_http_send, hc); }

static gboolean _purple_http_reconnect(PurpleHttpConnection *hc) @@ -2326,7 +2224,7 @@ purple_http_keepalive_pool_unref(PurpleHttpKeepalivePool *pool) static PurpleHttpKeepaliveRequest * purple_http_keepalive_pool_request(PurpleHttpKeepalivePool *pool, PurpleConnection *gc, const gchar *host, int port, gboolean is_ssl,

  • PurpleHttpSocketConnectCb cb, gpointer user_data)
  • PurpleSocketConnectCb cb, gpointer user_data) { PurpleHttpKeepaliveRequest *req; PurpleHttpKeepaliveHost *kahost; @@ -2369,15 +2267,19 @@ purple_http_keepalive_pool_request(PurpleHttpKeepalivePool *pool, }

static void -_purple_http_keepalive_socket_connected(PurpleHttpSocket *hs, +_purple_http_keepalive_socket_connected(PurpleSocket *ps, const gchar *error, gpointer _req) {

  • PurpleHttpSocket *hs = NULL; PurpleHttpKeepaliveRequest *req = _req;

  • if (ps != NULL)

  •   hs = purple_socket_get_data(ps, "hs");
    
  • if (hs != NULL) hs->use_count++;

  • req->cb(hs, error, req->user_data);
  • req->cb(ps, error, req->user_data); g_free(req); }

@@ -2433,7 +2335,7 @@ _purple_http_keepalive_host_process_queue_cb(gpointer _host)

	purple_http_keepalive_host_process_queue(host);
  •   req->cb(hs, NULL, req->user_data);
    
  •   req->cb(hs->ps, NULL, req->user_data);
      g_free(req);
    
      return FALSE;
    

@@ -2504,16 +2406,7 @@ purple_http_keepalive_pool_release(PurpleHttpSocket *hs, gboolean invalidate) if (purple_debug_is_verbose()) purple_debug_misc("http", "releasing a socket: %p\n", hs);

  • if (hs->input_source > 0) {
  •   g_source_remove(hs->input_source);
    
  •   hs->input_source = 0;
    
  • }
  • if (hs->output_source > 0) {
  •   g_source_remove(hs->output_source);
    
  •   hs->output_source = 0;
    
  • }
  • purple_socket_watch(hs->ps, 0, NULL, NULL); hs->is_busy = FALSE; host = hs->host;

diff --git a/pidgin/libpurple/protocols/facebook/Makefile.am b/pidgin/libpurple/protocols/facebook/Makefile.am index 268e8efc..87dd0825 100644 --- a/pidgin/libpurple/protocols/facebook/Makefile.am +++ b/pidgin/libpurple/protocols/facebook/Makefile.am @@ -1,9 +1,12 @@ EXTRA_DIST = \

  • Makefile.mingw
  • Makefile.mingw \
  • marshaller.list

pkgdir = @PURPLE_PLUGINDIR@

FACEBOOKSOURCES = \

  • marshal.c \
  • marshal.h
    api.c
    api.h
    data.c
    @@ -20,7 +23,23 @@ FACEBOOKSOURCES =
    thrift.c
    thrift.h
    util.c \
  • util.h
  • util.h \
  • ../../glibcompat.h \
  • ../../http.c \
  • ../../http.h \
  • ../../purple-socket.h \
  • ../../purple-socket.c

+CLEANFILES = \

  • marshal.c \
  • marshal.h

+marshal.c: $(srcdir)/marshaller.list marshal.h

  • $(AM_V_GEN)echo "#include "marshal.h"" > $@
  • $(AM_V_at)$(GLIB_GENMARSHAL) --prefix=fb_marshal --body $(srcdir)/marshaller.list >> $@

+marshal.h: $(srcdir)/marshaller.list

  • $(AM_V_GEN)$(GLIB_GENMARSHAL) --prefix=fb_marshal --header $(srcdir)/marshaller.list > $@

AM_CFLAGS = $(st)

@@ -43,10 +62,9 @@ libfacebook_la_LIBADD = @PURPLE_LIBS@ $(JSON_LIBS) endif

AM_CPPFLAGS = \

  • -I$(top_srcdir)/libpurple \
  • -I$(top_builddir)/libpurple \
  • -I$(top_srcdir)
    $(GLIB_CFLAGS)
    $(JSON_CFLAGS) \
  • $(GPLUGIN_CFLAGS) \
  • $(PURPLE_CFLAGS) \
  • $(ZLIB_CFLAGS) \
  • $(PLUGIN_CFLAGS)
    $(DEBUG_CFLAGS) diff --git a/pidgin/libpurple/protocols/facebook/Makefile.mingw b/pidgin/libpurple/protocols/facebook/Makefile.mingw index c2aaad84..181937ff 100644 --- a/pidgin/libpurple/protocols/facebook/Makefile.mingw +++ b/pidgin/libpurple/protocols/facebook/Makefile.mingw @@ -42,6 +42,7 @@ LIB_PATHS += -L$(GTK_TOP)/lib \

SOURCES, OBJECTS

C_SRC = \

  •   	marshal.c \
      	api.c \
      	data.c \
      	facebook.c \
    

@@ -49,7 +50,9 @@ C_SRC =
json.c
mqtt.c
thrift.c \

  •   	util.c
    
  •   	util.c \
    
  •   	../../http.c \
    
  •   	../../purple-socket.c
    

OBJECTS = $(C_SRC:%.c=%.o)

@@ -62,7 +65,6 @@ LIBS =
-lgobject-2.0
-lws2_32
-lintl \

  •   	-lgplugin \
      	-ljson-glib-1.0 \
      	-lz \
      	-lpurple
    

@@ -76,19 +78,27 @@ include $(PIDGIN_COMMON_RULES)

all: $(TARGET).dll

-install: all $(DLL_INSTALL_DIR) +install: all cp $(TARGET).dll $(DLL_INSTALL_DIR)

$(OBJECTS): $(PURPLE_CONFIG_H)

-$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS) +$(TARGET).dll: $(OBJECTS) $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll

+marshal.c: marshaller.list marshal.h

  • @echo "#include "marshal.h"" > $@
  • @$(GLIB_GENMARSHAL) --prefix=fb_marshal --body marshaller.list >> $@

+marshal.h: marshaller.list

  • @$(GLIB_GENMARSHAL) --prefix=fb_marshal --header marshaller.list > $@

CLEAN RULES

clean:

  • rm -f $(OBJECTS)
  • rm -f $(OBJECTS) marshal.c marshal.h rm -f $(TARGET).dll

include $(PIDGIN_COMMON_TARGETS) diff --git a/pidgin/libpurple/protocols/facebook/api.c b/pidgin/libpurple/protocols/facebook/api.c index 163a4884..445714bb 100644 --- a/pidgin/libpurple/protocols/facebook/api.c +++ b/pidgin/libpurple/protocols/facebook/api.c @@ -28,6 +28,7 @@ #include "api.h" #include "http.h" #include "json.h" +#include "marshal.h" #include "thrift.h" #include "util.h"

@@ -91,7 +92,7 @@ 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); +G_DEFINE_TYPE_WITH_CODE(FbApi, fb_api, G_TYPE_OBJECT, G_ADD_PRIVATE(FbApi));

static void fb_api_set_property(GObject *obj, guint prop, const GValue *val, @@ -291,7 +292,8 @@ fb_api_class_init(FbApiClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,

  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__VOID,
               G_TYPE_NONE,
               0);
    

@@ -306,7 +308,8 @@ fb_api_class_init(FbApiClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,

  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__VOID,
               G_TYPE_NONE,
               0);
    

@@ -322,7 +325,8 @@ fb_api_class_init(FbApiClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,

  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__POINTER,
               G_TYPE_NONE,
               1, G_TYPE_POINTER);
    

@@ -342,7 +346,8 @@ fb_api_class_init(FbApiClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,

  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__POINTER_BOOLEAN,
               G_TYPE_NONE,
               2, G_TYPE_POINTER, G_TYPE_BOOLEAN);
    

@@ -358,7 +363,8 @@ fb_api_class_init(FbApiClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,

  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__POINTER_POINTER,
               G_TYPE_NONE,
               2, G_TYPE_POINTER, G_TYPE_POINTER);
    

@@ -374,7 +380,8 @@ fb_api_class_init(FbApiClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,

  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__POINTER,
               G_TYPE_NONE,
               1, G_TYPE_POINTER);
    

@@ -389,7 +396,8 @@ fb_api_class_init(FbApiClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,

  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__POINTER,
               G_TYPE_NONE,
               1, G_TYPE_POINTER);
    

@@ -404,7 +412,8 @@ fb_api_class_init(FbApiClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,

  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__POINTER,
               G_TYPE_NONE,
               1, G_TYPE_POINTER);
    

@@ -419,7 +428,8 @@ fb_api_class_init(FbApiClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,

  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__POINTER,
               G_TYPE_NONE,
               1, G_TYPE_POINTER);
    

@@ -435,7 +445,8 @@ fb_api_class_init(FbApiClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,

  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__POINTER,
               G_TYPE_NONE,
               1, G_TYPE_POINTER);
    

@@ -452,7 +463,8 @@ fb_api_class_init(FbApiClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,

  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__INT64,
               G_TYPE_NONE,
               1, FB_TYPE_ID);
    

@@ -468,7 +480,8 @@ fb_api_class_init(FbApiClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,

  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__POINTER,
               G_TYPE_NONE,
               1, G_TYPE_POINTER);
    

@@ -484,7 +497,8 @@ fb_api_class_init(FbApiClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,

  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__POINTER,
               G_TYPE_NONE,
               1, G_TYPE_POINTER);
    

@@ -499,7 +513,8 @@ fb_api_class_init(FbApiClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,

  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__POINTER,
               G_TYPE_NONE,
               1, G_TYPE_POINTER);
    

} @@ -1486,6 +1501,23 @@ fb_api_cb_publish_ms_new_message(FbApi *api, JsonNode *root, GSList *msgs, GErro 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) { @@ -1516,10 +1548,14 @@ fb_api_cb_publish_ms(FbApi *api, GByteArray *pload)

/* Read identifier string (for Facebook employees) */
thft = fb_thrift_new(pload, 0);
  • fb_thrift_read_str(thft, NULL);
  • 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; @@ -1829,10 +1865,10 @@ fb_api_cb_publish_pt(FbThrift *thft, GSList **press, GError **error) pres->active = i32 != 0; *press = g_slist_prepend(*press, pres);

  •   fb_util_debug_info("Presence: %" FB_ID_FORMAT " (%d)",
    
  •                      i64, i32 != 0);
    
  •   fb_util_debug_info("Presence: %" FB_ID_FORMAT " (%d) id: %d",
    
  •                      i64, i32 != 0, id);
    
  •   while (id <= 5) {
    
  •   while (id <= 6) {
      	if (fb_thrift_read_isstop(thft)) {
      		break;
      	}
    

@@ -1879,7 +1915,9 @@ fb_api_cb_publish_pt(FbThrift *thft, GSList **press, GError **error) }

/* Read the field stop */
  • FB_API_TCHK(fb_thrift_read_stop(thft));
  • if (fb_thrift_read_isstop(thft)) {
  •   FB_API_TCHK(fb_thrift_read_stop(thft));
    
  • } }

static void @@ -2409,7 +2447,7 @@ fb_api_cb_contacts(PurpleHttpConnection *con, PurpleHttpResponse *res, priv->contacts_delta = g_strdup(is_delta ? cursor : delta_cursor); }

  •   if (users) {
    
  •   if (users || (complete && !is_delta)) {
      	g_signal_emit_by_name(api, "contacts", users, complete);
      }
    

diff --git a/pidgin/libpurple/protocols/facebook/api.h b/pidgin/libpurple/protocols/facebook/api.h index 111788ea..63c9a1b9 100644 --- a/pidgin/libpurple/protocols/facebook/api.h +++ b/pidgin/libpurple/protocols/facebook/api.h @@ -104,14 +104,14 @@

  • server started checking this. */

-#define FB_ORCA_AGENT "[FBAN/Orca-Android;FBAV/109.0.0.17.70;FBPN/com.facebook.orca;FBLC/en_US;FBBV/52182662]" +#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 +#define FB_API_AGENT "Facebook plugin / Purple / " PACKAGE_VERSION " " FB_ORCA_AGENT

/**

  • FB_API_MQTT_AGENT diff --git a/pidgin/libpurple/protocols/facebook/data.c b/pidgin/libpurple/protocols/facebook/data.c index fe32404f..81e32581 100644 --- a/pidgin/libpurple/protocols/facebook/data.c +++ b/pidgin/libpurple/protocols/facebook/data.c @@ -59,8 +59,8 @@ static const gchar *fb_props_strs[] = { "token" };

-G_DEFINE_TYPE(FbData, fb_data, G_TYPE_OBJECT); -G_DEFINE_TYPE(FbDataImage, fb_data_image, G_TYPE_OBJECT); +G_DEFINE_TYPE_WITH_CODE(FbData, fb_data, G_TYPE_OBJECT, G_ADD_PRIVATE(FbData)); +G_DEFINE_TYPE_WITH_CODE(FbDataImage, fb_data_image, G_TYPE_OBJECT, G_ADD_PRIVATE(FbDataImage));

static void fb_data_dispose(GObject *obj) diff --git a/pidgin/libpurple/protocols/facebook/facebook.c b/pidgin/libpurple/protocols/facebook/facebook.c index 9554adc7..7a6ed818 100644 --- a/pidgin/libpurple/protocols/facebook/facebook.c +++ b/pidgin/libpurple/protocols/facebook/facebook.c @@ -373,8 +373,8 @@ fb_cb_api_error(FbApi *api, GError *error, gpointer data)

gc = fb_data_get_connection(fata);
  • if (error->domain == G_IO_ERROR) {
  •   purple_connection_g_error(gc, error);
    
  • if (error->domain == FB_MQTT_SSL_ERROR) {
  •   purple_connection_ssl_error(gc, error->code);
      return;
    
    }

@@ -500,7 +500,7 @@ fb_cb_image(FbDataImage *img, GError *error) id = purple_image_store_add_weak(pimg);

g_free(msg->text);
  • msg->text = g_strdup_printf("<img src=""
  • msg->text = g_strdup_printf("<img id="" PURPLE_IMAGE_STORE_PROTOCOL "%u">", id); msg->flags |= FB_API_MESSAGE_FLAG_DONE; @@ -966,7 +966,7 @@ fb_blist_chat_init(PurpleBlistNode *node, gpointer data) GSList *select = NULL; PurpleConnection *gc;
  • if (!PURPLE_IS_BUDDY(node)) {
  • if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) { return; }

@@ -1160,7 +1160,7 @@ fb_client_blist_node_menu(PurpleBlistNode *node) PurpleConnection *gc; PurpleMenuAction *act;

  • if (!PURPLE_IS_BUDDY(node)) {
  • if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) { return NULL; }

@@ -1208,7 +1208,8 @@ fb_server_set_status(PurpleAccount *acct, PurpleStatus *status) }

static gint -fb_im_send(PurpleConnection *gc, PurpleMessage *msg) +fb_im_send(PurpleConnection *gc, const gchar *who, const gchar *tmsg,

  •       PurpleMessageFlags flags)
    

{ const gchar *name; const gchar *text; @@ -1217,6 +1218,8 @@ fb_im_send(PurpleConnection *gc, PurpleMessage *msg) FbId uid; gchar *sext;

  • PurpleMessage *msg = purple_message_new_outgoing(who, tmsg, flags);
  • fata = purple_connection_get_protocol_data(gc); api = fb_data_get_api(fata);

@@ -1355,7 +1358,8 @@ fb_chat_invite(PurpleConnection *gc, gint id, const gchar *msg, }

static gint -fb_chat_send(PurpleConnection *gc, gint id, PurpleMessage *msg) +fb_chat_send(PurpleConnection *gc, gint id, const gchar *tmsg,

  •         PurpleMessageFlags flags)
    

{ const gchar *name; const gchar *text; @@ -1366,6 +1370,8 @@ fb_chat_send(PurpleConnection *gc, gint id, PurpleMessage *msg) PurpleAccount *acct; PurpleChatConversation *chat;

  • PurpleMessage *msg = purple_message_new_outgoing(NULL, tmsg, flags);
  • acct = purple_connection_get_account(gc); fata = purple_connection_get_protocol_data(gc); api = fb_data_get_api(fata); @@ -1533,107 +1539,6 @@ fb_cmd_leave(PurpleConversation *conv, const gchar *cmd, gchar **args, return PURPLE_CMD_RET_OK; }

-static void -facebook_protocol_init(PurpleProtocol *protocol) -{

  • GList *opts = NULL;
  • PurpleAccountOption *opt;
  • protocol->id = FB_PROTOCOL_ID;
  • protocol->name = "Facebook";
  • protocol->options = OPT_PROTO_CHAT_TOPIC;
  • 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);
  • protocol->account_options = g_list_reverse(opts); -}

-static void -facebook_protocol_class_init(PurpleProtocolClass *klass) -{

  • klass->login = fb_login;
  • klass->close = fb_close;
  • klass->status_types = fb_status_types;
  • klass->list_icon = fb_list_icon; -}

-static void -facebook_protocol_client_iface_init(PurpleProtocolClientIface *iface) -{

  • iface->tooltip_text = fb_client_tooltip_text;
  • iface->blist_node_menu = fb_client_blist_node_menu;
  • iface->offline_message = fb_client_offline_message; -}

-static void -facebook_protocol_server_iface_init(PurpleProtocolServerIface *iface) -{

  • iface->set_status = fb_server_set_status; -}

-static void -facebook_protocol_im_iface_init(PurpleProtocolIMIface *iface) -{

  • iface->send = fb_im_send;
  • iface->send_typing = fb_im_send_typing; -}

-static void -facebook_protocol_chat_iface_init(PurpleProtocolChatIface *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(PurpleProtocolRoomlistIface *iface) -{

  • iface->get_list = fb_roomlist_get_list;
  • iface->cancel = fb_roomlist_cancel; -}

-PURPLE_DEFINE_TYPE_EXTENDED(

  • FacebookProtocol, facebook_protocol, PURPLE_TYPE_PROTOCOL, 0,
  • PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_CLIENT_IFACE,
  •                                 facebook_protocol_client_iface_init)
    
  • PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_SERVER_IFACE,
  •                                 facebook_protocol_server_iface_init)
    
  • PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_IM_IFACE,
  •                                 facebook_protocol_im_iface_init)
    
  • PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_CHAT_IFACE,
  •                                 facebook_protocol_chat_iface_init)
    
  • PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_ROOMLIST_IFACE,
  •                                 facebook_protocol_roomlist_iface_init)
    

-);

static void fb_cmds_register(void) { @@ -1646,13 +1551,13 @@ fb_cmds_register(void) g_return_if_fail(fb_cmds == NULL);

id = purple_cmd_register("kick", "s", PURPLE_CMD_P_PROTOCOL, cflags,
  •   		 fb_protocol->id, fb_cmd_kick,
    
  •   		 "prpl-facebook", 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,
    
  •   		 "prpl-facebook", fb_cmd_leave,
      		 _("leave: Leave the chat"),
      		 NULL);
    
    fb_cmds = g_slist_prepend(fb_cmds, GUINT_TO_POINTER(id)); @@ -1671,43 +1576,110 @@ fb_cmds_unregister(void) g_slist_free_full(fb_cmds, fb_cmds_unregister_free); }

-static PurplePluginInfo * -plugin_query(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 -plugin_load(PurplePlugin *plugin, GError **error) +plugin_load(PurplePlugin *plugin) {

  • facebook_protocol_register_type(plugin);
  • fb_protocol = purple_protocols_add(FACEBOOK_TYPE_PROTOCOL, error);
  • if (fb_protocol == NULL) {
  •   return FALSE;
    
  • }
  • fb_cmds_register();
  • _purple_socket_init();
  • purple_http_init(); return TRUE; }

static gboolean -plugin_unload(PurplePlugin *plugin, GError **error) +plugin_unload(PurplePlugin *plugin) { fb_cmds_unregister();

  • return purple_protocols_remove(fb_protocol, error);
  • purple_http_uninit();
  • _purple_socket_uninit();
  • return TRUE; }

-PURPLE_PLUGIN_INIT(facebook, plugin_query, plugin_load, plugin_unload); +G_MODULE_EXPORT gboolean +purple_init_plugin(PurplePlugin *plugin); + +G_MODULE_EXPORT gboolean +purple_init_plugin(PurplePlugin *plugin) +{

  • GList *opts = NULL;
  • PurpleAccountOption *opt;
  • static gboolean inited = FALSE;
  • static PurplePluginInfo info;
  • static PurplePluginProtocolInfo pinfo;
  • (void) fb_protocol;
  • plugin->info = &info;
  • if (G_LIKELY(inited)) {
  •   return purple_plugin_register(plugin);
    
  • }
  • memset(&info, 0, sizeof info);
  • memset(&pinfo, 0, sizeof pinfo);
  • info.magic = PURPLE_PLUGIN_MAGIC;
  • info.major_version = PURPLE_MAJOR_VERSION;
  • info.minor_version = PURPLE_MINOR_VERSION;
  • info.type = PURPLE_PLUGIN_PROTOCOL;
  • info.priority = PURPLE_PRIORITY_DEFAULT;
  • info.id = FB_PROTOCOL_ID;
  • info.name = "Facebook";
  • info.version = PACKAGE_VERSION;
  • info.summary = N_("Facebook Protocol Plugin");
  • info.description = N_("Facebook Protocol Plugin");
  • info.homepage = PACKAGE_URL;
  • info.load = plugin_load;
  • info.unload = plugin_unload;
  • info.extra_info = &pinfo;
  • pinfo.options = OPT_PROTO_CHAT_TOPIC;
  • pinfo.list_icon = fb_list_icon;
  • pinfo.tooltip_text = fb_client_tooltip_text;
  • pinfo.status_types = fb_status_types;
  • pinfo.blist_node_menu = fb_client_blist_node_menu;
  • pinfo.chat_info = fb_chat_info;
  • pinfo.chat_info_defaults = fb_chat_info_defaults;
  • pinfo.login = fb_login;
  • pinfo.close = fb_close;
  • pinfo.send_im = fb_im_send;
  • pinfo.send_typing = fb_im_send_typing;
  • pinfo.set_status = fb_server_set_status;
  • pinfo.join_chat = fb_chat_join;
  • pinfo.get_chat_name = fb_chat_get_name;
  • pinfo.chat_invite = fb_chat_invite;
  • pinfo.chat_send = fb_chat_send;
  • pinfo.set_chat_topic = fb_chat_set_topic;
  • pinfo.roomlist_get_list = fb_roomlist_get_list;
  • pinfo.roomlist_cancel = fb_roomlist_cancel;
  • pinfo.offline_message = fb_client_offline_message;
  • pinfo.struct_size = sizeof pinfo;
  • 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);
  • pinfo.protocol_options = g_list_reverse(opts);
  • inited = TRUE;
  • return purple_plugin_register(plugin); +} diff --git a/pidgin/libpurple/protocols/facebook/facebook.h b/pidgin/libpurple/protocols/facebook/facebook.h index edc8b262..aa8b3c34 100644 --- a/pidgin/libpurple/protocols/facebook/facebook.h +++ b/pidgin/libpurple/protocols/facebook/facebook.h @@ -22,24 +22,7 @@ #ifndef FACEBOOK_H #define FACEBOOK_H

-/**

    • SECTION:facebook
    • @section_id: facebook-plugin
    • @short_description: facebook.h
    • @title: Facebook Plugin
    • The Facebook Messenger #PurpleProtocol.
  • */

#include <glib.h> -#include <gmodule.h>

-#define FACEBOOK_TYPE_PROTOCOL (facebook_protocol_get_type()) -#define FACEBOOK_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), FACEBOOK_TYPE_PROTOCOL, FacebookProtocol)) -#define FACEBOOK_PROTOCOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), FACEBOOK_TYPE_PROTOCOL, FacebookProtocolClass)) -#define FACEBOOK_IS_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), FACEBOOK_TYPE_PROTOCOL)) -#define FACEBOOK_IS_PROTOCOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), FACEBOOK_TYPE_PROTOCOL)) -#define FACEBOOK_PROTOCOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), FACEBOOK_TYPE_PROTOCOL, FacebookProtocolClass))

/**

  • FB_PROTOCOL_ID: @@ -48,37 +31,4 @@ */ #define FB_PROTOCOL_ID "prpl-facebook"

-typedef struct _FacebookProtocol FacebookProtocol; -typedef struct _FacebookProtocolClass FacebookProtocolClass;

-/**

    • FacebookProtocol:
    • Represents the Facebook #PurpleProtocol.
  • */ -struct _FacebookProtocol -{
  • /< private >/
  • PurpleProtocol parent; -};

-/**

    • FacebookProtocolClass:
    • The base class for all #FacebookProtocol's.
  • */ -struct _FacebookProtocolClass -{
  • /< private >/
  • PurpleProtocolClass parent_class; -};

-/**

    • facebook_protocol_get_type:
    • Returns: The #GType for a #FacebookProtocol.
  • */ -G_MODULE_EXPORT GType -facebook_protocol_get_type(void);

#endif /* FACEBOOK_H */ diff --git a/pidgin/libpurple/protocols/facebook/http.c b/pidgin/libpurple/protocols/facebook/http.c index 148c9c26..cd9876cf 100644 --- a/pidgin/libpurple/protocols/facebook/http.c +++ b/pidgin/libpurple/protocols/facebook/http.c @@ -381,7 +381,7 @@ fb_http_urlcmp(const gchar *url1, const gchar *url2, gboolean protocol) PurpleHttpURL *purl1; PurpleHttpURL *purl2;

  • static const const gchar * (*funcs[]) (const PurpleHttpURL *url) = {
  • static const gchar * (*funcs[]) (const PurpleHttpURL url) = { / Always first so it can be skipped */ purple_http_url_get_protocol,

diff --git a/pidgin/libpurple/protocols/facebook/json.c b/pidgin/libpurple/protocols/facebook/json.c index f36839c5..448c5b2e 100644 --- a/pidgin/libpurple/protocols/facebook/json.c +++ b/pidgin/libpurple/protocols/facebook/json.c @@ -25,6 +25,7 @@ #include <string.h>

#include "json.h" +#include "glibcompat.h" #include "util.h"

typedef struct _FbJsonValue FbJsonValue; @@ -50,7 +51,7 @@ struct _FbJsonValuesPrivate GError *error; };

-G_DEFINE_TYPE(FbJsonValues, fb_json_values, G_TYPE_OBJECT); +G_DEFINE_TYPE_WITH_CODE(FbJsonValues, fb_json_values, G_TYPE_OBJECT, G_ADD_PRIVATE(FbJsonValues));

static void fb_json_values_dispose(GObject *obj) diff --git a/pidgin/libpurple/protocols/facebook/mqtt.c b/pidgin/libpurple/protocols/facebook/mqtt.c index da279cbe..ec87b0f7 100644 --- a/pidgin/libpurple/protocols/facebook/mqtt.c +++ b/pidgin/libpurple/protocols/facebook/mqtt.c @@ -28,26 +28,26 @@ #include "account.h" #include "eventloop.h" #include "glibcompat.h" -#include "purple-gio.h" -#include "queuedoutputstream.h" +#include "sslconn.h"

+#include "marshal.h" #include "mqtt.h" #include "util.h"

struct _FbMqttPrivate { PurpleConnection *gc;

  • GIOStream *conn;
  • GBufferedInputStream *input;
  • PurpleQueuedOutputStream *output;
  • GCancellable *cancellable;
  • PurpleSslConnection *gsc; gboolean connected; guint16 mid;

    GByteArray *rbuf;

  • GByteArray *wbuf; gsize remz;

    gint tev;

  • gint rev;

  • gint wev; };

struct _FbMqttMessagePrivate @@ -62,10 +62,8 @@ struct _FbMqttMessagePrivate gboolean local; };

-G_DEFINE_TYPE(FbMqtt, fb_mqtt, G_TYPE_OBJECT); -G_DEFINE_TYPE(FbMqttMessage, fb_mqtt_message, G_TYPE_OBJECT);

-static void fb_mqtt_read_packet(FbMqtt *mqtt); +G_DEFINE_TYPE_WITH_CODE(FbMqtt, fb_mqtt, G_TYPE_OBJECT, G_ADD_PRIVATE(FbMqtt)); +G_DEFINE_TYPE_WITH_CODE(FbMqttMessage, fb_mqtt_message, G_TYPE_OBJECT, G_ADD_PRIVATE(FbMqttMessage));

static void fb_mqtt_dispose(GObject *obj) @@ -75,6 +73,7 @@ fb_mqtt_dispose(GObject *obj)

fb_mqtt_close(mqtt);
g_byte_array_free(priv->rbuf, TRUE);
  • g_byte_array_free(priv->wbuf, TRUE); }

static void @@ -96,7 +95,8 @@ fb_mqtt_class_init(FbMqttClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,

  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__VOID,
               G_TYPE_NONE,
               0);
    

@@ -112,9 +112,10 @@ fb_mqtt_class_init(FbMqttClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,

  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__POINTER,
               G_TYPE_NONE,
    
  •            1, G_TYPE_ERROR);
    
  •            1, G_TYPE_POINTER);
    
    /**
    • FbMqtt::open: @@ -128,7 +129,8 @@ fb_mqtt_class_init(FbMqttClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,
  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__VOID,
               G_TYPE_NONE,
               0);
    

@@ -144,7 +146,8 @@ fb_mqtt_class_init(FbMqttClass *klass) G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0,

  •            NULL, NULL, NULL,
    
  •            NULL, NULL,
    
  •            fb_marshal_VOID__STRING_BOXED,
               G_TYPE_NONE,
               2, G_TYPE_STRING, G_TYPE_BYTE_ARRAY);
    

} @@ -158,6 +161,7 @@ fb_mqtt_init(FbMqtt *mqtt) mqtt->priv = priv;

priv->rbuf = g_byte_array_new();
  • priv->wbuf = g_byte_array_new(); }

static void @@ -201,6 +205,18 @@ fb_mqtt_error_quark(void) return q; }

+GQuark +fb_mqtt_ssl_error_quark(void) +{

  • static GQuark q = 0;
  • if (G_UNLIKELY(q == 0)) {
  •   q = g_quark_from_static_string("fb-mqtt-ssl-error-quark");
    
  • }
  • return q; +}

FbMqtt * fb_mqtt_new(PurpleConnection *gc) { @@ -224,47 +240,33 @@ fb_mqtt_close(FbMqtt *mqtt) g_return_if_fail(FB_IS_MQTT(mqtt)); priv = mqtt->priv;

  • if (priv->tev > 0) {
  •   g_source_remove(priv->tev);
    
  •   priv->tev = 0;
    
  • if (priv->wev > 0) {
  •   purple_input_remove(priv->wev);
    
  •   priv->wev = 0;
    
    }
  • if (priv->cancellable != NULL) {
  •   g_cancellable_cancel(priv->cancellable);
    
  •   g_clear_object(&priv->cancellable);
    
  • if (priv->rev > 0) {
  •   purple_input_remove(priv->rev);
    
  •   priv->rev = 0;
    
    }
  • if (priv->conn != NULL) {
  •   purple_gio_graceful_close(priv->conn,
    
  •   		G_INPUT_STREAM(priv->input),
    
  •   		G_OUTPUT_STREAM(priv->output));
    
  •   g_clear_object(&priv->input);
    
  •   g_clear_object(&priv->output);
    
  •   g_clear_object(&priv->conn);
    
  • if (priv->tev > 0) {
  •   purple_timeout_remove(priv->tev);
    
  •   priv->tev = 0;
    
    }
  • priv->connected = FALSE;
  • g_byte_array_set_size(priv->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;
    
  • if (priv->gsc != NULL) {
  •   purple_ssl_close(priv->gsc);
    
  •   priv->gsc = NULL;
    
    }
  • /* Now we can check for programming errors */
  • g_return_if_fail(FB_IS_MQTT(mqtt));
  • if (prefix != NULL) {
  •   g_prefix_error(&err, "%s: ", prefix);
    
  • if (priv->wbuf->len > 0) {
  •   fb_util_debug_warning("Closing with unwritten data");
    
    }
  • g_signal_emit_by_name(mqtt, "error", err);
  • g_error_free(err);
  • priv->connected = FALSE;
  • g_byte_array_set_size(priv->rbuf, 0);
  • g_byte_array_set_size(priv->wbuf, 0); }

void @@ -342,127 +344,84 @@ fb_mqtt_ping(FbMqtt *mqtt) }

static void -fb_mqtt_cb_fill(GObject *source, GAsyncResult *res, gpointer data) +fb_mqtt_cb_read(gpointer data, gint fd, PurpleInputCondition cond) {

  • GBufferedInputStream *input = G_BUFFERED_INPUT_STREAM(source); FbMqtt *mqtt = data;
  • gssize ret;
  • GError *err = NULL;
  • FbMqttMessage *msg;
  • FbMqttPrivate *priv = mqtt->priv;
  • gint res;
  • guint mult;
  • guint8 buf[1024];
  • guint8 byte;
  • gsize size;
  • gssize rize;
  • if (priv->remz < 1) {
  •   /* Reset the read buffer */
    
  •   g_byte_array_set_size(priv->rbuf, 0);
    
  • ret = g_buffered_input_stream_fill_finish(input, res, &err);
  •   res = purple_ssl_read(priv->gsc, &byte, sizeof byte);
    
  • if (ret < 1) {
  •   if (ret == 0) {
    
  •   	err = g_error_new_literal(G_IO_ERROR,
    
  •   			G_IO_ERROR_CONNECTION_CLOSED,
    
  •   			_("Connection closed"));
    
  •   if (res < 0 && errno == EAGAIN) {
    
  •   	return;
    
  •   } else if (res != 1) {
    
  •   	fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL,
    
  •   	              _("Failed to read fixed header"));
    
  •   	return;
      }
    
  •   fb_mqtt_take_error(mqtt, err, _("Failed to read fixed header"));
    
  •   return;
    
  • }
  •   g_byte_array_append(priv->rbuf, &byte, sizeof byte);
    
  • fb_mqtt_read_packet(mqtt); -}
  •   mult = 1;
    

-static void -fb_mqtt_cb_read_packet(GObject *source, GAsyncResult *res, gpointer data) -{

  • FbMqtt *mqtt = data;
  • FbMqttPrivate *priv;
  • gssize ret;
  • FbMqttMessage *msg;
  • GError *err = NULL;
  •   do {
    
  •   	res = purple_ssl_read(priv->gsc, &byte, sizeof byte);
    
  • ret = g_input_stream_read_finish(G_INPUT_STREAM(source), res, &err);
  •   	/* TODO: this case isn't handled yet */
    
  •   	if (0 && res < 0 && errno == EAGAIN) {
    
  •   		return;
    
  •   	} else if (res != 1) {
    
  •   		fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL,
    
  •   		              _("Failed to read packet size"));
    
  •   		return;
    
  •   	}
    
  • if (ret < 1) {
  •   if (ret == 0) {
    
  •   	err = g_error_new_literal(G_IO_ERROR,
    
  •   			G_IO_ERROR_CONNECTION_CLOSED,
    
  •   			_("Connection closed"));
    
  •   }
    
  •   	g_byte_array_append(priv->rbuf, &byte, sizeof byte);
    
  •   fb_mqtt_take_error(mqtt, err, _("Failed to read packet data"));
    
  •   return;
    
  •   	priv->remz += (byte & 127) * mult;
    
  •   	mult *= 128;
    
  •   } while ((byte & 128) != 0);
    
    }
  • priv = mqtt->priv;
  • priv->remz -= ret;
  • if (priv->remz > 0) {
  •   g_input_stream_read_async(G_INPUT_STREAM(source),
    
  •   		priv->rbuf->data +
    
  •   		priv->rbuf->len - priv->remz, priv->remz,
    
  •   		G_PRIORITY_DEFAULT, priv->cancellable,
    
  •   		fb_mqtt_cb_read_packet, mqtt);
    
  •   return;
    
  • }
  • msg = fb_mqtt_message_new_bytes(priv->rbuf);
  •   size = MIN(priv->remz, sizeof buf);
    
  •   rize = purple_ssl_read(priv->gsc, buf, size);
    
  • if (G_UNLIKELY(msg == NULL)) {
  •   fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL,
    
  •                 _("Failed to parse message"));
    
  •   return;
    
  • }
  • fb_mqtt_read(mqtt, msg);
  • g_object_unref(msg);
  •   if (rize < 0 && errno == EAGAIN) {
    
  •   	return;
    
  •   } else if (rize < 1) {
    
  •   	fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL,
    
  •   	              _("Failed to read packet data"));
    
  •   	return;
    
  •   }
    
  • /* Read another packet if connection wasn't reset in fb_mqtt_read() */
  • if (fb_mqtt_connected(mqtt, FALSE)) {
  •   fb_mqtt_read_packet(mqtt);
    
  •   g_byte_array_append(priv->rbuf, buf, rize);
    
  •   priv->remz -= rize;
    
    } -}

-static void -fb_mqtt_read_packet(FbMqtt *mqtt) -{

  • FbMqttPrivate *priv = mqtt->priv;
  • const guint8 const *buf;
  • gsize count = 0;
  • gsize pos;
  • guint mult = 1;
  • guint8 byte;
  • gsize size = 0;
  • if (priv->remz < 1) {
  •   msg = fb_mqtt_message_new_bytes(priv->rbuf);
    
  •   priv->remz = 0;
    
  • buf = g_buffered_input_stream_peek_buffer(priv->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(priv->input, -1,
    
  •   			G_PRIORITY_DEFAULT, priv->cancellable,
    
  •   			fb_mqtt_cb_fill, mqtt);
    
  •   if (G_UNLIKELY(msg == NULL)) {
    
  •   	fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL,
    
  •   	              _("Failed to parse message"));
      	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(priv->rbuf, size);
  • priv->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(priv->input),
  •   	priv->rbuf->data, priv->rbuf->len,
    
  •   	G_PRIORITY_DEFAULT, priv->cancellable,
    
  •   	fb_mqtt_cb_read_packet, mqtt);
    
  •   fb_mqtt_read(mqtt, msg);
    
  •   g_object_unref(msg);
    
  • } }

void @@ -569,16 +528,27 @@ fb_mqtt_read(FbMqtt *mqtt, FbMqttMessage *msg) }

static void -fb_mqtt_cb_flush(GObject *source, GAsyncResult *res, gpointer data) +fb_mqtt_cb_write(gpointer data, gint fd, PurpleInputCondition cond) { FbMqtt *mqtt = data;

  • GError *err = NULL;
  • FbMqttPrivate *priv = mqtt->priv;
  • gssize wize;
  • wize = purple_ssl_write(priv->gsc, priv->wbuf->data, priv->wbuf->len);
  • if (!g_output_stream_flush_finish(G_OUTPUT_STREAM(source),
  •   	res, &err)) {
    
  •   fb_mqtt_take_error(mqtt, err, _("Failed to write data"));
    
  • if (wize < 0) {
  •   fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL,
    
  •                 _("Failed to write data"));
      return;
    
    }
  • if (wize > 0) {
  •   g_byte_array_remove_range(priv->wbuf, 0, wize);
    
  • }
  • if (priv->wbuf->len < 1) {
  •   priv->wev = 0;
    
  • } }

void @@ -587,7 +557,6 @@ fb_mqtt_write(FbMqtt *mqtt, FbMqttMessage *msg) const GByteArray *bytes; FbMqttMessagePrivate *mriv; FbMqttPrivate *priv;

  • GBytes *gbytes;

    g_return_if_fail(FB_IS_MQTT(mqtt)); g_return_if_fail(FB_IS_MQTT_MESSAGE(msg)); @@ -606,46 +575,46 @@ fb_mqtt_write(FbMqtt *mqtt, FbMqttMessage *msg) "Writing %d (flags: 0x%0X)", mriv->type, mriv->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(priv->output, gbytes);

  • g_bytes_unref(gbytes);

  • g_byte_array_append(priv->wbuf, bytes->data, bytes->len);
  • fb_mqtt_cb_write(mqtt, priv->gsc->fd, PURPLE_INPUT_WRITE);
  • if (!g_output_stream_has_pending(G_OUTPUT_STREAM(priv->output))) {
  •   g_output_stream_flush_async(G_OUTPUT_STREAM(priv->output),
    
  •   		G_PRIORITY_DEFAULT, priv->cancellable,
    
  •   		fb_mqtt_cb_flush, mqtt);
    
  • if (priv->wev > 0) {
  •   priv->wev = purple_input_add(priv->gsc->fd,
    
  •                                PURPLE_INPUT_WRITE,
    
  •                                fb_mqtt_cb_write, mqtt);
    
    } }

static void -fb_mqtt_cb_open(GObject *source, GAsyncResult *res, gpointer data) +fb_mqtt_cb_open(gpointer data, PurpleSslConnection *ssl,

  •            PurpleInputCondition cond)
    

{ FbMqtt *mqtt = data;

  • FbMqttPrivate *priv;
  • 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;
    
  • }
  • FbMqttPrivate *priv = mqtt->priv;

    fb_mqtt_timeout_clear(mqtt);

  • priv->rev = purple_input_add(priv->gsc->fd, PURPLE_INPUT_READ,

  •                            fb_mqtt_cb_read, mqtt);
    
  • g_signal_emit_by_name(mqtt, "open"); +}

  • priv = mqtt->priv;
  • priv->conn = G_IO_STREAM(conn);
  • priv->input = G_BUFFERED_INPUT_STREAM(g_buffered_input_stream_new(
  •   	g_io_stream_get_input_stream(priv->conn)));
    
  • priv->output = purple_queued_output_stream_new(
  •   	g_io_stream_get_output_stream(priv->conn));
    

+static void +fb_mqtt_cb_open_error(PurpleSslConnection *ssl, PurpleSslErrorType error,

  •                  gpointer data)
    

+{

  • const gchar *str;
  • FbMqtt *mqtt = data;
  • FbMqttPrivate *priv = mqtt->priv;
  • GError *err;
  • fb_mqtt_read_packet(mqtt);
  • str = purple_ssl_strerror(error);
  • err = g_error_new_literal(FB_MQTT_SSL_ERROR, error, str);
  • g_signal_emit_by_name(mqtt, "open");
  • /* Do not call purple_ssl_close() from the error_func */
  • priv->gsc = NULL;
  • g_signal_emit_by_name(mqtt, "error", err);
  • g_error_free(err); }

void @@ -653,29 +622,20 @@ fb_mqtt_open(FbMqtt *mqtt, const gchar *host, gint port) { FbMqttPrivate *priv; PurpleAccount *acc;

  • GSocketClient *client;

  • GError *err = NULL;

    g_return_if_fail(FB_IS_MQTT(mqtt)); priv = mqtt->priv;

    acc = purple_connection_get_account(priv->gc); fb_mqtt_close(mqtt);

  • priv->gsc = purple_ssl_connect(acc, host, port, fb_mqtt_cb_open,
  •                              fb_mqtt_cb_open_error, mqtt);
    
  • client = purple_gio_socket_client_new(acc, &err);
  • if (client == NULL) {
  •   fb_mqtt_take_error(mqtt, err, NULL);
    
  • if (priv->gsc == NULL) {
  •   fb_mqtt_cb_open_error(NULL, 0, mqtt);
      return;
    
    }
  • priv->cancellable = g_cancellable_new();
  • g_socket_client_set_tls(client, TRUE);
  • g_socket_client_connect_to_host_async(client, host, port,
  •   	priv->cancellable, fb_mqtt_cb_open, mqtt);
    
  • g_object_unref(client);
  • fb_mqtt_timeout(mqtt); }

@@ -711,7 +671,7 @@ fb_mqtt_connected(FbMqtt *mqtt, gboolean error)

g_return_val_if_fail(FB_IS_MQTT(mqtt), FALSE);
priv = mqtt->priv;
  • connected = (priv->conn != NULL) && priv->connected;
  • connected = (priv->gsc != NULL) && priv->connected;

    if (!connected && error) { fb_mqtt_error(mqtt, FB_MQTT_ERROR_GENERAL, diff --git a/pidgin/libpurple/protocols/facebook/mqtt.h b/pidgin/libpurple/protocols/facebook/mqtt.h index 30172eb4..a33b4f52 100644 --- a/pidgin/libpurple/protocols/facebook/mqtt.h +++ b/pidgin/libpurple/protocols/facebook/mqtt.h @@ -107,6 +107,13 @@ */ #define FB_MQTT_ERROR fb_mqtt_error_quark()

+/**

    • FB_MQTT_SSL_ERROR:
    • The #GQuark of the domain of MQTT SSL errors.
  • */ +#define FB_MQTT_SSL_ERROR fb_mqtt_ssl_error_quark()

typedef struct _FbMqtt FbMqtt; typedef struct _FbMqttClass FbMqttClass; typedef struct _FbMqttPrivate FbMqttPrivate; @@ -290,6 +297,16 @@ fb_mqtt_message_get_type(void); GQuark fb_mqtt_error_quark(void);

+/**

    • fb_mqtt_ssl_error_quark:
    • Gets the #GQuark of the domain of MQTT SSL errors.
    • Returns: The #GQuark of the domain.
  • */ +GQuark +fb_mqtt_ssl_error_quark(void);

/**

  • fb_mqtt_new:
  • @gc: The #PurpleConnection. diff --git a/pidgin/libpurple/protocols/facebook/thrift.c b/pidgin/libpurple/protocols/facebook/thrift.c index d33a94e7..c4356f6f 100644 --- a/pidgin/libpurple/protocols/facebook/thrift.c +++ b/pidgin/libpurple/protocols/facebook/thrift.c @@ -21,6 +21,7 @@

#include <string.h>

+#include "glibcompat.h" #include "thrift.h"

struct _FbThriftPrivate @@ -32,7 +33,7 @@ struct _FbThriftPrivate guint lastbool; };

-G_DEFINE_TYPE(FbThrift, fb_thrift, G_TYPE_OBJECT); +G_DEFINE_TYPE_WITH_CODE(FbThrift, fb_thrift, G_TYPE_OBJECT, G_ADD_PRIVATE(FbThrift));

static void fb_thrift_dispose(GObject *obj)

av1934413 avatar Jan 16 '23 18:01 av1934413

I would not recommend this change. There's been very little change to the actual facebook code here and the majority of these changes are for libpurple3 only. In fact, I'm positive that not all of the patches in this repository have made it back into the copy in the pidgin3 repository.

grimmy avatar Jan 17 '23 10:01 grimmy