Пример #1
0
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['<mm-digest-radio-button>'] = ""
        replacements['<mm-undigest-radio-button>'] = ""
        replacements['<mm-digest-question-start>'] = '<!-- '
        replacements['<mm-digest-question-end>'] = ' -->'
    else:
        replacements['<mm-digest-radio-button>'] = mlist.FormatDigestButton()
        replacements['<mm-undigest-radio-button>'] = \
                                                   mlist.FormatUndigestButton()
        replacements['<mm-digest-question-start>'] = ''
        replacements['<mm-digest-question-end>'] = ''
    replacements['<mm-plain-digests-button>'] = \
                                              mlist.FormatPlainDigestsButton()
    replacements['<mm-mime-digests-button>'] = mlist.FormatMimeDigestsButton()
    replacements['<mm-subscribe-box>'] = mlist.FormatBox('email', size=30)
    replacements['<mm-subscribe-button>'] = mlist.FormatButton(
        'email-button', text=_('Subscribe'))
    replacements['<mm-new-password-box>'] = mlist.FormatSecureBox('pw')
    replacements['<mm-confirm-password>'] = mlist.FormatSecureBox('pw-conf')
    replacements['<mm-subscribe-form-start>'] = mlist.FormatFormStart(
        'subscribe')
    if mm_cfg.SUBSCRIBE_FORM_SECRET:
        now = str(int(time.time()))
        replacements['<mm-subscribe-form-start>'] += (
            '<input type="hidden" name="sub_form_token" value="%s:%s">\n' %
            (now,
             Utils.sha_new(
                 mm_cfg.SUBSCRIBE_FORM_SECRET + now + mlist.internal_name() +
                 os.environ.get('REMOTE_HOST',
                                os.environ.get('REMOTE_ADDR', 'w.x.y.z'))).
             hexdigest()))
    # Roster form substitutions
    replacements['<mm-roster-form-start>'] = mlist.FormatFormStart('roster')
    replacements['<mm-roster-option>'] = mlist.FormatRosterOptionForUser(lang)
    # Options form substitutions
    replacements['<mm-options-form-start>'] = mlist.FormatFormStart('options')
    replacements['<mm-editing-options>'] = mlist.FormatEditingOption(lang)
    replacements['<mm-info-button>'] = 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['<mm-displang-box>'] = displang
    replacements['<mm-lang-form-start>'] = mlist.FormatFormStart('listinfo')
    replacements['<mm-fullname-box>'] = mlist.FormatBox('fullname', size=30)

    # Do the expansion.
    doc.AddItem(mlist.ParseTags('listinfo.html', replacements, lang))
    print doc.Format()
Пример #2
0
    def create(self, email):
        if self.exists:
            raise ListAlreadyExists

        langs = [mm_cfg.DEFAULT_SERVER_LANGUAGE]
        pw = Utils.MakeRandomPassword()
        pw_hashed = Utils.sha_new(pw).hexdigest()
        urlhost = mm_cfg.DEFAULT_URL_HOST
        host_name = mm_cfg.DEFAULT_EMAIL_HOST
        web_page_url = mm_cfg.DEFAULT_URL_PATTERN % urlhost

        # TODO: Add some atomicity. We should roll back changes using
        #       a try/else if something (like MTA alias update) fails
        #       before the function terminates.

        try:
            oldmask = os.umask(002)
            self.mlist.Create(self.name, email, pw_hashed, langs=langs,
                              emailhost=host_name, urlhost=urlhost)
            self.mlist.preferred_language = langs[0]

            # Reply-To set to list address
            self.mlist.reply_goes_to_list = 2
            self.mlist.reply_to_address = "%s@%s" % (self.list, self.domain)

            # Allow messages from listname@domain
            self.mlist.acceptable_aliases = "%s@%s\n" % (self.list, self.domain)

            self.mlist.subject_prefix = "[%s] " % (self.list)
            self.mlist.msg_footer = ""
            self.mlist.subscribe_policy = 2 # Confirm and approve
            self.mlist.max_message_size = 20480 # 20M

            self.mlist.Save()

        finally:
            os.umask(oldmask)
            self.mlist.Unlock()

        if mm_cfg.MTA:
            modname = 'Mailman.MTA.' + mm_cfg.MTA
            __import__(modname)
            sys.modules[modname].create(self.mlist)

        siteowner = Utils.get_site_email(self.mlist.host_name, 'owner')
        text = Utils.maketext(
            'newlist.txt',
            {'listname'    : self.name,
             'password'    : pw,
             'admin_url'   : self.mlist.GetScriptURL('admin', absolute=1),
             'listinfo_url': self.mlist.GetScriptURL('listinfo', absolute=1),
             'requestaddr' : self.mlist.GetRequestEmail(),
             'siteowner'   : siteowner,
             }, mlist=self.mlist)


        msg = Message.UserNotification(email, siteowner, 'Your new mailing list: %s' % self.name,
                                        text, self.mlist.preferred_language)
        msg.send(self.mlist)
Пример #3
0
def set_list_password(name, password):
    '''
    Set the list admin password
    '''

    l = MailList.MailList(name.lower(), lock=0)
    if len(password) < 1:
        return False, 'Empty passwords are not allowed'
    shapassword = Utils.sha_new(password).hexdigest()
    l.Lock()
    try:
        l.password = shapassword
        l.Save()
    finally:
        l.Unlock()
    return True
Пример #4
0
def create_list(listname):
    """Create an email list.

    **Method**: POST

    **URI**: /v2/lists/<listname>

    **Parameters**:

      * `admin`: email of list admin
      * `password`: list admin password
      * `subscribe_policy`: 1) Confirm; 2) Approval; 3)Confirm and approval.
      Default is Confirm (1)
      * `archive_private`: 0) Public; 1) Private. Default is Public (0) """
    admin = request.forms.get('admin')
    password = request.forms.get('password')
    subscribe_policy = request.forms.get('subscribe_policy', 1)
    archive_private = request.forms.get('archive_private', 0)

    try:
        subscribe_policy = int(subscribe_policy)
        archive_private = int(archive_private)
    except ValueError:
        return jsonify(ERRORS_CODE['InvalidParams'])

    if subscribe_policy < 1 or subscribe_policy > 3:
        subscribe_policy = 1

    if archive_private < 0 or archive_private > 1:
        archive_private = 0

    result = jsonify(ERRORS_CODE['Ok'])

    if password == '':
        return jsonify(ERRORS_CODE['InvalidPassword'])
    else:
        password = Utils.sha_new(password).hexdigest()

    mail_list = MailList.MailList()
    try:
        mail_list.Create(listname, admin, password)
        mail_list.archive_private = archive_private
        mail_list.subscribe_policy = subscribe_policy
        mail_list.Save()
    except (Errors.BadListNameError, AssertionError,
            Errors.MMBadEmailError, Errors.MMListAlreadyExistsError), e:
        result = jsonify(ERRORS_CODE[e.__class__.__name__])
Пример #5
0
def create_list(listname):
    """Create an email list.

    **Method**: PUT

    **URI**: /v3/<listname>

    **Parameters**:

      * `admin`: email of list admin
      * `password`: list admin password
      * `subscribe_policy`: 1) Confirm; 2) Approval; 3)Confirm and approval.
      Default is Confirm (1)
      * `archive_private`: 0) Public; 1) Private. Default is Public (0) """
    admin = request.forms.get('admin')
    password = request.forms.get('password')
    subscribe_policy = request.forms.get('subscribe_policy', 1)
    archive_private = request.forms.get('archive_private', 0)

    try:
        subscribe_policy = int(subscribe_policy)
        archive_private = int(archive_private)
    except ValueError:
        return jsonify(ERRORS_CODE['InvalidParams'])

    if subscribe_policy < 1 or subscribe_policy > 3:
        subscribe_policy = 1

    if archive_private < 0 or archive_private > 1:
        archive_private = 0

    result = jsonify(ERRORS_CODE['Ok'])

    if password == '':
        return jsonify(ERRORS_CODE['InvalidPassword'])
    else:
        password = Utils.sha_new(password).hexdigest()

    mail_list = MailList.MailList()
    try:
        mail_list.Create(listname, admin, password)
        mail_list.archive_private = archive_private
        mail_list.subscribe_policy = subscribe_policy
        mail_list.Save()
    except (Errors.BadListNameError, AssertionError,
            Errors.MMBadEmailError, Errors.MMListAlreadyExistsError), e:
        result = jsonify(ERRORS_CODE[e.__class__.__name__])
Пример #6
0
def process_form(mlist, doc, cgidata, lang):
    listowner = mlist.GetOwnerEmail()
    realname = mlist.real_name
    results = []

    # The email address being subscribed, required
    email = cgidata.getvalue('email', '').strip()
    if not email:
        results.append(_('You must supply a valid email address.'))

    fullname = cgidata.getvalue('fullname', '')
    # Canonicalize the full name
    fullname = Utils.canonstr(fullname, lang)
    # Who was doing the subscribing?
    remote = os.environ.get('HTTP_FORWARDED_FOR',
             os.environ.get('HTTP_X_FORWARDED_FOR',
             os.environ.get('REMOTE_ADDR',
                            'unidentified origin')))
    # Are we checking the hidden data?
    if mm_cfg.SUBSCRIBE_FORM_SECRET:
        now = int(time.time())
        # Try to accept a range in case of load balancers, etc.  (LP: #1447445)
        if remote.find('.') >= 0:
            # ipv4 - drop last octet
            remote1 = 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.
            remote1 = remote.rsplit(':', 1)[0]
        try:
            ftime, fhash = cgidata.getvalue('sub_form_token', '').split(':')
            then = int(ftime)
        except ValueError:
            ftime = fhash = ''
            then = 0
        token = Utils.sha_new(mm_cfg.SUBSCRIBE_FORM_SECRET +
                              ftime +
                              mlist.internal_name() +
                              remote1).hexdigest()
        if ftime and now - then > mm_cfg.FORM_LIFETIME:
            results.append(_('The form is too old.  Please GET it again.'))
        if ftime and now - then < mm_cfg.SUBSCRIBE_FORM_MIN_TIME:
            results.append(
    _('Please take a few seconds to fill out the form before submitting it.'))
        if ftime and token != fhash:
            results.append(
                _("The hidden token didn't match.  Did your IP change?"))
        if not ftime:
            results.append(
    _('There was no hidden token in your submission or it was corrupted.'))
            results.append(_('You must GET the form before submitting it.'))
    # Was an attempt made to subscribe the list to itself?
    if email == mlist.GetListEmail():
        syslog('mischief', 'Attempt to self subscribe %s: %s', email, remote)
        results.append(_('You may not subscribe a list to itself!'))
    # If the user did not supply a password, generate one for him
    password = cgidata.getvalue('pw', '').strip()
    confirmed = cgidata.getvalue('pw-conf', '').strip()

    if not password and not confirmed:
        password = Utils.MakeRandomPassword()
    elif not password or not confirmed:
        results.append(_('If you supply a password, you must confirm it.'))
    elif password <> confirmed:
        results.append(_('Your passwords did not match.'))

    # Get the digest option for the subscription.
    digestflag = cgidata.getvalue('digest')
    if digestflag:
        try:
            digest = int(digestflag)
        except (TypeError, ValueError):
            digest = 0
    else:
        digest = mlist.digest_is_default

    # Sanity check based on list configuration.  BAW: It's actually bogus that
    # the page allows you to set the digest flag if you don't really get the
    # choice. :/
    if not mlist.digestable:
        digest = 0
    elif not mlist.nondigestable:
        digest = 1

    if results:
        print_results(mlist, ERRORSEP.join(results), doc, lang)
        return

    # If this list has private rosters, we have to be careful about the
    # message that gets printed, otherwise the subscription process can be
    # used to mine for list members.  It may be inefficient, but it's still
    # possible, and that kind of defeats the purpose of private rosters.
    # We'll use this string for all successful or unsuccessful subscription
    # results.
    if mlist.private_roster == 0:
        # Public rosters
        privacy_results = ''
    else:
        privacy_results = _("""\
Your subscription request has been received, and will soon be acted upon.
Depending on the configuration of this mailing list, your subscription request
may have to be first confirmed by you via email, or approved by the list
moderator.  If confirmation is required, you will soon get a confirmation
email which contains further instructions.""")

    try:
        userdesc = UserDesc(email, fullname, password, digest, lang)
        mlist.AddMember(userdesc, remote)
        results = ''
    # Check for all the errors that mlist.AddMember can throw options on the
    # web page for this cgi
    except Errors.MembershipIsBanned:
        results = _("""The email address you supplied is banned from this
        mailing list.  If you think this restriction is erroneous, please
        contact the list owners at %(listowner)s.""")
    except Errors.MMBadEmailError:
        results = _("""\
The email address you supplied is not valid.  (E.g. it must contain an
`@'.)""")
    except Errors.MMHostileAddress:
        results = _("""\
Your subscription is not allowed because the email address you gave is
insecure.""")
    except Errors.MMSubscribeNeedsConfirmation:
        # Results string depends on whether we have private rosters or not
        if privacy_results:
            results = privacy_results
        else:
            results = _("""\
Confirmation from your email address is required, to prevent anyone from
subscribing you without permission.  Instructions are being sent to you at
%(email)s.  Please note your subscription will not start until you confirm
your subscription.""")
    except Errors.MMNeedApproval, x:
        # Results string depends on whether we have private rosters or not
        if privacy_results:
            results = privacy_results
        else:
            # We need to interpolate into x.__str__()
            x = _(str(x))
            results = _("""\
Your subscription request was deferred because %(x)s.  Your request has been
forwarded to the list moderator.  You will receive email informing you of the
moderator's decision when they get to your request.""")
Пример #7
0
         # ipv4 - drop last octet
         remote1 = 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.
         remote1 = remote.rsplit(':', 1)[0]
     try:
         ftime, fcaptcha_idx, fhash = cgidata.getfirst('sub_form_token', '').split(':')
         then = int(ftime)
     except ValueError:
         ftime = fcaptcha_idx = fhash = ''
         then = 0
     token = Utils.sha_new(mm_cfg.SUBSCRIBE_FORM_SECRET + ":" +
                           ftime + ":" +
                           fcaptcha_idx + ":" +
                           mlist.internal_name() + ":" +
                           remote1).hexdigest()
     if ftime and now - then > mm_cfg.FORM_LIFETIME:
         results.append(_('The form is too old.  Please GET it again.'))
     if ftime and now - then < mm_cfg.SUBSCRIBE_FORM_MIN_TIME:
         results.append(
 _('Please take a few seconds to fill out the form before submitting it.'))
     if ftime and token != fhash:
         results.append(
             _("The hidden token didn't match.  Did your IP change?"))
     if not ftime:
         results.append(
 _('There was no hidden token in your submission or it was corrupted.'))
         results.append(_('You must GET the form before submitting it.'))
 # Check captcha
Пример #8
0
def ssha_password(password):
    salt = os.urandom(SALT_LENGTH)
    h = Utils.sha_new(password)
    h.update(salt)
    return '{SSHA}' + base64.b64encode(h.digest() + salt)
Пример #9
0
def sha_password(password):
    h = Utils.sha_new(password)
    return '{SHA}' + base64.b64encode(h.digest())
Пример #10
0
def ssha_password(password):
    salt = os.urandom(SALT_LENGTH)
    h = Utils.sha_new(password)
    h.update(salt)
    return '{SSHA}' + base64.b64encode(h.digest() + salt)
Пример #11
0
def sha_password(password):
    h = Utils.sha_new(password)
    return '{SHA}' + base64.b64encode(h.digest())
Пример #12
0
def process_form(mlist, doc, cgidata, lang):
    listowner = mlist.GetOwnerEmail()
    realname = mlist.real_name
    results = []

    # The email address being subscribed, required
    email = cgidata.getvalue('email', '').strip()
    if not email:
        results.append(_('You must supply a valid email address.'))

    fullname = cgidata.getvalue('fullname', '')
    # Canonicalize the full name
    fullname = Utils.canonstr(fullname, lang)
    # Who was doing the subscribing?
    remote = os.environ.get(
        'REMOTE_HOST', os.environ.get('REMOTE_ADDR', 'unidentified origin'))
    # Are we checking the hidden data?
    if mm_cfg.SUBSCRIBE_FORM_SECRET:
        now = int(time.time())
        try:
            ftime, fhash = cgidata.getvalue('sub_form_token', '').split(':')
            then = int(ftime)
        except ValueError:
            ftime = fhash = ''
            then = now
        token = Utils.sha_new(mm_cfg.SUBSCRIBE_FORM_SECRET + ftime +
                              mlist.internal_name() + remote).hexdigest()
        if now - then > mm_cfg.FORM_LIFETIME:
            results.append(_('The form is too old.  Please GET it again.'))
        if now - then < mm_cfg.SUBSCRIBE_FORM_MIN_TIME:
            results.append(
                _('Please take a few seconds to fill out the form before submitting it.'
                  ))
        if token != fhash:
            results.append(_('You must GET the form before submitting it.'))
    # Was an attempt made to subscribe the list to itself?
    if email == mlist.GetListEmail():
        syslog('mischief', 'Attempt to self subscribe %s: %s', email, remote)
        results.append(_('You may not subscribe a list to itself!'))
    # If the user did not supply a password, generate one for him
    password = cgidata.getvalue('pw', '').strip()
    confirmed = cgidata.getvalue('pw-conf', '').strip()

    if not password and not confirmed:
        password = Utils.MakeRandomPassword()
    elif not password or not confirmed:
        results.append(_('If you supply a password, you must confirm it.'))
    elif password <> confirmed:
        results.append(_('Your passwords did not match.'))

    # Get the digest option for the subscription.
    digestflag = cgidata.getvalue('digest')
    if digestflag:
        try:
            digest = int(digestflag)
        except ValueError:
            digest = 0
    else:
        digest = mlist.digest_is_default

    # Sanity check based on list configuration.  BAW: It's actually bogus that
    # the page allows you to set the digest flag if you don't really get the
    # choice. :/
    if not mlist.digestable:
        digest = 0
    elif not mlist.nondigestable:
        digest = 1

    if results:
        print_results(mlist, ERRORSEP.join(results), doc, lang)
        return

    # If this list has private rosters, we have to be careful about the
    # message that gets printed, otherwise the subscription process can be
    # used to mine for list members.  It may be inefficient, but it's still
    # possible, and that kind of defeats the purpose of private rosters.
    # We'll use this string for all successful or unsuccessful subscription
    # results.
    if mlist.private_roster == 0:
        # Public rosters
        privacy_results = ''
    else:
        privacy_results = _("""\
Your subscription request has been received, and will soon be acted upon.
Depending on the configuration of this mailing list, your subscription request
may have to be first confirmed by you via email, or approved by the list
moderator.  If confirmation is required, you will soon get a confirmation
email which contains further instructions.""")

    try:
        userdesc = UserDesc(email, fullname, password, digest, lang)
        mlist.AddMember(userdesc, remote)
        results = ''
    # Check for all the errors that mlist.AddMember can throw options on the
    # web page for this cgi
    except Errors.MembershipIsBanned:
        results = _("""The email address you supplied is banned from this
        mailing list.  If you think this restriction is erroneous, please
        contact the list owners at %(listowner)s.""")
    except Errors.MMBadEmailError:
        results = _("""\
The email address you supplied is not valid.  (E.g. it must contain an
`@'.)""")
    except Errors.MMHostileAddress:
        results = _("""\
Your subscription is not allowed because the email address you gave is
insecure.""")
    except Errors.MMSubscribeNeedsConfirmation:
        # Results string depends on whether we have private rosters or not
        if privacy_results:
            results = privacy_results
        else:
            results = _("""\
Confirmation from your email address is required, to prevent anyone from
subscribing you without permission.  Instructions are being sent to you at
%(email)s.  Please note your subscription will not start until you confirm
your subscription.""")
    except Errors.MMNeedApproval, x:
        # Results string depends on whether we have private rosters or not
        if privacy_results:
            results = privacy_results
        else:
            # We need to interpolate into x.__str__()
            x = _(str(x))
            results = _("""\
Your subscription request was deferred because %(x)s.  Your request has been
forwarded to the list moderator.  You will receive email informing you of the
moderator's decision when they get to your request.""")
Пример #13
0
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['<mm-digest-radio-button>'] = ""
        replacements['<mm-undigest-radio-button>'] = ""
        replacements['<mm-digest-question-start>'] = '<!-- '
        replacements['<mm-digest-question-end>'] = ' -->'
    else:
        replacements['<mm-digest-radio-button>'] = mlist.FormatDigestButton()
        replacements['<mm-undigest-radio-button>'] = \
                                                   mlist.FormatUndigestButton()
        replacements['<mm-digest-question-start>'] = ''
        replacements['<mm-digest-question-end>'] = ''
    replacements['<mm-plain-digests-button>'] = \
                                              mlist.FormatPlainDigestsButton()
    replacements['<mm-mime-digests-button>'] = mlist.FormatMimeDigestsButton()
    replacements['<mm-subscribe-box>'] = mlist.FormatBox('email', size=30)
    replacements['<mm-subscribe-button>'] = mlist.FormatButton(
        'email-button', text=_('Subscribe'))
    replacements['<mm-new-password-box>'] = mlist.FormatSecureBox('pw')
    replacements['<mm-confirm-password>'] = mlist.FormatSecureBox('pw-conf')
    replacements['<mm-subscribe-form-start>'] = 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]
        replacements['<mm-subscribe-form-start>'] += (
            '<input type="hidden" name="sub_form_token" value="%s:%s">\n' %
            (now,
             Utils.sha_new(mm_cfg.SUBSCRIBE_FORM_SECRET + now +
                           mlist.internal_name() + remote).hexdigest()))
    # Roster form substitutions
    replacements['<mm-roster-form-start>'] = mlist.FormatFormStart('roster')
    replacements['<mm-roster-option>'] = mlist.FormatRosterOptionForUser(lang)
    # Options form substitutions
    replacements['<mm-options-form-start>'] = mlist.FormatFormStart('options')
    replacements['<mm-editing-options>'] = mlist.FormatEditingOption(lang)
    replacements['<mm-info-button>'] = 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['<mm-displang-box>'] = displang
    replacements['<mm-lang-form-start>'] = mlist.FormatFormStart('listinfo')
    replacements['<mm-fullname-box>'] = mlist.FormatBox('fullname', size=30)
    # If reCAPTCHA is enabled, display its user interface
    if mm_cfg.RECAPTCHA_SITE_KEY:
        replacements['<mm-recaptcha-ui>'] = ("""<tr><td>&nbsp;</td><td>
            <script src="https://www.google.com/recaptcha/api.js?hl=%s">
            </script>
            <div class="g-recaptcha" data-sitekey="%s"></div>
            </td></tr>""" % (lang, mm_cfg.RECAPTCHA_SITE_KEY))
    else:
        replacements['<mm-recaptcha-ui>'] = ''

    # Do the expansion.
    doc.AddItem(mlist.ParseTags('listinfo.html', replacements, lang))
    print doc.Format()
Пример #14
0
def process_form(mlist, doc, cgidata, lang):
    listowner = mlist.GetOwnerEmail()
    realname = mlist.real_name
    results = []

    # The email address being subscribed, required
    email = cgidata.getfirst('email', '').strip()
    if not email:
        results.append(_('You must supply a valid email address.'))

    fullname = cgidata.getfirst('fullname', '')
    # Canonicalize the full name
    fullname = Utils.canonstr(fullname, lang)
    # Who was doing the subscribing?
    remote = os.environ.get('HTTP_FORWARDED_FOR',
             os.environ.get('HTTP_X_FORWARDED_FOR',
             os.environ.get('REMOTE_ADDR',
                            'unidentified origin')))

    # Check reCAPTCHA submission, if enabled
    if mm_cfg.RECAPTCHA_SECRET_KEY:
        request = urllib2.Request(
            url = 'https://www.google.com/recaptcha/api/siteverify',
            data = urllib.urlencode({
                'secret': mm_cfg.RECAPTCHA_SECRET_KEY,
                'response': cgidata.getvalue('g-recaptcha-response', ''),
                'remoteip': remote}))
        try:
            httpresp = urllib2.urlopen(request)
            captcha_response = json.load(httpresp)
            httpresp.close()
            if not captcha_response['success']:
                e_codes = COMMASPACE.join(captcha_response['error-codes'])
                results.append(_('reCAPTCHA validation failed: %(e_codes)s'))
        except urllib2.URLError as e:
            e_reason = e.reason
            results.append(_('reCAPTCHA could not be validated: %(e_reason)s'))

    # Are we checking the hidden data?
    if mm_cfg.SUBSCRIBE_FORM_SECRET:
        now = int(time.time())
        # Try to accept a range in case of load balancers, etc.  (LP: #1447445)
        if remote.find('.') >= 0:
            # ipv4 - drop last octet
            remote1 = 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.
            remote1 = remote.rsplit(':', 1)[0]
        try:
            ftime, fhash = cgidata.getfirst('sub_form_token', '').split(':')
            then = int(ftime)
        except ValueError:
            ftime = fhash = ''
            then = 0
        token = Utils.sha_new(mm_cfg.SUBSCRIBE_FORM_SECRET +
                              ftime +
                              mlist.internal_name() +
                              remote1).hexdigest()
        if ftime and now - then > mm_cfg.FORM_LIFETIME:
            results.append(_('The form is too old.  Please GET it again.'))
        if ftime and now - then < mm_cfg.SUBSCRIBE_FORM_MIN_TIME:
            results.append(
    _('Please take a few seconds to fill out the form before submitting it.'))
        if ftime and token != fhash:
            results.append(
                _("The hidden token didn't match.  Did your IP change?"))
        if not ftime:
            results.append(
    _('There was no hidden token in your submission or it was corrupted.'))
            results.append(_('You must GET the form before submitting it.'))
    # Was an attempt made to subscribe the list to itself?
    if email == mlist.GetListEmail():
        syslog('mischief', 'Attempt to self subscribe %s: %s', email, remote)
        results.append(_('You may not subscribe a list to itself!'))
    # If the user did not supply a password, generate one for him
    password = cgidata.getfirst('pw', '').strip()
    confirmed = cgidata.getfirst('pw-conf', '').strip()

    if not password and not confirmed:
        password = Utils.MakeRandomPassword()
    elif not password or not confirmed:
        results.append(_('If you supply a password, you must confirm it.'))
    elif password <> confirmed:
        results.append(_('Your passwords did not match.'))

    # Get the digest option for the subscription.
    digestflag = cgidata.getfirst('digest')
    if digestflag:
        try:
            digest = int(digestflag)
        except (TypeError, ValueError):
            digest = 0
    else:
        digest = mlist.digest_is_default

    # Sanity check based on list configuration.  BAW: It's actually bogus that
    # the page allows you to set the digest flag if you don't really get the
    # choice. :/
    if not mlist.digestable:
        digest = 0
    elif not mlist.nondigestable:
        digest = 1

    if results:
        print_results(mlist, ERRORSEP.join(results), doc, lang)
        return

    # If this list has private rosters, we have to be careful about the
    # message that gets printed, otherwise the subscription process can be
    # used to mine for list members.  It may be inefficient, but it's still
    # possible, and that kind of defeats the purpose of private rosters.
    # We'll use this string for all successful or unsuccessful subscription
    # results.
    if mlist.private_roster == 0:
        # Public rosters
        privacy_results = ''
    else:
        privacy_results = _("""\
Your subscription request has been received, and will soon be acted upon.
Depending on the configuration of this mailing list, your subscription request
may have to be first confirmed by you via email, or approved by the list
moderator.  If confirmation is required, you will soon get a confirmation
email which contains further instructions.""")

    try:
        userdesc = UserDesc(email, fullname, password, digest, lang)
        mlist.AddMember(userdesc, remote)
        results = ''
    # Check for all the errors that mlist.AddMember can throw options on the
    # web page for this cgi
    except Errors.MembershipIsBanned:
        results = _("""The email address you supplied is banned from this
        mailing list.  If you think this restriction is erroneous, please
        contact the list owners at %(listowner)s.""")
    except Errors.MMBadEmailError:
        results = _("""\
The email address you supplied is not valid.  (E.g. it must contain an
`@'.)""")
    except Errors.MMHostileAddress:
        results = _("""\
Your subscription is not allowed because the email address you gave is
insecure.""")
    except Errors.MMSubscribeNeedsConfirmation:
        # Results string depends on whether we have private rosters or not
        if privacy_results:
            results = privacy_results
        else:
            results = _("""\
Confirmation from your email address is required, to prevent anyone from
subscribing you without permission.  Instructions are being sent to you at
%(email)s.  Please note your subscription will not start until you confirm
your subscription.""")
    except Errors.MMNeedApproval, x:
        # Results string depends on whether we have private rosters or not
        if privacy_results:
            results = privacy_results
        else:
            # We need to interpolate into x.__str__()
            x = _(str(x))
            results = _("""\
Your subscription request was deferred because %(x)s.  Your request has been
forwarded to the list moderator.  You will receive email informing you of the
moderator's decision when they get to your request.""")
Пример #15
0
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['<mm-digest-radio-button>'] = ""
        replacements['<mm-undigest-radio-button>'] = ""
        replacements['<mm-digest-question-start>'] = '<!-- '
        replacements['<mm-digest-question-end>'] = ' -->'
    else:
        replacements['<mm-digest-radio-button>'] = mlist.FormatDigestButton()
        replacements['<mm-undigest-radio-button>'] = \
                                                   mlist.FormatUndigestButton()
        replacements['<mm-digest-question-start>'] = ''
        replacements['<mm-digest-question-end>'] = ''
    replacements['<mm-plain-digests-button>'] = \
                                              mlist.FormatPlainDigestsButton()
    replacements['<mm-mime-digests-button>'] = mlist.FormatMimeDigestsButton()
    replacements['<mm-subscribe-box>'] = mlist.FormatBox('email', size=30)
    replacements['<mm-subscribe-button>'] = mlist.FormatButton(
        'email-button', text=_('Subscribe'))
    replacements['<mm-new-password-box>'] = mlist.FormatSecureBox('pw')
    replacements['<mm-confirm-password>'] = mlist.FormatSecureBox('pw-conf')
    replacements['<mm-subscribe-form-start>'] = mlist.FormatFormStart(
        'subscribe')
    if mm_cfg.SUBSCRIBE_FORM_SECRET:
        now = str(int(time.time()))
        remote = os.environ.get('REMOTE_HOST',
                                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]
        replacements['<mm-subscribe-form-start>'] += (
                '<input type="hidden" name="sub_form_token" value="%s:%s">\n'
                % (now, Utils.sha_new(mm_cfg.SUBSCRIBE_FORM_SECRET +
                          now +
                          mlist.internal_name() +
                          remote
                          ).hexdigest()
                    )
                )
    # Roster form substitutions
    replacements['<mm-roster-form-start>'] = mlist.FormatFormStart('roster')
    replacements['<mm-roster-option>'] = mlist.FormatRosterOptionForUser(lang)
    # Options form substitutions
    replacements['<mm-options-form-start>'] = mlist.FormatFormStart('options')
    replacements['<mm-editing-options>'] = mlist.FormatEditingOption(lang)
    replacements['<mm-info-button>'] = 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['<mm-displang-box>'] = displang
    replacements['<mm-lang-form-start>'] = mlist.FormatFormStart('listinfo')
    replacements['<mm-fullname-box>'] = mlist.FormatBox('fullname', size=30)

    # Do the expansion.
    doc.AddItem(mlist.ParseTags('listinfo.html', replacements, lang))
    print doc.Format()