aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--configure.in1
-rw-r--r--plugin/Makefile.am2
-rw-r--r--plugin/attachment_tool/Makefile.am21
-rw-r--r--plugin/attachment_tool/README26
-rw-r--r--plugin/attachment_tool/attachment_tool.c285
6 files changed, 341 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index b89601b5..dd90cbec 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
2010-08-04
+ * configure.in
+ plugin/Makefile.am
+ plugin/attachment_tool/*: added new plug-in 'Attachment Tool
+ Plug-in'. This plug-in is distributed under the GNU LGPL.
+
+2010-08-04
+
* src/plugin.[ch]
src/main.c
src/summaryview.[ch]: added/fixed SummaryView and alert panel
diff --git a/configure.in b/configure.in
index 6b10c5c3..4aecdba1 100644
--- a/configure.in
+++ b/configure.in
@@ -457,6 +457,7 @@ src/sylpheed.rc
src/Makefile
src/icons/Makefile
plugin/Makefile
+plugin/attachment_tool/Makefile
plugin/test/Makefile
po/Makefile.in
faq/Makefile
diff --git a/plugin/Makefile.am b/plugin/Makefile.am
index 02af5b3e..5f2ed523 100644
--- a/plugin/Makefile.am
+++ b/plugin/Makefile.am
@@ -1 +1 @@
-SUBDIRS = test
+SUBDIRS = attachment_tool test
diff --git a/plugin/attachment_tool/Makefile.am b/plugin/attachment_tool/Makefile.am
new file mode 100644
index 00000000..9fc7f39e
--- /dev/null
+++ b/plugin/attachment_tool/Makefile.am
@@ -0,0 +1,21 @@
+libdir = $(plugindir)
+
+lib_LTLIBRARIES = attachment_tool.la
+
+attachment_tool_la_SOURCES = attachment_tool.c
+attachment_tool_la_LDFLAGS = -module -no-undefined -avoid-version
+
+INCLUDES = \
+ $(GTK_CFLAGS) \
+ -I$(includedir) \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/libsylph \
+ -I$(top_srcdir)/src
+
+test_la_LIBADD = \
+ $(GTK_LIBS) \
+ $(top_builddir)/src/libsylpheed-plugin-0.la \
+ $(top_builddir)/libsylph/libsylph-0.la
+
+install:
+install-plugin: install-am
diff --git a/plugin/attachment_tool/README b/plugin/attachment_tool/README
new file mode 100644
index 00000000..159a2aff
--- /dev/null
+++ b/plugin/attachment_tool/README
@@ -0,0 +1,26 @@
+Attachment Tool Plug-in
+=======================
+
+This is a plug-in for handling messages with attached files.
+
+Currently, this plug-in can only remove data of attached files with file name.
+MIME structure will be retained, and users will see 0 byte files.
+
+This tool is available on local folders only.
+
+Requirement
+-----------
+
+This plug-in requires Sylpheed 3.1beta3 or later.
+
+Install
+-------
+
+This plugin will not be installed by 'make install'.
+To install this test plugin, type 'make install-plugin'.
+
+Usage
+-----
+
+1. Select target messages in the summary view.
+2. Select 'Tools - Remove attachments'.
diff --git a/plugin/attachment_tool/attachment_tool.c b/plugin/attachment_tool/attachment_tool.c
new file mode 100644
index 00000000..9db808c2
--- /dev/null
+++ b/plugin/attachment_tool/attachment_tool.c
@@ -0,0 +1,285 @@
+/*
+ * Attachment Tool Plug-in -- an attachment processing plug-in for Sylpheed
+ * Copyright (C) 2010 Hiroyuki Yamamoto
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "defs.h"
+
+#include <glib.h>
+#include <gtk/gtk.h>
+
+#include <stdio.h>
+#include <sys/stat.h>
+
+#include "sylmain.h"
+#include "plugin.h"
+#include "procmsg.h"
+#include "procmime.h"
+#include "utils.h"
+
+#include <glib/gi18n-lib.h>
+
+static SylPluginInfo info = {
+ "Attachment Tool Plug-in",
+ "0.1.0",
+ "Hiroyuki Yamamoto",
+ "Attachment processing plug-in for Sylpheed"
+};
+
+static void remove_attachment_cb(void);
+
+void plugin_load(void)
+{
+ debug_print("initializing attachment_tool plug-in\n");
+
+ syl_plugin_add_menuitem("/Tools", NULL, NULL, NULL);
+ syl_plugin_add_menuitem("/Tools", _("Remove attachments"), remove_attachment_cb, NULL);
+
+ debug_print("attachment_tool plug-in loading done.\n");
+}
+
+void plugin_unload(void)
+{
+ debug_print("attachment_tool plug-in unloaded.\n");
+}
+
+SylPluginInfo *plugin_info(void)
+{
+ return &info;
+}
+
+gint plugin_interface_version(void)
+{
+ return SYL_PLUGIN_INTERFACE_VERSION;
+}
+
+static gboolean remove_attachment_rec(MimeInfo *partinfo, FILE *fp, FILE *outfp)
+{
+ gchar buf[BUFFSIZE];
+ gchar *boundary = NULL;
+ gint boundary_len = 0;
+ gboolean err = FALSE;
+
+ while (partinfo) {
+ gboolean is_attach_part = FALSE;
+ gint count;
+
+ debug_print("------------------------------------------------- begin %s\n", partinfo->content_type);
+ debug_print("fpos = %ld\n", partinfo->fpos);
+ debug_print("content_type = %s\n", partinfo->content_type);
+
+ if (partinfo->filename || partinfo->name) {
+ is_attach_part = TRUE;
+ debug_print("skip this body\n");
+ }
+
+ if (fseek(fp, partinfo->fpos, SEEK_SET) < 0) {
+ perror("fseek");
+ err = TRUE;
+ break;
+ }
+ /* write part headers */
+ count = 0;
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ count++;
+ fputs(buf, outfp);
+ if (buf[0] == '\r' || buf[0] == '\n') break;
+ }
+ debug_print("wrote header: %d lines\n", count);
+
+ /* write until first boundary */
+ count = 0;
+ if (partinfo->children && partinfo->boundary) {
+ boundary = partinfo->boundary;
+ boundary_len = strlen(boundary);
+ debug_print("write until %s\n", boundary);
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ count++;
+ if (IS_BOUNDARY(buf, boundary, boundary_len)) {
+ fputs(buf, outfp);
+ debug_print("start boundary: %s", buf);
+ break;
+ } else {
+ fputs(buf, outfp);
+ }
+ }
+ debug_print("wrote %d lines\n", count);
+ }
+
+ if (partinfo->sub) {
+ debug_print("enter rfc822 -----------------------------\n");
+ err = !remove_attachment_rec(partinfo->sub, fp, outfp);
+ debug_print("leave rfc822 -----------------------------\n");
+ if (err)
+ break;
+ } else if (partinfo->children) {
+ debug_print("enter child -----------------------------\n");
+ err = !remove_attachment_rec
+ (partinfo->children, fp, outfp);
+ debug_print("leave child -----------------------------\n");
+ if (err)
+ break;
+ }
+
+ if (partinfo->parent && partinfo->parent->boundary) {
+ boundary = partinfo->parent->boundary;
+ boundary_len = strlen(boundary);
+ debug_print("boundary = %s\n", boundary);
+ } else {
+ boundary = NULL;
+ boundary_len = 0;
+ }
+
+ /* write (or skip) part body and end boundary */
+ if (boundary && !partinfo->main) {
+ count = 0;
+ debug_print("write until %s\n", boundary);
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ if (IS_BOUNDARY(buf, boundary, boundary_len)) {
+ count++;
+ fputs(buf, outfp);
+ debug_print("end boundary: %s", buf);
+ break;
+ } else {
+ if (!is_attach_part)
+ count++;
+ if (!is_attach_part)
+ fputs(buf, outfp);
+ }
+ }
+ debug_print("wrote body: %d lines\n", count);
+ }
+
+ debug_print("------------------------------------------------- end %s\n", partinfo->content_type);
+
+ partinfo = partinfo->next;
+ }
+
+ return !err;
+}
+
+static gboolean remove_attachment(MsgInfo *msginfo)
+{
+ MimeInfo *mimeinfo;
+ FILE *fp, *outfp;
+ gchar *infile, *outfile;
+ gboolean err = FALSE;
+
+ mimeinfo = procmime_scan_message(msginfo);
+ g_return_val_if_fail(mimeinfo != NULL, FALSE);
+
+ if ((fp = procmsg_open_message(msginfo)) == NULL) {
+ procmime_mimeinfo_free_all(mimeinfo);
+ return FALSE;
+ }
+
+ infile = procmsg_get_message_file(msginfo);
+ outfile = g_strconcat(infile, ".tmp", NULL);
+ debug_print("infile: %s\n", infile);
+ debug_print("outfile: %s\n", outfile);
+
+ if ((outfp = g_fopen(outfile, "wb")) == NULL) {
+ g_free(outfile);
+ g_free(infile);
+ procmime_mimeinfo_free_all(mimeinfo);
+ return FALSE;
+ }
+
+ err = !remove_attachment_rec(mimeinfo, fp, outfp);
+
+ if (fclose(outfp) == EOF) {
+ FILE_OP_ERROR(outfile, "fclose");
+ err = TRUE;
+ }
+
+ fclose(fp);
+
+ if (!err) {
+ debug_print("overwriting original message file: %s\n", infile);
+ if (copy_file(outfile, infile, TRUE) == 0) {
+ struct stat s;
+ if (g_stat(infile, &s) == 0) {
+ msginfo->size = s.st_size;
+ msginfo->mtime = s.st_mtime;
+ }
+ if (msginfo->folder)
+ msginfo->folder->cache_dirty = TRUE;
+ } else
+ err = TRUE;
+ }
+
+ g_unlink(outfile);
+ g_free(outfile);
+ g_free(infile);
+ procmime_mimeinfo_free_all(mimeinfo);
+
+ return !err;
+}
+
+static void remove_attachment_cb(void)
+{
+ FolderItem *item;
+ GSList *mlist, *cur;
+ gint val;
+
+ debug_print("remove_attachment_cb\n");
+
+ if (syl_plugin_summary_is_locked())
+ return;
+
+ item = syl_plugin_summary_get_current_folder();
+ if (!item || !item->folder || FOLDER_TYPE(item->folder) != F_MH ||
+ item->stype == F_VIRTUAL) {
+ syl_plugin_alertpanel_message(_("Error"), _("This tool is available on local folders only."), 3);
+ return;
+ }
+
+ mlist = syl_plugin_summary_get_selected_msg_list();
+ if (!mlist)
+ return;
+
+ val = syl_plugin_alertpanel(_("Remove attachments"),
+ _("Do you really remove attached files from the selected messages?"),
+ GTK_STOCK_YES, GTK_STOCK_NO, NULL);
+ if (val != 0) {
+ g_slist_free(mlist);
+ return;
+ }
+
+ for (cur = mlist; cur != NULL; cur = cur->next) {
+ MsgInfo *msginfo = (MsgInfo *)cur->data;
+
+ if (!msginfo)
+ continue;
+ if (!MSG_IS_MIME(msginfo->flags)) {
+ debug_print("message %u is not multi-part. skipping.\n", msginfo->msgnum);
+ continue;
+ }
+ debug_print("Removing attachments of message: %u: %s\n", msginfo->msgnum, msginfo->subject ? msginfo->subject : "(No Subject)");
+
+ if (!remove_attachment(msginfo)) {
+ g_warning("Cannot remove attachments from %u: %s\n", msginfo->msgnum, msginfo->subject ? msginfo->subject : "(No Subject)");
+ break;
+ }
+
+ syl_plugin_summary_update_by_msgnum(msginfo->msgnum);
+ }
+
+ g_slist_free(mlist);
+
+ syl_plugin_summary_redisplay_msg();
+}