View | Details | Raw Unified | Return to bug 227394
Collapse All | Expand All

(-)www/moinmoin/Makefile (+1 lines)
Lines 3-8 Link Here
3
3
4
PORTNAME=	moinmoin
4
PORTNAME=	moinmoin
5
PORTVERSION=	1.9.9
5
PORTVERSION=	1.9.9
6
PORTREVISION=	1
6
CATEGORIES=	www python
7
CATEGORIES=	www python
7
MASTER_SITES=	http://static.moinmo.in/files/
8
MASTER_SITES=	http://static.moinmo.in/files/
8
DISTNAME=	moin-${PORTVERSION}
9
DISTNAME=	moin-${PORTVERSION}
(-)www/moinmoin/files/patch-MoinMoin_PageEditor.py (+12 lines)
Added Link Here
1
--- MoinMoin/PageEditor.py.orig	2016-10-31 20:44:01 UTC
2
+++ MoinMoin/PageEditor.py
3
@@ -422,6 +422,9 @@ If you don't want that, hit '''%(cancel_button_text)s'
4
         from MoinMoin.security.textcha import TextCha
5
         request.write(TextCha(request).render())
6
 
7
+        from MoinMoin.security.sec_recaptcha import ReCaptcha
8
+        request.write(ReCaptcha(request).render())
9
+
10
         # Add textarea with page text
11
         self.sendconfirmleaving()
12
 
(-)www/moinmoin/files/patch-MoinMoin_PageGraphicalEditor.py (+12 lines)
Added Link Here
1
--- MoinMoin/PageGraphicalEditor.py.orig	2016-10-31 20:44:01 UTC
2
+++ MoinMoin/PageGraphicalEditor.py
3
@@ -305,6 +305,9 @@ If you don't want that, hit '''%(cancel_button_text)s'
4
         from MoinMoin.security.textcha import TextCha
5
         request.write(TextCha(request).render())
6
 
7
+        from MoinMoin.security.sec_recaptcha import ReCaptcha
8
+        request.write(ReCaptcha(request).render())
9
+
10
         self.sendconfirmleaving() # TODO update state of flgChange to make this work, see PageEditor
11
 
12
         # Add textarea with page text
(-)www/moinmoin/files/patch-MoinMoin_action_AttachFile.py (+35 lines)
Added Link Here
1
--- MoinMoin/action/AttachFile.py.orig	2016-10-31 20:44:01 UTC
2
+++ MoinMoin/action/AttachFile.py
3
@@ -44,6 +44,7 @@ from MoinMoin import config, packages
4
 from MoinMoin.Page import Page
5
 from MoinMoin.util import filesys, timefuncs
6
 from MoinMoin.security.textcha import TextCha
7
+from MoinMoin.security.sec_recaptcha import ReCaptcha
8
 from MoinMoin.events import FileAttachedEvent, FileRemovedEvent, send_event
9
 
10
 action_name = __name__.split('.')[-1]
11
@@ -654,6 +655,7 @@ def send_uploadform(pagename, request):
12
 <dd><input type="checkbox" name="overwrite" value="1" %(overwrite_checked)s></dd>
13
 </dl>
14
 %(textcha)s
15
+%(recaptcha)s
16
 <p>
17
 <input type="hidden" name="action" value="%(action_name)s">
18
 <input type="hidden" name="do" value="upload">
19
@@ -671,6 +673,7 @@ def send_uploadform(pagename, request):
20
     'overwrite_checked': ('', 'checked')[request.form.get('overwrite', '0') == '1'],
21
     'upload_button': _('Upload'),
22
     'textcha': TextCha(request).render(),
23
+    'recaptcha': ReCaptcha(request).render(),
24
     'ticket': wikiutil.createTicket(request),
25
 })
26
 
27
@@ -728,6 +731,8 @@ def _do_upload(pagename, request):
28
     # but it could be extended to more/all attachment write access
29
     if not TextCha(request).check_answer_from_form():
30
         return _('TextCha: Wrong answer! Go back and try again...')
31
+    if not ReCaptcha(request).check_answer_from_form():
32
+        return _('ReCaptcha: Wrong answer! Go back and try again...')
33
 
34
     form = request.form
35
 
(-)www/moinmoin/files/patch-MoinMoin_action_CopyPage.py (+57 lines)
Added Link Here
1
--- MoinMoin/action/CopyPage.py.orig	2016-10-31 20:44:01 UTC
2
+++ MoinMoin/action/CopyPage.py
3
@@ -14,6 +14,7 @@ from MoinMoin.Page import Page
4
 from MoinMoin.PageEditor import PageEditor
5
 from MoinMoin.action import ActionBase
6
 from MoinMoin.security.textcha import TextCha
7
+from MoinMoin.security.sec_recaptcha import ReCaptcha
8
 
9
 class CopyPage(ActionBase):
10
     """ Copy page action
11
@@ -45,11 +46,14 @@ class CopyPage(ActionBase):
12
 
13
     def do_action(self):
14
         """ copy this page to "pagename" """
15
+        status = False
16
         _ = self._
17
         # Currently we only check TextCha for upload (this is what spammers ususally do),
18
         # but it could be extended to more/all attachment write access
19
         if not TextCha(self.request).check_answer_from_form():
20
             return False, _('TextCha: Wrong answer! Go back and try again...')
21
+        if not ReCaptcha(self.request).check_answer_from_form():
22
+            return status, _('ReCaptcha: Wrong answer! Go back and try again...')
23
 
24
         form = self.form
25
         newpagename = form.get('newpagename', u'')
26
@@ -90,6 +94,7 @@ class CopyPage(ActionBase):
27
 
28
             d = {
29
                 'textcha': TextCha(self.request).render(),
30
+                'recaptcha': ReCaptcha(self.request).render(),
31
                 'subpage': subpages,
32
                 'subpages_checked': ('', 'checked')[self.request.args.get('subpages_checked', '0') == '1'],
33
                 'subpage_label': _('Copy all /subpages too?'),
34
@@ -105,6 +110,7 @@ class CopyPage(ActionBase):
35
 <br>
36
 <br>
37
 %(textcha)s
38
+%(recaptcha)s
39
 <table>
40
     <tr>
41
     <dd>
42
@@ -140,6 +146,7 @@ class CopyPage(ActionBase):
43
         else:
44
             d = {
45
                 'textcha': TextCha(self.request).render(),
46
+                'recaptcha': ReCaptcha(self.request).render(),
47
                 'pagename': wikiutil.escape(self.pagename, True),
48
                 'newname_label': _("New name"),
49
                 'comment_label': _("Optional reason for the copying"),
50
@@ -147,6 +154,7 @@ class CopyPage(ActionBase):
51
                 }
52
             return '''
53
 %(textcha)s
54
+%(recaptcha)s
55
 <table>
56
     <tr>
57
         <td class="label"><label>%(newname_label)s</label></td>
(-)www/moinmoin/files/patch-MoinMoin_action_Load.py (+35 lines)
Added Link Here
1
--- MoinMoin/action/Load.py.orig	2016-10-31 20:44:01 UTC
2
+++ MoinMoin/action/Load.py
3
@@ -14,6 +14,7 @@ from MoinMoin.action import ActionBase, AttachFile
4
 from MoinMoin.PageEditor import PageEditor
5
 from MoinMoin.Page import Page
6
 from MoinMoin.security.textcha import TextCha
7
+from MoinMoin.security.sec_recaptcha import ReCaptcha
8
 
9
 class Load(ActionBase):
10
     """ Load page action
11
@@ -40,6 +41,8 @@ class Load(ActionBase):
12
         # but it could be extended to more/all attachment write access
13
         if not TextCha(request).check_answer_from_form():
14
             return status, _('TextCha: Wrong answer! Go back and try again...')
15
+        if not ReCaptcha(request).check_answer_from_form():
16
+            return _('ReCaptcha: Wrong answer! Go back and try again...')
17
 
18
         comment = form.get('comment', u'')
19
         comment = wikiutil.clean_input(comment)
20
@@ -97,6 +100,7 @@ class Load(ActionBase):
21
 <dd><input type="text" name="comment" size="80" maxlength="200"></dd>
22
 </dl>
23
 %(textcha)s
24
+%(recaptcha)s
25
 <p>
26
 <input type="hidden" name="action" value="%(action_name)s">
27
 <input type="hidden" name="do" value="upload">
28
@@ -115,6 +119,7 @@ class Load(ActionBase):
29
     'buttons_html': buttons_html,
30
     'action_name': self.form_trigger,
31
     'textcha': TextCha(self.request).render(),
32
+    'recaptcha': ReCaptcha(self.request).render(),
33
 }
34
 
35
 def execute(pagename, request):
(-)www/moinmoin/files/patch-MoinMoin_action_edit.py (+12 lines)
Added Link Here
1
--- MoinMoin/action/edit.py.orig	2016-10-31 20:44:01 UTC
2
+++ MoinMoin/action/edit.py
3
@@ -163,6 +163,9 @@ def execute(pagename, request):
4
             from MoinMoin.security.textcha import TextCha
5
             if not TextCha(request).check_answer_from_form():
6
                 raise pg.SaveError(_('TextCha: Wrong answer! Try again below...'))
7
+            from MoinMoin.security.sec_recaptcha import ReCaptcha
8
+            if not ReCaptcha(request).check_answer_from_form():
9
+                raise pg.SaveError(_('ReCaptcha: Wrong answer! Try again below...'))
10
             if request.cfg.comment_required and not comment:
11
                 raise pg.SaveError(_('Supplying a comment is mandatory. Write a comment below and try again...'))
12
             savemsg = pg.saveText(savetext, rev, trivial=trivial, comment=comment)
(-)www/moinmoin/files/patch-MoinMoin_action_newaccount.py (+38 lines)
Added Link Here
1
--- MoinMoin/action/newaccount.py.orig	2016-10-31 20:44:01 UTC
2
+++ MoinMoin/action/newaccount.py
3
@@ -10,6 +10,7 @@ from MoinMoin import user, wikiutil
4
 from MoinMoin.Page import Page
5
 from MoinMoin.widget import html
6
 from MoinMoin.security.textcha import TextCha
7
+from MoinMoin.security.sec_recaptcha import ReCaptcha
8
 from MoinMoin.auth import MoinAuth
9
 
10
 
11
@@ -26,6 +27,9 @@ def _create_user(request):
12
     if not TextCha(request).check_answer_from_form():
13
         return _('TextCha: Wrong answer! Go back and try again...')
14
 
15
+    if not ReCaptcha(request).check_answer_from_form():
16
+        return _('ReCaptcha: Wrong answer! Go back and try again...')
17
+
18
     # Create user profile
19
     theuser = user.User(request, auth_method="new-user")
20
 
21
@@ -141,6 +145,17 @@ def _create_form(request):
22
         if textcha:
23
             td.append(textcha.render())
24
         row.append(td)
25
+
26
+    recaptcha = ReCaptcha(request)
27
+    if recaptcha.is_enabled():
28
+        row = html.TR()
29
+        tbl.append(row)
30
+        row.append(html.TD().append(html.STRONG().append(
31
+                                      html.Text(_('ReCaptcha (required)')))))
32
+        td = html.TD()
33
+        if recaptcha:
34
+            td.append(recaptcha.render())
35
+        row.append(td)        
36
 
37
     row = html.TR()
38
     tbl.append(row)
(-)www/moinmoin/files/patch-MoinMoin_security_sec__recaptcha.py (+96 lines)
Added Link Here
1
--- MoinMoin/security/sec_recaptcha.py.orig	2018-05-02 03:24:23 UTC
2
+++ MoinMoin/security/sec_recaptcha.py
3
@@ -0,0 +1,93 @@
4
+# -*- coding: iso-8859-1 -*-
5
+"""
6
+    MoinMoin - recaptcha support
7
+
8
+    Based heavily on the textcha support in textcha.py
9
+
10
+    @copyright: 2011 by Steve McIntyre
11
+    @copyright: 2018 by d42
12
+    @license: GNU GPL, see COPYING for details.
13
+"""
14
+import json
15
+import urllib
16
+import urllib2
17
+from textwrap import dedent
18
+
19
+from MoinMoin import log
20
+
21
+logging = log.getLogger(__name__)
22
+
23
+
24
+class ReCaptcha(object):
25
+    """ Recaptcha support """
26
+
27
+    VERIFY_URL = "https://www.google.com/recaptcha/api/siteverify"
28
+
29
+    def __init__(self, request):
30
+        """ Initialize the Recaptcha setup.
31
+
32
+            @param request: the request object
33
+        """
34
+        self.request = request
35
+        self.user_info = request.user.valid and request.user.name or request.remote_addr
36
+
37
+        self.site_key = getattr(request.cfg, "recaptcha_site_key", None)
38
+        self.secret_key = getattr(request.cfg, "recaptcha_secret_key", None)
39
+
40
+    def is_enabled(self):
41
+        """ check if we're configured, i.e. we have a key
42
+        """
43
+        return self.site_key and self.secret_key
44
+
45
+    def check_answer_from_form(self, form=None):
46
+        form = self.request.form if form is None else form
47
+
48
+        if not self.is_enabled():
49
+            return True
50
+
51
+        return self._submit(
52
+            response=form.get("g-recaptcha-response"),
53
+            remoteip=self.request.remote_addr
54
+        )
55
+
56
+    def _submit(self, response, remoteip):
57
+
58
+        def encode_if_necessary(s):
59
+            return s.encode("utf-8") if isinstance(s, unicode) else s
60
+
61
+        data = urllib.urlencode({
62
+            "secret": encode_if_necessary(self.secret_key),
63
+            "response":  encode_if_necessary(response),
64
+            "remoteip":  encode_if_necessary(remoteip),
65
+        })
66
+
67
+        request = urllib2.Request(
68
+            url=self.VERIFY_URL,
69
+            data=data,
70
+            headers={"Content-type": "application/x-www-form-urlencoded"}
71
+        )
72
+
73
+        try:
74
+            resp = urllib2.urlopen(request)
75
+            http_code = resp.getcode()
76
+            resp_json = json.loads(resp.read())
77
+            return resp_json["success"] if http_code == 200 else False
78
+        except urllib2.URLError as e:
79
+            logging.exception(e)
80
+            return False
81
+        finally:
82
+            resp.close()
83
+
84
+    def render(self, form=None):
85
+        """ Checks if ReCaptchas are enabled and returns HTML for one,
86
+            or an empty string if they are not enabled.
87
+
88
+            @return: unicode result html
89
+        """
90
+        if not self.is_enabled():
91
+            return u""
92
+
93
+        return dedent(u"""
94
+            <script src='//www.google.com/recaptcha/api.js'></script>
95
+            <div class="g-recaptcha" data-sitekey="{SITE_KEY}"></div>
96
+        """.format(SITE_KEY=self.site_key))
(-)www/moinmoin/files/patch-setup.py (-3 / +3 lines)
Lines 1-6 Link Here
1
--- ./setup.py.orig	2010-04-30 10:09:50.411058590 -0400
1
--- setup.py.orig	2016-10-31 20:44:02 UTC
2
+++ ./setup.py	2010-04-30 10:10:32.801862294 -0400
2
+++ setup.py
3
@@ -26,6 +26,7 @@
3
@@ -26,6 +26,7 @@ def isbad(name):
4
     return (name.startswith('.') or
4
     return (name.startswith('.') or
5
             name.startswith('#') or
5
             name.startswith('#') or
6
             name.endswith('.pickle') or
6
             name.endswith('.pickle') or
(-)www/moinmoin/pkg-descr (-1 / +1 lines)
Lines 2-5 MoinMoin is a Python clone of WikiWiki, which is a composition system; Link Here
2
it's a discussion medium; it's a repository; it's a mail system;
2
it's a discussion medium; it's a repository; it's a mail system;
3
it's a tool for collaboration.
3
it's a tool for collaboration.
4
4
5
WWW: http://moinmo.in/
5
WWW: https://moinmo.in/
(-)www/moinmoin/pkg-plist (+3 lines)
Lines 1039-1044 bin/moin Link Here
1039
%%PYTHON_SITELIBDIR%%/MoinMoin/security/textcha.py
1039
%%PYTHON_SITELIBDIR%%/MoinMoin/security/textcha.py
1040
%%PYTHON_SITELIBDIR%%/MoinMoin/security/textcha.pyc
1040
%%PYTHON_SITELIBDIR%%/MoinMoin/security/textcha.pyc
1041
%%PYTHON_SITELIBDIR%%/MoinMoin/security/textcha.%%PYTHON_PYOEXTENSION%%
1041
%%PYTHON_SITELIBDIR%%/MoinMoin/security/textcha.%%PYTHON_PYOEXTENSION%%
1042
%%PYTHON_SITELIBDIR%%/MoinMoin/security/sec_recaptcha.py
1043
%%PYTHON_SITELIBDIR%%/MoinMoin/security/sec_recaptcha.pyc
1044
%%PYTHON_SITELIBDIR%%/MoinMoin/security/sec_recaptcha.%%PYTHON_PYOEXTENSION%%
1042
%%PYTHON_SITELIBDIR%%/MoinMoin/stats/__init__.py
1045
%%PYTHON_SITELIBDIR%%/MoinMoin/stats/__init__.py
1043
%%PYTHON_SITELIBDIR%%/MoinMoin/stats/__init__.pyc
1046
%%PYTHON_SITELIBDIR%%/MoinMoin/stats/__init__.pyc
1044
%%PYTHON_SITELIBDIR%%/MoinMoin/stats/__init__.%%PYTHON_PYOEXTENSION%%
1047
%%PYTHON_SITELIBDIR%%/MoinMoin/stats/__init__.%%PYTHON_PYOEXTENSION%%

Return to bug 227394