Commit d9a9b601 d9a9b601ddbfa36443aa6482c892c5587986dbff by Alain Magloire

attribute.c auth.c header.c io.c locker.c mailbox.c mbx_imap.c

 	mbx_mbox.c mbx_mdir.c mbx_mh.c mbx_mmdf.c mbx_pop.c mbx_unix.c
 	message.c mime.c registrar.c url.c url_file.c url_imap.c
 	url_mail.c url_mbox.c url_mdir.c url_mh.c url_mmdf.c url_pop.c
 	url_unix.c include/private/mailbox0.h
 	include/private/mbx_imap.h include/private/mbx_mbox.h
 	include/private/mbx_mdir.h include/private/mbx_mmdf.h
 	include/private/mbx_pop.h include/private/mbx_unix.h
 	include/private/message0.h include/private/mime0.h
 	include/private/url0.h include/public/attribute.h
 	include/public/auth.h include/public/event.h
 	include/public/header.h include/public/io.h
 	include/public/locker.h include/public/mailbox.h
 	include/public/message.h include/public/mime.h
 	include/public/registrar.h include/public/transcode.h
 	include/public/url.h

changed all the *_init to *_create().
added *_lines() functions
optimisation of the parsing.
1 parent edadcf90
......@@ -15,29 +15,15 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <attribute.h>
#include <attribute0.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define MU_ATTRIBUTE_SEEN ((int)1)
#define MU_ATTRIBUTE_ANSWERED (MU_ATTRIBUTE_SEEN << 1)
#define MU_ATTRIBUTE_FLAGGED (MU_ATTRIBUTE_ANSWERED << 1)
#define MU_ATTRIBUTE_DELETED (MU_ATTRIBUTE_FLAGGED << 1)
#define MU_ATTRIBUTE_DRAFT (MU_ATTRIBUTE_DELETED << 1)
#define MU_ATTRIBUTE_RECENT (MU_ATTRIBUTE_DRAFT << 1)
#define MU_ATTRIBUTE_READ (MU_ATTRIBUTE_RECENT << 1)
struct _attribute
{
size_t flag;
void *owner;
};
int
attribute_init (attribute_t *pattr, void *owner)
attribute_create (attribute_t *pattr, void *owner)
{
attribute_t attr;
if (pattr == NULL || owner == NULL)
......@@ -274,7 +260,7 @@ string_to_attribute (const char *buffer, size_t len,
char *sep;
int status;
status = attribute_init (pattr, owner);
status = attribute_create (pattr, owner);
if (status != 0)
return status;
......
......@@ -32,7 +32,7 @@ struct _auth
};
int
auth_init (auth_t *pauth, void *owner)
auth_create (auth_t *pauth, void *owner)
{
auth_t auth;
if (pauth == NULL)
......
......@@ -57,7 +57,7 @@ struct _header
};
int
header_init (header_t *ph, const char *blurb, size_t len, void *owner)
header_create (header_t *ph, const char *blurb, size_t len, void *owner)
{
header_t h;
int status;
......@@ -66,14 +66,9 @@ header_init (header_t *ph, const char *blurb, size_t len, void *owner)
return ENOMEM;
h->owner = owner;
status = header_parse (h, (char *)blurb, len);
if (status != 0)
{
free (h);
return status;
}
header_parse (h, (char *)blurb, len);
status = stream_init (&(h->stream), h);
status = stream_create (&(h->stream), h);
if (status != 0)
return status;
......@@ -132,7 +127,7 @@ header_parse (header_t header, char *blurb, int len)
return 0;
header->blurb_len = len;
header->blurb = calloc (1, header->blurb_len);
header->blurb = calloc (1, header->blurb_len + 1);
if (header->blurb == NULL)
return ENOMEM;
memcpy (header->blurb, blurb, header->blurb_len);
......@@ -214,6 +209,7 @@ header_parse (header_t header, char *blurb, int len)
header->hdr_count++;
} /* for (header_start ...) */
#if 0
header->blurb_len -= len;
if (header->blurb_len <= 0)
{
......@@ -221,6 +217,10 @@ header_parse (header_t header, char *blurb, int len)
free (header->hdr);
return EINVAL;
}
/* always add the separtor LF */
header->blurb [header->blurb_len] = '\n';
header->blurb_len++;
#endif
return 0;
}
......@@ -305,7 +305,24 @@ header_entry_count (header_t header, size_t *pnum)
}
int
header_get_size (header_t header, size_t *pnum)
header_lines (header_t header, size_t *plines)
{
int n;
size_t t = 0;
if (header == NULL)
return EINVAL;
for (n = header->blurb_len - 1; n >= 0; n--)
{
if (header->blurb[n] == '\n')
t++;
}
if (plines)
*plines = t;
return 0;
}
int
header_size (header_t header, size_t *pnum)
{
if (header == NULL)
return EINVAL;
......
......@@ -42,6 +42,7 @@ struct _mailbox
char *name;
auth_t auth;
locker_t locker;
netinstance_t netinstance;
url_t url;
/* register events */
......@@ -53,7 +54,7 @@ struct _mailbox
/* Public methods */
int (*_init) __P ((mailbox_t *, const char *));
int (*_create) __P ((mailbox_t *, const char *));
void (*_destroy) __P ((mailbox_t *));
int (*_open) __P ((mailbox_t, int flag));
......@@ -75,19 +76,8 @@ struct _mailbox
};
/* private */
extern int mailbox_delete __P ((mailbox_t, size_t msgno));
extern int mailbox_undelete __P ((mailbox_t, size_t msgno));
extern int mailbox_is_deleted __P ((mailbox_t, size_t msgno));
extern int mailbox_num_deleted __P ((mailbox_t, size_t *));
extern int mailbox_get_auth __P ((mailbox_t mbox, auth_t *auth));
extern int mailbox_set_auth __P ((mailbox_t mbox, auth_t auth));
extern int mailbox_get_locker __P ((mailbox_t mbox, locker_t *locker));
extern int mailbox_set_locker __P ((mailbox_t mbox, locker_t locker));
extern int mailbox_get_attribute __P ((mailbox_t mbox, size_t msgno,
attribute_t *attr));
extern int mailbox_set_attribute __P ((mailbox_t mbox, size_t msgno,
attribute_t attr));
extern int mailbox_notification __P ((mailbox_t mbox, size_t type));
......
......@@ -20,7 +20,7 @@
#include <mailbox0.h>
extern int mailbox_imap_init __P ((mailbox_t *mbox, const char *name));
extern int mailbox_imap_create __P ((mailbox_t *mbox, const char *name));
extern void mailbox_imap_destroy __P ((mailbox_t *mbox));
extern struct mailbox_type _mailbox_imap_type;
......
......@@ -20,7 +20,7 @@
#include <mailbox.h>
extern int mailbox_mbox_init __P ((mailbox_t *mbox, const char *name));
extern int mailbox_mbox_create __P ((mailbox_t *mbox, const char *name));
extern void mailbox_mbox_destroy __P ((mailbox_t *mbox));
extern struct mailbox_type _mailbox_mbox_type;
......
......@@ -20,7 +20,7 @@
#include <mailbox0.h>
extern int mailbox_maildir_init __P ((mailbox_t *mbox, const char *name));
extern int mailbox_maildir_create __P ((mailbox_t *mbox, const char *name));
extern void mailbox_maildir_destroy __P ((mailbox_t *mbox));
extern struct mailbox_type _mailbox_maildir_type;
......
......@@ -20,7 +20,7 @@
#include <mailbox0.h>
extern int mailbox_mmdf_init __P ((mailbox_t *mbox, const char *name));
extern int mailbox_mmdf_create __P ((mailbox_t *mbox, const char *name));
extern void mailbox_mmdf_destroy __P ((mailbox_t *mbox));
extern struct mailbox_type _mailbox_mmdf_type;
......
......@@ -20,7 +20,7 @@
#include <mailbox0.h>
extern int mailbox_pop_init __P ((mailbox_t *mbox, const char *name));
extern int mailbox_pop_create __P ((mailbox_t *mbox, const char *name));
extern void mailbox_pop_destroy __P ((mailbox_t *mbox));
extern struct mailbox_type _mailbox_pop_type;
......
......@@ -24,7 +24,7 @@
extern "C" {
#endif
extern int mailbox_unix_init __P ((mailbox_t *mbox, const char *name));
extern int mailbox_unix_create __P ((mailbox_t *mbox, const char *name));
extern void mailbox_unix_destroy __P ((mailbox_t *mbox));
extern struct mailbox_type _mailbox_unix_type;
......
......@@ -39,20 +39,6 @@ extern "C" {
# endif
#endif /*__P */
/* The notion of body_t is not exported outside,
* there was no need for yet another object.
* since only floating messages need them. The functions
* that manipulate those objects are static to message.c
*
*/
struct _body
{
FILE *file;
void *owner;
};
typedef struct _body * body_t;
/* forward declaration */
struct _message
{
......@@ -79,9 +65,9 @@ struct _message
int (*_get_stream) __P ((message_t msg, stream_t *));
int (*_set_stream) __P ((message_t msg, stream_t, void *owner));
int (*_size) __P ((message_t msg, size_t *size));
int (*_from) __P ((message_t msg, char *, size_t, size_t *));
int (*_received) __P ((message_t msg, char *, size_t, size_t *));
int (*_clone) __P ((message_t msg, message_t *cmsg));
};
#ifdef _cplusplus
......
......@@ -81,6 +81,7 @@ struct _mime
struct _mime_part
{
char sig[4];
mime_t mime;
header_t hdr;
message_t msg;
......
......@@ -47,7 +47,7 @@ struct _url
void *data;
int (*_init) __P ((url_t *url, const char *name));
int (*_create) __P ((url_t *url, const char *name));
void (*_destroy) __P ((url_t *url));
/* Methods */
......
......@@ -35,7 +35,7 @@ extern "C" {
struct _attribute;
typedef struct _attribute * attribute_t;
extern int attribute_init __P ((attribute_t *, void *owner));
extern int attribute_create __P ((attribute_t *, void *owner));
extern void attribute_destroy __P ((attribute_t *, void *owner));
extern int attribute_is_seen __P ((attribute_t));
......
......@@ -36,7 +36,7 @@ extern "C" {
struct _auth;
typedef struct _auth *auth_t;
extern int auth_init __P ((auth_t *, void *owner));
extern int auth_create __P ((auth_t *, void *owner));
extern void auth_destroy __P ((auth_t *, void *owner));
extern int auth_prologue __P ((auth_t));
......
......@@ -67,7 +67,7 @@ extern "C" {
struct _header;
typedef struct _header * header_t;
extern int header_init __P ((header_t *, const char *blurb,
extern int header_create __P ((header_t *, const char *blurb,
size_t ln, void *owner));
extern void header_destroy __P ((header_t *, void *owner));
......@@ -81,7 +81,8 @@ extern int header_entry_name __P ((header_t, size_t num, char *buf,
extern int header_entry_value __P ((header_t, size_t num, char *buf,
size_t buflen, size_t *total));
extern int header_get_stream __P ((header_t, stream_t *stream));
extern int header_get_size __P ((header_t, size_t *size));
extern int header_size __P ((header_t, size_t *size));
extern int header_lines __P ((header_t, size_t *lines));
#ifdef _cplusplus
}
......
......@@ -35,7 +35,7 @@ extern "C" { /*}*/
struct _stream;
typedef struct _stream *stream_t;
extern int stream_init __P ((stream_t *, void *owner));
extern int stream_create __P ((stream_t *, void *owner));
extern void stream_destroy __P ((stream_t *, void *owner));
extern int stream_set_fd __P ((stream_t,
......
......@@ -35,7 +35,7 @@ extern "C" {
struct _locker;
typedef struct _locker *locker_t;
extern int locker_init __P ((locker_t *, char *filename,
extern int locker_create __P ((locker_t *, char *filename,
size_t len, int flags));
extern void locker_destroy __P ((locker_t *));
......
......@@ -18,13 +18,14 @@
#ifndef _MAILBOX_H
# define _MAILBOX_H
#include <sys/types.h>
#include <url.h>
#include <message.h>
#include <attribute.h>
#include <auth.h>
#include <locker.h>
#include <net.h>
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
......@@ -43,7 +44,7 @@ struct _mailbox;
typedef struct _mailbox *mailbox_t;
/* constructor/destructor and possible types */
extern int mailbox_init __P ((mailbox_t *, const char *, int id));
extern int mailbox_create __P ((mailbox_t *, const char *, int id));
extern void mailbox_destroy __P ((mailbox_t *));
/* flags for mailbox_open () */
......@@ -63,6 +64,10 @@ extern int mailbox_append_message __P ((mailbox_t, message_t msg));
extern int mailbox_messages_count __P ((mailbox_t, size_t *num));
extern int mailbox_expunge __P ((mailbox_t));
/* netinstance settings */
extern int mailbox_get_netinstance __P ((mailbox_t, netinstance_t *net));
extern int mailbox_set_netinstance __P ((mailbox_t, netinstance_t net));
/* Lock settings */
extern int mailbox_get_locker __P ((mailbox_t, locker_t *locker));
extern int mailbox_set_locker __P ((mailbox_t, locker_t locker));
......
......@@ -19,6 +19,7 @@
#define _MESSAGE_H
#include <header.h>
#include <body.h>
#include <attribute.h>
#include <io.h>
......@@ -48,24 +49,38 @@ typedef struct _message *message_t;
* was enough.
*/
extern int message_init __P ((message_t *, void *owner));
extern int message_create __P ((message_t *, void *owner));
extern void message_destroy __P ((message_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));
extern int message_get_body __P ((message_t, body_t *));
extern int message_set_body __P ((message_t, body_t, void *owner));
extern int message_get_stream __P ((message_t, stream_t *));
extern int message_set_stream __P ((message_t, stream_t, void *owner));
extern int message_is_multipart __P ((message_t));
extern int message_get_size __P ((message_t, size_t *));
extern int message_set_size __P ((message_t, size_t, void *owner));
extern int message_size __P ((message_t, size_t *));
extern int message_lines __P ((message_t, size_t *));
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_attribute __P ((message_t, attribute_t *));
extern int message_set_attribute __P ((message_t, attribute_t, void *owner));
extern int message_clone __P ((message_t));
//extern int message_clone __P ((message_t));
/* events */
#define MU_EVT_MSG_DESTROY 32
......
......@@ -41,7 +41,7 @@ extern "C" {
struct _mime;
typedef struct _mime *mime_t;
int mime_init __P ((mime_t *pmime, message_t msg, int flags));
int mime_create __P ((mime_t *pmime, message_t msg, int flags));
void mime_destroy __P ((mime_t *pmime));
int mime_is_multi_part __P ((mime_t mime));
int mime_get_part __P ((mime_t mime, int part, message_t *msg));
......
......@@ -38,14 +38,14 @@ extern "C" {
struct url_registrar
{
const char *scheme;
int (*_init) __P ((url_t *, const char * name));
int (*_create) __P ((url_t *, const char * name));
void (*_destroy) __P ((url_t *));
};
struct mailbox_registrar
{
const char *name;
int (*_init) __P ((mailbox_t *, const char *name));
int (*_create) __P ((mailbox_t *, const char *name));
void (*_destroy) __P ((mailbox_t *));
};
......
......@@ -44,7 +44,7 @@ struct _transcoder
void *tcdata;
};
extern int transcode_init __P ((transcoder_t *, char *encoding));
extern int transcode_create __P ((transcoder_t *, char *encoding));
extern void transcode_destroy __P ((transcoder_t *));
extern int transcode_get_stream __P ((transcoder_t tc, stream_t *pis));
extern int transcode_set_stream __P ((transcoder_t tc, stream_t is));
......
......@@ -36,7 +36,7 @@ extern "C" {
struct _url;
typedef struct _url * url_t;
extern int url_init __P ((url_t *, const char *name));
extern int url_create __P ((url_t *, const char *name));
extern void url_destroy __P ((url_t *));
extern int url_get_id __P ((const url_t, int *id));
......
......@@ -22,7 +22,7 @@
#include <stdio.h>
int
stream_init (stream_t *pstream, void *owner)
stream_create (stream_t *pstream, void *owner)
{
stream_t stream;
if (pstream == NULL || owner == NULL)
......
......@@ -45,7 +45,7 @@ struct _locker
};
int
locker_init (locker_t *plocker, char *filename, size_t len, int flags)
locker_create (locker_t *plocker, char *filename, size_t len, int flags)
{
locker_t l;
......
......@@ -23,6 +23,7 @@
#include <message0.h>
#include <registrar.h>
#include <locker.h>
#include <net.h>
#include <stdlib.h>
#include <string.h>
......@@ -32,23 +33,23 @@
* Point of entry.
* Simple, first check if they ask for something specific; with the ID.
* Then try to discover the type of mailbox with the url(name).
* Then we call the appropriate mailbox_*type*_init() function.
* Then we call the appropriate mailbox_*type*_create() function.
*/
int
mailbox_init (mailbox_t *pmbox, const char *name, int id)
mailbox_create (mailbox_t *pmbox, const char *name, int id)
{
int status = EINVAL;
struct mailbox_registrar *mreg;
url_t url = NULL;
url_init (&url, name);
url_create (&url, name);
/* 1st guest: if an ID is specify, shortcut */
if (id)
{
status = registrar_get (id, NULL, &mreg);
if (status == 0)
status = mreg->_init (pmbox, name);
status = mreg->_create (pmbox, name);
}
/* 2nd fallback: Use the URL */
else if (url != NULL)
......@@ -56,7 +57,7 @@ mailbox_init (mailbox_t *pmbox, const char *name, int id)
url_get_id (url, &id);
status = registrar_get (id, NULL, &mreg);
if (status == 0)
status = mreg->_init (pmbox, name);
status = mreg->_create (pmbox, name);
}
/* set the URL */
......@@ -189,6 +190,24 @@ mailbox_get_auth (mailbox_t mbox, auth_t *pauth)
}
int
mailbox_set_netinstance (mailbox_t mbox, netinstance_t netinstance)
{
if (mbox == NULL)
return EINVAL;
mbox->netinstance = netinstance;
return 0;
}
int
mailbox_get_netinstance (mailbox_t mbox, netinstance_t *pnetinstance)
{
if (mbox == NULL || pnetinstance == NULL)
return EINVAL;
*pnetinstance = mbox->netinstance;
return 0;
}
int
mailbox_register (mailbox_t mbox, size_t type,
int (*action) (size_t type, void *arg),
void *arg)
......
......@@ -20,13 +20,13 @@
#include <errno.h>
static int mailbox_imap_init (mailbox_t *mbox, const char *name);
static int mailbox_imap_create (mailbox_t *mbox, const char *name);
static void mailbox_imap_destroy (mailbox_t *mbox);
struct mailbox_registrar _mailbox_imap_registrar =
{
"IMAP4",
mailbox_imap_init, mailbox_imap_destroy
mailbox_imap_create, mailbox_imap_destroy
};
void
......@@ -37,7 +37,7 @@ mailbox_imap_destroy (mailbox_t *mbox)
}
int
mailbox_imap_init (mailbox_t *mbox, const char *name)
mailbox_imap_create (mailbox_t *mbox, const char *name)
{
(void)mbox; (void)name;
return ENOSYS;
......
......@@ -22,13 +22,13 @@
#include <errno.h>
#include <sys/stat.h>
static int mailbox_mbox_init (mailbox_t *mbox, const char *name);
static int mailbox_mbox_create (mailbox_t *mbox, const char *name);
static void mailbox_mbox_destroy (mailbox_t *mbox);
struct mailbox_registrar _mailbox_mbox_registrar =
{
"UNIX_MBOX/Maildir/MMDF",
mailbox_mbox_init, mailbox_mbox_destroy
mailbox_mbox_create, mailbox_mbox_destroy
};
/*
......@@ -45,7 +45,7 @@ struct mailbox_registrar _mailbox_mbox_registrar =
*/
static int
mailbox_mbox_init (mailbox_t *mbox, const char *name)
mailbox_mbox_create (mailbox_t *mbox, const char *name)
{
struct stat st;
size_t len;
......@@ -69,7 +69,7 @@ mailbox_mbox_init (mailbox_t *mbox, const char *name)
* For the default is unix if the file does not exist.
*/
if (stat (name, &st) < 0)
return _mailbox_unix_registrar._init (mbox, name);
return _mailbox_unix_registrar._create (mbox, name);
if (S_ISREG (st.st_mode))
{
......@@ -101,7 +101,7 @@ mailbox_mbox_init (mailbox_t *mbox, const char *name)
if (count == 0) /*empty file*/
{
close (fd);
return _mailbox_unix_registrar._init (mbox, name);
return _mailbox_unix_registrar._create (mbox, name);
}
if (count >= 5)
......@@ -110,18 +110,18 @@ mailbox_mbox_init (mailbox_t *mbox, const char *name)
{
/* This is a Unix Mbox */
close (fd);
return _mailbox_unix_registrar._init (mbox, name);
return _mailbox_unix_registrar._create (mbox, name);
}
}
/* Try MMDF */
close (fd);
#endif
return _mailbox_unix_registrar._init (mbox, name);
return _mailbox_unix_registrar._create (mbox, name);
}
/* Is that true ? Are all directories Maildir ?? */
else if (S_ISDIR (st.st_mode))
return _mailbox_maildir_registrar._init (mbox, name);
return _mailbox_maildir_registrar._create (mbox, name);
/* Why can't a mailbox be FIFO ? or a DOOR/Portal ??? */
return EINVAL;
......
......@@ -19,17 +19,17 @@
#include <registrar0.h>
#include <errno.h>
static int mailbox_maildir_init (mailbox_t *mbox, const char *name);
static int mailbox_maildir_create (mailbox_t *mbox, const char *name);
static void mailbox_maildir_destroy (mailbox_t *mbox);
struct mailbox_registrar _mailbox_maildir_registrar =
{
"MAILDIR",
mailbox_maildir_init, mailbox_maildir_destroy
mailbox_maildir_create, mailbox_maildir_destroy
};
int
mailbox_maildir_init (mailbox_t *mbox, const char *name)
mailbox_maildir_create (mailbox_t *mbox, const char *name)
{
(void)mbox; (void)name;
return ENOSYS;
......
......@@ -27,13 +27,13 @@
#include <stdlib.h>
#include <ctype.h>
static int mailbox_mh_init (mailbox_t *pmbox, const char *name);
static int mailbox_mh_create (mailbox_t *pmbox, const char *name);
static void mailbox_mh_destroy (mailbox_t *pmbox);
struct mailbox_registrar _mailbox_mh_registrar =
{
"MH",
mailbox_mh_init, mailbox_mh_destroy
mailbox_mh_create, mailbox_mh_destroy
};
typedef struct _mh_data
......@@ -43,11 +43,11 @@ typedef struct _mh_data
static int mh_open (mailbox_t mbox, int flags);
static int mh_close (mailbox_t mbox);
static int mh_scan (mailbox_t mbox, size_t *msgs);
static int mh_scan (mailbox_t mbox, size_t msgno, size_t *msgs);
static int mh_sequence(const char *name);
static int
mailbox_mh_init (mailbox_t *pmbox, const char *name)
mailbox_mh_create (mailbox_t *pmbox, const char *name)
{
mailbox_t mbox;
mh_data *data;
......@@ -57,10 +57,11 @@ mailbox_mh_init (mailbox_t *pmbox, const char *name)
mbox->name = malloc(strlen(name) + 1);
strcpy(mbox->name, name);
mbox->data = data;
mbox->_init = mailbox_mh_init;
mbox->_create = mailbox_mh_create;
mbox->_destroy = mailbox_mh_destroy;
mbox->_open = mh_open;
mbox->_close = mh_close;
mbox->_scan = mh_scan;
*pmbox = mbox;
return 0;
......@@ -110,7 +111,7 @@ mh_close (mailbox_t mbox)
}
static int
mh_scan (mailbox_t mbox, size_t *msgs)
mh_scan (mailbox_t mbox, size_t msgno, size_t *msgs)
{
struct stat st;
DIR *maildir;
......@@ -119,6 +120,8 @@ mh_scan (mailbox_t mbox, size_t *msgs)
unsigned int count = 0;
int parse_sequence_file = 0;
(void)msgno;
data = mbox->data;
maildir = opendir(mbox->name);
......
......@@ -20,17 +20,17 @@
#include <errno.h>
static int mailbox_mmdf_init (mailbox_t *mbox, const char *name);
static int mailbox_mmdf_create (mailbox_t *mbox, const char *name);
static void mailbox_mmdf_destroy (mailbox_t *mbox);
struct mailbox_registrar _mailbox_mmdf_registrar =
{
"MMDF",
mailbox_mmdf_init, mailbox_mmdf_destroy
mailbox_mmdf_create, mailbox_mmdf_destroy
};
static int
mailbox_mmdf_init (mailbox_t *mbox, const char *name)
mailbox_mmdf_create (mailbox_t *mbox, const char *name)
{
(void)mbox; (void)name;
return ENOSYS;
......
......@@ -20,13 +20,13 @@
#include <errno.h>
static int mailbox_pop_init (mailbox_t *mbox, const char *name);
static int mailbox_pop_create (mailbox_t *mbox, const char *name);
static void mailbox_pop_destroy (mailbox_t *mbox);
struct mailbox_registrar _mailbox_pop_registrar =
{
"POP3",
mailbox_pop_init, mailbox_pop_destroy
mailbox_pop_create, mailbox_pop_destroy
};
static void
......@@ -37,7 +37,7 @@ mailbox_pop_destroy (mailbox_t *mbox)
}
static int
mailbox_pop_init (mailbox_t *mbox, const char *name)
mailbox_pop_create (mailbox_t *mbox, const char *name)
{
(void)mbox; (void)name;
return ENOSYS;
......
......@@ -22,7 +22,8 @@
#include <message0.h>
#include <url0.h>
#include <io0.h>
#include <attribute.h>
#include <body0.h>
#include <attribute0.h>
#include <header.h>
#include <auth.h>
#include <locker.h>
......@@ -48,13 +49,13 @@
#include <ctype.h>
#include <limits.h>
static int mailbox_unix_init (mailbox_t *pmbox, const char *name);
static int mailbox_unix_create (mailbox_t *pmbox, const char *name);
static void mailbox_unix_destroy (mailbox_t *pmbox);
struct mailbox_registrar _mailbox_unix_registrar =
{
"UNIX MBOX",
mailbox_unix_init, mailbox_unix_destroy
mailbox_unix_create, mailbox_unix_destroy
};
/*
......@@ -64,13 +65,13 @@ struct mailbox_registrar _mailbox_unix_registrar =
typedef struct _mailbox_unix_message
{
/* offset of the parts of the messages in the mailbox*/
off_t header;
off_t header_end;
off_t header_from;
off_t header_from_end;
/* little hack to make things easier
* when updating the attribute
*/
off_t hdr_status;
off_t hdr_status_end;
off_t header_status;
off_t header_status_end;
off_t body;
off_t body_end;
......@@ -79,11 +80,8 @@ typedef struct _mailbox_unix_message
attribute_t old_attr;
attribute_t new_attr;
/* some sort of uniq id, maybe we should use the
* Message-ID of the message, but we'll have to free
* when done.
*/
size_t num;
size_t header_lines;
size_t body_lines;
FILE *file;
/* if we have a message attach to it */
......@@ -130,19 +128,20 @@ static int mailbox_unix_is_updated (mailbox_t);
static int mailbox_unix_size (mailbox_t, off_t *size);
static ssize_t mailbox_unix_get_header (mailbox_t, size_t msgno, char *h,
size_t len, off_t off, int *err);
/* private stuff */
static int mailbox_unix_is_deleted (mailbox_t mbox, size_t msgno);
static int mailbox_unix_validity (mailbox_t mbox, size_t msgno);
static int mailbox_unix_get_header (mailbox_unix_message_t mum, char *buffer,
size_t len, off_t off, ssize_t *pnread);
static int mailbox_unix_getfd (stream_t is, int *pfd);
static int mailbox_unix_readstream (stream_t is, char *buffer, size_t buflen,
off_t off, size_t *pnread);
static int mailbox_unix_is_from (const char *);
static int mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len,
off_t *content_length, size_t msgno);
static int mailbox_unix_body_size (body_t body, size_t *psize);
static int mailbox_unix_body_lines (body_t body, size_t *plines);
static int mailbox_unix_msg_from (message_t msg, char *buf, size_t len,
size_t *pnwrite);
static int mailbox_unix_msg_received (message_t msg, char *buf, size_t len,
size_t *pnwrite);
static int mailbox_unix_lock (mailbox_t mbox, int flag);
static int mailbox_unix_touchlock (mailbox_t mbox);
static int mailbox_unix_unlock (mailbox_t mbox);
......@@ -156,7 +155,7 @@ static int mailbox_unix_iunlock (mailbox_t mbox);
* Hopefully there will not be a mailbox name "unix:"
*/
static int
mailbox_unix_init (mailbox_t *pmbox, const char *name)
mailbox_unix_create (mailbox_t *pmbox, const char *name)
{
mailbox_t mbox;
mailbox_unix_data_t mud;
......@@ -271,7 +270,7 @@ mailbox_unix_init (mailbox_t *pmbox, const char *name)
pthread_mutex_init (&(mud->mutex), NULL);
#endif
mbox->_init = mailbox_unix_init;
mbox->_create = mailbox_unix_create;
mbox->_destroy = mailbox_unix_destroy;
mbox->_open = mailbox_unix_open;
......@@ -437,10 +436,11 @@ mailbox_unix_open (mailbox_t mbox, int flags)
if (mud->file == NULL)
{
/* what's up ?? */
int err = errno;
mailbox_unix_iunlock (mbox);
return ENOMEM;
return err;
}
/* Is this necessary ?? */
/* Is this check necessary ?? */
/* Check to make sure this is indeed a Unix Mail format */
flockfile (mud->file);
{
......@@ -496,410 +496,8 @@ mailbox_unix_close (mailbox_t mbox)
return 0;
}
/* FIXME: a little weak, we should do full reconnaissance of the
* the "From " header :
* From <user> <weekday> <month> <day> <hr:min:sec>
* [T1 [T2]] <year> [remote-list]
*/
static int
mailbox_unix_is_from (const char *from)
{
const char *sep;
/* From_ */
if (strncmp (from, "From ", 5) != 0)
return 0;
from += 5;
/* <user> */
sep = strchr (from, ' ');
if (sep == NULL)
return 0;
from = ++sep;
/* weekday */
sep = strchr (from, ' ');
if (sep == NULL)
return 0;
from = ++sep;
/* month */
sep = strchr (from, ' ');
if (sep == NULL)
return 0;
from = ++sep;
/* day */
sep = strchr (from, ' ');
if (sep == NULL)
return 0;
from = ++sep;
/* hr:min:sec */
/* hr */
sep = strchr (from, ':');
if (sep == NULL)
return 0;
from = ++sep;
/* min */
sep = strchr (from, ':');
if (sep == NULL)
return 0;
from = ++sep ;
/* sec */
sep = strchr (from, ' ');
if (sep == NULL)
return 0;
/* FIXME PLEASE: the rest is getting more complex, finish it later */
return 1;
}
/*
* We skip over the rest of the header. Scan for
* Status: to set the attribute. Hopefully the Content-Length
* in there too.
*/
static int
mailbox_unix_readhdr (mailbox_t mbox, char *buf, size_t len,
off_t *content_length, size_t msgno)
{
mailbox_unix_data_t mud = (mailbox_unix_data_t)mbox->data;
mailbox_unix_message_t mum = mud->umessages[msgno];
char *sep;
/* skip over the remaining header */
errno = 0;
while (fgets (buf, len, mud->file))
{
/* FIXME: The heuristic is still weak
we will break and consider things not to be a header if:
1: an empty line
2: can not be a header
*/
if (strcmp (buf, "\n") == 0 || strcmp (buf, "\r\n") == 0
|| (isalpha (buf[0]) && (sep = strchr (buf, ':')) == NULL))
break;
/* get the the Content lenght of the body if possible */
else if (strncmp (buf, "Content-Length:", 15) == 0)
{
sep = strchr(buf, ':'); /* pass the ':' */
sep[strlen (sep) - 1] = '\0'; /* chop the newline */
/* FIXME: use xstrtol() if strtol() is not on the platform */
/* FIXME: what an awkward way of handling error
Some damage control can be done here.
for example just set content_length = -1;
and rely above to discover the body part */
errno = 0;
*content_length = strtol (sep + 1, NULL, 10);
if (*content_length == 0 ||
*content_length == LONG_MIN ||
*content_length == LONG_MAX)
{
if (errno != 0)
return errno;
}
}
/* Set the attribute */
else if (strncasecmp (buf, "Status:", 7) == 0)
{
mum->hdr_status_end = ftell (mud->file);
mum->hdr_status = mum->hdr_status_end - strlen (buf);
sep = strchr(buf, ':'); /* pass the ':' */
if (strchr (sep, 'R') != NULL || strchr (sep, 'r') != NULL)
attribute_set_read (mum->old_attr);
if (strchr (sep, 'O') != NULL || strchr (sep, 'o') != NULL)
attribute_set_seen (mum->old_attr);
if (strchr (sep, 'A') != NULL || strchr (sep, 'a') != NULL)
attribute_set_answered (mum->old_attr);
if (strchr (sep, 'F') != NULL || strchr (sep, 'f') != NULL)
attribute_set_flagged (mum->old_attr);
attribute_copy (mum->new_attr, mum->old_attr);
}
}
/* check for any dubious conditions */
if (feof (mud->file) || ferror (mud->file))
return errno;
return 0;
}
/* Parsing.
* This a bit fragile, I need to secure this.
* The approach is to detect the "From " as start of a
* new message, give the position of the header and scan
* until "\n" then set header_end, set body position, if we have
* a Content-Length field jump to the point if not
* scan until we it another "From " and set body_end.
*/
static int
mailbox_unix_scan (mailbox_t mbox, size_t msgno, size_t *pcount)
{
char buf[BUFSIZ];
int header = 0;
int body = 0;
off_t content_length = -1;
mailbox_unix_data_t mud;
mailbox_unix_message_t mum = NULL;
struct stat st;
int status;
size_t progress_counter = 0;
/* sanity */
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
return EINVAL;
/* FIXME: I should also block signals and check cancelstate(Pthread)
since We can not afford to be intr */
mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK);
mailbox_unix_lock (mbox, MU_LOCKER_RDLOCK);
flockfile (mud->file);
if (fstat (fileno (mud->file), &st) != 0)
{
status = errno;
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
return status;
}
mud->mtime = st.st_mtime;
mud->size = st.st_size;
rewind (mud->file);
/* seek to the starting point */
if (mud->umessages)
{
if (mud->messages_count > 0 &&
msgno != 0 &&
msgno <= mud->messages_count)
{
mum = mud->umessages[msgno - 1];
if (mum)
fseek (mud->file, mum->body_end, SEEK_SET);
mud->messages_count = msgno;
}
}
errno = 0;
while (fgets (buf, sizeof (buf), mud->file))
{
if (mailbox_unix_is_from (buf))
{
if (body && mum )
{
int over = strlen (buf);
mum->body_end = ftell (mud->file);
mum->body_end -= (over);
body = 0;
mud->messages_count++;
/* reset the progress_counter */
progress_counter = 0;
/* notifications ADD_MESG */
{
off_t where = ftell (mud->file);
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
/*
* My! I do not like this way of bailing out.
*/
if (mailbox_notification (mbox, MU_EVT_MBX_MSG_ADD) != 0)
{
if (pcount)
*pcount = mud->messages_count;
return EINTR;
}
flockfile (mud->file);
mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK);
mailbox_unix_lock (mbox, MU_LOCKER_RDLOCK);
fseek (mud->file, where, SEEK_SET);
}
}
header = 1;
}
/* header */
if (header)
{
/* FIXME: What happen if some mailer violates the rfc822 and the
"From " field contains a NULL byte */
int over = strlen (buf);
/* allocate a slot for the new message */
if (mud->messages_count >= mud->umessages_count)
{
mailbox_unix_message_t *m;
m = realloc (mud->umessages,
(mud->messages_count + 1) * sizeof (*m));
if (m == NULL)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
return ENOMEM;
}
mud->umessages = m;
mud->umessages[mud->umessages_count] = NULL;
mud->umessages_count++;
}
/* allocate space for the new message */
if (mud->umessages[mud->messages_count] == NULL)
{
mum = calloc (1, sizeof (*mum));
if (mum == NULL)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
return ENOMEM;
}
mud->umessages[mud->messages_count] = mum;
}
else
{
/* reuse the message */
mum = mud->umessages[mud->messages_count];
}
status = attribute_init (&(mum->old_attr), mbox);
if (status != 0)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
return ENOMEM;
}
status = attribute_init (&(mum->new_attr), mbox);
if (status != 0)
{
attribute_destroy (&(mum->old_attr), mbox);
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
return ENOMEM;
}
mum->file = mud->file;
mum->num = mud->messages_count + 1;
mum->header = ftell (mud->file);
/* substract the overrun */
mum->header -= over;
/* skip the remaining header and set the attributes */
if ((status = mailbox_unix_readhdr (mbox, buf,
sizeof (buf), &content_length,
mud->messages_count)) != 0)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
return status;
}
mum->header_end = ftell (mud->file) - strlen(buf);
header = 0;
body = !header;
} /* header */
/* body */
if (body)
{
/* set the body position */
if (mum->body == 0)
mum->body = ftell (mud->file);
if (content_length >= 0)
{
/* ouf ! we got the lenght, jump */
mum->body_end = mum->body + content_length;
fseek (mud->file, content_length, SEEK_CUR);
content_length = -1;
body = 0;
mud->messages_count++;
/* reset the progress_counter */
progress_counter = 0;
/* notification ADD MESG*/
{
off_t where = ftell (mud->file);
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
/*
* Brian E. are sure this is a good idea ??
*/
if (mailbox_notification (mbox, MU_EVT_MBX_MSG_ADD) != 0)
{
if (pcount)
*pcount = mud->messages_count;
return EINTR;
}
flockfile (mud->file);
mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK);
mailbox_unix_lock (mbox, MU_LOCKER_RDLOCK);
fseek (mud->file, where, SEEK_SET);
}
}
}
/* notification MBX_PROGRESS
* We do not want to fire up the progress notification
* every line, it will be too expensive, so we do it
* arbitrarely every 10 000 Lines.
* FIXME: maybe this should be configurable.
*/
if ((++progress_counter % 10000) == 0)
{
off_t where = ftell (mud->file);
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
/*
* This is more tricky we can not leave the mum
* struct incomplete. If they want to bailout
* they probably did not care about the last message
* we should free it;
*/
if (mailbox_notification (mbox, MU_EVT_MBX_PROGRESS) != 0)
{
if (mum)
{
attribute_destroy (&(mum->old_attr), mbox);
attribute_destroy (&(mum->new_attr), mbox);
message_destroy (&(mum->message), mbox);
free (mum);
mud->umessages[mud->messages_count - 1] = NULL;
mud->messages_count--;
}
if (pcount)
*pcount = mud->messages_count;
return EINTR;
}
flockfile (mud->file);
mailbox_unix_ilock (mbox, MU_LOCKER_WRLOCK);
mailbox_unix_lock (mbox, MU_LOCKER_RDLOCK);
fseek (mud->file, where, SEEK_SET);
}
mailbox_unix_touchlock (mbox);
} /* while */
status = errno;
if (feof (mud->file))
status = 0;
clearerr (mud->file);
if (mum)
{
mum->body_end = ftell (mud->file);
mud->messages_count++;
}
rewind (mud->file);
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
mailbox_unix_unlock (mbox);
if (pcount)
*pcount = mud->messages_count;
mailbox_notification (mbox, MU_EVT_MBX_MSG_ADD);
return status;
}
/* Mailbox Parsing */
#include "mbx_unixscan.c"
/* FIXME: How to handle a shrink ? meaning, the &^$^@%#@^& user
* start two browsers and delete files in one. My views
......@@ -911,38 +509,13 @@ mailbox_unix_is_updated (mailbox_t mbox)
{
mailbox_unix_data_t mud;
struct stat st;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL ||
fstat (fileno (mud->file), &st) < 0)
if ((mud = (mailbox_unix_data_t)mbox->data) == NULL ||
fstat (fileno (mud->file), &st) < 0)
return 0;
return (mud->mtime == st.st_mtime);
}
static int
mailbox_unix_validity (mailbox_t mbox, size_t msgno)
{
mailbox_unix_data_t mud;
if (mbox == NULL ||
(mud = (mailbox_unix_data_t) mbox->data) == NULL)
return EINVAL;
/* valid ? */
return !(mud->messages_count > 0 && msgno > 0 &&
msgno <= mud->messages_count);
}
static int
mailbox_unix_is_deleted (mailbox_t mbox, size_t msgno)
{
mailbox_unix_data_t mud;
int status = mailbox_unix_validity (mbox, msgno);
if (status != 0)
return status;
msgno--;
mud = (mailbox_unix_data_t) mbox->data;
return attribute_is_deleted (mud->umessages[msgno]->new_attr);
}
static int
mailbox_unix_num_deleted (mailbox_t mbox, size_t *num)
{
mailbox_unix_data_t mud;
......@@ -1065,6 +638,17 @@ mailbox_unix_expunge (mailbox_t mbox)
mailbox_unix_ilock (mbox, MU_LOCKER_RDLOCK);
flockfile (mud->file);
/*
* We can not be NONBLOCKING here.
* It would irresponsable.
*/
if ((oflags = fcntl (fileno (mud->file), F_GETFL, 0)) < 0)
{
status = errno;
goto bailout;
}
fcntl (fileno (mud->file), F_SETFL, oflags & ~O_NONBLOCK);
/* Do we have a consistent view of the mailbox */
/* FIXME: this is not enough we can do better
* - by checking the file size and scream bloody murder
......@@ -1078,17 +662,6 @@ mailbox_unix_expunge (mailbox_t mbox)
goto bailout;
}
/*
* We can not be NONBLOCKING here.
* It would irresponsable.
*/
if ((oflags = fcntl (fileno (mud->file), F_GETFL, 0)) < 0)
{
status = errno;
goto bailout;
}
fcntl (fileno (mud->file), F_SETFL, oflags & ~O_NONBLOCK);
rewind (mud->file);
/* Go to the first mail with an attribute change */
......@@ -1108,7 +681,7 @@ mailbox_unix_expunge (mailbox_t mbox)
}
/* set the marker position */
total = marker = mud->umessages[j]->header;
total = marker = mud->umessages[j]->header_from;
/* copy to tempfile emails not mark changed */
for (first = 1, i = j; i < mud->messages_count; i++)
......@@ -1130,17 +703,17 @@ mailbox_unix_expunge (mailbox_t mbox)
total++;
}
/* copy the header */
if (fseek (mud->file, mum->header, SEEK_SET) == -1)
if (fseek (mud->file, mum->header_from, SEEK_SET) == -1)
{
status = errno;
goto bailout;
}
/* attribute change ? */
if (! attribute_is_equal (mum->old_attr, mum->new_attr) &&
mum->hdr_status > mum->header)
mum->header_status > mum->header_from)
{
len = mum->hdr_status - mum->header;
current = mum->hdr_status_end;
len = mum->header_status - mum->header_from;
current = mum->header_status_end;
while (len > 0)
{
nread = (len < sizeof (buffer)) ? len : sizeof (buffer);
......@@ -1190,9 +763,9 @@ mailbox_unix_expunge (mailbox_t mbox)
}
else /* attribute did not change */
{
current = mum->header;
current = mum->header_from;
}
len = mum->header_end - current;
len = mum->body - current;
while (len > 0)
{
nread = (len < sizeof (buffer)) ? len : sizeof (buffer);
......@@ -1207,8 +780,8 @@ mailbox_unix_expunge (mailbox_t mbox)
}
/* Separate the header from body */
fputc ('\n', tempfile);
total++;
/*fputc ('\n', tempfile); */
/*total++;*/
/* copy the body */
if (fseek (mud->file, mum->body, SEEK_SET) < 0)
......@@ -1281,8 +854,8 @@ mailbox_unix_expunge (mailbox_t mbox)
{
if (errno == EAGAIN || errno == EINTR)
{
continue;
errno = 0;
continue;
}
status = errno;
goto bailout;
......@@ -1352,19 +925,13 @@ mailbox_unix_readstream (stream_t is, char *buffer, size_t buflen,
{
nread = ((size_t)ln < buflen) ? ln : buflen;
/* position the file pointer and the buffer */
if (fseek (mum->file, mum->body + off, SEEK_SET) < 0)
{
funlockfile (mum->file);
return errno;
}
if (fread (buffer, sizeof (*buffer), nread, mum->file) != nread)
if (fseek (mum->file, mum->body + off, SEEK_SET) < 0 ||
fread (buffer, sizeof (*buffer), nread, mum->file) != nread)
{
funlockfile (mum->file);
return errno;
}
}
else
nread = 0;
}
funlockfile (mum->file);
......@@ -1374,56 +941,146 @@ mailbox_unix_readstream (stream_t is, char *buffer, size_t buflen,
}
static int
mailbox_unix_get_header (mailbox_t mbox, size_t msgno, char *buffer,
mailbox_unix_get_header (mailbox_unix_message_t mum, char *buffer,
size_t len, off_t off, ssize_t *pnread)
{
mailbox_unix_data_t mud;
size_t nread = 0;
/* check if valid */
int status = mailbox_unix_validity (mbox, msgno);
if (status != 0)
return status;
FILE *file = mum->file;
mud = (mailbox_unix_data_t) mbox->data;
msgno--;
if (buffer == NULL || len == 0)
{
if (pnread)
*pnread = nread;
return 0;
}
mailbox_unix_ilock (mbox, MU_LOCKER_RDLOCK);
flockfile (mud->file);
flockfile (file);
{
mailbox_unix_message_t mum = mud->umessages[msgno];
off_t ln = mum->header_end - (mum->header + off);
off_t ln = mum->body - (mum->header_from_end + off);
if (ln > 0)
{
nread = ((size_t)ln < len) ? ln : len;
/* position the file pointer and the buffer */
if (fseek (mud->file, mum->header + off, SEEK_SET) < 0)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
return errno;
}
if (fread (buffer, sizeof (*buffer), nread, mud->file) != nread)
if (fseek (file, mum->header_from_end + off, SEEK_SET) < 0 ||
fread (buffer, sizeof (*buffer), nread, file) != nread)
{
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
funlockfile (file);
return errno;
}
}
else
nread = 0;
}
funlockfile (mud->file);
mailbox_unix_iunlock (mbox);
funlockfile (file);
if (pnread)
*pnread = nread;
*pnread = nread;
return 0;
}
static int
mailbox_unix_body_size (body_t body, size_t *psize)
{
mailbox_unix_message_t mum = body->owner;
if (mum == NULL)
return EINVAL;
if (psize)
*psize = mum->body_end - mum->body;
return 0;
}
static int
mailbox_unix_body_lines (body_t body, size_t *plines)
{
mailbox_unix_message_t mum = body->owner;
if (mum == NULL)
return EINVAL;
if (plines)
*plines = mum->body_lines;
return 0;
}
static int
mailbox_unix_msg_received (message_t msg, char *buf, size_t len,
size_t *pnwrite)
{
mailbox_unix_message_t mum = msg->owner;
char buffer[512];
if (mum == NULL)
return EINVAL;
flockfile (mum->file);
{
if (fseek (mum->file, mum->header_from, SEEK_SET) < 0 ||
fgets (buffer, sizeof (buffer), mum->file) == NULL)
{
if (pnwrite)
*pnwrite = 0;
if (buf)
*buf = '\0';
return errno;
}
}
funlockfile (mum->file);
if (strlen (buffer) > 5)
{
char *s;
s = strchr (buffer + 5, ' ');
if (s)
{
if (buf && len > 0)
{
strncpy (buf, s + 1, len);
buffer [len - 1] = '\0';
}
if (pnwrite)
*pnwrite = strlen (s);
return 0;
}
}
if (pnwrite)
*pnwrite = 0;
if (buf)
*buf = '\0';
return 0;
}
static int
mailbox_unix_msg_from (message_t msg, char *buf, size_t len, size_t *pnwrite)
{
mailbox_unix_message_t mum = msg->owner;
char buffer[512];
if (mum == NULL)
return EINVAL;
flockfile (mum->file);
{
if (fseek (mum->file, mum->header_from, SEEK_SET) < 0 ||
fgets (buffer, sizeof (buffer), mum->file) == NULL)
{
if (pnwrite)
*pnwrite = 0;
if (buf)
*buf = '\0';
return errno;
}
}
funlockfile (mum->file);
if (strlen (buffer) > 5)
{
char *s;
s = strchr (buffer + 5, ' ');
if (s)
{
*s = '\0';
if (buf && len > 0)
{
strncpy (buf, buffer + 5, len);
buffer [len - 1] = '\0';
}
if (pnwrite)
*pnwrite = strlen (buffer + 5);
return 0;
}
}
if (pnwrite)
*pnwrite = 0;
if (buf)
*buf = '\0';
return 0;
}
......@@ -1441,9 +1098,12 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
message_t msg = NULL;
stream_t stream = NULL;
header_t header = NULL;
body_t body = NULL;
if (mbox == NULL || pmsg == NULL ||
(mud = (mailbox_unix_data_t)mbox->data) == NULL)
(mud = (mailbox_unix_data_t)mbox->data) == NULL ||
(!(mud->messages_count > 0 && msgno > 0 &&
msgno <= mud->messages_count)))
return EINVAL;
mum = mud->umessages[msgno - 1];
......@@ -1457,32 +1117,32 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
}
/* get the headers */
do {
status = mailbox_unix_get_header (mbox, msgno, buf, sizeof(buf),
offset, &nread);
if (status != 0)
{
free (pbuf);
return status;
}
do
{
status = mailbox_unix_get_header (mum, buf, sizeof(buf), offset, &nread);
if (status != 0)
{
free (pbuf);
return status;
}
if (nread == 0)
break;
if (nread == 0)
break;
tbuf = realloc (pbuf, offset + nread);
if (tbuf == NULL)
{
free (pbuf);
return ENOMEM;
}
else
pbuf = tbuf;
memcpy (pbuf + offset, buf, nread);
offset += nread;
} while (nread > 0);
tbuf = realloc (pbuf, offset + nread);
if (tbuf == NULL)
{
free (pbuf);
return ENOMEM;
}
else
pbuf = tbuf;
memcpy (pbuf + offset, buf, nread);
offset += nread;
} while (nread > 0);
/* get an empty message struct */
status = message_init (&msg, mum);
status = message_create (&msg, mum);
if (status != 0)
{
free (pbuf);
......@@ -1490,8 +1150,8 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
}
/* set the header */
if ((status = header_init (&header, pbuf, offset, mum)) != 0 ||
(status = message_set_header (msg, header, mum)) != 0)
status = header_create (&header, pbuf, offset, mum);
if (status != 0)
{
free (pbuf);
message_destroy (&msg, mum);
......@@ -1500,33 +1160,39 @@ mailbox_unix_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
free (pbuf);
message_set_header (msg, header, mum);
/* prepare the stream */
status = stream_init (&stream, mum);
/* prepare the body */
status = body_create (&body, mum);
if (status != 0)
{
message_destroy (&msg, mum);
return status;
}
stream_set_read (stream, mailbox_unix_readstream, mum);
stream_set_fd (stream, mailbox_unix_getfd, mum);
message_set_stream (msg, stream, mum);
/* set the attribute */
status = message_set_attribute (msg, mum->new_attr, mum);
status = stream_create (&stream, mum);
if (status != 0)
{
message_destroy (&msg, mum);
return status;
}
stream_set_read (stream, mailbox_unix_readstream, mum);
stream_set_fd (stream, mailbox_unix_getfd, mum);
body_set_stream (body, stream, mum);
body_set_size (body, mailbox_unix_body_size, mum);
/* set the line */
body_set_lines (body, mailbox_unix_body_lines, mum);
message_set_body (msg, body, mum);
/* set the size */
status = message_set_size (msg, mum->body_end - mum->header, mum);
/* set the attribute */
status = message_set_attribute (msg, mum->new_attr, mum);
if (status != 0)
{
message_destroy (&msg, mum);
return status;
}
/* set the envelope */
message_set_from (msg, mailbox_unix_msg_from, mum);
message_set_received (msg, mailbox_unix_msg_received, mum);
/* attach the message to the mailbox unix data */
mum->message = msg;
......@@ -1555,12 +1221,13 @@ mailbox_unix_append_message (mailbox_t mbox, message_t msg)
struct stat st;
int fd;
char buffer[BUFSIZ];
size_t nread;
size_t nread = 0;
off_t off = 0;
stream_t is;
header_t hdr;
int status;
/* move to the end of the file, not necesary if _APPEND mode */
fd = fileno (mud->file);
if (fstat (fd, &st) != 0)
{
......@@ -1576,24 +1243,42 @@ mailbox_unix_append_message (mailbox_t mbox, message_t msg)
}
/* header */
message_get_header (msg, &hdr);
header_get_stream (hdr, &is);
if (st.st_size != 0)
fputc ('\n', mud->file);
message_get_header (msg, &hdr);
/* generate a "From " separator */
{
char from[128];
char date[128];
char *s;
size_t n = 0;
*date = *from = '\0';
message_from (msg, from, sizeof (from), &n);
s = memchr (from, '\n', n);
if (s) *s = '\0'; n = 0;
message_received (msg, date, sizeof (date), &n);
s = memchr (date, '\n', n);
if (s) *s = '\0';
fprintf (mud->file, "From %s %s\n", from, date);
}
header_get_stream (hdr, &is);
do {
status = stream_read (is, buffer, sizeof (buffer), off, &nread);
if (status != 0)
return status;
if (nread == 0)
break;
fwrite (buffer, sizeof (*buffer), nread, mud->file);
off += nread;
} while (nread > 0);
*buffer = '\0';
/* separator */
fputc ('\n', mud->file);
/*fputc ('\n', mud->file);*/
/* body */
off = 0;
message_get_stream (msg, &is);
do {
stream_read (is, buffer, sizeof (buffer), off, &nread);
......@@ -1630,17 +1315,17 @@ mailbox_unix_size (mailbox_t mbox, off_t *size)
}
static int
mailbox_unix_messages_count (mailbox_t mbox, size_t *count)
mailbox_unix_messages_count (mailbox_t mbox, size_t *pcount)
{
mailbox_unix_data_t mud;
if (mbox == NULL || (mud = (mailbox_unix_data_t) mbox->data) == NULL)
return EINVAL;
if (! mailbox_unix_is_updated (mbox))
return mailbox_unix_scan (mbox, 1, count);
return mailbox_unix_scan (mbox, 1, pcount);
if (count)
*count = mud->messages_count;
if (pcount)
*pcount = mud->messages_count;
return 0;
}
......
......@@ -16,20 +16,19 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <header.h>
#include <attribute.h>
#include <message0.h>
#include <mailbox0.h>
#include <io0.h>
#include <message0.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <string.h>
static int body_init (body_t *pbody, void *owner);
static void body_destroy (body_t *pbody, void *owner);
static int extract_addr(const char *s, size_t n, char **presult,
size_t *pnwrite);
static int message_read (stream_t is, char *buf, size_t buflen,
off_t off, size_t *pnread );
static int message_write (stream_t os, const char *buf, size_t buflen,
......@@ -37,142 +36,25 @@ static int message_write (stream_t os, const char *buf, size_t buflen,
static int message_get_fd (stream_t stream, int *pfd);
int
message_clone (message_t msg)
message_create (message_t *pmsg, void *owner)
{
int status;
message_t msg;
stream_t stream;
header_t header;
attribute_t attribute;
body_t body;
char buffer[BUFSIZ];
char *pbuf = NULL;
char *tbuf = NULL;
off_t offset = 0;
size_t nread = 0;
int status;
if (msg == NULL)
if (pmsg == NULL)
return EINVAL;
/* If is not own, then it's a floating message
* just bump the reference count.
*/
if (msg->owner == NULL)
{
if (msg->ref_count <= 0)
msg->ref_count = 1;
else
msg->ref_count++;
return 0;
}
/* retreive the header */
{
header = msg->header;
status = header_get_stream (header, &stream);
if (status != 0)
return status;
do {
status = stream_read (stream, buffer, sizeof (buffer), offset, &nread);
if (status != 0)
{
free (pbuf);
return status;
}
if (nread == 0)
break;
tbuf = realloc (pbuf, offset + nread);
if (tbuf == NULL)
{
free (pbuf);
return ENOMEM;
}
else
pbuf = tbuf;
memcpy (pbuf + offset, buffer, nread);
offset += nread;
} while (nread > 0);
}
/* set the new header */
status = header_init (&header, pbuf, offset, msg);
msg = calloc (1, sizeof (*msg));
if (msg == NULL)
return ENOMEM;
status = stream_create (&stream, msg);
if (status != 0)
{
free (pbuf);
return status;
}
free (pbuf);
/* retrieve the body */
{
status = body_init (&body, msg);
if (status != 0)
{
header_destroy (&header, msg);
return status;
}
stream = msg->stream;
offset = 0;
do {
do
{
status = stream_read (stream, buffer, sizeof (buffer), offset, &nread);
} while (status == EAGAIN);
if (status != 0)
{
header_destroy (&header, msg);
body_destroy (&body, msg);
return status;
}
fwrite (buffer, sizeof (*buffer), nread, body->file);
offset += nread;
} while (nread > 0);
rewind (body->file);
}
/* set the body with the streams */
status = stream_init (&stream, msg);
if (status != 0 )
{
header_destroy (&header, msg);
body_destroy (&body, msg);
free (msg);
return status;
}
stream_set_read (stream, message_read, msg);
stream_set_write (stream, message_write, msg);
/* attribute */
status = attribute_init (&attribute, msg);
if (status != 0)
{
header_destroy (&header, msg);
body_destroy (&body, msg);
stream_destroy (&stream, msg);
}
attribute_copy (attribute, msg->attribute);
/* every thing went ok */
msg->header = header;
msg->attribute = attribute;
msg->stream = stream;
msg->body = body;
msg->size = offset;
msg->ref_count++;
msg->owner = NULL; /* orphan */
return 0;
}
int
message_init (message_t *pmsg, void *owner)
{
message_t msg;
if (pmsg == NULL)
return EINVAL;
msg = calloc (1, sizeof (*msg));
if (msg == NULL)
return ENOMEM;
msg->owner = owner;
*pmsg = msg;
return 0;
......@@ -200,9 +82,9 @@ message_destroy (message_t *pmsg, void *owner)
if (destroy)
{
header_t header = msg->header;
attribute_t attribute = msg->attribute;
stream_t stream = msg->stream;
header_t header = msg->header;
body_t body = msg->body;
/* notify the listeners */
......@@ -215,12 +97,7 @@ message_destroy (message_t *pmsg, void *owner)
stream_destroy (&stream, owner);
/* if sometype of floating/temporary message */
if (body)
{
if (body->file)
fclose (body->file);
free (body);
}
body_destroy (&body, owner);
/* notifications are done */
free (msg->event);
......@@ -240,14 +117,14 @@ message_destroy (message_t *pmsg, void *owner)
int
message_get_header (message_t msg, header_t *phdr)
{
if (phdr == NULL || msg == NULL)
if (msg == NULL || phdr == NULL)
return EINVAL;
/* is it a floating mesg */
if (msg->header == NULL && msg->owner == NULL)
{
header_t header;
int status = header_init (&header, NULL, 0, msg);
int status = header_create (&header, NULL, 0, msg);
if (status != 0)
return status;
msg->header = header;
......@@ -270,26 +147,53 @@ message_set_header (message_t msg, header_t hdr, void *owner)
}
int
message_get_body (message_t msg, body_t *pbody)
{
if (msg == NULL || pbody == NULL)
return EINVAL;
/* is it a floating mesg */
if (msg->body == NULL)
{
body_t body;
int status = body_create (&body, msg);
if (status != 0)
return status;
msg->body = body;
}
*pbody = msg->body;
return 0;
}
int
message_set_body (message_t msg, body_t body, void *owner)
{
if (msg == NULL )
return EINVAL;
if (msg->owner != owner)
return EACCES;
/* make sure we destoy the old if it was own by the mesg */
body_destroy (&(msg->body), msg);
msg->body = body;
return 0;
}
int
message_get_stream (message_t msg, stream_t *pstream)
{
if (msg == NULL || pstream == NULL)
return EINVAL;
if (msg->stream == NULL && msg->owner == NULL)
if (msg->stream == NULL)
{
stream_t stream;
int status;
/* lazy floating message the body is created when
* doing the first message_write creation
*/
status = stream_init (&stream, msg);
status = stream_create (&stream, msg);
if (status != 0)
return status;
stream_set_read (stream, message_read, msg);
stream_set_write (stream, message_write, msg);
stream_set_fd (stream, message_get_fd, msg);
/* make sure we've clean */
stream_destroy (&(msg->stream), msg);
msg->stream = stream;
}
......@@ -298,36 +202,143 @@ message_get_stream (message_t msg, stream_t *pstream)
}
int
message_set_stream (message_t msg, stream_t stream, void *owner)
message_lines (message_t msg, size_t *plines)
{
size_t hlines, blines;
if (msg == NULL)
return EINVAL;
return EINVAL;
if (plines)
{
hlines = blines = 0;
header_lines (msg->header, &hlines);
body_lines (msg->body, &blines);
*plines = hlines + blines;
}
return 0;
}
int
message_size (message_t msg, size_t *psize)
{
size_t hsize, bsize;
if (msg == NULL)
return EINVAL;
if (psize)
{
hsize = bsize = 0;
header_size (msg->header, &hsize);
body_size (msg->body, &bsize);
*psize = hsize + bsize;
}
return 0;
}
int
message_set_from (message_t msg,
int (*_from)(message_t, char *, size_t, size_t*),
void *owner)
{
if (msg == NULL)
return EINVAL;
if (msg->owner != owner)
return EACCES;
/* make sure we destroy the old one if it is own by the message */
stream_destroy (&(msg->stream), msg);
msg->stream = stream;
msg->_from = _from;
return 0;
}
int
message_get_size (message_t msg, size_t *psize)
message_from (message_t msg, char *buf, size_t len, size_t *pnwrite)
{
header_t header = NULL;
size_t n = 0;
int status;
if (msg == NULL)
return EINVAL;
if (psize)
*psize = msg->size;
/* 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, "FROM", NULL, 0, &n);
if (status == 0 && n != 0)
{
char *from = calloc (1, n + 1);
char *addr;
header_get_value (header, "FROM", from, n + 1, NULL);
if (extract_addr (from, n, &addr, &n) == 0)
{
n = (n > len) ? len : n;
if (buf && len > 0)
{
memcpy (buf, addr, n);
buf[n - 1] = '\0';
}
free (addr);
free (from);
if (pnwrite)
*pnwrite = n;
return 0;
}
}
/* oops */
n = (7 > len) ? len: 7;
if (buf && len > 0)
{
memcpy (buf, "unknown", n);
buf [n - 1] = '\0';
}
if (pnwrite)
*pnwrite = n;
return 0;
}
int
message_set_size (message_t msg, size_t size, void *owner)
message_set_received (message_t msg,
int (*_received) (message_t, char *, size_t , size_t *),
void *owner)
{
if (msg == NULL)
return EINVAL;
if (msg->owner != owner)
return EACCES;
msg->size = size;
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 - 1] = '\0';
if (pnwrite)
*pnwrite = n;
return 0;
}
......@@ -339,7 +350,7 @@ message_get_attribute (message_t msg, attribute_t *pattribute)
if (msg->attribute == NULL && msg->owner == NULL)
{
attribute_t attribute;
int status = attribute_init (&attribute, msg);
int status = attribute_create (&attribute, msg);
if (status != 0)
return status;
msg->attribute = attribute;
......@@ -427,100 +438,43 @@ message_notification (message_t msg, size_t type)
}
}
/* We use the notion of body_t here */
static int
body_init (body_t *pbody, void *owner)
{
body_t body;
FILE *file;
if (pbody == NULL)
return EINVAL;
#ifdef HAVE_MKSTEMP
{
char tmpbuf[L_tmpnam + 1];
int fd;
if (tmpnam (tmpbuf) == NULL ||
(fd = mkstemp (tmpbuf)) == -1 ||
(file = fdopen(fd, "w+")) == NULL)
return errno;
(void)remove(tmpbuf);
}
#else
file = tmpfile ();
if (file == NULL)
return errno;
/* make sure the mode is right */
fchmod (fileno (file), 0600);
#endif
/* set the body with the streams */
body = calloc (1, sizeof (*body));
if (body == NULL)
{
fclose (file);
return ENOMEM;
}
body->file = file;
body->owner = owner;
*pbody = body;
return 0;
}
static void
body_destroy (body_t *pbody, void *owner)
{
if (pbody && *pbody)
{
body_t body = *pbody;
if (body->owner == owner)
{
if (body->file)
fclose (body->file);
}
*pbody = NULL;
}
}
static int
message_read (stream_t is, char *buf, size_t buflen,
off_t off, size_t *pnread )
{
message_t msg;
size_t nread = 0;
stream_t his, bis;
size_t hread, hsize, bread, bsize;
if (is == NULL || (msg = is->owner) == NULL)
return EINVAL;
if (msg->body)
bsize = hsize = bread = hread = 0;
his = bis = NULL;
header_size (msg->header, &hsize);
body_size (msg->body, &bsize);
if ((size_t)off <= hsize)
{
body_t body = msg->body;
if (body->file)
header_get_stream (msg->header, &his);
stream_read (his, buf, buflen, off, &hread);
/* still room left for some body, .. a pun ;-) */
if ((buflen - hread) > 0)
{
/* we're not checking the error of fseek for some handlers
* like socket in those not make sense.
* FIXME: Alternative is to check fseeck and errno == EBADF
* if not a seekable stream.
*/
fseek (body->file, off, SEEK_SET);
nread = fread (buf, sizeof (char), buflen, body->file);
if (nread == 0)
{
if (ferror (body->file))
return errno;
/* clear the error for feof() */
clearerr (body->file);
}
/* errno set by fread()/fseek() ? */
body_get_stream (msg->body, &bis);
stream_read (bis, buf + hread, buflen - hread, 0, &bread);
}
else
return EINVAL;
}
else
{
body_get_stream (msg->body, &bis);
stream_read (bis, buf, buflen, off - hsize, &bread);
}
if (pnread)
*pnread = nread;
*pnread = hread + bread;
return 0;
}
......@@ -529,47 +483,11 @@ message_write (stream_t os, const char *buf, size_t buflen,
off_t off, size_t *pnwrite)
{
message_t msg;
size_t nwrite = 0;
body_t body;
(void)buf; (void)buflen; (void)off; (void)pnwrite;
if (os == NULL || (msg = os->owner) == NULL)
return EINVAL;
/* Probably being lazy, then create a body for the stream */
if (msg->body == NULL)
{
int status = body_init (&body, msg);
if (status != 0 )
return status;
msg->body = body;
}
else
body = msg->body;
if (body->file)
{
/* we're not checking the error of fseek for some handlers
* like socket in those not make sense.
* FIXME: Alternative is to check fseeck and errno == EBADF
* if not a seekable stream.
*/
fseek (body->file, off, SEEK_SET);
nwrite = fwrite (buf, sizeof (char), buflen, body->file);
if (nwrite == 0)
{
if (ferror (body->file))
return errno;
/* clear the error for feof() */
clearerr (body->file);
}
/* errno set by fread()/fseek() ? */
}
else
return EINVAL;
if (pnwrite)
*pnwrite = nwrite;
return 0;
return ENOSYS;
}
static int
......@@ -577,6 +495,7 @@ message_get_fd (stream_t stream, int *pfd)
{
message_t msg;
body_t body;
stream_t is;
if (stream == NULL || (msg = stream->owner) == NULL)
return EINVAL;
......@@ -584,7 +503,7 @@ message_get_fd (stream_t stream, int *pfd)
/* Probably being lazy, then create a body for the stream */
if (msg->body == NULL)
{
int status = body_init (&body, msg);
int status = body_create (&body, msg);
if (status != 0 )
return status;
msg->body = body;
......@@ -592,8 +511,75 @@ message_get_fd (stream_t stream, int *pfd)
else
body = msg->body;
if (pfd)
*pfd = fileno (body->file);
body_get_stream (body, &is);
return stream_get_fd (is, pfd);
}
static int
extract_addr (const char *s, size_t n, char **presult, size_t *pnwrite)
{
char *p, *p1, *p2;
if (s == NULL || n == 0 || presult == NULL)
return EINVAL;
/* skip the double quotes */
p = memchr (s, '\"', n);
if (p != NULL)
{
p1 = memchr (s, '<', p - s);
p2 = memchr (s, '@', p - s);
if (p1 == NULL && p2 == NULL)
{
p1 = memchr (p + 1, '\"', n - ((p + 1) - s));
if (p1 != NULL)
{
n -= (p1 + 1) - s;
s = p1 + 1;
}
}
}
/* <name@hostname> ?? */
p = memchr (s, '<', n);
if (p != NULL)
{
p1 = memchr (p, '>', n - (p - s));
if (p1 != NULL && (p1 - p) > 1)
{
p2 = memchr (p, ' ', p1 - p);
if (p2 == NULL)
{
/* the NULL is already accounted for */
*presult = calloc (1, p1 - p);
if (*presult == NULL)
return ENOMEM;
memcpy (*presult, p + 1, (p1 - p) - 1);
if (pnwrite)
*pnwrite = (p1 - p) - 1;
return 0;
}
}
}
/* name@domain */
p = memchr (s, '@', n);
if (p != NULL)
{
p1 = p;
while (*p != ' ' && p != s)
p--;
while (*p1 != ' ' && p1 < (s + n))
p1++;
*presult = calloc (1, (p1 - p) + 1);
if (*presult == NULL)
return ENOMEM;
memcpy (*presult, p, p1 - p);
if (pnwrite)
*pnwrite = p1 - p;
return 0;
}
*presult = NULL;
return EINVAL;
return 0;
}
......
......@@ -19,6 +19,7 @@
#include <message0.h>
#include <mime0.h>
#include <io0.h>
#include <body0.h>
#include <mime.h>
#include <errno.h>
......@@ -37,17 +38,15 @@
* Define mbx i/f for protocols that support mime parsing (IMAP).
*/
static int _mime_append_part( mime_t mime, int body_offset, int body_len, int encap_msg )
static int _mime_append_part(mime_t mime, message_t msg, int body_offset, int body_len, int encap_msg)
{
struct _mime_part *mime_part, **part_arr;
int ret;
if ( ( mime_part = calloc(1, sizeof(*mime_part)) ) == NULL )
return ENOMEM;
if ( ( ret = header_init(&mime_part->hdr, mime->header_buf, mime->header_length, mime_part) ) != 0 ) {
free(mime_part);
return ret;
}
memcpy(mime_part->sig,"MIME", 4);
if ( encap_msg ) {
if ( mime->ncap_msgs >= mime->tmsgs ) {
if ( ( part_arr = realloc(mime->cap_msgs, ( mime->tmsgs + 2 ) * sizeof(mime_part)) ) == NULL ) {
......@@ -70,24 +69,31 @@ static int _mime_append_part( mime_t mime, int body_offset, int body_len, int en
}
mime->mtp_parts[mime->nmtp_parts++] = mime_part;
}
if ( msg == NULL ) {
if ( ( ret = header_create(&mime_part->hdr, mime->header_buf, mime->header_length, mime_part) ) != 0 ) {
free(mime_part);
return ret;
}
mime->header_length = 0;
}
mime_part->body_len = body_len;
mime_part->body_offset = body_offset;
mime_part->msg = msg;
mime_part->mime = mime;
mime->header_length = 0;
return 0;
}
static struct _mime_part *_mime_get_owner(mime_t mime, message_t msg)
{
int i;
for ( i = 0; i < mime->nmtp_parts; i++ ) {
if ( mime->mtp_parts[i] == msg->owner )
return mime->mtp_parts[i];
}
return NULL;
}
static char *_strltrim(char *str)
{
char *p;
......@@ -100,7 +106,7 @@ static char *_strltrim(char *str)
static char *_strttrim(char *str)
{
char *p;
for (p = str + strlen(str) - 1; isspace(*p) && p >= str; --p)
;
*++p = '\0';
......@@ -115,28 +121,28 @@ char *_strtrim(char *str);
|| ((c) == '@') || ((c) == ',') || ((c) == ';') || ((c) == ':') \
|| ((c) == '\\') || ((c) == '"') || ((c) == '.') || ((c) == '[') \
|| ((c) == ']') )
static void _mime_munge_content_header(char *field_body )
{
char *p, *e, *str = field_body;
int quoted = 0;
_strtrim(field_body);
if ( ( e = p = strchr(str, ';') ) == NULL )
return;
e++;
return;
e++;
while ( *e && isspace(*e) ) /* remove space upto param */
e++;
memmove(p+1, e, strlen(e)+1);
e = p+1;
while ( *e && *e != '=' ) /* find end of value */
e++;
e = p = e+1;
while ( *e && (quoted || !_ISSPECIAL(*e) || !isspace(*e) ) ) {
if ( *e == '\\' ) { /* escaped */
memmove(e, e+1, strlen(e)+2);
memmove(e, e+1, strlen(e)+2);
} else if ( *e == '\"' )
quoted = ~quoted;
e++;
......@@ -147,7 +153,7 @@ static char *_mime_get_param(char *field_body, const char *param, int *len)
{
char *str, *p, *v, *e;
int quoted = 0, was_quoted = 0;
if ( len == NULL || ( str = field_body ) == NULL )
return NULL;
......@@ -162,7 +168,7 @@ static char *_mime_get_param(char *field_body, const char *param, int *len)
if ( *e == '\"' )
quoted = ~quoted, was_quoted = 1;
else
(*len)++;
(*len)++;
e++;
}
if ( strncasecmp(p, param, strlen(param)) ) { /* no match jump to next */
......@@ -171,7 +177,7 @@ static char *_mime_get_param(char *field_body, const char *param, int *len)
}
else
return was_quoted ? v + 1 : v; /* return unquted value */
}
}
return NULL;
}
......@@ -205,11 +211,11 @@ static int _mime_parse_mpart_message(mime_t mime)
char *cp, *cp2;
int blength, body_length, body_offset, ret;
size_t nbytes;
if ( !(mime->flags & MIME_PARSER_ACTIVE) ) {
char *boundary;
int len;
if ( ( ret = _mime_setup_buffers(mime) ) != 0 )
return ret;
if ( ( boundary = _mime_get_param(mime->content_type, "boundary", &len) ) == NULL )
......@@ -217,7 +223,7 @@ static int _mime_parse_mpart_message(mime_t mime)
if ( ( mime->boundary = calloc(1, len + 1) ) == NULL )
return ENOMEM;
strncpy(mime->boundary, boundary, len );
mime->cur_offset = 0;
mime->line_ndx = 0;
mime->parser_state = MIME_STATE_SCAN_BOUNDARY;
......@@ -225,7 +231,7 @@ static int _mime_parse_mpart_message(mime_t mime)
}
body_length = mime->body_length;
body_offset = mime->body_offset;
while ( ( ret = stream_read(mime->stream, mime->cur_buf, mime->buf_size, mime->cur_offset, &nbytes) ) == 0 && nbytes ) {
cp = mime->cur_buf;
while ( nbytes ) {
......@@ -241,14 +247,14 @@ 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->line_ndx >= blength ) {
if ( ( !strncasecmp(cp2,"--", 2) && !strncasecmp(cp2+2, mime->boundary, 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;
if ( mime->header_length ) /* this skips the preamble */
_mime_append_part(mime, body_offset, body_length, FALSE );
if ( ( cp2 + blength + 2 < cp && !strncasecmp(cp2+2+blength, "--",2) ) ||
_mime_append_part(mime, NULL, body_offset, body_length, FALSE );
if ( ( cp2 + blength + 2 < cp && !strncasecmp(cp2+2+blength, "--",2) ) ||
!strncasecmp(cp2+blength, "--",2) ) { /* very last boundary */
break;
}
......@@ -256,7 +262,7 @@ static int _mime_parse_mpart_message(mime_t mime)
break;
}
}
mime->line_ndx = 0;
mime->line_ndx = 0;
mime->cur_line[0] = *cp; /* stay in this state but leave '\n' at begining */
break;
case MIME_STATE_HEADERS:
......@@ -265,7 +271,7 @@ static int _mime_parse_mpart_message(mime_t mime)
if ( mime->line_ndx == 1 || mime->cur_line[0] == '\r' ) {
mime->parser_state = MIME_STATE_BEGIN_LINE;
body_offset = mime->cur_offset + 1;
}
}
mime->line_ndx = -1;
break;
}
......@@ -278,12 +284,12 @@ static int _mime_parse_mpart_message(mime_t mime)
mime->cur_offset++;
nbytes--;
cp++;
}
}
if ( mime->flags & MIME_INCREAMENTAL_PARSER ) {
ret = EAGAIN;
break;
break;
}
}
}
mime->body_length = body_length;
mime->body_offset = body_offset;
if ( ret != EAGAIN ) { /* finished cleanup */
......@@ -297,7 +303,7 @@ static int _mime_message_read(stream_t stream, char *buf, size_t buflen, off_t o
{
struct _mime_part *mime_part = stream->owner;
size_t read_len;
if ( nbytes == NULL )
return(EINVAL);
......@@ -310,7 +316,26 @@ static int _mime_message_read(stream_t stream, char *buf, size_t buflen, off_t o
return stream_read(mime_part->mime->stream, buf, read_len, mime_part->body_offset + off, nbytes );
}
int mime_init(mime_t *pmime, message_t msg, int flags)
static int _mime_new_message_read(stream_t stream, char *buf, size_t buflen, off_t off, size_t *nbytes)
{
(void)stream; (void)buf; (void)buflen; (void)off;
if ( nbytes == NULL )
return(EINVAL);
return 0;
}
static int _mime_body_size (body_t body, size_t *psize)
{
struct _mime_part *mime_part = body->owner;
if (mime_part == NULL)
return EINVAL;
if (psize)
*psize = mime_part->body_len;
return 0;
}
int mime_create(mime_t *pmime, message_t msg, int flags)
{
mime_t mime = NULL;
int ret = 0;
......@@ -336,15 +361,12 @@ int mime_init(mime_t *pmime, message_t msg, int flags)
mime->msg = msg;
mime->buf_size = MIME_DFLT_BUF_SIZE;
message_get_stream(msg, &(mime->stream));
}
}
}
}
else { /* create a floating message to contain this new mime message */
if ( ( ret = message_init( &msg, NULL ) ) == 0 ) {
if ( ( ret = message_get_stream(msg, &(mime->stream)) ) == 0 ) {
msg->owner = mime;
mime->flags |= MIME_NEW_MESSAGE;
}
}
else {
if ( ( ret = message_create( &msg, mime ) ) == 0 ) {
mime->flags |= MIME_NEW_MESSAGE;
}
}
if ( ret != 0 ) {
......@@ -364,22 +386,22 @@ void mime_destroy(mime_t *pmime)
mime_t mime;
struct _mime_part *mime_part;
int i;
if (pmime && *pmime) {
mime = *pmime;
if ( mime->mtp_parts != NULL ) {
for ( i = 0; i < mime->nmtp_parts; i++ ) {
mime_part = mime->mtp_parts[i];
if ( mime_part->msg )
for ( i = 0; i < mime->nmtp_parts; i++ ) {
mime_part = mime->mtp_parts[i];
if ( mime_part->msg )
message_destroy(&mime_part->msg, mime_part);
else
header_destroy(&mime_part->hdr, mime_part);
}
}
if ( mime->cap_msgs != NULL ) {
for ( i = 0; i < mime->ncap_msgs; i++ ) {
mime_part = mime->cap_msgs[i];
if ( mime_part->msg )
for ( i = 0; i < mime->ncap_msgs; i++ ) {
mime_part = mime->cap_msgs[i];
if ( mime_part->msg )
message_destroy(&mime_part->msg, mime_part);
else
header_destroy(&mime_part->hdr, mime_part);
......@@ -391,7 +413,7 @@ void mime_destroy(mime_t *pmime)
free(mime->cur_buf);
if ( mime->cur_line )
free(mime->cur_line);
if ( mime->boundary )
if ( mime->boundary )
free(mime->boundary);
if ( mime->header_buf )
free(mime->header_buf);
......@@ -413,8 +435,9 @@ int mime_get_part(mime_t mime, int part, message_t *msg)
int nmtp_parts, ret = 0;
size_t hsize = 0;
stream_t stream;
body_t body;
struct _mime_part *mime_part;
if ( ( ret = mime_get_num_parts(mime, &nmtp_parts ) ) == 0 ) {
if ( part < 1 || part > nmtp_parts )
return EINVAL;
......@@ -422,18 +445,17 @@ int mime_get_part(mime_t mime, int part, message_t *msg)
*msg = mime->msg;
else {
mime_part = mime->mtp_parts[part-1];
if ( ( ret = message_init(&(mime_part->msg), mime_part) ) == 0 ) {
if ( ( ret = message_create(&(mime_part->msg), mime_part) ) == 0 ) {
message_set_header(mime_part->msg, mime_part->hdr, mime_part);
header_get_size(mime_part->hdr, &hsize);
message_set_size (mime_part->msg, mime_part->body_len + hsize, mime_part);
if ( ( ret = stream_init(&stream, mime_part) ) == 0 ) {
if ( ( ret = stream_set_read(stream, _mime_message_read, mime_part) ) == 0 ) {
if ( ( ret = message_set_stream( mime_part->msg, stream, mime_part) ) == 0 ) {
*msg = mime_part->msg;
return 0;
}
header_size(mime_part->hdr, &hsize);
if ( ( ret = body_create(&body, mime_part) ) == 0 ) {
if ( ( ret = stream_create(&stream, mime_part) ) == 0 ) {
body_set_size (body, _mime_body_size, mime_part);
stream_set_read(stream, _mime_message_read, mime_part);
body_set_stream(body, stream, mime_part);
*msg = mime_part->msg;
return 0;
}
stream_destroy(&stream, mime_part);
}
message_destroy(&mime_part->msg, mime_part);
}
......@@ -449,11 +471,12 @@ int mime_unencapsulate(mime_t mime, message_t msg, message_t *newmsg)
char *content_type, *cp;
header_t hdr;
stream_t stream;
body_t body;
struct _mime_part *mime_part;
if ( mime == NULL || msg == NULL || newmsg == NULL || mime->flags & MIME_NEW_MESSAGE )
return EINVAL;
if ( mime->msg != msg && ( mime_part = _mime_get_owner( mime, msg ) ) == NULL ) /* I don't know about or own this message */
return EPERM;
......@@ -493,21 +516,20 @@ int mime_unencapsulate(mime_t mime, message_t msg, message_t *newmsg)
}
body_length -= mime->cur_offset - body_offset;
body_offset = mime->cur_offset + 1;
if ( ( ret = _mime_append_part( mime, body_offset, body_length, TRUE ) ) == 0 ) {
if ( ( ret = _mime_append_part( mime, NULL, body_offset, body_length, TRUE ) ) == 0 ) {
mime_part = mime->cap_msgs[mime->ncap_msgs - 1];
if ( ( ret = message_init(&(mime_part->msg), mime_part) ) == 0) {
if ( ( ret = message_create(&(mime_part->msg), mime_part) ) == 0) {
message_set_header(mime_part->msg, mime_part->hdr, mime_part);
message_set_size (mime_part->msg, mime_part->body_len, mime_part);
if ( ( ret = stream_init(&stream, mime_part) ) == 0 ) {
if ( ( ret = stream_set_read(stream, _mime_message_read, mime_part) ) == 0 ) {
if ( ( ret = message_set_stream( mime_part->msg, stream, mime_part) ) == 0 ) {
*newmsg = mime_part->msg;
return 0;
}
if ( ( ret = body_create(&body, mime_part) ) == 0 ) {
if ( ( ret = stream_create(&stream, mime_part) ) == 0 ) {
stream_set_read(stream, _mime_message_read, mime_part);
body_set_size (body, _mime_body_size, mime_part);
body_set_stream( body, stream, mime_part);
*newmsg = mime_part->msg;
return 0;
}
stream_destroy(&stream, mime_part);
message_destroy(&mime_part->msg, mime_part);
}
message_destroy(&mime_part->msg, mime_part);
}
}
}
......@@ -515,13 +537,13 @@ int mime_unencapsulate(mime_t mime, message_t msg, message_t *newmsg)
}
}
}
return ret;
return ret;
}
int mime_get_num_parts(mime_t mime, int *nmtp_parts)
{
int ret = 0;
if ( mime->nmtp_parts == 0 || mime->flags & MIME_PARSER_ACTIVE ) {
if ( mime_is_multi_part(mime) ) {
if ( ( ret = _mime_parse_mpart_message(mime) ) != 0 )
......@@ -531,14 +553,14 @@ int mime_get_num_parts(mime_t mime, int *nmtp_parts)
}
*nmtp_parts = mime->nmtp_parts;
return(ret);
}
int mime_add_part(mime_t mime, message_t msg)
{
if ( mime == NULL || msg == NULL || ( mime->flags & MIME_NEW_MESSAGE ) == 0 )
return EINVAL;
return ENOTSUP;
return _mime_append_part(mime, msg, 0, 0, FALSE);
}
int mime_get_message(mime_t mime, message_t *msg)
......@@ -548,3 +570,4 @@ int mime_get_message(mime_t mime, message_t *msg)
*msg = mime->msg;
return 0;
}
......
......@@ -88,7 +88,7 @@ registrar_add (struct url_registrar *new_ureg,
return ENOMEM;
}
}
mreg->_init = new_mreg->_init;
mreg->_create = new_mreg->_create;
mreg->_destroy = new_mreg->_destroy;
/* URL */
......@@ -110,7 +110,7 @@ registrar_add (struct url_registrar *new_ureg,
return ENOMEM;
}
}
ureg->_init = new_ureg->_init;
ureg->_create = new_ureg->_create;
ureg->_destroy = new_ureg->_destroy;
}
......
......@@ -39,7 +39,7 @@ static int get_query (const url_t, char *, size_t, size_t *);
static int get_id (const url_t, int *);
int
url_init (url_t * purl, const char *name)
url_create (url_t * purl, const char *name)
{
int status = EINVAL;
struct url_registrar *ureg;
......@@ -87,7 +87,7 @@ url_init (url_t * purl, const char *name)
/* Found one initialize it */
if (status == 0)
{
status = ureg->_init (purl, name);
status = ureg->_create (purl, name);
if (status == 0)
{
url_t url = *purl;
......
......@@ -23,12 +23,12 @@
#include <string.h>
static void url_file_destroy (url_t *purl);
static int url_file_init (url_t *purl, const char *name);
static int url_file_create (url_t *purl, const char *name);
struct url_registrar _url_file_registrar =
{
"file:",
url_file_init, url_file_destroy
url_file_create, url_file_destroy
};
static void
......@@ -48,7 +48,7 @@ url_file_destroy (url_t *purl)
UNIX box
*/
static int
url_file_init (url_t *purl, const char *name)
url_file_create (url_t *purl, const char *name)
{
url_t url;
struct url_registrar *ureg = &_url_mbox_registrar;
......@@ -64,7 +64,7 @@ url_file_init (url_t *purl, const char *name)
return ENOMEM;
/* TYPE */
url->_init = ureg->_init;
url->_create = ureg->_create;
url->_destroy = ureg->_destroy;
/* SCHEME */
......
......@@ -19,13 +19,13 @@
#include <registrar.h>
#include <errno.h>
static int url_imap_init (url_t *purl, const char *name);
static int url_imap_create (url_t *purl, const char *name);
static void url_imap_destroy (url_t *purl);
struct url_registrar _url_imap_registrar =
{
"imap://",
url_imap_init, url_imap_destroy
url_imap_create, url_imap_destroy
};
static void
......@@ -36,7 +36,7 @@ url_imap_destroy (url_t *purl)
}
static int
url_imap_init (url_t *purl, const char *name)
url_imap_create (url_t *purl, const char *name)
{
(void)purl; (void)name;
return ENOSYS;
......
......@@ -19,13 +19,13 @@
#include <registrar.h>
#include <errno.h>
static int url_mailto_init (url_t *purl, const char *name);
static int url_mailto_create (url_t *purl, const char *name);
static void url_mailto_destroy (url_t *purl);
struct url_registrar _url_mailto_registrar =
{
"mailto:",
url_mailto_init, url_mailto_destroy
url_mailto_create, url_mailto_destroy
};
static void
......@@ -36,7 +36,7 @@ url_mailto_destroy (url_t *purl)
}
static int
url_mailto_init (url_t *purl, const char *name)
url_mailto_create (url_t *purl, const char *name)
{
(void)purl; (void)name;
return ENOSYS;
......
......@@ -23,12 +23,12 @@
#include <string.h>
static void url_mbox_destroy (url_t *purl);
static int url_mbox_init (url_t *purl, const char *name);
static int url_mbox_create (url_t *purl, const char *name);
struct url_registrar _url_mbox_registrar =
{
"/",
url_mbox_init, url_mbox_destroy
url_mbox_create, url_mbox_destroy
};
static void
......@@ -48,7 +48,7 @@ url_mbox_destroy (url_t *purl)
UNIX box
*/
static int
url_mbox_init (url_t *purl, const char *name)
url_mbox_create (url_t *purl, const char *name)
{
url_t url;
struct url_registrar *ureg = &_url_mbox_registrar;
......@@ -64,7 +64,7 @@ url_mbox_init (url_t *purl, const char *name)
return ENOMEM;
/* TYPE */
url->_init = ureg->_init;
url->_create = ureg->_create;
url->_destroy = ureg->_destroy;
/* SCHEME */
......
......@@ -23,12 +23,12 @@
#include <string.h>
static void url_maildir_destroy (url_t *purl);
static int url_maildir_init (url_t *purl, const char *name);
static int url_maildir_create (url_t *purl, const char *name);
struct url_registrar _url_maildir_registrar =
{
"maildir:",
url_maildir_init, url_maildir_destroy
url_maildir_create, url_maildir_destroy
};
static void
......@@ -49,7 +49,7 @@ url_maildir_destroy (url_t *purl)
maildir:
*/
static int
url_maildir_init (url_t *purl, const char *name)
url_maildir_create (url_t *purl, const char *name)
{
url_t url;
struct url_registrar *ureg = &_url_maildir_registrar;
......@@ -67,7 +67,7 @@ url_maildir_init (url_t *purl, const char *name)
return EINVAL;
/* TYPE */
url->_init = ureg->_init;
url->_create = ureg->_create;
url->_destroy = ureg->_destroy;
/* SCHEME */
......
......@@ -23,12 +23,12 @@
#include <string.h>
static void url_mh_destroy (url_t *purl);
static int url_mh_init (url_t *purl, const char *name);
static int url_mh_create (url_t *purl, const char *name);
struct url_registrar _url_mh_registrar =
{
"mh:",
url_mh_init, url_mh_destroy
url_mh_create, url_mh_destroy
};
static void
......@@ -49,7 +49,7 @@ url_mh_destroy (url_t *purl)
mh:
*/
static int
url_mh_init (url_t *purl, const char *name)
url_mh_create (url_t *purl, const char *name)
{
url_t url;
struct url_registrar *ureg = &_url_mh_registrar;
......@@ -67,7 +67,7 @@ url_mh_init (url_t *purl, const char *name)
return ENOMEM;
/* TYPE */
url->_init = ureg->_init;
url->_create = ureg->_create;
url->_destroy = ureg->_destroy;
/* SCHEME */
......
......@@ -23,12 +23,12 @@
#include <string.h>
static void url_mmdf_destroy (url_t *purl);
static int url_mmdf_init (url_t *purl, const char *name);
static int url_mmdf_create (url_t *purl, const char *name);
struct url_registrar _url_mmdf_registrar =
{
"mmdf:",
url_mmdf_init, url_mmdf_destroy
url_mmdf_create, url_mmdf_destroy
};
static void
......@@ -49,7 +49,7 @@ url_mmdf_destroy (url_t *purl)
mmdf:
*/
static int
url_mmdf_init (url_t *purl, const char *name)
url_mmdf_create (url_t *purl, const char *name)
{
url_t url;
struct url_registrar *ureg = &_url_mmdf_registrar;
......@@ -67,7 +67,7 @@ url_mmdf_init (url_t *purl, const char *name)
return ENOMEM;
/* TYPE */
url->_init = ureg->_init;
url->_create = ureg->_create;
url->_destroy = ureg->_destroy;
/* SCHEME */
......
......@@ -25,12 +25,12 @@
#include <errno.h>
static void url_pop_destroy (url_t *purl);
static int url_pop_init (url_t *purl, const char *name);
static int url_pop_create (url_t *purl, const char *name);
struct url_registrar _url_pop_registrar =
{
"pop://",
url_pop_init, url_pop_destroy
url_pop_create, url_pop_destroy
};
static int get_auth (const url_pop_t up, char *s, size_t len, size_t *);
......@@ -80,7 +80,7 @@ url_pop_destroy (url_t *purl)
pop://<user>;AUTH=<auth>@<host>:<port>
*/
static int
url_pop_init (url_t *purl, const char *name)
url_pop_create (url_t *purl, const char *name)
{
const char *host_port, *indexe;
struct url_registrar *ureg = &_url_pop_registrar;
......@@ -101,7 +101,7 @@ url_pop_init (url_t *purl, const char *name)
up->_get_auth = get_auth;
/* TYPE */
url->_init = _url_pop_registrar._init;
url->_create = _url_pop_registrar._create;
url->_destroy = _url_pop_registrar._destroy;
/* SCHEME */
......
......@@ -23,12 +23,12 @@
#include <string.h>
static void url_unix_destroy (url_t *purl);
static int url_unix_init (url_t *purl, const char *name);
static int url_unix_create (url_t *purl, const char *name);
struct url_registrar _url_unix_registrar =
{
"unix:",
url_unix_init, url_unix_destroy
url_unix_create, url_unix_destroy
};
static void
......@@ -49,7 +49,7 @@ url_unix_destroy (url_t *purl)
unix:/path
*/
static int
url_unix_init (url_t *purl, const char *name)
url_unix_create (url_t *purl, const char *name)
{
url_t url;
struct url_registrar *ureg = &_url_unix_registrar;
......@@ -67,7 +67,7 @@ url_unix_init (url_t *purl, const char *name)
return ENOMEM;
/* TYPE */
url->_init = ureg->_init;
url->_create = ureg->_create;
url->_destroy = ureg->_destroy;
/* SCHEME */
......