diff --git a/wiki-lenny/share/PageGraphicalEditor.orig.py b/wiki-lenny/share/PageGraphicalEditor.orig.py new file mode 100644 index 00000000..04005739 --- /dev/null +++ b/wiki-lenny/share/PageGraphicalEditor.orig.py @@ -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"\(\?" + 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]"), '
') + 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, ), '
') + else: + request.write(_("[Template %s not found]") % (template_page, ), '
') + else: + request.write(_("[You may not read %s]") % (template_page, ), '
') + + # 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"'''<
>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('
' % ( + 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('
') + + request.write(unicode(html.INPUT(type="hidden", name="action", value="edit"))) + + # Send revision of the page our edit is based on + request.write('' % (rev, )) + + # Add src format (e.g. 'wiki') into a hidden form field, so that + # we can load the correct converter after POSTing. + request.write('' % self.pi['format']) + + # Create and send a ticket, so we can check the POST + request.write('' % 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 = '' % _('Check Spelling') + + save_button_text = _('Save Changes') + cancel_button_text = _('Cancel') + + if self.cfg.page_license_enabled: + request.write('

', _( +"""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), + }, '

') + + request.write(''' + + + +''' % (save_button_text, _('Preview'), _('Text mode'), )) + + if loadable_draft: + request.write(''' + + + +''' % (_('Load Draft'), draft_timestamp, draft_rev)) + + request.write(''' +%s + + +''' % (button_spellcheck, cancel_button_text, )) + if self.cfg.mail_enabled: + request.write(''' + +  + + +''' % { + '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(""" + + +""") + request.write("

") + request.write(_("Comment:"), + ' ' % ( + wikiutil.escape(kw.get('comment', ''), 1), )) + request.write("

") + + # 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, ('', _(''))) + request.write("

") + request.write(_('Add to: %(category)s') % { + 'category': unicode(web.makeSelection('category', cat_pages)), + }) + if self.cfg.mail_enabled: + request.write(''' +  + + ''' % { + 'checked': ('', 'checked')[form.get('trivial', ['0'])[0] == '1'], + 'label': _("Trivial change"), + }) + + request.write(''' +  + + +

''' % { + 'checked': ('', 'checked')[form.get('rstrip', ['0'])[0] == '1'], + 'label': _('Remove trailing whitespace from each line') + }) + + request.write("

") + + 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("

%s

" % msg) + request.write('
') + request.write("
") + + 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() + diff --git a/wiki-lenny/share/PageGraphicalEditor.py b/wiki-lenny/share/PageGraphicalEditor.py new file mode 100644 index 00000000..2256edff --- /dev/null +++ b/wiki-lenny/share/PageGraphicalEditor.py @@ -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"\(\?" + 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]"), '
') + 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, ), '
') + else: + request.write(_("[Template %s not found]") % (template_page, ), '
') + else: + request.write(_("[You may not read %s]") % (template_page, ), '
') + + # 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"'''<
>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('
' % ( + 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('
') + + request.write(unicode(html.INPUT(type="hidden", name="action", value="edit"))) + + # Send revision of the page our edit is based on + request.write('' % (rev, )) + + # Add src format (e.g. 'wiki') into a hidden form field, so that + # we can load the correct converter after POSTing. + request.write('' % self.pi['format']) + + # Create and send a ticket, so we can check the POST + request.write('' % 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 = '' % _('Check Spelling') + + save_button_text = _('Save Changes') + cancel_button_text = _('Cancel') + + if self.cfg.page_license_enabled: + request.write('

', _( +"""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), + }, '

') + + request.write(''' + + + +''' % (save_button_text, _('Preview'), _('Text mode'), )) + + if loadable_draft: + request.write(''' + + + +''' % (_('Load Draft'), draft_timestamp, draft_rev)) + + request.write(''' +%s + + +''' % (button_spellcheck, cancel_button_text, )) + if self.cfg.mail_enabled: + request.write(''' + +  + + +''' % { + '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(""" + + +""") + request.write("

") + request.write(_("Comment:"), + ' ' % ( + wikiutil.escape(kw.get('comment', ''), 1), )) + request.write("

") + + # 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, ('', _(''))) + request.write("

") + request.write(_('Add to: %(category)s') % { + 'category': unicode(web.makeSelection('category', cat_pages)), + }) + if self.cfg.mail_enabled: + request.write(''' +  + + ''' % { + 'checked': ('', 'checked')[form.get('trivial', ['0'])[0] == '1'], + 'label': _("Trivial change"), + }) + + request.write(''' +  + + +

''' % { + 'checked': ('', 'checked')[form.get('rstrip', ['0'])[0] == '1'], + 'label': _('Remove trailing whitespace from each line') + }) + + request.write("

") + + 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("

%s

" % msg) + request.write('
') + request.write("
") + + 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() + diff --git a/wiki-lenny/share/action.edit.orig.py b/wiki-lenny/share/action.edit.orig.py new file mode 100644 index 00000000..c07f183c --- /dev/null +++ b/wiki-lenny/share/action.edit.orig.py @@ -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 , + 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 != _(''): # 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() diff --git a/wiki-lenny/share/action.edit.py b/wiki-lenny/share/action.edit.py new file mode 100644 index 00000000..c07f183c --- /dev/null +++ b/wiki-lenny/share/action.edit.py @@ -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 , + 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 != _(''): # 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() diff --git a/wiki-lenny/share/action.newaccount.orig.py b/wiki-lenny/share/action.newaccount.orig.py new file mode 100644 index 00000000..43641049 --- /dev/null +++ b/wiki-lenny/share/action.newaccount.orig.py @@ -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('
' % lang_attr)) + tbl = html.TABLE(border="0") + ret.append(tbl) + ret.append(html.Raw('
')) + + 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() + diff --git a/wiki-lenny/share/action.newaccount.py b/wiki-lenny/share/action.newaccount.py new file mode 100644 index 00000000..43de207c --- /dev/null +++ b/wiki-lenny/share/action.newaccount.py @@ -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('
' % lang_attr)) + tbl = html.TABLE(border="0") + ret.append(tbl) + ret.append(html.Raw('
')) + + 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() + diff --git a/wiki-lenny/share/formatter.__init__.py b/wiki-lenny/share/formatter.__init__.py new file mode 100644 index 00000000..e8f85a14 --- /dev/null +++ b/wiki-lenny/share/formatter.__init__.py @@ -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 + @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 . 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 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 diff --git a/wiki-lenny/share/formatter.text_html.py b/wiki-lenny/share/formatter.text_html.py new file mode 100644 index 00000000..9968588a --- /dev/null +++ b/wiki-lenny/share/formatter.text_html.py @@ -0,0 +1,1405 @@ +# -*- coding: iso-8859-1 -*- +""" + MoinMoin - "text/html+css" Formatter + + @copyright: 2000-2004 by Juergen Hermann + @license: GNU GPL, see COPYING for details. +""" +import os.path, re + +from MoinMoin import log +logging = log.getLogger(__name__) + +from MoinMoin.formatter import FormatterBase +from MoinMoin import wikiutil, i18n +from MoinMoin.Page import Page +from MoinMoin.action import AttachFile +from MoinMoin.support.python_compatibility import set, rsplit + +# insert IDs into output wherever they occur +# warning: breaks toggle line numbers javascript +_id_debug = False + +line_anchors = True +prettyprint = False + +# These are the HTML elements that we treat as block elements. +_blocks = set(['dd', 'div', 'dl', 'dt', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', + 'hr', 'li', 'ol', 'p', 'pre', 'table', 'tbody', 'td', 'tfoot', 'th', + 'thead', 'tr', 'ul', 'blockquote', ]) + +# These are the HTML elements which are typically only used with +# an opening tag without a separate closing tag. We do not +# include 'script' or 'style' because sometimes they do have +# content, and also IE has a parsing bug with those two elements (only) +# when they don't have a closing tag even if valid XHTML. + +_self_closing_tags = set(['area', 'base', 'br', 'col', 'frame', 'hr', 'img', + 'input', 'isindex', 'link', 'meta', 'param']) + +# We only open those tags and let the browser auto-close them: +_auto_closing_tags = set(['p']) + +# These are the elements which generally should cause an increase in the +# indention level in the html souce code. +_indenting_tags = set(['ol', 'ul', 'dl', 'li', 'dt', 'dd', 'tr', 'td']) + +# These are the elements that discard any whitespace they contain as +# immediate child nodes. +_space_eating_tags = set(['colgroup', 'dl', 'frameset', 'head', 'map' 'menu', + 'ol', 'optgroup', 'select', 'table', 'tbody', 'tfoot', + 'thead', 'tr', 'ul']) + +# These are standard HTML attributes which are typically used without any +# value; e.g., as boolean flags indicated by their presence. +_html_attribute_boolflags = set(['compact', 'disabled', 'ismap', 'nohref', + 'noresize', 'noshade', 'nowrap', 'readonly', + 'selected', 'wrap']) + +# These are all the standard HTML attributes that are allowed on any element. +_common_attributes = set(['accesskey', 'class', 'dir', 'disabled', 'id', 'lang', + 'style', 'tabindex', 'title']) + + +def rewrite_attribute_name(name, default_namespace='html'): + """ + Takes an attribute name and tries to make it HTML correct. + + This function takes an attribute name as a string, as it may be + passed in to a formatting method using a keyword-argument syntax, + and tries to convert it into a real attribute name. This is + necessary because some attributes may conflict with Python + reserved words or variable syntax (such as 'for', 'class', or + 'z-index'); and also to help with backwards compatibility with + older versions of MoinMoin where different names may have been + used (such as 'content_id' or 'css'). + + Returns a tuple of strings: (namespace, attribute). + + Namespaces: The default namespace is always assumed to be 'html', + unless the input string contains a colon or a double-underscore; + in which case the first such occurance is assumed to separate the + namespace prefix from name. So, for example, to get the HTML + attribute 'for' (as on a