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; }
/* Well, since Solaris is a tad broken wrt its 'mbox' folder format, * we must convert it to a real mbox format. Thankfully this is * mostly pretty easy */ static gint camel_movemail_solaris (gint oldsfd, gint dfd, GError **error) { CamelMimeParser *mp; gchar *buffer; gint len; gint sfd; CamelMimeFilter *ffrom; gint ret = 1; gchar *from = NULL; /* need to dup as the mime parser will close on finish */ sfd = dup (oldsfd); if (sfd == -1) { g_set_error ( error, G_IO_ERROR, g_io_error_from_errno (errno), _("Error copying mail temp file: %s"), g_strerror (errno)); return -1; } mp = camel_mime_parser_new (); camel_mime_parser_scan_from (mp, TRUE); camel_mime_parser_init_with_fd (mp, sfd); ffrom = camel_mime_filter_from_new (); while (camel_mime_parser_step (mp, &buffer, &len) == CAMEL_MIME_PARSER_STATE_FROM) { g_return_val_if_fail (camel_mime_parser_from_line (mp), -1); from = g_strdup (camel_mime_parser_from_line (mp)); if (camel_mime_parser_step (mp, &buffer, &len) != CAMEL_MIME_PARSER_STATE_FROM_END) { CamelNameValueArray *headers; const gchar *cl; gint length; gint start, body; goffset newpos; ret = 0; start = camel_mime_parser_tell_start_from (mp); body = camel_mime_parser_tell (mp); if (write (dfd, from, strlen (from)) != strlen (from)) goto fail; /* write out headers, but NOT content-length header */ headers = camel_mime_parser_dup_headers (mp); if (solaris_header_write (dfd, headers) == -1) { camel_name_value_array_free (headers); goto fail; } camel_name_value_array_free (headers); cl = camel_mime_parser_header (mp, "content-length", NULL); if (cl == NULL) { g_warning ("Required Content-Length header is missing from solaris mail box @ %d", (gint) camel_mime_parser_tell (mp)); camel_mime_parser_drop_step (mp); camel_mime_parser_drop_step (mp); camel_mime_parser_step (mp, &buffer, &len); camel_mime_parser_unstep (mp); length = camel_mime_parser_tell_start_from (mp) - body; newpos = -1; } else { length = atoi (cl); camel_mime_parser_drop_step (mp); camel_mime_parser_drop_step (mp); newpos = length + body; } /* copy body->length converting From lines */ if (camel_movemail_copy_filter (sfd, dfd, body, length, ffrom) == -1) goto fail; if (newpos != -1) camel_mime_parser_seek (mp, newpos, SEEK_SET); } else { g_error ("Inalid parser state: %d", camel_mime_parser_state (mp)); } g_free (from); } g_object_unref (mp); g_object_unref (ffrom); return ret; fail: g_free (from); g_set_error ( error, G_IO_ERROR, g_io_error_from_errno (errno), _("Error copying mail temp file: %s"), g_strerror (errno)); g_object_unref (mp); g_object_unref (ffrom); return -1; }