1.1 --- a/MoinForms.py Sat Jan 19 22:50:29 2013 +0100
1.2 +++ b/MoinForms.py Sun Jan 20 18:24:06 2013 +0100
1.3 @@ -6,8 +6,11 @@
1.4 @license: GNU GPL (v2 or later), see COPYING.txt for details.
1.5 """
1.6
1.7 +from compiler import parse
1.8 +from compiler.ast import Const, Dict, Discard, List, Module, Stmt
1.9 from MoinMoin.action import do_show
1.10 from MoinMoin.Page import Page
1.11 +from MoinMoin.security import parseACL
1.12 from MoinMoin import wikiutil
1.13 from MoinSupport import *
1.14 import re
1.15 @@ -47,7 +50,14 @@
1.16
1.17 # Get the form definition.
1.18
1.19 - structure = self.getFormStructure(fields)
1.20 + self.attributes, structure = self.getFormStructure(fields)
1.21 +
1.22 + # Check the permissions on the form.
1.23 +
1.24 + if not self.checkPermissions("write"):
1.25 + self.request.theme.add_msg(_("You do not appear to have access to this form."), "error")
1.26 + do_show(self.pagename, self.request)
1.27 + return
1.28
1.29 # Without any form definition, the page is probably the wrong one.
1.30
1.31 @@ -67,6 +77,7 @@
1.32
1.33 "Handle the finished 'fields' and 'form'."
1.34
1.35 + self.storeFields(fields)
1.36 self.unfinished(fields, form)
1.37
1.38 def unfinished(self, fields, form):
1.39 @@ -80,12 +91,33 @@
1.40
1.41 def getFormStructure(self, fields):
1.42
1.43 - "Return the structure of the form being handled."
1.44 + "Return the attributes and structure of the form being handled."
1.45
1.46 fragment = fields.get("fragment", [None])[0]
1.47 text = Page(self.request, self.pagename).get_raw_body()
1.48 - text = getFormForFragment(text, fragment)
1.49 - return getFormStructure(text, self.request)
1.50 + attributes, text = getFormForFragment(text, fragment)
1.51 + return attributes, getFormStructure(text, self.request)
1.52 +
1.53 + def checkPermissions(self, action):
1.54 +
1.55 + """
1.56 + Check the permissions of the user against any restrictions specified in
1.57 + the form's 'attributes'.
1.58 + """
1.59 +
1.60 + user = self.request.user
1.61 +
1.62 + # Use the page permissions if no access definition is given.
1.63 +
1.64 + if not self.attributes.has_key("access"):
1.65 + return user and getattr(user.may, action)(self.pagename)
1.66 +
1.67 + # Otherwise use the access definition.
1.68 +
1.69 + else:
1.70 + access = self.attributes["access"]
1.71 + acl = parseACL(self.request, access)
1.72 + return user and acl.may(self.request, user.name, action)
1.73
1.74 def validateFields(self, fields, structure):
1.75
1.76 @@ -221,6 +253,70 @@
1.77 max_index = -1
1.78 section[name] = {0 : placeholder}
1.79
1.80 + # Storage of form submissions.
1.81 +
1.82 + def storeFields(self, fields):
1.83 +
1.84 + """
1.85 + Store the given 'fields' as a Python object representation, subject to
1.86 + the given 'attributes'.
1.87 + """
1.88 +
1.89 + store = FormStore(self)
1.90 + store.append(repr(fields))
1.91 +
1.92 + def loadFields(self, number):
1.93 +
1.94 + "Load the fields associated with the given submission 'number'."
1.95 +
1.96 + try:
1.97 + module = parse(store[number])
1.98 + if checkStoredFormData(module):
1.99 + return eval(module)
1.100 +
1.101 + # NOTE: Should indicate any errors in retrieving form data.
1.102 +
1.103 + except:
1.104 + pass
1.105 +
1.106 + return {}
1.107 +
1.108 +def checkStoredFormData(node):
1.109 +
1.110 + """
1.111 + Check the syntax 'node' and its descendants for suitability as parts of
1.112 + a field definition.
1.113 + """
1.114 +
1.115 + for child in node.getChildNodes():
1.116 + if isinstance(child, Const):
1.117 + pass
1.118 + elif not isinstance(child, (Dict, Discard, List, Module, Stmt)) or not checkStoredFormData(child):
1.119 + return False
1.120 +
1.121 + return True
1.122 +
1.123 +class FormStore(ItemStore):
1.124 +
1.125 + "A form-specific storage mechanism."
1.126 +
1.127 + def __init__(self, handler):
1.128 +
1.129 + "Initialise the store with the form 'handler'."
1.130 +
1.131 + self.handler = handler
1.132 + page = Page(handler.request, handler.pagename)
1.133 + ItemStore.__init__(self, page, "forms", "form-locks")
1.134 +
1.135 + def can_write(self):
1.136 +
1.137 + """
1.138 + Permit writing of form data using the form attributes or page
1.139 + permissions.
1.140 + """
1.141 +
1.142 + return self.handler.checkPermissions("write")
1.143 +
1.144 # Form and field information.
1.145
1.146 def getFormStructure(text, request, path=None, structure=None):
1.147 @@ -265,14 +361,16 @@
1.148
1.149 """
1.150 Return the form region from the given 'text' for the specified 'fragment'.
1.151 - If no fragment is specified, the first form region is returned.
1.152 + If no fragment is specified, the first form region is returned. The form
1.153 + region is described using a tuple containing the attributes for the form
1.154 + and the body text of the form.
1.155 """
1.156
1.157 for format, attributes, body in getFragments(text):
1.158 - if not fragment or attributes.get("fragment") == fragment:
1.159 - return body
1.160 + if format == "form" and (not fragment or attributes.get("fragment") == fragment):
1.161 + return attributes, body
1.162
1.163 - return None
1.164 + return {}, None
1.165
1.166 def getFieldArguments(field_definition):
1.167