7
7
8
8
import six
9
9
from jinja2 import Environment , PackageLoader
10
- from jinja2 .exceptions import SecurityError
11
10
from jsonschema import validate
12
11
from jsonschema .exceptions import ValidationError as JsonSchemaError
13
12
14
13
from . import renderers
15
14
from ...exceptions import ValidationError
16
- from ...utils import merge_config
17
- from ..base import ConfigSandbox
15
+ from ...utils import evaluate_vars , merge_config , var_pattern
18
16
from .schema import DEFAULT_FILE_MODE , schema
19
17
20
18
@@ -45,11 +43,10 @@ def __init__(self, config, templates=[], context={}):
45
43
if 'type' not in config :
46
44
config .update ({'type' : 'DeviceConfiguration' })
47
45
self .config = self ._merge_config (config , templates )
48
- self .context = context
46
+ self .config = self . _evaluate_vars ( self . config , context )
49
47
self .env = Environment (loader = PackageLoader ('netjsonconfig.backends.openwrt' ,
50
48
'templates' ),
51
49
trim_blocks = True )
52
- self .sandbox = ConfigSandbox ()
53
50
54
51
def _load (self , config ):
55
52
""" loads config from string or dict """
@@ -77,6 +74,18 @@ def _merge_config(self, config, templates):
77
74
return merge_config (base_config , config )
78
75
return config
79
76
77
+ def _evaluate_vars (self , config , context ):
78
+ """ evaluates configuration variables """
79
+ # return immediately if context is empty
80
+ if not context :
81
+ return config
82
+ # return immediately if no variables are found
83
+ netjson = self .json (validate = False )
84
+ if var_pattern .search (netjson ) is None :
85
+ return config
86
+ # only if variables are found perform evaluation
87
+ return evaluate_vars (config , context )
88
+
80
89
def render (self , files = True ):
81
90
"""
82
91
Converts the configuration dictionary into the native OpenWRT UCI format.
@@ -101,9 +110,6 @@ def render(self, files=True):
101
110
files_output = self ._render_files ()
102
111
if files_output :
103
112
output += files_output .replace ('\n \n \n ' , '\n \n ' ) # max 3 \n
104
- # configuration variables
105
- if self .context :
106
- output = self ._render_context (output )
107
113
return output
108
114
109
115
def _render_files (self ):
@@ -125,38 +131,13 @@ def _render_files(self):
125
131
output += file_output
126
132
return output
127
133
128
- def _render_context (self , input_ ):
129
- """
130
- Evaluates configuration variables passed in ``context`` arg
131
-
132
- :param input_: string containing rendered configuration
133
- :returns: string containing modified input_
134
- """
135
- # disable jinja blocks
136
- block_start = self .sandbox .block_start_string
137
- block_end = self .sandbox .block_end_string
138
- if block_start in input_ or block_end in input_ :
139
- raise SecurityError ('blocks are disabled' )
140
- # forbid calling methods or accessing properties
141
- forbidden = ['(' , '.' , '[' , '__' ]
142
- var_start = re .escape (self .sandbox .variable_start_string )
143
- var_end = re .escape (self .sandbox .variable_end_string )
144
- exp = '{0}.*?{1}' .format (var_start , var_end )
145
- exp = re .compile (exp )
146
- for match in exp .findall (input_ , re .DOTALL ):
147
- if any (char in match for char in forbidden ):
148
- raise SecurityError ('"{0}" contains one or more forbidden '
149
- 'characters' .format (match ))
150
- output = self .sandbox .from_string (input_ ).render (self .context )
151
- return output
152
-
153
134
def validate (self ):
154
135
try :
155
136
validate (self .config , self .schema )
156
137
except JsonSchemaError as e :
157
138
raise ValidationError (e )
158
139
159
- def json (self , * args , ** kwargs ):
140
+ def json (self , validate = True , * args , ** kwargs ):
160
141
"""
161
142
returns a string formatted in **NetJSON**;
162
143
performs validation before returning output;
@@ -165,7 +146,8 @@ def json(self, *args, **kwargs):
165
146
166
147
:returns: string
167
148
"""
168
- self .validate ()
149
+ if validate :
150
+ self .validate ()
169
151
return json .dumps (self .config , * args , ** kwargs )
170
152
171
153
@classmethod
0 commit comments