masqmail

diff src/alias.c @ 0:08114f7dcc23

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 diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/alias.c	Fri Sep 26 17:05:23 2008 +0200
     1.3 @@ -0,0 +1,195 @@
     1.4 +/*  MasqMail
     1.5 +    Copyright (C) 2000-2001 Oliver Kurth
     1.6 +
     1.7 +    This program is free software; you can redistribute it and/or modify
     1.8 +    it under the terms of the GNU General Public License as published by
     1.9 +    the Free Software Foundation; either version 2 of the License, or
    1.10 +    (at your option) any later version.
    1.11 +
    1.12 +    This program is distributed in the hope that it will be useful,
    1.13 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.14 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.15 +    GNU General Public License for more details.
    1.16 +
    1.17 +    You should have received a copy of the GNU General Public License
    1.18 +    along with this program; if not, write to the Free Software
    1.19 +    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    1.20 +*/
    1.21 +
    1.22 +#include "masqmail.h"
    1.23 +#include <fnmatch.h>
    1.24 +
    1.25 +gboolean addr_is_local(address *addr)
    1.26 +{
    1.27 +  GList *dom_node;
    1.28 +  GList *addr_node;
    1.29 +  address *a;
    1.30 +
    1.31 +  foreach(conf.local_hosts, dom_node){
    1.32 +    if(addr->domain == NULL)
    1.33 +      return TRUE;
    1.34 +    if(fnmatch(dom_node->data, addr->domain, FNM_CASEFOLD) == 0){
    1.35 +      foreach(conf.not_local_addresses,addr_node){
    1.36 +	a = create_address_qualified(addr_node->data, TRUE, conf.host_name);
    1.37 +	if(addr_isequal(a,addr)){
    1.38 +	  destroy_address(a);
    1.39 +	  return FALSE;
    1.40 +	}
    1.41 +	destroy_address(a);
    1.42 +      }
    1.43 +      return TRUE;
    1.44 +    }
    1.45 +  }
    1.46 +  foreach(conf.local_addresses,addr_node){
    1.47 +    a = create_address_qualified(addr_node->data, TRUE, conf.host_name);
    1.48 +    if(addr_isequal(a,addr)){
    1.49 +      destroy_address(a);
    1.50 +      return TRUE;
    1.51 +    }
    1.52 +    destroy_address(a);
    1.53 +  }
    1.54 +  return FALSE;
    1.55 +}
    1.56 +
    1.57 +static
    1.58 +gboolean addr_isequal_alias(address *addr1, address *addr2)
    1.59 +{
    1.60 +  return
    1.61 +    (conf.alias_local_cmp(addr1->local_part, addr2->local_part) == 0) &&
    1.62 +    (strcasecmp(addr1->domain, addr2->domain) == 0);
    1.63 +}
    1.64 +
    1.65 +static
    1.66 +GList *parse_list(gchar *line)
    1.67 +{
    1.68 +  GList *list = NULL;
    1.69 +  gchar buf[256];
    1.70 +  gchar *p, *q;
    1.71 +
    1.72 +  p = line;
    1.73 +  while(*p != 0){
    1.74 +    q = buf;
    1.75 +    while(isspace(*p)) p++;
    1.76 +    if(*p != '\"'){
    1.77 +      while(*p && (*p != ',') && (q < buf+255))
    1.78 +	*(q++) = *(p++);
    1.79 +      *q = 0;
    1.80 +    }else{
    1.81 +      gboolean escape = FALSE;
    1.82 +      p++;
    1.83 +      while(*p && (*p != '\"' || escape) && (q < buf+255)){
    1.84 +	if((*p == '\\') && !escape)
    1.85 +	  escape = TRUE;
    1.86 +	else{
    1.87 +	  escape = FALSE;
    1.88 +	  *(q++) = *p;
    1.89 +	}
    1.90 +	p++;
    1.91 +      }
    1.92 +      *q = 0;
    1.93 +      while(*p && (*p != ',')) p++;
    1.94 +    }
    1.95 +    list = g_list_append(list, g_strdup(g_strchomp(buf)));
    1.96 +    if(*p) p++;
    1.97 +  }
    1.98 +  return list;
    1.99 +}
   1.100 +
   1.101 +GList *alias_expand(GList *alias_table, GList *rcpt_list, GList *non_rcpt_list)
   1.102 +{
   1.103 +  GList *done_list = NULL;
   1.104 +  GList *rcpt_node = g_list_copy(rcpt_list);
   1.105 +
   1.106 +  while(rcpt_node != NULL){
   1.107 +    address *addr = (address *)(rcpt_node->data);
   1.108 +    DEBUG(5) debugf("alias_expand begin: '%s@%s'\n", addr->local_part, addr->domain);
   1.109 +//    if(addr_is_local(addr) && (addr->local_part[0] != '|') &&
   1.110 +    if(addr_is_local(addr) && 
   1.111 +        !(addr->flags & ADDR_FLAG_NOEXPAND)){
   1.112 +      gchar *val;
   1.113 +      
   1.114 +      /* special handling for postmaster */
   1.115 +      if(strcasecmp(addr->local_part, "postmaster") == 0)
   1.116 +	val = (gchar *)table_find_func(alias_table, addr->local_part, strcasecmp);
   1.117 +      else
   1.118 +	val = (gchar *)table_find_func(alias_table, addr->local_part, conf.alias_local_cmp);
   1.119 +
   1.120 +      DEBUG(5) debugf("alias: '%s' is local\n", addr->local_part);
   1.121 +      if(val != NULL){
   1.122 +	GList *val_list = parse_list(val);
   1.123 +	GList *val_node;
   1.124 +	GList *alias_list = NULL;
   1.125 +
   1.126 +	DEBUG(5) debugf("alias: '%s' -> '%s'\n", addr->local_part, val);
   1.127 +	foreach(val_list, val_node){
   1.128 +	  gchar *val = (gchar *)(val_node->data);
   1.129 +	  address *alias_addr;
   1.130 +	  address *addr_parent = NULL;
   1.131 +
   1.132 +	  if(val[0] == '|'){
   1.133 +	    DEBUG(5) debugf("alias: %s is a pipe address\n", val);
   1.134 +	    alias_addr = create_address_pipe(val);
   1.135 +	    DEBUG(5) debugf("alias_pipe: %s is a pipe address\n", alias_addr->local_part);
   1.136 +	  }else if(val[0] == '\\'){
   1.137 +	    DEBUG(5) debugf("alias: shall not be expanded: '%s'\n", val);
   1.138 +	    alias_addr = create_address_qualified(&(val[1]), TRUE, conf.host_name);
   1.139 +	    alias_addr->flags |= ADDR_FLAG_NOEXPAND;
   1.140 +	    DEBUG(5) debugf("alias: not expanded: '%s'\n",alias_addr->local_part);
   1.141 +	  }else{
   1.142 +	    alias_addr = create_address_qualified(val, TRUE, conf.host_name);
   1.143 +
   1.144 +	    /* search in parents for loops: */
   1.145 +	    for(addr_parent = addr; addr_parent; addr_parent = addr_parent->parent){
   1.146 +	      if(addr_isequal_alias(alias_addr, addr_parent)){
   1.147 +		logwrite(LOG_ALERT, "detected alias loop, (ignoring): %s@%s -> %s@%s\n",
   1.148 +			 addr_parent->local_part, addr_parent->domain,
   1.149 +			 addr->local_part, addr->domain);
   1.150 +		break;
   1.151 +	      }
   1.152 +	    }
   1.153 +	  }
   1.154 +	  if(!addr_parent){
   1.155 +	    alias_list = g_list_append(alias_list, alias_addr);
   1.156 +	    alias_addr->parent = addr;
   1.157 +	  }
   1.158 +	  g_free(val);
   1.159 +	}
   1.160 +	g_list_free(val_list);
   1.161 +	addr->children = g_list_copy(alias_list);
   1.162 +	rcpt_node = g_list_concat(rcpt_node, alias_list);
   1.163 +      }else{
   1.164 +	DEBUG(5) debugf("alias: '%s' is completed\n", addr->local_part);
   1.165 +	done_list = g_list_append(done_list, addr);
   1.166 +      }
   1.167 +    }else{
   1.168 +      DEBUG(5) debugf("alias: '%s@%s' is not local\n", addr->local_part, addr->domain);
   1.169 +      done_list = g_list_append(done_list, addr);
   1.170 +    }
   1.171 +    rcpt_node = g_list_next(rcpt_node);
   1.172 +  }
   1.173 +
   1.174 +  /* delete addresses from done_list if they are in the non_rcpt_list */
   1.175 +  if(non_rcpt_list){
   1.176 +    GList *rcpt_node_next;
   1.177 +    for(rcpt_node = g_list_first(done_list);
   1.178 +	 rcpt_node;
   1.179 +	 rcpt_node = rcpt_node_next){
   1.180 +      address *addr = (address *)(rcpt_node->data);
   1.181 +      GList *non_node;
   1.182 +
   1.183 +      rcpt_node_next = g_list_next(rcpt_node);
   1.184 +
   1.185 +      foreach(non_rcpt_list, non_node){
   1.186 +	address *non_addr = (address *)(non_node->data);
   1.187 +	if(addr_isequal(addr, non_addr)){
   1.188 +	  done_list = g_list_remove_link(done_list, rcpt_node);
   1.189 +	  g_list_free_1(rcpt_node);
   1.190 +	  addr_mark_delivered(addr); /* this address is still in the children lists
   1.191 +				      of the original address */
   1.192 +	  break;
   1.193 +	}
   1.194 +      }
   1.195 +    }
   1.196 +  }
   1.197 +  return done_list;
   1.198 +}