CVS: tmda/TMDA Util.py,1.100,1.101 FilterParser.py,1.58,1.59 Defaults.py,1.183,1.184 ChangeLog,1.280,1.281
Timothy Legant <[email protected]>
| Newsgroups | gmane.mail.spam.tmda.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/tmda/tmda/TMDA
In directory sc8-pr-cvs1:/tmp/cvs-serv4926/TMDA
Modified Files:
Util.py FilterParser.py Defaults.py ChangeLog
Log Message:
Defaults.py: New variables DB_BARE_APPEND and DB_CONFIRM_APPEND.
FilterParser.py: Removed {from,to}-mysql code. Moved
__create_sql_params method to module-level function create_sql_params.
Removed -domains argument and always add the domains into the keys.
Made the domains list contain only unique domains.
Util.py: New function 'db_insert' used by the DB_BARE_APPEND and
DB_CONFIRM_APPEND code.
tmda-inject: Added code to insert recipient into database using the
SQL code in DB_BARE_APPEND if both DB_BARE_APPEND and DB_CONNECTION
are set. Mimics BARE_APPEND functionality.
tmda-rfilter: Added code to insert sender into database using the SQL
code in DB_CONFIRM_APPEND if both DB_CONFIRM_APPEND and DB_CONNECTION
are set. Mimics CONFIRM_APPEND functionality. Made 'sender_list' in
main() contain only unique senders.
filter-sources.ht: Removed {from,to}-mysql documentation, moved
-domains documentation to top, since now it is default behavior.
Index: Util.py
===================================================================
RCS file: /cvsroot/tmda/tmda/TMDA/Util.py,v
retrieving revision 1.100
retrieving revision 1.101
diff -u -r1.100 -r1.101
--- Util.py 9 Jul 2003 18:23:01 -0000 1.100
+++ Util.py 11 Jul 2003 23:02:59 -0000 1.101
@@ -737,6 +737,21 @@
return object
+def db_insert(db, insert_sql, params):
+ """Insert (using the 'insert_sql' SQL) an address into a SQL DB."""
+ dbmodule = sys.modules[db.__module__]
+ DatabaseError = getattr(dbmodule, 'DatabaseError')
+ cursor = db.cursor()
+ try:
+ try:
+ cursor.execute(insert_sql, params)
+ db.commit()
+ except DatabaseError:
+ pass
+ finally:
+ cursor.close()
+
+
def findmatch(list, addrs):
"""Determine whether any of the passed e-mail addresses match a
Unix shell-style wildcard pattern contained in list. The
Index: FilterParser.py
===================================================================
RCS file: /cvsroot/tmda/tmda/TMDA/FilterParser.py,v
retrieving revision 1.58
retrieving revision 1.59
diff -u -r1.58 -r1.59
--- FilterParser.py 1 Jul 2003 06:29:51 -0000 1.58
+++ FilterParser.py 11 Jul 2003 23:02:59 -0000 1.59
@@ -262,22 +262,18 @@
arguments = {
'from' : None,
'to' : None,
- 'from-file' : ('autocdb', 'autodbm', 'domains', 'optional'),
- 'to-file' : ('autocdb', 'autodbm', 'domains', 'optional'),
- 'from-cdb' : ('domains', 'optional',),
- 'to-cdb' : ('domains', 'optional',),
- 'from-dbm' : ('domains', 'optional',),
- 'to-dbm' : ('domains', 'optional',),
+ 'from-file' : ('autocdb', 'autodbm', 'optional'),
+ 'to-file' : ('autocdb', 'autodbm', 'optional'),
+ 'from-cdb' : ('optional',),
+ 'to-cdb' : ('optional',),
+ 'from-dbm' : ('optional',),
+ 'to-dbm' : ('optional',),
'from-ezmlm' : ('optional',),
'to-ezmlm' : ('optional',),
'from-mailman' : ('attr', 'optional' ),
'to-mailman' : ('attr', 'optional' ),
- 'from-mysql' : ('like', 'rlike'),
- 'to-mysql' : ('like', 'rlike'),
- 'from-sql' : ('action_column', 'addr_column',
- 'domains', 'wildcards'),
- 'to-sql' : ('action_column', 'addr_column',
- 'domains', 'wildcards'),
+ 'from-sql' : ('action_column', 'addr_column', 'wildcards'),
+ 'to-sql' : ('action_column', 'addr_column', 'wildcards'),
'body' : ('case',),
'headers' : ('case',),
'body-file' : ('case', 'optional'),
@@ -724,44 +720,6 @@
source)
- def __search_mysql(self, Table, Args, Keys, Actions, Source):
- "Search MySQL table."
- if not self.MySQL:
- # Connect to the database if we have not yet connected
- import _mysql
- self.MySQL = _mysql.connect \
- (
- host = Defaults.MYSQL_HOST,
- db = Defaults.MYSQL_DATABASE,
- user = Defaults.MYSQL_USER,
- passwd = Defaults.MYSQL_PASSWORD
- )
- # Searches can be for records that are "=", "like", or "rlike" the
- # keys. "=" is the fastest and the default, but it does not allow any
- # wildcarding. "like" allows "_" to mean any character and "%" to
- # mean any string. "rlike" allows regular expressions.
- Compare = "="
- if Args.has_key('like'): Compare = "LIKE"
- elif Args.has_key('rlike'): Compare = "RLIKE"
- Test = ""
- for Key in Keys:
- if Test: Test += "OR "
- Test += "('%s' %s ADDRESS) " % (Key.replace("'", "\\'"), Compare)
- # Perform the query
- self.MySQL.query("SELECT * FROM %s WHERE %s LIMIT 1" % (Table, Test))
- # Fetch the result
- Result = self.MySQL.store_result().fetch_row(0, 1)
- found_match = len(Result)
-
- # If there is an entry for this key, we consider it an overriding
- # action specification.
- if found_match and Result[0]["ACTION"]:
- Actions.clear()
- Actions.update(self.__buildactions(Result[0]["ACTION"], Source))
-
- return found_match
-
-
def __search_cdb(self, pathname, keys, actions, source):
"""
Search DJB's constant databases; see <http:/cr.yp.to/cdb.html>.
@@ -842,24 +800,13 @@
"""
Attempt to extract the domain name from each address in keys.
"""
- domains = []
+ domains = {}
for k in keys:
try:
- domains.append(k.split('@', 1)[1])
+ domains[k.split('@', 1)[1]] = None
except IndexError:
pass
- return domains
-
-
- def __create_sql_params(self, dbkeys):
- """Return dictionary of parameters for sql statement."""
- params = { 'recipient': Defaults.USERNAME+'@'+Defaults.HOSTNAME,
- 'username' : Defaults.USERNAME,
- 'hostname' : Defaults.HOSTNAME
- }
- for i in range(len(dbkeys)):
- params['criterion'+str(i)] = dbkeys[i]
- return params
+ return domains.keys()
def __create_sql_criteria(self, dbkeys, addresscolumn):
@@ -889,33 +836,42 @@
dbkeys = keys
if args.has_key('wildcards'):
dbkeys = []
- params = self.__create_sql_params(dbkeys)
+ _username = Defaults.USERNAME.lower()
+ _hostname = Defaults.HOSTNAME.lower()
+ _recipient = _username + '@' + _hostname
+ params = create_sql_params(dbkeys,
+ recipient=_recipient,
+ username=_username,
+ hostname=_hostname)
cursor = self.db_instance.cursor()
- cursor.execute(selectstmt, params)
- rows = cursor.fetchall()
- if cursor.rowcount <= 0:
- return 0
- if args.has_key('wildcards'):
- if len(cursor.description) > 1:
- dblist = [' '.join([row[0], row[1] or '']) for row in rows]
+ try:
+ cursor.execute(selectstmt, params)
+ rows = cursor.fetchall()
+ if cursor.rowcount <= 0:
+ return 0
+ if args.has_key('wildcards'):
+ if len(cursor.description) > 1:
+ dblist = [' '.join([row[0], row[1] or '']) for row in rows]
+ else:
+ dblist = [row[0] for row in rows]
+ found_match = self.__search_list(dblist, keys, actions, source)
else:
- dblist = [row[0] for row in rows]
- found_match = self.__search_list(dblist, keys, actions, source)
- else:
- action_column = args.get('action_column')
- if action_column:
- actcolidx = self.__get_column_index(action_column, cursor)
- if actcolidx == -1:
- actcolidx = self.__get_column_index(action_column.lower(),
- cursor)
+ action_column = args.get('action_column')
+ if action_column:
+ actcolidx = self.__get_column_index(action_column, cursor)
if actcolidx == -1:
- err = "no action column (%s)" % (action_column,)
- raise MatchError(lineno, err)
- action = rows[0][actcolidx]
- if action:
- actions.clear()
- actions.update(self.__buildactions(action, source))
- found_match = 1
+ actcolidx = self.__get_column_index(
+ action_column.lower(), cursor)
+ if actcolidx == -1:
+ err = "no action column (%s)" % (action_column,)
+ raise MatchError(lineno, err)
+ action = rows[0][actcolidx]
+ if action:
+ actions.clear()
+ actions.update(self.__buildactions(action, source))
+ found_match = 1
+ finally:
+ cursor.close()
return found_match
@@ -945,8 +901,7 @@
if source in ('from-file', 'to-file'):
dbname = os.path.expanduser(match)
search_func = self.__search_file
- if args.has_key('domains'):
- keys += self.__extract_domains(keys)
+ keys += self.__extract_domains(keys)
# If we have an 'auto*' argument, ensure that the database
# is up-to-date. If the 'optional' argument is also given,
# don't die if the file doesn't exist.
@@ -974,8 +929,7 @@
if source in ('from-dbm', 'to-dbm'):
import anydbm
match = os.path.expanduser(match)
- if args.has_key('domains'):
- keys += self.__extract_domains(keys)
+ keys += self.__extract_domains(keys)
try:
found_match = self.__search_dbm(match, keys,
actions, source)
@@ -988,8 +942,7 @@
if source in ('from-cdb', 'to-cdb'):
import cdb
match = os.path.expanduser(match)
- if args.has_key('domains'):
- keys += self.__extract_domains(keys)
+ keys += self.__extract_domains(keys)
try:
found_match = self.__search_cdb(match, keys,
actions, source)
@@ -1059,22 +1012,13 @@
break
if found_match:
break
- # MySQL-style databases.
- if source in ('from-mysql', 'to-mysql'):
- found_match = self.__search_mysql \
- (
- match, args, keys, actions, source
- )
- if found_match:
- break
# Generic SQL. Expects a SELECT statement as the 'match' field.
# There are two "modes", depending on the presence of TMDA-style
# wildcards in the database. See the filter source documentation
# for more information.
if source in ('from-sql', 'to-sql'):
selectstmt = match
- if args.has_key('domains'):
- keys += self.__extract_domains(keys)
+ keys += self.__extract_domains(keys)
addr_column = args.get('addr_column')
if args.has_key('wildcards'):
if addr_column:
@@ -1235,3 +1179,12 @@
if len(parts) == 1:
return (parts[0], None)
return tuple(parts)
+
+
+def create_sql_params(dbkeys=[], **kwargs):
+ """Return dictionary of parameters for SQL statement."""
+ params = kwargs.copy()
+ for i in range(len(dbkeys)):
+ params['criterion'+str(i)] = dbkeys[i]
+ return params
+
Index: Defaults.py
===================================================================
RCS file: /cvsroot/tmda/tmda/TMDA/Defaults.py,v
retrieving revision 1.183
retrieving revision 1.184
diff -u -r1.183 -r1.184
--- Defaults.py 1 Jul 2003 06:29:51 -0000 1.183
+++ Defaults.py 11 Jul 2003 23:02:59 -0000 1.184
@@ -1102,6 +1102,59 @@
if not vars().has_key('DB_CONNECTION'):
DB_CONNECTION = None
+# DB_CONFIRM_APPEND
+# SQL INSERT statement to be used to insert confirmed sender addresses
+# into a SQL database. The Python DB API will take care of properly
+# quoting parameters that are strings.
+# Requires a valid DB_CONNECTION object.
+#
+# Available substition parameters are:
+#
+# %(recipient)s - USERNAME@HOSTNAME
+# %(username)s - USERNAME
+# %(hostname)s - HOSTNAME
+# %(sender)s - sender's address (envelope sender or X-Primary-Address)
+#
+# Examples:
+#
+# DB_CONFIRM_APPEND = """
+# INSERT INTO whitelist (user_email, address)
+# VALUES (%(recipient)s, %(sender)s)"""
+#
+# DB_CONFIRM_APPEND = """
+# INSERT INTO wildcard_list (uid, address, action)
+# SELECT uid, %(sender)s, 'accept'
+# FROM users
+# WHERE users.email = %(recipient)s"""
+#
+# Default is None
+if not vars().has_key('DB_CONFIRM_APPEND'):
+ DB_CONFIRM_APPEND = None
+
+# DB_BARE_APPEND
+# SQL INSERT statement to be used to insert recipient addresses into
+# a SQL database if the outgoing <action> was 'bare=append'. The Python
+# DB API will take care of properly quoting parameters that are strings.
+# Requires a valid DB_CONNECTION object.
+#
+# Available substition parameters are:
+#
+# %(recipient)s - recipient's email address
+# %(username)s - USERNAME (of TMDA user)
+# %(hostname)s - HOSTNAME (of TMDA user)
+# %(sender)s - USERNAME@HOSTNAME (address of TMDA user)
+# %(fromheader)s - address of TMDA user in From: header field
+#
+# Examples:
+#
+# DB_BARE_APPEND = """
+# INSERT INTO whitelist (user_email, address)
+# VALUES (%(sender)s, %(recipient)s)"""
+#
+# Default is None
+if not vars().has_key('DB_BARE_APPEND'):
+ DB_BARE_APPEND = None
+
# PENDING_DIR
# Full path to the directory containing messages pending confirmation
# (aka, the "pending queue"). If this directory doesn't exist, it
Index: ChangeLog
===================================================================
RCS file: /cvsroot/tmda/tmda/TMDA/ChangeLog,v
retrieving revision 1.280
retrieving revision 1.281
diff -u -r1.280 -r1.281
--- ChangeLog 5 Jul 2003 00:25:19 -0000 1.280
+++ ChangeLog 11 Jul 2003 23:03:00 -0000 1.281
@@ -1,3 +1,17 @@
+2003-07-11 Tim Legant <[email protected]>
+
+ * Defaults.py: New variables DB_BARE_APPEND and
+ DB_CONFIRM_APPEND.
+
+ * FilterParser.py (FilterParser): Removed {from,to}-mysql code.
+ Moved __create_sql_params method to module-level function
+ create_sql_params. Removed -domains argument and always add the
+ domains into the keys. Made the domains list contain only unique
+ domains.
+
+ * Util.py (db_insert): New function, used by the DB_BARE_APPEND
+ and DB_CONFIRM_APPEND code.
+
2003-07-01 Tim Legant <[email protected]>
* Util.py (filter_match): Create FilterParser with DB_CONNECTION.
_______________________________________
tmda-cvs mailing list
http://tmda.net/lists/listinfo/tmda-cvs