1
/* -*- Mode: c; c-basic-offset: 2 -*-
3
* legacy-auth.c - Flickr Legacy authentication
5
* Copyright (C) 2007-2012, David Beckett http://www.dajobe.org/
7
* This file is licensed under the following three licenses as alternatives:
8
* 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
9
* 2. GNU General Public License (GPL) V2 or any newer version
10
* 3. Apache License, V2.0 or any newer version
12
* You may not use this file except in compliance with at least one of
13
* the above three licenses.
15
* See LICENSE.html or LICENSE.txt at the top of this package for the
16
* complete terms and further detail along with the license texts for
17
* the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
30
#include <win32_flickcurl_config.h>
33
#include <flickcurl.h>
34
#include <flickcurl_internal.h>
39
compare_args(const void *a, const void *b)
41
return strcmp(*(char**)a, *(char**)b);
46
flickcurl_sort_args(flickcurl *fc)
48
qsort((void*)fc->parameters, fc->count, sizeof(char*[2]), compare_args);
53
flickcurl_legacy_prepare_common(flickcurl *fc,
56
const char* upload_field,
57
const char* upload_value,
58
int parameters_in_url, int need_auth)
61
char *md5_string = NULL;
62
size_t* values_len = NULL;
63
unsigned int fc_uri_len = 0;
64
unsigned int full_uri_len = 0;
69
/* If one is given, both are required */
70
if((upload_field || upload_value) && (!upload_field || !upload_value))
81
/* Default to no data */
89
if(fc->param_fields) {
90
for(i = 0; fc->param_fields[i]; i++) {
91
free(fc->param_fields[i]);
92
free(fc->param_values[i]);
94
free(fc->param_fields);
95
free(fc->param_values);
96
fc->param_fields = NULL;
97
fc->param_values = NULL;
98
fc->parameter_count = 0;
100
if(fc->upload_field) {
101
free(fc->upload_field);
102
fc->upload_field = NULL;
104
if(fc->upload_value) {
105
free(fc->upload_value);
106
fc->upload_value = NULL;
110
flickcurl_error(fc, "No legacy Flickr auth secret");
114
flickcurl_error(fc, "No API Key (OAuth Client Key)");
122
size_t len = strlen(method);
123
fc->method = (char*)malloc(len + 1);
124
memcpy(fc->method, method, len + 1);
129
flickcurl_add_param(fc, "method", fc->method);
131
flickcurl_add_param(fc, "api_key", fc->api_key);
133
if(need_auth && fc->auth_token)
134
flickcurl_add_param(fc, "auth_token", fc->auth_token);
136
flickcurl_end_params(fc);
138
/* +1 for api_sig +1 for NULL terminating pointer */
139
fc->param_fields = (char**)calloc(fc->count + 2, sizeof(char*));
140
fc->param_values = (char**)calloc(fc->count + 2, sizeof(char*));
141
values_len = (size_t*)calloc(fc->count + 2, sizeof(size_t));
143
if((need_auth && fc->auth_token) || fc->sign)
144
flickcurl_sort_args(fc);
146
fc_uri_len = strlen(url);
147
full_uri_len = fc_uri_len;
149
/* Save away the parameters and calculate the value lengths */
150
for(i = 0; fc->parameters[i][0]; i++) {
151
size_t param_len = strlen(fc->parameters[i][0]);
153
if(fc->parameters[i][1])
154
values_len[i] = strlen(fc->parameters[i][1]);
157
fc->parameters[i][1] = "";
160
fc->param_fields[i] = (char*)malloc(param_len + 1);
161
memcpy(fc->param_fields[i], fc->parameters[i][0], param_len + 1);
163
fc->param_values[i] = (char*)malloc(values_len[i] + 1);
164
memcpy(fc->param_values[i], fc->parameters[i][1], values_len[i] + 1);
166
/* 3x value len is conservative URI %XX escaping on every char */
167
full_uri_len += param_len + 1 /* = */ + 3 * values_len[i];
171
size_t len = strlen(upload_field);
172
fc->upload_field = (char*)malloc(len + 1);
173
memcpy(fc->upload_field, upload_field, len + 1);
175
len = strlen(upload_value);
176
fc->upload_value = (char*)malloc(len + 1);
177
memcpy(fc->upload_value, upload_value, len + 1);
180
if((need_auth && fc->auth_token) || fc->sign) {
186
secret_len = strlen(fc->secret);
187
buf_len = secret_len;
188
for(i = 0; fc->parameters[i][0]; i++)
189
buf_len += strlen(fc->parameters[i][0]) + values_len[i];
191
buf = (char*)malloc(buf_len + 1);
194
memcpy(p, fc->secret, secret_len);
196
for(i = 0; fc->parameters[i][0]; i++) {
197
size_t len = strlen(fc->parameters[i][0]);
198
memcpy(p, fc->parameters[i][0], len);
200
memcpy(p, fc->parameters[i][1], values_len[i]);
205
#ifdef FLICKCURL_DEBUG
206
fprintf(stderr, "MD5 Buffer '%s'\n", buf);
208
md5_string = MD5_string(buf);
210
flickcurl_add_param(fc, "api_sig", md5_string);
213
/* Add a new parameter pair */
214
values_len[fc->count] = 32; /* MD5 is always 32 */
215
fc->param_fields[fc->count] = (char*)malloc(7+1); /* 7 = strlen(api_sig) */
216
memcpy(fc->param_fields[fc->count], fc->parameters[fc->count][0], 7 + 1);
218
fc->param_values[fc->count] = (char*)malloc(32+1); /* 32 = MD5 */
219
memcpy(fc->param_values[fc->count], fc->parameters[fc->count][1], 32 + 1);
221
full_uri_len += 7 /* "api_sig" */ + 1 /* = */ + 32 /* MD5 value: never escaped */;
225
#ifdef FLICKCURL_DEBUG
226
fprintf(stderr, "Signature: '%s'\n", fc->parameters[fc->count - 1][1]);
231
flickcurl_end_params(fc);
234
/* add &s between parameters */
235
full_uri_len += fc->count - 1;
237
/* reuse or grow uri buffer */
238
if(fc->uri_len < full_uri_len) {
240
fc->uri = (char*)malloc(full_uri_len + 1);
241
fc->uri_len = full_uri_len;
243
memcpy(fc->uri, url, fc_uri_len);
244
fc->uri[fc_uri_len] = '\0';
246
if(parameters_in_url) {
247
char* p = fc->uri + fc_uri_len;
249
for(i = 0; fc->parameters[i][0]; i++) {
250
char *value = (char*)fc->parameters[i][1];
251
int value_is_escaped = 0;
254
if(!fc->parameters[i][1])
257
len = strlen(fc->parameters[i][0]);
258
memcpy(p, fc->parameters[i][0], len);
263
if(!strcmp(fc->parameters[i][0], "method")) {
264
/* do not touch method name */
266
value = curl_escape(value, len);
268
value_is_escaped = 1;
271
memcpy(p, value, len);
280
/* zap last & and terminate fc->url */
284
#ifdef FLICKCURL_DEBUG
285
fprintf(stderr, "URI is '%s'\n", fc->uri);
287
FLICKCURL_ASSERT((strlen(fc->uri) == full_uri_len),
288
"Final URI does not match expected length");