diff options
Diffstat (limited to 'facebook')
-rw-r--r-- | facebook/facebook-api.c | 146 | ||||
-rw-r--r-- | facebook/facebook-api.h | 24 | ||||
-rw-r--r-- | facebook/facebook-thrift.c | 37 | ||||
-rw-r--r-- | facebook/facebook-thrift.h | 10 |
4 files changed, 132 insertions, 85 deletions
diff --git a/facebook/facebook-api.c b/facebook/facebook-api.c index 3461e2a..6b30bcd 100644 --- a/facebook/facebook-api.c +++ b/facebook/facebook-api.c @@ -808,66 +808,66 @@ fb_api_cb_mqtt_open(FbMqtt *mqtt, gpointer data) thft = fb_thrift_new(NULL, 0); /* Write the client identifier */ - fb_thrift_write_field(thft, FB_THRIFT_TYPE_STRING, 1); + fb_thrift_write_field(thft, FB_THRIFT_TYPE_STRING, 1, 0); fb_thrift_write_str(thft, priv->cid); - fb_thrift_write_field(thft, FB_THRIFT_TYPE_STRUCT, 4); + fb_thrift_write_field(thft, FB_THRIFT_TYPE_STRUCT, 4, 1); /* Write the user identifier */ - fb_thrift_write_field(thft, FB_THRIFT_TYPE_I64, 5); + fb_thrift_write_field(thft, FB_THRIFT_TYPE_I64, 1, 0); fb_thrift_write_i64(thft, priv->uid); /* Write the information string */ - fb_thrift_write_field(thft, FB_THRIFT_TYPE_STRING, 6); + fb_thrift_write_field(thft, FB_THRIFT_TYPE_STRING, 2, 1); fb_thrift_write_str(thft, ""); /* Write the UNKNOWN ("cp"?) */ - fb_thrift_write_field(thft, FB_THRIFT_TYPE_I64, 7); + 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, 8); + 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, 9); + 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, 10); + 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, 11); + fb_thrift_write_field(thft, FB_THRIFT_TYPE_BOOL, 7, 6); fb_thrift_write_bool(thft, !priv->invisible); /* Write the device identifier */ - fb_thrift_write_field(thft, FB_THRIFT_TYPE_STRING, 12); + fb_thrift_write_field(thft, FB_THRIFT_TYPE_STRING, 8, 7); fb_thrift_write_str(thft, priv->did); /* Write the UNKNOWN ("fg"?) */ - fb_thrift_write_field(thft, FB_THRIFT_TYPE_BOOL, 13); + 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, 14); + 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, 15); + 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, 16); + fb_thrift_write_field(thft, FB_THRIFT_TYPE_I64, 12, 11); fb_thrift_write_i64(thft, priv->mid); /* Write the UNKNOWN */ - fb_thrift_write_field(thft, FB_THRIFT_TYPE_LIST, 18); + 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, 19); + fb_thrift_write_field(thft, FB_THRIFT_TYPE_STRING, 15, 14); fb_thrift_write_str(thft, priv->token); /* Write the STOP for the struct */ @@ -1340,6 +1340,7 @@ fb_api_cb_publish_ms(FbApi *api, GByteArray *pload) JsonNode *root; JsonNode *node; + /* Read identifier string (for Facebook employees) */ thft = fb_thrift_new(pload, 0); fb_thrift_read_str(thft, NULL); size = fb_thrift_get_pos(thft); @@ -1465,87 +1466,112 @@ fb_api_cb_publish_ms(FbApi *api, GByteArray *pload) } static void -fb_api_cb_publish_p(FbApi *api, GByteArray *pload) +fb_api_cb_publish_pt(FbThrift *thft, GSList **press, GError **error) { FbApiPresence *pres; - FbThrift *thft; FbThriftType type; + gint16 id; gint32 i32; gint64 i64; - GSList *press; guint i; - guint size; + guint size = 0; - /* Start at 1 to skip the NULL byte */ - thft = fb_thrift_new(pload, 1); - press = NULL; + /* Read identifier string (for Facebook employees) */ + FB_API_TCHK(fb_thrift_read_str(thft, NULL)); - /* Skip the full list boolean field */ - fb_thrift_read_field(thft, &type, NULL); - g_warn_if_fail(type == FB_THRIFT_TYPE_BOOL); - fb_thrift_read_bool(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_thrift_read_field(thft, &type, NULL); - g_warn_if_fail(type == FB_THRIFT_TYPE_LIST); + 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_thrift_read_list(thft, &type, &size); - g_warn_if_fail(type == FB_THRIFT_TYPE_STRUCT); + 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_thrift_read_field(thft, &type, NULL); - g_warn_if_fail(type == FB_THRIFT_TYPE_I64); - fb_thrift_read_i64(thft, &i64); + 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_thrift_read_field(thft, &type, NULL); - g_warn_if_fail(type == FB_THRIFT_TYPE_I32); - fb_thrift_read_i32(thft, &i32); + 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)); pres = fb_api_presence_dup(NULL); pres->uid = i64; pres->active = i32 != 0; - press = g_slist_prepend(press, pres); + *press = g_slist_prepend(*press, pres); fb_util_debug_info("Presence: %" FB_ID_FORMAT " (%d)", i64, i32 != 0); - /* Skip the last active timestamp field */ - if (!fb_thrift_read_field(thft, &type, NULL)) { - continue; - } + while (id <= 5) { + if (fb_thrift_read_isstop(thft)) { + break; + } - g_warn_if_fail(type == FB_THRIFT_TYPE_I64); - fb_thrift_read_i64(thft, NULL); + FB_API_TCHK(fb_thrift_read_field(thft, &type, &id, id)); - /* Skip the active client bits field */ - if (!fb_thrift_read_field(thft, &type, NULL)) { - continue; - } + 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; - g_warn_if_fail(type == FB_THRIFT_TYPE_I16); - fb_thrift_read_i16(thft, NULL); + 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; - /* Skip the VoIP compatibility bits field */ - if (!fb_thrift_read_field(thft, &type, NULL)) { - continue; - } + 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; - g_warn_if_fail(type == FB_THRIFT_TYPE_I64); - fb_thrift_read_i64(thft, NULL); + default: + FB_API_TCHK(FALSE); + break; + } + } /* Read the field stop */ - fb_thrift_read_stop(thft); + FB_API_TCHK(fb_thrift_read_stop(thft)); } /* Read the field stop */ - fb_thrift_read_stop(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 *press = NULL; + + thft = fb_thrift_new(pload, 0); + fb_api_cb_publish_pt(thft, &press, &err); g_object_unref(thft); - press = g_slist_reverse(press); - g_signal_emit_by_name(api, "presences", press); + if (G_LIKELY(err == NULL)) { + g_signal_emit_by_name(api, "presences", press); + } else { + fb_api_error_emit(api, err); + } + g_slist_free_full(press, (GDestroyNotify) fb_api_presence_free); } diff --git a/facebook/facebook-api.h b/facebook/facebook-api.h index 15e4cb2..757de9d 100644 --- a/facebook/facebook-api.h +++ b/facebook/facebook-api.h @@ -190,6 +190,30 @@ #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. diff --git a/facebook/facebook-thrift.c b/facebook/facebook-thrift.c index bde1eb1..9604e4d 100644 --- a/facebook/facebook-thrift.c +++ b/facebook/facebook-thrift.c @@ -26,7 +26,6 @@ struct _FbThriftPrivate guint offset; guint pos; guint lastbool; - gint16 lastid; }; G_DEFINE_TYPE(FbThrift, fb_thrift, G_TYPE_OBJECT); @@ -330,7 +329,8 @@ fb_thrift_read_str(FbThrift *thft, gchar **value) } gboolean -fb_thrift_read_field(FbThrift *thft, FbThriftType *type, gint16 *id) +fb_thrift_read_field(FbThrift *thft, FbThriftType *type, gint16 *id, + gint16 lastid) { FbThriftPrivate *priv; gint16 i16; @@ -338,6 +338,7 @@ fb_thrift_read_field(FbThrift *thft, FbThriftType *type, gint16 *id) 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); priv = thft->priv; if (!fb_thrift_read_byte(thft, &byte)) { @@ -352,29 +353,22 @@ fb_thrift_read_field(FbThrift *thft, FbThriftType *type, gint16 *id) *type = fb_thrift_ct2t(byte & 0x0F); i16 = (byte & 0xF0) >> 4; - if (*type == FB_THRIFT_TYPE_BOOL) { - priv->lastbool = 0x01; - - if ((byte & 0x0F) == 0x01) { - priv->lastbool |= 0x01 << 2; - } - - return TRUE; - } - if (i16 == 0) { - if (!fb_thrift_read_i16(thft, &i16)) { + if (!fb_thrift_read_i16(thft, id)) { return FALSE; } } else { - i16 = priv->lastid + i16; + *id = lastid + i16; } - if (id != NULL) { - *id = i16; + if (*type == FB_THRIFT_TYPE_BOOL) { + priv->lastbool = 0x01; + + if ((byte & 0x0F) == 0x01) { + priv->lastbool |= 0x01 << 2; + } } - priv->lastid = i16; return TRUE; } @@ -585,7 +579,8 @@ fb_thrift_write_str(FbThrift *thft, const gchar *value) } void -fb_thrift_write_field(FbThrift *thft, FbThriftType type, gint16 id) +fb_thrift_write_field(FbThrift *thft, FbThriftType type, gint16 id, + gint16 lastid) { FbThriftPrivate *priv; gint16 diff; @@ -598,16 +593,14 @@ fb_thrift_write_field(FbThrift *thft, FbThriftType type, gint16 id) } type = fb_thrift_t2ct(type); - diff = id - priv->lastid; + diff = id - lastid; - if ((id <= priv->lastid) || (diff > 0x0F)) { + 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); } - - priv->lastid = id; } void diff --git a/facebook/facebook-thrift.h b/facebook/facebook-thrift.h index 65257c4..943825d 100644 --- a/facebook/facebook-thrift.h +++ b/facebook/facebook-thrift.h @@ -326,14 +326,16 @@ 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 or #NULL. + * @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); +fb_thrift_read_field(FbThrift *thft, FbThriftType *type, gint16 *id, + gint16 lastid); /** * fb_thrift_read_stop: @@ -520,11 +522,13 @@ fb_thrift_write_str(FbThrift *thft, const gchar *value); * @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); +fb_thrift_write_field(FbThrift *thft, FbThriftType type, gint16 id, + gint16 lastid); /** * fb_thrift_write_stop: |