summaryrefslogtreecommitdiff
path: root/Mailman/Cgi/admin.py
Commit message (Collapse)AuthorAgeFilesLines
...
* Changes to fix the CGI cookie security flaw reported by John Morton.hmeland1999-06-111-2/+2
| | | | | | | | | SecurityManager: New functions MakeCookie() and CheckCookie(). These functions work with cookies containing cookie creation and expire time, the client's IP number, and a checksum hash of these values as well as a secret (the lists (encrypted) admin password). admin.py, admindb.py and private.py: isAuthenticated now uses these new cookie functions.
* Changes to speed up mass subscription via the web:hmeland1999-06-041-27/+28
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | MailList.py: Changed MailList.SetUserOption() to take a `save_list' keyword argument (defaulting to true). When false, SetUserOption won't do self.Save() after changing the option. New function MailList.ApprovedAddMembers() (note plural) that takes a list of prospective new list members (and possibly a list of corresponding passwords), and does _all_ the necessary list changes before saving the list configuration. Empty passwords are substituted with randomly generated ones. Returns a dict with {address: exception_tuple} entries -- exception_tuple is either None or a two-element tuple containing the first exception type and value raised when trying to add address. The exception traceback object isn't included in the returned dict, because a) I don't think it is very useful for the relevant exceptions, and b) using it wrongly could cause some fuzz with Python's garbage collector -- i.e. we would leak memory. Changed MailList.ApprovedAddMember() to be a mere wrapper, calling the new ApprovedAddMembers() function and reraising any exception in the returned dict. Also made the logic of the code doing subject prefixing a bit clearer, and changed MailList.aside_new() so that list's config.db files are saved with umask 007 (as they contain all list members' passwords in clear text). Utils.py: New function MakeRandomPassword(length=4), used by MailList.ApprovedAddMembers() whenever empty passwords are found. The default random password length should possibly be made site configurable. Also, fixed an error in the _badchars regular expression -- the final "," was probably meant to be inside the character set. Cgi/admin.py: Changed ChangeOptions() to use the new MailList.ApprovedAddMembers() function.
* Catch Errors.MMNoSuchUserError when unsubscribing, so that alreadyhmeland1999-04-211-3/+11
| | | | | | unsubscribed addresses doesn't generate tracebacks. Failed unsubscribes are listed on the top of the admin page generated after submitting.
* Sweeping changes to hopefully and finally (for 1.0 at least) make sanebwarsaw1999-03-291-2/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | address case matching. These changes require the DATA_FILE_VERSION to be bumped, which should auto-update your config.db files. I sure hope this works correctly! Details of changes: MailList.GetUserSubscribedAddress(): New method. If the address is a member, this returns the case-preserved address the user is subscribed with. If not a member, None is returned. MailList.GetUserCanonicalAddress(): New method. If the address is a member, this returns the lowercased address the user is subscribed with. If not a member, None is returned. MailList.FindUser(): Wrote down, in a big comment, the constraints for the dictionaries self.members, self.digest_members, self.passwords. This wasn't always followed, but now it should be. FindUser() is now also guaranteed to return the lowercased version of the subscribed email address. This wasn't always the case. FindUser() also provides a shortcut for the common case. ApprovedAddMember(): Guarantee that passwords stored in self.passwords are keyed off the lowercased address. Deliverer.MailUserPassword(): Find the user's password using the lowercased version of their address. However, be sure to use their case-preserved address for the recipient of the password email. Digester.SetUserDigest(): Fixed a fairly old bug where a user switching from regular to digest membership (or vice versa) would get their case-preserved address blown away. I don't think there's any way to recover this information, but at least now we properly save it. SecurityManager.ConfirmUserPassword(): Simplified address matching stuff, since we now guarantee that FindUser() will return a lowercased address, and that the passwords dictionary has lowercased keys. FindUser() will return None if the address isn't found, and it also has a built-in shortcut so that the more expensive FindMatchingAddresses() isn't called in the common case. I eliminated the case-insensitive password comparision that Ken rightly questioned in his comment. admin.py: In the list of members, display a member's case-preserved address instead of their lowercased address. Also, obscure the URL in the hyperlink (probably not terribly necessary). handle_opts.py: When the password can't be found (when emailing it), put the address we tried to find in the result message. Makes for better debugging. options.py: Use a better mechanism for finding if the member has a case-preserved address different from their lowercased address.
* FormatMembershipOptions(): To reflect the change that Ken recentlybwarsaw1999-03-241-4/+5
| | | | | | made, we now change the `norcv' option to be `notmetoo'. This is still backwards, but changing the sense of this option is to much work right now. `norcv' is accepted as an alias for `notmetoo'.
* FormatMembershipOptions(): Minor rewording of the `hide' legend entrybwarsaw1999-03-241-2/+2
|
* FormatMembershipOptions(): Two small changes. First, hyperlink thebwarsaw1999-03-241-13/+22
| | | | | | | | user's address, which jumps you to their member info page. Second, reorder the items in the table so that digest comes just before plain. Didn't make sense to separate these two digest related items.
* Don't know how this snuck by, at least a few versions: "bottom at theklm1999-03-161-9/+12
| | | | | | | | | | | | bottom" => "button at the bottom". Sounds somehow obscene the other way, but nonetheless we'd like it to make sense. While i was here i did a few *more* trivial things... Using "not metoo" instead of "norcv" for member's status column headings (and legend), to disambiguate from "nomail"! (I think i recall "metoo" from things like /bin/mail, in any case, it's a lot more descriptive of the intention.) While i'm here i centered all the checkbuttons, which i think looks a lot tidier.
* The password stuff was removed from all but the general page, so iklm1999-03-161-3/+6
| | | | | changed the message so it only says it's at the bottom of the page when it really is.
* Including the total number of members and the display chunk size in theklm1999-03-151-1/+9
| | | | members table [and testing the emailing of this checkin message, as well].
* FormatConfiguration(): Only put the FormatPasswordStuff() on thebwarsaw1999-03-091-1/+2
| | | | `general' category page. The others are just too noisy.
* split a long linebwarsaw1999-03-091-1/+2
|
* Utils.GetRequestURI(): New function, returns the full virtual path thehmeland1999-03-021-2/+2
| | | | | | | | | | calling CGI script was invoked with. Uses (non-standard, but convenient) environment variable REQUEST_URI when available, otherwise SCRIPT_NAME and PATH_INFO (which are part of the CGI/1.1 spec) if available, or simply returns optional argument `fallback' (which defaults to None). Cgi/admin.py, Cgi/admindb.py: Use it when generating admin authentication page.
* main(), FormatAdminOverview(): take care of special cases where CGIbwarsaw1999-02-281-3/+4
| | | | extension needs to be added to script path.
* ChangeOptions(): In `subscribees' section, ValidateEmail() now handlesbwarsaw1999-01-091-9/+2
| | | | | catching blank lines, so we can (mostly) get rid of the special treatment here.
* GetValidValue(): Use new ValidateEmail() interface andbwarsaw1999-01-091-12/+9
| | | | | | | | EmailAddressError, and clean up logic. ChangeOptions(): In the `subscribees' section, add a call to ValidateEmail() so that invalid email addresses can't be added in the Membership Management text window.
* main(): in previous VARHELP workaround, QUERY_STRING could exist butbwarsaw1999-01-091-3/+4
| | | | be an empty string.
* main(): Kludge-around for accessing variable details when cookies arebwarsaw1999-01-081-13/+23
| | | | | | | | | | | | | | disabled. The problem: because cookies are disabled, the admin has to authenticate for each access. We can't change this because otherwise option values could leak. So when the admin fills in the password and clicks `let me in...', the form gets POSTed, and even those the variable to get details on is given in the form's ACTION, cgi.py ignores any QUERY_STRING on a POST. Maybe cgi.py should be fixed? In the meantime, we just watch for the FieldStorage having a `request_login' field and a QUERY_STRING environment variable. In that case, we manually parse out the query string and use its value if available.
* FormatMembershipOptions(): Changes to the table that gets built tobwarsaw1998-12-301-8/+28
| | | | | | make it much more readable. First, use bare checkboxes and column headers for what used to be the checkbox labels. Put a border around the table. Add a legend for what the column headers mean.
* In `subscribees' section, parse address through Utils.ParseAddrs() sobwarsaw1998-12-301-0/+1
| | | | | the success notification specifies the address instead of any other goo.
* ChangeOptions(): Rework the test for empty or whitespace-only blankbwarsaw1998-12-291-8/+18
| | | | line in mass subscribe dialog. The old way didn't really work.
* GetValidValue(): Fixed small bug in return value of mm_cfg.Numberbwarsaw1998-12-291-0/+1
| | | | converter
* GetValidValue(): Zap another case of eval() for string->number conversion.bwarsaw1998-12-291-7/+11
|
* GetValidValue(): Don't use eval() to turn a string into an int, usebwarsaw1998-12-291-4/+3
| | | | int() -- it's safer.
* These changes represent the changes that make mailman's addressingcotton1998-11-211-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | work like unix mail: username portions of addresses are case-preserved for delivery only. All other address comparisons are lowercase. up'd data version in Defaults to 13 ** MailList.py: added an __AddMember method that takes an address and whether or not it is a digest address as args and populates the member dictionary like this: if string.lower(addr) == LCDomain(addr): member_dict[addr] = 0 else: member_dictp[string.lower(addr)] == LCDomain(addr) added .GetDeliveryMembers() and .GetDigestDeliveryMembers() methods for use by posting and digest delivery mechanisms. changed a nested def portion in Post to use an explicit loop. **Digester.py: uses .GetDigestDeliveryMembers instead of .GetDigestMembers(). **Utils.py: address comparisons are lc. **versions.py: populate the member dicts according to the above formula. **Cgi/admin.py: fixed a bug introduced from the first change to using member dictionaries: all members were showing up as digest members on the admin membership page. changed a dict.get to dict.has_key to fix this. NOTE: this code is tested only insofar as I posted and poked around on the cgi's a bit, and let lists do the versions code. These changes should be tested more, but I *have* to go now and wanted to check them in before someone made it difficult to do so by changing stuff tomarrow, cause i'm gone all day tomarrow. scott
* I should have broken this up into 2 checkins because it implements onecotton1998-11-211-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | fix and one addition. Sorry, i realized that too late. This change adds another list conifg variable "admin_notify_mchanges", which is a boolean 0 or 1 and specifies whether or not the list admin gets notifications of subscriptions and unsubscriptions. The functions MailList.DeleteMember and MailList.ApprovedAddMember trigger the delivery if it is turned on for the list or passed in as an optional argument. This way, it is the duty of programs/code that do mass subscriptions/unsubscriptions where this notification may not be appropriate to specify that in the call to .DeleteMember or .ApprovedAddMember. There are 2 new templates, adminsubscribeack.txt and adminunsubscribeack.txt which are used in sending these notifications. Defaults.py.in has a variable "DEFAULT_ADMIN_NOTIFY_MCHANGES" which is set to 0 so that old lists will act the same by default, and the data version is up'ed to 12. versions.py sets the variable if it's not already there for a list. The config info for the admin cgi program for this new variable is set right after the variable for immediate notifications. The second change is a fix where ApprovedAddMember was calling a "self.Save()", which made mass subscribe situiations really far too slow. I removed the .Save() from there and added it to the more outer level code in the following places: bin/convert_list Mailman/ListAdmin.py Mailman/MailCommandHandler.py Mailman/Cgi/admin.py Note that since AddMember can trigger a call to ApprovedAddMember, all the places where AddMember is called needed a .Save() added as well. I need to add a call to .Save() for Mailman/Cgi/subscribe.py as well and will do that in a moment. scott
* Cleaned up the change-password table so it looks a bit nicer, andklm1998-11-211-31/+50
| | | | | | | | | | | | | tabbing between entry fields goes in the right sequence. (In the process i separated out the formatting for the Submit button, and i'm wondering whether it makes sense to put a copy of it above the table, as well as below - it can be handy to not have to go to the end of the page to submit. Unfortunately, it looks ugly hanging out up top!) As ever, wrapped a bunch of long lines. Trimmed some odd whitespace (extending beyond margin) at the end of a line.
* This change implements storing list members and digest members ascotton1998-11-191-18/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | dicts instead of lists, which optimizes Utils.FindMatchingAddresses and general membership management, especially for large lists. MailList.py now supplies .GetMembers() and .GetDigestMembers() to supply the data in list form to anything that needs it that way. An new install showed this worked fine with some cursory testing of the cgi's and interactive poking around. A detailed listing of the changes follows: Mailman/Defaults.py.in: change data version to 11 Mailman/Digester.py: initvars now instantiates digest_members as {} instead of [] lines 113-114 and 121-122 now use del This change implements storing list members and digest members as dicts instead of lists, which optimizes Utils.FindMatchingAddresses and general membership management, especially for large lists. MailList.py now supplies .GetMembers() and .GetDigestMembers() to supply the data in list form to anything that needs it that way. Though INSTALL shows up on the changed files section, a diff a few seconds ago didn't show any differences in that file, so I hope nobody changed it in the interim. An new install showed this worked fine with some cursory testing of the cgi's and interactive poking around. A detailed listing of the changes follows: Mailman/Defaults.py.in: change data version to 11 Mailman/Digester.py: initvars now instantiates digest_members as {} instead of [] lines 113-114 and 121-122 now use del list.[digest_]member instead of list.[digest_]members.remove when figuring who to actually send digests to, use list.GetDigestMembers() instead of list.digest_members. Mailman/HTMLFormatter: now uses list.Get[Digest]Members to get subscribers, and length of digested subscribers and regular members MailCommandHandler, SecurityManager,Cgi/handle_opts, Cgi/options: all simple replacements of list.[digest_]members with list.Get[Digest]Members(). Mailman/Cgi/admin.py: mostly simple replacements of list.[digest_]members with the Get..() methods, however, the membership management section now works much quicker and changes digest->nodigest subscriptions via dictionary manipulations. Mailman/versions.py: updates lists to use dicts and changed list.[digest_]members to use the list.Get[Digest]Members() methods. Mailman/Utils.py: added a function "GetPossibleMatchingAddresses" which when fed an address, returns the list of addresses that "smart" address matching would match. changed FindMatchingAddresses(name, list) to use a new signature: FindMatchingAddresses(name, *dicts), where dicts is a list of dictionaries keyed by addresses. Just realized that this would better be FindMatchingAddresses(name, dict, *dicts) so that it enforces atleast 2 args... I'll make that change in a sec. All uses of FindMatchingAddresses have been changed to fit the new arguments. scott ----:**-F1 cvs30458aaa 1:12PM 0.98 Mail (Text Fill)--L59--32%------------------------------------------- ?
* made it use %s/%s instead of os.path.join forcotton1998-11-091-3/+3
| | | | | 2 spots changed: lines 220 and 401 scott
* changed the site site variable ADMIN_MEMBER_CHUNKSIZE to a per-listcotton1998-10-231-2/+2
| | | | | | | | | | | | | | | | | variable (admin_member_chunksize). this is not yet settable by means of cgi, but you can set it at an interactive python session. This is a start on making the membership management part of the admin cgi scalable for really big lists. details: * up'd DATA_FILE_VERSION in Mailman/Defaults.py.in * replaced ADMIN_MEMBER_CHUNKSIZE with DEFAULT_ADMIN_MEMBER_CHUNKSIZE in Mailman/Defaults.py.in. * added a list variable assignment in Mailman.MailList.InitVars * added code to add the admin_member_chunksize attribute to a list when versions change in Mailman/versions.py * made admin.py format members according to list.admin_member_chunksize instead of mm_cfg.ADMIN_MEMBER_CHUNKSIZE scott
* corrected misspelling of "address".cotton1998-10-201-1/+1
| | | | scott
* This is the same typo fix that john checked in the other day which preventedcotton1998-10-141-1/+1
| | | | | | listowners from unsubscribing digest members. I don't know how it got back in the code! scott
* added option to override list value for wend_welcome_msg when mass subscribing.cotton1998-10-111-3/+13
| | | | scott
* Better check this in while I'm thinking about it ;-)viega1998-10-111-1/+1
| | | | | Fixed a typo that prevented digestified users from unsubscribing via the web.
* These changing are a cleanup of the sorry state the subscription policycotton1998-10-101-6/+22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | was in (which was largely my fault from before). Before: 1) web_subscribe_requires_confirmation was showing in the admin cgi, but not working. 2) all subscribes that required admin approval were going through the confirmation process. 3) the code implementing the confirmation process was distributed between the subscribe cgi and MailCommandHandler, duplicated in places and disrupting the previous interface to list.AddMember. 4) the open_subscribe variable was confusing because it didn't pay any attention to confirmations. Now, things are organized a little differently, but in a much cleaner way. there is one variable that deals with subscription policy, called "subscribe_policy". It's setting determines what happens with both the web based and the mail based subscriptions. there are 4 options: 0 - open subscribe policy 1 - confirmation required 2 - admin approval required 3 - confirmation and then admin approval required there is a site configuration variable in Defaults.py called ALLOW_OPEN_SUBSCRIBE, which determines whether or not an open subscribe policy is an option. If it's not, the admin cgi interface does not present it as an option. I have restored a slightly modified version of the prior-to-confirmations interface for list.AddMember, where all you have to code is: try: list.AddMember(email, digest, password) except Errors.MMBadEmail: except Errors.MMAlreadySubscribed: [ ... all those other good things it used to check ...] except Errors.MMSubscribeNeedsConfirmation: # the confirmation has already been sent. # so just report accordingly to whatever the ap is. In addition, I have moved the code for processing a confirmation request to MailList.py so that it can be used in both a confirmation cgi (which does not yet exist, but will) and the mailcmd script. it's interface is: try: list.ProcessConfirmation(cookie) except Errors.MMBadConfirmation: # the cookie doesn't correspond to anything except Errors.MMNeedApproval: # the list is set to approve+confirm subscribe_policy. A listing of the changes to the files follows: Mailman/Defaults.in: added ALLOW_OPEN_SUBSCRIBE,DEFAULT_SUBSCRIBE_POLICY deleted DEFAULT_OPEN_SUBSCRIBE, changed DATA_FILE_VERSION to 5 Mailman/Errors.py: added MMBadConfirmation and MMSubscribeNeedsConfirmation Mailman/MailCommandHandler.py: moved the confirmation code to MailList.py and use the new (old) list.AddMember interface MailMan/MailList.py: added .ProcessConfirmation(cookie), changed AddMember to fit new (old) interface. deleted config info for open_subscribe and replaced with config info for subscribe_policy that acts according to mm_cfg.ALLOW_OPEN_SUBSCRIBE. Also made list.ApprovedAddMember's "noack" argument just "ack" for simplicities sake and made it default to None instead of 0 so that if the ack variable isn't passed, it sets it to the value of the lists .send_welcome_msg setting. Mailman/versions.py: added handling for new data file format, replacing open_subscribe with a reasonable value for subscribe_policy based on a combination of what open_subscribe is and what mm_cfg.ALLOW_OPEN_SUBSCRIBE is set to. Mailman/Cgi/admin.py: made the cgi handle the output and processing of subscribe_policy based on the setting of mm_cfg.ALLOW_OPEN_SUBSCRIBE. removed erroneous processing of whether or not to send an ack with mass subscription based on new interface to list.ApprovedAddMember (this processing is to be replaced with a good idea from john -- making mass subscribe have it's own option of whether or not to send welcome messages). Mailman/Cgi/subscribe.py: made backgrounds white, and made it use the MailList.AddMember interface described above. Mailman/Makefile.in: looks like this part of that distclean patch from NAGY didn't make it in yet (rm'ing mm_cfg.py as well as Defaults.py) scott
* whoops, the last fix was backwards.cotton1998-10-091-3/+3
| | | | scott
* fixed bug where mass subscribe wasn't checking whether or not to sendcotton1998-10-091-1/+5
| | | | | welcome message as per the list config. scott
* The cookie mechanism was causing a binascii.error: Incorrect Paddingcotton1998-10-081-12/+6
| | | | | | error to be raised with MSIE on a MAC. I have simplified the encodeing to simply be `hash(list_name)`. scott
* The chunk indices on the membership management page werecotton1998-10-011-4/+4
| | | | | | | broken for lists that didn't use the default /mailman ScriptAlias. admin.py now uses list.GetAbsoluteScriptURL('admin'), which should apply to virtual hosts and other odd configurations scott
* Scott's patch to "path" string interpolation value when REQUEST_URIbwarsaw1998-08-071-1/+2
| | | | doesn't exist (as in older versions of Apache).
* Strip out all logging stuff. This will get taken care of by the CGIbwarsaw1998-07-021-21/+0
| | | | driver.
* Convert all module names to their new names. Import all modules frombwarsaw1998-06-191-66/+42
| | | | | | | | | | | the Mailman package (using the semi-bogus, but quickly implemented from ... import style). Moved the TQS LOGIN_PAGE to a templates file Sundry "maillist" -> "mailing list" Fix crypt imports
* Fixed a typo that probably kept it from loading.viega1998-06-161-4/+3
|
* From the error message, and what I've learned about base64, my bestviega1998-06-141-6/+4
| | | | | | | | | guess about the transient errors (ie, some people get them, some people do not) is that sometimes the base64 encoding can cause \n's to get in the string, which the mime stuff will treat as a newline. So I replace \n w/ @ before putting it in the cookie, and do the reverse before checking the cookie. Hopefully we won't hear about this problem again.
* These are the files that used to be in ../cgi, except they no longerviega1998-06-141-0/+835
handle logging to an error file, and no longer import paths. Also, any checks for __main__ have been removed.