Пример #1
0
int
mu_pop3_stat (mu_pop3_t pop3, size_t *msg_count, mu_off_t *size)
{
  int status;
  unsigned long lv, count;
  
  if (pop3 == NULL || msg_count == NULL)
    return EINVAL;
  if (size == NULL)
    return MU_ERR_OUT_PTR_NULL;

  switch (pop3->state)
    {
    case MU_POP3_NO_STATE:
      status = mu_pop3_writeline (pop3, "STAT\r\n");
      MU_POP3_CHECK_ERROR (pop3, status);
      MU_POP3_FCLR (pop3, MU_POP3_ACK);
      pop3->state = MU_POP3_STAT;

    case MU_POP3_STAT:
      status = mu_pop3_response (pop3, NULL);
      MU_POP3_CHECK_EAGAIN (pop3, status);
      MU_POP3_CHECK_OK (pop3);
      pop3->state = MU_POP3_NO_STATE;

      /* Parse the answer.  */
      *msg_count = 0;
      lv = 0;
      /* FIXME: Error checking */
      sscanf (pop3->ackbuf, "+OK %lu %lu", &count, &lv);
      *msg_count = count;
      *size = lv;
      break;

      /* They must deal with the error first by reopening.  */
    case MU_POP3_ERROR:
      status = ECANCELED;
      break;

    default:
      status = EINPROGRESS;
    }

  return status;
}
Пример #2
0
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);
      /* Obscure the passwd.  */
      memset (pop3->io.buf, '\0', pop3->io.len);
      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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
/* 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 == NULL)
    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 = mu_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 (mu_c_strncasecmp (pop3->ack.buf, "+OK", 3) != 0)
	  {
	    mu_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)
		  {
		    mu_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;
}