Commit e9cbb752 e9cbb752d119ef43246cd69de1352bdb0a7f7955 by Alain Magloire

This feature was put in to help the imap4d server, in this protocol

you can get a substring of the message starting from a certain offset.
To make the coding of imap4d simpler the complexity was move to the
library.  It is possible now by setting a property of the mailbox
to make it output rfc822 stream i.e. "\r\n" terminated stream, the
offset and the size are also in term of rfc822.
1 parent 898646b3
......@@ -29,6 +29,8 @@
#include <imap0.h>
#define PROP_RFC822 1
/* Variable use for the registrar. */
static struct _record _imap_record =
{
......@@ -222,7 +224,7 @@ folder_imap_open (folder_t folder, int flags)
url_get_host (folder->url, host, len + 1, NULL);
url_get_port (folder->url, &port);
folder->flags = flags | MU_STREAM_IMAP;
folder->flags = flags;
switch (f_imap->state)
{
......@@ -1579,7 +1581,9 @@ imap_readline (f_imap_t f_imap)
while (f_imap->nl == NULL);
/* Conversion \r\n --> \n\0 */
/* FIXME: We should use a property to enable or disable conversion. */
/**/
if (f_imap->selected == NULL
|| f_imap->selected->mailbox->properties[PROP_RFC822].value == 0)
if (f_imap->nl > f_imap->buffer)
{
*(f_imap->nl - 1) = '\n';
......
......@@ -40,17 +40,18 @@ static int fill_blurb __P ((header_t));
int
header_create (header_t *ph, const char *blurb, size_t len, void *owner)
{
header_t h;
header_t header;
int status = 0;
h = calloc (1, sizeof (*h));
if (h == NULL)
header = calloc (1, sizeof (*header));
if (header == NULL)
return ENOMEM;
h->owner = owner;
/* Ignore the return value. */
status = header_parse (h, blurb, len);
header->owner = owner;
*ph = h;
status = header_parse (header, blurb, len);
*ph = header;
return status;
}
......@@ -59,27 +60,37 @@ header_destroy (header_t *ph, void *owner)
{
if (ph && *ph)
{
header_t h = *ph;
header_t header = *ph;
/* Can we destroy ?. */
if (h->owner == owner)
if (header->owner == owner)
{
stream_destroy (&(header->stream), header);
if (header->hdr)
free (header->hdr);
if (header->blurb)
free (header->blurb);
/* Clean up the fast header cache. */
if (header->fhdr)
{
size_t i;
stream_destroy (&(h->stream), h);
if (h->hdr)
free (h->hdr);
if (h->blurb)
free (h->blurb);
for (i = 0; i < h->fhdr_count; i++)
{
if (h->fhdr[i].fn)
free (h->fhdr[i].fn);
if (h->fhdr[i].fv)
free (h->fhdr[i].fv);
}
if (h->fhdr)
free (h->fhdr);
free (h);
for (i = 0; i < header->fhdr_count; i++)
{
if (header->fhdr[i].fn)
free (header->fhdr[i].fn);
if (header->fhdr[i].fv)
free (header->fhdr[i].fv);
}
free (header->fhdr);
}
if (header->property)
property_destroy (&(header->property), header);
free (header);
}
*ph = NULL;
}
......@@ -142,9 +153,9 @@ header_parse (header_t header, const char *blurb, int len)
{
char *fn, *fn_end, *fv, *fv_end;
if (header_start[0] == ' ' ||
header_start[0] == '\t' ||
header_start[0]== '\n')
if (header_start[0] == ' '
|| header_start[0] == '\t'
|| header_start[0] == '\n')
break;
/* Second loop extract one header field. */
......@@ -245,13 +256,13 @@ header_set_value (header_t header, const char *fn, const char *fv, int replace)
/* Easy approach: if replace, overwrite the field-{name,value} and readjust
the pointers by calling header_parse () this is wastefull, we're just
fragmenting the memory it can be done better. But that may imply a
rewite of the headers So for another day. */
rewite of the headers ... for another day. */
if (replace)
{
size_t name_len;
size_t i;
size_t fn_len;
size_t fv_len;
size_t fn_len; /* Field Name len. */
size_t fv_len; /* Field Value len. */
len = header->blurb_len;
for (name_len = strlen (fn), i = 0; i < header->hdr_count; i++)
{
......@@ -401,7 +412,8 @@ header_get_value (header_t header, const char *name, char *buffer,
size_t i = 0;
size_t name_len;
size_t total = 0, fn_len = 0, fv_len = 0;
int threshold;
size_t threshold;
int rfc822 = 0;
int err = 0;
if (header == NULL || name == NULL)
......@@ -444,6 +456,10 @@ header_get_value (header_t header, const char *name, char *buffer,
return err;
}
/* Do they want rfc822 format */
if (header->property)
rfc822 = property_is_set (header->property, "RFC822");
/* We set the threshold to be 1 less for the null. */
threshold = --buflen;
......@@ -464,20 +480,29 @@ header_get_value (header_t header, const char *name, char *buffer,
/* Can everything fit in the buffer. */
if (buffer && threshold > 0)
{
threshold -= fv_len;
if (threshold >= 0)
buflen = (fv_len < threshold) ? fv_len : threshold;
if (rfc822)
{
memcpy (buffer, header->hdr[i].fv, fv_len);
buffer += fv_len;
}
else if (threshold < 0)
/* Convert to \r\n */
char *s = header->hdr[i].fv;
size_t j;
for (j = 0; j < buflen; s++, j++)
{
threshold += fv_len;
memcpy (buffer, header->hdr[i].fv, threshold);
buffer += threshold;
threshold = 0;
if (*s == '\n')
{
buffer[j] = '\r';
/* Side effect. */
if (++j >= buflen)
break;
}
buffer[j] = *s;
}
}
else
memcpy (buffer, header->hdr[i].fv, buflen);
buffer += buflen;
threshold -= buflen;
}
}
}
if (buffer)
......@@ -659,9 +684,30 @@ header_size (header_t header, size_t *psize)
}
int
header_set_property (header_t header, property_t property, void *owner)
{
if (header == NULL)
return EINVAL;
if (header->owner != owner)
return EACCES;
property_destroy (&(header->property), header);
header->property = property;
return 0;
}
int
header_get_property (header_t header, property_t *pp)
{
if (header == NULL || pp == NULL)
return EINVAL;
*pp = header->property;
return 0;
}
int
header_set_get_fvalue (header_t header, int (*_get_fvalue)
__P ((header_t, const char *, char *, size_t, size_t *)),
void *owner)
__P ((header_t, const char *, char *, size_t,
size_t *)), void *owner)
{
if (header == NULL)
return EINVAL;
......@@ -746,7 +792,14 @@ fill_blurb (header_t header)
free (header->fhdr);
header->fhdr = NULL;
}
/* The entire header is now ours(part of header_t), clear all the
overloading. */
header->_get_fvalue = NULL;
header->_get_value = NULL;
header->_set_value = NULL;
header->_size = NULL;
header->_lines = NULL;
do
{
......@@ -811,12 +864,20 @@ header_write (stream_t os, const char *buf, size_t buflen,
static int
header_read (stream_t is, char *buf, size_t buflen, off_t off, size_t *pnread)
{
header_t header = stream_get_owner (is);
int len;
header_t header = stream_get_owner (is);
int rfc822 = 0;
if (is == NULL || header == NULL)
return EINVAL;
if (buf == NULL || buflen == 0)
{
if (pnread)
*pnread = 0;
return 0;
}
/* Try to fill out the buffer, if we know how. */
if (header->blurb == NULL)
{
......@@ -825,17 +886,53 @@ header_read (stream_t is, char *buf, size_t buflen, off_t off, size_t *pnread)
return err;
}
if (header->property)
rfc822 = property_is_set (header->property, "RFC822");
if (rfc822)
{
size_t j;
int residue = 0;
char *s = header->blurb;
char *e = header->blurb + header->blurb_len;
/* Get to the offset. */
for (j = 0; j < (size_t)off && s <= e; j++, s++)
{
if (*s == '\n')
{
if (++j >= (size_t)off)
{
residue = 1;
break;
}
}
}
if (residue)
buf[0] = '\r';
/* Copy. */
for (j = residue ; j < buflen && s <= e; j++, s++)
{
if (*s == '\n')
{
buf[j] = '\r';
if (++j >= buflen)
break;
}
buf[j] = *s;
}
len = j;
}
else
{
len = header->blurb_len - off;
if (len > 0)
{
if (buf)
{
len = (buflen < (size_t)len) ? buflen : len;
memcpy (buf, header->blurb + off, len);
}
}
else
len = 0;
}
if (pnread)
*pnread = len;
......@@ -845,8 +942,9 @@ header_read (stream_t is, char *buf, size_t buflen, off_t off, size_t *pnread)
static int
header_readline (stream_t is, char *buf, size_t buflen, off_t off, size_t *pn)
{
header_t header = stream_get_owner (is);
int len;
header_t header = stream_get_owner (is);
int rfc822 = 0;
if (is == NULL || header == NULL)
return EINVAL;
......@@ -866,24 +964,57 @@ header_readline (stream_t is, char *buf, size_t buflen, off_t off, size_t *pn)
return err;
}
if (header->property)
rfc822 = property_is_set (header->property, "RFC822");
buflen--; /* Space for the null. */
if (rfc822)
{
size_t j;
char *s = header->blurb;
char *e = header->blurb + header->blurb_len;
char *nl;
/* Get to the offset. */
for (j = 0; j < (size_t)off && s <= e; j++, s++)
{
if (*s == '\n')
{
if (++j >= (size_t)off)
break;
}
}
/* Copy. */
e = (nl = memchr (s, '\n', e - s)) ? nl : e;
for (j = 0 ; j < buflen && s <= e; j++, s++)
{
if (*s == '\n')
{
buf[j] = '\r';
if (++j >= buflen)
break;
}
buf[j] = *s;
}
len = j;
}
else
{
len = header->blurb_len - off;
if (len > 0)
{
char *nl = memchr (header->blurb + off, '\n', len);
if (nl)
len = nl - (header->blurb + off) + 1;
len = (buflen < (size_t)len) ? buflen : len;
memcpy (buf, header->blurb + off, len);
buf[len] = '\0';
}
else
len = 0;
}
if (pn)
*pn = len;
buf[len] = '\0';
return 0;
}
......
......@@ -17,6 +17,7 @@ mime0.h \
misc.h \
monitor0.h \
observer0.h \
property0.h \
registrar0.h \
stream0.h \
tcp0.h \
......
......@@ -64,6 +64,7 @@ struct _header
size_t fhdr_count;
struct _hdr *fhdr;
int flags;
property_t property;
/* Streams. */
stream_t stream;
......
......@@ -27,7 +27,6 @@
#include <mailutils/monitor.h>
#include <mailutils/mailbox.h>
#include <mailutils/folder.h>
#ifdef __cplusplus
extern "C" {
......@@ -49,6 +48,8 @@ struct _mailbox
ticket_t ticket;
authority_t authority;
property_t property;
struct property_list *properties;
size_t properties_count;
locker_t locker;
stream_t stream;
url_t url;
......
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Library General Public License as published by
......@@ -25,6 +25,7 @@
#include <sys/types.h>
#include <mailutils/mailer.h>
#include <mailutils/monitor.h>
#ifdef __cplusplus
extern "C" {
#endif
......@@ -60,6 +61,9 @@ struct _mailer
url_t url;
int flags;
monitor_t monitor;
property_t property;
struct property_list *properties;
size_t properties_count;
/* Pointer to the specific mailer data. */
void *data;
......
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001 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 _PROPERTY0_H
#define _PROPERTY0_H
#ifdef DMALLOC
# include <dmalloc.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <mailutils/property.h>
#include <mailutils/iterator.h>
#ifndef __P
#ifdef __STDC__
#define __P(args) args
#else
#define __P(args) ()
#endif
#endif /*__P */
#ifdef __cplusplus
extern "C" {
#endif
struct property_private
{
size_t hash;
int *address;
};
struct _property
{
void *owner;
list_t list;
};
#ifdef __cplusplus
}
#endif
#endif /* _PROPERTY0_H */
......@@ -54,7 +54,7 @@ struct _stream
/* Read space. */
off_t roff;
struct rbuffer rbuffer; /* The buffer (at least 1 byte, if !NULL) */
struct rbuffer rbuffer;
void (*_destroy) __P ((stream_t));
int (*_open) __P ((stream_t, const char *, int port, int flags));
......
......@@ -154,6 +154,9 @@ list_remove (list_t list, void *item)
return ENOENT;
}
/* FIXME: FIXME: FIXME: URGENT:
Every time we iterate through the loop to get the data, an easy
fix is to a an index to the current. */
int
list_get (list_t list, size_t index, void **pitem)
{
......
......@@ -27,10 +27,9 @@
#include <mailbox0.h>
/* The Mailbox Factory.
We create an iterator for the mailbox_register and see if any scheme
match, if not we check in the mailbox_manager register for a match.
Then we call the mailbox's >url_create() to parse the URL. Last
initiliaze the concrete mailbox. */
Create an iterator for registrar and see if any url scheme match,
Then we call the mailbox's url_create() to parse the URL. Last
initiliaze the concrete mailbox and folder. */
int
mailbox_create (mailbox_t *pmbox, const char *name)
{
......@@ -45,7 +44,7 @@ mailbox_create (mailbox_t *pmbox, const char *name)
if (pmbox == NULL)
return EINVAL;
/* Look in the mailbox_register, for a match */
/* Look in the registrar, for a match */
registrar_get_list (&list);
status = iterator_create (&iterator, list);
if (status != 0)
......@@ -137,15 +136,17 @@ mailbox_destroy (mailbox_t *pmbox)
observable_destroy (&(mbox->observable), mbox);
}
/* Call the concrete mailbox. */
/* Call the concrete mailbox _destroy method. So it can clean itself. */
if (mbox->_destroy)
mbox->_destroy (mbox);
monitor_wrlock (monitor);
/* Nuke the stream and close it */
/* Close the stream and nuke it */
if (mbox->stream)
{
/* FIXME: Is this right, should be the client responsabilty to
the stream? */
stream_close (mbox->stream);
stream_destroy (&(mbox->stream), mbox);
}
......@@ -168,6 +169,20 @@ mailbox_destroy (mailbox_t *pmbox)
if (mbox->folder)
folder_destroy (&(mbox->folder));
if (mbox->properties)
{
size_t i;
for (i = 0; i < mbox->properties_count; i++)
{
if (mbox->properties[i].key)
free (mbox->properties[i].key);
}
free (mbox->properties);
}
if (mbox->property)
property_destroy (&(mbox->property), mbox);
free (mbox);
*pmbox = NULL;
monitor_unlock (monitor);
......@@ -246,7 +261,7 @@ int
mailbox_is_updated (mailbox_t mbox)
{
if (mbox == NULL || mbox->_is_updated == NULL)
return 0;
return ENOSYS;
return mbox->_is_updated (mbox);
}
......@@ -254,7 +269,7 @@ int
mailbox_scan (mailbox_t mbox, size_t msgno, size_t *pcount)
{
if (mbox == NULL || mbox->_scan == NULL)
return 0;
return ENOSYS;
return mbox->_scan (mbox, msgno, pcount);
}
......@@ -262,7 +277,7 @@ int
mailbox_size (mailbox_t mbox, off_t *psize)
{
if (mbox == NULL || mbox->_size == NULL)
return 0;
return ENOSYS;
return mbox->_size (mbox, psize);
}
......@@ -270,7 +285,7 @@ int
mailbox_uidvalidity (mailbox_t mbox, unsigned long *pvalid)
{
if (mbox == NULL || mbox->_uidvalidity == NULL)
return 0;
return ENOSYS;
return mbox->_uidvalidity (mbox, pvalid);
}
......@@ -278,7 +293,7 @@ int
mailbox_uidnext (mailbox_t mbox, size_t *puidnext)
{
if (mbox == NULL || mbox->_uidnext == NULL)
return 0;
return ENOSYS;
return mbox->_uidnext (mbox, puidnext);
}
......@@ -308,6 +323,7 @@ mailbox_set_authority (mailbox_t mbox, authority_t authority)
{
if (mbox == NULL)
return EINVAL;
/* The authority is set on the folder if exist, not the mailbox. */
if (mbox->folder)
return folder_set_authority (mbox->folder, authority);
if (mbox->authority)
......@@ -321,6 +337,7 @@ mailbox_get_authority (mailbox_t mbox, authority_t *pauthority)
{
if (mbox == NULL || pauthority == NULL)
return EINVAL;
/* The authority is set on the folder if exist, not the mailbox. */
if (mbox->folder)
return folder_get_authority (mbox->folder, pauthority);
*pauthority = mbox->authority;
......@@ -332,6 +349,7 @@ mailbox_set_ticket (mailbox_t mbox, ticket_t ticket)
{
if (mbox == NULL)
return EINVAL;
/* The ticket is set on the folder if exist, not the mailbox. */
if (mbox->folder)
return folder_set_ticket (mbox->folder, ticket);
if (mbox->ticket)
......@@ -345,6 +363,7 @@ mailbox_get_ticket (mailbox_t mbox, ticket_t *pticket)
{
if (mbox == NULL || pticket == NULL)
return EINVAL;
/* The ticket is set on the folder if exist, not the mailbox. */
if (mbox->folder)
return folder_get_ticket (mbox->folder, pticket);
*pticket = mbox->ticket;
......@@ -356,6 +375,7 @@ mailbox_set_stream (mailbox_t mbox, stream_t stream)
{
if (mbox == NULL)
return EINVAL;
/* The stream is set on the folder if exist, not the mailbox. */
if (mbox->folder)
return folder_set_stream (mbox->folder, stream);
if (mbox->stream)
......@@ -369,6 +389,7 @@ mailbox_get_stream (mailbox_t mbox, stream_t *pstream)
{
if (mbox == NULL || pstream)
return EINVAL;
/* The stream is set on the folder if exist, not the mailbox. */
if (mbox->folder)
return folder_get_stream (mbox->folder, pstream);
*pstream = mbox->stream;
......@@ -398,18 +419,28 @@ mailbox_get_property (mailbox_t mbox, property_t *pproperty)
return EINVAL;
if (mbox->property == NULL)
{
int status;
if (mbox->_get_property)
return mbox->_get_property (mbox, pproperty);
status = property_create (&(mbox->property), mbox);
size_t i;
int status = property_create (&(mbox->property), mbox);
if (status != 0)
return status;
/* Add the defaults. */
for (i = 0; i < mbox->properties_count; i++)
{
status = property_add_default (mbox->property,
mbox->properties[i].key,
&(mbox->properties[i].value),
mbox);
if (status != 0)
{
property_destroy (&(mbox->property), mbox);
return status;
}
}
}
*pproperty = mbox->property;
return 0;
}
int
mailbox_set_debug (mailbox_t mbox, debug_t debug)
{
......
......@@ -118,7 +118,8 @@ mailer_destroy (mailer_t *pmailer)
observable_notify (mailer->observable, MU_EVT_MAILER_DESTROY);
observable_destroy (&(mailer->observable), mailer);
}
/* Call the object. */
/* Call the object destructor. */
if (mailer->_destroy)
mailer->_destroy (mailer);
......@@ -126,14 +127,31 @@ mailer_destroy (mailer_t *pmailer)
if (mailer->stream)
{
/* FIXME: Should we close this? */
stream_close (mailer->stream);
stream_destroy (&(mailer->stream), mailer);
}
if (mailer->url)
url_destroy (&(mailer->url));
if (mailer->debug)
debug_destroy (&(mailer->debug), mailer);
if (mailer->properties)
{
size_t i;
for (i = 0; i < mailer->properties_count; i++)
{
if (mailer->properties[i].key)
free (mailer->properties[i].key);
}
free (mailer->properties);
}
if (mailer->property)
property_destroy (&(mailer->property), mailer);
free (mailer);
*pmailer = NULL;
monitor_unlock (monitor);
......@@ -206,6 +224,35 @@ mailer_get_observable (mailer_t mailer, observable_t *pobservable)
}
int
mailer_get_property (mailer_t mailer, property_t *pproperty)
{
if (mailer == NULL || pproperty == NULL)
return EINVAL;
if (mailer->property == NULL)
{
size_t i;
int status = property_create (&(mailer->property), mailer);
if (status != 0)
return status;
/* Add the defaults. */
for (i = 0; i < mailer->properties_count; i++)
{
status = property_add_default (mailer->property,
mailer->properties[i].key,
&(mailer->properties[i].value),
mailer);
if (status != 0)
{
property_destroy (&(mailer->property), mailer);
return status;
}
}
}
*pproperty = mailer->property;
return 0;
}
int
mailer_set_debug (mailer_t mailer, debug_t debug)
{
if (mailer == NULL)
......
......@@ -144,6 +144,15 @@ _mailbox_imap_init (mailbox_t mailbox)
/* maibox back pointer. */
m_imap->mailbox = mailbox;
/* Set our properties. */
mailbox->properties = calloc (2, sizeof (*(mailbox->properties)));
if (mailbox->properties == NULL)
return ENOMEM;
mailbox->properties_count = 2;
mailbox->properties[0].key = strdup ("IMAP4");
mailbox->properties[0].value = 1;
mailbox->properties[1].key = strdup ("RFC822");
mailbox->properties[1].value = 0;
return 0;
}
......
......@@ -47,6 +47,10 @@
#include <mailbox0.h>
/* See porperties in _init. */
#define PROP_TYPE 0
#define PROP_RFC822 1
#define ATTRIBUTE_IS_DELETED(flag) (flag & MU_ATTRIBUTE_DELETED)
#define ATTRIBUTE_IS_EQUAL(flag1, flag2) (flag1 == flag2)
......@@ -96,33 +100,37 @@ const char *fhdr_table[] =
"X-UIDL"
};
/* Keep the positions of where the headers and bodies start and end.
/* Keep the file positions of where the headers and bodies start and end.
attr_flags is the "Status:" message. */
struct _mbox_message
{
/* Offset of the parts of the messages in the mailbox. */
/* Offset of the messages in the mailbox. */
off_t header_from;
off_t header_from_end;
off_t body;
off_t body_end;
/* Fast header retrieve, we save here the most common header. This will
speed the header search. The entire headers are copied when modified
/* Save the offset for rfc822 format. */
struct _rfc822
{
off_t r_offset;
off_t f_offset;
int residue;
} rfc822;
/* Fast header retrieve, we save here the most common headers. This will
speed the header search. The entire headers are copied, when modified,
by the header_t object, we do not have to worry about updating them. */
char *fhdr[HDRSIZE];
/* IMAP uid. */
size_t uid;
size_t uid; /* IMAP uid. */
/* The attr_flags contains the "Status:" attribute */
int attr_flags;
int attr_flags; /* The attr_flags contains the "Status:" attribute */
size_t header_lines;
size_t body_lines;
stream_t stream;
/* A message attach to it. */
message_t message;
message_t message; /* A message attach to it. */
mbox_data_t mud; /* Back pointer. */
};
......@@ -136,8 +144,7 @@ struct _mbox_data
mbox_message_t *umessages; /* Array. */
size_t umessages_count; /* How big is the umessages[]. */
size_t messages_count; /* How many valid entry in umessages[]. */
stream_t stream;
off_t size;
off_t size; /* Size of the mailbox. */
unsigned long uidvalidity;
size_t uidnext;
char *name;
......@@ -153,7 +160,6 @@ struct _mbox_data
char *sender;
char *date;
off_t off;
property_t property;
mailbox_t mailbox; /* Back pointer. */
};
......@@ -172,7 +178,6 @@ static int mbox_uidnext __P ((mailbox_t, size_t *));
static int mbox_scan __P ((mailbox_t, size_t, size_t *));
static int mbox_is_updated __P ((mailbox_t));
static int mbox_size __P ((mailbox_t, off_t *));
static int mbox_get_property __P ((mailbox_t, property_t *));
/* private stuff */
static int mbox_scan0 __P ((mailbox_t, size_t, size_t *, int));
......@@ -181,8 +186,6 @@ static int mbox_append_message0 __P ((mailbox_t, message_t, off_t *,
static int mbox_message_uid __P ((message_t, size_t *));
static int mbox_header_fill __P ((header_t, char *, size_t, off_t,
size_t *));
static int mbox_get_header_readstream __P ((message_t, char *, size_t, off_t,
size_t *, int));
static int mbox_get_body_fd __P ((stream_t, int *));
static int mbox_get_fd __P ((mbox_message_t, int *));
static int mbox_get_attr_flags __P ((attribute_t, int *));
......@@ -192,8 +195,13 @@ static int mbox_body_read __P ((stream_t, char *, size_t, off_t,
size_t *));
static int mbox_body_readline __P ((stream_t, char *, size_t, off_t,
size_t *));
static int mbox_body_readstream __P ((stream_t, char *, size_t, off_t,
size_t *, int));
static int mbox_readstream_rfc822 __P ((mbox_message_t, char *, size_t,
off_t, size_t *, int, off_t,
off_t));
static int mbox_readstream __P ((mbox_message_t, char *, size_t,
off_t, size_t *, int, off_t,
off_t));
static int mbox_header_size __P ((header_t, size_t *));
static int mbox_header_lines __P ((header_t, size_t *));
static int mbox_body_size __P ((body_t, size_t *));
......@@ -228,7 +236,7 @@ _mailbox_mbox_init (mailbox_t mailbox)
/* Back pointer. */
mud->mailbox = mailbox;
/* Copy the name.
/* Copy the name:
We do not do any further interpretation after the scheme "mbox:"
Because for example on distributed system like QnX4 a file name is
//390/etc/passwd. So the best approach is to let the OS handle it
......@@ -269,7 +277,15 @@ _mailbox_mbox_init (mailbox_t mailbox)
mailbox->_size = mbox_size;
mailbox->_get_property = mbox_get_property;
/* Set our properties. */
mailbox->properties = calloc (2, sizeof (*(mailbox->properties)));
if (mailbox->properties == NULL)
return ENOMEM;
mailbox->properties_count = 2;
mailbox->properties[0].key = strdup ("MBOX");
mailbox->properties[0].value = 1;
mailbox->properties[1].key = strdup ("RFC822");
mailbox->properties[1].value = 0;
MAILBOX_DEBUG1 (mailbox, MU_DEBUG_TRACE, "mbox_init(%s)\n", mud->name);
return 0; /* okdoke */
......@@ -320,7 +336,7 @@ mbox_open (mailbox_t mailbox, int flags)
if (mud == NULL)
return EINVAL;
mailbox->flags = flags | MU_STREAM_FILE;
mailbox->flags = flags;
/* Get a stream. */
if (mailbox->stream == NULL)
......@@ -329,7 +345,7 @@ mbox_open (mailbox_t mailbox, int flags)
status = (flags & MU_STREAM_CREAT)
|| (mailbox->flags & MU_STREAM_APPEND);
/* Try to mmap() the file first. */
/* Try to mmap () the file first. */
if (status == 0)
{
status = mapfile_stream_create (&(mailbox->stream));
......@@ -928,7 +944,7 @@ mbox_get_fd (mbox_message_t mum, int *pfd)
int status;
if (mum == NULL)
return EINVAL;
status = stream_get_fd (mum->stream, pfd);
status = stream_get_fd (mum->mud->mailbox->stream, pfd);
return status;
}
......@@ -970,67 +986,130 @@ mbox_unset_attr_flags (attribute_t attr, int flags)
}
static int
mbox_property_set_value (property_t property, const char *k, const void *v)
mbox_body_readline (stream_t is, char *buffer, size_t buflen,
off_t off, size_t *pnread)
{
mailbox_t mbox = property_get_owner (property);
mbox_data_t mud = mbox->data;
return property_set_value (mud->property, k, v);
body_t body = stream_get_owner (is);
message_t msg = body_get_owner (body);
mbox_message_t mum = message_get_owner (msg);
if (mum->mud->mailbox->properties[PROP_RFC822].value)
return mbox_readstream_rfc822 (mum, buffer, buflen, off, pnread, 1,
mum->body, mum->body_end);
else
return mbox_readstream (mum, buffer, buflen, off, pnread, 1,
mum->body, mum->body_end);
}
static int
mbox_property_get_value (property_t property, const char *k, void **v)
mbox_body_read (stream_t is, char *buffer, size_t buflen,
off_t off, size_t *pnread)
{
mailbox_t mbox = property_get_owner (property);
mbox_data_t mud = mbox->data;
return property_get_value (mud->property, k, v);
body_t body = stream_get_owner (is);
message_t msg = body_get_owner (body);
mbox_message_t mum = message_get_owner (msg);
if (mum->mud->mailbox->properties[PROP_RFC822].value)
return mbox_readstream_rfc822 (mum, buffer, buflen, off, pnread, 0,
mum->body, mum->body_end);
else
return mbox_readstream (mum, buffer, buflen, off, pnread, 0,
mum->body, mum->body_end);
}
static int
mbox_get_property (mailbox_t mbox, property_t *pprop)
mbox_readstream_rfc822 (mbox_message_t mum, char *buffer, size_t buflen,
off_t off, size_t *pnread, int isreadline,
off_t start, off_t end)
{
mbox_data_t mud = mbox->data;
int status = property_create (&(mbox->property), mbox);
size_t total = 0;
int status = 0;
if (isreadline)
buflen--;
/* Catch up i.e bring us to the current offset. */
if (mum->rfc822.r_offset != off)
{
mum->rfc822.r_offset = off - mum->body_lines;
mum->rfc822.residue = 0;
if (mum->rfc822.r_offset < 0)
mum->rfc822.r_offset = 0;
mum->rfc822.f_offset = mum->rfc822.r_offset;
while (mum->rfc822.r_offset < off)
{
char c;
size_t n = 0;
status = stream_read (mum->mud->mailbox->stream, &c, 1,
mum->rfc822.f_offset, &n);
if (status != 0)
return status;
status = property_create (&(mud->property), mud);
if (status != 0)
if (n == 0)
break;
if (c == '\n')
{
mum->rfc822.r_offset++;
if (mum->rfc822.r_offset == off)
{
property_destroy (&(mbox->property), mbox);
mum->rfc822.residue = 1;
break;
}
}
mum->rfc822.r_offset++;
mum->rfc822.f_offset++;
}
}
do
{
size_t nread = 0;
status = mbox_readstream (mum, buffer, buflen, mum->rfc822.f_offset,
&nread, 1, start, end);
if (status != 0)
return status;
if (nread == 0)
break;
mum->rfc822.f_offset += nread;
mum->rfc822.r_offset += nread;
total += nread;
buflen -= nread;
if (buffer[nread - 1] == '\n')
{
if (!mum->rfc822.residue)
{
buffer[nread - 1] = '\r';
if (buflen == 0)
{
mum->rfc822.residue = 1;
break;
}
property_set_set_value (mbox->property, mbox_property_set_value, mbox);
property_set_get_value (mbox->property, mbox_property_get_value, mbox);
*pprop = mbox->property;
return 0;
}
buffer[nread] = '\n';
buflen--;
nread++;
total++;
mum->rfc822.r_offset++;
}
else
mum->rfc822.residue = 0;
}
buffer += nread;
} while (buflen > 0 || !isreadline);
static int
mbox_body_readline (stream_t is, char *buffer, size_t buflen,
off_t off, size_t *pnread)
{
return mbox_body_readstream (is, buffer, buflen, off, pnread, 1);
}
if (isreadline)
*buffer = '\0';
static int
mbox_body_read (stream_t is, char *buffer, size_t buflen,
off_t off, size_t *pnread)
{
return mbox_body_readstream (is, buffer, buflen, off, pnread, 0);
if (pnread)
*pnread = total;
return status;
}
static int
mbox_body_readstream (stream_t is, char *buffer, size_t buflen,
off_t off, size_t *pnread, int isreadline)
mbox_readstream (mbox_message_t mum, char *buffer, size_t buflen,
off_t off, size_t *pnread, int isreadline,
off_t start, off_t end)
{
body_t body = stream_get_owner (is);
message_t msg = body_get_owner (body);
mbox_message_t mum = message_get_owner (msg);
size_t nread = 0;
int status = 0;
if (mum == NULL)
return EINVAL;
if (buffer == NULL || buflen == 0)
{
if (pnread)
......@@ -1045,29 +1124,17 @@ mbox_body_readstream (stream_t is, char *buffer, size_t buflen,
pthread_cleanup_push (mbox_cleanup, (void *)mum->mud->mailbox);
#endif
{
off_t ln = mum->body_end - (mum->body + off);
off_t ln = end - (start + off);
if (ln > 0)
{
/* Position the file pointer and the buffer. */
nread = ((size_t)ln < buflen) ? ln : buflen;
if (isreadline)
{
status = stream_readline (mum->stream, buffer, buflen,
mum->body + off, &nread);
/* This mean we went pass the message boundary, technically it
should not be since we are reading by line, but just in case
truncate the string. */
if (nread > (size_t)ln)
{
buffer[ln] = '\0';
nread = ln;
}
}
status = stream_readline (mum->mud->mailbox->stream, buffer, buflen,
start + off, &nread);
else
{
nread = ((size_t)ln < buflen) ? ln : buflen;
status = stream_read (mum->stream, buffer, nread,
mum->body + off, &nread);
}
status = stream_read (mum->mud->mailbox->stream, buffer, nread,
start + off, &nread);
}
}
monitor_unlock (mum->mud->mailbox->monitor);
......@@ -1097,14 +1164,19 @@ mbox_header_fill (header_t header, char *buffer, size_t len,
mum->fhdr[j] = NULL;
}
}
return mbox_get_header_readstream (msg, buffer, len, off, pnread, 0);
if (mum->mud->mailbox->properties[PROP_RFC822].value)
return mbox_readstream_rfc822 (mum, buffer, len, off, pnread, 0,
mum->header_from_end, mum->body);
else
return mbox_readstream (mum, buffer, len, off, pnread, 0,
mum->header_from_end, mum->body);
}
static int
mbox_header_get_fvalue (header_t header, const char *name, char *buffer,
size_t buflen, size_t *pnread)
{
size_t i, fv_value = 0;
size_t i, fv_len = 0;
message_t msg = header_get_owner (header);
mbox_message_t mum = message_get_owner (msg);
int err = ENOENT;
......@@ -1114,13 +1186,34 @@ mbox_header_get_fvalue (header_t header, const char *name, char *buffer,
{
if (mum->fhdr[i])
{
fv_value = strlen (mum->fhdr[i]);
fv_len = strlen (mum->fhdr[i]);
if (buffer && buflen > 0)
{
/* For the null. */
buflen--;
fv_value = (fv_value < buflen) ? fv_value : buflen;
memcpy (buffer, mum->fhdr[i], fv_value);
buffer[fv_value] = '\0';
/* Convert to \r\n */
if (mum->mud->mailbox->properties[PROP_RFC822].value)
{
char *s = mum->fhdr[i];
for (fv_len = 0; *s && fv_len < buflen;
s++, fv_len++)
{
if (*s == '\n')
{
buffer[fv_len] = '\r';
/* Side effect. */
if (++fv_len >= buflen)
break;
}
buffer[fv_len] = *s;
}
}
else
{
fv_len = (fv_len < buflen) ? fv_len : buflen;
memcpy (buffer, mum->fhdr[i], fv_len);
}
buffer[fv_len] = '\0';
}
err = 0;
}
......@@ -1131,49 +1224,11 @@ mbox_header_get_fvalue (header_t header, const char *name, char *buffer,
}
if (pnread)
*pnread = fv_value;
*pnread = fv_len;
return err;
}
static int
mbox_get_header_readstream (message_t msg, char *buffer, size_t len,
off_t off, size_t *pnread, int isreadline)
{
mbox_message_t mum = message_get_owner (msg);
size_t nread = 0;
int status = 0;
off_t ln;
if (mum == NULL)
return EINVAL;
monitor_rdlock (mum->mud->mailbox->monitor);
#ifdef WITH_PTHREAD
/* read() is cancellation point since we're doing a potentially
long operation. Lets make sure we clean the state. */
pthread_cleanup_push (mbox_cleanup, (void *)mum->mud->mailbox);
#endif
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. */
status = (isreadline) ?
stream_readline (mum->stream, buffer, nread,
mum->header_from_end + off, &nread) :
stream_read (mum->stream, buffer, nread,
mum->header_from_end + off, &nread);
}
monitor_unlock (mum->mud->mailbox->monitor);
#ifdef WITH_PTHREAD
pthread_cleanup_pop (0);
#endif
if (pnread)
*pnread = nread;
return status;
}
static int
mbox_header_size (header_t header, size_t *psize)
{
message_t msg = header_get_owner (header);
......@@ -1181,7 +1236,11 @@ mbox_header_size (header_t header, size_t *psize)
if (mum == NULL)
return EINVAL;
if (psize)
{
*psize = mum->body - mum->header_from_end;
if (mum->mud->mailbox->properties[PROP_RFC822].value)
*psize += mum->header_lines;
}
return 0;
}
......@@ -1205,7 +1264,11 @@ mbox_body_size (body_t body, size_t *psize)
if (mum == NULL)
return EINVAL;
if (psize)
{
*psize = mum->body_end - mum->body + 1;
if (mum->mud->mailbox->properties[PROP_RFC822].value)
*psize += mum->body_lines;
}
return 0;
}
......@@ -1235,7 +1298,7 @@ mbox_envelope_date (envelope_t envelope, char *buf, size_t len,
if (mum == NULL)
return EINVAL;
status = stream_readline (mum->stream, buffer, sizeof(buffer),
status = stream_readline (mum->mud->mailbox->stream, buffer, sizeof(buffer),
mum->header_from, &n);
if (status != 0)
{
......@@ -1279,7 +1342,7 @@ mbox_envelope_sender (envelope_t envelope, char *buf, size_t len,
if (mum == NULL)
return EINVAL;
status = stream_readline (mum->stream, buffer, sizeof(buffer),
status = stream_readline (mum->mud->mailbox->stream, buffer, sizeof(buffer),
mum->header_from, &n);
if (status != 0)
{
......@@ -1358,12 +1421,16 @@ mbox_get_message (mailbox_t mailbox, size_t msgno, message_t *pmsg)
/* Set the header. */
{
header_t header = NULL;
property_t property = NULL;
status = header_create (&header, NULL, 0, msg);
if (status != 0)
{
message_destroy (&msg, mum);
return status;
}
/* Force the mailbox to register the properties. */
mailbox_get_property (mailbox, &property);
header_set_property (header, property, msg);
header_set_fill (header, mbox_header_fill, msg);
header_set_get_fvalue (header, mbox_header_get_fvalue, msg);
header_set_size (header, mbox_header_size, msg);
......
......@@ -639,7 +639,6 @@ mbox_scan0 (mailbox_t mailbox, size_t msgno, size_t *pcount, int do_notif)
ALLOCATE_MSGS(mailbox, mud);
mud->messages_count++;
mum = mud->umessages[mud->messages_count - 1];
mum->stream = mailbox->stream;
mum->mud = mud;
mum->header_from = total - n;
mum->header_from_end = total;
......
......@@ -38,6 +38,8 @@
#include <mailbox0.h>
#include <registrar0.h>
#define PROP_RFC822 1
/* Advance declarations. */
struct _pop_data;
struct _pop_message;
......@@ -292,6 +294,15 @@ _mailbox_pop_init (mailbox_t mbox)
mbox->_size = pop_size;
/* Properties. */
mbox->properties = calloc (2, sizeof (*(mbox->properties)));
if (mbox->properties == NULL)
return ENOMEM;
mbox->properties_count = 2;
mbox->properties[0].key = strdup ("POP3");
mbox->properties[0].value = 1;
mbox->properties[1].key = strdup ("RFC822");
mbox->properties[1].value = 0;
return 0; /* Okdoke. */
}
......@@ -460,7 +471,7 @@ pop_open (mailbox_t mbox, int flags)
url_get_host (mbox->url, host, hostlen + 1, NULL);
url_get_port (mbox->url, &port);
mbox->flags = flags | MU_STREAM_POP;
mbox->flags = flags;
CHECK_BUSY (mbox, mpd, func, 0);
......@@ -1844,7 +1855,9 @@ pop_readline (pop_data_t mpd)
mpd->nl = NULL;
}
}
/* \r\n --> \n\0 */
/* \r\n --> \n\0, conversion, If the propety is set no conversion
is done. */
if (mpd->mbox->properties[PROP_RFC822].value == 0)
if (mpd->nl > mpd->buffer)
{
*(mpd->nl - 1) = '\n';
......
......@@ -19,50 +19,22 @@
#include <config.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <property0.h>
#include <mailutils/property.h>
#include <mailutils/list.h>
#include <mailutils/iterator.h>
#ifdef DMALLOC
# include <dmalloc.h>
#endif
struct property_data
{
size_t hash;
const void *value;
};
struct _property
{
void *owner;
list_t list;
int (*_set_value) __P ((property_t , const char *, const void *));
int (*_get_value) __P ((property_t, const char *, void **));
};
static int property_find __P ((list_t, const char *, struct property_data **));
static size_t hash __P ((const char *));
static int property_find __P ((list_t, const char *, struct property_list **));
static int property_add __P ((property_t, const char *, int, int *));
static void property_update __P ((struct property_list *));
static size_t property_hash __P ((const char *));
int
property_create (property_t *pp, void *owner)
{
property_t prop;
int status;
if (pp == NULL)
return EINVAL;
prop = calloc (1, sizeof (*prop));
if (prop == NULL)
return ENOMEM;
status = list_create (&(prop->list));
if (status != 0)
{
free (prop);
return status;
}
prop->owner = owner;
*pp = prop;
return 0;
......@@ -76,7 +48,30 @@ property_destroy (property_t *pp, void *owner)
property_t prop = *pp;
if (prop->owner == owner)
{
/* Destroy the list and is properties. */
if (prop->list)
{
struct property_list *pl = NULL;
iterator_t iterator = NULL;
iterator_create (&iterator, prop->list);
for (iterator_first (iterator); !iterator_is_done (iterator);
iterator_next (iterator))
{
iterator_current (iterator, (void **)&pl);
if (pl)
{
if (pl->key)
free (pl->key);
if (pl->private_)
free (pl->private_);
free (pl);
}
}
iterator_destroy (&iterator);
list_destroy (&(prop->list));
}
free (prop);
}
*pp = NULL;
......@@ -90,148 +85,103 @@ property_get_owner (property_t prop)
}
int
property_set_set_value (property_t prop, int (*_set_value)
__P ((property_t , const char *, const void *)),
property_add_default (property_t prop, const char *key, int *address,
void *owner)
{
if (prop == NULL)
return EINVAL;
if (prop->owner != owner)
return EACCES;
prop->_set_value = _set_value;
return 0;
return property_add (prop, key, 0, address);
}
int
property_set_value (property_t prop, const char *key, const void *value)
property_set_value (property_t prop, const char *key, int value)
{
struct property_data *pd = NULL;
int status;
if (prop == NULL)
return EINVAL;
if (prop->_set_value)
return prop->_set_value (prop, key, value);
status = property_find (prop->list, key, &pd);
if (status != 0)
return status;
if (pd == NULL)
{
pd = calloc (1, sizeof (*pd));
if (pd == NULL)
return ENOMEM;
pd->hash = hash (key);
pd->value = (void *)value;
list_append (prop->list, (void *)pd);
}
else
pd->value = (void *)value;
return 0;
}
int
property_set_get_value (property_t prop, int (*_get_value)
__P ((property_t, const char *, void **)),
void *owner)
{
if (prop == NULL)
return EINVAL;
if (prop->owner != owner)
return EACCES;
prop->_get_value = _get_value;
return 0;
return property_add (prop, key, value, NULL);
}
int
property_get_value (property_t prop, const char *key, void **pvalue)
property_get_value (property_t prop, const char *key, int *pvalue)
{
struct property_data *pd = NULL;
struct property_list *pl = NULL;
int status;
if (prop == NULL)
return EINVAL;
if (prop->_get_value)
return prop->_get_value (prop, key, pvalue);
status = property_find (prop->list, key, &pd);
status = property_find (prop->list, key, &pl);
if (status != 0)
return status;
if (pd == NULL)
if (pl == NULL)
return ENOENT;
/* Update the value. */
property_update (pl);
if (pvalue)
*pvalue = (void *)pd->value;
*pvalue = pl->value;
return 0;
}
int
property_set (property_t prop, const char *k)
{
return property_set_int (prop, k, 1);
return property_set_value (prop, k, 1);
}
int
property_unset (property_t prop, const char *k)
{
return property_set_int (prop, k, 0);
int v = 0;
property_get_value (prop, k, &v);
if (v != 0)
return property_set_value (prop, k, 0);
return 0;
}
int
property_is_set (property_t prop, const char *k)
{
return property_get_int (prop, k);
int v = 0;
property_get_value (prop, k, &v);
return (v != 0);
}
int
property_set_int (property_t prop, const char *k, int i)
property_get_list (property_t prop, list_t *plist)
{
return property_set_value (prop, k, (void *)i);
}
int
property_get_int (property_t prop, const char *k)
{
int value = 0;
property_get_value (prop, k, (void **)&value);
return value;
}
struct property_list *pl = NULL;
iterator_t iterator = NULL;
int status;
int
property_set_long (property_t prop, const char *k, long l)
{
return property_set_value (prop, k, (const void *)l);
}
if (plist == NULL || prop == NULL)
return EINVAL;
long
property_get_long (property_t prop, const char *k)
{
long value = 0;
property_get_value (prop, k, (void **)&value);
return value;
}
status = iterator_create (&iterator, prop->list);
if (status != 0)
return status;
int
property_set_pointer (property_t prop, const char *k, void *p)
{
return property_set_value (prop, k, p);
}
/* Make sure the values are updated before passing it outside. */
for (iterator_first (iterator); !iterator_is_done (iterator);
iterator_next (iterator))
{
iterator_current (iterator, (void **)&pl);
if (pl)
property_update (pl);
}
iterator_destroy (&iterator);
void *
property_get_pointer (property_t prop, const char *k)
{
void *value = NULL;
property_get_value (prop, k, &value);
return value;
*plist = prop->list;
return 0;
}
/* Taking from an article in Dr Dobbs. */
static size_t
hash (const char *s)
property_hash (const char *s)
{
size_t hashval;
for (hashval = 0; *s != '\0' ; s++)
......@@ -246,30 +196,106 @@ hash (const char *s)
return hashval;
}
static void
property_update (struct property_list *pl)
{
/* Update the value. */
if (pl->private_)
{
struct property_private *private_ = pl->private_;
if (private_->address)
pl->value = *(private_->address);
}
}
static int
property_find (list_t list, const char *key, struct property_data **p)
property_find (list_t list, const char *key, struct property_list **p)
{
int status;
size_t h;
struct property_data *pd = NULL;
struct property_list *pl = NULL;
iterator_t iterator;
status = iterator_create (&iterator, list);
if (status != 0)
return status;
h = hash (key);
h = property_hash (key);
for (iterator_first (iterator); !iterator_is_done (iterator);
iterator_next (iterator))
{
iterator_current (iterator, (void **)&pd);
if (pd && pd->hash == h)
iterator_current (iterator, (void **)&pl);
if (pl)
{
struct property_private *private_ = pl->private_;
if (private_->hash == h)
if (strcasecmp (pl->key, key) == 0)
break;
}
pd = NULL;
pl = NULL;
}
iterator_destroy (&iterator);
*p = pd;
*p = pl;
return 0;
}
static int
property_add (property_t prop, const char *key, int value, int *address)
{
struct property_list *pl = NULL;
int status;
if (key == NULL)
return EINVAL;
if (prop->list == NULL)
{
status = list_create (&(prop->list));
if (status != 0)
return status;
}
status = property_find (prop->list, key, &pl);
if (status != 0)
return status;
/* None find create a new one. */
if (pl == NULL)
{
struct property_private *private_;
pl = calloc (1, sizeof (*pl));
if (pl == NULL)
return ENOMEM;
private_ = calloc (1, sizeof (*private_));
if (private_ == NULL)
{
free (pl);
return ENOMEM;
}
pl->key = strdup (key);
if (pl->key == NULL)
{
free (private_);
free (pl);
return ENOMEM;
}
pl->value = value;
private_->hash = property_hash (key);
private_->address = address;
pl->private_ = private_;
list_append (prop->list, (void *)pl);
}
else
{
struct property_private *private_ = pl->private_;
if (address)
private_->address = address;
else
{
if (private_->address)
*(private_->address) = value;
pl->value = value;
}
}
return 0;
}
......
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2001 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
......@@ -81,6 +81,13 @@ _mailer_sendmail_init (mailer_t mailer)
mailer->_close = sendmail_close;
mailer->_send_message = sendmail_send_message;
/* Set our properties. */
mailer->properties = calloc (1, sizeof (*(mailer->properties)));
if (mailer->properties == NULL)
return ENOMEM;
mailer->properties_count = 1;
mailer->properties[0].key = strdup ("SENDMAIL");
mailer->properties[0].value = 1;
return 0;
}
......@@ -109,7 +116,7 @@ sendmail_open (mailer_t mailer, int flags)
if (sendmail == NULL)
return EINVAL;
mailer->flags = flags | MU_STREAM_SENDMAIL;
mailer->flags = flags;
/* Fetch the mailer server name and the port in the url_t. */
if ((status = url_get_path (mailer->url, NULL, 0, &pathlen)) != 0
......
......@@ -159,6 +159,14 @@ _mailer_smtp_init (mailer_t mailer)
mailer->_close = smtp_close;
mailer->_send_message = smtp_send_message;
/* Set our properties. */
mailer->properties = calloc (1, sizeof (*(mailer->properties)));
if (mailer->properties == NULL)
return ENOMEM;
mailer->properties_count = 1;
mailer->properties[0].key = strdup ("SMTP");
mailer->properties[0].value = 1;
return 0;
}
......@@ -193,7 +201,7 @@ smtp_open (mailer_t mailer, int flags)
if (smtp == NULL)
return EINVAL;
mailer->flags = flags | MU_STREAM_SMTP;
mailer->flags = flags;
/* Fetch the mailer server name and the port in the url_t. */
if ((status = url_get_host (mailer->url, NULL, 0, &buf_len)) != 0
......