1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
rest.php
См. документацию.
1<?php
10
11use Bitrix\Bitrix24\Feature;
13use Bitrix\Main;
22
24{
25 const STATUS_OK = "200 OK";
26 const STATUS_CREATED = "201 Created";
27 const STATUS_WRONG_REQUEST = "400 Bad Request";
28 const STATUS_UNAUTHORIZED = "401 Unauthorized";
29 const STATUS_PAYMENT_REQUIRED = "402 Payment Required"; // reserved for future use
30 const STATUS_FORBIDDEN = "403 Forbidden";
31 const STATUS_NOT_FOUND = "404 Not Found";
32 const STATUS_TO_MANY_REQUESTS = "429 Too Many Requests";
33 const STATUS_INTERNAL = "500 Internal Server Error";
34
35 /* @var \CRestServer */
36 protected static $instance = null;
37
38 protected $class = '';
39 protected $method = '';
40 protected $transport = '';
41 protected $scope = '';
42 protected $query = array();
43
44 protected $timeStart = 0;
45 protected $timeProcessStart = 0;
46 protected $timeProcessFinish = 0;
47 protected $usage = null;
48
49 protected $auth = array();
50 protected $authData = array();
51 protected $authScope = null;
52 protected $clientId = '';
53 protected $passwordId = '';
54
55 /* @var RestException */
56 protected $error = '';
57 protected $resultStatus = null;
58
59 protected $securityMethodState = null;
60 protected $securityClientState = null;
61
62 protected $arServiceDesc = array();
63
64 protected $tokenCheck = false;
65 protected $authType = null;
66
67 public function __construct($params, $toLowerMethod = true)
68 {
69 $this->class = $params['CLASS'];
70 $this->method = $toLowerMethod ? mb_strtolower($params['METHOD']) : $params['METHOD'];
71 $this->query = $params['QUERY'];
72
73 $this->transport = $params['TRANSPORT'] ?? null;
74
75 $this->securityClientState = $params['STATE'] ?? null;
76
77 if(!$this->transport)
78 {
79 $this->transport = 'json';
80 }
81
82 if(self::$instance === null)
83 {
84 self::$instance = $this;
85 }
86 }
87
91 public static function instance()
92 {
93 return self::$instance;
94 }
95
96 public static function transportSupported($transport)
97 {
98 return $transport == 'xml' || $transport == 'json';
99 }
100
101 public function process()
102 {
103 global $APPLICATION;
104
105 $this->timeStart = microtime(true);
106
107 if(!defined('BX24_REST_SKIP_SEND_HEADERS'))
108 {
109 \CRestUtil::sendHeaders();
110 }
111
112 try
113 {
114 if($this->init())
115 {
116 $handler = new $this->class();
117 /* @var IRestService $handler */
118 $this->arServiceDesc = $handler->getDescription();
119
120 $this->tokenCheck = $this->isTokenCheck();
121
122 if($this->checkScope())
123 {
124 $APPLICATION->RestartBuffer();
125
126 if($this->checkAuth())
127 {
129 $logger = new RestServerProcessLogger($this);
130 $logger->logRequest();
131
132 if($this->tokenCheck)
133 {
135 }
136 else
137 {
138 $result = $this->processCall();
139 }
140
141 $logger->logResponse($result);
142
143 return $result;
144 }
145 else
146 {
147 throw new AccessException();
148 }
149 }
150 else
151 {
152 throw new RestException('Method not found!', RestException::ERROR_METHOD_NOT_FOUND, self::STATUS_NOT_FOUND);
153 }
154 }
155 }
156 catch(Exception $e)
157 {
158 if ($e instanceof NonLoggedExceptionDecorator)
159 {
160 $e = RestException::initFromException($e->getOriginalException());
161 }
162 elseif (!($e instanceof RestException))
163 {
164 Main\Application::getInstance()->getExceptionHandler()->writeToLog($e);
165
166 $e = RestException::initFromException($e);
167 }
168
169 $this->error = $e;
170
171 $ex = $APPLICATION->GetException();
172 if ($ex)
173 {
174 $this->error->setApplicationException($ex);
175 }
176 }
177
178 if ($this->error)
179 {
180 return $this->outputError();
181 }
182
183 return null;
184 }
185
186 protected function isTokenCheck()
187 {
188 $methodDescription = $this->getMethodDescription();
189 if(!$methodDescription)
190 {
191 throw new RestException('Method not found!', RestException::ERROR_METHOD_NOT_FOUND, self::STATUS_NOT_FOUND);
192 }
193
194 return in_array($this->method, array(
195 \CRestUtil::METHOD_DOWNLOAD,
196 \CRestUtil::METHOD_UPLOAD,
197 )) || isset($this->query['token']);
198 }
199
200 protected function processTokenCheckCall()
201 {
202 $token = $this->query["token"];
203
204 [$this->scope, $queryString, $querySignature] = explode(\CRestUtil::TOKEN_DELIMITER, $token);
205
206 $signature = $this->getTokenCheckSignature($this->method, $queryString);
207
208 if($signature === $querySignature)
209 {
210 $queryString = base64_decode($queryString);
211
212 $query = array();
213 parse_str($queryString, $query);
214
215 unset($query["_"]);
216
217 $callback = $this->getMethodCallback();
218
219 if(!$callback)
220 {
221 throw new RestException('Method not found!', RestException::ERROR_METHOD_NOT_FOUND, self::STATUS_NOT_FOUND);
222 }
223
224 $result = call_user_func_array($callback, array($query, $this->scope, $this));
225
226 return array("result" => $result);
227 }
228 else
229 {
230 throw new AccessException("Link check failed");
231 }
232 }
233
234 protected function processCall()
235 {
236 if (
237 LoadLimiter::is(
238 $this->getAuthType(),
239 !empty($this->getClientId()) ? $this->getClientId() : $this->getPasswordId(),
240 $this->method
241 )
242 )
243 {
244 throw new RestException('Method is blocked due to operation time limit.', RestException::ERROR_OPERATION_TIME_LIMIT, self::STATUS_TO_MANY_REQUESTS);
245 }
246
247 $start = 0;
248 if(isset($this->query['start']))
249 {
250 $start = intval($this->query['start']);
251 unset($this->query['start']);
252 }
253
254 $callback = $this->getMethodCallback();
255
256 if(!$callback)
257 {
258 throw new RestException('Method not found!', RestException::ERROR_METHOD_NOT_FOUND, self::STATUS_NOT_FOUND);
259 }
260
261 $this->timeProcessStart = microtime(true);
262
263 if(\Bitrix\Main\ModuleManager::isModuleInstalled('bitrix24') && function_exists('getrusage'))
264 {
265 $this->usage = getrusage();
266 }
267
268 $entity = !empty($this->getClientId()) ? $this->getClientId() : $this->getPasswordId();
269 LoadLimiter::registerStarting(
270 $this->getAuthType(),
271 $entity,
272 $this->method
273 );
274 $result = call_user_func_array($callback, array($this->query, $start, $this));
275 LoadLimiter::registerEnding(
276 $this->getAuthType(),
277 $entity,
278 $this->method
279 );
280 $this->timeProcessFinish = microtime(true);
281
282 if (!empty($result['error']) && !empty($result['error_description']))
283 {
284 return $result;
285 }
286
287 $result = array("result" => $result);
288 if(is_array($result['result']))
289 {
290 if(isset($result['result']['next']))
291 {
292 $result["next"] = intval($result['result']['next']);
293 unset($result['result']['next']);
294 }
295
296 //Using array_key_exists instead isset for process NULL values
297 if(array_key_exists('total', $result['result']))
298 {
299 $result['total'] = intval($result['result']['total']);
300 unset($result['result']['total']);
301 }
302 }
303
304 if($this->securityClientState != null && $this->securityMethodState != null)
305 {
306 $result['signature'] = $this->getApplicationSignature();
307 }
308
310
311 return $result;
312 }
313
314 public function getTransport()
315 {
316 return $this->transport;
317 }
318
319 public function getAuth()
320 {
321 return $this->auth;
322 }
323
324 public function getAuthData()
325 {
326 return $this->authData;
327 }
328
329 public function getAuthScope()
330 {
331 if ($this->authScope == null)
332 {
333 $this->authScope = array();
334
335 $authData = $this->getAuthData();
336 $this->authScope = explode(',', $authData['scope']);
337 }
338
339 return $this->authScope;
340 }
341
342 public function getQuery()
343 {
344 return $this->query;
345 }
346
347 public function getAuthType()
348 {
349 return $this->authType;
350 }
351
357 public function getAppId()
358 {
359 return $this->getClientId();
360 }
361
362 public function getClientId()
363 {
364 return $this->clientId;
365 }
366
367 public function getPasswordId()
368 {
369 return $this->passwordId;
370 }
371
372 public function getMethod()
373 {
374 return $this->method;
375 }
376
377 public function setStatus($status)
378 {
379 $this->resultStatus = $status;
380 }
381
382 public function setSecurityState($state = null)
383 {
384 $this->securityMethodState = $state;
385 }
386
387 public function getScope()
388 {
389 return $this->scope;
390 }
391
392 public function getScopeList()
393 {
394 return array_keys($this->arServiceDesc);
395 }
396
397 public function getServiceDescription()
398 {
399 return $this->arServiceDesc;
400 }
401
402 public function getTokenCheckSignature($method, $queryString)
403 {
404 if(!\Bitrix\Rest\OAuthService::getEngine()->isRegistered())
405 {
406 try
407 {
409 \Bitrix\Rest\OAuthService::getEngine()->getClient()->getApplicationList();
410 }
411 catch(\Bitrix\Main\SystemException $e)
412 {
413 }
414 }
415
416 $key = \Bitrix\Rest\OAuthService::getEngine()->getClientSecret();
417
418 $signatureState = mb_strtolower($method)
419 .\CRestUtil::TOKEN_DELIMITER.($this->scope === \CRestUtil::GLOBAL_SCOPE ? '' : $this->scope)
420 .\CRestUtil::TOKEN_DELIMITER.$queryString
421 .\CRestUtil::TOKEN_DELIMITER.implode(\CRestUtil::TOKEN_DELIMITER, $this->auth);
422
423 return $this->makeSignature($key, $signatureState);
424 }
425
426 public function getApplicationSignature()
427 {
428 $signature = '';
429
431 if(is_array($arRes) && $arRes['SHARED_KEY'] <> '')
432 {
433 $methodState = is_array($this->securityMethodState)
434 ? $this->securityMethodState
435 : array('data' => $this->securityMethodState);
436
437 $methodState['state'] = $this->securityClientState;
438
439 $signature = $this->makeSignature($arRes['SHARED_KEY'], $methodState);
440 }
441
442 return $signature;
443 }
444
445
447 {
448 if($message == '')
449 {
450 throw new ArgumentNullException('message');
451 }
452
453 if(!is_array($userList) && intval($userList) > 0)
454 {
456 }
457
458 if(count($userList) <= 0)
459 {
460 throw new ArgumentNullException('userList');
461 }
462
463 if(!$this->getClientId())
464 {
465 throw new AccessException('Application context required');
466 }
467
468 if(
469 !isset($this->authData['parameters'])
470 || !isset($this->authData['parameters']['notify_allow'])
471 || !array_key_exists($this->method, $this->authData['parameters']['notify_allow'])
472 )
473 {
474 $notify = new \Bitrix\Rest\Notify(\Bitrix\Rest\Notify::NOTIFY_BOT, $userList);
475 $notify->send($this->getClientId(), $this->authData['access_token'], $this->method, $message);
476
477 $this->authData['parameters']['notify_allow'][$this->method] = 0;
478
479 if($this->authData['parameters_callback'] && is_callable($this->authData['parameters_callback']))
480 {
481 call_user_func_array($this->authData['parameters_callback'], array($this->authData));
482 }
483 }
484
485 if($this->authData['parameters']['notify_allow'][$this->method] === 0)
486 {
487 throw new RestException('Waiting for confirmation', 'METHOD_CONFIRM_WAITING', static::STATUS_UNAUTHORIZED);
488 }
489 elseif($this->authData['parameters']['notify_allow'][$this->method] < 0)
490 {
491 throw new RestException('Method call denied', 'METHOD_CONFIRM_DENIED', static::STATUS_FORBIDDEN);
492 }
493
494 return true;
495 }
496
497 private function init()
498 {
499 if(!in_array($this->transport, array('json', 'xml')))
500 {
501 throw new RestException('Wrong transport!', RestException::ERROR_INTERNAL_WRONG_TRANSPORT, self::STATUS_INTERNAL);
502 }
503 elseif(!$this->checkSite())
504 {
505 throw new RestException('Portal was deleted', RestException::ERROR_INTERNAL_PORTAL_DELETED, self::STATUS_FORBIDDEN);
506 }
507 elseif(!class_exists($this->class) || !method_exists($this->class, 'getDescription'))
508 {
509 throw new RestException('Wrong handler class!', RestException::ERROR_INTERNAL_WRONG_HANDLER_CLASS, self::STATUS_INTERNAL);
510 }
511 else
512 {
513 if(array_key_exists("state", $this->query))
514 {
515 $this->securityClientState = $this->query["state"];
516 unset($this->query["state"]);
517 }
518 }
519
520 return true;
521 }
522
523 private function checkSite()
524 {
525 return \Bitrix\Main\Config\Option::get("main", "site_stopped", "N") !== 'Y';
526 }
527
528 private function getMethodDescription()
529 {
530 if(!$this->scope)
531 {
532 foreach($this->arServiceDesc as $scope => $arMethods)
533 {
534 if(array_key_exists($this->method, $arMethods))
535 {
536 $this->scope = $scope;
537 break;
538 }
539 }
540 }
541
542 if(!isset($this->arServiceDesc[$this->scope]) || !isset($this->arServiceDesc[$this->scope][$this->method]))
543 {
544 foreach(GetModuleEvents('rest', 'onFindMethodDescription', true) as $event)
545 {
546 $result = ExecuteModuleEventEx($event, array($this->method, $this->scope));
547 if(is_array($result))
548 {
549 if (!isset($this->arServiceDesc[$result['scope']]) || !is_array($this->arServiceDesc[$result['scope']]))
550 {
551 $this->arServiceDesc[$result['scope']] = array();
552 }
553
554 $this->scope = $result['scope'];
555
556 $this->arServiceDesc[$this->scope][$this->method] = $result;
557
558 return $result;
559 }
560 }
561 }
562
563 return $this->arServiceDesc[$this->scope][$this->method];
564 }
565
566 private function getMethodCallback()
567 {
568 $methodDescription = $this->getMethodDescription();
569
570 if($methodDescription)
571 {
572 $callback = isset($methodDescription['callback'])
573 ? $methodDescription['callback']
574 : $methodDescription;
575
576 // hack to prevent callback structure doubling in case of strange doubling of event handlers
577 if(!is_callable($callback) && is_array($callback) && count($callback) > 2)
578 {
579 $callback = array($callback[0], $callback[1]);
580 }
581
582 if(is_callable($callback))
583 {
584 return $callback;
585 }
586 }
587
588 return false;
589 }
590
591 private function checkScope()
592 {
593 if($this->tokenCheck)
594 {
595 if(isset($this->query["token"]) && $this->query["token"] <> '')
596 {
597 [$scope] = explode(\CRestUtil::TOKEN_DELIMITER, $this->query["token"], 2);
598 $this->scope = $scope == "" ? \CRestUtil::GLOBAL_SCOPE : $scope;
599 }
600 }
601
602 $callback = $this->getMethodCallback();
603
604 if($callback)
605 {
606 return true;
607 }
608
609 return false;
610 }
611
612 protected function checkAuth()
613 {
614 $res = array();
615 if(\CRestUtil::checkAuth($this->query, $this->scope, $res))
616 {
617 $this->authType = $res['auth_type'];
618
619 $this->clientId = isset($res['client_id']) ? $res['client_id'] : null;
620 $this->passwordId = isset($res['password_id']) ? $res['password_id'] : null;
621
622 $this->authData = $res;
623
624 if(
625 (isset($this->authData['auth_connector']))
626 && !$this->canUseConnectors()
627 )
628 {
629 throw new \Bitrix\Rest\LicenseException('auth_connector');
630 }
631
632 if(isset($res['parameters_clear']) && is_array($res['parameters_clear']))
633 {
634 foreach($res['parameters_clear'] as $param)
635 {
636 if(array_key_exists($param, $this->query))
637 {
638 $this->auth[$param] = $this->query[$param];
639 unset($this->query[$param]);
640 }
641 }
642 }
643
644 $arAdditionalParams = $res['parameters'] ?? null;
645 if(isset($arAdditionalParams[\Bitrix\Rest\Event\Session::PARAM_SESSION]))
646 {
647 \Bitrix\Rest\Event\Session::set($arAdditionalParams[\Bitrix\Rest\Event\Session::PARAM_SESSION]);
648 }
649
650 return true;
651 }
652 else
653 {
654 throw new \Bitrix\Rest\OAuthException($res);
655 }
656 }
657
658 protected function canUseConnectors()
659 {
660 return !Loader::includeModule('bitrix24')
661 || Feature::isFeatureEnabled('rest_auth_connector');
662 }
663
664 protected function getMethodOptions()
665 {
666 $methodDescription = $this->getMethodDescription();
667 return is_array($methodDescription['options'])
668 ? $methodDescription['options']
669 : array();
670 }
671
672 private function makeSignature($key, $state)
673 {
674 $signature = '';
675
676 if(Loader::includeModule('socialservices'))
677 {
678 $signer = new Bitrix24Signer();
679 $signer->setKey($key);
680 $signature = $signer->sign($state);
681 }
682
683 return $signature;
684 }
685
686 /*************************************************************/
687
688 private function outputError()
689 {
690 $res = array_merge(array(
691 'error' => $this->error->getErrorCode(),
692 'error_description' => $this->error->getMessage(),
693 ), $this->error->getAdditional());
694
695 return $res;
696 }
697
698 public function sendHeaders()
699 {
700 if($this->error)
701 {
702 \CHTTP::setStatus($this->error->getStatus());
703 }
704 elseif($this->resultStatus)
705 {
706 \CHTTP::setStatus($this->resultStatus);
707 }
708 else
709 {
710 \CHTTP::setStatus(self::STATUS_OK);
711 }
712
713 switch($this->transport)
714 {
715 case 'json':
716 Header('Content-Type: application/json; charset=utf-8');
717 break;
718 case 'xml':
719 Header('Content-Type: text/xml; charset=utf-8');
720 break;
721 }
722
723 $this->sendHeadersAdditional();
724 }
725
726 public function sendHeadersAdditional()
727 {
729 {
730 if($this->clientId)
731 {
732 Header('X-Bitrix-Rest-Application: '.$this->clientId);
733 }
734
735 Header('X-Bitrix-Rest-Time: '.number_format($this->timeProcessFinish - $this->timeProcessStart, 10, '.', ''));
736
737 if($this->usage && function_exists('getrusage'))
738 {
739 $usage = getrusage();
740
741 Header('X-Bitrix-Rest-User-Time: '.number_format($usage['ru_utime.tv_sec'] - $this->usage['ru_utime.tv_sec'] + ($usage['ru_utime.tv_usec'] - $this->usage['ru_utime.tv_usec']) / 1000000, 10, '.', ''));
742 Header('X-Bitrix-Rest-System-Time: '.number_format($usage['ru_stime.tv_sec'] - $this->usage['ru_stime.tv_sec'] + ($usage['ru_stime.tv_usec'] - $this->usage['ru_stime.tv_usec']) / 1000000, 10, '.', ''));
743 }
744 }
745 }
746
747 public function output($data)
748 {
750
751 if (
752 isset($data['result'])
753 && $data['result'] instanceof \Bitrix\Main\Engine\Response\BFile
754 )
755 {
756 return $data['result'];
757 }
758
759 switch($this->transport)
760 {
761 case 'json':
762 return $this->outputJson($data);
763 break;
764 case 'xml':
765 return $this->outputXml(array('response' => $data));
766 break;
767 }
768 return null;
769 }
770
771 protected function appendDebugInfo(array $data)
772 {
773 $data['time'] = array(
774 'start' => $this->timeStart,
775 'finish' => microtime(true),
776 );
777
778 $data['time']['duration'] = $data['time']['finish'] - $data['time']['start'];
779 $data['time']['processing'] = $this->timeProcessFinish - $this->timeProcessStart;
780
781 $data['time']['date_start'] = date('c', $data['time']['start']);
782 $data['time']['date_finish'] = date('c', $data['time']['finish']);
783
784 if (LoadLimiter::isActive())
785 {
786 $reset = LoadLimiter::getResetTime(
787 $this->getAuthType(),
788 !empty($this->getClientId()) ? $this->getClientId() : $this->getPasswordId(),
789 $this->method
790 );
791 if ($reset)
792 {
793 $data['time']['operating_reset_at'] = $reset;
794 }
795
796 $data['time']['operating'] = LoadLimiter::getRestTime(
797 $this->getAuthType(),
798 !empty($this->getClientId()) ? $this->getClientId() : $this->getPasswordId(),
799 $this->method
800 );
801 }
802
803 return $data;
804 }
805
806 private function outputJson($data)
807 {
808 try
809 {
810 $res = Json::encode($data);
811 }
812 catch(\Bitrix\Main\ArgumentException $e)
813 {
814 $res = '{"error":"WRONG_ENCODING","error_description":"Wrong request encoding"}';
815 }
816
817 return $res;
818 }
819
820 private function outputXml($data)
821 {
822 $res = "";
823 foreach($data as $key => $value)
824 {
825 if($key === intval($key))
826 $key = 'item';
827
828 $res .= '<'.$key.'>';
829
830 if(is_array($value))
831 $res .= $this->outputXml($value);
832 else
833 $res .= \CDataXML::xmlspecialchars($value);
834
835 $res .= '</'.$key.'>';
836 }
837 return $res;
838 }
839
840 public function finalize(): void
841 {
842 self::$instance = null;
843 }
844}
845
847{
848 protected $authKeys = array();
849
850 public function setApplicationId($appId)
851 {
852 $this->clientId = $appId;
853 }
854
855 public function setAuthKeys($keys)
856 {
857 $this->authKeys = $keys;
858 }
859
860 public function setAuthData($authData)
861 {
862 $this->authData = $authData;
863 }
864
865 public function setAuthType($authType)
866 {
867 $this->authType = $authType;
868 }
869
870 protected function checkAuth()
871 {
872 foreach($this->authKeys as $param)
873 {
874 if(array_key_exists($param, $this->query))
875 {
876 $this->auth[$param] = $this->query[$param];
877 unset($this->query[$param]);
878 }
879 }
880
881 if($this->scope !== \CRestUtil::GLOBAL_SCOPE)
882 {
883 $allowedScope = explode(',', $this->authData['scope']);
884 $allowedScope = \Bitrix\Rest\Engine\RestManager::fillAlternativeScope($this->scope, $allowedScope);
885 if(!in_array($this->scope, $allowedScope))
886 {
887 throw new \Bitrix\Rest\OAuthException(array('error' => 'insufficient_scope'));
888 }
889 }
890
891 return true;
892 }
893}
894
896{
897 const LIST_LIMIT = 50;
898
899 protected static function getNavData($start, $bORM = false)
900 {
901 if($start >= 0)
902 {
903 return ($bORM
904 ? array(
905 'limit' => static::LIST_LIMIT,
906 'offset' => intval($start)
907 )
908 : array(
909 'nPageSize' => static::LIST_LIMIT,
910 'iNumPage' => intval($start / static::LIST_LIMIT) + 1
911 )
912 );
913 }
914 else
915 {
916 return ($bORM
917 ? array(
918 'limit' => static::LIST_LIMIT,
919 )
920 : array(
921 'nTopCount' => static::LIST_LIMIT,
922 )
923 );
924 }
925 }
926
927 protected static function setNavData($result, $dbRes)
928 {
929 if (is_array($dbRes))
930 {
931 // backward compatibility moment...
932 if ($result instanceof Countable || is_array($result))
933 {
935 }
936 elseif (is_null($result))
937 {
938 $count = 0;
939 }
940 else
941 {
942 $count = 1;
943 }
944
945 if($dbRes["offset"] + $count < $dbRes["count"])
946 {
947 $result['next'] = $dbRes["offset"] + $count;
948 }
949 if (!is_scalar($result))
950 {
951 $result['total'] = $dbRes["count"];
952 }
953 }
954 else
955 {
956 $result['total'] = $dbRes->NavRecordCount;
957 if($dbRes->NavPageNomer < $dbRes->NavPageCount)
958 {
959 $result['next'] = $dbRes->NavPageNomer * $dbRes->NavPageSize;
960 }
961 }
962
963 return $result;
964 }
965
966 public function getDescription()
967 {
968 $arMethods = get_class_methods($this);
969
970 $arResult = array();
971
972 foreach ($arMethods as $name)
973 {
974 if($name != 'getDescription')
975 {
976 $arResult[$name] = array($this, $name);
977 }
978 }
979
980 return $arResult;
981 }
982
983 protected static function sanitizeFilter($filter, array $availableFields = null, $valueCallback = null, array $availableOperations = null)
984 {
985 static $defaultOperations = array('', '=', '>', '<', '>=', '<=', '@', '%');
986
987 if($availableOperations === null)
988 {
989 $availableOperations = $defaultOperations;
990 }
991
992 if(!is_array($filter))
993 {
994 throw new RestException('The filter is not an array.', RestException::ERROR_ARGUMENT, \CRestServer::STATUS_WRONG_REQUEST);
995 }
996
997 $filter = array_change_key_case($filter, CASE_UPPER);
998
999 $resultFilter = array();
1000 foreach($filter as $key => $value)
1001 {
1002 if(preg_match('/^([^a-zA-Z]*)(.*)/', $key, $matches))
1003 {
1004 $operation = $matches[1];
1005 $field = $matches[2];
1006
1007 if(!in_array($operation, $availableOperations))
1008 {
1009 throw new RestException('Filter operation not allowed: '.$operation, RestException::ERROR_ARGUMENT, \CRestServer::STATUS_WRONG_REQUEST);
1010 }
1011
1012 if($availableFields !== null && !in_array($field, $availableFields))
1013 {
1014 throw new RestException('Filter field not allowed: '.$field, RestException::ERROR_ARGUMENT, \CRestServer::STATUS_WRONG_REQUEST);
1015 }
1016
1017 if(is_callable($valueCallback))
1018 {
1019 $value = call_user_func_array($valueCallback, array($field, $value, $operation));
1020 }
1021
1022 $resultFilter[$operation.$field] = $value;
1023 }
1024 }
1025
1026 return $resultFilter;
1027 }
1028
1029 protected static function sanitizeOrder($order, array $availableFields = null)
1030 {
1031 if(!is_array($order))
1032 {
1033 throw new RestException('The order is not an array.', RestException::ERROR_ARGUMENT, \CRestServer::STATUS_WRONG_REQUEST);
1034 }
1035
1036 $order = array_change_key_case($order, CASE_UPPER);
1037
1038 foreach($order as $key => $value)
1039 {
1040 if(!is_numeric($key))
1041 {
1042 if($availableFields !== null && !in_array($key, $availableFields))
1043 {
1044 throw new RestException('Order field not allowed: '.$key, RestException::ERROR_ARGUMENT, \CRestServer::STATUS_WRONG_REQUEST);
1045 }
1046
1047 if(!in_array(mb_strtoupper($value), array('ASC', 'DESC')))
1048 {
1049 throw new RestException('Order direction should be one of {ASC|DESC}', RestException::ERROR_ARGUMENT, \CRestServer::STATUS_WRONG_REQUEST);
1050 }
1051 }
1052 elseif($availableFields !== null && !in_array($value, $availableFields))
1053 {
1054 throw new RestException('Order field not allowed: '.$value, RestException::ERROR_ARGUMENT, \CRestServer::STATUS_WRONG_REQUEST);
1055 }
1056 }
1057
1058 return $order;
1059 }
1060
1061}
$count
Определения admin_tab.php:4
global $APPLICATION
Определения include.php:80
$arResult
Определения generate_coupon.php:16
static getInstance()
Определения application.php:98
Определения event.php:5
Определения loader.php:13
static includeModule($moduleName)
Определения loader.php:67
static isModuleInstalled($moduleName)
Определения modulemanager.php:125
Определения response.php:5
Определения json.php:9
static getByClientId($clientId)
Определения app.php:967
static fillAlternativeScope($scope, $scopeList)
Определения restmanager.php:90
static set($session)
Определения session.php:39
static getEngine()
Определения oauthservice.php:49
static register()
Определения oauthservice.php:59
static log(\CRestServer $server)
Определения usagestat.php:200
static finalize()
Определения usagestat.php:374
Определения rest.php:847
checkAuth()
Определения rest.php:870
$authKeys
Определения rest.php:848
setAuthData($authData)
Определения rest.php:860
setAuthKeys($keys)
Определения rest.php:855
setAuthType($authType)
Определения rest.php:865
setApplicationId($appId)
Определения rest.php:850
Определения rest.php:24
checkAuth()
Определения rest.php:612
$passwordId
Определения rest.php:53
getScope()
Определения rest.php:387
requestConfirmation($userList, $message)
Определения rest.php:446
static instance()
Определения rest.php:91
processTokenCheckCall()
Определения rest.php:200
$method
Определения rest.php:39
appendDebugInfo(array $data)
Определения rest.php:771
const STATUS_FORBIDDEN
Определения rest.php:30
$securityMethodState
Определения rest.php:59
$transport
Определения rest.php:40
$auth
Определения rest.php:49
$class
Определения rest.php:38
isTokenCheck()
Определения rest.php:186
$scope
Определения rest.php:41
getTokenCheckSignature($method, $queryString)
Определения rest.php:402
getAppId()
Определения rest.php:357
$timeProcessStart
Определения rest.php:45
const STATUS_WRONG_REQUEST
Определения rest.php:27
__construct($params, $toLowerMethod=true)
Определения rest.php:67
canUseConnectors()
Определения rest.php:658
$timeProcessFinish
Определения rest.php:46
getQuery()
Определения rest.php:342
sendHeadersAdditional()
Определения rest.php:726
const STATUS_OK
Определения rest.php:25
getServiceDescription()
Определения rest.php:397
getScopeList()
Определения rest.php:392
processCall()
Определения rest.php:234
getAuthData()
Определения rest.php:324
getTransport()
Определения rest.php:314
getAuth()
Определения rest.php:319
$tokenCheck
Определения rest.php:64
const STATUS_NOT_FOUND
Определения rest.php:31
setStatus($status)
Определения rest.php:377
process()
Определения rest.php:101
$authData
Определения rest.php:50
$clientId
Определения rest.php:52
getApplicationSignature()
Определения rest.php:426
$arServiceDesc
Определения rest.php:62
finalize()
Определения rest.php:840
getAuthScope()
Определения rest.php:329
$authScope
Определения rest.php:51
$timeStart
Определения rest.php:44
const STATUS_UNAUTHORIZED
Определения rest.php:28
$usage
Определения rest.php:47
getPasswordId()
Определения rest.php:367
getAuthType()
Определения rest.php:347
$authType
Определения rest.php:65
setSecurityState($state=null)
Определения rest.php:382
static transportSupported($transport)
Определения rest.php:96
getClientId()
Определения rest.php:362
sendHeaders()
Определения rest.php:698
output($data)
Определения rest.php:747
$securityClientState
Определения rest.php:60
static $instance
Определения rest.php:36
getMethodOptions()
Определения rest.php:664
const STATUS_TO_MANY_REQUESTS
Определения rest.php:32
const STATUS_PAYMENT_REQUIRED
Определения rest.php:29
const STATUS_INTERNAL
Определения rest.php:33
$error
Определения rest.php:56
$resultStatus
Определения rest.php:57
getMethod()
Определения rest.php:372
$query
Определения rest.php:42
const STATUS_CREATED
Определения rest.php:26
const GLOBAL_SCOPE
Определения rest_util.php:12
Определения rest.php:896
static sanitizeOrder($order, array $availableFields=null)
Определения rest.php:1029
static setNavData($result, $dbRes)
Определения rest.php:927
getDescription()
Определения rest.php:966
static sanitizeFilter($filter, array $availableFields=null, $valueCallback=null, array $availableOperations=null)
Определения rest.php:983
static getNavData($start, $bORM=false)
Определения rest.php:899
const LIST_LIMIT
Определения rest.php:897
$data['IS_AVAILABLE']
Определения .description.php:13
$userList
Определения discount_coupon_list.php:276
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
$result
Определения get_property_values.php:14
$start
Определения get_search.php:9
$query
Определения get_search.php:11
$auth
Определения get_user.php:29
$entity
$filter
Определения iblock_catalog_list.php:54
$status
Определения session.php:10
ExecuteModuleEventEx($arEvent, $arParams=[])
Определения tools.php:5214
GetModuleEvents($MODULE_ID, $MESSAGE_ID, $bReturnArray=false)
Определения tools.php:5177
$name
Определения menu_edit.php:35
Определения action.php:3
Определения handlers.php:8
$order
Определения payment.php:8
$message
Определения payment.php:8
$event
Определения prolog_after.php:141
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
if(empty($signedUserToken)) $key
Определения quickway.php:257
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
Определения template.php:799
$method
Определения index.php:27
$matches
Определения index.php:22
$clientId
Определения seo_client.php:18
$arRes
Определения options.php:104
$dbRes
Определения yandex_detail.php:168