static gboolean
mime_message_construct_from_parser_sync (CamelMimePart *dw,
                                         CamelMimeParser *mp,
                                         GCancellable *cancellable,
                                         GError **error)
{
	CamelMimePartClass *mime_part_class;
	gchar *buf;
	gsize len;
	gint state;
	gint err;
	gboolean success;

	/* let the mime-part construct the guts ... */
	mime_part_class = CAMEL_MIME_PART_CLASS (camel_mime_message_parent_class);
	success = mime_part_class->construct_from_parser_sync (
		dw, mp, cancellable, error);

	if (!success)
		return FALSE;

	/* ... then clean up the follow-on state */
	state = camel_mime_parser_step (mp, &buf, &len);
	switch (state) {
	case CAMEL_MIME_PARSER_STATE_EOF:
	case CAMEL_MIME_PARSER_STATE_FROM_END:
		/* these doesn't belong to us */
		camel_mime_parser_unstep (mp);
	case CAMEL_MIME_PARSER_STATE_MESSAGE_END:
		break;
	default:
		g_error ("Bad parser state: Expecing MESSAGE_END or EOF or EOM, got: %u", camel_mime_parser_state (mp));
		camel_mime_parser_unstep (mp);
		return FALSE;
	}

	err = camel_mime_parser_errno (mp);
	if (err != 0) {
		errno = err;
		g_set_error (
			error, G_IO_ERROR,
			g_io_error_from_errno (errno),
			"%s", g_strerror (errno));
		success = FALSE;
	}

	return success;
}
static gint
multipart_signed_skip_content (CamelMimeParser *cmp)
{
	gchar *buf;
	gsize len;
	gint state;

	switch (camel_mime_parser_state (cmp)) {
	case CAMEL_MIME_PARSER_STATE_HEADER:
		/* body part */
		while (camel_mime_parser_step (cmp, &buf, &len) != CAMEL_MIME_PARSER_STATE_BODY_END)
			/* NOOP */ ;
		break;
	case CAMEL_MIME_PARSER_STATE_MESSAGE:
		/* message body part */
		(void) camel_mime_parser_step (cmp, &buf, &len);
		multipart_signed_skip_content (cmp);

		/* clean up followon state if any, see camel-mime-message.c */
		state = camel_mime_parser_step (cmp, &buf, &len);
		switch (state) {
		case CAMEL_MIME_PARSER_STATE_EOF:
		case CAMEL_MIME_PARSER_STATE_FROM_END: /* these doesn't belong to us */
			camel_mime_parser_unstep (cmp);
		case CAMEL_MIME_PARSER_STATE_MESSAGE_END:
			break;
		default:
			g_error ("Bad parser state: Expecting MESSAGE_END or EOF or EOM, got: %u", camel_mime_parser_state (cmp));
			camel_mime_parser_unstep (cmp);
			return -1;
		}
		break;
	case CAMEL_MIME_PARSER_STATE_MULTIPART:
		/* embedded multipart */
		while (camel_mime_parser_step (cmp, &buf, &len) != CAMEL_MIME_PARSER_STATE_MULTIPART_END)
			multipart_signed_skip_content (cmp);
		break;
	default:
		g_warning ("Invalid state encountered???: %u", camel_mime_parser_state (cmp));
	}

	return 0;
}
static gint
multipart_construct_from_parser (CamelMultipart *multipart,
                                 CamelMimeParser *mp)
{
	gint err;
	CamelContentType *content_type;
	CamelMimePart *bodypart;
	gchar *buf;
	gsize len;

	g_assert (camel_mime_parser_state (mp) == CAMEL_MIME_PARSER_STATE_MULTIPART);

	/* FIXME: we should use a came-mime-mutlipart, not jsut a camel-multipart, but who cares */
	d(printf("Creating multi-part\n"));

	content_type = camel_mime_parser_content_type (mp);
	camel_multipart_set_boundary (multipart,
				     camel_content_type_param(content_type, "boundary"));

	while (camel_mime_parser_step (mp, &buf, &len) != CAMEL_MIME_PARSER_STATE_MULTIPART_END) {
		camel_mime_parser_unstep (mp);
		bodypart = camel_mime_part_new ();
		camel_mime_part_construct_from_parser_sync (
			bodypart, mp, NULL, NULL);
		camel_multipart_add_part (multipart, bodypart);
		g_object_unref (bodypart);
	}

	/* these are only return valid data in the MULTIPART_END state */
	camel_multipart_set_preface (multipart, camel_mime_parser_preface (mp));
	camel_multipart_set_postface (multipart, camel_mime_parser_postface (mp));

	err = camel_mime_parser_errno (mp);
	if (err != 0) {
		errno = err;
		return -1;
	} else
		return 0;
}
/* 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;
}