| [7424] | 1 | # -*- coding: utf-8 -*- |
|---|
| 2 | # |
|---|
| 3 | # Copyright (C) 2009 Verigy (Singapore) Pte. Ltd. |
|---|
| 4 | # All rights reserved. |
|---|
| 5 | # |
|---|
| 6 | # This software is licensed as described in the file COPYING, which |
|---|
| 7 | # you should have received as part of this distribution. |
|---|
| 8 | # |
|---|
| 9 | |
|---|
| [14958] | 10 | import StringIO |
|---|
| [10651] | 11 | import smtplib |
|---|
| [14958] | 12 | import random |
|---|
| [7424] | 13 | import re |
|---|
| [14958] | 14 | import time |
|---|
| [16871] | 15 | from datetime import datetime |
|---|
| [7424] | 16 | |
|---|
| [8190] | 17 | from genshi.core import escape |
|---|
| [14958] | 18 | from genshi.filters.html import HTMLSanitizer |
|---|
| [8190] | 19 | from genshi.input import HTMLParser, ParseError |
|---|
| [16876] | 20 | from trac.core import TracError, implements |
|---|
| [16872] | 21 | from trac.db.api import DatabaseManager |
|---|
| [14958] | 22 | from trac.db.schema import Column, Table |
|---|
| 23 | from trac.env import IEnvironmentSetupParticipant |
|---|
| [16871] | 24 | from trac.mimeview.api import Context, Mimeview |
|---|
| 25 | from trac.perm import IPermissionRequestor |
|---|
| 26 | from trac.util.datefmt import format_datetime, pretty_timedelta, utc |
|---|
| [16875] | 27 | from trac.util.text import exception_to_unicode |
|---|
| [14958] | 28 | from trac.web import IRequestHandler |
|---|
| [16871] | 29 | from trac.web.api import HTTPBadRequest |
|---|
| [14958] | 30 | from trac.wiki.macros import WikiMacroBase |
|---|
| 31 | from trac.wiki.model import WikiPage |
|---|
| 32 | from trac.wiki.formatter import Formatter, system_message |
|---|
| [8190] | 33 | |
|---|
| [14958] | 34 | import wikiforms_lib |
|---|
| [8190] | 35 | |
|---|
| [7424] | 36 | |
|---|
| [16876] | 37 | class WikiFormsMacro(WikiMacroBase): |
|---|
| [14958] | 38 | """Docs for WikiForms wiki processor. |
|---|
| 39 | """ |
|---|
| 40 | implements(IEnvironmentSetupParticipant, IPermissionRequestor, |
|---|
| 41 | IRequestHandler) |
|---|
| [7424] | 42 | |
|---|
| [14958] | 43 | # Database schema version (used to detect the need for upgrades)... |
|---|
| 44 | db_version = 1 |
|---|
| [7424] | 45 | |
|---|
| [14958] | 46 | # Database schema |
|---|
| [16871] | 47 | db_schema = [ |
|---|
| 48 | Table('wikiforms_fields', key=('field'))[ |
|---|
| 49 | Column('field'), |
|---|
| 50 | Column('value'), |
|---|
| 51 | Column('updated_by'), |
|---|
| 52 | Column('updated_on', type='INTEGER') |
|---|
| 53 | ] |
|---|
| 54 | ] |
|---|
| [7424] | 55 | |
|---|
| [16871] | 56 | # currently installed database schema version is stored here. |
|---|
| [14958] | 57 | found_db_version = None |
|---|
| [7424] | 58 | |
|---|
| [16871] | 59 | placeholder_cnt = 0 |
|---|
| [7424] | 60 | |
|---|
| [16871] | 61 | # IPermissionRequestor methods |
|---|
| [7424] | 62 | |
|---|
| [14958] | 63 | def get_permission_actions(self): |
|---|
| 64 | return ['WIKIFORMS_ADMIN', 'WIKIFORMS_UPDATE'] |
|---|
| [7424] | 65 | |
|---|
| [16871] | 66 | # IEnvironmentSetupParticipant |
|---|
| [7424] | 67 | |
|---|
| [14958] | 68 | def environment_created(self): |
|---|
| 69 | WikiFormsMacro.found_db_version = 0 |
|---|
| 70 | self.upgrade_environment(self.env.get_db_cnx()) |
|---|
| [7424] | 71 | |
|---|
| [14958] | 72 | def environment_needs_upgrade(self, db): |
|---|
| 73 | cursor = db.cursor() |
|---|
| [16872] | 74 | cursor.execute(""" |
|---|
| 75 | SELECT value FROM system WHERE name='wikiforms_version' |
|---|
| 76 | """) |
|---|
| [14958] | 77 | value = cursor.fetchone() |
|---|
| 78 | if not value: |
|---|
| 79 | WikiFormsMacro.found_db_version = 0 |
|---|
| 80 | return True |
|---|
| 81 | else: |
|---|
| 82 | WikiFormsMacro.found_db_version = int(value[0]) |
|---|
| 83 | return WikiFormsMacro.found_db_version < WikiFormsMacro.db_version |
|---|
| [7424] | 84 | |
|---|
| [14958] | 85 | def upgrade_environment(self, db): |
|---|
| 86 | db_manager = DatabaseManager(self.env)._get_connector()[0] |
|---|
| [7424] | 87 | |
|---|
| [14958] | 88 | # Insert the default table |
|---|
| 89 | cursor = db.cursor() |
|---|
| 90 | if not WikiFormsMacro.found_db_version: |
|---|
| 91 | # remember current database schema version... |
|---|
| [16871] | 92 | cursor.execute(""" |
|---|
| 93 | INSERT INTO system (name, value) |
|---|
| [16872] | 94 | VALUES ('wikiforms_version', %s) |
|---|
| 95 | """, (self.db_version,)) |
|---|
| [14958] | 96 | else: |
|---|
| 97 | # remember current database schema version... |
|---|
| [16871] | 98 | cursor.execute(""" |
|---|
| 99 | UPDATE system SET value = %s WHERE name = 'wikiforms_version' |
|---|
| [16872] | 100 | """, (self.db_version,)) |
|---|
| [7424] | 101 | |
|---|
| [16871] | 102 | # in case tables (from previous versions) are already available, |
|---|
| 103 | # remove them... |
|---|
| [14958] | 104 | for tbl in WikiFormsMacro.db_schema: |
|---|
| 105 | try: |
|---|
| [16871] | 106 | cursor.execute("DROP TABLE %s" % tbl.name) |
|---|
| [14958] | 107 | except: |
|---|
| 108 | pass |
|---|
| [7424] | 109 | |
|---|
| [14958] | 110 | # create tables according defined schema... |
|---|
| 111 | for tbl in WikiFormsMacro.db_schema: |
|---|
| 112 | for sql in db_manager.to_sql(tbl): |
|---|
| 113 | cursor.execute(sql) |
|---|
| [7424] | 114 | |
|---|
| [14958] | 115 | def match_request(self, req): |
|---|
| [16876] | 116 | return req.path_info == '/wikiforms/update' |
|---|
| [7424] | 117 | |
|---|
| [14958] | 118 | def process_request(self, req): |
|---|
| 119 | try: |
|---|
| [16871] | 120 | # check whether user has form-update permissions... |
|---|
| 121 | if 'WIKIFORMS_UPDATE' in req.perm or 'WIKIFORMS_ADMIN' in req.perm: |
|---|
| [14958] | 122 | pass |
|---|
| 123 | else: |
|---|
| [16871] | 124 | msg = "You(%s) don't have enough permissions to update " \ |
|---|
| 125 | "form values..." % req.authname |
|---|
| [14958] | 126 | raise TracError(msg) |
|---|
| [7424] | 127 | |
|---|
| [14958] | 128 | args = dict(req.args) |
|---|
| 129 | # |
|---|
| 130 | # you get something like this... |
|---|
| 131 | # |
|---|
| [16871] | 132 | # { |
|---|
| [14958] | 133 | # '__BACKPATH' : u'/trac/TPdev/wiki/sandbox', |
|---|
| 134 | # '__FORM_TOKEN': u'28b12aa6e225d804bd863ec0', |
|---|
| 135 | # '__SUBMIT' : u'Commit', |
|---|
| 136 | # '/wiki/sandbox/spec_comment': u'Please fill in your comment...', |
|---|
| 137 | # '/wiki/sandbox/spec_completion': u'foo', |
|---|
| 138 | # '/wiki/sandbox/spec_done': u'my_value', |
|---|
| 139 | # '/wiki/sandbox/choose_one': u'val2', |
|---|
| 140 | # '/wiki/sandbox/approval_comment': u'Please fill your\r\napproval\r\ncomment\r\nhere' |
|---|
| [16871] | 141 | # } |
|---|
| [14958] | 142 | # |
|---|
| [16871] | 143 | # self.log.debug(req.args) |
|---|
| 144 | backpath = args.pop('__BACKPATH', None) |
|---|
| [16873] | 145 | args.pop('__FORM_TOKEN', None) |
|---|
| 146 | args.pop('__SUBMIT', None) |
|---|
| [16871] | 147 | page = args.pop('__PAGE', None) |
|---|
| 148 | notify_mailto = args.pop('__NOTIFY_MAILTO', None) |
|---|
| 149 | notify_subject = args.pop('__NOTIFY_SUBJECT', None) |
|---|
| 150 | notify_body = args.pop('__NOTIFY_BODY', None) |
|---|
| [7424] | 151 | |
|---|
| [14958] | 152 | if page is None: |
|---|
| 153 | raise HTTPBadRequest('__PAGE is required') |
|---|
| [8369] | 154 | |
|---|
| [14958] | 155 | fields_to_be_stored = {} |
|---|
| [16871] | 156 | checkbox_state = {} |
|---|
| 157 | unprocessed = {} |
|---|
| [8369] | 158 | |
|---|
| [14958] | 159 | # first step : extract hidden fields to find all checkboxes... |
|---|
| [16871] | 160 | for name, value in args.iteritems(): |
|---|
| 161 | m = re.match('^hidden_(.+)$', name) |
|---|
| [8369] | 162 | |
|---|
| [16871] | 163 | if m is not None: |
|---|
| 164 | # there is a checkbutton... |
|---|
| 165 | checkbox_name = m.group(1) |
|---|
| [14958] | 166 | checkbox_state[checkbox_name] = value |
|---|
| 167 | else: |
|---|
| [16871] | 168 | unprocessed[name] = value |
|---|
| [7424] | 169 | |
|---|
| [14958] | 170 | # process checkboxes first (as they have a different logic)... |
|---|
| [16871] | 171 | # an unchecked checkbox has no response => the absence of a |
|---|
| 172 | # response has to be interpreted as 'off'. |
|---|
| 173 | # In addition, even for checkboxes in 'on' state nothing is |
|---|
| 174 | # responded if they're disabled (read-only)... |
|---|
| 175 | for name, state in checkbox_state.iteritems(): |
|---|
| 176 | if state == 'enabled_off': |
|---|
| [14958] | 177 | # checkbox was 'off' at time when form was rendered. |
|---|
| 178 | # => the only possible transition is to 'on' |
|---|
| [16871] | 179 | if name in unprocessed: |
|---|
| [14958] | 180 | # state change ('off' -> 'on') => update database... |
|---|
| [16871] | 181 | fields_to_be_stored[name] = unprocessed[name] |
|---|
| 182 | elif state == 'enabled_on': |
|---|
| [14958] | 183 | # checkbox was 'on' at time when form was rendered. |
|---|
| 184 | # => the only possible transition is to 'off' |
|---|
| [16871] | 185 | if name not in unprocessed: |
|---|
| [14958] | 186 | # interprete no response as 'off'... |
|---|
| 187 | # state change ('on' -> 'off') => update database... |
|---|
| [16871] | 188 | fields_to_be_stored[name] = '' |
|---|
| [7424] | 189 | |
|---|
| [14958] | 190 | # third step : process all non-checkbox fields... |
|---|
| [16871] | 191 | for name, value in unprocessed.iteritems(): |
|---|
| [16879] | 192 | if name not in checkbox_state and \ |
|---|
| 193 | isinstance(value, basestring): |
|---|
| [14958] | 194 | # it's not a checkbox... |
|---|
| [16871] | 195 | # might be compared against current database state to log |
|---|
| 196 | # changes, only... |
|---|
| 197 | fields_to_be_stored[name] = value |
|---|
| [10651] | 198 | |
|---|
| [14958] | 199 | # store all values in database... |
|---|
| [16871] | 200 | db = self.env.get_db_cnx() |
|---|
| [14958] | 201 | authname = req.authname |
|---|
| [16871] | 202 | for name, value in fields_to_be_stored.iteritems(): |
|---|
| 203 | value = re.sub('(\r\n|\r|\n)', '\\\\n', value) |
|---|
| [10651] | 204 | |
|---|
| [16872] | 205 | self.set_tracform_field(db, name, value, authname) |
|---|
| [10651] | 206 | |
|---|
| [14958] | 207 | # set form modification date... |
|---|
| [16872] | 208 | self.set_tracform_field(db, page, '', authname) |
|---|
| [10651] | 209 | |
|---|
| [14958] | 210 | if notify_mailto is not None: |
|---|
| [7424] | 211 | |
|---|
| [16871] | 212 | if self.config.get('notification', 'smtp_enabled'): |
|---|
| 213 | smtp_from = self.config.get('notification', 'smtp_from') |
|---|
| 214 | smtp_to = notify_mailto.split(",") |
|---|
| 215 | smtp_msg = [] |
|---|
| [7424] | 216 | |
|---|
| [14958] | 217 | smtp_msg.append("From: %s" % smtp_from) |
|---|
| 218 | smtp_msg.append("To: %s" % ", ".join(smtp_to)) |
|---|
| 219 | smtp_msg.append("Subject: %s" % notify_subject) |
|---|
| 220 | smtp_msg.append("") |
|---|
| [7424] | 221 | |
|---|
| [14958] | 222 | smtp_msg.append("Hello,") |
|---|
| 223 | smtp_msg.append("") |
|---|
| [16871] | 224 | smtp_msg.append("please note that form '%s' was updated " |
|---|
| 225 | "by user '%s'." % (page, req.authname)) |
|---|
| [7424] | 226 | |
|---|
| [14958] | 227 | if backpath is not None: |
|---|
| 228 | smtp_msg.append("") |
|---|
| [16871] | 229 | smtp_msg.append("Link : %s%s" % ( |
|---|
| 230 | self.config.get('trac', 'base_url'), backpath)) |
|---|
| [7424] | 231 | |
|---|
| [14958] | 232 | smtp_msg.append("") |
|---|
| 233 | smtp_msg.append("Value(s) of field(s) in the form are:") |
|---|
| [7424] | 234 | |
|---|
| [16872] | 235 | rows = self.get_tracform(db) |
|---|
| [7424] | 236 | |
|---|
| [14958] | 237 | regexp = re.compile("%s\/(.*)" % page) |
|---|
| [7424] | 238 | |
|---|
| [14958] | 239 | for row in rows: |
|---|
| 240 | m = regexp.match(row['field']) |
|---|
| 241 | if m: |
|---|
| [16871] | 242 | smtp_msg.append(" %-15s : %s" % |
|---|
| 243 | (m.group(1), row['value'])) |
|---|
| [7424] | 244 | |
|---|
| [14958] | 245 | if notify_body is not None: |
|---|
| 246 | smtp_msg.append("") |
|---|
| 247 | smtp_msg.append("Custom information follows:") |
|---|
| 248 | smtp_msg.append(notify_body) |
|---|
| [7424] | 249 | |
|---|
| [14958] | 250 | smtp_server = smtplib.SMTP('localhost') |
|---|
| [16871] | 251 | smtp_server.sendmail( |
|---|
| 252 | smtp_from, smtp_to, "\r\n".join(smtp_msg)) |
|---|
| [14958] | 253 | smtp_server.quit() |
|---|
| [7424] | 254 | |
|---|
| [14958] | 255 | if backpath is not None: |
|---|
| [16876] | 256 | # req.redirect(backpath) |
|---|
| [14958] | 257 | req.send_response(302) |
|---|
| [16871] | 258 | req.send_header('Content-type', 'text/plain') |
|---|
| 259 | req.send_header('Location', backpath) |
|---|
| [14958] | 260 | req.send_header('Content-Length', 2) |
|---|
| 261 | req.end_headers() |
|---|
| 262 | req.write('OK') |
|---|
| 263 | else: |
|---|
| 264 | req.send_response(200) |
|---|
| 265 | req.send_header('Content-type', 'text/plain') |
|---|
| 266 | req.send_header('Content-Length', 2) |
|---|
| 267 | req.end_headers() |
|---|
| 268 | req.write('OK') |
|---|
| 269 | except Exception, e: |
|---|
| [16875] | 270 | etb = exception_to_unicode(e, traceback=True).encode('utf-8') |
|---|
| [14958] | 271 | req.send_response(500) |
|---|
| 272 | req.send_header('Content-type', 'text/plain') |
|---|
| [16875] | 273 | req.send_header('Content-Length', len(etb)) |
|---|
| [14958] | 274 | req.end_headers() |
|---|
| [16875] | 275 | self.log.warning("Failed processing request for %s: " |
|---|
| 276 | "%s", req.path_info, etb) |
|---|
| 277 | req.write(etb) |
|---|
| [7424] | 278 | |
|---|
| [14958] | 279 | def expand_macro(self, formatter, name, args): |
|---|
| 280 | # set defaults... |
|---|
| [16871] | 281 | page = formatter.req.path_info |
|---|
| [14958] | 282 | context = '' |
|---|
| [16871] | 283 | db = formatter.env.get_db_cnx() |
|---|
| [7424] | 284 | |
|---|
| [14958] | 285 | formatter.req.send_header('Pragma', 'no-cache') |
|---|
| 286 | formatter.req.send_header('Cache-Control', 'no-cache') |
|---|
| 287 | formatter.req.send_header('Cache-Control', 'must-revalidate') |
|---|
| 288 | formatter.req.send_header('Expires', 'Fri, 01 Jan 1999 00:00:00 GMT') |
|---|
| [7424] | 289 | |
|---|
| [14958] | 290 | # parse request... |
|---|
| 291 | unprocessed = args |
|---|
| [16871] | 292 | result = '' |
|---|
| [14958] | 293 | final_html = {} |
|---|
| [16871] | 294 | permission = {'r': True, 'w': True} |
|---|
| [14958] | 295 | permission_alias = {} |
|---|
| [7424] | 296 | |
|---|
| [14958] | 297 | tags = [ |
|---|
| [16871] | 298 | {'start': '<tf>', 'end': '</tf>'}, |
|---|
| 299 | {'start': '<f>', 'end': '</f>'} |
|---|
| 300 | ] |
|---|
| [7424] | 301 | |
|---|
| [16871] | 302 | while unprocessed != '': |
|---|
| [14958] | 303 | # search for start-of-tag... |
|---|
| 304 | start_tag_idx = -1 |
|---|
| 305 | for tag in tags: |
|---|
| 306 | idx = unprocessed.find(tag['start']) |
|---|
| 307 | if (idx >= 0): |
|---|
| [16871] | 308 | if (start_tag_idx == -1 or idx < start_tag_idx): |
|---|
| [14958] | 309 | start_tag_idx = idx |
|---|
| [16871] | 310 | start_tag = tag['start'] |
|---|
| 311 | end_tag = tag['end'] |
|---|
| [7424] | 312 | |
|---|
| [16871] | 313 | if start_tag_idx >= 0: |
|---|
| [14958] | 314 | # start-tag found... |
|---|
| 315 | # search for end-tag... |
|---|
| 316 | end_tag_idx = unprocessed.find(end_tag) |
|---|
| [10651] | 317 | |
|---|
| [16871] | 318 | if end_tag_idx >= 0: |
|---|
| [14958] | 319 | # start-tag and end-tag found... |
|---|
| [16871] | 320 | if permission['r']: |
|---|
| 321 | # part before start-tag... |
|---|
| 322 | result += unprocessed[0: start_tag_idx] |
|---|
| 323 | # part between start- and end-tag... |
|---|
| 324 | tag = unprocessed[start_tag_idx + |
|---|
| 325 | len(start_tag): end_tag_idx] |
|---|
| 326 | # part including start- and end-tag... |
|---|
| 327 | full_tag = unprocessed[ |
|---|
| 328 | start_tag_idx: end_tag_idx + len(end_tag)] |
|---|
| 329 | # part after end-tag... |
|---|
| 330 | unprocessed = unprocessed[end_tag_idx + len(end_tag):] |
|---|
| [10651] | 331 | |
|---|
| [16871] | 332 | tag = re.sub('#[^\n\f]*', '', tag) # strip comments... |
|---|
| [7424] | 333 | |
|---|
| [16871] | 334 | command, options = wikiforms_lib.get_piece(tag) |
|---|
| [7424] | 335 | |
|---|
| [16871] | 336 | if command == 'context': |
|---|
| [14958] | 337 | # set context to... |
|---|
| [16871] | 338 | context, ignored = wikiforms_lib.get_piece(options) |
|---|
| 339 | elif command == 'value': |
|---|
| [14958] | 340 | # get value of... |
|---|
| [16871] | 341 | name, ignored = wikiforms_lib.get_piece(options) |
|---|
| 342 | resolved_name = self.resolve_name(page, context, name) |
|---|
| [7424] | 343 | |
|---|
| [16871] | 344 | db = formatter.env.get_db_cnx() |
|---|
| [16872] | 345 | entry = self.get_tracform_field(db, resolved_name) |
|---|
| [16871] | 346 | if permission['r']: |
|---|
| 347 | result += "%s" % entry['value'] |
|---|
| 348 | elif command == 'permission': |
|---|
| [14958] | 349 | # get/set permission... |
|---|
| [16871] | 350 | sub_command, remainder = \ |
|---|
| 351 | wikiforms_lib.get_piece(options, [':']) |
|---|
| [7424] | 352 | |
|---|
| [16871] | 353 | if sub_command == 'alias': |
|---|
| 354 | alias_name, ignored = \ |
|---|
| 355 | wikiforms_lib.get_piece(remainder, [' ']) |
|---|
| [7424] | 356 | |
|---|
| [16871] | 357 | if alias_name in permission_alias: |
|---|
| 358 | # fetch already defined permission setup... |
|---|
| 359 | permission['r'] = \ |
|---|
| 360 | permission_alias[alias_name]['r'] |
|---|
| 361 | permission['w'] = \ |
|---|
| 362 | permission_alias[alias_name]['w'] |
|---|
| [14958] | 363 | else: |
|---|
| 364 | # create alias for current permission setup... |
|---|
| [16871] | 365 | permission_alias[alias_name] = { |
|---|
| 366 | 'r': permission['r'], |
|---|
| 367 | 'w': permission['w'] |
|---|
| 368 | } |
|---|
| 369 | elif sub_command == 'show': |
|---|
| [14958] | 370 | result += 'current permission is (' |
|---|
| [16871] | 371 | if permission['r']: |
|---|
| [14958] | 372 | result += 'r' |
|---|
| [7424] | 373 | |
|---|
| [16871] | 374 | if permission['w']: |
|---|
| [14958] | 375 | result += 'w' |
|---|
| [7424] | 376 | |
|---|
| [14958] | 377 | result += ')' |
|---|
| [16871] | 378 | elif sub_command == 'change': |
|---|
| 379 | permission_action, permission_condition = \ |
|---|
| 380 | wikiforms_lib.get_piece(remainder, [':']) |
|---|
| [7424] | 381 | |
|---|
| [16871] | 382 | if permission_condition != '': |
|---|
| 383 | condition, msg = \ |
|---|
| 384 | self.resolve_permission(permission_condition, formatter) |
|---|
| [7424] | 385 | |
|---|
| [16871] | 386 | if msg != '': |
|---|
| [14958] | 387 | return system_message(msg) |
|---|
| 388 | else: |
|---|
| 389 | condition = True |
|---|
| [10651] | 390 | |
|---|
| [16871] | 391 | if condition: |
|---|
| 392 | if permission_action in \ |
|---|
| 393 | ['r', 'rw', '+r', '+rw', '+r-w', '+r+w']: |
|---|
| [14958] | 394 | permission['r'] = True |
|---|
| [16871] | 395 | elif permission_action in \ |
|---|
| 396 | ['', 'w', '-r', '-rw', '-r-w', '-r+w']: |
|---|
| [14958] | 397 | permission['r'] = False |
|---|
| [16871] | 398 | if permission_action in \ |
|---|
| 399 | ['w', 'rw', '+w', '+rw', '-r+w', '+r+w']: |
|---|
| [14958] | 400 | permission['w'] = True |
|---|
| [16871] | 401 | elif permission_action in \ |
|---|
| 402 | ['', 'r', '-w', '-rw', '+r-w', '-r-w']: |
|---|
| [14958] | 403 | permission['w'] = False |
|---|
| 404 | else: |
|---|
| [16871] | 405 | return system_message("unknown sub-command '%s' " |
|---|
| 406 | "of command '%s'" |
|---|
| 407 | % (sub_command, command)) |
|---|
| 408 | |
|---|
| 409 | elif command == 'values': |
|---|
| [14958] | 410 | # get value of... |
|---|
| [16871] | 411 | local_context, parameters = \ |
|---|
| 412 | wikiforms_lib.get_piece(options) |
|---|
| [7424] | 413 | |
|---|
| [16871] | 414 | while (parameters != ''): |
|---|
| 415 | m = re.match('(.*?)<(\S+?)>(.*)$', parameters) |
|---|
| [14958] | 416 | if (m is not None): |
|---|
| [16871] | 417 | if permission['r']: |
|---|
| 418 | result += m.group(1) |
|---|
| 419 | name = m.group(2) |
|---|
| 420 | parameters = m.group(3) |
|---|
| [7424] | 421 | |
|---|
| [16871] | 422 | resolved_name = self.resolve_name( |
|---|
| 423 | page, local_context, name) |
|---|
| 424 | db = formatter.env.get_db_cnx() |
|---|
| [16872] | 425 | entry = \ |
|---|
| 426 | self.get_tracform_field(db, resolved_name) |
|---|
| [16871] | 427 | if permission['r']: |
|---|
| 428 | result += "%s" % entry['value'] |
|---|
| [14958] | 429 | else: |
|---|
| [16871] | 430 | if permission['r']: |
|---|
| 431 | result += parameters |
|---|
| 432 | parameters = '' |
|---|
| 433 | |
|---|
| 434 | elif command == 'who': |
|---|
| [14958] | 435 | # get updated_by of... |
|---|
| [16871] | 436 | name, ignored = wikiforms_lib.get_piece(options) |
|---|
| [7424] | 437 | |
|---|
| [16871] | 438 | resolved_name = self.resolve_name(page, context, name) |
|---|
| 439 | db = formatter.env.get_db_cnx() |
|---|
| [16872] | 440 | entry = self.get_tracform_field(db, resolved_name) |
|---|
| [16871] | 441 | if permission['r']: |
|---|
| 442 | result += "%s" % entry['updated_by'] |
|---|
| 443 | |
|---|
| 444 | elif command == 'when': |
|---|
| [14958] | 445 | # get updated_on of... |
|---|
| [16871] | 446 | name, ignored = wikiforms_lib.get_piece(options) |
|---|
| [7424] | 447 | |
|---|
| [16871] | 448 | resolved_name = self.resolve_name(page, context, name) |
|---|
| 449 | db = formatter.env.get_db_cnx() |
|---|
| [16872] | 450 | entry = self.get_tracform_field(db, resolved_name) |
|---|
| [16871] | 451 | if permission['r']: |
|---|
| 452 | result += "%s" \ |
|---|
| 453 | % self.to_timestring(entry['updated_on']) |
|---|
| 454 | |
|---|
| 455 | elif command == 'when2': |
|---|
| [14958] | 456 | # get updated_on of... |
|---|
| [16871] | 457 | name, ignored = wikiforms_lib.get_piece(options) |
|---|
| [7424] | 458 | |
|---|
| [16871] | 459 | resolved_name = self.resolve_name(page, context, name) |
|---|
| 460 | db = formatter.env.get_db_cnx() |
|---|
| [16872] | 461 | entry = self.get_tracform_field(db, resolved_name) |
|---|
| [7424] | 462 | |
|---|
| [16871] | 463 | if permission['r']: |
|---|
| 464 | if entry['field'] is not None: |
|---|
| 465 | last_modified = \ |
|---|
| 466 | datetime.fromtimestamp(entry['updated_on'], |
|---|
| 467 | utc) |
|---|
| 468 | now = datetime.now(utc) |
|---|
| 469 | pretty_delta = \ |
|---|
| 470 | pretty_timedelta(now, last_modified) |
|---|
| [14958] | 471 | else: |
|---|
| [16871] | 472 | pretty_delta = 'unset-time' |
|---|
| 473 | result += "%s, %s ago" \ |
|---|
| 474 | % (self.to_timestring(entry['updated_on']), |
|---|
| 475 | pretty_delta) |
|---|
| 476 | |
|---|
| 477 | elif command == 'lastmodified': |
|---|
| [14958] | 478 | # get updated_on,updated_by of... |
|---|
| [16871] | 479 | name, ignored = wikiforms_lib.get_piece(options) |
|---|
| [7424] | 480 | |
|---|
| [16871] | 481 | resolved_name = self.resolve_name(page, context, name) |
|---|
| 482 | db = formatter.env.get_db_cnx() |
|---|
| [16872] | 483 | entry = self.get_tracform_field(db, resolved_name) |
|---|
| [7424] | 484 | |
|---|
| [14958] | 485 | now = datetime.now(utc) |
|---|
| [7424] | 486 | |
|---|
| [14959] | 487 | req = formatter.req |
|---|
| [14958] | 488 | if (entry['field'] is not None): |
|---|
| [14959] | 489 | last_modified = \ |
|---|
| [16871] | 490 | datetime.fromtimestamp( |
|---|
| 491 | entry['updated_on'], utc) |
|---|
| [14959] | 492 | pretty_delta = pretty_timedelta(now, last_modified) |
|---|
| 493 | time_string = format_datetime(last_modified, |
|---|
| 494 | '%a %b %d %T %Y %Z', |
|---|
| 495 | req.tz, req.locale) |
|---|
| [14958] | 496 | else: |
|---|
| [16871] | 497 | time_string = self.to_timestring( |
|---|
| 498 | entry['updated_on']) |
|---|
| 499 | pretty_delta = 'unset-time' |
|---|
| [8369] | 500 | |
|---|
| [16871] | 501 | if permission['r']: |
|---|
| 502 | result += "'''Last Modified:''' %s (%s ago) " \ |
|---|
| 503 | "by %s" % (time_string, pretty_delta, |
|---|
| 504 | entry['updated_by']) |
|---|
| 505 | |
|---|
| 506 | elif command == 'set': |
|---|
| [14958] | 507 | # set value of... |
|---|
| [16871] | 508 | name, value = wikiforms_lib.get_piece(options) |
|---|
| 509 | resolved_name = self.resolve_name(page, context, name) |
|---|
| 510 | authname = formatter.req.authname |
|---|
| 511 | db = formatter.env.get_db_cnx() |
|---|
| [16872] | 512 | self.set_tracform_field(db, resolved_name, value, |
|---|
| 513 | authname) |
|---|
| [8369] | 514 | |
|---|
| [16871] | 515 | elif command == 'dump': |
|---|
| [14958] | 516 | # dump fields... |
|---|
| [16871] | 517 | name, ignored = wikiforms_lib.get_piece(options) |
|---|
| 518 | db = formatter.env.get_db_cnx() |
|---|
| [16872] | 519 | rows = self.get_tracform(db) |
|---|
| [8369] | 520 | |
|---|
| [16871] | 521 | if permission['r']: |
|---|
| [14958] | 522 | result += "||'''field'''||'''value'''||'''who'''||'''when'''\n" |
|---|
| 523 | for row in rows: |
|---|
| [16871] | 524 | m = re.search(name, row['field']) |
|---|
| [14958] | 525 | if m: |
|---|
| [16871] | 526 | if permission['r']: |
|---|
| 527 | result += "||%s||%s||%s||%s\n" \ |
|---|
| 528 | % (row['field'], |
|---|
| 529 | re.sub('\n', '\\\\n', |
|---|
| 530 | row['value']), |
|---|
| 531 | row['updated_by'], |
|---|
| 532 | row['updated_on']) |
|---|
| 533 | |
|---|
| 534 | elif command == 'delete': |
|---|
| [14958] | 535 | # delete a field... |
|---|
| [16871] | 536 | formatter.req.perm.require('WIKIFORMS_ADMIN') |
|---|
| 537 | name, ignored = wikiforms_lib.get_piece(options) |
|---|
| 538 | resolved_name = self.resolve_name(page, context, name) |
|---|
| 539 | db = formatter.env.get_db_cnx() |
|---|
| [16872] | 540 | self.delete_tracform_field(db, resolved_name) |
|---|
| [8369] | 541 | |
|---|
| [16871] | 542 | elif command == 'checkbox': |
|---|
| 543 | # create checkbox... |
|---|
| 544 | name, parameters = wikiforms_lib.get_piece(options) |
|---|
| 545 | resolved_name = self.resolve_name(page, context, name) |
|---|
| [8369] | 546 | |
|---|
| [16871] | 547 | placeholder_id = self.get_placeholder_id() |
|---|
| 548 | result += placeholder_id |
|---|
| [7424] | 549 | |
|---|
| [16871] | 550 | final_html[placeholder_id] = \ |
|---|
| 551 | self.create_checkbox(db, name, resolved_name, |
|---|
| 552 | parameters, placeholder_id, |
|---|
| 553 | permission) |
|---|
| [7424] | 554 | |
|---|
| [16871] | 555 | elif command == 'radio': |
|---|
| [14958] | 556 | # create radio... |
|---|
| [16871] | 557 | name, parameters = wikiforms_lib.get_piece(options) |
|---|
| 558 | resolved_name = self.resolve_name(page, context, name) |
|---|
| [7424] | 559 | |
|---|
| [16871] | 560 | placeholder_id = self.get_placeholder_id() |
|---|
| 561 | result += placeholder_id |
|---|
| [7424] | 562 | |
|---|
| [16871] | 563 | final_html[placeholder_id] = \ |
|---|
| 564 | self.create_radio(db, name, resolved_name, |
|---|
| 565 | parameters, placeholder_id, |
|---|
| 566 | permission) |
|---|
| 567 | |
|---|
| 568 | elif command == 'input': |
|---|
| [14958] | 569 | # create input... |
|---|
| [16871] | 570 | name, parameters = wikiforms_lib.get_piece(options) |
|---|
| 571 | resolved_name = self.resolve_name(page, context, name) |
|---|
| [7424] | 572 | |
|---|
| [16871] | 573 | placeholder_id = self.get_placeholder_id() |
|---|
| 574 | result += placeholder_id |
|---|
| [7424] | 575 | |
|---|
| [16871] | 576 | final_html[placeholder_id] = \ |
|---|
| 577 | self.create_input(db, name, resolved_name, |
|---|
| 578 | parameters, placeholder_id, |
|---|
| 579 | permission) |
|---|
| 580 | |
|---|
| 581 | elif command == 'textarea': |
|---|
| [14958] | 582 | # create text... |
|---|
| [16871] | 583 | name, parameters = wikiforms_lib.get_piece(options) |
|---|
| 584 | resolved_name = self.resolve_name(page, context, name) |
|---|
| [7424] | 585 | |
|---|
| [16871] | 586 | placeholder_id = self.get_placeholder_id() |
|---|
| 587 | result += placeholder_id |
|---|
| [7424] | 588 | |
|---|
| [16871] | 589 | final_html[placeholder_id] = \ |
|---|
| 590 | self.create_textarea(db, name, resolved_name, |
|---|
| 591 | parameters, placeholder_id, |
|---|
| 592 | permission) |
|---|
| 593 | |
|---|
| 594 | elif command == 'select': |
|---|
| [14958] | 595 | # create select... |
|---|
| [16871] | 596 | name, parameters = wikiforms_lib.get_piece(options) |
|---|
| 597 | resolved_name = self.resolve_name(page, context, name) |
|---|
| [7424] | 598 | |
|---|
| [16871] | 599 | placeholder_id = self.get_placeholder_id() |
|---|
| 600 | result += placeholder_id |
|---|
| [7424] | 601 | |
|---|
| [16871] | 602 | final_html[placeholder_id] = \ |
|---|
| 603 | self.create_select(db, name, resolved_name, |
|---|
| 604 | parameters, placeholder_id, |
|---|
| 605 | permission) |
|---|
| 606 | |
|---|
| 607 | elif command == 'notify': |
|---|
| [14958] | 608 | # create notify... |
|---|
| [16871] | 609 | resolved_name = self.resolve_name(page, context, '') |
|---|
| [7424] | 610 | |
|---|
| [16871] | 611 | placeholder_id = self.get_placeholder_id() |
|---|
| 612 | result += placeholder_id |
|---|
| [7424] | 613 | |
|---|
| [16871] | 614 | final_html[placeholder_id] = \ |
|---|
| 615 | self.create_notify(db, '', resolved_name, |
|---|
| 616 | options, placeholder_id) |
|---|
| 617 | |
|---|
| 618 | elif command == 'submit': |
|---|
| [14958] | 619 | # create button... |
|---|
| [7424] | 620 | |
|---|
| [16871] | 621 | placeholder_id = self.get_placeholder_id() |
|---|
| 622 | result += placeholder_id |
|---|
| 623 | resolved_name = self.resolve_name(page, context, name) |
|---|
| [7424] | 624 | |
|---|
| [16871] | 625 | final_html[placeholder_id] = \ |
|---|
| 626 | self.create_submit(name, resolved_name, options, |
|---|
| 627 | placeholder_id, permission) |
|---|
| [14958] | 628 | else: |
|---|
| [16871] | 629 | # unknown command => echo original description |
|---|
| 630 | # including tags around... |
|---|
| 631 | if permission['r']: |
|---|
| [14958] | 632 | result += full_tag |
|---|
| 633 | else: |
|---|
| 634 | # start-tag but no end-tag found... |
|---|
| [16871] | 635 | if permission['r']: |
|---|
| [14958] | 636 | result += unprocessed |
|---|
| [16871] | 637 | unprocessed = '' |
|---|
| [7424] | 638 | |
|---|
| [14958] | 639 | else: |
|---|
| 640 | # no start-tag found... |
|---|
| [16871] | 641 | if permission['r']: |
|---|
| [14958] | 642 | result += unprocessed |
|---|
| [16871] | 643 | unprocessed = '' |
|---|
| [7424] | 644 | |
|---|
| [14958] | 645 | # wikify structure of document... |
|---|
| [16871] | 646 | result = self.wiki_to_html(formatter, result) |
|---|
| [7424] | 647 | |
|---|
| [14958] | 648 | # fill in final html for placeholders... |
|---|
| [16871] | 649 | for placeholder_id, placeholder_value in final_html.iteritems(): |
|---|
| 650 | result = re.sub(placeholder_id, placeholder_value, result, 1) |
|---|
| [7424] | 651 | |
|---|
| [16871] | 652 | return ''.join(self.build_form(formatter, page, result)) |
|---|
| [7424] | 653 | |
|---|
| [16871] | 654 | def create_checkbox(self, db, name, resolved_name, parameters, |
|---|
| 655 | placeholder_id, permission): |
|---|
| [14958] | 656 | # create checkbox... |
|---|
| [16871] | 657 | result = '' |
|---|
| 658 | checkbox_def = { |
|---|
| 659 | 'cfg': { |
|---|
| 660 | 'name': resolved_name, |
|---|
| 661 | 'checked': False, |
|---|
| 662 | 'value': 'true', |
|---|
| 663 | 'class': 'checkbox_css_class', |
|---|
| 664 | 'id': 'checkbox_css_id', |
|---|
| 665 | 'debug': False |
|---|
| 666 | }, |
|---|
| 667 | 'xtras': [], |
|---|
| 668 | 'xtra': {}, |
|---|
| 669 | } |
|---|
| [7424] | 670 | |
|---|
| [14958] | 671 | # ...overwrite hardcoded defaults with user-defined values... |
|---|
| [16871] | 672 | checkbox_def = wikiforms_lib.parse_options(parameters, checkbox_def) |
|---|
| [7424] | 673 | |
|---|
| [14958] | 674 | # fetch state from database... |
|---|
| [16872] | 675 | entry = self.get_tracform_field(db, resolved_name) |
|---|
| [7424] | 676 | |
|---|
| [14958] | 677 | if (entry['field'] is not None): |
|---|
| 678 | # derive checked-state from database... |
|---|
| [16871] | 679 | checkbox_def['cfg']['checked'] = ( |
|---|
| 680 | entry['value'] == checkbox_def['cfg']['value']) |
|---|
| [14958] | 681 | else: |
|---|
| [16871] | 682 | checkbox_def['cfg']['checked'] = self.to_boolean( |
|---|
| 683 | checkbox_def['cfg']['checked']) |
|---|
| [7424] | 684 | |
|---|
| [16871] | 685 | if checkbox_def['cfg']['debug']: |
|---|
| 686 | result += "debug: parameters=>%s< name=>%s<>%s< cfg=>%s< xtras=>%s< xtra=>%s< db=>%s< perm=>%s<" \ |
|---|
| 687 | % (parameters, |
|---|
| 688 | name, resolved_name, |
|---|
| 689 | str(checkbox_def['cfg']), |
|---|
| 690 | str(checkbox_def['xtras']), |
|---|
| 691 | str(checkbox_def['xtra']), |
|---|
| 692 | str(entry), permission) |
|---|
| [7424] | 693 | |
|---|
| [14958] | 694 | # map flag to html needs... |
|---|
| 695 | hidden_value = "" |
|---|
| [7424] | 696 | |
|---|
| [16871] | 697 | if not permission['w']: |
|---|
| 698 | access_flag = 'DISABLED' |
|---|
| [14958] | 699 | hidden_value = 'disabled' |
|---|
| 700 | else: |
|---|
| [16871] | 701 | access_flag = '' |
|---|
| [14958] | 702 | hidden_value = 'enabled' |
|---|
| [10651] | 703 | |
|---|
| [16871] | 704 | if checkbox_def['cfg']['checked']: |
|---|
| 705 | checkbox_def['cfg']['checked'] = 'checked="checked"' |
|---|
| 706 | hidden_value += '_on' |
|---|
| [14958] | 707 | else: |
|---|
| [16871] | 708 | checkbox_def['cfg']['checked'] = '' |
|---|
| 709 | hidden_value += '_off' |
|---|
| [10651] | 710 | |
|---|
| [14958] | 711 | # when submitting the form, checked checkboxes are transmitted, only. |
|---|
| 712 | # => the update-processor will not know about unchecked ones. |
|---|
| 713 | # => send a hidden field for all checkboxes to allow to find those. |
|---|
| [16871] | 714 | if permission['r']: |
|---|
| [14958] | 715 | result += """ |
|---|
| [16871] | 716 | <INPUT type='checkbox' name='%s' id='%s' class='%s' value='%s' %s %s> |
|---|
| 717 | """ % (checkbox_def['cfg']['name' ], |
|---|
| 718 | checkbox_def['cfg']['id'], |
|---|
| 719 | checkbox_def['cfg']['class'], |
|---|
| 720 | checkbox_def['cfg']['value'], |
|---|
| 721 | checkbox_def['cfg']['checked'], |
|---|
| 722 | access_flag) |
|---|
| [10651] | 723 | |
|---|
| [14958] | 724 | result += """ |
|---|
| [16871] | 725 | <INPUT type="hidden" name='hidden_%s' value='%s'> |
|---|
| 726 | """ % (checkbox_def['cfg']['name'], hidden_value) |
|---|
| [10651] | 727 | |
|---|
| [14958] | 728 | return result |
|---|
| [7424] | 729 | |
|---|
| [16871] | 730 | def create_radio(self, db, name, resolved_name, parameters, placeholder_id, |
|---|
| 731 | permission): |
|---|
| [14958] | 732 | # create radio... |
|---|
| [16871] | 733 | result = '' |
|---|
| 734 | radio_def = { |
|---|
| 735 | 'cfg': { |
|---|
| 736 | 'name': resolved_name, |
|---|
| 737 | 'checked': False, |
|---|
| 738 | 'value': 'true', |
|---|
| 739 | 'class': 'radio_css_class', |
|---|
| 740 | 'id': 'radio_css_id', |
|---|
| 741 | 'debug': False |
|---|
| 742 | }, |
|---|
| 743 | 'xtras': [], |
|---|
| 744 | 'xtra': {}, |
|---|
| 745 | } |
|---|
| [7424] | 746 | |
|---|
| [14958] | 747 | # ...overwrite hardcoded defaults with user-defined values... |
|---|
| [16871] | 748 | radio_def = wikiforms_lib.parse_options(parameters, radio_def) |
|---|
| [7424] | 749 | |
|---|
| [14958] | 750 | # fetch state from database... |
|---|
| [16872] | 751 | entry = self.get_tracform_field(db, resolved_name) |
|---|
| [7424] | 752 | |
|---|
| [16871] | 753 | if entry['field'] is not None: |
|---|
| [14958] | 754 | # derive checked-state from database... |
|---|
| [16871] | 755 | radio_def['cfg']['checked'] = ( |
|---|
| 756 | entry['value'] == radio_def['cfg']['value']) |
|---|
| [14958] | 757 | else: |
|---|
| [16871] | 758 | radio_def['cfg']['checked'] = self.to_boolean( |
|---|
| 759 | radio_def['cfg']['checked']) |
|---|
| [7424] | 760 | |
|---|
| [14958] | 761 | if (radio_def['cfg']['debug']): |
|---|
| [16871] | 762 | result += "debug: parameters=>%s< name=>%s<>%s< cfg=>%s< xtras=>%s< xtra=>%s< db=>%s< perm=>%s<" \ |
|---|
| 763 | % (parameters, |
|---|
| 764 | name, resolved_name, |
|---|
| 765 | str(radio_def['cfg']), |
|---|
| 766 | str(radio_def['xtras']), |
|---|
| 767 | str(radio_def['xtra']), |
|---|
| 768 | str(entry), permission) |
|---|
| [7424] | 769 | |
|---|
| [14958] | 770 | # map flag to html needs... |
|---|
| [16871] | 771 | if radio_def['cfg']['checked']: |
|---|
| [14958] | 772 | radio_def['cfg']['checked'] = 'checked="checked"' |
|---|
| 773 | else: |
|---|
| 774 | radio_def['cfg']['checked'] = '' |
|---|
| [7424] | 775 | |
|---|
| [16871] | 776 | if not permission['w']: |
|---|
| [14958] | 777 | access_flag = 'DISABLED' |
|---|
| 778 | else: |
|---|
| 779 | access_flag = '' |
|---|
| [7424] | 780 | |
|---|
| [16871] | 781 | if permission['r']: |
|---|
| [14958] | 782 | result += """ |
|---|
| [16871] | 783 | <INPUT type='radio' name='%s' id='%s' class='%s' value='%s' %s %s > |
|---|
| 784 | """ % (radio_def['cfg']['name'], |
|---|
| 785 | radio_def['cfg']['id'], |
|---|
| 786 | radio_def['cfg']['class'], |
|---|
| 787 | radio_def['cfg']['value'], |
|---|
| 788 | radio_def['cfg']['checked'], |
|---|
| 789 | access_flag) |
|---|
| [14958] | 790 | return result |
|---|
| [7424] | 791 | |
|---|
| [16871] | 792 | def create_input(self, db, name, resolved_name, parameters, placeholder_id, |
|---|
| 793 | permission): |
|---|
| [14958] | 794 | # create input... |
|---|
| [16871] | 795 | result = '' |
|---|
| 796 | input_def = { |
|---|
| 797 | 'cfg': { |
|---|
| 798 | 'name': resolved_name, |
|---|
| 799 | 'value': '', |
|---|
| 800 | 'size': 22, |
|---|
| 801 | 'class': 'input_css_class', |
|---|
| 802 | 'id': 'input_css_id', |
|---|
| 803 | 'debug': False, |
|---|
| 804 | }, |
|---|
| 805 | 'xtras': [], |
|---|
| 806 | 'xtra': {}, |
|---|
| 807 | } |
|---|
| [7424] | 808 | |
|---|
| [14958] | 809 | # ...overwrite hardcoded defaults with user-defined values... |
|---|
| [16871] | 810 | input_def = wikiforms_lib.parse_options(parameters, input_def) |
|---|
| [7424] | 811 | |
|---|
| [14958] | 812 | # fetch state from database... |
|---|
| [16872] | 813 | entry = self.get_tracform_field(db, resolved_name) |
|---|
| [7424] | 814 | |
|---|
| [16871] | 815 | if input_def['cfg']['debug']: |
|---|
| 816 | result += "debug: parameters=>%s< name=>%s<>%s< cfg=>%s< xtras=>%s< xtra=>%s< db=>%s< perm=>%s<" \ |
|---|
| 817 | % (parameters, |
|---|
| 818 | name, resolved_name, |
|---|
| 819 | str(input_def['cfg']), |
|---|
| 820 | str(input_def['xtras']), |
|---|
| 821 | str(input_def['xtra']), |
|---|
| 822 | str(entry), permission) |
|---|
| [7424] | 823 | |
|---|
| [16871] | 824 | if entry['field'] is not None: |
|---|
| 825 | # ...overwrite hardcoded/user-defined default with database value. |
|---|
| [14958] | 826 | input_def['cfg']['value'] = entry['value'] |
|---|
| [7424] | 827 | |
|---|
| [16871] | 828 | if not permission['w']: |
|---|
| [14958] | 829 | access_flag = 'DISABLED' |
|---|
| 830 | else: |
|---|
| 831 | access_flag = '' |
|---|
| [7424] | 832 | |
|---|
| [16871] | 833 | if permission['r']: |
|---|
| [14958] | 834 | result += """ |
|---|
| [16871] | 835 | <INPUT name='%s' id='%s' class='%s' value='%s' size=%s %s > |
|---|
| 836 | """ % (input_def['cfg']['name'], |
|---|
| 837 | input_def['cfg']['id'], |
|---|
| 838 | input_def['cfg']['class'], |
|---|
| 839 | self.to_quote(input_def['cfg']['value']), |
|---|
| 840 | input_def['cfg']['size'], |
|---|
| 841 | access_flag) |
|---|
| [14958] | 842 | return result |
|---|
| [7424] | 843 | |
|---|
| [16871] | 844 | def create_textarea(self, db, name, resolved_name, parameters, |
|---|
| 845 | placeholder_id, permission): |
|---|
| [14958] | 846 | # create text... |
|---|
| [16871] | 847 | result = '' |
|---|
| 848 | text_def = { |
|---|
| 849 | 'cfg': { |
|---|
| 850 | 'name': resolved_name, |
|---|
| 851 | 'cols': 10, |
|---|
| 852 | 'rows': 2, |
|---|
| 853 | 'value': '', |
|---|
| 854 | 'class': 'text_css_class', |
|---|
| 855 | 'id': 'text_css_id', |
|---|
| 856 | 'debug': False |
|---|
| 857 | }, |
|---|
| 858 | 'xtras': [], |
|---|
| 859 | 'xtra': {} |
|---|
| 860 | } |
|---|
| [7424] | 861 | |
|---|
| [14958] | 862 | # ...overwrite hardcoded defaults with user-defined values... |
|---|
| [16871] | 863 | text_def = wikiforms_lib.parse_options(parameters, text_def) |
|---|
| [7424] | 864 | |
|---|
| [14958] | 865 | # fetch state from database... |
|---|
| [16872] | 866 | entry = self.get_tracform_field(db, resolved_name) |
|---|
| [7424] | 867 | |
|---|
| [16871] | 868 | if text_def['cfg']['debug']: |
|---|
| 869 | result += "debug: parameters=>%s< name=>%s<>%s< cfg=>%s< xtras=>%s< xtra=>%s< db=>%s< perm=>%s<" \ |
|---|
| 870 | % (parameters, |
|---|
| 871 | name, resolved_name, |
|---|
| 872 | str(text_def['cfg']), |
|---|
| 873 | str(text_def['xtras']), |
|---|
| 874 | str(text_def['xtra']), |
|---|
| 875 | str(entry), permission) |
|---|
| [7424] | 876 | |
|---|
| [16871] | 877 | if entry['field'] is not None: |
|---|
| 878 | # ...overwrite hardcoded/user-defined default with database value. |
|---|
| [14958] | 879 | text_def['cfg']['value'] = entry['value'] |
|---|
| [7424] | 880 | |
|---|
| [16871] | 881 | if not permission['w']: |
|---|
| [14958] | 882 | access_flag = 'DISABLED' |
|---|
| 883 | else: |
|---|
| 884 | access_flag = '' |
|---|
| [7424] | 885 | |
|---|
| [16871] | 886 | if permission['r']: |
|---|
| [14958] | 887 | result += """ |
|---|
| [16871] | 888 | <TEXTAREA name='%s' id='%s' class='%s' cols='%s' rows='%s' %s >%s</TEXTAREA> |
|---|
| 889 | """ % (text_def['cfg']['name' ], |
|---|
| 890 | text_def['cfg']['id'], |
|---|
| 891 | text_def['cfg']['class'], |
|---|
| 892 | text_def['cfg']['cols'], |
|---|
| 893 | text_def['cfg']['rows'], |
|---|
| 894 | access_flag, |
|---|
| 895 | escape(text_def['cfg']['value'])) |
|---|
| [14958] | 896 | return result |
|---|
| [7424] | 897 | |
|---|
| [16871] | 898 | def create_select(self, db, name, resolved_name, parameters, |
|---|
| 899 | placeholder_id, permission): |
|---|
| [14958] | 900 | # create select... |
|---|
| 901 | result = '' |
|---|
| [16871] | 902 | select_def = { |
|---|
| 903 | 'cfg': { |
|---|
| 904 | 'name': resolved_name, |
|---|
| 905 | 'default': None, |
|---|
| 906 | 'class': 'select_css_class', |
|---|
| 907 | 'id': 'select_css_id', |
|---|
| 908 | 'debug': False |
|---|
| 909 | }, |
|---|
| 910 | 'xtras': [], |
|---|
| 911 | 'xtra': {} |
|---|
| 912 | } |
|---|
| [7424] | 913 | |
|---|
| [14958] | 914 | # ...overwrite hardcoded defaults with user-defined values... |
|---|
| [16871] | 915 | select_def = wikiforms_lib.parse_options(parameters, select_def) |
|---|
| [7424] | 916 | |
|---|
| [14958] | 917 | # fetch state from database... |
|---|
| [16872] | 918 | entry = self.get_tracform_field(db, resolved_name) |
|---|
| [7424] | 919 | |
|---|
| [14958] | 920 | if (select_def['cfg']['debug']): |
|---|
| [16871] | 921 | result += "debug: parameters=>%s< name=>%s<>%s< cfg=>%s< xtras=>%s< xtra=>%s< db=>%s< perm=>%s<" \ |
|---|
| 922 | % (parameters, |
|---|
| 923 | name, resolved_name, |
|---|
| 924 | str(select_def['cfg']), |
|---|
| 925 | str(select_def['xtras']), |
|---|
| 926 | str(select_def['xtra']), |
|---|
| 927 | str(entry), permission) |
|---|
| [7424] | 928 | |
|---|
| [16871] | 929 | if not permission['w']: |
|---|
| [14958] | 930 | access_flag = 'DISABLED' |
|---|
| 931 | else: |
|---|
| 932 | access_flag = '' |
|---|
| [7424] | 933 | |
|---|
| [14958] | 934 | option_section = '' |
|---|
| 935 | for option in select_def['xtras']: |
|---|
| [16871] | 936 | if select_def['xtra'][option] == '': |
|---|
| [14958] | 937 | value = option |
|---|
| 938 | label = option |
|---|
| 939 | else: |
|---|
| 940 | value = option |
|---|
| 941 | label = select_def['xtra'][option] |
|---|
| [8225] | 942 | |
|---|
| [14958] | 943 | selected = False |
|---|
| [8225] | 944 | |
|---|
| [16871] | 945 | if select_def['cfg']['default'] is not None: |
|---|
| [14958] | 946 | selected = (value == select_def['cfg']['default']) |
|---|
| [7424] | 947 | |
|---|
| [16871] | 948 | if entry['field'] is not None: |
|---|
| 949 | selected = value == entry['value'] |
|---|
| [8190] | 950 | |
|---|
| [14958] | 951 | # map flag to html needs... |
|---|
| [16871] | 952 | if selected: |
|---|
| [14958] | 953 | selected = 'selected' |
|---|
| 954 | else: |
|---|
| 955 | selected = '' |
|---|
| [8225] | 956 | |
|---|
| [14958] | 957 | option_section += """ |
|---|
| [16871] | 958 | <OPTION value='%s' %s>%s</OPTION> |
|---|
| 959 | """ % (self.to_quote(value), selected, label) |
|---|
| [8225] | 960 | |
|---|
| [16871] | 961 | if permission['r']: |
|---|
| [14958] | 962 | result += """ |
|---|
| [16871] | 963 | <SELECT name='%s' id='%s' class='%s' %s>%s</SELECT> |
|---|
| 964 | """ % (select_def['cfg']['name'], |
|---|
| 965 | select_def['cfg']['id'], |
|---|
| 966 | select_def['cfg']['class'], |
|---|
| 967 | access_flag, |
|---|
| 968 | option_section) |
|---|
| [14958] | 969 | return result |
|---|
| [8190] | 970 | |
|---|
| [16871] | 971 | def create_notify(self, db, name, resolved_name, parameters, |
|---|
| 972 | placeholder_id): |
|---|
| [14958] | 973 | # create notify... |
|---|
| 974 | result = '' |
|---|
| [16871] | 975 | notify_def = { |
|---|
| 976 | 'cfg': { |
|---|
| 977 | 'mail_to': 'default_receiver', |
|---|
| 978 | 'subject': 'wikiform updated', |
|---|
| 979 | 'body': None |
|---|
| 980 | }, |
|---|
| 981 | 'xtras': [], |
|---|
| 982 | 'xtra': {} |
|---|
| 983 | } |
|---|
| [8190] | 984 | |
|---|
| [14958] | 985 | # ...overwrite hardcoded defaults with user-defined values... |
|---|
| [16871] | 986 | notify_def = wikiforms_lib.parse_options(parameters, notify_def) |
|---|
| [8215] | 987 | |
|---|
| [14958] | 988 | result += """ |
|---|
| [16871] | 989 | <INPUT type="hidden" name="__NOTIFY_MAILTO" value="%s"> |
|---|
| 990 | """ % notify_def['cfg']['mail_to'] |
|---|
| [8190] | 991 | |
|---|
| [14958] | 992 | result += """ |
|---|
| [16871] | 993 | <INPUT type="hidden" name="__NOTIFY_SUBJECT" value="%s"> |
|---|
| 994 | """ % notify_def['cfg']['subject'] |
|---|
| [8190] | 995 | |
|---|
| [16871] | 996 | if notify_def['cfg']['body'] is not None: |
|---|
| [14958] | 997 | result += """ |
|---|
| [16871] | 998 | <INPUT type="hidden" name="__NOTIFY_BODY" value="%s"> |
|---|
| 999 | """ % notify_def['cfg']['body'] |
|---|
| [8190] | 1000 | |
|---|
| [14958] | 1001 | return result |
|---|
| [8190] | 1002 | |
|---|
| [16871] | 1003 | def create_submit(self, name, resolved_name, parameters, placeholder_id, |
|---|
| 1004 | permission): |
|---|
| [14958] | 1005 | # create submit... |
|---|
| 1006 | result = '' |
|---|
| [16871] | 1007 | button_def = { |
|---|
| 1008 | 'cfg': { |
|---|
| 1009 | 'label': 'Send', |
|---|
| 1010 | 'class': 'buttons', |
|---|
| 1011 | 'id': 'button_css_id', |
|---|
| 1012 | 'debug': False |
|---|
| 1013 | }, |
|---|
| 1014 | 'xtras': [], |
|---|
| 1015 | 'xtra': {} |
|---|
| 1016 | } |
|---|
| [8190] | 1017 | |
|---|
| [16871] | 1018 | button_def = wikiforms_lib.parse_options(parameters, button_def) |
|---|
| [8190] | 1019 | |
|---|
| [16871] | 1020 | if button_def['cfg']['debug']: |
|---|
| 1021 | result += "debug: parameters=>%s< name=>%s<>%s< cfg=>%s< xtras=>%s< xtra=>%s< db=>%s< perm=>%s<" \ |
|---|
| 1022 | % (parameters, |
|---|
| 1023 | name, resolved_name, |
|---|
| 1024 | str(button_def['cfg']), |
|---|
| 1025 | str(button_def['xtras']), |
|---|
| 1026 | str(button_def['xtra']), |
|---|
| 1027 | permission) |
|---|
| [8190] | 1028 | |
|---|
| [16871] | 1029 | if not permission['w']: |
|---|
| [14958] | 1030 | access_flag = 'DISABLED' |
|---|
| 1031 | else: |
|---|
| 1032 | access_flag = '' |
|---|
| [8190] | 1033 | |
|---|
| [16871] | 1034 | if permission['r']: |
|---|
| [14958] | 1035 | result += """ |
|---|
| [16871] | 1036 | <INPUT type='submit' name='__SUBMIT' id='%s' class='%s' value='%s' %s > |
|---|
| 1037 | """ % (button_def['cfg']['id'], |
|---|
| 1038 | button_def['cfg']['class'], |
|---|
| 1039 | button_def['cfg']['label'], |
|---|
| 1040 | access_flag) |
|---|
| [14958] | 1041 | return result |
|---|
| [8190] | 1042 | |
|---|
| [16871] | 1043 | def build_form(self, formatter, page, form_body): |
|---|
| 1044 | form_name = 'form_name' |
|---|
| 1045 | form_css_id = 'form_css_id' |
|---|
| [14958] | 1046 | form_css_class = 'form_css_class' |
|---|
| [16871] | 1047 | dest = str(formatter.req.href('/wikiforms/update')) |
|---|
| 1048 | backpath = str(formatter.req.href(formatter.req.path_info)) |
|---|
| 1049 | form_token = str(formatter.req.form_token) |
|---|
| [8190] | 1050 | |
|---|
| [14958] | 1051 | yield """ |
|---|
| 1052 | <FORM |
|---|
| 1053 | class="printableform" |
|---|
| 1054 | method="POST" |
|---|
| 1055 | action=%s |
|---|
| 1056 | name="%s" |
|---|
| 1057 | id="%s" |
|---|
| 1058 | class="%s" |
|---|
| 1059 | > |
|---|
| [8190] | 1060 | |
|---|
| [14958] | 1061 | %s |
|---|
| [8190] | 1062 | |
|---|
| [14958] | 1063 | <INPUT |
|---|
| 1064 | type="hidden" |
|---|
| 1065 | name="__BACKPATH" |
|---|
| 1066 | value=%s |
|---|
| 1067 | > |
|---|
| [7424] | 1068 | |
|---|
| [14958] | 1069 | <INPUT |
|---|
| 1070 | type="hidden" |
|---|
| 1071 | name="__FORM_TOKEN" |
|---|
| 1072 | value=%s |
|---|
| 1073 | > |
|---|
| [7424] | 1074 | |
|---|
| [14958] | 1075 | <INPUT |
|---|
| 1076 | type="hidden" |
|---|
| 1077 | name="__PAGE" |
|---|
| 1078 | value='%s' |
|---|
| 1079 | > |
|---|
| [7424] | 1080 | |
|---|
| [14958] | 1081 | </FORM> |
|---|
| [16871] | 1082 | """ % (dest, form_name, form_css_id, form_css_class, |
|---|
| 1083 | form_body, backpath, form_token, page) |
|---|
| [7424] | 1084 | |
|---|
| [14958] | 1085 | def to_quote(self, value): |
|---|
| 1086 | if value is None: |
|---|
| 1087 | result = '' |
|---|
| 1088 | else: |
|---|
| 1089 | result = value |
|---|
| 1090 | result = re.sub("'", "'", result) |
|---|
| 1091 | return result |
|---|
| [7424] | 1092 | |
|---|
| [14958] | 1093 | def to_unquote(self, value): |
|---|
| 1094 | if value is None: |
|---|
| 1095 | result = '' |
|---|
| 1096 | else: |
|---|
| 1097 | result = value |
|---|
| 1098 | result = re.sub("'", "'", result) |
|---|
| [7424] | 1099 | |
|---|
| [14958] | 1100 | return result |
|---|
| [7424] | 1101 | |
|---|
| [14958] | 1102 | def to_timestring(self, time_int, format='%Y-%b-%d %H:%M:%S'): |
|---|
| 1103 | if time_int is None: |
|---|
| 1104 | result = 'unset-time' |
|---|
| [8190] | 1105 | else: |
|---|
| [14958] | 1106 | result = time.strftime(format, time.localtime(time_int)) |
|---|
| [7424] | 1107 | |
|---|
| [14958] | 1108 | return result |
|---|
| [7424] | 1109 | |
|---|
| [14958] | 1110 | def to_userstring(self, user): |
|---|
| 1111 | if user is None: |
|---|
| 1112 | result = 'unset-user' |
|---|
| 1113 | else: |
|---|
| 1114 | result = user |
|---|
| [7424] | 1115 | |
|---|
| [14958] | 1116 | return result |
|---|
| [8190] | 1117 | |
|---|
| [14958] | 1118 | def get_tracform_field(self, db, resolved_name): |
|---|
| 1119 | result = { |
|---|
| 1120 | 'field': None, |
|---|
| 1121 | 'value': '', |
|---|
| 1122 | 'updated_by': self.to_userstring(None), |
|---|
| 1123 | 'updated_on': None |
|---|
| 1124 | } |
|---|
| [16872] | 1125 | row = [] |
|---|
| [14958] | 1126 | |
|---|
| [16872] | 1127 | cursor = db.cursor() |
|---|
| 1128 | cursor.execute(""" |
|---|
| [16871] | 1129 | SELECT field,value,updated_by,updated_on |
|---|
| 1130 | FROM wikiforms_fields |
|---|
| [16872] | 1131 | WHERE field=%s |
|---|
| 1132 | """, (resolved_name,)) |
|---|
| [14958] | 1133 | |
|---|
| [16871] | 1134 | for field, value, updated_by, updated_on in cursor: |
|---|
| 1135 | row.append({ |
|---|
| 1136 | 'field': self.to_unquote(field), |
|---|
| 1137 | 'value': self.to_unquote(value), |
|---|
| 1138 | 'updated_by': self.to_userstring(updated_by), |
|---|
| 1139 | 'updated_on': updated_on |
|---|
| 1140 | }) |
|---|
| [14958] | 1141 | |
|---|
| [16871] | 1142 | if len(row) == 1: |
|---|
| [14958] | 1143 | result = row[0] |
|---|
| 1144 | |
|---|
| [16872] | 1145 | return result |
|---|
| [14958] | 1146 | |
|---|
| [16871] | 1147 | def get_tracform(self, db): |
|---|
| 1148 | result = [] |
|---|
| [14958] | 1149 | |
|---|
| [16872] | 1150 | cursor = db.cursor() |
|---|
| 1151 | cursor.execute(""" |
|---|
| [16871] | 1152 | SELECT field,value,updated_by,updated_on |
|---|
| 1153 | FROM wikiforms_fields |
|---|
| [16872] | 1154 | """) |
|---|
| [14958] | 1155 | |
|---|
| [16871] | 1156 | for field, value, updated_by, updated_on in cursor: |
|---|
| 1157 | result.append({ |
|---|
| 1158 | 'field': self.to_unquote(field), |
|---|
| 1159 | 'value': self.to_unquote(value), |
|---|
| 1160 | 'updated_by': updated_by, |
|---|
| 1161 | 'updated_on': self.to_timestring(updated_on) |
|---|
| 1162 | }) |
|---|
| [14958] | 1163 | |
|---|
| [16872] | 1164 | return result |
|---|
| [14958] | 1165 | |
|---|
| [16871] | 1166 | def set_tracform_field(self, db, resolved_name, value, authname): |
|---|
| 1167 | cursor = db.cursor() |
|---|
| 1168 | updated_on = int(time.time()) |
|---|
| 1169 | updated_by = authname |
|---|
| [14958] | 1170 | |
|---|
| [16872] | 1171 | cursor.execute(""" |
|---|
| [16871] | 1172 | SELECT value |
|---|
| 1173 | FROM wikiforms_fields |
|---|
| [16872] | 1174 | WHERE field=%s |
|---|
| 1175 | """, (resolved_name,)) |
|---|
| [14958] | 1176 | |
|---|
| 1177 | row = cursor.fetchone() |
|---|
| 1178 | |
|---|
| 1179 | if not row: |
|---|
| 1180 | # does not exist => insert... |
|---|
| [16872] | 1181 | cursor.execute(""" |
|---|
| [16871] | 1182 | INSERT INTO wikiforms_fields |
|---|
| 1183 | (field,value,updated_on,updated_by) |
|---|
| [16872] | 1184 | VALUES (%s, %s, %s, %s) |
|---|
| 1185 | """, (resolved_name, value, updated_on, updated_by)) |
|---|
| [14958] | 1186 | db.commit() |
|---|
| [16871] | 1187 | elif self.to_quote(value) != row[0]: |
|---|
| [14958] | 1188 | # new value => update... |
|---|
| [16872] | 1189 | cursor.execute(""" |
|---|
| [16871] | 1190 | UPDATE wikiforms_fields |
|---|
| [16872] | 1191 | SET value=%s, updated_on=%s, updated_by=%s |
|---|
| 1192 | WHERE field=%s |
|---|
| 1193 | """, (value, updated_on, updated_by, resolved_name)) |
|---|
| [14958] | 1194 | db.commit() |
|---|
| 1195 | |
|---|
| [16871] | 1196 | def delete_tracform_field(self, db, resolved_name): |
|---|
| [14958] | 1197 | cursor = db.cursor() |
|---|
| [16872] | 1198 | cursor.execute(""" |
|---|
| [16871] | 1199 | DELETE FROM wikiforms_fields |
|---|
| [16872] | 1200 | WHERE field=%s |
|---|
| 1201 | """, (resolved_name,)) |
|---|
| [14958] | 1202 | db.commit() |
|---|
| 1203 | |
|---|
| 1204 | def get_placeholder_id(self): |
|---|
| 1205 | WikiFormsMacro.placeholder_cnt += 1 |
|---|
| [16871] | 1206 | return "CNT/%s/:VAL/%s/" % (WikiFormsMacro.placeholder_cnt, |
|---|
| 1207 | random.randint(0, 1000000000)) |
|---|
| [14958] | 1208 | |
|---|
| 1209 | def wiki_to_html(self, formatter, text): |
|---|
| 1210 | out = StringIO.StringIO() |
|---|
| 1211 | Formatter(formatter.env, formatter.context).format(text, out) |
|---|
| 1212 | return out.getvalue() |
|---|
| 1213 | |
|---|
| [16871] | 1214 | def resolve_name(self, page, context, name): |
|---|
| [14958] | 1215 | result = page |
|---|
| 1216 | |
|---|
| [16871] | 1217 | if name != '': |
|---|
| 1218 | if context != '': |
|---|
| 1219 | if context[0] == '/': |
|---|
| [14958] | 1220 | # absolute context... |
|---|
| 1221 | result = context |
|---|
| 1222 | else: |
|---|
| 1223 | # relative context... |
|---|
| 1224 | result += '/' + context |
|---|
| 1225 | |
|---|
| [16871] | 1226 | if name[0] == '/': |
|---|
| [14958] | 1227 | # absolute name... |
|---|
| 1228 | result = name |
|---|
| 1229 | else: |
|---|
| 1230 | # relative name... |
|---|
| 1231 | result += '/' + name |
|---|
| 1232 | |
|---|
| 1233 | return result |
|---|
| 1234 | |
|---|
| [16871] | 1235 | def to_boolean(self, value): |
|---|
| 1236 | if value is not None: |
|---|
| [14958] | 1237 | if isinstance(value, (bool)): |
|---|
| 1238 | result = value |
|---|
| [16871] | 1239 | elif value.lower() in ['1', 'true', 'on', 'yes']: |
|---|
| [14958] | 1240 | result = True |
|---|
| 1241 | else: |
|---|
| 1242 | result = False |
|---|
| [8190] | 1243 | else: |
|---|
| [14958] | 1244 | result = False |
|---|
| [8190] | 1245 | |
|---|
| [14958] | 1246 | return result |
|---|
| [8190] | 1247 | |
|---|
| [16871] | 1248 | def resolve_permission(self, permission_condition, formatter): |
|---|
| [14958] | 1249 | result = None |
|---|
| [16871] | 1250 | msg = '' |
|---|
| [14958] | 1251 | |
|---|
| [16871] | 1252 | lhs, rest_of_line = wikiforms_lib.get_piece( |
|---|
| 1253 | permission_condition, [' ']) |
|---|
| [14958] | 1254 | |
|---|
| [16871] | 1255 | if lhs == 'user': |
|---|
| 1256 | LHS = formatter.req.authname |
|---|
| 1257 | operator, rhs = wikiforms_lib.get_piece(rest_of_line, [' ']) |
|---|
| [14958] | 1258 | |
|---|
| [16871] | 1259 | elif lhs == 'ticket_state': |
|---|
| 1260 | ticket_id, rest_of_line = wikiforms_lib.get_piece( |
|---|
| 1261 | rest_of_line, [' ']) |
|---|
| 1262 | operator, rhs = wikiforms_lib.get_piece(rest_of_line, [' ']) |
|---|
| 1263 | db = formatter.env.get_db_cnx() |
|---|
| 1264 | cursor = db.cursor() |
|---|
| [16872] | 1265 | cursor.execute(""" |
|---|
| [16871] | 1266 | SELECT status FROM ticket WHERE id=%s |
|---|
| [16872] | 1267 | """, (ticket_id,)) |
|---|
| [14958] | 1268 | |
|---|
| 1269 | row = cursor.fetchone() |
|---|
| 1270 | if row: |
|---|
| 1271 | LHS, = row |
|---|
| 1272 | else: |
|---|
| 1273 | msg += 'Ticket(%s) does not exist' % (ticket_id) |
|---|
| [16871] | 1274 | elif lhs == 'milestone_is_complete': |
|---|
| 1275 | milestone_name, ignored = \ |
|---|
| 1276 | wikiforms_lib.get_piece(rest_of_line, [' ']) |
|---|
| [14958] | 1277 | |
|---|
| [16871] | 1278 | db = formatter.env.get_db_cnx() |
|---|
| 1279 | cursor = db.cursor() |
|---|
| [16872] | 1280 | cursor.execute(""" |
|---|
| 1281 | SELECT completed FROM milestone WHERE name=%s |
|---|
| 1282 | """, (milestone_name,)) |
|---|
| [14958] | 1283 | |
|---|
| 1284 | row = cursor.fetchone() |
|---|
| 1285 | if row: |
|---|
| 1286 | completed, = row |
|---|
| 1287 | |
|---|
| [16871] | 1288 | if completed > 0: |
|---|
| 1289 | LHS = '1' |
|---|
| [14958] | 1290 | else: |
|---|
| [16871] | 1291 | LHS = '0' |
|---|
| [14958] | 1292 | |
|---|
| 1293 | operator = 'in' |
|---|
| [16871] | 1294 | rhs = '1' |
|---|
| [14958] | 1295 | else: |
|---|
| [16871] | 1296 | msg += 'Milestone(%s) does not exist' % milestone_name |
|---|
| [14958] | 1297 | else: |
|---|
| 1298 | LHS = lhs |
|---|
| [16871] | 1299 | operator, rhs = wikiforms_lib.get_piece(rest_of_line, [' ']) |
|---|
| [14958] | 1300 | |
|---|
| [16871] | 1301 | if msg == '': |
|---|
| [14958] | 1302 | RHS = [] |
|---|
| 1303 | |
|---|
| 1304 | while rhs != '': |
|---|
| [16871] | 1305 | tmp, rhs = wikiforms_lib.get_piece(rhs, [',']) |
|---|
| [14958] | 1306 | RHS.append(tmp) |
|---|
| 1307 | |
|---|
| [16871] | 1308 | if operator == 'in': |
|---|
| 1309 | if LHS in RHS: |
|---|
| [14958] | 1310 | result = True |
|---|
| 1311 | else: |
|---|
| 1312 | result = False |
|---|
| [16871] | 1313 | elif operator == 'not_in': |
|---|
| 1314 | if LHS not in RHS: |
|---|
| [14958] | 1315 | result = True |
|---|
| 1316 | else: |
|---|
| 1317 | result = False |
|---|
| 1318 | else: |
|---|
| 1319 | msg += 'Operator(%s) is not yet supported' % (operator) |
|---|
| 1320 | |
|---|
| 1321 | return result, msg |
|---|
| 1322 | |
|---|
| 1323 | |
|---|
| [8190] | 1324 | class WikiFormIncludeMacro(WikiMacroBase): |
|---|
| [14958] | 1325 | """ |
|---|
| 1326 | A macro to include wiki forms (wiki pages) with optional parameters. |
|---|
| 1327 | """ |
|---|
| [8190] | 1328 | |
|---|
| [16871] | 1329 | # the following stuff is a stripped down and adapted version of |
|---|
| 1330 | # IncludeMacro. |
|---|
| [14958] | 1331 | def expand_macro(self, formatter, name, args): |
|---|
| 1332 | wikiforms_page, args = wikiforms_lib.get_piece(args) |
|---|
| [8190] | 1333 | |
|---|
| [14958] | 1334 | if wikiforms_page == "": |
|---|
| 1335 | return system_message('Invalid(empty) argument') |
|---|
| [8190] | 1336 | |
|---|
| [14958] | 1337 | parameters = { |
|---|
| 1338 | 'cfg': {}, |
|---|
| 1339 | 'xtras': [], |
|---|
| 1340 | 'xtra': {} |
|---|
| 1341 | } |
|---|
| [8190] | 1342 | |
|---|
| [14958] | 1343 | parameters = wikiforms_lib.parse_options(args, parameters) |
|---|
| [8190] | 1344 | |
|---|
| [16871] | 1345 | formatter.req.perm.require('WIKI_VIEW') |
|---|
| [14958] | 1346 | page = WikiPage(self.env, wikiforms_page) |
|---|
| 1347 | if page.exists is False: |
|---|
| [16871] | 1348 | return system_message("Can't include non existing WikiForm(%s)" |
|---|
| 1349 | % wikiforms_page) |
|---|
| [8190] | 1350 | |
|---|
| [14958] | 1351 | out = page.text |
|---|
| 1352 | ctxt = Context.from_request(formatter.req, 'wiki', wikiforms_page) |
|---|
| [8190] | 1353 | |
|---|
| [14958] | 1354 | # replace defined keys... |
|---|
| 1355 | for key in parameters['xtras']: |
|---|
| [16871] | 1356 | out = re.sub('\{\{\s*' + key + '\s*\}\}', |
|---|
| 1357 | parameters['xtra'][key], out) |
|---|
| [8190] | 1358 | |
|---|
| [14958] | 1359 | out = Mimeview(self.env).render(ctxt, 'text/x-trac-wiki', out) |
|---|
| [8190] | 1360 | |
|---|
| [14958] | 1361 | # Escape if needed |
|---|
| [16871] | 1362 | if not self.config.getbool('wiki', 'render_unsafe_content', False): |
|---|
| 1363 | buf = StringIO.StringIO(out) |
|---|
| [14958] | 1364 | try: |
|---|
| [16871] | 1365 | out = HTMLParser(buf).parse() | HTMLSanitizer() |
|---|
| [14958] | 1366 | except ParseError: |
|---|
| 1367 | out = escape(out) |
|---|
| 1368 | |
|---|
| 1369 | return out |
|---|