Index: lib/oauth2.c
===================================================================
--- lib/oauth2.c	(revision ca8037e28d09ed96448509316a935eb130e6d3db)
+++ lib/oauth2.c	(revision 3bda2c2bc34fa21ef143f068a4f4f3feb7eb48d5)
@@ -2,7 +2,7 @@
 *                                                                           *
 *  BitlBee - An IRC to IM gateway                                           *
-*  Simple OAuth2 client (consumer) implementation.                          *
+*  Simple OAuth client (consumer) implementation.                           *
 *                                                                           *
-*  Copyright 2010-2013 Wilmer van der Gaast <wilmer@gaast.net>              *
+*  Copyright 2010-2011 Wilmer van der Gaast <wilmer@gaast.net>              *
 *                                                                           *
 *  This program is free software; you can redistribute it and/or modify     *
@@ -22,26 +22,8 @@
 \***************************************************************************/
 
-/* Out of protest, I should rename this file. OAuth2 is a pathetic joke, and
-   of all things, DEFINITELY NOT A STANDARD. The only thing various OAuth2
-   implementations have in common is that name, wrongfully stolen from
-   a pretty nice standard called OAuth 1.0a. That, and the fact that they
-   use JSON. Wait, no, Facebook's version doesn't use JSON. For some of its
-   responses.
-   
-   Apparently too many people were too retarded to comprehend the elementary
-   bits of crypto in OAuth 1.0a (took me one afternoon to implement) so
-   the standard was replaced with what comes down to a complicated scheme
-   around what's really just application-specific passwords.
-   
-   And then a bunch of mostly incompatible implementations. Great work, guys.
-   
-   http://hueniverse.com/2012/07/oauth-2-0-and-the-road-to-hell/ */
-
 #include <glib.h>
 #include "http_client.h"
 #include "oauth2.h"
 #include "oauth.h"
-#include "json.h"
-#include "json_util.h"
 #include "url.h"
 
@@ -62,4 +44,5 @@
 };
 
+static char *oauth2_json_dumb_get( const char *json, const char *key );
 static void oauth2_access_token_done( struct http_request *req );
 
@@ -96,4 +79,5 @@
 	                     "Content-Type: application/x-www-form-urlencoded\r\n"
 	                     "Content-Length: %zd\r\n"
+	                     "Connection: close\r\n"
 	                     "\r\n"
 	                     "%s", url_p.file, url_p.host, strlen( args_s ), args_s );
@@ -115,33 +99,8 @@
 }
 
-static char* oauth2_parse_error( json_value *e )
-{
-	/* This does a reasonable job with some of the flavours of error
-	   responses I've seen. Because apparently it's not standardised. */
-	
-	if( e->type == json_object )
-	{
-		/* Facebook style */
-		const char *msg = json_o_str( e, "message" );
-		const char *type = json_o_str( e, "type" );
-		json_value *code_o = json_o_get( e, "code" );
-		int code = 0;
-		
-		if( code_o && code_o->type == json_integer )
-			code = code_o->u.integer;
-		
-		return g_strdup_printf( "Error %d: %s", code, msg ? msg : type ? type : "Unknown error" );
-	}
-	else if( e->type == json_string )
-	{
-		return g_strdup( e->u.string.ptr );
-	}
-	return NULL;
-}
-
 static void oauth2_access_token_done( struct http_request *req )
 {
 	struct oauth2_access_token_data *cb_data = req->data;
-	char *atoken = NULL, *rtoken = NULL, *error = NULL;
+	char *atoken = NULL, *rtoken = NULL;
 	char *content_type;
 	
@@ -151,23 +110,11 @@
 	content_type = get_rfc822_header( req->reply_headers, "Content-Type", 0 );
 	
-	if( content_type && ( strstr( content_type, "application/json" ) ||
-	                      strstr( content_type, "text/javascript" ) ) )
+	if( req->status_code != 200 )
 	{
-		json_value *js = json_parse( req->reply_body );
-		if( js && js->type == json_object )
-		{
-			JSON_O_FOREACH( js, k, v )
-			{
-				if( strcmp( k, "error" ) == 0 )
-					error = oauth2_parse_error( v );
-				if( v->type != json_string )
-					continue;
-				if( strcmp( k, "access_token" ) == 0 )
-					atoken = g_strdup( v->u.string.ptr );
-				if( strcmp( k, "refresh_token" ) == 0 )
-					rtoken = g_strdup( v->u.string.ptr );
-			}
-		}
-		json_value_free( js );
+	}
+	else if( content_type && strstr( content_type, "application/json" ) )
+	{
+		atoken = oauth2_json_dumb_get( req->reply_body, "access_token" );
+		rtoken = oauth2_json_dumb_get( req->reply_body, "refresh_token" );
 	}
 	else
@@ -183,12 +130,68 @@
 	if( getenv( "BITLBEE_DEBUG" ) )
 		printf( "Extracted atoken=%s rtoken=%s\n", atoken, rtoken );
-	if( !atoken && !rtoken && !error )
-		error = g_strdup( "Unusuable response" );
 	
-	cb_data->func( cb_data->data, atoken, rtoken, error );
+	cb_data->func( cb_data->data, atoken, rtoken );
 	g_free( content_type );
 	g_free( atoken );
 	g_free( rtoken );
-	g_free( error );
 	g_free( cb_data );
 }
+
+/* Super dumb. I absolutely refuse to use/add a complete json parser library
+   (adding a new dependency to BitlBee for the first time in.. 6 years?) just
+   to parse 100 bytes of data. So I have to do my own parsing because OAuth2
+   dropped support for XML. (GRRR!) This is very dumb and for example won't
+   work for integer values, nor will it strip/handle backslashes. */
+static char *oauth2_json_dumb_get( const char *json, const char *key )
+{
+	int is_key = 0; /* 1 == reading key, 0 == reading value */
+	int found_key = 0;
+		
+	while( json && *json )
+	{
+		/* Grab strings and see if they're what we're looking for. */
+		if( *json == '"' || *json == '\'' )
+		{
+			char q = *json;
+			const char *str_start;
+			json ++;
+			str_start = json;
+			
+			while( *json )
+			{
+				/* \' and \" are not string terminators. */
+				if( *json == '\\' && json[1] == q )
+					json ++;
+				/* But without a \ it is. */
+				else if( *json == q )
+					break;
+				json ++;
+			}
+			if( *json == '\0' )
+				return NULL;
+			
+			if( is_key && strncmp( str_start, key, strlen( key ) ) == 0 )
+			{
+				found_key = 1;
+			}
+			else if( !is_key && found_key )
+			{
+				char *ret = g_memdup( str_start, json - str_start + 1 );
+				ret[json-str_start] = '\0';
+				return ret;
+			}
+			
+		}
+		else if( *json == '{' || *json == ',' )
+		{
+			found_key = 0;
+			is_key = 1;
+		}
+		else if( *json == ':' )
+			is_key = 0;
+		
+		json ++;
+	}
+	
+	return NULL;
+}
