view src/header.c @ 0:08114f7dcc23 0.2.21

this is masqmail-0.2.21 from oliver kurth
author meillo@marmaro.de
date Fri, 26 Sep 2008 17:05:23 +0200
parents
children 26e34ae9a3e3
line wrap: on
line source

/*  MasqMail
    Copyright (C) 2000 Oliver Kurth

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "masqmail.h"

header_name header_names[] =
{
  { "From", HEAD_FROM, },
  { "Sender", HEAD_SENDER, },
  { "To", HEAD_TO, },
  { "Cc", HEAD_CC, },
  { "Bcc", HEAD_BCC, },
  { "Date", HEAD_DATE, },
  { "Message-Id", HEAD_MESSAGE_ID, },
  { "Reply-To", HEAD_REPLY_TO, },
  { "Subject", HEAD_SUBJECT, },
  { "Return-Path", HEAD_RETURN_PATH, },
  { "Envelope-To", HEAD_ENVELOPE_TO, },
  { "Received", HEAD_RECEIVED },
};

/* this was borrowed from exim and slightly changed */
gchar *rec_timestamp()
{
  static gchar buf[64];
  int len;
  
  time_t now = time(NULL);
  struct tm *t = localtime(&now);

  int diff_hour, diff_min;
  struct tm local;
  struct tm *gmt;

  memcpy(&local, t, sizeof(struct tm));
  gmt = gmtime(&now);
  diff_min = 60*(local.tm_hour - gmt->tm_hour) + local.tm_min - gmt->tm_min;
  if (local.tm_year != gmt->tm_year)
    diff_min += (local.tm_year > gmt->tm_year)? 1440 : -1440;
  else if (local.tm_yday != gmt->tm_yday)
    diff_min += (local.tm_yday > gmt->tm_yday)? 1440 : -1440;
  diff_hour = diff_min/60;
  diff_min  = abs(diff_min - diff_hour*60);

  len = strftime(buf, sizeof(buf), "%a, ", &local);
  g_snprintf(buf + len, sizeof(buf) - len, "%02d ", local.tm_mday);
  len += strlen(buf + len);
  len += strftime(buf + len, sizeof(buf) - len, "%b %Y %H:%M:%S", &local);
  g_snprintf(buf + len, sizeof(buf) - len, " %+03d%02d", diff_hour, diff_min);

  return buf;
}

/* finds list of headers matching id
   if id == HEAD_UNKNOWN and header == NULL finds all unknown headers
   else finds all headers matching header
*/
GList *find_header(GList *hdr_list, header_id id, gchar *hdr_str)
{
  GList *found_list = NULL;
  GList *node;

  if((id != HEAD_UNKNOWN) || (hdr_str == NULL)){
    foreach(hdr_list, node){
      header *hdr = (header *)(node->data);
      if(hdr->id == id)
        found_list = g_list_append(found_list, hdr);
    }
  }else{
    foreach(hdr_list, node){
      header *hdr = (header *)(node->data);
      gchar buf[64], *q = buf, *p = hdr->header;
      
      while(*p != ':' && q < buf+63 && *p) *(q++) = *(p++);
      *q = 0;
      
      if(strcasecmp(buf, hdr_str) == 0)
        found_list = g_list_append(found_list, hdr);
    }
  }
  return found_list;
}

void header_unfold(header *hdr)
{
  gchar *tmp_hdr = g_malloc(strlen(hdr->header));
  gchar *p = hdr->header, *q = tmp_hdr;
  gboolean flag = FALSE;

  while(*p){
    if(*p != '\n')
      *(q++) = *p;
    else
      flag = TRUE;
    p++;
  }
  *(q++) = '\n';

  if(flag){
    gchar *new_hdr;

    g_free(hdr->header);
    new_hdr = g_strdup(tmp_hdr);
    g_free(tmp_hdr);
    hdr->value = new_hdr + (hdr->value - hdr->header);
    hdr->header = new_hdr;
  }
}

#define MAX_HDR_LEN 72
void header_fold(header *hdr)
{
  gint len = strlen(hdr->header);
  gchar *p, *q;
  /* size is probably overestimated, but so we are on the safe side */
  gchar *tmp_hdr = g_malloc(len + 2*len/MAX_HDR_LEN);

  p = hdr->header;
  q = tmp_hdr;

  if(p[len-1] == '\n')
    p[len-1] = 0;

  while(*p){
    gint i,l;
    gchar *pp;
    
    /* look forward and find potential break points */
    i = 0; l = -1;
    pp = p;
    while(*pp && (i < MAX_HDR_LEN)){
      if((*pp == ' ') || (*pp == '\t'))
	l = i;
      pp++;
      i++;
    }
    if(!*pp) l = pp-p; /* take rest, if EOS found */

    if(l == -1){
      /* no potential break point was found within MAX_HDR_LEN
       so advance further until the next */
      while(*pp && *pp != ' ' && *pp != '\t'){
	pp++;
	i++;
      }
      l = i;
    }

    /* copy */
    i = 0;
    while(i < l){
      *(q++) = *(p++);
      i++;
    }
    *(q++) = '\n';
    *(q++) = *(p++); /* this is either space, tab or 0 */
  }
  {
    gchar *new_hdr;
    
    g_free(hdr->header);
    new_hdr = g_strdup(tmp_hdr);
    g_free(tmp_hdr);
    hdr->value = new_hdr + (hdr->value - hdr->header);
    hdr->header = new_hdr;
  }
}

header *create_header(header_id id, gchar *fmt, ...)
{
  gchar *p;
  header *hdr;
  va_list args;
  va_start(args, fmt);

  if((hdr = g_malloc(sizeof(header)))){

    hdr->id = id;
    hdr->header = g_strdup_vprintf(fmt, args);
    hdr->value = NULL;

    p = hdr->header;
    while(*p && *p != ':') p++;
    if(*p)
      hdr->value = p+1;
  }

  va_end(args);
  return hdr;
}

void destroy_header(header *hdr)
{
  if(hdr){
    if(hdr->header) g_free(hdr->header);
    g_free(hdr);
  }
}

header *copy_header(header *hdr)
{
  header *new_hdr = NULL;

  if(hdr){
    if((new_hdr = g_malloc(sizeof(header)))){
      new_hdr->id = hdr->id;
      new_hdr->header = g_strdup(hdr->header);
      new_hdr->value = new_hdr->header + (hdr->value - hdr->header);
    }
  }
  return new_hdr;
}

header *get_header(gchar *line)
{
  gchar *p = line;
  gchar buf[64], *q = buf;
  gint i;
  header *hdr;
  
  while(*p && (*p != ':') && (q < buf+63)) *(q++) = *(p++);
  *q = 0;
  
  if(*p != ':') return NULL;

  hdr = g_malloc(sizeof(header));

  hdr->value = NULL;
  p++;

  while(*p && (*p == ' ' || *p == '\t')) p++;
  hdr->value = p;

  for(i = 0; i < HEAD_NUM_IDS; i++){
    if(strcasecmp(header_names[i].header, buf) == 0)
      break;
  }
  hdr->id = (header_id)i;
  hdr->header = g_strdup(line);
  hdr->value = hdr->header + (hdr->value - line);

  DEBUG(4) debugf("header: %d = %s", hdr->id, hdr->header);

  return hdr;
}