source: wikiformsplugin/0.11/wikiforms/wikiforms.py

Last change on this file was 16879, checked in by Ryan J Ollos, 6 years ago

WikiForms 0.4dev: Ignore arguments that are not string type

Fixes #13300.

File size: 50.9 KB
RevLine 
[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]10import StringIO
[10651]11import smtplib
[14958]12import random
[7424]13import re
[14958]14import time
[16871]15from datetime import datetime
[7424]16
[8190]17from genshi.core import escape
[14958]18from genshi.filters.html import HTMLSanitizer
[8190]19from genshi.input import HTMLParser, ParseError
[16876]20from trac.core import TracError, implements
[16872]21from trac.db.api import DatabaseManager
[14958]22from trac.db.schema import Column, Table
23from trac.env import IEnvironmentSetupParticipant
[16871]24from trac.mimeview.api import Context, Mimeview
25from trac.perm import IPermissionRequestor
26from trac.util.datefmt import format_datetime, pretty_timedelta, utc
[16875]27from trac.util.text import exception_to_unicode
[14958]28from trac.web import IRequestHandler
[16871]29from trac.web.api import HTTPBadRequest
[14958]30from trac.wiki.macros import WikiMacroBase
31from trac.wiki.model import WikiPage
32from trac.wiki.formatter import Formatter, system_message
[8190]33
[14958]34import wikiforms_lib
[8190]35
[7424]36
[16876]37class 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("'", "&#39;", 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("&#39;", "'", 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]1324class 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
Note: See TracBrowser for help on using the repository browser.