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,13 +1581,15 @@ 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->nl > f_imap->buffer)
{
*(f_imap->nl - 1) = '\n';
*(f_imap->nl) = '\0';
f_imap->ptr = f_imap->nl;
}
/**/
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';
*(f_imap->nl) = '\0';
f_imap->ptr = f_imap->nl;
}
return 0;
}
......
......@@ -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;
status = header_parse (header, blurb, len);
*ph = h;
*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)
{
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++)
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)
{
if (h->fhdr[i].fn)
free (h->fhdr[i].fn);
if (h->fhdr[i].fv)
free (h->fhdr[i].fv);
size_t i;
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 (h->fhdr)
free (h->fhdr);
free (h);
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,19 +480,28 @@ 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)
{
memcpy (buffer, header->hdr[i].fv, fv_len);
buffer += fv_len;
}
else if (threshold < 0)
buflen = (fv_len < threshold) ? fv_len : threshold;
if (rfc822)
{
threshold += fv_len;
memcpy (buffer, header->hdr[i].fv, threshold);
buffer += threshold;
threshold = 0;
/* Convert to \r\n */
char *s = header->hdr[i].fv;
size_t j;
for (j = 0; j < buflen; s++, j++)
{
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;
}
}
}
......@@ -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;
}
len = header->blurb_len - off;
if (len > 0)
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
{
if (buf)
len = header->blurb_len - off;
if (len > 0)
{
len = (buflen < (size_t)len) ? buflen : len;
memcpy (buf, header->blurb + off, len);
}
else
len = 0;
}
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. */
len = header->blurb_len - off;
if (len > 0)
if (rfc822)
{
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';
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 = 0;
{
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);
}
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
......@@ -38,8 +39,8 @@ extern "C" {
#endif /*__P */
// mailer states
#define MAILER_STATE_HDR 1
#define MAILER_STATE_MSG 2
#define MAILER_STATE_HDR 1
#define MAILER_STATE_MSG 2
#define MAILER_STATE_COMPLETE 3
// mailer messages
......@@ -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;
}
......
......@@ -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,12 +1855,14 @@ pop_readline (pop_data_t mpd)
mpd->nl = NULL;
}
}
/* \r\n --> \n\0 */
if (mpd->nl > mpd->buffer)
{
*(mpd->nl - 1) = '\n';
*(mpd->nl) = '\0';
mpd->ptr = mpd->nl;
}
/* \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';
*(mpd->nl) = '\0';
mpd->ptr = mpd->nl;
}
return 0;
}
......
......@@ -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)
{
list_destroy (&(prop->list));
/* 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 *)),
void *owner)
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)
{
break;
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
......