summaryrefslogtreecommitdiff
path: root/libmailutils/stream/message_stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmailutils/stream/message_stream.c')
-rw-r--r--libmailutils/stream/message_stream.c219
1 files changed, 83 insertions, 136 deletions
diff --git a/libmailutils/stream/message_stream.c b/libmailutils/stream/message_stream.c
index e1952ab0f..a26ecd531 100644
--- a/libmailutils/stream/message_stream.c
+++ b/libmailutils/stream/message_stream.c
@@ -1,5 +1,5 @@
/* GNU Mailutils -- a suite of utilities for electronic mail
- Copyright (C) 1999-2019 Free Software Foundation, Inc.
+ Copyright (C) 1999-2024 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
@@ -33,6 +33,7 @@
#include <mailutils/message.h>
#include <mailutils/header.h>
#include <mailutils/body.h>
+#include <mailutils/attribute.h>
#include <mailutils/stream.h>
#include <mailutils/util.h>
#include <mailutils/datetime.h>
@@ -44,47 +45,50 @@
static int
-_env_msg_date (mu_envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
+envelope_substr (struct _mu_message_stream *str,
+ struct mu_substring_location *loc,
+ char *buf, size_t len, size_t *pnwrite)
{
- struct _mu_message_stream *str = mu_envelope_get_owner (envelope);
-
- if (!str || !str->date)
- return EINVAL;
if (buf)
{
- strncpy (buf, str->date, len);
- buf[len-1] = 0;
+ if (len == 0)
+ return EINVAL;
+ --len;
+ if (len > loc->length)
+ len = loc->length;
+ strncpy (buf, str->envelope_string + loc->start, len);
+ buf[len] = 0;
if (pnwrite)
*pnwrite = len;
}
else if (!pnwrite)
return EINVAL;
else
- *pnwrite = strlen (str->date);
+ *pnwrite = loc->length;
return 0;
}
static int
+_env_msg_date (mu_envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
+{
+ struct _mu_message_stream *str =
+ mu_message_get_owner (mu_envelope_get_owner (envelope));
+
+ if (!str)
+ return EINVAL;
+ return envelope_substr (str, &str->date, buf, len, pnwrite);
+}
+
+static int
_env_msg_sender (mu_envelope_t envelope, char *buf, size_t len,
size_t *pnwrite)
{
- struct _mu_message_stream *str = mu_envelope_get_owner (envelope);
+ struct _mu_message_stream *str =
+ mu_message_get_owner (mu_envelope_get_owner (envelope));
- if (!str || !str->from)
+ if (!str)
return EINVAL;
- if (buf)
- {
- strncpy (buf, str->from, len);
- buf[len-1] = 0;
- if (pnwrite)
- *pnwrite = len;
- }
- else if (!pnwrite)
- return EINVAL;
- else
- *pnwrite = strlen (str->from);
-
- return 0;
+ return envelope_substr (str, &str->from, buf, len, pnwrite);
}
@@ -96,13 +100,13 @@ _message_read (mu_stream_t stream, char *optr, size_t osize, size_t *nbytes)
mu_off_t offset = s->offset + s->envelope_length;
size_t rsize;
- if (offset < s->mark_offset)
+ if (offset < s->mark.start)
{
- if (offset + osize >= s->mark_offset)
- osize = s->mark_offset - offset;
+ if (offset + osize >= s->mark.start)
+ osize = s->mark.start - offset;
}
else
- offset += s->mark_length;
+ offset += s->mark.length;
/* FIXME: Seeking each time before read is awkward. The streamref
should be modified to take care of it */
rc = mu_stream_seek (s->transport, offset, MU_SEEK_SET, NULL);
@@ -126,25 +130,10 @@ _message_size (mu_stream_t stream, mu_off_t *psize)
int rc = mu_stream_size (s->transport, psize);
if (rc == 0)
- *psize -= s->envelope_length + s->mark_length;
+ *psize -= s->envelope_length + s->mark.length;
return rc;
}
-static char *
-copy_trimmed_value (const char *str)
-{
- char *p;
- size_t len;
-
- str = mu_str_skip_class (str, MU_CTYPE_SPACE);
- p = mu_str_skip_class_comp (str, MU_CTYPE_ENDLN);
- len = p - str;
- p = malloc (len + 1);
- memcpy (p, str, len);
- p[len] = 0;
- return p;
-}
-
static int
is_header_start (const char *buf)
{
@@ -168,9 +157,6 @@ static int
_message_open (mu_stream_t stream)
{
struct _mu_message_stream *str = (struct _mu_message_stream*) stream;
- char *from = NULL;
- char *env_from = NULL;
- char *env_date = NULL;
int rc;
char *buffer = NULL;
size_t bufsize = 0;
@@ -191,37 +177,27 @@ _message_open (mu_stream_t stream)
str->envelope_length = len;
if (str->construct_envelope)
{
- char *s, *p;
-
- str->envelope_string = mu_strdup (buffer);
+ len = mu_rtrim_class (buffer, MU_CTYPE_SPACE);
+ str->envelope_string = strdup (buffer);
if (!str->envelope_string)
return ENOMEM;
- str->envelope_string[len - 1] = 0;
-
- s = str->envelope_string + 5;
- p = strchr (s, ' ');
-
- if (p)
- {
- size_t n = p - s;
- env_from = mu_alloc (n + 1);
- if (!env_from)
- return ENOMEM;
- memcpy (env_from, s, n);
- env_from[n] = 0;
- env_date = mu_strdup (p + 1);
- if (!env_date)
- {
- free (env_from);
- return ENOMEM;
- }
- }
+
+ str->from.start = 5;
+ str->from.length =
+ strcspn (str->envelope_string + str->from.start, " \t");
+
+ str->date.start = str->from.start + str->from.length +
+ strspn (str->envelope_string + str->from.start +
+ str->from.length, " \t");
+ str->date.length = len - str->date.start;
+
+ str->construct_envelope = 0;
}
}
else if (mu_mh_delim (buffer))
{
- str->mark_offset = offset;
- str->mark_length = len - 1; /* do not count the terminating
+ str->mark.start = offset;
+ str->mark.length = len - 1; /* do not count the terminating
newline */
break;
}
@@ -237,23 +213,6 @@ _message_open (mu_stream_t stream)
return MU_ERR_INVALID_EMAIL;
}
has_headers = 1;
- if (str->construct_envelope && (!env_from || !env_date))
- {
- if (!from && mu_c_strncasecmp (buffer, MU_HEADER_FROM,
- sizeof (MU_HEADER_FROM) - 1) == 0)
-
- from = copy_trimmed_value (buffer + sizeof (MU_HEADER_FROM));
- else if (!env_from
- && mu_c_strncasecmp (buffer, MU_HEADER_ENV_SENDER,
- sizeof (MU_HEADER_ENV_SENDER) - 1) == 0)
- env_from = copy_trimmed_value (buffer +
- sizeof (MU_HEADER_ENV_SENDER));
- else if (!env_date
- && mu_c_strncasecmp (buffer, MU_HEADER_ENV_DATE,
- sizeof (MU_HEADER_ENV_DATE) - 1) == 0)
- env_date = copy_trimmed_value (buffer +
- sizeof (MU_HEADER_ENV_DATE));
- }
}
offset += len;
}
@@ -267,45 +226,6 @@ _message_open (mu_stream_t stream)
if (rc)
return rc;
- if (str->construct_envelope)
- {
- if (!env_from)
- {
- if (from)
- {
- mu_address_t addr;
-
- mu_address_create (&addr, from);
- if (addr)
- {
- mu_address_aget_email (addr, 1, &env_from);
- mu_address_destroy (&addr);
- }
- }
-
- if (!env_from)
- env_from = mu_get_user_email (NULL);
- }
- free (from);
-
- if (!env_date)
- {
- struct tm *tm;
- time_t t;
- char date[MU_DATETIME_FROM_LENGTH+1];
-
- time (&t);
- tm = gmtime (&t);
- mu_strftime (date, sizeof (date), MU_DATETIME_FROM, tm);
- env_date = strdup (date);
- if (!env_date)
- return ENOMEM;
- }
-
- str->from = env_from;
- str->date = env_date;
- }
-
str->body_start = body_start;
str->body_end = body_end - 1;
@@ -325,8 +245,6 @@ _message_done (mu_stream_t stream)
struct _mu_message_stream *s = (struct _mu_message_stream*) stream;
free (s->envelope_string);
- free (s->date);
- free (s->from);
mu_stream_destroy (&s->transport);
}
@@ -419,6 +337,7 @@ mu_message_from_stream_with_envelope (mu_message_t *pmsg,
{
mu_message_t msg;
mu_body_t body;
+ mu_header_t hdr;
mu_stream_t bstream;
mu_stream_t draftstream;
int rc;
@@ -436,23 +355,51 @@ mu_message_from_stream_with_envelope (mu_message_t *pmsg,
mu_message_set_stream (msg, draftstream, draftstream);
+ sp = (struct _mu_message_stream *) draftstream;
+
if (!env)
{
- if ((rc = mu_envelope_create (&env, draftstream)))
+ if (sp->construct_envelope)
+ {
+ /*
+ * FIXME: Currently the envelope *must* be owned by the message,
+ * otherwise _mu_message_free won't destroy it.
+ * The same holds true for attribute and body.
+ */
+ rc = mu_message_reconstruct_envelope (msg, &env);
+ sp->construct_envelope = 0;
+ }
+ else if ((rc = mu_envelope_create (&env, msg)) == 0)
+ {
+ mu_envelope_set_date (env, _env_msg_date, msg);
+ mu_envelope_set_sender (env, _env_msg_sender, msg);
+ }
+
+ if (rc)
{
mu_message_destroy (&msg, draftstream);
mu_stream_destroy (&draftstream);
return rc;
}
-
- mu_envelope_set_date (env, _env_msg_date, draftstream);
- mu_envelope_set_sender (env, _env_msg_sender, draftstream);
}
mu_message_set_envelope (msg, env, draftstream);
+ if (mu_message_get_header (msg, &hdr) == 0)
+ {
+ char const *s;
+ if (mu_header_sget_value (hdr, MU_HEADER_STATUS, &s) == 0)
+ {
+ mu_attribute_t atr;
+ int flags = 0;
+ mu_attribute_string_to_flags (s, &flags);
+ mu_message_get_attribute (msg, &atr);
+ mu_attribute_unset_flags (atr, ~flags);
+ mu_attribute_set_flags (atr, flags);
+ }
+ }
+
mu_body_create (&body, msg);
- /* FIXME: It would be cleaner to use ioctl here */
- sp = (struct _mu_message_stream *) draftstream;
+
rc = mu_streamref_create_abridged (&bstream, instream,
sp->body_start, sp->body_end);
if (rc)

Return to:

Send suggestions and report system problems to the System administrator.