[wiki-lenny/share/] Hacking sauvage de MoinMoin fonctionnel
Plusieurs fichiers ont été sauvagement hacké pour que MoiMoin ait le comportement que l'on attend de lui au Cr@ns. * PageGraphicalEditor.py --- Pour interdire l'éditeur graphique sur certains pages * action/newaccount.py --- Pour interdre la création de compte depuis l'extérieur * formatter/__init__.py --- Pour pouvoir afficher des boîtes dans les différents formatters... * formatter/text_html.py --- ... ce qui n'est implémenté que dans le formatteur html pour l'instant. * security/__init__.py --- Pour n'autoriser l'accès en lecture qu'aux pages publiques depuis l'extérieur. darcs-hash:20081109154331-bd074-0c8a84ce7016e8a1ebe63795d377fe91065cb0b8.gz
This commit is contained in:
parent
73e1af5309
commit
cd5d080e49
10 changed files with 4410 additions and 0 deletions
411
wiki-lenny/share/PageGraphicalEditor.orig.py
Normal file
411
wiki-lenny/share/PageGraphicalEditor.orig.py
Normal file
|
@ -0,0 +1,411 @@
|
||||||
|
# -*- coding: iso-8859-1 -*-
|
||||||
|
"""
|
||||||
|
MoinMoin - Call the GUI editor (FCKeditor)
|
||||||
|
|
||||||
|
Same as PageEditor, but we use the HTML based GUI editor here.
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
* see PageEditor.py
|
||||||
|
|
||||||
|
@copyright: 2006 Bastian Blank, Florian Festi,
|
||||||
|
2006-2007 MoinMoin:ThomasWaldmann
|
||||||
|
@license: GNU GPL, see COPYING for details.
|
||||||
|
"""
|
||||||
|
import re
|
||||||
|
|
||||||
|
from MoinMoin import PageEditor
|
||||||
|
from MoinMoin import wikiutil
|
||||||
|
from MoinMoin.Page import Page
|
||||||
|
from MoinMoin.widget import html
|
||||||
|
from MoinMoin.widget.dialog import Status
|
||||||
|
from MoinMoin.util import web
|
||||||
|
from MoinMoin.parser.text_moin_wiki import Parser as WikiParser
|
||||||
|
|
||||||
|
def execute(pagename, request):
|
||||||
|
if not request.user.may.write(pagename):
|
||||||
|
_ = request.getText
|
||||||
|
request.theme.add_msg_('You are not allowed to edit this page.', "error")
|
||||||
|
Page(request, pagename).send_page()
|
||||||
|
return
|
||||||
|
|
||||||
|
PageGraphicalEditor(request, pagename).sendEditor()
|
||||||
|
|
||||||
|
|
||||||
|
class PageGraphicalEditor(PageEditor.PageEditor):
|
||||||
|
""" Same as PageEditor, but use the GUI editor (FCKeditor) """
|
||||||
|
def word_rule(self):
|
||||||
|
regex = re.compile(r"\(\?<![^)]*?\)")
|
||||||
|
word_rule = regex.sub("", WikiParser.word_rule_js)
|
||||||
|
return repr(word_rule)[1:]
|
||||||
|
|
||||||
|
def sendEditor(self, **kw):
|
||||||
|
""" Send the editor form page.
|
||||||
|
|
||||||
|
@keyword preview: if given, show this text in preview mode
|
||||||
|
@keyword staytop: don't go to #preview
|
||||||
|
@keyword comment: comment field (when preview is true)
|
||||||
|
"""
|
||||||
|
from MoinMoin import i18n
|
||||||
|
from MoinMoin.action import SpellCheck
|
||||||
|
|
||||||
|
request = self.request
|
||||||
|
form = request.form
|
||||||
|
_ = self._
|
||||||
|
request.disableHttpCaching(level=2)
|
||||||
|
request.emit_http_headers()
|
||||||
|
|
||||||
|
raw_body = ''
|
||||||
|
msg = None
|
||||||
|
conflict_msg = None
|
||||||
|
edit_lock_message = None
|
||||||
|
preview = kw.get('preview', None)
|
||||||
|
staytop = kw.get('staytop', 0)
|
||||||
|
|
||||||
|
# check edit permissions
|
||||||
|
if not request.user.may.write(self.page_name):
|
||||||
|
msg = _('You are not allowed to edit this page.')
|
||||||
|
elif not self.isWritable():
|
||||||
|
msg = _('Page is immutable!')
|
||||||
|
elif self.rev:
|
||||||
|
# Trying to edit an old version, this is not possible via
|
||||||
|
# the web interface, but catch it just in case...
|
||||||
|
msg = _('Cannot edit old revisions!')
|
||||||
|
else:
|
||||||
|
# try to acquire edit lock
|
||||||
|
ok, edit_lock_message = self.lock.acquire()
|
||||||
|
if not ok:
|
||||||
|
# failed to get the lock
|
||||||
|
if preview is not None:
|
||||||
|
edit_lock_message = _('The lock you held timed out. Be prepared for editing conflicts!'
|
||||||
|
) + "<br>" + edit_lock_message
|
||||||
|
else:
|
||||||
|
msg = edit_lock_message
|
||||||
|
|
||||||
|
# Did one of the prechecks fail?
|
||||||
|
if msg:
|
||||||
|
request.theme.add_msg(msg, "error")
|
||||||
|
self.send_page()
|
||||||
|
return
|
||||||
|
|
||||||
|
# check if we want to load a draft
|
||||||
|
use_draft = None
|
||||||
|
if 'button_load_draft' in form:
|
||||||
|
wanted_draft_timestamp = int(form.get('draft_ts', ['0'])[0])
|
||||||
|
if wanted_draft_timestamp:
|
||||||
|
draft = self._load_draft()
|
||||||
|
if draft is not None:
|
||||||
|
draft_timestamp, draft_rev, draft_text = draft
|
||||||
|
if draft_timestamp == wanted_draft_timestamp:
|
||||||
|
use_draft = draft_text
|
||||||
|
|
||||||
|
# Check for draft / normal / preview submit
|
||||||
|
if use_draft is not None:
|
||||||
|
title = _('Draft of "%(pagename)s"')
|
||||||
|
# Propagate original revision
|
||||||
|
rev = int(form['draft_rev'][0])
|
||||||
|
self.set_raw_body(use_draft, modified=1)
|
||||||
|
preview = use_draft
|
||||||
|
elif preview is None:
|
||||||
|
title = _('Edit "%(pagename)s"')
|
||||||
|
else:
|
||||||
|
title = _('Preview of "%(pagename)s"')
|
||||||
|
# Propagate original revision
|
||||||
|
rev = request.rev
|
||||||
|
self.set_raw_body(preview, modified=1)
|
||||||
|
|
||||||
|
# send header stuff
|
||||||
|
lock_timeout = self.lock.timeout / 60
|
||||||
|
lock_page = wikiutil.escape(self.page_name, quote=1)
|
||||||
|
lock_expire = _("Your edit lock on %(lock_page)s has expired!") % {'lock_page': lock_page}
|
||||||
|
lock_mins = _("Your edit lock on %(lock_page)s will expire in # minutes.") % {'lock_page': lock_page}
|
||||||
|
lock_secs = _("Your edit lock on %(lock_page)s will expire in # seconds.") % {'lock_page': lock_page}
|
||||||
|
|
||||||
|
# get request parameters
|
||||||
|
try:
|
||||||
|
text_rows = int(form['rows'][0])
|
||||||
|
except StandardError:
|
||||||
|
text_rows = self.cfg.edit_rows
|
||||||
|
if request.user.valid:
|
||||||
|
text_rows = int(request.user.edit_rows)
|
||||||
|
|
||||||
|
if preview is not None:
|
||||||
|
# Check for editing conflicts
|
||||||
|
if not self.exists():
|
||||||
|
# page does not exist, are we creating it?
|
||||||
|
if rev:
|
||||||
|
conflict_msg = _('Someone else deleted this page while you were editing!')
|
||||||
|
elif rev != self.current_rev():
|
||||||
|
conflict_msg = _('Someone else changed this page while you were editing!')
|
||||||
|
if self.mergeEditConflict(rev):
|
||||||
|
conflict_msg = _("""Someone else saved this page while you were editing!
|
||||||
|
Please review the page and save then. Do not save this page as it is!""")
|
||||||
|
rev = self.current_rev()
|
||||||
|
if conflict_msg:
|
||||||
|
# We don't show preview when in conflict
|
||||||
|
preview = None
|
||||||
|
|
||||||
|
elif self.exists():
|
||||||
|
# revision of existing page
|
||||||
|
rev = self.current_rev()
|
||||||
|
else:
|
||||||
|
# page creation
|
||||||
|
rev = 0
|
||||||
|
|
||||||
|
self.setConflict(bool(conflict_msg))
|
||||||
|
|
||||||
|
# Page editing is done using user language
|
||||||
|
request.setContentLanguage(request.lang)
|
||||||
|
|
||||||
|
# Get the text body for the editor field.
|
||||||
|
# TODO: what about deleted pages? show the text of the last revision or use the template?
|
||||||
|
if preview is not None:
|
||||||
|
raw_body = self.get_raw_body()
|
||||||
|
if use_draft:
|
||||||
|
request.write(_("[Content loaded from draft]"), '<br>')
|
||||||
|
elif self.exists():
|
||||||
|
# If the page exists, we get the text from the page.
|
||||||
|
# TODO: maybe warn if template argument was ignored because the page exists?
|
||||||
|
raw_body = self.get_raw_body()
|
||||||
|
elif 'template' in form:
|
||||||
|
# If the page does not exist, we try to get the content from the template parameter.
|
||||||
|
template_page = wikiutil.unquoteWikiname(form['template'][0])
|
||||||
|
if request.user.may.read(template_page):
|
||||||
|
raw_body = Page(request, template_page).get_raw_body()
|
||||||
|
if raw_body:
|
||||||
|
request.write(_("[Content of new page loaded from %s]") % (template_page, ), '<br>')
|
||||||
|
else:
|
||||||
|
request.write(_("[Template %s not found]") % (template_page, ), '<br>')
|
||||||
|
else:
|
||||||
|
request.write(_("[You may not read %s]") % (template_page, ), '<br>')
|
||||||
|
|
||||||
|
# Make backup on previews - but not for new empty pages
|
||||||
|
if not use_draft and preview and raw_body:
|
||||||
|
self._save_draft(raw_body, rev)
|
||||||
|
|
||||||
|
draft_message = None
|
||||||
|
loadable_draft = False
|
||||||
|
if preview is None:
|
||||||
|
draft = self._load_draft()
|
||||||
|
if draft is not None:
|
||||||
|
draft_timestamp, draft_rev, draft_text = draft
|
||||||
|
if draft_text != raw_body:
|
||||||
|
loadable_draft = True
|
||||||
|
page_rev = rev
|
||||||
|
draft_timestamp_str = request.user.getFormattedDateTime(draft_timestamp)
|
||||||
|
draft_message = _(u"'''<<BR>>Your draft based on revision %(draft_rev)d (saved %(draft_timestamp_str)s) can be loaded instead of the current revision %(page_rev)d by using the load draft button - in case you lost your last edit somehow without saving it.''' A draft gets saved for you when you do a preview, cancel an edit or unsuccessfully save.", wiki=True, percent=True) % locals()
|
||||||
|
|
||||||
|
# Setup status message
|
||||||
|
status = [kw.get('msg', ''), conflict_msg, edit_lock_message, draft_message]
|
||||||
|
status = [msg for msg in status if msg]
|
||||||
|
status = ' '.join(status)
|
||||||
|
status = Status(request, content=status)
|
||||||
|
|
||||||
|
request.theme.add_msg(status, "error")
|
||||||
|
request.theme.send_title(
|
||||||
|
title % {'pagename': self.split_title(), },
|
||||||
|
page=self,
|
||||||
|
html_head=self.lock.locktype and (
|
||||||
|
PageEditor._countdown_js % {
|
||||||
|
'countdown_script': request.theme.externalScript('countdown'),
|
||||||
|
'lock_timeout': lock_timeout,
|
||||||
|
'lock_expire': lock_expire,
|
||||||
|
'lock_mins': lock_mins,
|
||||||
|
'lock_secs': lock_secs,
|
||||||
|
}) or '',
|
||||||
|
editor_mode=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
request.write(request.formatter.startContent("content"))
|
||||||
|
|
||||||
|
# Generate default content for new pages
|
||||||
|
if not raw_body:
|
||||||
|
raw_body = _('Describe %s here.') % (self.page_name, )
|
||||||
|
|
||||||
|
# send form
|
||||||
|
request.write('<form id="editor" method="post" action="%s/%s#preview">' % (
|
||||||
|
request.getScriptname(),
|
||||||
|
wikiutil.quoteWikinameURL(self.page_name),
|
||||||
|
))
|
||||||
|
|
||||||
|
# yet another weird workaround for broken IE6 (it expands the text
|
||||||
|
# editor area to the right after you begin to type...). IE sucks...
|
||||||
|
# http://fplanque.net/2003/Articles/iecsstextarea/
|
||||||
|
request.write('<fieldset style="border:none;padding:0;">')
|
||||||
|
|
||||||
|
request.write(unicode(html.INPUT(type="hidden", name="action", value="edit")))
|
||||||
|
|
||||||
|
# Send revision of the page our edit is based on
|
||||||
|
request.write('<input type="hidden" name="rev" value="%d">' % (rev, ))
|
||||||
|
|
||||||
|
# Add src format (e.g. 'wiki') into a hidden form field, so that
|
||||||
|
# we can load the correct converter after POSTing.
|
||||||
|
request.write('<input type="hidden" name="format" value="%s">' % self.pi['format'])
|
||||||
|
|
||||||
|
# Create and send a ticket, so we can check the POST
|
||||||
|
request.write('<input type="hidden" name="ticket" value="%s">' % wikiutil.createTicket(request))
|
||||||
|
|
||||||
|
# Save backto in a hidden input
|
||||||
|
backto = form.get('backto', [None])[0]
|
||||||
|
if backto:
|
||||||
|
request.write(unicode(html.INPUT(type="hidden", name="backto", value=backto)))
|
||||||
|
|
||||||
|
# button bar
|
||||||
|
button_spellcheck = '<input class="button" type="submit" name="button_spellcheck" value="%s">' % _('Check Spelling')
|
||||||
|
|
||||||
|
save_button_text = _('Save Changes')
|
||||||
|
cancel_button_text = _('Cancel')
|
||||||
|
|
||||||
|
if self.cfg.page_license_enabled:
|
||||||
|
request.write('<p><em>', _(
|
||||||
|
"""By hitting '''%(save_button_text)s''' you put your changes under the %(license_link)s.
|
||||||
|
If you don't want that, hit '''%(cancel_button_text)s''' to cancel your changes.""", wiki=True) % {
|
||||||
|
'save_button_text': save_button_text,
|
||||||
|
'cancel_button_text': cancel_button_text,
|
||||||
|
'license_link': wikiutil.getLocalizedPage(request, self.cfg.page_license_page).link_to(request),
|
||||||
|
}, '</em></p>')
|
||||||
|
|
||||||
|
request.write('''
|
||||||
|
<input class="button" type="submit" name="button_save" value="%s">
|
||||||
|
<input class="button" type="submit" name="button_preview" value="%s">
|
||||||
|
<input class="button" type="submit" name="button_switch" value="%s">
|
||||||
|
''' % (save_button_text, _('Preview'), _('Text mode'), ))
|
||||||
|
|
||||||
|
if loadable_draft:
|
||||||
|
request.write('''
|
||||||
|
<input class="button" type="submit" name="button_load_draft" value="%s" onClick="flgChange = false;">
|
||||||
|
<input type="hidden" name="draft_ts" value="%d">
|
||||||
|
<input type="hidden" name="draft_rev" value="%d">
|
||||||
|
''' % (_('Load Draft'), draft_timestamp, draft_rev))
|
||||||
|
|
||||||
|
request.write('''
|
||||||
|
%s
|
||||||
|
<input class="button" type="submit" name="button_cancel" value="%s">
|
||||||
|
<input type="hidden" name="editor" value="gui">
|
||||||
|
''' % (button_spellcheck, cancel_button_text, ))
|
||||||
|
if self.cfg.mail_enabled:
|
||||||
|
request.write('''
|
||||||
|
<script type="text/javascript">
|
||||||
|
function toggle_trivial(CheckedBox)
|
||||||
|
{
|
||||||
|
TrivialBoxes = document.getElementsByName("trivial");
|
||||||
|
for (var i = 0; i < TrivialBoxes.length; i++)
|
||||||
|
TrivialBoxes[i].checked = CheckedBox.checked;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<input type="checkbox" name="trivial" id="chktrivialtop" value="1" %(checked)s onclick="toggle_trivial(this)">
|
||||||
|
<label for="chktrivialtop">%(label)s</label>
|
||||||
|
''' % {
|
||||||
|
'checked': ('', 'checked')[form.get('trivial', ['0'])[0] == '1'],
|
||||||
|
'label': _("Trivial change"),
|
||||||
|
})
|
||||||
|
|
||||||
|
from MoinMoin.security.textcha import TextCha
|
||||||
|
request.write(TextCha(request).render())
|
||||||
|
|
||||||
|
self.sendconfirmleaving() # TODO update state of flgChange to make this work, see PageEditor
|
||||||
|
|
||||||
|
# Add textarea with page text
|
||||||
|
lang = self.pi.get('language', request.cfg.language_default)
|
||||||
|
contentlangdirection = i18n.getDirection(lang) # 'ltr' or 'rtl'
|
||||||
|
uilanguage = request.lang
|
||||||
|
url_prefix_static = request.cfg.url_prefix_static
|
||||||
|
url_prefix_local = request.cfg.url_prefix_local
|
||||||
|
wikipage = wikiutil.quoteWikinameURL(self.page_name)
|
||||||
|
fckbasepath = url_prefix_local + '/applets/FCKeditor'
|
||||||
|
wikiurl = request.getScriptname()
|
||||||
|
if not wikiurl or wikiurl[-1] != '/':
|
||||||
|
wikiurl += '/'
|
||||||
|
themepath = '%s/%s' % (url_prefix_static, request.theme.name)
|
||||||
|
smileypath = themepath + '/img'
|
||||||
|
# auto-generating a list for SmileyImages does NOT work from here!
|
||||||
|
editor_size = int(request.user.edit_rows) * 22 # 22 height_pixels/line
|
||||||
|
word_rule = self.word_rule()
|
||||||
|
|
||||||
|
request.write("""
|
||||||
|
<script type="text/javascript" src="%(fckbasepath)s/fckeditor.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
<!--
|
||||||
|
var oFCKeditor = new FCKeditor( 'savetext', '100%%', %(editor_size)s, 'MoinDefault' ) ;
|
||||||
|
oFCKeditor.BasePath= '%(fckbasepath)s/' ;
|
||||||
|
oFCKeditor.Config['WikiBasePath'] = '%(wikiurl)s' ;
|
||||||
|
oFCKeditor.Config['WikiPage'] = '%(wikipage)s' ;
|
||||||
|
oFCKeditor.Config['PluginsPath'] = '%(url_prefix_local)s/applets/moinFCKplugins/' ;
|
||||||
|
oFCKeditor.Config['CustomConfigurationsPath'] = '%(url_prefix_local)s/applets/moinfckconfig.js' ;
|
||||||
|
oFCKeditor.Config['WordRule'] = %(word_rule)s ;
|
||||||
|
oFCKeditor.Config['SmileyPath'] = '%(smileypath)s/' ;
|
||||||
|
oFCKeditor.Config['EditorAreaCSS'] = '%(themepath)s/css/common.css' ;
|
||||||
|
oFCKeditor.Config['SkinPath'] = '%(fckbasepath)s/editor/skins/silver/' ;
|
||||||
|
oFCKeditor.Config['AutoDetectLanguage'] = false ;
|
||||||
|
oFCKeditor.Config['DefaultLanguage'] = '%(uilanguage)s' ;
|
||||||
|
oFCKeditor.Config['ContentLangDirection'] = '%(contentlangdirection)s' ;
|
||||||
|
oFCKeditor.Value= """ % locals())
|
||||||
|
|
||||||
|
from MoinMoin.formatter.text_gedit import Formatter
|
||||||
|
self.formatter = Formatter(request)
|
||||||
|
self.formatter.page = self
|
||||||
|
output = request.redirectedOutput(self.send_page_content, request, raw_body, format=self.pi['format'], do_cache=False)
|
||||||
|
output = repr(output)
|
||||||
|
if output[0] == 'u':
|
||||||
|
output = output[1:]
|
||||||
|
request.write(output)
|
||||||
|
request.write(""" ;
|
||||||
|
oFCKeditor.Create() ;
|
||||||
|
//-->
|
||||||
|
</script>
|
||||||
|
""")
|
||||||
|
request.write("<p>")
|
||||||
|
request.write(_("Comment:"),
|
||||||
|
' <input id="editor-comment" type="text" name="comment" value="%s" size="80" maxlength="200">' % (
|
||||||
|
wikiutil.escape(kw.get('comment', ''), 1), ))
|
||||||
|
request.write("</p>")
|
||||||
|
|
||||||
|
# Category selection
|
||||||
|
filterfn = self.cfg.cache.page_category_regexact.search
|
||||||
|
cat_pages = request.rootpage.getPageList(filter=filterfn)
|
||||||
|
cat_pages.sort()
|
||||||
|
cat_pages = [wikiutil.pagelinkmarkup(p) for p in cat_pages]
|
||||||
|
cat_pages.insert(0, ('', _('<No addition>')))
|
||||||
|
request.write("<p>")
|
||||||
|
request.write(_('Add to: %(category)s') % {
|
||||||
|
'category': unicode(web.makeSelection('category', cat_pages)),
|
||||||
|
})
|
||||||
|
if self.cfg.mail_enabled:
|
||||||
|
request.write('''
|
||||||
|
|
||||||
|
<input type="checkbox" name="trivial" id="chktrivial" value="1" %(checked)s onclick="toggle_trivial(this)">
|
||||||
|
<label for="chktrivial">%(label)s</label> ''' % {
|
||||||
|
'checked': ('', 'checked')[form.get('trivial', ['0'])[0] == '1'],
|
||||||
|
'label': _("Trivial change"),
|
||||||
|
})
|
||||||
|
|
||||||
|
request.write('''
|
||||||
|
|
||||||
|
<input type="checkbox" name="rstrip" id="chkrstrip" value="1" %(checked)s>
|
||||||
|
<label for="chkrstrip">%(label)s</label>
|
||||||
|
</p> ''' % {
|
||||||
|
'checked': ('', 'checked')[form.get('rstrip', ['0'])[0] == '1'],
|
||||||
|
'label': _('Remove trailing whitespace from each line')
|
||||||
|
})
|
||||||
|
|
||||||
|
request.write("</p>")
|
||||||
|
|
||||||
|
badwords_re = None
|
||||||
|
if preview is not None:
|
||||||
|
if 'button_spellcheck' in form or 'button_newwords' in form:
|
||||||
|
badwords, badwords_re, msg = SpellCheck.checkSpelling(self, request, own_form=0)
|
||||||
|
request.write("<p>%s</p>" % msg)
|
||||||
|
request.write('</fieldset>')
|
||||||
|
request.write("</form>")
|
||||||
|
|
||||||
|
if preview is not None:
|
||||||
|
if staytop:
|
||||||
|
content_id = 'previewbelow'
|
||||||
|
else:
|
||||||
|
content_id = 'preview'
|
||||||
|
self.send_page(content_id=content_id, content_only=1, hilite_re=badwords_re)
|
||||||
|
|
||||||
|
request.write(request.formatter.endContent()) # end content div
|
||||||
|
request.theme.send_footer(self.page_name)
|
||||||
|
request.theme.send_closing_html()
|
||||||
|
|
428
wiki-lenny/share/PageGraphicalEditor.py
Normal file
428
wiki-lenny/share/PageGraphicalEditor.py
Normal file
|
@ -0,0 +1,428 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
MoinMoin - Call the GUI editor (FCKeditor)
|
||||||
|
|
||||||
|
Same as PageEditor, but we use the HTML based GUI editor here.
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
* see PageEditor.py
|
||||||
|
|
||||||
|
@copyright: 2006 Bastian Blank, Florian Festi,
|
||||||
|
2006-2007 MoinMoin:ThomasWaldmann
|
||||||
|
@license: GNU GPL, see COPYING for details.
|
||||||
|
"""
|
||||||
|
import re
|
||||||
|
|
||||||
|
from MoinMoin import PageEditor
|
||||||
|
from MoinMoin import wikiutil
|
||||||
|
from MoinMoin.Page import Page
|
||||||
|
from MoinMoin.widget import html
|
||||||
|
from MoinMoin.widget.dialog import Status
|
||||||
|
from MoinMoin.util import web
|
||||||
|
from MoinMoin.parser.text_moin_wiki import Parser as WikiParser
|
||||||
|
|
||||||
|
def execute(pagename, request):
|
||||||
|
if not request.user.may.write(pagename):
|
||||||
|
_ = request.getText
|
||||||
|
request.theme.add_msg_('You are not allowed to edit this page.', "error")
|
||||||
|
Page(request, pagename).send_page()
|
||||||
|
return
|
||||||
|
|
||||||
|
PageGraphicalEditor(request, pagename).sendEditor()
|
||||||
|
|
||||||
|
|
||||||
|
class PageGraphicalEditor(PageEditor.PageEditor):
|
||||||
|
""" Same as PageEditor, but use the GUI editor (FCKeditor) """
|
||||||
|
def word_rule(self):
|
||||||
|
regex = re.compile(r"\(\?<![^)]*?\)")
|
||||||
|
word_rule = regex.sub("", WikiParser.word_rule_js)
|
||||||
|
return repr(word_rule)[1:]
|
||||||
|
|
||||||
|
def sendEditor(self, **kw):
|
||||||
|
""" Send the editor form page.
|
||||||
|
|
||||||
|
@keyword preview: if given, show this text in preview mode
|
||||||
|
@keyword staytop: don't go to #preview
|
||||||
|
@keyword comment: comment field (when preview is true)
|
||||||
|
"""
|
||||||
|
from MoinMoin import i18n
|
||||||
|
from MoinMoin.action import SpellCheck
|
||||||
|
|
||||||
|
request = self.request
|
||||||
|
form = request.form
|
||||||
|
_ = self._
|
||||||
|
request.disableHttpCaching(level=2)
|
||||||
|
page_categories = self.getCategories(request)
|
||||||
|
|
||||||
|
|
||||||
|
raw_body = ''
|
||||||
|
msg = None
|
||||||
|
conflict_msg = None
|
||||||
|
edit_lock_message = None
|
||||||
|
preview = kw.get('preview', None)
|
||||||
|
staytop = kw.get('staytop', 0)
|
||||||
|
|
||||||
|
# check edit permissions
|
||||||
|
if not request.user.may.write(self.page_name):
|
||||||
|
# L'effet de bord dans le test empêche-t-il la ligne suivante
|
||||||
|
# d'être exécutée ?
|
||||||
|
msg = _('You are not allowed to edit this page.')
|
||||||
|
elif not self.isWritable():
|
||||||
|
# même remarque.
|
||||||
|
msg = _('Page is immutable!')
|
||||||
|
elif self.rev:
|
||||||
|
# Trying to edit an old version, this is not possible via
|
||||||
|
# the web interface, but catch it just in case...
|
||||||
|
msg = _('Cannot edit old revisions!')
|
||||||
|
elif u"CatégorieEditeurGraphiqueInterdit" in page_categories:
|
||||||
|
msg =_('Cannot edit this page with the graphical editor')
|
||||||
|
request.theme.add_msg(msg, "error")
|
||||||
|
from MoinMoin.PageEditor import PageTextEditor
|
||||||
|
# Pour éviter à l'utilisateur de rester sur le cul, on le
|
||||||
|
# redirige vers l'éditeur texte
|
||||||
|
pg = PageTextEditor(request, self.page_name, **kw)
|
||||||
|
pg.sendEditor()
|
||||||
|
else:
|
||||||
|
# try to acquire edit lock
|
||||||
|
ok, edit_lock_message = self.lock.acquire()
|
||||||
|
if not ok:
|
||||||
|
# failed to get the lock
|
||||||
|
if preview is not None:
|
||||||
|
edit_lock_message = _('The lock you held timed out. Be prepared for editing conflicts!'
|
||||||
|
) + "<br>" + edit_lock_message
|
||||||
|
else:
|
||||||
|
msg = edit_lock_message
|
||||||
|
|
||||||
|
# Did one of the prechecks fail?
|
||||||
|
if msg:
|
||||||
|
request.theme.add_msg(msg, "error")
|
||||||
|
# Il est manifestement hors de question d'avoir envoyé les
|
||||||
|
# headers http avant d'appeler cette fonction
|
||||||
|
self.send_page()
|
||||||
|
return
|
||||||
|
|
||||||
|
# par contre, il faut les envoyer dans le cas contraire
|
||||||
|
request.emit_http_headers()
|
||||||
|
|
||||||
|
# check if we want to load a draft
|
||||||
|
use_draft = None
|
||||||
|
if 'button_load_draft' in form:
|
||||||
|
wanted_draft_timestamp = int(form.get('draft_ts', ['0'])[0])
|
||||||
|
if wanted_draft_timestamp:
|
||||||
|
draft = self._load_draft()
|
||||||
|
if draft is not None:
|
||||||
|
draft_timestamp, draft_rev, draft_text = draft
|
||||||
|
if draft_timestamp == wanted_draft_timestamp:
|
||||||
|
use_draft = draft_text
|
||||||
|
|
||||||
|
# Check for draft / normal / preview submit
|
||||||
|
if use_draft is not None:
|
||||||
|
title = _('Draft of "%(pagename)s"')
|
||||||
|
# Propagate original revision
|
||||||
|
rev = int(form['draft_rev'][0])
|
||||||
|
self.set_raw_body(use_draft, modified=1)
|
||||||
|
preview = use_draft
|
||||||
|
elif preview is None:
|
||||||
|
title = _('Edit "%(pagename)s"')
|
||||||
|
else:
|
||||||
|
title = _('Preview of "%(pagename)s"')
|
||||||
|
# Propagate original revision
|
||||||
|
rev = request.rev
|
||||||
|
self.set_raw_body(preview, modified=1)
|
||||||
|
|
||||||
|
# send header stuff
|
||||||
|
lock_timeout = self.lock.timeout / 60
|
||||||
|
lock_page = wikiutil.escape(self.page_name, quote=1)
|
||||||
|
lock_expire = _("Your edit lock on %(lock_page)s has expired!") % {'lock_page': lock_page}
|
||||||
|
lock_mins = _("Your edit lock on %(lock_page)s will expire in # minutes.") % {'lock_page': lock_page}
|
||||||
|
lock_secs = _("Your edit lock on %(lock_page)s will expire in # seconds.") % {'lock_page': lock_page}
|
||||||
|
|
||||||
|
# get request parameters
|
||||||
|
try:
|
||||||
|
text_rows = int(form['rows'][0])
|
||||||
|
except StandardError:
|
||||||
|
text_rows = self.cfg.edit_rows
|
||||||
|
if request.user.valid:
|
||||||
|
text_rows = int(request.user.edit_rows)
|
||||||
|
|
||||||
|
if preview is not None:
|
||||||
|
# Check for editing conflicts
|
||||||
|
if not self.exists():
|
||||||
|
# page does not exist, are we creating it?
|
||||||
|
if rev:
|
||||||
|
conflict_msg = _('Someone else deleted this page while you were editing!')
|
||||||
|
elif rev != self.current_rev():
|
||||||
|
conflict_msg = _('Someone else changed this page while you were editing!')
|
||||||
|
if self.mergeEditConflict(rev):
|
||||||
|
conflict_msg = _("""Someone else saved this page while you were editing!
|
||||||
|
Please review the page and save then. Do not save this page as it is!""")
|
||||||
|
rev = self.current_rev()
|
||||||
|
if conflict_msg:
|
||||||
|
# We don't show preview when in conflict
|
||||||
|
preview = None
|
||||||
|
|
||||||
|
elif self.exists():
|
||||||
|
# revision of existing page
|
||||||
|
rev = self.current_rev()
|
||||||
|
else:
|
||||||
|
# page creation
|
||||||
|
rev = 0
|
||||||
|
|
||||||
|
self.setConflict(bool(conflict_msg))
|
||||||
|
|
||||||
|
# Page editing is done using user language
|
||||||
|
request.setContentLanguage(request.lang)
|
||||||
|
|
||||||
|
# Get the text body for the editor field.
|
||||||
|
# TODO: what about deleted pages? show the text of the last revision or use the template?
|
||||||
|
if preview is not None:
|
||||||
|
raw_body = self.get_raw_body()
|
||||||
|
if use_draft:
|
||||||
|
request.write(_("[Content loaded from draft]"), '<br>')
|
||||||
|
elif self.exists():
|
||||||
|
# If the page exists, we get the text from the page.
|
||||||
|
# TODO: maybe warn if template argument was ignored because the page exists?
|
||||||
|
raw_body = self.get_raw_body()
|
||||||
|
elif 'template' in form:
|
||||||
|
# If the page does not exist, we try to get the content from the template parameter.
|
||||||
|
template_page = wikiutil.unquoteWikiname(form['template'][0])
|
||||||
|
if request.user.may.read(template_page):
|
||||||
|
raw_body = Page(request, template_page).get_raw_body()
|
||||||
|
if raw_body:
|
||||||
|
request.write(_("[Content of new page loaded from %s]") % (template_page, ), '<br>')
|
||||||
|
else:
|
||||||
|
request.write(_("[Template %s not found]") % (template_page, ), '<br>')
|
||||||
|
else:
|
||||||
|
request.write(_("[You may not read %s]") % (template_page, ), '<br>')
|
||||||
|
|
||||||
|
# Make backup on previews - but not for new empty pages
|
||||||
|
if not use_draft and preview and raw_body:
|
||||||
|
self._save_draft(raw_body, rev)
|
||||||
|
|
||||||
|
draft_message = None
|
||||||
|
loadable_draft = False
|
||||||
|
if preview is None:
|
||||||
|
draft = self._load_draft()
|
||||||
|
if draft is not None:
|
||||||
|
draft_timestamp, draft_rev, draft_text = draft
|
||||||
|
if draft_text != raw_body:
|
||||||
|
loadable_draft = True
|
||||||
|
page_rev = rev
|
||||||
|
draft_timestamp_str = request.user.getFormattedDateTime(draft_timestamp)
|
||||||
|
draft_message = _(u"'''<<BR>>Your draft based on revision %(draft_rev)d (saved %(draft_timestamp_str)s) can be loaded instead of the current revision %(page_rev)d by using the load draft button - in case you lost your last edit somehow without saving it.''' A draft gets saved for you when you do a preview, cancel an edit or unsuccessfully save.", wiki=True, percent=True) % locals()
|
||||||
|
|
||||||
|
# Setup status message
|
||||||
|
status = [kw.get('msg', ''), conflict_msg, edit_lock_message, draft_message]
|
||||||
|
status = [msg for msg in status if msg]
|
||||||
|
status = ' '.join(status)
|
||||||
|
status = Status(request, content=status)
|
||||||
|
|
||||||
|
request.theme.add_msg(status, "error")
|
||||||
|
request.theme.send_title(
|
||||||
|
title % {'pagename': self.split_title(), },
|
||||||
|
page=self,
|
||||||
|
html_head=self.lock.locktype and (
|
||||||
|
PageEditor._countdown_js % {
|
||||||
|
'countdown_script': request.theme.externalScript('countdown'),
|
||||||
|
'lock_timeout': lock_timeout,
|
||||||
|
'lock_expire': lock_expire,
|
||||||
|
'lock_mins': lock_mins,
|
||||||
|
'lock_secs': lock_secs,
|
||||||
|
}) or '',
|
||||||
|
editor_mode=1,
|
||||||
|
)
|
||||||
|
|
||||||
|
request.write(request.formatter.startContent("content"))
|
||||||
|
|
||||||
|
# Generate default content for new pages
|
||||||
|
if not raw_body:
|
||||||
|
raw_body = _('Describe %s here.') % (self.page_name, )
|
||||||
|
|
||||||
|
# send form
|
||||||
|
request.write('<form id="editor" method="post" action="%s/%s#preview">' % (
|
||||||
|
request.getScriptname(),
|
||||||
|
wikiutil.quoteWikinameURL(self.page_name),
|
||||||
|
))
|
||||||
|
|
||||||
|
# yet another weird workaround for broken IE6 (it expands the text
|
||||||
|
# editor area to the right after you begin to type...). IE sucks...
|
||||||
|
# http://fplanque.net/2003/Articles/iecsstextarea/
|
||||||
|
request.write('<fieldset style="border:none;padding:0;">')
|
||||||
|
|
||||||
|
request.write(unicode(html.INPUT(type="hidden", name="action", value="edit")))
|
||||||
|
|
||||||
|
# Send revision of the page our edit is based on
|
||||||
|
request.write('<input type="hidden" name="rev" value="%d">' % (rev, ))
|
||||||
|
|
||||||
|
# Add src format (e.g. 'wiki') into a hidden form field, so that
|
||||||
|
# we can load the correct converter after POSTing.
|
||||||
|
request.write('<input type="hidden" name="format" value="%s">' % self.pi['format'])
|
||||||
|
|
||||||
|
# Create and send a ticket, so we can check the POST
|
||||||
|
request.write('<input type="hidden" name="ticket" value="%s">' % wikiutil.createTicket(request))
|
||||||
|
|
||||||
|
# Save backto in a hidden input
|
||||||
|
backto = form.get('backto', [None])[0]
|
||||||
|
if backto:
|
||||||
|
request.write(unicode(html.INPUT(type="hidden", name="backto", value=backto)))
|
||||||
|
|
||||||
|
# button bar
|
||||||
|
button_spellcheck = '<input class="button" type="submit" name="button_spellcheck" value="%s">' % _('Check Spelling')
|
||||||
|
|
||||||
|
save_button_text = _('Save Changes')
|
||||||
|
cancel_button_text = _('Cancel')
|
||||||
|
|
||||||
|
if self.cfg.page_license_enabled:
|
||||||
|
request.write('<p><em>', _(
|
||||||
|
"""By hitting '''%(save_button_text)s''' you put your changes under the %(license_link)s.
|
||||||
|
If you don't want that, hit '''%(cancel_button_text)s''' to cancel your changes.""", wiki=True) % {
|
||||||
|
'save_button_text': save_button_text,
|
||||||
|
'cancel_button_text': cancel_button_text,
|
||||||
|
'license_link': wikiutil.getLocalizedPage(request, self.cfg.page_license_page).link_to(request),
|
||||||
|
}, '</em></p>')
|
||||||
|
|
||||||
|
request.write('''
|
||||||
|
<input class="button" type="submit" name="button_save" value="%s">
|
||||||
|
<input class="button" type="submit" name="button_preview" value="%s">
|
||||||
|
<input class="button" type="submit" name="button_switch" value="%s">
|
||||||
|
''' % (save_button_text, _('Preview'), _('Text mode'), ))
|
||||||
|
|
||||||
|
if loadable_draft:
|
||||||
|
request.write('''
|
||||||
|
<input class="button" type="submit" name="button_load_draft" value="%s" onClick="flgChange = false;">
|
||||||
|
<input type="hidden" name="draft_ts" value="%d">
|
||||||
|
<input type="hidden" name="draft_rev" value="%d">
|
||||||
|
''' % (_('Load Draft'), draft_timestamp, draft_rev))
|
||||||
|
|
||||||
|
request.write('''
|
||||||
|
%s
|
||||||
|
<input class="button" type="submit" name="button_cancel" value="%s">
|
||||||
|
<input type="hidden" name="editor" value="gui">
|
||||||
|
''' % (button_spellcheck, cancel_button_text, ))
|
||||||
|
if self.cfg.mail_enabled:
|
||||||
|
request.write('''
|
||||||
|
<script type="text/javascript">
|
||||||
|
function toggle_trivial(CheckedBox)
|
||||||
|
{
|
||||||
|
TrivialBoxes = document.getElementsByName("trivial");
|
||||||
|
for (var i = 0; i < TrivialBoxes.length; i++)
|
||||||
|
TrivialBoxes[i].checked = CheckedBox.checked;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<input type="checkbox" name="trivial" id="chktrivialtop" value="1" %(checked)s onclick="toggle_trivial(this)">
|
||||||
|
<label for="chktrivialtop">%(label)s</label>
|
||||||
|
''' % {
|
||||||
|
'checked': ('', 'checked')[form.get('trivial', ['0'])[0] == '1'],
|
||||||
|
'label': _("Trivial change"),
|
||||||
|
})
|
||||||
|
|
||||||
|
from MoinMoin.security.textcha import TextCha
|
||||||
|
request.write(TextCha(request).render())
|
||||||
|
|
||||||
|
self.sendconfirmleaving() # TODO update state of flgChange to make this work, see PageEditor
|
||||||
|
|
||||||
|
# Add textarea with page text
|
||||||
|
lang = self.pi.get('language', request.cfg.language_default)
|
||||||
|
contentlangdirection = i18n.getDirection(lang) # 'ltr' or 'rtl'
|
||||||
|
uilanguage = request.lang
|
||||||
|
url_prefix_static = request.cfg.url_prefix_static
|
||||||
|
url_prefix_local = request.cfg.url_prefix_local
|
||||||
|
wikipage = wikiutil.quoteWikinameURL(self.page_name)
|
||||||
|
fckbasepath = url_prefix_local + '/applets/FCKeditor'
|
||||||
|
wikiurl = request.getScriptname()
|
||||||
|
if not wikiurl or wikiurl[-1] != '/':
|
||||||
|
wikiurl += '/'
|
||||||
|
themepath = '%s/%s' % (url_prefix_static, request.theme.name)
|
||||||
|
smileypath = themepath + '/img'
|
||||||
|
# auto-generating a list for SmileyImages does NOT work from here!
|
||||||
|
editor_size = int(request.user.edit_rows) * 22 # 22 height_pixels/line
|
||||||
|
word_rule = self.word_rule()
|
||||||
|
|
||||||
|
request.write("""
|
||||||
|
<script type="text/javascript" src="%(fckbasepath)s/fckeditor.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
<!--
|
||||||
|
var oFCKeditor = new FCKeditor( 'savetext', '100%%', %(editor_size)s, 'MoinDefault' ) ;
|
||||||
|
oFCKeditor.BasePath= '%(fckbasepath)s/' ;
|
||||||
|
oFCKeditor.Config['WikiBasePath'] = '%(wikiurl)s' ;
|
||||||
|
oFCKeditor.Config['WikiPage'] = '%(wikipage)s' ;
|
||||||
|
oFCKeditor.Config['PluginsPath'] = '%(url_prefix_local)s/applets/moinFCKplugins/' ;
|
||||||
|
oFCKeditor.Config['CustomConfigurationsPath'] = '%(url_prefix_local)s/applets/moinfckconfig.js' ;
|
||||||
|
oFCKeditor.Config['WordRule'] = %(word_rule)s ;
|
||||||
|
oFCKeditor.Config['SmileyPath'] = '%(smileypath)s/' ;
|
||||||
|
oFCKeditor.Config['EditorAreaCSS'] = '%(themepath)s/css/common.css' ;
|
||||||
|
oFCKeditor.Config['SkinPath'] = '%(fckbasepath)s/editor/skins/silver/' ;
|
||||||
|
oFCKeditor.Config['AutoDetectLanguage'] = false ;
|
||||||
|
oFCKeditor.Config['DefaultLanguage'] = '%(uilanguage)s' ;
|
||||||
|
oFCKeditor.Config['ContentLangDirection'] = '%(contentlangdirection)s' ;
|
||||||
|
oFCKeditor.Value= """ % locals())
|
||||||
|
|
||||||
|
from MoinMoin.formatter.text_gedit import Formatter
|
||||||
|
self.formatter = Formatter(request)
|
||||||
|
self.formatter.page = self
|
||||||
|
output = request.redirectedOutput(self.send_page_content, request, raw_body, format=self.pi['format'], do_cache=False)
|
||||||
|
output = repr(output)
|
||||||
|
if output[0] == 'u':
|
||||||
|
output = output[1:]
|
||||||
|
request.write(output)
|
||||||
|
request.write(""" ;
|
||||||
|
oFCKeditor.Create() ;
|
||||||
|
//-->
|
||||||
|
</script>
|
||||||
|
""")
|
||||||
|
request.write("<p>")
|
||||||
|
request.write(_("Comment:"),
|
||||||
|
' <input id="editor-comment" type="text" name="comment" value="%s" size="80" maxlength="200">' % (
|
||||||
|
wikiutil.escape(kw.get('comment', ''), 1), ))
|
||||||
|
request.write("</p>")
|
||||||
|
|
||||||
|
# Category selection
|
||||||
|
filterfn = self.cfg.cache.page_category_regexact.search
|
||||||
|
cat_pages = request.rootpage.getPageList(filter=filterfn)
|
||||||
|
cat_pages.sort()
|
||||||
|
cat_pages = [wikiutil.pagelinkmarkup(p) for p in cat_pages]
|
||||||
|
cat_pages.insert(0, ('', _('<No addition>')))
|
||||||
|
request.write("<p>")
|
||||||
|
request.write(_('Add to: %(category)s') % {
|
||||||
|
'category': unicode(web.makeSelection('category', cat_pages)),
|
||||||
|
})
|
||||||
|
if self.cfg.mail_enabled:
|
||||||
|
request.write('''
|
||||||
|
|
||||||
|
<input type="checkbox" name="trivial" id="chktrivial" value="1" %(checked)s onclick="toggle_trivial(this)">
|
||||||
|
<label for="chktrivial">%(label)s</label> ''' % {
|
||||||
|
'checked': ('', 'checked')[form.get('trivial', ['0'])[0] == '1'],
|
||||||
|
'label': _("Trivial change"),
|
||||||
|
})
|
||||||
|
|
||||||
|
request.write('''
|
||||||
|
|
||||||
|
<input type="checkbox" name="rstrip" id="chkrstrip" value="1" %(checked)s>
|
||||||
|
<label for="chkrstrip">%(label)s</label>
|
||||||
|
</p> ''' % {
|
||||||
|
'checked': ('', 'checked')[form.get('rstrip', ['0'])[0] == '1'],
|
||||||
|
'label': _('Remove trailing whitespace from each line')
|
||||||
|
})
|
||||||
|
|
||||||
|
request.write("</p>")
|
||||||
|
|
||||||
|
badwords_re = None
|
||||||
|
if preview is not None:
|
||||||
|
if 'button_spellcheck' in form or 'button_newwords' in form:
|
||||||
|
badwords, badwords_re, msg = SpellCheck.checkSpelling(self, request, own_form=0)
|
||||||
|
request.write("<p>%s</p>" % msg)
|
||||||
|
request.write('</fieldset>')
|
||||||
|
request.write("</form>")
|
||||||
|
|
||||||
|
if preview is not None:
|
||||||
|
if staytop:
|
||||||
|
content_id = 'previewbelow'
|
||||||
|
else:
|
||||||
|
content_id = 'preview'
|
||||||
|
self.send_page(content_id=content_id, content_only=1, hilite_re=badwords_re)
|
||||||
|
|
||||||
|
request.write(request.formatter.endContent()) # end content div
|
||||||
|
request.theme.send_footer(self.page_name)
|
||||||
|
request.theme.send_closing_html()
|
||||||
|
|
187
wiki-lenny/share/action.edit.orig.py
Normal file
187
wiki-lenny/share/action.edit.orig.py
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
# -*- coding: iso-8859-1 -*-
|
||||||
|
"""
|
||||||
|
MoinMoin - edit a page
|
||||||
|
|
||||||
|
This either calls the text or the GUI page editor.
|
||||||
|
|
||||||
|
@copyright: 2000-2004 Juergen Hermann <jh@web.de>,
|
||||||
|
2006 MoinMoin:ThomasWaldmann
|
||||||
|
@license: GNU GPL, see COPYING for details.
|
||||||
|
"""
|
||||||
|
from MoinMoin import wikiutil
|
||||||
|
from MoinMoin.Page import Page
|
||||||
|
|
||||||
|
def execute(pagename, request):
|
||||||
|
""" edit a page """
|
||||||
|
_ = request.getText
|
||||||
|
|
||||||
|
if 'button_preview' in request.form and 'button_spellcheck' in request.form:
|
||||||
|
# multiple buttons pressed at once? must be some spammer/bot
|
||||||
|
request.makeForbidden403()
|
||||||
|
request.surge_protect(kick_him=True) # get rid of him
|
||||||
|
return
|
||||||
|
|
||||||
|
if not request.user.may.write(pagename):
|
||||||
|
request.theme.add_msg(_('You are not allowed to edit this page.'), "error")
|
||||||
|
Page(request, pagename).send_page()
|
||||||
|
return
|
||||||
|
|
||||||
|
valideditors = ['text', 'gui', ]
|
||||||
|
editor = ''
|
||||||
|
if request.user.valid:
|
||||||
|
editor = request.user.editor_default
|
||||||
|
if editor not in valideditors:
|
||||||
|
editor = request.cfg.editor_default
|
||||||
|
|
||||||
|
editorparam = request.form.get('editor', [editor])[0]
|
||||||
|
if editorparam == "guipossible":
|
||||||
|
lasteditor = editor
|
||||||
|
elif editorparam == "textonly":
|
||||||
|
editor = lasteditor = 'text'
|
||||||
|
else:
|
||||||
|
editor = lasteditor = editorparam
|
||||||
|
|
||||||
|
if request.cfg.editor_force:
|
||||||
|
editor = request.cfg.editor_default
|
||||||
|
|
||||||
|
# if it is still nothing valid, we just use the text editor
|
||||||
|
if editor not in valideditors:
|
||||||
|
editor = 'text'
|
||||||
|
|
||||||
|
rev = request.rev or 0
|
||||||
|
savetext = request.form.get('savetext', [None])[0]
|
||||||
|
comment = request.form.get('comment', [u''])[0]
|
||||||
|
category = request.form.get('category', [None])[0]
|
||||||
|
rstrip = int(request.form.get('rstrip', ['0'])[0])
|
||||||
|
trivial = int(request.form.get('trivial', ['0'])[0])
|
||||||
|
|
||||||
|
if 'button_switch' in request.form:
|
||||||
|
if editor == 'text':
|
||||||
|
editor = 'gui'
|
||||||
|
else: # 'gui'
|
||||||
|
editor = 'text'
|
||||||
|
|
||||||
|
# load right editor class
|
||||||
|
if editor == 'gui':
|
||||||
|
from MoinMoin.PageGraphicalEditor import PageGraphicalEditor
|
||||||
|
pg = PageGraphicalEditor(request, pagename)
|
||||||
|
else: # 'text'
|
||||||
|
from MoinMoin.PageEditor import PageEditor
|
||||||
|
pg = PageEditor(request, pagename)
|
||||||
|
|
||||||
|
# is invoked without savetext start editing
|
||||||
|
if savetext is None or 'button_load_draft' in request.form:
|
||||||
|
pg.sendEditor()
|
||||||
|
return
|
||||||
|
|
||||||
|
# did user hit cancel button?
|
||||||
|
cancelled = 'button_cancel' in request.form
|
||||||
|
|
||||||
|
if request.cfg.edit_ticketing:
|
||||||
|
ticket = request.form.get('ticket', [''])[0]
|
||||||
|
if not wikiutil.checkTicket(request, ticket):
|
||||||
|
request.theme.add_msg(_('Please use the interactive user interface to use action %(actionname)s!') % {'actionname': 'edit' }, "error")
|
||||||
|
pg.send_page()
|
||||||
|
return
|
||||||
|
|
||||||
|
from MoinMoin.error import ConvertError
|
||||||
|
try:
|
||||||
|
if lasteditor == 'gui':
|
||||||
|
# convert input from Graphical editor
|
||||||
|
format = request.form.get('format', ['wiki'])[0]
|
||||||
|
if format == 'wiki':
|
||||||
|
converter_name = 'text_html_text_moin_wiki'
|
||||||
|
else:
|
||||||
|
converter_name = 'undefined' # XXX we don't have other converters yet
|
||||||
|
convert = wikiutil.importPlugin(request.cfg, "converter", converter_name, 'convert')
|
||||||
|
savetext = convert(request, pagename, savetext)
|
||||||
|
|
||||||
|
# IMPORTANT: normalize text from the form. This should be done in
|
||||||
|
# one place before we manipulate the text.
|
||||||
|
savetext = pg.normalizeText(savetext, stripspaces=rstrip)
|
||||||
|
except ConvertError:
|
||||||
|
# we don't want to throw an exception if user cancelled anyway
|
||||||
|
if not cancelled:
|
||||||
|
raise
|
||||||
|
|
||||||
|
if cancelled:
|
||||||
|
pg.sendCancel(savetext or "", rev)
|
||||||
|
pagedir = pg.getPagePath(check_create=0)
|
||||||
|
import os
|
||||||
|
if not os.listdir(pagedir):
|
||||||
|
os.removedirs(pagedir)
|
||||||
|
return
|
||||||
|
|
||||||
|
comment = wikiutil.clean_input(comment)
|
||||||
|
|
||||||
|
# Add category
|
||||||
|
|
||||||
|
# TODO: this code does not work with extended links, and is doing
|
||||||
|
# things behind your back, and in general not needed. Either we have
|
||||||
|
# a full interface for categories (add, delete) or just add them by
|
||||||
|
# markup.
|
||||||
|
|
||||||
|
if category and category != _('<No addition>'): # opera 8.5 needs this
|
||||||
|
# strip trailing whitespace
|
||||||
|
savetext = savetext.rstrip()
|
||||||
|
|
||||||
|
# Add category separator if last non-empty line contains
|
||||||
|
# non-categories.
|
||||||
|
lines = [line for line in savetext.splitlines() if line]
|
||||||
|
if lines:
|
||||||
|
|
||||||
|
#TODO: this code is broken, will not work for extended links
|
||||||
|
#categories, e.g ["category hebrew"]
|
||||||
|
categories = lines[-1].split()
|
||||||
|
|
||||||
|
if categories:
|
||||||
|
confirmed = wikiutil.filterCategoryPages(request, categories)
|
||||||
|
if len(confirmed) < len(categories):
|
||||||
|
# This was not a categories line, add separator
|
||||||
|
savetext += u'\n----\n'
|
||||||
|
|
||||||
|
# Add new category
|
||||||
|
if savetext and savetext[-1] != u'\n':
|
||||||
|
savetext += ' '
|
||||||
|
savetext += category + u'\n' # Should end with newline!
|
||||||
|
|
||||||
|
# Preview, spellcheck or spellcheck add new words
|
||||||
|
if ('button_preview' in request.form or
|
||||||
|
'button_spellcheck' in request.form or
|
||||||
|
'button_newwords' in request.form):
|
||||||
|
pg.sendEditor(preview=savetext, comment=comment)
|
||||||
|
|
||||||
|
# Preview with mode switch
|
||||||
|
elif 'button_switch' in request.form:
|
||||||
|
pg.sendEditor(preview=savetext, comment=comment, staytop=1)
|
||||||
|
|
||||||
|
# Save new text
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
from MoinMoin.security.textcha import TextCha
|
||||||
|
if not TextCha(request).check_answer_from_form():
|
||||||
|
raise pg.SaveError(_('TextCha: Wrong answer! Go back and try again...'))
|
||||||
|
savemsg = pg.saveText(savetext, rev, trivial=trivial, comment=comment)
|
||||||
|
except pg.EditConflict, e:
|
||||||
|
msg = e.message
|
||||||
|
|
||||||
|
# Handle conflict and send editor
|
||||||
|
pg.set_raw_body(savetext, modified=1)
|
||||||
|
|
||||||
|
pg.mergeEditConflict(rev)
|
||||||
|
# We don't send preview when we do merge conflict
|
||||||
|
pg.sendEditor(msg=msg, comment=comment)
|
||||||
|
return
|
||||||
|
|
||||||
|
except pg.SaveError, msg:
|
||||||
|
# msg contains a unicode string
|
||||||
|
savemsg = unicode(msg)
|
||||||
|
|
||||||
|
# Send new page after save or after unsuccessful conflict merge.
|
||||||
|
request.reset()
|
||||||
|
pg = Page(request, pagename)
|
||||||
|
|
||||||
|
# sets revision number to default for further actions
|
||||||
|
request.rev = 0
|
||||||
|
request.theme.add_msg(savemsg, "info")
|
||||||
|
pg.send_page()
|
187
wiki-lenny/share/action.edit.py
Normal file
187
wiki-lenny/share/action.edit.py
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
# -*- coding: iso-8859-1 -*-
|
||||||
|
"""
|
||||||
|
MoinMoin - edit a page
|
||||||
|
|
||||||
|
This either calls the text or the GUI page editor.
|
||||||
|
|
||||||
|
@copyright: 2000-2004 Juergen Hermann <jh@web.de>,
|
||||||
|
2006 MoinMoin:ThomasWaldmann
|
||||||
|
@license: GNU GPL, see COPYING for details.
|
||||||
|
"""
|
||||||
|
from MoinMoin import wikiutil
|
||||||
|
from MoinMoin.Page import Page
|
||||||
|
|
||||||
|
def execute(pagename, request):
|
||||||
|
""" edit a page """
|
||||||
|
_ = request.getText
|
||||||
|
|
||||||
|
if 'button_preview' in request.form and 'button_spellcheck' in request.form:
|
||||||
|
# multiple buttons pressed at once? must be some spammer/bot
|
||||||
|
request.makeForbidden403()
|
||||||
|
request.surge_protect(kick_him=True) # get rid of him
|
||||||
|
return
|
||||||
|
|
||||||
|
if not request.user.may.write(pagename):
|
||||||
|
request.theme.add_msg(_('You are not allowed to edit this page.'), "error")
|
||||||
|
Page(request, pagename).send_page()
|
||||||
|
return
|
||||||
|
|
||||||
|
valideditors = ['text', 'gui', ]
|
||||||
|
editor = ''
|
||||||
|
if request.user.valid:
|
||||||
|
editor = request.user.editor_default
|
||||||
|
if editor not in valideditors:
|
||||||
|
editor = request.cfg.editor_default
|
||||||
|
|
||||||
|
editorparam = request.form.get('editor', [editor])[0]
|
||||||
|
if editorparam == "guipossible":
|
||||||
|
lasteditor = editor
|
||||||
|
elif editorparam == "textonly":
|
||||||
|
editor = lasteditor = 'text'
|
||||||
|
else:
|
||||||
|
editor = lasteditor = editorparam
|
||||||
|
|
||||||
|
if request.cfg.editor_force:
|
||||||
|
editor = request.cfg.editor_default
|
||||||
|
|
||||||
|
# if it is still nothing valid, we just use the text editor
|
||||||
|
if editor not in valideditors:
|
||||||
|
editor = 'text'
|
||||||
|
|
||||||
|
rev = request.rev or 0
|
||||||
|
savetext = request.form.get('savetext', [None])[0]
|
||||||
|
comment = request.form.get('comment', [u''])[0]
|
||||||
|
category = request.form.get('category', [None])[0]
|
||||||
|
rstrip = int(request.form.get('rstrip', ['0'])[0])
|
||||||
|
trivial = int(request.form.get('trivial', ['0'])[0])
|
||||||
|
|
||||||
|
if 'button_switch' in request.form:
|
||||||
|
if editor == 'text':
|
||||||
|
editor = 'gui'
|
||||||
|
else: # 'gui'
|
||||||
|
editor = 'text'
|
||||||
|
|
||||||
|
# load right editor class
|
||||||
|
if editor == 'gui':
|
||||||
|
from MoinMoin.PageGraphicalEditor import PageGraphicalEditor
|
||||||
|
pg = PageGraphicalEditor(request, pagename)
|
||||||
|
else: # 'text'
|
||||||
|
from MoinMoin.PageEditor import PageEditor
|
||||||
|
pg = PageEditor(request, pagename)
|
||||||
|
|
||||||
|
# is invoked without savetext start editing
|
||||||
|
if savetext is None or 'button_load_draft' in request.form:
|
||||||
|
pg.sendEditor()
|
||||||
|
return
|
||||||
|
|
||||||
|
# did user hit cancel button?
|
||||||
|
cancelled = 'button_cancel' in request.form
|
||||||
|
|
||||||
|
if request.cfg.edit_ticketing:
|
||||||
|
ticket = request.form.get('ticket', [''])[0]
|
||||||
|
if not wikiutil.checkTicket(request, ticket):
|
||||||
|
request.theme.add_msg(_('Please use the interactive user interface to use action %(actionname)s!') % {'actionname': 'edit' }, "error")
|
||||||
|
pg.send_page()
|
||||||
|
return
|
||||||
|
|
||||||
|
from MoinMoin.error import ConvertError
|
||||||
|
try:
|
||||||
|
if lasteditor == 'gui':
|
||||||
|
# convert input from Graphical editor
|
||||||
|
format = request.form.get('format', ['wiki'])[0]
|
||||||
|
if format == 'wiki':
|
||||||
|
converter_name = 'text_html_text_moin_wiki'
|
||||||
|
else:
|
||||||
|
converter_name = 'undefined' # XXX we don't have other converters yet
|
||||||
|
convert = wikiutil.importPlugin(request.cfg, "converter", converter_name, 'convert')
|
||||||
|
savetext = convert(request, pagename, savetext)
|
||||||
|
|
||||||
|
# IMPORTANT: normalize text from the form. This should be done in
|
||||||
|
# one place before we manipulate the text.
|
||||||
|
savetext = pg.normalizeText(savetext, stripspaces=rstrip)
|
||||||
|
except ConvertError:
|
||||||
|
# we don't want to throw an exception if user cancelled anyway
|
||||||
|
if not cancelled:
|
||||||
|
raise
|
||||||
|
|
||||||
|
if cancelled:
|
||||||
|
pg.sendCancel(savetext or "", rev)
|
||||||
|
pagedir = pg.getPagePath(check_create=0)
|
||||||
|
import os
|
||||||
|
if not os.listdir(pagedir):
|
||||||
|
os.removedirs(pagedir)
|
||||||
|
return
|
||||||
|
|
||||||
|
comment = wikiutil.clean_input(comment)
|
||||||
|
|
||||||
|
# Add category
|
||||||
|
|
||||||
|
# TODO: this code does not work with extended links, and is doing
|
||||||
|
# things behind your back, and in general not needed. Either we have
|
||||||
|
# a full interface for categories (add, delete) or just add them by
|
||||||
|
# markup.
|
||||||
|
|
||||||
|
if category and category != _('<No addition>'): # opera 8.5 needs this
|
||||||
|
# strip trailing whitespace
|
||||||
|
savetext = savetext.rstrip()
|
||||||
|
|
||||||
|
# Add category separator if last non-empty line contains
|
||||||
|
# non-categories.
|
||||||
|
lines = [line for line in savetext.splitlines() if line]
|
||||||
|
if lines:
|
||||||
|
|
||||||
|
#TODO: this code is broken, will not work for extended links
|
||||||
|
#categories, e.g ["category hebrew"]
|
||||||
|
categories = lines[-1].split()
|
||||||
|
|
||||||
|
if categories:
|
||||||
|
confirmed = wikiutil.filterCategoryPages(request, categories)
|
||||||
|
if len(confirmed) < len(categories):
|
||||||
|
# This was not a categories line, add separator
|
||||||
|
savetext += u'\n----\n'
|
||||||
|
|
||||||
|
# Add new category
|
||||||
|
if savetext and savetext[-1] != u'\n':
|
||||||
|
savetext += ' '
|
||||||
|
savetext += category + u'\n' # Should end with newline!
|
||||||
|
|
||||||
|
# Preview, spellcheck or spellcheck add new words
|
||||||
|
if ('button_preview' in request.form or
|
||||||
|
'button_spellcheck' in request.form or
|
||||||
|
'button_newwords' in request.form):
|
||||||
|
pg.sendEditor(preview=savetext, comment=comment)
|
||||||
|
|
||||||
|
# Preview with mode switch
|
||||||
|
elif 'button_switch' in request.form:
|
||||||
|
pg.sendEditor(preview=savetext, comment=comment, staytop=1)
|
||||||
|
|
||||||
|
# Save new text
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
from MoinMoin.security.textcha import TextCha
|
||||||
|
if not TextCha(request).check_answer_from_form():
|
||||||
|
raise pg.SaveError(_('TextCha: Wrong answer! Go back and try again...'))
|
||||||
|
savemsg = pg.saveText(savetext, rev, trivial=trivial, comment=comment)
|
||||||
|
except pg.EditConflict, e:
|
||||||
|
msg = e.message
|
||||||
|
|
||||||
|
# Handle conflict and send editor
|
||||||
|
pg.set_raw_body(savetext, modified=1)
|
||||||
|
|
||||||
|
pg.mergeEditConflict(rev)
|
||||||
|
# We don't send preview when we do merge conflict
|
||||||
|
pg.sendEditor(msg=msg, comment=comment)
|
||||||
|
return
|
||||||
|
|
||||||
|
except pg.SaveError, msg:
|
||||||
|
# msg contains a unicode string
|
||||||
|
savemsg = unicode(msg)
|
||||||
|
|
||||||
|
# Send new page after save or after unsuccessful conflict merge.
|
||||||
|
request.reset()
|
||||||
|
pg = Page(request, pagename)
|
||||||
|
|
||||||
|
# sets revision number to default for further actions
|
||||||
|
request.rev = 0
|
||||||
|
request.theme.add_msg(savemsg, "info")
|
||||||
|
pg.send_page()
|
195
wiki-lenny/share/action.newaccount.orig.py
Normal file
195
wiki-lenny/share/action.newaccount.orig.py
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
# -*- coding: iso-8859-1 -*-
|
||||||
|
"""
|
||||||
|
MoinMoin - create account action
|
||||||
|
|
||||||
|
@copyright: 2007 MoinMoin:JohannesBerg
|
||||||
|
@license: GNU GPL, see COPYING for details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from MoinMoin import user, wikiutil, util
|
||||||
|
from MoinMoin.Page import Page
|
||||||
|
from MoinMoin.widget import html
|
||||||
|
from MoinMoin.security.textcha import TextCha
|
||||||
|
from MoinMoin.auth import MoinAuth
|
||||||
|
|
||||||
|
|
||||||
|
_debug = False
|
||||||
|
|
||||||
|
def _create_user(request):
|
||||||
|
_ = request.getText
|
||||||
|
form = request.form
|
||||||
|
|
||||||
|
if request.request_method != 'POST':
|
||||||
|
return
|
||||||
|
|
||||||
|
if not TextCha(request).check_answer_from_form():
|
||||||
|
return _('TextCha: Wrong answer! Go back and try again...')
|
||||||
|
|
||||||
|
# Create user profile
|
||||||
|
theuser = user.User(request, auth_method="new-user")
|
||||||
|
|
||||||
|
# Require non-empty name
|
||||||
|
try:
|
||||||
|
theuser.name = form['name'][0]
|
||||||
|
except KeyError:
|
||||||
|
return _("Empty user name. Please enter a user name.")
|
||||||
|
|
||||||
|
# Don't allow creating users with invalid names
|
||||||
|
if not user.isValidName(request, theuser.name):
|
||||||
|
return _("""Invalid user name {{{'%s'}}}.
|
||||||
|
Name may contain any Unicode alpha numeric character, with optional one
|
||||||
|
space between words. Group page name is not allowed.""", wiki=True) % wikiutil.escape(theuser.name)
|
||||||
|
|
||||||
|
# Name required to be unique. Check if name belong to another user.
|
||||||
|
if user.getUserId(request, theuser.name):
|
||||||
|
return _("This user name already belongs to somebody else.")
|
||||||
|
|
||||||
|
# try to get the password and pw repeat
|
||||||
|
password = form.get('password1', [''])[0]
|
||||||
|
password2 = form.get('password2', [''])[0]
|
||||||
|
|
||||||
|
# Check if password is given and matches with password repeat
|
||||||
|
if password != password2:
|
||||||
|
return _("Passwords don't match!")
|
||||||
|
if not password:
|
||||||
|
return _("Please specify a password!")
|
||||||
|
|
||||||
|
pw_checker = request.cfg.password_checker
|
||||||
|
if pw_checker:
|
||||||
|
pw_error = pw_checker(theuser.name, password)
|
||||||
|
if pw_error:
|
||||||
|
return _("Password not acceptable: %s") % pw_error
|
||||||
|
|
||||||
|
# Encode password
|
||||||
|
if password and not password.startswith('{SHA}'):
|
||||||
|
try:
|
||||||
|
theuser.enc_password = user.encodePassword(password)
|
||||||
|
except UnicodeError, err:
|
||||||
|
# Should never happen
|
||||||
|
return "Can't encode password: %s" % str(err)
|
||||||
|
|
||||||
|
# try to get the email, for new users it is required
|
||||||
|
email = wikiutil.clean_input(form.get('email', [''])[0])
|
||||||
|
theuser.email = email.strip()
|
||||||
|
if not theuser.email and 'email' not in request.cfg.user_form_remove:
|
||||||
|
return _("Please provide your email address. If you lose your"
|
||||||
|
" login information, you can get it by email.")
|
||||||
|
|
||||||
|
# Email should be unique - see also MoinMoin/script/accounts/moin_usercheck.py
|
||||||
|
if theuser.email and request.cfg.user_email_unique:
|
||||||
|
if user.get_by_email_address(request, theuser.email):
|
||||||
|
return _("This email already belongs to somebody else.")
|
||||||
|
|
||||||
|
# save data
|
||||||
|
theuser.save()
|
||||||
|
|
||||||
|
if form.has_key('create_and_mail'):
|
||||||
|
theuser.mailAccountData()
|
||||||
|
|
||||||
|
result = _("User account created! You can use this account to login now...")
|
||||||
|
if _debug:
|
||||||
|
result = result + util.dumpFormData(form)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _create_form(request):
|
||||||
|
_ = request.getText
|
||||||
|
url = request.page.url(request)
|
||||||
|
ret = html.FORM(action=url)
|
||||||
|
ret.append(html.INPUT(type='hidden', name='action', value='newaccount'))
|
||||||
|
lang_attr = request.theme.ui_lang_attr()
|
||||||
|
ret.append(html.Raw('<div class="userpref"%s>' % lang_attr))
|
||||||
|
tbl = html.TABLE(border="0")
|
||||||
|
ret.append(tbl)
|
||||||
|
ret.append(html.Raw('</div>'))
|
||||||
|
|
||||||
|
row = html.TR()
|
||||||
|
tbl.append(row)
|
||||||
|
row.append(html.TD().append(html.STRONG().append(
|
||||||
|
html.Text(_("Name")))))
|
||||||
|
cell = html.TD()
|
||||||
|
row.append(cell)
|
||||||
|
cell.append(html.INPUT(type="text", size="36", name="name"))
|
||||||
|
cell.append(html.Text(' ' + _("(Use FirstnameLastname)")))
|
||||||
|
|
||||||
|
row = html.TR()
|
||||||
|
tbl.append(row)
|
||||||
|
row.append(html.TD().append(html.STRONG().append(
|
||||||
|
html.Text(_("Password")))))
|
||||||
|
row.append(html.TD().append(html.INPUT(type="password", size="36",
|
||||||
|
name="password1")))
|
||||||
|
|
||||||
|
row = html.TR()
|
||||||
|
tbl.append(row)
|
||||||
|
row.append(html.TD().append(html.STRONG().append(
|
||||||
|
html.Text(_("Password repeat")))))
|
||||||
|
row.append(html.TD().append(html.INPUT(type="password", size="36",
|
||||||
|
name="password2")))
|
||||||
|
|
||||||
|
row = html.TR()
|
||||||
|
tbl.append(row)
|
||||||
|
row.append(html.TD().append(html.STRONG().append(html.Text(_("Email")))))
|
||||||
|
row.append(html.TD().append(html.INPUT(type="text", size="36",
|
||||||
|
name="email")))
|
||||||
|
|
||||||
|
textcha = TextCha(request)
|
||||||
|
if textcha.is_enabled():
|
||||||
|
row = html.TR()
|
||||||
|
tbl.append(row)
|
||||||
|
row.append(html.TD().append(html.STRONG().append(
|
||||||
|
html.Text(_('TextCha (required)')))))
|
||||||
|
td = html.TD()
|
||||||
|
if textcha:
|
||||||
|
td.append(textcha.render())
|
||||||
|
row.append(td)
|
||||||
|
|
||||||
|
row = html.TR()
|
||||||
|
tbl.append(row)
|
||||||
|
row.append(html.TD())
|
||||||
|
td = html.TD()
|
||||||
|
row.append(td)
|
||||||
|
td.append(html.INPUT(type="submit", name="create_only",
|
||||||
|
value=_('Create Profile')))
|
||||||
|
if request.cfg.mail_enabled:
|
||||||
|
td.append(html.Text(' '))
|
||||||
|
td.append(html.INPUT(type="submit", name="create_and_mail",
|
||||||
|
value="%s + %s" % (_('Create Profile'),
|
||||||
|
_('Email'))))
|
||||||
|
|
||||||
|
return unicode(ret)
|
||||||
|
|
||||||
|
def execute(pagename, request):
|
||||||
|
found = False
|
||||||
|
for auth in request.cfg.auth:
|
||||||
|
if isinstance(auth, MoinAuth):
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not found:
|
||||||
|
# we will not have linked, so forbid access
|
||||||
|
request.makeForbidden403()
|
||||||
|
return
|
||||||
|
|
||||||
|
page = Page(request, pagename)
|
||||||
|
_ = request.getText
|
||||||
|
form = request.form
|
||||||
|
|
||||||
|
submitted = form.has_key('create_only') or form.has_key('create_and_mail')
|
||||||
|
|
||||||
|
if submitted: # user pressed create button
|
||||||
|
request.theme.add_msg(_create_user(request), "dialog")
|
||||||
|
return page.send_page()
|
||||||
|
else: # show create form
|
||||||
|
request.emit_http_headers()
|
||||||
|
request.theme.send_title(_("Create Account"), pagename=pagename)
|
||||||
|
|
||||||
|
request.write(request.formatter.startContent("content"))
|
||||||
|
|
||||||
|
# THIS IS A BIG HACK. IT NEEDS TO BE CLEANED UP
|
||||||
|
request.write(_create_form(request))
|
||||||
|
|
||||||
|
request.write(request.formatter.endContent())
|
||||||
|
|
||||||
|
request.theme.send_footer(pagename)
|
||||||
|
request.theme.send_closing_html()
|
||||||
|
|
207
wiki-lenny/share/action.newaccount.py
Normal file
207
wiki-lenny/share/action.newaccount.py
Normal file
|
@ -0,0 +1,207 @@
|
||||||
|
# -*- coding: iso-8859-1 -*-
|
||||||
|
"""
|
||||||
|
MoinMoin - create account action
|
||||||
|
|
||||||
|
@copyright: 2007 MoinMoin:JohannesBerg
|
||||||
|
@license: GNU GPL, see COPYING for details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from MoinMoin import user, wikiutil, util
|
||||||
|
from MoinMoin.Page import Page
|
||||||
|
from MoinMoin.widget import html
|
||||||
|
from MoinMoin.security.textcha import TextCha
|
||||||
|
from MoinMoin.auth import MoinAuth
|
||||||
|
|
||||||
|
|
||||||
|
_debug = False
|
||||||
|
|
||||||
|
def _create_user(request):
|
||||||
|
_ = request.getText
|
||||||
|
form = request.form
|
||||||
|
|
||||||
|
if request.request_method != 'POST':
|
||||||
|
return
|
||||||
|
|
||||||
|
if not TextCha(request).check_answer_from_form():
|
||||||
|
return _('TextCha: Wrong answer! Go back and try again...')
|
||||||
|
|
||||||
|
# Create user profile
|
||||||
|
theuser = user.User(request, auth_method="new-user")
|
||||||
|
|
||||||
|
# Require non-empty name
|
||||||
|
try:
|
||||||
|
theuser.name = form['name'][0]
|
||||||
|
except KeyError:
|
||||||
|
return _("Empty user name. Please enter a user name.")
|
||||||
|
|
||||||
|
# Don't allow creating users with invalid names
|
||||||
|
if not user.isValidName(request, theuser.name):
|
||||||
|
return _("""Invalid user name {{{'%s'}}}.
|
||||||
|
Name may contain any Unicode alpha numeric character, with optional one
|
||||||
|
space between words. Group page name is not allowed.""", wiki=True) % wikiutil.escape(theuser.name)
|
||||||
|
|
||||||
|
# Name required to be unique. Check if name belong to another user.
|
||||||
|
if user.getUserId(request, theuser.name):
|
||||||
|
return _("This user name already belongs to somebody else.")
|
||||||
|
|
||||||
|
# HACK SAUVAGE 1/1
|
||||||
|
# On interdit la création de compte aux gens qui ne sont pas en zone Cr@ns
|
||||||
|
import sys
|
||||||
|
sys.path.append('/usr/scripts/gestion/')
|
||||||
|
from iptools import is_crans
|
||||||
|
if not is_crans(self.request.remote_addr):
|
||||||
|
return _(u"""Création de compte impossible.
|
||||||
|
Pour des raisons de sécurité, la fonction de création d'un compte n'est
|
||||||
|
possible que depuis la zone CRANS. Si vous possédez un compte sur zamok,
|
||||||
|
vous pouvez y exécuter creer_compte_wiki.""")
|
||||||
|
# FIN HACK
|
||||||
|
|
||||||
|
# try to get the password and pw repeat
|
||||||
|
password = form.get('password1', [''])[0]
|
||||||
|
password2 = form.get('password2', [''])[0]
|
||||||
|
|
||||||
|
# Check if password is given and matches with password repeat
|
||||||
|
if password != password2:
|
||||||
|
return _("Passwords don't match!")
|
||||||
|
if not password:
|
||||||
|
return _("Please specify a password!")
|
||||||
|
|
||||||
|
pw_checker = request.cfg.password_checker
|
||||||
|
if pw_checker:
|
||||||
|
pw_error = pw_checker(theuser.name, password)
|
||||||
|
if pw_error:
|
||||||
|
return _("Password not acceptable: %s") % pw_error
|
||||||
|
|
||||||
|
# Encode password
|
||||||
|
if password and not password.startswith('{SHA}'):
|
||||||
|
try:
|
||||||
|
theuser.enc_password = user.encodePassword(password)
|
||||||
|
except UnicodeError, err:
|
||||||
|
# Should never happen
|
||||||
|
return "Can't encode password: %s" % str(err)
|
||||||
|
|
||||||
|
# try to get the email, for new users it is required
|
||||||
|
email = wikiutil.clean_input(form.get('email', [''])[0])
|
||||||
|
theuser.email = email.strip()
|
||||||
|
if not theuser.email and 'email' not in request.cfg.user_form_remove:
|
||||||
|
return _("Please provide your email address. If you lose your"
|
||||||
|
" login information, you can get it by email.")
|
||||||
|
|
||||||
|
# Email should be unique - see also MoinMoin/script/accounts/moin_usercheck.py
|
||||||
|
if theuser.email and request.cfg.user_email_unique:
|
||||||
|
if user.get_by_email_address(request, theuser.email):
|
||||||
|
return _("This email already belongs to somebody else.")
|
||||||
|
|
||||||
|
# save data
|
||||||
|
theuser.save()
|
||||||
|
|
||||||
|
if form.has_key('create_and_mail'):
|
||||||
|
theuser.mailAccountData()
|
||||||
|
|
||||||
|
result = _("User account created! You can use this account to login now...")
|
||||||
|
if _debug:
|
||||||
|
result = result + util.dumpFormData(form)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _create_form(request):
|
||||||
|
_ = request.getText
|
||||||
|
url = request.page.url(request)
|
||||||
|
ret = html.FORM(action=url)
|
||||||
|
ret.append(html.INPUT(type='hidden', name='action', value='newaccount'))
|
||||||
|
lang_attr = request.theme.ui_lang_attr()
|
||||||
|
ret.append(html.Raw('<div class="userpref"%s>' % lang_attr))
|
||||||
|
tbl = html.TABLE(border="0")
|
||||||
|
ret.append(tbl)
|
||||||
|
ret.append(html.Raw('</div>'))
|
||||||
|
|
||||||
|
row = html.TR()
|
||||||
|
tbl.append(row)
|
||||||
|
row.append(html.TD().append(html.STRONG().append(
|
||||||
|
html.Text(_("Name")))))
|
||||||
|
cell = html.TD()
|
||||||
|
row.append(cell)
|
||||||
|
cell.append(html.INPUT(type="text", size="36", name="name"))
|
||||||
|
cell.append(html.Text(' ' + _("(Use FirstnameLastname)")))
|
||||||
|
|
||||||
|
row = html.TR()
|
||||||
|
tbl.append(row)
|
||||||
|
row.append(html.TD().append(html.STRONG().append(
|
||||||
|
html.Text(_("Password")))))
|
||||||
|
row.append(html.TD().append(html.INPUT(type="password", size="36",
|
||||||
|
name="password1")))
|
||||||
|
|
||||||
|
row = html.TR()
|
||||||
|
tbl.append(row)
|
||||||
|
row.append(html.TD().append(html.STRONG().append(
|
||||||
|
html.Text(_("Password repeat")))))
|
||||||
|
row.append(html.TD().append(html.INPUT(type="password", size="36",
|
||||||
|
name="password2")))
|
||||||
|
|
||||||
|
row = html.TR()
|
||||||
|
tbl.append(row)
|
||||||
|
row.append(html.TD().append(html.STRONG().append(html.Text(_("Email")))))
|
||||||
|
row.append(html.TD().append(html.INPUT(type="text", size="36",
|
||||||
|
name="email")))
|
||||||
|
|
||||||
|
textcha = TextCha(request)
|
||||||
|
if textcha.is_enabled():
|
||||||
|
row = html.TR()
|
||||||
|
tbl.append(row)
|
||||||
|
row.append(html.TD().append(html.STRONG().append(
|
||||||
|
html.Text(_('TextCha (required)')))))
|
||||||
|
td = html.TD()
|
||||||
|
if textcha:
|
||||||
|
td.append(textcha.render())
|
||||||
|
row.append(td)
|
||||||
|
|
||||||
|
row = html.TR()
|
||||||
|
tbl.append(row)
|
||||||
|
row.append(html.TD())
|
||||||
|
td = html.TD()
|
||||||
|
row.append(td)
|
||||||
|
td.append(html.INPUT(type="submit", name="create_only",
|
||||||
|
value=_('Create Profile')))
|
||||||
|
if request.cfg.mail_enabled:
|
||||||
|
td.append(html.Text(' '))
|
||||||
|
td.append(html.INPUT(type="submit", name="create_and_mail",
|
||||||
|
value="%s + %s" % (_('Create Profile'),
|
||||||
|
_('Email'))))
|
||||||
|
|
||||||
|
return unicode(ret)
|
||||||
|
|
||||||
|
def execute(pagename, request):
|
||||||
|
found = False
|
||||||
|
for auth in request.cfg.auth:
|
||||||
|
if isinstance(auth, MoinAuth):
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not found:
|
||||||
|
# we will not have linked, so forbid access
|
||||||
|
request.makeForbidden403()
|
||||||
|
return
|
||||||
|
|
||||||
|
page = Page(request, pagename)
|
||||||
|
_ = request.getText
|
||||||
|
form = request.form
|
||||||
|
|
||||||
|
submitted = form.has_key('create_only') or form.has_key('create_and_mail')
|
||||||
|
|
||||||
|
if submitted: # user pressed create button
|
||||||
|
request.theme.add_msg(_create_user(request), "dialog")
|
||||||
|
return page.send_page()
|
||||||
|
else: # show create form
|
||||||
|
request.emit_http_headers()
|
||||||
|
request.theme.send_title(_("Create Account"), pagename=pagename)
|
||||||
|
|
||||||
|
request.write(request.formatter.startContent("content"))
|
||||||
|
|
||||||
|
# THIS IS A BIG HACK. IT NEEDS TO BE CLEANED UP
|
||||||
|
request.write(_create_form(request))
|
||||||
|
|
||||||
|
request.write(request.formatter.endContent())
|
||||||
|
|
||||||
|
request.theme.send_footer(pagename)
|
||||||
|
request.theme.send_closing_html()
|
||||||
|
|
435
wiki-lenny/share/formatter.__init__.py
Normal file
435
wiki-lenny/share/formatter.__init__.py
Normal file
|
@ -0,0 +1,435 @@
|
||||||
|
# -*- coding: iso-8859-1 -*-
|
||||||
|
"""
|
||||||
|
MoinMoin - Formatter Package and FormatterBase
|
||||||
|
|
||||||
|
See "base.py" for the formatter interface.
|
||||||
|
|
||||||
|
@copyright: 2000-2004 by Juergen Hermann <jh@web.de>
|
||||||
|
@license: GNU GPL, see COPYING for details.
|
||||||
|
"""
|
||||||
|
import re
|
||||||
|
|
||||||
|
from MoinMoin import log
|
||||||
|
logging = log.getLogger(__name__)
|
||||||
|
|
||||||
|
from MoinMoin.util import pysupport
|
||||||
|
from MoinMoin import wikiutil
|
||||||
|
from MoinMoin.support.python_compatibility import rsplit
|
||||||
|
|
||||||
|
modules = pysupport.getPackageModules(__file__)
|
||||||
|
|
||||||
|
|
||||||
|
class FormatterBase:
|
||||||
|
""" This defines the output interface used all over the rest of the code.
|
||||||
|
|
||||||
|
Note that no other means should be used to generate _content_ output,
|
||||||
|
while navigational elements (HTML page header/footer) and the like
|
||||||
|
can be printed directly without violating output abstraction.
|
||||||
|
"""
|
||||||
|
|
||||||
|
hardspace = ' '
|
||||||
|
|
||||||
|
def __init__(self, request, **kw):
|
||||||
|
self.request = request
|
||||||
|
self._ = request.getText
|
||||||
|
|
||||||
|
self._store_pagelinks = kw.get('store_pagelinks', 0)
|
||||||
|
self._terse = kw.get('terse', 0)
|
||||||
|
self.pagelinks = []
|
||||||
|
self.in_p = 0
|
||||||
|
self.in_pre = 0
|
||||||
|
self._highlight_re = None
|
||||||
|
self._base_depth = 0
|
||||||
|
|
||||||
|
def set_highlight_re(self, hi_re=None):
|
||||||
|
""" set the highlighting regular expression (e.g. for search terms)
|
||||||
|
|
||||||
|
@param hi_re: either a valid re as str/unicode (you may want to use
|
||||||
|
re.escape before passing generic strings!) or a compiled
|
||||||
|
re object. raises re.error for invalid re.
|
||||||
|
"""
|
||||||
|
if isinstance(hi_re, (str, unicode)):
|
||||||
|
hi_re = re.compile(hi_re, re.U + re.IGNORECASE)
|
||||||
|
self._highlight_re = hi_re
|
||||||
|
|
||||||
|
def lang(self, on, lang_name):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def setPage(self, page):
|
||||||
|
self.page = page
|
||||||
|
|
||||||
|
def sysmsg(self, on, **kw):
|
||||||
|
""" Emit a system message (embed it into the page).
|
||||||
|
|
||||||
|
Normally used to indicate disabled options, or invalid markup.
|
||||||
|
"""
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# Document Level #####################################################
|
||||||
|
|
||||||
|
def startDocument(self, pagename):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def endDocument(self):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def startContent(self, content_id="content", **kw):
|
||||||
|
if self.page:
|
||||||
|
self.request.begin_include(self.page.page_name)
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def endContent(self):
|
||||||
|
if self.page:
|
||||||
|
self.request.end_include()
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# Links ##############################################################
|
||||||
|
|
||||||
|
def pagelink(self, on, pagename='', page=None, **kw):
|
||||||
|
""" make a link to page <pagename>. Instead of supplying a pagename,
|
||||||
|
it is also possible to give a live Page object, then page.page_name
|
||||||
|
will be used.
|
||||||
|
"""
|
||||||
|
if not self._store_pagelinks or not on or kw.get('generated'):
|
||||||
|
return ''
|
||||||
|
if not pagename and page:
|
||||||
|
pagename = page.page_name
|
||||||
|
pagename = self.request.normalizePagename(pagename)
|
||||||
|
if pagename and pagename not in self.pagelinks:
|
||||||
|
self.pagelinks.append(pagename)
|
||||||
|
|
||||||
|
def interwikilink(self, on, interwiki='', pagename='', **kw):
|
||||||
|
""" calls pagelink() for internal interwikilinks
|
||||||
|
to make sure they get counted for self.pagelinks.
|
||||||
|
IMPORTANT: on and off must be called with same parameters, see
|
||||||
|
also the text_html formatter.
|
||||||
|
"""
|
||||||
|
wikitag, wikiurl, wikitail, wikitag_bad = wikiutil.resolve_interwiki(self.request, interwiki, pagename)
|
||||||
|
if wikitag == 'Self' or wikitag == self.request.cfg.interwikiname:
|
||||||
|
if '#' in wikitail:
|
||||||
|
wikitail, kw['anchor'] = rsplit(wikitail, '#', 1)
|
||||||
|
wikitail = wikiutil.url_unquote(wikitail)
|
||||||
|
return self.pagelink(on, wikitail, **kw)
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def url(self, on, url=None, css=None, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
# Attachments ######################################################
|
||||||
|
|
||||||
|
def attachment_link(self, on, url=None, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
def attachment_image(self, url, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
def attachment_drawing(self, url, text, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def attachment_inlined(self, url, text, **kw):
|
||||||
|
from MoinMoin.action import AttachFile
|
||||||
|
import os
|
||||||
|
_ = self.request.getText
|
||||||
|
pagename, filename = AttachFile.absoluteName(url, self.page.page_name)
|
||||||
|
fname = wikiutil.taintfilename(filename)
|
||||||
|
fpath = AttachFile.getFilename(self.request, pagename, fname)
|
||||||
|
ext = os.path.splitext(filename)[1]
|
||||||
|
Parser = wikiutil.getParserForExtension(self.request.cfg, ext)
|
||||||
|
if Parser is not None:
|
||||||
|
try:
|
||||||
|
content = file(fpath, 'r').read()
|
||||||
|
# Try to decode text. It might return junk, but we don't
|
||||||
|
# have enough information with attachments.
|
||||||
|
content = wikiutil.decodeUnknownInput(content)
|
||||||
|
colorizer = Parser(content, self.request, filename=filename)
|
||||||
|
colorizer.format(self)
|
||||||
|
except IOError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return (self.attachment_link(1, url) +
|
||||||
|
self.text(text) +
|
||||||
|
self.attachment_link(0))
|
||||||
|
|
||||||
|
def anchordef(self, name):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def line_anchordef(self, lineno):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def anchorlink(self, on, name='', **kw):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def line_anchorlink(self, on, lineno=0):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def image(self, src=None, **kw):
|
||||||
|
"""An inline image.
|
||||||
|
|
||||||
|
Extra keyword arguments are according to the HTML <img> tag attributes.
|
||||||
|
In particular an 'alt' or 'title' argument should give a description
|
||||||
|
of the image.
|
||||||
|
"""
|
||||||
|
title = src
|
||||||
|
for titleattr in ('title', 'html__title', 'alt', 'html__alt'):
|
||||||
|
if titleattr in kw:
|
||||||
|
title = kw[titleattr]
|
||||||
|
break
|
||||||
|
if title:
|
||||||
|
return '[Image:%s]' % title
|
||||||
|
return '[Image]'
|
||||||
|
|
||||||
|
# generic transclude/include:
|
||||||
|
def transclusion(self, on, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
def transclusion_param(self, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def smiley(self, text):
|
||||||
|
return text
|
||||||
|
|
||||||
|
def nowikiword(self, text):
|
||||||
|
return self.text(text)
|
||||||
|
|
||||||
|
# Text and Text Attributes ###########################################
|
||||||
|
|
||||||
|
def text(self, text, **kw):
|
||||||
|
if not self._highlight_re:
|
||||||
|
return self._text(text)
|
||||||
|
|
||||||
|
result = []
|
||||||
|
lastpos = 0
|
||||||
|
match = self._highlight_re.search(text)
|
||||||
|
while match and lastpos < len(text):
|
||||||
|
# add the match we found
|
||||||
|
result.append(self._text(text[lastpos:match.start()]))
|
||||||
|
result.append(self.highlight(1))
|
||||||
|
result.append(self._text(match.group(0)))
|
||||||
|
result.append(self.highlight(0))
|
||||||
|
|
||||||
|
# search for the next one
|
||||||
|
lastpos = match.end() + (match.end() == lastpos)
|
||||||
|
match = self._highlight_re.search(text, lastpos)
|
||||||
|
|
||||||
|
result.append(self._text(text[lastpos:]))
|
||||||
|
return ''.join(result)
|
||||||
|
|
||||||
|
def _text(self, text):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def strong(self, on, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def emphasis(self, on, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def underline(self, on, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def highlight(self, on, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def sup(self, on, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def sub(self, on, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def strike(self, on, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def code(self, on, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def preformatted(self, on, **kw):
|
||||||
|
self.in_pre = on != 0
|
||||||
|
|
||||||
|
def small(self, on, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def big(self, on, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
# special markup for syntax highlighting #############################
|
||||||
|
|
||||||
|
def code_area(self, on, code_id, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def code_line(self, on):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def code_token(self, tok_text, tok_type):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def crans_box(self, title, content, color=None):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
# Paragraphs, Lines, Rules ###########################################
|
||||||
|
|
||||||
|
def linebreak(self, preformatted=1):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def paragraph(self, on, **kw):
|
||||||
|
self.in_p = on != 0
|
||||||
|
|
||||||
|
def rule(self, size=0, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def icon(self, type):
|
||||||
|
return type
|
||||||
|
|
||||||
|
# Lists ##############################################################
|
||||||
|
|
||||||
|
def number_list(self, on, type=None, start=None, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def bullet_list(self, on, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def listitem(self, on, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def definition_list(self, on, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def definition_term(self, on, compact=0, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def definition_desc(self, on, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def heading(self, on, depth, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
# Tables #############################################################
|
||||||
|
|
||||||
|
def table(self, on, attrs={}, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def table_row(self, on, attrs={}, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def table_cell(self, on, attrs={}, **kw):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
# Dynamic stuff / Plugins ############################################
|
||||||
|
|
||||||
|
def macro(self, macro_obj, name, args, markup=None):
|
||||||
|
# call the macro
|
||||||
|
try:
|
||||||
|
return macro_obj.execute(name, args)
|
||||||
|
except ImportError, err:
|
||||||
|
errmsg = unicode(err)
|
||||||
|
if not name in errmsg:
|
||||||
|
raise
|
||||||
|
if markup:
|
||||||
|
return (self.span(1, title=errmsg) +
|
||||||
|
self.text(markup) +
|
||||||
|
self.span(0))
|
||||||
|
else:
|
||||||
|
return self.text(errmsg)
|
||||||
|
def _get_bang_args(self, line):
|
||||||
|
if line.startswith('#!'):
|
||||||
|
try:
|
||||||
|
name, args = line[2:].split(None, 1)
|
||||||
|
except ValueError:
|
||||||
|
return ''
|
||||||
|
else:
|
||||||
|
return args
|
||||||
|
return None
|
||||||
|
|
||||||
|
def parser(self, parser_name, lines):
|
||||||
|
""" parser_name MUST be valid!
|
||||||
|
writes out the result instead of returning it!
|
||||||
|
"""
|
||||||
|
# attention: this is copied into text_python!
|
||||||
|
parser = wikiutil.searchAndImportPlugin(self.request.cfg, "parser", parser_name)
|
||||||
|
args = None
|
||||||
|
if lines:
|
||||||
|
args = self._get_bang_args(lines[0])
|
||||||
|
logging.debug("formatter.parser: parser args %r" % args)
|
||||||
|
if args is not None:
|
||||||
|
lines = lines[1:]
|
||||||
|
if lines and not lines[0]:
|
||||||
|
lines = lines[1:]
|
||||||
|
if lines and not lines[-1].strip():
|
||||||
|
lines = lines[:-1]
|
||||||
|
p = parser('\n'.join(lines), self.request, format_args=args)
|
||||||
|
p.format(self)
|
||||||
|
del p
|
||||||
|
return ''
|
||||||
|
|
||||||
|
# Other ##############################################################
|
||||||
|
|
||||||
|
def div(self, on, **kw):
|
||||||
|
""" open/close a blocklevel division """
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def span(self, on, **kw):
|
||||||
|
""" open/close a inline span """
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def rawHTML(self, markup):
|
||||||
|
""" This allows emitting pre-formatted HTML markup, and should be
|
||||||
|
used wisely (i.e. very seldom).
|
||||||
|
|
||||||
|
Using this event while generating content results in unwanted
|
||||||
|
effects, like loss of markup or insertion of CDATA sections
|
||||||
|
when output goes to XML formats.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import formatter, htmllib
|
||||||
|
from MoinMoin.util import simpleIO
|
||||||
|
|
||||||
|
# Regenerate plain text
|
||||||
|
f = simpleIO()
|
||||||
|
h = htmllib.HTMLParser(formatter.AbstractFormatter(formatter.DumbWriter(f)))
|
||||||
|
h.feed(markup)
|
||||||
|
h.close()
|
||||||
|
|
||||||
|
return self.text(f.getvalue())
|
||||||
|
|
||||||
|
def escapedText(self, on, **kw):
|
||||||
|
""" This allows emitting text as-is, anything special will
|
||||||
|
be escaped (at least in HTML, some text output format
|
||||||
|
would possibly do nothing here)
|
||||||
|
"""
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def comment(self, text, **kw):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# ID handling #################################################
|
||||||
|
|
||||||
|
def sanitize_to_id(self, text):
|
||||||
|
'''
|
||||||
|
Take 'text' and return something that is a valid ID
|
||||||
|
for this formatter.
|
||||||
|
The default returns the first non-space character of the string.
|
||||||
|
|
||||||
|
Because of the way this is used, it must be idempotent,
|
||||||
|
i.e. calling it on an already sanitized id must yield the
|
||||||
|
original id.
|
||||||
|
'''
|
||||||
|
return text.strip()[:1]
|
||||||
|
|
||||||
|
def make_id_unique(self, id):
|
||||||
|
'''
|
||||||
|
Take an ID and make it unique in the current namespace.
|
||||||
|
'''
|
||||||
|
ns = self.request.include_id
|
||||||
|
if not ns is None:
|
||||||
|
ns = self.sanitize_to_id(ns)
|
||||||
|
id = self.sanitize_to_id(id)
|
||||||
|
id = self.request.make_unique_id(id, ns)
|
||||||
|
return id
|
||||||
|
|
||||||
|
def qualify_id(self, id):
|
||||||
|
'''
|
||||||
|
Take an ID and return a string that is qualified by
|
||||||
|
the current namespace; this default implementation
|
||||||
|
is suitable if the dot ('.') is valid in IDs for your
|
||||||
|
formatter.
|
||||||
|
'''
|
||||||
|
ns = self.request.include_id
|
||||||
|
if not ns is None:
|
||||||
|
ns = self.sanitize_to_id(ns)
|
||||||
|
return '%s.%s' % (ns, id)
|
||||||
|
return id
|
1405
wiki-lenny/share/formatter.text_html.py
Normal file
1405
wiki-lenny/share/formatter.text_html.py
Normal file
File diff suppressed because it is too large
Load diff
454
wiki-lenny/share/security.__init__.orig.py
Normal file
454
wiki-lenny/share/security.__init__.orig.py
Normal file
|
@ -0,0 +1,454 @@
|
||||||
|
# -*- coding: iso-8859-1 -*-
|
||||||
|
"""
|
||||||
|
MoinMoin - Wiki Security Interface and Access Control Lists
|
||||||
|
|
||||||
|
|
||||||
|
This implements the basic interface for user permissions and
|
||||||
|
system policy. If you want to define your own policy, inherit
|
||||||
|
from the base class 'Permissions', so that when new permissions
|
||||||
|
are defined, you get the defaults.
|
||||||
|
|
||||||
|
Then assign your new class to "SecurityPolicy" in wikiconfig;
|
||||||
|
and I mean the class, not an instance of it!
|
||||||
|
|
||||||
|
@copyright: 2000-2004 Juergen Hermann <jh@web.de>,
|
||||||
|
2003-2008 MoinMoin:ThomasWaldmann,
|
||||||
|
2003 Gustavo Niemeyer,
|
||||||
|
2005 Oliver Graf,
|
||||||
|
2007 Alexander Schremmer
|
||||||
|
@license: GNU GPL, see COPYING for details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from MoinMoin import wikiutil, user
|
||||||
|
from MoinMoin.Page import Page
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
### Basic Permissions Interface -- most features enabled by default
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
def _check(request, pagename, username, right):
|
||||||
|
""" Check <right> access permission for user <username> on page <pagename>
|
||||||
|
|
||||||
|
For cfg.acl_hierarchic=False we just check the page in question.
|
||||||
|
|
||||||
|
For cfg.acl_hierarchic=True we, we check each page in the hierarchy. We
|
||||||
|
start with the deepest page and recurse to the top of the tree.
|
||||||
|
If one of those permits, True is returned.
|
||||||
|
|
||||||
|
For both configurations, we check acl_rights_before before the page/default
|
||||||
|
acl and acl_rights_after after the page/default acl, of course.
|
||||||
|
|
||||||
|
This method should not be called by users, use __getattr__ instead.
|
||||||
|
|
||||||
|
@param request: the current request object
|
||||||
|
@param pagename: pagename to get permissions from
|
||||||
|
@param username: the user name
|
||||||
|
@param right: the right to check
|
||||||
|
|
||||||
|
@rtype: bool
|
||||||
|
@return: True if you have permission or False
|
||||||
|
"""
|
||||||
|
cache = request.cfg.cache
|
||||||
|
allowed = cache.acl_rights_before.may(request, username, right)
|
||||||
|
if allowed is not None:
|
||||||
|
return allowed
|
||||||
|
|
||||||
|
if request.cfg.acl_hierarchic:
|
||||||
|
pages = pagename.split('/') # create page hierarchy list
|
||||||
|
some_acl = False
|
||||||
|
for i in range(len(pages), 0, -1):
|
||||||
|
# Create the next pagename in the hierarchy
|
||||||
|
# starting at the leaf, going to the root
|
||||||
|
name = '/'.join(pages[:i])
|
||||||
|
# Get page acl and ask for permission
|
||||||
|
acl = Page(request, name).getACL(request)
|
||||||
|
if acl.acl:
|
||||||
|
some_acl = True
|
||||||
|
allowed = acl.may(request, username, right)
|
||||||
|
if allowed is not None:
|
||||||
|
return allowed
|
||||||
|
if not some_acl:
|
||||||
|
allowed = cache.acl_rights_default.may(request, username, right)
|
||||||
|
if allowed is not None:
|
||||||
|
return allowed
|
||||||
|
else:
|
||||||
|
if request.page is not None and pagename == request.page.page_name:
|
||||||
|
p = request.page # reuse is good
|
||||||
|
else:
|
||||||
|
p = Page(request, pagename)
|
||||||
|
acl = p.getACL(request) # this will be fast in a reused page obj
|
||||||
|
allowed = acl.may(request, username, right)
|
||||||
|
if allowed is not None:
|
||||||
|
return allowed
|
||||||
|
|
||||||
|
allowed = cache.acl_rights_after.may(request, username, right)
|
||||||
|
if allowed is not None:
|
||||||
|
return allowed
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class Permissions:
|
||||||
|
""" Basic interface for user permissions and system policy.
|
||||||
|
|
||||||
|
Note that you still need to allow some of the related actions, this
|
||||||
|
just controls their behavior, not their activation.
|
||||||
|
|
||||||
|
When sub classing this class, you must extend the class methods, not
|
||||||
|
replace them, or you might break the acl in the wiki. Correct sub
|
||||||
|
classing looks like this:
|
||||||
|
|
||||||
|
def read(self, pagename):
|
||||||
|
# Your special security rule
|
||||||
|
if something:
|
||||||
|
return false
|
||||||
|
|
||||||
|
# Do not return True or you break acl!
|
||||||
|
# This call will use the default acl rules
|
||||||
|
return Permissions.read(pagename)
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, user):
|
||||||
|
self.name = user.name
|
||||||
|
self.request = user._request
|
||||||
|
|
||||||
|
def save(self, editor, newtext, rev, **kw):
|
||||||
|
""" Check whether user may save a page.
|
||||||
|
|
||||||
|
`editor` is the PageEditor instance, the other arguments are
|
||||||
|
those of the `PageEditor.saveText` method.
|
||||||
|
|
||||||
|
@param editor: PageEditor instance.
|
||||||
|
@param newtext: new page text, you can enable of disable saving according
|
||||||
|
to the content of the text, e.g. prevent link spam.
|
||||||
|
@param rev: new revision number? XXX
|
||||||
|
@param kw: XXX
|
||||||
|
@rtype: bool
|
||||||
|
@return: True if you can save or False
|
||||||
|
"""
|
||||||
|
return self.write(editor.page_name)
|
||||||
|
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
""" Shortcut to export getPermission function for all known ACL rights
|
||||||
|
|
||||||
|
if attr is one of the rights in acl_rights_valid, then return a
|
||||||
|
checking function for it. Else raise an AttributeError.
|
||||||
|
|
||||||
|
@param attr: one of ACL rights as defined in acl_rights_valid
|
||||||
|
@rtype: function
|
||||||
|
@return: checking function for that right, accepting a pagename
|
||||||
|
"""
|
||||||
|
request = self.request
|
||||||
|
if attr not in request.cfg.acl_rights_valid:
|
||||||
|
raise AttributeError, attr
|
||||||
|
return lambda pagename: _check(self.request, pagename, self.name, attr)
|
||||||
|
|
||||||
|
|
||||||
|
# make an alias for the default policy
|
||||||
|
Default = Permissions
|
||||||
|
|
||||||
|
|
||||||
|
class AccessControlList:
|
||||||
|
''' Access Control List
|
||||||
|
|
||||||
|
Control who may do what on or with a wiki page.
|
||||||
|
|
||||||
|
Syntax of an ACL string:
|
||||||
|
|
||||||
|
[+|-]User[,User,...]:[right[,right,...]] [[+|-]SomeGroup:...] ...
|
||||||
|
... [[+|-]Known:...] [[+|-]All:...]
|
||||||
|
|
||||||
|
"User" is a user name and triggers only if the user matches. Up
|
||||||
|
to version 1.2 only WikiNames were supported, as of version 1.3,
|
||||||
|
any name can be used in acl lines, including name with spaces
|
||||||
|
using esoteric languages.
|
||||||
|
|
||||||
|
"SomeGroup" is a page name matching cfg.page_group_regex with
|
||||||
|
some lines in the form " * Member", defining the group members.
|
||||||
|
|
||||||
|
"Known" is a group containing all valid / known users.
|
||||||
|
|
||||||
|
"All" is a group containing all users (Known and Anonymous users).
|
||||||
|
|
||||||
|
"right" may be an arbitrary word like read, write, delete, admin.
|
||||||
|
Only words in cfg.acl_validrights are accepted, others are
|
||||||
|
ignored. It is allowed to specify no rights, which means that no
|
||||||
|
rights are given.
|
||||||
|
|
||||||
|
How ACL is processed
|
||||||
|
|
||||||
|
When some user is trying to access some ACL-protected resource,
|
||||||
|
the ACLs will be processed in the order they are found. The first
|
||||||
|
matching ACL will tell if the user has access to that resource
|
||||||
|
or not.
|
||||||
|
|
||||||
|
For example, the following ACL tells that SomeUser is able to
|
||||||
|
read and write the resources protected by that ACL, while any
|
||||||
|
member of SomeGroup (besides SomeUser, if part of that group)
|
||||||
|
may also admin that, and every other user is able to read it.
|
||||||
|
|
||||||
|
SomeUser:read,write SomeGroup:read,write,admin All:read
|
||||||
|
|
||||||
|
In this example, SomeUser can read and write but can not admin,
|
||||||
|
revert or delete pages. Rights that are NOT specified on the
|
||||||
|
right list are automatically set to NO.
|
||||||
|
|
||||||
|
Using Prefixes
|
||||||
|
|
||||||
|
To make the system more flexible, there are also two modifiers:
|
||||||
|
the prefixes "+" and "-".
|
||||||
|
|
||||||
|
+SomeUser:read -OtherUser:write
|
||||||
|
|
||||||
|
The acl line above will grant SomeUser read right, and OtherUser
|
||||||
|
write right, but will NOT block automatically all other rights
|
||||||
|
for these users. For example, if SomeUser ask to write, the
|
||||||
|
above acl line does not define if he can or can not write. He
|
||||||
|
will be able to write if acl_rights_before or acl_rights_after
|
||||||
|
allow this (see configuration options).
|
||||||
|
|
||||||
|
Using prefixes, this acl line:
|
||||||
|
|
||||||
|
SomeUser:read,write SomeGroup:read,write,admin All:read
|
||||||
|
|
||||||
|
Can be written as:
|
||||||
|
|
||||||
|
-SomeUser:admin SomeGroup:read,write,admin All:read
|
||||||
|
|
||||||
|
Or even:
|
||||||
|
|
||||||
|
+All:read -SomeUser:admin SomeGroup:read,write,admin
|
||||||
|
|
||||||
|
Notice that you probably will not want to use the second and
|
||||||
|
third examples in ACL entries of some page. They are very
|
||||||
|
useful on the moin configuration entries though.
|
||||||
|
|
||||||
|
Configuration options
|
||||||
|
|
||||||
|
cfg.acl_rights_default
|
||||||
|
It is is ONLY used when no other ACLs are given.
|
||||||
|
Default: "Known:read,write,delete All:read,write",
|
||||||
|
|
||||||
|
cfg.acl_rights_before
|
||||||
|
When the page has ACL entries, this will be inserted BEFORE
|
||||||
|
any page entries.
|
||||||
|
Default: ""
|
||||||
|
|
||||||
|
cfg.acl_rights_after
|
||||||
|
When the page has ACL entries, this will be inserted AFTER
|
||||||
|
any page entries.
|
||||||
|
Default: ""
|
||||||
|
|
||||||
|
cfg.acl_rights_valid
|
||||||
|
These are the acceptable (known) rights (and the place to
|
||||||
|
extend, if necessary).
|
||||||
|
Default: ["read", "write", "delete", "admin"]
|
||||||
|
'''
|
||||||
|
|
||||||
|
special_users = ["All", "Known", "Trusted"] # order is important
|
||||||
|
|
||||||
|
def __init__(self, cfg, lines=[]):
|
||||||
|
"""Initialize an ACL, starting from <nothing>.
|
||||||
|
"""
|
||||||
|
if lines:
|
||||||
|
self.acl = [] # [ ('User', {"read": 0, ...}), ... ]
|
||||||
|
self.acl_lines = []
|
||||||
|
for line in lines:
|
||||||
|
self._addLine(cfg, line)
|
||||||
|
else:
|
||||||
|
self.acl = None
|
||||||
|
self.acl_lines = None
|
||||||
|
|
||||||
|
def _addLine(self, cfg, aclstring, remember=1):
|
||||||
|
""" Add another ACL line
|
||||||
|
|
||||||
|
This can be used in multiple subsequent calls to process longer lists.
|
||||||
|
|
||||||
|
@param cfg: current config
|
||||||
|
@param aclstring: acl string from page or cfg
|
||||||
|
@param remember: should add the line to self.acl_lines
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Remember lines
|
||||||
|
if remember:
|
||||||
|
self.acl_lines.append(aclstring)
|
||||||
|
|
||||||
|
# Iterate over entries and rights, parsed by acl string iterator
|
||||||
|
acliter = ACLStringIterator(cfg.acl_rights_valid, aclstring)
|
||||||
|
for modifier, entries, rights in acliter:
|
||||||
|
if entries == ['Default']:
|
||||||
|
self._addLine(cfg, cfg.acl_rights_default, remember=0)
|
||||||
|
else:
|
||||||
|
for entry in entries:
|
||||||
|
rightsdict = {}
|
||||||
|
if modifier:
|
||||||
|
# Only user rights are added to the right dict.
|
||||||
|
# + add rights with value of 1
|
||||||
|
# - add right with value of 0
|
||||||
|
for right in rights:
|
||||||
|
rightsdict[right] = (modifier == '+')
|
||||||
|
else:
|
||||||
|
# All rights from acl_rights_valid are added to the
|
||||||
|
# dict, user rights with value of 1, and other with
|
||||||
|
# value of 0
|
||||||
|
for right in cfg.acl_rights_valid:
|
||||||
|
rightsdict[right] = (right in rights)
|
||||||
|
self.acl.append((entry, rightsdict))
|
||||||
|
|
||||||
|
def may(self, request, name, dowhat):
|
||||||
|
""" May <name> <dowhat>? Returns boolean answer.
|
||||||
|
|
||||||
|
Note: this check does NOT include the acl_rights_before / _after ACL,
|
||||||
|
but it WILL use acl_rights_default if there is no (page) ACL.
|
||||||
|
"""
|
||||||
|
if self.acl is None: # no #acl used on Page
|
||||||
|
acl = request.cfg.cache.acl_rights_default.acl
|
||||||
|
else: # we have a #acl on the page (self.acl can be [] if #acl is empty!)
|
||||||
|
acl = self.acl
|
||||||
|
is_group_member = request.dicts.has_member
|
||||||
|
group_re = request.cfg.cache.page_group_regexact
|
||||||
|
allowed = None
|
||||||
|
for entry, rightsdict in acl:
|
||||||
|
if entry in self.special_users:
|
||||||
|
handler = getattr(self, "_special_"+entry, None)
|
||||||
|
allowed = handler(request, name, dowhat, rightsdict)
|
||||||
|
elif group_re.search(entry):
|
||||||
|
if is_group_member(entry, name):
|
||||||
|
allowed = rightsdict.get(dowhat)
|
||||||
|
else:
|
||||||
|
for special in self.special_users:
|
||||||
|
if is_group_member(entry, special):
|
||||||
|
handler = getattr(self, "_special_" + special, None)
|
||||||
|
allowed = handler(request, name, dowhat, rightsdict)
|
||||||
|
break # order of self.special_users is important
|
||||||
|
elif entry == name:
|
||||||
|
allowed = rightsdict.get(dowhat)
|
||||||
|
if allowed is not None:
|
||||||
|
return allowed
|
||||||
|
return allowed # should be None
|
||||||
|
|
||||||
|
def getString(self, b='#acl ', e='\n'):
|
||||||
|
"""print the acl strings we were fed with"""
|
||||||
|
if self.acl_lines:
|
||||||
|
acl_lines = ''.join(["%s%s%s" % (b, l, e) for l in self.acl_lines])
|
||||||
|
else:
|
||||||
|
acl_lines = ''
|
||||||
|
return acl_lines
|
||||||
|
|
||||||
|
def _special_All(self, request, name, dowhat, rightsdict):
|
||||||
|
return rightsdict.get(dowhat)
|
||||||
|
|
||||||
|
def _special_Known(self, request, name, dowhat, rightsdict):
|
||||||
|
""" check if user <name> is known to us,
|
||||||
|
that means that there is a valid user account present.
|
||||||
|
works for subscription emails.
|
||||||
|
"""
|
||||||
|
if user.getUserId(request, name): # is a user with this name known?
|
||||||
|
return rightsdict.get(dowhat)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _special_Trusted(self, request, name, dowhat, rightsdict):
|
||||||
|
""" check if user <name> is known AND has logged in using a trusted
|
||||||
|
authentication method.
|
||||||
|
Does not work for subsription emails that should be sent to <user>,
|
||||||
|
as he is not logged in in that case.
|
||||||
|
"""
|
||||||
|
if (request.user.name == name and
|
||||||
|
request.user.auth_method in request.cfg.auth_methods_trusted):
|
||||||
|
return rightsdict.get(dowhat)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.acl_lines == other.acl_lines
|
||||||
|
|
||||||
|
def __ne__(self, other):
|
||||||
|
return self.acl_lines != other.acl_lines
|
||||||
|
|
||||||
|
|
||||||
|
class ACLStringIterator:
|
||||||
|
""" Iterator for acl string
|
||||||
|
|
||||||
|
Parse acl string and return the next entry on each call to
|
||||||
|
next. Implement the Iterator protocol.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
iter = ACLStringIterator(cfg.acl_rights_valid, 'user name:right')
|
||||||
|
for modifier, entries, rights in iter:
|
||||||
|
# process data
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, rights, aclstring):
|
||||||
|
""" Initialize acl iterator
|
||||||
|
|
||||||
|
@param rights: the acl rights to consider when parsing
|
||||||
|
@param aclstring: string to parse
|
||||||
|
"""
|
||||||
|
self.rights = rights
|
||||||
|
self.rest = aclstring.strip()
|
||||||
|
self.finished = 0
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
""" Required by the Iterator protocol """
|
||||||
|
return self
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
""" Return the next values from the acl string
|
||||||
|
|
||||||
|
When the iterator is finished and you try to call next, it
|
||||||
|
raises a StopIteration. The iterator finish as soon as the
|
||||||
|
string is fully parsed or can not be parsed any more.
|
||||||
|
|
||||||
|
@rtype: 3 tuple - (modifier, [entry, ...], [right, ...])
|
||||||
|
@return: values for one item in an acl string
|
||||||
|
"""
|
||||||
|
# Handle finished state, required by iterator protocol
|
||||||
|
if self.rest == '':
|
||||||
|
self.finished = 1
|
||||||
|
if self.finished:
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
# Get optional modifier [+|-]entries:rights
|
||||||
|
modifier = ''
|
||||||
|
if self.rest[0] in ('+', '-'):
|
||||||
|
modifier, self.rest = self.rest[0], self.rest[1:]
|
||||||
|
|
||||||
|
# Handle the Default meta acl
|
||||||
|
if self.rest.startswith('Default ') or self.rest == 'Default':
|
||||||
|
self.rest = self.rest[8:]
|
||||||
|
entries, rights = ['Default'], []
|
||||||
|
|
||||||
|
# Handle entries:rights pairs
|
||||||
|
else:
|
||||||
|
# Get entries
|
||||||
|
try:
|
||||||
|
entries, self.rest = self.rest.split(':', 1)
|
||||||
|
except ValueError:
|
||||||
|
self.finished = 1
|
||||||
|
raise StopIteration("Can't parse rest of string")
|
||||||
|
if entries == '':
|
||||||
|
entries = []
|
||||||
|
else:
|
||||||
|
# TODO strip each entry from blanks?
|
||||||
|
entries = entries.split(',')
|
||||||
|
|
||||||
|
# Get rights
|
||||||
|
try:
|
||||||
|
rights, self.rest = self.rest.split(' ', 1)
|
||||||
|
# Remove extra white space after rights fragment,
|
||||||
|
# allowing using multiple spaces between items.
|
||||||
|
self.rest = self.rest.lstrip()
|
||||||
|
except ValueError:
|
||||||
|
rights, self.rest = self.rest, ''
|
||||||
|
rights = [r for r in rights.split(',') if r in self.rights]
|
||||||
|
|
||||||
|
return modifier, entries, rights
|
||||||
|
|
||||||
|
|
||||||
|
def parseACL(request, text):
|
||||||
|
""" Parse acl lines from text and return ACL object """
|
||||||
|
pi, dummy = wikiutil.get_processing_instructions(text)
|
||||||
|
acl_lines = [args for verb, args in pi if verb == 'acl']
|
||||||
|
return AccessControlList(request.cfg, acl_lines)
|
||||||
|
|
501
wiki-lenny/share/security.__init__.py
Normal file
501
wiki-lenny/share/security.__init__.py
Normal file
|
@ -0,0 +1,501 @@
|
||||||
|
# -*- coding: iso-8859-1 -*-
|
||||||
|
"""
|
||||||
|
MoinMoin - Wiki Security Interface and Access Control Lists
|
||||||
|
|
||||||
|
|
||||||
|
This implements the basic interface for user permissions and
|
||||||
|
system policy. If you want to define your own policy, inherit
|
||||||
|
from the base class 'Permissions', so that when new permissions
|
||||||
|
are defined, you get the defaults.
|
||||||
|
|
||||||
|
Then assign your new class to "SecurityPolicy" in wikiconfig;
|
||||||
|
and I mean the class, not an instance of it!
|
||||||
|
|
||||||
|
@copyright: 2000-2004 Juergen Hermann <jh@web.de>,
|
||||||
|
2003-2008 MoinMoin:ThomasWaldmann,
|
||||||
|
2003 Gustavo Niemeyer,
|
||||||
|
2005 Oliver Graf,
|
||||||
|
2007 Alexander Schremmer
|
||||||
|
@license: GNU GPL, see COPYING for details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from MoinMoin import wikiutil, user
|
||||||
|
from MoinMoin.Page import Page
|
||||||
|
|
||||||
|
#### HACK SAUVAGE 1/5
|
||||||
|
import sys
|
||||||
|
sys.path.append('/usr/scripts/gestion/')
|
||||||
|
from iptools import is_crans
|
||||||
|
#### FIN DU HACK 1/5
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
### Basic Permissions Interface -- most features enabled by default
|
||||||
|
#############################################################################
|
||||||
|
|
||||||
|
def _check(request, pagename, username, right):
|
||||||
|
""" Check <right> access permission for user <username> on page <pagename>
|
||||||
|
|
||||||
|
For cfg.acl_hierarchic=False we just check the page in question.
|
||||||
|
|
||||||
|
For cfg.acl_hierarchic=True we, we check each page in the hierarchy. We
|
||||||
|
start with the deepest page and recurse to the top of the tree.
|
||||||
|
If one of those permits, True is returned.
|
||||||
|
|
||||||
|
For both configurations, we check acl_rights_before before the page/default
|
||||||
|
acl and acl_rights_after after the page/default acl, of course.
|
||||||
|
|
||||||
|
This method should not be called by users, use __getattr__ instead.
|
||||||
|
|
||||||
|
@param request: the current request object
|
||||||
|
@param pagename: pagename to get permissions from
|
||||||
|
@param username: the user name
|
||||||
|
@param right: the right to check
|
||||||
|
|
||||||
|
@rtype: bool
|
||||||
|
@return: True if you have permission or False
|
||||||
|
"""
|
||||||
|
cache = request.cfg.cache
|
||||||
|
allowed = cache.acl_rights_before.may(request, username, right)
|
||||||
|
if allowed is not None:
|
||||||
|
return allowed
|
||||||
|
|
||||||
|
if request.cfg.acl_hierarchic:
|
||||||
|
pages = pagename.split('/') # create page hierarchy list
|
||||||
|
some_acl = False
|
||||||
|
for i in range(len(pages), 0, -1):
|
||||||
|
# Create the next pagename in the hierarchy
|
||||||
|
# starting at the leaf, going to the root
|
||||||
|
name = '/'.join(pages[:i])
|
||||||
|
# Get page acl and ask for permission
|
||||||
|
acl = Page(request, name).getACL(request)
|
||||||
|
if acl.acl:
|
||||||
|
some_acl = True
|
||||||
|
allowed = acl.may(request, username, right)
|
||||||
|
if allowed is not None:
|
||||||
|
return allowed
|
||||||
|
if not some_acl:
|
||||||
|
allowed = cache.acl_rights_default.may(request, username, right)
|
||||||
|
if allowed is not None:
|
||||||
|
return allowed
|
||||||
|
else:
|
||||||
|
if request.page is not None and pagename == request.page.page_name:
|
||||||
|
p = request.page # reuse is good
|
||||||
|
else:
|
||||||
|
p = Page(request, pagename)
|
||||||
|
acl = p.getACL(request) # this will be fast in a reused page obj
|
||||||
|
allowed = acl.may(request, username, right)
|
||||||
|
if allowed is not None:
|
||||||
|
return allowed
|
||||||
|
|
||||||
|
allowed = cache.acl_rights_after.may(request, username, right)
|
||||||
|
if allowed is not None:
|
||||||
|
return allowed
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class Permissions:
|
||||||
|
""" Basic interface for user permissions and system policy.
|
||||||
|
|
||||||
|
Note that you still need to allow some of the related actions, this
|
||||||
|
just controls their behavior, not their activation.
|
||||||
|
|
||||||
|
When sub classing this class, you must extend the class methods, not
|
||||||
|
replace them, or you might break the acl in the wiki. Correct sub
|
||||||
|
classing looks like this:
|
||||||
|
|
||||||
|
def read(self, pagename):
|
||||||
|
# Your special security rule
|
||||||
|
if something:
|
||||||
|
return false
|
||||||
|
|
||||||
|
# Do not return True or you break acl!
|
||||||
|
# This call will use the default acl rules
|
||||||
|
return Permissions.read(pagename)
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, user):
|
||||||
|
self.name = user.name
|
||||||
|
self.request = user._request
|
||||||
|
|
||||||
|
def save(self, editor, newtext, rev, **kw):
|
||||||
|
""" Check whether user may save a page.
|
||||||
|
|
||||||
|
`editor` is the PageEditor instance, the other arguments are
|
||||||
|
those of the `PageEditor.saveText` method.
|
||||||
|
|
||||||
|
@param editor: PageEditor instance.
|
||||||
|
@param newtext: new page text, you can enable of disable saving according
|
||||||
|
to the content of the text, e.g. prevent link spam.
|
||||||
|
@param rev: new revision number? XXX
|
||||||
|
@param kw: XXX
|
||||||
|
@rtype: bool
|
||||||
|
@return: True if you can save or False
|
||||||
|
"""
|
||||||
|
return self.write(editor.page_name)
|
||||||
|
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
""" Shortcut to export getPermission function for all known ACL rights
|
||||||
|
|
||||||
|
if attr is one of the rights in acl_rights_valid, then return a
|
||||||
|
checking function for it. Else raise an AttributeError.
|
||||||
|
|
||||||
|
@param attr: one of ACL rights as defined in acl_rights_valid
|
||||||
|
@rtype: function
|
||||||
|
@return: checking function for that right, accepting a pagename
|
||||||
|
"""
|
||||||
|
request = self.request
|
||||||
|
if attr not in request.cfg.acl_rights_valid:
|
||||||
|
raise AttributeError, attr
|
||||||
|
return lambda pagename: _check(self.request, pagename, self.name, attr)
|
||||||
|
|
||||||
|
|
||||||
|
# make an alias for the default policy
|
||||||
|
Default = Permissions
|
||||||
|
|
||||||
|
|
||||||
|
class AccessControlList:
|
||||||
|
''' Access Control List
|
||||||
|
|
||||||
|
Control who may do what on or with a wiki page.
|
||||||
|
|
||||||
|
Syntax of an ACL string:
|
||||||
|
|
||||||
|
[+|-]User[,User,...]:[right[,right,...]] [[+|-]SomeGroup:...] ...
|
||||||
|
... [[+|-]Known:...] [[+|-]All:...]
|
||||||
|
|
||||||
|
"User" is a user name and triggers only if the user matches. Up
|
||||||
|
to version 1.2 only WikiNames were supported, as of version 1.3,
|
||||||
|
any name can be used in acl lines, including name with spaces
|
||||||
|
using esoteric languages.
|
||||||
|
|
||||||
|
"SomeGroup" is a page name matching cfg.page_group_regex with
|
||||||
|
some lines in the form " * Member", defining the group members.
|
||||||
|
|
||||||
|
"Known" is a group containing all valid / known users.
|
||||||
|
|
||||||
|
"All" is a group containing all users (Known and Anonymous users).
|
||||||
|
|
||||||
|
"right" may be an arbitrary word like read, write, delete, admin.
|
||||||
|
Only words in cfg.acl_validrights are accepted, others are
|
||||||
|
ignored. It is allowed to specify no rights, which means that no
|
||||||
|
rights are given.
|
||||||
|
|
||||||
|
How ACL is processed
|
||||||
|
|
||||||
|
When some user is trying to access some ACL-protected resource,
|
||||||
|
the ACLs will be processed in the order they are found. The first
|
||||||
|
matching ACL will tell if the user has access to that resource
|
||||||
|
or not.
|
||||||
|
|
||||||
|
For example, the following ACL tells that SomeUser is able to
|
||||||
|
read and write the resources protected by that ACL, while any
|
||||||
|
member of SomeGroup (besides SomeUser, if part of that group)
|
||||||
|
may also admin that, and every other user is able to read it.
|
||||||
|
|
||||||
|
SomeUser:read,write SomeGroup:read,write,admin All:read
|
||||||
|
|
||||||
|
In this example, SomeUser can read and write but can not admin,
|
||||||
|
revert or delete pages. Rights that are NOT specified on the
|
||||||
|
right list are automatically set to NO.
|
||||||
|
|
||||||
|
Using Prefixes
|
||||||
|
|
||||||
|
To make the system more flexible, there are also two modifiers:
|
||||||
|
the prefixes "+" and "-".
|
||||||
|
|
||||||
|
+SomeUser:read -OtherUser:write
|
||||||
|
|
||||||
|
The acl line above will grant SomeUser read right, and OtherUser
|
||||||
|
write right, but will NOT block automatically all other rights
|
||||||
|
for these users. For example, if SomeUser ask to write, the
|
||||||
|
above acl line does not define if he can or can not write. He
|
||||||
|
will be able to write if acl_rights_before or acl_rights_after
|
||||||
|
allow this (see configuration options).
|
||||||
|
|
||||||
|
Using prefixes, this acl line:
|
||||||
|
|
||||||
|
SomeUser:read,write SomeGroup:read,write,admin All:read
|
||||||
|
|
||||||
|
Can be written as:
|
||||||
|
|
||||||
|
-SomeUser:admin SomeGroup:read,write,admin All:read
|
||||||
|
|
||||||
|
Or even:
|
||||||
|
|
||||||
|
+All:read -SomeUser:admin SomeGroup:read,write,admin
|
||||||
|
|
||||||
|
Notice that you probably will not want to use the second and
|
||||||
|
third examples in ACL entries of some page. They are very
|
||||||
|
useful on the moin configuration entries though.
|
||||||
|
|
||||||
|
Configuration options
|
||||||
|
|
||||||
|
cfg.acl_rights_default
|
||||||
|
It is is ONLY used when no other ACLs are given.
|
||||||
|
Default: "Known:read,write,delete All:read,write",
|
||||||
|
|
||||||
|
cfg.acl_rights_before
|
||||||
|
When the page has ACL entries, this will be inserted BEFORE
|
||||||
|
any page entries.
|
||||||
|
Default: ""
|
||||||
|
|
||||||
|
cfg.acl_rights_after
|
||||||
|
When the page has ACL entries, this will be inserted AFTER
|
||||||
|
any page entries.
|
||||||
|
Default: ""
|
||||||
|
|
||||||
|
cfg.acl_rights_valid
|
||||||
|
These are the acceptable (known) rights (and the place to
|
||||||
|
extend, if necessary).
|
||||||
|
Default: ["read", "write", "delete", "admin"]
|
||||||
|
'''
|
||||||
|
|
||||||
|
#special_users = ["All", "Known", "Trusted"] # order is important
|
||||||
|
## HACK SAUVAGE 2/5
|
||||||
|
special_users = ["All", "Known", "Trusted", "Crans", "NoCrans"] # order is important
|
||||||
|
## FIN HACK 2/5
|
||||||
|
|
||||||
|
def __init__(self, cfg, lines=[]):
|
||||||
|
"""Initialize an ACL, starting from <nothing>.
|
||||||
|
"""
|
||||||
|
if lines:
|
||||||
|
self.acl = [] # [ ('User', {"read": 0, ...}), ... ]
|
||||||
|
self.acl_lines = []
|
||||||
|
for line in lines:
|
||||||
|
self._addLine(cfg, line)
|
||||||
|
else:
|
||||||
|
self.acl = None
|
||||||
|
self.acl_lines = None
|
||||||
|
|
||||||
|
def _addLine(self, cfg, aclstring, remember=1):
|
||||||
|
""" Add another ACL line
|
||||||
|
|
||||||
|
This can be used in multiple subsequent calls to process longer lists.
|
||||||
|
|
||||||
|
@param cfg: current config
|
||||||
|
@param aclstring: acl string from page or cfg
|
||||||
|
@param remember: should add the line to self.acl_lines
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Remember lines
|
||||||
|
if remember:
|
||||||
|
self.acl_lines.append(aclstring)
|
||||||
|
|
||||||
|
# Iterate over entries and rights, parsed by acl string iterator
|
||||||
|
acliter = ACLStringIterator(cfg.acl_rights_valid, aclstring)
|
||||||
|
for modifier, entries, rights in acliter:
|
||||||
|
if entries == ['Default']:
|
||||||
|
self._addLine(cfg, cfg.acl_rights_default, remember=0)
|
||||||
|
else:
|
||||||
|
for entry in entries:
|
||||||
|
rightsdict = {}
|
||||||
|
if modifier:
|
||||||
|
# Only user rights are added to the right dict.
|
||||||
|
# + add rights with value of 1
|
||||||
|
# - add right with value of 0
|
||||||
|
for right in rights:
|
||||||
|
rightsdict[right] = (modifier == '+')
|
||||||
|
else:
|
||||||
|
# All rights from acl_rights_valid are added to the
|
||||||
|
# dict, user rights with value of 1, and other with
|
||||||
|
# value of 0
|
||||||
|
for right in cfg.acl_rights_valid:
|
||||||
|
rightsdict[right] = (right in rights)
|
||||||
|
self.acl.append((entry, rightsdict))
|
||||||
|
|
||||||
|
def may(self, request, name, dowhat):
|
||||||
|
""" May <name> <dowhat>? Returns boolean answer.
|
||||||
|
|
||||||
|
Note: this check does NOT include the acl_rights_before / _after ACL,
|
||||||
|
but it WILL use acl_rights_default if there is no (page) ACL.
|
||||||
|
"""
|
||||||
|
if self.acl is None: # no #acl used on Page
|
||||||
|
acl = request.cfg.cache.acl_rights_default.acl
|
||||||
|
else: # we have a #acl on the page (self.acl can be [] if #acl is empty!)
|
||||||
|
acl = self.acl
|
||||||
|
is_group_member = request.dicts.has_member
|
||||||
|
group_re = request.cfg.cache.page_group_regexact
|
||||||
|
allowed = None
|
||||||
|
for entry, rightsdict in acl:
|
||||||
|
if entry in self.special_users:
|
||||||
|
handler = getattr(self, "_special_"+entry, None)
|
||||||
|
allowed = handler(request, name, dowhat, rightsdict)
|
||||||
|
elif group_re.search(entry):
|
||||||
|
if is_group_member(entry, name):
|
||||||
|
allowed = rightsdict.get(dowhat)
|
||||||
|
else:
|
||||||
|
for special in self.special_users:
|
||||||
|
if is_group_member(entry, special):
|
||||||
|
handler = getattr(self, "_special_" + special, None)
|
||||||
|
allowed = handler(request, name, dowhat, rightsdict)
|
||||||
|
break # order of self.special_users is important
|
||||||
|
elif entry == name:
|
||||||
|
allowed = rightsdict.get(dowhat)
|
||||||
|
if allowed is not None:
|
||||||
|
return allowed
|
||||||
|
return allowed # should be None
|
||||||
|
|
||||||
|
def getString(self, b='#acl ', e='\n'):
|
||||||
|
"""print the acl strings we were fed with"""
|
||||||
|
if self.acl_lines:
|
||||||
|
acl_lines = ''.join(["%s%s%s" % (b, l, e) for l in self.acl_lines])
|
||||||
|
else:
|
||||||
|
acl_lines = ''
|
||||||
|
return acl_lines
|
||||||
|
|
||||||
|
def _special_All(self, request, name, dowhat, rightsdict):
|
||||||
|
## HACK SAUVAGE 3/5
|
||||||
|
if dowhat == "read" and is_page_public(request):
|
||||||
|
return True
|
||||||
|
## FIN HACK 3/5
|
||||||
|
return rightsdict.get(dowhat)
|
||||||
|
|
||||||
|
def _special_Known(self, request, name, dowhat, rightsdict):
|
||||||
|
""" check if user <name> is known to us,
|
||||||
|
that means that there is a valid user account present.
|
||||||
|
works for subscription emails.
|
||||||
|
"""
|
||||||
|
if user.getUserId(request, name): # is a user with this name known?
|
||||||
|
return rightsdict.get(dowhat)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _special_Trusted(self, request, name, dowhat, rightsdict):
|
||||||
|
""" check if user <name> is known AND has logged in using a trusted
|
||||||
|
authentication method.
|
||||||
|
Does not work for subsription emails that should be sent to <user>,
|
||||||
|
as he is not logged in in that case.
|
||||||
|
"""
|
||||||
|
if (request.user.name == name and
|
||||||
|
request.user.auth_method in request.cfg.auth_methods_trusted):
|
||||||
|
return rightsdict.get(dowhat)
|
||||||
|
return None
|
||||||
|
|
||||||
|
#### HACK SAUVAGE 4/5
|
||||||
|
def _requete_interne(self, request):
|
||||||
|
try:
|
||||||
|
if is_crans(request.remote_addr) and (request.remote_addr != u'138.231.136.3' or is_crans(request.mpyreq.headers_in['X-Forwarded-For'].split(",")[-1].strip())):
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _special_Crans(self, request, name, dowhat, rightsdict):
|
||||||
|
if self._requete_interne(request):
|
||||||
|
return rightsdict.get(dowhat)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _special_NoCrans(self, request, name, dowhat, rightsdict):
|
||||||
|
if dowhat == "read" and is_page_public(request):
|
||||||
|
return True
|
||||||
|
if not self._requete_interne(request):
|
||||||
|
return rightsdict.get(dowhat)
|
||||||
|
return None
|
||||||
|
#### FIN Du HACK 4/5
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
return self.acl_lines == other.acl_lines
|
||||||
|
|
||||||
|
def __ne__(self, other):
|
||||||
|
return self.acl_lines != other.acl_lines
|
||||||
|
|
||||||
|
|
||||||
|
class ACLStringIterator:
|
||||||
|
""" Iterator for acl string
|
||||||
|
|
||||||
|
Parse acl string and return the next entry on each call to
|
||||||
|
next. Implement the Iterator protocol.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
iter = ACLStringIterator(cfg.acl_rights_valid, 'user name:right')
|
||||||
|
for modifier, entries, rights in iter:
|
||||||
|
# process data
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, rights, aclstring):
|
||||||
|
""" Initialize acl iterator
|
||||||
|
|
||||||
|
@param rights: the acl rights to consider when parsing
|
||||||
|
@param aclstring: string to parse
|
||||||
|
"""
|
||||||
|
self.rights = rights
|
||||||
|
self.rest = aclstring.strip()
|
||||||
|
self.finished = 0
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
""" Required by the Iterator protocol """
|
||||||
|
return self
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
""" Return the next values from the acl string
|
||||||
|
|
||||||
|
When the iterator is finished and you try to call next, it
|
||||||
|
raises a StopIteration. The iterator finish as soon as the
|
||||||
|
string is fully parsed or can not be parsed any more.
|
||||||
|
|
||||||
|
@rtype: 3 tuple - (modifier, [entry, ...], [right, ...])
|
||||||
|
@return: values for one item in an acl string
|
||||||
|
"""
|
||||||
|
# Handle finished state, required by iterator protocol
|
||||||
|
if self.rest == '':
|
||||||
|
self.finished = 1
|
||||||
|
if self.finished:
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
# Get optional modifier [+|-]entries:rights
|
||||||
|
modifier = ''
|
||||||
|
if self.rest[0] in ('+', '-'):
|
||||||
|
modifier, self.rest = self.rest[0], self.rest[1:]
|
||||||
|
|
||||||
|
# Handle the Default meta acl
|
||||||
|
if self.rest.startswith('Default ') or self.rest == 'Default':
|
||||||
|
self.rest = self.rest[8:]
|
||||||
|
entries, rights = ['Default'], []
|
||||||
|
|
||||||
|
# Handle entries:rights pairs
|
||||||
|
else:
|
||||||
|
# Get entries
|
||||||
|
try:
|
||||||
|
entries, self.rest = self.rest.split(':', 1)
|
||||||
|
except ValueError:
|
||||||
|
self.finished = 1
|
||||||
|
raise StopIteration("Can't parse rest of string")
|
||||||
|
if entries == '':
|
||||||
|
entries = []
|
||||||
|
else:
|
||||||
|
# TODO strip each entry from blanks?
|
||||||
|
entries = entries.split(',')
|
||||||
|
|
||||||
|
# Get rights
|
||||||
|
try:
|
||||||
|
rights, self.rest = self.rest.split(' ', 1)
|
||||||
|
# Remove extra white space after rights fragment,
|
||||||
|
# allowing using multiple spaces between items.
|
||||||
|
self.rest = self.rest.lstrip()
|
||||||
|
except ValueError:
|
||||||
|
rights, self.rest = self.rest, ''
|
||||||
|
rights = [r for r in rights.split(',') if r in self.rights]
|
||||||
|
|
||||||
|
return modifier, entries, rights
|
||||||
|
|
||||||
|
|
||||||
|
def parseACL(request, text):
|
||||||
|
""" Parse acl lines from text and return ACL object """
|
||||||
|
pi, dummy = wikiutil.get_processing_instructions(text)
|
||||||
|
acl_lines = [args for verb, args in pi if verb == 'acl']
|
||||||
|
return AccessControlList(request.cfg, acl_lines)
|
||||||
|
|
||||||
|
#### HACK SAUVAGE 5/5
|
||||||
|
def is_page_public(request):
|
||||||
|
#return True
|
||||||
|
## On recherche si la page est publique
|
||||||
|
this_page = request.page.page_name
|
||||||
|
categories = request.page.getCategories(request)
|
||||||
|
if u'CatégoriePagePublique' in categories:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
#### FIn DU HACK 5/5
|
Loading…
Add table
Add a link
Reference in a new issue