Commit d22b2199 d22b2199ab813bf994afc2dbe8e033ffcc01d045 by Sergey Poznyakoff

Minor change in stream API. Improve POP3 client interface.

* include/mailutils/sys/stream.h (_MU_STR_EVENT_SET)
(_MU_STR_EVENT_CLR): New defines.
(_mu_stream) <event_cb, event_mask>: New members.
* mailbox/stream.c (_stream_setflag, _stream_clrflag): New static
functions.
All functions use these instead of setting/clearing flags directly.
(_mu_stream_cleareof, _mu_stream_seteof): New extern functions.
(_stream_cleareof): Remove define, use _mu_stream_cleareof instead.
(_stream_fill_buffer): Set EOF marker when end of stream is reached.

* mailbox/fltstream.c (filter_read): Call _mu_stream_seteof to set
EOF flag.

* include/mailutils/pop3.h: Get rid of the superfluous "extern" in
front of function prototypes.
Add new prototypes.
Remove extra whitespace.

* libproto/pop/pop3_capatst.c: New file.
* libproto/pop/pop3_list_cmd.c: New file.
* libproto/pop/pop3_listas.c: New file.
* libproto/pop/pop3_rdlist.c: New file.
* libproto/pop/pop3_uidl_cmd.c: New file.
* libproto/pop/pop3_uidlas.c: New file.
* libproto/pop/Makefile.am: Add new files.
* libproto/pop/pop3_capa.c (_mu_pop3_fill_list): Remove.
Use mu_pop3_read_list instead.
(capa_comp): New comparator for capa lists.
* libproto/pop/pop3_list.c (mu_pop3_list): Fix format specifier.
* libproto/pop/pop3_lista.c (mu_pop3_list_all): Rewrite.
* libproto/pop/pop3_retr.c (mu_pop3_retr) <MU_POP3_RETR_RX>: do not
reset state, this is done by the EOF event callback.
* libproto/pop/pop3_top.c (mu_pop3_top) <MU_POP3_TOP_RX>: Likewise.
* libproto/pop/pop3_stream.c (pop3_decode_state): New state pds_char.
Change semantics of pds_init.
(newstate, _pop3_decoder): Handle .\r\n in the initial state.
(_pop3_event_cb): New event callback.
(mu_pop3_filter_create): Set event callback on the filter stream.
* libproto/pop/pop3_uidla.c (mu_pop3_uidl_all): Rewrite.

* examples/Makefile.am (pop3client_CPPFLAGS): Add MU_APP_COMMON_INCLUDES.
* examples/pop3client.c: Rewrite command parser.
1 parent b94a6d3c
......@@ -111,6 +111,7 @@ sfrom_LDADD =\
@MU_AUTHLIBS@\
${MU_LIB_MAILUTILS}
pop3client_CPPFLAGS = @MU_APP_COMMON_INCLUDES@
pop3client_LDADD = \
../lib/libmuaux.la\
${MU_LIB_POP}\
......
......@@ -32,87 +32,99 @@ struct _mu_pop3;
typedef struct _mu_pop3 *mu_pop3_t;
#define MU_POP3_DEFAULT_PORT 110
#define MU_POP3_DEFAULT_SSL_PORT 995
extern int mu_pop3_create (mu_pop3_t *pop3);
extern void mu_pop3_destroy (mu_pop3_t *pop3);
int mu_pop3_create (mu_pop3_t *pop3);
void mu_pop3_destroy (mu_pop3_t *pop3);
extern int mu_pop3_set_carrier (mu_pop3_t pop3, mu_stream_t carrier);
extern int mu_pop3_get_carrier (mu_pop3_t pop3, mu_stream_t *pcarrier);
int mu_pop3_set_carrier (mu_pop3_t pop3, mu_stream_t carrier);
int mu_pop3_get_carrier (mu_pop3_t pop3, mu_stream_t *pcarrier);
extern int mu_pop3_connect (mu_pop3_t pop3);
extern int mu_pop3_disconnect (mu_pop3_t pop3);
int mu_pop3_connect (mu_pop3_t pop3);
int mu_pop3_disconnect (mu_pop3_t pop3);
extern int mu_pop3_set_timeout (mu_pop3_t pop3, int timeout);
extern int mu_pop3_get_timeout (mu_pop3_t pop3, int *timeout);
int mu_pop3_set_timeout (mu_pop3_t pop3, int timeout);
int mu_pop3_get_timeout (mu_pop3_t pop3, int *timeout);
#define MU_POP3_TRACE_CLR 0
#define MU_POP3_TRACE_SET 1
#define MU_POP3_TRACE_QRY 2
extern int mu_pop3_trace (mu_pop3_t pop3, int op);
int mu_pop3_trace (mu_pop3_t pop3, int op);
extern int mu_pop3_apop (mu_pop3_t pop3, const char *name, const char *digest);
int mu_pop3_apop (mu_pop3_t pop3, const char *name, const char *digest);
extern int mu_pop3_stls (mu_pop3_t pop3);
int mu_pop3_stls (mu_pop3_t pop3);
/* It is the responsability of the caller to call mu_iterator_destroy() when
done with the iterator. The items returned by the iterator are of type
"const char *", no processing is done on the item except the removal of
the trailing newline. */
extern int mu_pop3_capa (mu_pop3_t pop3, int reread,
mu_iterator_t *piter);
int mu_pop3_capa (mu_pop3_t pop3, int reread, mu_iterator_t *piter);
int pop3_capa_test (mu_pop3_t pop3, const char *name, const char **pret);
extern int mu_pop3_dele (mu_pop3_t pop3, unsigned int mesgno);
int mu_pop3_dele (mu_pop3_t pop3, unsigned int mesgno);
extern int mu_pop3_list (mu_pop3_t pop3, unsigned int mesgno, size_t *mesg_octet);
int mu_pop3_list (mu_pop3_t pop3, unsigned int mesgno, size_t *mesg_octet);
/* An iterator is return with the multi-line answer. It is the responsability
of the caller to call mu_iterator_destroy() to dispose of the iterator. */
extern int mu_pop3_list_all (mu_pop3_t pop3, mu_iterator_t *piterator);
/* Send the LIST command and prepare pop3 for receiving a multiline answer.
The caller is expected to obtain a stream via mu_pop3_stream_create,
or an iterator via mu_pop3_iterator_create and read data from them.
extern int mu_pop3_noop (mu_pop3_t pop3);
This function is not intended for use by a casual user, better use
mu_pop3_list_all or mu_pop3_list_all_stream. */
int mu_pop3_list_cmd (mu_pop3_t pop3);
int mu_pop3_list_all (mu_pop3_t pop3, mu_iterator_t *pitr);
int mu_pop3_list_all_stream (mu_pop3_t pop3, mu_stream_t *pstream);
extern int mu_pop3_pass (mu_pop3_t pop3, const char *pass);
int mu_pop3_noop (mu_pop3_t pop3);
extern int mu_pop3_quit (mu_pop3_t pop3);
int mu_pop3_pass (mu_pop3_t pop3, const char *pass);
int mu_pop3_quit (mu_pop3_t pop3);
/* A stream is returned with the multi-line answer. It is the responsability
of the caller to call mu_stream_destroy() to dipose of the stream. */
extern int mu_pop3_retr (mu_pop3_t pop3, unsigned int mesgno,
int mu_pop3_retr (mu_pop3_t pop3, unsigned int mesgno,
mu_stream_t *pstream);
extern int mu_pop3_rset (mu_pop3_t pop3);
int mu_pop3_rset (mu_pop3_t pop3);
extern int mu_pop3_stat (mu_pop3_t pop3, unsigned int *count,
size_t *octets);
int mu_pop3_stat (mu_pop3_t pop3, unsigned int *count, size_t *octets);
/* A stream is returned with the multi-line answer. It is the responsability
of the caller to call mu_stream_destroy() to dipose of the stream. */
extern int mu_pop3_top (mu_pop3_t pop3, unsigned int mesgno,
int mu_pop3_top (mu_pop3_t pop3, unsigned int mesgno,
unsigned int lines, mu_stream_t *pstream);
/* The uidl is malloc'ed and returned in puidl; it is the responsability of
the caller to free() the uild when done. */
extern int mu_pop3_uidl (mu_pop3_t pop3, unsigned int mesgno,
char **puidl);
/* An iterator is returned with the multi-line answer. It is the
responsability of the caller to call mu_iterator_destroy() to dispose of
the iterator. */
extern int mu_pop3_uidl_all (mu_pop3_t pop3, mu_iterator_t *piterator);
int mu_pop3_uidl (mu_pop3_t pop3, unsigned int mesgno, char **puidl);
extern int mu_pop3_user (mu_pop3_t pop3, const char *user);
/* Send the UIDL command and prepare pop3 for receiving a multiline answer.
The caller is expected to obtain a stream via mu_pop3_stream_create,
or an iterator via mu_pop3_iterator_create and read data from them.
This function is not intended for use by a casual user, better use
mu_pop3_uidl_all or mu_pop3_uidl_all_stream. */
int mu_pop3_uidl_all_cmd (mu_pop3_t pop3);
int mu_pop3_uidl_all (mu_pop3_t pop3, mu_iterator_t *piterator);
int mu_pop3_uidl_all_stream (mu_pop3_t pop3, mu_stream_t *pstream);
int mu_pop3_user (mu_pop3_t pop3, const char *user);
/* Returns the last command acknowledge. If the server supports RESP-CODE,
the message could be retrieved, but it is up to the caller to do the
parsing. */
extern int mu_pop3_response (mu_pop3_t pop3, size_t *nread);
int mu_pop3_response (mu_pop3_t pop3, size_t *nread);
extern int mu_pop3_writeline (mu_pop3_t pop3, const char *format, ...)
int mu_pop3_writeline (mu_pop3_t pop3, const char *format, ...)
MU_PRINTFLIKE(2,3);
extern int mu_pop3_sendline (mu_pop3_t pop3, const char *line);
extern int mu_pop3_getline (mu_pop3_t pop3);
int mu_pop3_sendline (mu_pop3_t pop3, const char *line);
int mu_pop3_getline (mu_pop3_t pop3);
int mu_pop3_read_list (mu_pop3_t pop3, mu_list_t list);
int mu_pop3_stream_to_list (mu_pop3_t pop3, mu_stream_t stream,
mu_list_t list);
#ifdef __cplusplus
}
......
......@@ -24,6 +24,9 @@
#define _MU_STR_INTERN_MASK 0xf000
#define _MU_STR_EVENT_SET 1
#define _MU_STR_EVENT_CLR 2
struct _mu_stream
{
int ref_count;
......@@ -54,6 +57,9 @@ struct _mu_stream
int (*truncate) (struct _mu_stream *, mu_off_t);
int (*shutdown) (struct _mu_stream *, int);
void (*event_cb) (struct _mu_stream *, int, int);
int event_mask;
const char *(*error_string) (struct _mu_stream *, int);
};
......@@ -65,6 +71,9 @@ int mu_stream_write_unbuffered (mu_stream_t stream,
const void *buf, size_t size,
int full_write, size_t *pnwritten);
void _mu_stream_cleareof (mu_stream_t str);
void _mu_stream_seteof (mu_stream_t str);
#define _MU_SWAP_FIRST_ONLY 0x01
#define _MU_SWAP_IOCTL_MUST_SUCCEED 0x02
......
......@@ -25,12 +25,13 @@ libmu_pop_la_LDFLAGS=-version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
libmu_pop_la_LIBADD = ${MU_LIB_AUTH} ${MU_LIB_MAILUTILS} @INTLLIBS@
# folder.c\
# mbox.c\
# url.c
# url.c\
# mbox.c
libmu_pop_la_SOURCES = \
\
pop3_apop.c \
pop3_capa.c \
pop3_capatst.c \
pop3_carrier.c \
pop3_connect.c \
pop3_create.c \
......@@ -39,10 +40,13 @@ libmu_pop_la_SOURCES = \
pop3_disconnect.c \
pop3_iterator.c \
pop3_lista.c \
pop3_listas.c \
pop3_list.c \
pop3_list_cmd.c \
pop3_noop.c \
pop3_pass.c \
pop3_quit.c \
pop3_rdlist.c \
pop3_readline.c \
pop3_response.c \
pop3_retr.c \
......@@ -54,7 +58,9 @@ libmu_pop_la_SOURCES = \
pop3_timeout.c \
pop3_top.c \
pop3_trace.c \
pop3_uidl_cmd.c \
pop3_uidla.c \
pop3_uidlas.c \
pop3_uidl.c \
pop3_user.c
......
......@@ -33,36 +33,18 @@
#include <mailutils/sys/pop3.h>
static int
string_comp (const void *item, const void *value)
capa_comp (const void *item, const void *value)
{
return strcmp (item, value);
}
int
_mu_pop3_fill_list (mu_pop3_t pop3, mu_list_t list)
{
mu_stream_t stream;
size_t n;
int status = mu_pop3_stream_create (pop3, &stream);
if (status)
return status;
while (mu_stream_getline (stream, &pop3->rdbuf, &pop3->rdsize, &n) == 0
&& n > 0)
const char *capa = item;
const char *needle = value;
for (; *needle; capa++, needle++)
{
char *np = strdup (pop3->rdbuf);
if (!np)
{
status = ENOMEM;
break;
}
mu_rtrim_class (np, MU_CTYPE_SPACE);
status = mu_list_append (list, np);
if (status)
break;
if (!*capa)
return 1;
if (mu_tolower (*capa) != mu_tolower (*needle))
return 1;
}
mu_stream_destroy (&stream);
return status;
return !(*capa == 0 || mu_isspace (*capa));
}
/*
......@@ -91,7 +73,7 @@ mu_pop3_capa (mu_pop3_t pop3, int reread, mu_iterator_t *piter)
status = mu_list_create (&pop3->capa);
if (status)
return status;
mu_list_set_comparator (pop3->capa, string_comp);
mu_list_set_comparator (pop3->capa, capa_comp);
mu_list_set_destroy_item (pop3->capa, mu_list_free_item);
switch (pop3->state)
......@@ -109,7 +91,7 @@ mu_pop3_capa (mu_pop3_t pop3, int reread, mu_iterator_t *piter)
pop3->state = MU_POP3_CAPA_RX;
case MU_POP3_CAPA_RX:
status = _mu_pop3_fill_list (pop3, pop3->capa);
status = mu_pop3_read_list (pop3, pop3->capa);
MU_POP3_CHECK_ERROR (pop3, status);
if (piter)
status = mu_list_get_iterator (pop3->capa, piter);
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003, 2004, 2005, 2007, 2010 Free Software Foundation,
Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <mailutils/list.h>
#include <mailutils/sys/pop3.h>
int
pop3_capa_test (mu_pop3_t pop3, const char *name, const char **pret)
{
int rc;
rc = mu_pop3_capa (pop3, 0, NULL);
if (rc)
return rc;
return mu_list_locate (pop3->capa, (void*) name, (void**)pret);
}
......@@ -40,7 +40,7 @@ mu_pop3_list (mu_pop3_t pop3, unsigned int msgno, size_t *psize)
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "LIST %d\r\n", msgno);
status = mu_pop3_writeline (pop3, "LIST %u\r\n", msgno);
MU_POP3_CHECK_ERROR (pop3, status);
MU_POP3_FCLR (pop3, MU_POP3_ACK);
pop3->state = MU_POP3_LIST;
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2004, 2007, 2010 Free Software
Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_list_cmd (mu_pop3_t pop3)
{
int status = 0;
if (pop3 == NULL)
return EINVAL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "LIST\r\n");
MU_POP3_CHECK_ERROR (pop3, status);
MU_POP3_FCLR (pop3, MU_POP3_ACK);
pop3->state = MU_POP3_LIST;
case MU_POP3_LIST:
status = mu_pop3_response (pop3, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
MU_POP3_CHECK_OK (pop3);
pop3->state = MU_POP3_LIST_RX;
case MU_POP3_LIST_RX:
/* The mu_iterator_t will read the stream and set the state to
MU_POP3_NO_STATE when done. */
break;
/* They must deal with the error first by reopening. */
case MU_POP3_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
......@@ -21,51 +21,19 @@
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_list_all (mu_pop3_t pop3, mu_iterator_t *piterator)
{
int status = 0;
int status = mu_pop3_list_cmd (pop3);
if (pop3 == NULL)
return EINVAL;
if (piterator == NULL)
return MU_ERR_OUT_PTR_NULL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "LIST\r\n");
MU_POP3_CHECK_ERROR (pop3, status);
MU_POP3_FCLR (pop3, MU_POP3_ACK);
pop3->state = MU_POP3_LIST;
if (status)
return status;
case MU_POP3_LIST:
status = mu_pop3_response (pop3, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
MU_POP3_CHECK_OK (pop3);
status = mu_pop3_iterator_create (pop3, piterator);
MU_POP3_CHECK_ERROR (pop3, status);
pop3->state = MU_POP3_LIST_RX;
case MU_POP3_LIST_RX:
/* The mu_iterator_t will read the stream and set the state to
MU_POP3_NO_STATE when done. */
break;
/* They must deal with the error first by reopening. */
case MU_POP3_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2004, 2007, 2010 Free Software
Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/sys/pop3.h>
int
mu_pop3_list_all_stream (mu_pop3_t pop3, mu_stream_t *pstream)
{
int status = mu_pop3_list_cmd (pop3);
if (status)
return status;
status = mu_pop3_stream_create (pop3, pstream);
MU_POP3_CHECK_ERROR (pop3, status);
pop3->state = MU_POP3_LIST_RX;
return status;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003, 2004, 2005, 2007, 2010 Free Software Foundation,
Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <mailutils/stream.h>
#include <mailutils/list.h>
#include <mailutils/cctype.h>
#include <mailutils/cstr.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_stream_to_list (mu_pop3_t pop3, mu_stream_t stream, mu_list_t list)
{
int status;
size_t n;
while (mu_stream_getline (stream, &pop3->rdbuf, &pop3->rdsize, &n) == 0
&& n > 0)
{
char *np = strdup (pop3->rdbuf);
if (!np)
{
status = ENOMEM;
break;
}
mu_rtrim_class (np, MU_CTYPE_SPACE);
status = mu_list_append (list, np);
if (status)
break;
}
return status;
}
int
mu_pop3_read_list (mu_pop3_t pop3, mu_list_t list)
{
mu_stream_t stream;
int status = mu_pop3_stream_create (pop3, &stream);
if (status)
return status;
status = mu_pop3_stream_to_list (pop3, stream, list);
mu_stream_destroy (&stream);
return status;
}
......@@ -48,12 +48,11 @@ mu_pop3_retr (mu_pop3_t pop3, unsigned int msgno, mu_stream_t *pstream)
status = mu_pop3_response (pop3, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
MU_POP3_CHECK_OK (pop3);
status = mu_pop3_stream_create (pop3, pstream);
MU_POP3_CHECK_ERROR (pop3, status);
pop3->state = MU_POP3_RETR_RX;
case MU_POP3_RETR_RX:
status = mu_pop3_stream_create (pop3, pstream);
MU_POP3_CHECK_ERROR (pop3, status);
pop3->state = MU_POP3_NO_STATE;
break;
/* They must deal with the error first by reopening. */
......
......@@ -39,6 +39,7 @@ struct mu_pop3_stream
enum pop3_decode_state
{
pds_init, /* initial state */
pds_char, /* Any character excepting [\r\n.] */
pds_cr, /* prev. char was \r */
pds_crlf, /* 2 prev. char were \r\n */
pds_dot, /* 3 prev. chars were \r\n. */
......@@ -56,6 +57,16 @@ newstate (int state, int c)
{
case '\r':
return pds_cr;
case '.':
return pds_dot;
}
break;
case pds_char:
switch (c)
{
case '\r':
return pds_cr;
}
break;
......@@ -93,7 +104,7 @@ newstate (int state, int c)
return pds_end;
}
}
return pds_init;
return pds_char;
}
/* Move min(isize,osize) bytes from iptr to optr, replacing each \r\n
......@@ -140,7 +151,7 @@ _pop3_decoder (void *xd,
if (*iptr == '\n')
continue;
}
else if (c == '.' && *pstate == pds_crlf)
else if (c == '.' && (*pstate == pds_init || *pstate == pds_crlf))
{
/* Make sure we have two more characters in the buffer */
if (i + 2 == isize)
......@@ -164,16 +175,39 @@ _pop3_decoder (void *xd,
return mu_filter_ok;
}
static void
_pop3_event_cb (mu_stream_t str, int ev, int flags)
{
if (ev == _MU_STR_EVENT_SET)
{
mu_transport_t trans[2];
if (mu_stream_ioctl (str, MU_IOCTL_GET_TRANSPORT, trans) == 0)
{
struct mu_pop3_stream *sp = (struct mu_pop3_stream *) trans[0];
sp->pop3->state = MU_POP3_NO_STATE;
}
}
}
static int
mu_pop3_filter_create (mu_stream_t *pstream, mu_stream_t stream)
{
int rc;
int *state = malloc (sizeof (*state));
if (!state)
return ENOMEM;
return mu_filter_stream_create (pstream, stream,
rc = mu_filter_stream_create (pstream, stream,
MU_FILTER_DECODE,
_pop3_decoder, state,
MU_STREAM_READ);
if (rc == 0)
{
mu_stream_t str = *pstream;
str->event_cb = _pop3_event_cb;
str->event_mask = _MU_STR_EOF;
}
return rc;
}
......@@ -257,6 +291,7 @@ mu_pop3_stream_create (mu_pop3_t pop3, mu_stream_t *pstream)
sp->stream.readdelim = _mu_pop3_readdelim;
sp->stream.flush = _mu_pop3_flush;
sp->stream.wait = _mu_pop3_wait;
sp->pop3 = pop3;
sp->done = 0;
str = (mu_stream_t) sp;
......
......@@ -48,12 +48,11 @@ mu_pop3_top (mu_pop3_t pop3, unsigned msgno, unsigned int lines,
status = mu_pop3_response (pop3, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
MU_POP3_CHECK_OK (pop3);
status = mu_pop3_stream_create (pop3, pstream);
MU_POP3_CHECK_ERROR (pop3, status);
pop3->state = MU_POP3_TOP_RX;
case MU_POP3_TOP_RX:
status = mu_pop3_stream_create (pop3, pstream);
MU_POP3_CHECK_ERROR (pop3, status);
pop3->state = MU_POP3_NO_STATE;
break;
/* They must deal with the error first by reopening. */
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003, 2004, 2007, 2010 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_uidl_all_cmd (mu_pop3_t pop3)
{
int status = 0;
if (pop3 == NULL)
return EINVAL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "UIDL\r\n");
MU_POP3_CHECK_ERROR (pop3, status);
MU_POP3_FCLR (pop3, MU_POP3_ACK);
pop3->state = MU_POP3_UIDL;
case MU_POP3_UIDL:
status = mu_pop3_response (pop3, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
MU_POP3_CHECK_OK (pop3);
pop3->state = MU_POP3_UIDL_RX;
case MU_POP3_UIDL_RX:
break;
/* They must deal with the error first by reopening. */
case MU_POP3_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
......@@ -20,50 +20,17 @@
# include <config.h>
#endif
#include <string.h>
# include <errno.h>
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_uidl_all (mu_pop3_t pop3, mu_iterator_t *piterator)
{
int status = 0;
if (pop3 == NULL)
return EINVAL;
if (piterator == NULL)
return MU_ERR_OUT_PTR_NULL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "UIDL\r\n");
MU_POP3_CHECK_ERROR (pop3, status);
MU_POP3_FCLR (pop3, MU_POP3_ACK);
pop3->state = MU_POP3_UIDL;
case MU_POP3_UIDL:
status = mu_pop3_response (pop3, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
MU_POP3_CHECK_OK (pop3);
int status = mu_pop3_uidl_all_cmd (pop3);
if (status)
return status;
status = mu_pop3_iterator_create (pop3, piterator);
MU_POP3_CHECK_ERROR (pop3, status);
pop3->state = MU_POP3_UIDL_RX;
case MU_POP3_UIDL_RX:
/* The mu_iterator_t will read the stream and set the state to
MU_POP3_NO_STATE when done. */
break;
/* They must deal with the error first by reopening. */
case MU_POP3_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003, 2004, 2007, 2010 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/sys/pop3.h>
int
mu_pop3_uidl_all_stream (mu_pop3_t pop3, mu_stream_t *pstream)
{
int status = mu_pop3_uidl_all_cmd (pop3);
if (status)
return status;
status = mu_pop3_stream_create (pop3, pstream);
MU_POP3_CHECK_ERROR (pop3, status);
pop3->state = MU_POP3_UIDL_RX;
return status;
}
......@@ -164,7 +164,7 @@ filter_read (mu_stream_t stream, char *buf, size_t size, size_t *pret)
return MU_ERR_FAILURE; /* FIXME: special error code? */
if (iobuf.eof)
{
stream->flags |= _MU_STR_EOF;
_mu_stream_seteof (stream);
stop = 1;
}
break;
......
......@@ -32,6 +32,22 @@
#include <mailutils/stream.h>
#include <mailutils/sys/stream.h>
static void
_stream_setflag (struct _mu_stream *stream, int flag)
{
if (stream->event_cb && (stream->event_mask & flag))
stream->event_cb (stream, _MU_STR_EVENT_SET, flag);
stream->flags |= flag;
}
static void
_stream_clrflag (struct _mu_stream *stream, int flag)
{
if (stream->event_cb && (stream->event_mask & flag))
stream->event_cb (stream, _MU_STR_EVENT_CLR, flag);
stream->flags &= ~flag;
}
int
mu_stream_seterr (struct _mu_stream *stream, int code, int perm)
{
......@@ -45,12 +61,23 @@ mu_stream_seterr (struct _mu_stream *stream, int code, int perm)
default:
if (perm)
stream->flags |= _MU_STR_ERR;
_stream_setflag (stream, _MU_STR_ERR);
}
return code;
}
#define _stream_cleareof(s) ((s)->flags &= ~_MU_STR_EOF)
void
_mu_stream_cleareof (mu_stream_t str)
{
_stream_clrflag (str, _MU_STR_EOF);
}
void
_mu_stream_seteof (mu_stream_t str)
{
_stream_setflag (str, _MU_STR_EOF);
}
#define _stream_advance_buffer(s,n) ((s)->cur += n, (s)->level -= n)
#define _stream_buffer_offset(s) ((s)->cur - (s)->buffer)
#define _stream_orig_level(s) ((s)->level + _stream_buffer_offset (s))
......@@ -82,9 +109,13 @@ _stream_fill_buffer (struct _mu_stream *stream)
for (n = 0;
n < stream->bufsize
&& (rc = mu_stream_read_unbuffered (stream,
&c, 1, 0, &rdn)) == 0
&& rdn; )
&c, 1, 0, &rdn)) == 0;)
{
if (rdn == 0)
{
_stream_setflag (stream, _MU_STR_EOF);
break;
}
stream->buffer[n++] = c;
if (c == '\n')
break;
......@@ -175,7 +206,7 @@ _stream_flush_buffer (struct _mu_stream *stream, int all)
}
else
{
stream->flags &= ~_MU_STR_DIRTY;
_stream_clrflag (stream, _MU_STR_DIRTY);
stream->level = 0;
}
stream->cur = stream->buffer;
......@@ -269,7 +300,7 @@ void
mu_stream_clearerr (mu_stream_t stream)
{
stream->last_err = 0;
stream->flags &= ~_MU_STR_ERR;
_stream_clrflag (stream, _MU_STR_ERR);
}
int
......@@ -327,7 +358,7 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
return rc;
if (rc)
return mu_stream_seterr (stream, rc, 1);
_stream_cleareof (stream);
_mu_stream_cleareof (stream);
}
if (pres)
......@@ -469,7 +500,7 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size,
{
if (rdbytes == 0)
{
stream->flags |= _MU_STR_EOF;
_stream_setflag (stream, _MU_STR_EOF);
break;
}
buf += rdbytes;
......@@ -487,7 +518,7 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size,
if (rc == 0)
{
if (nread == 0)
stream->flags |= _MU_STR_EOF;
_stream_setflag (stream, _MU_STR_EOF);
stream->bytes_in += nread;
}
mu_stream_seterr (stream, rc, rc != 0);
......@@ -551,7 +582,7 @@ mu_stream_write_unbuffered (mu_stream_t stream,
if (rc == 0)
stream->bytes_out += nwritten;
}
stream->flags |= _MU_STR_WRT;
_stream_setflag (stream, _MU_STR_WRT);
stream->offset += nwritten;
if (pnwritten)
*pnwritten = nwritten;
......@@ -806,7 +837,7 @@ mu_stream_write (mu_stream_t stream, const void *buf, size_t size,
nbytes += n;
bufp += n;
size -= n;
stream->flags |= _MU_STR_DIRTY;
_stream_setflag (stream, _MU_STR_DIRTY);
}
if (pnwritten)
*pnwritten = nbytes;
......@@ -835,7 +866,7 @@ mu_stream_flush (mu_stream_t stream)
return rc;
if ((stream->flags & _MU_STR_WRT) && stream->flush)
return stream->flush (stream);
stream->flags &= ~_MU_STR_WRT;
_stream_clrflag (stream, _MU_STR_WRT);
return 0;
}
......