/soc/2015/jgeboski/facebook: 7c454f51b56b: facebook: handle auth...

James Geboski <[email protected]>
Newsgroups gmane.comp.gnome.gaim.cvs
Message-ID <[email protected]>
Changeset: 7c454f51b56b8d71f4f9ba444c8d60c7848d226e
Author:	 James Geboski <[email protected]>
Date:	 2015-07-27 16:43 -0400
Branch:	 facebook
URL: https://hg.pidgin.im/soc/2015/jgeboski/facebook/rev/7c454f51b56b

Description:

facebook: handle authentication errors

Currently, authentication errors are essentially ignored with ambiguous
error messages. This is due to errors never being fully parsed for the
failure reason. This issue leads to the user being unaware of the cause
as it often breaks long after the password has been changed.

This extends the error parsing as well as refactors some of the error
handling mechanisms.

diffstat:

 libpurple/protocols/facebook/api.c      |  103 ++++++++++++++++++++++++-------
 libpurple/protocols/facebook/api.h      |    3 +-
 libpurple/protocols/facebook/facebook.c |   25 +++----
 3 files changed, 93 insertions(+), 38 deletions(-)

diffs (198 lines):

diff --git a/libpurple/protocols/facebook/api.c b/libpurple/protocols/facebook/api.c
--- a/libpurple/protocols/facebook/api.c
+++ b/libpurple/protocols/facebook/api.c
@@ -306,13 +306,24 @@ fb_api_error_quark(void)
 static gboolean
 fb_api_json_chk(FbApi *api, gconstpointer data, gsize size, JsonNode **node)
 {
+	FbApiError errc = FB_API_ERROR_GENERAL;
 	FbApiPrivate *priv;
-	gboolean success = FALSE;
+	gboolean success = TRUE;
 	gchar *msg = NULL;
+	gchar *str;
 	GError *err = NULL;
 	gint64 code;
+	guint i;
 	JsonNode *root;
 
+	static const gchar *exprs[] = {
+		"$.error.message",
+		"$.error.summary",
+		"$.error_msg",
+		"$.errorCode",
+		"$.failedSend.errorMessage",
+	};
+
 	g_return_val_if_fail(FB_IS_API(api), FALSE);
 	priv = api->priv;
 
@@ -325,37 +336,71 @@ fb_api_json_chk(FbApi *api, gconstpointe
 	root = fb_json_node_new(data, size, &err);
 	FB_API_ERROR_CHK(api, err, return FALSE);
 
-	if (fb_json_node_chk_str(root, "$.error.summary", &msg) ||
-	    fb_json_node_chk_str(root, "$.failedSend.errorMessage", &msg))
+	if (fb_json_node_chk_int(root, "$.error_code", &code) &&
+	    (code == 401))
 	{
-		fb_api_error(api, FB_API_ERROR_GENERAL, "%s", msg);
-	} else if (fb_json_node_chk_int(root, "$.error_code", &code)) {
-		if (!fb_json_node_chk_str(root, "$.error_msg", &msg)) {
-			msg = g_strdup(_("Generic error"));
-		}
+		errc = FB_API_ERROR_AUTH;
+		success = FALSE;
 
-		fb_api_error(api, FB_API_ERROR_GENERAL, "%s", msg);
-	} else if (fb_json_node_chk_str(root, "$.errorCode", &msg)) {
-		if ((g_ascii_strcasecmp(msg, "ERROR_QUEUE_NOT_FOUND") == 0) ||
-		    (g_ascii_strcasecmp(msg, "ERROR_QUEUE_LOST") == 0))
-		{
-			g_free(priv->stoken);
-			priv->stoken = NULL;
-		}
+		g_free(priv->stoken);
+		priv->stoken = NULL;
 
-		fb_api_error(api, FB_API_ERROR_GENERAL, "%s", msg);
-	} else {
-		success = TRUE;
+		g_free(priv->token);
+		priv->token = NULL;
 	}
 
-	if (success && (node != NULL)) {
+	if (fb_json_node_chk_str(root, "$.error.type", &str) &&
+	    (g_ascii_strcasecmp(str, "OAuthException") == 0))
+	{
+		errc = FB_API_ERROR_AUTH;
+		success = FALSE;
+		g_free(str);
+
+		g_free(priv->stoken);
+		priv->stoken = NULL;
+
+		g_free(priv->token);
+		priv->token = NULL;
+
+	}
+
+	if (fb_json_node_chk_str(root, "$.errorCode", &str) && (
+		(g_ascii_strcasecmp(str, "ERROR_QUEUE_NOT_FOUND") == 0) ||
+		(g_ascii_strcasecmp(str, "ERROR_QUEUE_LOST") == 0)))
+	{
+		errc = FB_API_ERROR_AUTH;
+		success = FALSE;
+		g_free(str);
+
+		g_free(priv->stoken);
+		priv->stoken = NULL;
+	}
+
+	for (i = 0; i < G_N_ELEMENTS(exprs); i++) {
+		if (fb_json_node_chk_str(root, exprs[i], &msg)) {
+			success = FALSE;
+			break;
+		}
+	}
+
+	if (!success && (msg == NULL)) {
+		msg = g_strdup(_("Unknown error"));
+	}
+
+	if (msg != NULL) {
+		fb_api_error(api, errc, "%s", msg);
+		json_node_free(root);
+		g_free(msg);
+		return FALSE;
+	}
+
+	if (node != NULL) {
 		*node = root;
 	} else {
 		json_node_free(root);
 	}
 
-	g_free(msg);
-	return success;
+	return TRUE;
 }
 
 static gboolean
@@ -388,11 +433,21 @@ fb_api_http_chk(FbApi *api, PurpleHttpCo
 		              (gint) size, data);
 	}
 
-	if (!fb_http_error_chk(res, &err)) {
+	if ((root == NULL) && fb_http_error_chk(res, &err)) {
+		return TRUE;
+	}
+
+	/* Rudimentary check to prevent wrongful error parsing */
+	if ((size < 2) || (data[0] != '{') || (data[size - 1] != '}')) {
 		FB_API_ERROR_CHK(api, err, return FALSE);
 	}
 
-	return (root == NULL) || fb_api_json_chk(api, data, size, root);
+	if (fb_api_json_chk(api, data, size, root)) {
+		FB_API_ERROR_CHK(api, err, return FALSE);
+		return TRUE;
+	}
+
+	return FALSE;
 }
 
 static PurpleHttpConnection *
diff --git a/libpurple/protocols/facebook/api.h b/libpurple/protocols/facebook/api.h
--- a/libpurple/protocols/facebook/api.h
+++ b/libpurple/protocols/facebook/api.h
@@ -87,7 +87,8 @@ typedef struct _FbApiHttpInfo FbApiHttpI
 
 enum _FbApiError
 {
-	FB_API_ERROR_GENERAL
+	FB_API_ERROR_GENERAL,
+	FB_API_ERROR_AUTH
 };
 
 struct _FbApi
diff --git a/libpurple/protocols/facebook/facebook.c b/libpurple/protocols/facebook/facebook.c
--- a/libpurple/protocols/facebook/facebook.c
+++ b/libpurple/protocols/facebook/facebook.c
@@ -170,23 +170,22 @@ static void
 fb_cb_api_error(FbApi *api, GError *error, gpointer data)
 {
 	FbData *fata = data;
-	gboolean nfatal;
 	PurpleConnection *gc;
-	PurpleConnectionError reason;
+	PurpleConnectionError errc;
 
-	/* Non-fatal errors */
-	nfatal = (error->domain == FB_API_ERROR) ||
-	         (error->domain == FB_MQTT_ERROR);
-
-	/* Non-fatal HTTP errors */
-	nfatal |= (error->domain == FB_HTTP_ERROR) &&
-	          ((error->code < 400) || (error->code > 500));
-
-	reason = (nfatal) ? PURPLE_CONNECTION_ERROR_NETWORK_ERROR
-	                  : PURPLE_CONNECTION_ERROR_OTHER_ERROR;
+	if ((error->domain == FB_HTTP_ERROR) &&
+	    (error->code >= 400) &&
+	    (error->code <= 500))
+	{
+		errc = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
+	} else if (g_error_matches(error, FB_API_ERROR, FB_API_ERROR_AUTH)) {
+		errc = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
+	} else {
+		errc = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+	}
 
 	gc = fb_data_get_connection(fata);
-	purple_connection_error(gc, reason, error->message);
+	purple_connection_error(gc, errc, error->message);
 }
 
 static void

_______________________________________________
Commits mailing list
[email protected]
https://pidgin.im/cgi-bin/mailman/listinfo/commits
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.