Exemplo n.º 1
0
void
rmm (mu_mailbox_t mbox, mu_message_t msg, size_t num, void *data)
{
  mu_attribute_t attr;
  mu_message_get_attribute (msg, &attr);
  mu_attribute_set_deleted (attr);
}
Exemplo n.º 2
0
/* %a */
static char *
hdr_attr (struct header_call_args *args, void *data)
{
  mu_attribute_t attr;
  char cflag;
  
  mu_message_get_attribute (args->msg, &attr);
  
  if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_MBOXED))
    cflag = 'M';
  else if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_PRESERVED))
    cflag = 'P';
  else if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_SAVED))
    cflag = '*';
  else if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_TAGGED))
    cflag = 'T';
  else if (mu_attribute_is_userflag (attr, MAIL_ATTRIBUTE_SHOWN))
    cflag = 'R';
  else if (mu_attribute_is_recent (attr))
    cflag = 'N';
  else if (!mu_attribute_is_read (attr))
    cflag = 'U';
  else
    cflag = ' ';
  return header_buf_string_len (args, &cflag, 1);
}
Exemplo n.º 3
0
int
pop3d_uidl (char *arg, struct pop3d_session *sess)
{
  size_t mesgno;
  char uidl[128];
  mu_message_t msg;
  mu_attribute_t attr;

  if (state != TRANSACTION)
    return ERR_WRONG_STATE;

  if (strchr (arg, ' ') != NULL)
    return ERR_BAD_ARGS;

  if (strlen (arg) == 0)
    {
      size_t total = 0;
      pop3d_outf ("+OK\n");
      mu_mailbox_messages_count (mbox, &total);
      for (mesgno = 1; mesgno <= total; mesgno++)
        {
          mu_mailbox_get_message (mbox, mesgno, &msg);
          mu_message_get_attribute (msg, &attr);
          if (!pop3d_is_deleted (attr))
            {
              mu_message_get_uidl (msg, uidl, sizeof (uidl), NULL);
              pop3d_outf ("%s %s\n", mu_umaxtostr (0, mesgno), uidl);
            }
        }
      pop3d_outf (".\n");
    }
  else
    {
      mesgno = strtoul (arg, NULL, 10);
      if (mu_mailbox_get_message (mbox, mesgno, &msg) != 0)
        return ERR_NO_MESG;
      mu_message_get_attribute (msg, &attr);
      if (pop3d_is_deleted (attr))
        return ERR_MESG_DELE;
      mu_message_get_uidl (msg, uidl, sizeof (uidl), NULL);
      pop3d_outf ("+OK %s %s\n", mu_umaxtostr (0, mesgno), uidl);
    }

  return OK;
}
Exemplo n.º 4
0
static int
moderator_filter_message (mu_sieve_machine_t mach, mu_list_t tags,
			  mu_message_t msg, int *pdiscard)
{
  int rc;
  mu_sieve_machine_t newmach;
  mu_attribute_t attr;
  mu_sieve_value_t *arg;
  
  if (mu_sieve_tag_lookup (tags, "source", &arg))
    {
      rc = mu_sieve_machine_inherit (mach, &newmach);
      if (rc)
	{
	  mu_sieve_error (mach, _("cannot initialize sieve machine: %s"),
			  mu_strerror (rc));
	  return 1;
	}
      /* FIXME: This should be configurable:
	   moderator :inherit
	   moderator :debug 2
	   ...
      */
      
      rc = mu_sieve_compile (newmach, arg->v.string);
      if (rc)
	mu_sieve_error (mach, _("cannot compile source `%s'"), arg->v.string);
    }
  else
    rc = mu_sieve_machine_dup (mach, &newmach);

  if (rc)
    return rc;

  mu_message_get_attribute (msg, &attr);
  mu_attribute_unset_deleted (attr);
  
  rc = mu_sieve_message (newmach, msg);

  if (rc)
    mu_sieve_error (newmach, _("failed to run inferior sieve machine"));
  else
    *pdiscard = mu_attribute_is_deleted (attr);
  
  mu_sieve_machine_destroy (&newmach);

  return rc;
}
Exemplo n.º 5
0
static int
_do_store (size_t msgno, mu_message_t msg, void *data)
{
  struct store_parse_closure *pclos = data;
  mu_attribute_t attr = NULL;
      
  mu_message_get_attribute (msg, &attr);
	      
  switch (pclos->how)
    {
    case STORE_ADD:
      mu_attribute_set_flags (attr, pclos->type);
      break;
      
    case STORE_UNSET:
      mu_attribute_unset_flags (attr, pclos->type);
      break;
      
    case STORE_SET:
      mu_attribute_unset_flags (attr, 0xffffffff); /* FIXME */
      mu_attribute_set_flags (attr, pclos->type);
    }

	  
  if (pclos->ack)
    {
      io_sendf ("* %lu FETCH (", (unsigned long) msgno);
      
      if (pclos->isuid)
	{
	  size_t uid;
	  int rc = mu_mailbox_translate (mbox, MU_MAILBOX_UID_TO_MSGNO,
					 msgno, &uid);
	  if (rc == 0)
	    io_sendf ("UID %lu ", (unsigned long) uid);
	}
      io_sendf ("FLAGS (");
      util_print_flags (attr);
      io_sendf ("))\n");
    }
  /* Update the flags of uid table.  */
  imap4d_sync_flags (msgno);
  return 0;
}
Exemplo n.º 6
0
int
pop3d_stat (char *arg)
{
  size_t mesgno;
  size_t size = 0;
  size_t lines = 0;
  size_t total = 0;
  size_t num = 0;
  size_t tsize = 0;
  mu_message_t msg = NULL;
  mu_attribute_t attr = NULL;

  if (strlen (arg) != 0)
    return ERR_BAD_ARGS;

  if (state != TRANSACTION)
    return ERR_WRONG_STATE;

  /* rfc1939: if the POP3 server host internally represents end-of-line as a
     single character, then the POP3 server simply counts each occurrence of
     this character in a message as two octets. */
  mu_mailbox_messages_count (mbox, &total);
  for (mesgno = 1; mesgno <= total; mesgno++)
    {
      mu_mailbox_get_message (mbox, mesgno, &msg);
      mu_message_get_attribute (msg, &attr);
      /* rfc1939: Note that messages marked as deleted are not counted in
	 either total.  */
      if (!pop3d_is_deleted (attr))
	{
	  mu_message_size (msg, &size);
	  mu_message_lines (msg, &lines);
	  tsize += size + lines;
	  num++;
	}
    }
  pop3d_outf ("+OK %s %s\r\n", mu_umaxtostr (0, num), mu_umaxtostr (1, tsize));

  return OK;
}
Exemplo n.º 7
0
static int
moderator_action (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
{
  mu_message_t msg, orig;
  int rc;
  size_t nparts = 0;
  int discard = 0;
  int ismime;
  
  if (mu_sieve_get_debug_level (mach) & MU_SIEVE_DEBUG_TRACE)
    {
      mu_sieve_debug (mach, "moderator_test %lu",
		      (unsigned long) mu_sieve_get_message_num (mach));
    }

  msg = mu_sieve_get_message (mach);
  mu_message_is_multipart (msg, &ismime);

  if (!ismime)
    {
      mu_sieve_error (mach, _("message is not multipart"));
      mu_sieve_abort (mach);
    }

  mu_message_get_num_parts (msg, &nparts);

  if (nparts != 3) /* Mailman moderation requests have three parts */
    {
      mu_sieve_error (mach, _("expected 3 parts, but found %lu"),
		      (unsigned long) nparts);
      mu_sieve_abort (mach);
    }

  if ((rc = moderator_message_get_part (mach, msg, 2, &orig)))
    mu_sieve_abort (mach);

  rc = moderator_filter_message (mach, tags, orig, &discard);
  mu_message_unref (orig);
  if (rc)
    mu_sieve_abort (mach);

  if (discard && !mu_sieve_is_dry_run (mach))
    {
      mu_message_t request;
      char *from = NULL;
      mu_sieve_value_t *arg;
      
      if ((rc = moderator_message_get_part (mach, msg, 3, &request)))
	{
	  mu_sieve_error (mach, _("cannot get message part #3: %s"),
			  mu_strerror (rc));
	  mu_sieve_abort (mach);
	}

      if (mu_sieve_tag_lookup (tags, "address", &arg))
	from = arg->v.string;
      
      if (moderator_discard_message (mach, request, from))
	discard = 0;
      else
	{
	  if (!mu_sieve_tag_lookup (tags, "keep", NULL))
	    {
	      mu_attribute_t attr = 0;

	      if (mu_message_get_attribute (msg, &attr) == 0)
		mu_attribute_set_deleted (attr);
	    }
	  else
	    discard = 0;
	}
      mu_message_unref (request);
    }

  mu_sieve_log_action (mach, "MODERATOR", 
		       discard ? _("discarding message") :
		       _("keeping message"));
  return 0;
}
Exemplo n.º 8
0
/* FIXME: Do we need to escape body line that begins with "From "? This
   will require reading the body line by line instead of by chunks,
   considerably hurting perfomance when expunging.  But should not this
   be the responsibility of the client ?  */
static int
mbox_append_message0 (mu_mailbox_t mailbox, mu_message_t msg, mu_off_t *psize,
		      int is_expunging, int first)
{
  mbox_data_t mud = mailbox->data;
  int status = 0;
  size_t n = 0;
  char nl = '\n';
  size_t orig_size = *psize;
  char *s;
  
  switch (mud->state)
    {
    case MBOX_NO_STATE:
      mud->off = 0;
      mud->state = MBOX_STATE_APPEND_SENDER;

    case MBOX_STATE_APPEND_SENDER:
      /* Generate the sender for the "From " separator.  */
      {
	char *s;
	mu_envelope_t envelope = NULL;
	mu_message_get_envelope (msg, &envelope);
	status = mu_envelope_aget_sender (envelope, &mud->sender);
	switch (status) {
	case 0:
	  break;
	  
	case EAGAIN:
	  return status;

	case MU_ERR_NOENT: /* Envelope headers not found: try to guess */
	  free (mud->sender);
          mud->sender = NULL;
	  status = restore_sender (msg, mud);
	  if (status == 0)
            break;
	  
	default:
	  free (mud->sender);
	  free (mud->date);
	  mud->date = mud->sender = NULL;
	  mud->state = MBOX_NO_STATE;
	  return status;
	}

	/* Nuke trailing newline.  */
	s = strchr (mud->sender, nl);
	if (s)
	  *s = '\0';
	mud->state = MBOX_STATE_APPEND_DATE;
      }

    case MBOX_STATE_APPEND_DATE:
      /* Generate a date for the "From "  separator.  */
      {
	mu_envelope_t envelope = NULL;
	const char *envarr[5];
	
	mu_message_get_envelope (msg, &envelope);
	status = mu_envelope_aget_date (envelope, &mud->date);
	switch (status) {
	case 0:
	  break;
	  
	case EAGAIN:
	  return status;

	case MU_ERR_NOENT: /* Envelope headers not found: try to guess */
	  free (mud->date);
          mud->date = NULL;
	  status = restore_date (msg, mud);
	  if (status == 0)
	    break;
	  
	default:
	  free (mud->sender);
	  free (mud->date);
	  mud->date = mud->sender = NULL;
	  mud->state = MBOX_NO_STATE;
	  return status;
	}

	/* Nuke trailing newline.  */
	s = strchr (mud->date, nl);
	if (s)
	  *s = '\0';

	/* Write the separator to the mailbox.  */
	envarr[0] = "From ";
	envarr[1] = mud->sender;
	envarr[2] = " ";
	envarr[3] = mud->date;
	envarr[4] = "\n";
	
	status = write_array (mailbox->stream, psize, 5, envarr);
	if (status)
	  break;

	free (mud->sender);
	free (mud->date);
	mud->sender = mud->date = NULL;
	/* If we are not expunging get the message in one block via the stream
	   message instead of the header/body.  This is good for POP where
	   there is no separation between header and body(RETR).  */
	if (! is_expunging)
	  {
	    mud->state = MBOX_STATE_APPEND_MESSAGE;
	    break;
	  }
	mud->state = MBOX_STATE_APPEND_HEADER;
      }

    case MBOX_STATE_APPEND_HEADER:
      /* Append the Header.  */
      {
	char buffer[1024];
	size_t nread = 0;
	mu_stream_t is = NULL;
	mu_header_t header = NULL;
	mu_message_get_header (msg, &header);
	mu_header_get_stream (header, &is);
	do
	  {
	    status = mu_stream_readline (is, buffer, sizeof (buffer), mud->off,
					 &nread);
	    if (status != 0)
	      {
		if (status != EAGAIN)
		  {
		    mud->state = MBOX_NO_STATE;
		    mud->off = 0;
		  }
		mu_stream_truncate (mailbox->stream, orig_size);
		return status;
	      }
	    mud->off += nread;
	    if (*buffer == '\n')
	      break;

	    /* We do not copy the Status since it is rewritten by the
	       attribute code below. Ditto for X-UID and X-IMAPBase.
	       FIXME:
	       - We have a problem here the header may not fit the buffer.
	       - Should  we skip the IMAP "X-Status"? */
	    if ((mu_c_strncasecmp (buffer, "Status", 6) == 0)
		|| (mu_c_strncasecmp (buffer, "X-IMAPbase", 10) == 0)
		/* FIXME: isn't the length of "X-UID" 5, not 4? And
		 this will match X-UID and X-UIDL, is this intended? */
		|| (mu_c_strncasecmp (buffer, "X-UID", 4) == 0
		    && (buffer[5] == ':' || buffer[5] == ' '
			|| buffer[5] == '\t')))
	      continue;

	    status = mu_stream_write (mailbox->stream, buffer, nread,
				      *psize, &n);
	    if (status)
	      break;
	    *psize += n;
	  }
	while (nread > 0);
	mud->off = 0;

	/* Rewrite the X-IMAPbase marker. */
	if (first && is_expunging)
	  {
	    n = sprintf (buffer, "X-IMAPbase: %lu %u\n",
			 (unsigned long) mud->uidvalidity,
			 (unsigned) mud->uidnext);
	    status = mu_stream_write (mailbox->stream, buffer, n, *psize, &n);
	    if (status)
	      break;
	    *psize += n;
	  }
	mud->state = MBOX_STATE_APPEND_ATTRIBUTE;
      }

      case MBOX_STATE_APPEND_ATTRIBUTE:
      /* Put the new attributes.  */
      {
#define STATUS_PREFIX_LEN (sizeof(MU_HEADER_STATUS) - 1 + 2)
	char abuf[STATUS_PREFIX_LEN + MU_STATUS_BUF_SIZE + 1];
	size_t na = 0;
	mu_attribute_t attr = NULL;

	strcpy(abuf, MU_HEADER_STATUS);
	strcat(abuf, ": ");
	mu_message_get_attribute (msg, &attr);
	mu_attribute_to_string (attr, abuf + STATUS_PREFIX_LEN, 
	                        sizeof(abuf) - STATUS_PREFIX_LEN - 1, &na);
	strcat (abuf, "\n");
	na = strlen (abuf);
	mu_stream_write (mailbox->stream, abuf, na, *psize, &n);
	if (status != 0)
	  break;
	*psize += n;

	mud->state = MBOX_STATE_APPEND_UID;
      }

    case MBOX_STATE_APPEND_UID:
      /* The new X-UID. */
      {
	char suid[64];
	size_t uid = 0;
	if (is_expunging)
	  {
	    status = mu_message_get_uid (msg, &uid);
	    if (status == EAGAIN)
	      return status;
	  }
	else
	  uid = mud->uidnext++;

	if (status == 0 || uid != 0)
	  {
	    n = sprintf (suid, "X-UID: %u\n", (unsigned) uid);
	    /* Put the UID.  */
	    status = mu_stream_write (mailbox->stream, suid, n, *psize, &n);
	    if (status)
	      break;
	    *psize += n;
	  }

	/* New line separator of the Header.  */
	status = mu_stream_write (mailbox->stream, &nl , 1, *psize, &n);
	if (status)
	  break;
	*psize += n;
	mud->state = MBOX_STATE_APPEND_BODY;
      }

    case MBOX_STATE_APPEND_BODY:
      /* Append the Body.  */
      {
	char buffer[1024];
	size_t nread = 0;
	mu_stream_t is = NULL;
	mu_body_t body = NULL;
	mu_message_get_body (msg, &body);
	mu_body_get_stream (body, &is);
	do
	  {
	    status = mu_stream_read (is, buffer, sizeof (buffer), mud->off,
				     &nread);
	    if (status != 0)
	      {
		if (status != EAGAIN)
		  {
		    mud->state = MBOX_NO_STATE;
		    mud->off = 0;
		  }
		return status;
	      }
	    mud->off += nread;
	    status = mu_stream_write (mailbox->stream, buffer, nread,
				      *psize, &n);
	    if (status)
	      break;
	    *psize += n;
	  }
	while (nread > 0);
	mud->off = 0;
	n = 0;
	status = mu_stream_write (mailbox->stream, &nl, 1, *psize, &n);
	if (status)
	  break;
	*psize += n;
      }

    default:
      break;
    }

  /* If not expunging we are taking the stream message.  */
  if (!is_expunging)
    {
      switch (mud->state)
        {
	case MBOX_STATE_APPEND_MESSAGE:
	  {
	    /* Append the Message.  */
	    char buffer[1024];
	    size_t nread = 0;
	    mu_stream_t is = NULL;
	    mu_message_get_stream (msg, &is);
	    do
	      {
		status = mu_stream_read (is, buffer, sizeof (buffer), mud->off,
				      &nread);
		if (status != 0)
		  {
		    if (status != EAGAIN)
		      {
			mud->state = MBOX_NO_STATE;
			mud->off = 0;
		      }
		    mu_stream_truncate (mailbox->stream, orig_size);
		    return status;
		  }
		status = mu_stream_write (mailbox->stream, buffer, nread,
					  *psize, &n);
		if (status)
		  break;
		mud->off += nread;
		*psize += n;
	      }
	    while (nread > 0);
	    if (status)
	      break;
       	    status = mu_stream_write (mailbox->stream, &nl, 1, *psize, &n);
	    if (status == 0)
	      *psize += n;
	  }

	default:
	  break;
	}
    } /* is_expunging */
  mud->state = MBOX_NO_STATE;
  if (status)
    mu_stream_truncate (mailbox->stream, orig_size);
  else
    mu_stream_flush (mailbox->stream);
  return status;
}