This is $Revision: 1.9 $ dated $Date: 1998/10/19 00:08:16 $.

innd and nnrpd now support some amount of Perl filtering of articles
received from another peer or from a newsreader and some authentication.
This code is based very heavily on work Christophe Wolfhugel <wolf@pasteur.fr>
did. He in turn was inspired by the existing TCL support. Send me
(<inn@isc.org>) and not Christophe any bug reports, as I fiddled with the
code, and am probably the cause of any problems.

What you get with the Perl support is described in more detail below, but
basically you can supply a perl subroutine that will be invoked on every
article received by innd from a peer, or by nnrpd from a reader. The
subroutine causes nnrpd or innd to accept or reject the article. This will
be most useful for spam killing.

To include Perl support, you need to have perl 5.004. Other Version before
5.004, you will get link error at compilation time. Go to
http://www.perl.com/CPAN for the latest Perl goodies.

To enable Perl support, you need to specify '--with-perl' with configure.

--------------------------------------------------

Innd:
	When innd starts it loads the file _PATH_PERL_STARTUP_INND, next it
loads _PATH_PERL_FILTER_INND. Everytime, before _PATH_PERL_FILTER_INND is
loaded, including the first time, if the perl subroutine
``filter_before_reload'' is defined, then it will be called with no
arguments, and it is not expected to return any values. After the
_PATH_PERL_FILTER_INND is loaded the routine ``filter_after_reload'' is
executed in the same way. These two functions are normally defined in
_PATH_PERL_STARTUP_INND. They could be used for doing things like flushing
cached data to disk, or loading up a cache etc.

	Whenever ctlinnd is run with the command ``reload'' and the
first argument ``filter.perl'' or ``all'', the filter file
_PATH_PERL_FILTER_INND is reloaded with the before and after functions
being run as just described. If the subroutine ``filter_art'' is defined
after the file has been reloaded, then filtering is turned on. If is not
defined, then filtering is turned of.
	
	Whenever ctlinnd is run with the command ``throttle'', or ``pause''
or ``go'', then the perl function ``filter_mode'' is called. It recives no
arguments and returns no value. It has access to a global associative array
called ``%mode'', which has three keyed values:

	'Mode' ==> the current mode (``throttled'', ``paused'', or ``running'')
	'NewMode' ==> the new mode.
	'reason' ==> the reason given for the mode change.

	Whenever a message-id is received from a peer via the CHECK command,
and filtering is turned on, the perl subroutine ``filter_messageid'' is
called. It receives a single argument, the message-id, and returns a single
scalar value. If the value is not the null string, the article is refused.

	Whenever an article is received from a peer via IHAVE or TAKETHIS,
and filtering is turned on, the perl subroutine ``filter_art'' is
called. It receives no arguments and returns a single scalar value or the
undefined value. It has access to a global associative array called
``%hdr'', which contains values for all standard headers with a non-null
value of the article. The standard headers are:

	Approved, Control, Date, Distribution, Expires, From, Lines,
	Message-ID, Newsgroups, Path, Reply-To, Sender, Subject, Supersedes,
	Bytes, Also-Control, References, __BODY__

	The special header value of "__BODY__" contains the body of the
article, for special content-based filters.

For example:

   %hdr = ('Subject', 'MAKE MONEY FAST!!', 
	   'From', 'Joe Spamer <him@aol.com>',
	   'Date', '10 Sep 1996 15:32:28 UTC',
	   'Newsgroups', 'alt.test',
	   'Path', 'data.ramona.vix.com!gw.home.vix.com!not-for-mail',
	   'Organization', 'Spammers Anonymous',
	   'Lines' '5',
	   'Distribution', 'world'
	   'Message-ID', '<6.20232.842369548@home.octet.com.au>',
	   '__BODY__', 'Send five dollars to the ISC, c/o ...'
	   )

If ``filter_art'' returns a null string (not a zero), then the article is
accepted. If it returns a non-zero value, then it is rejected, and the
value returned (typically a string) is used to log the reason why it was
rejected.

	There are four perl subs available from the perl subroutines called
from within INN:

INN::havehist(messageid)  # returns true if messageid is in the history db

INN::newsgroup(newsgroup) # returns the status of the news group (the last
			  # field of the active file, or false if the
			  # isn't in your active file

INN::cancel(messageid)    # cancels messageid on your server
 
INN::addhist(messageid, arrivaltime,articletime,expiretime,paths)
			  # adds messageid to the history database
			  # all the other fields are optional.
			  # the time fields default to the current
			  # time, and the paths field defaults to
			  # the empty string.

--------------------------------------------------

nnrpd:

	When nnrpd starts it load the file _PATH_PERL_FILTER_NNRPD. If the
function ``filter_post'' is defined, then filtering is turned on. If it
isn't, then filtering is turned off. When filtering is on, every article
received via the POST command is given to the ``filter_post'' subroutine in
exactly the same manner as for filter_art in innd. The return value must be
a null string to accept the article, anything else will cause the article
to be rejected and the reason sent back to the client will be the returned
value of the ``filter_post'' function.  If $modify_headers is set to a
non-zero value, then all headers in the associative array ``%hdr'' are written
back to the posted message.  Here are other items for filtering articles for
nnrpd.

  - can access to message bodies, in the $body variable.
  - can access to the poster's authinfo username, in the $user variable.
    Obviously this has no effect unless you use authinfo.
  - check a returncode 'DROP' to the Perl interface.  If the string returned
    by the Perl subroutine begins with 'DROP', the post will be discarded
    and success returned to the client.
  - check a returncode 'SPOOL' to the Perl interface.  If the string
    returned by the Perl subroutine begins with 'SPOOL', success will be
    returned to the client and the post will be saved to in.coming/spam
    for manual inspection.

	If ``nnrpperlauth'' in inn.conf is set to ``true'', nnrpd authenticates
reader with perl instead of normal authentication  with  nnrp.access.  For
perl authentication, nnrpd_auth.pl is used.  This file is loaded when nnrpd
starts up. If it defines a sub named `authenticate', then that function will
be called during processing of a connect, auth request or disconnect.
Attributes about the connection are passed to the program in the %attributes
global variable.  It should return an array with 4 elements:

1) NNTP response code.  Should be one of the codes from %connectcodes or %auth
   codes
2) Reading Allowed. Should be a boolean value.
3) Posting Allowed. Should be a boolean value.
4) Wildmat expression that says what groups to provide access to.

All four of these are required.  If there is a problem with them then nnrpd
will die and syslog the exact reason.  See samples/nnrpd_auth.pl.in for sample
authentication.
--------------------------------------------------

Some notes:

In the samples directory there are filter_inn.pl, filter_nnrpd.pl and
startup_innd.pl, with some simplistic examples on how to use them. Note
that all perl evaluation is done inside an implicit ``eval'', so calling
die() will not kill the innd or nnrpd process, nor any other sort of syntax
or functional error.

You should always do 'perl -c -w file' before starting or reloading. If you
change the file after innd is running, and then reload it, filtering wil be
disabled if there was an error in the file. At which point you'll have to
fix the file and reload it.

--------------------------------------------------

Available packages using filter_innd.pl and filter_nnrpd.pl:

This is an unofficial list of known filtering packages at the time of
publication. This is not an endorsement of these filters by the ISC or the
INN developers, but is included as assistance in locating packages which
make use of this filter mechanism.

CleanFeed		Jeremy Nixon <jeremy@exit109.com>
http://www.exit109.com/~jeremy/news/antispam.html
	A spam filter catching excessive multi-posting and a host of other
	filtering tools. Uses filter_innd.pl exclusively, requires MD5
	perl module.

Usenet II Filter	Edward S. Marshall <emarshal@xnet.com>
http://www.xnet.com/~emarshal/inn/filter_nnrpd.pl
	Checks for "soundness" according to Usenet II guidelines in the
	net.* hierarchy. Designed to use filter_nnrpd.pl.
