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