[exim-cvs] cvs commit: exim/exim-src/OS Makefile-Base exim/…

Góra strony
Delete this message
Reply to this message
Autor: Tom Kistner
Data:  
Dla: exim-cvs
Temat: [exim-cvs] cvs commit: exim/exim-src/OS Makefile-Base exim/exim-src/exim_monitor em_globals.c exim/exim-src/scripts MakeLinks exim/exim-src/src EDITME acl.c bmi_spam.c bmi_spam.h config.h.defaults
tom 2004/12/16 15:11:48 GMT

  Modified files:
    exim-src/OS          Makefile-Base 
    exim-src/exim_monitor em_globals.c 
    exim-src/scripts     MakeLinks 
    exim-src/src         EDITME acl.c config.h.defaults deliver.c 
                         exim.c exim.h expand.c functions.h 
                         globals.c globals.h header.c local_scan.h 
                         macros.h readconf.c receive.c route.c 
                         smtp_in.c spool_in.c spool_out.c 
                         structs.h 
    exim-src/src/routers redirect.c redirect.h 
  Added files:
    exim-src/src         bmi_spam.c bmi_spam.h demime.c demime.h 
                         malware.c mime.c mime.h regex.c spam.c 
                         spam.h spf.c spf.h spool_mbox.c srs.c 
                         srs.h 
  Log:
  Merge from EXISCAN branch.


  Revision  Changes    Path
  1.2       +33 -2     exim/exim-src/OS/Makefile-Base
  1.2       +14 -0     exim/exim-src/exim_monitor/em_globals.c
  1.2       +21 -0     exim/exim-src/scripts/MakeLinks
  1.5       +44 -0     exim/exim-src/src/EDITME
  1.6       +342 -14   exim/exim-src/src/acl.c
  1.2       +472 -0    exim/exim-src/src/bmi_spam.c (new)
  1.2       +24 -0     exim/exim-src/src/bmi_spam.h (new)
  1.3       +10 -2     exim/exim-src/src/config.h.defaults
  1.4       +20 -0     exim/exim-src/src/deliver.c
  1.2       +1245 -0   exim/exim-src/src/demime.c (new)
  1.2       +136 -0    exim/exim-src/src/demime.h (new)
  1.11      +15 -0     exim/exim-src/src/exim.c
  1.4       +17 -1     exim/exim-src/src/exim.h
  1.8       +57 -0     exim/exim-src/src/expand.c
  1.7       +27 -0     exim/exim-src/src/functions.h
  1.9       +95 -0     exim/exim-src/src/globals.c
  1.8       +80 -0     exim/exim-src/src/globals.h
  1.2       +13 -0     exim/exim-src/src/header.c
  1.2       +4 -0      exim/exim-src/src/local_scan.h
  1.5       +13 -5     exim/exim-src/src/macros.h
  1.2       +1322 -0   exim/exim-src/src/malware.c (new)
  1.2       +730 -0    exim/exim-src/src/mime.c (new)
  1.2       +85 -0     exim/exim-src/src/mime.h (new)
  1.3       +15 -0     exim/exim-src/src/readconf.c
  1.6       +176 -0    exim/exim-src/src/receive.c
  1.2       +247 -0    exim/exim-src/src/regex.c (new)
  1.2       +50 -0     exim/exim-src/src/route.c
  1.3       +79 -0     exim/exim-src/src/routers/redirect.c
  1.2       +7 -0      exim/exim-src/src/routers/redirect.h
  1.6       +26 -0     exim/exim-src/src/smtp_in.c
  1.2       +340 -0    exim/exim-src/src/spam.c (new)
  1.2       +30 -0     exim/exim-src/src/spam.h (new)
  1.2       +131 -0    exim/exim-src/src/spf.c (new)
  1.2       +39 -0     exim/exim-src/src/spf.h (new)
  1.2       +18 -0     exim/exim-src/src/spool_in.c
  1.2       +174 -0    exim/exim-src/src/spool_mbox.c (new)
  1.2       +7 -0      exim/exim-src/src/spool_out.c
  1.2       +206 -0    exim/exim-src/src/srs.c (new)
  1.2       +31 -0     exim/exim-src/src/srs.h (new)
  1.2       +8 -0      exim/exim-src/src/structs.h


  Index: Makefile-Base
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/OS/Makefile-Base,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Makefile-Base    6 Oct 2004 15:07:39 -0000    1.1
  +++ Makefile-Base    16 Dec 2004 15:11:47 -0000    1.2
  @@ -1,4 +1,4 @@
  -# $Cambridge: exim/exim-src/OS/Makefile-Base,v 1.1 2004/10/06 15:07:39 ph10 Exp $
  +# $Cambridge: exim/exim-src/OS/Makefile-Base,v 1.2 2004/12/16 15:11:47 tom Exp $


   # This file is the basis of the main makefile for Exim and friends. The
   # makefile at the top level arranges to build the main makefile by calling
  @@ -284,6 +284,14 @@
       @echo ">>> convert4r4 script built"; echo ""



+# These are objects of optional features. They are always compiled, but
+# if the corresponding #defines are not set, they wind up empty and
+# are thrown away by the linker.
+
+OBJ_WITH_CONTENT_SCAN = malware.o mime.o regex.o spam.o spool_mbox.o
+OBJ_WITH_OLD_DEMIME = demime.o
+OBJ_EXPERIMENTAL = bmi_spam.o spf.o srs.o
+
# Targets for final binaries; the main one has a build number which is
# updated each time. We don't bother with that for the auxiliaries.

  @@ -295,7 +303,8 @@
           rda.o readconf.o receive.o retry.o rewrite.o rfc2047.o \
           route.o search.o sieve.o smtp_in.o smtp_out.o spool_in.o spool_out.o \
           store.o string.o tls.o tod.o transport.o tree.o verify.o \
  -        local_scan.o $(EXIM_PERL)
  +        local_scan.o $(EXIM_PERL) $(OBJ_WITH_CONTENT_SCAN) \
  +        $(OBJ_WITH_OLD_DEMIME) $(OBJ_EXPERIMENTAL) 


   exim:   pcre/libpcre.a lookups/lookups.a auths/auths.a \
           routers/routers.a transports/transports.a \
  @@ -311,7 +320,7 @@
         auths/auths.a \
         $(LIBRESOLV) $(LIBS) $(LIBS_EXIM) $(IPV6_LIBS) $(EXTRALIBS) \
         $(EXTRALIBS_EXIM) $(DBMLIB) $(LOOKUP_LIBS) $(AUTH_LIBS) \
  -      $(PERL_LIBS) $(TLS_LIBS)
  +      $(PERL_LIBS) $(TLS_LIBS) $(LDFLAGS)
       @if [ x"$(STRIP_COMMAND)" != x"" ]; then \
         echo $(STRIP_COMMAND) exim; \
         $(STRIP_COMMAND) exim; \
  @@ -545,6 +554,28 @@
   transport.o:     $(HDRS) transport.c
   tree.o:          $(HDRS) tree.c
   verify.o:        $(HDRS) verify.c
  +
  +
  +# Dependencies for WITH_CONTENT_SCAN modules
  +
  +malware.o:       $(HDRS) malware.c
  +mime.o:          $(HDRS) mime.c
  +regex.o:         $(HDRS) regex.c
  +spam.o:          $(HDRS) spam.c
  +spool_mbox.o:    $(HDRS) spool_mbox.c
  +
  +
  +# Dependencies for WITH_OLD_DEMIME modules
  +
  +demime.o:        $(HDRS) demime.c
  +
  +
  +# Dependencies for EXPERIMENTAL_* modules
  +
  +bmi_spam.o:      $(HDRS) bmi_spam.c
  +spf.o:           $(HDRS) spf.c
  +srs.o:           $(HDRS) srs.c
  +


# The module containing tables of available lookups, routers, auths, and
# transports must be rebuilt if any of them are. However, because the makefiles

  Index: em_globals.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/exim_monitor/em_globals.c,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- em_globals.c    7 Oct 2004 10:39:01 -0000    1.1
  +++ em_globals.c    16 Dec 2004 15:11:47 -0000    1.2
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/exim_monitor/em_globals.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/exim_monitor/em_globals.c,v 1.2 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *                Exim Monitor                    *
  @@ -44,6 +44,11 @@
   uschar *action_required;
   uschar *alternate_config = NULL;


  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +int     bmi_run                = 0;
  +uschar *bmi_verdicts           = NULL;
  +#endif
  +
   int     body_max = 20000;


   uschar *exim_path              = US BIN_DIRECTORY "/exim"
  @@ -132,6 +137,10 @@
   BOOL    deliver_manual_thaw    = FALSE;
   BOOL    dont_deliver           = FALSE;


  +#ifdef WITH_CONTENT_SCAN
  +BOOL   fake_reject             = FALSE;
  +#endif
  +
   header_line *header_last       = NULL;
   header_line *header_list       = NULL;


  @@ -142,6 +151,11 @@
   BOOL    local_error_message    = FALSE;
   uschar *local_scan_data        = NULL;
   BOOL    log_timezone           = FALSE;
  +
  +#ifdef WITH_CONTENT_SCAN
  +uschar *spam_score_int         = NULL;
  +#endif
  +
   int     message_age            = 0;
   uschar *message_id;
   uschar *message_id_external;


  Index: MakeLinks
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/scripts/MakeLinks,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- MakeLinks    6 Oct 2004 15:07:40 -0000    1.1
  +++ MakeLinks    16 Dec 2004 15:11:47 -0000    1.2
  @@ -1,5 +1,5 @@
   #!/bin/sh
  -# $Cambridge: exim/exim-src/scripts/MakeLinks,v 1.1 2004/10/06 15:07:40 ph10 Exp $
  +# $Cambridge: exim/exim-src/scripts/MakeLinks,v 1.2 2004/12/16 15:11:47 tom Exp $


   # Script to build links for all the exim source files from the system-
   # specific build directory. It should be run from within that directory.
  @@ -240,5 +240,26 @@
   ln -s ../src/tree.c            tree.c
   ln -s ../src/verify.c          verify.c
   ln -s ../src/version.c         version.c
  +
  +# WITH_CONTENT_SCAN
  +ln -s ../src/spam.c            spam.c
  +ln -s ../src/spam.h            spam.h
  +ln -s ../src/spool_mbox.c      spool_mbox.c
  +ln -s ../src/regex.c           regex.c
  +ln -s ../src/mime.c            mime.c
  +ln -s ../src/mime.h            mime.h
  +ln -s ../src/malware.c         malware.c
  +
  +# WITH_OLD_DEMIME
  +ln -s ../src/demime.c          demime.c
  +ln -s ../src/demime.h          demime.h
  +
  +# EXPERIMENTAL_*
  +ln -s ../src/bmi_spam.c        bmi_spam.c
  +ln -s ../src/bmi_spam.h        bmi_spam.h
  +ln -s ../src/spf.c             spf.c
  +ln -s ../src/spf.h             spf.h
  +ln -s ../src/srs.c             srs.c
  +ln -s ../src/srs.h             srs.h


# End of MakeLinks
















  Index: EDITME
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/EDITME,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- EDITME    5 Nov 2004 12:33:59 -0000    1.4
  +++ EDITME    16 Dec 2004 15:11:47 -0000    1.5
  @@ -1,4 +1,4 @@
  -# $Cambridge: exim/exim-src/src/EDITME,v 1.4 2004/11/05 12:33:59 ph10 Exp $
  +# $Cambridge: exim/exim-src/src/EDITME,v 1.5 2004/12/16 15:11:47 tom Exp $


   ##################################################
   #          The Exim mail transport agent         #
  @@ -313,6 +313,50 @@
   # local OS-specific make files.


EXIM_MONITOR=eximon.bin
+
+#------------------------------------------------------------------------------
+# Compiling Exim with content scanning support: If you want to compile Exim
+# with support for message body content scanning, set WITH_CONTENT_SCAN to
+# the value "yes". This will give you malware and spam scanning in the DATA ACL,
+# and the MIME ACL. Please read the documentation to learn more about these
+# features.
+
+#WITH_CONTENT_SCAN=yes
+
+# If you want to use the deprecated "demime" condition in the DATA ACL,
+# uncomment the line below. Doing so will also explicitly turn on the
+# WITH_CONTENT_SCAN option. If possible, use the MIME ACL instead of
+# the "demime" condition.
+
+#WITH_OLD_DEMIME=yes
+
+#------------------------------------------------------------------------------
+# Compiling Exim with experimental features. These are documented in
+# experimental-spec.txt. "Experimental" means that the way these features are
+# implemented may still change. Backward compatability is not guaranteed.
+
+# Uncomment the following lines to add SPF support. You need to have libspf2
+# installed on your system (www.libspf2.org). Depending on where it is installed
+# you may have to edit the CFLAGS and LDFLAGS lines.
+#EXPERIMENTAL_SPF=yes
+#CFLAGS += -I/usr/local/include
+#LDFLAGS += -lspf2
+
+# Uncommend the following lines to add SRS (Sender rewriting scheme) support.
+# You need to have libsrs_alt installed on your system (srs.mirtol.com).
+# Depending on where it is installed you may have to edit the CFLAGS and
+# LDFLAGS lines.
+#EXPERIMENTAL_SRS=yes
+#CFLAGS += -I/usr/local/include
+#LDFLAGS += -lsrs_alt
+
+# Uncommend the following lines to add Brightmail AntiSpam support. You need
+# to have the Brightmail client SDK installed. Please check the experimental
+# documentation for implementation details. You need to edit the CFLAGS and
+# LDFLAGS lines.
+#EXPERIMENTAL_BRIGHTMAIL=yes
+#CFLAGS += -I/opt/brightmail/bsdk-6.0/include
+#LDFLAGS += -lxml2 -lbmiclient_single -L/opt/brightmail/bsdk-6.0/lib




  Index: acl.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/acl.c,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- acl.c    4 Nov 2004 12:19:48 -0000    1.5
  +++ acl.c    16 Dec 2004 15:11:47 -0000    1.6
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/acl.c,v 1.5 2004/11/04 12:19:48 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/acl.c,v 1.6 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -34,19 +34,77 @@
   /* ACL condition and modifier codes - keep in step with the table that
   follows. */


  -enum { ACLC_ACL, ACLC_AUTHENTICATED, ACLC_CONDITION, ACLC_CONTROL, ACLC_DELAY,
  -  ACLC_DNSLISTS, ACLC_DOMAINS, ACLC_ENCRYPTED, ACLC_ENDPASS, ACLC_HOSTS,
  -  ACLC_LOCAL_PARTS, ACLC_LOG_MESSAGE, ACLC_LOGWRITE, ACLC_MESSAGE,
  -  ACLC_RECIPIENTS, ACLC_SENDER_DOMAINS, ACLC_SENDERS, ACLC_SET, ACLC_VERIFY };
  +enum { ACLC_ACL, ACLC_AUTHENTICATED,
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +       ACLC_BMI_OPTIN,
  +#endif
  +ACLC_CONDITION, ACLC_CONTROL,
  +#ifdef WITH_CONTENT_SCAN
  +       ACLC_DECODE,
  +#endif
  +       ACLC_DELAY,
  +#ifdef WITH_OLD_DEMIME
  +       ACLC_DEMIME,
  +#endif        
  +       ACLC_DNSLISTS, ACLC_DOMAINS, ACLC_ENCRYPTED, ACLC_ENDPASS,
  +       ACLC_HOSTS, ACLC_LOCAL_PARTS, ACLC_LOG_MESSAGE, ACLC_LOGWRITE,
  +#ifdef WITH_CONTENT_SCAN
  +       ACLC_MALWARE,
  +#endif
  +       ACLC_MESSAGE,
  +#ifdef WITH_CONTENT_SCAN
  +       ACLC_MIME_REGEX,
  +#endif
  +       ACLC_RECIPIENTS,
  +#ifdef WITH_CONTENT_SCAN
  +       ACLC_REGEX,
  +#endif
  +       ACLC_SENDER_DOMAINS, ACLC_SENDERS, ACLC_SET,
  +#ifdef WITH_CONTENT_SCAN
  +       ACLC_SPAM,       
  +#endif
  +#ifdef EXPERIMENTAL_SPF
  +       ACLC_SPF,
  +#endif
  +       ACLC_VERIFY };


/* ACL conditions/modifiers: "delay", "control", "endpass", "message",
"log_message", "logwrite", and "set" are modifiers that look like conditions
but always return TRUE. They are used for their side effects. */

  -static uschar *conditions[] = { US"acl", US"authenticated", US"condition",
  -  US"control", US"delay", US"dnslists", US"domains", US"encrypted",
  +static uschar *conditions[] = { US"acl", US"authenticated",
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +  US"bmi_optin",
  +#endif
  +  US"condition",
  +  US"control", 
  +#ifdef WITH_CONTENT_SCAN
  +  US"decode",
  +#endif
  +  US"delay",
  +#ifdef WITH_OLD_DEMIME
  +  US"demime",
  +#endif
  +  US"dnslists", US"domains", US"encrypted",
     US"endpass", US"hosts", US"local_parts", US"log_message", US"logwrite",
  -  US"message", US"recipients", US"sender_domains", US"senders", US"set",
  +#ifdef WITH_CONTENT_SCAN
  +  US"malware",
  +#endif
  +  US"message",
  +#ifdef WITH_CONTENT_SCAN
  +  US"mime_regex",
  +#endif
  +  US"recipients",
  +#ifdef WITH_CONTENT_SCAN
  +  US"regex",
  +#endif
  +  US"sender_domains", US"senders", US"set",
  +#ifdef WITH_CONTENT_SCAN
  +  US"spam",
  +#endif
  +#ifdef EXPERIMENTAL_SPF
  +  US"spf",
  +#endif
     US"verify" };


   /* ACL control names */
  @@ -62,9 +120,18 @@
   static uschar cond_expand_at_top[] = {
     TRUE,    /* acl */
     FALSE,   /* authenticated */
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +  TRUE,    /* bmi_optin */
  +#endif  
     TRUE,    /* condition */
     TRUE,    /* control */
  +#ifdef WITH_CONTENT_SCAN
  +  TRUE,    /* decode */
  +#endif
     TRUE,    /* delay */
  +#ifdef WITH_OLD_DEMIME
  +  TRUE,    /* demime */
  +#endif
     TRUE,    /* dnslists */
     FALSE,   /* domains */
     FALSE,   /* encrypted */
  @@ -73,11 +140,26 @@
     FALSE,   /* local_parts */
     TRUE,    /* log_message */
     TRUE,    /* logwrite */
  +#ifdef WITH_CONTENT_SCAN
  +  TRUE,    /* malware */
  +#endif
     TRUE,    /* message */
  +#ifdef WITH_CONTENT_SCAN
  +  TRUE,    /* mime_regex */
  +#endif
     FALSE,   /* recipients */
  +#ifdef WITH_CONTENT_SCAN
  +  TRUE,    /* regex */
  +#endif
     FALSE,   /* sender_domains */
     FALSE,   /* senders */
     TRUE,    /* set */
  +#ifdef WITH_CONTENT_SCAN
  +  TRUE,    /* spam */
  +#endif
  +#ifdef EXPERIMENTAL_SPF
  +  TRUE,    /* spf */
  +#endif
     TRUE     /* verify */
   };


  @@ -86,9 +168,18 @@
   static uschar cond_modifiers[] = {
     FALSE,   /* acl */
     FALSE,   /* authenticated */
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +  TRUE,    /* bmi_optin */
  +#endif  
     FALSE,   /* condition */
     TRUE,    /* control */
  +#ifdef WITH_CONTENT_SCAN
  +  FALSE,   /* decode */
  +#endif
     TRUE,    /* delay */
  +#ifdef WITH_OLD_DEMIME
  +  FALSE,   /* demime */
  +#endif
     FALSE,   /* dnslists */
     FALSE,   /* domains */
     FALSE,   /* encrypted */
  @@ -96,12 +187,27 @@
     FALSE,   /* hosts */
     FALSE,   /* local_parts */
     TRUE,    /* log_message */
  -  TRUE,    /* log_write */
  +  TRUE,    /* logwrite */
  +#ifdef WITH_CONTENT_SCAN
  +  FALSE,   /* malware */
  +#endif
     TRUE,    /* message */
  +#ifdef WITH_CONTENT_SCAN
  +  FALSE,   /* mime_regex */
  +#endif
     FALSE,   /* recipients */
  +#ifdef WITH_CONTENT_SCAN
  +  FALSE,   /* regex */
  +#endif
     FALSE,   /* sender_domains */
     FALSE,   /* senders */
     TRUE,    /* set */
  +#ifdef WITH_CONTENT_SCAN
  +  FALSE,   /* spam */
  +#endif
  +#ifdef EXPERIMENTAL_SPF
  +  FALSE,   /* spf */
  +#endif
     FALSE    /* verify */
   };


  @@ -112,13 +218,46 @@
     0,                                               /* acl */
     (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_CONNECT)|   /* authenticated */
       (1<<ACL_WHERE_HELO),
  +  
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +  (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_AUTH)|      /* bmi_optin */
  +    (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
  +    (1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_MIME)|
  +    (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|                                       
  +    (1<<ACL_WHERE_MAILAUTH)|
  +    (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
  +    (1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_PREDATA),
  +#endif
  +  
     0,                                               /* condition */
  -
  +  
     /* Certain types of control are always allowed, so we let it through
     always and check in the control processing itself */
  -
  +  
     0,                                               /* control */
  +  
  +#ifdef WITH_CONTENT_SCAN
  +  (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_AUTH)|      /* decode */
  +    (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
  +    (1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_PREDATA)|
  +    (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
  +    (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
  +    (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
  +    (1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_RCPT),
  +#endif
  +
     0,                                               /* delay */
  +  
  +#ifdef WITH_CONTENT_SCAN
  +  (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_AUTH)|      /* demime */
  +    (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
  +    (1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
  +    (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
  +    (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
  +    (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
  +    (1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_MIME),
  +#endif
  +  
     (1<<ACL_WHERE_NOTSMTP),                          /* dnslists */


     (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_AUTH)|      /* domains */
  @@ -144,8 +283,29 @@


     0,                                               /* log_message */
     0,                                               /* logwrite */
  +  
  +#ifdef WITH_CONTENT_SCAN
  +  (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_AUTH)|      /* malware */
  +    (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
  +    (1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
  +    (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
  +    (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
  +    (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
  +    (1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_MIME),
  +#endif
  +
     0,                                               /* message */


  +#ifdef WITH_CONTENT_SCAN
  +  (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_AUTH)|      /* mime_regex */
  +    (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
  +    (1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_PREDATA)|
  +    (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
  +    (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
  +    (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
  +    (1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_RCPT),
  +#endif
  +
     (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_AUTH)|      /* recipients */
       (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
       (1<<ACL_WHERE_DATA)|(1<<ACL_WHERE_PREDATA)|
  @@ -154,6 +314,16 @@
       (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
       (1<<ACL_WHERE_VRFY),


  +#ifdef WITH_CONTENT_SCAN
  +  (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_AUTH)|      /* regex */
  +    (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
  +    (1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
  +    (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
  +    (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
  +    (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
  +    (1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_MIME),
  +#endif
  +
     (1<<ACL_WHERE_AUTH)|(1<<ACL_WHERE_CONNECT)|      /* sender_domains */
       (1<<ACL_WHERE_HELO)|
       (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
  @@ -168,6 +338,24 @@


     0,                                               /* set */


  +#ifdef WITH_CONTENT_SCAN
  +  (1<<ACL_WHERE_NOTSMTP)|(1<<ACL_WHERE_AUTH)|      /* spam */
  +    (1<<ACL_WHERE_CONNECT)|(1<<ACL_WHERE_HELO)|
  +    (1<<ACL_WHERE_RCPT)|(1<<ACL_WHERE_PREDATA)|
  +    (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
  +    (1<<ACL_WHERE_MAILAUTH)|(1<<ACL_WHERE_QUIT)|
  +    (1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_STARTTLS)|
  +    (1<<ACL_WHERE_VRFY)|(1<<ACL_WHERE_MIME),
  +#endif
  +
  +#ifdef EXPERIMENTAL_SPF
  +  (1<<ACL_WHERE_AUTH)|(1<<ACL_WHERE_CONNECT)|      /* spf */
  +    (1<<ACL_WHERE_HELO)|
  +    (1<<ACL_WHERE_MAILAUTH)|
  +    (1<<ACL_WHERE_ETRN)|(1<<ACL_WHERE_EXPN)|
  +    (1<<ACL_WHERE_STARTTLS)|(1<<ACL_WHERE_VRFY),
  +#endif
  +
     /* Certain types of verify are always allowed, so we let it through
     always and check in the verify function itself */


@@ -177,15 +365,26 @@

/* Return values from decode_control() */

  -enum { CONTROL_ERROR, CONTROL_CASEFUL_LOCAL_PART, CONTROL_CASELOWER_LOCAL_PART,
  +enum { 
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +  CONTROL_BMI_RUN,
  +#endif  
  +  CONTROL_ERROR, CONTROL_CASEFUL_LOCAL_PART, CONTROL_CASELOWER_LOCAL_PART,
     CONTROL_ENFORCE_SYNC, CONTROL_NO_ENFORCE_SYNC, CONTROL_FREEZE,
  -  CONTROL_QUEUE_ONLY, CONTROL_SUBMISSION, CONTROL_NO_MULTILINE };
  +  CONTROL_QUEUE_ONLY, CONTROL_SUBMISSION,
  +#ifdef WITH_CONTENT_SCAN
  +  CONTROL_NO_MBOX_UNSPOOL, CONTROL_FAKEREJECT,
  +#endif
  +  CONTROL_NO_MULTILINE };


/* Bit map vector of which controls are not allowed at certain times. For
each control, there's a bitmap of dis-allowed times. For some, it is easier to
specify the negation of a small number of allowed times. */

   static unsigned int control_forbids[] = {
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +  0,                                               /* bmi_run */
  +#endif
     0,                                               /* error */
     ~(1<<ACL_WHERE_RCPT),                            /* caseful_local_part */
     ~(1<<ACL_WHERE_RCPT),                            /* caselower_local_part */
  @@ -202,7 +401,12 @@


     ~((1<<ACL_WHERE_MAIL)|(1<<ACL_WHERE_RCPT)|       /* submission */
       (1<<ACL_WHERE_PREDATA)),                       
  -     
  +
  +#ifdef WITH_CONTENT_SCAN
  +  (1<<ACL_WHERE_NOTSMTP),                          /* no_mbox_unspool */
  +  (1<<ACL_WHERE_NOTSMTP),                          /* fakereject */
  +#endif
  +
     (1<<ACL_WHERE_NOTSMTP)                           /* no_multiline */
   };


@@ -215,6 +419,9 @@
} control_def;

   static control_def controls_list[] = {
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +  { US"bmi_run",                CONTROL_BMI_RUN, FALSE},
  +#endif
     { US"caseful_local_part",     CONTROL_CASEFUL_LOCAL_PART, FALSE},
     { US"caselower_local_part",   CONTROL_CASELOWER_LOCAL_PART, FALSE},
     { US"enforce_sync",           CONTROL_ENFORCE_SYNC, FALSE},
  @@ -222,6 +429,10 @@
     { US"no_enforce_sync",        CONTROL_NO_ENFORCE_SYNC, FALSE},
     { US"no_multiline_responses", CONTROL_NO_MULTILINE, FALSE},
     { US"queue_only",             CONTROL_QUEUE_ONLY, FALSE},
  +#ifdef WITH_CONTENT_SCAN
  +  { US"no_mbox_unspool",        CONTROL_NO_MBOX_UNSPOOL, FALSE},
  +  { US"fakereject",             CONTROL_FAKEREJECT, TRUE},
  +#endif
     { US"submission",             CONTROL_SUBMISSION, TRUE}
     };


  @@ -547,6 +758,11 @@
           newtype = htype_add_rec;
           p += 16;
           }
  +      else if (strncmpic(p, US":at_start_rfc:", 14) == 0)
  +        {
  +        newtype = htype_add_rfc;
  +        p += 14;
  +        }        
         else if (strncmpic(p, US":at_start:", 10) == 0)
           {
           newtype = htype_add_top;
  @@ -1253,6 +1469,9 @@
   uschar *log_message = NULL;
   uschar *p;
   int rc = OK;
  +#ifdef WITH_CONTENT_SCAN
  +int sep = '/';
  +#endif


   for (; cb != NULL; cb = cb->next)
     {
  @@ -1360,6 +1579,17 @@
           TRUE, NULL);
       break;


  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +    case ACLC_BMI_OPTIN:
  +      {
  +      int old_pool = store_pool;
  +      store_pool = POOL_PERM;
  +      bmi_current_optin = string_copy(arg);
  +      store_pool = old_pool;
  +      }
  +    break;
  +#endif
  +
       case ACLC_CONDITION:
       if (Ustrspn(arg, "0123456789") == Ustrlen(arg))     /* Digits, or empty */
         rc = (Uatoi(arg) == 0)? FAIL : OK;
  @@ -1375,7 +1605,7 @@
       case ACLC_CONTROL:
       control_type = decode_control(arg, &p, where, log_msgptr);


  -    /* Check this control makes sense at this time */
  +    /* Check if this control makes sense at this time */


       if ((control_forbids[control_type] & (1 << where)) != 0)
         {
  @@ -1386,6 +1616,12 @@


       switch(control_type)
         {
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +      case CONTROL_BMI_RUN:
  +      bmi_run = 1;
  +      break;
  +#endif
  +      
         case CONTROL_ERROR:
         return ERROR;


  @@ -1405,10 +1641,34 @@
         smtp_enforce_sync = FALSE;
         break;


  +#ifdef WITH_CONTENT_SCAN
  +      case CONTROL_NO_MBOX_UNSPOOL:
  +      no_mbox_unspool = TRUE;
  +      break;
  +#endif
  +
         case CONTROL_NO_MULTILINE:
         no_multiline_responses = TRUE;
         break;


  +#ifdef WITH_CONTENT_SCAN
  +      case CONTROL_FAKEREJECT:
  +      fake_reject = TRUE;
  +      if (*p == '/')
  +        { 
  +        uschar *pp = p + 1;
  +        while (*pp != 0) pp++; 
  +        fake_reject_text = expand_string(string_copyn(p+1, pp-p));
  +        p = pp;
  +        }
  +       else
  +        {
  +        /* Explicitly reset to default string */
  +        fake_reject_text = US"Your message has been rejected but is being kept for evaluation.\nIf it was a legit message, it may still be delivered to the target recipient(s).";
  +        }
  +      break;
  +#endif
  +
         case CONTROL_FREEZE:
         deliver_freeze = TRUE;
         deliver_frozen_at = time(NULL);
  @@ -1446,6 +1706,12 @@
         }
       break;


  +#ifdef WITH_CONTENT_SCAN
  +    case ACLC_DECODE:
  +    rc = mime_decode(&arg);
  +    break;
  +#endif
  +
       case ACLC_DELAY:
         {
         int delay = readconf_readtime(arg, 0, FALSE);
  @@ -1469,6 +1735,12 @@
         }
       break;


  +#ifdef WITH_OLD_DEMIME
  +    case ACLC_DEMIME:
  +      rc = demime(&arg);
  +    break;
  +#endif
  +
       case ACLC_DNSLISTS:
       rc = verify_check_dnsbl(&arg);
       break;
  @@ -1548,12 +1820,42 @@
         log_write(0, logbits, "%s", string_printing(s));
         }
       break;
  +    
  +#ifdef WITH_CONTENT_SCAN
  +    case ACLC_MALWARE:
  +      {
  +      /* Seperate the regular expression and any optional parameters. */
  +      uschar *ss = string_nextinlist(&arg, &sep, big_buffer, big_buffer_size);
  +      /* Run the malware backend. */
  +      rc = malware(&ss);
  +      /* Modify return code based upon the existance of options. */
  +      while ((ss = string_nextinlist(&arg, &sep, big_buffer, big_buffer_size))
  +            != NULL) {
  +        if (strcmpic(ss, US"defer_ok") == 0 && rc == DEFER)
  +          {
  +          /* FAIL so that the message is passed to the next ACL */
  +          rc = FAIL;
  +          }
  +        }
  +      }
  +    break;
  +
  +    case ACLC_MIME_REGEX:
  +      rc = mime_regex(&arg);
  +    break;
  +#endif


       case ACLC_RECIPIENTS:
       rc = match_address_list(addr->address, TRUE, TRUE, &arg, NULL, -1, 0,
         &recipient_data);
       break;


  +#ifdef WITH_CONTENT_SCAN
  +   case ACLC_REGEX:
  +      rc = regex(&arg);
  +    break;
  +#endif
  +
       case ACLC_SENDER_DOMAINS:
         {
         uschar *sdomain;
  @@ -1579,6 +1881,32 @@
         store_pool = old_pool;
         }
       break;
  +
  +#ifdef WITH_CONTENT_SCAN
  +    case ACLC_SPAM:
  +      {
  +      /* Seperate the regular expression and any optional parameters. */
  +      uschar *ss = string_nextinlist(&arg, &sep, big_buffer, big_buffer_size);
  +      /* Run the spam backend. */
  +      rc = spam(&ss);
  +      /* Modify return code based upon the existance of options. */
  +      while ((ss = string_nextinlist(&arg, &sep, big_buffer, big_buffer_size))
  +            != NULL) {
  +        if (strcmpic(ss, US"defer_ok") == 0 && rc == DEFER)
  +          {
  +          /* FAIL so that the message is passed to the next ACL */
  +          rc = FAIL;
  +          }
  +        }
  +      }
  +    break;
  +#endif
  +
  +#ifdef EXPERIMENTAL_SPF
  +    case ACLC_SPF:
  +      rc = spf_process(&arg, sender_address);
  +    break;
  +#endif


       /* If the verb is WARN, discard any user message from verification, because
       such messages are SMTP responses, not header additions. The latter come


  Index: config.h.defaults
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/config.h.defaults,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- config.h.defaults    18 Oct 2004 09:16:57 -0000    1.2
  +++ config.h.defaults    16 Dec 2004 15:11:47 -0000    1.3
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/config.h.defaults,v 1.2 2004/10/18 09:16:57 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/config.h.defaults,v 1.3 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -53,7 +53,7 @@
   #define HAVE_CRYPT16
   #define HAVE_SA_LEN
   #define HEADERS_CHARSET           "ISO-8859-1"
  -#define HEADER_ADD_BUFFER_SIZE     8192
  +#define HEADER_ADD_BUFFER_SIZE    (8192 * 4)
   #define HEADER_MAXSIZE            (1024*1024)


   #define INPUT_DIRECTORY_MODE       0750
  @@ -107,7 +107,7 @@
   #define SPOOL_DIRECTORY
   #define SPOOL_DIRECTORY_MODE       0750
   #define SPOOL_MODE                 0640
  -#define STRING_SPRINTF_BUFFER_SIZE 8192
  +#define STRING_SPRINTF_BUFFER_SIZE (8192 * 4)


#define SUPPORT_A6
#define SUPPORT_CRYPTEQ
@@ -137,6 +137,14 @@
#define USE_READLINE
#define USE_TCP_WRAPPERS
#define USE_TDB
+
+#define WITH_CONTENT_SCAN
+#define WITH_OLD_DEMIME
+
+/* EXPERIMENTAL features */
+#define EXPERIMENTAL_SPF
+#define EXPERIMENTAL_SRS
+#define EXPERIMENTAL_BRIGHTMAIL

/* Things that are not routinely changed but are nevertheless configurable
just in case. */

  Index: deliver.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/deliver.c,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- deliver.c    24 Nov 2004 14:38:13 -0000    1.3
  +++ deliver.c    16 Dec 2004 15:11:47 -0000    1.4
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/deliver.c,v 1.3 2004/11/24 14:38:13 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/deliver.c,v 1.4 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -156,6 +156,13 @@
   deliver_domain = addr->domain;
   self_hostname = addr->self_hostname;


  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +bmi_deliver = 1;    /* deliver by default */
  +bmi_alt_location = NULL;
  +bmi_base64_verdict = NULL;
  +bmi_base64_tracker_verdict = NULL;
  +#endif
  +
   /* If there's only one address we can set everything. */


   if (addr->next == NULL)
  @@ -205,6 +212,19 @@
         deliver_localpart_suffix = addr->parent->suffix;
         }
       }
  +
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +    /* Set expansion variables related to Brightmail AntiSpam */
  +    bmi_base64_verdict = bmi_get_base64_verdict(deliver_localpart_orig, deliver_domain_orig);
  +    bmi_base64_tracker_verdict = bmi_get_base64_tracker_verdict(bmi_base64_verdict);
  +    /* get message delivery status (0 - don't deliver | 1 - deliver) */
  +    bmi_deliver = bmi_get_delivery_status(bmi_base64_verdict);
  +    /* if message is to be delivered, get eventual alternate location */
  +    if (bmi_deliver == 1) {
  +      bmi_alt_location = bmi_get_alt_location(bmi_base64_verdict);
  +    };
  +#endif
  +
     }


/* For multiple addresses, don't set local part, and leave the domain and

  Index: exim.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/exim.c,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- exim.c    25 Nov 2004 13:54:31 -0000    1.10
  +++ exim.c    16 Dec 2004 15:11:47 -0000    1.11
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/exim.c,v 1.10 2004/11/25 13:54:31 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/exim.c,v 1.11 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -838,6 +838,21 @@
     #else
     fprintf(f, " OpenSSL");
     #endif
  +#endif
  +#ifdef WITH_CONTENT_SCAN
  +  fprintf(f, " Content_Scanning");
  +#endif
  +#ifdef WITH_OLD_DEMIME
  +  fprintf(f, " Old_Demime");
  +#endif
  +#ifdef EXPERIMENTAL_SPF
  +  fprintf(f, " Experimental_SPF");
  +#endif
  +#ifdef EXPERIMENTAL_SRS
  +  fprintf(f, " Experimental_SRS");
  +#endif
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +  fprintf(f, " Experimental_Brightmail");
   #endif
   fprintf(f, "\n");



  Index: exim.h
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/exim.h,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- exim.h    24 Nov 2004 15:43:36 -0000    1.3
  +++ exim.h    16 Dec 2004 15:11:47 -0000    1.4
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/exim.h,v 1.3 2004/11/24 15:43:36 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/exim.h,v 1.4 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -381,16 +381,32 @@


/* Exim includes are in several files. Note that local_scan.h #includes
mytypes.h and store.h, so we don't need to mention them explicitly. */
+#include "config.h"
+
+/* Before including the rest of the Exim headers, lets clear up some content
+scanning dependencies. */
+#ifdef WITH_OLD_DEMIME
+#define WITH_CONTENT_SCAN
+#endif

#include "local_scan.h"
#include "macros.h"
-#include "config.h"
#include "dbstuff.h"
#include "structs.h"
#include "globals.h"
#include "functions.h"
#include "dbfunctions.h"
#include "osfunctions.h"
+
+#ifdef EXPERIMENTAL_BRIGHTMAIL
+#include "bmi_spam.h"
+#endif
+#ifdef EXPERIMENTAL_SPF
+#include "spf.h"
+#endif
+#ifdef EXPERIMENTAL_SRS
+#include "srs.h"
+#endif

/* The following stuff must follow the inclusion of config.h because it
requires various things that are set therein. */

  Index: expand.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/expand.c,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- expand.c    18 Nov 2004 11:17:33 -0000    1.7
  +++ expand.c    16 Dec 2004 15:11:47 -0000    1.8
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/expand.c,v 1.7 2004/11/18 11:17:33 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/expand.c,v 1.8 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -318,6 +318,12 @@
     { "authenticated_id",    vtype_stringptr,   &authenticated_id },
     { "authenticated_sender",vtype_stringptr,   &authenticated_sender },
     { "authentication_failed",vtype_int,        &authentication_failed },
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +  { "bmi_alt_location",    vtype_stringptr,   &bmi_alt_location },
  +  { "bmi_base64_tracker_verdict", vtype_stringptr, &bmi_base64_tracker_verdict },
  +  { "bmi_base64_verdict",  vtype_stringptr,   &bmi_base64_verdict },
  +  { "bmi_deliver",         vtype_int,         &bmi_deliver },
  +#endif
     { "body_linecount",      vtype_int,         &body_linecount },
     { "body_zerocount",      vtype_int,         &body_zerocount },
     { "bounce_recipient",    vtype_stringptr,   &bounce_recipient },
  @@ -326,6 +332,10 @@
     { "caller_uid",          vtype_uid,         &real_uid },
     { "compile_date",        vtype_stringptr,   &version_date },
     { "compile_number",      vtype_stringptr,   &version_cnumber },
  +#ifdef WITH_OLD_DEMIME
  +  { "demime_errorlevel",   vtype_int,         &demime_errorlevel },
  +  { "demime_reason",       vtype_stringptr,   &demime_reason },
  +#endif
     { "dnslist_domain",      vtype_stringptr,   &dnslist_domain },
     { "dnslist_text",        vtype_stringptr,   &dnslist_text },
     { "dnslist_value",       vtype_stringptr,   &dnslist_value },
  @@ -334,6 +344,9 @@
     { "exim_gid",            vtype_gid,         &exim_gid },
     { "exim_path",           vtype_stringptr,   &exim_path },
     { "exim_uid",            vtype_uid,         &exim_uid },
  +#ifdef WITH_OLD_DEMIME
  +  { "found_extension",     vtype_stringptr,   &found_extension },
  +#endif 
     { "home",                vtype_stringptr,   &deliver_home },
     { "host",                vtype_stringptr,   &deliver_host },
     { "host_address",        vtype_stringptr,   &deliver_host_address },
  @@ -357,6 +370,9 @@
     { "log_inodes",          vtype_pinodes,     (void *)FALSE },
     { "log_space",           vtype_pspace,      (void *)FALSE },  
     { "mailstore_basename",  vtype_stringptr,   &mailstore_basename },
  +#ifdef WITH_CONTENT_SCAN
  +  { "malware_name",        vtype_stringptr,   &malware_name },
  +#endif
     { "message_age",         vtype_int,         &message_age },
     { "message_body",        vtype_msgbody,     &message_body },
     { "message_body_end",    vtype_msgbody_end, &message_body_end },
  @@ -364,6 +380,24 @@
     { "message_headers",     vtype_msgheaders,  NULL },
     { "message_id",          vtype_stringptr,   &message_id },
     { "message_size",        vtype_int,         &message_size },
  +#ifdef WITH_CONTENT_SCAN
  +  { "mime_anomaly_level",  vtype_int,         &mime_anomaly_level },
  +  { "mime_anomaly_text",   vtype_stringptr,   &mime_anomaly_text },
  +  { "mime_boundary",       vtype_stringptr,   &mime_boundary },
  +  { "mime_charset",        vtype_stringptr,   &mime_charset },
  +  { "mime_content_description", vtype_stringptr, &mime_content_description },
  +  { "mime_content_disposition", vtype_stringptr, &mime_content_disposition },
  +  { "mime_content_id",     vtype_stringptr,   &mime_content_id },
  +  { "mime_content_size",   vtype_int,         &mime_content_size },
  +  { "mime_content_transfer_encoding",vtype_stringptr, &mime_content_transfer_encoding },
  +  { "mime_content_type",   vtype_stringptr,   &mime_content_type },
  +  { "mime_decoded_filename", vtype_stringptr, &mime_decoded_filename },
  +  { "mime_filename",       vtype_stringptr,   &mime_filename },
  +  { "mime_is_coverletter", vtype_int,         &mime_is_coverletter },
  +  { "mime_is_multipart",   vtype_int,         &mime_is_multipart },
  +  { "mime_is_rfc822",      vtype_int,         &mime_is_rfc822 },
  +  { "mime_part_count",     vtype_int,         &mime_part_count },
  +#endif
     { "n0",                  vtype_filter_int,  &filter_n[0] },
     { "n1",                  vtype_filter_int,  &filter_n[1] },
     { "n2",                  vtype_filter_int,  &filter_n[2] },
  @@ -394,6 +428,9 @@
     { "recipient_verify_failure",vtype_stringptr,&recipient_verify_failure }, 
     { "recipients",          vtype_recipients,  NULL },
     { "recipients_count",    vtype_int,         &recipients_count },
  +#ifdef WITH_CONTENT_SCAN
  +  { "regex_match_string",  vtype_stringptr,   &regex_match_string },
  +#endif
     { "reply_address",       vtype_reply,       NULL },
     { "return_path",         vtype_stringptr,   &return_path },
     { "return_size_limit",   vtype_int,         &bounce_return_size_limit },
  @@ -424,9 +461,29 @@
     { "sn7",                 vtype_filter_int,  &filter_sn[7] },
     { "sn8",                 vtype_filter_int,  &filter_sn[8] },
     { "sn9",                 vtype_filter_int,  &filter_sn[9] },
  +#ifdef WITH_CONTENT_SCAN
  +  { "spam_bar",            vtype_stringptr,   &spam_bar },
  +  { "spam_report",         vtype_stringptr,   &spam_report },
  +  { "spam_score",          vtype_stringptr,   &spam_score },
  +  { "spam_score_int",      vtype_stringptr,   &spam_score_int },
  +#endif
  +#ifdef EXPERIMENTAL_SPF
  +  { "spf_header_comment",  vtype_stringptr,   &spf_header_comment },
  +  { "spf_received",        vtype_stringptr,   &spf_received },
  +  { "spf_result",          vtype_stringptr,   &spf_result },
  +  { "spf_smtp_comment",    vtype_stringptr,   &spf_smtp_comment },
  +#endif
     { "spool_directory",     vtype_stringptr,   &spool_directory },
     { "spool_inodes",        vtype_pinodes,     (void *)TRUE },
     { "spool_space",         vtype_pspace,      (void *)TRUE },  
  +#ifdef EXPERIMENTAL_SRS
  +  { "srs_db_address",      vtype_stringptr,   &srs_db_address },
  +  { "srs_db_key",          vtype_stringptr,   &srs_db_key },
  +  { "srs_orig_recipient",  vtype_stringptr,   &srs_orig_recipient },
  +  { "srs_orig_sender",     vtype_stringptr,   &srs_orig_sender },
  +  { "srs_recipient",       vtype_stringptr,   &srs_recipient },
  +  { "srs_status",          vtype_stringptr,   &srs_status },
  +#endif
     { "thisaddress",         vtype_stringptr,   &filter_thisaddress },
     { "tls_certificate_verified", vtype_int,    &tls_certificate_verified },
     { "tls_cipher",          vtype_stringptr,   &tls_cipher },


  Index: functions.h
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/functions.h,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- functions.h    25 Nov 2004 13:54:31 -0000    1.6
  +++ functions.h    16 Dec 2004 15:11:47 -0000    1.7
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/functions.h,v 1.6 2004/11/25 13:54:31 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/functions.h,v 1.7 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -68,6 +68,9 @@
   extern void    deliver_set_expansions(address_item *);
   extern int     deliver_split_address(address_item *);
   extern void    deliver_succeeded(address_item *);
  +#ifdef WITH_OLD_DEMIME
  +extern int     demime(uschar **);
  +#endif
   extern BOOL    directory_make(uschar *, uschar *, int, BOOL);
   extern dns_address *dns_address_from_rr(dns_answer *, dns_record *);
   extern void    dns_build_reverse(uschar *, uschar *);
  @@ -126,6 +129,9 @@
   extern uschar *local_part_quote(uschar *lpart);
   extern void    log_close_all(void);


  +#ifdef WITH_CONTENT_SCAN
  +extern int     malware(uschar **);
  +#endif
   extern int     match_address_list(uschar *, BOOL, BOOL, uschar **,
                    unsigned int *, int, int, uschar **);
   extern int     match_check_list(uschar **, int, tree_node **, unsigned int **,
  @@ -139,6 +145,13 @@
   extern void    md5_mid(md5 *, const uschar *);
   extern void    md5_start(md5 *);
   extern void    millisleep(int);
  +#ifdef WITH_CONTENT_SCAN
  +struct mime_boundary_context;
  +extern int     mime_acl_check(FILE *f, struct mime_boundary_context *,
  +                              uschar **, uschar **);
  +extern int     mime_decode(uschar **);
  +extern int     mime_regex(uschar **);
  +#endif
   extern uschar *moan_check_errorcopy(uschar *);
   extern BOOL    moan_skipped_syntax_errors(uschar *, error_block *, uschar *,
                    BOOL, uschar *);
  @@ -163,6 +176,9 @@
   extern void    queue_run(uschar *, uschar *, BOOL);


   extern int     random_number(int);
  +#ifdef WITH_CONTENT_SCAN
  +extern int     recv_line(int, uschar *, int);
  +#endif
   extern int     rda_interpret(redirect_block *, int, uschar *, uschar *, ugid_block *,
                    address_item **, uschar **, error_block **, int *, uschar *);
   extern int     rda_is_filter(const uschar *);
  @@ -183,6 +199,9 @@
   extern BOOL    receive_msg(BOOL);
   extern int     receive_statvfs(BOOL, int *); 
   extern void    receive_swallow_smtp(void);
  +#ifdef WITH_CONTENT_SCAN
  +extern int     regex(uschar **);
  +#endif
   extern BOOL    regex_match_and_setup(const pcre *, uschar *, int, int);
   extern const pcre *regex_must_compile(uschar *, BOOL, BOOL);
   extern void    retry_add_item(address_item *, uschar *, int);
  @@ -243,6 +262,10 @@
   extern BOOL    smtp_start_session(void);
   extern int     smtp_ungetc(int);
   extern int     smtp_write_command(smtp_outblock *, BOOL, char *, ...);
  +#ifdef WITH_CONTENT_SCAN
  +extern int     spam(uschar **);
  +extern FILE   *spool_mbox(unsigned long long *);
  +#endif
   extern BOOL    spool_move_message(uschar *, uschar *, uschar *, uschar *);
   extern BOOL    spool_open_datafile(uschar *);
   extern int     spool_open_temp(uschar *);
  @@ -293,6 +316,10 @@
   extern int     tree_insertnode(tree_node **, tree_node *);
   extern tree_node *tree_search(tree_node *, uschar *);
   extern void    tree_write(tree_node *, FILE *);
  +
  +#ifdef WITH_CONTENT_SCAN
  +extern void    unspool_mbox(void);
  +#endif


   extern int     verify_address(address_item *, FILE *, int, int, int, int,
                    uschar *, uschar *, BOOL *);


  Index: globals.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/globals.c,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- globals.c    25 Nov 2004 13:54:31 -0000    1.8
  +++ globals.c    16 Dec 2004 15:11:47 -0000    1.9
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/globals.c,v 1.8 2004/11/25 13:54:31 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/globals.c,v 1.9 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -164,6 +164,9 @@
   uschar *acl_smtp_helo          = NULL;
   uschar *acl_smtp_mail          = NULL;
   uschar *acl_smtp_mailauth      = NULL;
  +#ifdef WITH_CONTENT_SCAN
  +uschar *acl_smtp_mime          = NULL;
  +#endif
   uschar *acl_smtp_predata       = NULL;
   uschar *acl_smtp_quit          = NULL;
   uschar *acl_smtp_rcpt          = NULL;
  @@ -181,6 +184,9 @@
   uschar *acl_wherenames[]       = { US"RCPT",
                                      US"MAIL",
                                      US"PREDATA",
  +#ifdef WITH_CONTENT_SCAN
  +                                   US"MIME",
  +#endif
                                      US"DATA",
                                      US"non-SMTP",
                                      US"AUTH",
  @@ -197,6 +203,9 @@
   int     acl_wherecodes[]       = { 550,     /* RCPT */
                                      550,     /* MAIL */
                                      550,     /* PREDATA */
  +#ifdef WITH_CONTENT_SCAN
  +                                   550,     /* MIME */
  +#endif                                   
                                      550,     /* DATA */
                                      0,       /* not SMTP; not relevant */
                                      503,     /* AUTH */
  @@ -309,6 +318,9 @@
   uschar *auth_defer_msg         = US"reason not recorded";
   uschar *auth_defer_user_msg    = US"";
   int     auto_thaw              = 0;
  +#ifdef WITH_CONTENT_SCAN
  +uschar *av_scanner             = US"sophie:/var/run/sophie";  /* AV scanner */
  +#endif


   BOOL    background_daemon      = TRUE;
   uschar *base62_chars=
  @@ -316,6 +328,15 @@
   uschar *bi_command             = NULL;
   uschar *big_buffer             = NULL;
   int     big_buffer_size        = BIG_BUFFER_SIZE;
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +uschar *bmi_alt_location       = NULL;
  +uschar *bmi_base64_tracker_verdict = NULL;
  +uschar *bmi_base64_verdict     = NULL;
  +uschar *bmi_config_file        = US"/opt/brightmail/etc/brightmail.cfg";
  +int     bmi_deliver            = 1;
  +int     bmi_run                = 0;
  +uschar *bmi_verdicts           = NULL;
  +#endif
   int     body_linecount         = 0;
   int     body_zerocount         = 0;
   uschar *bounce_message_file    = NULL;
  @@ -435,6 +456,11 @@
   BOOL    deliver_selectstring_regex = FALSE;
   uschar *deliver_selectstring_sender = NULL;
   BOOL    deliver_selectstring_sender_regex = FALSE;
  +#ifdef WITH_OLD_DEMIME
  +int     demime_errorlevel      = 0;
  +int     demime_ok              = 0;
  +uschar *demime_reason          = NULL;
  +#endif
   BOOL    disable_logging        = FALSE;


   uschar *dns_again_means_nonexist = NULL;
  @@ -473,6 +499,10 @@
   BOOL    extract_addresses_remove_arguments = TRUE;
   uschar *extra_local_interfaces = NULL;


  +#ifdef WITH_CONTENT_SCAN
  +BOOL    fake_reject            = FALSE;
  +uschar *fake_reject_text       = US"Your message has been rejected but is being kept for evaluation.\nIf it was a legit message, it may still be delivered to the target recipient(s).";
  +#endif
   int     filter_n[FILTER_VARIABLE_COUNT];
   BOOL    filter_running         = FALSE;
   int     filter_sn[FILTER_VARIABLE_COUNT];
  @@ -481,6 +511,9 @@
   uschar *filter_test_ufile      = NULL;
   uschar *filter_thisaddress     = NULL;
   int     finduser_retries       = 0;
  +#ifdef WITH_OLD_DEMIME
  +uschar *found_extension        = NULL;
  +#endif
   uid_t   fixed_never_users[]    = { FIXED_NEVER_USERS };
   uschar *freeze_tell            = NULL;
   uschar *fudged_queue_times     = US"";
  @@ -636,6 +669,9 @@


   macro_item  *macros            = NULL;
   uschar *mailstore_basename     = NULL;
  +#ifdef WITH_CONTENT_SCAN
  +uschar *malware_name           = NULL;  /* Virus Name */
  +#endif
   int     max_username_length    = 0;
   int     message_age            = 0;
   uschar *message_body           = NULL;
  @@ -656,9 +692,33 @@
   uschar *message_size_limit     = US"50M";
   uschar  message_subdir[2]      = { 0, 0 };
   uschar *message_reference      = NULL;
  +
  +/* MIME ACL expandables */
  +#ifdef WITH_CONTENT_SCAN
  +int     mime_anomaly_level     = NULL;
  +uschar *mime_anomaly_text      = NULL;
  +uschar *mime_boundary          = NULL;
  +uschar *mime_charset           = NULL;
  +uschar *mime_content_description = NULL;
  +uschar *mime_content_disposition = NULL;
  +uschar *mime_content_id        = NULL;
  +unsigned int mime_content_size = 0;
  +uschar *mime_content_transfer_encoding = NULL;
  +uschar *mime_content_type      = NULL;
  +uschar *mime_decoded_filename  = NULL;
  +uschar *mime_filename          = NULL;
  +int     mime_is_multipart      = 0;
  +int     mime_is_coverletter    = 0;
  +int     mime_is_rfc822         = 0;
  +int     mime_part_count        = -1;
  +#endif
  +
   BOOL    mua_wrapper            = FALSE;


   uid_t  *never_users            = NULL;
  +#ifdef WITH_CONTENT_SCAN
  +BOOL    no_mbox_unspool        = FALSE;
  +#endif
   BOOL    no_multiline_responses = FALSE;


   uid_t   original_euid;
  @@ -759,6 +819,9 @@
   const pcre *regex_PIPELINING   = NULL;
   const pcre *regex_SIZE         = NULL;
   const pcre *regex_ismsgid      = NULL;
  +#ifdef WITH_CONTENT_SCAN
  +uschar *regex_match_string     = NULL;
  +#endif
   int     remote_delivery_count  = 0;
   int     remote_max_parallel    = 2;
   uschar *remote_sort_domains    = NULL;
  @@ -783,6 +846,9 @@
       NULL,                      /* driver name */


       NULL,                      /* address_data */
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +    NULL,                      /* bmi_rule */
  +#endif    
       NULL,                      /* cannot_route_message */
       NULL,                      /* condition */
       NULL,                      /* current_directory */
  @@ -811,6 +877,11 @@
       NULL,                      /* transport_name */


       TRUE,                      /* address_test */
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +    FALSE,                     /* bmi_deliver_alternate */
  +    FALSE,                     /* bmi_deliver_default */
  +    FALSE,                     /* bmi_dont_deliver */
  +#endif
       TRUE,                      /* expn */
       FALSE,                     /* caseful_local_part */
       FALSE,                     /* check_local_user */
  @@ -939,9 +1010,33 @@
   int     smtp_rlr_threshold     = INT_MAX;
   BOOL    smtp_use_pipelining    = FALSE;
   BOOL    smtp_use_size          = FALSE;
  +
  +#ifdef WITH_CONTENT_SCAN
  +uschar *spamd_address          = US"127.0.0.1 783";
  +uschar *spam_bar               = NULL;
  +uschar *spam_report            = NULL;
  +uschar *spam_score             = NULL;
  +uschar *spam_score_int         = NULL;
  +#endif
  +#ifdef EXPERIMENTAL_SPF
  +uschar *spf_header_comment     = NULL;
  +uschar *spf_received           = NULL;
  +uschar *spf_result             = NULL;
  +uschar *spf_smtp_comment       = NULL;
  +#endif
  +
   BOOL    split_spool_directory  = FALSE;
   uschar *spool_directory        = US SPOOL_DIRECTORY
                              "\0<--------------Space to patch spool_directory->";
  +#ifdef EXPERIMENTAL_SRS
  +uschar *srs_config             = NULL;
  +uschar *srs_db_address         = NULL;
  +uschar *srs_db_key             = NULL;
  +uschar *srs_orig_recipient     = NULL;
  +uschar *srs_orig_sender        = NULL;
  +uschar *srs_recipient          = NULL;
  +uschar *srs_status             = NULL;
  +#endif      
   int     string_datestamp_offset= -1;
   BOOL    strip_excess_angle_brackets = FALSE;
   BOOL    strip_trailing_dot     = FALSE;


  Index: globals.h
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/globals.h,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- globals.h    25 Nov 2004 13:54:31 -0000    1.7
  +++ globals.h    16 Dec 2004 15:11:47 -0000    1.8
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/globals.h,v 1.7 2004/11/25 13:54:31 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/globals.h,v 1.8 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -106,6 +106,9 @@
   extern uschar *acl_smtp_helo;          /* ACL run for HELO/EHLO */
   extern uschar *acl_smtp_mail;          /* ACL run for MAIL */
   extern uschar *acl_smtp_mailauth;      /* ACL run for MAIL AUTH */
  +#ifdef WITH_CONTENT_SCAN
  +extern uschar *acl_smtp_mime;          /* ACL run after DATA, before acl_smtp_data, for each MIME part */
  +#endif
   extern uschar *acl_smtp_predata;       /* ACL run for DATA command */
   extern uschar *acl_smtp_quit;          /* ACL run for QUIT */
   extern uschar *acl_smtp_rcpt;          /* ACL run for RCPT */
  @@ -144,12 +147,24 @@
   extern uschar *auth_defer_msg;         /* Error message for log */
   extern uschar *auth_defer_user_msg;    /* Error message for user */
   extern int     auto_thaw;              /* Auto-thaw interval */
  +#ifdef WITH_CONTENT_SCAN
  +extern uschar *av_scanner;             /* AntiVirus scanner to use for the malware condition */
  +#endif


   extern BOOL    background_daemon;      /* Set FALSE to keep in foreground */
   extern uschar *base62_chars;           /* Table of base-62 characters */
   extern uschar *bi_command;             /* Command for -bi option */
   extern uschar *big_buffer;             /* Used for various temp things */
   extern int     big_buffer_size;        /* Current size (can expand) */
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +extern uschar *bmi_alt_location;       /* expansion variable that contains the alternate location for the rcpt (available during routing) */
  +extern uschar *bmi_base64_tracker_verdict; /* expansion variable with base-64 encoded OLD verdict string (available during routing) */
  +extern uschar *bmi_base64_verdict;     /* expansion variable with base-64 encoded verdict string (available during routing) */
  +extern uschar *bmi_config_file;        /* Brightmail config file */
  +extern int     bmi_deliver;            /* Flag that determines if the message should be delivered to the rcpt (available during routing) */
  +extern int     bmi_run;                /* Flag that determines if message should be run through Brightmail server */
  +extern uschar *bmi_verdicts;           /* BASE64-encoded verdicts with recipient lists */
  +#endif
   extern int     body_linecount;         /* Line count in body */
   extern int     body_zerocount;         /* Binary zero count in body */
   extern uschar *bounce_message_file;    /* Template file */
  @@ -235,6 +250,11 @@
   extern BOOL    deliver_selectstring_regex; /* String is regex */
   extern uschar *deliver_selectstring_sender; /* For selecting by sender */
   extern BOOL    deliver_selectstring_sender_regex; /* String is regex */
  +#ifdef WITH_OLD_DEMIME
  +extern int     demime_errorlevel;      /* Severity of MIME error */
  +extern int     demime_ok;              /* Nonzero if message has been demimed */
  +extern uschar *demime_reason;          /* Reason for broken MIME container */
  +#endif
   extern BOOL    disable_logging;        /* Disables log writing when TRUE */


   extern uschar *dns_again_means_nonexist; /* Domains that are badly set up */
  @@ -272,6 +292,10 @@
   extern BOOL    extract_addresses_remove_arguments; /* Controls -t behaviour */
   extern uschar *extra_local_interfaces; /* Local, non-listen interfaces */


  +#ifdef WITH_CONTENT_SCAN
  +extern BOOL    fake_reject;            /* TRUE if fake reject is to be given */
  +extern uschar *fake_reject_text;       /* Option for the fakereject control statement: can contain user defined message. Default is in globals.c. */
  +#endif
   extern int     filter_n[FILTER_VARIABLE_COUNT]; /* filter variables */
   extern BOOL    filter_running;         /* TRUE while running a filter */
   extern int     filter_sn[FILTER_VARIABLE_COUNT]; /* variables set by system filter */
  @@ -281,6 +305,9 @@
   extern uschar *filter_thisaddress;     /* For address looping */
   extern int     finduser_retries;       /* Retry count for getpwnam() */
   extern uid_t   fixed_never_users[];    /* Can't be overridden */
  +#ifdef WITH_OLD_DEMIME
  +extern uschar *found_extension;        /* demime acl condition: file extension found */
  +#endif
   extern uschar *freeze_tell;            /* Message on (some) freezings */
   extern uschar *fudged_queue_times;     /* For use in test harness */


@@ -360,6 +387,9 @@

   extern macro_item *macros;             /* Configuration macros */
   extern uschar *mailstore_basename;     /* For mailstore deliveries */
  +#ifdef WITH_CONTENT_SCAN
  +extern uschar *malware_name;           /* Name of virus or malware ("W32/Klez-H") */
  +#endif
   extern int     max_username_length;    /* For systems with broken getpwnam() */
   extern int     message_age;            /* In seconds */
   extern uschar *message_body;           /* Start of message body for filter */
  @@ -379,9 +409,33 @@
   extern uschar *message_size_limit;     /* As it says */
   extern uschar  message_subdir[];       /* Subdirectory for messages */
   extern uschar *message_reference;      /* Reference for error messages */
  +
  +/* MIME ACL expandables */
  +#ifdef WITH_CONTENT_SCAN
  +extern int     mime_anomaly_level;
  +extern uschar *mime_anomaly_text;
  +extern uschar *mime_boundary;
  +extern uschar *mime_charset;
  +extern uschar *mime_content_description;
  +extern uschar *mime_content_disposition;
  +extern uschar *mime_content_id;
  +extern unsigned int mime_content_size;
  +extern uschar *mime_content_transfer_encoding;
  +extern uschar *mime_content_type;
  +extern uschar *mime_decoded_filename;
  +extern uschar *mime_filename;
  +extern int     mime_is_multipart;
  +extern int     mime_is_coverletter;
  +extern int     mime_is_rfc822;
  +extern int     mime_part_count;
  +#endif
  +
   extern BOOL    mua_wrapper;            /* TRUE when Exim is wrapping an MUA */


   extern uid_t  *never_users;            /* List of uids never to be used */
  +#ifdef WITH_CONTENT_SCAN
  +extern BOOL    no_mbox_unspool;        /* don't unlink files in /scan directory */
  +#endif
   extern BOOL    no_multiline_responses; /* For broken clients */


   extern optionlist optionlist_auths[];      /* These option lists are made */
  @@ -467,6 +521,9 @@
   extern const pcre  *regex_PIPELINING;  /* For recognizing PIPELINING */
   extern const pcre  *regex_SIZE;        /* For recognizing SIZE settings */
   extern const pcre  *regex_ismsgid;     /* Compiled r.e. for message it */
  +#ifdef WITH_CONTENT_SCAN
  +extern uschar *regex_match_string;     /* regex that matched a line (regex ACL condition) */
  +#endif
   extern int     remote_delivery_count;  /* Number of remote addresses */
   extern int     remote_max_parallel;    /* Maximum parallel delivery */
   extern uschar *remote_sort_domains;    /* Remote domain sorting order */
  @@ -558,8 +615,31 @@
   extern int     smtp_rlr_threshold;     /* Threshold for RCPT rate limit */
   extern BOOL    smtp_use_pipelining;    /* Global for passed connections */
   extern BOOL    smtp_use_size;          /* Global for passed connections */
  +
  +#ifdef WITH_CONTENT_SCAN
  +extern uschar *spamd_address;          /* address for the spamassassin daemon */
  +extern uschar *spam_bar;               /* the spam "bar" (textual representation of spam_score) */
  +extern uschar *spam_report;            /* the spamd report (multiline) */
  +extern uschar *spam_score;             /* the spam score (float) */
  +extern uschar *spam_score_int;         /* spam_score * 10 (int) */
  +#endif
  +#ifdef EXPERIMENTAL_SPF
  +extern uschar *spf_header_comment;     /* spf header comment */
  +extern uschar *spf_received;           /* SPF-Received: header */
  +extern uschar *spf_result;             /* spf result in string form */
  +extern uschar *spf_smtp_comment;       /* spf comment to include in SMTP reply */
  +#endif
   extern BOOL    split_spool_directory;  /* TRUE to use multiple subdirs */
   extern uschar *spool_directory;        /* Name of spool directory */
  +#ifdef EXPERIMENTAL_SRS
  +extern uschar *srs_config;             /* SRS config secret:max age:hash length:use timestamp:use hash */
  +extern uschar *srs_db_address;         /* SRS db address */
  +extern uschar *srs_db_key;             /* SRS db key */
  +extern uschar *srs_orig_sender;        /* SRS original sender */
  +extern uschar *srs_orig_recipient;     /* SRS original recipient */
  +extern uschar *srs_recipient;          /* SRS recipient */
  +extern uschar *srs_status;             /* SRS staus */
  +#endif
   extern int     string_datestamp_offset;/* After insertion by string_format */
   extern BOOL    strip_excess_angle_brackets; /* Surrounding route-addrs */
   extern BOOL    strip_trailing_dot;     /* Remove dots at ends of domains */


  Index: header.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/header.c,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- header.c    7 Oct 2004 10:39:01 -0000    1.1
  +++ header.c    16 Dec 2004 15:11:47 -0000    1.2
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/header.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/header.c,v 1.2 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -40,6 +40,19 @@
   return *tt == ':';
   }


+/* This is a copy of the function above, only that it is possible to pass
+ only the beginning of a header name. It simply does a front-anchored
+ substring match. Arguments and Return codes are the same as for
+ header_testname() above. */
+
+BOOL
+header_testname_incomplete(header_line *h, uschar *name, int len, BOOL notdel)
+{
+uschar *tt;
+if (h->type == '*' && notdel) return FALSE;
+if (h->text == NULL || strncmpic(h->text, name, len) != 0) return FALSE;
+return TRUE;
+}


/*************************************************

  Index: local_scan.h
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/local_scan.h,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- local_scan.h    7 Oct 2004 10:39:01 -0000    1.1
  +++ local_scan.h    16 Dec 2004 15:11:47 -0000    1.2
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/local_scan.h,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/local_scan.h,v 1.2 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -109,6 +109,9 @@
     uschar *address;              /* the recipient address */
     int     pno;                  /* parent number for "one_time" alias, or -1 */
     uschar *errors_to;            /* the errors_to address or NULL */
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +  uschar *bmi_optin;
  +#endif
   } recipient_item;



  @@ -147,6 +150,7 @@
   extern void    header_add_at_position(BOOL, uschar *, BOOL, int, char *, ...);
   extern void    header_remove(int, uschar *);
   extern BOOL    header_testname(header_line *, uschar *, int, BOOL);
  +extern BOOL    header_testname_incomplete(header_line *, uschar *, int, BOOL);
   extern void    log_write(unsigned int, int, char *format, ...);
   extern int     lss_b64decode(uschar *, uschar **);
   extern uschar *lss_b64encode(uschar *, int);


  Index: macros.h
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/macros.h,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- macros.h    25 Nov 2004 13:54:31 -0000    1.4
  +++ macros.h    16 Dec 2004 15:11:47 -0000    1.5
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/macros.h,v 1.4 2004/11/25 13:54:31 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/macros.h,v 1.5 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -131,12 +131,12 @@
   into big_buffer_size and in some circumstances increased. It should be at least
   as long as the maximum path length. */


-#if defined PATH_MAX && PATH_MAX > 1024
+#if defined PATH_MAX && PATH_MAX > 16384
#define BIG_BUFFER_SIZE PATH_MAX
-#elif defined MAXPATHLEN && MAXPATHLEN > 1024
+#elif defined MAXPATHLEN && MAXPATHLEN > 16384
#define BIG_BUFFER_SIZE MAXPATHLEN
#else
-#define BIG_BUFFER_SIZE 1024
+#define BIG_BUFFER_SIZE 16384
#endif

   /* This limits the length of data returned by local_scan(). Because it is
  @@ -552,6 +552,7 @@
   #define htype_add_top       'a'
   #define htype_add_rec       'r'
   #define htype_add_bot       'z'
  +#define htype_add_rfc       'f'


/* Types of item in options lists. These are the bottom 8 bits of the "type"
field, which is an int. The opt_void value is used for entries in tables that
@@ -741,11 +742,18 @@
order without checking carefully! Furthermore, remember to keep these in step
with the tables of names and response codes in globals.c. */

  +/* FIXME: the #ifdef below does not work here. Why? */
  +
   enum { ACL_WHERE_RCPT,       /* Some controls are for RCPT only */
          ACL_WHERE_MAIL,       /* )                                           */
          ACL_WHERE_PREDATA,    /* ) There are several tests for "in message", */
  -       ACL_WHERE_DATA,       /* ) implemented by <= WHERE_NOTSMTP           */
  -       ACL_WHERE_NOTSMTP,    /* )                                           */
  +                             /* ) implemented by <= WHERE_NOTSMTP           */
  +                             /* )                                           */
  +#ifdef WITH_CONTENT_SCAN
  +       ACL_WHERE_MIME,       
  +#endif
  +       ACL_WHERE_DATA,       
  +       ACL_WHERE_NOTSMTP,    


          ACL_WHERE_AUTH,       /* These remaining ones are not currently    */
          ACL_WHERE_CONNECT,    /* required to be in a special order so they */


  Index: readconf.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/readconf.c,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- readconf.c    18 Oct 2004 09:16:57 -0000    1.2
  +++ readconf.c    16 Dec 2004 15:11:47 -0000    1.3
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/readconf.c,v 1.2 2004/10/18 09:16:57 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/readconf.c,v 1.3 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -143,6 +143,9 @@
     { "acl_smtp_helo",            opt_stringptr,   &acl_smtp_helo },
     { "acl_smtp_mail",            opt_stringptr,   &acl_smtp_mail },
     { "acl_smtp_mailauth",        opt_stringptr,   &acl_smtp_mailauth },
  +#ifdef WITH_CONTENT_SCAN
  +  { "acl_smtp_mime",            opt_stringptr,   &acl_smtp_mime },
  +#endif
     { "acl_smtp_predata",         opt_stringptr,   &acl_smtp_predata },
     { "acl_smtp_quit",            opt_stringptr,   &acl_smtp_quit },
     { "acl_smtp_rcpt",            opt_stringptr,   &acl_smtp_rcpt },
  @@ -156,7 +159,13 @@
     { "allow_utf8_domains",       opt_bool,        &allow_utf8_domains },
     { "auth_advertise_hosts",     opt_stringptr,   &auth_advertise_hosts },
     { "auto_thaw",                opt_time,        &auto_thaw },
  +#ifdef WITH_CONTENT_SCAN
  +  { "av_scanner",               opt_stringptr,   &av_scanner },
  +#endif
     { "bi_command",               opt_stringptr,   &bi_command },
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +  { "bmi_config_file",          opt_stringptr,   &bmi_config_file },
  +#endif
     { "bounce_message_file",      opt_stringptr,   &bounce_message_file },
     { "bounce_message_text",      opt_stringptr,   &bounce_message_text },
     { "bounce_return_body",       opt_bool,        &bounce_return_body },
  @@ -318,8 +327,14 @@
     { "smtp_receive_timeout",     opt_time,        &smtp_receive_timeout },
     { "smtp_reserve_hosts",       opt_stringptr,   &smtp_reserve_hosts },
     { "smtp_return_error_details",opt_bool,        &smtp_return_error_details },
  +#ifdef WITH_CONTENT_SCAN
  +  { "spamd_address",            opt_stringptr,   &spamd_address },
  +#endif
     { "split_spool_directory",    opt_bool,        &split_spool_directory },
     { "spool_directory",          opt_stringptr,   &spool_directory },
  +#ifdef EXPERIMENTAL_SRS
  +  { "srs_config",               opt_stringptr,   &srs_config },
  +#endif
     { "strip_excess_angle_brackets", opt_bool,     &strip_excess_angle_brackets },
     { "strip_trailing_dot",       opt_bool,        &strip_trailing_dot },
     { "syslog_duplication",       opt_bool,        &syslog_duplication },


  Index: receive.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/receive.c,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- receive.c    25 Nov 2004 13:54:31 -0000    1.5
  +++ receive.c    16 Dec 2004 15:11:47 -0000    1.6
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/receive.c,v 1.5 2004/11/25 13:54:31 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/receive.c,v 1.6 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -470,6 +470,11 @@


recipients_list[recipients_count].address = recipient;
recipients_list[recipients_count].pno = pno;
+#ifdef EXPERIMENTAL_BRIGHTMAIL
+recipients_list[recipients_count].bmi_optin = bmi_current_optin;
+/* reset optin string pointer for next recipient */
+bmi_current_optin = NULL;
+#endif
recipients_list[recipients_count++].errors_to = NULL;
}

  @@ -918,6 +923,21 @@
       DEBUG(D_receive|D_acl) debug_printf("  (after Received:)");
       break;


  +    case htype_add_rfc:
  +    /* add header before any header which is NOT Received: or Resent- */
  +    last_received = header_list;
  +    while ( (last_received->next != NULL) &&
  +            ( (header_testname(last_received->next, US"Received", 8, FALSE)) ||
  +              (header_testname_incomplete(last_received->next, US"Resent-", 7, FALSE)) ) )
  +              last_received = last_received->next;
  +    /* last_received now points to the last Received: or Resent-* header
  +       in an uninterrupted chain of those header types (seen from the beginning
  +       of all headers. Our current header must follow it. */
  +    h->next = last_received->next;
  +    last_received->next = h;
  +    DEBUG(D_receive|D_acl) debug_printf("  (before any non-Received: or Resent-*: header)");        
  +    break;
  +
       default:
       h->next = NULL;
       header_last->next = h;
  @@ -2716,6 +2736,130 @@


     if (smtp_input && !smtp_batched_input)
       {
  +
  +#ifdef WITH_CONTENT_SCAN
  +     /* MIME ACL hook */
  +    if (acl_smtp_mime != NULL && recipients_count > 0)
  +      {
  +      FILE *mbox_file;
  +      uschar rfc822_file_path[2048];
  +      unsigned long long mbox_size;
  +      header_line *my_headerlist;
  +      uschar *user_msg, *log_msg;
  +      int mime_part_count_buffer = -1;
  +      
  +      memset(CS rfc822_file_path,0,2048);
  +      
  +      /* check if it is a MIME message */
  +      my_headerlist = header_list;
  +      while (my_headerlist != NULL) {
  +        /* skip deleted headers */
  +        if (my_headerlist->type == '*') {
  +          my_headerlist = my_headerlist->next;
  +          continue;
  +        };
  +        if (strncmpic(my_headerlist->text, US"Content-Type:", 13) == 0) {
  +          DEBUG(D_receive) debug_printf("Found Content-Type: header - executing acl_smtp_mime.\n");
  +          goto DO_MIME_ACL;
  +        };
  +        my_headerlist = my_headerlist->next;
  +      };
  +      
  +      DEBUG(D_receive) debug_printf("No Content-Type: header - presumably not a MIME message.\n");
  +      goto NO_MIME_ACL;
  +      
  +      DO_MIME_ACL:
  +      /* make sure the eml mbox file is spooled up */
  +      mbox_file = spool_mbox(&mbox_size);
  +      if (mbox_file == NULL) {
  +        /* error while spooling */
  +        log_write(0, LOG_MAIN|LOG_PANIC,
  +               "acl_smtp_mime: error while creating mbox spool file, message temporarily rejected.");
  +        Uunlink(spool_name);
  +        unspool_mbox(); 
  +        smtp_respond(451, TRUE, US"temporary local problem");
  +        message_id[0] = 0;            /* Indicate no message accepted */
  +        smtp_reply = US"";            /* Indicate reply already sent */
  +        goto TIDYUP;                  /* Skip to end of function */
  +      };
  +      
  +      mime_is_rfc822 = 0;
  +
  +      MIME_ACL_CHECK:
  +      mime_part_count = -1;
  +      rc = mime_acl_check(mbox_file, NULL, &user_msg, &log_msg);
  +      fclose(mbox_file);
  +      
  +      if (Ustrlen(rfc822_file_path) > 0) {
  +        mime_part_count = mime_part_count_buffer;
  +        
  +        if (unlink(CS rfc822_file_path) == -1) {
  +          log_write(0, LOG_PANIC,
  +               "acl_smtp_mime: can't unlink RFC822 spool file, skipping.");
  +            goto END_MIME_ACL;
  +        };
  +      };
  +      
  +      /* check if we must check any message/rfc822 attachments */
  +      if (rc == OK) {
  +        uschar temp_path[1024];
  +        int n;
  +        struct dirent *entry;
  +        DIR *tempdir;
  + 
  +        snprintf(CS temp_path, 1024, "%s/scan/%s", spool_directory, message_id);
  +
  +       tempdir = opendir(CS temp_path);
  +       n = 0;
  +       do {
  +         entry = readdir(tempdir);
  +         if (entry == NULL) break;
  +          if (strncmpic(US entry->d_name,US"__rfc822_",9) == 0) {
  +            snprintf(CS rfc822_file_path, 2048,"%s/scan/%s/%s", spool_directory, message_id, entry->d_name);
  +           debug_printf("RFC822 attachment detected: running MIME ACL for '%s'\n", rfc822_file_path);
  +           break;
  +          }; 
  +       } while (1);
  +       closedir(tempdir);
  +        
  +        if (entry != NULL) {
  +          mbox_file = Ufopen(rfc822_file_path,"r");
  +          if (mbox_file == NULL) {
  +            log_write(0, LOG_PANIC,
  +               "acl_smtp_mime: can't open RFC822 spool file, skipping.");
  +            unlink(CS rfc822_file_path);
  +            goto END_MIME_ACL;
  +          };
  +          /* set RFC822 expansion variable */
  +          mime_is_rfc822 = 1;
  +          mime_part_count_buffer = mime_part_count;
  +          goto MIME_ACL_CHECK;
  +        };
  +      };
  +      
  +      END_MIME_ACL:
  +      add_acl_headers(US"MIME");
  +      if (rc == DISCARD)      
  +        {
  +        recipients_count = 0;
  +        blackholed_by = US"MIME ACL";
  +        }
  +      else if (rc != OK)
  +        {
  +        Uunlink(spool_name);
  +        unspool_mbox();
  +        if (smtp_handle_acl_fail(ACL_WHERE_MIME, rc, user_msg, log_msg) != 0)
  +          smtp_yield = FALSE;    /* No more messsages after dropped connection */
  +        smtp_reply = US"";       /* Indicate reply already sent */
  +        message_id[0] = 0;       /* Indicate no message accepted */
  +        goto TIDYUP;             /* Skip to end of function */
  +        }; 
  +      }
  + 
  +    NO_MIME_ACL:      
  +#endif /* WITH_CONTENT_SCAN */
  +
  +
       if (acl_smtp_data != NULL && recipients_count > 0)
         {
         uschar *user_msg, *log_msg;
  @@ -2729,6 +2873,9 @@
         else if (rc != OK)
           {
           Uunlink(spool_name);
  +#ifdef WITH_CONTENT_SCAN
  +        unspool_mbox();
  +#endif
           if (smtp_handle_acl_fail(ACL_WHERE_DATA, rc, user_msg, log_msg) != 0)
             smtp_yield = FALSE;    /* No more messsages after dropped connection */
           smtp_reply = US"";       /* Indicate reply already sent */
  @@ -2779,6 +2926,10 @@
     enable_dollar_recipients = FALSE;
     }


+#ifdef WITH_CONTENT_SCAN
+unspool_mbox();
+#endif
+
/* The final check on the message is to run the scan_local() function. The
version supplied with Exim always accepts, but this is a hook for sysadmins to
supply their own checking code. The local_scan() function is run even when all
@@ -2949,6 +3100,14 @@

deliver_firsttime = TRUE;

  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +if (bmi_run == 1) {
  +  /* rewind data file */
  +  lseek(data_fd, (long int)SPOOL_DATA_START_OFFSET, SEEK_SET);
  +  bmi_verdicts = bmi_process_message(header_list, data_fd);
  +};
  +#endif
  +
   /* Update the timstamp in our Received: header to account for any time taken by
   an ACL or by local_scan(). The new time is the time that all reception
   processing is complete. */
  @@ -3235,12 +3394,29 @@
       {
       if (smtp_reply == NULL)
         {
  +#ifndef WITH_CONTENT_SCAN
         smtp_printf("250 OK id=%s\r\n", message_id);
  +#else      
  +        if (fake_reject)
  +          smtp_respond(550,TRUE,fake_reject_text);
  +        else  
  +          smtp_printf("250 OK id=%s\r\n", message_id);      
  +#endif     
         if (host_checking)
           fprintf(stdout,
             "\n**** SMTP testing: that is not a real message id!\n\n");
         }
  +#ifndef WITH_CONTENT_SCAN
       else if (smtp_reply[0] != 0) smtp_printf("%.1024s\r\n", smtp_reply);
  +#else
  +    else if (smtp_reply[0] != 0)
  +      {
  +        if (fake_reject && (smtp_reply[0] == '2'))
  +          smtp_respond(550,TRUE,fake_reject_text);
  +        else 
  +          smtp_printf("%.1024s\r\n", smtp_reply);
  +      };
  +#endif
       }


     /* For batched SMTP, generate an error message on failure, and do


  Index: route.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/route.c,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- route.c    7 Oct 2004 10:39:01 -0000    1.1
  +++ route.c    16 Dec 2004 15:11:47 -0000    1.2
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/route.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/route.c,v 1.2 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -34,6 +34,16 @@
                    (void *)(offsetof(router_instance, address_data)) },
     { "address_test",       opt_bool|opt_public,
                    (void *)(offsetof(router_instance, address_test)) },
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +  { "bmi_deliver_alternate",   opt_bool | opt_public,
  +                 (void *)(offsetof(router_instance, bmi_deliver_alternate)) },
  +  { "bmi_deliver_default",   opt_bool | opt_public,
  +                 (void *)(offsetof(router_instance, bmi_deliver_default)) },
  +  { "bmi_dont_deliver",   opt_bool | opt_public,
  +                 (void *)(offsetof(router_instance, bmi_dont_deliver)) },
  +  { "bmi_rule",           opt_stringptr|opt_public,
  +                 (void *)(offsetof(router_instance, bmi_rule)) },
  +#endif
     { "cannot_route_message", opt_stringptr | opt_public,
                    (void *)(offsetof(router_instance, cannot_route_message)) },
     { "caseful_local_part", opt_bool | opt_public,
  @@ -981,6 +991,46 @@
       return SKIP;
       }
     }
  +
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +/* check if a specific Brightmail AntiSpam rule fired on the message */
  +if (r->bmi_rule != NULL) {
  +  DEBUG(D_route) debug_printf("checking bmi_rule\n");
  +  if (bmi_check_rule(bmi_base64_verdict, r->bmi_rule) == 0) {
  +    /* none of the rules fired */
  +    DEBUG(D_route)
  +      debug_printf("%s router skipped: none of bmi_rule rules fired\n", r->name);
  +    return SKIP;
  +  };
  +};
  +
  +/* check if message should not be delivered */
  +if (r->bmi_dont_deliver) {
  +  if (bmi_deliver == 1) {
  +    DEBUG(D_route)
  +      debug_printf("%s router skipped: bmi_dont_deliver is FALSE\n", r->name);
  +    return SKIP;
  +  };
  +};
  +
  +/* check if message should go to an alternate location */
  +if (r->bmi_deliver_alternate) {
  +  if ((bmi_deliver == 0) || (bmi_alt_location == NULL)) {
  +    DEBUG(D_route)
  +      debug_printf("%s router skipped: bmi_deliver_alternate is FALSE\n", r->name);
  +    return SKIP;
  +  };
  +};
  +
  +/* check if message should go to default location */
  +if (r->bmi_deliver_default) {
  +  if ((bmi_deliver == 0) || (bmi_alt_location != NULL)) {
  +    DEBUG(D_route)
  +      debug_printf("%s router skipped: bmi_deliver_default is FALSE\n", r->name);
  +    return SKIP;
  +  };
  +};
  +#endif


/* All the checks passed. */


  Index: smtp_in.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/smtp_in.c,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- smtp_in.c    10 Nov 2004 15:21:16 -0000    1.5
  +++ smtp_in.c    16 Dec 2004 15:11:47 -0000    1.6
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/smtp_in.c,v 1.5 2004/11/10 15:21:16 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/smtp_in.c,v 1.6 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -805,6 +805,10 @@
   acl_warn_headers = NULL;
   queue_only_policy = FALSE;
   deliver_freeze = FALSE;                              /* Can be set by ACL */
  +#ifdef WITH_CONTENT_SCAN
  +fake_reject = FALSE;                                 /* Can be set by ACL */
  +no_mbox_unspool = FALSE;                             /* Can be set by ACL */
  +#endif
   submission_mode = FALSE;                             /* Can be set by ACL */
   active_local_from_check = local_from_check;          /* Can be set by ACL */
   active_local_sender_retain = local_sender_retain;    /* Can be set by ACL */
  @@ -815,6 +819,16 @@
   memset(sender_address_cache, 0, sizeof(sender_address_cache));
   memset(sender_domain_cache, 0, sizeof(sender_domain_cache));
   authenticated_sender = NULL;
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +bmi_run = 0;
  +bmi_verdicts = NULL;
  +#endif
  +#ifdef EXPERIMENTAL_SPF
  +spf_header_comment = NULL;
  +spf_received = NULL;
  +spf_result = NULL;  
  +spf_smtp_comment = NULL;
  +#endif
   body_linecount = body_zerocount = 0;


   for (i = 0; i < ACL_M_MAX; i++) acl_var[ACL_C_MAX + i] = NULL;
  @@ -1774,6 +1788,9 @@
   uschar *lognl;
   uschar *sender_info = US"";
   uschar *what = (where == ACL_WHERE_PREDATA)? US"DATA" :
  +#ifdef WITH_CONTENT_SCAN
  +               (where == ACL_WHERE_MIME)? US"during MIME ACL checks" :
  +#endif  
                  (where == ACL_WHERE_DATA)? US"after DATA" :
     string_sprintf("%s %s", acl_wherenames[where], smtp_data);


@@ -1785,7 +1802,11 @@
this is what should be logged, so I've changed to logging the unrewritten
address to retain backward compatibility. */

  +#ifndef WITH_CONTENT_SCAN
   if (where == ACL_WHERE_RCPT || where == ACL_WHERE_DATA)
  +#else
  +if (where == ACL_WHERE_RCPT || where == ACL_WHERE_DATA || where == ACL_WHERE_MIME)
  +#endif
     {
     sender_info = string_sprintf("F=<%s> ", (sender_address_unrewritten != NULL)?
       sender_address_unrewritten : sender_address);
  @@ -2339,6 +2360,11 @@
             }
           }
         }
  +
  +#ifdef EXPERIMENTAL_SPF
  +    /* set up SPF context */
  +    spf_init(sender_helo_name, sender_host_address);
  +#endif


       /* Apply an ACL check if one is defined */



  Index: spool_in.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/spool_in.c,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- spool_in.c    7 Oct 2004 10:39:01 -0000    1.1
  +++ spool_in.c    16 Dec 2004 15:11:47 -0000    1.2
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/spool_in.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/spool_in.c,v 1.2 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -271,12 +271,22 @@
   sender_set_untrusted = FALSE;
   tree_nonrecipients = NULL;


+#ifdef EXPERIMENTAL_BRIGHTMAIL
+bmi_run = 0;
+bmi_verdicts = NULL;
+#endif
+
#ifdef SUPPORT_TLS
tls_certificate_verified = FALSE;
tls_cipher = NULL;
tls_peerdn = NULL;
#endif

  +#ifdef WITH_CONTENT_SCAN
  +fake_reject = FALSE;
  +spam_score_int = NULL;
  +#endif
  +
   /* Generate the full name and open the file. If message_subdir is already
   set, just look in the given directory. Otherwise, look in both the split
   and unsplit directories, as for the data file above. */
  @@ -369,6 +379,14 @@
       local_error_message = TRUE;
     else if (Ustrncmp(big_buffer, "-local_scan ", 12) == 0)
       local_scan_data = string_copy(big_buffer + 12);
  +#ifdef WITH_CONTENT_SCAN    
  +  else if (Ustrncmp(big_buffer, "-spam_score_int ", 16) == 0)
  +    spam_score_int = string_copy(big_buffer + 16);  
  +#endif
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +  else if (Ustrncmp(big_buffer, "-bmi_verdicts ", 14) == 0)
  +    bmi_verdicts = string_copy(big_buffer + 14);
  +#endif
     else if (Ustrcmp(big_buffer, "-host_lookup_failed") == 0)
       host_lookup_failed = TRUE;
     else if (Ustrncmp(big_buffer, "-body_linecount", 15) == 0)


  Index: spool_out.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/spool_out.c,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- spool_out.c    7 Oct 2004 10:39:01 -0000    1.1
  +++ spool_out.c    16 Dec 2004 15:11:47 -0000    1.2
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/spool_out.c,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/spool_out.c,v 1.2 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -216,8 +216,15 @@
   if (sender_local) fprintf(f, "-local\n");
   if (local_error_message) fprintf(f, "-localerror\n");
   if (local_scan_data != NULL) fprintf(f, "-local_scan %s\n", local_scan_data);
  +#ifdef WITH_CONTENT_SCAN
  +if (spam_score_int != NULL) fprintf(f,"-spam_score_int %s\n", spam_score_int);
  +#endif
   if (deliver_manual_thaw) fprintf(f, "-manual_thaw\n");
   if (sender_set_untrusted) fprintf(f, "-sender_set_untrusted\n");
  +
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +if (bmi_verdicts != NULL) fprintf(f, "-bmi_verdicts %s\n", bmi_verdicts);
  +#endif


#ifdef SUPPORT_TLS
if (tls_certificate_verified) fprintf(f, "-tls_certificate_verified\n");

  Index: structs.h
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/structs.h,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- structs.h    7 Oct 2004 10:39:01 -0000    1.1
  +++ structs.h    16 Dec 2004 15:11:47 -0000    1.2
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/structs.h,v 1.1 2004/10/07 10:39:01 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/structs.h,v 1.2 2004/12/16 15:11:47 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -221,6 +221,9 @@
     uschar *driver_name;            /* Must be first */


     uschar *address_data;           /* Arbitrary data */
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +  uschar *bmi_rule;               /* Brightmail AntiSpam rule checking */
  +#endif  
     uschar *cannot_route_message;   /* Used when routing fails */
     uschar *condition;              /* General condition */
     uschar *current_directory;      /* For use during delivery */
  @@ -249,6 +252,11 @@
     uschar *transport_name;         /* Transport name */


     BOOL    address_test;           /* Use this router when testing addresses */
  +#ifdef EXPERIMENTAL_BRIGHTMAIL
  +  BOOL    bmi_deliver_alternate;  /* TRUE => BMI said that message should be delivered to alternate location */
  +  BOOL    bmi_deliver_default;    /* TRUE => BMI said that message should be delivered to default location */
  +  BOOL    bmi_dont_deliver;       /* TRUE => BMI said that message should not be delivered at all */
  +#endif
     BOOL    expn;                   /* Use this router when processing EXPN */
     BOOL    caseful_local_part;     /* TRUE => don't lowercase */
     BOOL    check_local_user;       /* TRUE => check local user */


  Index: redirect.c
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/routers/redirect.c,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- redirect.c    4 Nov 2004 10:42:11 -0000    1.2
  +++ redirect.c    16 Dec 2004 15:11:48 -0000    1.3
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/routers/redirect.c,v 1.2 2004/11/04 10:42:11 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/routers/redirect.c,v 1.3 2004/12/16 15:11:48 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -101,6 +101,16 @@
         (void *)offsetof(redirect_router_options_block, sieve_vacation_directory) },
     { "skip_syntax_errors", opt_bool,
         (void *)offsetof(redirect_router_options_block, skip_syntax_errors) },
  +#ifdef EXPERIMENTAL_SRS
  +  { "srs",                opt_stringptr,
  +      (void *)offsetof(redirect_router_options_block, srs) },
  +  { "srs_alias",          opt_stringptr,
  +      (void *)offsetof(redirect_router_options_block, srs_alias) },
  +  { "srs_condition",      opt_stringptr,
  +      (void *)offsetof(redirect_router_options_block, srs_condition) },
  +  { "srs_db",             opt_stringptr,
  +      (void *)offsetof(redirect_router_options_block, srs_db) },
  +#endif
     { "syntax_errors_text", opt_stringptr,
         (void *)offsetof(redirect_router_options_block, syntax_errors_text) },
     { "syntax_errors_to",   opt_stringptr,
  @@ -134,6 +144,12 @@
     NULL,        /* qualify_domain */
     NULL,        /* owners */
     NULL,        /* owngroups */
  +#ifdef EXPERIMENTAL_SRS
  +  NULL,        /* srs */
  +  NULL,        /* srs_condition */
  +  NULL,        /* srs_db */
  +  NULL,        /* srs_alias */
  +#endif
     022,         /* modemask */
     RDO_REWRITE, /* bit_options */
     FALSE,       /* check_ancestor */
  @@ -526,6 +542,36 @@
     ugid.gid_set = TRUE;
     }


  +#ifdef EXPERIMENTAL_SRS
  +  /* For reverse SRS, fill the srs_recipient expandsion variable,
  +  on failure, return decline/fail as relevant */
  +  if(ob->srs != NULL)
  +  {
  +    BOOL usesrs = TRUE;
  +    
  +    if(ob->srs_condition != NULL)
  +      usesrs = expand_check_condition(ob->srs_condition, "srs_condition expansion failed", NULL);
  +    
  +    if(usesrs)
  +      if(Ustrcmp(ob->srs, "reverse") == 0 || Ustrcmp(ob->srs, "reverseandforward") == 0)
  +      {
  +        uschar *res;
  +        int n_srs;
  +    
  +        srs_orig_recipient = addr->address;
  +        eximsrs_init();
  +        if(ob->srs_db)
  +          eximsrs_db_set(TRUE, ob->srs_db);
  +        if((n_srs = eximsrs_reverse(&res, addr->address)) != OK)
  +          return n_srs;
  +        srs_recipient = res;
  +        eximsrs_done();
  +        DEBUG(D_any)
  +          debug_printf("SRS: Recipient '%s' rewriteen to '%s'\n", srs_orig_recipient, srs_recipient);
  +      }
  +  }
  +#endif
  +
   /* Call the function that interprets redirection data, either inline or from a
   file. This is a separate function so that the system filter can use it. It will
   run the function in a subprocess if necessary. If qualify_preserve_domain is
  @@ -748,6 +794,39 @@
       (addr_prop.errors_address != NULL)? addr_prop.errors_address : US"",
       (addr_prop.errors_address != NULL)? "\n" : "");
     }
  +
  +#ifdef EXPERIMENTAL_SRS
  +  /* On successful redirection, check for SRS forwarding and adjust sender */
  +  if(ob->srs != NULL)
  +  {
  +    BOOL usesrs = TRUE;
  +    
  +    if(ob->srs_condition != NULL)
  +      usesrs = expand_check_condition(ob->srs_condition, "srs_condition expansion failed", NULL);
  +    
  +    if(usesrs)
  +      if((Ustrcmp(ob->srs, "forward") == 0 || Ustrcmp(ob->srs, "reverseandforward") == 0) && !verify)
  +      {
  +        uschar *res;
  +        uschar *usedomain;
  +        int n_srs;
  +      
  +        srs_orig_sender = sender_address;
  +        eximsrs_init();
  +        if(ob->srs_db)
  +          eximsrs_db_set(FALSE, ob->srs_db);
  +
  +        if(ob->srs_alias != NULL ? (usedomain = expand_string(ob->srs_alias)) == NULL : 1)
  +          usedomain = deliver_domain;
  +                
  +        if((n_srs = eximsrs_forward(&res, sender_address, usedomain)) != OK)
  +          return n_srs;
  +        sender_address = res;
  +        DEBUG(D_any)
  +          debug_printf("SRS: Sender '%s' rewritten to '%s'\n", srs_orig_sender, sender_address);
  +    }
  +  }
  +#endif


/* Control gets here only when the address has been completely handled. Put the
original address onto the succeed queue so that any retry items that get

  Index: redirect.h
  ===================================================================
  RCS file: /home/cvs/exim/exim-src/src/routers/redirect.h,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- redirect.h    7 Oct 2004 13:10:02 -0000    1.1
  +++ redirect.h    16 Dec 2004 15:11:48 -0000    1.2
  @@ -1,4 +1,4 @@
  -/* $Cambridge: exim/exim-src/src/routers/redirect.h,v 1.1 2004/10/07 13:10:02 ph10 Exp $ */
  +/* $Cambridge: exim/exim-src/src/routers/redirect.h,v 1.2 2004/12/16 15:11:48 tom Exp $ */


   /*************************************************
   *     Exim - an Internet mail transport agent    *
  @@ -32,6 +32,13 @@


     uid_t  *owners;
     gid_t  *owngroups;
  +
  +#ifdef EXPERIMENTAL_SRS
  +  uschar *srs;
  +  uschar *srs_condition;
  +  uschar *srs_db;
  +  uschar *srs_alias;
  +#endif


     int   modemask;
     int   bit_options;