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