PluginProbe
The WP Remote WordPress Plugin / 5.42
The WP Remote WordPress Plugin v5.42
6.72 6.69 6.65 6.62 6.48 6.47 4.87 4.97 5.05 5.09 5.16 5.22 5.24 5.25 5.38 5.41 5.42 5.45 5.47 5.53 5.56 5.65 5.68 5.72 5.73 All 53 releases
wpremote / protect / fw / rule / engine.php

engine.php in The WP Remote WordPress Plugin 5.42, at protect/fw/rule/engine.php

342 lines 8.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH') && !defined('MCDATAPATH')) exit;
3
4 if (!class_exists('WPRProtectFWRuleEngine_V542')) :
5 require_once dirname( __FILE__ ) . '/functions.php';
6
7 class WPRProtectFWRuleEngine_V542 {
8 use WPRProtectFWRuleStringFunc_V542;
9 use WPRProtectFWRuleArrayFunc_V542;
10 use WPRProtectFWRuleMiscFunc_V542;
11 use WPRProtectFWRuleRequestFunc_V542;
12 use WPRProtectFWRuleWPFunc_V542;
13
14 private $request;
15 private $variables;
16
17 private $error;
18 private $ex_stack = array();
19 private $ex_stack_inx = -1;
20
21 const VERSION = 1.1;
22
23 const MAX_DEPTH_TO_ALLOWED_TYPE_FUNC = 8;
24 const FUNC_NAME_PREFIX = '_rf_';
25 const CONST_NAME_PREFIX = 'WPRProtectFWRule_V542::';
26 const ALLOWED_EXT_CONSTANTS = [
27 'DOING_CRON'
28 ];
29
30 public function __construct($request = null, $variables = array()) {
31 $this->request = $request;
32 $this->variables = self::toAllowedType($variables);
33 }
34
35 public function hasError() {
36 return isset($this->error);
37 }
38
39 public function getErrorMessage() {
40 if (isset($this->error)) {
41 return $this->error->getMessage();
42 }
43 }
44
45 public function evaluate($rule) {
46 try {
47 return $this->executeStmt($rule->logic);
48 } catch (WPRProtectRuleError_V542 $e) {
49 $this->error = $e;
50 }
51 }
52
53 private static function toAllowedType($value, $depth = 1) {
54 if ($depth > self::MAX_DEPTH_TO_ALLOWED_TYPE_FUNC) {
55 return null;
56 }
57
58 switch (gettype($value)) {
59 case 'null':
60 case 'boolean':
61 case 'integer':
62 case 'double':
63 case 'string':
64 return $value;
65 case 'array':
66 $array_value = [];
67
68 foreach ($value as $key => $val) {
69 $array_value[$key] = self::toAllowedType($val, $depth + 1);
70 }
71
72 return $array_value;
73 case 'object':
74 $object_vars = [];
75
76 foreach (get_object_vars($value) as $key => $val) {
77 $object_vars[$key] = self::toAllowedType($val, $depth + 1);
78 }
79
80 return $object_vars;
81 default:
82 return null;
83 }
84 }
85
86 private function pushExStack() {
87 array_push($this->ex_stack, array('cur_op' => '-', 'op_cnt' => 0));
88 $this->ex_stack_inx += 1;
89 }
90
91 private function popExStack() {
92 array_pop($this->ex_stack);
93 $this->ex_stack_inx -= 1;
94 }
95
96 private function updateCurOp($cur_op) {
97 if (!empty($this->ex_stack[$this->ex_stack_inx])) {
98 $this->ex_stack[$this->ex_stack_inx]['cur_op'] = $cur_op;
99 }
100 }
101
102 private function incrOpCnt() {
103 if (!empty($this->ex_stack[$this->ex_stack_inx])) {
104 $this->ex_stack[$this->ex_stack_inx]['op_cnt'] += 1;
105 }
106 }
107
108 private function addExState($msg) {
109 if (!empty($this->ex_stack[$this->ex_stack_inx])) {
110 $msg .= " on " . $this->ex_stack[$this->ex_stack_inx]['cur_op'];
111 $msg .= " at (" . $this->ex_stack_inx . ":" .
112 $this->ex_stack[$this->ex_stack_inx]['op_cnt'] . ").";
113 }
114
115 return $msg;
116 }
117
118 private function getValue($stmt) {
119 if (!is_array($stmt) || empty($stmt["type"])) {
120 throw new WPRProtectRuleError_V542(
121 $this->addExState("InvalidStatementError: Malformed value statement"));
122 }
123
124 $this->incrOpCnt();
125
126 switch ($stmt["type"]) {
127 case "NUMBER":
128 if (!isset($stmt["value"]) || !is_int($stmt["value"])) {
129 throw new WPRProtectRuleError_V542(
130 $this->addExState("TypeError: Value is not a number")
131 );
132 }
133
134 return $stmt["value"];
135 case "STRING":
136 if (!isset($stmt["value"]) || !is_string($stmt["value"])) {
137 throw new WPRProtectRuleError_V542(
138 $this->addExState("TypeError: Value is not a string")
139 );
140 }
141
142 return $stmt["value"];
143 case "BOOL":
144 if (!isset($stmt["value"]) || !is_bool($stmt["value"])) {
145 throw new WPRProtectRuleError_V542(
146 $this->addExState("TypeError: Value is not a boolean")
147 );
148 }
149
150 return $stmt["value"];
151 case "CONST":
152 if (!isset($stmt["value"]) || !is_string($stmt["value"])) {
153 throw new WPRProtectRuleError_V542(
154 $this->addExState("TypeError: Invalid constant name")
155 );
156 }
157
158 //For backward compatibility.
159 $name = str_replace('BVFW::', '', $stmt["value"]);
160 if (!in_array($name, self::ALLOWED_EXT_CONSTANTS, true)) {
161 $name = self::CONST_NAME_PREFIX . $name;
162 }
163
164 if (!defined($name)) {
165 throw new WPRProtectRuleError_V542(
166 $this->addExState("TypeError: Undefined constant" . $stmt["value"])
167 );
168 }
169
170 return constant($name);
171 case "ARRAY":
172 if (!isset($stmt["value"]) || !is_array($stmt["value"])) {
173 throw new WPRProtectRuleError_V542(
174 $this->addExState("TypeError: Value is not a array")
175 );
176 }
177
178 $arr = array();
179 foreach ($stmt["value"] as $element) {
180 $arr[] = $this->getValue($element);
181 }
182
183 return $arr;
184 case "HASH_MAP":
185 if (!isset($stmt["value"]) || !is_array($stmt["value"])) {
186 throw new MCProtectRuleError(
187 $this->addExState("TypeError: Value is not a hash map")
188 );
189 }
190
191 $hash_map = array();
192 foreach($stmt["value"] as $key => $value) {
193 $hash_map[$key] = $this->getValue($value);
194 }
195
196 return $hash_map;
197 default:
198 return $this->executeStmt($stmt);
199 }
200 }
201
202 private function executeStmt($stmt) {
203 if (!is_array($stmt) || empty($stmt["type"])) {
204 throw new WPRProtectRuleError_V542(
205 $this->addExState("InvalidStatementError: Malformed logic statement")
206 );
207 }
208
209 $this->pushExStack();
210 $this->updateCurOp($stmt["type"]);
211 $return_val = null;
212
213 switch ($stmt["type"]) {
214 case "AND":
215 if (empty($stmt["left_operand"]) || empty($stmt["right_operand"])) {
216 throw new WPRProtectRuleError_V542(
217 $this->addExState("InvalidOperandError: Malformed operand(s)")
218 );
219 }
220
221 $return_val = $this->getValue($stmt["left_operand"]) && $this->getValue($stmt["right_operand"]);
222 break;
223 case "OR":
224 if (empty($stmt["left_operand"]) || empty($stmt["right_operand"])) {
225 throw new WPRProtectRuleError_V542(
226 $this->addExState("InvalidOperandError: Malformed operand(s)")
227 );
228 }
229
230 $return_val = $this->getValue($stmt["left_operand"]) || $this->getValue($stmt["right_operand"]);
231 break;
232 case "NOT":
233 if (empty($stmt["value"])) {
234 throw new WPRProtectRuleError_V542(
235 $this->addExState("InvalidOperandError: Malformed operand")
236 );
237 }
238
239 $return_val = !$this->getValue($stmt["value"]);
240 break;
241 case "FUNCTION":
242 if (empty($stmt["name"]) || !is_string($stmt["name"])) {
243 throw new WPRProtectRuleError_V542(
244 $this->addExState("InvalidFunctionName: Malformed name")
245 );
246 }
247
248 $name = self::FUNC_NAME_PREFIX . $stmt["name"];
249 $handler = array($this, $name);
250
251 if (!is_callable($handler)) {
252 throw new WPRProtectRuleError_V542(
253 $this->addExState("UndefinedFunctionCall: " . $stmt["name"])
254 );
255 }
256
257 if (!array_key_exists('args', $stmt) || !is_array($stmt['args'])) {
258 throw new WPRProtectRuleError_V542(
259 $this->addExState("InvalidArguments: Malformed args")
260 );
261 }
262
263 $args = array();
264 foreach ($stmt['args'] as $arg_stmt) {
265 array_push($args, $this->getValue($arg_stmt));
266 }
267
268 $return_val = self::toAllowedType(call_user_func_array($handler, $args));
269 break;
270 default:
271 throw new WPRProtectRuleError_V542(
272 $this->addExState("UnknownOperation: -")
273 );
274 }
275
276 $this->popExStack();
277 return $return_val;
278 }
279
280 private function processRuleFunctionParams($func_name, $args_cnt, $args, $required_params = 0, $param_types = array()) {
281 if (($args_cnt < $required_params)) {
282 throw new WPRProtectRuleError_V542(
283 $this->addExState("ArgumentCountError: Too few arguments for " . $func_name)
284 );
285 }
286
287 foreach ($param_types as $pos => $type) {
288 if (!is_int($pos)) {
289 throw new WPRProtectRuleError_V542(
290 $this->addExState("InvalidParamType: " . $pos)
291 );
292 }
293
294 switch ($type) {
295 case "string":
296 if (!isset($args[$pos]) || !is_string($args[$pos])) {
297 throw new WPRProtectRuleError_V542(
298 $this->addExState("TypeError: " . $func_name . " param at " . $pos . " is not a string.")
299 );
300 }
301 break;
302 case 'integer':
303 if (!isset($args[$pos]) || !is_int($args[$pos])) {
304 throw new WPRProtectRuleError_V542(
305 $this->addExState("TypeError: " . $func_name . " param at " . $pos . " is not a integer.")
306 );
307 }
308 break;
309 case 'double':
310 if (!isset($args[$pos]) || !is_double($args[$pos])) {
311 throw new WPRProtectRuleError_V542(
312 $this->addExState("TypeError: " . $func_name . " param at " . $pos . " is not a double.")
313 );
314 }
315 break;
316 case 'boolean':
317 if (!isset($args[$pos]) || !is_bool($args[$pos])) {
318 throw new WPRProtectRuleError_V542(
319 $this->addExState("TypeError: " . $func_name . " param at " . $pos . " is not a boolean.")
320 );
321 }
322 break;
323 case 'array':
324 if (!isset($args[$pos]) || !is_array($args[$pos])) {
325 throw new WPRProtectRuleError_V542(
326 $this->addExState("TypeError: " . $func_name . " param at " . $pos . " is not an array.")
327 );
328 }
329 break;
330 case 'mixed':
331 break;
332 default:
333 throw new WPRProtectRuleError_V542(
334 $this->addExState("InvalidParamTypeError: Invalid type at " . $pos . " for " . $func_name)
335 );
336 }
337 }
338
339 return $args;
340 }
341 }
342 endif;