Hacking on the mail plugin

View: New views
5 Messages — Rating Filter:   Alert me  

Hacking on the mail plugin

by Chris Mohler :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

OK, so I thought bug 596066
(https://bugzilla.gnome.org/show_bug.cgi?id=596066) might be easy
enough for me, an admitted novice in C.

However, I can not for the life of me figure out why my call to
g_spawn_async throws a segfault every time.  I would be most grateful
if someone could point out the problem (I'm sure it's a newbie error
on my part).

This patch has known problems.  Due to the new import/export structure
(I think), it will only work on native .XCF files right now., and the
file must be saved.  There is some legacy code from the original
sendmail plugin hanging around that isn't doing much.  And the
segfault of course :)  And finally, xdg-email is broken, and needs to
be patched in order for Evolution or Thunderbird to even accept
attachments.  You can grab the patch for xdg-email from launchpad
(filed upstream also):
https://bugs.launchpad.net/ubuntu/+source/xdg-utils/+bug/408350

The git patch is attached.

Thanks!
Chris

PS - is there any reason to maintain backwards compatibility with the
original mail plugin?  The attached patch was a heavy-handed attack
just to see if I could get it working with xdg-utils - I have not
really settled on the best approach yet.

[0001-Update-mail-plugin-to-use-xdg-email.patch]

From 099cf07983d1dbc82510952b2a2bce798b7ef62f Mon Sep 17 00:00:00 2001
From: Chris Mohler <cr33dog@...>
Date: Sat, 3 Oct 2009 21:10:35 -0500
Subject: [PATCH] Update mail plugin to use xdg-email

This is a work-in-progress patch to use xdg-email instead of sendmail.  There are known problems.
---
 plug-ins/common/mail.c |  501 +++---------------------------------------------
 1 files changed, 30 insertions(+), 471 deletions(-)

diff --git a/plug-ins/common/mail.c b/plug-ins/common/mail.c
index 8f5625a..19b8e71 100644
--- a/plug-ins/common/mail.c
+++ b/plug-ins/common/mail.c
@@ -102,8 +102,8 @@ static const guint8 mail_icon[] =
 };
 
 
-#ifndef SENDMAIL
-#define SENDMAIL "/usr/lib/sendmail"
+#ifndef XDGEMAIL
+#define XDGEMAIL "/usr/bin/xdg-email"
 #endif
 
 #define BUFFER_SIZE 256
@@ -114,10 +114,6 @@ static const guint8 mail_icon[] =
 typedef struct
 {
   gchar filename[BUFFER_SIZE];
-  gchar receipt[BUFFER_SIZE];
-  gchar from[BUFFER_SIZE];
-  gchar subject[BUFFER_SIZE];
-  gchar comment[BUFFER_SIZE];
 } m_info;
 
 
@@ -128,26 +124,11 @@ static void               run                  (const gchar      *name,
                                                 gint             *nreturn_vals,
                                                 GimpParam       **return_vals);
 
-static GimpPDBStatusType  save_image           (const gchar      *filename,
+static GimpPDBStatusType  save_image           (gchar     *filename,
                                                 gint32            image_ID,
                                                 gint32            drawable_ID,
                                                 gint32            run_mode);
 
-static gboolean           save_dialog          (void);
-static void               mail_entry_callback  (GtkWidget        *widget,
-                                                gchar            *data);
-static void               mesg_body_callback   (GtkTextBuffer    *buffer,
-                                                gpointer          data);
-
-static gboolean           valid_file           (const gchar      *filename);
-static void               create_headers       (FILE             *mailpipe);
-static gchar            * find_extension       (const gchar      *filename);
-static gboolean           to64                 (const gchar      *filename,
-                                                FILE             *outfile,
-                                                GError          **error);
-static FILE             * sendmail_pipe        (gchar           **cmd,
-                                                GPid             *pid);
-
 
 const GimpPlugInInfo PLUG_IN_INFO =
 {
@@ -159,11 +140,9 @@ const GimpPlugInInfo PLUG_IN_INFO =
 
 static m_info mail_info =
 {
-  "", "", "", "", ""
+  ""
 };
 
-static gchar *mesg_body = NULL;
-
 
 MAIN ()
 
@@ -176,16 +155,11 @@ query (void)
     { GIMP_PDB_IMAGE,    "image",         "Input image" },
     { GIMP_PDB_DRAWABLE, "drawable",      "Drawable to save" },
     { GIMP_PDB_STRING,   "filename",      "The name of the file to save the image in" },
-    { GIMP_PDB_STRING,   "to-address",    "The email address to send to" },
-    { GIMP_PDB_STRING,   "from-address",  "The email address for the From: field" },
-    { GIMP_PDB_STRING,   "subject",       "The subject" },
-    { GIMP_PDB_STRING,   "comment",       "The Comment" },
-    { GIMP_PDB_INT32,    "encapsulation", "ignored" }
   };
 
   gimp_install_procedure (PLUG_IN_PROC,
                           N_("Send the image by email"),
-                          "You need to have sendmail installed",
+                          "You need to have xdg-utils installed",
                           "Adrian Likins, Reagan Blundell",
                           "Adrian Likins, Reagan Blundell, Daniel Risacher, "
                           "Spencer Kimball and Peter Mattis",
@@ -245,8 +219,6 @@ run (const gchar      *name,
               }
           }
 
-          if (! save_dialog ())
-            status = GIMP_PDB_CANCEL;
           break;
 
         case GIMP_RUN_NONINTERACTIVE:
@@ -259,14 +231,6 @@ run (const gchar      *name,
             {
               g_strlcpy (mail_info.filename,
                          param[3].data.d_string, BUFFER_SIZE);
-              g_strlcpy (mail_info.receipt,
-                         param[4].data.d_string, BUFFER_SIZE);
-              g_strlcpy (mail_info.from,
-                         param[5].data.d_string, BUFFER_SIZE);
-              g_strlcpy (mail_info.subject,
-                         param[6].data.d_string, BUFFER_SIZE);
-              g_strlcpy (mail_info.comment,
-                         param[7].data.d_string, BUFFER_SIZE);
             }
           break;
 
@@ -285,13 +249,6 @@ run (const gchar      *name,
                                drawable_ID,
                                run_mode);
 
-          if (status == GIMP_PDB_SUCCESS)
-            {
-              if (mesg_body)
-                g_strlcpy (mail_info.comment, mesg_body, BUFFER_SIZE);
-
-              gimp_set_data (PLUG_IN_PROC, &mail_info, sizeof (m_info));
-            }
         }
     }
   else
@@ -303,434 +260,36 @@ run (const gchar      *name,
 }
 
 static GimpPDBStatusType
-save_image (const gchar *filename,
+save_image (gchar *filename,
             gint32       image_ID,
             gint32       drawable_ID,
             gint32       run_mode)
 {
   GimpPDBStatusType  status = GIMP_PDB_SUCCESS;
-  gchar             *ext;
-  gchar             *tmpname;
-  gchar             *mailcmd[3];
-  GPid               mailpid;
-  FILE              *mailpipe;
-  GError            *error = NULL;
-
-  ext = find_extension (filename);
-
-  if (ext == NULL)
-    return GIMP_PDB_CALLING_ERROR;
-
-  /* get a temp name with the right extension and save into it. */
-  tmpname = gimp_temp_name (ext + 1);
-
-  /* construct the "sendmail user@location" line */
-  mailcmd[0] = SENDMAIL;
-  mailcmd[1] = mail_info.receipt;
-  mailcmd[2] = NULL;
-
-  /* create a pipe to sendmail */
-  mailpipe = sendmail_pipe (mailcmd, &mailpid);
-
-  if (mailpipe == NULL)
-    return GIMP_PDB_EXECUTION_ERROR;
-
-  create_headers (mailpipe);
-
-  fflush (mailpipe);
-
-  if (! (gimp_file_save (run_mode,
-                         image_ID,
-                         drawable_ID,
-                         tmpname,
-                         tmpname) && valid_file (tmpname)))
-    {
-      goto error;
-    }
-
-  if (! to64 (tmpname, mailpipe, &error))
-    {
-      g_message ("%s", error->message);
-      g_error_free (error);
-      goto error;
-    }
-
-  fprintf (mailpipe, "\n--GUMP-MIME-boundary--\n");
-
-  goto cleanup;
-
-error:
-  /* stop sendmail from doing anything */
-  kill (mailpid, SIGINT);
-  status = GIMP_PDB_EXECUTION_ERROR;
-
-cleanup:
-  /* close out the sendmail process */
-  fclose (mailpipe);
-  waitpid (mailpid, NULL, 0);
-  g_spawn_close_pid (mailpid);
-
-  /* delete the tmpfile that was generated */
-  g_unlink (tmpname);
-  g_free (tmpname);
+  gchar *xdgargs[sizeof (gchar)];
+  gulong flags;
+  GPid childpid;
+  GError *spawnerr;
+
+  /* pass the image to xdg-email */
+  g_message("%s", filename);
+  flags=G_SPAWN_SEARCH_PATH|G_SPAWN_STDERR_TO_DEV_NULL;
+  
+  xdgargs[0] = XDGEMAIL;
+  xdgargs[1] = "--attach";
+  xdgargs[2] = filename;
+  xdgargs[3] = NULL;
+
+  if (!(g_spawn_async (NULL, xdgargs, NULL, flags, NULL, NULL,
+   &childpid, &spawnerr)))
+ {
+ g_message("%s", spawnerr->message);
+ }
+
+  /* kill & close */
+  //g_free (xdgargs[sizeof (gchar)]);
+  //g_spawn_close_pid(childpid);
+  //g_error_free(spawnerr);
 
   return status;
 }
-
-
-static gboolean
-save_dialog (void)
-{
-  GtkWidget     *dlg;
-  GtkWidget     *main_vbox;
-  GtkWidget     *entry;
-  GtkWidget     *table;
-  GtkWidget     *scrolled_window;
-  GtkWidget     *text_view;
-  GtkTextBuffer *text_buffer;
-  gchar         *gump_from;
-  gint           row = 0;
-  gboolean       run;
-
-  gimp_ui_init (PLUG_IN_BINARY, FALSE);
-
-  /* check gimprc for a preferred "From:" address */
-  gump_from = gimp_gimprc_query ("gump-from");
-
-  if (gump_from)
-    {
-      g_strlcpy (mail_info.from, gump_from, BUFFER_SIZE);
-      g_free (gump_from);
-    }
-
-  dlg = gimp_dialog_new (_("Send by Email"), PLUG_IN_BINARY,
-                         NULL, 0,
-                         gimp_standard_help_func, PLUG_IN_PROC,
-
-                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                         _("_Send"),       GTK_RESPONSE_OK,
-
-                         NULL);
-
-  gtk_dialog_set_alternative_button_order (GTK_DIALOG (dlg),
-                                           GTK_RESPONSE_OK,
-                                           GTK_RESPONSE_CANCEL,
-                                           -1);
-
-  gimp_window_set_transient (GTK_WINDOW (dlg));
-
-  main_vbox = gtk_vbox_new (FALSE, 12);
-  gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 12);
-  gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
-                      main_vbox, TRUE, TRUE, 0);
-  gtk_widget_show (main_vbox);
-
-  /* table */
-  table = gtk_table_new (5, 2, FALSE);
-  gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 0);
-  gtk_widget_show (table);
-
-  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
-  gtk_table_set_row_spacing (GTK_TABLE (table), 0, 12);
-  gtk_table_set_col_spacings (GTK_TABLE (table), 6);
-
-  /* Filename entry */
-  entry = gtk_entry_new ();
-  gtk_widget_set_size_request (entry, 200, -1);
-  gtk_entry_set_max_length (GTK_ENTRY (entry), BUFFER_SIZE - 1);
-  gtk_entry_set_text (GTK_ENTRY (entry), mail_info.filename);
-  gimp_table_attach_aligned (GTK_TABLE (table), 0, row++,
-                             _("_Filename:"), 0.0, 0.5,
-                             entry, 1, FALSE);
-  g_signal_connect (entry, "changed",
-                    G_CALLBACK (mail_entry_callback),
-                    mail_info.filename);
-
-  /* To entry */
-  entry = gtk_entry_new ();
-  gtk_widget_set_size_request (entry, 200, -1);
-  gtk_entry_set_max_length (GTK_ENTRY (entry), BUFFER_SIZE - 1);
-  gtk_entry_set_text (GTK_ENTRY (entry), mail_info.receipt);
-  gimp_table_attach_aligned (GTK_TABLE (table), 0, row++,
-                             _("_To:"), 0.0, 0.5,
-                             entry, 1, FALSE);
-  g_signal_connect (entry, "changed",
-                    G_CALLBACK (mail_entry_callback),
-                    mail_info.receipt);
-
-  gtk_widget_grab_focus (entry);
-
-  /* From entry */
-  entry = gtk_entry_new ();
-  gtk_widget_set_size_request (entry, 200, -1);
-  gtk_entry_set_max_length (GTK_ENTRY (entry), BUFFER_SIZE - 1);
-  gtk_entry_set_text (GTK_ENTRY (entry), mail_info.from);
-  gimp_table_attach_aligned (GTK_TABLE (table), 0, row++,
-                             _("_From:"), 0.0, 0.5,
-                             entry, 1, FALSE);
-  g_signal_connect (entry, "changed",
-                    G_CALLBACK (mail_entry_callback),
-                    mail_info.from);
-
-  /* Subject entry */
-  entry = gtk_entry_new ();
-  gtk_widget_set_size_request (entry, 200, -1);
-  gtk_entry_set_max_length (GTK_ENTRY (entry), BUFFER_SIZE - 1);
-  gtk_entry_set_text (GTK_ENTRY (entry), mail_info.subject);
-  gimp_table_attach_aligned (GTK_TABLE (table), 0, row++,
-                             _("S_ubject:"), 0.0, 0.5,
-                             entry, 1, FALSE);
-  g_signal_connect (entry, "changed",
-                    G_CALLBACK (mail_entry_callback),
-                    mail_info.subject);
-
-  /* Body  */
-  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
-  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
-                                       GTK_SHADOW_IN);
-  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
-                                  GTK_POLICY_AUTOMATIC,
-                                  GTK_POLICY_AUTOMATIC);
-  gtk_box_pack_start (GTK_BOX (main_vbox), scrolled_window, TRUE, TRUE, 0);
-  gtk_widget_show (scrolled_window);
-
-  text_buffer = gtk_text_buffer_new (NULL);
-
-  g_signal_connect (text_buffer, "changed",
-                    G_CALLBACK (mesg_body_callback),
-                    NULL);
-
-  gtk_text_buffer_set_text (text_buffer, mail_info.comment, -1);
-
-  text_view = gtk_text_view_new_with_buffer (text_buffer);
-  g_object_unref (text_buffer);
-
-  gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text_view), GTK_WRAP_WORD);
-  gtk_container_add (GTK_CONTAINER (scrolled_window), text_view);
-  gtk_widget_show (text_view);
-
-  gtk_widget_show (dlg);
-
-  run = (gimp_dialog_run (GIMP_DIALOG (dlg)) == GTK_RESPONSE_OK);
-
-  gtk_widget_destroy (dlg);
-
-  return run;
-}
-
-static gboolean
-valid_file (const gchar *filename)
-{
-  struct stat buf;
-
-  return g_stat (filename, &buf) == 0 && buf.st_size > 0;
-}
-
-static gchar *
-find_content_type (const gchar *filename)
-{
-  /* This function returns a MIME Content-type: value based on the
-     filename it is given.  */
-  const gchar *type_mappings[20] =
-  {
-    "gif" , "image/gif",
-    "jpg" , "image/jpeg",
-    "jpeg", "image/jpeg",
-    "tif" , "image/tiff",
-    "tiff", "image/tiff",
-    "png" , "image/png",
-    "g3"  , "image/g3fax",
-    "ps"  , "application/postscript",
-    "eps" , "application/postscript",
-    NULL, NULL
-  };
-
-  gchar *ext;
-  gint   i;
-
-  ext = find_extension (filename);
-
-  if (!ext)
-    {
-      return g_strdup ("application/octet-stream");
-    }
-
-  i = 0;
-  ext += 1;
-
-  while (type_mappings[i])
-    {
-      if (g_ascii_strcasecmp (ext, type_mappings[i]) == 0)
-        {
-          return g_strdup (type_mappings[i + 1]);
-        }
-
-      i += 2;
-    }
-
-  return g_strdup_printf ("image/x-%s", ext);
-}
-
-static gchar *
-find_extension (const gchar *filename)
-{
-  gchar *filename_copy;
-  gchar *ext;
-
-  /* we never free this copy - aren't we evil! */
-  filename_copy = g_strdup (filename);
-
-  /* find the extension, boy! */
-  ext = strrchr (filename_copy, '.');
-
-  while (TRUE)
-    {
-      if (!ext || ext[1] == '\0' || strchr (ext, G_DIR_SEPARATOR))
-        {
-          g_message (_("some sort of error with the file extension "
-                       "or lack thereof"));
-
-          return NULL;
-        }
-
-      if (0 != g_ascii_strcasecmp (ext, ".gz") &&
-          0 != g_ascii_strcasecmp (ext, ".bz2"))
-        {
-          return ext;
-        }
-      else
-        {
-          /* we found somehting, loop back, and look again */
-          *ext = 0;
-          ext = strrchr (filename_copy, '.');
-        }
-    }
-
-  return ext;
-}
-
-static void
-mail_entry_callback (GtkWidget *widget,
-                     gchar     *data)
-{
-  g_strlcpy (data, gtk_entry_get_text (GTK_ENTRY (widget)), BUFFER_SIZE);
-}
-
-static void
-mesg_body_callback (GtkTextBuffer *buffer,
-                    gpointer       data)
-{
-  GtkTextIter start_iter;
-  GtkTextIter end_iter;
-
-  gtk_text_buffer_get_bounds (buffer, &start_iter, &end_iter);
-
-  g_free (mesg_body);
-  mesg_body = gtk_text_buffer_get_text (buffer, &start_iter, &end_iter, FALSE);
-}
-
-static void
-create_headers (FILE *mailpipe)
-{
-  /* create all the mail header stuff. Feel free to add your own */
-  /* It is advisable to leave the X-Mailer header though, as     */
-  /* there is a possibilty of a Gimp mail scanner/reader in the  */
-  /* future. It will probabaly need that header.                 */
-
-  fprintf (mailpipe, "To: %s \n", mail_info.receipt);
-  fprintf (mailpipe, "Subject: %s \n", mail_info.subject);
-  if (strlen (mail_info.from) > 0)
-    fprintf (mailpipe, "From: %s \n", mail_info.from);
-
-  fprintf (mailpipe, "X-Mailer: GIMP Useless Mail Plug-In %s\n", GIMP_VERSION);
-
-  fprintf (mailpipe, "MIME-Version: 1.0\n");
-  fprintf (mailpipe, "Content-type: multipart/mixed; "
-                     "boundary=GUMP-MIME-boundary\n");
-
-  fprintf (mailpipe, "\n\n");
-
-  fprintf (mailpipe, "--GUMP-MIME-boundary\n");
-  fprintf (mailpipe, "Content-type: text/plain; charset=UTF-8\n\n");
-
-  if (mesg_body)
-    fprintf (mailpipe, "%s", mesg_body);
-
-  fprintf (mailpipe, "\n\n");
-
-  {
-    gchar *content = find_content_type (mail_info.filename);
-
-    fprintf (mailpipe, "--GUMP-MIME-boundary\n");
-    fprintf (mailpipe, "Content-type: %s\n", content);
-    fprintf (mailpipe, "Content-transfer-encoding: base64\n");
-    fprintf (mailpipe, "Content-disposition: attachment; filename=\"%s\"\n",
-             mail_info.filename);
-    fprintf (mailpipe, "Content-description: %s\n\n", mail_info.filename);
-
-    g_free (content);
-  }
-}
-
-static gboolean
-to64 (const gchar  *filename,
-      FILE         *outfile,
-      GError      **error)
-{
-  GMappedFile  *infile;
-  const guchar *in;
-  gchar         out[2048];
-  gint          state = 0;
-  gint          save  = 0;
-  gsize         len;
-  gsize         bytes;
-  gsize         c;
-
-  infile = g_mapped_file_new (filename, FALSE, error);
-  if (! infile)
-    return FALSE;
-
-  in = (const guchar *) g_mapped_file_get_contents (infile);
-  len = g_mapped_file_get_length (infile);
-
-  for (c = 0; c < len;)
-    {
-      gsize step = MIN (1024, len - c);
-
-      bytes = g_base64_encode_step (in + c, step, TRUE, out, &state, &save);
-      fwrite (out, 1, bytes, outfile);
-
-      c += step;
-    }
-
-  bytes = g_base64_encode_close (TRUE, out, &state, &save);
-  fwrite (out, 1, bytes, outfile);
-
-#if GLIB_CHECK_VERSION(2, 21, 3)
-  g_mapped_file_unref (infile);
-#else
-  g_mapped_file_free (infile);
-#endif
-
-  return TRUE;
-}
-
-static FILE *
-sendmail_pipe (gchar **cmd,
-               GPid   *pid)
-{
-  gint    fd;
-  GError *err = NULL;
-
-  if (! g_spawn_async_with_pipes (NULL, cmd, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
-                                  NULL, NULL, pid, &fd, NULL, NULL, &err))
-    {
-      g_message (_("Could not start sendmail (%s)"), err->message);
-      g_error_free (err);
-
-      *pid = -1;
-      return NULL;
-    }
-
-  return fdopen (fd, "wb");
-}
--
1.6.0.4



_______________________________________________
Gimp-developer mailing list
Gimp-developer@...
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer

Re: Hacking on the mail plugin

by Sven Neumann :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sat, 2009-10-03 at 21:27 -0500, Chris Mohler wrote:
> However, I can not for the life of me figure out why my call to
> g_spawn_async throws a segfault every time.  

Well, you pass it a pointer to xdgargs which was previously allocated on
the stack like this:

  gchar *xdgargs[sizeof (gchar)];

This should probably read

  gchar *xdgargs[4];

instead, since you want to store three arguments plus a trailing NULL.

And please make sure that you convert your tabs to spaces before you
submit your patch. Thanks.


Sven


_______________________________________________
Gimp-developer mailing list
Gimp-developer@...
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer

Re: Hacking on the mail plugin

by Chris Mohler :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sun, Oct 4, 2009 at 1:25 PM, Sven Neumann <sven@...> wrote:

> This should probably read
>
>  gchar *xdgargs[4];

(sorry forgot to reply-all)

Oops (facepalm).  Thanks.

So, I've written a replacement plug-in that works pretty well.
However, the only filetype supported is still .XCF.

Looking at the new api docs, it seems possible to raise a GimpDialog
that contains something like a toggle for "Native XCF or Export" and
also the new 'gimp_export_dialog_new' widget.  Does this sound
reasonable?

Thanks,
Chris
_______________________________________________
Gimp-developer mailing list
Gimp-developer@...
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer

Re: Hacking on the mail plugin

by Chris Mohler :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sun, Oct 4, 2009 at 4:59 PM, Chris Mohler <cr33dog@...> wrote:

> Looking at the new api docs, it seems possible to raise a GimpDialog
> that contains something like a toggle for "Native XCF or Export" and
> also the new 'gimp_export_dialog_new' widget.  Does this sound
> reasonable?

Also - is there some way to grab a list of all of the file types
supported by GIMP automatically?  I've taken a look in the
app/dialogs/file-save-dialog, but I'm beginning to doubt that a call
like 'gimp->plug_in_manager->export_procs' is possible from a
plug-in...

Thanks,
Chris
_______________________________________________
Gimp-developer mailing list
Gimp-developer@...
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer

Re: Hacking on the mail plugin

by Sven Neumann :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

On Sun, 2009-10-04 at 16:59 -0500, Chris Mohler wrote:

> So, I've written a replacement plug-in that works pretty well.
> However, the only filetype supported is still .XCF.

I don't quite understand where this limitation comes from. If you allow
the user to enter any filename, then GIMP will select a save procedure
that matches the file extension. That should work for all file-types
that GIMP knows about, not only for XCF. If it indeed does only work for
XCF, then that's a regression in the plug-in API that should be reported
and fixed for 2.8.


Sven


_______________________________________________
Gimp-developer mailing list
Gimp-developer@...
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer