static gchar * mbox_folder_get_filename (CamelFolder *folder, const gchar *uid, GError **error) { CamelLocalFolder *lf = (CamelLocalFolder *) folder; CamelMboxMessageInfo *info; goffset frompos; gchar *filename = NULL; d (printf ("Getting message %s\n", uid)); /* lock the folder first, burn if we can't, need write lock for summary check */ if (camel_local_folder_lock (lf, CAMEL_LOCK_WRITE, error) == -1) return NULL; /* check for new messages always */ if (camel_local_summary_check ((CamelLocalSummary *) folder->summary, lf->changes, NULL, error) == -1) { camel_local_folder_unlock (lf); return NULL; } /* get the message summary info */ info = (CamelMboxMessageInfo *) camel_folder_summary_get (folder->summary, uid); if (info == NULL) { set_cannot_get_message_ex ( error, CAMEL_FOLDER_ERROR_INVALID_UID, uid, lf->folder_path, _("No such message")); goto fail; } if (info->frompos == -1) { camel_message_info_unref (info); goto fail; } frompos = info->frompos; camel_message_info_unref (info); filename = g_strdup_printf ("%s%s!%" PRId64, lf->folder_path, G_DIR_SEPARATOR_S, (gint64) frompos); fail: /* and unlock now we're finished with it */ camel_local_folder_unlock (lf); return filename; }
static gchar * maildir_folder_get_filename (CamelFolder *folder, const gchar *uid, GError **error) { CamelLocalFolder *lf = (CamelLocalFolder *)folder; CamelMaildirMessageInfo *mdi; CamelMessageInfo *info; gchar *res; /* get the message summary info */ if ((info = camel_folder_summary_uid (folder->summary, uid)) == NULL) { set_cannot_get_message_ex ( error, CAMEL_FOLDER_ERROR_INVALID_UID, uid, lf->folder_path, _("No such message")); return NULL; } mdi = (CamelMaildirMessageInfo *)info; /* what do we do if the message flags (and :info data) changes? filename mismatch - need to recheck I guess If filename is NULL, it means folder_summary_check is not yet executed. */ if (!camel_maildir_info_filename (mdi)) { gchar *temp; temp = camel_maildir_summary_info_to_name (mdi); res = g_strdup_printf("%s/cur/%s", lf->folder_path, temp); g_free (temp); } else res = g_strdup_printf("%s/cur/%s", lf->folder_path, camel_maildir_info_filename (mdi)); camel_message_info_free (info); return res; }
static gboolean maildir_folder_transfer_messages_to_sync (CamelFolder *source, GPtrArray *uids, CamelFolder *dest, gboolean delete_originals, GPtrArray **transferred_uids, GCancellable *cancellable, GError **error) { gboolean fallback = FALSE; if (delete_originals && CAMEL_IS_MAILDIR_FOLDER (source) && CAMEL_IS_MAILDIR_FOLDER (dest)) { gint i; CamelLocalFolder *lf = (CamelLocalFolder *) source; CamelLocalFolder *df = (CamelLocalFolder *) dest; camel_operation_push_message ( cancellable, _("Moving messages")); camel_folder_freeze (dest); camel_folder_freeze (source); for (i = 0; i < uids->len; i++) { gchar *uid = (gchar *) uids->pdata[i]; gchar *s_filename, *d_filename, *tmp; CamelMaildirMessageInfo *mdi; CamelMessageInfo *info; if ((info = camel_folder_summary_uid (source->summary, uid)) == NULL) { set_cannot_get_message_ex ( error, CAMEL_FOLDER_ERROR_INVALID_UID, uid, lf->folder_path, _("No such message")); return FALSE; } mdi = (CamelMaildirMessageInfo *) info; tmp = camel_maildir_summary_info_to_name (mdi); d_filename = g_strdup_printf ("%s/cur/%s", df->folder_path, tmp); g_free (tmp); s_filename = g_strdup_printf("%s/cur/%s", lf->folder_path, camel_maildir_info_filename (mdi)); if (g_rename (s_filename, d_filename) != 0) { if (errno == EXDEV) { i = uids->len + 1; fallback = TRUE; } else { g_set_error ( error, G_IO_ERROR, g_io_error_from_errno (errno), _("Cannot transfer message to destination folder: %s"), g_strerror (errno)); camel_message_info_free (info); break; } } else { camel_folder_set_message_flags ( source, uid, CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_SEEN, ~0); camel_folder_summary_remove (source->summary, info); } camel_message_info_free (info); g_free (s_filename); g_free (d_filename); } camel_folder_thaw (source); camel_folder_thaw (dest); camel_operation_pop_message (cancellable); } else fallback = TRUE; if (fallback) { CamelFolderClass *folder_class; /* Chain up to parent's transfer_messages_to() method. */ folder_class = CAMEL_FOLDER_CLASS (camel_maildir_folder_parent_class); return folder_class->transfer_messages_to_sync ( source, uids, dest, delete_originals, transferred_uids, cancellable, error); } return TRUE; }
static gchar * maildir_folder_get_filename (CamelFolder *folder, const gchar *uid, GError **error) { CamelLocalFolder *lf = (CamelLocalFolder *) folder; CamelMaildirMessageInfo *mdi; CamelMessageInfo *info; gchar *res; /* get the message summary info */ if ((info = camel_folder_summary_get (folder->summary, uid)) == NULL) { set_cannot_get_message_ex ( error, CAMEL_FOLDER_ERROR_INVALID_UID, uid, lf->folder_path, _("No such message")); return NULL; } mdi = (CamelMaildirMessageInfo *) info; /* If filename is NULL, it means folder_summary_check is not yet executed. * Try to find the file in the folder and use it, otherwise construct its * name based on actual flags. */ if (!camel_maildir_info_filename (mdi)) { const gchar *uid = camel_message_info_get_uid (info); if (uid) { GDir *dir; gchar *dirname; dirname = g_strdup_printf ("%s/cur", lf->folder_path); dir = g_dir_open (dirname, 0, NULL); g_free (dirname); if (dir) { const gchar *filename; gint uid_len = strlen (uid); while (filename = g_dir_read_name (dir), filename) { if (g_str_has_prefix (filename, uid) && (filename[uid_len] == '\0' || filename[uid_len] == CAMEL_MAILDIR_FLAG_SEP)) { camel_maildir_info_set_filename (mdi, g_strdup (filename)); break; } } g_dir_close (dir); } } if (!camel_maildir_info_filename (mdi)) { camel_maildir_info_set_filename (mdi, camel_maildir_summary_info_to_name (mdi)); } } res = g_strdup_printf ("%s/cur/%s", lf->folder_path, camel_maildir_info_filename (mdi)); camel_message_info_unref (info); return res; }
static gboolean maildir_folder_transfer_messages_to_sync (CamelFolder *source, GPtrArray *uids, CamelFolder *dest, gboolean delete_originals, GPtrArray **transferred_uids, GCancellable *cancellable, GError **error) { gboolean fallback = FALSE; if (delete_originals && CAMEL_IS_MAILDIR_FOLDER (source) && CAMEL_IS_MAILDIR_FOLDER (dest) && camel_folder_get_parent_store (source) == camel_folder_get_parent_store (dest)) { gint i; CamelLocalFolder *lf = (CamelLocalFolder *) source; CamelLocalFolder *df = (CamelLocalFolder *) dest; camel_operation_push_message ( cancellable, _("Moving messages")); camel_folder_freeze (dest); camel_folder_freeze (source); for (i = 0; i < uids->len; i++) { gchar *uid = (gchar *) uids->pdata[i]; gchar *s_filename, *d_filename, *new_filename; CamelMaildirMessageInfo *mdi; CamelMessageInfo *info; if ((info = camel_folder_summary_get (source->summary, uid)) == NULL) { set_cannot_get_message_ex ( error, CAMEL_FOLDER_ERROR_INVALID_UID, uid, lf->folder_path, _("No such message")); return FALSE; } mdi = (CamelMaildirMessageInfo *) info; new_filename = camel_maildir_summary_info_to_name (mdi); d_filename = g_strdup_printf ("%s/cur/%s", df->folder_path, new_filename); s_filename = g_strdup_printf ("%s/cur/%s", lf->folder_path, camel_maildir_info_filename (mdi)); if (g_rename (s_filename, d_filename) != 0) { if (errno == EXDEV) { i = uids->len + 1; fallback = TRUE; } else { g_set_error ( error, G_IO_ERROR, g_io_error_from_errno (errno), _("Cannot transfer message to destination folder: %s"), g_strerror (errno)); camel_message_info_unref (info); g_free (s_filename); g_free (d_filename); g_free (new_filename); break; } } else { CamelMessageInfo *clone; CamelMaildirMessageInfo *mclone; clone = camel_message_info_clone (info); clone->summary = dest->summary; mclone = (CamelMaildirMessageInfo *) clone; /* preserve also UID, as it matches the file name */ mclone->info.info.uid = camel_pstring_strdup (camel_message_info_get_uid (info)); camel_maildir_info_set_filename (clone, g_strdup (new_filename)); /* unset deleted flag when transferring from trash folder */ if ((source->folder_flags & CAMEL_FOLDER_IS_TRASH) != 0) camel_message_info_set_flags (info, CAMEL_MESSAGE_DELETED, 0); /* unset junk flag when transferring from junk folder */ if ((source->folder_flags & CAMEL_FOLDER_IS_JUNK) != 0) camel_message_info_set_flags (info, CAMEL_MESSAGE_JUNK, 0); camel_folder_summary_add (dest->summary, clone); camel_folder_change_info_add_uid (df->changes, camel_message_info_get_uid (clone)); camel_folder_set_message_flags ( source, uid, CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_SEEN, ~0); camel_folder_change_info_remove_uid (lf->changes, camel_message_info_get_uid (info)); camel_folder_summary_remove (source->summary, info); } camel_message_info_unref (info); g_free (s_filename); g_free (d_filename); g_free (new_filename); } if (lf && camel_folder_change_info_changed (lf->changes)) { camel_folder_changed (source, lf->changes); camel_folder_change_info_clear (lf->changes); } if (df && camel_folder_change_info_changed (df->changes)) { camel_folder_changed (dest, df->changes); camel_folder_change_info_clear (df->changes); } camel_folder_thaw (source); camel_folder_thaw (dest); camel_operation_pop_message (cancellable); } else fallback = TRUE; if (fallback) { CamelFolderClass *folder_class; /* Chain up to parent's transfer_messages_to() method. */ folder_class = CAMEL_FOLDER_CLASS (camel_maildir_folder_parent_class); return folder_class->transfer_messages_to_sync ( source, uids, dest, delete_originals, transferred_uids, cancellable, error); } return TRUE; }
static CamelMimeMessage * mbox_folder_get_message_sync (CamelFolder *folder, const gchar *uid, GCancellable *cancellable, GError **error) { CamelLocalFolder *lf = (CamelLocalFolder *) folder; CamelMimeMessage *message = NULL; CamelMboxMessageInfo *info; CamelMimeParser *parser = NULL; gint fd, retval; gint retried = FALSE; goffset frompos; d (printf ("Getting message %s\n", uid)); /* lock the folder first, burn if we can't, need write lock for summary check */ if (camel_local_folder_lock (lf, CAMEL_LOCK_WRITE, error) == -1) return NULL; /* check for new messages always */ if (camel_local_summary_check ((CamelLocalSummary *) folder->summary, lf->changes, cancellable, error) == -1) { camel_local_folder_unlock (lf); return NULL; } retry: /* get the message summary info */ info = (CamelMboxMessageInfo *) camel_folder_summary_get (folder->summary, uid); if (info == NULL) { set_cannot_get_message_ex ( error, CAMEL_FOLDER_ERROR_INVALID_UID, uid, lf->folder_path, _("No such message")); goto fail; } if (info->frompos == -1) { camel_message_info_unref (info); goto fail; } frompos = info->frompos; camel_message_info_unref (info); /* we use an fd instead of a normal stream here - the reason is subtle, camel_mime_part will cache * the whole message in memory if the stream is non-seekable (which it is when built from a parser * with no stream). This means we dont have to lock the mbox for the life of the message, but only * while it is being created. */ fd = g_open (lf->folder_path, O_LARGEFILE | O_RDONLY | O_BINARY, 0); if (fd == -1) { set_cannot_get_message_ex ( error, CAMEL_ERROR_GENERIC, uid, lf->folder_path, g_strerror (errno)); goto fail; } /* we use a parser to verify the message is correct, and in the correct position */ parser = camel_mime_parser_new (); camel_mime_parser_init_with_fd (parser, fd); camel_mime_parser_scan_from (parser, TRUE); camel_mime_parser_seek (parser, frompos, SEEK_SET); if (camel_mime_parser_step (parser, NULL, NULL) != CAMEL_MIME_PARSER_STATE_FROM || camel_mime_parser_tell_start_from (parser) != frompos) { g_warning ("Summary doesn't match the folder contents! eek!\n" " expecting offset %ld got %ld, state = %d", (glong) frompos, (glong) camel_mime_parser_tell_start_from (parser), camel_mime_parser_state (parser)); g_object_unref (parser); parser = NULL; if (!retried) { retried = TRUE; camel_local_summary_check_force ((CamelLocalSummary *) folder->summary); retval = camel_local_summary_check ((CamelLocalSummary *) folder->summary, lf->changes, cancellable, error); if (retval != -1) goto retry; } set_cannot_get_message_ex ( error, CAMEL_FOLDER_ERROR_INVALID, uid, lf->folder_path, _("The folder appears to be irrecoverably corrupted.")); goto fail; } message = camel_mime_message_new (); if (!camel_mime_part_construct_from_parser_sync ( (CamelMimePart *) message, parser, cancellable, error)) { g_prefix_error ( error, _("Cannot get message %s from folder %s: "), uid, lf->folder_path); g_object_unref (message); message = NULL; goto fail; } camel_medium_remove_header ((CamelMedium *) message, "X-Evolution"); fail: /* and unlock now we're finished with it */ camel_local_folder_unlock (lf); if (parser) g_object_unref (parser); /* use the opportunity to notify of changes (particularly if we had a rebuild) */ if (camel_folder_change_info_changed (lf->changes)) { camel_folder_changed (folder, lf->changes); camel_folder_change_info_clear (lf->changes); } return message; }
static CamelMimeMessage * mh_folder_get_message_sync (CamelFolder *folder, const gchar *uid, GCancellable *cancellable, GError **error) { CamelLocalFolder *lf = (CamelLocalFolder *) folder; CamelStream *message_stream = NULL; CamelMimeMessage *message = NULL; CamelMessageInfo *info; gchar *name = NULL; d(printf("getting message: %s\n", uid)); if (!lf || camel_local_folder_lock (lf, CAMEL_LOCK_WRITE, error) == -1) return NULL; /* get the message summary info */ if ((info = camel_folder_summary_get (folder->summary, uid)) == NULL) { set_cannot_get_message_ex ( error, CAMEL_FOLDER_ERROR_INVALID_UID, uid, lf->folder_path, _("No such message")); goto fail; } /* we only need it to check the message exists */ camel_message_info_free (info); name = g_strdup_printf("%s/%s", lf->folder_path, uid); message_stream = camel_stream_fs_new_with_name ( name, O_RDONLY, 0, error); if (message_stream == NULL) { g_prefix_error ( error, _("Cannot get message %s from folder %s: "), name, lf->folder_path); goto fail; } message = camel_mime_message_new (); if (!camel_data_wrapper_construct_from_stream_sync ( (CamelDataWrapper *) message, message_stream, cancellable, error)) { g_prefix_error ( error, _("Cannot get message %s from folder %s: "), name, lf->folder_path); g_object_unref (message); message = NULL; } g_object_unref (message_stream); fail: g_free (name); 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 message; }