static gboolean mbox_folder_append_message_sync (CamelFolder *folder, CamelMimeMessage *message, CamelMessageInfo *info, gchar **appended_uid, GCancellable *cancellable, GError **error) { CamelLocalFolder *lf = (CamelLocalFolder *) folder; CamelStream *output_stream = NULL, *filter_stream = NULL; CamelMimeFilter *filter_from; CamelMboxSummary *mbs = (CamelMboxSummary *) folder->summary; CamelMessageInfo *mi; gchar *fromline = NULL; struct stat st; gint retval; gboolean has_attachment; #if 0 gchar *xev; #endif /* If we can't lock, dont do anything */ if (camel_local_folder_lock (lf, CAMEL_LOCK_WRITE, error) == -1) return FALSE; d (printf ("Appending message\n")); /* first, check the summary is correct (updates folder_size too) */ retval = camel_local_summary_check ((CamelLocalSummary *) folder->summary, lf->changes, cancellable, error); if (retval == -1) goto fail; /* add it to the summary/assign the uid, etc */ mi = camel_local_summary_add ((CamelLocalSummary *) folder->summary, message, info, lf->changes, error); if (mi == NULL) goto fail; d (printf ("Appending message: uid is %s\n", camel_message_info_get_uid (mi))); has_attachment = camel_mime_message_has_attachment (message); if (((camel_message_info_get_flags (mi) & CAMEL_MESSAGE_ATTACHMENTS) && !has_attachment) || ((camel_message_info_get_flags (mi) & CAMEL_MESSAGE_ATTACHMENTS) == 0 && has_attachment)) { camel_message_info_set_flags (mi, CAMEL_MESSAGE_ATTACHMENTS, has_attachment ? CAMEL_MESSAGE_ATTACHMENTS : 0); } output_stream = camel_stream_fs_new_with_name ( lf->folder_path, O_WRONLY | O_APPEND | O_LARGEFILE, 0666, error); if (output_stream == NULL) { g_prefix_error ( error, _("Cannot open mailbox: %s: "), lf->folder_path); goto fail; } /* and we need to set the frompos/XEV explicitly */ ((CamelMboxMessageInfo *) mi)->frompos = mbs->folder_size; #if 0 xev = camel_local_summary_encode_x_evolution ((CamelLocalSummary *) folder->summary, mi); if (xev) { /* the x-ev header should match the 'current' flags, no problem, so store as much */ camel_medium_set_header ((CamelMedium *) message, "X-Evolution", xev); mi->flags &= ~ CAMEL_MESSAGE_FOLDER_NOXEV | CAMEL_MESSAGE_FOLDER_FLAGGED; g_free (xev); } #endif /* we must write this to the non-filtered stream ... */ fromline = camel_mime_message_build_mbox_from (message); if (camel_stream_write (output_stream, fromline, strlen (fromline), cancellable, error) == -1) goto fail_write; /* and write the content to the filtering stream, that translates '\nFrom' into '\n>From' */ filter_stream = camel_stream_filter_new (output_stream); filter_from = camel_mime_filter_from_new (); camel_stream_filter_add ((CamelStreamFilter *) filter_stream, filter_from); g_object_unref (filter_from); if (camel_data_wrapper_write_to_stream_sync ( (CamelDataWrapper *) message, filter_stream, cancellable, error) == -1 || camel_stream_write (filter_stream, "\n", 1, cancellable, error) == -1 || camel_stream_flush (filter_stream, cancellable, error) == -1) goto fail_write; /* filter stream ref's the output stream itself, so we need to unref it too */ g_object_unref (filter_stream); g_object_unref (output_stream); g_free (fromline); if (!((CamelMessageInfoBase *) mi)->preview && camel_folder_summary_get_need_preview (folder->summary)) { if (camel_mime_message_build_preview ((CamelMimePart *) message, mi) && ((CamelMessageInfoBase *) mi)->preview) camel_folder_summary_add_preview (folder->summary, mi); } /* now we 'fudge' the summary to tell it its uptodate, because its idea of uptodate has just changed */ /* the stat really shouldn't fail, we just wrote to it */ if (g_stat (lf->folder_path, &st) == 0) { ((CamelFolderSummary *) mbs)->time = st.st_mtime; mbs->folder_size = st.st_size; } /* unlock as soon as we can */ camel_local_folder_unlock (lf); if (camel_folder_change_info_changed (lf->changes)) { camel_folder_changed (folder, lf->changes); camel_folder_change_info_clear (lf->changes); } if (appended_uid) *appended_uid = g_strdup(camel_message_info_get_uid(mi)); return TRUE; fail_write: g_prefix_error ( error, _("Cannot append message to mbox file: %s: "), lf->folder_path); if (output_stream) { gint fd; fd = camel_stream_fs_get_fd (CAMEL_STREAM_FS (output_stream)); if (fd != -1) { /* reset the file to original size */ do { retval = ftruncate (fd, mbs->folder_size); } while (retval == -1 && errno == EINTR); } g_object_unref (output_stream); } if (filter_stream) g_object_unref (filter_stream); g_free (fromline); /* remove the summary info so we are not out-of-sync with the mbox */ camel_folder_summary_remove (CAMEL_FOLDER_SUMMARY (mbs), mi); /* and tell the summary it's up-to-date */ if (g_stat (lf->folder_path, &st) == 0) { ((CamelFolderSummary *) mbs)->time = st.st_mtime; mbs->folder_size = st.st_size; } fail: /* make sure we unlock the folder - before we start triggering events into appland */ camel_local_folder_unlock (lf); /* cascade the changes through, anyway, if there are any outstanding */ if (camel_folder_change_info_changed (lf->changes)) { camel_folder_changed (folder, lf->changes); camel_folder_change_info_clear (lf->changes); } return FALSE; }
static gboolean maildir_folder_append_message_sync (CamelFolder *folder, CamelMimeMessage *message, CamelMessageInfo *info, gchar **appended_uid, GCancellable *cancellable, GError **error) { CamelLocalFolder *lf = (CamelLocalFolder *)folder; CamelStream *output_stream; CamelMessageInfo *mi; CamelMaildirMessageInfo *mdi; gchar *name, *dest = NULL; gboolean success = TRUE; d(printf("Appending message\n")); /* If we can't lock, don't do anything */ if (camel_local_folder_lock (lf, CAMEL_LOCK_WRITE, error) == -1) return FALSE; /* add it to the summary/assign the uid, etc */ mi = camel_local_summary_add ( CAMEL_LOCAL_SUMMARY (folder->summary), message, info, lf->changes, error); if (mi == NULL) goto check_changed; if ((camel_message_info_flags (mi) & CAMEL_MESSAGE_ATTACHMENTS) && !camel_mime_message_has_attachment (message)) camel_message_info_set_flags (mi, CAMEL_MESSAGE_ATTACHMENTS, 0); mdi = (CamelMaildirMessageInfo *)mi; d(printf("Appending message: uid is %s filename is %s\n", camel_message_info_uid(mi), mdi->filename)); /* write it out to tmp, use the uid we got from the summary */ name = g_strdup_printf ("%s/tmp/%s", lf->folder_path, camel_message_info_uid(mi)); output_stream = camel_stream_fs_new_with_name ( name, O_WRONLY|O_CREAT, 0600, error); if (output_stream == NULL) goto fail_write; if (camel_data_wrapper_write_to_stream_sync ( (CamelDataWrapper *)message, output_stream, cancellable, error) == -1 || camel_stream_close (output_stream, cancellable, error) == -1) goto fail_write; /* now move from tmp to cur (bypass new, does it matter?) */ dest = g_strdup_printf("%s/cur/%s", lf->folder_path, camel_maildir_info_filename (mdi)); if (g_rename (name, dest) == -1) { g_set_error ( error, G_IO_ERROR, g_io_error_from_errno (errno), "%s", g_strerror (errno)); goto fail_write; } g_free (dest); g_free (name); if (appended_uid) *appended_uid = g_strdup(camel_message_info_uid(mi)); if (output_stream) g_object_unref (output_stream); goto check_changed; fail_write: /* remove the summary info so we are not out-of-sync with the mh folder */ camel_folder_summary_remove_uid (CAMEL_FOLDER_SUMMARY (folder->summary), camel_message_info_uid (mi)); g_prefix_error ( error, _("Cannot append message to maildir folder: %s: "), name); if (output_stream) { g_object_unref (CAMEL_OBJECT (output_stream)); unlink (name); } g_free (name); g_free (dest); success = FALSE; check_changed: camel_local_folder_unlock (lf); if (lf && camel_folder_change_info_changed (lf->changes)) { camel_folder_changed (folder, lf->changes); camel_folder_change_info_clear (lf->changes); } return success; }
static gboolean mh_folder_append_message_sync (CamelFolder *folder, CamelMimeMessage *message, CamelMessageInfo *info, gchar **appended_uid, GCancellable *cancellable, GError **error) { CamelLocalFolder *lf = (CamelLocalFolder *) folder; CamelStream *output_stream; CamelMessageInfo *mi; gchar *name; gboolean has_attachment; /* FIXME: probably needs additional locking (although mh doesn't appear do do it) */ d(printf("Appending message\n")); /* If we can't lock, don't do anything */ if (!lf || camel_local_folder_lock (lf, CAMEL_LOCK_WRITE, error) == -1) return FALSE; /* add it to the summary/assign the uid, etc */ mi = camel_local_summary_add ((CamelLocalSummary *) folder->summary, message, info, lf->changes, error); if (mi == NULL) goto check_changed; has_attachment = camel_mime_message_has_attachment (message); if (((camel_message_info_flags (mi) & CAMEL_MESSAGE_ATTACHMENTS) && !has_attachment) || ((camel_message_info_flags (mi) & CAMEL_MESSAGE_ATTACHMENTS) == 0 && has_attachment)) { camel_message_info_set_flags (mi, CAMEL_MESSAGE_ATTACHMENTS, has_attachment ? CAMEL_MESSAGE_ATTACHMENTS : 0); } d(printf("Appending message: uid is %s\n", camel_message_info_uid(mi))); /* write it out, use the uid we got from the summary */ name = g_strdup_printf("%s/%s", lf->folder_path, camel_message_info_uid(mi)); output_stream = camel_stream_fs_new_with_name ( name, O_WRONLY | O_CREAT, 0600, error); if (output_stream == NULL) goto fail_write; if (camel_data_wrapper_write_to_stream_sync ( (CamelDataWrapper *) message, output_stream, cancellable, error) == -1 || camel_stream_close (output_stream, cancellable, error) == -1) goto fail_write; /* close this? */ g_object_unref (output_stream); g_free (name); if (appended_uid) *appended_uid = g_strdup(camel_message_info_uid(mi)); goto check_changed; fail_write: /* remove the summary info so we are not out-of-sync with the mh folder */ camel_folder_summary_remove_uid (CAMEL_FOLDER_SUMMARY (folder->summary), camel_message_info_uid (mi)); g_prefix_error ( error, _("Cannot append message to mh folder: %s: "), name); if (output_stream) { g_object_unref (output_stream); unlink (name); } g_free (name); check_changed: camel_local_folder_unlock (lf); if (camel_folder_change_info_changed (lf->changes)) { camel_folder_changed (folder, lf->changes); camel_folder_change_info_clear (lf->changes); } return TRUE; }