Browse Source

purple-facebook package update

Signed-off-by: guibuilder_pel7x64builder0 <guibuilder@powerel.org>
master
guibuilder_pel7x64builder0 5 years ago
parent
commit
24c3c6b6ee
  1. 845
      SOURCES/purple-facebook-0.9.6-fb-work-chat.patch
  2. 46
      SOURCES/purple-facebook-0.9.6-option-show-inactive-as-away.patch
  3. 89
      SPECS/purple-facebook.spec

845
SOURCES/purple-facebook-0.9.6-fb-work-chat.patch

@ -0,0 +1,845 @@
Index: purple-facebook-0.9.6/pidgin/libpurple/protocols/facebook/api.c
===================================================================
--- purple-facebook-0.9.6.orig/pidgin/libpurple/protocols/facebook/api.c
+++ purple-facebook-0.9.6/pidgin/libpurple/protocols/facebook/api.c
@@ -33,6 +33,7 @@
#include "util.h"
typedef struct _FbApiData FbApiData;
+typedef struct _FbApiPreloginData FbApiPreloginData;
enum
{
@@ -44,6 +45,8 @@ enum
PROP_STOKEN,
PROP_TOKEN,
PROP_UID,
+ PROP_TWEAK,
+ PROP_WORK,
PROP_N
};
@@ -69,6 +72,11 @@ struct _FbApiPrivate
guint unread;
FbId lastmid;
gchar *contacts_delta;
+ int tweak;
+ gboolean is_work;
+ gboolean need_work_switch;
+ gchar *sso_verifier;
+ FbId work_community_id;
};
struct _FbApiData
@@ -77,6 +85,13 @@ struct _FbApiData
GDestroyNotify func;
};
+struct _FbApiPreloginData
+{
+ FbApi *api;
+ const gchar *user;
+ const gchar *pass;
+};
+
static void
fb_api_attach(FbApi *api, FbId aid, const gchar *msgid, FbApiMessage *msg);
@@ -94,6 +109,24 @@ fb_api_contacts_delta(FbApi *api, const
G_DEFINE_TYPE_WITH_CODE(FbApi, fb_api, G_TYPE_OBJECT, G_ADD_PRIVATE(FbApi));
+static const gchar *agents[] = {
+ FB_API_AGENT,
+ NULL,
+};
+
+static const gchar *
+fb_api_get_agent_string(int tweak, gboolean mqtt)
+{
+ gboolean http_only = tweak & 4;
+ gboolean mqtt_only = tweak & 8;
+
+ if (tweak <= 0 || tweak > 15 || (http_only && mqtt) || (mqtt_only && !mqtt)) {
+ return agents[0];
+ }
+
+ return agents[tweak & 3];
+}
+
static void
fb_api_set_property(GObject *obj, guint prop, const GValue *val,
GParamSpec *pspec)
@@ -123,6 +156,12 @@ fb_api_set_property(GObject *obj, guint
case PROP_UID:
priv->uid = g_value_get_int64(val);
break;
+ case PROP_TWEAK:
+ priv->tweak = g_value_get_int(val);
+ break;
+ case PROP_WORK:
+ priv->is_work = g_value_get_boolean(val);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop, pspec);
@@ -154,6 +193,12 @@ fb_api_get_property(GObject *obj, guint
case PROP_UID:
g_value_set_int64(val, priv->uid);
break;
+ case PROP_TWEAK:
+ g_value_set_int(val, priv->tweak);
+ break;
+ case PROP_WORK:
+ g_value_set_boolean(val, priv->is_work);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop, pspec);
@@ -190,6 +235,7 @@ fb_api_dispose(GObject *obj)
g_free(priv->stoken);
g_free(priv->token);
g_free(priv->contacts_delta);
+ g_free(priv->sso_verifier);
}
static void
@@ -279,6 +325,26 @@ fb_api_class_init(FbApiClass *klass)
"User identifier",
0, G_MAXINT64, 0,
G_PARAM_READWRITE);
+
+ /**
+ * FbApi:tweak:
+ */
+ props[PROP_TWEAK] = g_param_spec_int(
+ "tweak",
+ "Tweak",
+ "",
+ 0, G_MAXINT, 0,
+ G_PARAM_READWRITE);
+
+ /**
+ * FbApi:work:
+ */
+ props[PROP_WORK] = g_param_spec_boolean(
+ "work",
+ "Work",
+ "",
+ FALSE,
+ G_PARAM_READWRITE);
g_object_class_install_properties(gklass, PROP_N, props);
/**
@@ -517,6 +583,22 @@ fb_api_class_init(FbApiClass *klass)
fb_marshal_VOID__POINTER,
G_TYPE_NONE,
1, G_TYPE_POINTER);
+
+ /**
+ * FbApi::work-sso-login:
+ * @api: The #FbApi.
+ *
+ * Emitted when user interaction is required to continue SAML SSO login
+ */
+
+ g_signal_new("work-sso-login",
+ G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_ACTION,
+ 0,
+ NULL, NULL,
+ fb_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
}
static void
@@ -760,7 +842,8 @@ fb_api_http_req(FbApi *api, const gchar
PurpleHttpConnection *ret;
PurpleHttpRequest *req;
- fb_http_params_set_str(params, "api_key", FB_API_KEY);
+ fb_http_params_set_str(params, "api_key",
+ priv->is_work ? FB_WORK_API_KEY : FB_API_KEY);
fb_http_params_set_str(params, "device_id", priv->did);
fb_http_params_set_str(params, "fb_api_req_friendly_name", name);
fb_http_params_set_str(params, "format", "json");
@@ -787,7 +870,7 @@ fb_api_http_req(FbApi *api, const gchar
g_string_append_printf(gstr, "%s=%s", key, val);
}
- g_string_append(gstr, FB_API_SECRET);
+ g_string_append(gstr, priv->is_work ? FB_WORK_API_SECRET : FB_API_SECRET);
data = g_compute_checksum_for_string(G_CHECKSUM_MD5, gstr->str,
gstr->len);
fb_http_params_set_str(params, "sig", data);
@@ -929,7 +1012,9 @@ fb_api_cb_mqtt_open(FbMqtt *mqtt, gpoint
/* Write the information string */
fb_thrift_write_field(thft, FB_THRIFT_TYPE_STRING, 2, 1);
- fb_thrift_write_str(thft, FB_API_MQTT_AGENT);
+ fb_thrift_write_str(thft, (priv->tweak != 0)
+ ? fb_api_get_agent_string(priv->tweak, 1)
+ : FB_API_MQTT_AGENT);
/* Write the UNKNOWN ("cp"?) */
fb_thrift_write_field(thft, FB_THRIFT_TYPE_I64, 3, 2);
@@ -2128,6 +2213,54 @@ fb_api_attach(FbApi *api, FbId aid, cons
}
static void
+fb_api_cb_work_peek(PurpleHttpConnection *con, PurpleHttpResponse *res, gpointer data)
+{
+ FbApi *api = data;
+ FbApiPrivate *priv = api->priv;
+ GError *err = NULL;
+ JsonNode *root;
+ gchar *community = NULL;
+
+ if (!fb_api_http_chk(api, con, res, &root)) {
+ return;
+ }
+
+ /* The work_users[0] explicitly only handles the first user.
+ * If more than one user is ever needed, this is what you want to change,
+ * but as far as I know this feature (linked work accounts) is deprecated
+ * and most users can detach their work accounts from their personal
+ * accounts by assigning a password to the work account. */
+ community = fb_json_node_get_str(root,
+ "$.data.viewer.work_users[0].community.login_identifier", &err);
+
+ FB_API_ERROR_EMIT(api, err,
+ g_free(community);
+ json_node_free(root);
+ return;
+ );
+
+ priv->work_community_id = FB_ID_FROM_STR(community);
+
+ fb_api_auth(api, "X", "X", "personal_to_work_switch");
+
+ g_free(community);
+ json_node_free(root);
+}
+
+static PurpleHttpConnection *
+fb_api_work_peek(FbApi *api)
+{
+ FbHttpParams *prms;
+
+ prms = fb_http_params_new();
+ fb_http_params_set_int(prms, "doc_id", FB_API_WORK_COMMUNITY_PEEK);
+
+ return fb_api_http_req(api, FB_API_URL_GQL, "WorkCommunityPeekQuery",
+ "post", prms, fb_api_cb_work_peek);
+}
+
+
+static void
fb_api_cb_auth(PurpleHttpConnection *con, PurpleHttpResponse *res,
gpointer data)
{
@@ -2143,7 +2276,14 @@ fb_api_cb_auth(PurpleHttpConnection *con
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");
+
+ /* extremely silly difference */
+ if (priv->is_work) {
+ fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, "$.uid");
+ } else {
+ fb_json_values_add(values, FB_JSON_TYPE_INT, TRUE, "$.uid");
+ }
+
fb_json_values_update(values, &err);
FB_API_ERROR_EMIT(api, err,
@@ -2154,25 +2294,218 @@ fb_api_cb_auth(PurpleHttpConnection *con
g_free(priv->token);
priv->token = fb_json_values_next_str_dup(values, NULL);
- priv->uid = fb_json_values_next_int(values, 0);
- g_signal_emit_by_name(api, "auth");
+ if (priv->is_work) {
+ priv->uid = FB_ID_FROM_STR(fb_json_values_next_str(values, "0"));
+ } else {
+ priv->uid = fb_json_values_next_int(values, 0);
+ }
+
+ if (priv->need_work_switch) {
+ fb_api_work_peek(api);
+ priv->need_work_switch = FALSE;
+ } else {
+ g_signal_emit_by_name(api, "auth");
+ }
+
g_object_unref(values);
json_node_free(root);
}
void
-fb_api_auth(FbApi *api, const gchar *user, const gchar *pass)
+fb_api_auth(FbApi *api, const gchar *user, const gchar *pass, const gchar *credentials_type)
{
+ FbApiPrivate *priv = api->priv;
FbHttpParams *prms;
prms = fb_http_params_new();
fb_http_params_set_str(prms, "email", user);
fb_http_params_set_str(prms, "password", pass);
+
+ if (credentials_type) {
+ fb_http_params_set_str(prms, "credentials_type", credentials_type);
+ }
+
+ if (priv->sso_verifier) {
+ fb_http_params_set_str(prms, "code_verifier", priv->sso_verifier);
+ g_free(priv->sso_verifier);
+ priv->sso_verifier = NULL;
+ }
+
+ if (priv->work_community_id) {
+ fb_http_params_set_int(prms, "community_id", priv->work_community_id);
+ }
+
+ if (priv->is_work && priv->token) {
+ fb_http_params_set_str(prms, "access_token", priv->token);
+ }
+
fb_api_http_req(api, FB_API_URL_AUTH, "authenticate", "auth.login",
prms, fb_api_cb_auth);
}
+static void
+fb_api_cb_work_prelogin(PurpleHttpConnection *con, PurpleHttpResponse *res, gpointer data)
+{
+ FbApiPreloginData *pata = data;
+ FbApi *api = pata->api;
+ FbApiPrivate *priv = api->priv;
+ GError *err = NULL;
+ JsonNode *root;
+ gchar *status;
+ const gchar *user = pata->user;
+ const gchar *pass = pata->pass;
+
+ g_free(pata);
+
+ if (!fb_api_http_chk(api, con, res, &root)) {
+ return;
+ }
+
+ status = fb_json_node_get_str(root, "$.status", &err);
+
+ FB_API_ERROR_EMIT(api, err,
+ json_node_free(root);
+ return;
+ );
+
+ if (g_strcmp0(status, "can_login_password") == 0) {
+ fb_api_auth(api, user, pass, "work_account_password");
+
+ } else if (g_strcmp0(status, "can_login_via_linked_account") == 0) {
+ fb_api_auth(api, user, pass, "personal_account_password_with_work_username");
+ priv->need_work_switch = TRUE;
+
+ } else if (g_strcmp0(status, "can_login_sso") == 0) {
+ g_signal_emit_by_name(api, "work-sso-login");
+
+ } else if (g_strcmp0(status, "cannot_login") == 0) {
+ char *reason = fb_json_node_get_str(root, "$.cannot_login_reason", NULL);
+
+ if (g_strcmp0(reason, "non_business_email") == 0) {
+ fb_api_error(api, FB_API_ERROR_AUTH,
+ "Cannot login with non-business email. "
+ "Change the 'username' setting or disable 'work'");
+ } else {
+ char *title = fb_json_node_get_str(root, "$.error_title", NULL);
+ char *body = fb_json_node_get_str(root, "$.error_body", NULL);
+
+ fb_api_error(api, FB_API_ERROR_AUTH,
+ "Work prelogin failed (%s - %s)", title, body);
+
+ g_free(title);
+ g_free(body);
+ }
+
+ g_free(reason);
+
+ } else if (g_strcmp0(status, "can_self_invite") == 0) {
+ fb_api_error(api, FB_API_ERROR_AUTH, "Unknown email. "
+ "Change the 'username' setting or disable 'work'");
+ }
+
+ g_free(status);
+ json_node_free(root);
+}
+
+void
+fb_api_work_login(FbApi *api, const gchar *user, const gchar *pass)
+{
+ FbApiPrivate *priv = api->priv;
+ FbApiPreloginData *pata = g_new0(FbApiPreloginData, 1);
+ FbHttpParams *prms;
+ gchar *data;
+ PurpleHttpConnection *ret;
+ PurpleHttpRequest *req;
+ const char *url = FB_API_URL_WORK_PRELOGIN;
+
+ pata->api = api;
+ pata->user = user;
+ pata->pass = pass;
+
+ priv->is_work = TRUE;
+
+ // see mark k
+ req = purple_http_request_new(url);
+ purple_http_request_set_max_len(req, -1);
+ purple_http_request_set_method(req, "POST");
+
+ purple_http_request_header_set(req, "Authorization", "OAuth null");
+ purple_http_request_header_set(req, "User-Agent", FB_API_AGENT);
+ purple_http_request_header_set(req, "Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
+
+ prms = fb_http_params_new();
+ fb_http_params_set_str(prms, "email", user);
+ fb_http_params_set_str(prms, "access_token",
+ FB_WORK_API_KEY "|" FB_WORK_API_SECRET);
+
+ data = fb_http_params_close(prms, NULL);
+ purple_http_request_set_contents(req, data, -1);
+ ret = purple_http_request(priv->gc, req, fb_api_cb_work_prelogin, pata);
+ fb_http_conns_add(priv->cons, ret);
+ purple_http_request_unref(req);
+
+ fb_util_debug(FB_UTIL_DEBUG_INFO, "HTTP Request (%p):", ret);
+ fb_util_debug(FB_UTIL_DEBUG_INFO, " Request URL: %s", url);
+ fb_util_debug(FB_UTIL_DEBUG_INFO, " Request Data: %s", data);
+
+ g_free(data);
+}
+
+gchar *
+fb_api_work_gen_sso_url(FbApi *api, const gchar *user)
+{
+ FbApiPrivate *priv = api->priv;
+ gchar *challenge, *verifier, *req_id, *email;
+ gchar *ret;
+
+ fb_util_gen_sso_verifier(&challenge, &verifier, &req_id);
+
+ email = g_uri_escape_string(user, NULL, FALSE);
+
+ ret = g_strdup_printf(FB_API_SSO_URL, req_id, challenge, email);
+
+ g_free(req_id);
+ g_free(challenge);
+ g_free(email);
+
+ g_free(priv->sso_verifier);
+ priv->sso_verifier = verifier;
+
+ return ret;
+}
+
+void
+fb_api_work_got_nonce(FbApi *api, const gchar *url)
+{
+ gchar **split;
+ gchar *uid = NULL;
+ gchar *nonce = NULL;
+ int i;
+
+ if (!g_str_has_prefix(url, "fb-workchat-sso://sso/?")) {
+ return;
+ }
+
+ split = g_strsplit(strchr(url, '?'), "&", -1);
+
+ for (i = 0; split[i]; i++) {
+ gchar *eq = strchr(split[i], '=');
+
+ if (g_str_has_prefix(split[i], "uid=")) {
+ uid = g_strstrip(eq + 1);
+ } else if (g_str_has_prefix(split[i], "nonce=")) {
+ nonce = g_strstrip(eq + 1);
+ }
+ }
+
+ if (uid && nonce) {
+ fb_api_auth(api, uid, nonce, "work_sso_nonce");
+ }
+
+ g_strfreev(split);
+}
+
static gchar *
fb_api_user_icon_checksum(gchar *icon)
{
@@ -2277,6 +2610,8 @@ fb_api_cb_contacts_nodes(FbApi *api, Jso
"$.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_BOOL, FALSE,
+ "$.is_on_viewer_contact_list");
fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
"$.structured_name.text");
fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
@@ -2289,12 +2624,15 @@ fb_api_cb_contacts_nodes(FbApi *api, Jso
}
while (fb_json_values_update(values, &err)) {
+ gboolean in_contact_list;
+
str = fb_json_values_next_str(values, "0");
uid = FB_ID_FROM_STR(str);
str = fb_json_values_next_str(values, NULL);
+ in_contact_list = fb_json_values_next_bool(values, FALSE);
- if ((!purple_strequal(str, "ARE_FRIENDS") &&
- (uid != priv->uid)) || (uid == 0))
+ if ((!in_contact_list && !purple_strequal(str, "ARE_FRIENDS") &&
+ (uid != priv->uid)) || (uid == 0))
{
if (!is_array) {
break;
Index: purple-facebook-0.9.6/pidgin/libpurple/protocols/facebook/api.h
===================================================================
--- purple-facebook-0.9.6.orig/pidgin/libpurple/protocols/facebook/api.h
+++ purple-facebook-0.9.6/pidgin/libpurple/protocols/facebook/api.h
@@ -98,6 +98,20 @@
#define FB_API_SECRET "374e60f8b9bb6b8cbb30f78030438895"
/**
+ * FB_WORK_API_KEY:
+ *
+ * The Facebook workchat app API key.
+ */
+#define FB_WORK_API_KEY "312713275593566"
+
+/**
+ * FB_WORK_API_SECRET:
+ *
+ * The Facebook workchat app API secret.
+ */
+#define FB_WORK_API_SECRET "d2901dc6cb685df3b074b30b56b78d28"
+
+/**
* FB_ORCA_AGENT
*
* The part of the user agent that looks like the official client, since the
@@ -137,6 +151,15 @@
#define FB_API_URL_AUTH FB_API_BHOST "/method/auth.login"
/**
+ * FB_API_URL_WORK_PRELOGIN
+ *
+ * The URL for workchat pre-login information, indicating what auth method
+ * should be used
+ */
+
+#define FB_API_URL_WORK_PRELOGIN FB_API_GHOST "/at_work/pre_login_info"
+
+/**
* FB_API_URL_GQL:
*
* The URL for GraphQL requests.
@@ -172,6 +195,14 @@
#define FB_API_URL_TOPIC FB_API_AHOST "/method/messaging.setthreadname"
/**
+ * FB_API_SSO_URL:
+ *
+ * Template for the URL shown to workchat users when trying to authenticate
+ * with SSO.
+ */
+#define FB_API_SSO_URL "https://m.facebook.com/work/sso/mobile?app_id=312713275593566&response_url=fb-workchat-sso%%3A%%2F%%2Fsso&request_id=%s&code_challenge=%s&email=%s"
+
+/**
* FB_API_QUERY_CONTACT:
*
* The query hash for the `UsersQuery`.
@@ -319,6 +350,16 @@
#define FB_API_QUERY_XMA 10153919431161729
/**
+ * FB_API_WORK_COMMUNITY_PEEK:
+ *
+ * The docid with information about the work community of the currently
+ * authenticated user.
+ *
+ * Used when prelogin returns can_login_via_linked_account
+ */
+#define FB_API_WORK_COMMUNITY_PEEK 1295334753880530
+
+/**
* FB_API_CONTACTS_COUNT:
*
* The maximum amount of contacts to fetch in a single request. If this
@@ -641,12 +682,49 @@ fb_api_error_emit(FbApi *api, GError *er
* @api: The #FbApi.
* @user: The Facebook user name, email, or phone number.
* @pass: The Facebook password.
+ * @credentials_type: Type of work account credentials, or NULL
*
* 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_auth(FbApi *api, const gchar *user, const gchar *pass, const gchar *credentials_type);
+
+/**
+ * fb_api_work_login:
+ * @api: The #FbApi.
+ * @user: The Facebook user name, email, or phone number.
+ * @pass: The Facebook password.
+ *
+ * Starts the workchat login sequence.
+ */
+void
+fb_api_work_login(FbApi *api, const gchar *user, const gchar *pass);
+
+/**
+ * fb_api_work_gen_sso_url:
+ * @api: The #FbApi.
+ * @user: The Facebook user email.
+ *
+ * Generates the URL to be shown to the user to get the SSO auth token. This
+ * url contains a challenge and the corresponding verifier is saved in the
+ * FbApi instance to be used later.
+ *
+ * Returns: a newly allocated string.
+ */
+gchar *
+fb_api_work_gen_sso_url(FbApi *api, const gchar *user);
+
+/**
+ * fb_api_work_got_nonce:
+ * @api: The #FbApi.
+ * @url: The fb-workchat-sso:// URL as entered by the user
+ *
+ * Parses the fb-workchat-sso:// URL that the user got redirected to and
+ * continues with work_sso_nonce auth
+ */
+void
+fb_api_work_got_nonce(FbApi *api, const gchar *url);
/**
* fb_api_contact:
Index: purple-facebook-0.9.6/pidgin/libpurple/protocols/facebook/facebook.c
===================================================================
--- purple-facebook-0.9.6.orig/pidgin/libpurple/protocols/facebook/facebook.c
+++ purple-facebook-0.9.6/pidgin/libpurple/protocols/facebook/facebook.c
@@ -828,6 +828,59 @@ fb_cb_api_typing(FbApi *api, FbApiTyping
}
static void
+fb_cb_work_sso_input_cb(gpointer user_data, const gchar *nonce)
+{
+ FbApi *api;
+ FbData *fata = user_data;
+
+ api = fb_data_get_api(fata);
+
+ fb_api_work_got_nonce(api, nonce);
+}
+
+static void
+fb_cb_work_sso_cancel_cb(gpointer user_data)
+{
+ PurpleConnection *gc;
+ FbData *fata = user_data;
+
+ gc = fb_data_get_connection(fata);
+
+ purple_connection_error(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE,
+ _("User cancelled authorization"));
+}
+
+static void
+fb_cb_api_work_sso_login(FbApi *api, gpointer data)
+{
+ FbData *fata = data;
+ PurpleAccount *acct;
+ PurpleConnection *gc;
+ gchar *url;
+
+ gc = fb_data_get_connection(fata);
+ acct = purple_connection_get_account(gc);
+
+ url = fb_api_work_gen_sso_url(api, purple_account_get_username(acct));
+
+ purple_notify_uri(gc, url);
+ purple_request_input(gc, _("Authorization Code"), "SSO auth",
+ _("Open this URL in your browser to authenticate.\n"
+ "Respond to this message with the URL starting with 'fb-workchat-sso://' that it attempts to redirect to.\n"
+ "If your browser says 'Address not understood' (like firefox), copy it from the address bar.\n"
+ "Otherwise you might have to right click -> view source in the last page and find it there. Good luck!"),
+ url,
+ FALSE, FALSE, NULL,
+ _("OK"), G_CALLBACK(fb_cb_work_sso_input_cb),
+ _("Cancel"), G_CALLBACK(fb_cb_work_sso_cancel_cb),
+ purple_connection_get_account(gc), NULL, NULL, fata);
+
+
+ g_free(url);
+}
+
+
+static void
fb_mark_read(FbData *fata, FbId id, gboolean thread)
{
FbApi *api;
@@ -1056,6 +1109,10 @@ fb_login(PurpleAccount *acct)
"typing",
G_CALLBACK(fb_cb_api_typing),
fata);
+ g_signal_connect(api,
+ "work-sso-login",
+ G_CALLBACK(fb_cb_api_work_sso_login),
+ fata);
purple_signal_connect(convh,
"conversation-updated",
@@ -1073,7 +1130,11 @@ fb_login(PurpleAccount *acct)
pass = purple_connection_get_password(gc);
purple_connection_update_progress(gc, _("Authenticating"),
1, 4);
- fb_api_auth(api, user, pass);
+ if (purple_account_get_bool(acct, "work", FALSE)) {
+ fb_api_work_login(api, user, pass);
+ } else {
+ fb_api_auth(api, user, pass, NULL);
+ }
return;
}
@@ -1678,6 +1739,11 @@ purple_init_plugin(PurplePlugin *plugin)
"incoming messages"),
"group-chat-open", TRUE);
opts = g_list_prepend(opts, opt);
+
+ opt = purple_account_option_bool_new(_("Login as a Workplace account"),
+ "work", FALSE);
+ opts = g_list_prepend(opts, opt);
+
pinfo.protocol_options = g_list_reverse(opts);
inited = TRUE;
Index: purple-facebook-0.9.6/pidgin/libpurple/protocols/facebook/util.c
===================================================================
--- purple-facebook-0.9.6.orig/pidgin/libpurple/protocols/facebook/util.c
+++ purple-facebook-0.9.6/pidgin/libpurple/protocols/facebook/util.c
@@ -564,3 +564,57 @@ fb_util_zlib_inflate(const GByteArray *b
g_object_unref(conv);
return ret;
}
+
+gchar *
+fb_util_urlsafe_base64_encode(const guchar *data, gsize len)
+{
+ gchar *out = g_base64_encode(data, len);
+ gchar *c;
+
+ for (c = out; *c; c++) {
+ if (*c == '+') {
+ *c = '-';
+ } else if (*c == '/') {
+ *c = '_';
+ } else if (*c == '=') {
+ *c = '\0';
+ break;
+ }
+ }
+
+ return out;
+}
+
+/* bitlbee compat */
+static void
+random_bytes(guint8 *buf, gsize len)
+{
+ gsize i;
+
+ for (i = 0; i < len; i++) {
+ buf[i] = (guint8) g_random_int_range(0, 256);
+ }
+}
+
+void
+fb_util_gen_sso_verifier(gchar **challenge, gchar **verifier, gchar **req_id)
+{
+ guint8 buf[32];
+ GChecksum *gc;
+ gsize digest_len = sizeof buf;
+
+ random_bytes(buf, sizeof buf);
+
+ *verifier = fb_util_urlsafe_base64_encode(buf, sizeof buf);
+
+ gc = g_checksum_new(G_CHECKSUM_SHA256);
+ g_checksum_update(gc, (guchar *) *verifier, -1);
+ g_checksum_get_digest(gc, buf, &digest_len);
+ g_checksum_free(gc);
+
+ *challenge = fb_util_urlsafe_base64_encode(buf, sizeof buf);
+
+ random_bytes(buf, 3);
+
+ *req_id = fb_util_urlsafe_base64_encode(buf, 3);
+}
Index: purple-facebook-0.9.6/pidgin/libpurple/protocols/facebook/util.h
===================================================================
--- purple-facebook-0.9.6.orig/pidgin/libpurple/protocols/facebook/util.h
+++ purple-facebook-0.9.6/pidgin/libpurple/protocols/facebook/util.h
@@ -347,4 +347,30 @@ fb_util_zlib_deflate(const GByteArray *b
GByteArray *
fb_util_zlib_inflate(const GByteArray *bytes, GError **error);
+/**
+ * fb_util_urlsafe_base64_encode:
+ * @data: the binary data to encode.
+ * @len: the length of data
+ *
+ * Wrapper around g_base64_encode() which substitutes '-' instead of '+'
+ * and '_' instead of '/' and removes the padding
+ *
+ * Returns: A newly allocated string.
+ */
+
+gchar *
+fb_util_urlsafe_base64_encode(const guchar *data, gsize len);
+
+/**
+ * fb_util_gen_sso_verifier:
+ * @challenge: base64 of sha256 of verifier
+ * @verifier: base64 of random data
+ * @req_id: base64 of random data
+ *
+ * Generates the challenge/response parameters used for the workchat SSO auth.
+ * All parameters are output parameters.
+ */
+void
+fb_util_gen_sso_verifier(gchar **challenge, gchar **verifier, gchar **req_id);
+
#endif /* _FACEBOOK_UTIL_H_ */
Index: purple-facebook-0.9.6/pidgin/libpurple/protocols/facebook/data.c
===================================================================
--- purple-facebook-0.9.6.orig/pidgin/libpurple/protocols/facebook/data.c
+++ purple-facebook-0.9.6/pidgin/libpurple/protocols/facebook/data.c
@@ -219,6 +219,13 @@ fb_data_load(FbData *fata)
ret = FALSE;
}
+ if (purple_account_get_bool(acct, "work", FALSE)) {
+ g_value_init(&val, G_TYPE_BOOLEAN);
+ g_value_set_boolean(&val, TRUE);
+ g_object_set_property(G_OBJECT(priv->api), "work", &val);
+ g_value_unset(&val);
+ }
+
fb_api_rehash(priv->api);
return ret;
}

46
SOURCES/purple-facebook-0.9.6-option-show-inactive-as-away.patch

@ -0,0 +1,46 @@
Index: purple-facebook-0.9.6/pidgin/libpurple/protocols/facebook/facebook.c
===================================================================
--- purple-facebook-0.9.6.orig/pidgin/libpurple/protocols/facebook/facebook.c
+++ purple-facebook-0.9.6/pidgin/libpurple/protocols/facebook/facebook.c
@@ -299,6 +299,10 @@ fb_cb_api_contacts(FbApi *api, GSList *u
fb_data_image_add(fata, user->icon, fb_cb_icon,
bdy, NULL);
}
+
+ if (purple_account_get_bool(acct, "inactive-as-away", FALSE)) {
+ purple_protocol_got_user_status(acct, uid, purple_primitive_get_id_from_type(PURPLE_STATUS_AWAY), NULL);
+ }
}
fb_data_image_queue(fata);
@@ -351,6 +355,10 @@ fb_cb_api_contacts_delta(FbApi *api, GSL
purple_blist_add_buddy(bdy, NULL, grp, NULL);
purple_buddy_set_server_alias(bdy, user->name);
+
+ if (purple_account_get_bool(acct, "inactive-as-away", FALSE)) {
+ purple_protocol_got_user_status(acct, uid, purple_primitive_get_id_from_type(PURPLE_STATUS_AWAY), NULL);
+ }
}
for (l = removed; l != NULL; l = l->next) {
@@ -631,7 +639,7 @@ fb_cb_api_presences(FbApi *api, GSList *
if (pres->active) {
pstat = PURPLE_STATUS_AVAILABLE;
} else {
- pstat = PURPLE_STATUS_OFFLINE;
+ pstat = purple_account_get_bool(acct, "inactive-as-away", FALSE) ? PURPLE_STATUS_AWAY : PURPLE_STATUS_OFFLINE;
}
FB_ID_TO_STR(pres->uid, uid);
@@ -1740,6 +1748,10 @@ purple_init_plugin(PurplePlugin *plugin)
"group-chat-open", TRUE);
opts = g_list_prepend(opts, opt);
+ opt = purple_account_option_bool_new(_("Show inactive buddies as away"),
+ "inactive-as-away", FALSE);
+ opts = g_list_prepend(opts, opt);
+
opt = purple_account_option_bool_new(_("Login as a Workplace account"),
"work", FALSE);
opts = g_list_prepend(opts, opt);

89
SPECS/purple-facebook.spec

@ -6,54 +6,53 @@
%filter_setup %filter_setup
%endif %endif


%global sha 9ff9acf9fa14
%global sha_rel .%{sha}
%global sha_ver -%{sha}


Name: purple-facebook
Version: 0.9.6
Release: 1%{?dist}
Summary: Facebook protocol plugin for purple2


Name: purple-facebook License: GPLv2+
Version: 0.9.5 URL: https://github.com/dequis/%{name}
Release: 4%{sha_rel}%{?dist} Source0: %{url}/releases/download/v%{version}/%{name}-%{version}.tar.gz
Summary: Facebook protocol plugin for purple2

License: GPLv2+
URL: https://github.com/dequis/%{name}
Source0: %{url}/releases/download/v%{version}%{sha_ver}/%{name}-%{version}%{sha_ver}.tar.gz


# Backported from upstream. # Backported from upstream.
# https://github.com/dequis/purple-facebook/issues/403 # https://github.com/dequis/purple-facebook/tree/wip-work-chat
Patch0: %{name}-0.9.5-glib-compiled-with-debug.patch Patch0000: %{name}-0.9.6-fb-work-chat.patch
# https://github.com/dequis/purple-facebook/commit/dc655d0556929cbbb0efbad360600d5987d740c5
Patch1: %{name}-0.9.5-contacts.patch # Backported from upstream pull-requests.
# https://github.com/dequis/purple-facebook/commit/8f124c72b969a5b688ad54695689c5d0aed53469 # https://github.com/dequis/purple-facebook/pull/414
Patch2: %{name}-0.9.5-glib-error-cast-bug-2-electric-boogaloo.patch Patch1000: %{name}-0.9.6-option-show-inactive-as-away.patch
# https://github.com/dequis/purple-facebook/commit/ef6ae47b8bf971d3f2803b1552b7debc59429dc1
Patch3: %{name}-0.9.5-async-sockets-are-hard.patch BuildRequires: gcc

BuildRequires: glib2-devel >= 2.28
BuildRequires: json-glib-devel BuildRequires: json-glib-devel >= 0.14
BuildRequires: libpurple-devel BuildRequires: libpurple-devel < 3.00
BuildRequires: zlib-devel BuildRequires: zlib-devel


%description %description
Purple Facebook implements the Facebook Messenger protocol for pidgin, Purple Facebook implements the Facebook Messenger protocol for pidgin,
finch, and libpurple. While the primary implementation is for purple3, finch, and libpurple. While the primary implementation is for purple3,
this plugin is back-ported for purple2. this plugin is back-ported for purple2.


This project is not affiliated with Facebook, Inc.



%prep %prep
%autosetup -n %{name}-%{version}%{sha_ver} -p 1 %autosetup -p 1




%build %build
%configure \ /bin/touch aclocal.m4 configure Makefile.am Makefile.in
--disable-silent-rules \ %configure \
--enable-warnings --disable-silent-rules \
--enable-warnings
%make_build %make_build




%install %install
%make_install %make_install
%{__rm} -f %{buildroot}%{_libdir}/purple-2/libfacebook.*a %{_bindir}/find %{buildroot}%{_libdir} -name '*.*a' -print -delete




%check %check
@ -67,6 +66,40 @@ this plugin is back-ported for purple2.




%changelog %changelog
* Sun Jan 13 2019 Björn Esser <besser82@fedoraproject.org> - 0.9.6-1
- New upstream release
- Remove patches being applied upstream
- Refactor left patches for alignment

* Mon Jan 07 2019 Björn Esser <besser82@fedoraproject.org> - 0.9.5-13.9ff9acf9fa14
- Add patch to check and link zlib

* Mon Jan 07 2019 Björn Esser <besser82@fedoraproject.org> - 0.9.5-12.9ff9acf9fa14
- Add patch from upstream fixing 'Failed to get sync_sequence_id' (#1663599)

* Sat Oct 13 2018 Björn Esser <besser82@fedoraproject.org> - 0.9.5-11.9ff9acf9fa14
- Backported upstream patch for Facebook Work Chat

* Sat Oct 13 2018 Björn Esser <besser82@fedoraproject.org> - 0.9.5-10.9ff9acf9fa14
- Optimize sortability of patches
- Refactor patches for smooth alignment
- Remove empty line from spec file

* Fri Oct 05 2018 Björn Esser <besser82@fedoraproject.org> - 0.9.5-9.9ff9acf9fa14
- Update Patch101 to match upstream PR

* Thu Oct 04 2018 Björn Esser <besser82@fedoraproject.org> - 0.9.5-8.9ff9acf9fa14
- Backported pull-request fixing compiler warnings

* Thu Oct 04 2018 Björn Esser <besser82@fedoraproject.org> - 0.9.5-7.9ff9acf9fa14
- Add disclaimer to %%description

* Thu Oct 04 2018 Björn Esser <besser82@fedoraproject.org> - 0.9.5-6.9ff9acf9fa14
- Backported pull-request adding an option to show inactive friends as away

* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.5-5.9ff9acf9fa14
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild

* Fri Mar 23 2018 Björn Esser <besser82@fedoraproject.org> - 0.9.5-4.9ff9acf9fa14 * Fri Mar 23 2018 Björn Esser <besser82@fedoraproject.org> - 0.9.5-4.9ff9acf9fa14
- Add patch from upstream fixing connection problem with TLS 1.3 - Add patch from upstream fixing connection problem with TLS 1.3
- Add patch from upstream fixing another segfault with newer glib - Add patch from upstream fixing another segfault with newer glib

Loading…
Cancel
Save