Projet

Général

Profil

0001-template-escape-substitution-variables-7860.patch

Frédéric Péters, 16 juillet 2015 12:38

Télécharger (12,1 ko)

Voir les différences:

Subject: [PATCH] template: escape substitution variables (#7860)

 tests/test_fields.py       |  6 ++++++
 tests/test_prefill.py      |  2 +-
 wcs/data_sources.py        |  4 ++--
 wcs/fields.py              |  7 ++++---
 wcs/forms/root.py          |  2 +-
 wcs/qommon/admin/texts.py  |  2 +-
 wcs/qommon/emails.py       |  2 +-
 wcs/qommon/form.py         |  4 ++--
 wcs/qommon/ident/idp.py    |  2 +-
 wcs/qommon/substitution.py | 10 +++++++++-
 wcs/qommon/template.py     |  2 +-
 wcs/wf/jump.py             |  2 +-
 wcs/wf/wscall.py           |  2 +-
 wcs/workflows.py           | 12 +++++++++---
 14 files changed, 40 insertions(+), 19 deletions(-)
tests/test_fields.py
128 128
    field.add_to_form(form)
129 129
    assert '<p>Foobar</p>' in str(form.render())
130 130

  
131
    # test for proper escaping of substitution variables
132
    field = fields.CommentField(label='[foo]')
133
    form = Form()
134
    field.add_to_form(form)
135
    assert '<p>1 &lt; 3</p>' in str(form.render())
136

  
131 137
    # test for html content
132 138
    field = fields.CommentField(label='<p>Foobar</p>')
133 139
    form = Form()
tests/test_prefill.py
57 57

  
58 58

  
59 59
def test_prefill_formula_substition_variable():
60
    pub.substitutions.get_context_variables = lambda: {'test': 'value'}
60
    pub.substitutions.get_context_variables = lambda escape: {'test': 'value'}
61 61
    field = fields.Field()
62 62
    field.prefill = {'type': 'formula', 'value': 'test'}
63 63

  
wcs/data_sources.py
104 104
        #   - three elements, (id, text, key)
105 105
        #   - two elements, (id, text)
106 106
        #   - a single element, (id,)
107
        vars = get_publisher().substitutions.get_context_variables()
107
        vars = get_publisher().substitutions.get_context_variables(escape=False)
108 108
        try:
109 109
            value = eval(data_source.get('value'), vars, data_source_functions)
110 110
            if not isinstance(value, collections.Iterable):
......
136 136
            get_logger().warn('Empty URL in JSON data source')
137 137
            return []
138 138
        if '[' in url:
139
            vars = get_publisher().substitutions.get_context_variables()
139
            vars = get_publisher().substitutions.get_context_variables(escape=False)
140 140
            url = get_variadic_url(url, vars)
141 141
        charset = get_publisher().site_charset
142 142
        try:
wcs/fields.py
257 257
            try:
258 258
                ret = eval(formula,
259 259
                    get_publisher().get_global_eval_dict(),
260
                    get_publisher().substitutions.get_context_variables())
260
                    get_publisher().substitutions.get_context_variables(escape=False))
261 261
                if ret:
262 262
                    return str(ret)
263 263
            except:
......
453 453
            label = self.label
454 454

  
455 455
        import wcs.workflows
456
        label = wcs.workflows.template_on_string(label)
456
        label = wcs.workflows.template_on_string(label,
457
                process=wcs.workflows.html_process)
457 458

  
458 459
        if '<p' in label:
459 460
            enclosing_tag = 'div'
......
1178 1179
            return True
1179 1180

  
1180 1181
        from formdata import get_dict_with_varnames
1181
        data = get_publisher().substitutions.get_context_variables()
1182
        data = get_publisher().substitutions.get_context_variables(escape=False)
1182 1183

  
1183 1184
        # create variables with values currently being evaluated, not yet
1184 1185
        # available in the formdata
wcs/forms/root.py
438 438
        if self.formdef.is_disabled():
439 439
            if self.formdef.disabled_redirection:
440 440
                return misc.get_variadic_url(self.formdef.disabled_redirection,
441
                        get_publisher().substitutions.get_context_variables())
441
                        get_publisher().substitutions.get_context_variables(escape=False))
442 442
            else:
443 443
                raise errors.AccessForbiddenError()
444 444
        return False
wcs/qommon/admin/texts.py
45 45
            if text[0] != '<':
46 46
                text = '<p>%s</p>' % text
47 47

  
48
        subst_vars = get_publisher().substitutions.get_context_variables()
48
        subst_vars = get_publisher().substitutions.get_context_variables(escape=True)
49 49
        if vars:
50 50
            subst_vars.update(vars)
51 51

  
wcs/qommon/emails.py
66 66
    mail_subject_template = ezt.Template(compress_whitespace = False)
67 67
    mail_subject_template.parse(subject)
68 68

  
69
    data = get_publisher().substitutions.get_context_variables()
69
    data = get_publisher().substitutions.get_context_variables(escape=False)
70 70
    if mail_body_data:
71 71
        data.update(mail_body_data)
72 72

  
wcs/qommon/form.py
1635 1635
                'searching': _('Searching...')})
1636 1636

  
1637 1637
        if '[' in self.url:
1638
            vars = get_publisher().substitutions.get_context_variables()
1638
            vars = get_publisher().substitutions.get_context_variables(escape=False)
1639 1639
            url = misc.get_variadic_url(self.url, vars, encode_query=False)
1640 1640
        else:
1641 1641
            url = self.url
......
1734 1734
        get_response().add_css_include('../js/smoothness/jquery-ui-1.10.0.custom.min.css')
1735 1735

  
1736 1736
        if '[' in self.url:
1737
            vars = get_publisher().substitutions.get_context_variables()
1737
            vars = get_publisher().substitutions.get_context_variables(escape=False)
1738 1738
            url = misc.get_variadic_url(self.url, vars, encode_query=False)
1739 1739
        else:
1740 1740
            url = self.url
wcs/qommon/ident/idp.py
137 137

  
138 138
        if not get_request().user or not get_session().name_identifier:
139 139
            if get_cfg('saml_identities', {}).get('registration-url'):
140
                vars = get_publisher().substitutions.get_context_variables()
140
                vars = get_publisher().substitutions.get_context_variables(escape=False)
141 141
                vars['next_url'] = get_request().get_frontoffice_url()
142 142
                registration_url = misc.get_variadic_url(
143 143
                                get_cfg('saml_identities', {}).get('registration-url'),
wcs/qommon/substitution.py
14 14
# You should have received a copy of the GNU General Public License
15 15
# along with this program; if not, see <http://www.gnu.org/licenses/>.
16 16

  
17
import cgi
18

  
17 19
from quixote.html import htmltext, TemplateIO
18 20

  
19 21
class Substitutions(object):
......
52 54
            return
53 55
        self.sources.append(source)
54 56

  
55
    def get_context_variables(self):
57
    def get_context_variables(self, escape=True):
56 58
        d = {}
57 59
        for source in self.sources:
58 60
            d.update(source.get_substitution_variables())
61
        if escape:
62
            for var_key, var_value in d.items():
63
                if isinstance(var_value, basestring):
64
                    d[var_key] = cgi.escape(var_value)
65
                else:
66
                    d[var_key] = var_value
59 67
        return d
60 68

  
61 69
    def get_substitution_html_table(cls):
wcs/qommon/template.py
438 438
            breadcrumb = ' <span class="separator">&gt;</span> '.join(s)
439 439

  
440 440
    vars = response.filter.copy()
441
    vars.update(get_publisher().substitutions.get_context_variables())
441
    vars.update(get_publisher().substitutions.get_context_variables(escape=True))
442 442
    vars.update(locals())
443 443
    fd = StringIO()
444 444
    template.generate(fd, vars)
wcs/wf/jump.py
194 194
        must_jump = True
195 195

  
196 196
        if self.condition:
197
            variables = get_publisher().substitutions.get_context_variables()
197
            variables = get_publisher().substitutions.get_context_variables(escape=False)
198 198
            try:
199 199
                must_jump = eval(self.condition, get_publisher().get_global_eval_dict(), variables)
200 200
            except:
wcs/wf/wscall.py
59 59
            return
60 60
        url = self.url
61 61
        if '[' in url:
62
            variables = get_publisher().substitutions.get_context_variables()
62
            variables = get_publisher().substitutions.get_context_variables(escape=False)
63 63
            url = get_variadic_url(url, variables)
64 64

  
65 65
        if self.request_signature_key:
wcs/workflows.py
15 15
# along with this program; if not, see <http://www.gnu.org/licenses/>.
16 16

  
17 17
from qommon import ezt
18
import cgi
18 19
from cStringIO import StringIO
19 20
import copy
20 21
import xml.etree.ElementTree as ET
......
826 827
            return var
827 828
        if not var.startswith('='):
828 829
            return var
829
        vars = get_publisher().substitutions.get_context_variables()
830
        vars = get_publisher().substitutions.get_context_variables(escape=False)
830 831
        try:
831 832
            return eval(var[1:], get_publisher().get_global_eval_dict(), vars)
832 833
        except:
......
1356 1357
    if not '[' in template:
1357 1358
        return template
1358 1359
    dict = {}
1359
    dict.update(get_publisher().substitutions.get_context_variables())
1360
    dict.update(get_publisher().substitutions.get_context_variables(escape=False))
1360 1361
    if formdata:
1361 1362
        dict['url'] = formdata.get_url()
1362 1363
        dict['url_status'] = '%sstatus' % formdata.get_url()
......
1462 1463
        tmpl.parse(self.message)
1463 1464

  
1464 1465
        dict = {}
1465
        dict.update(get_publisher().substitutions.get_context_variables())
1466
        dict.update(get_publisher().substitutions.get_context_variables(escape=True))
1466 1467
        dict['date'] = misc.localstrftime(filled.receipt_time)
1467 1468
        dict['number'] = filled.id
1468 1469
        handling_role = filled.get_handling_role()
......
1590 1591
        return None
1591 1592
    return str2rtf(unicode(str(value), get_publisher().site_charset))
1592 1593

  
1594
def html_process(value):
1595
    if not isinstance(value, basestring):
1596
        return value
1597
    return cgi.escape(value)
1598

  
1593 1599
class ExportToModel(WorkflowStatusItem):
1594 1600
    description = N_('Create Document')
1595 1601
    key = 'export_to_model'
1596
-