Project

General

Profile

0001-flickr-switch-to-oauth-authentication.patch

jean-luc Le Corre, 06/19/2019 09:47 AM

View differences:

cmake/modules/FindFLICKCURL.cmake
1
# - Try to find FlickCurl
2
# Once done, this will define
3
#
4
#  FLICKCURL_FOUND - system has Glib
5
#  FLICKCURL_INCLUDE_DIRS - the Glib include directories
6
#  FLICKCURL_LIBRARIES - link these to use Glib
7

  
8

  
9
# INCLUDE(UsePkgConfig)
10

  
11
# use pkg-config to get the directories and then use these values
12
# in the FIND_PATH() and FIND_LIBRARY() calls
13
# PKGCONFIG(flickcurl _flickcurlIncDir _flickcurlLinkDir _flickculrLinkFlags _flickcurlCflags)
14

  
15
# SET(FLICKCURL_LIBS ${_flickcurlCflags})
16

  
17
FIND_PATH(FLICKCURL_INCLUDE_DIR flickcurl.h
18
  PATHS /usr/include
19
  /usr/local/include
20
  /opt/local/include
21
  HINTS ENV FLICKCURL_INCLUDE_DIR
22
  PATH_SUFFIXES flickcurl
23
)
24

  
25
FIND_LIBRARY(FLICKCURL_LIBRARY
26
  NAMES ${FLICKCURL_NAMES} flickcurl libflickcurl.so libflickcurl.dylib
27
  PATHS /usr/lib /usr/local/lib /opt/local/lib
28
  HINTS ENV FLICKCURL_LIBRARY
29
)
30

  
31
include(FindPackageHandleStandardArgs)
32
find_package_handle_standard_args(FLICKCURL DEFAULT_MSG FLICKCURL_LIBRARY FLICKCURL_INCLUDE_DIR)
33

  
34
IF(FLICKCURL_FOUND)
35
  SET(FLICKCURL_LIBRARIES ${FLICKCURL_LIBRARY})
36
  SET(FLICKCURL_INCLUDE_DIRS ${FLICKCURL_INCLUDE_DIR})
37
ENDIF(FLICKCURL_FOUND)
cmake/modules/FindOAUTH.cmake
1
# - Try to find oauth
2
# Once done, this will define
3
#
4
#  OAUTH_FOUND - system has Glib
5
#  OAUTH_INCLUDE_DIRS - the Glib include directories
6
#  OAUTH_LIBRARIES - link these to use Glib
7

  
8

  
9
# INCLUDE(UsePkgConfig)
10

  
11
# use pkg-config to get the directories and then use these values
12
# in the FIND_PATH() and FIND_LIBRARY() calls
13
# PKGCONFIG(oauth _oauthIncDir _oauthLinkDir _oauthLinkFlags _oauthCflags)
14

  
15

  
16
# SET(OAUTH_LIBS ${_flickcurlCflags})
17

  
18
FIND_PATH(OAUTH_INCLUDE_DIR oauth.h
19
  PATHS /usr/include
20
  /usr/local/include
21
  /opt/local/include
22
  HINTS ENV OAUTH_INCLUDE_DIR
23
  PATH_SUFFIXES oauth
24
)
25

  
26
FIND_LIBRARY(OAUTH_LIBRARY
27
  NAMES ${OAUTH_NAMES} oauth liboauth.so liboauth.dylib
28
  PATHS /usr/lib /usr/local/lib /opt/local/lib
29
  HINTS ENV OAUTH_LIBRARY
30
)
31

  
32
include(FindPackageHandleStandardArgs)
33
find_package_handle_standard_args(OAUTH DEFAULT_MSG OAUTH_LIBRARY OAUTH_INCLUDE_DIR)
34

  
35
IF(OAUTH_FOUND)
36
  SET(OAUTH_LIBRARIES ${OAUTH_LIBRARY})
37
  SET(OAUTH_INCLUDE_DIRS ${OAUTH_INCLUDE_DIR})
38
ENDIF(OAUTH_FOUND)
src/CMakeLists.txt
332 332
add_definitions(${Exiv2_DEFINITIONS})
333 333

  
334 334
if(USE_FLICKR)
335
  find_package(FLICKCURL)
336
  if(FLICKCURL_FOUND)
337
    include_directories(SYSTEM ${FLICKCURL_INCLUDE_DIRS})
338
    list(APPEND LIBS ${FLICKCURL_LIBRARIES})
339
    add_definitions(${FLICKCURL_DEFINITIONS})
340
  endif(FLICKCURL_FOUND)
335
  find_package(OAUTH)
336
  if(OAUTH_FOUND)
337
    include_directories(SYSTEM ${OAUTH_INCLUDE_DIRS})
338
    list(APPEND LIBS ${OAUTH_LIBRARIES})
339
    add_definitions(${OAUTH_DEFINITIONS})
340
  endif(OAUTH_FOUND)
341 341
endif(USE_FLICKR)
342 342

  
343 343
if(USE_OPENJPEG)
src/imageio/storage/CMakeLists.txt
7 7

  
8 8
set(MODULES disk email gallery latex)
9 9

  
10
if(FLICKCURL_FOUND)
11
	list(APPEND MODULES flickr)
12
endif(FLICKCURL_FOUND)
10
if(OAUTH_FOUND)
11
	list(APPEND MODULES  flickr)
12
endif(OAUTH_FOUND)
13 13

  
14 14
if (JsonGlib_FOUND)
15 15
	list(APPEND MODULES facebook googlephoto)
src/imageio/storage/flickr.c
1 1
/*
2 2
    This file is part of darktable,
3 3
    copyright (c) 2010-2011 Jose Carlos Garcia Sogo
4
    copyright (c) 2019 Jean-Luc Le Corre
4 5

  
5 6
    darktable is free software: you can redistribute it and/or modify
6 7
    it under the terms of the GNU General Public License as published by
......
29 30
#include "control/control.h"
30 31
#include "dtgtk/button.h"
31 32
#include "gui/gtk.h"
33
#include <json-glib/json-glib.h>
34
#include <libxml/parser.h>
35
#include <libxml/tree.h>
32 36
#include "imageio/storage/imageio_storage_api.h"
33 37
#ifdef GDK_WINDOWING_QUARTZ
34 38
#include "osx/osx.h"
35 39
#endif
36 40
#include <curl/curl.h>
37
#include <flickcurl.h>
41
#include <oauth.h>
38 42
#include <stdio.h>
39 43
#include <stdlib.h>
40 44
#include <unistd.h>
......
43 47

  
44 48
#define API_KEY "1d25b2dfcceba8c55fecb27645c968a3"
45 49
#define SHARED_SECRET "ac66b6c212be6f0c"
50
#define MSGCOLOR_RED "#e07f7f"
46 51

  
47
typedef struct _flickr_api_context_t
52
typedef struct _flickr_album_t
48 53
{
49
  flickcurl *fc;
54
  gchar *id;
55
  gchar *title;
56
  gchar *summary;
57
  gint photos_count;
58
} _flickr_album_t;
50 59

  
60
typedef struct _flickr_api_context_t
61
{
62
  CURL *curl;
63
  char *user_token;
64
  char *user_token_secret;
65
  char *user_nsid;
66
  char *user_name;
51 67
  gboolean needsReauthentication;
52

  
53 68
  /** Current album used when posting images... */
54
  flickcurl_photoset *current_album;
55

  
69
  _flickr_album_t *current_album;
56 70
  char *album_title;
57 71
  char *album_summary;
58 72
  int album_public;
59 73
  gboolean new_album;
60 74
  gboolean error_occured;
61

  
62 75
} _flickr_api_context_t;
63 76

  
64 77
typedef struct dt_storage_flickr_gui_data_t
65 78
{
66

  
67 79
  GtkLabel *status_label;
68 80
  GtkEntry *user_entry, *title_entry, *summary_entry;
69 81
  GtkWidget *export_tags;
70 82
  GtkBox *create_box;                               // Create album options...
71 83
  GtkWidget *permission_list, *album_list;
72

  
73 84
  char *user_token;
74

  
85
  char *user_token_secret;
86
  char *user_nsid;
87
  gboolean authenticated;
75 88
  /* List of albums */
76
  flickcurl_photoset **albums;
77

  
89
  _flickr_album_t **albums;
78 90
  /** Current Flickr context for the gui */
79 91
  _flickr_api_context_t *flickr_api;
80

  
81 92
} dt_storage_flickr_gui_data_t;
82 93

  
83

  
84 94
typedef struct dt_storage_flickr_params_t
85 95
{
86 96
  int64_t hash;
......
91 101
  gboolean family_perm;
92 102
} dt_storage_flickr_params_t;
93 103

  
94

  
95
/** Authenticates and retrieves an initialized flickr api object */
96
static _flickr_api_context_t *_flickr_api_authenticate(dt_storage_flickr_gui_data_t *ui);
97

  
98
static flickcurl_upload_status *_flickr_api_upload_photo(dt_storage_flickr_params_t *params, char *data,
99
                                                         char *caption, char *description, gint imgid);
104
typedef struct flickr_upload_params
105
{
106
  const char *photo_file;
107
  const char *title;
108
  const char *description;
109
  const char *tags;
110
  int is_public;
111
  int is_friend;
112
  int is_family;
113
  int safety_level;
114
  int content_type;
115
  int hidden;
116
} flickr_upload_params;
100 117

  
101 118
static void _flickr_api_free(_flickr_api_context_t *ctx)
102 119
{
103

  
104 120
  g_free(ctx->album_title);
105 121
  g_free(ctx->album_summary);
122
  if(ctx->current_album != NULL)
123
  {
124
    free(ctx->current_album->id);
125
    free(ctx->current_album->title);
126
    free(ctx->current_album->summary);
127
    free(ctx->current_album);
128
    }
129
  curl_free(ctx->curl);
130
  g_free(ctx);
131
}
106 132

  
107
  if(ctx->current_album != NULL) flickcurl_free_photoset(ctx->current_album);
108 133

  
109
  flickcurl_free(ctx->fc);
134
static size_t curl_write_data_cb(void *ptr, size_t size, size_t nmemb, void *data)
135
{
136
  GString *string = (GString *)data;
137
  g_string_append_len(string, ptr, size * nmemb);
138
  return size * nmemb;
139
}
110 140

  
111
  g_free(ctx);
141
static char *getParameterValue(const char *parameter, const char *buffer)
142
{
143
  char value[128];
144
  char *v = value;
145
  char *p = strstr(buffer,parameter);
146
  if(p)
147
  {
148
    p += strlen(parameter);
149
    if (*p == '=')
150
    {
151
      p++;
152
      while (*p && *p != '&')
153
      {
154
        *v++ = *p++ ;
155
      }
156
      *v = '\0';
157
    }
158
    else
159
    {
160
      return NULL;
161
    }
162
  }
163
  else
164
  {
165
    return NULL;
166
  }
167
  return strdup(value) ;
112 168
}
113 169

  
114
static void _flickr_api_error_handler(void *data, const char *message)
170

  
171
static JsonObject *flickr_parse_response(JsonParser *json_parser, GString *response)
115 172
{
116
  dt_control_log(_("flickr authentication: %s"), message);
117
  fprintf(stderr, "[flickr] error: %s\n", message);
118
  if(data)
173
  GError *error;
174
  // unwrap jsonFlickrApi( .... )
175
  #define L_JSON_HEAD  14  //  jsonFlickrApi(
176
  #define L_JSON_WRAP  15 // L_JSON_HEAD + )
177
  const gboolean ret = json_parser_load_from_data(json_parser, response->str + L_JSON_HEAD, response->len - L_JSON_WRAP, &error);
178
  g_return_val_if_fail((ret), NULL);
179
  JsonNode *root = json_parser_get_root(json_parser);
180
  g_return_val_if_fail((json_node_get_node_type(root) == JSON_NODE_OBJECT), NULL);
181
  JsonObject *rootdict = json_node_get_object(root);
182
  if (json_object_has_member(rootdict, "error"))
119 183
  {
120
    _flickr_api_context_t *ctx = (_flickr_api_context_t *)data;
121
    ctx->error_occured = 1;
184
    JsonObject *errorstruct = json_object_get_object_member(rootdict, "error");
185
    g_return_val_if_fail((errorstruct != NULL), NULL);
186
    const gchar *errormessage = json_object_get_string_member(errorstruct, "message");
187
    g_return_val_if_fail((errormessage != NULL), NULL);
188
    return NULL;
122 189
  }
190
  return rootdict;
123 191
}
124 192

  
125
static _flickr_api_context_t *_flickr_api_authenticate(dt_storage_flickr_gui_data_t *ui)
193

  
194
static gboolean _open_browser(const char *url)
126 195
{
127
  char *perms = NULL, *frob;
128
  gchar *token;
129
  char *flickr_user_token = NULL;
196
  GError *error = NULL;
197
  GtkWidget *win = dt_ui_main_window(darktable.gui->ui);
198
  if (!gtk_show_uri_on_window(GTK_WINDOW(win), url, gtk_get_current_event_time(), &error))
199
  {
200
    fprintf(stderr, "[flickr] error opening browser: %s\n", error->message);
201
    g_error_free(error);
202
    return FALSE;
203
  }
204
  return TRUE;
205
}
206

  
207

  
208
static char *flickr_check_token(_flickr_api_context_t *ctx)
209
{
210
  CURLcode res;
211
  char *checkUrl;
212
  JsonObject *resp_obj, *oauth_obj, *perms_obj;
213
  JsonParser *parser ;
214
  char *signed_checkUrl, *fk_perms = NULL;
215
  ctx->error_occured=FALSE;
216
  checkUrl = "https://api.flickr.com/services/rest?method=flickr.auth.oauth.checkToken&format=json";
217
  signed_checkUrl = oauth_sign_url2(checkUrl, NULL, OA_HMAC, NULL, API_KEY, SHARED_SECRET,
218
                                    ctx->user_token, ctx->user_token_secret);
219
  GString *response = g_string_new("");
220
  curl_easy_setopt(ctx->curl, CURLOPT_URL, signed_checkUrl);
221
  curl_easy_setopt(ctx->curl, CURLOPT_WRITEDATA, response);
222
  res = curl_easy_perform(ctx->curl);
223
  free(signed_checkUrl);
224
  if (res == CURLE_OK)
225
  {
226
    parser = json_parser_new();
227
    resp_obj = flickr_parse_response(parser, response);
228
    const char *result = json_object_get_string_member(resp_obj, "stat");
229
    if(strcmp(result, "ok") == 0)
230
    {
231
      oauth_obj = json_object_get_object_member(resp_obj, "oauth");
232
      perms_obj = json_object_get_object_member(oauth_obj, "perms");
233
      fk_perms = strdup(json_object_get_string_member(perms_obj, "_content"));
234
    }
235
    else
236
    {
237
      const char *msg = json_object_get_string_member(resp_obj, "message");
238
      fprintf(stderr, "[imageio_storage_flickr] checkToken error : %s\n", msg);
239
      ctx->error_occured = TRUE;
240
      ctx->needsReauthentication = TRUE;
241
    }
242
    g_string_free(response, TRUE);
243
    g_object_unref(parser);
244
    return strdup(fk_perms);
245
  }
246
  else
247
  {
248
    g_string_free(response, TRUE);
249
    ctx->error_occured = TRUE;
250
    return NULL ;
251
  }
252

  
253
}
254

  
255
static gchar *flickr_get_verifier_from_url(GtkWidget *window)
256
{
257
  gchar *text1 = _("step 1: a new window or tab of your browser should have been "
258
                 "loaded. you have to login into your flickr account there "
259
                 "and authorize darktable to upload photos before continuing.");
260
  gchar *text2 = _("step 2: paste the code (xxx-xxx-xxx) and click the OK button once "
261
                 "you are done.");
262

  
263
  GtkDialog *fk_auth_dialog = GTK_DIALOG(gtk_message_dialog_new(GTK_WINDOW(window),
264
                                         GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION,
265
                                        GTK_BUTTONS_OK_CANCEL, _("flickr authentication")));
266
  gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(fk_auth_dialog), "%s\n\n%s", text1, text2);
267

  
268
  GtkWidget *entry = gtk_entry_new();
269
  GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
270
  gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(gtk_label_new(_("Code:"))), FALSE, FALSE, 0);
271
  gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(entry), TRUE, TRUE, 0);
272

  
273
  GtkWidget *fbauthdialog_vbox = gtk_message_dialog_get_message_area(GTK_MESSAGE_DIALOG(fk_auth_dialog));
274
  gtk_box_pack_end(GTK_BOX(fbauthdialog_vbox), hbox, TRUE, TRUE, 0);
275
#ifdef GDK_WINDOWING_QUARTZ
276
    dt_osx_disallow_fullscreen(fk_auth_dialog);
277
#endif
278
  gtk_widget_show_all(GTK_WIDGET(fk_auth_dialog));
279

  
130 280
  gint result;
131
  _flickr_api_context_t *ctx = (_flickr_api_context_t *)g_malloc0(sizeof(_flickr_api_context_t));
281
  gchar *verifier = NULL;
282
  const char *reply;
283
  while (TRUE)
284
  {
285
    result = gtk_dialog_run(GTK_DIALOG(fk_auth_dialog));
286
    if (result == GTK_RESPONSE_CANCEL)
287
      break;
288
    reply = gtk_entry_get_text(GTK_ENTRY(entry));
289
    if (reply == NULL || g_strcmp0(reply, "") == 0)
290
    {
291
      gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(fk_auth_dialog),
292
                                                 "%s\n\n%s\n\n<span foreground=\"" MSGCOLOR_RED
293
                                                 "\" ><small>%s</small></span>",
294
                                                 text1, text2, "please enter the flickr code");
295
      continue;
296
    }
297
    verifier = g_strdup(reply);
298
    if (verifier != NULL) // we have a valid token
299
      break;
300
    else
301
      gtk_message_dialog_format_secondary_markup(
302
          GTK_MESSAGE_DIALOG(fk_auth_dialog),
303
          "%s\n\n%s\n\n<span foreground=\"" MSGCOLOR_RED "\"><small>%s</small></span>", text1, text2,
304
          "the given code is not valid, it should look like: xxx-xxx-xxx");
305
  }
306
  gtk_widget_destroy(GTK_WIDGET(fk_auth_dialog));
132 307

  
133
  flickcurl_init();
134
  ctx->fc = flickcurl_new();
135
  flickcurl_set_api_key(ctx->fc, API_KEY);
136
  flickcurl_set_shared_secret(ctx->fc, SHARED_SECRET);
137
  flickcurl_set_error_handler(ctx->fc, _flickr_api_error_handler, ctx);
308
  return verifier;
309
}
138 310

  
139
  if(!ui->user_token)
311
static _flickr_api_context_t *_flickr_api_authenticate(dt_storage_flickr_gui_data_t *ui)
312
{
313
  char *perms = NULL;
314
  char *flickr_user_token = NULL;
315
  char *flickr_user_token_secret = NULL;
316
  char *flickr_user_nsid = NULL;
317
  char *flickr_user_name = NULL;
318
  _flickr_api_context_t *ctx = (_flickr_api_context_t *)g_malloc0(sizeof(_flickr_api_context_t));
319
  ctx->error_occured=FALSE;
320
  GString *response = g_string_new("");
321
  ctx->curl = curl_easy_init();
322
  curl_easy_setopt(ctx->curl, CURLOPT_VERBOSE, 0L);
323
  curl_easy_setopt(ctx->curl, CURLOPT_WRITEDATA, response);
324
  curl_easy_setopt(ctx->curl, CURLOPT_WRITEFUNCTION, curl_write_data_cb);
325
  curl_easy_setopt(ctx->curl, CURLOPT_SSL_VERIFYPEER, FALSE);
326
  curl_easy_setopt(ctx->curl, CURLOPT_FOLLOWLOCATION, 1L);
327
  curl_easy_setopt(ctx->curl, CURLOPT_TIMEOUT, 20L);
328

  
329
  if(!ui->authenticated)
140 330
  {
141
    // Retrieve stored auth_key
331
    // Retrieve stored oauth token and  secret
142 332
    // TODO: We should be able to store token for different users
143 333
    GHashTable *table = dt_pwstorage_get("flickr");
144 334
    gchar *_username = g_strdup(g_hash_table_lookup(table, "username"));
145 335
    gchar *_user_token = g_strdup(g_hash_table_lookup(table, "token"));
336
    gchar *_user_token_secret = g_strdup(g_hash_table_lookup(table, "secret"));
337
    gchar *_user_nsid = g_strdup(g_hash_table_lookup(table, "nsid"));
146 338
    g_hash_table_destroy(table);
147

  
148
    if(_username)
339
    if(_username && _user_token && _user_token_secret)
149 340
    {
150 341
      if(!strcmp(_username, gtk_entry_get_text(ui->user_entry)))
151 342
      {
152
        flickr_user_token = g_strdup(_user_token);
153
        perms = flickcurl_auth_checkToken(ctx->fc, flickr_user_token);
343
        ctx->user_token = g_strdup(_user_token);
344
        ctx->user_token_secret = g_strdup(_user_token_secret);
345
        ctx->user_nsid = g_strdup(_user_nsid);
346
        ctx->user_name = g_strdup(_username);
347
        perms = flickr_check_token(ctx);
154 348
      }
155 349
      g_free(_username);
156 350
    }
157 351
    g_free(_user_token);
352
    g_free(_user_token_secret);
353
    g_free(_user_nsid);
158 354
  }
159
  else
160
  {
161
    flickr_user_token = ui->user_token;
162
    perms = flickcurl_auth_checkToken(ctx->fc, ui->user_token);
163
  }
164

  
165 355

  
166 356
  if(perms)
167 357
  {
168
    ui->user_token = flickr_user_token;
169
    flickcurl_set_auth_token(ctx->fc, flickr_user_token);
358
    free(perms);
170 359
    return ctx;
171 360
  }
172 361
  else if(!ctx->error_occured)
173 362
  {
174
    frob = flickcurl_auth_getFrob(ctx->fc);
175
    GError *error = NULL;
176
    char *sign = g_strdup_printf("%sapi_key%sfrob%spermswrite", SHARED_SECRET, API_KEY, frob);
177
    char *sign_md5 = g_compute_checksum_for_string(G_CHECKSUM_MD5, sign, strlen(sign));
178
    gchar auth_url[250];
179
    snprintf(auth_url, sizeof(auth_url),
180
             "https://flickr.com/services/auth/?api_key=%s&perms=write&frob=%s&api_sig=%s", API_KEY, frob,
181
             sign_md5);
182

  
363
    int res;
364
    char *auth_key, *auth_secret, *oauth_verifier;
365
    response = g_string_new("");
366
    /*
367
      ask for a request token
368
    */
369
    char *request_token_url = "https://www.flickr.com/services/oauth/request_token&oauth_callback=oob" ;
370
    char *signed_request_token_url = oauth_sign_url2(request_token_url, NULL, OA_HMAC, NULL, API_KEY,
371
                                                     SHARED_SECRET, NULL, NULL);
372
    curl_easy_setopt(ctx->curl, CURLOPT_URL, signed_request_token_url);
373
    curl_easy_setopt(ctx->curl, CURLOPT_WRITEDATA, response);
374
    res = curl_easy_perform(ctx->curl);
375
    free(signed_request_token_url) ;
376
    if (res == CURLE_OK)
377
    {
378
      char *err = NULL ;
379
      err = getParameterValue("oauth_problem",response->str);
380
      if (err) {
381
        dt_control_log(_("Flickr request_token failed"));
382
        free(err);
383
        g_string_free(response, TRUE);
384
        ctx->error_occured = TRUE ;
385
        return NULL ;
386
      }
387
      auth_key = getParameterValue("oauth_token",response->str);
388
      auth_secret = getParameterValue("oauth_token_secret",response->str);
389
    }
390
    else
391
    {
392
      g_string_free(response, TRUE);
393
      ctx->error_occured = TRUE ;
394
      return NULL ;
395
    }
396
    g_string_free(response, TRUE);
397
    /*
398
      the user has to sign on to flickr to get a verifier
399
    */
400
    GString *auth_token_url = g_string_new("https://www.flickr.com/services/oauth/authorize?oauth_token=");
401
    g_string_append(auth_token_url, (gchar *)auth_key);
402

  
403
    _open_browser(auth_token_url->str);
183 404
    GtkWidget *win = dt_ui_main_window(darktable.gui->ui);
184
    if(!gtk_show_uri_on_window(GTK_WINDOW(win), auth_url, gtk_get_current_event_time(), &error))
405
    g_string_free(auth_token_url, TRUE);
406
    oauth_verifier = flickr_get_verifier_from_url(GTK_WIDGET(win));
407
    if (!oauth_verifier) {
408
      dt_print(DT_DEBUG_PWSTORAGE, "[flickr] user cancelled the login process\n");
409
      ctx->error_occured = TRUE ;
410
      return NULL;
411
    }
412
    /*
413
      we can now get an access token
414
    */
415
    GString  *get_perm_token_url = g_string_new("https://www.flickr.com/services/oauth/access_token&oauth_verifier=");
416
    g_string_append(get_perm_token_url , oauth_verifier);
417
    char *signed_get_perm_token_url  = oauth_sign_url2(get_perm_token_url->str, NULL, OA_HMAC, NULL, API_KEY,
418
                                                       SHARED_SECRET, auth_key, auth_secret);
419
    response = g_string_new("");
420
    curl_easy_setopt(ctx->curl, CURLOPT_URL, signed_get_perm_token_url);
421
    curl_easy_setopt(ctx->curl, CURLOPT_WRITEDATA, response);
422
    res = curl_easy_perform(ctx->curl);
423
    g_string_free(get_perm_token_url, TRUE);
424
    free(signed_get_perm_token_url) ;
425
    if (res == CURLE_OK)
185 426
    {
186
      fprintf(stderr, "[flickr] error opening browser: %s\n", error->message);
187
      g_error_free(error);
427
      char *err = NULL ;
428
      err = getParameterValue("oauth_problem",response->str);
429
      if (err) {
430
        dt_control_log(_("Flickr verification code '%s' refused"), oauth_verifier);
431
        free(oauth_verifier);
432
        free(err);
433
        g_string_free(response, TRUE);
434
        ctx->error_occured = TRUE ;
435
        return NULL ;
436
      }
437
      flickr_user_token = getParameterValue("oauth_token",response->str);
438
      flickr_user_token_secret = getParameterValue("oauth_token_secret",response->str);
439
      flickr_user_nsid = getParameterValue("user_nsid",response->str);
440
      flickr_user_name = getParameterValue("username",response->str);
441
      ctx->user_token = strdup(flickr_user_token);
442
      ctx->user_token_secret = strdup(flickr_user_token_secret);
443
      ctx->user_nsid = strdup(flickr_user_nsid);
444
      ctx->user_name = strdup(flickr_user_name);
445
      ui->authenticated = TRUE;
446
      ui->flickr_api = ctx;
447
      ui->flickr_api->needsReauthentication = FALSE;
448
      free(oauth_verifier);
449
      g_string_free(response, TRUE);
450
    }
451
    else
452
    {
453
      free(oauth_verifier);
454
      g_string_free(response, TRUE);
455
      ctx->error_occured = TRUE ;
456
      return NULL ;
457
    }
458
    /* Add creds to pwstorage */
459
    GHashTable *table = g_hash_table_new(g_str_hash, g_str_equal);
460
    g_hash_table_insert(table, "username", flickr_user_name);
461
    g_hash_table_insert(table, "token", flickr_user_token);
462
    g_hash_table_insert(table, "secret", flickr_user_token_secret);
463
    g_hash_table_insert(table, "nsid", flickr_user_nsid);
464

  
465
    if(!dt_pwstorage_set("flickr", table))
466
    {
467
      dt_print(DT_DEBUG_PWSTORAGE, "[flickr] cannot store username/token\n");
188 468
    }
189 469

  
190
    g_free(sign);
191
    g_free(sign_md5);
192

  
193
    // Hold here to let the user interact
194
    // Show a dialog.
195
    gchar *text1, *text2;
196
    text1 = g_strdup(
197
        _("step 1: a new window or tab of your browser should have been loaded. you have to login into your "
198
          "flickr account there and authorize darktable to upload photos before continuing."));
199
    text2 = g_strdup(_("step 2: click the OK button once you are done."));
200

  
201
    GtkWidget *window = dt_ui_main_window(darktable.gui->ui);
202
    GtkWidget *flickr_auth_dialog
203
        = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO,
204
                                 GTK_BUTTONS_OK_CANCEL, _("flickr authentication"));
205
#ifdef GDK_WINDOWING_QUARTZ
206
    dt_osx_disallow_fullscreen(flickr_auth_dialog);
207
#endif
208
    gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(flickr_auth_dialog), "%s\n\n%s", text1, text2);
470
    g_free(flickr_user_token);
471
    g_free(flickr_user_token_secret);
472
    g_free(flickr_user_nsid);
473
    g_free(flickr_user_name);
209 474

  
210
    result = gtk_dialog_run(GTK_DIALOG(flickr_auth_dialog));
475
    g_hash_table_destroy(table);
211 476

  
212
    gtk_widget_destroy(flickr_auth_dialog);
477
    return ctx;
478
  }
479
  return NULL ;
480
}
213 481

  
214
    g_free(text1);
215
    g_free(text2);
216 482

  
217
    switch(result)
218
    {
219
      case GTK_RESPONSE_OK:
220
        token = flickcurl_auth_getToken(ctx->fc, frob);
221
        g_free(frob);
222
        // TODO: Handle timeouts errors
223
        if(token)
224
        {
225
          flickr_user_token = g_strdup(token);
226
        }
227
        else
228
        {
229
          g_free(token);
230
          _flickr_api_free(ctx);
231
          return NULL;
232
        }
233
        ui->user_token = g_strdup(flickr_user_token);
234
        flickcurl_set_auth_token(ctx->fc, flickr_user_token);
235

  
236
        /* Add creds to pwstorage */
237
        GHashTable *table = g_hash_table_new(g_str_hash, g_str_equal);
238
        gchar *username = (gchar *)gtk_entry_get_text(ui->user_entry);
239

  
240
        g_hash_table_insert(table, "username", username);
241
        g_hash_table_insert(table, "token", flickr_user_token);
242

  
243
        if(!dt_pwstorage_set("flickr", table))
244
        {
245
          dt_print(DT_DEBUG_PWSTORAGE, "[flickr] cannot store username/token\n");
246
        }
247

  
248
        g_free(flickr_user_token);
249
        g_hash_table_destroy(table);
250

  
251
        return ctx;
252

  
253
      default:
254
        dt_print(DT_DEBUG_PWSTORAGE, "[flickr] user cancelled the login process\n");
255
        return NULL;
256
    }
257
  }
258 483

  
259
  free(perms);
260 484

  
261
  return NULL;
485
static _flickr_album_t *flickr_photoset_getInfo(_flickr_api_context_t *ctx, const char *albumid)
486
{
487
  GString *photosetInfo_url ;
488
  CURLcode res;
489
  _flickr_album_t *a = (_flickr_album_t *)g_malloc0(sizeof(_flickr_album_t));
490
  ctx->error_occured = FALSE;
491
  photosetInfo_url = g_string_new("https://api.flickr.com/services/rest/?method=flickr.photosets.getInfo&api_key=");
492
  g_string_append(photosetInfo_url, API_KEY);
493
  g_string_append(photosetInfo_url, "&user_id=");
494
  g_string_append(photosetInfo_url, ctx->user_nsid);
495
  g_string_append(photosetInfo_url, "&photoset_id=");
496
  g_string_append(photosetInfo_url, albumid);
497
  g_string_append(photosetInfo_url, "&format=json");
498
  char *signed_photosetInfo_url= oauth_sign_url2(photosetInfo_url->str, NULL, OA_HMAC, NULL, API_KEY,
499
                                                 SHARED_SECRET, ctx->user_token, ctx->user_token_secret);
500
  GString *response = g_string_new("");
501
  curl_easy_setopt(ctx->curl, CURLOPT_URL, signed_photosetInfo_url);
502
  curl_easy_setopt(ctx->curl, CURLOPT_WRITEDATA, response);
503
  res = curl_easy_perform(ctx->curl);
504
  g_string_free(photosetInfo_url, TRUE);
505
  free(signed_photosetInfo_url);
506
  if (res !=CURLE_OK)
507
  {
508
    g_string_free(response, TRUE);
509
    ctx->error_occured = TRUE;
510
    return NULL;
511
  }
512
  JsonParser *parser = json_parser_new();
513
  JsonObject *respobj = flickr_parse_response(parser, response);
514
  const char *result = json_object_get_string_member(respobj, "stat");
515
  if(strcmp(result, "ok") == 0)
516
  {
517
    JsonObject *albobj = json_object_get_object_member(respobj, "photoset");
518
    JsonObject *otitle = json_object_get_object_member(albobj, "title");
519
    const int  count = json_object_get_int_member(albobj, "count_photos");
520
    const char *name = json_object_get_string_member(otitle, "_content");
521
    JsonObject *desc = json_object_get_object_member(albobj, "description");
522
    const char *sdesc = json_object_get_string_member(desc, "_content");
523
    a->id = strdup(albumid) ;
524
    a->title = strdup(name) ;
525
    a->summary = strdup(sdesc);
526
    a->photos_count = count ;
527
  }
528
  else
529
  {
530
    const char *msg = json_object_get_string_member(respobj, "message");
531
    fprintf(stderr, "[imageio_storage_flickr] photoset getInfo error : %s\n", msg);
532
    ctx->error_occured = TRUE;
533
  }
534
  g_string_free(response, TRUE);
535
  g_object_unref(parser);
536
  return a;
262 537
}
263 538

  
264 539

  
265
static flickcurl_upload_status *_flickr_api_upload_photo(dt_storage_flickr_params_t *p, char *fname,
266
                                                         char *caption, char *description, gint imgid)
540
char *flickr_photo_upload(_flickr_api_context_t *ctx, flickr_upload_params *p)
267 541
{
542
  CURLcode res;
543
  char *postargs = NULL;
544
  char *photo_id = NULL;
545
  ctx->error_occured = FALSE;
546
  GString *upload_url=g_string_new("https://up.flickr.com/services/upload/?");
547
  g_string_append(upload_url, "content_type=1&safety_level=1");
548
  if (p->title)
549
  {
550
    g_string_append(upload_url, "&title=");
551
    g_string_append(upload_url, p->title);
552
  }
553
  if (p->description)
554
  {
555
    g_string_append(upload_url, "&description=");
556
    g_string_append(upload_url, p->description);
557
  }
558
  if (p->tags)
559
  {
560
    g_string_append(upload_url, "&tags=");
561
    g_string_append(upload_url, p->tags);
562
  }
563
  if (p->is_public) g_string_append(upload_url, "&is_public=1");
564
  if (p->is_friend) g_string_append(upload_url, "&is_friend=1");
565
  if (p->is_public) g_string_append(upload_url, "&is_family=1");
566
  char *signed_upload_url= oauth_sign_url2(upload_url->str, &postargs, OA_HMAC, "POST", API_KEY,
567
                                            SHARED_SECRET, ctx->user_token, ctx->user_token_secret);
568
  GString *response = g_string_new("");
569
  curl_easy_setopt(ctx->curl, CURLOPT_URL, signed_upload_url);
570
  curl_easy_setopt(ctx->curl, CURLOPT_POST, 1);
571
  curl_easy_setopt(ctx->curl, CURLOPT_WRITEDATA, response);
572
  curl_mime *form = NULL;
573
  curl_mimepart *field = NULL;
574
  form = curl_mime_init(ctx->curl);
575
  gchar **params = g_strsplit (postargs, "&", 15);
576
  gchar **vals ;
577
  char *uval;
578
  int g = 0 ;
579
  while (params[g] != NULL)
580
  {
581
    vals = g_strsplit (params[g], "=", 2);
582
    field = curl_mime_addpart(form);
583
    curl_mime_name(field, vals[0]);
584
    uval = g_uri_unescape_string(vals[1],NULL) ;   // mandatory : signature
585
    curl_mime_data(field, uval , CURL_ZERO_TERMINATED);
586
    g_strfreev(vals);
587
    free(uval);
588
    g++ ;
589
  }
590
  free(postargs);
591
  g_strfreev(params);
592
  field = curl_mime_addpart(form);
593
  curl_mime_name(field, "photo");
594
  curl_mime_type(field, "image/jpeg");
595
  curl_mime_filedata(field, p->photo_file);
596
  curl_easy_setopt(ctx->curl, CURLOPT_MIMEPOST, form);
597
  res = curl_easy_perform(ctx->curl);
598
  curl_easy_setopt(ctx->curl, CURLOPT_POST, 0); // reset to default
599
  curl_mime_free(form);
600
  free(signed_upload_url);
601
  g_string_free(upload_url, TRUE);
602
  if (res == CURLE_OK)
603
  {
604
    // no json available here ...
605
    xmlDoc *doc = NULL;
606
    xmlNode *root_element = NULL;
607
    const xmlChar *result = xmlCharStrdup("stat");
608
    doc = xmlReadDoc((xmlChar *)(response->str), NULL, NULL, XML_PARSE_NOBLANKS) ;
609
    root_element = xmlDocGetRootElement(doc) ;
610
    if(strcmp((char *)xmlGetProp(root_element,result), "ok") == 0)
611
    {
612
      photo_id = strdup((char *)root_element->children->children->content) ;
613
    }
614
    xmlFreeDoc(doc);
615
    xmlCleanupParser();
616
  }
617
  g_string_free(response, TRUE);
618
  return(photo_id);
619
}
620

  
268 621

  
269
  flickcurl_upload_params *params = g_malloc0(sizeof(flickcurl_upload_params));
270
  flickcurl_upload_status *status;
271 622

  
623

  
624
static char *upload_photo(dt_storage_flickr_params_t *p, char *fname,
625
                                      char *caption, char *description, gint imgid)
626
{
627
  flickr_upload_params *params = g_malloc0(sizeof(flickr_upload_params));
628
  char *photo_id;
272 629
  params->safety_level = 1; // Defaults to safe photos
273 630
  params->content_type = 1; // Defaults to photo (we don't support video!)
274

  
275 631
  params->title = caption;
276 632
  params->description = description;
277

  
278 633
  if(imgid)
279 634
  {
280 635
    GList *tags_list = dt_tag_get_list(imgid);
281 636
    params->tags = dt_util_glist_to_str(",", tags_list);
282 637
    g_list_free_full(tags_list, g_free);
283 638
  }
639

  
284 640
  params->photo_file = fname; // fname should be the URI of temp file
285 641

  
286 642
  params->is_public = (int)p->public_perm;
287 643
  params->is_friend = (int)p->friend_perm;
288 644
  params->is_family = (int)p->family_perm;
289 645

  
290
  status = flickcurl_photos_upload_params(p->flickr_api->fc, params);
291
  if(!status)
646
  photo_id = flickr_photo_upload(p->flickr_api, params);
647
  if(!photo_id)
292 648
  {
293 649
    fprintf(stderr, "[flickr] Something went wrong when uploading");
294 650
    g_free((gchar *)params->tags);
......
297 653
  }
298 654
  g_free((gchar *)params->tags);
299 655
  g_free(params);
300
  return status;
656
  return photo_id;
301 657
}
302 658

  
303

  
304
static char *_flickr_api_create_photoset(_flickr_api_context_t *ctx, const char *photo_id)
659
char *flickr_create_album(_flickr_api_context_t *ctx, const char *photo_id)
305 660
{
306
  char *photoset;
661
  char *photoset_id = NULL ;
307 662
  const char *title = ctx->album_title;
308 663
  const char *summary = ctx->album_summary;
664
  CURLcode res;
665
  char *postargs = NULL;
666
  ctx->error_occured = FALSE;
667
  GString *rest_url=g_string_new("https://api.flickr.com/services/rest/?method=flickr.photosets.create")  ;
668
  g_string_append(rest_url, "&title=");
669
  g_string_append(rest_url, title);
670
  g_string_append(rest_url, "&description=");
671
  g_string_append(rest_url, summary);
672
  g_string_append(rest_url, "&primary_photo_id=");
673
  g_string_append(rest_url, photo_id);
674
  g_string_append(rest_url, "&format=json");
675
  char *signed_rest_url= oauth_sign_url2(rest_url->str, &postargs, OA_HMAC, "POST", API_KEY, SHARED_SECRET,
676
                                         ctx->user_token, ctx->user_token_secret);
677
  GString *response = g_string_new("");
678
  curl_easy_setopt(ctx->curl, CURLOPT_URL, signed_rest_url);
679
  curl_easy_setopt(ctx->curl, CURLOPT_POST, 1);
680
  curl_easy_setopt(ctx->curl, CURLOPT_WRITEDATA, response);
681
  curl_mime *form = NULL;
682
  curl_mimepart *field = NULL;
683
  form = curl_mime_init(ctx->curl);
684
  gchar **params = g_strsplit (postargs, "&", 15);
685
  gchar **vals ;
686
  char *uval;
687
  int g = 0 ;
688
  while (params[g] != NULL)
689
  {
690
    vals = g_strsplit (params[g], "=", 2);
691
    field = curl_mime_addpart(form);
692
    curl_mime_name(field, vals[0]);
693
    uval = g_uri_unescape_string(vals[1],NULL) ;   // mandatory : signature
694
    curl_mime_data(field, uval , CURL_ZERO_TERMINATED);
695
    free(uval);
696
    g_strfreev(vals);
697
    g++ ;
698
  }
699
  g_strfreev(params);
700
  free(postargs);
701
  curl_easy_setopt(ctx->curl, CURLOPT_MIMEPOST, form);
702
  res = curl_easy_perform(ctx->curl);
703
  curl_easy_setopt(ctx->curl, CURLOPT_POST, 0); // reset to default
704
  curl_mime_free(form);
705
  free(signed_rest_url);
706
  g_string_free(rest_url, TRUE);
707
  if (res == CURLE_OK)
708
  {
709
    JsonParser *parser = json_parser_new();
710
    JsonObject *respobj = flickr_parse_response(parser, response);
711
    const char *result = json_object_get_string_member(respobj, "stat");
712
    if(strcmp(result, "ok") == 0)
713
    {
714
      JsonObject *jphotoset = json_object_get_object_member(respobj, "photoset");
715
      const char *jphotoset_id = json_object_get_string_member(jphotoset, "id");
716
      photoset_id  = strdup(jphotoset_id);
717
    }
718
    else
719
    {
720
      const char *msg = json_object_get_string_member(respobj, "message");
721
      fprintf(stderr, "[imageio_storage_flickr] create album error : %s\n", msg);
722
      ctx->error_occured = TRUE;
723
    }
724
    g_object_unref(parser);
725
  }
726
  g_string_free(response, TRUE);
727
  return(photoset_id);
728
}
729

  
309 730

  
310
  photoset = flickcurl_photosets_create(ctx->fc, title, summary, photo_id, NULL);
311
  if(!photoset) fprintf(stderr, "[flickr] Something went wrong when creating gallery %s", title);
312
  return photoset;
731

  
732

  
733
gboolean flickr_photoset_addPhoto(_flickr_api_context_t *ctx, char *album_id, char * photo_id)
734
{
735
  CURLcode res;
736
  char *postargs = NULL;
737
  ctx->error_occured = FALSE;
738
  GString *rest_url=g_string_new("https://api.flickr.com/services/rest/?method=flickr.photosets.addPhoto")  ;
739
  g_string_append(rest_url, "&photoset_id=");
740
  g_string_append(rest_url, album_id);
741
  g_string_append(rest_url, "&photo_id=");
742
  g_string_append(rest_url, photo_id);
743
  g_string_append(rest_url, "&format=json");
744
  char *signed_rest_url= oauth_sign_url2(rest_url->str, &postargs, OA_HMAC, "POST", API_KEY, SHARED_SECRET,
745
                                          ctx->user_token, ctx->user_token_secret);
746
  GString *response = g_string_new("");
747
  curl_easy_setopt(ctx->curl, CURLOPT_URL, signed_rest_url);
748
  curl_easy_setopt(ctx->curl, CURLOPT_POST, 1);
749
  curl_easy_setopt(ctx->curl, CURLOPT_WRITEFUNCTION, curl_write_data_cb);
750
  curl_easy_setopt(ctx->curl, CURLOPT_WRITEDATA, response);
751
  curl_mime *form = NULL;
752
  curl_mimepart *field = NULL;
753
  form = curl_mime_init(ctx->curl);
754
  gchar **params = g_strsplit (postargs, "&", 15);
755
  gchar **vals ;
756
  char *uval;
757
  int g = 0 ;
758
  while (params[g] != NULL)
759
  {
760
    vals = g_strsplit (params[g], "=", 2);
761
    field = curl_mime_addpart(form);
762
    curl_mime_name(field, vals[0]);
763
    uval = g_uri_unescape_string(vals[1],NULL) ;   // mandatory : signature
764
    curl_mime_data(field, uval , CURL_ZERO_TERMINATED);
765
    g_strfreev(vals);
766
    free(uval);
767
    g++ ;
768
  }
769
  g_strfreev(params);
770
  free(postargs);
771
  curl_easy_setopt(ctx->curl, CURLOPT_MIMEPOST, form);
772
  res = curl_easy_perform(ctx->curl);
773
  curl_easy_setopt(ctx->curl, CURLOPT_POST, 0); // reset to default
774
  curl_mime_free(form);
775
  g_string_free(rest_url, TRUE);
776
  free(signed_rest_url);
777
  if (res == CURLE_OK)
778
  {
779
    JsonParser *parser = json_parser_new();
780
    JsonObject *respobj = flickr_parse_response(parser, response);
781
    const char *result = json_object_get_string_member(respobj, "stat");
782
    if(strcmp(result, "ok") != 0)
783
    {
784
      const char *msg = json_object_get_string_member(respobj, "message");
785
      fprintf(stderr, "[imageio_storage_flickr] photoset addPhoto error : %s\n", msg);
786
      ctx->error_occured = TRUE;
787
    }
788
    g_object_unref(parser);
789
  }
790
  g_string_free(response, TRUE);
791
  return (!ctx->error_occured) ;
313 792
}
314 793

  
315 794
const char *name(const struct dt_imageio_module_storage_t *self)
......
333 812
  if(ui->flickr_api != NULL)
334 813
  {
335 814
    ui->flickr_api->needsReauthentication = TRUE;
336
    g_free(ui->user_token);
337
    ui->user_token = NULL;
338 815
    set_status(ui, _("not authenticated"), "#e07f7f");
339 816
    gtk_widget_set_sensitive(GTK_WIDGET(ui->album_list), FALSE);
340 817
  }
341 818
}
342 819

  
343
static flickcurl_photoset **_flickr_api_photosets(_flickr_api_context_t *ctx, const char *user)
820
static _flickr_album_t **flickr_photosets_getList(_flickr_api_context_t *ctx)
344 821
{
345
  flickcurl_photoset **photoset;
346
  //  char *nsid;
347

  
348
  // TODO: Support both userid and email. As more services uses email as username
349
  //      users can confuse the needed id to be introduced in the user field.
350
  //  nsid = flickcurl_people_findByEmail(ctx->fc, "@");
351

  
352
  //  no need to specify nsid at all
353
  //  nsid = flickcurl_people_findByUsername(ctx->fc, user);
354

  
355
  // "If none is specified, the calling user is assumed (or NULL) "
356
  // (c) http://librdf.org/flickcurl/api/flickcurl-section-photoset.html#flickcurl-photosets-getList
357
  photoset = flickcurl_photosets_getList(ctx->fc, NULL);
358

  
359
  return photoset;
822
  CURLcode res;
823
  gint i, nb_albums;
824
  _flickr_album_t **albums = NULL ;
825
  ctx->error_occured = FALSE;
826
  GString *photoset_url = g_string_new("https://api.flickr.com/services/rest/?method=flickr.photosets.getList&api_key=");
827
  g_string_append(photoset_url, API_KEY);
828
  g_string_append(photoset_url, "&user_id=");
829
  g_string_append(photoset_url, ctx->user_nsid);
830
  g_string_append(photoset_url, "&format=json");
831
  char *signed_photoset_url= oauth_sign_url2(photoset_url->str, NULL, OA_HMAC, NULL, API_KEY, SHARED_SECRET,
832
                                             ctx->user_token, ctx->user_token_secret);
833
  GString *response = g_string_new("");
834
  curl_easy_setopt(ctx->curl, CURLOPT_URL, signed_photoset_url);
835
  curl_easy_setopt(ctx->curl, CURLOPT_WRITEDATA, response);
836
  res = curl_easy_perform(ctx->curl);
837
  free(signed_photoset_url);
838
  g_string_free(photoset_url, TRUE);
839
  if(res != CURLE_OK)
840
  {
841
    g_string_free(response, TRUE);
842
    return NULL;
843
  }
844
  JsonParser *parser = json_parser_new();
845
  JsonObject *respobj = flickr_parse_response(parser, response);
846
  const char *result = json_object_get_string_member(respobj, "stat");
847
  if(strcmp(result, "ok") == 0)
848
  {
849
    JsonObject *albs = json_object_get_object_member(respobj, "photosets");
850
    JsonArray *jsalbums = json_object_get_array_member(albs, "photoset");
851
    if (jsalbums != NULL)
852
    {
853
      nb_albums = json_array_get_length(jsalbums) ;
854
      albums = g_malloc0( (nb_albums + 1) * sizeof(_flickr_album_t *));
855
      for (i = 0; i < nb_albums; i++)
856
      {
857
        JsonObject *obj = json_array_get_object_element(jsalbums, i);
858
        if (obj == NULL) continue ;
859
        const char *id = json_object_get_string_member(obj, "id");
860
        JsonObject *otitle = json_object_get_object_member(obj, "title");
861
        const char *name = json_object_get_string_member(otitle, "_content");
862
        const int photos = json_object_get_int_member(obj, "photos");
863
        albums[i] = g_malloc0(sizeof(_flickr_album_t));
864
        albums[i]->id = g_strdup(id);
865
        albums[i]->title = g_strdup(name);
866
        albums[i]->photos_count = photos ;
867
      }
868
    }
869
  }
870
  else
871
  {
872
    const char *msg = json_object_get_string_member(respobj, "message");
873
    fprintf(stderr, "[imageio_storage_flickr] photoset getList error: %s\n", msg);
874
    ctx->error_occured = TRUE;
875
  }
876
  g_object_unref(parser);
877
  g_string_free(response, TRUE);
878
  return albums;
360 879
}
361 880

  
362 881
/** Refresh albums */
......
383 902

  
384 903
  // First clear the cobobox except first 2 items (none / create new album)
385 904
  dt_bauhaus_combobox_clear(ui->album_list);
386

  
387
  ui->albums = _flickr_api_photosets(ui->flickr_api, gtk_entry_get_text(ui->user_entry));
905
  if (ui->albums)
906
  {
907
    for(i=0; ui->albums[i]; i++)
908
    {
909
      free(ui->albums[i]->id) ;
910
      free(ui->albums[i]->title) ;
911
      free(ui->albums[i]);
912
    }
913
    free(ui->albums);
914
  }
915
  ui->albums = flickr_photosets_getList(ui->flickr_api);
388 916
  if(ui->albums)
389 917
  {
390

  
391 918
    // Add standard action
392 919
    dt_bauhaus_combobox_add(ui->album_list, _("without album"));
393 920
    dt_bauhaus_combobox_add(ui->album_list, _("create new album"));
......
569 1096
  /**
570 1097
  don't populate the combo on startup, save 3 second
571 1098

  
572
  // If username and password is stored, let's populate the combo
573
  if( _username && _password )
574
  {
575
    ui->user_token = _password;
576
    refresh_albums(ui);
577
  }
578 1099
  */
579 1100

  
580 1101
  g_free(_username);
......
587 1108
  dt_gui_key_accel_block_on_focus_disconnect(GTK_WIDGET(ui->user_entry));
588 1109
  dt_gui_key_accel_block_on_focus_disconnect(GTK_WIDGET(ui->title_entry));
589 1110
  dt_gui_key_accel_block_on_focus_disconnect(GTK_WIDGET(ui->summary_entry));
1111
  if (ui->albums)
1112
  {
1113
    for(int i=0; ui->albums[i]; i++)
1114
    {
1115
      free(ui->albums[i]->id) ;
1116
      free(ui->albums[i]->title) ;
1117
      free(ui->albums[i]);
1118
    }
1119
    free(ui->albums);
1120
  }
590 1121
  g_free(self->gui_data);
591 1122
}
592 1123

  
......
601 1132
{
602 1133
  gint result = 0;
603 1134
  dt_storage_flickr_params_t *p = (dt_storage_flickr_params_t *)sdata;
604
  flickcurl_upload_status *photo_status;
1135
  char *photo_id;
605 1136
  gint tags = 0;
606 1137

  
607 1138
  const char *ext = format->extension(fdata);
......
666 1197
    // Upload image
667 1198
    // Do we export tags?
668 1199
    if(p->export_tags == TRUE) tags = imgid;
669
    photo_status = _flickr_api_upload_photo(p, fname, caption, description, tags);
1200
    photo_id = upload_photo(p, fname, caption, description, tags);
670 1201
  }
671 1202

  
672
  if(!photo_status)
1203
  if(!photo_id)
673 1204
  {
674 1205
    fprintf(stderr, "[imageio_storage_flickr] could not upload to flickr!\n");
675 1206
    dt_control_log(_("could not upload to flickr!"));
......
681 1212
  // A photoset is only created if we have an album title set
682 1213
  if(p->flickr_api->current_album == NULL && p->flickr_api->new_album == TRUE)
683 1214
  {
684
    char *photoset_id;
685
    photoset_id = _flickr_api_create_photoset(p->flickr_api, photo_status->photoid);
1215
    char *photoset_id = NULL;
1216
    photoset_id = flickr_create_album(p->flickr_api, photo_id);
1217
    fprintf(stderr, "[imageio_storage_flickr] photoset_id = %s\n", photoset_id );
686 1218

  
687 1219
    if(photoset_id == NULL)
688 1220
    {
......
691 1223
    }
692 1224
    else
693 1225
    {
694
      //      p->flickr_api->new_album = FALSE;
695
      p->flickr_api->current_album = flickcurl_photosets_getInfo(p->flickr_api->fc, photoset_id);
1226
      p->flickr_api->current_album = flickr_photoset_getInfo(p->flickr_api, photoset_id);
1227
      free(photoset_id);
696 1228
    }
1229

  
697 1230
  }
698 1231

  
699 1232
  //  if(fail) return 1;
......
702 1235
  // Add to gallery, if needed
703 1236
  if(p->flickr_api->current_album != NULL && p->flickr_api->new_album != TRUE)
704 1237
  {
705
    flickcurl_photosets_addPhoto(p->flickr_api->fc, p->flickr_api->current_album->id, photo_status->photoid);
1238
    flickr_photoset_addPhoto(p->flickr_api, p->flickr_api->current_album->id, photo_id);
706 1239
    // TODO: Check for errors adding photo to gallery
707 1240
  }
708 1241
  else
......
712 1245
      p->flickr_api->new_album = FALSE;
713 1246
    }
714 1247
  }
1248
  free(photo_id);
715 1249

  
716 1250
cleanup:
717 1251

  
......
771 1305
        default:
772 1306
          // use existing album
773 1307
          d->flickr_api->current_album
774
              = flickcurl_photosets_getInfo(d->flickr_api->fc, ui->albums[index - 2]->id);
1308
              = flickr_photoset_getInfo(d->flickr_api, ui->albums[index - 2]->id);
775 1309
          if(d->flickr_api->current_album == NULL)
776 1310
          {
777 1311
            // Something went wrong...
......
843 1377
  return d;
844 1378
}
845 1379

  
1380

  
1381

  
846 1382
int set_params(dt_imageio_module_storage_t *self, const void *params, const int size)
847 1383
{
848 1384
  if(size != self->params_size(self)) return 1;
849
- 
Go to top