#! /usr/local/bin/python2.3
# Another server version of hammie.py
# This is not intended to be run manually, it is the opportunistic
# daemon backend of sb_bnfilter.
#
# Author: Toby Dickenson
#
"""Usage: %(program)s [options] FILE
Where:
-h
show usage and exit
-p FILE
use pickle FILE as the persistent store. loads data from this file
if it exists, and saves data to this file at the end.
-d FILE
use DBM store FILE as the persistent store.
-o section:option:value
set [section, option] in the options database to value
-a seconds
timeout in seconds between requests before this server terminates
-A number
terminate this server after this many requests
FILE
unix domain socket used on which we listen
"""
import os, getopt, sys, SocketServer, time, traceback, select, socket, errno
try:
True, False
except NameError:
# Maintain compatibility with Python 2.2
True, False = 1, 0
# See Options.py for explanations of these properties
program = sys.argv[0]
def usage(code, msg=''):
"""Print usage message and sys.exit(code)."""
if msg:
print >> sys.stderr, msg
print >> sys.stderr
print >> sys.stderr, __doc__
sys.exit(code)
def main():
"""Main program; parse options and go."""
try:
opts, args = getopt.getopt(sys.argv[1:], 'hd:p:o:a:A:')
except getopt.error, msg:
usage(2, msg)
if len(args) != 1:
usage(2, "socket not specified")
# get the server up before initializing spambayes, so that
# we havent wasted time if we later find we cant start the server
try:
server = BNServer(args[0], BNRequest)
except socket.error,e:
if e[0]==errno.EADDRINUSE:
pass # in use, no need
else:
raise # a real error
else:
try:
from spambayes import Options, storage
options = Options.options
for opt, arg in opts:
if opt == '-h':
usage(0)
elif opt == '-o':
options.set_from_cmdline(arg, sys.stderr)
elif opt == '-a':
server.timeout = float(arg)
elif opt == '-A':
server.number = int(arg)
h = make_HammieFilter()
h.dbname, h.usedb = storage.database_type(opts)
server.hammie = h
server.serve_until_idle()
h.close()
finally:
try:
os.unlink(args[0])
except EnvironmentError:
pass
class NowIdle(Exception):
pass
class BNServer(SocketServer.UnixStreamServer):
allow_reuse_address = True
timeout = 10.0
number = 100
def serve_until_idle(self):
try:
for i in range(self.number):
self.handle_request()
except NowIdle:
pass
def get_request(self):
r,w,e = select.select([self.socket], [], [], self.timeout)
if r:
return self.socket.accept()
else:
raise NowIdle()
class BNRequest(SocketServer.StreamRequestHandler):
def handle(self):
switches = self.rfile.readline()
body = self.rfile.read()
try:
response = self._calc_response(switches,body)
self.wfile.write('0\n%d\n'%(len(response),))
self.wfile.write(response)
except:
response = traceback.format_exception_only(sys.exc_info()[0],sys.exc_info()[1])[0]
self.wfile.write('1\n%d\n'%(len(response),))
self.wfile.write(response)
def _calc_response(self,switches,body):
switches = switches.split()
actions = []
opts, args = getopt.getopt(switches, 'fgstGS')
h = self.server.hammie
for opt, arg in opts:
if opt == '-f':
actions.append(h.filter)
elif opt == '-g':
actions.append(h.train_ham)
elif opt == '-s':
actions.append(h.train_spam)
elif opt == '-t':
actions.append(h.filter_train)
elif opt == '-G':
actions.append(h.untrain_ham)
elif opt == '-S':
actions.append(h.untrain_spam)
if actions == []:
actions = [h.filter]
from spambayes import mboxutils
msg = mboxutils.get_message(body)
for action in actions:
action(msg)
return mboxutils.as_string(msg, 1)
def make_HammieFilter():
# The sb_hammie script has some logic in the HammieFiler class that we need here too.
# Ideally that should be moved into the spambayes package, but for now lets just
# abuse sys.path, make assumptions about the directory layout, and import it direct
# from the sb_filter script.
from spambayes import Options
path = os.path.split(Options.__file__)[0]+'/../scripts'
if path not in sys.path:
sys.path.append(path)
from sb_filter import HammieFilter
return HammieFilter()
if __name__ == "__main__":
main()
syntax highlighted by Code2HTML, v. 0.9.1