Example #1
0
/* %d */
static char *
hdr_date (struct header_call_args *args, void *data)
{
  char date[80];
  mu_header_t hdr;

  mu_message_get_header (args->msg, &hdr);
  
  date[0] = 0;
  if (mailvar_get (NULL, "datefield", mailvar_type_boolean, 0) == 0
      && mu_header_get_value (hdr, MU_HEADER_DATE,
			      date, sizeof (date), NULL) == 0)
    {
      time_t t;
      if (mu_parse_date (date, &t, NULL) == 0)
	strftime (date, sizeof(date), "%a %b %e %H:%M", localtime (&t));
      else
	date[0] = 0;
    }

  if (date[0] == 0)
    {
      const char *p;
      struct tm tm;
      mu_timezone tz;
      mu_envelope_t env;
      
      mu_message_get_envelope (args->msg, &env);
      if (mu_envelope_sget_date (env, &p) == 0
          && mu_parse_ctime_date_time (&p, &tm, &tz) == 0)
	strftime (date, sizeof(date), "%a %b %e %H:%M", &tm);
    }
  return header_buf_string (args, date);
}
Example #2
0
int
print_envelope (msgset_t *mspec, mu_message_t msg, void *data)
{
  int status;
  mu_envelope_t env = NULL;
  const char *sender = NULL, *date = NULL;

  status = mu_message_get_envelope (msg, &env);
  if (status)
    {
      mu_error (_("%lu: Cannot get envelope"),
		(unsigned long) mspec->msg_part[0]);
    }
  else
    {
      mu_envelope_sget_sender (env, &sender);
      mu_envelope_sget_date (env, &date);
      if (data)
	mu_printf ("%s ", (char*) data);
      mu_printf ("%s %s", sender, date);
    }
  return 0;
}
Example #3
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;
}
Example #4
0
/* %f */
static char *
hdr_from (struct header_call_args *args, void *data)
{
  char *from = NULL;
  
  if (mailvar_get (NULL, "fromfield", mailvar_type_boolean, 0) == 0)
    {  
      mu_header_t hdr;
      
      mu_message_get_header (args->msg, &hdr);
      if (mu_header_aget_value_unfold (hdr, MU_HEADER_FROM, &from) == 0)
	{
	  mu_address_t address = NULL;
	  if (mu_address_create (&address, from) == 0)
	    {
	      char *name;
	      const char *email;
	  
	      if (mu_address_sget_email (address, 1, &email) == 0)
		{
		  if (mailvar_get (NULL, "showto",
				   mailvar_type_boolean, 0) == 0
		      && mail_is_my_name (email))
		    {
		      char *tmp;

		      if (mu_header_aget_value_unfold (hdr, MU_HEADER_TO, 
						       &tmp) == 0)
			{
			  mu_address_t addr_to;
			  if (mu_address_create (&addr_to, tmp) == 0)
			    {
			      mu_address_destroy (&address);
			      address = addr_to;
			    }
			  free (tmp);
			}
		    }
		}
	      
	      if ((mu_address_aget_personal (address, 1, &name) == 0
		   && name)
		  || (mu_address_aget_email (address, 1, &name) == 0
		      && name))
		{
		  free (from);
		  from = name;
		}
	      mu_address_destroy (&address);
	    }
	}
      util_rfc2047_decode (&from);
    }
  else
    {
      mu_envelope_t env = NULL;
      const char *sender = "";
      
      if (mu_message_get_envelope (args->msg, &env) == 0)
	mu_envelope_sget_sender (env, &sender);
      from = strdup (sender);
    }

  header_buf_string (args, from);
  free (from);
  return args->buf;
}