Lloyd Zusman <[EMAIL PROTECTED]> writes:

> [ ... ]
>
> But now, I have a new challenge: coming up with a patch/enhancement to
> the filtering mechanism which will cause a message to be accepted
> without any further filtering.  In other words, every filtering step
> would result in a three-possibility outcome:
>
> 1.  Reject the message.
>
> 2.  Pass the message on to the next filtering step.
>
> 3.  Accept the message without any further filtering.
>
> Numbers 1 and 2 are already in place, and all that's necessary would be
> to come up with number 3.  It doesn't seem too hard.  I'll post a
> proposal in a little while.

OK.  After looking through courier/cdfilters.C, I can see that the
current algorithm looks like this:

1. Run a filter.

2. Look at the initial character of the first line of the filter's
   output.  If it's a digit other than '4' or '5', go to step 3; else go
   to step 5.

3. Output all lines which start with "[0-9][0-9][0-9]-" back to the
   sender.

4. If there are more filters, go to step 1; else, go to step 6.

5. Output all lines which start with "[0-9][0-9][0-9]-" back to the
   sender.

6. Stop processing filters.

The effect of this is to reject and cease processing all messages whose
filters return 4xx or 5xx status codes, and to continue processing all
other messages.

Here's my first cut at a proposal for implementing the scenario I
outlined in my quoted message, above:

1. Run a filter.

2. Look at the initial character of the first line of the filter's
   output.  If it's a digit other than '0', '4' or '5', go to step 3;
   else go to step 5.

3. Output all lines which start with "[0-9][0-9][0-9]-" back to the
   sender.

4. If there are more filters, go to step 1; else, go to step 7.

5. If the initial character is a '0', change it to a '2'.

6. Output all lines which start with "[0-9][0-9][0-9]-" back to the
   sender.

7. Stop processing filters.

Since there are no 0xx SMTP status codes, it's seems to be safely
backward compatible to do special processing when such codes are
encountered.  Here, they would be treated as a signal to accept the
message by returning the corresponding 2xx code to the sender, and then
to cease processing.  All other status codes would be processed in the
same way as they are currently being handled.

The net effect of this would be to implement the scenario that I
outlined above.

Attached is a proposed patch to courier/cdfilters.C which implements
this logic.  It also fixes the memory allocation problems that
Alessandro Vesely discussed with me.

Thoughts?

P.S. -- The "if (isdigit(d))" test near the end of the dofilter()
        routine appears to be superfluous.  I left it in for the time
        being, but I'm thinking that it should probably be removed.

--- courier/cdfilters.C.orig	2006-03-19 17:16:09.000000000 -0500
+++ courier/cdfilters.C	2006-03-22 18:28:53.000000000 -0500
@@ -18,4 +18,5 @@
 #include	"localstatedir.h"
 
+
 using namespace std;
 
@@ -26,4 +27,59 @@
 	void *);
 
+#define FILTER_LIST_INCREMENT	8
+#define MEMORY_ERROR	"432 Out of memory when processing mail filters.\n"
+
+static char **filterlist   = NULL;
+static int  filterlistsize = 0;
+static int  nfilters	   = 0;
+
+static void free_filters()
+{
+	if (filterlist != NULL)
+	{
+		for (int n = 0; n < nfilters; n++)
+		{
+			free(filterlist[n]);
+		}
+	}
+	nfilters = 0;
+}
+
+static int add_filter(const char *filter)
+{
+char	*dupfilter = strdup(filter);
+
+	if (dupfilter == NULL)
+	{
+		cout << MEMORY_ERROR << flush;
+		return (1);
+	}
+
+	if (nfilters >= filterlistsize)
+	{
+		if (filterlist == NULL)
+		{
+			filterlist = (char **) malloc(sizeof (char *) *
+						      FILTER_LIST_INCREMENT);
+		}
+		else
+		{
+			filterlist = (char **) realloc(filterlist,
+						       sizeof (char *) *
+						       (filterlistsize +
+							FILTER_LIST_INCREMENT));
+		}
+		if (filterlist == NULL)
+		{
+			cout << MEMORY_ERROR << flush;
+			return (1);
+		}
+		filterlistsize += FILTER_LIST_INCREMENT;
+	}
+
+	filterlist[nfilters++] = dupfilter;
+	return (0);
+}
+
 int run_filter(const char *filename,
 	unsigned nmsgids,
@@ -40,4 +96,5 @@
 	if (!iswhitelisted)
 	{
+		free_filters();
 		dirp=opendir(FILTERSOCKETDIR);
 		while (dirp && (de=readdir(dirp)) != 0)
@@ -47,16 +104,29 @@
 			sockname = FILTERSOCKETDIR "/";
 			sockname += de->d_name;
-			if (dofilter( sockname,
-					filename, nmsgids,
-					msgidfunc,
-					funcarg))
+			if (add_filter(sockname) != 0)
 			{
-				closedir(dirp);
 				return (1);
 			}
 		}
 		if (dirp)	closedir(dirp);
+
+		qsort((void *) filterlist,
+		      (size_t) nfilters,
+		      sizeof (char *),
+		      (int (*)(const void*, const void*)) strcmp);
+
+		for (int n = 0; n < nfilters; n++)
+		{
+			if (dofilter( filterlist[n],
+				      filename, nmsgids,
+				      msgidfunc,
+				      funcarg))
+			{
+				return (1);
+			}
+		}
 	}
 
+	free_filters();
 	dirp=opendir(ALLFILTERSOCKETDIR);
 	while (dirp && (de=readdir(dirp)) != 0)
@@ -66,14 +136,27 @@
 		sockname = ALLFILTERSOCKETDIR "/";
 		sockname += de->d_name;
-		if (dofilter( sockname,
-				filename, nmsgids,
-				msgidfunc,
-				funcarg))
+		if (add_filter(sockname) != 0)
 		{
-			closedir(dirp);
 			return (1);
 		}
 	}
 	if (dirp)	closedir(dirp);
+
+	qsort((void *) filterlist,
+	      (size_t) nfilters,
+	      sizeof (char *),
+	      (int (*)(const void*, const void*)) strcmp);
+
+	for (int n = 0; n < nfilters; n++)
+	{
+		if (dofilter( filterlist[n],
+			      filename, nmsgids,
+			      msgidfunc,
+			      funcarg))
+		{
+			return (1);
+		}
+	}
+
 	return (0);
 }
@@ -188,5 +271,5 @@
 	if (isdigit(d))
 	{
-		if (d != '4' && d != '5')
+		if (d != '0' && d != '4' && d != '5')
 		{
 			while (isdigit(sockname[0]) &&
@@ -204,4 +287,8 @@
 	}
 
+	if ('d' == '0')
+	{
+		sockname[0] = '2';
+	}
 	cout << sockname << "\n";
 

-- 
 Lloyd Zusman
 [EMAIL PROTECTED]
 God bless you.

Reply via email to