Example #1
0
_flickr_api_context_t static *_flickr_api_authenticate(dt_storage_flickr_gui_data_t *ui)
{
  char *perms = NULL, *frob;
  gchar *token;
  char *flickr_user_token = NULL;
  gint result;
  _flickr_api_context_t *ctx = (_flickr_api_context_t *)g_malloc(sizeof(_flickr_api_context_t));
  memset(ctx,0,sizeof(_flickr_api_context_t));

  flickcurl_init ();
  ctx->fc = flickcurl_new ();
  flickcurl_set_api_key (ctx->fc, API_KEY);
  flickcurl_set_shared_secret (ctx->fc, SHARED_SECRET);
  flickcurl_set_error_handler(ctx->fc, _flickr_api_error_handler, ctx);

  if (!ui->user_token)
  {
    // Retrieve stored auth_key
    // TODO: We should be able to store token for different users
    GHashTable* table = dt_pwstorage_get("flickr");
    gchar * _username = g_strdup( g_hash_table_lookup(table, "username"));
    gchar *_user_token = g_strdup( g_hash_table_lookup(table, "token"));
    g_hash_table_destroy(table);

    if (_username)
    {
      if (!strcmp(_username,gtk_entry_get_text(ui->entry1)))
      {
        flickr_user_token = g_strdup(_user_token);
        perms = flickcurl_auth_checkToken(ctx->fc, flickr_user_token);
      }
      g_free (_username);
    }
    if (_user_token)
      g_free (_user_token);
  }
  else
  {
    flickr_user_token = ui->user_token;
    perms = flickcurl_auth_checkToken(ctx->fc, ui->user_token);
  }


  if (perms)
  {
    ui->user_token = flickr_user_token;
    flickcurl_set_auth_token(ctx->fc, flickr_user_token);
    return ctx;

  }
  else if (!ctx->error_occured)
  {
    frob = flickcurl_auth_getFrob(ctx->fc);
    GError *error = NULL;
    char *sign = g_strdup_printf ("%sapi_key%sfrob%spermswrite", SHARED_SECRET, API_KEY, frob);
    char *sign_md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, sign, strlen (sign));
    gchar auth_url[250];
    sprintf(auth_url,"http://flickr.com/services/auth/?api_key=%s&perms=write&frob=%s&api_sig=%s", API_KEY, frob, sign_md5);

    gtk_show_uri (gdk_screen_get_default(), auth_url, gtk_get_current_event_time (), &error);

    g_free(sign);
    g_free(sign_md5);

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

    GtkWidget *window = dt_ui_main_window(darktable.gui->ui);
    GtkWidget *flickr_auth_dialog = gtk_message_dialog_new (GTK_WINDOW (window),
                                    GTK_DIALOG_DESTROY_WITH_PARENT,
                                    GTK_MESSAGE_INFO,
                                    GTK_BUTTONS_OK_CANCEL,
                                    _("flickr authentication"));
    gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (flickr_auth_dialog),
        "%s\n\n%s", text1, text2);

    result = gtk_dialog_run (GTK_DIALOG (flickr_auth_dialog));

    gtk_widget_destroy(flickr_auth_dialog);

    g_free (text1);
    g_free (text2);

    switch (result)
    {
      case GTK_RESPONSE_OK:
        token = flickcurl_auth_getToken(ctx->fc, frob);
        g_free(frob);
        // TODO: Handle timeouts errors
        if (token)
        {
          flickr_user_token = g_strdup (token);
        }
        else
        {
          g_free(token);
          _flickr_api_free(ctx);
          return NULL;
        }
        ui->user_token = g_strdup(flickr_user_token);
        flickcurl_set_auth_token(ctx->fc, flickr_user_token);

        /* Add creds to pwstorage */
        GHashTable *table = g_hash_table_new(g_str_hash, g_str_equal);
        gchar* username = g_strdup(gtk_entry_get_text(ui->entry1));

        g_hash_table_insert(table, "username", username);
        g_hash_table_insert(table, "token", flickr_user_token);

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

        g_free(flickr_user_token);
        g_hash_table_destroy(table);

        return ctx;
        break;

      default:
        dt_print(DT_DEBUG_PWSTORAGE,"[flickr] user cancelled the login process\n");
        return NULL;
    }
  }

  if (perms)
    free(perms);

  return NULL;
}
Example #2
0
int
main(int argc, char *argv[]) 
{
  flickcurl *fc = NULL;
  int rc = 0;
  int usage = 0;
  int help = 0;
  int read_auth = 1;
  int i;
  const char* home;
  char config_path[1024];
  int request_delay= -1;
  char section[50];
  size_t section_len;
  char** methods = NULL;
  
  flickcurl_init();
  
  program = my_basename(argv[0]);

  home = getenv("HOME");
  if(home)
    sprintf(config_path, "%s/%s", home, config_filename);
  else
    strcpy(config_path, config_filename);
  

  while (!usage && !help)
  {
    int c;
#ifdef HAVE_GETOPT_LONG
    int option_index = 0;

    c = getopt_long (argc, argv, GETOPT_STRING, long_options, &option_index);
#else
    c = getopt (argc, argv, GETOPT_STRING);
#endif
    if (c == -1)
      break;

    switch (c) {
      case 0:
      case '?': /* getopt() - unknown option */
        usage = 1;
        break;

      case 'd':
        if(optarg)
          request_delay = atoi(optarg);
        break;
        
      case 'h':
        help = 1;
        break;

      case 'v':
        fputs(flickcurl_version_string, stdout);
        fputc('\n', stdout);

        exit(0);
    }
    
  }
  
  if(help)
    goto help;
  
  if(argc < 2) {
    fprintf(stderr, "%s: No API section given\n", program);
    usage = 1;
  }

  if(usage) {
    if(usage>1) {
      fprintf(stderr, title_format_string, flickcurl_version_string);
      fputs("Flickcurl home page: ", stderr);
      fputs(flickcurl_home_url_string, stderr);
      fputc('\n', stderr);
      fputs(flickcurl_copyright_string, stderr);
      fputs("\nLicense: ", stderr);
      fputs(flickcurl_license_string, stderr);
      fputs("\n\n", stderr);
    }
    fprintf(stderr, "Try `%s " HELP_ARG(h, help) "' for more information.\n",
            program);
    rc = 1;
    goto tidy;
  }

  help:
  if(help) {
    printf(title_format_string, flickcurl_version_string);
    puts("Generate C code from Flickr API by reflection.");
    printf("Usage: %s [OPTIONS] command args...\n\n", program);

    fputs(flickcurl_copyright_string, stdout);
    fputs("\nLicense: ", stdout);
    puts(flickcurl_license_string);
    fputs("Flickcurl home page: ", stdout);
    puts(flickcurl_home_url_string);

    fputs("\n", stdout);

    puts(HELP_TEXT("d", "delay DELAY     ", "Set delay between requests in milliseconds"));
    puts(HELP_TEXT("h", "help            ", "Print this help, then exit"));
    puts(HELP_TEXT("v", "version         ", "Print the flickcurl version"));

    rc = 0;
    goto tidy;
  }


  /* Initialise the Flickcurl library */
  fc = flickcurl_new();
  if(!fc) {
    rc = 1;
    goto tidy;
  }

  flickcurl_set_error_handler(fc, my_message_handler, NULL);

  if(read_auth && !access((const char*)config_path, R_OK)) {
    if(read_ini_config(config_path, config_section, fc,
                       my_set_config_var_handler)) {
      fprintf(stderr, "%s: Failed to read config filename %s: %s\n",
              program, config_path, strerror(errno));
      rc = 1;
      goto tidy;
    }
  }

  if(request_delay >= 0)
    flickcurl_set_request_delay(fc, request_delay);

  strcpy(section, "flickr.");
  strcpy(section+7, argv[1]);
  
  /* allow old format commands to work */
  for(i = 0; section[i]; i++) {
    if(section[i] == '-')
      section[i] = '.';
  }
  
  if(!strncmp(section, "flickr.flickr", 13))
    strcpy(section, section+7);
  section_len = strlen(section);
  
  fprintf(stderr, "%s: section '%s'\n", program, section);
    
  methods = flickcurl_reflection_getMethods(fc);
  if(!methods) {
    fprintf(stderr, "%s: getMethods failed\n", program);
    rc = 1;
    goto tidy;
  }

  fprintf(stdout,
"/* -*- Mode: c; c-basic-offset: 2 -*-\n"
" *\n"
" * %s-api.c - Flickr %s.* API calls\n"
" *\n",
          argv[1], section);

  fprintf(stdout,
" * Copyright (C) 2010, David Beckett http://www.dajobe.org/\n"
" * \n"
" * This file is licensed under the following three licenses as alternatives:\n"
" *   1. GNU Lesser General Public License (LGPL) V2.1 or any newer version\n"
" *   2. GNU General Public License (GPL) V2 or any newer version\n"
" *   3. Apache License, V2.0 or any newer version\n"
" * \n"
" * You may not use this file except in compliance with at least one of\n"
" * the above three licenses.\n"
" * \n"
" * See LICENSE.html or LICENSE.txt at the top of this package for the\n"
" * complete terms and further detail along with the license texts for\n"
" * the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.\n"
" * \n"
" */\n"
"\n"
"#include <stdio.h>\n"
"#include <string.h>\n"
"#include <stdarg.h>\n"
"\n"
"#ifdef HAVE_CONFIG_H\n"
"#include <config.h>\n"
"#endif\n"
"\n"
"#ifdef HAVE_STDLIB_H\n"
"#include <stdlib.h>\n"
"#undef HAVE_STDLIB_H\n"
"#endif\n"
"#ifdef HAVE_UNISTD_H\n"
"#include <unistd.h>\n"
"#endif\n"
"\n"
"#include <flickcurl.h>\n"
"#include <flickcurl_internal.h>\n"
"\n"
"\n"
          );

  
  for(i = 0; methods[i]; i++) {
    flickcurl_method* method;
    char* method_name;
    char function_name[100];
    int c, j;
    int is_write = 0;
    
    if(strncmp(methods[i], section, section_len))
      continue;
    
    method = flickcurl_reflection_getMethodInfo(fc, methods[i]);
    if(!method) {
      fprintf(stderr, "%s: getMethodInfo(%s) failed\n", program, methods[i]);
      rc = 1;
      break;
    }

    method_name = method->name;

    if(
      strstr(method_name, ".add") ||
      strstr(method_name, ".create") ||
      strstr(method_name, ".delete") ||
      strstr(method_name, ".edit") ||
      strstr(method_name, ".remove") ||
      strstr(method_name, ".set")
       )
      is_write = 1;
    
    strcpy(function_name, "flickcurl_");
    for(j = 0; (c = methods[i][j+7]); j++) {
      if(c == '.')
        c = '_';
      function_name[j+10] = c;
    }
    function_name[j+10] = '\0';

    fprintf(stdout, "/**\n * %s:\n", function_name);

    /* fixed arguments */
    fprintf(stdout, " * @fc: flickcurl context\n");

    if(method->args_count) {
      int argi;
      for(argi = 0; method->args[argi]; argi++) {
        flickcurl_arg* arg = method->args[argi];
        if(!strcmp(arg->name, "api_key"))
          continue;

        fprintf(stdout, " * @%s: %s", arg->name, arg->description);
        if(arg->optional) {
          fputs((IS_INT_ARG(arg)? " (or < 0)" : " (or NULL)"), stdout);
        }
        fputc('\n', stdout);

      }
    }

    fprintf(stdout,
" * \n"
" * %s\n"
" *\n"
" * Implements %s (%s)\n",
            method->description, method->name, flickcurl_version_string
           );

    fprintf(stdout,
" * \n"
" * Return value: non-0 on failure\n"
" **/\n"
           );
      
    fprintf(stdout, "int\n%s(flickcurl* fc", function_name);
    if(method->args_count) {
      int argi;
      for(argi = 0; method->args[argi]; argi++) {
        flickcurl_arg* arg = method->args[argi];
        if(!strcmp(arg->name, "api_key"))
          continue;
        
        if(IS_INT_ARG(arg)) {
          fprintf(stdout, ", int %s", arg->name);
        } else {
          fprintf(stdout, ", const char* %s", arg->name);
        }
      }
    }
    fprintf(stdout, ")\n{\n");

    fprintf(stdout,
"  const char* parameters[%d][2];\n"
"  int count = 0;\n"
"  xmlDocPtr doc = NULL;\n"
"  xmlXPathContextPtr xpathCtx = NULL; \n"
"  void* result = NULL;\n",
  6+method->args_count);
    if(method->args_count) {
      int argi;
      for(argi = 0; method->args[argi]; argi++) {
        flickcurl_arg* arg = method->args[argi];
        if(IS_INT_ARG(arg)) {
          fprintf(stdout,
"  char %s_str[10];\n",
                  arg->name);
        }
      }
    }

    fputs(
"  \n",
    stdout);
    
    
    if(method->args_count) {
      int argi;
      int print_or = 0;
      
      fprintf(stdout, "  if(");
      for(argi = 0; method->args[argi]; argi++) {
        flickcurl_arg* arg = method->args[argi];
        if(!strcmp(arg->name, "api_key"))
          continue;
        
        if(!arg->optional) {
          if(print_or)
            fprintf(stdout, " || ");
          
          fprintf(stdout, "!%s", arg->name);
          print_or = 1;
        }
      }
      fprintf(stdout,
")\n"
"    return 1;\n"
"\n");
    }


    if(method->args_count) {
      int argi;
      for(argi = 0; method->args[argi]; argi++) {
        flickcurl_arg* arg = method->args[argi];
        if(!strcmp(arg->name, "api_key"))
          continue;
        
        if(arg->optional) {
          if(IS_INT_ARG(arg)) {
            fprintf(stdout,
"  if(%s >= 0) {\n"
"    sprintf(%s_str, \"%%d\", %s);\n"
"    parameters[count][0]  = \"%s\";\n"
"    parameters[count++][1]= %s_str;\n"
"  }\n",
                    arg->name, arg->name, arg->name, arg->name, arg->name);
            continue;
          }
          fprintf(stdout,
"  if(%s) {\n",
                  arg->name);
        }
        
        fprintf(stdout,
"  parameters[count][0]  = \"%s\";\n"
"  parameters[count++][1]= %s;\n",
              arg->name, arg->name);

        if(arg->optional) {
          fprintf(stdout,
"  }\n"
                  );
        }
        
      }
    }

    fprintf(stdout,
"\n"
"  parameters[count][0]  = NULL;\n"
"\n"
            );

    fprintf(stdout,
"  if(flickcurl_prepare(fc, \"%s\", parameters, count))\n"
"    goto tidy;\n"
"\n",
    method->name);

    if(is_write)
      fprintf(stdout, 
"  flickcurl_set_write(fc, 1);\n"
"  flickcurl_set_data(fc, (void*)\"\", 0);\n"
"\n"
);

    fprintf(stdout,
"  doc = flickcurl_invoke(fc);\n"
"  if(!doc)\n"
"    goto tidy;\n"
"\n"
"\n"
"  xpathCtx = xmlXPathNewContext(doc);\n"
"  if(!xpathCtx) {\n"
"    flickcurl_error(fc, \"Failed to create XPath context for document\");\n"
"    fc->failed = 1;\n"
"    goto tidy;\n"
"  }\n"
"\n"
"  result = NULL; /* your code here */\n"
"\n"
"  tidy:\n"
"  if(xpathCtx)\n"
"    xmlXPathFreeContext(xpathCtx);\n"
"\n"
"  if(fc->failed)\n"
"    result = NULL;\n"
"\n"
"  return (result == NULL);\n"
"}\n"
"\n"
"\n");

    flickcurl_free_method(method);
  }


 tidy:
  if(methods) {
    for(i = 0; methods[i]; i++)
      free(methods[i]);
    free(methods);
    methods = NULL;
  }

  if(fc)
    flickcurl_free(fc);

  flickcurl_finish();

  return(rc);
}
Example #3
0
int
main(int argc, char *argv[]) 
{
  flickcurl *fc = NULL;
  int rc = 0;
  int usage = 0;
  int help = 0;
  const char* home;
  char config_path[1024];
  char* photo_id = NULL;
  const char* prefix_uri = "http://www.flickr.com/photos/";
  size_t prefix_uri_len = strlen(prefix_uri);
  const char *serializer_syntax_name = "ntriples";
  raptor_uri* base_uri = NULL;
  raptor_serializer* serializer = NULL;
  int request_delay= -1;
  flickcurl_serializer* fs = NULL;
  flickcurl_photo* photo = NULL;

  program = my_basename(argv[0]);

  flickcurl_init();

  rworld = raptor_new_world();
  raptor_world_open(rworld);

  home = getenv("HOME");
  if(home)
    sprintf(config_path, "%s/%s", home, config_filename);
  else
    strcpy(config_path, config_filename);
  

  while (!usage && !help)
  {
    int c;
    
#ifdef HAVE_GETOPT_LONG
    int option_index = 0;

    c = getopt_long (argc, argv, GETOPT_STRING, long_options, &option_index);
#else
    c = getopt (argc, argv, GETOPT_STRING);
#endif
    if (c == -1)
      break;

    switch (c) {
      case 0:
      case '?': /* getopt() - unknown option */
        usage = 1;
        break;

      case 'd':
        if(optarg)
          request_delay = atoi(optarg);
        break;
        
      case 'D':
        debug = 1;
        break;
        
      case 'h':
        help = 1;
        break;

      case 'o':
        if(optarg) {
          if(raptor_world_is_serializer_name(rworld, optarg))
            serializer_syntax_name = optarg;
          else {
            int i;
            
            fprintf(stderr,
                    "%s: invalid argument `%s' for `" HELP_ARG(o, output) "'\n",
                    program, optarg);
            fprintf(stderr, "Valid arguments are:\n");
            for(i = 0; 1; i++) {
              const raptor_syntax_description *d;

              d = raptor_world_get_serializer_description(rworld, i);
              if(!d)
                break;
              printf("  %-12s for %s\n", d->names[0], d->label);
            }
            usage = 1;
            break;
            
          }
        }
        break;
        
      case 'v':
        fputs(flickcurl_version_string, stdout);
        fputc('\n', stdout);

        exit(0);
    }
    
  }

  argv+= optind;
  argc-= optind;
  
  if(!help && argc < 1)
    usage = 2; /* Title and usage */

  if(!help && !argc) {
    fprintf(stderr, "%s: No photo URI given\n", program);
    usage = 1;
    goto usage;
  }

  if(usage || help)
    goto usage;

  photo_id = argv[0];
  if(strncmp(photo_id, prefix_uri, prefix_uri_len))
    usage = 1;
  else {
    size_t len;

    photo_id+= prefix_uri_len;
    len = strlen(photo_id);
    if(!len)
      usage = 1;
    else {
      if(photo_id[len-1] == '/')
        photo_id[--len] = '\0';
      
      while(*photo_id && *photo_id != '/')
        photo_id++;
      if(!*photo_id)
        usage = 1;
      else
        photo_id++;
    }
  }

  if(usage) {
    fprintf(stderr,
            "%s: Argument is not a Flickr photo URI like\n"
            "  http://www.flickr.com/photos/USER/PHOTO/\n", 
            program);
    goto usage;
  }


  serializer = raptor_new_serializer(rworld, serializer_syntax_name);
  if(!serializer) {
    fprintf(stderr, 
            "%s: Failed to create raptor serializer type %s\n", program,
            serializer_syntax_name);
    return(1);
  }

  base_uri = raptor_new_uri(rworld, (const unsigned char*)argv[0]);

  raptor_serializer_start_to_file_handle(serializer, base_uri, stdout);


  /* Initialise the Flickcurl library */
  fc = flickcurl_new();
  if(!fc) {
    rc = 1;
    goto tidy;
  }

  flickcurl_set_error_handler(fc, my_message_handler, NULL);

  if(!access((const char*)config_path, R_OK)) {
    if(flickcurl_config_read_ini(fc, config_path, config_section, fc,
                                 flickcurl_config_var_handler)) {
      rc = 1;
      goto tidy;
    }
  }
  
 usage:
  if(usage) {
    if(usage>1) {
      fprintf(stderr, title_format_string, flickcurl_version_string);
      fputs("Flickcurl home page: ", stderr);
      fputs(flickcurl_home_url_string, stderr);
      fputc('\n', stderr);
      fputs(flickcurl_copyright_string, stderr);
      fputs("\nLicense: ", stderr);
      fputs(flickcurl_license_string, stderr);
      fputs("\n\n", stderr);
    }
    fprintf(stderr, "Try `%s " HELP_ARG(h, help) "' for more information.\n",
            program);
    rc = 1;
    goto tidy;
  }

  if(help) {
    int i;

    printf(title_format_string, flickcurl_version_string);
    puts("Get Triples from Flickr photos.");
    printf("Usage: %s [OPTIONS] FLICKR-PHOTO-URI\n\n", program);

    fputs(flickcurl_copyright_string, stdout);
    fputs("\nLicense: ", stdout);
    puts(flickcurl_license_string);
    fputs("Flickcurl home page: ", stdout);
    puts(flickcurl_home_url_string);

    fputs("\n", stdout);

    puts(HELP_TEXT("d", "delay DELAY     ", "Set delay between requests in milliseconds"));
    puts(HELP_TEXT("D", "debug           ", "Print lots of output"));
    puts(HELP_TEXT("h", "help            ", "Print this help, then exit"));
    puts(HELP_TEXT("o", "output FORMAT   ", "Set output format to one of:"));
    for(i = 0; 1; i++) {
      const raptor_syntax_description* d;

      d = raptor_world_get_serializer_description(rworld, i);
      if(!d)
        break;

      if(!strcmp(d->names[0], serializer_syntax_name))
        printf("      %-15s %s (default)\n", d->names[0], d->label);
      else
        printf("      %-15s %s\n", d->names[0], d->label);
    }
#ifdef HAVE_RAPTOR
    printf("    via Raptor %s serializers\n", raptor_version_string);
#else
    puts("    via internal RDF serializer");
#endif
    puts(HELP_TEXT("v", "version         ", "Print the flickcurl version"));

    rc = 0;
    goto tidy;
  }


  if(request_delay >= 0)
    flickcurl_set_request_delay(fc, request_delay);
  
  fs = flickcurl_new_serializer(fc, serializer, &flickrdf_serializer_factory);
  if(!fs) {
    fprintf(stderr, "%s: Failed to create Flickcurl serializer\n", program);
    goto tidy;
  }
  
  photo = flickcurl_photos_getInfo(fc, photo_id);

  if(!photo)
    goto tidy;

  if(debug)
    fprintf(stderr, "%s: Photo with URI %s ID %s has %d tags\n",
            program, photo->uri, photo->id, photo->tags_count);

  rc = flickcurl_serialize_photo(fs, photo);

 tidy:
  if(photo)
    flickcurl_free_photo(photo);

  if(fs)
    flickcurl_free_serializer(fs);

  if(fc)
    flickcurl_free(fc);

  if(serializer)
    raptor_free_serializer(serializer);
  if(base_uri)
    raptor_free_uri(base_uri);

  if(rworld)
    raptor_free_world(rworld);

  flickcurl_finish();

  return(rc);
}
Example #4
0
int
main(int argc, char *argv[]) 
{
  flickcurl *fc = NULL;
  int rc = 0;
  int usage = 0;
  int help = 0;
  int read_auth = 1;
  int i;
  const char* home;
  char config_path[1024];
  char** methods = NULL;
  int count = 0;
  
  flickcurl_init();
  
  program = my_basename(argv[0]);

  home = getenv("HOME");
  if(home)
    sprintf(config_path, "%s/%s", home, config_filename);
  else
    strcpy(config_path, config_filename);
  

  while (!usage && !help)
  {
    int c;
#ifdef HAVE_GETOPT_LONG
    int option_index = 0;

    c = getopt_long (argc, argv, GETOPT_STRING, long_options, &option_index);
#else
    c = getopt (argc, argv, GETOPT_STRING);
#endif
    if (c == -1)
      break;

    switch (c) {
      case 0:
      case '?': /* getopt() - unknown option */
        usage = 1;
        break;

      case 'h':
        help = 1;
        break;

      case 'v':
        fputs(flickcurl_version_string, stdout);
        fputc('\n', stdout);

        exit(0);
    }
    
  }
  
  if(help)
    goto help;
  
  if(argc != 1) {
    fprintf(stderr, "%s: Extra arguments given\n", program);
    usage = 1;
  }

  if(usage) {
    if(usage>1) {
      fprintf(stderr, title_format_string, flickcurl_version_string);
      fputs("Flickcurl home page: ", stderr);
      fputs(flickcurl_home_url_string, stderr);
      fputc('\n', stderr);
      fputs(flickcurl_copyright_string, stderr);
      fputs("\nLicense: ", stderr);
      fputs(flickcurl_license_string, stderr);
      fputs("\n\n", stderr);
    }
    fprintf(stderr, "Try `%s " HELP_ARG(h, help) "' for more information.\n",
            program);
    rc = 1;
    goto tidy;
  }

  help:
  if(help) {
    printf(title_format_string, flickcurl_version_string);
    puts("List Flickr API methods by reflection.");
    printf("Usage: %s [OPTIONS]\n\n", program);

    fputs(flickcurl_copyright_string, stdout);
    fputs("\nLicense: ", stdout);
    puts(flickcurl_license_string);
    fputs("Flickcurl home page: ", stdout);
    puts(flickcurl_home_url_string);

    fputs("\n", stdout);

    puts(HELP_TEXT("h", "help            ", "Print this help, then exit"));
    puts(HELP_TEXT("v", "version         ", "Print the flickcurl version"));

    rc = 0;
    goto tidy;
  }


  /* Initialise the Flickcurl library */
  fc = flickcurl_new();
  if(!fc) {
    rc = 1;
    goto tidy;
  }

  flickcurl_set_error_handler(fc, my_message_handler, NULL);

  if(read_auth && !access((const char*)config_path, R_OK)) {
    if(flickcurl_config_read_ini(fc, config_path, config_section, fc,
                                 flickcurl_config_var_handler)) {
      rc = 1;
      goto tidy;
    }
  }

  methods = flickcurl_reflection_getMethods(fc);
  if(!methods) {
    fprintf(stderr, "%s: getMethods failed\n", program);
    rc = 1;
    goto tidy;
  }

  for(i = 0; methods[i]; i++)
    ;
  count = i;
  
  fprintf(stderr, "%s: Found %d API methods\n", program, count);
  
  /* it seems to be sorted when returned but ensure it anyway */
  qsort(methods, count, sizeof(char*), compare_strings);
  
  for(i = 0; methods[i]; i++) {
    fputs((const char*)methods[i], stdout);
    fputc('\n', stdout);
  }


 tidy:
  if(methods) {
    for(i = 0; methods[i]; i++)
      free(methods[i]);
    free(methods);
    methods = NULL;
  }

  if(fc)
    flickcurl_free(fc);

  flickcurl_finish();

  return(rc);
}