1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
request.php
См. документацию.
1<?php
9namespace Bitrix\Security\Filter;
10
11use Bitrix\Main\Config\Option;
12use Bitrix\Main\Config\Ini;
13use Bitrix\Main\Type\IRequestFilter;
14
21class Request implements IRequestFilter
22{
23 const ACTION_NONE = 'none';
24 const ACTION_CLEAR = 'clear';
25 const ACTION_FILTER = 'filter';
26
28 protected $auditors = [];
29 protected $changedContext = [];
30
31 private $action = 'filter';
32 private $doLog = false;
33 private $changedVars = [];
34 private $isAuditorsTriggered = false;
35 private $filteringMap = [
36 'get' => [
37 'Name' => '$_GET',
38 ],
39 'post' => [
40 'Name' => '$_POST',
41 'SkipRegExp' => '#^File\d+_\d+$#',
42 ],
43 'cookie' => [
44 'Name' => '$_COOKIE',
45 ],
46 'json' => [
47 'Name' => 'JSON',
48 ],
49 'data' => [
50 'Name' => 'data',
51 ]
52 ];
53 private static $validActions = [
54 self::ACTION_NONE,
55 self::ACTION_CLEAR,
56 self::ACTION_FILTER,
57 ];
58
59 public function __construct($customOptions = array())
60 {
61 if (isset($customOptions['action']))
62 {
63 $this->setAction($customOptions['action']);
64 }
65 else
66 {
67 $this->setAction(Option::get('security', 'filter_action'));
68 }
69
70 if (isset($customOptions['log']))
71 {
72 $this->setLog($customOptions['log']);
73 }
74 else
75 {
76 $this->setLog(Option::get('security', 'filter_log'));
77 }
78 }
79
86 public function setAuditors(array $auditors)
87 {
88 $this->auditors = $auditors;
89 return $this;
90 }
91
97 public function getChangedVars()
98 {
99 return $this->changedVars;
100 }
101
135 public function filter(array $values, $isReturnChangedOnly = true)
136 {
137 $this->onFilterStarted();
138
139 foreach ($values as $key => &$val)
140 {
141 if (!isset($this->filteringMap[$key]))
142 {
143 continue;
144 }
145
146 if (!is_array($val))
147 {
148 continue;
149 }
150
151 $val = $this->filterArray(
152 $key,
153 $val,
154 $this->filteringMap[$key]['Name'],
155 $this->filteringMap[$key]['SkipRegExp'] ?? ''
156 );
157 }
158 unset($val);
159
160 $this->onFilterFinished();
161
162 if ($isReturnChangedOnly)
163 {
164 return array_intersect_key($values, $this->changedContext);
165 }
166 return $values;
167 }
168
169
174 public function isAuditorsTriggered()
175 {
176 return $this->isAuditorsTriggered;
177 }
178
179 protected function onFilterStarted()
180 {
181 $this->changedContext = array();
182 $this->changedVars = array();
183 $this->isAuditorsTriggered = false;
184 }
185
186 protected function onFilterFinished()
187 {
188 }
189
196 protected function filterVar($context, $value, $name)
197 {
198 if (!is_string($value) || preg_match('#^[A-Za-z0-9_.,-]*$#D', $value))
199 return $value;
200
201 $filteredValue = \CSecurityHtmlEntity::decodeString($value);
202 self::adjustPcreBacktrackLimit($filteredValue);
203
204 $isValueChanged = false;
205 foreach($this->auditors as $auditName => $auditor)
206 {
207 if ($auditor->process($filteredValue))
208 {
209 $this->isAuditorsTriggered = true;
210
211 if ($this->isLogNeeded())
212 {
213 $this->logVariable($value, $name, $auditName);
214 }
215
216 if ($this->isFilterAction())
217 {
218 $isValueChanged = true;
219 $filteredValue = $auditor->getFilteredValue();
220 }
221 elseif ($this->isClearAction())
222 {
223 $isValueChanged = true;
224 $filteredValue = '';
225 break;
226 }
227 }
228 }
229
230 if ($isValueChanged)
231 {
232 $this->pushChangedVar($context, $value, $name);
233 return $filteredValue;
234 }
235 else
236 {
237 return $value;
238 }
239 }
240
248 protected function filterArray($context, ?array $array, $name, $skipKeyPreg = '')
249 {
250 if (!is_array($array))
251 {
252 return null;
253 }
254
255 foreach($array as $key => $value)
256 {
257 if ($skipKeyPreg && preg_match($skipKeyPreg, $key))
258 continue;
259
260 $filteredKey = $this->filterVar($context, $key, "{$name}['{$key}']");
261 if ($filteredKey != $key)
262 {
263 unset($array[$key]);
264 $key = $filteredKey;
265 }
266
267 if (is_array($value))
268 {
269 $array[$key] = $this->filterArray($context, $value, "{$name}['{$key}']", $skipKeyPreg);
270 }
271 elseif (is_string($value))
272 {
273 $array[$key] = $this->filterVar($context, $value, "{$name}['{$key}']");
274 }
275 else
276 {
277 $array[$key] = $value;
278 }
279 }
280 return $array;
281 }
282
287 protected static function isActionValid($action)
288 {
289 return in_array($action, self::getValidActions());
290 }
291
298 protected static function logVariable($value, $name, $auditorName)
299 {
300 return \CSecurityEvent::getInstance()->doLog('SECURITY', 'SECURITY_FILTER_'.$auditorName, $name, $value);
301 }
302
307 protected static function adjustPcreBacktrackLimit($string)
308 {
309 if (!is_string($string))
310 return false;
311
312 $strlen = strlen($string) * 2;
314 return true;
315 }
316
320 protected static function getValidActions()
321 {
322 return self::$validActions;
323 }
324
329 protected function setAction($action)
330 {
331 if (self::isActionValid($action))
332 {
333 $this->action = $action;
334 }
335 return $this;
336 }
337
342 protected function setLog($log)
343 {
344 $this->doLog = (is_string($log) && $log == 'Y');
345 return $this;
346 }
347
351 protected function isFilterAction()
352 {
353 return ($this->action === self::ACTION_FILTER);
354 }
355
359 protected function isClearAction()
360 {
361 return ($this->action === self::ACTION_CLEAR);
362 }
363
367 protected function isLogNeeded()
368 {
369 return $this->doLog;
370 }
371
378 protected function pushChangedVar($context, $value, $name)
379 {
380 $this->changedVars[$name] = $value;
381 if (!isset($this->changedContext[$context]))
382 $this->changedContext[$context] = 1;
383 return $this;
384 }
385}
static adjustPcreBacktrackLimit(int $val)
Определения ini.php:45
setAuditors(array $auditors)
Определения request.php:86
setAction($action)
Определения request.php:329
const ACTION_FILTER
Определения request.php:25
const ACTION_NONE
Определения request.php:23
filterArray($context, ?array $array, $name, $skipKeyPreg='')
Определения request.php:248
static logVariable($value, $name, $auditorName)
Определения request.php:298
const ACTION_CLEAR
Определения request.php:24
static isActionValid($action)
Определения request.php:287
filterVar($context, $value, $name)
Определения request.php:196
static getValidActions()
Определения request.php:320
setLog($log)
Определения request.php:342
filter(array $values, $isReturnChangedOnly=true)
Определения request.php:135
__construct($customOptions=array())
Определения request.php:59
pushChangedVar($context, $value, $name)
Определения request.php:378
static adjustPcreBacktrackLimit($string)
Определения request.php:307
isAuditorsTriggered()
Определения request.php:174
static decodeString($pString)
Определения html_entity.php:65
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$context
Определения csv_new_setup.php:223
$name
Определения menu_edit.php:35
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
if(empty($signedUserToken)) $key
Определения quickway.php:257
$val
Определения options.php:1793