Back to index

moin  1.9.0~rc2
Despam.py
Go to the documentation of this file.
00001 # -*- coding: iso-8859-1 -*-
00002 """
00003     MoinMoin - Despam action
00004 
00005     Mass revert changes done by some specific author / bot.
00006 
00007     @copyright: 2005 by ???, Thomas Waldmann
00008     @license: GNU GPL, see COPYING for details.
00009 """
00010 
00011 DAYS = 30 # we look for spam edits in the last x days
00012 
00013 import time
00014 
00015 from MoinMoin import log
00016 logging = log.getLogger(__name__)
00017 
00018 from MoinMoin.logfile import editlog
00019 from MoinMoin.util.dataset import TupleDataset, Column
00020 from MoinMoin.widget.browser import DataBrowserWidget
00021 from MoinMoin import wikiutil, Page, PageEditor
00022 from MoinMoin.macro import RecentChanges
00023 
00024 def render(editor_tuple):
00025     etype, evalue = editor_tuple
00026     if etype in ('ip', 'email', ):
00027         ret = evalue
00028     elif etype == 'interwiki':
00029         ewiki, euser = evalue
00030         if ewiki == 'Self':
00031             ret = euser
00032         else:
00033             ret = '%s:%s' % evalue
00034     else:
00035         ret = repr(editor_tuple)
00036     return ret
00037 
00038 def show_editors(request, pagename, timestamp):
00039     _ = request.getText
00040 
00041     timestamp = int(timestamp * 1000000)
00042     log = editlog.EditLog(request)
00043     editors = {}
00044     pages = {}
00045     for line in log.reverse():
00046         if line.ed_time_usecs < timestamp:
00047             break
00048 
00049         if not request.user.may.read(line.pagename):
00050             continue
00051 
00052         editor = line.getInterwikiEditorData(request)
00053         if not line.pagename in pages:
00054             pages[line.pagename] = 1
00055             editors[editor] = editors.get(editor, 0) + 1
00056 
00057     editors = [(nr, editor) for editor, nr in editors.iteritems()]
00058     editors.sort()
00059     editors.reverse()
00060 
00061     pg = Page.Page(request, pagename)
00062 
00063     dataset = TupleDataset()
00064     dataset.columns = [Column('editor', label=_("Editor"), align='left'),
00065                        Column('pages', label=_("Pages"), align='right'),
00066                        Column('link', label='', align='left')]
00067     for nr, editor in editors:
00068         dataset.addRow((render(editor), unicode(nr),
00069             pg.link_to(request, text=_("Select Author"),
00070                 querystr={
00071                     'action': 'Despam',
00072                     'editor': repr(editor),
00073                 })))
00074 
00075     table = DataBrowserWidget(request)
00076     table.setData(dataset)
00077     return table.render(method="GET")
00078 
00079 class tmp:
00080     pass
00081 
00082 def show_pages(request, pagename, editor, timestamp):
00083     _ = request.getText
00084 
00085     timestamp = int(timestamp * 1000000)
00086     log = editlog.EditLog(request)
00087     pages = {}
00088     #  mimic macro object for use of RecentChanges subfunctions
00089     macro = tmp()
00090     macro.request = request
00091     macro.formatter = request.html_formatter
00092 
00093     request.write("<table>")
00094     for line in log.reverse():
00095         if line.ed_time_usecs < timestamp:
00096             break
00097 
00098         if not request.user.may.read(line.pagename):
00099             continue
00100 
00101         if not line.pagename in pages:
00102             pages[line.pagename] = 1
00103             if repr(line.getInterwikiEditorData(request)) == editor:
00104                 line.time_tuple = request.user.getTime(wikiutil.version2timestamp(line.ed_time_usecs))
00105                 request.write(RecentChanges.format_page_edits(macro, [line], timestamp))
00106 
00107     request.write('''
00108 </table>
00109 <p>
00110 <form method="post" action="%s">
00111 <input type="hidden" name="action" value="Despam">
00112 <input type="hidden" name="editor" value="%s">
00113 <input type="submit" name="ok" value="%s">
00114 </form>
00115 </p>
00116 ''' % (request.href(pagename), wikiutil.url_quote(editor), _("Revert all!")))
00117 
00118 def revert_page(request, pagename, editor):
00119     if not request.user.may.revert(pagename):
00120         return
00121 
00122     log = editlog.EditLog(request, rootpagename=pagename)
00123 
00124     first = True
00125     rev = u"00000000"
00126     for line in log.reverse():
00127         if first:
00128             first = False
00129             if repr(line.getInterwikiEditorData(request)) != editor:
00130                 return
00131         else:
00132             if repr(line.getInterwikiEditorData(request)) != editor:
00133                 rev = line.rev
00134                 break
00135 
00136     if rev == u"00000000": # page created by spammer
00137         comment = u"Page deleted by Despam action"
00138         pg = PageEditor.PageEditor(request, pagename, do_editor_backup=0)
00139         try:
00140             savemsg = pg.deletePage(comment)
00141         except pg.SaveError, msg:
00142             savemsg = unicode(msg)
00143     else: # page edited by spammer
00144         oldpg = Page.Page(request, pagename, rev=int(rev))
00145         pg = PageEditor.PageEditor(request, pagename, do_editor_backup=0)
00146         try:
00147             savemsg = pg.saveText(oldpg.get_raw_body(), 0, extra=rev, action="SAVE/REVERT")
00148         except pg.SaveError, msg:
00149             savemsg = unicode(msg)
00150     return savemsg
00151 
00152 def revert_pages(request, editor, timestamp):
00153     _ = request.getText
00154 
00155     editor = wikiutil.url_unquote(editor)
00156     timestamp = int(timestamp * 1000000)
00157     log = editlog.EditLog(request)
00158     pages = {}
00159     revertpages = []
00160     for line in log.reverse():
00161         if line.ed_time_usecs < timestamp:
00162             break
00163 
00164         if not request.user.may.read(line.pagename):
00165             continue
00166 
00167         if not line.pagename in pages:
00168             pages[line.pagename] = 1
00169             if repr(line.getInterwikiEditorData(request)) == editor:
00170                 revertpages.append(line.pagename)
00171 
00172     request.write("Pages to revert:<br>%s" % "<br>".join(revertpages))
00173     for pagename in revertpages:
00174         request.write("Begin reverting %s ...<br>" % pagename)
00175         msg = revert_page(request, pagename, editor)
00176         if msg:
00177             request.write("<p>%s: %s</p>" % (
00178                 Page.Page(request, pagename).link_to(request), msg))
00179         request.write("Finished reverting %s.<br>" % pagename)
00180 
00181 def execute(pagename, request):
00182     _ = request.getText
00183     # check for superuser
00184     if not request.user.isSuperUser():
00185         request.theme.add_msg(_('You are not allowed to use this action.'), "error")
00186         return Page.Page(request, pagename).send_page()
00187 
00188     editor = request.values.get('editor')
00189     timestamp = time.time() - DAYS * 24 * 3600
00190     ok = request.form.get('ok', 0)
00191     logging.debug("editor: %r ok: %r" % (editor, ok))
00192 
00193     request.theme.send_title("Despam", pagename=pagename)
00194     # Start content (important for RTL support)
00195     request.write(request.formatter.startContent("content"))
00196 
00197     if ok:
00198         revert_pages(request, editor, timestamp)
00199     elif editor:
00200         show_pages(request, pagename, editor, timestamp)
00201     else:
00202         request.write(show_editors(request, pagename, timestamp))
00203 
00204     # End content and send footer
00205     request.write(request.formatter.endContent())
00206     request.theme.send_footer(pagename)
00207     request.theme.send_closing_html()
00208