Commit 2f91c458 2f91c458b8c009c0ef6245241f7042b167d98062 by Sergey Poznyakoff

Rewritten using mu_stream_to_message. Actually,

the source can be removed now and the function moved elsewhere,
e.g. to mh_init...
1 parent 8247640c
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2001, 2002, 2005,
2006 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -24,385 +25,18 @@
#include <mh.h>
#include <mailutils/stream.h>
static int
_mh_delim (char *str)
{
if (str[0] == '-')
{
for (; *str == '-'; str++)
;
for (; *str == ' ' || *str == '\t'; str++)
;
}
return str[0] == '\n';
}
struct _mhdraft_stream {
mu_stream_t stream; /* Actual stream */
size_t mark_offset; /* Offset of the header separator */
size_t mark_length; /* Length of the header separator (not counting the
newline) */
};
static int
_mhdraft_read (mu_stream_t stream, char *optr, size_t osize,
mu_off_t offset, size_t *nbytes)
{
struct _mhdraft_stream *s = mu_stream_get_owner (stream);
if (offset < s->mark_offset)
{
if (offset + osize >= s->mark_offset)
osize = s->mark_offset - offset;
}
else
offset += s->mark_length;
return mu_stream_read (s->stream, optr, osize, offset, nbytes);
}
static int
_mhdraft_readline (mu_stream_t stream, char *optr, size_t osize,
mu_off_t offset, size_t *nbytes)
{
struct _mhdraft_stream *s = mu_stream_get_owner (stream);
if (offset < s->mark_offset)
{
if (offset + osize >= s->mark_offset)
{
int rc;
size_t n;
size_t rdsize = s->mark_offset - offset + 1;
rc = mu_stream_readline (s->stream, optr, rdsize, offset, &n);
if (rc == 0)
{
if (nbytes)
*nbytes = n;
}
return rc;
}
}
else
offset += s->mark_length;
return mu_stream_readline (s->stream, optr, osize, offset, nbytes);
}
static int
_mhdraft_size (mu_stream_t stream, mu_off_t *psize)
{
struct _mhdraft_stream *s = mu_stream_get_owner (stream);
int rc = mu_stream_size (s->stream, psize);
if (rc == 0)
*psize -= s->mark_length;
return rc;
}
static int
_mhdraft_open (mu_stream_t stream)
{
struct _mhdraft_stream *s = mu_stream_get_owner (stream);
size_t offset, len;
char buffer[256];
int rc;
offset = 0;
while ((rc = mu_stream_readline (s->stream, buffer, sizeof buffer,
offset, &len)) == 0
&& len > 0)
{
if (_mh_delim (buffer))
{
s->mark_offset = offset;
s->mark_length = len - 1; /* do not count the terminating newline */
break;
}
offset += len;
}
return 0;
}
static int
_mhdraft_close (mu_stream_t stream)
{
struct _mhdraft_stream *s = mu_stream_get_owner (stream);
return mu_stream_close (s->stream);
}
static void
_mhdraft_destroy (mu_stream_t stream)
{
struct _mhdraft_stream *s = mu_stream_get_owner (stream);
if (s->stream)
mu_stream_destroy (&s->stream, mu_stream_get_owner (s->stream));
free (s);
}
int
mhdraft_stream_create (mu_stream_t *stream, mu_stream_t src, int flags)
{
struct _mhdraft_stream *s;
int rc;
if (!flags)
flags = MU_STREAM_READ;
if (flags != MU_STREAM_READ)
return EINVAL;
s = calloc (1, sizeof (*s));
if (s == NULL)
return ENOMEM;
s->stream = src;
rc = mu_stream_create (stream, flags|MU_STREAM_NO_CHECK, s);
if (rc)
{
free (s);
return rc;
}
mu_stream_set_open (*stream, _mhdraft_open, s);
mu_stream_set_close (*stream, _mhdraft_close, s);
mu_stream_set_destroy (*stream, _mhdraft_destroy, s);
mu_stream_set_readline (*stream, _mhdraft_readline, s);
mu_stream_set_read (*stream, _mhdraft_read, s);
mu_stream_set_size (*stream, _mhdraft_size, s);
return 0;
}
/* *************************** MH draft message **************************** */
char *
skipws (char *p, size_t off)
{
int len;
for (p += off; *p && isspace (*p); p++)
;
len = strlen (p);
if (len > 0 && p[len-1] == '\n')
p[len-1] = 0;
return p;
}
struct _mhdraft_message
{
char *from;
char *date;
mu_off_t body_start;
mu_off_t body_end;
};
static int
restore_envelope (mu_stream_t str, struct _mhdraft_message **pmenv)
{
size_t offset = 0;
char *from = NULL;
char *env_from = NULL;
char *env_date = NULL;
int rc;
char buffer[128];
size_t len;
mu_off_t body_start, body_end;
while ((rc = mu_stream_readline (str, buffer, sizeof buffer, offset, &len)) == 0
&& len > 0)
{
if (buffer[0] == '\n')
break;
buffer[len] = 0;
offset += len;
if (strncasecmp (buffer, MU_HEADER_FROM,
sizeof (MU_HEADER_FROM) - 1) == 0)
from = strdup (skipws (buffer, sizeof (MU_HEADER_FROM)));
else if (strncasecmp (buffer, MU_HEADER_ENV_SENDER,
sizeof (MU_HEADER_ENV_SENDER) - 1) == 0)
env_from = strdup (skipws (buffer, sizeof (MU_HEADER_ENV_SENDER)));
else if (strncasecmp (buffer, MU_HEADER_ENV_DATE,
sizeof (MU_HEADER_ENV_DATE) - 1) == 0)
env_date = strdup (skipws (buffer, sizeof (MU_HEADER_ENV_DATE)));
}
body_start = offset + 1;
mu_stream_size (str, &body_end);
if (!env_from)
{
if (from)
{
mu_address_t addr;
mu_address_create (&addr, from);
if (!addr
|| mu_address_aget_email (addr, 1, &env_from))
env_from = strdup ("GNU-MH");
mu_address_destroy (&addr);
}
else
env_from = strdup ("GNU-MH");
}
if (!env_date)
{
struct tm *tm;
time_t t;
char date[80];
time(&t);
tm = gmtime(&t);
strftime (date, sizeof (date), "%a %b %e %H:%M:%S %Y", tm);
env_date = strdup (date);
}
*pmenv = xmalloc (sizeof (**pmenv)
+ strlen (env_from)
+ strlen (env_date)
+ 2);
(*pmenv)->from = (char*) (*pmenv + 1);
(*pmenv)->date = (char*) ((*pmenv)->from + strlen (env_from) + 1);
strcpy ((*pmenv)->from, env_from);
strcpy ((*pmenv)->date, env_date);
(*pmenv)->body_start = body_start;
(*pmenv)->body_end = body_end;
free (env_from);
free (env_date);
free (from);
return 0;
}
static int
_env_msg_date (mu_envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
{
mu_message_t msg = mu_envelope_get_owner (envelope);
struct _mhdraft_message *env = mu_message_get_owner (msg);
if (!env || !env->date)
return EINVAL;
strncpy (buf, env->date, len);
buf[len-1] = 0;
return 0;
}
static int
_env_msg_sender (mu_envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
{
mu_message_t msg = mu_envelope_get_owner (envelope);
struct _mhdraft_message *env = mu_message_get_owner (msg);
if (!env || !env->from)
return EINVAL;
strncpy (buf, env->from, len);
buf[len-1] = 0;
return 0;
}
static int
_body_size (mu_body_t body, size_t *size)
{
mu_message_t msg = mu_body_get_owner (body);
struct _mhdraft_message *mp = mu_message_get_owner (msg);
if (size)
*size = mp->body_end - mp->body_start;
return 0;
}
static int
_body_read (mu_stream_t stream, char *optr, size_t osize,
mu_off_t offset, size_t *nbytes)
{
mu_body_t body = mu_stream_get_owner (stream);
mu_message_t msg = mu_body_get_owner (body);
struct _mhdraft_message *mp = mu_message_get_owner (msg);
mu_stream_t str;
mu_message_get_stream (msg, &str);
return mu_stream_read (str, optr, osize, mp->body_start + offset, nbytes);
}
static int
_body_readline (mu_stream_t stream, char *optr, size_t osize,
mu_off_t offset, size_t *nbytes)
{
mu_body_t body = mu_stream_get_owner (stream);
mu_message_t msg = mu_body_get_owner (body);
struct _mhdraft_message *mp = mu_message_get_owner (msg);
mu_stream_t str;
mu_message_get_stream (msg, &str);
return mu_stream_readline (str, optr, osize, mp->body_start + offset, nbytes);
}
static int
_body_stream_size (mu_stream_t stream, mu_off_t *psize)
{
mu_body_t body = mu_stream_get_owner (stream);
mu_message_t msg = mu_body_get_owner (body);
struct _mhdraft_message *mp = mu_message_get_owner (msg);
if (psize)
*psize = mp->body_end - mp->body_start;
return 0;
}
mu_message_t
mh_stream_to_message (mu_stream_t instream)
{
struct _mhdraft_message *mp;
mu_envelope_t env;
mu_message_t msg;
mu_body_t body;
mu_stream_t bstream;
mu_stream_t draftstream;
int rc;
mu_message_t msg;
if ((rc = mhdraft_stream_create (&draftstream, instream, 0)))
{
mh_error(_("cannot create draft message stream: %s"),
mu_strerror (rc));
return NULL;
}
if ((rc = mu_stream_open (draftstream)))
rc = mu_stream_to_message (instream, &msg);
if (rc)
{
mh_error (_("cannot open draft message stream: %s"),
mu_strerror (rc));
mu_stream_destroy (&draftstream, mu_stream_get_owner (draftstream));
return NULL;
}
restore_envelope (draftstream, &mp);
if (mu_message_create (&msg, mp))
return NULL;
mu_message_set_stream (msg, draftstream, mp);
if (mu_envelope_create (&env, msg))
return NULL;
mu_envelope_set_date (env, _env_msg_date, msg);
mu_envelope_set_sender (env, _env_msg_sender, msg);
mu_message_set_envelope (msg, env, mp);
mu_body_create (&body, msg);
mu_stream_create (&bstream, MU_STREAM_RDWR | MU_STREAM_SEEKABLE, body);
mu_stream_set_read (bstream, _body_read, body);
mu_stream_set_readline (bstream, _body_readline, body);
mu_stream_set_size (bstream, _body_stream_size, body);
mu_body_set_stream (body, bstream, msg);
mu_body_set_size (body, _body_size, msg);
mu_message_set_body (msg, body, mp);
return msg;
}
......