Commit f30fe5bf f30fe5bfa76d2631c1480ac31e487f23a03868a5 by Alain Magloire

Introduction of the notion of filter_t object takes a stream and

	perform some filtering on it.  All the decoding streams will move
	to this i.e. quoted-printable, base64 etc .. This scheme will also
	permit users to add to the list new filters.  Still work in progress.

	* mailbox/Makefile.am : Add filter.c filter_rfc822.c.
	* mailbox/body.c ( : When creating a floating body i.e creating
	a temporary file, the stream was not "own" by the body_t.
	(_body_get_fd): Likewised.
	(_body_read):_ Likewised.
	(_body_readline): Likewised.
	(_body_write): Likewised.
	(_body_truncate): Likewised.
	(_body_size): Likewised.
	(_body_flush): Likewised.

	* mailbox/folder_imap.c (imap_literal_string): Check if the
	callback.buffer is NULL.
	(imap_body): Do no set the callback.type if "FIELDS" is part of the
	string.

	* mailbox/header.c: Remove the support for RFC822 it will be part
	of the filter_t object.
	* mailbox/mbx_mbox.c: Likewised.
	* mailbox/mailbox.c (mailbox_size): Rename to mailbox_get_size().

	* mailbox/stream.c (stream_is_seekable): New function.
	(stream_set_property): New function.
	(stream_get_property): New function.

	* mailbox/trans_stream.c: Beautify.
1 parent 360bc51c
......@@ -20,6 +20,8 @@ body.c \
debug.c \
envelope.c \
file_stream.c \
filter.c \
filter_rfc822.c \
folder.c \
folder_imap.c \
folder_mbox.c \
......
......@@ -32,6 +32,13 @@
#include <body0.h>
static int lazy_create __P ((body_t));
static int _body_flush __P ((stream_t));
static int _body_get_fd __P ((stream_t, int *));
static int _body_read __P ((stream_t, char *, size_t, off_t, size_t *));
static int _body_readline __P ((stream_t, char *, size_t, off_t, size_t *));
static int _body_write __P ((stream_t, const char *, size_t, off_t, size_t *));
static int _body_truncate __P ((stream_t, off_t));
static int _body_size __P ((stream_t, off_t *));
int
body_create (body_t *pbody, void *owner)
......@@ -60,10 +67,23 @@ body_destroy (body_t *pbody, void *owner)
{
if (body->filename)
{
/* FIXME: should we do this? */
remove (body->filename);
free (body->filename);
}
stream_destroy (&(body->stream), body);
if (body->stream)
stream_destroy (&(body->stream), body);
if (body->fstream)
{
stream_close (body->fstream);
stream_destroy (&(body->fstream), NULL);
}
if (body->property)
property_destroy (&(body->property), body);
free (body);
}
*pbody = NULL;
......@@ -93,6 +113,33 @@ body_clear_modified (body_t body)
}
int
body_set_property (body_t body, property_t property, void *owner)
{
if (body == NULL)
return EINVAL;
if (body->owner != owner)
return EACCES;
property_destroy (&(body->property), body);
body->property = property;
return 0;
}
int
body_get_property (body_t body, property_t *pproperty)
{
if (body == NULL || pproperty == NULL)
return EINVAL;
if (body->property == NULL)
{
int status = property_create (&(body->property), body);
if (status != 0)
return status;
}
*pproperty = body->property;
return 0;
}
int
body_get_filename (body_t body, char *filename, size_t len, size_t *pn)
{
int n = 0;
......@@ -120,19 +167,27 @@ body_get_stream (body_t body, stream_t *pstream)
if (body->stream == NULL)
{
stream_t stream;
int fd;
int status = file_stream_create (&stream);
int status = stream_create (&(body->stream), MU_STREAM_RDWR, body);
if (status != 0)
return status;
status = file_stream_create (&(body->fstream));
if (status != 0)
return status;
fd = lazy_create (body);
if (fd == -1)
return errno;
status = stream_open (stream, body->filename, 0, MU_STREAM_RDWR);
status = stream_open (body->fstream, body->filename, 0, MU_STREAM_RDWR);
close (fd);
if (status != 0)
return status;
body->stream = stream;
stream_set_fd (body->stream, _body_get_fd, body);
stream_set_read (body->stream, _body_read, body);
stream_set_readline (body->stream, _body_readline, body);
stream_set_write (body->stream, _body_write, body);
stream_set_truncate (body->stream, _body_truncate, body);
stream_set_size (body->stream, _body_size, body);
stream_set_flush (body->stream, _body_flush, body);
}
*pstream = body->stream;
return 0;
......@@ -223,6 +278,55 @@ body_set_size (body_t body, int (*_size)(body_t, size_t*) , void *owner)
return 0;
}
static int
_body_get_fd (stream_t stream, int *fd)
{
body_t body = stream_get_owner (stream);
return stream_get_fd (body->fstream, fd);
}
static int
_body_read (stream_t stream, char *buffer, size_t n, off_t off, size_t *pn)
{
body_t body = stream_get_owner (stream);
return stream_read (body->fstream, buffer, n, off, pn);
}
static int
_body_readline (stream_t stream, char *buffer, size_t n, off_t off, size_t *pn)
{
body_t body = stream_get_owner (stream);
return stream_readline (body->fstream, buffer, n, off, pn);
}
static int
_body_write (stream_t stream, const char *buf, size_t n, off_t off, size_t *pn)
{
body_t body = stream_get_owner (stream);
return stream_write (body->fstream, buf, n, off, pn);
}
static int
_body_truncate (stream_t stream, off_t n)
{
body_t body = stream_get_owner (stream);
return stream_truncate (body->fstream, n);
}
static int
_body_size (stream_t stream, off_t *size)
{
body_t body = stream_get_owner (stream);
return stream_size (body->fstream, size);
}
static int
_body_flush (stream_t stream)
{
body_t body = stream_get_owner (stream);
return stream_flush (body->fstream);
}
#ifndef P_tmpdir
# define P_tmpdir "/tmp"
#endif
......
/* 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. */
/* First draft by Alain Magloire */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <errno.h>
#ifdef HAVE_PTHREAD_H
# define _XOPEN_SOURCE 500
# include <pthread.h>
#endif
#include <mailutils/filter.h>
#include <mailutils/property.h>
static int rfc822_property __P ((property_t, const char *, const char *));
static int rfc822_init __P ((filter_t));
static void rfc822_destroy __P ((filter_t));
static int rfc822_read __P ((filter_t, char *, size_t, off_t, size_t *));
static int rfc822_readline __P ((filter_t, char *, size_t, off_t, size_t *));
static int rfc822_read0 __P ((filter_t, char *, size_t, off_t, size_t *, int));
struct rfc822
{
off_t r_offset; /* rfc822 offset. */
off_t s_offset; /* stream offset. */
size_t lines;
int residue;
};
static struct _filter _rfc822_filter =
{
"RFC822",
rfc822_init,
rfc822_read,
rfc822_readline,
NULL,
rfc822_destroy,
NULL,
NULL,
NULL,
0,
NULL
};
/* Exported. */
filter_t rfc822_filter = &_rfc822_filter;
static int
rfc822_property (property_t property, const char *key, const char *value)
{
filter_t filter = property_get_owner (property);
struct rfc822 *rfc822 = filter->data;
(void)key;
rfc822->lines = strtoul (value, NULL, 10);
return 0;
}
static int
rfc822_init (filter_t filter)
{
property_t property;
int status;
filter->data = calloc (1, sizeof (struct rfc822));
if (filter->data == NULL)
return ENOMEM;
/* We are interested in this property. */
if ((status = stream_get_property (filter->filter_stream, &property) != 0)
|| (status = property_add_defaults (property, "LINES", "0",
rfc822_property, NULL, filter)) != 0)
{
free (filter->data);
filter->data = NULL;
return status;
}
return 0;
}
static void
rfc822_destroy (filter_t filter)
{
if (filter->data)
free (filter->data);
}
static int
rfc822_read (filter_t filter, char *buffer, size_t buflen,
off_t off, size_t *pnread)
{
return rfc822_read0 (filter, buffer, buflen, off, pnread, 0);
}
static int
rfc822_readline (filter_t filter, char *buffer, size_t buflen,
off_t off, size_t *pnread)
{
return rfc822_read0 (filter, buffer, buflen, off, pnread, 1);
}
/* RFC 822 converter "\n" --> "\r\n"
We maintain to offset, the rfc822 offset (r_offset) and the offset of
the stream (s_offset). If they do not match we go back as for as possible
and start to read by 1 'till we reach the current offset. */
static int
rfc822_read0 (filter_t filter, char *buffer, size_t buflen,
off_t off, size_t *pnread, int isreadline)
{
size_t total = 0;
int status = 0;
struct rfc822 *rfc822 = filter->data;
/* Catch up i.e bring us to the current offset. */
if (rfc822->r_offset != off)
{
rfc822->r_offset = off - rfc822->lines;
rfc822->residue = 0;
if (rfc822->r_offset < 0)
rfc822->r_offset = 0;
rfc822->s_offset = rfc822->r_offset;
while (rfc822->r_offset < off)
{
char c;
size_t n = 0;
status = stream_read (filter->stream, &c, 1, rfc822->s_offset, &n);
if (status != 0)
return status;
if (n == 0)
break;
if (c == '\n')
{
rfc822->r_offset++;
if (rfc822->r_offset == off)
{
rfc822->residue = 1;
break;
}
}
rfc822->r_offset++;
rfc822->s_offset++;
}
}
do
{
size_t nread = 0;
status = stream_readline (filter->stream, buffer, buflen,
rfc822->s_offset, &nread);
if (status != 0)
return status;
if (nread == 0)
break;
rfc822->r_offset += nread;
rfc822->s_offset += nread;
total += nread;
buflen -= nread;
if (buffer[nread - 1] == '\n')
{
if (!rfc822->residue)
{
buffer[nread - 1] = '\r';
if (buflen == 0)
{
rfc822->residue = 1;
break;
}
buffer[nread] = '\n';
buflen--;
nread++;
total++;
rfc822->r_offset++;
}
else
rfc822->residue = 0;
}
buffer += nread;
} while (buflen > 0 || !isreadline);
if (isreadline)
*buffer = '\0';
if (pnread)
*pnread = total;
return status;
}
......@@ -756,11 +756,11 @@ imap_literal_string (f_imap_t f_imap, char **ptr)
f_imap->ptr = f_imap->buffer;
/* How much ? */
len0= len = f_imap->nl - f_imap->buffer;
len0 = len = f_imap->nl - f_imap->buffer;
/* Check if the last read did not finish on a line, if yes do not copy in
callback buffer the terminating sequence ")\r\n". We are doing this
by checking if the amount(total) we got so far + the len of the line
+1 (taking to account the strip '\r'). */
+1 (taking to account the strip '\r') goes behond the request. */
if ((total + len + 1) > f_imap->callback.nleft)
{
len0 = len = f_imap->callback.nleft - total;
......@@ -777,8 +777,9 @@ imap_literal_string (f_imap_t f_imap, char **ptr)
/* Check how much we can fill the callback buffer. */
int x = (f_imap->callback.buflen - f_imap->callback.total) - len0;
x = (x >= 0) ? len0 : (x + len0);
memcpy (f_imap->callback.buffer + f_imap->callback.total,
f_imap->buffer, x);
if (f_imap->callback.buffer)
memcpy (f_imap->callback.buffer + f_imap->callback.total,
f_imap->buffer, x);
f_imap->callback.total += x;
/* Depending on the type of request we incremente the xxxx_lines
......@@ -838,7 +839,8 @@ imap_quoted_string (f_imap_t f_imap, char **ptr)
f_imap->callback.total = *ptr - bquote;
/* Fill the call back buffer. The if is redundant there should always
be enough room since the request is base on the buffer size. */
if (f_imap->callback.total <= f_imap->callback.buflen)
if (f_imap->callback.total <= f_imap->callback.buflen
&& f_imap->callback.buffer)
memcpy (f_imap->callback.buffer, bquote, f_imap->callback.total);
if (**ptr == '"')
(*ptr)++;
......@@ -1238,6 +1240,7 @@ imap_body (f_imap_t f_imap, char **ptr)
if (**ptr == '[')
{
char *sep = strchr (*ptr, ']');
(*ptr)++; /* Move pass the '[' */
if (sep)
{
size_t len = sep - *ptr;
......@@ -1250,20 +1253,22 @@ imap_body (f_imap_t f_imap, char **ptr)
if (isalpha((unsigned)*p))
*p = toupper ((unsigned)*p);
/* Check to see the callback type to update the line count. */
if (strstr (section, "MIME")
|| (strstr (section, "HEADER") && ! strstr (section, "FIELD")))
if (!strstr (section, "FIELD"))
{
f_imap->callback.type = IMAP_HEADER;
}
else if (strstr (section, "TEXT"))
{
f_imap->callback.type = IMAP_BODY;
}
else if (len == 1) /* body[] */
{
f_imap->callback.type = IMAP_MESSAGE;
if (strstr (section, "MIME") || (strstr (section, "HEADER")))
{
f_imap->callback.type = IMAP_HEADER;
}
else if (strstr (section, "TEXT") || len > 0)
{
f_imap->callback.type = IMAP_BODY;
}
else if (len == 0) /* body[] */
{
f_imap->callback.type = IMAP_MESSAGE;
}
}
sep++;
sep++; /* Move pass the ']' */
*ptr = sep;
}
}
......@@ -1586,15 +1591,12 @@ imap_readline (f_imap_t f_imap)
while (f_imap->nl == NULL);
/* Conversion \r\n --> \n\0 */
/**/
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;
}
if (f_imap->nl > f_imap->buffer)
{
*(f_imap->nl - 1) = '\n';
*(f_imap->nl) = '\0';
f_imap->ptr = f_imap->nl;
}
return 0;
}
......
......@@ -413,7 +413,6 @@ header_get_value (header_t header, const char *name, char *buffer,
size_t name_len;
size_t total = 0, fn_len = 0, fv_len = 0;
size_t threshold;
int rfc822 = 0;
int err = 0;
if (header == NULL || name == NULL)
......@@ -456,10 +455,6 @@ 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;
......@@ -481,25 +476,7 @@ header_get_value (header_t header, const char *name, char *buffer,
if (buffer && threshold > 0)
{
buflen = (fv_len < threshold) ? fv_len : threshold;
if (rfc822)
{
/* 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);
memcpy (buffer, header->hdr[i].fv, buflen);
buffer += buflen;
threshold -= buflen;
}
......@@ -679,15 +656,7 @@ header_size (header_t header, size_t *psize)
}
if (psize)
{
*psize = header->blurb_len;
if (property_is_set (header->property, "RFC822"))
{
size_t lines = 0;
header_lines (header, &lines);
*psize += lines;
}
}
*psize = header->blurb_len;
return 0;
}
......@@ -708,6 +677,12 @@ header_get_property (header_t header, property_t *pp)
{
if (header == NULL || pp == NULL)
return EINVAL;
if (header->property == NULL)
{
int status = property_create (&(header->property), header);
if (status != 0)
return status;
}
*pp = header->property;
return 0;
}
......@@ -874,7 +849,6 @@ header_read (stream_t is, char *buf, size_t buflen, off_t off, size_t *pnread)
{
int len;
header_t header = stream_get_owner (is);
int rfc822 = 0;
if (is == NULL || header == NULL)
return EINVAL;
......@@ -894,53 +868,14 @@ 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)
len = header->blurb_len - off;
if (len > 0)
{
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;
len = (buflen < (size_t)len) ? buflen : len;
memcpy (buf, header->blurb + off, len);
}
else
{
len = header->blurb_len - off;
if (len > 0)
{
len = (buflen < (size_t)len) ? buflen : len;
memcpy (buf, header->blurb + off, len);
}
else
len = 0;
}
len = 0;
if (pnread)
*pnread = len;
......@@ -952,7 +887,6 @@ header_readline (stream_t is, char *buf, size_t buflen, off_t off, size_t *pn)
{
int len;
header_t header = stream_get_owner (is);
int rfc822 = 0;
if (is == NULL || header == NULL)
return EINVAL;
......@@ -972,54 +906,19 @@ 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)
len = header->blurb_len - off;
if (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;
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 = 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;
}
len = 0;
if (pn)
*pn = len;
buf[len] = '\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
......@@ -43,11 +43,12 @@ extern "C" {
struct _body
{
void *owner;
/* it's better and more portable to use stdio */
FILE *file;
char *filename;
stream_t stream;
stream_t fstream;
property_t property;
int flags;
int (*_size) (body_t, size_t*);
int (*_lines) (body_t, size_t*);
};
......
......@@ -40,6 +40,14 @@ extern "C" {
# endif
#endif /*__P */
struct default_properties
{
char *key;
char *value;
int (*_set_value) __P ((property_t, const char *, const char *));
int (*_get_value) __P ((property_t, const char *, char *, size_t, size_t *));
};
struct _mailbox
{
/* Data */
......@@ -48,7 +56,7 @@ struct _mailbox
ticket_t ticket;
authority_t authority;
property_t property;
struct property_list *properties;
struct default_properties *properties;
size_t properties_count;
locker_t locker;
stream_t stream;
......@@ -81,7 +89,7 @@ struct _mailbox
int (*_scan) __P ((mailbox_t, size_t msgno, size_t *count));
int (*_is_updated) __P ((mailbox_t));
int (*_size) __P ((mailbox_t, off_t *size));
int (*_get_size) __P ((mailbox_t, off_t *size));
};
......
......@@ -53,6 +53,14 @@ extern "C" {
#define MAILER_LINE_BUF_SIZE 1000
struct default_properties
{
char *key;
char *value;
int (*_set_value) __P ((property_t, const char *, const char *));
int (*_get_value) __P ((property_t, const char *, char *, size_t, size_t *));
};
struct _mailer
{
stream_t stream;
......@@ -62,7 +70,7 @@ struct _mailer
int flags;
monitor_t monitor;
property_t property;
struct property_list *properties;
struct default_properties *properties;
size_t properties_count;
/* Pointer to the specific mailer data. */
......
......@@ -50,7 +50,9 @@ struct _message
header_t header;
body_t body;
int flags;
stream_t stream;
property_t property;
attribute_t attribute;
monitor_t monitor;
mime_t mime;
......
......@@ -41,10 +41,13 @@
extern "C" {
#endif
struct property_private
struct property_data
{
size_t hash;
int *address;
char *key;
char *value;
int (*_set_value) __P ((property_t, const char *, const char *));
int (*_get_value) __P ((property_t, const char *, char *, size_t, size_t *));
};
struct _property
......
......@@ -48,6 +48,7 @@ struct rbuffer
struct _stream
{
void *owner;
property_t property;
int flags;
int state;
......
......@@ -274,11 +274,11 @@ mailbox_scan (mailbox_t mbox, size_t msgno, size_t *pcount)
}
int
mailbox_size (mailbox_t mbox, off_t *psize)
mailbox_get_size (mailbox_t mbox, off_t *psize)
{
if (mbox == NULL || mbox->_size == NULL)
if (mbox == NULL || mbox->_get_size == NULL)
return ENOSYS;
return mbox->_size (mbox, psize);
return mbox->_get_size (mbox, psize);
}
int
......@@ -426,10 +426,12 @@ mailbox_get_property (mailbox_t mbox, property_t *pproperty)
/* 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);
status = property_add_defaults (mbox->property,
mbox->properties[i].key,
mbox->properties[i].value,
mbox->properties[i]._set_value,
mbox->properties[i]._get_value,
mbox);
if (status != 0)
{
property_destroy (&(mbox->property), mbox);
......
......@@ -145,6 +145,8 @@ mailer_destroy (mailer_t *pmailer)
{
if (mailer->properties[i].key)
free (mailer->properties[i].key);
if (mailer->properties[i].value)
free (mailer->properties[i].value);
}
free (mailer->properties);
}
......@@ -237,10 +239,12 @@ mailer_get_property (mailer_t mailer, property_t *pproperty)
/* 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);
status = property_add_defaults (mailer->property,
mailer->properties[i].key,
mailer->properties[i].value,
mailer->properties[i]._set_value,
mailer->properties[i]._get_value,
mailer);
if (status != 0)
{
property_destroy (&(mailer->property), mailer);
......
......@@ -145,14 +145,12 @@ _mailbox_imap_init (mailbox_t mailbox)
m_imap->mailbox = mailbox;
/* Set our properties. */
mailbox->properties = calloc (2, sizeof (*(mailbox->properties)));
mailbox->properties = calloc (1, 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;
mailbox->properties_count = 1;
mailbox->properties[0].key = strdup ("TYPE");
mailbox->properties[0].value = strdup ("IMAP");
return 0;
}
......@@ -436,6 +434,7 @@ imap_get_message0 (msg_imap_t msg_imap, message_t *pmsg)
/* Set the UID on the message. */
message_set_uid (msg, imap_message_uid, msg_imap);
message_set_mailbox (msg, mailbox, msg_imap);
*pmsg = msg;
return 0;
......@@ -720,6 +719,7 @@ imap_submessage_size (msg_imap_t msg_imap, size_t *psize)
{
if (psize)
{
*psize = 0;
if (msg_imap->message_size == 0)
{
size_t i, size;
......@@ -1129,13 +1129,10 @@ imap_header_get_value (header_t header, const char *field, char * buffer,
/* Hack, if buffer == NULL they want to know how big is the field value,
Unfortunately IMAP does not say, so we take a guess hoping that the
value will not be over 1024. */
/* FIXME: This is stupid, find a way to fix this. */
if (buffer == NULL || buflen == 0)
len = 1024;
else
len = strlen (field) + buflen + 4;
value = alloca (len);
/*memset (value, '0', len); */
if (f_imap->state == IMAP_NO_STATE)
{
......@@ -1151,14 +1148,18 @@ imap_header_get_value (header_t header, const char *field, char * buffer,
f_imap->state = IMAP_FETCH;
}
value = calloc (len, sizeof (*value));
status = message_operation (f_imap, msg_imap, value, len, &len);
if (status == 0)
{
char *colon;
/* The field-matching is case-insensitive but otherwise exact. In all
cases, the delimiting blank line between the header and the body is
always included. */
/* The field-matching is case-insensitive. In all cases, the delimiting
newline between the header and the body is always included.
Nuke it */
value[len - 1] = '\0';
/* Move pass the field-name. */
colon = strchr (value, ':');
if (colon)
{
......@@ -1183,8 +1184,8 @@ imap_header_get_value (header_t header, const char *field, char * buffer,
if (len == 0)
status = ENOENT;
}
free (value);
return status;
}
static int
......
......@@ -46,11 +46,6 @@
#include <registrar0.h>
#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)
......@@ -110,14 +105,6 @@ struct _mbox_message
off_t body;
off_t body_end;
/* 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. */
......@@ -177,7 +164,7 @@ static int mbox_uidvalidity __P ((mailbox_t, unsigned long *));
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_size __P ((mailbox_t, off_t *));
/* private stuff */
static int mbox_scan0 __P ((mailbox_t, size_t, size_t *, int));
......@@ -195,9 +182,6 @@ 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_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));
......@@ -275,17 +259,15 @@ _mailbox_mbox_init (mailbox_t mailbox)
mailbox->_scan = mbox_scan;
mailbox->_is_updated = mbox_is_updated;
mailbox->_size = mbox_size;
mailbox->_get_size = mbox_get_size;
/* Set our properties. */
mailbox->properties = calloc (2, sizeof (*(mailbox->properties)));
mailbox->properties = calloc (1, 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->properties_count = 1;
mailbox->properties[0].key = strdup ("TYPE");
mailbox->properties[0].value = strdup ("MBOX");
MAILBOX_DEBUG1 (mailbox, MU_DEBUG_TRACE, "mbox_init(%s)\n", mud->name);
return 0; /* okdoke */
......@@ -993,12 +975,8 @@ mbox_body_readline (stream_t is, char *buffer, size_t buflen,
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);
return mbox_readstream (mum, buffer, buflen, off, pnread, 1,
mum->body, mum->body_end);
}
static int
......@@ -1008,98 +986,8 @@ mbox_body_read (stream_t is, char *buffer, size_t buflen,
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_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)
{
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;
if (n == 0)
break;
if (c == '\n')
{
mum->rfc822.r_offset++;
if (mum->rfc822.r_offset == off)
{
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;
}
buffer[nread] = '\n';
buflen--;
nread++;
total++;
mum->rfc822.r_offset++;
}
else
mum->rfc822.residue = 0;
}
buffer += nread;
} while (buflen > 0 || !isreadline);
if (isreadline)
*buffer = '\0';
if (pnread)
*pnread = total;
return status;
return mbox_readstream (mum, buffer, buflen, off, pnread, 0,
mum->body, mum->body_end);
}
static int
......@@ -1187,28 +1075,8 @@ mbox_header_get_fvalue (header_t header, const char *name, char *buffer,
{
/* For the null. */
buflen--;
/* 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);
}
fv_len = (fv_len < buflen) ? fv_len : buflen;
memcpy (buffer, mum->fhdr[i], fv_len);
buffer[fv_len] = '\0';
}
err = 0;
......@@ -1232,13 +1100,7 @@ mbox_header_size (header_t header, size_t *psize)
if (mum == NULL)
return EINVAL;
if (psize)
{
*psize = mum->body - mum->header_from_end;
#if 1
if (mum->mud->mailbox->properties[PROP_RFC822].value)
*psize += mum->header_lines;
#endif
}
*psize = mum->body - mum->header_from_end;
return 0;
}
......@@ -1262,13 +1124,7 @@ mbox_body_size (body_t body, size_t *psize)
if (mum == NULL)
return EINVAL;
if (psize)
{
*psize = mum->body_end - mum->body + 1;
#if 1
if (mum->mud->mailbox->properties[PROP_RFC822].value)
*psize += mum->body_lines;
#endif
}
*psize = mum->body_end - mum->body + 1;
return 0;
}
......@@ -1421,16 +1277,12 @@ 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);
......@@ -1458,7 +1310,9 @@ mbox_get_message (mailbox_t mailbox, size_t msgno, message_t *pmsg)
body_t body = NULL;
stream_t stream = NULL;
if ((status = body_create (&body, msg)) != 0
|| (status = stream_create (&stream, mailbox->flags, body)) != 0)
|| (status = stream_create (&stream,
mailbox->flags | MU_STREAM_SEEKABLE,
body)) != 0)
{
body_destroy (&body, msg);
stream_destroy (&stream, body);
......@@ -1493,7 +1347,7 @@ mbox_get_message (mailbox_t mailbox, size_t msgno, message_t *pmsg)
/* Attach the message to the mailbox mbox data. */
mum->message = msg;
message_set_mailbox (msg, mailbox);
message_set_mailbox (msg, mailbox, mum);
*pmsg = msg;
return 0;
......@@ -1832,7 +1686,7 @@ mbox_append_message0 (mailbox_t mailbox, message_t msg, off_t *psize,
}
static int
mbox_size (mailbox_t mailbox, off_t *psize)
mbox_get_size (mailbox_t mailbox, off_t *psize)
{
off_t size;
int status;
......
......@@ -87,7 +87,7 @@ static int pop_is_updated __P ((mailbox_t));
/* The implementation of message_t */
static int pop_user __P ((authority_t));
static int pop_size __P ((mailbox_t, off_t *));
static int pop_get_size __P ((mailbox_t, off_t *));
/* We use pop_top for retreiving headers. */
/* static int pop_header_read (header_t, char *, size_t, off_t, size_t *); */
static int pop_body_fd __P ((stream_t, int *));
......@@ -292,17 +292,15 @@ _mailbox_pop_init (mailbox_t mbox)
mbox->_scan = pop_scan;
mbox->_is_updated = pop_is_updated;
mbox->_size = pop_size;
mbox->_get_size = pop_get_size;
/* Properties. */
mbox->properties = calloc (2, sizeof (*(mbox->properties)));
mbox->properties = calloc (1, 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;
mbox->properties_count = 1;
mbox->properties[0].key = strdup ("TYPE");
mbox->properties[0].value = strdup ("POP3");
return 0; /* Okdoke. */
}
......@@ -799,7 +797,7 @@ pop_get_message (mailbox_t mbox, size_t msgno, message_t *pmsg)
monitor_unlock (mbox->monitor);
/* Save The message pointer. */
message_set_mailbox (msg, mbox);
message_set_mailbox (msg, mbox, mpm);
*pmsg = mpm->message = msg;
return 0;
......@@ -1005,7 +1003,7 @@ pop_expunge (mailbox_t mbox)
/* Mailbox size ? It is part of the STAT command */
static int
pop_size (mailbox_t mbox, off_t *psize)
pop_get_size (mailbox_t mbox, off_t *psize)
{
pop_data_t mpd = mbox->data;
int status = 0;
......@@ -1865,14 +1863,12 @@ pop_readline (pop_data_t mpd)
mpd->nl = NULL;
}
}
/* \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;
}
/* \r\n --> \n\0, conversion. */
if (mpd->nl > mpd->buffer)
{
*(mpd->nl - 1) = '\n';
*(mpd->nl) = '\0';
mpd->ptr = mpd->nl;
}
return 0;
}
......
......@@ -182,10 +182,43 @@ message_clear_modified (message_t msg)
}
int
message_set_mailbox (message_t msg, mailbox_t mailbox)
message_set_property (message_t msg, property_t property, void *owner)
{
if (msg == NULL)
return EINVAL;
if (msg->owner != owner)
return EACCES;
header_set_property (msg->header, property, msg);
body_set_property (msg->body, property, msg);
property_destroy (&(msg->property), msg);
msg->property = property;
return 0;
}
int
message_get_property (message_t msg, property_t *pproperty)
{
if (msg == NULL || pproperty == NULL)
return EINVAL;
if (msg->property == NULL)
{
int status = property_create (&(msg->property), msg);
if (status != 0)
return status;
header_set_property (msg->header, msg->property, msg);
body_set_property (msg->body, msg->property, msg);
}
*pproperty = msg->property;
return 0;
}
int
message_set_mailbox (message_t msg, mailbox_t mailbox, void *owner)
{
if (msg == NULL)
return EINVAL;
if (msg->owner != owner)
return EACCES;
msg->mailbox = mailbox;
return 0;
}
......
......@@ -21,9 +21,13 @@
#include <property0.h>
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 int property_find __P ((list_t, const char *, struct property_data **));
static int property_add __P ((property_t, const char *, const char *,
int (*_set_value)
__P ((property_t, const char *, const char *)),
int (*_get_value)
__P ((property_t, const char *, char *,
size_t, size_t *))));
static size_t property_hash __P ((const char *));
int
......@@ -51,22 +55,21 @@ property_destroy (property_t *pp, void *owner)
/* Destroy the list and is properties. */
if (prop->list)
{
struct property_list *pl = NULL;
struct property_data *pd = 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)
iterator_current (iterator, (void **)&pd);
if (pd)
{
if (pl->key)
free (pl->key);
if (pl->private_)
free (pl->private_);
free (pl);
if (pd->key)
free (pd->key);
if (pd->value)
free (pd->value);
free (pd);
}
}
iterator_destroy (&iterator);
......@@ -85,98 +88,126 @@ property_get_owner (property_t prop)
}
int
property_add_default (property_t prop, const char *key, int *address,
property_add_defaults (property_t prop, const char *key, const char *value,
int (*_set_value) __P ((property_t, const char *,
const char *)),
int (*_get_value) __P ((property_t, const char *,
char *, size_t, size_t *)),
void *owner)
{
if (prop == NULL)
return EINVAL;
if (prop->owner != owner)
return EACCES;
return property_add (prop, key, 0, address);
return property_add (prop, key, value, _set_value, _get_value);
}
int
property_set_value (property_t prop, const char *key, int value)
property_set_value (property_t prop, const char *key, const char *value)
{
if (prop == NULL)
return EINVAL;
return property_add (prop, key, value, NULL);
return property_add (prop, key, value, NULL, NULL);
}
int
property_get_value (property_t prop, const char *key, int *pvalue)
property_get_value (property_t prop, const char *key, char *buffer,
size_t buflen, size_t *n)
{
struct property_list *pl = NULL;
struct property_data *pd = NULL;
int status;
size_t len;
if (prop == NULL)
return EINVAL;
status = property_find (prop->list, key, &pl);
status = property_find (prop->list, key, &pd);
if (status != 0)
return status;
if (pl == NULL)
if (pd == NULL)
return ENOENT;
/* Update the value. */
property_update (pl);
if (pvalue)
*pvalue = pl->value;
if (pd->_get_value)
return pd->_get_value (prop, key, buffer, buflen, n);
len = (pd->value) ? strlen (pd->value) : 0;
if (buffer && buflen != 0)
{
buflen--;
len = (buflen < len) ? buflen : len;
strncpy (buffer, pd->value, len)[len] = '\0';
}
if (n)
*n = len;
return 0;
}
#if 0
int
property_set (property_t prop, const char *k)
property_load (property_t prop, stream_t stream)
{
return property_set_value (prop, k, 1);
size_t n = 0;
off_t off = 0;
int status;
int buflen = 512;
char *buf = calloc (buflen, sizeof (*buf));
if (buf == NULL)
return ENOMEM;
while ((status = stream_readline (stream, buf, buflen, off, &n)) == 0
&& n > 0)
{
char *sep;
if (buf[n] != '\n')
{
char *tmp;
buflen *= 2;
tmp = realloc (buf, buflen);
if (tmp == NULL)
{
free (buf);
return ENOMEM;
}
buf = tmp;
continue;
}
sep = strchr (buf, '=');
if (sep)
{
*sep++ = '\0';
property_set_value (prop, buf, sep);
}
else
property_set (prop, buf);
}
return 0;
}
#endif
int
property_unset (property_t prop, const char *k)
property_set (property_t prop, const char *k)
{
int v = 0;
property_get_value (prop, k, &v);
if (v != 0)
return property_set_value (prop, k, 0);
if (!property_is_set (prop, k))
return property_set_value (prop, k, "1");
return 0;
}
int
property_is_set (property_t prop, const char *k)
property_unset (property_t prop, const char *k)
{
int v = 0;
property_get_value (prop, k, &v);
return (v != 0);
if (property_is_set (prop, k))
return property_set_value (prop, k, NULL);
return 0;
}
int
property_get_list (property_t prop, list_t *plist)
property_is_set (property_t prop, const char *k)
{
struct property_list *pl = NULL;
iterator_t iterator = NULL;
int status;
if (plist == NULL || prop == NULL)
return EINVAL;
status = iterator_create (&iterator, prop->list);
if (status != 0)
return status;
/* 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);
*plist = prop->list;
return 0;
int n = 0;
property_get_value (prop, k, NULL, 0, &n);
return (n != 0);
}
/* Taking from an article in Dr Dobbs. */
......@@ -196,24 +227,12 @@ property_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_list **p)
property_find (list_t list, const char *key, struct property_data **p)
{
int status;
size_t h;
struct property_list *pl = NULL;
struct property_data *pd = NULL;
iterator_t iterator;
status = iterator_create (&iterator, list);
......@@ -224,28 +243,30 @@ property_find (list_t list, const char *key, struct property_list **p)
for (iterator_first (iterator); !iterator_is_done (iterator);
iterator_next (iterator))
{
iterator_current (iterator, (void **)&pl);
if (pl)
iterator_current (iterator, (void **)&pd);
if (pd)
{
struct property_private *private_ = pl->private_;
if (private_->hash == h)
if (strcasecmp (pl->key, key) == 0)
if (pd->hash == h)
if (pd->key && strcasecmp (pd->key, key) == 0)
break;
}
pl = NULL;
pd = NULL;
}
iterator_destroy (&iterator);
*p = pl;
*p = pd;
return 0;
}
static int
property_add (property_t prop, const char *key, int value, int *address)
property_add (property_t prop, const char *key, const char *value,
int (*_set_value) __P ((property_t, const char *, const char *)),
int (*_get_value) __P ((property_t, const char *, char *,
size_t, size_t *)))
{
struct property_list *pl = NULL;
struct property_data *pd = NULL;
int status;
if (key == NULL)
if (key == NULL || *key == '\0')
return EINVAL;
if (prop->list == NULL)
......@@ -255,47 +276,26 @@ property_add (property_t prop, const char *key, int value, int *address)
return status;
}
status = property_find (prop->list, key, &pl);
status = property_find (prop->list, key, &pd);
if (status != 0)
return status;
/* None find create a new one. */
if (pl == NULL)
if (pd == NULL)
{
struct property_private *private_;
pl = calloc (1, sizeof (*pl));
if (pl == NULL)
pd = calloc (1, sizeof (*pd));
if (pd == 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;
}
pd->hash = property_hash (key);
list_append (prop->list, (void *)pd);
}
if (pd->key == NULL)
pd->key = strdup (key);
if (pd->value)
free (pd->value);
pd->value = (value) ? strdup (value) : NULL;
pd->_set_value = _set_value;
pd->_get_value = _get_value;
return 0;
}
......
......@@ -86,8 +86,8 @@ _mailer_sendmail_init (mailer_t mailer)
if (mailer->properties == NULL)
return ENOMEM;
mailer->properties_count = 1;
mailer->properties[0].key = strdup ("SENDMAIL");
mailer->properties[0].value = 1;
mailer->properties[0].key = strdup ("TYPE");
mailer->properties[0].value = strdup ("SENDMAIL");
return 0;
}
......
......@@ -164,8 +164,8 @@ _mailer_smtp_init (mailer_t mailer)
if (mailer->properties == NULL)
return ENOMEM;
mailer->properties_count = 1;
mailer->properties[0].key = strdup ("SMTP");
mailer->properties[0].value = 1;
mailer->properties[0].key = strdup ("TYPE");
mailer->properties[0].value = strdup ("SMTP");
return 0;
}
......
......@@ -41,7 +41,9 @@ static int refill (stream_t, off_t);
/* Stream is a way for object to do I/O, they can take over(overload) the
the read/write functions for there needs. We are doing some very
minimal buffering on the read when the stream_bufsiz is set, this
unfortunately does not take to account the offset, this buffering is more
unfortunately does not take to account the offset i.e if the offset ask
is different then the offset we maintain internally, the buffer is flushed
and a new buffer is use, this buffering is more
for networking stream (POP/IMAP). No buffering on the write. */
int
stream_create (stream_t *pstream, int flags, void *owner)
......@@ -116,6 +118,12 @@ stream_close (stream_t stream)
}
int
stream_is_seekable (stream_t stream)
{
return (stream) ? stream->flags & MU_STREAM_SEEKABLE : 0;
}
int
stream_setbufsiz (stream_t stream, size_t size)
{
if (stream == NULL)
......@@ -396,6 +404,34 @@ stream_get_flags (stream_t stream, int *pfl)
}
int
stream_set_property (stream_t stream, property_t property, void *owner)
{
if (stream == NULL)
return EINVAL;
if (stream->owner != owner)
return EACCES;
if (stream->property)
property_destroy (&(stream->property), stream);
stream->property = property;
return 0;
}
int
stream_get_property (stream_t stream, property_t *pp)
{
if (stream == NULL)
return EINVAL;
if (stream->property == NULL)
{
int status = property_create (&(stream->property), stream);
if (status != 0)
return status;
}
*pp = stream->property;
return 0;
}
int
stream_size (stream_t stream, off_t *psize)
{
if (stream == NULL || stream->_size == NULL)
......