Commit 9f739684 9f73968409cff3e3d5b59dbb5b841d5fcffca582 by Alain Magloire

* mailbox/Makefile.am: filter_trans.c added, trans_stream.c deleted.

	* mailbox/attachment.c (message_create_attachment): use
	filter_create().
	(message_save_attachment): use filter_create().
	* mailbox/body.c (body_set_lines): Wrong comparison for the owner.
	* mailbox/mbx_mbox.c: Do not count the line separtor of part
	of the mailbox.

	* mailbox/url.c (url_is_same_sheme): New function.
	(url_is_same_user): New function.
	(url_is_same_path): New function.
	(url_is_same_host): New function.
	(url_is_same_port): New function.
	* mailbox/folder.c : Moved the is_same_*() functions in url.c
	they can be generally usefull.
	(is_same_sheme): Removed.
	(is_same_user): Removed.
	(is_same_path): Removed.
	(is_same_host): Removed.
	(is_same_port): Removed.

	* mailbox/folder_imap.c (folder_imap_create): New function,
	CREATE a new mailbox.
	(folder_imap_open): Calls folder_imap_create when the MU_STREAM_CREAT
	flag is set.
	* mailbox/mbx_imap.c: Appending messages implemented, if the message
	comes from the same imap folder, it is COPY otherwise APPEND.
	(is_same_folder): New function.
	(imap_append_message): Implemented.
	(attribute_string): New functions.
	(imap_copy_message): New function.
	* mailbox/include/imap0.h: New enum, IMAP_APPEND, IMAP_APPEND_ACK,
	IMAP_APPEND_CONT, IMAP_APPEND_SEND, IMAP_COPY, IMAP_COPY_ACK,
	IMAP_CREATE, IMAP_CREATE_ACK.


* mailbox/parse822.c: New parser.
	* include/mailutils/parse822.h: New file.
	* mailbox/address.c (address_create): Remove the old parsing and use
	parse822 as the underlying engine.
	(address_parse): Removed.
	(gettoken): Removed.
	(quotes): Removed.
	(address_get_personal): Remove the code to unquote, parse822 takes
	care if it. Return value when no field is ENOENT.
	(address_get_comments): Reutrn value when no field ENOENT.
	(address_get_local_part): Reutrn value when no field ENOENT.
	(address_get_domain): Reutrn value when no field ENOENT.
	(address_get_email): Reutrn value when no field ENOENT.
	(address_get_route): Reutrn value when no field ENOENT.
	* mailbox/message.c (message_sender): Use parse822 to retrieve
	the email from the From: field.
	(message_set_mailbox): New function.
	* mailbox/misc.c : Removed the old parsing code.
	(gettoken): Removed.
	(parseaddr): Removed.
	* mailbox/include/misc.h : Removed parseaddr() prototypes.
	From Sam Roberts, the new parse822 parser..
1 parent f9979c0e
......@@ -22,6 +22,7 @@ envelope.c \
file_stream.c \
filter.c \
filter_rfc822.c \
filter_trans.c \
folder.c \
folder_imap.c \
folder_mbox.c \
......@@ -50,7 +51,6 @@ sendmail.c \
smtp.c \
stream.c \
tcp.c \
trans_stream.c \
url.c \
url_file.c \
url_imap.c \
......
......@@ -27,297 +27,38 @@
#include <stdlib.h>
#include <errno.h>
#include <address0.h>
#include <mailutils/parse822.h>
#include <misc.h>
/*
* parseaddr.c Read a valid RFC822 address with all the comments
* etc in it, and return _just_ the email address.
*
* Version: @(#)parseaddr.c 1.00 02-Apr-1999 miquels@cistron.nl
*
*/
struct token
{
struct token *next;
char word[1];
};
#define SKIPSPACE(p) do { while(*p && isspace((unsigned char)*p)) p++; } while(0)
/* Skip everything between quotes. */
static void
quotes (const char **ptr)
{
const char *p = *ptr;
p++;
while (*p && *p != '"')
{
if (*p == '\\' && p[1])
p++;
p++;
}
*ptr = p;
}
/* Return the next token. A token can be "<>()," or any "word". */
static struct token *
gettoken (const char **ptr)
{
struct token *tok;
const char *p = *ptr;
const char *begin;
int l, quit = 0;
SKIPSPACE(p);
begin = p;
while (!quit)
{
switch (*p)
{
case 0:
case ' ':
case '\t':
case '\n':
quit = 1;
break;
case '(':
case ')':
case '<':
case '>':
case ',':
if (p == begin)
p++;
quit = 1;
break;
case '\\':
if (p[1])
p++;
break;
case '"':
quotes (&p);
break;
}
if (!quit)
p++;
}
l = p - begin;
if (l == 0)
return NULL;
tok = malloc (sizeof (struct token) + l);
if (tok == NULL)
return NULL;
tok->next = NULL;
strncpy (tok->word, begin, l);
tok->word[l] = 0;
SKIPSPACE (p);
*ptr = p;
return tok;
}
#include <address0.h>
/* Get email address from rfc822 address. */
/* Note: This again as for header.c an awfull way of doing things.
Meaning I need a correct rfc822 Parser. This one does not
understand group. There is not doubt a better way to do this. */
static int
address_parse (address_t *paddress, const char **paddr)
{
const char *p;
struct token *t, *tok, *last;
struct token *brace = NULL;
struct token *comments = NULL;
struct token *start_comments = NULL;
address_t address;
int in_comment = 0;
int status = 0;
tok = last = NULL;
address = *paddress = calloc (1, sizeof (*address));
if (address == NULL)
return ENOMEM;
/* Read address, remove comments right away. */
p = *paddr;
while ((t = gettoken(&p)) != NULL && (t->word[0] != ',' || in_comment))
{
if (t->word[0] == '(' || t->word[0] == ')' || in_comment)
{
if (t->word[0] == '(')
in_comment++;
if (t->word[0] == ')')
in_comment--;
if (!start_comments)
comments = start_comments = t;
else
{
comments->next = t;
comments = t;
}
continue;
}
if (t->word[0] == '<')
brace = t;
if (tok)
last->next = t;
else
tok = t;
last = t;
}
if (t != NULL)
free (t);
/* Put extracted address into email */
t = brace ? brace->next : tok;
for (; t && t->word[0] != ',' && t->word[0] != '>'; t = t->next)
{
char *tmp;
if (address->email
&& (tmp = realloc (address->email, strlen (address->email)
+ strlen (t->word) + 1)) != NULL)
{
address->email = tmp;
strcat (address->email, t->word);
}
else if ((tmp = calloc (strlen (t->word) + 1, sizeof (char))) != NULL)
{
address->email = tmp;
strcat (address->email, t->word);
}
else
{
address_destroy (&address);
status = ENOMEM;
goto freenodes;
}
}
/* Extract Comments. */
for (t = start_comments; t ; t = t->next)
{
char *tmp;
if (t->word[0] == '(' || t->word[0] == ')')
continue;
if (address->comments
&& (tmp = realloc (address->comments, strlen (address->comments)
+ strlen (t->word) + 2)) != NULL)
{
address->comments = tmp;
strcat (address->comments, " ");
strcat (address->comments, t->word);
}
else if ((tmp = calloc (strlen (t->word) + 1, sizeof (char))) != NULL)
{
address->comments = tmp;
strcat (address->comments, t->word);
}
else
{
address_destroy (&address);
status = ENOMEM;
goto freenodes;
}
}
/* Extract Personal. */
if (brace == NULL)
{
address->personal = strdup ("");
}
else
{
int in_brace = 0;
for (t = tok; t ; t = t->next)
{
char *tmp;
if (t->word[0] == '<' || t->word[0] == '>' || in_brace)
{
if (t->word[0] == '<')
in_brace++;
else if (t->word[0] == '>')
in_brace--;
continue;
}
if (address->personal
&& (tmp = realloc (address->personal, strlen (address->personal)
+ strlen (t->word) + 2)) != NULL)
{
address->personal = tmp;
strcat (address->personal, " ");
strcat (address->personal, t->word);
}
else if ((tmp = calloc (strlen (t->word) + 1, sizeof (char))) != NULL)
{
address->personal = tmp;
strcat (address->personal, t->word);
}
else
{
address_destroy (&address);
status = ENOMEM;
goto freenodes;
}
}
}
/* Free list of tokens. */
freenodes:
for (t = tok; t; t = last)
{
last = t->next;
free (t);
}
for (t = start_comments; t; t = last)
{
last = t->next;
free (t);
}
*paddr = p;
return status;
}
int
address_create (address_t *paddress, const char *addr)
address_create (address_t *a, const char *s)
{
address_t address = NULL;
address_t current = NULL;
address_t head = NULL;
const char *p = addr;
int status = 0;
/* 'paddress' must exist, and can't already have been initialized
*/
int status;
if (paddress == NULL)
if (!a)
return EINVAL;
if (addr)
*a = NULL;
status = parse822_address_list (a, (char*) s);
if (status == 0)
{
while (*addr != 0)
/* There was a group that got parsed correctly, but had
* no addresses...
*/
if (!*a)
return ENOENT;
(*a)->addr = strdup (s);
if (!(*a)->addr)
{
status = address_parse (&address, &addr);
if (status == 0)
{
if (head == NULL)
{
head = address;
head->addr = strdup (p);
}
else
current->next = address;
current = address;
p = addr;
}
}
address_destroy (a);
return ENOMEM;
}
}
*paddress = head;
return status;
}
......@@ -356,7 +97,7 @@ address_get_personal (address_t addr, size_t no, char *buf, size_t len,
size_t *n)
{
size_t i, j;
int status = EINVAL;
int status = ENOENT;
if (addr == NULL)
return EINVAL;
for (i = 0, j = 1; addr; addr = addr->next, j++)
......@@ -368,18 +109,6 @@ address_get_personal (address_t addr, size_t no, char *buf, size_t len,
break;
}
}
/* Remove the leading doublequotes. */
if (i && buf && *buf == '"')
{
memmove (buf, buf + 1, i - 1);
i--;
}
/* Remove the trailing doublequotes. */
if (i && buf && buf[i - 1] == '"')
{
buf[i - 1] = '\0';
i--;
}
if (n)
*n = i;
return status;
......@@ -390,7 +119,7 @@ address_get_comments (address_t addr, size_t no, char *buf, size_t len,
size_t *n)
{
size_t i, j;
int status = EINVAL;
int status = ENOENT;
if (addr == NULL)
return EINVAL;
for (j = 1; addr; addr = addr->next, j++)
......@@ -411,7 +140,7 @@ int
address_get_email (address_t addr, size_t no, char *buf, size_t len, size_t *n)
{
size_t i, j;
int status = EINVAL;
int status = ENOENT;
if (addr == NULL)
return EINVAL;
for (j = 1; addr; addr = addr->next, j++)
......@@ -432,7 +161,7 @@ int
address_get_local_part (address_t addr, size_t no, char *buf, size_t len, size_t *n)
{
size_t i, j;
int status = EINVAL;
int status = ENOENT;
if (addr == NULL)
return EINVAL;
for (j = 1; addr; addr = addr->next, j++)
......@@ -453,7 +182,7 @@ int
address_get_domain (address_t addr, size_t no, char *buf, size_t len, size_t *n)
{
size_t i, j;
int status = EINVAL;
int status = ENOENT;
if (addr == NULL)
return EINVAL;
for (j = 1; addr; addr = addr->next, j++)
......@@ -474,7 +203,7 @@ int
address_get_route (address_t addr, size_t no, char *buf, size_t len, size_t *n)
{
size_t i, j;
int status = EINVAL;
int status = ENOENT;
if (addr == NULL)
return EINVAL;
for (j = 1; addr; addr = addr->next, j++)
......
......@@ -23,9 +23,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <mailutils/message.h>
#include <mailutils/filter.h>
#include <mailutils/stream.h>
#define MAX_HDR_LEN 256
......@@ -75,7 +77,7 @@ int message_create_attachment(const char *content_type, const char *encoding, co
message_get_body(*newmsg, &body);
if ( ( ret = file_stream_create(&fstream) ) == 0 ) {
if ( ( ret = stream_open(fstream, filename, 0, MU_STREAM_READ) ) == 0 ) {
if ( ( ret = encoder_stream_create(&tstream, fstream, encoding) ) == 0 ) {
if ( ( ret = filter_create(&tstream, fstream, encoding, MU_FILTER_ENCODE, MU_STREAM_READ) ) == 0 ) {
body_set_stream(body, tstream, *newmsg);
message_set_header(*newmsg, hdr, NULL);
}
......@@ -245,7 +247,7 @@ int message_save_attachment(message_t msg, const char *filename, void **data)
header_get_value(hdr, "Content-Transfer-Encoding", content_encoding, size+1, 0);
} else
content_encoding = (char *)"7bit";
ret = decoder_stream_create(&info->ostream, fstream, content_encoding);
ret = filter_create(&info->ostream, fstream, content_encoding, MU_FILTER_DECODE, MU_STREAM_READ);
}
}
}
......
......@@ -211,7 +211,7 @@ body_set_lines (body_t body, int (*_lines)(body_t, size_t *), void *owner)
{
if (body == NULL)
return EINVAL;
if (body->owner == owner)
if (body->owner != owner)
return EACCES;
body->_lines = _lines;
return 0;
......
......@@ -28,7 +28,7 @@
# include <pthread.h>
#endif
#include <mailutils/filter.h>
#include <filter0.h>
#include <mailutils/property.h>
static int rfc822_property __P ((property_t, const char *, const char *));
......@@ -46,23 +46,17 @@ struct rfc822
int residue;
};
static struct _filter _rfc822_filter =
static struct _filter_record _rfc822_filter =
{
"RFC822",
rfc822_init,
rfc822_read,
rfc822_readline,
NULL,
rfc822_destroy,
NULL,
NULL,
NULL,
0,
NULL
};
/* Exported. */
filter_t rfc822_filter = &_rfc822_filter;
filter_record_t rfc822_filter = &_rfc822_filter;
static int
rfc822_property (property_t property, const char *key, const char *value)
......@@ -82,6 +76,11 @@ rfc822_init (filter_t filter)
filter->data = calloc (1, sizeof (struct rfc822));
if (filter->data == NULL)
return ENOMEM;
filter->_read = rfc822_read;
filter->_readline = rfc822_readline;
filter->_destroy = rfc822_destroy;
/* We are interested in this property. */
if ((status = stream_get_property (filter->filter_stream, &property) != 0)
|| (status = property_add_defaults (property, "LINES", "0",
......
......@@ -16,7 +16,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Notes:
First Draft: Dave Inglis.
*/
#ifdef HAVE_CONFIG_H
......@@ -28,18 +28,72 @@
#include <stdlib.h>
#include <string.h>
#include <mailutils/stream.h>
#include <filter0.h>
#define MU_TRANS_DECODE 1
#define MU_TRANS_ENCODE 2
#define MU_TRANS_BSIZE 2048
static int qp_init __P ((filter_t));
static int base64_init __P ((filter_t));
static struct _filter_record _qp_filter =
{
"quoted-printable",
qp_init,
NULL,
NULL,
NULL
};
static struct _filter_record _base64_filter =
{
"base64",
base64_init,
NULL,
NULL,
NULL
};
static struct _filter_record _bit8_filter =
{
"8bit",
NULL,
NULL,
NULL,
NULL
};
static struct _filter_record _bit7_filter =
{
"7bit",
NULL,
NULL,
NULL,
NULL
};
static struct _filter_record _binary_filter =
{
"binary",
NULL,
NULL,
NULL,
NULL
};
/* Export. */
filter_record_t qp_filter = &_qp_filter;
filter_record_t base64_filter = &_base64_filter;
filter_record_t binary_filter = &_binary_filter;
filter_record_t bit8_filter = &_bit8_filter;
filter_record_t bit7_filter = &_bit7_filter;
struct _trans_stream
{
stream_t stream; /* encoder/decoder read/writes data to/from here */
int t_offset;
int t_offset; /* Orignal stream offset. */
int min_size;
size_t min_size;
int s_offset;
char *s_buf; /* Used when read if not big enough to handle min_size
for decoder/encoder */
......@@ -55,53 +109,30 @@ struct _trans_stream
size_t osize, size_t *nbytes, int *line_len));
};
struct _ts_desc
{
const char *encoding;
int (*_init) __P ((struct _trans_stream *ts, int type));
int (*_decode) __P ((const char *iptr, size_t isize, char *optr,
size_t osize, size_t *nbytes, int *line_len));
int (*_encode) __P ((const char *iptr, size_t isize, char *optr,
size_t osize, size_t *nbytes, int *line_len));
};
static int _base64_init __P ((struct _trans_stream *ts, int type));
static int _base64_decode __P ((const char *iptr, size_t isize, char *optr,
static int base64_decode __P ((const char *iptr, size_t isize, char *optr,
size_t osize, size_t *nbytes, int *line_len));
static int _base64_encode __P ((const char *iptr, size_t isize, char *optr,
static int base64_encode __P ((const char *iptr, size_t isize, char *optr,
size_t osize, size_t *nbytes, int *line_len));
static int _qp_init __P ((struct _trans_stream *ts, int type));
static int _qp_decode __P ((const char *iptr, size_t isize, char *optr,
static int qp_decode __P ((const char *iptr, size_t isize, char *optr,
size_t osize, size_t *nbytes, int *line_len));
static int _qp_encode __P ((const char *iptr, size_t isize, char *optr,
static int qp_encode __P ((const char *iptr, size_t isize, char *optr,
size_t osize, size_t *nbytes, int *line_len));
/* #define NUM_TRANSCODERS 6 */
/* struct _ts_desc tslist[NUM_TRANSCODERS] = */
struct _ts_desc tslist[] =
{
{ "base64", _base64_init, _base64_decode, _base64_encode },
{ "quoted-printable", _qp_init, _qp_decode, _qp_encode },
{ "7bit", NULL, NULL, NULL },
{ "8bit", NULL, NULL, NULL },
{ "binary", NULL, NULL, NULL }
};
static void
_trans_destroy (stream_t stream)
trans_destroy (filter_t filter)
{
struct _trans_stream *ts = stream_get_owner (stream);
stream_destroy (&(ts->stream), NULL);
struct _trans_stream *ts = filter->data;
if (ts->s_buf)
free (ts->s_buf);
free (ts);
}
static int
_trans_read (stream_t stream, char *optr, size_t osize, off_t offset,
trans_read (filter_t filter, char *optr, size_t osize, off_t offset,
size_t *n_bytes)
{
struct _trans_stream *ts = stream_get_owner (stream);
struct _trans_stream *ts = filter->data;
size_t obytes, wbytes;
int ret = 0, i;
size_t bytes, *nbytes = &bytes;
......@@ -109,9 +140,6 @@ _trans_read (stream_t stream, char *optr, size_t osize, off_t offset,
if (optr == NULL || osize == 0)
return EINVAL;
if (ts->transcoder == NULL)
return stream_read (ts->stream, optr, osize, offset, n_bytes);
if (n_bytes)
nbytes = n_bytes;
*nbytes = 0;
......@@ -125,12 +153,12 @@ _trans_read (stream_t stream, char *optr, size_t osize, off_t offset,
while (*nbytes < osize)
{
if ((ts->w_rhd + ts->min_size) >= ts->w_whd)
if ((ts->w_rhd + (int)ts->min_size) >= ts->w_whd)
{
memmove (ts->w_buf, ts->w_buf + ts->w_rhd, ts->w_whd - ts->w_rhd);
ts->w_whd = ts->w_whd - ts->w_rhd;
ts->w_rhd = 0;
ret = stream_read (ts->stream, ts->w_buf + ts->w_whd,
ret = stream_read (filter->stream, ts->w_buf + ts->w_whd,
MU_TRANS_BSIZE - ts->w_whd, ts->offset,
&wbytes );
if (ret != 0)
......@@ -182,62 +210,23 @@ _trans_read (stream_t stream, char *optr, size_t osize, off_t offset,
return ret;
}
#if 0
static int
_trans_write (stream_t stream, const char *iptr, size_t isize, off_t offset,
trans_write (stream_t stream, const char *iptr, size_t isize, off_t offset,
size_t *nbytes)
{
struct _trans_stream *ts = stream_get_owner (stream);
return stream_write (ts->stream, iptr, isize, offset, nbytes);
}
#endif
static int
_trans_open (stream_t stream, const char *filename, int port, int flags)
{
struct _trans_stream *ts = stream_get_owner (stream);
return stream_open (ts->stream, filename, port, flags);
}
static int
_trans_truncate (stream_t stream, off_t len)
{
struct _trans_stream *ts = stream_get_owner (stream);
return stream_truncate (ts->stream, len);
}
static int
_trans_size (stream_t stream, off_t *psize)
{
struct _trans_stream *ts = stream_get_owner (stream);
return stream_size (ts->stream, psize);
}
static int
_trans_flush (stream_t stream)
{
struct _trans_stream *ts = stream_get_owner(stream);
return stream_flush (ts->stream);
}
static int
_trans_get_fd (stream_t stream, int *pfd)
{
struct _trans_stream *ts = stream_get_owner (stream);
return stream_get_fd (ts->stream, pfd);
}
static int
_trans_close (stream_t stream)
{
struct _trans_stream *ts = stream_get_owner (stream);
return stream_close (ts->stream);
}
/*------------------------------------------------------
* base64 encode/decode
*----------------------------------------------------*/
static int
_b64_input (char c)
b64_input (char c)
{
const char table[64] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
......@@ -252,29 +241,43 @@ _b64_input (char c)
}
static int
_base64_init (struct _trans_stream *ts, int type)
base64_init (filter_t filter)
{
struct _trans_stream *ts;
ts = calloc (sizeof (*ts), 1);
if (ts == NULL)
return ENOMEM;
ts->min_size = 4;
ts->s_buf = calloc (4, 1);
if (ts->s_buf == NULL)
return ENOMEM;
{
free (ts);
return ENOMEM;
}
ts->transcoder = (filter->type == MU_FILTER_DECODE) ? base64_decode : base64_encode;
filter->_read = trans_read;
filter->_destroy = trans_destroy;
filter->data = ts;
return 0;
}
static int
_base64_decode (const char *iptr, size_t isize, char *optr, size_t osize,
size_t *nbytes, int *line_len)
base64_decode (const char *iptr, size_t isize, char *optr, size_t osize,
size_t *nbytes, int *line_len)
{
int i = 0, tmp = 0, pad = 0;
size_t consumed = 0;
char data[4];
(void) line_len;
*nbytes = 0;
while (consumed < isize && (*nbytes)+3 < osize)
{
while (( i < 4 ) && (consumed < isize))
{
tmp = _b64_input (*iptr++);
tmp = b64_input (*iptr++);
consumed++;
if (tmp != -1)
data[i++] = tmp;
......@@ -306,8 +309,8 @@ _base64_decode (const char *iptr, size_t isize, char *optr, size_t osize,
#define BASE64_LINE_MAX 77
static int
_base64_encode (const char *iptr, size_t isize, char *optr, size_t osize,
size_t *nbytes, int *line_len)
base64_encode (const char *iptr, size_t isize, char *optr, size_t osize,
size_t *nbytes, int *line_len)
{
size_t consumed = 0;
int pad = 0;
......@@ -348,23 +351,37 @@ _base64_encode (const char *iptr, size_t isize, char *optr, size_t osize,
static const char _hexdigits[16] = "0123456789ABCDEF";
static int
_qp_init (struct _trans_stream *ts, int type)
qp_init (filter_t filter)
{
struct _trans_stream *ts;
ts = calloc (sizeof (*ts), 1);
if (ts == NULL)
return ENOMEM;
ts->min_size = 4;
ts->s_buf = calloc (4, 1);
if (ts->s_buf == NULL)
return ENOMEM;
{
free (ts);
return ENOMEM;
}
ts->transcoder = (filter->type == MU_FILTER_DECODE) ? qp_decode : qp_encode;
filter->_read = trans_read;
filter->_destroy = trans_destroy;
filter->data = ts;
return 0;
}
static int
_qp_decode (const char *iptr, size_t isize, char *optr, size_t osize,
size_t *nbytes, int *line_len)
qp_decode (const char *iptr, size_t isize, char *optr, size_t osize,
size_t *nbytes, int *line_len)
{
char c;
int last_char = 0;
size_t consumed = 0;
(void)line_len;
*nbytes = 0;
while (consumed < isize && *nbytes < osize)
{
......@@ -430,15 +447,15 @@ _qp_decode (const char *iptr, size_t isize, char *optr, size_t osize,
return consumed;
}
static int
_qp_encode (const char *iptr, size_t isize, char *optr, size_t osize,
size_t *nbytes, int *line_len)
qp_encode (const char *iptr, size_t isize, char *optr, size_t osize,
size_t *nbytes, int *line_len)
{
#define QP_LINE_MAX 76
int c;
size_t consumed = 0;
(void)osize;
*nbytes = 0;
while (consumed < isize && (*nbytes + 4) < isize)
{
......@@ -484,119 +501,3 @@ _qp_encode (const char *iptr, size_t isize, char *optr, size_t osize,
}
return consumed;
}
int
encoder_stream_create (stream_t *stream, stream_t iostream,
const char *encoding)
{
struct _trans_stream *ts;
int i, ret;
int NUM_TRANSCODERS = sizeof (tslist)/sizeof (*tslist);
if (stream == NULL || iostream == NULL || encoding == NULL)
return EINVAL;
ts = calloc (sizeof (struct _trans_stream), 1);
if (ts == NULL)
return ENOMEM;
for (i = 0; i < NUM_TRANSCODERS; i++)
{
if (strcasecmp (encoding, tslist[i].encoding) == 0)
break;
}
if (i == NUM_TRANSCODERS)
{
free (ts);
return ENOTSUP;
}
if (tslist[i]._init != NULL)
{
ret = tslist[i]._init (ts, MU_TRANS_ENCODE);
if (ret != 0)
{
free (ts);
return ret;
}
}
ret = stream_create (stream, MU_STREAM_RDWR | MU_STREAM_NO_CHECK, ts);
if (ret != 0)
{
free (ts);
return ret;
}
ts->transcoder = tslist[i]._encode;
ts->stream = iostream;
stream_set_open (*stream, _trans_open, ts);
stream_set_close (*stream, _trans_close, ts);
stream_set_fd (*stream, _trans_get_fd, ts);
stream_set_truncate (*stream, _trans_truncate, ts);
stream_set_size (*stream, _trans_size, ts);
stream_set_flush (*stream, _trans_flush, ts);
stream_set_read (*stream, _trans_read, ts);
stream_set_write (*stream, _trans_write, ts);
stream_set_destroy (*stream, _trans_destroy, ts);
return ret;
}
int
decoder_stream_create (stream_t *stream, stream_t iostream,
const char *encoding)
{
struct _trans_stream *ts;
int i, ret;
int NUM_TRANSCODERS = sizeof (tslist)/sizeof (*tslist);
if (stream == NULL || iostream == NULL || encoding == NULL)
return EINVAL;
ts = calloc (sizeof (struct _trans_stream), 1);
if (ts == NULL )
return ENOMEM;
for (i = 0; i < NUM_TRANSCODERS; i++)
{
if (strcasecmp (encoding, tslist[i].encoding) == 0)
break;
}
if (i == NUM_TRANSCODERS)
{
free (ts);
return ENOTSUP;
}
if (tslist[i]._init != NULL)
{
ret = tslist[i]._init (ts, MU_TRANS_DECODE);
if (ret != 0)
{
free (ts);
return ret;
}
}
ret = stream_create (stream, MU_STREAM_RDWR | MU_STREAM_NO_CHECK, ts);
if (ret != 0)
{
free (ts);
return ret;
}
ts->transcoder = tslist[i]._decode;
ts->stream = iostream;
stream_set_open (*stream, _trans_open, ts );
stream_set_close (*stream, _trans_close, ts );
stream_set_fd (*stream, _trans_get_fd, ts );
stream_set_truncate (*stream, _trans_truncate, ts );
stream_set_size (*stream, _trans_size, ts );
stream_set_flush (*stream, _trans_flush, ts );
stream_set_read (*stream, _trans_read, ts);
stream_set_write (*stream, _trans_write, ts);
stream_set_destroy (*stream, _trans_destroy, ts);
return ret;
}
......
......@@ -34,11 +34,6 @@
/* Internal folder list. */
static list_t known_folder_list;
static int is_known_folder __P ((url_t, folder_t *));
static int is_same_scheme __P ((url_t, url_t));
static int is_same_user __P ((url_t, url_t));
static int is_same_path __P ((url_t, url_t));
static int is_same_host __P ((url_t, url_t));
static int is_same_port __P ((url_t, url_t));
/* Static folder lock. */
static struct _monitor folder_lock = MU_MONITOR_INITIALIZER;
......@@ -200,6 +195,7 @@ folder_destroy (folder_t *pfolder)
if (folder->stream)
stream_destroy (&(folder->stream), folder);
if (folder->url)
url_destroy (&(folder->url));
free (folder);
}
......@@ -210,7 +206,6 @@ folder_destroy (folder_t *pfolder)
}
}
/* Cover functions. */
int
folder_open (folder_t folder, int flags)
......@@ -410,8 +405,6 @@ folder_get_url (folder_t folder, url_t *purl)
return 0;
}
/* ---------------------- Private ---------------------- */
static int is_known_folder (url_t url, folder_t *pfolder)
{
int ret = 0;
......@@ -430,126 +423,18 @@ static int is_known_folder (url_t url, folder_t *pfolder)
iterator_current (iterator, (void **)&folder);
/* Check if the same URL type. */
if (folder && folder->url
&& is_same_scheme (url, folder->url)
&& is_same_user (url, folder->url)
&& is_same_path (url, folder->url)
&& is_same_host (url, folder->url)
&& is_same_port (url, folder->url))
&& url_is_same_scheme (url, folder->url)
&& url_is_same_user (url, folder->url)
&& url_is_same_host (url, folder->url)
/*&& url_is_same_path (url, folder->url) */
&& url_is_same_port (url, folder->url))
{
ret = 1;
break;
}
}
if (ret)
*pfolder = folder;
iterator_destroy (&iterator);
return ret;
}
static int
is_same_scheme (url_t url1, url_t url2)
{
size_t i = 0, j = 0;
char *s1, *s2;
int ret = 1;
url_get_scheme (url1, NULL, 0, &i);
url_get_scheme (url2, NULL, 0, &j);
s1 = calloc (i + 1, sizeof (char));
if (s1)
{
url_get_scheme (url1, s1, i + 1, NULL);
s2 = calloc (j + 1, sizeof (char));
if (s2)
{
url_get_scheme (url2, s2, j + 1, NULL);
ret = !strcasecmp (s1, s2);
free (s2);
}
free (s1);
}
return ret;
}
static int
is_same_user (url_t url1, url_t url2)
{
size_t i = 0, j = 0;
char *s1, *s2;
int ret = 0;
url_get_user (url1, NULL, 0, &i);
url_get_user (url2, NULL, 0, &j);
s1 = calloc (i + 1, sizeof (char));
if (s1)
{
url_get_user (url1, s1, i + 1, NULL);
s2 = calloc (j + 1, sizeof (char));
if (s2)
{
url_get_user (url2, s2, j + 1, NULL);
ret = !strcasecmp (s1, s2);
free (s2);
}
free (s1);
}
return ret;
}
static int
is_same_path (url_t url1, url_t url2)
{
size_t i = 0, j = 0;
char *s1, *s2;
int ret = 0;
url_get_path (url1, NULL, 0, &i);
url_get_path (url2, NULL, 0, &j);
s1 = calloc (i + 1, sizeof (char));
if (s1)
{
url_get_path (url1, s1, i + 1, NULL);
s2 = calloc (j + 1, sizeof (char));
if (s2)
{
url_get_path (url2, s2, j + 1, NULL);
ret = !strcasecmp (s1, s2);
free (s2);
}
free (s1);
}
return ret;
}
static int
is_same_host (url_t url1, url_t url2)
{
size_t i = 0, j = 0;
char *s1, *s2;
int ret = 0;
url_get_host (url1, NULL, 0, &i);
url_get_host (url2, NULL, 0, &j);
s1 = calloc (i + 1, sizeof (char));
if (s1)
{
url_get_host (url1, s1, i + 1, NULL);
s2 = calloc (j + 1, sizeof (char));
if (s2)
{
url_get_host (url2, s2, j + 1, NULL);
ret = !strcasecmp (s1, s2);
free (s2);
}
free (s1);
}
return ret;
}
static int
is_same_port (url_t url1, url_t url2)
{
long p1 = 0, p2 = 0;
url_get_port (url1, &p1);
url_get_port (url2, &p2);
return (p1 == p2);
}
......
......@@ -53,6 +53,7 @@ record_t imap_record = &_imap_record;
/* Concrete IMAP implementation. */
static int folder_imap_open __P ((folder_t, int));
static int folder_imap_create __P ((folder_t));
static int folder_imap_close __P ((folder_t));
static void folder_imap_destroy __P ((folder_t));
static int folder_imap_delete __P ((folder_t, const char *));
......@@ -211,7 +212,9 @@ folder_imap_open (folder_t folder, int flags)
monitor_wrlock (folder->monitor);
if (f_imap->isopen)
{
monitor_wrlock (folder->monitor);
monitor_unlock (folder->monitor);
if (flags & MU_STREAM_CREAT)
status = folder_imap_create (folder);
return 0;
}
monitor_unlock (folder->monitor);
......@@ -324,6 +327,11 @@ folder_imap_open (folder_t folder, int flags)
monitor_wrlock (folder->monitor);
f_imap->isopen++;
monitor_unlock (folder->monitor);
if (flags & MU_STREAM_CREAT)
{
status = folder_imap_create (folder);
CHECK_EAGAIN (f_imap, status);
}
return 0;
}
......@@ -372,6 +380,51 @@ folder_imap_close (folder_t folder)
return 0;
}
/* Create a folder/mailbox. */
static int
folder_imap_create (folder_t folder)
{
f_imap_t f_imap = folder->data;
int status = 0;
switch (f_imap->state)
{
case IMAP_NO_STATE:
{
char *path;
size_t len;
url_get_path (folder->url, NULL, 0, &len);
if (len == 0)
return 0;
path = calloc (len + 1, sizeof (*path));
if (path == NULL)
return ENOMEM;
url_get_path (folder->url, path, len + 1, NULL);
status = imap_writeline (f_imap, "g%d CREATE %s\r\n", f_imap->seq++,
path);
free (path);
CHECK_ERROR (f_imap, status);
FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, f_imap->buffer);
f_imap->state = IMAP_CREATE;
}
case IMAP_CREATE:
status = imap_send (f_imap);
CHECK_EAGAIN (f_imap, status);
f_imap->state = IMAP_DELETE_ACK;
case IMAP_CREATE_ACK:
status = imap_parse (f_imap);
CHECK_EAGAIN (f_imap, status);
FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, f_imap->buffer);
default:
break;
}
f_imap->state = IMAP_NO_STATE;
return status;
}
/* Remove a mailbox. */
static int
folder_imap_delete (folder_t folder, const char *name)
......@@ -1528,9 +1581,9 @@ int
imap_send (f_imap_t f_imap)
{
int status = 0;
size_t len;
if (f_imap->ptr > f_imap->buffer)
{
size_t len;
len = f_imap->ptr - f_imap->buffer;
status = stream_write (f_imap->folder->stream, f_imap->buffer, len,
0, &len);
......@@ -1543,7 +1596,6 @@ imap_send (f_imap_t f_imap)
else
{
f_imap->ptr = f_imap->buffer;
len = 0;
}
return status;
}
......@@ -1823,18 +1875,18 @@ imap_parse (f_imap_t f_imap)
{
/* Not sure why we would get an untagged ok...but we do... */
/* Still should we be verbose about is ? */
printf("Untagged OK: %s\n", remainder);
fprintf (stderr, "Untagged OK: %s\n", remainder);
}
}
else if (strcasecmp (response, "NO") == 0)
{
/* This does not mean failure but rather a strong warning. */
printf ("Untagged NO: %s\n", remainder);
fprintf (stderr, "Untagged NO: %s\n", remainder);
}
else if (strcasecmp (response, "BAD") == 0)
{
/* We're dead, protocol/syntax error. */
printf ("Untagged BAD: %s\n", remainder);
fprintf (stderr, "Untagged BAD: %s\n", remainder);
}
else if (strcasecmp (response, "PREAUTH") == 0)
{
......@@ -1893,8 +1945,8 @@ imap_parse (f_imap_t f_imap)
else
{
/* Once again, check for something strange. */
printf("unknown untagged response: \"%s\" %s\n",
response, remainder);
fprintf (stderr, "unknown untagged response: \"%s\" %s\n",
response, remainder);
}
}
/* Continuation token ???. */
......@@ -1917,7 +1969,7 @@ imap_parse (f_imap_t f_imap)
folder_get_observable (f_imap->folder, &observable);
observable_notify (observable, MU_EVT_AUTHORITY_FAILED);
}
printf("NO/Bad Tagged: %s %s\n", response, remainder);
fprintf (stderr, "NO/Bad Tagged: %s %s\n", response, remainder);
status = EINVAL;
}
}
......
......@@ -5,6 +5,7 @@ auth0.h \
body0.h \
debug0.h \
envelope0.h \
filter0.h \
folder0.h \
header0.h \
iterator0.h \
......
/* 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. */
/* Notes:
*/
#ifndef _FILTER0_H
#define _FILTER0_H
#include <mailutils/filter.h>
#include <mailutils/list.h>
#include <mailutils/monitor.h>
#include <mailutils/property.h>
#ifndef __P
# ifdef __STDC__
# define __P(args) args
# else
# define __P(args) ()
# endif
#endif /*__P */
#ifdef __cplusplus
extern "C" {
#endif
struct _filter
{
stream_t stream;
stream_t filter_stream;
property_t property;
int direction;
int type;
void *data;
int (*_read) __P ((filter_t, char *, size_t, off_t, size_t *));
int (*_readline) __P ((filter_t, char *, size_t, off_t, size_t *));
int (*_write) __P ((filter_t, const char *, size_t, off_t, size_t *));
void (*_destroy) __P ((filter_t));
};
#ifdef __cplusplus
}
#endif
#endif /* _FILTER0_H */
......@@ -93,8 +93,11 @@ enum imap_state
{
IMAP_NO_STATE=0,
IMAP_AUTH, IMAP_AUTH_DONE,
IMAP_APPEND, IMAP_APPEND_CONT, IMAP_APPEND_SEND, IMAP_APPEND_ACK,
IMAP_BODY,
IMAP_CLOSE, IMAP_CLOSE_ACK,
IMAP_COPY, IMAP_COPY_ACK,
IMAP_CREATE, IMAP_CREATE_ACK,
IMAP_DELETE, IMAP_DELETE_ACK,
IMAP_FETCH, IMAP_FETCH_ACK,
IMAP_GREETINGS,
......
/* 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
......@@ -39,8 +39,8 @@ extern "C" {
# define __P(x)
# endif
#endif
extern size_t _cpystr __P ((char *dst, const char *src, size_t size));
extern int parseaddr __P ((const char *addr, char *buf, size_t bufsz));
#ifdef __cplusplus
}
......
......@@ -69,7 +69,7 @@ mailbox_create (mailbox_t *pmbox, const char *name)
if (found)
{
url_t url = NULL;
mailbox_t mbox = NULL;
mailbox_t mbox;
/* Allocate memory for mbox. */
mbox = calloc (1, sizeof (*mbox));
......
......@@ -34,58 +34,59 @@
#include <imap0.h>
/* Functions to overload the mailbox_t API. */
static void mailbox_imap_destroy (mailbox_t);
static int mailbox_imap_open (mailbox_t, int);
static int mailbox_imap_close (mailbox_t);
static int imap_uidvalidity (mailbox_t, unsigned long *);
static int imap_uidnext (mailbox_t, size_t *);
static int imap_expunge (mailbox_t);
static int imap_get_message (mailbox_t, size_t, message_t *);
static int imap_messages_count (mailbox_t, size_t *);
static int imap_messages_recent (mailbox_t, size_t *);
static int imap_message_unseen (mailbox_t, size_t *);
static int imap_scan (mailbox_t, size_t, size_t *);
static int imap_is_updated (mailbox_t);
static int imap_append_message (mailbox_t, message_t);
static void mailbox_imap_destroy __P ((mailbox_t));
static int mailbox_imap_open __P ((mailbox_t, int));
static int mailbox_imap_close __P ((mailbox_t));
static int imap_uidvalidity __P ((mailbox_t, unsigned long *));
static int imap_uidnext __P ((mailbox_t, size_t *));
static int imap_expunge __P ((mailbox_t));
static int imap_get_message __P ((mailbox_t, size_t, message_t *));
static int imap_messages_count __P ((mailbox_t, size_t *));
static int imap_messages_recent __P ((mailbox_t, size_t *));
static int imap_message_unseen __P ((mailbox_t, size_t *));
static int imap_scan __P ((mailbox_t, size_t, size_t *));
static int imap_is_updated __P ((mailbox_t));
static int imap_append_message __P ((mailbox_t, message_t));
static int imap_copy_message __P ((mailbox_t, message_t));
/* Message API. */
static int imap_submessage_size (msg_imap_t, size_t *);
static int imap_message_size (message_t, size_t *);
static int imap_message_lines (message_t, size_t *);
static int imap_message_fd (stream_t, int *);
static int imap_message_read (stream_t , char *, size_t, off_t, size_t *);
static int imap_message_uid (message_t, size_t *);
static int imap_submessage_size __P ((msg_imap_t, size_t *));
static int imap_message_size __P ((message_t, size_t *));
static int imap_message_lines __P ((message_t, size_t *));
static int imap_message_fd __P ((stream_t, int *));
static int imap_message_read __P ((stream_t , char *, size_t, off_t, size_t *));
static int imap_message_uid __P ((message_t, size_t *));
/* Mime handling. */
static int imap_is_multipart (message_t, int *);
static int imap_get_num_parts (message_t, size_t *);
static int imap_get_part (message_t, size_t, message_t *);
static int imap_is_multipart __P ((message_t, int *));
static int imap_get_num_parts __P ((message_t, size_t *));
static int imap_get_part __P ((message_t, size_t, message_t *));
/* Envelope. */
static int imap_envelope_sender (envelope_t, char *, size_t, size_t *);
static int imap_envelope_date (envelope_t, char *, size_t, size_t *);
static int imap_envelope_sender __P ((envelope_t, char *, size_t, size_t *));
static int imap_envelope_date __P ((envelope_t, char *, size_t, size_t *));
/* Attributes. */
static int imap_attr_get_flags (attribute_t, int *);
static int imap_attr_set_flags (attribute_t, int);
static int imap_attr_unset_flags (attribute_t, int);
static int imap_attr_get_flags __P ((attribute_t, int *));
static int imap_attr_set_flags __P ((attribute_t, int));
static int imap_attr_unset_flags __P ((attribute_t, int));
/* Header. */
static int imap_header_read (header_t, char*, size_t, off_t, size_t *);
static int imap_header_get_value (header_t, const char*, char *, size_t, size_t *);
static int imap_header_read __P ((header_t, char*, size_t, off_t, size_t *));
static int imap_header_get_value __P ((header_t, const char*, char *, size_t, size_t *));
/* Body. */
static int imap_body_read (stream_t, char *, size_t, off_t, size_t *);
static int imap_body_size (body_t, size_t *);
static int imap_body_lines (body_t, size_t *);
static int imap_body_fd (stream_t, int *);
static int imap_body_read __P ((stream_t, char *, size_t, off_t, size_t *));
static int imap_body_size __P ((body_t, size_t *));
static int imap_body_lines __P ((body_t, size_t *));
static int imap_body_fd __P ((stream_t, int *));
/* Private. */
static int imap_get_fd (msg_imap_t, int *);
static int imap_get_message0 (msg_imap_t, message_t *);
static int message_operation (f_imap_t, msg_imap_t, char *, size_t, size_t *);
static void free_subparts (msg_imap_t);
static int imap_get_fd __P ((msg_imap_t, int *));
static int imap_get_message0 __P ((msg_imap_t, message_t *));
static int message_operation __P ((f_imap_t, msg_imap_t, char *, size_t, size_t *));
static void free_subparts __P ((msg_imap_t));
static const char *MONTHS[] =
{
......@@ -650,12 +651,275 @@ imap_expunge (mailbox_t mailbox)
}
static int
imap_append_message (mailbox_t mailbox, message_t msg)
attribute_string (attribute_t attribute, char **pbuf)
{
(void)mailbox; (void)msg;
char *abuf = *pbuf;
if (attribute_is_deleted (attribute))
{
char *tmp = realloc (abuf, strlen (abuf) + strlen ("\\Deleted") + 2);
if (tmp == NULL)
{
free (abuf);
return ENOMEM;
}
abuf = tmp;
if (*abuf)
strcat (abuf, " ");
strcat (abuf, "\\Deleted");
}
if (attribute_is_seen (attribute))
{
char *tmp = realloc (abuf, strlen (abuf) + strlen ("\\Seen") + 2);
if (tmp == NULL)
{
free (abuf);
return ENOMEM;
}
abuf = tmp;
if (*abuf)
strcat (abuf, " ");
strcat (abuf, "\\Seen");
}
if (attribute_is_answered (attribute))
{
char *tmp = realloc (abuf, strlen (abuf) + strlen ("\\Answered") + 2);
if (tmp == NULL)
{
free (abuf);
return ENOMEM;
}
abuf = tmp;
if (*abuf)
strcat (abuf, " ");
strcat (abuf, "\\Answered");
}
if (attribute_is_draft (attribute))
{
char *tmp = realloc (abuf, strlen (abuf) + strlen ("\\Draft") + 2);
if (tmp == NULL)
{
free (abuf);
return ENOMEM;
}
abuf = tmp;
if (*abuf)
strcat (abuf, " ");
strcat (abuf, "\\Draft");
}
if (attribute_is_flagged (attribute))
{
char *tmp = realloc (abuf, strlen (abuf) + strlen ("\\Flagged") + 2);
if (tmp == NULL)
{
free (abuf);
return ENOMEM;
}
abuf = tmp;
if (*abuf)
strcat (abuf, " ");
strcat (abuf, "\\Flagged");
}
*pbuf = abuf;
return 0;
}
static int
is_same_folder (mailbox_t mailbox, message_t msg)
{
mailbox_t mbox = NULL;
message_get_mailbox (msg, &mbox);
return (mbox != NULL && mbox->url != NULL
&& url_is_same_scheme (mbox->url, mailbox->url)
&& url_is_same_host (mbox->url, mailbox->url)
&& url_is_same_port (mbox->url, mailbox->url));
}
/* Not Nonblocking safe. */
/* DANGER: The message_t object makes no guarenty the size and the lines
that it returns are exact if its pointing to non-local file messages.
FIXME: So we should download the message to a floating message so to
make sure that we know the exacte size then transmit it back the IMAP
server. */
static int
imap_append_message (mailbox_t mailbox, message_t msg)
{
size_t total;
int status;
m_imap_t m_imap = mailbox->data;
f_imap_t f_imap = m_imap->f_imap;
/* FIXME: Can we append to self. */
/* Check to see if we are selected. If the message was not modified
and came from the imap folder. use COPY.*/
if (f_imap->selected != m_imap && !message_is_modified (msg)
&& is_same_folder (mailbox, msg))
return imap_copy_message (mailbox, msg);
/* FIXME: Do we need to get the envelope_date? */
switch (f_imap->state)
{
case IMAP_NO_STATE:
{
size_t lines, size;
char *path;
char *abuf = malloc (1);
/* Get the desired flags attribute. */
if (abuf == NULL)
return ENOMEM;
*abuf = '\0';
{
attribute_t attribute = NULL;
message_get_attribute (msg, &attribute);
status = attribute_string (attribute, &abuf);
if (status != 0)
return status;
if (*abuf != '\0')
{
char *tmp = calloc (strlen (abuf) + 3, 1);
if (tmp == NULL)
{
free (abuf);
return ENOMEM;
}
sprintf (tmp, "(%s)", abuf);
free (abuf);
abuf = tmp;
}
}
{
size_t n = 0;
url_get_path (mailbox->url, NULL, 0, &n);
if (n == 0)
return EINVAL;
path = calloc (n + 1, sizeof (*path));
if (path == NULL)
return ENOMEM;
url_get_path (mailbox->url, path, n + 1, NULL);
}
lines = size = 0;
message_size (msg, &size);
message_lines (msg, &lines);
total = size + lines;
status = imap_writeline (f_imap, "g%d APPEND %s %s {%d}\r\n",
f_imap->seq++, path, abuf, size + lines);
free (abuf);
free (path);
CHECK_ERROR (f_imap, status);
MAILBOX_DEBUG0 (mailbox, MU_DEBUG_PROT, f_imap->buffer);
f_imap->state = IMAP_APPEND;
}
case IMAP_APPEND:
status = imap_send (f_imap);
CHECK_EAGAIN (f_imap, status);
MAILBOX_DEBUG0 (m_imap->mailbox, MU_DEBUG_PROT, f_imap->buffer);
f_imap->state = IMAP_APPEND_CONT;
case IMAP_APPEND_CONT:
status = imap_parse (f_imap);
CHECK_EAGAIN (f_imap, status);
MAILBOX_DEBUG0 (mailbox, MU_DEBUG_PROT, f_imap->buffer);
/* If we did not receive the continuation token, it is an error
bail out. */
if (f_imap->buffer[0] != '+')
{
status = EACCES;
break;
}
f_imap->state = IMAP_APPEND_SEND;
case IMAP_APPEND_SEND:
{
stream_t stream = NULL;
off_t off = 0;
size_t n = 0;
char buffer[255];
message_get_stream (msg, &stream);
while (stream_readline (stream, buffer, sizeof (buffer), off, &n) == 0
&& n > 0)
{
if (buffer[n - 1] == '\n')
{
buffer[n - 1] = '\0';
status = imap_writeline (f_imap, "%s\r\n", buffer);
}
else
imap_writeline (f_imap, "%s", buffer);
off += n;
status = imap_send (f_imap);
}
f_imap->state = IMAP_APPEND_ACK;
}
/* !@#%$ UW-IMAP server hack: insists on the last line. */
imap_writeline (f_imap, "\n");
imap_send (f_imap);
case IMAP_APPEND_ACK:
status = imap_parse (f_imap);
CHECK_EAGAIN (f_imap, status);
MAILBOX_DEBUG0 (m_imap->mailbox, MU_DEBUG_PROT, f_imap->buffer);
default:
/* fprintf (stderr, "imap_expunge: unknow state\n"); */
break;
}
f_imap->state = IMAP_NO_STATE;
return status;
}
/* Not Nonblocking safe. */
static int
imap_copy_message (mailbox_t mailbox, message_t msg)
{
m_imap_t m_imap = mailbox->data;
f_imap_t f_imap = m_imap->f_imap;
msg_imap_t msg_imap = message_get_owner (msg);
int status = 0;
switch (f_imap->state)
{
case IMAP_NO_STATE:
{
char *path;
/* Check for a valid mailbox name. */
{
size_t n = 0;
url_get_path (mailbox->url, NULL, 0, &n);
if (n == 0)
return EINVAL;
path = calloc (n + 1, sizeof (*path));
if (path == NULL)
return ENOMEM;
url_get_path (mailbox->url, path, n + 1, NULL);
}
status = imap_writeline (f_imap, "g%d COPY %d %s\r\n", f_imap->seq++,
msg_imap->num, path);
free (path);
CHECK_ERROR (f_imap, status);
MAILBOX_DEBUG0 (mailbox, MU_DEBUG_PROT, f_imap->buffer);
f_imap->state = IMAP_COPY;
}
case IMAP_COPY:
status = imap_send (f_imap);
CHECK_EAGAIN (f_imap, status);
MAILBOX_DEBUG0 (mailbox, MU_DEBUG_PROT, f_imap->buffer);
f_imap->state = IMAP_COPY_ACK;
case IMAP_COPY_ACK:
status = imap_parse (f_imap);
CHECK_EAGAIN (f_imap, status);
MAILBOX_DEBUG0 (mailbox, MU_DEBUG_PROT, f_imap->buffer);
default:
break;
}
f_imap->state = IMAP_NO_STATE;
return status;
}
/* Message. */
static int
imap_message_read (stream_t stream, char *buffer, size_t buflen,
......@@ -1075,8 +1339,6 @@ imap_attr_set_flags (attribute_t attribute, int flags)
status = imap_writeline (f_imap, "g%d STORE %d +FLAGS.SILENT (%s %s %s %s)\r\n",
f_imap->seq++, msg_imap->num,
(flags & MU_ATTRIBUTE_ANSWERED) ? "\\Answered" : "",
(flags & MU_ATTRIBUTE_RECENT) ? "\\Recent" : "",
(flags & MU_ATTRIBUTE_READ) ? "\\Read" : "",
(flags & MU_ATTRIBUTE_SEEN) ? "\\Seen" : "",
(flags & MU_ATTRIBUTE_DRAFT) ? "\\Draft" : "",
(flags & MU_ATTRIBUTE_FLAGGED) ? "\\Flagged" : "");
......
......@@ -1124,7 +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;
*psize = mum->body_end - mum->body;
return 0;
}
......
......@@ -1770,9 +1770,9 @@ static int
pop_write (pop_data_t mpd)
{
int status = 0;
size_t len;
if (mpd->ptr > mpd->buffer)
{
size_t len;
len = mpd->ptr - mpd->buffer;
status = stream_write (mpd->mbox->stream, mpd->buffer, len, 0, &len);
if (status == 0)
......@@ -1782,10 +1782,7 @@ pop_write (pop_data_t mpd)
}
}
else
{
mpd->ptr = mpd->buffer;
len = 0;
}
mpd->ptr = mpd->buffer;
return status;
}
......
......@@ -30,8 +30,8 @@
#include "md5.h"
#include <misc.h>
#include <message0.h>
#include <mailutils/address.h>
static int message_read __P ((stream_t is, char *buf, size_t buflen,
off_t off, size_t *pnread ));
......@@ -213,6 +213,15 @@ message_get_property (message_t msg, property_t *pproperty)
}
int
message_get_mailbox (message_t msg, mailbox_t *pmailbox)
{
if (msg == NULL || pmailbox == NULL)
return EINVAL;
*pmailbox = msg->mailbox;
return 0;
}
int
message_set_mailbox (message_t msg, mailbox_t mailbox, void *owner)
{
if (msg == NULL)
......@@ -894,34 +903,16 @@ message_sender (envelope_t envelope, char *buf, size_t len, size_t *pnwrite)
if (status == 0 && n != 0)
{
char *sender;
char *addr;
address_t address = NULL;
sender = calloc (1, n + 1);
if (sender == NULL)
return ENOMEM;
addr = calloc (1, n + 1);
if (addr == NULL)
{
free (sender);
return ENOMEM;
}
header_get_value (header, MU_HEADER_FROM, sender, n + 1, NULL);
if (parseaddr (sender, addr, n + 1) == 0)
{
size_t i = strlen (addr);
n = (i > len) ? len : i;
if (buf && len > 0)
{
memcpy (buf, addr, n);
buf[n] = '\0';
}
free (addr);
free (sender);
if (pnwrite)
*pnwrite = n;
return 0;
}
free (addr);
if (address_create (&address, sender) == 0)
address_get_email (address, 1, buf, n + 1, pnwrite);
free (sender);
address_destroy (&address);
return 0;
}
else if (status == EAGAIN)
return status;
......
/* 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
......@@ -27,6 +27,8 @@
#include <ctype.h>
#include <stdlib.h>
/* Smart strncpy that always add the null and returns the number of bytes
written. */
size_t
_cpystr (char *dst, const char *src, size_t size)
{
......@@ -39,153 +41,3 @@ _cpystr (char *dst, const char *src, size_t size)
dst[len] = '\0';
return len;
}
/*
* parseaddr.c Read a valid RFC822 address with all the comments
* etc in it, and return _just_ the email address.
*
* Version: @(#)parseaddr.c 1.00 02-Apr-1999 miquels@cistron.nl
*
*/
struct token
{
struct token *next;
char word[1];
};
#define SKIPSPACE(p) do { while(*p && isspace((unsigned char)*p)) p++; } while(0)
/* Skip everything between quotes. */
static void
quotes (const char **ptr)
{
const char *p = *ptr;
p++;
while (*p && *p != '"')
{
if (*p == '\\' && p[1])
p++;
p++;
}
*ptr = p;
}
/* Return the next token. A token can be "<>()," or any "word". */
static struct token *
gettoken (const char **ptr)
{
struct token *tok;
const char *p = *ptr;
const char *begin;
int l, quit = 0;
SKIPSPACE(p);
begin = p;
while (!quit)
{
switch (*p)
{
case 0:
case ' ':
case '\t':
case '\n':
quit = 1;
break;
case '(':
case ')':
case '<':
case '>':
case ',':
if (p == begin)
p++;
quit = 1;
break;
case '\\':
if (p[1])
p++;
break;
case '"':
quotes (&p);
break;
}
if (!quit)
p++;
}
l = p - begin;
if (l == 0)
return NULL;
tok = malloc (sizeof (struct token) + l);
if (tok == NULL)
return NULL;
tok->next = NULL;
strncpy (tok->word, begin, l);
tok->word[l] = 0;
SKIPSPACE (p);
*ptr = p;
return tok;
}
/* Get email address from rfc822 address. */
int
parseaddr (const char *addr, char *buf, size_t bufsz)
{
const char *p;
struct token *t, *tok, *last;
struct token *brace = NULL;
int comment = 0;
int status = 0;
tok = last = NULL;
/* Read address, remove comments right away. */
p = addr;
while ((t = gettoken(&p)) != NULL && t->word[0] != ',')
{
if (t->word[0] == '(' || t->word[0] == ')' || comment)
{
free (t);
if (t->word[0] == '(')
comment++;
if (t->word[0] == ')')
comment--;
continue;
}
if (t->word[0] == '<')
brace = t;
if (tok)
last->next = t;
else
tok = t;
last = t;
}
/* Put extracted address into "buf" */
buf[0] = 0;
t = brace ? brace->next : tok;
for (; t && t->word[0] != ',' && t->word[0] != '>'; t = t->next)
{
if (strlen (t->word) >= bufsz)
{
status = -1;
break;
}
bufsz -= strlen (t->word);
strcat (buf, t->word);
}
/* Free list of tokens. */
for (t = tok; t; t = last)
{
last = t->next;
free (t);
}
return status;
}
......
......@@ -95,7 +95,7 @@ static int str_append_n(char** to, const char* from, size_t n)
if(!bigger) {
return ENOMEM;
}
*to = bigger;
} else {
*to = malloc(n + 1);
......@@ -283,7 +283,7 @@ int parse822_comment(const char** p, const char* e, char** comment)
if((rc = parse822_special(p, e, '('))) {
return rc;
}
while(*p != e) {
char c = **p;
......@@ -307,7 +307,7 @@ int parse822_comment(const char** p, const char* e, char** comment)
if(rc != EOK)
break;
}
if(*p == e) {
rc = EPARSE; /* end-of-comment not found */
}
......@@ -536,6 +536,8 @@ static int fill_mb(
return rc;
}
/* FIXME: Delete this one. adddress.c do the work now. */
#if 0
int address_create0 (address_t* a, const char* s)
{
/* 'a' must exist, and can't already have been initialized
......@@ -546,7 +548,7 @@ int address_create0 (address_t* a, const char* s)
if(!a || *a) {
return EINVAL;
}
status = parse822_address_list(a, (char*) s);
if(status == EOK) {
......@@ -566,6 +568,7 @@ int address_create0 (address_t* a, const char* s)
return status;
}
#endif
int parse822_address_list(address_t* a, const char* s)
{
......@@ -585,7 +588,7 @@ int parse822_address_list(address_t* a, const char* s)
{
/* An address can contain a group, so an entire
* list of addresses may have been appended, or no
* addresses at all. Walk to the end.
* addresses at all. Walk to the end.
*/
while(*n) {
n = &(*n)->next;
......@@ -626,7 +629,7 @@ int parse822_address(const char** p, const char* e, address_t* a)
/* address = mailbox / group */
int rc;
if((rc = parse822_mail_box(p, e, a)) == EPARSE)
rc = parse822_group(p, e, a);
......@@ -672,7 +675,7 @@ int parse822_group(const char** p, const char* e, address_t* a)
} else if(rc != EPARSE) {
break;
}
if((rc = parse822_special(p, e, ','))) {
/* the commas aren't optional */
break;
......@@ -785,7 +788,7 @@ int parse822_route_addr(const char** p, const char* e, address_t* a)
*p = save;
address_destroy(a);
return rc;
}
......@@ -898,7 +901,7 @@ int parse822_local_part(const char** p, const char* e, char** local_part)
return rc;
}
/* We've got a local-part, but keep looking for more. */
parse822_skip_comments(p, e);
/* If we get a parse error, we roll back to save2, but if
......@@ -992,7 +995,7 @@ int parse822_sub_domain(const char** p, const char* e, char** sub_domain)
*/
int rc;
if((rc = parse822_domain_ref(p, e, sub_domain)) == EPARSE)
rc = parse822_domain_literal(p, e, sub_domain);
......@@ -1157,6 +1160,4 @@ int parse822_field_body(const char** p, const char* e, Rope& fieldbody)
return 1;
}
#endif
......
/* 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
......@@ -196,3 +196,113 @@ url_to_string (const url_t url)
return "";
return url->name;
}
int
url_is_same_scheme (url_t url1, url_t url2)
{
size_t i = 0, j = 0;
char *s1, *s2;
int ret = 1;
url_get_scheme (url1, NULL, 0, &i);
url_get_scheme (url2, NULL, 0, &j);
s1 = calloc (i + 1, sizeof (char));
if (s1)
{
url_get_scheme (url1, s1, i + 1, NULL);
s2 = calloc (j + 1, sizeof (char));
if (s2)
{
url_get_scheme (url2, s2, j + 1, NULL);
ret = !strcasecmp (s1, s2);
free (s2);
}
free (s1);
}
return ret;
}
int
url_is_same_user (url_t url1, url_t url2)
{
size_t i = 0, j = 0;
char *s1, *s2;
int ret = 0;
url_get_user (url1, NULL, 0, &i);
url_get_user (url2, NULL, 0, &j);
s1 = calloc (i + 1, sizeof (char));
if (s1)
{
url_get_user (url1, s1, i + 1, NULL);
s2 = calloc (j + 1, sizeof (char));
if (s2)
{
url_get_user (url2, s2, j + 1, NULL);
ret = !strcasecmp (s1, s2);
free (s2);
}
free (s1);
}
return ret;
}
int
url_is_same_path (url_t url1, url_t url2)
{
size_t i = 0, j = 0;
char *s1, *s2;
int ret = 0;
url_get_path (url1, NULL, 0, &i);
url_get_path (url2, NULL, 0, &j);
s1 = calloc (i + 1, sizeof (char));
if (s1)
{
url_get_path (url1, s1, i + 1, NULL);
s2 = calloc (j + 1, sizeof (char));
if (s2)
{
url_get_path (url2, s2, j + 1, NULL);
ret = !strcasecmp (s1, s2);
free (s2);
}
free (s1);
}
return ret;
}
int
url_is_same_host (url_t url1, url_t url2)
{
size_t i = 0, j = 0;
char *s1, *s2;
int ret = 0;
url_get_host (url1, NULL, 0, &i);
url_get_host (url2, NULL, 0, &j);
s1 = calloc (i + 1, sizeof (char));
if (s1)
{
url_get_host (url1, s1, i + 1, NULL);
s2 = calloc (j + 1, sizeof (char));
if (s2)
{
url_get_host (url2, s2, j + 1, NULL);
ret = !strcasecmp (s1, s2);
free (s2);
}
free (s1);
}
return ret;
}
int
url_is_same_port (url_t url1, url_t url2)
{
long p1 = 0, p2 = 0;
url_get_port (url1, &p1);
url_get_port (url2, &p2);
return (p1 == p2);
}
......