Changes in lib/oauth2.c [3bda2c2:ca8037e]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
lib/oauth2.c
r3bda2c2 rca8037e 2 2 * * 3 3 * BitlBee - An IRC to IM gateway * 4 * Simple OAuth client (consumer) implementation.*4 * Simple OAuth2 client (consumer) implementation. * 5 5 * * 6 * Copyright 2010-201 1Wilmer van der Gaast <wilmer@gaast.net> *6 * Copyright 2010-2013 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, and 25 of all things, DEFINITELY NOT A STANDARD. The only thing various OAuth2 26 implementations have in common is that name, wrongfully stolen from 27 a pretty nice standard called OAuth 1.0a. That, and the fact that they 28 use JSON. Wait, no, Facebook's version doesn't use JSON. For some of its 29 responses. 30 31 Apparently too many people were too retarded to comprehend the elementary 32 bits of crypto in OAuth 1.0a (took me one afternoon to implement) so 33 the standard was replaced with what comes down to a complicated scheme 34 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 24 40 #include <glib.h> 25 41 #include "http_client.h" 26 42 #include "oauth2.h" 27 43 #include "oauth.h" 44 #include "json.h" 45 #include "json_util.h" 28 46 #include "url.h" 29 47 … … 44 62 }; 45 63 46 static char *oauth2_json_dumb_get( const char *json, const char *key );47 64 static void oauth2_access_token_done( struct http_request *req ); 48 65 … … 79 96 "Content-Type: application/x-www-form-urlencoded\r\n" 80 97 "Content-Length: %zd\r\n" 81 "Connection: close\r\n"82 98 "\r\n" 83 99 "%s", url_p.file, url_p.host, strlen( args_s ), args_s ); … … 99 115 } 100 116 117 static char* oauth2_parse_error( json_value *e ) 118 { 119 /* This does a reasonable job with some of the flavours of error 120 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 101 142 static void oauth2_access_token_done( struct http_request *req ) 102 143 { 103 144 struct oauth2_access_token_data *cb_data = req->data; 104 char *atoken = NULL, *rtoken = NULL ;145 char *atoken = NULL, *rtoken = NULL, *error = NULL; 105 146 char *content_type; 106 147 … … 110 151 content_type = get_rfc822_header( req->reply_headers, "Content-Type", 0 ); 111 152 112 if( req->status_code != 200 ) 153 if( content_type && ( strstr( content_type, "application/json" ) || 154 strstr( content_type, "text/javascript" ) ) ) 113 155 { 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" ); 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 ); 119 172 } 120 173 else … … 130 183 if( getenv( "BITLBEE_DEBUG" ) ) 131 184 printf( "Extracted atoken=%s rtoken=%s\n", atoken, rtoken ); 185 if( !atoken && !rtoken && !error ) 186 error = g_strdup( "Unusuable response" ); 132 187 133 cb_data->func( cb_data->data, atoken, rtoken );188 cb_data->func( cb_data->data, atoken, rtoken, error ); 134 189 g_free( content_type ); 135 190 g_free( atoken ); 136 191 g_free( rtoken ); 192 g_free( error ); 137 193 g_free( cb_data ); 138 194 } 139 140 /* Super dumb. I absolutely refuse to use/add a complete json parser library141 (adding a new dependency to BitlBee for the first time in.. 6 years?) just142 to parse 100 bytes of data. So I have to do my own parsing because OAuth2143 dropped support for XML. (GRRR!) This is very dumb and for example won't144 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.