Example #1
0
flickcurl_upload_status static *_flickr_api_upload_photo( dt_storage_flickr_params_t *p, char *fname, char *caption, char *description, gint imgid )
{

  flickcurl_upload_params *params = g_malloc(sizeof(flickcurl_upload_params));
  flickcurl_upload_status *status;

  memset(params,0,sizeof(flickcurl_upload_params));
  params->safety_level = 1; //Defaults to safe photos
  params->content_type = 1; //Defaults to photo (we don't support video!)

  params->title = caption;
  params->description = description;

  if (imgid)
    params->tags = dt_tag_get_list(imgid, ",");
  params->photo_file = fname; //fname should be the URI of temp file

  params->is_public = (int) p->public_perm;
  params->is_friend = (int) p->friend_perm;
  params->is_family = (int) p->family_perm;

  status = flickcurl_photos_upload_params(p->flickr_api->fc, params);
  if (!status)
  {
    fprintf (stderr,"[flickr] Something went wrong when uploading");
    g_free (params);
    return NULL;
  }
  g_free(params);
  return status;
}
Example #2
0
static int _picasa_api_upload_photo( _picasa_api_context_t *ctx, char *mime , char *data, int size , char *caption, char *description, gint imgid )
{
  _buffer_t buffer;
  memset(&buffer,0,sizeof(_buffer_t));
  char uri[4096]= {0};

  gchar *entry = g_markup_printf_escaped (
                   "<entry xmlns='http://www.w3.org/2005/Atom'>"
                   "<title>%s</title>"
                   "<summary>%s</summary>"
                   "<category scheme=\"http://schemas.google.com/g/2005#kind\""
                   " term=\"http://schemas.google.com/photos/2007#photo\"/>"
                   "</entry>",
                   caption,description);


  // Hack for nonform multipart post...
  gchar mpart1[4096]= {0};
  gchar *mpart_format="Media multipart posting\n--END_OF_PART\nContent-Type: application/atom+xml\n\n%s\n--END_OF_PART\nContent-Type: %s\n\n";
  sprintf(mpart1,mpart_format,entry,mime);

  int mpart1size=strlen(mpart1);
  int postdata_length=mpart1size+size+strlen("\n--END_OF_PART--");
  gchar *postdata=g_malloc(postdata_length);
  memcpy( postdata, mpart1, mpart1size);
  memcpy( postdata+mpart1size, data, size);
  memcpy( postdata+mpart1size+size, "\n--END_OF_PART--",strlen("\n--END_OF_PART--") );

  struct curl_slist *headers = NULL;
  headers = curl_slist_append(headers,ctx->authHeader);
  headers = curl_slist_append(headers,"Content-Type: multipart/related; boundary=\"END_OF_PART\"");
  headers = curl_slist_append(headers,"MIME-version: 1.0");
  headers = curl_slist_append(headers,"Expect:");
  headers = curl_slist_append(headers,"GData-Version: 2");

  sprintf(uri,"http://picasaweb.google.com/data/feed/api/user/default/albumid/%s", ctx->current_album->id);
  curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, uri);
#ifdef _DEBUG
  curl_easy_setopt(ctx->curl_handle, CURLOPT_VERBOSE, 1);
#else
  curl_easy_setopt(ctx->curl_handle, CURLOPT_VERBOSE, 0);
#endif
  curl_easy_setopt(ctx->curl_handle, CURLOPT_HTTPHEADER, headers);
  curl_easy_setopt(ctx->curl_handle, CURLOPT_UPLOAD,0);   // A post request !
  curl_easy_setopt(ctx->curl_handle, CURLOPT_POST,1);
  curl_easy_setopt(ctx->curl_handle, CURLOPT_POSTFIELDS, postdata);
  curl_easy_setopt(ctx->curl_handle, CURLOPT_POSTFIELDSIZE, postdata_length);
  curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEFUNCTION, _picasa_api_buffer_write_func);
  curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEDATA, &buffer);

  curl_easy_perform( ctx->curl_handle );

  curl_slist_free_all(headers);

  long result;
  curl_easy_getinfo(ctx->curl_handle,CURLINFO_RESPONSE_CODE,&result );

  // If we want to add tags let's do...
  if( result == 201 && imgid > 0 )
  {
    // Image was created , fine.. and result have the fully created photo xml entry..
    // Let's perform an update of the photos keywords with tags passed along to this function..
    // and use picasa photo update api to add keywords to the photo...

    // Build the keywords content string
    gchar *keywords = NULL;
    keywords = dt_tag_get_list(imgid, ",");

    xmlDocPtr doc;
    xmlNodePtr entryNode;
    // Parse xml document
    if( ( doc = xmlParseDoc( (xmlChar *)buffer.data ))==NULL) return 0;
    entryNode = xmlDocGetRootElement(doc);
    if(  !xmlStrcmp(entryNode->name, (const xmlChar *) "entry") )
    {
      // Let's get the gd:etag attribute of entry...
      // For now, we force update using "If-Match: *"
      /*
        if( !xmlHasProp(entryNode, (const xmlChar*)"gd:etag") ) return 0;
        xmlChar *etag = xmlGetProp(entryNode,(const xmlChar*)"gd:etag");
      */

      gchar *photo_id=NULL;
      gchar *updateUri=NULL;
      xmlNodePtr entryChilds = entryNode->xmlChildrenNode;
      if( entryChilds != NULL )
      {
        do
        {
          if ((!xmlStrcmp(entryChilds->name, (const xmlChar *)"id")) )
          {
            // Get the photo id used in uri for update
            xmlChar *id= xmlNodeListGetString(doc, entryChilds->xmlChildrenNode, 1);
            if( xmlStrncmp( id, (const xmlChar *)"http://",7) )
              photo_id = g_strdup((const char *)id);
            xmlFree(id);
          }
          else  if ((!xmlStrcmp(entryChilds->name, (const xmlChar *)"group")) )
          {
            // Got the media:group entry lets find the child media:keywords
            xmlNodePtr mediaChilds = entryChilds->xmlChildrenNode;
            if(mediaChilds != NULL)
            {
              do
              {
                // Got the keywords tag, let's set the tags
                if ((!xmlStrcmp(mediaChilds->name, (const xmlChar *)"keywords")) )
                  xmlNodeSetContent(mediaChilds, (xmlChar *)keywords);
              }
              while( (mediaChilds = mediaChilds->next)!=NULL );
            }
          }
          else if (( !xmlStrcmp(entryChilds->name,(const xmlChar*)"link")) )
          {
            xmlChar *rel = xmlGetProp(entryChilds,(const xmlChar*)"rel");
            if( !xmlStrcmp(rel,(const xmlChar *)"edit") )
            {
              updateUri=(char *)xmlGetProp(entryChilds,(const xmlChar*)"href");
            }
            xmlFree(rel);
          }
        }
        while( (entryChilds = entryChilds->next)!=NULL );
      }

      // Let's update the photo
      struct curl_slist *headers = NULL;
      headers = curl_slist_append(headers,ctx->authHeader);
      headers = curl_slist_append(headers,"Content-Type: application/atom+xml");
      headers = curl_slist_append(headers,"If-Match: *");
      headers = curl_slist_append(headers,"Expect:");
      headers = curl_slist_append(headers,"GData-Version: 2");

      _buffer_t response;
      memset(&response,0,sizeof(_buffer_t));

      // Setup data to send..
      _buffer_t writebuffer;
      int datasize;
      xmlDocDumpMemory(doc,(xmlChar **)&writebuffer.data, &datasize);
      writebuffer.size = datasize;
      writebuffer.offset=0;

      curl_easy_setopt(ctx->curl_handle, CURLOPT_URL, updateUri);
#ifdef _DEBUG
      curl_easy_setopt(ctx->curl_handle, CURLOPT_VERBOSE, 1);
#else
      curl_easy_setopt(ctx->curl_handle, CURLOPT_VERBOSE, 0);
#endif
      curl_easy_setopt(ctx->curl_handle, CURLOPT_HTTPHEADER, headers);
      curl_easy_setopt(ctx->curl_handle, CURLOPT_UPLOAD,1);   // A put request
      curl_easy_setopt(ctx->curl_handle, CURLOPT_READDATA,&writebuffer);
      curl_easy_setopt(ctx->curl_handle, CURLOPT_INFILESIZE,writebuffer.size);
      curl_easy_setopt(ctx->curl_handle, CURLOPT_READFUNCTION,_picasa_api_buffer_read_func);
      curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEFUNCTION, _picasa_api_buffer_write_func);
      curl_easy_setopt(ctx->curl_handle, CURLOPT_WRITEDATA, &response);
      curl_easy_perform( ctx->curl_handle );

      xmlFree( updateUri );
      xmlFree( writebuffer.data );
      if (response.data != NULL)
        g_free(response.data);
      if (photo_id != NULL)
        g_free(photo_id); // FIXME: never used!

      curl_slist_free_all( headers );
    }

  }
  return result;
}
Example #3
0
int store(dt_imageio_module_storage_t *self, dt_imageio_module_data_t *sdata, const int imgid,
          dt_imageio_module_format_t *format, dt_imageio_module_data_t *fdata, const int num, const int total,
          const gboolean high_quality, const gboolean upscale, dt_colorspaces_color_profile_type_t icc_type,
          const gchar *icc_filename, dt_iop_color_intent_t icc_intent)
{
  dt_storage_piwigo_gui_data_t *ui = self->gui_data;

  gint result = 0;

  const char *ext = format->extension(fdata);

  // Let's upload image...

  /* construct a temporary file name */
  char fname[PATH_MAX] = { 0 };
  dt_loc_get_tmp_dir(fname, sizeof(fname));
  g_strlcat(fname, "/darktable.XXXXXX.", sizeof(fname));
  g_strlcat(fname, ext, sizeof(fname));

  char *caption = NULL;
  char *description = NULL;
  char *author = NULL;

  gint fd = g_mkstemp(fname);
  if(fd == -1)
  {
    dt_control_log("failed to create temporary image for piwigo export");
    fprintf(stderr, "failed to create tempfile: %s\n", fname);
    return 1;
  }
  close(fd);
  const dt_image_t *img = dt_image_cache_get(darktable.image_cache, imgid, 'r');

  // If title is not existing, then use the filename without extension. If not, then use title instead
  GList *title = dt_metadata_get(img->id, "Xmp.dc.title", NULL);
  if(title != NULL)
  {
    caption = g_strdup(title->data);
    g_list_free_full(title, &g_free);
  }
  else
  {
    caption = g_path_get_basename(img->filename);
    (g_strrstr(caption, "."))[0] = '\0'; // chop extension...
  }

  GList *desc = dt_metadata_get(img->id, "Xmp.dc.description", NULL);
  if(desc != NULL)
  {
    description = g_strdup(desc->data);
    g_list_free_full(desc, &g_free);
  }
  dt_image_cache_read_release(darktable.image_cache, img);

  GList *auth = dt_metadata_get(img->id, "Xmp.dc.creator", NULL);
  if(auth != NULL)
  {
    author = g_strdup(auth->data);
    g_list_free_full(auth, &g_free);
  }

  if(dt_imageio_export(imgid, fname, format, fdata, high_quality, upscale, FALSE, icc_type, icc_filename, icc_intent,
                       self, sdata, num, total) != 0)
  {
    fprintf(stderr, "[imageio_storage_piwigo] could not export to file: `%s'!\n", fname);
    dt_control_log(_("could not export to file `%s'!"), fname);
    result = 1;
    goto cleanup;
  }

  dt_pthread_mutex_lock(&darktable.plugin_threadsafe);
  {
    gboolean status = TRUE;
    dt_storage_piwigo_params_t *p = (dt_storage_piwigo_params_t *)sdata;

    if(p->export_tags)
    {
      GList *tags_list = dt_tag_get_list(imgid);
      if(p->tags) g_free(p->tags);
      p->tags = dt_util_glist_to_str(",", tags_list);
      g_list_free_full(tags_list, g_free);
    }

    if(p->new_album)
    {
      status = _piwigo_api_create_new_album(p);
      if(!status) dt_control_log(_("cannot create a new piwigo album!"));
    }

    if(status)
    {
      status = _piwigo_api_upload_photo(p, fname, author, caption, description);
      if(!status)
      {
        fprintf(stderr, "[imageio_storage_piwigo] could not upload to piwigo!\n");
        dt_control_log(_("could not upload to piwigo!"));
        result = 1;
      }
      else if (p->new_album)
      {
        // we do not want to create more albums when multiple upload
        p->new_album = FALSE;
        _piwigo_refresh_albums(ui, p->album);
      }
    }
  }
  dt_pthread_mutex_unlock(&darktable.plugin_threadsafe);

cleanup:

  // And remove from filesystem..
  g_unlink(fname);
  g_free(caption);
  g_free(description);
  g_free(author);

  if(!result)
  {
    // this makes sense only if the export was successful
    dt_control_log(ngettext("%d/%d exported to piwigo webalbum", "%d/%d exported to piwigo webalbum", num),
                   num, total);
  }
  return result;
}