changeset 5523:af66afbc9a31

merged moin/1.7
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Mon, 08 Feb 2010 19:01:03 +0100
parents 5359bfdf91ba (current diff) 879674c9320a (diff)
children 069f75c3d59c 7252009186c0
files MoinMoin/action/AttachFile.py MoinMoin/support/python_compatibility.py MoinMoin/wikiutil.py
diffstat 3 files changed, 60 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/action/AttachFile.py	Mon Feb 08 00:02:55 2010 +0100
+++ b/MoinMoin/action/AttachFile.py	Mon Feb 08 19:01:03 2010 +0100
@@ -79,6 +79,11 @@
 
 def attachUrl(request, pagename, filename=None, **kw):
     # filename is not used yet, but should be used later to make a sub-item url
+    if not (kw.get('do') in ['get', 'view', None]
+            and
+            kw.get('rename') is None):
+        # create a ticket for the not so harmless operations
+        kw['ticket'] = wikiutil.createTicket(request)
     if kw:
         qs = '?%s' % wikiutil.makeQueryString(kw, want_unicode=False)
     else:
@@ -474,6 +479,7 @@
 <p>
 <input type="hidden" name="action" value="%(action_name)s">
 <input type="hidden" name="do" value="upload">
+<input type="hidden" name="ticket" value="%(ticket)s">
 <input type="submit" value="%(upload_button)s">
 </p>
 </form>
@@ -488,6 +494,7 @@
     'overwrite_checked': ('', 'checked')[request.form.get('overwrite', ['0'])[0] == '1'],
     'upload_button': _('Upload'),
     'textcha': TextCha(request).render(),
+    'ticket': wikiutil.createTicket(request),
 })
 
     request.write('<h2>' + _("Attached Files") + '</h2>')
@@ -552,6 +559,10 @@
 
 def _do_upload(pagename, request):
     _ = request.getText
+
+    if not wikiutil.checkTicket(request, request.form.get('ticket', [''])[0]):
+        return _('Please use the interactive user interface to use action %(actionname)s!') % {'actionname': 'AttachFile.upload' }
+
     # Currently we only check TextCha for upload (this is what spammers ususally do),
     # but it could be extended to more/all attachment write access
     if not TextCha(request).check_answer_from_form():
@@ -607,6 +618,9 @@
 def _do_savedrawing(pagename, request):
     _ = request.getText
 
+    if not wikiutil.checkTicket(request, request.form.get('ticket', [''])[0]):
+        return _('Please use the interactive user interface to use action %(actionname)s!') % {'actionname': 'AttachFile.savedrawing' }
+
     if not request.user.may.write(pagename):
         return _('You are not allowed to save a drawing on this page.')
 
@@ -654,6 +668,9 @@
 def _do_del(pagename, request):
     _ = request.getText
 
+    if not wikiutil.checkTicket(request, request.form.get('ticket', [''])[0]):
+        return _('Please use the interactive user interface to use action %(actionname)s!') % {'actionname': 'AttachFile.del' }
+
     pagename, filename, fpath = _access_file(pagename, request)
     if not request.user.may.delete(pagename):
         return _('You are not allowed to delete attachments on this page.')
@@ -713,8 +730,8 @@
 
     if 'cancel' in request.form:
         return _('Move aborted!')
-    if not wikiutil.checkTicket(request, request.form['ticket'][0]):
-        return _('Please use the interactive user interface to move attachments!')
+    if not wikiutil.checkTicket(request, request.form.get('ticket', [''])[0]):
+        return _('Please use the interactive user interface to use action %(actionname)s!') % {'actionname': 'AttachFile.move' }
     if not request.user.may.delete(pagename):
         return _('You are not allowed to move attachments from this page.')
 
@@ -831,6 +848,9 @@
 def _do_install(pagename, request):
     _ = request.getText
 
+    if not wikiutil.checkTicket(request, request.form.get('ticket', [''])[0]):
+        return _('Please use the interactive user interface to use action %(actionname)s!') % {'actionname': 'AttachFile.install' }
+
     pagename, target, targetpath = _access_file(pagename, request)
     if not request.user.isSuperUser():
         return _('You are not allowed to install files.')
@@ -854,8 +874,11 @@
 
 def _do_unzip(pagename, request, overwrite=False):
     _ = request.getText
+
+    if not wikiutil.checkTicket(request, request.form.get('ticket', [''])[0]):
+        return _('Please use the interactive user interface to use action %(actionname)s!') % {'actionname': 'AttachFile.unzip' }
+
     pagename, filename, fpath = _access_file(pagename, request)
-
     if not (request.user.may.delete(pagename) and request.user.may.read(pagename) and request.user.may.write(pagename)):
         return _('You are not allowed to unzip attachments of this page.')
 
--- a/MoinMoin/support/python_compatibility.py	Mon Feb 08 00:02:55 2010 +0100
+++ b/MoinMoin/support/python_compatibility.py	Mon Feb 08 19:01:03 2010 +0100
@@ -76,6 +76,7 @@
             else:
                 d = kw or self.kw
             return self.fn(*(self.args + args), **d)
+
 """
 This is a feature from python 2.5, needed for compatibility with python 2.3 and 2.4,
 although it may not be 100% compatible.
--- a/MoinMoin/wikiutil.py	Mon Feb 08 00:02:55 2010 +0100
+++ b/MoinMoin/wikiutil.py	Mon Feb 08 19:01:03 2010 +0100
@@ -2461,10 +2461,12 @@
         return pagename, ""
 
 ########################################################################
-### Tickets - used by RenamePage and DeletePage
+### Tickets - usually used in forms to make sure that form submissions
+### are in response to a form the same user got from moin for the same
+### action and same page.
 ########################################################################
 
-def createTicket(request, tm=None, action=None):
+def createTicket(request, tm=None, action=None, pagename=None):
     """ Create a ticket using a configured secret
 
         @param tm: unix timestamp (optional, uses current time if not given)
@@ -2472,41 +2474,47 @@
                        Note: if you create a ticket for a form that calls another
                              action than the current one, you MUST specify the
                              action you call when posting the form.
+        @param pagename: page name (optional, uses current page name if not given)
+                       Note: if you create a ticket for a form that posts to another
+                             page than the current one, you MUST specify the
+                             page name you use when posting the form.
     """
 
-    from MoinMoin.support.python_compatibility import hash_new
+    from MoinMoin.support.python_compatibility import hmac_new
     if tm is None:
+        # for age-check of ticket
         tm = "%010x" % time.time()
 
-    # make the ticket specific to the page and action:
-    try:
-        pagename = quoteWikinameURL(request.page.page_name)
-    except:
-        pagename = 'None'
+    # make the ticket very specific:
+    if pagename is None:
+        try:
+            pagename = request.page.page_name
+        except:
+            pagename = ''
 
     if action is None:
-        try:
-            action = request.action
-        except:
-            action = 'None'
-
-    secret = request.cfg.secrets['wikiutil/tickets']
-    digest = hash_new('sha1', secret)
-
-    ticket = "%s.%s.%s" % (tm, pagename, action)
-    digest.update(ticket)
+        action = request.action
 
     if request.session and not request.session.is_new:
         sid = request.session.name
     else:
-        sid = 'None'
+        sid = ''
+
     if request.user.valid:
         uid = request.user.id
     else:
-        uid = 'None'
-    digest.update(sid+uid)
-
-    return "%s.%s" % (ticket, digest.hexdigest())
+        uid = ''
+
+    hmac_data = []
+    for value in [tm, pagename, action, sid, uid, ]:
+        if isinstance(value, unicode):
+            value = value.encode('utf-8')
+        hmac_data.append(value)
+
+    hmac = hmac_new(request.cfg.secrets['wikiutil/tickets'],
+                    ''.join(hmac_data))
+    return "%s.%s" % (tm, hmac.hexdigest())
+
 
 
 def checkTicket(request, ticket):
@@ -2523,6 +2531,8 @@
         # we don't accept tickets older than 10h
         logging.debug("checkTicket: too old ticket, timestamp %r" % timestamp)
         return False
+    # Note: if the session timed out, that will also invalidate the ticket,
+    #       if the ticket was created within a session.
     ourticket = createTicket(request, timestamp_str)
     logging.debug("checkTicket: returning %r, got %r, expected %r" % (ticket == ourticket, ticket, ourticket))
     return ticket == ourticket