# Copyright (C) 1998-2018 by the Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. """Produce listinfo page, primary web entry-point to mailing lists. """ # No lock needed in this script, because we don't change data. import os import cgi import time from Mailman import mm_cfg from Mailman import Utils from Mailman import MailList from Mailman import Errors from Mailman import i18n from Mailman.htmlformat import * from Mailman.Logging.Syslog import syslog # Set up i18n _ = i18n._ i18n.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE) def main(): parts = Utils.GetPathPieces() if not parts: listinfo_overview() return listname = parts[0].lower() try: mlist = MailList.MailList(listname, lock=0) except Errors.MMListError, e: # Avoid cross-site scripting attacks safelistname = Utils.websafe(listname) # Send this with a 404 status. print 'Status: 404 Not Found' listinfo_overview(_('No such list %(safelistname)s')) syslog('error', 'listinfo: No such list "%s": %s', listname, e) return # See if the user want to see this page in other language cgidata = cgi.FieldStorage() try: language = cgidata.getfirst('language') except TypeError: # Someone crafted a POST with a bad Content-Type:. doc = Document() doc.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE) doc.AddItem(Header(2, _("Error"))) doc.AddItem(Bold(_('Invalid options to CGI script.'))) # Send this with a 400 status. print 'Status: 400 Bad Request' print doc.Format() return if not Utils.IsLanguage(language): language = mlist.preferred_language i18n.set_language(language) list_listinfo(mlist, language) def listinfo_overview(msg=''): # Present the general listinfo overview hostname = Utils.get_domain() # Set up the document and assign it the correct language. The only one we # know about at the moment is the server's default. doc = Document() doc.set_language(mm_cfg.DEFAULT_SERVER_LANGUAGE) legend = _("%(hostname)s Mailing Lists") doc.SetTitle(legend) table = Table(border=0, width="100%") table.AddRow([Center(Header(2, legend))]) table.AddCellInfo(table.GetCurrentRowIndex(), 0, colspan=2, bgcolor=mm_cfg.WEB_HEADER_COLOR) # Skip any mailing lists that isn't advertised. advertised = [] listnames = Utils.list_names() listnames.sort() for name in listnames: try: mlist = MailList.MailList(name, lock=0) except Errors.MMUnknownListError: # The list could have been deleted by another process. continue if mlist.advertised: if mm_cfg.VIRTUAL_HOST_OVERVIEW and ( mlist.web_page_url.find('/%s/' % hostname) == -1 and mlist.web_page_url.find('/%s:' % hostname) == -1): # List is for different identity of this host - skip it. continue else: advertised.append((mlist.GetScriptURL('listinfo'), mlist.real_name, Utils.websafe(mlist.GetDescription()))) if msg: greeting = FontAttr(msg, color="ff5060", size="+1") else: greeting = FontAttr(_('Welcome!'), size='+2') welcome = [greeting] mailmanlink = Link(mm_cfg.MAILMAN_URL, _('Mailman')).Format() if not advertised: welcome.extend( _('''

There currently are no publicly-advertised %(mailmanlink)s mailing lists on %(hostname)s.''')) else: welcome.append( _('''

Below is a listing of all the public mailing lists on %(hostname)s. Click on a list name to get more information about the list, or to subscribe, unsubscribe, and change the preferences on your subscription.''')) # set up some local variables adj = msg and _('right') or '' siteowner = Utils.get_site_email() welcome.extend( (_(''' To visit the general information page for an unadvertised list, open a URL similar to this one, but with a '/' and the %(adj)s list name appended.

List administrators, you can visit '''), Link(Utils.ScriptURL('admin'), _('the list admin overview page')), _(''' to find the management interface for your list.

If you are having trouble using the lists, please contact '''), Link('mailto:' + siteowner, siteowner), '.

')) table.AddRow([apply(Container, welcome)]) table.AddCellInfo(max(table.GetCurrentRowIndex(), 0), 0, colspan=2) if advertised: table.AddRow([' ', ' ']) table.AddRow([Bold(FontAttr(_('List'), size='+2')), Bold(FontAttr(_('Description'), size='+2')) ]) highlight = 1 for url, real_name, description in advertised: table.AddRow( [Link(url, Bold(real_name)), description or Italic(_('[no description available]'))]) if highlight and mm_cfg.WEB_HIGHLIGHT_COLOR: table.AddRowInfo(table.GetCurrentRowIndex(), bgcolor=mm_cfg.WEB_HIGHLIGHT_COLOR) highlight = not highlight doc.AddItem(table) doc.AddItem('


') doc.AddItem(MailmanLogo()) print doc.Format() def list_listinfo(mlist, lang): # Generate list specific listinfo doc = HeadlessDocument() doc.set_language(lang) replacements = mlist.GetStandardReplacements(lang) if not mlist.digestable or not mlist.nondigestable: replacements[''] = "" replacements[''] = "" replacements[''] = '' else: replacements[''] = mlist.FormatDigestButton() replacements[''] = \ mlist.FormatUndigestButton() replacements[''] = '' replacements[''] = '' replacements[''] = \ mlist.FormatPlainDigestsButton() replacements[''] = mlist.FormatMimeDigestsButton() replacements[''] = mlist.FormatBox('email', size=30) replacements[''] = mlist.FormatButton( 'email-button', text=_('Subscribe')) replacements[''] = mlist.FormatSecureBox('pw') replacements[''] = mlist.FormatSecureBox('pw-conf') replacements[''] = mlist.FormatFormStart( 'subscribe') if mm_cfg.SUBSCRIBE_FORM_SECRET: now = str(int(time.time())) remote = os.environ.get('HTTP_FORWARDED_FOR', os.environ.get('HTTP_X_FORWARDED_FOR', os.environ.get('REMOTE_ADDR', 'w.x.y.z'))) # Try to accept a range in case of load balancers, etc. (LP: #1447445) if remote.find('.') >= 0: # ipv4 - drop last octet remote = remote.rsplit('.', 1)[0] else: # ipv6 - drop last 16 (could end with :: in which case we just # drop one : resulting in an invalid format, but it's only # for our hash so it doesn't matter. remote = remote.rsplit(':', 1)[0] # render CAPTCHA, if configured if isinstance(mm_cfg.CAPTCHAS, dict) and 'en' in mm_cfg.CAPTCHAS: (captcha_question, captcha_box, captcha_idx) = \ Utils.captcha_display(mlist, lang, mm_cfg.CAPTCHAS) pre_question = _( """Please answer the following question to prove that you are not a bot:""" ) replacements[''] = ( """%s
%s%s""" % (pre_question, captcha_question, captcha_box)) else: # just to have something to include in the hash below captcha_idx = '' # fill form replacements[''] += ( '\n' % (now, captcha_idx, Utils.sha_new(mm_cfg.SUBSCRIBE_FORM_SECRET + ":" + now + ":" + captcha_idx + ":" + mlist.internal_name() + ":" + remote ).hexdigest() ) ) # Roster form substitutions replacements[''] = mlist.FormatFormStart('roster') replacements[''] = mlist.FormatRosterOptionForUser(lang) # Options form substitutions replacements[''] = mlist.FormatFormStart('options') replacements[''] = mlist.FormatEditingOption(lang) replacements[''] = SubmitButton('UserOptions', _('Edit Options')).Format() # If only one language is enabled for this mailing list, omit the choice # buttons. if len(mlist.GetAvailableLanguages()) == 1: displang = '' else: displang = mlist.FormatButton('displang-button', text = _("View this page in")) replacements[''] = displang replacements[''] = mlist.FormatFormStart('listinfo') replacements[''] = mlist.FormatBox('fullname', size=30) # If reCAPTCHA is enabled, display its user interface if mm_cfg.RECAPTCHA_SITE_KEY: noscript = _('This form requires JavaScript.') replacements[''] = ( """ 
""" % (noscript, lang, mm_cfg.RECAPTCHA_SITE_KEY)) else: replacements[''] = '' # Do the expansion. doc.AddItem(mlist.ParseTags('listinfo.html', replacements, lang)) print doc.Format() if __name__ == "__main__": main()