Commit 10f8e961 10f8e961abb75053a515a9d93d51375dd95bd0f5 by Alain Magloire

Update the pop3/* diretory.

1 parent 35d245fc
2001-06-09 18:44 sroberts
2001-06-09 Alain Magloire
* mailbox2/pop3/pop3_open.c: Remove for pop3_connect.c
* mailbox2/pop3/pop3_close.c: Remove for pop3_disconnect.c
* mailbox2/pop3/pop3_connect.c: New.
* mailbox2/pop3/pop3_disconnect.c: New.
* mailbox2/include/mailutiils/error.h: New macro
MU_ERROR_OPERATION_CANCELED
* mailbox2/include/mailutils/pop3.h: Move the enum state in sys/pop3.h
2001-06-09 Sam Roberts
* rfc1738.txt, rfc2045.txt, rfc2046.txt, rfc2047.txt, rfc2049.txt,
rfc2088.txt, rfc2111.txt, rfc2192.txt, rfc2193.txt, rfc2221.txt,
......
......@@ -113,6 +113,12 @@ extern "C" {
# define MU_ERROR_INVALID_SEEK (MU_ERROR_RANGE + 12)
#endif
#if defined (ECANCELED)
# define MU_ERROR_OPERATION_CANCELED ECANCELED
#else
# define MU_ERROR_OPERATION_CANCELED (MU_ERROR_RANGE + 13)
#endif
typedef int (*error_pfn_t) __P ((const char *fmt, va_list ap));
extern int mu_error __P ((const char *fmt, ...));
......
......@@ -26,34 +26,13 @@ __MAILUTILS_BEGIN_DECLS
struct _pop3;
typedef struct _pop3* pop3_t;
enum pop3_state
{
POP3_NO_STATE,
POP3_OPEN, POP3_GREETINGS,
POP3_APOP, POP3_APOP_ACK,
POP3_AUTH, POP3_AUTH_ACK,
POP3_CAPA, POP3_CAPA_ACK, POP3_CAPA_RX,
POP3_DELE, POP3_DELE_ACK,
POP3_LIST, POP3_LIST_ACK, POP3_LIST_RX,
POP3_NOOP, POP3_NOOP_ACK,
POP3_PASS, POP3_PASS_ACK,
POP3_QUIT, POP3_QUIT_ACK,
POP3_RETR, POP3_RETR_ACK, POP3_RETR_RX,
POP3_RSET, POP3_RSET_ACK,
POP3_STAT, POP3_STAT_ACK,
POP3_TOP, POP3_TOP_ACK, POP3_TOP_RX,
POP3_UIDL, POP3_UIDL_ACK, POP3_UIDL_RX,
POP3_USER, POP3_USER_ACK,
POP3_DONE, POP3_UNKNOWN, POP3_ERROR
};
struct list_item
struct pop3_list_item
{
unsigned int msgno;
unsigned int size;
};
struct uidl_item
struct pop3_uidl_item
{
unsigned int msgno;
char *uidl;
......@@ -62,8 +41,8 @@ struct uidl_item
extern int pop3_create __P ((pop3_t *));
extern void pop3_destroy __P ((pop3_t));
extern int pop3_open __P ((pop3_t, const char *, unsigned int, int));
extern int pop3_close __P ((pop3_t));
extern int pop3_connect __P ((pop3_t, const char *, unsigned int));
extern int pop3_disconnect __P ((pop3_t));
extern int pop3_set_stream __P ((pop3_t, stream_t));
extern int pop3_get_stream __P ((pop3_t, stream_t *));
......@@ -71,8 +50,6 @@ extern int pop3_get_stream __P ((pop3_t, stream_t *));
extern int pop3_set_timeout __P ((pop3_t, unsigned int));
extern int pop3_get_timeout __P ((pop3_t, unsigned int *));
extern int pop3_get_state __P ((pop3_t, enum pop3_state *));
extern int pop3_apop __P ((pop3_t, const char *, const char *));
extern int pop3_capa __P ((pop3_t, iterator_t *));
extern int pop3_dele __P ((pop3_t, unsigned int));
......
......@@ -25,8 +25,33 @@
#include <mailutils/sys/iterator.h>
#include <mailutils/error.h>
#ifdef DMALLOC
# include <dmalloc.h>
#endif
__MAILUTILS_BEGIN_DECLS
enum pop3_state
{
POP3_NO_STATE,
POP3_CONNECT, POP3_GREETINGS,
POP3_APOP, POP3_APOP_ACK,
POP3_AUTH, POP3_AUTH_ACK,
POP3_CAPA, POP3_CAPA_ACK, POP3_CAPA_RX,
POP3_DELE, POP3_DELE_ACK,
POP3_LIST, POP3_LIST_ACK, POP3_LIST_RX,
POP3_NOOP, POP3_NOOP_ACK,
POP3_PASS, POP3_PASS_ACK,
POP3_QUIT, POP3_QUIT_ACK,
POP3_RETR, POP3_RETR_ACK, POP3_RETR_RX,
POP3_RSET, POP3_RSET_ACK,
POP3_STAT, POP3_STAT_ACK,
POP3_TOP, POP3_TOP_ACK, POP3_TOP_RX,
POP3_UIDL, POP3_UIDL_ACK, POP3_UIDL_RX,
POP3_USER, POP3_USER_ACK,
POP3_DONE, POP3_UNKNOWN, POP3_ERROR
};
struct p_iterator
{
struct _iterator base;
......
......@@ -25,6 +25,10 @@
#include <mailutils/sys/pop3.h>
#include <mailutils/md5-rsa.h>
/*
APOP name digest
a string identifying a mailbox and a MD5 digest string (both required)
*/
int
pop3_apop (pop3_t pop3, const char *user, const char *secret)
{
......@@ -33,12 +37,13 @@ pop3_apop (pop3_t pop3, const char *user, const char *secret)
if (pop3 == NULL)
return MU_ERROR_INVALID_PARAMETER;
/* The server did not offer a time stamp, bail early. */
/* The server did not offer a time stamp in the greeting, bailout early. */
if (pop3->timestamp == NULL)
return MU_ERROR_NOT_SUPPORTED;
switch (pop3->state)
{
/* Generate the md5 from the secret and timestamp. */
case POP3_NO_STATE:
{
MD5_CTX md5context;
......@@ -50,7 +55,6 @@ pop3_apop (pop3_t pop3, const char *user, const char *secret)
if (user == NULL || secret == NULL)
return MU_ERROR_INVALID_PARAMETER;
/* Generate md5 digest. */
MD5Init (&md5context);
MD5Update (&md5context, (unsigned char *)pop3->timestamp,
strlen (pop3->timestamp));
......@@ -78,6 +82,11 @@ pop3_apop (pop3_t pop3, const char *user, const char *secret)
pop3->state = POP3_NO_STATE;
break;
/* They must deal with the error first by reopening. */
case POP3_ERROR:
status = MU_ERROR_OPERATION_CANCELED;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
......
......@@ -56,6 +56,11 @@ pop3_capa (pop3_t pop3, iterator_t *piterator)
POP3_CHECK_ERROR (pop3, status);
break;
/* They must deal with the error first by reopening. */
case POP3_ERROR:
status = MU_ERROR_OPERATION_CANCELED;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
......
......@@ -28,9 +28,10 @@
static int pop3_sleep (int seconds);
/* Open the connection to the server. */
/* Open the connection to the server. The server sends an affirmative greeting
that may contain a timestamp for APOP. */
int
pop3_open (pop3_t pop3, const char *host, unsigned int port, int flags)
pop3_connect (pop3_t pop3, const char *host, unsigned int port)
{
int status = 0;
......@@ -47,7 +48,6 @@ pop3_open (pop3_t pop3, const char *host, unsigned int port, int flags)
{
default:
/* __Fallthrough__, they want to clear an error. */
/* status = MU_ERROR_OPERATION_IN_PROGRESS; */
case POP3_NO_STATE:
/* Create the networking stack. */
if (pop3->stream == NULL)
......@@ -62,19 +62,21 @@ pop3_open (pop3_t pop3, const char *host, unsigned int port, int flags)
/* This is sudden death: for many pop servers, it is important to
let them time to remove locks or move the .user.pop files. This
happen when we do close() and immediately open(). For example,
the user does not want to read the entire file, and wants start
the user does not want to read the entire file, and wants to start
to read a new message, closing the connection and immediately
contacting the server again, and he'll end up having
"-ERR Mail Lock busy" or something similar. To prevent this race
condition we sleep 2 seconds. */
stream_close (pop3->stream);
condition we sleep 2 seconds. This really obvious for in
environment where QPopper is use, the user as a big mailbox. */
pop3_disconnect (pop3);
pop3_sleep (2);
}
pop3->state = POP3_OPEN;
pop3->state = POP3_CONNECT;
case POP3_OPEN:
case POP3_CONNECT:
/* Establish the connection. */
status = stream_open (pop3->stream, host, port, flags);
status = stream_open (pop3->stream, host, port,
MU_STREAM_READ|MU_STREAM_WRITE);
POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = POP3_GREETINGS;
......
......@@ -54,6 +54,11 @@ pop3_dele (pop3_t pop3, unsigned msgno)
pop3->state = POP3_NO_STATE;
break;
/* They must deal with the error first by reopening. */
case POP3_ERROR:
status = MU_ERROR_OPERATION_CANCELED;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
......
......@@ -25,7 +25,7 @@
/* Sudden death. */
int
pop3_close (pop3_t pop3)
pop3_disconnect (pop3_t pop3)
{
/* Sanity checks. */
if (pop3 == NULL)
......
......@@ -162,7 +162,7 @@ p_next (iterator_t iterator)
if (buf == NULL)
return MU_ERROR_NO_MEMORY;
p_iterator->item = calloc (1, sizeof (struct list_item));
p_iterator->item = calloc (1, sizeof (struct pop3_uidl_item));
if (p_iterator->item == NULL)
return MU_ERROR_NO_MEMORY;
......@@ -179,8 +179,8 @@ p_next (iterator_t iterator)
space[strlen (space) - 1] = '\0';
if (space == NULL)
space = (char *)"";
((struct uidl_item *)(p_iterator->item))->msgno = msgno;
((struct uidl_item *)(p_iterator->item))->uidl = strdup (space);
((struct pop3_uidl_item *)(p_iterator->item))->msgno = msgno;
((struct pop3_uidl_item *)(p_iterator->item))->uidl = strdup (space);
free (buf);
}
break;
......@@ -194,7 +194,7 @@ p_next (iterator_t iterator)
if (buf == NULL)
return MU_ERROR_NO_MEMORY;
p_iterator->item = calloc (1, sizeof (struct list_item));
p_iterator->item = calloc (1, sizeof (struct pop3_list_item));
if (p_iterator->item == NULL)
return MU_ERROR_NO_MEMORY;
......@@ -202,8 +202,8 @@ p_next (iterator_t iterator)
pop3_readline (p_iterator->pop3, buf, n + 1, NULL);
size = msgno = 0;
sscanf (buf, "%d %d", &msgno, &size);
((struct list_item *)(p_iterator->item))->msgno = msgno;
((struct list_item *)(p_iterator->item))->size = size;
((struct pop3_list_item *)(p_iterator->item))->msgno = msgno;
((struct pop3_list_item *)(p_iterator->item))->size = size;
free (buf);
}
break;
......@@ -235,7 +235,7 @@ p_current (iterator_t iterator, void *item)
break;
case POP3_LIST_RX:
*((struct list_item **)item) = p_iterator->item;
*((struct pop3_list_item **)item) = p_iterator->item;
break;
default:
......
......@@ -62,6 +62,11 @@ pop3_list (pop3_t pop3, unsigned msgno, size_t *psize)
sscanf (pop3->ack.buf, "+OK %d %d", &msgno, psize);
break;
/* They must deal with the error first by reopening. */
case POP3_ERROR:
status = MU_ERROR_OPERATION_CANCELED;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
......
......@@ -61,6 +61,11 @@ pop3_list_all (pop3_t pop3, iterator_t *piterator)
POP3_CHECK_ERROR (pop3, status);
break;
/* They must deal with the error first by reopening. */
case POP3_ERROR:
status = MU_ERROR_OPERATION_CANCELED;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
......
......@@ -54,6 +54,11 @@ pop3_noop (pop3_t pop3)
pop3->state = POP3_NO_STATE;
break;
/* They must deal with the error first by reopening. */
case POP3_ERROR:
status = MU_ERROR_OPERATION_CANCELED;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
......
......@@ -56,6 +56,11 @@ pop3_pass (pop3_t pop3, const char *passwd)
pop3->state = POP3_NO_STATE;
break;
/* They must deal with the error first by reopening. */
case POP3_ERROR:
status = MU_ERROR_OPERATION_CANCELED;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
......
......@@ -59,6 +59,11 @@ pop3_retr (pop3_t pop3, unsigned msgno, stream_t *pstream)
POP3_CHECK_ERROR (pop3, status);
break;
/* They must deal with the error first by reopening. */
case POP3_ERROR:
status = MU_ERROR_OPERATION_CANCELED;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
......
......@@ -54,6 +54,11 @@ pop3_rset (pop3_t pop3)
pop3->state = POP3_NO_STATE;
break;
/* They must deal with the error first by reopening. */
case POP3_ERROR:
status = MU_ERROR_OPERATION_CANCELED;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
......
......@@ -62,6 +62,11 @@ pop3_stat (pop3_t pop3, unsigned *msg_count, size_t *size)
sscanf (pop3->ack.buf, "+OK %d %d", msg_count, size);
break;
/* They must deal with the error first by reopening. */
case POP3_ERROR:
status = MU_ERROR_OPERATION_CANCELED;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
......
......@@ -163,14 +163,15 @@ static int
p_open (stream_t stream, const char *h, int p, int f)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return pop3_open (p_stream->pop3, h, p, f);
(void)f;
return pop3_connect (p_stream->pop3, h, p);
}
static int
p_close (stream_t stream)
{
struct p_stream *p_stream = (struct p_stream *)stream;
return pop3_close (p_stream->pop3);
return pop3_disconnect (p_stream->pop3);
}
static int
......
......@@ -60,6 +60,11 @@ pop3_top (pop3_t pop3, unsigned msgno, size_t lines, stream_t *pstream)
POP3_CHECK_ERROR (pop3, status);
break;
/* They must deal with the error first by reopening. */
case POP3_ERROR:
status = MU_ERROR_OPERATION_CANCELED;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
......
......@@ -89,6 +89,11 @@ pop3_uidl (pop3_t pop3, unsigned msgno, char **uidl)
}
break;
/* They must deal with the error first by reopening. */
case POP3_ERROR:
status = MU_ERROR_OPERATION_CANCELED;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
......
......@@ -61,6 +61,11 @@ pop3_uidl_all (pop3_t pop3, iterator_t *piterator)
POP3_CHECK_ERROR (pop3, status);
break;
/* They must deal with the error first by reopening. */
case POP3_ERROR:
status = MU_ERROR_OPERATION_CANCELED;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
......
......@@ -56,6 +56,11 @@ pop3_user (pop3_t pop3, const char *user)
pop3->state = POP3_NO_STATE;
break;
/* They must deal with the error first by reopening. */
case POP3_ERROR:
status = MU_ERROR_OPERATION_CANCELED;
break;
default:
status = MU_ERROR_OPERATION_IN_PROGRESS;
}
......
......@@ -31,13 +31,13 @@ typedef struct {
/* The names of functions that actually do the manipulation. */
int com_apop (char *);
int com_close (char *);
int com_disconnect (char *);
int com_dele (char *);
int com_exit (char *);
int com_help (char *);
int com_list (char *);
int com_noop (char *);
int com_open (char *);
int com_connect (char *);
int com_pass (char *);
int com_quit (char *);
int com_retr (char *);
......@@ -58,7 +58,7 @@ int valid_argument (const char *, char *);
COMMAND commands[] = {
{ "apop", com_apop, "Authenticate with APOP: APOP user secret" },
{ "close", com_close, "Close connection: close" },
{ "disconnect", com_disconnect, "Close connection: disconnect" },
{ "dele", com_dele, "Mark message: DELE msgno" },
{ "exit", com_exit, "exit program" },
{ "help", com_help, "Display this text" },
......@@ -66,7 +66,7 @@ COMMAND commands[] = {
{ "list", com_list, "List messages: LIST [msgno]" },
{ "noop", com_noop, "Send no operation: NOOP" },
{ "pass", com_pass, "Send passwd: PASS [passwd]" },
{ "open", com_open, "Open connection: open hostname [port]" },
{ "connect", com_connect, "Open connection: connect hostname [port]" },
{ "quit", com_quit, "Go to Update state : QUIT" },
{ "retr", com_retr, "Dowload message: RETR msgno" },
{ "rset", com_rset, "Unmark all messages: RSET" },
......@@ -301,7 +301,7 @@ print_response ()
fprintf (stderr, "%s\n", response);
}
else
fprintf (stderr, "Not connected, try `open' first\n");
fprintf (stderr, "Not connected, try `connect' first\n");
return 0;
}
......@@ -342,7 +342,7 @@ com_uidl (char *arg)
!iterator_is_done (uidl_iterator);
iterator_next (uidl_iterator))
{
struct uidl_item *pl;
struct pop3_uidl_item *pl;
iterator_current (uidl_iterator, (void *)&pl);
printf ("Msg: %d UIDL: %s\n", pl->msgno, pl->uidl);
free (pl);
......@@ -375,7 +375,7 @@ com_list (char *arg)
!iterator_is_done (list_iterator);
iterator_next (list_iterator))
{
struct list_item *pl;
struct pop3_list_item *pl;
iterator_current (list_iterator, (void *)&pl);
printf ("Msg: %d Size: %d\n", pl->msgno, pl->size);
free (pl);
......@@ -576,23 +576,23 @@ com_retr (char *arg)
}
int
com_open (char *arg)
com_connect (char *arg)
{
char host[256];
int port = 0;
int status;
if (!valid_argument ("open", arg))
if (!valid_argument ("connect", arg))
return 1;
*host = '\0';
sscanf (arg, "%256s %d", host, &port);
if (!valid_argument ("open", host))
if (!valid_argument ("connect", host))
return 1;
if (pop3)
com_close (NULL);
com_disconnect (NULL);
status = pop3_create (&pop3);
if (status == 0)
{
pop3_open (pop3, host, port, MU_STREAM_RDWR);
pop3_connect (pop3, host, port);
print_response ();
}
else
......@@ -601,12 +601,12 @@ com_open (char *arg)
}
int
com_close (char *arg)
com_disconnect (char *arg)
{
(void) arg;
if (pop3)
{
pop3_close (pop3);
pop3_disconnect (pop3);
pop3_destroy (pop3);
pop3 = NULL;
}
......@@ -620,6 +620,7 @@ com_quit (char *arg)
if (pop3)
{
pop3_quit (pop3);
pop3_disconnect (pop3);
print_response ();
}
return 0;
......@@ -631,7 +632,7 @@ com_exit (char *arg)
(void)arg;
if (pop3)
{
pop3_close (pop3);
pop3_disconnect (pop3);
pop3_destroy (pop3);
}
done = 1;
......