Exemple #1
0
/**
 * reopen_mailbox - Close and reopen a mailbox
 * @param m          Mailbox
 * @param index_hint Current email
 * @retval >0 Success, e.g. #MUTT_REOPENED, #MUTT_NEW_MAIL
 * @retval -1 Error
 */
static int reopen_mailbox(struct Mailbox *m, int *index_hint)
{
  if (!m)
    return -1;

  struct MboxAccountData *adata = mbox_adata_get(m);
  if (!adata)
    return -1;

  bool (*cmp_headers)(const struct Email *, const struct Email *) = NULL;
  struct Email **old_hdrs = NULL;
  int old_msg_count;
  bool msg_mod = false;
  int rc = -1;

  /* silent operations */
  m->quiet = true;

  if (!m->quiet)
    mutt_message(_("Reopening mailbox..."));

  /* our heuristics require the old mailbox to be unsorted */
  if (C_Sort != SORT_ORDER)
  {
    short old_sort = C_Sort;
    C_Sort = SORT_ORDER;
    mutt_mailbox_changed(m, MBN_RESORT);
    C_Sort = old_sort;
  }

  old_hdrs = NULL;
  old_msg_count = 0;

  /* simulate a close */
  mutt_mailbox_changed(m, MBN_CLOSED);
  mutt_hash_free(&m->id_hash);
  mutt_hash_free(&m->subj_hash);
  mutt_hash_free(&m->label_hash);
  FREE(&m->v2r);
  if (m->readonly)
  {
    for (int i = 0; i < m->msg_count; i++)
      mutt_email_free(&(m->emails[i])); /* nothing to do! */
    FREE(&m->emails);
  }
  else
  {
    /* save the old headers */
    old_msg_count = m->msg_count;
    old_hdrs = m->emails;
    m->emails = NULL;
  }

  m->email_max = 0; /* force allocation of new headers */
  m->msg_count = 0;
  m->vcount = 0;
  m->msg_tagged = 0;
  m->msg_deleted = 0;
  m->msg_new = 0;
  m->msg_unread = 0;
  m->msg_flagged = 0;
  m->changed = false;
  m->id_hash = NULL;
  m->subj_hash = NULL;
  mutt_make_label_hash(m);

  switch (m->magic)
  {
    case MUTT_MBOX:
    case MUTT_MMDF:
      cmp_headers = mutt_email_cmp_strict;
      mutt_file_fclose(&adata->fp);
      adata->fp = mutt_file_fopen(m->path, "r");
      if (!adata->fp)
        rc = -1;
      else if (m->magic == MUTT_MBOX)
        rc = mbox_parse_mailbox(m);
      else
        rc = mmdf_parse_mailbox(m);
      break;

    default:
      rc = -1;
      break;
  }

  if (rc == -1)
  {
    /* free the old headers */
    for (int i = 0; i < old_msg_count; i++)
      mutt_email_free(&(old_hdrs[i]));
    FREE(&old_hdrs);

    m->quiet = false;
    return -1;
  }

  mutt_file_touch_atime(fileno(adata->fp));

  /* now try to recover the old flags */

  if (!m->readonly)
  {
    for (int i = 0; i < m->msg_count; i++)
    {
      bool found = false;

      /* some messages have been deleted, and new  messages have been
       * appended at the end; the heuristic is that old messages have then
       * "advanced" towards the beginning of the folder, so we begin the
       * search at index "i" */
      int j;
      for (j = i; j < old_msg_count; j++)
      {
        if (!old_hdrs[j])
          continue;
        if (cmp_headers(m->emails[i], old_hdrs[j]))
        {
          found = true;
          break;
        }
      }
      if (!found)
      {
        for (j = 0; (j < i) && (j < old_msg_count); j++)
        {
          if (!old_hdrs[j])
            continue;
          if (cmp_headers(m->emails[i], old_hdrs[j]))
          {
            found = true;
            break;
          }
        }
      }

      if (found)
      {
        /* this is best done here */
        if (index_hint && (*index_hint == j))
          *index_hint = i;

        if (old_hdrs[j]->changed)
        {
          /* Only update the flags if the old header was changed;
           * otherwise, the header may have been modified externally,
           * and we don't want to lose _those_ changes */
          mutt_set_flag(m, m->emails[i], MUTT_FLAG, old_hdrs[j]->flagged);
          mutt_set_flag(m, m->emails[i], MUTT_REPLIED, old_hdrs[j]->replied);
          mutt_set_flag(m, m->emails[i], MUTT_OLD, old_hdrs[j]->old);
          mutt_set_flag(m, m->emails[i], MUTT_READ, old_hdrs[j]->read);
        }
        mutt_set_flag(m, m->emails[i], MUTT_DELETE, old_hdrs[j]->deleted);
        mutt_set_flag(m, m->emails[i], MUTT_PURGE, old_hdrs[j]->purge);
        mutt_set_flag(m, m->emails[i], MUTT_TAG, old_hdrs[j]->tagged);

        /* we don't need this header any more */
        mutt_email_free(&(old_hdrs[j]));
      }
    }

    /* free the remaining old headers */
    for (int j = 0; j < old_msg_count; j++)
    {
      if (old_hdrs[j])
      {
        mutt_email_free(&(old_hdrs[j]));
        msg_mod = true;
      }
    }
    FREE(&old_hdrs);
  }

  m->quiet = false;

  return (m->changed || msg_mod) ? MUTT_REOPENED : MUTT_NEW_MAIL;
}
Exemple #2
0
int mutt_reopen_mailbox(CONTEXT *ctx, int *index_hint)
{
    int (*cmp_headers) (const HEADER *,
                        const HEADER *) = NULL;
    HEADER **old_hdrs;
    int old_msgcount;
    int msg_mod = 0;
    int index_hint_set;
    int i, j;
    int rc = -1;

    /* silent operations */
    ctx->quiet = 1;

    if (!ctx->quiet)
        mutt_message _("Reopening mailbox...");

    /* our heuristics require the old mailbox to be unsorted */
    if (Sort != SORT_ORDER) {
        short old_sort;

        old_sort = Sort;
        Sort = SORT_ORDER;
        mutt_sort_headers(ctx, 1);
        Sort = old_sort;
    }

    old_hdrs = NULL;
    old_msgcount = 0;

    /* simulate a close */
    if (ctx->id_hash)
        hash_destroy(&ctx->id_hash, NULL);

    if (ctx->subj_hash)
        hash_destroy(&ctx->subj_hash, NULL);
    mutt_clear_threads(ctx);
    safe_free(&ctx->v2r);

    if (ctx->readonly) {
        for (i = 0; i < ctx->msgcount; i++)
            mutt_free_header(&(ctx->hdrs[i]));  /* nothing to do! */
        safe_free(&ctx->hdrs);
    } else {
        /* save the old headers */
        old_msgcount = ctx->msgcount;
        old_hdrs = ctx->hdrs;
        ctx->hdrs = NULL;
    }

    ctx->hdrmax = 0; /* force allocation of new headers */
    ctx->msgcount = 0;
    ctx->vcount = 0;
    ctx->tagged = 0;
    ctx->deleted = 0;
    ctx->new_messages = 0;
    ctx->unread = 0;
    ctx->flagged = 0;
    ctx->changed = 0;
    ctx->id_hash = NULL;
    ctx->subj_hash = NULL;

    switch (ctx->magic) {
    case M_MBOX:
    case M_MMDF:
        cmp_headers = mbox_strict_cmp_headers;
        safe_fclose(&ctx->fp);

        if (!(ctx->fp = safe_fopen(ctx->path, "r")))
            rc = -1;
        else
            rc = ((ctx->magic == M_MBOX) ? mbox_parse_mailbox
                  : mmdf_parse_mailbox)(ctx);
        break;

    default:
        rc = -1;
        break;
    }

    if (rc == -1) {
        /* free the old headers */
        for (j = 0; j < old_msgcount; j++)
            mutt_free_header(&(old_hdrs[j]));
        safe_free(&old_hdrs);

        ctx->quiet = 0;
        return -1;
    }

    /* now try to recover the old flags */

    index_hint_set = (index_hint == NULL);

    if (!ctx->readonly) {
        for (i = 0; i < ctx->msgcount; i++) {
            int found = 0;

            /* some messages have been deleted, and new  messages have been
             * appended at the end; the heuristic is that old messages have then
             * "advanced" towards the beginning of the folder, so we begin the
             * search at index "i"
             */
            for (j = i; j < old_msgcount; j++) {
                if (old_hdrs[j] == NULL)
                    continue;

                if (cmp_headers(ctx->hdrs[i], old_hdrs[j])) {
                    found = 1;
                    break;
                }
            }

            if (!found) {
                for (j = 0; j < i
                     && j < old_msgcount; j++) {
                    if (old_hdrs[j] == NULL)
                        continue;

                    if (cmp_headers(ctx->hdrs[i], old_hdrs[j])) {
                        found = 1;
                        break;
                    }
                }
            }

            if (found) {
                /* this is best done here */
                if (!index_hint_set
                    && (*index_hint == j))
                    *index_hint = i;

                if (old_hdrs[j]->changed) {
                    /* Only update the flags if the old header was changed;
                     * otherwise, the header may have been modified externally,
                     * and we don't want to lose _those_ changes
                     */
                    mutt_set_flag(ctx, ctx->hdrs[i], M_FLAG, old_hdrs[j]->flagged);
                    mutt_set_flag(ctx, ctx->hdrs[i], M_REPLIED, old_hdrs[j]->replied);
                    mutt_set_flag(ctx, ctx->hdrs[i], M_OLD, old_hdrs[j]->old);
                    mutt_set_flag(ctx, ctx->hdrs[i], M_READ, old_hdrs[j]->read);
                }
                mutt_set_flag(ctx, ctx->hdrs[i], M_DELETE, old_hdrs[j]->deleted);
                mutt_set_flag(ctx, ctx->hdrs[i], M_TAG, old_hdrs[j]->tagged);

                /* we don't need this header any more */
                mutt_free_header(&(old_hdrs[j]));
            }
        }

        /* free the remaining old headers */
        for (j = 0; j < old_msgcount; j++) {
            if (old_hdrs[j]) {
                mutt_free_header(&(old_hdrs[j]));
                msg_mod = 1;
            }
        }
        safe_free(&old_hdrs);
    }

    ctx->quiet = 0;

    return (ctx->changed
            || msg_mod) ? M_REOPENED : M_NEW_MAIL;
}