11cb0ef41Sopenharmony_ci# -*- coding: utf-8 -*-
21cb0ef41Sopenharmony_ci"""
31cb0ef41Sopenharmony_ci    jinja2.sandbox
41cb0ef41Sopenharmony_ci    ~~~~~~~~~~~~~~
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ci    Adds a sandbox layer to Jinja as it was the default behavior in the old
71cb0ef41Sopenharmony_ci    Jinja 1 releases.  This sandbox is slightly different from Jinja 1 as the
81cb0ef41Sopenharmony_ci    default behavior is easier to use.
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci    The behavior can be changed by subclassing the environment.
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci    :copyright: (c) 2017 by the Jinja Team.
131cb0ef41Sopenharmony_ci    :license: BSD.
141cb0ef41Sopenharmony_ci"""
151cb0ef41Sopenharmony_ciimport types
161cb0ef41Sopenharmony_ciimport operator
171cb0ef41Sopenharmony_cifrom collections import Mapping
181cb0ef41Sopenharmony_cifrom jinja2.environment import Environment
191cb0ef41Sopenharmony_cifrom jinja2.exceptions import SecurityError
201cb0ef41Sopenharmony_cifrom jinja2._compat import string_types, PY2
211cb0ef41Sopenharmony_cifrom jinja2.utils import Markup
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_cifrom markupsafe import EscapeFormatter
241cb0ef41Sopenharmony_cifrom string import Formatter
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci#: maximum number of items a range may produce
281cb0ef41Sopenharmony_ciMAX_RANGE = 100000
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci#: attributes of function objects that are considered unsafe.
311cb0ef41Sopenharmony_ciif PY2:
321cb0ef41Sopenharmony_ci    UNSAFE_FUNCTION_ATTRIBUTES = set(['func_closure', 'func_code', 'func_dict',
331cb0ef41Sopenharmony_ci                                      'func_defaults', 'func_globals'])
341cb0ef41Sopenharmony_cielse:
351cb0ef41Sopenharmony_ci    # On versions > python 2 the special attributes on functions are gone,
361cb0ef41Sopenharmony_ci    # but they remain on methods and generators for whatever reason.
371cb0ef41Sopenharmony_ci    UNSAFE_FUNCTION_ATTRIBUTES = set()
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci#: unsafe method attributes.  function attributes are unsafe for methods too
411cb0ef41Sopenharmony_ciUNSAFE_METHOD_ATTRIBUTES = set(['im_class', 'im_func', 'im_self'])
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci#: unsafe generator attirbutes.
441cb0ef41Sopenharmony_ciUNSAFE_GENERATOR_ATTRIBUTES = set(['gi_frame', 'gi_code'])
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci#: unsafe attributes on coroutines
471cb0ef41Sopenharmony_ciUNSAFE_COROUTINE_ATTRIBUTES = set(['cr_frame', 'cr_code'])
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci#: unsafe attributes on async generators
501cb0ef41Sopenharmony_ciUNSAFE_ASYNC_GENERATOR_ATTRIBUTES = set(['ag_code', 'ag_frame'])
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ciimport warnings
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci# make sure we don't warn in python 2.6 about stuff we don't care about
551cb0ef41Sopenharmony_ciwarnings.filterwarnings('ignore', 'the sets module', DeprecationWarning,
561cb0ef41Sopenharmony_ci                        module='jinja2.sandbox')
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_cifrom collections import deque
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci_mutable_set_types = (set,)
611cb0ef41Sopenharmony_ci_mutable_mapping_types = (dict,)
621cb0ef41Sopenharmony_ci_mutable_sequence_types = (list,)
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci# on python 2.x we can register the user collection types
661cb0ef41Sopenharmony_citry:
671cb0ef41Sopenharmony_ci    from UserDict import UserDict, DictMixin
681cb0ef41Sopenharmony_ci    from UserList import UserList
691cb0ef41Sopenharmony_ci    _mutable_mapping_types += (UserDict, DictMixin)
701cb0ef41Sopenharmony_ci    _mutable_set_types += (UserList,)
711cb0ef41Sopenharmony_ciexcept ImportError:
721cb0ef41Sopenharmony_ci    pass
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci# if sets is still available, register the mutable set from there as well
751cb0ef41Sopenharmony_citry:
761cb0ef41Sopenharmony_ci    from sets import Set
771cb0ef41Sopenharmony_ci    _mutable_set_types += (Set,)
781cb0ef41Sopenharmony_ciexcept ImportError:
791cb0ef41Sopenharmony_ci    pass
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci#: register Python 2.6 abstract base classes
821cb0ef41Sopenharmony_cifrom collections import MutableSet, MutableMapping, MutableSequence
831cb0ef41Sopenharmony_ci_mutable_set_types += (MutableSet,)
841cb0ef41Sopenharmony_ci_mutable_mapping_types += (MutableMapping,)
851cb0ef41Sopenharmony_ci_mutable_sequence_types += (MutableSequence,)
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci_mutable_spec = (
891cb0ef41Sopenharmony_ci    (_mutable_set_types, frozenset([
901cb0ef41Sopenharmony_ci        'add', 'clear', 'difference_update', 'discard', 'pop', 'remove',
911cb0ef41Sopenharmony_ci        'symmetric_difference_update', 'update'
921cb0ef41Sopenharmony_ci    ])),
931cb0ef41Sopenharmony_ci    (_mutable_mapping_types, frozenset([
941cb0ef41Sopenharmony_ci        'clear', 'pop', 'popitem', 'setdefault', 'update'
951cb0ef41Sopenharmony_ci    ])),
961cb0ef41Sopenharmony_ci    (_mutable_sequence_types, frozenset([
971cb0ef41Sopenharmony_ci        'append', 'reverse', 'insert', 'sort', 'extend', 'remove'
981cb0ef41Sopenharmony_ci    ])),
991cb0ef41Sopenharmony_ci    (deque, frozenset([
1001cb0ef41Sopenharmony_ci        'append', 'appendleft', 'clear', 'extend', 'extendleft', 'pop',
1011cb0ef41Sopenharmony_ci        'popleft', 'remove', 'rotate'
1021cb0ef41Sopenharmony_ci    ]))
1031cb0ef41Sopenharmony_ci)
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ciclass _MagicFormatMapping(Mapping):
1071cb0ef41Sopenharmony_ci    """This class implements a dummy wrapper to fix a bug in the Python
1081cb0ef41Sopenharmony_ci    standard library for string formatting.
1091cb0ef41Sopenharmony_ci
1101cb0ef41Sopenharmony_ci    See https://bugs.python.org/issue13598 for information about why
1111cb0ef41Sopenharmony_ci    this is necessary.
1121cb0ef41Sopenharmony_ci    """
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci    def __init__(self, args, kwargs):
1151cb0ef41Sopenharmony_ci        self._args = args
1161cb0ef41Sopenharmony_ci        self._kwargs = kwargs
1171cb0ef41Sopenharmony_ci        self._last_index = 0
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci    def __getitem__(self, key):
1201cb0ef41Sopenharmony_ci        if key == '':
1211cb0ef41Sopenharmony_ci            idx = self._last_index
1221cb0ef41Sopenharmony_ci            self._last_index += 1
1231cb0ef41Sopenharmony_ci            try:
1241cb0ef41Sopenharmony_ci                return self._args[idx]
1251cb0ef41Sopenharmony_ci            except LookupError:
1261cb0ef41Sopenharmony_ci                pass
1271cb0ef41Sopenharmony_ci            key = str(idx)
1281cb0ef41Sopenharmony_ci        return self._kwargs[key]
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ci    def __iter__(self):
1311cb0ef41Sopenharmony_ci        return iter(self._kwargs)
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci    def __len__(self):
1341cb0ef41Sopenharmony_ci        return len(self._kwargs)
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_cidef inspect_format_method(callable):
1381cb0ef41Sopenharmony_ci    if not isinstance(callable, (types.MethodType,
1391cb0ef41Sopenharmony_ci                                 types.BuiltinMethodType)) or \
1401cb0ef41Sopenharmony_ci       callable.__name__ != 'format':
1411cb0ef41Sopenharmony_ci        return None
1421cb0ef41Sopenharmony_ci    obj = callable.__self__
1431cb0ef41Sopenharmony_ci    if isinstance(obj, string_types):
1441cb0ef41Sopenharmony_ci        return obj
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_cidef safe_range(*args):
1481cb0ef41Sopenharmony_ci    """A range that can't generate ranges with a length of more than
1491cb0ef41Sopenharmony_ci    MAX_RANGE items.
1501cb0ef41Sopenharmony_ci    """
1511cb0ef41Sopenharmony_ci    rng = range(*args)
1521cb0ef41Sopenharmony_ci    if len(rng) > MAX_RANGE:
1531cb0ef41Sopenharmony_ci        raise OverflowError('range too big, maximum size for range is %d' %
1541cb0ef41Sopenharmony_ci                            MAX_RANGE)
1551cb0ef41Sopenharmony_ci    return rng
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_cidef unsafe(f):
1591cb0ef41Sopenharmony_ci    """Marks a function or method as unsafe.
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci    ::
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci        @unsafe
1641cb0ef41Sopenharmony_ci        def delete(self):
1651cb0ef41Sopenharmony_ci            pass
1661cb0ef41Sopenharmony_ci    """
1671cb0ef41Sopenharmony_ci    f.unsafe_callable = True
1681cb0ef41Sopenharmony_ci    return f
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_cidef is_internal_attribute(obj, attr):
1721cb0ef41Sopenharmony_ci    """Test if the attribute given is an internal python attribute.  For
1731cb0ef41Sopenharmony_ci    example this function returns `True` for the `func_code` attribute of
1741cb0ef41Sopenharmony_ci    python objects.  This is useful if the environment method
1751cb0ef41Sopenharmony_ci    :meth:`~SandboxedEnvironment.is_safe_attribute` is overridden.
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci    >>> from jinja2.sandbox import is_internal_attribute
1781cb0ef41Sopenharmony_ci    >>> is_internal_attribute(str, "mro")
1791cb0ef41Sopenharmony_ci    True
1801cb0ef41Sopenharmony_ci    >>> is_internal_attribute(str, "upper")
1811cb0ef41Sopenharmony_ci    False
1821cb0ef41Sopenharmony_ci    """
1831cb0ef41Sopenharmony_ci    if isinstance(obj, types.FunctionType):
1841cb0ef41Sopenharmony_ci        if attr in UNSAFE_FUNCTION_ATTRIBUTES:
1851cb0ef41Sopenharmony_ci            return True
1861cb0ef41Sopenharmony_ci    elif isinstance(obj, types.MethodType):
1871cb0ef41Sopenharmony_ci        if attr in UNSAFE_FUNCTION_ATTRIBUTES or \
1881cb0ef41Sopenharmony_ci           attr in UNSAFE_METHOD_ATTRIBUTES:
1891cb0ef41Sopenharmony_ci            return True
1901cb0ef41Sopenharmony_ci    elif isinstance(obj, type):
1911cb0ef41Sopenharmony_ci        if attr == 'mro':
1921cb0ef41Sopenharmony_ci            return True
1931cb0ef41Sopenharmony_ci    elif isinstance(obj, (types.CodeType, types.TracebackType, types.FrameType)):
1941cb0ef41Sopenharmony_ci        return True
1951cb0ef41Sopenharmony_ci    elif isinstance(obj, types.GeneratorType):
1961cb0ef41Sopenharmony_ci        if attr in UNSAFE_GENERATOR_ATTRIBUTES:
1971cb0ef41Sopenharmony_ci            return True
1981cb0ef41Sopenharmony_ci    elif hasattr(types, 'CoroutineType') and isinstance(obj, types.CoroutineType):
1991cb0ef41Sopenharmony_ci        if attr in UNSAFE_COROUTINE_ATTRIBUTES:
2001cb0ef41Sopenharmony_ci            return True
2011cb0ef41Sopenharmony_ci    elif hasattr(types, 'AsyncGeneratorType') and isinstance(obj, types.AsyncGeneratorType):
2021cb0ef41Sopenharmony_ci        if attr in UNSAFE_ASYNC_GENERATOR_ATTRIBUTES:
2031cb0ef41Sopenharmony_ci            return True
2041cb0ef41Sopenharmony_ci    return attr.startswith('__')
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_cidef modifies_known_mutable(obj, attr):
2081cb0ef41Sopenharmony_ci    """This function checks if an attribute on a builtin mutable object
2091cb0ef41Sopenharmony_ci    (list, dict, set or deque) would modify it if called.  It also supports
2101cb0ef41Sopenharmony_ci    the "user"-versions of the objects (`sets.Set`, `UserDict.*` etc.) and
2111cb0ef41Sopenharmony_ci    with Python 2.6 onwards the abstract base classes `MutableSet`,
2121cb0ef41Sopenharmony_ci    `MutableMapping`, and `MutableSequence`.
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci    >>> modifies_known_mutable({}, "clear")
2151cb0ef41Sopenharmony_ci    True
2161cb0ef41Sopenharmony_ci    >>> modifies_known_mutable({}, "keys")
2171cb0ef41Sopenharmony_ci    False
2181cb0ef41Sopenharmony_ci    >>> modifies_known_mutable([], "append")
2191cb0ef41Sopenharmony_ci    True
2201cb0ef41Sopenharmony_ci    >>> modifies_known_mutable([], "index")
2211cb0ef41Sopenharmony_ci    False
2221cb0ef41Sopenharmony_ci
2231cb0ef41Sopenharmony_ci    If called with an unsupported object (such as unicode) `False` is
2241cb0ef41Sopenharmony_ci    returned.
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci    >>> modifies_known_mutable("foo", "upper")
2271cb0ef41Sopenharmony_ci    False
2281cb0ef41Sopenharmony_ci    """
2291cb0ef41Sopenharmony_ci    for typespec, unsafe in _mutable_spec:
2301cb0ef41Sopenharmony_ci        if isinstance(obj, typespec):
2311cb0ef41Sopenharmony_ci            return attr in unsafe
2321cb0ef41Sopenharmony_ci    return False
2331cb0ef41Sopenharmony_ci
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ciclass SandboxedEnvironment(Environment):
2361cb0ef41Sopenharmony_ci    """The sandboxed environment.  It works like the regular environment but
2371cb0ef41Sopenharmony_ci    tells the compiler to generate sandboxed code.  Additionally subclasses of
2381cb0ef41Sopenharmony_ci    this environment may override the methods that tell the runtime what
2391cb0ef41Sopenharmony_ci    attributes or functions are safe to access.
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci    If the template tries to access insecure code a :exc:`SecurityError` is
2421cb0ef41Sopenharmony_ci    raised.  However also other exceptions may occur during the rendering so
2431cb0ef41Sopenharmony_ci    the caller has to ensure that all exceptions are caught.
2441cb0ef41Sopenharmony_ci    """
2451cb0ef41Sopenharmony_ci    sandboxed = True
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci    #: default callback table for the binary operators.  A copy of this is
2481cb0ef41Sopenharmony_ci    #: available on each instance of a sandboxed environment as
2491cb0ef41Sopenharmony_ci    #: :attr:`binop_table`
2501cb0ef41Sopenharmony_ci    default_binop_table = {
2511cb0ef41Sopenharmony_ci        '+':        operator.add,
2521cb0ef41Sopenharmony_ci        '-':        operator.sub,
2531cb0ef41Sopenharmony_ci        '*':        operator.mul,
2541cb0ef41Sopenharmony_ci        '/':        operator.truediv,
2551cb0ef41Sopenharmony_ci        '//':       operator.floordiv,
2561cb0ef41Sopenharmony_ci        '**':       operator.pow,
2571cb0ef41Sopenharmony_ci        '%':        operator.mod
2581cb0ef41Sopenharmony_ci    }
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_ci    #: default callback table for the unary operators.  A copy of this is
2611cb0ef41Sopenharmony_ci    #: available on each instance of a sandboxed environment as
2621cb0ef41Sopenharmony_ci    #: :attr:`unop_table`
2631cb0ef41Sopenharmony_ci    default_unop_table = {
2641cb0ef41Sopenharmony_ci        '+':        operator.pos,
2651cb0ef41Sopenharmony_ci        '-':        operator.neg
2661cb0ef41Sopenharmony_ci    }
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_ci    #: a set of binary operators that should be intercepted.  Each operator
2691cb0ef41Sopenharmony_ci    #: that is added to this set (empty by default) is delegated to the
2701cb0ef41Sopenharmony_ci    #: :meth:`call_binop` method that will perform the operator.  The default
2711cb0ef41Sopenharmony_ci    #: operator callback is specified by :attr:`binop_table`.
2721cb0ef41Sopenharmony_ci    #:
2731cb0ef41Sopenharmony_ci    #: The following binary operators are interceptable:
2741cb0ef41Sopenharmony_ci    #: ``//``, ``%``, ``+``, ``*``, ``-``, ``/``, and ``**``
2751cb0ef41Sopenharmony_ci    #:
2761cb0ef41Sopenharmony_ci    #: The default operation form the operator table corresponds to the
2771cb0ef41Sopenharmony_ci    #: builtin function.  Intercepted calls are always slower than the native
2781cb0ef41Sopenharmony_ci    #: operator call, so make sure only to intercept the ones you are
2791cb0ef41Sopenharmony_ci    #: interested in.
2801cb0ef41Sopenharmony_ci    #:
2811cb0ef41Sopenharmony_ci    #: .. versionadded:: 2.6
2821cb0ef41Sopenharmony_ci    intercepted_binops = frozenset()
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_ci    #: a set of unary operators that should be intercepted.  Each operator
2851cb0ef41Sopenharmony_ci    #: that is added to this set (empty by default) is delegated to the
2861cb0ef41Sopenharmony_ci    #: :meth:`call_unop` method that will perform the operator.  The default
2871cb0ef41Sopenharmony_ci    #: operator callback is specified by :attr:`unop_table`.
2881cb0ef41Sopenharmony_ci    #:
2891cb0ef41Sopenharmony_ci    #: The following unary operators are interceptable: ``+``, ``-``
2901cb0ef41Sopenharmony_ci    #:
2911cb0ef41Sopenharmony_ci    #: The default operation form the operator table corresponds to the
2921cb0ef41Sopenharmony_ci    #: builtin function.  Intercepted calls are always slower than the native
2931cb0ef41Sopenharmony_ci    #: operator call, so make sure only to intercept the ones you are
2941cb0ef41Sopenharmony_ci    #: interested in.
2951cb0ef41Sopenharmony_ci    #:
2961cb0ef41Sopenharmony_ci    #: .. versionadded:: 2.6
2971cb0ef41Sopenharmony_ci    intercepted_unops = frozenset()
2981cb0ef41Sopenharmony_ci
2991cb0ef41Sopenharmony_ci    def intercept_unop(self, operator):
3001cb0ef41Sopenharmony_ci        """Called during template compilation with the name of a unary
3011cb0ef41Sopenharmony_ci        operator to check if it should be intercepted at runtime.  If this
3021cb0ef41Sopenharmony_ci        method returns `True`, :meth:`call_unop` is excuted for this unary
3031cb0ef41Sopenharmony_ci        operator.  The default implementation of :meth:`call_unop` will use
3041cb0ef41Sopenharmony_ci        the :attr:`unop_table` dictionary to perform the operator with the
3051cb0ef41Sopenharmony_ci        same logic as the builtin one.
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ci        The following unary operators are interceptable: ``+`` and ``-``
3081cb0ef41Sopenharmony_ci
3091cb0ef41Sopenharmony_ci        Intercepted calls are always slower than the native operator call,
3101cb0ef41Sopenharmony_ci        so make sure only to intercept the ones you are interested in.
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_ci        .. versionadded:: 2.6
3131cb0ef41Sopenharmony_ci        """
3141cb0ef41Sopenharmony_ci        return False
3151cb0ef41Sopenharmony_ci
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci    def __init__(self, *args, **kwargs):
3181cb0ef41Sopenharmony_ci        Environment.__init__(self, *args, **kwargs)
3191cb0ef41Sopenharmony_ci        self.globals['range'] = safe_range
3201cb0ef41Sopenharmony_ci        self.binop_table = self.default_binop_table.copy()
3211cb0ef41Sopenharmony_ci        self.unop_table = self.default_unop_table.copy()
3221cb0ef41Sopenharmony_ci
3231cb0ef41Sopenharmony_ci    def is_safe_attribute(self, obj, attr, value):
3241cb0ef41Sopenharmony_ci        """The sandboxed environment will call this method to check if the
3251cb0ef41Sopenharmony_ci        attribute of an object is safe to access.  Per default all attributes
3261cb0ef41Sopenharmony_ci        starting with an underscore are considered private as well as the
3271cb0ef41Sopenharmony_ci        special attributes of internal python objects as returned by the
3281cb0ef41Sopenharmony_ci        :func:`is_internal_attribute` function.
3291cb0ef41Sopenharmony_ci        """
3301cb0ef41Sopenharmony_ci        return not (attr.startswith('_') or is_internal_attribute(obj, attr))
3311cb0ef41Sopenharmony_ci
3321cb0ef41Sopenharmony_ci    def is_safe_callable(self, obj):
3331cb0ef41Sopenharmony_ci        """Check if an object is safely callable.  Per default a function is
3341cb0ef41Sopenharmony_ci        considered safe unless the `unsafe_callable` attribute exists and is
3351cb0ef41Sopenharmony_ci        True.  Override this method to alter the behavior, but this won't
3361cb0ef41Sopenharmony_ci        affect the `unsafe` decorator from this module.
3371cb0ef41Sopenharmony_ci        """
3381cb0ef41Sopenharmony_ci        return not (getattr(obj, 'unsafe_callable', False) or
3391cb0ef41Sopenharmony_ci                    getattr(obj, 'alters_data', False))
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_ci    def call_binop(self, context, operator, left, right):
3421cb0ef41Sopenharmony_ci        """For intercepted binary operator calls (:meth:`intercepted_binops`)
3431cb0ef41Sopenharmony_ci        this function is executed instead of the builtin operator.  This can
3441cb0ef41Sopenharmony_ci        be used to fine tune the behavior of certain operators.
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_ci        .. versionadded:: 2.6
3471cb0ef41Sopenharmony_ci        """
3481cb0ef41Sopenharmony_ci        return self.binop_table[operator](left, right)
3491cb0ef41Sopenharmony_ci
3501cb0ef41Sopenharmony_ci    def call_unop(self, context, operator, arg):
3511cb0ef41Sopenharmony_ci        """For intercepted unary operator calls (:meth:`intercepted_unops`)
3521cb0ef41Sopenharmony_ci        this function is executed instead of the builtin operator.  This can
3531cb0ef41Sopenharmony_ci        be used to fine tune the behavior of certain operators.
3541cb0ef41Sopenharmony_ci
3551cb0ef41Sopenharmony_ci        .. versionadded:: 2.6
3561cb0ef41Sopenharmony_ci        """
3571cb0ef41Sopenharmony_ci        return self.unop_table[operator](arg)
3581cb0ef41Sopenharmony_ci
3591cb0ef41Sopenharmony_ci    def getitem(self, obj, argument):
3601cb0ef41Sopenharmony_ci        """Subscribe an object from sandboxed code."""
3611cb0ef41Sopenharmony_ci        try:
3621cb0ef41Sopenharmony_ci            return obj[argument]
3631cb0ef41Sopenharmony_ci        except (TypeError, LookupError):
3641cb0ef41Sopenharmony_ci            if isinstance(argument, string_types):
3651cb0ef41Sopenharmony_ci                try:
3661cb0ef41Sopenharmony_ci                    attr = str(argument)
3671cb0ef41Sopenharmony_ci                except Exception:
3681cb0ef41Sopenharmony_ci                    pass
3691cb0ef41Sopenharmony_ci                else:
3701cb0ef41Sopenharmony_ci                    try:
3711cb0ef41Sopenharmony_ci                        value = getattr(obj, attr)
3721cb0ef41Sopenharmony_ci                    except AttributeError:
3731cb0ef41Sopenharmony_ci                        pass
3741cb0ef41Sopenharmony_ci                    else:
3751cb0ef41Sopenharmony_ci                        if self.is_safe_attribute(obj, argument, value):
3761cb0ef41Sopenharmony_ci                            return value
3771cb0ef41Sopenharmony_ci                        return self.unsafe_undefined(obj, argument)
3781cb0ef41Sopenharmony_ci        return self.undefined(obj=obj, name=argument)
3791cb0ef41Sopenharmony_ci
3801cb0ef41Sopenharmony_ci    def getattr(self, obj, attribute):
3811cb0ef41Sopenharmony_ci        """Subscribe an object from sandboxed code and prefer the
3821cb0ef41Sopenharmony_ci        attribute.  The attribute passed *must* be a bytestring.
3831cb0ef41Sopenharmony_ci        """
3841cb0ef41Sopenharmony_ci        try:
3851cb0ef41Sopenharmony_ci            value = getattr(obj, attribute)
3861cb0ef41Sopenharmony_ci        except AttributeError:
3871cb0ef41Sopenharmony_ci            try:
3881cb0ef41Sopenharmony_ci                return obj[attribute]
3891cb0ef41Sopenharmony_ci            except (TypeError, LookupError):
3901cb0ef41Sopenharmony_ci                pass
3911cb0ef41Sopenharmony_ci        else:
3921cb0ef41Sopenharmony_ci            if self.is_safe_attribute(obj, attribute, value):
3931cb0ef41Sopenharmony_ci                return value
3941cb0ef41Sopenharmony_ci            return self.unsafe_undefined(obj, attribute)
3951cb0ef41Sopenharmony_ci        return self.undefined(obj=obj, name=attribute)
3961cb0ef41Sopenharmony_ci
3971cb0ef41Sopenharmony_ci    def unsafe_undefined(self, obj, attribute):
3981cb0ef41Sopenharmony_ci        """Return an undefined object for unsafe attributes."""
3991cb0ef41Sopenharmony_ci        return self.undefined('access to attribute %r of %r '
4001cb0ef41Sopenharmony_ci                              'object is unsafe.' % (
4011cb0ef41Sopenharmony_ci            attribute,
4021cb0ef41Sopenharmony_ci            obj.__class__.__name__
4031cb0ef41Sopenharmony_ci        ), name=attribute, obj=obj, exc=SecurityError)
4041cb0ef41Sopenharmony_ci
4051cb0ef41Sopenharmony_ci    def format_string(self, s, args, kwargs):
4061cb0ef41Sopenharmony_ci        """If a format call is detected, then this is routed through this
4071cb0ef41Sopenharmony_ci        method so that our safety sandbox can be used for it.
4081cb0ef41Sopenharmony_ci        """
4091cb0ef41Sopenharmony_ci        if isinstance(s, Markup):
4101cb0ef41Sopenharmony_ci            formatter = SandboxedEscapeFormatter(self, s.escape)
4111cb0ef41Sopenharmony_ci        else:
4121cb0ef41Sopenharmony_ci            formatter = SandboxedFormatter(self)
4131cb0ef41Sopenharmony_ci        kwargs = _MagicFormatMapping(args, kwargs)
4141cb0ef41Sopenharmony_ci        rv = formatter.vformat(s, args, kwargs)
4151cb0ef41Sopenharmony_ci        return type(s)(rv)
4161cb0ef41Sopenharmony_ci
4171cb0ef41Sopenharmony_ci    def call(__self, __context, __obj, *args, **kwargs):
4181cb0ef41Sopenharmony_ci        """Call an object from sandboxed code."""
4191cb0ef41Sopenharmony_ci        fmt = inspect_format_method(__obj)
4201cb0ef41Sopenharmony_ci        if fmt is not None:
4211cb0ef41Sopenharmony_ci            return __self.format_string(fmt, args, kwargs)
4221cb0ef41Sopenharmony_ci
4231cb0ef41Sopenharmony_ci        # the double prefixes are to avoid double keyword argument
4241cb0ef41Sopenharmony_ci        # errors when proxying the call.
4251cb0ef41Sopenharmony_ci        if not __self.is_safe_callable(__obj):
4261cb0ef41Sopenharmony_ci            raise SecurityError('%r is not safely callable' % (__obj,))
4271cb0ef41Sopenharmony_ci        return __context.call(__obj, *args, **kwargs)
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_ci
4301cb0ef41Sopenharmony_ciclass ImmutableSandboxedEnvironment(SandboxedEnvironment):
4311cb0ef41Sopenharmony_ci    """Works exactly like the regular `SandboxedEnvironment` but does not
4321cb0ef41Sopenharmony_ci    permit modifications on the builtin mutable objects `list`, `set`, and
4331cb0ef41Sopenharmony_ci    `dict` by using the :func:`modifies_known_mutable` function.
4341cb0ef41Sopenharmony_ci    """
4351cb0ef41Sopenharmony_ci
4361cb0ef41Sopenharmony_ci    def is_safe_attribute(self, obj, attr, value):
4371cb0ef41Sopenharmony_ci        if not SandboxedEnvironment.is_safe_attribute(self, obj, attr, value):
4381cb0ef41Sopenharmony_ci            return False
4391cb0ef41Sopenharmony_ci        return not modifies_known_mutable(obj, attr)
4401cb0ef41Sopenharmony_ci
4411cb0ef41Sopenharmony_ci
4421cb0ef41Sopenharmony_ci# This really is not a public API apparenlty.
4431cb0ef41Sopenharmony_citry:
4441cb0ef41Sopenharmony_ci    from _string import formatter_field_name_split
4451cb0ef41Sopenharmony_ciexcept ImportError:
4461cb0ef41Sopenharmony_ci    def formatter_field_name_split(field_name):
4471cb0ef41Sopenharmony_ci        return field_name._formatter_field_name_split()
4481cb0ef41Sopenharmony_ci
4491cb0ef41Sopenharmony_ci
4501cb0ef41Sopenharmony_ciclass SandboxedFormatterMixin(object):
4511cb0ef41Sopenharmony_ci
4521cb0ef41Sopenharmony_ci    def __init__(self, env):
4531cb0ef41Sopenharmony_ci        self._env = env
4541cb0ef41Sopenharmony_ci
4551cb0ef41Sopenharmony_ci    def get_field(self, field_name, args, kwargs):
4561cb0ef41Sopenharmony_ci        first, rest = formatter_field_name_split(field_name)
4571cb0ef41Sopenharmony_ci        obj = self.get_value(first, args, kwargs)
4581cb0ef41Sopenharmony_ci        for is_attr, i in rest:
4591cb0ef41Sopenharmony_ci            if is_attr:
4601cb0ef41Sopenharmony_ci                obj = self._env.getattr(obj, i)
4611cb0ef41Sopenharmony_ci            else:
4621cb0ef41Sopenharmony_ci                obj = self._env.getitem(obj, i)
4631cb0ef41Sopenharmony_ci        return obj, first
4641cb0ef41Sopenharmony_ci
4651cb0ef41Sopenharmony_ciclass SandboxedFormatter(SandboxedFormatterMixin, Formatter):
4661cb0ef41Sopenharmony_ci
4671cb0ef41Sopenharmony_ci    def __init__(self, env):
4681cb0ef41Sopenharmony_ci        SandboxedFormatterMixin.__init__(self, env)
4691cb0ef41Sopenharmony_ci        Formatter.__init__(self)
4701cb0ef41Sopenharmony_ci
4711cb0ef41Sopenharmony_ciclass SandboxedEscapeFormatter(SandboxedFormatterMixin, EscapeFormatter):
4721cb0ef41Sopenharmony_ci
4731cb0ef41Sopenharmony_ci    def __init__(self, env, escape):
4741cb0ef41Sopenharmony_ci        SandboxedFormatterMixin.__init__(self, env)
4751cb0ef41Sopenharmony_ci        EscapeFormatter.__init__(self, escape)
476