Changes in lib/oauth2.c [ca8037e:3bda2c2]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
lib/oauth2.c
rca8037e r3bda2c2 2 2 * * 3 3 * BitlBee - An IRC to IM gateway * 4 * Simple OAuth 2 client (consumer) implementation.*4 * Simple OAuth client (consumer) implementation. * 5 5 * * 6 * Copyright 2010-201 3Wilmer van der Gaast <wilmer@gaast.net> *6 * Copyright 2010-2011 Wilmer van der Gaast <wilmer@gaast.net> * 7 7 * * 8 8 * This program is free software; you can redistribute it and/or modify * … … 22 22 \***************************************************************************/ 23 23 24 /* Out of protest, I should rename this file. OAuth2 is a pathetic joke, and25 of all things, DEFINITELY NOT A STANDARD. The only thing various OAuth226 implementations have in common is that name, wrongfully stolen from27 a pretty nice standard called OAuth 1.0a. That, and the fact that they28 use JSON. Wait, no, Facebook's version doesn't use JSON. For some of its29 responses.30 31 Apparently too many people were too retarded to comprehend the elementary32 bits of crypto in OAuth 1.0a (took me one afternoon to implement) so33 the standard was replaced with what comes down to a complicated scheme34 around what's really just application-specific passwords.35 36 And then a bunch of mostly incompatible implementations. Great work, guys.37 38 http://hueniverse.com/2012/07/oauth-2-0-and-the-road-to-hell/ */39 40 24 #include <glib.h> 41 25 #include "http_client.h" 42 26 #include "oauth2.h" 43 27 #include "oauth.h" 44 #include "json.h"45 #include "json_util.h"46 28 #include "url.h" 47 29 … … 62 44 }; 63 45 46 static char *oauth2_json_dumb_get( const char *json, const char *key ); 64 47 static void oauth2_access_token_done( struct http_request *req ); 65 48 … … 96 79 "Content-Type: application/x-www-form-urlencoded\r\n" 97 80 "Content-Length: %zd\r\n" 81 "Connection: close\r\n" 98 82 "\r\n" 99 83 "%s", url_p.file, url_p.host, strlen( args_s ), args_s ); … … 115 99 } 116 100 117 static char* oauth2_parse_error( json_value *e )118 {119 /* This does a reasonable job with some of the flavours of error120 responses I've seen. Because apparently it's not standardised. */121 122 if( e->type == json_object )123 {124 /* Facebook style */125 const char *msg = json_o_str( e, "message" );126 const char *type = json_o_str( e, "type" );127 json_value *code_o = json_o_get( e, "code" );128 int code = 0;129 130 if( code_o && code_o->type == json_integer )131 code = code_o->u.integer;132 133 return g_strdup_printf( "Error %d: %s", code, msg ? msg : type ? type : "Unknown error" );134 }135 else if( e->type == json_string )136 {137 return g_strdup( e->u.string.ptr );138 }139 return NULL;140 }141 142 101 static void oauth2_access_token_done( struct http_request *req ) 143 102 { 144 103 struct oauth2_access_token_data *cb_data = req->data; 145 char *atoken = NULL, *rtoken = NULL , *error = NULL;104 char *atoken = NULL, *rtoken = NULL; 146 105 char *content_type; 147 106 … … 151 110 content_type = get_rfc822_header( req->reply_headers, "Content-Type", 0 ); 152 111 153 if( content_type && ( strstr( content_type, "application/json" ) || 154 strstr( content_type, "text/javascript" ) ) ) 112 if( req->status_code != 200 ) 155 113 { 156 json_value *js = json_parse( req->reply_body ); 157 if( js && js->type == json_object ) 158 { 159 JSON_O_FOREACH( js, k, v ) 160 { 161 if( strcmp( k, "error" ) == 0 ) 162 error = oauth2_parse_error( v ); 163 if( v->type != json_string ) 164 continue; 165 if( strcmp( k, "access_token" ) == 0 ) 166 atoken = g_strdup( v->u.string.ptr ); 167 if( strcmp( k, "refresh_token" ) == 0 ) 168 rtoken = g_strdup( v->u.string.ptr ); 169 } 170 } 171 json_value_free( js ); 114 } 115 else if( content_type && strstr( content_type, "application/json" ) ) 116 { 117 atoken = oauth2_json_dumb_get( req->reply_body, "access_token" ); 118 rtoken = oauth2_json_dumb_get( req->reply_body, "refresh_token" ); 172 119 } 173 120 else … … 183 130 if( getenv( "BITLBEE_DEBUG" ) ) 184 131 printf( "Extracted atoken=%s rtoken=%s\n", atoken, rtoken ); 185 if( !atoken && !rtoken && !error )186 error = g_strdup( "Unusuable response" );187 132 188 cb_data->func( cb_data->data, atoken, rtoken , error);133 cb_data->func( cb_data->data, atoken, rtoken ); 189 134 g_free( content_type ); 190 135 g_free( atoken ); 191 136 g_free( rtoken ); 192 g_free( error );193 137 g_free( cb_data ); 194 138 } 139 140 /* Super dumb. I absolutely refuse to use/add a complete json parser library 141 (adding a new dependency to BitlBee for the first time in.. 6 years?) just 142 to parse 100 bytes of data. So I have to do my own parsing because OAuth2 143 dropped support for XML. (GRRR!) This is very dumb and for example won't 144 work for integer values, nor will it strip/handle backslashes. */ 145 static char *oauth2_json_dumb_get( const char *json, const char *key ) 146 { 147 int is_key = 0; /* 1 == reading key, 0 == reading value */ 148 int found_key = 0; 149 150 while( json && *json ) 151 { 152 /* Grab strings and see if they're what we're looking for. */ 153 if( *json == '"' || *json == '\'' ) 154 { 155 char q = *json; 156 const char *str_start; 157 json ++; 158 str_start = json; 159 160 while( *json ) 161 { 162 /* \' and \" are not string terminators. */ 163 if( *json == '\\' && json[1] == q ) 164 json ++; 165 /* But without a \ it is. */ 166 else if( *json == q ) 167 break; 168 json ++; 169 } 170 if( *json == '\0' ) 171 return NULL; 172 173 if( is_key && strncmp( str_start, key, strlen( key ) ) == 0 ) 174 { 175 found_key = 1; 176 } 177 else if( !is_key && found_key ) 178 { 179 char *ret = g_memdup( str_start, json - str_start + 1 ); 180 ret[json-str_start] = '\0'; 181 return ret; 182 } 183 184 } 185 else if( *json == '{' || *json == ',' ) 186 { 187 found_key = 0; 188 is_key = 1; 189 } 190 else if( *json == ':' ) 191 is_key = 0; 192 193 json ++; 194 } 195 196 return NULL; 197 }
Note: See TracChangeset
for help on using the changeset viewer.