chiark / gitweb /
REORG Delete everything that's not innduct or build system or changed for innduct
[innduct.git] / samples / filter_innd.py
diff --git a/samples/filter_innd.py b/samples/filter_innd.py
deleted file mode 100644 (file)
index 21d094f..0000000
+++ /dev/null
@@ -1,274 +0,0 @@
-##  $Id: filter_innd.py 7903 2008-06-22 20:41:59Z iulius $
-##
-##  This is a sample filter for the Python innd hook.
-##
-##  See the INN Python Filtering and Authentication Hooks documentation
-##  for more information.
-##
-##  You have access to the following methods from the module INN:
-##   - addhist(message-id)
-##   - article(message-id)
-##   - cancel(message-id)
-##   - havehist(message-id)
-##   - hashstring(string)
-##   - head(message-id)
-##   - newsgroup(groupname)
-##   - set_filter_hook(instance)
-##   - syslog(level, message)
-
-import re
-from string import *
-
-##  This looks weird, but creating and interning these strings should
-##  let us get faster access to header keys (which innd also interns) by
-##  losing some strcmps under the covers.
-Also_Control = intern("Also-Control")
-Approved = intern("Approved")
-Bytes = intern("Bytes")
-Cancel_Key = intern("Cancel-Key")
-Cancel_Lock = intern("Cancel-Lock")
-Content_Base = intern("Content-Base")
-Content_Disposition = intern("Content-Disposition")
-Content_Transfer_Encoding = intern("Content-Transfer-Encoding")
-Content_Type = intern("Content-Type")
-Control = intern("Control")
-Date = intern("Date")
-Date_Received = intern("Date-Received")
-Distribution = intern("Distribution")
-Expires = intern("Expires")
-Face = intern("Face")
-Followup_To = intern("Followup-To")
-From = intern("From")
-In_Reply_To = intern("In-Reply-To")
-Injection_Date = intern("Injection-Date")
-Injection_Info = intern("Injection-Info")
-Keywords = intern("Keywords")
-Lines = intern("Lines")
-List_ID = intern("List-ID")
-Message_ID = intern("Message-ID")
-MIME_Version = intern("MIME-Version")
-Newsgroups = intern("Newsgroups")
-NNTP_Posting_Date = intern("NNTP-Posting-Date")
-NNTP_Posting_Host = intern("NNTP-Posting-Host")
-Organization = intern("Organization")
-Originator = intern("Originator")
-Path = intern("Path")
-Posted = intern("Posted")
-Posting_Version = intern("Posting-Version")
-Received = intern("Received")
-References = intern("References")
-Relay_Version = intern("Relay-Version")
-Reply_To = intern("Reply-To")
-Sender = intern("Sender")
-Subject = intern("Subject")
-Supersedes = intern("Supersedes")
-User_Agent = intern("User-Agent")
-X_Auth = intern("X-Auth")
-X_Canceled_By = intern("X-Canceled-By")
-X_Cancelled_By = intern("X-Cancelled-By")
-X_Complaints_To = intern("X-Complaints-To")
-X_Face = intern("X-Face")
-X_HTTP_UserAgent = intern("X-HTTP-UserAgent")
-X_HTTP_Via = intern("X-HTTP-Via")
-X_Mailer = intern("X-Mailer")
-X_Modbot = intern("X-Modbot")
-X_Modtrace = intern("X-Modtrace")
-X_Newsposter = intern("X-Newsposter")
-X_Newsreader = intern("X-Newsreader")
-X_No_Archive = intern("X-No-Archive")
-X_Original_Message_ID = intern("X-Original-Message-ID")
-X_Original_Trace = intern("X-Original-Trace")
-X_Originating_IP = intern("X-Originating-IP")
-X_PGP_Key = intern("X-PGP-Key")
-X_PGP_Sig = intern("X-PGP-Sig")
-X_Poster_Trace = intern("X-Poster-Trace")
-X_Postfilter = intern("X-Postfilter")
-X_Proxy_User = intern("X-Proxy-User")
-X_Submissions_To = intern("X-Submissions-To")
-X_Trace = intern("X-Trace")
-X_Usenet_Provider = intern("X-Usenet-Provider")
-Xref = intern("Xref")
-__BODY__ = intern("__BODY__")
-_LINES__ = intern("__LINES__")
-
-
-class InndFilter:
-    """Provide filtering callbacks to innd."""
-
-    def __init__(self):
-        """This runs every time the filter is loaded or reloaded.
-        This is a good place to initialize variables and precompile
-        regular expressions, or maybe reload stats from disk.
-        """
-        self.re_newrmgroup = re.compile('(?:new|rm)group\s')
-        self.re_obsctl = re.compile('(?:sendsys|version|uuname)')
-        # Message-ID pattern from a once-common spambot.
-        self.re_none44 = re.compile('none\d+\.yet>')
-        # There is a mad newgrouper who likes to meow.
-        self.re_meow = re.compile("^Meow\!", re.M)
-        # One of my silly addresses.
-        self.re_fluffymorph = re.compile("andruQ@myremarQ.coM", re.I)
-
-    def filter_before_reload(self):
-        """Runs just before the filter gets reloaded.
-
-        You can use this method to save state information to be
-        restored by the __init__() method or down in the main module.
-        """
-        syslog('notice', "filter_before_reload executing...")
-
-    def filter_close(self):
-        """Runs when innd exits.
-
-        You can use this method to save state information to be
-        restored by the __init__() method or down in the main module.
-        """
-        syslog('notice', "filter_close running, bye!")
-
-    def filter_messageid(self, msgid):
-        """Filter articles just by their Message-IDs.
-
-        This method interacts with the IHAVE and CHECK NNTP commands.
-        If you return a non-empty string here, the offered article
-        will be refused before you ever have to waste any bandwidth
-        looking at it.  This is not foolproof, so you should do your
-        ID checks both here and in filter_art.  (TAKETHIS does not
-        offer the ID for examination, and a TAKETHIS isn't always
-        preceded by a CHECK.)
-        """
-        return ""               # Deactivate the samples.
-        
-        if self.re_none44.search(msgid):
-            return "But I don't like spam!"
-        if msgid[0:8] == '<cancel.':
-            return "I don't do cybercancels."
-
-    def filter_art(self, art):
-        """Decide whether to keep offered articles.
-
-        art is a dictionary with a bunch of headers, the article's
-        body, and innd's reckoning of the line count.  Items not
-        in the article will have a value of None.
-
-        The available headers are the ones listed near the top of
-        innd/art.c.  At this writing, they are:
-
-            Also-Control, Approved, Bytes, Cancel-Key, Cancel-Lock,
-            Content-Base, Content-Disposition, Content-Transfer-Encoding,
-            Content-Type, Control, Date, Date-Received, Distribution, Expires,
-            Face, Followup-To, From, In-Reply-To, Injection-Date, Injection-Info,
-            Keywords, Lines, List-ID, Message-ID, MIME-Version, Newsgroups,
-            NNTP-Posting-Date, NNTP-Posting-Host, Organization, Originator,
-            Path, Posted, Posting-Version, Received, References, Relay-Version,
-            Reply-To, Sender, Subject, Supersedes, User-Agent,
-            X-Auth, X-Canceled-By, X-Cancelled-By, X-Complaints-To, X-Face,
-            X-HTTP-UserAgent, X-HTTP-Via, X-Mailer, X-Modbot, X-Modtrace,
-            X-Newsposter, X-Newsreader, X-No-Archive, X-Original-Message-ID,
-            X-Original-Trace, X-Originating-IP, X-PGP-Key, X-PGP-Sig,
-            X-Poster-Trace, X-Postfilter, X-Proxy-User, X-Submissions-To,
-            X-Trace, X-Usenet-Provider, Xref.
-
-        The body is the buffer in art['__BODY__'] and the INN-reckoned
-        line count is held as an integer in art['__LINES__'].  (The
-        Lines: header is often generated by the poster, and large
-        differences can be a good indication of a corrupt article.)
-
-        If you want to keep an article, return None or "".  If you
-        want to reject, return a non-empty string.  The rejection
-        string will appear in transfer and posting response banners,
-        and local posters will see them if their messages are
-        rejected.
-        """
-        return ""               # Deactivate the samples.
-
-        # Catch bad Message-IDs from articles fed with TAKETHIS but no CHECK.
-        idcheck = self.filter_messageid(art[Message_ID])
-        if idcheck:
-            return idcheck
-
-        # There are some control messages we don't want to process or
-        # forward to other sites.
-        try:
-            if art[Control] is not None:
-                if self.re_newrmgroup.match(art[Control]):
-                    if self.re_meow.search(art[__BODY__]):
-                        return "The fake tale meows again."
-                    if art[Distribution] == buffer('mxyzptlk'):
-                        return "Evil control message from the 10th dimension"
-                if self.re_obsctl.match(art[Control]):
-                    return "Obsolete control message"
-
-            # If you don't know, you don't want to know.
-            if self.re_fluffymorph.search(art[From]):
-                return "No, you may NOT meow."
-        except:
-            syslog('n', str(sys.exc_info[1]))
-
-    def filter_mode(self, oldmode, newmode, reason):
-        """Capture server events and do something useful.
-
-        When the admin throttles or pauses innd (and lets it go
-        again), this method will be called.  oldmode is the state we
-        just left, and newmode is where we are going.  reason is
-        usually just a comment string.
-
-        The possible values of newmode and oldmode are the five
-        strings 'running', 'paused', 'throttled', 'shutdown' and
-        'unknown'.  Actually 'unknown' shouldn't happen; it's there
-        in case feeping creatures invade innd.
-        """
-        syslog('notice', 'state change from %s to %s - %s'
-               % (oldmode, newmode, reason))
-
-
-"""
-Okay, that's the end of our class definition.  What follows is the
-stuff you need to do to get it all working inside innd.
-"""
-
-##  This import must succeed, or your filter won't work.  I'll repeat
-##  that: You MUST import INN.
-from INN import *
-
-##  Some of the stuff below is gratuitous, just demonstrating how the
-##  INN.syslog call works.  That first thingy tells the Unix syslogger
-##  what severity to use; you can abbreviate down to one letter and
-##  it's case insensitive.  Available levels are (in increasing levels
-##  of seriousness) Debug, Info, Notice, Warning, Err, Crit, and
-##  Alert.  If you provide any other string, it will be defaulted to
-##  Notice.  You'll find the entries in the same log files innd itself
-##  uses, with an 'innd: python:' prefix.
-##
-##  The native Python syslog module seems to clash with INN, so use
-##  INN's.  Oh yeah -- you may notice that stdout and stderr have been
-##  redirected to /dev/null -- if you want to print stuff, open your
-##  own files.
-
-try:
-    import sys
-except Exception, errmsg:
-    syslog('Error', "import boo-boo: " + errmsg[0])
-
-
-##  If you want to do something special when the server first starts
-##  up, this is how to find out when it's time.
-
-if 'spamfilter' not in dir():
-    syslog('n', "First load, so I can do initialization stuff.")
-    # You could unpickle a saved hash here, so that your hard-earned
-    # spam scores aren't lost whenever you shut down innd.
-else:
-    syslog('NoTicE', "I'm just reloading, so skip the formalities.")
-
-
-##  Finally, here is how we get our class on speaking terms with innd.
-##  The hook is refreshed on every reload, so that you can change the
-##  methods on a running server.  Don't forget to test your changes
-##  before reloading!
-spamfilter = InndFilter()
-try:
-    set_filter_hook(spamfilter)
-    syslog('n', "spamfilter successfully hooked into INN")
-except Exception, errmsg:
-    syslog('e', "Cannot obtain INN hook for spamfilter: %s" % errmsg[0])
-