00001 #ifdef HAVE_CONFIG_H
00002 #include "config.h"
00003 #endif
00004
00005 #define _GNU_SOURCE
00006 #include <microfeed-provider/microfeedhttp.h>
00007 #include <microfeed-common/microfeedmisc.h>
00008 #include <microfeed-common/microfeedthread.h>
00009 #include <microfeed-common/microfeedstore.h>
00010
00011 #include <curl/curl.h>
00012 #include <openssl/hmac.h>
00013 #include <openssl/crypto.h>
00014
00015 #include <string.h>
00016
00017 typedef struct _Buffer Buffer;
00018
00019 typedef struct _OAuth OAuth;
00020
00021 struct _MicrofeedHttp {
00022 Buffer* buffer;
00023 CURL* curl;
00024 char* cookie_filename;
00025 char* userpass;
00026 time_t server_time;
00027 time_t reply_start_time;
00028 OAuth* oauth;
00029 };
00030
00031 struct _Buffer {
00032 void* data;
00033 size_t size;
00034 size_t reserved;
00035 };
00036
00037 struct _OAuth {
00038 char* request_token_url;
00039 char* user_authorization_url;
00040 char* access_token_url;
00041 char* consumer_key;
00042 char* consumer_secret;
00043 MicrofeedHttpOAuthAuthorizeCallback authorize_callback;
00044 MicrofeedHttpOAuthAccessCallback access_callback;
00045 void* user_data;
00046 MicrofeedHttpOAuthSignatureMethod signature_method;
00047 char* access_token;
00048 char* access_token_secret;
00049 };
00050
00051 static unsigned int serial = 1;
00052 static MicrofeedMutex** mutexes = NULL;
00053
00054 static Buffer* buffer_new();
00055 static void buffer_free(Buffer* buffer);
00056 static void buffer_append(Buffer* buffer, const void* data, size_t size);
00057
00058 static OAuth* oauth_new(const char* request_token_url, const char* user_authorization_url, const char* access_token_url, const char* consumer_key, const char* consumer_secret, MicrofeedHttpOAuthAuthorizeCallback authorize_callback, MicrofeedHttpOAuthAccessCallback access_callback, void* user_data);
00059 static void oauth_free(OAuth* oauth);
00060
00061 static size_t curl_header(void* ptr, size_t size, size_t nmemb, void* data);
00062 static size_t curl_write(void* ptr, size_t size, size_t nmemb, void* data);
00063 static char* append_oauth_authentication(MicrofeedHttp* http, const char* method, const char* url, const char* parameters);
00064 static CURLcode do_http_get_data(MicrofeedHttp* http, const char* url);
00065 static void openssl_locking_function(int mode, int n, const char *file, int line);
00066 static unsigned long openssl_id_function(void);
00067
00068 void microfeed_http_init(int multithreaded) {
00069 int i;
00070 CURLcode code;
00071
00072 if (multithreaded) {
00073 mutexes = (MicrofeedMutex**)malloc(CRYPTO_num_locks() * sizeof(MicrofeedMutex*));
00074 for (i = 0; i < CRYPTO_num_locks(); i++) {
00075 mutexes[i] = microfeed_mutex_new();
00076 }
00077 CRYPTO_set_locking_callback(openssl_locking_function);
00078 CRYPTO_set_id_callback(openssl_id_function);
00079 }
00080
00081 if ((code = curl_global_init(CURL_GLOBAL_ALL)) != 0) {
00082 fprintf(stderr, "ERROR: curl_global_init failed: %d\n", code);
00083 }
00084 }
00085
00086 void microfeed_http_cleanup() {
00087 int i;
00088
00089 if (mutexes) {
00090 CRYPTO_set_locking_callback(NULL);
00091 CRYPTO_set_id_callback(NULL);
00092 for (i = 0; i < CRYPTO_num_locks(); i++) {
00093 microfeed_mutex_free(mutexes[i]);
00094 }
00095 free(mutexes);
00096 mutexes = NULL;
00097 }
00098 curl_global_cleanup();
00099 }
00100
00101 MicrofeedHttp* microfeed_http_new() {
00102 MicrofeedHttp* http = NULL;
00103 CURLcode code;
00104
00105 http = microfeed_memory_allocate(MicrofeedHttp);
00106 http->buffer = buffer_new();
00107
00108 if ((http->curl = curl_easy_init())) {
00109 if ((code = curl_easy_setopt(http->curl, CURLOPT_WRITEFUNCTION, curl_write)) ||
00110 (code = curl_easy_setopt(http->curl, CURLOPT_WRITEDATA, http->buffer)) ||
00111 (code = curl_easy_setopt(http->curl, CURLOPT_HEADERFUNCTION, curl_header)) ||
00112 (code = curl_easy_setopt(http->curl, CURLOPT_HEADERDATA, http)) ||
00113 (code = curl_easy_setopt(http->curl, CURLOPT_COOKIEFILE, "")) ||
00114 (code = curl_easy_setopt(http->curl, CURLOPT_FOLLOWLOCATION, (long)1)) ||
00115 (code = curl_easy_setopt(http->curl, CURLOPT_TIMEOUT, (long)300)) ||
00116 (code = curl_easy_setopt(http->curl, CURLOPT_NOSIGNAL, (long)1)) ||
00117 (code = curl_easy_setopt(http->curl, CURLOPT_USERAGENT, "Microfeed/" PACKAGE_VERSION))) {
00118 curl_easy_cleanup(http->curl);
00119 buffer_free(http->buffer);
00120 microfeed_memory_free(http);
00121 http = NULL;
00122 }
00123 } else {
00124 buffer_free(http->buffer);
00125 microfeed_memory_free(http);
00126 http = NULL;
00127 }
00128
00129 return http;
00130 }
00131
00132 void microfeed_http_free(MicrofeedHttp* http) {
00133 if (http) {
00134 curl_easy_cleanup(http->curl);
00135 buffer_free(http->buffer);
00136 free(http->cookie_filename);
00137 free(http->userpass);
00138 free(http);
00139 }
00140 }
00141
00142 void microfeed_http_free_string(MicrofeedHttp* http, char* ptr) {
00143 curl_free(ptr);
00144 }
00145
00146
00147 const void* microfeed_http_get_data(MicrofeedHttp* http, const char* url, size_t* size_return) {
00148 char* url_with_oauth = NULL;
00149 CURLcode code;
00150 long response;
00151
00152 *size_return = 0;
00153 if (http->oauth) {
00154 if ((url_with_oauth = append_oauth_authentication(http, "GET", url, NULL))) {
00155 code = do_http_get_data(http, url_with_oauth);
00156 free(url_with_oauth);
00157 if (code) {
00158
00159 return NULL;
00160 }
00161 if (http->oauth && (curl_easy_getinfo(http->curl, CURLINFO_RESPONSE_CODE, &response) ||
00162 response == 0 || response == 401)) {
00163 free(http->oauth->access_token);
00164 free(http->oauth->access_token_secret);
00165 http->oauth->access_token = http->oauth->access_token_secret = NULL;
00166 if (http->oauth->access_callback) {
00167 http->oauth->access_callback(http, http->oauth->access_token, http->oauth->access_token_secret, http->oauth->user_data);
00168 }
00169 return NULL;
00170 }
00171 }
00172 } else {
00173 if (do_http_get_data(http, url)) {
00174
00175 return NULL;
00176 }
00177 }
00178 *size_return = http->buffer->size;
00179
00180 return http->buffer->data;
00181 }
00182
00183 MicrofeedJson* microfeed_http_get_json(MicrofeedHttp* http, const char* url) {
00184 MicrofeedJson* json = NULL;
00185 const char* data;
00186 size_t size;
00187
00188 if ((data = microfeed_http_get_data(http, url, &size))) {
00189 json = microfeed_json_new_from_data(http->buffer->data, http->buffer->size);
00190 }
00191
00192 return json;
00193 }
00194
00195 time_t microfeed_http_get_reply_start_time(MicrofeedHttp* http) {
00196
00197 return http->reply_start_time;
00198 }
00199
00200 time_t microfeed_http_get_server_time(MicrofeedHttp* http) {
00201
00202 return http->server_time;
00203 }
00204
00205 char* microfeed_http_post_data(MicrofeedHttp* http, const char* url, size_t* size_return, const char* post_data) {
00206 CURLcode code;
00207 struct curl_slist* slist = NULL;
00208 char* post_data_with_oauth = NULL;
00209 long response;
00210
00211 *size_return = 0;
00212 http->buffer->size = 0;
00213 if (!(slist = curl_slist_append(slist, "Content-Type: application/x-www-form-urlencoded; charset=utf-8"))) {
00214
00215 return NULL;
00216 }
00217 if (http->oauth) {
00218 if (!(post_data_with_oauth = append_oauth_authentication(http, "POST", url, post_data))) {
00219
00220 return NULL;
00221 }
00222 if ((code = curl_easy_setopt(http->curl, CURLOPT_POST, 1)) ||
00223 (code = curl_easy_setopt(http->curl, CURLOPT_POSTFIELDS, post_data_with_oauth)) ||
00224 (code = curl_easy_setopt(http->curl, CURLOPT_URL, url)) ||
00225 (code = curl_easy_setopt(http->curl, CURLOPT_HTTPHEADER, slist))) {
00226 free(post_data_with_oauth);
00227 curl_slist_free_all(slist);
00228
00229 return NULL;
00230 }
00231 } else {
00232 if ((code = curl_easy_setopt(http->curl, CURLOPT_POST, 1)) ||
00233 (code = curl_easy_setopt(http->curl, CURLOPT_POSTFIELDS, post_data)) ||
00234 (code = curl_easy_setopt(http->curl, CURLOPT_URL, url)) ||
00235 (code = curl_easy_setopt(http->curl, CURLOPT_HTTPHEADER, slist))) {
00236 curl_slist_free_all(slist);
00237
00238 return NULL;
00239 }
00240 }
00241 http->reply_start_time = http->server_time = 0;
00242 if ((code = curl_easy_perform(http->curl)) != 0) {
00243 curl_easy_setopt(http->curl, CURLOPT_HTTPHEADER, NULL);
00244 curl_slist_free_all(slist);
00245 free(post_data_with_oauth);
00246
00247 return NULL;
00248 }
00249 if (http->oauth && (curl_easy_getinfo(http->curl, CURLINFO_RESPONSE_CODE, &response) ||
00250 response == 0 || response == 401)) {
00251 free(http->oauth->access_token);
00252 free(http->oauth->access_token_secret);
00253 http->oauth->access_token = http->oauth->access_token_secret = NULL;
00254 if (http->oauth->access_callback) {
00255 http->oauth->access_callback(http, http->oauth->access_token, http->oauth->access_token_secret, http->oauth->user_data);
00256 }
00257
00258 return NULL;
00259 }
00260 free(post_data_with_oauth);
00261 curl_easy_setopt(http->curl, CURLOPT_HTTPHEADER, NULL);
00262 curl_slist_free_all(slist);
00263
00264 *size_return = http->buffer->size;
00265
00266 return http->buffer->data;
00267 }
00268
00269 time_t microfeed_http_parse_date(MicrofeedHttp* http, const char* datestring) {
00270 time_t retvalue;
00271
00272 if ((retvalue = curl_getdate(datestring, NULL)) == -1) {
00273 retvalue = 0;
00274 }
00275
00276 return retvalue;
00277 }
00278
00279 MicrofeedJson* microfeed_http_post_json(MicrofeedHttp* http, const char* url, const char* post_data) {
00280 MicrofeedJson* json = NULL;
00281 const char* data;
00282 size_t size;
00283
00284 if ((data = microfeed_http_post_data(http, url, &size, post_data))) {
00285 json = microfeed_json_new_from_data(http->buffer->data, http->buffer->size);
00286 }
00287
00288 return json;
00289 }
00290
00291 int microfeed_http_set_cookie_file(MicrofeedHttp* http, const char* filename) {
00292 int retvalue = 1;
00293
00294 if (http->cookie_filename) {
00295 free(http->cookie_filename);
00296 }
00297 http->cookie_filename = strdup(filename);
00298 if (curl_easy_setopt(http->curl, CURLOPT_COOKIEFILE, http->cookie_filename) ||
00299 curl_easy_setopt(http->curl, CURLOPT_COOKIEJAR, http->cookie_filename)) {
00300
00301 retvalue = 0;
00302 }
00303
00304 return retvalue;
00305 }
00306
00307 int microfeed_http_set_basic_authentication(MicrofeedHttp* http, const char* userpass) {
00308 int retvalue = 1;
00309
00310 if (http->userpass) {
00311 free(http->userpass);
00312 }
00313 if (userpass) {
00314 http->userpass = strdup(userpass);
00315 if (curl_easy_setopt(http->curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC) ||
00316 curl_easy_setopt(http->curl, CURLOPT_USERPWD, http->userpass)) {
00317
00318 retvalue = 0;
00319 }
00320 } else {
00321 http->userpass = NULL;
00322 if (curl_easy_setopt(http->curl, CURLOPT_USERPWD, NULL)) {
00323
00324 retvalue = 0;
00325 }
00326 }
00327
00328 return retvalue;
00329 }
00330
00331 int microfeed_http_set_oauth_authentication(MicrofeedHttp* http, const char* request_token_url, const char* user_authorization_url, const char* access_token_url, const char* consumer_key, const char* consumer_secret, MicrofeedHttpOAuthAuthorizeCallback authorize_callback, MicrofeedHttpOAuthAccessCallback access_callback, void* user_data) {
00332 oauth_free(http->oauth);
00333 http->oauth = oauth_new(request_token_url, user_authorization_url, access_token_url, consumer_key, consumer_secret, authorize_callback, access_callback, user_data);
00334
00335 return 1;
00336 }
00337
00338 void microfeed_http_unset_oauth_authentication(MicrofeedHttp* http) {
00339 oauth_free(http->oauth);
00340 http->oauth = NULL;
00341 }
00342
00343
00344 void microfeed_http_set_oauth_access_token(MicrofeedHttp* http, const char* access_token, const char* access_token_secret) {
00345 free(http->oauth->access_token);
00346 free(http->oauth->access_token_secret);
00347 http->oauth->access_token = strdup(access_token);
00348 http->oauth->access_token_secret = strdup(access_token_secret);
00349 }
00350
00351
00352
00353
00354
00355 static Buffer* buffer_new() {
00356 Buffer* buffer;
00357
00358 buffer = microfeed_memory_allocate(Buffer);
00359 buffer->reserved = 1;
00360 buffer->data = malloc(buffer->reserved);
00361 *((char*)buffer->data) = 0;
00362
00363 return buffer;
00364 }
00365
00366 static void buffer_free(Buffer* buffer) {
00367 free(buffer->data);
00368 microfeed_memory_free(buffer);
00369 }
00370
00371 static void buffer_append(Buffer* buffer, const void* data, size_t size) {
00372 if (buffer->size + size >= buffer->reserved) {
00373 buffer->reserved += buffer->size + size + 1;
00374 buffer->data = realloc(buffer->data, buffer->reserved);
00375 }
00376 memcpy(buffer->data + buffer->size, data, size);
00377 buffer->size += size;
00378 *((char*)(buffer->data + buffer->size)) = 0;
00379 }
00380
00381
00382
00383
00384
00385 static OAuth* oauth_new(const char* request_token_url, const char* user_authorization_url, const char* access_token_url, const char* consumer_key, const char* consumer_secret, MicrofeedHttpOAuthAuthorizeCallback authorize_callback, MicrofeedHttpOAuthAccessCallback access_callback, void* user_data) {
00386 OAuth* oauth;
00387
00388 oauth = microfeed_memory_allocate(OAuth);
00389 oauth->request_token_url = strdup(request_token_url);
00390 oauth->user_authorization_url = strdup(user_authorization_url);
00391 oauth->access_token_url = strdup(access_token_url);
00392 oauth->consumer_key = strdup(consumer_key);
00393 oauth->consumer_secret = strdup(consumer_secret);
00394 oauth->authorize_callback = authorize_callback;
00395 oauth->access_callback = access_callback;
00396 oauth->user_data = user_data;
00397 oauth->signature_method = MICROFEED_HTTP_OAUTH_SIGNATURE_METHOD_HMAC_SHA1;
00398
00399 return oauth;
00400 }
00401
00402 void oauth_free(OAuth* oauth) {
00403 if (oauth) {
00404 free(oauth->request_token_url);
00405 free(oauth->user_authorization_url);
00406 free(oauth->access_token_url);
00407 free(oauth->consumer_key);
00408 free(oauth->consumer_secret);
00409 free(oauth->access_token);
00410 free(oauth->access_token_secret);
00411 microfeed_memory_free(oauth);
00412 }
00413 }
00414
00415
00416
00417
00418
00419 static size_t curl_header(void* ptr, size_t size, size_t nmemb, void* data) {
00420 MicrofeedHttp* http;
00421 char* s;
00422
00423 http = (MicrofeedHttp*)data;
00424
00425 if (!http->reply_start_time) {
00426 http->reply_start_time = time(NULL);
00427 }
00428
00429 if (size * nmemb > 5 && !strncasecmp(ptr, "date:", 5)) {
00430 s = strndup(ptr + 5, size * nmemb - 5);
00431 http->server_time = curl_getdate(s, NULL);
00432 free(s);
00433 }
00434
00435 return size * nmemb;
00436 }
00437
00438 static size_t curl_write(void* ptr, size_t size, size_t nmemb, void* data) {
00439 Buffer* buffer;
00440
00441 buffer = (Buffer*)data;
00442 buffer_append(buffer, ptr, size * nmemb);
00443
00444 return size * nmemb;
00445 }
00446
00447 static char* hmac_sha1(const char* s, const char* key, size_t* length_return) {
00448 char* hmac;
00449 unsigned int u;
00450
00451 u = EVP_MAX_MD_SIZE;
00452 hmac = (char*)malloc(u);
00453 HMAC(EVP_sha1(), key, strlen(key), (const unsigned char*)s, strlen(s), hmac, &u);
00454 hmac = (char*)realloc(hmac, u);
00455 *length_return = (size_t)u;
00456
00457 return hmac;
00458 }
00459
00460 static void copy_parameters_into_store(const char* parameters, MicrofeedStore* store) {
00461 const char* end;
00462 char* copy;
00463 char* old;
00464
00465 while (*parameters) {
00466 while (*parameters == '?' || *parameters == '&') {
00467 parameters++;
00468 }
00469 if (*parameters) {
00470 end = strchrnul(parameters, '&');
00471 copy = strndup(parameters, end - parameters);
00472 if ((old = microfeed_store_replace(store, copy, char))) {
00473 free(old);
00474 }
00475 parameters = end;
00476 }
00477 }
00478 }
00479
00480 static char* generate_oauth_signature(const char* method, const char* url, const char* parameters, const char* oauth_parameters, const char* consumer_secret, const char* token_secret) {
00481 MicrofeedStore* parameters_store;
00482 char* s;
00483 char* copy;
00484 char* escaped_url;
00485 Buffer* buffer;
00486 MicrofeedStoreIterator* iterator;
00487 char* escaped_parameters;
00488 char* signature_base_string;
00489 char* key;
00490 char* signature;
00491 size_t length;
00492 char* base64;
00493 char* escaped;
00494
00495 parameters_store = microfeed_store_new_sorted((MicrofeedStoreCompareKeysFunction)strcmp, microfeed_store_get_key_direct);
00496 if ((s = strchr(url, '?'))) {
00497 copy = strndup(url, s - url);
00498 escaped_url = microfeed_util_string_percent_encoding_escape(copy);
00499 free(copy);
00500 copy_parameters_into_store(s + 1, parameters_store);
00501 } else {
00502 escaped_url = microfeed_util_string_percent_encoding_escape(url);
00503 }
00504 if (parameters) {
00505 copy_parameters_into_store(parameters, parameters_store);
00506 }
00507 copy_parameters_into_store(oauth_parameters, parameters_store);
00508
00509 buffer = buffer_new();
00510 for (iterator = microfeed_store_iterate(parameters_store, NULL); (s = microfeed_store_iterator_get(iterator, char)); microfeed_store_iterator_next(iterator)) {
00511 if (buffer->size) {
00512 buffer_append(buffer, "&", 1);
00513 }
00514 buffer_append(buffer, s, strlen(s));
00515 }
00516 escaped_parameters = microfeed_util_string_percent_encoding_escape((char*)buffer->data);
00517 buffer_free(buffer);
00518 signature_base_string = microfeed_util_string_concatenate(method, "&", escaped_url, "&", escaped_parameters, NULL);
00519
00520 free(escaped_parameters);
00521 free(escaped_url);
00522 if (token_secret) {
00523 key = microfeed_util_string_concatenate(consumer_secret, "&", token_secret, NULL);
00524 } else {
00525 key = microfeed_util_string_concatenate(consumer_secret, "&", NULL);
00526 }
00527 signature = hmac_sha1(signature_base_string, key, &length);
00528 free(key);
00529 base64 = microfeed_util_string_base64_encode(signature, length);
00530 free(signature);
00531 escaped = microfeed_util_string_percent_encoding_escape(base64);
00532 free(base64);
00533
00534 return escaped;
00535 }
00536
00537 static void parse_oauth_reply(const char* s, size_t length, char** token_return, char** token_secret_return) {
00538 const char* s1;
00539 const char* s2;
00540
00541 while ((s1 = memchr(s, '=', length))) {
00542 if (!(s2 = memchr(s1 + 1, '&', length - (s1 - s)))) {
00543 s2 =s + length;
00544 }
00545 if (!strncmp(s, "oauth_token", s1 - s)) {
00546 free(*token_return);
00547 *token_return = strndup(s1 + 1, s2 - s1 -1);
00548 } else if (!strncmp(s, "oauth_token_secret", s1 - s)) {
00549 free(*token_secret_return);
00550 *token_secret_return = strndup(s1 + 1, s2 - s1 -1);
00551 }
00552 if (s2 - s == length) {
00553 break;
00554 }
00555 s = s2 + 1;
00556 length -= s2 - s + 1;
00557 }
00558 }
00559
00560 static char* append_oauth_authentication(MicrofeedHttp* http, const char* method, const char* url, const char* parameters) {
00561 char* result = NULL;
00562 char nonce[128];
00563 char timestamp[128];
00564 char* oauth_parameters;
00565 char* signature;
00566 char* oauth_url;
00567 char* request_token = NULL;
00568 char* request_token_secret = NULL;
00569 long response;
00570
00571 if (!http->oauth->access_token) {
00572 snprintf(timestamp, 128, "%ld", time(NULL));
00573 snprintf(nonce, 128, "%u", serial++);
00574 oauth_parameters = microfeed_util_string_concatenate("oauth_consumer_key=", http->oauth->consumer_key,
00575 "&oauth_nonce=", nonce, "&oauth_signature_method=HMAC-SHA1&oauth_timestamp=", timestamp,
00576 "&oauth_version=1.0", NULL);
00577 signature = generate_oauth_signature("GET", http->oauth->request_token_url, NULL, oauth_parameters, http->oauth->consumer_secret, NULL);
00578 oauth_url = microfeed_util_string_concatenate(http->oauth->request_token_url, (strchr(http->oauth->request_token_url, '?') ? "&" : "?"), oauth_parameters, "&oauth_signature=", signature, NULL);
00579 if (!do_http_get_data(http, oauth_url) && http->buffer->size > 30) {
00580 if (!curl_easy_getinfo(http->curl, CURLINFO_RESPONSE_CODE, &response) &&
00581 response != 0 && response != 401) {
00582 parse_oauth_reply(http->buffer->data, http->buffer->size, &request_token, &request_token_secret);
00583 }
00584 }
00585 free(oauth_url);
00586 if (request_token && request_token_secret) {
00587 oauth_url = microfeed_util_string_concatenate(http->oauth->user_authorization_url, (strchr(http->oauth->user_authorization_url, '?') ? "&" : "?"), "oauth_token=", request_token, NULL);
00588 if (http->oauth->authorize_callback(http, oauth_url, http->oauth->user_data)) {
00589 snprintf(timestamp, 128, "%ld", time(NULL));
00590 snprintf(nonce, 128, "%u", serial++);
00591 oauth_parameters = microfeed_util_string_concatenate("oauth_consumer_key=", http->oauth->consumer_key,
00592 "&oauth_nonce=", nonce, "&oauth_signature_method=HMAC-SHA1&oauth_timestamp=", timestamp,
00593 "&oauth_token=", request_token, "&oauth_version=1.0", NULL);
00594 signature = generate_oauth_signature("GET", http->oauth->access_token_url, NULL, oauth_parameters, http->oauth->consumer_secret, request_token_secret);
00595 oauth_url = microfeed_util_string_concatenate(http->oauth->access_token_url, (strchr(http->oauth->request_token_url, '?') ? "&" : "?"), oauth_parameters, "&oauth_signature=", signature, NULL);
00596 if (!do_http_get_data(http, oauth_url) && http->buffer->size > 30) {
00597 if (!curl_easy_getinfo(http->curl, CURLINFO_RESPONSE_CODE, &response) &&
00598 response != 0 && response != 401) {
00599 parse_oauth_reply(http->buffer->data, http->buffer->size, &http->oauth->access_token, &http->oauth->access_token_secret);
00600 }
00601 }
00602 }
00603 }
00604 if (http->oauth->access_token && http->oauth->access_token_secret) {
00605 if (http->oauth->access_callback) {
00606 http->oauth->access_callback(http, http->oauth->access_token, http->oauth->access_token_secret, http->oauth->user_data);
00607 }
00608 } else {
00609 free(http->oauth->access_token);
00610 free(http->oauth->access_token_secret);
00611 http->oauth->access_token = http->oauth->access_token_secret = NULL;
00612 }
00613
00614 }
00615 if (http->oauth->access_token) {
00616 snprintf(timestamp, 128, "%ld", time(NULL));
00617 snprintf(nonce, 127, "%u", serial++);
00618 oauth_parameters = microfeed_util_string_concatenate("oauth_consumer_key=", http->oauth->consumer_key,
00619 "&oauth_nonce=", nonce, "&oauth_signature_method=HMAC-SHA1&oauth_timestamp=", timestamp,
00620 "&oauth_token=", http->oauth->access_token, "&oauth_version=1.0", NULL);
00621 signature = generate_oauth_signature(method, url, parameters, oauth_parameters, http->oauth->consumer_secret, http->oauth->access_token_secret);
00622 if (parameters) {
00623 result = microfeed_util_string_concatenate(parameters, "&", oauth_parameters, "&oauth_signature=", signature, NULL);
00624 } else {
00625 result = microfeed_util_string_concatenate(url, (strchr(http->oauth->request_token_url, '?') ? "&" : "?"), oauth_parameters, "&oauth_signature=", signature, NULL);
00626 }
00627 free(signature);
00628 }
00629
00630 return result;
00631 }
00632
00633 static CURLcode do_http_get_data(MicrofeedHttp* http, const char* url) {
00634 CURLcode code;
00635
00636 http->buffer->size = 0;
00637 if (!(code = curl_easy_setopt(http->curl, CURLOPT_POST, 0)) &&
00638 !(code = curl_easy_setopt(http->curl, CURLOPT_URL, url))) {
00639 http->reply_start_time = http->server_time = 0;
00640 code = curl_easy_perform(http->curl);
00641 }
00642
00643 return code;
00644 }
00645
00646 static void openssl_locking_function(int mode, int n, const char *file, int line) {
00647 if (mode & CRYPTO_LOCK) {
00648 microfeed_mutex_lock(mutexes[n]);
00649 } else {
00650 microfeed_mutex_unlock(mutexes[n]);
00651 }
00652 }
00653
00654 static unsigned long openssl_id_function(void) {
00655
00656 return microfeed_thread_get_id(microfeed_thread_get_current());
00657 }