391
393
(void)gettimeofday(&tp, NULL);
392
394
sprintf(timestamp, "%ld", (long)tp.tv_sec);
394
parameters[count][0] = "oauth_timestamp";
395
parameters[count++][1]= timestamp;
397
parameters[count][0] = "oauth_version";
398
parameters[count++][1]= "1.0";
401
parameters[count][0] = "oauth_token";
402
parameters[count++][1]= od->token;
403
} else if(od->request_token) {
404
parameters[count][0] = "oauth_token";
405
parameters[count++][1]= od->request_token;
408
parameters[count][0] = "oauth_verifier";
409
parameters[count++][1]= od->verifier;
412
parameters[count][0] = NULL;
396
flickcurl_add_param(fc, "oauth_timestamp", timestamp);
398
flickcurl_add_param(fc, "oauth_version", "1.0");
401
flickcurl_add_param(fc, "oauth_token", od->token);
402
else if(od->request_token)
403
flickcurl_add_param(fc, "oauth_token", od->request_token);
406
flickcurl_add_param(fc, "oauth_verifier", od->verifier);
408
flickcurl_end_params(fc);
414
410
/* +FLICKCURL_FLICKCURL_MAX_OAUTH_PARAM_COUNT for oauth fields +1 for NULL terminating pointer */
415
fc->param_fields = (char**)calloc(count + FLICKCURL_MAX_OAUTH_PARAM_COUNT + 1, sizeof(char*));
416
fc->param_values = (char**)calloc(count + FLICKCURL_MAX_OAUTH_PARAM_COUNT + 1, sizeof(char*));
417
values_len = (size_t*)calloc(count + FLICKCURL_MAX_OAUTH_PARAM_COUNT + 1, sizeof(size_t));
411
fc->param_fields = (char**)calloc(fc->count + FLICKCURL_MAX_OAUTH_PARAM_COUNT + 1, sizeof(char*));
412
fc->param_values = (char**)calloc(fc->count + FLICKCURL_MAX_OAUTH_PARAM_COUNT + 1, sizeof(char*));
413
values_len = (size_t*)calloc(fc->count + FLICKCURL_MAX_OAUTH_PARAM_COUNT + 1, sizeof(size_t));
419
415
if((need_auth && (od->client_secret || od->token_secret)) || fc->sign)
420
flickcurl_sort_args(fc, parameters, count);
416
flickcurl_sort_args(fc);
423
419
fc_uri_len = strlen(url);
424
if(url[fc_uri_len -1] != '?')
420
full_uri_len = fc_uri_len;
422
if(url[fc_uri_len - 1] != '?')
425
423
need_to_add_query++;
427
425
/* Save away the parameters and calculate the value lengths */
428
for(i = 0; parameters[i][0]; i++) {
429
size_t param_len = strlen(parameters[i][0]);
426
for(i = 0; fc->parameters[i][0]; i++) {
427
size_t param_len = strlen(fc->parameters[i][0]);
432
values_len[i] = strlen(parameters[i][1]);
429
if(fc->parameters[i][1])
430
values_len[i] = strlen(fc->parameters[i][1]);
434
432
values_len[i] = 0;
435
parameters[i][1] = "";
433
fc->parameters[i][1] = "";
437
435
fc->param_fields[i] = (char*)malloc(param_len + 1);
438
strcpy(fc->param_fields[i], parameters[i][0]);
436
memcpy(fc->param_fields[i], fc->parameters[i][0], param_len + 1);
439
438
fc->param_values[i] = (char*)malloc(values_len[i] + 1);
440
strcpy(fc->param_values[i], parameters[i][1]);
439
memcpy(fc->param_values[i], fc->parameters[i][1], values_len[i] + 1);
442
441
/* 3x value len is conservative URI %XX escaping on every char */
443
fc_uri_len += param_len + 1 /* = */ + 3 * values_len[i];
442
full_uri_len += param_len + 1 /* = */ + 3 * values_len[i];
446
445
if(upload_field) {
447
fc->upload_field = (char*)malloc(strlen(upload_field) + 1);
448
strcpy(fc->upload_field, upload_field);
446
size_t len = strlen(upload_field);
447
fc->upload_field = (char*)malloc(len + 1);
448
memcpy(fc->upload_field, upload_field, len + 1);
450
fc->upload_value = (char*)malloc(strlen(upload_value) + 1);
451
strcpy(fc->upload_value, upload_value);
450
len = strlen(upload_value);
451
fc->upload_value = (char*)malloc(len + 1);
452
memcpy(fc->upload_value, upload_value, len + 1);
460
461
size_t param_buf_len = 0;
462
463
char *escaped_value = NULL;
464
const char* http_method;
465
size_t http_method_len;
466
size_t escaped_value_len;
464
for(i = 0; parameters[i][0]; i++)
465
param_buf_len += strlen(parameters[i][0]) + 3 + (3 * values_len[i]) + 3;
468
for(i = 0; fc->parameters[i][0]; i++)
469
param_buf_len += strlen(fc->parameters[i][0]) + 3 + (3 * values_len[i]) + 3;
466
470
param_buf = (char*)malloc(param_buf_len + 1);
467
471
*param_buf = '\0';
469
for(i = 0; parameters[i][0]; i++) {
475
for(i = 0; fc->parameters[i][0]; i++) {
476
size_t len = strlen(fc->parameters[i][0]);
471
strcat(param_buf, "&");
472
strcat(param_buf, parameters[i][0]);
473
strcat(param_buf, "=");
474
escaped_value = curl_escape(parameters[i][1], 0);
475
strcat(param_buf, escaped_value);
479
memcpy(p, fc->parameters[i][0], len);
484
escaped_value = curl_escape(fc->parameters[i][1], 0);
485
escaped_value_len = strlen(escaped_value);
486
memcpy(p, escaped_value, escaped_value_len);
487
p += escaped_value_len;
476
488
curl_free(escaped_value);
479
buf_len = strlen(http_method);
492
http_method = (upload_field || fc->is_write) ? "POST" : "GET";
493
http_method_len = (upload_field || fc->is_write) ? 4 : 3;
495
buf_len = http_method_len;
480
496
buf_len += 1; /* & */
481
497
buf_len += (3 * strlen(url));
482
498
buf_len += 1; /* & */
483
499
buf_len += param_buf_len * 3;
485
501
buf = (char*)malloc(buf_len + 1);
486
strcpy(buf, http_method);
504
memcpy(p, http_method, http_method_len);
505
p += http_method_len;
488
509
escaped_value = curl_escape(url, 0);
489
strcat(buf, escaped_value);
510
escaped_value_len = strlen(escaped_value);
511
memcpy(p, escaped_value, escaped_value_len);
512
p += escaped_value_len;
490
513
curl_free(escaped_value);
492
517
escaped_value = curl_escape(param_buf, 0);
493
strcat(buf, escaped_value);
518
escaped_value_len = strlen(escaped_value);
519
memcpy(p, escaped_value, escaped_value_len);
520
p += escaped_value_len;
494
521
curl_free(escaped_value);
498
526
if(flickcurl_oauth_build_key(od)) {
520
parameters[count][0] = "oauth_signature";
521
parameters[count][1] = signature_string;
548
flickcurl_add_param(fc, "oauth_signature", signature_string);
523
551
/* Add a new parameter pair */
524
values_len[count] = vlen;
552
values_len[fc->count] = vlen;
525
553
/* 15 = strlen(oauth_signature) */
526
fc->param_fields[count] = (char*)malloc(15 + 1);
527
strcpy(fc->param_fields[count], parameters[count][0]);
528
fc->param_values[count] = (char*)malloc(vlen + 1);
529
strcpy(fc->param_values[count], parameters[count][1]);
531
fc_uri_len += 15 /* "oauth_signature" */ + 1 /* = */ + vlen;
554
fc->param_fields[fc->count] = (char*)malloc(15 + 1);
555
memcpy(fc->param_fields[fc->count], fc->parameters[fc->count][0], 15 + 1);
557
fc->param_values[fc->count] = (char*)malloc(vlen + 1);
558
memcpy(fc->param_values[fc->count], fc->parameters[fc->count][1], vlen + 1);
560
full_uri_len += 15 /* "oauth_signature" */ + 1 /* = */ + vlen;
535
564
#ifdef FLICKCURL_DEBUG
536
565
fprintf(stderr, "HMAC-SHA1 signature:\n %s\n", signature_string);
541
570
od->data_len = 0;
543
parameters[count][0] = NULL;
572
flickcurl_end_params(fc);
546
/* add &s between parameters */
547
fc_uri_len += count-1;
575
/* add &s between fc->parameters */
576
full_uri_len += fc->count - 1;
549
578
/* reuse or grow uri buffer */
550
if(fc->uri_len < fc_uri_len) {
579
if(fc->uri_len < full_uri_len) {
552
fc->uri = (char*)malloc(fc_uri_len+1);
553
fc->uri_len = fc_uri_len;
581
fc->uri = (char*)malloc(full_uri_len + 1);
582
fc->uri_len = full_uri_len;
555
strcpy(fc->uri, url);
584
memcpy(fc->uri, url, fc_uri_len);
586
p = fc->uri + fc_uri_len;
557
589
if(need_to_add_query)
558
strcat(fc->uri, "?");
560
592
if(parameters_in_url) {
561
for(i = 0; parameters[i][0]; i++) {
562
char *value = (char*)parameters[i][1];
563
char *escaped_value = NULL;
593
for(i = 0; fc->parameters[i][0]; i++) {
594
char *value = (char*)fc->parameters[i][1];
565
if(!parameters[i][1])
597
if(!fc->parameters[i][1])
568
strcat(fc->uri, parameters[i][0]);
569
strcat(fc->uri, "=");
570
escaped_value = curl_escape(value, values_len[i]);
571
strcat(fc->uri, escaped_value);
572
curl_free(escaped_value);
573
strcat(fc->uri, "&");
600
len = strlen(fc->parameters[i][0]);
601
memcpy(p, fc->parameters[i][0], len);
605
value = curl_escape(value, values_len[i]);
607
memcpy(p, value, len);
577
fc->uri[strlen(fc->uri)-1] = '\0';
614
/* zap last & and terminate fc->url */
580
618
#ifdef FLICKCURL_DEBUG
606
* flickcurl_oauth_request_token:
644
* flickcurl_oauth_create_request_token:
607
645
* @fc: flickcurl object
609
* INTERNAL - get a Flickr OAuth request token
611
* Calls the Flickr OAuth endpoint to get a request token.
613
* Stores the request token in @od fields 'request_token' and
614
* 'request_token_secret' on success.
646
* @callback: callback URL or NULL for out of band
648
* Request an OAuth request token from Flickr for the application API Key/secret
650
* Requires the OAuth Client key (API key) and Client secret to have
651
* been set with flickcurl_set_oauth_client_key() and
652
* flickcurl_set_oauth_client_secret() respectively.
654
* Calls the Flickr OAuth endpoint to get a request token for the
655
* given callback or uses out-of-band if @callback is NULL.
657
* On success, stores the request token in the @fc structure.
616
659
* Return value: non-0 on failure
619
flickcurl_oauth_request_token(flickcurl* fc)
662
flickcurl_oauth_create_request_token(flickcurl* fc, const char* callback)
621
664
flickcurl_oauth_data* od = &fc->od;
622
const char * parameters[2 + FLICKCURL_MAX_OAUTH_PARAM_COUNT][2];
624
665
char* request_token = NULL;
625
666
char* request_token_secret = NULL;
626
667
char** form = NULL;
628
669
const char* uri = fc->oauth_request_token_uri;
631
parameters[count][0] = NULL;
673
flickcurl_end_params(fc);
633
675
/* Require signature */
634
676
flickcurl_set_sign(fc);
636
od->callback = "oob";
678
if(!callback || !*callback)
680
od->callback = callback;
637
682
rc = flickcurl_oauth_prepare_common(fc,
639
684
/* method */ "flickr.oauth.request_token",
640
685
/* upload_field */ NULL,
641
686
/* upload_value */ NULL,
643
687
/* parameters_in_url */ 1,
644
688
/* need_auth */ 1);
645
689
od->callback = NULL;
736
* flickcurl_oauth_access_token:
791
* flickcurl_oauth_create_access_token:
737
792
* @fc: flickcurl object
738
793
* @verifier: verifier from OOB authentication
740
* INTERNAL - get a Flickr OAuth access token from a verifier
795
* Get a Flickr OAuth access token from request token credentials and verifier
742
797
* Calls the Flickr OAuth access token endpoint using the verifier
743
* from out of band authentication to get an access token.
745
* Uses the @verifier and the @od fields 'request_token' and
746
* 'request_token_secret' to get an access token stored which on
747
* success is stored in the @od fields 'access_token' and
748
* 'access_token_secret'. The request token fields are deleted on
798
* from out of band authentication to get an access token to enable
799
* authenticated calls to the Flickr API.
751
801
* Return value: non-0 on failure
754
flickcurl_oauth_access_token(flickcurl* fc, const char* verifier)
804
flickcurl_oauth_create_access_token(flickcurl* fc, const char* verifier)
756
806
flickcurl_oauth_data* od = &fc->od;
757
const char * parameters[2 + FLICKCURL_MAX_OAUTH_PARAM_COUNT][2];
759
807
char* access_token = NULL;
760
808
char* access_token_secret = NULL;
809
char* username = NULL;
810
char* user_nsid = NULL;
761
811
char** form = NULL;
763
813
const char* uri = fc->oauth_access_token_uri;
766
parameters[count][0] = NULL;
820
flickcurl_end_params(fc);
768
822
/* Require signature */
769
823
flickcurl_set_sign(fc);
801
854
access_token = form[i+1];
802
855
} else if(!strcmp(form[i], "oauth_token_secret")) {
803
856
access_token_secret = form[i+1];
857
} else if(!strcmp(form[i], "username")) {
858
username = form[i+1];
859
} else if(!strcmp(form[i], "user_nsid")) {
860
user_nsid = form[i+1];
805
/* ignoring: fullname, user_nsid, username */
862
/* ignoring: fullname */
808
865
if(access_token && access_token_secret) {
809
866
/* Take copies that are owned by od */
810
od->token = strdup(access_token);
811
od->token_len = strlen(od->token);
812
od->token_secret = strdup(access_token_secret);
813
od->token_secret_len = strlen(od->token_secret);
867
size_t len = strlen(access_token);
868
od->token = (char*)malloc(len + 1);
869
memcpy(od->token, access_token, len + 1);
872
len = strlen(access_token_secret);
873
od->token_secret = (char*)malloc(len + 1);
874
memcpy(od->token_secret, access_token_secret, len + 1);
875
od->token_secret_len = len;
878
len = strlen(username);
879
od->username = (char*)malloc(len + 1);
880
memcpy(od->username, username, len + 1);
881
od->username_len = len;
884
od->username_len = 0;
888
len = strlen(user_nsid);
889
od->user_nsid = (char*)malloc(len + 1);
890
memcpy(od->user_nsid, user_nsid, len + 1);
891
od->user_nsid_len = len;
893
od->user_nsid = NULL;
894
od->user_nsid_len = 0;
815
897
/* Delete temporary request token and secret */
816
898
free(od->request_token);
817
899
od->request_token = NULL;
924
* flickcurl_get_oauth_client_key:
925
* @fc: flickcurl object
927
* Get OAuth Client Key (aka Consumer key, API Key)
929
* See also flickcurl_get_oauth_client_secret()
931
* Return value: client key or NULL if none set
934
flickcurl_get_oauth_client_key(flickcurl *fc)
936
return fc->od.client_key;
941
* flickcurl_get_oauth_client_secret:
942
* @fc: flickcurl object
944
* Get OAuth Client secret
946
* See also flickcurl_get_oauth_client_key()
948
* Return value: client secret or NULL if none set
951
flickcurl_get_oauth_client_secret(flickcurl *fc)
953
return fc->od.client_secret;
958
* flickcurl_set_oauth_client_key:
959
* @fc: flickcurl object
960
* @client_key: client key (API key)
962
* Set OAuth client key (aka API key)
964
* See also flickcurl_get_oauth_client_key()
967
flickcurl_set_oauth_client_key(flickcurl *fc, const char* client_key)
969
if(fc->od.client_key) {
970
free(fc->od.client_key);
971
fc->od.client_key = NULL;
972
fc->od.client_key_len = 0;
976
size_t len = strlen(client_key);
977
fc->od.client_key = (char*)malloc(len + 1);
978
memcpy(fc->od.client_key, client_key, len + 1);
979
fc->od.client_key_len = len;
985
* flickcurl_set_oauth_client_secret:
986
* @fc: flickcurl object
987
* @client_secret: client key (shared key)
989
* Set OAuth client key (aka shared secret)
991
* See also flickcurl_set_oauth_client_secret()
994
flickcurl_set_oauth_client_secret(flickcurl *fc, const char* client_secret)
996
if(fc->od.client_secret) {
997
free(fc->od.client_secret);
998
fc->od.client_secret = NULL;
999
fc->od.client_secret_len = 0;
1003
size_t len = strlen(client_secret);
1004
fc->od.client_secret = (char*)malloc(len + 1);
1005
memcpy(fc->od.client_secret, client_secret, len + 1);
1006
fc->od.client_secret_len = len;
1012
* flickcurl_get_oauth_token:
1013
* @fc: flickcurl object
1017
* Return value: auth token or NULL if none set
1020
flickcurl_get_oauth_token(flickcurl *fc)
1022
return fc->od.token;
1027
* flickcurl_set_oauth_token:
1028
* @fc: flickcurl object
1029
* @token: auth token
1034
flickcurl_set_oauth_token(flickcurl *fc, const char* token)
1036
#if FLICKCURL_DEBUG > 1
1037
fprintf(stderr, "OAuth token: '%s'\n", token);
1041
fc->od.token = NULL;
1042
fc->od.token_len = 0;
1045
size_t len = strlen(token);
1046
fc->od.token = (char*)malloc(len + 1);
1047
memcpy(fc->od.token, token, len + 1);
1048
fc->od.token_len = len;
1054
* flickcurl_get_oauth_token_secret:
1055
* @fc: flickcurl object
1057
* Get OAuth token secret
1059
* Return value: secret or NULL if none set
1062
flickcurl_get_oauth_token_secret(flickcurl* fc)
1064
return fc->od.token_secret;
1068
* flickcurl_get_oauth_username:
1069
* @fc: flickcurl object
1071
* Get the username for the authenticated user
1073
* Return value: username or NULL if none set
1076
flickcurl_get_oauth_username(flickcurl* fc)
1078
return fc->od.username;
1082
* flickcurl_get_oauth_user_nsid:
1083
* @fc: flickcurl object
1085
* Get the user_nsid for the authenticated user
1087
* Return value: user_nsid or NULL if none set
1090
flickcurl_get_oauth_user_nsid(flickcurl* fc)
1092
return fc->od.user_nsid;
1096
* flickcurl_set_oauth_token_secret:
1097
* @fc: flickcurl object
1098
* @secret: shared secret
1100
* Set OAuth token Secret
1103
flickcurl_set_oauth_token_secret(flickcurl* fc, const char *secret)
1105
#if FLICKCURL_DEBUG > 1
1106
fprintf(stderr, "OAuth token secret: '%s'\n", secret);
1108
if(fc->od.token_secret) {
1109
free(fc->od.token_secret);
1110
fc->od.token_secret = NULL;
1111
fc->od.token_secret_len = 0;
1115
size_t len = strlen(secret);
1116
fc->od.token_secret = (char*)malloc(len + 1);
1117
memcpy(fc->od.token_secret, secret, len + 1);
1118
fc->od.token_secret_len = len;
1124
* flickcurl_get_oauth_request_token:
1125
* @fc: flickcurl object
1127
* Get OAuth request token
1129
* Return value: request token or NULL if none set
1132
flickcurl_get_oauth_request_token(flickcurl* fc)
1134
return fc->od.request_token;
1139
* flickcurl_get_oauth_request_token_secret:
1140
* @fc: flickcurl object
1142
* Get OAuth request token secret
1144
* Return value: request token secret or NULL if none set
1147
flickcurl_get_oauth_request_token_secret(flickcurl* fc)
1149
return fc->od.request_token_secret;
1154
* flickcurl_set_oauth_request_token:
1155
* @fc: flickcurl object
1156
* @token: request token
1158
* Set OAuth request token
1160
* See also flickcurl_get_oauth_request_token()
1163
flickcurl_set_oauth_request_token(flickcurl *fc, const char* token)
1165
#if FLICKCURL_DEBUG > 1
1166
fprintf(stderr, "OAuth request token: '%s'\n", token);
1168
if(fc->od.request_token) {
1169
free(fc->od.request_token);
1170
fc->od.request_token = NULL;
1171
fc->od.request_token_len = 0;
1175
size_t len = strlen(token);
1176
fc->od.request_token = (char*)malloc(len + 1);
1177
memcpy(fc->od.request_token, token, len + 1);
1178
fc->od.request_token_len = len;
1184
* flickcurl_set_oauth_request_token_secret:
1185
* @fc: flickcurl object
1186
* @secret: request token secret
1188
* Set OAuth request token secret credentials
1190
* See also flickcurl_get_oauth_request_token_secret()
1193
flickcurl_set_oauth_request_token_secret(flickcurl *fc, const char* secret)
1195
#if FLICKCURL_DEBUG > 1
1196
fprintf(stderr, "OAuth request token secret: '%s'\n", secret);
1198
if(fc->od.request_token_secret) {
1199
free(fc->od.request_token_secret);
1200
fc->od.request_token_secret = NULL;
1201
fc->od.request_token_secret = 0;
1204
size_t len = strlen(secret);
1205
fc->od.request_token_secret = (char*)malloc(len + 1);
1206
memcpy(fc->od.request_token_secret, secret, len + 1);
1207
fc->od.request_token_secret_len = len;
1006
1382
test_uri_base_string,
1007
1383
test_request_parameters);
1009
fprintf(stderr, "%s: key is (%d bytes)\n %s\n", program, (int)od->key_len, od->key);
1010
fprintf(stderr, "%s: expected key is\n %s\n", program, expected_key);
1012
fprintf(stderr, "%s: data is (%d bytes)\n %s\n", program, (int)od->data_len, od->data);
1013
fprintf(stderr, "%s: expected data is\n %s\n", program, expected_data);
1385
if(strcmp((const char*)od->key, expected_key)) {
1386
fprintf(stderr, "%s: FAIL\n"
1387
" key is (%d bytes)\n %s\n"
1388
" expected key is\n %s\n",
1389
program, (int)od->key_len, od->key, expected_key);
1393
if(strcmp((const char*)od->data, expected_data)) {
1394
fprintf(stderr, "%s: FAIL\n"
1395
" data is (%d bytes)\n %s\n"
1396
" expected data is\n %s\n",
1397
program, (int)od->data_len, od->data, expected_data);
1015
1401
signature = flickcurl_oauth_compute_signature(od, &escaped_s_len);