MoinMoin/action/Despam.py
author Thomas Waldmann <tw AT waldmann-edv DOT de>
Wed, 11 Feb 2009 02:34:33 +0100
changeset 4569 3caaa8c74c41
parent 4552 7d8c6d279cff
child 4570 e86a7b66eb0e
permissions -rw-r--r--
wikiutil: replace moin's cgi/urllib wrappers by calls to werkzeug.utils code
     1 # -*- coding: iso-8859-1 -*-
     2 """
     3     MoinMoin - Despam action
     4 
     5     Mass revert changes done by some specific author / bot.
     6 
     7     @copyright: 2005 by ???, Thomas Waldmann
     8     @license: GNU GPL, see COPYING for details.
     9 """
    10 
    11 DAYS = 30 # we look for spam edits in the last x days
    12 
    13 import time
    14 
    15 from MoinMoin.logfile import editlog
    16 from MoinMoin.util.dataset import TupleDataset, Column
    17 from MoinMoin.widget.browser import DataBrowserWidget
    18 from MoinMoin import wikiutil, Page, PageEditor
    19 from MoinMoin.macro import RecentChanges
    20 
    21 def render(editor_tuple):
    22     etype, evalue = editor_tuple
    23     if etype in ('ip', 'email', ):
    24         ret = evalue
    25     elif etype == 'interwiki':
    26         ewiki, euser = evalue
    27         if ewiki == 'Self':
    28             ret = euser
    29         else:
    30             ret = '%s:%s' % evalue
    31     else:
    32         ret = repr(editor_tuple)
    33     return ret
    34 
    35 def show_editors(request, pagename, timestamp):
    36     _ = request.getText
    37 
    38     timestamp = int(timestamp * 1000000)
    39     log = editlog.EditLog(request)
    40     editors = {}
    41     pages = {}
    42     for line in log.reverse():
    43         if line.ed_time_usecs < timestamp:
    44             break
    45 
    46         if not request.user.may.read(line.pagename):
    47             continue
    48 
    49         editor = line.getInterwikiEditorData(request)
    50         if not line.pagename in pages:
    51             pages[line.pagename] = 1
    52             editors[editor] = editors.get(editor, 0) + 1
    53 
    54     editors = [(nr, editor) for editor, nr in editors.iteritems()]
    55     editors.sort()
    56     editors.reverse()
    57 
    58     pg = Page.Page(request, pagename)
    59 
    60     dataset = TupleDataset()
    61     dataset.columns = [Column('editor', label=_("Editor"), align='left'),
    62                        Column('pages', label=_("Pages"), align='right'),
    63                        Column('link', label='', align='left')]
    64     for nr, editor in editors:
    65         dataset.addRow((render(editor), unicode(nr),
    66             pg.link_to(request, text=_("Select Author"),
    67                 querystr={
    68                     'action': 'Despam',
    69                     'editor': repr(editor),
    70                 })))
    71 
    72     table = DataBrowserWidget(request)
    73     table.setData(dataset)
    74     return table.render(method="GET")
    75 
    76 class tmp:
    77     pass
    78 
    79 def show_pages(request, pagename, editor, timestamp):
    80     _ = request.getText
    81 
    82     timestamp = int(timestamp * 1000000)
    83     log = editlog.EditLog(request)
    84     pages = {}
    85     #  mimic macro object for use of RecentChanges subfunctions
    86     macro = tmp()
    87     macro.request = request
    88     macro.formatter = request.html_formatter
    89 
    90     request.write("<table>")
    91     for line in log.reverse():
    92         if line.ed_time_usecs < timestamp:
    93             break
    94 
    95         if not request.user.may.read(line.pagename):
    96             continue
    97 
    98         if not line.pagename in pages:
    99             pages[line.pagename] = 1
   100             if repr(line.getInterwikiEditorData(request)) == editor:
   101                 line.time_tuple = request.user.getTime(wikiutil.version2timestamp(line.ed_time_usecs))
   102                 request.write(RecentChanges.format_page_edits(macro, [line], timestamp))
   103 
   104     request.write('''
   105 </table>
   106 <p>
   107 <form method="post" action="%s">
   108 <input type="hidden" name="action" value="Despam">
   109 <input type="hidden" name="editor" value="%s">
   110 <input type="submit" name="ok" value="%s">
   111 </form>
   112 </p>
   113 ''' % (request.href(pagename), wikiutil.url_quote(editor), _("Revert all!")))
   114 
   115 def revert_page(request, pagename, editor):
   116     if not request.user.may.revert(pagename):
   117         return
   118 
   119     log = editlog.EditLog(request, rootpagename=pagename)
   120 
   121     first = True
   122     rev = u"00000000"
   123     for line in log.reverse():
   124         if first:
   125             first = False
   126             if repr(line.getInterwikiEditorData(request)) != editor:
   127                 return
   128         else:
   129             if repr(line.getInterwikiEditorData(request)) != editor:
   130                 rev = line.rev
   131                 break
   132 
   133     if rev == u"00000000": # page created by spammer
   134         comment = u"Page deleted by Despam action"
   135         pg = PageEditor.PageEditor(request, pagename, do_editor_backup=0)
   136         try:
   137             savemsg = pg.deletePage(comment)
   138         except pg.SaveError, msg:
   139             savemsg = unicode(msg)
   140     else: # page edited by spammer
   141         oldpg = Page.Page(request, pagename, rev=int(rev))
   142         pg = PageEditor.PageEditor(request, pagename, do_editor_backup=0)
   143         try:
   144             savemsg = pg.saveText(oldpg.get_raw_body(), 0, extra=rev, action="SAVE/REVERT")
   145         except pg.SaveError, msg:
   146             savemsg = unicode(msg)
   147     return savemsg
   148 
   149 def revert_pages(request, editor, timestamp):
   150     _ = request.getText
   151 
   152     editor = wikiutil.url_unquote(editor)
   153     timestamp = int(timestamp * 1000000)
   154     log = editlog.EditLog(request)
   155     pages = {}
   156     revertpages = []
   157     for line in log.reverse():
   158         if line.ed_time_usecs < timestamp:
   159             break
   160 
   161         if not request.user.may.read(line.pagename):
   162             continue
   163 
   164         if not line.pagename in pages:
   165             pages[line.pagename] = 1
   166             if repr(line.getInterwikiEditorData(request)) == editor:
   167                 revertpages.append(line.pagename)
   168 
   169     request.write("Pages to revert:<br>%s" % "<br>".join(revertpages))
   170     for pagename in revertpages:
   171         request.write("Begin reverting %s ...<br>" % pagename)
   172         msg = revert_page(request, pagename, editor)
   173         if msg:
   174             request.write("<p>%s: %s</p>" % (
   175                 Page.Page(request, pagename).link_to(request), msg))
   176         request.write("Finished reverting %s.<br>" % pagename)
   177 
   178 def execute(pagename, request):
   179     _ = request.getText
   180     # check for superuser
   181     if not request.user.isSuperUser():
   182         request.theme.add_msg(_('You are not allowed to use this action.'), "error")
   183         return Page.Page(request, pagename).send_page()
   184 
   185     editor = request.form.get('editor')
   186     timestamp = time.time() - DAYS * 24 * 3600
   187     ok = request.form.get('ok', 0)
   188 
   189     request.theme.send_title("Despam", pagename=pagename)
   190     # Start content (important for RTL support)
   191     request.write(request.formatter.startContent("content"))
   192 
   193     if ok:
   194         revert_pages(request, editor, timestamp)
   195     elif editor:
   196         show_pages(request, pagename, editor, timestamp)
   197     else:
   198         request.write(show_editors(request, pagename, timestamp))
   199 
   200     # End content and send footer
   201     request.write(request.formatter.endContent())
   202     request.theme.send_footer(pagename)
   203     request.theme.send_closing_html()
   204