def get_bool(arg, name=None, default=None): """ For use with values returned from parse_quoted_separated or given as macro parameters, return a boolean from a unicode string. Valid input is 'true'/'false', 'yes'/'no' and '1'/'0' or None for the default value. :param arg: The argument, may be None or a unicode string :param name: Name of the argument, for error messages :param default: default value if arg is None :rtype: boolean or None :returns: the boolean value of the string according to above rules (or default value) """ assert default is None or isinstance(default, bool) if arg is None: return default elif not isinstance(arg, unicode): raise TypeError('Argument must be None or unicode') arg = arg.lower() if arg in [u'0', u'false', u'no']: return False elif arg in [u'1', u'true', u'yes']: return True else: if name: raise ValueError( _('Argument "%(name)s" must be a boolean value, not "%(value)s"', name=name, value=arg)) else: raise ValueError( _('Argument must be a boolean value, not "%(value)s"', value=arg))
def macro(self): request = self.request groups = [] for groupname in defaultconfig.options: groups.append((groupname, True, defaultconfig.options)) for groupname in defaultconfig.options_no_group_name: groups.append( (groupname, False, defaultconfig.options_no_group_name)) groups.sort() result = moin_page.div() for groupname, addgroup, optsdict in groups: heading, desc, opts = optsdict[groupname] result.append( moin_page.h(attrib={moin_page.outline_level: '1'}, children=[heading])) if desc: result.append(moin_page.p(children=[desc])) table = moin_page.table() result.append(table) header = moin_page.table_header() table.append(header) row = moin_page.table_row() header.append(row) for text in [ _('Variable name'), _('Default'), _('Description'), ]: strong_text = moin_page.strong(children=[text]) row.append(moin_page.table_cell(children=[strong_text])) body = moin_page.table_body() table.append(body) opts = list(opts) opts.sort() for name, default, description in opts: if addgroup: name = groupname + '_' + name if isinstance(default, defaultconfig.DefaultExpression): default_txt = default.text else: default_txt = '%r' % (default, ) if len(default_txt) > 30: default_txt = moin_page.span( attrib={moin_page.title: default_txt}, children=['...']) description = _(description or '') row = moin_page.table_row() body.append(row) row.append(moin_page.table_cell(children=[name])) default = moin_page.code(children=[default_txt]) row.append(moin_page.table_cell(children=[default])) row.append(moin_page.table_cell(children=[description])) return result
def stats(self, request, formatter, hitsFrom): """ Return search statistics, formatted with formatter @param request: current request @param formatter: formatter to use @param hitsFrom: current position in the hits @rtype: unicode @return formatted statistics """ if not self.estimated_hits: self.estimated_hits = ('', len(self.hits)) output = [ formatter.paragraph(1, attr={'class': 'searchstats'}), _("Results %(bs)s%(hitsFrom)d - %(hitsTo)d%(be)s " "of %(aboutHits)s %(bs)s%(hits)d%(be)s results out of " "about %(items)d items.") % {'aboutHits': self.estimated_hits[0], 'hits': self.estimated_hits[1], 'items': self.pages, 'hitsFrom': hitsFrom + 1, 'hitsTo': hitsFrom + min(self.estimated_hits[1] - hitsFrom, app.cfg.search_results_per_page), 'bs': formatter.strong(1), 'be': formatter.strong(0)}, u' (%s %s)' % (''.join([formatter.strong(1), formatter.text("%.2f" % self.elapsed), formatter.strong(0)]), formatter.text(_("seconds"))), formatter.paragraph(0), ] return ''.join(output)
def login(self, user_obj, **kw): username = kw.get('username') password = kw.get('password') # simply continue if something else already logged in successfully if user_obj and user_obj.valid: return ContinueLogin(user_obj) if not username and not password: return ContinueLogin(user_obj) logging.debug("%s: performing login action" % self.name) if username and not password: return ContinueLogin( user_obj, _('Missing password. Please enter user name and password.')) u = user.User(name=username, password=password, auth_method=self.name) if u.valid: logging.debug("%s: successfully authenticated user %r (valid)" % (self.name, u.name)) return ContinueLogin(u) else: logging.debug("%s: could not authenticate user %r (not valid)" % (self.name, username)) return ContinueLogin(user_obj, _("Invalid username or password."))
def get_complex(arg, name=None, default=None): """ For use with values returned from parse_quoted_separated or given as macro parameters, return a complex from a unicode string. None is a valid input and yields the default value. :param arg: The argument, may be None or a unicode string :param name: Name of the argument, for error messages :param default: default return value if arg is None :rtype: complex or None :returns: the complex value of the string (or default value) """ assert default is None or isinstance(default, (int, long, float, complex)) if arg is None: return default elif not isinstance(arg, unicode): raise TypeError('Argument must be None or unicode') try: # allow writing 'i' instead of 'j' arg = arg.replace('i', 'j').replace('I', 'j') return complex(arg) except ValueError: if name: raise ValueError( _('Argument "%(name)s" must be a complex value, not "%(value)s"', name=name, value=arg)) else: raise ValueError( _('Argument must be a complex value, not "%(value)s"', value=arg))
def create_user(username, password, email, openid=None): """ create a user """ # Create user profile theuser = User(auth_method="new-user") theuser.name = username # Don't allow creating users with invalid names if not isValidName(theuser.name): return _("""Invalid user name '%(name)s'. Name may contain any Unicode alpha numeric character, with optional one space between words. Group page name is not allowed.""", name=theuser.name) # Name required to be unique. Check if name belong to another user. if getUserId(theuser.name): return _("This user name already belongs to somebody else.") pw_checker = app.cfg.password_checker if pw_checker: pw_error = pw_checker(theuser.name, password) if pw_error: return _("Password not acceptable: %(msg)s", msg=pw_error) # Encode password try: theuser.enc_password = encodePassword(password) except UnicodeError, err: # Should never happen return "Can't encode password: %(msg)s" % dict(msg=str(err))
def get_int(arg, name=None, default=None): """ For use with values returned from parse_quoted_separated or given as macro parameters, return an integer from a unicode string containing the decimal representation of a number. None is a valid input and yields the default value. :param arg: The argument, may be None or a unicode string :param name: Name of the argument, for error messages :param default: default value if arg is None :rtype: int or None :returns: the integer value of the string (or default value) """ assert default is None or isinstance(default, (int, long)) if arg is None: return default elif not isinstance(arg, unicode): raise TypeError('Argument must be None or unicode') try: return int(arg) except ValueError: if name: raise ValueError( _('Argument "%(name)s" must be an integer value, not "%(value)s"', name=name, value=arg)) else: raise ValueError( _('Argument must be an integer value, not "%(value)s"', value=arg))
def get_float(arg, name=None, default=None): """ For use with values returned from parse_quoted_separated or given as macro parameters, return a float from a unicode string. None is a valid input and yields the default value. :param arg: The argument, may be None or a unicode string :param name: Name of the argument, for error messages :param default: default return value if arg is None :rtype: float or None :returns: the float value of the string (or default value) """ assert default is None or isinstance(default, (int, long, float)) if arg is None: return default elif not isinstance(arg, unicode): raise TypeError('Argument must be None or unicode') try: return float(arg) except ValueError: if name: raise ValueError( _('Argument "%(name)s" must be a floating point value, not "%(value)s"', name=name, value=arg)) else: raise ValueError( _('Argument must be a floating point value, not "%(value)s"', value=arg))
def login_hint(self): msg = _( 'If you do not have an account, <a href="%(register_url)s">you can create one now</a>. ', register_url=url_for('frontend.register')) msg += _('<a href="%(recover_url)s">Forgot your password?</a>', recover_url=url_for('frontend.lostpass')) return Markup(msg)
def _default_password_checker(cfg, username, password): """ Check if a password is secure enough. We use a built-in check to get rid of the worst passwords. We do NOT use cracklib / python-crack here any more because it is not thread-safe (we experienced segmentation faults when using it). If you don't want to check passwords, use password_checker = None. :returns: None if there is no problem with the password, some unicode object with an error msg, if the password is problematic. """ # in any case, do a very simple built-in check to avoid the worst passwords if len(password) < 6: return _("Password is too short.") if len(set(password)) < 4: return _("Password has not enough different characters.") username_lower = username.lower() password_lower = password.lower() if username in password or password in username or \ username_lower in password_lower or password_lower in username_lower: return _("Password is too easy to guess (password contains name or name contains password).") keyboards = (ur"`1234567890-=qwertyuiop[]\asdfghjkl;'zxcvbnm,./", # US kbd ur"^1234567890ß´qwertzuiopü+asdfghjklöä#yxcvbnm,.-", # german kbd ) # add more keyboards! for kbd in keyboards: rev_kbd = kbd[::-1] if password in kbd or password in rev_kbd or \ password_lower in kbd or password_lower in rev_kbd: return _("Password is too easy to guess (keyboard sequence).") return None
def mailAccountData(self, cleartext_passwd=None): """ Mail a user who forgot his password a message enabling him to login again. """ from MoinMoin.mail import sendmail token = self.generate_recovery_token() text = _("""\ Somebody has requested to email you a password recovery link. Please use the link below to change your password to a known value: %(link)s If you didn't forget your password, please ignore this email. """, link=url_for('frontend.recoverpass', username=self.name, token=token, _external=True)) subject = _('[%(sitename)s] Your wiki password recovery link', sitename=self._cfg.sitename or "Wiki") mailok, msg = sendmail.sendmail([self.email], subject, text, mail_from=self._cfg.mail_from) return mailok, msg
def formatHitInfoBar(self, page): """ Returns the code for the information below a search hit @param page: the FoundPage instance """ request = self.request f = self.formatter p = page.page rev = p.get_real_rev() if rev is None: rev = 0 size_str = '%.1fk' % (p.size()/1024.0) revisions = p.getRevList() if len(revisions) and rev == revisions[0]: rev_str = '%s: %d (%s)' % (_('rev'), rev, _('current')) else: rev_str = '%s: %d' % (_('rev'), rev, ) lastmod_str = _('last modified: %s') % p.mtime(printable=True) result = f.paragraph(1, attr={'class': 'searchhitinfobar'}) + \ f.text('%s - %s %s' % (size_str, rev_str, lastmod_str)) + \ f.paragraph(0) return result
def _render_data_diff(self, oldrev, newrev): hash_name = HASH_ALGORITHM if oldrev.meta[hash_name] == newrev.meta[hash_name]: return _( "The items have the same data hash code (that means they very likely have the same data)." ) else: return _("The items have different data.")
def trash(namespace): """ Returns the trashed items. """ trash = _trashed(namespace) return render_template('admin/trash.html', headline=_(u'Trashed Items'), title_name=_(u'Trashed Items'), results=trash)
def __init__(self, username=None, priv=None, item=None): if None in (username, priv, item): message = _("Permission denied!") else: username = username or L_("You") message = _("%(username)s may not %(priv)s '%(item)s'.", username=username, priv=_(priv), item=item) # XXX add _('...') for all privs elsewhere for extraction AccessError.__init__(self, message)
def interwikihelp(): """display a table with list of known interwiki names / urls""" headings = [_('InterWiki name'), _('URL'), ] rows = sorted(app.cfg.interwiki_map.items()) return render_template('admin/interwikihelp.html', title_name=_(u"Interwiki Help"), headings=headings, rows=rows)
def button_filter(tagname, attributes, contents, context, bind): """Show translated text in clickable buttons and submits.""" if bind is None: return contents if tagname == 'input': if ('value' not in attributes and attributes.get('type') in ['submit', 'reset', ]): attributes['value'] = _(bind.default_value) elif tagname == 'button' and not contents: contents = _(bind.default_value) return contents
def macro(self, content, arguments, page_url, alternative): headings = (_('Lexer Name'), _('Lexer Aliases'), _('File Patterns'), _('Mimetypes'), ) rows = list(pygments.lexers.get_all_lexers()) rows.sort(key=lambda t: tuple(t[0].lower())) table = TableMixin() ret = table.build_dom_table(rows, head=headings, cls='moin-sortable') return ret
def interwikihelp(): """display a table with list of known interwiki names / urls""" headings = [ _('InterWiki name'), _('URL'), ] rows = sorted(app.cfg.interwiki_map.items()) return render_template('user/interwikihelp.html', title_name=_(u"Interwiki Names"), headings=headings, rows=rows)
def _render_data(self): # TODO: this could be a converter -> dom, then transcluding this kind # of items and also rendering them with the code in base class could work png_url = url_for('frontend.get_item', item_name=self.name, member='drawing.png', rev=self.rev.revid) title = _('Edit drawing %(filename)s (opens in new window)', filename=self.name) image_map = self._read_map() if image_map: mapid, image_map = self._transform_map(image_map, title) title = _('Clickable drawing: %(filename)s', filename=self.name) return Markup(image_map + u'<img src="{0}" alt="{1}" usemap="#{2}" />'.format(png_url, title, mapid)) else: return Markup(u'<img src="{0}" alt="{1}" />'.format(png_url, title))
def itemsize(): """display a table with item sizes""" headings = [_('Size'), _('Item name'), ] rows = [(rev.meta[SIZE], rev.meta[NAME]) for rev in flaskg.storage.documents(wikiname=app.cfg.interwikiname)] rows = sorted(rows, reverse=True) return render_template('admin/itemsize.html', title_name=_(u"Item Size"), headings=headings, rows=rows)
def __call__(self, data, contenttype=None, arguments=None): """ Function called by the converter to process the conversion. TODO: Add support for different arguments """ text = decode_data(data, contenttype) # data cleanup is not needed by html_out, but is needed by moinwiki_out; CKEditor adds unwanted \n\t while '\t\t' in text: text = text.replace('\t\t', '\t') text = text.replace('\r\n\t', '').replace('\n\t', '') content = normalize_split_text(text) # Be sure we have empty string in the base url self.base_url = '' # We create an element tree from the HTML content # The content is a list of string, line per line # We can concatenate all in one string html_str = u'\n'.join(content) try: html_tree = HTML(html_str) except AssertionError as reason: # we suspect user has created or uploaded malformed HTML, try to show input as preformatted code msg = _('Error: malformed HTML: {reason}.').format(reason=reason) msg = '<div class="error"><p><strong>%s</strong></p></div>' % msg html_str = ''.join(['<html>', msg, '<pre>', html_str, '</pre></html>']) try: html_tree = HTML(html_str) except ValueError: msg = _('Error: malformed HTML. Try viewing source with Highlight or Modify links.') msg = '<div class="error"><p><strong>%s</strong></p></div>' % msg html_str = ''.join(['<html>', msg, '</html>']) html_tree = HTML(html_str) # We should have a root element, which will be converted as <page> # for the DOM Tree. # NB : If <html> used, it will be converted back to <div> after # one roundtrip if html_tree.tag.name != 'html': html_str = ''.join(['<div>', html_str, '</div>']) html_tree = HTML(html_str) # Start the conversion of the first element # Every child of each element will be recursively convert too element = self.do_children(html_tree) # Add Global element to our DOM Tree body = moin_page.body(children=element) root = moin_page.page(children=[body]) return root
def button_filter(tagname, attributes, contents, context, bind): """Show translated text in clickable buttons and submits.""" if bind is None: return contents if tagname == 'input': if ('value' not in attributes and attributes.get('type') in [ 'submit', 'reset', ]): attributes['value'] = _(bind.default_value) elif tagname == 'button' and not contents: contents = _(bind.default_value) return contents
def itemsize(): """display a table with item sizes""" headings = [ _('Size'), _('Item name'), ] rows = [(rev.meta[SIZE], rev.fqname) for rev in flaskg.storage.documents(wikiname=app.cfg.interwikiname)] rows = sorted(rows, reverse=True) return render_template('user/itemsize.html', title_name=_(u"Item Sizes"), headings=headings, rows=rows)
def msgs(): """ Encapsulates the main notification messages :return: a dictionary of notification messages """ _ = lambda x: x messages = { ACTION_CREATE: _("The '%(fqname)s' ('%(item_url)s') item on '%(wiki_name)s' has been created by %(user_name)s:" ), ACTION_MODIFY: _("The '%(fqname)s' ('%(item_url)s') item on '%(wiki_name)s' has been modified by %(user_name)s:" ), ACTION_RENAME: _("The '%(fqname)s' ('%(item_url)s') item on '%(wiki_name)s' has been renamed by %(user_name)s:" ), ACTION_COPY: _("The '%(fqname)s' ('%(item_url)s') item on '%(wiki_name)s' has been copied by %(user_name)s:" ), ACTION_REVERT: _("The '%(fqname)s' ('%(item_url)s') item on '%(wiki_name)s' has been reverted by %(user_name)s:" ), ACTION_TRASH: _("The '%(fqname)s' ('%(item_url)s') item on '%(wiki_name)s' has been deleted by %(user_name)s:" ), DESTROY_REV: _("The '%(fqname)s' ('%(item_url)s') item on '%(wiki_name)s' has one revision destroyed by %(user_name)s:" ), DESTROY_ALL: _("The '%(fqname)s' ('%(item_url)s') item on '%(wiki_name)s' has been destroyed by %(user_name)s:" ), } return messages
def __call__(self, rev, contenttype=None, arguments=None): self.item_name = rev.item.name try: contents = self.list_contents(rev.data) contents = [(self.process_size(size), self.process_datetime(dt), self.process_name(name), ) for size, dt, name in contents] return self.build_dom_table(contents, head=[_("Size"), _("Date"), _("Name")], cls='zebra') except ArchiveException as err: logging.exception("An exception within archive file handling occurred:") # XXX we also use a table for error reporting, could be # something more adequate, though: return self.build_dom_table([[str(err)]])
def login(self, userobj, **kw): """ Handles an login request and continues to multistage continuation if necessary. """ continuation = kw.get('multistage') # process another subsequent step if continuation: return self._handleContinuation() openid = kw.get('openid') # no openid entered if not openid: return ContinueLogin(userobj) # we make a consumer object with an in-memory storage oid_consumer = consumer.Consumer(session, self.store) # we catch any possible openid-related exceptions try: oid_response = oid_consumer.begin(openid) except HTTPFetchingError: return ContinueLogin(None, _('Failed to resolve OpenID.')) except DiscoveryFailure: return ContinueLogin( None, _('OpenID discovery failure, not a valid OpenID.')) else: # we got no response from the service if oid_response is None: return ContinueLogin(None, _('No OpenID service at this URL.')) # site root and where to return after the redirect site_root = url_for('frontend.show_root', _external=True) return_to = get_multistage_continuation_url( self.name, {'oidstage': '1'}) # should we redirect the user? if oid_response.shouldSendRedirect(): redirect_url = oid_response.redirectURL(site_root, return_to) return MultistageRedirectLogin(redirect_url) else: # send a form form_html = oid_response.htmlMarkup( site_root, return_to, form_tag_attrs={'id': 'openid_message'}) # returns a MultistageFormLogin return MultistageFormLogin(form_html)
def highlighterhelp(): """display a table with list of available Pygments lexers""" import pygments.lexers headings = [_('Lexer description'), _('Lexer names'), _('File patterns'), _('Mimetypes'), ] lexers = pygments.lexers.get_all_lexers() rows = sorted([[desc, ' '.join(names), ' '.join(patterns), ' '.join(mimetypes), ] for desc, names, patterns, mimetypes in lexers]) return render_template('admin/highlighterhelp.html', title_name=_(u"Highlighter Help"), headings=headings, rows=rows)
def _reset(self, request, formatter): """ Update internal state before new output Do not call this, it should be called only by the instance code. Each request might need different translations or other user preferences. @param request: current request @param formatter: the formatter instance to use """ self.buffer = StringIO.StringIO() self.formatter = formatter self.request = request # Use 1 match, 2 matches... self.matchLabel = (_('match'), _('matches'))
def item_acl_report(): """ Return a sorted list of all items in the wiki along with the ACL Meta-data. Item names are prefixed with the namespace, if there is a non-default namespace. If there are multiple names, the first name is used for sorting. """ all_items = flaskg.storage.documents(wikiname=app.cfg.interwikiname) items_acls = [] for item in all_items: item_namespace = item.meta.get(NAMESPACE) item_id = item.meta.get(ITEMID) if item_namespace: item_name = [item_namespace + '/' + name for name in item.meta.get(NAME)] else: item_name = item.meta.get(NAME) item_acl = item.meta.get(ACL) acl_default = item_acl is None if acl_default: for namespace, acl_config in app.cfg.acl_mapping: if item_namespace == namespace: item_acl = acl_config['default'] items_acls.append({'name': item_name, 'name_old': item.meta['name_old'], 'itemid': item_id, 'fqname': item.rev.fqname, 'fqnames': item.rev.fqnames, 'acl': item_acl, 'acl_default': acl_default}) items_acls = sorted(items_acls, key=lambda k: (k['name'], k['name_old'])) return render_template('admin/item_acl_report.html', title_name=_('Item ACL Report'), items_acls=items_acls)
def item_acl_report(): """ Return a list of all items in the wiki along with the ACL Meta-data """ all_items = flaskg.storage.documents(wikiname=app.cfg.interwikiname) items_acls = [] for item in all_items: item_namespace = item.meta.get(NAMESPACE) item_id = item.meta.get(ITEMID) item_name = item.meta.get(NAME) item_acl = item.meta.get(ACL) acl_default = item_acl is None fqname = CompositeName(item_namespace, u'itemid', item_id) if acl_default: for namespace, acl_config in app.cfg.acl_mapping: if item_namespace == namespace[:-1]: item_acl = acl_config['default'] items_acls.append({'name': item_name, 'itemid': item_id, 'fqname': fqname, 'acl': item_acl, 'acl_default': acl_default}) return render_template('admin/item_acl_report.html', title_name=_('Item ACL Report'), items_acls=items_acls)
def item_acl_report(): """ Return a list of all items in the wiki along with the ACL Meta-data """ all_items = flaskg.storage.documents(wikiname=app.cfg.interwikiname) items_acls = [] for item in all_items: item_namespace = item.meta.get(NAMESPACE) item_id = item.meta.get(ITEMID) item_name = item.meta.get(NAME) item_acl = item.meta.get(ACL) acl_default = item_acl is None fqname = CompositeName(item_namespace, u'itemid', item_id) if acl_default: for namespace, acl_config in app.cfg.acl_mapping: if item_namespace == namespace[:-1]: item_acl = acl_config['default'] items_acls.append({ 'name': item_name, 'itemid': item_id, 'fqname': fqname, 'acl': item_acl, 'acl_default': acl_default }) return render_template('admin/item_acl_report.html', title_name=_('Item ACL Report'), items_acls=items_acls)
def group_acl_report(group_name): """ Display a 2-column table of items and ACLs, where the ACL rule specifies any WikiGroup or ConfigGroup name. """ group = search_group(group_name) all_items = flaskg.storage.documents(wikiname=app.cfg.interwikiname) group_items = [] for item in all_items: acl_iterator = ACLStringIterator(ACL_RIGHTS_CONTENTS, item.meta.get(ACL, '')) for modifier, entries, rights in acl_iterator: if group_name in entries: item_id = item.meta.get(ITEMID) fqname = CompositeName(item.meta.get(NAMESPACE), u'itemid', item_id) group_items.append( dict(name=item.meta.get(NAME), itemid=item_id, fqname=fqname, rights=rights)) return render_template('admin/group_acl_report.html', title_name=_(u'Group ACL Report'), group_items=group_items, group_name=group_name)
def userbrowser(): """ User Account Browser """ groups = flaskg.groups revs = user.search_users() # all users user_accounts = [] for rev in revs: user_groups = [] user_names = rev.meta[NAME] for groupname in groups: group = groups[groupname] for name in user_names: if name in group: user_groups.append(groupname) user_accounts.append( dict(uid=rev.meta[ITEMID], name=user_names, fqname=CompositeName(NAMESPACE_USERPROFILES, NAME_EXACT, rev.name), email=rev.meta[EMAIL] if EMAIL in rev.meta else rev.meta[EMAIL_UNVALIDATED], disabled=rev.meta[DISABLED], groups=user_groups)) return render_template('admin/userbrowser.html', user_accounts=user_accounts, title_name=_(u"Users"))
def highlighterhelp(): """display a table with list of available Pygments lexers""" import pygments.lexers headings = [ _('Lexer description'), _('Lexer names'), _('File patterns'), _('Mimetypes'), ] lexers = pygments.lexers.get_all_lexers() rows = sorted([[desc, ' '.join(names), ' '.join(patterns), ' '.join(mimetypes), ] for desc, names, patterns, mimetypes in lexers]) return render_template('user/highlighterhelp.html', title_name=_(u"Highlighters"), headings=headings, rows=rows)
def mail_password_recovery(self, cleartext_passwd=None, subject=None, text=None): """ Mail a user who forgot his password a message enabling him to login again. """ if not self.email: return False, "user has no E-Mail address in his profile." token = self.generate_recovery_token() if subject is None: subject = _('[%(sitename)s] Your wiki password recovery link', sitename='%(sitename)s') subject = subject % dict(sitename=self._cfg.sitename or "Wiki") if text is None: link = url_for('frontend.recoverpass', username=self.name0, token=token, _external=True) text = render_template('mail/password_recovery.txt', link=link) mailok, msg = sendmail.sendmail(subject, text, to=[self.email], mail_from=self._cfg.mail_from) return mailok, msg
def wikiconfighelp(): def format_default(default): if isinstance(default, defaultconfig.DefaultExpression): default_txt = default.text else: default_txt = repr(default) if len(default_txt) > 30: default_txt = '...' return default_txt groups = [] for groupname in defaultconfig.options: heading, desc, opts = defaultconfig.options[groupname] opts = sorted([(groupname + '_' + name, format_default(default), description) for name, default, description in opts]) groups.append((heading, desc, opts)) for groupname in defaultconfig.options_no_group_name: heading, desc, opts = defaultconfig.options_no_group_name[groupname] opts = sorted([(name, format_default(default), description) for name, default, description in opts]) groups.append((heading, desc, opts)) groups.sort() return render_template('admin/wikiconfighelp.html', title_name=_(u"Wiki Configuration Help"), groups=groups)
def userprofile(user_name): """ Set values in user profile """ u = user.User(auth_username=user_name) if request.method == 'GET': return _(u"User profile of %(username)s: %(email)s %(disabled)s", username=user_name, email=u.email, disabled=u.disabled) if request.method == 'POST': key = request.form.get('key', '') val = request.form.get('val', '') ok = False if hasattr(u, key): ok = True oldval = u.profile[key] if isinstance(oldval, bool): val = bool(int(val)) elif isinstance(oldval, int): val = int(val) elif isinstance(oldval, unicode): val = unicode(val) else: ok = False if ok: u.profile[key] = val u.save() flash(u'{0}.{1}: {2} -> {3}'.format(user_name, key, unicode(oldval), unicode(val), ), "info") else: flash(u'modifying {0}.{1} failed'.format(user_name, key, ), "error") return redirect(url_for('.userbrowser'))
def request(self, user_obj, **kw): u = None # always revalidate auth if user_obj and user_obj.auth_method == self.name: user_obj = None # something else authenticated before us if user_obj: return user_obj, True auth = request.authorization if auth and auth.username and auth.password is not None: logging.debug("http basic auth, received username: {0!r} password: {1!r}".format( auth.username, auth.password)) u = user.User(name=auth.username.decode(self.coding), password=auth.password.decode(self.coding), auth_method=self.name, auth_attribs=[], trusted=self.trusted) logging.debug("user: {0!r}".format(u)) if not u or not u.valid: from werkzeug import Response, abort response = Response(_('Please log in first.'), 401, {'WWW-Authenticate': 'Basic realm="{0}"'.format(self.realm)}) abort(response) logging.debug("u: {0!r}".format(u)) if u and self.autocreate: logging.debug("autocreating user") u.create_or_update() if u and u.valid: logging.debug("returning valid user {0!r}".format(u)) return u, True # True to get other methods called, too else: logging.debug("returning {0!r}".format(user_obj)) return user_obj, True
def add_heading(self, elem, level, id=None): elem.append(html.a(attrib={ html.href: "#{0}".format(id), html.class_: "moin-permalink", html.title_: _("Link to this heading") }, children=(u"¶", ))) self._headings.append((elem, level, id))
def userprofile(user_name): """ Set values in user profile """ u = user.User(auth_username=user_name) if request.method == 'GET': return _(u"User profile of %(username)s: %(email)r", username=user_name, email=(u.email, u.disabled)) if request.method == 'POST': key = request.form.get('key', '') val = request.form.get('val', '') ok = False if hasattr(u, key): ok = True oldval = getattr(u, key) if isinstance(oldval, bool): val = bool(val) elif isinstance(oldval, int): val = int(val) elif isinstance(oldval, unicode): val = unicode(val) else: ok = False if ok: setattr(u, key, val) u.save() flash('{0}.{1}: {2} -> {3}'.format(user_name, key, unicode(oldval), unicode(val), ), "info") else: flash('modifying {0}.{1} failed'.format(user_name, key, ), "error") return redirect(url_for('.userbrowser'))
def __call__(self, data, contenttype=None, arguments=None): text = decode_data(data, contenttype) content = normalize_split_text(text) # as of py 2.7.x (and in the year 2013), the csv module seems to still # have troubles with unicode, thus we encode to utf-8 ... content = [line.encode('utf-8') for line in content] dialect = csv.Sniffer().sniff(content[0]) reader = csv.reader(content, dialect) # ... and decode back to unicode rows = [] for encoded_row in reader: row = [] for encoded_cell in encoded_row: row.append(encoded_cell.decode('utf-8')) if row: rows.append(row) head = None cls = None try: # fragile function throws errors when csv file is incorrectly formatted if csv.Sniffer().has_header('\n'.join(content)): head = rows[0] rows = rows[1:] cls = 'moin-sortable' except csv.Error as e: head = [_('Error parsing CSV file:'), str(e)] table = self.build_dom_table(rows, head=head, cls=cls) body = moin_page.body(children=(table, )) return moin_page.page(children=(body, ))
def __call__(self, rev, contenttype=None, arguments=None): item_name = rev.item.fqname.value attrib = { xlink.href: Iri(scheme='wiki', authority='', path='/' + item_name, query='do=modify'), } a = moin_page.a(attrib=attrib, children=[_("%(item_name)s does not exist. Create it?", item_name=item_name)]) body = moin_page.body(children=(a, )) return moin_page.page(children=(body, ))
def sysitems_upgrade(): from MoinMoin.storage.backends import upgrade_sysitems from MoinMoin.storage.error import BackendError if request.method == 'GET': action = 'syspages_upgrade' label = 'Upgrade System Pages' return render_template('admin/sysitems_upgrade.html', title_name=_(u"System items upgrade")) if request.method == 'POST': xmlfile = request.files.get('xmlfile') try: upgrade_sysitems(xmlfile) except BackendError as e: flash(_('System items upgrade failed due to the following error: %(error)s.', error=e), 'error') else: flash(_('System items have been upgraded successfully!')) return redirect(url_for('.index'))
def get_choice(arg, name=None, choices=[None], default_none=False): """ For use with values returned from parse_quoted_separated or given as macro parameters, return a unicode string that must be in the choices given. None is a valid input and yields first of the valid choices. :param arg: The argument, may be None or a unicode string :param name: Name of the argument, for error messages :param choices: the possible choices :param default_none: If False (default), get_choice returns first available choice if arg is None. If True, get_choice returns None if arg is None. This is useful if some arg value is required (no default choice). :rtype: unicode or None :returns: the unicode string (or default value) """ assert isinstance(choices, (tuple, list)) if arg is None: if default_none: return None else: return choices[0] elif not isinstance(arg, unicode): raise TypeError("Argument must be None or unicode") elif arg not in choices: if name: raise ValueError( _( 'Argument "%(name)s" must be one of "%(choices)s", not "%(value)s"', name=name, choices='", "'.join([repr(choice) for choice in choices]), value=arg, ) ) else: raise ValueError( _( 'Argument must be one of "%(choices)s", not "%(value)s"', choices='", "'.join([repr(choice) for choice in choices]), value=arg, ) ) return arg
def login(self, userobj, **kw): """ Handles an login request and continues to multistage continuation if necessary. """ continuation = kw.get('multistage') # process another subsequent step if continuation: return self._handleContinuation() openid = kw.get('openid') # no openid entered if not openid: return ContinueLogin(userobj) # we make a consumer object with an in-memory storage oid_consumer = consumer.Consumer(session, self.store) # we catch any possible openid-related exceptions try: oid_response = oid_consumer.begin(openid) except HTTPFetchingError: return ContinueLogin(None, _('Failed to resolve OpenID.')) except DiscoveryFailure: return ContinueLogin(None, _('OpenID discovery failure, not a valid OpenID.')) else: # we got no response from the service if oid_response is None: return ContinueLogin(None, _('No OpenID service at this URL.')) # site root and where to return after the redirect site_root = url_for('frontend.show_root', _external=True) return_to = get_multistage_continuation_url(self.name, {'oidstage': '1'}) # should we redirect the user? if oid_response.shouldSendRedirect(): redirect_url = oid_response.redirectURL(site_root, return_to) return MultistageRedirectLogin(redirect_url) else: # send a form form_html = oid_response.htmlMarkup(site_root, return_to, form_tag_attrs={'id': 'openid_message'}) # returns a MultistageFormLogin return MultistageFormLogin(form_html)
def mail_email_verification(self): """ Mail a user a link to verify his email address. """ token = self.generate_recovery_token() link = url_for("frontend.verifyemail", username=self.name0, token=token, _external=True) text = render_template("mail/account_verification.txt", link=link) subject = _("[%(sitename)s] Please verify your email address", sitename=self._cfg.sitename or "Wiki") email = self.profile[EMAIL_UNVALIDATED] mailok, msg = sendmail.sendmail(subject, text, to=[email], mail_from=self._cfg.mail_from) return mailok, msg
def mail_email_verification(self): """ Mail a user a link to verify his email address. """ token = self.generate_recovery_token() text = _("""\ Somebody has created an account with this email address. Please use the link below to verify your email address: %(link)s If you didn't create this account, please ignore this email. """, link=url_for('frontend.verifyemail', username=self.name, token=token, _external=True)) subject = _('[%(sitename)s] Please verify your email address', sitename=self._cfg.sitename or "Wiki") mailok, msg = sendmail.sendmail(subject, text, to=[self.email], mail_from=self._cfg.mail_from) return mailok, msg
def mail_password_recovery(self, cleartext_passwd=None): """ Mail a user who forgot his password a message enabling him to login again. """ token = self.generate_recovery_token() text = _("""\ Somebody has requested to email you a password recovery link. Please use the link below to change your password to a known value: %(link)s If you didn't forget your password, please ignore this email. """, link=url_for('frontend.recoverpass', username=self.name, token=token, _external=True)) subject = _('[%(sitename)s] Your wiki password recovery link', sitename=self._cfg.sitename or "Wiki") mailok, msg = sendmail.sendmail(subject, text, to=[self.email], mail_from=self._cfg.mail_from) return mailok, msg
def get_editor_info(meta, external=False): addr = meta.get(ADDRESS) hostname = meta.get(HOSTNAME) text = _('anonymous') # link text title = '' # link title css = 'editor' # link/span css class name = None # author name uri = None # author homepage uri email = None # pure email address of author if app.cfg.show_hosts and addr: # only tell ip / hostname if show_hosts is True if hostname: text = hostname[:15] # 15 = len(ipaddr) name = title = '{0}[{1}]'.format(hostname, addr) css = 'editor host' else: name = text = addr title = '[{0}]'.format(addr) css = 'editor ip' userid = meta.get(USERID) if userid: u = user.User(userid) name = u.name text = name aliasname = u.aliasname if not aliasname: aliasname = name if title: # we already have some address info title = "{0} @ {1}".format(aliasname, title) else: title = aliasname if u.mailto_author and u.email: email = u.email css = 'editor mail' else: homewiki = app.cfg.user_homewiki if is_local_wiki(homewiki): css = 'editor homepage local' else: css = 'editor homepage interwiki' uri = url_for_item(name, wiki_name=homewiki, _external=external) result = dict(name=name, text=text, css=css, title=title) if uri: result['uri'] = uri if email: result['email'] = email return result
def login(self, user_obj, **kw): username = kw.get('username') password = kw.get('password') # simply continue if something else already logged in successfully if user_obj and user_obj.valid: return ContinueLogin(user_obj) if not username and not password: return ContinueLogin(user_obj) logging.debug("{0}: performing login action".format(self.name)) if username and not password: return ContinueLogin(user_obj, _('Missing password. Please enter user name and password.')) u = user.User(name=username, password=password, auth_method=self.name, trusted=self.trusted) if u.valid: logging.debug("{0}: successfully authenticated user {1!r} (valid)".format(self.name, u.name)) return ContinueLogin(u) else: logging.debug("{0}: could not authenticate user {1!r} (not valid)".format(self.name, username)) return ContinueLogin(user_obj, _("Invalid username or password."))
def test_text(): # test for gettext result = _('test_text') assert result == 'test_text' # test for lazy_gettext result = L_('test_lazy_text') assert result == u'test_lazy_text' # test for ngettext result1 = N_('text1', 'text2', 1) assert result1 == 'text1' result2 = N_('text1', 'text2', 2) assert result2 == 'text2'
def validate(self, element, state): # Make sure that the other meta is valid before validating the name. # TODO Change/Make sure that the below statement holds good. try: if not element.parent.parent['extra_meta_text'].valid: return False except AttributeError: pass try: validate_name(state['meta'], state[ITEMID]) except NameNotValidError as e: self.invalid_name_msg = _(e) return self.note_error(element, state, 'invalid_name_msg') return True
def msgs(): """ Encapsulates the main notification messages :return: a dictionary of notification messages """ _ = lambda x: x messages = { ACTION_CREATE: _("The '%(item_name)s' item on '%(wiki_name)s' has been created by %(user_name)s:"), ACTION_MODIFY: _("The '%(item_name)s' item on '%(wiki_name)s' has been modified by %(user_name)s:"), ACTION_RENAME: _("The '%(item_name)s' item on '%(wiki_name)s' has been renamed by %(user_name)s:"), ACTION_COPY: _("The '%(item_name)s' item on '%(wiki_name)s' has been copied by %(user_name)s:"), ACTION_REVERT: _("The '%(item_name)s' item on '%(wiki_name)s' has been reverted by %(user_name)s:"), ACTION_TRASH: _("The '%(item_name)s' item on '%(wiki_name)s' has been deleted by %(user_name)s:"), DESTROY_REV: _("The '%(item_name)s' item on '%(wiki_name)s' has one revision destroyed by %(user_name)s:"), DESTROY_ALL: _("The '%(item_name)s' item on '%(wiki_name)s' has been destroyed by %(user_name)s:"), } return messages