Пример #1
0
static int
pop_scan (mu_mailbox_t mbox, size_t msgno, size_t *pcount)
{
  int status;
  size_t i;
  size_t count = 0;
  struct _pop3_mailbox *mpd = mbox->data;
  int flags;
  mu_iterator_t itr;
  
  status = pop_messages_count (mbox, &count);
  if (status != 0)
    return status;
  if (pcount)
    *pcount = count;

  flags = _POP3_MSG_SIZE;
  if (!mu_pop3_capa_test (mpd->pop3, "XLINES", NULL))
    flags |= _POP3_MSG_LINES;

  status = mu_pop3_list_all (mpd->pop3, &itr);
  if (status)
    return status;
  
  for (i = 0, mu_iterator_first (itr);
       i <= count && !mu_iterator_is_done (itr);
       i++, mu_iterator_next (itr))
    {
      const char *str;
      char *p;
      size_t num;
      
      mu_iterator_current (itr, (void**) &str);
      num = strtoul (str, &p, 10);

      if (*p != ' ')
	{
	  mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR,
		    ("invalid reply to LIST command: %s", str));
	  status = MU_ERR_BADREPLY;
	  break;
	}
      if (num >= msgno)
	{
	  size_t size, lines;
	  struct _pop3_message *mpm;

	  size = strtoul (p + 1, &p, 10);
	  if (flags & _POP3_MSG_LINES)
	    {
	      if (*p != ' ')
		{
		  mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR,
			    ("invalid reply to LIST command: %s", str));
		  status = MU_ERR_BADREPLY;
		  break;
		}
	      lines = strtoul (p + 1, &p, 10);
	    }

	  status = pop_create_pop3_message (mpd, num, &mpm);
	  if (status)
	    break;
	  mpm->message_size = size;
	  if (flags & _POP3_MSG_LINES)
	    mpm->message_lines = lines;
	  mpm->flags |= flags;

	  if (mbox->observable)
	    {
	      if (((i + 1) % 10) == 0)
		mu_observable_notify (mbox->observable,
				      MU_EVT_MAILBOX_PROGRESS,
				      NULL);
	    }
	}
    }
  
  mu_iterator_destroy (&itr);

  if (mbox->observable)
    {
      /* MU_EVT_MESSAGE_ADD must be delivered only when it is already possible
         to retrieve the message in question.  It could not be done in the
         main loop because no other pop3d function can be called while LIST
         is being handled.  Hence the extra loop. */
      for (i = 0; i <= count; i++)
	{
	  if (mu_observable_notify (mbox->observable, MU_EVT_MESSAGE_ADD,
				    &i) != 0)
	    break;
	}
    }
  
  return status;
}
Пример #2
0
int
mu_msgset_sub_range (mu_msgset_t mset, size_t beg, size_t end, int mode)
{
  int rc;
  mu_iterator_t itr;
  struct mu_msgrange *mr;

  if (!mset)
    return EINVAL;
  if (mu_list_is_empty (mset->list))
    return MU_ERR_NOENT;
  if (end && beg > end)
    {
      size_t t = end;
      end = beg;
      beg = t;
    }

  rc = _mu_msgset_translate_pair (mset, mode, &beg, &end);
  if (rc == MU_ERR_NOENT)
    return 0;
  else if (rc)
    return rc;
  
  rc = mu_msgset_aggregate (mset);
  if (rc)
    return rc;

  if (end == MU_MSGNO_LAST)
    return sub_msgno_last (mset, beg);
  
  /* Test border cases */
  rc = mu_list_head (mset->list, (void**)&mr);
  if (rc)
    return rc;
  if (end < mr->msg_beg)
    return 0;
  if (beg < mr->msg_beg)
    beg = mr->msg_beg;
  
  rc = mu_list_tail (mset->list, (void**) &mr);
  if (mr->msg_end != MU_MSGNO_LAST)
    {
      if (beg > mr->msg_end)
	return 0;
      if (end > mr->msg_end)
	end = mr->msg_end;
    }

  rc = mu_list_get_iterator (mset->list, &itr);
  if (rc)
    return rc;
  for (mu_iterator_first (itr); rc == 0 && !mu_iterator_is_done (itr);
       mu_iterator_next (itr))
    {
      mu_iterator_current (itr, (void **)&mr);

      if (mr->msg_end == MU_MSGNO_LAST)
	{
	  /* This is the last element in list. */
	  if (mr->msg_beg == beg)
	    rc = mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
	  else if (mr->msg_beg > beg)
	    mr->msg_beg = end + 1;
	  break;
	}
      
      if (mr->msg_beg == beg && mr->msg_end == end) /* See case 2 above */
	{
	  rc = mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
	  break;
	}
      else if (mr->msg_beg <= beg && beg <= mr->msg_end) 
	{ 
	  if (mr->msg_beg <= end && end <= mr->msg_end) /* Case 3 */
	    {
	      /* Split the range */
	      if (end != mr->msg_end)
		{
		  struct mu_msgrange *newrange = calloc (1,
							 sizeof (*newrange));
		  if (!newrange)
		    {
		      rc = ENOMEM;
		      break;
		    }
		  newrange->msg_beg = end + 1;
		  newrange->msg_end = mr->msg_end;
		  rc = mu_iterator_ctl (itr, mu_itrctl_insert, newrange);
		  if (rc)
		    {
		      free (newrange);
		      break;
		    }
		}
	      
	      if (mr->msg_beg == beg)
		rc = mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
	      else
		mr->msg_end = beg - 1;
	      break;
	    }
	  else if (mr->msg_beg == beg)      /* Case 4 */
	    {
	      beg = mr->msg_end;
	      rc = mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
	    }
	  else
	    {
	      size_t n = mr->msg_end;
	      mr->msg_end = beg - 1;
	      beg = n;
	    }
	}
      else if (mr->msg_beg <= end && end <= mr->msg_end) /* Case 5 */
	{
	  mr->msg_beg = end + 1;
	  if (mr->msg_beg >= mr->msg_end)
	    rc = mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
	  break;
	}
      else if (beg <= mr->msg_beg && mr->msg_beg <= end)
	{
	  rc = mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
	}
    }
  mu_iterator_destroy (&itr);
  
  return rc;
}