Commit bbbdd3d8 bbbdd3d8f2b51a3e9ec0bbc4af756fe4291c4789 by Alain Magloire

message_t is a general structure that encapsulate envelope_t, header_t and

body_t etc ...
Accessing member of the structure is thread-safe, a monitor/lock is use
the downside the lock is grab for each modification.
1 parent 87eccb42
@code{#include <mailutils/message.h>}
The @code{message_t} object is a convenient way to manipulate messages. It
encapsulates the @code{header_t}, the @code{attribute_t} and the @code{body_t}.
encapsulates the @code{envelope_t}, the @code{header_t} and the @code{body_t}.
@example
@group
__________ message_t
(message[1]) +------>+-----------------------+
---------- | | header_t |
---------- | | envelope_t |
(message[2]) | |-----------------------|
---------- | | attribute_t |
---------- | | header_t |
(message[3])--------+ |-----------------------|
---------- | stream_t |
(message[n]) |-----------------------|
---------- | body_t |
(message[n]) |-----------------------|
---------- | attribute_t |
|-----------------------|
| from |
| stream_t |
|-----------------------|
| size |
|-----------------------|
......@@ -78,10 +78,10 @@ Return non-zero value if message is multi-part.
@deftypefun int message_set_attribute (message_t @var{msg}, attribute_t @var{attribute}, void *owner)
@end deftypefun
@deftypefun int message_get_from (message_t @var{msg}, char *buffer, size_t len, size_t *n)
@deftypefun int message_get_envelope (message_t @var{msg}, envelope_t *penvelope)
@end deftypefun
@deftypefun int message_set_from (message_t @var{msg}, int (*@var{_from}) (message_t, char *, size_t, size_t *), void *@var{owner})
@deftypefun int message_set_envelope (message_t @var{msg}, envelope_t envelope, void *@var{owner})
@end deftypefun
@deftypefun int message_get_uidl (message_t @var{msg}, char *@var{buffer}, size_t @var{buflen}, size_t *@var{pwriten})
......
......@@ -5,6 +5,7 @@ pkginclude_HEADERS = \
auth.h \
body.h \
debug.h \
envelope.h \
folder.h \
header.h \
iterator.h \
......@@ -14,6 +15,7 @@ pkginclude_HEADERS = \
mailer.h \
message.h \
mime.h \
monitor.h \
observer.h \
registrar.h \
stream.h \
......
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Library Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _MAILUTILS_ENVELOPE_H
# define _MAILUTILS_ENVELOPE_H
#include <sys/types.h>
#ifdef __cplusplus
extern "C" { /*}*/
#endif
#ifndef __P
# ifdef __STDC__
# define __P(args) args
# else
# define __P(args) ()
# endif
#endif /*__P */
struct _envelope;
typedef struct _envelope *envelope_t;
int envelope_create (envelope_t *, void *);
void envelope_destroy (envelope_t *, void *);
void * envelope_get_owner (envelope_t);
int envelope_set_from (envelope_t, int (*_from) __P ((envelope_t, char *, size_t, size_t*)), void *);
int envelope_from (envelope_t, char *, size_t, size_t *);
int envelope_set_date (envelope_t, int (*_date) __P ((envelope_t, char *, size_t , size_t *)), void *);
int envelope_date (envelope_t, char *, size_t, size_t *);
#endif /* _MAILUTILS_ENVELOPE_H */
......@@ -53,7 +53,7 @@ extern int folder_close __P ((folder_t));
extern int folder_delete_mailbox __P ((folder_t, const char *));
extern int folder_list __P ((folder_t, list_t *list));
extern int folder_list __P ((folder_t, char *vector[][], size_t *));
/* Stream settings. */
extern int folder_get_stream __P ((folder_t, stream_t *));
......
......@@ -19,11 +19,13 @@
#define _MAILUTILS_MESSAGE_H
#include <sys/types.h>
#include <mailutils/stream.h>
#include <mailutils/envelope.h>
#include <mailutils/header.h>
#include <mailutils/body.h>
#include <mailutils/stream.h>
#include <mailutils/observer.h>
#include <mailutils/attribute.h>
#include <mailutils/monitor.h>
#ifndef __P
......@@ -53,6 +55,9 @@ extern void * message_get_owner __P ((message_t));
extern int message_ref __P ((message_t));
#define message_unref(msg) message_destroy (&msg, NULL)
extern int message_get_envelope __P ((message_t, envelope_t *));
extern int message_set_envelope __P ((message_t, envelope_t, void *owner));
extern int message_get_header __P ((message_t, header_t *));
extern int message_set_header __P ((message_t, header_t, void *owner));
......@@ -81,16 +86,6 @@ extern int message_set_lines __P ((message_t, int (*_lines)
__P ((message_t, size_t *)),
void *owner));
extern int message_from __P ((message_t, char *, size_t, size_t *));
extern int message_set_from __P ((message_t, int (*_from)
__P ((message_t, char *, size_t,
size_t *)), void *owner));
extern int message_received __P ((message_t, char *, size_t, size_t *));
extern int message_set_received __P ((message_t, int (*_received)
__P ((message_t, char *, size_t,
size_t *)), void *owner));
extern int message_get_num_parts __P ((message_t, size_t *nparts));
extern int message_set_get_num_parts __P ((message_t, int (*_get_num_parts)
__P ((message_t, size_t *)),
......
......@@ -245,7 +245,7 @@ main (int argc, char **argv)
{
int len;
free (command);
command = readline (prompt->set && prompt->value != NULL ? prompt->value : "");
command = readline (prompt->set && prompt->value != NULL ? prompt->value : " ");
len = strlen (command);
while (command[len-1] == '\\')
{
......
......@@ -19,6 +19,7 @@ auth.c \
bio.c \
body.c \
debug.c \
envelope.c \
file_stream.c \
folder.c \
header.c \
......@@ -35,6 +36,7 @@ mbx_pop.c \
message.c \
mime.c \
misc.c
monitor.c
observer.c \
registrar.c \
sendmail.c \
......
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Library Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <errno.h>
#include <stdlib.h>
#include <envelope0.h>
int
envelope_create (envelope_t *penvelope, void *owner)
{
envelope_t envelope;
if (penvelope == NULL)
return EINVAL;
envelope = calloc (1, sizeof (*envelope));
if (envelope == NULL)
return ENOMEM;
envelope->owner = owner;
*penvelope = envelope;
return 0;
}
void
envelope_destroy (envelope_t *penvelope, void *owner)
{
if (penvelope && *penvelope)
{
envelope_t envelope = *penvelope;
if (envelope->owner == owner)
{
if (envelope->_destroy)
envelope->_destroy (envelope);
free (envelope);
}
*penvelope = NULL;
}
}
void *
envelope_get_owner (envelope_t envelope)
{
return (envelope) ? envelope->owner : NULL;
}
int
envelope_set_from (envelope_t envelope,
int (*_from) __P ((envelope_t, char *, size_t, size_t*)),
void *owner)
{
if (envelope == NULL)
return EINVAL;
if (envelope->owner != owner)
return EACCES;
envelope->_from = _from;
return 0;
}
int
envelope_from (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
{
if (envelope == NULL)
return EINVAL;
if (envelope->_from)
return envelope->_from (envelope, buf, len, pnwrite);
if (buf && len)
*buf = '\0';
if (pnwrite)
*pnwrite = 0;
return 0;
}
int
envelope_set_date (envelope_t envelope,
int (*_date) __P ((envelope_t, char *, size_t , size_t *)),
void *owner)
{
if (envelope == NULL)
return EINVAL;
if (envelope->owner != owner)
return EACCES;
envelope->_date = _date;
return 0;
}
int
envelope_date (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
{
if (envelope == NULL)
return EINVAL;
if (envelope->_date)
return envelope->_date (envelope, buf, len, pnwrite);
if (buf && len)
*buf = '\0';
if (pnwrite)
*pnwrite = 0;
return 0;
}
......@@ -165,23 +165,19 @@ folder_destroy (folder_t *pfolder)
folder_t folder = *pfolder;
int destroy_lock = 0;
monitor_t monitor = folder->monitor;
size_t reference;
monitor_wrlock (monitor);
#ifdef WITH_PTHREAD
pthread_mutex_lock (&slock);
#endif
{
folder->ref--;
reference = folder->ref;
/* Remove the folder from the list of known folder. */
if (reference == 0)
list_remove (known_folder_list, folder);
}
folder->ref--;
/* Remove the folder from the list of known folder. */
if (folder->ref <= 0)
list_remove (known_folder_list, folder);
#ifdef WITH_PHTREAD
pthread_mutex_unlock (&slock);
#endif
if (reference == 0)
if (folder->ref <= 0)
{
monitor_unlock (monitor);
destroy_lock = 1;
......@@ -328,13 +324,12 @@ folder_get_debug (folder_t folder, debug_t *pdebug)
return 0;
}
int
folder_list (folder_t folder, list_t *plist)
folder_list (folder_t folder, char *vector[][], size_t *pnum)
{
if (folder == NULL || folder->_list == NULL)
return ENOSYS;
return folder->_list (folder, plist);
return folder->_list (folder, vector, pnum);
}
int
......@@ -380,7 +375,7 @@ static int is_known_folder (url_t url, folder_t *pfolder)
static int
is_same_scheme (url_t url1, url_t url2)
{
int i = 0, j = 0;
size_t i = 0, j = 0;
char *s1, *s2;
int ret = 1;
......@@ -405,7 +400,7 @@ is_same_scheme (url_t url1, url_t url2)
static int
is_same_user (url_t url1, url_t url2)
{
int i = 0, j = 0;
size_t i = 0, j = 0;
char *s1, *s2;
int ret = 0;
......@@ -430,7 +425,7 @@ is_same_user (url_t url1, url_t url2)
static int
is_same_path (url_t url1, url_t url2)
{
int i = 0, j = 0;
size_t i = 0, j = 0;
char *s1, *s2;
int ret = 0;
......@@ -455,7 +450,7 @@ is_same_path (url_t url1, url_t url2)
static int
is_same_host (url_t url1, url_t url2)
{
int i = 0, j = 0;
size_t i = 0, j = 0;
char *s1, *s2;
int ret = 0;
......
......@@ -5,6 +5,7 @@ auth0.h \
bio.h \
body0.h \
debug0.h \
envelope0.h \
folder0.h \
header0.h \
iterator0.h \
......@@ -14,6 +15,7 @@ mailer0.h \
message0.h \
mime0.h \
misc.h \
monitor0.h \
observer0.h \
registrar0.h \
stream0.h \
......
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Library Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifndef _ENVELOPE0_H
#define _ENVELOPE0_H
#ifdef DMALLOC
#include <dmalloc.h>
#endif
#include <mailutils/envelope.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __P
# ifdef __STDC__
# define __P(args) args
# else
# define __P(args) ()
# endif
#endif /*__P */
struct _envelope
{
void *owner;
int (*_destroy) __P ((envelope_t));
int (*_from) __P ((envelope_t, char *, size_t, size_t*));
int (*_date) __P ((envelope_t, char *, size_t , size_t *));
};
#endif /* _ENVELOPE0_H */
......@@ -51,7 +51,7 @@ struct _folder
monitor_t monitor;
url_t url;
int flags;
size_t ref;
int ref;
size_t uid;
/* Back pointer to the specific mailbox */
......@@ -64,7 +64,7 @@ struct _folder
int (*_open) __P ((folder_t, int flag));
int (*_close) __P ((folder_t));
int (*_list) __P ((folder_t, list_t *));
int (*_list) __P ((folder_t, char *vector[][], size_t *num));
int (*_delete_mailbox) __P ((folder_t, const char *));
};
......
......@@ -45,10 +45,13 @@ struct _message
/* Who is the owner. */
void *owner;
envelope_t envelope;
header_t header;
stream_t stream;
body_t body;
stream_t stream;
attribute_t attribute;
monitor_t monitor;
mime_t mime;
observable_t observable;
......@@ -60,8 +63,6 @@ struct _message
size_t hdr_buflen;
int hdr_done;
int (*_from) __P ((message_t, char *, size_t, size_t *));
int (*_received) __P ((message_t, char *, size_t, size_t *));
int (*_get_uidl) __P ((message_t, char *, size_t, size_t *));
int (*_get_num_parts) __P ((message_t, size_t *));
int (*_get_part) __P ((message_t, size_t, message_t *));
......
......@@ -162,8 +162,8 @@ static int mbox_header_size (header_t, size_t *);
static int mbox_header_lines (header_t, size_t *);
static int mbox_body_size (body_t, size_t *);
static int mbox_body_lines (body_t, size_t *);
static int mbox_msg_from (message_t, char *, size_t, size_t *);
static int mbox_msg_received (message_t, char *, size_t, size_t *);
static int mbox_envelope_from (envelope_t, char *, size_t, size_t *);
static int mbox_envelope_date (envelope_t, char *, size_t, size_t *);
static void mbox_cleanup (void *);
/* We allocate the mbox_data_t struct, but don't do any parsing on the name or
......@@ -981,9 +981,10 @@ mbox_body_lines (body_t body, size_t *plines)
}
static int
mbox_msg_received (message_t msg, char *buf, size_t len,
mbox_envelope_date (envelope_t envelope, char *buf, size_t len,
size_t *pnwrite)
{
message_t msg = envelope_get_owner (envelope);
mbox_message_t mum = message_get_owner (msg);
size_t n = 0;
int status;
......@@ -1026,8 +1027,10 @@ mbox_msg_received (message_t msg, char *buf, size_t len,
}
static int
mbox_msg_from (message_t msg, char *buf, size_t len, size_t *pnwrite)
mbox_envelope_from (envelope_t envelope, char *buf, size_t len,
size_t *pnwrite)
{
message_t msg = envelope_get_owner (envelope);
mbox_message_t mum = message_get_owner (msg);
size_t n = 0;
int status;
......@@ -1158,8 +1161,18 @@ mbox_get_message (mailbox_t mailbox, size_t msgno, message_t *pmsg)
}
/* Set the envelope. */
message_set_from (msg, mbox_msg_from, mum);
message_set_received (msg, mbox_msg_received, mum);
{
envelope_t envelope= NULL;
status = envelope_create (&envelope, msg);
if (status != 0)
{
message_destroy (&msg, mum);
return status;
}
envelope_set_from (envelope, mbox_envelope_from, msg);
envelope_set_date (envelope, mbox_envelope_date, msg);
message_set_envelope (msg, envelope, mum);
}
/* Attach the message to the mailbox mbox data. */
mum->message = msg;
......@@ -1229,7 +1242,9 @@ mbox_append_message (mailbox_t mailbox, message_t msg)
{
char *s;
size_t len = 0;
status = message_from (msg, mud->from, 127, &len);
envelope_t envelope;
message_get_envelope (msg, &envelope);
status = envelope_from (envelope, mud->from, 127, &len);
if (status != 0)
{
if (status != EAGAIN)
......@@ -1255,7 +1270,9 @@ mbox_append_message (mailbox_t mailbox, message_t msg)
{
char *s;
size_t len = 0;
status = message_received (msg, mud->date, 127, &len);
envelope_t envelope;
message_get_envelope (msg, &envelope);
status = envelope_date (envelope, mud->date, 127, &len);
if (status != 0)
{
if (status != EAGAIN)
......
......@@ -352,7 +352,7 @@ mbox_scan0 (mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif)
mum->mud = mud;
mum->header_from = total - n;
mum->header_from_end = total;
mum->body_end = 0;
mum->body_end = mum->body = 0;
lines = 0;
}
else if ((n > 7) && ISSTATUS(buf))
......
......@@ -196,7 +196,7 @@ do \
|| (mpd->id && mpd->id != (size_t)identity)) \
{ \
mpd->id = 0; \
mpd->func = pop_open; \
mpd->func = (void *)pop_open; \
mpd->state = POP_NO_STATE; \
monitor_unlock (mbox->monitor); \
err = pop_open (mbox, mbox->flags); \
......
......@@ -37,18 +37,29 @@ static int message_read (stream_t is, char *buf, size_t buflen,
static int message_write (stream_t os, const char *buf, size_t buflen,
off_t off, size_t *pnwrite);
static int message_get_fd (stream_t stream, int *pfd);
static int message_from (envelope_t envelope, char *buf, size_t len,
size_t *pnwrite);
static int message_date (envelope_t envelope, char *buf, size_t len,
size_t *pnwrite);
/* Allocate ressources for the message_t. */
int
message_create (message_t *pmsg, void *owner)
{
message_t msg;
int status;
if (pmsg == NULL)
return EINVAL;
msg = calloc (1, sizeof (*msg));
if (msg == NULL)
return ENOMEM;
status = monitor_create (&(msg->monitor), msg);
if (status != 0)
{
free (msg);
return status;
}
msg->owner = owner;
msg->ref = 1;
*pmsg = msg;
......@@ -61,11 +72,15 @@ message_destroy (message_t *pmsg, void *owner)
if (pmsg && *pmsg)
{
message_t msg = *pmsg;
monitor_t monitor = msg->monitor;
int destroy_lock = 0;
monitor_wrlock (monitor);
msg->ref--;
if ((msg->owner && msg->owner == owner)
|| (msg->owner == NULL && msg->ref <= 0))
{
destroy_lock = 1;
/* Notify the listeners. */
/* FIXME: to be removed since we do not supoort this event. */
if (msg->observable)
......@@ -74,10 +89,18 @@ message_destroy (message_t *pmsg, void *owner)
observable_destroy (&(msg->observable), msg);
}
/* Envelope. */
if (msg->envelope)
envelope_destroy (&(msg->envelope), msg);
/* Header. */
if (msg->header)
header_destroy (&(msg->header), msg);
/* Body. */
if (msg->body)
body_destroy (&(msg->body), msg);
/* Attribute. */
if (msg->attribute)
attribute_destroy (&(msg->attribute), msg);
......@@ -86,10 +109,6 @@ message_destroy (message_t *pmsg, void *owner)
if (msg->stream)
stream_destroy (&(msg->stream), msg);
/* Body. */
if (msg->body)
body_destroy (&(msg->body), msg);
/* Mime. */
if (msg->mime)
mime_destroy (&(msg->mime));
......@@ -100,6 +119,9 @@ message_destroy (message_t *pmsg, void *owner)
if (msg->ref <= 0)
free (msg);
}
monitor_unlock (monitor);
if (destroy_lock)
monitor_destroy (&monitor, msg);
/* Loose the link */
*pmsg = NULL;
}
......@@ -109,7 +131,11 @@ int
message_ref (message_t msg)
{
if (msg)
msg->ref++;
{
monitor_wrlock (msg->monitor);
msg->ref++;
monitor_unlock (msg->monitor);
}
return 0;
}
......@@ -126,14 +152,19 @@ message_get_header (message_t msg, header_t *phdr)
return EINVAL;
/* Is it a floating mesg */
monitor_wrlock (msg->monitor);
if (msg->header == NULL)
{
header_t header;
int status = header_create (&header, NULL, 0, msg);
if (status != 0)
return status;
{
monitor_unlock (msg->monitor);
return status;
}
msg->header = header;
}
monitor_unlock (msg->monitor);
*phdr = msg->header;
return 0;
}
......@@ -147,8 +178,11 @@ message_set_header (message_t msg, header_t hdr, void *owner)
return EACCES;
/* Make sure we destoy the old if it was own by the mesg */
/* FIXME: I do not know if somebody has already a ref on this ? */
header_destroy (&(msg->header), msg);
monitor_wrlock (msg->monitor);
if (msg->header)
header_destroy (&(msg->header), msg);
msg->header = hdr;
monitor_unlock (msg->monitor);
return 0;
}
......@@ -158,15 +192,20 @@ message_get_body (message_t msg, body_t *pbody)
if (msg == NULL || pbody == NULL)
return EINVAL;
monitor_wrlock (msg->monitor);
/* Is it a floating mesg. */
if (msg->body == NULL)
{
body_t body;
int status = body_create (&body, msg);
if (status != 0)
return status;
{
monitor_unlock (msg->monitor);
return status;
}
msg->body = body;
}
monitor_unlock (msg->monitor);
*pbody = msg->body;
return 0;
}
......@@ -180,8 +219,11 @@ message_set_body (message_t msg, body_t body, void *owner)
return EACCES;
/* Make sure we destoy the old if it was own by the mesg. */
/* FIXME: I do not know if somebody has already a ref on this ? */
body_destroy (&(msg->body), msg);
monitor_wrlock (msg->monitor);
if (msg->body)
body_destroy (&(msg->body), msg);
msg->body = body;
monitor_unlock (msg->monitor);
return 0;
}
......@@ -194,8 +236,11 @@ message_set_stream (message_t msg, stream_t stream, void *owner)
return EACCES;
/* Make sure we destoy the old if it was own by the mesg. */
/* FIXME: I do not know if somebody has already a ref on this ? */
stream_destroy (&(msg->stream), msg);
monitor_wrlock (msg->monitor);
if (msg->stream)
stream_destroy (&(msg->stream), msg);
msg->stream = stream;
monitor_unlock (msg->monitor);
return 0;
}
......@@ -205,19 +250,24 @@ message_get_stream (message_t msg, stream_t *pstream)
if (msg == NULL || pstream == NULL)
return EINVAL;
monitor_wrlock (msg->monitor);
if (msg->stream == NULL)
{
stream_t stream;
int status;
status = stream_create (&stream, MU_STREAM_RDWR, msg);
if (status != 0)
return status;
{
monitor_unlock (msg->monitor);
return status;
}
stream_set_read (stream, message_read, msg);
stream_set_write (stream, message_write, msg);
stream_set_fd (stream, message_get_fd, msg);
stream_set_flags (stream, MU_STREAM_RDWR);
msg->stream = stream;
}
monitor_unlock (msg->monitor);
*pstream = msg->stream;
return 0;
......@@ -290,123 +340,42 @@ message_size (message_t msg, size_t *psize)
}
int
message_set_from (message_t msg,
int (*_from) __P ((message_t, char *, size_t, size_t*)),
void *owner)
{
if (msg == NULL)
return EINVAL;
if (msg->owner != owner)
return EACCES;
msg->_from = _from;
return 0;
}
int
message_from (message_t msg, char *buf, size_t len, size_t *pnwrite)
message_get_envelope (message_t msg, envelope_t *penvelope)
{
header_t header = NULL;
size_t n = 0;
int status;
if (msg == NULL)
if (msg == NULL || penvelope == NULL)
return EINVAL;
/* Did they provide a way to get it ? */
if (msg->_from)
return msg->_from (msg, buf, len, pnwrite);
/* Can it be extracted from the From: */
message_get_header (msg, &header);
status = header_get_value (header, MU_HEADER_FROM, NULL, 0, &n);
if (status == 0 && n != 0)
monitor_wrlock (msg->monitor);
if (msg->envelope == NULL)
{
char *from;
char *addr;
from = calloc (1, n + 1);
if (from == NULL)
return ENOMEM;
addr = calloc (1, n + 1);
if (addr == NULL)
{
free (from);
return ENOMEM;
}
header_get_value (header, MU_HEADER_FROM, from, n + 1, NULL);
if (parseaddr (from, addr, n + 1) == 0)
envelope_t envelope;
int status = envelope_create (&envelope, msg);
if (status != 0)
{
size_t i = strlen (addr);
n = (i > len) ? len : i;
if (buf && len > 0)
{
memcpy (buf, addr, n);
buf[n] = '\0';
}
free (addr);
free (from);
if (pnwrite)
*pnwrite = n;
return 0;
monitor_unlock (msg->monitor);
return status;
}
envelope_set_from (envelope, message_from, msg);
envelope_set_date (envelope, message_date, msg);
msg->envelope = envelope;
}
else if (status == EAGAIN)
return status;
/* oops */
n = (7 > len) ? len: 7;
if (buf && len > 0)
{
memcpy (buf, "unknown", n);
buf [n] = '\0';
}
if (pnwrite)
*pnwrite = n;
monitor_unlock (msg->monitor);
*penvelope = msg->envelope;
return 0;
}
int
message_set_received (message_t msg, int (*_received)
__P ((message_t, char *, size_t , size_t *)),
void *owner)
message_set_envelope (message_t msg, envelope_t envelope, void *owner)
{
if (msg == NULL)
return EINVAL;
if (msg->owner != owner)
return EACCES;
msg->_received = _received;
return 0;
}
int
message_received (message_t msg, char *buf, size_t len, size_t *pnwrite)
{
time_t t;
size_t n;
if (msg == NULL)
return EINVAL;
/* Is it provided ? */
if (msg->_received)
return msg->_received (msg, buf, len, pnwrite);
/* FIXME: extract the time from "Date:". */
/* Catch all. */
/* FIXME: ctime() is not thread safe use strftime(). */
t = time (NULL);
n = strlen (ctime (&t));
if (buf == NULL || len == 0)
{
if (pnwrite)
*pnwrite = n;
return 0;
}
n = (n > len) ? len : n;
strncpy (buf, ctime (&t), n);
buf [n] = '\0';
if (pnwrite)
*pnwrite = n;
monitor_wrlock (msg->monitor);
if (msg->envelope)
envelope_destroy (&(msg->envelope), msg);
msg->envelope = envelope;
monitor_unlock (msg->monitor);
return 0;
}
......@@ -415,14 +384,19 @@ message_get_attribute (message_t msg, attribute_t *pattribute)
{
if (msg == NULL || pattribute == NULL)
return EINVAL;
monitor_wrlock (msg->monitor);
if (msg->attribute == NULL)
{
attribute_t attribute;
int status = attribute_create (&attribute, msg);
if (status != 0)
return status;
{
monitor_unlock (msg->monitor);
return status;
}
msg->attribute = attribute;
}
monitor_unlock (msg->monitor);
*pattribute = msg->attribute;
return 0;
}
......@@ -434,8 +408,11 @@ message_set_attribute (message_t msg, attribute_t attribute, void *owner)
return EINVAL;
if (msg->owner != owner)
return EACCES;
attribute_destroy (&(msg->attribute), owner);
monitor_wrlock (msg->monitor);
if (msg->attribute)
attribute_destroy (&(msg->attribute), owner);
msg->attribute = attribute;
monitor_unlock (msg->monitor);
return 0;
}
......@@ -540,12 +517,17 @@ message_get_num_parts (message_t msg, size_t *pparts)
if (msg->_get_num_parts)
return msg->_get_num_parts (msg, pparts);
monitor_wrlock (msg->monitor);
if (msg->mime == NULL)
{
int status = mime_create (&(msg->mime), msg, 0);
if (status != 0)
return status;
{
monitor_unlock (msg->monitor);
return status;
}
}
monitor_unlock (msg->monitor);
return mime_get_num_parts (msg->mime, pparts);
}
......@@ -571,12 +553,17 @@ message_get_part (message_t msg, size_t part, message_t *pmsg)
if (msg->_get_part)
return msg->_get_part (msg, part, pmsg);
monitor_wrlock (msg->monitor);
if (msg->mime == NULL)
{
int status = mime_create (&(msg->mime), msg, 0);
if (status != 0)
return status;
{
monitor_unlock (msg->monitor);
return status;
}
}
monitor_unlock (msg->monitor);
return mime_get_part (msg->mime, part, pmsg);
}
......@@ -599,12 +586,17 @@ message_get_observable (message_t msg, observable_t *pobservable)
if (msg == NULL || pobservable == NULL)
return EINVAL;
monitor_wrlock (msg->monitor);
if (msg->observable == NULL)
{
int status = observable_create (&(msg->observable), msg);
if (status != 0)
return status;
{
monitor_unlock (msg->monitor);
return status;
}
}
monitor_unlock (msg->monitor);
*pobservable = msg->observable;
return 0;
}
......@@ -665,6 +657,7 @@ message_write (stream_t os, const char *buf, size_t buflen,
return 0;
}
monitor_wrlock (msg->monitor);
if (!msg->hdr_done)
{
size_t len;
......@@ -680,6 +673,7 @@ message_write (stream_t os, const char *buf, size_t buflen,
free (msg->hdr_buf);
msg->hdr_buf = NULL;
msg->hdr_buflen = 0;
monitor_unlock (msg->monitor);
return ENOMEM;
}
else
......@@ -698,6 +692,7 @@ message_write (stream_t os, const char *buf, size_t buflen,
if (status != 0)
{
msg->hdr_buflen = 0;
monitor_unlock (msg->monitor);
return status;
}
msg->hdr_done = 1;
......@@ -706,16 +701,19 @@ message_write (stream_t os, const char *buf, size_t buflen,
buflen -= len;
}
}
monitor_unlock (msg->monitor);
/* Message header is not complete but was not a full line. */
if (!msg->hdr_done && buflen > 0)
{
char *thdr = realloc (msg->hdr_buf, msg->hdr_buflen + buflen);
monitor_wrlock (msg->monitor);
if (thdr == NULL)
{
free (msg->hdr_buf);
msg->hdr_buf = NULL;
msg->hdr_buflen = 0;
monitor_unlock (msg->monitor);
return ENOMEM;
}
else
......@@ -723,6 +721,7 @@ message_write (stream_t os, const char *buf, size_t buflen,
memcpy (msg->hdr_buf + msg->hdr_buflen, buf, buflen);
msg->hdr_buflen += buflen;
buflen = 0;
monitor_unlock (msg->monitor);
}
else if (buflen > 0) /* In the body. */
{
......@@ -759,18 +758,115 @@ message_get_fd (stream_t stream, int *pfd)
if (msg == NULL)
return EINVAL;
monitor_wrlock (msg->monitor);
/* Probably being lazy, then create a body for the stream. */
if (msg->body == NULL)
{
int status = body_create (&body, msg);
if (status != 0 )
return status;
{
monitor_unlock (msg->monitor);
return status;
}
msg->body = body;
}
else
body = msg->body;
monitor_unlock (msg->monitor);
body_get_stream (body, &is);
return stream_get_fd (is, pfd);
}
static int
message_date (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
{
message_t msg = envelope_get_owner (envelope);
time_t t;
size_t n;
if (msg == NULL)
return EINVAL;
/* FIXME: extract the time from "Date:". */
/* Catch all. */
/* FIXME: ctime() is not thread safe use strftime(). */
t = time (NULL);
n = strlen (ctime (&t));
if (buf == NULL || len == 0)
{
if (pnwrite)
*pnwrite = n;
return 0;
}
n = (n > len) ? len : n;
strncpy (buf, ctime (&t), n);
buf [n] = '\0';
if (pnwrite)
*pnwrite = n;
return 0;
}
static int
message_from (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
{
message_t msg = envelope_get_owner (envelope);
header_t header = NULL;
size_t n = 0;
int status;
if (msg == NULL)
return EINVAL;
/* Can it be extracted from the From: */
message_get_header (msg, &header);
status = header_get_value (header, MU_HEADER_FROM, NULL, 0, &n);
if (status == 0 && n != 0)
{
char *from;
char *addr;
from = calloc (1, n + 1);
if (from == NULL)
return ENOMEM;
addr = calloc (1, n + 1);
if (addr == NULL)
{
free (from);
return ENOMEM;
}
header_get_value (header, MU_HEADER_FROM, from, n + 1, NULL);
if (parseaddr (from, addr, n + 1) == 0)
{
size_t i = strlen (addr);
n = (i > len) ? len : i;
if (buf && len > 0)
{
memcpy (buf, addr, n);
buf[n] = '\0';
}
free (addr);
free (from);
if (pnwrite)
*pnwrite = n;
return 0;
}
free (addr);
free (from);
}
else if (status == EAGAIN)
return status;
/* oops */
n = (7 > len) ? len: 7;
if (buf && len > 0)
{
memcpy (buf, "unknown", n);
buf [n] = '\0';
}
if (pnwrite)
*pnwrite = n;
return 0;
}
......
......@@ -21,8 +21,8 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <time.h>
#include <unistd.h>
#include <mailutils/message.h>
#include <mailutils/stream.h>
......@@ -217,7 +217,7 @@ static void _mime_append_header_line(mime_t mime)
static int _mime_parse_mpart_message(mime_t mime)
{
char *cp, *cp2;
int blength, body_length, body_offset, body_lines, ret;
int blength, mb_length, mb_offset, mb_lines, ret;
size_t nbytes;
if ( !(mime->flags & MIME_PARSER_ACTIVE) ) {
......@@ -237,9 +237,9 @@ static int _mime_parse_mpart_message(mime_t mime)
mime->parser_state = MIME_STATE_SCAN_BOUNDARY;
mime->flags |= MIME_PARSER_ACTIVE;
}
body_length = mime->body_length;
body_offset = mime->body_offset;
body_lines = mime->body_lines;
mb_length = mime->body_length;
mb_offset = mime->body_offset;
mb_lines = mime->body_lines;
while ( ( ret = stream_read(mime->stream, mime->cur_buf, mime->buf_size, mime->cur_offset, &nbytes) ) == 0 && nbytes ) {
cp = mime->cur_buf;
......@@ -256,15 +256,15 @@ static int _mime_parse_mpart_message(mime_t mime)
cp2 = mime->cur_line[0] == '\n' ? mime->cur_line + 1 : mime->cur_line;
blength = strlen(mime->boundary);
if ( mime->header_length )
body_lines++;
mb_lines++;
if ( mime->line_ndx >= blength ) {
if ( ( !strncasecmp(cp2,"--", 2) && !strncasecmp(cp2+2, mime->boundary, blength) )
|| !strncasecmp(cp2, mime->boundary, blength) ) {
mime->parser_state = MIME_STATE_HEADERS;
mime->flags &= ~MIME_PARSER_HAVE_CR;
body_length = mime->cur_offset - body_offset - mime->line_ndx + 1;
mb_length = mime->cur_offset - mb_offset - mime->line_ndx + 1;
if ( mime->header_length ) /* this skips the preamble */
_mime_append_part(mime, NULL, body_offset, body_length, body_lines);
_mime_append_part(mime, NULL, mb_offset, mb_length, mb_lines);
if ( ( cp2 + blength + 2 < cp && !strncasecmp(cp2+2+blength, "--",2) ) ||
!strncasecmp(cp2+blength, "--",2) ) { /* very last boundary */
mime->parser_state = MIME_STATE_BEGIN_LINE;
......@@ -283,8 +283,8 @@ static int _mime_parse_mpart_message(mime_t mime)
_mime_append_header_line(mime);
if ( mime->line_ndx == 1 || mime->cur_line[0] == '\r' ) {
mime->parser_state = MIME_STATE_BEGIN_LINE;
body_offset = mime->cur_offset + 1;
body_lines = 0;
mb_offset = mime->cur_offset + 1;
mb_lines = 0;
}
mime->line_ndx = -1;
break;
......@@ -300,12 +300,12 @@ static int _mime_parse_mpart_message(mime_t mime)
cp++;
}
}
mime->body_lines = body_lines;
mime->body_length = body_length;
mime->body_offset = body_offset;
mime->body_lines = mb_lines;
mime->body_length = mb_length;
mime->body_offset = mb_offset;
if ( ret != EAGAIN ) { /* finished cleanup */
if ( mime->header_length ) /* this skips the preamble */
_mime_append_part(mime, NULL, body_offset, body_length, body_lines);
_mime_append_part(mime, NULL, mb_offset, mb_length, mb_lines);
mime->flags &= ~MIME_PARSER_ACTIVE;
mime->body_offset = mime->body_length = mime->header_length = mime->body_lines = 0;
}
......@@ -373,7 +373,7 @@ static int _mime_set_content_type(mime_t mime)
char boundary[128];
header_t hdr = NULL;
size_t size;
if ( mime->nmtp_parts > 1 ) {
if ( mime->flags & MIME_ADDED_MULTIPART_CT )
return 0;
......@@ -382,7 +382,7 @@ static int _mime_set_content_type(mime_t mime)
else
strcpy(content_type, "multipart/alternative; boundary=");
if ( mime->boundary == NULL ) {
sprintf (boundary,"%ld-%ld=:%ld",random (),time (0), getpid ());
sprintf (boundary,"%ld-%ld=:%ld",(long)random (), (long)time (0), (long)getpid ());
if ( ( mime->boundary = strdup(boundary) ) == NULL )
return ENOMEM;
}
......@@ -455,7 +455,7 @@ static int _mime_body_read(stream_t stream, char *buf, size_t buflen, off_t off,
}
while(mime->postamble) {
mime->postamble--;
ADD_CHAR(buf, '-', mime->cur_offset, buflen, *nbytes);
ADD_CHAR(buf, '-', mime->cur_offset, buflen, *nbytes);
}
mime->flags &= ~(MIME_INSERT_BOUNDARY|MIME_ADDING_BOUNDARY);
mime->part_offset = 0;
......@@ -465,9 +465,12 @@ static int _mime_body_read(stream_t stream, char *buf, size_t buflen, off_t off,
return 0;
message_get_stream(mime->mtp_parts[mime->cur_part]->msg, &msg_stream);
} else {
body_t b;
message_get_body(mime->mtp_parts[mime->cur_part]->msg, &b);
body_get_stream(b, &msg_stream);
body_t part_body;
if ( mime->cur_part >= mime->nmtp_parts )
return 0;
message_get_body(mime->mtp_parts[mime->cur_part]->msg, &part_body);
body_get_stream(part_body, &msg_stream);
}
ret = stream_read(msg_stream, buf, buflen, mime->part_offset, &part_nbytes );
len += part_nbytes;
......@@ -475,11 +478,11 @@ static int _mime_body_read(stream_t stream, char *buf, size_t buflen, off_t off,
if ( nbytes )
*nbytes += len;
mime->cur_offset += len;
if ( ret == 0 && part_nbytes == 0 && mime->nmtp_parts > 1 ) {
if ( ret == 0 && part_nbytes == 0 ) {
mime->flags |= MIME_INSERT_BOUNDARY;
mime->cur_part++;
}
} while( ret == 0 && part_nbytes == 0 && mime->cur_part < mime->nmtp_parts );
} while( ret == 0 && part_nbytes == 0 && mime->cur_part <= mime->nmtp_parts );
}
return ret;
}
......@@ -675,7 +678,7 @@ int mime_get_num_parts(mime_t mime, int *nmtp_parts)
int mime_add_part(mime_t mime, message_t msg)
{
int ret;
if ( mime == NULL || msg == NULL || ( mime->flags & MIME_NEW_MESSAGE ) == 0 )
return EINVAL;
if ( ( ret = _mime_append_part(mime, msg, 0, 0, 0) ) == 0 )
......
......@@ -140,6 +140,7 @@ parseaddr (const char *addr, char *buf, size_t bufsz)
struct token *t, *tok, *last;
struct token *brace = NULL;
int comment = 0;
int status = 0;
tok = last = NULL;
......@@ -171,7 +172,10 @@ parseaddr (const char *addr, char *buf, size_t bufsz)
for (; t && t->word[0] != ',' && t->word[0] != '>'; t = t->next)
{
if (strlen (t->word) >= bufsz)
return -1;
{
status = -1;
break;
}
bufsz -= strlen (t->word);
strcat (buf, t->word);
}
......@@ -183,5 +187,5 @@ parseaddr (const char *addr, char *buf, size_t bufsz)
free (t);
}
return 0;
return status;
}
......
......@@ -33,7 +33,6 @@
#include <mailer0.h>
#include <registrar0.h>
#include <bio.h>
#include <misc.h>
static int smtp_init (mailer_t);
......