Ejemplo n.º 1
0
/* logout from POP server */
void pop_logout (CONTEXT *ctx)
{
  int ret = 0;
  char buf[LONG_STRING];
  POP_DATA *pop_data = (POP_DATA *)ctx->data;

  if (pop_data->status == POP_CONNECTED)
  {
    mutt_message _("Closing connection to POP server...");

    if (ctx->readonly)
    {
      strfcpy (buf, "RSET\r\n", sizeof (buf));
      ret = pop_query (pop_data, buf, sizeof (buf));
    }

    if (ret != -1)
    {
      strfcpy (buf, "QUIT\r\n", sizeof (buf));
      pop_query (pop_data, buf, sizeof (buf));
    }

    mutt_clear_error ();
  }

  pop_data->status = POP_DISCONNECTED;
  return;
}
Ejemplo n.º 2
0
/* update POP mailbox - delete messages from server */
int pop_sync_mailbox(CONTEXT *ctx, int *index_hint)
{
    int i, j, ret = 0;
    char buf[LONG_STRING];
    POP_DATA *pop_data = (POP_DATA *)ctx->data;
    progress_t progress;

    pop_data->check_time = 0;

    FOREVER
    {
        if (pop_reconnect(ctx) < 0)
            return -1;

        mutt_progress_init(&progress, _("Marking messages deleted..."),
                           M_PROGRESS_MSG, WriteInc, ctx->deleted);

        for (i = 0, j = 0, ret = 0; ret == 0
             && i < ctx->msgcount; i++) {
            if (ctx->hdrs[i]->deleted
                && (ctx->hdrs[i]->refno != -1)) {
                j++;

                if (!ctx->quiet)
                    mutt_progress_update(&progress, j, -1);
                snprintf(buf, sizeof(buf), "DELE %d\r\n", ctx->hdrs[i]->refno);

                if ((ret = pop_query(pop_data, buf, sizeof(buf))) == 0) {
                    mutt_bcache_del(pop_data->bcache, ctx->hdrs[i]->data);
                }
            }

        }

        if (ret == 0) {
            strfcpy(buf, "QUIT\r\n", sizeof(buf));
            ret = pop_query(pop_data, buf, sizeof(buf));
        }

        if (ret == 0) {
            pop_data->clear_cache = 1;
            pop_clear_cache(pop_data);
            pop_data->status = POP_DISCONNECTED;
            return 0;
        }

        if (ret == -2) {
            mutt_error("%s", pop_data->err_msg);
            mutt_sleep(2);
            return -1;
        }
    }
}
Ejemplo n.º 3
0
/*
 * This function calls  funct(*line, *data)  for each received line,
 * funct(NULL, *data)  if  rewind(*data)  needs, exits when fail or done.
 * Returned codes:
 *  0 - successful,
 * -1 - connection lost,
 * -2 - invalid command or execution error,
 * -3 - error in funct(*line, *data)
 */
int pop_fetch_data (POP_DATA *pop_data, char *query, progress_t *progressbar,
		    int (*funct) (char *, void *), void *data)
{
  char buf[LONG_STRING];
  char *inbuf;
  char *p;
  int ret, chunk = 0;
  long pos = 0;
  size_t lenbuf = 0;

  strfcpy (buf, query, sizeof (buf));
  ret = pop_query (pop_data, buf, sizeof (buf));
  if (ret < 0)
    return ret;

  inbuf = safe_malloc (sizeof (buf));

  FOREVER
  {
    chunk = mutt_socket_readln_d (buf, sizeof (buf), pop_data->conn, M_SOCK_LOG_HDR);
    if (chunk < 0)
    {
      pop_data->status = POP_DISCONNECTED;
      ret = -1;
      break;
    }

    p = buf;
    if (!lenbuf && buf[0] == '.')
    {
      if (buf[1] != '.')
	break;
      p++;
    }

    strfcpy (inbuf + lenbuf, p, sizeof (buf));
    pos += chunk;

    /* cast is safe since we break out of the loop when chunk<=0 */
    if ((size_t)chunk >= sizeof (buf))
    {
      lenbuf += strlen (p);
    }
    else
    {
      if (progressbar)
	mutt_progress_update (progressbar, pos, -1);
      if (ret == 0 && funct (inbuf, data) < 0)
	ret = -3;
      lenbuf = 0;
    }

    safe_realloc (&inbuf, lenbuf + sizeof (buf));
  }

  FREE (&inbuf);
  return ret;
}
Ejemplo n.º 4
0
/*
 * Open connection and authenticate
 *  0 - successful,
 * -1 - conection lost,
 * -2 - invalid command or execution error,
 * -3 - authentication canceled.
*/
int pop_open_connection (POP_DATA *pop_data)
{
  int ret;
  unsigned int n, size;
  char buf[LONG_STRING];

  ret = pop_connect (pop_data);
  if (ret < 0)
  {
    mutt_sleep (2);
    return ret;
  }

  ret = pop_capabilities (pop_data, 0);
  if (ret == -1)
    goto err_conn;
  if (ret == -2)
  {
    mutt_sleep (2);
    return -2;
  }

#if defined(USE_SSL)
  /* Attempt STLS if available and desired. */
  if (!pop_data->conn->ssf && (pop_data->cmd_stls || option(OPTSSLFORCETLS)))
  {
    if (option(OPTSSLFORCETLS))
      pop_data->use_stls = 2;
    if (pop_data->use_stls == 0)
    {
      ret = query_quadoption (OPT_SSLSTARTTLS,
	    _("Secure connection with TLS?"));
      if (ret == -1)
	return -2;
      pop_data->use_stls = 1;
      if (ret == M_YES)
	pop_data->use_stls = 2;
    }
    if (pop_data->use_stls == 2)
    {
      strfcpy (buf, "STLS\r\n", sizeof (buf));
      ret = pop_query (pop_data, buf, sizeof (buf));
      if (ret == -1)
	goto err_conn;
      if (ret != 0)
      {
	mutt_error ("%s", pop_data->err_msg);
	mutt_sleep (2);
      }
      else if (mutt_ssl_starttls (pop_data->conn))
      {
	mutt_error (_("Could not negotiate TLS connection"));
	mutt_sleep (2);
	return -2;
      }
      else
      {
	/* recheck capabilities after STLS completes */
	ret = pop_capabilities (pop_data, 1);
	if (ret == -1)
	  goto err_conn;
	if (ret == -2)
	{
	  mutt_sleep (2);
	  return -2;
	}
      }
    }
  }

  if (option(OPTSSLFORCETLS) && !pop_data->conn->ssf)
  {
    mutt_error _("Encrypted connection unavailable");
    mutt_sleep (1);
    return -2;
  }
#endif

  ret = pop_authenticate (pop_data);
  if (ret == -1)
    goto err_conn;
  if (ret == -3)
    mutt_clear_error ();
  if (ret != 0)
    return ret;

  /* recheck capabilities after authentication */
  ret = pop_capabilities (pop_data, 2);
  if (ret == -1)
    goto err_conn;
  if (ret == -2)
  {
    mutt_sleep (2);
    return -2;
  }

  /* get total size of mailbox */
  strfcpy (buf, "STAT\r\n", sizeof (buf));
  ret = pop_query (pop_data, buf, sizeof (buf));
  if (ret == -1)
    goto err_conn;
  if (ret == -2)
  {
    mutt_error ("%s", pop_data->err_msg);
    mutt_sleep (2);
    return ret;
  }

  sscanf (buf, "+OK %u %u", &n, &size);
  pop_data->size = size;
  return 0;

err_conn:
  pop_data->status = POP_DISCONNECTED;
  mutt_error _("Server closed connection!");
  mutt_sleep (2);
  return -1;
}
Ejemplo n.º 5
0
/* Fetch messages and save them in $spoolfile */
void pop_fetch_mail(void)
{
    char buffer[LONG_STRING];
    char msgbuf[SHORT_STRING];
    char *url, *p;
    int i, delanswer, last = 0, msgs, bytes, rset = 0, ret;
    CONNECTION *conn;
    CONTEXT ctx;
    MESSAGE *msg = NULL;
    ACCOUNT acct;
    POP_DATA *pop_data;

    if (!PopHost) {
        mutt_error _("POP host is not defined.");
        return;
    }

    url = p = safe_calloc(strlen(PopHost) + 7, sizeof(char));

    if (url_check_scheme(PopHost) == U_UNKNOWN) {
        strcpy(url, "pop://"); /* __STRCPY_CHECKED__ */
        p = strchr(url, '\0');
    }
    strcpy(p, PopHost);        /* __STRCPY_CHECKED__ */

    ret = pop_parse_path(url, &acct);
    safe_free(&url);

    if (ret) {
        mutt_error(_("%s is an invalid POP path"), PopHost);
        return;
    }

    conn = mutt_conn_find(NULL, &acct);

    if (!conn)
        return;

    pop_data = safe_calloc(1, sizeof(POP_DATA));
    pop_data->conn = conn;

    if (pop_open_connection(pop_data) < 0) {
        mutt_socket_free(pop_data->conn);
        safe_free(&pop_data);
        return;
    }

    conn->data = pop_data;

    mutt_message _("Checking for new messages...");

    /* find out how many messages are in the mailbox. */
    strfcpy(buffer, "STAT\r\n", sizeof(buffer));
    ret = pop_query(pop_data, buffer, sizeof(buffer));

    if (ret == -1)
        goto fail;

    if (ret == -2) {
        mutt_error("%s", pop_data->err_msg);
        goto finish;
    }

    sscanf(buffer, "+OK %d %d", &msgs, &bytes);

    /* only get unread messages */
    if ((msgs > 0)
        && option(OPTPOPLAST)) {
        strfcpy(buffer, "LAST\r\n", sizeof(buffer));
        ret = pop_query(pop_data, buffer, sizeof(buffer));

        if (ret == -1)
            goto fail;

        if (ret == 0)
            sscanf(buffer, "+OK %d", &last);
    }

    if (msgs <= last) {
        mutt_message _("No new mail in POP mailbox.");
        goto finish;
    }

    if (mx_open_mailbox(NONULL(Spoolfile), M_APPEND, &ctx) == NULL)
        goto finish;

    delanswer = query_quadoption(OPT_POPDELETE, _(
                                     "Delete messages from server?"));

    snprintf(msgbuf, sizeof(msgbuf), _(
                 "Reading new messages (%d bytes)..."), bytes);
    mutt_message("%s", msgbuf);

    for (i = last + 1; i <= msgs; i++) {
        if ((msg = mx_open_new_message(&ctx, NULL, M_ADD_FROM)) == NULL)
            ret = -3;
        else {
            snprintf(buffer, sizeof(buffer), "RETR %d\r\n", i);
            ret =
                pop_fetch_data(pop_data, buffer, NULL, fetch_message, msg->fp);

            if (ret == -3)
                rset = 1;

            if ((ret == 0)
                && (mx_commit_message(msg, &ctx) != 0)) {
                rset = 1;
                ret = -3;
            }

            mx_close_message(&msg);
        }

        if ((ret == 0)
            && (delanswer == M_YES)) {
            /* delete the message on the server */
            snprintf(buffer, sizeof(buffer), "DELE %d\r\n", i);
            ret = pop_query(pop_data, buffer, sizeof(buffer));
        }

        if (ret == -1) {
            mx_close_mailbox(&ctx, NULL);
            goto fail;
        }

        if (ret == -2) {
            mutt_error("%s", pop_data->err_msg);
            break;
        }

        if (ret == -3) {
            mutt_error _("Error while writing mailbox!");
            break;
        }

        mutt_message(_(
                         "%s [%d of %d messages read]"), msgbuf, i - last,
                     msgs - last);
    }

    mx_close_mailbox(&ctx, NULL);

    if (rset) {
        /* make sure no messages get deleted */
        strfcpy(buffer, "RSET\r\n", sizeof(buffer));

        if (pop_query(pop_data, buffer, sizeof(buffer)) == -1)
            goto fail;
    }

    finish:

    /* exit gracefully */
    strfcpy(buffer, "QUIT\r\n", sizeof(buffer));

    if (pop_query(pop_data, buffer, sizeof(buffer)) == -1)
        goto fail;
    mutt_socket_close(conn);
    safe_free(&pop_data);
    return;

    fail:
    mutt_error _("Server closed connection!");
    mutt_socket_close(conn);
    safe_free(&pop_data);
}
Ejemplo n.º 6
0
/*
 * Read header
 * returns:
 *  0 on success
 * -1 - connection lost,
 * -2 - invalid command or execution error,
 * -3 - error writing to tempfile
 */
static int pop_read_header(POP_DATA *pop_data, HEADER *h)
{
    FILE *f;
    int ret, index;
    long length;
    char buf[LONG_STRING];
    char tempfile[_POSIX_PATH_MAX];

    mutt_mktemp(tempfile, sizeof(tempfile));

    if (!(f = safe_fopen(tempfile, "w+"))) {
        mutt_perror(tempfile);
        return -3;
    }

    snprintf(buf, sizeof(buf), "LIST %d\r\n", h->refno);
    ret = pop_query(pop_data, buf, sizeof(buf));

    if (ret == 0) {
        sscanf(buf, "+OK %d %ld", &index, &length);

        snprintf(buf, sizeof(buf), "TOP %d 0\r\n", h->refno);
        ret = pop_fetch_data(pop_data, buf, NULL, fetch_message, f);

        if (pop_data->cmd_top == 2) {
            if (ret == 0) {
                pop_data->cmd_top = 1;

                dprint(1, "pop_read_header: set TOP capability\n");
            }

            if (ret == -2) {
                pop_data->cmd_top = 0;

                dprint(1, "pop_read_header: unset TOP capability\n");
                snprintf(pop_data->err_msg, sizeof(pop_data->err_msg),
                         _("Command TOP is not supported by server."));
            }
        }
    }

    switch (ret) {
    case 0:
    {
        rewind(f);
        h->env = mutt_read_rfc822_header(f, h, 0, 0);
        h->content->length = length - h->content->offset + 1;
        rewind(f);

        while (!feof(f)) {
            h->content->length--;
            fgets(buf, sizeof(buf), f);
        }
        break;
    }

    case -2:
    {
        mutt_error("%s", pop_data->err_msg);
        break;
    }

    case -3:
    {
        mutt_error _("Can't write header to temporary file!");
        break;
    }
    }

    safe_fclose(&f);
    unlink(tempfile);
    return ret;
}
Ejemplo n.º 7
0
/* update POP mailbox - delete messages from server */
int pop_sync_mailbox (CONTEXT *ctx, int *index_hint)
{
  int i, j, ret = 0;
  char buf[LONG_STRING];
  POP_DATA *pop_data = (POP_DATA *)ctx->data;
  progress_t progress;
#ifdef USE_HCACHE
  header_cache_t *hc = NULL;
#endif

  pop_data->check_time = 0;

  FOREVER
  {
    if (pop_reconnect (ctx) < 0)
      return -1;

    mutt_progress_init (&progress, _("Marking messages deleted..."),
			M_PROGRESS_MSG, WriteInc, ctx->deleted);

#if USE_HCACHE
    hc = pop_hcache_open (pop_data, ctx->path);
#endif

    for (i = 0, j = 0, ret = 0; ret == 0 && i < ctx->msgcount; i++)
    {
      if (ctx->hdrs[i]->deleted && ctx->hdrs[i]->refno != -1)
      {
	j++;
	if (!ctx->quiet)
	  mutt_progress_update (&progress, j, -1);
	snprintf (buf, sizeof (buf), "DELE %d\r\n", ctx->hdrs[i]->refno);
	if ((ret = pop_query (pop_data, buf, sizeof (buf))) == 0)
	{
	  mutt_bcache_del (pop_data->bcache, ctx->hdrs[i]->data);
#if USE_HCACHE
	  mutt_hcache_delete (hc, ctx->hdrs[i]->data, strlen);
#endif
	}
      }

#if USE_HCACHE
      if (ctx->hdrs[i]->changed)
      {
	mutt_hcache_store (hc, ctx->hdrs[i]->data, ctx->hdrs[i], 0, strlen, M_GENERATE_UIDVALIDITY);
      }
#endif

    }

#if USE_HCACHE
    mutt_hcache_close (hc);
#endif

    if (ret == 0)
    {
      strfcpy (buf, "QUIT\r\n", sizeof (buf));
      ret = pop_query (pop_data, buf, sizeof (buf));
    }

    if (ret == 0)
    {
      pop_data->clear_cache = 1;
      pop_clear_cache (pop_data);
      pop_data->status = POP_DISCONNECTED;
      return 0;
    }

    if (ret == -2)
    {
      mutt_error ("%s", pop_data->err_msg);
      mutt_sleep (2);
      return -1;
    }
  }
}