Attachment 'sud.py'
Download 1 # -*- coding: iso-8859-1 -*-
2
3 import tokenize
4 import StringIO
5 import string
6 import os
7 import re
8 from traceback import format_exception
9 import codecs
10
11 from MoinMoin.util.ParserBase import ParserBase
12 from MoinMoin.util import MoinMoinNoFooter, filesys
13 from MoinMoin import config
14
15 Dependencies = ['time']
16
17 class StopScriptError(StandardError):
18 pass
19
20 def redirect(target, message=None):
21 raise StopScriptError('redirect ' + target, message)
22
23 def return_(message=None):
24 raise StopScriptError('return', message)
25
26 class SudData(object):
27 zone = None
28 status = None
29 _datafile = None
30 inventory = None
31 otherzones = None
32
33 lzone_re = re.compile(r'lastzone\s*=\s*(.*)')
34 zone_re = re.compile(r'zonestatus\((.*)\)\s*=\s*(.*)')
35 dict_re = re.compile(r'(.*):(.*)')
36 def __init__(self, cfg, user, zone):
37 self.zone = zone
38 self.status = 0
39 self.otherzones = ''
40 self.inventory = {}
41 self._datafile = os.path.join(cfg.user_dir, user.id + '.suddata')
42 if os.path.exists(self._datafile):
43 self.load()
44 def get_status(self):
45 return self.status
46 def set_status(self, status):
47 if isinstance(status, int) or \
48 isinstance(status, basestring) or \
49 isinstance(status, list):
50 self.status = status
51 else:
52 raise ValueError('Status must be int, str or list')
53 def get_inventory(self):
54 class Empty(object):
55 pass
56 result = Empty()
57 result.set_item = self.inventory.__setitem__
58 result.get_item = self.inventory.__getitem__
59 result.del_item = self.inventory.__delitem__
60 result.has_key = self.inventory.has_key
61 return result
62 def load(self):
63 data = codecs.open(self._datafile, "r", config.charset)
64 for line in map(string.strip, data.readlines()):
65 if not line or line.startswith('#'):
66 continue
67 match = self.lzone_re.search(line)
68 if match:
69 lastzone = match.group(1)
70 continue
71 match = self.zone_re.search(line)
72 if match:
73 if match.group(1) == self.zone:
74 self.status = match.group(2)
75 if self.status.startswith('['):
76 self.status = eval(self.status)
77 else:
78 self.otherzones += line + '\n'
79 continue
80 if self.zone != lastzone:
81 continue
82 match = self.dict_re.search(line)
83 if match:
84 self.inventory[match.group(1)] = match.group(2)
85 data.close()
86 def save(self):
87 filesys.makeDirs(os.path.dirname(self._datafile))
88 data = codecs.open(self._datafile, "w", config.charset)
89 data.write('lastzone = %s\n' % self.zone)
90 data.write('zonestatus(%s) = %s\n' % (self.zone, str(self.status)))
91 data.write(self.otherzones)
92 for ii in self.inventory.keys():
93 data.write('%s:%s' % (ii, self.inventory[ii]) + '\n')
94 data.close()
95
96 class Parser(ParserBase):
97
98 parsername = "SudParser"
99 extensions = ['']
100
101 _restricted_tokens = ('import', 'open', 'eval', 'exec', \
102 'print', 'execfile', 'file')
103 emsg = None
104 messages = None
105
106 def __init__(self, raw, request, **kw):
107 self.request = request
108 self.messages = []
109 _ = request.getText
110
111 pagename = request.page.page_name
112 adampage = pagename.split('/')[0]
113 zone = request.pragma.get('zone', adampage)
114 if zone.split('/')[0] != adampage:
115 self.emsg = _('Invalid %s') % 'zone'
116 return
117
118 if request.form.has_key('message'):
119 self.messages = request.form['message'][0].split(',,')
120 try:
121 rf_count = int(request.form.get('refreshed', (0,))[0])
122 except ValueError:
123 rf_count = 0
124
125 # Check raw text input
126 tokenstream = tokenize.generate_tokens(StringIO.StringIO(raw).readline)
127 try:
128 while 1: # tokenstream ends by raising an exception
129 token = tokenstream.next()
130 if token[0] == 1 and \
131 ( token[1] in self._restricted_tokens or \
132 token[1].find('__') != -1 ):
133 self.emsg = _('Disabled statement %s used in line %s.') % \
134 (token[1], token[2][0])
135 return
136 except StopIteration:
137 pass
138
139 requested_redirect = ''
140 # Create environment
141 suddata = SudData(request.cfg, request.user, zone)
142 referer = request.http_referer.replace(request.getBaseURL(), '')
143 referer = referer.strip('/')
144 if referer.find('?') > 0:
145 referer = referer[:referer.index('?')]
146 sb_locals = {'msg':'',
147 'referer':referer,
148 'username':request.user.name,
149 'status':suddata.get_status(),
150 'inventory':suddata.get_inventory(),
151 'return_':return_,
152 'redirect':redirect,
153 'refresh':0,
154 'refresh_count':rf_count,
155 }
156
157 try:
158 exec raw in sb_locals
159 except StopScriptError, sse:
160 if len(sse.args) > 1:
161 sb_locals['msg'] = sse.args[1]
162 if sse.args[0].startswith('redirect '):
163 requested_redirect = sse.args[0].split(' ', 1)[1]
164 if requested_redirect.find('://') > -1:
165 self.emsg = 'Illegal redirect to external page'
166 return
167 except StandardError, se:
168 self.emsg = ''.join(format_exception(se.__class__, se, None))
169 return
170
171 sbmsg = sb_locals.get('msg', '')
172 if isinstance(sbmsg, list) or isinstance(sbmsg, tuple):
173 self.messages.extend(sbmsg)
174 elif sbmsg:
175 self.messages.append(unicode(sbmsg))
176
177 try:
178 suddata.set_status(sb_locals.get('status', 0))
179 except ValueError:
180 self.emsg = 'Invalid %s' % 'status'
181 return
182 suddata.save()
183
184 if requested_redirect:
185 if not request.form.has_key('debug'):
186 url = requested_redirect
187 if self.messages:
188 url += ('?', '&')[url.find('?') != -1] + 'message='
189 url += ',,'.join( \
190 ['%s:+%s' % (pagename, x.replace(' ', '+')) \
191 for x in self.messages])
192 url = url.encode("utf-8")
193 print '<script language="javascript">\n' + \
194 '<!--\n' + \
195 'document.location.replace("%s");\n' % url + \
196 '//-->\n' + \
197 '</script>\n'
198 print 'This page redirects to %s using Javascript!' \
199 % requested_redirect
200 raise MoinMoinNoFooter
201 else:
202 self.messages.append('Redirection to %s on hold (debug mode)' \
203 % requested_redirect)
204 del sb_locals['__builtins__']
205 self.messages.append(str(sb_locals))
206
207 try:
208 secs = int(sb_locals.get('refresh', 0))
209 if secs > 0:
210 cmd = pagename + '?refreshed=%d' % (rf_count + 1)
211 cmd = 'document.location.replace("%s")' % cmd
212 print '<script language="javascript">\n' + \
213 '<!--\n' + \
214 "setTimeout('%s', %d);\n" % (cmd, secs*1000) + \
215 '//-->\n' + \
216 '</script>\n'
217 except ValueError:
218 self.emsg = _('Invalid value for %s') % 'refresh'
219
220 def format(self, formatter):
221 if self.emsg:
222 self.request.write('<div class="error">%s</div>\n' % self.emsg)
223 if self.messages:
224 self.request.write('<div id="message">\n')
225 for ii in self.messages:
226 self.request.write(' %s<br />\n' % ii.encode("utf-8"))
227 self.request.write('</div>\n')
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.