Revision: 8118
http://svn.sourceforge.net/mailman/?rev=8118&view=rev
Author: bwarsaw
Date: 2006-12-27 15:45:41 -0800 (Wed, 27 Dec 2006)
Log Message:
-----------
Utils.list_names(): Use a database query to get all the list names.
dbcontext.py: Added api_get_list_names() to support Utils.list_names().
listdata.py: Added two additional MailList attributes which need to be stored
in the database. The first is 'admin_member_chunksize' which isn't modifiable
from the web. The second is 'password' which holds the list's password.
HTMLFormatObject: item strings can now be unicodes.
bin/list_lists.py: Must call initialize() to get the database properly
initialized, not just config.load(). This will be a common theme.
SecurityManager.py:
- Remove md5 and crypt support
- Added mailman.debug logger, though it will be only used during
debugging.
- The 'secret' can be a unicode now.
- A few coding style updates; repr() instead of backticks, 'key in dict'
instead of 'dict.has_key(key)'
Modified Paths:
--------------
branches/tmp-sqlalchemy-branch/Mailman/SecurityManager.py
branches/tmp-sqlalchemy-branch/Mailman/Utils.py
branches/tmp-sqlalchemy-branch/Mailman/bin/list_lists.py
branches/tmp-sqlalchemy-branch/Mailman/database/dbcontext.py
branches/tmp-sqlalchemy-branch/Mailman/database/listdata.py
branches/tmp-sqlalchemy-branch/Mailman/htmlformat.py
Modified: branches/tmp-sqlalchemy-branch/Mailman/SecurityManager.py
===================================================================
--- branches/tmp-sqlalchemy-branch/Mailman/SecurityManager.py 2006-12-12
03:58:06 UTC (rev 8117)
+++ branches/tmp-sqlalchemy-branch/Mailman/SecurityManager.py 2006-12-27
23:45:41 UTC (rev 8118)
@@ -28,7 +28,7 @@
#
# Each cookie has the following ingredients: the authorization context's
# secret (i.e. the password, and a timestamp. We generate an SHA1 hex
-# digest of these ingredients, which we call the `mac'. We then marshal
+# digest of these ingredients, which we call the 'mac'. We then marshal
# up a tuple of the timestamp and the mac, hexlify that and return that as
# a cookie keyed off the authcontext. Note that authenticating the user
# also requires the user's email address to be included in the cookie.
@@ -48,7 +48,6 @@
import os
import re
-import md5
import sha
import time
import urllib
@@ -64,12 +63,8 @@
from Mailman import Utils
from Mailman.configuration import config
-try:
- import crypt
-except ImportError:
- crypt = None
-
log = logging.getLogger('mailman.error')
+dlog = logging.getLogger('mailman.debug')
SLASH = '/'
@@ -77,8 +72,6 @@
class SecurityManager:
def InitVars(self):
- # We used to set self.password here, from a crypted_password argument,
- # but that's been removed when we generalized the mixin architecture.
# self.password is really a SecurityManager attribute, but it's set in
# MailList.InitVars().
self.mod_password = None
@@ -146,50 +139,15 @@
if ok:
return Defaults.AuthSiteAdmin
elif ac == Defaults.AuthListAdmin:
- def cryptmatchp(response, secret):
- try:
- salt = secret[:2]
- if crypt and crypt.crypt(response, salt) == secret:
- return True
- return False
- except TypeError:
- # BAW: Hard to say why we can get a TypeError here.
- # SF bug report #585776 says crypt.crypt() can raise
- # this if salt contains null bytes, although I don't
- # know how that can happen (perhaps if a MM2.0 list
- # with USE_CRYPT = 0 has been updated? Doubtful.
- return False
# The password for the list admin and list moderator are not
# kept as plain text, but instead as an sha hexdigest. The
# response being passed in is plain text, so we need to
- # digestify it first. Note however, that for backwards
- # compatibility reasons, we'll also check the admin response
- # against the crypted and md5'd passwords, and if they match,
- # we'll auto-migrate the passwords to sha.
+ # digestify it first.
key, secret = self.AuthContextInfo(ac)
if secret is None:
continue
sharesponse = sha.new(response).hexdigest()
- upgrade = ok = False
if sharesponse == secret:
- ok = True
- elif md5.new(response).digest() == secret:
- ok = upgrade = True
- elif cryptmatchp(response, secret):
- ok = upgrade = True
- if upgrade:
- save_and_unlock = False
- if not self.Locked():
- self.Lock()
- save_and_unlock = True
- try:
- self.password = sharesponse
- if save_and_unlock:
- self.Save()
- finally:
- if save_and_unlock:
- self.Unlock()
- if ok:
return ac
elif ac == Defaults.AuthListModerator:
# The list moderator password must be sha'd
@@ -234,17 +192,17 @@
def MakeCookie(self, authcontext, user=None):
key, secret = self.AuthContextInfo(authcontext, user)
- if key is None or secret is None or not isinstance(secret, str):
+ if key is None or secret is None or not isinstance(secret, basestring):
raise ValueError
# Timestamp
issued = int(time.time())
# Get a digest of the secret, plus other information.
- mac = sha.new(secret + `issued`).hexdigest()
+ mac = sha.new(secret + repr(issued)).hexdigest()
# Create the cookie object.
c = Cookie.SimpleCookie()
c[key] = binascii.hexlify(marshal.dumps((issued, mac)))
c[key]['path'] = self._cookie_path()
- # We use session cookies, so don't set `expires' or `max-age' keys.
+ # We use session cookies, so don't set 'expires' or 'max-age' keys.
# Set the RFC 2109 required header.
c[key]['version'] = 1
return c
@@ -293,7 +251,7 @@
for k in c.keys():
if k.startswith(prefix):
usernames.append(k[len(prefix):])
- # If any check out, we're golden. Note: `@'s are no longer legal
+ # If any check out, we're golden. Note: '@'s are no longer legal
# values in cookie keys.
for user in [Utils.UnobscureEmail(u) for u in usernames]:
ok = self.__checkone(c, authcontext, user)
@@ -310,7 +268,7 @@
key, secret = self.AuthContextInfo(authcontext, user)
except Errors.NotAMemberError:
return False
- if not c.has_key(key) or not isinstance(secret, str):
+ if key not in c or not isinstance(secret, basestring):
return False
# Undo the encoding we performed in MakeCookie() above. BAW: I
# believe this is safe from exploit because marshal can't be forced to
@@ -332,7 +290,7 @@
return False
# Calculate what the mac ought to be based on the cookie's timestamp
# and the shared secret.
- mac = sha.new(secret + `issued`).hexdigest()
+ mac = sha.new(secret + repr(issued)).hexdigest()
if mac <> received_mac:
return False
# Authenticated!
Modified: branches/tmp-sqlalchemy-branch/Mailman/Utils.py
===================================================================
--- branches/tmp-sqlalchemy-branch/Mailman/Utils.py 2006-12-12 03:58:06 UTC
(rev 8117)
+++ branches/tmp-sqlalchemy-branch/Mailman/Utils.py 2006-12-27 23:45:41 UTC
(rev 8118)
@@ -76,12 +76,9 @@
def list_names():
- """Return the names of all lists in default list directory."""
- got = set()
- for fn in os.listdir(config.LIST_DATA_DIR):
- if list_exists(fn):
- got.add(fn)
- return got
+ """Return the fqdn names of all lists in default list directory."""
+ return ['[EMAIL PROTECTED]' % (listname, hostname)
+ for listname, hostname in database.get_list_names()]
def split_listname(listname):
Modified: branches/tmp-sqlalchemy-branch/Mailman/bin/list_lists.py
===================================================================
--- branches/tmp-sqlalchemy-branch/Mailman/bin/list_lists.py 2006-12-12
03:58:06 UTC (rev 8117)
+++ branches/tmp-sqlalchemy-branch/Mailman/bin/list_lists.py 2006-12-27
23:45:41 UTC (rev 8118)
@@ -21,7 +21,7 @@
from Mailman import MailList
from Mailman import Utils
from Mailman import Version
-from Mailman.configuration import config
+from Mailman.initialize import initialize
from Mailman.i18n import _
__i18n_templates__ = True
@@ -65,7 +65,7 @@
def main():
parser, opts, args = parseargs()
- config.load(opts.config)
+ initialize(opts.config)
names = list(Utils.list_names())
names.sort()
Modified: branches/tmp-sqlalchemy-branch/Mailman/database/dbcontext.py
===================================================================
--- branches/tmp-sqlalchemy-branch/Mailman/database/dbcontext.py
2006-12-12 03:58:06 UTC (rev 8117)
+++ branches/tmp-sqlalchemy-branch/Mailman/database/dbcontext.py
2006-12-27 23:45:41 UTC (rev 8118)
@@ -22,7 +22,7 @@
from Mailman import Version
from Mailman.configuration import config
-from Mailman.database import address
+from Mailman.database import address
from Mailman.database import listdata
from Mailman.database import version
from Mailman.database.txnsupport import txn
@@ -132,6 +132,13 @@
return mlists[0]
return None
+ @txn
+ def api_get_list_names(self):
+ table = self.tables['Listdata']
+ results = table.select().execute()
+ return [(row[table.c.list_name], row[table.c.host_name])
+ for row in results.fetchall()]
+
dbcontext = DBContext()
Modified: branches/tmp-sqlalchemy-branch/Mailman/database/listdata.py
===================================================================
--- branches/tmp-sqlalchemy-branch/Mailman/database/listdata.py 2006-12-12
03:58:06 UTC (rev 8117)
+++ branches/tmp-sqlalchemy-branch/Mailman/database/listdata.py 2006-12-27
23:45:41 UTC (rev 8118)
@@ -25,9 +25,10 @@
table = Table(
'Listdata', metadata,
# Attributes not directly modifiable via the web u/i
- Column('list_id', Integer, primary_key=True),
- Column('list_name', Unicode),
- Column('web_page_url', Unicode),
+ Column('list_id', Integer, primary_key=True),
+ Column('list_name', Unicode),
+ Column('web_page_url', Unicode),
+ Column('admin_member_chunksize', Integer),
# OldStyleMemberships attributes, temporarily stored as pickles.
Column('bounce_info', PickleType),
Column('delivery_status', PickleType),
@@ -119,6 +120,7 @@
Column('owner', PickleType),
Column('pass_filename_extensions', PickleType),
Column('pass_mime_types', PickleType),
+ Column('password', Unicode),
Column('personalize', Integer),
Column('preferred_language', Unicode),
Column('private_roster', Boolean),
Modified: branches/tmp-sqlalchemy-branch/Mailman/htmlformat.py
===================================================================
--- branches/tmp-sqlalchemy-branch/Mailman/htmlformat.py 2006-12-12
03:58:06 UTC (rev 8117)
+++ branches/tmp-sqlalchemy-branch/Mailman/htmlformat.py 2006-12-27
23:45:41 UTC (rev 8118)
@@ -36,12 +36,11 @@
# Format an arbitrary object.
def HTMLFormatObject(item, indent):
"Return a presentation of an object, invoking their Format method if any."
- if type(item) == type(''):
- return item
- elif not hasattr(item, "Format"):
- return `item`
- else:
+ if hasattr(item, 'Format'):
return item.Format(indent)
+ if isinstance(item, basestring):
+ return item
+ return str(item)
def CaseInsensitiveKeyedDict(d):
result = {}
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
_______________________________________________
Mailman-checkins mailing list
[email protected]
Unsubscribe:
http://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org