Commit e6c6ca30 e6c6ca30a4e40a07eb3b21803dea175580edc7c9 by Alain Magloire

First draft of the implementation of the public low level call to POP3

1 parent 579b593e
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2003 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "../md5.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <mailutils/sys/pop3.h>
/*
* APOP name digest
* a string identifying a mailbox and a MD5 digest string (both required)
*/
int
mu_pop3_apop (mu_pop3_t pop3, const char *user, const char *secret)
{
int status;
/* Sanity checks. */
if (pop3 == NULL || user == NULL || secret == NULL)
{
return EINVAL;
}
/* The server did not offer a timestamp in the greeting, bailout early. */
if (pop3->timestamp == NULL)
{
return ENOTSUP;
}
switch (pop3->state)
{
/* Generate the md5 from the secret and timestamp. */
case MU_POP3_NO_STATE:
{
MD5_CTX md5context;
unsigned char md5digest[16];
char digest[64]; /* Really it just has to be 32 + 1(null). */
char *tmp;
size_t n;
MD5Init (&md5context);
MD5Update (&md5context, (unsigned char *)pop3->timestamp, strlen (pop3->timestamp));
MD5Update (&md5context, (unsigned char *)secret, strlen (secret));
MD5Final (md5digest, &md5context);
for (tmp = digest, n = 0; n < 16; n++, tmp += 2)
{
sprintf (tmp, "%02x", md5digest[n]);
}
*tmp = '\0';
status = mu_pop3_writeline (pop3, "APOP %s %s\r\n", user, digest);
MU_POP3_CHECK_ERROR (pop3, status);
mu_pop3_debug_cmd (pop3);
pop3->state = MU_POP3_APOP;
}
case MU_POP3_APOP:
status = mu_pop3_send (pop3);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = MU_POP3_APOP_ACK;
case MU_POP3_APOP_ACK:
status = mu_pop3_response (pop3, NULL, 0, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
mu_pop3_debug_ack (pop3);
MU_POP3_CHECK_OK (pop3);
pop3->state = MU_POP3_NO_STATE;
break;
/* They must deal with the error first by reopening. */
case MU_POP3_ERROR:
status = ECANCELED;
break;
/* No case in the switch another operation was in progress. */
default:
status = EINPROGRESS;
}
return status;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <errno.h>
#include <mailutils/error.h>
#include <mailutils/sys/pop3.h>
/*
CAPA command, return a list that contains the result.
It is the responsability of the caller to destroy the list(list_destroy).
*/
int
mu_pop3_capa (mu_pop3_t pop3, list_t *plist)
{
int status;
if (pop3 == NULL || plist == NULL)
return EINVAL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "CAPA\r\n");
MU_POP3_CHECK_ERROR (pop3, status);
mu_pop3_debug_cmd (pop3);
pop3->state = MU_POP3_CAPA;
case MU_POP3_CAPA:
status = mu_pop3_send (pop3);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = MU_POP3_CAPA_ACK;
case MU_POP3_CAPA_ACK:
status = mu_pop3_response (pop3, NULL, 0, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
mu_pop3_debug_ack (pop3);
MU_POP3_CHECK_OK (pop3);
status = list_create (plist);
MU_POP3_CHECK_ERROR(pop3, status);
list_set_destroy_item(*plist, free);
pop3->state = MU_POP3_CAPA_RX;
case MU_POP3_CAPA_RX:
{
/* CAPA line are 512 octets maximum according to RFC 2449.
But do not use the stack and malloc. */
char *capability;
size_t n = 0;
capability = malloc (512);
if (capability == NULL)
{
MU_POP3_CHECK_ERROR(pop3, ENOMEM);
}
while ((status = mu_pop3_readline (pop3, capability, 512, &n)) > 0 && n > 0)
{
/* Nuke the trailing newline */
if (capability[n - 1] == '\n')
capability[n - 1] = '\0';
/* add to the list. */
list_append (*plist, strdup (capability));
n = 0;
}
free (capability);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->state = MU_POP3_NO_STATE;
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 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_set_carrier (mu_pop3_t pop3, stream_t carrier)
{
/* Sanity checks. */
if (pop3 == NULL)
return EINVAL;
if (pop3->carrier)
{
/* Close any old carrier. */
mu_pop3_disconnect (pop3);
stream_destroy (&pop3->carrier, pop3);
}
pop3->carrier = carrier;
return 0;
}
int
mu_pop3_get_carrier (mu_pop3_t pop3, stream_t *pcarrier)
{
/* Sanity checks. */
if (pop3 == NULL || pcarrier == NULL)
return EINVAL;
*pcarrier = pop3->carrier;
return 0;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <mailutils/sys/pop3.h>
static int mu_pop3_sleep (int seconds);
/* Open the connection to the server. The server sends an affirmative greeting
that may contain a timestamp for APOP. */
int
mu_pop3_connect (mu_pop3_t pop3)
{
int status;
/* Sanity checks. */
if (pop3 == NULL)
return EINVAL;
/* A networking stack. */
if (pop3->carrier)
return EINVAL;
/* Enter the pop state machine, and boogy: AUTHORISATION State. */
switch (pop3->state)
{
default:
/* FALLTHROUGH */
/* If pop3 was in an error state going through here should clear it. */
case MU_POP3_NO_STATE:
/* If the stream was previoulsy open this is sudden death:
for many pop servers, it is important to let them time to remove any 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 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. You can see this behaviour in an
environment where QPopper(Qualcomm POP3 server) is use and the user as a big mailbox. */
status = mu_pop3_disconnect (pop3);
if (status != 0)
mu_pop3_sleep (2);
pop3->state = MU_POP3_CONNECT;
case MU_POP3_CONNECT:
/* Establish the connection. */
status = stream_open (pop3->carrier);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = MU_POP3_GREETINGS;
case MU_POP3_GREETINGS:
/* Get the greetings. */
{
size_t len = 0;
char *right, *left;
status = mu_pop3_response (pop3, NULL, 0, &len);
MU_POP3_CHECK_EAGAIN (pop3, status);
mu_pop3_debug_ack (pop3);
if (strncasecmp (pop3->ack.buf, "+OK", 3) != 0)
{
stream_close (pop3->carrier);
pop3->state = MU_POP3_NO_STATE;
return EACCES;
}
/* Get the timestamp. */
right = memchr (pop3->ack.buf, '<', len);
if (right)
{
len = len - (right - pop3->ack.buf);
left = memchr (right, '>', len);
if (left)
{
len = left - right + 1;
pop3->timestamp = calloc (len + 1, 1);
if (pop3->timestamp == NULL)
{
stream_close (pop3->carrier);
MU_POP3_CHECK_ERROR (pop3, ENOMEM);
}
memcpy (pop3->timestamp, right, len);
}
}
pop3->state = MU_POP3_NO_STATE;
}
} /* End AUTHORISATION state. */
return status;
}
/* GRRRRR!! We can not use sleep in the library since this we'll
muck up any alarm() done by the user. */
static int
mu_pop3_sleep (int seconds)
{
struct timeval tval;
tval.tv_sec = seconds;
tval.tv_usec = 0;
return select (1, NULL, NULL, NULL, &tval);
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <errno.h>
#include <mailutils/errno.h>
#include <mailutils/sys/pop3.h>
/* Initialise a mu_pop3_t handle. */
int
mu_pop3_create (mu_pop3_t *ppop3)
{
mu_pop3_t pop3;
/* Sanity check. */
if (ppop3 == NULL)
return EINVAL;
pop3 = calloc (1, sizeof *pop3);
if (pop3 == NULL)
return ENOMEM;
/* Reserve space for the ack(nowledgement) response.
According to RFC 2449: The maximum length of the first line of a
command response (including the initial greeting) is unchanged at
512 octets (including the terminating CRLF). */
pop3->ack.len = 512;
pop3->ack.buf = calloc (pop3->ack.len, 1);
if (pop3->ack.buf == NULL)
{
mu_pop3_destroy (&pop3);
return ENOMEM;
}
pop3->ack.ptr = pop3->ack.buf;
/* Reserve space for the data response/content.
RFC 2449 recommands 255, but we grow it as needed. */
pop3->io.len = 255;
pop3->io.buf = calloc (pop3->io.len, 1);
if (pop3->io.buf == NULL)
{
mu_pop3_destroy (&pop3);
return ENOMEM;
}
pop3->io.ptr = pop3->io.buf;
pop3->state = MU_POP3_NO_STATE; /* Init with no state. */
pop3->timeout = (10 * 60) * 100; /* The default Timeout is 10 minutes. */
pop3->acknowledge = 0; /* No Ack received. */
*ppop3 = pop3;
return 0; /* Okdoke. */
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <errno.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_set_debug (mu_pop3_t pop3, void (*print)(const char *buffer))
{
if (pop3 == NULL)
return EINVAL;
pop3->debug = print;
return 0;
}
int
mu_pop3_debug_cmd (mu_pop3_t pop3)
{
if (pop3->debug)
pop3->debug (pop3->io.buf);
return 0;
}
int
mu_pop3_debug_ack (mu_pop3_t pop3)
{
if (pop3->debug)
{
pop3->debug (pop3->ack.buf);
pop3->debug ("\n");
}
return 0;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_dele (mu_pop3_t pop3, unsigned msgno)
{
int status;
if (pop3 == NULL || msgno == 0)
return MU_ERR_INVALID_PARAMETER;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "DELE %d\r\n", msgno);
MU_POP3_CHECK_ERROR (pop3, status);
mu_pop3_debug_cmd (pop3);
pop3->state = MU_POP3_DELE;
case MU_POP3_DELE:
status = mu_pop3_send (pop3);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = MU_POP3_DELE_ACK;
case MU_POP3_DELE_ACK:
status = mu_pop3_response (pop3, NULL, 0, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
mu_pop3_debug_ack (pop3);
MU_POP3_CHECK_OK (pop3);
pop3->state = MU_POP3_NO_STATE;
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 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <mailutils/errno.h>
#include <mailutils/sys/pop3.h>
void
mu_pop3_destroy (mu_pop3_t *ppop3)
{
if (ppop3 && *ppop3)
{
mu_pop3_t pop3 = *ppop3;
/* Free the response buffer. */
if (pop3->ack.buf)
free (pop3->ack.buf);
/* Free the io buffer. */
if (pop3->io.buf)
free (pop3->io.buf);
/* Free the timestamp use for APOP. */
if (pop3->timestamp)
free (pop3->timestamp);
/* Release the carrier. */
if (pop3->carrier)
stream_destroy (&pop3->carrier, pop3);
free (pop3);
*ppop3 = NULL;
}
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2003 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_disconnect (mu_pop3_t pop3)
{
/* Sanity checks. */
if (pop3 == NULL)
return EINVAL;
/* We can keep some of the fields, if they decide to pop3_connect() again but
clear the states. */
pop3->state = MU_POP3_NO_STATE;
pop3->acknowledge = 0;
/* Clear the buffers. */
memset (pop3->io.buf, '\0', pop3->io.len);
pop3->io.ptr = pop3->io.buf;
memset (pop3->ack.buf, '\0', pop3->ack.len);
pop3->ack.ptr = pop3->ack.buf;
/* Free the timestamp, it will be different on each connection. */
if (pop3->timestamp)
{
free (pop3->timestamp);
pop3->timestamp = NULL;
}
/* Close the stream. */
return stream_close (pop3->carrier);
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_list (mu_pop3_t pop3, unsigned int msgno, size_t *psize)
{
int status;
if (pop3 == NULL || msgno == 0 || psize == NULL)
return EINVAL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "LIST %d\r\n", msgno);
MU_POP3_CHECK_ERROR (pop3, status);
mu_pop3_debug_cmd (pop3);
pop3->state = MU_POP3_LIST;
case MU_POP3_LIST:
status = mu_pop3_send (pop3);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = MU_POP3_LIST_ACK;
case MU_POP3_LIST_ACK:
status = mu_pop3_response (pop3, NULL, 0, NULL);
mu_pop3_debug_ack (pop3);
MU_POP3_CHECK_EAGAIN (pop3, status);
MU_POP3_CHECK_OK (pop3);
pop3->state = MU_POP3_NO_STATE;
/* Parse the answer. */
*psize = 0;
sscanf (pop3->ack.buf, "+OK %d %d", &msgno, psize);
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 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# 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, list_t *plist)
{
int status;
if (pop3 == NULL || plist == 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_debug_cmd (pop3);
pop3->state = MU_POP3_LIST;
case MU_POP3_LIST:
status = mu_pop3_send (pop3);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = MU_POP3_LIST_ACK;
case MU_POP3_LIST_ACK:
status = mu_pop3_response (pop3, NULL, 0, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
mu_pop3_debug_cmd (pop3);
MU_POP3_CHECK_OK (pop3);
status = list_create (plist);
MU_POP3_CHECK_ERROR(pop3, status);
list_set_destroy_item(*plist, free);
pop3->state = MU_POP3_LIST_RX;
case MU_POP3_LIST_RX:
{
/* LIST line should not be over 512 octets maximum according to RFC 2449.
But do not use the stack and malloc. */
char *lista;
size_t n = 0;
lista = malloc (512);
if (lista == NULL)
{
MU_POP3_CHECK_ERROR(pop3, ENOMEM);
}
while ((status = mu_pop3_readline (pop3, lista, 512, &n)) > 0 && n > 0)
{
/* Nuke the trailing newline */
if (lista[n - 1] == '\n')
lista[n - 1] = '\0';
/* add to the list. */
list_append (*plist, strdup (lista));
n = 0;
}
free (lista);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->state = MU_POP3_NO_STATE;
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 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_noop (mu_pop3_t pop3)
{
int status;
if (pop3 == NULL)
return EINVAL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "NOOP\r\n");
MU_POP3_CHECK_ERROR (pop3, status);
mu_pop3_debug_cmd (pop3);
pop3->state = MU_POP3_NOOP;
case MU_POP3_NOOP:
status = mu_pop3_send (pop3);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = MU_POP3_NOOP_ACK;
case MU_POP3_NOOP_ACK:
status = mu_pop3_response (pop3, NULL, 0, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
mu_pop3_debug_ack (pop3);
MU_POP3_CHECK_OK (pop3);
pop3->state = MU_POP3_NO_STATE;
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 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_pass (mu_pop3_t pop3, const char *passwd)
{
int status;
if (pop3 == NULL || passwd == NULL)
return EINVAL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "PASS %s\r\n", passwd);
MU_POP3_CHECK_ERROR (pop3, status);
mu_pop3_debug_cmd (pop3);
pop3->state = MU_POP3_PASS;
case MU_POP3_PASS:
status = mu_pop3_send (pop3);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = MU_POP3_PASS_ACK;
case MU_POP3_PASS_ACK:
status = mu_pop3_response (pop3, NULL, 0, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
mu_pop3_debug_ack (pop3);
MU_POP3_CHECK_OK (pop3);
pop3->state = MU_POP3_NO_STATE;
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 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_quit (mu_pop3_t pop3)
{
int status;
if (pop3 == NULL)
return EINVAL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "QUIT\r\n");
MU_POP3_CHECK_ERROR (pop3, status);
mu_pop3_debug_cmd (pop3);
pop3->state = MU_POP3_QUIT;
case MU_POP3_QUIT:
status = mu_pop3_send (pop3);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = MU_POP3_QUIT_ACK;
case MU_POP3_QUIT_ACK:
status = mu_pop3_response (pop3, NULL, 0, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
mu_pop3_debug_ack (pop3);
MU_POP3_CHECK_OK (pop3);
pop3->state = MU_POP3_NO_STATE;
break;
default:
status = EINPROGRESS;
}
return status;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <mailutils/sys/pop3.h>
#include <mailutils/error.h>
static int
mu_pop3_carrier_is_read_ready(stream_t carrier, int timeout)
{
int fd = -1;
int ready = 0;
stream_get_fd (carrier, &fd);
if (fd >= 0)
{
struct timeval tv;
fd_set fset;
FD_ZERO (&fset);
FD_SET (fds->fd, &fset);
tv.tv_sec = timeout / 100;
tv.tv_usec = (timeout % 1000) * 1000;
ready = select (fds->fd + 1, &fset, NULL, NULL, (timeout == -1) ? NULL: &tv);
ready = (ready == -1) ? 0 : 1;
}
return ready;
}
/* Read a complete line from the pop server. Transform CRLF to LF, remove
the stuff byte termination octet ".", put a null in the buffer
when done. And Do a select() (stream_is_readready()) for the timeout. */
static int
mu_pop3_getline (pop3_t pop3)
{
size_t n = 0;
size_t total = pop3->io.ptr - pop3->io.buf;
int status = 0;
/* Must get a full line before bailing out. */
do
{
/* Timeout with select(), note that we have to reset select()
since on linux tv is modified when error. */
if (pop3->timeout)
{
int ready = mu_pop3_carrier_is_read_ready (pop3->carrier, pop3->timeout);
if (ready == 0)
return ETIMEDOUT;
}
status = stream_readline (pop3->carrier, pop3->io.buf + total, pop3->io.len - total, pop3->io.offset, &n);
if (status != 0)
return status;
pop3->io.offset += n;
/* The server went away: It maybe a timeout and some pop server
does not send the -ERR. Consider this like an error. */
if (n == 0)
return EIO;
total += n;
pop3->io.nl = memchr (pop3->io.buf, '\n', total);
if (pop3->io.nl == NULL) /* Do we have a full line. */
{
/* Allocate a bigger buffer ? */
if (total >= pop3->io.len - 1)
{
pop3->io.len *= 2;
pop3->io.buf = realloc (pop3->io.buf, pop3->io.len + 1);
if (pop3->io.buf == NULL)
return ENOMEM;
}
}
pop3->io.ptr = pop3->io.buf + total;
}
while (pop3->io.nl == NULL); /* Bail only if we have a complete line. */
/* When examining a multi-line response, the client checks to see if the
line begins with the termination octet "."(DOT). If yes and if octets
other than CRLF follow, the first octet of the line (the termination
octet) is stripped away. */
if (total >= 3 && pop3->io.buf[0] == '.')
{
if (pop3->io.buf[1] != '\r' && pop3->io.buf[2] != '\n')
{
memmove (pop3->io.buf, pop3->io.buf + 1, total - 1);
pop3->io.ptr--;
pop3->io.nl--;
}
/* And if CRLF immediately follows the termination character, then
the response from the POP server is ended and the line containing
".CRLF" is not considered part of the multi-line response. */
else if (pop3->io.buf[1] == '\r' && pop3->io.buf[2] == '\n')
{
pop3->io.buf[0] = '\0';
pop3->io.ptr = pop3->io.buf;
pop3->io.nl = NULL;
}
}
/* \r\n --> \n\0, conversion. */
if (pop3->io.nl > pop3->io.buf)
{
*(pop3->io.nl - 1) = '\n';
*(pop3->io.nl) = '\0';
pop3->io.ptr = pop3->io.nl;
}
return status;
}
/* Call pop3_getline() for the dirty work, and consume i.e. put
in the user buffer only buflen. If buflen == 0 or buffer == NULL
nothing is consume, the data is save for another call to pop3_readline()
with a buffer != NULL.
*/
int
mu_pop3_readline (pop3_t pop3, char *buffer, size_t buflen, size_t *pnread)
{
size_t nread = 0;
size_t n = 0;
int status = 0;
/* Do we need to fill up? Yes if no NL or the buffer is empty. */
if (pop3->carrier && (pop3->io.nl == NULL || pop3->io.ptr == pop3->io.buf))
{
status = pop3_getline (pop3);
if (status != 0)
return status;
}
/* How much we can copy ? */
n = pop3->io.ptr - pop3->io.buf;
/* Consume the line? */
if (buffer && buflen)
{
buflen--; /* For the null. */
if (buflen)
{
int nleft = buflen - n;
/* We got more then requested. */
if (nleft < 0)
{
size_t sentinel;
nread = buflen;
sentinel = pop3->io.ptr - (pop3->io.buf + nread);
memcpy (buffer, pop3->io.buf, nread);
memmove (pop3->io.buf, pop3->io.buf + nread, sentinel);
pop3->io.ptr = pop3->io.buf + sentinel;
}
else
{
/* Drain our buffer. */;
nread = n;
memcpy (buffer, pop3->io.buf, nread);
pop3->io.ptr = pop3->io.buf;
/* Clear of all residue. */
memset (pop3->io.buf, '\0', pop3->io.len);
}
}
buffer[nread] = '\0';
}
else
nread = n;
if (pnread)
*pnread = nread;
return status;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <mailutils/sys/pop3.h>
/* If we did not grap the ack already, call pop3_readline() but handle
Nonblocking also. */
int
mu_pop3_response (mu_pop3_t pop3, char *buffer, size_t buflen, size_t *pnread)
{
size_t n = 0;
int status = 0;
if (pop3 == NULL)
return EINVAL;
if (!pop3->acknowledge)
{
size_t len = pop3->ack.len - (pop3->ack.ptr - pop3->ack.buf);
status = mu_pop3_readline (pop3, pop3->ack.ptr, len, &n);
pop3->ack.ptr += n;
if (status == 0)
{
len = pop3->ack.ptr - pop3->ack.buf;
if (len && pop3->ack.buf[len - 1] == '\n')
pop3->ack.buf[len - 1] = '\0';
pop3->acknowledge = 1; /* Flag that we have the ack. */
pop3->ack.ptr = pop3->ack.buf;
}
else
{
/* Provide them with an error. */
const char *econ = "-ERR POP3 IO ERROR";
n = strlen (econ);
strcpy (pop3->ack.buf, econ);
}
}
else
n = strlen (pop3->ack.buf);
if (buffer)
{
buflen--; /* Leave space for the NULL. */
n = (buflen < n) ? buflen : n;
memcpy (buffer, pop3->ack.buf, n);
buffer[n] = '\0';
}
if (pnread)
*pnread = n;
return status;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_retr (mu_pop3_t pop3, unsigned int msgno, stream_t *pstream)
{
int status;
if (pop3 == NULL || msgno == 0 || pstream == NULL)
return EINVAL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "RETR %d\r\n", msgno);
MU_POP3_CHECK_ERROR (pop3, status);
mu_pop3_debug_cmd (pop3);
pop3->state = MU_POP3_RETR;
case MU_POP3_RETR:
status = mu_pop3_send (pop3);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = MU_POP3_RETR_ACK;
case MU_POP3_RETR_ACK:
status = mu_pop3_response (pop3, NULL, 0, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
mu_pop3_debug_ack (pop3);
MU_POP3_CHECK_OK (pop3);
pop3->state = MU_POP3_RETR_RX;
case MU_POP3_RETR_RX:
status = mu_pop3_stream_create (pop3, pstream);
MU_POP3_CHECK_ERROR (pop3, status);
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 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_rset (mu_pop3_t pop3)
{
int status;
if (pop3 == NULL)
return EINVAL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "RSET\r\n");
MU_POP3_CHECK_ERROR (pop3, status);
mu_pop3_debug_cmd (pop3);
pop3->state = MU_POP3_RSET;
case MU_POP3_RSET:
status = mu_pop3_send (pop3);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = MU_POP3_RSET_ACK;
case MU_POP3_RSET_ACK:
status = mu_pop3_response (pop3, NULL, 0, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
mu_pop3_debug_ack (pop3);
MU_POP3_CHECK_OK (pop3);
pop3->state = MU_POP3_NO_STATE;
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 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <mailutils/sys/pop3.h>
static int mu_pop3_carrier_is_write_ready (stream_t carrier, int timeout);
/* A socket may write less then expected but stream.c:stream_write() will
always try to send the entire buffer unless an error is reported. We have
to cope with nonblocking, it is done by keeping track with the pop3->ptr
pointer if the write failed we keep track and restart where we left. */
int
mu_pop3_send (mu_pop3_t pop3)
{
int status = 0;
if (pop3->carrier && (pop3->io.ptr > pop3->io.buf))
{
size_t n = 0;
size_t len = pop3->io.ptr - pop3->io.buf;
/* Timeout with select(), note that we have to reset select()
since on linux tv is modified when error. */
if (pop3->timeout)
{
int ready = mu_pop3_carrier_is_write_ready (pop3->carrier, pop3->timeout);
if (ready == 0)
return ETIMEDOUT;
}
status = stream_write (pop3->carrier, pop3->io.buf, len, 0, &n);
if (n)
{
/* Consume what we sent. */
memmove (pop3->io.buf, pop3->io.buf + n, len - n);
pop3->io.ptr -= n;
}
}
else
pop3->io.ptr = pop3->io.buf;
return status;
}
/* According to RFC 2449: The maximum length of a command is increased from
47 characters (4 character command, single space, 40 character argument,
CRLF) to 255 octets, including the terminating CRLF. But we are flexible
on this and realloc() as needed. NOTE: The terminated CRLF is not
included. */
int
mu_pop3_writeline (mu_pop3_t pop3, const char *format, ...)
{
int len;
va_list ap;
int done = 1;
va_start(ap, format);
/* C99 says that a conforming implementation of snprintf () should
return the number of char that would have been call but many old
GNU/Linux && BSD implementations return -1 on error. Worse,
QnX/Neutrino actually does not put the terminal null char. So
let's try to cope. */
do
{
len = vsnprintf (pop3->io.buf, pop3->io.len - 1, format, ap);
if (len < 0 || len >= (int)pop3->io.len
|| !memchr (pop3->io.buf, '\0', len + 1))
{
pop3->io.len *= 2;
pop3->io.buf = realloc (pop3->io.buf, pop3->io.len);
if (pop3->io.buf == NULL)
return ENOMEM;
done = 0;
}
else
done = 1;
}
while (!done);
va_end(ap);
pop3->io.ptr = pop3->io.buf + len;
return 0;
}
int
mu_pop3_sendline (mu_pop3_t pop3, const char *line)
{
if (line)
{
int status = mu_pop3_writeline (pop3, line);
if (status)
return status;
}
return mu_pop3_send (pop3);
}
static int
mu_pop3_carrier_is_write_ready (stream_t carrier, int timeout)
{
int fd = -1;
int ready = 0;
stream_get_fd (carrier, &fd);
if (fd >= 0)
{
struct timeval tv;
fd_set fset;
FD_ZERO (&fset);
FD_SET (fd, &fset);
tv.tv_sec = timeout / 100;
tv.tv_usec = (timeout % 1000) * 1000;
ready = select (fd + 1, NULL, &fset, NULL, (timeout == -1) ? NULL: &tv);
ready = (ready == -1) ? 0 : 1;
}
return ready;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_stat (mu_pop3_t pop3, unsigned *msg_count, size_t *size)
{
int status;
if (pop3 == NULL || msg_count == NULL || size == NULL)
return EINVAL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "STAT\r\n");
MU_POP3_CHECK_ERROR (pop3, status);
mu_pop3_debug_cmd (pop3);
pop3->state = MU_POP3_STAT;
case MU_POP3_STAT:
status = mu_pop3_send (pop3);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = MU_POP3_STAT_ACK;
case MU_POP3_STAT_ACK:
status = mu_pop3_response (pop3, NULL, 0, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
mu_pop3_debug_ack (pop3);
MU_POP3_CHECK_OK (pop3);
pop3->state = MU_POP3_NO_STATE;
/* Parse the answer. */
*msg_count = 0;
*size = 0;
sscanf (pop3->ack.buf, "+OK %d %d", msg_count, size);
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 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
/* Implementation of the stream for TOP and RETR. */
struct mu_pop3_stream
{
mu_pop3_t pop3;
int done;
};
static void
mu_pop3_stream_destroy (stream_t stream)
{
struct mu_pop3_stream *pop3_stream = stream_get_owner (stream);
if (pop3_stream)
{
free (pop3_stream);
}
}
static int
mu_pop3_stream_read (stream_t stream, char *buf, size_t buflen, off_t offset, size_t *pn)
{
struct mu_pop3_stream *pop3_stream = stream_get_owner (stream);
size_t n = 0;
int status = 0;
char *p = buf;
(void)offset;
if (pop3_stream)
{
if (!pop3_stream->done)
{
do
{
size_t nread = 0;
/* The pop3_readline () function will always read one less to
be able to null terminate the buffer, this will cause
serious grief for stream_read() where it is legitimate to
have a buffer of 1 char. So we must catch it here. */
if (buflen == 1)
{
char buffer[2];
*buffer = '\0';
status = mu_pop3_readline (pop3_stream->pop3, buffer, 2, &nread);
*p = *buffer;
}
else
status = mu_pop3_readline (pop3_stream->pop3, p, buflen, &nread);
if (status != 0)
break;
if (nread == 0)
{
pop3_stream->pop3->state = MU_POP3_NO_STATE;
pop3_stream->done = 1;
break;
}
n += nread;
buflen -= nread;
p += nread;
}
while (buflen > 0);
}
}
if (pn)
*pn = n;
return status;
}
static int
mu_pop3_stream_readline (stream_t stream, char *buf, size_t buflen, off_t offset, size_t *pn)
{
struct mu_pop3_stream *pop3_stream = stream_get_owner (stream);
size_t n = 0;
int status = 0;
(void)offset;
if (pop3_stream)
{
if (!pop3_stream->done)
{
status = mu_pop3_readline (pop3_stream->pop3, buf, buflen, &n);
if (n == 0)
{
pop3_stream->pop3->state = MU_POP3_NO_STATE;
pop3_stream->done = 1;
}
}
}
if (pn)
*pn = n;
return status;
}
int
mu_pop3_stream_create (mu_pop3_t pop3, stream_t *pstream)
{
struct mu_pop3_stream *pop3_stream;
int status;
pop3_stream = malloc (sizeof *pop3_stream);
if (pop3_stream == NULL)
return ENOMEM;
pop3_stream->pop3 = pop3;
pop3_stream->done = 0;
status = stream_create (pstream, MU_STREAM_READ | MU_STREAM_NO_CLOSE | MU_STREAM_NO_CHECK, pop3_stream);
if (status != 0)
{
free (pop3_stream);
return status;
}
stream_set_read (*pstream, mu_pop3_stream_read, pop3_stream);
stream_set_readline (*pstream, mu_pop3_stream_readline, pop3_stream);
stream_set_destroy (*pstream, mu_pop3_stream_destroy, pop3_stream);
return 0;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2003 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <errno.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_set_timeout (mu_pop3_t pop3, int timeout)
{
/* Sanity checks. */
if (pop3 == NULL)
return EINVAL;
pop3->timeout = timeout;
return 0;
}
int
mu_pop3_get_timeout (mu_pop3_t pop3, int *ptimeout)
{
/* Sanity checks. */
if (pop3 == NULL || ptimeout == NULL)
return EINVAL;
*ptimeout = pop3->timeout;
return 0;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_top (mu_pop3_t pop3, unsigned msgno, unsigned int lines, stream_t *pstream)
{
int status;
if (pop3 == NULL || msgno == 0 || pstream == NULL)
return EINVAL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "TOP %d %d\r\n", msgno, lines);
MU_POP3_CHECK_ERROR (pop3, status);
mu_pop3_debug_cmd (pop3);
pop3->state = MU_POP3_TOP;
case MU_POP3_TOP:
status = mu_pop3_send (pop3);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = MU_POP3_TOP_ACK;
case MU_POP3_TOP_ACK:
status = mu_pop3_response (pop3, NULL, 0, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
mu_pop3_debug_ack (pop3);
MU_POP3_CHECK_OK (pop3);
pop3->state = MU_POP3_TOP_RX;
case MU_POP3_TOP_RX:
status = mu_pop3_stream_create (pop3, pstream);
MU_POP3_CHECK_ERROR (pop3, status);
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 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_uidl (mu_pop3_t pop3, unsigned int msgno, char **uidl)
{
int status;
if (pop3 == NULL || uidl == NULL)
return EINVAL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "UIDL %d\r\n", msgno);
MU_POP3_CHECK_ERROR (pop3, status);
mu_pop3_debug_cmd (pop3);
pop3->state = MU_POP3_UIDL;
case MU_POP3_UIDL:
status = mu_pop3_send (pop3);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = MU_POP3_UIDL_ACK;
case MU_POP3_UIDL_ACK:
status = mu_pop3_response (pop3, NULL, 0, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
mu_pop3_debug_ack (pop3);
MU_POP3_CHECK_OK (pop3);
pop3->state = MU_POP3_NO_STATE;
*uidl = NULL;
{
char *space;
/* Format: +OK msgno uidlstring */
/* Pass the "+OK". */
space = strchr (pop3->ack.buf, ' ');
if (space)
{
/* Skip spaces. */
while (*space == ' ') space++;
/* Pass the number. */
space = strchr (space, ' ');
if (space)
{
size_t len;
/* Skip spaces between msgno and uidlstring */
while (*space == ' ') space++;
len = strlen (space);
if (space[len - 1] == '\n')
{
space[len - 1] = '\0';
len--;
}
*uidl = calloc (len + 1, 1);
if (*uidl)
memcpy (*uidl, space, len);
}
}
}
if (*uidl == NULL) /* What can we do? */
{
*uidl = malloc (1);
if (*uidl)
**uidl = '\0';
else
status = ENOMEM;
}
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 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# 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, list_t *plist)
{
int status;
if (pop3 == NULL || plist == 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_debug_cmd (pop3);
pop3->state = MU_POP3_UIDL;
case MU_POP3_UIDL:
status = mu_pop3_send (pop3);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = MU_POP3_UIDL_ACK;
case MU_POP3_UIDL_ACK:
status = mu_pop3_response (pop3, NULL, 0, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
mu_pop3_debug_ack (pop3);
MU_POP3_CHECK_OK (pop3);
pop3->state = MU_POP3_UIDL_RX;
case MU_POP3_UIDL_RX:
{
/* UIDL line are 512 octets maximum according to RFC 1939.
But do not use the stack and malloc. */
char *uidla;
size_t n = 0;
uidla = malloc (512);
if (uidla == NULL)
{
MU_POP3_CHECK_ERROR(pop3, ENOMEM);
}
while ((status = mu_pop3_readline (pop3, uidla, 512, &n)) > 0 && n > 0)
{
/* Nuke the trailing newline */
if (uidla[n - 1] == '\n')
uidla[n - 1] = '\0';
/* add to the list. */
list_append (*plist, strdup (uidla));
n = 0;
}
free (uidla);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->state = MU_POP3_NO_STATE;
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 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 2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <errno.h>
#include <mailutils/sys/pop3.h>
int
mu_pop3_user (mu_pop3_t pop3, const char *user)
{
int status;
if (pop3 == NULL || user == NULL)
return EINVAL;
switch (pop3->state)
{
case MU_POP3_NO_STATE:
status = mu_pop3_writeline (pop3, "USER %s\r\n", user);
MU_POP3_CHECK_ERROR (pop3, status);
mu_pop3_debug_cmd (pop3);
pop3->state = MU_POP3_USER;
case MU_POP3_USER:
status = mu_pop3_send (pop3);
MU_POP3_CHECK_EAGAIN (pop3, status);
pop3->acknowledge = 0;
pop3->state = MU_POP3_USER_ACK;
case MU_POP3_USER_ACK:
status = mu_pop3_response (pop3, NULL, 0, NULL);
MU_POP3_CHECK_EAGAIN (pop3, status);
mu_pop3_debug_ack (pop3);
MU_POP3_CHECK_OK (pop3);
pop3->state = MU_POP3_NO_STATE;
break;
/* They must deal with the error first by reopening. */
case MU_POP3_ERROR:
status = ECANCELED;
break;
default:
status = EINPROGRESS;
}
return status;
}