aboutsummaryrefslogtreecommitdiff
path: root/libsylph/procmsg.c
diff options
context:
space:
mode:
authorhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2010-07-12 09:33:27 +0000
committerhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2010-07-12 09:33:27 +0000
commitec14e81935047bd2b2182595b76650b5f2fef893 (patch)
treed87f0c546859b5ef9a8f49a4f9abcdbd75ac63e7 /libsylph/procmsg.c
parentaf81f08052caa5dd3bf88b31d9eed3cf6158e9df (diff)
implemented concatenation of partial messages (RFC 2046).
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@2608 ee746299-78ed-0310-b773-934348b2243d
Diffstat (limited to 'libsylph/procmsg.c')
-rw-r--r--libsylph/procmsg.c145
1 files changed, 144 insertions, 1 deletions
diff --git a/libsylph/procmsg.c b/libsylph/procmsg.c
index 2f6ebaad..6c384aa6 100644
--- a/libsylph/procmsg.c
+++ b/libsylph/procmsg.c
@@ -1,6 +1,6 @@
/*
* LibSylph -- E-Mail client library
- * Copyright (C) 1999-2009 Hiroyuki Yamamoto
+ * Copyright (C) 1999-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
@@ -1724,6 +1724,149 @@ void procmsg_print_message_part(MsgInfo *msginfo, MimeInfo *partinfo,
g_free(prtmp);
}
+/**
+ * procmsg_concat_partial_messages:
+ * @mlist: list of MsgInfo* including message/partial messages.
+ * @file: output file name of concatenated message.
+ *
+ * Concatenate @mlist which consists of message/partial messages and
+ * output to @file. If @mlist has different partial id, the first one
+ * is used.
+ *
+ * Return value: 0 on success, or -1 if failed.
+ **/
+gint procmsg_concat_partial_messages(GSList *mlist, const gchar *file)
+{
+ static HeaderEntry hentry[] = {{"Content-Type:", NULL, FALSE},
+ {NULL, NULL, FALSE}};
+ FILE *fp;
+ gchar buf[BUFFSIZE];
+ FILE *tmp_fp;
+ gchar *part_id = NULL;
+ gint total = 0;
+ MsgInfo *msg_array[100] = {NULL};
+ MsgInfo *msginfo;
+ MimeInfo *mimeinfo;
+ GSList *cur;
+ gint i;
+
+ g_return_val_if_fail(mlist != NULL, -1);
+ g_return_val_if_fail(file != NULL, -1);
+
+ debug_print("procmsg_concat_partial_messages\n");
+
+ for (cur = mlist; cur != NULL; cur = cur->next) {
+ gint n = 0;
+ gint t = 0;
+ gchar *cur_id = NULL;
+
+ msginfo = (MsgInfo *)cur->data;
+
+ fp = procmsg_open_message_decrypted(msginfo, &mimeinfo);
+ if (!fp)
+ continue;
+ if (!mimeinfo->content_type ||
+ g_ascii_strcasecmp(mimeinfo->content_type, "message/partial") != 0)
+ goto skip;
+
+ rewind(fp);
+ if (procheader_get_one_field(buf, sizeof(buf), fp, hentry) == -1)
+ goto skip;
+
+ procmime_scan_content_type_partial(buf + strlen(hentry[0].name), &t, &cur_id, &n);
+ if (n == 0 || t > 100 || n > t) {
+ debug_print("skip\n");
+ g_free(cur_id);
+ goto skip;
+ }
+
+ debug_print("partial: %d/%d id=%s\n", n, t, cur_id);
+ if (!part_id)
+ part_id = g_strdup(cur_id);
+ if (total == 0)
+ total = t;
+
+ if (total != t || strcmp(part_id, cur_id) != 0) {
+ debug_print("skip\n");
+ g_free(cur_id);
+ goto skip;
+ }
+
+ msg_array[n - 1] = msginfo;
+
+ g_free(cur_id);
+skip:
+ fclose(fp);
+ procmime_mimeinfo_free_all(mimeinfo);
+ }
+
+ if (!part_id) {
+ debug_print("piece not found\n");
+ return -1;
+ }
+
+ g_print("part_id = %s , total = %d\n", part_id, total);
+ g_free(part_id);
+
+ /* check if all pieces exist */
+ for (i = 0; i < total; i++) {
+ if (msg_array[i] == NULL) {
+ debug_print("message part %d not exist\n", i + 1);
+ return -1;
+ }
+ }
+
+ /* concatenate parts */
+ if ((tmp_fp = g_fopen(file, "wb")) == NULL) {
+ FILE_OP_ERROR(file, "fopen");
+ return -1;
+ }
+
+ for (i = 0; i < total; i++) {
+ msginfo = msg_array[i];
+ off_t out_size;
+ gint empty_line_size = 0;
+
+ fp = procmsg_open_message_decrypted(msginfo, &mimeinfo);
+ if (!fp) {
+ g_warning("cannot open message part %d\n", i + 1);
+ fclose(tmp_fp);
+ g_unlink(file);
+ return -1;
+ }
+
+ out_size = get_left_file_size(fp);
+ if (out_size < 0) {
+ g_warning("cannot tell left file size of part %d\n", i + 1);
+ fclose(tmp_fp);
+ g_unlink(file);
+ return -1;
+ }
+ empty_line_size = get_last_empty_line_size(fp, out_size);
+ if (empty_line_size < 0) {
+ g_warning("cannot get last empty line size of part %d\n", i + 1);
+ fclose(tmp_fp);
+ g_unlink(file);
+ return -1;
+ }
+
+ if (append_file_part(fp, ftell(fp), out_size - empty_line_size,
+ tmp_fp) < 0) {
+ g_warning("write failed\n");
+ fclose(tmp_fp);
+ g_unlink(file);
+ return -1;
+ }
+
+ fclose(fp);
+ procmime_mimeinfo_free_all(mimeinfo);
+ }
+
+ fclose(tmp_fp);
+
+ return 0;
+}
+
static gboolean procmsg_get_flags(FolderItem *item, gint num,
MsgPermFlags *flags)
{